[FFmpeg-devel] [PATCH] Incorrect Ogg Theora duration

Måns Rullgård mans
Fri Apr 18 10:10:39 CEST 2008


Henrik Gulbrandsen <henrik at gulbra.net> writes:

> This problem showed up when I was getting ready to deliver my next patch
> yesterday. In effect, the duration calculation for Ogg streams seems to
> drop the first and last frame. This would be true for all Ogg data, but
> it's only noticeable for video at a low frame rate.
>
> The attached examples show the result of
>
>     ffmpeg -i video.mp4 -vcodec libtheora -f ogg video.ogv
>     ffplay -stats video.ogv > report.txt 2>&1
>
> before and after the patch. Here, video.mp4 is exactly 24 seconds long,
> at 10 fps. Notice the "Duration: 00:00:23.80, start: 0.100000" part in
> the stats given with current code!
>
> /Henrik
>
> P.S. The "granule + 1" part of the patch is not technically correct, but
> should work for Theora, Vorbis, FLAC, and Speex, since none of them use
> overly complex semantics for the granule position. A more correct way of
> handling it would require extra code in each of the supported codecs...
>
>
>
>
> Index: libavformat/oggdec.c
> ===================================================================
> --- libavformat/oggdec.c	(revision 12884)
> +++ libavformat/oggdec.c	(working copy)
> @@ -307,6 +307,7 @@ ogg_packet (AVFormatContext * s, int *st
>      ogg_stream_t *os;
>      int complete = 0;
>      int segp = 0, psize = 0;
> +    uint64_t start = url_ftell(s->pb);
>  
>  #if 0
>      av_log (s, AV_LOG_DEBUG, "ogg_packet: curidx=%i\n", ogg->curidx);
> @@ -368,6 +369,7 @@ ogg_packet (AVFormatContext * s, int *st
>      if (os->header < 0){
>          int hdr = os->codec->header (s, idx);
>          if (!hdr){
> +          url_fseek (s->pb, start, SEEK_SET);
>            os->header = os->seq;
>            os->segp = segp;
>            os->psize = psize;

This looks very wrong.

> @@ -463,14 +465,14 @@ ogg_get_length (AVFormatContext * s)
>  
>      if (idx != -1){
>          s->streams[idx]->duration =
> -            ogg_gptopts (s, idx, ogg->streams[idx].granule);
> +            ogg_gptopts (s, idx, ogg->streams[idx].granule + 1);
>      }

Baptiste is right, the last value gives the length of the stream.

>      ogg->size = size;
>      ogg_restore (s, 0);
>      ogg_save (s);
>      while (!ogg_read_page (s, &i)) {
> -        if (i == idx && ogg->streams[i].granule != -1 && ogg->streams[i].granule != 0)
> +        if (i == idx && ogg->streams[i].granule != -1)
>              break;
>      }
>      if (i == idx) {

Why?

-- 
M?ns Rullg?rd
mans at mansr.com




More information about the ffmpeg-devel mailing list