--- libavformat/dashenc.c | 43 +++++++++++++++++++- libavformat/movenc-test.c | 3 ++ libavformat/movenc.c | 100 +++++++++++++++++++++++++++++++++++----------- 3 files changed, 121 insertions(+), 25 deletions(-)
diff --git a/libavformat/dashenc.c b/libavformat/dashenc.c index dce5525..4e66caa 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; @@ -617,6 +617,7 @@ static int dash_write_header(AVFormatContext *s) ctx->opaque = s->opaque; ctx->io_close = s->io_close; ctx->io_open = s->io_open; + av_dict_set(&opts, "fflags", "-autobsf", 0); if (!(st = avformat_new_stream(ctx, NULL))) return AVERROR(ENOMEM); @@ -644,7 +645,8 @@ 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) + av_dict_set(&opts, "fflags", "-autobsf", 0); + if ((ret = avformat_init_output(ctx, &opts)) < 0) return ret; os->ctx_inited = 1; avio_flush(ctx->pb); @@ -683,6 +685,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); @@ -979,6 +995,27 @@ 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->bsfc = ost->internal->bsfc; + ost->internal->bsfc = NULL; + } + return ret; + } + return 1; +} + #define OFFSET(x) offsetof(DASHContext, x) #define E AV_OPT_FLAG_ENCODING_PARAM static const AVOption options[] = { @@ -1009,10 +1046,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-test.c b/libavformat/movenc-test.c index 8c69c76..7aeedb5 100644 --- a/libavformat/movenc-test.c +++ b/libavformat/movenc-test.c @@ -475,6 +475,7 @@ int main(int argc, char **argv) init_out("empty-moov-header"); av_dict_set(&opts, "movflags", "frag_keyframe+empty_moov", 0); av_dict_set(&opts, "use_editlist", "0", 0); + av_dict_set(&opts, "fflags", "-autobsf", 0); init(0, 0); close_out(); memcpy(header, hash, HASH_SIZE); @@ -498,6 +499,7 @@ int main(int argc, char **argv) init_out("delay-moov-header"); av_dict_set(&opts, "movflags", "frag_custom+delay_moov", 0); av_dict_set(&opts, "use_editlist", "0", 0); + av_dict_set(&opts, "fflags", "-autobsf", 0); init(0, 0); check(out_size == 0, "Output written during init with delay_moov"); mux_gops(1); // Write 1 second of content @@ -534,6 +536,7 @@ int main(int argc, char **argv) av_dict_set(&opts, "fragment_index", "2", 0); av_dict_set(&opts, "avoid_negative_ts", "0", 0); av_dict_set(&opts, "use_editlist", "0", 0); + av_dict_set(&opts, "fflags", "-autobsf", 0); init(0, 0); skip_gops(1); init_out("empty-moov-second-frag-discont"); diff --git a/libavformat/movenc.c b/libavformat/movenc.c index 3146799..94acf1e 100644 --- a/libavformat/movenc.c +++ b/libavformat/movenc.c @@ -5086,11 +5086,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; @@ -5173,11 +5172,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++; @@ -5361,6 +5355,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->enc->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->codec->codec_type == AVMEDIA_TYPE_VIDEO || + st->codec->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->codec->extradata_size) { if (st->codec->codec_id == AV_CODEC_ID_DVD_SUBTITLE) @@ -5375,19 +5411,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->enc->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->codec->codec_type != AVMEDIA_TYPE_AUDIO || track->enc->channel_layout != AV_CH_LAYOUT_MONO) continue; @@ -5408,8 +5431,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); @@ -5721,6 +5746,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->codec->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 = { @@ -5731,6 +5769,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, @@ -5739,6 +5778,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 @@ -5751,12 +5791,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 @@ -5771,12 +5813,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 @@ -5790,12 +5834,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 @@ -5808,12 +5854,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 @@ -5827,12 +5875,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 @@ -5846,12 +5896,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 @@ -5865,12 +5917,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.7.3 _______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel