r854: Merge 2.1:
[cinelerra_cv/ct.git] / cinelerra / videodevice.C
bloba1026f869a5390cbc67e76472cfe4632a6bae98c
1 #include "asset.h"
2 #include "assets.h"
3 #include "bccapture.h"
4 #include "bcsignals.h"
5 #include "channel.h"
6 #include "chantables.h"
7 #include "file.inc"
8 #include "mutex.h"
9 #include "picture.h"
10 #include "playbackconfig.h"
11 #include "playbackengine.h"
12 #include "preferences.h"
13 #include "quicktime.h"
14 #include "recordconfig.h"
15 #include "recordmonitor.h"
16 #ifdef HAVE_FIREWIRE
17 #include "vdevice1394.h"
18 #endif
19 #include "vdevicebuz.h"
20 #include "vdevicev4l.h"
21 #include "vdevicev4l2.h"
22 #include "vdevicev4l2jpeg.h"
23 #include "vdevicex11.h"
24 #include "videoconfig.h"
25 #include "videodevice.h"
26 #include "videowindow.h"
27 #include "videowindowgui.h"
28 #include "vframe.h"
30 #include <unistd.h>
31 #include <fcntl.h>
33 KeepaliveThread::KeepaliveThread(VideoDevice *device)
34  : Thread()
36         still_alive = 1;
37         failed = 0;
38         interrupted = 0;
39         set_synchronous(1);
40         this->device = device;
41         capturing = 0;
42         startup_lock = new Mutex("KeepaliveThread::startup_lock");
45 KeepaliveThread::~KeepaliveThread()
47         delete startup_lock;
50 int KeepaliveThread::start_keepalive()
52         startup_lock->lock("KeepaliveThread::start_keepalive 1");
53         start();
54         startup_lock->lock("KeepaliveThread::start_keepalive 2");
55         startup_lock->unlock();
58 void KeepaliveThread::run()
60         startup_lock->unlock();
61         while(!interrupted)
62         {
63                 still_alive = 0;
64 // Give the capture a moment
65 // Should fix the delay in case users want slower frame rates.
66                 timer.delay((long)(KEEPALIVE_DELAY * 1000));
68 // See if a capture happened
69                 if(still_alive == 0 && capturing)
70                 {
71 //                      printf("KeepaliveThread::run: device crashed\n");
72                         failed++;
73                 }
74                 else
75                         failed = 0;
76         }
79 int KeepaliveThread::reset_keepalive()
81         still_alive = 1;
84 int KeepaliveThread::get_failed()
86         if(failed) return 1; else return 0;
89 int KeepaliveThread::stop()
91         interrupted = 1;
93 // Force an immediate exit even if capture_frame worked.
94         Thread::end();
95         Thread::join();
104 VideoDevice::VideoDevice(MWindow *mwindow)
106         this->mwindow = mwindow;
107         in_config = new VideoInConfig;
108         out_config = new VideoOutConfig;
109         channel = new Channel;
110         picture = new PictureConfig(mwindow ? mwindow->defaults : 0);
111         sharing_lock = new Mutex("VideoDevice::sharing_lock");
112         channel_lock = new Mutex("VideoDevice::channel_lock");
113         picture_lock = new Mutex("VideoDevice::picture_lock");
114         initialize();
118 VideoDevice::~VideoDevice()
120         input_sources.remove_all_objects();
121         delete in_config;
122         delete out_config;
123         delete channel;
124         delete picture;
125         delete sharing_lock;
126         delete channel_lock;
127         delete picture_lock;
130 int VideoDevice::initialize()
132         sharing = 0;
133         done_sharing = 0;
134         sharing_lock->reset();
135         orate = irate = 0;
136         out_w = out_h = 0;
137         r = w = 0;
138         is_playing_back = is_recording = 0;
139         input_x = 0;
140         input_y = 0;
141         input_z = 1;
142         frame_resized = 0;
143         capturing = 0;
144         keepalive = 0;
145         swap_bytes = 0;
146         input_base = 0;
147         output_base = 0;
148         output_format = 0;
149         interrupt = 0;
150         adevice = 0;
151         quality = 80;
152         cpus = 1;
153         single_frame = 0;
154         channel_changed = 0;
155         picture_changed = 0;
158 int VideoDevice::open_input(VideoInConfig *config, 
159         int input_x, 
160         int input_y, 
161         float input_z,
162         double frame_rate)
164         int result = 0;
166         *this->in_config = *config;
168         r = 1;
169         this->input_z = -1;   // Force initialization.
170         this->frame_rate = frame_rate;
173         switch(in_config->driver)
174         {
175                 case VIDEO4LINUX:
176                         keepalive = new KeepaliveThread(this);
177                         keepalive->start_keepalive();
178                         new_device_base();
179                         result = input_base->open_input();
180                         break;
183 #ifdef HAVE_VIDEO4LINUX2
184                 case VIDEO4LINUX2:
185                         new_device_base();
186                         result = input_base->open_input();
187                         break;
188                 case VIDEO4LINUX2JPEG:
189                         new_device_base();
190                         result = input_base->open_input();
191                         break;
192 #endif
194                 case SCREENCAPTURE:
195                         this->input_x = input_x;
196                         this->input_y = input_y;
197                         new_device_base();
198                         result = input_base->open_input();
199                         break;
200                 case CAPTURE_BUZ:
201 //printf("VideoDevice 1\n");
202                         keepalive = new KeepaliveThread(this);
203                         keepalive->start_keepalive();
204                         new_device_base();
205                         result = input_base->open_input();
206                         break;
207 #ifdef HAVE_FIREWIRE
208                 case CAPTURE_FIREWIRE:
209                 case CAPTURE_IEC61883:
210                         new_device_base();
211                         result = input_base->open_input();
212                         break;
213 #endif
214         }
215         
216         if(!result) capturing = 1;
217         return 0;
220 VDeviceBase* VideoDevice::new_device_base()
222         switch(in_config->driver)
223         {
224                 case VIDEO4LINUX:
225                         return input_base = new VDeviceV4L(this);
227 #ifdef HAVE_VIDEO4LINUX2
228                 case VIDEO4LINUX2:
229                         return input_base = new VDeviceV4L2(this);
231                 case VIDEO4LINUX2JPEG:
232                         return input_base = new VDeviceV4L2JPEG(this);
233 #endif
235                 case SCREENCAPTURE:
236                         return input_base = new VDeviceX11(this, 0);
238                 case CAPTURE_BUZ:
239                         return input_base = new VDeviceBUZ(this);
241 #ifdef HAVE_FIREWIRE
242                 case CAPTURE_FIREWIRE:
243                 case CAPTURE_IEC61883:
244                         return input_base = new VDevice1394(this);
245 #endif
246         }
247         return 0;
251 VDeviceBase* VideoDevice::get_output_base()
253         return output_base;
256 int VideoDevice::is_compressed(int driver, int use_file, int use_fixed)
258 // FileMOV needs to have write_frames called so the start codes get scanned.
259         return ((driver == CAPTURE_BUZ && use_fixed) ||
260                 (driver == VIDEO4LINUX2JPEG && use_fixed) || 
261                 driver == CAPTURE_LML || 
262                 driver == CAPTURE_FIREWIRE ||
263                 driver == CAPTURE_IEC61883);
266 int VideoDevice::is_compressed(int use_file, int use_fixed)
268         return is_compressed(in_config->driver, use_file, use_fixed);
272 void VideoDevice::fix_asset(Asset *asset, int driver)
274 // Fix asset using legacy routine
275         switch(driver)
276         {
277                 case CAPTURE_BUZ:
278                 case CAPTURE_LML:
279                 case VIDEO4LINUX2JPEG:
280                         if(asset->format != FILE_AVI &&
281                                 asset->format != FILE_MOV)
282                                 asset->format = FILE_MOV;
283                         strcpy(asset->vcodec, QUICKTIME_MJPA);
284                         return;
285                 
286                 case CAPTURE_FIREWIRE:
287                 case CAPTURE_IEC61883:
288                         if(asset->format != FILE_AVI &&
289                                 asset->format != FILE_MOV)
290                                 asset->format = FILE_MOV;
291                         strcpy(asset->vcodec, QUICKTIME_DVSD);
292                         return;
293         }
295 // Fix asset using inherited routine
296         new_device_base();
298         if(input_base) input_base->fix_asset(asset);
299         delete input_base;
300         input_base = 0;
304 char* VideoDevice::drivertostr(int driver)
306         switch(driver)
307         {
308                 case PLAYBACK_X11:
309                         return PLAYBACK_X11_TITLE;
310                         break;
311                 case PLAYBACK_X11_XV:
312                         return PLAYBACK_X11_XV_TITLE;
313                         break;
314                 case PLAYBACK_X11_GL:
315                         return PLAYBACK_X11_GL_TITLE;
316                         break;
317                 case PLAYBACK_BUZ:
318                         return PLAYBACK_BUZ_TITLE;
319                         break;
320                 case VIDEO4LINUX:
321                         return VIDEO4LINUX_TITLE;
322                         break;
323                 case VIDEO4LINUX2:
324                         return VIDEO4LINUX2_TITLE;
325                         break;
326                 case VIDEO4LINUX2JPEG:
327                         return VIDEO4LINUX2JPEG_TITLE;
328                         break;
329                 case SCREENCAPTURE:
330                         return SCREENCAPTURE_TITLE;
331                         break;
332                 case CAPTURE_BUZ:
333                         return CAPTURE_BUZ_TITLE;
334                         break;
335 #ifdef HAVE_FIREWIRE
336                 case CAPTURE_FIREWIRE:
337                         return CAPTURE_FIREWIRE_TITLE;
338                         break;
339                 case CAPTURE_IEC61883:
340                         return CAPTURE_IEC61883_TITLE;
341                         break;
342 #endif
343         }
344         return "";
347 int VideoDevice::get_best_colormodel(Asset *asset)
349         if(input_base)
350                 return input_base->get_best_colormodel(asset);
351         else
352                 return BC_RGB888;
355 int VideoDevice::close_all()
357         int i;
359         if(w)
360         {
361                 if(output_base)
362                 {
363                         output_base->close_all();
364                         delete output_base;
365                 }
366         }
368         if(r && capturing)
369         {
370                 capturing = 0;
371                 if(input_base)
372                 {
373                         input_base->close_all();
374                         delete input_base;
376                         input_base = 0;
377                 }
379                 if(keepalive)
380                 {
381                         keepalive->stop();
382                         delete keepalive;
383                 }
384         }
387         input_sources.remove_all_objects();
389         initialize();
391         return 0;
395 int VideoDevice::set_adevice(AudioDevice *adevice)
397         this->adevice = adevice;
398         return 0;
402 ArrayList<Channel*>* VideoDevice::get_inputs()
404         return &input_sources;
407 Channel* VideoDevice::new_input_source(char *device_name)
409         for(int i = 0; i < input_sources.total; i++)
410         {
411                 if(!strcmp(input_sources.values[i]->device_name, device_name))
412                         return input_sources.values[i];
413         }
414         Channel *item = new Channel;
415         strcpy(item->device_name, device_name);
416         input_sources.append(item);
417         return item;
420 int VideoDevice::get_failed()
422         if(keepalive)
423                 return keepalive->get_failed();
424         else
425                 return 0;
428 int VideoDevice::interrupt_crash()
430         if(input_base) return input_base->interrupt_crash();
431         return 0;
434 int VideoDevice::set_translation(int input_x, int input_y)
436         this->input_x = input_x;
437         this->input_y = input_y;
438         return 0;
441 int VideoDevice::set_field_order(int odd_field_first)
443         this->odd_field_first = odd_field_first;
444         return 0;
447 int VideoDevice::set_channel(Channel *channel)
449         if(channel)
450         {
451                 channel_lock->lock("VideoDevice::set_channel");
452                 this->channel->copy_settings(channel);
453                 channel_changed = 1;
454                 channel_lock->unlock();
456                 if(input_base) return input_base->set_channel(channel);
457                 if(output_base) return output_base->set_channel(channel);
458         }
461 void VideoDevice::set_quality(int quality)
463         this->quality = quality;
466 void VideoDevice::set_cpus(int cpus)
468         this->cpus = cpus;
471 int VideoDevice::set_picture(PictureConfig *picture)
473         if(picture)
474         {
475                 picture_lock->lock("VideoDevice::set_picture");
476                 this->picture->copy_settings(picture);
477                 picture_changed = 1;
478                 picture_lock->unlock();
480                 if(input_base) return input_base->set_picture(picture);
481         }
484 int VideoDevice::update_translation()
486         float frame_in_capture_x1f, frame_in_capture_x2f, frame_in_capture_y1f, frame_in_capture_y2f;
487         float capture_in_frame_x1f, capture_in_frame_x2f, capture_in_frame_y1f, capture_in_frame_y2f;
488         int z_changed = 0;
490         if(frame_resized)
491         {
492                 input_x = new_input_x;
493                 input_y = new_input_y;
495                 if(in_config->driver == VIDEO4LINUX || in_config->driver == VIDEO4LINUX2)
496                 {
497                         if(input_z != new_input_z)
498                         {
499                                 input_z = new_input_z;
500                                 z_changed = 1;
502                                 capture_w = (int)((float)in_config->w * input_z + 0.5);
503                                 capture_h = (int)((float)in_config->h * input_z + 0.5);
505 // Need to align to multiple of 4
506                                 capture_w &= ~3;
507                                 capture_h &= ~3;
508                         }
510                         frame_in_capture_x1f = (float)input_x * input_z + capture_w / 2 - in_config->w / 2;
511                         frame_in_capture_x2f = (float)input_x * input_z  + capture_w / 2 + in_config->w / 2;
512                         frame_in_capture_y1f = (float)input_y * input_z  + capture_h / 2 - in_config->h / 2;
513                         frame_in_capture_y2f = (float)input_y * input_z  + capture_h / 2 + in_config->h / 2;
515                         capture_in_frame_x1f = 0;
516                         capture_in_frame_y1f = 0;
517                         capture_in_frame_x2f = in_config->w;
518                         capture_in_frame_y2f = in_config->h;
520                         if(frame_in_capture_x1f < 0) { capture_in_frame_x1f -= frame_in_capture_x1f; frame_in_capture_x1f = 0; }
521                         if(frame_in_capture_y1f < 0) { capture_in_frame_y1f -= frame_in_capture_y1f; frame_in_capture_y1f = 0; }
522                         if(frame_in_capture_x2f > capture_w) { capture_in_frame_x2f -= frame_in_capture_x2f - capture_w; frame_in_capture_x2f = capture_w; }
523                         if(frame_in_capture_y2f > capture_h) { capture_in_frame_y2f -= frame_in_capture_y2f - capture_h; frame_in_capture_y2f = capture_h; }
525                         frame_in_capture_x1 = (int)frame_in_capture_x1f;
526                         frame_in_capture_y1 = (int)frame_in_capture_y1f;
527                         frame_in_capture_x2 = (int)frame_in_capture_x2f;
528                         frame_in_capture_y2 = (int)frame_in_capture_y2f;
530                         capture_in_frame_x1 = (int)capture_in_frame_x1f;
531                         capture_in_frame_y1 = (int)capture_in_frame_y1f;
532                         capture_in_frame_x2 = (int)capture_in_frame_x2f;
533                         capture_in_frame_y2 = (int)capture_in_frame_y2f;
535                         frame_resized = 0;
536                 }
537         }
538         return 0;
541 int VideoDevice::set_latency_counter(int value)
543         latency_counter = value;
544         return 0;
547 int VideoDevice::has_signal()
549         if(input_base) return input_base->has_signal();
550         return 0;
554 int VideoDevice::read_buffer(VFrame *frame)
556         int result = 0;
557         if(!capturing) return 0;
559 //printf("VideoDevice::read_buffer %p %p\n", frame, input_base);
560         if(input_base)
561         {
562 // Reset the keepalive thread
563                 if(keepalive) keepalive->capturing = 1;
564                 result = input_base->read_buffer(frame);
565                 if(keepalive)
566                 {
567                         keepalive->capturing = 0;
568                         keepalive->reset_keepalive();
569                 }
570                 return result;
571         }
573         return 0;
577 // ================================= OUTPUT ==========================================
580 int VideoDevice::open_output(VideoOutConfig *config, 
581                                         float rate, 
582                                         int out_w, 
583                                         int out_h,
584                                         Canvas *output,
585                                         int single_frame)
587         w = 1;
588 //printf("VideoDevice::open_output 1 %d\n", out_config->driver);
589         *this->out_config = *config;
590 //printf("VideoDevice::open_output 1 %d\n", out_config->driver);
591         this->out_w = out_w;
592         this->out_h = out_h;
593         this->orate = rate;
594         this->single_frame = single_frame;
596 //printf("VideoDevice::open_output 1 %d\n", out_config->driver);
597         switch(out_config->driver)
598         {
599                 case PLAYBACK_BUZ:
600                         output_base = new VDeviceBUZ(this);
601                         break;
602                 case PLAYBACK_X11:
603                 case PLAYBACK_X11_XV:
604                 case PLAYBACK_X11_GL:
605                         output_base = new VDeviceX11(this, output);
606                         break;
608 #ifdef HAVE_FIREWIRE
609                 case PLAYBACK_DV1394:
610                 case PLAYBACK_FIREWIRE:
611                 case PLAYBACK_IEC61883:
612                         output_base = new VDevice1394(this);
613                         break;
614 #endif
615         }
616 //printf("VideoDevice::open_output 2 %d\n", out_config->driver);
618         if(output_base->open_output())
619         {
620                 delete output_base;
621                 output_base = 0;
622         }
623 //printf("VideoDevice::open_output 3 %d\n", out_config->driver);
625         if(output_base) 
626                 return 0;
627         else
628                 return 1;
633 int VideoDevice::start_playback()
635 // arm buffer before doing this
636         is_playing_back = 1;
637         interrupt = 0;
639         if(output_base) return output_base->start_playback();
640         return 1;
643 int VideoDevice::stop_playback()
645         if(output_base) output_base->stop_playback();
646         is_playing_back = 0;
647         interrupt = 0;
648         return 0;
651 void VideoDevice::goose_input()
653         if(input_base) input_base->goose_input();
656 void VideoDevice::new_output_buffer(VFrame **output, int colormodel)
658         if(!output_base) return;
659         output_base->new_output_buffer(output, colormodel);
663 int VideoDevice::interrupt_playback()
665         interrupt = 1;
666         return 0;
669 int VideoDevice::write_buffer(VFrame *output, EDL *edl)
671 //printf("VideoDevice::write_buffer 1 %p\n", output_base);
672         if(output_base) return output_base->write_buffer(output, edl);
673         return 1;
676 int VideoDevice::output_visible()
678         if(output_base) return output_base->output_visible();
681 BC_Bitmap* VideoDevice::get_bitmap()
683         if(output_base) return output_base->get_bitmap();
687 int VideoDevice::set_cloexec_flag(int desc, int value)
689         int oldflags = fcntl(desc, F_GETFD, 0);
690         if(oldflags < 0) return oldflags;
691         if(value != 0) 
692                 oldflags |= FD_CLOEXEC;
693         else
694                 oldflags &= ~FD_CLOEXEC;
695         return fcntl(desc, F_SETFD, oldflags);