[FFmpeg-devel] [patch 3/3] Make timing calculations less dependant on start_time being defined.

Neil Brown neilb
Thu Aug 23 02:17:20 CEST 2007


On Wednesday August 22, andreas at olebyn.nu wrote:
> 
> Since Neil does not seem to come back with a cleaned up patch
> I've done that. (Getting invalid durations bugs me a bit :)

Hi,
 thanks for doing that.

I was planning to come back with an update (sorry about the tabs in
the first version) but was distracted by several things.

One being that I still don't get all the results I expect with my .wmv
file.

With this patch in place, it reports the correct duration (00:05:00.8)
which is an improvement, however I have problems syncing video and
audio.

For example, if I
   ffmpeg -i myfile.wmv  -b 1M myfile.mpeg

The resulting mpeg is nearly 2 seconds longer (00:05:02.2), reports a start
time of 0.500000, and the audio is about 1.5 seconds ahead of the
video.

Interestingly, the "preroll" number which used to be used to initialise
start_time is 1579 (milliseconds), which is 1 second and 14 frames.
If I offset the audio from the video by exactly that, it is perfectly
in sync.  This puts the audio starting at the exact moment that the
first non-black pixel appears in the video stream.

If I set st->start_time to asf->hdr.preroll in asf.c, then transcode
to mpeg, the resulting mpeg is perfectly in sync.
So there is still something wrong here.

Interestingly playing the original .wmv with 'ffplay' plays the audio
in sync with the video.  It is just using ffmpeg to transcode that
gets it wrong (plus kdenlive not only plays it out-of-sync, but also
the audio is a bit choppy).

So I'm perfectly willing to believe that st->start_time shouldn't be
set to hdr.preroll, but it seems that something else needs to be done
with that number and I have no idea what.....

However I found
      http://msdn2.microsoft.com/en-us/library/bb643323.aspx

which says:

  Preroll

  Specifies the amount of time to buffer data before starting to play
  the file, in millisecond units. If this value is nonzero, the Play
  Duration field and all of the payload Presentation Time fields have
  been offset by this amount. Therefore, player software must subtract
  the value in the preroll field from the play duration and
  presentation times to calculate their actual values. 

  It follows that all payload Presentation Time fields need to be at
  least this value. 

So if the video packets have a timestamp, which starts from 1.5
seconds, and the audio packets don't have a timestamp, and just rely
on starting at 'start_time', then I would get exactly the behaviour I
see.  It can be fixed either by subtracting hdr.preroll from the
timestamp in all the video packets, or by setting start_time to
hdr.preroll.

I presume the former is preferred.  This patch seems to fix it.

Index: libavformat/asf.c
===================================================================
--- libavformat/asf.c	(revision 10189)
+++ libavformat/asf.c	(working copy)
@@ -793,7 +793,7 @@
             /* new packet */
             av_new_packet(&asf_st->pkt, asf->packet_obj_size);
             asf_st->seq = asf->packet_seq;
-            asf_st->pkt.pts = asf->packet_frag_timestamp;
+            asf_st->pkt.pts = asf->packet_frag_timestamp - asf->hdr.preroll;
             asf_st->pkt.stream_index = asf->stream_index;
             asf_st->pkt.pos =
             asf_st->packet_pos= asf->packet_pos;

With this, the transcoded .mpeg is perfectly in-sync, and the file is
the correct length (well.. at 00:05:00.7 it seems to have lost one
frame).

NeilBrown





More information about the ffmpeg-devel mailing list