Fix setup guide
[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 "pafdec.h"
42 #include "pafsp.h"
43 #include "paf_decOpCircBuf.h"
45 #define MAX_NUM_AF_PCM      ( 4 )
46 #define MAX_NUM_AF_DDP      ( 2 )
48 #define CB_INIT_RD_LAG      ( 2 )
50 // Initialize circular buffer
51 Int cbInit(
52     Int8 sourceSelect,          // source select (PCM, DDP, etc.)
53     Int16 decOpFrameLen,        // decoder output frame length (PCM samples)
54     Int16 strFrameLen,          // stream frame length (PCM samples)
55     PAF_DecodeOpCircBuf *pCb    // decoder output circular buffer
56 )
57 {
58     PAF_AudioFrame *pAfCb;
59     PAF_AudioData *pPcmBuf;
60     Int8 *pMetaBuf; //QIN
61     Int8 n;
62     Int8 i;
64     // set input frame length
65     pCb->decOpFrameLen = decOpFrameLen;
66     
67     // set output frame length
68     pCb->strFrameLen = strFrameLen;
69     
70     // initialize circular buffer maximum number of audio frames
71     if (sourceSelect == PAF_SOURCE_PCM)
72     {
73         pCb->maxNumAfCb = MAX_NUM_AF_PCM;
74         pCb->afWrtIdx = CB_INIT_RD_LAG;
75         pCb->afRdIdx = 0;
76         pCb->pcmRdIdx = 0; // 2*256 in behind
77         
78         // initialize audio frames
79         for (n=0; n<pCb->maxNumAfCb; n++)
80         {
81             pAfCb = &pCb->afCb[n];
82             pAfCb->sampleDecode = PAF_SOURCE_PCM;
83             PAF_PROCESS_ZERO(pAfCb->sampleProcess);
84             pAfCb->sampleRate = PAF_SAMPLERATE_48000HZ;
85             pAfCb->sampleCount = decOpFrameLen;
86             pAfCb->channelConfigurationRequest.full = 0;
87             pAfCb->channelConfigurationRequest.part.sat = PAF_CC_SAT_SURROUND4;
88             pAfCb->channelConfigurationRequest.part.sub = PAF_CC_SUB_ONE;
89             pAfCb->channelConfigurationStream.full = 0;
90             pAfCb->channelConfigurationStream.part.sat = PAF_CC_SAT_SURROUND4;
91             pAfCb->channelConfigurationStream.part.sub = PAF_CC_SUB_ONE;
92         }
93     }
94     else if (sourceSelect == PAF_SOURCE_DDP)
95     {
96         pCb->maxNumAfCb = MAX_NUM_AF_DDP;
97         pCb->afRdIdx = 0;
98         pCb->afWrtIdx = 0;//1;//QIN - Reduce delay to prevent cb overflow. Need further investigation.
99         pCb->pcmRdIdx = 0;//decOpFrameLen - CB_INIT_RD_LAG*strFrameLen; //QIN - Reduce delay to prevent cb overflow. Need further investigation.
100         
101         // initialize audio frames
102         for (n=0; n<pCb->maxNumAfCb; n++)
103         {
104             pAfCb = &pCb->afCb[n];
105             pAfCb->sampleDecode = PAF_SOURCE_DDP;
106             PAF_PROCESS_ZERO(pAfCb->sampleProcess);
107             pAfCb->sampleRate = PAF_SAMPLERATE_48000HZ;
108             pAfCb->sampleCount = decOpFrameLen;
109             pAfCb->channelConfigurationRequest.full = 0;
110             pAfCb->channelConfigurationRequest.part.sat = PAF_CC_SAT_SURROUND4;
111             pAfCb->channelConfigurationRequest.part.sub = PAF_CC_SUB_ONE;
112             pAfCb->channelConfigurationStream.full = 0;
113             pAfCb->channelConfigurationStream.part.sat = PAF_CC_SAT_SURROUND4;
114             pAfCb->channelConfigurationStream.part.sub = PAF_CC_SUB_ONE;
115         }
116     }
117     else
118     {
119         return PAF_DECOP_CB_INIT_INV_SOURCE_SEL;
120     }
122     // initialize circular buffer current number of frames
123     pCb->numAfCb = pCb->afWrtIdx - pCb->afRdIdx;
124     
125     // initialize audio frame PCM buffers
126     pPcmBuf = pCb->pcmBuf;
127     pMetaBuf = pCb->metaBuf; //QIN
128     for (n=0; n<pCb->maxNumAfCb; n++)
129     {
130         pAfCb = &pCb->afCb[n];
131         pAfCb->data.nChannels = PAF_DECOP_CB_MAX_NUM_PCM_CH;
132         pAfCb->data.nSamples = decOpFrameLen;
133         for (i=0; i<PAF_DECOP_CB_MAX_NUM_PCM_CH; i++)
134         {
135             pAfCb->data.sample[i] = pPcmBuf;
136             memset(pAfCb->data.sample[i], decOpFrameLen, 0);
137             pPcmBuf += decOpFrameLen;
138             
139             pAfCb->data.samsiz[i] = 0;
140         }
141         //Initialize metadata buffers //QIN
142         for (i=0; i<PAF_MAX_NUM_PRIVATE_MD; i++)
143         {
144             pAfCb->pafPrivateMetadata[i].offset = 0; 
145             pAfCb->pafPrivateMetadata[i].size   = 0; 
146             pAfCb->pafPrivateMetadata[i].pMdBuf = pMetaBuf;
147             pMetaBuf += PAF_MAX_PRIVATE_MD_SZ;
148         }
149     }
150     // update flags
151     pCb->writerActiveFlag = 0;
152     pCb->readerActiveFlag = 0;
153     pCb->emptyFlag = 0;
154     //pCb->cbWriteAfInit = 0;
155     
156     // (***) FL: revisit
157     // Write back circular buffer configuration
158     Cache_wb(pCb, sizeof(PAF_DecodeOpCircBuf), Cache_Type_ALLD, 0);
159     // Write back AF circular buffer
160     Cache_wb(pCb->afCb, pCb->maxNumAfCb*sizeof(PAF_AudioFrame), Cache_Type_ALLD, 0);
161     // Write back PCM data
162     for (n=0; n<pCb->maxNumAfCb; n++)
163     {
164         pAfCb = &pCb->afCb[n];
165         Cache_wb(pAfCb->data.samsiz, PAF_DECOP_CB_MAX_NUM_PCM_CH*sizeof(PAF_AudioSize), Cache_Type_ALLD, 0);
166         Cache_wb(pAfCb->data.sample, PAF_DECOP_CB_MAX_NUM_PCM_CH*sizeof(PAF_AudioData *), Cache_Type_ALLD, 0);
167         for (i=0; i<PAF_DECOP_CB_MAX_NUM_PCM_CH; i++)
168         {
169             Cache_wb(pAfCb->data.sample[i], decOpFrameLen*sizeof(PAF_AudioData), Cache_Type_ALLD, 0);
170         }
171         for (i=0; i<PAF_MAX_NUM_PRIVATE_MD; i++)     // Write back metadata //QIN
172         {
173             Cache_wb(&pAfCb->pafPrivateMetadata[i], sizeof(PAF_PrivateMetadata), Cache_Type_ALLD, 0);
174         }
175     }
176     Cache_wait();
178     return PAF_DECOP_CB_SOK;
181 // Start writes to circular buffer
182 Int cbWriteStart(
183     PAF_DecodeOpCircBuf *pCb    // decoder output circular buffer
186     PAF_AudioFrame *pAfCb;
187     Int8 n;
188     Int8 i;
190     // (***) FL: revisit
191     // Invalidate circular buffer configuration.
192     // NOTE: Probably only a subset of this information needs to be updated.
193     Cache_inv(pCb, sizeof(PAF_DecodeOpCircBuf), Cache_Type_ALLD, 0);
194     Cache_wait();
195     
196     // Invalidate AF circular buffer
197     Cache_inv(pCb->afCb, pCb->maxNumAfCb*sizeof(PAF_AudioFrame), Cache_Type_ALLD, 0);
198     for (n=0; n<pCb->maxNumAfCb; n++)
199     {
200         pAfCb = &pCb->afCb[n];
201         Cache_inv(pAfCb->data.sample, PAF_DECOP_CB_MAX_NUM_PCM_CH*sizeof(PAF_AudioData *), Cache_Type_ALLD, 0);
202         for (i=0; i<PAF_MAX_NUM_PRIVATE_MD; i++) //QIN
203         {
204              Cache_inv(&pAfCb->pafPrivateMetadata[i], sizeof(PAF_PrivateMetadata), Cache_Type_ALLD, 0);
205         }
206     }
207     Cache_wait();
208             
209     // update flags
210     pCb->writerActiveFlag = 1;
211     pCb->emptyFlag = 0;
212     
213     // (***) FL: revisit
214     // Write back circular buffer configuration
215     Cache_wb(pCb, sizeof(PAF_DecodeOpCircBuf), Cache_Type_ALLD, 0);
217     return PAF_DECOP_CB_SOK;
218 };
220 // Stop writes to circular buffer
221 Int cbWriteStop(
222     PAF_DecodeOpCircBuf *pCb    // decoder output circular buffer
225     // update flags
226     pCb->writerActiveFlag = 0;
227     pCb->emptyFlag = 1;
229     // (***) FL: revisit
230     // Write back circular buffer configuration
231     Cache_wb(pCb, sizeof(PAF_DecodeOpCircBuf), Cache_Type_ALLD, 0);
232     
233     return PAF_DECOP_CB_SOK;
236 // Start reads from circular buffer
237 Int cbReadStart(
238     PAF_DecodeOpCircBuf *pCb    // decoder output circular buffer
241     // update flags
242     pCb->readerActiveFlag = 1;
243     
244     // (***) FL: revisit
245     // Write back circular buffer configuration
246     Cache_wb(pCb, sizeof(PAF_DecodeOpCircBuf), Cache_Type_ALLD, 0);
248     return PAF_DECOP_CB_SOK;
251 // Stop reads from circular buffer
252 Int cbReadStop(
253     PAF_DecodeOpCircBuf *pCb    // decoder output circular buffer
256     // update flags
257     pCb->readerActiveFlag = 0;
258     
259     // (***) FL: revisit
260     // Write back circular buffer configuration
261     Cache_wb(pCb, sizeof(PAF_DecodeOpCircBuf), Cache_Type_ALLD, 0);
263     return PAF_DECOP_CB_SOK;
265 // restore read/write flags of the circular buffer. - QIN
266 Int cbReadWriteRestore(
267     PAF_DecodeOpCircBuf *pCb    // decoder output circular buffer
270     // Invalidate circular buffer configuration.
271     Cache_inv(pCb, sizeof(PAF_DecodeOpCircBuf), Cache_Type_ALLD, 0);
272     Cache_wait();
274     // update flags
275     pCb->readerActiveFlag = 1;
276     pCb->writerActiveFlag = 1;
277     
278     // (***) FL: revisit
279     // Write back circular buffer configuration
280     Cache_wb(pCb, sizeof(PAF_DecodeOpCircBuf), Cache_Type_ALLD, 0);
282     return PAF_DECOP_CB_SOK;
285 // Read audio frame from circular buffer
286 Int cbReadAf(
287     PAF_DecodeOpCircBuf *pCb,   // decoder output circular buffer
288     PAF_AudioFrame *pAfRd       // audio frame into which to read
291     PAF_AudioFrame *pAfCb;
292     PAF_ChannelMask_HD streamMask;
293     Int8 i;
294     Int16 j;
296     // (***) FL: revisit
297     // Invalidate circular buffer configuration.
298     Cache_inv(pCb, sizeof(PAF_DecodeOpCircBuf), Cache_Type_ALLD, 0);
299     Cache_wait();
301     if ((pCb->writerActiveFlag == 1) && (pCb->emptyFlag == 1))
302     {
303         // This shouldn't occur:
304         //  writer is active AND draining circular buffer
305         Log_info2("cbReadAf: ERROR: writerActiveFlag=%d, emptyFlag=%d", pCb->writerActiveFlag, pCb->emptyFlag);
306         return PAF_DECOP_CB_READ_INVSTATE;
307     }
309     if ((pCb->writerActiveFlag == 0) && (pCb->emptyFlag == 0))
310     {
311         //
312         // No active writer, not draining circular buffer.
313         // Skip UNDerflow check, mute output.
314         //
315         
316         pAfRd->sampleDecode = PAF_SOURCE_PCM;
317         PAF_PROCESS_ZERO(pAfRd->sampleProcess);
318         pAfRd->sampleRate = PAF_SAMPLERATE_48000HZ;
319         pAfRd->sampleCount = pCb->strFrameLen;
320         pAfRd->channelConfigurationRequest.full = 0;
321         pAfRd->channelConfigurationRequest.part.sat = PAF_CC_SAT_SURROUND4;
322         pAfRd->channelConfigurationRequest.part.sub = PAF_CC_SUB_ONE;
323         pAfRd->channelConfigurationStream.full = 0;
324         pAfRd->channelConfigurationStream.part.sat = PAF_CC_SAT_SURROUND4;
325         pAfRd->channelConfigurationStream.part.sub = PAF_CC_SUB_ONE;
326         
327         // compute stream mask
328         streamMask = pAfRd->fxns->channelMask(pAfRd, pAfRd->channelConfigurationStream);
329         // Clear PCM data
330         for (i = 0; i < PAF_DECOP_CB_MAX_NUM_PCM_CH; i++)
331         {
332             if ((streamMask >> i) & 0x1)
333             {
334                 memset(pAfRd->data.sample[i], pCb->strFrameLen, 0);
335             }
336             pAfRd->data.samsiz[i] = 0;
337         }
338         
339         return PAF_DECOP_CB_SOK;
340     }
341         
342     if ((pCb->writerActiveFlag == 1))
343     {
344         // check underflow
345         if (pCb->numAfCb <= 0)
346         {
347             return PAF_DECOP_CB_READ_UNDERFLOW;
348         }
349     }
350     
351     if ((pCb->writerActiveFlag == 1) || (pCb->emptyFlag == 1))
352     {
353         //
354         // Writer active or draining remaining frames in circular buffer.
355         // Get next output audio frame.
356         //
357         
358         // get pointer to current audio frame in circular buffer
359         pAfCb = &pCb->afCb[pCb->afRdIdx];
361         // (***) FL: revisit
362         // Invalidate audio frame
363         Cache_inv(pAfCb, sizeof(PAF_AudioFrame), Cache_Type_ALLD, 0);
364         Cache_inv(pAfCb->data.samsiz, PAF_DECOP_CB_MAX_NUM_PCM_CH*sizeof(PAF_AudioSize), Cache_Type_ALLD, 0);
365         for (i=0; i<PAF_MAX_NUM_PRIVATE_MD; i++) //QIN
366         {
367             Cache_inv(&pAfCb->pafPrivateMetadata[i], sizeof(PAF_PrivateMetadata), Cache_Type_ALLD, 0);
368             Cache_inv(pAfCb->pafPrivateMetadata[i].pMdBuf, PAF_MAX_PRIVATE_MD_SZ*sizeof(Int8), Cache_Type_ALLD, 0);
369         }
370         Cache_wait();
372         // compute stream mask
373         streamMask = pAfRd->fxns->channelMask(pAfRd, pAfCb->channelConfigurationStream);
375         // Invalidate PCM data
376         for (i = 0; i < PAF_DECOP_CB_MAX_NUM_PCM_CH; i++)
377         {
378             if ((streamMask >> i) & 0x1)
379             {
380                 Cache_inv(&pAfCb->data.sample[i][pCb->pcmRdIdx], pCb->strFrameLen*sizeof(PAF_AudioData), Cache_Type_ALLD, 0);
381             }
382         }
383         Cache_wait();        
384         
385         // read audio frame information updated by decoder
386         pAfRd->sampleDecode = pAfCb->sampleDecode;
387         PAF_PROCESS_COPY(pAfRd->sampleProcess, pAfCb->sampleProcess);
388         pAfRd->sampleRate = pAfCb->sampleRate;
389         pAfRd->sampleCount = pCb->strFrameLen;
390         pAfRd->channelConfigurationRequest = pAfCb->channelConfigurationRequest;
391         pAfRd->channelConfigurationStream = pAfCb->channelConfigurationStream;
392         
393         // read metadata information updated by decoder //QIN
394         pAfRd->bsMetadata_type     = pAfCb->bsMetadata_type;        /* non zero if metadata is attached. */
395         pAfRd->pafBsMetadataUpdate = pAfCb->pafBsMetadataUpdate;    /* indicates whether bit-stream metadata update */
396         pAfRd->numPrivateMetadata  = pAfCb->numPrivateMetadata;     /* number of valid private metadata (0 or 1 if metadata filtering enabled) */
397         pAfRd->bsMetadata_offset   = pAfCb->bsMetadata_offset;      /* offset into audio frame for change in bsMetadata_type field */
398         
399         // read PCM samples
400         for (i = 0; i < PAF_DECOP_CB_MAX_NUM_PCM_CH; i++)
401         {
402             if ((streamMask >> i) & 0x1)
403             {
404                 for (j = 0; j < pCb->strFrameLen; j++)
405                 {
406                     pAfRd->data.sample[i][j] = pAfCb->data.sample[i][pCb->pcmRdIdx+j];
407                 }
409                 pAfRd->data.samsiz[i] = pAfCb->data.samsiz[i];
410             }
411         }
412         // read metadata //QIN
413         for (i = 0; i < PAF_MAX_NUM_PRIVATE_MD; i++)
414         {
415             //Invalidate metadata data
416               Cache_inv(&pAfCb->pafPrivateMetadata[i], sizeof(PAF_PrivateMetadata), Cache_Type_ALLD, 0);
417             Cache_wait();        
418             if ((pAfCb->pafPrivateMetadata[i].offset >= pCb->pcmRdIdx) 
419                  &&(pAfCb->pafPrivateMetadata[i].offset < (pCb->pcmRdIdx + pCb->strFrameLen))
420                  &&(pAfCb->pafPrivateMetadata[i].size))
421             {
422                 //Invalidate metadata data
423                 Cache_inv(pAfCb->pafPrivateMetadata[i].pMdBuf, pAfCb->pafPrivateMetadata[i].size, Cache_Type_ALLD, 0);
424                 Cache_wait();        
426                 // the offset is adjusted for segment [pCb->pcmRdIdx, (pCb->pcmRdIdx + pCb->pafFrameLen)]
427                 pAfRd->pafPrivateMetadata[i].offset = 0;//pAfCb->pafPrivateMetadata[i].offset - pCb->pcmRdIdx;
428                 pAfRd->pafPrivateMetadata[i].size   = pAfCb->pafPrivateMetadata[i].size;
429                 memcpy (pAfRd->pafPrivateMetadata[i].pMdBuf, pAfCb->pafPrivateMetadata[i].pMdBuf, pAfCb->pafPrivateMetadata[i].size);
430             }
431             else //reset un-used buf
432             {
433                 pAfRd->pafPrivateMetadata[i].offset = 0;
434                 pAfRd->pafPrivateMetadata[i].size   = 0;
435             }
436         }
437         pCb->pcmRdIdx += pCb->strFrameLen; // update PCM read index
438         if (pCb->pcmRdIdx == pCb->decOpFrameLen)
439         {
440             // update audio frame read index
441             pCb->afRdIdx++;
442             if (pCb->afRdIdx >= pCb->maxNumAfCb)
443             {
444                 pCb->afRdIdx = 0;
445             }
446             
447             // update PCM read index
448             pCb->pcmRdIdx = 0;
449             
450             // update number of audio frames in circular buffer
451             pCb->numAfCb--;
452         }
453     }
454     
455     if (pCb->emptyFlag == 1)
456     {
457         //
458         // Writer inactive, but remaining frames in circular buffer.
459         // Update empty flag.
460         //
461         if (pCb->numAfCb <= 0)
462         {
463             pCb->emptyFlag = 0;
464         }
465     }
466     
467     // (***) FL: revisit
468     // Write back circular buffer configuration.
469     // NOTE: Probably only a subset of this information needs to be updated.
470     Cache_wb(pCb, sizeof(PAF_DecodeOpCircBuf), Cache_Type_ALLD, 0);
471     Cache_wait();    
472         
473     return PAF_DECOP_CB_SOK;
476 // Write audio frame to circular buffer
477 Int cbWriteAf(
478     PAF_DecodeOpCircBuf *pCb,   // decoder output circular buffer
479     PAF_AudioFrame *pAfWrt      // audio frame from which to write
482     PAF_AudioFrame *pAfCb;
483     PAF_ChannelMask_HD streamMask;
484     Int8 i;
485     Int16 j;
487     // (***) FL: revisit
488     // Invalidate circular buffer configuration.
489     // NOTE: Probably only a subset of this information needs to be updated.
490     Cache_inv(pCb, sizeof(PAF_DecodeOpCircBuf), Cache_Type_ALLD, 0);
491     Cache_wait();
492     
493     if (pCb->readerActiveFlag == 1)
494     {
495         //
496         // Normal case, reader active.
497         // If reader not active, don't write to circular buffer or check OVRflow.
499 #if 0        
500         if (pCb->cbWriteAfInit == 0)
501         {
502             // Invalidate AF circular buffer
503             Cache_inv(pCb->afCb, pCb->maxNumAfCb*sizeof(PAF_AudioFrame), Cache_Type_ALLD, 0);
504             for (n=0; n<pCb->maxNumAfCb; n++)
505             {
506                 pAfCb = &pCb->afCb[n];
507                 Cache_inv(pAfCb->data.sample, PAF_DECOP_CB_MAX_NUM_PCM_CH*sizeof(PAF_AudioData *), Cache_Type_ALLD, 0);
508             }
509             Cache_wait();
511             pCb->cbWriteAfInit = 1;
512         }
513 #endif        
516         // check overflow
517         //if (pCb->numAfCb >= pCb->maxNumAfCb)
518         //{
519         //    return PAF_DECOP_CB_WRITE_OVERFLOW;
520         //}
521         while (pCb->numAfCb >= pCb->maxNumAfCb); //Qin replace with while loop for debugging
522         // get pointer to current audio frame in circular buffer
523         pAfCb = &pCb->afCb[pCb->afWrtIdx];
524            
525         // write audio frame information updated by decoder
526         pAfCb->sampleDecode = pAfWrt->sampleDecode;
527         PAF_PROCESS_COPY(pAfCb->sampleProcess, pAfWrt->sampleProcess);
528         pAfCb->sampleRate = pAfWrt->sampleRate;
529         pAfCb->sampleCount = pAfWrt->sampleCount;
530         pAfCb->channelConfigurationRequest = pAfWrt->channelConfigurationRequest;
531         pAfCb->channelConfigurationStream = pAfWrt->channelConfigurationStream;
532         // write metadata information updated by decoder//QIN
533         pAfCb->bsMetadata_type     = pAfWrt->bsMetadata_type;        /* non zero if metadata is attached. */
534         pAfCb->pafBsMetadataUpdate = pAfWrt->pafBsMetadataUpdate;    /* indicates whether bit-stream metadata update */
535         pAfCb->numPrivateMetadata  = pAfWrt->numPrivateMetadata;     /* number of valid private metadata (0 or 1 if metadata filtering enabled) */
536         pAfCb->bsMetadata_offset   = pAfWrt->bsMetadata_offset;      /* offset into audio frame for change in bsMetadata_type field */
537         // write PCM samples
538         streamMask = pAfWrt->fxns->channelMask(pAfWrt, pAfCb->channelConfigurationStream);
539         for (i = 0; i < PAF_DECOP_CB_MAX_NUM_PCM_CH; i++)
540         {
541             if ((streamMask >> i) & 0x1)
542             {
543                 for (j = 0; j < pCb->decOpFrameLen; j++)
544                 {
545                     pAfCb->data.sample[i][j] = pAfWrt->data.sample[i][j];
546                 }            
547                 
548                 pAfCb->data.samsiz[i] = pAfWrt->data.samsiz[i];
549             }
550         }
551         
552         //Write metadata to circular buffer //QIN
553         for (i = 0; i < PAF_MAX_NUM_PRIVATE_MD; i++)
554         {
555             if (pAfWrt->pafPrivateMetadata[i].size )
556             {
557                 pAfCb->pafPrivateMetadata[i].offset = pAfWrt->pafPrivateMetadata[i].offset; 
558                 pAfCb->pafPrivateMetadata[i].size   = pAfWrt->pafPrivateMetadata[i].size; 
559                 memcpy (pAfCb->pafPrivateMetadata[i].pMdBuf, pAfWrt->pafPrivateMetadata[i].pMdBuf, pAfWrt->pafPrivateMetadata[i].size); 
560             }
561             else 
562             {
563                 pAfCb->pafPrivateMetadata[i].offset = 0; 
564                 pAfCb->pafPrivateMetadata[i].size   = 0; 
565             }
566         }
567         // update audio frame write index
568         pCb->afWrtIdx++;
569         if (pCb->afWrtIdx >= pCb->maxNumAfCb)
570         {
571             pCb->afWrtIdx = 0;
572         }
573         
574         // update number of audio frames in circular buffer
575         pCb->numAfCb++;
577         // (***) FL: revisit
578         // Write back circular buffer configuration
579         Cache_wb(pCb, sizeof(PAF_DecodeOpCircBuf), Cache_Type_ALLD, 0);
580         // write back audio frame
581         Cache_wb(pAfCb, sizeof(PAF_AudioFrame), Cache_Type_ALLD, 0);
582         Cache_wb(pAfCb->data.samsiz, PAF_DECOP_CB_MAX_NUM_PCM_CH*sizeof(PAF_AudioSize), Cache_Type_ALLD, 0);
583         // write back PCM data
584         for (i = 0; i < PAF_DECOP_CB_MAX_NUM_PCM_CH; i++)
585         {
586             if ((streamMask >> i) & 0x1)
587             {
588                 Cache_wb(pAfCb->data.sample[i], pCb->decOpFrameLen*sizeof(PAF_AudioData), Cache_Type_ALLD, 0);
589             }
590         }
592         for (i=0; i<PAF_MAX_NUM_PRIVATE_MD; i++) //QIN
593         {
594             Cache_wb(&pAfCb->pafPrivateMetadata[i], sizeof(PAF_PrivateMetadata), Cache_Type_ALLD, 0);
595             Cache_wb(pAfCb->pafPrivateMetadata[i].pMdBuf, PAF_MAX_PRIVATE_MD_SZ*sizeof(Int8), Cache_Type_ALLD, 0);
596         }
597         Cache_wait();
598     }  
599     
600     return PAF_DECOP_CB_SOK;
603 // Get next audio frame to write in circular buffer
604 Int cbGetNextWriteAf(
605     PAF_DecodeOpCircBuf *pCb, // decoder output circular buffer
606     PAF_AudioFrame **ppAfWrt  // audio frame next to be written
609     // get pointer to current audio frame in circular buffer
610     *ppAfWrt = &pCb->afCb[pCb->afWrtIdx];
611     
612     // update audio frame write index
613     pCb->afWrtIdx++;
614     if (pCb->afWrtIdx > pCb->maxNumAfCb)
615     {
616         pCb->afWrtIdx = 0;
617     }    
618     
619     return PAF_DECOP_CB_SOK;
622 // Output log of circular buffer control variables (debug)
623 Int cbLog(
624     PAF_DecodeOpCircBuf *pCb,
625     Int8 fullLog
628     Log_info4("afRdIdx=%d, pcmRdIdx=%d, afWrtIdx=%d, numAfCb=%d", pCb->afRdIdx, pCb->pcmRdIdx, 
629         pCb->afWrtIdx, 
630         pCb->numAfCb);
631     if (fullLog)
632     {
633         Log_info1("maxNumAfCb=%d", pCb->maxNumAfCb);  
634         Log_info2("decOpFrameLen=%d, strFrameLen=%d", pCb->decOpFrameLen, pCb->strFrameLen);
635         //Log_info1("cbWriteInit=%d", pCb->cbWriteAfInit);
636     }
637     
638     return 0;