From patchwork Mon Oct 31 06:27:36 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Matthew Gregan X-Patchwork-Id: 1238 Delivered-To: ffmpegpatchwork@gmail.com Received: by 10.103.90.1 with SMTP id o1csp216013vsb; Sun, 30 Oct 2016 23:27:51 -0700 (PDT) X-Received: by 10.28.68.131 with SMTP id r125mr8514148wma.28.1477895271587; Sun, 30 Oct 2016 23:27:51 -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 z13si22447837wmz.143.2016.10.30.23.27.51; Sun, 30 Oct 2016 23:27:51 -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 35F8F687ED3; Mon, 31 Oct 2016 08:27:45 +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 F0586687EBB for ; Mon, 31 Oct 2016 08:27:37 +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 D365114178 for ; Mon, 31 Oct 2016 06:27:38 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=flim.org; s=default; t=1477895259; bh=n7dTD9m0VrjEgCUP8T9NLBaeEUtgxmduB6XrHiJdbtw=; h=Date:From:To:Subject:From; b=FkNVaDCYrdPLWcNt9fBRYvQPV9H52f7HEkD2DnvuNGvchi7wNRES78G/xSEeMpSNi e9/Jr1iFQOdlBQJToOHE7tGlDMXGgfjzNfL87AEiAloIuTLX/UVjwjIT5lkiisQMPE 4SlYw2zgbs8iFEyHX598cSMWOVwPcJa85KV14NbM= Date: Mon, 31 Oct 2016 19:27:36 +1300 From: Matthew Gregan To: ffmpeg-devel@ffmpeg.org Message-ID: <82396c770b2569fa6b0398e311a58e5c6fa39fa3.1477894999.git.kinetik@flim.org> Mail-Followup-To: ffmpeg-devel@ffmpeg.org MIME-Version: 1.0 Content-Disposition: inline User-Agent: Mutt/1.5.23 (2014-03-12) Subject: [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" 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 | 43 +++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 43 insertions(+), 2 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..d77250e 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'); @@ -5733,6 +5762,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) {