Clean up metadata handling in Dec Op circular buffer. Change initial delay (experiment).
[processor-sdk/performance-audio-sr.git] / processor_audio_sdk_1_00_00_00 / pasdk / common / paf_decOpCircBuf.c
2 /*
3 Copyright (c) 2016, Texas Instruments Incorporated - http://www.ti.com/
4 All rights reserved.
6 * Redistribution and use in source and binary forms, with or without 
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 *
13 * Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the
16 * distribution.
17 *
18 * Neither the name of Texas Instruments Incorporated nor the names of
19 * its contributors may be used to endorse or promote products derived
20 * from this software without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
25 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
26 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
27 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
28 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
29 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
30 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
32 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 *
34 */
36 #include <string.h> // for memset()
37 #include <xdc/std.h>
38 #include <ti/sysbios/hal/Cache.h>
39 #include <xdc/runtime/Log.h>
41 #include "common.h"
42 #include "pafdec.h"
43 #include "pafsp.h"
44 #include "paf_decOpCircBuf.h"
46 #define MAX_NUM_AF_PCM      ( 4 )
47 #define MAX_NUM_AF_DDP      ( 2 )
49 #define CB_INIT_RD_LAG      ( 4 )
51 // Initialize circular buffer
52 Int cbInit(
53     Int8 sourceSelect,          // source select (PCM, DDP, etc.)
54     Int16 decOpFrameLen,        // decoder output frame length (PCM samples)
55     Int16 strFrameLen,          // stream frame length (PCM samples)
56     PAF_DecodeOpCircBuf *pCb,   // decoder output circular buffer
57     Int8 resetRwFlags           // whether to reset reader, writer, and empty flags
58 )
59 {
60     PAF_AudioFrame *pAfCb;
61     PAF_AudioData *pPcmBuf;
62     Int8 *pMetaBuf; //QIN
63     Int8 n;
64     Int8 i;
66     // set input frame length
67     pCb->decOpFrameLen = decOpFrameLen;
68     
69     // set output frame length
70     pCb->strFrameLen = strFrameLen;
71     
72     // initialize circular buffer maximum number of audio frames
73     if (sourceSelect == PAF_SOURCE_PCM)
74     {
75         pCb->maxNumAfCb = MAX_NUM_AF_PCM;
76         pCb->afWrtIdx = CB_INIT_RD_LAG;
77         pCb->afRdIdx = 0;
78         pCb->pcmRdIdx = 0; // 2*256 in behind
79         
80         // initialize audio frames
81         for (n=0; n<pCb->maxNumAfCb; n++)
82         {
83             pAfCb = &pCb->afCb[n];
84             pAfCb->sampleDecode = PAF_SOURCE_PCM;
85             PAF_PROCESS_ZERO(pAfCb->sampleProcess);
86             pAfCb->sampleRate = PAF_SAMPLERATE_48000HZ;
87             pAfCb->sampleCount = decOpFrameLen;
88             pAfCb->channelConfigurationRequest.full = 0;
89             pAfCb->channelConfigurationRequest.part.sat = PAF_CC_SAT_SURROUND4;
90             pAfCb->channelConfigurationRequest.part.sub = PAF_CC_SUB_ONE;
91             pAfCb->channelConfigurationStream.full = 0;
92             pAfCb->channelConfigurationStream.part.sat = PAF_CC_SAT_SURROUND4;
93             pAfCb->channelConfigurationStream.part.sub = PAF_CC_SUB_ONE;
94         }
95     }
96     else if (sourceSelect == PAF_SOURCE_DDP)
97     {
98         pCb->maxNumAfCb = MAX_NUM_AF_DDP;
99         pCb->afRdIdx = 0;
100         pCb->pcmRdIdx = decOpFrameLen - CB_INIT_RD_LAG*strFrameLen;
101         pCb->afWrtIdx = 1;
102         
103         // initialize audio frames
104         for (n=0; n<pCb->maxNumAfCb; n++)
105         {
106             pAfCb = &pCb->afCb[n];
107             pAfCb->sampleDecode = PAF_SOURCE_DDP;
108             PAF_PROCESS_ZERO(pAfCb->sampleProcess);
109             pAfCb->sampleRate = PAF_SAMPLERATE_48000HZ;
110             pAfCb->sampleCount = decOpFrameLen;
111             pAfCb->channelConfigurationRequest.full = 0;
112             pAfCb->channelConfigurationRequest.part.sat = PAF_CC_SAT_SURROUND4;
113             pAfCb->channelConfigurationRequest.part.sub = PAF_CC_SUB_ONE;
114             pAfCb->channelConfigurationStream.full = 0;
115             pAfCb->channelConfigurationStream.part.sat = PAF_CC_SAT_SURROUND4;
116             pAfCb->channelConfigurationStream.part.sub = PAF_CC_SUB_ONE;
117         }
118     }
119     else
120     {
121         return PAF_DECOP_CB_INIT_INV_SOURCE_SEL;
122     }
124     // initialize circular buffer current number of frames
125     pCb->numAfCb = pCb->afWrtIdx - pCb->afRdIdx;
126     
127     // initialize audio frame PCM buffers
128     pPcmBuf = pCb->pcmBuf;
129     pMetaBuf = pCb->metaBuf; //QIN
130     for (n=0; n<pCb->maxNumAfCb; n++)
131     {
132         pAfCb = &pCb->afCb[n];
133         pAfCb->data.nChannels = PAF_DECOP_CB_MAX_NUM_PCM_CH;
134         pAfCb->data.nSamples = decOpFrameLen;
135         for (i=0; i<PAF_DECOP_CB_MAX_NUM_PCM_CH; i++)
136         {
137             pAfCb->data.sample[i] = pPcmBuf;
138             memset(pAfCb->data.sample[i], decOpFrameLen, 0);
139             pPcmBuf += decOpFrameLen;
140             
141             pAfCb->data.samsiz[i] = 0;
142         }
143         
144         // Initialize metadata buffers //QIN
145         for (i=0; i<PAF_MAX_NUM_PRIVATE_MD; i++)
146         {
147             pAfCb->pafPrivateMetadata[i].offset = 0; 
148             pAfCb->pafPrivateMetadata[i].size   = 0; 
149             pAfCb->pafPrivateMetadata[i].pMdBuf = pMetaBuf;
150             pMetaBuf += PAF_MAX_PRIVATE_MD_SZ;
151         }
152     }
153     
154     // reset read/write flags
155     if (resetRwFlags)
156     {
157         pCb->writerActiveFlag = 0;
158         pCb->readerActiveFlag = 0;
159         pCb->emptyFlag = 0;
160     }
161     // reset error counts
162     pCb->errUndCnt = 0;
163     pCb->errOvrCnt = 0;
164     
165     // (***) FL: revisit
166     // Write back circular buffer configuration
167     Cache_wb(pCb, sizeof(PAF_DecodeOpCircBuf), Cache_Type_ALLD, 0);
168     // Write back AF circular buffer
169     Cache_wb(pCb->afCb, pCb->maxNumAfCb*sizeof(PAF_AudioFrame), Cache_Type_ALLD, 0);
170     // Write back PCM data
171     for (n=0; n<pCb->maxNumAfCb; n++)
172     {
173         pAfCb = &pCb->afCb[n];
174         Cache_wb(pAfCb->data.samsiz, PAF_DECOP_CB_MAX_NUM_PCM_CH*sizeof(PAF_AudioSize), Cache_Type_ALLD, 0);
175         Cache_wb(pAfCb->data.sample, PAF_DECOP_CB_MAX_NUM_PCM_CH*sizeof(PAF_AudioData *), Cache_Type_ALLD, 0);
176         for (i=0; i<PAF_DECOP_CB_MAX_NUM_PCM_CH; i++)
177         {
178             Cache_wb(pAfCb->data.sample[i], decOpFrameLen*sizeof(PAF_AudioData), Cache_Type_ALLD, 0);
179         }
180         // FL: unnecessary since part of AF
181         //for (i=0; i<PAF_MAX_NUM_PRIVATE_MD; i++)     // Write back metadata //QIN
182         //{
183         //    Cache_wb(&pAfCb->pafPrivateMetadata[i], sizeof(PAF_PrivateMetadata), Cache_Type_ALLD, 0);
184         //}
185     }
186     Cache_wait();
188     return PAF_DECOP_CB_SOK;
191 // Start writes to circular buffer
192 Int cbWriteStart(
193     PAF_DecodeOpCircBuf *pCb    // decoder output circular buffer
196     PAF_AudioFrame *pAfCb;
197     Int8 n;
198     Int8 i;
200     // (***) FL: revisit
201     // Invalidate circular buffer configuration.
202     // NOTE: Probably only a subset of this information needs to be updated.
203     Cache_inv(pCb, sizeof(PAF_DecodeOpCircBuf), Cache_Type_ALLD, 0);
204     Cache_wait();
205     
206     // Invalidate AF circular buffer
207     Cache_inv(pCb->afCb, pCb->maxNumAfCb*sizeof(PAF_AudioFrame), Cache_Type_ALLD, 0);
208     for (n=0; n<pCb->maxNumAfCb; n++)
209     {
210         pAfCb = &pCb->afCb[n];
211         Cache_inv(pAfCb->data.sample, PAF_DECOP_CB_MAX_NUM_PCM_CH*sizeof(PAF_AudioData *), Cache_Type_ALLD, 0);
212         // FL: unnecessary since part of AF
213         //for (i=0; i<PAF_MAX_NUM_PRIVATE_MD; i++) //QIN
214         //{
215         //     Cache_inv(&pAfCb->pafPrivateMetadata[i], sizeof(PAF_PrivateMetadata), Cache_Type_ALLD, 0);
216         //}
217     }
218     Cache_wait();
219             
220     // update flags
221     pCb->writerActiveFlag = 1;
222     pCb->emptyFlag = 0;
223     
224     // (***) FL: revisit
225     // Write back circular buffer configuration
226     Cache_wb(pCb, sizeof(PAF_DecodeOpCircBuf), Cache_Type_ALLD, 0);
227     Cache_wait();
229     return PAF_DECOP_CB_SOK;
230 };
232 // Stop writes to circular buffer
233 Int cbWriteStop(
234     PAF_DecodeOpCircBuf *pCb    // decoder output circular buffer
237     // Invalidate circular buffer configuration
238     Cache_inv(pCb, sizeof(PAF_DecodeOpCircBuf), Cache_Type_ALLD, 0);
239     Cache_wait();
240     
241     // update flags
242     pCb->writerActiveFlag = 0;
243     pCb->emptyFlag = 1;
245     // (***) FL: revisit
246     // Write back circular buffer configuration
247     Cache_wb(pCb, sizeof(PAF_DecodeOpCircBuf), Cache_Type_ALLD, 0);
248     Cache_wait();
249     
250     return PAF_DECOP_CB_SOK;
253 // Start reads from circular buffer
254 Int cbReadStart(
255     PAF_DecodeOpCircBuf *pCb    // decoder output circular buffer
258     // Invalidate circular buffer configuration
259     Cache_inv(pCb, sizeof(PAF_DecodeOpCircBuf), Cache_Type_ALLD, 0);
260     Cache_wait();
261     
262     // update flags
263     pCb->readerActiveFlag = 1;
264     
265     // (***) FL: revisit
266     // Write back circular buffer configuration
267     Cache_wb(pCb, sizeof(PAF_DecodeOpCircBuf), Cache_Type_ALLD, 0);
268     Cache_wait();
270     return PAF_DECOP_CB_SOK;
273 // Stop reads from circular buffer
274 Int cbReadStop(
275     PAF_DecodeOpCircBuf *pCb    // decoder output circular buffer
278     // Invalidate circular buffer configuration
279     Cache_inv(pCb, sizeof(PAF_DecodeOpCircBuf), Cache_Type_ALLD, 0);
280     Cache_wait();
281     
282     // update flags
283     pCb->readerActiveFlag = 0;
284     
285     // (***) FL: revisit
286     // Write back circular buffer configuration
287     Cache_wb(pCb, sizeof(PAF_DecodeOpCircBuf), Cache_Type_ALLD, 0);
288     Cache_wait();
290     return PAF_DECOP_CB_SOK;
293 // Read audio frame from circular buffer
294 Int cbReadAf(
295     PAF_DecodeOpCircBuf *pCb,   // decoder output circular buffer
296     PAF_AudioFrame *pAfRd       // audio frame into which to read
299     PAF_AudioFrame *pAfCb;
300     PAF_ChannelMask_HD streamMask;
301     Int8 i;
302     Int16 j;
304     // (***) FL: revisit
305     // Invalidate circular buffer configuration.
306     Cache_inv(pCb, sizeof(PAF_DecodeOpCircBuf), Cache_Type_ALLD, 0);
307     Cache_wait();
309     if ((pCb->writerActiveFlag == 1) && (pCb->emptyFlag == 1))
310     {
311         // This shouldn't occur:
312         //  writer is active AND draining circular buffer
313         Log_info2("cbReadAf: ERROR: writerActiveFlag=%d, emptyFlag=%d", pCb->writerActiveFlag, pCb->emptyFlag);
314         SW_BREAKPOINT; // FL: debug
315         return PAF_DECOP_CB_READ_INVSTATE;
316     }
318     if ((pCb->writerActiveFlag == 0) && (pCb->emptyFlag == 0))
319     {
320         //
321         // No active writer, not draining circular buffer.
322         // Skip UNDerflow check, mute output.
323         //
324         pAfRd->sampleDecode = PAF_SOURCE_PCM;
325         PAF_PROCESS_ZERO(pAfRd->sampleProcess);
326         pAfRd->sampleRate = PAF_SAMPLERATE_48000HZ;
327         pAfRd->sampleCount = pCb->strFrameLen;
328         pAfRd->channelConfigurationRequest.full = 0;
329         pAfRd->channelConfigurationRequest.part.sat = PAF_CC_SAT_SURROUND4;
330         pAfRd->channelConfigurationRequest.part.sub = PAF_CC_SUB_ONE;
331         pAfRd->channelConfigurationStream.full = 0;
332         pAfRd->channelConfigurationStream.part.sat = PAF_CC_SAT_SURROUND4;
333         pAfRd->channelConfigurationStream.part.sub = PAF_CC_SUB_ONE;
334         
335         // compute stream mask
336         streamMask = pAfRd->fxns->channelMask(pAfRd, pAfRd->channelConfigurationStream);
337         // Clear PCM data
338         for (i = 0; i < PAF_DECOP_CB_MAX_NUM_PCM_CH; i++)
339         {
340             if ((streamMask >> i) & 0x1)
341             {
342                 memset(pAfRd->data.sample[i], pCb->strFrameLen, 0);
343             }
344             pAfRd->data.samsiz[i] = 0;
345         }
346         
347         return PAF_DECOP_CB_SOK;
348     }
349         
350     if ((pCb->writerActiveFlag == 1))
351     {
352         // check underflow
353         if (pCb->numAfCb <= 0)
354         {
355             pCb->errUndCnt++;
356             //SW_BREAKPOINT; // FL: debug
357             return PAF_DECOP_CB_READ_UNDERFLOW;
358         }
359     }
360     
361     if ((pCb->writerActiveFlag == 1) || (pCb->emptyFlag == 1))
362     {
363         //
364         // Writer active or draining remaining frames in circular buffer.
365         // Get next output audio frame.
366         //
367         
368         // get pointer to current audio frame in circular buffer
369         pAfCb = &pCb->afCb[pCb->afRdIdx];
371         // (***) FL: revisit
372         // Invalidate audio frame
373         Cache_inv(pAfCb, sizeof(PAF_AudioFrame), Cache_Type_ALLD, 0);
374         Cache_inv(pAfCb->data.samsiz, PAF_DECOP_CB_MAX_NUM_PCM_CH*sizeof(PAF_AudioSize), Cache_Type_ALLD, 0);
375         for (i=0; i<pAfCb->numPrivateMetadata; i++) //QIN // FL: only invalidate numPrivateMetadata
376         {
377             //Cache_inv(&pAfCb->pafPrivateMetadata[i], sizeof(PAF_PrivateMetadata), Cache_Type_ALLD, 0); // FL: unnecessary since part of AF
378             Cache_inv(pAfCb->pafPrivateMetadata[i].pMdBuf, pAfCb->pafPrivateMetadata[i].size, Cache_Type_ALLD, 0); // FL: only update metadata package size
379         }
380         Cache_wait();
382         // compute stream mask
383         streamMask = pAfRd->fxns->channelMask(pAfRd, pAfCb->channelConfigurationStream);
385         // Invalidate PCM data
386         for (i = 0; i < PAF_DECOP_CB_MAX_NUM_PCM_CH; i++)
387         {
388             if ((streamMask >> i) & 0x1)
389             {
390                 Cache_inv(&pAfCb->data.sample[i][pCb->pcmRdIdx], pCb->strFrameLen*sizeof(PAF_AudioData), Cache_Type_ALLD, 0);
391             }
392         }
393         Cache_wait();        
394         
395         // read audio frame information updated by decoder
396         pAfRd->sampleDecode = pAfCb->sampleDecode;
397         PAF_PROCESS_COPY(pAfRd->sampleProcess, pAfCb->sampleProcess);
398         pAfRd->sampleRate = pAfCb->sampleRate;
399         pAfRd->sampleCount = pCb->strFrameLen;
400         pAfRd->channelConfigurationRequest = pAfCb->channelConfigurationRequest;
401         pAfRd->channelConfigurationStream = pAfCb->channelConfigurationStream;
402         
403         // read metadata information updated by decoder //QIN
404         pAfRd->bsMetadata_type     = pAfCb->bsMetadata_type;        /* non zero if metadata is attached. */
405         pAfRd->pafBsMetadataUpdate = pAfCb->pafBsMetadataUpdate;    /* indicates whether bit-stream metadata update */
406         pAfRd->numPrivateMetadata  = pAfCb->numPrivateMetadata;     /* number of valid private metadata (0 or 1 if metadata filtering enabled) */
407         pAfRd->bsMetadata_offset   = pAfCb->bsMetadata_offset;      /* offset into audio frame for change in bsMetadata_type field */
408         
409         // read PCM samples
410         for (i = 0; i < PAF_DECOP_CB_MAX_NUM_PCM_CH; i++)
411         {
412             if ((streamMask >> i) & 0x1)
413             {
414                 for (j = 0; j < pCb->strFrameLen; j++)
415                 {
416                     pAfRd->data.sample[i][j] = pAfCb->data.sample[i][pCb->pcmRdIdx+j];
417                 }
419                 pAfRd->data.samsiz[i] = pAfCb->data.samsiz[i];
420             }
421         }
422         // read metadata //QIN
423         for (i = 0; i < pAfCb->numPrivateMetadata; i++) // FL: only read numPrivateMetadata
424         {
425             // FL: this is done above
426             ////Invalidate metadata data
427             //Cache_inv(&pAfCb->pafPrivateMetadata[i], sizeof(PAF_PrivateMetadata), Cache_Type_ALLD, 0);
428             //Cache_wait();        
429             
430             if ((pAfCb->pafPrivateMetadata[i].offset >= pCb->pcmRdIdx) 
431                  &&(pAfCb->pafPrivateMetadata[i].offset < (pCb->pcmRdIdx + pCb->strFrameLen))
432                  &&(pAfCb->pafPrivateMetadata[i].size))
433             {
434                 // FL: this is done above
435                 ////Invalidate metadata data
436                 //Cache_inv(pAfCb->pafPrivateMetadata[i].pMdBuf, pAfCb->pafPrivateMetadata[i].size, Cache_Type_ALLD, 0);
437                 //Cache_wait();        
438         
439                 // the offset is adjusted for segment [pCb->pcmRdIdx, (pCb->pcmRdIdx + pCb->pafFrameLen)]
440                 pAfRd->pafPrivateMetadata[i].offset = 0; //pAfCb->pafPrivateMetadata[i].offset - pCb->pcmRdIdx;
441                 pAfRd->pafPrivateMetadata[i].size   = pAfCb->pafPrivateMetadata[i].size;
442                 memcpy(pAfRd->pafPrivateMetadata[i].pMdBuf, pAfCb->pafPrivateMetadata[i].pMdBuf, pAfCb->pafPrivateMetadata[i].size);
443             }
444             else //reset un-used buf
445             {
446                 pAfRd->pafPrivateMetadata[i].offset = 0;
447                 pAfRd->pafPrivateMetadata[i].size   = 0;
448             }
449         }
450         
451         pCb->pcmRdIdx += pCb->strFrameLen; // update PCM read index
452         if (pCb->pcmRdIdx == pCb->decOpFrameLen)
453         {
454             // update audio frame read index
455             pCb->afRdIdx++;
456             if (pCb->afRdIdx >= pCb->maxNumAfCb)
457             {
458                 pCb->afRdIdx = 0;
459             }
460             
461             // update PCM read index
462             pCb->pcmRdIdx = 0;
463             
464             // update number of audio frames in circular buffer
465             pCb->numAfCb--;
466         }
467     }
468     
469     if (pCb->emptyFlag == 1)
470     {
471         //
472         // Writer inactive, but remaining frames in circular buffer.
473         // Update empty flag.
474         //
475         if (pCb->numAfCb <= 0)
476         {
477             pCb->emptyFlag = 0;
478         }
479     }
480     
481     // (***) FL: revisit
482     // Write back circular buffer configuration.
483     // NOTE: Probably only a subset of this information needs to be updated.
484     Cache_wb(pCb, sizeof(PAF_DecodeOpCircBuf), Cache_Type_ALLD, 0);
485     Cache_wait();    
486         
487     return PAF_DECOP_CB_SOK;
490 // Write audio frame to circular buffer
491 Int cbWriteAf(
492     PAF_DecodeOpCircBuf *pCb,   // decoder output circular buffer
493     PAF_AudioFrame *pAfWrt      // audio frame from which to write
496     PAF_AudioFrame *pAfCb;
497     PAF_ChannelMask_HD streamMask;
498     Int8 i;
499     Int16 j;
501     // (***) FL: revisit
502     // Invalidate circular buffer configuration.
503     // NOTE: Probably only a subset of this information nexeds to be updated.
504     Cache_inv(pCb, sizeof(PAF_DecodeOpCircBuf), Cache_Type_ALLD, 0);
505     Cache_wait();
506     
507     if (pCb->readerActiveFlag == 1)
508     {
509         //
510         // Normal case, reader active.
511         // If reader not active, don't write to circular buffer or check OVRflow.
513 #if 0        
514         if (pCb->cbWriteAfInit == 0)
515         {
516             // Invalidate AF circular buffer
517             Cache_inv(pCb->afCb, pCb->maxNumAfCb*sizeof(PAF_AudioFrame), Cache_Type_ALLD, 0);
518             for (n=0; n<pCb->maxNumAfCb; n++)
519             {
520                 pAfCb = &pCb->afCb[n];
521                 Cache_inv(pAfCb->data.sample, PAF_DECOP_CB_MAX_NUM_PCM_CH*sizeof(PAF_AudioData *), Cache_Type_ALLD, 0);
522             }
523             Cache_wait();
525             pCb->cbWriteAfInit = 1;
526         }
527 #endif        
529         // check overflow
530         if (pCb->numAfCb >= pCb->maxNumAfCb)
531         {
532             pCb->errOvrCnt++;
533             //SW_BREAKPOINT;
534             Log_info1("cbWriteAf: ERROR: overflow, numAfCb=%d", pCb->numAfCb);
535             return PAF_DECOP_CB_WRITE_OVERFLOW;
536         }
537         
538         // get pointer to current audio frame in circular buffer
539         pAfCb = &pCb->afCb[pCb->afWrtIdx];
540            
541         // write audio frame information updated by decoder
542         pAfCb->sampleDecode = pAfWrt->sampleDecode;
543         PAF_PROCESS_COPY(pAfCb->sampleProcess, pAfWrt->sampleProcess);
544         pAfCb->sampleRate = pAfWrt->sampleRate;
545         pAfCb->sampleCount = pAfWrt->sampleCount;
546         pAfCb->channelConfigurationRequest = pAfWrt->channelConfigurationRequest;
547         pAfCb->channelConfigurationStream = pAfWrt->channelConfigurationStream;
548         // write metadata information updated by decoder //QIN
549         pAfCb->bsMetadata_type     = pAfWrt->bsMetadata_type;        /* non zero if metadata is attached. */
550         pAfCb->pafBsMetadataUpdate = pAfWrt->pafBsMetadataUpdate;    /* indicates whether bit-stream metadata update */
551         pAfCb->numPrivateMetadata  = pAfWrt->numPrivateMetadata;     /* number of valid private metadata (0 or 1 if metadata filtering enabled) */
552         pAfCb->bsMetadata_offset   = pAfWrt->bsMetadata_offset;      /* offset into audio frame for change in bsMetadata_type field */
553         // write PCM samples
554         streamMask = pAfWrt->fxns->channelMask(pAfWrt, pAfCb->channelConfigurationStream);
555         for (i = 0; i < PAF_DECOP_CB_MAX_NUM_PCM_CH; i++)
556         {
557             if ((streamMask >> i) & 0x1)
558             {
559                 for (j = 0; j < pCb->decOpFrameLen; j++)
560                 {
561                     pAfCb->data.sample[i][j] = pAfWrt->data.sample[i][j];
562                 }            
563                 
564                 pAfCb->data.samsiz[i] = pAfWrt->data.samsiz[i];
565             }
566         }
567         
568         // Write metadata to circular buffer
569         for (i = 0; i < pAfCb->numPrivateMetadata; i++) // FL: only copy numPrivateMetadata
570         {
571             pAfCb->pafPrivateMetadata[i].offset = pAfWrt->pafPrivateMetadata[i].offset; 
572             pAfCb->pafPrivateMetadata[i].size   = pAfWrt->pafPrivateMetadata[i].size; 
573             memcpy(pAfCb->pafPrivateMetadata[i].pMdBuf, pAfWrt->pafPrivateMetadata[i].pMdBuf, pAfWrt->pafPrivateMetadata[i].size); 
574         }
575         
576         // update audio frame write index
577         pCb->afWrtIdx++;
578         if (pCb->afWrtIdx >= pCb->maxNumAfCb)
579         {
580             pCb->afWrtIdx = 0;
581         }
582         
583         // update number of audio frames in circular buffer
584         pCb->numAfCb++;
586         // (***) FL: revisit
587         // Write back circular buffer configuration
588         Cache_wb(pCb, sizeof(PAF_DecodeOpCircBuf), Cache_Type_ALLD, 0);
589         // write back audio frame
590         Cache_wb(pAfCb, sizeof(PAF_AudioFrame), Cache_Type_ALLD, 0);
591         Cache_wb(pAfCb->data.samsiz, PAF_DECOP_CB_MAX_NUM_PCM_CH*sizeof(PAF_AudioSize), Cache_Type_ALLD, 0);
592         // write back PCM data
593         for (i = 0; i < PAF_DECOP_CB_MAX_NUM_PCM_CH; i++)
594         {
595             if ((streamMask >> i) & 0x1)
596             {
597                 Cache_wb(pAfCb->data.sample[i], pCb->decOpFrameLen*sizeof(PAF_AudioData), Cache_Type_ALLD, 0);
598             }
599         }
600         
601         // write back private metadata // QIN
602         for (i=0; i<pAfCb->numPrivateMetadata; i++) // FL: only write back numPrivateMetadata
603         {
604             //Cache_wb(&pAfCb->pafPrivateMetadata[i], sizeof(PAF_PrivateMetadata), Cache_Type_ALLD, 0); // FL: unnecessary since part of AF
605             Cache_wb(pAfCb->pafPrivateMetadata[i].pMdBuf, pAfCb->pafPrivateMetadata[i].size, Cache_Type_ALLD, 0);
606         }
607         Cache_wait();
608     }  
609     
610     return PAF_DECOP_CB_SOK;
613 // Get next audio frame to write in circular buffer
614 Int cbGetNextWriteAf(
615     PAF_DecodeOpCircBuf *pCb, // decoder output circular buffer
616     PAF_AudioFrame **ppAfWrt  // audio frame next to be written
619     // get pointer to current audio frame in circular buffer
620     *ppAfWrt = &pCb->afCb[pCb->afWrtIdx];
621     
622     // update audio frame write index
623     pCb->afWrtIdx++;
624     if (pCb->afWrtIdx > pCb->maxNumAfCb)
625     {
626         pCb->afWrtIdx = 0;
627     }    
628     
629     return PAF_DECOP_CB_SOK;
632 // Output log of circular buffer control variables (debug)
633 Int cbLog(
634     PAF_DecodeOpCircBuf *pCb,
635     Int8 fullLog, 
636     char *locInfo
639     Log_info1("CB: %s", (IArg)locInfo);
640     Log_info3("CB: readerActiveFlag=%d, writerActiveFlag=%d, emptyFlag=%d", pCb->readerActiveFlag, pCb->writerActiveFlag, pCb->emptyFlag);
641     Log_info4("CB: afRdIdx=%d, pcmRdIdx=%d, afWrtIdx=%d, numAfCb=%d", pCb->afRdIdx, pCb->pcmRdIdx, 
642         pCb->afWrtIdx, 
643         pCb->numAfCb);
644     if (fullLog)
645     {
646         Log_info1("CB: maxNumAfCb=%d", pCb->maxNumAfCb);  
647         Log_info2("CB: decOpFrameLen=%d, strFrameLen=%d", pCb->decOpFrameLen, pCb->strFrameLen);
648         //Log_info1("cbWriteInit=%d", pCb->cbWriteAfInit);
649     }
650     
651     return 0;