2 Copyright (C) 2006 Michael Niedermayer <michaelni@gmx.at>
\r
4 This program is free software; you can redistribute it and/or modify
\r
5 it under the terms of the GNU General Public License as published by
\r
6 the Free Software Foundation; either version 2 of the License, or
\r
7 (at your option) any later version.
\r
9 This program is distributed in the hope that it will be useful,
\r
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
\r
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
\r
12 GNU General Public License for more details.
\r
14 You should have received a copy of the GNU General Public License
\r
15 along with this program; if not, write to the Free Software
\r
16 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
\r
20 #include "ffmpeg/avcodec.h"
\r
21 #include "mpeg2dec/mpeg2.h"
\r
23 #define SUPPRESS_AV_LOG
\r
25 #define YADIF_MODE_DEFAULT -1
\r
26 #define YADIF_PARITY_DEFAULT -1
\r
28 #define MCDEINT_MODE_DEFAULT -1
\r
29 #define MCDEINT_QP_DEFAULT 1
\r
31 #define ABS(a) ((a) > 0 ? (a) : (-(a)))
\r
32 #define MIN3(a,b,c) MIN(MIN(a,b),c)
\r
33 #define MAX3(a,b,c) MAX(MAX(a,b),c)
\r
35 struct hb_filter_private_s
\r
45 uint8_t * yadif_ref[4][3];
\r
46 int yadif_ref_stride[3];
\r
51 int mcdeint_outbuf_size;
\r
52 uint8_t * mcdeint_outbuf;
\r
53 AVCodecContext * mcdeint_avctx_enc;
\r
54 AVFrame * mcdeint_frame;
\r
55 AVFrame * mcdeint_frame_dec;
\r
59 hb_buffer_t * buf_out[2];
\r
60 hb_buffer_t * buf_settings;
\r
63 hb_filter_private_t * hb_deinterlace_init( int pix_fmt,
\r
68 int hb_deinterlace_work( const hb_buffer_t * buf_in,
\r
69 hb_buffer_t ** buf_out,
\r
73 hb_filter_private_t * pv );
\r
75 void hb_deinterlace_close( hb_filter_private_t * pv );
\r
77 hb_filter_object_t hb_filter_deinterlace =
\r
80 "Deinterlace (ffmpeg or yadif/mcdeint)",
\r
82 hb_deinterlace_init,
\r
83 hb_deinterlace_work,
\r
84 hb_deinterlace_close,
\r
87 static void yadif_store_ref( const uint8_t ** pic,
\r
88 hb_filter_private_t * pv )
\r
90 memcpy( pv->yadif_ref[3],
\r
92 sizeof(uint8_t *)*3 );
\r
94 memmove( pv->yadif_ref[0],
\r
96 sizeof(uint8_t *)*3*3 );
\r
99 for( i = 0; i < 3; i++ )
\r
101 const uint8_t * src = pic[i];
\r
102 uint8_t * ref = pv->yadif_ref[2][i];
\r
104 int w = pv->width[i];
\r
105 int h = pv->height[i];
\r
106 int ref_stride = pv->yadif_ref_stride[i];
\r
109 for( y = 0; y < pv->height[i]; y++ )
\r
111 memcpy(ref, src, w);
\r
112 src = (uint8_t*)src + w;
\r
113 ref = (uint8_t*)ref + ref_stride;
\r
118 static void yadif_filter_line( uint8_t *dst,
\r
124 hb_filter_private_t * pv )
\r
126 uint8_t *prev2 = parity ? prev : cur ;
\r
127 uint8_t *next2 = parity ? cur : next;
\r
129 int w = pv->width[plane];
\r
130 int refs = pv->yadif_ref_stride[plane];
\r
133 for( x = 0; x < w; x++)
\r
135 int c = cur[-refs];
\r
136 int d = (prev2[0] + next2[0])>>1;
\r
137 int e = cur[+refs];
\r
138 int temporal_diff0 = ABS(prev2[0] - next2[0]);
\r
139 int temporal_diff1 = ( ABS(prev[-refs] - c) + ABS(prev[+refs] - e) ) >> 1;
\r
140 int temporal_diff2 = ( ABS(next[-refs] - c) + ABS(next[+refs] - e) ) >> 1;
\r
141 int diff = MAX3(temporal_diff0>>1, temporal_diff1, temporal_diff2);
\r
142 int spatial_pred = (c+e)>>1;
\r
143 int spatial_score = ABS(cur[-refs-1] - cur[+refs-1]) + ABS(c-e) +
\r
144 ABS(cur[-refs+1] - cur[+refs+1]) - 1;
\r
146 #define YADIF_CHECK(j)\
\r
147 { int score = ABS(cur[-refs-1+j] - cur[+refs-1-j])\
\r
148 + ABS(cur[-refs +j] - cur[+refs -j])\
\r
149 + ABS(cur[-refs+1+j] - cur[+refs+1-j]);\
\r
150 if( score < spatial_score ){\
\r
151 spatial_score = score;\
\r
152 spatial_pred = (cur[-refs +j] + cur[+refs -j])>>1;\
\r
154 YADIF_CHECK(-1) YADIF_CHECK(-2) }} }}
\r
155 YADIF_CHECK( 1) YADIF_CHECK( 2) }} }}
\r
157 if( pv->yadif_mode < 2 )
\r
159 int b = (prev2[-2*refs] + next2[-2*refs])>>1;
\r
160 int f = (prev2[+2*refs] + next2[+2*refs])>>1;
\r
162 int max = MAX3(d-e, d-c, MIN(b-c, f-e));
\r
163 int min = MIN3(d-e, d-c, MAX(b-c, f-e));
\r
165 diff = MAX3( diff, min, -max );
\r
168 if( spatial_pred > d + diff )
\r
170 spatial_pred = d + diff;
\r
172 else if( spatial_pred < d - diff )
\r
174 spatial_pred = d - diff;
\r
177 dst[0] = spatial_pred;
\r
188 static void yadif_filter( uint8_t ** dst,
\r
191 hb_filter_private_t * pv )
\r
194 for( i = 0; i < 3; i++ )
\r
196 int w = pv->width[i];
\r
197 int h = pv->height[i];
\r
198 int ref_stride = pv->yadif_ref_stride[i];
\r
201 for( y = 0; y < h; y++ )
\r
203 if( (y ^ parity) & 1 )
\r
205 uint8_t *prev = &pv->yadif_ref[0][i][y*ref_stride];
\r
206 uint8_t *cur = &pv->yadif_ref[1][i][y*ref_stride];
\r
207 uint8_t *next = &pv->yadif_ref[2][i][y*ref_stride];
\r
208 uint8_t *dst2 = &dst[i][y*w];
\r
210 yadif_filter_line( dst2, prev, cur, next, i, parity ^ tff, pv );
\r
214 memcpy( &dst[i][y*w],
\r
215 &pv->yadif_ref[1][i][y*ref_stride],
\r
216 w * sizeof(uint8_t) );
\r
222 static void mcdeint_filter( uint8_t ** dst,
\r
225 hb_filter_private_t * pv )
\r
230 #ifdef SUPPRESS_AV_LOG
\r
231 /* TODO: temporarily change log level to suppress obnoxious debug output */
\r
232 int loglevel = av_log_get_level();
\r
233 av_log_set_level( AV_LOG_QUIET );
\r
236 for( i=0; i<3; i++ )
\r
238 pv->mcdeint_frame->data[i] = src[i];
\r
239 pv->mcdeint_frame->linesize[i] = pv->width[i];
\r
241 pv->mcdeint_avctx_enc->me_cmp = FF_CMP_SAD;
\r
242 pv->mcdeint_avctx_enc->me_sub_cmp = FF_CMP_SAD;
\r
243 pv->mcdeint_frame->quality = pv->mcdeint_qp * FF_QP2LAMBDA;
\r
245 out_size = avcodec_encode_video( pv->mcdeint_avctx_enc,
\r
246 pv->mcdeint_outbuf,
\r
247 pv->mcdeint_outbuf_size,
\r
248 pv->mcdeint_frame );
\r
250 pv->mcdeint_frame_dec = pv->mcdeint_avctx_enc->coded_frame;
\r
252 for( i = 0; i < 3; i++ )
\r
254 int w = pv->width[i];
\r
255 int h = pv->height[i];
\r
256 int fils = pv->mcdeint_frame_dec->linesize[i];
\r
257 int srcs = pv->width[i];
\r
259 for( y = 0; y < h; y++ )
\r
261 if( (y ^ parity) & 1 )
\r
263 for( x = 0; x < w; x++ )
\r
265 if( (x-2)+(y-1)*w >= 0 && (x+2)+(y+1)*w < w*h )
\r
268 &pv->mcdeint_frame_dec->data[i][x + y*fils];
\r
269 uint8_t * srcp = &src[i][x + y*srcs];
\r
271 int diff0 = filp[-fils] - srcp[-srcs];
\r
272 int diff1 = filp[+fils] - srcp[+srcs];
\r
274 int spatial_score =
\r
275 ABS(srcp[-srcs-1] - srcp[+srcs-1])
\r
276 + ABS(srcp[-srcs ] - srcp[+srcs ])
\r
277 + ABS(srcp[-srcs+1] - srcp[+srcs+1]) - 1;
\r
279 int temp = filp[0];
\r
281 #define MCDEINT_CHECK(j)\
\r
282 { int score = ABS(srcp[-srcs-1+j] - srcp[+srcs-1-j])\
\r
283 + ABS(srcp[-srcs +j] - srcp[+srcs -j])\
\r
284 + ABS(srcp[-srcs+1+j] - srcp[+srcs+1-j]);\
\r
285 if( score < spatial_score ) {\
\r
286 spatial_score = score;\
\r
287 diff0 = filp[-fils+j] - srcp[-srcs+j];\
\r
288 diff1 = filp[+fils-j] - srcp[+srcs-j];
\r
290 MCDEINT_CHECK(-1) MCDEINT_CHECK(-2) }} }}
\r
291 MCDEINT_CHECK( 1) MCDEINT_CHECK( 2) }} }}
\r
293 if(diff0 + diff1 > 0)
\r
295 temp -= (diff0 + diff1 -
\r
296 ABS( ABS(diff0) - ABS(diff1) ) / 2) / 2;
\r
300 temp -= (diff0 + diff1 +
\r
301 ABS( ABS(diff0) - ABS(diff1) ) / 2) / 2;
\r
304 filp[0] = dst[i][x + y*w] =
\r
305 temp > 255U ? ~(temp>>31) : temp;
\r
310 pv->mcdeint_frame_dec->data[i][x + y*fils];
\r
316 for( y = 0; y < h; y++ )
\r
318 if( !((y ^ parity) & 1) )
\r
320 for( x = 0; x < w; x++ )
\r
322 pv->mcdeint_frame_dec->data[i][x + y*fils] =
\r
323 dst[i][x + y*w]= src[i][x + y*srcs];
\r
329 #ifdef SUPPRESS_AV_LOG
\r
330 /* TODO: restore previous log level */
\r
331 av_log_set_level(loglevel);
\r
335 hb_filter_private_t * hb_deinterlace_init( int pix_fmt,
\r
340 if( pix_fmt != PIX_FMT_YUV420P )
\r
345 hb_filter_private_t * pv = calloc( 1, sizeof(struct hb_filter_private_s) );
\r
347 pv->pix_fmt = pix_fmt;
\r
349 pv->width[0] = width;
\r
350 pv->height[0] = height;
\r
351 pv->width[1] = pv->width[2] = width >> 1;
\r
352 pv->height[1] = pv->height[2] = height >> 1;
\r
354 int buf_size = 3 * width * height / 2;
\r
355 pv->buf_out[0] = hb_buffer_init( buf_size );
\r
356 pv->buf_out[1] = hb_buffer_init( buf_size );
\r
357 pv->buf_settings = hb_buffer_init( 0 );
\r
359 pv->yadif_ready = 0;
\r
360 pv->yadif_mode = YADIF_MODE_DEFAULT;
\r
361 pv->yadif_parity = YADIF_PARITY_DEFAULT;
\r
363 pv->mcdeint_mode = MCDEINT_MODE_DEFAULT;
\r
364 pv->mcdeint_qp = MCDEINT_QP_DEFAULT;
\r
368 sscanf( settings, "%d:%d:%d:%d",
\r
375 /* Allocate yadif specific buffers */
\r
376 if( pv->yadif_mode >= 0 )
\r
379 for( i = 0; i < 3; i++ )
\r
381 int is_chroma = !!i;
\r
382 int w = ((width + 31) & (~31))>>is_chroma;
\r
383 int h = ((height+6+ 31) & (~31))>>is_chroma;
\r
385 pv->yadif_ref_stride[i] = w;
\r
387 for( j = 0; j < 3; j++ )
\r
389 pv->yadif_ref[j][i] = malloc( w*h*sizeof(uint8_t) ) + 3*w;
\r
394 /* Allocate mcdeint specific buffers */
\r
395 if( pv->mcdeint_mode >= 0 )
\r
398 avcodec_register_all();
\r
400 AVCodec * enc = avcodec_find_encoder( CODEC_ID_SNOW );
\r
403 for (i = 0; i < 3; i++ )
\r
405 AVCodecContext * avctx_enc;
\r
407 avctx_enc = pv->mcdeint_avctx_enc = avcodec_alloc_context();
\r
409 avctx_enc->width = width;
\r
410 avctx_enc->height = height;
\r
411 avctx_enc->time_base = (AVRational){1,25}; // meaningless
\r
412 avctx_enc->gop_size = 300;
\r
413 avctx_enc->max_b_frames = 0;
\r
414 avctx_enc->pix_fmt = PIX_FMT_YUV420P;
\r
415 avctx_enc->flags = CODEC_FLAG_QSCALE | CODEC_FLAG_LOW_DELAY;
\r
416 avctx_enc->strict_std_compliance = FF_COMPLIANCE_EXPERIMENTAL;
\r
417 avctx_enc->global_quality = 1;
\r
418 avctx_enc->flags2 = CODEC_FLAG2_MEMC_ONLY;
\r
419 avctx_enc->me_cmp = FF_CMP_SAD; //SSE;
\r
420 avctx_enc->me_sub_cmp = FF_CMP_SAD; //SSE;
\r
421 avctx_enc->mb_cmp = FF_CMP_SSE;
\r
423 switch( pv->mcdeint_mode )
\r
426 avctx_enc->refs = 3;
\r
428 avctx_enc->me_method = ME_UMH;
\r
430 avctx_enc->flags |= CODEC_FLAG_4MV;
\r
431 avctx_enc->dia_size =2;
\r
433 avctx_enc->flags |= CODEC_FLAG_QPEL;
\r
436 avcodec_open(avctx_enc, enc);
\r
439 pv->mcdeint_frame = avcodec_alloc_frame();
\r
440 pv->mcdeint_outbuf_size = width * height * 10;
\r
441 pv->mcdeint_outbuf = malloc( pv->mcdeint_outbuf_size );
\r
447 void hb_deinterlace_close( hb_filter_private_t * pv )
\r
454 /* Cleanup frame buffers */
\r
455 if( pv->buf_out[0] )
\r
457 hb_buffer_close( &pv->buf_out[0] );
\r
459 if( pv->buf_out[1] )
\r
461 hb_buffer_close( &pv->buf_out[1] );
\r
463 if (pv->buf_settings )
\r
465 hb_buffer_close( &pv->buf_settings );
\r
468 /* Cleanup yadif specific buffers */
\r
469 if( pv->yadif_mode >= 0 )
\r
472 for( i = 0; i<3*3; i++ )
\r
474 uint8_t **p = &pv->yadif_ref[i%3][i/3];
\r
477 free( *p - 3*pv->yadif_ref_stride[i/3] );
\r
483 /* Cleanup mcdeint specific buffers */
\r
484 if( pv->mcdeint_mode >= 0 )
\r
486 if( pv->mcdeint_avctx_enc )
\r
488 avcodec_close( pv->mcdeint_avctx_enc );
\r
489 av_freep( &pv->mcdeint_avctx_enc );
\r
491 if( pv->mcdeint_outbuf )
\r
493 free( pv->mcdeint_outbuf );
\r
500 int hb_deinterlace_work( const hb_buffer_t * buf_in,
\r
501 hb_buffer_t ** buf_out,
\r
505 hb_filter_private_t * pv )
\r
508 pix_fmt != pv->pix_fmt ||
\r
509 width != pv->width[0] ||
\r
510 height != pv->height[0] )
\r
512 return FILTER_FAILED;
\r
515 avpicture_fill( &pv->pic_in, buf_in->data,
\r
516 pix_fmt, width, height );
\r
518 /* Use libavcodec deinterlace if yadif_mode < 0 */
\r
519 if( pv->yadif_mode < 0 )
\r
521 avpicture_fill( &pv->pic_out, pv->buf_out[0]->data,
\r
522 pix_fmt, width, height );
\r
524 avpicture_deinterlace( &pv->pic_out, &pv->pic_in,
\r
525 pix_fmt, width, height );
\r
527 hb_buffer_copy_settings( pv->buf_out[0], buf_in );
\r
529 *buf_out = pv->buf_out[0];
\r
534 /* Determine if top-field first layout */
\r
536 if( pv->yadif_parity < 0 )
\r
538 tff = !!(buf_in->flags & PIC_FLAG_TOP_FIELD_FIRST);
\r
542 tff = (pv->yadif_parity & 1) ^ 1;
\r
545 /* Store current frame in yadif cache */
\r
546 yadif_store_ref( (const uint8_t**)pv->pic_in.data, pv );
\r
548 /* If yadif is not ready, store another ref and return FILTER_DELAY */
\r
549 if( pv->yadif_ready == 0 )
\r
551 yadif_store_ref( (const uint8_t**)pv->pic_in.data, pv );
\r
553 hb_buffer_copy_settings( pv->buf_settings, buf_in );
\r
555 pv->yadif_ready = 1;
\r
557 return FILTER_DELAY;
\r
560 /* Perform yadif and mcdeint filtering */
\r
562 for( frame = 0; frame <= (pv->yadif_mode & 1); frame++ )
\r
564 int parity = frame ^ tff ^ 1;
\r
566 avpicture_fill( &pv->pic_out, pv->buf_out[!(frame^1)]->data,
\r
567 pix_fmt, width, height );
\r
569 yadif_filter( pv->pic_out.data, parity, tff, pv );
\r
571 if( pv->mcdeint_mode >= 0 )
\r
573 avpicture_fill( &pv->pic_in, pv->buf_out[(frame^1)]->data,
\r
574 pix_fmt, width, height );
\r
576 mcdeint_filter( pv->pic_in.data, pv->pic_out.data, parity, pv );
\r
578 *buf_out = pv->buf_out[ (frame^1)];
\r
582 *buf_out = pv->buf_out[!(frame^1)];
\r
586 /* Copy buffered settings to output buffer settings */
\r
587 hb_buffer_copy_settings( *buf_out, pv->buf_settings );
\r
589 /* Replace buffered settings with input buffer settings */
\r
590 hb_buffer_copy_settings( pv->buf_settings, buf_in );
\r