diff options
author | jstebbins <[email protected]> | 2010-10-23 17:09:27 +0000 |
---|---|---|
committer | jstebbins <[email protected]> | 2010-10-23 17:09:27 +0000 |
commit | 07331bb1e1c3d237fd63579d82c82440a7380883 (patch) | |
tree | 268cea75cf6fa0afe6defaefa97765cbb35f0fdb /libhb | |
parent | a57e235b627a7f1609f3e967bc106b60d344dba2 (diff) |
ffmpeg video decoder enhancements
Add film/video cadence logging.
Set buffer flags indicating field order, progressive, and repeats.
Fix frame duration calculation when ffmpeg ticks_per_frame > 1
git-svn-id: svn://svn.handbrake.fr/HandBrake/trunk@3609 b64f7644-9d1e-0410-96f1-a4d463321fa5
Diffstat (limited to 'libhb')
-rw-r--r-- | libhb/decavcodec.c | 107 | ||||
-rw-r--r-- | libhb/internal.h | 11 |
2 files changed, 116 insertions, 2 deletions
diff --git a/libhb/decavcodec.c b/libhb/decavcodec.c index 019f595b1..cff6e43b2 100644 --- a/libhb/decavcodec.c +++ b/libhb/decavcodec.c @@ -111,6 +111,7 @@ struct hb_work_private_s struct SwsContext *sws_context; // if we have to rescale or convert color space hb_downmix_t *downmix; hb_sample_t *downmix_buffer; + int cadence[12]; hb_chan_map_t *out_map; }; @@ -578,6 +579,85 @@ static void flushDelayQueue( hb_work_private_t *pv ) } } +#define TOP_FIRST PIC_FLAG_TOP_FIELD_FIRST +#define PROGRESSIVE PIC_FLAG_PROGRESSIVE_FRAME +#define REPEAT_FIRST PIC_FLAG_REPEAT_FIRST_FIELD +#define TB 8 +#define BT 16 +#define BT_PROG 32 +#define BTB_PROG 64 +#define TB_PROG 128 +#define TBT_PROG 256 + +static void checkCadence( int * cadence, uint16_t flags, int64_t start ) +{ + /* Rotate the cadence tracking. */ + int i = 0; + for(i=11; i > 0; i--) + { + cadence[i] = cadence[i-1]; + } + + if ( !(flags & PROGRESSIVE) && !(flags & TOP_FIRST) ) + { + /* Not progressive, not top first... + That means it's probably bottom + first, 2 fields displayed. + */ + //hb_log("MPEG2 Flag: Bottom field first, 2 fields displayed."); + cadence[0] = BT; + } + else if ( !(flags & PROGRESSIVE) && (flags & TOP_FIRST) ) + { + /* Not progressive, top is first, + Two fields displayed. + */ + //hb_log("MPEG2 Flag: Top field first, 2 fields displayed."); + cadence[0] = TB; + } + else if ( (flags & PROGRESSIVE) && !(flags & TOP_FIRST) && !( flags & REPEAT_FIRST ) ) + { + /* Progressive, but noting else. + That means Bottom first, + 2 fields displayed. + */ + //hb_log("MPEG2 Flag: Progressive. Bottom field first, 2 fields displayed."); + cadence[0] = BT_PROG; + } + else if ( (flags & PROGRESSIVE) && !(flags & TOP_FIRST) && ( flags & REPEAT_FIRST ) ) + { + /* Progressive, and repeat. . + That means Bottom first, + 3 fields displayed. + */ + //hb_log("MPEG2 Flag: Progressive repeat. Bottom field first, 3 fields displayed."); + cadence[0] = BTB_PROG; + } + else if ( (flags & PROGRESSIVE) && (flags & TOP_FIRST) && !( flags & REPEAT_FIRST ) ) + { + /* Progressive, top first. + That means top first, + 2 fields displayed. + */ + //hb_log("MPEG2 Flag: Progressive. Top field first, 2 fields displayed."); + cadence[0] = TB_PROG; + } + else if ( (flags & PROGRESSIVE) && (flags & TOP_FIRST) && ( flags & REPEAT_FIRST ) ) + { + /* Progressive, top, repeat. + That means top first, + 3 fields displayed. + */ + //hb_log("MPEG2 Flag: Progressive repeat. Top field first, 3 fields displayed."); + cadence[0] = TBT_PROG; + } + + if ( (cadence[2] <= TB) && (cadence[1] <= TB) && (cadence[0] > TB) && (cadence[11]) ) + hb_log("%fs: Video -> Film", (float)start / 90000); + if ( (cadence[2] > TB) && (cadence[1] <= TB) && (cadence[0] <= TB) && (cadence[11]) ) + hb_log("%fs: Film -> Video", (float)start / 90000); +} + /* * Decodes a video frame from the specified raw packet data ('data', 'size', 'sequence'). * The output of this function is stored in 'pv->list', which contains a list @@ -616,6 +696,8 @@ static int decodeFrame( hb_work_private_t *pv, uint8_t *data, int size, int sequ } if( got_picture ) { + uint16_t flags = 0; + // ffmpeg makes it hard to attach a pts to a frame. if the MPEG ES // packet had a pts we handed it to av_parser_parse (if the packet had // no pts we set it to -1 but before the parse we can't distinguish between @@ -635,9 +717,13 @@ static int decodeFrame( hb_work_private_t *pv, uint8_t *data, int size, int sequ (double)pv->context->time_base.den; pv->duration = frame_dur; } + if ( pv->context->ticks_per_frame > 1 ) + { + frame_dur *= 2; + } if ( frame.repeat_pict ) { - frame_dur += frame.repeat_pict * frame_dur * 0.5; + frame_dur += frame.repeat_pict * pv->duration; } // XXX Unlike every other video decoder, the Raw decoder doesn't // use the standard buffer allocation routines so we never @@ -656,6 +742,19 @@ static int decodeFrame( hb_work_private_t *pv, uint8_t *data, int size, int sequ } pv->pts_next = pts + frame_dur; + if ( frame.top_field_first ) + { + flags |= PIC_FLAG_TOP_FIELD_FIRST; + } + if ( !frame.interlaced_frame ) + { + flags |= PIC_FLAG_PROGRESSIVE_FRAME; + } + if ( frame.repeat_pict ) + { + flags |= PIC_FLAG_REPEAT_FIRST_FIELD; + } + hb_buffer_t *buf; // if we're doing a scan or this content couldn't have been broken @@ -665,6 +764,7 @@ static int decodeFrame( hb_work_private_t *pv, uint8_t *data, int size, int sequ buf = copy_frame( pv, &frame ); buf->start = pts; buf->sequence = sequence; + buf->flags = flags; if ( pv->new_chap && buf->start >= pv->chap_time ) { buf->new_chap = pv->new_chap; @@ -676,6 +776,7 @@ static int decodeFrame( hb_work_private_t *pv, uint8_t *data, int size, int sequ { log_chapter( pv, pv->job->chapter_start, buf->start ); } + checkCadence( pv->cadence, buf->flags, buf->start ); hb_list_add( pv->list, buf ); ++pv->nframes; return got_picture; @@ -719,12 +820,14 @@ static int decodeFrame( hb_work_private_t *pv, uint8_t *data, int size, int sequ { log_chapter( pv, pv->job->chapter_start, buf->start ); } + checkCadence( pv->cadence, buf->flags, buf->start ); hb_list_add( pv->list, buf ); } // add the new frame to the delayq & push its timestamp on the heap buf = copy_frame( pv, &frame ); buf->sequence = sequence; + buf->flags = flags; pv->delayq[slot] = buf; heap_push( &pv->pts_heap, pts ); @@ -978,7 +1081,7 @@ static int decavcodecvInfo( hb_work_object_t *w, hb_work_info_t *info ) // field rate rather than frame rate so convert back to frames. info->rate_base *= context->ticks_per_frame; } - + info->pixel_aspect_width = context->sample_aspect_ratio.num; info->pixel_aspect_height = context->sample_aspect_ratio.den; diff --git a/libhb/internal.h b/libhb/internal.h index b6fbd1ddb..335c9a854 100644 --- a/libhb/internal.h +++ b/libhb/internal.h @@ -369,6 +369,17 @@ enum FILTER_ROTATE }; +// Picture flags used by filters +#ifndef PIC_FLAG_REPEAT_FIRST_FIELD +#define PIC_FLAG_REPEAT_FIRST_FIELD 256 +#endif +#ifndef PIC_FLAG_TOP_FIELD_FIRST +#define PIC_FLAG_TOP_FIELD_FIRST 8 +#endif +#ifndef PIC_FLAG_PROGRESSIVE_FRAME +#define PIC_FLAG_PROGRESSIVE_FRAME 16 +#endif + extern hb_work_object_t * hb_objects; #define HB_WORK_IDLE 0 |