2 #include "channelpicker.h"
6 #include "edlsession.h"
8 #include "meterpanel.h"
10 #include "playbackconfig.h"
11 #include "preferences.h"
13 #include "recordconfig.h"
14 #include "recordgui.h"
15 #include "recordtransport.h"
16 #include "recordmonitor.h"
17 #include "mainsession.h"
19 #include "videodevice.inc"
21 #include "videodevice.h"
25 #define _(String) gettext(String)
26 #define gettext_noop(String) String
27 #define N_(String) gettext_noop (String)
29 RecordMonitor::RecordMonitor(MWindow *mwindow, Record *record)
32 this->mwindow = mwindow;
33 this->record = record;
39 RecordMonitor::~RecordMonitor()
41 //printf("RecordMonitor::~RecordMonitor 1\n");
44 thread->stop_playback();
47 //printf("RecordMonitor::~RecordMonitor 1\n");
49 //printf("RecordMonitor::~RecordMonitor 1\n");
51 //printf("RecordMonitor::~RecordMonitor 1\n");
57 //printf("RecordMonitor::~RecordMonitor 1\n");
59 //printf("RecordMonitor::~RecordMonitor 2\n");
62 int RecordMonitor::create_objects()
64 //printf("RecordMonitor::create_objects 1\n");
65 window = new RecordMonitorGUI(mwindow,
68 //printf("RecordMonitor::create_objects 2\n");
69 window->create_objects();
70 //printf("RecordMonitor::create_objects 3\n");
72 if(record->default_asset->video_data)
74 // Configure the output for record monitoring
75 VideoOutConfig config(PLAYBACK_LOCALHOST, 0);
76 device = new VideoDevice;
77 //printf("RecordMonitor::create_objects 4\n");
81 // Override default device for X11 drivers
82 if(mwindow->edl->session->playback_config[PLAYBACK_LOCALHOST].values[0]->vconfig->driver ==
83 PLAYBACK_X11_XV) config.driver = PLAYBACK_X11_XV;
84 config.x11_use_fields = 0;
87 device->open_output(&config,
88 record->default_asset->frame_rate,
89 record->default_asset->width,
90 record->default_asset->height,
93 //printf("RecordMonitor::create_objects 5\n");
95 thread = new RecordMonitorThread(mwindow, record, this);
96 //printf("RecordMonitor::create_objects 6\n");
97 thread->start_playback();
105 void RecordMonitor::run()
107 window->run_window();
111 int RecordMonitor::close_threads()
113 if(window->channel_picker) window->channel_picker->close_threads();
116 int RecordMonitor::update(VFrame *vframe)
118 return thread->write_frame(vframe);
121 void RecordMonitor::update_channel(char *text)
123 if(window->channel_picker)
124 window->channel_picker->channel_text->update(text);
127 int RecordMonitor::get_mbuttons_height()
129 return RECBUTTON_HEIGHT;
132 int RecordMonitor::fix_size(int &w, int &h, int width_given, float aspect_ratio)
135 h = (int)((float)width_given / aspect_ratio);
138 float RecordMonitor::get_scale(int w)
140 if(mwindow->edl->get_aspect_ratio() >
141 (float)record->frame_w / record->frame_h)
144 ((float)record->frame_h *
145 mwindow->edl->get_aspect_ratio());
149 return (float)w / record->frame_w;
153 int RecordMonitor::get_canvas_height()
155 return window->get_h() - get_mbuttons_height();
158 int RecordMonitor::get_channel_x()
164 int RecordMonitor::get_channel_y()
178 RecordMonitorGUI::RecordMonitorGUI(MWindow *mwindow,
180 RecordMonitor *thread)
181 : BC_Window(PROGRAM_NAME ": Video in",
182 mwindow->session->rmonitor_x,
183 mwindow->session->rmonitor_y,
184 mwindow->session->rmonitor_w,
185 mwindow->session->rmonitor_h,
192 this->mwindow = mwindow;
193 this->thread = thread;
194 this->record = record;
197 reverse_interlace = 0;
200 current_operation = MONITOR_NONE;
203 RecordMonitorGUI::~RecordMonitorGUI()
205 if(bitmap) delete bitmap;
206 if(channel_picker) delete channel_picker;
209 int RecordMonitorGUI::create_objects()
211 //printf("RecordMonitorGUI::create_objects 1\n");
212 mwindow->theme->get_recordmonitor_sizes(record->default_asset->audio_data,
213 record->default_asset->video_data);
214 mwindow->theme->draw_rmonitor_bg(this);
215 //printf("RecordMonitorGUI::create_objects 1\n");
217 record_transport = new RecordTransport(mwindow,
220 mwindow->theme->rmonitor_tx_x,
221 mwindow->theme->rmonitor_tx_y);
222 record_transport->create_objects();
223 //printf("RecordMonitorGUI::create_objects 1\n");
225 if(record->default_asset->video_data)
227 canvas = new RecordMonitorCanvas(mwindow,
230 mwindow->theme->rmonitor_canvas_x,
231 mwindow->theme->rmonitor_canvas_y,
232 mwindow->theme->rmonitor_canvas_w,
233 mwindow->theme->rmonitor_canvas_h);
234 canvas->create_objects(0);
235 //printf("RecordMonitorGUI::create_objects 1\n");
237 if(mwindow->edl->session->vconfig_in->driver == VIDEO4LINUX ||
238 mwindow->edl->session->vconfig_in->driver == CAPTURE_BUZ)
240 channel_picker = new ChannelPicker(mwindow,
243 record->current_channeldb(),
244 mwindow->theme->rmonitor_channel_x,
245 mwindow->theme->rmonitor_channel_y);
246 channel_picker->create_objects();
248 //printf("RecordMonitorGUI::create_objects 1\n");
250 if(mwindow->edl->session->vconfig_in->driver == CAPTURE_BUZ)
252 add_subwindow(reverse_interlace = new ReverseInterlace(record,
253 mwindow->theme->rmonitor_interlace_x,
254 mwindow->theme->rmonitor_interlace_y));
256 //printf("RecordMonitorGUI::create_objects 1\n");
258 add_subwindow(monitor_menu = new BC_PopupMenu(0,
263 monitor_menu->add_item(new RecordMonitorFullsize(mwindow,
265 //printf("RecordMonitorGUI::create_objects 1\n");
267 //printf("RecordMonitorGUI::create_objects 1\n");
269 if(record->default_asset->audio_data)
271 meters = new MeterPanel(mwindow,
273 mwindow->theme->rmonitor_meter_x,
274 mwindow->theme->rmonitor_meter_y,
275 mwindow->theme->rmonitor_meter_h,
276 record->default_asset->channels,
278 meters->create_objects();
280 //printf("RecordMonitorGUI::create_objects 2\n");
284 int RecordMonitorGUI::button_press()
286 if(get_buttonpress() == 2)
292 if(get_button_down() == 3)
294 monitor_menu->activate_menu();
300 int RecordMonitorGUI::button_release()
305 int RecordMonitorGUI::get_virtual_center()
309 int RecordMonitorGUI::cursor_motion()
314 int RecordMonitorGUI::keypress_event()
317 switch(get_keypress())
322 record->record_gui->set_translation(--(record->video_x), record->video_y, record->video_zoom);
326 record->video_zoom -= 0.1;
327 record->record_gui->set_translation(record->video_x, record->video_y, record->video_zoom);
334 record->record_gui->set_translation(++(record->video_x), record->video_y, record->video_zoom);
338 record->video_zoom += 0.1;
339 record->record_gui->set_translation(record->video_x, record->video_y, record->video_zoom);
346 record->record_gui->set_translation(record->video_x, --(record->video_y), record->video_zoom);
350 record->video_zoom -= 0.1;
351 record->record_gui->set_translation(record->video_x, record->video_y, record->video_zoom);
358 record->record_gui->set_translation(record->video_x, ++(record->video_y), record->video_zoom);
362 record->video_zoom += 0.1;
363 record->record_gui->set_translation(record->video_x, record->video_y, record->video_zoom);
371 result = record_transport->keypress_event();
378 int RecordMonitorGUI::translation_event()
380 //printf("MWindowGUI::translation_event 1 %d %d\n", get_x(), get_y());
381 mwindow->session->rmonitor_x = get_x();
382 mwindow->session->rmonitor_y = get_y();
386 int RecordMonitorGUI::resize_event(int w, int h)
388 //printf("RecordMonitorGUI::resize_event %d %d\n", w, h);
389 mwindow->session->rmonitor_x = get_x();
390 mwindow->session->rmonitor_y = get_y();
391 mwindow->session->rmonitor_w = w;
392 mwindow->session->rmonitor_h = h;
394 mwindow->theme->get_recordmonitor_sizes(record->default_asset->audio_data,
395 record->default_asset->video_data);
396 mwindow->theme->draw_rmonitor_bg(this);
400 record_transport->reposition_window(mwindow->theme->rmonitor_tx_x,
401 mwindow->theme->rmonitor_tx_y);
402 if(channel_picker) channel_picker->reposition();
403 if(reverse_interlace) reverse_interlace->reposition_window(reverse_interlace->get_x(),
404 reverse_interlace->get_y());
405 if(record->default_asset->video_data)
407 canvas->reposition_window(0,
408 mwindow->theme->rmonitor_canvas_x,
409 mwindow->theme->rmonitor_canvas_y,
410 mwindow->theme->rmonitor_canvas_w,
411 mwindow->theme->rmonitor_canvas_h);
414 if(record->default_asset->audio_data)
416 meters->reposition_window(mwindow->theme->rmonitor_meter_x,
417 mwindow->theme->rmonitor_meter_y,
418 mwindow->theme->rmonitor_meter_h);
422 BC_WindowBase::resize_event(w, h);
428 int RecordMonitorGUI::set_title()
434 scale = (int)(thread->get_scale(thread->record->video_window_w) * 100 + 0.5);
436 sprintf(string, PROGRAM_NAME ": Video in %d%%", scale);
437 BC_Window::set_title(string);
441 int RecordMonitorGUI::close_event()
443 thread->record->monitor_video = 0;
444 thread->record->monitor_audio = 0;
445 thread->record->video_window_open = 0;
446 if(record->record_gui->monitor_video) record->record_gui->monitor_video->update(0);
447 if(record->record_gui->monitor_audio) record->record_gui->monitor_audio->update(0);
449 record->record_gui->flush();
453 int RecordMonitorGUI::create_bitmap()
456 (bitmap->get_w() != get_w() ||
457 bitmap->get_h() != thread->get_canvas_height()))
465 // bitmap = canvas->new_bitmap(get_w(), thread->get_canvas_height());
470 ReverseInterlace::ReverseInterlace(Record *record, int x, int y)
471 : BC_CheckBox(x, y, record->reverse_interlace, _("Swap fields"))
473 this->record = record;
476 ReverseInterlace::~ReverseInterlace()
480 int ReverseInterlace::handle_event()
482 record->reverse_interlace = get_value();
486 RecordMonitorCanvas::RecordMonitorCanvas(MWindow *mwindow,
487 RecordMonitorGUI *window,
498 record->default_asset->width,
499 record->default_asset->height,
504 this->window = window;
505 this->mwindow = mwindow;
506 this->record = record;
507 //printf("RecordMonitorCanvas::RecordMonitorCanvas 1 %d\n", mwindow->edl->session->vconfig_in->driver);
508 //printf("RecordMonitorCanvas::RecordMonitorCanvas 2\n");
511 RecordMonitorCanvas::~RecordMonitorCanvas()
515 int RecordMonitorCanvas::get_output_w()
517 return record->default_asset->width;
520 int RecordMonitorCanvas::get_output_h()
522 return record->default_asset->height;
526 int RecordMonitorCanvas::button_press_event()
528 if(Canvas::button_press_event()) return 1;
530 if(mwindow->edl->session->vconfig_in->driver == SCREENCAPTURE)
532 window->current_operation = MONITOR_TRANSLATE;
533 window->translate_x_origin = record->video_x;
534 window->translate_y_origin = record->video_y;
535 window->cursor_x_origin = get_cursor_x();
536 window->cursor_y_origin = get_cursor_y();
542 void RecordMonitorCanvas::zoom_resize_window(float percentage)
544 int canvas_w, canvas_h;
545 calculate_sizes(mwindow->edl->get_aspect_ratio(),
546 record->default_asset->width,
547 record->default_asset->height,
552 new_w = canvas_w + (window->get_w() - mwindow->theme->rmonitor_canvas_w);
553 new_h = canvas_h + (window->get_h() - mwindow->theme->rmonitor_canvas_h);
554 window->resize_window(new_w, new_h);
555 window->resize_event(new_w, new_h);
558 int RecordMonitorCanvas::button_release_event()
560 window->current_operation = MONITOR_NONE;
564 int RecordMonitorCanvas::cursor_motion_event()
566 if(window->current_operation == MONITOR_TRANSLATE)
568 record->set_translation(
569 get_cursor_x() - window->cursor_x_origin + window->translate_x_origin,
570 get_cursor_y() - window->cursor_y_origin + window->translate_y_origin);
576 int RecordMonitorCanvas::cursor_enter_event()
578 if(mwindow->edl->session->vconfig_in->driver == SCREENCAPTURE)
579 set_cursor(MOVE_CURSOR);
583 void RecordMonitorCanvas::reset_translation()
585 record->set_translation(0, 0);
588 int RecordMonitorCanvas::keypress_event()
591 switch(canvas->get_keypress())
594 record->set_translation(--record->video_x, record->video_y);
597 record->set_translation(++record->video_x, record->video_y);
600 record->set_translation(record->video_x, --record->video_y);
603 record->set_translation(record->video_x, ++record->video_y);
610 RecordMonitorFullsize::RecordMonitorFullsize(MWindow *mwindow,
611 RecordMonitorGUI *window)
612 : BC_MenuItem(_("Zoom 100%"))
614 this->mwindow = mwindow;
615 this->window = window;
617 int RecordMonitorFullsize::handle_event()
629 // ================================== slippery playback ============================
632 RecordMonitorThread::RecordMonitorThread(MWindow *mwindow,
634 RecordMonitor *record_monitor)
637 this->mwindow = mwindow;
638 this->record_monitor = record_monitor;
639 this->record = record;
644 void RecordMonitorThread::reset_parameters()
654 RecordMonitorThread::~RecordMonitorThread()
656 if(input_frame && !shared_data) delete input_frame;
659 void RecordMonitorThread::init_output_format()
663 //printf("RecordMonitorThread::init_output_format 1\n");
664 switch(mwindow->edl->session->vconfig_in->driver)
667 output_colormodel = record->vdevice->get_best_colormodel(record->default_asset);
672 jpeg_engine = new RecVideoMJPGThread(record, this);
673 jpeg_engine->start_rendering();
674 output_colormodel = BC_YUV422P;
677 case CAPTURE_FIREWIRE:
678 dv_engine = new RecVideoDVThread(record, this);
679 dv_engine->start_rendering();
680 output_colormodel = BC_YUV422P;
684 output_colormodel = record->vdevice->get_best_colormodel(record->default_asset);
685 //printf("RecordMonitorThread::init_output_format 2 %d\n", output_colormodel);
690 int RecordMonitorThread::start_playback()
700 int RecordMonitorThread::stop_playback()
703 output_lock.unlock();
705 //printf("RecordMonitorThread::stop_playback 1\n");
707 switch(mwindow->edl->session->vconfig_in->driver)
710 //printf("RecordMonitorThread::stop_playback 2\n");
713 jpeg_engine->stop_rendering();
714 //printf("RecordMonitorThread::stop_playback 2\n");
717 //printf("RecordMonitorThread::stop_playback 3\n");
720 case CAPTURE_FIREWIRE:
723 dv_engine->stop_rendering();
728 //printf("RecordMonitorThread::stop_playback 4\n");
733 int RecordMonitorThread::write_frame(VFrame *new_frame)
738 shared_data = (new_frame->get_color_model() != BC_COMPRESSED);
739 // Need to wait until after Record creates the input device before starting monitor
740 // because the input device deterimes the output format.
742 if(!output_frame[0]) init_output_format();
745 if(!input_frame) input_frame = new VFrame;
746 input_frame->allocate_compressed_data(new_frame->get_compressed_size());
747 memcpy(input_frame->get_data(),
748 new_frame->get_data(),
749 new_frame->get_compressed_size());
750 input_frame->set_compressed_size(new_frame->get_compressed_size());
751 input_frame->set_field2_offset(new_frame->get_field2_offset());
756 input_frame = new_frame;
758 output_lock.unlock();
763 int RecordMonitorThread::render_jpeg()
765 //printf("RecordMonitorThread::render_jpeg 1\n");
766 jpeg_engine->render_frame(input_frame, input_frame->get_compressed_size());
767 //printf("RecordMonitorThread::render_jpeg 2\n");
771 int RecordMonitorThread::render_dv()
773 dv_engine->render_frame(input_frame, input_frame->get_compressed_size());
777 void RecordMonitorThread::render_uncompressed()
779 // printf("RecordMonitorThread::render_uncompressed 1 %p %p %p %p %p %p %p\n",
781 // output_frame[0]->get_y(),
782 // output_frame[0]->get_u(),
783 // output_frame[0]->get_v(),
784 // input_frame->get_y(),
785 // input_frame->get_u(),
786 // input_frame->get_v());
788 output_frame[0]->copy_from(input_frame);
790 //printf("RecordMonitorThread::render_uncompressed 2\n");
793 void RecordMonitorThread::show_output_frame()
795 record_monitor->device->write_buffer(output_frame, record->edl);
798 void RecordMonitorThread::unlock_input()
800 if(shared_data) input_lock.unlock();
803 int RecordMonitorThread::render_frame()
805 switch(mwindow->edl->session->vconfig_in->driver)
811 case CAPTURE_FIREWIRE:
816 render_uncompressed();
823 void RecordMonitorThread::new_output_frame()
826 //printf("RecordMonitorThread::new_output_frame %d %p %p\n", output_colormodel, record_monitor, record_monitor->device);
827 record_monitor->device->new_output_buffers(output_frame, output_colormodel);
828 //printf("RecordMonitorThread::new_output_frame 2\n");
831 void RecordMonitorThread::run()
835 // Wait for next frame
842 //printf("RecordMonitorThread::run 1\n");
844 //printf("RecordMonitorThread::run 2\n");
846 //printf("RecordMonitorThread::run 3\n");
848 //printf("RecordMonitorThread::run 4\n");
857 RecVideoMJPGThread::RecVideoMJPGThread(Record *record, RecordMonitorThread *thread)
859 this->record = record;
860 this->thread = thread;
864 RecVideoMJPGThread::~RecVideoMJPGThread()
868 int RecVideoMJPGThread::start_rendering()
870 mjpeg = mjpeg_new(record->default_asset->width,
871 record->default_asset->height,
873 //printf("RecVideoMJPGThread::start_rendering 1 %p\n", mjpeg);
877 int RecVideoMJPGThread::stop_rendering()
879 //printf("RecVideoMJPGThread::stop_rendering 1 %p\n", mjpeg);
880 if(mjpeg) mjpeg_delete(mjpeg);
881 //printf("RecVideoMJPGThread::stop_rendering 2\n");
885 int RecVideoMJPGThread::render_frame(VFrame *frame, long size)
887 // printf("RecVideoMJPGThread::render_frame %d %02x%02x %02x%02x\n", frame->get_field2_offset(),
888 // frame->get_data()[0],
889 // frame->get_data()[1],
890 // frame->get_data()[frame->get_field2_offset()],
891 // frame->get_data()[frame->get_field2_offset() + 1]);
892 //frame->set_field2_offset(0);
893 mjpeg_decompress(mjpeg,
895 frame->get_compressed_size(),
896 frame->get_field2_offset(),
897 thread->output_frame[0]->get_rows(),
898 thread->output_frame[0]->get_y(),
899 thread->output_frame[0]->get_u(),
900 thread->output_frame[0]->get_v(),
901 thread->output_frame[0]->get_color_model(),
902 record->mwindow->edl->session->smp + 1);
909 RecVideoDVThread::RecVideoDVThread(Record *record, RecordMonitorThread *thread)
911 this->record = record;
912 this->thread = thread;
916 RecVideoDVThread::~RecVideoDVThread()
921 int RecVideoDVThread::start_rendering()
923 ((dv_t*)dv) = dv_new();
927 int RecVideoDVThread::stop_rendering()
929 if(dv) dv_delete(((dv_t*)dv));
933 int RecVideoDVThread::render_frame(VFrame *frame, long size)
935 unsigned char *yuv_planes[3];
936 yuv_planes[0] = thread->output_frame[0]->get_y();
937 yuv_planes[1] = thread->output_frame[0]->get_u();
938 yuv_planes[2] = thread->output_frame[0]->get_v();
939 dv_read_video(((dv_t*)dv),
942 frame->get_compressed_size(),
943 thread->output_frame[0]->get_color_model());