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: Ronald S. Bultje <rsbultje@gmail.com>tags/n0.9
@@ -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) | |||||
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) | |||||
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, | |||||
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, | |||||
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, | |||||
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; | ||||