r125: This commit was manufactured by cvs2svn to create tag 'r1_1_7-last'.
[cinelerra_cv/mob.git] / hvirtual / cinelerra / videodevice.C
blob6cb95d6f310e88a433f2a71d3aaa4c9f5682f690
1 #include "assets.h"
2 #include "bccapture.h"
3 #include "channel.h"
4 #include "chantables.h"
5 #include "playbackconfig.h"
6 #include "playbackengine.h"
7 #include "preferences.h"
8 #include "recordconfig.h"
9 #include "recordmonitor.h"
10 #include "vdevice1394.h"
11 #include "vdevicebuz.h"
12 #include "vdevicev4l.h"
13 #include "vdevicex11.h"
14 #include "videoconfig.h"
15 #include "videodevice.h"
16 #include "videowindow.h"
17 #include "videowindowgui.h"
18 #include "vframe.h"
21 KeepaliveThread::KeepaliveThread(VideoDevice *device) : Thread()
23         still_alive = 1;
24         failed = 0;
25         interrupted = 0;
26         set_synchronous(1);
27         this->device = device;
28         capturing = 0;
31 KeepaliveThread::~KeepaliveThread()
35 int KeepaliveThread::start_keepalive()
37         startup_lock.lock();
38         start();
39         startup_lock.lock();
40         startup_lock.unlock();
43 void KeepaliveThread::run()
45         startup_lock.unlock();
46         while(!interrupted)
47         {
48                 still_alive = 0;
49 // Give the capture a moment
50 // Should fix the delay in case users want slower frame rates.
51                 timer.delay((long)(KEEPALIVE_DELAY * 1000));
53 // See if a capture happened
54                 if(still_alive == 0 && capturing)
55                 {
56 //                      printf("KeepaliveThread::run: device crashed\n");
57                         failed++;
58                 }
59                 else
60                         failed = 0;
61         }
64 int KeepaliveThread::reset_keepalive()
66         still_alive = 1;
69 int KeepaliveThread::get_failed()
71         if(failed) return 1; else return 0;
74 int KeepaliveThread::stop()
76         interrupted = 1;
78 // Force an immediate exit even if capture_frame worked.
79         Thread::end();
80         Thread::join();
89 VideoDevice::VideoDevice()
91         in_config = new VideoInConfig;
92         out_config = new VideoOutConfig(0, 0);
93         initialize();
96 VideoDevice::~VideoDevice()
98         input_sources.remove_all_objects();
99         delete in_config;
100         delete out_config;
103 int VideoDevice::initialize()
105         sharing = 0;
106         done_sharing = 0;
107         sharing_lock.reset();
108         orate = irate = 0;
109         out_w = out_h = 0;
110         r = w = 0;
111         is_playing_back = is_recording = 0;
112         input_x = 0;
113         input_y = 0;
114         input_z = 1;
115         frame_resized = 0;
116         capturing = 0;
117         keepalive = 0;
118         swap_bytes = 0;
119         input_base = 0;
120         output_base = 0;
121         output_format = 0;
122         interrupt = 0;
123         adevice = 0;
124         quality = 80;
125         cpus = 1;
126         single_frame = 0;
129 int VideoDevice::open_input(VideoInConfig *config, 
130         int input_x, 
131         int input_y, 
132         float input_z,
133         float frame_rate)
135         int result = 0;
137         *this->in_config = *config;
139         r = 1;
140         this->input_z = -1;   // Force initialization.
141         this->frame_rate = frame_rate;
143         switch(in_config->driver)
144         {
145                 case VIDEO4LINUX:
146                         keepalive = new KeepaliveThread(this);
147                         keepalive->start_keepalive();
148                         input_base = new VDeviceV4L(this);
149                         result = input_base->open_input();
150                         break;
151                 case SCREENCAPTURE:
152                         this->input_x = input_x;
153                         this->input_y = input_y;
154                         input_base = new VDeviceX11(this, 0);
155                         result = input_base->open_input();
156                         break;
157                 case CAPTURE_BUZ:
158 //printf("VideoDevice 1\n");
159                         keepalive = new KeepaliveThread(this);
160                         keepalive->start_keepalive();
161                         input_base = new VDeviceBUZ(this);
162                         result = input_base->open_input();
163                         break;
164 #ifdef HAVE_FIREWIRE
165                 case CAPTURE_FIREWIRE:
166                         input_base = new VDevice1394(this);
167                         result = input_base->open_input();
168                         break;
169 #endif
170         }
171         
172         if(!result) capturing = 1;
173         return 0;
176 int VideoDevice::is_compressed(int driver)
178         return (driver == CAPTURE_BUZ || 
179                 driver == CAPTURE_LML || 
180                 driver == CAPTURE_FIREWIRE);
183 char* VideoDevice::get_vcodec(int driver)
185         switch(driver)
186         {
187                 case CAPTURE_BUZ:
188                 case CAPTURE_LML:
189                         return QUICKTIME_MJPA;
190                         break;
191                 
192                 case CAPTURE_FIREWIRE:
193                         return QUICKTIME_DV;
194                         break;
195         }
199 char* VideoDevice::drivertostr(int driver)
201         switch(driver)
202         {
203                 case PLAYBACK_X11:
204                         return PLAYBACK_X11_TITLE;
205                         break;
206                 case PLAYBACK_X11_XV:
207                         return PLAYBACK_X11_XV_TITLE;
208                         break;
209                 case PLAYBACK_BUZ:
210                         return PLAYBACK_BUZ_TITLE;
211                         break;
212                 case VIDEO4LINUX:
213                         return VIDEO4LINUX_TITLE;
214                         break;
215                 case SCREENCAPTURE:
216                         return SCREENCAPTURE_TITLE;
217                         break;
218                 case CAPTURE_BUZ:
219                         return CAPTURE_BUZ_TITLE;
220                         break;
221                 case CAPTURE_FIREWIRE:
222                         return CAPTURE_FIREWIRE_TITLE;
223                         break;
224         }
225         return "";
228 int VideoDevice::is_compressed()
230         return is_compressed(in_config->driver);
233 int VideoDevice::get_best_colormodel(Asset *asset)
235         if(input_base)
236                 return input_base->get_best_colormodel(asset);
237         else
238                 return BC_RGB888;
241 int VideoDevice::close_all()
243         int i;
245 //printf("VideoDevice::close_all 1\n");
246         if(w)
247         {
248                 if(output_base)
249                 {
250                         output_base->close_all();
251                         delete output_base;
252                 }
253         }
255 //printf("VideoDevice::close_all 2\n");
256         if(r && capturing)
257         {
258                 capturing = 0;
259                 if(input_base)
260                 {
261                         input_base->close_all();
262                         delete input_base;
263                         input_base = 0;
264                 }
266                 if(keepalive)
267                 {
268                         keepalive->stop();
269                         delete keepalive;
270                 }
271         }
273 //printf("VideoDevice::close_all 3\n");
274         input_sources.remove_all_objects();
276 //printf("VideoDevice::close_all 4\n");
277         initialize();
279 //printf("VideoDevice::close_all 5\n");
280         return 0;
284 int VideoDevice::set_adevice(AudioDevice *adevice)
286         this->adevice = adevice;
287         return 0;
291 // int VideoDevice::stop_sharing()
292 // {
293 //      if(sharing)
294 //      {
295 //              sharing_lock.lock();
296 //              done_sharing = 1;
297 //              if(input_base) input_base->stop_sharing();
298 //      }
299 //      return 0;
300 // }
301 // 
303 // int VideoDevice::get_shared_data(unsigned char *data, long size)
304 // {
305 //      if(input_base)
306 //      {
307 //              input_base->get_shared_data(data, size);
308 //      }
309 //      return 0;
310 // }
312 void VideoDevice::create_channeldb(ArrayList<Channel*> *channeldb)
314         if(input_base)
315                 input_base->create_channeldb(channeldb);
318 ArrayList<char *>* VideoDevice::get_inputs()
320         return &input_sources;
323 int VideoDevice::get_failed()
325         if(keepalive)
326                 return keepalive->get_failed();
327         else
328                 return 0;
331 int VideoDevice::interrupt_crash()
333         if(input_base) return input_base->interrupt_crash();
334         return 0;
337 int VideoDevice::set_translation(int input_x, int input_y)
339         this->input_x = input_x;
340         this->input_y = input_y;
341         return 0;
344 int VideoDevice::set_field_order(int odd_field_first)
346         this->odd_field_first = odd_field_first;
347         return 0;
350 int VideoDevice::set_channel(Channel *channel)
352         if(input_base) return input_base->set_channel(channel);
353         if(output_base) return output_base->set_channel(channel);
356 void VideoDevice::set_quality(int quality)
358         this->quality = quality;
361 void VideoDevice::set_cpus(int cpus)
363         this->cpus = cpus;
366 int VideoDevice::set_picture(int brightness, 
367         int hue, 
368         int color, 
369         int contrast, 
370         int whiteness)
372         if(input_base) return input_base->set_picture(brightness, 
373                         hue, 
374                         color, 
375                         contrast, 
376                         whiteness);
379 int VideoDevice::update_translation()
381         float frame_in_capture_x1f, frame_in_capture_x2f, frame_in_capture_y1f, frame_in_capture_y2f;
382         float capture_in_frame_x1f, capture_in_frame_x2f, capture_in_frame_y1f, capture_in_frame_y2f;
383         int z_changed = 0;
385         if(frame_resized)
386         {
387                 input_x = new_input_x;
388                 input_y = new_input_y;
390                 if(in_config->driver == VIDEO4LINUX || in_config->driver == VIDEO4LINUX2)
391                 {
392                         if(input_z != new_input_z)
393                         {
394                                 input_z = new_input_z;
395                                 z_changed = 1;
397                                 capture_w = (int)((float)in_config->w * input_z + 0.5);
398                                 capture_h = (int)((float)in_config->h * input_z + 0.5);
400 // Need to align to multiple of 4
401                                 capture_w &= ~3;
402                                 capture_h &= ~3;
403                         }
405                         frame_in_capture_x1f = (float)input_x * input_z + capture_w / 2 - in_config->w / 2;
406                         frame_in_capture_x2f = (float)input_x * input_z  + capture_w / 2 + in_config->w / 2;
407                         frame_in_capture_y1f = (float)input_y * input_z  + capture_h / 2 - in_config->h / 2;
408                         frame_in_capture_y2f = (float)input_y * input_z  + capture_h / 2 + in_config->h / 2;
410                         capture_in_frame_x1f = 0;
411                         capture_in_frame_y1f = 0;
412                         capture_in_frame_x2f = in_config->w;
413                         capture_in_frame_y2f = in_config->h;
415                         if(frame_in_capture_x1f < 0) { capture_in_frame_x1f -= frame_in_capture_x1f; frame_in_capture_x1f = 0; }
416                         if(frame_in_capture_y1f < 0) { capture_in_frame_y1f -= frame_in_capture_y1f; frame_in_capture_y1f = 0; }
417                         if(frame_in_capture_x2f > capture_w) { capture_in_frame_x2f -= frame_in_capture_x2f - capture_w; frame_in_capture_x2f = capture_w; }
418                         if(frame_in_capture_y2f > capture_h) { capture_in_frame_y2f -= frame_in_capture_y2f - capture_h; frame_in_capture_y2f = capture_h; }
420                         frame_in_capture_x1 = (int)frame_in_capture_x1f;
421                         frame_in_capture_y1 = (int)frame_in_capture_y1f;
422                         frame_in_capture_x2 = (int)frame_in_capture_x2f;
423                         frame_in_capture_y2 = (int)frame_in_capture_y2f;
425                         capture_in_frame_x1 = (int)capture_in_frame_x1f;
426                         capture_in_frame_y1 = (int)capture_in_frame_y1f;
427                         capture_in_frame_x2 = (int)capture_in_frame_x2f;
428                         capture_in_frame_y2 = (int)capture_in_frame_y2f;
430                         frame_resized = 0;
431                 }
432         }
433         return 0;
436 int VideoDevice::set_latency_counter(int value)
438         latency_counter = value;
439         return 0;
442 int VideoDevice::read_buffer(VFrame *frame)
444         int result = 0;
445         if(!capturing) return 0;
447 //printf("VideoDevice::read_buffer %p %p\n", frame, input_base);
448         if(input_base)
449         {
450 // Reset the keepalive thread
451                 if(keepalive) keepalive->capturing = 1;
452                 result = input_base->read_buffer(frame);
453                 if(keepalive)
454                 {
455                         keepalive->capturing = 0;
456                         keepalive->reset_keepalive();
457                 }
458                 return result;
459         }
461         return 0;
465 // ================================= OUTPUT ==========================================
468 int VideoDevice::open_output(VideoOutConfig *config, 
469                                         float rate, 
470                                         int out_w, 
471                                         int out_h,
472                                         Canvas *output,
473                                         int single_frame)
475         w = 1;
476 //printf("VideoDevice::open_output 1 %d\n", out_config->driver);
477         *this->out_config = *config;
478 //printf("VideoDevice::open_output 1 %d\n", out_config->driver);
479         this->out_w = out_w;
480         this->out_h = out_h;
481         this->orate = rate;
482         this->single_frame = single_frame;
484 //printf("VideoDevice::open_output 1 %d\n", out_config->driver);
485         switch(out_config->driver)
486         {
487                 case PLAYBACK_BUZ:
488                         output_base = new VDeviceBUZ(this);
489                         break;
490                 case PLAYBACK_X11:
491                 case PLAYBACK_X11_XV:
492                         output_base = new VDeviceX11(this, output);
493                         break;
495                 case PLAYBACK_FIREWIRE:
496                         output_base = new VDevice1394(this);
497                         break;
498         }
499 //printf("VideoDevice::open_output 2 %d\n", out_config->driver);
501         if(output_base->open_output())
502         {
503                 delete output_base;
504                 output_base = 0;
505         }
506 //printf("VideoDevice::open_output 3 %d\n", out_config->driver);
508         if(output_base) 
509                 return 0;
510         else
511                 return 1;
516 int VideoDevice::start_playback()
518 // arm buffer before doing this
519         is_playing_back = 1;
520         interrupt = 0;
522         if(output_base) return output_base->start_playback();
523         return 1;
526 int VideoDevice::stop_playback()
528         if(output_base) output_base->stop_playback();
529         is_playing_back = 0;
530         interrupt = 0;
531         return 0;
534 void VideoDevice::goose_input()
536         if(input_base) input_base->goose_input();
539 void VideoDevice::new_output_buffers(VFrame **outputs, int colormodel)
541         for(int i = 0; i < MAX_CHANNELS; i++)
542                 outputs[i] = 0;
544         if(!output_base) return;
545         output_base->new_output_buffer(outputs, colormodel);
549 int VideoDevice::interrupt_playback()
551         interrupt = 1;
552         return 0;
555 int VideoDevice::write_buffer(VFrame **outputs, EDL *edl)
557 //printf("VideoDevice::write_buffer 1 %p\n", output_base);
558         if(output_base) return output_base->write_buffer(outputs, edl);
559         return 1;
562 int VideoDevice::output_visible()
564         if(output_base) return output_base->output_visible();
567 BC_Bitmap* VideoDevice::get_bitmap()
569         if(output_base) return output_base->get_bitmap();