/* 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 "common.h" #include "paftyp.h" //#include "pafdec.h" //#include "pafsp.h" #include "aspDecOpCircBuf_slave.h" // Start writes to circular buffer Int cbWriteStart( PAF_AST_DecOpCircBuf *pCb // decoder output circular buffer ) { PAF_AudioFrame *pAfCb; Int8 n; //Int8 i; // (***) 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(); // 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(); return ASP_DECOP_CB_SOK; }; // Stop writes to circular buffer Int cbWriteStop( PAF_AST_DecOpCircBuf *pCb // decoder output circular buffer ) { // Invalidate circular buffer configuration Cache_inv(pCb, sizeof(PAF_AST_DecOpCircBuf), Cache_Type_ALLD, 0); Cache_wait(); // 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(); return ASP_DECOP_CB_SOK; } // Write audio frame to circular buffer Int cbWriteAf( PAF_AST_DecOpCircBuf *pCb, // decoder output circular buffer PAF_AudioFrame *pAfWrt // audio frame from which to write ) { PAF_AudioFrame *pAfCb; PAF_ChannelMask_HD streamMask; Int8 i; Int16 j; // (***) 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(); 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 // check overflow if (pCb->numAfCb >= pCb->maxNumAfCb) { pCb->errOvrCnt++; //SW_BREAKPOINT; Log_info1("cbWriteAf: ERROR: overflow, numAfCb=%d", pCb->numAfCb); return ASP_DECOP_CB_WRITE_OVERFLOW; } // get pointer to current audio frame in circular buffer pAfCb = &pCb->afCb[pCb->afWrtIdx]; // 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); 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]; } } // 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 pCb->afWrtIdx++; if (pCb->afWrtIdx >= pCb->maxNumAfCb) { pCb->afWrtIdx = 0; } // update number of audio frames in circular buffer pCb->numAfCb++; // (***) 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(); } return ASP_DECOP_CB_SOK; } // Get next audio frame to write in circular buffer Int cbGetNextWriteAf( PAF_AST_DecOpCircBuf *pCb, // decoder output circular buffer PAF_AudioFrame **ppAfWrt // audio frame next to be written ) { // 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; } return ASP_DECOP_CB_SOK; }