Main Page | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Class Members | File Members

videodevice.C

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

Generated on Sun Jan 8 13:39:02 2006 for Cinelerra-svn by  doxygen 1.4.4