7 #include "chantables.h"
12 #include "playbackconfig.h"
13 #include "playbackengine.h"
14 #include "preferences.h"
15 #include "quicktime.h"
16 #include "recordconfig.h"
17 #include "recordmonitor.h"
19 #include "vdevice1394.h"
21 #include "vdevicebuz.h"
22 #include "vdevicedvb.h"
23 #include "vdevicev4l.h"
24 #include "vdevicev4l2.h"
25 #include "vdevicev4l2jpeg.h"
26 #include "vdevicex11.h"
27 #include "videoconfig.h"
28 #include "videodevice.h"
29 #include "videowindow.h"
30 #include "videowindowgui.h"
36 KeepaliveThread::KeepaliveThread(VideoDevice *device)
43 this->device = device;
45 startup_lock = new Mutex("KeepaliveThread::startup_lock");
48 KeepaliveThread::~KeepaliveThread()
53 int KeepaliveThread::start_keepalive()
55 startup_lock->lock("KeepaliveThread::start_keepalive 1");
57 startup_lock->lock("KeepaliveThread::start_keepalive 2");
58 startup_lock->unlock();
61 void KeepaliveThread::run()
63 startup_lock->unlock();
67 // Give the capture a moment
68 // Should fix the delay in case users want slower frame rates.
69 timer.delay((long)(KEEPALIVE_DELAY * 1000));
71 // See if a capture happened
72 if(still_alive == 0 && capturing)
74 // printf("KeepaliveThread::run: device crashed\n");
82 int KeepaliveThread::reset_keepalive()
87 int KeepaliveThread::get_failed()
89 if(failed) return 1; else return 0;
92 int KeepaliveThread::stop()
96 // Force an immediate exit even if capture_frame worked.
107 VideoDevice::VideoDevice(MWindow *mwindow)
109 this->mwindow = mwindow;
110 in_config = new VideoInConfig;
111 out_config = new VideoOutConfig;
112 channel = new Channel;
113 picture = new PictureConfig(mwindow ? mwindow->defaults : 0);
114 sharing_lock = new Mutex("VideoDevice::sharing_lock");
115 channel_lock = new Mutex("VideoDevice::channel_lock");
116 picture_lock = new Mutex("VideoDevice::picture_lock");
121 VideoDevice::~VideoDevice()
123 input_sources.remove_all_objects();
133 int VideoDevice::initialize()
137 sharing_lock->reset();
141 is_playing_back = is_recording = 0;
161 int VideoDevice::open_input(VideoInConfig *config,
169 *this->in_config = *config;
172 this->input_z = -1; // Force initialization.
173 this->frame_rate = frame_rate;
176 switch(in_config->driver)
179 keepalive = new KeepaliveThread(this);
180 keepalive->start_keepalive();
182 result = input_base->open_input();
186 #ifdef HAVE_VIDEO4LINUX2
189 result = input_base->open_input();
191 case VIDEO4LINUX2JPEG:
193 result = input_base->open_input();
198 this->input_x = input_x;
199 this->input_y = input_y;
201 result = input_base->open_input();
204 //printf("VideoDevice 1\n");
205 keepalive = new KeepaliveThread(this);
206 keepalive->start_keepalive();
208 result = input_base->open_input();
211 case CAPTURE_FIREWIRE:
212 case CAPTURE_IEC61883:
214 result = input_base->open_input();
220 result = input_base->open_input();
224 if(!result) capturing = 1;
228 VDeviceBase* VideoDevice::new_device_base()
230 switch(in_config->driver)
233 return input_base = new VDeviceV4L(this);
235 #ifdef HAVE_VIDEO4LINUX2
237 return input_base = new VDeviceV4L2(this);
239 case VIDEO4LINUX2JPEG:
240 return input_base = new VDeviceV4L2JPEG(this);
244 return input_base = new VDeviceX11(this, 0);
247 return input_base = new VDeviceBUZ(this);
250 case CAPTURE_FIREWIRE:
251 case CAPTURE_IEC61883:
252 return input_base = new VDevice1394(this);
256 return input_base = new VDeviceDVB(this);
261 static char* get_channeldb_path(VideoInConfig *vconfig_in)
264 switch(vconfig_in->driver)
267 path = "channels_v4l";
270 path = "channels_v4l2";
272 case VIDEO4LINUX2JPEG:
273 path = "channels_v4l2jpeg";
276 path = "channels_buz";
279 path = "channels_dvb";
285 void VideoDevice::load_channeldb(ChannelDB *channeldb, VideoInConfig *vconfig_in)
287 channeldb->load(get_channeldb_path(vconfig_in));
290 void VideoDevice::save_channeldb(ChannelDB *channeldb, VideoInConfig *vconfig_in)
292 channeldb->save(get_channeldb_path(vconfig_in));
296 VDeviceBase* VideoDevice::get_output_base()
301 int VideoDevice::is_compressed(int driver, int use_file, int use_fixed)
303 // FileMOV needs to have write_frames called so the start codes get scanned.
304 return ((driver == CAPTURE_BUZ && use_fixed) ||
305 (driver == VIDEO4LINUX2JPEG && use_fixed) ||
306 driver == CAPTURE_LML ||
307 driver == CAPTURE_FIREWIRE ||
308 driver == CAPTURE_IEC61883);
311 int VideoDevice::is_compressed(int use_file, int use_fixed)
313 return is_compressed(in_config->driver, use_file, use_fixed);
317 void VideoDevice::fix_asset(Asset *asset, int driver)
319 // Fix asset using legacy routine
324 case VIDEO4LINUX2JPEG:
325 if(asset->format != FILE_AVI &&
326 asset->format != FILE_MOV)
327 asset->format = FILE_MOV;
328 strcpy(asset->vcodec, QUICKTIME_MJPA);
331 case CAPTURE_FIREWIRE:
332 case CAPTURE_IEC61883:
333 if(asset->format != FILE_AVI &&
334 asset->format != FILE_MOV)
335 asset->format = FILE_MOV;
336 strcpy(asset->vcodec, QUICKTIME_DVSD);
340 // Fix asset using inherited routine
343 if(input_base) input_base->fix_asset(asset);
349 char* VideoDevice::drivertostr(int driver)
354 return PLAYBACK_X11_TITLE;
356 case PLAYBACK_X11_XV:
357 return PLAYBACK_X11_XV_TITLE;
359 case PLAYBACK_X11_GL:
360 return PLAYBACK_X11_GL_TITLE;
363 return PLAYBACK_BUZ_TITLE;
366 return VIDEO4LINUX_TITLE;
369 return VIDEO4LINUX2_TITLE;
371 case VIDEO4LINUX2JPEG:
372 return VIDEO4LINUX2JPEG_TITLE;
375 return SCREENCAPTURE_TITLE;
378 return CAPTURE_BUZ_TITLE;
381 case CAPTURE_FIREWIRE:
382 return CAPTURE_FIREWIRE_TITLE;
384 case CAPTURE_IEC61883:
385 return CAPTURE_IEC61883_TITLE;
392 int VideoDevice::get_best_colormodel(Asset *asset)
395 return input_base->get_best_colormodel(asset);
400 int VideoDevice::close_all()
408 output_base->close_all();
418 input_base->close_all();
432 input_sources.remove_all_objects();
440 int VideoDevice::set_adevice(AudioDevice *adevice)
442 this->adevice = adevice;
447 ArrayList<Channel*>* VideoDevice::get_inputs()
449 return &input_sources;
452 Channel* VideoDevice::new_input_source(char *device_name)
454 for(int i = 0; i < input_sources.total; i++)
456 if(!strcmp(input_sources.values[i]->device_name, device_name))
457 return input_sources.values[i];
459 Channel *item = new Channel;
460 strcpy(item->device_name, device_name);
461 input_sources.append(item);
465 int VideoDevice::get_failed()
468 return keepalive->get_failed();
473 int VideoDevice::interrupt_crash()
475 if(input_base) return input_base->interrupt_crash();
479 int VideoDevice::set_translation(int input_x, int input_y)
481 this->input_x = input_x;
482 this->input_y = input_y;
486 int VideoDevice::set_field_order(int odd_field_first)
488 this->odd_field_first = odd_field_first;
492 int VideoDevice::set_channel(Channel *channel)
496 channel_lock->lock("VideoDevice::set_channel");
497 this->channel->copy_settings(channel);
499 channel_lock->unlock();
501 if(input_base) return input_base->set_channel(channel);
502 if(output_base) return output_base->set_channel(channel);
506 void VideoDevice::set_quality(int quality)
508 this->quality = quality;
511 void VideoDevice::set_cpus(int cpus)
516 int VideoDevice::set_picture(PictureConfig *picture)
520 picture_lock->lock("VideoDevice::set_picture");
521 this->picture->copy_settings(picture);
523 picture_lock->unlock();
525 if(input_base) return input_base->set_picture(picture);
529 int VideoDevice::update_translation()
531 float frame_in_capture_x1f, frame_in_capture_x2f, frame_in_capture_y1f, frame_in_capture_y2f;
532 float capture_in_frame_x1f, capture_in_frame_x2f, capture_in_frame_y1f, capture_in_frame_y2f;
537 input_x = new_input_x;
538 input_y = new_input_y;
540 if(in_config->driver == VIDEO4LINUX || in_config->driver == VIDEO4LINUX2)
542 if(input_z != new_input_z)
544 input_z = new_input_z;
547 capture_w = (int)((float)in_config->w * input_z + 0.5);
548 capture_h = (int)((float)in_config->h * input_z + 0.5);
550 // Need to align to multiple of 4
555 frame_in_capture_x1f = (float)input_x * input_z + capture_w / 2 - in_config->w / 2;
556 frame_in_capture_x2f = (float)input_x * input_z + capture_w / 2 + in_config->w / 2;
557 frame_in_capture_y1f = (float)input_y * input_z + capture_h / 2 - in_config->h / 2;
558 frame_in_capture_y2f = (float)input_y * input_z + capture_h / 2 + in_config->h / 2;
560 capture_in_frame_x1f = 0;
561 capture_in_frame_y1f = 0;
562 capture_in_frame_x2f = in_config->w;
563 capture_in_frame_y2f = in_config->h;
565 if(frame_in_capture_x1f < 0) { capture_in_frame_x1f -= frame_in_capture_x1f; frame_in_capture_x1f = 0; }
566 if(frame_in_capture_y1f < 0) { capture_in_frame_y1f -= frame_in_capture_y1f; frame_in_capture_y1f = 0; }
567 if(frame_in_capture_x2f > capture_w) { capture_in_frame_x2f -= frame_in_capture_x2f - capture_w; frame_in_capture_x2f = capture_w; }
568 if(frame_in_capture_y2f > capture_h) { capture_in_frame_y2f -= frame_in_capture_y2f - capture_h; frame_in_capture_y2f = capture_h; }
570 frame_in_capture_x1 = (int)frame_in_capture_x1f;
571 frame_in_capture_y1 = (int)frame_in_capture_y1f;
572 frame_in_capture_x2 = (int)frame_in_capture_x2f;
573 frame_in_capture_y2 = (int)frame_in_capture_y2f;
575 capture_in_frame_x1 = (int)capture_in_frame_x1f;
576 capture_in_frame_y1 = (int)capture_in_frame_y1f;
577 capture_in_frame_x2 = (int)capture_in_frame_x2f;
578 capture_in_frame_y2 = (int)capture_in_frame_y2f;
586 int VideoDevice::set_latency_counter(int value)
588 latency_counter = value;
592 int VideoDevice::has_signal()
594 if(input_base) return input_base->has_signal();
599 int VideoDevice::read_buffer(VFrame *frame)
602 if(!capturing) return 0;
604 //printf("VideoDevice::read_buffer %p %p\n", frame, input_base);
607 // Reset the keepalive thread
608 if(keepalive) keepalive->capturing = 1;
609 result = input_base->read_buffer(frame);
612 keepalive->capturing = 0;
613 keepalive->reset_keepalive();
622 // ================================= OUTPUT ==========================================
625 int VideoDevice::open_output(VideoOutConfig *config,
633 //printf("VideoDevice::open_output 1 %d\n", out_config->driver);
634 *this->out_config = *config;
635 //printf("VideoDevice::open_output 1 %d\n", out_config->driver);
639 this->single_frame = single_frame;
641 //printf("VideoDevice::open_output 1 %d\n", out_config->driver);
642 switch(out_config->driver)
645 output_base = new VDeviceBUZ(this);
648 case PLAYBACK_X11_XV:
649 case PLAYBACK_X11_GL:
650 output_base = new VDeviceX11(this, output);
654 case PLAYBACK_DV1394:
655 case PLAYBACK_FIREWIRE:
656 case PLAYBACK_IEC61883:
657 output_base = new VDevice1394(this);
661 //printf("VideoDevice::open_output 2 %d\n", out_config->driver);
663 if(output_base->open_output())
668 //printf("VideoDevice::open_output 3 %d\n", out_config->driver);
678 int VideoDevice::start_playback()
680 // arm buffer before doing this
684 if(output_base) return output_base->start_playback();
688 int VideoDevice::stop_playback()
690 if(output_base) output_base->stop_playback();
696 void VideoDevice::goose_input()
698 if(input_base) input_base->goose_input();
701 void VideoDevice::new_output_buffer(VFrame **output, int colormodel)
703 if(!output_base) return;
704 output_base->new_output_buffer(output, colormodel);
708 int VideoDevice::interrupt_playback()
714 int VideoDevice::write_buffer(VFrame *output, EDL *edl)
716 //printf("VideoDevice::write_buffer 1 %p\n", output_base);
717 if(output_base) return output_base->write_buffer(output, edl);
721 int VideoDevice::output_visible()
723 if(output_base) return output_base->output_visible();
726 BC_Bitmap* VideoDevice::get_bitmap()
728 if(output_base) return output_base->get_bitmap();
732 int VideoDevice::set_cloexec_flag(int desc, int value)
734 int oldflags = fcntl(desc, F_GETFD, 0);
735 if(oldflags < 0) return oldflags;
737 oldflags |= FD_CLOEXEC;
739 oldflags &= ~FD_CLOEXEC;
740 return fcntl(desc, F_SETFD, oldflags);