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 RecordChannelPicker(mwindow,
331 mwindow->theme->rmonitor_channel_x,
332 mwindow->theme->rmonitor_channel_y);
333 channel_picker->create_objects();
336 if(driver == CAPTURE_BUZ ||
337 driver == VIDEO4LINUX2JPEG)
339 add_subwindow(reverse_interlace = new ReverseInterlace(record,
340 mwindow->theme->rmonitor_interlace_x,
341 mwindow->theme->rmonitor_interlace_y));
344 add_subwindow(monitor_menu = new BC_PopupMenu(0,
349 monitor_menu->add_item(new RecordMonitorFullsize(mwindow,
356 mwindow->theme->draw_rmonitor_bg(this);
360 if(record->default_asset->audio_data)
362 meters = new MeterPanel(mwindow,
364 mwindow->theme->rmonitor_meter_x,
365 mwindow->theme->rmonitor_meter_y,
366 mwindow->theme->rmonitor_meter_h,
367 record->default_asset->channels,
370 meters->create_objects();
375 int RecordMonitorGUI::button_press_event()
377 if(mwindow->session->rwindow_fullscreen && canvas && canvas->get_canvas())
378 return canvas->button_press_event_base(canvas->get_canvas());
380 if(get_buttonpress() == 2)
386 if(get_buttonpress() == 3)
388 monitor_menu->activate_menu();
394 int RecordMonitorGUI::cursor_leave_event()
396 if(canvas && canvas->get_canvas())
397 return canvas->cursor_leave_event_base(canvas->get_canvas());
401 int RecordMonitorGUI::cursor_enter_event()
403 if(canvas && canvas->get_canvas())
404 return canvas->cursor_enter_event_base(canvas->get_canvas());
408 int RecordMonitorGUI::button_release_event()
410 if(canvas && canvas->get_canvas())
411 return canvas->button_release_event();
415 int RecordMonitorGUI::cursor_motion_event()
418 if(canvas && canvas->get_canvas())
421 canvas->get_canvas()->unhide_cursor();
423 return canvas->cursor_motion_event();
428 int RecordMonitorGUI::keypress_event()
431 switch(get_keypress())
436 record->record_gui->set_translation(--(record->video_x), record->video_y, record->video_zoom);
440 record->video_zoom -= 0.1;
441 record->record_gui->set_translation(record->video_x, record->video_y, record->video_zoom);
448 record->record_gui->set_translation(++(record->video_x), record->video_y, record->video_zoom);
452 record->video_zoom += 0.1;
453 record->record_gui->set_translation(record->video_x, record->video_y, record->video_zoom);
460 record->record_gui->set_translation(record->video_x, --(record->video_y), record->video_zoom);
464 record->video_zoom -= 0.1;
465 record->record_gui->set_translation(record->video_x, record->video_y, record->video_zoom);
472 record->record_gui->set_translation(record->video_x, ++(record->video_y), record->video_zoom);
476 record->video_zoom += 0.1;
477 record->record_gui->set_translation(record->video_x, record->video_y, record->video_zoom);
485 result = canvas->keypress_event(this);
487 if(!result && avc1394_transport)
488 result = avc1394_transport->keypress_event(get_keypress());
496 int RecordMonitorGUI::translation_event()
498 //printf("MWindowGUI::translation_event 1 %d %d\n", get_x(), get_y());
499 mwindow->session->rmonitor_x = get_x();
500 mwindow->session->rmonitor_y = get_y();
504 int RecordMonitorGUI::resize_event(int w, int h)
506 int do_channel = (mwindow->edl->session->vconfig_in->driver == VIDEO4LINUX ||
507 mwindow->edl->session->vconfig_in->driver == CAPTURE_BUZ ||
508 mwindow->edl->session->vconfig_in->driver == VIDEO4LINUX2 ||
509 mwindow->edl->session->vconfig_in->driver == VIDEO4LINUX2JPEG);
510 int do_interlace = (mwindow->edl->session->vconfig_in->driver == CAPTURE_BUZ ||
511 mwindow->edl->session->vconfig_in->driver == VIDEO4LINUX2JPEG);
514 do_avc = avc1394_transport ? 1 : 0;
517 mwindow->session->rmonitor_x = get_x();
518 mwindow->session->rmonitor_y = get_y();
519 mwindow->session->rmonitor_w = w;
520 mwindow->session->rmonitor_h = h;
522 mwindow->theme->get_rmonitor_sizes(record->default_asset->audio_data,
523 record->default_asset->video_data,
527 record->default_asset->channels);
528 mwindow->theme->draw_rmonitor_bg(this);
532 // record_transport->reposition_window(mwindow->theme->rmonitor_tx_x,
533 // mwindow->theme->rmonitor_tx_y);
535 if(avc1394_transport)
537 avc1394_transport->reposition_window(mwindow->theme->rmonitor_tx_x,
538 mwindow->theme->rmonitor_tx_y);
542 if(channel_picker) channel_picker->reposition();
543 if(reverse_interlace) reverse_interlace->reposition_window(reverse_interlace->get_x(),
544 reverse_interlace->get_y());
545 if(canvas && record->default_asset->video_data)
547 canvas->reposition_window(0,
548 mwindow->theme->rmonitor_canvas_x,
549 mwindow->theme->rmonitor_canvas_y,
550 mwindow->theme->rmonitor_canvas_w,
551 mwindow->theme->rmonitor_canvas_h);
554 if(record->default_asset->audio_data)
556 meters->reposition_window(mwindow->theme->rmonitor_meter_x,
557 mwindow->theme->rmonitor_meter_y,
558 mwindow->theme->rmonitor_meter_h);
562 BC_WindowBase::resize_event(w, h);
568 int RecordMonitorGUI::set_title()
574 scale = (int)(thread->get_scale(thread->record->video_window_w) * 100 + 0.5);
576 sprintf(string, PROGRAM_NAME ": Video in %d%%", scale);
577 BC_Window::set_title(string);
581 int RecordMonitorGUI::close_event()
583 thread->record->monitor_video = 0;
584 thread->record->monitor_audio = 0;
585 thread->record->video_window_open = 0;
588 record->record_gui->lock_window("RecordMonitorGUI::close_event");
589 if(record->record_gui->monitor_video) record->record_gui->monitor_video->update(0);
590 if(record->record_gui->monitor_audio) record->record_gui->monitor_audio->update(0);
591 record->record_gui->flush();
592 record->record_gui->unlock_window();
595 lock_window("RecordMonitorGUI::close_event");
600 int RecordMonitorGUI::create_bitmap()
603 (bitmap->get_w() != get_w() ||
604 bitmap->get_h() != thread->get_canvas_height()))
610 if(!bitmap && canvas)
612 // bitmap = canvas->new_bitmap(get_w(), thread->get_canvas_height());
617 ReverseInterlace::ReverseInterlace(Record *record, int x, int y)
618 : BC_CheckBox(x, y, record->reverse_interlace, _("Swap fields"))
620 this->record = record;
623 ReverseInterlace::~ReverseInterlace()
627 int ReverseInterlace::handle_event()
629 record->reverse_interlace = get_value();
633 RecordMonitorCanvas::RecordMonitorCanvas(MWindow *mwindow,
634 RecordMonitorGUI *window,
646 record->default_asset->width,
647 record->default_asset->height,
652 this->window = window;
653 this->mwindow = mwindow;
654 this->record = record;
655 printf("RecordMonitorCanvas::RecordMonitorCanvas 1 %d %d %d %d\n",
657 //printf("RecordMonitorCanvas::RecordMonitorCanvas 2\n");
660 RecordMonitorCanvas::~RecordMonitorCanvas()
664 int RecordMonitorCanvas::get_output_w()
666 return record->default_asset->width;
669 int RecordMonitorCanvas::get_output_h()
671 return record->default_asset->height;
675 int RecordMonitorCanvas::button_press_event()
678 if(Canvas::button_press_event()) return 1;
680 if(mwindow->edl->session->vconfig_in->driver == SCREENCAPTURE)
682 window->current_operation = MONITOR_TRANSLATE;
683 window->translate_x_origin = record->video_x;
684 window->translate_y_origin = record->video_y;
685 window->cursor_x_origin = get_cursor_x();
686 window->cursor_y_origin = get_cursor_y();
692 void RecordMonitorCanvas::zoom_resize_window(float percentage)
694 int canvas_w, canvas_h;
695 calculate_sizes(mwindow->edl->get_aspect_ratio(),
696 record->default_asset->width,
697 record->default_asset->height,
702 new_w = canvas_w + (window->get_w() - mwindow->theme->rmonitor_canvas_w);
703 new_h = canvas_h + (window->get_h() - mwindow->theme->rmonitor_canvas_h);
704 window->resize_window(new_w, new_h);
705 window->resize_event(new_w, new_h);
708 int RecordMonitorCanvas::get_fullscreen()
710 return mwindow->session->rwindow_fullscreen;
713 void RecordMonitorCanvas::set_fullscreen(int value)
715 mwindow->session->rwindow_fullscreen = value;
719 int RecordMonitorCanvas::button_release_event()
721 window->current_operation = MONITOR_NONE;
725 int RecordMonitorCanvas::cursor_motion_event()
728 if(window->current_operation == MONITOR_TRANSLATE)
731 record->set_translation(
732 get_cursor_x() - window->cursor_x_origin + window->translate_x_origin,
733 get_cursor_y() - window->cursor_y_origin + window->translate_y_origin);
740 int RecordMonitorCanvas::cursor_enter_event()
742 if(mwindow->edl->session->vconfig_in->driver == SCREENCAPTURE)
743 set_cursor(MOVE_CURSOR);
747 void RecordMonitorCanvas::reset_translation()
749 record->set_translation(0, 0);
752 int RecordMonitorCanvas::keypress_event()
755 switch(get_canvas() && get_canvas()->get_keypress())
758 record->set_translation(--record->video_x, record->video_y);
761 record->set_translation(++record->video_x, record->video_y);
764 record->set_translation(record->video_x, --record->video_y);
767 record->set_translation(record->video_x, ++record->video_y);
774 RecordMonitorFullsize::RecordMonitorFullsize(MWindow *mwindow,
775 RecordMonitorGUI *window)
776 : BC_MenuItem(_("Zoom 100%"))
778 this->mwindow = mwindow;
779 this->window = window;
781 int RecordMonitorFullsize::handle_event()
793 // ================================== slippery playback ============================
796 RecordMonitorThread::RecordMonitorThread(MWindow *mwindow,
798 RecordMonitor *record_monitor)
801 this->mwindow = mwindow;
802 this->record_monitor = record_monitor;
803 this->record = record;
805 output_lock = new Condition(1, "RecordMonitor::output_lock");
806 input_lock = new Condition(1, "RecordMonitor::input_lock");
810 void RecordMonitorThread::reset_parameters()
821 RecordMonitorThread::~RecordMonitorThread()
823 if(input_frame && !shared_data) delete input_frame;
828 void RecordMonitorThread::init_output_format()
832 //printf("RecordMonitorThread::init_output_format 1\n");
833 switch(mwindow->edl->session->vconfig_in->driver)
836 output_colormodel = record->vdevice->get_best_colormodel(record->default_asset);
841 case VIDEO4LINUX2JPEG:
842 jpeg_engine = new RecVideoMJPGThread(record, this);
843 jpeg_engine->start_rendering();
844 output_colormodel = BC_YUV422P;
847 case CAPTURE_FIREWIRE:
848 case CAPTURE_IEC61883:
849 dv_engine = new RecVideoDVThread(record, this);
850 dv_engine->start_rendering();
851 output_colormodel = BC_YUV422P;
856 output_colormodel = record->vdevice->get_best_colormodel(record->default_asset);
857 //printf("RecordMonitorThread::init_output_format 2 %d\n", output_colormodel);
862 int RecordMonitorThread::start_playback()
866 output_lock->lock("RecordMonitorThread::start_playback");
871 int RecordMonitorThread::stop_playback()
874 output_lock->unlock();
876 //printf("RecordMonitorThread::stop_playback 1\n");
878 switch(mwindow->edl->session->vconfig_in->driver)
881 case VIDEO4LINUX2JPEG:
884 jpeg_engine->stop_rendering();
889 case CAPTURE_FIREWIRE:
890 case CAPTURE_IEC61883:
893 dv_engine->stop_rendering();
898 //printf("RecordMonitorThread::stop_playback 4\n");
903 int RecordMonitorThread::write_frame(VFrame *new_frame)
908 shared_data = (new_frame->get_color_model() != BC_COMPRESSED);
911 // Need to wait until after Record creates the input device before starting monitor
912 // because the input device deterimes the output format.
914 if(!output_frame) init_output_format();
917 if(!input_frame) input_frame = new VFrame;
918 input_frame->allocate_compressed_data(new_frame->get_compressed_size());
919 memcpy(input_frame->get_data(),
920 new_frame->get_data(),
921 new_frame->get_compressed_size());
922 input_frame->set_compressed_size(new_frame->get_compressed_size());
923 input_frame->set_field2_offset(new_frame->get_field2_offset());
927 input_lock->lock("RecordMonitorThread::write_frame");
928 input_frame = new_frame;
930 output_lock->unlock();
935 int RecordMonitorThread::render_jpeg()
937 //printf("RecordMonitorThread::render_jpeg 1\n");
938 jpeg_engine->render_frame(input_frame, input_frame->get_compressed_size());
939 //printf("RecordMonitorThread::render_jpeg 2\n");
943 int RecordMonitorThread::render_dv()
945 dv_engine->render_frame(input_frame, input_frame->get_compressed_size());
949 void RecordMonitorThread::render_uncompressed()
951 output_frame->copy_from(input_frame);
954 void RecordMonitorThread::show_output_frame()
956 record_monitor->device->write_buffer(output_frame, record->edl);
959 void RecordMonitorThread::unlock_input()
961 if(shared_data) input_lock->unlock();
964 int RecordMonitorThread::render_frame()
966 switch(mwindow->edl->session->vconfig_in->driver)
969 case VIDEO4LINUX2JPEG:
973 case CAPTURE_FIREWIRE:
974 case CAPTURE_IEC61883:
979 render_uncompressed();
986 void RecordMonitorThread::new_output_frame()
989 record_monitor->device->new_output_buffer(&output_frame, output_colormodel);
992 void RecordMonitorThread::run()
994 //printf("RecordMonitorThread::run 1 %d\n", getpid());
997 // Wait for next frame
999 output_lock->lock("RecordMonitorThread::run");
1012 show_output_frame();
1022 RecVideoMJPGThread::RecVideoMJPGThread(Record *record, RecordMonitorThread *thread)
1024 this->record = record;
1025 this->thread = thread;
1029 RecVideoMJPGThread::~RecVideoMJPGThread()
1033 int RecVideoMJPGThread::start_rendering()
1035 mjpeg = mjpeg_new(record->default_asset->width,
1036 record->default_asset->height,
1038 //printf("RecVideoMJPGThread::start_rendering 1 %p\n", mjpeg);
1042 int RecVideoMJPGThread::stop_rendering()
1044 //printf("RecVideoMJPGThread::stop_rendering 1 %p\n", mjpeg);
1045 if(mjpeg) mjpeg_delete(mjpeg);
1046 //printf("RecVideoMJPGThread::stop_rendering 2\n");
1050 int RecVideoMJPGThread::render_frame(VFrame *frame, long size)
1052 // printf("RecVideoMJPGThread::render_frame %d %02x%02x %02x%02x\n",
1053 // frame->get_field2_offset(),
1054 // frame->get_data()[0],
1055 // frame->get_data()[1],
1056 // frame->get_data()[frame->get_field2_offset()],
1057 // frame->get_data()[frame->get_field2_offset() + 1]);
1058 //frame->set_field2_offset(0);
1059 mjpeg_decompress(mjpeg,
1061 frame->get_compressed_size(),
1062 frame->get_field2_offset(),
1063 thread->output_frame->get_rows(),
1064 thread->output_frame->get_y(),
1065 thread->output_frame->get_u(),
1066 thread->output_frame->get_v(),
1067 thread->output_frame->get_color_model(),
1068 record->mwindow->preferences->processors);
1075 RecVideoDVThread::RecVideoDVThread(Record *record, RecordMonitorThread *thread)
1077 this->record = record;
1078 this->thread = thread;
1082 RecVideoDVThread::~RecVideoDVThread()
1087 int RecVideoDVThread::start_rendering()
1093 int RecVideoDVThread::stop_rendering()
1095 if(dv) dv_delete(((dv_t*)dv));
1099 int RecVideoDVThread::render_frame(VFrame *frame, long size)
1101 unsigned char *yuv_planes[3];
1102 yuv_planes[0] = thread->output_frame->get_y();
1103 yuv_planes[1] = thread->output_frame->get_u();
1104 yuv_planes[2] = thread->output_frame->get_v();
1105 dv_read_video(((dv_t*)dv),
1108 frame->get_compressed_size(),
1109 thread->output_frame->get_color_model());