Browse code

Add single stream LATM/LOAS decoder

The decoder is just a wrapper around the AAC decoder.
based on patch by Paul Kendall { paul <ät> kcbbs gen nz }

Originally committed as revision 25642 to svn://svn.ffmpeg.org/ffmpeg/trunk

Janne Grunau authored on 2010/11/02 17:32:04
Showing 7 changed files
... ...
@@ -50,6 +50,7 @@ version <next>:
50 50
 - transpose filter added
51 51
 - ffmpeg -force_key_frames option added
52 52
 - demuxer for receiving raw rtp:// URLs without an SDP description
53
+- single stream LATM/LOAS decoder
53 54
 
54 55
 
55 56
 version 0.6:
... ...
@@ -1188,6 +1188,7 @@ rdft_select="fft"
1188 1188
 # decoders / encoders / hardware accelerators
1189 1189
 aac_decoder_select="mdct rdft"
1190 1190
 aac_encoder_select="mdct"
1191
+aac_latm_decoder_select="aac_decoder aac_latm_parser"
1191 1192
 ac3_decoder_select="mdct ac3_parser"
1192 1193
 alac_encoder_select="lpc"
1193 1194
 amrnb_decoder_select="lsp"
... ...
@@ -576,6 +576,7 @@ OBJS-$(CONFIG_H264_PARSER)             += h264_parser.o h264.o            \
576 576
                                           h264_loopfilter.o h264_cabac.o \
577 577
                                           h264_cavlc.o h264_ps.o \
578 578
                                           mpegvideo.o error_resilience.o
579
+OBJS-$(CONFIG_AAC_LATM_PARSER)         += latm_parser.o
579 580
 OBJS-$(CONFIG_MJPEG_PARSER)            += mjpeg_parser.o
580 581
 OBJS-$(CONFIG_MLP_PARSER)              += mlp_parser.o mlp.o
581 582
 OBJS-$(CONFIG_MPEG4VIDEO_PARSER)       += mpeg4video_parser.o h263.o \
... ...
@@ -3,6 +3,10 @@
3 3
  * Copyright (c) 2005-2006 Oded Shimon ( ods15 ods15 dyndns org )
4 4
  * Copyright (c) 2006-2007 Maxim Gavrilov ( maxim.gavrilov gmail com )
5 5
  *
6
+ * AAC LATM decoder
7
+ * Copyright (c) 2008-2010 Paul Kendall <paul@kcbbs.gen.nz>
8
+ * Copyright (c) 2010      Janne Grunau <janne-ffmpeg@jannau.net>
9
+ *
6 10
  * This file is part of FFmpeg.
7 11
  *
8 12
  * FFmpeg is free software; you can redistribute it and/or
... ...
@@ -2098,6 +2102,261 @@ static av_cold int aac_decode_close(AVCodecContext *avctx)
2098 2098
     return 0;
2099 2099
 }
2100 2100
 
2101
+
2102
+#define LOAS_SYNC_WORD   0x2b7       ///< 11 bits LOAS sync word
2103
+
2104
+struct LATMContext {
2105
+    AACContext      aac_ctx;             ///< containing AACContext
2106
+    int             initialized;         ///< initilized after a valid extradata was seen
2107
+
2108
+    // parser data
2109
+    int             audio_mux_version_A; ///< LATM syntax version
2110
+    int             frame_length_type;   ///< 0/1 variable/fixed frame length
2111
+    int             frame_length;        ///< frame length for fixed frame length
2112
+};
2113
+
2114
+static inline uint32_t latm_get_value(GetBitContext *b)
2115
+{
2116
+    int length = get_bits(b, 2);
2117
+
2118
+    return get_bits_long(b, (length+1)*8);
2119
+}
2120
+
2121
+static int latm_decode_audio_specific_config(struct LATMContext *latmctx,
2122
+                                             GetBitContext *gb)
2123
+{
2124
+    AVCodecContext *avctx = latmctx->aac_ctx.avctx;
2125
+    MPEG4AudioConfig m4ac;
2126
+    int  config_start_bit = get_bits_count(gb);
2127
+    int     bits_consumed, esize;
2128
+
2129
+    if (config_start_bit % 8) {
2130
+        av_log_missing_feature(latmctx->aac_ctx.avctx, "audio specific "
2131
+                               "config not byte aligned.\n", 1);
2132
+        return AVERROR_INVALIDDATA;
2133
+    } else {
2134
+        bits_consumed =
2135
+            decode_audio_specific_config(NULL, avctx, &m4ac,
2136
+                                         gb->buffer + (config_start_bit / 8),
2137
+                                         get_bits_left(gb) / 8);
2138
+
2139
+        if (bits_consumed < 0)
2140
+            return AVERROR_INVALIDDATA;
2141
+
2142
+        esize = (bits_consumed+7) / 8;
2143
+
2144
+        if (avctx->extradata_size <= esize) {
2145
+            av_free(avctx->extradata);
2146
+            avctx->extradata = av_malloc(esize + FF_INPUT_BUFFER_PADDING_SIZE);
2147
+            if (!avctx->extradata)
2148
+                return AVERROR(ENOMEM);
2149
+        }
2150
+
2151
+        avctx->extradata_size = esize;
2152
+        memcpy(avctx->extradata, gb->buffer + (config_start_bit/8), esize);
2153
+        memset(avctx->extradata+esize, 0, FF_INPUT_BUFFER_PADDING_SIZE);
2154
+    }
2155
+
2156
+    return bits_consumed;
2157
+}
2158
+
2159
+static int read_stream_mux_config(struct LATMContext *latmctx,
2160
+                                  GetBitContext *gb)
2161
+{
2162
+    int ret, audio_mux_version = get_bits(gb, 1);
2163
+
2164
+    latmctx->audio_mux_version_A = 0;
2165
+    if (audio_mux_version)
2166
+        latmctx->audio_mux_version_A = get_bits(gb, 1);
2167
+
2168
+    if (!latmctx->audio_mux_version_A) {
2169
+
2170
+        if (audio_mux_version)
2171
+            latm_get_value(gb);                 // taraFullness
2172
+
2173
+        skip_bits(gb, 1);                       // allStreamSameTimeFraming
2174
+        skip_bits(gb, 6);                       // numSubFrames
2175
+        // numPrograms
2176
+        if (get_bits(gb, 4)) {                  // numPrograms
2177
+            av_log_missing_feature(latmctx->aac_ctx.avctx,
2178
+                                   "multiple programs are not supported\n", 1);
2179
+            return AVERROR_PATCHWELCOME;
2180
+        }
2181
+
2182
+        // for each program (which there is only on in DVB)
2183
+
2184
+        // for each layer (which there is only on in DVB)
2185
+        if (get_bits(gb, 3)) {                   // numLayer
2186
+            av_log_missing_feature(latmctx->aac_ctx.avctx,
2187
+                                   "multiple layers are not supported\n", 1);
2188
+            return AVERROR_PATCHWELCOME;
2189
+        }
2190
+
2191
+        // for all but first stream: use_same_config = get_bits(gb, 1);
2192
+        if (!audio_mux_version) {
2193
+            if ((ret = latm_decode_audio_specific_config(latmctx, gb)) < 0)
2194
+                return ret;
2195
+        } else {
2196
+            int ascLen = latm_get_value(gb);
2197
+            if ((ret = latm_decode_audio_specific_config(latmctx, gb)) < 0)
2198
+                return ret;
2199
+            ascLen -= ret;
2200
+            skip_bits_long(gb, ascLen);
2201
+        }
2202
+
2203
+        latmctx->frame_length_type = get_bits(gb, 3);
2204
+        switch (latmctx->frame_length_type) {
2205
+        case 0:
2206
+            skip_bits(gb, 8);       // latmBufferFullness
2207
+            break;
2208
+        case 1:
2209
+            latmctx->frame_length = get_bits(gb, 9);
2210
+            break;
2211
+        case 3:
2212
+        case 4:
2213
+        case 5:
2214
+            skip_bits(gb, 6);       // CELP frame length table index
2215
+            break;
2216
+        case 6:
2217
+        case 7:
2218
+            skip_bits(gb, 1);       // HVXC frame length table index
2219
+            break;
2220
+        }
2221
+
2222
+        if (get_bits(gb, 1)) {                  // other data
2223
+            if (audio_mux_version) {
2224
+                latm_get_value(gb);             // other_data_bits
2225
+            } else {
2226
+                int esc;
2227
+                do {
2228
+                    esc = get_bits(gb, 1);
2229
+                    skip_bits(gb, 8);
2230
+                } while (esc);
2231
+            }
2232
+        }
2233
+
2234
+        if (get_bits(gb, 1))                     // crc present
2235
+            skip_bits(gb, 8);                    // config_crc
2236
+    }
2237
+
2238
+    return 0;
2239
+}
2240
+
2241
+static int read_payload_length_info(struct LATMContext *ctx, GetBitContext *gb)
2242
+{
2243
+    uint8_t tmp;
2244
+
2245
+    if (ctx->frame_length_type == 0) {
2246
+        int mux_slot_length = 0;
2247
+        do {
2248
+            tmp = get_bits(gb, 8);
2249
+            mux_slot_length += tmp;
2250
+        } while (tmp == 255);
2251
+        return mux_slot_length;
2252
+    } else if (ctx->frame_length_type == 1) {
2253
+        return ctx->frame_length;
2254
+    } else if (ctx->frame_length_type == 3 ||
2255
+               ctx->frame_length_type == 5 ||
2256
+               ctx->frame_length_type == 7) {
2257
+        skip_bits(gb, 2);          // mux_slot_length_coded
2258
+    }
2259
+    return 0;
2260
+}
2261
+
2262
+static int read_audio_mux_element(struct LATMContext *latmctx,
2263
+                                  GetBitContext *gb)
2264
+{
2265
+    int err;
2266
+    uint8_t use_same_mux = get_bits(gb, 1);
2267
+    if (!use_same_mux) {
2268
+        if ((err = read_stream_mux_config(latmctx, gb)) < 0)
2269
+            return err;
2270
+    } else if (!latmctx->aac_ctx.avctx->extradata) {
2271
+        av_log(latmctx->aac_ctx.avctx, AV_LOG_DEBUG,
2272
+               "no decoder config found\n");
2273
+        return AVERROR(EAGAIN);
2274
+    }
2275
+    if (latmctx->audio_mux_version_A == 0) {
2276
+        int mux_slot_length_bytes = read_payload_length_info(latmctx, gb);
2277
+        if (mux_slot_length_bytes * 8 > get_bits_left(gb)) {
2278
+            av_log(latmctx->aac_ctx.avctx, AV_LOG_ERROR, "incomplete frame\n");
2279
+            return AVERROR_INVALIDDATA;
2280
+        } else if (mux_slot_length_bytes * 8 + 256 < get_bits_left(gb)) {
2281
+            av_log(latmctx->aac_ctx.avctx, AV_LOG_ERROR,
2282
+                   "frame length mismatch %d << %d\n",
2283
+                   mux_slot_length_bytes * 8, get_bits_left(gb));
2284
+            return AVERROR_INVALIDDATA;
2285
+        }
2286
+    }
2287
+    return 0;
2288
+}
2289
+
2290
+
2291
+static int latm_decode_frame(AVCodecContext *avctx, void *out, int *out_size,
2292
+                             AVPacket *avpkt)
2293
+{
2294
+    struct LATMContext *latmctx = avctx->priv_data;
2295
+    int                 muxlength, err;
2296
+    GetBitContext       gb;
2297
+
2298
+    if (avpkt->size == 0)
2299
+        return 0;
2300
+
2301
+    init_get_bits(&gb, avpkt->data, avpkt->size * 8);
2302
+
2303
+    // check for LOAS sync word
2304
+    if (get_bits(&gb, 11) != LOAS_SYNC_WORD)
2305
+        return AVERROR_INVALIDDATA;
2306
+
2307
+    muxlength = get_bits(&gb, 13);
2308
+    // not enough data, the parser should have sorted this
2309
+    if (muxlength+3 > avpkt->size)
2310
+        return AVERROR_INVALIDDATA;
2311
+
2312
+    if ((err = read_audio_mux_element(latmctx, &gb)) < 0)
2313
+        return err;
2314
+
2315
+    if (!latmctx->initialized) {
2316
+        if (!avctx->extradata) {
2317
+            *out_size = 0;
2318
+            return avpkt->size;
2319
+        } else {
2320
+            if ((err = aac_decode_init(avctx)) < 0)
2321
+                return err;
2322
+            latmctx->initialized = 1;
2323
+        }
2324
+    }
2325
+
2326
+    if (show_bits(&gb, 12) == 0xfff) {
2327
+        av_log(latmctx->aac_ctx.avctx, AV_LOG_ERROR,
2328
+               "ADTS header detected, probably as result of configuration "
2329
+               "misparsing\n");
2330
+        return AVERROR_INVALIDDATA;
2331
+    }
2332
+
2333
+    if ((err = aac_decode_frame_int(avctx, out, out_size, &gb)) < 0)
2334
+        return err;
2335
+
2336
+    return muxlength;
2337
+}
2338
+
2339
+av_cold static int latm_decode_init(AVCodecContext *avctx)
2340
+{
2341
+    struct LATMContext *latmctx = avctx->priv_data;
2342
+    int ret;
2343
+
2344
+    ret = aac_decode_init(avctx);
2345
+
2346
+    if (avctx->extradata_size > 0) {
2347
+        latmctx->initialized = !ret;
2348
+    } else {
2349
+        latmctx->initialized = 0;
2350
+    }
2351
+
2352
+    return ret;
2353
+}
2354
+
2355
+
2101 2356
 AVCodec aac_decoder = {
2102 2357
     "aac",
2103 2358
     AVMEDIA_TYPE_AUDIO,
... ...
@@ -2113,3 +2372,23 @@ AVCodec aac_decoder = {
2113 2113
     },
2114 2114
     .channel_layouts = aac_channel_layout,
2115 2115
 };
2116
+
2117
+/*
2118
+    Note: This decoder filter is intended to decode LATM streams transferred
2119
+    in MPEG transport streams which only contain one program.
2120
+    To do a more complex LATM demuxing a separate LATM demuxer should be used.
2121
+*/
2122
+AVCodec aac_latm_decoder = {
2123
+    .name = "aac_latm",
2124
+    .type = CODEC_TYPE_AUDIO,
2125
+    .id   = CODEC_ID_AAC_LATM,
2126
+    .priv_data_size = sizeof(struct LATMContext),
2127
+    .init   = latm_decode_init,
2128
+    .close  = aac_decode_close,
2129
+    .decode = latm_decode_frame,
2130
+    .long_name = NULL_IF_CONFIG_SMALL("AAC LATM (Advanced Audio Codec LATM syntax)"),
2131
+    .sample_fmts = (const enum SampleFormat[]) {
2132
+        SAMPLE_FMT_S16,SAMPLE_FMT_NONE
2133
+    },
2134
+    .channel_layouts = aac_channel_layout,
2135
+};
... ...
@@ -220,6 +220,7 @@ void avcodec_register_all(void)
220 220
 
221 221
     /* audio codecs */
222 222
     REGISTER_ENCDEC  (AAC, aac);
223
+    REGISTER_DECODER (AAC_LATM, aac_latm);
223 224
     REGISTER_ENCDEC  (AC3, ac3);
224 225
     REGISTER_ENCDEC  (ALAC, alac);
225 226
     REGISTER_DECODER (ALS, als);
... ...
@@ -366,6 +367,7 @@ void avcodec_register_all(void)
366 366
 
367 367
     /* parsers */
368 368
     REGISTER_PARSER  (AAC, aac);
369
+    REGISTER_PARSER  (AAC_LATM, aac_latm);
369 370
     REGISTER_PARSER  (AC3, ac3);
370 371
     REGISTER_PARSER  (CAVSVIDEO, cavsvideo);
371 372
     REGISTER_PARSER  (DCA, dca);
... ...
@@ -31,7 +31,7 @@
31 31
 #include "libavutil/cpu.h"
32 32
 
33 33
 #define LIBAVCODEC_VERSION_MAJOR 52
34
-#define LIBAVCODEC_VERSION_MINOR 93
34
+#define LIBAVCODEC_VERSION_MINOR 94
35 35
 #define LIBAVCODEC_VERSION_MICRO  0
36 36
 
37 37
 #define LIBAVCODEC_VERSION_INT  AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \
... ...
@@ -376,6 +376,7 @@ enum CodecID {
376 376
     CODEC_ID_ATRAC1,
377 377
     CODEC_ID_BINKAUDIO_RDFT,
378 378
     CODEC_ID_BINKAUDIO_DCT,
379
+    CODEC_ID_AAC_LATM,
379 380
 
380 381
     /* subtitle codecs */
381 382
     CODEC_ID_DVD_SUBTITLE= 0x17000,
382 383
new file mode 100644
... ...
@@ -0,0 +1,119 @@
0
+/*
1
+ * copyright (c) 2008 Paul Kendall <paul@kcbbs.gen.nz>
2
+ *
3
+ * This file is part of FFmpeg.
4
+ *
5
+ * FFmpeg is free software; you can redistribute it and/or
6
+ * modify it under the terms of the GNU Lesser General Public
7
+ * License as published by the Free Software Foundation; either
8
+ * version 2.1 of the License, or (at your option) any later version.
9
+ *
10
+ * FFmpeg is distributed in the hope that it will be useful,
11
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13
+ * Lesser General Public License for more details.
14
+ *
15
+ * You should have received a copy of the GNU Lesser General Public
16
+ * License along with FFmpeg; if not, write to the Free Software
17
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18
+ */
19
+
20
+/**
21
+ * @file
22
+ * AAC LATM parser
23
+ */
24
+
25
+#include <stdio.h>
26
+#include <stdlib.h>
27
+#include <string.h>
28
+#include <math.h>
29
+#include <sys/types.h>
30
+
31
+#include "parser.h"
32
+
33
+#define LATM_HEADER     0x56e000        // 0x2b7 (11 bits)
34
+#define LATM_MASK       0xFFE000        // top 11 bits
35
+#define LATM_SIZE_MASK  0x001FFF        // bottom 13 bits
36
+
37
+typedef struct LATMParseContext{
38
+    ParseContext pc;
39
+    int count;
40
+} LATMParseContext;
41
+
42
+/**
43
+ * finds the end of the current frame in the bitstream.
44
+ * @return the position of the first byte of the next frame, or -1
45
+ */
46
+static int latm_find_frame_end(AVCodecParserContext *s1, const uint8_t *buf,
47
+                               int buf_size)
48
+{
49
+    LATMParseContext *s = s1->priv_data;
50
+    ParseContext *pc    = &s->pc;
51
+    int pic_found, i;
52
+    uint32_t state;
53
+
54
+    pic_found = pc->frame_start_found;
55
+    state     = pc->state;
56
+
57
+    i = 0;
58
+    if (!pic_found) {
59
+        for (i = 0; i < buf_size; i++) {
60
+            state = (state<<8) | buf[i];
61
+            if ((state & LATM_MASK) == LATM_HEADER) {
62
+                i++;
63
+                s->count  = -i;
64
+                pic_found = 1;
65
+                break;
66
+            }
67
+        }
68
+    }
69
+
70
+    if (pic_found) {
71
+        /* EOF considered as end of frame */
72
+        if (buf_size == 0)
73
+            return 0;
74
+        if ((state & LATM_SIZE_MASK) - s->count <= buf_size) {
75
+            pc->frame_start_found = 0;
76
+            pc->state             = -1;
77
+            return (state & LATM_SIZE_MASK) - s->count;
78
+        }
79
+    }
80
+
81
+    s->count             += buf_size;
82
+    pc->frame_start_found = pic_found;
83
+    pc->state             = state;
84
+
85
+    return END_NOT_FOUND;
86
+}
87
+
88
+static int latm_parse(AVCodecParserContext *s1, AVCodecContext *avctx,
89
+                      const uint8_t **poutbuf, int *poutbuf_size,
90
+                      const uint8_t *buf, int buf_size)
91
+{
92
+    LATMParseContext *s = s1->priv_data;
93
+    ParseContext *pc    = &s->pc;
94
+    int next;
95
+
96
+    if (s1->flags & PARSER_FLAG_COMPLETE_FRAMES) {
97
+        next = buf_size;
98
+    } else {
99
+        next = latm_find_frame_end(s1, buf, buf_size);
100
+
101
+        if (ff_combine_frame(pc, next, &buf, &buf_size) < 0) {
102
+            *poutbuf      = NULL;
103
+            *poutbuf_size = 0;
104
+            return buf_size;
105
+        }
106
+    }
107
+    *poutbuf      = buf;
108
+    *poutbuf_size = buf_size;
109
+    return next;
110
+}
111
+
112
+AVCodecParser aac_latm_parser = {
113
+    { CODEC_ID_AAC_LATM },
114
+    sizeof(LATMParseContext),
115
+    NULL,
116
+    latm_parse,
117
+    ff_parse_close
118
+};