shithub: aacdec

Download patch

ref: facf1c46148257b9fc33c4b5552e187bd7e5f461
parent: 2ed7cad8bfd9b8bec0ac6856e92963cfe8ee36bf
author: menno <menno>
date: Sun Mar 23 19:03:30 EDT 2008

Applied some patches received

--- a/common/mp4ff/mp4ff_int_types.h
+++ b/common/mp4ff/mp4ff_int_types.h
@@ -3,6 +3,10 @@
 
 #if defined (_WIN32)
 
+#ifdef __MINGW32__
+#include <stdlib.h>
+#endif /* #ifdef __MINGW32__ */
+
 typedef char int8_t;
 typedef unsigned char uint8_t;
 typedef short int16_t;
--- a/frontend/main.c
+++ b/frontend/main.c
@@ -25,7 +25,7 @@
 ** Commercial non-GPL licensing of this software is possible.
 ** For more info contact Nero AG through Mpeg4AAClicense@nero.com.
 **
-** $Id: main.c,v 1.81 2007/11/01 12:33:29 menno Exp $
+** $Id: main.c,v 1.82 2008/03/23 23:03:27 menno Exp $
 **/
 
 #ifdef _WIN32
@@ -40,6 +40,7 @@
 #include <stdio.h>
 #include <stdarg.h>
 #include <stdlib.h>
+#include <string.h>
 #include <getopt.h>
 
 #include <neaacdec.h>
@@ -640,8 +641,9 @@
 
         if ((frameInfo.error == 0) && (frameInfo.samples > 0) && (!adts_out))
         {
-            write_audio_file(aufile, sample_buffer, frameInfo.samples, 0);
-        }
+            if (write_audio_file(aufile, sample_buffer, frameInfo.samples, 0) == 0)
+                break;
+		}
 
         /* fill buffer */
         fill_buffer(&b);
@@ -976,7 +978,8 @@
 
         if ((frameInfo.error == 0) && (sample_count > 0) && (!adts_out))
         {
-            write_audio_file(aufile, sample_buffer, sample_count, delay);
+            if (write_audio_file(aufile, sample_buffer, sample_count, delay) == 0)
+                break;
         }
 
         if (frameInfo.error > 0)
--- a/include/neaacdec.h
+++ b/include/neaacdec.h
@@ -25,7 +25,7 @@
 ** Commercial non-GPL licensing of this software is possible.
 ** For more info contact Nero AG through Mpeg4AAClicense@nero.com.
 **
-** $Id: neaacdec.h,v 1.11 2007/11/01 12:33:29 menno Exp $
+** $Id: neaacdec.h,v 1.12 2008/03/23 23:03:27 menno Exp $
 **/
 
 #ifndef __NEAACDEC_H__
@@ -69,7 +69,7 @@
   #endif
 #endif
 
-#define FAAD2_VERSION "2.6"
+#define FAAD2_VERSION "2.7"
 
 /* object types for AAC */
 #define MAIN       1
@@ -86,6 +86,7 @@
 #define RAW        0
 #define ADIF       1
 #define ADTS       2
+#define LATM       3
 
 /* SBR signalling */
 #define NO_SBR           0
--- a/libfaad/common.c
+++ b/libfaad/common.c
@@ -25,7 +25,7 @@
 ** Commercial non-GPL licensing of this software is possible.
 ** For more info contact Nero AG through Mpeg4AAClicense@nero.com.
 **
-** $Id: common.c,v 1.26 2007/11/01 12:33:30 menno Exp $
+** $Id: common.c,v 1.27 2008/03/23 23:03:28 menno Exp $
 **/
 
 /* just some common functions that could be used anywhere */
@@ -244,7 +244,7 @@
     return (*__r1 = (t3 >> 1) | t1 ) ^ (*__r2 = (t4 + t4) | t2 );
 }
 
-uint32_t ones32(uint32_t x)
+static uint32_t ones32(uint32_t x)
 {
     x -= ((x >> 1) & 0x55555555);
     x = (((x >> 2) & 0x33333333) + (x & 0x33333333));
@@ -255,7 +255,7 @@
     return (x & 0x0000003f);
 }
 
-uint32_t floor_log2(uint32_t x)
+static uint32_t floor_log2(uint32_t x)
 {
 #if 1
     x |= (x >> 1);
--- a/libfaad/common.h
+++ b/libfaad/common.h
@@ -25,7 +25,7 @@
 ** Commercial non-GPL licensing of this software is possible.
 ** For more info contact Nero AG through Mpeg4AAClicense@nero.com.
 **
-** $Id: common.h,v 1.72 2007/11/01 12:33:30 menno Exp $
+** $Id: common.h,v 1.73 2008/03/23 23:03:28 menno Exp $
 **/
 
 #ifndef __COMMON_H__
@@ -405,8 +405,6 @@
 /* common functions */
 uint8_t cpu_has_sse(void);
 uint32_t ne_rng(uint32_t *__r1, uint32_t *__r2);
-uint32_t ones32(uint32_t x);
-uint32_t floor_log2(uint32_t x);
 uint32_t wl_min_lzc(uint32_t x);
 #ifdef FIXED_POINT
 #define LOG2_MIN_INF REAL_CONST(-10000)
--- a/libfaad/decoder.c
+++ b/libfaad/decoder.c
@@ -25,7 +25,7 @@
 ** Commercial non-GPL licensing of this software is possible.
 ** For more info contact Nero AG through Mpeg4AAClicense@nero.com.
 **
-** $Id: decoder.c,v 1.111 2007/11/01 12:33:30 menno Exp $
+** $Id: decoder.c,v 1.112 2008/03/23 23:03:28 menno Exp $
 **/
 
 #include "common.h"
@@ -32,6 +32,7 @@
 #include "structs.h"
 
 #include <stdlib.h>
+#include <stdio.h>
 #include <string.h>
 
 #include "decoder.h"
@@ -111,6 +112,7 @@
     hDecoder->config.downMatrix = 0;
     hDecoder->adts_header_present = 0;
     hDecoder->adif_header_present = 0;
+	hDecoder->latm_header_present = 0;
 #ifdef ERROR_RESILIENCE
     hDecoder->aacSectionDataResilienceFlag = 0;
     hDecoder->aacScalefactorDataResilienceFlag = 0;
@@ -203,6 +205,31 @@
 }
 
 
+static int latmCheck(latm_header *latm, bitfile *ld)
+{
+    uint32_t good=0, bad=0, bits, m;
+
+    while(!ld->error)
+    {
+        bits = faad_latm_frame(latm, ld);
+        if(bits==-1U)
+            bad++;
+        else
+        {
+            good++;
+            while(bits>0)
+            {
+                m = min(bits, 8);
+                faad_getbits(ld, m);
+                bits -= m;
+            }
+        }
+    }
+
+    return (good>0);
+}
+
+
 int32_t NEAACDECAPI NeAACDecInit(NeAACDecHandle hDecoder, uint8_t *buffer,
                                  uint32_t buffer_size,
                                  uint32_t *samplerate, uint8_t *channels)
@@ -223,12 +250,29 @@
 
     if (buffer != NULL)
     {
-        faad_initbits(&ld, buffer, buffer_size);
+        int is_latm;
+        latm_header *l = &hDecoder->latm_config;
 
-        /* Check if an ADIF header is present */
-        if ((buffer[0] == 'A') && (buffer[1] == 'D') &&
-            (buffer[2] == 'I') && (buffer[3] == 'F'))
+        faad_initbits(&ld, buffer, buffer_size);
+ 
+        memset(l, 0, sizeof(latm_header));
+        is_latm = latmCheck(l, &ld);
+        l->inited = 0;
+        l->frameLength = 0;
+        faad_rewindbits(&ld);
+        if(is_latm && l->ASCbits>0)
         {
+            int32_t x;
+            hDecoder->latm_header_present = 1;
+            x = NeAACDecInit2(hDecoder, l->ASC, (l->ASCbits+7)/8, samplerate, channels);
+            if(x!=0)
+                hDecoder->latm_header_present = 0;
+            return x;
+        }
+        /* Check if an ADIF header is present */
+        else if ((buffer[0] == 'A') && (buffer[1] == 'D') &&
+			(buffer[2] == 'I') && (buffer[3] == 'F'))
+		{
             hDecoder->adif_header_present = 1;
 
             get_adif_header(&adif, &ld);
@@ -331,7 +375,7 @@
 
     /* decode the audio specific config */
     rc = AudioSpecificConfig2(pBuffer, SizeOfDecoderSpecificInfo, &mp4ASC,
-        &(hDecoder->pce));
+        &(hDecoder->pce), hDecoder->latm_header_present);
 
     /* copy the relevant info to the decoder handle */
     *samplerate = mp4ASC.samplingFrequency;
@@ -768,6 +812,7 @@
     uint32_t bitsconsumed;
     uint16_t frame_len;
     void *sample_buffer;
+    uint32_t startbit=0, endbit=0, payload_bits=0;
 
 #ifdef PROFILE
     int64_t count = faad_get_ts();
@@ -837,6 +882,17 @@
     }
 #endif
 
+    if(hDecoder->latm_header_present)
+    {
+        payload_bits = faad_latm_frame(&hDecoder->latm_config, &ld);
+        startbit = faad_get_processed_bits(&ld);
+        if(payload_bits == -1U)
+        {
+            hInfo->error = 1;
+            goto error;
+        }
+    }
+
 #ifdef DRM
     if (hDecoder->object_type == DRM_ER_LC)
     {
@@ -882,6 +938,17 @@
     }
 #endif
 
+    if(hDecoder->latm_header_present)
+    {
+        endbit = faad_get_processed_bits(&ld);
+        if(endbit-startbit > payload_bits)
+            fprintf(stderr, "\r\nERROR, too many payload bits read: %u > %d. Please. report with a link to a sample\n",
+                endbit-startbit, payload_bits);
+        if(hDecoder->latm_config.otherDataLenBits > 0)
+            faad_getbits(&ld, hDecoder->latm_config.otherDataLenBits);
+        faad_byte_align(&ld);
+    }
+
     channels = hDecoder->fr_channels;
 
     if (hInfo->error > 0)
@@ -906,7 +973,7 @@
     faad_endbits(&ld);
 
 
-    if (!hDecoder->adts_header_present && !hDecoder->adif_header_present)
+    if (!hDecoder->adts_header_present && !hDecoder->adif_header_present && !hDecoder->latm_header_present)
     {
         if (hDecoder->channelConfiguration == 0)
             hDecoder->channelConfiguration = channels;
@@ -955,6 +1022,8 @@
         hInfo->header_type = ADIF;
     if (hDecoder->adts_header_present)
         hInfo->header_type = ADTS;
+    if (hDecoder->latm_header_present)
+        hInfo->header_type = LATM;
 #if (defined(PS_DEC) || defined(DRM_PS))
     hInfo->ps = hDecoder->ps_used_global;
 #endif
--- a/libfaad/hcr.c
+++ b/libfaad/hcr.c
@@ -25,7 +25,7 @@
 ** Commercial non-GPL licensing of this software is possible.
 ** For more info contact Nero AG through Mpeg4AAClicense@nero.com.
 **
-** $Id: hcr.c,v 1.24 2007/11/01 12:33:30 menno Exp $
+** $Id: hcr.c,v 1.25 2008/03/23 23:03:28 menno Exp $
 **/
 
 #include "common.h"
@@ -173,7 +173,7 @@
     b->len += a->len;
 }
      
-uint8_t is_good_cb(uint8_t this_CB, uint8_t this_sec_CB)
+static uint8_t is_good_cb(uint8_t this_CB, uint8_t this_sec_CB)
 {
     /* only want spectral data CB's */
     if ((this_sec_CB > ZERO_HCB && this_sec_CB <= ESC_HCB) || (this_sec_CB >= VCB11_FIRST && this_sec_CB <= VCB11_LAST))
@@ -191,7 +191,7 @@
     return 0;
 }
                     
-void read_segment(bits_t *segment, uint8_t segwidth, bitfile *ld)
+static void read_segment(bits_t *segment, uint8_t segwidth, bitfile *ld)
 {
     segment->len = segwidth;
 
@@ -206,7 +206,7 @@
     }    
 }
 
-void fill_in_codeword(codeword_t *codeword, uint16_t index, uint16_t sp, uint8_t cb)
+static void fill_in_codeword(codeword_t *codeword, uint16_t index, uint16_t sp, uint8_t cb)
 {
     codeword[index].sp_offset = sp;
     codeword[index].cb = cb;
--- a/libfaad/mp4.c
+++ b/libfaad/mp4.c
@@ -25,7 +25,7 @@
 ** Commercial non-GPL licensing of this software is possible.
 ** For more info contact Nero AG through Mpeg4AAClicense@nero.com.
 **
-** $Id: mp4.c,v 1.38 2007/11/01 12:33:32 menno Exp $
+** $Id: mp4.c,v 1.39 2008/03/23 23:03:29 menno Exp $
 **/
 
 #include "common.h"
@@ -118,37 +118,33 @@
                                                uint32_t buffer_size,
                                                mp4AudioSpecificConfig *mp4ASC)
 {
-    return AudioSpecificConfig2(pBuffer, buffer_size, mp4ASC, NULL);
+    return AudioSpecificConfig2(pBuffer, buffer_size, mp4ASC, NULL, 0);
 }
 
-int8_t AudioSpecificConfig2(uint8_t *pBuffer,
-                            uint32_t buffer_size,
+int8_t AudioSpecificConfigFromBitfile(bitfile *ld,
                             mp4AudioSpecificConfig *mp4ASC,
-                            program_config *pce)
+                            program_config *pce, uint32_t buffer_size, uint8_t short_form)
 {
-    bitfile ld;
     int8_t result = 0;
+    uint32_t startpos = faad_get_processed_bits(ld);
 #ifdef SBR_DEC
     int8_t bits_to_decode = 0;
 #endif
 
-    if (pBuffer == NULL)
-        return -7;
     if (mp4ASC == NULL)
         return -8;
 
     memset(mp4ASC, 0, sizeof(mp4AudioSpecificConfig));
 
-    faad_initbits(&ld, pBuffer, buffer_size);
-    faad_byte_align(&ld);
-
-    mp4ASC->objectTypeIndex = (uint8_t)faad_getbits(&ld, 5
+    mp4ASC->objectTypeIndex = (uint8_t)faad_getbits(ld, 5
         DEBUGVAR(1,1,"parse_audio_decoder_specific_info(): ObjectTypeIndex"));
 
-    mp4ASC->samplingFrequencyIndex = (uint8_t)faad_getbits(&ld, 4
+    mp4ASC->samplingFrequencyIndex = (uint8_t)faad_getbits(ld, 4
         DEBUGVAR(1,2,"parse_audio_decoder_specific_info(): SamplingFrequencyIndex"));
+	if(mp4ASC->samplingFrequencyIndex==0x0f)
+		faad_getbits(ld, 24);
 
-    mp4ASC->channelsConfiguration = (uint8_t)faad_getbits(&ld, 4
+    mp4ASC->channelsConfiguration = (uint8_t)faad_getbits(ld, 4
         DEBUGVAR(1,3,"parse_audio_decoder_specific_info(): ChannelsConfiguration"));
 
     mp4ASC->samplingFrequency = get_sample_rate(mp4ASC->samplingFrequencyIndex);
@@ -155,19 +151,16 @@
 
     if (ObjectTypesTable[mp4ASC->objectTypeIndex] != 1)
     {
-        faad_endbits(&ld);
         return -1;
     }
 
     if (mp4ASC->samplingFrequency == 0)
     {
-        faad_endbits(&ld);
         return -2;
     }
 
     if (mp4ASC->channelsConfiguration > 7)
     {
-        faad_endbits(&ld);
         return -3;
     }
 
@@ -187,7 +180,7 @@
         uint8_t tmp;
 
         mp4ASC->sbr_present_flag = 1;
-        tmp = (uint8_t)faad_getbits(&ld, 4
+        tmp = (uint8_t)faad_getbits(ld, 4
             DEBUGVAR(1,5,"parse_audio_decoder_specific_info(): extensionSamplingFrequencyIndex"));
         /* check for downsampled SBR */
         if (tmp == mp4ASC->samplingFrequencyIndex)
@@ -195,12 +188,12 @@
         mp4ASC->samplingFrequencyIndex = tmp;
         if (mp4ASC->samplingFrequencyIndex == 15)
         {
-            mp4ASC->samplingFrequency = (uint32_t)faad_getbits(&ld, 24
+            mp4ASC->samplingFrequency = (uint32_t)faad_getbits(ld, 24
                 DEBUGVAR(1,6,"parse_audio_decoder_specific_info(): extensionSamplingFrequencyIndex"));
         } else {
             mp4ASC->samplingFrequency = get_sample_rate(mp4ASC->samplingFrequencyIndex);
         }
-        mp4ASC->objectTypeIndex = (uint8_t)faad_getbits(&ld, 5
+        mp4ASC->objectTypeIndex = (uint8_t)faad_getbits(ld, 5
             DEBUGVAR(1,7,"parse_audio_decoder_specific_info(): ObjectTypeIndex"));
     }
 #endif
@@ -210,12 +203,12 @@
         mp4ASC->objectTypeIndex == 3 || mp4ASC->objectTypeIndex == 4 ||
         mp4ASC->objectTypeIndex == 6 || mp4ASC->objectTypeIndex == 7)
     {
-        result = GASpecificConfig(&ld, mp4ASC, pce);
+        result = GASpecificConfig(ld, mp4ASC, pce);
 
 #ifdef ERROR_RESILIENCE
     } else if (mp4ASC->objectTypeIndex >= ER_OBJECT_START) { /* ER */
-        result = GASpecificConfig(&ld, mp4ASC, pce);
-        mp4ASC->epConfig = (uint8_t)faad_getbits(&ld, 2
+        result = GASpecificConfig(ld, mp4ASC, pce);
+        mp4ASC->epConfig = (uint8_t)faad_getbits(ld, 2
             DEBUGVAR(1,143,"parse_audio_decoder_specific_info(): epConfig"));
 
         if (mp4ASC->epConfig != 0)
@@ -234,21 +227,24 @@
 
 
 #ifdef SBR_DEC
-    bits_to_decode = (int8_t)(buffer_size*8 - faad_get_processed_bits(&ld));
+    if(short_form)
+        bits_to_decode = 0;
+    else
+		bits_to_decode = (int8_t)(buffer_size*8 - (startpos-faad_get_processed_bits(ld)));
 
     if ((mp4ASC->objectTypeIndex != 5) && (bits_to_decode >= 16))
     {
-        int16_t syncExtensionType = (int16_t)faad_getbits(&ld, 11
+        int16_t syncExtensionType = (int16_t)faad_getbits(ld, 11
             DEBUGVAR(1,9,"parse_audio_decoder_specific_info(): syncExtensionType"));
 
         if (syncExtensionType == 0x2b7)
         {
-            uint8_t tmp_OTi = (uint8_t)faad_getbits(&ld, 5
+            uint8_t tmp_OTi = (uint8_t)faad_getbits(ld, 5
                 DEBUGVAR(1,10,"parse_audio_decoder_specific_info(): extensionAudioObjectType"));
 
             if (tmp_OTi == 5)
             {
-                mp4ASC->sbr_present_flag = (uint8_t)faad_get1bit(&ld
+                mp4ASC->sbr_present_flag = (uint8_t)faad_get1bit(ld
                     DEBUGVAR(1,11,"parse_audio_decoder_specific_info(): sbr_present_flag"));
 
                 if (mp4ASC->sbr_present_flag)
@@ -258,7 +254,7 @@
 					/* Don't set OT to SBR until checked that it is actually there */
 					mp4ASC->objectTypeIndex = tmp_OTi;
 
-                    tmp = (uint8_t)faad_getbits(&ld, 4
+                    tmp = (uint8_t)faad_getbits(ld, 4
                         DEBUGVAR(1,12,"parse_audio_decoder_specific_info(): extensionSamplingFrequencyIndex"));
 
                     /* check for downsampled SBR */
@@ -268,7 +264,7 @@
 
                     if (mp4ASC->samplingFrequencyIndex == 15)
                     {
-                        mp4ASC->samplingFrequency = (uint32_t)faad_getbits(&ld, 24
+                        mp4ASC->samplingFrequency = (uint32_t)faad_getbits(ld, 24
                             DEBUGVAR(1,13,"parse_audio_decoder_specific_info(): extensionSamplingFrequencyIndex"));
                     } else {
                         mp4ASC->samplingFrequency = get_sample_rate(mp4ASC->samplingFrequencyIndex);
@@ -292,7 +288,22 @@
     }
 #endif
 
-    faad_endbits(&ld);
+    faad_endbits(ld);
 
     return result;
+}
+
+int8_t AudioSpecificConfig2(uint8_t *pBuffer,
+                            uint32_t buffer_size,
+                            mp4AudioSpecificConfig *mp4ASC,
+                            program_config *pce,
+                            uint8_t short_form)
+{
+    uint8_t ret = 0;
+    bitfile ld;
+    faad_initbits(&ld, pBuffer, buffer_size);
+    faad_byte_align(&ld);
+    ret = AudioSpecificConfigFromBitfile(&ld, mp4ASC, pce, buffer_size, short_form);
+    faad_endbits(&ld);
+    return ret;
 }
--- a/libfaad/mp4.h
+++ b/libfaad/mp4.h
@@ -25,7 +25,7 @@
 ** Commercial non-GPL licensing of this software is possible.
 ** For more info contact Nero AG through Mpeg4AAClicense@nero.com.
 **
-** $Id: mp4.h,v 1.25 2007/11/01 12:33:32 menno Exp $
+** $Id: mp4.h,v 1.26 2008/03/23 23:03:29 menno Exp $
 **/
 
 #ifndef __MP4_H__
@@ -44,7 +44,11 @@
 int8_t AudioSpecificConfig2(uint8_t *pBuffer,
                             uint32_t buffer_size,
                             mp4AudioSpecificConfig *mp4ASC,
-                            program_config *pce);
+                            program_config *pce, uint8_t short_form);
+ 
+int8_t AudioSpecificConfigFromBitfile(bitfile *ld,
+                                      mp4AudioSpecificConfig *mp4ASC,
+                                      program_config *pce, uint32_t bsize, uint8_t short_form);
 
 #ifdef __cplusplus
 }
--- a/libfaad/sbr_e_nf.c
+++ b/libfaad/sbr_e_nf.c
@@ -25,7 +25,7 @@
 ** Commercial non-GPL licensing of this software is possible.
 ** For more info contact Nero AG through Mpeg4AAClicense@nero.com.
 **
-** $Id: sbr_e_nf.c,v 1.21 2007/11/01 12:33:35 menno Exp $
+** $Id: sbr_e_nf.c,v 1.22 2008/03/23 23:03:29 menno Exp $
 **/
 
 #include "common.h"
@@ -234,7 +234,7 @@
 
 /* calculates 1/(1+Q) */
 /* [0..1] */
-real_t calc_Q_div(sbr_info *sbr, uint8_t ch, uint8_t m, uint8_t l)
+static real_t calc_Q_div(sbr_info *sbr, uint8_t ch, uint8_t m, uint8_t l)
 {
     if (sbr->bs_coupling)
     {
@@ -353,7 +353,7 @@
 
 /* calculates Q/(1+Q) */
 /* [0..1] */
-real_t calc_Q_div2(sbr_info *sbr, uint8_t ch, uint8_t m, uint8_t l)
+static real_t calc_Q_div2(sbr_info *sbr, uint8_t ch, uint8_t m, uint8_t l)
 {
     if (sbr->bs_coupling)
     {
--- a/libfaad/structs.h
+++ b/libfaad/structs.h
@@ -25,7 +25,7 @@
 ** Commercial non-GPL licensing of this software is possible.
 ** For more info contact Nero AG through Mpeg4AAClicense@nero.com.
 **
-** $Id: structs.h,v 1.46 2007/11/01 12:33:40 menno Exp $
+** $Id: structs.h,v 1.47 2008/03/23 23:03:29 menno Exp $
 **/
 
 #ifndef __STRUCTS_H__
@@ -335,6 +335,23 @@
     /*uint8_t*/ char downSampledSBR;
 } mp4AudioSpecificConfig;
 
+#define MAX_ASC_BYTES 64
+typedef struct {
+    int inited;
+    int version, versionA;
+    int framelen_type;
+    int useSameStreamMux;
+    int allStreamsSameTimeFraming;
+    int numSubFrames;
+    int numPrograms;
+    int numLayers;
+    int otherDataPresent;
+    uint32_t otherDataLenBits;
+    uint32_t frameLength;
+    uint8_t ASC[MAX_ASC_BYTES];
+    uint32_t ASCbits;
+} latm_header;
+
 typedef struct NeAACDecConfiguration
 {
     /*uint8_t*/ unsigned char defObjectType;
@@ -377,6 +394,7 @@
 {
     uint8_t adts_header_present;
     uint8_t adif_header_present;
+    uint8_t latm_header_present;
     uint8_t sf_index;
     uint8_t object_type;
     uint8_t channelConfiguration;
@@ -476,6 +494,7 @@
     int64_t scalefac_cycles;
     int64_t requant_cycles;
 #endif
+	latm_header latm_config;
 	const unsigned char *cmes;
 } NeAACDecStruct, *NeAACDecHandle;
 
--- a/libfaad/syntax.c
+++ b/libfaad/syntax.c
@@ -25,7 +25,7 @@
 ** Commercial non-GPL licensing of this software is possible.
 ** For more info contact Nero AG through Mpeg4AAClicense@nero.com.
 **
-** $Id: syntax.c,v 1.89 2007/11/01 12:33:40 menno Exp $
+** $Id: syntax.c,v 1.90 2008/03/23 23:03:29 menno Exp $
 **/
 
 /*
@@ -36,6 +36,7 @@
 #include "structs.h"
 
 #include <stdlib.h>
+#include <stdio.h>
 #include <string.h>
 
 #include "decoder.h"
@@ -52,6 +53,7 @@
 #ifdef SBR_DEC
 #include "sbr_syntax.h"
 #endif
+#include "mp4.h"
 
 
 /* static function declarations */
@@ -154,10 +156,10 @@
                 DEBUGVAR(1,145,"GASpecificConfig(): aacScalefactorDataResilienceFlag"));
             mp4ASC->aacSpectralDataResilienceFlag = faad_get1bit(ld
                 DEBUGVAR(1,146,"GASpecificConfig(): aacSpectralDataResilienceFlag"));
-
-            /* 1 bit: extensionFlag3 */
         }
-    }
+        /* 1 bit: extensionFlag3 */
+        faad_getbits(ld, 1);
+	}
 #endif
 
     return 0;
@@ -573,7 +575,7 @@
 
     /* new in corrigendum 14496-3:2002 */
 #ifdef DRM
-    if (hDecoder->object_type != DRM_ER_LC)
+    if (hDecoder->object_type != DRM_ER_LC && !hDecoder->latm_header_present)
 #endif
     {
         faad_byte_align(ld);
@@ -2441,4 +2443,189 @@
         adts->crc_check = (uint16_t)faad_getbits(ld, 16
             DEBUGVAR(1,134,"adts_error_check(): crc_check"));
     }
+}
+
+/* LATM parsing functions */
+
+static uint32_t latm_get_value(bitfile *ld)
+{
+    uint32_t l, value;
+    uint8_t bytesForValue;
+
+    bytesForValue = (uint8_t)faad_getbits(ld, 2);
+    value = 0;
+    for(l=0; l<bytesForValue; l++)
+        value = (value << 8) | (uint8_t)faad_getbits(ld, 8);
+
+    return value;
+}
+
+
+static uint32_t latmParsePayload(latm_header *latm, bitfile *ld)
+{
+    //assuming there's only one program with a single layer and 1 subFrame,
+    //allStreamsSametimeframing is set,
+    uint32_t framelen;
+    uint8_t tmp;
+
+    //this should be the payload length field for the current configuration
+    framelen = 0;
+    if(latm->framelen_type==0)
+    {
+        do
+        {
+            tmp = (uint8_t)faad_getbits(ld, 8);
+            framelen += tmp;
+        } while(tmp==0xff);
+    }
+    else if(latm->framelen_type==1)
+        framelen=latm->frameLength;
+
+    return framelen;
+}
+
+
+static uint32_t latmAudioMuxElement(latm_header *latm, bitfile *ld)
+{
+    uint32_t ascLen, asc_bits=0;
+    uint32_t x1, y1, m, n, i;
+    program_config pce;
+    mp4AudioSpecificConfig mp4ASC;
+
+    latm->useSameStreamMux = (uint8_t)faad_getbits(ld, 1);
+    if(!latm->useSameStreamMux)
+    {
+        //parseSameStreamMuxConfig
+        latm->version = (uint8_t) faad_getbits(ld, 1);
+        if(latm->version)
+            latm->versionA = (uint8_t) faad_getbits(ld, 1);
+        if(latm->versionA)
+        {
+            //dunno the payload format for versionA
+            fprintf(stderr, "versionA not supported\n");
+            return 0;
+        }
+        if(latm->version) //read taraBufferFullness
+            latm_get_value(ld);
+        latm->allStreamsSameTimeFraming = (uint8_t)faad_getbits(ld, 1);
+        latm->numSubFrames = (uint8_t)faad_getbits(ld, 6) + 1;
+        latm->numPrograms = (uint8_t)faad_getbits(ld, 4) + 1;
+        latm->numLayers = faad_getbits(ld, 3) + 1;
+        if(latm->numPrograms>1 || !latm->allStreamsSameTimeFraming || latm->numSubFrames>1 || latm->numLayers>1)
+        {
+            fprintf(stderr, "\r\nUnsupported LATM configuration: %d programs/ %d subframes, %d layers, allstreams: %d\n",
+                latm->numPrograms, latm->numSubFrames, latm->numLayers, latm->allStreamsSameTimeFraming);
+            return 0;
+        }
+        ascLen = 0;
+        if(latm->version)
+            ascLen = latm_get_value(ld);
+
+        x1 = faad_get_processed_bits(ld);
+        if(AudioSpecificConfigFromBitfile(ld, &mp4ASC, &pce, 0, 1) < 0)
+            return 0;
+
+        //horrid hack to unread the ASC bits and store them in latm->ASC
+        //the correct code would rely on an ideal faad_ungetbits()
+        y1 = faad_get_processed_bits(ld);
+        if((y1-x1) <= MAX_ASC_BYTES*8)
+        {
+            faad_rewindbits(ld);
+            m = x1;
+            while(m>0)
+            {
+                n = min(m, 32);
+                faad_getbits(ld, n);
+                m -= n;
+            }
+
+            i = 0;
+            m = latm->ASCbits = y1 - x1;
+            while(m > 0)
+            {
+                n = min(m, 8);
+                latm->ASC[i++] = (uint8_t) faad_getbits(ld, n);
+                m -= n;
+            }
+        }
+
+        asc_bits = y1-x1;
+
+        if(ascLen>asc_bits)
+            faad_getbits(ld, ascLen-asc_bits);
+
+        latm->framelen_type = (uint8_t) faad_getbits(ld, 3);
+        if(latm->framelen_type == 0)
+        {
+            latm->frameLength = 0;
+            faad_getbits(ld, 8); //buffer fullness for frame_len_type==0, useless
+        }
+        else if(latm->framelen_type == 1)
+        {
+            latm->frameLength = faad_getbits(ld, 9);
+            if(latm->frameLength==0)
+            {
+                fprintf(stderr, "Invalid frameLength: 0\r\n");
+                return 0;
+            }
+            latm->frameLength = (latm->frameLength+20)*8;
+        }
+        else
+        {   //hellish CELP or HCVX stuff, discard
+            fprintf(stderr, "Unsupported CELP/HCVX framelentype: %d\n", latm->framelen_type);
+            return 0;
+        }
+
+        latm->otherDataLenBits = 0;
+        if(faad_getbits(ld, 1))
+        {   //other data present
+            int esc, tmp;
+            if(latm->version)
+                latm->otherDataLenBits = latm_get_value(ld);
+            else do
+            {
+                esc = faad_getbits(ld, 1);
+                tmp = faad_getbits(ld, 8);
+                latm->otherDataLenBits = (latm->otherDataLenBits << 8) + tmp;
+            } while(esc);
+        }
+        if(faad_getbits(ld, 1)) //crc
+            faad_getbits(ld, 8);
+        latm->inited = 1;
+      }
+
+      //read payload
+      if(latm->inited)
+          return latmParsePayload(latm, ld);
+      else
+          return 0;
+}
+
+
+uint32_t faad_latm_frame(latm_header *latm, bitfile *ld)
+{
+    uint16_t len;
+    uint32_t initpos, endpos, firstpos, ret;
+
+    firstpos = faad_get_processed_bits(ld);
+    while(!ld->error)
+    {
+        faad_byte_align(ld);
+        if(faad_showbits(ld, 11) != 0x2B7)
+        {
+            faad_getbits(ld, 8);
+            continue;
+        }
+        faad_getbits(ld, 11);
+        len = faad_getbits(ld, 13);
+        if(!len)
+            continue;
+        initpos = faad_get_processed_bits(ld);
+        ret = latmAudioMuxElement(latm, ld);
+        endpos = faad_get_processed_bits(ld);
+        if(ret>0)
+            return (len*8)-(endpos-initpos);
+        //faad_getbits(ld, initpos-endpos); //go back to initpos, but is valid a getbits(-N) ? 
+    }
+    return -1U;
 }
--- a/libfaad/syntax.h
+++ b/libfaad/syntax.h
@@ -25,7 +25,7 @@
 ** Commercial non-GPL licensing of this software is possible.
 ** For more info contact Nero AG through Mpeg4AAClicense@nero.com.
 **
-** $Id: syntax.h,v 1.58 2007/11/01 12:33:40 menno Exp $
+** $Id: syntax.h,v 1.59 2008/03/23 23:03:30 menno Exp $
 **/
 
 #ifndef __SYNTAX_H__
@@ -52,6 +52,7 @@
 #define RAW        0
 #define ADIF       1
 #define ADTS       2
+#define LATM       3
 
 /* SBR signalling */
 #define NO_SBR           0
@@ -121,6 +122,7 @@
 void DRM_aac_scalable_main_element(NeAACDecHandle hDecoder, NeAACDecFrameInfo *hInfo,
                                    bitfile *ld, program_config *pce, drc_info *drc);
 #endif
+uint32_t faad_latm_frame(latm_header *latm, bitfile *ld);
 
 #ifdef __cplusplus
 }