/* Copyright (c) 2016, 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" // 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->pXDecOpCb = pXDecOpCb; return ASP_DECOP_CB_SOK; } // 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; // Get gate handle gateHandle = pCbCtl->gateHandle; // Enter gate key = GateMP_enter(gateHandle); // Get circular buffer base pointer pCb = &((*pCbCtl->pXDecOpCb)[cbIdx]); // (***) FL: revisit // 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); // FL: 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, ASP_DECOP_CB_MAX_NUM_PCM_CH*sizeof(PAF_AudioData *), Cache_Type_ALLD, 0); // FL: unnecessary since part of AF //for (i=0; ipafPrivateMetadata[i], sizeof(PAF_PrivateMetadata), Cache_Type_ALLD, 0); //} } Cache_wait(); // update flags pCb->writerActiveFlag = 1; pCb->emptyFlag = 0; // (***) FL: revisit // 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); // FL: debug // update flags pCb->writerActiveFlag = 0; pCb->emptyFlag = 1; // (***) FL: revisit // 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; } // 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; // 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); // FL: debug // Get circular buffer base pointer pCb = &((*pCbCtl->pXDecOpCb)[cbIdx]); //Log_info1("cbWriteAf:pCb=0x%04x", (IArg)pCb); // FL: debug // (***) FL: revisit // Invalidate circular buffer configuration. // NOTE: Probably only a subset of this information nexeds 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); // FL: debug //Log_info2("cbWriteAf:pCb->readerActiveFlag=%d, pCb->writerActiveFlag=%d", (IArg)pCb->readerActiveFlag, (IArg)pCb->writerActiveFlag); // FL: debug if (pCb->readerActiveFlag == 1) { // // Normal case, reader active. // If reader not active, don't write to circular buffer or check OVRflow. #if 0 if (pCb->cbWriteAfInit == 0) { // 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, ASP_DECOP_CB_MAX_NUM_PCM_CH*sizeof(PAF_AudioData *), Cache_Type_ALLD, 0); } Cache_wait(); pCb->cbWriteAfInit = 1; } #endif //Log_info2("cbWriteAf:pCb->numAfCb=%d, pCb->maxNumAfCb=%d", (IArg)pCb->readerActiveFlag, (IArg)pCb->maxNumAfCb); // FL: debug // check overflow if (pCb->numAfCb >= pCb->maxNumAfCb) { pCb->errOvrCnt++; //SW_BREAKPOINT; Log_info1("cbWriteAf: ERROR: overflow, numAfCb=%d", pCb->numAfCb); // Write back circular buffer configuration Cache_wb(pCb, sizeof(PAF_AST_DecOpCircBuf), Cache_Type_ALLD, 0); // Leave the gate GateMP_leave(gateHandle, key); //Log_info2("cbWriteAf:gate leave, gateHandle=0x%04x, key=%d", (IArg)gateHandle, (IArg)key); // FL: debug return ASP_DECOP_CB_WRITE_OVERFLOW; } // get pointer to current audio frame in circular buffer //Log_info2("cbWriteAf:afCb=0x%04x, pCb->afWrtIdx=%d", (IArg)pCb->afCb, (IArg)pCb->afWrtIdx); // FL: debug pAfCb = &pCb->afCb[pCb->afWrtIdx]; //Log_info1("cbWriteAf:pAfCb=0x%04x", (IArg)pAfCb); // FL: debug // 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 //QIN 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 */ // write PCM samples streamMask = pAfWrt->fxns->channelMask(pAfWrt, pAfCb->channelConfigurationStream); //Log_info1("cbWriteAf:streamMask=0x%04x", (IArg)streamMask); // FL: debug //Log_info1("cbWriteAf:pCb->decOpFrameLen=%d", (IArg)pCb->decOpFrameLen); // FL: debug //Log_info2("cbWriteAf:pAfCb->data.sample=0x%04x, pAfWrt->data.sample=0x%04x", (IArg)pAfCb->data.sample, (IArg)pAfWrt->data.sample); // FL: debug //Log_info2("cbWriteAf:pAfCb->data.samsiz=0x%04x, pAfWrt->data.samsiz=0x%04x", (IArg)pAfCb->data.samsiz, (IArg)pAfWrt->data.samsiz); // FL: debug for (i = 0; i < ASP_DECOP_CB_MAX_NUM_PCM_CH; i++) { if ((streamMask >> i) & 0x1) { for (j = 0; j < pCb->decOpFrameLen; j++) { pAfCb->data.sample[i][j] = pAfWrt->data.sample[i][j]; } pAfCb->data.samsiz[i] = pAfWrt->data.samsiz[i]; } } //Log_info1("cbWriteAf:pAfCb->numPrivateMetadata=%d", (IArg)pAfCb->numPrivateMetadata); // FL: debug // Write metadata to circular buffer for (i = 0; i < pAfCb->numPrivateMetadata; i++) // FL: 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); } // update audio frame write index //Log_info2("cbWriteAf:pCb->afWrtIdx=%d, pCb->maxNumAfCb", (IArg)pCb->afWrtIdx, (IArg)pCb->maxNumAfCb); // FL: debug pCb->afWrtIdx++; if (pCb->afWrtIdx >= pCb->maxNumAfCb) { pCb->afWrtIdx = 0; } //Log_info2("cbWriteAf:pCb->afWrtIdx=%d, pCb->maxNumAfCb", (IArg)pCb->afWrtIdx, (IArg)pCb->maxNumAfCb); // FL: debug // update number of audio frames in circular buffer //Log_info1("cbWriteAf:pCb->numAfCb=%d", (IArg)pCb->numAfCb); // FL: debug pCb->numAfCb++; //Log_info1("cbWriteAf:pCb->numAfCb=%d", (IArg)pCb->numAfCb); // FL: debug // (***) FL: revisit // 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, ASP_DECOP_CB_MAX_NUM_PCM_CH*sizeof(PAF_AudioSize), Cache_Type_ALLD, 0); // write back PCM data for (i = 0; i < ASP_DECOP_CB_MAX_NUM_PCM_CH; i++) { if ((streamMask >> i) & 0x1) { Cache_wb(pAfCb->data.sample[i], pCb->decOpFrameLen*sizeof(PAF_AudioData), Cache_Type_ALLD, 0); } } // write back private metadata // QIN for (i=0; inumPrivateMetadata; i++) // FL: only write back numPrivateMetadata { //Cache_wb(&pAfCb->pafPrivateMetadata[i], sizeof(PAF_PrivateMetadata), Cache_Type_ALLD, 0); // FL: unnecessary since part of AF Cache_wb(pAfCb->pafPrivateMetadata[i].pMdBuf, pAfCb->pafPrivateMetadata[i].size, 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); // FL: debug return ASP_DECOP_CB_SOK; } // 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; }