4 #include "chantables.h"
7 #include "playbackconfig.h"
8 #include "playbackengine.h"
9 #include "preferences.h"
10 #include "recordconfig.h"
11 #include "recordmonitor.h"
12 #include "vdevice1394.h"
13 #include "vdevicebuz.h"
14 #include "vdevicev4l.h"
15 #include "vdevicev4l2.h"
16 #include "vdevicev4l2jpeg.h"
17 #include "vdevicex11.h"
18 #include "videoconfig.h"
19 #include "videodevice.h"
20 #include "videowindow.h"
21 #include "videowindowgui.h"
27 KeepaliveThread::KeepaliveThread(VideoDevice *device)
34 this->device = device;
36 startup_lock = new Mutex("KeepaliveThread::startup_lock");
39 KeepaliveThread::~KeepaliveThread()
44 int KeepaliveThread::start_keepalive()
46 startup_lock->lock("KeepaliveThread::start_keepalive 1");
48 startup_lock->lock("KeepaliveThread::start_keepalive 2");
49 startup_lock->unlock();
52 void KeepaliveThread::run()
54 startup_lock->unlock();
58 // Give the capture a moment
59 // Should fix the delay in case users want slower frame rates.
60 timer.delay((long)(KEEPALIVE_DELAY * 1000));
62 // See if a capture happened
63 if(still_alive == 0 && capturing)
65 // printf("KeepaliveThread::run: device crashed\n");
73 int KeepaliveThread::reset_keepalive()
78 int KeepaliveThread::get_failed()
80 if(failed) return 1; else return 0;
83 int KeepaliveThread::stop()
87 // Force an immediate exit even if capture_frame worked.
98 VideoDevice::VideoDevice()
100 in_config = new VideoInConfig;
101 out_config = new VideoOutConfig;
102 channel = new Channel;
103 picture = new Picture;
104 sharing_lock = new Mutex("VideoDevice::sharing_lock");
105 channel_lock = new Mutex("VideoDevice::channel_lock");
106 picture_lock = new Mutex("VideoDevice::picture_lock");
110 VideoDevice::~VideoDevice()
112 input_sources.remove_all_objects();
122 int VideoDevice::initialize()
126 sharing_lock->reset();
130 is_playing_back = is_recording = 0;
150 int VideoDevice::open_input(VideoInConfig *config,
158 *this->in_config = *config;
161 this->input_z = -1; // Force initialization.
162 this->frame_rate = frame_rate;
165 switch(in_config->driver)
168 keepalive = new KeepaliveThread(this);
169 keepalive->start_keepalive();
170 input_base = new VDeviceV4L(this);
171 result = input_base->open_input();
175 #ifdef HAVE_VIDEO4LINUX2
177 input_base = new VDeviceV4L2(this);
178 result = input_base->open_input();
180 case VIDEO4LINUX2JPEG:
181 input_base = new VDeviceV4L2JPEG(this);
182 result = input_base->open_input();
187 this->input_x = input_x;
188 this->input_y = input_y;
189 input_base = new VDeviceX11(this, 0);
190 result = input_base->open_input();
193 //printf("VideoDevice 1\n");
194 keepalive = new KeepaliveThread(this);
195 keepalive->start_keepalive();
196 input_base = new VDeviceBUZ(this);
197 result = input_base->open_input();
200 case CAPTURE_FIREWIRE:
201 input_base = new VDevice1394(this);
202 result = input_base->open_input();
207 if(!result) capturing = 1;
211 int VideoDevice::is_compressed(int driver, int use_file, int use_fixed)
213 // FileMOV needs to have write_frames called so the start codes get scanned.
214 return ((driver == CAPTURE_BUZ && use_fixed) ||
215 (driver == VIDEO4LINUX2JPEG && use_fixed) ||
216 driver == CAPTURE_LML ||
217 driver == CAPTURE_FIREWIRE);
220 int VideoDevice::is_compressed(int use_file, int use_fixed)
222 return is_compressed(in_config->driver, use_file, use_fixed);
226 char* VideoDevice::get_vcodec(int driver)
232 case VIDEO4LINUX2JPEG:
233 return QUICKTIME_MJPA;
236 case CAPTURE_FIREWIRE:
244 char* VideoDevice::drivertostr(int driver)
249 return PLAYBACK_X11_TITLE;
251 case PLAYBACK_X11_XV:
252 return PLAYBACK_X11_XV_TITLE;
255 return PLAYBACK_BUZ_TITLE;
258 return VIDEO4LINUX_TITLE;
261 return VIDEO4LINUX2_TITLE;
263 case VIDEO4LINUX2JPEG:
264 return VIDEO4LINUX2JPEG_TITLE;
267 return SCREENCAPTURE_TITLE;
270 return CAPTURE_BUZ_TITLE;
272 case CAPTURE_FIREWIRE:
273 return CAPTURE_FIREWIRE_TITLE;
279 int VideoDevice::get_best_colormodel(Asset *asset)
282 return input_base->get_best_colormodel(asset);
287 int VideoDevice::close_all()
291 //printf("VideoDevice::close_all 1\n");
296 output_base->close_all();
301 //printf("VideoDevice::close_all 2\n");
307 input_base->close_all();
319 //printf("VideoDevice::close_all 3\n");
320 input_sources.remove_all_objects();
322 //printf("VideoDevice::close_all 4\n");
325 //printf("VideoDevice::close_all 5\n");
330 int VideoDevice::set_adevice(AudioDevice *adevice)
332 this->adevice = adevice;
337 ArrayList<Channel*>* VideoDevice::get_inputs()
339 return &input_sources;
342 Channel* VideoDevice::new_input_source(char *device_name)
344 for(int i = 0; i < input_sources.total; i++)
346 if(!strcmp(input_sources.values[i]->device_name, device_name))
347 return input_sources.values[i];
349 Channel *item = new Channel;
350 strcpy(item->device_name, device_name);
351 input_sources.append(item);
355 int VideoDevice::get_failed()
358 return keepalive->get_failed();
363 int VideoDevice::interrupt_crash()
365 if(input_base) return input_base->interrupt_crash();
369 int VideoDevice::set_translation(int input_x, int input_y)
371 this->input_x = input_x;
372 this->input_y = input_y;
376 int VideoDevice::set_field_order(int odd_field_first)
378 this->odd_field_first = odd_field_first;
382 int VideoDevice::set_channel(Channel *channel)
386 channel_lock->lock("VideoDevice::set_channel");
387 this->channel->copy_settings(channel);
389 channel_lock->unlock();
391 if(input_base) return input_base->set_channel(channel);
392 if(output_base) return output_base->set_channel(channel);
396 void VideoDevice::set_quality(int quality)
398 this->quality = quality;
401 void VideoDevice::set_cpus(int cpus)
406 int VideoDevice::set_picture(Picture *picture)
410 picture_lock->lock("VideoDevice::set_picture");
411 this->picture->copy_settings(picture);
413 picture_lock->unlock();
415 if(input_base) return input_base->set_picture(picture);
419 int VideoDevice::update_translation()
421 float frame_in_capture_x1f, frame_in_capture_x2f, frame_in_capture_y1f, frame_in_capture_y2f;
422 float capture_in_frame_x1f, capture_in_frame_x2f, capture_in_frame_y1f, capture_in_frame_y2f;
427 input_x = new_input_x;
428 input_y = new_input_y;
430 if(in_config->driver == VIDEO4LINUX || in_config->driver == VIDEO4LINUX2)
432 if(input_z != new_input_z)
434 input_z = new_input_z;
437 capture_w = (int)((float)in_config->w * input_z + 0.5);
438 capture_h = (int)((float)in_config->h * input_z + 0.5);
440 // Need to align to multiple of 4
445 frame_in_capture_x1f = (float)input_x * input_z + capture_w / 2 - in_config->w / 2;
446 frame_in_capture_x2f = (float)input_x * input_z + capture_w / 2 + in_config->w / 2;
447 frame_in_capture_y1f = (float)input_y * input_z + capture_h / 2 - in_config->h / 2;
448 frame_in_capture_y2f = (float)input_y * input_z + capture_h / 2 + in_config->h / 2;
450 capture_in_frame_x1f = 0;
451 capture_in_frame_y1f = 0;
452 capture_in_frame_x2f = in_config->w;
453 capture_in_frame_y2f = in_config->h;
455 if(frame_in_capture_x1f < 0) { capture_in_frame_x1f -= frame_in_capture_x1f; frame_in_capture_x1f = 0; }
456 if(frame_in_capture_y1f < 0) { capture_in_frame_y1f -= frame_in_capture_y1f; frame_in_capture_y1f = 0; }
457 if(frame_in_capture_x2f > capture_w) { capture_in_frame_x2f -= frame_in_capture_x2f - capture_w; frame_in_capture_x2f = capture_w; }
458 if(frame_in_capture_y2f > capture_h) { capture_in_frame_y2f -= frame_in_capture_y2f - capture_h; frame_in_capture_y2f = capture_h; }
460 frame_in_capture_x1 = (int)frame_in_capture_x1f;
461 frame_in_capture_y1 = (int)frame_in_capture_y1f;
462 frame_in_capture_x2 = (int)frame_in_capture_x2f;
463 frame_in_capture_y2 = (int)frame_in_capture_y2f;
465 capture_in_frame_x1 = (int)capture_in_frame_x1f;
466 capture_in_frame_y1 = (int)capture_in_frame_y1f;
467 capture_in_frame_x2 = (int)capture_in_frame_x2f;
468 capture_in_frame_y2 = (int)capture_in_frame_y2f;
476 int VideoDevice::set_latency_counter(int value)
478 latency_counter = value;
482 int VideoDevice::read_buffer(VFrame *frame)
485 if(!capturing) return 0;
487 //printf("VideoDevice::read_buffer %p %p\n", frame, input_base);
490 // Reset the keepalive thread
491 if(keepalive) keepalive->capturing = 1;
492 result = input_base->read_buffer(frame);
495 keepalive->capturing = 0;
496 keepalive->reset_keepalive();
505 // ================================= OUTPUT ==========================================
508 int VideoDevice::open_output(VideoOutConfig *config,
516 //printf("VideoDevice::open_output 1 %d\n", out_config->driver);
517 *this->out_config = *config;
518 //printf("VideoDevice::open_output 1 %d\n", out_config->driver);
522 this->single_frame = single_frame;
524 //printf("VideoDevice::open_output 1 %d\n", out_config->driver);
525 switch(out_config->driver)
528 output_base = new VDeviceBUZ(this);
531 case PLAYBACK_X11_XV:
532 output_base = new VDeviceX11(this, output);
535 case PLAYBACK_DV1394:
536 case PLAYBACK_FIREWIRE:
537 output_base = new VDevice1394(this);
540 //printf("VideoDevice::open_output 2 %d\n", out_config->driver);
542 if(output_base->open_output())
547 //printf("VideoDevice::open_output 3 %d\n", out_config->driver);
557 int VideoDevice::start_playback()
559 // arm buffer before doing this
563 if(output_base) return output_base->start_playback();
567 int VideoDevice::stop_playback()
569 if(output_base) output_base->stop_playback();
575 void VideoDevice::goose_input()
577 if(input_base) input_base->goose_input();
580 void VideoDevice::new_output_buffers(VFrame **outputs, int colormodel)
582 for(int i = 0; i < MAX_CHANNELS; i++)
585 if(!output_base) return;
586 output_base->new_output_buffer(outputs, colormodel);
590 int VideoDevice::interrupt_playback()
596 int VideoDevice::write_buffer(VFrame **outputs, EDL *edl)
598 //printf("VideoDevice::write_buffer 1 %p\n", output_base);
599 if(output_base) return output_base->write_buffer(outputs, edl);
603 int VideoDevice::output_visible()
605 if(output_base) return output_base->output_visible();
608 BC_Bitmap* VideoDevice::get_bitmap()
610 if(output_base) return output_base->get_bitmap();
614 int VideoDevice::set_cloexec_flag(int desc, int value)
616 int oldflags = fcntl(desc, F_GETFD, 0);
617 if(oldflags < 0) return oldflags;
619 oldflags |= FD_CLOEXEC;
621 oldflags &= ~FD_CLOEXEC;
622 return fcntl(desc, F_SETFD, oldflags);