changeset 25834:69a4d646e55d

generic functions and structures to parse and statekeep LATM streams
author nicodvb
date Sat, 26 Jan 2008 18:31:48 +0000
parents ed27d1c01f93
children 645cbba10a57
files libfaad2/neaacdec.h libfaad2/structs.h libfaad2/syntax.c libfaad2/syntax.h
diffstat 4 files changed, 207 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- a/libfaad2/neaacdec.h	Sat Jan 26 18:21:44 2008 +0000
+++ b/libfaad2/neaacdec.h	Sat Jan 26 18:31:48 2008 +0000
@@ -83,6 +83,7 @@
 #define RAW        0
 #define ADIF       1
 #define ADTS       2
+#define LATM       3
 
 /* SBR signalling */
 #define NO_SBR           0
--- a/libfaad2/structs.h	Sat Jan 26 18:21:44 2008 +0000
+++ b/libfaad2/structs.h	Sat Jan 26 18:31:48 2008 +0000
@@ -330,6 +330,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;
@@ -372,6 +389,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;
@@ -463,6 +481,7 @@
     int64_t scalefac_cycles;
     int64_t requant_cycles;
 #endif
+    latm_header latm_config;
 } NeAACDecStruct, *NeAACDecHandle;
 
 
--- a/libfaad2/syntax.c	Sat Jan 26 18:21:44 2008 +0000
+++ b/libfaad2/syntax.c	Sat Jan 26 18:31:48 2008 +0000
@@ -2329,3 +2329,188 @@
             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 && !ld->no_more_reading)
+    {
+        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/libfaad2/syntax.h	Sat Jan 26 18:21:44 2008 +0000
+++ b/libfaad2/syntax.h	Sat Jan 26 18:31:48 2008 +0000
@@ -49,6 +49,7 @@
 #define RAW        0
 #define ADIF       1
 #define ADTS       2
+#define LATM       3
 
 /* SBR signalling */
 #define NO_SBR           0
@@ -116,6 +117,7 @@
                                 int16_t *spectral_data);
 void aac_scalable_main_element(NeAACDecHandle hDecoder, NeAACDecFrameInfo *hInfo,
                                bitfile *ld, program_config *pce, drc_info *drc);
+uint32_t faad_latm_frame(latm_header *latm, bitfile *ld);
 
 
 #ifdef __cplusplus