/* 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 "common.h" #include "paftyp.h" //#include "pafdec.h" //#include "pafsp.h" #include "aspDecOpCircBuf_slave.h" #include "evmc66x_gpio_dbg.h" // Debug // Init last audio frame configuration info static Void cbInitLastAfInfo( PAF_AST_DecOpCircBuf *pCb, // decoder output circular buffer control PAF_AudioFrame *pAfInit // audio frame used for init ); #if 0 // FL: moved to common // Initialize circular buffer control Int cbCtlInit( PAF_AST_DecOpCircBufCtl *pCbCtl, // decoder output circular buffer control PAF_AST_DecOpCircBuf **pXDecOpCb // address of decoder output circular buffer base pointer ) { GateMP_Handle gateHandle; Int status; do { status = GateMP_open(ASP_DECODE_CB_GATE_NAME, &gateHandle); } while (status == GateMP_E_NOTFOUND); if (status == GateMP_S_SUCCESS) { 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 // debug //Int8 gCbInitDecWriteCnt=0; //Int8 gCbInitDecWriteThdCnt=0; /// Initialize circular buffer for Decoder writes Int cbInitDecWrite( 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) Int8 resetRwFlags, // whether to reset reader, writer, and drain flags PAF_AudioFrame *pDecInitAf // pointer to Dec output audio frame used for CB initialization ) { IArg key; GateMP_Handle gateHandle; PAF_AST_DecOpCircBuf *pCb; PAF_AudioFrame *pAfCb; PAF_AudioData *pPcmBuf; UInt8 *pMetaBuf; Int8 n; Int8 i; //gCbInitDecWriteCnt++; // 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("cbInitDecWrite:afCb=0x%04x", (IArg)pCb->afCb); // debug // Set source select pCb->sourceSel = sourceSelect; // Set input frame length pCb->decOpFrameLen = decOpFrameLen; //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 AFs // - target nominal delay // - AF write, read indices // - maximum AF channel and sample counts // - maximum number of PCM samples per channel if (sourceSelect == PAF_SOURCE_PCM) { pCb->maxNumAfCb = ASP_DECOP_CB_MAX_NUM_AF_PCM; //pCb->afInitialLag = ASP_DECOP_CB_INIT_LAG_PCM; 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->maxAFChanNum = ASP_DECOP_CB_MAX_NUM_PCM_CH; pCb->maxAFSampCount = DEF_DEC_OP_FRAME_LEN; pCb->maxNumPcmSampsPerCh = (Int32)(pCb->pcmBufEnd - pCb->pcmBuf)/pCb->maxAFChanNum; } else if (sourceSelect == PAF_SOURCE_AAC) { pCb->maxNumAfCb = ASP_DECOP_CB_MAX_NUM_AF_AAC; //pCb->afInitialLag = ASP_DECOP_CB_INIT_LAG_PCM; pCb->targetNDSamps = ASP_DECOP_CB_TARGET_ND_SAMPS_AAC; pCb->afWrtIdx = ASP_DECOP_CB_INIT_WRTIDX_AAC; pCb->afRdIdx = ASP_DECOP_CB_INIT_RDIDX_AAC; pCb->maxAFChanNum = ASP_DECOP_CB_MAX_NUM_PCM_CH_AAC; pCb->maxAFSampCount = ASP_DECOP_CB_MAX_PCM_FRAME_LEN_48kAAC; pCb->maxNumPcmSampsPerCh = (Int32)(pCb->pcmBufEnd - pCb->pcmBuf)/pCb->maxAFChanNum; } 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; pCb->targetNDSamps = ASP_DECOP_CB_TARGET_ND_SAMPS_DDP; pCb->afWrtIdx = ASP_DECOP_CB_INIT_WRTIDX_DDP; pCb->afRdIdx = ASP_DECOP_CB_INIT_RDIDX_DDP; pCb->maxAFChanNum = ASP_DECOP_CB_MAX_NUM_PCM_CH_DDP; pCb->maxAFSampCount = ASP_DECOP_CB_MAX_PCM_FRAME_LEN_48kDDP; pCb->maxNumPcmSampsPerCh = (Int32)(pCb->pcmBufEnd - pCb->pcmBuf)/pCb->maxAFChanNum; } 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; // FL: (***) set nominal delay per sampling rate -- need to review these settings switch (pDecInitAf->sampleRate) { case PAF_SAMPLERATE_44100HZ: case PAF_SAMPLERATE_48000HZ: pCb->targetNDSamps = ASP_DECOP_CB_TARGET_ND_SAMPS_48kTHD; break; case PAF_SAMPLERATE_88200HZ: case PAF_SAMPLERATE_96000HZ: pCb->targetNDSamps = ASP_DECOP_CB_TARGET_ND_SAMPS_96kTHD; break; case PAF_SAMPLERATE_176400HZ: case PAF_SAMPLERATE_192000HZ: pCb->targetNDSamps = ASP_DECOP_CB_TARGET_ND_SAMPS_192kTHD; break; default: pCb->targetNDSamps = ASP_DECOP_CB_TARGET_ND_SAMPS_48kTHD; break; } pCb->afWrtIdx = ASP_DECOP_CB_INIT_WRTIDX_THD; pCb->afRdIdx = ASP_DECOP_CB_INIT_RDIDX_THD; pCb->maxAFChanNum = ASP_DECOP_CB_MAX_NUM_PCM_CH_MAT; pCb->maxAFSampCount = ASP_DECOP_CB_MAX_PCM_FRAME_LEN_48kMAT; pCb->maxNumPcmSampsPerCh = (Int32)(pCb->pcmBufEnd - pCb->pcmBuf)/pCb->maxAFChanNum; } else if ((sourceSelect == PAF_SOURCE_DTS) || (sourceSelect == PAF_SOURCE_DTSHD) || (sourceSelect == PAF_SOURCE_DTS12) || (sourceSelect == PAF_SOURCE_DTS13) || (sourceSelect == PAF_SOURCE_DTS14) || (sourceSelect == PAF_SOURCE_DTS16) || (sourceSelect == PAF_SOURCE_DTSALL) ) { pCb->maxNumAfCb = ASP_DECOP_CB_MAX_NUM_AF_DTS; pCb->afWrtIdx = ASP_DECOP_CB_INIT_WRTIDX_DTS; pCb->afRdIdx = ASP_DECOP_CB_INIT_RDIDX_DTS; pCb->pcmRdIdx = 0; pCb->maxAFChanNum = ASP_DECOP_CB_MAX_NUM_PCM_CH_DTS; pCb->maxAFSampCount = ASP_DECOP_CB_MAX_PCM_FRAME_LEN_48kDTS; // 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_DTS_X; /* Audio data from DTSX decoder. */ 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 { // // Currently unsupported source select // SW_BREAKPOINT; // debug // Leave the gate GateMP_leave(gateHandle, key); return ASP_DECOP_CB_INIT_INV_SOURCE_SEL; } // Initialize circular buffer: // - PCM read index // - Private metadata read index // - number of PCM samples in CB pCb->pcmRdIdx = 0; pCb->prvMdRdIdx = 0; pCb->numPcmSampsPerCh = 0; // Initialize audio frames for (n = 0; n < pCb->maxNumAfCb; n++) { pAfCb = &pCb->afCb[n]; // get pointer to CB AF // Dec init AF sample count not correct for CB AFs. // Dec Op frame length is computed in framework based on selected source. pAfCb->sampleCount = decOpFrameLen; // initialize CB AF using Dec init AF pAfCb->sampleDecode = pDecInitAf->sampleDecode; PAF_PROCESS_COPY(pAfCb->sampleProcess, pDecInitAf->sampleProcess); pAfCb->sampleRate = pDecInitAf->sampleRate; pAfCb->channelConfigurationRequest.full = pDecInitAf->channelConfigurationRequest.full; pAfCb->channelConfigurationStream.full = pDecInitAf->channelConfigurationStream.full; // initialize metadata information updated by decoder pAfCb->bsMetadata_type = PAF_bsMetadata_none; /* 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 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]; // get pointer to CB AF 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; } } // Initialize last audio frame configuration info cbInitLastAfInfo(pCb, pDecInitAf); // Reset read/write flags if (resetRwFlags != 0) { pCb->writerActiveFlag = 0; pCb->readerActiveFlag = 0; pCb->drainFlag = 0; } // Reset stats pCb->readAfWriterInactiveCnt = 0; pCb->readAfNdCnt = 0; pCb->wrtAfReaderInactiveCnt = 0; pCb->wrtAfZeroSampsCnt = 0; pCb->errAfUndCnt = 0; pCb->errAfOvrCnt = 0; pCb->errPcmUndCnt = 0; pCb->errPcmOvrCnt = 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; } //Int8 gCbWriteStartCnt=0; // debug // Start writes to circular buffer Int cbWriteStart( 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; PAF_AudioFrame *pAfCb; Int8 n; //Int8 i; //gCbWriteStartCnt++; // 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. // NOTE: Probably only a subset of this information needs to be updated. Cache_inv(pCb, sizeof(PAF_AST_DecOpCircBuf), Cache_Type_ALLD, 0); Cache_wait(); //Log_info1("cbWriteStart:afCb=0x%04x", (IArg)pCb->afCb); // debug // Invalidate AF circular buffer Cache_inv(pCb->afCb, pCb->maxNumAfCb*sizeof(PAF_AudioFrame), Cache_Type_ALLD, 0); for (n=0; nmaxNumAfCb; n++) { pAfCb = &pCb->afCb[n]; Cache_inv(pAfCb->data.sample, pCb->maxAFChanNum*sizeof(PAF_AudioData *), Cache_Type_ALLD, 0); } Cache_wait(); // update flags pCb->writerActiveFlag = 1; pCb->drainFlag = 0; //pCb->afLagIdx = 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; }; // Stop writes to circular buffer Int cbWriteStop( 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("cbWriteStop:afCb=0x%04x", (IArg)pCb->afCb); // debug // update flags pCb->writerActiveFlag = 0; pCb->drainFlag = 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; } // debug //Int16 gSampleCountBuf[10]; //Int16 gCalcDeltaSampsBuf[10]; //Int8 gPrimedFlagCnt=0; // (***) FL: revisit // Write audio frame to circular buffer Int cbWriteAf( PAF_AST_DecOpCircBufCtl *pCbCtl, // decoder output circular buffer control Int8 cbIdx, // decoder output circular buffer index PAF_AudioFrame *pAfWrt // audio frame from which to write ) { IArg key; GateMP_Handle gateHandle; PAF_AST_DecOpCircBuf *pCb; PAF_AudioFrame *pAfCb; PAF_ChannelMask_HD streamMask; Int8 i; Int16 j; PAF_AudioData *pPcmBuf; UInt8 *pMetaBuf; //int nextWrtIdx; //PAF_AudioFrame *pAfCbNextAf; PAF_AudioFrame *pAfCbRd; PAF_AudioData *pPcmBufRd, *pPcmBufWrt; Int8 pcmOvr; // Get gate handle gateHandle = pCbCtl->gateHandle; // Enter gate key = GateMP_enter(gateHandle); //Log_info2("cbWriteAf:gate enter, gateHandle=0x%04x, key=%d", (IArg)gateHandle, (IArg)key); // debug // Get circular buffer base pointer pCb = &((*pCbCtl->pXDecOpCb)[cbIdx]); //Log_info1("cbWriteAf:pCb=0x%04x", (IArg)pCb); // debug // Invalidate circular buffer configuration. // NOTE: Probably only a subset of this information needs to be updated. Cache_inv(pCb, sizeof(PAF_AST_DecOpCircBuf), Cache_Type_ALLD, 0); Cache_wait(); //Log_info1("cbWriteAf:afCb=0x%04x", (IArg)pCb->afCb); // debug //Log_info2("cbWriteAf:pCb->readerActiveFlag=%d, pCb->writerActiveFlag=%d", (IArg)pCb->readerActiveFlag, (IArg)pCb->writerActiveFlag); // debug //if (pCb->readerActiveFlag == 1) //{ // // // // Normal case, reader active. // // if (pAfWrt->sampleCount != 0) { //Log_info2("cbWriteAf:pCb->numAfCb=%d, pCb->maxNumAfCb=%d", (IArg)pCb->readerActiveFlag, (IArg)pCb->maxNumAfCb); // debug // check AF overflow if (pCb->numAfCb >= pCb->maxNumAfCb) { pCb->errAfOvrCnt++; //SW_BREAKPOINT; Log_info1("cbWriteAf: ERROR: AF CB overflow, numAfCb=%d", pCb->numAfCb); // 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); //Log_info2("cbWriteAf:gate leave, gateHandle=0x%04x, key=%d", (IArg)gateHandle, (IArg)key); // debug return ASP_DECOP_CB_AF_WRITE_OVERFLOW; } // FL: this won't reliably detect overflow because of PCM buffer write address wrap // check PCM overflow //if ((pCb->numPcmSampsPerCh + pAfWrt->sampleCount) > pCb->maxNumPcmSampsPerCh) //{ // pCb->errPcmOvrCnt++; // // Log_info3("cbWriteAf: ERROR: PCM CB overflow, sampleCount=%d, numPcmSampsPerCh=%d, maxNumPcmSampsPerCh=%d", // pCb->numPcmSampsPerCh, pAfWrt->sampleCount, pCb->maxNumPcmSampsPerCh); // // // 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_WRITE_OVERFLOW; //} // get CB AF write info pAfCb = &pCb->afCb[pCb->afWrtIdx]; // get CB AF to be written pPcmBufWrt = pAfCb->data.sample[0]; // get current location in PCM buffer to be written // (***) FL: currently no metadata buffer overflow detection pMetaBuf = pAfCb->pafPrivateMetadata[0].pMdBuf; // get current location in MD buffer to be written // get CB AF read info pAfCbRd = &pCb->afCb[pCb->afRdIdx]; // get CB AF being read //pPcmBufRd = pAfCbRd->data.sample[0]; // FL: starting location of PCM samples for AF being read pPcmBufRd = pAfCbRd->data.sample[0] + pCb->pcmRdIdx; // FL: current location of PCM samples for AF being read // Check PCM buffer overflow pPcmBuf = pPcmBufWrt; pcmOvr = 0; for (i = 0; i < pCb->maxAFChanNum; i++) { // // Writes of PCM to PCM CB use CC stream, but this isn't considered here. // For each channel which *can* be written, check the current reader location won't be overwritten. // The current reader location is the earliest channel which *could have been* written for that CB AF. // if ((pPcmBuf + pAfWrt->sampleCount) >= pCb->pcmBufEnd) { // this write will wrap // check OVR before wrap if ((pPcmBuf < pPcmBufRd) && ((pPcmBuf + pAfWrt->sampleCount) >= pPcmBufRd)) { pCb->errPcmOvrCnt++; pcmOvr = 1; } if (pcmOvr == 0) { // wrap pointer pPcmBuf = pCb->pcmBuf; // check OVR after wrap if ((pPcmBuf < pPcmBufRd) && ((pPcmBuf + pAfWrt->sampleCount) >= pPcmBufRd)) { pCb->errPcmOvrCnt++; pcmOvr = 1; } } } else if ((pPcmBuf < pPcmBufRd) && ((pPcmBuf + pAfWrt->sampleCount) >= pPcmBufRd)) { // this write won't wrap pCb->errPcmOvrCnt++; pcmOvr = 1; } else { // update pointer pPcmBuf += pAfWrt->sampleCount; } if (pcmOvr == 1) { Log_info2("cbWriteAf: ERROR: PCM CB overflow, sampleCount=%d, numPcmSampsPerCh=%d", pAfWrt->sampleCount, pCb->numPcmSampsPerCh); //SW_BREAKPOINT; // debug // 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_WRITE_OVERFLOW; } } // (***) FL: !!! REVISIT!!! // Allocating memory for max # channels (e.g. 32 for THD). // GROSS over allocation for THD 192 kHz, 6ch max. // configure AF sample pointers pPcmBuf = pPcmBufWrt; for (i = 0; i < pCb->maxAFChanNum; i++) { // check PCM buffer wrap if ((pPcmBuf + pAfWrt->sampleCount) >= pCb->pcmBufEnd) { pPcmBuf = pCb->pcmBuf; } pAfCb->data.sample[i] = pPcmBuf; pPcmBuf += pAfWrt->sampleCount; pAfCb->data.samsiz[i] = 0; } Cache_inv(pAfCb->data.sample, pCb->maxAFChanNum*sizeof(PAF_AudioData *), Cache_Type_ALLD, 0); // FL: this is write back and invalidate?? Cache_wait(); // FL: brute force reset of all metadata in CB AF? for (i=0; ipafPrivateMetadata[i].offset = 0; pAfCb->pafPrivateMetadata[i].size = 0; pAfCb->pafPrivateMetadata[i].pMdBuf = pMetaBuf; pMetaBuf += PAF_MAX_PRIVATE_MD_SZ; } #if 0 // FL: unused nextWrtIdx = 0; if ((pCb->afWrtIdx + 1) >= pCb->maxNumAfCb) { //Log_info0("cbWriteAf: AF Wrap around **** "); // next audio frame will be audio frame 0 nextWrtIdx = 0; } else { // next audio frame will be current audio frame + 1 nextWrtIdx = pCb->afWrtIdx + 1; } pAfCbNextAf = &pCb->afCb[nextWrtIdx]; // +1 or last AF if overflow pAfCbNextAf->data.sample[0] = &pAfCb->data.sample[pCb->maxAFChanNum - 1][pAfWrt->sampleCount]; // pAfCb->data.sample[15] + (pAfCb->sampleCount * sizeof(PAF_AudioData)); #endif // write audio frame information updated by decoder pAfCb->sampleDecode = pAfWrt->sampleDecode; PAF_PROCESS_COPY(pAfCb->sampleProcess, pAfWrt->sampleProcess); pAfCb->sampleRate = pAfWrt->sampleRate; pAfCb->sampleCount = pAfWrt->sampleCount; pAfCb->channelConfigurationRequest = pAfWrt->channelConfigurationRequest; pAfCb->channelConfigurationStream = pAfWrt->channelConfigurationStream; // write metadata information updated by decoder pAfCb->bsMetadata_type = pAfWrt->bsMetadata_type; /* non zero if metadata is attached. */ pAfCb->pafBsMetadataUpdate = pAfWrt->pafBsMetadataUpdate; /* indicates whether bit-stream metadata update */ pAfCb->numPrivateMetadata = pAfWrt->numPrivateMetadata; /* number of valid private metadata (0 or 1 if metadata filtering enabled) */ pAfCb->bsMetadata_offset = pAfWrt->bsMetadata_offset; /* offset into audio frame for change in bsMetadata_type field */ #ifdef DTS_BUILD pAfCb->mode = pAfWrt->mode; /* mode is used in DTSX to pass info to PARMA */ pAfCb->numChansUsedForMetadata = pAfWrt->numChansUsedForMetadata; /* if metadata is used in DTSX*/ pAfCb->pafBsFixedData = pAfWrt->pafBsFixedData; /* if true, do not convert float to fixed in DTSX metadata transfer */ pAfCb->root = pAfWrt->root; /* used for channel MASK in DTSX . BAD IDEA, need fix */ pAfCb->resetCount = pAfWrt->resetCount; /* used for communication between DTSX and PARMA */ #endif // write PCM samples streamMask = pAfWrt->fxns->channelMask(pAfWrt, pAfCb->channelConfigurationStream); 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 < pAfWrt->sampleCount; j++) { pAfCb->data.sample[i][j] = pAfWrt->data.sample[i][j]; } pAfCb->data.samsiz[i] = pAfWrt->data.samsiz[i]; } } // Update PCM samples per channel pCb->numPcmSampsPerCh += pAfWrt->sampleCount; #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] = pAfWrt->sampleCount; pCb->cb_op_owner[pCb->cb_opCnt] = CB_OP_W; // 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 // prepare metadata buffer pointers according to the metadata and buffer sizes for (i = 0; i < pAfWrt->numPrivateMetadata; i++) { UInt8 *nextMdBuf; if (i == 0) { nextMdBuf = (pAfCb->pafPrivateMetadata[0].pMdBuf + pAfWrt->pafPrivateMetadata[0].size); } else { nextMdBuf = (pAfCb->pafPrivateMetadata[i-1].pMdBuf + pAfWrt->pafPrivateMetadata[i-1].size); } if (nextMdBuf >= pCb->metaBufEnd) // metadata buffer overflow { pAfCb->pafPrivateMetadata[i].pMdBuf = pCb->metaBuf; } else if (i != 0) { pAfCb->pafPrivateMetadata[i].pMdBuf = nextMdBuf; } Cache_inv(pAfCb->pafPrivateMetadata[i].pMdBuf, sizeof(UInt8 *), Cache_Type_ALLD, 0); } // Write metadata to circular buffer for (i = 0; i < pAfWrt->numPrivateMetadata; i++) // only copy numPrivateMetadata { pAfCb->pafPrivateMetadata[i].offset = pAfWrt->pafPrivateMetadata[i].offset; pAfCb->pafPrivateMetadata[i].size = pAfWrt->pafPrivateMetadata[i].size; memcpy(pAfCb->pafPrivateMetadata[i].pMdBuf, pAfWrt->pafPrivateMetadata[i].pMdBuf, pAfWrt->pafPrivateMetadata[i].size); } Cache_inv(pAfCb->pafPrivateMetadata, pAfWrt->numPrivateMetadata*sizeof(PAF_PrivateMetadata *), Cache_Type_ALLD, 0); // FL: this is write back and invalidate?? Cache_wait(); for (i = 0; i < pAfCb->numPrivateMetadata; i++) // only write back numPrivateMetadata { //Log_info4("cbWriteAf: AF: %d nummd: %d offset: %d size: %d ", pCb->afWrtIdx, pAfCb->numPrivateMetadata, pAfCb->pafPrivateMetadata[i].offset, pAfCb->pafPrivateMetadata[i].size); Cache_wb(pAfCb->pafPrivateMetadata[i].pMdBuf, pAfCb->pafPrivateMetadata[i].size, Cache_Type_ALLD, 0); } // update audio frame write index pCb->afWrtIdx++; if (pCb->afWrtIdx >= pCb->maxNumAfCb) { pCb->afWrtIdx = 0; } pCb->afCb[pCb->afWrtIdx].data.sample[0] = &pAfCb->data.sample[pCb->maxAFChanNum - 1][pAfWrt->sampleCount]; if (pAfWrt->numPrivateMetadata > 0) { pCb->afCb[pCb->afWrtIdx].pafPrivateMetadata[0].pMdBuf = pAfCb->pafPrivateMetadata[pAfWrt->numPrivateMetadata - 1].pMdBuf + pAfWrt->pafPrivateMetadata[pAfWrt->numPrivateMetadata - 1].size; } else { pCb->afCb[pCb->afWrtIdx].pafPrivateMetadata[0].pMdBuf = pAfCb->pafPrivateMetadata[0].pMdBuf; Cache_wb(pCb->afCb , ASP_DECOP_CB_MAX_NUM_PCM_FRAMES*sizeof(PAF_AudioFrame *), Cache_Type_ALLD, 0); Cache_wait(); } Cache_inv(pCb->afCb[pCb->afWrtIdx].pafPrivateMetadata[0].pMdBuf, sizeof(UInt8 *), Cache_Type_ALLD, 0); Cache_wait(); // update number of audio frames in circular buffer pCb->numAfCb++; // Update CB Lag index //if (pCb->afLagIdx < pCb->afInitialLag) //{ // pCb->afLagIdx += 1; //} // Update CB primed flag // calculate number of delta samples before allowing CB read if (pCb->primedFlag == 0) { pCb->primedFlag = 1; // Calculate number of output frames to block reader. // This is sample count reader waits before allowed to actually read samples from the CB. //pCb->deltaSamps = (pCb->targetNDSamps - pAfWrt->sampleCount + (pCb->strFrameLen-1)) / pCb->strFrameLen * pCb->strFrameLen; // FL: CB read decrements by strFrameLen and tests for >0, so rounding to strFrameLen is unnecessary pCb->deltaSamps = pCb->targetNDSamps - pAfWrt->sampleCount; // debug //gSampleCountBuf[gPrimedFlagCnt] = pAfWrt->sampleCount; //gCalcDeltaSampsBuf[gPrimedFlagCnt] = pCb->deltaSamps; //if (gPrimedFlagCnt < 10) // gPrimedFlagCnt++; } // Write back circular buffer configuration Cache_wb(pCb, sizeof(PAF_AST_DecOpCircBuf), Cache_Type_ALLD, 0); // write back audio frame Cache_wb(pAfCb, sizeof(PAF_AudioFrame), Cache_Type_ALLD, 0); Cache_wb(pAfCb->data.samsiz, pCb->maxAFChanNum*sizeof(PAF_AudioSize), Cache_Type_ALLD, 0); Cache_wb(pAfCb->pafPrivateMetadata, pAfWrt->numPrivateMetadata*sizeof(PAF_PrivateMetadata *), Cache_Type_ALLD, 0); Cache_wait(); // write back PCM data 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_wb(pAfCb->data.sample[i], pAfWrt->sampleCount * sizeof(PAF_AudioData), Cache_Type_ALLD, 0); } } Cache_wait(); #if 0 // (***) FL: shows timing of CB write // debug { static Uint8 toggleState = 0; if (toggleState == 0) GPIOSetOutput(GPIO_PORT_0, GPIO_PIN_99); else GPIOClearOutput(GPIO_PORT_0, GPIO_PIN_99); toggleState = ~(toggleState); } #endif Log_info3("wrote %d samples into AF %d sourceSel: %d", pAfCb->sampleCount, pCb->afWrtIdx, pCb->sourceSel); Log_info4("CBWMETA num=%d size=%d offset=%d chrequest=0x%04x", pAfCb->numPrivateMetadata, pAfCb->pafPrivateMetadata[0].size, pAfCb->pafPrivateMetadata[0].offset, pAfCb->channelConfigurationRequest.full); } else { // // Skip write in case of 0 sample count // // writing audio frame w/ zero samples // update stat pCb->wrtAfZeroSampsCnt++; // Write back circular buffer configuration Cache_wb(pCb, sizeof(PAF_AST_DecOpCircBuf), Cache_Type_ALLD, 0); Cache_wait(); } //} //else if (pCb->readerActiveFlag == 0) if (pCb->readerActiveFlag == 0) { // // Reader inactive, don't write to circular buffer or check OVRflow. // // writing AF w/ inactive reader // update stat pCb->wrtAfReaderInactiveCnt++; // 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); //Log_info2("cbWriteAf:gate leave, gateHandle=0x%04x, key=%d", (IArg)gateHandle, (IArg)key); // debug return ASP_DECOP_CB_SOK; } #if 0 // Get next audio frame to write in circular buffer Int cbGetNextWriteAf( PAF_AST_DecOpCircBufCtl *pCbCtl, // decoder output circular buffer control Int8 cbIdx, // decoder output circular buffer index PAF_AudioFrame **ppAfWrt // audio frame next to be written ) { 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]); // get pointer to current audio frame in circular buffer *ppAfWrt = &pCb->afCb[pCb->afWrtIdx]; // update audio frame write index pCb->afWrtIdx++; if (pCb->afWrtIdx > pCb->maxNumAfCb) { pCb->afWrtIdx = 0; } // Leave the gate GateMP_leave(gateHandle, key); return ASP_DECOP_CB_SOK; } #endif // Init last audio frame configuration info static Void cbInitLastAfInfo( PAF_AST_DecOpCircBuf *pCb, // decoder output circular buffer control PAF_AudioFrame *pAfInit // audio frame used for init ) { memset(&pCb->lastAf, 0, sizeof(PAF_AudioFrame)); pCb->lastAf.sampleDecode = pAfInit->sampleDecode; pCb->lastAf.sampleRate = pAfInit->sampleRate; pCb->lastAf.channelConfigurationRequest.full = pAfInit->channelConfigurationRequest.full; pCb->lastAf.channelConfigurationStream.full = pAfInit->channelConfigurationStream.full; }