Merge commit '831018b0bbe26a603802a9022472f714a59293be'
[ffmpeg.git] / libavformat / latmenc.c
index ea13a8a..273197b 100644 (file)
@@ -2,20 +2,20 @@
  * LATM/LOAS muxer
  * Copyright (c) 2011 Kieran Kunhya <kieran@kunhya.com>
  *
- * This file is part of Libav.
+ * This file is part of FFmpeg.
  *
- * Libav is free software; you can redistribute it and/or
+ * FFmpeg is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
  * License as published by the Free Software Foundation; either
  * version 2.1 of the License, or (at your option) any later version.
  *
- * Libav is distributed in the hope that it will be useful,
+ * FFmpeg is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  * Lesser General Public License for more details.
  *
  * You should have received a copy of the GNU Lesser General Public
- * License along with Libav; if not, write to the Free Software
+ * License along with FFmpeg; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  */
 
 #include "libavcodec/mpeg4audio.h"
 #include "libavutil/opt.h"
 #include "avformat.h"
+#include "internal.h"
+#include "rawenc.h"
+
+#define MAX_EXTRADATA_SIZE 1024
 
 typedef struct LATMContext {
     AVClass *av_class;
@@ -33,6 +37,7 @@ typedef struct LATMContext {
     int object_type;
     int counter;
     int mod;
+    uint8_t buffer[0x1fff + MAX_EXTRADATA_SIZE + 1024];
 } LATMContext;
 
 static const AVOption options[] = {
@@ -50,15 +55,21 @@ static const AVClass latm_muxer_class = {
 
 static int latm_decode_extradata(LATMContext *ctx, uint8_t *buf, int size)
 {
-    GetBitContext gb;
     MPEG4AudioConfig m4ac;
 
-    init_get_bits(&gb, buf, size * 8);
+    if (size > MAX_EXTRADATA_SIZE) {
+        av_log(ctx, AV_LOG_ERROR, "Extradata is larger than currently supported.\n");
+        return AVERROR_INVALIDDATA;
+    }
     ctx->off = avpriv_mpeg4audio_get_config(&m4ac, buf, size * 8, 1);
     if (ctx->off < 0)
         return ctx->off;
-    skip_bits_long(&gb, ctx->off);
 
+    if (ctx->object_type == AOT_ALS && (ctx->off & 7)) {
+        // as long as avpriv_mpeg4audio_get_config works correctly this is impossible
+        av_log(ctx, AV_LOG_ERROR, "BUG: ALS offset is not byte-aligned\n");
+        return AVERROR_INVALIDDATA;
+    }
     /* FIXME: are any formats not allowed in LATM? */
 
     if (m4ac.object_type > AOT_SBR && m4ac.object_type != AOT_ALS) {
@@ -76,6 +87,9 @@ static int latm_write_header(AVFormatContext *s)
     LATMContext *ctx = s->priv_data;
     AVCodecParameters *par = s->streams[0]->codecpar;
 
+    if (par->codec_id == AV_CODEC_ID_AAC_LATM)
+        return 0;
+
     if (par->extradata_size > 0 &&
         latm_decode_extradata(ctx, par->extradata, par->extradata_size) < 0)
         return AVERROR_INVALIDDATA;
@@ -83,19 +97,16 @@ static int latm_write_header(AVFormatContext *s)
     return 0;
 }
 
-static int latm_write_frame_header(AVFormatContext *s, PutBitContext *bs)
+static void latm_write_frame_header(AVFormatContext *s, PutBitContext *bs)
 {
     LATMContext *ctx = s->priv_data;
     AVCodecParameters *par = s->streams[0]->codecpar;
-    GetBitContext gb;
     int header_size;
 
     /* AudioMuxElement */
     put_bits(bs, 1, !!ctx->counter);
 
     if (!ctx->counter) {
-        init_get_bits(&gb, par->extradata, par->extradata_size * 8);
-
         /* StreamMuxConfig */
         put_bits(bs, 1, 0); /* audioMuxVersion */
         put_bits(bs, 1, 1); /* allStreamsSameTimeFraming */
@@ -105,12 +116,18 @@ static int latm_write_frame_header(AVFormatContext *s, PutBitContext *bs)
 
         /* AudioSpecificConfig */
         if (ctx->object_type == AOT_ALS) {
-            header_size = par->extradata_size-(ctx->off + 7) >> 3;
-            avpriv_copy_bits(bs, &par->extradata[ctx->off], header_size);
+            header_size = par->extradata_size-(ctx->off >> 3);
+            avpriv_copy_bits(bs, &par->extradata[ctx->off >> 3], header_size);
         } else {
+            // + 3 assumes not scalable and dependsOnCoreCoder == 0,
+            // see decode_ga_specific_config in libavcodec/aacdec.c
             avpriv_copy_bits(bs, par->extradata, ctx->off + 3);
 
             if (!ctx->channel_conf) {
+                GetBitContext gb;
+                int ret = init_get_bits8(&gb, par->extradata, par->extradata_size);
+                av_assert0(ret >= 0); // extradata size has been checked already, so this should not fail
+                skip_bits_long(&gb, ctx->off + 3);
                 ff_copy_pce_data(bs, &gb);
             }
         }
@@ -124,28 +141,45 @@ static int latm_write_frame_header(AVFormatContext *s, PutBitContext *bs)
 
     ctx->counter++;
     ctx->counter %= ctx->mod;
-
-    return 0;
 }
 
 static int latm_write_packet(AVFormatContext *s, AVPacket *pkt)
 {
+    LATMContext *ctx = s->priv_data;
+    AVCodecParameters *par = s->streams[0]->codecpar;
     AVIOContext *pb = s->pb;
     PutBitContext bs;
     int i, len;
     uint8_t loas_header[] = "\x56\xe0\x00";
-    uint8_t *buf;
 
-    if (pkt->size > 2 && pkt->data[0] == 0xff && (pkt->data[1] >> 4) == 0xf) {
-        av_log(s, AV_LOG_ERROR, "ADTS header detected - ADTS will not be incorrectly muxed into LATM\n");
-        return AVERROR_INVALIDDATA;
+    if (par->codec_id == AV_CODEC_ID_AAC_LATM)
+        return ff_raw_write_packet(s, pkt);
+
+    if (!par->extradata) {
+        if(pkt->size > 2 && pkt->data[0] == 0x56 && (pkt->data[1] >> 4) == 0xe &&
+            (AV_RB16(pkt->data + 1) & 0x1FFF) + 3 == pkt->size)
+            return ff_raw_write_packet(s, pkt);
+        else {
+            uint8_t *side_data;
+            int side_data_size = 0, ret;
+
+            side_data = av_packet_get_side_data(pkt, AV_PKT_DATA_NEW_EXTRADATA,
+                                                &side_data_size);
+            if (side_data_size) {
+                if (latm_decode_extradata(ctx, side_data, side_data_size) < 0)
+                    return AVERROR_INVALIDDATA;
+                ret = ff_alloc_extradata(par, side_data_size);
+                if (ret < 0)
+                    return ret;
+                memcpy(par->extradata, side_data, side_data_size);
+            }
+        }
     }
 
-    buf = av_malloc(pkt->size+1024);
-    if (!buf)
-        return AVERROR(ENOMEM);
+    if (pkt->size > 0x1fff)
+        goto too_large;
 
-    init_put_bits(&bs, buf, pkt->size+1024);
+    init_put_bits(&bs, ctx->buffer, pkt->size+1024+MAX_EXTRADATA_SIZE);
 
     latm_write_frame_header(s, &bs);
 
@@ -158,35 +192,65 @@ static int latm_write_packet(AVFormatContext *s, AVPacket *pkt)
     /* The LATM payload is written unaligned */
 
     /* PayloadMux() */
-    for (i = 0; i < pkt->size; i++)
-        put_bits(&bs, 8, pkt->data[i]);
+    if (pkt->size && (pkt->data[0] & 0xe1) == 0x81) {
+        // Convert byte-aligned DSE to non-aligned.
+        // Due to the input format encoding we know that
+        // it is naturally byte-aligned in the input stream,
+        // so there are no padding bits to account for.
+        // To avoid having to add padding bits and rearrange
+        // the whole stream we just remove the byte-align flag.
+        // This allows us to remux our FATE AAC samples into latm
+        // files that are still playable with minimal effort.
+        put_bits(&bs, 8, pkt->data[0] & 0xfe);
+        avpriv_copy_bits(&bs, pkt->data + 1, 8*pkt->size - 8);
+    } else
+        avpriv_copy_bits(&bs, pkt->data, 8*pkt->size);
 
     avpriv_align_put_bits(&bs);
     flush_put_bits(&bs);
 
     len = put_bits_count(&bs) >> 3;
 
+    if (len > 0x1fff)
+        goto too_large;
+
     loas_header[1] |= (len >> 8) & 0x1f;
     loas_header[2] |= len & 0xff;
 
     avio_write(pb, loas_header, 3);
-    avio_write(pb, buf, len);
-
-    av_free(buf);
+    avio_write(pb, ctx->buffer, len);
 
     return 0;
+
+too_large:
+    av_log(s, AV_LOG_ERROR, "LATM packet size larger than maximum size 0x1fff\n");
+    return AVERROR_INVALIDDATA;
+}
+
+static int latm_check_bitstream(struct AVFormatContext *s, const AVPacket *pkt)
+{
+    int ret = 1;
+    AVStream *st = s->streams[pkt->stream_index];
+
+    if (st->codecpar->codec_id == AV_CODEC_ID_AAC) {
+        if (pkt->size > 2 && (AV_RB16(pkt->data) & 0xfff0) == 0xfff0)
+            ret = ff_stream_add_bitstream_filter(st, "aac_adtstoasc", NULL);
+    }
+
+    return ret;
 }
 
 AVOutputFormat ff_latm_muxer = {
     .name           = "latm",
     .long_name      = NULL_IF_CONFIG_SMALL("LOAS/LATM"),
     .mime_type      = "audio/MP4A-LATM",
-    .extensions     = "latm",
+    .extensions     = "latm,loas",
     .priv_data_size = sizeof(LATMContext),
     .audio_codec    = AV_CODEC_ID_AAC,
     .video_codec    = AV_CODEC_ID_NONE,
     .write_header   = latm_write_header,
     .write_packet   = latm_write_packet,
     .priv_class     = &latm_muxer_class,
+    .check_bitstream= latm_check_bitstream,
     .flags          = AVFMT_NOTIMESTAMPS,
 };