r856: Merge 2.1:
[cinelerra_cv/ct.git] / cinelerra / recordmonitor.C
blobf0c713110632f262a78336036391f37405bf22cd
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 ChannelPicker(mwindow,
327                                 record,
328                                 thread,
329                                 record->channeldb,
330                                 mwindow->theme->rmonitor_channel_x, 
331                                 mwindow->theme->rmonitor_channel_y);
332                         channel_picker->create_objects();
333                 }
335                 if(driver == CAPTURE_BUZ ||
336                         driver == VIDEO4LINUX2JPEG)
337                 {
338                         add_subwindow(reverse_interlace = new ReverseInterlace(record,
339                                 mwindow->theme->rmonitor_interlace_x, 
340                                 mwindow->theme->rmonitor_interlace_y));
341                 }
342                 
343                 add_subwindow(monitor_menu = new BC_PopupMenu(0, 
344                         0, 
345                         0, 
346                         "", 
347                         0));
348                 monitor_menu->add_item(new RecordMonitorFullsize(mwindow, 
349                         this));
350         }
353         if(!background_done)
354         {
355                 mwindow->theme->draw_rmonitor_bg(this);
356                 background_done = 1;
357         }
359         if(record->default_asset->audio_data)
360         {
361                 meters = new MeterPanel(mwindow, 
362                         this,
363                         mwindow->theme->rmonitor_meter_x,
364                         mwindow->theme->rmonitor_meter_y,
365                         mwindow->theme->rmonitor_meter_h,
366                         record->default_asset->channels,
367                         1,
368                         1);
369                 meters->create_objects();
370         }
371         return 0;
374 int RecordMonitorGUI::button_press_event()
376         if(mwindow->session->rwindow_fullscreen && canvas && canvas->get_canvas())
377                 return canvas->button_press_event_base(canvas->get_canvas());
378                 
379         if(get_buttonpress() == 2)
380         {
381                 return 0;
382         }
383         else
384 // Right button
385         if(get_buttonpress() == 3)
386         {
387                 monitor_menu->activate_menu();
388                 return 1;
389         }
390         return 0;
393 int RecordMonitorGUI::cursor_leave_event()
395         if(canvas && canvas->get_canvas())
396                 return canvas->cursor_leave_event_base(canvas->get_canvas());
397         return 0;
400 int RecordMonitorGUI::cursor_enter_event()
402         if(canvas && canvas->get_canvas())
403                 return canvas->cursor_enter_event_base(canvas->get_canvas());
404         return 0;
407 int RecordMonitorGUI::button_release_event()
409         if(canvas && canvas->get_canvas())
410                 return canvas->button_release_event();
411         return 0;
414 int RecordMonitorGUI::cursor_motion_event()
416 SET_TRACE
417         if(canvas && canvas->get_canvas())
418         {
419 SET_TRACE
420                 canvas->get_canvas()->unhide_cursor();
421 SET_TRACE
422                 return canvas->cursor_motion_event();
423         }
424         return 0;
427 int RecordMonitorGUI::keypress_event()
429         int result = 0;
430         switch(get_keypress())
431         {
432                 case LEFT:
433                         if(!ctrl_down()) 
434                         { 
435                                 record->record_gui->set_translation(--(record->video_x), record->video_y, record->video_zoom);
436                         }
437                         else
438                         {
439                                 record->video_zoom -= 0.1;
440                                 record->record_gui->set_translation(record->video_x, record->video_y, record->video_zoom);
441                         }
442                         result = 1;
443                         break;
444                 case RIGHT:
445                         if(!ctrl_down()) 
446                         { 
447                                 record->record_gui->set_translation(++(record->video_x), record->video_y, record->video_zoom);
448                         }
449                         else
450                         {
451                                 record->video_zoom += 0.1;
452                                 record->record_gui->set_translation(record->video_x, record->video_y, record->video_zoom);
453                         }
454                         result = 1;
455                         break;
456                 case UP:
457                         if(!ctrl_down()) 
458                         { 
459                                 record->record_gui->set_translation(record->video_x, --(record->video_y), record->video_zoom);
460                         }
461                         else
462                         {
463                                 record->video_zoom -= 0.1;
464                                 record->record_gui->set_translation(record->video_x, record->video_y, record->video_zoom);
465                         }
466                         result = 1;
467                         break;
468                 case DOWN:
469                         if(!ctrl_down()) 
470                         { 
471                                 record->record_gui->set_translation(record->video_x, ++(record->video_y), record->video_zoom);
472                         }
473                         else
474                         {
475                                 record->video_zoom += 0.1;
476                                 record->record_gui->set_translation(record->video_x, record->video_y, record->video_zoom);
477                         }
478                         result = 1;
479                         break;
480                 case 'w':
481                         close_event();
482                         break;
483                 default:
484                         result = canvas->keypress_event(this);
485 #ifdef HAVE_FIREWIRE
486                         if(!result && avc1394_transport)
487                                 result = avc1394_transport->keypress_event(get_keypress());
488 #endif
489                         break;
490         }
491         return result;
495 int RecordMonitorGUI::translation_event()
497 //printf("MWindowGUI::translation_event 1 %d %d\n", get_x(), get_y());
498         mwindow->session->rmonitor_x = get_x();
499         mwindow->session->rmonitor_y = get_y();
500         return 0;
503 int RecordMonitorGUI::resize_event(int w, int h)
505         int do_channel = (mwindow->edl->session->vconfig_in->driver == VIDEO4LINUX ||
506                         mwindow->edl->session->vconfig_in->driver == CAPTURE_BUZ ||
507                         mwindow->edl->session->vconfig_in->driver == VIDEO4LINUX2 ||
508                         mwindow->edl->session->vconfig_in->driver == VIDEO4LINUX2JPEG);
509         int do_interlace = (mwindow->edl->session->vconfig_in->driver == CAPTURE_BUZ ||
510                 mwindow->edl->session->vconfig_in->driver == VIDEO4LINUX2JPEG);
511         int do_avc = 0;
512 #ifdef HAVE_FIREWIRE
513         do_avc = avc1394_transport ? 1 : 0;
514 #endif
516         mwindow->session->rmonitor_x = get_x();
517         mwindow->session->rmonitor_y = get_y();
518         mwindow->session->rmonitor_w = w;
519         mwindow->session->rmonitor_h = h;
521         mwindow->theme->get_rmonitor_sizes(record->default_asset->audio_data, 
522                 record->default_asset->video_data,
523                 do_channel,
524                 do_interlace,
525                 do_avc,
526                 record->default_asset->channels);
527         mwindow->theme->draw_rmonitor_bg(this);
528         flash();
531 //      record_transport->reposition_window(mwindow->theme->rmonitor_tx_x,
532 //              mwindow->theme->rmonitor_tx_y);
533 #ifdef HAVE_FIREWIRE
534         if(avc1394_transport)
535         {
536                 avc1394_transport->reposition_window(mwindow->theme->rmonitor_tx_x,
537                         mwindow->theme->rmonitor_tx_y);
538         }
539 #endif
540         
541         if(channel_picker) channel_picker->reposition();
542         if(reverse_interlace) reverse_interlace->reposition_window(reverse_interlace->get_x(),
543                 reverse_interlace->get_y());
544         if(canvas && record->default_asset->video_data)
545         {
546                 canvas->reposition_window(0,
547                         mwindow->theme->rmonitor_canvas_x, 
548                         mwindow->theme->rmonitor_canvas_y, 
549                         mwindow->theme->rmonitor_canvas_w, 
550                         mwindow->theme->rmonitor_canvas_h);
551         }
553         if(record->default_asset->audio_data)
554         {
555                 meters->reposition_window(mwindow->theme->rmonitor_meter_x, 
556                         mwindow->theme->rmonitor_meter_y, 
557                         mwindow->theme->rmonitor_meter_h);
558         }
560         set_title();
561         BC_WindowBase::resize_event(w, h);
562         flash();
563         flush();
564         return 1;
567 int RecordMonitorGUI::set_title()
569 return 0;
570         char string[1024];
571         int scale;
573         scale = (int)(thread->get_scale(thread->record->video_window_w) * 100 + 0.5);
575         sprintf(string, PROGRAM_NAME ": Video in %d%%", scale);
576         BC_Window::set_title(string);
577         return 0;
580 int RecordMonitorGUI::close_event()
582         thread->record->monitor_video = 0;
583         thread->record->monitor_audio = 0;
584         thread->record->video_window_open = 0;
585         unlock_window();
587         record->record_gui->lock_window("RecordMonitorGUI::close_event");
588         if(record->record_gui->monitor_video) record->record_gui->monitor_video->update(0);
589         if(record->record_gui->monitor_audio) record->record_gui->monitor_audio->update(0);
590         record->record_gui->flush();
591         record->record_gui->unlock_window();
594         lock_window("RecordMonitorGUI::close_event");
595         hide_window();
596         return 0;
599 int RecordMonitorGUI::create_bitmap()
601         if(bitmap && 
602                 (bitmap->get_w() != get_w() || 
603                         bitmap->get_h() != thread->get_canvas_height()))
604         {
605                 delete bitmap;
606                 bitmap = 0;
607         }
609         if(!bitmap && canvas)
610         {
611 //              bitmap = canvas->new_bitmap(get_w(), thread->get_canvas_height());
612         }
613         return 0;
616 ReverseInterlace::ReverseInterlace(Record *record, int x, int y)
617  : BC_CheckBox(x, y, record->reverse_interlace, _("Swap fields"))
619         this->record = record;
622 ReverseInterlace::~ReverseInterlace()
626 int ReverseInterlace::handle_event()
628         record->reverse_interlace = get_value();
629         return 0;
632 RecordMonitorCanvas::RecordMonitorCanvas(MWindow *mwindow, 
633         RecordMonitorGUI *window, 
634         Record *record, 
635         int x, 
636         int y, 
637         int w, 
638         int h)
639  : Canvas(mwindow,
640         window, 
641         x, 
642         y, 
643         w, 
644         h, 
645         record->default_asset->width,
646         record->default_asset->height,
647         0,
648         0,
649         1)
651         this->window = window;
652         this->mwindow = mwindow;
653         this->record = record;
654 printf("RecordMonitorCanvas::RecordMonitorCanvas 1 %d %d %d %d\n", 
655 x, y, w, h);
656 //printf("RecordMonitorCanvas::RecordMonitorCanvas 2\n");
659 RecordMonitorCanvas::~RecordMonitorCanvas()
663 int RecordMonitorCanvas::get_output_w()
665         return record->default_asset->width;
668 int RecordMonitorCanvas::get_output_h()
670         return record->default_asset->height;
674 int RecordMonitorCanvas::button_press_event()
677         if(Canvas::button_press_event()) return 1;
678         
679         if(mwindow->edl->session->vconfig_in->driver == SCREENCAPTURE)
680         {
681                 window->current_operation = MONITOR_TRANSLATE;
682                 window->translate_x_origin = record->video_x;
683                 window->translate_y_origin = record->video_y;
684                 window->cursor_x_origin = get_cursor_x();
685                 window->cursor_y_origin = get_cursor_y();
686         }
688         return 0;
691 void RecordMonitorCanvas::zoom_resize_window(float percentage)
693         int canvas_w, canvas_h;
694         calculate_sizes(mwindow->edl->get_aspect_ratio(), 
695                 record->default_asset->width, 
696                 record->default_asset->height, 
697                 percentage,
698                 canvas_w,
699                 canvas_h);
700         int new_w, new_h;
701         new_w = canvas_w + (window->get_w() - mwindow->theme->rmonitor_canvas_w);
702         new_h = canvas_h + (window->get_h() - mwindow->theme->rmonitor_canvas_h);
703         window->resize_window(new_w, new_h);
704         window->resize_event(new_w, new_h);
707 int RecordMonitorCanvas::get_fullscreen()
709         return mwindow->session->rwindow_fullscreen;
712 void RecordMonitorCanvas::set_fullscreen(int value)
714         mwindow->session->rwindow_fullscreen = value;
718 int RecordMonitorCanvas::button_release_event()
720         window->current_operation = MONITOR_NONE;
721         return 0;
724 int RecordMonitorCanvas::cursor_motion_event()
726 SET_TRACE
727         if(window->current_operation == MONITOR_TRANSLATE)
728         {
729 SET_TRACE
730                 record->set_translation(
731                         get_cursor_x() - window->cursor_x_origin + window->translate_x_origin,
732                         get_cursor_y() - window->cursor_y_origin + window->translate_y_origin);
733 SET_TRACE
734         }
736         return 0;
739 int RecordMonitorCanvas::cursor_enter_event()
741         if(mwindow->edl->session->vconfig_in->driver == SCREENCAPTURE)
742                 set_cursor(MOVE_CURSOR);
743         return 0;
746 void RecordMonitorCanvas::reset_translation()
748         record->set_translation(0, 0);
751 int RecordMonitorCanvas::keypress_event()
753         int result = 0;
754         switch(get_canvas() && get_canvas()->get_keypress())
755         {
756                 case LEFT:
757                         record->set_translation(--record->video_x, record->video_y);
758                         break;
759                 case RIGHT:
760                         record->set_translation(++record->video_x, record->video_y);
761                         break;
762                 case UP:
763                         record->set_translation(record->video_x, --record->video_y);
764                         break;
765                 case DOWN:
766                         record->set_translation(record->video_x, ++record->video_y);
767                         break;
768         }
769         return result;
773 RecordMonitorFullsize::RecordMonitorFullsize(MWindow *mwindow, 
774         RecordMonitorGUI *window)
775  : BC_MenuItem(_("Zoom 100%"))
777         this->mwindow = mwindow;
778         this->window = window;
780 int RecordMonitorFullsize::handle_event()
782         return 1;
792 // ================================== slippery playback ============================
795 RecordMonitorThread::RecordMonitorThread(MWindow *mwindow, 
796         Record *record, 
797         RecordMonitor *record_monitor)
798  : Thread(1, 0, 0)
800         this->mwindow = mwindow;
801         this->record_monitor = record_monitor;
802         this->record = record;
803         reset_parameters();
804         output_lock = new Condition(1, "RecordMonitor::output_lock");
805         input_lock = new Condition(1, "RecordMonitor::input_lock");
809 void RecordMonitorThread::reset_parameters()
811         input_frame = 0;
812         output_frame = 0;
813         shared_data = 0;
814         jpeg_engine = 0;
815         dv_engine = 0;
816         ready = 0;
820 RecordMonitorThread::~RecordMonitorThread()
822         if(input_frame && !shared_data) delete input_frame;
823         delete output_lock;
824         delete input_lock;
827 void RecordMonitorThread::init_output_format()
829         long offset;
831 //printf("RecordMonitorThread::init_output_format 1\n");
832         switch(mwindow->edl->session->vconfig_in->driver)
833         {
834                 case SCREENCAPTURE:
835                         output_colormodel = record->vdevice->get_best_colormodel(record->default_asset);
836                         break;
837         
838         
839                 case CAPTURE_BUZ:
840                 case VIDEO4LINUX2JPEG:
841                         jpeg_engine = new RecVideoMJPGThread(record, this);
842                         jpeg_engine->start_rendering();
843                         output_colormodel = BC_YUV422P;
844                         break;
846                 case CAPTURE_FIREWIRE:
847                 case CAPTURE_IEC61883:
848                         dv_engine = new RecVideoDVThread(record, this);
849                         dv_engine->start_rendering();
850                         output_colormodel = BC_YUV422P;
851                         break;
853                 case VIDEO4LINUX:
854                 case VIDEO4LINUX2:
855                         output_colormodel = record->vdevice->get_best_colormodel(record->default_asset);
856 //printf("RecordMonitorThread::init_output_format 2 %d\n", output_colormodel);
857                         break;
858         }
861 int RecordMonitorThread::start_playback()
863         ready = 1;
864         done = 0;
865         output_lock->lock("RecordMonitorThread::start_playback");
866         Thread::start();
867         return 0;
870 int RecordMonitorThread::stop_playback()
872         done = 1;
873         output_lock->unlock();
874         Thread::join();
875 //printf("RecordMonitorThread::stop_playback 1\n");
877         switch(mwindow->edl->session->vconfig_in->driver)
878         {
879                 case CAPTURE_BUZ:
880                 case VIDEO4LINUX2JPEG:
881                         if(jpeg_engine) 
882                         {
883                                 jpeg_engine->stop_rendering();
884                                 delete jpeg_engine;
885                         }
886                         break;
888                 case CAPTURE_FIREWIRE:
889                 case CAPTURE_IEC61883:
890                         if(dv_engine)
891                         {
892                                 dv_engine->stop_rendering();
893                                 delete dv_engine;
894                         }
895                         break;
896         }
897 //printf("RecordMonitorThread::stop_playback 4\n");
899         return 0;
902 int RecordMonitorThread::write_frame(VFrame *new_frame)
904         if(ready)
905         {
906                 ready = 0;
907                 shared_data = (new_frame->get_color_model() != BC_COMPRESSED);
910 // Need to wait until after Record creates the input device before starting monitor
911 // because the input device deterimes the output format.
912 // First time
913                 if(!output_frame) init_output_format();
914                 if(!shared_data)
915                 {
916                         if(!input_frame) input_frame = new VFrame;
917                         input_frame->allocate_compressed_data(new_frame->get_compressed_size());
918                         memcpy(input_frame->get_data(), 
919                                 new_frame->get_data(), 
920                                 new_frame->get_compressed_size());
921                         input_frame->set_compressed_size(new_frame->get_compressed_size());
922                         input_frame->set_field2_offset(new_frame->get_field2_offset());
923                 }
924                 else
925                 {
926                         input_lock->lock("RecordMonitorThread::write_frame");
927                         input_frame = new_frame;
928                 }
929                 output_lock->unlock();
930         }
931         return 0;
934 int RecordMonitorThread::render_jpeg()
936 //printf("RecordMonitorThread::render_jpeg 1\n");
937         jpeg_engine->render_frame(input_frame, input_frame->get_compressed_size());
938 //printf("RecordMonitorThread::render_jpeg 2\n");
939         return 0;
942 int RecordMonitorThread::render_dv()
944         dv_engine->render_frame(input_frame, input_frame->get_compressed_size());
945         return 0;
948 void RecordMonitorThread::render_uncompressed()
950         output_frame->copy_from(input_frame);
953 void RecordMonitorThread::show_output_frame()
955         record_monitor->device->write_buffer(output_frame, record->edl);
958 void RecordMonitorThread::unlock_input()
960         if(shared_data) input_lock->unlock();
963 int RecordMonitorThread::render_frame()
965         switch(mwindow->edl->session->vconfig_in->driver)
966         {
967                 case CAPTURE_BUZ:
968                 case VIDEO4LINUX2JPEG:
969                         render_jpeg();
970                         break;
972                 case CAPTURE_FIREWIRE:
973                 case CAPTURE_IEC61883:
974                         render_dv();
975                         break;
977                 default:
978                         render_uncompressed();
979                         break;
980         }
982         return 0;
985 void RecordMonitorThread::new_output_frame()
987         long offset;
988         record_monitor->device->new_output_buffer(&output_frame, output_colormodel);
991 void RecordMonitorThread::run()
993 //printf("RecordMonitorThread::run 1 %d\n", getpid());
994         while(!done)
995         {
996 // Wait for next frame
997 SET_TRACE
998                 output_lock->lock("RecordMonitorThread::run");
1000                 if(done)
1001                 {
1002                         unlock_input();
1003                         return;
1004                 }
1006 SET_TRACE
1007                 new_output_frame();
1008 SET_TRACE
1009                 render_frame();
1010 SET_TRACE
1011                 show_output_frame();
1012 SET_TRACE
1013                 unlock_input();
1014 // Get next frame
1015                 ready = 1;
1016         }
1021 RecVideoMJPGThread::RecVideoMJPGThread(Record *record, RecordMonitorThread *thread)
1023         this->record = record;
1024         this->thread = thread;
1025         mjpeg = 0;
1028 RecVideoMJPGThread::~RecVideoMJPGThread()
1032 int RecVideoMJPGThread::start_rendering()
1034         mjpeg = mjpeg_new(record->default_asset->width, 
1035                 record->default_asset->height, 
1036                 2);
1037 //printf("RecVideoMJPGThread::start_rendering 1 %p\n", mjpeg);
1038         return 0;
1041 int RecVideoMJPGThread::stop_rendering()
1043 //printf("RecVideoMJPGThread::stop_rendering 1 %p\n", mjpeg);
1044         if(mjpeg) mjpeg_delete(mjpeg);
1045 //printf("RecVideoMJPGThread::stop_rendering 2\n");
1046         return 0;
1049 int RecVideoMJPGThread::render_frame(VFrame *frame, long size)
1051 // printf("RecVideoMJPGThread::render_frame %d %02x%02x %02x%02x\n", 
1052 // frame->get_field2_offset(), 
1053 // frame->get_data()[0], 
1054 // frame->get_data()[1], 
1055 // frame->get_data()[frame->get_field2_offset()], 
1056 // frame->get_data()[frame->get_field2_offset() + 1]);
1057 //frame->set_field2_offset(0);
1058         mjpeg_decompress(mjpeg, 
1059                 frame->get_data(), 
1060                 frame->get_compressed_size(), 
1061                 frame->get_field2_offset(), 
1062                 thread->output_frame->get_rows(), 
1063                 thread->output_frame->get_y(), 
1064                 thread->output_frame->get_u(), 
1065                 thread->output_frame->get_v(),
1066                 thread->output_frame->get_color_model(),
1067                 record->mwindow->preferences->processors);
1068         return 0;
1074 RecVideoDVThread::RecVideoDVThread(Record *record, RecordMonitorThread *thread)
1076         this->record = record;
1077         this->thread = thread;
1078         dv = 0;
1081 RecVideoDVThread::~RecVideoDVThread()
1086 int RecVideoDVThread::start_rendering()
1088         dv = dv_new();
1089         return 0;
1092 int RecVideoDVThread::stop_rendering()
1094         if(dv) dv_delete(((dv_t*)dv));
1095         return 0;
1098 int RecVideoDVThread::render_frame(VFrame *frame, long size)
1100         unsigned char *yuv_planes[3];
1101         yuv_planes[0] = thread->output_frame->get_y();
1102         yuv_planes[1] = thread->output_frame->get_u();
1103         yuv_planes[2] = thread->output_frame->get_v();
1104         dv_read_video(((dv_t*)dv), 
1105                 yuv_planes, 
1106                 frame->get_data(), 
1107                 frame->get_compressed_size(),
1108                 thread->output_frame->get_color_model());
1110         return 0;