History

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 committed 16 years ago

Commit 136e19e1 parent 6c003e67 files · +405 −1Browse files

Unified · Split

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

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t