00001 #include "asset.h"
00002 #include "bcdisplayinfo.h"
00003 #include "bcsignals.h"
00004 #include "channel.h"
00005 #include "channeldb.h"
00006 #include "clip.h"
00007 #include "bchash.h"
00008 #include "edlsession.h"
00009 #include "filexml.h"
00010 #include "guicast.h"
00011 #include "language.h"
00012 #include "libdv.h"
00013 #include "libmjpeg.h"
00014 #include "mwindow.h"
00015 #include "picon_png.h"
00016 #include "picture.h"
00017 #include "pluginvclient.h"
00018 #include "recordconfig.h"
00019 #include "transportque.inc"
00020 #include "vframe.h"
00021 #include "videodevice.h"
00022 #include "videodevice.inc"
00023
00024 #include <string.h>
00025 #include <stdint.h>
00026
00027 #define HISTORY_FRAMES 30
00028 class LiveVideo;
00029 class LiveVideoWindow;
00030
00031
00032 class LiveVideoConfig
00033 {
00034 public:
00035 LiveVideoConfig();
00036 void copy_from(LiveVideoConfig &src);
00037 int equivalent(LiveVideoConfig &src);
00038 void interpolate(LiveVideoConfig &prev,
00039 LiveVideoConfig &next,
00040 int64_t prev_frame,
00041 int64_t next_frame,
00042 int64_t current_frame);
00043 int channel;
00044 };
00045
00046
00047
00048
00049
00050 class LiveChannelList : public BC_ListBox
00051 {
00052 public:
00053 LiveChannelList(LiveVideo *plugin,
00054 LiveVideoWindow *gui,
00055 int x,
00056 int y,
00057 int w,
00058 int h);
00059 int handle_event();
00060 LiveVideo *plugin;
00061 LiveVideoWindow *gui;
00062 };
00063
00064 class LiveChannelSelect : public BC_Button
00065 {
00066 public:
00067 LiveChannelSelect(LiveVideo *plugin,
00068 LiveVideoWindow *gui,
00069 int x,
00070 int y);
00071 int handle_event();
00072 LiveVideo *plugin;
00073 LiveVideoWindow *gui;
00074 };
00075
00076
00077 class LiveVideoWindow : public BC_Window
00078 {
00079 public:
00080 LiveVideoWindow(LiveVideo *plugin, int x, int y);
00081 ~LiveVideoWindow();
00082
00083 void create_objects();
00084 int close_event();
00085 int resize_event(int w, int h);
00086
00087 ArrayList<BC_ListBoxItem*> channel_list;
00088 BC_Title *title;
00089 LiveChannelList *list;
00090 LiveChannelSelect *select;
00091 LiveVideo *plugin;
00092 };
00093
00094
00095 PLUGIN_THREAD_HEADER(LiveVideo, LiveVideoThread, LiveVideoWindow)
00096
00097
00098
00099 class LiveVideo : public PluginVClient
00100 {
00101 public:
00102 LiveVideo(PluginServer *server);
00103 ~LiveVideo();
00104
00105
00106 PLUGIN_CLASS_MEMBERS(LiveVideoConfig, LiveVideoThread);
00107
00108 int process_buffer(VFrame *frame,
00109 int64_t start_position,
00110 double frame_rate);
00111 int is_realtime();
00112 int is_multichannel();
00113 int is_synthesis();
00114 int load_defaults();
00115 int save_defaults();
00116 void save_data(KeyFrame *keyframe);
00117 void read_data(KeyFrame *keyframe);
00118 void update_gui();
00119 void render_stop();
00120
00121 ChannelDB *channeldb;
00122 VideoDevice *vdevice;
00123
00124 int input_cmodel;
00125
00126 VFrame *temp;
00127
00128 Channel master_channel;
00129 PictureConfig *picture;
00130 BC_Hash *picture_defaults;
00131 int prev_channel;
00132 int w, h;
00133
00134 dv_t *dv;
00135 mjpeg_t *mjpeg;
00136 };
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149 LiveVideoConfig::LiveVideoConfig()
00150 {
00151 channel = 0;
00152 }
00153
00154 void LiveVideoConfig::copy_from(LiveVideoConfig &src)
00155 {
00156 this->channel = src.channel;
00157 }
00158
00159 int LiveVideoConfig::equivalent(LiveVideoConfig &src)
00160 {
00161 return (this->channel == src.channel);
00162 }
00163
00164 void LiveVideoConfig::interpolate(LiveVideoConfig &prev,
00165 LiveVideoConfig &next,
00166 int64_t prev_frame,
00167 int64_t next_frame,
00168 int64_t current_frame)
00169 {
00170 this->channel = prev.channel;
00171 }
00172
00173
00174
00175
00176
00177 LiveVideoWindow::LiveVideoWindow(LiveVideo *plugin, int x, int y)
00178 : BC_Window(plugin->gui_string,
00179 x,
00180 y,
00181 plugin->w,
00182 plugin->h,
00183 100,
00184 100,
00185 1,
00186 0,
00187 1)
00188 {
00189 this->plugin = plugin;
00190 }
00191
00192 LiveVideoWindow::~LiveVideoWindow()
00193 {
00194 channel_list.remove_all_objects();
00195 }
00196
00197 void LiveVideoWindow::create_objects()
00198 {
00199 int x = 10, y = 10;
00200
00201 for(int i = 0; i < plugin->channeldb->size(); i++)
00202 {
00203 BC_ListBoxItem *current;
00204 channel_list.append(current =
00205 new BC_ListBoxItem(plugin->channeldb->get(i)->title));
00206 if(i == plugin->config.channel) current->set_selected(1);
00207 }
00208
00209 add_subwindow(title = new BC_Title(x, y, _("Channels:")));
00210 y += title->get_h() + 5;
00211 add_subwindow(list = new LiveChannelList(plugin,
00212 this,
00213 x,
00214 y,
00215 get_w() - x - 10,
00216 get_h() - y - BC_OKButton::calculate_h() - 10 - 10));
00217 y += list->get_h() + 10;
00218 add_subwindow(select = new LiveChannelSelect(plugin,
00219 this,
00220 x,
00221 y));
00222 show_window();
00223 flush();
00224 }
00225
00226 WINDOW_CLOSE_EVENT(LiveVideoWindow)
00227
00228 int LiveVideoWindow::resize_event(int w, int h)
00229 {
00230 int list_bottom = get_h() - list->get_y() - list->get_h();
00231 int list_side = get_w() - list->get_x() - list->get_w();
00232 int select_top = get_h() - select->get_y();
00233
00234 title->reposition_window(title->get_x(), title->get_y());
00235
00236 list->reposition_window(list->get_x(),
00237 list->get_y(),
00238 w - list->get_x() - list_side,
00239 h - list->get_y() - list_bottom);
00240 select->reposition_window(select->get_x(),
00241 h - select_top);
00242 plugin->w = w;
00243 plugin->h = h;
00244 return 1;
00245 }
00246
00247
00248
00249
00250 LiveChannelList::LiveChannelList(LiveVideo *plugin,
00251 LiveVideoWindow *gui,
00252 int x,
00253 int y,
00254 int w,
00255 int h)
00256 : BC_ListBox(x,
00257 y,
00258 w,
00259 h,
00260 LISTBOX_TEXT,
00261 &gui->channel_list)
00262 {
00263 this->plugin = plugin;
00264 this->gui = gui;
00265 }
00266
00267 int LiveChannelList::handle_event()
00268 {
00269 plugin->config.channel = get_selection_number(0, 0);
00270 plugin->send_configure_change();
00271 return 1;
00272 }
00273
00274
00275 LiveChannelSelect::LiveChannelSelect(LiveVideo *plugin,
00276 LiveVideoWindow *gui,
00277 int x,
00278 int y)
00279 : BC_Button(x, y,
00280 BC_WindowBase::get_resources()->ok_images)
00281 {
00282 this->plugin = plugin;
00283 this->gui = gui;
00284 }
00285
00286 int LiveChannelSelect::handle_event()
00287 {
00288 plugin->config.channel = gui->list->get_selection_number(0, 0);
00289 plugin->send_configure_change();
00290 return 1;
00291 }
00292
00293
00294
00295
00296
00297
00298
00299
00300
00301
00302
00303
00304
00305
00306
00307 PLUGIN_THREAD_OBJECT(LiveVideo, LiveVideoThread, LiveVideoWindow)
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318 REGISTER_PLUGIN(LiveVideo)
00319
00320
00321
00322
00323
00324
00325 LiveVideo::LiveVideo(PluginServer *server)
00326 : PluginVClient(server)
00327 {
00328 vdevice = 0;
00329 temp = 0;
00330 channeldb = new ChannelDB;
00331 w = 320;
00332 h = 640;
00333 prev_channel = 0;
00334 dv = 0;
00335 mjpeg = 0;
00336 picture = 0;
00337 picture_defaults = 0;
00338 PLUGIN_CONSTRUCTOR_MACRO
00339 }
00340
00341
00342 LiveVideo::~LiveVideo()
00343 {
00344 PLUGIN_DESTRUCTOR_MACRO
00345 if(vdevice)
00346 {
00347 vdevice->interrupt_crash();
00348 vdevice->close_all();
00349 delete vdevice;
00350 }
00351
00352 delete channeldb;
00353 delete temp;
00354 if(dv) dv_delete(dv);
00355 if(mjpeg) mjpeg_delete(mjpeg);
00356 delete picture;
00357 delete picture_defaults;
00358 }
00359
00360
00361
00362 int LiveVideo::process_buffer(VFrame *frame,
00363 int64_t start_position,
00364 double frame_rate)
00365 {
00366 load_configuration();
00367
00368
00369
00370 EDLSession *session = PluginClient::get_edlsession();
00371 if(!vdevice)
00372 {
00373 if(session)
00374 {
00375 vdevice = new VideoDevice;
00376 vdevice->open_input(session->vconfig_in,
00377 0,
00378 0,
00379 1.0,
00380 frame_rate);
00381
00382
00383
00384
00385
00386 switch(session->vconfig_in->driver)
00387 {
00388 case CAPTURE_FIREWIRE:
00389 case CAPTURE_IEC61883:
00390 case CAPTURE_BUZ:
00391 case VIDEO4LINUX2JPEG:
00392 input_cmodel = BC_COMPRESSED;
00393 break;
00394 default:
00395 input_cmodel = vdevice->get_best_colormodel(session->recording_format);
00396 break;
00397 }
00398
00399
00400
00401 if(!picture_defaults)
00402 {
00403 char path[BCTEXTLEN];
00404 MWindow::create_defaults_path(path);
00405 picture_defaults = new BC_Hash(path);
00406 picture_defaults->load();
00407 }
00408
00409 if(!picture)
00410 {
00411 picture = new PictureConfig(picture_defaults);
00412 }
00413
00414
00415 master_channel.copy_usage(vdevice->channel);
00416 picture->copy_usage(vdevice->picture);
00417 picture->load_defaults();
00418
00419
00420 vdevice->set_picture(picture);
00421 vdevice->set_channel(channeldb->get(config.channel));
00422 }
00423 prev_channel = config.channel;
00424 }
00425
00426 if(session && vdevice)
00427 {
00428
00429 if(prev_channel != config.channel)
00430 {
00431 prev_channel = config.channel;
00432 vdevice->set_picture(picture);
00433 vdevice->set_channel(channeldb->get(config.channel));
00434 }
00435
00436
00437 VFrame *input = frame;
00438 if(input_cmodel != frame->get_color_model() ||
00439 session->vconfig_in->w != frame->get_w() ||
00440 session->vconfig_in->h != frame->get_h())
00441 {
00442 if(!temp)
00443 {
00444 temp = new VFrame(0,
00445 session->vconfig_in->w,
00446 session->vconfig_in->h,
00447 input_cmodel);
00448 }
00449 input = temp;
00450 }
00451 vdevice->read_buffer(input);
00452 if(input != frame)
00453 {
00454 if(input->get_color_model() != BC_COMPRESSED)
00455 {
00456 SET_TRACE
00457 int w = MIN(session->vconfig_in->w, frame->get_w());
00458 int h = MIN(session->vconfig_in->h, frame->get_h());
00459 cmodel_transfer(frame->get_rows(),
00460 input->get_rows(),
00461 frame->get_y(),
00462 frame->get_u(),
00463 frame->get_v(),
00464 input->get_y(),
00465 input->get_u(),
00466 input->get_v(),
00467 0,
00468 0,
00469 w,
00470 h,
00471 0,
00472 0,
00473 w,
00474 h,
00475 input->get_color_model(),
00476 frame->get_color_model(),
00477 0,
00478 input->get_bytes_per_line(),
00479 frame->get_bytes_per_line());
00480 frame->set_opengl_state(VFrame::RAM);
00481 SET_TRACE
00482 }
00483 else
00484 {
00485 switch(session->vconfig_in->driver)
00486 {
00487 case CAPTURE_FIREWIRE:
00488 case CAPTURE_IEC61883:
00489
00490 if(!dv)
00491 dv = dv_new();
00492 dv_read_video(((dv_t*)dv),
00493 frame->get_rows(),
00494 input->get_data(),
00495 input->get_compressed_size(),
00496 frame->get_color_model());
00497 frame->set_opengl_state(VFrame::RAM);
00498 SET_TRACE
00499 break;
00500
00501 case CAPTURE_BUZ:
00502 case VIDEO4LINUX2JPEG:
00503 if(!mjpeg)
00504 mjpeg = mjpeg_new(w,
00505 h,
00506 2);
00507 mjpeg_decompress(mjpeg,
00508 input->get_data(),
00509 input->get_compressed_size(),
00510 input->get_field2_offset(),
00511 frame->get_rows(),
00512 frame->get_y(),
00513 frame->get_u(),
00514 frame->get_v(),
00515 frame->get_color_model(),
00516 get_project_smp() + 1);
00517 break;
00518 }
00519 }
00520 }
00521 }
00522
00523 return 0;
00524 }
00525
00526 void LiveVideo::render_stop()
00527 {
00528 if(vdevice)
00529 {
00530 vdevice->interrupt_crash();
00531 vdevice->close_all();
00532 delete vdevice;
00533 vdevice = 0;
00534 }
00535 delete picture_defaults;
00536 picture_defaults = 0;
00537 delete picture;
00538 picture = 0;
00539 }
00540
00541
00542 char* LiveVideo::plugin_title() { return N_("Live Video"); }
00543 int LiveVideo::is_realtime() { return 1; }
00544 int LiveVideo::is_multichannel() { return 0; }
00545 int LiveVideo::is_synthesis() { return 1; }
00546
00547
00548 NEW_PICON_MACRO(LiveVideo)
00549
00550 SHOW_GUI_MACRO(LiveVideo, LiveVideoThread)
00551
00552 RAISE_WINDOW_MACRO(LiveVideo)
00553
00554 SET_STRING_MACRO(LiveVideo);
00555
00556 LOAD_CONFIGURATION_MACRO(LiveVideo, LiveVideoConfig)
00557
00558 int LiveVideo::load_defaults()
00559 {
00560 char directory[BCTEXTLEN], string[BCTEXTLEN];
00561
00562 sprintf(directory, "%slivevideo.rc", BCASTDIR);
00563
00564 defaults = new BC_Hash(directory);
00565 defaults->load();
00566
00567
00568 EDLSession *session = PluginClient::get_edlsession();
00569 if(session)
00570 VideoDevice::load_channeldb(channeldb, session->vconfig_in);
00571 config.channel = defaults->get("CHANNEL", 0);
00572 w = defaults->get("W", w);
00573 h = defaults->get("H", h);
00574 return 0;
00575 }
00576
00577 int LiveVideo::save_defaults()
00578 {
00579 defaults->update("CHANNEL", config.channel);
00580 defaults->update("W", w);
00581 defaults->update("H", h);
00582 defaults->save();
00583 return 0;
00584 }
00585
00586 void LiveVideo::save_data(KeyFrame *keyframe)
00587 {
00588 FileXML output;
00589 output.set_shared_string(keyframe->data, MESSAGESIZE);
00590 output.tag.set_title("LIVEVIDEO");
00591 output.tag.set_property("CHANNEL", config.channel);
00592 output.append_tag();
00593 output.tag.set_title("/LIVEVIDEO");
00594 output.append_tag();
00595 output.terminate_string();
00596 }
00597
00598 void LiveVideo::read_data(KeyFrame *keyframe)
00599 {
00600 FileXML input;
00601
00602 input.set_shared_string(keyframe->data, strlen(keyframe->data));
00603
00604 int result = 0;
00605
00606 while(!result)
00607 {
00608 result = input.read_tag();
00609
00610 if(!result)
00611 {
00612 if(input.tag.title_is("LIVEVIDEO"))
00613 {
00614 config.channel = input.tag.get_property("CHANNEL", config.channel);
00615 }
00616 }
00617 }
00618 }
00619
00620 void LiveVideo::update_gui()
00621 {
00622 if(thread)
00623 {
00624 if(load_configuration())
00625 {
00626 thread->window->lock_window("LiveVideo::update_gui");
00627 thread->window->list->set_selected(&thread->window->channel_list,
00628 config.channel,
00629 1);
00630 thread->window->list->draw_items(1);
00631 thread->window->unlock_window();
00632 }
00633 }
00634 }
00635
00636
00637
00638
00639