[FFmpeg-devel] [PATCH] Fix failure in av_read_frame on timestamp rollover

Michael Niedermayer michaelni
Wed Jun 9 19:25:14 CEST 2010


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 work

[...]
> +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

[...]

-- 
Michael     GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB

When you are offended at any man's fault, turn to yourself and study your
own failings. Then you will forget your anger. -- Epictetus
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 189 bytes
Desc: Digital signature
URL: <http://lists.mplayerhq.hu/pipermail/ffmpeg-devel/attachments/20100609/18f172fd/attachment.pgp>



More information about the ffmpeg-devel mailing list