Mercurial > mplayer.hg
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