00001 #include "clip.h"
00002 #include "colormodels.h"
00003 #include "filexml.h"
00004 #include "language.h"
00005 #include "picon_png.h"
00006 #include "rgb601.h"
00007 #include "rgb601window.h"
00008
00009 #include <stdio.h>
00010 #include <string.h>
00011
00012
00013 REGISTER_PLUGIN(RGB601Main)
00014
00015
00016
00017
00018 RGB601Config::RGB601Config()
00019 {
00020 direction = 0;
00021 }
00022
00023 RGB601Main::RGB601Main(PluginServer *server)
00024 : PluginVClient(server)
00025 {
00026 PLUGIN_CONSTRUCTOR_MACRO
00027 }
00028
00029 RGB601Main::~RGB601Main()
00030 {
00031 PLUGIN_DESTRUCTOR_MACRO
00032 }
00033
00034 char* RGB601Main::plugin_title() { return N_("RGB - 601"); }
00035 int RGB601Main::is_realtime() { return 1; }
00036
00037
00038 SHOW_GUI_MACRO(RGB601Main, RGB601Thread)
00039
00040 SET_STRING_MACRO(RGB601Main)
00041
00042 RAISE_WINDOW_MACRO(RGB601Main)
00043
00044 NEW_PICON_MACRO(RGB601Main)
00045
00046 void RGB601Main::update_gui()
00047 {
00048 if(thread)
00049 {
00050 load_configuration();
00051 thread->window->lock_window();
00052 thread->window->forward->update(config.direction == 1);
00053 thread->window->reverse->update(config.direction == 2);
00054 thread->window->unlock_window();
00055 }
00056 }
00057
00058 int RGB601Main::load_defaults()
00059 {
00060 char directory[1024], string[1024];
00061
00062 sprintf(directory, "%srgb601.rc", BCASTDIR);
00063
00064
00065 defaults = new BC_Hash(directory);
00066 defaults->load();
00067
00068 config.direction = defaults->get("DIRECTION", config.direction);
00069 return 0;
00070 }
00071
00072 int RGB601Main::save_defaults()
00073 {
00074 defaults->update("DIRECTION", config.direction);
00075 defaults->save();
00076 return 0;
00077 }
00078
00079 void RGB601Main::load_configuration()
00080 {
00081 KeyFrame *prev_keyframe;
00082
00083 prev_keyframe = get_prev_keyframe(get_source_position());
00084
00085 read_data(prev_keyframe);
00086 }
00087
00088
00089 void RGB601Main::save_data(KeyFrame *keyframe)
00090 {
00091 FileXML output;
00092
00093
00094 output.set_shared_string(keyframe->data, MESSAGESIZE);
00095 output.tag.set_title("RGB601");
00096 output.tag.set_property("DIRECTION", config.direction);
00097 output.append_tag();
00098 output.tag.set_title("/RGB601");
00099 output.append_tag();
00100 output.terminate_string();
00101 }
00102
00103 void RGB601Main::read_data(KeyFrame *keyframe)
00104 {
00105 FileXML input;
00106
00107 input.set_shared_string(keyframe->data, strlen(keyframe->data));
00108
00109 int result = 0;
00110 float new_threshold;
00111
00112 while(!result)
00113 {
00114 result = input.read_tag();
00115
00116 if(!result)
00117 {
00118 if(input.tag.title_is("RGB601"))
00119 {
00120 config.direction = input.tag.get_property("DIRECTION", config.direction);
00121 }
00122 }
00123 }
00124
00125 if(thread)
00126 {
00127 thread->window->update();
00128 }
00129 }
00130
00131
00132 #define CREATE_TABLE(max) \
00133 { \
00134 for(int i = 0; i < max; i++) \
00135 { \
00136 int forward_output = (int)((double)0.8588 * i + max * 0.0627 + 0.5); \
00137 int reverse_output = (int)((double)1.1644 * i - max * 0.0627 + 0.5); \
00138 forward_table[i] = CLIP(forward_output, 0, max - 1); \
00139 reverse_table[i] = CLIP(reverse_output, 0, max - 1); \
00140 } \
00141 }
00142
00143 void RGB601Main::create_table(VFrame *input_ptr)
00144 {
00145 switch(input_ptr->get_color_model())
00146 {
00147 case BC_RGB888:
00148 case BC_YUV888:
00149 case BC_RGBA8888:
00150 case BC_YUVA8888:
00151 CREATE_TABLE(0x100);
00152 break;
00153
00154 case BC_RGB161616:
00155 case BC_YUV161616:
00156 case BC_RGBA16161616:
00157 case BC_YUVA16161616:
00158 CREATE_TABLE(0x10000);
00159 break;
00160 }
00161 }
00162
00163 #define PROCESS(table, type, components, yuv) \
00164 { \
00165 int bytes = w * components; \
00166 for(int i = 0; i < h; i++) \
00167 { \
00168 type *in_row = (type*)input_ptr->get_rows()[i]; \
00169 type *out_row = (type*)output_ptr->get_rows()[i]; \
00170 \
00171 if(yuv) \
00172 { \
00173 \
00174 for(int j = 0; j < w; j++) \
00175 { \
00176 out_row[j * components] = table[(int)in_row[j * components]]; \
00177 out_row[j * components + 1] = in_row[j * components + 1]; \
00178 out_row[j * components + 2] = in_row[j * components + 2]; \
00179 } \
00180 } \
00181 else \
00182 if(sizeof(type) == 4) \
00183 { \
00184 for(int j = 0; j < w; j++) \
00185 { \
00186 if(table == forward_table) \
00187 { \
00188 out_row[j * components] = (type)(in_row[j * components] * 0.8588 + 0.0627); \
00189 out_row[j * components + 1] = (type)(in_row[j * components + 1] * 0.8588 + 0.0627); \
00190 out_row[j * components + 2] = (type)(in_row[j * components + 2] * 0.8588 + 0.0627); \
00191 } \
00192 else \
00193 { \
00194 out_row[j * components] = (type)(in_row[j * components] * 1.1644 - 0.0627); \
00195 out_row[j * components + 1] = (type)(in_row[j * components + 1] * 1.1644 - 0.0627); \
00196 out_row[j * components + 2] = (type)(in_row[j * components + 2] * 1.1644 - 0.0627); \
00197 } \
00198 } \
00199 } \
00200 else \
00201 { \
00202 for(int j = 0; j < w; j++) \
00203 { \
00204 out_row[j * components] = table[(int)in_row[j * components]]; \
00205 out_row[j * components + 1] = table[(int)in_row[j * components + 1]]; \
00206 out_row[j * components + 2] = table[(int)in_row[j * components + 2]]; \
00207 } \
00208 } \
00209 } \
00210 }
00211
00212 void RGB601Main::process(int *table, VFrame *input_ptr, VFrame *output_ptr)
00213 {
00214 int w = input_ptr->get_w();
00215 int h = input_ptr->get_h();
00216
00217 if(config.direction == 1)
00218 switch(input_ptr->get_color_model())
00219 {
00220 case BC_YUV888:
00221 PROCESS(forward_table, unsigned char, 3, 1);
00222 break;
00223 case BC_YUVA8888:
00224 PROCESS(forward_table, unsigned char, 4, 1);
00225 break;
00226 case BC_YUV161616:
00227 PROCESS(forward_table, u_int16_t, 3, 1);
00228 break;
00229 case BC_YUVA16161616:
00230 PROCESS(forward_table, u_int16_t, 4, 1);
00231 break;
00232 case BC_RGB888:
00233 PROCESS(forward_table, unsigned char, 3, 0);
00234 break;
00235 case BC_RGBA8888:
00236 PROCESS(forward_table, unsigned char, 4, 0);
00237 break;
00238 case BC_RGB_FLOAT:
00239 PROCESS(forward_table, float, 3, 0);
00240 break;
00241 case BC_RGBA_FLOAT:
00242 PROCESS(forward_table, float, 4, 0);
00243 break;
00244 case BC_RGB161616:
00245 PROCESS(forward_table, u_int16_t, 3, 0);
00246 break;
00247 case BC_RGBA16161616:
00248 PROCESS(forward_table, u_int16_t, 4, 0);
00249 break;
00250 }
00251 else
00252 if(config.direction == 2)
00253 switch(input_ptr->get_color_model())
00254 {
00255 case BC_YUV888:
00256 PROCESS(reverse_table, unsigned char, 3, 1);
00257 break;
00258 case BC_YUVA8888:
00259 PROCESS(reverse_table, unsigned char, 4, 1);
00260 break;
00261 case BC_YUV161616:
00262 PROCESS(reverse_table, u_int16_t, 3, 1);
00263 break;
00264 case BC_YUVA16161616:
00265 PROCESS(reverse_table, u_int16_t, 4, 1);
00266 break;
00267 case BC_RGB888:
00268 PROCESS(reverse_table, unsigned char, 3, 0);
00269 break;
00270 case BC_RGBA8888:
00271 PROCESS(reverse_table, unsigned char, 4, 0);
00272 break;
00273 case BC_RGB_FLOAT:
00274 PROCESS(reverse_table, float, 3, 0);
00275 break;
00276 case BC_RGBA_FLOAT:
00277 PROCESS(reverse_table, float, 4, 0);
00278 break;
00279 case BC_RGB161616:
00280 PROCESS(reverse_table, u_int16_t, 3, 0);
00281 break;
00282 case BC_RGBA16161616:
00283 PROCESS(reverse_table, u_int16_t, 4, 0);
00284 break;
00285 }
00286 }
00287
00288 int RGB601Main::process_buffer(VFrame *frame,
00289 int64_t start_position,
00290 double frame_rate)
00291 {
00292 load_configuration();
00293
00294
00295 frame->get_params()->update("RGB601_DIRECTION", config.direction);
00296
00297 read_frame(frame,
00298 0,
00299 start_position,
00300 frame_rate,
00301 get_use_opengl());
00302
00303
00304 if(get_use_opengl() &&
00305 (prev_effect_is("Frames to fields") ||
00306 next_effect_is("Frames to fields")))
00307 {
00308 return 0;
00309 }
00310
00311 if(get_use_opengl() && config.direction)
00312 {
00313 run_opengl();
00314 return 0;
00315 }
00316
00317
00318 create_table(frame);
00319
00320 if(config.direction == 1)
00321 process(forward_table, frame, frame);
00322 else
00323 if(config.direction == 2)
00324 process(reverse_table, frame, frame);
00325
00326 return 0;
00327 }
00328
00329 int RGB601Main::handle_opengl()
00330 {
00331 #ifdef HAVE_GL
00332 static char *yuv_fwd_frag =
00333 "uniform sampler2D tex;\n"
00334 "void main()\n"
00335 "{\n"
00336 " gl_FragColor = texture2D(tex, gl_TexCoord[0].st);\n"
00337 " gl_FragColor.r = gl_FragColor.r * 0.8588 + 0.0627;\n"
00338 "}\n";
00339 static char *yuv_rev_frag =
00340 "uniform sampler2D tex;\n"
00341 "void main()\n"
00342 "{\n"
00343 " gl_FragColor = texture2D(tex, gl_TexCoord[0].st);\n"
00344 " gl_FragColor.r = gl_FragColor.r * 1.1644 - 0.0627;\n"
00345 "}\n";
00346 static char *rgb_fwd_frag =
00347 "uniform sampler2D tex;\n"
00348 "void main()\n"
00349 "{\n"
00350 " gl_FragColor = texture2D(tex, gl_TexCoord[0].st);\n"
00351 " gl_FragColor.rgb = gl_FragColor.rgb * vec3(0.8588, 0.8588, 0.8588) + vec3(0.0627, 0.0627, 0.0627);\n"
00352 "}\n";
00353 static char *rgb_rev_frag =
00354 "uniform sampler2D tex;\n"
00355 "void main()\n"
00356 "{\n"
00357 " gl_FragColor = texture2D(tex, gl_TexCoord[0].st);\n"
00358 " gl_FragColor.rgb = gl_FragColor.rgb * vec3(1.1644, 1.1644, 1.1644) - vec3(0.0627, 0.0627, 0.0627);\n"
00359 "}\n";
00360
00361
00362 get_output()->to_texture();
00363 get_output()->enable_opengl();
00364 get_output()->bind_texture(0);
00365
00366 unsigned int frag_shader = 0;
00367 switch(get_output()->get_color_model())
00368 {
00369 case BC_YUV888:
00370 case BC_YUVA8888:
00371 frag_shader = VFrame::make_shader(0,
00372 config.direction == 1 ? yuv_fwd_frag : yuv_rev_frag,
00373 0);
00374 break;
00375
00376 default:
00377 frag_shader = VFrame::make_shader(0,
00378 config.direction == 1 ? rgb_fwd_frag : rgb_rev_frag,
00379 0);
00380 break;
00381 }
00382
00383 if(frag_shader)
00384 {
00385 glUseProgram(frag_shader);
00386 glUniform1i(glGetUniformLocation(frag_shader, "tex"), 0);
00387 }
00388 VFrame::init_screen(get_output()->get_w(), get_output()->get_h());
00389 get_output()->draw_texture();
00390 glUseProgram(0);
00391 get_output()->set_opengl_state(VFrame::SCREEN);
00392 #endif
00393 }
00394
00395
00396