Commit d68adbd6 authored by Michael Niedermayer's avatar Michael Niedermayer

Merge commit 'f8ef91ff'

* commit 'f8ef91ff':
  movenc: add faststart option for web streaming

Conflicts:
	doc/muxers.texi
	libavformat/movenc.c
	libavformat/movenc.h
Merged-by: 's avatarMichael Niedermayer <michaelni@gmx.at>
parents 221a99aa f8ef91ff
...@@ -451,8 +451,8 @@ pair for each track, making it easier to separate tracks. ...@@ -451,8 +451,8 @@ pair for each track, making it easier to separate tracks.
This option is implicitly set when writing ismv (Smooth Streaming) files. This option is implicitly set when writing ismv (Smooth Streaming) files.
@item -movflags faststart @item -movflags faststart
Run a second pass moving the moov atom on top of the file. This Run a second pass moving the index (moov atom) to the beginning of the file.
operation can take a while, and will not work in various situations such This operation can take a while, and will not work in various situations such
as fragmented output, thus it is not enabled by default. as fragmented output, thus it is not enabled by default.
@item -movflags rtphint @item -movflags rtphint
Add RTP hinting tracks to the output file. Add RTP hinting tracks to the output file.
......
...@@ -52,7 +52,7 @@ static const AVOption options[] = { ...@@ -52,7 +52,7 @@ static const AVOption options[] = {
{ "separate_moof", "Write separate moof/mdat atoms for each track", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_SEPARATE_MOOF}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "movflags" }, { "separate_moof", "Write separate moof/mdat atoms for each track", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_SEPARATE_MOOF}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "movflags" },
{ "frag_custom", "Flush fragments on caller requests", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_FRAG_CUSTOM}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "movflags" }, { "frag_custom", "Flush fragments on caller requests", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_FRAG_CUSTOM}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "movflags" },
{ "isml", "Create a live smooth streaming feed (for pushing to a publishing point)", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_ISML}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "movflags" }, { "isml", "Create a live smooth streaming feed (for pushing to a publishing point)", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_ISML}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "movflags" },
{ "faststart", "Run a second pass to put the moov at the beginning of the file", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_FASTSTART}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "movflags" }, { "faststart", "Run a second pass to put the index (moov atom) at the beginning of the file", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_FASTSTART}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "movflags" },
FF_RTP_FLAG_OPTS(MOVMuxContext, rtp_flags), FF_RTP_FLAG_OPTS(MOVMuxContext, rtp_flags),
{ "skip_iods", "Skip writing iods atom.", offsetof(MOVMuxContext, iods_skip), AV_OPT_TYPE_INT, {.i64 = 1}, 0, 1, AV_OPT_FLAG_ENCODING_PARAM}, { "skip_iods", "Skip writing iods atom.", offsetof(MOVMuxContext, iods_skip), AV_OPT_TYPE_INT, {.i64 = 1}, 0, 1, AV_OPT_FLAG_ENCODING_PARAM},
{ "iods_audio_profile", "iods audio profile atom.", offsetof(MOVMuxContext, iods_audio_profile), AV_OPT_TYPE_INT, {.i64 = -1}, -1, 255, AV_OPT_FLAG_ENCODING_PARAM}, { "iods_audio_profile", "iods audio profile atom.", offsetof(MOVMuxContext, iods_audio_profile), AV_OPT_TYPE_INT, {.i64 = -1}, -1, 255, AV_OPT_FLAG_ENCODING_PARAM},
...@@ -74,6 +74,8 @@ static const AVClass flavor ## _muxer_class = {\ ...@@ -74,6 +74,8 @@ static const AVClass flavor ## _muxer_class = {\
.version = LIBAVUTIL_VERSION_INT,\ .version = LIBAVUTIL_VERSION_INT,\
}; };
static int get_moov_size(AVFormatContext *s);
//FIXME support 64 bit variant with wide placeholders //FIXME support 64 bit variant with wide placeholders
static int64_t update_size(AVIOContext *pb, int64_t pos) static int64_t update_size(AVIOContext *pb, int64_t pos)
{ {
...@@ -3003,21 +3005,6 @@ static void mov_parse_vc1_frame(AVPacket *pkt, MOVTrack *trk, int fragment) ...@@ -3003,21 +3005,6 @@ static void mov_parse_vc1_frame(AVPacket *pkt, MOVTrack *trk, int fragment)
} }
} }
static int get_moov_size(AVFormatContext *s)
{
int ret;
uint8_t *buf;
AVIOContext *moov_buf;
MOVMuxContext *mov = s->priv_data;
if ((ret = avio_open_dyn_buf(&moov_buf)) < 0)
return ret;
mov_write_moov_tag(moov_buf, mov, s);
ret = avio_close_dyn_buf(moov_buf, &buf);
av_free(buf);
return ret;
}
static int mov_flush_fragment(AVFormatContext *s) static int mov_flush_fragment(AVFormatContext *s)
{ {
MOVMuxContext *mov = s->priv_data; MOVMuxContext *mov = s->priv_data;
...@@ -3535,7 +3522,8 @@ static int mov_write_header(AVFormatContext *s) ...@@ -3535,7 +3522,8 @@ static int mov_write_header(AVFormatContext *s)
/* faststart: moov at the beginning of the file, if supported */ /* faststart: moov at the beginning of the file, if supported */
if (mov->flags & FF_MOV_FLAG_FASTSTART) { if (mov->flags & FF_MOV_FLAG_FASTSTART) {
if (mov->flags & FF_MOV_FLAG_FRAGMENT) if ((mov->flags & FF_MOV_FLAG_FRAGMENT) ||
(s->flags & AVFMT_FLAG_CUSTOM_IO))
mov->flags &= ~FF_MOV_FLAG_FASTSTART; mov->flags &= ~FF_MOV_FLAG_FASTSTART;
else else
mov->reserved_moov_size = -1; mov->reserved_moov_size = -1;
...@@ -3743,8 +3731,11 @@ static int mov_write_header(AVFormatContext *s) ...@@ -3743,8 +3731,11 @@ static int mov_write_header(AVFormatContext *s)
avio_skip(pb, mov->reserved_moov_size); avio_skip(pb, mov->reserved_moov_size);
} }
if (!(mov->flags & FF_MOV_FLAG_FRAGMENT)) if (!(mov->flags & FF_MOV_FLAG_FRAGMENT)) {
if (mov->flags & FF_MOV_FLAG_FASTSTART)
mov->reserved_moov_pos = avio_tell(pb);
mov_write_mdat_tag(pb, mov); mov_write_mdat_tag(pb, mov);
}
if (t = av_dict_get(s->metadata, "creation_time", NULL, 0)) if (t = av_dict_get(s->metadata, "creation_time", NULL, 0))
mov->time = ff_iso8601_to_unix_time(t->value); mov->time = ff_iso8601_to_unix_time(t->value);
...@@ -3801,11 +3792,26 @@ static int mov_write_header(AVFormatContext *s) ...@@ -3801,11 +3792,26 @@ static int mov_write_header(AVFormatContext *s)
return -1; return -1;
} }
/** static int get_moov_size(AVFormatContext *s)
{
int ret;
uint8_t *buf;
AVIOContext *moov_buf;
MOVMuxContext *mov = s->priv_data;
if ((ret = avio_open_dyn_buf(&moov_buf)) < 0)
return ret;
mov_write_moov_tag(moov_buf, mov, s);
ret = avio_close_dyn_buf(moov_buf, &buf);
av_free(buf);
return ret;
}
/*
* This function gets the moov size if moved to the top of the file: the chunk * This function gets the moov size if moved to the top of the file: the chunk
* offset table can switch between stco (32-bit entries) to co64 (64-bit * offset table can switch between stco (32-bit entries) to co64 (64-bit
* entries) when the moov is moved to the top, so the size of the moov would * entries) when the moov is moved to the beginning, so the size of the moov
* change. It also updates the chunk offset tables. * would change. It also updates the chunk offset tables.
*/ */
static int compute_moov_size(AVFormatContext *s) static int compute_moov_size(AVFormatContext *s)
{ {
...@@ -3823,7 +3829,7 @@ static int compute_moov_size(AVFormatContext *s) ...@@ -3823,7 +3829,7 @@ static int compute_moov_size(AVFormatContext *s)
if (moov_size2 < 0) if (moov_size2 < 0)
return moov_size2; return moov_size2;
/* if the size changed, we just switched from stco to co64 and needs to /* if the size changed, we just switched from stco to co64 and need to
* update the offsets */ * update the offsets */
if (moov_size2 != moov_size) if (moov_size2 != moov_size)
for (i = 0; i < mov->nb_streams; i++) for (i = 0; i < mov->nb_streams; i++)
...@@ -3926,9 +3932,9 @@ static int mov_write_trailer(AVFormatContext *s) ...@@ -3926,9 +3932,9 @@ static int mov_write_trailer(AVFormatContext *s)
} }
} }
moov_pos = avio_tell(pb);
if (!(mov->flags & FF_MOV_FLAG_FRAGMENT)) { if (!(mov->flags & FF_MOV_FLAG_FRAGMENT)) {
moov_pos = avio_tell(pb);
/* Write size of mdat tag */ /* Write size of mdat tag */
if (mov->mdat_size + 8 <= UINT32_MAX) { if (mov->mdat_size + 8 <= UINT32_MAX) {
avio_seek(pb, mov->mdat_pos, SEEK_SET); avio_seek(pb, mov->mdat_pos, SEEK_SET);
...@@ -3944,8 +3950,8 @@ static int mov_write_trailer(AVFormatContext *s) ...@@ -3944,8 +3950,8 @@ static int mov_write_trailer(AVFormatContext *s)
} }
avio_seek(pb, mov->reserved_moov_size > 0 ? mov->reserved_moov_pos : moov_pos, SEEK_SET); avio_seek(pb, mov->reserved_moov_size > 0 ? mov->reserved_moov_pos : moov_pos, SEEK_SET);
if (mov->reserved_moov_size == -1) { if (mov->flags & FF_MOV_FLAG_FASTSTART) {
av_log(s, AV_LOG_INFO, "Starting second pass: moving header on top of the file\n"); av_log(s, AV_LOG_INFO, "Starting second pass: moving the moov atom to the beginning of the file\n");
res = shift_data(s); res = shift_data(s);
if (res == 0) { if (res == 0) {
avio_seek(s->pb, mov->reserved_moov_pos, SEEK_SET); avio_seek(s->pb, mov->reserved_moov_pos, SEEK_SET);
......
...@@ -156,8 +156,6 @@ typedef struct MOVMuxContext { ...@@ -156,8 +156,6 @@ typedef struct MOVMuxContext {
int flags; int flags;
int rtp_flags; int rtp_flags;
int reserved_moov_size; ///< 0 for disabled, -1 for automatic, size otherwise
int64_t reserved_moov_pos;
int iods_skip; int iods_skip;
int iods_video_profile; int iods_video_profile;
...@@ -172,6 +170,9 @@ typedef struct MOVMuxContext { ...@@ -172,6 +170,9 @@ typedef struct MOVMuxContext {
int use_editlist; int use_editlist;
int video_track_timescale; int video_track_timescale;
int reserved_moov_size; ///< 0 for disabled, -1 for automatic, size otherwise
int64_t reserved_moov_pos;
} MOVMuxContext; } MOVMuxContext;
#define FF_MOV_FLAG_RTP_HINT 1 #define FF_MOV_FLAG_RTP_HINT 1
......
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