WinGui: Fix another instance of the Caliburn vs Json.net sillyness where objects...
[HandBrake.git] / libhb / deinterlace.c
blob0e8de8d8e986452537be5a0c223870e61a4b6478
1 /*
2 Copyright (C) 2006 Michael Niedermayer <michaelni@gmx.at>
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 #include "hb.h"
20 #include "hbffmpeg.h"
21 #include "taskset.h"
23 // yadif_mode is a bit vector with the following flags
24 #define MODE_YADIF_ENABLE 1
25 #define MODE_YADIF_SPATIAL 2
26 #define MODE_YADIF_2PASS 4
27 #define MODE_YADIF_BOB 8
29 #define YADIF_MODE_DEFAULT 0
30 #define YADIF_PARITY_DEFAULT -1
32 #define ABS(a) ((a) > 0 ? (a) : (-(a)))
33 #define MIN3(a,b,c) MIN(MIN(a,b),c)
34 #define MAX3(a,b,c) MAX(MAX(a,b),c)
36 typedef struct yadif_arguments_s {
37 hb_buffer_t * dst;
38 int parity;
39 int tff;
40 } yadif_arguments_t;
42 typedef struct deint_arguments_s {
43 hb_buffer_t * src;
44 hb_buffer_t * dst;
45 } deint_arguments_t;
47 typedef struct deint_thread_arg_s {
48 hb_filter_private_t *pv;
49 int segment;
50 } deint_thread_arg_t;
52 struct hb_filter_private_s
54 int width;
55 int height;
57 int yadif_mode;
58 int yadif_parity;
59 int yadif_ready;
61 hb_buffer_t * yadif_ref[3];
63 int cpu_count;
64 int segments;
66 int deint_nsegs;
68 taskset_t deint_taskset; // Threads for fast deint
69 taskset_t yadif_taskset; // Threads for Yadif
71 deint_arguments_t *deint_arguments; // Arguments to thread for work
72 yadif_arguments_t *yadif_arguments; // Arguments to thread for work
75 static int hb_deinterlace_init( hb_filter_object_t * filter,
76 hb_filter_init_t * init );
78 static int hb_deinterlace_work( hb_filter_object_t * filter,
79 hb_buffer_t ** buf_in,
80 hb_buffer_t ** buf_out );
82 static void hb_deinterlace_close( hb_filter_object_t * filter );
84 hb_filter_object_t hb_filter_deinterlace =
86 .id = HB_FILTER_DEINTERLACE,
87 .enforce_order = 1,
88 .name = "Deinterlace",
89 .settings = NULL,
90 .init = hb_deinterlace_init,
91 .work = hb_deinterlace_work,
92 .close = hb_deinterlace_close,
96 static void yadif_store_ref(hb_filter_private_t *pv, hb_buffer_t *b)
99 hb_buffer_close(&pv->yadif_ref[0]);
100 memmove(&pv->yadif_ref[0], &pv->yadif_ref[1], sizeof(hb_buffer_t *) * 2 );
101 pv->yadif_ref[2] = b;
104 static void yadif_filter_line(
105 hb_filter_private_t * pv,
106 uint8_t * dst,
107 uint8_t * prev,
108 uint8_t * cur,
109 uint8_t * next,
110 int width,
111 int stride,
112 int parity)
114 uint8_t *prev2 = parity ? prev : cur ;
115 uint8_t *next2 = parity ? cur : next;
117 int x;
118 for( x = 0; x < width; x++)
120 int c = cur[-stride];
121 int d = (prev2[0] + next2[0])>>1;
122 int e = cur[+stride];
123 int temporal_diff0 = ABS(prev2[0] - next2[0]);
124 int temporal_diff1 = ( ABS(prev[-stride] - c) + ABS(prev[+stride] - e) ) >> 1;
125 int temporal_diff2 = ( ABS(next[-stride] - c) + ABS(next[+stride] - e) ) >> 1;
126 int diff = MAX3(temporal_diff0>>1, temporal_diff1, temporal_diff2);
127 int spatial_pred = (c+e)>>1;
128 int spatial_score = ABS(cur[-stride-1] - cur[+stride-1]) + ABS(c-e) +
129 ABS(cur[-stride+1] - cur[+stride+1]) - 1;
131 #define YADIF_CHECK(j)\
132 { int score = ABS(cur[-stride-1+j] - cur[+stride-1-j])\
133 + ABS(cur[-stride +j] - cur[+stride -j])\
134 + ABS(cur[-stride+1+j] - cur[+stride+1-j]);\
135 if( score < spatial_score ){\
136 spatial_score = score;\
137 spatial_pred = (cur[-stride +j] + cur[+stride -j])>>1;\
139 YADIF_CHECK(-1) YADIF_CHECK(-2) }} }}
140 YADIF_CHECK( 1) YADIF_CHECK( 2) }} }}
142 if( pv->yadif_mode & MODE_YADIF_SPATIAL )
144 int b = (prev2[-2*stride] + next2[-2*stride])>>1;
145 int f = (prev2[+2*stride] + next2[+2*stride])>>1;
147 int max = MAX3(d-e, d-c, MIN(b-c, f-e));
148 int min = MIN3(d-e, d-c, MAX(b-c, f-e));
150 diff = MAX3( diff, min, -max );
153 if( spatial_pred > d + diff )
155 spatial_pred = d + diff;
157 else if( spatial_pred < d - diff )
159 spatial_pred = d - diff;
162 dst[0] = spatial_pred;
164 dst++;
165 cur++;
166 prev++;
167 next++;
168 prev2++;
169 next2++;
173 typedef struct yadif_thread_arg_s {
174 hb_filter_private_t *pv;
175 int segment;
176 } yadif_thread_arg_t;
179 * deinterlace this segment of all three planes in a single thread.
181 void yadif_filter_thread( void *thread_args_v )
183 yadif_arguments_t *yadif_work = NULL;
184 hb_filter_private_t * pv;
185 int run = 1;
186 int segment, segment_start, segment_stop;
187 yadif_thread_arg_t *thread_args = thread_args_v;
189 pv = thread_args->pv;
190 segment = thread_args->segment;
192 hb_log("Yadif Deinterlace thread started for segment %d", segment);
194 while( run )
197 * Wait here until there is work to do.
199 taskset_thread_wait4start( &pv->yadif_taskset, segment );
202 if( taskset_thread_stop( &pv->yadif_taskset, segment ) )
205 * No more work to do, exit this thread.
207 run = 0;
208 goto report_completion;
211 yadif_work = &pv->yadif_arguments[segment];
213 if( yadif_work->dst == NULL )
215 hb_error( "Thread started when no work available" );
216 goto report_completion;
220 * Process all three planes, but only this segment of it.
222 int pp;
223 for(pp = 0; pp < 3; pp++)
225 hb_buffer_t *dst = yadif_work->dst;
226 int w = dst->plane[pp].width;
227 int s = dst->plane[pp].stride;
228 int h = dst->plane[pp].height;
229 int yy;
230 int parity = yadif_work->parity;
231 int tff = yadif_work->tff;
232 int penultimate = h - 2;
234 int segment_height = (h / pv->segments) & ~1;
235 segment_start = segment_height * segment;
236 if( segment == pv->segments - 1 )
239 * Final segment
241 segment_stop = h;
242 } else {
243 segment_stop = segment_height * ( segment + 1 );
246 uint8_t *dst2 = &dst->plane[pp].data[segment_start * s];
247 uint8_t *prev = &pv->yadif_ref[0]->plane[pp].data[segment_start * s];
248 uint8_t *cur = &pv->yadif_ref[1]->plane[pp].data[segment_start * s];
249 uint8_t *next = &pv->yadif_ref[2]->plane[pp].data[segment_start * s];
250 for( yy = segment_start; yy < segment_stop; yy++ )
252 if(((yy ^ parity) & 1))
254 /* This is the bottom field when TFF and vice-versa.
255 It's the field that gets filtered. Because yadif
256 needs 2 lines above and below the one being filtered,
257 we need to mirror the edges. When TFF, this means
258 replacing the 2nd line with a copy of the 1st,
259 and the last with the second-to-last. */
260 if( yy > 1 && yy < penultimate )
262 /* This isn't the top or bottom,
263 * proceed as normal to yadif. */
264 yadif_filter_line(pv, dst2, prev, cur, next, w, s,
265 parity ^ tff);
267 else
269 // parity == 0 (TFF), y1 = y0
270 // parity == 1 (BFF), y0 = y1
271 // parity == 0 (TFF), yu = yp
272 // parity == 1 (BFF), yp = yu
273 uint8_t *src = &pv->yadif_ref[1]->plane[pp].data[(yy^parity)*s];
274 memcpy(dst2, src, w);
277 else
279 /* Preserve this field unfiltered */
280 memcpy(dst2, cur, w);
282 dst2 += s;
283 prev += s;
284 cur += s;
285 next += s;
289 report_completion:
291 * Finished this segment, let everyone know.
293 taskset_thread_complete( &pv->yadif_taskset, segment );
299 * threaded yadif - each thread deinterlaces a single segment of all
300 * three planes. Where a segment is defined as the frame divided by
301 * the number of CPUs.
303 * This function blocks until the frame is deinterlaced.
305 static void yadif_filter( hb_filter_private_t * pv,
306 hb_buffer_t * dst, int parity, int tff)
309 int segment;
311 for( segment = 0; segment < pv->segments; segment++ )
314 * Setup the work for this plane.
316 pv->yadif_arguments[segment].parity = parity;
317 pv->yadif_arguments[segment].tff = tff;
318 pv->yadif_arguments[segment].dst = dst;
321 /* Allow the taskset threads to make one pass over the data. */
322 taskset_cycle( &pv->yadif_taskset );
325 * Entire frame is now deinterlaced.
330 * deinterlace a frame in a single thread.
332 void deint_filter_thread( void *thread_args_v )
334 deint_arguments_t *args = NULL;
335 hb_filter_private_t * pv;
336 int run = 1;
337 int segment;
338 deint_thread_arg_t *thread_args = thread_args_v;
340 pv = thread_args->pv;
341 segment = thread_args->segment;
343 hb_log("Fast Deinterlace thread started for segment %d", segment);
345 while( run )
348 * Wait here until there is work to do.
350 taskset_thread_wait4start( &pv->deint_taskset, segment );
353 if( taskset_thread_stop( &pv->deint_taskset, segment ) )
356 * No more work to do, exit this thread.
358 run = 0;
359 goto report_completion;
362 args = &pv->deint_arguments[segment];
364 if( args->dst == NULL )
366 // This can happen when flushing final buffers.
367 goto report_completion;
371 * Process all three planes, but only this segment of it.
373 hb_deinterlace(args->dst, args->src);
375 report_completion:
377 * Finished this segment, let everyone know.
379 taskset_thread_complete( &pv->deint_taskset, segment );
384 * threaded fast deint - each thread deinterlaces a single frame.
386 * This function blocks until all frames are deinterlaced.
388 static hb_buffer_t * deint_fast(hb_filter_private_t * pv, hb_buffer_t * in)
391 int ii;
392 hb_buffer_t *dst, *src;
394 if (in != NULL)
396 dst = hb_frame_buffer_init(in->f.fmt, in->f.width, in->f.height);
397 pv->deint_arguments[pv->deint_nsegs].src = in;
398 pv->deint_arguments[pv->deint_nsegs].dst = dst;
399 pv->deint_nsegs++;
401 if (in != NULL && pv->deint_nsegs < pv->segments)
403 return NULL;
406 if (pv->deint_nsegs > 0)
408 /* Allow the taskset threads to make one pass over the data. */
409 taskset_cycle( &pv->deint_taskset );
412 hb_buffer_t *first = NULL, *last = NULL;
413 for (ii = 0; ii < pv->deint_nsegs; ii++)
415 src = pv->deint_arguments[ii].src;
416 dst = pv->deint_arguments[ii].dst;
417 pv->deint_arguments[ii].src = NULL;
418 pv->deint_arguments[ii].dst = NULL;
419 if (first == NULL)
421 first = dst;
423 if (last != NULL)
425 last->next = dst;
427 last = dst;
429 dst->s = src->s;
430 hb_buffer_move_subs(dst, src);
431 hb_buffer_close(&src);
433 if (in == NULL)
435 // Flushing final buffers. Append EOS marker buffer.
436 dst = hb_buffer_eof_init();
437 if (first == NULL)
439 first = dst;
441 else
443 last->next = dst;
446 pv->deint_nsegs = 0;
448 return first;
451 static int hb_deinterlace_init( hb_filter_object_t * filter,
452 hb_filter_init_t * init )
454 filter->private_data = calloc( 1, sizeof(struct hb_filter_private_s) );
455 hb_filter_private_t * pv = filter->private_data;
457 pv->width = init->geometry.width;
458 pv->height = init->geometry.height;
460 pv->yadif_ready = 0;
461 pv->yadif_mode = YADIF_MODE_DEFAULT;
462 pv->yadif_parity = YADIF_PARITY_DEFAULT;
464 if( filter->settings )
466 sscanf( filter->settings, "%d:%d",
467 &pv->yadif_mode,
468 &pv->yadif_parity);
471 pv->cpu_count = hb_get_cpu_count();
473 /* Allocate yadif specific buffers */
474 if( pv->yadif_mode & MODE_YADIF_ENABLE )
477 * Setup yadif taskset.
479 pv->segments = pv->cpu_count;
480 pv->yadif_arguments = malloc( sizeof( yadif_arguments_t ) * pv->segments );
481 if( pv->yadif_arguments == NULL ||
482 taskset_init( &pv->yadif_taskset, /*thread_count*/pv->segments,
483 sizeof( yadif_thread_arg_t ) ) == 0 )
485 hb_error( "yadif could not initialize taskset" );
488 int ii;
489 for( ii = 0; ii < pv->segments; ii++ )
491 yadif_thread_arg_t *thread_args;
493 thread_args = taskset_thread_args( &pv->yadif_taskset, ii );
495 thread_args->pv = pv;
496 thread_args->segment = ii;
497 pv->yadif_arguments[ii].dst = NULL;
499 if( taskset_thread_spawn( &pv->yadif_taskset, ii,
500 "yadif_filter_segment",
501 yadif_filter_thread,
502 HB_NORMAL_PRIORITY ) == 0 )
504 hb_error( "yadif could not spawn thread" );
508 else
511 * Setup fast deint taskset.
513 pv->segments = pv->cpu_count;
514 pv->deint_arguments = malloc( sizeof( deint_arguments_t ) * pv->segments );
515 if( pv->deint_arguments == NULL ||
516 taskset_init( &pv->deint_taskset, pv->segments,
517 sizeof( deint_thread_arg_t ) ) == 0 )
519 hb_error( "deint could not initialize taskset" );
522 int ii;
523 for( ii = 0; ii < pv->segments; ii++ )
525 deint_thread_arg_t *thread_args;
527 thread_args = taskset_thread_args( &pv->deint_taskset, ii );
529 thread_args->pv = pv;
530 thread_args->segment = ii;
531 pv->deint_arguments[ii].dst = NULL;
533 if( taskset_thread_spawn( &pv->deint_taskset, ii,
534 "deint_filter_segment",
535 deint_filter_thread,
536 HB_NORMAL_PRIORITY ) == 0 )
538 hb_error( "deint could not spawn thread" );
543 return 0;
546 static void hb_deinterlace_close( hb_filter_object_t * filter )
548 hb_filter_private_t * pv = filter->private_data;
550 if( !pv )
552 return;
555 /* Cleanup yadif specific buffers */
556 if( pv->yadif_mode & MODE_YADIF_ENABLE )
558 taskset_fini( &pv->yadif_taskset );
560 int ii;
561 for(ii = 0; ii < 3; ii++)
563 hb_buffer_close(&pv->yadif_ref[ii]);
566 free( pv->yadif_arguments );
568 else
570 taskset_fini( &pv->deint_taskset );
571 free( pv->deint_arguments );
574 free( pv );
575 filter->private_data = NULL;
578 static int hb_deinterlace_work( hb_filter_object_t * filter,
579 hb_buffer_t ** buf_in,
580 hb_buffer_t ** buf_out )
582 hb_filter_private_t * pv = filter->private_data;
583 hb_buffer_t * in = *buf_in;
584 hb_buffer_t * last = NULL, * out = NULL;
586 if (in->s.flags & HB_BUF_FLAG_EOF)
588 *buf_out = in;
589 *buf_in = NULL;
590 if( !( pv->yadif_mode & MODE_YADIF_ENABLE ) )
592 // Flush final frames
593 *buf_out = deint_fast(pv, NULL);
595 return HB_FILTER_DONE;
598 /* Use libavcodec deinterlace if yadif_mode < 0 */
599 if( !( pv->yadif_mode & MODE_YADIF_ENABLE ) )
601 *buf_in = NULL;
602 *buf_out = deint_fast(pv, in);
603 return HB_FILTER_OK;
606 /* Store current frame in yadif cache */
607 *buf_in = NULL;
608 yadif_store_ref(pv, in);
610 // yadif requires 3 buffers, prev, cur, and next. For the first
611 // frame, there can be no prev, so we duplicate the first frame.
612 if (!pv->yadif_ready)
614 // If yadif is not ready, store another ref and return HB_FILTER_DELAY
615 yadif_store_ref(pv, hb_buffer_dup(in));
616 pv->yadif_ready = 1;
617 // Wait for next
618 return HB_FILTER_DELAY;
621 /* Determine if top-field first layout */
622 int tff;
623 if( pv->yadif_parity < 0 )
625 tff = !!(in->s.flags & PIC_FLAG_TOP_FIELD_FIRST);
627 else
629 tff = (pv->yadif_parity & 1) ^ 1;
632 /* deinterlace both fields if yadif 2 pass or bob */
633 int frame, num_frames = 1;
634 if ((pv->yadif_mode & MODE_YADIF_2PASS) ||
635 (pv->yadif_mode & MODE_YADIF_BOB))
637 num_frames = 2;
640 // Will need up to 2 buffers simultaneously
641 int idx = 0;
642 hb_buffer_t * o_buf[2] = {NULL,};
644 /* Perform yadif filtering */
645 for( frame = 0; frame < num_frames; frame++ )
647 int parity = frame ^ tff ^ 1;
649 if (o_buf[idx] == NULL)
651 o_buf[idx] = hb_frame_buffer_init(in->f.fmt, in->f.width, in->f.height);
653 yadif_filter(pv, o_buf[idx], parity, tff);
655 // If bob, add both frames
656 // else, add only final frame
657 if (( pv->yadif_mode & MODE_YADIF_BOB ) || frame == num_frames - 1)
659 if ( out == NULL )
661 last = out = o_buf[idx];
663 else
665 last->next = o_buf[idx];
666 last = last->next;
668 last->next = NULL;
670 // Indicate that buffer was consumed
671 o_buf[idx] = NULL;
673 /* Copy buffered settings to output buffer settings */
674 last->s = pv->yadif_ref[1]->s;
675 idx ^= 1;
679 // Copy subs only to first output buffer
680 hb_buffer_move_subs( out, pv->yadif_ref[1] );
682 hb_buffer_close(&o_buf[0]);
683 hb_buffer_close(&o_buf[1]);
685 /* if bob mode is engaged, halve the duration of the
686 * timestamps. */
687 if (pv->yadif_mode & MODE_YADIF_BOB)
689 out->s.stop -= (out->s.stop - out->s.start) / 2LL;
690 last->s.start = out->s.stop;
691 last->s.new_chap = 0;
694 *buf_out = out;
696 return HB_FILTER_OK;