This is disabled by default when the empty_moov flag is enabled --- libavformat/dashenc.c | 43 +++++++++++++++++++- libavformat/movenc.c | 107 +++++++++++++++++++++++++++++++++++++++----------- 2 files changed, 124 insertions(+), 26 deletions(-)
diff --git a/libavformat/dashenc.c b/libavformat/dashenc.c index 0848052..534fa75 100644 --- a/libavformat/dashenc.c +++ b/libavformat/dashenc.c @@ -551,7 +551,7 @@ static int write_manifest(AVFormatContext *s, int final) return avpriv_io_move(temp_filename, s->filename); } -static int dash_write_header(AVFormatContext *s) +static int dash_init(AVFormatContext *s) { DASHContext *c = s->priv_data; int ret = 0, i; @@ -643,7 +643,7 @@ static int dash_write_header(AVFormatContext *s) os->init_start_pos = 0; av_dict_set(&opts, "movflags", "frag_custom+dash+delay_moov", 0); - if ((ret = avformat_write_header(ctx, &opts)) < 0) + if ((ret = avformat_init_output(ctx, &opts)) < 0) return ret; os->ctx_inited = 1; avio_flush(ctx->pb); @@ -682,6 +682,20 @@ static int dash_write_header(AVFormatContext *s) av_log(s, AV_LOG_WARNING, "no video stream and no min seg duration set\n"); return AVERROR(EINVAL); } + return 0; +} + +static int dash_write_header(AVFormatContext *s) +{ + DASHContext *c = s->priv_data; + int i, ret; + for (i = 0; i < s->nb_streams; i++) { + OutputStream *os = &c->streams[i]; + if ((ret = avformat_write_header(os->ctx, NULL)) < 0) { + dash_free(s); + return ret; + } + } ret = write_manifest(s, 0); if (!ret) av_log(s, AV_LOG_VERBOSE, "Manifest written to: %s\n", s->filename); @@ -978,6 +992,29 @@ static int dash_write_trailer(AVFormatContext *s) return 0; } +static int dash_check_bitstream(struct AVFormatContext *s, const AVPacket *avpkt) +{ + DASHContext *c = s->priv_data; + OutputStream *os = &c->streams[avpkt->stream_index]; + AVFormatContext *oc = os->ctx; + if (oc->oformat->check_bitstream) { + int ret; + AVPacket pkt = *avpkt; + pkt.stream_index = 0; + ret = oc->oformat->check_bitstream(oc, &pkt); + if (ret == 1) { + AVStream *st = s->streams[avpkt->stream_index]; + AVStream *ost = oc->streams[0]; + st->internal->bsfcs = ost->internal->bsfcs; + st->internal->nb_bsfcs = ost->internal->nb_bsfcs; + ost->internal->bsfcs = NULL; + ost->internal->nb_bsfcs = 0; + } + return ret; + } + return 1; +} + #define OFFSET(x) offsetof(DASHContext, x) #define E AV_OPT_FLAG_ENCODING_PARAM static const AVOption options[] = { @@ -1008,10 +1045,12 @@ AVOutputFormat ff_dash_muxer = { .audio_codec = AV_CODEC_ID_AAC, .video_codec = AV_CODEC_ID_H264, .flags = AVFMT_GLOBALHEADER | AVFMT_NOFILE | AVFMT_TS_NEGATIVE, + .init = dash_init, .write_header = dash_write_header, .write_packet = dash_write_packet, .write_trailer = dash_write_trailer, .deinit = dash_free, .codec_tag = (const AVCodecTag* const []){ ff_mp4_obj_type, 0 }, + .check_bitstream = dash_check_bitstream, .priv_class = &dash_class, }; diff --git a/libavformat/movenc.c b/libavformat/movenc.c index 1fe1eb6..93f52f2 100644 --- a/libavformat/movenc.c +++ b/libavformat/movenc.c @@ -5415,11 +5415,10 @@ static int mov_create_dvd_sub_decoder_specific_info(MOVTrack *track, return 0; } -static int mov_write_header(AVFormatContext *s) +static int mov_init(AVFormatContext *s) { - AVIOContext *pb = s->pb; MOVMuxContext *mov = s->priv_data; - AVDictionaryEntry *t, *global_tcr = av_dict_get(s->metadata, "timecode", NULL, 0); + AVDictionaryEntry *global_tcr = av_dict_get(s->metadata, "timecode", NULL, 0); int i, ret, hint_track = 0, tmcd_track = 0; mov->fc = s; @@ -5456,6 +5455,11 @@ static int mov_write_header(AVFormatContext *s) mov->flags |= FF_MOV_FLAG_FRAGMENT | FF_MOV_FLAG_EMPTY_MOOV | FF_MOV_FLAG_DEFAULT_BASE_MOOF; + if (mov->flags & FF_MOV_FLAG_EMPTY_MOOV && s->flags & AVFMT_FLAG_AUTO_BSF) { + av_log(s, AV_LOG_VERBOSE, "Empty MOOV enabled; disabling automatic bitstream filtering\n"); + s->flags &= ~AVFMT_FLAG_AUTO_BSF; + } + if (mov->flags & FF_MOV_FLAG_FASTSTART) { mov->reserved_moov_size = -1; } @@ -5502,11 +5506,6 @@ static int mov_write_header(AVFormatContext *s) return AVERROR(EINVAL); } - if (!(mov->flags & FF_MOV_FLAG_DELAY_MOOV)) { - if ((ret = mov_write_identification(pb, s)) < 0) - return ret; - } - mov->nb_streams = s->nb_streams; if (mov->mode & (MODE_MP4|MODE_MOV|MODE_IPOD) && s->nb_chapters) mov->chapter_track = mov->nb_streams++; @@ -5529,7 +5528,7 @@ static int mov_write_header(AVFormatContext *s) /* +1 tmcd track for each video stream with a timecode */ for (i = 0; i < s->nb_streams; i++) { AVStream *st = s->streams[i]; - t = global_tcr; + AVDictionaryEntry *t = global_tcr; if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && (t || (t=av_dict_get(st->metadata, "timecode", NULL, 0)))) { AVTimecode tc; @@ -5705,6 +5704,48 @@ static int mov_write_header(AVFormatContext *s) avpriv_set_pts_info(st, 64, 1, track->timescale); + if (mov->encryption_scheme == MOV_ENC_CENC_AES_CTR) { + ret = ff_mov_cenc_init(&track->cenc, mov->encryption_key, + track->par->codec_id == AV_CODEC_ID_H264, s->flags & AVFMT_FLAG_BITEXACT); + if (ret) + return ret; + } + } + + enable_tracks(s); + return 0; +} + +static int mov_write_header(AVFormatContext *s) +{ + AVIOContext *pb = s->pb; + MOVMuxContext *mov = s->priv_data; + AVDictionaryEntry *t, *global_tcr = av_dict_get(s->metadata, "timecode", NULL, 0); + int i, ret, hint_track = 0, tmcd_track = 0, nb_tracks = s->nb_streams; + + if (mov->mode & (MODE_MP4|MODE_MOV|MODE_IPOD) && s->nb_chapters) + nb_tracks++; + + if (mov->flags & FF_MOV_FLAG_RTP_HINT) { + /* Add hint tracks for each audio and video stream */ + hint_track = nb_tracks; + for (i = 0; i < s->nb_streams; i++) { + AVStream *st = s->streams[i]; + if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO || + st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) { + nb_tracks++; + } + } + } + + if (mov->mode == MODE_MOV || mov->mode == MODE_MP4) + tmcd_track = nb_tracks; + + for (i = 0; i < s->nb_streams; i++) { + int j; + AVStream *st= s->streams[i]; + MOVTrack *track= &mov->tracks[i]; + /* copy extradata if it exists */ if (st->codecpar->extradata_size) { if (st->codecpar->codec_id == AV_CODEC_ID_DVD_SUBTITLE) @@ -5719,19 +5760,6 @@ static int mov_write_header(AVFormatContext *s) } } - if (mov->encryption_scheme == MOV_ENC_CENC_AES_CTR) { - ret = ff_mov_cenc_init(&track->cenc, mov->encryption_key, - track->par->codec_id == AV_CODEC_ID_H264, s->flags & AVFMT_FLAG_BITEXACT); - if (ret) - return ret; - } - } - - for (i = 0; i < s->nb_streams; i++) { - int j; - AVStream *st= s->streams[i]; - MOVTrack *track= &mov->tracks[i]; - if (st->codecpar->codec_type != AVMEDIA_TYPE_AUDIO || track->par->channel_layout != AV_CH_LAYOUT_MONO) continue; @@ -5752,8 +5780,10 @@ static int mov_write_header(AVFormatContext *s) } } - enable_tracks(s); - + if (!(mov->flags & FF_MOV_FLAG_DELAY_MOOV)) { + if ((ret = mov_write_identification(pb, s)) < 0) + return ret; + } if (mov->reserved_moov_size){ mov->reserved_header_pos = avio_tell(pb); @@ -6085,6 +6115,19 @@ static int mov_write_trailer(AVFormatContext *s) return res; } +static int mov_check_bitstream(struct AVFormatContext *s, const AVPacket *pkt) +{ + int ret = 1; + AVStream *st = s->streams[pkt->stream_index]; + + if (st->codecpar->codec_id == AV_CODEC_ID_AAC) { + if (pkt->size > 2 && (AV_RB16(pkt->data) & 0xfff0) == 0xfff0) + ret = ff_stream_add_bitstream_filter(st, "aac_adtstoasc", NULL); + } + + return ret; +} + #if CONFIG_MOV_MUXER MOV_CLASS(mov) AVOutputFormat ff_mov_muxer = { @@ -6095,6 +6138,7 @@ AVOutputFormat ff_mov_muxer = { .audio_codec = AV_CODEC_ID_AAC, .video_codec = CONFIG_LIBX264_ENCODER ? AV_CODEC_ID_H264 : AV_CODEC_ID_MPEG4, + .init = mov_init, .write_header = mov_write_header, .write_packet = mov_write_packet, .write_trailer = mov_write_trailer, @@ -6103,6 +6147,7 @@ AVOutputFormat ff_mov_muxer = { .codec_tag = (const AVCodecTag* const []){ ff_codec_movvideo_tags, ff_codec_movaudio_tags, 0 }, + .check_bitstream = mov_check_bitstream, .priv_class = &mov_muxer_class, }; #endif @@ -6115,12 +6160,14 @@ AVOutputFormat ff_tgp_muxer = { .priv_data_size = sizeof(MOVMuxContext), .audio_codec = AV_CODEC_ID_AMR_NB, .video_codec = AV_CODEC_ID_H263, + .init = mov_init, .write_header = mov_write_header, .write_packet = mov_write_packet, .write_trailer = mov_write_trailer, .deinit = mov_free, .flags = AVFMT_GLOBALHEADER | AVFMT_ALLOW_FLUSH | AVFMT_TS_NEGATIVE, .codec_tag = (const AVCodecTag* const []){ codec_3gp_tags, 0 }, + .check_bitstream = mov_check_bitstream, .priv_class = &tgp_muxer_class, }; #endif @@ -6135,12 +6182,14 @@ AVOutputFormat ff_mp4_muxer = { .audio_codec = AV_CODEC_ID_AAC, .video_codec = CONFIG_LIBX264_ENCODER ? AV_CODEC_ID_H264 : AV_CODEC_ID_MPEG4, + .init = mov_init, .write_header = mov_write_header, .write_packet = mov_write_packet, .write_trailer = mov_write_trailer, .deinit = mov_free, .flags = AVFMT_GLOBALHEADER | AVFMT_ALLOW_FLUSH | AVFMT_TS_NEGATIVE, .codec_tag = (const AVCodecTag* const []){ ff_mp4_obj_type, 0 }, + .check_bitstream = mov_check_bitstream, .priv_class = &mp4_muxer_class, }; #endif @@ -6154,12 +6203,14 @@ AVOutputFormat ff_psp_muxer = { .audio_codec = AV_CODEC_ID_AAC, .video_codec = CONFIG_LIBX264_ENCODER ? AV_CODEC_ID_H264 : AV_CODEC_ID_MPEG4, + .init = mov_init, .write_header = mov_write_header, .write_packet = mov_write_packet, .write_trailer = mov_write_trailer, .deinit = mov_free, .flags = AVFMT_GLOBALHEADER | AVFMT_ALLOW_FLUSH | AVFMT_TS_NEGATIVE, .codec_tag = (const AVCodecTag* const []){ ff_mp4_obj_type, 0 }, + .check_bitstream = mov_check_bitstream, .priv_class = &psp_muxer_class, }; #endif @@ -6172,12 +6223,14 @@ AVOutputFormat ff_tg2_muxer = { .priv_data_size = sizeof(MOVMuxContext), .audio_codec = AV_CODEC_ID_AMR_NB, .video_codec = AV_CODEC_ID_H263, + .init = mov_init, .write_header = mov_write_header, .write_packet = mov_write_packet, .write_trailer = mov_write_trailer, .deinit = mov_free, .flags = AVFMT_GLOBALHEADER | AVFMT_ALLOW_FLUSH | AVFMT_TS_NEGATIVE, .codec_tag = (const AVCodecTag* const []){ codec_3gp_tags, 0 }, + .check_bitstream = mov_check_bitstream, .priv_class = &tg2_muxer_class, }; #endif @@ -6191,12 +6244,14 @@ AVOutputFormat ff_ipod_muxer = { .priv_data_size = sizeof(MOVMuxContext), .audio_codec = AV_CODEC_ID_AAC, .video_codec = AV_CODEC_ID_H264, + .init = mov_init, .write_header = mov_write_header, .write_packet = mov_write_packet, .write_trailer = mov_write_trailer, .deinit = mov_free, .flags = AVFMT_GLOBALHEADER | AVFMT_ALLOW_FLUSH | AVFMT_TS_NEGATIVE, .codec_tag = (const AVCodecTag* const []){ codec_ipod_tags, 0 }, + .check_bitstream = mov_check_bitstream, .priv_class = &ipod_muxer_class, }; #endif @@ -6210,12 +6265,14 @@ AVOutputFormat ff_ismv_muxer = { .priv_data_size = sizeof(MOVMuxContext), .audio_codec = AV_CODEC_ID_AAC, .video_codec = AV_CODEC_ID_H264, + .init = mov_init, .write_header = mov_write_header, .write_packet = mov_write_packet, .write_trailer = mov_write_trailer, .deinit = mov_free, .flags = AVFMT_GLOBALHEADER | AVFMT_ALLOW_FLUSH | AVFMT_TS_NEGATIVE, .codec_tag = (const AVCodecTag* const []){ ff_mp4_obj_type, 0 }, + .check_bitstream = mov_check_bitstream, .priv_class = &ismv_muxer_class, }; #endif @@ -6229,12 +6286,14 @@ AVOutputFormat ff_f4v_muxer = { .priv_data_size = sizeof(MOVMuxContext), .audio_codec = AV_CODEC_ID_AAC, .video_codec = AV_CODEC_ID_H264, + .init = mov_init, .write_header = mov_write_header, .write_packet = mov_write_packet, .write_trailer = mov_write_trailer, .deinit = mov_free, .flags = AVFMT_GLOBALHEADER | AVFMT_ALLOW_FLUSH, .codec_tag = (const AVCodecTag* const []){ codec_f4v_tags, 0 }, + .check_bitstream = mov_check_bitstream, .priv_class = &f4v_muxer_class, }; #endif -- 2.10.0 _______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel