source: svn/newcon3bcm2_21bu/nexus/modules/audio/7552/src/nexus_audio_decoder.c

Last change on this file was 76, checked in by megakiss, 10 years ago

1W 대기전력을 만족시키기 위하여 POWEROFF시 튜너를 Standby 상태로 함

  • Property svn:executable set to *
File size: 112.9 KB
Line 
1/***************************************************************************
2*     (c)2004-2011 Broadcom Corporation
3
4*  This program is the proprietary software of Broadcom Corporation and/or its licensors,
5*  and may only be used, duplicated, modified or distributed pursuant to the terms and
6*  conditions of a separate, written license agreement executed between you and Broadcom
7*  (an "Authorized License").  Except as set forth in an Authorized License, Broadcom grants
8*  no license (express or implied), right to use, or waiver of any kind with respect to the
9*  Software, and Broadcom expressly reserves all rights in and to the Software and all
10*  intellectual property rights therein.  IF YOU HAVE NO AUTHORIZED LICENSE, THEN YOU
11*  HAVE NO RIGHT TO USE THIS SOFTWARE IN ANY WAY, AND SHOULD IMMEDIATELY
12*  NOTIFY BROADCOM AND DISCONTINUE ALL USE OF THE SOFTWARE. 
13*   
14*  Except as expressly set forth in the Authorized License,
15*   
16*  1.     This program, including its structure, sequence and organization, constitutes the valuable trade
17*  secrets of Broadcom, and you shall use all reasonable efforts to protect the confidentiality thereof,
18*  and to use this information only in connection with your use of Broadcom integrated circuit products.
19*   
20*  2.     TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS"
21*  AND WITH ALL FAULTS AND BROADCOM MAKES NO PROMISES, REPRESENTATIONS OR
22*  WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT TO
23*  THE SOFTWARE.  BROADCOM SPECIFICALLY DISCLAIMS ANY AND ALL IMPLIED WARRANTIES
24*  OF TITLE, MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR PURPOSE,
25*  LACK OF VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT, QUIET POSSESSION
26*  OR CORRESPONDENCE TO DESCRIPTION. YOU ASSUME THE ENTIRE RISK ARISING OUT OF
27*  USE OR PERFORMANCE OF THE SOFTWARE.
28
29*  3.     TO THE MAXIMUM EXTENT PERMITTED BY LAW, IN NO EVENT SHALL BROADCOM OR ITS
30*  LICENSORS BE LIABLE FOR (i) CONSEQUENTIAL, INCIDENTAL, SPECIAL, INDIRECT, OR
31*  EXEMPLARY DAMAGES WHATSOEVER ARISING OUT OF OR IN ANY WAY RELATING TO YOUR
32*  USE OF OR INABILITY TO USE THE SOFTWARE EVEN IF BROADCOM HAS BEEN ADVISED OF
33*  THE POSSIBILITY OF SUCH DAMAGES; OR (ii) ANY AMOUNT IN EXCESS OF THE AMOUNT
34*  ACTUALLY PAID FOR THE SOFTWARE ITSELF OR U.S. $1, WHICHEVER IS GREATER. THESE
35*  LIMITATIONS SHALL APPLY NOTWITHSTANDING ANY FAILURE OF ESSENTIAL PURPOSE OF
36*  ANY LIMITED REMEDY.
37*
38* $brcm_Workfile: nexus_audio_decoder.c $
39* $brcm_Revision: 47 $
40* $brcm_Date: 12/21/11 4:52p $
41*
42* API Description:
43*   API name: AudioDecoder
44*    API for audio decoder management.
45*
46* Revision History:
47*
48* $brcm_Log: /nexus/modules/audio/7422/src/nexus_audio_decoder.c $
49*
50* 47   12/21/11 4:52p jgarrett
51* SW7425-2042: Audio decoder will only report running when actually
52*  started.  This resolves issues with attaching a mixer to HDMI/SPDIF
53*  inputs
54*
55* 46   12/21/11 12:45p jgarrett
56* SW7425-1756: Bitrate changes should not fire sourceChagned callback
57*
58* 45   12/21/11 12:21p jgarrett
59* SW7425-2000: Disabling TSM for OGG source material
60*
61* 44   12/20/11 4:18p jgarrett
62* SW7425-1018: Propagating loudness equivalence setting to APE
63*
64* 43   12/20/11 4:13p jgarrett
65* SW7425-1018: Adding initial A/85 implementation
66*
67* 42   12/13/11 9:44p bandrews
68* SW7425-1772: merge to main
69*
70* SW7425-1772/4   12/12/11 10:18p bandrews
71* SW7425-1772: merge from main
72*
73* 41   12/9/11 5:51p jgarrett
74* SW7425-1756: Adding stream status callback and bitrate/mode change
75*  handling
76*
77* 40   12/7/11 5:36p jgarrett
78* SW7425-1893: Adding MPEG Conformance mode
79*
80* 39   11/21/11 11:30a jgarrett
81* SW7425-1756: Adding overflow callback
82*
83* 38   11/18/11 3:04p jgarrett
84* SW7425-1756: Adding PTS callbacks and overflow callback
85*
86* 37   11/18/11 2:57p jgarrett
87* SW7425-1519: Adding decoder mixing mode settings
88*
89* SW7425-1772/3   12/12/11 10:02p bandrews
90* SW7425-1772: add priority scheme to stc channel
91*
92* SW7425-1772/2   11/17/11 9:19p bandrews
93* SW7425-1772: make decoders id themselves to stc channel as index,
94*  instead of funky way based on compressed / pcm / input
95*
96* SW7425-1772/1   11/17/11 6:31p bandrews
97* SW7425-1772: 6 channel support to stc channel
98*
99* 36   11/8/11 6:06p jgarrett
100* SW7422-400: Adding audio debug log support in kernel mode
101*
102* 35   11/3/11 6:53p jgarrett
103* SW7422-400: Enabling audio debug logs on 40nm APE chips
104*
105* 34   11/2/11 6:26p jgarrett
106* SW7422-400: Adding routines for audio DSP debug
107*
108* 33   10/25/11 2:50p gskerl
109* SW7231-129: Removed call to NEXUS_AudioInput_P_RemoveInput() from
110*  NEXUS_AudioDecoder_Start()
111*
112* 32   10/10/11 1:42p jgarrett
113* SW7425-1457: Ensuring PidChannel is only refernced after
114*  NEXUS_AudioDecoder_Start() during ApplySettings()
115*
116* 31   10/6/11 6:20p jgarrett
117* SW7425-1428: Fixing pause handling
118*
119* 30   9/30/11 5:31p jgarrett
120* SW7425-1297: Changes for 0.5x..2.0x audio trick modes and automatic
121*  muting on unsupported rates
122*
123* SW7425-1297/1   9/28/11 6:29p jgarrett
124* SW7425-1297: Adding automatic mute on unsupported trick rates
125*
126* 29   9/20/11 5:10p jgarrett
127* SW7425-1045: Mapping additional settings and status between nexus and
128*  the audio FW
129*
130* 28   9/9/11 3:20p jgarrett
131* SW7552-113: Merge to main branch (original branch was inadvertent)
132*
133* 27   9/9/11 10:08a ialauder
134* SWDTV-8364: Added call to convert the decoder codec to the nexus codec
135*  when callling NEXUS_AudioDecoder_GetStatus().
136*
137* SW7425-1212/1   9/9/11 3:12p jgarrett
138* SW7552-113: Adding ASTM hooks
139*
140* 24   8/15/11 5:01p jgarrett
141* SW7346-438: Coverity CID 34705,32711
142*
143* 23   8/8/11 6:01p jgarrett
144* SW7346-412: Propagating errors from BAPE_GetTsmStatus
145*
146* 22   7/29/11 5:34p jgarrett
147* SW7346-358: coverity cid 33739
148*
149* 21   7/14/11 1:02p jgarrett
150* SW7425-406: Fixing TSM Playback setting with no STC channel
151*
152* 20   7/1/11 10:54a jgarrett
153* SW7405-5072: Adding numWatchdogs and raveIndex status
154*
155* 19   6/22/11 11:36a jgarrett
156* SW7425-654: Adding NRT hooks
157*
158* 18   6/21/11 5:03p jgarrett
159* SW7425-654: Adding Audio NRT APIs
160*
161* 17   6/9/11 2:56p jgarrett
162* SW7425-406: Adding secondary decoder support
163*
164* 16   5/25/11 5:16p jgarrett
165* SW7425-408: Adding BDBG_OBJECT to input/output types and MS11 features
166*
167* 15   5/20/11 11:32a jgarrett
168* SW7405-5335: Adding numBytesDecoded to NEXUS_AudioDecoderStatus
169*
170* 14   5/5/11 6:07p jgarrett
171* SW7425-524: Muting decoder on invalid trick modes
172*
173* 13   5/4/11 4:04p jgarrett
174* SW7425-469: Adding no_watchdog environment variable to disable audio
175*  watchdog
176*
177* 12   4/26/11 4:23p jgarrett
178* SW7425-437: Not allowing dead nodes in the filter graph
179*
180* 11   4/20/11 6:16p jtna
181* SW7425-365: fix build warnings for 2.6.37 kernel
182*
183* 10   4/18/11 10:29p jgarrett
184* SW7425-361: Not implicitly forcing audio connection memory to be
185*  allocated with sync mute
186*
187* 9   3/23/11 6:28p jgarrett
188* SW7422-352: adding HDMI input support to nexus
189*
190* 8   3/23/11 4:29p jgarrett
191* SW7422-403: Fixing sync mute and DSOLA
192*
193* 7   3/21/11 6:59p jgarrett
194* SW7422-146: Fixing crash on stop with external inputs
195*
196* 6   3/11/11 6:02p jgarrett
197* SW7422-146: Decoder supports external inputs
198*
199* 5   2/22/11 5:44p jgarrett
200* SW7422-146: Implemented type renaming based on filter graph review
201*  comments
202*
203* 4   2/7/11 11:30a jgarrett
204* SW7422-146: Implementing DDP -> AC3 conversion and status for
205*  MPEG/AAC/AC3
206*
207* 3   1/13/11 5:25p jgarrett
208* SW7422-146: Adding encoder hooks
209*
210* 2   1/12/11 4:25p jgarrett
211* SW7422-146: Refactoring data path from decoder
212*
213* 1   12/17/10 3:56p jgarrett
214* SW7422-146: Adding initial nexus on APE for 7422
215*
216***************************************************************************/
217
218#include "nexus_audio_module.h"
219#include "priv/nexus_audio_decoder_priv.h"
220
221#define RAAGA_DEBUG_LOG_CHANGES 1
222#include "bdsp_raaga.h"
223
224BDBG_MODULE(nexus_audio_decoder);
225
226BDBG_OBJECT_ID(NEXUS_AudioDecoder);
227static NEXUS_AudioDecoder g_decoders[NEXUS_NUM_AUDIO_DECODERS];
228
229static void NEXUS_AudioDecoder_P_Watchdog(void *pParam);
230static void NEXUS_AudioDecoder_P_SampleRate(void *pParam);
231static void NEXUS_AudioDecoder_P_ChannelChangeReport(void * context);
232static void NEXUS_AudioDecoder_P_FirstPts_isr(void *pParam1, int param2, const BAPE_DecoderTsmStatus *pTsmStatus);
233static void NEXUS_AudioDecoder_P_AudioTsmFail_isr(void *pParam1, int param2, const BAPE_DecoderTsmStatus *pTsmStatus);
234static void NEXUS_AudioDecoder_P_AudioTsmPass_isr(void *pParam1, int param2, const BAPE_DecoderTsmStatus *pTsmStatus);
235static void NEXUS_AudioDecoder_P_SampleRateChange_isr(void *pParam1, int param2, unsigned sampleRate);
236static void NEXUS_AudioDecoder_P_Lock_isr(void *pParam1, int param2);
237static void NEXUS_AudioDecoder_P_StreamStatusAvailable_isr(void *pParam1, int param2);
238static void NEXUS_AudioDecoder_P_StreamParameterChanged_isr(void *pParam1, int param2);
239static BERR_Code NEXUS_AudioDecoder_P_GetPtsCallback_isr(void *pContext, BAVC_PTSInfo *pPTSInfo);
240static BERR_Code NEXUS_AudioDecoder_P_GetCdbLevelCallback_isr(void *pContext, unsigned *pCdbLevel);
241static BERR_Code NEXUS_AudioDecoder_P_StcValidCallback_isr(void *pContext);
242static void NEXUS_AudioDecoder_P_FifoWatchdog(void *context);
243static void NEXUS_AudioDecoder_P_Watchdog_isr(void *pParam1, int param2);
244static void NEXUS_AudioDecoder_P_InputFormatChange_isr(void *pParam1, int param2);
245static void NEXUS_AudioDecoder_P_InputFormatChange(void *pContext);
246static BERR_Code NEXUS_AudioDecoder_P_SetPcrOffset_isr(void *pContext, uint32_t pcrOffset);
247static BERR_Code NEXUS_AudioDecoder_P_GetPcrOffset_isr(void *pContext, uint32_t *pPcrOffset);
248
249#define LOCK_TRANSPORT()    NEXUS_Module_Lock(g_NEXUS_audioModuleData.settings.modules.transport)
250#define UNLOCK_TRANSPORT()  NEXUS_Module_Unlock(g_NEXUS_audioModuleData.settings.modules.transport)
251
252static BKNI_EventHandle g_watchdogEvent;
253static NEXUS_EventCallbackHandle g_watchdogCallback;
254static unsigned g_numWatchdogs;
255
256static void NEXUS_AudioDecoder_P_Watchdog_isr(void *pParam1, int param2)
257{
258    BSTD_UNUSED(pParam1);
259    BSTD_UNUSED(param2);
260    BDBG_ERR(("Audio Watchdog Interrupt Received"));
261    BKNI_SetEvent_isr(g_watchdogEvent);
262}
263
264NEXUS_Error NEXUS_AudioDecoder_P_Init(void)
265{
266    BERR_Code errCode;
267    BAPE_InterruptHandlers interrupts;
268
269    g_numWatchdogs = 0;
270    errCode = BKNI_CreateEvent(&g_watchdogEvent);
271    if ( errCode ) 
272    {
273        return BERR_TRACE(errCode);
274    }
275    g_watchdogCallback = NEXUS_RegisterEvent(g_watchdogEvent, NEXUS_AudioDecoder_P_Watchdog, NULL);
276    if ( NULL == g_watchdogCallback ) 
277    {
278        BKNI_DestroyEvent(g_watchdogEvent);
279        g_watchdogEvent = NULL;
280        return BERR_TRACE(BERR_OS_ERROR);
281    }
282
283    /* Allow watchdog to be disabled for debugging */
284    if ( !NEXUS_GetEnv("no_watchdog") && g_NEXUS_audioModuleData.settings.watchdogEnabled )
285    {
286        BAPE_GetInterruptHandlers(NEXUS_AUDIO_DEVICE_HANDLE, &interrupts);
287        interrupts.watchdog.pCallback_isr = NEXUS_AudioDecoder_P_Watchdog_isr;
288        errCode = BAPE_SetInterruptHandlers(NEXUS_AUDIO_DEVICE_HANDLE, &interrupts);
289        if ( errCode ) 
290        {
291            NEXUS_UnregisterEvent(g_watchdogCallback);
292            g_watchdogCallback = NULL;
293            BKNI_DestroyEvent(g_watchdogEvent);
294            g_watchdogEvent = NULL;
295            return BERR_TRACE(errCode);
296        }
297    }
298
299    return BERR_SUCCESS;
300}
301
302void NEXUS_AudioDecoder_P_Uninit(void)
303{
304    BAPE_InterruptHandlers interrupts;
305
306    BAPE_GetInterruptHandlers(NEXUS_AUDIO_DEVICE_HANDLE, &interrupts);
307    interrupts.watchdog.pCallback_isr = NULL;
308    BAPE_SetInterruptHandlers(NEXUS_AUDIO_DEVICE_HANDLE, &interrupts);
309
310    NEXUS_UnregisterEvent(g_watchdogCallback);
311    g_watchdogCallback = NULL;
312    BKNI_DestroyEvent(g_watchdogEvent);
313    g_watchdogEvent = NULL;
314}
315
316/***************************************************************************
317Summary:
318Get default open settings for an audio decoder
319***************************************************************************/
320void NEXUS_AudioDecoder_GetDefaultOpenSettings(
321    NEXUS_AudioDecoderOpenSettings *pSettings   /* [out] default settings */
322    )
323{
324    BDBG_ASSERT(NULL != pSettings);
325    BKNI_Memset(pSettings, 0, sizeof(*pSettings));
326    pSettings->independentDelay = g_NEXUS_audioModuleData.settings.independentDelay;
327}
328
329static void NEXUS_AudioDecoder_P_GetDefaultSettings(
330    NEXUS_AudioDecoderSettings *pSettings   /* [out] default settings */
331    )
332{
333    int i;   
334    BDBG_ASSERT(NULL != pSettings);
335    BKNI_Memset(pSettings, 0, sizeof(NEXUS_AudioDecoderSettings));   
336    pSettings->loudnessEquivalenceEnabled = true;
337    for ( i = 0; i < NEXUS_AudioChannel_eMax; i++ )
338    {
339        pSettings->volumeMatrix[i][i] = NEXUS_AUDIO_VOLUME_LINEAR_NORMAL;
340    }
341}
342
343/***************************************************************************
344Summary:
345Open an audio decoder of the specified type
346***************************************************************************/
347NEXUS_AudioDecoderHandle NEXUS_AudioDecoder_Open( /* attr{destructor=NEXUS_AudioDecoder_Close}  */
348    unsigned index,
349    const NEXUS_AudioDecoderOpenSettings *pSettings   /* settings */
350    )
351{
352    NEXUS_AudioDecoderHandle handle;
353    NEXUS_AudioDecoderOpenSettings openSettings;
354    NEXUS_RaveOpenSettings raveSettings;
355    BAPE_DecoderOpenSettings decoderOpenSettings;
356    BAPE_DecoderInterruptHandlers interrupts;
357    BAPE_Connector mixerInput;
358    BERR_Code errCode;
359    unsigned j;
360
361    if ( index >= NEXUS_NUM_AUDIO_DECODERS )
362    {
363        errCode=BERR_TRACE(BERR_INVALID_PARAMETER);
364        return NULL;
365    }
366
367    handle = &g_decoders[index];
368
369    /* Check if handle is already open */
370    if ( handle->opened )
371    {
372        BDBG_ERR(("Decoder %d already opened", index));
373        errCode=BERR_TRACE(BERR_INVALID_PARAMETER);
374        return NULL;
375    }
376
377    if ( NULL == pSettings )
378    {
379        NEXUS_AudioDecoder_GetDefaultOpenSettings(&openSettings);
380        pSettings = &openSettings;
381    }
382
383    /* Reset to default state */
384    BKNI_Memset(handle, 0, sizeof(NEXUS_AudioDecoder));
385    BDBG_OBJECT_SET(handle, NEXUS_AudioDecoder);
386    handle->index = index;
387    handle->stcDecoderType = NEXUS_StcChannelDecoderType_eMax;    /* Invalid */
388    handle->trickMute = false;
389    handle->trickForceStopped = false;
390
391#if NEXUS_HAS_ASTM
392    BKNI_Memset(&handle->astm.settings, 0, sizeof(NEXUS_AudioDecoderAstmSettings));
393    BKNI_Memset(&handle->astm.status, 0, sizeof(NEXUS_AudioDecoderAstmStatus));
394#endif
395
396    for ( j = 0; j < NEXUS_AudioDecoderConnectorType_eMax; j++ )
397    {
398        /* Setup handle linkage */
399        NEXUS_AUDIO_INPUT_INIT(&handle->connectors[j], NEXUS_AudioInputType_eDecoder, handle);
400
401        /* Set format per-connector */
402        if ( j == NEXUS_AudioDecoderConnectorType_eStereo )
403        {
404            handle->connectors[j].format = NEXUS_AudioInputFormat_ePcmStereo;
405        }
406        else if ( j == NEXUS_AudioDecoderConnectorType_eMultichannel )
407        {
408            /* The correct value for this is set later if multichannel is enabled */
409            handle->connectors[j].format = NEXUS_AudioInputFormat_eNone;
410        }
411        else
412        {
413            handle->connectors[j].format = NEXUS_AudioInputFormat_eCompressed;
414        }
415
416        /* Invalidate outputs */
417        BKNI_Memset(&(handle->outputLists[j]), 0, sizeof(NEXUS_AudioOutputList));
418    }
419
420    NEXUS_AudioDecoder_P_TrickReset(handle);
421
422    /* Create Events */
423    errCode = BKNI_CreateEvent(&handle->sampleRateEvent);
424    if ( errCode )
425    {
426        errCode=BERR_TRACE(errCode);
427        goto err_sample_rate_event;
428    }
429
430    handle->sampleRateCallback = NEXUS_RegisterEvent(handle->sampleRateEvent, NEXUS_AudioDecoder_P_SampleRate, handle);
431    if ( NULL == handle->sampleRateCallback )
432    {
433        errCode=BERR_TRACE(BERR_OS_ERROR);
434        goto err_sample_rate_callback;
435    }
436
437    errCode = BKNI_CreateEvent(&handle->channelChangeReportEvent);
438    if ( errCode )
439    {
440        errCode=BERR_TRACE(errCode);
441        goto err_channel_change_report_event;
442    }
443
444     handle->channelChangeReportEventHandler = NEXUS_RegisterEvent(handle->channelChangeReportEvent, NEXUS_AudioDecoder_P_ChannelChangeReport, handle);
445     if ( NULL == handle->channelChangeReportEventHandler )
446     {
447         errCode=BERR_TRACE(BERR_OS_ERROR);
448         goto err_channel_change_report_event_handler;
449     }
450
451     errCode = BKNI_CreateEvent(&handle->inputFormatChangeEvent);
452     if ( errCode )
453     {
454         errCode=BERR_TRACE(errCode);
455         goto err_input_format_change_event;
456     }
457
458    handle->inputFormatChangeEventHandler = NEXUS_RegisterEvent(handle->inputFormatChangeEvent, NEXUS_AudioDecoder_P_InputFormatChange, handle);
459    if ( NULL == handle->inputFormatChangeEventHandler )
460    {
461      errCode=BERR_TRACE(BERR_OS_ERROR);
462      goto err_input_format_change_event_handler;
463    }
464
465    if ( NEXUS_GetEnv("multichannel_disabled") || NEXUS_GetEnv("audio_processing_disabled") )
466    {
467        handle->connectors[NEXUS_AudioDecoderConnectorType_eMultichannel].format = NEXUS_AudioInputFormat_ePcmStereo;
468    }
469    else
470    {
471        switch ( pSettings->multichannelFormat )
472        {
473        case NEXUS_AudioMultichannelFormat_eNone:
474            /* Multichannel output disabled */
475            handle->connectors[NEXUS_AudioDecoderConnectorType_eMultichannel].format = NEXUS_AudioInputFormat_ePcmStereo;
476            break;
477        case NEXUS_AudioMultichannelFormat_e5_1:
478            handle->connectors[NEXUS_AudioDecoderConnectorType_eMultichannel].format = NEXUS_AudioInputFormat_ePcm5_1;
479            #if NEXUS_NUM_HDMI_OUTPUTS && 0
480            /* TODO: Notify PI of 5.1 vs. 7.1 */
481            pChannelSettings->sChnRBufPool.uiMaxNumOutChPairs[0] += 3;
482            #endif
483            break;
484        #if 0 /* Not supported on any current chipsets */
485        case NEXUS_AudioMultichannelFormat_e7_1:
486            handle->connectors[NEXUS_AudioDecoderConnectorType_eMultichannel].format = NEXUS_AudioInputFormat_ePcm7_1;
487            #if NEXUS_NUM_HDMI_OUTPUTS && 0
488            /* TODO: Notify PI of 5.1 vs. 7.1 */
489            pChannelSettings->sChnRBufPool.uiMaxNumOutChPairs[0] += 4;
490            #endif
491            break;
492        #endif
493        default:
494            BDBG_ERR(("Unsupported multichannel audio format"));
495            errCode = BERR_TRACE(BERR_INVALID_PARAMETER);
496            goto err_channel;
497        }
498    }
499    if ( pSettings->independentDelay && !g_NEXUS_audioModuleData.settings.independentDelay )
500    {
501        BDBG_ERR(("Independent delay must be enabled at the audio module level.  Please check NEXUS_AudioModuleSettings.independentDelay."));
502        errCode = BERR_TRACE(BERR_INVALID_PARAMETER);
503        goto err_channel;
504    }
505
506    /* Open APE decoder */
507    BAPE_Decoder_GetDefaultOpenSettings(&decoderOpenSettings);
508    errCode = BAPE_Decoder_Open(NEXUS_AUDIO_DEVICE_HANDLE, index, &decoderOpenSettings, &handle->channel);
509    if ( errCode )
510    {
511        errCode = BERR_TRACE(errCode);
512        goto err_channel;
513    }
514
515    /* Init connectors */
516    BAPE_Decoder_GetConnector(handle->channel, BAPE_ConnectorFormat_eStereo, &mixerInput);
517    handle->connectors[NEXUS_AudioDecoderConnectorType_eStereo].port = (uint32_t)mixerInput;
518    BAPE_Decoder_GetConnector(handle->channel, BAPE_ConnectorFormat_eMultichannel, &mixerInput);
519    handle->connectors[NEXUS_AudioDecoderConnectorType_eMultichannel].port = (uint32_t)mixerInput;
520    BAPE_Decoder_GetConnector(handle->channel, BAPE_ConnectorFormat_eCompressed, &mixerInput);
521    handle->connectors[NEXUS_AudioDecoderConnectorType_eCompressed].port = (uint32_t)mixerInput;
522
523    /* Hook up decoder interrupts */
524    BAPE_Decoder_GetInterruptHandlers(handle->channel, &interrupts);
525    interrupts.firstPts.pCallback_isr = NEXUS_AudioDecoder_P_FirstPts_isr;
526    interrupts.firstPts.pParam1 = handle;
527    interrupts.tsmFail.pCallback_isr = NEXUS_AudioDecoder_P_AudioTsmFail_isr;
528    interrupts.tsmFail.pParam1 = handle;
529    interrupts.tsmPass.pCallback_isr = NEXUS_AudioDecoder_P_AudioTsmPass_isr;
530    interrupts.tsmPass.pParam1 = handle;
531    interrupts.sampleRateChange.pCallback_isr = NEXUS_AudioDecoder_P_SampleRateChange_isr;
532    interrupts.sampleRateChange.pParam1 = handle;
533    interrupts.lock.pCallback_isr = NEXUS_AudioDecoder_P_Lock_isr;
534    interrupts.lock.pParam1 = handle;
535    interrupts.lock.param2 = true;
536    interrupts.unlock.pCallback_isr = NEXUS_AudioDecoder_P_Lock_isr;
537    interrupts.unlock.pParam1 = handle;
538    interrupts.unlock.param2 = false;
539    interrupts.statusReady.pCallback_isr = NEXUS_AudioDecoder_P_StreamStatusAvailable_isr;
540    interrupts.statusReady.pParam1 = handle;
541    interrupts.modeChange.pCallback_isr = NEXUS_AudioDecoder_P_StreamParameterChanged_isr;
542    interrupts.modeChange.pParam1 = handle;
543#if 0   /* JDG: This causes far too many source changed callbacks to fire.  Some codecs will trigger
544                this interrupt on every frame.  It was not functional on older RAP platforms likely
545                for the same reason. */
546    interrupts.bitrateChange.pCallback_isr = NEXUS_AudioDecoder_P_StreamParameterChanged_isr;
547    interrupts.bitrateChange.pParam1 = handle;
548#endif
549    BAPE_Decoder_SetInterruptHandlers(handle->channel, &interrupts);
550
551    LOCK_TRANSPORT();
552    NEXUS_Rave_GetDefaultOpenSettings_priv(&raveSettings);
553    UNLOCK_TRANSPORT();
554
555    BAPE_Decoder_GetDefaultCdbItbConfig(handle->channel, &raveSettings.config);
556
557    if ( pSettings->fifoSize == 0 )
558    {
559        /* NOTE: Don't automatically increase CDB/ITB for IP Settop internally. */
560    }
561    else
562    {
563        /* Make ITB proportional to CDB */
564        raveSettings.config.Itb.Length = 1024*((raveSettings.config.Itb.Length/1024) * (pSettings->fifoSize/1024))/(raveSettings.config.Cdb.Length/1024);
565        BDBG_ASSERT(0 != raveSettings.config.Itb.Length);
566        raveSettings.config.Cdb.Length = pSettings->fifoSize;
567    }
568
569    LOCK_TRANSPORT();
570    handle->raveContext = NEXUS_Rave_Open_priv(&raveSettings);
571    UNLOCK_TRANSPORT();
572    if ( NULL == handle->raveContext )
573    {
574        BDBG_ERR(("Unable to allocate RAVE context"));
575        goto err_rave;
576    }
577
578    handle->sourceChangeAppCallback = NEXUS_IsrCallback_Create(handle, NULL);
579    if ( NULL == handle->sourceChangeAppCallback )
580    {
581        goto err_app_callback;
582    }
583
584    handle->lockCallback = NEXUS_IsrCallback_Create(handle, NULL);
585    if ( NULL == handle->lockCallback )
586    {
587        goto err_lock_callback;
588    }
589
590    handle->ptsErrorCallback = NEXUS_IsrCallback_Create(handle, NULL);
591    if ( NULL == handle->ptsErrorCallback )
592    {
593        goto err_pts_error_callback;
594    }
595
596    handle->firstPtsCallback = NEXUS_IsrCallback_Create(handle, NULL);
597    if ( NULL == handle->firstPtsCallback )
598    {
599        goto err_first_pts_callback;
600    }
601
602    handle->fifoOverflowCallback = NEXUS_IsrCallback_Create(handle, NULL);
603    if ( NULL == handle->fifoOverflowCallback )
604    {
605        goto err_overflow_callback;
606    }
607
608    handle->streamStatusCallback = NEXUS_IsrCallback_Create(handle, NULL);
609    if ( NULL == handle->streamStatusCallback )
610    {
611        goto err_status_callback;
612    }
613
614    /* Success */
615    NEXUS_AudioDecoder_P_GetDefaultSettings(&handle->settings);
616    (void)NEXUS_AudioDecoder_SetSettings(handle, &handle->settings);
617    handle->opened = true;
618
619    return handle;
620
621err_status_callback:
622    NEXUS_IsrCallback_Destroy(handle->fifoOverflowCallback);
623err_overflow_callback:
624    NEXUS_IsrCallback_Destroy(handle->firstPtsCallback);
625err_first_pts_callback:
626    NEXUS_IsrCallback_Destroy(handle->ptsErrorCallback);
627err_pts_error_callback:
628    NEXUS_IsrCallback_Destroy(handle->lockCallback);
629err_lock_callback:
630    NEXUS_IsrCallback_Destroy(handle->sourceChangeAppCallback);
631err_app_callback:
632    LOCK_TRANSPORT();
633    NEXUS_Rave_Close_priv(handle->raveContext);
634    UNLOCK_TRANSPORT();
635err_rave:
636    BAPE_Decoder_Close(handle->channel);
637err_channel:
638    NEXUS_UnregisterEvent(handle->inputFormatChangeEventHandler);
639err_input_format_change_event_handler:
640    BKNI_DestroyEvent(handle->inputFormatChangeEvent);
641err_input_format_change_event:
642    NEXUS_UnregisterEvent(handle->channelChangeReportEventHandler);
643err_channel_change_report_event_handler:
644    BKNI_DestroyEvent(handle->channelChangeReportEvent);
645err_channel_change_report_event:
646    NEXUS_UnregisterEvent(handle->sampleRateCallback);
647err_sample_rate_callback:
648    BKNI_DestroyEvent(handle->sampleRateEvent);
649err_sample_rate_event:
650    BDBG_OBJECT_UNSET(handle, NEXUS_AudioDecoder);
651    BKNI_Memset(handle, 0, sizeof(NEXUS_AudioDecoder));
652    return NULL;
653}
654
655/***************************************************************************
656Summary:
657Close an audio decoder of the specified type
658***************************************************************************/
659void NEXUS_AudioDecoder_Close(
660    NEXUS_AudioDecoderHandle handle
661    )
662{
663    int i;
664
665    BDBG_OBJECT_ASSERT(handle, NEXUS_AudioDecoder);
666    BDBG_ASSERT(true == handle->opened);
667
668    if ( handle->started )
669    {
670        NEXUS_AudioDecoder_Stop(handle);
671    }
672
673    for ( i = 0; i < NEXUS_AudioDecoderConnectorType_eMax; i++ )
674    {
675        if ( handle->connectors[i].pMixerData )
676        {
677            const char *pType;
678            switch ( i )
679            {
680            case NEXUS_AudioDecoderConnectorType_eStereo:
681                pType = "stereo";
682                break;
683            case NEXUS_AudioDecoderConnectorType_eCompressed:
684                pType = "compressed";
685                break;
686            case NEXUS_AudioDecoderConnectorType_eMultichannel:
687                pType = "multichannel";
688                break;
689            default:
690                pType = "unknown";
691                break;
692            }
693            BDBG_WRN(("Decoder Connector %p (type=%s) is still active. Calling NEXUS_AudioInput_Shutdown.", &handle->connectors[i], pType));
694            NEXUS_AudioInput_Shutdown(&handle->connectors[i]);
695        }
696    }
697
698    BAPE_Decoder_Close(handle->channel);
699
700    NEXUS_IsrCallback_Destroy(handle->ptsErrorCallback);
701    NEXUS_IsrCallback_Destroy(handle->lockCallback);
702    NEXUS_IsrCallback_Destroy(handle->sourceChangeAppCallback);
703    NEXUS_IsrCallback_Destroy(handle->firstPtsCallback);
704    NEXUS_IsrCallback_Destroy(handle->fifoOverflowCallback);
705    NEXUS_IsrCallback_Destroy(handle->streamStatusCallback);
706    LOCK_TRANSPORT();
707    NEXUS_Rave_Close_priv(handle->raveContext);
708    UNLOCK_TRANSPORT();
709    NEXUS_UnregisterEvent(handle->inputFormatChangeEventHandler);
710    BKNI_DestroyEvent(handle->inputFormatChangeEvent);
711    NEXUS_UnregisterEvent(handle->channelChangeReportEventHandler);
712    BKNI_DestroyEvent(handle->channelChangeReportEvent);
713    NEXUS_UnregisterEvent(handle->sampleRateCallback);
714    BKNI_DestroyEvent(handle->sampleRateEvent);
715    BKNI_Memset(handle, 0, sizeof(NEXUS_AudioDecoder));
716}
717
718/***************************************************************************
719Summary:
720Get Settings for an audio decoder
721***************************************************************************/
722void NEXUS_AudioDecoder_GetSettings(
723    NEXUS_AudioDecoderHandle handle,
724    NEXUS_AudioDecoderSettings *pSettings   /* [out] Settings */
725    )
726{
727    BDBG_OBJECT_ASSERT(handle, NEXUS_AudioDecoder);
728    BDBG_ASSERT(NULL != pSettings);
729
730    *pSettings = handle->settings;
731}
732
733/***************************************************************************
734Summary:
735Set Settings for an audio decoder
736***************************************************************************/
737NEXUS_Error NEXUS_AudioDecoder_SetSettings(
738    NEXUS_AudioDecoderHandle handle,
739    const NEXUS_AudioDecoderSettings *pSettings /* Settings */
740    )
741{
742    if ( NULL == pSettings )
743    {
744        NEXUS_AudioDecoder_P_GetDefaultSettings(&handle->settings);
745    }
746    else
747    {
748        if ( pSettings->fifoThreshold != handle->settings.fifoThreshold )
749        {
750            BERR_Code rc;
751
752            LOCK_TRANSPORT();
753
754            rc = NEXUS_Rave_SetCdbThreshold_priv(handle->raveContext, pSettings->fifoThreshold);
755
756            UNLOCK_TRANSPORT();
757
758            if (rc) return BERR_TRACE(rc);
759        }
760
761        handle->settings = *pSettings;
762    }
763    NEXUS_IsrCallback_Set(handle->sourceChangeAppCallback, &(handle->settings.sourceChanged));
764    NEXUS_IsrCallback_Set(handle->lockCallback, &(handle->settings.lockChanged));
765    NEXUS_IsrCallback_Set(handle->ptsErrorCallback, &(handle->settings.ptsError));
766    NEXUS_IsrCallback_Set(handle->firstPtsCallback, &(handle->settings.firstPts));
767    NEXUS_IsrCallback_Set(handle->fifoOverflowCallback, &(handle->settings.fifoOverflow));
768    NEXUS_IsrCallback_Set(handle->streamStatusCallback, &(handle->settings.streamStatusAvailable));
769    return NEXUS_AudioDecoder_ApplySettings_priv(handle);
770}
771
772/***************************************************************************
773Summary:
774Initialize an audio decoder program structure
775***************************************************************************/
776void NEXUS_AudioDecoder_GetDefaultStartSettings(
777    NEXUS_AudioDecoderStartSettings *pSettings /* [out] Program Defaults */
778    )
779{
780    BKNI_Memset(pSettings, 0, sizeof(NEXUS_AudioDecoderStartSettings));
781    pSettings->codec = NEXUS_AudioCodec_eAc3;
782    pSettings->targetSyncEnabled = true;
783}
784
785/***************************************************************************
786Summary:
787Start deocding the specified program
788***************************************************************************/
789NEXUS_Error NEXUS_AudioDecoder_Start(
790    NEXUS_AudioDecoderHandle handle,
791    const NEXUS_AudioDecoderStartSettings *pProgram    /* What to start decoding */
792    )
793{
794    NEXUS_Error errCode;
795    bool useTsm, playback=false;
796    NEXUS_PidChannelStatus pidChannelStatus;
797    NEXUS_RaveSettings raveSettings;
798    BAVC_StreamType streamType=BAVC_StreamType_eTsMpeg;
799    BAPE_DecoderStartSettings *pStartSettings;
800    BAPE_DecoderTsmSettings tsmSettings;
801
802
803    BDBG_ENTER(NEXUS_AudioDecoder_Start);
804
805    BDBG_OBJECT_ASSERT(handle, NEXUS_AudioDecoder);
806    BDBG_ASSERT(NULL != pProgram);
807
808    if ( handle->started )
809    {
810        BDBG_ERR(("This decoder is already started.  Please call stop first."));
811        return BERR_TRACE(BERR_INVALID_PARAMETER);
812    }
813
814    pStartSettings = &handle->apeStartSettings;
815    BAPE_Decoder_GetDefaultStartSettings(pStartSettings);
816    pStartSettings->targetSyncEnabled = pProgram->targetSyncEnabled;
817    pStartSettings->nonRealTime = pProgram->nonRealTime;
818    switch ( pProgram->mixingMode )
819    {
820    default:
821        BDBG_ERR(("Invalid mixing mode"));
822        return BERR_TRACE(BERR_INVALID_PARAMETER);
823    case NEXUS_AudioDecoderMixingMode_eDescription:
824        pStartSettings->mixingMode = BAPE_DecoderMixingMode_eDescription;
825        break;
826    case NEXUS_AudioDecoderMixingMode_eSoundEffects:
827        pStartSettings->mixingMode = BAPE_DecoderMixingMode_eSoundEffects;
828        break;
829    }
830    NEXUS_AudioDecoder_P_TrickReset(handle); /* reset trick state on start */
831
832    /* Save Program */
833    handle->programSettings = *pProgram;
834
835    /* Sanity check program */
836    if ( pProgram->pidChannel )
837    {
838        /* Transport source */
839        errCode = NEXUS_PidChannel_GetStatus(pProgram->pidChannel, &pidChannelStatus);
840        if ( errCode )
841        {
842            errCode = BERR_TRACE(errCode);
843        }
844
845        handle->isPlayback = pidChannelStatus.playback;
846        playback = handle->isPlayback;
847
848        /* There are 4 types of DSS A/V streams:
849        DSS SD video - this is DSS ES
850        DSS HD video - this is DSS PES
851        DSS MPEG audio - this actually uses MPEG1 system headers, but it's very similar to PES, therefore DSS PES
852            Therefore we convert DSS ES to DSS PES here.
853        DSS AC3 audio - uses MPEG2 System PES, therefore DSS PES
854        */
855        if (pidChannelStatus.transportType == NEXUS_TransportType_eDssEs)
856        {
857            pidChannelStatus.transportType = NEXUS_TransportType_eDssPes;
858        }
859        /* All DSS is converted to PES above */
860        handle->isDss = (pidChannelStatus.transportType == NEXUS_TransportType_eDssPes)?true:false;
861
862        /* Convert to AVC transport type */
863        errCode = NEXUS_P_TransportType_ToMagnum(pidChannelStatus.transportType, &streamType);
864        if (errCode) return BERR_TRACE(errCode);
865
866        switch( pidChannelStatus.transportType )
867        {
868        case NEXUS_TransportType_eEs:
869            streamType = BAVC_StreamType_eEs;
870            break;
871        case NEXUS_TransportType_eTs:
872            streamType = BAVC_StreamType_eTsMpeg;
873            break;
874        case NEXUS_TransportType_eDssEs:
875            streamType = BAVC_StreamType_eDssEs;
876            break;
877        case NEXUS_TransportType_eDssPes:
878            streamType = BAVC_StreamType_eDssPes;
879            break;
880        case NEXUS_TransportType_eMpeg2Pes:
881            streamType = BAVC_StreamType_ePes;
882            break;
883        case NEXUS_TransportType_eMpeg1Ps:
884            streamType = BAVC_StreamType_eMpeg1System;
885            break;
886        default:
887            return BERR_TRACE(BERR_INVALID_PARAMETER);
888        }
889    }
890    else if ( pProgram->input )
891    {
892        streamType = BAVC_StreamType_ePes;
893        handle->isPlayback = false;
894        handle->isDss = false;
895        pStartSettings->inputPort = NEXUS_AudioInput_P_GetInputPort(pProgram->input);
896        /* TODO: Make this a start-time parameter from nexus */
897        pStartSettings->delayMode = BAPE_DspDelayMode_eLow;
898        if ( NULL == pStartSettings->inputPort )
899        {
900            return BERR_TRACE(BERR_INVALID_PARAMETER);
901        }
902        playback = false;
903        BKNI_Memset(&pidChannelStatus, 0, sizeof(NEXUS_PidChannelStatus));       
904    }
905    else
906    {
907        BDBG_ERR(("No PID Channel or Input provided"));
908        return BERR_TRACE(BERR_INVALID_PARAMETER);
909    }
910
911    pStartSettings->streamType = streamType;
912    pStartSettings->codec = NEXUS_Audio_P_CodecToMagnum(pProgram->codec);
913
914    if (pProgram->stcChannel) 
915    {
916        NEXUS_StcChannelSettings stcSettings;
917        LOCK_TRANSPORT();
918        NEXUS_StcChannel_GetIndex_priv(pProgram->stcChannel, &pStartSettings->stcIndex);
919        UNLOCK_TRANSPORT();
920        NEXUS_StcChannel_GetSettings(pProgram->stcChannel, &stcSettings);
921        playback = (stcSettings.mode != NEXUS_StcChannelMode_ePcr && NULL == pProgram->input);
922    }
923
924    /* Compute TSM details */
925    BAPE_Decoder_GetTsmSettings(handle->channel, &tsmSettings);
926    tsmSettings.playback = handle->isPlayback && playback;
927    tsmSettings.ptsOffset = handle->settings.ptsOffset + handle->syncSettings.delay;
928    tsmSettings.thresholds.discard = (tsmSettings.playback)?30000:3000;   /* ms */
929    tsmSettings.thresholds.grossAdjustment = (pidChannelStatus.originalTransportType == NEXUS_TransportType_eAvi) ? 0x30 : 0x8;
930    BAPE_Decoder_SetTsmSettings(handle->channel, &tsmSettings);
931
932    /* Determine TSM mode */
933    if ( NULL == pProgram->stcChannel ||
934         NULL != NEXUS_GetEnv("force_vsync") ||
935         (pProgram->pidChannel && (pidChannelStatus.transportType == NEXUS_TransportType_eEs ||
936                                   pidChannelStatus.originalTransportType == NEXUS_TransportType_eWav ||
937                                   #if 1 /* SW7425-2000: OGG PTS values are invalid from bmedia currently */
938                                   pidChannelStatus.originalTransportType == NEXUS_TransportType_eOgg ||
939                                   #endif
940                                   pidChannelStatus.originalTransportType == NEXUS_TransportType_eEs)) )
941    {
942        useTsm = false;
943    }
944    else
945    {
946        useTsm = true;
947    }
948    handle->tsmPermitted = useTsm;
949    NEXUS_AudioDecoder_P_SetTsm(handle);
950
951    if ( pProgram->pidChannel )
952    {
953        LOCK_TRANSPORT();
954        NEXUS_Rave_GetDefaultSettings_priv(&raveSettings);
955        raveSettings.pidChannel = pProgram->pidChannel;
956        raveSettings.bandHold = handle->isPlayback;
957        raveSettings.continuityCountEnabled = !handle->isPlayback;
958        raveSettings.numOutputBytesEnabled = true;
959        raveSettings.audioDescriptor = pProgram->secondaryDecoder; /* We need descriptor values for any secondary decoder */
960        errCode = NEXUS_Rave_ConfigureAudio_priv(handle->raveContext, pProgram->codec, &raveSettings);
961        if (errCode)
962        {
963            UNLOCK_TRANSPORT();
964            return BERR_TRACE(errCode);
965        }
966        errCode = NEXUS_Rave_GetStatus_priv(handle->raveContext, &handle->raveStatus);
967        UNLOCK_TRANSPORT();
968        if (errCode)
969        {
970            errCode = BERR_TRACE(errCode);
971            goto err_rave_status;
972        }
973        pStartSettings->pContextMap = &handle->raveStatus.xptContextMap;
974    }
975
976    if ( pProgram->input )
977    {
978        if ( NEXUS_AudioInput_P_SupportsFormatChanges(pProgram->input) )
979        {
980            /* If this input supports dynamic format changes, enable the dynamic format change interrupt and kick off the format state machine. */
981            errCode = NEXUS_AudioInput_P_SetFormatChangeInterrupt(pProgram->input, NEXUS_AudioDecoder_P_InputFormatChange_isr, handle, 0);
982            if ( errCode )
983            {
984                errCode = BERR_TRACE(errCode);
985                goto err_start;
986            }
987            handle->started = true;
988            NEXUS_AudioDecoder_P_InputFormatChange(handle);
989            return BERR_SUCCESS;
990        }
991    }
992
993    /* We're ready to start.  Build up lists of outputs to check for configuration changes. */
994    errCode = NEXUS_AudioDecoder_P_Start(handle);
995    if ( errCode )
996    {
997        errCode=BERR_TRACE(errCode);
998        goto err_start;
999    }
1000
1001    handle->started = true;
1002
1003    BDBG_LEAVE(NEXUS_AudioDecoder_Start);
1004
1005    /* Success */
1006    return BERR_SUCCESS;
1007
1008err_start:
1009err_rave_status:
1010    if ( pProgram->pidChannel )
1011    {
1012        LOCK_TRANSPORT();
1013        NEXUS_Rave_RemovePidChannel_priv(handle->raveContext);
1014        UNLOCK_TRANSPORT();
1015    }
1016   return errCode;
1017}
1018
1019/***************************************************************************
1020Summary:
1021Stop deocding the current program
1022***************************************************************************/
1023void NEXUS_AudioDecoder_Stop(
1024    NEXUS_AudioDecoderHandle handle
1025    )
1026{
1027    NEXUS_Error errCode;
1028
1029    BDBG_OBJECT_ASSERT(handle, NEXUS_AudioDecoder);
1030
1031    BDBG_ENTER(NEXUS_AudioDecoder_Stop);
1032
1033    if ( !handle->started )
1034    {
1035        BDBG_ERR(("Decoder not started"));
1036        return;
1037    }
1038
1039    if ( handle->programSettings.input )
1040    {
1041        if ( NEXUS_AudioInput_P_SupportsFormatChanges(handle->programSettings.input) )
1042        {
1043            /* If this input supports dynamic format changes, disable the dynamic format change interrupt. */
1044            (void)NEXUS_AudioInput_P_SetFormatChangeInterrupt(handle->programSettings.input, NULL, NULL, 0);
1045        }
1046    }
1047
1048    errCode = NEXUS_AudioDecoder_P_Stop(handle, true);
1049    if ( errCode )
1050    {
1051        errCode = BERR_TRACE(errCode);
1052    }
1053
1054    handle->running = false;
1055    handle->started = false;
1056    handle->trickForceStopped = false; /* do we need to forcedly unmute on Stop, in a way it helps if in a PIP change mode decoder is moved from trickmode on one channel to normal mode on another channel, however it hurts if one stops decoder just in order to change a PID/ audio program */
1057
1058    if ( handle->programSettings.pidChannel )
1059    {
1060        LOCK_TRANSPORT();
1061        NEXUS_Rave_RemovePidChannel_priv(handle->raveContext);
1062        UNLOCK_TRANSPORT();
1063    }
1064
1065    BKNI_Memset(&handle->programSettings, 0, sizeof(handle->programSettings));
1066
1067    BDBG_LEAVE(NEXUS_AudioDecoder_Stop);
1068}
1069
1070/***************************************************************************
1071Summary:
1072Discards all data accumulated in the decoder buffer
1073***************************************************************************/
1074NEXUS_Error NEXUS_AudioDecoder_Flush(
1075    NEXUS_AudioDecoderHandle handle
1076    )
1077{
1078    BERR_Code rc = BERR_SUCCESS;
1079    BDBG_OBJECT_ASSERT(handle, NEXUS_AudioDecoder);
1080
1081    if ( !handle->started || !handle->running )
1082    {
1083        return BERR_SUCCESS;
1084    }
1085
1086    BAPE_Decoder_DisableForFlush(handle->channel);
1087
1088    BDBG_ASSERT(handle->raveContext);
1089
1090    if ( handle->programSettings.pidChannel )
1091    {
1092        LOCK_TRANSPORT();
1093        NEXUS_Rave_Disable_priv(handle->raveContext);
1094        NEXUS_Rave_Flush_priv(handle->raveContext);
1095        UNLOCK_TRANSPORT();
1096    }
1097
1098    rc = BAPE_Decoder_Flush(handle->channel);
1099    if ( rc )
1100    {
1101        (void)BERR_TRACE(rc);
1102    }
1103
1104    if ( handle->programSettings.pidChannel )
1105    {
1106        LOCK_TRANSPORT();
1107        NEXUS_Rave_Enable_priv(handle->raveContext);
1108        UNLOCK_TRANSPORT();
1109    }
1110
1111    return rc;
1112}
1113
1114/***************************************************************************
1115Summary:
1116    Get codec-specific decoder settings
1117***************************************************************************/
1118void NEXUS_AudioDecoder_GetCodecSettings(
1119    NEXUS_AudioDecoderHandle handle,
1120    NEXUS_AudioCodec codec,
1121    NEXUS_AudioDecoderCodecSettings *pSettings  /* [out] settings for specified codec */
1122    )
1123{
1124    BAPE_DecoderCodecSettings codecSettings;
1125    BAVC_AudioCompressionStd avcCodec;
1126
1127    BDBG_OBJECT_ASSERT(handle, NEXUS_AudioDecoder);
1128    BDBG_ASSERT(NULL != pSettings);
1129
1130    avcCodec = NEXUS_Audio_P_CodecToMagnum(codec);
1131
1132    BKNI_Memset(pSettings, 0, sizeof(*pSettings));
1133    pSettings->codec = codec;
1134
1135    BAPE_Decoder_GetCodecSettings(handle->channel, avcCodec, &codecSettings);
1136    switch ( codec )
1137    {
1138    case NEXUS_AudioCodec_eAc3:
1139        BDBG_CASSERT(NEXUS_AudioDecoderDolbyDrcMode_eLine == (NEXUS_AudioDecoderDolbyDrcMode)BAPE_Ac3DrcMode_eLine);
1140        BDBG_CASSERT(NEXUS_AudioDecoderDolbyDrcMode_eRf == (NEXUS_AudioDecoderDolbyDrcMode)BAPE_Ac3DrcMode_eRf);
1141        BDBG_CASSERT(NEXUS_AudioDecoderDolbyDrcMode_eCustomA == (NEXUS_AudioDecoderDolbyDrcMode)BAPE_Ac3DrcMode_eCustomA);
1142        BDBG_CASSERT(NEXUS_AudioDecoderDolbyDrcMode_eCustomD == (NEXUS_AudioDecoderDolbyDrcMode)BAPE_Ac3DrcMode_eCustomD);
1143        pSettings->codecSettings.ac3.drcMode = codecSettings.codecSettings.ac3.drcMode;
1144        pSettings->codecSettings.ac3.drcModeDownmix = codecSettings.codecSettings.ac3.drcModeDownmix;
1145        pSettings->codecSettings.ac3.cut = codecSettings.codecSettings.ac3.drcScaleHi;
1146        pSettings->codecSettings.ac3.boost = codecSettings.codecSettings.ac3.drcScaleLow;
1147        pSettings->codecSettings.ac3.cutDownmix = codecSettings.codecSettings.ac3.drcScaleHiDownmix;
1148        pSettings->codecSettings.ac3.boostDownmix = codecSettings.codecSettings.ac3.drcScaleLowDownmix;
1149        BDBG_CASSERT(NEXUS_AudioDecoderDolbyStereoDownmixMode_eAutomatic == (NEXUS_AudioDecoderDolbyStereoDownmixMode)BAPE_Ac3StereoMode_eAuto);
1150        BDBG_CASSERT(NEXUS_AudioDecoderDolbyStereoDownmixMode_eDolbySurroundCompatible == (NEXUS_AudioDecoderDolbyStereoDownmixMode)BAPE_Ac3StereoMode_eLtRt);
1151        BDBG_CASSERT(NEXUS_AudioDecoderDolbyStereoDownmixMode_eStandard == (NEXUS_AudioDecoderDolbyStereoDownmixMode)BAPE_Ac3StereoMode_eLoRo);
1152        pSettings->codecSettings.ac3.stereoDownmixMode = codecSettings.codecSettings.ac3.stereoMode;
1153        pSettings->codecSettings.ac3.scale = codecSettings.codecSettings.ac3.scale;
1154        pSettings->codecSettings.ac3.scaleDownmix = codecSettings.codecSettings.ac3.scaleDownmix;
1155        pSettings->codecSettings.ac3.dialogNormalization = codecSettings.codecSettings.ac3.dialogNormalization;
1156        pSettings->codecSettings.ac3.dialogNormalizationValue = codecSettings.codecSettings.ac3.dialogNormalizationValue;
1157        pSettings->codecSettings.ac3.substreamId = codecSettings.codecSettings.ac3.substreamId;
1158        break;
1159    case NEXUS_AudioCodec_eAc3Plus:
1160        pSettings->codecSettings.ac3Plus.drcMode = codecSettings.codecSettings.ac3Plus.drcMode;
1161        pSettings->codecSettings.ac3Plus.drcModeDownmix = codecSettings.codecSettings.ac3Plus.drcModeDownmix;
1162        pSettings->codecSettings.ac3Plus.cut = codecSettings.codecSettings.ac3Plus.drcScaleHi;
1163        pSettings->codecSettings.ac3Plus.boost = codecSettings.codecSettings.ac3Plus.drcScaleLow;
1164        pSettings->codecSettings.ac3Plus.cutDownmix = codecSettings.codecSettings.ac3Plus.drcScaleHiDownmix;
1165        pSettings->codecSettings.ac3Plus.boostDownmix = codecSettings.codecSettings.ac3Plus.drcScaleLowDownmix;
1166        pSettings->codecSettings.ac3Plus.stereoDownmixMode = codecSettings.codecSettings.ac3Plus.stereoMode;
1167        pSettings->codecSettings.ac3Plus.scale = codecSettings.codecSettings.ac3Plus.scale;
1168        pSettings->codecSettings.ac3Plus.scaleDownmix = codecSettings.codecSettings.ac3Plus.scaleDownmix;
1169        pSettings->codecSettings.ac3Plus.dialogNormalization = codecSettings.codecSettings.ac3Plus.dialogNormalization;
1170        pSettings->codecSettings.ac3Plus.dialogNormalizationValue = codecSettings.codecSettings.ac3Plus.dialogNormalizationValue;
1171        pSettings->codecSettings.ac3Plus.substreamId = codecSettings.codecSettings.ac3Plus.substreamId;
1172        break;
1173    case NEXUS_AudioCodec_eAacAdts:
1174    case NEXUS_AudioCodec_eAacLoas:
1175        pSettings->codecSettings.aac.cut = codecSettings.codecSettings.aac.drcScaleHi;
1176        pSettings->codecSettings.aac.boost = codecSettings.codecSettings.aac.drcScaleLow;
1177        pSettings->codecSettings.aac.drcTargetLevel = codecSettings.codecSettings.aac.drcTargetLevel;
1178        BDBG_CASSERT((int)BAPE_AacStereoMode_eMatrix == (int)NEXUS_AudioDecoderAacDownmixMode_eMatrix);
1179        BDBG_CASSERT((int)BAPE_AacStereoMode_eArib == (int)NEXUS_AudioDecoderAacDownmixMode_eArib);
1180        BDBG_CASSERT((int)BAPE_AacStereoMode_eLtRt == (int)NEXUS_AudioDecoderAacDownmixMode_eLtRt);
1181        BDBG_CASSERT((int)BAPE_AacStereoMode_eLoRo == (int)NEXUS_AudioDecoderAacDownmixMode_eLoRo);
1182        pSettings->codecSettings.aac.downmixMode = codecSettings.codecSettings.aac.downmixMode;
1183        BDBG_CASSERT((int)NEXUS_AudioDecoderDolbyPulseDrcMode_eLine == (int)BAPE_DolbyPulseDrcMode_eLine);
1184        BDBG_CASSERT((int)NEXUS_AudioDecoderDolbyPulseDrcMode_eRf == (int)BAPE_DolbyPulseDrcMode_eRf);
1185        pSettings->codecSettings.aac.drcMode = codecSettings.codecSettings.aac.drcMode;
1186        pSettings->codecSettings.aac.drcTargetLevel = codecSettings.codecSettings.aac.drcDefaultLevel;
1187        pSettings->codecSettings.aac.mpegConformanceMode = codecSettings.codecSettings.aac.mpegConformanceMode;
1188        break;
1189    case NEXUS_AudioCodec_eAacPlusAdts:
1190    case NEXUS_AudioCodec_eAacPlusLoas:
1191        pSettings->codecSettings.aacPlus.cut = codecSettings.codecSettings.aacPlus.drcScaleHi;
1192        pSettings->codecSettings.aacPlus.boost = codecSettings.codecSettings.aacPlus.drcScaleLow;
1193        pSettings->codecSettings.aacPlus.drcTargetLevel = codecSettings.codecSettings.aacPlus.drcTargetLevel;
1194        BDBG_CASSERT((int)BAPE_AacStereoMode_eMatrix == (int)NEXUS_AudioDecoderAacDownmixMode_eMatrix);
1195        BDBG_CASSERT((int)BAPE_AacStereoMode_eArib == (int)NEXUS_AudioDecoderAacDownmixMode_eArib);
1196        BDBG_CASSERT((int)BAPE_AacStereoMode_eLtRt == (int)NEXUS_AudioDecoderAacDownmixMode_eLtRt);
1197        BDBG_CASSERT((int)BAPE_AacStereoMode_eLoRo == (int)NEXUS_AudioDecoderAacDownmixMode_eLoRo);
1198        pSettings->codecSettings.aacPlus.downmixMode = codecSettings.codecSettings.aacPlus.downmixMode;
1199        BDBG_CASSERT((int)NEXUS_AudioDecoderDolbyPulseDrcMode_eLine == (int)BAPE_DolbyPulseDrcMode_eLine);
1200        BDBG_CASSERT((int)NEXUS_AudioDecoderDolbyPulseDrcMode_eRf == (int)BAPE_DolbyPulseDrcMode_eRf);
1201        pSettings->codecSettings.aacPlus.drcMode = codecSettings.codecSettings.aacPlus.drcMode;
1202        pSettings->codecSettings.aacPlus.drcTargetLevel = codecSettings.codecSettings.aacPlus.drcDefaultLevel;
1203        pSettings->codecSettings.aacPlus.mpegConformanceMode = codecSettings.codecSettings.aacPlus.mpegConformanceMode;
1204        break;
1205    case NEXUS_AudioCodec_eWmaPro:
1206        /* TODO: Nexus is exposing the older WMA Pro DRC mode.  This should switch from bool .. enum to match APE */
1207        switch ( codecSettings.codecSettings.wmaPro.drcMode )
1208        {
1209        case BAPE_WmaProDrcMode_eDisabled:
1210            pSettings->codecSettings.wmaPro.dynamicRangeControlValid = false;
1211            break;
1212        default:
1213            pSettings->codecSettings.wmaPro.dynamicRangeControlValid = true;
1214            break;
1215        }
1216        /* TODO: Expose stereo mode */
1217        pSettings->codecSettings.wmaPro.dynamicRangeControl.peakReference = codecSettings.codecSettings.wmaPro.peakAmplitudeReference;
1218        pSettings->codecSettings.wmaPro.dynamicRangeControl.peakTarget = codecSettings.codecSettings.wmaPro.desiredPeak;
1219        pSettings->codecSettings.wmaPro.dynamicRangeControl.averageReference = codecSettings.codecSettings.wmaPro.rmsAmplitudeReference;
1220        pSettings->codecSettings.wmaPro.dynamicRangeControl.averageTarget = codecSettings.codecSettings.wmaPro.desiredRms;
1221        break;
1222    case NEXUS_AudioCodec_eDts:
1223    case NEXUS_AudioCodec_eDtsHd:
1224    case NEXUS_AudioCodec_eDtsLegacy: /* For DTS streams with legacy frame-sync.  These streams are something called as 14bits stream */
1225        pSettings->codecSettings.dts.mixLfeToPrimary = codecSettings.codecSettings.dts.mixLfeToPrimary;
1226        BDBG_CASSERT((int)NEXUS_AudioDecoderDtsDownmixMode_eAuto == (int)BAPE_DtsStereoMode_eAuto);
1227        BDBG_CASSERT((int)NEXUS_AudioDecoderDtsDownmixMode_eLtRt == (int)BAPE_DtsStereoMode_eLtRt);
1228        BDBG_CASSERT((int)NEXUS_AudioDecoderDtsDownmixMode_eLoRo == (int)BAPE_DtsStereoMode_eLoRo);
1229        pSettings->codecSettings.dts.stereoDownmixMode = (NEXUS_AudioDecoderDtsStereoDownmixMode)codecSettings.codecSettings.dts.stereoMode;
1230        pSettings->codecSettings.dts.enableDrc = codecSettings.codecSettings.dts.drcMode == BAPE_DtsDrcMode_eEnabled ? true : false;
1231        pSettings->codecSettings.dts.boost = codecSettings.codecSettings.dts.drcScaleLow;
1232        pSettings->codecSettings.dts.cut = codecSettings.codecSettings.dts.drcScaleHi;
1233        break;
1234    case NEXUS_AudioCodec_eAdpcm:
1235        pSettings->codecSettings.adpcm.enableGain = codecSettings.codecSettings.adpcm.gain.enabled;
1236        pSettings->codecSettings.adpcm.gainFactor = codecSettings.codecSettings.adpcm.gain.factor;
1237        break;
1238    default:
1239        return;
1240    }
1241}
1242
1243/***************************************************************************
1244Summary:
1245    Set codec-specific decoder settings
1246***************************************************************************/
1247NEXUS_Error NEXUS_AudioDecoder_SetCodecSettings(
1248    NEXUS_AudioDecoderHandle handle,
1249    const NEXUS_AudioDecoderCodecSettings *pSettings
1250    )
1251{
1252    BAPE_DecoderCodecSettings codecSettings;
1253    BAVC_AudioCompressionStd avcCodec;
1254    BERR_Code errCode;
1255
1256    BDBG_OBJECT_ASSERT(handle, NEXUS_AudioDecoder);
1257    BDBG_ASSERT(NULL != pSettings);
1258
1259    avcCodec = NEXUS_Audio_P_CodecToMagnum(pSettings->codec);
1260
1261    BAPE_Decoder_GetCodecSettings(handle->channel, avcCodec, &codecSettings);
1262    switch ( pSettings->codec )
1263    {
1264    case NEXUS_AudioCodec_eAc3:
1265        codecSettings.codecSettings.ac3.drcMode = pSettings->codecSettings.ac3.drcMode;
1266        codecSettings.codecSettings.ac3.drcModeDownmix = pSettings->codecSettings.ac3.drcModeDownmix;
1267        codecSettings.codecSettings.ac3.drcScaleHi = pSettings->codecSettings.ac3.cut;
1268        codecSettings.codecSettings.ac3.drcScaleLow = pSettings->codecSettings.ac3.boost;
1269        codecSettings.codecSettings.ac3.drcScaleHiDownmix = pSettings->codecSettings.ac3.cutDownmix;
1270        codecSettings.codecSettings.ac3.drcScaleLowDownmix = pSettings->codecSettings.ac3.boostDownmix;
1271        codecSettings.codecSettings.ac3.stereoMode = pSettings->codecSettings.ac3.stereoDownmixMode;
1272        codecSettings.codecSettings.ac3.scale = pSettings->codecSettings.ac3.scale;
1273        codecSettings.codecSettings.ac3.scaleDownmix = pSettings->codecSettings.ac3.scaleDownmix;
1274        codecSettings.codecSettings.ac3.dialogNormalization = pSettings->codecSettings.ac3.dialogNormalization;
1275        codecSettings.codecSettings.ac3.dialogNormalizationValue = pSettings->codecSettings.ac3.dialogNormalizationValue;
1276        codecSettings.codecSettings.ac3.substreamId = pSettings->codecSettings.ac3.substreamId;
1277        break;
1278    case NEXUS_AudioCodec_eAc3Plus:
1279        codecSettings.codecSettings.ac3Plus.drcMode = pSettings->codecSettings.ac3Plus.drcMode;
1280        codecSettings.codecSettings.ac3Plus.drcModeDownmix = pSettings->codecSettings.ac3Plus.drcModeDownmix;
1281        codecSettings.codecSettings.ac3Plus.drcScaleHi = pSettings->codecSettings.ac3Plus.cut;
1282        codecSettings.codecSettings.ac3Plus.drcScaleLow = pSettings->codecSettings.ac3Plus.boost;
1283        codecSettings.codecSettings.ac3Plus.drcScaleHiDownmix = pSettings->codecSettings.ac3Plus.cutDownmix;
1284        codecSettings.codecSettings.ac3Plus.drcScaleLowDownmix = pSettings->codecSettings.ac3Plus.boostDownmix;
1285        codecSettings.codecSettings.ac3Plus.stereoMode = pSettings->codecSettings.ac3Plus.stereoDownmixMode;
1286        codecSettings.codecSettings.ac3Plus.scale = pSettings->codecSettings.ac3Plus.scale;
1287        codecSettings.codecSettings.ac3Plus.scaleDownmix = pSettings->codecSettings.ac3Plus.scaleDownmix;
1288        codecSettings.codecSettings.ac3Plus.dialogNormalization = pSettings->codecSettings.ac3Plus.dialogNormalization;
1289        codecSettings.codecSettings.ac3Plus.dialogNormalizationValue = pSettings->codecSettings.ac3Plus.dialogNormalizationValue;
1290        codecSettings.codecSettings.ac3Plus.substreamId = pSettings->codecSettings.ac3Plus.substreamId;
1291        break;
1292    case NEXUS_AudioCodec_eAacAdts:
1293    case NEXUS_AudioCodec_eAacLoas:
1294        codecSettings.codecSettings.aac.drcScaleHi = pSettings->codecSettings.aac.cut;
1295        codecSettings.codecSettings.aac.drcScaleLow = pSettings->codecSettings.aac.boost;
1296        codecSettings.codecSettings.aac.drcTargetLevel = pSettings->codecSettings.aac.drcTargetLevel;
1297        codecSettings.codecSettings.aac.downmixMode = pSettings->codecSettings.aac.downmixMode;
1298        codecSettings.codecSettings.aac.drcMode = pSettings->codecSettings.aac.drcMode;
1299        codecSettings.codecSettings.aac.drcDefaultLevel = pSettings->codecSettings.aac.drcTargetLevel;
1300        codecSettings.codecSettings.aac.mpegConformanceMode = pSettings->codecSettings.aac.mpegConformanceMode;
1301        break;
1302    case NEXUS_AudioCodec_eAacPlusAdts:
1303    case NEXUS_AudioCodec_eAacPlusLoas:
1304        codecSettings.codecSettings.aacPlus.drcScaleHi = pSettings->codecSettings.aacPlus.cut;
1305        codecSettings.codecSettings.aacPlus.drcScaleLow = pSettings->codecSettings.aacPlus.boost;
1306        codecSettings.codecSettings.aacPlus.drcTargetLevel = pSettings->codecSettings.aacPlus.drcTargetLevel;
1307        codecSettings.codecSettings.aacPlus.downmixMode = pSettings->codecSettings.aacPlus.downmixMode;
1308        codecSettings.codecSettings.aacPlus.drcMode = pSettings->codecSettings.aacPlus.drcMode;
1309        codecSettings.codecSettings.aacPlus.drcDefaultLevel = pSettings->codecSettings.aacPlus.drcTargetLevel;
1310        codecSettings.codecSettings.aacPlus.mpegConformanceMode = pSettings->codecSettings.aacPlus.mpegConformanceMode;
1311        break;
1312    case NEXUS_AudioCodec_eWmaPro:
1313        /* TODO: Nexus is exposing the older WMA Pro DRC mode.  This should switch from bool .. enum to match APE */
1314        if ( pSettings->codecSettings.wmaPro.dynamicRangeControlValid )
1315        {
1316            codecSettings.codecSettings.wmaPro.drcMode = BAPE_WmaProDrcMode_eHigh;
1317        }
1318        else
1319        {
1320            codecSettings.codecSettings.wmaPro.drcMode = BAPE_WmaProDrcMode_eDisabled;
1321        }
1322        /* TODO: Expose stereo mode */
1323        codecSettings.codecSettings.wmaPro.peakAmplitudeReference = pSettings->codecSettings.wmaPro.dynamicRangeControl.peakReference;
1324        codecSettings.codecSettings.wmaPro.desiredPeak = pSettings->codecSettings.wmaPro.dynamicRangeControl.peakTarget;
1325        codecSettings.codecSettings.wmaPro.rmsAmplitudeReference = pSettings->codecSettings.wmaPro.dynamicRangeControl.averageReference;
1326        codecSettings.codecSettings.wmaPro.desiredRms = pSettings->codecSettings.wmaPro.dynamicRangeControl.averageTarget;
1327        break;
1328    case NEXUS_AudioCodec_eDts:
1329    case NEXUS_AudioCodec_eDtsHd:
1330    case NEXUS_AudioCodec_eDtsLegacy: /* For DTS streams with legacy frame-sync.  These streams are something called as 14bits stream */
1331        codecSettings.codecSettings.dts.mixLfeToPrimary = pSettings->codecSettings.dts.mixLfeToPrimary;
1332        codecSettings.codecSettings.dts.stereoMode = (BAPE_DtsStereoMode)pSettings->codecSettings.dts.stereoDownmixMode;
1333        codecSettings.codecSettings.dts.drcMode = pSettings->codecSettings.dts.enableDrc ? BAPE_DtsDrcMode_eEnabled : BAPE_DtsDrcMode_eDisabled;
1334        codecSettings.codecSettings.dts.drcScaleLow = pSettings->codecSettings.dts.boost;
1335        codecSettings.codecSettings.dts.drcScaleHi = pSettings->codecSettings.dts.cut;
1336        break;
1337    case NEXUS_AudioCodec_eAdpcm:
1338        codecSettings.codecSettings.adpcm.gain.enabled = pSettings->codecSettings.adpcm.enableGain;
1339        codecSettings.codecSettings.adpcm.gain.factor = pSettings->codecSettings.adpcm.gainFactor;
1340        break;
1341    default:
1342        return BERR_SUCCESS;
1343    }
1344
1345    errCode = BAPE_Decoder_SetCodecSettings(handle->channel, &codecSettings);
1346    if ( errCode )
1347    {
1348        return BERR_TRACE(errCode);
1349    }
1350    return BERR_SUCCESS;
1351}
1352
1353static unsigned NEXUS_AudioDecoder_P_GetAc3Bitrate(unsigned frameSizeCode)
1354{
1355    const unsigned bitrateTable[] = {
1356
1357        32000,  /* '000000' 32 kbps  */
1358        32000,  /* '000001' 32 kbps  */
1359        40000,  /* '000010' 40 kbps  */
1360        40000,  /* '000011' 40 kbps  */
1361        48000,  /* '000100' 48 kbps  */
1362        48000,  /* '000101' 48 kbps  */
1363        56000,  /* '000110' 56 kbps  */
1364        56000,  /* '000111' 56 kbps  */
1365        64000,  /* '001000' 64 kbps  */
1366        64000,  /* '001001' 64 kbps  */
1367        80000,  /* '001010' 80 kbps  */
1368        80000,  /* '001011' 80 kbps  */
1369        96000,  /* '001100' 96 kbps  */
1370        96000,  /* '001101' 96 kbps  */
1371        112000, /* '001110' 112 kbps */
1372        112000, /* '001111' 112 kbps */
1373
1374        128000, /* '010000' 128 kbps */
1375        128000, /* '010001' 128 kbps */
1376        160000, /* '010010' 160 kbps */
1377        160000, /* '010011' 160 kbps */
1378        192000, /* '010100' 192 kbps */
1379        192000, /* '010101' 192 kbps */
1380        224000, /* '010110' 224 kbps */
1381        224000, /* '010111' 224 kbps */
1382        256000, /* '011000' 256 kbps */
1383        256000, /* '011001' 256 kbps */
1384        320000, /* '011010' 320 kbps */
1385        320000, /* '011011' 320 kbps */
1386        384000, /* '011100' 384 kbps */
1387        384000, /* '011101' 384 kbps */
1388        448000, /* '011110' 448 kbps */
1389        448000, /* '011111' 448 kbps */
1390
1391        512000, /* '100000' 512 kbps */
1392        512000, /* '100001' 512 kbps */
1393        576000, /* '100010' 576 kbps */
1394        576000, /* '100011' 576 kbps */
1395        640000, /* '100100' 640 kbps */
1396        640000  /* '100101' 640 kbps */
1397    };
1398
1399    if ( frameSizeCode < 38 )
1400    {
1401        return bitrateTable[frameSizeCode];
1402    }
1403    else
1404    {
1405        return 0;
1406    }
1407}
1408
1409/***************************************************************************
1410Summary:
1411    Get the current audio decoder status
1412***************************************************************************/
1413NEXUS_Error NEXUS_AudioDecoder_GetStatus(
1414    NEXUS_AudioDecoderHandle handle,
1415    NEXUS_AudioDecoderStatus *pStatus   /* [out] current status */
1416    )
1417{
1418    unsigned depth=0, size=0;
1419    BAPE_DecoderStatus decoderStatus;
1420
1421    BDBG_OBJECT_ASSERT(handle, NEXUS_AudioDecoder);
1422    BDBG_ASSERT(NULL != pStatus);
1423
1424    BKNI_Memset(pStatus, 0, sizeof(NEXUS_AudioDecoderStatus));
1425    pStatus->started = handle->started;
1426    pStatus->locked = handle->locked;
1427    pStatus->codec = handle->programSettings.codec;
1428    pStatus->ptsType = NEXUS_PtsType_eInterpolatedFromInvalidPTS;
1429    pStatus->numFifoOverflows = handle->numFifoOverflows;
1430    pStatus->numFifoUnderflows = handle->numFifoUnderflows;
1431
1432    if(!handle->running)
1433    {
1434        return BERR_SUCCESS;
1435    }
1436
1437    BKNI_EnterCriticalSection();
1438    if ( handle->programSettings.pidChannel )
1439    {
1440        NEXUS_Rave_GetCdbBufferInfo_isr(handle->raveContext, &depth, &size);
1441    }
1442    BKNI_LeaveCriticalSection();
1443
1444    pStatus->fifoDepth = depth;
1445    pStatus->fifoSize = size;
1446
1447    pStatus->tsm = handle->tsmEnabled;
1448    pStatus->timebase = handle->apeStartSettings.stcIndex;
1449    pStatus->ptsErrorCount = handle->ptsErrorCount;
1450    pStatus->codec = handle->programSettings.codec;
1451    pStatus->numWatchdogs = g_numWatchdogs;
1452
1453    if ( handle->programSettings.pidChannel )
1454    {
1455        NEXUS_RaveStatus raveStatus;
1456        NEXUS_Error errCode;
1457        LOCK_TRANSPORT();
1458        NEXUS_Rave_GetAudioFrameCount_priv(handle->raveContext, &pStatus->queuedFrames);
1459        errCode = NEXUS_Rave_GetStatus_priv(handle->raveContext, &raveStatus);
1460        UNLOCK_TRANSPORT();
1461        if ( NEXUS_SUCCESS == errCode )
1462        {
1463            pStatus->numBytesDecoded = raveStatus.numOutputBytes;
1464        }
1465    }
1466
1467    /* Get decoder info */
1468    BAPE_Decoder_GetStatus(handle->channel, &decoderStatus);
1469    {
1470        unsigned frameLength, bitrate;
1471
1472        pStatus->sampleRate = decoderStatus.sampleRate;
1473        pStatus->pts = decoderStatus.tsmStatus.ptsInfo.ui32CurrentPTS;
1474        pStatus->ptsType = decoderStatus.tsmStatus.ptsInfo.ePTSType == BAVC_PTSType_eCoded ? NEXUS_PtsType_eCoded :
1475            decoderStatus.tsmStatus.ptsInfo.ePTSType == BAVC_PTSType_eInterpolatedFromValidPTS ? NEXUS_PtsType_eInterpolatedFromValidPTS : NEXUS_PtsType_eInterpolatedFromInvalidPTS;
1476        pStatus->ptsStcDifference = decoderStatus.tsmStatus.ptsStcDifference;
1477
1478        pStatus->framesDecoded = decoderStatus.framesDecoded;
1479        pStatus->frameErrors = decoderStatus.frameErrors;
1480        pStatus->dummyFrames = decoderStatus.dummyFrames;
1481
1482        /* Convert codec to nexus type */
1483        pStatus->codec = NEXUS_Audio_P_MagnumToCodec(decoderStatus.codec);
1484       
1485        /* Handle specifics per-codec */
1486        switch ( decoderStatus.codec )
1487        {
1488        case BAVC_AudioCompressionStd_eMpegL1:
1489        case BAVC_AudioCompressionStd_eMpegL2:
1490        case BAVC_AudioCompressionStd_eMpegL3:
1491            pStatus->codec = (decoderStatus.codecStatus.mpeg.layer == 3)?NEXUS_AudioCodec_eMp3:NEXUS_AudioCodec_eMpeg;
1492            pStatus->codecStatus.mpeg.channelMode = decoderStatus.codecStatus.mpeg.mpegChannelMode;
1493            switch (  decoderStatus.codecStatus.mpeg.layer )
1494            {
1495            default:
1496            case 1:
1497                pStatus->codecStatus.mpeg.layer = NEXUS_AudioMpegLayer_e1;
1498                pStatus->codec = NEXUS_AudioCodec_eMpeg;
1499                break;
1500            case 2:
1501                pStatus->codecStatus.mpeg.layer = NEXUS_AudioMpegLayer_e2;
1502                pStatus->codec = NEXUS_AudioCodec_eMpeg;
1503                break;
1504            case 3:
1505                pStatus->codecStatus.mpeg.layer = NEXUS_AudioMpegLayer_e3;
1506                pStatus->codec = NEXUS_AudioCodec_eMp3;
1507                break;
1508            }
1509            pStatus->codecStatus.mpeg.emphasis = decoderStatus.codecStatus.mpeg.emphasisMode;
1510            pStatus->codecStatus.mpeg.original = decoderStatus.codecStatus.mpeg.original;
1511            pStatus->codecStatus.mpeg.copyright = decoderStatus.codecStatus.mpeg.copyright;
1512            pStatus->codecStatus.mpeg.bitrate = decoderStatus.codecStatus.mpeg.bitRate;
1513            if (  pStatus->sampleRate > 0 )
1514            {
1515                /* MPEG audio uses a CDB sync, so the frame count is bogus.  Calculate based on frame size and CDB depth */
1516                bitrate = (decoderStatus.codecStatus.mpeg.bitRate>0)?1000*decoderStatus.codecStatus.mpeg.bitRate:128000;
1517                if ( decoderStatus.codecStatus.mpeg.layer == 1 )
1518                {
1519                    frameLength = (48*bitrate)/pStatus->sampleRate;
1520                }
1521                else
1522                {
1523                    frameLength = (144*bitrate)/pStatus->sampleRate;
1524                }
1525                if ( frameLength == 0 )
1526                {
1527                    pStatus->queuedFrames = 0;
1528                }
1529                else
1530                {
1531                    pStatus->queuedFrames = pStatus->fifoDepth/frameLength;
1532                }
1533                BDBG_MSG(("Queued Frames %d bitrate %d framelength %d samplerate %d", pStatus->queuedFrames, bitrate, frameLength, pStatus->sampleRate));
1534            }
1535            break;
1536        case BAVC_AudioCompressionStd_eAacLoas:
1537        case BAVC_AudioCompressionStd_eAacAdts:
1538        case BAVC_AudioCompressionStd_eAacPlusLoas:
1539        case BAVC_AudioCompressionStd_eAacPlusAdts:
1540            /* Convert channel mode to aac acmod */
1541            switch ( decoderStatus.codecStatus.aac.channelMode )
1542            {
1543            case BAPE_ChannelMode_e1_0: pStatus->codecStatus.aac.acmod = NEXUS_AudioAacAcmod_eOneCenter_1_0_C; break;
1544            case BAPE_ChannelMode_e1_1: pStatus->codecStatus.aac.acmod = NEXUS_AudioAacAcmod_eTwoMono_1_ch1_ch2; break;
1545            case BAPE_ChannelMode_e2_0: pStatus->codecStatus.aac.acmod = NEXUS_AudioAacAcmod_eTwoChannel_2_0_L_R; break;
1546            case BAPE_ChannelMode_e3_0: pStatus->codecStatus.aac.acmod = NEXUS_AudioAacAcmod_eThreeChannel_3_0_L_C_R; break;
1547            case BAPE_ChannelMode_e2_1: pStatus->codecStatus.aac.acmod = NEXUS_AudioAacAcmod_eThreeChannel_2_1_L_R_S; break;
1548            case BAPE_ChannelMode_e3_1: pStatus->codecStatus.aac.acmod = NEXUS_AudioAacAcmod_eFourChannel_3_1_L_C_R_S; break;
1549            case BAPE_ChannelMode_e2_2: pStatus->codecStatus.aac.acmod = NEXUS_AudioAacAcmod_eFourChannel_2_2_L_R_SL_SR; break;
1550            case BAPE_ChannelMode_e3_2: pStatus->codecStatus.aac.acmod = NEXUS_AudioAacAcmod_eFiveChannel_3_2_L_C_R_SL_SR; break;
1551            default:                    pStatus->codecStatus.aac.acmod = NEXUS_AudioAacAcmod_eMax; break;
1552            }
1553            pStatus->codecStatus.aac.profile = decoderStatus.codecStatus.aac.profile;
1554            pStatus->codecStatus.aac.bitrate = decoderStatus.codecStatus.aac.bitRate;
1555            pStatus->codecStatus.aac.lfe = decoderStatus.codecStatus.aac.lfe;
1556            pStatus->codecStatus.aac.pseudoSurround = decoderStatus.codecStatus.aac.pseudoSurround;
1557            pStatus->codecStatus.aac.stereoMatrix = decoderStatus.codecStatus.aac.stereoMatrix;
1558            pStatus->codecStatus.aac.matrixIndex = decoderStatus.codecStatus.aac.matrixIndex;
1559            pStatus->codecStatus.aac.numLfeChannels = decoderStatus.codecStatus.aac.numLfeChannels;
1560            pStatus->codecStatus.aac.numBackChannels = decoderStatus.codecStatus.aac.numBackChannels;
1561            pStatus->codecStatus.aac.numSideChannels = decoderStatus.codecStatus.aac.numSideChannels;
1562            pStatus->codecStatus.aac.numFrontChannels = decoderStatus.codecStatus.aac.numFrontChannels;
1563            break;
1564        case BAVC_AudioCompressionStd_eAc3:
1565        case BAVC_AudioCompressionStd_eAc3Plus:
1566            pStatus->codec = (decoderStatus.codec == BAVC_AudioCompressionStd_eAc3)?NEXUS_AudioCodec_eAc3:NEXUS_AudioCodec_eAc3Plus;
1567            pStatus->codecStatus.ac3.bitStreamId = decoderStatus.codecStatus.ac3.bitstreamId;
1568            pStatus->codecStatus.ac3.acmod = decoderStatus.codecStatus.ac3.acmod;
1569            pStatus->codecStatus.ac3.frameSizeCode = decoderStatus.codecStatus.ac3.frameSizeCode;
1570            pStatus->codecStatus.ac3.bitrate = NEXUS_AudioDecoder_P_GetAc3Bitrate(decoderStatus.codecStatus.ac3.frameSizeCode);
1571            pStatus->codecStatus.ac3.lfe = decoderStatus.codecStatus.ac3.lfe;
1572            pStatus->codecStatus.ac3.copyright = decoderStatus.codecStatus.ac3.copyright;
1573            break;
1574        case BAVC_AudioCompressionStd_eDts:
1575        case BAVC_AudioCompressionStd_eDtshd:
1576        case BAVC_AudioCompressionStd_eDtsLegacy:
1577            pStatus->codecStatus.dts.amode = decoderStatus.codecStatus.dts.amode;
1578            pStatus->codecStatus.dts.pcmResolution = decoderStatus.codecStatus.dts.pcmResolution;
1579            pStatus->codecStatus.dts.copyHistory = decoderStatus.codecStatus.dts.copyHistory;
1580            pStatus->codecStatus.dts.extensionDescriptor = decoderStatus.codecStatus.dts.extensionDescriptor;
1581            pStatus->codecStatus.dts.bitRate = decoderStatus.codecStatus.dts.bitRate;
1582            pStatus->codecStatus.dts.version = decoderStatus.codecStatus.dts.version;
1583            pStatus->codecStatus.dts.esFormat = decoderStatus.codecStatus.dts.esFormat;
1584            pStatus->codecStatus.dts.lfe = decoderStatus.codecStatus.dts.lfe;
1585            pStatus->codecStatus.dts.extensionPresent = decoderStatus.codecStatus.dts.extensionPresent;
1586            pStatus->codecStatus.dts.crc = decoderStatus.codecStatus.dts.crc;
1587            pStatus->codecStatus.dts.hdcdFormat = decoderStatus.codecStatus.dts.hdcdFormat;
1588            pStatus->codecStatus.dts.drc = decoderStatus.codecStatus.dts.drc;
1589            pStatus->codecStatus.dts.downmixCoefficients = decoderStatus.codecStatus.dts.downmixCoefficients;
1590            pStatus->codecStatus.dts.neo = decoderStatus.codecStatus.dts.neo;
1591            pStatus->codecStatus.dts.frameSize = decoderStatus.codecStatus.dts.frameSize;
1592            pStatus->codecStatus.dts.numChannels = decoderStatus.codecStatus.dts.numChannels;
1593            pStatus->codecStatus.dts.pcmFrameSize = decoderStatus.codecStatus.dts.pcmFrameSize;
1594            pStatus->codecStatus.dts.numPcmBlocks = decoderStatus.codecStatus.dts.numPcmBlocks;
1595            break;
1596        case BAVC_AudioCompressionStd_eWmaStd:
1597        case BAVC_AudioCompressionStd_eWmaStdTs:
1598            pStatus->codecStatus.wma.bitRate = decoderStatus.codecStatus.wma.bitRate;
1599            pStatus->codecStatus.wma.original = decoderStatus.codecStatus.wma.original;
1600            pStatus->codecStatus.wma.copyright = decoderStatus.codecStatus.wma.copyright;
1601            pStatus->codecStatus.wma.crc = decoderStatus.codecStatus.wma.crc;
1602            pStatus->codecStatus.wma.stereo = decoderStatus.codecStatus.wma.channelMode == (BAPE_ChannelMode_e2_0)?true:false;
1603            pStatus->codecStatus.wma.version = decoderStatus.codecStatus.wma.version;
1604            break;
1605        case BAVC_AudioCompressionStd_eWmaPro:
1606            pStatus->codecStatus.wmaPro.bitRate = decoderStatus.codecStatus.wmaPro.bitRate;
1607            pStatus->codecStatus.wmaPro.original = decoderStatus.codecStatus.wmaPro.original;
1608            pStatus->codecStatus.wmaPro.copyright = decoderStatus.codecStatus.wmaPro.copyright;
1609            pStatus->codecStatus.wmaPro.crc = decoderStatus.codecStatus.wmaPro.crc;
1610            pStatus->codecStatus.wmaPro.lfe = decoderStatus.codecStatus.wmaPro.lfe;
1611            pStatus->codecStatus.wmaPro.version = decoderStatus.codecStatus.wmaPro.version;
1612            pStatus->codecStatus.wmaPro.stereoMode = decoderStatus.codecStatus.wmaPro.stereoMode;
1613            switch ( decoderStatus.codecStatus.wmaPro.channelMode )
1614            {
1615            case BAPE_ChannelMode_e1_0:
1616                pStatus->codecStatus.wmaPro.acmod = NEXUS_AudioWmaProAcmod_e1_0_C;
1617                break;
1618            case BAPE_ChannelMode_e2_0:
1619                pStatus->codecStatus.wmaPro.acmod = NEXUS_AudioWmaProAcmod_e2_0_LR;
1620                break;
1621            case BAPE_ChannelMode_e3_0:
1622                pStatus->codecStatus.wmaPro.acmod = NEXUS_AudioWmaProAcmod_e3_0_LCR;
1623                break;
1624            case BAPE_ChannelMode_e2_1:
1625                pStatus->codecStatus.wmaPro.acmod = NEXUS_AudioWmaProAcmod_e2_1_LRS;
1626                break;
1627            case BAPE_ChannelMode_e3_1:
1628                pStatus->codecStatus.wmaPro.acmod = NEXUS_AudioWmaProAcmod_e3_1_LCRS;
1629                break;
1630            case BAPE_ChannelMode_e2_2:
1631                pStatus->codecStatus.wmaPro.acmod = NEXUS_AudioWmaProAcmod_e2_2_LRLsRs;
1632                break;
1633            case BAPE_ChannelMode_e3_2:
1634                pStatus->codecStatus.wmaPro.acmod = NEXUS_AudioWmaProAcmod_e3_2_LCRLsRs;
1635                break;
1636            default:
1637                pStatus->codecStatus.wmaPro.acmod = NEXUS_AudioWmaProAcmod_eUndefined;
1638                break;
1639            }
1640            break;
1641        case BAVC_AudioCompressionStd_ePcmWav:
1642            pStatus->codecStatus.pcmWav.numChannels = decoderStatus.codecStatus.pcmWav.numChannels;
1643            break;
1644        case BAVC_AudioCompressionStd_eAmr:
1645            pStatus->codecStatus.amr.bitRate = decoderStatus.codecStatus.amr.bitRate;
1646            break;
1647        case BAVC_AudioCompressionStd_eDra:
1648            pStatus->codecStatus.dra.frameSize = decoderStatus.codecStatus.dra.frameSize;
1649            pStatus->codecStatus.dra.numBlocks = decoderStatus.codecStatus.dra.numBlocks;
1650            pStatus->codecStatus.dra.acmod = decoderStatus.codecStatus.dra.acmod;
1651            pStatus->codecStatus.dra.lfe = decoderStatus.codecStatus.dra.lfe;
1652            pStatus->codecStatus.dra.stereoMode = decoderStatus.codecStatus.dra.stereoMode;
1653            break;
1654        case BAVC_AudioCompressionStd_eCook:
1655            pStatus->codecStatus.cook.stereo = decoderStatus.codecStatus.cook.stereo;
1656            pStatus->codecStatus.cook.frameSize = decoderStatus.codecStatus.cook.frameSize;
1657            break;
1658        default:
1659            /* No specifics for this codec */
1660            break;
1661        }
1662    }
1663
1664    return NEXUS_SUCCESS;
1665}
1666
1667/***************************************************************************
1668Summary:
1669    Get raw channel status information from the decoder
1670   
1671Description:
1672    When the decoder is connected to a digital input, this routine can
1673    return the raw channel status bit information from the input device.
1674    Currently, this applies to HDMI or SPDIF inputs only.  This routine
1675    will return an error if not connected to a digital input.
1676   
1677See Also:
1678    NEXUS_SpdifOutput_SetRawChannelStatus
1679***************************************************************************/
1680NEXUS_Error NEXUS_AudioDecoder_GetRawChannelStatus(
1681    NEXUS_AudioDecoderHandle handle,
1682    NEXUS_AudioRawChannelStatus *pStatus   /* [out] current status */
1683    )
1684{
1685    BSTD_UNUSED(handle);
1686    BSTD_UNUSED(pStatus);
1687    return BERR_TRACE(BERR_NOT_SUPPORTED);
1688}
1689
1690/***************************************************************************
1691Summary:
1692    Get an audio connector for use in the audio mixer
1693***************************************************************************/
1694NEXUS_AudioInput NEXUS_AudioDecoder_GetConnector( /* attr{shutdown=NEXUS_AudioInput_Shutdown} */
1695    NEXUS_AudioDecoderHandle handle,
1696    NEXUS_AudioDecoderConnectorType type
1697    )
1698{
1699    BDBG_OBJECT_ASSERT(handle, NEXUS_AudioDecoder);
1700    BDBG_ASSERT(type < NEXUS_AudioDecoderConnectorType_eMax);
1701    return &handle->connectors[type];
1702}
1703
1704NEXUS_Error NEXUS_AudioDecoder_ApplySettings_priv(
1705    NEXUS_AudioDecoderHandle handle
1706    )
1707{
1708    BAPE_DecoderTsmSettings tsmSettings;
1709    BAPE_DecoderSettings decoderSettings;
1710    BAPE_MixerInputVolume volume;
1711    unsigned i,j;
1712    BERR_Code errCode;
1713    bool forceMute=false;
1714
1715    BDBG_OBJECT_ASSERT(handle, NEXUS_AudioDecoder);
1716
1717    BAPE_Decoder_GetTsmSettings(handle->channel, &tsmSettings);
1718    tsmSettings.ptsOffset = handle->settings.ptsOffset + handle->syncSettings.delay;
1719
1720#if NEXUS_HAS_ASTM
1721    if (handle->astm.settings.enableAstm)
1722    {
1723        BDBG_MSG(("ASTM is setting the sync limit for audio channel %p to %d", handle, handle->astm.settings.syncLimit));
1724        tsmSettings.thresholds.syncLimit = handle->astm.settings.syncLimit;
1725        /* PR49489 20081201 bandrews - added for audio master mode */
1726        BDBG_MSG(("ASTM is %s playback mode for audio channel %p", handle->astm.settings.enablePlayback ? "enabling" : "disabling", handle));
1727        tsmSettings.playback = handle->astm.settings.enablePlayback;
1728        tsmSettings.ptsOffset += handle->astm.settings.ptsOffset;
1729    }
1730    else
1731    {
1732        tsmSettings.thresholds.syncLimit = 0;
1733    }
1734#endif
1735
1736    if ( 0 == handle->settings.discardThreshold )
1737    {
1738        tsmSettings.thresholds.discard = (handle->isPlayback)?30000:3000;   /* ms */
1739    }
1740    else
1741    {
1742        tsmSettings.thresholds.discard = handle->settings.discardThreshold;
1743    }
1744
1745    if ( 0 == handle->settings.gaThreshold )
1746    {
1747        NEXUS_PidChannelStatus pidChannelStatus;
1748
1749        BKNI_Memset(&pidChannelStatus, 0, sizeof(pidChannelStatus));
1750        if ( handle->started && NULL != handle->programSettings.pidChannel )
1751        {
1752            (void)NEXUS_PidChannel_GetStatus(handle->programSettings.pidChannel, &pidChannelStatus);
1753        }
1754
1755        tsmSettings.thresholds.grossAdjustment = (pidChannelStatus.originalTransportType == NEXUS_TransportType_eAvi) ? 0x30 : 0x8;
1756    }
1757    else
1758    {
1759        tsmSettings.thresholds.grossAdjustment = handle->settings.gaThreshold;
1760    }
1761    BAPE_Decoder_SetTsmSettings(handle->channel, &tsmSettings);
1762
1763    NEXUS_AudioDecoder_P_SetTsm(handle);
1764
1765    BAPE_Decoder_GetSettings(handle->channel, &decoderSettings);
1766    switch ( handle->settings.outputLfeMode )
1767    {
1768    default:
1769        decoderSettings.outputLfe = true;
1770        break;
1771    case NEXUS_AudioDecoderOutputLfeMode_eOff:
1772        decoderSettings.outputLfe = false;
1773        break;
1774    }
1775    switch ( handle->settings.outputMode )
1776    {
1777    default:
1778    case NEXUS_AudioDecoderOutputMode_eAuto:
1779        decoderSettings.outputMode = BAPE_ChannelMode_e3_2;
1780        break;
1781    case NEXUS_AudioDecoderOutputMode_e1_0:
1782        decoderSettings.outputMode = BAPE_ChannelMode_e1_0;
1783        break;
1784    case NEXUS_AudioDecoderOutputMode_e1_1:
1785        decoderSettings.outputMode = BAPE_ChannelMode_e1_1;
1786        break;
1787    case NEXUS_AudioDecoderOutputMode_e2_0:
1788        decoderSettings.outputMode = BAPE_ChannelMode_e2_0;
1789        break;
1790    case NEXUS_AudioDecoderOutputMode_e3_0:
1791        decoderSettings.outputMode = BAPE_ChannelMode_e3_0;
1792        break;
1793    case NEXUS_AudioDecoderOutputMode_e2_1:
1794        decoderSettings.outputMode = BAPE_ChannelMode_e2_1;
1795        break;
1796    case NEXUS_AudioDecoderOutputMode_e3_1:
1797        decoderSettings.outputMode = BAPE_ChannelMode_e3_1;
1798        break;
1799    case NEXUS_AudioDecoderOutputMode_e2_2:
1800        decoderSettings.outputMode = BAPE_ChannelMode_e2_2;
1801        break;
1802    case NEXUS_AudioDecoderOutputMode_e3_2:
1803        decoderSettings.outputMode = BAPE_ChannelMode_e3_2;
1804        break;
1805    case NEXUS_AudioDecoderOutputMode_e3_4:
1806        decoderSettings.outputMode = BAPE_ChannelMode_e3_4;
1807        break;
1808    }
1809    switch ( handle->settings.dualMonoMode )
1810    {
1811    default:
1812    case NEXUS_AudioDecoderDualMonoMode_eStereo:
1813        decoderSettings.dualMonoMode = BAPE_DualMonoMode_eStereo;
1814        break;
1815    case NEXUS_AudioDecoderDualMonoMode_eLeft:
1816        decoderSettings.dualMonoMode = BAPE_DualMonoMode_eLeft;
1817        break;
1818    case NEXUS_AudioDecoderDualMonoMode_eRight:
1819        decoderSettings.dualMonoMode = BAPE_DualMonoMode_eRight;
1820        break;
1821    case NEXUS_AudioDecoderDualMonoMode_eMix:
1822        decoderSettings.dualMonoMode = BAPE_DualMonoMode_eMix;
1823        break;
1824    }
1825
1826    if ( handle->trickState.rate == 0 )
1827    {
1828        decoderSettings.decodeRate = BAPE_NORMAL_DECODE_RATE;
1829    }
1830    else if ( handle->trickState.rate > (2*NEXUS_NORMAL_DECODE_RATE) || handle->trickState.rate < (NEXUS_NORMAL_DECODE_RATE/2) )
1831    {
1832        BDBG_MSG(("Audio trick modes are only supported between 0.5x and 2x normal rate.  Muting audio decoder."));
1833        forceMute = true;
1834        decoderSettings.decodeRate = BAPE_NORMAL_DECODE_RATE;
1835    }
1836    else
1837    {
1838        decoderSettings.decodeRate = (handle->trickState.rate * BAPE_NORMAL_DECODE_RATE)/ NEXUS_NORMAL_DECODE_RATE;
1839    }
1840    // JPF decoderSettings.loudnessEquivalenceEnabled = handle->settings.loudnessEquivalenceEnabled;
1841    errCode = BAPE_Decoder_SetSettings(handle->channel, &decoderSettings);
1842    if ( errCode )
1843    {
1844        return BERR_TRACE(errCode);
1845    }
1846   
1847    /* Apply volume settings - but only if an output has ever been connected by the user.
1848       Otherwise this forces a Shutdown() call in the application. */
1849    if ( handle->connectors[NEXUS_AudioDecoderConnectorType_eStereo].pMixerData )
1850    {
1851        NEXUS_AudioInput_P_GetVolume(&handle->connectors[NEXUS_AudioDecoderConnectorType_eStereo], &volume);
1852    }
1853    else if ( handle->connectors[NEXUS_AudioDecoderConnectorType_eMultichannel].pMixerData )
1854    {
1855        NEXUS_AudioInput_P_GetVolume(&handle->connectors[NEXUS_AudioDecoderConnectorType_eMultichannel], &volume);
1856    }
1857    else
1858    {
1859        goto skip_volume;
1860    }
1861    for ( i = 0; i < NEXUS_AudioChannel_eMax; i++ )
1862    {
1863        for ( j = 0; j < NEXUS_AudioChannel_eMax; j++ )
1864        {
1865            volume.coefficients[i][j] = handle->settings.volumeMatrix[j][i];
1866        }
1867    }       
1868    volume.muted = handle->settings.muted || handle->trickState.muted || handle->syncSettings.mute || forceMute;
1869    if ( handle->connectors[NEXUS_AudioDecoderConnectorType_eStereo].pMixerData )
1870    {
1871        errCode = NEXUS_AudioInput_P_SetVolume(&handle->connectors[NEXUS_AudioDecoderConnectorType_eStereo], &volume);
1872        if ( errCode )
1873        {
1874            return BERR_TRACE(errCode);
1875        }
1876    }
1877    if ( handle->connectors[NEXUS_AudioDecoderConnectorType_eMultichannel].pMixerData )
1878    {
1879        errCode = NEXUS_AudioInput_P_SetVolume(&handle->connectors[NEXUS_AudioDecoderConnectorType_eMultichannel], &volume);
1880        if ( errCode )
1881        {
1882            return BERR_TRACE(errCode);
1883        }
1884    }
1885skip_volume:
1886    return BERR_SUCCESS;
1887}
1888       
1889#if NEXUS_HAS_ASTM
1890void NEXUS_AudioDecoder_GetAstmSettings_priv(
1891    NEXUS_AudioDecoderHandle audioDecoder, 
1892    NEXUS_AudioDecoderAstmSettings * pAstmSettings  /* [out] */
1893    )
1894{
1895    NEXUS_ASSERT_MODULE();
1896
1897    *pAstmSettings = audioDecoder->astm.settings;
1898}
1899
1900NEXUS_Error NEXUS_AudioDecoder_SetAstmSettings_priv( 
1901    NEXUS_AudioDecoderHandle audioDecoder, 
1902    const NEXUS_AudioDecoderAstmSettings * pAstmSettings
1903    )
1904{
1905    NEXUS_Error rc = NEXUS_SUCCESS;
1906
1907    NEXUS_ASSERT_MODULE();
1908
1909    /* copy settings as-is, this way ASTM will always get what it set */
1910    audioDecoder->astm.settings = *pAstmSettings;
1911
1912    /* if ASTM is internally permitted, apply settings */
1913    rc = NEXUS_AudioDecoder_ApplySettings_priv(audioDecoder);
1914
1915    return rc;
1916}
1917   
1918NEXUS_Error NEXUS_AudioDecoder_GetAstmStatus_isr( 
1919    NEXUS_AudioDecoderHandle audioDecoder, 
1920    NEXUS_AudioDecoderAstmStatus * pAstmStatus  /* [out] */
1921    )
1922{
1923    BAPE_DecoderTsmStatus tsmStatus;
1924    BERR_Code rc;
1925
1926    BKNI_ASSERT_ISR_CONTEXT();
1927
1928    rc = BAPE_Decoder_GetTsmStatus_isr(audioDecoder->channel, &tsmStatus);
1929    audioDecoder->astm.status.ptsStcDiff = tsmStatus.ptsStcDifference;
1930
1931    *pAstmStatus = audioDecoder->astm.status;
1932
1933    return 0;
1934}
1935#endif
1936
1937void NEXUS_AudioDecoder_GetSyncSettings_priv(
1938    NEXUS_AudioDecoderHandle audioDecoder, 
1939    NEXUS_AudioInputSyncSettings *pSyncSettings  /* [out] */
1940    )
1941{
1942    BDBG_OBJECT_ASSERT(audioDecoder, NEXUS_AudioDecoder);
1943    BDBG_ASSERT(NULL != pSyncSettings);
1944    *pSyncSettings = audioDecoder->syncSettings;
1945}
1946   
1947NEXUS_Error NEXUS_AudioDecoder_SetSyncSettings_priv( 
1948    NEXUS_AudioDecoderHandle audioDecoder, 
1949    const NEXUS_AudioInputSyncSettings *pSyncSettings
1950    )
1951{
1952    BDBG_OBJECT_ASSERT(audioDecoder, NEXUS_AudioDecoder);
1953    BDBG_ASSERT(NULL != pSyncSettings);
1954    audioDecoder->syncSettings = *pSyncSettings;
1955    return NEXUS_AudioDecoder_ApplySettings_priv(audioDecoder);
1956}
1957   
1958NEXUS_Error NEXUS_AudioDecoder_GetSyncStatus_isr( 
1959    NEXUS_AudioDecoderHandle audioDecoder, 
1960    NEXUS_AudioInputSyncStatus *pSyncStatus  /* [out] */
1961    )
1962{
1963    BDBG_OBJECT_ASSERT(audioDecoder, NEXUS_AudioDecoder);
1964    BDBG_ASSERT(NULL != pSyncStatus);
1965    BKNI_Memset(pSyncStatus, 0, sizeof(*pSyncStatus));
1966    pSyncStatus->started = audioDecoder->running;
1967    pSyncStatus->digital = true;
1968    pSyncStatus->dsolaEnabled = false;
1969    BAPE_GetDecoderPathDelay(NEXUS_AUDIO_DEVICE_HANDLE, &pSyncStatus->delay);
1970    return BERR_SUCCESS;
1971}
1972
1973bool NEXUS_AudioDecoder_P_IsRunning(NEXUS_AudioDecoderHandle handle)
1974{
1975    BDBG_OBJECT_ASSERT(handle, NEXUS_AudioDecoder);
1976    /* This is slightly dangerous with trick modes, because a trick mute may cause this to return false.
1977       But, it's required for HDMI/SPDIF inputs where the decoder actually "starts stopped".  */
1978    return handle->running;
1979}
1980
1981void NEXUS_AudioDecoder_P_Reset(void)
1982{
1983    unsigned i;
1984
1985    LOCK_TRANSPORT();
1986    for ( i = 0; i < NEXUS_NUM_AUDIO_DECODERS; i++ )
1987    {
1988        if ( g_decoders[i].opened && g_decoders[i].running && NULL == g_decoders[i].programSettings.input )
1989        {
1990            NEXUS_Rave_Disable_priv(g_decoders[i].raveContext);
1991            NEXUS_Rave_Flush_priv(g_decoders[i].raveContext);
1992        }
1993    }
1994    UNLOCK_TRANSPORT();
1995
1996    /* Process watchdog event */
1997    BAPE_ProcessWatchdogInterrupt(NEXUS_AUDIO_DEVICE_HANDLE);
1998
1999    /* Restart RAVE contexts */
2000    LOCK_TRANSPORT();
2001    for ( i = 0; i < NEXUS_NUM_AUDIO_DECODERS; i++ )
2002    {
2003        if ( g_decoders[i].opened && g_decoders[i].running && NULL == g_decoders[i].programSettings.input )
2004        {
2005            NEXUS_Rave_Enable_priv(g_decoders[i].raveContext);
2006        }
2007    }
2008    UNLOCK_TRANSPORT();
2009
2010#if NEXUS_HAS_ASTM
2011    for ( i = 0; i < NEXUS_NUM_AUDIO_DECODERS; i++ )
2012    {
2013        if ( g_decoders[i].opened && g_decoders[i].running && g_decoders[i].astm.settings.enableAstm )
2014        {
2015            NEXUS_Callback astm_watchdog_isr = g_decoders[i].astm.settings.watchdog_isr;
2016            BDBG_MSG(("Audio channel %p is notifying ASTM of its watchdog recovery", &g_decoders[i]));
2017            if (astm_watchdog_isr)
2018            {
2019                BKNI_EnterCriticalSection();
2020                astm_watchdog_isr(g_decoders[i].astm.settings.callbackContext, 0);
2021                BKNI_LeaveCriticalSection();
2022            }
2023        }
2024    }
2025#endif       
2026}
2027
2028static void NEXUS_AudioDecoder_P_Watchdog(void *pParam)
2029{   
2030    bool corePending=false;
2031
2032    BSTD_UNUSED(pParam);   
2033
2034    g_numWatchdogs++;
2035
2036    /* Check if core dump support is enabled.  If so, spin and wait for it to complete. */
2037    if ( g_NEXUS_audioModuleData.settings.dspDebugSettings.typeSettings[NEXUS_AudioDspDebugType_eCoreDump].enabled )
2038    {
2039        /* Poll for core dump to finish and inform application */
2040        unsigned retries = 100;
2041
2042        while ( BDSP_Raaga_GetCoreDumpStatus(g_NEXUS_audioModuleData.dspHandle, 0) == BDSP_Raaga_FwStatus_eCoreDumpInProgress )
2043        {
2044            BKNI_Sleep(1);
2045            if ( 0 == --retries )
2046            {
2047                break;
2048            }
2049        }
2050
2051        if ( BDSP_Raaga_GetCoreDumpStatus(g_NEXUS_audioModuleData.dspHandle, 0) == BDSP_Raaga_FwStatus_eCoreDumpComplete )
2052        {
2053            corePending = true;
2054        }
2055    }
2056
2057    if ( corePending )
2058    {
2059        BDBG_WRN(("Audio watchdog reset postponed for core dump retrieval"));
2060        g_NEXUS_audioModuleData.watchdogDeferred = true;
2061    }
2062    else
2063    {
2064        /* Just restart now */
2065        NEXUS_AudioDecoder_P_Reset();
2066    }
2067}
2068
2069static void NEXUS_AudioDecoder_P_SampleRate(void *pParam)
2070{
2071    NEXUS_AudioDecoder *pDecoder = (NEXUS_AudioDecoder *)pParam;
2072
2073    #if 0 /* TODO */
2074    if(pDecoder->settings.wideGaThreshold) {
2075        BRAP_DSPCHN_TsmDebugInfo info;
2076        uint32_t new_threshold;
2077
2078        BRAP_GetTsmDebugInfo(pDecoder->rapChannel, &info);
2079
2080        new_threshold = (info.sPtsInfo.i32TSMUpperThreshold*3)/2;
2081
2082        BDBG_WRN(("Adjusting GA threshold to: %d (was %d)", new_threshold, info.sPtsInfo.i32TSMUpperThreshold));
2083
2084        BRAP_SetTsmGAThreshold(pDecoder->rapChannel, new_threshold/45);
2085    }
2086    #else
2087    BSTD_UNUSED(pDecoder);
2088    #endif
2089
2090    BDBG_MSG(("Sample Rate decoder[%d]", pDecoder->index));   
2091}
2092
2093static void NEXUS_AudioDecoder_P_ChannelChangeReport(void * context)
2094{
2095    BSTD_UNUSED(context);
2096}
2097
2098static void NEXUS_AudioDecoder_P_FirstPts_isr(void *pParam1, int param2, const BAPE_DecoderTsmStatus *pTsmStatus)
2099{
2100    NEXUS_Error errCode;
2101    NEXUS_AudioDecoder *pDecoder = (NEXUS_AudioDecoder *)pParam1;
2102
2103    BSTD_UNUSED(param2);
2104
2105    BDBG_MSG(("audio[%d] First PTS %08x", pDecoder->index, pTsmStatus->ptsInfo.ui32CurrentPTS));
2106    if ( pDecoder->programSettings.stcChannel )
2107    {
2108        NEXUS_IsrCallback_Fire_isr(pDecoder->firstPtsCallback);
2109        errCode = NEXUS_StcChannel_RequestStc_isr(pDecoder->programSettings.stcChannel, pDecoder->stcDecoderType, &pTsmStatus->ptsInfo);
2110        if ( errCode )
2111        {
2112            errCode=BERR_TRACE(errCode);
2113        }
2114    }   
2115#if NEXUS_HAS_ASTM
2116    if (pDecoder->astm.settings.enableAstm)
2117    {
2118        pDecoder->astm.status.pts = pTsmStatus->ptsInfo.ui32CurrentPTS;
2119
2120        if (pDecoder->astm.settings.firstPts_isr)
2121        {
2122            pDecoder->astm.settings.firstPts_isr(pDecoder->astm.settings.callbackContext, 0);
2123        }
2124    }
2125#endif /* NEXUS_HAS_ASTM */
2126}
2127
2128static void NEXUS_AudioDecoder_P_AudioTsmFail_isr(void *pParam1, int param2, const BAPE_DecoderTsmStatus *pTsmStatus)
2129{
2130    NEXUS_AudioDecoder *pDecoder = (NEXUS_AudioDecoder *)pParam1;
2131    BAPE_DecoderTsmStatus tsmStatus;
2132    NEXUS_Error errCode;
2133
2134    uint32_t stc;
2135
2136    BSTD_UNUSED(param2);
2137    BDBG_ASSERT(NULL != pTsmStatus);
2138
2139    BDBG_MSG(("audio[%d] Tsm fail: PTS 0x%08x, type %d",
2140        pDecoder->index, pTsmStatus->ptsInfo.ui32CurrentPTS, pTsmStatus->ptsInfo.ePTSType));
2141
2142    NEXUS_StcChannel_GetStc_isr(pDecoder->programSettings.stcChannel, &stc);
2143
2144    /* If we're in a non-standard STC trick mode */
2145    if ( pDecoder->trickState.stcTrickEnabled && (pDecoder->trickState.rate < 500 || pDecoder->trickState.rate > 2000) )
2146    {
2147        /* in STC trick mode, PTS might lag the STC because of decoder drop algorithm. don't reset STC in this case. */
2148        if ( stc > pTsmStatus->ptsInfo.ui32CurrentPTS && stc - pTsmStatus->ptsInfo.ui32CurrentPTS < 45000 * 8 )
2149        {
2150            return;
2151        }
2152    }
2153
2154    BDBG_MSG(("pts2stcphase: %d", pTsmStatus->ptsStcDifference));
2155
2156#if NEXUS_HAS_ASTM
2157    if (pDecoder->astm.settings.enableAstm && pDecoder->astm.settings.syncLimit > 0)
2158    {
2159        tsmStatus = *pTsmStatus;       
2160        tsmStatus.ptsInfo.ui32CurrentPTS = (uint32_t)((int32_t)stc - tsmStatus.ptsStcDifference);
2161        pTsmStatus = &tsmStatus;
2162    }
2163#endif /* NEXUS_HAS_ASTM */
2164
2165    /* PR:52308 ignore PTS errors for non-XPT inputs - we can't do anything about them from stcchannel/pcrlib anyway */
2166    if (!pDecoder->programSettings.input)
2167    {
2168        NEXUS_IsrCallback_Fire_isr(pDecoder->ptsErrorCallback);
2169        errCode = NEXUS_StcChannel_PtsError_isr(pDecoder->programSettings.stcChannel, pDecoder->stcDecoderType, &pTsmStatus->ptsInfo);
2170        if (errCode)
2171        {
2172            errCode=BERR_TRACE(errCode);
2173            /* keep going */
2174        }
2175    }
2176
2177#if NEXUS_HAS_ASTM
2178    if (pDecoder->astm.settings.enableAstm)
2179    {
2180        pDecoder->astm.status.pts = pTsmStatus->ptsInfo.ui32CurrentPTS;
2181
2182        if (pDecoder->astm.settings.tsmFail_isr)
2183        {
2184            pDecoder->astm.settings.tsmFail_isr(pDecoder->astm.settings.callbackContext, 0);
2185        }
2186    }
2187#endif /* NEXUS_HAS_ASTM */
2188
2189    pDecoder->ptsErrorCount++;   
2190}
2191
2192static void NEXUS_AudioDecoder_P_AudioTsmPass_isr(void *pParam1, int param2, const BAPE_DecoderTsmStatus *pTsmStatus)
2193{
2194    NEXUS_AudioDecoder *pDecoder = (NEXUS_AudioDecoder *)pParam1;
2195
2196    BSTD_UNUSED(param2);
2197    BDBG_ASSERT(NULL != pTsmStatus);
2198
2199    BDBG_MSG(("audio[%d] TSM pass: PTS 0x%08x, type %d",
2200        pDecoder->index, pTsmStatus->ptsInfo.ui32CurrentPTS, pTsmStatus->ptsInfo.ePTSType));
2201
2202    if (pDecoder->astm.settings.enableAstm)
2203    {
2204        pDecoder->astm.status.pts = pTsmStatus->ptsInfo.ui32CurrentPTS;
2205
2206        if (pDecoder->astm.settings.tsmPass_isr)
2207        {
2208            pDecoder->astm.settings.tsmPass_isr(pDecoder->astm.settings.callbackContext, 0);
2209        }
2210    }
2211}
2212
2213static void NEXUS_AudioDecoder_P_SampleRateChange_isr(void *pParam1, int param2, BAVC_AudioSamplingRate sampleRate)
2214{
2215    NEXUS_AudioDecoder *pDecoder = (NEXUS_AudioDecoder *)pParam1;
2216
2217    BSTD_UNUSED(param2);
2218
2219    BDBG_MSG(("audio[%d] Sampling Rate Info, samplingRate=%x", pDecoder->index, sampleRate));
2220
2221    BKNI_SetEvent_isr(pDecoder->sampleRateEvent);
2222    NEXUS_IsrCallback_Fire_isr(pDecoder->sourceChangeAppCallback);
2223
2224    if (pDecoder->syncSettings.sampleRateCallback_isr) {
2225        (*pDecoder->syncSettings.sampleRateCallback_isr)(pDecoder->syncSettings.callbackContext, 0);
2226    }
2227
2228}
2229
2230static void NEXUS_AudioDecoder_P_Lock_isr(void *pParam1, int param2)
2231{
2232    NEXUS_AudioDecoder *pDecoder = (NEXUS_AudioDecoder *)pParam1;
2233
2234    pDecoder->locked = param2;
2235    BDBG_MSG(("Decoder %u %s", pDecoder->index, param2?"lock":"unlock"));
2236    NEXUS_IsrCallback_Fire_isr(pDecoder->lockCallback);
2237}
2238
2239static void NEXUS_AudioDecoder_P_StreamStatusAvailable_isr(void *pParam1, int param2)
2240{
2241    NEXUS_AudioDecoder *pDecoder = (NEXUS_AudioDecoder *)pParam1;
2242
2243    pDecoder->locked = param2;
2244    BDBG_MSG(("Decoder %u Stream Status Ready", pDecoder->index));
2245    NEXUS_IsrCallback_Fire_isr(pDecoder->streamStatusCallback);
2246    NEXUS_IsrCallback_Fire_isr(pDecoder->sourceChangeAppCallback);
2247}
2248
2249static void NEXUS_AudioDecoder_P_StreamParameterChanged_isr(void *pParam1, int param2)
2250{
2251    NEXUS_AudioDecoder *pDecoder = (NEXUS_AudioDecoder *)pParam1;
2252
2253    pDecoder->locked = param2;
2254    BDBG_MSG(("Decoder %u Stream Parameter Changed", pDecoder->index));
2255    NEXUS_IsrCallback_Fire_isr(pDecoder->sourceChangeAppCallback);
2256}
2257
2258void NEXUS_AudioDecoder_P_SetTsm(NEXUS_AudioDecoderHandle handle)
2259{
2260    BAPE_DecoderTsmSettings tsmSettings;
2261
2262    BAPE_Decoder_GetTsmSettings(handle->channel, &tsmSettings);
2263    tsmSettings.tsmEnabled = false;
2264
2265    if ( handle->tsmPermitted )
2266    {
2267        if ( handle->trickState.tsmEnabled )
2268        {
2269#if NEXUS_HAS_ASTM
2270            if ( handle->astm.settings.enableAstm )
2271            {
2272                BDBG_MSG(("ASTM is %s TSM for audio channel %p", handle->astm.settings.enableTsm ? "enabling" : "disabling", handle));
2273                if ( handle->astm.settings.enableTsm )
2274                {
2275                    tsmSettings.tsmEnabled = true;
2276                }
2277            }
2278            else
2279#endif
2280            {
2281                tsmSettings.tsmEnabled = true;
2282            }
2283        }
2284    }
2285
2286    BDBG_MSG(("%s TSM",tsmSettings.tsmEnabled?"Enabling":"Disabling"));
2287
2288#if NEXUS_HAS_ASTM
2289    /* Only allow ASTM if we have TSM enabled for all non-ASTM controls and we have a TS source */
2290    if ( handle->tsmPermitted && handle->trickState.tsmEnabled &&
2291         handle->apeStartSettings.streamType == BAVC_StreamType_eTsMpeg )
2292    {
2293        BDBG_MSG(("%s ASTM mode for audio channel %p",handle->astm.settings.enableAstm?"Enabling":"Disabling", handle));
2294        tsmSettings.astmEnabled = handle->astm.settings.enableAstm;
2295    }
2296    else
2297    {
2298        BDBG_MSG(("Disabling ASTM mode for audio channel %p", handle));
2299        tsmSettings.astmEnabled = false;
2300    }
2301#endif
2302
2303    BAPE_Decoder_SetTsmSettings(handle->channel, &tsmSettings);
2304
2305    handle->tsmEnabled = tsmSettings.tsmEnabled;
2306}
2307
2308NEXUS_Error NEXUS_AudioDecoder_P_Start(NEXUS_AudioDecoderHandle handle)
2309{
2310    NEXUS_Error errCode;
2311    const NEXUS_AudioDecoderStartSettings *pProgram;
2312
2313    BDBG_ASSERT(NULL != handle);
2314
2315    BDBG_ENTER(NEXUS_AudioDecoder_P_Start);
2316
2317    pProgram = &handle->programSettings;
2318
2319    if ( handle->programSettings.input || !handle->started || handle->outputLists[NEXUS_AudioDecoderConnectorType_eCompressed].outputs[0] != NULL )
2320    {
2321        int i;
2322        bool changed=false;
2323        NEXUS_AudioOutputList outputLists[NEXUS_AudioDecoderConnectorType_eMax];
2324
2325        /* Get output lists */
2326        for ( i = 0; i < NEXUS_AudioDecoderConnectorType_eMax; i++ )
2327        {
2328            NEXUS_AudioInput_P_GetOutputs(&handle->connectors[i], &outputLists[i], false);
2329            /* Check for changes */
2330            if ( BKNI_Memcmp(&outputLists[i], &handle->outputLists[i], sizeof(NEXUS_AudioOutputList)) )
2331            {
2332                BDBG_MSG(("Output change detected for connector type %d", i));
2333                changed = true;
2334            }
2335            else
2336            {
2337                BDBG_MSG(("NO Output change detected for connector type %d (firstOld=%p, firstNew=%p)", i, outputLists[i].outputs[0], handle->outputLists[i].outputs[0]));
2338            }
2339        }
2340
2341        /* 20111212 bandrews - the following code is concerned with stc programming priority.
2342        As such, the variable in use has been renamed to stcPriority.  DecoderType is now simply
2343        a mapping combining type and index */
2344
2345        /* type now matches index directly */
2346        handle->stcDecoderType = NEXUS_StcChannelDecoderType_eAudio0 + handle->index;
2347
2348        /* Determine mode to add new outputs */
2349        if ( outputLists[NEXUS_AudioDecoderConnectorType_eCompressed].outputs[0] != NULL &&
2350             outputLists[NEXUS_AudioDecoderConnectorType_eStereo].outputs[0] == NULL &&
2351             outputLists[NEXUS_AudioDecoderConnectorType_eMultichannel].outputs[0] == NULL )
2352        {
2353            /* Compressed output, but no stereo or multichannel.  This is a passthrough channel. */
2354            if ( handle->connectors[NEXUS_AudioDecoderConnectorType_eCompressed].format == NEXUS_AudioInputFormat_eCompressed )
2355            {
2356                BDBG_MSG(("Decoder %d is a passthrough channel", handle->index));
2357            }
2358            else
2359            {
2360                BDBG_MSG(("Decoder %d is a decode channel (PCM data for passthrough)", handle->index));
2361            }
2362
2363            handle->stcPriority = 1;
2364        }
2365        else
2366        {
2367            if ( handle->descriptorParent || handle->programSettings.secondaryDecoder )
2368            {
2369                /* AD child or secondary decoder (MS10/MS11).  This is decoder type audio2 */
2370                handle->stcPriority = 2;
2371            }
2372            else
2373            {
2374                /* Standard decode channel.  Compressed will be simul */
2375                handle->stcPriority = 0;
2376            }
2377            /* Determine decoder mode as decode or simul based on presence of compressed outputs */
2378            if ( outputLists[NEXUS_AudioDecoderConnectorType_eCompressed].outputs[0] != NULL )
2379            {
2380                /* Simul Mode */
2381                BDBG_MSG(("Decoder %d is a simul channel", handle->index));
2382            }
2383            else
2384            {
2385                /* Decode Mode */
2386                BDBG_MSG(("Decoder %d is a decode channel", handle->index));
2387            }
2388        }
2389
2390        /* This process is slow and involves memory allocation/free.  Only do it if something changed */
2391        if ( changed )
2392        {
2393            /* Remove all outputs */
2394            for ( i = 0; i < NEXUS_AudioDecoderConnectorType_eMax; i++ )
2395            {
2396                int j;
2397
2398                handle->hdmiOutput = NULL;  /* Invalidate this, it will be re-discovered when ports are added */
2399                for ( j = 0; j < NEXUS_AUDIO_MAX_OUTPUTS; j++ )
2400                {
2401                    NEXUS_AudioOutput output = handle->outputLists[i].outputs[j];
2402                    if ( output )
2403                    {
2404                        BDBG_MSG(("Removing output port %d from decoder %d", output->port, handle->index));
2405                        /* Clear this output port */
2406                        handle->outputLists[i].outputs[j] = NULL;
2407                    }
2408                }
2409            }
2410
2411            /* Now, actually attach outputs */
2412            for ( i = 0; i < NEXUS_AUDIO_MAX_OUTPUTS; i++ )
2413            {
2414                NEXUS_AudioOutput output = outputLists[NEXUS_AudioDecoderConnectorType_eStereo].outputs[i];
2415                if ( NULL == output )
2416                {
2417                    break;
2418                }
2419                else
2420                {
2421                    BDBG_MSG(("Adding output port %d to decoder %d (pcm) %p", output->port, handle->index, output));
2422                    handle->outputLists[NEXUS_AudioDecoderConnectorType_eStereo].outputs[i] = output;
2423                    if ( output->objectType == NEXUS_AudioOutputType_eHdmi )
2424                    {
2425                        handle->hdmiOutput = output;
2426                    }
2427                }
2428            }
2429
2430            for ( i = 0; i < NEXUS_AUDIO_MAX_OUTPUTS; i++ )
2431            {
2432                NEXUS_AudioOutput output = outputLists[NEXUS_AudioDecoderConnectorType_eMultichannel].outputs[i];
2433                if ( NULL == output )
2434                {
2435                    break;
2436                }
2437                else
2438                {
2439                    BDBG_MSG(("Adding output port %d to decoder %d (multichannel)", output->port, handle->index));
2440                    handle->outputLists[NEXUS_AudioDecoderConnectorType_eMultichannel].outputs[i] = output;
2441                    if ( output->objectType == NEXUS_AudioOutputType_eHdmi )
2442                    {
2443                        handle->hdmiOutput = output;
2444                    }
2445                }
2446            }
2447
2448            /* Add compressed ports */
2449            for ( i = 0; i < NEXUS_AUDIO_MAX_OUTPUTS; i++ )
2450            {
2451                NEXUS_AudioOutput output = outputLists[NEXUS_AudioDecoderConnectorType_eCompressed].outputs[i];
2452                if ( NULL == output )
2453                {
2454                    break;
2455                }
2456                else
2457                {
2458                    BDBG_MSG(("Adding output port %d to decoder %d (compressed) %p", output->port, handle->index, output));
2459                    handle->outputLists[NEXUS_AudioDecoderConnectorType_eCompressed].outputs[i] = output;
2460                    if ( output->objectType == NEXUS_AudioOutputType_eHdmi )
2461                    {
2462                        handle->hdmiOutput = output;
2463                    }
2464                }
2465            }
2466        }
2467
2468        if ( NULL == outputLists[NEXUS_AudioDecoderConnectorType_eStereo].outputs[0] &&
2469             NULL == outputLists[NEXUS_AudioDecoderConnectorType_eMultichannel].outputs[0] &&
2470             NULL == outputLists[NEXUS_AudioDecoderConnectorType_eCompressed].outputs[0] )
2471        {
2472            BDBG_ERR(("No outputs have been connected to this decoder."));
2473            return BERR_TRACE(BERR_NOT_SUPPORTED);
2474        }
2475
2476        /* Notify downstream objects we're about to start - should be done after outputs are connected on 7400/7401 */
2477        /* This will trigger connections on the 7405/3563/... */
2478        for ( i = 0; i < NEXUS_AudioDecoderConnectorType_eMax; i++ )
2479        {
2480            /* Only call this for inputs about to actually start */
2481            BDBG_MSG(("Preparing to start path %d", i));
2482
2483            errCode = NEXUS_AudioInput_P_PrepareToStart(&handle->connectors[i]);
2484            if ( errCode )
2485            {
2486                return BERR_TRACE(errCode);
2487            }
2488        }
2489    }
2490
2491    /* Setup StcChannel */
2492    if ( pProgram->stcChannel )
2493    {
2494        NEXUS_StcChannelCallbacks callbacks;
2495
2496        LOCK_TRANSPORT();
2497
2498        NEXUS_StcChannel_GetDefaultCallbacks_priv(&callbacks);
2499        callbacks.getPts_isr = NEXUS_AudioDecoder_P_GetPtsCallback_isr;
2500        callbacks.getCdbLevel_isr = NEXUS_AudioDecoder_P_GetCdbLevelCallback_isr;
2501        callbacks.stcValid_isr = NEXUS_AudioDecoder_P_StcValidCallback_isr;
2502        callbacks.pDevContext = handle;
2503        if ( pProgram->nonRealTime )
2504        {
2505            callbacks.getPcrOffset_isr = NEXUS_AudioDecoder_P_GetPcrOffset_isr;
2506            callbacks.setPcrOffset_isr = NEXUS_AudioDecoder_P_SetPcrOffset_isr;
2507        }
2508        NEXUS_StcChannel_SetCallbacks_priv(pProgram->stcChannel, handle->stcDecoderType, handle->stcPriority, &callbacks);
2509        if ( pProgram->pidChannel )
2510        {
2511            NEXUS_StcChannel_EnablePidChannel_priv(pProgram->stcChannel, pProgram->pidChannel);
2512            handle->fifoWatchdogTimer = NEXUS_ScheduleTimer(250, NEXUS_AudioDecoder_P_FifoWatchdog, handle);
2513        }
2514
2515        UNLOCK_TRANSPORT();
2516    }
2517
2518    /* After all that, we're ready to go.  Start. */
2519    handle->ptsErrorCount = 0;
2520    BDBG_MSG(("Starting Decoder %d", handle->index));
2521
2522    /* Re-apply settings */
2523    NEXUS_AudioDecoder_ApplySettings_priv(handle);
2524    BDBG_MSG(("Starting with codec %u", handle->apeStartSettings.codec));
2525
2526    handle->locked = false;
2527    handle->numFifoOverflows = handle->numFifoUnderflows = 0;
2528    errCode = BAPE_Decoder_Start(handle->channel, &handle->apeStartSettings);
2529    if ( errCode && !handle->started )
2530    {
2531        if ( handle->programSettings.stcChannel )
2532        {
2533            LOCK_TRANSPORT();
2534            if ( handle->programSettings.pidChannel )
2535            {
2536                NEXUS_StcChannel_DisablePidChannel_priv(handle->programSettings.stcChannel, handle->programSettings.pidChannel);
2537                if ( handle->fifoWatchdogTimer )
2538                {
2539                    NEXUS_CancelTimer(handle->fifoWatchdogTimer);
2540                    handle->fifoWatchdogTimer = NULL;
2541                }
2542            }
2543            NEXUS_StcChannel_ClearCallbacks_priv(handle->programSettings.stcChannel, handle->stcDecoderType);
2544            UNLOCK_TRANSPORT();
2545        }
2546        return BERR_TRACE(errCode);
2547    }
2548
2549    if ( handle->programSettings.pidChannel )
2550    {
2551        LOCK_TRANSPORT();
2552        NEXUS_Rave_Enable_priv(handle->raveContext);
2553        UNLOCK_TRANSPORT();
2554    }
2555    handle->running = true;
2556
2557    if ( handle->programSettings.pidChannel )
2558    {
2559        (void)NEXUS_PidChannel_ConsumerStarted(handle->programSettings.pidChannel);
2560    }
2561
2562    /* PR:49294 sync/astm must know that audio has been started *every* time it is started */
2563    if (handle->syncSettings.startCallback_isr) {
2564        BKNI_EnterCriticalSection();
2565        (*handle->syncSettings.startCallback_isr)(handle->syncSettings.callbackContext, 0);
2566        BKNI_LeaveCriticalSection();
2567    }
2568
2569#if NEXUS_HAS_ASTM
2570    handle->astm.status.started = true;
2571
2572    if (handle->astm.settings.enableAstm)
2573    {
2574        BDBG_MSG(("Audio channel %p is notifying ASTM of its start action", handle));
2575        if (handle->astm.settings.lifecycle_isr)
2576        {
2577            BKNI_EnterCriticalSection();
2578            (*handle->astm.settings.lifecycle_isr)(handle->astm.settings.callbackContext, 0);
2579            BKNI_LeaveCriticalSection();
2580        }
2581    }
2582
2583#endif
2584
2585    BDBG_LEAVE(NEXUS_AudioDecoder_P_Start);
2586
2587    return BERR_SUCCESS;
2588}
2589
2590NEXUS_Error NEXUS_AudioDecoder_P_Stop(NEXUS_AudioDecoderHandle handle, bool flush)
2591{
2592    BDBG_ENTER(NEXUS_AudioDecoder_P_Stop);
2593
2594    BDBG_OBJECT_ASSERT(handle, NEXUS_AudioDecoder);
2595
2596    if ( handle->running )
2597    {
2598        if ( handle->fifoWatchdogTimer )
2599        {
2600            NEXUS_CancelTimer(handle->fifoWatchdogTimer);
2601            handle->fifoWatchdogTimer = NULL;
2602        }
2603
2604        handle->locked = false;
2605        BAPE_Decoder_Stop(handle->channel);
2606
2607        if ( handle->programSettings.pidChannel && flush )
2608        {
2609            LOCK_TRANSPORT();
2610            NEXUS_Rave_Disable_priv(handle->raveContext);
2611            NEXUS_Rave_Flush_priv(handle->raveContext);
2612            UNLOCK_TRANSPORT();
2613        }
2614
2615        handle->running = false;
2616
2617        if ( handle->programSettings.stcChannel && handle->stcDecoderType != NEXUS_StcChannelDecoderType_eMax )
2618        {
2619            LOCK_TRANSPORT();
2620            if ( handle->programSettings.pidChannel && handle->programSettings.stcChannel )
2621            {
2622                NEXUS_StcChannel_DisablePidChannel_priv(handle->programSettings.stcChannel, handle->programSettings.pidChannel);
2623            }
2624            NEXUS_StcChannel_ClearCallbacks_priv(handle->programSettings.stcChannel, handle->stcDecoderType);
2625            UNLOCK_TRANSPORT();
2626        }
2627
2628        /* PR:49294 sync/astm must know that audio has been started *every* time it is started */
2629        if (handle->syncSettings.startCallback_isr) {
2630            BKNI_EnterCriticalSection();
2631            (*handle->syncSettings.startCallback_isr)(handle->syncSettings.callbackContext, 0);
2632            BKNI_LeaveCriticalSection();
2633        }
2634
2635#if NEXUS_HAS_ASTM
2636        handle->astm.status.started = false;
2637
2638        if (handle->astm.settings.enableAstm)
2639        {
2640            BDBG_MSG(("Audio channel %p is notifying ASTM of its stop action", handle));
2641            if (handle->astm.settings.lifecycle_isr)
2642            {
2643                BKNI_EnterCriticalSection();
2644                (*handle->astm.settings.lifecycle_isr)(handle->astm.settings.callbackContext, 0);
2645                BKNI_LeaveCriticalSection();
2646            }
2647        }
2648
2649#endif
2650    }
2651
2652    BDBG_LEAVE(NEXUS_AudioDecoder_P_Stop);
2653
2654    return BERR_SUCCESS;
2655}
2656
2657static BERR_Code NEXUS_AudioDecoder_P_GetPtsCallback_isr(void *pContext, BAVC_PTSInfo *pPTSInfo)
2658{
2659    BERR_Code errCode;
2660    NEXUS_AudioDecoderHandle handle = pContext;
2661    BAPE_DecoderTsmStatus tsmStatus;
2662    BDBG_OBJECT_ASSERT(handle, NEXUS_AudioDecoder);
2663    BDBG_ASSERT(NULL != pPTSInfo);
2664    errCode = BAPE_Decoder_GetTsmStatus_isr(handle->channel, &tsmStatus);
2665    if ( errCode )
2666    {
2667        return errCode; /* BERR_TRACE intentionally omitted */   
2668    }
2669    *pPTSInfo = tsmStatus.ptsInfo;
2670    return BERR_SUCCESS;
2671}
2672
2673static BERR_Code NEXUS_AudioDecoder_P_GetCdbLevelCallback_isr(void *pContext, unsigned *pCdbLevel)
2674{
2675    unsigned depth=0, size=0;
2676    NEXUS_AudioDecoderHandle audioDecoder = (NEXUS_AudioDecoderHandle)pContext;
2677    BDBG_OBJECT_ASSERT(audioDecoder, NEXUS_AudioDecoder);
2678    if ( audioDecoder->programSettings.pidChannel )
2679    {
2680        NEXUS_Rave_GetCdbBufferInfo_isr(audioDecoder->raveContext, &depth, &size);
2681    }
2682    BDBG_MSG(("GetCdbLevel - returned %d", depth));
2683    *pCdbLevel = depth;
2684    return 0;
2685}
2686
2687static BERR_Code NEXUS_AudioDecoder_P_StcValidCallback_isr(void *pContext)
2688{
2689    NEXUS_AudioDecoderHandle audioDecoder = (NEXUS_AudioDecoderHandle)pContext;
2690    BDBG_OBJECT_ASSERT(audioDecoder, NEXUS_AudioDecoder);
2691    return BAPE_Decoder_SetStcValid_isr(audioDecoder->channel);
2692}
2693
2694static void NEXUS_AudioDecoder_P_FifoWatchdog(void *context)
2695{
2696    NEXUS_AudioDecoderHandle audioDecoder = context;
2697    unsigned timeout=150;
2698
2699    audioDecoder->fifoWatchdogTimer = NULL;
2700
2701    if (audioDecoder->programSettings.stcChannel) {
2702        uint32_t cdbValidPointer, cdbReadPointer;
2703        bool shouldFlush, isLocked;
2704        unsigned depth, size;
2705
2706        BKNI_EnterCriticalSection();
2707        NEXUS_Rave_GetCdbPointers_isr(audioDecoder->raveContext, &cdbValidPointer, &cdbReadPointer);
2708        NEXUS_Rave_GetCdbBufferInfo_isr(audioDecoder->raveContext, &depth, &size);
2709        BKNI_LeaveCriticalSection();
2710        if (audioDecoder->lastCdbValidPointer == cdbValidPointer && audioDecoder->lastCdbReadPointer == cdbReadPointer) {
2711            if (audioDecoder->staticFifoCount < 20) {
2712                audioDecoder->staticFifoCount++;
2713            }
2714        }
2715        else {
2716            audioDecoder->staticFifoCount = 0;
2717            audioDecoder->lastCdbValidPointer = cdbValidPointer;
2718            audioDecoder->lastCdbReadPointer = cdbReadPointer;
2719        }
2720
2721        isLocked = (audioDecoder->staticFifoCount > 4) && (audioDecoder->trickState.rate >= NEXUS_NORMAL_DECODE_RATE);
2722
2723        LOCK_TRANSPORT();
2724        NEXUS_StcChannel_ReportDecoderHang_priv(audioDecoder->programSettings.stcChannel,
2725            audioDecoder->stcDecoderType, isLocked, size?depth*100/size:0, &shouldFlush);
2726        UNLOCK_TRANSPORT();
2727
2728        if (shouldFlush) {
2729            NEXUS_AudioDecoder_Flush(audioDecoder);
2730            LOCK_TRANSPORT();
2731            NEXUS_StcChannel_ReportFlush_priv(audioDecoder->programSettings.stcChannel,
2732                audioDecoder->stcDecoderType);
2733            UNLOCK_TRANSPORT();
2734        }
2735    }
2736
2737    audioDecoder->fifoWatchdogTimer = NEXUS_ScheduleTimer(timeout, NEXUS_AudioDecoder_P_FifoWatchdog, audioDecoder);
2738}
2739
2740static void NEXUS_AudioDecoder_P_InputFormatChange_isr(void *pParam1, int param2)
2741{
2742    NEXUS_AudioDecoderHandle handle = (NEXUS_AudioDecoderHandle)pParam1;
2743    BSTD_UNUSED(param2);
2744    /* convert to task time */
2745    BKNI_SetEvent_isr(handle->inputFormatChangeEvent);
2746}
2747
2748static void NEXUS_AudioDecoder_P_InputFormatChange(void *pParam)
2749{
2750    NEXUS_AudioDecoderHandle handle = (NEXUS_AudioDecoderHandle)pParam;
2751    NEXUS_AudioInputPortStatus inputPortStatus;
2752    NEXUS_Error errCode;
2753    BAVC_AudioCompressionStd avcCodec;
2754    bool stop=false, start=false;
2755
2756    errCode = NEXUS_AudioInput_P_GetInputPortStatus(handle->programSettings.input, &inputPortStatus);
2757    if ( errCode )
2758    {
2759        (void)BERR_TRACE(errCode);
2760        return;
2761    }
2762       
2763    avcCodec = NEXUS_Audio_P_CodecToMagnum(inputPortStatus.codec);
2764    if ( handle->running )
2765    {
2766        BDBG_MSG(("Input Format Change - Decoder is running"));
2767        if ( avcCodec == handle->apeStartSettings.codec )
2768        {
2769            /* Nothing to do, return. */
2770            BDBG_MSG(("Signal codec has not changed.  Not restarting decoder."));
2771            return;
2772        }
2773        else
2774        {
2775            /* Must stop if codec has changed */
2776            stop = true;
2777            if ( inputPortStatus.signalPresent )
2778            {
2779                /* Restart with new codec if signal is present */
2780                start = true;
2781                BDBG_MSG(("Valid input signal with different codec, restarting decoder."));
2782            }
2783            else
2784            {
2785                BDBG_MSG(("No valid input signal, stopping decoder."));
2786            }
2787        }
2788    }
2789    else
2790    {
2791        BDBG_MSG(("Input Format Change - Decoder is not running"));
2792        if ( inputPortStatus.signalPresent )
2793        {
2794            /* Start with new codec if signal is present */
2795            BDBG_MSG(("Valid input signal, starting decoder."));
2796            start = true;
2797        }
2798        else
2799        {
2800            BDBG_MSG(("No valid input signal, not starting decoder."));
2801        }
2802    }
2803
2804    if ( stop )
2805    {
2806        BDBG_MSG(("Stop decoder on input format change"));
2807        NEXUS_AudioDecoder_P_Stop(handle, true);
2808    }
2809    handle->apeStartSettings.codec = avcCodec;
2810    if ( start )
2811    {
2812        NEXUS_Error errCode;
2813        BDBG_MSG(("Start decoder on input format change"));
2814        errCode = NEXUS_AudioDecoder_P_Start(handle);
2815        if ( errCode )
2816        {
2817            (void)BERR_TRACE(errCode);
2818        }
2819    }
2820}
2821
2822static BERR_Code NEXUS_AudioDecoder_P_SetPcrOffset_isr(void *pContext, uint32_t pcrOffset)
2823{
2824    NEXUS_AudioDecoderHandle handle = (NEXUS_AudioDecoderHandle)pContext;
2825    BAPE_DecoderTsmSettings tsmSettings;
2826    BERR_Code errCode;
2827
2828    BDBG_OBJECT_ASSERT(handle, NEXUS_AudioDecoder);
2829
2830    BAPE_Decoder_GetTsmSettings_isr(handle->channel, &tsmSettings);
2831    tsmSettings.stcOffset = pcrOffset;
2832    errCode = BAPE_Decoder_SetTsmSettings_isr(handle->channel, &tsmSettings);
2833    if ( errCode )
2834    {
2835        return BERR_TRACE(errCode);
2836    }
2837    return BERR_SUCCESS;
2838}
2839
2840static BERR_Code NEXUS_AudioDecoder_P_GetPcrOffset_isr(void *pContext, uint32_t *pPcrOffset)
2841{
2842    NEXUS_AudioDecoderHandle handle = (NEXUS_AudioDecoderHandle)pContext;
2843    BAPE_DecoderTsmSettings tsmSettings;
2844
2845    BDBG_OBJECT_ASSERT(handle, NEXUS_AudioDecoder);
2846    BDBG_ASSERT(NULL != pPcrOffset);
2847
2848    BAPE_Decoder_GetTsmSettings_isr(handle->channel, &tsmSettings);
2849    *pPcrOffset = tsmSettings.stcOffset;
2850    return BERR_SUCCESS;   
2851}
2852
2853NEXUS_Error NEXUS_AudioDecoder_GetExtendedStatus(
2854    NEXUS_AudioDecoderHandle handle,
2855    NEXUS_AudioDecoderExtendedStatus *pStatus /* [out] */
2856    )
2857{
2858    BERR_Code errCode = BERR_SUCCESS;
2859
2860    BDBG_OBJECT_ASSERT(handle, NEXUS_AudioDecoder);
2861    BDBG_ASSERT(NULL != pStatus);
2862    LOCK_TRANSPORT();
2863    if ( handle->raveContext ) 
2864    {
2865        NEXUS_RaveStatus raveStatus;
2866
2867        errCode = NEXUS_Rave_GetStatus_priv(handle->raveContext, &raveStatus);
2868        if ( errCode == BERR_SUCCESS ) 
2869        {
2870            pStatus->raveIndex = raveStatus.index;
2871        }
2872    }
2873    UNLOCK_TRANSPORT();
2874
2875    return errCode;
2876}
2877
Note: See TracBrowser for help on using the repository browser.