00001 #include "bcdisplayinfo.h"
00002 #include "bchash.h"
00003 #include "filexml.h"
00004 #include "guicast.h"
00005 #include "keyframe.h"
00006 #include "transportque.h"
00007 #include "language.h"
00008 #include "mainprogress.h"
00009 #include "picon_png.h"
00010 #include "pluginvclient.h"
00011 #include "transportque.inc"
00012 #include "vframe.h"
00013
00014 #include <string.h>
00015
00016
00017 #define TOP_FIELD_FIRST 0
00018 #define BOTTOM_FIELD_FIRST 1
00019
00020 class FieldFrame;
00021 class FieldFrameWindow;
00022
00023
00024
00025
00026
00027
00028
00029 class FieldFrameConfig
00030 {
00031 public:
00032 FieldFrameConfig();
00033 int equivalent(FieldFrameConfig &src);
00034 int field_dominance;
00035 int first_frame;
00036 };
00037
00038
00039
00040
00041 class FieldFrameTop : public BC_Radial
00042 {
00043 public:
00044 FieldFrameTop(FieldFrame *plugin, FieldFrameWindow *gui, int x, int y);
00045 int handle_event();
00046 FieldFrame *plugin;
00047 FieldFrameWindow *gui;
00048 };
00049
00050
00051 class FieldFrameBottom : public BC_Radial
00052 {
00053 public:
00054 FieldFrameBottom(FieldFrame *plugin, FieldFrameWindow *gui, int x, int y);
00055 int handle_event();
00056 FieldFrame *plugin;
00057 FieldFrameWindow *gui;
00058 };
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078 class FieldFrameWindow : public BC_Window
00079 {
00080 public:
00081 FieldFrameWindow(FieldFrame *plugin, int x, int y);
00082 void create_objects();
00083 int close_event();
00084 FieldFrame *plugin;
00085 FieldFrameTop *top;
00086 FieldFrameBottom *bottom;
00087
00088
00089 };
00090
00091
00092 PLUGIN_THREAD_HEADER(FieldFrame, FieldFrameThread, FieldFrameWindow)
00093
00094
00095 class FieldFrame : public PluginVClient
00096 {
00097 public:
00098 FieldFrame(PluginServer *server);
00099 ~FieldFrame();
00100
00101 PLUGIN_CLASS_MEMBERS(FieldFrameConfig, FieldFrameThread);
00102
00103 int process_buffer(VFrame *frame,
00104 int64_t start_position,
00105 double frame_rate);
00106 int is_realtime();
00107 int load_defaults();
00108 int save_defaults();
00109 void save_data(KeyFrame *keyframe);
00110 void read_data(KeyFrame *keyframe);
00111 void update_gui();
00112 void apply_field(VFrame *output, VFrame *input, int field);
00113
00114
00115 VFrame *input;
00116 };
00117
00118
00119
00120
00121
00122
00123
00124
00125 REGISTER_PLUGIN(FieldFrame)
00126
00127
00128
00129
00130 FieldFrameConfig::FieldFrameConfig()
00131 {
00132 field_dominance = TOP_FIELD_FIRST;
00133 first_frame = 0;
00134 }
00135
00136 int FieldFrameConfig::equivalent(FieldFrameConfig &src)
00137 {
00138 return src.field_dominance == field_dominance &&
00139 src.first_frame == first_frame;
00140 }
00141
00142
00143
00144
00145
00146
00147
00148
00149 FieldFrameWindow::FieldFrameWindow(FieldFrame *plugin, int x, int y)
00150 : BC_Window(plugin->gui_string,
00151 x,
00152 y,
00153 230,
00154 100,
00155 230,
00156 100,
00157 0,
00158 0,
00159 1)
00160 {
00161 this->plugin = plugin;
00162 }
00163
00164 void FieldFrameWindow::create_objects()
00165 {
00166 int x = 10, y = 10;
00167 add_subwindow(top = new FieldFrameTop(plugin, this, x, y));
00168 y += 30;
00169 add_subwindow(bottom = new FieldFrameBottom(plugin, this, x, y));
00170
00171
00172
00173
00174
00175 show_window();
00176 flush();
00177 }
00178
00179 WINDOW_CLOSE_EVENT(FieldFrameWindow)
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193 FieldFrameTop::FieldFrameTop(FieldFrame *plugin,
00194 FieldFrameWindow *gui,
00195 int x,
00196 int y)
00197 : BC_Radial(x,
00198 y,
00199 plugin->config.field_dominance == TOP_FIELD_FIRST,
00200 _("Top field first"))
00201 {
00202 this->plugin = plugin;
00203 this->gui = gui;
00204 }
00205
00206 int FieldFrameTop::handle_event()
00207 {
00208 plugin->config.field_dominance = TOP_FIELD_FIRST;
00209 gui->bottom->update(0);
00210 plugin->send_configure_change();
00211 return 1;
00212 }
00213
00214
00215
00216
00217
00218 FieldFrameBottom::FieldFrameBottom(FieldFrame *plugin,
00219 FieldFrameWindow *gui,
00220 int x,
00221 int y)
00222 : BC_Radial(x,
00223 y,
00224 plugin->config.field_dominance == BOTTOM_FIELD_FIRST,
00225 _("Bottom field first"))
00226 {
00227 this->plugin = plugin;
00228 this->gui = gui;
00229 }
00230
00231 int FieldFrameBottom::handle_event()
00232 {
00233 plugin->config.field_dominance = BOTTOM_FIELD_FIRST;
00234 gui->top->update(0);
00235 plugin->send_configure_change();
00236 return 1;
00237 }
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296
00297
00298
00299
00300
00301
00302
00303 PLUGIN_THREAD_OBJECT(FieldFrame, FieldFrameThread, FieldFrameWindow)
00304
00305
00306
00307
00308
00309 FieldFrame::FieldFrame(PluginServer *server)
00310 : PluginVClient(server)
00311 {
00312 PLUGIN_CONSTRUCTOR_MACRO
00313 input = 0;
00314 }
00315
00316
00317 FieldFrame::~FieldFrame()
00318 {
00319 PLUGIN_DESTRUCTOR_MACRO
00320
00321 if(input) delete input;
00322 }
00323
00324 char* FieldFrame::plugin_title() { return N_("Fields to frames"); }
00325 int FieldFrame::is_realtime() { return 1; }
00326
00327
00328 NEW_PICON_MACRO(FieldFrame)
00329
00330 SHOW_GUI_MACRO(FieldFrame, FieldFrameThread)
00331
00332 RAISE_WINDOW_MACRO(FieldFrame)
00333
00334 SET_STRING_MACRO(FieldFrame);
00335
00336 int FieldFrame::load_configuration()
00337 {
00338 KeyFrame *prev_keyframe;
00339 FieldFrameConfig old_config = config;
00340
00341 prev_keyframe = get_prev_keyframe(get_source_position());
00342 read_data(prev_keyframe);
00343
00344 return !old_config.equivalent(config);
00345 }
00346
00347
00348 int FieldFrame::load_defaults()
00349 {
00350 char directory[BCTEXTLEN];
00351
00352 sprintf(directory, "%sfieldframe.rc", BCASTDIR);
00353
00354
00355 defaults = new BC_Hash(directory);
00356 defaults->load();
00357
00358 config.field_dominance = defaults->get("DOMINANCE", config.field_dominance);
00359 config.first_frame = defaults->get("FIRST_FRAME", config.first_frame);
00360 return 0;
00361 }
00362
00363 int FieldFrame::save_defaults()
00364 {
00365 defaults->update("DOMINANCE", config.field_dominance);
00366 defaults->update("FIRST_FRAME", config.first_frame);
00367 defaults->save();
00368 return 0;
00369 }
00370
00371 void FieldFrame::save_data(KeyFrame *keyframe)
00372 {
00373 FileXML output;
00374
00375
00376 output.set_shared_string(keyframe->data, MESSAGESIZE);
00377 output.tag.set_title("FIELD_FRAME");
00378 output.tag.set_property("DOMINANCE", config.field_dominance);
00379 output.tag.set_property("FIRST_FRAME", config.first_frame);
00380 output.append_tag();
00381 output.tag.set_title("/FIELD_FRAME");
00382 output.append_tag();
00383 output.terminate_string();
00384 }
00385
00386 void FieldFrame::read_data(KeyFrame *keyframe)
00387 {
00388 FileXML input;
00389
00390 input.set_shared_string(keyframe->data, strlen(keyframe->data));
00391
00392 int result = 0;
00393
00394 while(!input.read_tag())
00395 {
00396 if(input.tag.title_is("FIELD_FRAME"))
00397 {
00398 config.field_dominance = input.tag.get_property("DOMINANCE", config.field_dominance);
00399 config.first_frame = input.tag.get_property("FIRST_FRAME", config.first_frame);
00400 }
00401 }
00402 }
00403
00404
00405 void FieldFrame::update_gui()
00406 {
00407 if(thread)
00408 {
00409 if(load_configuration())
00410 {
00411 thread->window->lock_window();
00412 thread->window->top->update(config.field_dominance == TOP_FIELD_FIRST);
00413 thread->window->bottom->update(config.field_dominance == BOTTOM_FIELD_FIRST);
00414
00415
00416 thread->window->unlock_window();
00417 }
00418 }
00419 }
00420
00421
00422 int FieldFrame::process_buffer(VFrame *frame,
00423 int64_t start_position,
00424 double frame_rate)
00425 {
00426 int result = 0;
00427 load_configuration();
00428
00429 if(input && !input->equivalent(frame, 0))
00430 {
00431 delete input;
00432 input = 0;
00433 }
00434
00435 if(!input)
00436 {
00437 input = new VFrame(0,
00438 frame->get_w(),
00439 frame->get_h(),
00440 frame->get_color_model());
00441 }
00442
00443
00444 int64_t field1_position = start_position * 2;
00445 int64_t field2_position = start_position * 2 + 1;
00446
00447 if (get_direction() == PLAY_REVERSE)
00448 {
00449 field1_position -= 1;
00450 field2_position -= 1;
00451 }
00452
00453
00454
00455
00456
00457
00458 read_frame(input,
00459 0,
00460 field1_position,
00461 frame_rate * 2);
00462 apply_field(frame,
00463 input,
00464 config.field_dominance == TOP_FIELD_FIRST ? 0 : 1);
00465 read_frame(input,
00466 0,
00467 field2_position,
00468 frame_rate * 2);
00469 apply_field(frame,
00470 input,
00471 config.field_dominance == TOP_FIELD_FIRST ? 1 : 0);
00472
00473
00474
00475
00476
00477 return result;
00478 }
00479
00480
00481 void FieldFrame::apply_field(VFrame *output, VFrame *input, int field)
00482 {
00483 unsigned char **input_rows = input->get_rows();
00484 unsigned char **output_rows = output->get_rows();
00485 int row_size = VFrame::calculate_bytes_per_pixel(output->get_color_model()) * output->get_w();
00486 for(int i = field; i < output->get_h(); i += 2)
00487 {
00488 memcpy(output_rows[i], input_rows[i], row_size);
00489 }
00490 }