static int init(sh_audio_t *sh){ int pos = 0; int32_t result = HXR_OK; uint16_t *temp; uint8_t *inBuf; int in_len; int32_t NumChannels, SampleRate; hAACDecoder = (HAACDecoder *)AACInitDecoder(); ga_config_data configData; int i; if (!hAACDecoder) { printf(" *** Error initializing decoder ***\n"); return 0; } if(!sh->codecdata_len && sh->wf) { sh->codecdata_len = sh->wf->cbSize; sh->codecdata = (char*)(sh->wf+1); mp_msg(MSGT_DECAUDIO,MSGL_DBG2,"realaac: codecdata extracted from WAVEFORMATEX\n"); } if(!sh->codecdata_len){ //return 0; sh->a_in_buffer_len = demux_read_data(sh->ds, sh->a_in_buffer, sh->a_in_buffer_size); inBuf = sh->a_in_buffer; in_len = sh->a_in_buffer_len; temp = (uint16_t *)malloc(sizeof(uint16_t) * sh->audio_out_minsize); /* decode ADTS frame from opaque data to get config data */ result = AACDecode(hAACDecoder, &inBuf, &in_len, temp); free(temp); if (result != HXR_OK) { return 0; } /* get the config data struct from the decoder */ AACGetLastFrameInfo(hAACDecoder, frameInfo); NumChannels = frameInfo->nChans; SampleRate = frameInfo->sampRateCore; }else{ struct BITSTREAM *pBitstream ; pBitstream = (struct BITSTREAM *)malloc(sizeof(struct BITSTREAM)) ; if (!pBitstream) return 0 ; pBitstream->cacheBitsLeft = 0 ; pBitstream->buffer = sh->codecdata ; pBitstream->nBits = sh->codecdata_len*8 ; pBitstream->pkptr = pBitstream->buffer + (0>>3) ; pBitstream->cacheBitsLeft = 0 ; pBitstream->cache = 0 ; pBitstream->inc = 1 ; result = ga_config_get_data(pBitstream, &configData); if(pBitstream){ free(pBitstream); } if (result != HXR_OK) /* config data error */ { return 0; } NumChannels = frameInfo->nChans=configData.numChannels; SampleRate = frameInfo->sampRateCore=configData.samplingFrequency; /* see MPEG4 spec for index of each object type */ if (configData.audioObjectType == 2) frameInfo->profile = AAC_PROFILE_LC; else if (configData.audioObjectType == 1) frameInfo->profile = AAC_PROFILE_MP; else if (configData.audioObjectType == 3) frameInfo->profile = AAC_PROFILE_SSR; else return 0; /* don't know - assume LC */ /* set decoder to handle raw data blocks */ AACSetRawBlockParams(hAACDecoder, 0, frameInfo); } mp_msg(MSGT_DECAUDIO,MSGL_V,"realaac: Decoder init done (%dBytes)!\n", sh->a_in_buffer_len); // XXX: remove or move to debug! mp_msg(MSGT_DECAUDIO,MSGL_V,"realaac: Negotiated samplerate: %ldHz channels: %d\n", SampleRate, NumChannels); sh->channels = NumChannels; if (audio_output_channels <= 2) sh->channels = NumChannels > 1 ? 2 : 1; sh->samplerate = SampleRate; sh->samplesize=2; if(!sh->i_bps) { mp_msg(MSGT_DECAUDIO,MSGL_WARN,"realaac: compressed input bitrate missing, assuming 128kbit/s!\n"); sh->i_bps = 128*1000/8; // XXX: HACK!!! ::atmos } else mp_msg(MSGT_DECAUDIO,MSGL_V,"realaac: got %dkbit/s bitrate from MP4 header!\n",sh->i_bps*8/1000); return 1; // return values: 1=OK 0=ERROR }
static int decode_audio(sh_audio_t *sh,unsigned char *buf,int minlen,int maxlen){ int len = 0, last_dec_len = 1, err = 0, in_len; int outOfData = 0, errors=0;; uint8_t *inBuf; while(len < minlen && last_dec_len > 0 ) { /* update buffer for raw aac streams: */ if(!sh->codecdata_len){ if(sh->a_in_buffer_len < sh->a_in_buffer_size){ sh->a_in_buffer_len += demux_read_data(sh->ds,&sh->a_in_buffer[sh->a_in_buffer_len], sh->a_in_buffer_size - sh->a_in_buffer_len); } //#define DUMP_AAC_COMPRESSED #ifdef DUMP_AAC_COMPRESSED {int i; inBuf = sh->a_in_buffer; for (i = 0; i < 16; i++) printf ("%02x ", inBuf[i]); printf ("\n");} #endif inBuf = sh->a_in_buffer; in_len = sh->a_in_buffer_len; // raw aac stream: err = AACDecode(hAACDecoder, &(inBuf), &(in_len), buf+len); if(in_len > 0) { memmove(sh->a_in_buffer,inBuf,in_len); } sh->a_in_buffer_len = in_len; if (err == ERR_AAC_NONE) { AACGetLastFrameInfo(hAACDecoder, frameInfo); reorder_ch_pcm(buf+len, frameInfo->outputSamps, frameInfo->nChans); last_dec_len = sh->samplesize*frameInfo->outputSamps*sh->channels/frameInfo->nChans; len += last_dec_len; sh->pts_bytes += last_dec_len; if(errors) errors=0; }else if(err == ERR_AAC_INDATA_UNDERFLOW){ errors++; }else if(sh->a_in_buffer_len > 0){ sh->a_in_buffer_len--; memmove(sh->a_in_buffer,&sh->a_in_buffer[1],sh->a_in_buffer_len); aac_sync(sh); errors++; } if(errors > 10){ break; } }else{ /* update buffer for raw aac streams: */ // packetized (.mp4) aac stream: unsigned char* bufptr=NULL; double pts; int buflen=ds_get_packet_pts(sh->ds, &bufptr, &pts); if(buflen<=0) break; if (pts != MP_NOPTS_VALUE) { sh->pts = pts; sh->pts_bytes = 0; } err = AACDecode(hAACDecoder, &bufptr, &buflen, buf+len); if (err == ERR_AAC_NONE) { AACGetLastFrameInfo(hAACDecoder, frameInfo); reorder_ch_pcm(buf+len, frameInfo->outputSamps, frameInfo->nChans); last_dec_len = sh->samplesize*frameInfo->outputSamps*sh->channels/frameInfo->nChans; len += last_dec_len; sh->pts_bytes += last_dec_len; } } } return len; }
//decoding-interrupt void decodeAac(void) { AudioPlaySdAac *o = aacobjptr; int db = o->decoding_block; if (o->decoded_length[db]) return; //this block is playing, do NOT fill it uint32_t cycles = ARM_DWT_CYCCNT; int eof = false; switch (o->decoding_state) { case 0: { o->sd_left = o->fillReadBuffer( o->file, o->sd_buf, o->sd_p, o->sd_left, AAC_SD_BUF_SIZE); if (!o->sd_left) { eof = true; goto aacend; } o->sd_p = o->sd_buf; uint32_t cycles_rd = ARM_DWT_CYCCNT - cycles; if (cycles_rd > o->decode_cycles_max_read ) o->decode_cycles_max_read = cycles_rd; break; } case 1: { if (o->isRAW) { // find start of next AAC frame - assume EOF if no sync found int offset = AACFindSyncWord(o->sd_p, o->sd_left); if (offset < 0) { eof = true; goto aacend; } o->sd_p += offset; o->sd_left -= offset; } int decode_res = AACDecode(o->hAACDecoder, &o->sd_p, (int*)&o->sd_left, o->buf[db]); if (!decode_res) { AACGetLastFrameInfo(o->hAACDecoder, &o->aacFrameInfo); o->decoded_length[db] = o->aacFrameInfo.outputSamps; } else { AudioPlaySdAac::lastError = decode_res; eof = true; //goto aacend; } //if (!o->isRAW && (o->fposition() > o->lastChunk)) eof = true; cycles = ARM_DWT_CYCCNT - cycles; if (cycles > o->decode_cycles_max ) o->decode_cycles_max = cycles; } } //switch aacend: o->decoding_state++; if (o->decoding_state >= DECODE_NUM_STATES) o->decoding_state = 0; if (eof) o->stop(); }
/* * aac_decode_init */ HX_RESULT aac_decode_init(void* pInitParams, UINT32 ulInitParamsSize, ra_format_info* pStreamInfo, void** pDecode, void* pUserMem, rm_malloc_func_ptr fpMalloc, rm_free_func_ptr fpFree) { HX_RESULT result = HXR_OK; aac_decode* pDec; AACFrameInfo *frameInfo; ga_config_data configData; UCHAR *pData; UCHAR *inBuf; INT16 *temp; UINT32 numBytes, numBits; UINT32 cfgType; /* for MP4 bitstream parsing */ struct BITSTREAM *pBs = 0; /* allocate the aac_decode struct */ pDec = (aac_decode*) fpMalloc(pUserMem, sizeof(aac_decode)); if (pDec == HXNULL) { return HXR_OUTOFMEMORY; } memset(pDec, 0, sizeof(aac_decode)); *pDecode = (void *)pDec; /* allocate the frame info struct */ pDec->pFrameInfo = fpMalloc(pUserMem, sizeof(AACFrameInfo)); frameInfo = (AACFrameInfo *) pDec->pFrameInfo; /* allocate the decoder backend instance */ pDec->pDecoder = AACInitDecoder(1); if (pDec->pFrameInfo == HXNULL || pDec->pDecoder == HXNULL) { return HXR_OUTOFMEMORY; } /* save the stream info and init data we'll need later */ pDec->ulNumChannels = (UINT32)pStreamInfo->usNumChannels; pDec->ulBlockSize = pStreamInfo->ulGranularity; pDec->ulFrameSize = pStreamInfo->ulBitsPerFrame; pDec->ulFramesPerBlock = pDec->ulBlockSize / pDec->ulFrameSize; /* output frame size is doubled for safety in case of implicit SBR */ pDec->ulSamplesPerFrame = 1024*pStreamInfo->usNumChannels*2; pDec->ulSampleRateCore = pStreamInfo->ulSampleRate; pDec->ulSampleRateOut = pStreamInfo->ulActualRate; if (pStreamInfo->ulOpaqueDataSize < 1) { return HXR_FAIL; /* insufficient config data */ } /* get the config data */ pData = (UCHAR *)pStreamInfo->pOpaqueData; cfgType = pData[0]; inBuf = pData + 1; numBytes = pStreamInfo->ulOpaqueDataSize - 1; if (cfgType == 1) /* ADTS Frame */ { /* allocate temp buffer for decoding first ADTS frame */ temp = (INT16 *)fpMalloc(pUserMem, sizeof(INT16) * pDec->ulSamplesPerFrame); if (temp == HXNULL) { return HXR_OUTOFMEMORY; } else { /* decode ADTS frame from opaque data to get config data */ result = AACDecode(pDec->pDecoder, &inBuf, (INT32*)&numBytes, temp); /* free the temp buffer */ fpFree(pUserMem, temp); } if (result == HXR_OK) { /* get the config data struct from the decoder */ AACGetLastFrameInfo(pDec->pDecoder, frameInfo); pDec->ulNumChannels = frameInfo->nChans; pDec->ulSamplesPerFrame = frameInfo->outputSamps; pDec->ulSampleRateCore = frameInfo->sampRateCore; pDec->ulSampleRateOut = frameInfo->sampRateOut; pDec->bSBR = (pDec->ulSampleRateCore != pDec->ulSampleRateOut); } } else if (cfgType == 2) /* MP4 Audio Specific Config Data */ { numBits = numBytes*8; if (newBitstream(&pBs, numBits, pUserMem, fpMalloc)) { return HXR_FAIL; } feedBitstream(pBs, (const UCHAR *)inBuf, numBits); setAtBitstream(pBs, 0, 1); result = ga_config_get_data(pBs, &configData); deleteBitstream(pBs, pUserMem, fpFree); if (result != HXR_OK) /* config data error */ { return HXR_FAIL; } pDec->ulNumChannels = configData.numChannels; pDec->ulSampleRateCore = configData.samplingFrequency; pDec->ulSampleRateOut = configData.extensionSamplingFrequency; pDec->bSBR = configData.bSBR; /* ulSamplesPerFrame is set to the maximum possible output length. * The config data has the initial output length, which might * be doubled once the first frame is handed in (if AAC+ is * signalled implicitly). */ pDec->ulSamplesPerFrame = 2*configData.frameLength*configData.numChannels; /* setup decoder to handle raw data blocks */ frameInfo->nChans = pDec->ulNumChannels; frameInfo->sampRateCore = pDec->ulSampleRateCore; /* see MPEG4 spec for index of each object type */ if (configData.audioObjectType == 2) frameInfo->profile = AAC_PROFILE_LC; else if (configData.audioObjectType == 1) frameInfo->profile = AAC_PROFILE_MP; else if (configData.audioObjectType == 3) frameInfo->profile = AAC_PROFILE_SSR; else frameInfo->profile = AAC_PROFILE_LC; /* don't know - assume LC */ frameInfo->audio_send_by_frame=0; } else /* unsupported config type */ { return HXR_FAIL; } /* make certain that all the channels can be handled */ if (pDec->ulNumChannels > AAC_MAX_NCHANS) { return HXR_UNSUPPORTED_AUDIO; } /* set the channel mask - custom maps not supported */ switch (pDec->ulNumChannels) { case 1: pDec->ulChannelMask = 0x00004; /* FC */ case 2: pDec->ulChannelMask = 0x00003; /* FL,FR */ case 3: pDec->ulChannelMask = 0x00007; /* FL,FR,FC */ case 4: pDec->ulChannelMask = 0x00107; /* FL,FR,FC,BC */ case 5: pDec->ulChannelMask = 0x00037; /* FL,FR,FC,BL,BR */ case 6: pDec->ulChannelMask = 0x0003F; /* FL,FR,FC,LF,BL,BR */ default: pDec->ulChannelMask = 0xFFFFF; /* Unknown */ } /* set the delay samples */ pDec->ulDelayRemaining = pDec->ulSamplesPerFrame; /* set decoder to handle raw data blocks */ AACSetRawBlockParams(pDec->pDecoder, 0, frameInfo); return HXR_OK; }
HX_RESULT aac_decode_decode(void* pDecode, UINT8* pData, UINT32 ulNumBytes, UINT32* pNumBytesConsumed, UINT16* pSamplesOut, UINT32 ulNumSamplesAvail, UINT32* pNumSamplesOut, UINT32 ulFlags, UINT32 ulTimeStamp) { HX_RESULT retVal = HXR_FAIL; aac_decode* pDec = (aac_decode*) pDecode; AACFrameInfo *frameInfo = pDec->pFrameInfo; UINT32 lostFlag, maxSamplesOut; UINT32 ulNumBytesRemaining; UINT8* inBuf = pData; UINT16* outBuf = pSamplesOut; ulNumBytesRemaining = ulNumBytes; *pNumBytesConsumed = 0; *pNumSamplesOut = 0; lostFlag = !(ulFlags & 1); if (pDec->ulSamplesToConceal || lostFlag) { if (lostFlag) /* conceal one frame */ *pNumSamplesOut = pDec->ulSamplesPerFrame; else { maxSamplesOut = pDec->ulSamplesPerFrame * pDec->ulFramesPerBlock; *pNumSamplesOut = maxSamplesOut; if (pDec->ulSamplesToConceal < maxSamplesOut) *pNumSamplesOut = pDec->ulSamplesToConceal; pDec->ulSamplesToConceal -= *pNumSamplesOut; } /* just fill with silence */ memset(pSamplesOut, 0, *pNumSamplesOut * sizeof(INT16)); AACFlushCodec(pDec->pDecoder); *pNumBytesConsumed = 0; return HXR_OK; } retVal = AACDecode(pDec->pDecoder, &inBuf, (INT32*)&ulNumBytesRemaining, (INT16*)outBuf); if (retVal == ERR_AAC_NONE) { AACGetLastFrameInfo(pDec->pDecoder, frameInfo); AACReorderPCMChannels((INT16*)outBuf, frameInfo->outputSamps, frameInfo->nChans); pDec->ulSampleRateCore = frameInfo->sampRateCore; pDec->ulSampleRateOut = frameInfo->sampRateOut; pDec->ulNumChannels = frameInfo->nChans; *pNumSamplesOut = frameInfo->outputSamps; *pNumBytesConsumed = ulNumBytes - ulNumBytesRemaining; retVal = HXR_OK; } else if (retVal == ERR_AAC_INDATA_UNDERFLOW) { retVal = HXR_NO_DATA; } else { retVal = HXR_FAIL; } /* Zero out invalid output samples */ if (*pNumSamplesOut == 0) { /* protect consumer ears by zeroing the output buffer */ memset(pSamplesOut, 0, pDec->ulSamplesPerFrame * sizeof(UINT16)); } else if (pDec->ulDelayRemaining > 0) /* delay samples */ { if (pDec->ulDelayRemaining >= *pNumSamplesOut) { pDec->ulDelayRemaining -= *pNumSamplesOut; *pNumSamplesOut = 0; } else { *pNumSamplesOut -= pDec->ulDelayRemaining; memmove(pSamplesOut, pSamplesOut + pDec->ulDelayRemaining, *pNumSamplesOut); pDec->ulDelayRemaining = 0; } } return retVal; }
/*---------------------------------------------------------------------- | AacDecoderInput_PutPacket +---------------------------------------------------------------------*/ BLT_METHOD AacDecoderInput_PutPacket(BLT_PacketConsumer* _self, BLT_MediaPacket* packet) { AacDecoder* self = ATX_SELF_M(input, AacDecoder, BLT_PacketConsumer); ATX_Result result; /* check to see if this is the end of a stream */ if (BLT_MediaPacket_GetFlags(packet) & BLT_MEDIA_PACKET_FLAG_END_OF_STREAM) { self->input.eos = BLT_TRUE; } /* check to see if we need to create a decoder for this */ if (self->helix_decoder == NULL) { AacDecoderConfig decoder_config; AACFrameInfo aac_frame_info; const BLT_MediaType* media_type; const BLT_Mp4AudioMediaType* mp4_media_type; BLT_MediaPacket_GetMediaType(packet, &media_type); if (media_type == NULL || media_type->id != self->mp4es_type_id) { return BLT_ERROR_INVALID_MEDIA_TYPE; } mp4_media_type = (const BLT_Mp4AudioMediaType*)media_type; if (mp4_media_type->base.stream_type != BLT_MP4_STREAM_TYPE_AUDIO) { return BLT_ERROR_INVALID_MEDIA_TYPE; } if (BLT_FAILED(AacDecoderConfig_Parse(mp4_media_type->decoder_info, mp4_media_type->decoder_info_length, &decoder_config))) { return BLT_ERROR_INVALID_MEDIA_FORMAT; } if (decoder_config.object_type != BLT_AAC_OBJECT_TYPE_AAC_LC && decoder_config.object_type != BLT_AAC_OBJECT_TYPE_SBR) { return BLT_ERROR_UNSUPPORTED_CODEC; } /* create the decoder */ self->helix_decoder = AACInitDecoder(); if (self->helix_decoder == NULL) return BLT_ERROR_OUT_OF_MEMORY; /* configure the decoder */ ATX_SetMemory(&aac_frame_info, 0, sizeof(aac_frame_info)); aac_frame_info.nChans = AacDecoderConfig_GetChannelCount(&decoder_config); aac_frame_info.sampRateCore = AacDecoderConfig_GetSampleRate(&decoder_config); if (decoder_config.object_type == BLT_AAC_OBJECT_TYPE_AAC_LC) { aac_frame_info.profile = AAC_PROFILE_LC; } self->sample_buffer_size = BLT_AAC_FRAME_SIZE*2*aac_frame_info.nChans*2; /* the last *2 is for SBR support */ AACSetRawBlockParams(self->helix_decoder, 0, &aac_frame_info); } { unsigned char* in_buffer; int in_size; short* out_buffer; BLT_MediaPacket* out_packet; AACFrameInfo aac_frame_info; /* create a PCM packet for the output */ result = BLT_Core_CreateMediaPacket(ATX_BASE(self, BLT_BaseMediaNode).core, self->sample_buffer_size, (BLT_MediaType*)&self->output.media_type, &out_packet); if (BLT_FAILED(result)) return result; /* copy the timestamp */ BLT_MediaPacket_SetTimeStamp(out_packet, BLT_MediaPacket_GetTimeStamp(packet)); /* decode the packet as a frame */ in_buffer = BLT_MediaPacket_GetPayloadBuffer(packet); in_size = BLT_MediaPacket_GetPayloadSize(packet); out_buffer = (short*)BLT_MediaPacket_GetPayloadBuffer(out_packet); result = AACDecode(self->helix_decoder, &in_buffer, &in_size, out_buffer); if (result != 0) { BLT_MediaPacket_Release(out_packet); return BLT_ERROR_INVALID_MEDIA_FORMAT; } /* check that the sample buffer matches our current media type */ AACGetLastFrameInfo(self->helix_decoder, &aac_frame_info); if (self->output.media_type.channel_count == 0) { /* first time, setup our media type */ self->output.media_type.channel_count = aac_frame_info.nChans; self->output.media_type.sample_rate = aac_frame_info.sampRateOut; self->output.media_type.bits_per_sample = 16; self->output.media_type.sample_format = BLT_PCM_SAMPLE_FORMAT_SIGNED_INT_NE; self->output.media_type.channel_mask = 0; /* update the stream info */ if (ATX_BASE(self, BLT_BaseMediaNode).context) { BLT_StreamInfo stream_info; stream_info.data_type = "MPEG-4 AAC"; stream_info.sample_rate = aac_frame_info.sampRateOut; stream_info.channel_count = aac_frame_info.nChans; stream_info.mask = BLT_STREAM_INFO_MASK_DATA_TYPE | BLT_STREAM_INFO_MASK_SAMPLE_RATE | BLT_STREAM_INFO_MASK_CHANNEL_COUNT; BLT_Stream_SetInfo(ATX_BASE(self, BLT_BaseMediaNode).context, &stream_info); } /* update the packet media type */ BLT_MediaPacket_SetMediaType(out_packet, (BLT_MediaType*)&self->output.media_type); } else { /* we've already setup a media type, check that this is the same */ if (self->output.media_type.sample_rate != (unsigned int)aac_frame_info.sampRateOut || self->output.media_type.channel_count != aac_frame_info.nChans) { BLT_MediaPacket_Release(out_packet); return BLT_ERROR_INVALID_MEDIA_FORMAT; } } /* add to the output packet list */ BLT_MediaPacket_SetPayloadSize(out_packet, aac_frame_info.outputSamps*2); ATX_List_AddData(self->output.packets, out_packet); } return BLT_SUCCESS; }