r851: Merge 2.1:
[cinelerra_cv/ct.git] / cinelerra / videodevice.C
blob599db7e0209d71e65deea8e7085c15e4779b62f0
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_BUZ:
315                         return PLAYBACK_BUZ_TITLE;
316                         break;
317                 case VIDEO4LINUX:
318                         return VIDEO4LINUX_TITLE;
319                         break;
320                 case VIDEO4LINUX2:
321                         return VIDEO4LINUX2_TITLE;
322                         break;
323                 case VIDEO4LINUX2JPEG:
324                         return VIDEO4LINUX2JPEG_TITLE;
325                         break;
326                 case SCREENCAPTURE:
327                         return SCREENCAPTURE_TITLE;
328                         break;
329                 case CAPTURE_BUZ:
330                         return CAPTURE_BUZ_TITLE;
331                         break;
332 #ifdef HAVE_FIREWIRE
333                 case CAPTURE_FIREWIRE:
334                         return CAPTURE_FIREWIRE_TITLE;
335                         break;
336                 case CAPTURE_IEC61883:
337                         return CAPTURE_IEC61883_TITLE;
338                         break;
339 #endif
340         }
341         return "";
344 int VideoDevice::get_best_colormodel(Asset *asset)
346         if(input_base)
347                 return input_base->get_best_colormodel(asset);
348         else
349                 return BC_RGB888;
352 int VideoDevice::close_all()
354         int i;
356         if(w)
357         {
358                 if(output_base)
359                 {
360                         output_base->close_all();
361                         delete output_base;
362                 }
363         }
365         if(r && capturing)
366         {
367                 capturing = 0;
368                 if(input_base)
369                 {
370                         input_base->close_all();
371                         delete input_base;
373                         input_base = 0;
374                 }
376                 if(keepalive)
377                 {
378                         keepalive->stop();
379                         delete keepalive;
380                 }
381         }
384         input_sources.remove_all_objects();
386         initialize();
388         return 0;
392 int VideoDevice::set_adevice(AudioDevice *adevice)
394         this->adevice = adevice;
395         return 0;
399 ArrayList<Channel*>* VideoDevice::get_inputs()
401         return &input_sources;
404 Channel* VideoDevice::new_input_source(char *device_name)
406         for(int i = 0; i < input_sources.total; i++)
407         {
408                 if(!strcmp(input_sources.values[i]->device_name, device_name))
409                         return input_sources.values[i];
410         }
411         Channel *item = new Channel;
412         strcpy(item->device_name, device_name);
413         input_sources.append(item);
414         return item;
417 int VideoDevice::get_failed()
419         if(keepalive)
420                 return keepalive->get_failed();
421         else
422                 return 0;
425 int VideoDevice::interrupt_crash()
427         if(input_base) return input_base->interrupt_crash();
428         return 0;
431 int VideoDevice::set_translation(int input_x, int input_y)
433         this->input_x = input_x;
434         this->input_y = input_y;
435         return 0;
438 int VideoDevice::set_field_order(int odd_field_first)
440         this->odd_field_first = odd_field_first;
441         return 0;
444 int VideoDevice::set_channel(Channel *channel)
446         if(channel)
447         {
448                 channel_lock->lock("VideoDevice::set_channel");
449                 this->channel->copy_settings(channel);
450                 channel_changed = 1;
451                 channel_lock->unlock();
453                 if(input_base) return input_base->set_channel(channel);
454                 if(output_base) return output_base->set_channel(channel);
455         }
458 void VideoDevice::set_quality(int quality)
460         this->quality = quality;
463 void VideoDevice::set_cpus(int cpus)
465         this->cpus = cpus;
468 int VideoDevice::set_picture(PictureConfig *picture)
470         if(picture)
471         {
472                 picture_lock->lock("VideoDevice::set_picture");
473                 this->picture->copy_settings(picture);
474                 picture_changed = 1;
475                 picture_lock->unlock();
477                 if(input_base) return input_base->set_picture(picture);
478         }
481 int VideoDevice::update_translation()
483         float frame_in_capture_x1f, frame_in_capture_x2f, frame_in_capture_y1f, frame_in_capture_y2f;
484         float capture_in_frame_x1f, capture_in_frame_x2f, capture_in_frame_y1f, capture_in_frame_y2f;
485         int z_changed = 0;
487         if(frame_resized)
488         {
489                 input_x = new_input_x;
490                 input_y = new_input_y;
492                 if(in_config->driver == VIDEO4LINUX || in_config->driver == VIDEO4LINUX2)
493                 {
494                         if(input_z != new_input_z)
495                         {
496                                 input_z = new_input_z;
497                                 z_changed = 1;
499                                 capture_w = (int)((float)in_config->w * input_z + 0.5);
500                                 capture_h = (int)((float)in_config->h * input_z + 0.5);
502 // Need to align to multiple of 4
503                                 capture_w &= ~3;
504                                 capture_h &= ~3;
505                         }
507                         frame_in_capture_x1f = (float)input_x * input_z + capture_w / 2 - in_config->w / 2;
508                         frame_in_capture_x2f = (float)input_x * input_z  + capture_w / 2 + in_config->w / 2;
509                         frame_in_capture_y1f = (float)input_y * input_z  + capture_h / 2 - in_config->h / 2;
510                         frame_in_capture_y2f = (float)input_y * input_z  + capture_h / 2 + in_config->h / 2;
512                         capture_in_frame_x1f = 0;
513                         capture_in_frame_y1f = 0;
514                         capture_in_frame_x2f = in_config->w;
515                         capture_in_frame_y2f = in_config->h;
517                         if(frame_in_capture_x1f < 0) { capture_in_frame_x1f -= frame_in_capture_x1f; frame_in_capture_x1f = 0; }
518                         if(frame_in_capture_y1f < 0) { capture_in_frame_y1f -= frame_in_capture_y1f; frame_in_capture_y1f = 0; }
519                         if(frame_in_capture_x2f > capture_w) { capture_in_frame_x2f -= frame_in_capture_x2f - capture_w; frame_in_capture_x2f = capture_w; }
520                         if(frame_in_capture_y2f > capture_h) { capture_in_frame_y2f -= frame_in_capture_y2f - capture_h; frame_in_capture_y2f = capture_h; }
522                         frame_in_capture_x1 = (int)frame_in_capture_x1f;
523                         frame_in_capture_y1 = (int)frame_in_capture_y1f;
524                         frame_in_capture_x2 = (int)frame_in_capture_x2f;
525                         frame_in_capture_y2 = (int)frame_in_capture_y2f;
527                         capture_in_frame_x1 = (int)capture_in_frame_x1f;
528                         capture_in_frame_y1 = (int)capture_in_frame_y1f;
529                         capture_in_frame_x2 = (int)capture_in_frame_x2f;
530                         capture_in_frame_y2 = (int)capture_in_frame_y2f;
532                         frame_resized = 0;
533                 }
534         }
535         return 0;
538 int VideoDevice::set_latency_counter(int value)
540         latency_counter = value;
541         return 0;
544 int VideoDevice::has_signal()
546         if(input_base) return input_base->has_signal();
547         return 0;
551 int VideoDevice::read_buffer(VFrame *frame)
553         int result = 0;
554         if(!capturing) return 0;
556 //printf("VideoDevice::read_buffer %p %p\n", frame, input_base);
557         if(input_base)
558         {
559 // Reset the keepalive thread
560                 if(keepalive) keepalive->capturing = 1;
561                 result = input_base->read_buffer(frame);
562                 if(keepalive)
563                 {
564                         keepalive->capturing = 0;
565                         keepalive->reset_keepalive();
566                 }
567                 return result;
568         }
570         return 0;
574 // ================================= OUTPUT ==========================================
577 int VideoDevice::open_output(VideoOutConfig *config, 
578                                         float rate, 
579                                         int out_w, 
580                                         int out_h,
581                                         Canvas *output,
582                                         int single_frame)
584         w = 1;
585 //printf("VideoDevice::open_output 1 %d\n", out_config->driver);
586         *this->out_config = *config;
587 //printf("VideoDevice::open_output 1 %d\n", out_config->driver);
588         this->out_w = out_w;
589         this->out_h = out_h;
590         this->orate = rate;
591         this->single_frame = single_frame;
593 //printf("VideoDevice::open_output 1 %d\n", out_config->driver);
594         switch(out_config->driver)
595         {
596                 case PLAYBACK_BUZ:
597                         output_base = new VDeviceBUZ(this);
598                         break;
599                 case PLAYBACK_X11:
600                 case PLAYBACK_X11_XV:
601                         output_base = new VDeviceX11(this, output);
602                         break;
604 #ifdef HAVE_FIREWIRE
605                 case PLAYBACK_DV1394:
606                 case PLAYBACK_FIREWIRE:
607                 case PLAYBACK_IEC61883:
608                         output_base = new VDevice1394(this);
609                         break;
610 #endif
611         }
612 //printf("VideoDevice::open_output 2 %d\n", out_config->driver);
614         if(output_base->open_output())
615         {
616                 delete output_base;
617                 output_base = 0;
618         }
619 //printf("VideoDevice::open_output 3 %d\n", out_config->driver);
621         if(output_base) 
622                 return 0;
623         else
624                 return 1;
629 int VideoDevice::start_playback()
631 // arm buffer before doing this
632         is_playing_back = 1;
633         interrupt = 0;
635         if(output_base) return output_base->start_playback();
636         return 1;
639 int VideoDevice::stop_playback()
641         if(output_base) output_base->stop_playback();
642         is_playing_back = 0;
643         interrupt = 0;
644         return 0;
647 void VideoDevice::goose_input()
649         if(input_base) input_base->goose_input();
652 void VideoDevice::new_output_buffers(VFrame **outputs, int colormodel)
654         for(int i = 0; i < MAX_CHANNELS; i++)
655                 outputs[i] = 0;
657         if(!output_base) return;
658         output_base->new_output_buffer(outputs, colormodel);
662 int VideoDevice::interrupt_playback()
664         interrupt = 1;
665         return 0;
668 int VideoDevice::write_buffer(VFrame **outputs, EDL *edl)
670 //printf("VideoDevice::write_buffer 1 %p\n", output_base);
671         if(output_base) return output_base->write_buffer(outputs, edl);
672         return 1;
675 int VideoDevice::output_visible()
677         if(output_base) return output_base->output_visible();
680 BC_Bitmap* VideoDevice::get_bitmap()
682         if(output_base) return output_base->get_bitmap();
686 int VideoDevice::set_cloexec_flag(int desc, int value)
688         int oldflags = fcntl(desc, F_GETFD, 0);
689         if(oldflags < 0) return oldflags;
690         if(value != 0) 
691                 oldflags |= FD_CLOEXEC;
692         else
693                 oldflags &= ~FD_CLOEXEC;
694         return fcntl(desc, F_SETFD, oldflags);