From 46cfd2988bb1fe6cd26aced8ab8af4c7a7c5ca2a Mon Sep 17 00:00:00 2001 From: nicodvb Date: Sat, 26 Jan 2008 18:31:48 +0000 Subject: generic functions and structures to parse and statekeep LATM streams git-svn-id: svn://svn.mplayerhq.hu/mplayer/trunk@25862 b3059339-0415-0410-9bf9-f77b7e298cf2 --- libfaad2/neaacdec.h | 1 + libfaad2/structs.h | 19 ++++++ libfaad2/syntax.c | 185 ++++++++++++++++++++++++++++++++++++++++++++++++++++ libfaad2/syntax.h | 2 + 4 files changed, 207 insertions(+) (limited to 'libfaad2') diff --git a/libfaad2/neaacdec.h b/libfaad2/neaacdec.h index 347732d7d4..e0c10b66c5 100644 --- a/libfaad2/neaacdec.h +++ b/libfaad2/neaacdec.h @@ -83,6 +83,7 @@ extern "C" { #define RAW 0 #define ADIF 1 #define ADTS 2 +#define LATM 3 /* SBR signalling */ #define NO_SBR 0 diff --git a/libfaad2/structs.h b/libfaad2/structs.h index a624b5f03a..8f25298e70 100644 --- a/libfaad2/structs.h +++ b/libfaad2/structs.h @@ -330,6 +330,23 @@ typedef struct mp4AudioSpecificConfig /*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 @@ typedef struct { 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 @@ typedef struct int64_t scalefac_cycles; int64_t requant_cycles; #endif + latm_header latm_config; } NeAACDecStruct, *NeAACDecHandle; diff --git a/libfaad2/syntax.c b/libfaad2/syntax.c index 70efafd424..52a08f25b7 100644 --- a/libfaad2/syntax.c +++ b/libfaad2/syntax.c @@ -2329,3 +2329,188 @@ static void adts_error_check(adts_header *adts, bitfile *ld) 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; lframelen_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; +} diff --git a/libfaad2/syntax.h b/libfaad2/syntax.h index ba7503c766..ba08b00a89 100644 --- a/libfaad2/syntax.h +++ b/libfaad2/syntax.h @@ -49,6 +49,7 @@ extern "C" { #define RAW 0 #define ADIF 1 #define ADTS 2 +#define LATM 3 /* SBR signalling */ #define NO_SBR 0 @@ -116,6 +117,7 @@ uint8_t reordered_spectral_data(NeAACDecHandle hDecoder, ic_stream *ics, bitfile 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 -- cgit v1.2.3