6 #include "chantables.h"
10 #include "playbackconfig.h"
11 #include "playbackengine.h"
12 #include "preferences.h"
13 #include "quicktime.h"
14 #include "recordconfig.h"
15 #include "recordmonitor.h"
17 #include "vdevice1394.h"
19 #include "vdevicebuz.h"
20 #include "vdevicev4l.h"
21 #include "vdevicev4l2.h"
22 #include "vdevicev4l2jpeg.h"
23 #include "vdevicex11.h"
24 #include "videoconfig.h"
25 #include "videodevice.h"
26 #include "videowindow.h"
27 #include "videowindowgui.h"
33 KeepaliveThread::KeepaliveThread(VideoDevice *device)
40 this->device = device;
42 startup_lock = new Mutex("KeepaliveThread::startup_lock");
45 KeepaliveThread::~KeepaliveThread()
50 int KeepaliveThread::start_keepalive()
52 startup_lock->lock("KeepaliveThread::start_keepalive 1");
54 startup_lock->lock("KeepaliveThread::start_keepalive 2");
55 startup_lock->unlock();
58 void KeepaliveThread::run()
60 startup_lock->unlock();
64 // Give the capture a moment
65 // Should fix the delay in case users want slower frame rates.
66 timer.delay((long)(KEEPALIVE_DELAY * 1000));
68 // See if a capture happened
69 if(still_alive == 0 && capturing)
71 // printf("KeepaliveThread::run: device crashed\n");
79 int KeepaliveThread::reset_keepalive()
84 int KeepaliveThread::get_failed()
86 if(failed) return 1; else return 0;
89 int KeepaliveThread::stop()
93 // Force an immediate exit even if capture_frame worked.
104 VideoDevice::VideoDevice(MWindow *mwindow)
106 this->mwindow = mwindow;
107 in_config = new VideoInConfig;
108 out_config = new VideoOutConfig;
109 channel = new Channel;
110 picture = new PictureConfig(mwindow ? mwindow->defaults : 0);
111 sharing_lock = new Mutex("VideoDevice::sharing_lock");
112 channel_lock = new Mutex("VideoDevice::channel_lock");
113 picture_lock = new Mutex("VideoDevice::picture_lock");
118 VideoDevice::~VideoDevice()
120 input_sources.remove_all_objects();
130 int VideoDevice::initialize()
134 sharing_lock->reset();
138 is_playing_back = is_recording = 0;
158 int VideoDevice::open_input(VideoInConfig *config,
166 *this->in_config = *config;
169 this->input_z = -1; // Force initialization.
170 this->frame_rate = frame_rate;
173 switch(in_config->driver)
176 keepalive = new KeepaliveThread(this);
177 keepalive->start_keepalive();
179 result = input_base->open_input();
183 #ifdef HAVE_VIDEO4LINUX2
186 result = input_base->open_input();
188 case VIDEO4LINUX2JPEG:
190 result = input_base->open_input();
195 this->input_x = input_x;
196 this->input_y = input_y;
198 result = input_base->open_input();
201 //printf("VideoDevice 1\n");
202 keepalive = new KeepaliveThread(this);
203 keepalive->start_keepalive();
205 result = input_base->open_input();
208 case CAPTURE_FIREWIRE:
209 case CAPTURE_IEC61883:
211 result = input_base->open_input();
216 if(!result) capturing = 1;
220 VDeviceBase* VideoDevice::new_device_base()
222 switch(in_config->driver)
225 return input_base = new VDeviceV4L(this);
227 #ifdef HAVE_VIDEO4LINUX2
229 return input_base = new VDeviceV4L2(this);
231 case VIDEO4LINUX2JPEG:
232 return input_base = new VDeviceV4L2JPEG(this);
236 return input_base = new VDeviceX11(this, 0);
239 return input_base = new VDeviceBUZ(this);
242 case CAPTURE_FIREWIRE:
243 case CAPTURE_IEC61883:
244 return input_base = new VDevice1394(this);
251 VDeviceBase* VideoDevice::get_output_base()
256 int VideoDevice::is_compressed(int driver, int use_file, int use_fixed)
258 // FileMOV needs to have write_frames called so the start codes get scanned.
259 return ((driver == CAPTURE_BUZ && use_fixed) ||
260 (driver == VIDEO4LINUX2JPEG && use_fixed) ||
261 driver == CAPTURE_LML ||
262 driver == CAPTURE_FIREWIRE ||
263 driver == CAPTURE_IEC61883);
266 int VideoDevice::is_compressed(int use_file, int use_fixed)
268 return is_compressed(in_config->driver, use_file, use_fixed);
272 void VideoDevice::fix_asset(Asset *asset, int driver)
274 // Fix asset using legacy routine
279 case VIDEO4LINUX2JPEG:
280 if(asset->format != FILE_AVI &&
281 asset->format != FILE_MOV)
282 asset->format = FILE_MOV;
283 strcpy(asset->vcodec, QUICKTIME_MJPA);
286 case CAPTURE_FIREWIRE:
287 case CAPTURE_IEC61883:
288 if(asset->format != FILE_AVI &&
289 asset->format != FILE_MOV)
290 asset->format = FILE_MOV;
291 strcpy(asset->vcodec, QUICKTIME_DVSD);
295 // Fix asset using inherited routine
298 if(input_base) input_base->fix_asset(asset);
304 char* VideoDevice::drivertostr(int driver)
309 return PLAYBACK_X11_TITLE;
311 case PLAYBACK_X11_XV:
312 return PLAYBACK_X11_XV_TITLE;
314 case PLAYBACK_X11_GL:
315 return PLAYBACK_X11_GL_TITLE;
318 return PLAYBACK_BUZ_TITLE;
321 return VIDEO4LINUX_TITLE;
324 return VIDEO4LINUX2_TITLE;
326 case VIDEO4LINUX2JPEG:
327 return VIDEO4LINUX2JPEG_TITLE;
330 return SCREENCAPTURE_TITLE;
333 return CAPTURE_BUZ_TITLE;
336 case CAPTURE_FIREWIRE:
337 return CAPTURE_FIREWIRE_TITLE;
339 case CAPTURE_IEC61883:
340 return CAPTURE_IEC61883_TITLE;
347 int VideoDevice::get_best_colormodel(Asset *asset)
350 return input_base->get_best_colormodel(asset);
355 int VideoDevice::close_all()
363 output_base->close_all();
373 input_base->close_all();
387 input_sources.remove_all_objects();
395 int VideoDevice::set_adevice(AudioDevice *adevice)
397 this->adevice = adevice;
402 ArrayList<Channel*>* VideoDevice::get_inputs()
404 return &input_sources;
407 Channel* VideoDevice::new_input_source(char *device_name)
409 for(int i = 0; i < input_sources.total; i++)
411 if(!strcmp(input_sources.values[i]->device_name, device_name))
412 return input_sources.values[i];
414 Channel *item = new Channel;
415 strcpy(item->device_name, device_name);
416 input_sources.append(item);
420 int VideoDevice::get_failed()
423 return keepalive->get_failed();
428 int VideoDevice::interrupt_crash()
430 if(input_base) return input_base->interrupt_crash();
434 int VideoDevice::set_translation(int input_x, int input_y)
436 this->input_x = input_x;
437 this->input_y = input_y;
441 int VideoDevice::set_field_order(int odd_field_first)
443 this->odd_field_first = odd_field_first;
447 int VideoDevice::set_channel(Channel *channel)
451 channel_lock->lock("VideoDevice::set_channel");
452 this->channel->copy_settings(channel);
454 channel_lock->unlock();
456 if(input_base) return input_base->set_channel(channel);
457 if(output_base) return output_base->set_channel(channel);
461 void VideoDevice::set_quality(int quality)
463 this->quality = quality;
466 void VideoDevice::set_cpus(int cpus)
471 int VideoDevice::set_picture(PictureConfig *picture)
475 picture_lock->lock("VideoDevice::set_picture");
476 this->picture->copy_settings(picture);
478 picture_lock->unlock();
480 if(input_base) return input_base->set_picture(picture);
484 int VideoDevice::update_translation()
486 float frame_in_capture_x1f, frame_in_capture_x2f, frame_in_capture_y1f, frame_in_capture_y2f;
487 float capture_in_frame_x1f, capture_in_frame_x2f, capture_in_frame_y1f, capture_in_frame_y2f;
492 input_x = new_input_x;
493 input_y = new_input_y;
495 if(in_config->driver == VIDEO4LINUX || in_config->driver == VIDEO4LINUX2)
497 if(input_z != new_input_z)
499 input_z = new_input_z;
502 capture_w = (int)((float)in_config->w * input_z + 0.5);
503 capture_h = (int)((float)in_config->h * input_z + 0.5);
505 // Need to align to multiple of 4
510 frame_in_capture_x1f = (float)input_x * input_z + capture_w / 2 - in_config->w / 2;
511 frame_in_capture_x2f = (float)input_x * input_z + capture_w / 2 + in_config->w / 2;
512 frame_in_capture_y1f = (float)input_y * input_z + capture_h / 2 - in_config->h / 2;
513 frame_in_capture_y2f = (float)input_y * input_z + capture_h / 2 + in_config->h / 2;
515 capture_in_frame_x1f = 0;
516 capture_in_frame_y1f = 0;
517 capture_in_frame_x2f = in_config->w;
518 capture_in_frame_y2f = in_config->h;
520 if(frame_in_capture_x1f < 0) { capture_in_frame_x1f -= frame_in_capture_x1f; frame_in_capture_x1f = 0; }
521 if(frame_in_capture_y1f < 0) { capture_in_frame_y1f -= frame_in_capture_y1f; frame_in_capture_y1f = 0; }
522 if(frame_in_capture_x2f > capture_w) { capture_in_frame_x2f -= frame_in_capture_x2f - capture_w; frame_in_capture_x2f = capture_w; }
523 if(frame_in_capture_y2f > capture_h) { capture_in_frame_y2f -= frame_in_capture_y2f - capture_h; frame_in_capture_y2f = capture_h; }
525 frame_in_capture_x1 = (int)frame_in_capture_x1f;
526 frame_in_capture_y1 = (int)frame_in_capture_y1f;
527 frame_in_capture_x2 = (int)frame_in_capture_x2f;
528 frame_in_capture_y2 = (int)frame_in_capture_y2f;
530 capture_in_frame_x1 = (int)capture_in_frame_x1f;
531 capture_in_frame_y1 = (int)capture_in_frame_y1f;
532 capture_in_frame_x2 = (int)capture_in_frame_x2f;
533 capture_in_frame_y2 = (int)capture_in_frame_y2f;
541 int VideoDevice::set_latency_counter(int value)
543 latency_counter = value;
547 int VideoDevice::has_signal()
549 if(input_base) return input_base->has_signal();
554 int VideoDevice::read_buffer(VFrame *frame)
557 if(!capturing) return 0;
559 //printf("VideoDevice::read_buffer %p %p\n", frame, input_base);
562 // Reset the keepalive thread
563 if(keepalive) keepalive->capturing = 1;
564 result = input_base->read_buffer(frame);
567 keepalive->capturing = 0;
568 keepalive->reset_keepalive();
577 // ================================= OUTPUT ==========================================
580 int VideoDevice::open_output(VideoOutConfig *config,
588 //printf("VideoDevice::open_output 1 %d\n", out_config->driver);
589 *this->out_config = *config;
590 //printf("VideoDevice::open_output 1 %d\n", out_config->driver);
594 this->single_frame = single_frame;
596 //printf("VideoDevice::open_output 1 %d\n", out_config->driver);
597 switch(out_config->driver)
600 output_base = new VDeviceBUZ(this);
603 case PLAYBACK_X11_XV:
604 case PLAYBACK_X11_GL:
605 output_base = new VDeviceX11(this, output);
609 case PLAYBACK_DV1394:
610 case PLAYBACK_FIREWIRE:
611 case PLAYBACK_IEC61883:
612 output_base = new VDevice1394(this);
616 //printf("VideoDevice::open_output 2 %d\n", out_config->driver);
618 if(output_base->open_output())
623 //printf("VideoDevice::open_output 3 %d\n", out_config->driver);
633 int VideoDevice::start_playback()
635 // arm buffer before doing this
639 if(output_base) return output_base->start_playback();
643 int VideoDevice::stop_playback()
645 if(output_base) output_base->stop_playback();
651 void VideoDevice::goose_input()
653 if(input_base) input_base->goose_input();
656 void VideoDevice::new_output_buffer(VFrame **output, int colormodel)
658 if(!output_base) return;
659 output_base->new_output_buffer(output, colormodel);
663 int VideoDevice::interrupt_playback()
669 int VideoDevice::write_buffer(VFrame *output, EDL *edl)
671 //printf("VideoDevice::write_buffer 1 %p\n", output_base);
672 if(output_base) return output_base->write_buffer(output, edl);
676 int VideoDevice::output_visible()
678 if(output_base) return output_base->output_visible();
681 BC_Bitmap* VideoDevice::get_bitmap()
683 if(output_base) return output_base->get_bitmap();
687 int VideoDevice::set_cloexec_flag(int desc, int value)
689 int oldflags = fcntl(desc, F_GETFD, 0);
690 if(oldflags < 0) return oldflags;
692 oldflags |= FD_CLOEXEC;
694 oldflags &= ~FD_CLOEXEC;
695 return fcntl(desc, F_SETFD, oldflags);