4 #include "chantables.h"
5 #include "../hvirtual_config.h"
8 #include "playbackconfig.h"
9 #include "playbackengine.h"
10 #include "preferences.h"
11 #include "recordconfig.h"
12 #include "recordmonitor.h"
13 #include "vdevice1394.h"
14 #include "vdevicebuz.h"
15 #include "vdevicev4l.h"
16 #include "vdevicev4l2.h"
17 #include "vdevicev4l2jpeg.h"
18 #include "vdevicex11.h"
19 #include "videoconfig.h"
20 #include "videodevice.h"
21 #include "videowindow.h"
22 #include "videowindowgui.h"
28 KeepaliveThread::KeepaliveThread(VideoDevice *device)
35 this->device = device;
37 startup_lock = new Mutex("KeepaliveThread::startup_lock");
40 KeepaliveThread::~KeepaliveThread()
45 int KeepaliveThread::start_keepalive()
47 startup_lock->lock("KeepaliveThread::start_keepalive 1");
49 startup_lock->lock("KeepaliveThread::start_keepalive 2");
50 startup_lock->unlock();
53 void KeepaliveThread::run()
55 startup_lock->unlock();
59 // Give the capture a moment
60 // Should fix the delay in case users want slower frame rates.
61 timer.delay((long)(KEEPALIVE_DELAY * 1000));
63 // See if a capture happened
64 if(still_alive == 0 && capturing)
66 // printf("KeepaliveThread::run: device crashed\n");
74 int KeepaliveThread::reset_keepalive()
79 int KeepaliveThread::get_failed()
81 if(failed) return 1; else return 0;
84 int KeepaliveThread::stop()
88 // Force an immediate exit even if capture_frame worked.
99 VideoDevice::VideoDevice()
101 in_config = new VideoInConfig;
102 out_config = new VideoOutConfig;
103 channel = new Channel;
104 picture = new Picture;
105 sharing_lock = new Mutex("VideoDevice::sharing_lock");
106 channel_lock = new Mutex("VideoDevice::channel_lock");
107 picture_lock = new Mutex("VideoDevice::picture_lock");
111 VideoDevice::~VideoDevice()
113 input_sources.remove_all_objects();
123 int VideoDevice::initialize()
127 sharing_lock->reset();
131 is_playing_back = is_recording = 0;
151 int VideoDevice::open_input(VideoInConfig *config,
159 *this->in_config = *config;
162 this->input_z = -1; // Force initialization.
163 this->frame_rate = frame_rate;
166 switch(in_config->driver)
169 keepalive = new KeepaliveThread(this);
170 keepalive->start_keepalive();
171 input_base = new VDeviceV4L(this);
172 result = input_base->open_input();
176 #ifdef HAVE_VIDEO4LINUX2
178 input_base = new VDeviceV4L2(this);
179 result = input_base->open_input();
181 case VIDEO4LINUX2JPEG:
182 input_base = new VDeviceV4L2JPEG(this);
183 result = input_base->open_input();
188 this->input_x = input_x;
189 this->input_y = input_y;
190 input_base = new VDeviceX11(this, 0);
191 result = input_base->open_input();
194 //printf("VideoDevice 1\n");
195 keepalive = new KeepaliveThread(this);
196 keepalive->start_keepalive();
197 input_base = new VDeviceBUZ(this);
198 result = input_base->open_input();
201 case CAPTURE_FIREWIRE:
202 input_base = new VDevice1394(this);
203 result = input_base->open_input();
208 if(!result) capturing = 1;
212 int VideoDevice::is_compressed(int driver, int use_file, int use_fixed)
214 // FileMOV needs to have write_frames called so the start codes get scanned.
215 return ((driver == CAPTURE_BUZ && use_fixed) ||
216 (driver == VIDEO4LINUX2JPEG && use_fixed) ||
217 driver == CAPTURE_LML ||
218 driver == CAPTURE_FIREWIRE);
221 int VideoDevice::is_compressed(int use_file, int use_fixed)
223 return is_compressed(in_config->driver, use_file, use_fixed);
227 char* VideoDevice::get_vcodec(int driver)
233 case VIDEO4LINUX2JPEG:
234 return QUICKTIME_MJPA;
237 case CAPTURE_FIREWIRE:
245 char* VideoDevice::drivertostr(int driver)
250 return PLAYBACK_X11_TITLE;
252 case PLAYBACK_X11_XV:
253 return PLAYBACK_X11_XV_TITLE;
256 return PLAYBACK_BUZ_TITLE;
259 return VIDEO4LINUX_TITLE;
262 return VIDEO4LINUX2_TITLE;
264 case VIDEO4LINUX2JPEG:
265 return VIDEO4LINUX2JPEG_TITLE;
268 return SCREENCAPTURE_TITLE;
271 return CAPTURE_BUZ_TITLE;
273 case CAPTURE_FIREWIRE:
274 return CAPTURE_FIREWIRE_TITLE;
280 int VideoDevice::get_best_colormodel(Asset *asset)
283 return input_base->get_best_colormodel(asset);
288 int VideoDevice::close_all()
292 //printf("VideoDevice::close_all 1\n");
297 output_base->close_all();
302 //printf("VideoDevice::close_all 2\n");
308 input_base->close_all();
320 //printf("VideoDevice::close_all 3\n");
321 input_sources.remove_all_objects();
323 //printf("VideoDevice::close_all 4\n");
326 //printf("VideoDevice::close_all 5\n");
331 int VideoDevice::set_adevice(AudioDevice *adevice)
333 this->adevice = adevice;
338 ArrayList<Channel*>* VideoDevice::get_inputs()
340 return &input_sources;
343 Channel* VideoDevice::new_input_source(char *device_name)
345 for(int i = 0; i < input_sources.total; i++)
347 if(!strcmp(input_sources.values[i]->device_name, device_name))
348 return input_sources.values[i];
350 Channel *item = new Channel;
351 strcpy(item->device_name, device_name);
352 input_sources.append(item);
356 int VideoDevice::get_failed()
359 return keepalive->get_failed();
364 int VideoDevice::interrupt_crash()
366 if(input_base) return input_base->interrupt_crash();
370 int VideoDevice::set_translation(int input_x, int input_y)
372 this->input_x = input_x;
373 this->input_y = input_y;
377 int VideoDevice::set_field_order(int odd_field_first)
379 this->odd_field_first = odd_field_first;
383 int VideoDevice::set_channel(Channel *channel)
387 channel_lock->lock("VideoDevice::set_channel");
388 this->channel->copy_settings(channel);
390 channel_lock->unlock();
392 if(input_base) return input_base->set_channel(channel);
393 if(output_base) return output_base->set_channel(channel);
397 void VideoDevice::set_quality(int quality)
399 this->quality = quality;
402 void VideoDevice::set_cpus(int cpus)
407 int VideoDevice::set_picture(Picture *picture)
411 picture_lock->lock("VideoDevice::set_picture");
412 this->picture->copy_settings(picture);
414 picture_lock->unlock();
416 if(input_base) return input_base->set_picture(picture);
420 int VideoDevice::update_translation()
422 float frame_in_capture_x1f, frame_in_capture_x2f, frame_in_capture_y1f, frame_in_capture_y2f;
423 float capture_in_frame_x1f, capture_in_frame_x2f, capture_in_frame_y1f, capture_in_frame_y2f;
428 input_x = new_input_x;
429 input_y = new_input_y;
431 if(in_config->driver == VIDEO4LINUX || in_config->driver == VIDEO4LINUX2)
433 if(input_z != new_input_z)
435 input_z = new_input_z;
438 capture_w = (int)((float)in_config->w * input_z + 0.5);
439 capture_h = (int)((float)in_config->h * input_z + 0.5);
441 // Need to align to multiple of 4
446 frame_in_capture_x1f = (float)input_x * input_z + capture_w / 2 - in_config->w / 2;
447 frame_in_capture_x2f = (float)input_x * input_z + capture_w / 2 + in_config->w / 2;
448 frame_in_capture_y1f = (float)input_y * input_z + capture_h / 2 - in_config->h / 2;
449 frame_in_capture_y2f = (float)input_y * input_z + capture_h / 2 + in_config->h / 2;
451 capture_in_frame_x1f = 0;
452 capture_in_frame_y1f = 0;
453 capture_in_frame_x2f = in_config->w;
454 capture_in_frame_y2f = in_config->h;
456 if(frame_in_capture_x1f < 0) { capture_in_frame_x1f -= frame_in_capture_x1f; frame_in_capture_x1f = 0; }
457 if(frame_in_capture_y1f < 0) { capture_in_frame_y1f -= frame_in_capture_y1f; frame_in_capture_y1f = 0; }
458 if(frame_in_capture_x2f > capture_w) { capture_in_frame_x2f -= frame_in_capture_x2f - capture_w; frame_in_capture_x2f = capture_w; }
459 if(frame_in_capture_y2f > capture_h) { capture_in_frame_y2f -= frame_in_capture_y2f - capture_h; frame_in_capture_y2f = capture_h; }
461 frame_in_capture_x1 = (int)frame_in_capture_x1f;
462 frame_in_capture_y1 = (int)frame_in_capture_y1f;
463 frame_in_capture_x2 = (int)frame_in_capture_x2f;
464 frame_in_capture_y2 = (int)frame_in_capture_y2f;
466 capture_in_frame_x1 = (int)capture_in_frame_x1f;
467 capture_in_frame_y1 = (int)capture_in_frame_y1f;
468 capture_in_frame_x2 = (int)capture_in_frame_x2f;
469 capture_in_frame_y2 = (int)capture_in_frame_y2f;
477 int VideoDevice::set_latency_counter(int value)
479 latency_counter = value;
483 int VideoDevice::read_buffer(VFrame *frame)
486 if(!capturing) return 0;
488 //printf("VideoDevice::read_buffer %p %p\n", frame, input_base);
491 // Reset the keepalive thread
492 if(keepalive) keepalive->capturing = 1;
493 result = input_base->read_buffer(frame);
496 keepalive->capturing = 0;
497 keepalive->reset_keepalive();
506 // ================================= OUTPUT ==========================================
509 int VideoDevice::open_output(VideoOutConfig *config,
517 //printf("VideoDevice::open_output 1 %d\n", out_config->driver);
518 *this->out_config = *config;
519 //printf("VideoDevice::open_output 1 %d\n", out_config->driver);
523 this->single_frame = single_frame;
525 //printf("VideoDevice::open_output 1 %d\n", out_config->driver);
526 switch(out_config->driver)
529 output_base = new VDeviceBUZ(this);
532 case PLAYBACK_X11_XV:
533 output_base = new VDeviceX11(this, output);
536 case PLAYBACK_DV1394:
537 case PLAYBACK_FIREWIRE:
538 output_base = new VDevice1394(this);
541 //printf("VideoDevice::open_output 2 %d\n", out_config->driver);
543 if(output_base->open_output())
548 //printf("VideoDevice::open_output 3 %d\n", out_config->driver);
558 int VideoDevice::start_playback()
560 // arm buffer before doing this
564 if(output_base) return output_base->start_playback();
568 int VideoDevice::stop_playback()
570 if(output_base) output_base->stop_playback();
576 void VideoDevice::goose_input()
578 if(input_base) input_base->goose_input();
581 void VideoDevice::new_output_buffers(VFrame **outputs, int colormodel)
583 for(int i = 0; i < MAX_CHANNELS; i++)
586 if(!output_base) return;
587 output_base->new_output_buffer(outputs, colormodel);
591 int VideoDevice::interrupt_playback()
597 int VideoDevice::write_buffer(VFrame **outputs, EDL *edl)
599 //printf("VideoDevice::write_buffer 1 %p\n", output_base);
600 if(output_base) return output_base->write_buffer(outputs, edl);
604 int VideoDevice::output_visible()
606 if(output_base) return output_base->output_visible();
609 BC_Bitmap* VideoDevice::get_bitmap()
611 if(output_base) return output_base->get_bitmap();
615 int VideoDevice::set_cloexec_flag(int desc, int value)
617 int oldflags = fcntl(desc, F_GETFD, 0);
618 if(oldflags < 0) return oldflags;
620 oldflags |= FD_CLOEXEC;
622 oldflags &= ~FD_CLOEXEC;
623 return fcntl(desc, F_SETFD, oldflags);