source: svn/newcon3bcm2_21bu/magnum/portinginterface/ape/7552/bape_mux_output.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: 81.4 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: bape_mux_output.c $
39* $brcm_Revision: Hydra_Software_Devel/36 $
40* $brcm_Date: 2/24/12 11:49a $
41*
42* API Description:
43*   API name: MuxOutput
44*    Specific APIs related to Audio Transcoder Output (GenCdbItb)
45*
46* Revision History:
47*
48* $brcm_Log: /magnum/portinginterface/ape/7422/bape_mux_output.c $
49*
50* Hydra_Software_Devel/36   2/24/12 11:49a jgarrett
51* SW7425-2416: Adding sanity checks for errant mux behavior and improved
52* empty CDB handling
53*
54* Hydra_Software_Devel/35   2/21/12 11:12a jgarrett
55* SW7425-2262: Adding empty frame support and fixing case where CDB data
56* was available before ITB data
57*
58* Hydra_Software_Devel/34   2/17/12 4:15p jgarrett
59* SW7425-2262: Adding handling for empty frames (currently disabled)
60*
61* Hydra_Software_Devel/33   2/16/12 4:41p jgarrett
62* SW7425-2416: Resetting shadow read pointers on BAPE_MuxOutput_Start in
63* case they are flushed
64*
65* Hydra_Software_Devel/32   2/14/12 3:17p jgarrett
66* SW7425-2395: Bumping max ITB descriptors to 128
67*
68* Hydra_Software_Devel/31   2/10/12 1:41p jgarrett
69* SW7425-1221: Adding STC Snapshot
70*
71* Hydra_Software_Devel/30   2/10/12 11:03a jgarrett
72* SW7425-624: Correcting ADTS segment wrap calculations
73*
74* Hydra_Software_Devel/29   2/9/12 5:45p jgarrett
75* SW7425-2268: Correcting CDB/ITB advancement logic with additional ITB
76* entries
77*
78* Hydra_Software_Devel/28   1/23/12 2:58p jgarrett
79* SW7425-1478: Adding metadata support for WMA
80*
81* Hydra_Software_Devel/27   12/16/11 11:34a jgarrett
82* SW7425-1478: Adding BlockAlign and NumChannels to WMA metadata
83*
84* Hydra_Software_Devel/26   12/9/11 4:57p jgarrett
85* SW7425-1478: Copying ITB metadata into descriptor
86*
87* Hydra_Software_Devel/25   12/8/11 2:05p jgarrett
88* SW7425-1478: Adding WMA metadata extraction
89*
90* Hydra_Software_Devel/24   11/17/11 10:34a jgarrett
91* SW7429-18: Fixing STC register address
92*
93* Hydra_Software_Devel/23   11/14/11 3:37p gskerl
94* SW7429-18: Merging 7429 changes back to main branch.
95*
96* Hydra_Software_Devel/SW7429-18/1   10/21/11 6:29p jgarrett
97* SW7429-18: Initial compileable version for 7429
98*
99* Hydra_Software_Devel/22   10/14/11 12:11p jgarrett
100* SW7425-468: Adding hooks for NRT DSP mixer support
101*
102* Hydra_Software_Devel/21   9/15/11 9:24a jgarrett
103* SW7425-1285: Sending lower 32-bits of STC to DSP on systems with 42-bit
104* STC support
105*
106* Hydra_Software_Devel/20   7/6/11 4:55p jgarrett
107* SW7358-62: Storing a local copy of the XptContextMap structure
108*
109* Hydra_Software_Devel/19   6/27/11 8:27a jgarrett
110* SW7425-654: Merging NRT to main line
111*
112* Hydra_Software_Devel/NRT_XCODE_DEVEL/2   6/23/11 11:03a jgarrett
113* SW7425-654: Changing realtimeMode setting for new API
114*
115* Hydra_Software_Devel/NRT_XCODE_DEVEL/1   6/21/11 5:54p jgarrett
116* SW7425-654: Adding NRT hooks
117*
118* Hydra_Software_Devel/18   6/21/11 3:50p jgarrett
119* SW7425-654: Adding NRT APIs to decoder and mux
120*
121* Hydra_Software_Devel/17   6/17/11 4:50p jgarrett
122* SW7425-741: Updated ITB parsing to drop variable entries for ASC and
123* AlgoInfo.
124*
125* Hydra_Software_Devel/16   5/24/11 3:18p jgarrett
126* SW7425-637: Initializing metadata structure to 0
127*
128* Hydra_Software_Devel/15   4/20/11 12:33p jgarrett
129* SW7425-288: Flushing data cache properly on ADTS wraparound cases
130*
131* Hydra_Software_Devel/14   4/18/11 10:16p jgarrett
132* SW7425-288: Coverity CID 398
133*
134* Hydra_Software_Devel/13   4/18/11 10:09p jgarrett
135* SW7425-361: Refactoring DSP branch decisions
136*
137* Hydra_Software_Devel/12   4/18/11 8:54p jgarrett
138* SW7425-288: Adding ADTS parsing and metadata
139*
140* Hydra_Software_Devel/11   4/17/11 1:55p jgarrett
141* SW7425-288: Adding audio codec to metadata
142*
143* Hydra_Software_Devel/10   4/17/11 1:26p jgarrett
144* SW7425-288: Filling metadata descriptors for sample rate
145*
146* Hydra_Software_Devel/9   4/16/11 2:01p jgarrett
147* SW7425-288: Adding metadata interface
148*
149* Hydra_Software_Devel/8   4/16/11 1:43p jgarrett
150* SW7425-329: Converting buffer descriptors and frame buffer to cached
151* addresses
152*
153* Hydra_Software_Devel/7   4/16/11 12:15p jgarrett
154* SW7425-371: Removing tab characters
155*
156* Hydra_Software_Devel/6   4/15/11 9:24p jgarrett
157* SW7425-88: Refactoring EOS handling to send one EOS at end of stream
158*
159* Hydra_Software_Devel/5   4/14/11 3:25p jgarrett
160* SW7425-360: Fixing shutdown crash if resources are leaked in the app
161*
162* Hydra_Software_Devel/4   4/12/11 3:05p jgarrett
163* SWDTV-6305: Eliminating strict-aliasing warnings.
164*
165* Hydra_Software_Devel/3   3/28/11 3:55p srajapur
166* SW7422-356 : [7425] Corrected stopped flag.
167*
168* Hydra_Software_Devel/2   3/22/11 2:35p jgarrett
169* SW7422-356: Fixing polarity of stopped flag
170*
171* Hydra_Software_Devel/1   3/21/11 7:08p jgarrett
172* SW7422-356: Adding MuxOutput
173*
174***************************************************************************/
175
176#include "bape.h"
177#include "bape_priv.h"
178#include "bchp_common.h"
179
180#ifdef BCHP_XPT_PCROFFSET_REG_START
181#include "bchp_xpt_pcroffset.h"
182#endif
183
184BDBG_MODULE(bape_mux_output);
185
186BDBG_OBJECT_ID(BAPE_MuxOutput);
187
188typedef union BAPE_MuxOutputItbEntry
189{
190    uint32_t ui32data[16];
191    struct
192    {
193        struct
194        {
195            uint32_t reserved0:23;
196            uint32_t error:1;
197            uint32_t entry_type:8;
198
199            uint32_t ui32CDB_Address;
200
201            uint32_t ui32Reserved0:31;
202            uint32_t ui32FrameValid:1;
203
204            uint32_t ui32Reserved1;
205        } base_address;
206
207        struct
208        {
209            uint32_t dts_32:1;
210            uint32_t pts_32:1;
211            uint32_t reserved1:13;
212            uint32_t dts_valid:1;
213            uint32_t reserved2:8;
214            uint32_t entry_type:8;
215
216            uint32_t ui32PTS;
217
218            uint32_t ui32STCSnapshotUpper;
219
220            uint32_t ui32STCSnapshotLower;
221        } pts_dts;
222
223        struct
224        {
225            uint32_t reserved3:24;
226            uint32_t entry_type:8;
227
228            uint32_t ticks_per_bit:16;
229            int32_t shr:16;
230
231            uint32_t ui32Samplerate;
232            uint32_t ui32Reserved3;
233        } bit_rate;
234
235        struct
236        {
237            uint32_t reserved4:24;
238            uint32_t entry_type:8;
239
240            uint32_t ui32ESCR;
241            uint32_t ui32OriginalPTS;
242
243            uint32_t ui32Reserved4:31;
244            uint32_t ui32OriginalPTSInterpolated:1;
245        } escr_metadata;
246    } fields;
247} BAPE_MuxOutputItbEntry;
248
249typedef struct 
250{
251    uint32_t algo_id:8;
252    uint32_t reserved1:16;
253    uint32_t entry_type:8;
254
255    uint32_t ui32BitsPerSample:8;
256    uint32_t ui32ChannelConfig:8;
257    uint32_t ui32HRDSize:16;
258
259    uint32_t ui32BitRate;
260
261    uint32_t ui32MaxBitRate;
262} BAPE_MuxOutputAlgoInfoItbEntry;
263
264typedef struct 
265{
266    uint32_t entry_number:8;
267    uint32_t num_entries:8;
268    uint32_t reserved:8;
269    uint32_t entry_type:8;
270
271    uint32_t ui32ASC0:16;
272    uint32_t ui32ASCSize:16;
273
274    uint32_t ui32ASC1;
275
276    uint32_t ui32ASC2;
277} BAPE_MuxOutputAscItbEntry;
278
279typedef struct
280{
281    uint32_t entry_number:8;
282    uint32_t num_entries:8;
283    uint32_t reserved1:8;
284    uint32_t entry_type:8;
285
286    uint32_t ui32EncodeOption:16;
287    uint32_t reserved2:16;
288
289    uint32_t ui32BlockAlign:16;
290    uint32_t ui32SamplesPerFrame:16;
291
292    uint32_t ui32SuperBlockAlign;
293} BAPE_MuxOutputWmaSpecificItbEntry;
294
295#define BAPE_MUXOUTPUT_MAX_ITBDESCRIPTORS 128
296#define BAPE_MUXOUTPUT_MAX_METADATADESCRIPTORS 1
297#define BAPE_MUXOUTPUT_MAX_ADTS_SEGMENTS 5          /* ADTS can have up to 4 data segments with a max of one CDB wrap around */
298#define BAPE_MUXOUTPUT_MAX_ASC_ENTRIES 2
299
300typedef struct BAPE_OutputDescriptorInfo
301{
302    uint32_t uiITBBufferShadowReadOffset; /* Points to the ITB entry that needs to be parsed next */
303    uint32_t uiCDBBufferShadowReadOffset; /* Points to the CDB location that needs to be muxed next */
304
305    BAVC_AudioBufferDescriptor *pstDescriptorsCached;
306    BAVC_AudioBufferDescriptor *pstDescriptorsUncached;
307    BAVC_AudioMetadataDescriptor *pstMetadataCached;
308    BAVC_AudioMetadataDescriptor *pstMetadataUncached;
309    uint32_t uiDescriptorWriteOffset;
310    uint32_t uiDescriptorReadOffset;
311    unsigned numOutstandingDescriptors;
312
313    /* ITB Parsing Info */
314    struct
315    {
316        bool nextValid, algoInfoValid;
317        BAPE_MuxOutputItbEntry current, next;
318        BAPE_MuxOutputAlgoInfoItbEntry algoInfo;
319        BAPE_MuxOutputAscItbEntry asc[BAPE_MUXOUTPUT_MAX_ASC_ENTRIES];       
320    } itb;
321
322    /* ADTS Parsing Info */
323    unsigned adtsSegment, adtsNumSegments;
324    unsigned adtsSegmentOffset[BAPE_MUXOUTPUT_MAX_ADTS_SEGMENTS];
325    unsigned adtsSegmentLength[BAPE_MUXOUTPUT_MAX_ADTS_SEGMENTS];
326    unsigned adtsSegmentRawOffset[BAPE_MUXOUTPUT_MAX_ADTS_SEGMENTS];
327    unsigned adtsSegmentRawLength[BAPE_MUXOUTPUT_MAX_ADTS_SEGMENTS];
328} BAPE_OutputDescriptorInfo;
329
330typedef struct BAPE_MuxOutput
331{
332    BDBG_OBJECT(BAPE_MuxOutput)
333    BAPE_PathNode node;
334    bool started;
335    bool sendEos;
336    bool sendMetadata;
337    BAPE_MuxOutputStartSettings startSettings;
338    BAVC_XptContextMap contextMap;
339    BAPE_MuxOutputCreateSettings createSettings;
340    BAPE_Connector input;
341    BDSP_TaskHandle task;
342    unsigned branchId, stageId;
343    void *pCdbBaseCached;
344    BAPE_OutputDescriptorInfo descriptorInfo;
345    BLST_S_ENTRY(BAPE_MuxOutput) deviceListNode;
346} BAPE_MuxOutput;
347
348static BERR_Code BAPE_MuxOutput_P_ConnectorSupported(struct BAPE_PathNode *pNode, BAPE_PathConnector *pConnector);
349static BERR_Code BAPE_MuxOutput_P_AllocatePathFromInput(struct BAPE_PathNode *pNode, struct BAPE_PathConnection *pConnection);
350static BERR_Code BAPE_MuxOutput_P_ConfigPathFromInput(struct BAPE_PathNode *pNode, struct BAPE_PathConnection *pConnection);
351static void BAPE_MuxOutput_P_StopPathFromInput(struct BAPE_PathNode *pNode, struct BAPE_PathConnection *pConnection);
352static void BAPE_MuxOutput_P_RemoveInputCallback(struct BAPE_PathNode *pNode, BAPE_PathConnector *pConnector);
353static void BAPE_MuxOutput_P_ParseItb(BAPE_MuxOutputHandle handle, BAPE_MuxOutputItbEntry **pCurrent, BAPE_MuxOutputItbEntry **pNext, BAVC_AudioMetadataDescriptor *pMetadataDescriptor);
354
355static BERR_Code BAPE_MuxOutput_P_ParseAdtsMetadata(
356    BAPE_MuxOutputHandle handle, 
357    BAVC_AudioBufferDescriptor *pFrameDescriptor, 
358    BAVC_AudioMetadataDescriptor *pMetadataDescriptor
359    );
360extern void BAPE_MuxOutput_P_ParseAdtsSegments( 
361    BAPE_MuxOutputHandle handle, 
362    const uint8_t *pBuffer,
363    size_t bufferLength,
364    const uint8_t *pWrapBuffer,
365    size_t wrapBufferLength
366    );
367
368/***************************************************************************
369Summary:
370    Get default settings for a MuxOutput stage
371***************************************************************************/
372void BAPE_MuxOutput_GetDefaultCreateSettings(
373    BAPE_MuxOutputCreateSettings *pSettings   /* [out] default settings */
374    )
375{
376    BDBG_ASSERT(NULL != pSettings);
377    BKNI_Memset(pSettings, 0, sizeof(*pSettings));
378}
379
380/***************************************************************************
381Summary:
382    Open a MuxOutput stage
383***************************************************************************/
384BERR_Code BAPE_MuxOutput_Create(
385    BAPE_Handle deviceHandle,
386    const BAPE_MuxOutputCreateSettings *pSettings,
387    BAPE_MuxOutputHandle *pHandle
388    )
389{
390    BAPE_MuxOutputHandle handle;
391    BERR_Code errCode;
392    uint32_t offset;
393    void *pAddress;
394    size_t cdbLength;
395
396    BDBG_OBJECT_ASSERT(deviceHandle, BAPE_Device);
397    BDBG_ASSERT(NULL != pSettings);
398    BDBG_ASSERT(NULL != pHandle);
399
400    BDBG_ASSERT(NULL != pSettings->pContextMap);
401
402    handle = BKNI_Malloc(sizeof(BAPE_MuxOutput));
403    if ( NULL == handle )
404    {
405        return BERR_TRACE(BERR_OUT_OF_SYSTEM_MEMORY);
406    }
407    BKNI_Memset(handle, 0, sizeof(BAPE_MuxOutput));
408    BDBG_OBJECT_SET(handle, BAPE_MuxOutput);
409    handle->createSettings = *pSettings;
410    /* Technically, this has no output paths, but unless you set 1 below you get a compiler warning */
411    BAPE_P_InitPathNode(&handle->node, BAPE_PathNodeType_eMuxOutput, 0, 1, deviceHandle, handle);
412    handle->node.pName = "MuxOutput";
413
414    /* Save RAVE Context */
415    BKNI_Memcpy(&handle->contextMap, pSettings->pContextMap, sizeof(BAVC_XptContextMap));
416    handle->createSettings.pContextMap = &handle->contextMap;
417
418    /* Reset shadow pointers */
419    handle->descriptorInfo.uiCDBBufferShadowReadOffset = BREG_Read32(handle->node.deviceHandle->regHandle, pSettings->pContextMap->CDB_Base);
420    handle->descriptorInfo.uiITBBufferShadowReadOffset = BREG_Read32(handle->node.deviceHandle->regHandle, pSettings->pContextMap->ITB_Base);
421
422    /* MuxOutput Specifics */
423    handle->node.connectorSupported = BAPE_MuxOutput_P_ConnectorSupported;
424    handle->node.allocatePathFromInput = BAPE_MuxOutput_P_AllocatePathFromInput;
425    handle->node.configPathFromInput = BAPE_MuxOutput_P_ConfigPathFromInput;
426    handle->node.stopPathFromInput = BAPE_MuxOutput_P_StopPathFromInput;
427    handle->node.removeInput = BAPE_MuxOutput_P_RemoveInputCallback;
428
429    offset = BREG_Read32(deviceHandle->regHandle, pSettings->pContextMap->CDB_Base);
430
431    errCode = BMEM_Heap_ConvertOffsetToAddress(deviceHandle->memHandle, offset, &pAddress);
432    if ( errCode )
433    {
434        errCode = BERR_TRACE(errCode);
435        goto err_cdb_offset;
436    }
437    errCode = BMEM_Heap_ConvertAddressToCached(deviceHandle->memHandle, pAddress, &handle->pCdbBaseCached);
438    if ( errCode )
439    {
440        errCode = BERR_TRACE(errCode);
441        goto err_cdb_cached;
442    }
443    /* Flush the CDB data from the cache prior to the HW filling it */
444    cdbLength = (1+BREG_Read32(deviceHandle->regHandle, pSettings->pContextMap->CDB_End))-offset;
445    BMEM_Heap_FlushCache(deviceHandle->memHandle, handle->pCdbBaseCached, cdbLength);
446
447    handle->descriptorInfo.pstDescriptorsUncached = BMEM_Heap_Alloc(deviceHandle->memHandle, sizeof(BAVC_AudioBufferDescriptor)*BAPE_MUXOUTPUT_MAX_ITBDESCRIPTORS);
448    if ( NULL == handle->descriptorInfo.pstDescriptorsUncached ) 
449    {
450        errCode = BERR_TRACE(BERR_OUT_OF_DEVICE_MEMORY);
451        goto err_alloc_descriptors;
452    }
453    errCode = BMEM_Heap_ConvertAddressToCached(deviceHandle->memHandle, handle->descriptorInfo.pstDescriptorsUncached, &pAddress);
454    if ( errCode )
455    {
456        errCode = BERR_TRACE(errCode);
457        goto err_cache_descriptors;
458    }
459    handle->descriptorInfo.pstDescriptorsCached = pAddress;
460    handle->descriptorInfo.pstMetadataUncached = BMEM_Heap_Alloc(deviceHandle->memHandle, sizeof(BAVC_AudioMetadataDescriptor)*BAPE_MUXOUTPUT_MAX_METADATADESCRIPTORS);
461    if ( NULL == handle->descriptorInfo.pstMetadataUncached ) 
462    {
463        errCode = BERR_TRACE(BERR_OUT_OF_DEVICE_MEMORY);
464        goto err_alloc_metadata;
465    }
466    errCode = BMEM_Heap_ConvertAddressToCached(deviceHandle->memHandle, handle->descriptorInfo.pstMetadataUncached, &pAddress);
467    if ( errCode )
468    {
469        errCode = BERR_TRACE(errCode);
470        goto err_cache_metadata;
471    }
472    handle->descriptorInfo.pstMetadataCached = pAddress;
473
474    BLST_S_INSERT_HEAD(&deviceHandle->muxOutputList, handle, deviceListNode);
475
476    *pHandle = handle;
477    return BERR_SUCCESS;
478
479err_cache_metadata:
480    BMEM_Heap_Free(deviceHandle->memHandle, handle->descriptorInfo.pstMetadataUncached);
481err_alloc_metadata:
482err_cache_descriptors:
483    BMEM_Heap_Free(deviceHandle->memHandle, handle->descriptorInfo.pstDescriptorsUncached);
484err_alloc_descriptors:
485err_cdb_cached:   
486err_cdb_offset:
487    BDBG_OBJECT_DESTROY(handle, BAPE_MuxOutput);
488    BKNI_Free(handle);
489
490    return errCode;
491}
492
493
494/***************************************************************************
495Summary:
496    Close a MuxOutput stage
497   
498Description:
499    Input to the stage must be removed prior to closing.
500***************************************************************************/
501void BAPE_MuxOutput_Destroy(
502    BAPE_MuxOutputHandle handle
503    )
504{
505    bool running;
506    BDBG_OBJECT_ASSERT(handle, BAPE_MuxOutput);
507    running = (handle->task != NULL)?true:false;
508    BDBG_ASSERT(false == running);
509    BDBG_ASSERT(NULL == handle->input);
510    BLST_S_REMOVE(&handle->node.deviceHandle->muxOutputList, handle, BAPE_MuxOutput, deviceListNode);
511    BMEM_Heap_Free(handle->node.deviceHandle->memHandle, handle->descriptorInfo.pstMetadataUncached);
512    BMEM_Heap_Free(handle->node.deviceHandle->memHandle, handle->descriptorInfo.pstDescriptorsUncached);
513    BDBG_OBJECT_DESTROY(handle, BAPE_MuxOutput);
514    BKNI_Free(handle);
515}
516
517/***************************************************************************
518Summary:
519    Get Default Start-time Settings for a MuxOutput object
520***************************************************************************/
521void BAPE_MuxOutput_GetDefaultStartSettings(
522    BAPE_MuxOutputStartSettings *pSettings    /* [out] Settings */
523    )
524{
525    BDBG_ASSERT(NULL != pSettings);
526    BKNI_Memset(pSettings, 0, sizeof(*pSettings));   
527}
528
529static BERR_Code BAPE_MuxOutput_P_ApplyDspSettings(
530    BAPE_MuxOutputHandle handle
531    )
532{
533    BERR_Code errCode;
534    BDSP_Raaga_Audio_GenCdbItbConfigParams userConfig;
535
536    BDBG_OBJECT_ASSERT(handle, BAPE_MuxOutput);
537    BDBG_ASSERT(NULL != handle->task);
538
539    errCode = BDSP_Task_GetStageSettings(handle->task, handle->branchId, handle->stageId, &userConfig, sizeof(userConfig));
540    if ( errCode )
541    {
542        return BERR_TRACE(errCode);
543    }
544
545    userConfig.eEnableEncode = handle->started ? BDSP_AF_P_eEnable : BDSP_AF_P_eDisable;
546    userConfig.ui32EncSTCAddr = BCHP_PHYSICAL_OFFSET + BAPE_CHIP_GET_STC_ADDRESS(handle->startSettings.stcIndex);
547    userConfig.ui32A2PInMilliSeconds = handle->startSettings.presentationDelay;
548    userConfig.eSnapshotRequired = (NULL == handle->startSettings.pNonRealTimeIncrement) ? BDSP_AF_P_eEnable /* RT */ : BDSP_AF_P_eDisable /* NRT */;
549
550    errCode = BDSP_Task_SetStageSettings(handle->task, handle->branchId, handle->stageId, &userConfig, sizeof(userConfig));
551    if ( errCode )
552    {
553        return BERR_TRACE(errCode);
554    }
555
556    return BERR_SUCCESS;
557}
558
559/***************************************************************************
560Summary:
561    Start a MuxOutput Object
562
563Description:
564    Typically, this is called prior to BAPE_Decoder_Start() in order to
565    guarantee all data is captured.
566
567See Also:
568    BAPE_MuxOutput_GetDefaultStartSettings
569    BAPE_MuxOutput_Stop
570***************************************************************************/
571BERR_Code BAPE_MuxOutput_Start(
572    BAPE_MuxOutputHandle handle,
573    const BAPE_MuxOutputStartSettings *pSettings
574    )
575{
576    BERR_Code errCode;
577
578    BDBG_OBJECT_ASSERT(handle, BAPE_MuxOutput);
579
580    if ( handle->started )
581    {
582        BDBG_ERR(("Already started."));
583        return BERR_TRACE(BERR_INVALID_PARAMETER);
584    }
585
586    if ( NULL == pSettings )
587    {
588        BAPE_MuxOutput_GetDefaultStartSettings(&handle->startSettings);
589        pSettings = &handle->startSettings;
590    }
591    else
592    {
593        if ( pSettings->stcIndex > BAPE_CHIP_MAX_STCS )
594        {
595            BDBG_ERR(("STC Index %u out of range.  Supported values are 0..%u", BAPE_CHIP_MAX_STCS));
596            return BERR_TRACE(BERR_INVALID_PARAMETER);
597        }
598        BKNI_Memcpy(&handle->startSettings, pSettings, sizeof(BAPE_MuxOutputStartSettings));
599    }
600
601    if ( NULL != pSettings->pNonRealTimeIncrement && handle->task )
602    {
603        BDBG_ERR(("To configure for Non-Realtime Transcode, BAPE_MuxOutput_Start must be called prior to starting transcoder input."));
604        return BERR_TRACE(BERR_NOT_SUPPORTED);
605    }
606
607    BDBG_MSG(("BAPE_MuxOutput_Start"));
608
609    /* Update shadow pointers for context to the current read pointer. */
610    handle->descriptorInfo.uiCDBBufferShadowReadOffset = BREG_Read32(handle->node.deviceHandle->regHandle, handle->createSettings.pContextMap->CDB_Read);
611    handle->descriptorInfo.uiITBBufferShadowReadOffset = BREG_Read32(handle->node.deviceHandle->regHandle, handle->createSettings.pContextMap->ITB_Read);
612    /* Reset Descriptor Offsets in case mux didn't consume all previous descriptors */
613    handle->descriptorInfo.uiDescriptorWriteOffset = 0;
614    handle->descriptorInfo.uiDescriptorReadOffset = 0;
615    handle->descriptorInfo.numOutstandingDescriptors = 0;
616
617    /* Start */
618    handle->started = true;
619    handle->sendEos = false;
620    handle->sendMetadata = true;
621
622    if ( handle->task )
623    {
624        errCode = BAPE_MuxOutput_P_ApplyDspSettings(handle);
625        if ( errCode )
626        {
627            return BERR_TRACE(errCode);
628        }
629    }
630
631    return BERR_SUCCESS;
632}
633
634/***************************************************************************
635Summary:
636    Stop a MuxOutput Object
637
638Description:
639    Typically, this is called after BAPE_Decoder_Stop() in order to
640    guarantee all data is captured.
641
642See Also:
643    BAPE_MuxOutput_Start
644***************************************************************************/
645void BAPE_MuxOutput_Stop(
646    BAPE_MuxOutputHandle handle
647    )
648{
649    BERR_Code errCode;
650
651    BDBG_OBJECT_ASSERT(handle, BAPE_MuxOutput);
652
653    if ( !handle->started )
654    {
655        return;
656    }
657
658    BDBG_MSG(("BAPE_MuxOutput_Stop"));
659    handle->started = false;
660    handle->sendEos = true;
661
662    if ( handle->task )
663    {
664        errCode = BAPE_MuxOutput_P_ApplyDspSettings(handle);
665        if ( errCode )
666        {
667            (void)BERR_TRACE(errCode);
668            return;
669        }
670    }
671}
672
673BERR_Code BAPE_MuxOutput_GetBufferDescriptors(
674    BAPE_MuxOutputHandle handle,
675    const BAVC_AudioBufferDescriptor **pBuffer, /* [out] pointer to BAVC_AudioBufferDescriptor structs */
676    size_t *pSize, /* [out] size of pBuffer in bytes (not number of BAVC_AudioBufferDescriptor structs) */
677    const BAVC_AudioBufferDescriptor **pBuffer2, /* [out] pointer to BAVC_AudioBufferDescriptor structs after wrap around */
678    size_t *pSize2 /* [out] size of pBuffer2 in bytes (not number of BAVC_AudioBufferDescriptor structs) */
679    )
680{
681    BREG_Handle regHandle;
682    BAPE_MuxOutputItbEntry *pITBEntry;
683    BAPE_MuxOutputItbEntry *pITBEntryNext = NULL;
684    BAVC_AudioBufferDescriptor *pAudioDescriptor;
685    uint32_t uiCDBBaseOffset;
686    uint32_t uiCDBEndOffset;
687    uint32_t uiCDBValidOffset;
688    uint32_t uiCDBReadOffset;
689    uint32_t uiCDBEndOfFrameOffset; 
690    uint32_t uiTemp;
691    BAPE_OutputDescriptorInfo *psOutputDescDetails;
692    BAVC_AudioMetadataDescriptor stMetadata;
693    BERR_Code ret = BERR_SUCCESS;
694
695    BDBG_OBJECT_ASSERT(handle, BAPE_MuxOutput);
696    BDBG_ASSERT(NULL != pBuffer);
697    BDBG_ASSERT(NULL != pBuffer2);
698    BDBG_ASSERT(NULL != pSize);
699    BDBG_ASSERT(NULL != pSize2);
700
701    BDBG_ENTER(BAPE_MuxOutput_GetBufferDescriptors);
702
703    regHandle = handle->node.deviceHandle->regHandle;
704
705    psOutputDescDetails = &handle->descriptorInfo;
706
707    *pBuffer = NULL;
708    *pBuffer2 = NULL;
709    *pSize = 0;
710    *pSize2 = 0;
711
712    /* Read CDB Addresses */           
713    uiCDBBaseOffset = BREG_Read32(regHandle, handle->createSettings.pContextMap->CDB_Base);
714    uiCDBEndOffset = BREG_Read32(regHandle, handle->createSettings.pContextMap->CDB_End);           
715    uiCDBValidOffset = BREG_Read32(regHandle, handle->createSettings.pContextMap->CDB_Valid);
716    uiCDBReadOffset = BREG_Read32(regHandle, handle->createSettings.pContextMap->CDB_Read);
717
718    if ( uiCDBEndOffset != 0 )
719    {
720        uiCDBEndOffset += 1; /* end is inclusive */
721    }
722
723    BDBG_MSG(("CDB Base/End/Shadow Read/Read/Write = %08x/%08x/%08x (%08x)/%08x",
724              uiCDBBaseOffset,
725              uiCDBEndOffset,
726              psOutputDescDetails->uiCDBBufferShadowReadOffset,
727              uiCDBReadOffset,
728              uiCDBValidOffset
729             ));
730
731    while ( 1 )
732    {
733        /* Check for Available ITB Entries */
734        /* TODO: We may want to copy ITB entries into local memory
735         * so that we can handle ITB wrap easily
736         */
737
738        BAPE_MuxOutput_P_ParseItb(handle, &pITBEntry, &pITBEntryNext, &stMetadata);
739        if ( NULL == pITBEntry )
740        {
741            BDBG_MSG(("No more ITB Entries"));
742            break;
743        }
744        if ( NULL == pITBEntryNext )
745        {
746            /* We can not work unless we have the next ITB entry to determine real frame size.
747               Full frame of data is required. */
748            BDBG_MSG(("Partial Frame in CDB"));
749            break;
750        }
751        else if ( uiCDBValidOffset == psOutputDescDetails->uiCDBBufferShadowReadOffset && \
752                  pITBEntry->fields.base_address.ui32FrameValid )
753        {
754            /* We ran out of CDB data */
755            BDBG_MSG(("No more CDB Data"));
756            break;
757        }
758        else
759        {
760            uint32_t uiDepthToNext;
761            uint32_t uiDepthToValid;
762
763            /* It is possible that the CDB Valid doesn't, yet, contain any of the next frame and
764             * may still be in the middle of the current frame, so we need use the depth that is the
765             * lesser of depth(cdb_read,cdb_next) depth(cdb_read,cdb_valid)
766             */
767            if ( pITBEntryNext->fields.base_address.ui32CDB_Address > \
768                 psOutputDescDetails->uiCDBBufferShadowReadOffset )
769            {
770                uiDepthToNext = pITBEntryNext->fields.base_address.ui32CDB_Address - \
771                                psOutputDescDetails->uiCDBBufferShadowReadOffset;
772            }
773            else
774            {
775                uiDepthToNext = uiCDBEndOffset - \
776                                psOutputDescDetails->uiCDBBufferShadowReadOffset;
777                uiDepthToNext += pITBEntryNext->fields.base_address.ui32CDB_Address - uiCDBBaseOffset;
778            }
779
780            if ( uiCDBValidOffset >= \
781                 psOutputDescDetails->uiCDBBufferShadowReadOffset )
782            {
783                uiDepthToValid = uiCDBValidOffset - \
784                                 psOutputDescDetails->uiCDBBufferShadowReadOffset;
785            }
786            else
787            {
788                uiDepthToValid = uiCDBEndOffset - \
789                                 psOutputDescDetails->uiCDBBufferShadowReadOffset;
790                uiDepthToValid += uiCDBValidOffset - uiCDBBaseOffset;
791            }
792
793            if ( uiDepthToValid < uiDepthToNext )
794            {
795                uiCDBEndOfFrameOffset = uiCDBValidOffset;
796            }
797            else
798            {
799                uiCDBEndOfFrameOffset = pITBEntryNext->fields.base_address.ui32CDB_Address;
800            }
801        }
802
803        /* Get Audio Descriptor for this ITB entry */
804        uiTemp = (psOutputDescDetails->uiDescriptorWriteOffset + 1) % BAPE_MUXOUTPUT_MAX_ITBDESCRIPTORS;
805        if ( uiTemp == psOutputDescDetails->uiDescriptorReadOffset )
806        {
807            BDBG_MSG(("Out of descriptors"));
808            break;
809        }
810        pAudioDescriptor = &psOutputDescDetails->pstDescriptorsCached[psOutputDescDetails->uiDescriptorWriteOffset];
811        psOutputDescDetails->uiDescriptorWriteOffset = uiTemp;
812
813        BKNI_Memset(pAudioDescriptor, 0, sizeof(BAVC_AudioBufferDescriptor));
814
815        if ( uiCDBEndOfFrameOffset > psOutputDescDetails->uiCDBBufferShadowReadOffset )
816        {
817            pAudioDescriptor->stCommon.uiLength = uiCDBEndOfFrameOffset - \
818                                                  psOutputDescDetails->uiCDBBufferShadowReadOffset;
819        }
820        else
821        {
822            /* CDB Wrap occurs, so we need to split this picture into two descriptors.  We handle the first one here. */
823            pAudioDescriptor->stCommon.uiLength = uiCDBEndOffset - \
824                                                  psOutputDescDetails->uiCDBBufferShadowReadOffset;
825        }
826
827        /* Populate other fields iff this descriptor contains the beginning of the frame */
828        if ( psOutputDescDetails->uiCDBBufferShadowReadOffset == \
829             pITBEntry->fields.base_address.ui32CDB_Address )
830        {
831
832            /* We're muxing the beginning of this frame */
833            pAudioDescriptor->stCommon.uiFlags |= BAVC_COMPRESSEDBUFFERDESCRIPTOR_FLAGS_FRAME_START;
834
835            /* Determine if the original PTS is coded or interpolated */
836            if ( pITBEntry->fields.escr_metadata.ui32OriginalPTSInterpolated == 0 )
837            {   
838                /* TODO: Is this the correct logic?  This could always be interpolated with frame size changes */
839                pAudioDescriptor->stCommon.uiFlags |= BAVC_COMPRESSEDBUFFERDESCRIPTOR_FLAGS_ORIGINALPTS_VALID;
840            }
841            pAudioDescriptor->stCommon.uiOriginalPTS = pITBEntry->fields.escr_metadata.ui32OriginalPTS;
842
843            pAudioDescriptor->stCommon.uiFlags |= BAVC_COMPRESSEDBUFFERDESCRIPTOR_FLAGS_PTS_VALID;
844            pAudioDescriptor->stCommon.uiPTS = pITBEntry->fields.pts_dts.pts_32;
845            pAudioDescriptor->stCommon.uiPTS <<= 32;
846            pAudioDescriptor->stCommon.uiPTS |= pITBEntry->fields.pts_dts.ui32PTS;
847
848            pAudioDescriptor->stCommon.uiFlags |= BAVC_COMPRESSEDBUFFERDESCRIPTOR_FLAGS_ESCR_VALID;
849            pAudioDescriptor->stCommon.uiESCR = pITBEntry->fields.escr_metadata.ui32ESCR;
850
851            pAudioDescriptor->stCommon.uiFlags |= BAVC_COMPRESSEDBUFFERDESCRIPTOR_FLAGS_TICKSPERBIT_VALID;
852            pAudioDescriptor->stCommon.uiTicksPerBit = pITBEntry->fields.bit_rate.ticks_per_bit;
853
854            pAudioDescriptor->stCommon.uiFlags |= BAVC_COMPRESSEDBUFFERDESCRIPTOR_FLAGS_SHR_VALID;
855            pAudioDescriptor->stCommon.iSHR = pITBEntry->fields.bit_rate.shr;
856
857            if ( 0 == pITBEntry->fields.base_address.ui32FrameValid )
858            {
859                pAudioDescriptor->stCommon.uiFlags |= BAVC_COMPRESSEDBUFFERDESCRIPTOR_FLAGS_EMPTY_FRAME;
860                BDBG_MSG(("Empty frame received in mux"));
861            }
862        }
863
864        /* Normalize the offset to 0 */
865        pAudioDescriptor->stCommon.uiOffset = \
866                                              psOutputDescDetails->uiCDBBufferShadowReadOffset - uiCDBBaseOffset;
867       
868        /* Invalidate this frame from the cache prior to the host accessing it */
869        BMEM_Heap_FlushCache(handle->node.deviceHandle->memHandle, 
870                             (char *)handle->pCdbBaseCached + pAudioDescriptor->stCommon.uiOffset, 
871                             pAudioDescriptor->stCommon.uiLength);
872
873        /* Set RAW data offset and length equal to frame offset and length.  When ADTS is parsed, add actual raw offset/length here */
874        pAudioDescriptor->uiRawDataOffset = pAudioDescriptor->stCommon.uiOffset;
875        pAudioDescriptor->uiRawDataLength = pAudioDescriptor->stCommon.uiLength;
876
877        switch ( handle->input->codec )
878        {
879        case BAVC_AudioCompressionStd_eAacAdts:
880        case BAVC_AudioCompressionStd_eAacPlusAdts:
881            /* If Start Of Frame */
882            if ( pAudioDescriptor->stCommon.uiFlags & BAVC_COMPRESSEDBUFFERDESCRIPTOR_FLAGS_FRAME_START )
883            {
884                uint8_t *pWrapBase;
885                size_t wrapLength;
886                if ( uiCDBEndOfFrameOffset > psOutputDescDetails->uiCDBBufferShadowReadOffset ) 
887                {                   
888                    pWrapBase = NULL;
889                    wrapLength = 0;
890                }
891                else
892                {
893                    pWrapBase = handle->pCdbBaseCached;
894                    wrapLength = uiCDBEndOfFrameOffset - uiCDBBaseOffset;
895                    /* Make sure any wraparound data is also invalidated from the cache prior to accessing it. */
896                    BMEM_Heap_FlushCache(handle->node.deviceHandle->memHandle, pWrapBase, wrapLength);
897                }
898                /* This function can not fail.  It will simply create a single segment equal to the
899                   entire frame if a parse error occurs */
900                BAPE_MuxOutput_P_ParseAdtsSegments(handle, 
901                                                   (uint8_t *)handle->pCdbBaseCached+pAudioDescriptor->stCommon.uiOffset,
902                                                   pAudioDescriptor->stCommon.uiLength,
903                                                   (uint8_t *)pWrapBase,
904                                                   wrapLength);
905            }
906            else
907            {
908                BDBG_MSG(("Not Parsing"));
909            }
910            /* Populate this segment's data */
911            {
912                unsigned segment = handle->descriptorInfo.adtsSegment;
913                if ( segment >= handle->descriptorInfo.adtsNumSegments)
914                {
915                    BDBG_ERR(("ADTS segment parsing error"));
916                    BKNI_Sleep(1000);   /* Let some debug data flush */
917                    BDBG_ASSERT(segment < handle->descriptorInfo.adtsNumSegments);
918                }
919                pAudioDescriptor->stCommon.uiOffset = handle->descriptorInfo.adtsSegmentOffset[segment];
920                pAudioDescriptor->stCommon.uiLength = handle->descriptorInfo.adtsSegmentLength[segment];
921                pAudioDescriptor->uiRawDataOffset = handle->descriptorInfo.adtsSegmentRawOffset[segment];
922                pAudioDescriptor->uiRawDataLength = handle->descriptorInfo.adtsSegmentRawLength[segment];
923                handle->descriptorInfo.adtsSegment = segment+1;
924            }
925            break;
926        default:
927            break;
928        }
929
930        /* Advance read pointer appropriately */
931        psOutputDescDetails->uiCDBBufferShadowReadOffset += \
932                                                            pAudioDescriptor->stCommon.uiLength;
933        if ( psOutputDescDetails->uiCDBBufferShadowReadOffset >= \
934             uiCDBEndOffset )
935        {
936            psOutputDescDetails->uiCDBBufferShadowReadOffset -= \
937                                                                ( uiCDBEndOffset - uiCDBBaseOffset );
938        }
939
940        BDBG_MSG(("Audio Descriptor Base/Length = %08x/%08x Shadow Read %08x",
941                  pAudioDescriptor->stCommon.uiOffset,
942                  pAudioDescriptor->stCommon.uiLength,
943                  psOutputDescDetails->uiCDBBufferShadowReadOffset
944                 ));
945
946        /* If we need to send metadata, send it on the first frame */
947        if ( handle->sendMetadata && (pAudioDescriptor->stCommon.uiFlags & BAVC_COMPRESSEDBUFFERDESCRIPTOR_FLAGS_FRAME_START) )
948        {
949            BAVC_AudioMetadataDescriptor *pMetadataDescriptor = &psOutputDescDetails->pstMetadataCached[0];
950            BAVC_AudioBufferDescriptor *pFrameDescriptor;
951
952            /* This is the first frame so we should always have another descriptor available. Assert for sanity. */
953            uiTemp = (psOutputDescDetails->uiDescriptorWriteOffset + 1) % BAPE_MUXOUTPUT_MAX_ITBDESCRIPTORS;
954            BDBG_ASSERT(uiTemp != psOutputDescDetails->uiDescriptorReadOffset);
955            pFrameDescriptor = &psOutputDescDetails->pstDescriptorsCached[psOutputDescDetails->uiDescriptorWriteOffset];
956            psOutputDescDetails->uiDescriptorWriteOffset = uiTemp;
957
958            /* The metadata descriptor must come before the first frame.  Swap them. */
959            *pFrameDescriptor = *pAudioDescriptor;   /* Copy frame descriptor contents into second descriptor - we're about to overwrite the old one */
960
961            BKNI_Memset(pAudioDescriptor, 0, sizeof(BAVC_AudioBufferDescriptor));
962            /* SW7425-75: For Phase 2.0, only a single metadata descriptor will be sent at the beginning */
963            /* TODO: Update this in Phase 3.0 to send a metadata descriptor on each RAP or when the metadata changes */
964            pAudioDescriptor->stCommon.uiOffset = 0;
965            pAudioDescriptor->stCommon.uiLength = sizeof( BAVC_AudioMetadataDescriptor );
966            pAudioDescriptor->stCommon.uiFlags |= BAVC_COMPRESSEDBUFFERDESCRIPTOR_FLAGS_METADATA;
967            pAudioDescriptor->uiDataUnitType = BAVC_AudioMetadataType_eCommon;
968           
969            /* Populate metadata */
970            BKNI_Memset(pMetadataDescriptor, 0, sizeof(*pMetadataDescriptor));
971
972            if ( stMetadata.uiMetadataFlags & BAVC_AUDIOMETADATADESCRIPTOR_FLAGS_BITRATE_VALID )
973            {
974                pMetadataDescriptor->uiMetadataFlags |= BAVC_AUDIOMETADATADESCRIPTOR_FLAGS_BITRATE_VALID;
975                pMetadataDescriptor->stBitrate = stMetadata.stBitrate;
976            }
977           
978            /* Set Sample Rate */
979            pMetadataDescriptor->uiMetadataFlags |= BAVC_AUDIOMETADATADESCRIPTOR_FLAGS_SAMPLING_FREQUENCY_VALID;
980            pMetadataDescriptor->stSamplingFrequency.uiSamplingFrequency = handle->input->sampleRate;
981           
982            /* Set STC Snapshot */
983            pMetadataDescriptor->uiMetadataFlags |= BAVC_AUDIOMETADATADESCRIPTOR_FLAGS_TIMING_VALID;
984            pMetadataDescriptor->stTiming = stMetadata.stTiming;
985
986            /* Set Protocol */
987            BDBG_MSG(("Setting protocol to %u", handle->input->codec));
988            pMetadataDescriptor->eProtocol = handle->input->codec;
989            switch ( pMetadataDescriptor->eProtocol )
990            {
991            case BAVC_AudioCompressionStd_eAacAdts:
992            case BAVC_AudioCompressionStd_eAacPlusAdts:
993                /* ASSUMPTION: This is the first frame and does not need to handle CDB Wrap or partial frames.
994                   That would make life much more difficult since metadata comes first, and the DSP should be doing this anyway... */
995                ret = BAPE_MuxOutput_P_ParseAdtsMetadata(handle, pFrameDescriptor, pMetadataDescriptor);
996                if ( ret == BERR_SUCCESS )
997                {
998                    pMetadataDescriptor->uiMetadataFlags |= BAVC_AUDIOMETADATADESCRIPTOR_FLAGS_PROTOCOL_DATA_VALID;
999                }
1000                else
1001                {
1002                    BDBG_WRN(("Unable to parse ADTS metadata."));
1003                    ret = BERR_SUCCESS;
1004                }
1005                break;
1006            case BAVC_AudioCompressionStd_eWmaStd:
1007                if ( stMetadata.uiMetadataFlags & BAVC_AUDIOMETADATADESCRIPTOR_FLAGS_PROTOCOL_DATA_VALID )
1008                {
1009                    BAPE_EncoderCodecSettings encoderCodecSettings;                   
1010
1011                    pMetadataDescriptor->uiMetadataFlags |= BAVC_AUDIOMETADATADESCRIPTOR_FLAGS_PROTOCOL_DATA_VALID;
1012                    pMetadataDescriptor->uProtocolData = stMetadata.uProtocolData;  /* Metadata was parsed above */
1013
1014                    BAPE_Encoder_GetCodecSettings(handle->input->pParent->pHandle, BAVC_AudioCompressionStd_eWmaStd, &encoderCodecSettings);
1015                    pMetadataDescriptor->uProtocolData.stWmaStd.uiNumChannels = (encoderCodecSettings.codecSettings.wmaStd.channelMode==BAPE_ChannelMode_e1_0)?1:2;
1016                }
1017                else
1018                {
1019                    BDBG_WRN(("WMA Metadata not available"));
1020                }
1021                break;
1022            default:
1023                break;
1024            }
1025            BDBG_MSG(("Sending Metadata for codec %s (%u) - Flags %#x", BAPE_P_GetCodecName(pMetadataDescriptor->eProtocol), pMetadataDescriptor->eProtocol, pMetadataDescriptor->uiMetadataFlags));
1026
1027            handle->sendMetadata = false;
1028        }
1029    }
1030
1031    if ( handle->sendEos )
1032    {
1033        BDBG_MSG(("EOS Required"));
1034        /* Get a descriptor for EOS */
1035        uiTemp = (psOutputDescDetails->uiDescriptorWriteOffset + 1) % BAPE_MUXOUTPUT_MAX_ITBDESCRIPTORS;
1036        if ( uiTemp == psOutputDescDetails->uiDescriptorReadOffset )
1037        {
1038            BDBG_MSG(("Out of descriptors, can't send EOS"));
1039        }
1040        else
1041        {
1042            pAudioDescriptor = &psOutputDescDetails->pstDescriptorsCached[psOutputDescDetails->uiDescriptorWriteOffset];
1043            psOutputDescDetails->uiDescriptorWriteOffset = uiTemp;
1044
1045            BKNI_Memset(pAudioDescriptor, 0, sizeof(BAVC_AudioBufferDescriptor));
1046
1047            /* Decoder is stopped and we have run out of data. Fill the EOS entry in Audio descriptor */
1048            pAudioDescriptor->stCommon.uiFlags = BAVC_COMPRESSEDBUFFERDESCRIPTOR_FLAGS_EOS;
1049            BDBG_MSG(("EOS %#x", pAudioDescriptor));
1050            handle->sendEos = false;
1051        }
1052    }
1053
1054    /* Assign array(s) and count(s) */
1055    if ( psOutputDescDetails->uiDescriptorWriteOffset >= \
1056         psOutputDescDetails->uiDescriptorReadOffset )
1057    {
1058        *pBuffer = &psOutputDescDetails->pstDescriptorsCached[psOutputDescDetails->uiDescriptorReadOffset];
1059        *pSize = psOutputDescDetails->uiDescriptorWriteOffset - psOutputDescDetails->uiDescriptorReadOffset;
1060
1061        *pBuffer2 = NULL;
1062        *pSize2 = 0;         
1063    }
1064    else
1065    {
1066        *pBuffer = &psOutputDescDetails->pstDescriptorsCached[psOutputDescDetails->uiDescriptorReadOffset];
1067        *pSize = BAPE_MUXOUTPUT_MAX_ITBDESCRIPTORS - psOutputDescDetails->uiDescriptorReadOffset;
1068
1069        *pBuffer2 = &psOutputDescDetails->pstDescriptorsCached[0];
1070        *pSize2 = psOutputDescDetails->uiDescriptorWriteOffset;
1071    }
1072
1073    BDBG_MSG(("pSize = %d",(*pSize)));
1074    for ( uiTemp=0;uiTemp < (*pSize);uiTemp++ )
1075        BDBG_MSG(("astDescriptors0[%d] = 0x%x (flags %#x, len %u)",uiTemp,&psOutputDescDetails->pstDescriptorsCached[psOutputDescDetails->uiDescriptorReadOffset+uiTemp],
1076                  psOutputDescDetails->pstDescriptorsCached[psOutputDescDetails->uiDescriptorReadOffset+uiTemp].stCommon.uiFlags,
1077                  psOutputDescDetails->pstDescriptorsCached[psOutputDescDetails->uiDescriptorReadOffset+uiTemp].stCommon.uiLength));
1078
1079    BDBG_MSG(("pSize2 = %d",(*pSize2)));
1080    for ( uiTemp=0;uiTemp < (*pSize2);uiTemp++ )
1081        BDBG_MSG(("astDescriptors1[%d] = 0x%x (flags %#x, len %u)",uiTemp,&psOutputDescDetails->pstDescriptorsCached[uiTemp],
1082                  psOutputDescDetails->pstDescriptorsCached[uiTemp].stCommon.uiFlags,
1083                  psOutputDescDetails->pstDescriptorsCached[uiTemp].stCommon.uiLength));
1084
1085    psOutputDescDetails->numOutstandingDescriptors = (*pSize) + (*pSize2);
1086    BDBG_MSG(("Returning %u descriptors", psOutputDescDetails->numOutstandingDescriptors));
1087
1088    BDBG_LEAVE(BAPE_MuxOutput_GetBufferDescriptors);
1089
1090    return ret;
1091}
1092
1093BERR_Code BAPE_MuxOutput_ConsumeBufferDescriptors(
1094    BAPE_MuxOutputHandle handle,
1095    unsigned numBufferDescriptors /* must be <= pSize+pSize2 returned by last BAPE_MuxOutput_GetBufferDescriptors call. */
1096    )
1097{
1098    BREG_Handle regHandle;
1099    BERR_Code   ret = BERR_SUCCESS;
1100    uint32_t uiCDBReadOffset;
1101    uint32_t uiCDBEndOffset;
1102    uint32_t uiCDBBaseOffset;
1103    uint32_t uiCDBValidOffset; 
1104    uint32_t uiCDBDepth;
1105    uint32_t uiCDBIncrement=0;
1106    BAPE_OutputDescriptorInfo  *psOutputDescDetails;
1107
1108    BDBG_OBJECT_ASSERT(handle, BAPE_MuxOutput);
1109    BDBG_ASSERT(numBufferDescriptors > 0); 
1110
1111    BDBG_ENTER(BAPE_MuxOutput_ConsumeBufferDescriptors);
1112
1113    BDBG_MSG(("BAPE_MuxOutput_ConsumeBufferDescriptors: uiNumBufferDescriptors = %d",numBufferDescriptors));
1114    regHandle = handle->node.deviceHandle->regHandle;
1115    psOutputDescDetails = &handle->descriptorInfo;
1116
1117    BDBG_ASSERT(numBufferDescriptors <= psOutputDescDetails->numOutstandingDescriptors);
1118    psOutputDescDetails->numOutstandingDescriptors -= numBufferDescriptors;
1119
1120    /* Read CDB Addresses */           
1121    uiCDBBaseOffset = BREG_Read32(regHandle, handle->createSettings.pContextMap->CDB_Base);
1122    uiCDBEndOffset = BREG_Read32(regHandle, handle->createSettings.pContextMap->CDB_End);           
1123    uiCDBValidOffset = BREG_Read32(regHandle, handle->createSettings.pContextMap->CDB_Valid);
1124    uiCDBReadOffset = BREG_Read32(regHandle, handle->createSettings.pContextMap->CDB_Read);
1125    uiCDBEndOffset++;
1126
1127    if ( uiCDBValidOffset == uiCDBReadOffset )
1128    {
1129        uiCDBDepth = 0;
1130    }
1131    else if ( uiCDBValidOffset > uiCDBReadOffset )
1132    {
1133        uiCDBDepth = uiCDBValidOffset - uiCDBReadOffset;
1134    }
1135    else
1136    {
1137        uiCDBDepth = uiCDBEndOffset - uiCDBReadOffset;
1138        uiCDBDepth += uiCDBValidOffset - uiCDBBaseOffset;
1139    }
1140
1141    while ( numBufferDescriptors )
1142    {
1143        if ( 0 == (psOutputDescDetails->pstDescriptorsCached[psOutputDescDetails->uiDescriptorReadOffset].stCommon.uiFlags & (BAVC_COMPRESSEDBUFFERDESCRIPTOR_FLAGS_EOS|BAVC_COMPRESSEDBUFFERDESCRIPTOR_FLAGS_METADATA)) )
1144        {
1145            /* Move CDB Read Offset */
1146            uiCDBIncrement += psOutputDescDetails->pstDescriptorsCached[psOutputDescDetails->uiDescriptorReadOffset].stCommon.uiLength;
1147        }
1148
1149        /* Move Descriptor Read Offset */
1150        psOutputDescDetails->uiDescriptorReadOffset++;
1151        psOutputDescDetails->uiDescriptorReadOffset %= BAPE_MUXOUTPUT_MAX_ITBDESCRIPTORS;
1152
1153        numBufferDescriptors--;
1154    }
1155
1156    if ( uiCDBIncrement > uiCDBDepth )
1157    {
1158        BDBG_ERR(("Attempting to consume %u bytes from CDB when only %u are present.", uiCDBIncrement, uiCDBDepth));
1159        BDBG_ASSERT(uiCDBDepth >= uiCDBIncrement);
1160    }
1161    else
1162    {
1163        BDBG_MSG(("Consume %u of %u bytes from CDB", uiCDBIncrement, uiCDBDepth));
1164    }
1165
1166    uiCDBReadOffset += uiCDBIncrement;
1167    if ( uiCDBReadOffset >= uiCDBEndOffset )
1168    {
1169        uiCDBReadOffset -= ( uiCDBEndOffset - uiCDBBaseOffset );
1170    }
1171
1172    BDBG_MSG(("BRAP_UpdateBufferDescriptors :uiDescriptorReadOffset = %d",\
1173              psOutputDescDetails->uiDescriptorReadOffset));
1174
1175    /* Update Actual ITB/CDB Read Pointers */
1176    BREG_Write32(regHandle, handle->createSettings.pContextMap->CDB_Read, uiCDBReadOffset);
1177    /* No need to compute the ITB amount - just consume all previously used ITB entries in one shot. */
1178    BREG_Write32(regHandle, handle->createSettings.pContextMap->ITB_Read, psOutputDescDetails->uiITBBufferShadowReadOffset);
1179
1180    BDBG_LEAVE (BAPE_MuxOutput_ConsumeBufferDescriptors);
1181    return ret;   
1182}
1183
1184BERR_Code BAPE_MuxOutput_GetBufferStatus(
1185    BAPE_MuxOutputHandle handle,
1186    BAVC_AudioBufferStatus *pBufferStatus    /* [out] */
1187    )
1188{
1189    BDBG_OBJECT_ASSERT(handle, BAPE_MuxOutput);
1190    BDBG_ASSERT(NULL != pBufferStatus);
1191
1192    pBufferStatus->stCommon.pFrameBufferBaseAddress = handle->pCdbBaseCached;
1193    pBufferStatus->stCommon.pMetadataBufferBaseAddress = handle->descriptorInfo.pstMetadataCached;
1194
1195    return BERR_SUCCESS;
1196}
1197
1198void BAPE_MuxOutput_GetConnector(
1199    BAPE_MuxOutputHandle handle,
1200    BAPE_Connector *pConnector
1201    )
1202{
1203    BDBG_OBJECT_ASSERT(handle, BAPE_MuxOutput);
1204    BDBG_ASSERT(NULL != pConnector);
1205    *pConnector = &handle->node.paths[0].connector;
1206}
1207
1208BERR_Code BAPE_MuxOutput_AddInput(
1209    BAPE_MuxOutputHandle handle,
1210    BAPE_Connector input
1211    )
1212{
1213    BERR_Code errCode;
1214    BDBG_OBJECT_ASSERT(handle, BAPE_MuxOutput);
1215    BDBG_OBJECT_ASSERT(input, BAPE_PathConnector);
1216    if ( NULL != handle->input )
1217    {
1218        BDBG_ERR(("Can not have more than one input"));
1219        return BERR_TRACE(BERR_NOT_SUPPORTED);
1220    }
1221    errCode = BAPE_PathNode_P_AddInput(&handle->node, input);
1222    if ( errCode )
1223    {
1224        return BERR_TRACE(errCode);
1225    }
1226    handle->input = input;
1227    return BERR_SUCCESS;
1228}
1229
1230BERR_Code BAPE_MuxOutput_RemoveInput(
1231    BAPE_MuxOutputHandle handle,
1232    BAPE_Connector input
1233    )
1234{
1235    BERR_Code errCode;
1236    BDBG_OBJECT_ASSERT(handle, BAPE_MuxOutput);
1237    BDBG_OBJECT_ASSERT(input, BAPE_PathConnector);
1238    if ( input != handle->input )
1239    {
1240        BDBG_ERR(("Input %s %s (%#x) is not connected", input->pParent->pName, input->pName, input));
1241        return BERR_TRACE(BERR_INVALID_PARAMETER);
1242    }
1243    errCode = BAPE_PathNode_P_RemoveInput(&handle->node, input);
1244    if ( errCode )
1245    {
1246        return BERR_TRACE(errCode);
1247    }
1248    handle->input = NULL;
1249    return BERR_SUCCESS;
1250}
1251
1252BERR_Code BAPE_MuxOutput_RemoveAllInputs(
1253    BAPE_MuxOutputHandle handle
1254    )
1255{
1256    BDBG_OBJECT_ASSERT(handle, BAPE_MuxOutput);
1257    if ( handle->input )
1258    {
1259        return BAPE_MuxOutput_RemoveInput(handle, handle->input);
1260    }
1261    return BERR_SUCCESS;
1262}
1263
1264static BERR_Code BAPE_MuxOutput_P_ConnectorSupported(struct BAPE_PathNode *pNode, BAPE_PathConnector *pConnector)
1265{
1266    BDBG_OBJECT_ASSERT(pNode, BAPE_PathNode);
1267    BDBG_OBJECT_ASSERT(pConnector, BAPE_PathConnector);
1268    if ( pConnector->dataSource == BAPE_DataSource_eDspBuffer &&
1269         pConnector->compressed )
1270    {
1271        return BERR_SUCCESS;
1272    }
1273    else
1274    {
1275        BDBG_ERR(("Only compressed DSP input is supported"));
1276        return BERR_TRACE(BERR_INVALID_PARAMETER);
1277    }
1278}
1279
1280static BERR_Code BAPE_MuxOutput_P_AllocatePathFromInput(struct BAPE_PathNode *pNode, struct BAPE_PathConnection *pConnection)
1281{
1282    BERR_Code errCode;
1283    BAPE_MuxOutputHandle handle;
1284    BDBG_OBJECT_ASSERT(pNode, BAPE_PathNode);
1285    BDBG_OBJECT_ASSERT(pConnection, BAPE_PathConnection);
1286    BDBG_ASSERT(NULL != pConnection->pSource->pTaskCreateSettings);
1287    handle = pNode->pHandle;
1288    BDBG_OBJECT_ASSERT(handle, BAPE_MuxOutput);
1289    /* Add stage to CIT and propagate task settings */
1290    errCode = BAPE_DSP_P_AddProcessingStage(pConnection->pSource->pTaskCreateSettings, pConnection->pSource->branchId, pConnection->pSource->stageId, 
1291                                            BDSP_AF_P_DistinctOpType_eCdb, 
1292                                            BDSP_AudioProcessing_eGenCdbItb,
1293                                            false,
1294                                            &handle->branchId, &handle->stageId);
1295    if ( errCode )
1296    {
1297        return BERR_TRACE(errCode);
1298    }
1299
1300    /* Add RAVE output buffer */
1301    errCode = BAPE_DSP_P_AddRaveOutputBuffer(pConnection->pSource->pTaskCreateSettings->pBranchInfo[handle->branchId],
1302                                             handle->stageId, handle->createSettings.pContextMap);
1303    if ( errCode )
1304    {
1305        return BERR_TRACE(errCode);
1306    }
1307
1308    /* If configuring for NRT, setup STC increment linkage */
1309    if ( handle->startSettings.pNonRealTimeIncrement )
1310    {
1311        pConnection->pSource->pTaskCreateSettings->stcIncrementConfig.enableStcTrigger = true;
1312        pConnection->pSource->pTaskCreateSettings->stcIncrementConfig.stcIncHiAddr = handle->startSettings.pNonRealTimeIncrement->StcIncHi + BCHP_PHYSICAL_OFFSET;
1313        pConnection->pSource->pTaskCreateSettings->stcIncrementConfig.stcIncLowAddr = handle->startSettings.pNonRealTimeIncrement->StcIncLo + BCHP_PHYSICAL_OFFSET;
1314        pConnection->pSource->pTaskCreateSettings->stcIncrementConfig.stcIncTrigAddr = handle->startSettings.pNonRealTimeIncrement->IncTrigger + BCHP_PHYSICAL_OFFSET;
1315        #ifdef BCHP_XPT_PCROFFSET_STC0_INC_TRIG
1316        pConnection->pSource->pTaskCreateSettings->stcIncrementConfig.triggerBit = BCHP_XPT_PCROFFSET_STC0_INC_TRIG_SOFT_INC_TRIG_SHIFT;
1317        #endif
1318        /* TODO: This shouldn't be mutually exclusive with Master/Slave */
1319        pConnection->pSource->pTaskCreateSettings->realtimeMode = BDSP_TaskRealtimeMode_eNonRealTime;
1320    }
1321
1322    return BERR_SUCCESS;
1323}
1324
1325static BERR_Code BAPE_MuxOutput_P_ConfigPathFromInput(struct BAPE_PathNode *pNode, struct BAPE_PathConnection *pConnection)
1326{
1327    BERR_Code errCode;
1328    BAPE_MuxOutputHandle handle;
1329    BDBG_OBJECT_ASSERT(pNode, BAPE_PathNode);
1330    BDBG_OBJECT_ASSERT(pConnection, BAPE_PathConnection);
1331    BDBG_ASSERT(NULL != pConnection->pSource->task);
1332    /* Need to apply settings to DSP and propagate task handle */
1333    handle = pNode->pHandle;
1334    BDBG_OBJECT_ASSERT(handle, BAPE_MuxOutput);
1335    handle->task = pConnection->pSource->task;
1336    errCode = BAPE_MuxOutput_P_ApplyDspSettings(handle);
1337    if ( errCode )
1338    {
1339        return BERR_TRACE(errCode);
1340    }
1341    return BERR_SUCCESS;
1342}
1343
1344static void BAPE_MuxOutput_P_StopPathFromInput(struct BAPE_PathNode *pNode, struct BAPE_PathConnection *pConnection)
1345{
1346    /* Invalidate task handle */
1347    BAPE_MuxOutputHandle handle;
1348    BDBG_OBJECT_ASSERT(pNode, BAPE_PathNode);
1349    BSTD_UNUSED(pConnection);
1350    handle = pNode->pHandle;
1351    BDBG_OBJECT_ASSERT(handle, BAPE_MuxOutput);
1352    handle->task = NULL;
1353    BDBG_MSG(("Requesting EOS on Task Stop"));
1354    handle->sendEos = true;
1355}
1356
1357BERR_Code BAPE_MuxOutput_GetDelayStatus(
1358    BAPE_MuxOutputHandle handle,
1359    BAVC_AudioCompressionStd codec,
1360    BAPE_MuxOutputDelayStatus *pStatus    /* [out] */
1361    )
1362{
1363    unsigned frameTime;
1364    BDBG_OBJECT_ASSERT(handle, BAPE_MuxOutput);
1365    BDBG_ASSERT(NULL != pStatus);
1366    pStatus->endToEndDelay = 0;
1367    if ( NULL == handle->input )
1368    {
1369        BDBG_ERR(("Not connected to any input.  Can not determine delay status."));
1370        return BERR_TRACE(BERR_INVALID_PARAMETER);
1371    }
1372    /* Determine codec delay */
1373    switch (codec)
1374    {
1375    /* End to End delay (Time difference between when First PCM sample comes to Encode buffer
1376       To the time when reference decoder can start decoding) is 2*FrameTime. 32kHz is chosen to
1377       take care of worst case delay */
1378    case BAVC_AudioCompressionStd_eMpegL1:
1379    case BAVC_AudioCompressionStd_eMpegL2:
1380    case BAVC_AudioCompressionStd_eMpegL3:
1381        frameTime = 1152/32;
1382        break;
1383    case BAVC_AudioCompressionStd_eAc3:
1384    case BAVC_AudioCompressionStd_eAc3Plus:
1385    case BAVC_AudioCompressionStd_eAc3Lossless:
1386        frameTime = 1536/32;
1387        break;
1388    case BAVC_AudioCompressionStd_eAacAdts:
1389    case BAVC_AudioCompressionStd_eAacLoas:
1390    case BAVC_AudioCompressionStd_eAacPlusAdts:
1391    case BAVC_AudioCompressionStd_eAacPlusLoas:
1392    default:
1393        frameTime = 2048/32;
1394        break;
1395    }
1396    if ( handle->input->pParent->type == BAPE_PathNodeType_eDecoder )
1397    {
1398        /* Decoder input */
1399        pStatus->endToEndDelay = frameTime;
1400    }
1401    else
1402    {
1403        /* Encoder requires an extra frame of buffering */
1404        pStatus->endToEndDelay = frameTime * 2;
1405    }
1406
1407    return BERR_SUCCESS;
1408}
1409
1410static void BAPE_MuxOutput_P_RemoveInputCallback(struct BAPE_PathNode *pNode, BAPE_PathConnector *pConnector)
1411{
1412    (void)BAPE_MuxOutput_RemoveInput(pNode->pHandle, pConnector);
1413}
1414
1415#define BAPE_ITB_ENTRY_TYPE_BASE_ADDRESS (0x20)
1416#define BAPE_ITB_ENTRY_TYPE_PTS_DTS      (0x21)
1417#define BAPE_ITB_ENTRY_TYPE_BIT_RATE     (0x60)
1418#define BAPE_ITB_ENTRY_TYPE_MUX_ESCR     (0x61)
1419#define BAPE_ITB_ENTRY_TYPE_ALGO_INFO    (0x62)
1420#define BAPE_ITB_ENTRY_TYPE_ASC          (0x63)
1421   
1422/* Get type of next entry */
1423static uint8_t BAPE_MuxOutput_P_GetNextItbEntryType(BAPE_MuxOutputHandle handle, uint32_t readOffset)
1424{
1425    void *pSource;
1426    BAPE_MuxOutputItbEntry *pEntry;
1427
1428    BMEM_Heap_ConvertOffsetToAddress(handle->node.deviceHandle->memHandle, readOffset, &pSource);
1429   
1430    pEntry = pSource;
1431    return pEntry->fields.base_address.entry_type;
1432}
1433
1434/* Read and handle wraparound */
1435static size_t BAPE_MuxOutput_P_ReadItb(BAPE_MuxOutputHandle handle, uint32_t baseOffset, uint32_t readOffset, uint32_t endOffset, uint32_t depth, uint8_t *pDest, size_t length)
1436{
1437    void *pSource;
1438
1439    if ( length <= depth )
1440    {
1441        BMEM_Heap_ConvertOffsetToAddress(handle->node.deviceHandle->memHandle, readOffset, &pSource);
1442        if ( readOffset + length > endOffset )
1443        {
1444            size_t preWrapAmount = endOffset-readOffset;
1445            size_t wrapAmount = length - preWrapAmount;
1446            /* Wraparound */
1447            BKNI_Memcpy(pDest, pSource, preWrapAmount);
1448            BMEM_Heap_ConvertOffsetToAddress(handle->node.deviceHandle->memHandle, baseOffset, &pSource);
1449            BKNI_Memcpy(pDest+preWrapAmount, pSource, wrapAmount);
1450        }
1451        else
1452        {
1453            /* No Wrap */
1454            BKNI_Memcpy(pDest, pSource, length);
1455        }
1456       
1457        return length;
1458    }
1459    else
1460    {
1461        return 0;
1462    }
1463}
1464
1465static void BAPE_MuxOutput_P_ParseItb(BAPE_MuxOutputHandle handle, BAPE_MuxOutputItbEntry **pCurrent, BAPE_MuxOutputItbEntry **pNext, BAVC_AudioMetadataDescriptor *pMetadataDescriptor)   
1466{
1467    BREG_Handle regHandle;
1468    uint32_t uiITBBaseOffset;
1469    uint32_t uiITBEndOffset;
1470    uint32_t uiITBValidOffset;
1471    uint32_t uiITBReadOffset;
1472    uint32_t uiITBDepth;
1473    uint32_t uiShadowReadOffset;
1474    uint32_t uiNextEntryOffset;
1475    size_t uiAmountRead;
1476    uint8_t entryType;
1477    BAPE_OutputDescriptorInfo *psOutputDescDetails;
1478    BAPE_MuxOutputItbEntry *pITBEntry, *pITBEntryNext;
1479
1480    regHandle = handle->node.deviceHandle->regHandle;
1481    psOutputDescDetails = &handle->descriptorInfo;
1482
1483    /* Invalidate pointers */
1484    *pCurrent = NULL;
1485    *pNext = NULL;
1486
1487    /* Setup Metadata */
1488    BKNI_Memset(pMetadataDescriptor, 0, sizeof(*pMetadataDescriptor));
1489
1490    /* Read ITB Addresses */
1491    uiITBBaseOffset = BREG_Read32(regHandle, handle->createSettings.pContextMap->ITB_Base);
1492    uiITBEndOffset = BREG_Read32(regHandle, handle->createSettings.pContextMap->ITB_End);
1493    uiITBValidOffset= BREG_Read32(regHandle, handle->createSettings.pContextMap->ITB_Valid);
1494    uiITBReadOffset= BREG_Read32(regHandle, handle->createSettings.pContextMap->ITB_Read);
1495
1496    if ( uiITBEndOffset != 0 )
1497    {
1498        uiITBEndOffset += 1; /* end is inclusive */
1499    }
1500
1501    BDBG_MSG(("ITB Base/End/Shadow Read/Valid = %08x/%08x/%08x (%08x)/%08x",\
1502              uiITBBaseOffset,
1503              uiITBEndOffset,
1504              psOutputDescDetails->uiITBBufferShadowReadOffset,
1505              uiITBReadOffset,
1506              uiITBValidOffset
1507             ));
1508
1509
1510    uiShadowReadOffset = psOutputDescDetails->uiITBBufferShadowReadOffset;
1511    for ( ;; )
1512    {
1513        pITBEntry = NULL;
1514        pITBEntryNext = NULL;
1515
1516        if ( uiITBValidOffset >= uiShadowReadOffset )
1517        {
1518            uiITBDepth = uiITBValidOffset - \
1519                         uiShadowReadOffset;
1520        }
1521        else
1522        {
1523            uiITBDepth = uiITBEndOffset - uiShadowReadOffset;
1524            uiITBDepth += uiITBValidOffset - uiITBBaseOffset;
1525        }
1526
1527        BDBG_MSG(("ITB Depth: %d bytes (Valid: %08x, Shadow Read: %08x)",
1528                  uiITBDepth,
1529                  uiITBValidOffset,
1530                  uiShadowReadOffset
1531                 ));
1532
1533        /* Don't attempt to read the next entry if it's invaild */
1534        if ( uiITBDepth < 16 )
1535        {
1536            BDBG_MSG(("No ITB entries available"));
1537            return;
1538        }
1539
1540        /* Check for odd ITB entries and drop them */
1541        entryType = BAPE_MuxOutput_P_GetNextItbEntryType(handle, uiShadowReadOffset);
1542        if ( entryType != BAPE_ITB_ENTRY_TYPE_BASE_ADDRESS )
1543        {
1544            /* this should never happen. We should be in sync looking for this entry drops should happen looking for the next one */
1545            BDBG_WRN(("Dropping ITB Entry type 0x%02x looking for first", entryType));
1546            uiShadowReadOffset += 16;
1547            if ( uiShadowReadOffset >= uiITBEndOffset )
1548            {
1549                uiShadowReadOffset -= (uiITBEndOffset-uiITBBaseOffset);
1550            }
1551            continue;
1552        }
1553
1554        uiAmountRead = BAPE_MuxOutput_P_ReadItb(handle, uiITBBaseOffset, uiShadowReadOffset, uiITBEndOffset, uiITBDepth, 
1555                                                (uint8_t *)&psOutputDescDetails->itb.current, sizeof(BAPE_MuxOutputItbEntry));
1556        if ( 0 == uiAmountRead )
1557        {
1558            /* We ran out of ITB entries */
1559            BDBG_MSG(("No more ITB Entries"));
1560            psOutputDescDetails->uiITBBufferShadowReadOffset = uiShadowReadOffset;
1561            return;
1562        }
1563   
1564        uiITBDepth -= uiAmountRead;
1565        pITBEntry = &psOutputDescDetails->itb.current;
1566
1567        /* Check other fields for sanity */           
1568        BDBG_ASSERT(pITBEntry->fields.pts_dts.entry_type == BAPE_ITB_ENTRY_TYPE_PTS_DTS);
1569        BDBG_ASSERT(pITBEntry->fields.bit_rate.entry_type == BAPE_ITB_ENTRY_TYPE_BIT_RATE);
1570        BDBG_ASSERT(pITBEntry->fields.escr_metadata.entry_type == BAPE_ITB_ENTRY_TYPE_MUX_ESCR);
1571   
1572        BDBG_MSG(("*** ITB Dump (entry size = %d bytes)***", sizeof(BAPE_MuxOutputItbEntry)));
1573        BDBG_MSG(("\n error = %1x\n cdb_address = %08x\n dts_valid = %1x\n pts[32] = %1x\n \
1574            \n dts[32] = %1x\n pts[31:0] = %08x\n stc[31:0] = %08x\n ticks_per_bit = %04x\n \
1575            \n shr = %4d\n samplerate = %08x\n ui32ESCR = %08x\n ui32OriginalPTS = %8x\n",
1576                  pITBEntry->fields.base_address.error,
1577                  pITBEntry->fields.base_address.ui32CDB_Address,
1578                  pITBEntry->fields.pts_dts.dts_valid,
1579                  pITBEntry->fields.pts_dts.pts_32,
1580                  pITBEntry->fields.pts_dts.dts_32,
1581                  pITBEntry->fields.pts_dts.ui32PTS,
1582                  pITBEntry->fields.pts_dts.ui32STCSnapshotLower,
1583                  pITBEntry->fields.bit_rate.ticks_per_bit,
1584                  (int16_t) pITBEntry->fields.bit_rate.shr,
1585                  pITBEntry->fields.bit_rate.ui32Samplerate,
1586                  pITBEntry->fields.escr_metadata.ui32ESCR,
1587                  pITBEntry->fields.escr_metadata.ui32OriginalPTS
1588                 ));       
1589   
1590        uiNextEntryOffset = uiShadowReadOffset + sizeof(BAPE_MuxOutputItbEntry);
1591        if ( uiNextEntryOffset >= uiITBEndOffset )
1592        {
1593            uiNextEntryOffset -= (uiITBEndOffset-uiITBBaseOffset);
1594        }
1595
1596        pMetadataDescriptor->uiMetadataFlags |= BAVC_AUDIOMETADATADESCRIPTOR_FLAGS_TIMING_VALID;
1597        pMetadataDescriptor->stTiming.uiSTCSnapshot = pITBEntry->fields.pts_dts.ui32STCSnapshotUpper;
1598        pMetadataDescriptor->stTiming.uiSTCSnapshot <<= 32;
1599        pMetadataDescriptor->stTiming.uiSTCSnapshot |= pITBEntry->fields.pts_dts.ui32STCSnapshotLower;
1600
1601        while ( uiITBDepth >= sizeof(BAPE_MuxOutputItbEntry) && NULL == pITBEntryNext )
1602        {
1603            /* Check for odd ITB entries and drop them */
1604            entryType = BAPE_MuxOutput_P_GetNextItbEntryType(handle, uiNextEntryOffset);
1605            if ( entryType != BAPE_ITB_ENTRY_TYPE_BASE_ADDRESS )
1606            {
1607                switch ( entryType )
1608                {
1609                case BAPE_ITB_ENTRY_TYPE_ASC:
1610                    /* Parse WMA Algo-specific info */
1611                    if ( handle->input->codec == BAVC_AudioCompressionStd_eWmaStd )
1612                    {
1613                        BAPE_MuxOutputWmaSpecificItbEntry wmaEntry;
1614                        uiAmountRead = BAPE_MuxOutput_P_ReadItb(handle, uiITBBaseOffset, uiNextEntryOffset, uiITBEndOffset, uiITBDepth, 
1615                                                                (uint8_t *)&wmaEntry, sizeof(BAPE_MuxOutputWmaSpecificItbEntry));
1616                        if ( uiAmountRead != sizeof(BAPE_MuxOutputWmaSpecificItbEntry) )
1617                        {
1618                            BDBG_MSG(("WMA entry unavailable"));
1619                            return;
1620                        }
1621                        pMetadataDescriptor->uProtocolData.stWmaStd.uiSamplesPerBlock = wmaEntry.ui32SamplesPerFrame;
1622                        pMetadataDescriptor->uProtocolData.stWmaStd.uiEncodeOptions = wmaEntry.ui32EncodeOption;
1623                        pMetadataDescriptor->uProtocolData.stWmaStd.uiSuperBlockAlign = wmaEntry.ui32SuperBlockAlign;
1624                        pMetadataDescriptor->uProtocolData.stWmaStd.uiBlockAlign = wmaEntry.ui32BlockAlign;
1625                        pMetadataDescriptor->uiMetadataFlags |= BAVC_AUDIOMETADATADESCRIPTOR_FLAGS_PROTOCOL_DATA_VALID;
1626                        BDBG_MSG(("WMA Protocol Data - Samples Per Block %u SuperBlockAlign %u Options %#x", 
1627                                  wmaEntry.ui32SamplesPerFrame, wmaEntry.ui32SuperBlockAlign, wmaEntry.ui32EncodeOption));
1628                    }
1629                    /* TODO: Parse AAC */
1630                    break;
1631                case BAPE_ITB_ENTRY_TYPE_ALGO_INFO:
1632                    {
1633                        BAPE_MuxOutputAlgoInfoItbEntry algoInfo;
1634                        uiAmountRead = BAPE_MuxOutput_P_ReadItb(handle, uiITBBaseOffset, uiNextEntryOffset, uiITBEndOffset, uiITBDepth, 
1635                                                                (uint8_t *)&algoInfo, sizeof(BAPE_MuxOutputAlgoInfoItbEntry));
1636                        if ( uiAmountRead != sizeof(BAPE_MuxOutputAlgoInfoItbEntry) )
1637                        {
1638                            BDBG_MSG(("ALGO_INFO entry unavailable"));
1639                            return;
1640                        }
1641                        pMetadataDescriptor->uiMetadataFlags |= BAVC_AUDIOMETADATADESCRIPTOR_FLAGS_BITRATE_VALID;
1642                        pMetadataDescriptor->stBitrate.uiMax = algoInfo.ui32MaxBitRate;
1643                    }
1644                    break;
1645                default:
1646                    BDBG_WRN(("Dropping ITB Entry type 0x%02x looking for next", entryType));
1647                    #if 0
1648                    BDBG_WRN(("uiNextEntryOffset 0x%08x base 0x%08x end 0x%08x shadow 0x%08x valid 0x%08x",uiNextEntryOffset,uiITBBaseOffset,uiITBEndOffset,uiShadowReadOffset,uiITBValidOffset));
1649                    #endif
1650                    break;
1651                }
1652                uiNextEntryOffset += 16;
1653                if ( uiNextEntryOffset >= uiITBEndOffset )
1654                {
1655                    uiNextEntryOffset -= (uiITBEndOffset-uiITBBaseOffset);
1656                }
1657                uiITBDepth -= 16;
1658                continue;
1659            }
1660           
1661            /* Found a base address entry.  Read the next entry. */
1662            uiAmountRead = BAPE_MuxOutput_P_ReadItb(handle, uiITBBaseOffset, uiNextEntryOffset, uiITBEndOffset, uiITBDepth, 
1663                                                    (uint8_t *)&psOutputDescDetails->itb.next, sizeof(BAPE_MuxOutputItbEntry));
1664            if ( 0 == uiAmountRead )
1665            {
1666                /* We ran out of ITB entries */
1667                BDBG_MSG(("Next ITB entry unavailable"));
1668                return;
1669            }
1670
1671            uiITBDepth -= uiAmountRead;
1672            pITBEntryNext = &psOutputDescDetails->itb.next;
1673        }
1674
1675        /* Figure out how much CDB data we have for the current Frame */
1676        if ( NULL != pITBEntryNext )
1677        {   
1678            /* Goto next frame's ITB Entry */
1679            if ( pITBEntryNext->fields.base_address.ui32CDB_Address == 
1680                 psOutputDescDetails->uiCDBBufferShadowReadOffset )
1681            {
1682                /* We have a next entry, and we've finished with the
1683                 * current entry, so move to the next entry
1684                 */               
1685                uiShadowReadOffset = uiNextEntryOffset;
1686                psOutputDescDetails->uiITBBufferShadowReadOffset = uiNextEntryOffset;
1687                BDBG_MSG(("Goto Next Entry"));
1688                continue;
1689            }
1690   
1691            *pCurrent = pITBEntry;
1692            *pNext = pITBEntryNext;
1693            return;
1694        }
1695        else
1696        {
1697            /* We ran out of ITB entries */
1698            BDBG_MSG(("Next ITB entry unavailable"));
1699            return;
1700        }
1701    }
1702}
1703
1704
1705/**
1706Advance both bit and index by one through the byte array
1707**/
1708#define BADTS_ADVANCE(abit, aindex, asize) \
1709        do {if (abit) {(abit)--;} else {(abit)=7;if(++(aindex)>=asize) {goto err_eof;}} } while (0)
1710
1711#define BADTS_GET_BITS(stream, val, len, bit, index, size) \
1712        do { unsigned i_tmp; (val)=0; for ( i_tmp=0; i_tmp < (len); i_tmp++) { (val) <<= 1; (val) |= ((((uint32_t)stream[(index)])>>(bit))&0x1); BADTS_ADVANCE(bit, index, size);} } while (0)
1713
1714#define BADTS_SET_BITS(stream, val, len, bit, index, size) \
1715        do { unsigned i_tmp; for ( i_tmp=(len); i_tmp > 0; i_tmp-- ) { (stream[(index)] |= ((((val)>>(i_tmp-1))&0x1)<<(bit))); BADTS_ADVANCE(bit, index, size); } } while (0)
1716
1717static BERR_Code BAPE_MuxOutput_P_ParseAdtsMetadata(
1718    BAPE_MuxOutputHandle handle, 
1719    BAVC_AudioBufferDescriptor *pFrameDescriptor, 
1720    BAVC_AudioMetadataDescriptor *pMetadataDescriptor
1721    )
1722{
1723    /* CDB Data is assumed to be a bytestream */
1724    unsigned bit=7;
1725    unsigned index=0;
1726    unsigned size=pFrameDescriptor->stCommon.uiLength;
1727    uint32_t value;
1728    uint32_t adtsId;
1729    uint32_t adtsLayer;
1730    uint32_t adtsObject;
1731    uint32_t adtsRateIndex;
1732    uint32_t adtsChanCfg;
1733    uint8_t *pBytestream = (uint8_t *)handle->pCdbBaseCached + pFrameDescriptor->stCommon.uiOffset;
1734   
1735    BADTS_GET_BITS(pBytestream, value, 12, bit, index, size);
1736
1737    /* Check syncword */
1738    if ( value != 0xfff )
1739    {
1740        BDBG_MSG(("Bad ADTS Syncword - expected 0xfff got 0x%x [offset=%u]", value, pFrameDescriptor->stCommon.uiOffset));
1741        goto err_parse;
1742    }
1743    /* Get ID */
1744    BADTS_GET_BITS(pBytestream, adtsId, 1, bit, index, size);
1745    BDBG_MSG(("ADTS ID: %u", adtsId));
1746    /* Get Layer */
1747    BADTS_GET_BITS(pBytestream, adtsLayer, 2, bit, index, size);
1748    BDBG_MSG(("ADTS Layer: %u", adtsLayer));
1749    /* Skip Protection */
1750    BADTS_ADVANCE(bit, index, size);
1751    /* Get Object Type */
1752    BADTS_GET_BITS(pBytestream, adtsObject, 2, bit, index, size);
1753    BDBG_MSG(("ADTS ObjectType: %u", adtsObject));
1754    /* Get Sample Rate Index */
1755    BADTS_GET_BITS(pBytestream, adtsRateIndex, 4, bit, index, size);
1756    BDBG_MSG(("ADTS SR Index: %u", adtsRateIndex));
1757    /* Skip Private Bit */
1758    BADTS_ADVANCE(bit, index, size);
1759    /* Get Channel Config */
1760    BADTS_GET_BITS(pBytestream, adtsChanCfg, 3, bit, index, size);
1761    BDBG_MSG(("ADTS Channel Config: %u", adtsChanCfg));
1762
1763    /* That's enough to get us what we need.  Convert Object Type to value for ASConfig. */
1764    adtsObject += 1;
1765
1766    /* Zero out Target Bytestream */
1767    bit=7;
1768    index=0;
1769    pBytestream = pMetadataDescriptor->uProtocolData.stAac.auiASC;
1770    size = BAVC_AUDIO_SPECIFIC_CONFIG_MAX_LENGTH;
1771    BKNI_Memset(pBytestream, 0, size);
1772    /* Write out payload */
1773    BADTS_SET_BITS(pBytestream, adtsObject, 5, bit, index, size);   /* audioObjectType:5 */
1774    BADTS_SET_BITS(pBytestream, adtsRateIndex, 4, bit, index, size);   /* samplingFrequency:4 */
1775    BADTS_SET_BITS(pBytestream, adtsChanCfg, 4, bit, index, size);  /* channelConfiguration:4 */
1776    /* TODO: SBR? Doesn't seem supported in ADTS (ADTS Object Type is 2 bits, max val 3 + 1 = 4 and SBR is 5) */
1777    /* Begin GASpecificConfig */
1778    BADTS_ADVANCE(bit, index, size);    /* frameLenthFlag:1 */
1779    BADTS_ADVANCE(bit, index, size);    /* dependsOnCoreCoder:1 */
1780    BADTS_ADVANCE(bit, index, size);    /* extensionFlag:1 */
1781    if ( adtsChanCfg == 0 )
1782    {
1783        /* Program Config element is required.  We don't support this. */
1784        BDBG_WRN(("PCE Not supported for ADTS."));
1785        goto err_parse;
1786    }
1787    /* Audio Object Types 6 and 20 are not supported, no layerNr. */
1788    /* No extension flag, so no other data */
1789    pMetadataDescriptor->uProtocolData.stAac.uiASCLengthBits = (8*index) + (7-bit);
1790    pMetadataDescriptor->uProtocolData.stAac.uiASCLengthBytes = (bit==7)?index:index+1;
1791#if 0
1792    {
1793        unsigned i;
1794        for ( i = 0; i < pMetadataDescriptor->uProtocolData.stAac.uiASCLengthBytes; i++ )
1795        {
1796            BDBG_WRN(("ASC[%u] = 0x%02x", i, pMetadataDescriptor->uProtocolData.stAac.auiASC[i]));
1797        }
1798    }
1799#endif
1800    return BERR_SUCCESS;
1801err_eof:
1802    BDBG_WRN(("ADTS EOF"));
1803err_parse:
1804    return BERR_INVALID_PARAMETER;       
1805}
1806
1807/**
1808Advance both bit and index by one through the byte array
1809**/
1810#define BADTS_ADVANCE_WRAP(astream1, astream2, abit, aindex, asize, asize2, awrap) \
1811        do {if (abit) {(abit)--;} else {(abit)=7;if(++(aindex)>=asize) {if ( (asize2) > 0 && ((astream2) != NULL) ) { (asize)=(asize2);(astream1)=(astream2);(asize2)=0;(astream2)=NULL; (aindex)=0; (awrap)=true;} else { goto err_eof;}}} } while (0)
1812
1813#define BADTS_SKIP_BITS_WRAP(stream1, stream2, len, bit, index, size, size2, wrap) \
1814        do { unsigned i_tmp; for ( i_tmp=0; i_tmp < (len); i_tmp++) { BADTS_ADVANCE_WRAP(stream1, stream2, bit, index, size, size2, wrap);} } while (0)
1815
1816#define BADTS_GET_BITS_WRAP(stream1, stream2, val, len, bit, index, size, size2, wrap) \
1817        do { unsigned i_tmp; (val)=0; for ( i_tmp=0; i_tmp < (len); i_tmp++) { (val) <<= 1; (val) |= ((((uint32_t)stream1[(index)])>>(bit))&0x1); BADTS_ADVANCE_WRAP(stream1, stream2, bit, index, size, size2, wrap);} } while (0)
1818
1819#define BADTS_HANDLE_HEADER_WRAP() \
1820do {\
1821if ( wrapped )\
1822{\
1823    /* Wrapped in header, no actual data */\
1824    handle->descriptorInfo.adtsSegmentOffset[0] = segmentOffset;\
1825    handle->descriptorInfo.adtsSegmentLength[0] = segmentLength;\
1826    handle->descriptorInfo.adtsSegmentRawOffset[0] = segmentOffset;\
1827    handle->descriptorInfo.adtsSegmentRawLength[0] = 0;\
1828    segmentLength = s1;\
1829    segmentOffset = (pBuf1-pBase);\
1830    segment=1;\
1831    wrapped = false;\
1832}} while (0)
1833
1834void BAPE_MuxOutput_P_ParseAdtsSegments( 
1835    BAPE_MuxOutputHandle handle, 
1836    const uint8_t *pBuffer,
1837    size_t bufferLength,
1838    const uint8_t *pWrapBuffer,
1839    size_t wrapBufferLength
1840    )
1841{
1842    const uint8_t *pBase = handle->pCdbBaseCached;
1843    bool wrapped=false;
1844    bool protection;
1845    size_t s1=bufferLength,s2=wrapBufferLength;
1846    const uint8_t *pBuf1=pBuffer, *pBuf2=pWrapBuffer;
1847    unsigned bit=7;
1848    unsigned index=0;
1849    unsigned frameLength, numBlocks;
1850    unsigned i;
1851    unsigned segment, blockLength;
1852    unsigned segmentOffset, segmentLength;
1853    unsigned rawOffset, rawLength;
1854    uint32_t val;
1855    /* Initialize default segment info */
1856    handle->descriptorInfo.adtsSegment = 0;
1857    handle->descriptorInfo.adtsNumSegments = 0;
1858    segment = 0;
1859    segmentOffset = (pBuf1 - pBase);    /* Segment starts at beginning of first buffer */
1860    segmentLength = s1;                 /* Segment length is until wraparound by default */
1861    /* Parse header */
1862    /* adts_fixed_header */
1863    BADTS_GET_BITS_WRAP(pBuf1, pBuf2, val, 12, bit, index, s1, s2, wrapped);    /* syncword:12 */
1864    BADTS_HANDLE_HEADER_WRAP();
1865    if ( val != 0xfff )
1866    {
1867        BDBG_MSG(("ADTS syncword mismatch expected 0xfff got 0x%03x", val));
1868        goto err_parse;
1869    }
1870    BADTS_ADVANCE_WRAP(pBuf1, pBuf2, bit, index, s1, s2, wrapped);              /* ID:1 */
1871    BADTS_HANDLE_HEADER_WRAP();
1872    BADTS_ADVANCE_WRAP(pBuf1, pBuf2, bit, index, s1, s2, wrapped);              /* layer:2 */
1873    BADTS_HANDLE_HEADER_WRAP();
1874    BADTS_ADVANCE_WRAP(pBuf1, pBuf2, bit, index, s1, s2, wrapped);             
1875    BADTS_HANDLE_HEADER_WRAP();
1876    BADTS_GET_BITS_WRAP(pBuf1, pBuf2, val, 1, bit, index, s1, s2, wrapped);     /* protection_absent:1 */
1877    BADTS_HANDLE_HEADER_WRAP();
1878    protection = (val)?false:true;  /* Bit indicates absence of protection */
1879    BADTS_SKIP_BITS_WRAP(pBuf1, pBuf2, 2, bit, index, s1, s2, wrapped);         /* profile_ObjectType:2 */
1880    BADTS_HANDLE_HEADER_WRAP();
1881    BADTS_SKIP_BITS_WRAP(pBuf1, pBuf2, 4, bit, index, s1, s2, wrapped);         /* sampling_frequency_index:4 */
1882    BADTS_HANDLE_HEADER_WRAP();
1883    BADTS_ADVANCE_WRAP(pBuf1, pBuf2, bit, index, s1, s2, wrapped);              /* private_bit:1 */
1884    BADTS_HANDLE_HEADER_WRAP();
1885    BADTS_SKIP_BITS_WRAP(pBuf1, pBuf2, 3, bit, index, s1, s2, wrapped);         /* channel_configuration:3 */
1886    BADTS_HANDLE_HEADER_WRAP();
1887    BADTS_ADVANCE_WRAP(pBuf1, pBuf2, bit, index, s1, s2, wrapped);              /* original_copy:1 */
1888    BADTS_HANDLE_HEADER_WRAP();
1889    BADTS_ADVANCE_WRAP(pBuf1, pBuf2, bit, index, s1, s2, wrapped);              /* home:1 */
1890    BADTS_HANDLE_HEADER_WRAP();
1891    /* adts_variable_header */
1892    BADTS_ADVANCE_WRAP(pBuf1, pBuf2, bit, index, s1, s2, wrapped);              /* copyright_identification_bit:1 */
1893    BADTS_HANDLE_HEADER_WRAP();
1894    BADTS_ADVANCE_WRAP(pBuf1, pBuf2, bit, index, s1, s2, wrapped);              /* copyright_identification_start:1 */
1895    BADTS_HANDLE_HEADER_WRAP();
1896    BADTS_GET_BITS_WRAP(pBuf1, pBuf2, val, 13, bit, index, s1, s2, wrapped);    /* aac_frame_length:13 */
1897    BADTS_HANDLE_HEADER_WRAP();
1898    frameLength = val;  /* In Bytes */
1899    if ( frameLength != bufferLength + wrapBufferLength ) 
1900    { 
1901        BDBG_MSG(("Frame Length error.  Expected %u got %u", bufferLength+wrapBufferLength, frameLength));
1902        goto err_parse;
1903    }
1904    BADTS_SKIP_BITS_WRAP(pBuf1, pBuf2, 11, bit, index, s1, s2, wrapped);        /* aac_buffer_fullness:11 */
1905    BADTS_HANDLE_HEADER_WRAP();
1906    BADTS_GET_BITS_WRAP(pBuf1, pBuf2, val, 2, bit, index, s1, s2, wrapped);     /* number_of_raw_data_blocks_in_frame:2 */
1907    BADTS_HANDLE_HEADER_WRAP();
1908    numBlocks = val;
1909    BDBG_ASSERT(bit == 7);  /* We should be byte aligned now.  If not something has gone horribly wrong. */
1910    /* Handle protection prior to data if required */
1911    if ( protection )
1912    {
1913        if ( numBlocks > 0 )
1914        {
1915            /* adts_header_error_check */
1916            for ( i = 1; i <= numBlocks; i++ ) 
1917            { 
1918                BADTS_SKIP_BITS_WRAP(pBuf1, pBuf2, 16, bit, index, s1, s2, wrapped);    /* raw_data_block_position(i):16 */
1919                BADTS_HANDLE_HEADER_WRAP();
1920            }
1921        }
1922        BADTS_SKIP_BITS_WRAP(pBuf1, pBuf2, 16, bit, index, s1, s2, wrapped);            /* crc_check:16 */
1923        BADTS_HANDLE_HEADER_WRAP();
1924    }
1925   
1926    numBlocks++;    /* Original numBlocks was inclusive.  That doesn't make sense for dividing. */
1927    if ( segment == 1 )
1928    {
1929        /* We have wrapped in the header */
1930        blockLength = frameLength - index - handle->descriptorInfo.adtsSegmentLength[0];  /* Subtract header bytes pre and post-wrap */
1931    }
1932    else
1933    {
1934        blockLength = frameLength - index;  /* Subtract header bytes */
1935    }
1936    if ( (blockLength % numBlocks) != 0 )
1937    {
1938        BDBG_MSG(("Raw Frame length not a multiple of number of blocks.  Fail."));
1939        goto err_parse;
1940    }
1941    blockLength /= numBlocks;
1942    if ( protection )
1943    {
1944        blockLength -= 2;   /* Remove 2-byte CRC that comes after each access unit */
1945    }
1946
1947    /* First data segment will start here. */   
1948    rawOffset = (pBuf1-pBase)+index;
1949    rawLength = blockLength;
1950
1951    /* Actual first segment starts wherever the header parsing started and contains the header data also */
1952    segmentOffset = pBuf1-pBase;
1953    if ( segment == 1 )
1954    {
1955        /* Wrapped in header */
1956        segmentLength = frameLength-handle->descriptorInfo.adtsSegmentLength[0];
1957    }
1958    else
1959    {
1960        segmentLength = frameLength;
1961    }
1962    BDBG_MSG(("S1 %u Segment Len %u Frame Len %u Raw Len %u nblk %u protection %u index %u", s1, segmentLength, frameLength, rawLength, numBlocks, protection, index));
1963
1964    /* Iterate through number of blocks (it's not inclusive anymore) */
1965    for ( i = 0; i < numBlocks; )
1966    {
1967        /* Find segment boundary */
1968        handle->descriptorInfo.adtsSegmentOffset[segment] = segmentOffset;
1969        handle->descriptorInfo.adtsSegmentRawOffset[segment] = rawOffset;
1970        if ( segmentLength >= s1 )
1971        {
1972            /* Truncate Segment */
1973             handle->descriptorInfo.adtsSegmentLength[segment] = s1;
1974             segmentLength -= s1;
1975             /* Determine if raw payload wrapped (it might wrap in segment CRC region instead) */
1976             if ( rawLength > s1 )
1977             {
1978                 handle->descriptorInfo.adtsSegmentRawLength[segment] = s1-(rawOffset-segmentOffset);
1979                 rawLength -= handle->descriptorInfo.adtsSegmentRawLength[segment];
1980             }
1981             else
1982             {
1983                 handle->descriptorInfo.adtsSegmentRawLength[segment] = rawLength;
1984                 rawLength = 0;
1985             }             
1986             /* Wrap pointers */
1987             s1 = s2;
1988             pBuf1 = pBuf2;
1989             s2 = 0;
1990             pBuf2 = NULL;
1991             /* Start new segment */
1992             segmentOffset = pBuf1 - pBase;
1993             rawOffset = segmentOffset;
1994        }
1995        else
1996        {
1997            /* No Wrap.  Use full segment */
1998            handle->descriptorInfo.adtsSegmentLength[segment] = segmentLength;
1999            handle->descriptorInfo.adtsSegmentOffset[segment] = segmentOffset;
2000            handle->descriptorInfo.adtsSegmentRawOffset[segment] = rawOffset;
2001            handle->descriptorInfo.adtsSegmentRawLength[segment] = rawLength;
2002            s1 -= segmentLength;
2003            pBuf1 += segmentLength;
2004            segmentOffset += segmentLength;
2005            rawOffset = segmentOffset;     /* The next RAW block starts with the next segment */
2006            segmentLength = 0;
2007            rawLength = 0;
2008        }
2009
2010        /* Determine if we need to update lengths */
2011        if ( 0 == segmentLength )
2012        {
2013            rawLength = blockLength;
2014            segmentLength = (protection)?rawLength + 2:rawLength;
2015            i++;    /* We consumed a data block */
2016        }
2017       
2018        segment++;
2019    }
2020    BDBG_ASSERT(segment <= BAPE_MUXOUTPUT_MAX_ADTS_SEGMENTS);
2021    BDBG_MSG(("ADTS Frame has %u segments", segment));
2022    handle->descriptorInfo.adtsNumSegments = segment;
2023#if 1
2024    for ( segment = 0; segment < handle->descriptorInfo.adtsNumSegments; segment++ )
2025    {
2026        BDBG_MSG(("Segment %u length %u", segment, handle->descriptorInfo.adtsSegmentLength[segment]));
2027    }
2028#endif
2029    return; /* Success */
2030err_parse:
2031err_eof:
2032    handle->descriptorInfo.adtsSegment = 0;
2033    handle->descriptorInfo.adtsNumSegments = 1;
2034    handle->descriptorInfo.adtsSegmentOffset[0] = pBuffer - pBase;
2035    handle->descriptorInfo.adtsSegmentLength[0] = bufferLength;
2036    handle->descriptorInfo.adtsSegmentRawOffset[0] = pBuffer - pBase;
2037    handle->descriptorInfo.adtsSegmentRawLength[0] = bufferLength;
2038    if ( pWrapBuffer != NULL )
2039    {
2040        handle->descriptorInfo.adtsNumSegments = 2;
2041        handle->descriptorInfo.adtsSegmentOffset[1] = pWrapBuffer - pBase;
2042        handle->descriptorInfo.adtsSegmentLength[1] = wrapBufferLength;
2043        handle->descriptorInfo.adtsSegmentRawOffset[1] = pWrapBuffer - pBase;
2044        handle->descriptorInfo.adtsSegmentRawLength[1] = wrapBufferLength;
2045    }   
2046}
2047
2048bool BAPE_MuxOutput_P_IsRunning(BAPE_MuxOutputHandle handle)
2049{
2050    BDBG_OBJECT_ASSERT(handle, BAPE_MuxOutput);
2051    return handle->started;
2052}
2053
Note: See TracBrowser for help on using the repository browser.