[FFmpeg-devel] [PATCH 1/2] Add experimental muxing support for FLAC in ISO BMFF (MP4).
James Almer
jamrial at gmail.com
Mon Oct 31 16:04:16 EET 2016
On 10/31/2016 3:27 AM, Matthew Gregan wrote:
> 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 <kinetik at flim.org>
> ---
> 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. */
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.
> + 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) {
>
More information about the ffmpeg-devel
mailing list