12 REGISTER_PLUGIN(yuv411Main)
15 yuv411Config::yuv411Config()
20 void yuv411Config::reset()
30 void yuv411Config::copy_from(yuv411Config &that)
32 int_horizontal = that.int_horizontal;
33 avg_vertical = that.avg_vertical;
34 inpainting = that.inpainting;
40 int yuv411Config::equivalent(yuv411Config &that)
42 return int_horizontal == that.int_horizontal &&
43 avg_vertical == that.avg_vertical &&
44 inpainting == that.inpainting &&
45 offset == that.offset &&
46 thresh == that.thresh &&
50 void yuv411Config::interpolate(yuv411Config &prev,
56 this->int_horizontal = prev.int_horizontal;
57 this->avg_vertical = prev.avg_vertical;
58 this->inpainting = prev.inpainting;
59 this->offset = prev.offset;
60 this->thresh = prev.thresh;
61 this->bias = prev.bias;
65 yuv411Main::yuv411Main(PluginServer *server)
66 : PluginVClient(server)
68 this->server = server;
73 yuv411Main::~yuv411Main()
78 const char *yuv411Main::plugin_title() { return N_("YUV411"); }
79 int yuv411Main::is_realtime() { return 1; }
81 #define YUV411_MACRO(type, components) \
83 type **input_rows = ((type**)input_ptr->get_rows()), **in_rows = input_rows; \
84 type **output_rows = ((type**)output_ptr->get_rows()), **out_rows = output_rows; \
85 if( config.avg_vertical ) { \
86 if( config.int_horizontal ) \
87 in_rows = out_rows = ((type**)temp_frame->get_rows()); \
88 for( int i=0,h3=h-3; i<h3; i+=4 ) { \
89 type *in_row0 = input_rows[i+0], *in_row1 = input_rows[i+1]; \
90 type *in_row2 = input_rows[i+2], *in_row3 = input_rows[i+3]; \
91 type *out_row0 = out_rows[i+0], *out_row1 = out_rows[i+1]; \
92 type *out_row2 = out_rows[i+2], *out_row3 = out_rows[i+3]; \
93 for( int k = 0; k<w; ++k ) { \
94 for( int uv=1; uv<=2; ++uv ) { \
95 out_row0[uv] = out_row2[uv] = (in_row0[uv]+in_row2[uv]+1)/2; \
96 out_row1[uv] = out_row3[uv] = (in_row1[uv]+in_row3[uv]+1)/2; \
98 in_row0 += components; in_row1 += components; \
99 in_row2 += components; in_row3 += components; \
100 out_row0 += components; out_row1 += components; \
101 out_row2 += components; out_row3 += components; \
106 if( config.int_horizontal ) { \
107 if( config.inpainting ) { \
108 int kmax = w-7+config.offset; \
109 for( int i=0; i<h; ++i ) { \
110 type *in_row0 = in_rows[i+0], *out_row0 = output_rows[i+0]; \
111 for( int k=config.offset; k<kmax; k+=4 ) { \
112 int k0 = (k+0) * components, a = in_row0[k0]; \
113 int b, d = 0, k4 = (k+4) * components; \
114 for( int jk=k0,n=4; --n>=0; a=b ) { \
115 b = in_row0[jk+=components]; \
116 d += a<b ? b-a : a-b; d += config.bias; \
118 if( d < config.thresh ) { \
119 for( int jk=k0,n=4; --n>0; ) { \
121 for( int uv=1; uv<=2; ++uv ) { \
122 out_row0[jk+uv] = (n*in_row0[jk+uv] + (4-n)*in_row0[k4+uv]+2)/4; \
127 int t = 0; a = in_row0[k0]; \
128 for( int jk=k0,n=4; --n>0; a=b ) { \
129 b = in_row0[jk+=components]; \
130 t += a<b ? b-a : a-b; t += config.bias; \
131 for( int uv=1; uv<=2; ++uv ) { \
132 out_row0[jk+uv] = (2*((d-t)*in_row0[k0+uv] + t*in_row0[k4+uv])+d)/(2*d); \
140 int kmax = w-7+config.offset; \
141 for( int i=0; i<h; ++i ) { \
142 type *in_row0 = in_rows[i]; \
143 type *out_row0 = output_rows[i]; \
144 for( int k=config.offset; k<kmax; k+=4 ) { \
145 for( int uv=1; uv<=2; ++uv ) { \
146 int sum, avg, k0 = (k+0) * components, k4 = (k+4) * components; \
147 sum = in_row0[k0 + uv]; sum += in_row0[(k0+=components) + uv]; \
148 sum += in_row0[k4 + uv]; sum += in_row0[(k4+=components) + uv]; \
149 avg = (sum + 2) / 4; \
150 out_row0[(k0+=components)+uv] = avg; \
151 out_row0[(k0+=components)+uv] = avg; \
159 int yuv411Main::process_realtime(VFrame *input_ptr, VFrame *output_ptr)
161 load_configuration();
162 int w = input_ptr->get_w();
163 int h = input_ptr->get_h();
164 colormodel = input_ptr->get_color_model();
166 if( input_ptr == output_ptr ||
167 ( config.avg_vertical && config.int_horizontal ) ) {
168 if( temp_frame && (temp_frame->get_color_model() != colormodel ||
169 temp_frame->get_w() != w || temp_frame->get_h() != h) ) {
174 temp_frame = new VFrame(w, h, colormodel, 0);
175 if( input_ptr == output_ptr ) {
176 temp_frame->copy_from(input_ptr);
177 input_ptr = temp_frame;
181 switch( colormodel ) {
183 YUV411_MACRO(unsigned char, 3);
186 YUV411_MACRO(unsigned char, 4);
190 send_render_gui(this);
195 NEW_WINDOW_MACRO(yuv411Main, yuv411Window)
197 LOAD_CONFIGURATION_MACRO(yuv411Main, yuv411Config)
199 void yuv411Main::update_gui()
203 load_configuration();
204 thread->window->lock_window();
205 yuv411Window *window = (yuv411Window *)thread->window;
206 window->update_enables();
207 window->avg_vertical->update((int)config.avg_vertical);
208 window->int_horizontal->update((int)config.int_horizontal);
209 window->inpainting->update((int)config.inpainting);
210 window->offset->update((int)config.offset);
211 window->thresh->update((int)config.thresh);
212 window->bias->update((int)config.bias);
213 window->unlock_window();
217 void yuv411Main::render_gui(void *data)
220 yuv411Window *window = (yuv411Window *)thread->window;
221 yuv411Main *client = (yuv411Main *)data;
222 if( window->colormodel != client->colormodel ) {
224 switch( client->colormodel ) {
230 if( warn == window->yuv_warning->is_hidden() ) {
231 window->lock_window("yuv411Main::render_gui");
232 window->show_warning(warn);
233 window->colormodel = client->colormodel;
234 window->unlock_window();
240 void yuv411Main::save_data(KeyFrame *keyframe)
244 // cause data to be stored directly in text
245 output.set_shared_output(keyframe->xbuf);
247 output.tag.set_title("YUV411");
248 output.tag.set_property("OFFSET",config.offset);
249 output.tag.set_property("THRESH",config.thresh);
250 output.tag.set_property("BIAS",config.bias);
252 if(config.avg_vertical) {
253 output.tag.set_title("VERTICAL");
255 output.tag.set_title("/VERTICAL");
258 if(config.int_horizontal) {
259 output.tag.set_title("HORIZONTAL");
261 output.tag.set_title("/HORIZONTAL");
264 if(config.inpainting ) {
265 output.tag.set_title("INPAINTING");
267 output.tag.set_title("/INPAINTING");
270 output.tag.set_title("/YUV411");
272 output.terminate_string();
275 void yuv411Main::read_data(KeyFrame *keyframe)
279 input.set_shared_input(keyframe->xbuf);
282 config.avg_vertical = config.int_horizontal = 0;
283 config.inpainting = 0;
288 while(!(result = input.read_tag()) ) {
289 if( input.tag.title_is("YUV411") ) {
290 config.offset = input.tag.get_property("OFFSET",config.offset);
291 config.thresh = input.tag.get_property("THRESH",config.thresh);
292 config.bias = input.tag.get_property("BIAS",config.bias);
294 else if(input.tag.title_is("VERTICAL")) {
295 config.avg_vertical = 1;
297 else if(input.tag.title_is("HORIZONTAL")) {
298 config.int_horizontal = 1;
300 else if(input.tag.title_is("INPAINTING")) {
301 config.inpainting = 1;