00001 #include "720to480.h"
00002 #include "clip.h"
00003 #include "bchash.h"
00004 #include "filexml.h"
00005 #include "bcdisplayinfo.h"
00006 #include "keyframe.h"
00007 #include "language.h"
00008 #include "mainprogress.h"
00009 #include "vframe.h"
00010
00011
00012 #include <stdint.h>
00013 #include <string.h>
00014
00015
00016 REGISTER_PLUGIN(_720to480Main)
00017
00018
00019 #define FORWARD 0
00020 #define REVERSE 1
00021
00022 _720to480Config::_720to480Config()
00023 {
00024 first_field = 0;
00025 direction = FORWARD;
00026 }
00027
00028
00029
00030
00031
00032 _720to480Window::_720to480Window(_720to480Main *client, int x, int y)
00033 : BC_Window(client->gui_string,
00034 x,
00035 y,
00036 230,
00037 150,
00038 230,
00039 150,
00040 0,
00041 0,
00042 1)
00043 {
00044 this->client = client;
00045 }
00046
00047
00048 _720to480Window::~_720to480Window()
00049 {
00050 }
00051
00052 int _720to480Window::create_objects()
00053 {
00054 int x = 10, y = 10;
00055
00056 add_tool(odd_first = new _720to480Order(client, this, 1, x, y, _("Odd field first")));
00057 y += 25;
00058 add_tool(even_first = new _720to480Order(client, this, 0, x, y, _("Even field first")));
00059
00060
00061
00062
00063
00064
00065 add_subwindow(new BC_OKButton(this));
00066 add_subwindow(new BC_CancelButton(this));
00067
00068 show_window();
00069 flush();
00070 return 0;
00071 }
00072
00073 WINDOW_CLOSE_EVENT(_720to480Window)
00074
00075 int _720to480Window::set_first_field(int first_field)
00076 {
00077 odd_first->update(first_field == 1);
00078 even_first->update(first_field == 0);
00079
00080 client->config.first_field = first_field;
00081 return 0;
00082 }
00083
00084 int _720to480Window::set_direction(int direction)
00085 {
00086 forward->update(direction == FORWARD);
00087 reverse->update(direction == REVERSE);
00088
00089
00090 client->config.direction = direction;
00091 return 0;
00092 }
00093
00094
00095
00096 _720to480Order::_720to480Order(_720to480Main *client,
00097 _720to480Window *window,
00098 int output,
00099 int x,
00100 int y,
00101 char *text)
00102 : BC_Radial(x,
00103 y,
00104 client->config.first_field == output,
00105 text)
00106 {
00107 this->client = client;
00108 this->window = window;
00109 this->output = output;
00110 }
00111
00112 int _720to480Order::handle_event()
00113 {
00114 window->set_first_field(output);
00115 return 1;
00116 }
00117
00118
00119
00120
00121
00122 _720to480Direction::_720to480Direction(_720to480Main *client,
00123 _720to480Window *window,
00124 int output,
00125 int x,
00126 int y,
00127 char *text)
00128 : BC_Radial(x,
00129 y,
00130 client->config.direction == output,
00131 text)
00132 {
00133 this->client = client;
00134 this->window = window;
00135 this->output = output;
00136 }
00137
00138 int _720to480Direction::handle_event()
00139 {
00140 window->set_direction(output);
00141 return 1;
00142 }
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159 _720to480Main::_720to480Main(PluginServer *server)
00160 : PluginVClient(server)
00161 {
00162 temp = 0;
00163 load_defaults();
00164 }
00165
00166 _720to480Main::~_720to480Main()
00167 {
00168 save_defaults();
00169 delete defaults;
00170
00171 if(temp) delete temp;
00172 }
00173
00174 char* _720to480Main::plugin_title() { return N_("720 to 480"); }
00175 int _720to480Main::is_realtime() { return 0; }
00176
00177 double _720to480Main::get_framerate()
00178 {
00179 return project_frame_rate / 2;
00180 }
00181
00182
00183
00184
00185
00186 int _720to480Main::load_defaults()
00187 {
00188 char directory[BCTEXTLEN], string[BCTEXTLEN];
00189 sprintf(directory, "%s720to480.rc", BCASTDIR);
00190
00191 defaults = new BC_Hash(directory);
00192 defaults->load();
00193 config.first_field = defaults->get("FIRST_FIELD", config.first_field);
00194 config.direction = defaults->get("DIRECTION", config.direction);
00195 return 0;
00196 }
00197
00198
00199 int _720to480Main::save_defaults()
00200 {
00201 defaults->update("FIRST_FIELD", config.first_field);
00202 defaults->update("DIRECTION", config.direction);
00203 defaults->save();
00204 return 0;
00205 }
00206
00207 int _720to480Main::get_parameters()
00208 {
00209 BC_DisplayInfo info;
00210 _720to480Window window(this,
00211 info.get_abs_cursor_x(),
00212 info.get_abs_cursor_y());
00213 window.create_objects();
00214 int result = window.run_window();
00215 return result;
00216 }
00217
00218 int _720to480Main::start_loop()
00219 {
00220 if(PluginClient::interactive)
00221 {
00222 char string[BCTEXTLEN];
00223 sprintf(string, "%s...", plugin_title());
00224 progress = start_progress(string,
00225 PluginClient::end - PluginClient::start);
00226 }
00227
00228 input_position = PluginClient::start;
00229 return 0;
00230 }
00231
00232
00233 int _720to480Main::stop_loop()
00234 {
00235 if(PluginClient::interactive)
00236 {
00237 progress->stop_progress();
00238 delete progress;
00239 }
00240 return 0;
00241 }
00242
00243
00244 #define DST_W 854
00245 #define DST_H 240
00246
00247
00248 void _720to480Main::reduce_field(VFrame *output, VFrame *input, int dest_row)
00249 {
00250 int in_w = input->get_w();
00251 int in_h = input->get_h();
00252 int out_w = output->get_w();
00253 int out_h = output->get_h();
00254
00255 #define REDUCE_MACRO(type, temp, components) \
00256 for(int i = 0; i < DST_H; i++) \
00257 { \
00258 int output_number = dest_row + i * 2; \
00259 if(output_number >= out_h) break; \
00260 \
00261 int in1 = i * 3 + dest_row * 2; \
00262 int in2 = i * 3 + 1 + dest_row * 2; \
00263 int in3 = i * 3 + 2 + dest_row * 2; \
00264 \
00265 if(in1 >= in_h) in1 = in_h - 1; \
00266 if(in2 >= in_h) in2 = in_h - 1; \
00267 if(in3 >= in_h) in3 = in_h - 1; \
00268 \
00269 type *out_row = (type*)output->get_rows()[output_number]; \
00270 type *in_row1 = (type*)input->get_rows()[in1]; \
00271 type *in_row2 = (type*)input->get_rows()[in2]; \
00272 type *in_row3 = (type*)input->get_rows()[in3]; \
00273 \
00274 int w = MIN(out_w, in_w) * components; \
00275 for(int j = 0; j < w; j++) \
00276 { \
00277 *out_row++ = ((temp)*in_row1++ + \
00278 (temp)*in_row2++ + \
00279 (temp)*in_row3++) / 3; \
00280 } \
00281 }
00282
00283 switch(input->get_color_model())
00284 {
00285 case BC_RGB888:
00286 case BC_YUV888:
00287 REDUCE_MACRO(unsigned char, int64_t, 3);
00288 break;
00289 case BC_RGB_FLOAT:
00290 REDUCE_MACRO(float, float, 3);
00291 break;
00292 case BC_RGBA8888:
00293 case BC_YUVA8888:
00294 REDUCE_MACRO(unsigned char, int64_t, 4);
00295 break;
00296 case BC_RGBA_FLOAT:
00297 REDUCE_MACRO(float, float, 4);
00298 break;
00299 case BC_RGB161616:
00300 case BC_YUV161616:
00301 REDUCE_MACRO(uint16_t, int64_t, 3);
00302 break;
00303 case BC_RGBA16161616:
00304 case BC_YUVA16161616:
00305 REDUCE_MACRO(uint16_t, int64_t, 4);
00306 break;
00307 }
00308 }
00309
00310 int _720to480Main::process_loop(VFrame *output)
00311 {
00312 int result = 0;
00313
00314 if(!temp)
00315 temp = new VFrame(0,
00316 output->get_w(),
00317 output->get_h(),
00318 output->get_color_model());
00319
00320 if(config.direction == FORWARD)
00321 {
00322
00323 read_frame(temp, input_position);
00324 reduce_field(output, temp, config.first_field == 0 ? 0 : 1);
00325 input_position++;
00326
00327 read_frame(temp, input_position);
00328 reduce_field(output, temp, config.first_field == 0 ? 1 : 0);
00329 input_position++;
00330 }
00331
00332 if(PluginClient::interactive)
00333 result = progress->update(input_position - PluginClient::start);
00334
00335 if(input_position >= PluginClient::end) result = 1;
00336
00337 return result;
00338 }
00339
00340
00341
00342
00343
00344
00345 void _720to480Main::save_data(KeyFrame *keyframe)
00346 {
00347 FileXML output;
00348 output.set_shared_string(keyframe->data, MESSAGESIZE);
00349 output.tag.set_title("720TO480");
00350 output.tag.set_property("FIRST_FIELD", config.first_field);
00351 output.tag.set_property("DIRECTION", config.direction);
00352 output.append_tag();
00353 output.tag.set_title("/720TO480");
00354 output.append_tag();
00355 output.terminate_string();
00356 }
00357
00358 void _720to480Main::read_data(KeyFrame *keyframe)
00359 {
00360 FileXML input;
00361 input.set_shared_string(keyframe->data, strlen(keyframe->data));
00362
00363 while(!input.read_tag())
00364 {
00365 if(input.tag.title_is("720TO480"))
00366 {
00367 config.first_field = input.tag.get_property("FIRST_FIELD", config.first_field);
00368 config.direction = input.tag.get_property("DIRECTION", config.direction);
00369 }
00370 }
00371 }
00372