]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - processor-sdk/performance-audio-sr.git/blob - processor_audio_sdk_1_00_00_00/pasdk/common/paf_decOpCircBuf.c
Change metadata buffer pointers types to match audio frame (remove ARM compiler warning)
[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 // Generate mute AF on circular buffer read
47 static Void cbReadAfMute(
48     PAF_AudioFrame *pAfRd,      // audio frame into which to read
49     Int16 strFrameLen           // stream frame length (output transaction size)
50 );
52 #define MAX_NUM_AF_PCM      ( 4 )
53 #define CB_INIT_RD_LAG_PCM  ( 2 ) // 0...3
55 #define MAX_NUM_AF_DDP      ( 2 )
56 #define CB_INIT_RD_LAG_DDP  ( 4 ) // 0...5
58 // Initialize circular buffer
59 Int cbInit(
60     Int8 sourceSelect,          // source select (PCM, DDP, etc.)
61     Int16 decOpFrameLen,        // decoder output frame length (PCM samples)
62     Int16 strFrameLen,          // stream frame length (PCM samples)
63     PAF_AST_DecOpCircBuf *pCb,  // decoder output circular buffer
64     Int8 resetRwFlags           // whether to reset reader, writer, and empty flags
65 )
66 {
67     PAF_AudioFrame *pAfCb;
68     PAF_AudioData *pPcmBuf;
69     UInt8 *pMetaBuf; //QIN
70     Int8 n;
71     Int8 i;
73     // set input frame length
74     pCb->decOpFrameLen = decOpFrameLen;
75     
76     // set output frame length
77     pCb->strFrameLen = strFrameLen;
78     
79     // initialize circular buffer maximum number of audio frames
80     if (sourceSelect == PAF_SOURCE_PCM)
81     {
82         pCb->maxNumAfCb = MAX_NUM_AF_PCM;
83         pCb->afWrtIdx = CB_INIT_RD_LAG_PCM;
84         pCb->afRdIdx = 0;
85         pCb->pcmRdIdx = 0; // 2*256 in behind
86         
87         // initialize audio frames
88         for (n=0; n<pCb->maxNumAfCb; n++)
89         {
90             pAfCb = &pCb->afCb[n];
91             pAfCb->sampleDecode = PAF_SOURCE_PCM;
92             PAF_PROCESS_ZERO(pAfCb->sampleProcess);
93             pAfCb->sampleRate = PAF_SAMPLERATE_48000HZ;
94             pAfCb->sampleCount = decOpFrameLen;
95             pAfCb->channelConfigurationRequest.full = 0;
96             pAfCb->channelConfigurationRequest.part.sat = PAF_CC_SAT_SURROUND4;
97             pAfCb->channelConfigurationRequest.part.sub = PAF_CC_SUB_ONE;
98             pAfCb->channelConfigurationStream.full = 0;
99             pAfCb->channelConfigurationStream.part.sat = PAF_CC_SAT_SURROUND4;
100             pAfCb->channelConfigurationStream.part.sub = PAF_CC_SUB_ONE;
101         }
102     }
103     else if (sourceSelect == PAF_SOURCE_DDP)
104     {
105         pCb->maxNumAfCb = MAX_NUM_AF_DDP;
106         pCb->afWrtIdx = 1;
107         pCb->afRdIdx = 0;
108         pCb->pcmRdIdx = decOpFrameLen - CB_INIT_RD_LAG_DDP*strFrameLen; // 4*256 behind
109         
110         // initialize audio frames
111         for (n=0; n<pCb->maxNumAfCb; n++)
112         {
113             pAfCb = &pCb->afCb[n];
114             pAfCb->sampleDecode = PAF_SOURCE_DDP;
115             PAF_PROCESS_ZERO(pAfCb->sampleProcess);
116             pAfCb->sampleRate = PAF_SAMPLERATE_48000HZ;
117             pAfCb->sampleCount = decOpFrameLen;
118             pAfCb->channelConfigurationRequest.full = 0;
119             pAfCb->channelConfigurationRequest.part.sat = PAF_CC_SAT_SURROUND4;
120             pAfCb->channelConfigurationRequest.part.sub = PAF_CC_SUB_ONE;
121             pAfCb->channelConfigurationStream.full = 0;
122             pAfCb->channelConfigurationStream.part.sat = PAF_CC_SAT_SURROUND4;
123             pAfCb->channelConfigurationStream.part.sub = PAF_CC_SUB_ONE;
124         }
125     }
126     else
127     {
128         return PAF_DECOP_CB_INIT_INV_SOURCE_SEL;
129     }
131     // initialize circular buffer current number of frames
132     pCb->numAfCb = pCb->afWrtIdx - pCb->afRdIdx;
133     
134     // initialize audio frame PCM buffers
135     pPcmBuf = pCb->pcmBuf;
136     pMetaBuf = pCb->metaBuf; //QIN
137     for (n=0; n<pCb->maxNumAfCb; n++)
138     {
139         pAfCb = &pCb->afCb[n];
140         pAfCb->data.nChannels = PAF_DECOP_CB_MAX_NUM_PCM_CH;
141         pAfCb->data.nSamples = decOpFrameLen;
142         for (i=0; i<PAF_DECOP_CB_MAX_NUM_PCM_CH; i++)
143         {
144             pAfCb->data.sample[i] = pPcmBuf;
145             memset(pAfCb->data.sample[i], decOpFrameLen, 0);
146             pPcmBuf += decOpFrameLen;
147             
148             pAfCb->data.samsiz[i] = 0;
149         }
150         
151         // Initialize metadata buffers //QIN
152         for (i=0; i<PAF_MAX_NUM_PRIVATE_MD; i++)
153         {
154             pAfCb->pafPrivateMetadata[i].offset = 0; 
155             pAfCb->pafPrivateMetadata[i].size   = 0; 
156             pAfCb->pafPrivateMetadata[i].pMdBuf = pMetaBuf;
157             pMetaBuf += PAF_MAX_PRIVATE_MD_SZ;
158         }
159     }
160     
161     // reset read/write flags
162     if (resetRwFlags)
163     {
164         pCb->writerActiveFlag = 0;
165         pCb->readerActiveFlag = 0;
166         pCb->emptyFlag = 0;
167     }
168     // reset error counts
169     pCb->errUndCnt = 0;
170     pCb->errOvrCnt = 0;
171     
172     // (***) FL: revisit
173     // Write back circular buffer configuration
174     Cache_wb(pCb, sizeof(PAF_AST_DecOpCircBuf), Cache_Type_ALLD, 0);
175     // Write back AF circular buffer
176     Cache_wb(pCb->afCb, pCb->maxNumAfCb*sizeof(PAF_AudioFrame), Cache_Type_ALLD, 0);
177     // Write back PCM data
178     for (n=0; n<pCb->maxNumAfCb; n++)
179     {
180         pAfCb = &pCb->afCb[n];
181         Cache_wb(pAfCb->data.samsiz, PAF_DECOP_CB_MAX_NUM_PCM_CH*sizeof(PAF_AudioSize), Cache_Type_ALLD, 0);
182         Cache_wb(pAfCb->data.sample, PAF_DECOP_CB_MAX_NUM_PCM_CH*sizeof(PAF_AudioData *), Cache_Type_ALLD, 0);
183         for (i=0; i<PAF_DECOP_CB_MAX_NUM_PCM_CH; i++)
184         {
185             Cache_wb(pAfCb->data.sample[i], decOpFrameLen*sizeof(PAF_AudioData), Cache_Type_ALLD, 0);
186         }
187         // FL: unnecessary since part of AF
188         //for (i=0; i<PAF_MAX_NUM_PRIVATE_MD; i++)     // Write back metadata //QIN
189         //{
190         //    Cache_wb(&pAfCb->pafPrivateMetadata[i], sizeof(PAF_PrivateMetadata), Cache_Type_ALLD, 0);
191         //}
192     }
193     Cache_wait();
195     return PAF_DECOP_CB_SOK;
198 // Start writes to circular buffer
199 Int cbWriteStart(
200     PAF_AST_DecOpCircBuf *pCb   // decoder output circular buffer
203     PAF_AudioFrame *pAfCb;
204     Int8 n;
205     //Int8 i;
207     // (***) FL: revisit
208     // Invalidate circular buffer configuration.
209     // NOTE: Probably only a subset of this information needs to be updated.
210     Cache_inv(pCb, sizeof(PAF_AST_DecOpCircBuf), Cache_Type_ALLD, 0);
211     Cache_wait();
212     
213     // Invalidate AF circular buffer
214     Cache_inv(pCb->afCb, pCb->maxNumAfCb*sizeof(PAF_AudioFrame), Cache_Type_ALLD, 0);
215     for (n=0; n<pCb->maxNumAfCb; n++)
216     {
217         pAfCb = &pCb->afCb[n];
218         Cache_inv(pAfCb->data.sample, PAF_DECOP_CB_MAX_NUM_PCM_CH*sizeof(PAF_AudioData *), Cache_Type_ALLD, 0);
219         // FL: unnecessary since part of AF
220         //for (i=0; i<PAF_MAX_NUM_PRIVATE_MD; i++) //QIN
221         //{
222         //     Cache_inv(&pAfCb->pafPrivateMetadata[i], sizeof(PAF_PrivateMetadata), Cache_Type_ALLD, 0);
223         //}
224     }
225     Cache_wait();
226             
227     // update flags
228     pCb->writerActiveFlag = 1;
229     pCb->emptyFlag = 0;
230     
231     // (***) FL: revisit
232     // Write back circular buffer configuration
233     Cache_wb(pCb, sizeof(PAF_AST_DecOpCircBuf), Cache_Type_ALLD, 0);
234     Cache_wait();
236     return PAF_DECOP_CB_SOK;
237 };
239 // Stop writes to circular buffer
240 Int cbWriteStop(
241     PAF_AST_DecOpCircBuf *pCb   // decoder output circular buffer
244     // Invalidate circular buffer configuration
245     Cache_inv(pCb, sizeof(PAF_AST_DecOpCircBuf), Cache_Type_ALLD, 0);
246     Cache_wait();
247     
248     // update flags
249     pCb->writerActiveFlag = 0;
250     pCb->emptyFlag = 1;
252     // (***) FL: revisit
253     // Write back circular buffer configuration
254     Cache_wb(pCb, sizeof(PAF_AST_DecOpCircBuf), Cache_Type_ALLD, 0);
255     Cache_wait();
256     
257     return PAF_DECOP_CB_SOK;
260 // Start reads from circular buffer
261 Int cbReadStart(
262     PAF_AST_DecOpCircBuf *pCb   // decoder output circular buffer
265     // Invalidate circular buffer configuration
266     Cache_inv(pCb, sizeof(PAF_AST_DecOpCircBuf), Cache_Type_ALLD, 0);
267     Cache_wait();
268     
269     // update flags
270     pCb->readerActiveFlag = 1;
271     
272     // (***) FL: revisit
273     // Write back circular buffer configuration
274     Cache_wb(pCb, sizeof(PAF_AST_DecOpCircBuf), Cache_Type_ALLD, 0);
275     Cache_wait();
277     return PAF_DECOP_CB_SOK;
280 // Stop reads from circular buffer
281 Int cbReadStop(
282     PAF_AST_DecOpCircBuf *pCb   // decoder output circular buffer
285     // Invalidate circular buffer configuration
286     Cache_inv(pCb, sizeof(PAF_AST_DecOpCircBuf), Cache_Type_ALLD, 0);
287     Cache_wait();
288     
289     // update flags
290     pCb->readerActiveFlag = 0;
291     
292     // (***) FL: revisit
293     // Write back circular buffer configuration
294     Cache_wb(pCb, sizeof(PAF_AST_DecOpCircBuf), Cache_Type_ALLD, 0);
295     Cache_wait();
297     return PAF_DECOP_CB_SOK;
300 // Read audio frame from circular buffer
301 Int cbReadAf(
302     PAF_AST_DecOpCircBuf *pCb,  // decoder output circular buffer
303     PAF_AudioFrame *pAfRd       // audio frame into which to read
306     PAF_AudioFrame *pAfCb;
307     PAF_ChannelMask_HD streamMask;
308     Int8 i;
309     Int16 j;
311     // (***) FL: revisit
312     // Invalidate circular buffer configuration.
313     Cache_inv(pCb, sizeof(PAF_AST_DecOpCircBuf), Cache_Type_ALLD, 0);
314     Cache_wait();
316     if ((pCb->writerActiveFlag == 1) && (pCb->emptyFlag == 1))
317     {
318         // This shouldn't occur:
319         //  writer is active AND draining circular buffer
320         Log_info2("cbReadAf: ERROR: writerActiveFlag=%d, emptyFlag=%d", pCb->writerActiveFlag, pCb->emptyFlag);
321         SW_BREAKPOINT; // FL: debug
322         return PAF_DECOP_CB_READ_INVSTATE;
323     }
325     if ((pCb->writerActiveFlag == 0) && (pCb->emptyFlag == 0))
326     {
327         //
328         // No active writer, not draining circular buffer.
329         // Skip UNDerflow check, mute output.
330         //
331         cbReadAfMute(pAfRd, pCb->strFrameLen);
332         
333         return PAF_DECOP_CB_SOK;
334     }
335         
336     if ((pCb->writerActiveFlag == 1))
337     {
338         // check underflow
339         if (pCb->numAfCb <= 0)
340         {
341             // 
342             // Increment underflow count.
343             // Mute output on underflow.
344             //
345             pCb->errUndCnt++;
346             cbReadAfMute(pAfRd, pCb->strFrameLen);
347             //SW_BREAKPOINT; // FL: debug
348             
349             // Write back circular buffer configuration.
350             Cache_wb(pCb, sizeof(PAF_AST_DecOpCircBuf), Cache_Type_ALLD, 0);
351             Cache_wait();    
352             
353             return PAF_DECOP_CB_READ_UNDERFLOW;
354         }
355     }
356     
357     if ((pCb->writerActiveFlag == 1) || (pCb->emptyFlag == 1))
358     {
359         //
360         // Writer active or draining remaining frames in circular buffer.
361         // Get next output audio frame.
362         //
363         
364         // get pointer to current audio frame in circular buffer
365         pAfCb = &pCb->afCb[pCb->afRdIdx];
367         // (***) FL: revisit
368         // Invalidate audio frame
369         Cache_inv(pAfCb, sizeof(PAF_AudioFrame), Cache_Type_ALLD, 0);
370         Cache_inv(pAfCb->data.samsiz, PAF_DECOP_CB_MAX_NUM_PCM_CH*sizeof(PAF_AudioSize), Cache_Type_ALLD, 0);
371         for (i=0; i<pAfCb->numPrivateMetadata; i++) //QIN // FL: only invalidate numPrivateMetadata
372         {
373             //Cache_inv(&pAfCb->pafPrivateMetadata[i], sizeof(PAF_PrivateMetadata), Cache_Type_ALLD, 0); // FL: unnecessary since part of AF
374             Cache_inv(pAfCb->pafPrivateMetadata[i].pMdBuf, pAfCb->pafPrivateMetadata[i].size, Cache_Type_ALLD, 0); // FL: only update metadata package size
375         }
376         Cache_wait();
378         // compute stream mask
379         streamMask = pAfRd->fxns->channelMask(pAfRd, pAfCb->channelConfigurationStream);
381         // Invalidate PCM data
382         for (i = 0; i < PAF_DECOP_CB_MAX_NUM_PCM_CH; i++)
383         {
384             if ((streamMask >> i) & 0x1)
385             {
386                 Cache_inv(&pAfCb->data.sample[i][pCb->pcmRdIdx], pCb->strFrameLen*sizeof(PAF_AudioData), Cache_Type_ALLD, 0);
387             }
388         }
389         Cache_wait();        
390         
391         // read audio frame information updated by decoder
392         pAfRd->sampleDecode = pAfCb->sampleDecode;
393         PAF_PROCESS_COPY(pAfRd->sampleProcess, pAfCb->sampleProcess);
394         pAfRd->sampleRate = pAfCb->sampleRate;
395         pAfRd->sampleCount = pCb->strFrameLen;
396         pAfRd->channelConfigurationRequest = pAfCb->channelConfigurationRequest;
397         pAfRd->channelConfigurationStream = pAfCb->channelConfigurationStream;
398         
399         // read metadata information updated by decoder //QIN
400         pAfRd->bsMetadata_type     = pAfCb->bsMetadata_type;        /* non zero if metadata is attached. */
401         pAfRd->pafBsMetadataUpdate = pAfCb->pafBsMetadataUpdate;    /* indicates whether bit-stream metadata update */
402         pAfRd->numPrivateMetadata  = pAfCb->numPrivateMetadata;     /* number of valid private metadata (0 or 1 if metadata filtering enabled) */
403         pAfRd->bsMetadata_offset   = pAfCb->bsMetadata_offset;      /* offset into audio frame for change in bsMetadata_type field */
404         
405         // read PCM samples
406         for (i = 0; i < PAF_DECOP_CB_MAX_NUM_PCM_CH; i++)
407         {
408             if ((streamMask >> i) & 0x1)
409             {
410                 for (j = 0; j < pCb->strFrameLen; j++)
411                 {
412                     pAfRd->data.sample[i][j] = pAfCb->data.sample[i][pCb->pcmRdIdx+j];
413                 }
415                 pAfRd->data.samsiz[i] = pAfCb->data.samsiz[i];
416             }
417         }
418         // read metadata //QIN
419         for (i = 0; i < pAfCb->numPrivateMetadata; i++) // FL: only read numPrivateMetadata
420         {
421             // FL: this is done above
422             ////Invalidate metadata data
423             //Cache_inv(&pAfCb->pafPrivateMetadata[i], sizeof(PAF_PrivateMetadata), Cache_Type_ALLD, 0);
424             //Cache_wait();        
425             
426             if ((pAfCb->pafPrivateMetadata[i].offset >= pCb->pcmRdIdx) 
427                  &&(pAfCb->pafPrivateMetadata[i].offset < (pCb->pcmRdIdx + pCb->strFrameLen))
428                  &&(pAfCb->pafPrivateMetadata[i].size))
429             {
430                 // FL: this is done above
431                 ////Invalidate metadata data
432                 //Cache_inv(pAfCb->pafPrivateMetadata[i].pMdBuf, pAfCb->pafPrivateMetadata[i].size, Cache_Type_ALLD, 0);
433                 //Cache_wait();        
434         
435                 // the offset is adjusted for segment [pCb->pcmRdIdx, (pCb->pcmRdIdx + pCb->pafFrameLen)]
436                 pAfRd->pafPrivateMetadata[i].offset = 0; //pAfCb->pafPrivateMetadata[i].offset - pCb->pcmRdIdx;
437                 pAfRd->pafPrivateMetadata[i].size   = pAfCb->pafPrivateMetadata[i].size;
438                 memcpy(pAfRd->pafPrivateMetadata[i].pMdBuf, pAfCb->pafPrivateMetadata[i].pMdBuf, pAfCb->pafPrivateMetadata[i].size);
439             }
440             else //reset un-used buf
441             {
442                 pAfRd->pafPrivateMetadata[i].offset = 0;
443                 pAfRd->pafPrivateMetadata[i].size   = 0;
444             }
445         }
446         
447         pCb->pcmRdIdx += pCb->strFrameLen; // update PCM read index
448         if (pCb->pcmRdIdx == pCb->decOpFrameLen)
449         {
450             // update audio frame read index
451             pCb->afRdIdx++;
452             if (pCb->afRdIdx >= pCb->maxNumAfCb)
453             {
454                 pCb->afRdIdx = 0;
455             }
456             
457             // update PCM read index
458             pCb->pcmRdIdx = 0;
459             
460             // update number of audio frames in circular buffer
461             pCb->numAfCb--;
462         }
463     }
464     
465     if (pCb->emptyFlag == 1)
466     {
467         //
468         // Writer inactive, but remaining frames in circular buffer.
469         // Update empty flag.
470         //
471         if (pCb->numAfCb <= 0)
472         {
473             pCb->emptyFlag = 0;
474         }
475     }
476     
477     // (***) FL: revisit
478     // Write back circular buffer configuration.
479     // NOTE: Probably only a subset of this information needs to be updated.
480     Cache_wb(pCb, sizeof(PAF_AST_DecOpCircBuf), Cache_Type_ALLD, 0);
481     Cache_wait();    
482         
483     return PAF_DECOP_CB_SOK;
486 // Write audio frame to circular buffer
487 Int cbWriteAf(
488     PAF_AST_DecOpCircBuf *pCb,  // decoder output circular buffer
489     PAF_AudioFrame *pAfWrt      // audio frame from which to write
492     PAF_AudioFrame *pAfCb;
493     PAF_ChannelMask_HD streamMask;
494     Int8 i;
495     Int16 j;
497     // (***) FL: revisit
498     // Invalidate circular buffer configuration.
499     // NOTE: Probably only a subset of this information nexeds to be updated.
500     Cache_inv(pCb, sizeof(PAF_AST_DecOpCircBuf), Cache_Type_ALLD, 0);
501     Cache_wait();
502     
503     if (pCb->readerActiveFlag == 1)
504     {
505         //
506         // Normal case, reader active.
507         // If reader not active, don't write to circular buffer or check OVRflow.
509 #if 0        
510         if (pCb->cbWriteAfInit == 0)
511         {
512             // Invalidate AF circular buffer
513             Cache_inv(pCb->afCb, pCb->maxNumAfCb*sizeof(PAF_AudioFrame), Cache_Type_ALLD, 0);
514             for (n=0; n<pCb->maxNumAfCb; n++)
515             {
516                 pAfCb = &pCb->afCb[n];
517                 Cache_inv(pAfCb->data.sample, PAF_DECOP_CB_MAX_NUM_PCM_CH*sizeof(PAF_AudioData *), Cache_Type_ALLD, 0);
518             }
519             Cache_wait();
521             pCb->cbWriteAfInit = 1;
522         }
523 #endif        
525         // check overflow
526         if (pCb->numAfCb >= pCb->maxNumAfCb)
527         {
528             pCb->errOvrCnt++;
529             //SW_BREAKPOINT;
530             Log_info1("cbWriteAf: ERROR: overflow, numAfCb=%d", pCb->numAfCb);
531             return PAF_DECOP_CB_WRITE_OVERFLOW;
532         }
533         
534         // get pointer to current audio frame in circular buffer
535         pAfCb = &pCb->afCb[pCb->afWrtIdx];
536            
537         // write audio frame information updated by decoder
538         pAfCb->sampleDecode = pAfWrt->sampleDecode;
539         PAF_PROCESS_COPY(pAfCb->sampleProcess, pAfWrt->sampleProcess);
540         pAfCb->sampleRate = pAfWrt->sampleRate;
541         pAfCb->sampleCount = pAfWrt->sampleCount;
542         pAfCb->channelConfigurationRequest = pAfWrt->channelConfigurationRequest;
543         pAfCb->channelConfigurationStream = pAfWrt->channelConfigurationStream;
544         // write metadata information updated by decoder //QIN
545         pAfCb->bsMetadata_type     = pAfWrt->bsMetadata_type;        /* non zero if metadata is attached. */
546         pAfCb->pafBsMetadataUpdate = pAfWrt->pafBsMetadataUpdate;    /* indicates whether bit-stream metadata update */
547         pAfCb->numPrivateMetadata  = pAfWrt->numPrivateMetadata;     /* number of valid private metadata (0 or 1 if metadata filtering enabled) */
548         pAfCb->bsMetadata_offset   = pAfWrt->bsMetadata_offset;      /* offset into audio frame for change in bsMetadata_type field */
549         // write PCM samples
550         streamMask = pAfWrt->fxns->channelMask(pAfWrt, pAfCb->channelConfigurationStream);
551         for (i = 0; i < PAF_DECOP_CB_MAX_NUM_PCM_CH; i++)
552         {
553             if ((streamMask >> i) & 0x1)
554             {
555                 for (j = 0; j < pCb->decOpFrameLen; j++)
556                 {
557                     pAfCb->data.sample[i][j] = pAfWrt->data.sample[i][j];
558                 }            
559                 
560                 pAfCb->data.samsiz[i] = pAfWrt->data.samsiz[i];
561             }
562         }
563         
564         // Write metadata to circular buffer
565         for (i = 0; i < pAfCb->numPrivateMetadata; i++) // FL: only copy numPrivateMetadata
566         {
567             pAfCb->pafPrivateMetadata[i].offset = pAfWrt->pafPrivateMetadata[i].offset; 
568             pAfCb->pafPrivateMetadata[i].size   = pAfWrt->pafPrivateMetadata[i].size; 
569             memcpy(pAfCb->pafPrivateMetadata[i].pMdBuf, pAfWrt->pafPrivateMetadata[i].pMdBuf, pAfWrt->pafPrivateMetadata[i].size); 
570         }
571         
572         // update audio frame write index
573         pCb->afWrtIdx++;
574         if (pCb->afWrtIdx >= pCb->maxNumAfCb)
575         {
576             pCb->afWrtIdx = 0;
577         }
578         
579         // update number of audio frames in circular buffer
580         pCb->numAfCb++;
582         // (***) FL: revisit
583         // Write back circular buffer configuration
584         Cache_wb(pCb, sizeof(PAF_AST_DecOpCircBuf), Cache_Type_ALLD, 0);
585         // write back audio frame
586         Cache_wb(pAfCb, sizeof(PAF_AudioFrame), Cache_Type_ALLD, 0);
587         Cache_wb(pAfCb->data.samsiz, PAF_DECOP_CB_MAX_NUM_PCM_CH*sizeof(PAF_AudioSize), Cache_Type_ALLD, 0);
588         // write back PCM data
589         for (i = 0; i < PAF_DECOP_CB_MAX_NUM_PCM_CH; i++)
590         {
591             if ((streamMask >> i) & 0x1)
592             {
593                 Cache_wb(pAfCb->data.sample[i], pCb->decOpFrameLen*sizeof(PAF_AudioData), Cache_Type_ALLD, 0);
594             }
595         }
596         
597         // write back private metadata // QIN
598         for (i=0; i<pAfCb->numPrivateMetadata; i++) // FL: only write back numPrivateMetadata
599         {
600             //Cache_wb(&pAfCb->pafPrivateMetadata[i], sizeof(PAF_PrivateMetadata), Cache_Type_ALLD, 0); // FL: unnecessary since part of AF
601             Cache_wb(pAfCb->pafPrivateMetadata[i].pMdBuf, pAfCb->pafPrivateMetadata[i].size, Cache_Type_ALLD, 0);
602         }
603         Cache_wait();
604     }  
605     
606     return PAF_DECOP_CB_SOK;
609 // Get next audio frame to write in circular buffer
610 Int cbGetNextWriteAf(
611     PAF_AST_DecOpCircBuf *pCb, // decoder output circular buffer
612     PAF_AudioFrame **ppAfWrt   // audio frame next to be written
615     // get pointer to current audio frame in circular buffer
616     *ppAfWrt = &pCb->afCb[pCb->afWrtIdx];
617     
618     // update audio frame write index
619     pCb->afWrtIdx++;
620     if (pCb->afWrtIdx > pCb->maxNumAfCb)
621     {
622         pCb->afWrtIdx = 0;
623     }    
624     
625     return PAF_DECOP_CB_SOK;
628 // Output log of circular buffer control variables (debug)
629 Int cbLog(
630     PAF_AST_DecOpCircBuf *pCb,
631     Int8 fullLog, 
632     char *locInfo
635     Log_info1("CB: %s", (IArg)locInfo);
636     Log_info3("CB: readerActiveFlag=%d, writerActiveFlag=%d, emptyFlag=%d", pCb->readerActiveFlag, pCb->writerActiveFlag, pCb->emptyFlag);
637     Log_info4("CB: afRdIdx=%d, pcmRdIdx=%d, afWrtIdx=%d, numAfCb=%d", pCb->afRdIdx, pCb->pcmRdIdx, 
638         pCb->afWrtIdx, 
639         pCb->numAfCb);
640     if (fullLog)
641     {
642         Log_info1("CB: maxNumAfCb=%d", pCb->maxNumAfCb);  
643         Log_info2("CB: decOpFrameLen=%d, strFrameLen=%d", pCb->decOpFrameLen, pCb->strFrameLen);
644         //Log_info1("cbWriteInit=%d", pCb->cbWriteAfInit);
645     }
646     
647     return 0;
650 // Generate mute AF on circular buffer read
651 static Void cbReadAfMute(
652     PAF_AudioFrame *pAfRd,      // audio frame into which to read
653     Int16 strFrameLen           // stream frame length (output transaction size)
656     PAF_ChannelMask_HD streamMask;
657     Int8 i;
658     
659     pAfRd->sampleDecode = PAF_SOURCE_PCM;
660     PAF_PROCESS_ZERO(pAfRd->sampleProcess);
661     pAfRd->sampleRate = PAF_SAMPLERATE_48000HZ;
662     pAfRd->sampleCount = strFrameLen;
663     pAfRd->channelConfigurationRequest.full = 0;
664     pAfRd->channelConfigurationRequest.part.sat = PAF_CC_SAT_SURROUND4;
665     pAfRd->channelConfigurationRequest.part.sub = PAF_CC_SUB_ONE;
666     pAfRd->channelConfigurationStream.full = 0;
667     pAfRd->channelConfigurationStream.part.sat = PAF_CC_SAT_SURROUND4;
668     pAfRd->channelConfigurationStream.part.sub = PAF_CC_SUB_ONE;
669     
670     // compute stream mask
671     streamMask = pAfRd->fxns->channelMask(pAfRd, pAfRd->channelConfigurationStream);
672     // Clear PCM data
673     for (i = 0; i < PAF_DECOP_CB_MAX_NUM_PCM_CH; i++)
674     {
675         if ((streamMask >> i) & 0x1)
676         {
677             memset(pAfRd->data.sample[i], strFrameLen, 0);
678         }
679         pAfRd->data.samsiz[i] = 0;
680     }