[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