Hi, As I've been promising myself for ages, I went hunting the cause of AV-sync drift with FFMPEGrec. The problem was in ffmpeg's libav - the audio PTS was tracked using a float; accumulating error sent the sync steadily off. I've done a quick change to use double instead of float - in testing, this holds lipsync for 3 hours at least. Would someone like to test this - I'd like to have some confirmations from others and then I'll try get it into the ffmpeg CVS. Brian Murrell, how about you? (I think you'll be interested in the next patch I'll send, too!) libav isn't documented and I'm not sure whether this change will affect other users of this library. I would really like to get rid of the float pts and track frames by integer count, working out the pts from "scratch" rather than incrememntally. I'll ask about that on the ffmpeg list. Anyway - for me this works nice. Regards, Steve
Index: libav/mpeg.c =================================================================== RCS file: /cvsroot/ffmpeg/ffmpeg/libav/mpeg.c,v retrieving revision 1.2 diff -u -r1.2 mpeg.c --- libav/mpeg.c 2001/08/13 21:37:10 1.2 +++ libav/mpeg.c 2001/12/30 00:41:11 @@ -16,6 +16,12 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +/* Steve Davies <steve@xxxxxxxxxxxxx> - 2001-12-29 - + Adjusted pts calcs from float to double to "fix" + AV sync trouble +*/ + #include "avformat.h" #define MAX_PAYLOAD_SIZE 4096 @@ -27,7 +33,7 @@ UINT8 id; int max_buffer_size; /* in bytes */ int packet_number; - float pts; + double pts; INT64 start_pts; } StreamInfo; @@ -233,8 +239,8 @@ timestamp = stream->start_pts; #if 0 - printf("packet ID=%2x PTS=%0.3f\n", - id, timestamp / 90000.0); + printf("\npacket ID=%2x PTS=%0.18f, %lli\n", + id, (double)(timestamp / 90000.0), timestamp); #endif buf_ptr = buffer; @@ -314,7 +320,12 @@ while (size > 0) { /* set pts */ if (stream->start_pts == -1) - stream->start_pts = stream->pts * 90000.0; + // 3000? tries to compensate for accumulating rounding error in the double pts. + // after 1 hour audio ptses are off by around 40msec. We add 3000 which is + // 3000/90000=33msec and result is that audio starts slightly behind and drifts + // to exact after 50 mins or so. 40 msec isn't noticable, whether ahead or behind, + // so this little tweak should mean acceptable sync for 3-4 hours of recording. + stream->start_pts = stream->pts * 90000.0 + 3000.0; len = s->packet_data_max_size - stream->buffer_ptr; if (len > size) len = size; @@ -325,15 +336,17 @@ while (stream->buffer_ptr >= s->packet_data_max_size) { /* output the packet */ if (stream->start_pts == -1) - stream->start_pts = stream->pts * 90000.0; + stream->start_pts = stream->pts * 90000.0 + 3000.0; flush_packet(ctx, stream_index); } } if (st->codec.codec_type == CODEC_TYPE_AUDIO) { - stream->pts += (float)st->codec.frame_size / st->codec.sample_rate; + //printf("\nbefore, stream->pts = %0.15f\n", stream->pts); + stream->pts += (double)st->codec.frame_size / st->codec.sample_rate; + //printf("after, stream->pts = %0.15f\n", stream->pts); } else { - stream->pts += FRAME_RATE_BASE / (float)st->codec.frame_rate; + stream->pts += (double)FRAME_RATE_BASE / st->codec.frame_rate; } return 0; }