r373: Merged the official release 1.2.1.
[cinelerra_cv.git] / cinelerra / videodevice.C
blobc441aaffcc1b2a644a47d8b58fac4f0cc2ea0dc1
1 #include "assets.h"
2 #include "bccapture.h"
3 #include "channel.h"
4 #include "chantables.h"
5 #include "mutex.h"
6 #include "picture.h"
7 #include "playbackconfig.h"
8 #include "playbackengine.h"
9 #include "preferences.h"
10 #include "recordconfig.h"
11 #include "recordmonitor.h"
12 #include "vdevice1394.h"
13 #include "vdevicebuz.h"
14 #include "vdevicev4l.h"
15 #include "vdevicev4l2.h"
16 #include "vdevicev4l2jpeg.h"
17 #include "vdevicex11.h"
18 #include "videoconfig.h"
19 #include "videodevice.h"
20 #include "videowindow.h"
21 #include "videowindowgui.h"
22 #include "vframe.h"
24 #include <unistd.h>
25 #include <fcntl.h>
27 KeepaliveThread::KeepaliveThread(VideoDevice *device)
28  : Thread()
30         still_alive = 1;
31         failed = 0;
32         interrupted = 0;
33         set_synchronous(1);
34         this->device = device;
35         capturing = 0;
36         startup_lock = new Mutex("KeepaliveThread::startup_lock");
39 KeepaliveThread::~KeepaliveThread()
41         delete startup_lock;
44 int KeepaliveThread::start_keepalive()
46         startup_lock->lock("KeepaliveThread::start_keepalive 1");
47         start();
48         startup_lock->lock("KeepaliveThread::start_keepalive 2");
49         startup_lock->unlock();
52 void KeepaliveThread::run()
54         startup_lock->unlock();
55         while(!interrupted)
56         {
57                 still_alive = 0;
58 // Give the capture a moment
59 // Should fix the delay in case users want slower frame rates.
60                 timer.delay((long)(KEEPALIVE_DELAY * 1000));
62 // See if a capture happened
63                 if(still_alive == 0 && capturing)
64                 {
65 //                      printf("KeepaliveThread::run: device crashed\n");
66                         failed++;
67                 }
68                 else
69                         failed = 0;
70         }
73 int KeepaliveThread::reset_keepalive()
75         still_alive = 1;
78 int KeepaliveThread::get_failed()
80         if(failed) return 1; else return 0;
83 int KeepaliveThread::stop()
85         interrupted = 1;
87 // Force an immediate exit even if capture_frame worked.
88         Thread::end();
89         Thread::join();
98 VideoDevice::VideoDevice()
100         in_config = new VideoInConfig;
101         out_config = new VideoOutConfig;
102         channel = new Channel;
103         picture = new Picture;
104         sharing_lock = new Mutex("VideoDevice::sharing_lock");
105         channel_lock = new Mutex("VideoDevice::channel_lock");
106         picture_lock = new Mutex("VideoDevice::picture_lock");
107         initialize();
110 VideoDevice::~VideoDevice()
112         input_sources.remove_all_objects();
113         delete in_config;
114         delete out_config;
115         delete channel;
116         delete picture;
117         delete sharing_lock;
118         delete channel_lock;
119         delete picture_lock;
122 int VideoDevice::initialize()
124         sharing = 0;
125         done_sharing = 0;
126         sharing_lock->reset();
127         orate = irate = 0;
128         out_w = out_h = 0;
129         r = w = 0;
130         is_playing_back = is_recording = 0;
131         input_x = 0;
132         input_y = 0;
133         input_z = 1;
134         frame_resized = 0;
135         capturing = 0;
136         keepalive = 0;
137         swap_bytes = 0;
138         input_base = 0;
139         output_base = 0;
140         output_format = 0;
141         interrupt = 0;
142         adevice = 0;
143         quality = 80;
144         cpus = 1;
145         single_frame = 0;
146         channel_changed = 0;
147         picture_changed = 0;
150 int VideoDevice::open_input(VideoInConfig *config, 
151         int input_x, 
152         int input_y, 
153         float input_z,
154         float frame_rate)
156         int result = 0;
158         *this->in_config = *config;
160         r = 1;
161         this->input_z = -1;   // Force initialization.
162         this->frame_rate = frame_rate;
165         switch(in_config->driver)
166         {
167                 case VIDEO4LINUX:
168                         keepalive = new KeepaliveThread(this);
169                         keepalive->start_keepalive();
170                         input_base = new VDeviceV4L(this);
171                         result = input_base->open_input();
172                         break;
175 #ifdef HAVE_VIDEO4LINUX2
176                 case VIDEO4LINUX2:
177                         input_base = new VDeviceV4L2(this);
178                         result = input_base->open_input();
179                         break;
180                 case VIDEO4LINUX2JPEG:
181                         input_base = new VDeviceV4L2JPEG(this);
182                         result = input_base->open_input();
183                         break;
184 #endif
186                 case SCREENCAPTURE:
187                         this->input_x = input_x;
188                         this->input_y = input_y;
189                         input_base = new VDeviceX11(this, 0);
190                         result = input_base->open_input();
191                         break;
192                 case CAPTURE_BUZ:
193 //printf("VideoDevice 1\n");
194                         keepalive = new KeepaliveThread(this);
195                         keepalive->start_keepalive();
196                         input_base = new VDeviceBUZ(this);
197                         result = input_base->open_input();
198                         break;
199 #ifdef HAVE_FIREWIRE
200                 case CAPTURE_FIREWIRE:
201                         input_base = new VDevice1394(this);
202                         result = input_base->open_input();
203                         break;
204 #endif
205         }
206         
207         if(!result) capturing = 1;
208         return 0;
211 int VideoDevice::is_compressed(int driver, int use_file, int use_fixed)
213 // FileMOV needs to have write_frames called so the start codes get scanned.
214         return ((driver == CAPTURE_BUZ && use_fixed) ||
215                 (driver == VIDEO4LINUX2JPEG && use_fixed) || 
216                 driver == CAPTURE_LML || 
217                 driver == CAPTURE_FIREWIRE);
220 int VideoDevice::is_compressed(int use_file, int use_fixed)
222         return is_compressed(in_config->driver, use_file, use_fixed);
226 char* VideoDevice::get_vcodec(int driver)
228         switch(driver)
229         {
230                 case CAPTURE_BUZ:
231                 case CAPTURE_LML:
232                 case VIDEO4LINUX2JPEG:
233                         return QUICKTIME_MJPA;
234                         break;
235                 
236                 case CAPTURE_FIREWIRE:
237                         return QUICKTIME_DV;
238                         break;
239         }
240         return "";
244 char* VideoDevice::drivertostr(int driver)
246         switch(driver)
247         {
248                 case PLAYBACK_X11:
249                         return PLAYBACK_X11_TITLE;
250                         break;
251                 case PLAYBACK_X11_XV:
252                         return PLAYBACK_X11_XV_TITLE;
253                         break;
254                 case PLAYBACK_BUZ:
255                         return PLAYBACK_BUZ_TITLE;
256                         break;
257                 case VIDEO4LINUX:
258                         return VIDEO4LINUX_TITLE;
259                         break;
260                 case VIDEO4LINUX2:
261                         return VIDEO4LINUX2_TITLE;
262                         break;
263                 case VIDEO4LINUX2JPEG:
264                         return VIDEO4LINUX2JPEG_TITLE;
265                         break;
266                 case SCREENCAPTURE:
267                         return SCREENCAPTURE_TITLE;
268                         break;
269                 case CAPTURE_BUZ:
270                         return CAPTURE_BUZ_TITLE;
271                         break;
272                 case CAPTURE_FIREWIRE:
273                         return CAPTURE_FIREWIRE_TITLE;
274                         break;
275         }
276         return "";
279 int VideoDevice::get_best_colormodel(Asset *asset)
281         if(input_base)
282                 return input_base->get_best_colormodel(asset);
283         else
284                 return BC_RGB888;
287 int VideoDevice::close_all()
289         int i;
291 //printf("VideoDevice::close_all 1\n");
292         if(w)
293         {
294                 if(output_base)
295                 {
296                         output_base->close_all();
297                         delete output_base;
298                 }
299         }
301 //printf("VideoDevice::close_all 2\n");
302         if(r && capturing)
303         {
304                 capturing = 0;
305                 if(input_base)
306                 {
307                         input_base->close_all();
308                         delete input_base;
309                         input_base = 0;
310                 }
312                 if(keepalive)
313                 {
314                         keepalive->stop();
315                         delete keepalive;
316                 }
317         }
319 //printf("VideoDevice::close_all 3\n");
320         input_sources.remove_all_objects();
322 //printf("VideoDevice::close_all 4\n");
323         initialize();
325 //printf("VideoDevice::close_all 5\n");
326         return 0;
330 int VideoDevice::set_adevice(AudioDevice *adevice)
332         this->adevice = adevice;
333         return 0;
337 ArrayList<Channel*>* VideoDevice::get_inputs()
339         return &input_sources;
342 Channel* VideoDevice::new_input_source(char *device_name)
344         for(int i = 0; i < input_sources.total; i++)
345         {
346                 if(!strcmp(input_sources.values[i]->device_name, device_name))
347                         return input_sources.values[i];
348         }
349         Channel *item = new Channel;
350         strcpy(item->device_name, device_name);
351         input_sources.append(item);
352         return item;
355 int VideoDevice::get_failed()
357         if(keepalive)
358                 return keepalive->get_failed();
359         else
360                 return 0;
363 int VideoDevice::interrupt_crash()
365         if(input_base) return input_base->interrupt_crash();
366         return 0;
369 int VideoDevice::set_translation(int input_x, int input_y)
371         this->input_x = input_x;
372         this->input_y = input_y;
373         return 0;
376 int VideoDevice::set_field_order(int odd_field_first)
378         this->odd_field_first = odd_field_first;
379         return 0;
382 int VideoDevice::set_channel(Channel *channel)
384         if(channel)
385         {
386                 channel_lock->lock("VideoDevice::set_channel");
387                 this->channel->copy_settings(channel);
388                 channel_changed = 1;
389                 channel_lock->unlock();
391                 if(input_base) return input_base->set_channel(channel);
392                 if(output_base) return output_base->set_channel(channel);
393         }
396 void VideoDevice::set_quality(int quality)
398         this->quality = quality;
401 void VideoDevice::set_cpus(int cpus)
403         this->cpus = cpus;
406 int VideoDevice::set_picture(Picture *picture)
408         if(picture)
409         {
410                 picture_lock->lock("VideoDevice::set_picture");
411                 this->picture->copy_settings(picture);
412                 picture_changed = 1;
413                 picture_lock->unlock();
415                 if(input_base) return input_base->set_picture(picture);
416         }
419 int VideoDevice::update_translation()
421         float frame_in_capture_x1f, frame_in_capture_x2f, frame_in_capture_y1f, frame_in_capture_y2f;
422         float capture_in_frame_x1f, capture_in_frame_x2f, capture_in_frame_y1f, capture_in_frame_y2f;
423         int z_changed = 0;
425         if(frame_resized)
426         {
427                 input_x = new_input_x;
428                 input_y = new_input_y;
430                 if(in_config->driver == VIDEO4LINUX || in_config->driver == VIDEO4LINUX2)
431                 {
432                         if(input_z != new_input_z)
433                         {
434                                 input_z = new_input_z;
435                                 z_changed = 1;
437                                 capture_w = (int)((float)in_config->w * input_z + 0.5);
438                                 capture_h = (int)((float)in_config->h * input_z + 0.5);
440 // Need to align to multiple of 4
441                                 capture_w &= ~3;
442                                 capture_h &= ~3;
443                         }
445                         frame_in_capture_x1f = (float)input_x * input_z + capture_w / 2 - in_config->w / 2;
446                         frame_in_capture_x2f = (float)input_x * input_z  + capture_w / 2 + in_config->w / 2;
447                         frame_in_capture_y1f = (float)input_y * input_z  + capture_h / 2 - in_config->h / 2;
448                         frame_in_capture_y2f = (float)input_y * input_z  + capture_h / 2 + in_config->h / 2;
450                         capture_in_frame_x1f = 0;
451                         capture_in_frame_y1f = 0;
452                         capture_in_frame_x2f = in_config->w;
453                         capture_in_frame_y2f = in_config->h;
455                         if(frame_in_capture_x1f < 0) { capture_in_frame_x1f -= frame_in_capture_x1f; frame_in_capture_x1f = 0; }
456                         if(frame_in_capture_y1f < 0) { capture_in_frame_y1f -= frame_in_capture_y1f; frame_in_capture_y1f = 0; }
457                         if(frame_in_capture_x2f > capture_w) { capture_in_frame_x2f -= frame_in_capture_x2f - capture_w; frame_in_capture_x2f = capture_w; }
458                         if(frame_in_capture_y2f > capture_h) { capture_in_frame_y2f -= frame_in_capture_y2f - capture_h; frame_in_capture_y2f = capture_h; }
460                         frame_in_capture_x1 = (int)frame_in_capture_x1f;
461                         frame_in_capture_y1 = (int)frame_in_capture_y1f;
462                         frame_in_capture_x2 = (int)frame_in_capture_x2f;
463                         frame_in_capture_y2 = (int)frame_in_capture_y2f;
465                         capture_in_frame_x1 = (int)capture_in_frame_x1f;
466                         capture_in_frame_y1 = (int)capture_in_frame_y1f;
467                         capture_in_frame_x2 = (int)capture_in_frame_x2f;
468                         capture_in_frame_y2 = (int)capture_in_frame_y2f;
470                         frame_resized = 0;
471                 }
472         }
473         return 0;
476 int VideoDevice::set_latency_counter(int value)
478         latency_counter = value;
479         return 0;
482 int VideoDevice::read_buffer(VFrame *frame)
484         int result = 0;
485         if(!capturing) return 0;
487 //printf("VideoDevice::read_buffer %p %p\n", frame, input_base);
488         if(input_base)
489         {
490 // Reset the keepalive thread
491                 if(keepalive) keepalive->capturing = 1;
492                 result = input_base->read_buffer(frame);
493                 if(keepalive)
494                 {
495                         keepalive->capturing = 0;
496                         keepalive->reset_keepalive();
497                 }
498                 return result;
499         }
501         return 0;
505 // ================================= OUTPUT ==========================================
508 int VideoDevice::open_output(VideoOutConfig *config, 
509                                         float rate, 
510                                         int out_w, 
511                                         int out_h,
512                                         Canvas *output,
513                                         int single_frame)
515         w = 1;
516 //printf("VideoDevice::open_output 1 %d\n", out_config->driver);
517         *this->out_config = *config;
518 //printf("VideoDevice::open_output 1 %d\n", out_config->driver);
519         this->out_w = out_w;
520         this->out_h = out_h;
521         this->orate = rate;
522         this->single_frame = single_frame;
524 //printf("VideoDevice::open_output 1 %d\n", out_config->driver);
525         switch(out_config->driver)
526         {
527                 case PLAYBACK_BUZ:
528                         output_base = new VDeviceBUZ(this);
529                         break;
530                 case PLAYBACK_X11:
531                 case PLAYBACK_X11_XV:
532                         output_base = new VDeviceX11(this, output);
533                         break;
535                 case PLAYBACK_DV1394:
536                 case PLAYBACK_FIREWIRE:
537                         output_base = new VDevice1394(this);
538                         break;
539         }
540 //printf("VideoDevice::open_output 2 %d\n", out_config->driver);
542         if(output_base->open_output())
543         {
544                 delete output_base;
545                 output_base = 0;
546         }
547 //printf("VideoDevice::open_output 3 %d\n", out_config->driver);
549         if(output_base) 
550                 return 0;
551         else
552                 return 1;
557 int VideoDevice::start_playback()
559 // arm buffer before doing this
560         is_playing_back = 1;
561         interrupt = 0;
563         if(output_base) return output_base->start_playback();
564         return 1;
567 int VideoDevice::stop_playback()
569         if(output_base) output_base->stop_playback();
570         is_playing_back = 0;
571         interrupt = 0;
572         return 0;
575 void VideoDevice::goose_input()
577         if(input_base) input_base->goose_input();
580 void VideoDevice::new_output_buffers(VFrame **outputs, int colormodel)
582         for(int i = 0; i < MAX_CHANNELS; i++)
583                 outputs[i] = 0;
585         if(!output_base) return;
586         output_base->new_output_buffer(outputs, colormodel);
590 int VideoDevice::interrupt_playback()
592         interrupt = 1;
593         return 0;
596 int VideoDevice::write_buffer(VFrame **outputs, EDL *edl)
598 //printf("VideoDevice::write_buffer 1 %p\n", output_base);
599         if(output_base) return output_base->write_buffer(outputs, edl);
600         return 1;
603 int VideoDevice::output_visible()
605         if(output_base) return output_base->output_visible();
608 BC_Bitmap* VideoDevice::get_bitmap()
610         if(output_base) return output_base->get_bitmap();
614 int VideoDevice::set_cloexec_flag(int desc, int value)
616         int oldflags = fcntl(desc, F_GETFD, 0);
617         if(oldflags < 0) return oldflags;
618         if(value != 0) 
619                 oldflags |= FD_CLOEXEC;
620         else
621                 oldflags &= ~FD_CLOEXEC;
622         return fcntl(desc, F_SETFD, oldflags);