mirror of
https://github.com/mpv-player/mpv
synced 2025-01-13 00:06:25 +01:00
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
This commit is contained in:
parent
715cd43c17
commit
46cfd2988b
@ -83,6 +83,7 @@ extern "C" {
|
||||
#define RAW 0
|
||||
#define ADIF 1
|
||||
#define ADTS 2
|
||||
#define LATM 3
|
||||
|
||||
/* SBR signalling */
|
||||
#define NO_SBR 0
|
||||
|
@ -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;
|
||||
|
||||
|
||||
|
@ -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; 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;
|
||||
}
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user