close Warning: Can't use blame annotator:
No changeset 2 in the repository

source: svn/newcon3bcm2_21bu/magnum/syslib/pvrlib/bpvrlib_play.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: 41.4 KB
RevLine 
1/***************************************************************************
2 *     Copyright (c) 2002-2010, Broadcom Corporation
3 *     All Rights Reserved
4 *     Confidential Property of Broadcom Corporation
5 *
6 *  THIS SOFTWARE MAY ONLY BE USED SUBJECT TO AN EXECUTED SOFTWARE LICENSE
7 *  AGREEMENT  BETWEEN THE USER AND BROADCOM.  YOU HAVE NO RIGHT TO USE OR
8 *  EXPLOIT THIS MATERIAL EXCEPT SUBJECT TO THE TERMS OF SUCH AN AGREEMENT.
9 *
10 * $brcm_Workfile: bpvrlib_play.c $
11 * $brcm_Revision: Hydra_Software_Devel/48 $
12 * $brcm_Date: 10/26/10 1:27p $
13 *
14 * Module Description:
15 *
16 * Revision History:
17 *
18 * $brcm_Log: /magnum/syslib/pvrlib/bpvrlib_play.c $
19 *
20 * Hydra_Software_Devel/48   10/26/10 1:27p vsilyaev
21 * SW7422-84: Upgraded to use  chip agnostic API
22 *
23 * Hydra_Software_Devel/47   3/25/10 2:37p gmullen
24 * SW35230-127:35230 has 5 playback channels
25 *
26 * Hydra_Software_Devel/46   12/4/09 8:08p randyjew
27 * SW7468-6:Add 7468 support
28 *
29 * Hydra_Software_Devel/45   11/19/09 4:30p gmohile
30 * SW7408-1 : Add 7408 support
31 *
32 * Hydra_Software_Devel/44   10/22/09 3:37p baginski
33 * SW7630-47: merge bdvd_v3.0 changes to main Hydra branch
34 *
35 * Hydra_Software_Devel/43   9/28/09 1:10p nitinb
36 * SW7550-29: Adding support for 7550
37 *
38 * Hydra_Software_Devel/42   9/21/09 5:21p jhaberf
39 * SW35230-1: Updated for 35230 support
40 *
41 * Hydra_Software_Devel/41   8/20/09 4:29p mward
42 * PR55545: Support 7125.
43 *
44 * Hydra_Software_Devel/40   8/11/09 12:26p jrubio
45 * PR55882: add 7340 support
46 *
47 * Hydra_Software_Devel/39   8/10/09 6:17p jrubio
48 * PR55232: add 7340/7342 support
49 *
50 * Hydra_Software_Devel/38   1/31/09 12:55a jrubio
51 * PR51629: add 7336
52 *
53 * Hydra_Software_Devel/37   12/7/08 4:36p nickh
54 * PR48963: Add 7420 support
55 *
56 * Hydra_Software_Devel/36   4/8/08 4:03p erickson
57 * PR39453: add 3548 & 3556
58 *
59 * Hydra_Software_Devel/35   12/5/07 10:33a katrep
60 * PR37217: Added support for 7335.
61 *
62 * Hydra_Software_Devel/34   11/1/07 9:40a erickson
63 * PR36570: added 3563
64 *
65 * Hydra_Software_Devel/33   10/31/07 4:45p jrubio
66 * PR35015: adding 7325 support
67 *
68 * Hydra_Software_Devel/32   8/6/07 1:49p katrep
69 * PR27643: 7405 has 5 playback inputs.
70 *
71 * Hydra_Software_Devel/31   7/12/07 9:46a gmullen
72 * PR32952: Added support for 5th playback channel in 7400B0
73 *
74 * Hydra_Software_Devel/30   1/2/07 11:43a erickson
75 * PR26860: fix sloppy logic in BPVRlib_Play_Flush without readding NULL
76 * packet flush for RAVE platforms
77 *
78 * Hydra_Software_Devel/29   12/15/06 9:26a erickson
79 * PR26620: added 7403 support
80 *
81 * Hydra_Software_Devel/28   7/18/06 2:58p mward
82 * PR21945: Add support for 7118 chip 97118 board.
83 *
84 * Hydra_Software_Devel/27   5/9/06 3:03p erickson
85 * PR20631: add 7401 B0 support
86 *
87 * Hydra_Software_Devel/26   4/3/06 6:59p ahulse
88 * PR19676: Add code to copy acros numBytesScatGat, numScatGatDesc,
89 * numMultiDescDone to p_stats structure in BPVRlib_Play_GetStats, so
90 * that counters are kept up-to-date.
91 *
92 * Hydra_Software_Devel/25   3/31/06 2:28p vsilyaev
93 * PR 20308: Refresh hardware status on BPVRlib_Play_GetBufferDepth
94 *
95 * Hydra_Software_Devel/24   2/3/06 11:28a jgarrett
96 * PR 19438: Update PVRLib for 7400
97 *
98 * Hydra_Software_Devel/23   10/14/05 4:33p vsilyaev
99 * PR 17607: Fixes for 7401 build
100 *
101 * Hydra_Software_Devel/22   8/17/05 10:48a marcusk
102 * PR16713: Fixed memory leak.
103 *
104 * Hydra_Software_Devel/21   3/23/05 10:53a dlwin
105 * PR 14517: Resolved compiler warnings.
106 *
107 * Hydra_Software_Devel/20   3/18/05 8:36a dlwin
108 * PR 14240: Added support for 3560.
109 *
110 * Hydra_Software_Devel/19   10/11/04 11:51a erickson
111 * PR12728: use typecast to avoid warning
112 *
113 * Hydra_Software_Devel/18   6/18/04 11:55a erickson
114 * PR11591: waitfordescriptor timeout shouldn't be an error message
115 *
116 * Hydra_Software_Devel/17   6/18/04 11:34a marcusk
117 * PR11591: Updated to support returning if descriptor is available when
118 * calling BPVRlib_Play_AddDataRequest()
119 *
120 * Hydra_Software_Devel/16   6/16/04 5:05p erickson
121 * PR11135: need to destroy BINT callback when closing
122 *
123 * Hydra_Software_Devel/15   6/3/04 6:04p marcusk
124 * PR11347: Added new functions
125 *
126 * Hydra_Software_Devel/14   5/6/04 11:42a erickson
127 * PR10971: GetStats needs to updated hardware state
128 *
129 * Hydra_Software_Devel/13   4/12/04 10:41p vsilyaev
130 * PR 10546: Make silent case with timeout and timeout value set to 0.
131 *
132 * Hydra_Software_Devel/12   4/12/04 10:27p vsilyaev
133 * PR10546: Added BERR_TRACE for TIMEOUT error.
134 *
135 * Hydra_Software_Devel/11   4/12/04 4:33p marcusk
136 * PR10543: Optimized path when timeout is zero (don't call wait for
137 * event)
138 *
139 * Hydra_Software_Devel/10   4/8/04 6:31p marcusk
140 * PR10543: Added feature to support skip size when updating ring buffer
141 * write pointer.
142 *
143 * Hydra_Software_Devel/9   4/7/04 11:33a marcusk
144 * PR10512: reinit the number of free descriptors when starting playback
145 *
146 * Hydra_Software_Devel/8   3/1/04 3:47p marcusk
147 * PR9930: Fixed warnings for VxWorks build.
148 *
149 * Hydra_Software_Devel/7   2/19/04 10:32a vsilyaev
150 * PR 8927: Added function to return events used by playback module
151 *
152 * Hydra_Software_Devel/6   1/21/04 4:43p marcusk
153 * PR8927: Fixed to work with latest version of XPT porting interface.
154 * Validate channel number.
155 *
156 * Hydra_Software_Devel/5   1/13/04 12:06p marcusk
157 * PR8927: Renamed the private functions to be compliant with Magnum
158 * architecture
159 *
160 * Hydra_Software_Devel/4   1/10/04 10:47a marcusk
161 * PR8927: Fixed playback isses.
162 *
163 * Hydra_Software_Devel/3   1/8/04 12:19p marcusk
164 * PR8927: Fixed CreateDesc() function call.
165 *
166 * Hydra_Software_Devel/2   1/7/04 6:12p marcusk
167 * PR8927: Initial magnum version
168 *
169 * Hydra_Software_Devel/1   12/10/03 11:00a marcusk
170 * PR 8927: Starting with 7115 PVR syslibs.
171 *
172 * Irvine_BSEAVSW_Devel/43   8/29/03 2:41p cnovak
173 * Corrected format warnings in debug print statements.
174 *
175 * Irvine_BSEAVSW_Devel/42   5/9/03 11:07a marcusk
176 * Added inital support for 7328.
177 *
178 * Irvine_BSEAVSW_Devel/41   2/20/03 6:14p marcusk
179 * Added pvr_playbackSwitchSyncModes() function.
180 *
181 * Irvine_HDDemo_Devel/40   7/12/02 10:50a marcusk
182 * Added a few functions to override default pause and packet length
183 * settings.
184 *
185 * Irvine_HDDemo_Devel\39   5/17/02 9:47a marcusk
186 * Added "" around BRCM_DBG_MODULE to support new debug routines.
187 *
188 * Irvine_HDDemo_Devel\38   5/10/02 12:25p marcusk
189 * Updated to support 4 playback channels.
190 *
191 * Irvine_HDDemo_Devel\37   4/1/02 6:6p marcusk
192 * Added some additional debug messages.
193 *
194 * Irvine_HDDemo_Devel\36   3/21/02 11:26a marcusk
195 * Added feature to auto-allocate buffer if p_bfr is set to 0 during the
196 * allocate routine.
197 *
198 * \main\Irvine_HDDemo_Devel\35   3/18/02 12:1p marcusk
199 * Adjusted message output levels.
200 *
201 * \main\Irvine_HDDemo_Devel\34   3/13/02 3:7p marcusk
202 * Updated code to properly call TransPvrCreatePlaybackDesc(), and
203 * TransPvrCreateDesc() functions.
204 *
205 * \main\Irvine_HDDemo_Devel\33   3/13/02 1:36p marcusk
206 * Updated to support 7115 (with only two playback channels)
207 *
208 ***************************************************************************/
209
210#include "bstd.h"
211#include "blst_squeue.h"
212#include "bkni.h"
213#include "bkni_multi.h"
214#include "bpvrlib_p_ringmgr.h"
215#include "bpvrlib_play.h"
216#include "bmem.h"
217
218#include "bint.h"
219#define B_HAS_RAVE 1
220
221
222BDBG_MODULE(BPVRlib_Play);
223
224typedef enum
225{
226    BPVRlib_Play_P_BufferModel_eRing,
227    BPVRlib_Play_P_BufferModel_eScatterGather
228} BPVRlib_Play_P_BufferModel;
229
230typedef struct BPVRlib_Play_P_DescEntry
231{
232    BLST_SQ_ENTRY(BPVRlib_Play_P_DescEntry) link;
233    BXPT_PvrDescriptor *p_desc;
234    size_t  skipSize;
235    BPVRlib_Play_P_BufferModel bufferModel;
236} BPVRlib_Play_P_DescEntry;
237
238typedef BLST_SQ_HEAD(BPVRlib_Play_P_DescList, BPVRlib_Play_P_DescEntry) BPVRlib_Play_P_DescList;
239
240typedef struct BPVRlib_Play_P_Handle
241{
242    BXPT_Handle         xptHandle;      /* XPT handle */
243    BXPT_Playback_Handle xptPlayHandle; /* XPT playback handle */
244    BMEM_Handle         memHandle;      /* Mem handle */
245    BINT_Handle         intHandle;      /* Int handle */
246    BINT_CallbackHandle hPlayInt;       /* cb Handle for playback interrupt */
247    volatile bool       isInProgress;   /* Playback is in progress */
248    unsigned            channelNum;     /* Channel number */
249    BPVRlib_P_RingMgr_Handle    rbmgr;  /* Allocated ring buffer manager */
250    uint8_t             *p_bfr;         /* Pointer to ring buffer */
251    bool                bfrAllocated;   /* 0 (buffer pointer passed in), 1 (buffer allocated internally) */
252    size_t          bfrSize;        /* Size of ring buffer */
253    uint8_t             *p_descBfr;     /* Buffer used for descriptor allocation */
254    BPVRlib_Play_P_DescEntry    *p_descEntries; /* Buffer used to store descriptor list entries */
255    uint32_t            numDesc;        /* Num of descriptors used for playback */
256    BKNI_EventHandle    descEvent;      /* Event used to signal when descriptor is added to free list */
257    BKNI_EventHandle    finishedEvent;  /* Event used to signal when the playback has finished */
258    volatile bool       resync;         /* Used to set the resync bit in the transport playback hardware */
259    BPVRlib_Play_P_DescList     freeDescList;   /* List containing all free descriptors */
260    BPVRlib_Play_P_DescList     hwDescList;     /* List containing descriptors that are loading in hardware */
261    BPVRlib_Play_MemCopyCb      pvrMemCopyCb;   /* Callback used to copy data into the ring buffer */
262    uint32_t            totalDescRemoved; /* Total number of descriptors removed from hw list */
263    uint32_t            timeoutValue;   /* Max number of msec to wait for an event to occur */
264    uint32_t            maxDescSize;    /* Maximum number of bytes to add into hardware at one time */
265    BPVRlib_Play_Stats  stats;          /* Statistics structure */
266    unsigned            scatGatBfrsComplete;    /* Tracks the current number of scatter gather buffers that have completed */
267} BPVRlib_Play_P_Handle;
268
269static void BPVRlib_Play_P_isr( void *Parm1, int Parm2 );
270static void BPVRlib_Play_P_UpdateHwDescriptors( BPVRlib_Play_Handle playHandle );
271static BERR_Code BPVRlib_Play_P_WaitForFreeDescriptor( BPVRlib_Play_Handle playHandle, BPVRlib_Play_BlockMode block );
272static bool BPVRlib_Play_P_IsActive( BPVRlib_Play_Handle playHandle );
273static BERR_Code BPVRlib_Play_P_CreateIntCallbacks( BPVRlib_Play_Handle playHandle );
274static BERR_Code BPVRlib_Play_P_EnableInterrupts( BPVRlib_Play_Handle playHandle );
275
276BERR_Code BPVRlib_Play_Open(
277    BPVRlib_Play_Handle *pPlayHandle,   /* [out] context handle */
278    BXPT_Handle xptHandle,              /* XPT handle */
279    BXPT_Playback_Handle xptPlayHandle, /* XPT playback handle */
280    BMEM_Handle memHandle,              /* Mem handle */
281    BINT_Handle intHandle,              /* Int handle */
282    unsigned channelNum,                /* playback channel number */
283    uint8_t *p_bfr,                     /* pointer to buffer that should be used for playback ring buffer, 0 to allocate the buffer internally */
284    size_t bfrSize,                 /* size of playback ring buffer (in bytes) */
285    uint32_t numDesc,                   /* number of descriptors to use  */
286    BPVRlib_Play_MemCopyCb pvrMemCopyCb         /* function pointer for memory copies (optional) */
287    )
288{
289    BERR_Code       err = BERR_SUCCESS;
290    uint32_t        i;
291    BXPT_PvrDescriptor  *p_desc;
292    BPVRlib_Play_Handle playHandle = NULL;
293    BXPT_Capability xptCaps;
294
295    BXPT_GetCapability(xptHandle, &xptCaps );
296
297    if( channelNum >= xptCaps.MaxPlaybacks )
298    {
299        err = BERR_TRACE(BERR_INVALID_PARAMETER);
300        goto done;
301    }
302
303    playHandle = BKNI_Malloc( sizeof(BPVRlib_Play_P_Handle) );
304    if( playHandle == NULL )
305    {
306        err = BERR_TRACE(BERR_OUT_OF_SYSTEM_MEMORY);
307        goto done;
308    }
309
310    BKNI_Memset( playHandle, 0, sizeof(BPVRlib_Play_P_Handle) );
311
312    if( p_bfr == NULL )
313    {
314        p_bfr = BMEM_Alloc( memHandle, bfrSize );
315        if( p_bfr == NULL )
316        {
317            err = BERR_TRACE(BERR_OUT_OF_DEVICE_MEMORY);
318            goto error;
319        }
320        playHandle->bfrAllocated = true;
321    }
322
323    /* Save parameters */
324    playHandle->p_bfr = p_bfr;
325    playHandle->numDesc = numDesc;
326    playHandle->pvrMemCopyCb = pvrMemCopyCb;
327    playHandle->timeoutValue = BKNI_INFINITE;
328    playHandle->maxDescSize = bfrSize / 2;
329    playHandle->xptHandle   = xptHandle;
330    playHandle->intHandle   = intHandle;
331    playHandle->xptPlayHandle = xptPlayHandle;
332    playHandle->memHandle   = memHandle;
333    playHandle->channelNum  = channelNum;
334
335    /* Init our lists */
336    BLST_SQ_INIT( &playHandle->freeDescList );
337    BLST_SQ_INIT( &playHandle->hwDescList );
338
339    /* Descriptors must be 16 byte aligned so allocate an extra 15 bytes */
340    playHandle->p_descBfr = BMEM_AllocAligned( playHandle->memHandle, (sizeof(BXPT_PvrDescriptor)*numDesc), 4 /* 16 byte aligned */, 0 );
341    p_desc = (BXPT_PvrDescriptor *)playHandle->p_descBfr;
342    if( p_desc == NULL )
343    {
344        err = BERR_TRACE(BERR_OUT_OF_DEVICE_MEMORY);
345        goto error;
346    }
347
348    /* Allocate storage for our descriptor entries */
349    playHandle->p_descEntries = BKNI_Malloc( sizeof(BPVRlib_Play_P_DescEntry) * numDesc );
350    if( playHandle->p_descEntries == NULL )
351    {
352        err = BERR_TRACE(BERR_OUT_OF_SYSTEM_MEMORY);
353        goto error;
354    }
355
356    /* Assign a descriptor to each descriptor list entry and add them to the free list */
357    for( i = 0; i < numDesc; i++ )
358    {
359        playHandle->p_descEntries[i].p_desc = &p_desc[i];
360        BLST_SQ_INSERT_HEAD(&playHandle->freeDescList, &playHandle->p_descEntries[i], link);
361        playHandle->stats.numFreeDesc++;
362    }
363
364    err = BPVRlib_P_RingMgr_Open( &playHandle->rbmgr, channelNum, 0, 0, p_bfr, bfrSize );
365    if( err != BERR_SUCCESS )
366    {
367        goto error;
368    }
369
370    err = BKNI_CreateEvent(&playHandle->descEvent);
371    if( err != BERR_SUCCESS )
372    {
373        goto error;
374    }
375    err = BKNI_CreateEvent(&playHandle->finishedEvent);
376    if( err != BERR_SUCCESS )
377    {
378        goto error;
379    }
380    err = BPVRlib_Play_P_CreateIntCallbacks(playHandle);
381    if( err != BERR_SUCCESS )
382    {
383        goto error;
384    }
385
386done:
387    *pPlayHandle = playHandle;
388    return err;
389
390error:
391    BPVRlib_Play_Close( playHandle );
392    return err;
393}
394
395BERR_Code BPVRlib_Play_Close(
396                BPVRlib_Play_Handle playHandle      /* context handle */
397                )
398{
399    if( playHandle->isInProgress )
400    {
401        return BERR_TRACE(BERR_UNKNOWN);
402    }
403
404    if (playHandle->hPlayInt) BINT_DestroyCallback(playHandle->hPlayInt);
405
406    if( playHandle->rbmgr != NULL ) BPVRlib_P_RingMgr_Close( playHandle->rbmgr );
407    if( playHandle->p_descBfr != NULL ) BMEM_Free( playHandle->memHandle, playHandle->p_descBfr );
408    if( playHandle->bfrAllocated == true ) BMEM_Free( playHandle->memHandle, playHandle->p_bfr );
409    if( playHandle->p_descEntries != NULL ) BKNI_Free( playHandle->p_descEntries );
410    if( playHandle->descEvent != NULL ) BKNI_DestroyEvent(playHandle->descEvent);
411    if( playHandle->finishedEvent != NULL ) BKNI_DestroyEvent(playHandle->finishedEvent);
412
413    BKNI_Free( playHandle );
414
415    return BERR_SUCCESS;
416}
417
418BERR_Code BPVRlib_Play_GetEvents(BPVRlib_Play_Handle playHandle, BPVRlib_Play_Events *events)
419{
420    events->descEvent = playHandle->descEvent;
421    events->finishedEvent = playHandle->finishedEvent;
422    return BERR_SUCCESS;
423}
424
425BERR_Code BPVRlib_Play_Start( BPVRlib_Play_Handle playHandle )
426{
427    BERR_Code err = BERR_SUCCESS;
428
429    if( playHandle->isInProgress )
430    {
431        return BERR_TRACE(BERR_UNKNOWN);
432    }
433
434    BKNI_Memset( &playHandle->stats, 0, sizeof( BPVRlib_Play_Stats ) );
435    playHandle->stats.numFreeDesc = playHandle->numDesc;
436    playHandle->scatGatBfrsComplete = 0;
437
438    err = BPVRlib_Play_P_EnableInterrupts( playHandle );
439    if( err != BERR_SUCCESS )
440    {
441        goto done;
442    }
443
444    playHandle->resync = true;
445
446    err = BXPT_Playback_StartChannel(playHandle->xptPlayHandle);
447    if( err != BERR_SUCCESS )
448    {
449        goto done;
450    }
451
452    playHandle->isInProgress = true;
453
454done:
455    return err;
456}
457
458BERR_Code BPVRlib_Play_P_CreateIntCallbacks( BPVRlib_Play_Handle playHandle )
459{
460    BINT_Id playInt;
461
462        playInt = BXPT_Playback_GetIntId(playHandle->xptPlayHandle, BXPT_PbInt_eDone);
463    return BINT_CreateCallback(&playHandle->hPlayInt, playHandle->intHandle, playInt, BPVRlib_Play_P_isr, playHandle, 0);
464}
465
466BERR_Code BPVRlib_Play_P_EnableInterrupts( BPVRlib_Play_Handle playHandle )
467{
468    return BINT_EnableCallback( playHandle->hPlayInt );
469}
470
471BERR_Code BPVRlib_Play_AddData( BPVRlib_Play_Handle playHandle, uint8_t *p_bfr, size_t *p_bfrSize, BPVRlib_Play_BlockMode block )
472{
473    uint32_t numBytesCopied = 0;
474    uint8_t *p_destBfr;
475    size_t destBfrSize;
476    BERR_Code err = BERR_SUCCESS;
477
478    if( !playHandle->isInProgress )
479    {
480        return BERR_TRACE(BERR_UNKNOWN);
481    }
482
483    while( *p_bfrSize )
484    {
485        err = BPVRlib_Play_AddDataRequest( playHandle, &p_destBfr, &destBfrSize, block );
486        BDBG_MSG(("BPVRlib_Play_AddData(): %d bytes available", destBfrSize));
487
488        if( destBfrSize == 0 || err != BERR_SUCCESS )
489        {
490            if( err == BERR_TIMEOUT)
491            {
492                goto done;
493            }
494        }
495
496        if( destBfrSize > *p_bfrSize )
497        {
498            destBfrSize = *p_bfrSize;
499        }
500
501        if( playHandle->pvrMemCopyCb )
502        {
503            (*playHandle->pvrMemCopyCb)( p_destBfr, p_bfr, destBfrSize );
504        }
505        else
506        {
507            err = BERR_TRACE(BERR_NOT_INITIALIZED);
508            goto done;
509        }
510
511        BDBG_MSG(("BPVRlib_Play_AddData(): adding %d bytes", destBfrSize));
512        err = BPVRlib_Play_UpdateWritePointer( playHandle, destBfrSize, block );
513        if( err != BERR_SUCCESS )
514        {
515            goto done;
516        }
517
518        p_bfr += destBfrSize;
519        numBytesCopied += destBfrSize;
520        *p_bfrSize -= destBfrSize;
521    }
522
523    *p_bfrSize = numBytesCopied;
524
525done:
526    return err;
527}
528
529BERR_Code BPVRlib_Play_AddDataRequest( BPVRlib_Play_Handle playHandle, uint8_t **pp_bfr, size_t *p_bfrSize, BPVRlib_Play_BlockMode block )
530{
531    BERR_Code err = BERR_SUCCESS;
532
533    *p_bfrSize = 0;
534
535    if( !playHandle->isInProgress )
536    {
537        return BERR_TRACE(BERR_UNKNOWN);
538    }
539
540    while( true )
541    {
542        BPVRlib_Play_CommitBuffersToHardware( playHandle, BPVRlib_Play_BlockMode_eNone );
543
544        if( block == BPVRlib_Play_BlockMode_eFreeDescriptor )
545        {
546            err = BPVRlib_Play_P_WaitForFreeDescriptor( playHandle, block );
547            if( err != BERR_SUCCESS )
548            {
549                return err;
550            }
551        }
552        else
553        {
554            BPVRlib_Play_P_UpdateHwDescriptors( playHandle );
555        }
556
557        if( (err = BPVRlib_P_RingMgr_AddDataRequest( playHandle->rbmgr, pp_bfr, p_bfrSize, 0, 0 )) != BERR_SUCCESS )
558        {
559            return err;
560        }
561
562        if( *p_bfrSize == 0 && block )
563        {
564            playHandle->stats.numBufferBlocks++;
565            if (playHandle->timeoutValue==0) {
566                return BERR_TIMEOUT;
567            }
568            BDBG_MSG(("Waiting event: Line: %ld.", __LINE__));
569            err = BKNI_WaitForEvent( playHandle->descEvent, playHandle->timeoutValue);
570            if( err != BERR_SUCCESS )
571            {
572                if( err == BERR_TIMEOUT)
573                {
574                    playHandle->stats.numTimeouts++;
575                    BDBG_ERR(("BPVRlib_Play_AddDataRequest(): Timeout waiting for descriptor to become available"));
576                    return err;
577                }
578                else
579                {
580                    BDBG_ERR(("BPVRlib_Play_AddDataRequest(): Error waiting for descriptor to become available"));
581                    return err;
582                }
583            }
584
585            if( !playHandle->isInProgress )
586            {
587                BDBG_ERR(("BPVRlib_Play_AddDataRequest(): Playback no longer in progress"));
588                return err;
589            }
590        }
591        else
592        {
593            break;
594        }
595    }
596
597    /* Use return code to specify if free descriptor is available. */
598    err = BPVRlib_Play_P_WaitForFreeDescriptor( playHandle, BPVRlib_Play_BlockMode_eNone );
599
600    return err;
601}
602
603BERR_Code BPVRlib_Play_UpdateWritePointer( BPVRlib_Play_Handle playHandle, size_t bfrSize, BPVRlib_Play_BlockMode block )
604{
605    uint8_t *p_ringBfrAddr;
606    size_t ringBfrSize;
607    BERR_Code err = BERR_SUCCESS;
608
609    if( !playHandle->isInProgress )
610    {
611        return BERR_TRACE(BERR_UNKNOWN);
612    }
613
614    BDBG_MSG(("Updating write pointer by %ld bytes for playback channel %ld. Block = %d", bfrSize, playHandle->channelNum, block));
615
616    /* Make sure we really have space in the ring buffer */
617    BPVRlib_P_RingMgr_AddDataRequest( playHandle->rbmgr, &p_ringBfrAddr, &ringBfrSize, 0 /* no block */, 0 /* no timeout*/ );
618
619    /* Sanity check */
620    BDBG_ASSERT( ringBfrSize >= bfrSize );
621
622    /* Update the write pointer after we have the descriptor to keep an accurate
623     * estimate of how much valid data is contained in the ring buffer.
624     */
625    BPVRlib_P_RingMgr_UpdateWritePointer( playHandle->rbmgr, bfrSize );
626
627    /* There may be times when we want to add data to the buffer, but not
628     * actually play it back until additional data is added.  Therefore,
629     * do not commit the data to hardware in these cases. */
630    if( block != BPVRlib_Play_BlockMode_eNoCommit )
631    {
632        err = BPVRlib_Play_CommitBuffersToHardware( playHandle, block );
633
634        if( err == BERR_TIMEOUT && block != BPVRlib_Play_BlockMode_eFreeDescriptor )
635        {
636            /* This is not really an error since we didn't block */
637            err = BERR_SUCCESS;
638        }
639    }
640
641    return err;
642}
643
644BERR_Code BPVRlib_Play_UpdateWritePointerWithSkip( BPVRlib_Play_Handle playHandle, size_t bfrSize, size_t skipSize, BPVRlib_Play_BlockMode block )
645{
646    BPVRlib_Play_P_DescEntry *p_descEntry;
647    uint8_t *p_ringBfrAddr;
648    size_t ringBfrSize;
649    BERR_Code err = BERR_SUCCESS;
650
651    if( !playHandle->isInProgress )
652    {
653        return BERR_TRACE(BERR_UNKNOWN);
654    }
655
656    BDBG_MSG(("Updating write pointer by %ld bytes with skip %ld for playback channel %ld.", bfrSize, skipSize, playHandle->channelNum));
657
658    /* All previously added data must be committed to hardware so we can properly program in the skip size */
659    err = BPVRlib_Play_CommitBuffersToHardware( playHandle, block );
660    if( err != BERR_SUCCESS )
661    {
662        return err;
663    }
664
665    /* Make sure we really have space in the ring buffer */
666    BPVRlib_P_RingMgr_AddDataRequest( playHandle->rbmgr, &p_ringBfrAddr, &ringBfrSize, 0 /* no block */, 0 /* no timeout*/ );
667
668    /* Sanity check */
669    BDBG_ASSERT( ringBfrSize >= bfrSize );
670
671    err = BPVRlib_Play_P_WaitForFreeDescriptor( playHandle, block );
672    if( err != BERR_SUCCESS )
673    {
674        return err;
675    }
676
677    BDBG_ASSERT( !BLST_SQ_EMPTY(&playHandle->freeDescList) );
678
679    /* Now that the data is in the ring buffer, add the data into hardware */
680    /* Remove the first free descriptor */
681    p_descEntry = BLST_SQ_FIRST( &playHandle->freeDescList );
682    BLST_SQ_REMOVE_HEAD( &playHandle->freeDescList, link );
683    playHandle->stats.numFreeDesc--;
684
685    BDBG_ASSERT( p_descEntry );
686    BDBG_ASSERT( p_descEntry->p_desc );
687
688    /* Update the write pointer after we have the descriptor to keep an accurate
689     * estimate of how much valid data is contained in the ring buffer.
690     */
691    BPVRlib_P_RingMgr_UpdateWritePointer( playHandle->rbmgr, bfrSize );
692
693    BXPT_Playback_CreateDesc(playHandle->xptHandle, p_descEntry->p_desc, p_ringBfrAddr+skipSize, bfrSize-skipSize, true /* int enable */, playHandle->resync, NULL);
694    p_descEntry->skipSize = skipSize;
695    p_descEntry->bufferModel = BPVRlib_Play_P_BufferModel_eRing;
696
697    playHandle->resync = false;
698
699    /* Add our descriptor entry to the hardware list */
700    BLST_SQ_INSERT_TAIL( &playHandle->hwDescList, p_descEntry, link );
701    playHandle->stats.numInHwDesc++;
702
703    /* Add this buffer into the hardware */
704    BXPT_Playback_AddDescriptors( playHandle->xptPlayHandle, p_descEntry->p_desc, p_descEntry->p_desc );
705
706    playHandle->stats.numDescAdded++;
707
708    BPVRlib_P_RingMgr_UpdateHwWriteCount( playHandle->rbmgr, bfrSize );
709
710    return err;
711
712}
713
714BERR_Code BPVRlib_Play_CommitBuffersToHardware( BPVRlib_Play_Handle playHandle, BPVRlib_Play_BlockMode block )
715{
716    BPVRlib_Play_P_DescEntry *p_descEntry;
717    BERR_Code err = BERR_SUCCESS;
718    uint8_t *p_bfrAddr;
719    size_t bfrSize;
720
721    BDBG_MSG(("Commiting buffers to hardware for playback channel %ld. Block = %d", playHandle->channelNum, block));
722
723    BPVRlib_P_RingMgr_GetHwWriteDifference( playHandle->rbmgr, &p_bfrAddr, &bfrSize );
724
725    while( bfrSize )
726    {
727        /* We don't want our descriptors to get too big, otherwise our buffer efficency will go down too low */
728        if( bfrSize > playHandle->maxDescSize )
729        {
730            bfrSize = playHandle->maxDescSize;
731        }
732
733        err = BPVRlib_Play_P_WaitForFreeDescriptor( playHandle, block );
734        if( err != BERR_SUCCESS )
735        {
736            return err;
737        }
738
739        BDBG_ASSERT( !BLST_SQ_EMPTY(&playHandle->freeDescList) );
740
741        /* Now that the data is in the ring buffer, add the data into hardware */
742        /* Remove the first free descriptor */
743        p_descEntry = BLST_SQ_FIRST( &playHandle->freeDescList );
744        BLST_SQ_REMOVE_HEAD( &playHandle->freeDescList, link );
745        playHandle->stats.numFreeDesc--;
746
747        BDBG_ASSERT( p_descEntry );
748        BDBG_ASSERT( p_descEntry->p_desc );
749
750        BXPT_Playback_CreateDesc(playHandle->xptHandle, p_descEntry->p_desc, p_bfrAddr, bfrSize, true /* int enable */, playHandle->resync, NULL);
751        p_descEntry->skipSize = 0;
752        p_descEntry->bufferModel = BPVRlib_Play_P_BufferModel_eRing;
753
754        playHandle->resync = false;
755
756        /* Add our descriptor entry to the hardware list */
757        BLST_SQ_INSERT_TAIL( &playHandle->hwDescList, p_descEntry, link );
758        playHandle->stats.numInHwDesc++;
759
760        /* Add this buffer into the hardware */
761        BXPT_Playback_AddDescriptors( playHandle->xptPlayHandle, p_descEntry->p_desc, p_descEntry->p_desc );
762
763        playHandle->stats.numDescAdded++;
764
765        BPVRlib_P_RingMgr_UpdateHwWriteCount( playHandle->rbmgr, bfrSize );
766        BPVRlib_P_RingMgr_GetHwWriteDifference( playHandle->rbmgr, &p_bfrAddr, &bfrSize );
767    }
768
769    return err;
770}
771
772/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ /**
773This function check if descriptors are available
774for loading into the playback hardware.  If
775not the function can block until one becomes available.
776+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
777BERR_Code BPVRlib_Play_P_WaitForFreeDescriptor( BPVRlib_Play_Handle playHandle, BPVRlib_Play_BlockMode block )
778{
779    BERR_Code err = BERR_SUCCESS;
780
781    BDBG_MSG(("Waiting for free descriptor on playback channel %ld. Block = %d", playHandle->channelNum, block));
782
783    BPVRlib_Play_P_UpdateHwDescriptors( playHandle );
784
785    /* Wait for a free descriptor to become available */
786    while( BLST_SQ_EMPTY(&playHandle->freeDescList) )
787    {
788        if( block != BPVRlib_Play_BlockMode_eFreeDescriptor )
789        {
790            /* We cannot block, but there are no descriptors available, so we must return */
791            return BERR_TIMEOUT;
792        }
793
794        playHandle->stats.numDescBlocks++;
795        if (playHandle->timeoutValue==0) {
796            return BERR_TIMEOUT;
797        }
798
799        BDBG_MSG(("Waiting event: Line: %ld.", __LINE__));
800        err = BKNI_WaitForEvent( playHandle->descEvent, playHandle->timeoutValue);
801        if( err != BERR_SUCCESS )
802        {
803            if( err == BERR_TIMEOUT )
804            {
805                playHandle->stats.numTimeouts++;
806                BDBG_ERR(("BPVRlib_Play_P_WaitForFreeDescriptor(): Timeout waiting for descriptor to become available"));
807                return err;
808            }
809            else
810            {
811                BDBG_ERR(("BPVRlib_Play_P_WaitForFreeDescriptor(): Error waiting for descriptor to become available"));
812                return err;
813            }
814        }
815
816        if( !playHandle->isInProgress )
817        {
818            BDBG_ERR(("BPVRlib_Play_P_WaitForFreeDescriptor(): Playback no longer in progress"));
819            return err;
820        }
821
822        BPVRlib_Play_P_UpdateHwDescriptors( playHandle );
823    }
824
825    return err;
826}
827
828/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ /**
829This function is called when a transport playback
830interrupt is signalled.  It simply sets one (or two)
831events to communicate to the task level code that a
832descriptor has completed.
833+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
834void BPVRlib_Play_P_isr( void *Parm1, int Parm2 )
835{
836    BXPT_Playback_ChannelStatus status;
837    BPVRlib_Play_Handle playHandle = (BPVRlib_Play_Handle)Parm1;
838
839    BSTD_UNUSED(Parm2);
840
841    BDBG_MSG(("Got interrupt for playback channel %ld.", playHandle->channelNum));
842
843    BXPT_Playback_GetChannelStatus( playHandle->xptPlayHandle, &status );
844
845    if( status.Finished )
846    {
847        playHandle->stats.numUnderFlows++;
848        BKNI_SetEvent( playHandle->finishedEvent );
849        BDBG_MSG(("BPVRlib_Play_P_isr(): Playback channel %ld underflowed!", playHandle->channelNum));
850    }
851
852    BKNI_SetEvent( playHandle->descEvent );
853}
854
855/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ /**
856This function frees any data
857(updates the ring buffer read pointer) that has now
858completed playback through the hardware.  It also
859places newly completed descriptors on the free list
860and wakes any tasks that may be waiting for one to
861free up (if the free list was previously empty).
862+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
863void BPVRlib_Play_P_UpdateHwDescriptors( BPVRlib_Play_Handle playHandle )
864{
865    uint32_t numDoneDesc = 0;
866    bool    descInUse = false;
867    uint32_t descSize;
868    BPVRlib_Play_P_DescEntry *p_descEntry;
869
870    BDBG_MSG(("Updating hardware descriptors for playback channel %ld.",playHandle->channelNum));
871
872    while( !descInUse )
873    {
874        /* Make sure we have entries in the hardware list */
875        if( BLST_SQ_EMPTY(&playHandle->hwDescList) )
876        {
877            BDBG_MSG(("BPVRlib_Play_P_UpdateHwDescriptors(): Hardware descriptor list is empty"));
878            descInUse = true;   /* exit the while loop */
879            continue;
880        }
881
882        /* Check if the head descriptor is complete */
883        p_descEntry = BLST_SQ_FIRST( &playHandle->hwDescList );
884
885        /* Sanity Check */
886        BDBG_ASSERT(p_descEntry);
887        BDBG_ASSERT(p_descEntry->p_desc);
888
889        BXPT_Playback_CheckHeadDescriptor(playHandle->xptPlayHandle, p_descEntry->p_desc, &descInUse, &descSize );
890
891        if( descInUse )
892        {
893            BDBG_MSG(("Head descriptor still in use."));
894            /* exit the while loop because there are no more complete descriptors */
895            continue;
896        }
897
898        /* Remove the first descriptor from the hardware list */
899        p_descEntry = BLST_SQ_FIRST(&playHandle->hwDescList);
900        BLST_SQ_REMOVE_HEAD( &playHandle->hwDescList, link );
901        playHandle->stats.numInHwDesc--;
902
903        BDBG_ASSERT( p_descEntry );
904        BDBG_ASSERT( p_descEntry->p_desc );
905
906        if( p_descEntry->bufferModel == BPVRlib_Play_P_BufferModel_eRing )
907        {
908            descSize += p_descEntry->skipSize;
909            BDBG_MSG(("BPVRlib_Play_P_UpdateHwDescriptors(): Updating read pointer by %d bytes.", descSize));
910            BPVRlib_P_RingMgr_UpdateReadPointer( playHandle->rbmgr, descSize );
911        }
912        else
913        {
914            playHandle->scatGatBfrsComplete++;
915            playHandle->stats.numBytesScatGat -= descSize;
916            playHandle->stats.numScatGatDesc--;
917        }
918
919        playHandle->stats.numDescCompleted++;
920
921        numDoneDesc++;
922        if( numDoneDesc == 2 )
923        {
924            playHandle->stats.numMultiDescDone++;
925        }
926
927        /* Place the descriptor back on the free list */
928        BLST_SQ_INSERT_TAIL( &playHandle->freeDescList, p_descEntry, link );
929        playHandle->stats.numFreeDesc++;
930    }
931}
932
933BERR_Code BPVRlib_Play_Stop( BPVRlib_Play_Handle playHandle )
934{
935    BPVRlib_Play_P_DescEntry *p_descEntry;
936
937    if( !playHandle->isInProgress )
938    {
939        return BERR_TRACE(BERR_UNKNOWN);
940    }
941
942    BDBG_MSG(("Stopping playback channel %ld.", playHandle->channelNum));
943
944    playHandle->isInProgress = false;
945
946    BXPT_Playback_StopChannel(playHandle->xptPlayHandle);
947
948    /* Stopping the ring buffer will wake any threads waiting to feed more data into the ring buffer */
949    BPVRlib_P_RingMgr_Reset( playHandle->rbmgr );
950
951    /* Wake any threads waiting for a free descriptor */
952    BKNI_SetEvent( playHandle->descEvent );
953    BKNI_SetEvent( playHandle->finishedEvent );
954
955    /* Move all of the descriptors from the hardware list to the free list */
956    while( !BLST_SQ_EMPTY( &playHandle->hwDescList ) )
957    {
958        p_descEntry = BLST_SQ_FIRST(&playHandle->hwDescList);
959        BLST_SQ_REMOVE_HEAD( &playHandle->hwDescList, link );
960        playHandle->stats.numInHwDesc--;
961
962        BDBG_ASSERT( p_descEntry );
963        BDBG_ASSERT( p_descEntry->p_desc );
964
965        BLST_SQ_INSERT_TAIL( &playHandle->freeDescList, p_descEntry, link );
966        playHandle->stats.numFreeDesc++;
967    }
968
969    return BERR_SUCCESS;
970}
971
972BERR_Code BPVRlib_Play_Flush( BPVRlib_Play_Handle playHandle )
973{
974#if !B_HAS_RAVE
975    BXPT_Playback_ChannelSettings settings;
976    uint8_t *p_bfr;
977    size_t bfrSize = 0;
978#endif
979
980    BERR_Code err = BERR_SUCCESS;
981
982    if( !playHandle->isInProgress )
983    {
984        return BERR_TRACE(BERR_UNKNOWN);
985    }
986
987    BDBG_MSG(("Flushing playback channel %ld", playHandle->channelNum));
988
989    err = BPVRlib_Play_Stop( playHandle );
990    if( err != BERR_SUCCESS )
991    {
992        return err;
993    }
994    err = BPVRlib_Play_Start( playHandle );
995    if( err != BERR_SUCCESS )
996    {
997        return err;
998    }
999
1000#if !B_HAS_RAVE
1001    err = BXPT_Playback_GetChannelSettings( playHandle->xptPlayHandle, &settings );
1002    if( err != BERR_SUCCESS )
1003    {
1004        return err;
1005    }
1006
1007    if( settings.SyncMode == BXPT_PB_SYNC_MPEG )
1008    {
1009        /* Insert a null packet to flush the video decoder once we start up again */
1010        if( (BPVRlib_Play_AddDataRequest( playHandle, &p_bfr, &bfrSize, BPVRlib_Play_BlockMode_eNone ) == BERR_SUCCESS)
1011            && (bfrSize >= settings.PacketLength) )
1012        {
1013            BPVRlib_Play_GenerateTsNullPacket( p_bfr );
1014            BPVRlib_Play_UpdateWritePointer( playHandle, settings.PacketLength, BPVRlib_Play_BlockMode_eNoCommit );
1015        }
1016        else
1017        {
1018            BDBG_ERR(("BPVRlib_Play_Flush(): Unable to send NULL packet!"));
1019        }
1020    }
1021#endif
1022
1023    if( BPVRlib_Play_P_IsActive( playHandle ) )
1024    {
1025        BDBG_ERR(("BPVRlib_Play_Flush(): Playback active immediately after flush!!"));
1026        return BERR_UNKNOWN;
1027    }
1028
1029    return err;
1030}
1031
1032BERR_Code BPVRlib_Play_GetBufferDepth( BPVRlib_Play_Handle playHandle, size_t *p_bfrDepth )
1033{
1034    /* This will cause the state to be applied and the status to be up-to-date. */
1035    BPVRlib_Play_CommitBuffersToHardware( playHandle, BPVRlib_Play_BlockMode_eNone );
1036    BPVRlib_Play_P_UpdateHwDescriptors( playHandle );
1037    BPVRlib_P_RingMgr_GetNumFreeBytes( playHandle->rbmgr, p_bfrDepth );
1038    *p_bfrDepth = playHandle->rbmgr->bufferSize - *p_bfrDepth;
1039    return BERR_SUCCESS;
1040}
1041
1042/***********************************************************/ /**
1043This function checks it the playback channel is active.
1044****************************************************************/
1045bool BPVRlib_Play_P_IsActive( BPVRlib_Play_Handle playHandle )
1046{
1047    BXPT_Playback_ChannelStatus status;
1048
1049    BXPT_Playback_GetChannelStatus( playHandle->xptPlayHandle, &status );
1050
1051    if( status.Run && !status.Finished )
1052        return true;
1053    else
1054        return false;
1055}
1056
1057BERR_Code BPVRlib_Play_WaitForFinished( BPVRlib_Play_Handle playHandle )
1058{
1059    BERR_Code err = BERR_SUCCESS;
1060
1061    if( !playHandle->isInProgress )
1062    {
1063        return BERR_TRACE(BERR_UNKNOWN);
1064    }
1065
1066    BDBG_MSG(("Waiting for playback channel %ld to complete.", playHandle->channelNum));
1067
1068    BPVRlib_Play_CommitBuffersToHardware( playHandle, BPVRlib_Play_BlockMode_eFreeDescriptor );
1069
1070    while( BPVRlib_Play_P_IsActive( playHandle ) )
1071    {
1072        BDBG_MSG(("Waiting event: Line: %ld.", __LINE__));
1073        err = (playHandle->timeoutValue?BKNI_WaitForEvent( playHandle->finishedEvent, playHandle->timeoutValue):BERR_TIMEOUT);
1074        if( err != BERR_SUCCESS )
1075        {
1076            if( err == BERR_TIMEOUT)
1077            {
1078                playHandle->stats.numTimeouts++;
1079                BDBG_ERR(("BPVRlib_Play_WaitForFinished(): Timeout waiting for playback to finish"));
1080                return err;
1081            }
1082            else
1083            {
1084                BDBG_ERR(("BPVRlib_Play_WaitForFinished(): Error waiting for playback to finish"));
1085                return err;
1086            }
1087        }
1088    }
1089
1090    return err;
1091}
1092
1093BERR_Code BPVRlib_Play_SetTimeout( BPVRlib_Play_Handle playHandle, uint32_t numMsec )
1094{
1095    playHandle->timeoutValue = numMsec;
1096
1097    return BERR_SUCCESS;
1098}
1099
1100BERR_Code BPVRlib_Play_GetTimeout( BPVRlib_Play_Handle playHandle, uint32_t *p_numMsec )
1101{
1102    *p_numMsec = playHandle->timeoutValue;
1103
1104    return BERR_SUCCESS;
1105}
1106
1107BERR_Code BPVRlib_Play_GetStats( BPVRlib_Play_Handle playHandle, BPVRlib_Play_Stats *p_stats )
1108{
1109    uint8_t *dummy;
1110    size_t count;
1111
1112    /* This will cause the state to be applied and the status to be up-to-date. */
1113    BPVRlib_Play_CommitBuffersToHardware( playHandle, BPVRlib_Play_BlockMode_eNone );
1114    BPVRlib_Play_P_UpdateHwDescriptors( playHandle );
1115
1116    p_stats->numBytesPlayed = (playHandle->rbmgr->bufferSize * playHandle->rbmgr->readWrapCount) + playHandle->rbmgr->readOffset;
1117    p_stats->numBytesAdded      = (playHandle->rbmgr->bufferSize * playHandle->rbmgr->writeWrapCount) + playHandle->rbmgr->writeOffset;
1118    p_stats->bfrSize            = playHandle->rbmgr->bufferSize;
1119    p_stats->readOffset     = playHandle->rbmgr->readOffset;
1120    p_stats->writeOffset        = playHandle->rbmgr->writeOffset;
1121    p_stats->hwWriteOffset      = playHandle->rbmgr->hwWriteOffset;
1122
1123    BPVRlib_P_RingMgr_GetHwWriteDifference( playHandle->rbmgr, &dummy, &count );
1124    p_stats->numBytesNotCommitted = count;
1125
1126    p_stats->numFreeDesc        = playHandle->stats.numFreeDesc;
1127    p_stats->numInHwDesc        = playHandle->stats.numInHwDesc;
1128    p_stats->numDesc            = playHandle->numDesc;
1129    p_stats->numDescAdded       = playHandle->stats.numDescAdded;
1130    p_stats->numDescCompleted   = playHandle->stats.numDescCompleted;
1131    p_stats->numUnderFlows      = playHandle->stats.numUnderFlows;
1132    p_stats->numBufferBlocks    = playHandle->stats.numBufferBlocks;
1133    p_stats->numDescBlocks      = playHandle->stats.numDescBlocks;
1134    p_stats->numTimeouts        = playHandle->stats.numTimeouts;
1135
1136        p_stats->numBytesScatGat        = playHandle->stats.numBytesScatGat;
1137        p_stats->numScatGatDesc         = playHandle->stats.numScatGatDesc;
1138        p_stats->numMultiDescDone       = playHandle->stats.numMultiDescDone;
1139
1140    return BERR_SUCCESS;
1141}
1142
1143void BPVRlib_Play_GenerateTsNullPacket( uint8_t *pkt )
1144{
1145    int i;
1146
1147    pkt[0] = 0x47;   /* SYNC BYTE */
1148    pkt[1] = 0x1f;
1149    pkt[2] = 0xff;  /* PID */
1150    pkt[3] = 0x10;
1151    for(i=4; i<188; ++i)
1152    {
1153        pkt[i] = 0xff;
1154    }
1155}
1156
1157BERR_Code BPVRlib_Play_AddBuffer( BPVRlib_Play_Handle playHandle,   const uint8_t *p_bfr, const size_t bfrSize, BPVRlib_Play_BlockMode block )
1158{
1159    BPVRlib_Play_P_DescEntry *p_descEntry;
1160    BERR_Code err = BERR_SUCCESS;
1161
1162    BDBG_MSG(("Adding buffer to hardware for playback channel %ld. Block = %d", playHandle->channelNum, block));
1163
1164    err = BPVRlib_Play_CommitBuffersToHardware( playHandle, block );
1165    if( err != BERR_SUCCESS )
1166    {
1167        return err;
1168    }
1169
1170    err = BPVRlib_Play_P_WaitForFreeDescriptor( playHandle, block );
1171    if( err != BERR_SUCCESS )
1172    {
1173        return err;
1174    }
1175
1176    BDBG_ASSERT( !BLST_SQ_EMPTY(&playHandle->freeDescList) );
1177
1178    /* Remove the first free descriptor */
1179    p_descEntry = BLST_SQ_FIRST( &playHandle->freeDescList );
1180    BLST_SQ_REMOVE_HEAD( &playHandle->freeDescList, link );
1181    playHandle->stats.numFreeDesc--;
1182
1183    BDBG_ASSERT( p_descEntry );
1184    BDBG_ASSERT( p_descEntry->p_desc );
1185
1186    BXPT_Playback_CreateDesc(playHandle->xptHandle, p_descEntry->p_desc, (uint8_t *)p_bfr, bfrSize, true /* int enable */, playHandle->resync, NULL);
1187    p_descEntry->skipSize = 0;
1188    p_descEntry->bufferModel = BPVRlib_Play_P_BufferModel_eScatterGather;
1189
1190    playHandle->resync = false;
1191
1192    /* Add our descriptor entry to the hardware list */
1193    BLST_SQ_INSERT_TAIL( &playHandle->hwDescList, p_descEntry, link );
1194    playHandle->stats.numInHwDesc++;
1195    playHandle->stats.numScatGatDesc++;
1196    playHandle->stats.numBytesScatGat += bfrSize;
1197
1198    /* Add this buffer into the hardware */
1199    BXPT_Playback_AddDescriptors( playHandle->xptPlayHandle, p_descEntry->p_desc, p_descEntry->p_desc );
1200
1201    playHandle->stats.numDescAdded++;
1202
1203    return err;
1204}
1205
1206BERR_Code BPVRlib_Play_IsBufferComplete( BPVRlib_Play_Handle playHandle, unsigned *p_bfrsCompleted, BPVRlib_Play_BlockMode block )
1207{
1208    BERR_Code err = BERR_SUCCESS;
1209
1210    BPVRlib_Play_P_UpdateHwDescriptors( playHandle );
1211
1212    if( block != BPVRlib_Play_BlockMode_eNone )
1213    {
1214        while( playHandle->scatGatBfrsComplete == 0 && playHandle->stats.numScatGatDesc != 0 )
1215        {
1216            BDBG_MSG(("Waiting event: Line: %ld.", __LINE__));
1217            err = BKNI_WaitForEvent( playHandle->descEvent, playHandle->timeoutValue);
1218            if( err != BERR_SUCCESS )
1219            {
1220                if( err == BERR_TIMEOUT )
1221                {
1222                    playHandle->stats.numTimeouts++;
1223                    BDBG_ERR(("BPVRlib_Play_IsBufferComplete(): Timeout waiting for descriptor to complete"));
1224                    return err;
1225                }
1226                else
1227                {
1228                    BDBG_ERR(("BPVRlib_Play_IsBufferComplete(): Error waiting for descriptor to complete"));
1229                    return err;
1230                }
1231            }
1232            BPVRlib_Play_P_UpdateHwDescriptors( playHandle );
1233        }
1234    }
1235
1236    *p_bfrsCompleted = playHandle->scatGatBfrsComplete;
1237    playHandle->scatGatBfrsComplete = 0;
1238
1239    return BERR_SUCCESS;
1240}
1241
Note: See TracBrowser for help on using the repository browser.