Merge branch 'ct' of git.pipapo.org:cinelerra-ct into ct
[cinelerra_cv/ct.git] / cinelerra / recordmonitor.C
blobf965317754556f7be4a20f7db5aba08c59d0265b
1 #include "asset.h"
2 #include "bcsignals.h"
3 #include "channelpicker.h"
4 #include "condition.h"
5 #include "cursors.h"
6 #include "libdv.h"
7 #include "edl.h"
8 #include "edlsession.h"
9 #include "keys.h"
10 #include "language.h"
11 #include "meterpanel.h"
12 #include "mwindow.h"
13 #include "playbackconfig.h"
14 #include "preferences.h"
15 #include "record.h"
16 #include "recordconfig.h"
17 #include "recordgui.h"
18 #include "recordtransport.h"
19 #include "recordmonitor.h"
20 #include "mainsession.h"
21 #include "theme.h"
22 #include "videodevice.inc"
23 #include "vframe.h"
24 #include "videodevice.h"
27 RecordMonitor::RecordMonitor(MWindow *mwindow, Record *record)
28  : Thread(1)
30         this->mwindow = mwindow;
31         this->record = record;
32         device = 0;
33         thread = 0;
37 RecordMonitor::~RecordMonitor()
39         if(thread)
40         {
41                 thread->stop_playback();
42                 delete thread;
43         }
44         window->set_done(0);
45         Thread::join();
46         if(device) 
47         {
48                 device->close_all();
49                 delete device;
50         }
51         delete window;
54 int RecordMonitor::create_objects()
56         int min_w = 150;
57         mwindow->session->rwindow_fullscreen = 0;
59         if(!record->default_asset->video_data)
60                 min_w = MeterPanel::get_meters_width(
61                         record->default_asset->channels, 1);
62 SET_TRACE
63         window = new RecordMonitorGUI(mwindow,
64                 record, 
65                 this,
66                 min_w);
67 SET_TRACE
68         window->create_objects();
69 SET_TRACE
71         if(record->default_asset->video_data)
72         {
73 // Configure the output for record monitoring
74                 VideoOutConfig config;
75 SET_TRACE
76                 device = new VideoDevice;
77 SET_TRACE
81 // Override default device for X11 drivers
82                 if(mwindow->edl->session->playback_config->vconfig->driver ==
83                         PLAYBACK_X11_XV) config.driver = PLAYBACK_X11_XV;
84                 config.x11_use_fields = 0;
86 SET_TRACE
88                 device->open_output(&config, 
89                                                 record->default_asset->frame_rate, 
90                                                 record->default_asset->width, 
91                                                 record->default_asset->height,
92                                                 window->canvas,
93                                                 0);
94 SET_TRACE
96                 thread = new RecordMonitorThread(mwindow, record, this);
97 SET_TRACE
98                 thread->start_playback();
99 SET_TRACE
100         }
101 SET_TRACE
103         Thread::start();
104         return 0;
108 void RecordMonitor::run()
110         window->run_window();
111         close_threads();
114 int RecordMonitor::close_threads()
116         if(window->channel_picker) window->channel_picker->close_threads();
119 int RecordMonitor::update(VFrame *vframe)
121         return thread->write_frame(vframe);
124 void RecordMonitor::update_channel(char *text)
126         if(window->channel_picker)
127                 window->channel_picker->channel_text->update(text);
130 int RecordMonitor::get_mbuttons_height()
132         return RECBUTTON_HEIGHT;
135 int RecordMonitor::fix_size(int &w, int &h, int width_given, float aspect_ratio)
137         w = width_given;
138         h = (int)((float)width_given / aspect_ratio);
141 float RecordMonitor::get_scale(int w)
143         if(mwindow->edl->get_aspect_ratio() > 
144                 (float)record->frame_w / record->frame_h)
145         {
146                 return (float)w / 
147                         ((float)record->frame_h * 
148                         mwindow->edl->get_aspect_ratio());
149         }
150         else
151         {
152                 return (float)w / record->frame_w;
153         }
156 int RecordMonitor::get_canvas_height()
158         return window->get_h() - get_mbuttons_height();
161 int RecordMonitor::get_channel_x()
163 //      return 240;
164         return 5;
167 int RecordMonitor::get_channel_y()
169         return 2;
181 RecordMonitorGUI::RecordMonitorGUI(MWindow *mwindow,
182         Record *record, 
183         RecordMonitor *thread,
184         int min_w)
185  : BC_Window(PROGRAM_NAME ": Video in", 
186                         mwindow->session->rmonitor_x,
187                         mwindow->session->rmonitor_y,
188                         mwindow->session->rmonitor_w, 
189                         mwindow->session->rmonitor_h, 
190                         min_w, 
191                         50, 
192                         1, 
193                         1,
194                         1)
196 //printf("%d %d\n", mwindow->session->rmonitor_w, mwindow->theme->rmonitor_meter_x);
197         this->mwindow = mwindow;
198         this->thread = thread;
199         this->record = record;
200 #ifdef HAVE_FIREWIRE
201         avc = 0;
202         avc1394_transport = 0;
203         avc1394transport_title = 0;
204         avc1394transport_timecode = 0;
205         avc1394transport_thread = 0;
206 #endif
207         bitmap = 0;
208         channel_picker = 0;
209         reverse_interlace = 0;
210         meters = 0;
211         canvas = 0;
212         current_operation = MONITOR_NONE;
215 RecordMonitorGUI::~RecordMonitorGUI()
217         delete canvas;
218         if(bitmap) delete bitmap;
219         if(channel_picker) delete channel_picker;
220 #ifdef HAVE_FIREWIRE
221         if(avc1394transport_thread)
222                 delete avc1394transport_thread;
223         if(avc)
224         {
225                 delete avc;
226         }
227         if(avc1394_transport)
228         {
229                 delete avc1394_transport;
230         }
231         if(avc1394transport_title)
232                 delete avc1394transport_title;
233 #endif
236 int RecordMonitorGUI::create_objects()
238 // y offset for video canvas if we have the transport controls
239         int do_channel = (mwindow->edl->session->vconfig_in->driver == VIDEO4LINUX ||
240                         mwindow->edl->session->vconfig_in->driver == CAPTURE_BUZ ||
241                         mwindow->edl->session->vconfig_in->driver == VIDEO4LINUX2 ||
242                         mwindow->edl->session->vconfig_in->driver == VIDEO4LINUX2JPEG);
243         int do_interlace = (mwindow->edl->session->vconfig_in->driver == CAPTURE_BUZ ||
244                 mwindow->edl->session->vconfig_in->driver == VIDEO4LINUX2JPEG);
245         int background_done = 0;
247         mwindow->theme->get_rmonitor_sizes(record->default_asset->audio_data, 
248                 record->default_asset->video_data,
249                 do_channel,
250                 do_interlace,
251                 0,
252                 record->default_asset->channels);
259         if(record->default_asset->video_data)
260         {
261                 int driver = mwindow->edl->session->vconfig_in->driver;
263 #ifdef HAVE_FIREWIRE
264                 if(driver == CAPTURE_FIREWIRE ||
265                         driver == CAPTURE_IEC61883)
266                 {
267                         avc = new AVC1394Control;
268                         if(avc->device > -1)
269                         {
270                                 mwindow->theme->get_rmonitor_sizes(record->default_asset->audio_data, 
271                                         record->default_asset->video_data,
272                                         do_channel,
273                                         do_interlace,
274                                         1,
275                                         record->default_asset->channels);
276                                 mwindow->theme->draw_rmonitor_bg(this);
277                                 background_done = 1;
279                                 avc1394_transport = new AVC1394Transport(mwindow,
280                                         avc,
281                                         this,
282                                         mwindow->theme->rmonitor_tx_x,
283                                         mwindow->theme->rmonitor_tx_y);
284                                 avc1394_transport->create_objects();
286                                 add_subwindow(avc1394transport_timecode =
287                                         new BC_Title(avc1394_transport->x_end,
288                                                 mwindow->theme->rmonitor_tx_y + 10,
289                                                 _("00:00:00:00"),
290                                                 MEDIUM_7SEGMENT,
291                                                 BLACK));
293                                 avc1394transport_thread =
294                                         new AVC1394TransportThread(avc1394transport_timecode,
295                                                 avc);
297                                 avc1394transport_thread->start();
299                         }
300                 }
301 #endif
304                 if(!background_done)
305                 {
306                         mwindow->theme->draw_rmonitor_bg(this);
307                         background_done = 1;
308                 }
310                 mwindow->theme->rmonitor_canvas_w = MAX(10, mwindow->theme->rmonitor_canvas_w);
311                 mwindow->theme->rmonitor_canvas_h = MAX(10, mwindow->theme->rmonitor_canvas_h);
312                 canvas = new RecordMonitorCanvas(mwindow, 
313                         this,
314                         record, 
315                         mwindow->theme->rmonitor_canvas_x, 
316                         mwindow->theme->rmonitor_canvas_y, 
317                         mwindow->theme->rmonitor_canvas_w, 
318                         mwindow->theme->rmonitor_canvas_h);
319                 canvas->create_objects(0);
321                 if(driver == VIDEO4LINUX ||
322                         driver == CAPTURE_BUZ ||
323                         driver == VIDEO4LINUX2 ||
324                         driver == VIDEO4LINUX2JPEG)
325                 {
326                         channel_picker = new RecordChannelPicker(mwindow,
327                                 record,
328                                 thread,
329                                 this,
330                                 record->channeldb,
331                                 mwindow->theme->rmonitor_channel_x, 
332                                 mwindow->theme->rmonitor_channel_y);
333                         channel_picker->create_objects();
334                 }
336                 if(driver == CAPTURE_BUZ ||
337                         driver == VIDEO4LINUX2JPEG)
338                 {
339                         add_subwindow(reverse_interlace = new ReverseInterlace(record,
340                                 mwindow->theme->rmonitor_interlace_x, 
341                                 mwindow->theme->rmonitor_interlace_y));
342                 }
343                 
344                 add_subwindow(monitor_menu = new BC_PopupMenu(0, 
345                         0, 
346                         0, 
347                         "", 
348                         0));
349                 monitor_menu->add_item(new RecordMonitorFullsize(mwindow, 
350                         this));
351         }
354         if(!background_done)
355         {
356                 mwindow->theme->draw_rmonitor_bg(this);
357                 background_done = 1;
358         }
360         if(record->default_asset->audio_data)
361         {
362                 meters = new MeterPanel(mwindow, 
363                         this,
364                         mwindow->theme->rmonitor_meter_x,
365                         mwindow->theme->rmonitor_meter_y,
366                         mwindow->theme->rmonitor_meter_h,
367                         record->default_asset->channels,
368                         1,
369                         1);
370                 meters->create_objects();
371         }
372         return 0;
375 int RecordMonitorGUI::button_press_event()
377         if(mwindow->session->rwindow_fullscreen && canvas && canvas->get_canvas())
378                 return canvas->button_press_event_base(canvas->get_canvas());
379                 
380         if(get_buttonpress() == 2)
381         {
382                 return 0;
383         }
384         else
385 // Right button
386         if(get_buttonpress() == 3)
387         {
388                 monitor_menu->activate_menu();
389                 return 1;
390         }
391         return 0;
394 int RecordMonitorGUI::cursor_leave_event()
396         if(canvas && canvas->get_canvas())
397                 return canvas->cursor_leave_event_base(canvas->get_canvas());
398         return 0;
401 int RecordMonitorGUI::cursor_enter_event()
403         if(canvas && canvas->get_canvas())
404                 return canvas->cursor_enter_event_base(canvas->get_canvas());
405         return 0;
408 int RecordMonitorGUI::button_release_event()
410         if(canvas && canvas->get_canvas())
411                 return canvas->button_release_event();
412         return 0;
415 int RecordMonitorGUI::cursor_motion_event()
417 SET_TRACE
418         if(canvas && canvas->get_canvas())
419         {
420 SET_TRACE
421                 canvas->get_canvas()->unhide_cursor();
422 SET_TRACE
423                 return canvas->cursor_motion_event();
424         }
425         return 0;
428 int RecordMonitorGUI::keypress_event()
430         int result = 0;
431         switch(get_keypress())
432         {
433                 case LEFT:
434                         if(!ctrl_down()) 
435                         { 
436                                 record->record_gui->set_translation(--(record->video_x), record->video_y, record->video_zoom);
437                         }
438                         else
439                         {
440                                 record->video_zoom -= 0.1;
441                                 record->record_gui->set_translation(record->video_x, record->video_y, record->video_zoom);
442                         }
443                         result = 1;
444                         break;
445                 case RIGHT:
446                         if(!ctrl_down()) 
447                         { 
448                                 record->record_gui->set_translation(++(record->video_x), record->video_y, record->video_zoom);
449                         }
450                         else
451                         {
452                                 record->video_zoom += 0.1;
453                                 record->record_gui->set_translation(record->video_x, record->video_y, record->video_zoom);
454                         }
455                         result = 1;
456                         break;
457                 case UP:
458                         if(!ctrl_down()) 
459                         { 
460                                 record->record_gui->set_translation(record->video_x, --(record->video_y), record->video_zoom);
461                         }
462                         else
463                         {
464                                 record->video_zoom -= 0.1;
465                                 record->record_gui->set_translation(record->video_x, record->video_y, record->video_zoom);
466                         }
467                         result = 1;
468                         break;
469                 case DOWN:
470                         if(!ctrl_down()) 
471                         { 
472                                 record->record_gui->set_translation(record->video_x, ++(record->video_y), record->video_zoom);
473                         }
474                         else
475                         {
476                                 record->video_zoom += 0.1;
477                                 record->record_gui->set_translation(record->video_x, record->video_y, record->video_zoom);
478                         }
479                         result = 1;
480                         break;
481                 case 'w':
482                         close_event();
483                         break;
484                 default:
485                         result = canvas->keypress_event(this);
486 #ifdef HAVE_FIREWIRE
487                         if(!result && avc1394_transport)
488                                 result = avc1394_transport->keypress_event(get_keypress());
489 #endif
490                         break;
491         }
492         return result;
496 int RecordMonitorGUI::translation_event()
498 //printf("MWindowGUI::translation_event 1 %d %d\n", get_x(), get_y());
499         mwindow->session->rmonitor_x = get_x();
500         mwindow->session->rmonitor_y = get_y();
501         return 0;
504 int RecordMonitorGUI::resize_event(int w, int h)
506         int do_channel = (mwindow->edl->session->vconfig_in->driver == VIDEO4LINUX ||
507                         mwindow->edl->session->vconfig_in->driver == CAPTURE_BUZ ||
508                         mwindow->edl->session->vconfig_in->driver == VIDEO4LINUX2 ||
509                         mwindow->edl->session->vconfig_in->driver == VIDEO4LINUX2JPEG);
510         int do_interlace = (mwindow->edl->session->vconfig_in->driver == CAPTURE_BUZ ||
511                 mwindow->edl->session->vconfig_in->driver == VIDEO4LINUX2JPEG);
512         int do_avc = 0;
513 #ifdef HAVE_FIREWIRE
514         do_avc = avc1394_transport ? 1 : 0;
515 #endif
517         mwindow->session->rmonitor_x = get_x();
518         mwindow->session->rmonitor_y = get_y();
519         mwindow->session->rmonitor_w = w;
520         mwindow->session->rmonitor_h = h;
522         mwindow->theme->get_rmonitor_sizes(record->default_asset->audio_data, 
523                 record->default_asset->video_data,
524                 do_channel,
525                 do_interlace,
526                 do_avc,
527                 record->default_asset->channels);
528         mwindow->theme->draw_rmonitor_bg(this);
529         flash();
532 //      record_transport->reposition_window(mwindow->theme->rmonitor_tx_x,
533 //              mwindow->theme->rmonitor_tx_y);
534 #ifdef HAVE_FIREWIRE
535         if(avc1394_transport)
536         {
537                 avc1394_transport->reposition_window(mwindow->theme->rmonitor_tx_x,
538                         mwindow->theme->rmonitor_tx_y);
539         }
540 #endif
541         
542         if(channel_picker) channel_picker->reposition();
543         if(reverse_interlace) reverse_interlace->reposition_window(reverse_interlace->get_x(),
544                 reverse_interlace->get_y());
545         if(canvas && record->default_asset->video_data)
546         {
547                 canvas->reposition_window(0,
548                         mwindow->theme->rmonitor_canvas_x, 
549                         mwindow->theme->rmonitor_canvas_y, 
550                         mwindow->theme->rmonitor_canvas_w, 
551                         mwindow->theme->rmonitor_canvas_h);
552         }
554         if(record->default_asset->audio_data)
555         {
556                 meters->reposition_window(mwindow->theme->rmonitor_meter_x, 
557                         mwindow->theme->rmonitor_meter_y, 
558                         mwindow->theme->rmonitor_meter_h);
559         }
561         set_title();
562         BC_WindowBase::resize_event(w, h);
563         flash();
564         flush();
565         return 1;
568 int RecordMonitorGUI::set_title()
570 return 0;
571         char string[1024];
572         int scale;
574         scale = (int)(thread->get_scale(thread->record->video_window_w) * 100 + 0.5);
576         sprintf(string, PROGRAM_NAME ": Video in %d%%", scale);
577         BC_Window::set_title(string);
578         return 0;
581 int RecordMonitorGUI::close_event()
583         thread->record->monitor_video = 0;
584         thread->record->monitor_audio = 0;
585         thread->record->video_window_open = 0;
586         unlock_window();
588         record->record_gui->lock_window("RecordMonitorGUI::close_event");
589         if(record->record_gui->monitor_video) record->record_gui->monitor_video->update(0);
590         if(record->record_gui->monitor_audio) record->record_gui->monitor_audio->update(0);
591         record->record_gui->flush();
592         record->record_gui->unlock_window();
595         lock_window("RecordMonitorGUI::close_event");
596         hide_window();
597         return 0;
600 int RecordMonitorGUI::create_bitmap()
602         if(bitmap && 
603                 (bitmap->get_w() != get_w() || 
604                         bitmap->get_h() != thread->get_canvas_height()))
605         {
606                 delete bitmap;
607                 bitmap = 0;
608         }
610         if(!bitmap && canvas)
611         {
612 //              bitmap = canvas->new_bitmap(get_w(), thread->get_canvas_height());
613         }
614         return 0;
617 ReverseInterlace::ReverseInterlace(Record *record, int x, int y)
618  : BC_CheckBox(x, y, record->reverse_interlace, _("Swap fields"))
620         this->record = record;
623 ReverseInterlace::~ReverseInterlace()
627 int ReverseInterlace::handle_event()
629         record->reverse_interlace = get_value();
630         return 0;
633 RecordMonitorCanvas::RecordMonitorCanvas(MWindow *mwindow, 
634         RecordMonitorGUI *window, 
635         Record *record, 
636         int x, 
637         int y, 
638         int w, 
639         int h)
640  : Canvas(mwindow,
641         window, 
642         x, 
643         y, 
644         w, 
645         h, 
646         record->default_asset->width,
647         record->default_asset->height,
648         0,
649         0,
650         1)
652         this->window = window;
653         this->mwindow = mwindow;
654         this->record = record;
655 printf("RecordMonitorCanvas::RecordMonitorCanvas 1 %d %d %d %d\n", 
656 x, y, w, h);
657 //printf("RecordMonitorCanvas::RecordMonitorCanvas 2\n");
660 RecordMonitorCanvas::~RecordMonitorCanvas()
664 int RecordMonitorCanvas::get_output_w()
666         return record->default_asset->width;
669 int RecordMonitorCanvas::get_output_h()
671         return record->default_asset->height;
675 int RecordMonitorCanvas::button_press_event()
678         if(Canvas::button_press_event()) return 1;
679         
680         if(mwindow->edl->session->vconfig_in->driver == SCREENCAPTURE)
681         {
682                 window->current_operation = MONITOR_TRANSLATE;
683                 window->translate_x_origin = record->video_x;
684                 window->translate_y_origin = record->video_y;
685                 window->cursor_x_origin = get_cursor_x();
686                 window->cursor_y_origin = get_cursor_y();
687         }
689         return 0;
692 void RecordMonitorCanvas::zoom_resize_window(float percentage)
694         int canvas_w, canvas_h;
695         calculate_sizes(mwindow->edl->get_aspect_ratio(), 
696                 record->default_asset->width, 
697                 record->default_asset->height, 
698                 percentage,
699                 canvas_w,
700                 canvas_h);
701         int new_w, new_h;
702         new_w = canvas_w + (window->get_w() - mwindow->theme->rmonitor_canvas_w);
703         new_h = canvas_h + (window->get_h() - mwindow->theme->rmonitor_canvas_h);
704         window->resize_window(new_w, new_h);
705         window->resize_event(new_w, new_h);
708 int RecordMonitorCanvas::get_fullscreen()
710         return mwindow->session->rwindow_fullscreen;
713 void RecordMonitorCanvas::set_fullscreen(int value)
715         mwindow->session->rwindow_fullscreen = value;
719 int RecordMonitorCanvas::button_release_event()
721         window->current_operation = MONITOR_NONE;
722         return 0;
725 int RecordMonitorCanvas::cursor_motion_event()
727 SET_TRACE
728         if(window->current_operation == MONITOR_TRANSLATE)
729         {
730 SET_TRACE
731                 record->set_translation(
732                         get_cursor_x() - window->cursor_x_origin + window->translate_x_origin,
733                         get_cursor_y() - window->cursor_y_origin + window->translate_y_origin);
734 SET_TRACE
735         }
737         return 0;
740 int RecordMonitorCanvas::cursor_enter_event()
742         if(mwindow->edl->session->vconfig_in->driver == SCREENCAPTURE)
743                 set_cursor(MOVE_CURSOR);
744         return 0;
747 void RecordMonitorCanvas::reset_translation()
749         record->set_translation(0, 0);
752 int RecordMonitorCanvas::keypress_event()
754         int result = 0;
755         switch(get_canvas() && get_canvas()->get_keypress())
756         {
757                 case LEFT:
758                         record->set_translation(--record->video_x, record->video_y);
759                         break;
760                 case RIGHT:
761                         record->set_translation(++record->video_x, record->video_y);
762                         break;
763                 case UP:
764                         record->set_translation(record->video_x, --record->video_y);
765                         break;
766                 case DOWN:
767                         record->set_translation(record->video_x, ++record->video_y);
768                         break;
769         }
770         return result;
774 RecordMonitorFullsize::RecordMonitorFullsize(MWindow *mwindow, 
775         RecordMonitorGUI *window)
776  : BC_MenuItem(_("Zoom 100%"))
778         this->mwindow = mwindow;
779         this->window = window;
781 int RecordMonitorFullsize::handle_event()
783         return 1;
793 // ================================== slippery playback ============================
796 RecordMonitorThread::RecordMonitorThread(MWindow *mwindow, 
797         Record *record, 
798         RecordMonitor *record_monitor)
799  : Thread(1, 0, 0)
801         this->mwindow = mwindow;
802         this->record_monitor = record_monitor;
803         this->record = record;
804         reset_parameters();
805         output_lock = new Condition(1, "RecordMonitor::output_lock");
806         input_lock = new Condition(1, "RecordMonitor::input_lock");
810 void RecordMonitorThread::reset_parameters()
812         input_frame = 0;
813         output_frame = 0;
814         shared_data = 0;
815         jpeg_engine = 0;
816         dv_engine = 0;
817         ready = 0;
821 RecordMonitorThread::~RecordMonitorThread()
823         if(input_frame && !shared_data) delete input_frame;
824         delete output_lock;
825         delete input_lock;
828 void RecordMonitorThread::init_output_format()
830         long offset;
832 //printf("RecordMonitorThread::init_output_format 1\n");
833         switch(mwindow->edl->session->vconfig_in->driver)
834         {
835                 case SCREENCAPTURE:
836                         output_colormodel = record->vdevice->get_best_colormodel(record->default_asset);
837                         break;
838         
839         
840                 case CAPTURE_BUZ:
841                 case VIDEO4LINUX2JPEG:
842                         jpeg_engine = new RecVideoMJPGThread(record, this);
843                         jpeg_engine->start_rendering();
844                         output_colormodel = BC_YUV422P;
845                         break;
847                 case CAPTURE_FIREWIRE:
848                 case CAPTURE_IEC61883:
849                         dv_engine = new RecVideoDVThread(record, this);
850                         dv_engine->start_rendering();
851                         output_colormodel = BC_YUV422P;
852                         break;
854                 case VIDEO4LINUX:
855                 case VIDEO4LINUX2:
856                         output_colormodel = record->vdevice->get_best_colormodel(record->default_asset);
857 //printf("RecordMonitorThread::init_output_format 2 %d\n", output_colormodel);
858                         break;
859         }
862 int RecordMonitorThread::start_playback()
864         ready = 1;
865         done = 0;
866         output_lock->lock("RecordMonitorThread::start_playback");
867         Thread::start();
868         return 0;
871 int RecordMonitorThread::stop_playback()
873         done = 1;
874         output_lock->unlock();
875         Thread::join();
876 //printf("RecordMonitorThread::stop_playback 1\n");
878         switch(mwindow->edl->session->vconfig_in->driver)
879         {
880                 case CAPTURE_BUZ:
881                 case VIDEO4LINUX2JPEG:
882                         if(jpeg_engine) 
883                         {
884                                 jpeg_engine->stop_rendering();
885                                 delete jpeg_engine;
886                         }
887                         break;
889                 case CAPTURE_FIREWIRE:
890                 case CAPTURE_IEC61883:
891                         if(dv_engine)
892                         {
893                                 dv_engine->stop_rendering();
894                                 delete dv_engine;
895                         }
896                         break;
897         }
898 //printf("RecordMonitorThread::stop_playback 4\n");
900         return 0;
903 int RecordMonitorThread::write_frame(VFrame *new_frame)
905         if(ready)
906         {
907                 ready = 0;
908                 shared_data = (new_frame->get_color_model() != BC_COMPRESSED);
911 // Need to wait until after Record creates the input device before starting monitor
912 // because the input device deterimes the output format.
913 // First time
914                 if(!output_frame) init_output_format();
915                 if(!shared_data)
916                 {
917                         if(!input_frame) input_frame = new VFrame;
918                         input_frame->allocate_compressed_data(new_frame->get_compressed_size());
919                         memcpy(input_frame->get_data(), 
920                                 new_frame->get_data(), 
921                                 new_frame->get_compressed_size());
922                         input_frame->set_compressed_size(new_frame->get_compressed_size());
923                         input_frame->set_field2_offset(new_frame->get_field2_offset());
924                 }
925                 else
926                 {
927                         input_lock->lock("RecordMonitorThread::write_frame");
928                         input_frame = new_frame;
929                 }
930                 output_lock->unlock();
931         }
932         return 0;
935 int RecordMonitorThread::render_jpeg()
937 //printf("RecordMonitorThread::render_jpeg 1\n");
938         jpeg_engine->render_frame(input_frame, input_frame->get_compressed_size());
939 //printf("RecordMonitorThread::render_jpeg 2\n");
940         return 0;
943 int RecordMonitorThread::render_dv()
945         dv_engine->render_frame(input_frame, input_frame->get_compressed_size());
946         return 0;
949 void RecordMonitorThread::render_uncompressed()
951         output_frame->copy_from(input_frame);
954 void RecordMonitorThread::show_output_frame()
956         record_monitor->device->write_buffer(output_frame, record->edl);
959 void RecordMonitorThread::unlock_input()
961         if(shared_data) input_lock->unlock();
964 int RecordMonitorThread::render_frame()
966         switch(mwindow->edl->session->vconfig_in->driver)
967         {
968                 case CAPTURE_BUZ:
969                 case VIDEO4LINUX2JPEG:
970                         render_jpeg();
971                         break;
973                 case CAPTURE_FIREWIRE:
974                 case CAPTURE_IEC61883:
975                         render_dv();
976                         break;
978                 default:
979                         render_uncompressed();
980                         break;
981         }
983         return 0;
986 void RecordMonitorThread::new_output_frame()
988         long offset;
989         record_monitor->device->new_output_buffer(&output_frame, output_colormodel);
992 void RecordMonitorThread::run()
994 //printf("RecordMonitorThread::run 1 %d\n", getpid());
995         while(!done)
996         {
997 // Wait for next frame
998 SET_TRACE
999                 output_lock->lock("RecordMonitorThread::run");
1001                 if(done)
1002                 {
1003                         unlock_input();
1004                         return;
1005                 }
1007 SET_TRACE
1008                 new_output_frame();
1009 SET_TRACE
1010                 render_frame();
1011 SET_TRACE
1012                 show_output_frame();
1013 SET_TRACE
1014                 unlock_input();
1015 // Get next frame
1016                 ready = 1;
1017         }
1022 RecVideoMJPGThread::RecVideoMJPGThread(Record *record, RecordMonitorThread *thread)
1024         this->record = record;
1025         this->thread = thread;
1026         mjpeg = 0;
1029 RecVideoMJPGThread::~RecVideoMJPGThread()
1033 int RecVideoMJPGThread::start_rendering()
1035         mjpeg = mjpeg_new(record->default_asset->width, 
1036                 record->default_asset->height, 
1037                 2);
1038 //printf("RecVideoMJPGThread::start_rendering 1 %p\n", mjpeg);
1039         return 0;
1042 int RecVideoMJPGThread::stop_rendering()
1044 //printf("RecVideoMJPGThread::stop_rendering 1 %p\n", mjpeg);
1045         if(mjpeg) mjpeg_delete(mjpeg);
1046 //printf("RecVideoMJPGThread::stop_rendering 2\n");
1047         return 0;
1050 int RecVideoMJPGThread::render_frame(VFrame *frame, long size)
1052 // printf("RecVideoMJPGThread::render_frame %d %02x%02x %02x%02x\n", 
1053 // frame->get_field2_offset(), 
1054 // frame->get_data()[0], 
1055 // frame->get_data()[1], 
1056 // frame->get_data()[frame->get_field2_offset()], 
1057 // frame->get_data()[frame->get_field2_offset() + 1]);
1058 //frame->set_field2_offset(0);
1059         mjpeg_decompress(mjpeg, 
1060                 frame->get_data(), 
1061                 frame->get_compressed_size(), 
1062                 frame->get_field2_offset(), 
1063                 thread->output_frame->get_rows(), 
1064                 thread->output_frame->get_y(), 
1065                 thread->output_frame->get_u(), 
1066                 thread->output_frame->get_v(),
1067                 thread->output_frame->get_color_model(),
1068                 record->mwindow->preferences->processors);
1069         return 0;
1075 RecVideoDVThread::RecVideoDVThread(Record *record, RecordMonitorThread *thread)
1077         this->record = record;
1078         this->thread = thread;
1079         dv = 0;
1082 RecVideoDVThread::~RecVideoDVThread()
1087 int RecVideoDVThread::start_rendering()
1089         dv = dv_new();
1090         return 0;
1093 int RecVideoDVThread::stop_rendering()
1095         if(dv) dv_delete(((dv_t*)dv));
1096         return 0;
1099 int RecVideoDVThread::render_frame(VFrame *frame, long size)
1101         unsigned char *yuv_planes[3];
1102         yuv_planes[0] = thread->output_frame->get_y();
1103         yuv_planes[1] = thread->output_frame->get_u();
1104         yuv_planes[2] = thread->output_frame->get_v();
1105         dv_read_video(((dv_t*)dv), 
1106                 yuv_planes, 
1107                 frame->get_data(), 
1108                 frame->get_compressed_size(),
1109                 thread->output_frame->get_color_model());
1111         return 0;
1114 //      Local Variables:
1115 //      mode: C++
1116 //      c-file-style: "linux"
1117 //      End: