2 #include "bcdisplayinfo.h"
8 #include "edlsession.h"
15 #include "picon_png.h"
17 #include "pluginvclient.h"
18 #include "recordconfig.h"
19 #include "transportque.inc"
21 #include "videodevice.h"
22 #include "videodevice.inc"
27 #define HISTORY_FRAMES 30
29 class LiveVideoWindow;
36 void copy_from(LiveVideoConfig &src);
37 int equivalent(LiveVideoConfig &src);
38 void interpolate(LiveVideoConfig &prev,
39 LiveVideoConfig &next,
42 int64_t current_frame);
47 // Without access to the video device, the ChannelPicker can't
48 // do any of the things it was designed to. Instead, just provide
49 // a list of channels.
50 class LiveChannelList : public BC_ListBox
53 LiveChannelList(LiveVideo *plugin,
64 class LiveChannelSelect : public BC_Button
67 LiveChannelSelect(LiveVideo *plugin,
77 class LiveVideoWindow : public BC_Window
80 LiveVideoWindow(LiveVideo *plugin, int x, int y);
83 void create_objects();
85 int resize_event(int w, int h);
87 ArrayList<BC_ListBoxItem*> channel_list;
89 LiveChannelList *list;
90 LiveChannelSelect *select;
95 PLUGIN_THREAD_HEADER(LiveVideo, LiveVideoThread, LiveVideoWindow)
99 class LiveVideo : public PluginVClient
102 LiveVideo(PluginServer *server);
106 PLUGIN_CLASS_MEMBERS(LiveVideoConfig, LiveVideoThread);
108 int process_buffer(VFrame *frame,
109 int64_t start_position,
112 int is_multichannel();
116 void save_data(KeyFrame *keyframe);
117 void read_data(KeyFrame *keyframe);
121 ChannelDB *channeldb;
122 VideoDevice *vdevice;
123 // Colormodel the device generates
125 // Temporary for colormodel conversion
127 // What configuration parameters the device supports
128 Channel master_channel;
129 PictureConfig *picture;
130 BC_Hash *picture_defaults;
133 // Decompressors for different video drivers
149 LiveVideoConfig::LiveVideoConfig()
154 void LiveVideoConfig::copy_from(LiveVideoConfig &src)
156 this->channel = src.channel;
159 int LiveVideoConfig::equivalent(LiveVideoConfig &src)
161 return (this->channel == src.channel);
164 void LiveVideoConfig::interpolate(LiveVideoConfig &prev,
165 LiveVideoConfig &next,
168 int64_t current_frame)
170 this->channel = prev.channel;
177 LiveVideoWindow::LiveVideoWindow(LiveVideo *plugin, int x, int y)
178 : BC_Window(plugin->gui_string,
189 this->plugin = plugin;
192 LiveVideoWindow::~LiveVideoWindow()
194 channel_list.remove_all_objects();
197 void LiveVideoWindow::create_objects()
201 for(int i = 0; i < plugin->channeldb->size(); i++)
203 BC_ListBoxItem *current;
204 channel_list.append(current =
205 new BC_ListBoxItem(plugin->channeldb->get(i)->title));
206 if(i == plugin->config.channel) current->set_selected(1);
209 add_subwindow(title = new BC_Title(x, y, _("Channels:")));
210 y += title->get_h() + 5;
211 add_subwindow(list = new LiveChannelList(plugin,
216 get_h() - y - BC_OKButton::calculate_h() - 10 - 10));
217 y += list->get_h() + 10;
218 add_subwindow(select = new LiveChannelSelect(plugin,
226 WINDOW_CLOSE_EVENT(LiveVideoWindow)
228 int LiveVideoWindow::resize_event(int w, int h)
230 int list_bottom = get_h() - list->get_y() - list->get_h();
231 int list_side = get_w() - list->get_x() - list->get_w();
232 int select_top = get_h() - select->get_y();
234 title->reposition_window(title->get_x(), title->get_y());
236 list->reposition_window(list->get_x(),
238 w - list->get_x() - list_side,
239 h - list->get_y() - list_bottom);
240 select->reposition_window(select->get_x(),
250 LiveChannelList::LiveChannelList(LiveVideo *plugin,
251 LiveVideoWindow *gui,
260 LISTBOX_TEXT, // Display text list or icons
261 &gui->channel_list) // Each column has an ArrayList of BC_ListBoxItems.
263 this->plugin = plugin;
267 int LiveChannelList::handle_event()
269 plugin->config.channel = get_selection_number(0, 0);
270 plugin->send_configure_change();
275 LiveChannelSelect::LiveChannelSelect(LiveVideo *plugin,
276 LiveVideoWindow *gui,
280 BC_WindowBase::get_resources()->ok_images)
282 this->plugin = plugin;
286 int LiveChannelSelect::handle_event()
288 plugin->config.channel = gui->list->get_selection_number(0, 0);
289 plugin->send_configure_change();
307 PLUGIN_THREAD_OBJECT(LiveVideo, LiveVideoThread, LiveVideoWindow)
318 REGISTER_PLUGIN(LiveVideo)
325 LiveVideo::LiveVideo(PluginServer *server)
326 : PluginVClient(server)
330 channeldb = new ChannelDB;
337 picture_defaults = 0;
338 PLUGIN_CONSTRUCTOR_MACRO
342 LiveVideo::~LiveVideo()
344 PLUGIN_DESTRUCTOR_MACRO
347 vdevice->interrupt_crash();
348 vdevice->close_all();
354 if(dv) dv_delete(dv);
355 if(mjpeg) mjpeg_delete(mjpeg);
357 delete picture_defaults;
362 int LiveVideo::process_buffer(VFrame *frame,
363 int64_t start_position,
366 load_configuration();
367 //printf("LiveVideo::process_buffer 10 start_position=%lld buffer_size=%d size=%d\n",
368 //start_position, get_buffer_size(), size);
370 EDLSession *session = PluginClient::get_edlsession();
375 vdevice = new VideoDevice;
376 vdevice->open_input(session->vconfig_in,
382 // The color model depends on the asset configured by the user for recording.
383 // Unfortunately, get_best_colormodel returns the best colormodel for displaying
384 // on the record monitor, not the colormodel supported by the device.
385 // Some devices can read directly to the best colormodel and some can't.
386 switch(session->vconfig_in->driver)
388 case CAPTURE_FIREWIRE:
389 case CAPTURE_IEC61883:
391 case VIDEO4LINUX2JPEG:
392 input_cmodel = BC_COMPRESSED;
395 input_cmodel = vdevice->get_best_colormodel(session->recording_format);
400 // Load the picture config from the main defaults file.
401 if(!picture_defaults)
403 char path[BCTEXTLEN];
404 MWindow::create_defaults_path(path);
405 picture_defaults = new BC_Hash(path);
406 picture_defaults->load();
411 picture = new PictureConfig(picture_defaults);
414 // Picture must have usage from driver before it can load defaults.
415 master_channel.copy_usage(vdevice->channel);
416 picture->copy_usage(vdevice->picture);
417 picture->load_defaults();
419 // Need to load picture defaults but this requires MWindow.
420 vdevice->set_picture(picture);
421 vdevice->set_channel(channeldb->get(config.channel));
423 prev_channel = config.channel;
426 if(session && vdevice)
429 if(prev_channel != config.channel)
431 prev_channel = config.channel;
432 vdevice->set_picture(picture);
433 vdevice->set_channel(channeldb->get(config.channel));
437 VFrame *input = frame;
438 if(input_cmodel != frame->get_color_model() ||
439 session->vconfig_in->w != frame->get_w() ||
440 session->vconfig_in->h != frame->get_h())
445 session->vconfig_in->w,
446 session->vconfig_in->h,
451 vdevice->read_buffer(input);
454 if(input->get_color_model() != BC_COMPRESSED)
457 int w = MIN(session->vconfig_in->w, frame->get_w());
458 int h = MIN(session->vconfig_in->h, frame->get_h());
459 cmodel_transfer(frame->get_rows(), /* Leave NULL if non existent */
461 frame->get_y(), /* Leave NULL if non existent */
464 input->get_y(), /* Leave NULL if non existent */
467 0, /* Dimensions to capture from input frame */
471 0, /* Dimensions to project on output frame */
475 input->get_color_model(),
476 frame->get_color_model(),
477 0, /* When transfering BC_RGBA8888 to non-alpha this is the background color in 0xRRGGBB hex */
478 input->get_bytes_per_line(), /* For planar use the luma rowspan */
479 frame->get_bytes_per_line()); /* For planar use the luma rowspan */
480 frame->set_opengl_state(VFrame::RAM);
485 switch(session->vconfig_in->driver)
487 case CAPTURE_FIREWIRE:
488 case CAPTURE_IEC61883:
489 // Decompress a DV frame from the driver
492 dv_read_video(((dv_t*)dv),
495 input->get_compressed_size(),
496 frame->get_color_model());
497 frame->set_opengl_state(VFrame::RAM);
502 case VIDEO4LINUX2JPEG:
507 mjpeg_decompress(mjpeg,
509 input->get_compressed_size(),
510 input->get_field2_offset(),
515 frame->get_color_model(),
516 get_project_smp() + 1);
526 void LiveVideo::render_stop()
530 vdevice->interrupt_crash();
531 vdevice->close_all();
535 delete picture_defaults;
536 picture_defaults = 0;
542 char* LiveVideo::plugin_title() { return N_("Live Video"); }
543 int LiveVideo::is_realtime() { return 1; }
544 int LiveVideo::is_multichannel() { return 0; }
545 int LiveVideo::is_synthesis() { return 1; }
548 NEW_PICON_MACRO(LiveVideo)
550 SHOW_GUI_MACRO(LiveVideo, LiveVideoThread)
552 RAISE_WINDOW_MACRO(LiveVideo)
554 SET_STRING_MACRO(LiveVideo);
556 LOAD_CONFIGURATION_MACRO(LiveVideo, LiveVideoConfig)
558 int LiveVideo::load_defaults()
560 char directory[BCTEXTLEN], string[BCTEXTLEN];
561 // set the default directory
562 sprintf(directory, "%slivevideo.rc", BCASTDIR);
564 defaults = new BC_Hash(directory);
567 // Load channel table
568 EDLSession *session = PluginClient::get_edlsession();
570 VideoDevice::load_channeldb(channeldb, session->vconfig_in);
571 config.channel = defaults->get("CHANNEL", 0);
572 w = defaults->get("W", w);
573 h = defaults->get("H", h);
577 int LiveVideo::save_defaults()
579 defaults->update("CHANNEL", config.channel);
580 defaults->update("W", w);
581 defaults->update("H", h);
586 void LiveVideo::save_data(KeyFrame *keyframe)
589 output.set_shared_string(keyframe->data, MESSAGESIZE);
590 output.tag.set_title("LIVEVIDEO");
591 output.tag.set_property("CHANNEL", config.channel);
593 output.tag.set_title("/LIVEVIDEO");
595 output.terminate_string();
598 void LiveVideo::read_data(KeyFrame *keyframe)
602 input.set_shared_string(keyframe->data, strlen(keyframe->data));
608 result = input.read_tag();
612 if(input.tag.title_is("LIVEVIDEO"))
614 config.channel = input.tag.get_property("CHANNEL", config.channel);
620 void LiveVideo::update_gui()
624 if(load_configuration())
626 thread->window->lock_window("LiveVideo::update_gui");
627 thread->window->list->set_selected(&thread->window->channel_list,
630 thread->window->list->draw_items(1);
631 thread->window->unlock_window();