[FFmpeg-devel] [PATCH] Keep track of stream duration and nb_frames when muxing

Aurelien Jacobs aurel
Wed Jan 20 17:40:35 CET 2010


On Tue, Jan 19, 2010 at 12:18:35AM -0500, David Conrad wrote:
> Hi,
> 
> This has av_(interleaved)_write_frame() keep track of duration and number of frames for each stream. This is generally useful for calculating an average frame rate after muxing is complete, as I intend to write for mkv.
> 
> [...]
> 
> commit 980dec0261bb25a47c8a0b65f85288ca70a3e2da
> Author: David Conrad <lessen42 at gmail.com>
> Date:   Tue Jan 19 00:12:33 2010 -0500
> 
>     Write average frame rate in the matroska header
> 
> diff --git a/libavformat/matroskaenc.c b/libavformat/matroskaenc.c
> index c119518..162467a 100644
> --- a/libavformat/matroskaenc.c
> +++ b/libavformat/matroskaenc.c
> @@ -580,6 +581,11 @@ static int mkv_write_tracks(AVFormatContext *s)
>                      put_ebml_uint(pb, MATROSKA_ID_VIDEODISPLAYWIDTH , d_width);
>                      put_ebml_uint(pb, MATROSKA_ID_VIDEODISPLAYHEIGHT, codec->height);
>                  }
> +                mkv->fps_offset[i] = url_ftell(pb);
> +                if (st->avg_frame_rate.num && st->avg_frame_rate.den)
> +                    put_ebml_float(pb, MATROSKA_ID_VIDEOFRAMERATE, av_q2d(st->avg_frame_rate));
> +                else
> +                    put_ebml_float(pb, MATROSKA_ID_VIDEOFRAMERATE, 1/av_q2d(codec->time_base));

IMHO it would be nicer to extract the put_ebml_float() call out of the if(),
IOW use a temporary fps variable.
But maybe that's just my cosmetical preference, so fell free to ignore this
comment if you don't like it.

> @@ -908,6 +914,17 @@ static int mkv_write_trailer(AVFormatContext *s)
>          url_fseek(pb, mkv->duration_offset, SEEK_SET);
>          put_ebml_float(pb, MATROSKA_ID_DURATION, mkv->duration);
>  
> +        // update the fps
> +        for (i = 0; i < s->nb_streams; i++) {
> +            AVStream *st = s->streams[i];
> +            int64_t duration = st->duration - st->start_time;
> +            if (duration && st->nb_frames) {
> +                double fps = st->nb_frames / (duration * av_q2d(st->time_base));
> +                url_fseek(pb, mkv->fps_offset[i], SEEK_SET);
> +                put_ebml_float(pb, MATROSKA_ID_VIDEOFRAMERATE, fps);
> +            }
> +        }

MATROSKA_ID_VIDEOFRAMERATE is only valid for video tracks. Here you
try to write it for every tracks, including the non-video ones (for
which mkv->fps_offset[i] was not initialized).

Aurel



More information about the ffmpeg-devel mailing list