From patchwork Sat Sep 10 04:37:21 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Rodger Combs X-Patchwork-Id: 511 Delivered-To: ffmpegpatchwork@gmail.com Received: by 10.103.140.134 with SMTP id o128csp631921vsd; Fri, 9 Sep 2016 21:39:05 -0700 (PDT) X-Received: by 10.28.156.16 with SMTP id f16mr1174849wme.56.1473482344943; Fri, 09 Sep 2016 21:39:04 -0700 (PDT) Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org. [79.124.17.100]) by mx.google.com with ESMTP id py14si5926721wjb.249.2016.09.09.21.39.00; Fri, 09 Sep 2016 21:39:04 -0700 (PDT) Received-SPF: pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) client-ip=79.124.17.100; Authentication-Results: mx.google.com; dkim=neutral (body hash did not verify) header.i=@gmail.com; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org; dmarc=fail (p=NONE dis=NONE) header.from=gmail.com Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 06B96689EBA; Sat, 10 Sep 2016 07:38:05 +0300 (EEST) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mail-oi0-f66.google.com (mail-oi0-f66.google.com [209.85.218.66]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 3796C689E9C for ; Sat, 10 Sep 2016 07:37:56 +0300 (EEST) Received: by mail-oi0-f66.google.com with SMTP id 2so13232043oif.2 for ; Fri, 09 Sep 2016 21:38:07 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=from:to:subject:date:message-id:in-reply-to:references; bh=foCXiIM0iL0atrSpzVkhylNc+4fTiziYN75I0gCAVh4=; b=lHL64gVvPNjRs/VQnPaOoBhW4SWSA+0Bx2QQjlL+76kXL6ZK4g7h+Krvoy0rkPrrBs z9OwtDt4RarozIO5QIu1xKmhHqFeSN4B2ywOt5dhCnPMkKVPEGimKfmYk2zCDjFaXMF4 lWXYXOxWswYMpmxiy5Y6DZQxFuTtDN9Iz/EqFT7KEQzyO2SxlQgN3CRkwHSfIdHH9o4P kkgecaKcNEiqQrEz+DGTmyBLTw1mCACXS2p8PA1zOcgMTDyxnjhmyJK2INejc6C9rqsI qzEpcz1lYeovT8/qvVTcp34d9Y+JNmVILBcdA4gLnEsqoVbKSJocl3MrcRT+Elc44/9Q 1Zng== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:subject:date:message-id:in-reply-to :references; bh=foCXiIM0iL0atrSpzVkhylNc+4fTiziYN75I0gCAVh4=; b=HLPa9HQhJji8xz9PUzZj5ZgbBC4o28kl2RxRAx3WShBL+zfXIjxUennXFkkY1mYlX1 YBqpXLse+1uDfifZ6K2E/SapnbcBB/oex+nU+QBzRrRiAzur5G+qDE/N0OKGvSQv9iJl QuG0bPCBhr+7KU+Q59zUaic1mxYafjsnqiaXPSudoabQUCYTps8MzxPXD7a72Q4vnpL2 5GIpsi/krrlI4o0GO/CupumCI5viGHFdPkYiniPMmNyeKJlyElANW5ibd9DFtCxRPLmx NxK6AjFsc+ZSuntxzXXtxUbrpZopKbJWH50L2BIzHntR3Idn5PRCznBtQh2rw9rLScIM LJRA== X-Gm-Message-State: AE9vXwNByFFszrK2ND/+4gLWfJkkKwB6I68XJn1xJQ4IuVC7x6i7rFyJjQZmiKBg2mvojw== X-Received: by 10.202.244.73 with SMTP id s70mr1536307oih.43.1473482285587; Fri, 09 Sep 2016 21:38:05 -0700 (PDT) Received: from Rodgers-MacBook-Pro.local.net (c-73-209-137-129.hsd1.il.comcast.net. [73.209.137.129]) by smtp.gmail.com with ESMTPSA id s185sm3616106ita.21.2016.09.09.21.38.04 for (version=TLS1 cipher=AES128-SHA bits=128/128); Fri, 09 Sep 2016 21:38:05 -0700 (PDT) From: Rodger Combs To: ffmpeg-devel@ffmpeg.org Date: Fri, 9 Sep 2016 23:37:21 -0500 Message-Id: <20160910043725.98484-7-rodger.combs@gmail.com> X-Mailer: git-send-email 2.10.0 In-Reply-To: <20160910043725.98484-1-rodger.combs@gmail.com> References: <20160910043725.98484-1-rodger.combs@gmail.com> Subject: [FFmpeg-devel] [PATCH 07/11] lavf/movenc+dashenc: add automatic bitstream filtering X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: FFmpeg development discussions and patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: FFmpeg development discussions and patches MIME-Version: 1.0 Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" 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