00001 #include "asset.h"
00002 #include "assets.h"
00003 #include "bccapture.h"
00004 #include "bcsignals.h"
00005 #include "channel.h"
00006 #include "channeldb.h"
00007 #include "chantables.h"
00008 #include "file.inc"
00009 #include "mutex.h"
00010 #include "mwindow.h"
00011 #include "picture.h"
00012 #include "playbackconfig.h"
00013 #include "playbackengine.h"
00014 #include "preferences.h"
00015 #include "quicktime.h"
00016 #include "recordconfig.h"
00017 #include "recordmonitor.h"
00018 #ifdef HAVE_FIREWIRE
00019 #include "vdevice1394.h"
00020 #endif
00021 #include "vdevicebuz.h"
00022 #include "vdevicedvb.h"
00023 #include "vdevicev4l.h"
00024 #include "vdevicev4l2.h"
00025 #include "vdevicev4l2jpeg.h"
00026 #include "vdevicex11.h"
00027 #include "videoconfig.h"
00028 #include "videodevice.h"
00029 #include "videowindow.h"
00030 #include "videowindowgui.h"
00031 #include "vframe.h"
00032
00033 #include <unistd.h>
00034 #include <fcntl.h>
00035
00036 KeepaliveThread::KeepaliveThread(VideoDevice *device)
00037 : Thread()
00038 {
00039 still_alive = 1;
00040 failed = 0;
00041 interrupted = 0;
00042 set_synchronous(1);
00043 this->device = device;
00044 capturing = 0;
00045 startup_lock = new Mutex("KeepaliveThread::startup_lock");
00046 }
00047
00048 KeepaliveThread::~KeepaliveThread()
00049 {
00050 delete startup_lock;
00051 }
00052
00053 int KeepaliveThread::start_keepalive()
00054 {
00055 startup_lock->lock("KeepaliveThread::start_keepalive 1");
00056 start();
00057 startup_lock->lock("KeepaliveThread::start_keepalive 2");
00058 startup_lock->unlock();
00059 }
00060
00061 void KeepaliveThread::run()
00062 {
00063 startup_lock->unlock();
00064 while(!interrupted)
00065 {
00066 still_alive = 0;
00067
00068
00069 timer.delay((long)(KEEPALIVE_DELAY * 1000));
00070
00071
00072 if(still_alive == 0 && capturing)
00073 {
00074
00075 failed++;
00076 }
00077 else
00078 failed = 0;
00079 }
00080 }
00081
00082 int KeepaliveThread::reset_keepalive()
00083 {
00084 still_alive = 1;
00085 }
00086
00087 int KeepaliveThread::get_failed()
00088 {
00089 if(failed) return 1; else return 0;
00090 }
00091
00092 int KeepaliveThread::stop()
00093 {
00094 interrupted = 1;
00095
00096
00097 Thread::end();
00098 Thread::join();
00099 }
00100
00101
00102
00103
00104
00105
00106
00107 VideoDevice::VideoDevice(MWindow *mwindow)
00108 {
00109 this->mwindow = mwindow;
00110 in_config = new VideoInConfig;
00111 out_config = new VideoOutConfig;
00112 channel = new Channel;
00113 picture = new PictureConfig(mwindow ? mwindow->defaults : 0);
00114 sharing_lock = new Mutex("VideoDevice::sharing_lock");
00115 channel_lock = new Mutex("VideoDevice::channel_lock");
00116 picture_lock = new Mutex("VideoDevice::picture_lock");
00117 initialize();
00118 }
00119
00120
00121 VideoDevice::~VideoDevice()
00122 {
00123 input_sources.remove_all_objects();
00124 delete in_config;
00125 delete out_config;
00126 delete channel;
00127 delete picture;
00128 delete sharing_lock;
00129 delete channel_lock;
00130 delete picture_lock;
00131 }
00132
00133 int VideoDevice::initialize()
00134 {
00135 sharing = 0;
00136 done_sharing = 0;
00137 sharing_lock->reset();
00138 orate = irate = 0;
00139 out_w = out_h = 0;
00140 r = w = 0;
00141 is_playing_back = is_recording = 0;
00142 input_x = 0;
00143 input_y = 0;
00144 input_z = 1;
00145 frame_resized = 0;
00146 capturing = 0;
00147 keepalive = 0;
00148 swap_bytes = 0;
00149 input_base = 0;
00150 output_base = 0;
00151 output_format = 0;
00152 interrupt = 0;
00153 adevice = 0;
00154 quality = 80;
00155 cpus = 1;
00156 single_frame = 0;
00157 channel_changed = 0;
00158 picture_changed = 0;
00159 }
00160
00161 int VideoDevice::open_input(VideoInConfig *config,
00162 int input_x,
00163 int input_y,
00164 float input_z,
00165 double frame_rate)
00166 {
00167 int result = 0;
00168
00169 *this->in_config = *config;
00170
00171 r = 1;
00172 this->input_z = -1;
00173 this->frame_rate = frame_rate;
00174
00175
00176 switch(in_config->driver)
00177 {
00178 case VIDEO4LINUX:
00179 keepalive = new KeepaliveThread(this);
00180 keepalive->start_keepalive();
00181 new_device_base();
00182 result = input_base->open_input();
00183 break;
00184
00185
00186 #ifdef HAVE_VIDEO4LINUX2
00187 case VIDEO4LINUX2:
00188 new_device_base();
00189 result = input_base->open_input();
00190 break;
00191 case VIDEO4LINUX2JPEG:
00192 new_device_base();
00193 result = input_base->open_input();
00194 break;
00195 #endif
00196
00197 case SCREENCAPTURE:
00198 this->input_x = input_x;
00199 this->input_y = input_y;
00200 new_device_base();
00201 result = input_base->open_input();
00202 break;
00203 case CAPTURE_BUZ:
00204
00205 keepalive = new KeepaliveThread(this);
00206 keepalive->start_keepalive();
00207 new_device_base();
00208 result = input_base->open_input();
00209 break;
00210 #ifdef HAVE_FIREWIRE
00211 case CAPTURE_FIREWIRE:
00212 case CAPTURE_IEC61883:
00213 new_device_base();
00214 result = input_base->open_input();
00215 break;
00216 #endif
00217
00218 case CAPTURE_DVB:
00219 new_device_base();
00220 result = input_base->open_input();
00221 break;
00222 }
00223
00224 if(!result) capturing = 1;
00225 return 0;
00226 }
00227
00228 VDeviceBase* VideoDevice::new_device_base()
00229 {
00230 switch(in_config->driver)
00231 {
00232 case VIDEO4LINUX:
00233 return input_base = new VDeviceV4L(this);
00234
00235 #ifdef HAVE_VIDEO4LINUX2
00236 case VIDEO4LINUX2:
00237 return input_base = new VDeviceV4L2(this);
00238
00239 case VIDEO4LINUX2JPEG:
00240 return input_base = new VDeviceV4L2JPEG(this);
00241 #endif
00242
00243 case SCREENCAPTURE:
00244 return input_base = new VDeviceX11(this, 0);
00245
00246 case CAPTURE_BUZ:
00247 return input_base = new VDeviceBUZ(this);
00248
00249 #ifdef HAVE_FIREWIRE
00250 case CAPTURE_FIREWIRE:
00251 case CAPTURE_IEC61883:
00252 return input_base = new VDevice1394(this);
00253 #endif
00254
00255 case CAPTURE_DVB:
00256 return input_base = new VDeviceDVB(this);
00257 }
00258 return 0;
00259 }
00260
00261 static char* get_channeldb_path(VideoInConfig *vconfig_in)
00262 {
00263 char *path = "";
00264 switch(vconfig_in->driver)
00265 {
00266 case VIDEO4LINUX:
00267 path = "channels_v4l";
00268 break;
00269 case VIDEO4LINUX2:
00270 path = "channels_v4l2";
00271 break;
00272 case VIDEO4LINUX2JPEG:
00273 path = "channels_v4l2jpeg";
00274 break;
00275 case CAPTURE_BUZ:
00276 path = "channels_buz";
00277 break;
00278 case CAPTURE_DVB:
00279 path = "channels_dvb";
00280 break;
00281 }
00282 return path;
00283 }
00284
00285 void VideoDevice::load_channeldb(ChannelDB *channeldb, VideoInConfig *vconfig_in)
00286 {
00287 channeldb->load(get_channeldb_path(vconfig_in));
00288 }
00289
00290 void VideoDevice::save_channeldb(ChannelDB *channeldb, VideoInConfig *vconfig_in)
00291 {
00292 channeldb->save(get_channeldb_path(vconfig_in));
00293 }
00294
00295
00296 VDeviceBase* VideoDevice::get_output_base()
00297 {
00298 return output_base;
00299 }
00300
00301 int VideoDevice::is_compressed(int driver, int use_file, int use_fixed)
00302 {
00303
00304 return ((driver == CAPTURE_BUZ && use_fixed) ||
00305 (driver == VIDEO4LINUX2JPEG && use_fixed) ||
00306 driver == CAPTURE_LML ||
00307 driver == CAPTURE_FIREWIRE ||
00308 driver == CAPTURE_IEC61883);
00309 }
00310
00311 int VideoDevice::is_compressed(int use_file, int use_fixed)
00312 {
00313 return is_compressed(in_config->driver, use_file, use_fixed);
00314 }
00315
00316
00317 void VideoDevice::fix_asset(Asset *asset, int driver)
00318 {
00319
00320 switch(driver)
00321 {
00322 case CAPTURE_BUZ:
00323 case CAPTURE_LML:
00324 case VIDEO4LINUX2JPEG:
00325 if(asset->format != FILE_AVI &&
00326 asset->format != FILE_MOV)
00327 asset->format = FILE_MOV;
00328 strcpy(asset->vcodec, QUICKTIME_MJPA);
00329 return;
00330
00331 case CAPTURE_FIREWIRE:
00332 case CAPTURE_IEC61883:
00333 if(asset->format != FILE_AVI &&
00334 asset->format != FILE_MOV)
00335 asset->format = FILE_MOV;
00336 strcpy(asset->vcodec, QUICKTIME_DVSD);
00337 return;
00338 }
00339
00340
00341 new_device_base();
00342
00343 if(input_base) input_base->fix_asset(asset);
00344 delete input_base;
00345 input_base = 0;
00346 }
00347
00348
00349 char* VideoDevice::drivertostr(int driver)
00350 {
00351 switch(driver)
00352 {
00353 case PLAYBACK_X11:
00354 return PLAYBACK_X11_TITLE;
00355 break;
00356 case PLAYBACK_X11_XV:
00357 return PLAYBACK_X11_XV_TITLE;
00358 break;
00359 case PLAYBACK_X11_GL:
00360 return PLAYBACK_X11_GL_TITLE;
00361 break;
00362 case PLAYBACK_BUZ:
00363 return PLAYBACK_BUZ_TITLE;
00364 break;
00365 case VIDEO4LINUX:
00366 return VIDEO4LINUX_TITLE;
00367 break;
00368 case VIDEO4LINUX2:
00369 return VIDEO4LINUX2_TITLE;
00370 break;
00371 case VIDEO4LINUX2JPEG:
00372 return VIDEO4LINUX2JPEG_TITLE;
00373 break;
00374 case SCREENCAPTURE:
00375 return SCREENCAPTURE_TITLE;
00376 break;
00377 case CAPTURE_BUZ:
00378 return CAPTURE_BUZ_TITLE;
00379 break;
00380 #ifdef HAVE_FIREWIRE
00381 case CAPTURE_FIREWIRE:
00382 return CAPTURE_FIREWIRE_TITLE;
00383 break;
00384 case CAPTURE_IEC61883:
00385 return CAPTURE_IEC61883_TITLE;
00386 break;
00387 #endif
00388 }
00389 return "";
00390 }
00391
00392 int VideoDevice::get_best_colormodel(Asset *asset)
00393 {
00394 if(input_base)
00395 return input_base->get_best_colormodel(asset);
00396 else
00397 return BC_RGB888;
00398 }
00399
00400 int VideoDevice::close_all()
00401 {
00402 int i;
00403
00404 if(w)
00405 {
00406 if(output_base)
00407 {
00408 output_base->close_all();
00409 delete output_base;
00410 }
00411 }
00412
00413 if(r && capturing)
00414 {
00415 capturing = 0;
00416 if(input_base)
00417 {
00418 input_base->close_all();
00419 delete input_base;
00420
00421 input_base = 0;
00422 }
00423
00424 if(keepalive)
00425 {
00426 keepalive->stop();
00427 delete keepalive;
00428 }
00429 }
00430
00431
00432 input_sources.remove_all_objects();
00433
00434 initialize();
00435
00436 return 0;
00437 }
00438
00439
00440 int VideoDevice::set_adevice(AudioDevice *adevice)
00441 {
00442 this->adevice = adevice;
00443 return 0;
00444 }
00445
00446
00447 ArrayList<Channel*>* VideoDevice::get_inputs()
00448 {
00449 return &input_sources;
00450 }
00451
00452 Channel* VideoDevice::new_input_source(char *device_name)
00453 {
00454 for(int i = 0; i < input_sources.total; i++)
00455 {
00456 if(!strcmp(input_sources.values[i]->device_name, device_name))
00457 return input_sources.values[i];
00458 }
00459 Channel *item = new Channel;
00460 strcpy(item->device_name, device_name);
00461 input_sources.append(item);
00462 return item;
00463 }
00464
00465 int VideoDevice::get_failed()
00466 {
00467 if(keepalive)
00468 return keepalive->get_failed();
00469 else
00470 return 0;
00471 }
00472
00473 int VideoDevice::interrupt_crash()
00474 {
00475 if(input_base) return input_base->interrupt_crash();
00476 return 0;
00477 }
00478
00479 int VideoDevice::set_translation(int input_x, int input_y)
00480 {
00481 this->input_x = input_x;
00482 this->input_y = input_y;
00483 return 0;
00484 }
00485
00486 int VideoDevice::set_field_order(int odd_field_first)
00487 {
00488 this->odd_field_first = odd_field_first;
00489 return 0;
00490 }
00491
00492 int VideoDevice::set_channel(Channel *channel)
00493 {
00494 if(channel)
00495 {
00496 channel_lock->lock("VideoDevice::set_channel");
00497 this->channel->copy_settings(channel);
00498 channel_changed = 1;
00499 channel_lock->unlock();
00500
00501 if(input_base) return input_base->set_channel(channel);
00502 if(output_base) return output_base->set_channel(channel);
00503 }
00504 }
00505
00506 void VideoDevice::set_quality(int quality)
00507 {
00508 this->quality = quality;
00509 }
00510
00511 void VideoDevice::set_cpus(int cpus)
00512 {
00513 this->cpus = cpus;
00514 }
00515
00516 int VideoDevice::set_picture(PictureConfig *picture)
00517 {
00518 if(picture)
00519 {
00520 picture_lock->lock("VideoDevice::set_picture");
00521 this->picture->copy_settings(picture);
00522 picture_changed = 1;
00523 picture_lock->unlock();
00524
00525 if(input_base) return input_base->set_picture(picture);
00526 }
00527 }
00528
00529 int VideoDevice::update_translation()
00530 {
00531 float frame_in_capture_x1f, frame_in_capture_x2f, frame_in_capture_y1f, frame_in_capture_y2f;
00532 float capture_in_frame_x1f, capture_in_frame_x2f, capture_in_frame_y1f, capture_in_frame_y2f;
00533 int z_changed = 0;
00534
00535 if(frame_resized)
00536 {
00537 input_x = new_input_x;
00538 input_y = new_input_y;
00539
00540 if(in_config->driver == VIDEO4LINUX || in_config->driver == VIDEO4LINUX2)
00541 {
00542 if(input_z != new_input_z)
00543 {
00544 input_z = new_input_z;
00545 z_changed = 1;
00546
00547 capture_w = (int)((float)in_config->w * input_z + 0.5);
00548 capture_h = (int)((float)in_config->h * input_z + 0.5);
00549
00550
00551 capture_w &= ~3;
00552 capture_h &= ~3;
00553 }
00554
00555 frame_in_capture_x1f = (float)input_x * input_z + capture_w / 2 - in_config->w / 2;
00556 frame_in_capture_x2f = (float)input_x * input_z + capture_w / 2 + in_config->w / 2;
00557 frame_in_capture_y1f = (float)input_y * input_z + capture_h / 2 - in_config->h / 2;
00558 frame_in_capture_y2f = (float)input_y * input_z + capture_h / 2 + in_config->h / 2;
00559
00560 capture_in_frame_x1f = 0;
00561 capture_in_frame_y1f = 0;
00562 capture_in_frame_x2f = in_config->w;
00563 capture_in_frame_y2f = in_config->h;
00564
00565 if(frame_in_capture_x1f < 0) { capture_in_frame_x1f -= frame_in_capture_x1f; frame_in_capture_x1f = 0; }
00566 if(frame_in_capture_y1f < 0) { capture_in_frame_y1f -= frame_in_capture_y1f; frame_in_capture_y1f = 0; }
00567 if(frame_in_capture_x2f > capture_w) { capture_in_frame_x2f -= frame_in_capture_x2f - capture_w; frame_in_capture_x2f = capture_w; }
00568 if(frame_in_capture_y2f > capture_h) { capture_in_frame_y2f -= frame_in_capture_y2f - capture_h; frame_in_capture_y2f = capture_h; }
00569
00570 frame_in_capture_x1 = (int)frame_in_capture_x1f;
00571 frame_in_capture_y1 = (int)frame_in_capture_y1f;
00572 frame_in_capture_x2 = (int)frame_in_capture_x2f;
00573 frame_in_capture_y2 = (int)frame_in_capture_y2f;
00574
00575 capture_in_frame_x1 = (int)capture_in_frame_x1f;
00576 capture_in_frame_y1 = (int)capture_in_frame_y1f;
00577 capture_in_frame_x2 = (int)capture_in_frame_x2f;
00578 capture_in_frame_y2 = (int)capture_in_frame_y2f;
00579
00580 frame_resized = 0;
00581 }
00582 }
00583 return 0;
00584 }
00585
00586 int VideoDevice::set_latency_counter(int value)
00587 {
00588 latency_counter = value;
00589 return 0;
00590 }
00591
00592 int VideoDevice::has_signal()
00593 {
00594 if(input_base) return input_base->has_signal();
00595 return 0;
00596 }
00597
00598
00599 int VideoDevice::read_buffer(VFrame *frame)
00600 {
00601 int result = 0;
00602 if(!capturing) return 0;
00603
00604
00605 if(input_base)
00606 {
00607
00608 if(keepalive) keepalive->capturing = 1;
00609 result = input_base->read_buffer(frame);
00610 if(keepalive)
00611 {
00612 keepalive->capturing = 0;
00613 keepalive->reset_keepalive();
00614 }
00615 return result;
00616 }
00617
00618 return 0;
00619 }
00620
00621
00622
00623
00624
00625 int VideoDevice::open_output(VideoOutConfig *config,
00626 float rate,
00627 int out_w,
00628 int out_h,
00629 Canvas *output,
00630 int single_frame)
00631 {
00632 w = 1;
00633
00634 *this->out_config = *config;
00635
00636 this->out_w = out_w;
00637 this->out_h = out_h;
00638 this->orate = rate;
00639 this->single_frame = single_frame;
00640
00641
00642 switch(out_config->driver)
00643 {
00644 case PLAYBACK_BUZ:
00645 output_base = new VDeviceBUZ(this);
00646 break;
00647 case PLAYBACK_X11:
00648 case PLAYBACK_X11_XV:
00649 case PLAYBACK_X11_GL:
00650 output_base = new VDeviceX11(this, output);
00651 break;
00652
00653 #ifdef HAVE_FIREWIRE
00654 case PLAYBACK_DV1394:
00655 case PLAYBACK_FIREWIRE:
00656 case PLAYBACK_IEC61883:
00657 output_base = new VDevice1394(this);
00658 break;
00659 #endif
00660 }
00661
00662
00663 if(output_base->open_output())
00664 {
00665 delete output_base;
00666 output_base = 0;
00667 }
00668
00669
00670 if(output_base)
00671 return 0;
00672 else
00673 return 1;
00674 }
00675
00676
00677
00678 int VideoDevice::start_playback()
00679 {
00680
00681 is_playing_back = 1;
00682 interrupt = 0;
00683
00684 if(output_base) return output_base->start_playback();
00685 return 1;
00686 }
00687
00688 int VideoDevice::stop_playback()
00689 {
00690 if(output_base) output_base->stop_playback();
00691 is_playing_back = 0;
00692 interrupt = 0;
00693 return 0;
00694 }
00695
00696 void VideoDevice::goose_input()
00697 {
00698 if(input_base) input_base->goose_input();
00699 }
00700
00701 void VideoDevice::new_output_buffer(VFrame **output, int colormodel)
00702 {
00703 if(!output_base) return;
00704 output_base->new_output_buffer(output, colormodel);
00705 }
00706
00707
00708 int VideoDevice::interrupt_playback()
00709 {
00710 interrupt = 1;
00711 return 0;
00712 }
00713
00714 int VideoDevice::write_buffer(VFrame *output, EDL *edl)
00715 {
00716
00717 if(output_base) return output_base->write_buffer(output, edl);
00718 return 1;
00719 }
00720
00721 int VideoDevice::output_visible()
00722 {
00723 if(output_base) return output_base->output_visible();
00724 }
00725
00726 BC_Bitmap* VideoDevice::get_bitmap()
00727 {
00728 if(output_base) return output_base->get_bitmap();
00729 }
00730
00731
00732 int VideoDevice::set_cloexec_flag(int desc, int value)
00733 {
00734 int oldflags = fcntl(desc, F_GETFD, 0);
00735 if(oldflags < 0) return oldflags;
00736 if(value != 0)
00737 oldflags |= FD_CLOEXEC;
00738 else
00739 oldflags &= ~FD_CLOEXEC;
00740 return fcntl(desc, F_SETFD, oldflags);
00741 }
00742