/* Copyright (c) 2018, Texas Instruments Incorporated - http://www.ti.com/ All rights reserved. * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the * distribution. * * Neither the name of Texas Instruments Incorporated nor the names of * its contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ /* * ======== audioStreamOutProc.c ======== */ #include #include #include "aspOutInitSync_master.h" #include "audioStreamProc_common.h" #include "audioStreamOutProc.h" #include "audioStreamOutInit.h" #include "audioStreamOutDec.h" #include "audioStreamOutIo.h" #include "common.h" //#include "pfp/pfp.h" //#include "pfp_app.h" /* contains all PFP ID's */ //Int32 gNumPfpAsot1=0; // debug // debug #include "evmc66x_gpio_dbg.h" //#include "ioConfig.h" // ----------------------------------------------------------------------------- // Debugging Trace Control, local to this file. // #include "logp.h" // Allow a developer to selectively enable tracing. #define CURRENT_TRACE_MASK 0x07 #define TRACE_MASK_TERSE 0x01 // only flag errors and show init #define TRACE_MASK_GENERAL 0x02 // half dozen lines per frame #define TRACE_MASK_VERBOSE 0x04 // trace full operation #if !(CURRENT_TRACE_MASK & TRACE_MASK_TERSE) #undef TRACE_TERSE0 #undef TRACE_TERSE1 #undef TRACE_TERSE2 #undef TRACE_TERSE3 #undef TRACE_TERSE4 #define TRACE_TERSE0(a) #define TRACE_TERSE1(a,b) #define TRACE_TERSE2(a,b,c) #define TRACE_TERSE3(a,b,c,d) #define TRACE_TERSE4(a,b,c,d,e) #endif #if !(CURRENT_TRACE_MASK & TRACE_MASK_GENERAL) #undef TRACE_GEN0 #undef TRACE_GEN1 #undef TRACE_GEN2 #undef TRACE_GEN3 #undef TRACE_GEN4 #define TRACE_GEN0(a) #define TRACE_GEN1(a,b) #define TRACE_GEN2(a,b,c) #define TRACE_GEN3(a,b,c,d) #define TRACE_GEN4(a,b,c,d,e) #endif #if !(CURRENT_TRACE_MASK & TRACE_MASK_VERBOSE) #undef TRACE_VERBOSE0 #undef TRACE_VERBOSE1 #undef TRACE_VERBOSE2 #undef TRACE_VERBOSE3 #undef TRACE_VERBOSE4 #define TRACE_VERBOSE0(a) #define TRACE_VERBOSE1(a,b) #define TRACE_VERBOSE2(a,b,c) #define TRACE_VERBOSE3(a,b,c,d) #define TRACE_VERBOSE4(a,b,c,d,e) #endif // ----------------------------------------------------------------------------- // // Audio Stream Output Task definitions // #define __TASK_NAME__ "TaskAsop" // status codes // ASOT FSM #define ASOP_SOK_INITSYNC_NOTREADY ( 1 ) // ok, init-sync not ready #define ASOP_SOK ( 0 ) // ok #define ASOP_ERR_FORWARD_ERR ( -1 ) // error, forward (ASIT) error #define ASOP_ERR_RESETOUTPROC_NOOUTDEVSEL ( -2 ) // error, reset dec out proc, no output device selected #define ASOP_ERR_PROCDECOUT_OUTDEVSELUPD ( -3 ) // error, proc dec out, output device select updated #define ASOP_ERR_PROCDECOUT_IOPHYXFERCOMPLETE ( -4 ) // error, proc dec out, io phy transfer complete #define ASOP_ERR_PROCDECOUT_CHKOUTDEVSELUPD ( -5 ) // error, proc dec out, check output device select update // ----------------------------------------------------------------------------- // ASOT FSM states enum { ASOT_STATE_SEL_OUT_DEV, ASOT_STATE_RESET_OUT_PROC, ASOT_STATE_INITSYNC_DEC_INFO1, ASOT_STATE_INITSYNC_DEC_DECODE1, ASOT_STATE_PROC_DEC_OUT, ASOT_STATE_RESEL_OUT_DEV, ASOT_STATE_INITSYNC_RESYNC }; // Check if Output device selected static Int checkOutDevSel( PAF_AST_IoOut *pOut, Bool *pOutDevSel); // Check if any Output device selected static Int checkAnyOutDevSel( const PAF_ASOT_Params *pP, PAF_AST_IoOut *pOut, Bool *pOutDevSel); // ASOT SM function // Purpose: Audio Stream Output Task Function for selecting the devices used // for output. static Int PAF_ASOT_selectDevices( const PAF_ASOT_Params *pP, const PAF_ASOT_Patchs *pQ, PAF_ASOT_Config *pAsotCfg, Bool *pOutDevSel ); // Reset audio frame pointers to original values static Void resetAfPointers( const PAF_ASOT_Params *pP, PAF_AST_Stream *xStr ); // Reset audio frame meta data elements static Void resetAfMetadata( const PAF_ASOT_Params *pP, PAF_AST_Stream *xStr ); // Reset audio frames static Void resetAfs( const PAF_ASOT_Params *pP, PAF_AST_Stream *xStr ); // used by new OutProc.c, will be changed back to static once refactoring is done // Purpose: Init-Sync Dec Reset state function. // Performs Dec Reset Init-Sync. static Int PAF_ASOT_initSyncDecReset( const PAF_ASOT_Params *pP, const PAF_ASOT_Patchs *pQ, PAF_ASOT_Config *pAsotCfg, PAF_AudioFrame *pDecResetAf, Int frame ); // ASOT SM function // Reset Decoder Output processing static Int PAF_ASOT_resetDecOutProc( const PAF_ASOT_Params *pP, const PAF_ASOT_Patchs *pQ, PAF_ASOT_Config *pAsotCfg, PAF_AudioFrame *pDecResetAf, Bool outDevSel, Int frame ); // ASOT SM function // Purpose: Init-Sync Dec Info1 state function. // Performs Dec Info1 Init-Sync. static Int PAF_ASOT_initSyncDecInfo1( const PAF_ASOT_Params *pP, const PAF_ASOT_Patchs *pQ, PAF_ASOT_Config *pAsotCfg, PAF_AudioFrame *pDecInfo1Af, Int frame ); // ASOT SM function // Purpose: Init-Sync Dec Decode1 state function. // Performs Dec Decode1 Init-Sync. static Int PAF_ASOT_initSyncDecDecode1( const PAF_ASOT_Params *pP, const PAF_ASOT_Patchs *pQ, PAF_ASOT_Config *pAsotCfg, Int frame ); // ASOT SM function // Process Decoder output audio data static Int PAF_ASOT_procDecOut( const PAF_ASOT_Params *pP, const PAF_ASOT_Patchs *pQ, PAF_ASOT_Config *pAsotCfg, Bool *pFirstTime, Int frame ); // ASOT SM function // Purpose: Init-Sync Re-Sync state function. // Performs Init-Sync using stored Dec Reset/Info1 AFs. static Int PAF_ASOT_initSyncResync( const PAF_ASOT_Params *pP, const PAF_ASOT_Patchs *pQ, PAF_ASOT_Config *pAsotCfg, PAF_AudioFrame *pDecResetAf, PAF_AudioFrame *pDecInfo1Af, Int frame ); static Int asopDecOutProcEncodeWrap( const PAF_ASOT_Params *pP, const PAF_ASOT_Patchs *pQ, PAF_ASOT_Config *pAsotCfg, Int frame, Int zO ); // ASOT SM function // Purpose: Re-select devices used for Output. // Performs Init-Sync using stored Dec Reset/Info1 AFs. static Int PAF_ASOT_reselectDevices( const PAF_ASOT_Params *pP, const PAF_ASOT_Patchs *pQ, PAF_ASOT_Config *pAsotCfg, PAF_AudioFrame *pDecResetAf, PAF_AudioFrame *pDecInfo1Af, Int frame, Bool *pOutDevSel ); // FL: debug, allow modification of Output frame length via JTAG. Int16 gOutFrameLen=PAF_ASOT_FRAMELENGTH; // output frame length (PCM samples) // ASOT configuration #pragma DATA_SECTION(gPAF_ASOT_config, ".globalSectionPafAsotConfig") PAF_ASOT_Config gPAF_ASOT_config = { NULL, // taskHandle 0, // asotState NULL, // acp 0,0,0, // cbDrainedFlag (size DECODE_MAXN) &gPAF_ASPM_config, // pAspmCfg &gPAF_AST_config // pAstCfg }; // ASOT event handle - to put in structure Event_Handle gAsotEvtHandle; extern Int d10Initialized; // For writeDECCommandRestart extern volatile UInt32 gCommandOutputTask_SYNC; extern volatile UInt32 gCommandOutputTask_ACK; LINNO_DEFN(TaskAsop); // Line number macros ERRNO_DEFN(TaskAsop); // Error number macros #define ASOP_DEBUG #ifdef ASOP_DEBUG Int asopLoopCount; #endif // Debug event-in-state counters UInt32 gSelOutDevState_EvtWakeTimer_cnt = 0; // Select Output state, Wake Timer event count UInt32 gSelOutDevState_EvtTxMcaspEdma_invCnt = 0; // Select Output state, invalid Tx McASP EDMA event count UInt32 gSelOutDevState_Evt_invCnt = 0; // Select Output state, invalid other event count UInt32 gResetOutProcState_EvtWakeTimer_cnt = 0; // Select Output state, Wake Timer event count UInt32 gResetOutProcState_EvtTxMcaspEdma_invCnt = 0; // Reset Output Processing state, invalid Tx McASP EDMA event count UInt32 gResetOutProcState_Evt_invCnt = 0; // Reset Output Processing state, invalid other event count UInt32 gInitSyncDecInfo1State_EvtWakeTimer_cnt = 0; // Init-Sync Dec Info1 state, Wake Timer event count UInt32 gInitSyncDecInfo1State_EvtTxMcaspEdma_invCnt = 0; // Init-Sync Dec Info1 state, invalid Tx McASP EDMA event count UInt32 gInitSyncDecInfo1State_Evt_invCnt = 0; // Init-Sync Dec Info1 state, invalid other event count UInt32 gInitSyncDecDecode1State_EvtWakeTimer_cnt = 0; // Init-Sync Dec Decode1 state, Wake Timer event count UInt32 gInitSyncDecDecode1State_EvtTxMcaspEdma_invCnt = 0; // Init-Sync Dec Decode1 state, invalid Tx McASP EDMA event count UInt32 gInitSyncDecDecode1State_Evt_invCnt = 0; // Init-Sync Dec Decode1 state, invalid other event count UInt32 gProcDecOutState_EvtWakeTimer_cnt = 0; // Process Output state, Wake Timer event count UInt32 gProcDecOutState_EvtTxMcaspEdma_cnt = 0; // Process Output state, Tx McASP EDMA event count UInt32 gProcDecOutState_Evt_invCnt = 0; // Process Output state, invalid other event count UInt32 gReselOutDevState_EvtWakeTimer_cnt = 0; // Process Output state, Wake Timer event count UInt32 gReselOutDevState_EvtTxMcaspEdma_invCnt = 0; // Re-select Output state, invalid other event count UInt32 gReselOutDevState_Evt_invCnt = 0; // Re-select Output state, invalid other event count // Debug state counters UInt32 gAsotInitSyncResyncState_Cnt = 0; // Init-Sync Re-sync (Local error) state execution count UInt32 gAsotInvState_Cnt = 0; // invalid state count /* * ======== taskAsopFxn ======== * Audio Stream Output Processing task function */ Void taskAsopFxn( const PAF_ASOT_Params *pP, const PAF_ASOT_Patchs *pQ ) { PAF_ASOT_Config *pAsotCfg; // ASOT configuration pointer PAF_AST_Config *pAstCfg; // Common (shared) configuration pointer Int as; // Audio Stream Number (1, 2, etc.) Int z; // input/encode/stream/decode/output counter Bool outDevSel; // whether output device selected PAF_AudioFrame decResetAf; PAF_AudioFrame decInfo1Af; UInt events; // latched event flags Bool procEvents; // process events flags Bool procOutFirstTime; // first time process output flag Int asopFrameCount; // frame counter Int status; // status code #ifndef ASOP_DEBUG Int asopLoopCount; // debug, ASOT loop counter #endif Log_info0("Enter taskAsopFxn()"); taskAsopFxnInit(pP, pQ); // initialization of output task // // Audio Stream Output Task Configuration (*pAsotCfg): // pAsotCfg = &gPAF_ASOT_config; // initialize pointer to task configuration pAstCfg = pAsotCfg->pAstCfg; // get pointer to AST common (shared) configuration as = pAstCfg->as; // obtain Audio Stream Number (1, 2, etc.) // // Main processing loop // for (z=STREAM1; z < STREAMN; z++) { TRACE_VERBOSE1("TaskAsop: AS%d: running", as+z); } pAsotCfg->state = ASOT_STATE_SEL_OUT_DEV; // init state procEvents = TRUE; // init proc events flag procOutFirstTime = TRUE; // init first time process output flag asopFrameCount = 0; // init frame counter TBD asopLoopCount = 0; // loop counter for (;;) { // Pend for next event // Evt_Id_AsotWakeTimer : Wakeup timer (poll for Output device selection) // Evt_Id_AsotTxMcaspEdma : Tx McASP EDMA completion if (procEvents == TRUE) { events = Event_pend(gAsotEvtHandle, Event_Id_NONE, (Evt_Id_AsotWakeTimer + Evt_Id_AsotTxMcaspEdma), BIOS_WAIT_FOREVER); } asopLoopCount++; //TRACE_GEN1("TaskAsop (begin Main loop %d)", asopLoopCount); switch (pAsotCfg->state) { // // Select Output Device state // case ASOT_STATE_SEL_OUT_DEV: if (events & Evt_Id_AsotWakeTimer) { gSelOutDevState_EvtWakeTimer_cnt++; events &= ~Evt_Id_AsotWakeTimer; // clear event // Select Output devices // outDevSel==TRUE if Output device selection successful status = PAF_ASOT_selectDevices(pP, pQ, pAsotCfg, &outDevSel); if (status < 0) { // FL, New IO: //Tx status==error message to ASIT; // ASOT initiated message to ASIT, "backward" error // No explicit handling of Select Output Device error, so stay in state and try again pAsotCfg->state = ASOT_STATE_SEL_OUT_DEV; break; } else if (outDevSel == TRUE) { // Select successful pAsotCfg->state = ASOT_STATE_RESET_OUT_PROC; } else { // No output device selected (outDevSel == FALSE). // Remain in current state. ; } } // Check for unexpected Tx McASP EDMA event if (events & Evt_Id_AsotTxMcaspEdma) { gSelOutDevState_EvtTxMcaspEdma_invCnt++; // log invalid event count in state TRACE_TERSE2("TaskAsop: invalid Tx McASP EDMA event, state=%u, events=%u", pAsotCfg->state, events); events &= ~Evt_Id_AsotTxMcaspEdma; // clear event } // Check for any other unexpected events if (events != 0) { gSelOutDevState_Evt_invCnt++; // log invalid event count in state TRACE_TERSE2("TaskAsop: invalid events, state=%u, events=%u", pAsotCfg->state, events); events &= ~events; // clear events } break; // FL, New IO: currently using timer event // // Reset Output Processing state // case ASOT_STATE_RESET_OUT_PROC: if (events & Evt_Id_AsotWakeTimer) { gResetOutProcState_EvtWakeTimer_cnt++; events &= ~Evt_Id_AsotWakeTimer; // clear event // // Allow Output device re-selection prior to Output processing. // Output device selection has already been performed in state==ASOT_STATE_SEL_OUT_DEV. // Output device can be re-selected via alpha commands before streaming is initiated. // Here check whether this has occurred. // // Select Output devices // outDevSel==TRUE if Output device selection successful status = PAF_ASOT_selectDevices(pP, pQ, pAsotCfg, &outDevSel); if (status < 0) { // FL, New IO: //Tx status==error message to ASIT; // ASOT initiated message to ASIT, "backward" error // Starting over with Output device selection in case of error pAsotCfg->state = ASOT_STATE_SEL_OUT_DEV; break; } // Reset Output processing status = PAF_ASOT_resetDecOutProc(pP, pQ, pAsotCfg, &decResetAf, outDevSel, asopFrameCount); if (status < 0) { // FL, New IO: //Tx status==error message to ASDT; // feedback message ASOT -> ASDT pAsotCfg->state = ASOT_STATE_SEL_OUT_DEV; // starting over with Output device selection in case of error break; } else if (status == ASOP_SOK_INITSYNC_NOTREADY) { // FL, New IO: this is only necessary for Wake Timer, POLLING Init-Sync // FL, New IO: can be removed once Rx ASDT messages are implemented for Init-Sync // Dec Reset Init-Sync not ready. // Remain in current state. ; } else { // FL, New IO: //Tx status==ok message to ASDT; // feedback message ASOT -> ASDT pAsotCfg->state = ASOT_STATE_INITSYNC_DEC_INFO1; } } // Check for unexpected Tx McASP EDMA event if (events & Evt_Id_AsotTxMcaspEdma) { gResetOutProcState_EvtTxMcaspEdma_invCnt++; // log invalid event count in state TRACE_TERSE2("TaskAsop: Tx McASP EDMA event, state=%u, events=%u", pAsotCfg->state, events); events &= ~Evt_Id_AsotTxMcaspEdma; // clear event } // Check for any other unexpected events if (events != 0) { gResetOutProcState_Evt_invCnt++; // log invalid event count in state TRACE_TERSE2("TaskAsop: invalid events, state=%u, events=%u", pAsotCfg->state, events); events &= ~events; // clear events } break; // FL, New IO: currently using timer event // // Init-Sync Info1 state // case ASOT_STATE_INITSYNC_DEC_INFO1: if (events & Evt_Id_AsotWakeTimer) { gInitSyncDecInfo1State_EvtWakeTimer_cnt++; events &= ~Evt_Id_AsotWakeTimer; // clear event status = PAF_ASOT_initSyncDecInfo1(pP, pQ, pAsotCfg, &decInfo1Af, asopFrameCount); if (status < 0) { // FL, New IO: //Tx status==error message to ASDT; // feedback message ASOT -> ASDT pAsotCfg->state = ASOT_STATE_SEL_OUT_DEV; // starting over with Output device selection in case of error break; } else if (status == ASOP_SOK_INITSYNC_NOTREADY) { // FL, New IO: this is only necessary for Wake Timer, POLLING Init-Sync // FL, New IO: can be removed once Rx ASDT messages are implemented for Init-Sync // Dec Reset Init-Sync not ready. // Remain in current state. ; } else { // FL, New IO: //Tx status==ok message to ASDT; // feedback message ASOT -> ASDT pAsotCfg->state = ASOT_STATE_INITSYNC_DEC_DECODE1; } } // Check for unexpected Tx McASP EDMA event if (events & Evt_Id_AsotTxMcaspEdma) { gInitSyncDecInfo1State_EvtTxMcaspEdma_invCnt++; // log invalid event count in state TRACE_TERSE2("TaskAsop: Tx McASP EDMA event, state=%u, events=%u", pAsotCfg->state, events); events &= ~Evt_Id_AsotTxMcaspEdma; // clear event } // Check for any other unexpected events if (events != 0) { gInitSyncDecInfo1State_Evt_invCnt++; // log invalid event count in state TRACE_TERSE2("TaskAsop: invalid events, state=%u, events=%u", pAsotCfg->state, events); events &= ~events; // clear events } break; // FL, New IO: currently using timer event // // Init-Sync Decode1 state // case ASOT_STATE_INITSYNC_DEC_DECODE1: if (events & Evt_Id_AsotWakeTimer) { gInitSyncDecDecode1State_EvtWakeTimer_cnt++; events &= ~Evt_Id_AsotWakeTimer; // clear event status = PAF_ASOT_initSyncDecDecode1(pP, pQ, pAsotCfg, asopFrameCount); if (status < 0) { // FL, New IO: //Tx status==error message to ASDT; // feedback message ASOT -> ASDT pAsotCfg->state = ASOT_STATE_SEL_OUT_DEV; // starting over with Output device selection in case of error break; } else if (status == ASOP_SOK_INITSYNC_NOTREADY) { // FL, New IO: this is only necessary for Wake Timer, POLLING Init-Sync // FL, New IO: can be removed once Rx ASDT messages are implemented for Init-Sync // Dec Reset Init-Sync not ready. // Remain in current state. ; } else { // FL, New IO: //Tx status==ok message to ASDT; // feedback message ASOT -> ASDT pAsotCfg->state = ASOT_STATE_PROC_DEC_OUT; procOutFirstTime = TRUE; } } // Check for unexpected Tx McASP EDMA event if (events & Evt_Id_AsotTxMcaspEdma) { gInitSyncDecDecode1State_EvtTxMcaspEdma_invCnt++; // log invalid event count in state TRACE_TERSE2("TaskAsop: Tx McASP EDMA event, state=%u, events=%u", pAsotCfg->state, events); events &= ~Evt_Id_AsotTxMcaspEdma; // clear event } // Check for any other unexpected events if (events != 0) { gInitSyncDecDecode1State_Evt_invCnt++; // log invalid event count in state TRACE_TERSE2("TaskAsop: invalid events, state=%u, events=%u", pAsotCfg->state, events); events &= ~events; // clear events } break; // // Process Decoder Output state // case ASOT_STATE_PROC_DEC_OUT: if (events & Evt_Id_AsotTxMcaspEdma) { gProcDecOutState_EvtTxMcaspEdma_cnt++; events &= ~Evt_Id_AsotTxMcaspEdma; // clear event #if 1 // (***) FL: shows timing of Output (Tx McASP EDMA) // (***) debug // B8 { static Uint8 toggleState = 0; if (toggleState == 0) GPIOSetOutput(GPIO_PORT_0, GPIO_PIN_106); else GPIOClearOutput(GPIO_PORT_0, GPIO_PIN_106); toggleState = ~(toggleState); } #endif // Process Output status = PAF_ASOT_procDecOut(pP, pQ, pAsotCfg, &procOutFirstTime, asopFrameCount); if (status < 0) { if (status == ASOP_DOP_ERR_FINALTEST_CBDRAINED) { // normal completion, CB drained @ EOS pAsotCfg->state = ASOT_STATE_SEL_OUT_DEV; break; } else if (status == ASOP_ERR_PROCDECOUT_OUTDEVSELUPD) { // Output re-select pAsotCfg->state = ASOT_STATE_RESEL_OUT_DEV; break; } // FL, New IO: "backward" error handling. // Currently all errors handled locally. else { // Handle ASOT "local" errors pAsotCfg->state = ASOT_STATE_INITSYNC_RESYNC; procEvents = FALSE; break; } } } // Check for Wakeup Timer event. // Wakeup Timer events are allowed to occur, but no processing is // performed in response to such an event. if (events & Evt_Id_AsotWakeTimer) { events &= ~Evt_Id_AsotWakeTimer; // clear event gProcDecOutState_EvtWakeTimer_cnt++; // log event count in state } // Check for any other unexpected events if (events != 0) { gProcDecOutState_Evt_invCnt++; // log invalid event count in state TRACE_TERSE2("TaskAsop: invalid events, state=%u, events=%u", pAsotCfg->state, events); events &= ~events; // clear events } break; // // Re-Select Output Device state // case ASOT_STATE_RESEL_OUT_DEV: if (events & Evt_Id_AsotWakeTimer) { gReselOutDevState_EvtWakeTimer_cnt++; events &= ~Evt_Id_AsotWakeTimer; // clear event status = PAF_ASOT_reselectDevices(pP, pQ, pAsotCfg, &decResetAf, &decInfo1Af, asopFrameCount, &outDevSel); if (status < 0) { // FL, New IO: //Tx status==error message to ASIT; // ASOT initiated message to ASIT, "backward" error pAsotCfg->state = ASOT_STATE_SEL_OUT_DEV; // starting over with Output device selection in case of error break; } else if (outDevSel == TRUE) { // Re-select successful pAsotCfg->state = ASOT_STATE_PROC_DEC_OUT; procOutFirstTime = TRUE; } else { // No output device selected (outDevSel == FALSE). // Remain in current state. ; } } // Check for unexpected Tx McASP EDMA event if (events & Evt_Id_AsotTxMcaspEdma) { events &= ~Evt_Id_AsotTxMcaspEdma; // clear event gReselOutDevState_EvtTxMcaspEdma_invCnt++; // log invalid event count in state } // Check for any other unexpected events if (events != 0) { gReselOutDevState_Evt_invCnt++; // log invalid event count in state TRACE_TERSE2("TaskAsop: invalid events, state=%u, events=%u", pAsotCfg->state, events); events &= ~events; // clear events } break; // // Init-Sync Re-sync (Process Output Local Error) state // case ASOT_STATE_INITSYNC_RESYNC: // not event driven state gAsotInitSyncResyncState_Cnt++; status = PAF_ASOT_initSyncResync(pP, pQ, pAsotCfg, &decResetAf, &decInfo1Af, asopFrameCount); if (status < 0) { // FL, New IO: //Tx status==error message to ASIT; // ASIT initiated message to ASOT, "backward" error pAsotCfg->state = ASOT_STATE_SEL_OUT_DEV; // starting over with Output device selection in case of error procEvents = TRUE; break; } else { pAsotCfg->state = ASOT_STATE_PROC_DEC_OUT; procEvents = TRUE; procOutFirstTime = TRUE; } break; default: gAsotInvState_Cnt++; TRACE_TERSE1("TaskAsop: invalid state, state=%u", pAsotCfg->state); break; } // FL, New IO: handle ASIT messages separately in each state // FL, New IO: proper SM clean up can be skipped if forward error / DEC restart is handled in this way // // Check forward (ASIT) error, TBD // // Check writeDECCommandRestart, TBD if (gCommandOutputTask_SYNC) { TRACE_TERSE0("TaskAsop: ack writeDECCommandRestart ... Wait for command de-assert"); gCommandOutputTask_ACK = 1; while (gCommandOutputTask_SYNC) { Event_pend(gAsotEvtHandle, Event_Id_NONE, Evt_Id_AsotWakeTimer, BIOS_WAIT_FOREVER); } TRACE_TERSE0("TaskAsop: ack for writeDECCommandRestart ... Sync-ed! Re-start the process"); pAsotCfg->state = ASOT_STATE_SEL_OUT_DEV; // init state -- start over status = ASOP_ERR_FORWARD_ERR; // set status -- force flushing of output device } // any error forces idling of output if (status < 0) { for (z=OUTPUT1; z < OUTPUTN; z++) { //if (pAstCfg->xOut[z].hTxSio) if (pAsotCfg->pIoOut[z].hIoPhy) { //SIO_idle(pAstCfg->xOut[z].hTxSio); JX TO DO: implement proper error handling } } TRACE_TERSE1("TaskAsop: Trace stopped at loop %d.", asopLoopCount); //ERRNO_RPRT(TaskAsop, errno); } } // End of main processing loop for (;;) } /* taskAsopFxn */ // ASOT wake timer (clock) function Void clkAsotFxn(Void) { Event_post(gAsotEvtHandle, Evt_Id_AsotWakeTimer); } void asopMcaspCallback(void* arg, MCASP_Packet *mcasp_packet) { /* post semaphore */ if(mcasp_packet->arg == IOPHY_XFER_FINAL) { //Semaphore_post(asopSemTx); Event_post(gAsotEvtHandle, Evt_Id_AsotTxMcaspEdma); } else { ; // intermediate packet due to buffer wrapping around } } // Reset audio frame pointers to original values static Void resetAfPointers( const PAF_ASOT_Params *pP, PAF_AST_Stream *xStr ) { Int z; Int ch; // Reset audio frame pointers to original values for (z = STREAM1; z < STREAMN; z++) { for (ch = PAF_LEFT; ch < PAF_MAXNUMCHAN_AF; ch++) { if (xStr[z].audioFrameChannelPointers[ch]) { xStr[z].audioFrameChannelPointers[ch] = xStr[z].origAudioFrameChannelPointers[ch]; } } } } // Check if Output device selected static Int checkOutDevSel( PAF_AST_IoOut *pOut, Bool *pOutDevSel ) { *pOutDevSel = (Bool)(pOut->hMcaspChan != NULL); return ASOP_SOK; } // Check if any Output device selected static Int checkAnyOutDevSel( const PAF_ASOT_Params *pP, PAF_AST_IoOut *pOut, Bool *pOutDevSel ) { Bool outDevSel; Int z; outDevSel = FALSE; for (z=OUTPUT1; z < OUTPUTN; z++) { if (pOut[z].hMcaspChan) { outDevSel = TRUE; break; } } *pOutDevSel = outDevSel; return ASOP_SOK; } // ASOT SM function // ----------------------------------------------------------------------------- // ASOT Selection Function - Output Device Selection // // Name: PAF_ASOT_selectDevices // Purpose: Audio Stream Output Task Function for selecting the devices used // for output. // static Int PAF_ASOT_selectDevices( const PAF_ASOT_Params *pP, const PAF_ASOT_Patchs *pQ, PAF_ASOT_Config *pAsotCfg, Bool *pOutDevSel ) { PAF_AST_Config *pAstCfg; // Common (shared) configuration pointer Int z; Int zS, zO; Int device; Int status; Bool ioPhyInit; pAstCfg = pAsotCfg->pAstCfg; // get pointer to AST common (shared) configuration // Find first Output associated with Master Stream zO = OUTPUT1; for (z=ENCODE1; z < ENCODEN; z++) { zS = pP->streamsFromEncodes[z]; // get Stream associated with Encoder if (zS == pAstCfg->masterStr) { // This Encoder is associated with Master Stream. // Note other Encoder can also be associated with Master Stream. zO = pP->outputsFromEncodes[z]; // get Output associated with Encoder } } ioPhyInit = asopIoPhyCheckInit(); // check if IO Phy is initialized device = pAstCfg->xOut[zO].outBufStatus.sioSelect; // obtain SIO select for Output if ((ioPhyInit == TRUE) && (device >= 0)) { // check for valid index into device array if (device >= pQ->devout->n) // DEVOUT_N { device = 0; // treat as device None } if (device > 0) { // Select Output Devices // FL, New IO: Placeholder function, this will be reorganized moving forward. // FL, New IO: API for single Output. // FL, New IO: Doesn't (re-)configure Output driver. status = asopSelectDevices(pQ->devout->x[device]->sio.pConfig, &pAsotCfg->pIoOut[zO]); if (status < 0) { pAstCfg->xOut[zO].outBufStatus.sioSelect = 0x80; *pOutDevSel = FALSE; return status; } // Reset IO Buff & IO Phy // FL, New IO: API for single Output status = asopIoCompsInit(&pAstCfg->xOut[zO], &pAsotCfg->pIoOut[zO]); if (status < 0) { pAstCfg->xOut[zO].outBufStatus.sioSelect = 0x80; *pOutDevSel = FALSE; return status; } } pAstCfg->xOut[zO].outBufStatus.sioSelect = device | 0x80; } // Check if Output device selected // FL, New IO: API for single Output status = checkOutDevSel(&pAsotCfg->pIoOut[zO], pOutDevSel); if (status < 0) { *pOutDevSel = FALSE; return status; } return ASOP_SOK; } // ASOT SM function // Wake Timer + *POLLING* version. // No explicit Rx ASDT message event from ASDT. // ASOT wakes on Wake Timer event and polls for flag set. // Reset Decoder Output processing static Int PAF_ASOT_resetDecOutProc( const PAF_ASOT_Params *pP, const PAF_ASOT_Patchs *pQ, PAF_ASOT_Config *pAsotCfg, PAF_AudioFrame *pDecResetAf, Bool outDevSel, Int frame ) { Int status; if (outDevSel == FALSE) { // // Rx Dec Out-IS message before Output selected. // Decoder is producing output, but no Output selected. // return ASOP_ERR_RESETOUTPROC_NOOUTDEVSEL; } // Perform Dec Reset Init-Sync status = PAF_ASOT_initSyncDecReset(pP, pQ, pAsotCfg, pDecResetAf, frame); return status; } // Reset audio frame meta data elements static Void resetAfMetadata( const PAF_ASOT_Params *pP, PAF_AST_Stream *xStr ) { Int z; Int i; for (z = STREAM1; z < STREAMN; z++) { xStr[z].pAudioFrame->pafBsMetadataUpdate = XDAS_FALSE; xStr[z].pAudioFrame->numPrivateMetadata = 0; xStr[z].pAudioFrame->bsMetadata_offset = 0; xStr[z].pAudioFrame->bsMetadata_type = PAF_bsMetadata_channelData; for (i = 0; i < pP->pMetadataBufStatus->NumBuf; i++) { xStr[z].pAudioFrame->pafPrivateMetadata[i].offset = 0; xStr[z].pAudioFrame->pafPrivateMetadata[i].size = 0; } } } // Reset audio frames static Void resetAfs( const PAF_ASOT_Params *pP, PAF_AST_Stream *xStr ) { // Reset audio frame pointers to original values // (may be needed if error occurred). resetAfPointers(pP, xStr); // Reset audio frame meta data elements resetAfMetadata(pP, xStr); } // Purpose: Performs Dec Reset Init-Sync. //static Int PAF_ASOT_initSyncDecReset( // used by new OutProc.c, will be changed back to static once refactoring is done static Int PAF_ASOT_initSyncDecReset( const PAF_ASOT_Params *pP, const PAF_ASOT_Patchs *pQ, PAF_ASOT_Config *pAsotCfg, PAF_AudioFrame *pDecResetAf, Int frame ) { PAF_AST_Config *pAstCfg; // ASIT/ASOT/ASDT shared configuration Int zMD, zMS; // Dec and Stream Master indices PAF_AudioFrame *pStrAf; // stream audio frame PAF_AST_OutInitSyncCtl *pOutIsCtl; // Output Init-Sync control Int8 decFlag; // dec stage flag Int status; // status code pAstCfg = pAsotCfg->pAstCfg; zMD = pAstCfg->masterDec; pOutIsCtl = &pAsotCfg->pAspmCfg->outIsCtl; // check for Dec Reset // store dec reset AF status = outIsReadDecStageFlagAndAf(pOutIsCtl, zMD, ASP_OUTIS_DEC_STAGE_RESET_IDX, &decFlag, pDecResetAf); if (status < 0) { return status; } if (decFlag == 0) { return ASOP_SOK_INITSYNC_NOTREADY; } else { zMS = pAstCfg->masterStr; pStrAf = pAstCfg->xStr[zMS].pAudioFrame; // Reset audio frames // FL, New IO: API for multiple streams. resetAfs(pP, pAstCfg->xStr); // Update Stream Audio Frame. // Copy Dec Reset AF to Stream AF. // FL, New IO: Only Master zone (single) stream handled. outIsCpyAf(pDecResetAf, pStrAf); // Enc activate // Enc reset status = asopDecOutProcReset(pP, pQ, pAsotCfg, frame); if (status < 0) { return status; } return ASOP_SOK; } } // ASOT SM function // Purpose: Init-Sync Dec Info1 state function. // Wake Timer + *POLLING* version. // No explicit Rx ASDT message event from ASDT. // ASOT wakes on Wake Timer event and polls for flag set. static Int PAF_ASOT_initSyncDecInfo1( const PAF_ASOT_Params *pP, const PAF_ASOT_Patchs *pQ, PAF_ASOT_Config *pAsotCfg, PAF_AudioFrame *pDecInfo1Af, Int frame ) { PAF_AST_Config *pAstCfg; // ASIT/ASOT/ASDT shared configuration Int zMD, zMS; // Dec and Stream Master indices PAF_AudioFrame *pStrAf; // stream audio frame PAF_AST_OutInitSyncCtl *pOutIsCtl; // Output Init-Sync control Int8 decFlag; // dec stage flag Int status; // status code pAstCfg = pAsotCfg->pAstCfg; zMD = pAstCfg->masterDec; pOutIsCtl = &pAsotCfg->pAspmCfg->outIsCtl; // Check for Dec Reset, // Store dec reset AF status = outIsReadDecStageFlagAndAf(pOutIsCtl, zMD, ASP_OUTIS_DEC_STAGE_INFO1_IDX, &decFlag, pDecInfo1Af); if (status < 0) { return status; } if (decFlag == 0) { return ASOP_SOK_INITSYNC_NOTREADY; } else { zMS = pAstCfg->masterStr; pStrAf = pAstCfg->xStr[zMS].pAudioFrame; // Set ASOT output frame length. // THD sets this to 256 (hard-coded in Dec Info) // DDP sets this to 0 (audio frame pass through, 0 from ASDT AF frame length) // PCM sets this to 256 (decodeControl.frameLength) //pDecInfo1Af->sampleCount = pAsotCfg->pAstCfg->xDecOpCb[zMS].strFrameLen; // gOutFrameLen; // !!!! GJ: Revisit !!!! pDecInfo1Af->sampleCount = 512; // debugging for 96kHz //pDecInfo1Af->sampleCount = 1024; // debugging for 192kHz // Update Stream Audio Frame. // Copy Dec Reset AF to Stream AF. outIsCpyAf(pDecInfo1Af, pStrAf); // outputInfo1(): // - ASP chain reset, // - Enc Info, // - Start Output status = asopDecOutProcInfo1(pP, pQ, pAsotCfg, frame); if (status < 0) { return status; } return ASOP_SOK; } } // ASOT SM function // Purpose: Init-Sync Dec Decode1 state function. // Wake Timer + *POLLING* version. // No explicit Rx ASDT message event from ASDT. // ASOT wakes on Wake Timer event and polls for flag set. //static Int PAF_ASOT_initSyncDecDecode1( static Int PAF_ASOT_initSyncDecDecode1( const PAF_ASOT_Params *pP, const PAF_ASOT_Patchs *pQ, PAF_ASOT_Config *pAsotCfg, Int frame ) { PAF_AST_Config *pAstCfg; // ASIT/ASOT/ASDT shared configuration Int zMD; // Dec Master index PAF_AST_OutInitSyncCtl *pOutIsCtl; // Output Init-Sync control Int8 decFlag; // dec stage flag Int z; Int zS, zO; Int status; // status code pAstCfg = pAsotCfg->pAstCfg; zMD = pAstCfg->masterDec; pOutIsCtl = &pAsotCfg->pAspmCfg->outIsCtl; // Check for Dec Reset, // Store dec reset AF status = outIsReadDecStageFlag(pOutIsCtl, zMD, ASP_OUTIS_DEC_STAGE_DECODE1_IDX, &decFlag); if (status < 0) { return status; } if (decFlag == 0) { return ASOP_SOK_INITSYNC_NOTREADY; } else { // Find first Output associated with Master Stream zO = OUTPUT1; for (z=ENCODE1; z < ENCODEN; z++) { zS = pP->streamsFromEncodes[z]; // get Stream associated with Encoder if (zS == pAstCfg->masterStr) { // This Encoder is associated with Master Stream. // Note other Encoder can also be associated with Master Stream. zO = pP->outputsFromEncodes[z]; // get Output associated with Encoder } } // FL, New IO: assumption here is Tx McASP clock dividers & // Output frame size are set correctly before IO prime, // i.e. IO prime is not using defaults // FL, New IO: API for single Output // I/O physical layer prime operation required by McASP LLD asopIoPhyPrime(&pAsotCfg->pIoOut[zO]); TRACE_VERBOSE0("PAF_ASOT_initSyncDecDecode1: ASOP McASP LLD primed."); return ASOP_SOK; } } // ASOT SM function // Process Decoder output audio data static Int PAF_ASOT_procDecOut( const PAF_ASOT_Params *pP, const PAF_ASOT_Patchs *pQ, PAF_ASOT_Config *pAsotCfg, Bool *pFirstTime, Int frame ) { PAF_AST_Config *pAstCfg; // ASIT/ASOT/ASDT shared configuration Bool outDevSioSelUpdate; // indicates whether Output SIO selection has changed Int zO, zS; Int z; // decode/encode counter Int errno; // error number Int status; // status code status = ASOP_SOK; pAstCfg = pAsotCfg->pAstCfg; if (*pFirstTime == TRUE) { // Initialize Decoder output processing errno = asopDecOutProcInit(pP, pQ, pAsotCfg, frame); if (errno < 0) { status = errno; } else { *pFirstTime = FALSE; } } if (status == ASOP_SOK) { // Find first Output associated with Master Stream zO = OUTPUT1; for (z=ENCODE1; z < ENCODEN; z++) { zS = pP->streamsFromEncodes[z]; // get Stream associated with Encoder if (zS == pAstCfg->masterStr) { // This Encoder is associated with Master Stream. // Note other Encoder can also be associated with Master Stream. zO = pP->outputsFromEncodes[z]; // get Output associated with Encoder } } // Mark Output transfer complete errno = ioPhyXferComplete(pAsotCfg->pIoOut[zO].hIoPhy, FALSE); if (errno) { status = ASOP_ERR_PROCDECOUT_IOPHYXFERCOMPLETE; } } if (status == ASOP_SOK) { // Check if Output device SIO selection changed errno = checkOutDevSioSelUpdate(pP, pAsotCfg, zO, &outDevSioSelUpdate); if (errno) { status = ASOP_ERR_PROCDECOUT_CHKOUTDEVSELUPD; } else if (outDevSioSelUpdate == TRUE) { status = ASOP_ERR_PROCDECOUT_OUTDEVSELUPD; } } if (status == ASOP_SOK) { // Process encoder command errno = asopDecOutProcEncodeCommand(pP, pQ, pAsotCfg); if (errno < 0) { status = errno; } } if (status == ASOP_SOK) { // Read CB, execute ASP chain errno = asopDecOutProcStream(pP, pQ, pAsotCfg, frame); if (errno < 0) { status = errno; } } if (status == ASOP_SOK) { size_t totalOutputSize; // Calculate the total size that encoder will write to output buffer totalOutputSize = pAstCfg->xEnc[zO].encodeInStruct.pAudioFrame->sampleCount * pAstCfg->xOut[zO].outBufConfig.stride * pAstCfg->xOut[zO].outBufConfig.sizeofElement; // Get output buffer pointers for encoder to write. Pointers are stored in pAsotCfg->pIoOut[zO] asopGetOutBufPtrs(&pAsotCfg->pIoOut[zO], totalOutputSize); // Invoke the encoder errno = asopDecOutProcEncodeWrap(pP, pQ, pAsotCfg, frame, zO); if (errno < 0) { status = errno; } // Mark Output buffers write complete asopMarkOutBuffsWriteComplete(&pAstCfg->xOut[zO], &pAsotCfg->pIoOut[zO]); } if (status == ASOP_SOK) { // Execute Info2 errno = asopDecOutProcInfo2(pP, pQ, pAsotCfg, frame); if (errno < 0) { status = errno; } } if (status == ASOP_SOK) { errno = asopDecOutProcFinalTest(pP, pQ, pAsotCfg, frame); if (errno < 0) { status = errno; } } if (status != ASOP_SOK) { // Complete Output Processing errno = asopDecOutProcComplete(pP, pQ, pAsotCfg, frame); if (errno < 0) { status = errno; } } return status; } static Int asopDecOutProcEncodeWrap( const PAF_ASOT_Params *pP, const PAF_ASOT_Patchs *pQ, PAF_ASOT_Config *pAsotCfg, Int frame, Int zO ) { PAF_AST_Config *pAstCfg; // ASIT/ASOT/ASDT shared configuration Int errno; // error number Int status; // status code PAF_OutBufConfig *pOutBufCfg; PAF_AudioFrame * pAf; status = ASOP_SOK; pAstCfg = pAsotCfg->pAstCfg; pOutBufCfg = &(pAstCfg->xOut[zO].outBufConfig); pAf = pAstCfg->xEnc[zO].encodeInStruct.pAudioFrame; if(pAsotCfg->pIoOut[zO].buff2 == NULL) { // Output buffer won't wrap around - to invoke the encoder once pOutBufCfg->lengthofFrame = pAf->sampleCount; pOutBufCfg->pntr.pLgInt = pAsotCfg->pIoOut[zO].buff1; // Execute encode errno = asopDecOutProcEncode(pP, pQ, pAsotCfg, frame); if (errno < 0) { status = errno; } } else { // Output buffer will wrap around - to invoke the encoder twice XDAS_Int16 sampleCountSave; PAF_AudioData *afDataAddrSave[16]; PAF_AudioData **afDataAddr; int i, ch; sampleCountSave = pAf->sampleCount; // save sample count for restoring later // Invoke the encoder to write data to the end of output buffer pOutBufCfg->lengthofFrame = pAsotCfg->pIoOut[zO].size1 / (pOutBufCfg->stride * pOutBufCfg->sizeofElement); pAf->sampleCount = pOutBufCfg->lengthofFrame; pOutBufCfg->pntr.pLgInt = pAsotCfg->pIoOut[zO].buff1; // Execute encode errno = asopDecOutProcEncode(pP, pQ, pAsotCfg, frame); if (errno < 0) { status = errno; } // Adjust audio frame buffer addresses for second invoking of the encoder afDataAddr = pAf->data.sample; for(i=0; istride; i++) { ch = pAstCfg->xEnc[zO].encodeStatus.channelMap.from[i]; afDataAddrSave[i] = afDataAddr[ch]; // save audio frame buffer addresses afDataAddr[ch] = &afDataAddr[ch][pOutBufCfg->lengthofFrame]; } // Invoke the encoder to write data to the beginning of output buffer (wrapping around) pOutBufCfg->lengthofFrame = pAsotCfg->pIoOut[zO].size2 / (pOutBufCfg->stride * pOutBufCfg->sizeofElement); pAf->sampleCount = pOutBufCfg->lengthofFrame; pOutBufCfg->pntr.pLgInt = pAsotCfg->pIoOut[zO].buff2; // Execute encode errno = asopDecOutProcEncode(pP, pQ, pAsotCfg, frame); if (errno < 0) { status = errno; } // Restore sample count and audio frame buffer addresses pAf->sampleCount = sampleCountSave; for(i=0; istride; i++) { ch = pAstCfg->xEnc[zO].encodeStatus.channelMap.from[i]; afDataAddr[ch] = afDataAddrSave[i]; } pAsotCfg->pIoOut[zO].ioBuffBuf2AllocCnt++; // debug } return status; } // ASOT SM function // Purpose: Init-Sync Re-Sync state function. // Performs Init-Sync using stored Dec Reset/Info1 AFs. static Int PAF_ASOT_initSyncResync( const PAF_ASOT_Params *pP, const PAF_ASOT_Patchs *pQ, PAF_ASOT_Config *pAsotCfg, PAF_AudioFrame *pDecResetAf, PAF_AudioFrame *pDecInfo1Af, Int frame ) { PAF_AST_Config *pAstCfg; // ASIT/ASOT/ASDT shared configuration Int zMS; // Stream Master index PAF_AudioFrame *pStrAf; // stream audio frame Int status; // status code pAstCfg = pAsotCfg->pAstCfg; zMS = pAstCfg->masterStr; pStrAf = pAstCfg->xStr[zMS].pAudioFrame; // Reset audio frames resetAfs(pP, pAstCfg->xStr); // // Dec Reset re-sync using stored Dec Reset AF // // Update Stream Audio Frame. // Copy Dec Reset AF to Stream AF. outIsCpyAf(pDecResetAf, pStrAf); // Enc activate, // Enc reset status = asopDecOutProcReset(pP, pQ, pAsotCfg, frame); if (status < 0) { return status; } // // Dec Info1 re-sync using stored Dec Info1 AF // // Update Stream Audio Frame. // Copy Dec Info1 AF to Stream AF. outIsCpyAf(pDecInfo1Af, pStrAf); // outputInfo1(): // - ASP chain reset, // - Enc Info, // - Start Output status = asopDecOutProcInfo1(pP, pQ, pAsotCfg, frame); if (status < 0) { return status; } return ASOP_SOK; } // ASOT SM function // Purpose: Re-select devices used for Output. // Performs Init-Sync using stored Dec Reset/Info1 AFs. static Int PAF_ASOT_reselectDevices( const PAF_ASOT_Params *pP, const PAF_ASOT_Patchs *pQ, PAF_ASOT_Config *pAsotCfg, PAF_AudioFrame *pDecResetAf, PAF_AudioFrame *pDecInfo1Af, Int frame, Bool *pOutDevSel ) { Bool outDevSel; Int status; // Re-select Output devices status = PAF_ASOT_selectDevices(pP, pQ, pAsotCfg, &outDevSel); if (status < 0) { *pOutDevSel = outDevSel; return status; } else if (outDevSel == FALSE) { *pOutDevSel = outDevSel; return status; } else { // Init-Sync Resync status = PAF_ASOT_initSyncResync(pP, pQ, pAsotCfg, pDecResetAf, pDecInfo1Af, frame); if (status < 0) { outDevSel = FALSE; *pOutDevSel = outDevSel; return status; } } *pOutDevSel = outDevSel; return status; }