r851: Merge 2.1:
[cinelerra_cv/ct.git] / cinelerra / recordmonitor.C
blobb512167c0e011b1b2b4b48f8221e8a25945da329
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                 canvas = new RecordMonitorCanvas(mwindow, 
311                         this,
312                         record, 
313                         mwindow->theme->rmonitor_canvas_x, 
314                         mwindow->theme->rmonitor_canvas_y, 
315                         mwindow->theme->rmonitor_canvas_w, 
316                         mwindow->theme->rmonitor_canvas_h);
317                 canvas->create_objects(0);
319                 if(driver == VIDEO4LINUX ||
320                         driver == CAPTURE_BUZ ||
321                         driver == VIDEO4LINUX2 ||
322                         driver == VIDEO4LINUX2JPEG)
323                 {
324                         channel_picker = new ChannelPicker(mwindow,
325                                 record,
326                                 thread,
327                                 record->channeldb,
328                                 mwindow->theme->rmonitor_channel_x, 
329                                 mwindow->theme->rmonitor_channel_y);
330                         channel_picker->create_objects();
331                 }
333                 if(driver == CAPTURE_BUZ ||
334                         driver == VIDEO4LINUX2JPEG)
335                 {
336                         add_subwindow(reverse_interlace = new ReverseInterlace(record,
337                                 mwindow->theme->rmonitor_interlace_x, 
338                                 mwindow->theme->rmonitor_interlace_y));
339                 }
340                 
341                 add_subwindow(monitor_menu = new BC_PopupMenu(0, 
342                         0, 
343                         0, 
344                         "", 
345                         0));
346                 monitor_menu->add_item(new RecordMonitorFullsize(mwindow, 
347                         this));
348         }
351         if(!background_done)
352         {
353                 mwindow->theme->draw_rmonitor_bg(this);
354                 background_done = 1;
355         }
357         if(record->default_asset->audio_data)
358         {
359                 meters = new MeterPanel(mwindow, 
360                         this,
361                         mwindow->theme->rmonitor_meter_x,
362                         mwindow->theme->rmonitor_meter_y,
363                         mwindow->theme->rmonitor_meter_h,
364                         record->default_asset->channels,
365                         1,
366                         1);
367                 meters->create_objects();
368         }
369         return 0;
372 int RecordMonitorGUI::button_press_event()
374         if(mwindow->session->rwindow_fullscreen && canvas && canvas->get_canvas())
375                 return canvas->button_press_event_base(canvas->get_canvas());
376                 
377         if(get_buttonpress() == 2)
378         {
379                 return 0;
380         }
381         else
382 // Right button
383         if(get_buttonpress() == 3)
384         {
385                 monitor_menu->activate_menu();
386                 return 1;
387         }
388         return 0;
391 int RecordMonitorGUI::cursor_leave_event()
393         if(canvas && canvas->get_canvas())
394                 return canvas->cursor_leave_event_base(canvas->get_canvas());
395         return 0;
398 int RecordMonitorGUI::cursor_enter_event()
400         if(canvas && canvas->get_canvas())
401                 return canvas->cursor_enter_event_base(canvas->get_canvas());
402         return 0;
405 int RecordMonitorGUI::button_release_event()
407         if(canvas && canvas->get_canvas())
408                 return canvas->button_release_event();
409         return 0;
412 int RecordMonitorGUI::cursor_motion_event()
414 SET_TRACE
415         if(canvas && canvas->get_canvas())
416         {
417 SET_TRACE
418                 canvas->get_canvas()->unhide_cursor();
419 SET_TRACE
420                 return canvas->cursor_motion_event();
421         }
422         return 0;
425 int RecordMonitorGUI::keypress_event()
427         int result = 0;
428         switch(get_keypress())
429         {
430                 case LEFT:
431                         if(!ctrl_down()) 
432                         { 
433                                 record->record_gui->set_translation(--(record->video_x), record->video_y, record->video_zoom);
434                         }
435                         else
436                         {
437                                 record->video_zoom -= 0.1;
438                                 record->record_gui->set_translation(record->video_x, record->video_y, record->video_zoom);
439                         }
440                         result = 1;
441                         break;
442                 case RIGHT:
443                         if(!ctrl_down()) 
444                         { 
445                                 record->record_gui->set_translation(++(record->video_x), record->video_y, record->video_zoom);
446                         }
447                         else
448                         {
449                                 record->video_zoom += 0.1;
450                                 record->record_gui->set_translation(record->video_x, record->video_y, record->video_zoom);
451                         }
452                         result = 1;
453                         break;
454                 case UP:
455                         if(!ctrl_down()) 
456                         { 
457                                 record->record_gui->set_translation(record->video_x, --(record->video_y), record->video_zoom);
458                         }
459                         else
460                         {
461                                 record->video_zoom -= 0.1;
462                                 record->record_gui->set_translation(record->video_x, record->video_y, record->video_zoom);
463                         }
464                         result = 1;
465                         break;
466                 case DOWN:
467                         if(!ctrl_down()) 
468                         { 
469                                 record->record_gui->set_translation(record->video_x, ++(record->video_y), record->video_zoom);
470                         }
471                         else
472                         {
473                                 record->video_zoom += 0.1;
474                                 record->record_gui->set_translation(record->video_x, record->video_y, record->video_zoom);
475                         }
476                         result = 1;
477                         break;
478                 case 'w':
479                         close_event();
480                         break;
481                 default:
482                         result = canvas->keypress_event(this);
483 #ifdef HAVE_FIREWIRE
484                         if(!result && avc1394_transport)
485                                 result = avc1394_transport->keypress_event(get_keypress());
486 #endif
487                         break;
488         }
489         return result;
493 int RecordMonitorGUI::translation_event()
495 //printf("MWindowGUI::translation_event 1 %d %d\n", get_x(), get_y());
496         mwindow->session->rmonitor_x = get_x();
497         mwindow->session->rmonitor_y = get_y();
498         return 0;
501 int RecordMonitorGUI::resize_event(int w, int h)
503         int do_channel = (mwindow->edl->session->vconfig_in->driver == VIDEO4LINUX ||
504                         mwindow->edl->session->vconfig_in->driver == CAPTURE_BUZ ||
505                         mwindow->edl->session->vconfig_in->driver == VIDEO4LINUX2 ||
506                         mwindow->edl->session->vconfig_in->driver == VIDEO4LINUX2JPEG);
507         int do_interlace = (mwindow->edl->session->vconfig_in->driver == CAPTURE_BUZ ||
508                 mwindow->edl->session->vconfig_in->driver == VIDEO4LINUX2JPEG);
509         int do_avc = 0;
510 #ifdef HAVE_FIREWIRE
511         do_avc = avc1394_transport ? 1 : 0;
512 #endif
514         mwindow->session->rmonitor_x = get_x();
515         mwindow->session->rmonitor_y = get_y();
516         mwindow->session->rmonitor_w = w;
517         mwindow->session->rmonitor_h = h;
519         mwindow->theme->get_rmonitor_sizes(record->default_asset->audio_data, 
520                 record->default_asset->video_data,
521                 do_channel,
522                 do_interlace,
523                 do_avc,
524                 record->default_asset->channels);
525         mwindow->theme->draw_rmonitor_bg(this);
526         flash();
529 //      record_transport->reposition_window(mwindow->theme->rmonitor_tx_x,
530 //              mwindow->theme->rmonitor_tx_y);
531 #ifdef HAVE_FIREWIRE
532         if(avc1394_transport)
533         {
534                 avc1394_transport->reposition_window(mwindow->theme->rmonitor_tx_x,
535                         mwindow->theme->rmonitor_tx_y);
536         }
537 #endif
538         
539         if(channel_picker) channel_picker->reposition();
540         if(reverse_interlace) reverse_interlace->reposition_window(reverse_interlace->get_x(),
541                 reverse_interlace->get_y());
542         if(canvas && record->default_asset->video_data)
543         {
544                 canvas->reposition_window(0,
545                         mwindow->theme->rmonitor_canvas_x, 
546                         mwindow->theme->rmonitor_canvas_y, 
547                         mwindow->theme->rmonitor_canvas_w, 
548                         mwindow->theme->rmonitor_canvas_h);
549         }
551         if(record->default_asset->audio_data)
552         {
553                 meters->reposition_window(mwindow->theme->rmonitor_meter_x, 
554                         mwindow->theme->rmonitor_meter_y, 
555                         mwindow->theme->rmonitor_meter_h);
556         }
558         set_title();
559         BC_WindowBase::resize_event(w, h);
560         flash();
561         flush();
562         return 1;
565 int RecordMonitorGUI::set_title()
567 return 0;
568         char string[1024];
569         int scale;
571         scale = (int)(thread->get_scale(thread->record->video_window_w) * 100 + 0.5);
573         sprintf(string, PROGRAM_NAME ": Video in %d%%", scale);
574         BC_Window::set_title(string);
575         return 0;
578 int RecordMonitorGUI::close_event()
580         thread->record->monitor_video = 0;
581         thread->record->monitor_audio = 0;
582         thread->record->video_window_open = 0;
583         unlock_window();
585         record->record_gui->lock_window("RecordMonitorGUI::close_event");
586         if(record->record_gui->monitor_video) record->record_gui->monitor_video->update(0);
587         if(record->record_gui->monitor_audio) record->record_gui->monitor_audio->update(0);
588         record->record_gui->flush();
589         record->record_gui->unlock_window();
592         lock_window("RecordMonitorGUI::close_event");
593         hide_window();
594         return 0;
597 int RecordMonitorGUI::create_bitmap()
599         if(bitmap && 
600                 (bitmap->get_w() != get_w() || 
601                         bitmap->get_h() != thread->get_canvas_height()))
602         {
603                 delete bitmap;
604                 bitmap = 0;
605         }
607         if(!bitmap && canvas)
608         {
609 //              bitmap = canvas->new_bitmap(get_w(), thread->get_canvas_height());
610         }
611         return 0;
614 ReverseInterlace::ReverseInterlace(Record *record, int x, int y)
615  : BC_CheckBox(x, y, record->reverse_interlace, _("Swap fields"))
617         this->record = record;
620 ReverseInterlace::~ReverseInterlace()
624 int ReverseInterlace::handle_event()
626         record->reverse_interlace = get_value();
627         return 0;
630 RecordMonitorCanvas::RecordMonitorCanvas(MWindow *mwindow, 
631         RecordMonitorGUI *window, 
632         Record *record, 
633         int x, 
634         int y, 
635         int w, 
636         int h)
637  : Canvas(mwindow,
638         window, 
639         x, 
640         y, 
641         w, 
642         h, 
643         record->default_asset->width,
644         record->default_asset->height,
645         0,
646         0,
647         1)
649         this->window = window;
650         this->mwindow = mwindow;
651         this->record = record;
652 printf("RecordMonitorCanvas::RecordMonitorCanvas 1 %d %d %d %d\n", 
653 x, y, w, h);
654 //printf("RecordMonitorCanvas::RecordMonitorCanvas 2\n");
657 RecordMonitorCanvas::~RecordMonitorCanvas()
661 int RecordMonitorCanvas::get_output_w()
663         return record->default_asset->width;
666 int RecordMonitorCanvas::get_output_h()
668         return record->default_asset->height;
672 int RecordMonitorCanvas::button_press_event()
675         if(Canvas::button_press_event()) return 1;
676         
677         if(mwindow->edl->session->vconfig_in->driver == SCREENCAPTURE)
678         {
679                 window->current_operation = MONITOR_TRANSLATE;
680                 window->translate_x_origin = record->video_x;
681                 window->translate_y_origin = record->video_y;
682                 window->cursor_x_origin = get_cursor_x();
683                 window->cursor_y_origin = get_cursor_y();
684         }
686         return 0;
689 void RecordMonitorCanvas::zoom_resize_window(float percentage)
691         int canvas_w, canvas_h;
692         calculate_sizes(mwindow->edl->get_aspect_ratio(), 
693                 record->default_asset->width, 
694                 record->default_asset->height, 
695                 percentage,
696                 canvas_w,
697                 canvas_h);
698         int new_w, new_h;
699         new_w = canvas_w + (window->get_w() - mwindow->theme->rmonitor_canvas_w);
700         new_h = canvas_h + (window->get_h() - mwindow->theme->rmonitor_canvas_h);
701         window->resize_window(new_w, new_h);
702         window->resize_event(new_w, new_h);
705 int RecordMonitorCanvas::get_fullscreen()
707         return mwindow->session->rwindow_fullscreen;
710 void RecordMonitorCanvas::set_fullscreen(int value)
712         mwindow->session->rwindow_fullscreen = value;
716 int RecordMonitorCanvas::button_release_event()
718         window->current_operation = MONITOR_NONE;
719         return 0;
722 int RecordMonitorCanvas::cursor_motion_event()
724 SET_TRACE
725         if(window->current_operation == MONITOR_TRANSLATE)
726         {
727 SET_TRACE
728                 record->set_translation(
729                         get_cursor_x() - window->cursor_x_origin + window->translate_x_origin,
730                         get_cursor_y() - window->cursor_y_origin + window->translate_y_origin);
731 SET_TRACE
732         }
734         return 0;
737 int RecordMonitorCanvas::cursor_enter_event()
739         if(mwindow->edl->session->vconfig_in->driver == SCREENCAPTURE)
740                 set_cursor(MOVE_CURSOR);
741         return 0;
744 void RecordMonitorCanvas::reset_translation()
746         record->set_translation(0, 0);
749 int RecordMonitorCanvas::keypress_event()
751         int result = 0;
752         switch(get_canvas() && get_canvas()->get_keypress())
753         {
754                 case LEFT:
755                         record->set_translation(--record->video_x, record->video_y);
756                         break;
757                 case RIGHT:
758                         record->set_translation(++record->video_x, record->video_y);
759                         break;
760                 case UP:
761                         record->set_translation(record->video_x, --record->video_y);
762                         break;
763                 case DOWN:
764                         record->set_translation(record->video_x, ++record->video_y);
765                         break;
766         }
767         return result;
771 RecordMonitorFullsize::RecordMonitorFullsize(MWindow *mwindow, 
772         RecordMonitorGUI *window)
773  : BC_MenuItem(_("Zoom 100%"))
775         this->mwindow = mwindow;
776         this->window = window;
778 int RecordMonitorFullsize::handle_event()
780         return 1;
790 // ================================== slippery playback ============================
793 RecordMonitorThread::RecordMonitorThread(MWindow *mwindow, 
794         Record *record, 
795         RecordMonitor *record_monitor)
796  : Thread(1, 0, 0)
798         this->mwindow = mwindow;
799         this->record_monitor = record_monitor;
800         this->record = record;
801         reset_parameters();
802         output_lock = new Condition(1, "RecordMonitor::output_lock");
803         input_lock = new Condition(1, "RecordMonitor::input_lock");
807 void RecordMonitorThread::reset_parameters()
809         input_frame = 0;
810         output_frame[0] = 0;
811         shared_data = 0;
812         jpeg_engine = 0;
813         dv_engine = 0;
814         ready = 0;
818 RecordMonitorThread::~RecordMonitorThread()
820         if(input_frame && !shared_data) delete input_frame;
821         delete output_lock;
822         delete input_lock;
825 void RecordMonitorThread::init_output_format()
827         long offset;
829 //printf("RecordMonitorThread::init_output_format 1\n");
830         switch(mwindow->edl->session->vconfig_in->driver)
831         {
832                 case SCREENCAPTURE:
833                         output_colormodel = record->vdevice->get_best_colormodel(record->default_asset);
834                         break;
835         
836         
837                 case CAPTURE_BUZ:
838                 case VIDEO4LINUX2JPEG:
839                         jpeg_engine = new RecVideoMJPGThread(record, this);
840                         jpeg_engine->start_rendering();
841                         output_colormodel = BC_YUV422P;
842                         break;
844                 case CAPTURE_FIREWIRE:
845                 case CAPTURE_IEC61883:
846                         dv_engine = new RecVideoDVThread(record, this);
847                         dv_engine->start_rendering();
848                         output_colormodel = BC_YUV422P;
849                         break;
851                 case VIDEO4LINUX:
852                 case VIDEO4LINUX2:
853                         output_colormodel = record->vdevice->get_best_colormodel(record->default_asset);
854 //printf("RecordMonitorThread::init_output_format 2 %d\n", output_colormodel);
855                         break;
856         }
859 int RecordMonitorThread::start_playback()
861         ready = 1;
862         done = 0;
863         output_lock->lock("RecordMonitorThread::start_playback");
864         Thread::start();
865         return 0;
868 int RecordMonitorThread::stop_playback()
870         done = 1;
871         output_lock->unlock();
872         Thread::join();
873 //printf("RecordMonitorThread::stop_playback 1\n");
875         switch(mwindow->edl->session->vconfig_in->driver)
876         {
877                 case CAPTURE_BUZ:
878                 case VIDEO4LINUX2JPEG:
879                         if(jpeg_engine) 
880                         {
881                                 jpeg_engine->stop_rendering();
882                                 delete jpeg_engine;
883                         }
884                         break;
886                 case CAPTURE_FIREWIRE:
887                 case CAPTURE_IEC61883:
888                         if(dv_engine)
889                         {
890                                 dv_engine->stop_rendering();
891                                 delete dv_engine;
892                         }
893                         break;
894         }
895 //printf("RecordMonitorThread::stop_playback 4\n");
897         return 0;
900 int RecordMonitorThread::write_frame(VFrame *new_frame)
902         if(ready)
903         {
904                 ready = 0;
905                 shared_data = (new_frame->get_color_model() != BC_COMPRESSED);
908 // Need to wait until after Record creates the input device before starting monitor
909 // because the input device deterimes the output format.
910 // First time
911                 if(!output_frame[0]) init_output_format();
912                 if(!shared_data)
913                 {
914                         if(!input_frame) input_frame = new VFrame;
915                         input_frame->allocate_compressed_data(new_frame->get_compressed_size());
916                         memcpy(input_frame->get_data(), 
917                                 new_frame->get_data(), 
918                                 new_frame->get_compressed_size());
919                         input_frame->set_compressed_size(new_frame->get_compressed_size());
920                         input_frame->set_field2_offset(new_frame->get_field2_offset());
921                 }
922                 else
923                 {
924                         input_lock->lock("RecordMonitorThread::write_frame");
925                         input_frame = new_frame;
926                 }
927                 output_lock->unlock();
928         }
929         return 0;
932 int RecordMonitorThread::render_jpeg()
934 //printf("RecordMonitorThread::render_jpeg 1\n");
935         jpeg_engine->render_frame(input_frame, input_frame->get_compressed_size());
936 //printf("RecordMonitorThread::render_jpeg 2\n");
937         return 0;
940 int RecordMonitorThread::render_dv()
942         dv_engine->render_frame(input_frame, input_frame->get_compressed_size());
943         return 0;
946 void RecordMonitorThread::render_uncompressed()
948         output_frame[0]->copy_from(input_frame);
951 void RecordMonitorThread::show_output_frame()
953         record_monitor->device->write_buffer(output_frame, record->edl);
956 void RecordMonitorThread::unlock_input()
958         if(shared_data) input_lock->unlock();
961 int RecordMonitorThread::render_frame()
963         switch(mwindow->edl->session->vconfig_in->driver)
964         {
965                 case CAPTURE_BUZ:
966                 case VIDEO4LINUX2JPEG:
967                         render_jpeg();
968                         break;
970                 case CAPTURE_FIREWIRE:
971                 case CAPTURE_IEC61883:
972                         render_dv();
973                         break;
975                 default:
976                         render_uncompressed();
977                         break;
978         }
980         return 0;
983 void RecordMonitorThread::new_output_frame()
985         long offset;
986         record_monitor->device->new_output_buffers(output_frame, output_colormodel);
989 void RecordMonitorThread::run()
991 //printf("RecordMonitorThread::run 1 %d\n", getpid());
992         while(!done)
993         {
994 // Wait for next frame
995 SET_TRACE
996                 output_lock->lock("RecordMonitorThread::run");
998                 if(done)
999                 {
1000                         unlock_input();
1001                         return;
1002                 }
1004 SET_TRACE
1005                 new_output_frame();
1006 SET_TRACE
1007                 render_frame();
1008 SET_TRACE
1009                 show_output_frame();
1010 SET_TRACE
1011                 unlock_input();
1012 // Get next frame
1013                 ready = 1;
1014         }
1019 RecVideoMJPGThread::RecVideoMJPGThread(Record *record, RecordMonitorThread *thread)
1021         this->record = record;
1022         this->thread = thread;
1023         mjpeg = 0;
1026 RecVideoMJPGThread::~RecVideoMJPGThread()
1030 int RecVideoMJPGThread::start_rendering()
1032         mjpeg = mjpeg_new(record->default_asset->width, 
1033                 record->default_asset->height, 
1034                 2);
1035 //printf("RecVideoMJPGThread::start_rendering 1 %p\n", mjpeg);
1036         return 0;
1039 int RecVideoMJPGThread::stop_rendering()
1041 //printf("RecVideoMJPGThread::stop_rendering 1 %p\n", mjpeg);
1042         if(mjpeg) mjpeg_delete(mjpeg);
1043 //printf("RecVideoMJPGThread::stop_rendering 2\n");
1044         return 0;
1047 int RecVideoMJPGThread::render_frame(VFrame *frame, long size)
1049 // printf("RecVideoMJPGThread::render_frame %d %02x%02x %02x%02x\n", 
1050 // frame->get_field2_offset(), 
1051 // frame->get_data()[0], 
1052 // frame->get_data()[1], 
1053 // frame->get_data()[frame->get_field2_offset()], 
1054 // frame->get_data()[frame->get_field2_offset() + 1]);
1055 //frame->set_field2_offset(0);
1056         mjpeg_decompress(mjpeg, 
1057                 frame->get_data(), 
1058                 frame->get_compressed_size(), 
1059                 frame->get_field2_offset(), 
1060                 thread->output_frame[0]->get_rows(), 
1061                 thread->output_frame[0]->get_y(), 
1062                 thread->output_frame[0]->get_u(), 
1063                 thread->output_frame[0]->get_v(),
1064                 thread->output_frame[0]->get_color_model(),
1065                 record->mwindow->preferences->processors);
1066         return 0;
1072 RecVideoDVThread::RecVideoDVThread(Record *record, RecordMonitorThread *thread)
1074         this->record = record;
1075         this->thread = thread;
1076         dv = 0;
1079 RecVideoDVThread::~RecVideoDVThread()
1084 int RecVideoDVThread::start_rendering()
1086         dv = dv_new();
1087         return 0;
1090 int RecVideoDVThread::stop_rendering()
1092         if(dv) dv_delete(((dv_t*)dv));
1093         return 0;
1096 int RecVideoDVThread::render_frame(VFrame *frame, long size)
1098         unsigned char *yuv_planes[3];
1099         yuv_planes[0] = thread->output_frame[0]->get_y();
1100         yuv_planes[1] = thread->output_frame[0]->get_u();
1101         yuv_planes[2] = thread->output_frame[0]->get_v();
1102         dv_read_video(((dv_t*)dv), 
1103                 yuv_planes, 
1104                 frame->get_data(), 
1105                 frame->get_compressed_size(),
1106                 thread->output_frame[0]->get_color_model());
1108         return 0;