1 /* decomb.c
2
3 Copyright (c) 2003-2021 HandBrake Team
4 This file is part of the HandBrake source code
5 Homepage: <http://handbrake.fr/>.
6 It may be used under the terms of the GNU General Public License v2.
7 For full terms see the file COPYING file or visit http://www.gnu.org/licenses/gpl-2.0.html
8
9 The yadif algorithm was created by Michael Niedermayer.
10 Tritical's work inspired much of the comb detection code:
11 http://web.missouri.edu/~kes25c/
12 */
13
14 /*****
15 Parameters:
16 Mode:
17 1 = yadif
18 2 = blend
19 4 = cubic interpolation
20 8 = EEDI2 interpolation
21 16 = Deinterlace each field to a separate frame
22 32 = Selectively deinterlace based on comb detection
23
24 Appended for EEDI2:
25 Magnitude thresh : Variance thresh : Laplacian thresh : Dilation thresh :
26 Erosion thresh : Noise thresh : Max search distance : Post-processing
27
28 Plus:
29 Parity
30
31 Defaults:
32 7:10:20:20:4:2:50:24:1:-1
33
34 *****/
35
36 /*****
37 These modes can be layered. For example, Yadif (1) + EEDI2 (8) = 9,
38 which will feed EEDI2 interpolations to yadif.
39
40 ** Working combos:
41 1: Just yadif
42 2: Just blend
43 3: Switch between yadif and blend
44 4: Just cubic interpolate
45 5: Cubic->yadif
46 6: Switch between cubic and blend
47 7: Switch between cubic->yadif and blend
48 8: Just EEDI2 interpolate
49 9: EEDI2->yadif
50 10: Switch between EEDI2 and blend
51 11: Switch between EEDI2->yadif and blend
52 ...okay I'm getting bored now listing all these different modes
53
54 12-15: EEDI2 will override cubic interpolation
55 *****/
56
57 #include "handbrake/handbrake.h"
58 #include "handbrake/hbffmpeg.h"
59 #include "handbrake/eedi2.h"
60 #include "handbrake/taskset.h"
61 #include "handbrake/decomb.h"
62
63 #define PARITY_DEFAULT -1
64
65 #define MIN3(a,b,c) MIN(MIN(a,b),c)
66 #define MAX3(a,b,c) MAX(MAX(a,b),c)
67
68 // Some names to correspond to the pv->eedi_half array's contents
69 #define SRCPF 0
70 #define MSKPF 1
71 #define TMPPF 2
72 #define DSTPF 3
73 // Some names to correspond to the pv->eedi_full array's contents
74 #define DST2PF 0
75 #define TMP2PF2 1
76 #define MSK2PF 2
77 #define TMP2PF 3
78 #define DST2MPF 4
79
80 struct yadif_arguments_s {
81 hb_buffer_t *dst;
82 int parity;
83 int tff;
84 int mode;
85 };
86
87 typedef struct yadif_arguments_s yadif_arguments_t;
88
89 typedef struct eedi2_thread_arg_s {
90 hb_filter_private_t *pv;
91 int plane;
92 } eedi2_thread_arg_t;
93
94 typedef struct yadif_thread_arg_s {
95 hb_filter_private_t *pv;
96 int segment;
97 int segment_start[3];
98 int segment_height[3];
99 } yadif_thread_arg_t;
100
101 struct hb_filter_private_s
102 {
103 // Decomb parameters
104 int mode;
105
106 /* Make buffers to store a comb masks. */
107 hb_buffer_t * mask;
108 hb_buffer_t * mask_filtered;
109 hb_buffer_t * mask_temp;
110 int mask_box_x;
111 int mask_box_y;
112 uint8_t mask_box_color;
113
114 // EEDI2 parameters
115 int magnitude_threshold;
116 int variance_threshold;
117 int laplacian_threshold;
118 int dilation_threshold;
119 int erosion_threshold;
120 int noise_threshold;
121 int maximum_search_distance;
122 int post_processing;
123
124 // Deinterlace parameters
125 int parity;
126 int tff;
127
128 int yadif_ready;
129
130 int deinterlaced;
131 int blended;
132 int unfiltered;
133 int frames;
134
135 hb_buffer_t * ref[3];
136
137 hb_buffer_t * eedi_half[4];
138 hb_buffer_t * eedi_full[5];
139 int * cx2;
140 int * cy2;
141 int * cxy;
142 int * tmpc;
143
144 int cpu_count;
145 int segment_height[3];
146
147 taskset_t yadif_taskset; // Threads for Yadif - one per CPU
148 yadif_arguments_t * yadif_arguments; // Arguments to thread for work
149
150 taskset_t eedi2_taskset; // Threads for eedi2 - one per plane
151
152 hb_buffer_list_t out_list;
153
154 hb_filter_init_t input;
155 hb_filter_init_t output;
156 };
157
158 typedef struct
159 {
160 int tap[5];
161 int normalize;
162 } filter_param_t;
163
164 static int hb_decomb_init( hb_filter_object_t * filter,
165 hb_filter_init_t * init );
166
167 static int hb_decomb_work( hb_filter_object_t * filter,
168 hb_buffer_t ** buf_in,
169 hb_buffer_t ** buf_out );
170
171 static void hb_decomb_close( hb_filter_object_t * filter );
172
173 static const char decomb_template[] =
174 "mode=^"HB_INT_REG"$:"
175 "magnitude-thresh=^"HB_INT_REG"$:variance-thresh=^"HB_INT_REG"$:"
176 "laplacian-thresh=^"HB_INT_REG"$:dilation-thresh=^"HB_INT_REG"$:"
177 "erosion-thresh=^"HB_INT_REG"$:noise-thresh=^"HB_INT_REG"$:"
178 "search-distance=^"HB_INT_REG"$:postproc=^([0-3])$:parity=^([01])$";
179
180 hb_filter_object_t hb_filter_decomb =
181 {
182 .id = HB_FILTER_DECOMB,
183 .enforce_order = 1,
184 .name = "Decomb",
185 .settings = NULL,
186 .init = hb_decomb_init,
187 .work = hb_decomb_work,
188 .close = hb_decomb_close,
189 .settings_template = decomb_template,
190 };
191
192 // Borrowed from libav
193 #define times4(x) x, x, x, x
194 #define times1024(x) times4(times4(times4(times4(times4(x)))))
195
196 static const uint8_t hb_crop_table[256 + 2 * 1024] = {
197 times1024(0x00),
198 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
199 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
200 0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,
201 0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x3A,0x3B,0x3C,0x3D,0x3E,0x3F,
202 0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4A,0x4B,0x4C,0x4D,0x4E,0x4F,
203 0x50,0x51,0x52,0x53,0x54,0x55,0x56,0x57,0x58,0x59,0x5A,0x5B,0x5C,0x5D,0x5E,0x5F,
204 0x60,0x61,0x62,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6A,0x6B,0x6C,0x6D,0x6E,0x6F,
205 0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7A,0x7B,0x7C,0x7D,0x7E,0x7F,
206 0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,
207 0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F,
208 0xA0,0xA1,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,
209 0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF,
210 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,
211 0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF,
212 0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF,
213 0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF,
214 times1024(0xFF)
215 };
216
cubic_interpolate_pixel(int y0,int y1,int y2,int y3)217 static inline int cubic_interpolate_pixel( int y0, int y1, int y2, int y3 )
218 {
219 /* From http://www.neuron2.net/library/cubicinterp.html */
220 int result = ( y0 * -3 ) + ( y1 * 23 ) + ( y2 * 23 ) + ( y3 * -3 );
221 result = hb_crop_table[(result / 40) + 1024];
222
223 return result;
224 }
225
cubic_interpolate_line(uint8_t * dst,uint8_t * cur,int width,int height,int stride,int y)226 static void cubic_interpolate_line(
227 uint8_t *dst,
228 uint8_t *cur,
229 int width,
230 int height,
231 int stride,
232 int y)
233 {
234 int w = width;
235 int x;
236
237 for( x = 0; x < w; x++)
238 {
239 int a, b, c, d;
240 a = b = c = d = 0;
241
242 if( y >= 3 )
243 {
244 /* Normal top*/
245 a = cur[-3*stride];
246 b = cur[-stride];
247 }
248 else if( y == 2 || y == 1 )
249 {
250 /* There's only one sample above this pixel, use it twice. */
251 a = cur[-stride];
252 b = cur[-stride];
253 }
254 else if( y == 0 )
255 {
256 /* No samples above, triple up on the one below. */
257 a = cur[+stride];
258 b = cur[+stride];
259 }
260
261 if( y <= ( height - 4 ) )
262 {
263 /* Normal bottom*/
264 c = cur[+stride];
265 d = cur[3*stride];
266 }
267 else if( y == ( height - 3 ) || y == ( height - 2 ) )
268 {
269 /* There's only one sample below, use it twice. */
270 c = cur[+stride];
271 d = cur[+stride];
272 }
273 else if( y == height - 1)
274 {
275 /* No samples below, triple up on the one above. */
276 c = cur[-stride];
277 d = cur[-stride];
278 }
279
280 dst[0] = cubic_interpolate_pixel( a, b, c, d );
281
282 dst++;
283 cur++;
284 }
285 }
286
store_ref(hb_filter_private_t * pv,hb_buffer_t * b)287 static void store_ref(hb_filter_private_t * pv, hb_buffer_t * b)
288 {
289 hb_buffer_close(&pv->ref[0]);
290 memmove(&pv->ref[0], &pv->ref[1], sizeof(hb_buffer_t *) * 2 );
291 pv->ref[2] = b;
292 }
293
blend_filter_pixel(filter_param_t * filter,int up2,int up1,int current,int down1,int down2)294 static inline int blend_filter_pixel(filter_param_t *filter, int up2, int up1, int current, int down1, int down2)
295 {
296 /* Low-pass 5-tap filter */
297 int result = 0;
298
299 result += up2 * filter->tap[0];
300 result += up1 * filter->tap[1];
301 result += current * filter->tap[2];
302 result += down1 * filter->tap[3];
303 result += down2 * filter->tap[4];
304 result >>= filter->normalize;
305
306 result = hb_crop_table[result + 1024];
307 return result;
308 }
309
blend_filter_line(filter_param_t * filter,uint8_t * dst,uint8_t * cur,int width,int height,int stride,int y)310 static void blend_filter_line(filter_param_t *filter,
311 uint8_t *dst,
312 uint8_t *cur,
313 int width,
314 int height,
315 int stride,
316 int y)
317 {
318 int w = width;
319 int x;
320 int up1, up2, down1, down2;
321
322 if (y > 1 && y < (height - 2))
323 {
324 up1 = -1 * stride;
325 up2 = -2 * stride;
326 down1 = 1 * stride;
327 down2 = 2 * stride;
328 }
329 else if (y == 0)
330 {
331 /* First line, so A and B don't exist.*/
332 up1 = up2 = 0;
333 down1 = 1 * stride;
334 down2 = 2 * stride;
335 }
336 else if (y == 1)
337 {
338 /* Second line, no A. */
339 up1 = up2 = -1 * stride;
340 down1 = 1 * stride;
341 down2 = 2 * stride;
342 }
343 else if (y == (height - 2))
344 {
345 /* Second to last line, no E. */
346 up1 = -1 * stride;
347 up2 = -2 * stride;
348 down1 = down2 = 1 * stride;
349 }
350 else if (y == (height -1))
351 {
352 /* Last line, no D or E. */
353 up1 = -1 * stride;
354 up2 = -2 * stride;
355 down1 = down2 = 0;
356 }
357 else
358 {
359 hb_error("Invalid value y %d height %d", y, height);
360 return;
361 }
362
363 for( x = 0; x < w; x++)
364 {
365 /* Low-pass 5-tap filter */
366 dst[0] = blend_filter_pixel(filter, cur[up2], cur[up1], cur[0],
367 cur[down1], cur[down2] );
368 dst++;
369 cur++;
370 }
371 }
372
373 // This function calls all the eedi2 filters in sequence for a given plane.
374 // It outputs the final interpolated image to pv->eedi_full[DST2PF].
eedi2_interpolate_plane(hb_filter_private_t * pv,int plane)375 static void eedi2_interpolate_plane( hb_filter_private_t * pv, int plane )
376 {
377 /* We need all these pointers. No, seriously.
378 I swear. It's not a joke. They're used.
379 All nine of them. */
380 uint8_t * mskp = pv->eedi_half[MSKPF]->plane[plane].data;
381 uint8_t * srcp = pv->eedi_half[SRCPF]->plane[plane].data;
382 uint8_t * tmpp = pv->eedi_half[TMPPF]->plane[plane].data;
383 uint8_t * dstp = pv->eedi_half[DSTPF]->plane[plane].data;
384 uint8_t * dst2p = pv->eedi_full[DST2PF]->plane[plane].data;
385 uint8_t * tmp2p2 = pv->eedi_full[TMP2PF2]->plane[plane].data;
386 uint8_t * msk2p = pv->eedi_full[MSK2PF]->plane[plane].data;
387 uint8_t * tmp2p = pv->eedi_full[TMP2PF]->plane[plane].data;
388 uint8_t * dst2mp = pv->eedi_full[DST2MPF]->plane[plane].data;
389 int * cx2 = pv->cx2;
390 int * cy2 = pv->cy2;
391 int * cxy = pv->cxy;
392 int * tmpc = pv->tmpc;
393
394 int pitch = pv->eedi_full[0]->plane[plane].stride;
395 int height = pv->eedi_full[0]->plane[plane].height;
396 int width = pv->eedi_full[0]->plane[plane].width;
397 int half_height = pv->eedi_half[0]->plane[plane].height;
398
399 // edge mask
400 eedi2_build_edge_mask( mskp, pitch, srcp, pitch,
401 pv->magnitude_threshold, pv->variance_threshold, pv->laplacian_threshold,
402 half_height, width );
403 eedi2_erode_edge_mask( mskp, pitch, tmpp, pitch, pv->erosion_threshold, half_height, width );
404 eedi2_dilate_edge_mask( tmpp, pitch, mskp, pitch, pv->dilation_threshold, half_height, width );
405 eedi2_erode_edge_mask( mskp, pitch, tmpp, pitch, pv->erosion_threshold, half_height, width );
406 eedi2_remove_small_gaps( tmpp, pitch, mskp, pitch, half_height, width );
407
408 // direction mask
409 eedi2_calc_directions( plane, mskp, pitch, srcp, pitch, tmpp, pitch,
410 pv->maximum_search_distance, pv->noise_threshold,
411 half_height, width );
412 eedi2_filter_dir_map( mskp, pitch, tmpp, pitch, dstp, pitch, half_height, width );
413 eedi2_expand_dir_map( mskp, pitch, dstp, pitch, tmpp, pitch, half_height, width );
414 eedi2_filter_map( mskp, pitch, tmpp, pitch, dstp, pitch, half_height, width );
415
416 // upscale 2x vertically
417 eedi2_upscale_by_2( srcp, dst2p, half_height, pitch );
418 eedi2_upscale_by_2( dstp, tmp2p2, half_height, pitch );
419 eedi2_upscale_by_2( mskp, msk2p, half_height, pitch );
420
421 // upscale the direction mask
422 eedi2_mark_directions_2x( msk2p, pitch, tmp2p2, pitch, tmp2p, pitch, pv->tff, height, width );
423 eedi2_filter_dir_map_2x( msk2p, pitch, tmp2p, pitch, dst2mp, pitch, pv->tff, height, width );
424 eedi2_expand_dir_map_2x( msk2p, pitch, dst2mp, pitch, tmp2p, pitch, pv->tff, height, width );
425 eedi2_fill_gaps_2x( msk2p, pitch, tmp2p, pitch, dst2mp, pitch, pv->tff, height, width );
426 eedi2_fill_gaps_2x( msk2p, pitch, dst2mp, pitch, tmp2p, pitch, pv->tff, height, width );
427
428 // interpolate a full-size plane
429 eedi2_interpolate_lattice( plane, tmp2p, pitch, dst2p, pitch, tmp2p2, pitch, pv->tff,
430 pv->noise_threshold, height, width );
431
432 if( pv->post_processing == 1 || pv->post_processing == 3 )
433 {
434 // make sure the edge directions are consistent
435 eedi2_bit_blit( tmp2p2, pitch, tmp2p, pitch, width, height );
436 eedi2_filter_dir_map_2x( msk2p, pitch, tmp2p, pitch, dst2mp, pitch, pv->tff, height, width );
437 eedi2_expand_dir_map_2x( msk2p, pitch, dst2mp, pitch, tmp2p, pitch, pv->tff, height, width );
438 eedi2_post_process( tmp2p, pitch, tmp2p2, pitch, dst2p, pitch, pv->tff, height, width );
439 }
440 if( pv->post_processing == 2 || pv->post_processing == 3 )
441 {
442 // filter junctions and corners
443 eedi2_gaussian_blur1( srcp, pitch, tmpp, pitch, srcp, pitch, half_height, width );
444 eedi2_calc_derivatives( srcp, pitch, half_height, width, cx2, cy2, cxy );
445 eedi2_gaussian_blur_sqrt2( cx2, tmpc, cx2, pitch, half_height, width);
446 eedi2_gaussian_blur_sqrt2( cy2, tmpc, cy2, pitch, half_height, width);
447 eedi2_gaussian_blur_sqrt2( cxy, tmpc, cxy, pitch, half_height, width);
448 eedi2_post_process_corner( cx2, cy2, cxy, pitch, tmp2p2, pitch, dst2p, pitch, height, width, pv->tff );
449 }
450 }
451
452 /*
453 * eedi2 interpolate this plane in a single thread.
454 */
eedi2_filter_thread(void * thread_args_v)455 static void eedi2_filter_thread( void *thread_args_v )
456 {
457 hb_filter_private_t * pv;
458 int plane;
459 eedi2_thread_arg_t *thread_args = thread_args_v;
460
461 pv = thread_args->pv;
462 plane = thread_args->plane;
463
464 hb_deep_log(3, "eedi2 thread started for plane %d", plane);
465
466 while (1)
467 {
468 /*
469 * Wait here until there is work to do.
470 */
471 taskset_thread_wait4start( &pv->eedi2_taskset, plane );
472
473 if( taskset_thread_stop( &pv->eedi2_taskset, plane ) )
474 {
475 /*
476 * No more work to do, exit this thread.
477 */
478 break;
479 }
480
481 /*
482 * Process plane
483 */
484 eedi2_interpolate_plane( pv, plane );
485
486 /*
487 * Finished this segment, let everyone know.
488 */
489 taskset_thread_complete( &pv->eedi2_taskset, plane );
490 }
491
492 taskset_thread_complete( &pv->eedi2_taskset, plane );
493 }
494
495 // Sets up the input field planes for EEDI2 in pv->eedi_half[SRCPF]
496 // and then runs eedi2_filter_thread for each plane.
eedi2_planer(hb_filter_private_t * pv)497 static void eedi2_planer( hb_filter_private_t * pv )
498 {
499 /* Copy the first field from the source to a half-height frame. */
500 int pp;
501 for( pp = 0; pp < 3; pp++ )
502 {
503 int pitch = pv->ref[1]->plane[pp].stride;
504 int height = pv->ref[1]->plane[pp].height;
505 int start_line = !pv->tff;
506
507 eedi2_fill_half_height_buffer_plane(
508 &pv->ref[1]->plane[pp].data[pitch * start_line],
509 pv->eedi_half[SRCPF]->plane[pp].data, pitch, height );
510 }
511
512 /*
513 * Now that all data is ready for our threads, fire them off
514 * and wait for their completion.
515 */
516 taskset_cycle( &pv->eedi2_taskset );
517 }
518
519 /* EDDI: Edge Directed Deinterlacing Interpolation
520 Checks 4 different slopes to see if there is more similarity along a diagonal
521 than there was vertically. If a diagonal is more similar, then it indicates
522 an edge, so interpolate along that instead of a vertical line, using either
523 linear or cubic interpolation depending on mode. */
524 #define YADIF_CHECK(j) {\
525 int score = ABS(cur[-stride-1+j] - cur[+stride-1-j])\
526 + ABS(cur[-stride +j] - cur[+stride -j])\
527 + ABS(cur[-stride+1+j] - cur[+stride+1-j]);\
528 if( score < spatial_score ){\
529 spatial_score = score;\
530 if( ( pv->mode & MODE_DECOMB_CUBIC ) && !vertical_edge )\
531 {\
532 switch(j)\
533 {\
534 case -1:\
535 spatial_pred = cubic_interpolate_pixel(cur[-3 * stride - 3], cur[-stride -1], cur[+stride + 1], cur[3* stride + 3] );\
536 break;\
537 case -2:\
538 spatial_pred = cubic_interpolate_pixel( ( ( cur[-3*stride - 4] + cur[-stride - 4] ) / 2 ) , cur[-stride -2], cur[+stride + 2], ( ( cur[3*stride + 4] + cur[stride + 4] ) / 2 ) );\
539 break;\
540 case 1:\
541 spatial_pred = cubic_interpolate_pixel(cur[-3 * stride +3], cur[-stride +1], cur[+stride - 1], cur[3* stride -3] );\
542 break;\
543 case 2:\
544 spatial_pred = cubic_interpolate_pixel(( ( cur[-3*stride + 4] + cur[-stride + 4] ) / 2 ), cur[-stride +2], cur[+stride - 2], ( ( cur[3*stride - 4] + cur[stride - 4] ) / 2 ) );\
545 break;\
546 }\
547 }\
548 else\
549 {\
550 spatial_pred = ( cur[-stride +j] + cur[+stride -j] ) >>1;\
551 }\
552
yadif_filter_line(hb_filter_private_t * pv,uint8_t * dst,uint8_t * prev,uint8_t * cur,uint8_t * next,int plane,int width,int height,int stride,int parity,int y)553 static void yadif_filter_line(
554 hb_filter_private_t * pv,
555 uint8_t * dst,
556 uint8_t * prev,
557 uint8_t * cur,
558 uint8_t * next,
559 int plane,
560 int width,
561 int height,
562 int stride,
563 int parity,
564 int y)
565 {
566 /* While prev and next point to the previous and next frames,
567 prev2 and next2 will shift depending on the parity, usually 1.
568 They are the previous and next fields, the fields temporally adjacent
569 to the other field in the current frame--the one not being filtered. */
570 uint8_t *prev2 = parity ? prev : cur ;
571 uint8_t *next2 = parity ? cur : next;
572
573 int x;
574 int eedi2_mode = ( pv->mode & MODE_DECOMB_EEDI2 );
575
576 /* We can replace spatial_pred with this interpolation*/
577 uint8_t * eedi2_guess = NULL;
578 if (eedi2_mode)
579 {
580 eedi2_guess = &pv->eedi_full[DST2PF]->plane[plane].data[y*stride];
581 }
582
583 /* Decomb's cubic interpolation can only function when there are
584 three samples above and below, so regress to yadif's traditional
585 two-tap interpolation when filtering at the top and bottom edges. */
586 int vertical_edge = 0;
587 if( ( y < 3 ) || ( y > ( height - 4 ) ) )
588 vertical_edge = 1;
589
590 for( x = 0; x < width; x++)
591 {
592 /* Pixel above*/
593 int c = cur[-stride];
594 /* Temporal average: the current location in the adjacent fields */
595 int d = (prev2[0] + next2[0])>>1;
596 /* Pixel below */
597 int e = cur[+stride];
598
599 /* How the current pixel changes between the adjacent fields */
600 int temporal_diff0 = ABS(prev2[0] - next2[0]);
601 /* The average of how much the pixels above and below change from the frame before to now. */
602 int temporal_diff1 = ( ABS(prev[-stride] - cur[-stride]) + ABS(prev[+stride] - cur[+stride]) ) >> 1;
603 /* The average of how much the pixels above and below change from now to the next frame. */
604 int temporal_diff2 = ( ABS(next[-stride] - cur[-stride]) + ABS(next[+stride] - cur[+stride]) ) >> 1;
605 /* For the actual difference, use the largest of the previous average diffs. */
606 int diff = MAX3(temporal_diff0>>1, temporal_diff1, temporal_diff2);
607
608 int spatial_pred;
609
610 if( eedi2_mode )
611 {
612 /* Who needs yadif's spatial predictions when we can have EEDI2's? */
613 spatial_pred = eedi2_guess[0];
614 eedi2_guess++;
615 }
616 else // Yadif spatial interpolation
617 {
618 /* SAD of how the pixel-1, the pixel, and the pixel+1 change from the line above to below. */
619 int spatial_score = ABS(cur[-stride-1] - cur[+stride-1]) + ABS(cur[-stride]-cur[+stride]) +
620 ABS(cur[-stride+1] - cur[+stride+1]) - 1;
621
622 /* Spatial pred is either a bilinear or cubic vertical interpolation. */
623 if( ( pv->mode & MODE_DECOMB_CUBIC ) && !vertical_edge)
624 {
625 spatial_pred = cubic_interpolate_pixel( cur[-3*stride], cur[-stride], cur[+stride], cur[3*stride] );
626 }
627 else
628 {
629 spatial_pred = (c+e)>>1;
630 }
631
632 // YADIF_CHECK requires a margin to avoid invalid memory access.
633 // In MODE_DECOMB_CUBIC, margin needed is 2 + ABS(param).
634 // Else, the margin needed is 1 + ABS(param).
635 int margin = 2;
636 if (pv->mode & MODE_DECOMB_CUBIC)
637 margin = 3;
638
639 if (x >= margin && x <= width - (margin + 1))
640 {
641 YADIF_CHECK(-1)
642 if (x >= margin + 1 && x <= width - (margin + 2))
643 YADIF_CHECK(-2) }} }}
644 }
645 if (x >= margin && x <= width - (margin + 1))
646 {
647 YADIF_CHECK(1)
648 if (x >= margin + 1 && x <= width - (margin + 2))
649 YADIF_CHECK(2) }} }}
650 }
651 }
652
653 /* Temporally adjust the spatial prediction by
654 comparing against lines in the adjacent fields. */
655 int b = (prev2[-2*stride] + next2[-2*stride])>>1;
656 int f = (prev2[+2*stride] + next2[+2*stride])>>1;
657
658 /* Find the median value */
659 int max = MAX3(d-e, d-c, MIN(b-c, f-e));
660 int min = MIN3(d-e, d-c, MAX(b-c, f-e));
661 diff = MAX3( diff, min, -max );
662
663 if( spatial_pred > d + diff )
664 {
665 spatial_pred = d + diff;
666 }
667 else if( spatial_pred < d - diff )
668 {
669 spatial_pred = d - diff;
670 }
671
672 dst[0] = spatial_pred;
673
674 dst++;
675 cur++;
676 prev++;
677 next++;
678 prev2++;
679 next2++;
680 }
681 }
682
683 /*
684 * deinterlace this segment of all three planes in a single thread.
685 */
686 static void yadif_decomb_filter_thread( void *thread_args_v )
687 {
688 yadif_arguments_t *yadif_work = NULL;
689 hb_filter_private_t * pv;
690 int segment, segment_start, segment_stop;
691 yadif_thread_arg_t *thread_args = thread_args_v;
692 filter_param_t filter;
693
694 filter.tap[0] = -1;
695 filter.tap[1] = 2;
696 filter.tap[2] = 6;
697 filter.tap[3] = 2;
698 filter.tap[4] = -1;
699 filter.normalize = 3;
700
701 pv = thread_args->pv;
702 segment = thread_args->segment;
703
704 hb_deep_log(3, "yadif thread started for segment %d", segment);
705
706 while (1)
707 {
708 /*
709 * Wait here until there is work to do.
710 */
711 taskset_thread_wait4start( &pv->yadif_taskset, segment );
712
713 if( taskset_thread_stop( &pv->yadif_taskset, segment ) )
714 {
715 /*
716 * No more work to do, exit this thread.
717 */
718 break;
719 }
720
721 yadif_work = &pv->yadif_arguments[segment];
722
723 /*
724 * Process all three planes, but only this segment of it.
725 */
726 hb_buffer_t *dst;
727 int parity, tff, mode;
728
729 mode = pv->yadif_arguments[segment].mode;
730 dst = yadif_work->dst;
731 tff = yadif_work->tff;
732 parity = yadif_work->parity;
733
734 int pp;
735 for (pp = 0; pp < 3; pp++)
736 {
737 int yy;
738 int width = dst->plane[pp].width;
739 int stride = dst->plane[pp].stride;
740 int height = dst->plane[pp].height_stride;
741 int penultimate = height - 2;
742
743 segment_start = thread_args->segment_start[pp];
744 segment_stop = segment_start + thread_args->segment_height[pp];
745
746 // Filter parity lines
747 int start = parity ? (segment_start + 1) & ~1 : segment_start | 1;
748 uint8_t *dst2 = &dst->plane[pp].data[start * stride];
749 uint8_t *prev = &pv->ref[0]->plane[pp].data[start * stride];
750 uint8_t *cur = &pv->ref[1]->plane[pp].data[start * stride];
751 uint8_t *next = &pv->ref[2]->plane[pp].data[start * stride];
752
753 if (mode == MODE_DECOMB_BLEND)
754 {
755 /* These will be useful if we ever do temporal blending. */
756 for( yy = start; yy < segment_stop; yy += 2 )
757 {
758 /* This line gets blend filtered, not yadif filtered. */
759 blend_filter_line(&filter, dst2, cur, width, height, stride, yy);
760 dst2 += stride * 2;
761 cur += stride * 2;
762 }
763 }
764 else if (mode == MODE_DECOMB_CUBIC)
765 {
766 for( yy = start; yy < segment_stop; yy += 2 )
767 {
768 /* Just apply vertical cubic interpolation */
769 cubic_interpolate_line(dst2, cur, width, height, stride, yy);
770 dst2 += stride * 2;
771 cur += stride * 2;
772 }
773 }
774 else if (mode & MODE_DECOMB_YADIF)
775 {
776 for( yy = start; yy < segment_stop; yy += 2 )
777 {
778 if( yy > 1 && yy < penultimate )
779 {
780 // This isn't the top or bottom,
781 // proceed as normal to yadif
782 yadif_filter_line(pv, dst2, prev, cur, next, pp,
783 width, height, stride,
784 parity ^ tff, yy);
785 }
786 else
787 {
788 // parity == 0 (TFF), y1 = y0
789 // parity == 1 (BFF), y0 = y1
790 // parity == 0 (TFF), yu = yp
791 // parity == 1 (BFF), yp = yu
792 int yp = (yy ^ parity) * stride;
793 memcpy(dst2, &pv->ref[1]->plane[pp].data[yp], width);
794 }
795 dst2 += stride * 2;
796 prev += stride * 2;
797 cur += stride * 2;
798 next += stride * 2;
799 }
800 }
801 else
802 {
803 // No combing, copy frame
804 for( yy = start; yy < segment_stop; yy += 2 )
805 {
806 memcpy(dst2, cur, width);
807 dst2 += stride * 2;
808 cur += stride * 2;
809 }
810 }
811
812 // Copy unfiltered lines
813 start = !parity ? (segment_start + 1) & ~1 : segment_start | 1;
814 dst2 = &dst->plane[pp].data[start * stride];
815 prev = &pv->ref[0]->plane[pp].data[start * stride];
816 cur = &pv->ref[1]->plane[pp].data[start * stride];
817 next = &pv->ref[2]->plane[pp].data[start * stride];
818 for( yy = start; yy < segment_stop; yy += 2 )
819 {
820 memcpy(dst2, cur, width);
821 dst2 += stride * 2;
822 cur += stride * 2;
823 }
824 }
825 taskset_thread_complete( &pv->yadif_taskset, segment );
826 }
827
828 /*
829 * Finished this segment, let everyone know.
830 */
831 taskset_thread_complete( &pv->yadif_taskset, segment );
832 }
833
834 static void yadif_filter( hb_filter_private_t * pv,
835 hb_buffer_t * dst,
836 int parity,
837 int tff)
838 {
839 /* If we're running comb detection, do it now, otherwise default to true. */
840 int is_combed = HB_COMB_HEAVY;
841 int mode = 0;
842
843 if (pv->mode & MODE_DECOMB_SELECTIVE)
844 {
845 is_combed = pv->ref[1]->s.combed;
846 }
847
848 // Pick a mode based on the comb detect state and selected decomb modes
849 if ((pv->mode & MODE_DECOMB_BLEND) && is_combed == HB_COMB_LIGHT )
850 {
851 mode = MODE_DECOMB_BLEND;
852 }
853 else if (is_combed != HB_COMB_NONE)
854 {
855 mode = pv->mode & ~MODE_DECOMB_SELECTIVE;
856 }
857
858 if (mode == MODE_DECOMB_BLEND)
859 {
860 pv->blended++;
861 }
862 else if (mode != 0)
863 {
864 pv->deinterlaced++;
865 }
866 else
867 {
868 pv->unfiltered++;
869 }
870 pv->frames++;
871
872 if (mode & MODE_DECOMB_EEDI2)
873 {
874 /* Generate an EEDI2 interpolation */
875 eedi2_planer( pv );
876 }
877
878 if (mode != 0)
879 {
880 if ((mode & MODE_DECOMB_EEDI2 ) && !(mode & MODE_DECOMB_YADIF))
881 {
882 // Just pass through the EEDI2 interpolation
883 int pp;
884 for( pp = 0; pp < 3; pp++ )
885 {
886 uint8_t * ref = pv->eedi_full[DST2PF]->plane[pp].data;
887 int ref_stride = pv->eedi_full[DST2PF]->plane[pp].stride;
888
889 uint8_t * dest = dst->plane[pp].data;
890 int width = dst->plane[pp].width;
891 int height = dst->plane[pp].height;
892 int stride = dst->plane[pp].stride;
893
894 int yy;
895 for( yy = 0; yy < height; yy++ )
896 {
897 memcpy(dest, ref, width);
898 dest += stride;
899 ref += ref_stride;
900 }
901 }
902 }
903 else
904 {
905 int segment;
906
907 for( segment = 0; segment < pv->cpu_count; segment++ )
908 {
909 /*
910 * Setup the work for this plane.
911 */
912 pv->yadif_arguments[segment].parity = parity;
913 pv->yadif_arguments[segment].tff = tff;
914 pv->yadif_arguments[segment].dst = dst;
915 pv->yadif_arguments[segment].mode = mode;
916 }
917
918 /*
919 * Allow the taskset threads to make one pass over the data.
920 */
921 taskset_cycle( &pv->yadif_taskset );
922
923 /*
924 * Entire frame is now deinterlaced.
925 */
926 }
927 }
928 else
929 {
930 /* Just passing through... */
931 pv->yadif_arguments[0].mode = mode; // 0
932 hb_buffer_copy(dst, pv->ref[1]);
933 }
934 }
935
936 static int hb_decomb_init( hb_filter_object_t * filter,
937 hb_filter_init_t * init )
938 {
939 filter->private_data = calloc( 1, sizeof(struct hb_filter_private_s) );
940 hb_filter_private_t * pv = filter->private_data;
941 pv->input = *init;
942 hb_buffer_list_clear(&pv->out_list);
943
944 pv->deinterlaced = 0;
945 pv->blended = 0;
946 pv->unfiltered = 0;
947 pv->frames = 0;
948 pv->yadif_ready = 0;
949
950 pv->mode = MODE_DECOMB_YADIF | MODE_DECOMB_BLEND |
951 MODE_DECOMB_CUBIC;
952 pv->magnitude_threshold = 10;
953 pv->variance_threshold = 20;
954 pv->laplacian_threshold = 20;
955 pv->dilation_threshold = 4;
956 pv->erosion_threshold = 2;
957 pv->noise_threshold = 50;
958 pv->maximum_search_distance = 24;
959 pv->post_processing = 1;
960 pv->parity = PARITY_DEFAULT;
961
962 if (filter->settings)
963 {
964 hb_value_t * dict = filter->settings;
965
966 // Get comb detection settings
967 hb_dict_extract_int(&pv->mode, dict, "mode");
968
969 // Get deinterlace settings
970 hb_dict_extract_int(&pv->parity, dict, "parity");
971 if (pv->mode & MODE_DECOMB_EEDI2)
972 {
973 hb_dict_extract_int(&pv->magnitude_threshold, dict,
974 "magnitude-thresh");
975 hb_dict_extract_int(&pv->variance_threshold, dict,
976 "variance-thresh");
977 hb_dict_extract_int(&pv->laplacian_threshold, dict,
978 "laplacian-thresh");
979 hb_dict_extract_int(&pv->dilation_threshold, dict,
980 "dilation-thresh");
981 hb_dict_extract_int(&pv->erosion_threshold, dict,
982 "erosion-thresh");
983 hb_dict_extract_int(&pv->noise_threshold, dict,
984 "noise-thresh");
985 hb_dict_extract_int(&pv->maximum_search_distance, dict,
986 "search-distance");
987 hb_dict_extract_int(&pv->post_processing, dict,
988 "postproc");
989 }
990 }
991
992 pv->cpu_count = hb_get_cpu_count();
993
994 // Make segment sizes an even number of lines
995 int height = hb_image_height(init->pix_fmt, init->geometry.height, 0);
996 // Each segment must begin on the even "parity" row.
997 // I.e. each segment of each plane must begin on an even row.
998 pv->segment_height[0] = (height / pv->cpu_count) & ~3;
999 pv->segment_height[1] = hb_image_height(init->pix_fmt, pv->segment_height[0], 1);
1000 pv->segment_height[2] = hb_image_height(init->pix_fmt, pv->segment_height[0], 2);
1001
1002 int ii;
1003 if( pv->mode & MODE_DECOMB_EEDI2 )
1004 {
1005 /* Allocate half-height eedi2 buffers */
1006 for( ii = 0; ii < 4; ii++ )
1007 {
1008 pv->eedi_half[ii] = hb_frame_buffer_init(
1009 init->pix_fmt, init->geometry.width, init->geometry.height / 2);
1010 }
1011
1012 /* Allocate full-height eedi2 buffers */
1013 for( ii = 0; ii < 5; ii++ )
1014 {
1015 pv->eedi_full[ii] = hb_frame_buffer_init(
1016 init->pix_fmt, init->geometry.width, init->geometry.height);
1017 }
1018 }
1019
1020 /*
1021 * Setup yadif taskset.
1022 */
1023 pv->yadif_arguments = malloc( sizeof( yadif_arguments_t ) * pv->cpu_count );
1024 if( pv->yadif_arguments == NULL ||
1025 taskset_init( &pv->yadif_taskset, pv->cpu_count,
1026 sizeof( yadif_thread_arg_t ) ) == 0 )
1027 {
1028 hb_error( "yadif could not initialize taskset" );
1029 }
1030
1031 yadif_thread_arg_t *yadif_prev_thread_args = NULL;
1032 for( ii = 0; ii < pv->cpu_count; ii++ )
1033 {
1034 yadif_thread_arg_t *thread_args;
1035
1036 thread_args = taskset_thread_args( &pv->yadif_taskset, ii );
1037 thread_args->pv = pv;
1038 thread_args->segment = ii;
1039
1040 int pp;
1041 for (pp = 0; pp < 3; pp++)
1042 {
1043 if (yadif_prev_thread_args != NULL)
1044 {
1045 thread_args->segment_start[pp] =
1046 yadif_prev_thread_args->segment_start[pp] +
1047 yadif_prev_thread_args->segment_height[pp];
1048 }
1049 if( ii == pv->cpu_count - 1 )
1050 {
1051 /*
1052 * Final segment
1053 */
1054 thread_args->segment_height[pp] =
1055 ((hb_image_height(init->pix_fmt, init->geometry.height, pp)
1056 + 3) & ~3) - thread_args->segment_start[pp];
1057 } else {
1058 thread_args->segment_height[pp] = pv->segment_height[pp];
1059 }
1060 }
1061 pv->yadif_arguments[ii].dst = NULL;
1062 if( taskset_thread_spawn( &pv->yadif_taskset, ii,
1063 "yadif_filter_segment",
1064 yadif_decomb_filter_thread,
1065 HB_NORMAL_PRIORITY ) == 0 )
1066 {
1067 hb_error( "yadif could not spawn thread" );
1068 }
1069 yadif_prev_thread_args = thread_args;
1070 }
1071
1072 if( pv->mode & MODE_DECOMB_EEDI2 )
1073 {
1074 /*
1075 * Create eedi2 taskset.
1076 */
1077 if( taskset_init( &pv->eedi2_taskset, /*thread_count*/3,
1078 sizeof( eedi2_thread_arg_t ) ) == 0 )
1079 {
1080 hb_error( "eedi2 could not initialize taskset" );
1081 }
1082
1083 if( pv->post_processing > 1 )
1084 {
1085 int stride;
1086 stride = hb_image_stride(init->pix_fmt, init->geometry.width, 0);
1087
1088 pv->cx2 = (int*)eedi2_aligned_malloc(
1089 init->geometry.height * stride * sizeof(int), 16);
1090
1091 pv->cy2 = (int*)eedi2_aligned_malloc(
1092 init->geometry.height * stride * sizeof(int), 16);
1093
1094 pv->cxy = (int*)eedi2_aligned_malloc(
1095 init->geometry.height * stride * sizeof(int), 16);
1096
1097 pv->tmpc = (int*)eedi2_aligned_malloc(
1098 init->geometry.height * stride * sizeof(int), 16);
1099
1100 if( !pv->cx2 || !pv->cy2 || !pv->cxy || !pv->tmpc )
1101 hb_error("EEDI2: failed to malloc derivative arrays");
1102 else
1103 hb_log("EEDI2: successfully malloced derivative arrays");
1104 }
1105
1106 for( ii = 0; ii < 3; ii++ )
1107 {
1108 eedi2_thread_arg_t *eedi2_thread_args;
1109
1110 eedi2_thread_args = taskset_thread_args( &pv->eedi2_taskset, ii );
1111
1112 eedi2_thread_args->pv = pv;
1113 eedi2_thread_args->plane = ii;
1114
1115 if( taskset_thread_spawn( &pv->eedi2_taskset, ii,
1116 "eedi2_filter_segment",
1117 eedi2_filter_thread,
1118 HB_NORMAL_PRIORITY ) == 0 )
1119 {
1120 hb_error( "eedi2 could not spawn thread" );
1121 }
1122 }
1123 }
1124
1125 pv->output = *init;
1126 init->job->use_decomb = 1;
1127
1128 return 0;
1129 }
1130
1131 static void hb_decomb_close( hb_filter_object_t * filter )
1132 {
1133 hb_filter_private_t * pv = filter->private_data;
1134
1135 if( !pv )
1136 {
1137 return;
1138 }
1139
1140 hb_log("decomb: deinterlaced %i | blended %i | unfiltered %i | total %i",
1141 pv->deinterlaced, pv->blended, pv->unfiltered, pv->frames);
1142
1143 taskset_fini( &pv->yadif_taskset );
1144
1145 if( pv->mode & MODE_DECOMB_EEDI2 )
1146 {
1147 taskset_fini( &pv->eedi2_taskset );
1148 }
1149
1150 /* Cleanup reference buffers. */
1151 int ii;
1152 for (ii = 0; ii < 3; ii++)
1153 {
1154 hb_buffer_close(&pv->ref[ii]);
1155 }
1156
1157 if( pv->mode & MODE_DECOMB_EEDI2 )
1158 {
1159 /* Cleanup eedi-half buffers */
1160 int ii;
1161 for( ii = 0; ii < 4; ii++ )
1162 {
1163 hb_buffer_close(&pv->eedi_half[ii]);
1164 }
1165
1166 /* Cleanup eedi-full buffers */
1167 for( ii = 0; ii < 5; ii++ )
1168 {
1169 hb_buffer_close(&pv->eedi_full[ii]);
1170 }
1171 }
1172
1173 if( pv->post_processing > 1 && ( pv->mode & MODE_DECOMB_EEDI2 ) )
1174 {
1175 if (pv->cx2) eedi2_aligned_free(pv->cx2);
1176 if (pv->cy2) eedi2_aligned_free(pv->cy2);
1177 if (pv->cxy) eedi2_aligned_free(pv->cxy);
1178 if (pv->tmpc) eedi2_aligned_free(pv->tmpc);
1179 }
1180
1181 /*
1182 * free memory for yadif structs
1183 */
1184 free( pv->yadif_arguments );
1185
1186 free( pv );
1187 filter->private_data = NULL;
1188 }
1189
1190 // Fill rows above height with copy of last row to prevent color distortion
1191 // during blending
1192 static void fill_stride(hb_buffer_t * buf)
1193 {
1194 int pp, ii;
1195
1196 for (pp = 0; pp < 3; pp++)
1197 {
1198 uint8_t * src, * dst;
1199
1200 src = buf->plane[pp].data + (buf->plane[pp].height - 1) *
1201 buf->plane[pp].stride;
1202 dst = buf->plane[pp].data + buf->plane[pp].height *
1203 buf->plane[pp].stride;
1204 for (ii = 0; ii < 3; ii++)
1205 {
1206 memcpy(dst, src, buf->plane[pp].stride);
1207 dst += buf->plane[pp].stride;
1208 }
1209 }
1210 }
1211
1212 static void process_frame( hb_filter_private_t * pv )
1213 {
1214 if ((pv->mode & MODE_DECOMB_SELECTIVE) &&
1215 pv->ref[1]->s.combed == HB_COMB_NONE)
1216 {
1217 // Input buffer is not combed. Just make a dup of it.
1218 hb_buffer_t * buf = hb_buffer_dup(pv->ref[1]);
1219 hb_buffer_list_append(&pv->out_list, buf);
1220 pv->frames++;
1221 pv->unfiltered++;
1222 }
1223 else
1224 {
1225 /* Determine if top-field first layout */
1226 int tff;
1227 if (pv->parity < 0)
1228 {
1229 tff = !!(pv->ref[1]->s.flags & PIC_FLAG_TOP_FIELD_FIRST);
1230 }
1231 else
1232 {
1233 tff = (pv->parity & 1) ^ 1;
1234 }
1235
1236 /* deinterlace both fields if bob */
1237 int frame, num_frames = 1;
1238 if (pv->mode & MODE_DECOMB_BOB)
1239 {
1240 num_frames = 2;
1241 }
1242
1243 // Will need up to 2 buffers simultaneously
1244
1245 /* Perform yadif filtering */
1246 for (frame = 0; frame < num_frames; frame++)
1247 {
1248 hb_buffer_t * buf;
1249 int parity = frame ^ tff ^ 1;
1250
1251 // tff for eedi2
1252 pv->tff = !parity;
1253
1254 buf = hb_frame_buffer_init(pv->ref[1]->f.fmt,
1255 pv->ref[1]->f.width,
1256 pv->ref[1]->f.height);
1257 buf->f.color_prim = pv->output.color_prim;
1258 buf->f.color_transfer = pv->output.color_transfer;
1259 buf->f.color_matrix = pv->output.color_matrix;
1260 buf->f.color_range = pv->output.color_range ;
1261 yadif_filter(pv, buf, parity, tff);
1262
1263 /* Copy buffered settings to output buffer settings */
1264 buf->s = pv->ref[1]->s;
1265
1266 hb_buffer_list_append(&pv->out_list, buf);
1267 }
1268
1269 /* if this frame was deinterlaced and bob mode is engaged, halve
1270 the duration of the saved timestamps. */
1271 if (pv->mode & MODE_DECOMB_BOB)
1272 {
1273 hb_buffer_t *first = hb_buffer_list_head(&pv->out_list);
1274 hb_buffer_t *second = hb_buffer_list_tail(&pv->out_list);
1275 first->s.stop -= (first->s.stop - first->s.start) / 2LL;
1276 second->s.start = first->s.stop;
1277 second->s.new_chap = 0;
1278 }
1279 }
1280 }
1281
1282 static int hb_decomb_work( hb_filter_object_t * filter,
1283 hb_buffer_t ** buf_in,
1284 hb_buffer_t ** buf_out )
1285 {
1286 hb_filter_private_t * pv = filter->private_data;
1287 hb_buffer_t * in = *buf_in;
1288
1289 // Input buffer is always consumed.
1290 *buf_in = NULL;
1291 if (in->s.flags & HB_BUF_FLAG_EOF)
1292 {
1293 if (pv->ref[2] != NULL)
1294 {
1295 // Duplicate last frame and process refs
1296 store_ref(pv, hb_buffer_dup(pv->ref[2]));
1297 process_frame(pv);
1298 }
1299 hb_buffer_list_append(&pv->out_list, in);
1300 *buf_out = hb_buffer_list_clear(&pv->out_list);
1301 return HB_FILTER_DONE;
1302 }
1303
1304 fill_stride(in);
1305
1306 // yadif requires 3 buffers, prev, cur, and next. For the first
1307 // frame, there can be no prev, so we duplicate the first frame.
1308 if (!pv->yadif_ready)
1309 {
1310 // If yadif is not ready, store another ref and return HB_FILTER_DELAY
1311 store_ref(pv, hb_buffer_dup(in));
1312 store_ref(pv, in);
1313 pv->yadif_ready = 1;
1314 // Wait for next
1315 return HB_FILTER_DELAY;
1316 }
1317
1318 store_ref(pv, in);
1319 process_frame(pv);
1320
1321 *buf_out = hb_buffer_list_clear(&pv->out_list);
1322 return HB_FILTER_OK;
1323 }
1324
1325 void hb_deinterlace(hb_buffer_t *dst, hb_buffer_t *src)
1326 {
1327 int pp;
1328 filter_param_t filter;
1329
1330 filter.tap[0] = -1;
1331 filter.tap[1] = 4;
1332 filter.tap[2] = 2;
1333 filter.tap[3] = 4;
1334 filter.tap[4] = -1;
1335 filter.normalize = 3;
1336
1337 fill_stride(src);
1338 for (pp = 0; pp < 3; pp++)
1339 {
1340 int yy;
1341 int width = src->plane[pp].width;
1342 int stride = src->plane[pp].stride;
1343 int height = src->plane[pp].height_stride;
1344
1345 // Filter parity lines
1346 uint8_t *pdst = &dst->plane[pp].data[0];
1347 uint8_t *psrc = &src->plane[pp].data[0];
1348
1349 /* These will be useful if we ever do temporal blending. */
1350 for( yy = 0; yy < height - 1; yy += 2 )
1351 {
1352 /* This line gets blend filtered, not yadif filtered. */
1353 memcpy(pdst, psrc, width);
1354 pdst += stride;
1355 psrc += stride;
1356 blend_filter_line(&filter, pdst, psrc, width, height, stride, yy + 1);
1357 pdst += stride;
1358 psrc += stride;
1359 }
1360 }
1361 }
1362
1363