3 * Copyright (C) 1997-2011 Adam Williams <broadcast at earthling dot net>
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
26 #include "interpolatevideo.h"
27 #include "motioncache-hv.h"
28 #include "motionscan-hv.h"
29 #include "opticflow.h"
37 OpticFlowMacroblock::OpticFlowMacroblock()
44 void OpticFlowMacroblock::copy_from(OpticFlowMacroblock *src)
50 this->is_valid = src->is_valid;
51 // Temporaries for blending macroblocks
52 this->angle1 = src->angle1;
53 this->angle2 = src->angle2;
54 this->dist = src->dist;
55 this->visible = src->visible;
64 OpticFlowPackage::OpticFlowPackage()
75 OpticFlowUnit::OpticFlowUnit(OpticFlow *server)
78 this->server = server;
82 OpticFlowUnit::~OpticFlowUnit()
87 void OpticFlowUnit::process_package(LoadPackage *package)
89 OpticFlowPackage *pkg = (OpticFlowPackage*)package;
90 InterpolateVideo *plugin = server->plugin;
91 //int w = plugin->frames[0]->get_w();
92 //int h = plugin->frames[0]->get_h();
93 struct timeval start_time;
94 gettimeofday(&start_time, 0);
96 if(!motion) motion = new MotionHVScan(1, 1);
98 motion->set_test_match(0);
99 motion->set_cache(server->downsample_cache);
101 // printf("OpticFlowUnit::process_package %d %d %d\n",
104 // pkg->macroblock1);
106 for(int i = pkg->macroblock0; i < pkg->macroblock1; i++)
108 OpticFlowMacroblock *mb = plugin->macroblocks.get(i);
109 //printf("OpticFlowUnit::process_package %d i=%d x=%d y=%d\n", __LINE__, i, mb->x, mb->y);
110 motion->scan_frame(plugin->frames[0],
111 // Frame after motion
113 plugin->config.search_radius,
114 plugin->config.search_radius,
115 plugin->config.macroblock_size,
116 plugin->config.macroblock_size,
119 MotionHVScan::TRACK_PREVIOUS,
120 MotionHVScan::CALCULATE,
121 // Get it to do the subpixel step
122 MotionHVScan::STABILIZE,
134 //printf("OpticFlowUnit::process_package 2\n", __LINE__);
137 mb->dx = motion->dx_result;
138 mb->dy = motion->dy_result;
139 // mb->is_valid = motion->result_valid;
143 struct timeval end_time;
144 gettimeofday(&end_time, 0);
145 // printf("OpticFlowUnit::process_package %d %d\n",
147 // end_time.tv_sec * 1000 + end_time.tv_usec / 1000 -
148 // start_time.tv_sec * 1000 - start_time.tv_usec / 1000);
156 OpticFlow::OpticFlow(InterpolateVideo *plugin,
161 : LoadServer(total_clients,
164 this->plugin = plugin;
165 downsample_cache = 0;
169 OpticFlow::~OpticFlow()
173 //printf("OpticFlow::~OpticFlow %d %p\n", __LINE__, downsample_cache);
174 delete downsample_cache;
178 void OpticFlow::init_packages()
180 if(!downsample_cache)
182 downsample_cache = new MotionHVCache();
185 downsample_cache->clear();
187 for(int i = 0; i < get_total_packages(); i++)
189 OpticFlowPackage *pkg = (OpticFlowPackage*)get_package(i);
190 pkg->macroblock0 = plugin->total_macroblocks * i / get_total_packages();
191 pkg->macroblock1 = plugin->total_macroblocks * (i + 1) / get_total_packages();
192 // printf("OpticFlow::init_packages %d %d %d %d %d\n",
194 // plugin->total_macroblocks,
195 // get_total_packages(),
197 // pkg->macroblock1);
201 LoadClient* OpticFlow::new_client()
203 return new OpticFlowUnit(this);
206 LoadPackage* OpticFlow::new_package()
208 return new OpticFlowPackage;
217 WarpPackage::WarpPackage()
228 WarpUnit::WarpUnit(Warp *server)
231 this->server = server;
234 WarpUnit::~WarpUnit()
239 #define AVERAGE2(type, components, max) \
241 type *prev0 = (type*)prev_rows[(int)prev_y0] + ((int)prev_x0) * components; \
242 type *prev1 = (type*)prev_rows[(int)prev_y0] + ((int)prev_x1) * components; \
243 type *prev2 = (type*)prev_rows[(int)prev_y1] + ((int)prev_x0) * components; \
244 type *prev3 = (type*)prev_rows[(int)prev_y1] + ((int)prev_x1) * components; \
248 type *next0 = (type*)next_rows[(int)next_y0] + ((int)next_x0) * components; \
249 type *next1 = (type*)next_rows[(int)next_y0] + ((int)next_x1) * components; \
250 type *next2 = (type*)next_rows[(int)next_y1] + ((int)next_x0) * components; \
251 type *next3 = (type*)next_rows[(int)next_y1] + ((int)next_x1) * components; \
255 type *out_row = (type*)out_rows[i] + j * components; \
257 for(int k = 0; k < components; k++) \
260 prev_alpha * (*prev0 * prev_fraction_x0 * prev_fraction_y0 + \
261 *prev1 * prev_fraction_x1 * prev_fraction_y0 + \
262 *prev2 * prev_fraction_x0 * prev_fraction_y1 + \
263 *prev3 * prev_fraction_x1 * prev_fraction_y1) + \
264 next_alpha * (*next0 * next_fraction_x0 * next_fraction_y0 + \
265 *next1 * next_fraction_x1 * next_fraction_y0 + \
266 *next2 * next_fraction_x0 * next_fraction_y1 + \
267 *next3 * next_fraction_x1 * next_fraction_y1); \
268 CLAMP(value, 0, max); \
269 *out_row++ = (type)value; \
282 void WarpUnit::process_package(LoadPackage *package)
284 WarpPackage *pkg = (WarpPackage*)package;
285 InterpolateVideo *plugin = server->plugin;
286 int w = plugin->frames[0]->get_w();
287 int h = plugin->frames[0]->get_h();
288 unsigned char **prev_rows = plugin->frames[0]->get_rows();
289 unsigned char **next_rows = plugin->frames[1]->get_rows();
290 unsigned char **out_rows = plugin->get_output()->get_rows();
291 int color_model = plugin->get_output()->get_color_model();
292 int macroblock_size = plugin->config.macroblock_size;
294 float lowest_fraction = plugin->lowest_fraction;
295 //float highest_fraction = 1.0 - lowest_fraction;
297 float prev_alpha = lowest_fraction;
298 float next_alpha = 1.0 - prev_alpha;
299 //printf("WarpUnit::process_package %d %p %d %d\n", __LINE__, this, pkg->y1, pkg->y2);
301 // Count all macroblocks as valid
302 for(int i = pkg->y1; i < pkg->y2; i++)
304 for(int j = 0; j < w; j++)
306 // Get the motion vector for each pixel, based on the nearest motion vectors
307 int x_macroblock = j / macroblock_size;
308 int y_macroblock = i / macroblock_size;
310 int x_macroblock2 = x_macroblock + 1;
311 int y_macroblock2 = y_macroblock + 1;
313 x_macroblock2 = MIN(x_macroblock2, plugin->x_macroblocks - 1);
314 y_macroblock2 = MIN(y_macroblock2, plugin->y_macroblocks - 1);
316 float x_fraction = (float)(j - x_macroblock * macroblock_size) / macroblock_size;
317 float y_fraction = (float)(i - y_macroblock * macroblock_size) / macroblock_size;
319 OpticFlowMacroblock *mb;
320 mb = plugin->macroblocks.get(
321 x_macroblock + y_macroblock * plugin->x_macroblocks);
323 float dx = (float)mb->dx * (1.0 - x_fraction) * (1.0 - y_fraction);
324 float dy = (float)mb->dy * (1.0 - x_fraction) * (1.0 - y_fraction);
326 mb = plugin->macroblocks.get(
327 x_macroblock2 + y_macroblock * plugin->x_macroblocks);
328 dx += (float)mb->dx * (x_fraction) * (1.0 - y_fraction);
329 dy += (float)mb->dy * (x_fraction) * (1.0 - y_fraction);
331 mb = plugin->macroblocks.get(
332 x_macroblock + y_macroblock2 * plugin->x_macroblocks);
333 dx += (float)mb->dx * (1.0 - x_fraction) * (y_fraction);
334 dy += (float)mb->dy * (1.0 - x_fraction) * (y_fraction);
336 mb = plugin->macroblocks.get(
337 x_macroblock2 + y_macroblock2 * plugin->x_macroblocks);
338 dx += (float)mb->dx * (x_fraction) * (y_fraction);
339 dy += (float)mb->dy * (x_fraction) * (y_fraction);
341 dx /= (float)OVERSAMPLE;
342 dy /= (float)OVERSAMPLE;
347 // 4 pixels from prev frame
348 float prev_x0 = (float)j + dx * (1.0 - lowest_fraction);
349 float prev_y0 = (float)i + dy * (1.0 - lowest_fraction);
350 float prev_x1 = prev_x0 + 1;
351 float prev_y1 = prev_y0 + 1;
352 float prev_fraction_x1 = prev_x0 - floor(prev_x0);
353 float prev_fraction_x0 = 1.0 - prev_fraction_x1;
354 float prev_fraction_y1 = prev_y0 - floor(prev_y0);
355 float prev_fraction_y0 = 1.0 - prev_fraction_y1;
358 // 4 pixels from next frame
359 float next_x0 = (float)j - dx * plugin->lowest_fraction;
360 float next_y0 = (float)i - dy * plugin->lowest_fraction;
361 float next_x1 = next_x0 + 1;
362 float next_y1 = next_y0 + 1;
363 float next_fraction_x1 = next_x0 - floor(next_x0);
364 float next_fraction_x0 = 1.0 - next_fraction_x1;
365 float next_fraction_y1 = next_y0 - floor(next_y0);
366 float next_fraction_y0 = 1.0 - next_fraction_y1;
369 CLAMP(prev_x0, 0, w - 1);
370 CLAMP(prev_y0, 0, h - 1);
371 CLAMP(prev_x1, 0, w - 1);
372 CLAMP(prev_y1, 0, h - 1);
374 CLAMP(next_x0, 0, w - 1);
375 CLAMP(next_y0, 0, h - 1);
376 CLAMP(next_x1, 0, w - 1);
377 CLAMP(next_y1, 0, h - 1);
379 //printf("WarpUnit::process_package %d\n", __LINE__);
384 AVERAGE2(float, 3, 1.0);
388 AVERAGE2(unsigned char, 3, 0xff);
391 AVERAGE2(float, 4, 1.0);
395 AVERAGE2(unsigned char, 4, 0xff);
398 //printf("WarpUnit::process_package %d\n", __LINE__);
408 Warp::Warp(InterpolateVideo *plugin,
411 : LoadServer(total_clients,
414 this->plugin = plugin;
422 void Warp::init_packages()
424 int out_h = plugin->frames[0]->get_h();
425 for(int i = 0; i < get_total_packages(); i++)
427 WarpPackage *pkg = (WarpPackage*)get_package(i);
428 pkg->y1 = out_h * i / get_total_packages();
429 pkg->y2 = out_h * (i + 1) / get_total_packages();
433 LoadClient* Warp::new_client()
435 return new WarpUnit(this);
438 LoadPackage* Warp::new_package()
440 return new WarpPackage;
450 BlendPackage::BlendPackage()
462 BlendMacroblockUnit::BlendMacroblockUnit(BlendMacroblock *server)
465 this->server = server;
468 BlendMacroblockUnit::~BlendMacroblockUnit()
472 void BlendMacroblockUnit::process_package(LoadPackage *package)
474 BlendPackage *pkg = (BlendPackage*)package;
475 InterpolateVideo *plugin = server->plugin;
477 for(int i = pkg->number0; i < pkg->number1; i++)
479 plugin->blend_macroblock(plugin->invalid_blocks.get(i));
492 BlendMacroblock::BlendMacroblock(InterpolateVideo *plugin,
495 : LoadServer(total_clients,
498 this->plugin = plugin;
502 BlendMacroblock::~BlendMacroblock()
506 void BlendMacroblock::init_packages()
508 for(int i = 0; i < get_total_packages(); i++)
510 BlendPackage *pkg = (BlendPackage*)get_package(i);
511 pkg->number0 = plugin->invalid_blocks.size() * i / get_total_packages();
512 pkg->number1 = plugin->invalid_blocks.size() * (i + 1) / get_total_packages();
518 LoadClient* BlendMacroblock::new_client()
520 return new BlendMacroblockUnit(this);
523 LoadPackage* BlendMacroblock::new_package()
525 return new BlendPackage;