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"
30 #include "edlsession.h"
33 #include "mainsession.h"
34 #include "meterpanel.h"
36 #include "playbackconfig.h"
37 #include "preferences.h"
39 #include "recordconfig.h"
40 #include "recordgui.h"
41 #include "recordscopes.h"
42 #include "recordtransport.h"
43 #include "recordmonitor.h"
45 #include "videodevice.inc"
47 #include "videodevice.h"
48 #include "vdevicedvb.h"
51 RecordMonitor::RecordMonitor(MWindow *mwindow, Record *record)
54 this->mwindow = mwindow;
55 this->record = record;
62 RecordMonitor::~RecordMonitor()
75 void RecordMonitor::create_objects()
78 mwindow->session->rwindow_fullscreen = 0;
80 if( !record->default_asset->video_data )
81 min_w = MeterPanel::get_meters_width(
83 record->default_asset->channels, 1);
88 window = new RecordMonitorGUI(mwindow, record, this, min_w);
90 window->create_objects();
93 if( record->default_asset->video_data ) {
94 // Configure the output for record monitoring
95 VideoOutConfig config;
97 device = new VideoDevice;
102 // Override default device for X11 drivers
103 if(mwindow->edl->session->playback_config->vconfig->driver ==
104 PLAYBACK_X11_XV) config.driver = PLAYBACK_X11_XV;
105 config.x11_use_fields = 0;
109 device->open_output(&config,
110 record->default_asset->frame_rate,
111 record->default_asset->width,
112 record->default_asset->height,
116 scope_thread = new RecordScopeThread(mwindow, this);
118 if(mwindow->session->record_scope)
120 scope_thread->start();
124 thread = new RecordMonitorThread(mwindow, record, this);
126 thread->start_playback();
135 void RecordMonitor::run()
137 window->run_window();
141 void RecordMonitor::close_threads()
143 if(window->channel_picker) window->channel_picker->close_threads();
146 int RecordMonitor::update(VFrame *vframe)
148 return thread->write_frame(vframe);
151 void RecordMonitor::update_channel(char *text)
153 if( window->channel_picker )
154 window->channel_picker->channel_text->update(text);
157 int RecordMonitor::get_mbuttons_height()
159 return RECBUTTON_HEIGHT;
162 void RecordMonitor::fix_size(int &w, int &h, int width_given, float aspect_ratio)
165 h = (int)((float)width_given / aspect_ratio);
168 float RecordMonitor::get_scale(int w)
170 if( mwindow->edl->get_aspect_ratio() >
171 (float)record->frame_w / record->frame_h ) {
173 ((float)record->frame_h *
174 mwindow->edl->get_aspect_ratio());
177 return (float)w / record->frame_w;
181 int RecordMonitor::get_canvas_height()
183 return window->get_h() - get_mbuttons_height();
186 int RecordMonitor::get_channel_x()
192 int RecordMonitor::get_channel_y()
197 void RecordMonitor::stop_playback()
199 if( !thread || thread->finished() ) return;
200 window->enable_signal_status(0);
202 thread->stop_playback();
206 void RecordMonitor::start_playback()
209 thread->output_lock->reset();
210 thread->start_playback();
212 window->enable_signal_status(1);
216 void RecordMonitor::reconfig()
219 VideoOutConfig config = *device->out_config;
221 device->open_output(&config,
222 record->default_asset->frame_rate,
223 record->default_asset->width,
224 record->default_asset->height,
230 void RecordMonitor::redraw()
232 if( thread && window && thread->record->video_window_open )
236 void RecordMonitor::display_vframe(VFrame *in, int x, int y,
237 int alpha, double secs, double scale)
239 if( !thread ) return;
240 thread->display_vframe(in, x, y, alpha, secs, scale);
243 void RecordMonitor::undisplay_vframe()
245 if( !thread ) return;
246 thread->undisplay_vframe();
249 RecordMonitorGUI::RecordMonitorGUI(MWindow *mwindow,
250 Record *record, RecordMonitor *thread, int min_w)
251 : BC_Window(_(PROGRAM_NAME ": Video in"),
252 mwindow->session->rmonitor_x,
253 mwindow->session->rmonitor_y,
254 mwindow->session->rmonitor_w,
255 mwindow->session->rmonitor_h,
256 min_w, 50, 1, 1, 1, -1,
257 mwindow->get_cwindow_display())
259 //printf("%d %d\n", mwindow->session->rmonitor_w, mwindow->theme->rmonitor_meter_x);
260 this->mwindow = mwindow;
261 this->thread = thread;
262 this->record = record;
265 avc1394_transport = 0;
266 avc1394transport_title = 0;
267 avc1394transport_timecode = 0;
268 avc1394transport_thread = 0;
272 reverse_interlace = 0;
275 current_operation = MONITOR_NONE;
279 RecordMonitorGUI::~RecordMonitorGUI()
281 lock_window("RecordMonitorGUI::~RecordMonitorGUI");
282 delete signal_status;
284 if( bitmap ) delete bitmap;
285 if( channel_picker ) delete channel_picker;
286 if( avc1394transport_thread )
288 delete avc1394transport_thread;
292 if( avc1394_transport ) {
293 delete avc1394_transport;
295 if( avc1394transport_title )
296 delete avc1394transport_title;
301 void RecordMonitorGUI::create_objects()
303 // y offset for video canvas if we have the transport controls
304 lock_window("RecordMonitorGUI::create_objects");
305 int driver = mwindow->edl->session->vconfig_in->driver;
306 int do_channel = (driver == VIDEO4LINUX ||
307 driver == CAPTURE_BUZ ||
308 driver == CAPTURE_DVB ||
309 driver == VIDEO4LINUX2 ||
310 driver == VIDEO4LINUX2JPEG ||
311 driver == VIDEO4LINUX2MPEG ||
312 driver == CAPTURE_JPEG_WEBCAM ||
313 driver == CAPTURE_YUYV_WEBCAM);
314 int do_scopes = do_channel || driver == SCREENCAPTURE;
315 int do_interlace = (driver == CAPTURE_BUZ ||
316 driver == VIDEO4LINUX2JPEG);
317 int background_done = 0;
318 int do_audio = record->default_asset->audio_data;
319 int do_video = record->default_asset->video_data;
320 int do_meters = record->metering_audio;
321 int channels = !do_meters ? 0 : record->default_asset->channels;
323 mwindow->theme->get_rmonitor_sizes(do_meters, do_video,
324 do_channel || do_scopes, do_interlace, 0, channels);
329 if( driver == CAPTURE_FIREWIRE || driver == CAPTURE_IEC61883 ) {
330 avc = new AVC1394Control;
331 if( avc->device > -1 ) {
332 mwindow->theme->get_rmonitor_sizes(do_meters, do_video,
333 do_channel, do_interlace, 1, channels);
334 mwindow->theme->draw_rmonitor_bg(this);
337 avc1394_transport = new AVC1394Transport(mwindow,
340 mwindow->theme->rmonitor_tx_x,
341 mwindow->theme->rmonitor_tx_y);
342 avc1394_transport->create_objects();
344 add_subwindow(avc1394transport_timecode =
345 new BC_Title(avc1394_transport->x_end,
346 mwindow->theme->rmonitor_tx_y + 10,
351 avc1394transport_thread =
352 new AVC1394TransportThread(avc1394transport_timecode,
355 avc1394transport_thread->start();
361 if( !background_done ) {
362 mwindow->theme->draw_rmonitor_bg(this);
366 mwindow->theme->rmonitor_canvas_w = MAX(10, mwindow->theme->rmonitor_canvas_w);
367 mwindow->theme->rmonitor_canvas_h = MAX(10, mwindow->theme->rmonitor_canvas_h);
368 canvas = new RecordMonitorCanvas(mwindow, this, record,
369 mwindow->theme->rmonitor_canvas_x,
370 mwindow->theme->rmonitor_canvas_y,
371 mwindow->theme->rmonitor_canvas_w,
372 mwindow->theme->rmonitor_canvas_h);
373 canvas->create_objects(0);
374 canvas->use_rwindow();
376 if( driver == CAPTURE_DVB ) {
377 int ssw = SignalStatus::calculate_w(this);
378 signal_status = new SignalStatus(this, get_w()-ssw-3, 0);
379 add_subwindow(signal_status);
380 signal_status->create_objects();
383 int x = mwindow->theme->widget_border;
384 int y = mwindow->theme->widget_border;
386 channel_picker = new RecordChannelPicker(mwindow,
387 record, thread, this, record->channeldb,
388 mwindow->theme->rmonitor_channel_x,
389 mwindow->theme->rmonitor_channel_y);
390 channel_picker->create_objects();
391 x += channel_picker->get_w() + mwindow->theme->widget_border;
393 if( driver == CAPTURE_BUZ ||
394 driver == VIDEO4LINUX2JPEG ) {
395 add_subwindow(reverse_interlace = new ReverseInterlace(record,
396 mwindow->theme->rmonitor_interlace_x,
397 mwindow->theme->rmonitor_interlace_y));
398 x += reverse_interlace->get_w() + mwindow->theme->widget_border;
403 scope_toggle = new ScopeEnable(mwindow, thread, x, y);
404 add_subwindow(scope_toggle);
405 x += scope_toggle->get_w() + mwindow->theme->widget_border;
408 add_subwindow(monitor_menu = new BC_PopupMenu(0, 0, 0, "", 0));
409 monitor_menu->add_item(new RecordMonitorFullsize(mwindow, this));
413 if( !background_done ) {
414 mwindow->theme->draw_rmonitor_bg(this);
419 meters = new MeterPanel(mwindow,
421 mwindow->theme->rmonitor_meter_x,
422 mwindow->theme->rmonitor_meter_y,
423 record->default_asset->video_data ? -1 : mwindow->theme->rmonitor_meter_w,
424 mwindow->theme->rmonitor_meter_h,
425 channels, do_meters, 1, 0);
426 meters->create_objects();
431 int RecordMonitorGUI::button_press_event()
433 if(mwindow->session->rwindow_fullscreen && canvas && canvas->get_canvas())
434 return canvas->button_press_event_base(canvas->get_canvas());
436 if( get_buttonpress() == 2 ) {
441 if( get_buttonpress() == 3 ) {
442 monitor_menu->activate_menu();
448 int RecordMonitorGUI::cursor_leave_event()
450 if(canvas && canvas->get_canvas())
451 return canvas->cursor_leave_event_base(canvas->get_canvas());
455 int RecordMonitorGUI::cursor_enter_event()
457 if( canvas && canvas->get_canvas() )
458 return canvas->cursor_enter_event_base(canvas->get_canvas());
462 int RecordMonitorGUI::button_release_event()
464 if( canvas && canvas->get_canvas() )
465 return canvas->button_release_event();
469 int RecordMonitorGUI::cursor_motion_event()
472 if( canvas && canvas->get_canvas() ) {
473 canvas->get_canvas()->unhide_cursor();
475 return canvas->cursor_motion_event();
480 int RecordMonitorGUI::keypress_event()
484 switch(get_keypress()) {
487 record->record_gui->set_translation(--(record->video_x), record->video_y, record->video_zoom);
490 record->video_zoom -= 0.1;
491 record->record_gui->set_translation(record->video_x, record->video_y, record->video_zoom);
497 record->record_gui->set_translation(++(record->video_x), record->video_y, record->video_zoom);
500 record->video_zoom += 0.1;
501 record->record_gui->set_translation(record->video_x, record->video_y, record->video_zoom);
507 record->record_gui->set_translation(record->video_x, --(record->video_y), record->video_zoom);
510 record->video_zoom -= 0.1;
511 record->record_gui->set_translation(record->video_x, record->video_y, record->video_zoom);
517 record->record_gui->set_translation(record->video_x, ++(record->video_y), record->video_zoom);
520 record->video_zoom += 0.1;
521 record->record_gui->set_translation(record->video_x, record->video_y, record->video_zoom);
530 if(canvas) result = canvas->keypress_event(this);
531 if(!result && avc1394_transport)
532 result = avc1394_transport->keypress_event(get_keypress());
540 int RecordMonitorGUI::translation_event()
542 //printf("MWindowGUI::translation_event 1 %d %d\n", get_x(), get_y());
543 mwindow->session->rmonitor_x = get_x();
544 mwindow->session->rmonitor_y = get_y();
548 int RecordMonitorGUI::resize_event(int w, int h)
550 int driver = mwindow->edl->session->vconfig_in->driver;
551 int do_channel = (driver == VIDEO4LINUX ||
552 driver == CAPTURE_BUZ ||
553 driver == CAPTURE_DVB ||
554 driver == VIDEO4LINUX2 ||
555 driver == VIDEO4LINUX2JPEG ||
556 driver == VIDEO4LINUX2MPEG ||
557 driver == CAPTURE_JPEG_WEBCAM ||
558 driver == CAPTURE_YUYV_WEBCAM);
559 int do_scopes = do_channel || driver == SCREENCAPTURE;
560 int do_interlace = (driver == CAPTURE_BUZ ||
561 driver == VIDEO4LINUX2JPEG);
564 do_avc = avc1394_transport ? 1 : 0;
566 int do_meters = meters && record->default_asset->audio_data &&
567 record->metering_audio;
568 int do_video = record->default_asset->video_data;
570 mwindow->session->rmonitor_x = get_x();
571 mwindow->session->rmonitor_y = get_y();
572 mwindow->session->rmonitor_w = w;
573 mwindow->session->rmonitor_h = h;
575 mwindow->theme->get_rmonitor_sizes(do_meters, do_video,
576 do_channel || do_scopes, do_interlace, do_avc,
577 record->default_asset->channels);
578 mwindow->theme->draw_rmonitor_bg(this);
581 // record_transport->reposition_window(mwindow->theme->rmonitor_tx_x,
582 // mwindow->theme->rmonitor_tx_y);
584 if(avc1394_transport)
586 avc1394_transport->reposition_window(mwindow->theme->rmonitor_tx_x,
587 mwindow->theme->rmonitor_tx_y);
591 if(channel_picker) channel_picker->reposition();
592 if(reverse_interlace) reverse_interlace->reposition_window(reverse_interlace->get_x(),
593 reverse_interlace->get_y());
594 if(canvas && do_video)
596 canvas->reposition_window(0,
597 mwindow->theme->rmonitor_canvas_x,
598 mwindow->theme->rmonitor_canvas_y,
599 mwindow->theme->rmonitor_canvas_w,
600 mwindow->theme->rmonitor_canvas_h);
604 meters->reposition_window(mwindow->theme->rmonitor_meter_x,
605 mwindow->theme->rmonitor_meter_y,
606 do_video ? -1 : mwindow->theme->rmonitor_meter_w,
607 mwindow->theme->rmonitor_meter_h);
608 meters->set_meters(record->default_asset->channels,1);
611 meters->set_meters(0,0);
615 BC_WindowBase::resize_event(w, h);
620 int RecordMonitorGUI::redraw()
622 lock_window("RecordMonitorGUI::redraw");
623 int w = mwindow->session->rmonitor_w;
624 int h = mwindow->session->rmonitor_h;
625 int result = resize_event(w, h);
630 int RecordMonitorGUI::set_title()
636 scale = (int)(thread->get_scale(thread->record->video_window_w) * 100 + 0.5);
638 sprintf(string, _(PROGRAM_NAME ": Video in %d%%"), scale);
639 BC_Window::set_title(string);
643 int RecordMonitorGUI::close_event()
645 thread->record->set_video_monitoring(0);
646 thread->record->set_audio_monitoring(0);
647 thread->record->video_window_open = 0;
649 lock_window("RecordMonitorGUI::close_event");
654 int RecordMonitorGUI::create_bitmap()
656 if(bitmap && (bitmap->get_w() != get_w() ||
657 bitmap->get_h() != thread->get_canvas_height())) {
662 if( !bitmap && canvas ) {
663 // bitmap = canvas->new_bitmap(get_w(), thread->get_canvas_height());
668 void RecordMonitorGUI::enable_signal_status(int enable)
670 if( !signal_status ) return;
671 signal_status->lock_window("RecordMonitorGUI::enable_signal_status");
673 signal_status->hide_window();
675 signal_status->show_window();
676 signal_status->unlock_window();
677 DeviceDVBInput *dvb_input = record->dvb_device();
679 dvb_input->set_signal_status(!enable ? 0 : signal_status);
682 void RecordMonitorGUI::
683 display_video_text(int x, int y, const char *text, int font,
684 int bg_color, int color, int alpha, double secs, double scale)
686 lock_window("RecordMonitorGUI::display_text");
688 int ch = get_text_height(font);
689 int h = get_text_height(font,text) + ch/2;
690 int w = get_text_width(font, text) + ch;
691 BC_Pixmap pixmap(this, w, h);
694 draw_box(0, 0, w, h, &pixmap);
696 draw_text(ch/2, ch, text, strlen(text), &pixmap);
697 BC_Bitmap bitmap(this, w, h, BC_RGB888, 0);
698 VFrame in(&bitmap, w, h, BC_RGB888, -1);
699 Drawable drawable = pixmap.get_pixmap();
700 bitmap.read_drawable(drawable, 0, 0, &in);
702 record->display_vframe(&in, x, y, alpha, secs, scale);
705 ReverseInterlace::ReverseInterlace(Record *record, int x, int y)
706 : BC_CheckBox(x, y, record->reverse_interlace, _("Swap fields"))
708 this->record = record;
711 ReverseInterlace::~ReverseInterlace()
715 int ReverseInterlace::handle_event()
717 record->reverse_interlace = get_value();
721 RecordMonitorCanvas::RecordMonitorCanvas(MWindow *mwindow,
722 RecordMonitorGUI *window, Record *record,
723 int x, int y, int w, int h)
724 : Canvas(mwindow, window, x, y, w, h,
725 record->default_asset->width,
726 record->default_asset->height,
729 this->window = window;
730 this->mwindow = mwindow;
731 this->record = record;
732 //printf("RecordMonitorCanvas::RecordMonitorCanvas 1 %d %d %d %d\n",
734 //printf("RecordMonitorCanvas::RecordMonitorCanvas 2\n");
737 RecordMonitorCanvas::~RecordMonitorCanvas()
741 int RecordMonitorCanvas::get_output_w()
743 return record->default_asset->width;
746 int RecordMonitorCanvas::get_output_h()
748 return record->default_asset->height;
752 int RecordMonitorCanvas::button_press_event()
755 if(Canvas::button_press_event()) return 1;
756 if( mwindow->edl->session->vconfig_in->driver == SCREENCAPTURE ) {
757 window->current_operation = MONITOR_TRANSLATE;
758 window->translate_x_origin = record->video_x;
759 window->translate_y_origin = record->video_y;
760 window->cursor_x_origin = get_cursor_x();
761 window->cursor_y_origin = get_cursor_y();
767 void RecordMonitorCanvas::zoom_resize_window(float percentage)
769 int canvas_w, canvas_h;
770 calculate_sizes(mwindow->edl->get_aspect_ratio(),
771 record->default_asset->width, record->default_asset->height,
772 percentage, canvas_w, canvas_h);
774 new_w = canvas_w + (window->get_w() - mwindow->theme->rmonitor_canvas_w);
775 new_h = canvas_h + (window->get_h() - mwindow->theme->rmonitor_canvas_h);
776 window->resize_window(new_w, new_h);
777 window->resize_event(new_w, new_h);
780 int RecordMonitorCanvas::get_fullscreen()
782 return mwindow->session->rwindow_fullscreen;
785 void RecordMonitorCanvas::set_fullscreen(int value)
787 mwindow->session->rwindow_fullscreen = value;
791 int RecordMonitorCanvas::button_release_event()
793 window->current_operation = MONITOR_NONE;
797 int RecordMonitorCanvas::cursor_motion_event()
800 if( window->current_operation == MONITOR_TRANSLATE ) {
802 record->set_translation(
803 get_cursor_x() - window->cursor_x_origin + window->translate_x_origin,
804 get_cursor_y() - window->cursor_y_origin + window->translate_y_origin);
811 int RecordMonitorCanvas::cursor_enter_event()
813 if(mwindow->edl->session->vconfig_in->driver == SCREENCAPTURE)
814 set_cursor(MOVE_CURSOR);
818 void RecordMonitorCanvas::reset_translation()
820 record->set_translation(0, 0);
823 int RecordMonitorCanvas::keypress_event()
825 if( !get_canvas() ) return 0;
827 switch(get_canvas()->get_keypress()) {
829 record->set_translation(--record->video_x, record->video_y);
832 record->set_translation(++record->video_x, record->video_y);
835 record->set_translation(record->video_x, --record->video_y);
838 record->set_translation(record->video_x, ++record->video_y);
847 RecordMonitorFullsize::RecordMonitorFullsize(MWindow *mwindow,
848 RecordMonitorGUI *window)
849 : BC_MenuItem(_("Zoom 100%"))
851 this->mwindow = mwindow;
852 this->window = window;
854 int RecordMonitorFullsize::handle_event()
866 // ================================== slippery playback ============================
869 RecordMonitorThread::RecordMonitorThread(MWindow *mwindow,
871 RecordMonitor *record_monitor)
874 this->mwindow = mwindow;
875 this->record_monitor = record_monitor;
876 this->record = record;
879 output_lock = new Condition(1, "RecordMonitor::output_lock");
880 input_lock = new Condition(1, "RecordMonitor::input_lock");
883 void RecordMonitorThread::reset_parameters()
895 RecordMonitorThread::~RecordMonitorThread()
898 if( input_frame && !shared_data )
905 void RecordMonitorThread::init_output_format()
907 //printf("RecordMonitorThread::init_output_format 1\n");
908 switch(mwindow->edl->session->vconfig_in->driver) {
910 output_colormodel = record->vdevice->get_best_colormodel(record->default_asset);
914 case VIDEO4LINUX2JPEG:
915 jpeg_engine = new RecVideoMJPGThread(record, this,
916 mwindow->edl->session->vconfig_in->v4l2jpeg_in_fields);
917 jpeg_engine->start_rendering();
918 output_colormodel = BC_YUV422P;
921 case CAPTURE_FIREWIRE:
922 case CAPTURE_IEC61883:
923 dv_engine = new RecVideoDVThread(record, this);
924 dv_engine->start_rendering();
925 output_colormodel = BC_YUV422P;
928 case CAPTURE_JPEG_WEBCAM:
929 jpeg_engine = new RecVideoMJPGThread(record, this, 1);
930 jpeg_engine->start_rendering();
931 output_colormodel = BC_YUV420P;
934 case CAPTURE_YUYV_WEBCAM:
935 output_colormodel = BC_YUV422;
942 case VIDEO4LINUX2MPEG:
943 output_colormodel = record->vdevice->get_best_colormodel(record->default_asset);
944 //printf("RecordMonitorThread::init_output_format 2 %d\n", output_colormodel);
949 int RecordMonitorThread::start_playback()
954 output_lock->lock("RecordMonitorThread::start_playback");
959 int RecordMonitorThread::stop_playback()
963 output_lock->unlock();
965 //printf("RecordMonitorThread::stop_playback 1\n");
967 switch(mwindow->edl->session->vconfig_in->driver) {
969 case VIDEO4LINUX2JPEG:
971 jpeg_engine->stop_rendering();
977 case CAPTURE_FIREWIRE:
978 case CAPTURE_IEC61883:
980 dv_engine->stop_rendering();
986 case VIDEO4LINUX2MPEG:
989 //printf("RecordMonitorThread::stop_playback 4\n");
994 int RecordMonitorThread::write_frame(VFrame *new_frame)
998 shared_data = (new_frame->get_color_model() != BC_COMPRESSED);
1001 // Need to wait until after Record creates the input device before starting monitor
1002 // because the input device deterimes the output format.
1004 if( !output_frame ) init_output_format();
1005 if( !shared_data ) {
1006 if(!input_frame) input_frame = new VFrame;
1007 input_frame->allocate_compressed_data(new_frame->get_compressed_size());
1008 memcpy(input_frame->get_data(),
1009 new_frame->get_data(),
1010 new_frame->get_compressed_size());
1011 input_frame->set_compressed_size(new_frame->get_compressed_size());
1012 input_frame->set_field2_offset(new_frame->get_field2_offset());
1015 input_lock->lock("RecordMonitorThread::write_frame");
1016 input_frame = new_frame;
1018 output_lock->unlock();
1023 int RecordMonitorThread::render_jpeg()
1025 //printf("RecordMonitorThread::render_jpeg 1\n");
1026 jpeg_engine->render_frame(input_frame, input_frame->get_compressed_size());
1027 //printf("RecordMonitorThread::render_jpeg 2\n");
1031 int RecordMonitorThread::render_dv()
1033 dv_engine->render_frame(input_frame, input_frame->get_compressed_size());
1037 void RecordMonitorThread::render_uncompressed()
1039 output_frame->copy_from(input_frame);
1042 void RecordMonitorThread::show_output_frame()
1044 if( ovly && ovly->overlay(output_frame) )
1046 record_monitor->device->write_buffer(output_frame, record->edl);
1050 void RecordMonitorThread::unlock_input()
1052 if(shared_data) input_lock->unlock();
1055 void RecordMonitorThread::lock_input()
1057 if(shared_data) input_lock->lock();
1060 int RecordMonitorThread::render_frame()
1062 switch(mwindow->edl->session->vconfig_in->driver) {
1064 case VIDEO4LINUX2JPEG:
1065 case CAPTURE_JPEG_WEBCAM:
1069 case CAPTURE_FIREWIRE:
1070 case CAPTURE_IEC61883:
1075 render_uncompressed();
1082 void RecordMonitorThread::new_output_frame()
1084 record_monitor->device->new_output_buffer(&output_frame, output_colormodel);
1087 void RecordMonitorThread::
1088 display_vframe(VFrame *in, int x, int y, int alpha, double secs, double scale)
1091 int ticks = secs * SESSION->vconfig_in->in_framerate;
1092 scale *= SESSION->vconfig_in->h / 1080.;
1093 ovly = new RecVideoOverlay(in, x, y, ticks, scale, alpha/255.);
1097 RecVideoOverlay(VFrame *vframe, int x, int y, int ticks, float scale, float alpha)
1101 this->ticks = ticks;
1102 this->scale = scale;
1103 this->alpha = alpha;
1104 this->vframe = new VFrame(*vframe);
1113 int RecVideoOverlay::
1114 overlay(VFrame *out)
1116 VFrame *in = vframe;
1117 int xx = x * scale, yy = y * scale;
1118 int w = in->get_w(), h = in->get_h();
1119 int ww = w * scale, hh = h * scale;
1120 BC_CModels::transfer(out->get_rows(), in->get_rows(),
1121 out->get_y(), out->get_u(), out->get_v(),
1122 in->get_y(), in->get_u(), in->get_v(),
1123 0, 0, w, h, xx, yy, ww, hh,
1124 in->get_color_model(), out->get_color_model(), 0,
1125 in->get_bytes_per_line(), out->get_bytes_per_line());
1126 return ticks > 0 && --ticks == 0 ? 1 : 0;
1129 void RecordMonitorThread::
1132 delete ovly; ovly = 0;
1135 void RecordMonitorThread::run()
1137 //printf("RecordMonitorThread::run 1 %d\n", getpid());
1139 // Wait for next frame
1141 output_lock->lock("RecordMonitorThread::run");
1152 record_monitor->scope_thread->process(output_frame);
1154 show_output_frame();
1164 RecVideoMJPGThread::RecVideoMJPGThread(Record *record,
1165 RecordMonitorThread *thread,
1168 this->record = record;
1169 this->thread = thread;
1171 this->fields = fields;
1174 RecVideoMJPGThread::~RecVideoMJPGThread()
1178 int RecVideoMJPGThread::start_rendering()
1180 mjpeg = mjpeg_new(record->default_asset->width,
1181 record->default_asset->height,
1183 //printf("RecVideoMJPGThread::start_rendering 1 %p\n", mjpeg);
1187 int RecVideoMJPGThread::stop_rendering()
1189 //printf("RecVideoMJPGThread::stop_rendering 1 %p\n", mjpeg);
1190 if(mjpeg) mjpeg_delete(mjpeg);
1191 //printf("RecVideoMJPGThread::stop_rendering 2\n");
1195 int RecVideoMJPGThread::render_frame(VFrame *frame, long size)
1197 // printf("RecVideoMJPGThread::render_frame %d %02x%02x %02x%02x\n",
1198 // frame->get_field2_offset(),
1199 // frame->get_data()[0],
1200 // frame->get_data()[1],
1201 // frame->get_data()[frame->get_field2_offset()],
1202 // frame->get_data()[frame->get_field2_offset() + 1]);
1203 //frame->set_field2_offset(0);
1204 mjpeg_decompress(mjpeg,
1206 frame->get_compressed_size(),
1207 frame->get_field2_offset(),
1208 thread->output_frame->get_rows(),
1209 thread->output_frame->get_y(),
1210 thread->output_frame->get_u(),
1211 thread->output_frame->get_v(),
1212 thread->output_frame->get_color_model(),
1213 record->mwindow->preferences->processors);
1220 RecVideoDVThread::RecVideoDVThread(Record *record, RecordMonitorThread *thread)
1222 this->record = record;
1223 this->thread = thread;
1227 RecVideoDVThread::~RecVideoDVThread()
1232 int RecVideoDVThread::start_rendering()
1238 int RecVideoDVThread::stop_rendering()
1240 if( dv ) { dv_delete(((dv_t*)dv)); dv = 0; }
1244 int RecVideoDVThread::render_frame(VFrame *frame, long size)
1246 unsigned char *yuv_planes[3];
1247 yuv_planes[0] = thread->output_frame->get_y();
1248 yuv_planes[1] = thread->output_frame->get_u();
1249 yuv_planes[2] = thread->output_frame->get_v();
1250 dv_read_video(((dv_t*)dv),
1253 frame->get_compressed_size(),
1254 thread->output_frame->get_color_model());