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
50- transpose filter added50- transpose filter added
51- ffmpeg -force_key_frames option added51- ffmpeg -force_key_frames option added
52- demuxer for receiving raw rtp:// URLs without an SDP description52- demuxer for receiving raw rtp:// URLs without an SDP description
53- single stream LATM/LOAS decoder
53 54
54 55
55version 0.6:56version 0.6:
configure+1−0
@@ -1188,6 +1188,7 @@ rdft_select="fft" · 1187 unmodified lines
1188# decoders / encoders / hardware accelerators1188# decoders / encoders / hardware accelerators
1189aac_decoder_select="mdct rdft"1189aac_decoder_select="mdct rdft"
1190aac_encoder_select="mdct"1190aac_encoder_select="mdct"
1191aac_latm_decoder_select="aac_decoder aac_latm_parser"
1191ac3_decoder_select="mdct ac3_parser"1192ac3_decoder_select="mdct ac3_parser"
1192alac_encoder_select="lpc"1193alac_encoder_select="lpc"
1193amrnb_decoder_select="lsp"1194amrnb_decoder_select="lsp"
libavcodec/Makefile+1−0
@@ -576,6 +576,7 @@ OBJS-$(CONFIG_H264_PARSER) += h264_parser.o h264.o \ · 575 unmodified lines
576 h264_loopfilter.o h264_cabac.o \576 h264_loopfilter.o h264_cabac.o \
577 h264_cavlc.o h264_ps.o \577 h264_cavlc.o h264_ps.o \
578 mpegvideo.o error_resilience.o578 mpegvideo.o error_resilience.o
579OBJS-$(CONFIG_AAC_LATM_PARSER) += latm_parser.o
579OBJS-$(CONFIG_MJPEG_PARSER) += mjpeg_parser.o580OBJS-$(CONFIG_MJPEG_PARSER) += mjpeg_parser.o
580OBJS-$(CONFIG_MLP_PARSER) += mlp_parser.o mlp.o581OBJS-$(CONFIG_MLP_PARSER) += mlp_parser.o mlp.o
581OBJS-$(CONFIG_MPEG4VIDEO_PARSER) += mpeg4video_parser.o h263.o \582OBJS-$(CONFIG_MPEG4VIDEO_PARSER) += mpeg4video_parser.o h263.o \
libavcodec/aacdec.c+279−0
@@ -3,6 +3,10 @@ · 2 unmodified lines
3 * Copyright (c) 2005-2006 Oded Shimon ( ods15 ods15 dyndns org )3 * Copyright (c) 2005-2006 Oded Shimon ( ods15 ods15 dyndns org )
4 * Copyright (c) 2006-2007 Maxim Gavrilov ( maxim.gavrilov gmail com )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 * This file is part of FFmpeg.10 * This file is part of FFmpeg.
7 *11 *
8 * FFmpeg is free software; you can redistribute it and/or12 * 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
2098 return 0;2102 return 0;
2099}2103}
2100 2104
2105
2106#define LOAS_SYNC_WORD 0x2b7 ///< 11 bits LOAS sync word
2107
2108struct 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
2118static 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
2125static 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
2163static 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
2245static 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
2266static 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
2295static 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
2343av_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
2101AVCodec aac_decoder = {2360AVCodec aac_decoder = {
2102 "aac",2361 "aac",
2103 AVMEDIA_TYPE_AUDIO,2362 AVMEDIA_TYPE_AUDIO,
@@ -2113,3 +2372,23 @@ AVCodec aac_decoder = { · 9 unmodified lines
2113 },2372 },
2114 .channel_layouts = aac_channel_layout,2373 .channel_layouts = aac_channel_layout,
2115};2374};
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*/
2381AVCodec 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
220 220
221 /* audio codecs */221 /* audio codecs */
222 REGISTER_ENCDEC (AAC, aac);222 REGISTER_ENCDEC (AAC, aac);
223 REGISTER_DECODER (AAC_LATM, aac_latm);
223 REGISTER_ENCDEC (AC3, ac3);224 REGISTER_ENCDEC (AC3, ac3);
224 REGISTER_ENCDEC (ALAC, alac);225 REGISTER_ENCDEC (ALAC, alac);
225 REGISTER_DECODER (ALS, als);226 REGISTER_DECODER (ALS, als);
@@ -366,6 +367,7 @@ void avcodec_register_all(void) · 140 unmodified lines
366 367
367 /* parsers */368 /* parsers */
368 REGISTER_PARSER (AAC, aac);369 REGISTER_PARSER (AAC, aac);
370 REGISTER_PARSER (AAC_LATM, aac_latm);
369 REGISTER_PARSER (AC3, ac3);371 REGISTER_PARSER (AC3, ac3);
370 REGISTER_PARSER (CAVSVIDEO, cavsvideo);372 REGISTER_PARSER (CAVSVIDEO, cavsvideo);
371 REGISTER_PARSER (DCA, dca);373 REGISTER_PARSER (DCA, dca);
libavcodec/avcodec.h+2−1
@@ -31,7 +31,7 @@ · 30 unmodified lines
31#include "libavutil/cpu.h"31#include "libavutil/cpu.h"
32 32
33#define LIBAVCODEC_VERSION_MAJOR 5233#define LIBAVCODEC_VERSION_MAJOR 52
34#define LIBAVCODEC_VERSION_MINOR 9334#define LIBAVCODEC_VERSION_MINOR 94
35#define LIBAVCODEC_VERSION_MICRO 035#define LIBAVCODEC_VERSION_MICRO 0
36 36
37#define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \37#define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \
@@ -376,6 +376,7 @@ enum CodecID { · 338 unmodified lines
376 CODEC_ID_ATRAC1,376 CODEC_ID_ATRAC1,
377 CODEC_ID_BINKAUDIO_RDFT,377 CODEC_ID_BINKAUDIO_RDFT,
378 CODEC_ID_BINKAUDIO_DCT,378 CODEC_ID_BINKAUDIO_DCT,
379 CODEC_ID_AAC_LATM,
379 380
380 /* subtitle codecs */381 /* subtitle codecs */
381 CODEC_ID_DVD_SUBTITLE= 0x17000,382 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
38typedef 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 */
47static 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
89static 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
113AVCodecParser 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