4 * Copyright (C) 2008-2013 Adam Williams <broadcast at earthling dot net>
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 #include "bccapture.h"
25 #include "bcsignals.h"
27 #include "channeldb.h"
28 #include "chantables.h"
30 #include "edlsession.h"
32 #include "../hvirtual_config.h"
36 #include "mwindowgui.h"
38 #include "playbackconfig.h"
39 #include "playbackengine.h"
40 #include "preferences.h"
41 #include "recordconfig.h"
42 #include "recordgui.h"
43 #include "recordmonitor.h"
45 #include "vdevice1394.h"
46 #include "vdevicebuz.h"
47 #include "vdevicedvb.h"
48 #include "vdevicev4l.h"
49 #include "vdevicev4l2.h"
50 #include "vdevicev4l2jpeg.h"
51 #include "vdevicev4l2mpeg.h"
52 #include "vdevicex11.h"
53 #include "videoconfig.h"
54 #include "videodevice.h"
55 #include "videowindow.h"
56 #include "videowindowgui.h"
62 KeepaliveThread::KeepaliveThread(VideoDevice *device)
69 this->device = device;
71 startup_lock = new Mutex("KeepaliveThread::startup_lock");
74 KeepaliveThread::~KeepaliveThread()
79 int KeepaliveThread::start_keepalive()
81 startup_lock->lock("KeepaliveThread::start_keepalive 1");
83 startup_lock->lock("KeepaliveThread::start_keepalive 2");
84 startup_lock->unlock();
88 void KeepaliveThread::run()
90 startup_lock->unlock();
94 // Give the capture a moment
95 // Should fix the delay in case users want slower frame rates.
96 timer.delay((long)(KEEPALIVE_DELAY * 1000));
98 // See if a capture happened
99 if(still_alive == 0 && capturing)
101 // printf("KeepaliveThread::run: device crashed\n");
109 int KeepaliveThread::reset_keepalive()
115 int KeepaliveThread::get_failed()
117 if(failed) return 1; else return 0;
120 int KeepaliveThread::stop()
124 // Force an immediate exit even if capture_frame worked.
136 VideoDevice::VideoDevice(MWindow *mwindow)
138 this->mwindow = mwindow;
139 in_config = new VideoInConfig;
140 out_config = new VideoOutConfig;
141 channel = new Channel;
142 picture = new PictureConfig();
143 sharing_lock = new Mutex("VideoDevice::sharing_lock");
144 channel_lock = new Mutex("VideoDevice::channel_lock");
145 picture_lock = new Mutex("VideoDevice::picture_lock");
150 VideoDevice::~VideoDevice()
152 input_sources.remove_all_objects();
162 int VideoDevice::initialize()
166 sharing_lock->reset();
170 is_playing_back = is_recording = 0;
180 in_config_updated = 0;
194 int VideoDevice::open_input(VideoInConfig *config,
202 *this->in_config = *config;
205 this->input_z = -1; // Force initialization.
206 this->frame_rate = frame_rate;
207 if( input_base ) return 1; // device already open
209 switch(in_config->driver) {
211 keepalive = new KeepaliveThread(this);
212 keepalive->start_keepalive();
216 #ifdef HAVE_VIDEO4LINUX2
219 case VIDEO4LINUX2JPEG:
220 case VIDEO4LINUX2MPEG:
221 case CAPTURE_JPEG_WEBCAM:
222 case CAPTURE_YUYV_WEBCAM:
228 this->input_x = input_x;
229 this->input_y = input_y;
233 //printf("VideoDevice 1\n");
234 keepalive = new KeepaliveThread(this);
235 keepalive->start_keepalive();
238 case CAPTURE_FIREWIRE:
239 case CAPTURE_IEC61883:
253 if( !input_base ) return 1;
254 result = input_base->open_input();
255 if(!result) capturing = 1;
256 in_config_updated = 0;
260 VDeviceBase* VideoDevice::new_device_base()
262 switch(in_config->driver) {
263 #ifdef HAVE_VIDEO4LINUX
265 return input_base = new VDeviceV4L(this);
268 #ifdef HAVE_VIDEO4LINUX2
270 case CAPTURE_JPEG_WEBCAM:
271 case CAPTURE_YUYV_WEBCAM:
272 return input_base = new VDeviceV4L2(this);
273 case VIDEO4LINUX2JPEG:
274 return input_base = new VDeviceV4L2JPEG(this);
275 case VIDEO4LINUX2MPEG:
276 return input_base = new VDeviceV4L2MPEG(this);
280 return input_base = new VDeviceX11(this, 0);
282 #ifdef HAVE_VIDEO4LINUX
284 return input_base = new VDeviceBUZ(this);
286 return input_base = new VDeviceLML(this);
290 case CAPTURE_FIREWIRE:
291 case CAPTURE_IEC61883:
292 return input_base = new VDevice1394(this);
297 return input_base = new VDeviceDVB(this);
303 static char* get_channeldb_path(VideoInConfig *vconfig_in)
306 switch(vconfig_in->driver)
309 path = (char*)"channels_v4l";
312 case CAPTURE_JPEG_WEBCAM:
313 case CAPTURE_YUYV_WEBCAM:
314 path = (char*)"channels_v4l2";
316 case VIDEO4LINUX2JPEG:
317 path = (char*)"channels_v4l2jpeg";
319 case VIDEO4LINUX2MPEG:
320 path = (char*)"channels_v4l2mpeg";
323 path = (char*)"channels_buz";
326 path = (char*)"channels_dvb";
332 void VideoDevice::load_channeldb(ChannelDB *channeldb, VideoInConfig *vconfig_in)
334 channeldb->load(get_channeldb_path(vconfig_in));
337 void VideoDevice::save_channeldb(ChannelDB *channeldb, VideoInConfig *vconfig_in)
339 channeldb->save(get_channeldb_path(vconfig_in));
343 VDeviceBase* VideoDevice::get_input_base()
348 VDeviceBase* VideoDevice::get_output_base()
353 DeviceMPEGInput *VideoDevice::mpeg_device()
355 return !input_base ? 0 : input_base->mpeg_device();
358 int VideoDevice::is_compressed(int driver, int use_file, int use_fixed)
360 // FileMOV needs to have write_frames called so the start codes get scanned.
361 return ((driver == CAPTURE_BUZ && use_fixed) ||
362 (driver == VIDEO4LINUX2JPEG && use_fixed) ||
363 (driver == VIDEO4LINUX2MPEG && use_fixed) ||
364 (driver == CAPTURE_JPEG_WEBCAM && use_fixed) ||
365 driver == CAPTURE_LML ||
366 driver == CAPTURE_FIREWIRE ||
367 driver == CAPTURE_IEC61883);
370 int VideoDevice::is_compressed(int use_file, int use_fixed)
372 return is_compressed(in_config->driver, use_file, use_fixed);
376 void VideoDevice::fix_asset(Asset *asset, int driver)
378 // Fix asset using legacy routine
381 case CAPTURE_JPEG_WEBCAM:
382 if(asset->format != FILE_AVI &&
383 asset->format != FILE_MOV)
384 asset->format = FILE_MOV;
385 strcpy(asset->vcodec, QUICKTIME_JPEG);
390 case VIDEO4LINUX2JPEG:
391 if(asset->format != FILE_AVI &&
392 asset->format != FILE_MOV)
393 asset->format = FILE_MOV;
394 if( strncmp(asset->vcodec,QUICKTIME_MJPG,4) != 0 )
395 strncpy(asset->vcodec,QUICKTIME_MJPA,4);
398 case CAPTURE_FIREWIRE:
399 case CAPTURE_IEC61883:
400 if(asset->format != FILE_AVI &&
401 asset->format != FILE_MOV)
402 asset->format = FILE_MOV;
403 strcpy(asset->vcodec, QUICKTIME_DVSD);
407 // Fix asset using inherited routine
410 if(input_base) input_base->fix_asset(asset);
416 const char* VideoDevice::drivertostr(int driver)
419 case PLAYBACK_X11: return PLAYBACK_X11_TITLE;
420 case PLAYBACK_X11_XV: return PLAYBACK_X11_XV_TITLE;
421 case PLAYBACK_X11_GL: return PLAYBACK_X11_GL_TITLE;
422 case PLAYBACK_BUZ: return PLAYBACK_BUZ_TITLE;
423 case VIDEO4LINUX: return VIDEO4LINUX_TITLE;
424 case VIDEO4LINUX2: return VIDEO4LINUX2_TITLE;
425 case VIDEO4LINUX2JPEG: return VIDEO4LINUX2JPEG_TITLE;
426 case VIDEO4LINUX2MPEG: return VIDEO4LINUX2MPEG_TITLE;
427 case CAPTURE_JPEG_WEBCAM: return CAPTURE_JPEG_WEBCAM_TITLE;
428 case CAPTURE_YUYV_WEBCAM: return CAPTURE_YUYV_WEBCAM_TITLE;
429 case SCREENCAPTURE: return SCREENCAPTURE_TITLE;
430 case CAPTURE_BUZ: return CAPTURE_BUZ_TITLE;
431 case CAPTURE_LML: return CAPTURE_LML_TITLE;
432 case CAPTURE_DVB: return CAPTURE_DVB_TITLE;
433 case CAPTURE_FIREWIRE: return CAPTURE_FIREWIRE_TITLE;
434 case CAPTURE_IEC61883: return CAPTURE_IEC61883_TITLE;
439 int VideoDevice::get_best_colormodel(Asset *asset)
441 return input_base ? input_base->get_best_colormodel(asset) : BC_RGB888;
444 int VideoDevice::drop_frames(int frames)
446 return input_base ? input_base->drop_frames(frames) : 1;
449 double VideoDevice::device_timestamp()
451 return input_base ? input_base->device_timestamp() : -1.;
454 double VideoDevice::get_timestamp()
459 int VideoDevice::close_all()
463 output_base->close_all();
472 input_base->close_all();
482 input_sources.remove_all_objects();
488 int VideoDevice::set_adevice(AudioDevice *adev)
495 ArrayList<Channel*>* VideoDevice::get_inputs()
497 return &input_sources;
500 Channel* VideoDevice::new_input_source(char *device_name)
502 for( int i=0; i<input_sources.total; ++i ) {
503 if(!strcmp(input_sources.values[i]->device_name, device_name))
504 return input_sources.values[i];
506 Channel *item = new Channel;
507 strcpy(item->device_name, device_name);
508 input_sources.append(item);
512 int VideoDevice::get_failed()
514 return keepalive ? keepalive->get_failed() : 0;
517 int VideoDevice::interrupt_crash()
519 return input_base ? input_base->interrupt_crash() : 0;
522 int VideoDevice::set_translation(int in_x, int in_y)
529 int VideoDevice::set_field_order(int odd_field_first)
531 this->odd_field_first = odd_field_first;
535 int VideoDevice::set_channel(Channel *channel)
539 channel_lock->lock("VideoDevice::set_channel");
540 this->channel->copy_settings(channel);
542 channel_lock->unlock();
543 result = input_base ? input_base->set_channel(channel) :
544 output_base ? output_base->set_channel(channel) :
550 int VideoDevice::set_captioning(int mode)
553 input_base->set_captioning(mode);
557 void VideoDevice::set_quality(int quality)
559 this->quality = quality;
562 void VideoDevice::set_cpus(int cpus)
567 int VideoDevice::set_picture(PictureConfig *picture)
570 picture_lock->lock("VideoDevice::set_picture");
571 this->picture->copy_settings(picture);
573 picture_lock->unlock();
575 if(input_base) return input_base->set_picture(picture);
580 int VideoDevice::update_translation()
582 float frame_in_capture_x1f, frame_in_capture_x2f, frame_in_capture_y1f, frame_in_capture_y2f;
583 float capture_in_frame_x1f, capture_in_frame_x2f, capture_in_frame_y1f, capture_in_frame_y2f;
587 input_x = new_input_x;
588 input_y = new_input_y;
589 if( in_config->driver == VIDEO4LINUX ||
590 in_config->driver == VIDEO4LINUX2 ) {
591 if(input_z != new_input_z) {
592 input_z = new_input_z;
595 capture_w = (int)((float)in_config->w * input_z + 0.5);
596 capture_h = (int)((float)in_config->h * input_z + 0.5);
598 // Need to align to multiple of 4
603 frame_in_capture_x1f = (float)input_x * input_z + capture_w / 2 - in_config->w / 2;
604 frame_in_capture_x2f = (float)input_x * input_z + capture_w / 2 + in_config->w / 2;
605 frame_in_capture_y1f = (float)input_y * input_z + capture_h / 2 - in_config->h / 2;
606 frame_in_capture_y2f = (float)input_y * input_z + capture_h / 2 + in_config->h / 2;
608 capture_in_frame_x1f = 0;
609 capture_in_frame_y1f = 0;
610 capture_in_frame_x2f = in_config->w;
611 capture_in_frame_y2f = in_config->h;
613 if(frame_in_capture_x1f < 0) { capture_in_frame_x1f -= frame_in_capture_x1f; frame_in_capture_x1f = 0; }
614 if(frame_in_capture_y1f < 0) { capture_in_frame_y1f -= frame_in_capture_y1f; frame_in_capture_y1f = 0; }
615 if(frame_in_capture_x2f > capture_w) { capture_in_frame_x2f -= frame_in_capture_x2f - capture_w; frame_in_capture_x2f = capture_w; }
616 if(frame_in_capture_y2f > capture_h) { capture_in_frame_y2f -= frame_in_capture_y2f - capture_h; frame_in_capture_y2f = capture_h; }
618 frame_in_capture_x1 = (int)frame_in_capture_x1f;
619 frame_in_capture_y1 = (int)frame_in_capture_y1f;
620 frame_in_capture_x2 = (int)frame_in_capture_x2f;
621 frame_in_capture_y2 = (int)frame_in_capture_y2f;
623 capture_in_frame_x1 = (int)capture_in_frame_x1f;
624 capture_in_frame_y1 = (int)capture_in_frame_y1f;
625 capture_in_frame_x2 = (int)capture_in_frame_x2f;
626 capture_in_frame_y2 = (int)capture_in_frame_y2f;
634 int VideoDevice::set_latency_counter(int value)
636 latency_counter = value;
640 int VideoDevice::has_signal()
642 return input_base ? input_base->has_signal() : 0;
645 int VideoDevice::create_channeldb(ArrayList<Channel*> *channeldb)
647 return input_base ? input_base->create_channeldb(channeldb) : 1;
651 int VideoDevice::read_buffer(VFrame *frame)
654 if(!capturing) return 0;
656 //printf("VideoDevice::read_buffer %p %p\n", frame, input_base);
658 // Reset the keepalive thread
659 if(keepalive) keepalive->capturing = 1;
660 result = input_base->read_buffer(frame);
661 timestamp = frame->get_timestamp();
662 if( timestamp < 0 ) {
663 struct timeval tv; gettimeofday(&tv, 0);
664 timestamp = tv.tv_sec + tv.tv_usec / 1000000.0;
667 keepalive->capturing = 0;
668 keepalive->reset_keepalive();
677 // ================================= OUTPUT ==========================================
680 int VideoDevice::open_output(VideoOutConfig *config, float rate,
681 int out_w, int out_h, Canvas *output, int single_frame)
684 //printf("VideoDevice::open_output 1 %d\n", out_config->driver);
685 *this->out_config = *config;
686 //printf("VideoDevice::open_output 1 %d\n", out_config->driver);
690 this->single_frame = single_frame;
692 //printf("VideoDevice::open_output 1 %d\n", out_config->driver);
693 switch(out_config->driver) {
694 #ifdef HAVE_VIDEO4LINUX
696 output_base = new VDeviceBUZ(this);
699 output_base = new VDeviceLML(this);
703 case PLAYBACK_X11_XV:
704 case PLAYBACK_X11_GL:
705 output_base = new VDeviceX11(this, output);
708 case PLAYBACK_DV1394:
709 case PLAYBACK_FIREWIRE:
710 case PLAYBACK_IEC61883:
711 output_base = new VDevice1394(this);
714 //printf("VideoDevice::open_output 2 %d\n", out_config->driver);
716 if(output_base->open_output()) {
720 //printf("VideoDevice::open_output 3 %d\n", out_config->driver);
721 return output_base ? 0 : 1;
726 int VideoDevice::start_playback()
728 // arm buffer before doing this
731 return output_base ? output_base->start_playback() : 1;
734 int VideoDevice::stop_playback()
736 if( output_base ) output_base->stop_playback();
742 void VideoDevice::goose_input()
744 if(input_base) input_base->goose_input();
747 void VideoDevice::new_output_buffer(VFrame **output, int colormodel)
749 if(!output_base) return;
750 output_base->new_output_buffer(output, colormodel);
754 int VideoDevice::interrupt_playback()
760 int VideoDevice::write_buffer(VFrame *output, EDL *edl)
762 return output_base ? output_base->write_buffer(output, edl) : 1;
765 int VideoDevice::output_visible()
767 return output_base ? output_base->output_visible() : 0;
770 BC_Bitmap* VideoDevice::get_bitmap()
772 return output_base ? output_base->get_bitmap() : 0;
776 int VideoDevice::set_cloexec_flag(int desc, int value)
778 int oldflags = fcntl(desc, F_GETFD, 0);
779 if( oldflags < 0 ) return oldflags;
781 oldflags |= FD_CLOEXEC;
783 oldflags &= ~FD_CLOEXEC;
784 return fcntl(desc, F_SETFD, oldflags);
788 void VideoDevice::auto_update(double rate, int width, int height)
790 if( !in_config || !in_config->follow_video ) return;
794 in_config_updated = 1;
797 int VideoDevice::config_updated()
799 if( !in_config || !in_config->follow_video ) return 0;
800 return in_config_updated;
803 void VideoDevice::config_update()
805 in_config_updated = 0;
806 VideoInConfig *vconfig_in = mwindow->edl->session->vconfig_in;
807 vconfig_in->w = capture_w;
808 vconfig_in->h = capture_h;
809 vconfig_in->in_framerate = frame_rate;
813 int VideoDevice::start_toc(const char *path, const char *toc_path)
815 return input_base ? input_base->start_toc(path, toc_path) : -1;
818 int VideoDevice::start_record(int fd, int bsz)
820 return input_base ? input_base->start_record(fd, bsz) : -1;
823 int VideoDevice::stop_record()
825 return input_base ? input_base->stop_record() : -1;
829 int VideoDevice::total_video_streams()
831 return input_base ? input_base->total_video_streams() : 0;
836 int VideoDevice::get_video_pid(int track)
838 return !input_base ? -1 : input_base->get_video_pid(track);
842 int VideoDevice::get_video_info(int track, int &pid,
843 double &framerate, int &width, int &height, char *title)
845 return !input_base ? 1 : input_base->
846 get_video_info(track, pid, framerate, width, height, title);
849 int VideoDevice::get_thumbnail(int stream, int64_t &position,
850 unsigned char *&thumbnail, int &ww, int &hh)
852 return !input_base ? 1 :
853 input_base->get_thumbnail(stream, position, thumbnail, ww, hh);
856 int VideoDevice::set_skimming(int track, int skim, skim_fn fn, void *vp)
858 return !input_base ? 1 :
859 input_base->set_skimming(track, skim, fn, vp);