[FFmpeg-devel] [PATCH] Fix failure in av_read_frame on timestamp rollover
Stephen Dredge i
sdredge
Thu Jun 10 04:19:19 CEST 2010
On 06/10/2010 03:25 AM, Michael Niedermayer wrote:
> On Wed, Jun 09, 2010 at 03:02:52PM +1000, Stephen Dredge i wrote:
>
>> av_read_frame can fail on some (TS) files at timestamp rollover, reading to
>> eof before returning a frame.
>>
>> The attached patch adds some utility functions for rollover aware timestamp
>> comparison and uses them in av_read_frame to avoid problems at timestamp
>> rollover.
>>
>> The utility functions provide normal comparisons if pts_wrap_bits is 0 or
>>
>>> = 63 so behaviour on formats without timestamp wrapping should be
>>>
>> unaffected.
>>
>> --
>> Stephen Dredge sdredge at tpg.com.au
>> _______________________________________________________________
>> System Administrator
>> +61 2 9850 0979
>>
>> TPG Internet
>> www.tpg.com.au
>>
>>
>>
>>
>
>> libavformat/utils.c | 9 ++++---
>> libavutil/mathematics.c | 59 ++++++++++++++++++++++++++++++++++++++++++++++++
>> libavutil/mathematics.h | 25 ++++++++++++++++++++
>> 3 files changed, 89 insertions(+), 4 deletions(-)
>> a5af48c8203ac3261e2c383073a131c64ca0d294 rollover_fix.patch
>> diff --git a/libavformat/utils.c b/libavformat/utils.c
>> index 6365f3e..02ffce1 100644
>> --- a/libavformat/utils.c
>> +++ b/libavformat/utils.c
>> @@ -1152,18 +1152,19 @@ int av_read_frame(AVFormatContext *s, AVPacket *pkt)
>> AVPacketList *pktl;
>> int eof=0;
>> const int genpts= s->flags& AVFMT_FLAG_GENPTS;
>> + int wrap_bits;
>>
>> for(;;){
>> pktl = s->packet_buffer;
>> if (pktl) {
>> AVPacket *next_pkt=&pktl->pkt;
>> -
>> + wrap_bits = s->streams[next_pkt->stream_index]->pts_wrap_bits;
>> if(genpts&& next_pkt->dts != AV_NOPTS_VALUE){
>> while(pktl&& next_pkt->pts == AV_NOPTS_VALUE){
>> if( pktl->pkt.stream_index == next_pkt->stream_index
>> -&& next_pkt->dts< pktl->pkt.dts
>>
>
>> -&& pktl->pkt.pts != pktl->pkt.dts //not b frame
>>
> a != check should
>
dts can be negative and pts positive for the same time
(compute_pkt_fields can emit negative dts), so a mod comparison is
required.
> [...]
>
>> +int64_t av_mod_wrap_bits(int64_t x, int wrap_bits){
>> + int64_t result;
>> + int64_t modulo;
>> + if(!wrap_bits || wrap_bits>= 63) {
>> + return x;
>> + }
>> + modulo = 1LL<< wrap_bits;
>> + result = x % modulo;
>> + if(result< 0) {
>> + result += modulo;
>> + }
>> + return result;
>> +}
>> +
>> +int av_gt_mod_wrap_bits(int64_t x, int64_t y, int wrap_bits){
>> + int64_t modulo;
>> + int64_t result;
>> + if(!wrap_bits || wrap_bits>= 63) {
>> + return x>y?1:0;
>> + }
>> + modulo = 1LL<< wrap_bits;
>> + result = av_mod_wrap_bits(x - y, wrap_bits);
>> + if(result< modulo/2) {
>> + return 1;
>> + }
>> + return 0;
>> +}
>>
> this is a mess, ive added a much simpler av_compare_mod() that could be used
>
Agreed it's clunky. I was going for clarity and simplicity of use over
elegance.
av_compare_mod is not much help here. It can't be used for negative
numbers or where pts_wrap_bits = 64.
The code could be cleaned up in a quite few places and potential bugs
eliminated if there was a set of mod math functions to use,
instead of adding code to catch wraps at every point where timestamp
math or comparisons are made.
I'm open to suggestions.
> [...]
>
>
>
>
> _______________________________________________
> ffmpeg-devel mailing list
> ffmpeg-devel at mplayerhq.hu
> https://lists.mplayerhq.hu/mailman/listinfo/ffmpeg-devel
--
Stephen Dredge sdredge at tpg.com.au
_______________________________________________________________
System Administrator
+61 2 9850 0979
TPG Internet
www.tpg.com.au
More information about the ffmpeg-devel
mailing list