Fixed initialisation of tf in file_open(). Without setting the memory to 0,
[cinelerra_cv/mob.git] / cinelerra / videodevice.C
blobdba76337795f8641596a9b930710e47cf05717db
1 #include "asset.h"
2 #include "assets.h"
3 #include "bccapture.h"
4 #include "bcsignals.h"
5 #include "channel.h"
6 #include "channeldb.h"
7 #include "chantables.h"
8 #include "file.inc"
9 #include "mutex.h"
10 #include "mwindow.h"
11 #include "picture.h"
12 #include "playbackconfig.h"
13 #include "playbackengine.h"
14 #include "preferences.h"
15 #include "quicktime.h"
16 #include "recordconfig.h"
17 #include "recordmonitor.h"
18 #ifdef HAVE_FIREWIRE
19 #include "vdevice1394.h"
20 #endif
21 #include "vdevicebuz.h"
22 #include "vdevicedvb.h"
23 #include "vdevicev4l.h"
24 #include "vdevicev4l2.h"
25 #include "vdevicev4l2jpeg.h"
26 #include "vdevicex11.h"
27 #include "videoconfig.h"
28 #include "videodevice.h"
29 #include "videowindow.h"
30 #include "videowindowgui.h"
31 #include "vframe.h"
33 #include <unistd.h>
34 #include <fcntl.h>
36 KeepaliveThread::KeepaliveThread(VideoDevice *device)
37  : Thread()
39         still_alive = 1;
40         failed = 0;
41         interrupted = 0;
42         set_synchronous(1);
43         this->device = device;
44         capturing = 0;
45         startup_lock = new Mutex("KeepaliveThread::startup_lock");
48 KeepaliveThread::~KeepaliveThread()
50         delete startup_lock;
53 int KeepaliveThread::start_keepalive()
55         startup_lock->lock("KeepaliveThread::start_keepalive 1");
56         start();
57         startup_lock->lock("KeepaliveThread::start_keepalive 2");
58         startup_lock->unlock();
61 void KeepaliveThread::run()
63         startup_lock->unlock();
64         while(!interrupted)
65         {
66                 still_alive = 0;
67 // Give the capture a moment
68 // Should fix the delay in case users want slower frame rates.
69                 timer.delay((long)(KEEPALIVE_DELAY * 1000));
71 // See if a capture happened
72                 if(still_alive == 0 && capturing)
73                 {
74 //                      printf("KeepaliveThread::run: device crashed\n");
75                         failed++;
76                 }
77                 else
78                         failed = 0;
79         }
82 int KeepaliveThread::reset_keepalive()
84         still_alive = 1;
87 int KeepaliveThread::get_failed()
89         if(failed) return 1; else return 0;
92 int KeepaliveThread::stop()
94         interrupted = 1;
96 // Force an immediate exit even if capture_frame worked.
97         Thread::end();
98         Thread::join();
107 VideoDevice::VideoDevice(MWindow *mwindow)
109         this->mwindow = mwindow;
110         in_config = new VideoInConfig;
111         out_config = new VideoOutConfig;
112         channel = new Channel;
113         picture = new PictureConfig(mwindow ? mwindow->defaults : 0);
114         sharing_lock = new Mutex("VideoDevice::sharing_lock");
115         channel_lock = new Mutex("VideoDevice::channel_lock");
116         picture_lock = new Mutex("VideoDevice::picture_lock");
117         initialize();
121 VideoDevice::~VideoDevice()
123         input_sources.remove_all_objects();
124         delete in_config;
125         delete out_config;
126         delete channel;
127         delete picture;
128         delete sharing_lock;
129         delete channel_lock;
130         delete picture_lock;
133 int VideoDevice::initialize()
135         sharing = 0;
136         done_sharing = 0;
137         sharing_lock->reset();
138         orate = irate = 0;
139         out_w = out_h = 0;
140         r = w = 0;
141         is_playing_back = is_recording = 0;
142         input_x = 0;
143         input_y = 0;
144         input_z = 1;
145         frame_resized = 0;
146         capturing = 0;
147         keepalive = 0;
148         swap_bytes = 0;
149         input_base = 0;
150         output_base = 0;
151         output_format = 0;
152         interrupt = 0;
153         adevice = 0;
154         quality = 80;
155         cpus = 1;
156         single_frame = 0;
157         channel_changed = 0;
158         picture_changed = 0;
161 int VideoDevice::open_input(VideoInConfig *config, 
162         int input_x, 
163         int input_y, 
164         float input_z,
165         double frame_rate)
167         int result = 0;
169         *this->in_config = *config;
171         r = 1;
172         this->input_z = -1;   // Force initialization.
173         this->frame_rate = frame_rate;
176         switch(in_config->driver)
177         {
178                 case VIDEO4LINUX:
179                         keepalive = new KeepaliveThread(this);
180                         keepalive->start_keepalive();
181                         new_device_base();
182                         result = input_base->open_input();
183                         break;
186 #ifdef HAVE_VIDEO4LINUX2
187                 case VIDEO4LINUX2:
188                         new_device_base();
189                         result = input_base->open_input();
190                         break;
191                 case VIDEO4LINUX2JPEG:
192                         new_device_base();
193                         result = input_base->open_input();
194                         break;
195 #endif
197                 case SCREENCAPTURE:
198                         this->input_x = input_x;
199                         this->input_y = input_y;
200                         new_device_base();
201                         result = input_base->open_input();
202                         break;
203                 case CAPTURE_BUZ:
204 //printf("VideoDevice 1\n");
205                         keepalive = new KeepaliveThread(this);
206                         keepalive->start_keepalive();
207                         new_device_base();
208                         result = input_base->open_input();
209                         break;
210 #ifdef HAVE_FIREWIRE
211                 case CAPTURE_FIREWIRE:
212                 case CAPTURE_IEC61883:
213                         new_device_base();
214                         result = input_base->open_input();
215                         break;
216 #endif
218                 case CAPTURE_DVB:
219                         new_device_base();
220                         result = input_base->open_input();
221                         break;
222         }
223         
224         if(!result) capturing = 1;
225         return 0;
228 VDeviceBase* VideoDevice::new_device_base()
230         switch(in_config->driver)
231         {
232                 case VIDEO4LINUX:
233                         return input_base = new VDeviceV4L(this);
235 #ifdef HAVE_VIDEO4LINUX2
236                 case VIDEO4LINUX2:
237                         return input_base = new VDeviceV4L2(this);
239                 case VIDEO4LINUX2JPEG:
240                         return input_base = new VDeviceV4L2JPEG(this);
241 #endif
243                 case SCREENCAPTURE:
244                         return input_base = new VDeviceX11(this, 0);
246                 case CAPTURE_BUZ:
247                         return input_base = new VDeviceBUZ(this);
249 #ifdef HAVE_FIREWIRE
250                 case CAPTURE_FIREWIRE:
251                 case CAPTURE_IEC61883:
252                         return input_base = new VDevice1394(this);
253 #endif
255                 case CAPTURE_DVB:
256                         return input_base = new VDeviceDVB(this);
257         }
258         return 0;
261 static char* get_channeldb_path(VideoInConfig *vconfig_in)
263         char *path = "";
264         switch(vconfig_in->driver)
265         {
266                 case VIDEO4LINUX:
267                         path = "channels_v4l";
268                         break;
269                 case VIDEO4LINUX2:
270                         path = "channels_v4l2";
271                         break;
272                 case VIDEO4LINUX2JPEG:
273                         path = "channels_v4l2jpeg";
274                         break;
275                 case CAPTURE_BUZ:
276                         path = "channels_buz";
277                         break;
278                 case CAPTURE_DVB:
279                         path = "channels_dvb";
280                         break;
281         }
282         return path;
285 void VideoDevice::load_channeldb(ChannelDB *channeldb, VideoInConfig *vconfig_in)
287         channeldb->load(get_channeldb_path(vconfig_in));
290 void VideoDevice::save_channeldb(ChannelDB *channeldb, VideoInConfig *vconfig_in)
292         channeldb->save(get_channeldb_path(vconfig_in));
296 VDeviceBase* VideoDevice::get_output_base()
298         return output_base;
301 int VideoDevice::is_compressed(int driver, int use_file, int use_fixed)
303 // FileMOV needs to have write_frames called so the start codes get scanned.
304         return ((driver == CAPTURE_BUZ && use_fixed) ||
305                 (driver == VIDEO4LINUX2JPEG && use_fixed) || 
306                 driver == CAPTURE_LML || 
307                 driver == CAPTURE_FIREWIRE ||
308                 driver == CAPTURE_IEC61883);
311 int VideoDevice::is_compressed(int use_file, int use_fixed)
313         return is_compressed(in_config->driver, use_file, use_fixed);
317 void VideoDevice::fix_asset(Asset *asset, int driver)
319 // Fix asset using legacy routine
320         switch(driver)
321         {
322                 case CAPTURE_BUZ:
323                 case CAPTURE_LML:
324                 case VIDEO4LINUX2JPEG:
325                         if(asset->format != FILE_AVI &&
326                                 asset->format != FILE_MOV)
327                                 asset->format = FILE_MOV;
328                         strcpy(asset->vcodec, QUICKTIME_MJPA);
329                         return;
330                 
331                 case CAPTURE_FIREWIRE:
332                 case CAPTURE_IEC61883:
333                         if(asset->format != FILE_AVI &&
334                                 asset->format != FILE_MOV)
335                                 asset->format = FILE_MOV;
336                         strcpy(asset->vcodec, QUICKTIME_DVSD);
337                         return;
338         }
340 // Fix asset using inherited routine
341         new_device_base();
343         if(input_base) input_base->fix_asset(asset);
344         delete input_base;
345         input_base = 0;
349 char* VideoDevice::drivertostr(int driver)
351         switch(driver)
352         {
353                 case PLAYBACK_X11:
354                         return PLAYBACK_X11_TITLE;
355                         break;
356                 case PLAYBACK_X11_XV:
357                         return PLAYBACK_X11_XV_TITLE;
358                         break;
359                 case PLAYBACK_X11_GL:
360                         return PLAYBACK_X11_GL_TITLE;
361                         break;
362                 case PLAYBACK_BUZ:
363                         return PLAYBACK_BUZ_TITLE;
364                         break;
365                 case VIDEO4LINUX:
366                         return VIDEO4LINUX_TITLE;
367                         break;
368                 case VIDEO4LINUX2:
369                         return VIDEO4LINUX2_TITLE;
370                         break;
371                 case VIDEO4LINUX2JPEG:
372                         return VIDEO4LINUX2JPEG_TITLE;
373                         break;
374                 case SCREENCAPTURE:
375                         return SCREENCAPTURE_TITLE;
376                         break;
377                 case CAPTURE_BUZ:
378                         return CAPTURE_BUZ_TITLE;
379                         break;
380 #ifdef HAVE_FIREWIRE
381                 case CAPTURE_FIREWIRE:
382                         return CAPTURE_FIREWIRE_TITLE;
383                         break;
384                 case CAPTURE_IEC61883:
385                         return CAPTURE_IEC61883_TITLE;
386                         break;
387 #endif
388         }
389         return "";
392 int VideoDevice::get_best_colormodel(Asset *asset)
394         if(input_base)
395                 return input_base->get_best_colormodel(asset);
396         else
397                 return BC_RGB888;
400 int VideoDevice::close_all()
402         int i;
404         if(w)
405         {
406                 if(output_base)
407                 {
408                         output_base->close_all();
409                         delete output_base;
410                 }
411         }
413         if(r && capturing)
414         {
415                 capturing = 0;
416                 if(input_base)
417                 {
418                         input_base->close_all();
419                         delete input_base;
421                         input_base = 0;
422                 }
424                 if(keepalive)
425                 {
426                         keepalive->stop();
427                         delete keepalive;
428                 }
429         }
432         input_sources.remove_all_objects();
434         initialize();
436         return 0;
440 int VideoDevice::set_adevice(AudioDevice *adevice)
442         this->adevice = adevice;
443         return 0;
447 ArrayList<Channel*>* VideoDevice::get_inputs()
449         return &input_sources;
452 Channel* VideoDevice::new_input_source(char *device_name)
454         for(int i = 0; i < input_sources.total; i++)
455         {
456                 if(!strcmp(input_sources.values[i]->device_name, device_name))
457                         return input_sources.values[i];
458         }
459         Channel *item = new Channel;
460         strcpy(item->device_name, device_name);
461         input_sources.append(item);
462         return item;
465 int VideoDevice::get_failed()
467         if(keepalive)
468                 return keepalive->get_failed();
469         else
470                 return 0;
473 int VideoDevice::interrupt_crash()
475         if(input_base) return input_base->interrupt_crash();
476         return 0;
479 int VideoDevice::set_translation(int input_x, int input_y)
481         this->input_x = input_x;
482         this->input_y = input_y;
483         return 0;
486 int VideoDevice::set_field_order(int odd_field_first)
488         this->odd_field_first = odd_field_first;
489         return 0;
492 int VideoDevice::set_channel(Channel *channel)
494         if(channel)
495         {
496                 channel_lock->lock("VideoDevice::set_channel");
497                 this->channel->copy_settings(channel);
498                 channel_changed = 1;
499                 channel_lock->unlock();
501                 if(input_base) return input_base->set_channel(channel);
502                 if(output_base) return output_base->set_channel(channel);
503         }
506 void VideoDevice::set_quality(int quality)
508         this->quality = quality;
511 void VideoDevice::set_cpus(int cpus)
513         this->cpus = cpus;
516 int VideoDevice::set_picture(PictureConfig *picture)
518         if(picture)
519         {
520                 picture_lock->lock("VideoDevice::set_picture");
521                 this->picture->copy_settings(picture);
522                 picture_changed = 1;
523                 picture_lock->unlock();
525                 if(input_base) return input_base->set_picture(picture);
526         }
529 int VideoDevice::update_translation()
531         float frame_in_capture_x1f, frame_in_capture_x2f, frame_in_capture_y1f, frame_in_capture_y2f;
532         float capture_in_frame_x1f, capture_in_frame_x2f, capture_in_frame_y1f, capture_in_frame_y2f;
533         int z_changed = 0;
535         if(frame_resized)
536         {
537                 input_x = new_input_x;
538                 input_y = new_input_y;
540                 if(in_config->driver == VIDEO4LINUX || in_config->driver == VIDEO4LINUX2)
541                 {
542                         if(input_z != new_input_z)
543                         {
544                                 input_z = new_input_z;
545                                 z_changed = 1;
547                                 capture_w = (int)((float)in_config->w * input_z + 0.5);
548                                 capture_h = (int)((float)in_config->h * input_z + 0.5);
550 // Need to align to multiple of 4
551                                 capture_w &= ~3;
552                                 capture_h &= ~3;
553                         }
555                         frame_in_capture_x1f = (float)input_x * input_z + capture_w / 2 - in_config->w / 2;
556                         frame_in_capture_x2f = (float)input_x * input_z  + capture_w / 2 + in_config->w / 2;
557                         frame_in_capture_y1f = (float)input_y * input_z  + capture_h / 2 - in_config->h / 2;
558                         frame_in_capture_y2f = (float)input_y * input_z  + capture_h / 2 + in_config->h / 2;
560                         capture_in_frame_x1f = 0;
561                         capture_in_frame_y1f = 0;
562                         capture_in_frame_x2f = in_config->w;
563                         capture_in_frame_y2f = in_config->h;
565                         if(frame_in_capture_x1f < 0) { capture_in_frame_x1f -= frame_in_capture_x1f; frame_in_capture_x1f = 0; }
566                         if(frame_in_capture_y1f < 0) { capture_in_frame_y1f -= frame_in_capture_y1f; frame_in_capture_y1f = 0; }
567                         if(frame_in_capture_x2f > capture_w) { capture_in_frame_x2f -= frame_in_capture_x2f - capture_w; frame_in_capture_x2f = capture_w; }
568                         if(frame_in_capture_y2f > capture_h) { capture_in_frame_y2f -= frame_in_capture_y2f - capture_h; frame_in_capture_y2f = capture_h; }
570                         frame_in_capture_x1 = (int)frame_in_capture_x1f;
571                         frame_in_capture_y1 = (int)frame_in_capture_y1f;
572                         frame_in_capture_x2 = (int)frame_in_capture_x2f;
573                         frame_in_capture_y2 = (int)frame_in_capture_y2f;
575                         capture_in_frame_x1 = (int)capture_in_frame_x1f;
576                         capture_in_frame_y1 = (int)capture_in_frame_y1f;
577                         capture_in_frame_x2 = (int)capture_in_frame_x2f;
578                         capture_in_frame_y2 = (int)capture_in_frame_y2f;
580                         frame_resized = 0;
581                 }
582         }
583         return 0;
586 int VideoDevice::set_latency_counter(int value)
588         latency_counter = value;
589         return 0;
592 int VideoDevice::has_signal()
594         if(input_base) return input_base->has_signal();
595         return 0;
599 int VideoDevice::read_buffer(VFrame *frame)
601         int result = 0;
602         if(!capturing) return 0;
604 //printf("VideoDevice::read_buffer %p %p\n", frame, input_base);
605         if(input_base)
606         {
607 // Reset the keepalive thread
608                 if(keepalive) keepalive->capturing = 1;
609                 result = input_base->read_buffer(frame);
610                 if(keepalive)
611                 {
612                         keepalive->capturing = 0;
613                         keepalive->reset_keepalive();
614                 }
615                 return result;
616         }
618         return 0;
622 // ================================= OUTPUT ==========================================
625 int VideoDevice::open_output(VideoOutConfig *config, 
626                                         float rate, 
627                                         int out_w, 
628                                         int out_h,
629                                         Canvas *output,
630                                         int single_frame)
632         w = 1;
633 //printf("VideoDevice::open_output 1 %d\n", out_config->driver);
634         *this->out_config = *config;
635 //printf("VideoDevice::open_output 1 %d\n", out_config->driver);
636         this->out_w = out_w;
637         this->out_h = out_h;
638         this->orate = rate;
639         this->single_frame = single_frame;
641 //printf("VideoDevice::open_output 1 %d\n", out_config->driver);
642         switch(out_config->driver)
643         {
644                 case PLAYBACK_BUZ:
645                         output_base = new VDeviceBUZ(this);
646                         break;
647                 case PLAYBACK_X11:
648                 case PLAYBACK_X11_XV:
649                 case PLAYBACK_X11_GL:
650                         output_base = new VDeviceX11(this, output);
651                         break;
653 #ifdef HAVE_FIREWIRE
654                 case PLAYBACK_DV1394:
655                 case PLAYBACK_FIREWIRE:
656                 case PLAYBACK_IEC61883:
657                         output_base = new VDevice1394(this);
658                         break;
659 #endif
660         }
661 //printf("VideoDevice::open_output 2 %d\n", out_config->driver);
663         if(output_base->open_output())
664         {
665                 delete output_base;
666                 output_base = 0;
667         }
668 //printf("VideoDevice::open_output 3 %d\n", out_config->driver);
670         if(output_base) 
671                 return 0;
672         else
673                 return 1;
678 int VideoDevice::start_playback()
680 // arm buffer before doing this
681         is_playing_back = 1;
682         interrupt = 0;
684         if(output_base) return output_base->start_playback();
685         return 1;
688 int VideoDevice::stop_playback()
690         if(output_base) output_base->stop_playback();
691         is_playing_back = 0;
692         interrupt = 0;
693         return 0;
696 void VideoDevice::goose_input()
698         if(input_base) input_base->goose_input();
701 void VideoDevice::new_output_buffer(VFrame **output, int colormodel)
703         if(!output_base) return;
704         output_base->new_output_buffer(output, colormodel);
708 int VideoDevice::interrupt_playback()
710         interrupt = 1;
711         return 0;
714 int VideoDevice::write_buffer(VFrame *output, EDL *edl)
716 //printf("VideoDevice::write_buffer 1 %p\n", output_base);
717         if(output_base) return output_base->write_buffer(output, edl);
718         return 1;
721 int VideoDevice::output_visible()
723         if(output_base) return output_base->output_visible();
726 BC_Bitmap* VideoDevice::get_bitmap()
728         if(output_base) return output_base->get_bitmap();
732 int VideoDevice::set_cloexec_flag(int desc, int value)
734         int oldflags = fcntl(desc, F_GETFD, 0);
735         if(oldflags < 0) return oldflags;
736         if(value != 0) 
737                 oldflags |= FD_CLOEXEC;
738         else
739                 oldflags &= ~FD_CLOEXEC;
740         return fcntl(desc, F_SETFD, oldflags);