]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - processor-sdk/performance-audio-sr.git/blob - pasdk/test_arm/framework/audioStreamDecodeProc.c
PASDK-53: Experimental code, remove Dec Op CB reset on CB underflow.
[processor-sdk/performance-audio-sr.git] / pasdk / test_arm / framework / audioStreamDecodeProc.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 /*
37  *  ======== audioStreamDecodeProc.c ========
38  */
40 #include <xdc/cfg/global.h>
41 #include <xdc/runtime/Error.h>
42 #include <xdc/runtime/Log.h>
43 #include <xdc/runtime/Memory.h>
44 #include <ti/sysbios/BIOS.h>
45 #include <ti/sysbios/hal/Cache.h>
46 #include <ti/sysbios/knl/Task.h>
47 #include <ti/ipc/Ipc.h>
48 #include <ti/ipc/MessageQ.h>
49 #include <ti/ipc/MultiProc.h>
51 #include <acp_mds.h>
52 #include <pcm.h>
53 #include "audioStreamProc_params.h"
54 #include "audioStreamProc_patchs.h"
55 #include "audioStreamProc_config.h"
57 #include "common.h"
58 #include "aspMsg_common.h"
59 #include "aspMsg_slave.h"
60 #include "aspDecOpCircBuf_slave.h"
61 #include "audioStreamProc_common.h"
62 #include "audioStreamDecodeProc.h"
64 #include "statusOp_common.h"
67 // FL: debug
68 //#include "fwkSim.h"
69 #include "dbgCapAf.h"
70 #include "dbgDib.h"
73 //
74 // Decoder Definitions
75 //
76 #define decLinkInit pQ->i_decLinkInit
78 #define __TASK_NAME__  "TaskAsdp"
80 extern struct {
81     Int size;
82     IALG_Status *pStatus[512];
83 } IACP_STD_BETA_TABLE;
85 extern const char AFChanPtrMap[PAF_MAXNUMCHAN+1][PAF_MAXNUMCHAN];
86 extern PAF_ChannelConfigurationMaskTable PAF_ASP_stdCCMT;
88 LINNO_DEFN(TaskAsdp); /* Line number macros */
89 ERRNO_DEFN(TaskAsdp); /* Error number macros */
91 // ASDT configuration
92 PAF_ASDT_Config gPAF_ASDT_config 
93 __attribute__ ((section(".globalSectionPafAsdtConfig"))) = {
94     NULL,               // acp
95     {NULL, NULL},       // decOpCircBufCtl
96     &gPAF_AST_config    // ASIT/ASOT/ASDT shared configuration
97 };
99 PAF_AudioFrame *gpDecAudioFrame=NULL;
100 PAF_AudioData  *gDecAudioFrameChannelPointers[PAF_MAXNUMCHAN_AF];
101 PAF_AudioSize  gDecAudioFrameChannelSizes[PAF_MAXNUMCHAN_AF];
102 PAF_AudioData  *gDecOrigAudioFrameChannelPointers[PAF_MAXNUMCHAN_AF];
104 // Underflow threshold before returning error to Top-Level FSM
105 #define DEC_OP_CB_WRTAF_OVR_THR  ( 20 ) // FL: arbitrary setting
106 UInt32 gDecOpCbWrtAfOvr  =0; // decoder output circular buffer overflow count
108 // Global debug counters */
109 UInt32 gSlaveStartErrCnt        =0;
110 UInt32 gSlaveStartCnt           =0;
111 UInt32 gSlaveSourceSelectCnt    =0;
112 UInt32 gSlaveExitCnt            =0;
113 UInt32 gSlaveDecExitCnt         =0;
114 UInt32 gSlaveDecControlCnt      =0;
115 UInt32 gSlaveDecActivateCnt     =0;
116 UInt32 gSlaveDecResetCnt        =0;
117 UInt32 gSlaveDecInfoCnt         =0;
118 UInt32 gSlaveDecDecodeCnt       =0;
119 UInt32 gSlaveDecDeactivateCnt   =0;
122 /*
123  *  ======== taskAsdpFxn ========
124  *  Audio Stream Decode Processing task function
125  */
126 Void taskAsdpFxn(
127 //    Int betaPrimeValue, // FL: revisit
128     const PAF_ASDT_Params *pP,
129     const PAF_ASDT_Patchs *pQ
132     PAF_ASDT_Config *pC;            /* Local configuration pointer */
133     PAF_AST_Config *pAstCfg;        /* Common (shared) configuration pointer */
134     Int as;                         /* Audio Stream Number (1, 2, etc.) */
135     Int z;                          /* input/encode/stream/decode/output counter */
136     Int i;                          /* phase */
137     Int zMD, zMS;
138     Bool done;
139     Bool decDone;
140     ALG_Handle alg[DECODEN_MAX];
141     ASP_Slave_Cmd slaveCmd;
142     Int sourceSelect;
143     DEC_Handle dec;
144     IALG_Cmd decCtrlCmd;            // decoder control command
145     Int decCtrlRet;                 // decoder control return
146     Int errno;                      /* error number */
147     Int size;
148     Int argIdx;
149     // Decoder output circular buffer
150     PAF_AST_DecOpCircBufCtl *pCbCtl;    /* Decoder output circular buffer control */
151     //PAF_AST_DecOpCircBuf *pCb;
152     PAF_AudioFrame *pAfWrt;
153     Int cbErrno;    
154     // Messaging
155     PAF_InpBufConfig *pIpBufConfig;
156     ASP_Msg *pAspMsg;
157     MessageQ_QueueId queId;
158     Int status;
159     Int zI;
160     Int bufEnd, wrapSize, currentBufSize, chunkSize;
161     Int8 temp8;
163     
164     Log_info0("Enter taskAsdpFxn()");
165     
166     //
167     // Audio Framework Parameters & Patch (*pP, *pQ):
168     //
169     if (!pP) 
170     {
171         TRACE_TERSE0("TaskAsdp: No Parameters defined. Exiting.");
172         LINNO_RPRT(TaskAsdp, -1);
173         return;
174     }
176     if (!pQ) 
177     {
178         TRACE_TERSE0("TaskAsdp: No Patchs defined. Exiting.");
179         LINNO_RPRT(TaskAsdp, -1);
180         return;
181     }    
183     //
184     // Audio Framework Configuration (*pC):
185     //
186     pC = &gPAF_ASDT_config;
187     pAstCfg = pC->pAstCfg; // get pointer to common (shared) configuration 
188     pCbCtl = &pC->decOpCircBufCtl; // get pointer to circular buffer control
190     // wait for initialization message from master
191     do {
192         status = MessageQ_get(hAspMsgSlave->slaveQue, (MessageQ_Msg *)&pAspMsg, MessageQ_FOREVER);
193         //TRACE_TERSE1("Rx ASP message: status=%d", status);
194     //} while ((status != MessageQ_S_SUCCESS || (pAspMsg->cmd != ASP_SLAVE_START));
195     } while (status != MessageQ_S_SUCCESS);
196     if ((pAspMsg->procId != hAspMsgSlave->masterProcId) ||
197         (pAspMsg->cmd != ASP_SLAVE_START))
198     {
199         TRACE_TERSE3("ERROR: Rx ASP message: procId=%d, cmd=%d, messageId=0x%04x", pAspMsg->procId, pAspMsg->cmd, pAspMsg->messageId);
200         SW_BREAKPOINT;
201     }
202     hAspMsgSlave->masterMessageId = pAspMsg->messageId; 
203     gSlaveStartCnt++;
204     TRACE_MSG3("Rx ASP message, procId=%d, cmd=%d, messageId=0x%04x", pAspMsg->procId, pAspMsg->cmd, pAspMsg->messageId);
206     // invalidate AST shared configuration
207     Cache_inv(pAstCfg, sizeof(PAF_AST_Config), Cache_Type_ALLD, 0);
208     // FL: no need to share this pointer, can be local
209     //Cache_inv(&pC, sizeof(PAF_AST_Config *), Cache_Type_ALLD, 0);
210     Cache_wait();
211     
212     // (***) FL: revisit
213     // invalidate Dec configuration for all Decoder zones
214     Cache_inv(&pAstCfg->xDec[0], DECODEN*sizeof(PAF_AST_Decode), Cache_Type_ALLD, 0);
215     Cache_wait();
217     // (***) FL: revisit
218     // invalidate Beta Table status pointers
219     Cache_inv((Ptr)(&IACP_STD_BETA_TABLE.pStatus[0]), 512*sizeof(IALG_Status *), Cache_Type_ALLD, 0); // invalidate entire beta table
220     Cache_wait();
222     /* Obtain Audio Stream Number (1, 2, etc.) */
223     as = pAstCfg->as;
224     TRACE_TERSE1("TaskAsdp: Started with AS%d.", as);
225     
226     //
227     // Initialize message log trace and line number reporting
228     //
229     for (z=STREAM1; z < STREAMN; z++)
230     {
231         TRACE_TERSE1("TaskAsdp: AS%d: initiated", as+z);
232     }
233     LINNO_RPRT(TaskAsdp, -1);
235     // Get decoder and stream index associated with the master input
236     zMD = pAstCfg->masterDec;
237     zMS = pAstCfg->masterStr;
239     // 
240     // Initialize per parameterized phases.
241     //   - Malloc: Memory Allocation
242     //   - Config: Configuration Initialization
243     //   - AcpAlg: ACP Algorithm Initialization and Local Attachment
244     //   - Common: Common Algorithm Initialization
245     //   - AlgKey: Dec/Enc chain to Array Initialization
246     //   - Unused: (available)
247     //   - Unused: (available)
248     //   - Unused: (available)
249     //
250     LINNO_RPRT(TaskAsdp, -2);
251     for (i=0; i < lengthof(pP->fxns->initPhase); i++)
252     {
253         Int linno;
254         if (pP->fxns->initPhase[i])
255         {
256             if ((linno = pP->fxns->initPhase[i](pP, pQ, pC)))
257             {
258                 LINNO_RPRT(TaskAsdp, linno);
259                 return;
260             }
261         }
262         else 
263         {
264             TRACE_TERSE1("TaskAsdp: AS%d: initialization phase - null", as+zMS);
265         }
266         TRACE_TERSE2("TaskAsdp: AS%d: initialization phase - %d completed", as+zMS, i);
267         LINNO_RPRT(TaskAsdp, -i-3);
268     }
269     
270     //
271     // End of Initialization -- final memory usage report.
272     //
273     if (pP->fxns->memStatusPrint)
274     {
275         pP->fxns->memStatusPrint(HEAP_INTERNAL, HEAP_INTERNAL1, HEAP_EXTERNAL, HEAP_INTERNAL1_SHM);
276     }
277     
278 #ifdef NON_CACHE_STATUS
279     //
280     // init Status structure Gate
281     //
282     if (statusOp_Init(GATEMP_INDEX_DEC) == STATUSOP_INIT_FAIL)
283     {
284         TRACE_TERSE1("TaskAsdp: Gate Index %d:initialization status GateMP Fail.", GATEMP_INDEX_DEC);
285     }
286     if (statusOp_Init(GATEMP_INDEX_DDP) == STATUSOP_INIT_FAIL)
287     {
288         TRACE_TERSE1("TaskAsdp: Gate Index %d:initialization status GateMP Fail.", GATEMP_INDEX_DDP);
289     }
290     if (statusOp_Init(GATEMP_INDEX_PCM) == STATUSOP_INIT_FAIL)
291     {
292         TRACE_TERSE1("TaskAsdp: Gate Index %d:initialization status GateMP Fail.", GATEMP_INDEX_PCM);
293     }
294     if (statusOp_Init(GATEMP_INDEX_THD) == STATUSOP_INIT_FAIL)
295     {
296         TRACE_TERSE1("TaskAsdp: Gate Index %d:initialization status GateMP Fail.", GATEMP_INDEX_THD);
297     }
298 #endif
300     // (***) FL: revisit
301     // write back Status structure addresses for Beta Units initialized on Slave
302     Cache_wb((Ptr)(&IACP_STD_BETA_TABLE.pStatus[STD_BETA_DECODE]), sizeof(IALG_Status *), Cache_Type_ALLD, 0);
303     Cache_wb((Ptr)(&IACP_STD_BETA_TABLE.pStatus[STD_BETA_PCM]), sizeof(IALG_Status *), Cache_Type_ALLD, 0);
304     Cache_wb((Ptr)(&IACP_STD_BETA_TABLE.pStatus[STD_BETA_PCM2]), sizeof(IALG_Status *), Cache_Type_ALLD, 0);
305     Cache_wb((Ptr)(&IACP_STD_BETA_TABLE.pStatus[STD_BETA_DDP]), sizeof(IALG_Status *), Cache_Type_ALLD, 0);
306     Cache_wb((Ptr)(&IACP_STD_BETA_TABLE.pStatus[STD_BETA_DDP2]), sizeof(IALG_Status *), Cache_Type_ALLD, 0);
307     Cache_wb((Ptr)(&IACP_STD_BETA_TABLE.pStatus[STD_BETA_THD]), sizeof(IALG_Status *), Cache_Type_ALLD, 0);
308     Cache_wb((Ptr)(&IACP_STD_BETA_TABLE.pStatus[STD_BETA_THD2]), sizeof(IALG_Status *), Cache_Type_ALLD, 0);
309     Cache_wait();
310     
311     // (***) FL: revisit
312     // write back Status structures for Beta Units initialized on Slave
313    /* size = IACP_STD_BETA_TABLE.pStatus[STD_BETA_DECODE]->size;
314     Cache_wbInv((Ptr)(IACP_STD_BETA_TABLE.pStatus[STD_BETA_DECODE]), size, Cache_Type_ALLD, 0);
315     size = IACP_STD_BETA_TABLE.pStatus[STD_BETA_PCM]->size;
316     Cache_wbInv((Ptr)(IACP_STD_BETA_TABLE.pStatus[STD_BETA_PCM]), size, Cache_Type_ALLD, 0);
317     size = IACP_STD_BETA_TABLE.pStatus[STD_BETA_PCM2]->size;
318     Cache_wbInv((Ptr)(IACP_STD_BETA_TABLE.pStatus[STD_BETA_PCM2]), size, Cache_Type_ALLD, 0);
319     size = IACP_STD_BETA_TABLE.pStatus[STD_BETA_DDP]->size;
320     Cache_wbInv((Ptr)(IACP_STD_BETA_TABLE.pStatus[STD_BETA_DDP]), size, Cache_Type_ALLD, 0);
321     size = IACP_STD_BETA_TABLE.pStatus[STD_BETA_DDP2]->size;
322     Cache_wbInv((Ptr)(IACP_STD_BETA_TABLE.pStatus[STD_BETA_DDP2]), size, Cache_Type_ALLD, 0);
323     Cache_wait();
325     // (***) FL: revisit
326     // write back Dec configuration
327     Cache_wbInv(&pAstCfg->xDec[0], DECODEN*sizeof(PAF_AST_Decode), Cache_Type_ALLD, 0);
328     Cache_wait();*/
329     
330     // Send initialization complete message to master
331     queId = MessageQ_getReplyQueue(pAspMsg);
332     pAspMsg->procId = hAspMsgSlave->slaveProcId;
333     pAspMsg->cmd = ASP_MASTER_START_DONE;
334     pAspMsg->messageId = hAspMsgSlave->masterMessageId | ((UInt32)1<<31);
335     TRACE_MSG3("Tx ASP message, procId=%d, cmd=%d, messageId=0x%04x", pAspMsg->procId, pAspMsg->cmd, pAspMsg->messageId);
336     status = MessageQ_put(queId, (MessageQ_Msg)pAspMsg); /* send message back */
337     if (status != MessageQ_S_SUCCESS)
338     {
339         SW_BREAKPOINT;
340     }
342     done = FALSE;
343     while (done==FALSE)
344     {
345         // wait for source select message from master
346         do {
347             status = MessageQ_get(hAspMsgSlave->slaveQue, (MessageQ_Msg *)&pAspMsg, MessageQ_FOREVER);
348         } while ((status < 0) || (pAspMsg->cmd != ASP_SLAVE_DEC_SOURCE_SELECT));
349         if ((pAspMsg->procId != hAspMsgSlave->masterProcId) ||
350             (pAspMsg->cmd != ASP_SLAVE_DEC_SOURCE_SELECT))
351         {
352             TRACE_TERSE3("ERROR: Rx ASP message: procId=%d, cmd=%d, messageId=0x%04x", pAspMsg->procId, pAspMsg->cmd, pAspMsg->messageId);
353             SW_BREAKPOINT;
354         }            
355         hAspMsgSlave->masterMessageId = pAspMsg->messageId; 
356         sourceSelect = *(Int32 *)&pAspMsg->buf[0];
357         TRACE_MSG3("Rx ASP message, procId=%d, cmd=%d, messageId=0x%04x", pAspMsg->procId, pAspMsg->cmd, pAspMsg->messageId);
358         TRACE_MSG1("sourceSelect=%d.", sourceSelect);
359         // send source select complete message to master
360         queId = MessageQ_getReplyQueue(pAspMsg);
361         pAspMsg->procId = hAspMsgSlave->slaveProcId;
362         pAspMsg->cmd = ASP_MASTER_DEC_SOURCE_SELECT_DONE;
363         pAspMsg->messageId = hAspMsgSlave->masterMessageId | ((UInt32)1<<31);
364         gSlaveSourceSelectCnt++;
365         TRACE_MSG3("Tx ASP message, procId=%d, cmd=%d, messageId=0x%04x", pAspMsg->procId, pAspMsg->cmd, pAspMsg->messageId);
366         MessageQ_put(queId, (MessageQ_Msg)pAspMsg); /* send message back */
367         
368         for (z=DECODE1; z < DECODEN; z++)
369         {
370             alg[z] = pAstCfg->xDec[z].decAlg[PAF_SOURCE_PCM];
371         }
372         alg[zMD] = pAstCfg->xDec[zMD].decAlg[sourceSelect];
374         // FL: debug, reset IB capture buffer
375         //capIbReset();
376         //Log_info0("capIbReset()");
377         // FL: debug, reset audio frame capture buffer
378         //capAfReset();
379         
380         decDone = FALSE;
381         while (decDone==FALSE)
382         {
383             // wait for received message from master
384             do {
385                 status = MessageQ_get(hAspMsgSlave->slaveQue, (MessageQ_Msg *)&pAspMsg, MessageQ_FOREVER);
386             } while (status < 0);
387             if (pAspMsg->procId != hAspMsgSlave->masterProcId)
388             {
389                 TRACE_TERSE3("ERROR: Rx ASP message: procId=%d, cmd=%d, messageId=0x%04x", pAspMsg->procId, pAspMsg->cmd, pAspMsg->messageId);
390                 SW_BREAKPOINT;
391             }
392             hAspMsgSlave->masterMessageId = pAspMsg->messageId; 
393             slaveCmd = pAspMsg->cmd;
394             TRACE_MSG3("Rx ASP message, procId=%d, cmd=%d, messageId=0x%04x", pAspMsg->procId, pAspMsg->cmd, pAspMsg->messageId);
396             switch (slaveCmd)
397             {
398                 case ASP_SLAVE_NULL:
399                 case ASP_SLAVE_START:
400                     gSlaveStartErrCnt++;
401                     TRACE_TERSE1("ERROR: unexpected slaveCmd=%d", slaveCmd);
402                     
403                     break;
404                     
405                 case ASP_SLAVE_EXIT:
406                     gSlaveExitCnt++;
407                     TRACE_TERSE1("slaveCmd=%d", slaveCmd);
408                     
409                     decDone = TRUE;
410                     done = TRUE;
411                     break;
412                     
413                 case ASP_SLAVE_DEC_EXIT:
414                     gSlaveDecExitCnt++;
415                     TRACE_TERSE1("slaveCmd=%d", slaveCmd);
416                     
417                     // send dec exit complete message to master
418                     queId = MessageQ_getReplyQueue(pAspMsg);
419                     pAspMsg->procId = hAspMsgSlave->slaveProcId;
420                     pAspMsg->cmd = ASP_MASTER_DEC_EXIT_DONE;
421                     pAspMsg->messageId = hAspMsgSlave->masterMessageId | ((UInt32)1<<31);
422                     TRACE_MSG3("Tx ASP message, procId=%d, cmd=%d, messageId=0x%04x", pAspMsg->procId, pAspMsg->cmd, pAspMsg->messageId);
423                     status = MessageQ_put(queId, (MessageQ_Msg)pAspMsg); /* send message back */
424                     if (status != MessageQ_S_SUCCESS)
425                     {
426                         SW_BREAKPOINT;
427                     }
428                     
429                     decDone=TRUE;
430                     break;
431                     
432                 case ASP_SLAVE_DEC_CONTROL:
433                     gSlaveDecControlCnt++;
434                     // simulate dec control load
435                     //simLoad(DEC_CONTROL_LOAD);
436                     
437                     argIdx = 0; // get decIdx
438                     z = *(Int32 *)&pAspMsg->buf[argIdx];
439                     argIdx += sizeof(Int32);
440                     decCtrlCmd = *(IALG_Cmd *)&pAspMsg->buf[argIdx]; // get decCtrlCmd
441                     TRACE_MSG3("slaveCmd=%d, decIdx=%d, decCtrlCmd=%d", slaveCmd, z, decCtrlCmd);
442                     
443                     decCtrlRet = alg[z]->fxns->algControl(alg[z], decCtrlCmd, NULL);
445                     // send dec control complete message to master
446                     queId = MessageQ_getReplyQueue(pAspMsg);
447                     pAspMsg->procId = hAspMsgSlave->slaveProcId;
448                     pAspMsg->cmd = ASP_MASTER_DEC_CONTROL_DONE;
449                     pAspMsg->messageId = hAspMsgSlave->masterMessageId | ((UInt32)1<<31);
450                     argIdx = 0; // set decCtrlRet
451                     *(Int32 *)&pAspMsg->buf[argIdx] = decCtrlRet;
452                     TRACE_MSG3("Tx ASP message, procId=%d, cmd=%d, messageId=0x%04x", pAspMsg->procId, pAspMsg->cmd, pAspMsg->messageId);
453                     status = MessageQ_put(queId, (MessageQ_Msg)pAspMsg); /* send message back */
454                     if (status != MessageQ_S_SUCCESS)
455                     {
456                         SW_BREAKPOINT;
457                     }
459                     break;
460                     
461                 case ASP_SLAVE_DEC_ACTIVATE:
462                     gSlaveDecActivateCnt++;
463                     // simulate dec activate load
464                     //simLoad(DEC_ACTIVATE_LOAD);
465                     
466                     // (***) FL: revisit
467                     // invalidate Status structures for shared Beta Units
468                     //size = IACP_STD_BETA_TABLE.pStatus[STD_BETA_DECODE]->size;
469                     //Cache_inv((Ptr)(IACP_STD_BETA_TABLE.pStatus[STD_BETA_DECODE]), size, Cache_Type_ALLD, 0);
470                     /*size = IACP_STD_BETA_TABLE.pStatus[STD_BETA_PCM]->size;
471                     Cache_inv((Ptr)(IACP_STD_BETA_TABLE.pStatus[STD_BETA_PCM]), size, Cache_Type_ALLD, 0);
472                     size = IACP_STD_BETA_TABLE.pStatus[STD_BETA_DDP]->size;
473                     Cache_inv((Ptr)(IACP_STD_BETA_TABLE.pStatus[STD_BETA_DDP]), size, Cache_Type_ALLD, 0);
474                     Cache_wait();*/
475                     
476                     argIdx = 0; // get decIdx
477                     z = *(Int32 *)&pAspMsg->buf[argIdx];
478                     TRACE_MSG2("slaveCmd=%d, decIdx=%d", slaveCmd, z);
479                     
480                     // invalidate Dec configuration
481                     Cache_inv(&pAstCfg->xDec[z], sizeof(PAF_AST_Decode), Cache_Type_ALLD, 0);
482                     Cache_wait();
483                     
484                     if (alg[z]->fxns->algActivate)
485                     {
486                         alg[z]->fxns->algActivate(alg[z]);
487                     }
489                     // Start writes to circular buffer
490                     //pCb = &pAstCfg->xDecOpCb[z];
491                     cbErrno = cbWriteStart(pCbCtl, z);
492                     if (cbErrno < 0)
493                     {
494                         SW_BREAKPOINT;
495                     }
496                     // FL: debug, log circular buffer control variables
497                     cbLog(pCbCtl, z, 1, "cbWriteStart");
498                     // Reset audio frame
499                     resetAf(pP, z, sourceSelect);
500                     
501                     // send dec activate complete message to master
502                     queId = MessageQ_getReplyQueue(pAspMsg);
503                     pAspMsg->procId = hAspMsgSlave->slaveProcId;
504                     pAspMsg->cmd = ASP_MASTER_DEC_ACTIVATE_DONE;
505                     pAspMsg->messageId = hAspMsgSlave->masterMessageId | ((UInt32)1<<31);
506                     TRACE_MSG3("Tx ASP message, procId=%d, cmd=%d, messageId=0x%04x", pAspMsg->procId, pAspMsg->cmd, pAspMsg->messageId);
507                     status = MessageQ_put(queId, (MessageQ_Msg)pAspMsg); /* send message back */
508                     if (status != MessageQ_S_SUCCESS)
509                     {
510                         SW_BREAKPOINT;
511                     }
512                    
513                     break;
514                     
515                 case ASP_SLAVE_DEC_RESET:
516                     gSlaveDecResetCnt++;
517                     // simulate dec reset load
518                     //simLoad(DEC_RESET_LOAD);
519                     
520                     argIdx = 0; // get decIdx
521                     z = *(Int32 *)&pAspMsg->buf[argIdx];
522                     TRACE_TERSE2("slaveCmd=%d,decIdx=%d", slaveCmd, z);
523                     
524                     dec = (DEC_Handle)alg[z];
525                     errno = 0;
526                     if (dec->fxns->reset)
527                     {
528                         errno = dec->fxns->reset(dec, NULL, &pAstCfg->xDec[z].decodeControl, &pAstCfg->xDec[z].decodeStatus);
529                     }
531                     // write back Dec configuration
532                     Cache_wb(&pAstCfg->xDec[z], sizeof(PAF_AST_Decode), Cache_Type_ALLD, 0);
533                     Cache_wait();            
535                     // (***) FL: revisit
536                     // write back Status structures for shared Beta Units
537                     //size = IACP_STD_BETA_TABLE.pStatus[STD_BETA_DECODE]->size;
538                     //Cache_wb((Ptr)(IACP_STD_BETA_TABLE.pStatus[STD_BETA_DECODE]), size, Cache_Type_ALLD, 0);
539                    /* size = IACP_STD_BETA_TABLE.pStatus[STD_BETA_PCM]->size;
540                     Cache_wbInv((Ptr)(IACP_STD_BETA_TABLE.pStatus[STD_BETA_PCM]), size, Cache_Type_ALLD, 0);
541                     size = IACP_STD_BETA_TABLE.pStatus[STD_BETA_DDP]->size;
542                     Cache_wbInv((Ptr)(IACP_STD_BETA_TABLE.pStatus[STD_BETA_DDP]), size, Cache_Type_ALLD, 0);
543                     Cache_wait();*/
544                     
545                     // send dec reset complete message to master
546                     queId = MessageQ_getReplyQueue(pAspMsg);
547                     pAspMsg->procId = hAspMsgSlave->slaveProcId;
548                     pAspMsg->cmd = ASP_MASTER_DEC_RESET_DONE;
549                     pAspMsg->messageId = hAspMsgSlave->masterMessageId | ((UInt32)1<<31);
550                     argIdx = 0; // set decErrno
551                     *(Int32 *)&pAspMsg->buf[argIdx] = errno;
552                     TRACE_MSG3("Tx ASP message, procId=%d, cmd=%d, messageId=0x%04x", pAspMsg->procId, pAspMsg->cmd, pAspMsg->messageId);
553                     status = MessageQ_put(queId, (MessageQ_Msg)pAspMsg); /* send message back */
554                     if (status != MessageQ_S_SUCCESS)
555                     {
556                         SW_BREAKPOINT;
557                     }
559                     break;
560                     
561                 case ASP_SLAVE_DEC_INFO:
562                     gSlaveDecInfoCnt++;
563                     // simulate dec info load
564                     //simLoad(DEC_INFO_LOAD);
565                     
566                     argIdx = 0; // get decIdx
567                     z = *(Int32 *)&pAspMsg->buf[argIdx];
568                     TRACE_TERSE2("slaveCmd=%d,decIdx=%d", slaveCmd, z);
569                     // Get input associated w/ decoder
570                     zI = pP->inputsFromDecodes[z];
572                     // (***) FL: revisit
573                     // invalidate Inp configuration
574                     Cache_inv(&pAstCfg->xInp[zI], sizeof(PAF_AST_InpBuf), Cache_Type_ALLD, 0);
575                     Cache_wait();
576                     // invalidate input data
577                     pIpBufConfig = &pAstCfg->xInp[zI].inpBufConfig;
578                     size = pIpBufConfig->frameLength * pIpBufConfig->sizeofElement;
579                     if (sourceSelect == PAF_SOURCE_PCM)
580                     {
581                         size *= pIpBufConfig->stride;
582                     }
584                     bufEnd = (Int) pIpBufConfig->base.pVoid + pIpBufConfig->sizeofBuffer;
585                     currentBufSize = (bufEnd - (Int)pIpBufConfig->pntr.pSmInt);
586                     if (currentBufSize >= size)
587                     {
588                         chunkSize = size;
589                     }
590                     else
591                     {
592                         chunkSize = currentBufSize;
593                     }
594                     wrapSize = size - chunkSize;
595                     // invalidate input data
596                     Cache_inv((Ptr)pIpBufConfig->pntr.pSmInt, chunkSize, Cache_Type_ALLD, 0);
597                     // invalidate Dec configuration
598                     TRACE_MSG2("IBUF : pIpBufConfig->pntr.pSmInt: 0x%x and chunkSize: %d", (IArg)pIpBufConfig->pntr.pSmInt, chunkSize);
599                     Cache_inv(&pAstCfg->xDec[z], sizeof(PAF_AST_Decode), Cache_Type_ALLD, 0);
600                     // status for selected decoder should be invalidated
601                     Cache_wait();
603                     /* Circular buffer wrap condition*/
604                     //if(((Int) pIpBufConfig->head.pVoid + size)  > bufEnd)
605                     if(wrapSize > 0)
606                     {
607                         // invalidate input data
608                         Cache_inv((Ptr)pIpBufConfig->base.pSmInt, wrapSize, Cache_Type_ALLD, 0);
609                         TRACE_MSG2("IBUF : pIpBufConfig->base.pSmInt: 0x%x and wrapSize: %d", (IArg)pIpBufConfig->base.pSmInt, wrapSize);
610                         // status for selected decoder should be invalidated
611                         Cache_wait();
612                     }
613                     /* Circular buffer wrap condition */
615                     dec = (DEC_Handle)alg[z];
616                     errno = 0;
617                     if (dec->fxns->info)
618                     {
619                         errno = dec->fxns->info(dec, NULL, &pAstCfg->xDec[z].decodeControl, &pAstCfg->xDec[z].decodeStatus);
620                     }
621                     
622                     // write back Dec configuration
623                     Cache_wb(&pAstCfg->xDec[z], sizeof(PAF_AST_Decode), Cache_Type_ALLD, 0);
624                     Cache_wait();            
625                     
626 #ifdef NON_CACHE_STATUS
627                     statusOp_read(&(temp8),
628                                   &(pAstCfg->xDec[z].decodeStatus.mode),
629                                   sizeof(Int8),
630                                   GATEMP_INDEX_DEC);
631                     // Re-initialize audio frame if decoder is disabled or
632                     // doesn't have a valid input
633                     if (!temp8 || !pAstCfg->xInp[zI].hRxSio)
634                     {
635                         pP->fxns->initFrame1(pP, pQ, pC, z, 0);
636                     }
637 #else
638                     // Re-initialize audio frame if decoder is disabled or
639                     // doesn't have a valid input
640                     if (!pAstCfg->xDec[z].decodeStatus.mode || !pAstCfg->xInp[zI].hRxSio)
641                     {
642                         pP->fxns->initFrame1(pP, pQ, pC, z, 0);
643                     }
644 #endif
646                     // send dec info complete message to master
647                     queId = MessageQ_getReplyQueue(pAspMsg);
648                     pAspMsg->procId = hAspMsgSlave->slaveProcId;
649                     pAspMsg->cmd = ASP_MASTER_DEC_INFO_DONE;
650                     pAspMsg->messageId = hAspMsgSlave->masterMessageId | ((UInt32)1<<31);
651                     argIdx = 0; // set decErrno
652                     *(Int32 *)&pAspMsg->buf[argIdx] = errno;
653                     TRACE_MSG3("Tx ASP message, procId=%d, cmd=%d, messageId=0x%04x", pAspMsg->procId, pAspMsg->cmd, pAspMsg->messageId);
654                     status = MessageQ_put(queId, (MessageQ_Msg)pAspMsg); /* send message back */
655                     if (status != MessageQ_S_SUCCESS)
656                     {
657                         SW_BREAKPOINT;
658                     }
659                     
660                     break;
661                     
662                 case ASP_SLAVE_DEC_DECODE:
663                     gSlaveDecDecodeCnt++;
664                     // simulate dec info load
665                     //simLoad(DEC_DECODE_LOAD);
666                     
667                     argIdx = 0; // get decIdx
668                     z = *(Int32 *)&pAspMsg->buf[argIdx];
669                     TRACE_TERSE2("slaveCmd=%d, decIdx=%d", slaveCmd, z);
670                     // Get input associated w/ decoder
671                     zI = pP->inputsFromDecodes[z];
672                     
673                     // Reset AF samsiz
674                     resetAfSamsiz(z);
675                     
676                     // invalidate Dec configuration
677                     Cache_inv(&pAstCfg->xDec[z], sizeof(PAF_AST_Decode), Cache_Type_ALLD, 0);
678                     Cache_wait();
679                     //TRACE_TERSE0("Dec:cache wb done");
680             
681                     dec = (DEC_Handle)alg[z];
682                     //TRACE_TERSE1("Dec:dec handle=0x%04x", (IArg)dec);
684                     errno = 0;
685                     cbErrno = 0;
686                     if (dec->fxns->decode)
687                     {
688                         // FL: debug, capture input buffer
689                         //capIb(pAstCfg->xInp[z].pInpBuf);
690                     
691                         errno = dec->fxns->decode(dec, NULL, &pAstCfg->xDec[z].decodeInStruct, &pAstCfg->xDec[z].decodeOutStruct);
692                         if (errno < 0)
693                         {
694                             //SW_BREAKPOINT;
695                         }
696                         TRACE_TERSE0("Dec:decode done");
697                         
698                         // copy decoder output to decoder output circular buffers
699                         //pCb = &pAstCfg->xDecOpCb[z];
700                         //TRACE_TERSE1("Dec:pCb=0x%04x", (IArg)pCb);
701                         
702                         pAfWrt = pAstCfg->xDec[z].decodeOutStruct.pAudioFrame;
703                         TRACE_TERSE1("Dec:pAfWrt=0x%04x", (IArg)pAfWrt);
704                         //TRACE_TERSE1("nSamples=%d",pAfWrt->data.nSamples);
705                         
706                         // FL: debug, capture audio frame
707                         //if (capAfWrite(pAfWrt, PAF_CNTR) != CAP_AF_SOK)
708                         //{
709                         //    Log_info0("capAfWrite() error");
710                         //}                        
712                         cbErrno = cbWriteAf(pCbCtl, z, pAfWrt);
713                         if (cbErrno < 0)
714                         {
715                             //SW_BREAKPOINT; // FL: debug
716                             
717                             if (cbErrno == ASP_DECOP_CB_WRITE_OVERFLOW)
718                             {
719                                 // Reset circular buffer
720                                 cbReset(pCbCtl, z);
721                                 // Update overflow count, return if above threshold
722                                 gDecOpCbWrtAfOvr++;
723                                 if (gDecOpCbWrtAfOvr < DEC_OP_CB_WRTAF_OVR_THR)
724                                 {
725                                     cbErrno = 0;
726                                 }
727                                 else 
728                                 {
729                                     gDecOpCbWrtAfOvr = 0;
730                                 }
731                             }
732                         }
733                         TRACE_TERSE0("Dec:cbWriteAf() complete");
734                         
735                         // FL: debug, log circular buffer control variables
736                         cbLog(pCbCtl, z, 1, "cbWriteAf");
737                     }
738                     
739                     // write back Dec configuration
740                     Cache_wb(&pAstCfg->xDec[z], sizeof(PAF_AST_Decode), Cache_Type_ALLD, 0);
741                     Cache_wait();
742                     
743 #ifdef NON_CACHE_STATUS
744                     statusOp_read(&(temp8),
745                                   &(pAstCfg->xDec[z].decodeStatus.mode),
746                                   sizeof(Int8),
747                                   GATEMP_INDEX_DEC);
748                     // Re-initialize audio frame if decoder is disabled or 
749                     // doesn't have a valid input 
750                     if (!temp8 || !pAstCfg->xInp[zI].hRxSio)
751                     {
752                         pP->fxns->initFrame1(pP, pQ, pC, z, 0);
753                     }
754 #else
755                     // Re-initialize audio frame if decoder is disabled or
756                     // doesn't have a valid input
757                     if (!pAstCfg->xDec[z].decodeStatus.mode || !pAstCfg->xInp[zI].hRxSio)
758                     {
759                         pP->fxns->initFrame1(pP, pQ, pC, z, 0);
760                     }
761 #endif
762                     // send dec info complete message to master
763                     queId = MessageQ_getReplyQueue(pAspMsg);
764                     pAspMsg->procId = hAspMsgSlave->slaveProcId;
765                     pAspMsg->cmd = ASP_MASTER_DEC_DECODE_DONE;
766                     pAspMsg->messageId = hAspMsgSlave->masterMessageId | ((UInt32)1<<31);
767                     argIdx = 0; // set decErrno
768                     *(Int32 *)&pAspMsg->buf[argIdx] = errno;
769                     argIdx += sizeof(Int32); // set cbErrno
770                     *(Int32 *)&pAspMsg->buf[argIdx] = cbErrno;                    
771                     TRACE_MSG3("Tx ASP message, procId=%d, cmd=%d, messageId=0x%04x", pAspMsg->procId, pAspMsg->cmd, pAspMsg->messageId);
772                     status = MessageQ_put(queId, (MessageQ_Msg)pAspMsg); /* send message back */
773                     if (status != MessageQ_S_SUCCESS)
774                     {
775                         SW_BREAKPOINT;
776                     }
777                     
778                     break;
779                     
780                 case ASP_SLAVE_DEC_DEACTIVATE:
781                     gSlaveDecDeactivateCnt++;
782                     // simulate dec info load
783                     //simLoad(DEC_DEACTIVATE_LOAD);
784                     
785                     argIdx = 0; // get decIdx
786                     z = *(Int32 *)&pAspMsg->buf[argIdx];
787                     TRACE_TERSE2("slaveCmd=%d, decIdx=%d", slaveCmd, z);
788                     
789                     if (alg[z]->fxns->algDeactivate)
790                     {
791                         alg[z]->fxns->algDeactivate(alg[z]);
792                     }
793                     
794                     // Stop writes to circular buffer
795                     //pCb = &pAstCfg->xDecOpCb[z];
796                     cbErrno = cbWriteStop(pCbCtl, z);
797                     if (cbErrno < 0)
798                     {
799                         SW_BREAKPOINT;
800                     }
801                     // FL: debug, log circular buffer control variables
802                     cbLog(pCbCtl, z, 1, "cbWriteStop");
803                     
804                     // send dec deactivate complete message to master
805                     queId = MessageQ_getReplyQueue(pAspMsg);
806                     pAspMsg->procId = hAspMsgSlave->slaveProcId;
807                     pAspMsg->cmd = ASP_MASTER_DEC_DEACTIVATE_DONE;
808                     pAspMsg->messageId = hAspMsgSlave->masterMessageId | ((UInt32)1<<31);
809                     TRACE_MSG3("Tx ASP message, procId=%d, cmd=%d, messageId=0x%04x", pAspMsg->procId, pAspMsg->cmd, pAspMsg->messageId);
810                     status = MessageQ_put(queId, (MessageQ_Msg)pAspMsg); /* send message back */
811                     if (status != MessageQ_S_SUCCESS)
812                     {
813                         SW_BREAKPOINT;
814                     }
815                     
816                     break;
817                     
818                 default:
819                     TRACE_TERSE1("ERROR: invalid slaveCmd=%d", slaveCmd);
820                     break;
821             }
822         }
823     }
824     
825     Log_info0("exit taskAsdpFxn()");   
829 // -----------------------------------------------------------------------------
830 // AST Initialization Function - Memory Allocation
831 //
832 //   Name:      PAF_AST_initPhaseMalloc
833 //   Purpose:   Audio Stream Task Function for initialization of data pointers
834 //              by allocation of memory.
835 //   From:      audioStream1Task or equivalent
836 //   Uses:      See code.
837 //   States:    x
838 //   Return:    0 on success.
839 //              Source code line number on MEM_calloc failure.
840 //   Trace:     Message Log "trace" in Debug Project Configuration reports:
841 //              * State information as per parent.
842 //              * Memory allocation errors.
843 //
844 Int
845 PAF_ASDT_initPhaseMalloc(
846     const PAF_ASDT_Params *pP, 
847     const PAF_ASDT_Patchs *pQ, 
848     PAF_ASDT_Config *pC
851     PAF_AST_Config *pAstCfg;
852     Int as;                     /* Audio Stream Number (1, 2, etc.) */
853     Int zMS;
854     Error_Block eb;
856     pAstCfg = pC->pAstCfg; // get pointer to common (shared) configuration
857     as = pAstCfg->as;
858     zMS = pAstCfg->masterStr;
859     
860     TRACE_TERSE1("PAF_ASDT_initPhaseMalloc: AS%d: initialization phase - memory allocation", as+zMS);
862     // Initialize error block
863     Error_init(&eb); 
865 //    if (!(gpDecAudioFrame = (PAF_AudioFrame *)Memory_calloc((IHeap_Handle)HEAP_INTERNAL1,
866     if (!(gpDecAudioFrame = (PAF_AudioFrame *)Memory_calloc((IHeap_Handle)HEAP_EXTERNAL, //Qin - moved to external memory
867         DECODEN * sizeof (PAF_AudioFrame), 4, &eb)))
868     {
869         TRACE_TERSE1("PAF_ASDT_initPhaseMalloc: AS%d: Memory_calloc failed", as+zMS);
870         SW_BREAKPOINT;
871         return __LINE__;
872     }
873     TRACE_TERSE3("PAF_ASDT_initPhaseMalloc. (gpAudioFrameSlave) %d bytes from space %d at 0x%x.",
874             DECODEN * sizeof (PAF_AudioFrame),
875             HEAP_ID_INTERNAL1, (IArg)gpDecAudioFrame);
877     TRACE_TERSE1("PAF_ASDT_initPhaseMalloc: AS%d: initialization phase - memory allocation complete.", as+zMS);
878     TRACE_TERSE1("PAF_ASDT_initPhaseMalloc: AS%d: initialization phase - memory allocation complete.", as+zMS);
879     return 0;
880 } //PAF_ASDT_initPhaseMalloc
882 // -----------------------------------------------------------------------------
883 // AST Initialization Function - Memory Initialization from Configuration
884 //
885 //   Name:      PAF_AST_initPhaseConfig
886 //   Purpose:   Audio Stream Task Function for initialization of data values
887 //              from parameters.
888 //   From:      audioStream1Task or equivalent
889 //   Uses:      See code.
890 //   States:    x
891 //   Return:    0 on success.
892 //              Other as per initFrame0 and initFrame1.
893 //   Trace:     Message Log "trace" in Debug Project Configuration reports:
894 //              * State information as per parent.
895 //
897 Int
898 PAF_ASDT_initPhaseConfig(
899     const PAF_ASDT_Params *pP, 
900     const PAF_ASDT_Patchs *pQ, 
901     PAF_ASDT_Config *pC
904     PAF_AST_Config *pAstCfg;
905     Int as;                    /* Audio Stream Number (1, 2, etc.) */
906     Int zMS;
907     Int z;
909     pAstCfg = pC->pAstCfg; // get pointer to common (shared) configuration
910     as = pAstCfg->as;
911     zMS = pAstCfg->masterStr;
912     
913     TRACE_TERSE1("PAF_ASDT_initPhaseConfig: AS%d: initialization phase - configuration", as+zMS);
915     // overwrite pointer to audio frame in framework decode control
916     for (z=DECODE1; z < DECODEN; z++) 
917     {
918         //Int zS = pP->streamsFromDecodes[z]; // FL: formerly on master
919         //pC->xDec[z].decodeControl.pAudioFrame = pC->xStr[zS].pAudioFrame; FL: formerly on master
920         //pC->xDec[z].decodeInStruct.pAudioFrame = pC->xStr[zS].pAudioFrame; FL: formerly on master
921         pAstCfg->xDec[z].decodeControl.pAudioFrame = &gpDecAudioFrame[z];
922         pAstCfg->xDec[z].decodeInStruct.pAudioFrame = &gpDecAudioFrame[z];
923         pAstCfg->xDec[z].decodeStatus = *pP->z_pDecodeStatus[z];
924         pP->fxns->initFrame0(pP, pQ, pC, z);
925     }
927     return 0;
928 }  //PAF_ASDT_initPhaseConfig
930 // -----------------------------------------------------------------------------
931 // AST Initialization Function - ACP Algorithm Instantiation
932 //
933 //   Name:      PAF_AST_initPhaseAcpAlg
934 //   Purpose:   Audio Stream Task Function for initialization of ACP by
935 //              instantiation of the algorithm.
936 //   From:      audioStream1Task or equivalent
937 //   Uses:      See code.
938 //   States:    x
939 //   Return:    0 on success.
940 //              Source code line number on ACP Algorithm creation failure.
941 //   Trace:     Message Log "trace" in Debug Project Configuration reports:
942 //              * State information as per parent.
943 //              * Memory allocation errors.
944 //
945 Int
946 PAF_ASDT_initPhaseAcpAlg(
947     const PAF_ASDT_Params *pP, 
948     const PAF_ASDT_Patchs *pQ, 
949     PAF_ASDT_Config *pC
952     PAF_AST_Config *pAstCfg;
953     Int as;                    /* Audio Stream Number (1, 2, etc.) */
954     Int z;                     /* input/encode/stream/decode/output counter */
955     Int betaPrimeOffset;
956     ACP_Handle acp;
957     Int zMS;
958     Int zS; //, zX;
960     pAstCfg = pC->pAstCfg; // get pointer to common (shared) configuration
961     as = pAstCfg->as;
962     zMS = pAstCfg->masterStr;    
964     TRACE_TERSE1("PAF_ASDT_initPhaseAcpAlg: AS%d: initialization phase - ACP Algorithm", as+zMS);
966     ACP_MDS_init();
968     if (!(acp = (ACP_Handle)ACP_MDS_create(NULL))) 
969     {
970         TRACE_TERSE1("PAF_ASDT_initPhaseAcpAlg: AS%d: ACP algorithm instance creation  failed", as+zMS);
971         return __LINE__;
972     }
973     pC->acp = acp;
975     ((ALG_Handle)acp)->fxns->algControl((ALG_Handle)acp,
976         ACP_GETBETAPRIMEOFFSET, (IALG_Status *)&betaPrimeOffset);
978     for (z=DECODE1; z < DECODEN; z++) 
979     {
980         zS = pP->streamsFromDecodes[z];
981         acp->fxns->attach(acp, ACP_SERIES_STD,
982             STD_BETA_DECODE + betaPrimeOffset * (as-1+zS),
983             (IALG_Status *)&pAstCfg->xDec[z].decodeStatus);
984         /* Ignore errors, not reported. */
985     }
987     TRACE_TERSE1("PAF_ASDT_initPhaseAcpAlg: AS%d: initialization phase - ACP Algorithm complete.", as+zMS);
989     return 0;
990 } //PAF_AST_initPhaseAcpAlg
992 // -----------------------------------------------------------------------------
993 // AST Initialization Function - Common Memory and Algorithms
994 //
995 //   Name:      PAF_AST_initPhaseCommon
996 //   Purpose:   Audio Stream Task Function for initialization of data pointers
997 //              by allocation for common memory and by instantiation for
998 //              algorithms.
999 //   From:      audioStream1Task or equivalent
1000 //   Uses:      See code.
1001 //   States:    x
1002 //   Return:    0 on success.
1003 //              Source code line number on PAF_ALG_alloc failure.
1004 //              Source code line number on PAF_ALG_mallocMemory failure.
1005 //              Source code line number on Decode Chain initialization failure.
1006 //              Source code line number on ASP Chain initialization failure.
1007 //              Source code line number on Encode Chain initialization failure.
1008 //   Trace:     Message Log "trace" in Debug Project Configuration reports:
1009 //              * State information as per parent.
1010 //              * Memory allocation errors.
1011 //
1013 #include <pafsio_ialg.h>
1015 Int
1016 PAF_ASDT_initPhaseCommon(
1017     const PAF_ASDT_Params *pP, 
1018     const PAF_ASDT_Patchs *pQ, 
1019     PAF_ASDT_Config *pC
1022     PAF_AST_Config *pAstCfg;
1023     Int as;                         /* Audio Stream Number (1, 2, etc.) */
1024     Int z;                          /* stream counter */
1025     //Int g;                        /* gear */
1026     ACP_Handle acp;
1027     PAF_IALG_Config pafAlgConfig;
1028     IALG_MemRec common[3][PAF_IALG_COMMON_MEMN+1];
1029    
1030     acp = pC->acp; // get acp handle
1031     pAstCfg = pC->pAstCfg; // get pointer to common (shared) configuration
1032     as = pAstCfg->as;
1033     
1034     TRACE_TERSE0("PAF_ASDT_initPhaseCommon: initialization phase - Common Memory");
1036     //
1037     // Determine memory needs and instantiate algorithms across audio streams
1038     //
1040     TRACE_TERSE0("PAF_ASDT_initPhaseCommon: calling PAF_ALG_setup.");
1041     PAF_ALG_setup(&pafAlgConfig, 
1042         HEAP_ID_INTERNAL,               HEAP_INTERNAL, 
1043         HEAP_ID_INTERNAL1,              HEAP_INTERNAL1, 
1044         HEAP_ID_EXTERNAL,               HEAP_EXTERNAL, 
1045         HEAP_ID_INTERNAL1_SHM,          HEAP_INTERNAL1_SHM, 
1046         HEAP_ID_EXTERNAL_SHM,           HEAP_EXTERNAL_SHM, 
1047         HEAP_ID_EXTERNAL_NONCACHED_SHM, HEAP_EXTERNAL_NONCACHED_SHM,
1048         HEAP_CLEAR);
1050     if (pP->fxns->headerPrint)
1051         pP->fxns->headerPrint();
1053     for (z=STREAM1; z < STREAMN; z++) 
1054     {
1055         //Int zD, zE, zX;
1056         Int zD, zX;
1058         TRACE_TERSE1("PAF_ASDT_initPhaseCommon: AS%d: initialization phase - Common Algorithms", as+z);
1060         //
1061         // Determine common memory needs of Decode Algorithms
1062         //
1063         PAF_ALG_init (common[z], lengthof (common[z]), COMMONSPACE);
1065         zD = -1;
1066         for (zX = DECODE1; zX < DECODEN; zX++) 
1067         {
1068             if (pP->streamsFromDecodes[zX] == z) 
1069             {
1070                 zD = zX;
1071                 break;
1072             }
1073         }
1075         if (zD >= 0) 
1076         {
1077             TRACE_TERSE1("PAF_ASDT_initPhaseCommon: calling PAF_ALG_ALLOC for decoder common[%d].", z);
1078             if (PAF_ALG_ALLOC (decLinkInit[zD-DECODE1], common[z])) 
1079             {
1080                 TRACE_TERSE3("AS%d: %s.%d: PAF_ALG_alloc failed", as+z, (IArg)__FUNCTION__, __LINE__);
1081                 TRACE_TERSE2("Failed to alloc %d bytes from space %d", common[z]->size, common[z]->space);
1083                 SW_BREAKPOINT;
1084                 return __LINE__;
1085             }
1086             TRACE_TERSE3("alloced %d bytes from space %d at 0x%x", common[z]->size, common[z]->space, (IArg)common[z]->base);
1087             if(pP->fxns->allocPrint)
1088                 pP->fxns->allocPrint ((const PAF_ALG_AllocInit *)(decLinkInit[z-DECODE1]),sizeof (*(decLinkInit[z-DECODE1])), &pafAlgConfig);
1089         }
1091 #if 0 // FL: master
1092         TRACE_TERSE3("%s.%d: calling PAF_ALG_ALLOC for stream common[%d].", (IArg)__FUNCTION__, __LINE__, z);
1093         TRACE_TERSE3("%s.%d: calling PAF_ALG_ALLOC for stream common[%d].", (IArg)__FUNCTION__, __LINE__, z);
1094         if (PAF_ALG_ALLOC (aspLinkInit[z-STREAM1][0], common[z])) 
1095         {
1096             TRACE_TERSE3("AS%d: %s.%d: PAF_ALG_alloc failed", as+z, (IArg)__FUNCTION__, __LINE__);
1097             TRACE_TERSE2("Failed to alloc %d bytes from space %d ", common[z]->size, common[z]->space);
1098             SW_BREAKPOINT;
1099             return __LINE__;
1100         }
1101         TRACE_TERSE3("alloced %d bytes from space %d at 0x%x", common[z]->size, common[z]->space, (IArg)common[z]->base);
1102         if(pP->fxns->allocPrint)
1103             pP->fxns->allocPrint((const PAF_ALG_AllocInit *)(aspLinkInit[z-STREAM1][0]), sizeof (*(aspLinkInit[z-STREAM1][0])), &pafAlgConfig);
1104 #endif
1105         
1106     }
1107     {
1108         // Changes made to share scratch between zones
1109         // Assume maximum 3 zones and scratch common memory is at offset 0;
1110         int max=0;
1111         for (z=STREAM1; z < STREAMN; z++)
1112         {
1113             if (max<common[z][0].size)
1114                 max=common[z][0].size;
1115         }
1116         common[STREAM1][0].size=max;
1117         for (z=STREAM1+1; z < STREAMN; z++)
1118             common[z][0].size=0;
1119     }
1120     
1121     //
1122     // Provide common memory needs of Decode Algorithms
1123     //
1124     for (z=STREAM1; z < STREAMN; z++) 
1125     {
1126         //Int zD, zE, zX;
1127         Int zD, zX;
1129         zD = -1;        
1130         for (zX = DECODE1; zX < DECODEN; zX++) 
1131         {
1132            if (pP->streamsFromDecodes[zX] == z) 
1133            {
1134                zD = zX;
1135                break;
1136            }
1137         }
1139         TRACE_TERSE0("PAF_ASDT_initPhaseCommon: calling PAF_ALG_mallocMemory for common space.");
1140         if (PAF_ALG_mallocMemory (common[z], &pafAlgConfig)) 
1141         {
1142             TRACE_TERSE3("AS%d: %s.%d: PAF_ALG_mallocMemory failed", as+z, (IArg)__FUNCTION__, __LINE__);
1143             TRACE_TERSE3("AS%d: z: %d.  Size 0x%x", as+z, z, common[z][0].size);
1144             SW_BREAKPOINT;
1145             return __LINE__;
1146         }
1147         TRACE_TERSE3("alloced %d bytes from space %d at 0x%x", common[z]->size, common[z]->space, (IArg)common[z]->base);
1148         // share zone0 scratch with all zones 
1149         common[z][0].base=common[0][0].base;
1150         if (pP->fxns->commonPrint)
1151                 pP->fxns->commonPrint (common[z], &pafAlgConfig);
1153         //
1154         // Instantiate Decode Algorithms
1155         //
1156         if (zD >= 0) 
1157         {
1158             PAF_ASP_Chain *chain;
1159             TRACE_TERSE0("PAF_ASDT_initPhaseCommon: calling PAF_ASP_chainInit for decode.");
1160             chain =
1161                 PAF_ASP_chainInit (&pAstCfg->xDec[zD].decChainData, pP->pChainFxns,
1162                                    HEAP_INTERNAL, as+z, acp, &trace,
1163                                    decLinkInit[zD-DECODE1], NULL, common[z], &pafAlgConfig);
1164             if (!chain) 
1165             {
1166                 TRACE_TERSE1("PAF_ASDT_initPhaseCommon: AS%d: Decode chain initialization failed", as+z);
1167                 return __LINE__;
1168             }
1169         }
1171 #if 0 // FL: master
1172         pC->xStr[z].aspChain[0] = NULL;
1173         for (g=0; g < GEARS; g++) 
1174         {
1175             PAF_ASP_Chain *chain;
1176             TRACE_TERSE2("%s.%d: calling PAF_ASP_chainInit for ASPs.", (IArg)__FUNCTION__, __LINE__);
1177             chain =
1178                 PAF_ASP_chainInit (&pC->xStr[z].aspChainData[g], pP->pChainFxns,
1179                                    HEAP_INTERNAL, as+z, acp, &trace,
1180                                    aspLinkInit[z-STREAM1][g], pC->xStr[z].aspChain[0], common[z], &pafAlgConfig);
1181             if (! chain) 
1182             {
1183                 TRACE_TERSE2("AS%d: ASP chain %d initialization failed", as+z, g);
1184                 return __LINE__;
1185             }
1186             else
1187                 pC->xStr[z].aspChain[g] = chain;
1188         }
1189 #endif
1191     }
1192     TRACE_TERSE1("PAF_ASDT_initPhaseCommon: AS%d: Returning complete.", as+z);
1194     return 0;
1195 } //PAF_ASDT_initPhaseCommon
1197 // -----------------------------------------------------------------------------
1198 // AST Initialization Function - Algorithm Keys
1199 //
1200 //   Name:      PAF_AST_initPhaseAlgKey
1201 //   Purpose:   Audio Stream Task Function for initialization of data values
1202 //              from parameters for Algorithm Keys.
1203 //   From:      audioStream1Task or equivalent
1204 //   Uses:      See code.
1205 //   States:    x
1206 //   Return:    0.
1207 //   Trace:     Message Log "trace" in Debug Project Configuration reports:
1208 //              * State information as per parent.
1209 //
1210 // .............................................................................
1211 Int
1212 PAF_ASDT_initPhaseAlgKey(
1213     const PAF_ASDT_Params *pP, 
1214     const PAF_ASDT_Patchs *pQ, 
1215     PAF_ASDT_Config *pC
1218     PAF_AST_Config *pAstCfg;
1219     Int as;                     /* Audio Stream Number (1, 2, etc.) */
1220     Int z;                      /* decode/encode counter */
1221     Int s;                      /* key number */
1222     PAF_ASP_Link *that;
1224     (void)as;  // clear warning.
1226     pAstCfg = pC->pAstCfg; // get pointer to common (shared) configuration
1227     as = pAstCfg->as;
1228     
1229     TRACE_VERBOSE1("PAF_ASDT_initPhaseAlgKey: AS%d: initialization phase - Algorithm Keys", as);
1231     for (z=DECODE1; z < DECODEN; z++) 
1232     {
1233         for (s=0; s < pP->pDecAlgKey->length; s++) 
1234         {
1235             if ((pP->pDecAlgKey->code[s].full != 0)
1236                 && (that = PAF_ASP_chainFind (&pAstCfg->xDec[z].decChainData, pP->pDecAlgKey->code[s])))
1237             {
1238                 pAstCfg->xDec[z].decAlg[s] = (ALG_Handle )that->alg;
1239                     /* Cast in interface, for now --Kurt */
1240             }
1241             else
1242                 pAstCfg->xDec[z].decAlg[s] = NULL;
1243         }
1244     }
1246     return 0;
1247 } //PAF_AST_initPhaseAlgKey
1249 //   Purpose:   Audio Stream Decode Task Function for initialization of the Audio
1250 //              Frame(s) by memory allocation and loading of data pointers
1251 //              and values.
1252 Int
1253 PAF_ASDT_initFrame0(
1254     const PAF_ASDT_Params *pP, 
1255     const PAF_ASDT_Patchs *pQ, 
1256     PAF_ASDT_Config *pC, 
1257     Int z
1260     PAF_AST_Config *pAstCfg;
1261     Int as;                    /* Audio Stream Number (1, 2, etc.) */
1262     Int aLen;
1263     Int aSize = sizeof(PAF_AudioData);
1264     Int aAlign = aSize < sizeof (int) ? sizeof (int) : aSize;
1265     Int maxFrameLength = pP->maxFramelength;
1266     PAF_AudioData *aBuf=NULL;
1267     XDAS_UInt8 *metadataBuf;
1268     Error_Block    eb;
1269     PAF_AudioFrame *pAudioFrame;
1270     Int i;
1272     pAstCfg = pC->pAstCfg; // get pointer to common (shared) configuration
1273     as = pAstCfg->as;
1275     pAudioFrame = &gpDecAudioFrame[z];
1276     if (pAudioFrame == NULL)
1277     {
1278         SW_BREAKPOINT;
1279     }
1280     
1281     // Initialize error block
1282     Error_init(&eb); 
1283     
1284     //maxFrameLength += PA_MODULO - maxFrameLength % PA_MODULO; // compute maximum framelength (needed for ARC support)
1285     //aLen = numchan[z] * maxFrameLength;
1286     aLen = numchan[z] * maxFrameLength + (maxFrameLength - FRAMELENGTH); /* Qin - need additional memory for starting offset
1287                                                                                       See line 1301 */
1289     //
1290     // Initialize audio frame elements directly
1291     //
1292     pAudioFrame->fxns = pP->pAudioFrameFunctions;
1293     pAudioFrame->data.nChannels = PAF_MAXNUMCHAN;
1294     pAudioFrame->data.nSamples = FRAMELENGTH;
1295     pAudioFrame->data.sample = gDecAudioFrameChannelPointers;
1296     pAudioFrame->data.samsiz = gDecAudioFrameChannelSizes;
1297     pAudioFrame->pChannelConfigurationMaskTable = &PAF_ASP_stdCCMT;
1299     //
1300     // Allocate memory for and initialize pointers to audio data buffers
1301     //
1302     //   The NUMCHANMASK is used to identify the channels for which data
1303     //   buffers can be allocated. Using this mask and switch statement
1304     //   rather than some other construct allows efficient code generation,
1305     //   providing just the code necessary (with significant savings).
1306     //
1307     if (pP->fxns->bufMemPrint)
1308     {
1309         pP->fxns->bufMemPrint(z, aLen*aSize, HEAP_ID_FRMBUF, 2);
1310     }
1312     TRACE_TERSE1("PAF_ASDT_initFrame0: AS%d: Memory_calloc for audio buffers", as+z);
1313     
1314     if (aLen != 0)
1315     {
1316         if (!(aBuf = (PAF_AudioData *)Memory_calloc((IHeap_Handle)HEAP_FRMBUF, aLen*aSize, aAlign, &eb)))
1317         {
1318             TRACE_TERSE1("PAF_ASDT_initFrame0: AS%d: Memory_calloc failed", as+z);
1319             TRACE_TERSE2("  maxFrameLength: %d.  aLen*aSize: %d", maxFrameLength, aLen*aSize);
1320             SW_BREAKPOINT;
1321             return __LINE__;
1322         }
1323     }
1325     TRACE_TERSE3("  maxFrameLength: %d.  aLen*aSize: %d.  aBuf: 0x%x", maxFrameLength, aLen*aSize, (IArg)aBuf);
1327     TRACE_TERSE1("PAF_ASDT_initFrame0: AS%d: Memory_calloc for metadata buffers", as+z);
1328     if (!(metadataBuf = (XDAS_UInt8 *)Memory_calloc((IHeap_Handle)HEAP_MDBUF, pP->pMetadataBufStatus->bufSize*pP->pMetadataBufStatus->NumBuf, pP->pMetadataBufStatus->alignment, &eb)))
1329     {
1330         TRACE_TERSE1("PAF_ASDT_initFrame0: AS%d: Memory_calloc failed", as+z);
1331         TRACE_TERSE1("  bufSize*NumBuf: %d", pP->pMetadataBufStatus->bufSize*pP->pMetadataBufStatus->NumBuf);
1332         SW_BREAKPOINT;
1333         return __LINE__;
1334     }
1336     for (i=0; i < PAF_MAXNUMCHAN_AF; i++)
1337     {
1338         gDecAudioFrameChannelPointers[i] = NULL;
1339     }
1341     if ((numchan[z] > PAF_MAXNUMCHAN) || (numchan[z] < 1)) 
1342     {
1343         TRACE_TERSE1("PAF_ASDT_initFrame0: AS%d: unsupported option", as+z);
1344         return __LINE__;
1345     }
1346     else 
1347     {
1348         Int j = 0;
1349         TRACE_TERSE1("PAF_ASDT_initFrame0: AFChanPtrMap[%d][i]", numchan[z]);
1350         for (i=0; i<numchan[z]; i++)
1351         {
1352             Int8 chan = AFChanPtrMap[numchan[z]][i];
1353             if (chan != -1)
1354             {
1355                 gDecAudioFrameChannelPointers[chan] = aBuf + maxFrameLength*(j+1) - FRAMELENGTH;
1356                 j++;
1357                 TRACE_TERSE3("PAF_ASDT_initFrame0: chan = %d = AFChanPtrMap[%d][%d].", chan, numchan[z], i);
1358                 TRACE_TERSE2("PAF_ASDT_initFrame0: audioFrameChannelPointers[%d]: 0x%x", chan, (IArg)gDecAudioFrameChannelPointers[chan]);
1359             }
1360         }
1361     }
1363     // Initialize original audio frame channel pointers
1364     for (i=PAF_LEFT; i < PAF_MAXNUMCHAN_AF; i++) 
1365     {
1366         if (gDecAudioFrameChannelPointers[i])
1367         {
1368             gDecOrigAudioFrameChannelPointers[i] = gDecAudioFrameChannelPointers[i];
1369         }
1370     }
1372     //
1373     // Initialize meta data elements
1374     //
1375     pAudioFrame->pafBsMetadataUpdate = XDAS_FALSE;
1376     pAudioFrame->numPrivateMetadata = 0;
1377     pAudioFrame->bsMetadata_offset = 0;
1378     pAudioFrame->bsMetadata_type = PAF_bsMetadata_channelData;
1379     pAudioFrame->privateMetadataBufSize = pP->pMetadataBufStatus->bufSize;
1380     for (i=0; i<pP->pMetadataBufStatus->NumBuf; i++)
1381     {
1382         pAudioFrame->pafPrivateMetadata[i].offset = 0;
1383         pAudioFrame->pafPrivateMetadata[i].size = 0;
1384         pAudioFrame->pafPrivateMetadata[i].pMdBuf = metadataBuf + pP->pMetadataBufStatus->bufSize*i;
1385     }
1387     return 0;
1388 } //PAF_ASDT_initFrame0
1390 // -----------------------------------------------------------------------------
1391 // ASOT Initialization Function Helper - Reinitialization of Audio Frame
1392 // AST Decoding Function              - Reinitialization of Audio Frame
1393 //
1394 //   Name:      PAF_ASOT_initFrame1
1395 //   Purpose:   Audio Stream Task Function for initialization or reinitiali-
1396 //              zation of the Audio Frame(s) by loading of data values of a
1397 //              time-varying nature.
1398 //   From:      audioStream1Task or equivalent
1399 //              AST Parameter Function -> decodeInfo
1400 //              AST Parameter Function -> decodeDecode
1401 //   Uses:      See code.
1402 //   States:    x
1403 //   Return:    0.
1404 //   Trace:     None.
1405 //
1406 Int
1407 PAF_ASDT_initFrame1(
1408     const PAF_ASDT_Params *pP, 
1409     const PAF_ASDT_Patchs *pQ, 
1410     PAF_ASDT_Config *pC, 
1411     Int z, 
1412     Int apply
1415     PAF_AudioFrame *pAudioFrame;
1417     //
1418     // Reinitialize audio frame elements:
1419     //
1420     //   Channel Configurations during sys init                 = Unknown
1421     //      "          "        during info or decode           = None
1422     //
1423     //   Sample Rate / Count    during sys init, info or decode = Unknown / 0
1424     //
1426     pAudioFrame = &gpDecAudioFrame[z];
1428     if (apply < 0) 
1429     {
1430         pAudioFrame->channelConfigurationRequest.legacy = PAF_CC_UNKNOWN;
1431         pAudioFrame->channelConfigurationStream.legacy = PAF_CC_UNKNOWN;
1432     }
1433     else 
1434     {
1435         pAudioFrame->channelConfigurationRequest.legacy = PAF_CC_NONE;
1436         pAudioFrame->channelConfigurationStream.legacy = PAF_CC_NONE;
1437     }
1439     if (apply < 1) 
1440     {
1441         pAudioFrame->sampleRate = PAF_SAMPLERATE_UNKNOWN;
1442         pAudioFrame->sampleCount = 0;
1443     }
1445     return 0;
1446 } //PAF_ASDT_initFrame1
1448 // Reset AF, invoked during decode ACTIVATE (during state=INIT on Master)
1449 Int resetAf(
1450     const PAF_ASDT_Params *pP, 
1451     Int z, 
1452     Int sourceSelect
1455     PAF_AudioFrame *pAudioFrame;
1456     Int ch;
1457     Int i;
1459     // Get audio frame
1460     pAudioFrame = &gpDecAudioFrame[z];
1461     if (pAudioFrame == NULL)
1462     {
1463         SW_BREAKPOINT;
1464     }
1466     // Reinitialize audio frame elements
1467     pAudioFrame->channelConfigurationRequest.legacy = PAF_CC_NONE;
1468     pAudioFrame->channelConfigurationStream.legacy = PAF_CC_NONE;
1469     pAudioFrame->sampleRate = PAF_SAMPLERATE_UNKNOWN;
1470     pAudioFrame->sampleCount = 0;
1471     pAudioFrame->data.nChannels = PAF_MAXNUMCHAN;
1472     
1473     switch (sourceSelect)
1474     {
1475         case PAF_SOURCE_PCM:
1476             pAudioFrame->data.nSamples = FRAMELENGTH;
1477             break;
1478         case PAF_SOURCE_AC3:
1479         case PAF_SOURCE_DDP:
1480             pAudioFrame->data.nSamples = 1536;
1481             break;
1482         case PAF_SOURCE_THD:
1483             pAudioFrame->data.nSamples = 5120; //QIN FIX ME
1484             break;
1485         default:  
1486             pAudioFrame->data.nSamples = FRAMELENGTH;
1487             break;
1488     }
1490     // Reset audio frame channel pointers
1491     for (ch=PAF_LEFT; ch < PAF_MAXNUMCHAN_AF; ch++) 
1492     {
1493         if (gDecAudioFrameChannelPointers[ch])
1494         {
1495             gDecAudioFrameChannelPointers[ch] = gDecOrigAudioFrameChannelPointers[ch];
1496         }
1497     }
1498     
1499     // Reset audio frame meta data elements
1500     pAudioFrame->pafBsMetadataUpdate = XDAS_FALSE;
1501     pAudioFrame->numPrivateMetadata = 0;
1502     pAudioFrame->bsMetadata_offset = 0;
1503     pAudioFrame->bsMetadata_type = PAF_bsMetadata_channelData;
1504     for (i=0; i<pP->pMetadataBufStatus->NumBuf; i++)
1505     {
1506         pAudioFrame->pafPrivateMetadata[i].offset = 0;
1507         pAudioFrame->pafPrivateMetadata[i].size = 0;
1508     }
1509     
1510     return 0;
1513 // Reset AF samsiz, invoked during DECODE
1514 Int resetAfSamsiz(
1515     Int z
1518     PAF_AudioFrame *pAudioFrame;
1519     Int ch;
1520     
1521     // Get audio frame
1522     pAudioFrame = &gpDecAudioFrame[z];
1523     if (pAudioFrame == NULL)
1524     {
1525         SW_BREAKPOINT;
1526     }
1527     
1528     // Clear samsiz for all channels - MID 208.
1529     for (ch=0; ch < PAF_MAXNUMCHAN_AF; ch++) 
1530     {
1531         pAudioFrame->data.samsiz[ch] = 0;
1532     }
1534     return 0;