Commit 0d802ac5 authored by John Stebbins's avatar John Stebbins Committed by Ronald S. Bultje

vc1: fix VC-1 Pulldown handling.

Pulldown flags are being set incorrectly and AVFrame->repeat_pict is not
being set.  Also, skipped frames exit header parsing too early and do not
set pulldown flags appropriately. Ticks_per_frame needs to be set and
time_base adjusted so player can extend frame duration by a field time.

This fixes problems encountered when attempting to transcode HD-DVD EVOB
files with HandBrake. Also makes these files play smoothly in avplay.
Signed-off-by: 's avatarRonald S. Bultje <rsbultje@gmail.com>
parent 1cf82cab
...@@ -501,6 +501,10 @@ static int decode_sequence_header_adv(VC1Context *v, GetBitContext *gb) ...@@ -501,6 +501,10 @@ static int decode_sequence_header_adv(VC1Context *v, GetBitContext *gb)
v->s.avctx->time_base.den = ff_vc1_fps_nr[nr - 1] * 1000; v->s.avctx->time_base.den = ff_vc1_fps_nr[nr - 1] * 1000;
} }
} }
if(v->broadcast) { // Pulldown may be present
v->s.avctx->time_base.den *= 2;
v->s.avctx->ticks_per_frame = 2;
}
} }
if(get_bits1(gb)){ if(get_bits1(gb)){
...@@ -818,7 +822,7 @@ int vc1_parse_frame_header_adv(VC1Context *v, GetBitContext* gb) ...@@ -818,7 +822,7 @@ int vc1_parse_frame_header_adv(VC1Context *v, GetBitContext* gb)
case 4: case 4:
v->s.pict_type = AV_PICTURE_TYPE_P; // skipped pic v->s.pict_type = AV_PICTURE_TYPE_P; // skipped pic
v->p_frame_skipped = 1; v->p_frame_skipped = 1;
return 0; break;
} }
if(v->tfcntrflag) if(v->tfcntrflag)
skip_bits(gb, 8); skip_bits(gb, 8);
...@@ -827,13 +831,16 @@ int vc1_parse_frame_header_adv(VC1Context *v, GetBitContext* gb) ...@@ -827,13 +831,16 @@ int vc1_parse_frame_header_adv(VC1Context *v, GetBitContext* gb)
v->rptfrm = get_bits(gb, 2); v->rptfrm = get_bits(gb, 2);
} else { } else {
v->tff = get_bits1(gb); v->tff = get_bits1(gb);
v->rptfrm = get_bits1(gb); v->rff = get_bits1(gb);
} }
} }
if(v->panscanflag) { if(v->panscanflag) {
av_log_missing_feature(v->s.avctx, "Pan-scan", 0); av_log_missing_feature(v->s.avctx, "Pan-scan", 0);
//... //...
} }
if(v->p_frame_skipped) {
return 0;
}
v->rnd = get_bits1(gb); v->rnd = get_bits1(gb);
if(v->interlace) if(v->interlace)
v->uvsamp = get_bits1(gb); v->uvsamp = get_bits1(gb);
......
...@@ -45,6 +45,7 @@ static void vc1_extract_headers(AVCodecParserContext *s, AVCodecContext *avctx, ...@@ -45,6 +45,7 @@ static void vc1_extract_headers(AVCodecParserContext *s, AVCodecContext *avctx,
vpc->v.s.avctx = avctx; vpc->v.s.avctx = avctx;
vpc->v.parse_only = 1; vpc->v.parse_only = 1;
next = buf; next = buf;
s->repeat_pict = 0;
for(start = buf, end = buf + buf_size; next < end; start = next){ for(start = buf, end = buf + buf_size; next < end; start = next){
int buf2_size, size; int buf2_size, size;
...@@ -73,6 +74,20 @@ static void vc1_extract_headers(AVCodecParserContext *s, AVCodecContext *avctx, ...@@ -73,6 +74,20 @@ static void vc1_extract_headers(AVCodecParserContext *s, AVCodecContext *avctx,
else else
s->pict_type = vpc->v.s.pict_type; s->pict_type = vpc->v.s.pict_type;
if (avctx->ticks_per_frame > 1){
// process pulldown flags
s->repeat_pict = 1;
// Pulldown flags are only valid when 'broadcast' has been set.
// So ticks_per_frame will be 2
if (vpc->v.rff){
// repeat field
s->repeat_pict = 2;
}else if (vpc->v.rptfrm){
// repeat frames
s->repeat_pict = vpc->v.rptfrm * 2 + 1;
}
}
break; break;
} }
} }
......
...@@ -3897,6 +3897,18 @@ static int vc1_decode_frame(AVCodecContext *avctx, ...@@ -3897,6 +3897,18 @@ static int vc1_decode_frame(AVCodecContext *avctx,
goto err; goto err;
} }
// process pulldown flags
s->current_picture_ptr->f.repeat_pict = 0;
// Pulldown flags are only valid when 'broadcast' has been set.
// So ticks_per_frame will be 2
if (v->rff){
// repeat field
s->current_picture_ptr->f.repeat_pict = 1;
}else if (v->rptfrm){
// repeat frames
s->current_picture_ptr->f.repeat_pict = v->rptfrm * 2;
}
// for skipping the frame // for skipping the frame
s->current_picture.f.pict_type = s->pict_type; s->current_picture.f.pict_type = s->pict_type;
s->current_picture.f.key_frame = s->pict_type == AV_PICTURE_TYPE_I; s->current_picture.f.key_frame = s->pict_type == AV_PICTURE_TYPE_I;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment