[FFmpeg-devel] [PATCH] Fix empty G-VOP header decoding in MPEG-4
Måns Rullgård
mans
Thu Feb 10 14:55:58 CET 2011
Anatoly Nenashev <anatoly.nenashev at ovsoft.ru> writes:
> On 10.02.2011 01:32, M?ns Rullg?rd wrote:
>> Anatoly Nenashev<anatoly.nenashev at ovsoft.ru> writes:
>>
>>
>>> On 08.02.2011 22:00, M?ns Rullg?rd wrote:
>>>
>>>> Anatoly Nenashev<anatoly.nenashev at ovsoft.ru> writes:
>>>>
>>>>
>>>>
>>>>> Hi all!
>>>>> There are some cameras which send mpeg-4 streams with empty G-VOP header.
>>>>> This part of stream looks like this:
>>>>> ... 00 00 01 B3 00 00 00 01 B6 ...
>>>>> Sample file uploaded in issue 2592.
>>>>> FFmpeg reports "header damaged" and ignores first I-frame in G-VOP.
>>>>> Attached patch fix this problem.
>>>>>
>>>>> Anatoly.
>>>>>
>>>>>
>>> [...]
>>>
>>>> Looking at this, I wonder why this is there at all. The s->time_base
>>>> field is only used to incorrectly set the pts field of the decoded
>>>> frame (now I understand why those values always are wrong). The
>>>> actual PTS is passed from the input packet to the pkt_pts field of the
>>>> output frame.
>>>>
>>>> IMO this nonsense should be removed. The time_code field in the
>>>> bitstream has nothing to do with PTS.
>>>>
>>>>
>>>>
>>> Hmm... So, if I understand you clearly, we just can ignore GOP header
>>> as done in attached patch.
>>>
>> The value seems to also be used in a convoluted calculation of direct
>> mode MVs. This calculation doesn't actually need the time_code value,
>> only the distance (in frames) between reference frames and the predicted
>> frame. I'd be careful messing with it.
>>
>> The part setting the PTS of the output frame should of course be
>> removed. It is clearly wrong.
>>
>>
> I've changed original patch to carefully check that time code
> obtained from GOP header is monotone.
> Also PTS setting for output frame is removed. See attachment.
>
> diff --git a/libavcodec/mpeg4videodec.c b/libavcodec/mpeg4videodec.c
> index 5303da3..02e7853 100644
> --- a/libavcodec/mpeg4videodec.c
> +++ b/libavcodec/mpeg4videodec.c
> @@ -1494,16 +1494,19 @@ end:
>
> static int mpeg4_decode_gop_header(MpegEncContext * s, GetBitContext *gb){
> int hours, minutes, seconds;
> + int val, time_base;
>
> - hours= get_bits(gb, 5);
> - minutes= get_bits(gb, 6);
> - skip_bits1(gb);
> - seconds= get_bits(gb, 6);
> + val= show_bits(gb, 18);
> + hours= (val >> 13) & 0x1F;
> + minutes= (val >> 7) & 0x3F;
> + seconds= val & 0x3F;
>
> - s->time_base= seconds + 60*(minutes + 60*hours);
> -
> - skip_bits1(gb);
> - skip_bits1(gb);
> + time_base= seconds + 60*(minutes + 60*hours);
> + if (time_base < s->time_base) {
> + av_log(s->avctx, AV_LOG_WARNING, "time_code in GOP header is non monotone, skipping\n");
> + } else {
> + s->time_base= time_base;
> + }
>
> return 0;
> }
The time_code doesn't have to be monotonically increasing IIUC. Better
to just check the marker bit and do nothing if it's not there. It won't
be there in your broken streams.
> @@ -1947,12 +1950,7 @@ static int decode_vop_header(MpegEncContext *s, GetBitContext *gb){
> }
> }
>
> - if(s->avctx->time_base.num)
> - s->current_picture_ptr->pts= (s->time + s->avctx->time_base.num/2) / s->avctx->time_base.num;
> - else
> - s->current_picture_ptr->pts= AV_NOPTS_VALUE;
> - if(s->avctx->debug&FF_DEBUG_PTS)
> - av_log(s->avctx, AV_LOG_DEBUG, "MPEG4 PTS: %"PRId64"\n", s->current_picture_ptr->pts);
> + s->current_picture_ptr->pts= AV_NOPTS_VALUE;
>
> check_marker(gb, "before vop_coded");
This is for another patch. I wouldn't worry about it right now.
--
M?ns Rullg?rd
mans at mansr.com
More information about the ffmpeg-devel
mailing list