12 REGISTER_PLUGIN(yuv411Main)
15 yuv411Config::yuv411Config()
25 void yuv411Config::copy_from(yuv411Config &that)
27 int_horizontal = that.int_horizontal;
28 avg_vertical = that.avg_vertical;
29 inpainting = that.inpainting;
35 int yuv411Config::equivalent(yuv411Config &that)
37 return int_horizontal == that.int_horizontal &&
38 avg_vertical == that.avg_vertical &&
39 inpainting == that.inpainting &&
40 offset == that.offset &&
41 thresh == that.thresh &&
45 void yuv411Config::interpolate(yuv411Config &prev,
51 this->int_horizontal = prev.int_horizontal;
52 this->avg_vertical = prev.avg_vertical;
53 this->inpainting = prev.inpainting;
54 this->offset = prev.offset;
55 this->thresh = prev.thresh;
56 this->bias = prev.bias;
60 yuv411Main::yuv411Main(PluginServer *server)
61 : PluginVClient(server)
63 this->server = server;
68 yuv411Main::~yuv411Main()
73 const char *yuv411Main::plugin_title() { return _("YUV411"); }
74 int yuv411Main::is_realtime() { return 1; }
76 #define YUV411_MACRO(type, components) \
78 type **input_rows = ((type**)input_ptr->get_rows()), **in_rows = input_rows; \
79 type **output_rows = ((type**)output_ptr->get_rows()), **out_rows = output_rows; \
80 if( config.avg_vertical ) { \
81 if( config.int_horizontal ) \
82 in_rows = out_rows = ((type**)temp_frame->get_rows()); \
83 for( int i=0,h3=h-3; i<h3; i+=4 ) { \
84 type *in_row0 = input_rows[i+0], *in_row1 = input_rows[i+1]; \
85 type *in_row2 = input_rows[i+2], *in_row3 = input_rows[i+3]; \
86 type *out_row0 = out_rows[i+0], *out_row1 = out_rows[i+1]; \
87 type *out_row2 = out_rows[i+2], *out_row3 = out_rows[i+3]; \
88 for( int k = 0; k<w; ++k ) { \
89 for( int uv=1; uv<=2; ++uv ) { \
90 out_row0[uv] = out_row2[uv] = (in_row0[uv]+in_row2[uv]+1)/2; \
91 out_row1[uv] = out_row3[uv] = (in_row1[uv]+in_row3[uv]+1)/2; \
93 in_row0 += components; in_row1 += components; \
94 in_row2 += components; in_row3 += components; \
95 out_row0 += components; out_row1 += components; \
96 out_row2 += components; out_row3 += components; \
101 if( config.int_horizontal ) { \
102 if( config.inpainting ) { \
103 int kmax = w-7+config.offset; \
104 for( int i=0; i<h; ++i ) { \
105 type *in_row0 = in_rows[i+0], *out_row0 = output_rows[i+0]; \
106 for( int k=config.offset; k<kmax; k+=4 ) { \
107 int k0 = (k+0) * components, a = in_row0[k0]; \
108 int b, d = 0, k4 = (k+4) * components; \
109 for( int jk=k0,n=4; --n>=0; a=b ) { \
110 b = in_row0[jk+=components]; \
111 d += a<b ? b-a : a-b; d += config.bias; \
113 if( d < config.thresh ) { \
114 for( int jk=k0,n=4; --n>0; ) { \
116 for( int uv=1; uv<=2; ++uv ) { \
117 out_row0[jk+uv] = (n*in_row0[jk+uv] + (4-n)*in_row0[k4+uv]+2)/4; \
122 int t = 0; a = in_row0[k0]; \
123 for( int jk=k0,n=4; --n>0; a=b ) { \
124 b = in_row0[jk+=components]; \
125 t += a<b ? b-a : a-b; t += config.bias; \
126 for( int uv=1; uv<=2; ++uv ) { \
127 out_row0[jk+uv] = (2*((d-t)*in_row0[k0+uv] + t*in_row0[k4+uv])+d)/(2*d); \
135 int kmax = w-7+config.offset; \
136 for( int i=0; i<h; ++i ) { \
137 type *in_row0 = in_rows[i]; \
138 type *out_row0 = output_rows[i]; \
139 for( int k=config.offset; k<kmax; k+=4 ) { \
140 for( int uv=1; uv<=2; ++uv ) { \
141 int sum, avg, k0 = (k+0) * components, k4 = (k+4) * components; \
142 sum = in_row0[k0 + uv]; sum += in_row0[(k0+=components) + uv]; \
143 sum += in_row0[k4 + uv]; sum += in_row0[(k4+=components) + uv]; \
144 avg = (sum + 2) / 4; \
145 out_row0[(k0+=components)+uv] = avg; \
146 out_row0[(k0+=components)+uv] = avg; \
154 int yuv411Main::process_realtime(VFrame *input_ptr, VFrame *output_ptr)
156 load_configuration();
157 int w = input_ptr->get_w();
158 int h = input_ptr->get_h();
159 int colormodel = input_ptr->get_color_model();
161 if( input_ptr == output_ptr ||
162 ( config.avg_vertical && config.int_horizontal ) ) {
163 if( temp_frame && (temp_frame->get_color_model() != colormodel ||
164 temp_frame->get_w() != w || temp_frame->get_h() != h) ) {
169 temp_frame = new VFrame(w, h, colormodel);
170 if( input_ptr == output_ptr ) {
171 temp_frame->copy_from(input_ptr);
172 input_ptr = temp_frame;
176 switch( colormodel ) {
178 YUV411_MACRO(unsigned char, 3);
181 YUV411_MACRO(unsigned char, 4);
185 if( this->colormodel != colormodel ) {
186 this->colormodel = colormodel;
187 send_render_gui(this);
194 NEW_WINDOW_MACRO(yuv411Main, yuv411Window)
196 LOAD_CONFIGURATION_MACRO(yuv411Main, yuv411Config)
198 void yuv411Main::update_gui()
202 load_configuration();
203 thread->window->lock_window();
204 yuv411Window *window = (yuv411Window *)thread->window;
205 window->update_enables();
206 window->avg_vertical->update((int)config.avg_vertical);
207 window->int_horizontal->update((int)config.int_horizontal);
208 window->inpainting->update((int)config.inpainting);
209 window->offset->update((int)config.offset);
210 window->thresh->update((int)config.thresh);
211 window->bias->update((int)config.bias);
212 window->unlock_window();
216 void yuv411Main::render_gui(void *data)
219 thread->window->lock_window();
220 yuv411Window *window = (yuv411Window *)thread->window;
221 yuv411Main *client = (yuv411Main *)data;
222 switch( client->colormodel ) {
225 window->show_warning(0);
228 window->show_warning(1);
231 window->unlock_window();
235 void yuv411Main::save_data(KeyFrame *keyframe)
239 // cause data to be stored directly in text
240 output.set_shared_output(keyframe->get_data(), MESSAGESIZE);
242 output.tag.set_title("YUV411");
243 output.tag.set_property("OFFSET",config.offset);
244 output.tag.set_property("THRESH",config.thresh);
245 output.tag.set_property("BIAS",config.bias);
247 if(config.avg_vertical) {
248 output.tag.set_title("VERTICAL");
250 output.tag.set_title("/VERTICAL");
253 if(config.int_horizontal) {
254 output.tag.set_title("HORIZONTAL");
256 output.tag.set_title("/HORIZONTAL");
259 if(config.inpainting ) {
260 output.tag.set_title("INPAINTING");
262 output.tag.set_title("/INPAINTING");
265 output.tag.set_title("/YUV411");
267 output.terminate_string();
270 void yuv411Main::read_data(KeyFrame *keyframe)
274 input.set_shared_input(keyframe->get_data(), strlen(keyframe->get_data()));
277 config.avg_vertical = config.int_horizontal = 0;
278 config.inpainting = 0;
283 while(!(result = input.read_tag()) ) {
284 if( input.tag.title_is("YUV411") ) {
285 config.offset = input.tag.get_property("OFFSET",config.offset);
286 config.thresh = input.tag.get_property("THRESH",config.thresh);
287 config.bias = input.tag.get_property("BIAS",config.bias);
289 else if(input.tag.title_is("VERTICAL")) {
290 config.avg_vertical = 1;
292 else if(input.tag.title_is("HORIZONTAL")) {
293 config.int_horizontal = 1;
295 else if(input.tag.title_is("INPAINTING")) {
296 config.inpainting = 1;