From patchwork Tue Nov 1 01:11:01 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Matthew Gregan X-Patchwork-Id: 1244 Delivered-To: ffmpegpatchwork@gmail.com Received: by 10.103.90.1 with SMTP id o1csp422357vsb; Mon, 31 Oct 2016 18:11:15 -0700 (PDT) X-Received: by 10.194.179.170 with SMTP id dh10mr30079718wjc.94.1477962675161; Mon, 31 Oct 2016 18:11:15 -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 f81si27854552wmd.82.2016.10.31.18.11.14; Mon, 31 Oct 2016 18:11:15 -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=@flim.org; 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 Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 6AC54689C10; Tue, 1 Nov 2016 03:11:09 +0200 (EET) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from flim.org (flim.org [65.99.223.158]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 6643B689BC8 for ; Tue, 1 Nov 2016 03:11:02 +0200 (EET) Received: from localhost (unknown [121.98.48.5]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by flim.org (Postfix) with ESMTPSA id 7F01614364 for ; Tue, 1 Nov 2016 01:11:03 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=flim.org; s=default; t=1477962664; bh=0bYUETYmMuuEhlK8Zy5aQ4x/eFbpKjF57jNjUtfSru0=; h=Date:From:To:Subject:References:In-Reply-To:From; b=iy3+Z+GBJPleplv5Bc86NfGhQxwXr9cWNILk8/H79RZ+jaAJxjybMJc8EDQOecNGD Wnxl8pc1OWnKWmBCwwrAk9xELR3pdL/iegrnbhINGoMvhdpb3NsHUOXnL2LcXyCqL4 5PhwyQiwfnNLga/c+MGcWVsa4adoet/rqflCscVM= Date: Tue, 1 Nov 2016 14:11:01 +1300 From: Matthew Gregan To: FFmpeg development discussions and patches Message-ID: <20161101011100.GA8366@brak.lan> Mail-Followup-To: FFmpeg development discussions and patches References: <82396c770b2569fa6b0398e311a58e5c6fa39fa3.1477894999.git.kinetik@flim.org> <26d88c9d-a385-f246-2f2a-6900ab7e0a89@gmail.com> MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: <26d88c9d-a385-f246-2f2a-6900ab7e0a89@gmail.com> User-Agent: Mutt/1.5.23 (2014-03-12) Subject: Re: [FFmpeg-devel] [PATCH 1/2] Add experimental muxing support for FLAC in ISO BMFF (MP4). 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 Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" At 2016-10-31T11:04:16-0300, James Almer wrote: > > +static int mov_write_dfla_tag(AVIOContext *pb, MOVTrack *track) > > +{ > > + const size_t FLAC_STREAMINFO_SIZE = 34; > > + int64_t pos = avio_tell(pb); > > + avio_wb32(pb, 0); > > + ffio_wfourcc(pb, "dfLa"); > > + avio_w8(pb, 0); /* version */ > > + avio_wb24(pb, 0); /* flags */ > > + > > + /* Expect the encoder to pass a METADATA_BLOCK_TYPE_STREAMINFO. */ > > The encoder may (or most likely will) also pass an updated streaminfo as > packet side data. See the flac muxer, you'll have to do the same here. Thanks. It looks like libavcodec/flacenc.c#flac_encode_frame updates the extradata at the same time it emits the packet side data, so I'm slightly confused why this is needed. Seems to be easy to handle by extending the existing case for AV_CODEC_ID_MP4ALS in mov_write_single_packet. That assumes pkt->size == 0, which seems to be true when the packet side data is emitted in flac_encode_frame. Updated patch attached. From ba197e6e9df3916f7dd433736c580b27f3c6ca75 Mon Sep 17 00:00:00 2001 Message-Id: From: Matthew Gregan Date: Thu, 20 Oct 2016 17:28:11 +1300 Subject: [PATCH 1/2] Add experimental muxing support for FLAC in ISO BMFF (MP4). Based on the draft spec at https://git.xiph.org/?p=flac.git;a=blob;f=doc/isoflac.txt '-strict -2' is required to create files in this format. Signed-off-by: Matthew Gregan --- libavformat/isom.c | 2 ++ libavformat/movenc.c | 46 +++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 45 insertions(+), 3 deletions(-) diff --git a/libavformat/isom.c b/libavformat/isom.c index ab79e22..aacbe43 100644 --- a/libavformat/isom.c +++ b/libavformat/isom.c @@ -60,6 +60,7 @@ const AVCodecTag ff_mp4_obj_type[] = { { AV_CODEC_ID_EAC3 , 0xA6 }, { AV_CODEC_ID_DTS , 0xA9 }, /* mp4ra.org */ { AV_CODEC_ID_VP9 , 0xC0 }, /* nonstandard, update when there is a standard value */ + { AV_CODEC_ID_FLAC , 0xC1 }, /* nonstandard, update when there is a standard value */ { AV_CODEC_ID_TSCC2 , 0xD0 }, /* nonstandard, camtasia uses it */ { AV_CODEC_ID_VORBIS , 0xDD }, /* nonstandard, gpac uses it */ { AV_CODEC_ID_DVD_SUBTITLE, 0xE0 }, /* nonstandard, see unsupported-embedded-subs-2.mp4 */ @@ -345,6 +346,7 @@ const AVCodecTag ff_codec_movaudio_tags[] = { { AV_CODEC_ID_WMAV2, MKTAG('W', 'M', 'A', '2') }, { AV_CODEC_ID_EVRC, MKTAG('s', 'e', 'v', 'c') }, /* 3GPP2 */ { AV_CODEC_ID_SMV, MKTAG('s', 's', 'm', 'v') }, /* 3GPP2 */ + { AV_CODEC_ID_FLAC, MKTAG('f', 'L', 'a', 'C') }, /* nonstandard */ { AV_CODEC_ID_NONE, 0 }, }; diff --git a/libavformat/movenc.c b/libavformat/movenc.c index 6228192..0a6ffb0 100644 --- a/libavformat/movenc.c +++ b/libavformat/movenc.c @@ -654,6 +654,27 @@ static int mov_write_wfex_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *tra return update_size(pb, pos); } +static int mov_write_dfla_tag(AVIOContext *pb, MOVTrack *track) +{ + const size_t FLAC_STREAMINFO_SIZE = 34; + int64_t pos = avio_tell(pb); + avio_wb32(pb, 0); + ffio_wfourcc(pb, "dfLa"); + avio_w8(pb, 0); /* version */ + avio_wb24(pb, 0); /* flags */ + + /* Expect the encoder to pass a METADATA_BLOCK_TYPE_STREAMINFO. */ + if (track->par->extradata_size != FLAC_STREAMINFO_SIZE) + return AVERROR_INVALIDDATA; + + /* TODO: Write other METADATA_BLOCK_TYPEs if the encoder makes them available. */ + avio_w8(pb, 1 << 7 | 0); /* LastMetadataBlockFlag << 7 | BlockType (STREAMINFO) */ + avio_wb24(pb, track->par->extradata_size); /* Length */ + avio_write(pb, track->par->extradata, track->par->extradata_size); /* BlockData[Length] */ + + return update_size(pb, pos); +} + static int mov_write_chan_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *track) { uint32_t layout_tag, bitmap; @@ -963,8 +984,13 @@ static int mov_write_audio_tag(AVFormatContext *s, AVIOContext *pb, MOVMuxContex avio_wb16(pb, 16); avio_wb16(pb, track->audio_vbr ? -2 : 0); /* compression ID */ } else { /* reserved for mp4/3gp */ - avio_wb16(pb, 2); - avio_wb16(pb, 16); + if (track->par->codec_id == AV_CODEC_ID_FLAC) { + avio_wb16(pb, track->par->channels); + avio_wb16(pb, av_get_bytes_per_sample(track->par->format) * 8); + } else { + avio_wb16(pb, 2); + avio_wb16(pb, 16); + } avio_wb16(pb, 0); } @@ -1009,6 +1035,8 @@ static int mov_write_audio_tag(AVFormatContext *s, AVIOContext *pb, MOVMuxContex mov_write_extradata_tag(pb, track); else if (track->par->codec_id == AV_CODEC_ID_WMAPRO) mov_write_wfex_tag(s, pb, track); + else if (track->par->codec_id == AV_CODEC_ID_FLAC) + mov_write_dfla_tag(pb, track); else if (track->vos_len > 0) mov_write_glbl_tag(pb, track); @@ -1177,6 +1205,7 @@ static int mp4_get_codec_tag(AVFormatContext *s, MOVTrack *track) else if (track->par->codec_id == AV_CODEC_ID_DIRAC) tag = MKTAG('d','r','a','c'); else if (track->par->codec_id == AV_CODEC_ID_MOV_TEXT) tag = MKTAG('t','x','3','g'); else if (track->par->codec_id == AV_CODEC_ID_VC1) tag = MKTAG('v','c','-','1'); + else if (track->par->codec_id == AV_CODEC_ID_FLAC) tag = MKTAG('f','L','a','C'); else if (track->par->codec_type == AVMEDIA_TYPE_VIDEO) tag = MKTAG('m','p','4','v'); else if (track->par->codec_type == AVMEDIA_TYPE_AUDIO) tag = MKTAG('m','p','4','a'); else if (track->par->codec_id == AV_CODEC_ID_DVD_SUBTITLE) tag = MKTAG('m','p','4','s'); @@ -5019,7 +5048,8 @@ static int mov_write_single_packet(AVFormatContext *s, AVPacket *pkt) trk->start_cts = 0; } - if (trk->par->codec_id == AV_CODEC_ID_MP4ALS) { + if (trk->par->codec_id == AV_CODEC_ID_MP4ALS || + trk->par->codec_id == AV_CODEC_ID_FLAC) { int side_size = 0; uint8_t *side = av_packet_get_side_data(pkt, AV_PKT_DATA_NEW_EXTRADATA, &side_size); if (side && side_size > 0 && (side_size != par->extradata_size || memcmp(side, par->extradata, side_size))) { @@ -5733,6 +5763,16 @@ static int mov_init(AVFormatContext *s) i, track->par->sample_rate); } } + if (track->mode == MODE_MP4 && + track->par->codec_id == AV_CODEC_ID_FLAC) { + if (s->strict_std_compliance > FF_COMPLIANCE_EXPERIMENTAL) { + av_log(s, AV_LOG_ERROR, + "FLAC in MP4 support is experimental, add " + "'-strict %d' if you want to use it.\n", + FF_COMPLIANCE_EXPERIMENTAL); + return AVERROR_EXPERIMENTAL; + } + } } else if (st->codecpar->codec_type == AVMEDIA_TYPE_SUBTITLE) { track->timescale = st->time_base.den; } else if (st->codecpar->codec_type == AVMEDIA_TYPE_DATA) { -- 2.10.1