Commit 871b641b authored by David Conrad's avatar David Conrad

Ensure that we write clusters and blocks with known size when streaming

Too many demuxers can't cope with clusters of unknown size.

Originally committed as revision 22201 to svn://svn.ffmpeg.org/ffmpeg/trunk
parent 434a70b8
...@@ -62,6 +62,7 @@ typedef struct { ...@@ -62,6 +62,7 @@ typedef struct {
} mkv_cues; } mkv_cues;
typedef struct MatroskaMuxContext { typedef struct MatroskaMuxContext {
ByteIOContext *dyn_bc;
ebml_master segment; ebml_master segment;
int64_t segment_offset; int64_t segment_offset;
int64_t segment_uid; int64_t segment_uid;
...@@ -760,10 +761,9 @@ static int ass_get_duration(const uint8_t *p) ...@@ -760,10 +761,9 @@ static int ass_get_duration(const uint8_t *p)
return end - start; return end - start;
} }
static int mkv_write_ass_blocks(AVFormatContext *s, AVPacket *pkt) static int mkv_write_ass_blocks(AVFormatContext *s, ByteIOContext *pb, AVPacket *pkt)
{ {
MatroskaMuxContext *mkv = s->priv_data; MatroskaMuxContext *mkv = s->priv_data;
ByteIOContext *pb = s->pb;
int i, layer = 0, max_duration = 0, size, line_size, data_size = pkt->size; int i, layer = 0, max_duration = 0, size, line_size, data_size = pkt->size;
uint8_t *start, *end, *data = pkt->data; uint8_t *start, *end, *data = pkt->data;
ebml_master blockgroup; ebml_master blockgroup;
...@@ -806,10 +806,10 @@ static int mkv_write_ass_blocks(AVFormatContext *s, AVPacket *pkt) ...@@ -806,10 +806,10 @@ static int mkv_write_ass_blocks(AVFormatContext *s, AVPacket *pkt)
return max_duration; return max_duration;
} }
static void mkv_write_block(AVFormatContext *s, unsigned int blockid, AVPacket *pkt, int flags) static void mkv_write_block(AVFormatContext *s, ByteIOContext *pb,
unsigned int blockid, AVPacket *pkt, int flags)
{ {
MatroskaMuxContext *mkv = s->priv_data; MatroskaMuxContext *mkv = s->priv_data;
ByteIOContext *pb = s->pb;
AVCodecContext *codec = s->streams[pkt->stream_index]->codec; AVCodecContext *codec = s->streams[pkt->stream_index]->codec;
uint8_t *data = NULL; uint8_t *data = NULL;
int size = pkt->size; int size = pkt->size;
...@@ -832,6 +832,21 @@ static void mkv_write_block(AVFormatContext *s, unsigned int blockid, AVPacket * ...@@ -832,6 +832,21 @@ static void mkv_write_block(AVFormatContext *s, unsigned int blockid, AVPacket *
av_free(data); av_free(data);
} }
static void mkv_flush_dynbuf(AVFormatContext *s)
{
MatroskaMuxContext *mkv = s->priv_data;
int bufsize;
uint8_t *dyn_buf;
if (!mkv->dyn_bc)
return;
bufsize = url_close_dyn_buf(mkv->dyn_bc, &dyn_buf);
put_buffer(s->pb, dyn_buf, bufsize);
av_free(dyn_buf);
mkv->dyn_bc = NULL;
}
static int mkv_write_packet(AVFormatContext *s, AVPacket *pkt) static int mkv_write_packet(AVFormatContext *s, AVPacket *pkt)
{ {
MatroskaMuxContext *mkv = s->priv_data; MatroskaMuxContext *mkv = s->priv_data;
...@@ -841,11 +856,17 @@ static int mkv_write_packet(AVFormatContext *s, AVPacket *pkt) ...@@ -841,11 +856,17 @@ static int mkv_write_packet(AVFormatContext *s, AVPacket *pkt)
int duration = pkt->duration; int duration = pkt->duration;
int ret; int ret;
if (url_is_streamed(s->pb)) {
if (!mkv->dyn_bc)
url_open_dyn_buf(&mkv->dyn_bc);
pb = mkv->dyn_bc;
}
if (!mkv->cluster_pos) { if (!mkv->cluster_pos) {
ret = mkv_add_seekhead_entry(mkv->cluster_seekhead, MATROSKA_ID_CLUSTER, url_ftell(pb)); ret = mkv_add_seekhead_entry(mkv->cluster_seekhead, MATROSKA_ID_CLUSTER, url_ftell(pb));
if (ret < 0) return ret; if (ret < 0) return ret;
mkv->cluster_pos = url_ftell(pb); mkv->cluster_pos = url_ftell(s->pb);
mkv->cluster = start_ebml_master(pb, MATROSKA_ID_CLUSTER, 0); mkv->cluster = start_ebml_master(pb, MATROSKA_ID_CLUSTER, 0);
put_ebml_uint(pb, MATROSKA_ID_CLUSTERTIMECODE, pkt->pts); put_ebml_uint(pb, MATROSKA_ID_CLUSTERTIMECODE, pkt->pts);
mkv->cluster_pts = pkt->pts; mkv->cluster_pts = pkt->pts;
...@@ -853,13 +874,13 @@ static int mkv_write_packet(AVFormatContext *s, AVPacket *pkt) ...@@ -853,13 +874,13 @@ static int mkv_write_packet(AVFormatContext *s, AVPacket *pkt)
} }
if (codec->codec_type != CODEC_TYPE_SUBTITLE) { if (codec->codec_type != CODEC_TYPE_SUBTITLE) {
mkv_write_block(s, MATROSKA_ID_SIMPLEBLOCK, pkt, keyframe << 7); mkv_write_block(s, pb, MATROSKA_ID_SIMPLEBLOCK, pkt, keyframe << 7);
} else if (codec->codec_id == CODEC_ID_SSA) { } else if (codec->codec_id == CODEC_ID_SSA) {
duration = mkv_write_ass_blocks(s, pkt); duration = mkv_write_ass_blocks(s, pb, pkt);
} else { } else {
ebml_master blockgroup = start_ebml_master(pb, MATROSKA_ID_BLOCKGROUP, mkv_blockgroup_size(pkt->size)); ebml_master blockgroup = start_ebml_master(pb, MATROSKA_ID_BLOCKGROUP, mkv_blockgroup_size(pkt->size));
duration = pkt->convergence_duration; duration = pkt->convergence_duration;
mkv_write_block(s, MATROSKA_ID_BLOCK, pkt, 0); mkv_write_block(s, pb, MATROSKA_ID_BLOCK, pkt, 0);
put_ebml_uint(pb, MATROSKA_ID_BLOCKDURATION, duration); put_ebml_uint(pb, MATROSKA_ID_BLOCKDURATION, duration);
end_ebml_master(pb, blockgroup); end_ebml_master(pb, blockgroup);
} }
...@@ -869,12 +890,15 @@ static int mkv_write_packet(AVFormatContext *s, AVPacket *pkt) ...@@ -869,12 +890,15 @@ static int mkv_write_packet(AVFormatContext *s, AVPacket *pkt)
if (ret < 0) return ret; if (ret < 0) return ret;
} }
// start a new cluster every 5 MB or 5 sec // start a new cluster every 5 MB or 5 sec, or 32k / 1 sec for streaming
if (url_ftell(pb) > mkv->cluster_pos + 5*1024*1024 || pkt->pts > mkv->cluster_pts + 5000) { if (url_is_streamed(s->pb) && (url_ftell(pb) > 32*1024 || pkt->pts > mkv->cluster_pts + 1000)
|| url_ftell(pb) > mkv->cluster_pos + 5*1024*1024 || pkt->pts > mkv->cluster_pts + 5000) {
av_log(s, AV_LOG_DEBUG, "Starting new cluster at offset %" PRIu64 av_log(s, AV_LOG_DEBUG, "Starting new cluster at offset %" PRIu64
" bytes, pts %" PRIu64 "\n", url_ftell(pb), pkt->pts); " bytes, pts %" PRIu64 "\n", url_ftell(pb), pkt->pts);
end_ebml_master(pb, mkv->cluster); end_ebml_master(pb, mkv->cluster);
mkv->cluster_pos = 0; mkv->cluster_pos = 0;
if (mkv->dyn_bc)
mkv_flush_dynbuf(s);
} }
mkv->duration = FFMAX(mkv->duration, pkt->pts + duration); mkv->duration = FFMAX(mkv->duration, pkt->pts + duration);
...@@ -888,7 +912,12 @@ static int mkv_write_trailer(AVFormatContext *s) ...@@ -888,7 +912,12 @@ static int mkv_write_trailer(AVFormatContext *s)
int64_t currentpos, second_seekhead, cuespos; int64_t currentpos, second_seekhead, cuespos;
int ret; int ret;
if (mkv->dyn_bc) {
end_ebml_master(mkv->dyn_bc, mkv->cluster);
mkv_flush_dynbuf(s);
} else if (mkv->cluster_pos) {
end_ebml_master(pb, mkv->cluster); end_ebml_master(pb, mkv->cluster);
}
if (!url_is_streamed(pb)) { if (!url_is_streamed(pb)) {
cuespos = mkv_write_cues(pb, mkv->cues, s->nb_streams); cuespos = mkv_write_cues(pb, mkv->cues, s->nb_streams);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment