[FFmpeg-devel] Implement muxing AAC in a CAFF container

Submitted by Lewis Fox on Nov. 10, 2018, 3:58 a.m.

Details

Message ID 20181110035841.96238-1-LRFLEW.Coll@gmail.com
State New
Headers show

Commit Message

Lewis Fox Nov. 10, 2018, 3:58 a.m.
From: Lewis Fox <LRFLEW@aol.com>

Signed-off-by: Lewis Fox <LRFLEW@aol.com>
---
 libavformat/cafenc.c   | 61 ++++++++++++++++++++++++++++++++++++------
 libavformat/mov.c      |  1 +
 libavformat/mov_esds.c |  1 -
 3 files changed, 54 insertions(+), 9 deletions(-)

Patch hide | download patch | download mbox

diff --git a/libavformat/cafenc.c b/libavformat/cafenc.c
index 0f7c4ebbb3..0eb3c27ad6 100644
--- a/libavformat/cafenc.c
+++ b/libavformat/cafenc.c
@@ -83,6 +83,8 @@  static uint32_t samples_per_packet(enum AVCodecID codec_id, int channels, int bl
         return 384;
     case AV_CODEC_ID_OPUS:
         return 960;
+    case AV_CODEC_ID_AAC:
+        return 1024;
     case AV_CODEC_ID_MP2:
     case AV_CODEC_ID_MP3:
         return 1152;
@@ -102,10 +104,57 @@  static uint32_t samples_per_packet(enum AVCodecID codec_id, int channels, int bl
     }
 }
 
+static void put_descr(AVIOContext *pb, int tag, unsigned int size)
+{
+    int i = 3;
+    avio_w8(pb, tag);
+    for (; i > 0; i--)
+        avio_w8(pb, (size >> (7 * i)) | 0x80);
+    avio_w8(pb, size & 0x7F);
+}
+
+static void caf_write_aac_kuki(AVIOContext *pb, AVStream *stream) {
+    AVCodecParameters *par = stream->codecpar;
+    int decoder_specific_info_len = par->extradata_size ? 5 + par->extradata_size : 0;
+
+    ffio_wfourcc(pb, "kuki");
+    avio_wb64(pb, 5 + 3 + 5 + 13 + decoder_specific_info_len + 5 + 1); // size
+
+    // ES descriptor
+    put_descr(pb, MP4ESDescrTag, 3 + 5 + 13 + decoder_specific_info_len + 5 + 1);
+    avio_wb16(pb, 0);
+    avio_w8(pb, 0x00); // flags (= no flags)
+
+    // DecoderConfig descriptor
+    put_descr(pb, MP4DecConfigDescrTag, 13 + decoder_specific_info_len);
+
+    // Object type indication
+    avio_w8(pb, ff_codec_get_tag(ff_mp4_obj_type, par->codec_id));
+
+    // the following fields is made of 6 bits to identify the streamtype (5 for audio)
+    // plus 1 bit to indicate upstream and 1 bit set to 1 (reserved)
+    avio_w8(pb, 0x15); // flags (= Audiostream)
+
+    avio_wb24(pb, 6144); // Buffersize DB
+    avio_wb32(pb, par->bit_rate); // max bitrate (FIXME should be max rate in any 1 sec window)
+    avio_wb32(pb, par->bit_rate); // average bitrate (target bitrate, or 0 for VBR)
+
+    if (par->extradata_size) {
+        // DecoderSpecific info descriptor
+        put_descr(pb, MP4DecSpecificDescrTag, par->extradata_size);
+        avio_write(pb, par->extradata, par->extradata_size);
+    }
+
+    // SL descriptor
+    put_descr(pb, MP4SLDescrTag, 1);
+    avio_w8(pb, 0x02);
+}
+
 static int caf_write_header(AVFormatContext *s)
 {
     AVIOContext *pb = s->pb;
-    AVCodecParameters *par = s->streams[0]->codecpar;
+    AVStream *stream = s->streams[0];
+    AVCodecParameters *par = stream->codecpar;
     CAFContext *caf = s->priv_data;
     AVDictionaryEntry *t = NULL;
     unsigned int codec_tag = ff_codec_get_tag(ff_codec_caf_tags, par->codec_id);
@@ -117,12 +166,6 @@  static int caf_write_header(AVFormatContext *s)
         return AVERROR(EINVAL);
     }
 
-    switch (par->codec_id) {
-    case AV_CODEC_ID_AAC:
-        av_log(s, AV_LOG_ERROR, "muxing codec currently unsupported\n");
-        return AVERROR_PATCHWELCOME;
-    }
-
     if (par->codec_id == AV_CODEC_ID_OPUS && par->channels > 2) {
         av_log(s, AV_LOG_ERROR, "Only mono and stereo are supported for Opus\n");
         return AVERROR_INVALIDDATA;
@@ -161,7 +204,9 @@  static int caf_write_header(AVFormatContext *s)
         ff_mov_write_chan(pb, par->channel_layout);
     }
 
-    if (par->codec_id == AV_CODEC_ID_ALAC) {
+    if (par->codec_id == AV_CODEC_ID_AAC) {
+        caf_write_aac_kuki(pb, stream);
+    } else if (par->codec_id == AV_CODEC_ID_ALAC) {
         ffio_wfourcc(pb, "kuki");
         avio_wb64(pb, 12 + par->extradata_size);
         avio_write(pb, "\0\0\0\14frmaalac", 12);
diff --git a/libavformat/mov.c b/libavformat/mov.c
index ec57a05803..f5f04d6ba6 100644
--- a/libavformat/mov.c
+++ b/libavformat/mov.c
@@ -776,6 +776,7 @@  static int mov_read_hdlr(MOVContext *c, AVIOContext *pb, MOVAtom atom)
 
 static int mov_read_esds(MOVContext *c, AVIOContext *pb, MOVAtom atom)
 {
+    avio_rb32(pb); /* version + flags */
     return ff_mov_read_esds(c->fc, pb);
 }
 
diff --git a/libavformat/mov_esds.c b/libavformat/mov_esds.c
index a444d969c6..ae7f4b6cbf 100644
--- a/libavformat/mov_esds.c
+++ b/libavformat/mov_esds.c
@@ -29,7 +29,6 @@  int ff_mov_read_esds(AVFormatContext *fc, AVIOContext *pb)
         return 0;
     st = fc->streams[fc->nb_streams-1];
 
-    avio_rb32(pb); /* version + flags */
     ff_mp4_read_descr(fc, pb, &tag);
     if (tag == MP4ESDescrTag) {
         ff_mp4_parse_es_descr(pb, NULL);