Merge commit '2cb9c2fc59c9267ad2631c07c81c188058502259'
* commit '2cb9c2fc59c9267ad2631c07c81c188058502259': movenc: Allow interleaving samples when writing fragmented files Conflicts: libavformat/movenc.c libavformat/movenc.h Merged-by: Michael Niedermayer <michaelni@gmx.at>
This commit is contained in:
		@@ -81,6 +81,7 @@ static const AVOption options[] = {
 | 
				
			|||||||
    { "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 = 1}, 1, 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},
 | 
				
			||||||
    { "mov_gamma", "gamma value for gama atom", offsetof(MOVMuxContext, gamma), AV_OPT_TYPE_FLOAT, {.dbl = 0.0 }, 0.0, 10, AV_OPT_FLAG_ENCODING_PARAM},
 | 
					    { "mov_gamma", "gamma value for gama atom", offsetof(MOVMuxContext, gamma), AV_OPT_TYPE_FLOAT, {.dbl = 0.0 }, 0.0, 10, AV_OPT_FLAG_ENCODING_PARAM},
 | 
				
			||||||
 | 
					    { "frag_interleave", "Interleave samples within fragments (max number of consecutive samples, lower is tighter interleaving, but with more overhead)", offsetof(MOVMuxContext, frag_interleave), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM },
 | 
				
			||||||
    { NULL },
 | 
					    { NULL },
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -4056,6 +4057,32 @@ static void mov_parse_vc1_frame(AVPacket *pkt, MOVTrack *trk)
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int mov_flush_fragment_interleaving(AVFormatContext *s, MOVTrack *track)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    MOVMuxContext *mov = s->priv_data;
 | 
				
			||||||
 | 
					    int ret, buf_size;
 | 
				
			||||||
 | 
					    uint8_t *buf;
 | 
				
			||||||
 | 
					    int i, offset;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (!track->mdat_buf)
 | 
				
			||||||
 | 
					        return 0;
 | 
				
			||||||
 | 
					    if (!mov->mdat_buf) {
 | 
				
			||||||
 | 
					        if ((ret = avio_open_dyn_buf(&mov->mdat_buf)) < 0)
 | 
				
			||||||
 | 
					            return ret;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    buf_size = avio_close_dyn_buf(track->mdat_buf, &buf);
 | 
				
			||||||
 | 
					    track->mdat_buf = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    offset = avio_tell(mov->mdat_buf);
 | 
				
			||||||
 | 
					    avio_write(mov->mdat_buf, buf, buf_size);
 | 
				
			||||||
 | 
					    av_free(buf);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    for (i = track->entries_flushed; i < track->entry; i++)
 | 
				
			||||||
 | 
					        track->cluster[i].pos += offset;
 | 
				
			||||||
 | 
					    track->entries_flushed = track->entry;
 | 
				
			||||||
 | 
					    return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int mov_flush_fragment(AVFormatContext *s)
 | 
					static int mov_flush_fragment(AVFormatContext *s)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    MOVMuxContext *mov = s->priv_data;
 | 
					    MOVMuxContext *mov = s->priv_data;
 | 
				
			||||||
@@ -4115,14 +4142,28 @@ static int mov_flush_fragment(AVFormatContext *s)
 | 
				
			|||||||
        return 0;
 | 
					        return 0;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (mov->frag_interleave) {
 | 
				
			||||||
        for (i = 0; i < mov->nb_streams; i++) {
 | 
					        for (i = 0; i < mov->nb_streams; i++) {
 | 
				
			||||||
            MOVTrack *track = &mov->tracks[i];
 | 
					            MOVTrack *track = &mov->tracks[i];
 | 
				
			||||||
        if (mov->flags & FF_MOV_FLAG_SEPARATE_MOOF)
 | 
					            int ret;
 | 
				
			||||||
 | 
					            if ((ret = mov_flush_fragment_interleaving(s, track)) < 0)
 | 
				
			||||||
 | 
					                return ret;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (!mov->mdat_buf)
 | 
				
			||||||
 | 
					            return 0;
 | 
				
			||||||
 | 
					        mdat_size = avio_tell(mov->mdat_buf);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    for (i = 0; i < mov->nb_streams; i++) {
 | 
				
			||||||
 | 
					        MOVTrack *track = &mov->tracks[i];
 | 
				
			||||||
 | 
					        if (mov->flags & FF_MOV_FLAG_SEPARATE_MOOF || mov->frag_interleave)
 | 
				
			||||||
            track->data_offset = 0;
 | 
					            track->data_offset = 0;
 | 
				
			||||||
        else
 | 
					        else
 | 
				
			||||||
            track->data_offset = mdat_size;
 | 
					            track->data_offset = mdat_size;
 | 
				
			||||||
        if (!track->mdat_buf)
 | 
					        if (!track->entry)
 | 
				
			||||||
            continue;
 | 
					            continue;
 | 
				
			||||||
 | 
					        if (track->mdat_buf)
 | 
				
			||||||
            mdat_size += avio_tell(track->mdat_buf);
 | 
					            mdat_size += avio_tell(track->mdat_buf);
 | 
				
			||||||
        if (first_track < 0)
 | 
					        if (first_track < 0)
 | 
				
			||||||
            first_track = i;
 | 
					            first_track = i;
 | 
				
			||||||
@@ -4162,10 +4203,18 @@ static int mov_flush_fragment(AVFormatContext *s)
 | 
				
			|||||||
        if (track->entry)
 | 
					        if (track->entry)
 | 
				
			||||||
            track->frag_start += duration;
 | 
					            track->frag_start += duration;
 | 
				
			||||||
        track->entry = 0;
 | 
					        track->entry = 0;
 | 
				
			||||||
 | 
					        track->entries_flushed = 0;
 | 
				
			||||||
 | 
					        if (!mov->frag_interleave) {
 | 
				
			||||||
            if (!track->mdat_buf)
 | 
					            if (!track->mdat_buf)
 | 
				
			||||||
                continue;
 | 
					                continue;
 | 
				
			||||||
            buf_size = avio_close_dyn_buf(track->mdat_buf, &buf);
 | 
					            buf_size = avio_close_dyn_buf(track->mdat_buf, &buf);
 | 
				
			||||||
            track->mdat_buf = NULL;
 | 
					            track->mdat_buf = NULL;
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            if (!mov->mdat_buf)
 | 
				
			||||||
 | 
					                continue;
 | 
				
			||||||
 | 
					            buf_size = avio_close_dyn_buf(mov->mdat_buf, &buf);
 | 
				
			||||||
 | 
					            mov->mdat_buf = NULL;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        avio_write(s->pb, buf, buf_size);
 | 
					        avio_write(s->pb, buf, buf_size);
 | 
				
			||||||
        av_free(buf);
 | 
					        av_free(buf);
 | 
				
			||||||
@@ -4219,6 +4268,13 @@ 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->moov_written || mov->flags & FF_MOV_FLAG_EMPTY_MOOV) {
 | 
					        if (mov->moov_written || mov->flags & FF_MOV_FLAG_EMPTY_MOOV) {
 | 
				
			||||||
 | 
					            if (mov->frag_interleave && mov->fragments > 0) {
 | 
				
			||||||
 | 
					                if (trk->entry - trk->entries_flushed >= mov->frag_interleave) {
 | 
				
			||||||
 | 
					                    if ((ret = mov_flush_fragment_interleaving(s, trk)) < 0)
 | 
				
			||||||
 | 
					                        return ret;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            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;
 | 
				
			||||||
@@ -4882,6 +4938,21 @@ static int mov_write_header(AVFormatContext *s)
 | 
				
			|||||||
    if (!mov->use_editlist && s->avoid_negative_ts == AVFMT_AVOID_NEG_TS_AUTO)
 | 
					    if (!mov->use_editlist && s->avoid_negative_ts == AVFMT_AVOID_NEG_TS_AUTO)
 | 
				
			||||||
        s->avoid_negative_ts = AVFMT_AVOID_NEG_TS_MAKE_ZERO;
 | 
					        s->avoid_negative_ts = AVFMT_AVOID_NEG_TS_MAKE_ZERO;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* Clear the omit_tfhd_offset flag if default_base_moof is set;
 | 
				
			||||||
 | 
					     * if the latter is set that's enough and omit_tfhd_offset doesn't
 | 
				
			||||||
 | 
					     * add anything extra on top of that. */
 | 
				
			||||||
 | 
					    if (mov->flags & FF_MOV_FLAG_OMIT_TFHD_OFFSET &&
 | 
				
			||||||
 | 
					        mov->flags & FF_MOV_FLAG_DEFAULT_BASE_MOOF)
 | 
				
			||||||
 | 
					        mov->flags &= ~FF_MOV_FLAG_OMIT_TFHD_OFFSET;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (mov->frag_interleave &&
 | 
				
			||||||
 | 
					        mov->flags & (FF_MOV_FLAG_OMIT_TFHD_OFFSET | FF_MOV_FLAG_SEPARATE_MOOF)) {
 | 
				
			||||||
 | 
					        av_log(s, AV_LOG_ERROR,
 | 
				
			||||||
 | 
					               "Sample interleaving in fragments is mutually exclusive with "
 | 
				
			||||||
 | 
					               "omit_tfhd_offset and separate_moof\n");
 | 
				
			||||||
 | 
					        return AVERROR(EINVAL);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* Non-seekable output is ok if using fragmentation. If ism_lookahead
 | 
					    /* Non-seekable output is ok if using fragmentation. If ism_lookahead
 | 
				
			||||||
     * is enabled, we don't support non-seekable output at all. */
 | 
					     * is enabled, we don't support non-seekable output at all. */
 | 
				
			||||||
    if (!s->pb->seekable &&
 | 
					    if (!s->pb->seekable &&
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -131,6 +131,7 @@ typedef struct MOVTrack {
 | 
				
			|||||||
    int64_t     data_offset;
 | 
					    int64_t     data_offset;
 | 
				
			||||||
    int64_t     frag_start;
 | 
					    int64_t     frag_start;
 | 
				
			||||||
    int         frag_discont;
 | 
					    int         frag_discont;
 | 
				
			||||||
 | 
					    int         entries_flushed;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    int         nb_frag_info;
 | 
					    int         nb_frag_info;
 | 
				
			||||||
    MOVFragmentInfo *frag_info;
 | 
					    MOVFragmentInfo *frag_info;
 | 
				
			||||||
@@ -189,6 +190,8 @@ typedef struct MOVMuxContext {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    int use_editlist;
 | 
					    int use_editlist;
 | 
				
			||||||
    float gamma;
 | 
					    float gamma;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    int frag_interleave;
 | 
				
			||||||
} MOVMuxContext;
 | 
					} MOVMuxContext;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define FF_MOV_FLAG_RTP_HINT              (1 <<  0)
 | 
					#define FF_MOV_FLAG_RTP_HINT              (1 <<  0)
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user