/* Copyright (c) 2017, Texas Instruments Incorporated - http://www.ti.com/ All rights reserved. * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the * distribution. * * Neither the name of Texas Instruments Incorporated nor the names of * its contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include // for memset() #include #include #include #include #include #include "common.h" #include "paftyp.h" #include "pafdec.h" #include "aspDecOpCircBuf_master.h" #include "evmc66x_gpio_dbg.h" // Debug #ifdef CB_RW_OP_CAP_PP // debug // Global variables Uint32 *gCB_samples_op = NULL; Uint8 *gCB_op_owner = NULL; Uint32 *gCB_opCnt = 0; Uint8 *gCB_afRdIdx = NULL; Uint8 *gCB_afWrtIdx = NULL; Uint8 *gCB_numAfCb = NULL; #endif #if 0 // Generate mute AF on circular buffer read static Void cbReadAfMute( PAF_AudioFrame *pAfRd, // audio frame into which to read Int16 strFrameLen // stream frame length (output transaction size) ); #endif #if 0 // Init last audio frame configuration info static Void cbInitLastAfInfo( PAF_AudioFrame *pAfRd // last audio frame stored in CB instance ); #endif // Update last audio frame configuration info static Void cbUpdateLastAfInfo( PAF_AST_DecOpCircBuf *pCb, // decoder output circular buffer control PAF_AudioFrame *pAfUpd // audio frame used for update ); // Generate mute AF on circular buffer read using the last AF configuration info static Void cbReadMuteWithLastAfInfo( PAF_AST_DecOpCircBuf *pCb, // decoder output circular buffer control PAF_AudioFrame *pAfRd // audio frame into which to read ); #if 0 // FL: moved to common // Initialize circular buffer control Int cbCtlInit( PAF_AST_DecOpCircBufCtl *pCbCtl, // decoder output circular buffer control Int8 numCb, // number of circular buffers PAF_AST_DecOpCircBuf **pXDecOpCb // address of decoder output circular buffer base pointer ) { GateMP_Params gateParams; GateMP_Handle gateHandle; GateMP_Params_init(&gateParams); gateParams.localProtect = GateMP_LocalProtect_THREAD; gateParams.remoteProtect = GateMP_RemoteProtect_SYSTEM; gateParams.name = ASP_DECODE_CB_GATE_NAME; gateParams.regionId = ASP_DECODE_CB_GATE_REGION_ID; gateHandle = GateMP_create(&gateParams); if (gateHandle != NULL) { pCbCtl->gateHandle = gateHandle; } else { pCbCtl->gateHandle = NULL; return ASP_DECOP_CB_CTL_INIT_INV_GATE; } pCbCtl->numCb = numCb; // init number of circular buffers pCbCtl->pXDecOpCb = pXDecOpCb; // init base address of circular buffers return ASP_DECOP_CB_SOK; } #endif // Initialize circular buffer Int cbInit( PAF_AST_DecOpCircBuf *pCb ) { #if 0 // FL: unused PAF_AudioFrame *pAfCb; PAF_AudioData *pPcmBuf; UInt8 *pMetaBuf; Int8 n; Int8 i; // set source select pCb->sourceSel = DEF_SOURCE_SEL; // set input frame length pCb->decOpFrameLen = DEF_DEC_OP_FRAME_LEN; // set output frame length pCb->strFrameLen = DEF_STR_FRAME_LEN; // initialize circular buffer maximum number of audio frames pCb->maxNumAfCb = ASP_DECOP_CB_MAX_NUM_AF_THD; //ASP_DECOP_CB_MAX_NUM_AF_PCM; pCb->afWrtIdx = ASP_DECOP_CB_INIT_LAG_PCM; pCb->afRdIdx = 0; pCb->pcmRdIdx = 0; // Initialize CB primed flag pCb->primedFlag = 0; // Initialize delta samples pCb->deltaSamps = 0; // set default value to PCM configuration pCb->maxAFChanNum = ASP_DECOP_CB_MAX_NUM_PCM_CH; pCb->maxAFSampCount = DEF_DEC_OP_FRAME_LEN; // initialize audio frames for (n=0; nmaxNumAfCb; n++) { pAfCb = &pCb->afCb[n]; pAfCb->sampleDecode = PAF_SOURCE_PCM; PAF_PROCESS_ZERO(pAfCb->sampleProcess); pAfCb->sampleRate = PAF_SAMPLERATE_48000HZ; pAfCb->sampleCount = DEF_DEC_OP_FRAME_LEN; pAfCb->channelConfigurationRequest.full = 0; pAfCb->channelConfigurationRequest.part.sat = PAF_CC_SAT_SURROUND4; pAfCb->channelConfigurationRequest.part.sub = PAF_CC_SUB_ONE; pAfCb->channelConfigurationStream.full = 0; pAfCb->channelConfigurationStream.part.sat = PAF_CC_SAT_SURROUND4; pAfCb->channelConfigurationStream.part.sub = PAF_CC_SUB_ONE; } // initialize circular buffer current number of frames pCb->numAfCb = pCb->afWrtIdx - pCb->afRdIdx; // initialize audio frame PCM buffers pPcmBuf = pCb->pcmBuf; pMetaBuf = pCb->metaBuf; for (n=0; nmaxNumAfCb; n++) { pAfCb = &pCb->afCb[n]; pAfCb->data.nChannels = ASP_DECOP_CB_MAX_NUM_PCM_CH; pAfCb->data.nSamples = DEF_DEC_OP_FRAME_LEN; for (i=0; idata.sample[i] = pPcmBuf; memset(pAfCb->data.sample[i], 0, DEF_DEC_OP_FRAME_LEN); pPcmBuf += DEF_DEC_OP_FRAME_LEN; pAfCb->data.samsiz[i] = 0; } // write metadata information updated by decoder pAfCb->bsMetadata_type = PAF_bsMetadata_channelData; /* non zero if metadata is attached. */ pAfCb->pafBsMetadataUpdate = 0; /* indicates whether bit-stream metadata update */ pAfCb->numPrivateMetadata = 0; /* number of valid private metadata (0 or 1 if metadata filtering enabled) */ pAfCb->bsMetadata_offset = 0; /* offset into audio frame for change in bsMetadata_type field */ // Initialize metadata buffers for (i=0; ipafPrivateMetadata[i].offset = 0; pAfCb->pafPrivateMetadata[i].size = 0; pAfCb->pafPrivateMetadata[i].pMdBuf = pMetaBuf; pMetaBuf += PAF_MAX_PRIVATE_MD_SZ; } } // reset read/write flags pCb->writerActiveFlag = 0; pCb->readerActiveFlag = 0; pCb->drainFlag = 0; // reset stats pCb->readAfWriterInactiveCnt = 0; pCb->readAfNdCnt = 0; pCb->wrtAfReaderInactiveCnt = 0; pCb->wrtAfZeroSampsCnt = 0; pCb->errUndCnt = 0; pCb->errOvrCnt = 0; #ifdef CB_RW_OP_CAP_PP // debug // Get address in global variables gCB_samples_op = pCb->cb_samples_op; gCB_op_owner = pCb->cb_op_owner; gCB_opCnt = &pCb->cb_opCnt; gCB_afRdIdx = pCb->cb_afRdIdx; gCB_afWrtIdx = pCb->cb_afWrtIdx; gCB_numAfCb = pCb->cb_numAfCb; #endif cbInitLastAfInfo(&pCb->lastAf); // Write back circular buffer configuration Cache_wb(pCb, sizeof(PAF_AST_DecOpCircBuf), Cache_Type_ALLD, 0); // Write back AF circular buffer Cache_wb(pCb->afCb, pCb->maxNumAfCb*sizeof(PAF_AudioFrame), Cache_Type_ALLD, 0); // Write back PCM data for (n=0; nmaxNumAfCb; n++) { pAfCb = &pCb->afCb[n]; Cache_wb(pAfCb->data.samsiz, ASP_DECOP_CB_MAX_NUM_PCM_CH*sizeof(PAF_AudioSize), Cache_Type_ALLD, 0); Cache_wb(pAfCb->data.sample, ASP_DECOP_CB_MAX_NUM_PCM_CH*sizeof(PAF_AudioData *), Cache_Type_ALLD, 0); for (i=0; idata.sample[i], DEF_DEC_OP_FRAME_LEN*sizeof(PAF_AudioData), Cache_Type_ALLD, 0); } } Cache_wait(); #endif // set source select pCb->sourceSel = PAF_SOURCE_UNKNOWN; #ifdef CB_RW_OP_CAP_PP // debug // Get address in global variables gCB_samples_op = pCb->cb_samples_op; gCB_op_owner = pCb->cb_op_owner; gCB_opCnt = &pCb->cb_opCnt; gCB_afRdIdx = pCb->cb_afRdIdx; gCB_afWrtIdx = pCb->cb_afWrtIdx; gCB_numAfCb = pCb->cb_numAfCb; #endif // Write back circular buffer configuration Cache_wb(pCb, sizeof(PAF_AST_DecOpCircBuf), Cache_Type_ALLD, 0); Cache_wait(); return ASP_DECOP_CB_SOK; } #if 0 // FL: moved to ARM // debug //Int8 gCbInitSourceSelCnt=0; //Int8 gCbInitSourceSelThdCnt=0; // Initialize circular buffer based on selected source Int cbInitSourceSel( PAF_AST_DecOpCircBufCtl *pCbCtl, // decoder output circular buffer control Int8 cbIdx, // decoder output circular buffer index Int8 sourceSelect, // source select (PCM, DDP, etc.) Int16 decOpFrameLen, // decoder output frame length (PCM samples) Int16 strFrameLen, // stream frame length (PCM samples) Int8 resetRwFlags // whether to reset reader, writer, and drain flags ) { IArg key; GateMP_Handle gateHandle; PAF_AST_DecOpCircBuf *pCb; PAF_AudioFrame *pAfCb; PAF_AudioData *pPcmBuf; UInt8 *pMetaBuf; Int8 n; Int8 i; //gCbInitSourceSelCnt++; // debug // Get gate handle gateHandle = pCbCtl->gateHandle; // Enter gate key = GateMP_enter(gateHandle); // Get circular buffer base pointer pCb = &((*pCbCtl->pXDecOpCb)[cbIdx]); // Invalidate circular buffer configuration Cache_inv(pCb, sizeof(PAF_AST_DecOpCircBuf), Cache_Type_ALLD, 0); Cache_wait(); //Log_info1("cbInitSourceSel:afCb=0x%04x", (IArg)pCb->afCb); // debug // set source select pCb->sourceSel = sourceSelect; // set input frame length pCb->decOpFrameLen = decOpFrameLen; // set output frame length pCb->strFrameLen = strFrameLen; //pCb->afInitialLag = 0; // default No lag //pCb->afLagIdx = 0; // Initialize CB primed flag pCb->primedFlag = 0; // Initialize delta samples pCb->deltaSamps = 0; // initialize circular buffer maximum number of audio frames if (sourceSelect == PAF_SOURCE_PCM) { pCb->maxNumAfCb = ASP_DECOP_CB_MAX_NUM_AF_PCM; //pCb->afInitialLag = ASP_DECOP_CB_INIT_LAG_PCM; // Initialize target nominal delay pCb->targetNDSamps = ASP_DECOP_CB_TARGET_ND_SAMPS_48kPCM; pCb->afWrtIdx = ASP_DECOP_CB_INIT_WRTIDX_PCM; pCb->afRdIdx = ASP_DECOP_CB_INIT_RDIDX_PCM; pCb->pcmRdIdx = 0; pCb->maxAFChanNum = ASP_DECOP_CB_MAX_NUM_PCM_CH; pCb->maxAFSampCount = DEF_DEC_OP_FRAME_LEN; // initialize audio frames for (n=0; nmaxNumAfCb; n++) { pAfCb = &pCb->afCb[n]; pAfCb->sampleDecode = sourceSelect; PAF_PROCESS_ZERO(pAfCb->sampleProcess); pAfCb->sampleRate = PAF_SAMPLERATE_48000HZ; pAfCb->sampleCount = decOpFrameLen; pAfCb->channelConfigurationRequest.full = 0; pAfCb->channelConfigurationRequest.part.sat = PAF_CC_SAT_SURROUND4; pAfCb->channelConfigurationRequest.part.sub = PAF_CC_SUB_ONE; pAfCb->channelConfigurationStream.full = 0; pAfCb->channelConfigurationStream.part.sat = PAF_CC_SAT_SURROUND4; pAfCb->channelConfigurationStream.part.sub = PAF_CC_SUB_ONE; // write metadata information updated by decoder pAfCb->bsMetadata_type = PAF_bsMetadata_channelData; /* non zero if metadata is attached. */ pAfCb->pafBsMetadataUpdate = 0; /* indicates whether bit-stream metadata update */ pAfCb->numPrivateMetadata = 0; /* number of valid private metadata (0 or 1 if metadata filtering enabled) */ pAfCb->bsMetadata_offset = 0; /* offset into audio frame for change in bsMetadata_type field */ } } else if ((sourceSelect == PAF_SOURCE_DDP) || (sourceSelect == PAF_SOURCE_AC3)) { pCb->maxNumAfCb = ASP_DECOP_CB_MAX_NUM_AF_DDP; //pCb->afInitialLag = ASP_DECOP_CB_INIT_LAG_DDP; // Initialize target nominal delay pCb->targetNDSamps = ASP_DECOP_CB_TARGET_ND_SAMPS_48kDDP; pCb->afWrtIdx = ASP_DECOP_CB_INIT_WRTIDX_DDP; pCb->afRdIdx = ASP_DECOP_CB_INIT_RDIDX_DDP; pCb->pcmRdIdx = 0; pCb->maxAFChanNum = ASP_DECOP_CB_MAX_NUM_PCM_CH_DDP; pCb->maxAFSampCount = ASP_DECOP_CB_MAX_PCM_FRAME_LEN_48kDDP; // initialize audio frames for (n=0; nmaxNumAfCb; n++) { pAfCb = &pCb->afCb[n]; pAfCb->sampleDecode = sourceSelect; PAF_PROCESS_ZERO(pAfCb->sampleProcess); pAfCb->sampleRate = PAF_SAMPLERATE_48000HZ; pAfCb->sampleCount = decOpFrameLen; pAfCb->channelConfigurationRequest.full = 0; pAfCb->channelConfigurationRequest.part.sat = PAF_CC_SAT_SURROUND4; pAfCb->channelConfigurationRequest.part.sub = PAF_CC_SUB_ONE; pAfCb->channelConfigurationStream.full = 0; pAfCb->channelConfigurationStream.part.sat = PAF_CC_SAT_SURROUND4; pAfCb->channelConfigurationStream.part.sub = PAF_CC_SUB_ONE; // write metadata information updated by decoder pAfCb->bsMetadata_type = PAF_bsMetadata_channelData; /* non zero if metadata is attached. */ pAfCb->pafBsMetadataUpdate = 0; /* indicates whether bit-stream metadata update */ pAfCb->numPrivateMetadata = 0; /* number of valid private metadata (0 or 1 if metadata filtering enabled) */ pAfCb->bsMetadata_offset = 0; /* offset into audio frame for change in bsMetadata_type field */ } } else if (sourceSelect == PAF_SOURCE_THD) { //gCbInitSourceSelThdCnt++; //debug pCb->maxNumAfCb = ASP_DECOP_CB_MAX_NUM_AF_THD; //pCb->afInitialLag = ASP_DECOP_CB_INIT_LAG_THD; // Initialize target nominal delay pCb->targetNDSamps = ASP_DECOP_CB_TARGET_ND_SAMPS_48kTHD; pCb->afWrtIdx = ASP_DECOP_CB_INIT_WRTIDX_THD; pCb->afRdIdx = ASP_DECOP_CB_INIT_RDIDX_THD; pCb->pcmRdIdx = 0; pCb->maxAFChanNum = ASP_DECOP_CB_MAX_NUM_PCM_CH_MAT; pCb->maxAFSampCount = ASP_DECOP_CB_MAX_PCM_FRAME_LEN_48kMAT; // initialize audio frames for (n=0; nmaxNumAfCb; n++) { pAfCb = &pCb->afCb[n]; pAfCb->sampleDecode = sourceSelect; PAF_PROCESS_ZERO(pAfCb->sampleProcess); pAfCb->sampleRate = PAF_SAMPLERATE_48000HZ; pAfCb->sampleCount = decOpFrameLen; pAfCb->channelConfigurationRequest.full = 0; pAfCb->channelConfigurationRequest.part.sat = PAF_CC_SAT_SURROUND4; pAfCb->channelConfigurationRequest.part.sub = PAF_CC_SUB_ONE; pAfCb->channelConfigurationStream.full = 0; pAfCb->channelConfigurationStream.part.sat = PAF_CC_SAT_SURROUND4; pAfCb->channelConfigurationStream.part.sub = PAF_CC_SUB_ONE; // write metadata information updated by decoder pAfCb->bsMetadata_type = PAF_bsMetadata_channelData; /* non zero if metadata is attached. */ pAfCb->pafBsMetadataUpdate = 0; /* indicates whether bit-stream metadata update */ pAfCb->numPrivateMetadata = 0; /* number of valid private metadata (0 or 1 if metadata filtering enabled) */ pAfCb->bsMetadata_offset = 0; /* offset into audio frame for change in bsMetadata_type field */ } } else { SW_BREAKPOINT; // Leave the gate GateMP_leave(gateHandle, key); return ASP_DECOP_CB_INIT_INV_SOURCE_SEL; } // initialize circular buffer current number of frames pCb->numAfCb = pCb->afWrtIdx - pCb->afRdIdx; // initialize audio frame PCM buffers pPcmBuf = pCb->pcmBuf; pMetaBuf = pCb->metaBuf; for (n=0; nmaxNumAfCb; n++) { pAfCb = &pCb->afCb[n]; pAfCb->data.nChannels = pCb->maxAFChanNum; pAfCb->data.nSamples = decOpFrameLen; for (i=0; imaxAFChanNum; i++) { pAfCb->data.sample[i] = pPcmBuf; memset(pAfCb->data.sample[i], 0, pCb->maxAFSampCount); pPcmBuf += pCb->maxAFSampCount; pAfCb->data.samsiz[i] = 0; } // Initialize metadata buffers for (i=0; ipafPrivateMetadata[i].offset = 0; pAfCb->pafPrivateMetadata[i].size = 0; pAfCb->pafPrivateMetadata[i].pMdBuf = pMetaBuf; pMetaBuf += PAF_MAX_PRIVATE_MD_SZ; } } // reset read/write flags if (resetRwFlags) { pCb->writerActiveFlag = 0; pCb->readerActiveFlag = 0; pCb->drainFlag = 0; } // reset stats pCb->readAfWriterInactiveCnt = 0; pCb->readAfNdCnt = 0; pCb->wrtAfReaderInactiveCnt = 0; pCb->wrtAfZeroSampsCnt = 0; pCb->errUndCnt = 0; pCb->errOvrCnt = 0; // Write back circular buffer configuration Cache_wb(pCb, sizeof(PAF_AST_DecOpCircBuf), Cache_Type_ALLD, 0); // Write back AF circular buffer Cache_wb(pCb->afCb, pCb->maxNumAfCb*sizeof(PAF_AudioFrame), Cache_Type_ALLD, 0); // Write back PCM data for (n=0; nmaxNumAfCb; n++) { pAfCb = &pCb->afCb[n]; Cache_wb(pAfCb->data.samsiz, pCb->maxAFChanNum*sizeof(PAF_AudioSize), Cache_Type_ALLD, 0); Cache_wb(pAfCb->data.sample, pCb->maxAFChanNum*sizeof(PAF_AudioData *), Cache_Type_ALLD, 0); for (i=0; imaxAFChanNum; i++) { Cache_wb(pAfCb->data.sample[i], pCb->maxAFSampCount*sizeof(PAF_AudioData), Cache_Type_ALLD, 0); } } Cache_wait(); // Leave the gate GateMP_leave(gateHandle, key); return ASP_DECOP_CB_SOK; } #endif // Initialize circular buffer for Stream reads Int cbInitStreamRead( PAF_AST_DecOpCircBufCtl *pCbCtl, // decoder output circular buffer control Int8 cbIdx // decoder output circular buffer index ) { IArg key; GateMP_Handle gateHandle; PAF_AST_DecOpCircBuf *pCb; // Get gate handle gateHandle = pCbCtl->gateHandle; // Enter gate key = GateMP_enter(gateHandle); // Get circular buffer base pointer pCb = &((*pCbCtl->pXDecOpCb)[cbIdx]); // Invalidate circular buffer configuration Cache_inv(pCb, sizeof(PAF_AST_DecOpCircBuf), Cache_Type_ALLD, 0); Cache_wait(); // Set output frame length pCb->strFrameLen = pCb->cbStatus.strFrameLen; // Write back circular buffer configuration Cache_wb(pCb, sizeof(PAF_AST_DecOpCircBuf), Cache_Type_ALLD, 0); Cache_wait(); // Leave the gate GateMP_leave(gateHandle, key); //return ret; return ASP_DECOP_CB_SOK; } // Start reads from circular buffer Int cbReadStart( PAF_AST_DecOpCircBufCtl *pCbCtl, // decoder output circular buffer control Int8 cbIdx // decoder output circular buffer index ) { IArg key; GateMP_Handle gateHandle; PAF_AST_DecOpCircBuf *pCb; // Get gate handle gateHandle = pCbCtl->gateHandle; // Enter gate key = GateMP_enter(gateHandle); // Get circular buffer base pointer pCb = &((*pCbCtl->pXDecOpCb)[cbIdx]); // Invalidate circular buffer configuration Cache_inv(pCb, sizeof(PAF_AST_DecOpCircBuf), Cache_Type_ALLD, 0); Cache_wait(); //Log_info1("cbReadStart:afCb=0x%04x", (IArg)pCb->afCb); // debug // update flags pCb->readerActiveFlag = 1; // Write back circular buffer configuration Cache_wb(pCb, sizeof(PAF_AST_DecOpCircBuf), Cache_Type_ALLD, 0); Cache_wait(); // Leave the gate GateMP_leave(gateHandle, key); return ASP_DECOP_CB_SOK; } // Stop reads from circular buffer Int cbReadStop( PAF_AST_DecOpCircBufCtl *pCbCtl, // decoder output circular buffer control Int8 cbIdx // decoder output circular buffer index ) { IArg key; GateMP_Handle gateHandle; PAF_AST_DecOpCircBuf *pCb; // Get gate handle gateHandle = pCbCtl->gateHandle; // Enter gate key = GateMP_enter(gateHandle); // Get circular buffer base pointer pCb = &((*pCbCtl->pXDecOpCb)[cbIdx]); // Invalidate circular buffer configuration Cache_inv(pCb, sizeof(PAF_AST_DecOpCircBuf), Cache_Type_ALLD, 0); Cache_wait(); //Log_info1("cbReadStop:afCb=0x%04x", (IArg)pCb->afCb); // debug // update flags pCb->readerActiveFlag = 0; // Write back circular buffer configuration Cache_wb(pCb, sizeof(PAF_AST_DecOpCircBuf), Cache_Type_ALLD, 0); Cache_wait(); // Leave the gate GateMP_leave(gateHandle, key); return ASP_DECOP_CB_SOK; } // debug //Int16 gDeltaSampsBuf[20]; //Int8 gDeltaSampsBufIdx=0; // Read audio frame from circular buffer Int cbReadAf( PAF_AST_DecOpCircBufCtl *pCbCtl, // decoder output circular buffer control Int8 cbIdx, // decoder output circular buffer index PAF_AudioFrame *pAfRd // audio frame into which to read ) { IArg key; GateMP_Handle gateHandle; // CB gate handle to arbitrate CB r/w access PAF_AST_DecOpCircBuf *pCb; // pointer to CB PAF_AudioFrame *pAfCb; // pointer to current CB AF PAF_ChannelMask_HD streamMask; // CB AF stream mask Int16 numSampsRd; // number of samples to read from current CB AF Int16 totNumSampsRd; // total number of samples read from CB Int16 pcmWrtIdx; // read audio frame PCM write index Int8 prvMdWrtIdx; // read audio frame metadata write index Int8 i; Int16 j; // Get gate handle gateHandle = pCbCtl->gateHandle; // Enter gate key = GateMP_enter(gateHandle); // Get circular buffer base pointer pCb = &((*pCbCtl->pXDecOpCb)[cbIdx]); // Invalidate circular buffer configuration. Cache_inv(pCb, sizeof(PAF_AST_DecOpCircBuf), Cache_Type_ALLD, 0); Cache_wait(); //Log_info1("cbReadAf:afCb=0x%04x", (IArg)pCb->afCb); // debug // // Check (writerActiveFlag,drainFlag)=(1,1) // if ((pCb->writerActiveFlag == 1) && (pCb->drainFlag == 1)) { // // This shouldn't occur: // writer is active AND draining circular buffer // //Log_info2("cbReadAf: ERROR: writerActiveFlag=%d, drainFlag=%d", pCb->writerActiveFlag, pCb->drainFlag); // debug SW_BREAKPOINT; // debug // Leave the gate GateMP_leave(gateHandle, key); return ASP_DECOP_CB_READ_INVSTATE; } // // Check (writerActiveFlag,drainFlag)=(0,0) // //if (((pCb->writerActiveFlag == 0) && (pCb->drainFlag == 0)) || (pCb->afLagIdx < pCb->afInitialLag)) if ((pCb->writerActiveFlag == 0) && (pCb->drainFlag == 0)) { // // Writer inactive, not draining circular buffer. // Skip UNDerflow check, mute output. // pCb->readAfWriterInactiveCnt++; // Mute output if write inactive and not draining CB //cbReadAfMute(pAfRd, pCb->strFrameLen); cbReadMuteWithLastAfInfo(pCb, pAfRd); // Write back circular buffer configuration. Cache_wb(pCb, sizeof(PAF_AST_DecOpCircBuf), Cache_Type_ALLD, 0); Cache_wait(); // Leave the gate GateMP_leave(gateHandle, key); return ASP_DECOP_CB_SOK; } if ((pCb->writerActiveFlag == 0) && (pCb->drainFlag == 1)) { // // Writer inactive, but remaining frames in circular buffer. // Update drain flag. // if (pCb->numAfCb <= 0) { pCb->drainFlag = 0; // Mute output if CB drained cbReadMuteWithLastAfInfo(pCb, pAfRd); // Write back circular buffer configuration. Cache_wb(pCb, sizeof(PAF_AST_DecOpCircBuf), Cache_Type_ALLD, 0); Cache_wait(); // Leave the gate GateMP_leave(gateHandle, key); return ASP_DECOP_CB_SOK; } } // // Hold off read of PCM samples from CB until Nominal Delay satisfied // //if ((pCb->primedFlag == 0) || ((pCb->primedFlag==1) && (pCb->deltaSamps > 0)) if ((pCb->primedFlag == 0) || (pCb->deltaSamps > 0)) { pCb->readAfNdCnt++; if (pCb->primedFlag == 1) { pCb->deltaSamps = pCb->deltaSamps - pCb->strFrameLen; // debug //gDeltaSampsBuf[gDeltaSampsBufIdx] = pCb->deltaSamps; //if (gDeltaSampsBufIdx < 20) // gDeltaSampsBufIdx++; } cbReadMuteWithLastAfInfo(pCb, pAfRd); // Write back circular buffer configuration. Cache_wb(pCb, sizeof(PAF_AST_DecOpCircBuf), Cache_Type_ALLD, 0); Cache_wait(); // Leave the gate GateMP_leave(gateHandle, key); return ASP_DECOP_CB_SOK; } // // (writerActiveFlag,drainFlag)= (0,0) and (1,1) states checked above // (writerActiveFlag,drainFlag)=(1,0) and (0,1) states are left // Checking (writerActiveFlag,drainFlag)=(1,0) state here // if (pCb->writerActiveFlag == 1) { // check underflow if (pCb->numAfCb <= 0) { // // Increment underflow count // pCb->errAfUndCnt++; // Mute output on underflow //cbReadAfMute(pAfRd, pCb->strFrameLen); cbReadMuteWithLastAfInfo(pCb, pAfRd); //SW_BREAKPOINT; // debug #if 0 // (***) FL: shows timing of CB underflow // debug { static Uint8 toggleState = 0; if (toggleState == 0) GPIOSetOutput(GPIO_PORT_0, GPIO_PIN_107); else GPIOClearOutput(GPIO_PORT_0, GPIO_PIN_107); toggleState = ~(toggleState); } #endif #ifdef CB_RW_OP_CAP_PP // debug if (pCb->cb_opCnt < CB_OP_COUNT_MAX) { if ((pCb->cb_samples_op != NULL) && (pCb->cb_op_owner != NULL)) { // log sample count pCb->cb_samples_op[pCb->cb_opCnt] = 0; // due to underflow pCb->cb_op_owner[pCb->cb_opCnt] = CB_OP_R; // log idxs pCb->cb_afRdIdx[pCb->cb_opCnt] = pCb->afRdIdx; pCb->cb_afWrtIdx[pCb->cb_opCnt] = pCb->afWrtIdx; pCb->cb_numAfCb[pCb->cb_opCnt] = pCb->numAfCb; // numAfCb might not be pointing to this instance pCb->cb_opCnt++; } } #endif // Write back circular buffer configuration. Cache_wb(pCb, sizeof(PAF_AST_DecOpCircBuf), Cache_Type_ALLD, 0); Cache_wait(); // Leave the gate GateMP_leave(gateHandle, key); return ASP_DECOP_CB_AF_READ_UNDERFLOW; } } // // Checking (writerActiveFlag,drainFlag)=(1,0) state above and here // Checking (writerActiveFlag,drainFlag)=(0,1) state here // if ((pCb->writerActiveFlag == 1) || (pCb->drainFlag == 1)) { // // Writer active or draining remaining frames in circular buffer. // Read next audio frame. // // // Read Audio Frame from CB Audio Frames. // Read PCM & associated metadata from CB AFs until Read AF is filled. // // If multiple CB AFs are read in creating Read AF, CB AF parameters // can *change* between read CB AFs. Since only one Read AF is produced // per CB read, this is a "data collision", i.e. can't have more than // one set of CB AF parameters in Read AF. // // Currently applying parameters from earliest read CB AF to Read Af. // This can result in delay (or skip) w.r.t. application of additional // CB AF parameters not used for creating Read AF. This is reasonable // given there's no way to "interpolate" AF parameters, e.g. how to // interpolation change in in bit-stream metadata type, or CC stream? // // Get pointer to current CB Audio Frame pAfCb = &pCb->afCb[pCb->afRdIdx]; // Cache invalidate CB AF Cache_inv(pAfCb, sizeof(PAF_AudioFrame), Cache_Type_ALLD, 0); Cache_wait(); // Read CB AF information updated by decoder pAfRd->sampleDecode = pAfCb->sampleDecode; PAF_PROCESS_COPY(pAfRd->sampleProcess, pAfCb->sampleProcess); pAfRd->sampleRate = pAfCb->sampleRate; pAfRd->channelConfigurationRequest = pAfCb->channelConfigurationRequest; pAfRd->channelConfigurationStream = pAfCb->channelConfigurationStream; // Read CB AF bit-stream metadata information updated by decoder pAfRd->bsMetadata_type = pAfCb->bsMetadata_type; /* non zero if private metadata is attached. */ pAfRd->pafBsMetadataUpdate = pAfCb->pafBsMetadataUpdate; /* indicates whether bit-stream metadata update */ pAfRd->bsMetadata_offset = pAfCb->bsMetadata_offset; /* offset into audio frame for change in bsMetadata_type field */ #ifdef DTS_BUILD pAfRd->mode = pAfCb->mode; /* mode is used in DTSX to pass info to PARMA */ pAfRd->numChansUsedForMetadata = pAfCb->numChansUsedForMetadata; /* if metadata is used in DTSX */ pAfRd->pafBsFixedData = pAfCb->pafBsFixedData; /* if true, do not convert float to fixed in DTSX metadata transfer */ pAfRd->root = pAfCb->root; /* used for channel MASK in DTSX. BAD IDEA, need fix */ #endif // Compute stream mask for current CB AF. // Mask indicates which channels are present in AF. // Mask needed for cache invalidate and read of PCM samples in AF. streamMask = pAfRd->fxns->channelMask(pAfRd, pAfCb->channelConfigurationStream); // Cache invalidate CB AF samsiz (volume scaling exponent) array Cache_inv(pAfCb->data.samsiz, pCb->maxAFChanNum*sizeof(PAF_AudioSize), Cache_Type_ALLD, 0); Cache_wait(); // Read CB AF samsiz array for (i = 0; i < pCb->maxAFChanNum; i++) { #ifndef DTS_BUILD if ((streamMask >> i) & 0x1) #endif {//DTSX needs up to 16 channels to transfer metadata. pAfRd->data.samsiz[i] = pAfCb->data.samsiz[i]; } } // FL: brute force clear of Read AF PCM data // Reset Read AF PCM data //for (i = 0; i < pCb->maxAFChanNum; i++) //{ // if ((streamMask >> i) & 0x1) // { // memset(pAfRd->data.sample[i], 0, pCb->strFrameLen); // } //} // FL: This brute force approach shouldn't be necessary if // decoders properly set, and downstream components // properly use, number of private metadata in frame // Reset Read AF metadata for (i = 0; i < PAF_MAX_NUM_PRIVATE_MD; i++) { pAfRd->pafPrivateMetadata[i].offset = 0; pAfRd->pafPrivateMetadata[i].size = 0; } totNumSampsRd = 0; // init total number of samples read from CB pcmWrtIdx = 0; // init Read AF PCM write index prvMdWrtIdx = 0; // init Read AF metadata write index while ((totNumSampsRd < pCb->strFrameLen) && (pCb->numAfCb > 0)) { // Compute how many PCM samples can be read from CB AF // Number of samples left in current CB AF: pAfCb->sampleCount - pCb->pcmRdIdx // Number of samples left to write to Read AF: pCb->strFrameLen - totNumSampsRd numSampsRd = (pAfCb->sampleCount - pCb->pcmRdIdx) < (pCb->strFrameLen - totNumSampsRd) ? (pAfCb->sampleCount - pCb->pcmRdIdx) : (pCb->strFrameLen - totNumSampsRd); // Cache invalidate CB AF PCM sample channel pointers Cache_inv(pAfCb->data.sample, pCb->maxAFChanNum*sizeof(PAF_AudioData *), Cache_Type_ALLD, 0); Cache_wait(); // Cache invalidate CB AF PCM samples for (i = 0; i < pCb->maxAFChanNum; i++) { #ifndef DTS_BUILD if ((streamMask >> i) & 0x1) #endif {//DTSX needs up to 16 channels to transfer metadata. Cache_inv(&pAfCb->data.sample[i][pCb->pcmRdIdx], numSampsRd*sizeof(PAF_AudioData), Cache_Type_ALLD, 0); } } Cache_wait(); // Read PCM samples from CB AF for (i = 0; i < pCb->maxAFChanNum; i++) { #ifndef DTS_BUILD if ((streamMask >> i) & 0x1) #endif {//DTSX needs up to 16 channels to transfer metadata. for (j = 0; j < numSampsRd; j++) { pAfRd->data.sample[i][pcmWrtIdx+j] = pAfCb->data.sample[i][pCb->pcmRdIdx+j]; } } } // Cache invalidate CB AF unused metadata for (i = pCb->prvMdRdIdx; i < pAfCb->numPrivateMetadata; i++) { Cache_inv(pAfCb->pafPrivateMetadata[i].pMdBuf, pAfCb->pafPrivateMetadata[i].size, Cache_Type_ALLD, 0); // only update metadata package size } Cache_wait(); // Read CB AF metadata while (((pCb->prvMdRdIdx < pAfCb->numPrivateMetadata) && (pAfCb->pafPrivateMetadata[pCb->prvMdRdIdx].offset >= pCb->pcmRdIdx) && (pAfCb->pafPrivateMetadata[pCb->prvMdRdIdx].offset < (pCb->pcmRdIdx + numSampsRd)) && (pAfCb->pafPrivateMetadata[pCb->prvMdRdIdx].size)) && (prvMdWrtIdx < PAF_MAX_NUM_PRIVATE_MD)) { // Write Read AF metadata offset. // Compute relative offset of PCM samples being read from CB AF. // Compute absolute offset of PCM samples written to Read AF by // adding relative offset to Read AF PCM write index. pAfRd->pafPrivateMetadata[prvMdWrtIdx].offset = (pAfCb->pafPrivateMetadata[pCb->prvMdRdIdx].offset - pCb->pcmRdIdx) + // offset relative to samples being read from CB AF pcmWrtIdx; // absolute offset into samples being written to read AF // Write Read AF metadata size pAfRd->pafPrivateMetadata[prvMdWrtIdx].size = pAfCb->pafPrivateMetadata[pCb->prvMdRdIdx].size; // Write Read AF metadata payload memcpy(pAfRd->pafPrivateMetadata[prvMdWrtIdx].pMdBuf, pAfCb->pafPrivateMetadata[pCb->prvMdRdIdx].pMdBuf, pAfCb->pafPrivateMetadata[pCb->prvMdRdIdx].size); pCb->prvMdRdIdx++; // update CB metadata read index prvMdWrtIdx++; // update CB metadata write index } // Update CB control pCb->pcmRdIdx += numSampsRd; // update PCM read index if (pCb->pcmRdIdx >= pAfCb->sampleCount) { // Finished reading PCM samples from current CB AF. // Move to next AF in CB. // Update audio frame read index. // Wrap index if required. pCb->afRdIdx++; if (pCb->afRdIdx >= pCb->maxNumAfCb) { pCb->afRdIdx = 0; } // Reset PCM read index pCb->pcmRdIdx = 0; // Reset metadata read index pCb->prvMdRdIdx = 0; // Update number of audio frames in circular buffer pCb->numAfCb--; } // Update PCM write index pcmWrtIdx += numSampsRd; // Update total number of samples read totNumSampsRd += numSampsRd; if (totNumSampsRd < pCb->strFrameLen) { // // Need to read another AF from CB to obtain all PCM/metadata for Read AF // // Get pointer to current CB Audio Frame pAfCb = &pCb->afCb[pCb->afRdIdx]; // Cache invalidate CB AF Cache_inv(pAfCb, sizeof(PAF_AudioFrame), Cache_Type_ALLD, 0); Cache_wait(); } } pAfRd->sampleCount = totNumSampsRd; // write Read AF sample count pAfRd->numPrivateMetadata = prvMdWrtIdx; // write Read AF number of metadata pCb->numPcmSampsPerCh -= totNumSampsRd; // update PCM samples per channel if (totNumSampsRd < pCb->strFrameLen) { // Clear remaining Read AF PCM samples for (i = 0; i < pCb->maxAFChanNum; i++) { #ifndef DTS_BUILD if ((streamMask >> i) & 0x1) #endif {//DTSX needs up to 16 channels to transfer metadata. memset(&pAfRd->data.sample[i][pcmWrtIdx], 0, (pCb->strFrameLen-totNumSampsRd)); } } if (pCb->writerActiveFlag == 1) { // // UNDerflow, // read stopped due to insufficient PCM samples in CB to fill Read AF // // // Increment underflow count // pCb->errPcmUndCnt++; // Mute output on underflow cbReadMuteWithLastAfInfo(pCb, pAfRd); #if 0 // (***) FL: shows timing of CB underflow // debug { static Uint8 toggleState = 0; if (toggleState == 0) GPIOSetOutput(GPIO_PORT_0, GPIO_PIN_107); else GPIOClearOutput(GPIO_PORT_0, GPIO_PIN_107); toggleState = ~(toggleState); } #endif #ifdef CB_RW_OP_CAP_PP // debug if (pCb->cb_opCnt < CB_OP_COUNT_MAX) { if ((pCb->cb_samples_op != NULL) && (pCb->cb_op_owner != NULL)) { // log sample count pCb->cb_samples_op[pCb->cb_opCnt] = 0; // due to underflow pCb->cb_op_owner[pCb->cb_opCnt] = CB_OP_R; // log idxs pCb->cb_afRdIdx[pCb->cb_opCnt] = pCb->afRdIdx; pCb->cb_afWrtIdx[pCb->cb_opCnt] = pCb->afWrtIdx; pCb->cb_numAfCb[pCb->cb_opCnt] = pCb->numAfCb; // numAfCb might not be pointing to this instance pCb->cb_opCnt++; } } #endif // Write back circular buffer configuration. Cache_wb(pCb, sizeof(PAF_AST_DecOpCircBuf), Cache_Type_ALLD, 0); Cache_wait(); // Leave the gate GateMP_leave(gateHandle, key); return ASP_DECOP_CB_PCM_READ_UNDERFLOW; } } // Read AF complete, update Last CB AF Info cbUpdateLastAfInfo(pCb, pAfRd); #if 0 // (***) FL: shows timing of successful CB read { static Uint8 toggleState = 0; if (toggleState == 0) GPIOSetOutput(GPIO_PORT_0, GPIO_PIN_106); else GPIOClearOutput(GPIO_PORT_0, GPIO_PIN_106); toggleState = ~(toggleState); } #endif #ifdef CB_RW_OP_CAP_PP // debug if (pCb->cb_opCnt < CB_OP_COUNT_MAX) { if ((pCb->cb_samples_op != NULL) && (pCb->cb_op_owner != NULL)) { // log sample count pCb->cb_samples_op[pCb->cb_opCnt] = pAfRd->sampleCount; pCb->cb_op_owner[pCb->cb_opCnt] = CB_OP_R; // log idxs pCb->cb_afRdIdx[pCb->cb_opCnt] = pCb->afRdIdx; pCb->cb_afWrtIdx[pCb->cb_opCnt] = pCb->afWrtIdx; pCb->cb_numAfCb[pCb->cb_opCnt] = pCb->numAfCb; // numAfCb might not be pointing to this instance pCb->cb_opCnt++; } } #endif } #if 0 if (pCb->drainFlag == 1) { // // Writer inactive, but remaining frames in circular buffer. // Update drain flag. // if (pCb->numAfCb <= 0) { pCb->drainFlag = 0; } } #endif // Write back circular buffer configuration. // NOTE: Probably only a subset of this information needs to be updated. Cache_wb(pCb, sizeof(PAF_AST_DecOpCircBuf), Cache_Type_ALLD, 0); Cache_wait(); // Leave the gate GateMP_leave(gateHandle, key); return ASP_DECOP_CB_SOK; } #if 0 // Generate mute AF on circular buffer read static Void cbReadAfMute( PAF_AudioFrame *pAfRd, // audio frame into which to read Int16 strFrameLen // stream frame length (output transaction size) ) { PAF_ChannelMask_HD streamMask; Int8 i; pAfRd->sampleDecode = PAF_SOURCE_PCM; PAF_PROCESS_ZERO(pAfRd->sampleProcess); pAfRd->sampleRate = PAF_SAMPLERATE_48000HZ; pAfRd->sampleCount = strFrameLen; pAfRd->channelConfigurationRequest.full = 0; pAfRd->channelConfigurationRequest.part.sat = PAF_CC_SAT_SURROUND4; pAfRd->channelConfigurationRequest.part.sub = PAF_CC_SUB_ONE; pAfRd->channelConfigurationStream.full = 0; pAfRd->channelConfigurationStream.part.sat = PAF_CC_SAT_SURROUND4; pAfRd->channelConfigurationStream.part.sub = PAF_CC_SUB_ONE; // compute stream mask streamMask = pAfRd->fxns->channelMask(pAfRd, pAfRd->channelConfigurationStream); // Clear PCM data for (i = 0; i < ASP_DECOP_CB_MAX_NUM_PCM_CH; i++) { #ifndef DTS_BUILD if ((streamMask >> i) & 0x1) #endif {//DTSX needs up to 16 channels to transfer metadata. memset(pAfRd->data.sample[i], 0, strFrameLen*sizeof(PAF_AudioData)); } pAfRd->data.samsiz[i] = 0; } // write metadata information updated by decoder pAfRd->bsMetadata_type = PAF_bsMetadata_channelData; /* non zero if metadata is attached. */ pAfRd->pafBsMetadataUpdate = 0; /* indicates whether bit-stream metadata update */ pAfRd->numPrivateMetadata = 0; /* number of valid private metadata (0 or 1 if metadata filtering enabled) */ pAfRd->bsMetadata_offset = 0; /* offset into audio frame for change in bsMetadata_type field */ } #endif #if 0 // FL: unused // Init last audio frame configuration info static Void cbInitLastAfInfo( PAF_AudioFrame *pAfRd // last audio frame stored in CB instance ) { pAfRd->sampleDecode = PAF_SOURCE_PCM; PAF_PROCESS_ZERO(pAfRd->sampleProcess); pAfRd->sampleRate = PAF_SAMPLERATE_48000HZ; pAfRd->sampleCount = DEF_DEC_OP_FRAME_LEN; pAfRd->channelConfigurationRequest.full = 0; pAfRd->channelConfigurationRequest.part.sat = PAF_CC_SAT_SURROUND4; pAfRd->channelConfigurationRequest.part.sub = PAF_CC_SUB_ONE; pAfRd->channelConfigurationStream.full = 0; pAfRd->channelConfigurationStream.part.sat = PAF_CC_SAT_SURROUND4; pAfRd->channelConfigurationStream.part.sub = PAF_CC_SUB_ONE; pAfRd->bsMetadata_type = PAF_bsMetadata_none; /* non zero if metadata is attached. */ pAfRd->pafBsMetadataUpdate = 0; /* indicates whether bit-stream metadata update */ pAfRd->numPrivateMetadata = 0; /* number of valid private metadata (0 or 1 if metadata filtering enabled) */ pAfRd->bsMetadata_offset = 0; /* offset into audio frame for change in bsMetadata_type field */ } #endif // Update last audio frame configuration info static Void cbUpdateLastAfInfo( PAF_AST_DecOpCircBuf *pCb, // decoder output circular buffer control PAF_AudioFrame *pAfUpd // audio frame used for update ) { // FL: full copy shouldn't be necessary // Note currently (data.nChannels, data.nSamples)=(32,256) is fixed in ASOT stream AF. // There parameters aren't copied from CB on CB read. //memcpy (&pCb->lastAf, pAfUpd, sizeof(PAF_AudioFrame)); // These are parameters used in cbReadMuteWithLastAfInfo() pCb->lastAf.sampleDecode = pAfUpd->sampleDecode; pCb->lastAf.sampleRate = pAfUpd->sampleRate; pCb->lastAf.channelConfigurationRequest.full = pAfUpd->channelConfigurationRequest.full; pCb->lastAf.channelConfigurationStream.full = pAfUpd->channelConfigurationStream.full; } // Generate mute AF on circular buffer read using the last AF configuration info static Void cbReadMuteWithLastAfInfo( PAF_AST_DecOpCircBuf *pCb, // decoder output circular buffer control PAF_AudioFrame *pAfRd // audio frame into which to read ) { PAF_ChannelMask_HD streamMask; Int8 i; pAfRd->sampleDecode = pCb->lastAf.sampleDecode; PAF_PROCESS_ZERO(pAfRd->sampleProcess); pAfRd->sampleRate = pCb->lastAf.sampleRate; pAfRd->sampleCount = pCb->strFrameLen; pAfRd->channelConfigurationRequest.full = pCb->lastAf.channelConfigurationRequest.full; //pAfRd->channelConfigurationRequest.part.sat = pCb->lastAf.channelConfigurationRequest.part.sat; // FL: not necessary since full in union already copied //pAfRd->channelConfigurationRequest.part.sub = pCb->lastAf.channelConfigurationRequest.part.sub; pAfRd->channelConfigurationStream.full = pCb->lastAf.channelConfigurationStream.full; //pAfRd->channelConfigurationStream.part.sat = pCb->lastAf.channelConfigurationStream.part.sat; //pAfRd->channelConfigurationStream.part.sub = pCb->lastAf.channelConfigurationStream.part.sub; // compute stream mask streamMask = pAfRd->fxns->channelMask(pAfRd, pAfRd->channelConfigurationStream); // Clear PCM data for (i = 0; i < ASP_DECOP_CB_MAX_NUM_PCM_CH; i++) { #ifndef DTS_BUILD if ((streamMask >> i) & 0x1) #endif {//DTSX needs up to 16 channels to transfer metadata. memset(pAfRd->data.sample[i], 0, pAfRd->sampleCount*sizeof(PAF_AudioData)); } pAfRd->data.samsiz[i] = 0; } pAfRd->bsMetadata_type = PAF_bsMetadata_none; /* non zero if metadata is attached. */ pAfRd->pafBsMetadataUpdate = 0; /* indicates whether bit-stream metadata update */ pAfRd->numPrivateMetadata = 0; /* number of valid private metadata (0 or 1 if metadata filtering enabled) */ pAfRd->bsMetadata_offset = 0; /* offset into audio frame for change in bsMetadata_type field */ #ifdef DTS_BUILD pAfRd->mode = 0; /* mode used by PARMA */ pAfRd->numChansUsedForMetadata = 15; /* constant of 15 */ pAfRd->pafBsFixedData = TRUE; /* if true, do not convert float to fixed in DTSX metadata transfer */ pAfRd->root = 0x1BF; /* used for channel MASK in DTSX. 0x1BF = 7.1 as defined in dtshd_dec_api_common.h */ #endif } // Check circular buffer drain state Int cbCheckDrainState( PAF_AST_DecOpCircBufCtl *pCbCtl, // decoder output circular buffer control Int8 cbIdx, // decoder output circular buffer index, or indicator combined drain state desired Int8 *pDrainedFlag // output drain state indicator (combined or for selected circular buffer) ) { IArg key; GateMP_Handle gateHandle; PAF_AST_DecOpCircBuf *pCb; Int8 drainedFlag; Int8 i; // Get gate handle gateHandle = pCbCtl->gateHandle; // Enter gate key = GateMP_enter(gateHandle); if (cbIdx != ASP_DECOP_CHECK_DRAINSTATE_ALL) { // // Check drain state for selected circular buffer // // Get circular buffer base pointer pCb = &((*pCbCtl->pXDecOpCb)[cbIdx]); // Invalidate circular buffer configuration Cache_inv(pCb, sizeof(PAF_AST_DecOpCircBuf), Cache_Type_ALLD, 0); Cache_wait(); drainedFlag = !pCb->writerActiveFlag && !pCb->drainFlag; } else { // // Check combined drain state for all circular buffers. // Combined drain state is logical AND of drain state for all circular buffers. // drainedFlag = 1; // init combined drained flag to TRUE for (i = 0; i < pCbCtl->numDecOpCb; i++) { // Get circular buffer base pointer pCb = &((*pCbCtl->pXDecOpCb)[i]); // Invalidate circular buffer configuration Cache_inv(pCb, sizeof(PAF_AST_DecOpCircBuf), Cache_Type_ALLD, 0); Cache_wait(); // Update combined drain state drainedFlag = drainedFlag && (!pCb->writerActiveFlag && !pCb->drainFlag); } } *pDrainedFlag = drainedFlag; // Leave the gate GateMP_leave(gateHandle, key); return ASP_DECOP_CB_SOK; }