3 #include "channelpicker.h"
8 #include "edlsession.h"
11 #include "meterpanel.h"
13 #include "playbackconfig.h"
14 #include "preferences.h"
16 #include "recordconfig.h"
17 #include "recordgui.h"
18 #include "recordtransport.h"
19 #include "recordmonitor.h"
20 #include "mainsession.h"
22 #include "videodevice.inc"
24 #include "videodevice.h"
27 RecordMonitor::RecordMonitor(MWindow *mwindow, Record *record)
30 this->mwindow = mwindow;
31 this->record = record;
37 RecordMonitor::~RecordMonitor()
41 thread->stop_playback();
54 int RecordMonitor::create_objects()
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);
63 window = new RecordMonitorGUI(mwindow,
68 window->create_objects();
71 if(record->default_asset->video_data)
73 // Configure the output for record monitoring
74 VideoOutConfig config;
76 device = new VideoDevice;
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;
88 device->open_output(&config,
89 record->default_asset->frame_rate,
90 record->default_asset->width,
91 record->default_asset->height,
96 thread = new RecordMonitorThread(mwindow, record, this);
98 thread->start_playback();
108 void RecordMonitor::run()
110 window->run_window();
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)
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)
147 ((float)record->frame_h *
148 mwindow->edl->get_aspect_ratio());
152 return (float)w / record->frame_w;
156 int RecordMonitor::get_canvas_height()
158 return window->get_h() - get_mbuttons_height();
161 int RecordMonitor::get_channel_x()
167 int RecordMonitor::get_channel_y()
181 RecordMonitorGUI::RecordMonitorGUI(MWindow *mwindow,
183 RecordMonitor *thread,
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,
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;
202 avc1394_transport = 0;
203 avc1394transport_title = 0;
204 avc1394transport_timecode = 0;
205 avc1394transport_thread = 0;
209 reverse_interlace = 0;
212 current_operation = MONITOR_NONE;
215 RecordMonitorGUI::~RecordMonitorGUI()
218 if(bitmap) delete bitmap;
219 if(channel_picker) delete channel_picker;
221 if(avc1394transport_thread)
222 delete avc1394transport_thread;
227 if(avc1394_transport)
229 delete avc1394_transport;
231 if(avc1394transport_title)
232 delete avc1394transport_title;
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,
252 record->default_asset->channels);
259 if(record->default_asset->video_data)
261 int driver = mwindow->edl->session->vconfig_in->driver;
264 if(driver == CAPTURE_FIREWIRE ||
265 driver == CAPTURE_IEC61883)
267 avc = new AVC1394Control;
270 mwindow->theme->get_rmonitor_sizes(record->default_asset->audio_data,
271 record->default_asset->video_data,
275 record->default_asset->channels);
276 mwindow->theme->draw_rmonitor_bg(this);
279 avc1394_transport = new AVC1394Transport(mwindow,
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,
293 avc1394transport_thread =
294 new AVC1394TransportThread(avc1394transport_timecode,
297 avc1394transport_thread->start();
306 mwindow->theme->draw_rmonitor_bg(this);
310 mwindow->theme->rmonitor_canvas_w = MAX(10, mwindow->theme->rmonitor_canvas_w);
311 mwindow->theme->rmonitor_canvas_h = MAX(10, mwindow->theme->rmonitor_canvas_h);
312 canvas = new RecordMonitorCanvas(mwindow,
315 mwindow->theme->rmonitor_canvas_x,
316 mwindow->theme->rmonitor_canvas_y,
317 mwindow->theme->rmonitor_canvas_w,
318 mwindow->theme->rmonitor_canvas_h);
319 canvas->create_objects(0);
321 if(driver == VIDEO4LINUX ||
322 driver == CAPTURE_BUZ ||
323 driver == VIDEO4LINUX2 ||
324 driver == VIDEO4LINUX2JPEG)
326 channel_picker = new ChannelPicker(mwindow,
330 mwindow->theme->rmonitor_channel_x,
331 mwindow->theme->rmonitor_channel_y);
332 channel_picker->create_objects();
335 if(driver == CAPTURE_BUZ ||
336 driver == VIDEO4LINUX2JPEG)
338 add_subwindow(reverse_interlace = new ReverseInterlace(record,
339 mwindow->theme->rmonitor_interlace_x,
340 mwindow->theme->rmonitor_interlace_y));
343 add_subwindow(monitor_menu = new BC_PopupMenu(0,
348 monitor_menu->add_item(new RecordMonitorFullsize(mwindow,
355 mwindow->theme->draw_rmonitor_bg(this);
359 if(record->default_asset->audio_data)
361 meters = new MeterPanel(mwindow,
363 mwindow->theme->rmonitor_meter_x,
364 mwindow->theme->rmonitor_meter_y,
365 mwindow->theme->rmonitor_meter_h,
366 record->default_asset->channels,
369 meters->create_objects();
374 int RecordMonitorGUI::button_press_event()
376 if(mwindow->session->rwindow_fullscreen && canvas && canvas->get_canvas())
377 return canvas->button_press_event_base(canvas->get_canvas());
379 if(get_buttonpress() == 2)
385 if(get_buttonpress() == 3)
387 monitor_menu->activate_menu();
393 int RecordMonitorGUI::cursor_leave_event()
395 if(canvas && canvas->get_canvas())
396 return canvas->cursor_leave_event_base(canvas->get_canvas());
400 int RecordMonitorGUI::cursor_enter_event()
402 if(canvas && canvas->get_canvas())
403 return canvas->cursor_enter_event_base(canvas->get_canvas());
407 int RecordMonitorGUI::button_release_event()
409 if(canvas && canvas->get_canvas())
410 return canvas->button_release_event();
414 int RecordMonitorGUI::cursor_motion_event()
417 if(canvas && canvas->get_canvas())
420 canvas->get_canvas()->unhide_cursor();
422 return canvas->cursor_motion_event();
427 int RecordMonitorGUI::keypress_event()
430 switch(get_keypress())
435 record->record_gui->set_translation(--(record->video_x), record->video_y, record->video_zoom);
439 record->video_zoom -= 0.1;
440 record->record_gui->set_translation(record->video_x, record->video_y, record->video_zoom);
447 record->record_gui->set_translation(++(record->video_x), record->video_y, record->video_zoom);
451 record->video_zoom += 0.1;
452 record->record_gui->set_translation(record->video_x, record->video_y, record->video_zoom);
459 record->record_gui->set_translation(record->video_x, --(record->video_y), record->video_zoom);
463 record->video_zoom -= 0.1;
464 record->record_gui->set_translation(record->video_x, record->video_y, record->video_zoom);
471 record->record_gui->set_translation(record->video_x, ++(record->video_y), record->video_zoom);
475 record->video_zoom += 0.1;
476 record->record_gui->set_translation(record->video_x, record->video_y, record->video_zoom);
484 result = canvas->keypress_event(this);
486 if(!result && avc1394_transport)
487 result = avc1394_transport->keypress_event(get_keypress());
495 int RecordMonitorGUI::translation_event()
497 //printf("MWindowGUI::translation_event 1 %d %d\n", get_x(), get_y());
498 mwindow->session->rmonitor_x = get_x();
499 mwindow->session->rmonitor_y = get_y();
503 int RecordMonitorGUI::resize_event(int w, int h)
505 int do_channel = (mwindow->edl->session->vconfig_in->driver == VIDEO4LINUX ||
506 mwindow->edl->session->vconfig_in->driver == CAPTURE_BUZ ||
507 mwindow->edl->session->vconfig_in->driver == VIDEO4LINUX2 ||
508 mwindow->edl->session->vconfig_in->driver == VIDEO4LINUX2JPEG);
509 int do_interlace = (mwindow->edl->session->vconfig_in->driver == CAPTURE_BUZ ||
510 mwindow->edl->session->vconfig_in->driver == VIDEO4LINUX2JPEG);
513 do_avc = avc1394_transport ? 1 : 0;
516 mwindow->session->rmonitor_x = get_x();
517 mwindow->session->rmonitor_y = get_y();
518 mwindow->session->rmonitor_w = w;
519 mwindow->session->rmonitor_h = h;
521 mwindow->theme->get_rmonitor_sizes(record->default_asset->audio_data,
522 record->default_asset->video_data,
526 record->default_asset->channels);
527 mwindow->theme->draw_rmonitor_bg(this);
531 // record_transport->reposition_window(mwindow->theme->rmonitor_tx_x,
532 // mwindow->theme->rmonitor_tx_y);
534 if(avc1394_transport)
536 avc1394_transport->reposition_window(mwindow->theme->rmonitor_tx_x,
537 mwindow->theme->rmonitor_tx_y);
541 if(channel_picker) channel_picker->reposition();
542 if(reverse_interlace) reverse_interlace->reposition_window(reverse_interlace->get_x(),
543 reverse_interlace->get_y());
544 if(canvas && record->default_asset->video_data)
546 canvas->reposition_window(0,
547 mwindow->theme->rmonitor_canvas_x,
548 mwindow->theme->rmonitor_canvas_y,
549 mwindow->theme->rmonitor_canvas_w,
550 mwindow->theme->rmonitor_canvas_h);
553 if(record->default_asset->audio_data)
555 meters->reposition_window(mwindow->theme->rmonitor_meter_x,
556 mwindow->theme->rmonitor_meter_y,
557 mwindow->theme->rmonitor_meter_h);
561 BC_WindowBase::resize_event(w, h);
567 int RecordMonitorGUI::set_title()
573 scale = (int)(thread->get_scale(thread->record->video_window_w) * 100 + 0.5);
575 sprintf(string, PROGRAM_NAME ": Video in %d%%", scale);
576 BC_Window::set_title(string);
580 int RecordMonitorGUI::close_event()
582 thread->record->monitor_video = 0;
583 thread->record->monitor_audio = 0;
584 thread->record->video_window_open = 0;
587 record->record_gui->lock_window("RecordMonitorGUI::close_event");
588 if(record->record_gui->monitor_video) record->record_gui->monitor_video->update(0);
589 if(record->record_gui->monitor_audio) record->record_gui->monitor_audio->update(0);
590 record->record_gui->flush();
591 record->record_gui->unlock_window();
594 lock_window("RecordMonitorGUI::close_event");
599 int RecordMonitorGUI::create_bitmap()
602 (bitmap->get_w() != get_w() ||
603 bitmap->get_h() != thread->get_canvas_height()))
609 if(!bitmap && canvas)
611 // bitmap = canvas->new_bitmap(get_w(), thread->get_canvas_height());
616 ReverseInterlace::ReverseInterlace(Record *record, int x, int y)
617 : BC_CheckBox(x, y, record->reverse_interlace, _("Swap fields"))
619 this->record = record;
622 ReverseInterlace::~ReverseInterlace()
626 int ReverseInterlace::handle_event()
628 record->reverse_interlace = get_value();
632 RecordMonitorCanvas::RecordMonitorCanvas(MWindow *mwindow,
633 RecordMonitorGUI *window,
645 record->default_asset->width,
646 record->default_asset->height,
651 this->window = window;
652 this->mwindow = mwindow;
653 this->record = record;
654 printf("RecordMonitorCanvas::RecordMonitorCanvas 1 %d %d %d %d\n",
656 //printf("RecordMonitorCanvas::RecordMonitorCanvas 2\n");
659 RecordMonitorCanvas::~RecordMonitorCanvas()
663 int RecordMonitorCanvas::get_output_w()
665 return record->default_asset->width;
668 int RecordMonitorCanvas::get_output_h()
670 return record->default_asset->height;
674 int RecordMonitorCanvas::button_press_event()
677 if(Canvas::button_press_event()) return 1;
679 if(mwindow->edl->session->vconfig_in->driver == SCREENCAPTURE)
681 window->current_operation = MONITOR_TRANSLATE;
682 window->translate_x_origin = record->video_x;
683 window->translate_y_origin = record->video_y;
684 window->cursor_x_origin = get_cursor_x();
685 window->cursor_y_origin = get_cursor_y();
691 void RecordMonitorCanvas::zoom_resize_window(float percentage)
693 int canvas_w, canvas_h;
694 calculate_sizes(mwindow->edl->get_aspect_ratio(),
695 record->default_asset->width,
696 record->default_asset->height,
701 new_w = canvas_w + (window->get_w() - mwindow->theme->rmonitor_canvas_w);
702 new_h = canvas_h + (window->get_h() - mwindow->theme->rmonitor_canvas_h);
703 window->resize_window(new_w, new_h);
704 window->resize_event(new_w, new_h);
707 int RecordMonitorCanvas::get_fullscreen()
709 return mwindow->session->rwindow_fullscreen;
712 void RecordMonitorCanvas::set_fullscreen(int value)
714 mwindow->session->rwindow_fullscreen = value;
718 int RecordMonitorCanvas::button_release_event()
720 window->current_operation = MONITOR_NONE;
724 int RecordMonitorCanvas::cursor_motion_event()
727 if(window->current_operation == MONITOR_TRANSLATE)
730 record->set_translation(
731 get_cursor_x() - window->cursor_x_origin + window->translate_x_origin,
732 get_cursor_y() - window->cursor_y_origin + window->translate_y_origin);
739 int RecordMonitorCanvas::cursor_enter_event()
741 if(mwindow->edl->session->vconfig_in->driver == SCREENCAPTURE)
742 set_cursor(MOVE_CURSOR);
746 void RecordMonitorCanvas::reset_translation()
748 record->set_translation(0, 0);
751 int RecordMonitorCanvas::keypress_event()
754 switch(get_canvas() && get_canvas()->get_keypress())
757 record->set_translation(--record->video_x, record->video_y);
760 record->set_translation(++record->video_x, record->video_y);
763 record->set_translation(record->video_x, --record->video_y);
766 record->set_translation(record->video_x, ++record->video_y);
773 RecordMonitorFullsize::RecordMonitorFullsize(MWindow *mwindow,
774 RecordMonitorGUI *window)
775 : BC_MenuItem(_("Zoom 100%"))
777 this->mwindow = mwindow;
778 this->window = window;
780 int RecordMonitorFullsize::handle_event()
792 // ================================== slippery playback ============================
795 RecordMonitorThread::RecordMonitorThread(MWindow *mwindow,
797 RecordMonitor *record_monitor)
800 this->mwindow = mwindow;
801 this->record_monitor = record_monitor;
802 this->record = record;
804 output_lock = new Condition(1, "RecordMonitor::output_lock");
805 input_lock = new Condition(1, "RecordMonitor::input_lock");
809 void RecordMonitorThread::reset_parameters()
820 RecordMonitorThread::~RecordMonitorThread()
822 if(input_frame && !shared_data) delete input_frame;
827 void RecordMonitorThread::init_output_format()
831 //printf("RecordMonitorThread::init_output_format 1\n");
832 switch(mwindow->edl->session->vconfig_in->driver)
835 output_colormodel = record->vdevice->get_best_colormodel(record->default_asset);
840 case VIDEO4LINUX2JPEG:
841 jpeg_engine = new RecVideoMJPGThread(record, this);
842 jpeg_engine->start_rendering();
843 output_colormodel = BC_YUV422P;
846 case CAPTURE_FIREWIRE:
847 case CAPTURE_IEC61883:
848 dv_engine = new RecVideoDVThread(record, this);
849 dv_engine->start_rendering();
850 output_colormodel = BC_YUV422P;
855 output_colormodel = record->vdevice->get_best_colormodel(record->default_asset);
856 //printf("RecordMonitorThread::init_output_format 2 %d\n", output_colormodel);
861 int RecordMonitorThread::start_playback()
865 output_lock->lock("RecordMonitorThread::start_playback");
870 int RecordMonitorThread::stop_playback()
873 output_lock->unlock();
875 //printf("RecordMonitorThread::stop_playback 1\n");
877 switch(mwindow->edl->session->vconfig_in->driver)
880 case VIDEO4LINUX2JPEG:
883 jpeg_engine->stop_rendering();
888 case CAPTURE_FIREWIRE:
889 case CAPTURE_IEC61883:
892 dv_engine->stop_rendering();
897 //printf("RecordMonitorThread::stop_playback 4\n");
902 int RecordMonitorThread::write_frame(VFrame *new_frame)
907 shared_data = (new_frame->get_color_model() != BC_COMPRESSED);
910 // Need to wait until after Record creates the input device before starting monitor
911 // because the input device deterimes the output format.
913 if(!output_frame) init_output_format();
916 if(!input_frame) input_frame = new VFrame;
917 input_frame->allocate_compressed_data(new_frame->get_compressed_size());
918 memcpy(input_frame->get_data(),
919 new_frame->get_data(),
920 new_frame->get_compressed_size());
921 input_frame->set_compressed_size(new_frame->get_compressed_size());
922 input_frame->set_field2_offset(new_frame->get_field2_offset());
926 input_lock->lock("RecordMonitorThread::write_frame");
927 input_frame = new_frame;
929 output_lock->unlock();
934 int RecordMonitorThread::render_jpeg()
936 //printf("RecordMonitorThread::render_jpeg 1\n");
937 jpeg_engine->render_frame(input_frame, input_frame->get_compressed_size());
938 //printf("RecordMonitorThread::render_jpeg 2\n");
942 int RecordMonitorThread::render_dv()
944 dv_engine->render_frame(input_frame, input_frame->get_compressed_size());
948 void RecordMonitorThread::render_uncompressed()
950 output_frame->copy_from(input_frame);
953 void RecordMonitorThread::show_output_frame()
955 record_monitor->device->write_buffer(output_frame, record->edl);
958 void RecordMonitorThread::unlock_input()
960 if(shared_data) input_lock->unlock();
963 int RecordMonitorThread::render_frame()
965 switch(mwindow->edl->session->vconfig_in->driver)
968 case VIDEO4LINUX2JPEG:
972 case CAPTURE_FIREWIRE:
973 case CAPTURE_IEC61883:
978 render_uncompressed();
985 void RecordMonitorThread::new_output_frame()
988 record_monitor->device->new_output_buffer(&output_frame, output_colormodel);
991 void RecordMonitorThread::run()
993 //printf("RecordMonitorThread::run 1 %d\n", getpid());
996 // Wait for next frame
998 output_lock->lock("RecordMonitorThread::run");
1011 show_output_frame();
1021 RecVideoMJPGThread::RecVideoMJPGThread(Record *record, RecordMonitorThread *thread)
1023 this->record = record;
1024 this->thread = thread;
1028 RecVideoMJPGThread::~RecVideoMJPGThread()
1032 int RecVideoMJPGThread::start_rendering()
1034 mjpeg = mjpeg_new(record->default_asset->width,
1035 record->default_asset->height,
1037 //printf("RecVideoMJPGThread::start_rendering 1 %p\n", mjpeg);
1041 int RecVideoMJPGThread::stop_rendering()
1043 //printf("RecVideoMJPGThread::stop_rendering 1 %p\n", mjpeg);
1044 if(mjpeg) mjpeg_delete(mjpeg);
1045 //printf("RecVideoMJPGThread::stop_rendering 2\n");
1049 int RecVideoMJPGThread::render_frame(VFrame *frame, long size)
1051 // printf("RecVideoMJPGThread::render_frame %d %02x%02x %02x%02x\n",
1052 // frame->get_field2_offset(),
1053 // frame->get_data()[0],
1054 // frame->get_data()[1],
1055 // frame->get_data()[frame->get_field2_offset()],
1056 // frame->get_data()[frame->get_field2_offset() + 1]);
1057 //frame->set_field2_offset(0);
1058 mjpeg_decompress(mjpeg,
1060 frame->get_compressed_size(),
1061 frame->get_field2_offset(),
1062 thread->output_frame->get_rows(),
1063 thread->output_frame->get_y(),
1064 thread->output_frame->get_u(),
1065 thread->output_frame->get_v(),
1066 thread->output_frame->get_color_model(),
1067 record->mwindow->preferences->processors);
1074 RecVideoDVThread::RecVideoDVThread(Record *record, RecordMonitorThread *thread)
1076 this->record = record;
1077 this->thread = thread;
1081 RecVideoDVThread::~RecVideoDVThread()
1086 int RecVideoDVThread::start_rendering()
1092 int RecVideoDVThread::stop_rendering()
1094 if(dv) dv_delete(((dv_t*)dv));
1098 int RecVideoDVThread::render_frame(VFrame *frame, long size)
1100 unsigned char *yuv_planes[3];
1101 yuv_planes[0] = thread->output_frame->get_y();
1102 yuv_planes[1] = thread->output_frame->get_u();
1103 yuv_planes[2] = thread->output_frame->get_v();
1104 dv_read_video(((dv_t*)dv),
1107 frame->get_compressed_size(),
1108 thread->output_frame->get_color_model());