2 #include "channelpicker.h"
7 #include "edlsession.h"
10 #include "meterpanel.h"
12 #include "playbackconfig.h"
13 #include "preferences.h"
15 #include "recordconfig.h"
16 #include "recordgui.h"
17 #include "recordtransport.h"
18 #include "recordmonitor.h"
19 #include "mainsession.h"
21 #include "videodevice.inc"
23 #include "videodevice.h"
26 RecordMonitor::RecordMonitor(MWindow *mwindow, Record *record)
29 this->mwindow = mwindow;
30 this->record = record;
36 RecordMonitor::~RecordMonitor()
40 thread->stop_playback();
53 int RecordMonitor::create_objects()
55 window = new RecordMonitorGUI(mwindow,
58 window->create_objects();
60 if(record->default_asset->video_data)
62 // Configure the output for record monitoring
63 VideoOutConfig config;
64 device = new VideoDevice;
68 // Override default device for X11 drivers
69 if(mwindow->edl->session->playback_config->vconfig->driver ==
70 PLAYBACK_X11_XV) config.driver = PLAYBACK_X11_XV;
71 config.x11_use_fields = 0;
74 device->open_output(&config,
75 record->default_asset->frame_rate,
76 record->default_asset->width,
77 record->default_asset->height,
81 thread = new RecordMonitorThread(mwindow, record, this);
82 thread->start_playback();
90 void RecordMonitor::run()
96 int RecordMonitor::close_threads()
98 if(window->channel_picker) window->channel_picker->close_threads();
101 int RecordMonitor::update(VFrame *vframe)
103 return thread->write_frame(vframe);
106 void RecordMonitor::update_channel(char *text)
108 if(window->channel_picker)
109 window->channel_picker->channel_text->update(text);
112 int RecordMonitor::get_mbuttons_height()
114 return RECBUTTON_HEIGHT;
117 int RecordMonitor::fix_size(int &w, int &h, int width_given, float aspect_ratio)
120 h = (int)((float)width_given / aspect_ratio);
123 float RecordMonitor::get_scale(int w)
125 if(mwindow->edl->get_aspect_ratio() >
126 (float)record->frame_w / record->frame_h)
129 ((float)record->frame_h *
130 mwindow->edl->get_aspect_ratio());
134 return (float)w / record->frame_w;
138 int RecordMonitor::get_canvas_height()
140 return window->get_h() - get_mbuttons_height();
143 int RecordMonitor::get_channel_x()
149 int RecordMonitor::get_channel_y()
163 RecordMonitorGUI::RecordMonitorGUI(MWindow *mwindow,
165 RecordMonitor *thread)
166 : BC_Window(PROGRAM_NAME ": Video in",
167 mwindow->session->rmonitor_x,
168 mwindow->session->rmonitor_y,
169 mwindow->session->rmonitor_w,
170 mwindow->session->rmonitor_h,
177 this->mwindow = mwindow;
178 this->thread = thread;
179 this->record = record;
181 avc1394_transport = 0;
182 avc1394transport_title = 0;
183 avc1394transport_timecode = 0;
184 avc1394transport_thread = 0;
187 reverse_interlace = 0;
190 current_operation = MONITOR_NONE;
193 RecordMonitorGUI::~RecordMonitorGUI()
195 if(bitmap) delete bitmap;
196 if(channel_picker) delete channel_picker;
197 if(avc1394transport_thread)
198 delete avc1394transport_thread;
203 if(avc1394_transport)
205 delete avc1394_transport;
207 if(avc1394transport_title)
208 delete avc1394transport_title;
211 int RecordMonitorGUI::create_objects()
213 // y offset for video canvas if we have the transport controls
214 int do_channel = (mwindow->edl->session->vconfig_in->driver == VIDEO4LINUX ||
215 mwindow->edl->session->vconfig_in->driver == CAPTURE_BUZ ||
216 mwindow->edl->session->vconfig_in->driver == VIDEO4LINUX2 ||
217 mwindow->edl->session->vconfig_in->driver == VIDEO4LINUX2JPEG);
218 int do_interlace = (mwindow->edl->session->vconfig_in->driver == CAPTURE_BUZ ||
219 mwindow->edl->session->vconfig_in->driver == VIDEO4LINUX2JPEG);
220 int background_done = 0;
222 mwindow->theme->get_rmonitor_sizes(record->default_asset->audio_data,
223 record->default_asset->video_data,
233 if(record->default_asset->video_data)
235 int driver = mwindow->edl->session->vconfig_in->driver;
237 if(driver == CAPTURE_FIREWIRE)
239 avc = new AVC1394Control;
242 mwindow->theme->get_rmonitor_sizes(record->default_asset->audio_data,
243 record->default_asset->video_data,
247 mwindow->theme->draw_rmonitor_bg(this);
250 printf("RecordMonitorGUI::create_objects %d %d\n", mwindow->theme->rmonitor_tx_x, mwindow->theme->rmonitor_tx_y);
251 avc1394_transport = new AVC1394Transport(mwindow,
254 mwindow->theme->rmonitor_tx_x,
255 mwindow->theme->rmonitor_tx_y);
256 avc1394_transport->create_objects();
258 add_subwindow(avc1394transport_timecode =
259 new BC_Title(avc1394_transport->x_end,
260 mwindow->theme->rmonitor_tx_y + 10,
265 avc1394transport_thread =
266 new AVC1394TransportThread(avc1394transport_timecode,
269 avc1394transport_thread->start();
277 mwindow->theme->draw_rmonitor_bg(this);
281 canvas = new RecordMonitorCanvas(mwindow,
284 mwindow->theme->rmonitor_canvas_x,
285 mwindow->theme->rmonitor_canvas_y,
286 mwindow->theme->rmonitor_canvas_w,
287 mwindow->theme->rmonitor_canvas_h);
288 canvas->create_objects(0);
290 if(driver == VIDEO4LINUX ||
291 driver == CAPTURE_BUZ ||
292 driver == VIDEO4LINUX2 ||
293 driver == VIDEO4LINUX2JPEG)
295 channel_picker = new ChannelPicker(mwindow,
299 mwindow->theme->rmonitor_channel_x,
300 mwindow->theme->rmonitor_channel_y);
301 channel_picker->create_objects();
304 if(driver == CAPTURE_BUZ ||
305 driver == VIDEO4LINUX2JPEG)
307 add_subwindow(reverse_interlace = new ReverseInterlace(record,
308 mwindow->theme->rmonitor_interlace_x,
309 mwindow->theme->rmonitor_interlace_y));
312 add_subwindow(monitor_menu = new BC_PopupMenu(0,
317 monitor_menu->add_item(new RecordMonitorFullsize(mwindow,
324 mwindow->theme->draw_rmonitor_bg(this);
328 if(record->default_asset->audio_data)
330 meters = new MeterPanel(mwindow,
332 mwindow->theme->rmonitor_meter_x,
333 mwindow->theme->rmonitor_meter_y,
334 mwindow->theme->rmonitor_meter_h,
335 record->default_asset->channels,
338 meters->create_objects();
343 int RecordMonitorGUI::button_press()
345 if(get_buttonpress() == 2)
351 if(get_button_down() == 3)
353 monitor_menu->activate_menu();
359 int RecordMonitorGUI::button_release()
364 int RecordMonitorGUI::get_virtual_center()
368 int RecordMonitorGUI::cursor_motion()
373 int RecordMonitorGUI::keypress_event()
376 switch(get_keypress())
381 record->record_gui->set_translation(--(record->video_x), record->video_y, record->video_zoom);
385 record->video_zoom -= 0.1;
386 record->record_gui->set_translation(record->video_x, record->video_y, record->video_zoom);
393 record->record_gui->set_translation(++(record->video_x), record->video_y, record->video_zoom);
397 record->video_zoom += 0.1;
398 record->record_gui->set_translation(record->video_x, record->video_y, record->video_zoom);
405 record->record_gui->set_translation(record->video_x, --(record->video_y), record->video_zoom);
409 record->video_zoom -= 0.1;
410 record->record_gui->set_translation(record->video_x, record->video_y, record->video_zoom);
417 record->record_gui->set_translation(record->video_x, ++(record->video_y), record->video_zoom);
421 record->video_zoom += 0.1;
422 record->record_gui->set_translation(record->video_x, record->video_y, record->video_zoom);
430 if(avc1394_transport)
431 result = avc1394_transport->keypress_event(get_keypress());
438 int RecordMonitorGUI::translation_event()
440 //printf("MWindowGUI::translation_event 1 %d %d\n", get_x(), get_y());
441 mwindow->session->rmonitor_x = get_x();
442 mwindow->session->rmonitor_y = get_y();
446 int RecordMonitorGUI::resize_event(int w, int h)
448 int do_channel = (mwindow->edl->session->vconfig_in->driver == VIDEO4LINUX ||
449 mwindow->edl->session->vconfig_in->driver == CAPTURE_BUZ ||
450 mwindow->edl->session->vconfig_in->driver == VIDEO4LINUX2 ||
451 mwindow->edl->session->vconfig_in->driver == VIDEO4LINUX2JPEG);
452 int do_interlace = (mwindow->edl->session->vconfig_in->driver == CAPTURE_BUZ ||
453 mwindow->edl->session->vconfig_in->driver == VIDEO4LINUX2JPEG);
454 int do_avc = avc1394_transport ? 1 : 0;
456 mwindow->session->rmonitor_x = get_x();
457 mwindow->session->rmonitor_y = get_y();
458 mwindow->session->rmonitor_w = w;
459 mwindow->session->rmonitor_h = h;
461 mwindow->theme->get_rmonitor_sizes(record->default_asset->audio_data,
462 record->default_asset->video_data,
466 mwindow->theme->draw_rmonitor_bg(this);
470 // record_transport->reposition_window(mwindow->theme->rmonitor_tx_x,
471 // mwindow->theme->rmonitor_tx_y);
472 if(avc1394_transport)
474 avc1394_transport->reposition_window(mwindow->theme->rmonitor_tx_x,
475 mwindow->theme->rmonitor_tx_y);
478 if(channel_picker) channel_picker->reposition();
479 if(reverse_interlace) reverse_interlace->reposition_window(reverse_interlace->get_x(),
480 reverse_interlace->get_y());
481 if(record->default_asset->video_data)
483 canvas->reposition_window(0,
484 mwindow->theme->rmonitor_canvas_x,
485 mwindow->theme->rmonitor_canvas_y,
486 mwindow->theme->rmonitor_canvas_w,
487 mwindow->theme->rmonitor_canvas_h);
490 if(record->default_asset->audio_data)
492 meters->reposition_window(mwindow->theme->rmonitor_meter_x,
493 mwindow->theme->rmonitor_meter_y,
494 mwindow->theme->rmonitor_meter_h);
498 BC_WindowBase::resize_event(w, h);
504 int RecordMonitorGUI::set_title()
510 scale = (int)(thread->get_scale(thread->record->video_window_w) * 100 + 0.5);
512 sprintf(string, PROGRAM_NAME ": Video in %d%%", scale);
513 BC_Window::set_title(string);
517 int RecordMonitorGUI::close_event()
519 thread->record->monitor_video = 0;
520 thread->record->monitor_audio = 0;
521 thread->record->video_window_open = 0;
522 if(record->record_gui->monitor_video) record->record_gui->monitor_video->update(0);
523 if(record->record_gui->monitor_audio) record->record_gui->monitor_audio->update(0);
525 record->record_gui->flush();
529 int RecordMonitorGUI::create_bitmap()
532 (bitmap->get_w() != get_w() ||
533 bitmap->get_h() != thread->get_canvas_height()))
541 // bitmap = canvas->new_bitmap(get_w(), thread->get_canvas_height());
546 ReverseInterlace::ReverseInterlace(Record *record, int x, int y)
547 : BC_CheckBox(x, y, record->reverse_interlace, _("Swap fields"))
549 this->record = record;
552 ReverseInterlace::~ReverseInterlace()
556 int ReverseInterlace::handle_event()
558 record->reverse_interlace = get_value();
562 RecordMonitorCanvas::RecordMonitorCanvas(MWindow *mwindow,
563 RecordMonitorGUI *window,
574 record->default_asset->width,
575 record->default_asset->height,
580 this->window = window;
581 this->mwindow = mwindow;
582 this->record = record;
583 //printf("RecordMonitorCanvas::RecordMonitorCanvas 1 %d\n", mwindow->edl->session->vconfig_in->driver);
584 //printf("RecordMonitorCanvas::RecordMonitorCanvas 2\n");
587 RecordMonitorCanvas::~RecordMonitorCanvas()
591 int RecordMonitorCanvas::get_output_w()
593 return record->default_asset->width;
596 int RecordMonitorCanvas::get_output_h()
598 return record->default_asset->height;
602 int RecordMonitorCanvas::button_press_event()
604 if(Canvas::button_press_event()) return 1;
606 if(mwindow->edl->session->vconfig_in->driver == SCREENCAPTURE)
608 window->current_operation = MONITOR_TRANSLATE;
609 window->translate_x_origin = record->video_x;
610 window->translate_y_origin = record->video_y;
611 window->cursor_x_origin = get_cursor_x();
612 window->cursor_y_origin = get_cursor_y();
618 void RecordMonitorCanvas::zoom_resize_window(float percentage)
620 int canvas_w, canvas_h;
621 calculate_sizes(mwindow->edl->get_aspect_ratio(),
622 record->default_asset->width,
623 record->default_asset->height,
628 new_w = canvas_w + (window->get_w() - mwindow->theme->rmonitor_canvas_w);
629 new_h = canvas_h + (window->get_h() - mwindow->theme->rmonitor_canvas_h);
630 window->resize_window(new_w, new_h);
631 window->resize_event(new_w, new_h);
634 int RecordMonitorCanvas::button_release_event()
636 window->current_operation = MONITOR_NONE;
640 int RecordMonitorCanvas::cursor_motion_event()
642 if(window->current_operation == MONITOR_TRANSLATE)
644 record->set_translation(
645 get_cursor_x() - window->cursor_x_origin + window->translate_x_origin,
646 get_cursor_y() - window->cursor_y_origin + window->translate_y_origin);
652 int RecordMonitorCanvas::cursor_enter_event()
654 if(mwindow->edl->session->vconfig_in->driver == SCREENCAPTURE)
655 set_cursor(MOVE_CURSOR);
659 void RecordMonitorCanvas::reset_translation()
661 record->set_translation(0, 0);
664 int RecordMonitorCanvas::keypress_event()
667 switch(canvas->get_keypress())
670 record->set_translation(--record->video_x, record->video_y);
673 record->set_translation(++record->video_x, record->video_y);
676 record->set_translation(record->video_x, --record->video_y);
679 record->set_translation(record->video_x, ++record->video_y);
686 RecordMonitorFullsize::RecordMonitorFullsize(MWindow *mwindow,
687 RecordMonitorGUI *window)
688 : BC_MenuItem(_("Zoom 100%"))
690 this->mwindow = mwindow;
691 this->window = window;
693 int RecordMonitorFullsize::handle_event()
705 // ================================== slippery playback ============================
708 RecordMonitorThread::RecordMonitorThread(MWindow *mwindow,
710 RecordMonitor *record_monitor)
713 this->mwindow = mwindow;
714 this->record_monitor = record_monitor;
715 this->record = record;
717 output_lock = new Condition(1, "RecordMonitor::output_lock");
718 input_lock = new Condition(1, "RecordMonitor::input_lock");
722 void RecordMonitorThread::reset_parameters()
733 RecordMonitorThread::~RecordMonitorThread()
735 if(input_frame && !shared_data) delete input_frame;
740 void RecordMonitorThread::init_output_format()
744 //printf("RecordMonitorThread::init_output_format 1\n");
745 switch(mwindow->edl->session->vconfig_in->driver)
748 output_colormodel = record->vdevice->get_best_colormodel(record->default_asset);
753 case VIDEO4LINUX2JPEG:
754 jpeg_engine = new RecVideoMJPGThread(record, this);
755 jpeg_engine->start_rendering();
756 output_colormodel = BC_YUV422P;
759 case CAPTURE_FIREWIRE:
760 dv_engine = new RecVideoDVThread(record, this);
761 dv_engine->start_rendering();
762 output_colormodel = BC_YUV422P;
767 output_colormodel = record->vdevice->get_best_colormodel(record->default_asset);
768 //printf("RecordMonitorThread::init_output_format 2 %d\n", output_colormodel);
773 int RecordMonitorThread::start_playback()
777 output_lock->lock("RecordMonitorThread::start_playback");
782 int RecordMonitorThread::stop_playback()
785 output_lock->unlock();
787 //printf("RecordMonitorThread::stop_playback 1\n");
789 switch(mwindow->edl->session->vconfig_in->driver)
792 case VIDEO4LINUX2JPEG:
795 jpeg_engine->stop_rendering();
800 case CAPTURE_FIREWIRE:
803 dv_engine->stop_rendering();
808 //printf("RecordMonitorThread::stop_playback 4\n");
813 int RecordMonitorThread::write_frame(VFrame *new_frame)
818 shared_data = (new_frame->get_color_model() != BC_COMPRESSED);
821 // Need to wait until after Record creates the input device before starting monitor
822 // because the input device deterimes the output format.
824 if(!output_frame[0]) init_output_format();
827 if(!input_frame) input_frame = new VFrame;
828 input_frame->allocate_compressed_data(new_frame->get_compressed_size());
829 memcpy(input_frame->get_data(),
830 new_frame->get_data(),
831 new_frame->get_compressed_size());
832 input_frame->set_compressed_size(new_frame->get_compressed_size());
833 input_frame->set_field2_offset(new_frame->get_field2_offset());
837 input_lock->lock("RecordMonitorThread::write_frame");
838 input_frame = new_frame;
840 output_lock->unlock();
845 int RecordMonitorThread::render_jpeg()
847 //printf("RecordMonitorThread::render_jpeg 1\n");
848 jpeg_engine->render_frame(input_frame, input_frame->get_compressed_size());
849 //printf("RecordMonitorThread::render_jpeg 2\n");
853 int RecordMonitorThread::render_dv()
855 dv_engine->render_frame(input_frame, input_frame->get_compressed_size());
859 void RecordMonitorThread::render_uncompressed()
861 // printf("RecordMonitorThread::render_uncompressed 1 %p %p %p %p %p %p %p\n",
863 // output_frame[0]->get_y(),
864 // output_frame[0]->get_u(),
865 // output_frame[0]->get_v(),
866 // input_frame->get_y(),
867 // input_frame->get_u(),
868 // input_frame->get_v());
870 output_frame[0]->copy_from(input_frame);
872 //printf("RecordMonitorThread::render_uncompressed 2\n");
875 void RecordMonitorThread::show_output_frame()
877 record_monitor->device->write_buffer(output_frame, record->edl);
880 void RecordMonitorThread::unlock_input()
882 if(shared_data) input_lock->unlock();
885 int RecordMonitorThread::render_frame()
887 switch(mwindow->edl->session->vconfig_in->driver)
890 case VIDEO4LINUX2JPEG:
894 case CAPTURE_FIREWIRE:
899 render_uncompressed();
906 void RecordMonitorThread::new_output_frame()
909 //printf("RecordMonitorThread::new_output_frame %d %p %p\n", output_colormodel, record_monitor, record_monitor->device);
910 record_monitor->device->new_output_buffers(output_frame, output_colormodel);
911 //printf("RecordMonitorThread::new_output_frame 2\n");
914 void RecordMonitorThread::run()
916 //printf("RecordMonitorThread::run 1 %d\n", getpid());
919 // Wait for next frame
920 output_lock->lock("RecordMonitorThread::run");
926 //printf("RecordMonitorThread::run 1\n");
928 //printf("RecordMonitorThread::run 2\n");
930 //printf("RecordMonitorThread::run 3\n");
932 //printf("RecordMonitorThread::run 4\n");
941 RecVideoMJPGThread::RecVideoMJPGThread(Record *record, RecordMonitorThread *thread)
943 this->record = record;
944 this->thread = thread;
948 RecVideoMJPGThread::~RecVideoMJPGThread()
952 int RecVideoMJPGThread::start_rendering()
954 mjpeg = mjpeg_new(record->default_asset->width,
955 record->default_asset->height,
957 //printf("RecVideoMJPGThread::start_rendering 1 %p\n", mjpeg);
961 int RecVideoMJPGThread::stop_rendering()
963 //printf("RecVideoMJPGThread::stop_rendering 1 %p\n", mjpeg);
964 if(mjpeg) mjpeg_delete(mjpeg);
965 //printf("RecVideoMJPGThread::stop_rendering 2\n");
969 int RecVideoMJPGThread::render_frame(VFrame *frame, long size)
971 // printf("RecVideoMJPGThread::render_frame %d %02x%02x %02x%02x\n",
972 // frame->get_field2_offset(),
973 // frame->get_data()[0],
974 // frame->get_data()[1],
975 // frame->get_data()[frame->get_field2_offset()],
976 // frame->get_data()[frame->get_field2_offset() + 1]);
977 //frame->set_field2_offset(0);
978 mjpeg_decompress(mjpeg,
980 frame->get_compressed_size(),
981 frame->get_field2_offset(),
982 thread->output_frame[0]->get_rows(),
983 thread->output_frame[0]->get_y(),
984 thread->output_frame[0]->get_u(),
985 thread->output_frame[0]->get_v(),
986 thread->output_frame[0]->get_color_model(),
987 record->mwindow->preferences->processors);
994 RecVideoDVThread::RecVideoDVThread(Record *record, RecordMonitorThread *thread)
996 this->record = record;
997 this->thread = thread;
1001 RecVideoDVThread::~RecVideoDVThread()
1006 int RecVideoDVThread::start_rendering()
1008 ((dv_t*)dv) = dv_new();
1012 int RecVideoDVThread::stop_rendering()
1014 if(dv) dv_delete(((dv_t*)dv));
1018 int RecVideoDVThread::render_frame(VFrame *frame, long size)
1020 unsigned char *yuv_planes[3];
1021 yuv_planes[0] = thread->output_frame[0]->get_y();
1022 yuv_planes[1] = thread->output_frame[0]->get_u();
1023 yuv_planes[2] = thread->output_frame[0]->get_v();
1024 dv_read_video(((dv_t*)dv),
1027 frame->get_compressed_size(),
1028 thread->output_frame[0]->get_color_model());