3 * Copyright (C) 2011 Adam Williams <broadcast at earthling dot net>
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 #include "bcsignals.h"
24 #include "channelpicker.h"
25 #include "condition.h"
27 #include "devicedvbinput.h"
32 #include "edlsession.h"
35 #include "mainsession.h"
36 #include "meterpanel.h"
38 #include "playbackconfig.h"
39 #include "preferences.h"
41 #include "recordconfig.h"
42 #include "recordgui.h"
43 #include "recordscopes.h"
44 #include "recordtransport.h"
45 #include "recordmonitor.h"
46 #include "signalstatus.h"
48 #include "videodevice.inc"
50 #include "videodevice.h"
51 #include "vdevicedvb.h"
54 RecordMonitor::RecordMonitor(MWindow *mwindow, Record *record)
57 this->mwindow = mwindow;
58 this->record = record;
65 RecordMonitor::~RecordMonitor()
78 void RecordMonitor::create_objects()
82 if( !record->default_asset->video_data )
83 min_w = MeterPanel::get_meters_width(mwindow->theme,
84 record->default_asset->channels, 1);
86 window = new RecordMonitorGUI(mwindow, record, this, min_w);
87 window->create_objects();
89 if( record->default_asset->video_data ) {
90 // Configure the output for record monitoring
91 VideoOutConfig config;
92 device = new VideoDevice;
94 // Override default device for X11 drivers
95 if(mwindow->edl->session->playback_config->vconfig->driver ==
96 PLAYBACK_X11_XV) config.driver = PLAYBACK_X11_XV;
97 config.x11_use_fields = 0;
98 device->open_output(&config,
99 record->default_asset->frame_rate,
100 record->default_asset->width,
101 record->default_asset->height,
104 scope_thread = new RecordScopeThread(mwindow, this);
106 if(mwindow->session->record_scope) {
107 scope_thread->start();
110 thread = new RecordMonitorThread(mwindow, record, this);
111 thread->start_playback();
118 void RecordMonitor::run()
120 window->run_window();
124 void RecordMonitor::close_threads()
126 if(window->channel_picker) window->channel_picker->close_threads();
129 int RecordMonitor::update(VFrame *vframe)
131 return thread->write_frame(vframe);
134 void RecordMonitor::update_channel(char *text)
136 if( window->channel_picker )
137 window->channel_picker->channel_text->update(text);
140 int RecordMonitor::get_mbuttons_height()
142 return RECBUTTON_HEIGHT;
145 void RecordMonitor::fix_size(int &w, int &h, int width_given, float aspect_ratio)
148 h = (int)((float)width_given / aspect_ratio);
151 float RecordMonitor::get_scale(int w)
153 if( mwindow->edl->get_aspect_ratio() >
154 (float)record->frame_w / record->frame_h ) {
156 ((float)record->frame_h *
157 mwindow->edl->get_aspect_ratio());
160 return (float)w / record->frame_w;
164 int RecordMonitor::get_canvas_height()
166 return window->get_h() - get_mbuttons_height();
169 int RecordMonitor::get_channel_x()
175 int RecordMonitor::get_channel_y()
180 void RecordMonitor::stop_playback()
182 if( !thread || thread->finished() ) return;
183 window->enable_signal_status(0);
185 thread->stop_playback();
189 void RecordMonitor::start_playback()
192 thread->output_lock->reset();
193 thread->start_playback();
195 window->enable_signal_status(1);
199 void RecordMonitor::reconfig()
202 VideoOutConfig config = *device->out_config;
204 device->open_output(&config,
205 record->default_asset->frame_rate,
206 record->default_asset->width,
207 record->default_asset->height,
213 void RecordMonitor::redraw()
215 if( thread && window && thread->record->video_window_open )
219 void RecordMonitor::display_vframe(VFrame *in, int x, int y,
220 int alpha, double secs, double scale)
222 if( !thread ) return;
223 thread->display_vframe(in, x, y, alpha, secs, scale);
226 void RecordMonitor::undisplay_vframe()
228 if( !thread ) return;
229 thread->undisplay_vframe();
232 RecordMonitorGUI::RecordMonitorGUI(MWindow *mwindow,
233 Record *record, RecordMonitor *thread, int min_w)
234 : BC_Window(_(PROGRAM_NAME ": Video in"),
235 mwindow->session->rmonitor_x,
236 mwindow->session->rmonitor_y,
237 mwindow->session->rmonitor_w,
238 mwindow->session->rmonitor_h,
239 min_w, 50, 1, 1, 1, -1,
240 mwindow->get_cwindow_display())
242 //printf("%d %d\n", mwindow->session->rmonitor_w, mwindow->theme->rmonitor_meter_x);
243 this->mwindow = mwindow;
244 this->thread = thread;
245 this->record = record;
248 avc1394_transport = 0;
249 avc1394transport_title = 0;
250 avc1394transport_timecode = 0;
251 avc1394transport_thread = 0;
255 reverse_interlace = 0;
259 big_cursor_toggle = 0;
260 current_operation = MONITOR_NONE;
264 RecordMonitorGUI::~RecordMonitorGUI()
266 lock_window("RecordMonitorGUI::~RecordMonitorGUI");
268 delete signal_status;
271 delete cursor_toggle;
272 delete big_cursor_toggle;
274 if( channel_picker ) delete channel_picker;
276 delete avc1394transport_thread;
278 delete avc1394_transport;
279 delete avc1394transport_title;
285 void RecordMonitorGUI::create_objects()
287 // y offset for video canvas if we have the transport controls
288 lock_window("RecordMonitorGUI::create_objects");
289 int driver = mwindow->edl->session->vconfig_in->driver;
290 int do_channel = (driver == CAPTURE_DVB ||
291 driver == VIDEO4LINUX2 ||
292 driver == VIDEO4LINUX2JPEG ||
293 driver == VIDEO4LINUX2MPEG ||
294 driver == CAPTURE_JPEG_WEBCAM ||
295 driver == CAPTURE_YUYV_WEBCAM);
296 int do_cursor = driver == SCREENCAPTURE;
297 int do_scopes = do_channel || driver == SCREENCAPTURE;
298 int do_interlace = driver == VIDEO4LINUX2JPEG;
299 int background_done = 0;
300 int do_audio = record->default_asset->audio_data;
301 int do_video = record->default_asset->video_data;
302 int do_meters = record->metering_audio;
303 int channels = !do_meters ? 0 : record->default_asset->channels;
305 mwindow->theme->get_rmonitor_sizes(do_meters, do_video,
306 do_channel || do_scopes, do_interlace, 0, channels);
311 if( driver == CAPTURE_FIREWIRE || driver == CAPTURE_IEC61883 ) {
312 avc = new AVC1394Control;
313 if( avc->device > -1 ) {
314 mwindow->theme->get_rmonitor_sizes(do_meters, do_video,
315 do_channel, do_interlace, 1, channels);
316 mwindow->theme->draw_rmonitor_bg(this);
319 avc1394_transport = new AVC1394Transport(mwindow,
322 mwindow->theme->rmonitor_tx_x,
323 mwindow->theme->rmonitor_tx_y);
324 avc1394_transport->create_objects();
326 add_subwindow(avc1394transport_timecode =
327 new BC_Title(avc1394_transport->x_end,
328 mwindow->theme->rmonitor_tx_y + 10,
333 avc1394transport_thread =
334 new AVC1394TransportThread(avc1394transport_timecode,
337 avc1394transport_thread->start();
343 if( !background_done ) {
344 mwindow->theme->draw_rmonitor_bg(this);
348 mwindow->theme->rmonitor_canvas_w = MAX(10, mwindow->theme->rmonitor_canvas_w);
349 mwindow->theme->rmonitor_canvas_h = MAX(10, mwindow->theme->rmonitor_canvas_h);
350 canvas = new RecordMonitorCanvas(mwindow, this, record,
351 mwindow->theme->rmonitor_canvas_x,
352 mwindow->theme->rmonitor_canvas_y,
353 mwindow->theme->rmonitor_canvas_w,
354 mwindow->theme->rmonitor_canvas_h);
355 canvas->create_objects(0);
356 canvas->use_rwindow();
359 if( driver == CAPTURE_DVB ) {
360 int ssw = SignalStatus::calculate_w(this);
361 signal_status = new SignalStatus(this, get_w()-ssw-3, 0);
362 add_subwindow(signal_status);
363 signal_status->create_objects();
367 int x = mwindow->theme->widget_border;
368 int y = mwindow->theme->widget_border;
370 channel_picker = new RecordChannelPicker(mwindow,
371 record, thread, this, record->channeldb,
372 mwindow->theme->rmonitor_channel_x,
373 mwindow->theme->rmonitor_channel_y);
374 channel_picker->create_objects();
375 x += channel_picker->get_w() + mwindow->theme->widget_border;
377 if( driver == VIDEO4LINUX2JPEG ) {
378 add_subwindow(reverse_interlace = new ReverseInterlace(record,
379 mwindow->theme->rmonitor_interlace_x,
380 mwindow->theme->rmonitor_interlace_y));
381 x += reverse_interlace->get_w() + mwindow->theme->widget_border;
385 scope_toggle = new ScopeEnable(mwindow, thread, x, y);
386 add_subwindow(scope_toggle);
387 x += scope_toggle->get_w() + mwindow->theme->widget_border;
391 add_subwindow(cursor_toggle = new DoCursor(record,
394 x += cursor_toggle->get_w() + mwindow->theme->widget_border;
395 add_subwindow(big_cursor_toggle = new DoBigCursor(record,
398 x += big_cursor_toggle->get_w() + mwindow->theme->widget_border;
401 add_subwindow(monitor_menu = new BC_PopupMenu(0, 0, 0, "", 0));
402 monitor_menu->add_item(new RecordMonitorFullsize(mwindow, this));
406 if( !background_done ) {
407 mwindow->theme->draw_rmonitor_bg(this);
412 meters = new MeterPanel(mwindow,
414 mwindow->theme->rmonitor_meter_x,
415 mwindow->theme->rmonitor_meter_y,
416 record->default_asset->video_data ? -1 : mwindow->theme->rmonitor_meter_w,
417 mwindow->theme->rmonitor_meter_h,
418 channels, do_meters, 1, 0);
419 meters->create_objects();
424 int RecordMonitorGUI::button_press_event()
426 if( canvas && canvas->get_fullscreen() && canvas->get_canvas())
427 return canvas->button_press_event_base(canvas->get_canvas());
429 if( get_buttonpress() == 2 ) {
434 if( get_buttonpress() == 3 ) {
435 monitor_menu->activate_menu();
441 int RecordMonitorGUI::cursor_leave_event()
443 if(canvas && canvas->get_canvas())
444 return canvas->cursor_leave_event_base(canvas->get_canvas());
448 int RecordMonitorGUI::cursor_enter_event()
450 if( canvas && canvas->get_canvas() )
451 return canvas->cursor_enter_event_base(canvas->get_canvas());
455 int RecordMonitorGUI::button_release_event()
457 if( canvas && canvas->get_canvas() )
458 return canvas->button_release_event();
462 int RecordMonitorGUI::cursor_motion_event()
464 if( canvas && canvas->get_canvas() ) {
465 canvas->get_canvas()->unhide_cursor();
466 return canvas->cursor_motion_event();
471 int RecordMonitorGUI::keypress_event()
475 switch(get_keypress()) {
478 record->record_gui->set_translation(--(record->video_x), record->video_y, record->video_zoom);
481 record->video_zoom -= 0.1;
482 record->record_gui->set_translation(record->video_x, record->video_y, record->video_zoom);
488 record->record_gui->set_translation(++(record->video_x), record->video_y, record->video_zoom);
491 record->video_zoom += 0.1;
492 record->record_gui->set_translation(record->video_x, record->video_y, record->video_zoom);
498 record->record_gui->set_translation(record->video_x, --(record->video_y), record->video_zoom);
501 record->video_zoom -= 0.1;
502 record->record_gui->set_translation(record->video_x, record->video_y, record->video_zoom);
508 record->record_gui->set_translation(record->video_x, ++(record->video_y), record->video_zoom);
511 record->video_zoom += 0.1;
512 record->record_gui->set_translation(record->video_x, record->video_y, record->video_zoom);
521 if(canvas) result = canvas->keypress_event(this);
523 if(!result && avc1394_transport)
524 result = avc1394_transport->keypress_event(get_keypress());
533 int RecordMonitorGUI::translation_event()
535 //printf("MWindowGUI::translation_event 1 %d %d\n", get_x(), get_y());
536 mwindow->session->rmonitor_x = get_x();
537 mwindow->session->rmonitor_y = get_y();
541 int RecordMonitorGUI::resize_event(int w, int h)
543 int driver = mwindow->edl->session->vconfig_in->driver;
544 int do_channel = (driver == CAPTURE_DVB ||
545 driver == VIDEO4LINUX2 ||
546 driver == VIDEO4LINUX2JPEG ||
547 driver == VIDEO4LINUX2MPEG ||
548 driver == CAPTURE_JPEG_WEBCAM ||
549 driver == CAPTURE_YUYV_WEBCAM);
550 int do_scopes = do_channel || driver == SCREENCAPTURE;
551 int do_interlace = (driver == VIDEO4LINUX2JPEG);
554 do_avc = avc1394_transport ? 1 : 0;
556 int do_meters = meters && record->default_asset->audio_data &&
557 record->metering_audio;
558 int do_video = record->default_asset->video_data;
560 mwindow->session->rmonitor_x = get_x();
561 mwindow->session->rmonitor_y = get_y();
562 mwindow->session->rmonitor_w = w;
563 mwindow->session->rmonitor_h = h;
565 mwindow->theme->get_rmonitor_sizes(do_meters, do_video,
566 do_channel || do_scopes, do_interlace, do_avc,
567 record->default_asset->channels);
568 mwindow->theme->draw_rmonitor_bg(this);
571 // record_transport->reposition_window(mwindow->theme->rmonitor_tx_x,
572 // mwindow->theme->rmonitor_tx_y);
574 if(avc1394_transport)
576 avc1394_transport->reposition_window(mwindow->theme->rmonitor_tx_x,
577 mwindow->theme->rmonitor_tx_y);
582 if( channel_picker ) {
583 channel_picker->reposition();
585 if( reverse_interlace ) {
586 reverse_interlace->reposition_window(
587 reverse_interlace->get_x(),
588 reverse_interlace->get_y());
590 if( cursor_toggle ) {
591 cursor_toggle->reposition_window(
592 cursor_toggle->get_x(),
593 cursor_toggle->get_y());
594 big_cursor_toggle->reposition_window(
595 big_cursor_toggle->get_x(),
596 big_cursor_toggle->get_y());
599 if( canvas && do_video ) {
600 canvas->reposition_window(0,
601 mwindow->theme->rmonitor_canvas_x,
602 mwindow->theme->rmonitor_canvas_y,
603 mwindow->theme->rmonitor_canvas_w,
604 mwindow->theme->rmonitor_canvas_h);
608 meters->reposition_window(mwindow->theme->rmonitor_meter_x,
609 mwindow->theme->rmonitor_meter_y,
610 do_video ? -1 : mwindow->theme->rmonitor_meter_w,
611 mwindow->theme->rmonitor_meter_h);
612 meters->set_meters(record->default_asset->channels,1);
615 meters->set_meters(0,0);
619 BC_WindowBase::resize_event(w, h);
624 int RecordMonitorGUI::redraw()
626 lock_window("RecordMonitorGUI::redraw");
627 int w = mwindow->session->rmonitor_w;
628 int h = mwindow->session->rmonitor_h;
629 int result = resize_event(w, h);
634 int RecordMonitorGUI::set_title()
640 scale = (int)(thread->get_scale(thread->record->video_window_w) * 100 + 0.5);
642 sprintf(string, _(PROGRAM_NAME ": Video in %d%%"), scale);
643 BC_Window::set_title(string);
647 int RecordMonitorGUI::close_event()
649 thread->record->set_video_monitoring(0);
650 thread->record->set_audio_monitoring(0);
651 thread->record->video_window_open = 0;
653 lock_window("RecordMonitorGUI::close_event");
658 int RecordMonitorGUI::create_bitmap()
660 if(bitmap && (bitmap->get_w() != get_w() ||
661 bitmap->get_h() != thread->get_canvas_height())) {
666 if( !bitmap && canvas ) {
667 // bitmap = canvas->new_bitmap(get_w(), thread->get_canvas_height());
673 DoCursor::DoCursor(Record *record, int x, int y)
674 : BC_CheckBox(x, y, record->do_cursor, _("Record cursor"))
676 this->record = record;
679 DoCursor::~DoCursor()
683 int DoCursor::handle_event()
685 record->do_cursor = get_value();
690 DoBigCursor::DoBigCursor(Record *record, int x, int y)
691 : BC_CheckBox(x, y, record->do_big_cursor, _("Big cursor"))
693 this->record = record;
696 DoBigCursor::~DoBigCursor()
700 int DoBigCursor::handle_event()
702 record->do_big_cursor = get_value();
707 void RecordMonitorGUI::enable_signal_status(int enable)
710 if( !signal_status ) return;
711 signal_status->lock_window("RecordMonitorGUI::enable_signal_status");
713 signal_status->hide_window();
715 signal_status->show_window();
716 signal_status->unlock_window();
717 DeviceDVBInput *dvb_input = record->dvb_device();
719 dvb_input->set_signal_status(!enable ? 0 : signal_status);
723 void RecordMonitorGUI::
724 display_video_text(int x, int y, const char *text, int font,
725 int bg_color, int color, int alpha, double secs, double scale)
727 lock_window("RecordMonitorGUI::display_text");
729 int ch = get_text_height(font);
730 int h = get_text_height(font,text) + ch/2;
731 int w = get_text_width(font, text) + ch;
732 BC_Pixmap pixmap(this, w, h);
735 draw_box(0, 0, w, h, &pixmap);
737 draw_text(ch/2, ch, text, strlen(text), &pixmap);
738 BC_Bitmap bitmap(this, w, h, BC_RGB888, 0);
739 VFrame in(&bitmap, w, h, BC_RGB888, -1);
740 Drawable drawable = pixmap.get_pixmap();
741 bitmap.read_drawable(drawable, 0, 0, &in);
743 record->display_vframe(&in, x, y, alpha, secs, scale);
746 ReverseInterlace::ReverseInterlace(Record *record, int x, int y)
747 : BC_CheckBox(x, y, record->reverse_interlace, _("Swap fields"))
749 this->record = record;
752 ReverseInterlace::~ReverseInterlace()
756 int ReverseInterlace::handle_event()
758 record->reverse_interlace = get_value();
762 RecordMonitorCanvas::RecordMonitorCanvas(MWindow *mwindow,
763 RecordMonitorGUI *window, Record *record,
764 int x, int y, int w, int h)
765 : Canvas(mwindow, window, x, y, w, h,
766 record->default_asset->width,
767 record->default_asset->height,
770 this->window = window;
771 this->mwindow = mwindow;
772 this->record = record;
773 //printf("RecordMonitorCanvas::RecordMonitorCanvas 1 %d %d %d %d\n",
775 //printf("RecordMonitorCanvas::RecordMonitorCanvas 2\n");
778 RecordMonitorCanvas::~RecordMonitorCanvas()
782 int RecordMonitorCanvas::get_output_w()
784 return record->default_asset->width;
787 int RecordMonitorCanvas::get_output_h()
789 return record->default_asset->height;
793 int RecordMonitorCanvas::button_press_event()
796 if(Canvas::button_press_event()) return 1;
797 if( mwindow->edl->session->vconfig_in->driver == SCREENCAPTURE ) {
798 window->current_operation = MONITOR_TRANSLATE;
799 window->translate_x_origin = record->video_x;
800 window->translate_y_origin = record->video_y;
801 window->cursor_x_origin = get_cursor_x();
802 window->cursor_y_origin = get_cursor_y();
808 void RecordMonitorCanvas::zoom_resize_window(float percentage)
810 int canvas_w, canvas_h;
811 calculate_sizes(mwindow->edl->get_aspect_ratio(),
812 record->default_asset->width, record->default_asset->height,
813 percentage, canvas_w, canvas_h);
815 new_w = canvas_w + (window->get_w() - mwindow->theme->rmonitor_canvas_w);
816 new_h = canvas_h + (window->get_h() - mwindow->theme->rmonitor_canvas_h);
817 window->resize_window(new_w, new_h);
818 window->resize_event(new_w, new_h);
822 int RecordMonitorCanvas::button_release_event()
824 window->current_operation = MONITOR_NONE;
828 int RecordMonitorCanvas::cursor_motion_event()
831 if( window->current_operation == MONITOR_TRANSLATE ) {
833 record->set_translation(
834 get_cursor_x() - window->cursor_x_origin + window->translate_x_origin,
835 get_cursor_y() - window->cursor_y_origin + window->translate_y_origin);
842 int RecordMonitorCanvas::cursor_enter_event()
844 if(mwindow->edl->session->vconfig_in->driver == SCREENCAPTURE)
845 set_cursor(MOVE_CURSOR);
849 void RecordMonitorCanvas::reset_translation()
851 record->set_translation(0, 0);
854 int RecordMonitorCanvas::keypress_event()
856 if( !get_canvas() ) return 0;
858 switch(get_canvas()->get_keypress()) {
860 record->set_translation(--record->video_x, record->video_y);
863 record->set_translation(++record->video_x, record->video_y);
866 record->set_translation(record->video_x, --record->video_y);
869 record->set_translation(record->video_x, ++record->video_y);
878 RecordMonitorFullsize::RecordMonitorFullsize(MWindow *mwindow,
879 RecordMonitorGUI *window)
880 : BC_MenuItem(_("Zoom 100%"))
882 this->mwindow = mwindow;
883 this->window = window;
885 int RecordMonitorFullsize::handle_event()
897 // ================================== slippery playback ============================
900 RecordMonitorThread::RecordMonitorThread(MWindow *mwindow,
902 RecordMonitor *record_monitor)
905 this->mwindow = mwindow;
906 this->record_monitor = record_monitor;
907 this->record = record;
910 output_lock = new Condition(1, "RecordMonitor::output_lock");
911 input_lock = new Condition(1, "RecordMonitor::input_lock");
914 void RecordMonitorThread::reset_parameters()
926 RecordMonitorThread::~RecordMonitorThread()
929 if( input_frame && !shared_data )
936 void RecordMonitorThread::init_output_format()
938 //printf("RecordMonitorThread::init_output_format 1\n");
939 switch(mwindow->edl->session->vconfig_in->driver) {
941 output_colormodel = record->vdevice->get_best_colormodel(record->default_asset);
944 case VIDEO4LINUX2JPEG:
945 jpeg_engine = new RecVideoMJPGThread(record, this,
946 mwindow->edl->session->vconfig_in->v4l2jpeg_in_fields);
947 jpeg_engine->start_rendering();
948 output_colormodel = BC_YUV422P;
951 case CAPTURE_FIREWIRE:
952 case CAPTURE_IEC61883:
953 dv_engine = new RecVideoDVThread(record, this);
954 dv_engine->start_rendering();
955 output_colormodel = BC_YUV422P;
958 case CAPTURE_JPEG_WEBCAM:
959 jpeg_engine = new RecVideoMJPGThread(record, this, 1);
960 jpeg_engine->start_rendering();
961 output_colormodel = BC_YUV420P;
964 case CAPTURE_YUYV_WEBCAM:
965 output_colormodel = BC_YUV422;
971 case VIDEO4LINUX2MPEG:
972 output_colormodel = record->vdevice->get_best_colormodel(record->default_asset);
973 //printf("RecordMonitorThread::init_output_format 2 %d\n", output_colormodel);
978 int RecordMonitorThread::start_playback()
983 output_lock->lock("RecordMonitorThread::start_playback");
988 int RecordMonitorThread::stop_playback()
992 output_lock->unlock();
994 //printf("RecordMonitorThread::stop_playback 1\n");
996 switch(mwindow->edl->session->vconfig_in->driver) {
997 case VIDEO4LINUX2JPEG:
999 jpeg_engine->stop_rendering();
1005 case CAPTURE_FIREWIRE:
1006 case CAPTURE_IEC61883:
1008 dv_engine->stop_rendering();
1014 case VIDEO4LINUX2MPEG:
1017 //printf("RecordMonitorThread::stop_playback 4\n");
1022 int RecordMonitorThread::write_frame(VFrame *new_frame)
1026 shared_data = (new_frame->get_color_model() != BC_COMPRESSED);
1029 // Need to wait until after Record creates the input device before starting monitor
1030 // because the input device deterimes the output format.
1032 if( !output_frame ) init_output_format();
1033 if( !shared_data ) {
1034 if(!input_frame) input_frame = new VFrame;
1035 input_frame->allocate_compressed_data(new_frame->get_compressed_size());
1036 memcpy(input_frame->get_data(),
1037 new_frame->get_data(),
1038 new_frame->get_compressed_size());
1039 input_frame->set_compressed_size(new_frame->get_compressed_size());
1040 input_frame->set_field2_offset(new_frame->get_field2_offset());
1043 input_lock->lock("RecordMonitorThread::write_frame");
1044 input_frame = new_frame;
1046 output_lock->unlock();
1051 int RecordMonitorThread::render_jpeg()
1053 //printf("RecordMonitorThread::render_jpeg 1\n");
1054 jpeg_engine->render_frame(input_frame, input_frame->get_compressed_size());
1055 //printf("RecordMonitorThread::render_jpeg 2\n");
1059 int RecordMonitorThread::render_dv()
1061 dv_engine->render_frame(input_frame, input_frame->get_compressed_size());
1065 void RecordMonitorThread::render_uncompressed()
1067 output_frame->transfer_from(input_frame);
1070 void RecordMonitorThread::show_output_frame()
1072 if( ovly && ovly->overlay(output_frame) )
1074 record_monitor->device->write_buffer(output_frame, record->edl);
1078 void RecordMonitorThread::unlock_input()
1080 if(shared_data) input_lock->unlock();
1083 void RecordMonitorThread::lock_input()
1085 if(shared_data) input_lock->lock();
1088 int RecordMonitorThread::render_frame()
1090 switch(mwindow->edl->session->vconfig_in->driver) {
1091 case VIDEO4LINUX2JPEG:
1092 case CAPTURE_JPEG_WEBCAM:
1096 case CAPTURE_FIREWIRE:
1097 case CAPTURE_IEC61883:
1102 render_uncompressed();
1109 void RecordMonitorThread::new_output_frame()
1111 record_monitor->device->new_output_buffer(&output_frame,
1116 void RecordMonitorThread::
1117 display_vframe(VFrame *in, int x, int y, int alpha, double secs, double scale)
1120 int ticks = secs * SESSION->vconfig_in->in_framerate;
1121 scale *= SESSION->vconfig_in->h / 1080.;
1122 ovly = new RecVideoOverlay(in, x, y, ticks, scale, alpha/255.);
1126 RecVideoOverlay(VFrame *vframe, int x, int y, int ticks, float scale, float alpha)
1130 this->ticks = ticks;
1131 this->scale = scale;
1132 this->alpha = alpha;
1133 this->vframe = new VFrame(*vframe);
1142 int RecVideoOverlay::
1143 overlay(VFrame *out)
1145 VFrame *in = vframe;
1146 int xx = x * scale, yy = y * scale;
1147 int w = in->get_w(), h = in->get_h();
1148 int ww = w * scale, hh = h * scale;
1149 BC_CModels::transfer(out->get_rows(), in->get_rows(),
1150 out->get_y(), out->get_u(), out->get_v(),
1151 in->get_y(), in->get_u(), in->get_v(),
1152 0, 0, w, h, xx, yy, ww, hh,
1153 in->get_color_model(), out->get_color_model(), 0,
1154 in->get_bytes_per_line(), out->get_bytes_per_line());
1155 return ticks > 0 && --ticks == 0 ? 1 : 0;
1158 void RecordMonitorThread::
1161 delete ovly; ovly = 0;
1164 void RecordMonitorThread::run()
1166 //printf("RecordMonitorThread::run 1 %d\n", getpid());
1168 // Wait for next frame
1170 output_lock->lock("RecordMonitorThread::run");
1181 record_monitor->scope_thread->process(output_frame);
1183 show_output_frame();
1193 RecVideoMJPGThread::RecVideoMJPGThread(Record *record,
1194 RecordMonitorThread *thread,
1197 this->record = record;
1198 this->thread = thread;
1200 this->fields = fields;
1203 RecVideoMJPGThread::~RecVideoMJPGThread()
1207 int RecVideoMJPGThread::start_rendering()
1209 mjpeg = mjpeg_new(record->default_asset->width,
1210 record->default_asset->height,
1212 //printf("RecVideoMJPGThread::start_rendering 1 %p\n", mjpeg);
1216 int RecVideoMJPGThread::stop_rendering()
1218 //printf("RecVideoMJPGThread::stop_rendering 1 %p\n", mjpeg);
1219 if(mjpeg) mjpeg_delete(mjpeg);
1220 //printf("RecVideoMJPGThread::stop_rendering 2\n");
1224 int RecVideoMJPGThread::render_frame(VFrame *frame, long size)
1226 // printf("RecVideoMJPGThread::render_frame %d %02x%02x %02x%02x\n",
1227 // frame->get_field2_offset(),
1228 // frame->get_data()[0],
1229 // frame->get_data()[1],
1230 // frame->get_data()[frame->get_field2_offset()],
1231 // frame->get_data()[frame->get_field2_offset() + 1]);
1232 //frame->set_field2_offset(0);
1233 mjpeg_decompress(mjpeg,
1235 frame->get_compressed_size(),
1236 frame->get_field2_offset(),
1237 thread->output_frame->get_rows(),
1238 thread->output_frame->get_y(),
1239 thread->output_frame->get_u(),
1240 thread->output_frame->get_v(),
1241 thread->output_frame->get_color_model(),
1242 record->mwindow->preferences->processors);
1249 RecVideoDVThread::RecVideoDVThread(Record *record, RecordMonitorThread *thread)
1251 this->record = record;
1252 this->thread = thread;
1256 RecVideoDVThread::~RecVideoDVThread()
1261 int RecVideoDVThread::start_rendering()
1269 int RecVideoDVThread::stop_rendering()
1272 if( dv ) { dv_delete(((dv_t*)dv)); dv = 0; }
1277 int RecVideoDVThread::render_frame(VFrame *frame, long size)
1280 unsigned char *yuv_planes[3];
1281 yuv_planes[0] = thread->output_frame->get_y();
1282 yuv_planes[1] = thread->output_frame->get_u();
1283 yuv_planes[2] = thread->output_frame->get_v();
1284 dv_read_video(((dv_t*)dv),
1287 frame->get_compressed_size(),
1288 thread->output_frame->get_color_model());