GNOME Bugzilla – Bug 371939
mov/mp4/m4a/3gp/3g2 muxers create wrong durations
Last modified: 2008-07-06 21:07:19 UTC
Copied from question/answer mail on gst-devel: Hi, On 11/4/06, Deeptendu Bikash <dbikash@gmail.com> wrote: > Hello, > > I am using the latest CVS version of gst-ffmpeg to mux raw AAC files into > MP4 format, but there seems to be some problem with the duration. > > gst-launch filesrc location=... ! audio/mpeg, rate=\(int\)8000, > channels=\(int\)2, mpegversion=\(int\)4 ! ffmux_mp4 ! filesink location=... > > The resulting file has the MP4 file format but has a huge duration (8000 > hours etc) and a zero bitrate. And of course, no player, including VLC, > could play it. Any suggestions on how to fix this? There are several issues at hand. What ffmpeg does, for a start, is utterly wrong: in libavformat/movenc.c (the code used by quicktime/mp4/iso muxing), the duration for a track is calculated using: mov->tracks[i].trackDuration = (int64_t)mov->tracks[i].sampleCount * mov->tracks[i].sampleDuration; The sampleCount is the number of samples for that track, and sampleDuration is computed using: track->sampleDuration = st->codec->frame_size; All of this is done when writing the headers of the file, after having received EOS. The problem is that the value of st->codec->frame_size is only calculated when receiving the first buffer (code you pasted below).... which doesn't mean anything (nothing guarantees that all the following buffers will have the same duration). In fact there's a VERY good chance that the first buffer will last longer than the following ones. Resulting in a computed duration which is way too big. The main problem, therefore, is that we need to give ffmpeg a combination of st->codec->frame_size and st->codec->sample_rate in such a way that: total_duration = frame_size * sample_rate * GST_SECOND. The fix I'm thinking about implementing is to, when we receive EOS and before writing the headers, compute the proper frame_size according to the real duration (which we know in GStreamer) as such : frame_size = RealDuration / (sample_rate * GST_SECOND). Unfortunately I currently don't have time to implement it right now (apart from creating a crude hack, doing it properly requires implementing GstSegment support in GstFFMpegMux so we get the REAL duration). Anyone up to the job can follow these ideas if I still haven't implmented it. Looking back on previous versions of both the ffmpeg and gst-ffmpeg code, this has always been broken (resulting in completely broken durations). The funniest part is that it plays fine in mplayer (using ffmpeg of course). In fact all the files I tried to create using the ffmpeg mov/mp4/iso muxers have broken duration with gstreamer qtdemux and Quicktime Player... but give correct duration with... ffmpeg :( > > Looking at the code (gstffmpegmux.c), the portion that sets the framerate > for audio, looks to incomplete/incorrect. There is a comment saying that > this might not work for any kind of audio. > > buffer=gst_collect_pads_peek(ffmpegmux->collect, > (GstCollectData *)collect_pad); > if(buffer){ > st->codec->frame_size = st->codec->sample_rate * > GST_BUFFER_DURATION(buffer)/GST_SECOND; > gst_buffer_unref(buffer); > } > > When I print the values of st->codec->frame_size, st->codec->sample_rate and > GST_BUFFER_DURATION(buffer)/GST_SECOND, I get the values > 1266874889, 8000 and 1266874889. Evidently, the buffer duration is wrong. > How can I correct it? > > Can anybody help with this much of info? > > Regards, > Deeptendu
Hi, this bug is present in the latest CVS code of gst-ffmpeg (in date of 01/17/2008), is there any plan to correct it for the next revision of gst-ffmpeg ? Regards.
*** Bug 541408 has been marked as a duplicate of this bug. ***
If I read things right, duration has become more reasonable in movenc.c now: trk->trackDuration = pkt->dts - trk->cluster[0].dts + pkt->duration; However, it appears there was also a problem with the pkt->duration that it was being fed; see above duplicate bug for background. 2008-07-06 Mark Nauwelaerts <mark.nauwelaerts@collabora.co.uk> Based on a patch by: Aurelien Grimaud <gstelzz at yahoo dot fr> * ext/ffmpeg/gstffmpegmux.c: (gst_ffmpegmux_collected): Properly convert buffer duration to an ffmpeg packet duration. Fixes #371939.