source: svn/trunk/newcon3bcm2_21bu/magnum/syslib/pcrlib/7552/bpcrlib.c @ 44

Last change on this file since 44 was 2, checked in by jglee, 11 years ago

first commit

  • Property svn:executable set to *
File size: 95.8 KB
Line 
1/***************************************************************************
2 *     Copyright (c) 2003-2012, 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: bpcrlib.c $
11 * $brcm_Revision: Hydra_Software_Devel/110 $
12 * $brcm_Date: 1/16/12 8:15p $
13 *
14 * Module Description:
15 *
16 * Revision History:
17 *
18 * $brcm_Log: /magnum/syslib/pcrlib/7038/bpcrlib.c $
19 *
20 * Hydra_Software_Devel/110   1/16/12 8:15p bandrews
21 * SW3556-1029: still one case where zero STC was loaded
22 *
23 * Hydra_Software_Devel/109   11/17/11 6:59p bandrews
24 * SW7346-544: add playback flag to check for refresh on invalidate
25 *
26 * Hydra_Software_Devel/108   6/27/11 4:40p bandrews
27 * SW7425-654: merge to main
28 *
29 * Hydra_Software_Devel/SW7425-654/3   6/24/11 12:25a bandrews
30 * SW7425-654: add pairing to config
31 *
32 * Hydra_Software_Devel/SW7425-654/2   6/24/11 12:16a bandrews
33 * SW7425-654: don't refresh stc on invalidate in NRT mode
34 *
35 * Hydra_Software_Devel/SW7425-654/1   6/23/11 11:41p bandrews
36 * SW7425-654: add non-real-time behavior and setting to pcrlib
37 *
38 * Hydra_Software_Devel/107   5/16/11 2:46p bandrews
39 * SW7125-944: remove trace call as failure is normal and handled
40 *
41 * Hydra_Software_Devel/106   4/15/11 7:21p bandrews
42 * SW7425-217: pcrlib needed to have its getPts logic cleaned up a bit;
43 * for the real fix to this problem see SW7405-5118
44 *
45 * Hydra_Software_Devel/105   4/12/11 4:47p bandrews
46 * SW3556-11: fix copy pasta error for secondary audio iface
47 *
48 * Hydra_Software_Devel/104   1/19/11 7:18p bandrews
49 * SW35230-2125: make CS encompass all calls to isr, not just the first
50 * two
51 *
52 * Hydra_Software_Devel/103   12/27/10 2:55p xhuang
53 * SW7358-29: Add 7358/7552 support
54 *
55 * Hydra_Software_Devel/102   12/8/10 2:30p jrubio
56 * SW7344-9: add 7344/7346/7231 support
57 *
58 * Hydra_Software_Devel/101   11/12/10 5:47p bandrews
59 * SW35230-2125: renamed config option to refresh_stc_on_invalidate, fixed
60 * warning
61 *
62 * Hydra_Software_Devel/100   11/11/10 9:00p bandrews
63 * SW35230-2125: allow pcrlib to seed STC from lowest PTS during
64 * invalidate
65 *
66 * Hydra_Software_Devel/99   5/11/10 9:41p bandrews
67 * SW7401-2855: removed warning
68 *
69 * Hydra_Software_Devel/98   5/5/10 3:56p bandrews
70 * SW7401-2855: condition last dss merge
71 *
72 * Hydra_Software_Devel/97   5/4/10 2:31p bandrews
73 * SW7401-2855: qualify merged dssification with 7401 chipdef
74 *
75 * Hydra_Software_Devel/96   5/3/10 8:44p bandrews
76 * SW7401-2855: merge to main, correct tabs/spaces
77 *
78 * Hydra_Software_Devel/95   2/8/10 3:57p bandrews
79 * SW3556-1029: fixed short-circuit eval causing zero-valued stc to be
80 * loaded
81 *
82 * Hydra_Software_Devel/95   2/8/10 3:57p bandrews
83 * SW3556-1029: fixed short-circuit eval causing zero-valued pcr to be
84 * loaded
85 *
86 * Hydra_Software_Devel/94   8/20/09 4:28p mward
87 * PR55545: Support 7125.
88 *
89 * Hydra_Software_Devel/93   8/10/09 6:17p jrubio
90 * PR55232: add 7340/7342 support
91 *
92 * Hydra_Software_Devel/92   6/9/09 3:49p erickson
93 * PR55611: pcr not required for PCROFFSET-based systems
94 *
95 * Hydra_Software_Devel/91   4/22/09 4:08p erickson
96 * PR49940: have audio and video master modes automatically switch to stc
97 * master if the necessary audio or video interface is not configured.
98 *
99 * Hydra_Software_Devel/90   1/31/09 12:54a jrubio
100 * PR51629: add 7336 support
101 *
102 * Hydra_Software_Devel/89   12/30/08 10:52a erickson
103 * PR49582: add asserts for easier debug
104 *
105 * Hydra_Software_Devel/88   12/15/08 11:28a erickson
106 * PR49489: fix warning
107 *
108 * Hydra_Software_Devel/87   12/2/08 9:13p bandrews
109 * PR49489: in AMM, don't apply an stc offset before reseeding with pts
110 *
111 * Hydra_Software_Devel/86   11/26/08 6:43p bandrews
112 * PR48177: Downgraded to messages for most, warning for some
113 *
114 * Hydra_Software_Devel/85   11/19/08 7:00p vishk
115 * PR 49424: Coverity Defect ID:11607 FORWARD_NULL bpcrlib.c Product=93549
116 * PR 48336: Coverity Defect ID:12067 FORWARD_NULL bpcrlib.c
117 * Product=97405nexus
118 *
119 * Hydra_Software_Devel/84   10/22/08 7:48p bandrews
120 * PR45126: Fixed primary channel lock state wasn't set; Fixed non-primary
121 * channels not receiving updates if primary channel lock state was
122 * locked, but pts-stc was out of bounds
123 *
124 * Hydra_Software_Devel/83   8/6/08 10:03a erickson
125 * PR45459: fix release build warnings
126 *
127 * Hydra_Software_Devel/82   7/23/08 3:46p jgarrett
128 * PR 39452: Merging to main branch
129 *
130 * Hydra_Software_Devel/Nexus_Audio_Descriptors/1   5/15/08 4:13p jgarrett
131 * PR 42360: Adding tertiary decoder for audio descriptors
132 *
133 * Hydra_Software_Devel/81   5/12/08 4:12p erickson
134 * PR42628: free BPCRlib_Handle
135 *
136 * Hydra_Software_Devel/80   4/30/08 10:10a erickson
137 * PR42349: cannot call BKNI_Free inside a critical section. PCRlib should
138 * already be inactive by the time BPCRlib_Close is called.
139 *
140 * Hydra_Software_Devel/79   4/23/08 10:07a erickson
141 * PR39453: add 3548/3556 support
142 *
143 * Hydra_Software_Devel/78   3/27/08 5:47p bandrews
144 * PR40090: fixed imbalance in display of messages or video pts error
145 *
146 * Hydra_Software_Devel/77   2/22/08 10:51a erickson
147 * PR39730: add memset to getdefault
148 *
149 * Hydra_Software_Devel/76   2/15/08 9:54p bandrews
150 * PR39635: Update to handle non-TSM tsm mode
151 *
152 * Hydra_Software_Devel/75   12/5/07 3:27p katrep
153 * PR37217: Added 7335 support
154 *
155 * Hydra_Software_Devel/74   12/5/07 10:33a katrep
156 * PR37217: Added support for 7335.
157 *
158 * Hydra_Software_Devel/73   11/2/07 11:14a jrubio
159 * PR35015: fix for 7325
160 *
161 * Hydra_Software_Devel/72   11/1/07 10:20a jrubio
162 * PR35015: add 7325 support
163 *
164 * Hydra_Software_Devel/71   10/17/07 7:21p bandrews
165 * PR33892: Fixed reference to AVC struct members to remove 32
166 *
167 * Hydra_Software_Devel/70   10/17/07 5:45p bandrews
168 * PR33892: Fixed by using dropped frame count to determine errors
169 * unrecoverable by DM and recover in PCRlib
170 *
171 * Hydra_Software_Devel/69   10/17/07 4:50p bandrews
172 * PR36196: Reload PTS + offset during underflow
173 *
174 * Hydra_Software_Devel/68   9/19/07 5:52p bandrews
175 * PR35035: Fixed memory leak
176 *
177 * Hydra_Software_Devel/67   9/19/07 4:10p bandrews
178 * PR33851: Add decoder flush request when outside sync limit
179 *
180 * Hydra_Software_Devel/66   9/7/07 10:57a mward
181 * PR23982:  compile warning in BDBG_MSG.
182 *
183 * Hydra_Software_Devel/65   8/27/07 8:07p bandrews
184 * PR33851: Audio master mode and prep for adaptive tsm
185 *
186 * Hydra_Software_Devel/64   8/22/07 3:32p katrep
187 * PR34204: Added support for mosaic mode API. Enabled as default only for
188 * 7405 And 7400
189 *
190 * Hydra_Software_Devel/7405_pip_support/1   8/21/07 2:43p katrep
191 * PR34204: Added mosaic mode support for 7405.
192 *
193 * Hydra_Software_Devel/PR32044/2   6/29/07 11:39a jgarrett
194 * PR 32044: Removing compiler warning
195 *
196 * Hydra_Software_Devel/PR32044/1   6/28/07 2:52p jgarrett
197 * PR 32044: Removing check for duplicate PCR block for mosaic mode (RAVE
198 * only)
199 *
200 * Hydra_Software_Devel/63   6/29/07 4:33p gmohile
201 * PR 32546 : Add audio and video pts offset while testing audio/video stc
202 *
203 * Hydra_Software_Devel/62   6/28/07 8:02p bandrews
204 * PR31796: PCRlib implementation of audio and video master modes
205 *
206 * Hydra_Software_Devel/61   6/15/07 1:47p erickson
207 * PR31535: fixed DBG output
208 *
209 * Hydra_Software_Devel/60   4/3/07 5:02p bandrews
210 * PR8915: Fixed spelling
211 *
212 * Hydra_Software_Devel/59   3/9/07 3:23p dlwin
213 * PR 28126: Fixed a problem with playback of streams where the streams
214 * that are muxed aggressively. These aggressive streams have video and
215 * audio farther apart.
216 *
217 * Hydra_Software_Devel/58   12/4/06 1:39p erickson
218 * PR26295: only call BXPT_PcrOffset_RegenOffset_isr on request_stc, not
219 * pts_error. this requires a new param to UpdateStc.
220 *
221 * Hydra_Software_Devel/57   11/17/06 11:18a erickson
222 * PR25108: add 7403 support
223 *
224 * Hydra_Software_Devel/56   11/14/06 4:33p bandrews
225 * PR25912: Converted to all hex displays to match other places in the
226 * codebase
227 *
228 * Hydra_Software_Devel/55   10/30/06 4:06p bandrews
229 * PR24904: Initial 3563 support
230 *
231 * Hydra_Software_Devel/54   10/23/06 10:12a mward
232 * PR21691: For 7118 should use == not >=.
233 *
234 * Hydra_Software_Devel/53   10/23/06 10:08a mward
235 * PR21691:  7118 is a member of 7400 family.
236 *
237 * Hydra_Software_Devel/52   10/2/06 4:24p vsilyaev
238 * PR 23826: Added functions to allow user control STC
239 *
240 * Hydra_Software_Devel/51   9/1/06 2:58p erickson
241 * PR23128: remove B_HAS_IP in .c file. already removed in .h.
242 *
243 * Hydra_Software_Devel/50   8/25/06 11:15a jjordan
244 * PR23128: rework PCR clock handling for 97401 B0
245 *
246 * Hydra_Software_Devel/49   8/4/06 12:46p erickson
247 * PR23098: convert b_stc and b_delta_stc to uint32_t and int32_t. these
248 * are standard values for PTS math. also made BPCRlib_StcDiff_isr
249 * unconditionally public.
250 *
251 * Hydra_Software_Devel/48   7/25/06 3:41p jgarrett
252 * PR 22630: Removing comments about BPCRlib_HeartBeat.
253 *
254 * Hydra_Software_Devel/47   7/19/06 2:00p bandrews
255 * PR22630: #if 0'd out the unused code for HeartBeat
256 *
257 * Hydra_Software_Devel/46   7/18/06 7:14p bandrews
258 * PR22630: Demoted warning into message
259 *
260 * Hydra_Software_Devel/45   7/17/06 6:43p bandrews
261 * PR21639: Fixed so that pcrlib reports wraparound when wrap occurs
262 *
263 * Hydra_Software_Devel/44   6/30/06 6:36p bandrews
264 * PR19434: Corrected so that everyone receives STC if requestor is video
265 * or primary audio, and only secondary audio receives update if
266 * secondary audio requests
267 *
268 * Hydra_Software_Devel/43   6/15/06 5:14p mward
269 * PR21691: Add support for 7118 chip 97118 board
270 *
271 * Hydra_Software_Devel/42   6/5/06 4:28p erickson
272 * PR21941: cleaned up minor warnings
273 *
274 * Hydra_Software_Devel/41   4/7/06 8:36p bandrews
275 * PR19434: Hack to ensure only requestor receives STC
276 *
277 * Hydra_Software_Devel/40   3/28/06 10:05a vsilyaev
278 * PR 18642: Demoted BDBG_WRN in PcrOffset function
279 *
280 * Hydra_Software_Devel/39   3/20/06 6:16p dlwin
281 * PR 15200: Fixed a  compiler warning for uninitialized variable.
282 *
283 * Hydra_Software_Devel/38   3/14/06 3:30p jjordan
284 * PR15200: fix build for non-7411 platforms
285 *
286 * Hydra_Software_Devel/37   3/2/06 11:39a jjordan
287 * PR15200: rework STC steering for 97398
288 *
289 * Hydra_Software_Devel/36   3/1/06 3:26p jjordan
290 * PR18981: fix "live playback" and add config option IP_USE_LIVE_PLAYBACK
291 *
292 * Hydra_Software_Devel/35   2/28/06 1:47p jjordan
293 * PR18981: PR18981: prototype "live playback"
294 *
295 * Hydra_Software_Devel/34   2/10/06 2:08p vsilyaev
296 * PR 18642: Added code to use pcr offset
297 *
298 * Hydra_Software_Devel/33   2/9/06 2:01p vsilyaev
299 * PR 18642: Better trust to PCR when updating STC
300 *
301 * Hydra_Software_Devel/32   2/3/06 5:08p jgarrett
302 * PR 19440: Updating build for the 7400
303 *
304 * Hydra_Software_Devel/31   2/3/06 3:50p vsilyaev
305 * PR 18642: Update PCRlibrary to support playback of constant bitrate
306 * streams
307 *
308 * Hydra_Software_Devel/PR18642/3   1/27/06 4:11p vsilyaev
309 * PR18642: Use special configuration mode to change offsets for the
310 * constant rate streams
311 *
312 * Hydra_Software_Devel/PR18642/2   1/27/06 2:28p vsilyaev
313 * PR18642: Added code to use PCR for STC update
314 *
315 * Hydra_Software_Devel/PR18642/1   1/19/06 6:15p vsilyaev
316 * PR18642: Use PTS offset to control buffer depth in the decoders
317 *
318 * Hydra_Software_Devel/30   12/20/05 2:12p vsilyaev
319 * PR 18642: Added BPCRlib_Channel_LoadStc function to load user defined
320 * STC
321 *
322 * Hydra_Software_Devel/29   12/15/05 4:38p vsilyaev
323 * PR 18642: Added support for the user configurable PTS offsets and CDB
324 * levels
325 *
326 * Hydra_Software_Devel/27   10/6/05 4:46p vsilyaev
327 * PR 17441: Demoted warnings to messages, it reduces traffic over the
328 * serial port
329 *
330 * Hydra_Software_Devel/26   9/23/05 12:51p erickson
331 * PR17108: initial 97401 checkin
332 *
333 * Hydra_Software_Devel/25   9/6/05 6:45p vsilyaev
334 * PR 16012: Added support for 7401.
335 *
336 * Hydra_Software_Devel/24   9/2/05 6:08p vsilyaev
337 * PR15967: Added more debug output.
338 *
339 * Hydra_Software_Devel/23   8/29/05 6:23p vsilyaev
340 * PR 16685,PR15967: Added use of UpdateStc function.
341 *
342 * Hydra_Software_Devel/22   8/26/05 12:32p erickson
343 * PR15967: Added Invalidate function to cover decoder based trickmodes
344 *
345 * Hydra_Software_Devel/21   8/17/05 7:56p vsilyaev
346 * PR 15967: Added BPCRlib_Channel_AudioPtsError_isr function.
347 *
348 * Hydra_Software_Devel/20   8/10/05 4:14p vsilyaev
349 * PR 15967: Removed references to BMVD_.
350 *
351 * Hydra_Software_Devel/19   8/9/05 2:30p vsilyaev
352 * PR 15967: Use both aux transport and decoder to access STC.
353 *
354 * Hydra_Software_Devel/18   8/5/05 3:07p vsilyaev
355 * PR 15967: Fixed compile time warnings
356 *
357 * Hydra_Software_Devel/17   6/28/05 1:16p vsilyaev
358 * PR 15697: Improved interface to update STC.
359 *
360 * Hydra_Software_Devel/16   6/24/05 3:53p vsilyaev
361 * PR 15967: Use audio/video interface to read STC and PTS.
362 *
363 * Hydra_Software_Devel/15   9/20/04 8:07p vsilyaev
364 * PR 11800: Added test for STC/PTS range into the videoPtsError handler.
365 * Increased range for valid video PTS's to -0.5+1.0sec.
366 *
367 * Hydra_Software_Devel/14   5/19/04 11:37a vsilyaev
368 * PR 10971: Added support for DSS playback.
369 *
370 * Hydra_Software_Devel/13   5/12/04 6:55p vsilyaev
371 * PR 10971: Added handling of DSS timebase.
372 *
373 * Hydra_Software_Devel/12   4/22/04 5:15p vsilyaev
374 * PR 8915: Check level of video VBV buffer before using audio PTS as STC.
375 *
376 * Hydra_Software_Devel/11   4/21/04 8:23p vsilyaev
377 * PR 8915: Better handling of playback, try to reuse STC if possible.
378 *
379 * Hydra_Software_Devel/10   4/21/04 1:47p vsilyaev
380 * PR 10668: PR 8915: Fixed test for duplicate audio/video decodes.
381 *
382 * Hydra_Software_Devel/9   4/5/04 10:28a vsilyaev
383 * PR 8915: Use new name for PTS field
384 *
385 * Hydra_Software_Devel/PVR_7038_PreRelease/1   3/24/04 8:09p vsilyaev
386 * Use new name for PTS field
387 *
388 * Hydra_Software_Devel/8   3/4/04 5:03p vsilyaev
389 * PR 8915: Added VideoPtsError handler
390 *
391 * Hydra_Software_Devel/7   3/1/04 7:17p vsilyaev
392 * PR 8915: Fixed comparsion function for the second channel.
393 *
394 * Hydra_Software_Devel/6   2/1/04 6:23p vsilyaev
395 * PR 8915: Don't acquire critical section in functions callable from ISR.
396 *
397 * Hydra_Software_Devel/5   2/1/04 6:01p vsilyaev
398 * PR 8915: Added handling of video decode.
399 *
400 * Hydra_Software_Devel/4   12/10/03 6:34p vsilyaev
401 * PR 8915: Use newly avaliable _isr safe XPT_PCR functions.
402 *
403 * Hydra_Software_Devel/3   12/10/03 12:15p marcusk
404 * PR8915: Fixed minor compiler error.
405 *
406 * Hydra_Software_Devel/2   12/9/03 2:29p vsilyaev
407 * PR 8915: PCRLib module for 7038.
408 *
409 * Hydra_Software_Devel/1   12/3/03 6:38p vsilyaev
410 * 7038 PCRlib module
411 *
412 ***************************************************************************/
413
414#include "bstd.h"
415#include "bpcrlib.h"
416#include "blst_list.h"
417#include "bkni.h"
418#include "bpcrlib_mvd.h"
419#include "bpcrlib_aud.h"
420
421#if defined (B_HAS_IP) && defined (BCHP_7411_VER)
422  #include "barc.h"
423  #include "barc_priv.h"
424#endif
425
426BDBG_MODULE(pcrlib);
427
428#define BDBG_MSG_TRACE(x) /* BDBG_MSG(x) */
429
430enum BPCRlib_Decoder_State {
431    BPCRlib_Decoder_State_eNotLocked,
432    BPCRlib_Decoder_State_eLocked,
433    BPCRlib_Decoder_State_eLocking,
434    BPCRlib_Decoder_State_eWaitingSTC,
435    BPCRlib_Decoder_State_eInvalidated
436};
437
438#if (BCHP_CHIP>=7400) || (BCHP_CHIP==7118) || (BCHP_CHIP==3563) || (BCHP_CHIP==7325) || (BCHP_CHIP==7335) || \
439    (BCHP_CHIP==7340) || (BCHP_CHIP==7342) || (BCHP_CHIP==3548) || (BCHP_CHIP==3556) || (BCHP_CHIP==7125) || \
440    (BCHP_CHIP==7344) || (BCHP_CHIP==7346) || (BCHP_CHIP==7231) || (BCHP_CHIP==7358) || (BCHP_CHIP==7552)
441#define B_PCRLIB_HAS_PCROFFSET  1
442#include "bxpt_pcr_offset.h"
443#endif
444
445#if defined (B_HAS_IP) && defined (BCHP_7411_VER)
446typedef enum OS_control_state {
447    OS_control_idle,
448    OS_control_waiting_for_pcr
449} OS_control_state;
450#endif
451
452#define BPCRlib_P_PCR_FIFO  32
453
454typedef struct {
455    uint32_t last_pcr;
456    bool    last_pcr_valid;
457    unsigned index;
458    unsigned count;
459    int32_t pcr_fifo[BPCRlib_P_PCR_FIFO];
460    bool    pcr_offset_valid;
461    uint32_t pcr_offset;
462}BPCRlib_P_PCROffset;
463
464struct BPCRlib_P_Channel {
465    BLST_D_ENTRY(BPCRlib_P_Channel) link;
466    BPCRlib_Handle parent;
467    BXPT_PCR_Handle pcr;
468    BPCRlib_ChannelSettings settings;
469    enum BPCRlib_Decoder_State video_state;
470    enum BPCRlib_Decoder_State audio_state;
471    BPCRlib_Config cfg;
472#if defined (B_HAS_IP) && defined (BCHP_7411_VER)
473    OS_control_state theOS_control_state;
474    int OS_bit;
475    int error_count;
476#endif
477
478    BPCRlib_P_PCROffset pcr_offset;
479
480    struct {
481        enum {delayed_stc_eInvalid, delayed_stc_eLocked, delayed_stc_eWaiting} state;
482        uint32_t stc; /* STC to be applied to the decoder */
483        uint32_t old_stc; /* snapshot of STC from the running counter */
484    } delayed_stc;
485
486    /* added to see if we get consecutive pts errors */
487    struct
488    {
489        uint32_t uiLastDroppedFrameCount;
490        uint32_t uiLastDecodedFrameCount;
491        uint32_t uiConsecutivePtsErrorCount;
492    } sVideo;
493};
494
495/* threshold to detect discontinuity in the streame */
496#define BPCRLIB_DISC_TRESHOLD   ((3003*30*5)/4)
497
498struct BPCRlib_P_Handle {
499    BLST_D_HEAD(BPCRlib_P_Handle_list, BPCRlib_P_Channel) list;
500};
501
502static void BPCRlib_P_InvalidatePCRCache(BPCRlib_Channel channel);
503
504BERR_Code
505BPCRlib_Open(BPCRlib_Handle *pHandle, BCHP_Handle hChip)
506{
507    BPCRlib_Handle handle;
508
509    BSTD_UNUSED(hChip);
510
511    BDBG_ASSERT(BPCRlib_StcDiff_isr(false, 16349, 4294746617U)==118514);
512    BDBG_ASSERT(BPCRlib_StcDiff_isr(false, 4294746617U, 16349)==-118514);
513    BDBG_ASSERT(BPCRlib_StcDiff_isr(false, 16349, 0)==8174);
514    BDBG_ASSERT(BPCRlib_StcDiff_isr(false, 0, 16349)==-8174);
515
516    handle = BKNI_Malloc(sizeof(*handle));
517    if (!handle) {
518        return BERR_TRACE(BERR_OUT_OF_SYSTEM_MEMORY);
519    }
520    BLST_D_INIT(&handle->list);
521    *pHandle = handle;
522
523    return BERR_SUCCESS;
524}
525
526void
527BPCRlib_Close(BPCRlib_Handle handle)
528{
529    BPCRlib_Channel pcr;
530
531    while((pcr=BLST_D_FIRST(&handle->list))!=NULL) {
532        BLST_D_REMOVE_HEAD(&handle->list, link);
533        BKNI_Free(pcr);
534    }
535    BKNI_Free(handle);
536    return;
537}
538
539#if B_PCRLIB_HAS_PCROFFSET
540#else
541#define B_HAS_STCDECIFACE 1
542#endif
543
544static const BPCRlib_Config pcr_cfg = {
545    false,
546    BAVC_StreamType_eTsMpeg,
547    NULL, /* primary audio */
548#if !B_HAS_STCDECIFACE
549    NULL,
550#else
551    &BPCRlib_Audio_Aud,
552#endif
553    NULL, /* video */
554#if !B_HAS_STCDECIFACE
555    NULL,
556#else
557    &BPCRlib_Video_Mvd,
558#endif
559    NULL, /* secondary audio */
560#if !B_HAS_STCDECIFACE
561    NULL,
562#else
563    &BPCRlib_Audio_Aud,
564#endif
565    NULL, /* tertiary audio */
566#if !B_HAS_STCDECIFACE
567    NULL,
568#else
569    &BPCRlib_Audio_Aud,
570#endif
571    NULL, /* aux transport */
572    96 * 1024, /* video CDB level */
573    ((3003*4)/2), /* video PTS offset, 120ms */
574    (3003/2)*30, /* video STC discard threshold, 1 sec */
575    4 * 1024,  /* audio CDB level */
576    ((3003*2)/2), /* audio PTS offset, 60ms */
577    (3003/2)*120, /* audio STC discard threshold, 4 sec */
578    (3003/2)*2, /* pcr_offset 60 ms delay */
579    (3003/2)*30*10, /* pcr_discard 10 sec delay */
580    BPCRlib_Mode_eAutoPts,
581    false, /* is_playback_ip */
582    BPCRlib_TsmMode_eSTCMaster, /* tsm_mode */
583    0, /* sync_limit */
584    NULL, /* dec flush event handle */
585    8, /* consecutive pts error limit */
586    true, /* refresh stc on invalidate */
587    false, /* non realtime mode */
588    false /* paired with another channel */
589};
590
591BERR_Code
592BPCRlib_Channel_GetChannelDefSettings(BPCRlib_Handle handle, BPCRlib_ChannelSettings *config)
593{
594    BSTD_UNUSED(handle);
595    BKNI_Memset(config, 0, sizeof(*config));
596    return BERR_SUCCESS;
597}
598
599BERR_Code
600BPCRlib_Channel_Create(BPCRlib_Handle handle, BXPT_PCR_Handle pcr, BPCRlib_Channel *pChannel, const BPCRlib_ChannelSettings *settings )
601{
602    BPCRlib_Channel channel;
603#if !B_PCRLIB_HAS_PCROFFSET
604    BPCRlib_Channel i;
605#endif
606
607    channel = BKNI_Malloc(sizeof(*channel));
608    if (!channel) {
609        return BERR_TRACE(BERR_OUT_OF_SYSTEM_MEMORY);
610    }
611    BKNI_EnterCriticalSection();
612#if !B_PCRLIB_HAS_PCROFFSET
613    for(i=BLST_D_FIRST(&handle->list);i;i=BLST_D_NEXT(i,link)) {
614        if (i->pcr == pcr) {
615            BKNI_LeaveCriticalSection();
616            if (channel)
617            {
618                BKNI_Free(channel);
619            }
620            BDBG_ERR(("Can't use the same PCR(%#x) channel for two different pcrlib channels", (unsigned)pcr));
621            return BERR_TRACE(BERR_INVALID_PARAMETER);
622        }
623    }
624#endif
625    channel->settings = *settings;
626    channel->pcr = pcr;
627    channel->cfg = pcr_cfg;
628    channel->parent=handle;
629    channel->audio_state = BPCRlib_Decoder_State_eWaitingSTC;
630    channel->video_state = BPCRlib_Decoder_State_eWaitingSTC;
631    channel->delayed_stc.state = delayed_stc_eInvalid;
632
633    BPCRlib_P_InvalidatePCRCache(channel);
634#if defined (B_HAS_IP) && defined (BCHP_7411_VER)
635    channel->theOS_control_state = OS_control_idle;
636    channel->OS_bit = 1;
637    channel->error_count = 0;
638#endif
639
640    BLST_D_INSERT_HEAD(&handle->list, channel, link);
641    BKNI_LeaveCriticalSection();
642
643    *pChannel = channel;
644
645    return BERR_SUCCESS;
646}
647
648void
649BPCRlib_Channel_Destroy(BPCRlib_Channel channel)
650{
651    BKNI_EnterCriticalSection();
652    BLST_D_REMOVE(&channel->parent->list, channel, link);
653    BKNI_LeaveCriticalSection();
654    BKNI_Free(channel);
655    return;
656}
657
658void
659BPCRlib_Channel_GetConfig(BPCRlib_Channel channel, BPCRlib_Config *config)
660{
661    *config = channel->cfg;
662    return;
663}
664
665BERR_Code
666BPCRlib_Channel_SetConfig( BPCRlib_Channel channel, const BPCRlib_Config *config)
667{
668    BPCRlib_Channel ch;
669
670    if (config == NULL)
671        return BERR_TRACE(BERR_INVALID_PARAMETER);
672    if (config->audio!=NULL && config->audio == config->secondary_audio)
673        return BERR_TRACE(BERR_INVALID_PARAMETER);
674    if (config->audio!=NULL && config->audio == config->tertiary_audio)
675        return BERR_TRACE(BERR_INVALID_PARAMETER);
676    /* coverity[var_compare_op: FALSE] */
677    if ((config->audio_iface==NULL && config->audio!=NULL) ||
678        (config->video_iface==NULL && config->video!=NULL) ||
679        (config->secondary_audio_iface==NULL && config->secondary_audio!=NULL) ||
680        (config->tertiary_audio_iface==NULL && config->tertiary_audio!=NULL))
681        return BERR_TRACE(BERR_INVALID_PARAMETER);
682    /* coverity[var_deref_op: FALSE] */
683    if (config->aux_transport==NULL &&
684            ((config->audio && config->audio_iface->useAuxTrp) ||
685             (config->secondary_audio && config->secondary_audio_iface->useAuxTrp) ||
686             (config->tertiary_audio && config->tertiary_audio_iface->useAuxTrp) ||
687             (config->video && config->video_iface->useAuxTrp)))
688        return BERR_TRACE(BERR_INVALID_PARAMETER);
689
690    BDBG_MSG(("pcr old config %#x: video %#x audio %#x,%#x", channel, channel->cfg.video, channel->cfg.audio, channel->cfg.secondary_audio));
691    BDBG_MSG(("pcr new config %#x: video %#x audio %#x,%#x", channel, config->video, config->audio, config->secondary_audio));
692    BKNI_EnterCriticalSection();
693    for(ch=BLST_D_FIRST(&channel->parent->list);ch;ch=BLST_D_NEXT(ch,link)) {
694        if (ch==channel) {
695            /* skip a current channel */
696            continue;
697        }
698        BDBG_MSG(("pcr %#x: video %#x audio %#x,%#x", ch, ch->cfg.video, ch->cfg.audio, ch->cfg.secondary_audio));
699        if (
700               (config->video && ch->cfg.video == config->video)
701            || (config->audio && (ch->cfg.audio == config->audio || ch->cfg.secondary_audio == config->audio))
702            || (config->secondary_audio && ( ch->cfg.secondary_audio == config->secondary_audio || ch->cfg.audio == config->secondary_audio))
703            || (config->tertiary_audio && ( ch->cfg.tertiary_audio == config->tertiary_audio || ch->cfg.audio == config->tertiary_audio))
704            ) {
705            BKNI_LeaveCriticalSection();
706            BDBG_ERR(("Selected audio or video channel currently assigned to other pcrlib channel"));
707            return BERR_TRACE(BERR_INVALID_PARAMETER);
708        }
709    }
710    if (channel->cfg.playback!= config->playback) {
711        BPCRlib_P_InvalidatePCRCache(channel);
712    }
713    /* when decoders changes they go to unlocked state */
714    if (channel->cfg.video != config->video) {
715        channel->video_state = BPCRlib_Decoder_State_eWaitingSTC;
716        BPCRlib_P_InvalidatePCRCache(channel);
717    }
718    if (channel->cfg.audio != config->audio) {
719        channel->audio_state = BPCRlib_Decoder_State_eWaitingSTC;
720        BPCRlib_P_InvalidatePCRCache(channel);
721    }
722#if defined (B_HAS_IP) && defined (BCHP_7411_VER)
723    if (channel->cfg.video != config->video || channel->cfg.audio != config->audio) {
724        channel->theOS_control_state = OS_control_idle;
725        channel->OS_bit = 1;
726        channel->error_count = 0;
727    }
728#endif
729    if (channel->cfg.video != config->video || channel->cfg.audio != config->audio || channel->cfg.playback!= config->playback) {
730        channel->delayed_stc.state= delayed_stc_eInvalid;
731    }
732    channel->cfg = *config;
733    BKNI_LeaveCriticalSection();
734    /* Note, we don't reconfigure audio/video decoders at pcrlib */
735    return BERR_SUCCESS;
736}
737
738static BPCRlib_Channel
739find_by_audio_isr(BPCRlib_Handle handle, void *audio)
740{
741    BPCRlib_Channel chn;
742    BDBG_ASSERT(audio);
743    for(chn=BLST_D_FIRST(&handle->list);chn;chn=BLST_D_NEXT(chn,link)) {
744        if (chn->cfg.audio==audio || chn->cfg.secondary_audio==audio || chn->cfg.tertiary_audio==audio) {
745            /* we exploit fact that audio and secondary audio can't be shared */
746            goto found;
747        }
748    }
749    BDBG_WRN(("Unknown audio channel %#x", (unsigned)audio));
750found:
751    return chn;
752}
753
754static BPCRlib_Channel
755find_by_video_isr(BPCRlib_Handle handle, void *video)
756{
757    BPCRlib_Channel chn;
758
759    BDBG_ASSERT(video);
760    for(chn=BLST_D_FIRST(&handle->list);chn;chn=BLST_D_NEXT(chn,link)) {
761        if (chn->cfg.video==video) {
762            goto found;
763        }
764    }
765    BDBG_WRN(("Unknown video channel %#x", (unsigned)video));
766found:
767    return chn;
768}
769
770
771
772/*
773* this function takes STC in the 45KHz domain (MPEG) or 27MHz domain (DSS)
774* as 32 bit unsigned and returns delta in the 22.5KHz domain, 32 bit signed
775*/
776int32_t
777BPCRlib_StcDiff_isr(bool dss, uint32_t stc1, uint32_t stc2)
778{
779    int32_t delta, modulo;
780
781    /* 1. convert to the 22.5KHz domain */
782    if (dss) {
783        stc1 /= 1200;
784        stc2 /= 1200;
785        modulo = (1<<30)/600;
786    } else {
787        stc1 /= 2;
788        stc2 /= 2;
789        modulo = (1<<30);
790    }
791
792    delta = stc1 - stc2;
793    /* 2. Handle wraparond cases */
794    if (stc1 < stc2 && delta < -modulo) {
795        delta += modulo*2;
796    } else if (stc1 > stc2 && delta > modulo) {
797        delta -= modulo*2;
798    }
799    return delta;
800}
801
802static bool
803b_is_dss_isr(const BPCRlib_Config *cfg)
804{
805    return cfg->stream == BAVC_StreamType_eDssPes || cfg->stream == BAVC_StreamType_eDssEs;
806}
807
808/* 20060717 bandrews - need update for send_stc to match update_stc for requestor behavior */
809static BERR_Code
810b_really_send_stc_isr(const BPCRlib_Channel chn, uint32_t stc)
811{
812    BERR_Code rc=BERR_SUCCESS;
813    bool dss = b_is_dss_isr(&chn->cfg);
814    uint32_t old_stc;
815
816    if (chn->cfg.mode == BPCRlib_Mode_eConstantDelay) {
817#if B_PCRLIB_HAS_PCROFFSET
818        rc = BXPT_PcrOffset_SetStc_isr(chn->cfg.aux_transport, stc);
819        if (rc!=BERR_SUCCESS) { BDBG_ERR(("BXPT_PcrOffset_SetStc_isr returned error %#x, ignored", rc)); }
820#else
821        rc = BXPT_PCR_SetUserStc_isr(chn->pcr, stc, 0);
822        if (rc!=BERR_SUCCESS) { BDBG_ERR(("BXPT_PCR_SetUserStc returned error %#x, ignored", rc)); }
823#endif
824    }
825    if (chn->cfg.video && chn->cfg.video_iface->setStc) {
826        BDBG_MSG(("updating video:STC %#x", stc));
827        rc = chn->cfg.video_iface->getStc(chn->cfg.aux_transport, chn->cfg.video, &old_stc);
828        rc = chn->cfg.video_iface->setStc(chn->cfg.video_iface->useAuxTrp?chn->cfg.aux_transport:chn->pcr, chn->cfg.video, dss,stc);
829        if (rc!=BERR_SUCCESS) { BDBG_ERR(("video setStc returned error %#x, ignored", rc)); }
830    }
831    if (chn->cfg.audio && chn->cfg.audio_iface->setStc) {
832        BDBG_MSG(("updating audio: STC %#x", stc));
833        rc = chn->cfg.audio_iface->getStc(chn->cfg.aux_transport, chn->cfg.audio, &old_stc);
834        rc = chn->cfg.audio_iface->setStc(chn->cfg.audio_iface->useAuxTrp?chn->cfg.aux_transport:chn->pcr, chn->cfg.audio, dss, stc);
835        if (rc!=BERR_SUCCESS) { BDBG_ERR(("audio setStc returned error %#x, ignored", rc)); }
836    }
837    if (chn->cfg.secondary_audio && chn->cfg.secondary_audio_iface->setStc) {
838        BDBG_MSG(("updating secondary_audio: STC %#x", stc));
839        rc = chn->cfg.secondary_audio_iface->setStc(chn->cfg.secondary_audio_iface->useAuxTrp?chn->cfg.aux_transport:chn->pcr, chn->cfg.secondary_audio, dss, stc);
840        if (rc!=BERR_SUCCESS) { BDBG_ERR(("secondary audio setStc returned error %#x, ignored", rc)); }
841    }
842    if (chn->cfg.tertiary_audio && chn->cfg.tertiary_audio_iface->setStc) {
843        BDBG_MSG(("updating tertiary_audio: STC %#x", stc));
844        rc = chn->cfg.tertiary_audio_iface->setStc(chn->cfg.tertiary_audio_iface->useAuxTrp?chn->cfg.aux_transport:chn->pcr, chn->cfg.tertiary_audio, dss, stc);
845        if (rc!=BERR_SUCCESS) { BDBG_ERR(("tertiary audio setStc returned error %#x, ignored", rc)); }
846    }
847    return rc;
848}
849
850static BERR_Code
851b_send_stc_isr(const BPCRlib_Channel chn, uint32_t stc, void * requestor)
852{
853    BERR_Code rc=BERR_SUCCESS;
854    bool dss = b_is_dss_isr(&chn->cfg);
855
856    /*
857        20060717 bandrews -
858        if video requests -> set video, primary audio, and secondary audio
859        if primary audio requests -> set video, primary audio, and secondary audio
860        if secondary audio requests -> set secondary audio only
861    */
862    if (requestor == chn->cfg.video || requestor == chn->cfg.audio)
863    {
864        rc = b_really_send_stc_isr(chn, stc);
865    }
866    else /* secondary or tertiary audio */
867    {
868        if ( requestor == chn->cfg.secondary_audio )
869        {
870            if (chn->cfg.secondary_audio && chn->cfg.secondary_audio_iface->setStc) {
871                BDBG_MSG(("updating secondary_audio: STC %#x", stc));
872                rc = chn->cfg.secondary_audio_iface->setStc(chn->cfg.secondary_audio_iface->useAuxTrp?chn->cfg.aux_transport:chn->pcr, chn->cfg.secondary_audio, dss, stc);
873                if (rc!=BERR_SUCCESS) { BDBG_ERR(("secondary audio setStc returned error %#x, ignored", rc)); }
874            }
875        }
876        else /* tertiary */
877        {
878            if (chn->cfg.tertiary_audio && chn->cfg.tertiary_audio_iface->setStc) {
879                BDBG_MSG(("updating tertiary_audio: STC %#x", stc));
880                rc = chn->cfg.tertiary_audio_iface->setStc(chn->cfg.tertiary_audio_iface->useAuxTrp?chn->cfg.aux_transport:chn->pcr, chn->cfg.tertiary_audio, dss, stc);
881                if (rc!=BERR_SUCCESS) { BDBG_ERR(("tertiary audio setStc returned error %#x, ignored", rc)); }
882            }
883        }
884    }
885
886    return rc;
887}
888
889static bool
890b_read_stc_isr(const BPCRlib_Channel chn, uint32_t *stc)
891{
892    BERR_Code rc;
893
894    if (chn->cfg.audio && chn->audio_state!=BPCRlib_Decoder_State_eWaitingSTC && chn->cfg.audio_iface->getStc ) {
895      rc = chn->cfg.audio_iface->getStc(chn->cfg.aux_transport, chn->cfg.audio, stc);
896      if (rc==BERR_SUCCESS) { return true; }
897    }
898    if (chn->cfg.video && chn->video_state!=BPCRlib_Decoder_State_eWaitingSTC && chn->cfg.video_iface->getStc) {
899      rc = chn->cfg.video_iface->getStc(chn->cfg.aux_transport, chn->cfg.video, stc);
900      if (rc==BERR_SUCCESS) { return true; }
901    }
902    return false;
903}
904
905#if defined (B_HAS_IP) && defined (BCHP_7411_VER)
906/* 7411 regs */
907#define TS_DISCONT_CNT  0x00100458
908#define TS_PCR_CHANGED  0x00100448
909#define TS_TSM_CONFIG   0x00100540
910
911static BPCRlib_Channel
912find_by_decoder_isr(BPCRlib_Handle handle, void *decoder)
913{
914    BPCRlib_Channel chn;
915    BDBG_ASSERT(decoder);
916    for(chn=BLST_D_FIRST(&handle->list);chn;chn=BLST_D_NEXT(chn,link)) {
917        if (chn->cfg.audio==decoder || chn->cfg.secondary_audio==decoder || chn->cfg.tertiary_audio==decoder) {
918            /* we exploit fact that audio and secondary audio can't be shared */
919            goto found;
920        }
921        else if (chn->cfg.video==decoder) {
922            goto found;
923        }
924    }
925    BDBG_WRN(("Unknown decoder channel %#x", (unsigned)decoder));
926found:
927    return chn;
928}
929
930BERR_Code
931BPCRlib_HasPcrDisco(
932    BPCRlib_Handle handle, /* [in] PCRlib channel handle */
933    void *decoder, /* [in] decoder handle */
934    bool *has_disco
935    )
936{
937    BERR_Code rc = BERR_SUCCESS;
938    uint32_t val;
939    uint32_t reg;
940    BARC_ChannelHandle hArcCh;
941    BPCRlib_Channel chn = find_by_decoder_isr(handle, decoder);
942
943    if (!chn)
944        return BERR_TRACE(BERR_INVALID_PARAMETER);
945
946    hArcCh = (BARC_ChannelHandle)(chn->cfg.video_iface->useAuxTrp?chn->cfg.aux_transport:chn->pcr);
947    reg = TS_DISCONT_CNT;
948    val = BARC_Reg_Read32_isr(hArcCh->hArc, reg);
949    if(val != 0) {
950        *has_disco = true;
951        BARC_Reg_Write32_isr(hArcCh->hArc, reg, 0);
952    }
953    else {
954        *has_disco = false;
955    }
956
957    return rc;
958}
959
960static BERR_Code
961b_os_control_isr(const BPCRlib_Channel chn, bool use_aux_trp)
962{
963    BERR_Code rc=BERR_SUCCESS;
964    uint32_t val;
965    uint32_t reg;
966    BARC_ChannelHandle  hArcCh = (BARC_ChannelHandle)(use_aux_trp?chn->cfg.aux_transport:chn->pcr);
967
968    /* OS - PCR_Offset Supression control */
969    switch(chn->theOS_control_state) {
970    case OS_control_idle:
971        chn->OS_bit = 1;
972        chn->error_count++;
973        if(chn->error_count > 10) {
974            chn->error_count = 0;
975            chn->OS_bit = 0;
976            /*  read it to clear the value */
977            reg = TS_PCR_CHANGED;
978            val = BARC_Reg_Read32_isr(hArcCh->hArc, reg);
979            BDBG_MSG(("@@@ TS_PCR_CHANGED: %#x <- %#x (OS_control_idle state)", (unsigned)reg, (unsigned)val));
980            chn->theOS_control_state = OS_control_waiting_for_pcr;
981        }
982        break;
983    case OS_control_waiting_for_pcr:
984        /* Really we need a "one shot", ie let only one PCR through (the first one encountered
985          in the stream after startup/disco event) */
986        reg = TS_PCR_CHANGED;
987        val = BARC_Reg_Read32_isr(hArcCh->hArc, reg);
988        BDBG_MSG(("@@@ TS_PCR_CHANGED: %#x <- %#x (OS_control_waiting_for_pcr state)", (unsigned)reg, (unsigned)val));
989        if(val) {
990            chn->error_count = 0;
991            chn->OS_bit = 1;
992            chn->theOS_control_state = OS_control_idle;
993        }
994        break;
995    }
996    reg = TS_TSM_CONFIG;
997    val = BARC_Reg_Read32_isr(hArcCh->hArc, reg);
998    if(chn->OS_bit) {
999        val |= 0x00000001;
1000    }
1001    else {
1002        val &= ~0x00000001;
1003    }
1004    BDBG_MSG(("TS_TSM_CONFIG: %#x <- %#x\n", (unsigned)reg, (unsigned)val));
1005    BARC_Reg_Write32_isr(hArcCh->hArc, reg, val);
1006
1007    return rc;
1008}
1009
1010static BERR_Code
1011b_update_stc_isr(const BPCRlib_Channel chn, bool is_request_stc)
1012{
1013    BERR_Code rc=BERR_SUCCESS;
1014
1015    if(chn->cfg.is_playback_ip) {
1016    if (chn->cfg.video && chn->cfg.video_iface->updateStc) {
1017        rc = b_os_control_isr(chn, chn->cfg.video_iface->useAuxTrp);
1018        if (rc!=BERR_SUCCESS) { BDBG_ERR(("b_os_control_isr() returned error %#x, ignored", rc)); }
1019        rc = chn->cfg.video_iface->updateStc(chn->cfg.video_iface->useAuxTrp?chn->cfg.aux_transport:chn->pcr, is_request_stc);
1020        if (rc!=BERR_SUCCESS) { BDBG_ERR(("video updateStc returned error %#x, ignored", rc)); }
1021    }
1022    else if (chn->cfg.audio && chn->cfg.audio_iface->updateStc) {
1023        rc = b_os_control_isr(chn, chn->cfg.audio_iface->useAuxTrp);
1024        if (rc!=BERR_SUCCESS) { BDBG_ERR(("b_os_control_isr() returned error %#x, ignored", rc)); }
1025        rc = chn->cfg.audio_iface->updateStc(chn->cfg.audio_iface->useAuxTrp?chn->cfg.aux_transport:chn->pcr, is_request_stc);
1026        if (rc!=BERR_SUCCESS) { BDBG_ERR(("audio updateStc returned error %#x, ignored", rc)); }
1027    }
1028    if (chn->cfg.secondary_audio && chn->cfg.secondary_audio_iface->updateStc) {
1029        rc = b_os_control_isr(chn, chn->cfg.secondary_audio_iface->useAuxTrp);
1030        if (rc!=BERR_SUCCESS) { BDBG_ERR(("b_os_control_isr() returned error %#x, ignored", rc)); }
1031        rc = chn->cfg.secondary_audio_iface->updateStc(chn->cfg.secondary_audio_iface->useAuxTrp?chn->cfg.aux_transport:chn->pcr, is_request_stc);
1032        if (rc!=BERR_SUCCESS) { BDBG_ERR(("audio updateStc returned error %#x, ignored", rc)); }
1033    }
1034    if (chn->cfg.tertiary_audio && chn->cfg.tertiary_audio_iface->updateStc) {
1035        rc = b_os_control_isr(chn, chn->cfg.tertiary_audio_iface->useAuxTrp);
1036        if (rc!=BERR_SUCCESS) { BDBG_ERR(("b_os_control_isr() returned error %#x, ignored", rc)); }
1037        rc = chn->cfg.tertiary_audio_iface->updateStc(chn->cfg.tertiary_audio_iface->useAuxTrp?chn->cfg.aux_transport:chn->pcr, is_request_stc);
1038        if (rc!=BERR_SUCCESS) { BDBG_ERR(("audio updateStc returned error %#x, ignored", rc)); }
1039    }
1040    }
1041    else {
1042        if (chn->cfg.video && chn->cfg.video_iface->updateStc) {
1043            rc = chn->cfg.video_iface->updateStc(chn->cfg.video_iface->useAuxTrp?chn->cfg.aux_transport:chn->pcr, is_request_stc);
1044            if (rc!=BERR_SUCCESS) { BDBG_ERR(("video updateStc returned error %#x, ignored", rc)); }
1045        }
1046        else if (chn->cfg.audio && chn->cfg.audio_iface->updateStc) {
1047            rc = chn->cfg.audio_iface->updateStc(chn->cfg.audio_iface->useAuxTrp?chn->cfg.aux_transport:chn->pcr, is_request_stc);
1048            if (rc!=BERR_SUCCESS) { BDBG_ERR(("audio updateStc returned error %#x, ignored", rc)); }
1049        }
1050        if (chn->cfg.secondary_audio && chn->cfg.secondary_audio_iface->updateStc) {
1051            rc = chn->cfg.secondary_audio_iface->updateStc(chn->cfg.secondary_audio_iface->useAuxTrp?chn->cfg.aux_transport:chn->pcr, is_request_stc);
1052            if (rc!=BERR_SUCCESS) { BDBG_ERR(("audio updateStc returned error %#x, ignored", rc)); }
1053        }
1054        if (chn->cfg.tertiary_audio && chn->cfg.tertiary_audio_iface->updateStc) {
1055            rc = chn->cfg.tertiary_audio_iface->updateStc(chn->cfg.tertiary_audio_iface->useAuxTrp?chn->cfg.aux_transport:chn->pcr, is_request_stc);
1056            if (rc!=BERR_SUCCESS) { BDBG_ERR(("audio updateStc returned error %#x, ignored", rc)); }
1057        }
1058    }
1059
1060    return rc;
1061}
1062#else
1063/* 20060630 bandrews - this is going to get ugly... more hacks */
1064static BERR_Code
1065b_really_update_stc_isr(const BPCRlib_Channel chn, bool is_request_stc)
1066{
1067    BERR_Code rc=BERR_SUCCESS;
1068
1069    if (chn->cfg.video && chn->cfg.video_iface->updateStc) {
1070        rc = chn->cfg.video_iface->updateStc(chn->cfg.video_iface->useAuxTrp?chn->cfg.aux_transport:chn->pcr, is_request_stc);
1071        if (rc!=BERR_SUCCESS) { BDBG_ERR(("video updateStc returned error %#x, ignored", rc)); }
1072    }
1073    if (chn->cfg.audio && chn->cfg.audio_iface->updateStc) {
1074        rc = chn->cfg.audio_iface->updateStc(chn->cfg.audio_iface->useAuxTrp?chn->cfg.aux_transport:chn->pcr, is_request_stc);
1075        if (rc!=BERR_SUCCESS) { BDBG_ERR(("audio updateStc returned error %#x, ignored", rc)); }
1076    }
1077    if (chn->cfg.secondary_audio && chn->cfg.secondary_audio_iface->updateStc) {
1078        rc = chn->cfg.secondary_audio_iface->updateStc(chn->cfg.secondary_audio_iface->useAuxTrp?chn->cfg.aux_transport:chn->pcr, is_request_stc);
1079        if (rc!=BERR_SUCCESS) { BDBG_ERR(("audio updateStc returned error %#x, ignored", rc)); }
1080    }
1081    if (chn->cfg.tertiary_audio && chn->cfg.tertiary_audio_iface->updateStc) {
1082        rc = chn->cfg.tertiary_audio_iface->updateStc(chn->cfg.tertiary_audio_iface->useAuxTrp?chn->cfg.aux_transport:chn->pcr, is_request_stc);
1083        if (rc!=BERR_SUCCESS) { BDBG_ERR(("audio updateStc returned error %#x, ignored", rc)); }
1084    }
1085
1086    return rc;
1087}
1088static BERR_Code
1089b_update_stc_isr(const BPCRlib_Channel chn, void * requestor, bool is_request_stc)
1090{
1091    BERR_Code rc=BERR_SUCCESS;
1092
1093    /*
1094        20060630 bandrews -
1095        if video requests -> update video, primary audio, and secondary audio
1096        if primary audio requests -> update video, primary audio, and secondary audio
1097        if secondary audio requests -> update secondary audio only
1098    */
1099    if (requestor == chn->cfg.video || requestor == chn->cfg.audio)
1100    {
1101        rc = b_really_update_stc_isr(chn, is_request_stc);
1102    }
1103    else /* secondary or tertiary audio */
1104    {
1105        if ( requestor == chn->cfg.secondary_audio )
1106        {
1107            if (chn->cfg.secondary_audio && chn->cfg.secondary_audio_iface->updateStc) {
1108                rc = chn->cfg.secondary_audio_iface->updateStc(chn->cfg.secondary_audio_iface->useAuxTrp?chn->cfg.aux_transport:chn->pcr, is_request_stc);
1109                if (rc!=BERR_SUCCESS) { BDBG_ERR(("audio updateStc returned error %#x, ignored", rc)); }
1110            }
1111        }
1112        else /* tertiary */
1113        {
1114            if (chn->cfg.tertiary_audio && chn->cfg.tertiary_audio_iface->updateStc) {
1115                rc = chn->cfg.tertiary_audio_iface->updateStc(chn->cfg.tertiary_audio_iface->useAuxTrp?chn->cfg.aux_transport:chn->pcr, is_request_stc);
1116                if (rc!=BERR_SUCCESS) { BDBG_ERR(("audio updateStc returned error %#x, ignored", rc)); }
1117            }
1118        }
1119    }
1120
1121    return rc;
1122}
1123#endif
1124
1125static BERR_Code
1126b_load_delayed_stc_isr(BPCRlib_Channel chn, void *requestor)
1127{
1128    BERR_Code rc=BERR_SUCCESS;
1129    uint32_t cur_stc;
1130    uint32_t stc;
1131    BSTD_UNUSED(requestor);
1132
1133    switch(chn->delayed_stc.state) {
1134    case delayed_stc_eInvalid:
1135        BDBG_WRN(("b_load_delayed_stc_isr: %#lx(%#lx) ignored, STC is not avaliable yet", (unsigned long)chn, (unsigned long)requestor));
1136        break;
1137    case delayed_stc_eLocked:
1138    case delayed_stc_eWaiting:
1139#if B_PCRLIB_HAS_PCROFFSET
1140        cur_stc = BXPT_PcrOffset_GetStc_isr(chn->cfg.aux_transport) + BXPT_PcrOffset_GetOffset_isr(chn->cfg.aux_transport);
1141#else
1142        rc = BXPT_PCR_GetStc_isr(chn->pcr, &cur_stc, &stc /* not used */ );
1143#endif
1144        stc = chn->delayed_stc.stc + (cur_stc - chn->delayed_stc.old_stc);
1145        BDBG_WRN(("b_load_delayed_stc_isr: %#lx(%#lx) loading STC %#x (%u + %d)", (unsigned long)chn, (unsigned long)requestor, (unsigned)stc, (unsigned)chn->delayed_stc.stc, (int)(cur_stc - chn->delayed_stc.old_stc)));
1146        rc = b_send_stc_isr(chn, stc, requestor);
1147        /* update delayed_stc, so following  call to b_load_delayed_stc_isr would not use stale values */
1148        chn->delayed_stc.stc = stc;
1149        chn->delayed_stc.old_stc = cur_stc;
1150        chn->delayed_stc.state = delayed_stc_eLocked;
1151        break;
1152    }
1153    return rc;
1154}
1155
1156
1157
1158static bool
1159BPCRlib_TestAudioStc_isr(BPCRlib_Channel chn, uint32_t new_stc, uint32_t pts)
1160{
1161    int32_t delta;
1162    bool dss = b_is_dss_isr(&chn->cfg);
1163
1164    delta = BPCRlib_StcDiff_isr(dss, new_stc, pts);
1165
1166    if (
1167    /* TODO: does this need dss qualification?  3003 is an MPEG number */
1168        (delta >= 0 && delta < (2*chn->cfg.audio_pts_offset + (3003 * 5)/(2*2))) ||
1169        (delta < 0 && delta > -(2*chn->cfg.audio_pts_offset + (3003 * 60 )/(2*2)))
1170    ) /* video STC could be  0.15 sec ahead or 1.0 sec behind of PTS */
1171    {
1172        BDBG_MSG(("TestAudioStc: STC %#x PTS %#x delta %ld (%s)", new_stc, pts, delta, "good"));
1173        return true;
1174    } else {
1175        BDBG_MSG(("TestAudioStc: STC %#x PTS %#x delta %ld (%s)", new_stc, pts, delta, "bad"));
1176        return false;
1177    }
1178}
1179
1180static bool
1181BPCRlib_P_GetStcFromPcr_isr(BPCRlib_Channel chn, uint32_t pts, uint32_t *new_stc)
1182{
1183    int32_t delta;
1184    int32_t offset;
1185    unsigned i;
1186    bool dss = b_is_dss_isr(&chn->cfg);
1187   
1188    if (!chn->pcr_offset.last_pcr_valid) {
1189        return false;
1190    }
1191    if (chn->pcr_offset.count==0) {
1192        delta = BPCRlib_StcDiff_isr(dss, pts, chn->pcr_offset.last_pcr);
1193        BDBG_WRN(("[pcr init]%s use PCR:  %#x %#x %d", delta<0?" can't":"", (unsigned)pts, (unsigned)chn->pcr_offset.last_pcr, (int)delta));
1194        if (delta<0) {
1195            return false;
1196        }
1197#if BCHP_CHIP == 7401
1198        if (dss)
1199        {
1200            *new_stc = chn->pcr_offset.last_pcr - chn->cfg.pcr_offset * 600;
1201        }
1202        else
1203#endif
1204        {
1205            *new_stc = chn->pcr_offset.last_pcr - chn->cfg.pcr_offset;
1206        }
1207        chn->pcr_offset.last_pcr_valid = false; /* use own PCR not more than one time */
1208        return true;
1209    }
1210    if(chn->pcr_offset.pcr_offset_valid) {
1211        bool stc_valid;
1212        uint32_t stc;
1213
1214        chn->pcr_offset.pcr_offset_valid=false;
1215        stc_valid = b_read_stc_isr(chn, &stc);
1216        if (stc_valid) {
1217            *new_stc = stc + chn->pcr_offset.pcr_offset;
1218            BDBG_WRN(("use PCR offset %d: PTS %#x PCR %#x old_STC %#x new_STC %#x", (int)chn->pcr_offset.pcr_offset, (unsigned)pts, (unsigned)chn->pcr_offset.last_pcr, (unsigned)stc, (unsigned)*new_stc));
1219            return true;
1220        }
1221    }
1222    for(offset=0,i=0;i<chn->pcr_offset.count;i++) {
1223        offset += chn->pcr_offset.pcr_fifo[i];
1224    }
1225    offset /= chn->pcr_offset.count;
1226    BDBG_MSG(("[pcr offset] median offset:  %d", (int)offset));
1227    if (2*offset > chn->cfg.pcr_offset) {
1228        offset -= (chn->cfg.pcr_offset/4); /* decresed buffer fullness a little bit */
1229    }
1230#if BCHP_CHIP==7401
1231    if (dss)
1232    {
1233        *new_stc = chn->pcr_offset.last_pcr - 2 * offset * 600;
1234    }
1235    else
1236#endif
1237    {
1238        *new_stc = chn->pcr_offset.last_pcr - 2 * offset;
1239    }
1240    delta = BPCRlib_StcDiff_isr(dss, pts, *new_stc);
1241    BDBG_WRN(("[pcr offset %d]%s use PCR: PTS %#x PCR %#x STC %#x %d(%d)", 2*offset, (delta*2<chn->cfg.pcr_offset)?""/*can't"*/:"", (unsigned)pts, (unsigned)chn->pcr_offset.last_pcr, (unsigned)*new_stc, (int)delta*2, (int)chn->cfg.pcr_offset));
1242#if 0
1243    if (delta*2<chn->cfg.pcr_offset) {
1244        return false;
1245    }
1246#endif
1247    return true;
1248}
1249
1250static bool
1251BPCRlib_TestVideoStc_isr(BPCRlib_Channel chn, uint32_t new_stc, uint32_t pts)
1252{
1253    int32_t delta;
1254    bool dss = b_is_dss_isr(&chn->cfg);
1255
1256    delta = BPCRlib_StcDiff_isr(dss, new_stc, pts);
1257
1258    if (
1259    /* TODO: does this need dss qualification?  3003 is an MPEG number */
1260        (delta >= 0 && delta < (chn->cfg.video_pts_offset + (3003 * 5)/(2*2))) ||
1261        (delta < 0 && delta > -(chn->cfg.video_pts_offset + (3003 * 60)/(2*2)))
1262    ) /* audio STC could be  0.15 sec ahead or 1.0 sec behind of PTS */
1263    {
1264        BDBG_MSG(("TestVideoStc: STC %#x PTS %#x delta %ld (%s)", new_stc, pts, delta, "good"));
1265        return true;
1266    } else {
1267        BDBG_MSG(("TestVideoStc: STC %#x PTS %#x delta %ld (%s)", new_stc, pts, delta, "bad"));
1268        return false;
1269    }
1270}
1271
1272static bool
1273BPCRlib_IsAudioLocked_isr(BPCRlib_Channel chn, uint32_t *locked_stc)
1274{
1275    BERR_Code rc;
1276    BAVC_PTSInfo pts;
1277
1278    if (!chn->cfg.audio) {
1279        return false;
1280    }
1281    BDBG_ASSERT(chn->cfg.audio_iface->getStc);
1282    rc = chn->cfg.audio_iface->getStc(chn->cfg.aux_transport, chn->cfg.audio, locked_stc);
1283    if (rc!=BERR_SUCCESS) {
1284        return false;
1285    }
1286
1287    BDBG_ASSERT(chn->cfg.audio_iface->getPts);
1288    rc = chn->cfg.audio_iface->getPts(chn->cfg.audio, &pts);
1289    if (rc!=BERR_SUCCESS) {
1290        return false;
1291    }
1292    return BPCRlib_TestAudioStc_isr(chn, *locked_stc, pts.ui32CurrentPTS);
1293}
1294
1295static bool
1296BPCRlib_IsVideoLocked_isr(BPCRlib_Channel chn, uint32_t *locked_stc)
1297{
1298    BAVC_PTSInfo pts;
1299    BERR_Code rc;
1300
1301    if (!chn->cfg.video) {
1302        return false;
1303    }
1304    BDBG_ASSERT(chn->cfg.video_iface->getPts);
1305    rc = chn->cfg.video_iface->getPts(chn->cfg.video, &pts);
1306    if (rc!=BERR_SUCCESS) {
1307        return false;
1308    }
1309    if (pts.ePTSType == BAVC_PTSType_eInterpolatedFromInvalidPTS) {
1310        return false;
1311    }
1312    BDBG_ASSERT(chn->cfg.video_iface->getStc);
1313    rc = chn->cfg.video_iface->getStc(chn->cfg.aux_transport, chn->cfg.video, locked_stc);
1314    if (rc!=BERR_SUCCESS) {
1315        return false;
1316    }
1317    return BPCRlib_TestVideoStc_isr(chn, *locked_stc, pts.ui32CurrentPTS);
1318}
1319
1320static bool
1321BPCRlib_IsVideoBufferLevel_isr(BPCRlib_Channel chn)
1322{
1323    unsigned cdb_level;
1324    BERR_Code rc;
1325
1326    BDBG_ASSERT(chn->cfg.video_iface->getCdbLevel);
1327    rc = chn->cfg.video_iface->getCdbLevel(chn->cfg.video, &cdb_level);
1328    if (rc!=BERR_SUCCESS) {
1329        BDBG_WRN(("Video buffer level request has returned error %d", cdb_level));
1330        return false;
1331    }
1332    BDBG_MSG(("video VBV %u(%d)", cdb_level, chn->cfg.video_cdb_level));
1333    return cdb_level > 96 * 1024; /* if there is more then 96KBytes in the VBV bufffer, video is just fine with STC */
1334}
1335
1336#if 0
1337static bool
1338BPCRlib_IsAudioBufferLevel_isr(BPCRlib_Channel chn)
1339{
1340    unsigned cdb_level;
1341    BERR_Code rc;
1342
1343    rc = chn->cfg.audio_iface->getCdbLevel(chn->cfg.audio, &cdb_level);
1344    if (rc!=BERR_SUCCESS) {
1345        BDBG_WRN(("Audio buffer level request has returned error %d", cdb_level));
1346        return false;
1347    }
1348    BDBG_MSG(("audio CDB %u(%d)", cdb_level, chn->cfg.audio_cdb_level));
1349    return cdb_level > 1 * 1024; /* if there is more then 1KBytes in the CDB bufffer, audio is just fine with STC */
1350}
1351#endif
1352
1353static BPCRlib_TsmMode BPCRlib_Channel_GetTsmMode(BPCRlib_Channel chn)
1354{
1355    switch (chn->cfg.tsm_mode) {
1356    case BPCRlib_TsmMode_eVideoMaster:
1357        if (!chn->cfg.paired && !chn->cfg.video) {
1358            return BPCRlib_TsmMode_eSTCMaster;
1359        }
1360        break;
1361    case BPCRlib_TsmMode_eAudioMaster:
1362        if (!chn->cfg.paired && !chn->cfg.audio && !chn->cfg.secondary_audio && !chn->cfg.tertiary_audio) {
1363            return BPCRlib_TsmMode_eSTCMaster;
1364        }
1365        break;
1366    default:
1367        break;
1368    }
1369    return chn->cfg.tsm_mode;
1370}
1371
1372BERR_Code
1373BPCRlib_Channel_AudioRequestStc_isr(BPCRlib_Handle handle, void *audio, uint32_t audio_pts)
1374{
1375    BPCRlib_Channel chn = find_by_audio_isr(handle, audio);
1376    BERR_Code rc = BERR_SUCCESS;
1377    bool dss = false;
1378   
1379    if (!chn) {
1380        return BERR_TRACE(BERR_INVALID_PARAMETER);
1381    }
1382    BDBG_MSG(("(%#x) AudioRequestStc(%#x) PTS %#x %s", (unsigned)chn, (unsigned)audio, (unsigned)audio_pts, chn->cfg.playback?"Playback":""));
1383    dss = b_is_dss_isr(&chn->cfg);
1384    if (chn->cfg.playback) {
1385        if (chn->cfg.mode == BPCRlib_Mode_eConstantDelay) {
1386            return b_load_delayed_stc_isr(chn, audio);
1387        }
1388
1389#if 0
1390        /* invalidation state */
1391        if (chn->audio_state == BPCRlib_Decoder_State_eInvalidated)
1392        {
1393            if (chn->cfg.video)
1394            {
1395                BAVC_PTSInfo pts;
1396                int32_t pts_diff;
1397                uint32_t new_stc = 0;
1398                BDBG_ASSERT(chn->cfg.video_iface->getPts);
1399                rc = chn->cfg.video_iface->getPts(chn->cfg.video, &pts);
1400                if (rc!=BERR_SUCCESS) {
1401                    return rc;
1402                }
1403                if (pts.ePTSType == BAVC_PTSType_eInterpolatedFromInvalidPTS) {
1404                    return rc;
1405                }
1406
1407                /* master mode exception: take the lower of audio or video PTS at this point
1408                this only happens when we've been invalidated */
1409                pts_diff = (int32_t)(audio_pts - pts.ui32CurrentPTS);
1410                if (pts_diff < 0)
1411                {
1412                    new_stc = audio_pts - chn->cfg.audio_pts_offset;
1413                }
1414                else
1415                {
1416                    new_stc = pts.ui32CurrentPTS - chn->cfg.video_pts_offset;
1417                }
1418
1419                BDBG_MSG(("AudioRequestStc(%#x): [invalidated] using lowest PTS %#x as new STC", (unsigned)audio, new_stc));
1420
1421                chn->video_state = BPCRlib_Decoder_State_eLocked;
1422                chn->audio_state = BPCRlib_Decoder_State_eLocked;
1423                rc = b_send_stc_isr(chn, new_stc, audio);
1424            }
1425            else /* no video */
1426            {
1427                uint32_t new_stc = 0;
1428
1429                new_stc = audio_pts - chn->cfg.audio_pts_offset;
1430                BDBG_MSG(("AudioRequestStc(%#x): [invalidated, no video] using audio PTS %#x as new STC", (unsigned)audio, new_stc));
1431                chn->video_state = BPCRlib_Decoder_State_eLocked;
1432                chn->audio_state = BPCRlib_Decoder_State_eLocked;
1433                rc = b_send_stc_isr(chn, new_stc, audio);
1434            }
1435        }
1436        else
1437#endif
1438        {
1439            switch (BPCRlib_Channel_GetTsmMode(chn))
1440            {
1441                case BPCRlib_TsmMode_eVideoMaster:
1442
1443                    if (chn->video_state != BPCRlib_Decoder_State_eWaitingSTC && chn->video_state != BPCRlib_Decoder_State_eInvalidated && chn->cfg.video)
1444                    {
1445                        uint32_t new_stc = 0;
1446
1447                        if (chn->video_state != BPCRlib_Decoder_State_eNotLocked)
1448                        {
1449                            if (BPCRlib_IsVideoLocked_isr(chn, &new_stc))
1450                            {
1451                                BDBG_MSG(("AudioRequestStc(%#x): Video master mode -> using video STC %#x as new STC", (unsigned)audio, new_stc));
1452                            }
1453                            else
1454                            {
1455                                BDBG_MSG(("AudioRequestStc(%#x): [video not locked] Video master mode -> awaiting video request", (unsigned)audio));
1456                                goto no_seed;
1457                            }
1458                        }
1459                        else if (BPCRlib_IsVideoLocked_isr(chn, &new_stc) && BPCRlib_IsVideoBufferLevel_isr(chn))
1460                        {
1461                            BDBG_MSG(("AudioRequestStc(%#x): [VBV/Fifo] Video master mode -> using video STC %#x as new STC", (unsigned)audio, new_stc));
1462                        }
1463                        else
1464                        {
1465                            BDBG_MSG(("AudioRequestStc(%#x): [video not locked] Video master mode -> awaiting video request", (unsigned)audio));
1466                            goto no_seed;
1467                        }
1468
1469                        rc = b_send_stc_isr(chn, new_stc, audio);
1470                    }
1471                    else
1472                    {
1473                        BDBG_MSG(("AudioRequestStc(%#x): [video not locked] Video master mode -> awaiting video request", (unsigned)audio));
1474                    }
1475no_seed:
1476                    break;
1477
1478                case BPCRlib_TsmMode_eAudioMaster:
1479
1480                    if (chn->cfg.secondary_audio == audio || chn->cfg.tertiary_audio == audio)
1481                    {
1482                        uint32_t new_stc;
1483#if BDBG_DEBUG_BUILD
1484                        const char *channel_name = (chn->cfg.secondary_audio == audio)?"secondary":"tertiary";
1485#endif
1486
1487                        if (chn->cfg.audio == NULL)
1488                        {
1489                            BDBG_ERR(("(%#x) AudioRequestStc called in audio master mode for %s channel when primary is not set",(unsigned)audio, channel_name));
1490                            return BERR_TRACE(BERR_INVALID_PARAMETER);
1491                        }
1492
1493                        rc = chn->cfg.audio_iface->getStc(chn->cfg.aux_transport, chn->cfg.audio, &new_stc);
1494                        if (rc != BERR_SUCCESS)
1495                        {
1496                            return rc;
1497                        }
1498
1499                        /* if primary audio is locked, use its STC, otherwise, wait for primary audio to lock and load its STC */
1500                        if (chn->audio_state != BPCRlib_Decoder_State_eWaitingSTC && chn->cfg.audio)
1501                        {
1502                            if (chn->audio_state != BPCRlib_Decoder_State_eNotLocked)
1503                            {
1504                                if (BPCRlib_IsAudioLocked_isr(chn, &new_stc))
1505                                {
1506                                    BDBG_MSG(("AudioRequestStc(%#x): Audio master mode -> %s channel, using primary audio STC %#x as new STC", (unsigned)audio, channel_name, new_stc));
1507                                    rc = b_send_stc_isr(chn, new_stc, audio);
1508                                }
1509                            }
1510                            else if (BPCRlib_IsAudioLocked_isr(chn, &new_stc))
1511                            {
1512                                BDBG_MSG(("AudioRequestStc(%#x): [CDB/Fifo] Audio master mode -> %s channel, using primary audio STC %#x as new STC", (unsigned)audio, channel_name, new_stc));
1513                                rc = b_send_stc_isr(chn, new_stc, audio);
1514                            }
1515                        }
1516                        else
1517                        {
1518                            BDBG_MSG(("AudioRequestStc(%#x): Audio master mode -> %s channel request before primary channel request, ignored", (unsigned)audio, channel_name));
1519                        }
1520                    }
1521                    else
1522                    {
1523                        uint32_t new_stc = 0;
1524
1525#if 0
1526                        if ((signed)audio_pts - (signed)chn->cfg.audio_pts_offset > 0)
1527                        {
1528                            new_stc = audio_pts - chn->cfg.audio_pts_offset;
1529                        }
1530                        else
1531#endif
1532                        {
1533                            new_stc = audio_pts;
1534                        }
1535                        BDBG_MSG(("AudioRequestStc(%#x): Audio master mode -> using audio PTS %#x as new STC %#x", (unsigned)audio, audio_pts, new_stc));
1536                        BPCRlib_P_InvalidatePCRCache(chn);
1537                        chn->audio_state = BPCRlib_Decoder_State_eLocked;
1538                        rc = b_send_stc_isr(chn, new_stc, audio);
1539                    }
1540
1541                    break;
1542
1543                case BPCRlib_TsmMode_eSTCMaster:
1544                default:
1545
1546                    if (chn->cfg.secondary_audio == audio || chn->cfg.tertiary_audio == audio)
1547                    {
1548                        uint32_t new_stc = 0;
1549#if BDBG_DEBUG_BUILD
1550                        const char *channel_name = (chn->cfg.secondary_audio == audio)?"secondary":"tertiary";
1551#endif
1552
1553                        if (chn->cfg.audio==NULL)
1554                        {
1555                            BDBG_ERR(("(%#x) AudioRequestStc called for %s channel when primary is not set", (unsigned)chn, channel_name));
1556                            return BERR_TRACE(BERR_INVALID_PARAMETER);
1557                        }
1558
1559                        rc = chn->cfg.audio_iface->getStc(chn->cfg.aux_transport, chn->cfg.audio, &new_stc);
1560                        if (rc!=BERR_SUCCESS)
1561                        {
1562                            BDBG_ERR(("AudioRequestStc(%#x): error retrieving STC", (unsigned)audio));
1563                            return rc;
1564                        }
1565
1566                        /* if primary audio is locked, use its STC, otherwise, wait for primary audio to lock and load its STC */
1567                        if (chn->audio_state != BPCRlib_Decoder_State_eWaitingSTC && chn->cfg.audio)
1568                        {
1569                            if (chn->audio_state != BPCRlib_Decoder_State_eNotLocked)
1570                            {
1571    /* PR45126 20081022 bandrews - Don't check if primary audio is locked if pcrlib state says it is */
1572    /*                            if (BPCRlib_IsAudioLocked_isr(chn, &new_stc))*/
1573                                {
1574                                    BDBG_MSG(("AudioRequestStc(%#x): %s channel, using primary audio STC %#x as new STC", (unsigned)audio, channel_name, new_stc));
1575                                    rc = b_send_stc_isr(chn, new_stc, audio);
1576                                }
1577#if 0
1578                                else
1579                                {
1580                                    BDBG_MSG(("AudioRequestStc(%#x): secondary audio channel, primary audio state not eNotLocked, but IsAudioLocked returned false", (unsigned)audio));
1581                                }
1582#endif
1583                            }
1584                            else if (BPCRlib_IsAudioLocked_isr(chn, &new_stc))
1585                            {
1586                                BDBG_MSG(("AudioRequestStc(%#x): [CDB/Fifo] %s channel, using primary audio STC %#x as new STC", (unsigned)audio, channel_name, new_stc));
1587                                b_send_stc_isr(chn, new_stc, audio);
1588                            }
1589                            else
1590                            {
1591                                BDBG_MSG(("AudioRequestStc(%#x): secondary audio channel, primary audio state eNotLocked and IsAudioLocked returned false", (unsigned)audio));
1592                            }
1593                        }
1594                        else
1595                        {
1596                            BDBG_MSG(("AudioRequestStc(%#x): %s channel request before primary channel request, ignored", (unsigned)audio, channel_name));
1597                        }
1598                    }
1599                    else
1600                    {
1601                        uint32_t new_stc = 0;
1602
1603                        if(b_read_stc_isr(chn, &new_stc) && BPCRlib_TestAudioStc_isr(chn, new_stc, audio_pts))
1604                        {
1605                            BDBG_WRN(("AudioRequestStc(%#x): primary audio reusing old STC %#x as new STC", (unsigned)audio, new_stc));
1606                            goto set_stc;
1607                        }
1608                        if (chn->video_state != BPCRlib_Decoder_State_eWaitingSTC && chn->cfg.video)
1609                        {
1610                            if (chn->video_state != BPCRlib_Decoder_State_eNotLocked)
1611                            {
1612                                if (BPCRlib_IsVideoLocked_isr(chn, &new_stc))
1613                                {
1614                                    BDBG_WRN(("AudioRequestStc(%#x): primary audio Using video STC %#x as new STC", (unsigned)audio, new_stc));
1615                                    goto set_stc;
1616                                }
1617                            }
1618                            else if (BPCRlib_IsVideoBufferLevel_isr(chn) && BPCRlib_IsVideoLocked_isr(chn, &new_stc))
1619                            {
1620                                BDBG_WRN(("AudioRequestStc(%#x): primary audio [VBV/Fifo] Using video STC %#x as new STC", (unsigned)audio, new_stc));
1621                                goto set_stc;
1622                            }
1623                        }
1624                        if (BPCRlib_P_GetStcFromPcr_isr(chn, audio_pts, &new_stc) && BPCRlib_TestAudioStc_isr(chn, new_stc, audio_pts))
1625                        {
1626                            BDBG_WRN(("AudioRequestStc(%#x): primary audio Using PCR %#x as new STC %#x", (unsigned)audio, chn->pcr_offset.last_pcr, new_stc));
1627                            BPCRlib_P_InvalidatePCRCache(chn);
1628                            goto set_stc;
1629                        }
1630                        if (chn->cfg.non_real_time)
1631                        {
1632                            new_stc = audio_pts;
1633                        }
1634                        else
1635                        {
1636#if BCHP_CHIP == 7401
1637                            if (dss)
1638                            {
1639                                new_stc = audio_pts - chn->cfg.audio_pts_offset * 600;
1640                            }
1641                            else
1642#endif
1643                            {
1644                                new_stc = audio_pts - chn->cfg.audio_pts_offset;
1645                            }
1646                        }
1647                        BDBG_WRN(("AudioRequestStc(%#x): primary audio Using audio PTS %#x as new STC %#x", (unsigned)audio, audio_pts, new_stc));
1648                        BPCRlib_P_InvalidatePCRCache(chn);
1649    set_stc:
1650                        chn->audio_state = BPCRlib_Decoder_State_eLocked;
1651                        rc = b_send_stc_isr(chn, new_stc, audio);
1652                    }
1653                    break;
1654            } /* switch */
1655        } /* invalidate state */
1656    }
1657    else /* live */
1658    {
1659#if defined (B_HAS_IP) && defined (BCHP_7411_VER)
1660        return b_update_stc_isr(chn, true);
1661#else
1662        return b_update_stc_isr(chn, audio, true);
1663#endif
1664    }
1665
1666    return rc;
1667}
1668
1669
1670BERR_Code
1671BPCRlib_Channel_VideoRequestStc_isr(BPCRlib_Handle handle, void *video, const BAVC_PTSInfo *video_pts)
1672{
1673    BPCRlib_Channel chn = find_by_video_isr(handle, video);
1674    BERR_Code rc = BERR_SUCCESS;
1675    bool dss = false;
1676
1677    BDBG_ASSERT(video_pts);
1678    if (!chn) {
1679        return BERR_TRACE(BERR_INVALID_PARAMETER);
1680    }
1681    BDBG_MSG(("(%#x) VideoRequestStc(%#x) PTS %#x(%d) %s", (unsigned)chn, (unsigned)video, (unsigned)video_pts->ui32CurrentPTS, (int)video_pts->ePTSType, chn->cfg.playback?"Playback":""));
1682    dss = b_is_dss_isr(&chn->cfg);
1683    if (chn->cfg.playback) 
1684    {
1685        uint32_t new_stc = 0;
1686
1687        chn->sVideo.uiConsecutivePtsErrorCount = 0;
1688        chn->sVideo.uiLastDecodedFrameCount = 0;
1689        chn->sVideo.uiLastDroppedFrameCount = 0;
1690
1691        if (chn->cfg.mode == BPCRlib_Mode_eConstantDelay) {
1692            return b_load_delayed_stc_isr(chn, video);
1693        }
1694
1695#if 0
1696        /* invalidation state */
1697        if (chn->video_state == BPCRlib_Decoder_State_eInvalidated)
1698        {
1699            if (chn->cfg.audio)
1700            {
1701                BAVC_PTSInfo pts;
1702                int32_t pts_diff;
1703                uint32_t new_stc = 0;
1704                BDBG_ASSERT(chn->cfg.audio_iface->getPts);
1705                rc = chn->cfg.audio_iface->getPts(chn->cfg.audio, &pts);
1706                if (rc!=BERR_SUCCESS) {
1707                    return rc;
1708                }
1709                if (pts.ePTSType == BAVC_PTSType_eInterpolatedFromInvalidPTS) {
1710                    return rc;
1711                }
1712
1713                /* master mode exception: take the lower of audio or video PTS at this point
1714                this only happens when we've been invalidated */
1715                pts_diff = (int32_t)(video_pts->ui32CurrentPTS - pts.ui32CurrentPTS);
1716                if (pts_diff < 0)
1717                {
1718                    new_stc = video_pts->ui32CurrentPTS - chn->cfg.video_pts_offset;
1719                }
1720                else
1721                {
1722                    new_stc = pts.ui32CurrentPTS - chn->cfg.audio_pts_offset;
1723                }
1724
1725                chn->video_state = BPCRlib_Decoder_State_eLocked;
1726                chn->audio_state = BPCRlib_Decoder_State_eLocked;
1727
1728                BDBG_MSG(("VideoRequestStc(%#x): [invalidated] using lowest PTS %#x as new STC", (unsigned)video, new_stc));
1729                rc = b_send_stc_isr(chn, new_stc, video);
1730            }
1731            else /* no audio */
1732            {
1733                uint32_t new_stc = 0;
1734
1735                new_stc = video_pts->ui32CurrentPTS - chn->cfg.video_pts_offset;
1736                BDBG_MSG(("VideoRequestStc(%#x): [invalidated, no audio] using video PTS %#x as new STC", (unsigned)video, new_stc));
1737                chn->video_state = BPCRlib_Decoder_State_eLocked;
1738                chn->audio_state = BPCRlib_Decoder_State_eLocked;
1739                rc = b_send_stc_isr(chn, new_stc, video);
1740            }
1741        }
1742        else
1743#endif
1744        {
1745            switch (BPCRlib_Channel_GetTsmMode(chn))
1746            {
1747                case BPCRlib_TsmMode_eAudioMaster:
1748
1749                    if (BPCRlib_IsAudioLocked_isr(chn, &new_stc) && chn->audio_state == BPCRlib_Decoder_State_eLocked)
1750                    {
1751                        BDBG_MSG(("VideoRequestStc(%#x): Audio master mode -> using audio STC %#x as new STC", (unsigned)video, new_stc));
1752                        chn->video_state = BPCRlib_Decoder_State_eLocked;
1753                        rc = b_send_stc_isr(chn, new_stc, video);
1754                    }
1755                    else
1756                    {
1757                        BDBG_MSG(("VideoRequestStc(%#x): [audio not locked] Audio master mode -> awaiting audio request", (unsigned)video));
1758                    }
1759                    break;
1760
1761                case BPCRlib_TsmMode_eVideoMaster:
1762
1763                    if (video_pts->ePTSType == BAVC_PTSType_eInterpolatedFromInvalidPTS) {
1764                        BDBG_WRN(("VideoRequestStc(%#x): Video master mode -> interpolated PTS ignored, STC not updated", (unsigned)video));
1765                        chn->video_state = BPCRlib_Decoder_State_eWaitingSTC;
1766                        return BERR_SUCCESS;
1767                    }
1768
1769                    if (chn->cfg.non_real_time)
1770                    {
1771                        new_stc = video_pts->ui32CurrentPTS;
1772                    }
1773                    else
1774                    {
1775#if BCHP_CHIP == 7401
1776                        if (dss)
1777                        {
1778                            new_stc = video_pts->ui32CurrentPTS - chn->cfg.video_pts_offset * 600;
1779                        }
1780                        else
1781#endif
1782                        {
1783                            new_stc = video_pts->ui32CurrentPTS - chn->cfg.video_pts_offset;
1784                        }
1785                    }
1786                    BDBG_WRN(("VideoRequestStc(%#x): Video master mode -> using video PTS %#x as new STC", (unsigned)video, new_stc));
1787                    BPCRlib_P_InvalidatePCRCache(chn);
1788
1789                    chn->video_state = BPCRlib_Decoder_State_eLocked;
1790                    rc = b_send_stc_isr(chn, new_stc, video);
1791                    break;
1792
1793                case BPCRlib_TsmMode_eSTCMaster:
1794                default:
1795
1796                    if (BPCRlib_IsAudioLocked_isr(chn, &new_stc) && chn->audio_state==BPCRlib_Decoder_State_eLocked) {
1797                        int32_t delta;
1798
1799                        delta = BPCRlib_StcDiff_isr(dss, new_stc, video_pts->ui32CurrentPTS);
1800                        /* TODO: 3003 is an MPEG number, needs dssification? */
1801                        /* if audio is more 2 seconds behind video, use video PTS */
1802                        if (delta< (3003 * 2)/(2))
1803                        {
1804                            goto set_video_stc;
1805                        }
1806                        BDBG_WRN(("VideoRequestStc(%#x): Using audio STC %#x as new STC", (unsigned)video, new_stc));
1807                        goto set_stc;
1808                    }
1809
1810                    if (video_pts->ePTSType == BAVC_PTSType_eInterpolatedFromInvalidPTS) {
1811                        if (chn->cfg.audio) {
1812                            rc = chn->cfg.audio_iface->getStc(chn->cfg.aux_transport, chn->cfg.audio, &new_stc);
1813                            if (rc==BERR_SUCCESS) {
1814                                BDBG_WRN(("VideoRequestStc(%#x): Interpolated PTS ignored, using audio STC %#x", (unsigned)video, new_stc));
1815                                goto set_stc;
1816                            }
1817                        }
1818                        BDBG_WRN(("VideoRequestStc(%#x): Interpolated PTS ignored, STC not updated", (unsigned)video));
1819                        chn->video_state = BPCRlib_Decoder_State_eWaitingSTC;
1820                        return BERR_SUCCESS;
1821                    }
1822                    if(b_read_stc_isr(chn, &new_stc) && BPCRlib_TestVideoStc_isr(chn, new_stc, video_pts->ui32CurrentPTS)) {
1823                        BDBG_WRN(("VideoRequestStc(%#x): reusing old STC %#x as new STC", (unsigned)video, new_stc));
1824                        goto set_stc;
1825                    }
1826                    if (BPCRlib_P_GetStcFromPcr_isr(chn, video_pts->ui32CurrentPTS, &new_stc)
1827                            /* && BPCRlib_TestVideoStc_isr(chn, new_stc, video_pts->ui32CurrentPTS)*/
1828                        ) {
1829                        BDBG_WRN(("VideoRequestStc(%#x): Using PCR %#x as new STC %#x", (unsigned)video, chn->pcr_offset.last_pcr, new_stc));
1830                        BPCRlib_P_InvalidatePCRCache(chn);
1831                        goto set_stc;
1832                    }
1833    set_video_stc:
1834                    if (chn->cfg.non_real_time)
1835                    {
1836                        new_stc = video_pts->ui32CurrentPTS;
1837                    }
1838                    else
1839                    {
1840#if BCHP_CHIP == 7401
1841                        if (dss)
1842                        {
1843                            new_stc = video_pts->ui32CurrentPTS - chn->cfg.video_pts_offset * 600;
1844                        }
1845                        else
1846#endif
1847                        {
1848                            new_stc = video_pts->ui32CurrentPTS - chn->cfg.video_pts_offset;
1849                        }
1850                    }
1851                    BDBG_WRN(("VideoRequestStc(%#x): Using video PTS %#x as new STC", (unsigned)video, new_stc));
1852                    BPCRlib_P_InvalidatePCRCache(chn);
1853    set_stc:
1854                    chn->video_state = BPCRlib_Decoder_State_eLocked;
1855                    rc = b_send_stc_isr(chn, new_stc, video);
1856                    break;
1857
1858            } /* switch */
1859        } /* invalidation state */
1860    }
1861    else
1862    {
1863#if defined (B_HAS_IP) && defined (BCHP_7411_VER)
1864        return b_update_stc_isr(chn, true);
1865#else
1866        return b_update_stc_isr(chn, video, true);
1867#endif
1868    }
1869    return rc;
1870}
1871
1872BERR_Code
1873BPCRlib_Channel_VideoPtsError_isr( BPCRlib_Handle handle, void *video, const BAVC_PTSInfo *video_pts, uint32_t video_stc)
1874{
1875    BPCRlib_Channel chn = find_by_video_isr(handle, video);
1876    BERR_Code rc = BERR_SUCCESS;
1877    unsigned cdb_level;
1878    int pts_offset;
1879    bool dss = false;
1880
1881    BDBG_ASSERT(video_pts);
1882
1883    if (!chn) {
1884        return BERR_TRACE(BERR_INVALID_PARAMETER);
1885    }
1886    dss = b_is_dss_isr(&chn->cfg);
1887    BDBG_MSG(("(%#x) VideoPtsError(%#x) PTS %#x(%d) STC %#x %d %s %u", (unsigned)chn, (unsigned)video, (unsigned)video_pts->ui32CurrentPTS, (int)video_pts->ePTSType, (unsigned)video_stc,  2*BPCRlib_StcDiff_isr(dss, video_stc, video_pts->ui32CurrentPTS), chn->cfg.playback?"Playback":"", chn->cfg.video_iface->getCdbLevel?chn->cfg.video_iface->getCdbLevel(chn->cfg.video, &cdb_level),cdb_level:0));
1888    if (chn->cfg.playback) {
1889        uint32_t new_stc;
1890
1891        if (chn->cfg.mode == BPCRlib_Mode_eConstantDelay) {
1892            if(chn->delayed_stc.state==delayed_stc_eWaiting) {
1893                return b_load_delayed_stc_isr(chn, video);
1894            } else {
1895                return BERR_SUCCESS;
1896            }
1897        }
1898
1899        if (video_pts->ePTSType == BAVC_PTSType_eInterpolatedFromInvalidPTS) {
1900            BDBG_MSG(("Interpolated PTS, ignored"));
1901            return BERR_SUCCESS;
1902        }
1903
1904#if 0
1905        if (chn->video_state == BPCRlib_Decoder_State_eWaitingSTC)
1906        {
1907            chn->video_state = BPCRlib_Decoder_State_eInvalidated;
1908            BDBG_MSG(("Invalidated -> converting PTS error to request STC"));
1909            /* we've been invalidated, and we need to treat this pts error as request stc */
1910            return BPCRlib_Channel_VideoRequestStc_isr(chn->parent, video, video_pts);
1911        }
1912#endif
1913
1914        switch (BPCRlib_Channel_GetTsmMode(chn))
1915        {
1916            case BPCRlib_TsmMode_eOutputMaster:
1917            case BPCRlib_TsmMode_eAudioMaster:
1918
1919                return rc;
1920                break;
1921
1922            case BPCRlib_TsmMode_eVideoMaster:
1923
1924                pts_offset = chn->cfg.video_pts_offset;
1925                if (chn->cfg.video_iface->getCdbLevel && chn->cfg.video_iface->getCdbLevel(chn->cfg.video, &cdb_level)==BERR_SUCCESS && cdb_level > chn->cfg.video_cdb_level) {
1926                    pts_offset = 0;
1927                }
1928#if BCHP_CHIP == 7401
1929                if (dss)
1930                {
1931                    new_stc = video_pts->ui32CurrentPTS - pts_offset * 600;
1932                }
1933                else
1934#endif
1935                {
1936                    new_stc = video_pts->ui32CurrentPTS - pts_offset;
1937                }
1938                BDBG_MSG(("VideoPtsError(%#x): Using video PTS %#x[%d] as new STC %#x (old %#x)", (unsigned)video, (unsigned)video_pts->ui32CurrentPTS, (int)pts_offset, (unsigned)new_stc, (unsigned)video_stc));
1939
1940                rc = b_send_stc_isr(chn, new_stc, video);
1941                chn->video_state = BPCRlib_Decoder_State_eLocked;
1942
1943                break;
1944
1945            case BPCRlib_TsmMode_eSTCMaster:
1946            default:
1947
1948#if 1
1949                /* 20070920 bandrews - added to detect DM-unrecoverable video error condition */
1950                if ((signed)video_pts->ui32CurrentPTS - (signed)video_stc > chn->cfg.video_stc_discard)
1951                {
1952                    BDBG_WRN(("Video STC/PTS difference outside of discard threshold"));
1953                    BDBG_MSG(("Last decoded frame count: %d; Current decoded frame count: %d", chn->sVideo.uiLastDecodedFrameCount, video_pts->uiDecodedFrameCount));
1954                    if (chn->sVideo.uiLastDecodedFrameCount && chn->sVideo.uiLastDecodedFrameCount == video_pts->uiDecodedFrameCount - 1)
1955                    {
1956                        BDBG_MSG(("Last dropped frame count: %d; Current dropped frame count: %d", chn->sVideo.uiLastDroppedFrameCount, video_pts->uiDroppedFrameCount));
1957                        /* no frames have been decoded by this channel between errors */
1958                        if (chn->sVideo.uiLastDroppedFrameCount < video_pts->uiDroppedFrameCount)
1959                        {
1960                            /* frames have been dropped by this channel between errors */
1961                            chn->sVideo.uiConsecutivePtsErrorCount++;
1962                            BDBG_MSG(("Consecutive PTS errors detected: %d", chn->sVideo.uiConsecutivePtsErrorCount));
1963                        }
1964                    }
1965                    else
1966                    {
1967                        /* set the error count to 1 on the first one after a series of good frames, since we are looking
1968                        for consecutive errors */
1969                        chn->sVideo.uiConsecutivePtsErrorCount = 1;
1970                        BDBG_MSG(("Consecutive PTS errors detected: %d", chn->sVideo.uiConsecutivePtsErrorCount));
1971                    }
1972
1973                    /* update the frame counters */
1974                    chn->sVideo.uiLastDecodedFrameCount = video_pts->uiDecodedFrameCount;
1975                    chn->sVideo.uiLastDroppedFrameCount = video_pts->uiDroppedFrameCount;
1976
1977                    if (chn->sVideo.uiConsecutivePtsErrorCount >= chn->cfg.consecutive_pts_error_limit)
1978                    {
1979                        BDBG_WRN(("Consecutive PTS error count reached"));
1980                        /* clear the error counter */
1981                        chn->sVideo.uiConsecutivePtsErrorCount = 0;
1982                        /* we have reached a DM-unrecoverable error, reseed STC with video PTS */
1983                        goto set_stc_from_pts;
1984                    }
1985                }
1986#endif
1987
1988                /* first test if PTS-STC is inside tracking range */
1989                if (BPCRlib_TestVideoStc_isr(chn, video_stc, video_pts->ui32CurrentPTS)) {
1990                    int32_t stc_delta;
1991
1992                    stc_delta=BPCRlib_StcDiff_isr(dss, video_stc, video_pts->ui32CurrentPTS);
1993                    if (stc_delta>0 && chn->cfg.video_iface->getCdbLevel) {
1994                        /* STC is ahead of STC, so decoder would drop a frame */
1995                        rc = chn->cfg.video_iface->getCdbLevel(chn->cfg.video, &cdb_level);
1996                        if (rc==BERR_SUCCESS && cdb_level<chn->cfg.video_cdb_level) {
1997                            /* decoder compressed buffer is too shallow, force STC reload to pause decoder and let it accumulate some data */
1998                            BDBG_MSG(("video decoder is underflowed %ld,%u:%u", stc_delta, cdb_level, chn->cfg.video_cdb_level));
1999                            goto set_stc_from_pts;
2000                        }
2001                    }
2002                    BDBG_MSG(("Video is still in range, ignored"));
2003                    chn->video_state = BPCRlib_Decoder_State_eLocking;
2004                    return BERR_SUCCESS;
2005                } 
2006                else 
2007                {
2008                    /* likely discontinuity in the stream, however if audio is just happy with STC, let it go */
2009                    if (BPCRlib_IsAudioLocked_isr(chn, &new_stc)) 
2010                    {
2011                        BDBG_MSG(("Video discontinuity detected, but audio is still locked, ignored"));
2012                        chn->video_state = BPCRlib_Decoder_State_eNotLocked;
2013                        return BERR_SUCCESS;
2014                    }
2015                    if (BPCRlib_P_GetStcFromPcr_isr(chn, video_pts->ui32CurrentPTS, &new_stc)
2016                            /* && BPCRlib_TestVideoStc_isr(chn, new_stc, video_pts->ui32CurrentPTS) */
2017                    ) 
2018                    {
2019                        BDBG_WRN(("VideoPtsError(%#x): Using PCR %#x as new STC %#x (old %#x)", (unsigned)video, (unsigned)chn->pcr_offset.last_pcr, (unsigned)new_stc, (unsigned)video_stc));
2020                        BPCRlib_P_InvalidatePCRCache(chn);
2021                        goto set_stc;
2022                    }
2023                    goto set_stc_from_pts;
2024                }
2025set_stc_from_pts:
2026                pts_offset = chn->cfg.video_pts_offset;
2027                if (chn->cfg.video_iface->getCdbLevel && chn->cfg.video_iface->getCdbLevel(chn->cfg.video, &cdb_level)==BERR_SUCCESS && cdb_level > chn->cfg.video_cdb_level) 
2028                {
2029                    pts_offset = 0;
2030                }
2031#if BCHP_CHIP == 7401
2032                if (dss)
2033                {
2034                    new_stc = video_pts->ui32CurrentPTS - pts_offset * 600;
2035                }
2036                else
2037#endif
2038                {
2039                    new_stc = video_pts->ui32CurrentPTS - pts_offset;
2040                }
2041                BDBG_WRN(("VideoPtsError(%#x): Using video PTS %#x[%d] as new STC %#x (old %#x)", (unsigned)video, (unsigned)video_pts->ui32CurrentPTS, (int)pts_offset, (unsigned)new_stc, (unsigned)video_stc));
2042set_stc:
2043                rc = b_send_stc_isr(chn, new_stc, video);
2044                chn->video_state = BPCRlib_Decoder_State_eLocked;
2045
2046                break;
2047        }
2048    } else {
2049#if defined (B_HAS_IP) && defined (BCHP_7411_VER)
2050        return b_update_stc_isr(chn, false);
2051#else
2052        return b_update_stc_isr(chn, video, false);
2053#endif
2054    }
2055    return rc;
2056}
2057
2058#define BPCRLIB_MILLISECONDS_TO_PTS_TICKS(CFG, X) (b_is_dss_isr(CFG) ? (X) * 27000 : (X) * 45)
2059
2060BERR_Code
2061BPCRlib_Channel_AudioPtsError_isr(BPCRlib_Handle handle, void *audio, const BAVC_PTSInfo *audio_pts, uint32_t audio_stc)
2062{
2063    BPCRlib_Channel chn = find_by_audio_isr(handle, audio);
2064    BERR_Code rc = BERR_SUCCESS;
2065    unsigned cdb_level;
2066    int pts_offset;
2067    bool dss = false;
2068
2069    BDBG_ASSERT(audio_pts);
2070
2071    if (!chn) {
2072        return BERR_TRACE(BERR_INVALID_PARAMETER);
2073    }
2074    dss = b_is_dss_isr(&chn->cfg);
2075    BDBG_MSG(("(%#x) AudioPtsError(%#x) PTS %#x(%d) STC %#x %d %s %u", (unsigned)chn, (unsigned)audio, (unsigned)audio_pts->ui32CurrentPTS, (int)audio_pts->ePTSType, (unsigned)audio_stc, 2*BPCRlib_StcDiff_isr(dss, audio_stc, audio_pts->ui32CurrentPTS), chn->cfg.playback?"Playback":"", chn->cfg.audio_iface->getCdbLevel?chn->cfg.audio_iface->getCdbLevel(chn->cfg.audio, &cdb_level),cdb_level:0));
2076    if (chn->cfg.playback) {
2077        uint32_t new_stc;
2078        int32_t stc_delta;
2079
2080        if (chn->cfg.secondary_audio == audio) {
2081            BDBG_MSG(("secondary audio ignored"));
2082            return BERR_SUCCESS;
2083        }
2084
2085        if (chn->cfg.tertiary_audio == audio) {
2086            BDBG_MSG(("tertiary audio ignored"));
2087            return BERR_SUCCESS;
2088        }
2089
2090        if (chn->cfg.mode == BPCRlib_Mode_eConstantDelay) {
2091            if(chn->delayed_stc.state==delayed_stc_eWaiting) {
2092                return b_load_delayed_stc_isr(chn, audio);
2093            } else {
2094                return BERR_SUCCESS;
2095            }
2096        }
2097
2098        if (audio_pts->ePTSType == BAVC_PTSType_eInterpolatedFromInvalidPTS) {
2099            BDBG_MSG(("Interpolated PTS ignored"));
2100            return BERR_SUCCESS;
2101        }
2102
2103#if 0
2104        if (chn->audio_state == BPCRlib_Decoder_State_eWaitingSTC)
2105        {
2106            chn->audio_state = BPCRlib_Decoder_State_eInvalidated;
2107            BDBG_MSG(("Invalidated -> converting PTS error to request STC"));
2108            /* we've been invalidated, and we need to treat this pts error as request stc */
2109            return BPCRlib_Channel_AudioRequestStc_isr(chn->parent, audio, audio_pts->ui32CurrentPTS);
2110        }
2111#endif
2112
2113        switch (BPCRlib_Channel_GetTsmMode(chn))
2114        {
2115            case BPCRlib_TsmMode_eOutputMaster:
2116            case BPCRlib_TsmMode_eVideoMaster:
2117
2118                return rc;
2119                break;
2120
2121            case BPCRlib_TsmMode_eAudioMaster:
2122
2123                pts_offset = chn->cfg.audio_pts_offset;
2124                stc_delta = (signed)audio_stc - (signed)audio_pts->ui32CurrentPTS;
2125
2126                if (stc_delta > BPCRLIB_MILLISECONDS_TO_PTS_TICKS(&chn->cfg, (signed)chn->cfg.sync_limit)
2127                    || stc_delta < - BPCRLIB_MILLISECONDS_TO_PTS_TICKS(&chn->cfg, (signed)chn->cfg.sync_limit)) /* sync limit in PTS ticks*/
2128                {
2129                    BDBG_MSG(("Outside of sync limit, requesting audio CDB flush"));
2130#if BCHP_CHIP == 7401
2131                    if (dss)
2132                    {
2133                        new_stc = audio_pts->ui32CurrentPTS - pts_offset * 600;
2134                    }
2135                    else
2136#endif
2137                    {
2138                        new_stc = audio_pts->ui32CurrentPTS - pts_offset;
2139                    }
2140                    if (chn->cfg.flush)
2141                    {
2142                        BKNI_SetEvent(chn->cfg.flush);
2143                    }
2144                }
2145                else
2146                {
2147#if 0
2148                    if (!BPCRlib_IsAudioBufferLevel_isr(chn))
2149                    {
2150                        BDBG_MSG(("Audio CDB underflow, applying pts offset"));
2151                        new_stc = audio_pts->ui32CurrentPTS - pts_offset;
2152                    }
2153                    else
2154#endif
2155                    {
2156                        new_stc = audio_pts->ui32CurrentPTS;
2157                    }
2158                }
2159                BDBG_MSG(("AudioPtsError(%#x): Using audio PTS %#x as new STC %#x (old %#x)", (unsigned)audio, (unsigned)audio_pts->ui32CurrentPTS, (unsigned)new_stc, (unsigned)audio_stc));
2160
2161                rc = b_send_stc_isr(chn, new_stc, audio);
2162                chn->audio_state = BPCRlib_Decoder_State_eLocked;
2163                return BERR_SUCCESS;
2164
2165                break;
2166
2167            case BPCRlib_TsmMode_eSTCMaster:
2168            default:
2169
2170                stc_delta=BPCRlib_StcDiff_isr(dss, audio_stc, audio_pts->ui32CurrentPTS);
2171                /* first test if PTS-STC is inside tracking range */
2172                if ( (stc_delta>0 && stc_delta<chn->cfg.audio_stc_discard) && chn->cfg.audio_iface->getCdbLevel) {
2173                    /* STC is ahead of STC, so decoder would drop a frame */
2174                    rc = chn->cfg.audio_iface->getCdbLevel(chn->cfg.audio, &cdb_level);
2175                    if (rc==BERR_SUCCESS && cdb_level<chn->cfg.audio_cdb_level) {
2176                        /* decoder compressed buffer is too shallow, force STC reload to pause decoder and let it accumulate some data */
2177                        BDBG_MSG(("audio decoder is underflowed %ld,%u:%u", stc_delta, cdb_level, chn->cfg.audio_cdb_level));
2178                        goto set_stc_from_pts;
2179                    }
2180                }
2181                if (BPCRlib_TestAudioStc_isr(chn, audio_stc, audio_pts->ui32CurrentPTS)) {
2182                    goto ignored;
2183                }
2184                /* likely discontinuity in the stream, however if vudei is just happy with STC, let it go */
2185                if (BPCRlib_IsVideoLocked_isr(chn, &new_stc)) {
2186                    BDBG_MSG(("Audio discontinuity detected, but video is still locked, ignored"));
2187                    chn->audio_state = BPCRlib_Decoder_State_eNotLocked;
2188                    return BERR_SUCCESS;
2189                }
2190                if (BPCRlib_P_GetStcFromPcr_isr(chn, audio_pts->ui32CurrentPTS, &new_stc)
2191                        /* && BPCRlib_TestAudioStc_isr(chn, new_stc, audio_pts->ui32CurrentPTS) */
2192                    ) {
2193                    BDBG_WRN(("AudioPtsError(%#x): Using PCR %#x as new STC %#x (old %#x)", (unsigned)audio, (unsigned)chn->pcr_offset.last_pcr, (unsigned)new_stc, (unsigned)audio_stc));
2194                    BPCRlib_P_InvalidatePCRCache(chn);
2195                    goto set_stc;
2196                }
2197                goto set_stc_from_pts;
2198set_stc_from_pts:
2199                pts_offset = chn->cfg.audio_pts_offset;
2200                if (chn->cfg.audio_iface->getCdbLevel && chn->cfg.audio_iface->getCdbLevel(chn->cfg.audio, &cdb_level)==BERR_SUCCESS && cdb_level > chn->cfg.audio_cdb_level) {
2201                    pts_offset = 0;
2202                }
2203#if BCHP_CHIP == 7401
2204                if (dss)
2205                {
2206                   new_stc = audio_pts->ui32CurrentPTS - pts_offset * 600;
2207                }
2208                else
2209#endif
2210                {
2211                   new_stc = audio_pts->ui32CurrentPTS - pts_offset;
2212                }
2213                BDBG_WRN(("AudioPtsError(%#x): Using audio PTS %#x[%d] as new STC %#x (old %#x)", (unsigned)audio, (unsigned)audio_pts->ui32CurrentPTS, (int)pts_offset, (unsigned)new_stc, (unsigned)audio_stc));
2214set_stc:
2215                rc = b_send_stc_isr(chn, new_stc, audio);
2216                chn->audio_state = BPCRlib_Decoder_State_eLocked;
2217                return BERR_SUCCESS;
2218ignored:
2219                BDBG_MSG(("Audio is still in range, ignored"));
2220                chn->audio_state = BPCRlib_Decoder_State_eLocking;
2221                return BERR_SUCCESS;
2222
2223                break;
2224        }
2225    } 
2226    else 
2227    {
2228#if defined (B_HAS_IP) && defined (BCHP_7411_VER)
2229        return b_update_stc_isr(chn, false);
2230#else
2231        return b_update_stc_isr(chn, audio, false);
2232#endif
2233    }
2234    return rc;
2235
2236}
2237
2238static void
2239BPCRlib_P_InvalidatePCRCache(BPCRlib_Channel chn)
2240{
2241    chn->pcr_offset.count = 0;
2242    chn->pcr_offset.index = 0;
2243    chn->pcr_offset.last_pcr_valid=false;
2244    chn->pcr_offset.pcr_offset_valid=false;
2245    return;
2246}
2247
2248bool BPCRlib_P_GetAudioPts_isr(BPCRlib_Channel chn, uint32_t * pts)
2249{
2250    bool valid = false;
2251    BAVC_PTSInfo audio_pts;
2252    BERR_Code rc = BERR_SUCCESS;
2253   
2254    if (chn->cfg.audio)
2255    {
2256        BDBG_ASSERT(chn->cfg.audio_iface->getPts);
2257        rc = chn->cfg.audio_iface->getPts(chn->cfg.audio, &audio_pts);
2258        if (rc!=BERR_SUCCESS) goto end; /* 20110516 bandrews - do not trace, failure is normal and handled */
2259
2260        if (audio_pts.ePTSType == BAVC_PTSType_eInterpolatedFromValidPTS
2261            || audio_pts.ePTSType == BAVC_PTSType_eCoded)
2262        {
2263            BDBG_MSG(("Audio returned valid (%u) PTS of %#x", audio_pts.ePTSType, audio_pts.ui32CurrentPTS));
2264            *pts = audio_pts.ui32CurrentPTS;
2265            valid = true;
2266            goto end;
2267        }
2268    }
2269
2270end:
2271    return valid;
2272}
2273
2274bool BPCRlib_P_GetVideoPts_isr(BPCRlib_Channel chn, uint32_t * pts)
2275{
2276    bool valid = false;
2277    BAVC_PTSInfo video_pts;
2278    BERR_Code rc = BERR_SUCCESS;
2279   
2280    if (chn->cfg.video)
2281    {
2282        BDBG_ASSERT(chn->cfg.video_iface->getPts);
2283        rc = chn->cfg.video_iface->getPts(chn->cfg.video, &video_pts);
2284        if (rc!=BERR_SUCCESS) {
2285            BERR_TRACE(rc);
2286            goto end;
2287        }
2288
2289        if (video_pts.ePTSType == BAVC_PTSType_eInterpolatedFromValidPTS
2290            || video_pts.ePTSType == BAVC_PTSType_eCoded)
2291        {
2292            BDBG_MSG(("Video returned valid (%u) PTS of %#x", video_pts.ePTSType, video_pts.ui32CurrentPTS));
2293            *pts = video_pts.ui32CurrentPTS;
2294            valid = true;
2295            goto end;
2296        }
2297    }
2298
2299end:
2300    return valid;
2301}
2302
2303BERR_Code
2304BPCRlib_Channel_Invalidate(BPCRlib_Channel chn)
2305{
2306    BERR_Code rc = BERR_SUCCESS;
2307    BDBG_ASSERT(chn);
2308    BDBG_MSG(("Invalidate: %#x", (unsigned)chn));
2309    chn->audio_state = BPCRlib_Decoder_State_eWaitingSTC;
2310    chn->video_state = BPCRlib_Decoder_State_eWaitingSTC;
2311    chn->delayed_stc.state = delayed_stc_eInvalid;
2312    BPCRlib_P_InvalidatePCRCache(chn);
2313
2314    /* handle invalidate call as part of playback resume, try to get lowest
2315    PTS to seed STC before errors start coming */
2316    /* 20111117 SW7346-544 bandrews - include playback flag, as some clients are calling this fn in live */
2317    if (chn->cfg.playback && chn->cfg.refresh_stc_on_invalidate && !chn->cfg.non_real_time)
2318    {
2319        uint32_t audio_pts = 0;
2320        uint32_t video_pts = 0;
2321        int32_t pts_diff;
2322        uint32_t new_stc = 0;
2323        bool audio_valid;
2324        bool video_valid;
2325
2326        BKNI_EnterCriticalSection();
2327        audio_valid = BPCRlib_P_GetAudioPts_isr(chn, &audio_pts);
2328        video_valid = BPCRlib_P_GetVideoPts_isr(chn, &video_pts);
2329
2330        if (audio_valid && video_valid)
2331        {
2332            pts_diff = (int32_t)(video_pts - audio_pts);
2333            if (pts_diff < 0)
2334            {
2335                new_stc = video_pts - chn->cfg.video_pts_offset;
2336            }
2337            else
2338            {
2339                new_stc = audio_pts - chn->cfg.audio_pts_offset;
2340            }
2341
2342            BDBG_MSG(("Invalidate: using lowest PTS %#x as new STC", new_stc));
2343        }
2344        else if (audio_valid)
2345        {
2346            new_stc = audio_pts - chn->cfg.audio_pts_offset;
2347            BDBG_MSG(("Invalidate: [video invalid] using audio PTS %#x as new STC", new_stc));
2348        }
2349        else if (video_valid)
2350        {
2351            new_stc = video_pts - chn->cfg.video_pts_offset;
2352            BDBG_MSG(("Invalidate: [audio invalid] using video PTS %#x as new STC", new_stc));
2353        }
2354        else
2355        {
2356            BDBG_MSG(("Invalidate: [video, audio invalid] no change in STC"));
2357            BKNI_LeaveCriticalSection();
2358            goto end;
2359        }
2360
2361        chn->video_state = BPCRlib_Decoder_State_eLocked;
2362        chn->audio_state = BPCRlib_Decoder_State_eLocked;
2363        rc = b_really_send_stc_isr(chn, new_stc);
2364        BKNI_LeaveCriticalSection();
2365    }
2366
2367end:
2368    return rc;
2369}
2370
2371BERR_Code
2372BPCRlib_Channel_GetStc(BPCRlib_Channel chn, uint32_t *stc)
2373{
2374    BERR_Code rc = BERR_SUCCESS;
2375    uint32_t stc_low;
2376
2377    BDBG_ASSERT(chn);
2378
2379    BKNI_EnterCriticalSection();
2380#if B_PCRLIB_HAS_PCROFFSET
2381    /* Systems with PCROFFSET require the aux_transport setting and do not use the pcr setting. */
2382    *stc = BXPT_PcrOffset_GetStc_isr(chn->cfg.aux_transport) + BXPT_PcrOffset_GetOffset_isr(chn->cfg.aux_transport);
2383#else
2384    /* Systems without PCROFFSET require the pcr setting. */
2385    BDBG_ASSERT(chn->pcr);
2386    rc = BXPT_PCR_GetStc_isr(chn->pcr, stc, &stc_low /* not used */ );
2387#endif
2388    if (rc!=BERR_SUCCESS) {
2389        rc = BERR_TRACE(rc);
2390        goto done;
2391    }
2392    if (!chn->cfg.playback || chn->cfg.mode!=BPCRlib_Mode_eConstantDelay) {
2393        goto done;
2394    }
2395    if (chn->delayed_stc.state == delayed_stc_eInvalid) {
2396        rc = BERR_TRACE(BERR_NOT_SUPPORTED);
2397        goto done;
2398    }
2399    stc_low = chn->delayed_stc.stc + (*stc - chn->delayed_stc.old_stc);
2400    BDBG_MSG_TRACE(("BPCRlib_Channel_GetStc: %#lx returning STC %#x (%u+%d)", (unsigned long)chn, (unsigned)stc_low, (unsigned)chn->delayed_stc.stc, (int)(*stc - chn->delayed_stc.old_stc)));
2401    *stc = stc_low;
2402done:
2403    BKNI_LeaveCriticalSection();
2404    return rc;
2405}
2406
2407
2408BERR_Code
2409BPCRlib_Channel_PcrUpdate(BPCRlib_Channel chn, uint32_t pcr)
2410{
2411    BERR_Code rc = BERR_SUCCESS;
2412    uint32_t stc=0;
2413    bool stc_valid;
2414    int32_t delta=0;
2415    bool send_video_stc=false;
2416    bool send_audio_stc=false;
2417
2418    if (!chn || !chn->cfg.playback) {
2419        return BERR_TRACE(BERR_INVALID_PARAMETER);
2420    }
2421    if (chn->cfg.mode==BPCRlib_Mode_eConstantDelay) {
2422        BKNI_EnterCriticalSection();
2423
2424        switch(chn->delayed_stc.state) {
2425        case delayed_stc_eLocked:
2426        case delayed_stc_eWaiting:
2427#if 0
2428            rc = BXPT_PCR_GetStc_isr(chn->pcr, &chn->delayed_stc.old_stc, &chn->delayed_stc.stc /* not used */ );
2429            chn->delayed_stc.stc = pcr;
2430            BDBG_MSG(("BPCRlib_Channel_PcrUpdate: %#lx saving STC %u (%d)", (unsigned long)chn, (unsigned)pcr, (int)(pcr - chn->delayed_stc.old_stc)));
2431            chn->delayed_stc.state = delayed_stc_eWaiting; /* don't load STC wait for decoder to ask */
2432            break;
2433#endif
2434        case delayed_stc_eInvalid:
2435            BDBG_WRN(("BPCRlib_Channel_PcrUpdate: %#lx loading new STC %#x", (unsigned long)chn, (unsigned)pcr));
2436            rc = b_really_send_stc_isr(chn, pcr);
2437            chn->delayed_stc.stc = pcr;
2438            chn->delayed_stc.old_stc = pcr;
2439            chn->delayed_stc.state = delayed_stc_eLocked;
2440            break;
2441        }
2442        /* update delayed_stc, so following  call to b_load_delayed_stc_isr would not use stale values */
2443        BKNI_LeaveCriticalSection();
2444        return rc;
2445    }
2446
2447
2448    BKNI_EnterCriticalSection();
2449    if (chn->cfg.video && chn->video_state==BPCRlib_Decoder_State_eWaitingSTC) {
2450        send_video_stc = true;
2451    }
2452    if (chn->cfg.audio && chn->audio_state==BPCRlib_Decoder_State_eWaitingSTC) {
2453        send_audio_stc = true;
2454    }
2455    if (send_audio_stc && send_video_stc) {
2456        BDBG_WRN(("%#x preloading stc %#x from pcr %#x", (unsigned)chn, pcr-chn->cfg.pcr_offset, pcr));
2457        b_send_stc_isr(chn, pcr-chn->cfg.pcr_offset, chn->cfg.video);
2458        b_send_stc_isr(chn, pcr-chn->cfg.pcr_offset, chn->cfg.audio);
2459        if (send_audio_stc) {
2460            chn->audio_state=BPCRlib_Decoder_State_eNotLocked;
2461        }
2462        if (send_video_stc) {
2463            chn->video_state=BPCRlib_Decoder_State_eNotLocked;
2464        }
2465    }
2466    chn->pcr_offset.last_pcr_valid=true;
2467    chn->pcr_offset.last_pcr=pcr;
2468    stc_valid = b_read_stc_isr(chn, &stc);
2469#if 0
2470    BDBG_MSG(("(%#x) PcrUpdate %u %u %d[%u:%u]", (unsigned)chn, (unsigned)pcr, stc, delta, chn->pcr_offset.index, chn->pcr_offset.count));
2471#endif
2472    if (stc_valid) {
2473        delta = BPCRlib_StcDiff_isr(b_is_dss_isr(&chn->cfg), pcr, stc);
2474        if (delta <= chn->cfg.pcr_discard/2 && delta >= -chn->cfg.pcr_discard/2) {
2475            chn->pcr_offset.pcr_fifo[chn->pcr_offset.index] = delta;
2476            chn->pcr_offset.index++;
2477            if (chn->pcr_offset.index >= BPCRlib_P_PCR_FIFO) {
2478                chn->pcr_offset.index = 0;
2479            }
2480            if (chn->pcr_offset.count < BPCRlib_P_PCR_FIFO) {
2481                chn->pcr_offset.count++;
2482            }
2483            chn->pcr_offset.pcr_offset_valid = false;
2484        } else {
2485            chn->pcr_offset.pcr_offset = pcr-stc;
2486            chn->pcr_offset.pcr_offset_valid = true;
2487            BDBG_MSG(("(%#x) PcrOffset %#x %#x (%d/%d/%d)", (unsigned)chn, (unsigned)pcr, stc, (int)delta*2, (int)chn->pcr_offset.pcr_offset,(int)chn->cfg.pcr_discard));
2488        }
2489    }
2490    BKNI_LeaveCriticalSection();
2491
2492    return rc;
2493}
2494
2495
Note: See TracBrowser for help on using the repository browser.