3 * Copyright (C) 2011 Adam Williams <broadcast at earthling dot net>
4 * Copyright (C) 2003-2016 Cinelerra CV contributors
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 #include "bcsignals.h"
25 #include "xfer/xfer.h"
26 #include "channelpicker.h"
27 #include "condition.h"
29 #include "devicedvbinput.h"
34 #include "edlsession.h"
37 #include "mainsession.h"
38 #include "meterpanel.h"
40 #include "playbackconfig.h"
41 #include "preferences.h"
43 #include "recordconfig.h"
44 #include "recordgui.h"
45 #include "recordscopes.h"
46 #include "recordtransport.h"
47 #include "recordmonitor.h"
48 #include "signalstatus.h"
50 #include "videodevice.inc"
52 #include "videodevice.h"
53 #include "vdevicedvb.h"
56 RecordMonitor::RecordMonitor(MWindow *mwindow, Record *record)
59 this->mwindow = mwindow;
60 this->record = record;
67 RecordMonitor::~RecordMonitor()
80 void RecordMonitor::create_objects()
84 if( !record->default_asset->video_data )
85 min_w = MeterPanel::get_meters_width(mwindow->theme,
86 record->default_asset->channels, 1);
88 window = new RecordMonitorGUI(mwindow, record, this, min_w);
89 window->create_objects();
91 if( record->default_asset->video_data ) {
92 // Configure the output for record monitoring
93 VideoOutConfig config;
94 device = new VideoDevice;
96 // Override default device for X11 drivers
97 if(mwindow->edl->session->playback_config->vconfig->driver ==
98 PLAYBACK_X11_XV) config.driver = PLAYBACK_X11_XV;
99 config.x11_use_fields = 0;
100 device->open_output(&config,
101 record->default_asset->frame_rate,
102 record->default_asset->width,
103 record->default_asset->height,
106 scope_thread = new RecordScopeThread(mwindow, this);
108 if(mwindow->session->record_scope) {
109 scope_thread->start();
112 thread = new RecordMonitorThread(mwindow, record, this);
113 thread->start_playback();
120 void RecordMonitor::run()
122 window->run_window();
126 void RecordMonitor::close_threads()
128 if(window->channel_picker) window->channel_picker->close_threads();
131 int RecordMonitor::update(VFrame *vframe)
133 return thread->write_frame(vframe);
136 void RecordMonitor::update_channel(char *text)
138 if( window->channel_picker )
139 window->channel_picker->channel_text->update(text);
142 int RecordMonitor::get_mbuttons_height()
144 return RECBUTTON_HEIGHT;
147 void RecordMonitor::fix_size(int &w, int &h, int width_given, float aspect_ratio)
150 h = (int)((float)width_given / aspect_ratio);
153 float RecordMonitor::get_scale(int w)
155 if( mwindow->edl->get_aspect_ratio() >
156 (float)record->frame_w / record->frame_h ) {
158 ((float)record->frame_h *
159 mwindow->edl->get_aspect_ratio());
162 return (float)w / record->frame_w;
166 int RecordMonitor::get_canvas_height()
168 return window->get_h() - get_mbuttons_height();
171 int RecordMonitor::get_channel_x()
177 int RecordMonitor::get_channel_y()
182 void RecordMonitor::stop_playback()
184 if( !thread || thread->finished() ) return;
185 window->enable_signal_status(0);
187 thread->stop_playback();
191 void RecordMonitor::start_playback()
194 thread->output_lock->reset();
195 thread->start_playback();
197 window->enable_signal_status(1);
201 void RecordMonitor::reconfig()
204 VideoOutConfig config = *device->out_config;
206 device->open_output(&config,
207 record->default_asset->frame_rate,
208 record->default_asset->width,
209 record->default_asset->height,
215 void RecordMonitor::redraw()
217 if( thread && window && thread->record->video_window_open )
221 void RecordMonitor::display_vframe(VFrame *in, int x, int y,
222 int alpha, double secs, double scale)
224 if( !thread ) return;
225 thread->display_vframe(in, x, y, alpha, secs, scale);
228 void RecordMonitor::undisplay_vframe()
230 if( !thread ) return;
231 thread->undisplay_vframe();
234 RecordMonitorGUI::RecordMonitorGUI(MWindow *mwindow,
235 Record *record, RecordMonitor *thread, int min_w)
236 : BC_Window(_(PROGRAM_NAME ": Video in"),
237 mwindow->session->rmonitor_x,
238 mwindow->session->rmonitor_y,
239 mwindow->session->rmonitor_w,
240 mwindow->session->rmonitor_h,
241 min_w, yS(50), 1, 1, 1, -1,
242 mwindow->get_cwindow_display())
244 //printf("%d %d\n", mwindow->session->rmonitor_w, mwindow->theme->rmonitor_meter_x);
245 this->mwindow = mwindow;
246 this->thread = thread;
247 this->record = record;
250 avc1394_transport = 0;
251 avc1394transport_title = 0;
252 avc1394transport_timecode = 0;
253 avc1394transport_thread = 0;
257 reverse_interlace = 0;
261 big_cursor_toggle = 0;
262 current_operation = MONITOR_NONE;
264 // *** CONTEXT_HELP ***
265 context_help_set_keyword("Capturing and Recording Media");
268 RecordMonitorGUI::~RecordMonitorGUI()
270 lock_window("RecordMonitorGUI::~RecordMonitorGUI");
272 delete signal_status;
275 delete cursor_toggle;
276 delete big_cursor_toggle;
278 if( channel_picker ) delete channel_picker;
280 delete avc1394transport_thread;
282 delete avc1394_transport;
283 delete avc1394transport_title;
289 void RecordMonitorGUI::create_objects()
291 // y offset for video canvas if we have the transport controls
292 lock_window("RecordMonitorGUI::create_objects");
293 int driver = mwindow->edl->session->vconfig_in->driver;
294 int do_channel = (driver == CAPTURE_DVB ||
295 driver == VIDEO4LINUX2 ||
296 driver == VIDEO4LINUX2JPEG ||
297 driver == VIDEO4LINUX2MPEG ||
298 driver == CAPTURE_JPEG_WEBCAM ||
299 driver == CAPTURE_YUYV_WEBCAM);
300 int do_cursor = driver == SCREENCAPTURE;
301 int do_scopes = do_channel || driver == SCREENCAPTURE;
302 int do_interlace = driver == VIDEO4LINUX2JPEG;
303 int background_done = 0;
304 int do_audio = record->default_asset->audio_data;
305 int do_video = record->default_asset->video_data;
306 int do_meters = record->metering_audio;
307 int channels = !do_meters ? 0 : record->default_asset->channels;
309 mwindow->theme->get_rmonitor_sizes(do_meters, do_video,
310 do_channel || do_scopes, do_interlace, 0, channels);
315 if( driver == CAPTURE_FIREWIRE || driver == CAPTURE_IEC61883 ) {
316 avc = new AVC1394Control;
317 if( avc->device > -1 ) {
318 mwindow->theme->get_rmonitor_sizes(do_meters, do_video,
319 do_channel, do_interlace, 1, channels);
320 mwindow->theme->draw_rmonitor_bg(this);
323 avc1394_transport = new AVC1394Transport(mwindow,
326 mwindow->theme->rmonitor_tx_x,
327 mwindow->theme->rmonitor_tx_y);
328 avc1394_transport->create_objects();
330 add_subwindow(avc1394transport_timecode =
331 new BC_Title(avc1394_transport->x_end,
332 mwindow->theme->rmonitor_tx_y + yS(10),
337 avc1394transport_thread =
338 new AVC1394TransportThread(avc1394transport_timecode,
341 avc1394transport_thread->start();
347 if( !background_done ) {
348 mwindow->theme->draw_rmonitor_bg(this);
352 mwindow->theme->rmonitor_canvas_w = MAX(xS(10), mwindow->theme->rmonitor_canvas_w);
353 mwindow->theme->rmonitor_canvas_h = MAX(yS(10), mwindow->theme->rmonitor_canvas_h);
354 canvas = new RecordMonitorCanvas(mwindow, this, record,
355 mwindow->theme->rmonitor_canvas_x,
356 mwindow->theme->rmonitor_canvas_y,
357 mwindow->theme->rmonitor_canvas_w,
358 mwindow->theme->rmonitor_canvas_h);
359 canvas->create_objects(0);
362 if( driver == CAPTURE_DVB ) {
363 int ssw = SignalStatus::calculate_w(this);
364 signal_status = new SignalStatus(this, get_w()-ssw-xS(3), 0);
365 add_subwindow(signal_status);
366 signal_status->create_objects();
370 int x = mwindow->theme->widget_border;
371 int y = mwindow->theme->widget_border;
373 channel_picker = new RecordChannelPicker(mwindow,
374 record, thread, this, record->channeldb,
375 mwindow->theme->rmonitor_channel_x,
376 mwindow->theme->rmonitor_channel_y);
377 channel_picker->create_objects();
378 x += channel_picker->get_w() + mwindow->theme->widget_border;
380 if( driver == VIDEO4LINUX2JPEG ) {
381 add_subwindow(reverse_interlace = new ReverseInterlace(record,
382 mwindow->theme->rmonitor_interlace_x,
383 mwindow->theme->rmonitor_interlace_y));
384 x += reverse_interlace->get_w() + mwindow->theme->widget_border;
388 scope_toggle = new ScopeEnable(mwindow, thread, x, y);
389 add_subwindow(scope_toggle);
390 x += scope_toggle->get_w() + mwindow->theme->widget_border;
394 add_subwindow(cursor_toggle = new DoCursor(record,
397 x += cursor_toggle->get_w() + mwindow->theme->widget_border;
398 add_subwindow(big_cursor_toggle = new DoBigCursor(record,
401 x += big_cursor_toggle->get_w() + mwindow->theme->widget_border;
404 add_subwindow(monitor_menu = new BC_PopupMenu(0, 0, 0, "", 0));
405 monitor_menu->add_item(new RecordMonitorFullsize(mwindow, this));
409 if( !background_done ) {
410 mwindow->theme->draw_rmonitor_bg(this);
415 meters = new MeterPanel(mwindow,
417 mwindow->theme->rmonitor_meter_x,
418 mwindow->theme->rmonitor_meter_y,
419 record->default_asset->video_data ? -1 : mwindow->theme->rmonitor_meter_w,
420 mwindow->theme->rmonitor_meter_h,
421 channels, do_meters, 1, 0);
422 meters->create_objects();
427 int RecordMonitorGUI::button_press_event()
429 if( canvas && canvas->get_fullscreen() && canvas->get_canvas())
430 return canvas->button_press_event_base(canvas->get_canvas());
432 if( get_buttonpress() == 2 ) {
437 if( get_buttonpress() == 3 ) {
438 monitor_menu->activate_menu();
444 int RecordMonitorGUI::cursor_leave_event()
446 if(canvas && canvas->get_canvas())
447 return canvas->cursor_leave_event_base(canvas->get_canvas());
451 int RecordMonitorGUI::cursor_enter_event()
453 if( canvas && canvas->get_canvas() )
454 return canvas->cursor_enter_event_base(canvas->get_canvas());
458 int RecordMonitorGUI::button_release_event()
460 if( canvas && canvas->get_canvas() )
461 return canvas->button_release_event();
465 int RecordMonitorGUI::cursor_motion_event()
467 if( canvas && canvas->get_canvas() ) {
468 canvas->get_canvas()->unhide_cursor();
469 return canvas->cursor_motion_event();
474 int RecordMonitorGUI::keypress_event()
478 switch(get_keypress()) {
481 record->record_gui->set_translation(--(record->video_x), record->video_y, record->video_zoom);
484 record->video_zoom -= 0.1;
485 record->record_gui->set_translation(record->video_x, record->video_y, record->video_zoom);
491 record->record_gui->set_translation(++(record->video_x), record->video_y, record->video_zoom);
494 record->video_zoom += 0.1;
495 record->record_gui->set_translation(record->video_x, record->video_y, record->video_zoom);
501 record->record_gui->set_translation(record->video_x, --(record->video_y), record->video_zoom);
504 record->video_zoom -= 0.1;
505 record->record_gui->set_translation(record->video_x, record->video_y, record->video_zoom);
511 record->record_gui->set_translation(record->video_x, ++(record->video_y), record->video_zoom);
514 record->video_zoom += 0.1;
515 record->record_gui->set_translation(record->video_x, record->video_y, record->video_zoom);
524 if(canvas) result = canvas->keypress_event(this);
526 if(!result && avc1394_transport)
527 result = avc1394_transport->keypress_event(get_keypress());
533 result = context_help_check_and_show();
539 int RecordMonitorGUI::translation_event()
541 //printf("MWindowGUI::translation_event 1 %d %d\n", get_x(), get_y());
542 mwindow->session->rmonitor_x = get_x();
543 mwindow->session->rmonitor_y = get_y();
547 int RecordMonitorGUI::resize_event(int w, int h)
549 int driver = mwindow->edl->session->vconfig_in->driver;
550 int do_channel = (driver == CAPTURE_DVB ||
551 driver == VIDEO4LINUX2 ||
552 driver == VIDEO4LINUX2JPEG ||
553 driver == VIDEO4LINUX2MPEG ||
554 driver == CAPTURE_JPEG_WEBCAM ||
555 driver == CAPTURE_YUYV_WEBCAM);
556 int do_scopes = do_channel || driver == SCREENCAPTURE;
557 int do_interlace = (driver == VIDEO4LINUX2JPEG);
560 do_avc = avc1394_transport ? 1 : 0;
562 int do_meters = meters && record->default_asset->audio_data &&
563 record->metering_audio;
564 int do_video = record->default_asset->video_data;
566 mwindow->session->rmonitor_x = get_x();
567 mwindow->session->rmonitor_y = get_y();
568 mwindow->session->rmonitor_w = w;
569 mwindow->session->rmonitor_h = h;
571 mwindow->theme->get_rmonitor_sizes(do_meters, do_video,
572 do_channel || do_scopes, do_interlace, do_avc,
573 record->default_asset->channels);
574 mwindow->theme->draw_rmonitor_bg(this);
577 // record_transport->reposition_window(mwindow->theme->rmonitor_tx_x,
578 // mwindow->theme->rmonitor_tx_y);
580 if(avc1394_transport)
582 avc1394_transport->reposition_window(mwindow->theme->rmonitor_tx_x,
583 mwindow->theme->rmonitor_tx_y);
588 if( channel_picker ) {
589 channel_picker->reposition();
591 if( reverse_interlace ) {
592 reverse_interlace->reposition_window(
593 reverse_interlace->get_x(),
594 reverse_interlace->get_y());
596 if( cursor_toggle ) {
597 cursor_toggle->reposition_window(
598 cursor_toggle->get_x(),
599 cursor_toggle->get_y());
600 big_cursor_toggle->reposition_window(
601 big_cursor_toggle->get_x(),
602 big_cursor_toggle->get_y());
605 if( canvas && do_video ) {
606 canvas->reposition_window(0,
607 mwindow->theme->rmonitor_canvas_x,
608 mwindow->theme->rmonitor_canvas_y,
609 mwindow->theme->rmonitor_canvas_w,
610 mwindow->theme->rmonitor_canvas_h);
614 meters->reposition_window(mwindow->theme->rmonitor_meter_x,
615 mwindow->theme->rmonitor_meter_y,
616 do_video ? -1 : mwindow->theme->rmonitor_meter_w,
617 mwindow->theme->rmonitor_meter_h);
618 meters->set_meters(record->default_asset->channels,1);
621 meters->set_meters(0,0);
625 BC_WindowBase::resize_event(w, h);
630 int RecordMonitorGUI::redraw()
632 lock_window("RecordMonitorGUI::redraw");
633 int w = mwindow->session->rmonitor_w;
634 int h = mwindow->session->rmonitor_h;
635 int result = resize_event(w, h);
640 int RecordMonitorGUI::set_title()
646 scale = (int)(thread->get_scale(thread->record->video_window_w) * 100 + 0.5);
648 sprintf(string, _(PROGRAM_NAME ": Video in %d%%"), scale);
649 BC_Window::set_title(string);
653 int RecordMonitorGUI::close_event()
655 thread->record->set_video_monitoring(0);
656 thread->record->set_audio_monitoring(0);
657 thread->record->video_window_open = 0;
659 lock_window("RecordMonitorGUI::close_event");
664 int RecordMonitorGUI::create_bitmap()
666 if(bitmap && (bitmap->get_w() != get_w() ||
667 bitmap->get_h() != thread->get_canvas_height())) {
672 if( !bitmap && canvas ) {
673 // bitmap = canvas->new_bitmap(get_w(), thread->get_canvas_height());
679 DoCursor::DoCursor(Record *record, int x, int y)
680 : BC_CheckBox(x, y, record->do_cursor, _("Record cursor"))
682 this->record = record;
685 DoCursor::~DoCursor()
689 int DoCursor::handle_event()
691 record->do_cursor = get_value();
696 DoBigCursor::DoBigCursor(Record *record, int x, int y)
697 : BC_CheckBox(x, y, record->do_big_cursor, _("Big cursor"))
699 this->record = record;
702 DoBigCursor::~DoBigCursor()
706 int DoBigCursor::handle_event()
708 record->do_big_cursor = get_value();
713 void RecordMonitorGUI::enable_signal_status(int enable)
716 if( !signal_status ) return;
717 signal_status->lock_window("RecordMonitorGUI::enable_signal_status");
719 signal_status->hide_window();
721 signal_status->show_window();
722 signal_status->unlock_window();
723 DeviceDVBInput *dvb_input = record->dvb_device();
725 dvb_input->set_signal_status(!enable ? 0 : signal_status);
729 void RecordMonitorGUI::
730 display_video_text(int x, int y, const char *text, int font,
731 int bg_color, int color, int alpha, double secs, double scale)
733 lock_window("RecordMonitorGUI::display_text");
735 int ch = get_text_height(font);
736 int h = get_text_height(font,text) + ch/2;
737 int w = get_text_width(font, text) + ch;
738 BC_Pixmap pixmap(this, w, h);
741 draw_box(0, 0, w, h, &pixmap);
743 draw_text(ch/2, ch, text, strlen(text), &pixmap);
744 BC_Bitmap bitmap(this, w, h, BC_RGB888, 0);
745 VFrame in(&bitmap, w, h, BC_RGB888, -1);
746 Drawable drawable = pixmap.get_pixmap();
747 bitmap.read_drawable(drawable, 0, 0, &in);
749 record->display_vframe(&in, x, y, alpha, secs, scale);
752 ReverseInterlace::ReverseInterlace(Record *record, int x, int y)
753 : BC_CheckBox(x, y, record->reverse_interlace, _("Swap fields"))
755 this->record = record;
758 ReverseInterlace::~ReverseInterlace()
762 int ReverseInterlace::handle_event()
764 record->reverse_interlace = get_value();
768 RecordMonitorCanvas::RecordMonitorCanvas(MWindow *mwindow,
769 RecordMonitorGUI *window, Record *record,
770 int x, int y, int w, int h)
771 : Canvas(mwindow, window, x, y, w, h,
772 record->default_asset->width,
773 record->default_asset->height,
776 this->window = window;
777 this->mwindow = mwindow;
778 this->record = record;
779 //printf("RecordMonitorCanvas::RecordMonitorCanvas 1 %d %d %d %d\n",
781 //printf("RecordMonitorCanvas::RecordMonitorCanvas 2\n");
784 RecordMonitorCanvas::~RecordMonitorCanvas()
788 void RecordMonitorCanvas::create_objects(EDL *edl)
790 Canvas::create_objects(edl);
791 canvas_menu->add_item(new CanvasPopupResetTranslation(this));
794 int RecordMonitorCanvas::get_output_w()
796 return record->default_asset->width;
799 int RecordMonitorCanvas::get_output_h()
801 return record->default_asset->height;
805 int RecordMonitorCanvas::button_press_event()
808 if(Canvas::button_press_event()) return 1;
809 if( mwindow->edl->session->vconfig_in->driver == SCREENCAPTURE ) {
810 window->current_operation = MONITOR_TRANSLATE;
811 window->translate_x_origin = record->video_x;
812 window->translate_y_origin = record->video_y;
813 window->cursor_x_origin = get_cursor_x();
814 window->cursor_y_origin = get_cursor_y();
820 void RecordMonitorCanvas::zoom_resize_window(float percentage)
822 int canvas_w, canvas_h;
823 calculate_sizes(mwindow->edl->get_aspect_ratio(),
824 record->default_asset->width, record->default_asset->height,
825 percentage, canvas_w, canvas_h);
827 new_w = canvas_w + (window->get_w() - mwindow->theme->rmonitor_canvas_w);
828 new_h = canvas_h + (window->get_h() - mwindow->theme->rmonitor_canvas_h);
829 window->resize_window(new_w, new_h);
830 window->resize_event(new_w, new_h);
834 int RecordMonitorCanvas::button_release_event()
836 window->current_operation = MONITOR_NONE;
840 int RecordMonitorCanvas::cursor_motion_event()
843 if( window->current_operation == MONITOR_TRANSLATE ) {
845 record->set_translation(
846 get_cursor_x() - window->cursor_x_origin + window->translate_x_origin,
847 get_cursor_y() - window->cursor_y_origin + window->translate_y_origin);
854 int RecordMonitorCanvas::cursor_enter_event()
856 if(mwindow->edl->session->vconfig_in->driver == SCREENCAPTURE)
857 set_cursor(MOVE_CURSOR);
861 void RecordMonitorCanvas::reset_translation()
863 record->set_translation(0, 0);
866 int RecordMonitorCanvas::keypress_event()
868 if( !get_canvas() ) return 0;
870 switch(get_canvas()->get_keypress()) {
872 record->set_translation(--record->video_x, record->video_y);
875 record->set_translation(++record->video_x, record->video_y);
878 record->set_translation(record->video_x, --record->video_y);
881 record->set_translation(record->video_x, ++record->video_y);
889 int RecordMonitorCanvas::keypress_event(RecordMonitorGUI *window)
891 return Canvas::keypress_event(window);
895 RecordMonitorFullsize::RecordMonitorFullsize(MWindow *mwindow,
896 RecordMonitorGUI *window)
897 : BC_MenuItem(_("Zoom 100%"))
899 this->mwindow = mwindow;
900 this->window = window;
902 int RecordMonitorFullsize::handle_event()
914 // ================================== slippery playback ============================
917 RecordMonitorThread::RecordMonitorThread(MWindow *mwindow,
919 RecordMonitor *record_monitor)
922 this->mwindow = mwindow;
923 this->record_monitor = record_monitor;
924 this->record = record;
927 output_lock = new Condition(1, "RecordMonitor::output_lock");
928 input_lock = new Condition(1, "RecordMonitor::input_lock");
931 void RecordMonitorThread::reset_parameters()
943 RecordMonitorThread::~RecordMonitorThread()
946 if( input_frame && !shared_data )
953 void RecordMonitorThread::init_output_format()
955 //printf("RecordMonitorThread::init_output_format 1\n");
956 switch(mwindow->edl->session->vconfig_in->driver) {
958 output_colormodel = record->vdevice->get_best_colormodel(record->default_asset);
961 case VIDEO4LINUX2JPEG:
962 jpeg_engine = new RecVideoMJPGThread(record, this,
963 mwindow->edl->session->vconfig_in->v4l2jpeg_in_fields);
964 jpeg_engine->start_rendering();
965 output_colormodel = BC_YUV422P;
968 case CAPTURE_FIREWIRE:
969 case CAPTURE_IEC61883:
970 dv_engine = new RecVideoDVThread(record, this);
971 dv_engine->start_rendering();
972 output_colormodel = BC_YUV422P;
975 case CAPTURE_JPEG_WEBCAM:
976 jpeg_engine = new RecVideoMJPGThread(record, this, 1);
977 jpeg_engine->start_rendering();
978 output_colormodel = BC_YUV420P;
981 case CAPTURE_YUYV_WEBCAM:
982 output_colormodel = BC_YUV422;
988 case VIDEO4LINUX2MPEG:
989 output_colormodel = record->vdevice->get_best_colormodel(record->default_asset);
990 //printf("RecordMonitorThread::init_output_format 2 %d\n", output_colormodel);
995 int RecordMonitorThread::start_playback()
1000 output_lock->lock("RecordMonitorThread::start_playback");
1005 int RecordMonitorThread::stop_playback()
1007 if( done ) return 0;
1009 output_lock->unlock();
1011 //printf("RecordMonitorThread::stop_playback 1\n");
1013 switch(mwindow->edl->session->vconfig_in->driver) {
1014 case VIDEO4LINUX2JPEG:
1016 jpeg_engine->stop_rendering();
1022 case CAPTURE_FIREWIRE:
1023 case CAPTURE_IEC61883:
1025 dv_engine->stop_rendering();
1031 case VIDEO4LINUX2MPEG:
1034 //printf("RecordMonitorThread::stop_playback 4\n");
1039 int RecordMonitorThread::write_frame(VFrame *new_frame)
1043 shared_data = (new_frame->get_color_model() != BC_COMPRESSED);
1046 // Need to wait until after Record creates the input device before starting monitor
1047 // because the input device deterimes the output format.
1049 if( !output_frame ) init_output_format();
1050 if( !shared_data ) {
1051 if(!input_frame) input_frame = new VFrame;
1052 input_frame->allocate_compressed_data(new_frame->get_compressed_size());
1053 memcpy(input_frame->get_data(),
1054 new_frame->get_data(),
1055 new_frame->get_compressed_size());
1056 input_frame->set_compressed_size(new_frame->get_compressed_size());
1057 input_frame->set_field2_offset(new_frame->get_field2_offset());
1060 input_lock->lock("RecordMonitorThread::write_frame");
1061 input_frame = new_frame;
1063 output_lock->unlock();
1068 int RecordMonitorThread::render_jpeg()
1070 //printf("RecordMonitorThread::render_jpeg 1\n");
1071 jpeg_engine->render_frame(input_frame, input_frame->get_compressed_size());
1072 //printf("RecordMonitorThread::render_jpeg 2\n");
1076 int RecordMonitorThread::render_dv()
1078 dv_engine->render_frame(input_frame, input_frame->get_compressed_size());
1082 // VFrame xfer all/odd/even inputs
1083 void RecordMonitorThread::render_uncompressed()
1085 VFrame *in = input_frame, *out = output_frame;
1086 out->set_timestamp(in->get_timestamp());
1087 out->copy_params(in);
1089 unsigned char *in_ptrs[4], *out_ptrs[4];
1090 unsigned char **inp, **outp;
1091 if( BC_CModels::is_planar(in->get_color_model()) ) {
1092 in_ptrs[0] = in->get_y();
1093 in_ptrs[1] = in->get_u();
1094 in_ptrs[2] = in->get_v();
1095 in_ptrs[3] = in->get_a();
1099 inp = in->get_rows();
1100 if( BC_CModels::is_planar(out->get_color_model()) ) {
1101 out_ptrs[0] = out->get_y();
1102 out_ptrs[1] = out->get_u();
1103 out_ptrs[2] = out->get_v();
1104 out_ptrs[3] = out->get_a();
1108 outp = out->get_rows();
1110 int out_colormodel = out->get_color_model();
1111 int out_x = 0, out_y = 0;
1112 int out_w = out->get_w(), out_h = out->get_h();
1113 int out_rowspan = out->get_bytes_per_line();
1114 int inp_colormodel = in->get_color_model();
1115 int inp_x = 0, inp_y = 0;
1116 int inp_w = in->get_w(), inp_h = in->get_h();
1117 int inp_rowspan = in->get_bytes_per_line();
1121 if( inp_w > 0 && inp_h > 0 && out_w > 0 && out_h > 0 ) {
1122 BC_Xfer xfer(outp, out_colormodel, out_x, out_y, out_w, out_h, out_rowspan,
1123 inp, inp_colormodel, inp_x, inp_y, inp_w, inp_h, inp_rowspan,
1125 int *row_table = xfer.row_table;
1126 switch( record->deinterlace ) {
1127 case RECORD_LACE_NONE:
1129 case RECORD_LACE_EVEN: {
1131 for( int i=0; i<out_h; ++i ) {
1132 if( (row_table[i] &= ~1) < inp_y1 )
1133 row_table[i] = inp_y1;
1136 case RECORD_LACE_ODD: {
1137 int inp_y2 = inp_y + inp_h-1;
1138 for( int i=0; i<out_h; ++i ) {
1139 if( (row_table[i] |= 1) > inp_y2 )
1140 row_table[i] = inp_y2;
1147 printf("RecordMonitorThread::render_uncompressed failed: "
1148 "%d %d(%dx%d) to %d(%dx%d)\n", __LINE__,
1149 inp_colormodel, inp_w, inp_h, out_colormodel, out_w, out_h);
1152 void RecordMonitorThread::show_output_frame()
1154 if( ovly && ovly->overlay(output_frame) )
1156 record_monitor->device->write_buffer(output_frame, record->edl);
1160 void RecordMonitorThread::unlock_input()
1162 if(shared_data) input_lock->unlock();
1165 void RecordMonitorThread::lock_input()
1167 if(shared_data) input_lock->lock();
1170 int RecordMonitorThread::render_frame()
1172 switch(mwindow->edl->session->vconfig_in->driver) {
1173 case VIDEO4LINUX2JPEG:
1174 case CAPTURE_JPEG_WEBCAM:
1178 case CAPTURE_FIREWIRE:
1179 case CAPTURE_IEC61883:
1184 render_uncompressed();
1191 void RecordMonitorThread::new_output_frame()
1193 record_monitor->device->new_output_buffer(&output_frame,
1198 void RecordMonitorThread::
1199 display_vframe(VFrame *in, int x, int y, int alpha, double secs, double scale)
1202 int ticks = secs * SESSION->vconfig_in->in_framerate;
1203 scale *= SESSION->vconfig_in->h / 1080.;
1204 ovly = new RecVideoOverlay(in, x, y, ticks, scale, alpha/255.);
1208 RecVideoOverlay(VFrame *vframe, int x, int y, int ticks, float scale, float alpha)
1212 this->ticks = ticks;
1213 this->scale = scale;
1214 this->alpha = alpha;
1215 this->vframe = new VFrame(*vframe);
1224 int RecVideoOverlay::
1225 overlay(VFrame *out)
1227 VFrame *in = vframe;
1228 int xx = x * scale, yy = y * scale;
1229 int w = in->get_w(), h = in->get_h();
1230 int ww = w * scale, hh = h * scale;
1231 BC_CModels::transfer(out->get_rows(), in->get_rows(),
1232 out->get_y(), out->get_u(), out->get_v(),
1233 in->get_y(), in->get_u(), in->get_v(),
1234 0, 0, w, h, xx, yy, ww, hh,
1235 in->get_color_model(), out->get_color_model(), 0,
1236 in->get_bytes_per_line(), out->get_bytes_per_line());
1237 return ticks > 0 && --ticks == 0 ? 1 : 0;
1240 void RecordMonitorThread::
1243 delete ovly; ovly = 0;
1246 void RecordMonitorThread::run()
1248 //printf("RecordMonitorThread::run 1 %d\n", getpid());
1250 // Wait for next frame
1252 output_lock->lock("RecordMonitorThread::run");
1263 record_monitor->scope_thread->process(output_frame);
1265 show_output_frame();
1275 RecVideoMJPGThread::RecVideoMJPGThread(Record *record,
1276 RecordMonitorThread *thread,
1279 this->record = record;
1280 this->thread = thread;
1282 this->fields = fields;
1285 RecVideoMJPGThread::~RecVideoMJPGThread()
1289 int RecVideoMJPGThread::start_rendering()
1291 mjpeg = mjpeg_new(record->default_asset->width,
1292 record->default_asset->height,
1294 //printf("RecVideoMJPGThread::start_rendering 1 %p\n", mjpeg);
1298 int RecVideoMJPGThread::stop_rendering()
1300 //printf("RecVideoMJPGThread::stop_rendering 1 %p\n", mjpeg);
1301 if(mjpeg) mjpeg_delete(mjpeg);
1302 //printf("RecVideoMJPGThread::stop_rendering 2\n");
1306 int RecVideoMJPGThread::render_frame(VFrame *frame, long size)
1308 // printf("RecVideoMJPGThread::render_frame %d %02x%02x %02x%02x\n",
1309 // frame->get_field2_offset(),
1310 // frame->get_data()[0],
1311 // frame->get_data()[1],
1312 // frame->get_data()[frame->get_field2_offset()],
1313 // frame->get_data()[frame->get_field2_offset() + 1]);
1314 //frame->set_field2_offset(0);
1315 mjpeg_decompress(mjpeg,
1317 frame->get_compressed_size(),
1318 frame->get_field2_offset(),
1319 thread->output_frame->get_rows(),
1320 thread->output_frame->get_y(),
1321 thread->output_frame->get_u(),
1322 thread->output_frame->get_v(),
1323 thread->output_frame->get_color_model(),
1324 record->mwindow->preferences->processors);
1331 RecVideoDVThread::RecVideoDVThread(Record *record, RecordMonitorThread *thread)
1333 this->record = record;
1334 this->thread = thread;
1338 RecVideoDVThread::~RecVideoDVThread()
1343 int RecVideoDVThread::start_rendering()
1351 int RecVideoDVThread::stop_rendering()
1354 if( dv ) { dv_delete(((dv_t*)dv)); dv = 0; }
1359 int RecVideoDVThread::render_frame(VFrame *frame, long size)
1362 unsigned char *yuv_planes[3];
1363 yuv_planes[0] = thread->output_frame->get_y();
1364 yuv_planes[1] = thread->output_frame->get_u();
1365 yuv_planes[2] = thread->output_frame->get_v();
1366 dv_read_video(((dv_t*)dv),
1369 frame->get_compressed_size(),
1370 thread->output_frame->get_color_model());