movenc: Support setting fragment_index before the moov atom is written

This way, the caller doesn't need to coordinate setting the option
after the moov atom has been written. The downside is that it is
no longer possible to use the option for checking whether the moov
atom already has been written, but a caller is able to keep track
of that by other means anyway.

Signed-off-by: Martin Storsjö <martin@martin.st>
pull/125/head
Martin Storsjö 10 years ago
parent 0c5e380c2c
commit 448c8cfe4c
  1. 17
      libavformat/movenc.c
  2. 1
      libavformat/movenc.h

@ -72,7 +72,7 @@ static const AVOption options[] = {
{ "ism_lookahead", "Number of lookahead entries for ISM files", offsetof(MOVMuxContext, ism_lookahead), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM}, { "ism_lookahead", "Number of lookahead entries for ISM files", offsetof(MOVMuxContext, ism_lookahead), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM},
{ "brand", "Override major brand", offsetof(MOVMuxContext, major_brand), AV_OPT_TYPE_STRING, {.str = NULL}, .flags = AV_OPT_FLAG_ENCODING_PARAM }, { "brand", "Override major brand", offsetof(MOVMuxContext, major_brand), AV_OPT_TYPE_STRING, {.str = NULL}, .flags = AV_OPT_FLAG_ENCODING_PARAM },
{ "use_editlist", "use edit list", offsetof(MOVMuxContext, use_editlist), AV_OPT_TYPE_INT, {.i64 = -1}, -1, 1, AV_OPT_FLAG_ENCODING_PARAM}, { "use_editlist", "use edit list", offsetof(MOVMuxContext, use_editlist), AV_OPT_TYPE_INT, {.i64 = -1}, -1, 1, AV_OPT_FLAG_ENCODING_PARAM},
{ "fragment_index", "Fragment number of the next fragment", offsetof(MOVMuxContext, fragments), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM}, { "fragment_index", "Fragment number of the next fragment", offsetof(MOVMuxContext, fragments), AV_OPT_TYPE_INT, {.i64 = 1}, 1, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM},
{ NULL }, { NULL },
}; };
@ -3119,7 +3119,7 @@ static int mov_flush_fragment(AVFormatContext *s)
if (!(mov->flags & FF_MOV_FLAG_FRAGMENT)) if (!(mov->flags & FF_MOV_FLAG_FRAGMENT))
return 0; return 0;
if (mov->fragments == 0) { if (!mov->moov_written) {
int64_t pos = avio_tell(s->pb); int64_t pos = avio_tell(s->pb);
int ret; int ret;
AVIOContext *moov_buf; AVIOContext *moov_buf;
@ -3148,7 +3148,7 @@ static int mov_flush_fragment(AVFormatContext *s)
if (mov->flags & FF_MOV_FLAG_FASTSTART) if (mov->flags & FF_MOV_FLAG_FASTSTART)
mov->reserved_moov_pos = avio_tell(s->pb); mov->reserved_moov_pos = avio_tell(s->pb);
avio_flush(s->pb); avio_flush(s->pb);
mov->fragments++; mov->moov_written = 1;
return 0; return 0;
} }
@ -3159,7 +3159,7 @@ static int mov_flush_fragment(AVFormatContext *s)
avio_write(s->pb, buf, buf_size); avio_write(s->pb, buf, buf_size);
av_free(buf); av_free(buf);
mov->fragments++; mov->moov_written = 1;
mov->mdat_size = 0; mov->mdat_size = 0;
for (i = 0; i < mov->nb_streams; i++) { for (i = 0; i < mov->nb_streams; i++) {
if (mov->tracks[i].entry) if (mov->tracks[i].entry)
@ -3237,12 +3237,13 @@ static int mov_flush_fragment(AVFormatContext *s)
static int mov_auto_flush_fragment(AVFormatContext *s) static int mov_auto_flush_fragment(AVFormatContext *s)
{ {
MOVMuxContext *mov = s->priv_data; MOVMuxContext *mov = s->priv_data;
int had_moov = mov->moov_written;
int ret = mov_flush_fragment(s); int ret = mov_flush_fragment(s);
if (ret < 0) if (ret < 0)
return ret; return ret;
// If using delay_moov, the first flush only wrote the moov, // If using delay_moov, the first flush only wrote the moov,
// not the actual moof+mdat pair, thus flush once again. // not the actual moof+mdat pair, thus flush once again.
if (mov->fragments == 1 && mov->flags & FF_MOV_FLAG_DELAY_MOOV) if (!had_moov && mov->flags & FF_MOV_FLAG_DELAY_MOOV)
ret = mov_flush_fragment(s); ret = mov_flush_fragment(s);
return ret; return ret;
} }
@ -3259,7 +3260,7 @@ int ff_mov_write_packet(AVFormatContext *s, AVPacket *pkt)
if (mov->flags & FF_MOV_FLAG_FRAGMENT) { if (mov->flags & FF_MOV_FLAG_FRAGMENT) {
int ret; int ret;
if (mov->fragments > 0 || mov->flags & FF_MOV_FLAG_EMPTY_MOOV) { if (mov->moov_written || mov->flags & FF_MOV_FLAG_EMPTY_MOOV) {
if (!trk->mdat_buf) { if (!trk->mdat_buf) {
if ((ret = avio_open_dyn_buf(&trk->mdat_buf)) < 0) if ((ret = avio_open_dyn_buf(&trk->mdat_buf)) < 0)
return ret; return ret;
@ -3391,7 +3392,7 @@ int ff_mov_write_packet(AVFormatContext *s, AVPacket *pkt)
trk->frag_start = pkt->dts; trk->frag_start = pkt->dts;
trk->start_dts = 0; trk->start_dts = 0;
trk->frag_discont = 0; trk->frag_discont = 0;
} else if (pkt->dts && mov->fragments >= 1) } else if (pkt->dts && mov->moov_written)
av_log(s, AV_LOG_WARNING, av_log(s, AV_LOG_WARNING,
"Track %d starts with a nonzero dts %"PRId64", while the moov " "Track %d starts with a nonzero dts %"PRId64", while the moov "
"already has been written. Set the delay_moov flag to handle " "already has been written. Set the delay_moov flag to handle "
@ -3898,7 +3899,7 @@ static int mov_write_header(AVFormatContext *s)
if (mov->flags & FF_MOV_FLAG_EMPTY_MOOV && if (mov->flags & FF_MOV_FLAG_EMPTY_MOOV &&
!(mov->flags & FF_MOV_FLAG_DELAY_MOOV)) { !(mov->flags & FF_MOV_FLAG_DELAY_MOOV)) {
mov_write_moov_tag(pb, mov, s); mov_write_moov_tag(pb, mov, s);
mov->fragments++; mov->moov_written = 1;
if (mov->flags & FF_MOV_FLAG_FASTSTART) if (mov->flags & FF_MOV_FLAG_FASTSTART)
mov->reserved_moov_pos = avio_tell(pb); mov->reserved_moov_pos = avio_tell(pb);
} }

@ -155,6 +155,7 @@ typedef struct MOVMuxContext {
int iods_video_profile; int iods_video_profile;
int iods_audio_profile; int iods_audio_profile;
int moov_written;
int fragments; int fragments;
int max_fragment_duration; int max_fragment_duration;
int min_fragment_duration; int min_fragment_duration;

Loading…
Cancel
Save