[FFmpeg-devel] [PATCH 1/2] Add experimental muxing support for FLAC in ISO BMFF (MP4).

James Almer jamrial at gmail.com
Fri Nov 18 03:57:49 EET 2016


On 11/1/2016 8:21 PM, Matthew Gregan wrote:
> At 2016-11-01T00:56:45-0300, James Almer wrote:
>> > The muxer gets the extradata as created by the encoder only during init().
>> > Even if the encoder changes it in any way afterwards, it will never make
>> > it to the muxer. That's why packet side data is used for this.
>> > 
>> > The reason the encoder used the AVCodecContext extradata to store the
>> > updated Streaminfo before creating the packet side data is most likely
>> > because it was an already allocated buffer. Technically, it's not the
>> > "proper" thing to do, but it also doesn't seem to make a difference.
> Makes sense, thanks for the explanation.
> 
> Updated patch attached with the following changes:
> - Uses libavcodec/flac.h for the FLAC_STREAMINFO_SIZE and
>   FLAC_METADATA_TYPE_STREAMINFO definitions, per the feedback on the demuxer
>   patch.
> - Fixes the sample size in bits written to the 'fLaC' audio box.
>   Thanks to Vittorio Giovara for pointing this out.
> 
> 
> 0001-Add-experimental-muxing-support-for-FLAC-in-ISO-BMFF.patch
> 
> 
> From e08e1b5041a331d640d190c39c00bdc61e81243c Mon Sep 17 00:00:00 2001
> From: Matthew Gregan <kinetik at flim.org>
> 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 <kinetik at flim.org>
> ---
>  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 */

This is enables muxing into mov, which bypasses the experimental check below
since mov isn't MODE_MP4.

>      { AV_CODEC_ID_NONE, 0 },
>  };
>  
> diff --git a/libavformat/movenc.c b/libavformat/movenc.c
> index 6228192..06f6dc6 100644
> --- a/libavformat/movenc.c
> +++ b/libavformat/movenc.c
> @@ -33,6 +33,7 @@
>  #include "avc.h"
>  #include "libavcodec/ac3_parser.h"
>  #include "libavcodec/dnxhddata.h"
> +#include "libavcodec/flac.h"
>  #include "libavcodec/get_bits.h"
>  #include "libavcodec/put_bits.h"
>  #include "libavcodec/vc1_common.h"
> @@ -654,6 +655,26 @@ 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)
> +{
> +    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 | FLAC_METADATA_TYPE_STREAMINFO); /* LastMetadataBlockFlag << 7 | BlockType */
> +    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, track->par->bits_per_raw_sample);
> +            } 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
> 
> 
> 
> _______________________________________________
> ffmpeg-devel mailing list
> ffmpeg-devel at ffmpeg.org
> http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
> 



More information about the ffmpeg-devel mailing list