All pastes #1059717 Raw Edit

AAC-LATM

public diff v1 · immutable
#1059717 ·published 2008-07-01 06:50 UTC
rendered paste body
Index: patch-ffmpeg-latm.patch===================================================================--- patch-ffmpeg-latm.patch	(revision 0)+++ patch-ffmpeg-latm.patch	(revision 0)@@ -0,0 +1,895 @@+Index: libavcodec/Makefile+===================================================================+--- libavcodec/Makefile	(revision 14016)++++ libavcodec/Makefile	(working copy)+@@ -322,7 +322,7 @@+ OBJS-$(CONFIG_LIBDIRAC_DECODER)        += libdiracdec.o+ OBJS-$(CONFIG_LIBDIRAC_ENCODER)        += libdiracenc.o libdirac_libschro.o+ OBJS-$(CONFIG_LIBFAAC)                 += libfaac.o+-OBJS-$(CONFIG_LIBFAAD)                 += libfaad.o++OBJS-$(CONFIG_LIBFAAD)                 += libfaad.o latmaac.o+ OBJS-$(CONFIG_LIBGSM)                  += libgsm.o+ OBJS-$(CONFIG_LIBMP3LAME)              += libmp3lame.o+ OBJS-$(CONFIG_LIBSCHROEDINGER_DECODER) += libschroedingerdec.o libschroedinger.o libdirac_libschro.o+@@ -333,7 +333,7 @@+ OBJS-$(CONFIG_LIBXVID)                 += libxvidff.o libxvid_rc.o+ + +-OBJS-$(CONFIG_AAC_PARSER)              += aac_parser.o aac_ac3_parser.o mpeg4audio.o++OBJS-$(CONFIG_AAC_PARSER)              += aac_parser.o aac_ac3_parser.o mpeg4audio.o latm_parser.o+ OBJS-$(CONFIG_AC3_PARSER)              += ac3_parser.o ac3tab.o aac_ac3_parser.o+ OBJS-$(CONFIG_CAVSVIDEO_PARSER)        += cavs_parser.o+ OBJS-$(CONFIG_DCA_PARSER)              += dca_parser.o+Index: libavcodec/latmaac.c+===================================================================+--- libavcodec/latmaac.c	(revision 0)++++ libavcodec/latmaac.c	(revision 0)+@@ -0,0 +1,624 @@++/*++ * copyright (c) 2008 Paul Kendall <paul@kcbbs.gen.nz>++ *++ * This file is part of FFmpeg.++ *++ * 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.++ *++ * 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 FFmpeg; if not, write to the Free Software++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA++ */++++/**++ * @file latmaac.c++ * LATM wrapped AAC decoder++ */++++#include <stdio.h>++#include <stdlib.h>++#include <string.h>++#include <math.h>++#include <sys/types.h>++++#include "parser.h"++#include "bitstream.h"++#include "mpeg4audio.h"++#include "neaacdec.h"++++#define min(a,b) ((a)<(b) ? (a) : (b))++++++/*++    Note: This decoder filter is intended to decode LATM streams transferred++    in MPEG transport streams which are only supposed to contain one program.++    To do a more complex LATM demuxing a separate LATM demuxer should be used.++*/++++#define AAC_NONE 0            // mode not detected (or indicated in mediatype)++#define AAC_LATM 1            // LATM packets (ISO/IEC 14496-3  1.7.3 Multiplex layer)++++#define SYNC_LATM 0x2b7            // 11 bits++++#define MAX_SIZE 8*1024++++typedef struct AACConfig++{++    uint8_t    extra[64];            // should be way enough++    int        extrasize;++++    int        audioObjectType;++    int        samplingFrequencyIndex;++    int        samplingFrequency;++    int        channelConfiguration;++    int        channels;++} AACConfig;++++typedef struct AACParser++{++    AACConfig          config;++    uint8_t            frameLengthType;++    uint16_t           muxSlotLengthBytes;++++    uint8_t            audio_mux_version;++    uint8_t            audio_mux_version_A;++    int                taraFullness;++    uint8_t            config_crc;++    int64_t            other_data_bits;++++    int                mode;++    int                offset;        // byte offset in "buf" buffer++    uint8_t            buf[MAX_SIZE]; // allocated buffer++    int                count;         // number of bytes written in buffer++} AACParser;++++typedef struct AACDecoder ++{++    AACParser          *parser;++    faacDecHandle      aac_decoder;++    int                open;++    uint32_t           in_samplerate;++    uint8_t            in_channels;++} AACDecoder;++++typedef struct {++    AACDecoder*        decoder;++} FAACContext;++++static inline int64_t latm_get_value(GetBitContext *b)++{++    uint8_t bytesForValue = get_bits(b, 2);++    int64_t value = 0;++    int i;++    for (i=0; i<=bytesForValue; i++) {++        value <<= 8;++        value |= get_bits(b, 8);++    }++    return value;++}++++static void readGASpecificConfig(struct AACConfig *cfg, GetBitContext *b, PutBitContext *o)++{++    int framelen_flag = get_bits(b, 1);++    put_bits(o, 1, framelen_flag);++    int dependsOnCoder = get_bits(b, 1);++    put_bits(o, 1, dependsOnCoder);++    int ext_flag;++    int delay;++    int layerNr;++++    if (dependsOnCoder) {++        delay = get_bits(b, 14);++        put_bits(o, 14, delay);++    }++    ext_flag = get_bits(b, 1);++    put_bits(o, 1, ext_flag);++    if (!cfg->channelConfiguration) {++        // program config element++        // TODO:++    }++++    if (cfg->audioObjectType == 6 || cfg->audioObjectType == 20) {++        layerNr = get_bits(b, 3);++        put_bits(o, 3, layerNr);++    }++    if (ext_flag) {++        if (cfg->audioObjectType == 22) {++            skip_bits(b, 5);                    // numOfSubFrame++            skip_bits(b, 11);                    // layer_length++++            put_bits(o, 16, 0);++        }++        if (cfg->audioObjectType == 17 ||++            cfg->audioObjectType == 19 ||++            cfg->audioObjectType == 20 ||++            cfg->audioObjectType == 23) {++++            skip_bits(b, 3);                    // stuff++            put_bits(o, 3, 0);++        }++++        skip_bits(b, 1);                        // extflag3++        put_bits(o, 1, 0);++    }++}++++static int readAudioSpecificConfig(struct AACConfig *cfg, GetBitContext *b)++{++    PutBitContext o;++    init_put_bits(&o, cfg->extra, sizeof(cfg->extra));++++    // returns the number of bits read++    int ret = 0;++    int sbr_present = -1;++++    // object++    cfg->audioObjectType = get_bits(b, 5);++        put_bits(&o, 5, cfg->audioObjectType);++    if (cfg->audioObjectType == 31) {++        uint8_t n = get_bits(b, 6);++        put_bits(&o, 6, n);++        cfg->audioObjectType = 32 + n;++    }++++    cfg->samplingFrequencyIndex = get_bits(b, 4);++    cfg->samplingFrequency = ff_mpeg4audio_sample_rates[cfg->samplingFrequencyIndex];++    put_bits(&o, 4, cfg->samplingFrequencyIndex);++    if (cfg->samplingFrequencyIndex == 0x0f) {++        uint32_t f = get_bits_long(b, 24);++        put_bits(&o, 24, f);++        cfg->samplingFrequency = f;++    }++    cfg->channelConfiguration = get_bits(b, 4);++    put_bits(&o, 4, cfg->channelConfiguration);++    cfg->channels = ff_mpeg4audio_channels[cfg->channelConfiguration];++++    if (cfg->audioObjectType == 5) {++        sbr_present = 1;++++        // TODO: parsing !!!!!!!!!!!!!!!!++    }++++    switch (cfg->audioObjectType) {++    case 1:++    case 2:++    case 3:++    case 4:++    case 6:++    case 7:++    case 17:++    case 19:++    case 20:++    case 21:++    case 22:++    case 23:++        readGASpecificConfig(cfg, b, &o);++        break;++    }++++    if (sbr_present == -1) {++        if (cfg->samplingFrequency <= 24000) {++            cfg->samplingFrequency *= 2;++        }            ++    }++++    // count the extradata++    ret = put_bits_count(&o);++    align_put_bits(&o);++    flush_put_bits(&o);++    cfg->extrasize = (ret + 7) >> 3;++    return ret;++}++++static void readStreamMuxConfig(struct AACParser *parser, GetBitContext *b)++{++    parser->audio_mux_version_A = 0;++    parser->audio_mux_version = get_bits(b, 1);++    if (parser->audio_mux_version == 1) {                // audioMuxVersion++        parser->audio_mux_version_A = get_bits(b, 1);++    }++++    if (parser->audio_mux_version_A == 0) {++        if (parser->audio_mux_version == 1) {++            parser->taraFullness = latm_get_value(b);++        }++        get_bits(b, 1);                    // allStreamSameTimeFraming = 1++        get_bits(b, 6);                    // numSubFrames = 0++        get_bits(b, 4);                    // numPrograms = 0++++        // for each program++        get_bits(b, 3);                    // numLayer = 0++++        // for each layer++        if (parser->audio_mux_version == 0) {++            // audio specific config.++            readAudioSpecificConfig(&parser->config, b);++        } else {++            int ascLen = latm_get_value(b);++            ascLen -= readAudioSpecificConfig(&parser->config, b);++++            // fill bits++            while (ascLen > 16) {++                skip_bits(b, 16);++                ascLen -= 16;++            }++            skip_bits(b, ascLen);                    ++        }++++        // these are not needed... perhaps++        int frame_length_type = get_bits(b, 3);++        parser->frameLengthType = frame_length_type;++        if (frame_length_type == 0) {++            get_bits(b, 8);++        } else if (frame_length_type == 1) {++            get_bits(b, 9);++        } else if (frame_length_type == 3 ||++            frame_length_type == 4 ||++            frame_length_type == 5) {++            int celp_table_index = get_bits(b, 6);++        } else if (frame_length_type == 6 ||++            frame_length_type == 7) {++            int hvxc_table_index = get_bits(b, 1);++        }++++        // other data++        parser->other_data_bits = 0;++        if (get_bits(b, 1)) {++            // other data present++            if (parser->audio_mux_version == 1) {++                parser->other_data_bits = latm_get_value(b);++            } else {++                // other data not present++                parser->other_data_bits = 0;++                int esc, tmp;++                do {++                    parser->other_data_bits <<= 8;++                    esc = get_bits(b, 1);++                    tmp = get_bits(b, 8);++                    parser->other_data_bits |= tmp;++                } while (esc);++            }++        }++++        // CRC++        if (get_bits(b, 1)) {++            parser->config_crc = get_bits(b, 8);++        }++    } else {++        // tbd++    }++}++++static void readPayloadLengthInfo(struct AACParser *parser, GetBitContext *b)++{++    uint8_t tmp;++    if (parser->frameLengthType == 0) {++        parser->muxSlotLengthBytes = 0;++        do {++            tmp = get_bits(b, 8);++            parser->muxSlotLengthBytes += tmp;++        } while (tmp == 255);++    } else {++        if (parser->frameLengthType == 5 ||++            parser->frameLengthType == 7 ||++            parser->frameLengthType == 3) {++            get_bits(b, 2);++        }++    }++}++++static void readAudioMuxElement(struct AACParser *parser, GetBitContext *b, uint8_t *payload, int *payloadsize)++{++    uint8_t    use_same_mux = get_bits(b, 1);++    if (!use_same_mux) {++        readStreamMuxConfig(parser, b);++    }++++    if (parser->audio_mux_version_A == 0) {++        int j;++++        readPayloadLengthInfo(parser, b);++++        // copy data++        for (j=0; j<parser->muxSlotLengthBytes; j++) {++            *payload++ = get_bits(b, 8);++        }++        *payloadsize = parser->muxSlotLengthBytes;++++        // ignore otherdata++    } else {++        // TBD++    }++}++++static int readAudioSyncStream(struct AACParser *parser, GetBitContext *b, int size, uint8_t *payload, int *payloadsize)++{++    // ISO/IEC 14496-3 Table 1.28 - Syntax of AudioMuxElement()++    if (get_bits(b, 11) != 0x2b7) return -1;        // not LATM++    int muxlength = get_bits(b, 13);++++    if (3+muxlength > size) return 0;            // not enough data++++    readAudioMuxElement(parser, b, payload, payloadsize);++++    // we don't parse anything else here...++    return (3+muxlength);++}++++++static void flush_buf(struct AACParser *parser, int offset) {++    int bytes_to_flush = min(parser->count, offset);++    int left = (parser->count - bytes_to_flush);++++    if (bytes_to_flush > 0) {++        if (left > 0) {++            memcpy(parser->buf, parser->buf+bytes_to_flush, left);++            parser->count = left;++        } else {++            parser->count = 0;++        }++    }++}++++static struct AACParser *latm_create_parser()++{++    struct AACParser *parser = (struct AACParser *)av_malloc(sizeof(struct AACParser));++    memset(parser, 0, sizeof(struct AACParser));++    return parser;++}++++static void latm_destroy_parser(struct AACParser *parser)++{++    av_free(parser);++}++++static void latm_flush(struct AACParser *parser)++{++    parser->offset = 0;++    parser->count = 0;++}++++static void latm_write_data(struct AACParser *parser, uint8_t *data, int len)++{++    // buffer overflow check... just ignore the data before++    if (parser->count + len > MAX_SIZE) {++        flush_buf(parser, parser->offset);++        parser->offset = 0;++        if (parser->count + len > MAX_SIZE) {++            int to_flush = (parser->count+len) - MAX_SIZE;++            flush_buf(parser, to_flush);++        }++    }++++    // append data++    memcpy(parser->buf+parser->count, data, len);++    parser->count += len;++}++++static int latm_parse_packet(struct AACParser *parser, uint8_t *data, int maxsize)++{++    /*++        Return value is either number of bytes parsed or++        -1 when failed.++        0 = need more data.++    */++++    uint8_t    *start = parser->buf + parser->offset;++    int        bytes  = parser->count - parser->offset;++    GetBitContext    b;++    init_get_bits(&b, start, bytes);++++    if (parser->mode == AAC_LATM) {++        int outsize = 0;++        int    ret = readAudioSyncStream(parser, &b, bytes, data, &outsize);++++        if (ret < 0) return -1;++        if (ret == 0) return 0;++++        // update the offset++        parser->offset += ret;++        return outsize;++    }++++    // check for syncwords++    while (bytes > 2) {++        if (show_bits(&b, 11) == SYNC_LATM) {++            // we must parse config first...++            int outsize = 0;++++            // check if there is a complete packet available...++            int ret = readAudioSyncStream(parser, &b, bytes, data, &outsize);++            if (ret < 0) return -1;++            if (ret == 0) return 0;++            parser->offset += ret;++++            parser->mode = AAC_LATM;++            return outsize;++        }++        skip_bits(&b, 8);++        parser->offset++;++        bytes--;++    }++    return 0;++}++++static void aac_filter_close(AACDecoder *decoder)++{++    if (decoder->aac_decoder) {++        NeAACDecClose(decoder->aac_decoder);++        decoder->aac_decoder = NULL;++    }++    decoder->open = 0;++}++++static int aac_decoder_open(AACDecoder *decoder)++{++    if (decoder->aac_decoder) return 0;++++    decoder->aac_decoder = NeAACDecOpen();++    if (!decoder->aac_decoder) return -1;++++    // are we going to initialize from decoder specific info ?++    if (decoder->parser->config.extrasize > 0) {++        char ret = NeAACDecInit2(decoder->aac_decoder, (unsigned char*)decoder->parser->config.extra, decoder->parser->config.extrasize, &decoder->in_samplerate, &decoder->in_channels);++        if (ret < 0) {++            aac_filter_close(decoder);        // gone wrong ?++            return -1;++        }++        decoder->open = 1;++    } else {++        // we'll open the decoder later...++        decoder->open = 0;++    }++    return 0;++}++++AACDecoder *aac_filter_create()++{++    AACDecoder *decoder = (AACDecoder *)av_malloc(sizeof(AACDecoder));++    decoder->parser = latm_create_parser();++    decoder->aac_decoder = NULL;++    decoder->open = 0;++    return (void *)decoder;++}++++void aac_filter_destroy(AACDecoder *decoder)++{++    aac_filter_close(decoder);++    latm_destroy_parser(decoder->parser);++    av_free(decoder);++}++++int aac_filter_receive(AACDecoder *decoder, void *out, int *out_size, uint8_t *data, int size)++{++    uint8_t    tempbuf[32*1024];++    int        ret;++    int        consumed = size;++    int        decoded;++    int        max_size = *out_size;++    ++    *out_size = 0;++++    //-------------------------------------------------------------------------++    // Multiplex Parsing++    //-------------------------------------------------------------------------++++    latm_write_data(decoder->parser, data, size);++++    do {++        ret = latm_parse_packet(decoder->parser, tempbuf, sizeof(tempbuf));++                if (ret < 0) {++                        latm_flush(decoder->parser);++                        return consumed;++                }++        if (ret == 0) return consumed;++++        data = tempbuf;++        size = ret;++++        //-------------------------------------------------------------------------++        // Initialize decoder (if necessary)++        //-------------------------------------------------------------------------++        if (!decoder->open) {++            aac_filter_close(decoder);++            if (decoder->parser->mode == AAC_LATM) {++                ret = aac_decoder_open(decoder);++                if (ret < 0) return consumed;++            }++++            if(!decoder->open) return consumed;++        }++++        //-------------------------------------------------------------------------++        // Decode samples++        //-------------------------------------------------------------------------++        NeAACDecFrameInfo    info;++        void *buf = NeAACDecDecode(decoder->aac_decoder, &info, data, size);++++        if (buf) {++            decoder->in_samplerate = info.samplerate;++            decoder->in_channels = info.channels;++++            //---------------------------------------------------------------------++            // Deliver decoded samples++            //---------------------------------------------------------------------++++            // kram dekoduje 16-bit. my vypustame 16-bit. takze by to malo byt okej++            decoded = info.samples * sizeof(short);++++            // napraskame tam sample++            *out_size += decoded;++            if(*out_size > max_size) {++                av_log(NULL, AV_LOG_ERROR, "overflow!\n");++            } else {++                memcpy(out, buf, decoded);++                out = (unsigned char *)out + decoded;++            }++        } else {++            // need more data++            break;++        }++++    } while (1);    // decode all packets++    return consumed;++}++++void aac_filter_getinfo(AACDecoder *decoder, int *sample_rate, int *channels)++{++    if(!decoder->open) return;++    *sample_rate = decoder->in_samplerate;++    *channels = decoder->in_channels;++}++++static int faac_decode_init(AVCodecContext *avctx)++{++    FAACContext *s = avctx->priv_data;++    avctx->frame_size = 360;++    avctx->sample_rate = 48000;++    avctx->channels = 2;++    avctx->bit_rate = 8192 * 8 * avctx->sample_rate / avctx->frame_size;++    s->decoder = aac_filter_create();++    return 0;++}++++static int faac_decode_frame(AVCodecContext *avctx,++                             void *data, int *data_size,++                             uint8_t *buf, int buf_size)++{++    FAACContext *s = avctx->priv_data;++    int ret;++++    if (s->decoder == NULL) faac_decode_init(avctx);++    ret = aac_filter_receive(s->decoder, data, data_size, buf, buf_size);++    aac_filter_getinfo(s->decoder, &(avctx->sample_rate), &(avctx->channels));++    return ret;++}++++static int faac_decode_end(AVCodecContext *avctx)++{++    FAACContext *s = avctx->priv_data;++    if(s->decoder != NULL) {++        aac_filter_destroy(s->decoder);++    }++    return 0;++}++++AVCodec libfaad2_decoder = {++    .name = "AAC_LATM",++    .type = CODEC_TYPE_AUDIO,++    .id = CODEC_ID_AAC_LATM,++    .priv_data_size = sizeof (FAACContext),++    .init = faac_decode_init,++    .close = faac_decode_end,++    .decode = faac_decode_frame,++    .long_name = "AAC over LATM",++};+++Index: libavcodec/latm_parser.c+===================================================================+--- libavcodec/latm_parser.c	(revision 0)++++ libavcodec/latm_parser.c	(revision 0)+@@ -0,0 +1,128 @@++/*++ * LATM parser++ * Copyright (c) 2008 Paul Kendall <paul@kcbbs.gen.nz>++ *++ * This file is part of FFmpeg.++ *++ * 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.++ *++ * 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 FFmpeg; if not, write to the Free Software++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA++ */++++/**++ * @file latm_parser.c++ * LATM parser++ */++++#include "parser.h"++++#define LATM_HEADER     0x56e000	// 0x2b7 (11 bits)++#define LATM_MASK       0xFFE000	// top 11 bits++#define LATM_SIZE_MASK  0x001FFF	// bottom 13 bits++++typedef struct LATMParseContext{++    ParseContext pc;++    int count;++} LATMParseContext;++++/**++ * finds the end of the current frame in the bitstream.++ * @return the position of the first byte of the next frame, or -1++ */++static int latm_find_frame_end(AVCodecParserContext *s1, const uint8_t *buf,++                               int buf_size) {++    LATMParseContext *s = s1->priv_data;++    ParseContext *pc = &s->pc;++    int pic_found, i;++    uint32_t state;++++    pic_found = pc->frame_start_found;++    state = pc->state;++++    i = 0;++    if(!pic_found){++        for(i=0; i<buf_size; i++){++            state = (state<<8) | buf[i];++            if((state & LATM_MASK) == LATM_HEADER){++                i++;++                s->count = - i;++                pic_found=1;++                break;++            }++        }++    }++++    if(pic_found){++        /* EOF considered as end of frame */++        if (buf_size == 0)++            return 0;++        if((state & LATM_SIZE_MASK) - s->count <= buf_size) {++            pc->frame_start_found = 0;++            pc->state = -1;++            return (state & LATM_SIZE_MASK) - s->count;++	}++    }++++    s->count += buf_size;++    pc->frame_start_found = pic_found;++    pc->state = state;++    return END_NOT_FOUND;++}++++static int latm_parse(AVCodecParserContext *s1,++                           AVCodecContext *avctx,++                           const uint8_t **poutbuf, int *poutbuf_size,++                           const uint8_t *buf, int buf_size)++{++    LATMParseContext *s = s1->priv_data;++    ParseContext *pc = &s->pc;++    int next;++++    if(s1->flags & PARSER_FLAG_COMPLETE_FRAMES){++        next = buf_size;++    }else{++        next = latm_find_frame_end(s1, buf, buf_size);++++        if (ff_combine_frame(pc, next, &buf, &buf_size) < 0) {++            *poutbuf = NULL;++            *poutbuf_size = 0;++            return buf_size;++        }++    }++    *poutbuf = buf;++    *poutbuf_size = buf_size;++    return next;++}++++static int latm_split(AVCodecContext *avctx,++                           const uint8_t *buf, int buf_size)++{++    int i;++    uint32_t state= -1;++++    for(i=0; i<buf_size; i++){++        state= (state<<8) | buf[i];++        if((state & LATM_MASK) == LATM_HEADER)++            return i-2;++    }++    return 0;++}++++AVCodecParser aac_latm_parser = {++    { CODEC_ID_AAC_LATM },++    sizeof(LATMParseContext),++    NULL,++    latm_parse,++    ff_parse_close,++    latm_split,++};+Index: libavcodec/allcodecs.c+===================================================================+--- libavcodec/allcodecs.c	(revision 14016)++++ libavcodec/allcodecs.c	(working copy)+@@ -280,6 +280,7 @@+     REGISTER_ENCDEC  (LIBDIRAC, libdirac);+     REGISTER_ENCODER (LIBFAAC, libfaac);+     REGISTER_DECODER (LIBFAAD, libfaad);++    REGISTER_DECODER (LIBFAAD, libfaad2);+     REGISTER_ENCDEC  (LIBGSM, libgsm);+     REGISTER_ENCDEC  (LIBGSM_MS, libgsm_ms);+     REGISTER_ENCODER (LIBMP3LAME, libmp3lame);+@@ -294,6 +295,7 @@+ +     /* parsers */+     REGISTER_PARSER  (AAC, aac);++    REGISTER_PARSER  (AAC, aac_latm);+     REGISTER_PARSER  (AC3, ac3);+     REGISTER_PARSER  (CAVSVIDEO, cavsvideo);+     REGISTER_PARSER  (DCA, dca);+Index: libavcodec/avcodec.h+===================================================================+--- libavcodec/avcodec.h	(revision 14016)++++ libavcodec/avcodec.h	(working copy)+@@ -259,6 +259,7 @@+ #if LIBAVCODEC_VERSION_INT < ((52<<16)+(0<<8)+0)+     CODEC_ID_MPEG4AAC,+ #endif++    CODEC_ID_AAC_LATM,+     CODEC_ID_AC3,+     CODEC_ID_DTS,+     CODEC_ID_VORBIS,+Index: libavformat/mpegts.c+===================================================================+--- libavformat/mpegts.c	(revision 14016)++++ libavformat/mpegts.c	(working copy)+@@ -611,6 +611,7 @@+         case STREAM_TYPE_VIDEO_H264:+         case STREAM_TYPE_VIDEO_VC1:+         case STREAM_TYPE_AUDIO_AAC:++        case STREAM_TYPE_AUDIO_AAC_LATM:+         case STREAM_TYPE_AUDIO_AC3:+         case STREAM_TYPE_AUDIO_DTS:+         case STREAM_TYPE_AUDIO_HDMV_DTS:+@@ -832,7 +833,7 @@+                     code = pes->header[3] | 0x100;+                     if (!((code >= 0x1c0 && code <= 0x1df) ||+                           (code >= 0x1e0 && code <= 0x1ef) ||+-                          (code == 0x1bd) || (code == 0x1fd)))++                          (code == 0x1bd) || (code == 0x1fa) || (code == 0x1fd)))+                         goto skip;+                     if (!pes->st) {+                         /* allocate stream */+@@ -948,6 +949,10 @@+         codec_type = CODEC_TYPE_AUDIO;+         codec_id = CODEC_ID_AAC;+         break;++    case STREAM_TYPE_AUDIO_AAC_LATM:++        codec_type = CODEC_TYPE_AUDIO;++        codec_id = CODEC_ID_AAC_LATM;++        break;+     case STREAM_TYPE_AUDIO_AC3:+         codec_type = CODEC_TYPE_AUDIO;+         codec_id = CODEC_ID_AC3;+Index: libavformat/mpegts.h+===================================================================+--- libavformat/mpegts.h	(revision 14016)++++ libavformat/mpegts.h	(working copy)+@@ -50,6 +50,7 @@+ #define STREAM_TYPE_PRIVATE_DATA    0x06+ #define STREAM_TYPE_AUDIO_AAC       0x0f+ #define STREAM_TYPE_VIDEO_MPEG4     0x10++#define STREAM_TYPE_AUDIO_AAC_LATM  0x11+ #define STREAM_TYPE_VIDEO_H264      0x1b+ #define STREAM_TYPE_VIDEO_VC1       0xea+ +Index: libavformat/mpeg.c+===================================================================+--- libavformat/mpeg.c	(revision 14016)++++ libavformat/mpeg.c	(working copy)+@@ -281,7 +281,7 @@+     /* find matching stream */+     if (!((startcode >= 0x1c0 && startcode <= 0x1df) ||+           (startcode >= 0x1e0 && startcode <= 0x1ef) ||+-          (startcode == 0x1bd) || (startcode == 0x1fd)))++          (startcode == 0x1bd) || (startcode == 0x1fa) || (startcode == 0x1fd)))+         goto redo;+     if (ppos) {+         *ppos = url_ftell(s->pb) - 4;+@@ -439,6 +439,9 @@+         } else if(es_type == STREAM_TYPE_AUDIO_AAC){+             codec_id = CODEC_ID_AAC;+             type = CODEC_TYPE_AUDIO;++        } else if(es_type == STREAM_TYPE_AUDIO_AAC_LATM){++            codec_id = CODEC_ID_AAC_LATM;++            type = CODEC_TYPE_AUDIO;+         } else if(es_type == STREAM_TYPE_VIDEO_MPEG4){+             codec_id = CODEC_ID_MPEG4;+             type = CODEC_TYPE_VIDEO;+Index: libavformat/mpeg.h+===================================================================+--- libavformat/mpeg.h	(revision 14016)++++ libavformat/mpeg.h	(working copy)+@@ -53,6 +53,7 @@+ #define STREAM_TYPE_PRIVATE_DATA    0x06+ #define STREAM_TYPE_AUDIO_AAC       0x0f+ #define STREAM_TYPE_VIDEO_MPEG4     0x10++#define STREAM_TYPE_AUDIO_AAC_LATM  0x11+ #define STREAM_TYPE_VIDEO_H264      0x1b+ + #define STREAM_TYPE_AUDIO_AC3       0x81Index: Jamfile===================================================================--- Jamfile	(revision 1546)+++ Jamfile	(working copy)@@ -78,6 +78,7 @@ rule LibAvCodec {     FFMPEG_PATCH = "$(PATCH) -p0 < ../patch-ffmpeg.patch" ;+    FFMPEG_PATCH += " && $(PATCH) -p0 < ../patch-ffmpeg-latm.patch " ;     if $(OS) = CYGWIN     {         FFMPEG_PATCH += " && $(PATCH) -p1 < ../patch-ffmpeg-cygwin.patch " ;