[FFmpeg-cvslog] r23473 - in trunk: libavformat/matroskaenc.c tests/ref/acodec/pcm tests/ref/lavf/mkv tests/ref/seek/lavf.mkv.ref

conrad subversion
Sat Jun 5 00:40:50 CEST 2010


Author: conrad
Date: Sat Jun  5 00:40:50 2010
New Revision: 23473

Log:
matroskaenc: Mux clusters better

Start them on keyframes when reasonable, and delay writing audio packets
to help ensure that there's audio samples available for the first frame in
clusters.

Patch by James Zern <jzern at google>

Modified:
   trunk/libavformat/matroskaenc.c
   trunk/tests/ref/acodec/pcm
   trunk/tests/ref/lavf/mkv
   trunk/tests/ref/seek/lavf.mkv.ref

Modified: trunk/libavformat/matroskaenc.c
==============================================================================
--- trunk/libavformat/matroskaenc.c	Sat Jun  5 00:40:44 2010	(r23472)
+++ trunk/libavformat/matroskaenc.c	Sat Jun  5 00:40:50 2010	(r23473)
@@ -81,6 +81,8 @@ typedef struct MatroskaMuxContext {
     mkv_track       *tracks;
 
     struct AVMD5    *md5_ctx;
+    unsigned int    audio_buffer_size;
+    AVPacket        cur_audio_pkt;
 } MatroskaMuxContext;
 
 
@@ -746,6 +748,10 @@ static int mkv_write_header(AVFormatCont
     if (mkv->cues == NULL)
         return AVERROR(ENOMEM);
 
+    av_init_packet(&mkv->cur_audio_pkt);
+    mkv->cur_audio_pkt.size = 0;
+    mkv->audio_buffer_size  = 0;
+
     put_flush_packet(pb);
     return 0;
 }
@@ -861,7 +867,7 @@ static void mkv_flush_dynbuf(AVFormatCon
     mkv->dyn_bc = NULL;
 }
 
-static int mkv_write_packet(AVFormatContext *s, AVPacket *pkt)
+static int mkv_write_packet_internal(AVFormatContext *s, AVPacket *pkt)
 {
     MatroskaMuxContext *mkv = s->priv_data;
     ByteIOContext *pb = s->pb;
@@ -910,9 +916,38 @@ static int mkv_write_packet(AVFormatCont
         if (ret < 0) return ret;
     }
 
-    // start a new cluster every 5 MB or 5 sec, or 32k / 1 sec for streaming
-    if ((url_is_streamed(s->pb) && (url_ftell(pb) > 32*1024 || ts > mkv->cluster_pts + 1000))
-        ||  url_ftell(pb) > mkv->cluster_pos + 5*1024*1024 || ts > mkv->cluster_pts + 5000) {
+    mkv->duration = FFMAX(mkv->duration, ts + duration);
+    return 0;
+}
+
+static int mkv_copy_packet(MatroskaMuxContext *mkv, const AVPacket *pkt)
+{
+    uint8_t *data           = mkv->cur_audio_pkt.data;
+    mkv->cur_audio_pkt      = *pkt;
+    mkv->cur_audio_pkt.data = av_fast_realloc(data, &mkv->audio_buffer_size, pkt->size);
+    if (!mkv->cur_audio_pkt.data)
+        return AVERROR(ENOMEM);
+
+    memcpy(mkv->cur_audio_pkt.data, pkt->data, pkt->size);
+    mkv->cur_audio_pkt.size = pkt->size;
+    return 0;
+}
+
+static int mkv_write_packet(AVFormatContext *s, AVPacket *pkt)
+{
+    MatroskaMuxContext *mkv = s->priv_data;
+    ByteIOContext *pb = url_is_streamed(s->pb) ? mkv->dyn_bc : s->pb;
+    AVCodecContext *codec = s->streams[pkt->stream_index]->codec;
+    int ret, keyframe = !!(pkt->flags & AV_PKT_FLAG_KEY);
+    int64_t ts = mkv->tracks[pkt->stream_index].write_dts ? pkt->dts : pkt->pts;
+    int cluster_size = url_ftell(pb) - (url_is_streamed(s->pb) ? 0 : mkv->cluster_pos);
+
+    // start a new cluster every 5 MB or 5 sec, or 32k / 1 sec for streaming or
+    // after 4k and on a keyframe
+    if (mkv->cluster_pos &&
+        ((url_is_streamed(s->pb) && (cluster_size > 32*1024 || ts > mkv->cluster_pts + 1000))
+         ||                      cluster_size > 5*1024*1024 || ts > mkv->cluster_pts + 5000
+         || (codec->codec_type == AVMEDIA_TYPE_VIDEO && keyframe && cluster_size > 4*1024))) {
         av_log(s, AV_LOG_DEBUG, "Starting new cluster at offset %" PRIu64
                " bytes, pts %" PRIu64 "\n", url_ftell(pb), ts);
         end_ebml_master(pb, mkv->cluster);
@@ -921,8 +956,23 @@ static int mkv_write_packet(AVFormatCont
             mkv_flush_dynbuf(s);
     }
 
-    mkv->duration = FFMAX(mkv->duration, ts + duration);
-    return 0;
+    // check if we have an audio packet cached
+    if (mkv->cur_audio_pkt.size > 0) {
+        ret = mkv_write_packet_internal(s, &mkv->cur_audio_pkt);
+        mkv->cur_audio_pkt.size = 0;
+        if (ret < 0) {
+            av_log(s, AV_LOG_ERROR, "Could not write cached audio packet ret:%d\n", ret);
+            return ret;
+        }
+    }
+
+    // buffer an audio packet to ensure the packet containing the video
+    // keyframe's timecode is contained in the same cluster for WebM
+    if (codec->codec_type == AVMEDIA_TYPE_AUDIO)
+        ret = mkv_copy_packet(mkv, pkt);
+    else
+        ret = mkv_write_packet_internal(s, pkt);
+    return ret;
 }
 
 static int mkv_write_trailer(AVFormatContext *s)
@@ -932,6 +982,16 @@ static int mkv_write_trailer(AVFormatCon
     int64_t currentpos, second_seekhead, cuespos;
     int ret;
 
+    // check if we have an audio packet cached
+    if (mkv->cur_audio_pkt.size > 0) {
+        ret = mkv_write_packet_internal(s, &mkv->cur_audio_pkt);
+        mkv->cur_audio_pkt.size = 0;
+        if (ret < 0) {
+            av_log(s, AV_LOG_ERROR, "Could not write cached audio packet ret:%d\n", ret);
+            return ret;
+        }
+    }
+
     if (mkv->dyn_bc) {
         end_ebml_master(mkv->dyn_bc, mkv->cluster);
         mkv_flush_dynbuf(s);
@@ -970,6 +1030,7 @@ static int mkv_write_trailer(AVFormatCon
     end_ebml_master(pb, mkv->segment);
     av_free(mkv->md5_ctx);
     av_free(mkv->tracks);
+    av_destruct_packet(&mkv->cur_audio_pkt);
     put_flush_packet(pb);
     return 0;
 }

Modified: trunk/tests/ref/acodec/pcm
==============================================================================
--- trunk/tests/ref/acodec/pcm	Sat Jun  5 00:40:44 2010	(r23472)
+++ trunk/tests/ref/acodec/pcm	Sat Jun  5 00:40:50 2010	(r23473)
@@ -22,11 +22,11 @@ stddev:    0.00 PSNR:999.99 bytes:  1058
 1058444 ./tests/data/acodec/pcm_s16le.wav
 95e54b261530a1bcf6de6fe3b21dc5f6 *./tests/data/pcm.acodec.out.wav
 stddev:    0.00 PSNR:999.99 bytes:  1058444/  1058444
-43440f8078f2383c0dd618ad606f6830 *./tests/data/acodec/pcm_s16be.mkv
+fca887459876a7fdc4b9580691acd835 *./tests/data/acodec/pcm_s16be.mkv
  1060693 ./tests/data/acodec/pcm_s16be.mkv
 95e54b261530a1bcf6de6fe3b21dc5f6 *./tests/data/pcm.acodec.out.wav
 stddev:    0.00 PSNR:999.99 bytes:  1058444/  1058444
-1e63166f1672b7eb00877c697c06743c *./tests/data/acodec/pcm_s16le.mkv
+2817e2a028a9117d4809604fa0f81a80 *./tests/data/acodec/pcm_s16le.mkv
  1060693 ./tests/data/acodec/pcm_s16le.mkv
 95e54b261530a1bcf6de6fe3b21dc5f6 *./tests/data/pcm.acodec.out.wav
 stddev:    0.00 PSNR:999.99 bytes:  1058444/  1058444

Modified: trunk/tests/ref/lavf/mkv
==============================================================================
--- trunk/tests/ref/lavf/mkv	Sat Jun  5 00:40:44 2010	(r23472)
+++ trunk/tests/ref/lavf/mkv	Sat Jun  5 00:40:50 2010	(r23473)
@@ -1,3 +1,3 @@
-cf230e089e737ed9449fbfb3cb87da92 *./tests/data/lavf/lavf.mkv
-  320471 ./tests/data/lavf/lavf.mkv
+5e906a7003f893cf6481f186c92dc16c *./tests/data/lavf/lavf.mkv
+  320537 ./tests/data/lavf/lavf.mkv
 ./tests/data/lavf/lavf.mkv CRC=0x2a83e6b0

Modified: trunk/tests/ref/seek/lavf.mkv.ref
==============================================================================
--- trunk/tests/ref/seek/lavf.mkv.ref	Sat Jun  5 00:40:44 2010	(r23472)
+++ trunk/tests/ref/seek/lavf.mkv.ref	Sat Jun  5 00:40:50 2010	(r23473)
@@ -2,35 +2,35 @@ ret: 0         st: 0 flags:1 dts: 0.0000
 ret: 0         st:-1 flags:0  ts:-1.000000
 ret: 0         st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos:    513 size: 27837
 ret: 0         st:-1 flags:1  ts: 1.894167
-ret: 0         st: 0 flags:1 dts: 0.960000 pts: 0.960000 pos: 291902 size: 27834
+ret: 0         st: 0 flags:1 dts: 0.960000 pts: 0.960000 pos: 291934 size: 27834
 ret: 0         st: 0 flags:0  ts: 0.788000
-ret: 0         st: 0 flags:1 dts: 0.960000 pts: 0.960000 pos: 291902 size: 27834
+ret: 0         st: 0 flags:1 dts: 0.960000 pts: 0.960000 pos: 291934 size: 27834
 ret: 0         st: 0 flags:1  ts:-0.317000
 ret: 0         st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos:    513 size: 27837
 ret: 0         st: 1 flags:0  ts: 2.577000
 ret:-EOF
 ret: 0         st: 1 flags:1  ts: 1.471000
-ret: 0         st: 1 flags:1 dts: 1.019000 pts: 1.019000 pos: 320175 size:   209
+ret: 0         st: 1 flags:1 dts: 1.019000 pts: 1.019000 pos: 320207 size:   209
 ret: 0         st:-1 flags:0  ts: 0.365002
-ret: 0         st: 0 flags:1 dts: 0.480000 pts: 0.480000 pos: 146687 size: 27925
+ret: 0         st: 0 flags:1 dts: 0.480000 pts: 0.480000 pos: 146703 size: 27925
 ret: 0         st:-1 flags:1  ts:-0.740831
 ret: 0         st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos:    513 size: 27837
 ret: 0         st: 0 flags:0  ts: 2.153000
 ret:-EOF
 ret: 0         st: 0 flags:1  ts: 1.048000
-ret: 0         st: 0 flags:1 dts: 0.960000 pts: 0.960000 pos: 291902 size: 27834
+ret: 0         st: 0 flags:1 dts: 0.960000 pts: 0.960000 pos: 291934 size: 27834
 ret: 0         st: 1 flags:0  ts:-0.058000
 ret: 0         st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos:    513 size: 27837
 ret: 0         st: 1 flags:1  ts: 2.836000
-ret: 0         st: 1 flags:1 dts: 1.019000 pts: 1.019000 pos: 320175 size:   209
+ret: 0         st: 1 flags:1 dts: 1.019000 pts: 1.019000 pos: 320207 size:   209
 ret: 0         st:-1 flags:0  ts: 1.730004
 ret:-EOF
 ret: 0         st:-1 flags:1  ts: 0.624171
-ret: 0         st: 0 flags:1 dts: 0.480000 pts: 0.480000 pos: 146687 size: 27925
+ret: 0         st: 0 flags:1 dts: 0.480000 pts: 0.480000 pos: 146703 size: 27925
 ret: 0         st: 0 flags:0  ts:-0.482000
 ret: 0         st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos:    513 size: 27837
 ret: 0         st: 0 flags:1  ts: 2.413000
-ret: 0         st: 0 flags:1 dts: 0.960000 pts: 0.960000 pos: 291902 size: 27834
+ret: 0         st: 0 flags:1 dts: 0.960000 pts: 0.960000 pos: 291934 size: 27834
 ret: 0         st: 1 flags:0  ts: 1.307000
 ret:-EOF
 ret: 0         st: 1 flags:1  ts: 0.201000
@@ -38,16 +38,16 @@ ret: 0         st: 1 flags:1 dts: 0.1830
 ret: 0         st:-1 flags:0  ts:-0.904994
 ret: 0         st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos:    513 size: 27837
 ret: 0         st:-1 flags:1  ts: 1.989173
-ret: 0         st: 0 flags:1 dts: 0.960000 pts: 0.960000 pos: 291902 size: 27834
+ret: 0         st: 0 flags:1 dts: 0.960000 pts: 0.960000 pos: 291934 size: 27834
 ret: 0         st: 0 flags:0  ts: 0.883000
-ret: 0         st: 0 flags:1 dts: 0.960000 pts: 0.960000 pos: 291902 size: 27834
+ret: 0         st: 0 flags:1 dts: 0.960000 pts: 0.960000 pos: 291934 size: 27834
 ret: 0         st: 0 flags:1  ts:-0.222000
 ret: 0         st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos:    513 size: 27837
 ret: 0         st: 1 flags:0  ts: 2.672000
 ret:-EOF
 ret: 0         st: 1 flags:1  ts: 1.566000
-ret: 0         st: 1 flags:1 dts: 1.019000 pts: 1.019000 pos: 320175 size:   209
+ret: 0         st: 1 flags:1 dts: 1.019000 pts: 1.019000 pos: 320207 size:   209
 ret: 0         st:-1 flags:0  ts: 0.460008
-ret: 0         st: 0 flags:1 dts: 0.480000 pts: 0.480000 pos: 146687 size: 27925
+ret: 0         st: 0 flags:1 dts: 0.480000 pts: 0.480000 pos: 146703 size: 27925
 ret: 0         st:-1 flags:1  ts:-0.645825
 ret: 0         st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos:    513 size: 27837



More information about the ffmpeg-cvslog mailing list