mirror of
https://github.com/FFmpeg/FFmpeg.git
synced 2024-12-28 20:53:54 +02:00
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> Originally committed as revision 23473 to svn://svn.ffmpeg.org/ffmpeg/trunk
This commit is contained in:
parent
3ad0b189f7
commit
ac9baa716b
@ -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(AVFormatContext *s)
|
||||
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(AVFormatContext *s)
|
||||
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(AVFormatContext *s, AVPacket *pkt)
|
||||
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(AVFormatContext *s, AVPacket *pkt)
|
||||
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(AVFormatContext *s)
|
||||
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(AVFormatContext *s)
|
||||
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;
|
||||
}
|
||||
|
@ -22,11 +22,11 @@ stddev: 0.00 PSNR:999.99 bytes: 1058444/ 1058444
|
||||
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
|
||||
|
@ -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
|
||||
|
@ -2,35 +2,35 @@ ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 513 size: 27837
|
||||
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.183000 pts: 0.183000 pos: 72083 size: 209
|
||||
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
|
||||
|
Loading…
Reference in New Issue
Block a user