source: svn/newcon3bcm2_21bu/BSEAV/api/src/nexus/bsettop_decode.c

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

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

  • Property svn:executable set to *
File size: 176.9 KB
Line 
1/***************************************************************************
2 *  Copyright (c) 2003-2010, Broadcom Corporation
3 *  All Rights Reserved
4 *  Confidential Property of Broadcom Corporation
5 *
6 *  THIS SOFTWARE MAY ONLY BE USED SUBJECT TO AN EXECUTED SOFTWARE LICENSE
7 *  AGREEMENT  BETWEEN THE USER AND BROADCOM.  YOU HAVE NO RIGHT TO USE OR
8 *  EXPLOIT THIS MATERIAL EXCEPT SUBJECT TO THE TERMS OF SUCH AN AGREEMENT.
9 *
10 * $brcm_Workfile: bsettop_decode.c $
11 * $brcm_Revision: SW7550-356/1 $
12 * $brcm_Date: 6/14/10 7:16p $
13 *
14 * Module Description:
15 *
16 * Revision History:
17 *
18 * $brcm_Log: /BSEAV/api/src/nexus/bsettop_decode.c $
19 *
20 * SW7550-356/1   6/14/10 7:16p nitinb
21 * SW7550-356: Use single timebase for both decode and display on 7550
22 * (single timebsae chip)
23 *
24 * 217   5/25/10 4:09p calvinho
25 * SW7125-279: Coverity Defect ID:20338 CHECKED_RETURN
26 *
27 * 216   4/14/10 11:58a calvinho
28 * SW7125-279: Fix Coverity Defects ID:20338, 20337 in bsettop_decode.c
29 *
30 * 215   3/19/10 5:59p jgarrett
31 * SW7405-4040: Ensuring audio and video are on the same timebase
32 *
33 * 214   3/16/10 10:47a jtna
34 * SW3556-1051: revert back to host-reordering
35 *
36 * 213   2/16/10 5:42p jtna
37 * SW3556-1051: use video decoder timestamp reordering
38 *
39 * 212   2/11/10 3:52p bandrews
40 * SW7550-241: clean up logic for assigning ASTM audio channels in
41 * set_astm
42 *
43 * 211   1/28/10 4:23p mward
44 * SW7400-2650:  DTS passthru support for 7400.  Passthru only, no decode.
45 *
46 * 210   1/27/10 10:01a jgarrett
47 * SW7550-213: Merge to main branch
48 *
49 * 209   1/26/10 6:02p jgarrett
50 * SW7405-3635: Allowing fixed audio decode->display mapping to avoid re-
51 * attaching outputs on every bdecode_stop/bdecode_start
52 *
53 * SW7550-213/1   1/25/10 5:22p jianweiz
54 * SW7550-213: set the stereo to dual mono when initialize the audio
55 * decoder.
56 *
57 * 208   12/9/09 12:03p gmohile
58 * SW7408-1 : Add 7408 support
59 *
60 * 207   12/3/09 2:45p jgarrett
61 * SW7405-3511: Adding compressed mute for outputs
62 *
63 * 206   12/2/09 7:31p katrep
64 * SW7405-3158:support for DTS certification app
65 *
66 * 205   12/1/09 7:26p katrep
67 * SW7405-3515:Add downmix modes for AAC formats
68 *
69 * 204   11/25/09 5:36p katrep
70 * SW7405-2740: Add support for WMA pro drc
71 *
72 * 203   11/24/09 2:41p katrep
73 * SW7405-3419: Add decode_aac_96khz run time environment variable
74 *
75 * 202   11/23/09 5:52p katrep
76 * SW7405-3457:Add DRA support
77 *
78 * 201   11/19/09 8:02p jgarrett
79 * SW7405-3357: Adding audio output routing for decode and pcm playback
80 * prior to start
81 *
82 * 200   11/12/09 11:41a gmohile
83 * SW7401-4340 : 7401 only supports simul mode for compressed DDP output
84 *
85 * 199   11/10/09 5:54p mward
86 * SW7400-2574: HD/SD sharpness optimizations incorporated in VDC,
87 * NEXUS_PictureCtrl_SetSharpnessValue() is no longer needed for simple
88 * sharpness setting.
89 *
90 * 198   11/10/09 4:57p mward
91 * SW7400-2574: When using the  NEXUS_PictureCtrl_SetSharpnessValue(), the
92 * quantity of sharpness must be set using lumaControlGain and
93 * chromaControlGain, the nPictureCtrlCommonSettings.sharpness is ignored
94 * by BVDC_Window_SetSharpness.
95 *
96 * 197   11/9/09 6:05p mward
97 * SW7400-2574:  Sharpness control optimization depends on source format,
98 * check and update when it changes.
99 *
100 * 196   11/2/09 11:16a erickson
101 * SW7405-3315: remove playbackOverride. use NEXUS_StcChannelMode instead.
102 *
103 * 195   10/23/09 4:26p jtna
104 * SW7405-3265: use same stc channel when using video primer FCC
105 *
106 * SW7405-3158/1   10/7/09 7:03p mward
107 * SW7405-3158: Remember audio decoder start settings for restart which
108 * may be necessary changing DTS decoder settings.
109 *
110 * 194   9/29/09 11:48a jgarrett
111 * SW7405-3100: Adding display underflows and display drops to video
112 * decode status
113 *
114 * 193   9/18/09 5:49p mward
115 * SW7400-2374:  For 7400, even timebases are used with decoder0, use
116 * audio pll0, odd with decoder1, use pll1.
117 *
118 * 192   9/14/09 4:26p jgarrett
119 * SW7405-3011: Fixing sync enable flag
120 *
121 * 191   9/14/09 3:05p jgarrett
122 * SW7405-3011: Splitting sync control into precision and basic
123 *
124 * 190   9/11/09 1:02p jjordan
125 * SW7405-2969: only alter the fifoThreshold for the PVR playback case,
126 * delayed startup of audio is not a problem for non-playback
127 *
128 * 189   9/11/09 10:05a jtna
129 * SWDEPRECATED-3910: improve FCC performance
130 *
131 * 188   9/10/09 6:04p mward
132 * SW7400-2374:  For 7400, select audio output PLL to match timebase
133 * number.
134 *
135 * 187   9/10/09 5:19p jgarrett
136 * SW7405-3011: Adding sync options to bsettop_init_settings
137 *
138 * 187   9/10/09 5:17p jgarrett
139 * SW7405-3011: Adding sync options to bsettop_init_settings
140 *
141 * 186   9/10/09 1:43p mward
142 * SW7400-2387: When forcing to PCM due to algorithm, remove inputs to
143 * HDMI, as well as to SPDIF.
144 *
145 * 185   9/4/09 11:45a jgarrett
146 * SWDEPRECATED-3910: Moving fifo_size to bsettop_init_settings
147 *
148 * 184   9/1/09 12:47p katrep
149 * SW7405-2934:Enable DTS encode for DTS Streams
150 *
151 * 183   8/25/09 12:52p jtna
152 * SWDEPRECATED-3910: video primer fast channel change feature
153 *
154 * 182   8/25/09 11:24a katrep
155 * SW7405-2934:add suppoort for audio capture to a file
156 *
157 * 181   8/18/09 6:44p katrep
158 * PR56109: Use calllbacks instead of using events for callbacks to the
159 * app
160 *
161 * 180   8/18/09 9:59a mward
162 * PR56489: Single PLL setting for DDP passthru now available on 7400.
163 *
164 * 179   8/4/09 2:26p mward
165 * PR56560: Passthru for SPDIF (and HDMI) should be disabled for MPEG
166 * decoder (on 7400).
167 *
168 * 178   8/4/09 12:10p katrep
169 * PR57100: Preserve dolby voulme,srs voulme setting across channel
170 * changes.
171 *
172 * 177   7/30/09 7:26p mward
173 * PR57243:  Don't need to check for non-null audio->decode in
174 * baudio_decode_get_status().
175 *
176 * 176   7/30/09 7:10p mward
177 * PR57242:  PR57241: Don't alter fifoThreshold if
178 * NEXUS_VideoDecoder_GetStatus() failed.
179 *
180 * 175   7/30/09 6:45p mward
181 * PR57241:  Failure of NEXUS_VideoDecoder_GetStatus() in
182 * bdecode_p_enable_audio is harmless.
183 *
184 * 174   7/27/09 1:46p mward
185 * PR45344: In some cases, (e.g. Brutus B) there may be no SPDIF,
186 * settings.spdif may be NULL.
187 *
188 * 173   7/17/09 7:33p bandrews
189 * PR49215: added back accidentally removed static functions
190 *
191 * 172   7/17/09 7:24p bandrews
192 * PR49215: astm dvr support
193 *
194 * 171   7/16/09 4:12p jjordan
195 * PR56878: only set non-zero PTS offset for "live playback" mode
196 *
197 * 170   7/7/09 6:21p katrep
198 * PR45344: spdif status reporting issue
199 *
200 * 169   7/1/09 9:25a erickson
201 * PR56446: added drop_field_mode=y env variable
202 *
203 * 168   6/30/09 4:27p katrep
204 * PR55809: add support for avi pcm
205 *
206 * 167   6/30/09 12:17p mward
207 * PR52051: PR 52051: Add dialog normalization setting.
208 *
209 * 166   6/29/09 6:01p mward
210 * PR 56384:  Set PLL based on decoder, not output timebase.
211 *
212 * 165   6/29/09 10:12a erickson
213 * PR56373: fix bdecode_close so that we can call bsettop_init a second
214 * time
215 *
216 * 164   6/26/09 6:49p mward
217 * PR 56384:  Moved pll setting for 7400 from Nexus.
218 *
219 * 163   6/26/09 9:32a katrep
220 * PR55074: Add DTS and PCM audio support for get status api
221 *
222 * 161   6/19/09 6:15p mward
223 * PR 47739: 7400 DDP passthru requires RAP DSP context 1, used by Nexus
224 * audio decoder 1.  Swap it for use by passthru if it is not currently
225 * in use.
226 *
227 * 160   6/19/09 6:01p mward
228 * PR 47729: DDP passthru for 7400 requires use of RAP channel 1, use
229 * Nexus audio decoder 1 for it, swap if it's not in use for second
230 * decode.
231 *
232 * 159   6/18/09 7:06p mward
233 * PR 56145: Hook up the Dolby codec settings, and initialize them to the
234 * settings used in the native Settop API implementation (DRC mode RF,
235 * standard downmix mode.
236 *
237 * 157   6/2/09 7:02p mward
238 * PR 50613:  Move open for TruVolume and Dolby Volume to audio start and
239 * close to audio stop, to avoid leaking the post-proc stage handle for
240 * detached audio decoder.
241 *
242 * 156   5/15/09 3:32p jjordan
243 * PR52687: PR52687: improve AAC downmix API
244 * PR52687: Add method to set audio downmix type
245 *
246 * 155   5/8/09 5:45p mward
247 * PR47739: Move create/register for audio source change event to audio
248 * start and unregister/destroy to audio stop, as in native Settop API to
249 * avoid leaking event  of detached audio decoder.
250 *
251 * 154   5/6/09 4:27p jjordan
252 * PR50291: add Wide GA mode
253 *
254 * 153   4/29/09 2:14p katrep
255 * PR54656: Fixed assert when sync_disabled=y
256 *
257 * 152   4/29/09 12:53p katrep
258 * PR54656: astm diabled by default, use astm_enabled=y to enable
259 *
260 * 151   4/29/09 11:15a katrep
261 * PR51938: Changing decode default volume to max. 0 mean half volume
262 *
263 * 150   4/27/09 6:42p katrep
264 * PR54586: crash with astm_disabled=y
265 *
266 * 149   4/27/09 3:29p katrep
267 * PR54586: Some cleanup and better debug
268 *
269 * 148   4/24/09 7:41p katrep
270 * PR54586: Add astm support,add audio_fifo_size,add use_first_pts run
271 * time variables
272 *
273 * 147   4/14/09 12:08p katrep
274 * PR52862: Fixed coveiry issue
275 *
276 * 146   3/26/09 6:12p katrep
277 * PR53631: Preserve brutus audio setting after forced PCM on WMA channel.
278 *
279 * 145   3/24/09 6:18p katrep
280 * PR52384: Do not start dts or ac3 encode if codec doesnt support encode.
281 *
282 * 144   3/23/09 3:45p katrep
283 * PR52340:More updates for true and dolby vol
284 *
285 * 143   3/23/09 3:05p katrep
286 * PR52340: Allow cascading for true and dolby voules if both are compiled
287 * in
288 *
289 * 142   3/20/09 1:09p katrep
290 * PR52340: Support srs true volume and dolby volume through brutus ans
291 * settop api
292 *
293 * 141   3/6/09 11:26a katrep
294 * PR50291: Fixed kernel crash in cases where secondary audio is not
295 * started (WMA)
296 *
297 * 140   3/3/09 2:55p jjordan
298 * PR50291: PR50291: conform to naming convention
299 * PR50291: add enable of audio wide gross adjustment mode
300 *
301 * 139   3/3/09 9:42a katrep
302 * PR52340: mixer was not getting configured when src_true_volume not set
303 *
304 * 138   3/2/09 6:10p katrep
305 * PR52340: Add support srs_true_volume
306 *
307 * 137   1/27/09 7:21p katrep
308 * PR43688: Add support for downmix and dual momo modes
309 *
310 * 136   1/19/09 4:26p mward
311 * PR47739: settings.dvi may be null, this display might not have HDMI
312 * output.
313 *
314 * 135   1/15/09 9:44a katrep
315 * PR50063: Fixed compiler warning in non debug builds
316 *
317 * 134   1/14/09 6:46p katrep
318 * PR44767: Set the correct dual mono mode
319 *
320 * 133   1/9/09 12:09a erickson
321 * PR50063: separate B_HAS_DTS_ENCODE and B_HAS_AC3_ENCODE logic
322 *
323 * 132   1/8/09 7:41p katrep
324 * PR50063: force PCM on DVD LPCM
325 *
326 * 131   1/8/09 12:21p katrep
327 * PR50063: Add suppport dor Ac3 encode in Settop shim and burtus.
328 *
329 * 130   12/15/08 4:49p katrep
330 * PR50222: Add independent delay support for audio dacs. dac_output_delay
331 *
332 * 129   12/3/08 5:29p jjordan
333 * PR49939: fix b/w video on IP channel change (during "auto-pids")
334 *
335 * 128   12/3/08 4:57p katrep
336 * PR49939: Set the frame mastership when decode started on the first
337 * window
338 *
339 * 127   12/2/08 12:10p jgarrett
340 * PR 47993: Allowing PID values > 0x1fff for VOB streams
341 *
342 * 126   11/25/08 11:19a mward
343 * PR47739: On 7400, a display might not have HDMI.
344 *
345 * 125   11/7/08 1:11p katrep
346 * PR47230: Fixed non ip build
347 *
348 * 124   11/6/08 8:36p katrep
349 * PR47230: reworked the output port timebase logic
350 *
351 * 123   11/6/08 4:48p katrep
352 * PR47230: Only pcr pid chanel only for live and ip modes
353 *
354 * 122   11/6/08 11:12a ssood
355 * PR48146: TSM broken for local & HTTP playback of ASF & MP4 files
356 *
357 * 121   11/4/08 2:56p katrep
358 * PR48292: Fixed coverity issues
359 *
360 * 120   11/3/08 2:56p erickson
361 * PR47230: fix non-TTS pacing case
362 *
363 * 119   10/31/08 12:29p jjordan
364 * PR47230: Add TTS Pacing
365 *
366 * 118   10/21/08 6:49p katrep
367 * PR47198: Add ind delay for audio decoder
368 *
369 * 117   10/21/08 6:21p katrep
370 * PR43187: Report fifo size and depth on the rave context even if the
371 * decoder is not started.
372 *
373 * 116   10/13/08 5:20p katrep
374 * PR46677: Loss of audio on spdif if previous channel was wma.
375 *
376 * 115   10/8/08 3:44p ssood
377 * PR47521: lowered the MAX ERROR to match the OFFSET THRESHOLD in PCR
378 * Offset block
379 *
380 * 114   9/25/08 3:31p katrep
381 * PR47073: fifo_size runtime varibale required to increase the CDB size
382 * to decode some VC1 streams.
383 *
384 * 113   9/24/08 7:14p katrep
385 * PR43187: lowered the cdb threshold for non ip cases. Improve loss of
386 * audio duration due audio decode stop and decode start.
387 *
388 * 112   9/23/08 6:02p katrep
389 * PR47229: Fixed segfault on channel change.
390 *
391 * 111   9/23/08 1:13p katrep
392 * PR47229: WMA pro should be processed as simul mode not passthrough mode
393 *
394 * 110   9/23/08 10:55a erickson
395 * PR47231: add preroll_rate env variable for test
396 *
397 * 109   9/22/08 10:03a erickson
398 * PR47145: fix warning
399 *
400 * 108   9/17/08 6:20p katrep
401 * PR47061: Add support for DTS encode
402 *
403 * 107   9/16/08 12:33p katrep
404 * PR46896: Fixed application crash,during pcm playback
405 *
406 * 106   9/15/08 5:27p jrubio
407 * PR46925:  fix PVR_SUPPORT=n compile issue
408 *
409 * 105   9/12/08 8:47a erickson
410 * PR44959: protect bdecode_set if decode->video_decode is NULL
411 *
412 * 104   9/11/08 2:04p vishk
413 * PR44959: impl bdecode_settings.stop_mode
414 *
415 * 103   9/10/08 7:57p katrep
416 * PR46732: Force pcm for wma compressed. Fixed no audio on hdmi during
417 * pcm pb and i2s capture.
418 *
419 * 102   9/8/08 10:26a erickson
420 * PR46534: fix order of NEXUS_VideoWindow_RemoveInput for clone window
421 *
422 * 101   8/26/08 8:30p katrep
423 * PR45577: Moved the HDMI audio ouput port settings from dispaly to
424 * decode.
425 *
426 * 100   8/26/08 6:47p katrep
427 * PR46089: Use the multichannel settings at the decoder open time.
428 *
429 * 99   8/22/08 7:49p erickson
430 * PR45959: StillDecoder is now normal part of VideoDecoder module
431 *
432 * 98   8/22/08 7:02p jgarrett
433 * PR 44767: Reworking dual-mono logic
434 *
435 * 97   8/13/08 7:08p katrep
436 * PR45577: Add supoort for 5.1 pcm audio on hdmi
437 *
438 * 96   8/5/08 6:19p zmao
439 * PR45311: Fix a build warning
440 *
441 * 95   8/5/08 5:55p zmao
442 * PR45311: Remove C++ style comments
443 *
444 * 94   8/5/08 5:25p zmao
445 * PR45311:Add status->downmix_mode and status->layer in
446 * baudio_decode_get_status function
447 *
448 * 93   8/5/08 11:37a jrubio
449 * PR45361: remove "//"
450 *
451 * 92   8/1/08 5:37p erickson
452 * PR45361: c89 fixes
453 *
454 * 91   7/29/08 1:08p katrep
455 * PR45045:WMA compressed request should yield no audio.
456 *
457 * 90   7/29/08 8:11a erickson
458 * PR42739: support IP TV platforms with no HdmiOutput
459 *
460 * 89   7/24/08 11:52a erickson
461 * PR44959: fix DTV builds
462 *
463 * 88   7/22/08 5:50p katrep
464 * PR45045:WMA/WMA passthrough support
465 *
466 * 87   7/21/08 10:31a erickson
467 * PR44959: fix DTV builds
468 *
469 * 86   7/18/08 4:22p erickson
470 * PR44959: impl bdecode_settings.stop_mode
471 *
472 * 85   7/17/08 6:40p jgarrett
473 * PR 44509: Converting audio decoder open to new API
474 *
475 * 84   7/16/08 3:37p ssood
476 * PR42739: fixing warning message for non-ip builds
477 *
478 * 83   7/14/08 4:42p ssood
479 * PR42739: fixing another non-ip compile error
480 *
481 * 82   7/14/08 4:33p ssood
482 * PR42739: fixing non-ip compile error
483 *
484 * 81   7/14/08 1:59p ssood
485 * PR42739: getting the audio dac handle via display structure
486 *
487 * 80   7/14/08 1:28p ssood
488 * PR42739: further changes to support high jitter support for live IP
489 * playback
490 *
491 * 80   7/14/08 1:20p ssood
492 * PR42739: further changes to support high jitter support for live IP
493 * playback
494 *
495 * 79   7/11/08 8:49a ssood
496 * PR42739: fixing IP related build error
497 *
498 * 78   7/10/08 10:19p ssood
499 * PR42739: Adding support to absorb high jitter for IPSTB
500 *
501 * 77   7/9/08 4:10p katrep
502 * PR43490: Add support 656/i2s tuning using analog tune api.
503 *
504 * 76   7/2/08 11:43a erickson
505 * PR44482: check dvi handle before using it
506 *
507 * 75   6/30/08 2:06p erickson
508 * PR44194: fix bdecode_p_set_video_input
509 *
510 * 74   6/30/08 10:03a erickson
511 * PR44321: check return code
512 *
513 * 73   6/27/08 1:41p erickson
514 * PR44194: impl hold_last_picture in Settop API shim
515 *
516 * 72   6/25/08 2:32p erickson
517 * PR39453: add hold_last_picture option
518 *
519 * 71   6/23/08 12:24p erickson
520 * PR43399: fix non-HDMI platforms
521 *
522 * 70   6/20/08 6:27p katrep
523 * PR43399: Do not set HDMI for compressed output if HDMI is not
524 * connected.
525 *
526 ***************************************************************************/
527#include "bsettop_impl.h"
528#include <string.h>
529#include <stdlib.h> /* atoi */
530
531BDBG_MODULE(decode);
532
533
534/* TODO: rework the attach/detach method. don't allow dangling decoders. */
535struct bdecode g_decode[B_MAX_DECODES+B_MAX_STILL_DECODES];
536struct bvideo_decode g_video_decode[B_MAX_DECODES];
537#if BCHP_CHIP == 7400
538struct baudio_decode g_audio_decode[B_MAX_DECODES];
539struct baudio_decode g_secondary_audio_decode[B_MAX_DECODES];
540#else
541struct baudio_decode g_audio_decode[1];
542struct baudio_decode g_secondary_audio_decode[1];
543#endif
544
545
546/* Max Supported Jitter for the IPSTB Configuration */
547#define IP_NETWORK_JITTER 300
548
549static bresult bdecode_p_open_sync_channel(bdecode_t decode);
550static bresult bdecode_p_close_sync_channel(bdecode_t decode);
551static bresult bdecode_p_set_sync_channel(bdecode_t decode, bool video,bool audio_pcm,bool audio_passthrough);
552static bresult bdecode_p_unset_sync_channel(bdecode_t decode,bool video,bool audio_pcm,bool audio_passthrough);
553static bresult bdecode_set_audio_ip_tsm_settings(baudio_decode_t audio_decode);
554
555static bresult bdecode_p_open_astm(bdecode_t decode);
556static bresult bdecode_p_close_astm(bdecode_t decode);
557static bresult bdecode_p_set_astm(bdecode_t decode, bool video,bool audio_pcm,bool audio_passthrough);
558static bresult bdecode_p_unset_astm(bdecode_t decode,bool video,bool audio_pcm,bool audio_passthrough);
559static bresult bdecode_p_start_astm(bdecode_t decode);
560static bresult bdecode_p_stop_astm(bdecode_t decode);
561static NEXUS_AudioDecoderDolbyStereoDownmixMode baudio_dolby_stereo_downmix_mode_to_nexus_ac3plus_stereo_mode(baudio_dolby_stereo_downmix_mode stereo_downmix_mode);
562static NEXUS_AudioDecoderDolbyDrcMode baudio_dolby_drc_mode_to_nexus_ac3plus_comp_mode(baudio_dolby_drc_mode drc_mode);
563int baudio_capture_open(baudio_decode_t audio);
564int baudio_capture_close(baudio_decode_t audio);
565int baudio_capture_start(baudio_decode_t audio);
566int baudio_capture_stop(baudio_decode_t audio);
567static bresult bdecode_p_set_audio_display(baudio_decode_t audio_decode, bdisplay_t display);
568
569
570
571typedef enum
572{
573    SOURCE_CHANGE_EVENT_AUDIO,
574    SOURCE_CHANGE_EVENT_VIDEO
575
576}SourceChangeEventType;
577
578static int g_open_audio_decodes=0;
579static NEXUS_AudioDecoderHandle g_n_audio_decoder[NEXUS_NUM_AUDIO_DECODERS];
580static NEXUS_AudioDecoderHandle g_audio_passthrough;
581static baudio_decode_t g_audio_passthrough_owner;
582
583static void bdecode_p_still_handler(void *context,int param);
584
585static void bdecode_p_source_changed(void *context, int param)
586{
587    bdecode_t decode = (bdecode_t)context;
588    SourceChangeEventType event = (SourceChangeEventType)param;
589    if (event==SOURCE_CHANGE_EVENT_VIDEO && decode->video_decode)
590    {
591        BDBG_MSG(("video source change"));
592        b_callback_fire(decode->video_decode->sourceChangedCallback);
593        /*B_Event_Set(decode->video_decode->sourceChangedEvent);*/
594    }
595    else if (event==SOURCE_CHANGE_EVENT_AUDIO && decode->audio_decode && decode->settings.audio.source_changed)
596    {
597        BDBG_MSG(("audio source change"));
598        /*B_Event_Set(decode->audio_decode->sourceChangedEvent);*/
599        b_callback_fire(decode->audio_decode->sourceChangedCallback);
600    }
601}
602
603static void bdecode_p_video_source_changed(void *context,int param )
604{
605    bdecode_t decode = context;
606    BSTD_UNUSED(param);
607    BDBG_ASSERT(NULL != decode);
608
609    if ( decode->settings.video.source_changed )
610    {
611        /* b_unlock();*/
612        (*decode->settings.video.source_changed)(decode->settings.callback_context);
613        /*b_lock();*/
614    }
615}
616
617static void bdecode_p_audio_source_changed(void *context,int param)
618{
619    bdecode_t decode = context;
620    BSTD_UNUSED(param);
621    BDBG_ASSERT(NULL != decode);
622    if ( decode->settings.audio.source_changed )
623    {
624        /*b_unlock();*/
625        (*decode->settings.audio.source_changed)(decode->settings.callback_context);
626        /*b_lock();*/
627    }
628}
629
630void bdecode_p_init()
631{
632    unsigned i;
633
634    BDBG_ASSERT(g_open_audio_decodes == 0);
635    BDBG_ASSERT(g_n_audio_decoder[0] == NULL);
636    BDBG_ASSERT(g_audio_passthrough == NULL);
637
638    BKNI_Memset(g_decode, 0, sizeof(g_decode));
639    BKNI_Memset(g_video_decode, 0, sizeof(g_video_decode));
640    BKNI_Memset(g_audio_decode, 0, sizeof(g_audio_decode));
641    BKNI_Memset(g_secondary_audio_decode, 0, sizeof(g_secondary_audio_decode));
642
643    for (i=0;i<B_MAX_DECODES;i++)
644    {
645        g_decode[i].volume.left = BAUDIO_LEVEL_MAX;
646        g_decode[i].volume.right = BAUDIO_LEVEL_MAX;
647
648        g_decode[i].video_decode = &g_video_decode[i];
649        g_decode[i].video_decode->decode = &g_decode[i];
650#if BCHP_CHIP == 7400
651        g_decode[i].audio_decode = &g_audio_decode[i];
652        g_decode[i].audio_decode->decode = &g_decode[i];
653        g_secondary_audio_decode[i].decode = &g_decode[i];
654        g_decode[i].audio_decode->secondary_audio_decode = &g_secondary_audio_decode[i];
655#else
656        if (i == 0)
657        {
658            g_decode[i].audio_decode = &g_audio_decode[i];
659            g_decode[i].audio_decode->decode = &g_decode[i];
660            g_secondary_audio_decode[i].decode = &g_decode[i];
661            g_decode[i].audio_decode->secondary_audio_decode = &g_secondary_audio_decode[i];
662        }
663#endif
664       g_decode[i].settings.audio.codec.dolby.drc_mode = baudio_dolby_drc_mode_rf;
665       g_decode[i].settings.audio.codec.dolby.stereo_downmix_mode = baudio_dolby_stereo_downmix_mode_standard;
666       g_decode[i].settings.audio.codec.dolby.dialog_norm = true;
667       g_decode[i].settings.audio.dualmono = baudio_dualmono_stereo;
668        if (bsettop_get_config("dolby_volume")){
669           g_decode[i].settings.audio.postproc.dolby.volume_proc_enable = true;
670        }
671        else {
672           g_decode[i].settings.audio.postproc.dolby.volume_proc_enable = false;
673        }
674
675        if (bsettop_get_config("hold_last_picture"))
676        {
677            g_decode[i].settings.stop_mode = bdecode_stop_mode_last_picture;
678        }
679    }
680}
681
682void bdecode_p_uninit()
683{
684    unsigned i;
685
686    for (i=0;i<B_MAX_DECODES;i++)
687    {
688        if( g_decode[i].video_decode && g_decode[i].video_decode->nVideoDecoder)
689        {
690            bdecode_stop(&g_decode[i]);
691            bdecode_close(&g_decode[i]);
692        }
693    }
694}
695
696bdecode_t bdecode_open(bobject_t decode_id)
697{
698    unsigned index = B_ID_GET_INDEX(decode_id);
699    bdecode_t decode;
700    NEXUS_VideoDecoderSettings  nVideoDecodeSettings;
701    NEXUS_AudioDecoderSettings  nAudioDecodeSettings;
702    NEXUS_StcChannelSettings    nStcChannelSettings;
703    NEXUS_AudioDecoderOpenSettings nAudioDecodeOpenSettings;
704    bsettop_init_settings initSettings;
705    const char* fifo_size=NULL;
706
707    bsettop_get_init_settings(&initSettings);
708
709    if (index >= B_MAX_DECODES+B_MAX_STILL_DECODES)
710    {
711        BSETTOP_ERROR(berr_not_available);
712        return NULL;
713    }
714    decode = &g_decode[index];
715
716    if (index >= B_MAX_DECODES)
717    {
718        /* still decode */
719        /* TODO: must open after main decode */
720        if ( NULL == g_decode[index-B_MAX_DECODES].video_decode ||
721             NULL == g_decode[index-B_MAX_DECODES].video_decode->nVideoDecoder )
722        {
723            BDBG_ERR(("Must open corresponding video decoder first"));
724            BSETTOP_ERROR(berr_not_available);
725            return NULL;
726        }
727        if ( g_decode[index].nStillDecoder )
728        {
729            BDBG_ERR(("Still decoder already open"));
730            BSETTOP_ERROR(berr_not_available);
731            return NULL;
732        }
733        decode->nStillDecoder = NEXUS_StillDecoder_Open(g_decode[index-B_MAX_DECODES].video_decode->nVideoDecoder, 0, NULL);
734        if (!decode->nStillDecoder)
735        {
736            BSETTOP_ERROR(berr_not_available);
737            return NULL;
738        }
739#if 0
740        decode->stillEvent = B_Event_Create(NULL);
741        if ( NULL == decode->stillEvent )
742        {
743            NEXUS_StillDecoder_Close(decode->nStillDecoder);
744            decode->nStillDecoder = NULL;
745            BSETTOP_ERROR(berr_external_error);
746            return NULL;
747        }
748        decode->stillEventId = b_event_register(decode->stillEvent, bdecode_p_still_handler, decode);
749        if ( NULL == decode->stillEventId )
750        {
751            B_Event_Destroy(decode->stillEvent);
752            NEXUS_StillDecoder_Close(decode->nStillDecoder);
753            decode->nStillDecoder = NULL;
754            BSETTOP_ERROR(berr_external_error);
755            return NULL;
756        }
757#endif
758        decode->stillEventCallback= b_callback_create(decode,bdecode_p_still_handler,decode,0);
759        if(decode->stillEventCallback== NULL)
760        {
761            BSETTOP_ERROR(berr_external_error);
762            return NULL;
763        }
764        BDBG_MSG(("bdecode_open %p (still decoder)", decode));
765        return decode;
766    }
767
768    /* open a sync channnel */
769    bdecode_p_open_sync_channel(decode);
770
771    if (decode->video_decode)
772    {
773        NEXUS_VideoDecoderOpenSettings openSettings;
774
775        if (decode->video_decode->nVideoDecoder)
776        {
777            BSETTOP_ERROR(berr_not_available);
778            return NULL;
779        }
780
781        NEXUS_VideoDecoder_GetDefaultOpenSettings(&openSettings);
782        fifo_size=bsettop_get_config("fifo_size");
783        if(fifo_size)
784        {
785            openSettings.fifoSize = atoi(fifo_size)*1000;
786            BDBG_WRN(("****************************************"));
787            BDBG_WRN(("* Changing Video FIFO size to %d bytes *",openSettings.fifoSize));
788            BDBG_WRN(("****************************************"));
789        }
790        else if ( initSettings.video_fifo_size )
791        {
792            openSettings.fifoSize = initSettings.video_fifo_size;
793        }
794
795        decode->video_decode->nVideoDecoder = NEXUS_VideoDecoder_Open(index, &openSettings);
796        if (!decode->video_decode->nVideoDecoder)
797        {
798            BSETTOP_ERROR(berr_external_error);
799            goto error;
800        }
801#if B_HAS_FCC
802                bstream_p_fcc_init(decode->video_decode->nVideoDecoder);
803#endif
804       
805        decode->video_decode->sourceChangedCallback = b_callback_create(decode->video_decode,bdecode_p_video_source_changed,decode,0);
806        if(NULL == decode->video_decode->sourceChangedCallback)
807        {
808            BSETTOP_ERROR(berr_out_of_memory);
809            goto error;
810        }
811        BDBG_MSG(("video_decode->sourceChangedCallback = %p, video_decode->decode = %p",decode->video_decode->sourceChangedCallback,decode->video_decode->decode));
812#if 0
813        decode->video_decode->sourceChangedEvent = B_Event_Create(NULL);
814        if ( NULL == decode->video_decode->sourceChangedEvent )
815        {
816            BSETTOP_ERROR(berr_external_error);
817            goto error;
818        }
819        decode->video_decode->sourceChangedEventId = b_event_register(decode->video_decode->sourceChangedEvent,
820                                                                      bdecode_p_video_source_changed,
821                                                                      decode);
822        if ( NULL == decode->video_decode->sourceChangedEventId )
823        {
824            BSETTOP_ERROR(berr_external_error);
825            goto error;
826        }
827#endif
828
829        /* add source changed callback */
830        NEXUS_VideoDecoder_GetSettings(decode->video_decode->nVideoDecoder,&nVideoDecodeSettings);
831
832        nVideoDecodeSettings.sourceChanged.callback = bdecode_p_source_changed;
833        nVideoDecodeSettings.sourceChanged.context = decode;
834        nVideoDecodeSettings.sourceChanged.param = SOURCE_CHANGE_EVENT_VIDEO;
835
836        if (bsettop_get_config("drop_field_mode")) {
837            nVideoDecodeSettings.dropFieldMode = true;
838        }
839
840        if (NEXUS_VideoDecoder_SetSettings(decode->video_decode->nVideoDecoder,&nVideoDecodeSettings))
841        {
842            BSETTOP_ERROR(berr_external_error);
843            goto error;
844        }
845
846#if B_HAS_ANALOG
847        decode->video_decode->nAnalogVideoDecoder = NEXUS_AnalogVideoDecoder_Open(index, NULL);
848        if (!decode->video_decode->nAnalogVideoDecoder)
849        {
850            BSETTOP_ERROR(berr_external_error);
851            goto error;
852        }
853#endif
854
855        decode->video_decode->nVideoImageInput = NEXUS_VideoImageInput_Open(index, NULL);
856        if (!decode->video_decode->nVideoImageInput)
857        {
858            BSETTOP_ERROR(berr_external_error);
859            goto error;
860        }
861    }
862
863    if (decode->audio_decode)
864    {
865        NEXUS_AudioDecoder_GetDefaultOpenSettings(&nAudioDecodeOpenSettings);
866        nAudioDecodeOpenSettings.multichannelFormat=NEXUS_AudioMultichannelFormat_e5_1;
867        if(bsettop_get_config("spdif_output_delay")|| bsettop_get_config("hdmi_output_delay")||bsettop_get_config("dac_output_delay"))
868            nAudioDecodeOpenSettings.independentDelay=true;
869
870        fifo_size=bsettop_get_config("audio_fifo_size");
871        if(fifo_size)
872        {
873            nAudioDecodeOpenSettings.fifoSize = atoi(fifo_size)*1000;
874            BDBG_WRN(("****************************************"));
875            BDBG_WRN(("* Changing Audio FIFO size to %d bytes *",nAudioDecodeOpenSettings.fifoSize));
876            BDBG_WRN(("****************************************"));
877        }
878        else if ( initSettings.audio_fifo_size )
879        {
880            nAudioDecodeOpenSettings.fifoSize = initSettings.audio_fifo_size;
881        }
882
883        g_n_audio_decoder[index] = decode->audio_decode->nAudioDecoder = NEXUS_AudioDecoder_Open(index, &nAudioDecodeOpenSettings);
884        if (!decode->audio_decode->nAudioDecoder)
885        {
886            BSETTOP_ERROR(berr_external_error);
887            goto error;
888        }
889        NEXUS_AudioDecoder_GetSettings(decode->audio_decode->nAudioDecoder, &nAudioDecodeSettings);
890
891        nAudioDecodeSettings.sourceChanged.callback = bdecode_p_source_changed;
892        nAudioDecodeSettings.sourceChanged.context = decode;
893        nAudioDecodeSettings.sourceChanged.param = SOURCE_CHANGE_EVENT_AUDIO;
894
895        NEXUS_AudioDecoder_SetSettings(decode->audio_decode->nAudioDecoder, &nAudioDecodeSettings);
896
897#if B_HAS_DTS_ENCODE
898        decode->audio_decode->nDtsEncoder=NEXUS_DtsEncode_Open(NULL);
899        if (!decode->audio_decode->nDtsEncoder)
900        {
901            BSETTOP_ERROR(berr_external_error);
902            goto error;
903        }
904#endif
905
906#if B_HAS_AC3_ENCODE
907        decode->audio_decode->nAc3Encoder=NEXUS_Ac3Encode_Open(NULL);
908        if (!decode->audio_decode->nAc3Encoder)
909        {
910            BSETTOP_ERROR(berr_external_error);
911            goto error;
912        }
913#endif
914
915#if B_HAS_SRS_TRUE_VOLUME
916        {
917            NEXUS_TruVolumeSettings trueVolSettings;
918            NEXUS_TruVolume_GetDefaultSettings(&trueVolSettings);
919            trueVolSettings.enabled = false;
920            /*
921            trueVolSettings.enabled = audio_decode->decode->settings.audio.postproc.srs.tru_volume_enable;
922            BDBG_WRN(("true volume %s",audio_decode->decode->settings.audio.postproc.srs.tru_volume_enable?"on":"off"));
923            */ 
924            decode->audio_decode->nTrueVolume = NEXUS_TruVolume_Open(&trueVolSettings);
925            if (!decode->audio_decode->nTrueVolume)
926            {
927                BSETTOP_ERROR(berr_external_error);
928                goto error;
929            }
930        }
931#endif
932
933#if B_HAS_DOLBY_VOLUME
934        {
935            NEXUS_DolbyVolumeSettings dolbyVolSettings;
936            NEXUS_DolbyVolume_GetDefaultSettings(&dolbyVolSettings);
937            dolbyVolSettings.enabled = false;
938            /*
939            dolbyVolSettings.enabled = audio_decode->decode->settings.audio.postproc.dolby.volume_proc_enable;
940            BDBG_WRN(("dolby volume %s",audio_decode->decode->settings.audio.postproc.dolby.volume_proc_enable?"on":"off"));
941            */ 
942            decode->audio_decode->nDolbyVolume = NEXUS_DolbyVolume_Open(&dolbyVolSettings);
943            if (!decode->audio_decode->nDolbyVolume)
944            {
945                BSETTOP_ERROR(berr_external_error);
946                goto error;
947            }
948        }
949#endif
950
951        if(bsettop_get_config("audio_capture"))
952        {
953            baudio_capture_open(decode->audio_decode);
954        }
955
956#if B_HAS_EXTERNAL_ANALOG
957        decode->audio_decode->i2sInput = NEXUS_I2sInput_Open(0, NULL);
958        if ( NULL == decode->audio_decode->i2sInput )
959        {
960            BSETTOP_ERROR(berr_external_error);
961            goto error;
962        }
963#endif
964    }
965    if ( 0 == g_open_audio_decodes++ )
966    {
967        NEXUS_AudioDecoder_GetDefaultOpenSettings(&nAudioDecodeOpenSettings);
968
969        if(bsettop_get_config("spdif_output_delay")|| bsettop_get_config("hdmi_output_delay"))
970            nAudioDecodeOpenSettings.independentDelay=true;
971
972        fifo_size=bsettop_get_config("audio_fifo_size");
973        if(fifo_size)
974        {
975            nAudioDecodeOpenSettings.fifoSize = atoi(fifo_size)*1000;
976            BDBG_WRN(("****************************************"));
977            BDBG_WRN(("* Changing Audio FIFO size to %d bytes *",nAudioDecodeOpenSettings.fifoSize));
978            BDBG_WRN(("****************************************"));
979        }
980
981        g_n_audio_decoder[NEXUS_NUM_AUDIO_DECODERS-1] = g_audio_passthrough = NEXUS_AudioDecoder_Open(NEXUS_NUM_AUDIO_DECODERS-1, &nAudioDecodeOpenSettings);
982        if ( NULL == g_audio_passthrough )
983        {
984            BSETTOP_ERROR(berr_external_error);
985            goto error;
986        }
987        g_audio_passthrough_owner = NULL;
988    }
989#if B_HAS_FCC
990        decode->stcChannel = NULL; /* Will be obtained from stream */
991#else /* B_HAS_FCC */
992    NEXUS_StcChannel_GetDefaultSettings(index, &nStcChannelSettings);
993    /* each decode has its own timebase */
994    nStcChannelSettings.timebase = index;
995    if(bsettop_get_config("use_first_pts"))
996    {
997        BDBG_WRN(("PTS auto behavior default %d,changing to %d",nStcChannelSettings.modeSettings.Auto.behavior,NEXUS_StcChannelAutoModeBehavior_eFirstAvailable));
998        nStcChannelSettings.modeSettings.Auto.behavior=NEXUS_StcChannelAutoModeBehavior_eFirstAvailable;
999    }
1000    decode->stcChannel = NEXUS_StcChannel_Open(index, &nStcChannelSettings);
1001    if (!decode->stcChannel)
1002    {
1003        BSETTOP_ERROR(berr_external_error);
1004        goto error;
1005    }
1006
1007    decode->settings.audio.secondary_audio_program = -1;
1008
1009    bdecode_p_open_astm(decode);
1010#endif /* B_HAS_FCC */
1011
1012    BDBG_MSG(("bdecode_open %p", decode));
1013    return decode;
1014
1015    error:
1016    bdecode_close(decode);
1017    return NULL;
1018}
1019
1020void bdecode_mosaic_settings_init(bdecode_t parent, bdecode_mosaic_settings *settings)
1021{
1022    BSTD_UNUSED(parent);
1023    BKNI_Memset(settings, 0, sizeof(*settings));
1024}
1025
1026bdecode_t bdecode_open_mosaic(bdecode_t parent,bobject_t decode_id, const bdecode_mosaic_settings *settings)
1027{
1028    BSTD_UNUSED(parent);
1029    BSTD_UNUSED(decode_id);
1030    BSTD_UNUSED(settings);
1031    /* TODO */
1032    BSETTOP_ERROR(berr_not_supported);
1033    return NULL;
1034}
1035
1036void bdecode_close(bdecode_t decode)
1037{
1038    BDBG_MSG(("bdecode_close %p", decode));
1039    if (decode->started) {
1040        bdecode_stop(decode);
1041    }
1042
1043    if (decode->nStillDecoder) {
1044        /* just in case it wasn't already stopped */
1045        NEXUS_StillDecoder_Stop(decode->nStillDecoder);
1046        NEXUS_StillDecoder_Close(decode->nStillDecoder);
1047#if 0
1048        b_event_unregister(decode->stillEventId);
1049        B_Event_Destroy(decode->stillEvent);
1050#endif
1051        b_callback_destroy(decode->stillEventCallback);
1052        decode->nStillDecoder = NULL;
1053        return;
1054    }
1055
1056    bdecode_p_close_astm(decode);
1057
1058    /* destroy the any syncChannel is till open */
1059    bdecode_p_close_sync_channel(decode);
1060
1061    if (decode->video_decode && decode->video_decode->nVideoDecoder) {
1062        NEXUS_VideoInput_Shutdown(NEXUS_VideoDecoder_GetConnector(decode->video_decode->nVideoDecoder));
1063        NEXUS_VideoDecoder_Close(decode->video_decode->nVideoDecoder);
1064        decode->video_decode->nVideoDecoder = NULL;
1065#if 0
1066        if ( decode->video_decode->sourceChangedEventId )
1067        {
1068            b_event_unregister(decode->video_decode->sourceChangedEventId);
1069        }
1070        if ( decode->video_decode->sourceChangedEvent )
1071        {
1072            B_Event_Destroy(decode->video_decode->sourceChangedEvent);
1073        }
1074#endif
1075        if (decode->video_decode->sourceChangedCallback)
1076        {
1077            b_callback_destroy(decode->video_decode->sourceChangedCallback);
1078        }
1079       
1080    }
1081#if B_HAS_ANALOG
1082    if (decode->video_decode && decode->video_decode->nAnalogVideoDecoder) {
1083        NEXUS_VideoInput_Shutdown(NEXUS_AnalogVideoDecoder_GetConnector(decode->video_decode->nAnalogVideoDecoder));
1084        NEXUS_AnalogVideoDecoder_Close(decode->video_decode->nAnalogVideoDecoder);
1085        decode->video_decode->nAnalogVideoDecoder = NULL;
1086    }
1087#endif
1088
1089    if (decode->video_decode && decode->video_decode->nVideoImageInput) {
1090        NEXUS_VideoImageInput_Close(decode->video_decode->nVideoImageInput);
1091        decode->video_decode->nVideoImageInput = NULL;
1092    }
1093
1094    if (decode->audio_decode) {
1095
1096#if NEXUS_NUM_AUDIO_CAPTURES
1097        if(bsettop_get_config("audio_capture"))
1098        {
1099            if(decode->audio_decode->nAudioCapture)
1100            {
1101                baudio_capture_close(decode->audio_decode);
1102            }
1103        }
1104#endif
1105       
1106        if (decode->audio_decode->nAudioDecoder) {
1107            int i;
1108            NEXUS_AudioInput_Shutdown(NEXUS_AudioDecoder_GetConnector(decode->audio_decode->nAudioDecoder, NEXUS_AudioDecoderConnectorType_eStereo));
1109            NEXUS_AudioInput_Shutdown(NEXUS_AudioDecoder_GetConnector(decode->audio_decode->nAudioDecoder, NEXUS_AudioDecoderConnectorType_eCompressed));
1110            NEXUS_AudioInput_Shutdown(NEXUS_AudioDecoder_GetConnector(decode->audio_decode->nAudioDecoder, NEXUS_AudioDecoderConnectorType_eMultichannel));
1111            NEXUS_AudioDecoder_Close(decode->audio_decode->nAudioDecoder);
1112            for (i=0;i<NEXUS_NUM_AUDIO_DECODERS;i++)
1113            {
1114                if (decode->audio_decode->nAudioDecoder == g_n_audio_decoder[i])
1115                {
1116                    g_n_audio_decoder[i] = NULL;
1117                }
1118            }
1119            decode->audio_decode->nAudioDecoder = NULL;
1120        }
1121#if B_HAS_DTS_ENCODE
1122        if (decode->audio_decode->nDtsEncoder) {
1123            NEXUS_DtsEncode_RemoveAllInputs(decode->audio_decode->nDtsEncoder);
1124            NEXUS_AudioInput_Shutdown(NEXUS_DtsEncode_GetConnector(decode->audio_decode->nDtsEncoder));
1125            NEXUS_DtsEncode_Close(decode->audio_decode->nDtsEncoder);
1126            decode->audio_decode->nDtsEncoder=NULL;
1127        }
1128#endif
1129
1130#if B_HAS_AC3_ENCODE
1131        if (decode->audio_decode->nAc3Encoder) {
1132            NEXUS_Ac3Encode_RemoveAllInputs(decode->audio_decode->nAc3Encoder);
1133            NEXUS_AudioInput_Shutdown(NEXUS_Ac3Encode_GetConnector(decode->audio_decode->nAc3Encoder));
1134            NEXUS_Ac3Encode_Close(decode->audio_decode->nAc3Encoder);
1135            decode->audio_decode->nAc3Encoder=NULL;
1136        }
1137#endif
1138
1139#if B_HAS_SRS_TRUE_VOLUME
1140        if (decode->audio_decode->nTrueVolume) {
1141            NEXUS_TruVolume_RemoveAllInputs(decode->audio_decode->nTrueVolume);
1142            NEXUS_AudioInput_Shutdown(NEXUS_TruVolume_GetConnector(decode->audio_decode->nTrueVolume));
1143            NEXUS_TruVolume_Close(decode->audio_decode->nTrueVolume);
1144            decode->audio_decode->nTrueVolume=NULL;
1145        }
1146#endif
1147
1148#if B_HAS_DOLBY_VOLUME
1149        if (decode->audio_decode->nDolbyVolume) {
1150            NEXUS_DolbyVolume_RemoveAllInputs(decode->audio_decode->nDolbyVolume);
1151            NEXUS_AudioInput_Shutdown(NEXUS_DolbyVolume_GetConnector(decode->audio_decode->nDolbyVolume));
1152            NEXUS_DolbyVolume_Close(decode->audio_decode->nDolbyVolume);
1153            decode->audio_decode->nDolbyVolume=NULL;
1154        }
1155#endif
1156
1157#if B_HAS_EXTERNAL_ANALOG
1158        if ( decode->audio_decode->i2sInput )
1159        {
1160            NEXUS_AudioInput_Shutdown(NEXUS_I2sInput_GetConnector(decode->audio_decode->i2sInput));
1161            NEXUS_I2sInput_Close(decode->audio_decode->i2sInput);
1162            decode->audio_decode->i2sInput = NULL;
1163        }
1164#endif
1165    }
1166    if ( 0 == --g_open_audio_decodes )
1167    {
1168        if ( NULL != g_audio_passthrough )
1169        {
1170            int i;
1171            NEXUS_AudioInput_Shutdown(NEXUS_AudioDecoder_GetConnector(g_audio_passthrough, NEXUS_AudioDecoderConnectorType_eCompressed));
1172            NEXUS_AudioDecoder_Close(g_audio_passthrough);
1173            for (i=0;i<NEXUS_NUM_AUDIO_DECODERS;i++)
1174            {
1175                if (g_audio_passthrough == g_n_audio_decoder[i])
1176                {
1177                    g_n_audio_decoder[i] = NULL;
1178                }
1179            }
1180            g_audio_passthrough = NULL;
1181        }
1182    }
1183
1184    if (decode->stcChannel) {
1185        NEXUS_StcChannel_Close(decode->stcChannel);
1186        decode->stcChannel = NULL;
1187    }
1188}
1189
1190
1191static bresult bdecode_p_set_downmix(bdecode_t decode)
1192{
1193    NEXUS_AudioDecoderSettings nDecoderSettings;
1194    NEXUS_AudioDecoderCodecSettings nCodecSettings;
1195    int32_t leftVolume=0,rightVolume=0;
1196    int nLeftVolume=0,nRightVolume=0;
1197    NEXUS_Error rc=0;
1198
1199    if (decode->window && decode->audio_decode && decode->audio_decode->nAudioDecoder)
1200    {
1201        NEXUS_AudioDecoder_GetSettings(decode->audio_decode->nAudioDecoder,&nDecoderSettings);
1202
1203        nLeftVolume = b_volume2nexus(decode->volume.left, false, &leftVolume);
1204        nRightVolume = b_volume2nexus(decode->volume.right, false, &rightVolume);
1205
1206        nDecoderSettings.muted = decode->volume.muted;
1207        /* BDBG_MSG(("left 0x%08x %d",nLeftVolume,decode->volume.left)); */
1208
1209        switch (decode->settings.audio.downmix)
1210        {
1211        case baudio_downmix_stereo: /* If applicable, down mix source to stereo output [default]. */
1212        case baudio_downmix_multichannel: /* Output decoded data as-is. If number of channels exceeds HW capabilities,
1213                                            downmix to match maximum number of output channels. No audio will be lost. */
1214        case baudio_downmix_none: /* Output decoded data as-is. If number of channels exceeds HW capabilities,
1215                                    additional audio channels will be lost. */
1216            nDecoderSettings.volumeMatrix[NEXUS_AudioChannel_eLeft][NEXUS_AudioChannel_eLeft] = nLeftVolume;
1217            nDecoderSettings.volumeMatrix[NEXUS_AudioChannel_eRight][NEXUS_AudioChannel_eRight] = nRightVolume;
1218            nDecoderSettings.volumeMatrix[NEXUS_AudioChannel_eLeft][NEXUS_AudioChannel_eRight] = 0;
1219            nDecoderSettings.volumeMatrix[NEXUS_AudioChannel_eRight][NEXUS_AudioChannel_eLeft] = 0;
1220            BDBG_WRN(("Setting standard downmix mode"));
1221            break;
1222
1223        case baudio_downmix_left: /* Take left channel and duplicate to left/right outputs. */
1224            nDecoderSettings.volumeMatrix[NEXUS_AudioChannel_eLeft][NEXUS_AudioChannel_eLeft] = nLeftVolume;
1225            nDecoderSettings.volumeMatrix[NEXUS_AudioChannel_eRight][NEXUS_AudioChannel_eRight] = 0;
1226            nDecoderSettings.volumeMatrix[NEXUS_AudioChannel_eLeft][NEXUS_AudioChannel_eRight] = 0;
1227            nDecoderSettings.volumeMatrix[NEXUS_AudioChannel_eRight][NEXUS_AudioChannel_eLeft] = nRightVolume;
1228            BDBG_WRN(("Setting downmix left"));
1229
1230            break;
1231        case baudio_downmix_right: /* Take right channel and duplicate to left/right outputs. */
1232            nDecoderSettings.volumeMatrix[NEXUS_AudioChannel_eLeft][NEXUS_AudioChannel_eLeft] = 0;
1233            nDecoderSettings.volumeMatrix[NEXUS_AudioChannel_eRight][NEXUS_AudioChannel_eRight] = nRightVolume;
1234            nDecoderSettings.volumeMatrix[NEXUS_AudioChannel_eLeft][NEXUS_AudioChannel_eRight] = nLeftVolume;
1235            nDecoderSettings.volumeMatrix[NEXUS_AudioChannel_eRight][NEXUS_AudioChannel_eLeft] = 0;
1236            BDBG_WRN(("Setting downmix right"));
1237            break;
1238        case baudio_downmix_monomix:  /* Mix left and right channels and output result to left/right outputs. This only applies if the stream
1239                                        is a dual mono stream. If not, it will be equivalent to baudio_downmix_stereo. */
1240            nDecoderSettings.volumeMatrix[NEXUS_AudioChannel_eLeft][NEXUS_AudioChannel_eLeft] = nLeftVolume/2;
1241            nDecoderSettings.volumeMatrix[NEXUS_AudioChannel_eRight][NEXUS_AudioChannel_eRight] = nRightVolume/2;
1242            nDecoderSettings.volumeMatrix[NEXUS_AudioChannel_eLeft][NEXUS_AudioChannel_eRight] = nLeftVolume/2;
1243            nDecoderSettings.volumeMatrix[NEXUS_AudioChannel_eRight][NEXUS_AudioChannel_eLeft] = nRightVolume/2;
1244            BDBG_WRN(("Setting downmix monomix"));
1245            break;
1246        }
1247        rc = NEXUS_AudioDecoder_SetSettings(decode->audio_decode->nAudioDecoder,&nDecoderSettings);
1248        if (rc) return BSETTOP_ERROR(rc);
1249
1250        switch (decode->settings.audio.codec.aac.downmix)
1251        {
1252        case baudio_aac_downmix_matrix:
1253            NEXUS_AudioDecoder_GetCodecSettings(decode->audio_decode->nAudioDecoder, NEXUS_AudioCodec_eAacAdts, &nCodecSettings);
1254            nCodecSettings.codecSettings.aac.downmixMode = NEXUS_AudioDecoderAacDownmixMode_eMatrix;
1255            rc = NEXUS_AudioDecoder_SetCodecSettings(decode->audio_decode->nAudioDecoder, &nCodecSettings);
1256            if (rc) return BSETTOP_ERROR(rc);
1257            NEXUS_AudioDecoder_GetCodecSettings(decode->audio_decode->nAudioDecoder, NEXUS_AudioCodec_eAacLoas, &nCodecSettings);
1258            nCodecSettings.codecSettings.aac.downmixMode = NEXUS_AudioDecoderAacDownmixMode_eMatrix;
1259            rc = NEXUS_AudioDecoder_SetCodecSettings(decode->audio_decode->nAudioDecoder, &nCodecSettings);
1260            if (rc) return BSETTOP_ERROR(rc);
1261            NEXUS_AudioDecoder_GetCodecSettings(decode->audio_decode->nAudioDecoder, NEXUS_AudioCodec_eAacPlusAdts, &nCodecSettings);
1262            nCodecSettings.codecSettings.aacPlus.downmixMode = NEXUS_AudioDecoderAacDownmixMode_eMatrix;
1263            rc = NEXUS_AudioDecoder_SetCodecSettings(decode->audio_decode->nAudioDecoder, &nCodecSettings);
1264            if (rc) return BSETTOP_ERROR(rc);
1265            NEXUS_AudioDecoder_GetCodecSettings(decode->audio_decode->nAudioDecoder, NEXUS_AudioCodec_eAacPlusLoas, &nCodecSettings);
1266            nCodecSettings.codecSettings.aacPlus.downmixMode = NEXUS_AudioDecoderAacDownmixMode_eMatrix;
1267            rc = NEXUS_AudioDecoder_SetCodecSettings(decode->audio_decode->nAudioDecoder, &nCodecSettings);
1268            if (rc) return BSETTOP_ERROR(rc);
1269            BDBG_WRN(("Setting downmix type to (BRCM) matrix"));
1270            break;
1271        case baudio_aac_downmix_arib:
1272            NEXUS_AudioDecoder_GetCodecSettings(decode->audio_decode->nAudioDecoder, NEXUS_AudioCodec_eAacAdts, &nCodecSettings);
1273            nCodecSettings.codecSettings.aac.downmixMode = NEXUS_AudioDecoderAacDownmixMode_eArib;
1274            rc = NEXUS_AudioDecoder_SetCodecSettings(decode->audio_decode->nAudioDecoder, &nCodecSettings);
1275            if (rc) return BSETTOP_ERROR(rc);
1276            NEXUS_AudioDecoder_GetCodecSettings(decode->audio_decode->nAudioDecoder, NEXUS_AudioCodec_eAacLoas, &nCodecSettings);
1277            nCodecSettings.codecSettings.aac.downmixMode = NEXUS_AudioDecoderAacDownmixMode_eArib;
1278            rc = NEXUS_AudioDecoder_SetCodecSettings(decode->audio_decode->nAudioDecoder, &nCodecSettings);
1279            if (rc) return BSETTOP_ERROR(rc);
1280            NEXUS_AudioDecoder_GetCodecSettings(decode->audio_decode->nAudioDecoder, NEXUS_AudioCodec_eAacPlusAdts, &nCodecSettings);
1281            nCodecSettings.codecSettings.aacPlus.downmixMode = NEXUS_AudioDecoderAacDownmixMode_eArib;
1282            rc = NEXUS_AudioDecoder_SetCodecSettings(decode->audio_decode->nAudioDecoder, &nCodecSettings);
1283            if (rc) return BSETTOP_ERROR(rc);
1284            NEXUS_AudioDecoder_GetCodecSettings(decode->audio_decode->nAudioDecoder, NEXUS_AudioCodec_eAacPlusLoas, &nCodecSettings);
1285            nCodecSettings.codecSettings.aacPlus.downmixMode = NEXUS_AudioDecoderAacDownmixMode_eArib;
1286            rc = NEXUS_AudioDecoder_SetCodecSettings(decode->audio_decode->nAudioDecoder, &nCodecSettings);
1287            if (rc) return BSETTOP_ERROR(rc);
1288            BDBG_WRN(("Setting downmix type to ARIB"));
1289            break;
1290        case baudio_aac_downmix_ltrt:
1291            NEXUS_AudioDecoder_GetCodecSettings(decode->audio_decode->nAudioDecoder, NEXUS_AudioCodec_eAacAdts, &nCodecSettings);
1292            nCodecSettings.codecSettings.aac.downmixMode = NEXUS_AudioDecoderAacDownmixMode_eLtRt;
1293            rc = NEXUS_AudioDecoder_SetCodecSettings(decode->audio_decode->nAudioDecoder, &nCodecSettings);
1294            if (rc) return BSETTOP_ERROR(rc);
1295            NEXUS_AudioDecoder_GetCodecSettings(decode->audio_decode->nAudioDecoder, NEXUS_AudioCodec_eAacLoas, &nCodecSettings);
1296            nCodecSettings.codecSettings.aac.downmixMode = NEXUS_AudioDecoderAacDownmixMode_eLtRt;
1297            rc = NEXUS_AudioDecoder_SetCodecSettings(decode->audio_decode->nAudioDecoder, &nCodecSettings);
1298            if (rc) return BSETTOP_ERROR(rc);
1299            NEXUS_AudioDecoder_GetCodecSettings(decode->audio_decode->nAudioDecoder, NEXUS_AudioCodec_eAacPlusAdts, &nCodecSettings);
1300            nCodecSettings.codecSettings.aacPlus.downmixMode = NEXUS_AudioDecoderAacDownmixMode_eLtRt;
1301            rc = NEXUS_AudioDecoder_SetCodecSettings(decode->audio_decode->nAudioDecoder, &nCodecSettings);
1302            if (rc) return BSETTOP_ERROR(rc);
1303            NEXUS_AudioDecoder_GetCodecSettings(decode->audio_decode->nAudioDecoder, NEXUS_AudioCodec_eAacPlusLoas, &nCodecSettings);
1304            nCodecSettings.codecSettings.aacPlus.downmixMode = NEXUS_AudioDecoderAacDownmixMode_eLtRt;
1305            rc = NEXUS_AudioDecoder_SetCodecSettings(decode->audio_decode->nAudioDecoder, &nCodecSettings);
1306            if (rc) return BSETTOP_ERROR(rc);
1307            BDBG_WRN(("Setting downmix type to ARIB"));
1308            break;
1309        }
1310
1311        bdisplay_p_set_compressed_mute(decode->window->display, decode->volume.muted);
1312    }
1313    return 0;
1314
1315}
1316
1317void bdecode_get(bdecode_t decode, bdecode_settings *settings)
1318{
1319    *settings = decode->settings;
1320}
1321
1322bresult bdecode_set(bdecode_t decode, const bdecode_settings *settings)
1323{
1324
1325    NEXUS_AudioDecoderSettings nDecoderSettings;
1326
1327    if ( decode->audio_decode )
1328    {
1329        if ( decode->settings.audio.display != settings->audio.display )
1330        {
1331            if ( decode->started )
1332            {
1333                BDBG_ERR(("Cannot change audio display while running."));
1334                return BSETTOP_ERROR(berr_busy);
1335            }
1336            if ( settings->audio.display && settings->audio.display->mixerInputsStarted > 0 )
1337            {
1338                return BSETTOP_ERROR(berr_busy);
1339            }
1340            if ( decode->settings.audio.display && decode->settings.audio.display->mixerInputsStarted )
1341            {
1342                return BSETTOP_ERROR(berr_busy);
1343            }
1344            if ( decode->settings.audio.display )
1345            {
1346                bdecode_p_set_audio_display(decode->audio_decode, NULL);
1347                decode->settings.audio.display = NULL;
1348            }
1349            if ( settings->audio.display )
1350            {
1351                bdecode_p_set_audio_display(decode->audio_decode, settings->audio.display);
1352                decode->settings.audio.display = settings->audio.display;
1353            }
1354        }
1355    }
1356
1357    /* set dual mono mode */
1358    if (decode->audio_decode && decode->audio_decode->nAudioDecoder)
1359    {
1360        if ( decode->settings.audio.dualmono != settings->audio.dualmono )
1361        {
1362            BDBG_WRN(("Setting dual mono %d",settings->audio.dualmono));
1363            NEXUS_AudioDecoder_GetSettings(decode->audio_decode->nAudioDecoder,&nDecoderSettings);
1364            switch (settings->audio.dualmono)
1365            {
1366            case baudio_dualmono_left:
1367                nDecoderSettings.dualMonoMode = NEXUS_AudioDecoderDualMonoMode_eLeft;
1368                break;
1369            case baudio_dualmono_right:
1370                nDecoderSettings.dualMonoMode = NEXUS_AudioDecoderDualMonoMode_eRight;
1371                break;
1372            case baudio_dualmono_stereo:
1373                nDecoderSettings.dualMonoMode = NEXUS_AudioDecoderDualMonoMode_eStereo;
1374                break;
1375            case baudio_dualmono_monomix:
1376                nDecoderSettings.dualMonoMode = NEXUS_AudioDecoderDualMonoMode_eMix;
1377                break;
1378            }
1379            NEXUS_AudioDecoder_SetSettings(decode->audio_decode->nAudioDecoder,&nDecoderSettings);
1380        }       
1381    }
1382
1383    /* set Dolby decoder configuration settings */
1384    if (decode->audio_decode && decode->audio_decode->nAudioDecoder)
1385    {
1386        NEXUS_Error rc;
1387        NEXUS_AudioDecoderCodecSettings nCodecSettings,newCodecSettings;
1388        NEXUS_AudioDecoderStatus nDecoderStatus;
1389        /* coverity[check_return] */ /* coverity[unchecked_value] */
1390        NEXUS_AudioDecoder_GetStatus(decode->audio_decode->nAudioDecoder,&nDecoderStatus);
1391
1392        switch(nDecoderStatus.codec)
1393        {
1394        case NEXUS_AudioCodec_eAc3:
1395        NEXUS_AudioDecoder_GetCodecSettings(decode->audio_decode->nAudioDecoder, NEXUS_AudioCodec_eAc3, &nCodecSettings);
1396        newCodecSettings = nCodecSettings;
1397        newCodecSettings.codecSettings.ac3.drcMode = baudio_dolby_drc_mode_to_nexus_ac3plus_comp_mode(settings->audio.codec.dolby.drc_mode);
1398        newCodecSettings.codecSettings.ac3.stereoDownmixMode = baudio_dolby_stereo_downmix_mode_to_nexus_ac3plus_stereo_mode(settings->audio.codec.dolby.stereo_downmix_mode); 
1399        newCodecSettings.codecSettings.ac3.cut = settings->audio.codec.dolby.cut;
1400        newCodecSettings.codecSettings.ac3.boost = settings->audio.codec.dolby.boost;
1401        newCodecSettings.codecSettings.ac3.dialogNormalization = settings->audio.codec.dolby.dialog_norm;
1402        BDBG_MSG(("ac3.drcMode = %d",newCodecSettings.codecSettings.ac3.drcMode));
1403        BDBG_MSG(("ac3.stereoDownmixMode = %d",newCodecSettings.codecSettings.ac3.stereoDownmixMode));
1404        BDBG_MSG(("ac3.cut = %d",newCodecSettings.codecSettings.ac3.cut));
1405        BDBG_MSG(("ac3.boost = %d",newCodecSettings.codecSettings.ac3.boost));
1406        BDBG_MSG(("ac3.dialogNormalization = %d",newCodecSettings.codecSettings.ac3.dialogNormalization));
1407        /* note that settings->audio.codec.dolby.lfe is not yet supported by Nexus */
1408        if ( (newCodecSettings.codecSettings.ac3.drcMode != nCodecSettings.codecSettings.ac3.drcMode) || 
1409             (newCodecSettings.codecSettings.ac3.stereoDownmixMode != nCodecSettings.codecSettings.ac3.stereoDownmixMode) || 
1410             (newCodecSettings.codecSettings.ac3.cut != nCodecSettings.codecSettings.ac3.cut) || 
1411             (newCodecSettings.codecSettings.ac3.boost != nCodecSettings.codecSettings.ac3.boost) || 
1412             (newCodecSettings.codecSettings.ac3.dialogNormalization != nCodecSettings.codecSettings.ac3.dialogNormalization) )
1413        {   /* Only set these if they've changed. */
1414            rc = NEXUS_AudioDecoder_SetCodecSettings(decode->audio_decode->nAudioDecoder, &newCodecSettings);
1415            if (rc) {return BSETTOP_ERROR(rc);}
1416        }
1417            break;
1418        case NEXUS_AudioCodec_eAc3Plus:
1419        NEXUS_AudioDecoder_GetCodecSettings(decode->audio_decode->nAudioDecoder, NEXUS_AudioCodec_eAc3Plus, &nCodecSettings);
1420        newCodecSettings = nCodecSettings;
1421        newCodecSettings.codecSettings.ac3Plus.drcMode = baudio_dolby_drc_mode_to_nexus_ac3plus_comp_mode(settings->audio.codec.dolby.drc_mode);
1422        newCodecSettings.codecSettings.ac3Plus.stereoDownmixMode = baudio_dolby_stereo_downmix_mode_to_nexus_ac3plus_stereo_mode(settings->audio.codec.dolby.stereo_downmix_mode); 
1423        newCodecSettings.codecSettings.ac3Plus.cut = settings->audio.codec.dolby.cut;
1424        newCodecSettings.codecSettings.ac3Plus.boost = settings->audio.codec.dolby.boost;
1425        newCodecSettings.codecSettings.ac3Plus.dialogNormalization = settings->audio.codec.dolby.dialog_norm;
1426        BDBG_MSG(("ac3Plus.drcMode = %d",newCodecSettings.codecSettings.ac3Plus.drcMode));
1427        BDBG_MSG(("ac3Plus.stereoDownmixMode = %d",newCodecSettings.codecSettings.ac3Plus.stereoDownmixMode));
1428        BDBG_MSG(("ac3Plus.cut = %d",newCodecSettings.codecSettings.ac3Plus.cut));
1429        BDBG_MSG(("ac3Plus.boost = %d",newCodecSettings.codecSettings.ac3Plus.boost));
1430        BDBG_MSG(("ac3Plus.dialogNormalization = %d",newCodecSettings.codecSettings.ac3Plus.dialogNormalization));
1431        /* note that settings->audio.codec.dolby.lfe is not yet supported by Nexus */
1432        if ( (newCodecSettings.codecSettings.ac3Plus.drcMode != nCodecSettings.codecSettings.ac3Plus.drcMode) || 
1433             (newCodecSettings.codecSettings.ac3Plus.stereoDownmixMode != nCodecSettings.codecSettings.ac3Plus.stereoDownmixMode) || 
1434             (newCodecSettings.codecSettings.ac3Plus.cut != nCodecSettings.codecSettings.ac3Plus.cut) || 
1435             (newCodecSettings.codecSettings.ac3Plus.boost != nCodecSettings.codecSettings.ac3Plus.boost)  || 
1436             (newCodecSettings.codecSettings.ac3Plus.dialogNormalization != nCodecSettings.codecSettings.ac3Plus.dialogNormalization) )
1437        {   /* Only set these if they've changed. */
1438            rc = NEXUS_AudioDecoder_SetCodecSettings(decode->audio_decode->nAudioDecoder, &newCodecSettings);
1439            if (rc) {return BSETTOP_ERROR(rc);}
1440        }
1441            break;
1442        case NEXUS_AudioCodec_eAac:            /* Advanced audio coding. Part of MPEG-4 */
1443        case NEXUS_AudioCodec_eAacLoas:        /* Advanced audio coding. Part of MPEG-4 */
1444            NEXUS_AudioDecoder_GetCodecSettings(decode->audio_decode->nAudioDecoder, nDecoderStatus.codec, &nCodecSettings);
1445            newCodecSettings = nCodecSettings;
1446            newCodecSettings.codecSettings.aac.downmixMode = settings->audio.codec.aac.downmix; 
1447           
1448            BDBG_MSG(("aac.downmix = %d",newCodecSettings.codecSettings.aac.downmixMode ));
1449           
1450            /* note that settings->audio.codec.dolby.lfe is not yet supported by Nexus */
1451            if (newCodecSettings.codecSettings.aac.downmixMode != nCodecSettings.codecSettings.aac.downmixMode )
1452            {   /* Only set these if they've changed. */
1453                rc = NEXUS_AudioDecoder_SetCodecSettings(decode->audio_decode->nAudioDecoder, &newCodecSettings);
1454                if (rc) {return BSETTOP_ERROR(rc);}
1455            }
1456            break;
1457        case NEXUS_AudioCodec_eAacPlus:        /* AAC plus SBR. aka MPEG-4 High Efficiency (AAC-HE) with ADTS (Audio Data Transport Format) */
1458        case NEXUS_AudioCodec_eAacPlusAdts:
1459            NEXUS_AudioDecoder_GetCodecSettings(decode->audio_decode->nAudioDecoder, nDecoderStatus.codec, &nCodecSettings);
1460            newCodecSettings = nCodecSettings;
1461            newCodecSettings.codecSettings.aacPlus.downmixMode = settings->audio.codec.aac.downmix; 
1462           
1463            BDBG_MSG(("aacPlus.downmix = %d",newCodecSettings.codecSettings.aacPlus.downmixMode ));
1464           
1465            /* note that settings->audio.codec.dolby.lfe is not yet supported by Nexus */
1466            if (newCodecSettings.codecSettings.aacPlus.downmixMode != nCodecSettings.codecSettings.aacPlus.downmixMode )
1467            {   /* Only set these if they've changed. */
1468                rc = NEXUS_AudioDecoder_SetCodecSettings(decode->audio_decode->nAudioDecoder, &newCodecSettings);
1469                if (rc) {return BSETTOP_ERROR(rc);}
1470            }
1471            break;
1472            break;
1473        default:
1474            break;
1475        }
1476    }
1477
1478#if B_HAS_SRS_TRUE_VOLUME
1479    if(decode->audio_decode && decode->audio_decode->nTrueVolume)
1480    {
1481        NEXUS_TruVolumeSettings nTrueVolumeSettings;
1482        NEXUS_TruVolume_GetSettings(decode->audio_decode->nTrueVolume,&nTrueVolumeSettings);
1483        nTrueVolumeSettings.enabled = settings->audio.postproc.srs.tru_volume_enable;
1484        BDBG_WRN(("true volume %s",nTrueVolumeSettings.enabled?"on":"off"));
1485        NEXUS_TruVolume_SetSettings(decode->audio_decode->nTrueVolume,&nTrueVolumeSettings);
1486    }
1487#endif
1488
1489#if B_HAS_DOLBY_VOLUME
1490    if(decode->audio_decode && decode->audio_decode->nDolbyVolume)
1491    {
1492        NEXUS_DolbyVolumeSettings nDolbyVolumeSettings;
1493        NEXUS_DolbyVolume_GetSettings(decode->audio_decode->nDolbyVolume,&nDolbyVolumeSettings);
1494        nDolbyVolumeSettings.enabled = settings->audio.postproc.dolby.volume_proc_enable;
1495        BDBG_WRN(("dolby volume %s",nDolbyVolumeSettings.enabled?"on":"off"));
1496        NEXUS_DolbyVolume_SetSettings(decode->audio_decode->nDolbyVolume,&nDolbyVolumeSettings);
1497    }
1498#endif
1499
1500    /* Settings are applied later on next bdecode_start except for freeze and stop_mode */
1501    decode->settings = *settings;
1502
1503    if (decode->video_decode)
1504    {
1505        NEXUS_Error rc;
1506        NEXUS_VideoDecoderSettings nVideoDecodeSettings;
1507
1508        NEXUS_VideoDecoder_GetSettings(decode->video_decode->nVideoDecoder, &nVideoDecodeSettings);
1509
1510        switch (decode->settings.stop_mode)
1511        {
1512        case bdecode_stop_mode_last_picture:
1513            nVideoDecodeSettings.channelChangeMode = NEXUS_VideoDecoder_ChannelChangeMode_eHoldUntilFirstPicture;
1514            break;
1515        default:
1516            nVideoDecodeSettings.channelChangeMode = NEXUS_VideoDecoder_ChannelChangeMode_eMute;
1517            break;
1518        }
1519
1520        nVideoDecodeSettings.freeze = settings->video.freeze;
1521
1522        rc = NEXUS_VideoDecoder_SetSettings(decode->video_decode->nVideoDecoder, &nVideoDecodeSettings);
1523        if (rc) {return BSETTOP_ERROR(rc);}
1524    }
1525
1526    return 0;
1527}
1528
1529bresult bdecode_display_surface(bdecode_t decode, bsurface_t surface, bdecode_window_t window)
1530{
1531    NEXUS_Error rc;
1532
1533    if (!decode->video_decode) {
1534        return BSETTOP_ERROR(berr_not_available);
1535    }
1536    if (decode->started) {
1537        bdecode_stop(decode);
1538    }
1539
1540    rc = NEXUS_VideoImageInput_SetSurface(decode->video_decode->nVideoImageInput, surface->nSurface);
1541    if (rc) return BSETTOP_ERROR(rc);
1542
1543    if (!decode->image_input_started) {
1544        rc = NEXUS_VideoWindow_AddInput(window->nWindow, NEXUS_VideoImageInput_GetConnector(decode->video_decode->nVideoImageInput));
1545        if (rc) return BSETTOP_ERROR(rc);
1546
1547        decode->image_input_started = true;
1548    }
1549
1550    return 0;
1551}
1552
1553/* bdecode_p_set_video_input allows the VDC window to be torn down only if there's an input change
1554This is needed for hold_last_picture mode. */
1555static void bdecode_p_set_video_input(bdecode_window_t window, NEXUS_VideoInput videoInput)
1556{
1557    if (videoInput != window->currentVideoInput) {
1558        if (window->currentVideoInput) {
1559            if (window->clone) {
1560                /* VDC requires that clone be destroyed first */
1561                NEXUS_VideoWindow_RemoveInput(window->clone->nWindow, window->currentVideoInput);
1562            }
1563            NEXUS_VideoWindow_RemoveInput(window->nWindow, window->currentVideoInput);
1564        }
1565        window->currentVideoInput = videoInput;
1566        if (videoInput) {
1567            bsettop_init_settings initSettings;
1568            bsettop_get_init_settings(&initSettings);
1569            if ( !initSettings.sync_path_swap )
1570            {
1571                /* Add primary window before clone normally */
1572                NEXUS_VideoWindow_AddInput(window->nWindow, videoInput);
1573            }
1574            if (window->clone) 
1575            {
1576                NEXUS_VideoWindow_AddInput(window->clone->nWindow, videoInput);
1577            }
1578            if ( initSettings.sync_path_swap )
1579            {
1580                /* Add primary window after clone if sync paths are swapped */
1581                NEXUS_VideoWindow_AddInput(window->nWindow, videoInput);
1582            }
1583        }
1584    }
1585}
1586
1587#if B_HAS_ANALOG
1588static bresult bdecode_p_start_analog_video(bvideo_decode_t video_decode, bstream_t source, bdecode_window_t window)
1589{
1590    if (!video_decode->nAnalogVideoDecoder) {
1591        return BSETTOP_ERROR(berr_not_available);
1592    }
1593    btuner_p_set_analog_input(video_decode->nAnalogVideoDecoder, source->producer.tuner, source->producer.linein);
1594
1595    bdecode_p_set_video_input(window, NEXUS_AnalogVideoDecoder_GetConnector(video_decode->nAnalogVideoDecoder));
1596
1597    video_decode->started = true;
1598
1599    return 0;
1600}
1601#endif
1602
1603#if B_HAS_EXTERNAL_ANALOG
1604static bresult bdecode_p_start_656_video(bvideo_decode_t video_decode, bstream_t source, bdecode_window_t window)
1605{
1606    NEXUS_Ccir656InputHandle ccir656Input = NEXUS_Ccir656Input_Open(0, NULL);
1607    BSTD_UNUSED(source);
1608    BDBG_MSG(("Start 656 input"));
1609    video_decode->ccir656Input = ccir656Input;
1610    bdecode_p_set_video_input(window, NEXUS_Ccir656Input_GetConnector(ccir656Input));
1611    video_decode->started = true;
1612    return 0;
1613}
1614#endif
1615
1616static bresult bdecode_set_video_ip_tsm_settings(bvideo_decode_t video_decode)
1617{
1618#ifdef B_HAS_IP
1619    if (video_decode && video_decode->nVideoDecoder)
1620    {
1621        NEXUS_VideoDecoderSettings  nVideoDecodeSettings;
1622
1623        NEXUS_VideoDecoder_GetSettings(video_decode->nVideoDecoder, &nVideoDecodeSettings);
1624        switch (video_decode->decode->cfg_type) {
1625        case BDECODE_STC_CHANNEL_CFG_TYPE_PARSER_BAND:
1626            nVideoDecodeSettings.ptsOffset = 0;
1627            break;
1628        case BDECODE_STC_CHANNEL_CFG_TYPE_TTS_PACING:
1629        case BDECODE_STC_CHANNEL_CFG_TYPE_PCR_PACING:
1630            nVideoDecodeSettings.ptsOffset = 0;
1631            break;
1632        case BDECODE_STC_CHANNEL_CFG_TYPE_IP_LIVE_PB:
1633            nVideoDecodeSettings.ptsOffset = 45 * IP_NETWORK_JITTER;
1634            break;
1635        case BDECODE_STC_CHANNEL_CFG_TYPE_PVR_PB:
1636            nVideoDecodeSettings.ptsOffset = 0;
1637            break;
1638        default:
1639            return BSETTOP_ERROR(berr_invalid_parameter);
1640            break;
1641        }
1642        if (NEXUS_VideoDecoder_SetSettings(video_decode->nVideoDecoder, &nVideoDecodeSettings))
1643        {
1644            return BSETTOP_ERROR(berr_external_error);
1645        }
1646    }
1647    return b_ok;
1648#else
1649    BSTD_UNUSED(video_decode);
1650    return (berr_not_supported);
1651#endif
1652}
1653
1654bresult bdecode_start_video(bvideo_decode_t video_decode, bstream_t source, bdecode_window_t window)
1655{
1656    uint16_t pid;
1657    NEXUS_Error rc;
1658    NEXUS_VideoDecoderStartSettings startSettings;
1659    bsettop_init_settings initSettings;
1660    bsettop_get_init_settings(&initSettings);
1661
1662    if (initSettings.lipsync_mode == bsettop_lipsync_mode_disabled) {
1663        video_decode->decode->tsm = false;
1664    }
1665
1666#if B_HAS_ANALOG
1667    if (source->producer.tuner) {
1668        return bdecode_p_start_analog_video(video_decode, source, window);
1669    }
1670#endif
1671#if B_HAS_EXTERNAL_ANALOG
1672    if (source->producer.tuner) {
1673        return bdecode_p_start_656_video(video_decode, source, window);
1674    }
1675#endif
1676    if (!video_decode->nVideoDecoder) {
1677        return BSETTOP_ERROR(berr_not_available);
1678    }
1679    if (window->parent) {
1680        BDBG_ERR(("can't start decode on cloned window"));
1681        return BSETTOP_ERROR(berr_not_available);
1682    }
1683
1684    BDBG_MSG(("start_video decode %p,src stream %p,window %p,zorder %d,%s",
1685              video_decode,source,window,window->settings.zorder,video_decode->decode->tsm?"TSM":"VSYNC"));
1686
1687    BDBG_MSG(("video stc channel %p",video_decode->decode->stcChannel));
1688
1689    pid = source->mpeg.video[video_decode->decode->video_program].pid;
1690    if ( pid == 0 || pid >= 0x1fff )
1691    {
1692        /* No video */
1693        return b_ok;
1694    }
1695
1696        if (source->producer.fcc.videoPidChannel)
1697        {
1698                video_decode->nPidChannel = source->producer.fcc.videoPidChannel;
1699        }
1700        else
1701        {
1702                video_decode->nPidChannel = bstream_p_open_pid(source, pid, bstream_pid_type_video);
1703                if ( NULL == video_decode->nPidChannel )
1704                {
1705                        BDBG_ERR(("Unable to allocate PID channel for video program"));
1706                        return BSETTOP_ERROR(berr_invalid_parameter);
1707                }
1708        }
1709
1710    bdecode_p_set_video_input(window, NEXUS_VideoDecoder_GetConnector(video_decode->nVideoDecoder));
1711
1712    /* ip TSM related settings: specify additional pts offset & override decoder playback mode */
1713    bdecode_set_video_ip_tsm_settings(video_decode);
1714
1715    NEXUS_VideoDecoder_GetDefaultStartSettings(&startSettings);
1716#if 0 /* TODO: decoder feature is being reworked. use host-reordering in the meantime */
1717    startSettings.timestampMode = (NEXUS_VideoDecoderTimestampMode)source->mpeg.timestamp_order;
1718#endif
1719    startSettings.pidChannel = video_decode->nPidChannel;
1720    startSettings.codec = b_videocodec2nexus(source->mpeg.video[video_decode->decode->video_program].format);
1721    startSettings.stcChannel = video_decode->decode->tsm? video_decode->decode->stcChannel : NULL;
1722
1723    if (bsettop_get_config("preroll_rate")) {
1724        startSettings.prerollRate = atoi(bsettop_get_config("preroll_rate"));
1725    }
1726   
1727    if (video_decode->decode->primerStart.stcChannel && !source->producer.playback) {
1728        startSettings.pidChannel = video_decode->decode->primerStart.pidChannel;
1729        startSettings.stcChannel = video_decode->decode->tsm? video_decode->decode->primerStart.stcChannel : NULL;
1730    }
1731
1732    /* set the sync channel for video decoder */
1733    bdecode_p_set_sync_channel(video_decode->decode, true,false,false);
1734    bdecode_p_set_astm(video_decode->decode, true,false,false);
1735
1736        if (source->producer.fcc.primerHandle)
1737        {
1738                rc = NEXUS_VideoDecoder_StartDecodeWithPrimer(video_decode->nVideoDecoder,source->producer.fcc.primerHandle);
1739                if (rc)
1740                {
1741                        BSETTOP_ERROR(berr_external_error);
1742                }
1743        }
1744        else
1745        {
1746                rc = NEXUS_VideoDecoder_Start(video_decode->nVideoDecoder, &startSettings);
1747                if (rc)
1748                {
1749                        BSETTOP_ERROR(berr_external_error);
1750                }
1751        }
1752
1753#if NEXUS_HAS_PLAYBACK
1754    if (source->producer.playback) {
1755        /* update playback pidchannel */
1756        NEXUS_PlaybackPidChannelSettings settings;
1757        NEXUS_Playback_GetPidChannelSettings(source->producer.playback->nPlayback, video_decode->nPidChannel, &settings);
1758                BDBG_ASSERT(settings.pidSettings.pidType == NEXUS_PidType_eVideo);
1759                settings.pidTypeSettings.video.decoder = video_decode->nVideoDecoder;
1760        NEXUS_Playback_SetPidChannelSettings(source->producer.playback->nPlayback, video_decode->nPidChannel, &settings);
1761    }
1762#endif
1763
1764    video_decode->started = true;
1765
1766    return 0;
1767}
1768
1769#if B_HAS_ANALOG
1770static void bdecode_p_stop_analog_video(bvideo_decode_t video_decode)
1771{
1772    bdecode_window_t window = video_decode->decode->window;
1773
1774    if (video_decode->decode->settings.stop_mode == bdecode_stop_mode_mute) {
1775        bdecode_p_set_video_input(window, NULL);
1776    }
1777    video_decode->started = false;
1778}
1779#endif
1780
1781#if B_HAS_EXTERNAL_ANALOG
1782static void bdecode_p_stop_656_video(bvideo_decode_t video_decode)
1783{
1784    bdecode_window_t window = video_decode->decode->window;
1785    BDBG_MSG(("Stop 656 input"));
1786    if (video_decode->decode->settings.stop_mode == bdecode_stop_mode_mute) {
1787        bdecode_p_set_video_input(window, NULL);
1788    }
1789    NEXUS_VideoInput_Shutdown(NEXUS_Ccir656Input_GetConnector(video_decode->ccir656Input));
1790    NEXUS_Ccir656Input_Close(video_decode->ccir656Input);
1791    video_decode->ccir656Input=NULL;
1792    video_decode->started = false;
1793}
1794#endif
1795
1796void bdecode_stop_video(bvideo_decode_t video_decode)
1797{
1798    bstream_t source = video_decode->decode->source;
1799    if (!video_decode->started) {
1800        return;
1801    }
1802    BDBG_MSG(("stop_video %p",video_decode));
1803
1804#if B_HAS_ANALOG
1805    if (source->producer.tuner) {
1806        bdecode_p_stop_analog_video(video_decode);
1807        return;
1808    }
1809#endif
1810
1811#if B_HAS_EXTERNAL_ANALOG
1812    if (source->producer.tuner) {
1813        bdecode_p_stop_656_video(video_decode);
1814        return;
1815    }
1816#endif
1817
1818    if (video_decode->started) {
1819        NEXUS_VideoDecoder_Stop(video_decode->nVideoDecoder);
1820        bdecode_p_unset_sync_channel(video_decode->decode,true,false,false);
1821        bdecode_p_unset_astm(video_decode->decode,true,false,false);
1822                if (video_decode->decode->source->producer.fcc.primerHandle)
1823                {
1824                        NEXUS_VideoDecoder_StartPrimer(video_decode->nVideoDecoder, video_decode->decode->source->producer.fcc.primerHandle,&( video_decode->decode->source->producer.fcc.decodeSettings));
1825                }
1826                else
1827                {
1828                        bstream_p_close_pid(source, video_decode->nPidChannel);
1829                }
1830        if (video_decode->decode->settings.stop_mode == bdecode_stop_mode_mute) {
1831            bdecode_p_set_video_input(video_decode->decode->window, NULL);
1832        }
1833        video_decode->started = false;
1834    }
1835
1836}
1837
1838#if B_HAS_EXTERNAL_ANALOG
1839static bresult bdecode_p_start_i2s_audio(baudio_decode_t audio_decode,bdecode_window_t window)
1840{
1841    BDBG_MSG(("Start i2s audio"));
1842    if ( NULL == audio_decode->display )
1843    {
1844        /* TODO: Handle multiple decodes/displays with analog more gracefully... */
1845    audio_decode->busy = true;
1846    bdisplay_p_enable_audio(window->display, false);
1847    NEXUS_AudioMixer_AddInput(window->display->nAudioMixer,NEXUS_I2sInput_GetConnector(audio_decode->i2sInput));
1848    bdisplay_p_enable_audio(window->display, true);
1849    audio_decode->busy = false;
1850    }
1851    NEXUS_I2sInput_Start(audio_decode->i2sInput);
1852    window->display->mixerInputsStarted++;
1853    audio_decode->started = true;
1854    return 0;
1855}
1856static void bdecode_p_stop_i2s_audio(baudio_decode_t audio_decode,bdecode_window_t window)
1857{
1858    BDBG_MSG(("Stop i2s audio"));
1859    if (!audio_decode->i2sInput)
1860    {
1861        BDBG_ERR(("I2S input not open"));
1862        BSETTOP_ERROR(berr_invalid_parameter);
1863        return;
1864    }
1865    audio_decode->started = false;
1866    NEXUS_I2sInput_Stop(audio_decode->i2sInput);
1867    window->display->mixerInputsStarted--;
1868    if ( NULL == audio_decode->display )
1869    {
1870    audio_decode->busy = true;
1871    bdisplay_p_enable_audio(window->display, false);
1872    NEXUS_AudioMixer_RemoveInput(audio_decode->decode->window->display->nAudioMixer,NEXUS_I2sInput_GetConnector(audio_decode->i2sInput));
1873    bdisplay_p_enable_audio(window->display, true);
1874    audio_decode->busy = false;
1875    }
1876    audio_decode->i2sInput=NULL;
1877    return ;
1878}
1879#endif
1880
1881
1882const char* g_audioCodecName[]=
1883{
1884    "unknown",
1885    "mpeg",
1886    "mp3",
1887    "aac",
1888    "aac_loas",
1889    "aac_plus",
1890    "aac_plus_adts",
1891    "ac3",
1892    "ac3_plus",
1893    "dts",
1894    "lpcm_dvd",
1895    "lpcm_hddvd",
1896    "lpcm_bluray",
1897    "dts_hd",
1898    "wma",
1899    "wma_pro",
1900    "avs",
1901    "pcm",
1902    "pcm_wave",
1903    "amr",
1904    "dra"
1905    ""
1906 };
1907
1908
1909#if B_N_DVI_OUTPUTS
1910static bool bdecode_p_hdmi_audio_format_supported(NEXUS_HdmiOutputHandle hdmi,NEXUS_AudioCodec codec)
1911{
1912    NEXUS_HdmiOutputStatus nHdmiStatus;
1913    BSTD_UNUSED(hdmi);
1914    BSTD_UNUSED(codec);
1915
1916#if (BCHP_CHIP==7400)
1917    if (NEXUS_AudioCodec_eAc3Plus == codec)
1918    {
1919        if (g_decode[1].audio_decode)
1920        {
1921            return false;
1922        }
1923        else if (g_audio_passthrough == g_n_audio_decoder[2])
1924        {
1925            /* DDP passthru on 7400 must use full-featured DSP context 1. Take it from g_decode[1] */
1926            if (NULL != g_audio_passthrough)
1927            {
1928                NEXUS_AudioInput_Shutdown(NEXUS_AudioDecoder_GetConnector(g_audio_passthrough, NEXUS_AudioDecoderConnectorType_eCompressed));
1929                NEXUS_AudioDecoder_Close(g_audio_passthrough);
1930                g_n_audio_decoder[2] = NULL;
1931            }
1932            g_audio_passthrough = g_n_audio_decoder[1];
1933            BDBG_WRN(("Swapped audio decoder 1 for DDP passthru.  Dual audio decode disabled"));
1934        }
1935    }
1936#endif
1937
1938#if (BCHP_CHIP==7401) || (BCHP_CHIP==7403)
1939    if (NEXUS_AudioCodec_eAc3Plus == codec)
1940    {
1941        return false;
1942    }
1943#endif
1944
1945    if (bsettop_get_config("hdmi_bypass_audio_edid"))
1946    {
1947        BDBG_WRN(("bypass edid for %s audio",g_audioCodecName[codec]));
1948        return true;
1949    }
1950    #if B_N_DVI_OUTPUTS
1951    NEXUS_HdmiOutput_GetStatus(hdmi, &nHdmiStatus);
1952    if(nHdmiStatus.connected && nHdmiStatus.audioCodecSupported[codec])
1953        return true;
1954    else
1955        return false;
1956    #endif
1957}
1958#endif
1959
1960static bresult bdecode_p_set_audio_display(baudio_decode_t audio_decode, bdisplay_t display)
1961{
1962    NEXUS_Error rc =0;
1963    if ( NULL == display )
1964    {
1965        display = audio_decode->display;
1966        if ( display == NULL )
1967        {
1968            return b_ok;
1969        }
1970        audio_decode->display = NULL;
1971#if B_HAS_SRS_TRUE_VOLUME && B_HAS_DOLBY_VOLUME
1972        if(audio_decode->nTrueVolume && audio_decode->nDolbyVolume)
1973        {
1974            NEXUS_AudioMixer_RemoveInput(display->nAudioMixer,NEXUS_DolbyVolume_GetConnector(audio_decode->nDolbyVolume));
1975            NEXUS_DolbyVolume_RemoveInput(audio_decode->nDolbyVolume,NEXUS_TruVolume_GetConnector(audio_decode->nTrueVolume));
1976            NEXUS_TruVolume_RemoveInput(audio_decode->nTrueVolume,NEXUS_AudioDecoder_GetConnector(audio_decode->nAudioDecoder, NEXUS_AudioDecoderConnectorType_eStereo));
1977        }
1978        else
1979        {
1980            NEXUS_AudioMixer_RemoveInput(display->nAudioMixer,
1981                   NEXUS_AudioDecoder_GetConnector(audio_decode->nAudioDecoder, NEXUS_AudioDecoderConnectorType_eStereo));
1982        }
1983#elif B_HAS_SRS_TRUE_VOLUME
1984        if(audio_decode->nTrueVolume)
1985        {
1986            NEXUS_AudioMixer_RemoveInput(display->nAudioMixer,NEXUS_TruVolume_GetConnector(audio_decode->nTrueVolume));
1987            NEXUS_TruVolume_RemoveInput(audio_decode->nTrueVolume,NEXUS_AudioDecoder_GetConnector(audio_decode->nAudioDecoder, NEXUS_AudioDecoderConnectorType_eStereo));
1988        }
1989        else
1990        {
1991            NEXUS_AudioMixer_RemoveInput(display->nAudioMixer,
1992            NEXUS_AudioDecoder_GetConnector(audio_decode->nAudioDecoder, NEXUS_AudioDecoderConnectorType_eStereo));
1993        }
1994#elif B_HAS_DOLBY_VOLUME
1995        if(audio_decode->nDolbyVolume)
1996        {
1997            NEXUS_AudioMixer_RemoveInput(display->nAudioMixer,NEXUS_DolbyVolume_GetConnector(audio_decode->nDolbyVolume));
1998            NEXUS_DolbyVolume_RemoveInput(audio_decode->nDolbyVolume,NEXUS_AudioDecoder_GetConnector(audio_decode->nAudioDecoder, NEXUS_AudioDecoderConnectorType_eStereo));
1999        }
2000        else
2001        {
2002            NEXUS_AudioMixer_RemoveInput(display->nAudioMixer,
2003            NEXUS_AudioDecoder_GetConnector(audio_decode->nAudioDecoder, NEXUS_AudioDecoderConnectorType_eStereo));
2004        }
2005#else
2006        NEXUS_AudioMixer_RemoveInput(display->nAudioMixer,
2007            NEXUS_AudioDecoder_GetConnector(audio_decode->nAudioDecoder, NEXUS_AudioDecoderConnectorType_eStereo));
2008#endif
2009    }
2010    else
2011    {
2012#if B_HAS_SRS_TRUE_VOLUME && B_HAS_DOLBY_VOLUME
2013    if(audio_decode->nTrueVolume && audio_decode->nDolbyVolume)
2014    {
2015        BDBG_WRN(("cascading SRS True Vol and Dolby vol post processing stages"));
2016        NEXUS_TruVolume_RemoveAllInputs(audio_decode->nTrueVolume);
2017        NEXUS_DolbyVolume_RemoveAllInputs(audio_decode->nDolbyVolume);
2018        /* connect decoder to tru volume */
2019        rc = NEXUS_TruVolume_AddInput(audio_decode->nTrueVolume,NEXUS_AudioDecoder_GetConnector(audio_decode->nAudioDecoder, NEXUS_AudioDecoderConnectorType_eStereo));
2020        if(rc)
2021        {
2022            BSETTOP_ERROR(berr_external_error);return rc;
2023        }
2024        /* connect true vlume to doly volume */
2025        rc = NEXUS_DolbyVolume_AddInput(audio_decode->nDolbyVolume,NEXUS_TruVolume_GetConnector(audio_decode->nTrueVolume));
2026        if(rc)
2027        {
2028            BSETTOP_ERROR(berr_external_error);return rc;
2029        }
2030        /*connect dolby volume to mixer */
2031            rc = NEXUS_AudioMixer_AddInput(display->nAudioMixer,NEXUS_DolbyVolume_GetConnector(audio_decode->nDolbyVolume));
2032        if(rc)
2033        {
2034            BSETTOP_ERROR(berr_external_error); return rc;
2035        }
2036    }
2037    else
2038    {
2039            NEXUS_AudioMixer_AddInput(display->nAudioMixer,
2040                                  NEXUS_AudioDecoder_GetConnector(audio_decode->nAudioDecoder, NEXUS_AudioDecoderConnectorType_eStereo));
2041    }
2042#elif B_HAS_SRS_TRUE_VOLUME
2043    if(audio_decode->nTrueVolume)
2044    {
2045        BDBG_WRN(("Setting SRS True Vol post processing stage "));
2046        NEXUS_TruVolume_RemoveAllInputs(audio_decode->nTrueVolume);
2047        rc = NEXUS_TruVolume_AddInput(audio_decode->nTrueVolume,
2048            NEXUS_AudioDecoder_GetConnector(audio_decode->nAudioDecoder, NEXUS_AudioDecoderConnectorType_eStereo));
2049        if(rc)
2050        {
2051            BSETTOP_ERROR(berr_external_error); return rc;
2052        }
2053            rc = NEXUS_AudioMixer_AddInput(display->nAudioMixer,NEXUS_TruVolume_GetConnector(audio_decode->nTrueVolume));
2054        if(rc)
2055        {
2056            BSETTOP_ERROR(berr_external_error); return rc;
2057        }
2058    }
2059    else
2060    {
2061            NEXUS_AudioMixer_AddInput(display->nAudioMixer,
2062        NEXUS_AudioDecoder_GetConnector(audio_decode->nAudioDecoder, NEXUS_AudioDecoderConnectorType_eStereo));
2063    }
2064#elif B_HAS_DOLBY_VOLUME
2065    if(audio_decode->nDolbyVolume)
2066    {
2067        BDBG_WRN(("Setting up Dolby volume post processing stage "));
2068        NEXUS_DolbyVolume_RemoveAllInputs(audio_decode->nDolbyVolume);
2069        rc = NEXUS_DolbyVolume_AddInput(audio_decode->nDolbyVolume,
2070            NEXUS_AudioDecoder_GetConnector(audio_decode->nAudioDecoder, NEXUS_AudioDecoderConnectorType_eStereo));
2071        if(rc)
2072        {
2073            BSETTOP_ERROR(berr_external_error); return rc;
2074        }
2075            rc = NEXUS_AudioMixer_AddInput(display->nAudioMixer,NEXUS_DolbyVolume_GetConnector(audio_decode->nDolbyVolume));
2076        if(rc)
2077        {
2078            BSETTOP_ERROR(berr_external_error); return rc;
2079        }
2080    }
2081    else
2082    {
2083            NEXUS_AudioMixer_AddInput(display->nAudioMixer,
2084        NEXUS_AudioDecoder_GetConnector(audio_decode->nAudioDecoder, NEXUS_AudioDecoderConnectorType_eStereo));
2085    }
2086#else
2087        NEXUS_AudioMixer_AddInput(display->nAudioMixer,
2088    NEXUS_AudioDecoder_GetConnector(audio_decode->nAudioDecoder, NEXUS_AudioDecoderConnectorType_eStereo));
2089#endif
2090        audio_decode->display = display;
2091    }
2092    return rc;
2093}
2094
2095static bool bdecode_p_dts_encode_supported(NEXUS_AudioCodec codec)
2096{
2097    bool codecSupported;
2098    switch(codec)
2099    {
2100    default:
2101        codecSupported=false;
2102        break;
2103    case NEXUS_AudioCodec_eAac:
2104    case NEXUS_AudioCodec_eAacLoas:
2105    case NEXUS_AudioCodec_eAacPlus:
2106    case NEXUS_AudioCodec_eAacPlusAdts:
2107    case NEXUS_AudioCodec_eDts:
2108        codecSupported=true;
2109        break;
2110   
2111    }
2112    return codecSupported; 
2113}
2114
2115static bool bdecode_p_ac3_encode_supported(NEXUS_AudioCodec codec)
2116{
2117    bool codecSupported;
2118    switch(codec)
2119    {
2120    default:
2121        codecSupported=false;
2122        break;
2123    case NEXUS_AudioCodec_eAac:
2124    case NEXUS_AudioCodec_eAacLoas:
2125    case NEXUS_AudioCodec_eAacPlus:
2126    case NEXUS_AudioCodec_eAacPlusAdts:
2127        codecSupported=true;
2128        break;
2129    }
2130    return codecSupported;
2131}
2132
2133
2134bresult bdecode_start_audio(baudio_decode_t audio_decode, bstream_t source, bdecode_window_t window)
2135{
2136    uint16_t pid;
2137    NEXUS_Error rc;
2138    NEXUS_AudioDecoderStartSettings startSettings;
2139    bool spdifDts=false;
2140    bool spdifAc3=false;
2141#if B_N_DVI_OUTPUTS
2142    bool hdmiDts=false;
2143    bool hdmiAc3=false;
2144    NEXUS_HdmiOutputStatus nHdmiStatus;
2145#endif
2146    bsettop_init_settings initSettings;
2147    bsettop_get_init_settings(&initSettings);
2148
2149    if (initSettings.lipsync_mode == bsettop_lipsync_mode_disabled)
2150        audio_decode->decode->tsm = false;
2151
2152    if (source->producer.tuner) {
2153#if B_HAS_EXTERNAL_ANALOG
2154        return bdecode_p_start_i2s_audio(audio_decode,window);
2155#endif
2156        return 0;
2157    }
2158
2159    if (!audio_decode->nAudioDecoder) {
2160        return BSETTOP_ERROR(berr_not_available);
2161    }
2162    BDBG_MSG(("start_audio decode %p,src stream %p,window %p,%s",
2163              audio_decode,source,window,audio_decode->decode->tsm?"TSM":"VSYNC"));
2164
2165    BDBG_ASSERT(false == audio_decode->decode->audio_disabled);
2166
2167    NEXUS_AudioDecoder_GetDefaultStartSettings(&startSettings);
2168
2169    BDBG_MSG(("audio stc channel %p",audio_decode->decode->stcChannel));
2170
2171    pid = source->mpeg.audio[audio_decode->decode->audio_program].pid;
2172    if ( pid == 0 || (source->mpeg.mpeg_type != bstream_mpeg_type_vob && pid >= 0x1fff) )
2173    {
2174        BDBG_MSG(("No audio PID"));
2175        /* No audio */
2176        return b_ok;
2177    }
2178
2179    audio_decode->nPidChannel = bstream_p_open_pid(source, pid, bstream_pid_type_audio);
2180    if ( NULL == audio_decode->nPidChannel )
2181    {
2182        BDBG_ERR(("Unable to allocate PID channel for audio program"));
2183        return BSETTOP_ERROR(berr_invalid_parameter);
2184    }
2185
2186    if ( audio_decode->decode->settings.audio.secondary_audio_program != -1 )
2187    {
2188        pid = source->mpeg.audio[audio_decode->decode->settings.audio.secondary_audio_program].pid;
2189        if ( pid == 0 || pid >= 0x1fff )
2190        {
2191            BDBG_WRN(("Invalid secondary audio program.  Using Primary."));
2192        }
2193        else
2194        {
2195            audio_decode->nSecondaryPidChannel = bstream_p_open_pid(source, pid, bstream_pid_type_audio);
2196            if ( NULL == audio_decode->nSecondaryPidChannel )
2197            {
2198                BDBG_WRN(("Unable to open pid channel for secondary audio progam.  Using Primary."));
2199            }
2200        }
2201    }
2202#if 0
2203    audio_decode->sourceChangedEvent = B_Event_Create(NULL);
2204    BDBG_MSG(("audio_decode->sourceChangedEvent = %p, audio_decode->decode = %p",
2205              audio_decode->sourceChangedEvent,audio_decode->decode));
2206    if ( NULL == audio_decode->sourceChangedEvent )
2207    {
2208        return BSETTOP_ERROR(berr_out_of_memory);
2209    }
2210    audio_decode->sourceChangedEventId = b_event_register(audio_decode->sourceChangedEvent,
2211                                                                  bdecode_p_audio_source_changed,
2212                                                                  audio_decode->decode);
2213    if ( NULL == audio_decode->sourceChangedEventId )
2214    {
2215        B_Event_Destroy(audio_decode->sourceChangedEvent);
2216        return BSETTOP_ERROR(berr_out_of_memory);
2217    }
2218#endif
2219    audio_decode->sourceChangedCallback = b_callback_create(audio_decode,bdecode_p_audio_source_changed,audio_decode->decode,0);
2220    if(NULL == audio_decode->sourceChangedCallback)
2221        return BSETTOP_ERROR(berr_out_of_memory);
2222    BDBG_MSG(("audio_decode->sourceChangedCallback = %p, audio_decode->decode = %p",audio_decode->sourceChangedCallback,audio_decode->decode));
2223
2224    audio_decode->restartSettings.pidChannel = startSettings.pidChannel = audio_decode->nPidChannel;
2225    audio_decode->restartSettings.codec = startSettings.codec = b_audiocodec2nexus(source->mpeg.audio[audio_decode->decode->audio_program].format);
2226    /* BDBG_MSG(("nexus %d, settop %d",startSettings.codec,source->mpeg.audio[audio_decode->decode->audio_program].format)); */
2227    audio_decode->restartSettings.stcChannel = startSettings.stcChannel = audio_decode->decode->tsm? audio_decode->decode->stcChannel : NULL;
2228
2229    if ( NULL == audio_decode->decode->settings.audio.display )
2230    {
2231        audio_decode->busy = true;
2232        bdisplay_p_enable_audio(window->display, false);
2233        bdecode_p_set_audio_display(audio_decode, window->display);
2234        bdisplay_p_enable_audio(window->display, true);
2235        audio_decode->busy = false;
2236    }
2237
2238    if (audio_decode->decode->primerStart.stcChannel  && !source->producer.playback) {
2239        startSettings.stcChannel = audio_decode->decode->tsm? audio_decode->decode->primerStart.stcChannel : NULL;
2240    }
2241
2242#if B_N_DVI_OUTPUTS
2243    if (window->display->settings.dvi) {
2244        NEXUS_HdmiOutput_GetStatus(window->display->settings.dvi->handle, &nHdmiStatus);
2245    }
2246
2247    if( window->display->settings.dvi && (window->display->settings.dvi->desired.hdmi_audio_mode == boutput_hdmi_audio_mode_pcm_6ch && nHdmiStatus.connected) )
2248    {
2249        bool isMultiChannelSupported=true;
2250        switch ( startSettings.codec )
2251        {
2252        case NEXUS_AudioCodec_eMpeg:
2253        case NEXUS_AudioCodec_eMp3:
2254        case NEXUS_AudioCodec_eWmaStd:
2255        case NEXUS_AudioCodec_eLpcmDvd:
2256        case NEXUS_AudioCodec_eLpcmHdDvd:
2257        case NEXUS_AudioCodec_eLpcmBluRay:
2258        #if (BCHP_CHIP == 7400)
2259        case NEXUS_AudioCodec_eDts:
2260        case NEXUS_AudioCodec_eDtsHd:
2261        #endif
2262            isMultiChannelSupported=0;
2263            break;
2264        default:
2265            isMultiChannelSupported=1;
2266        }
2267        if (isMultiChannelSupported)
2268        {
2269            BDBG_MSG(("Attaching HDMI audio to decoder %p",audio_decode));
2270            /* remove any inputs*/
2271            NEXUS_AudioOutput_RemoveAllInputs(NEXUS_HdmiOutput_GetAudioConnector(window->display->settings.dvi->handle));
2272            NEXUS_AudioOutput_AddInput(NEXUS_HdmiOutput_GetAudioConnector(window->display->settings.dvi->handle),
2273                                       NEXUS_AudioDecoder_GetConnector(audio_decode->nAudioDecoder,
2274                                                                       NEXUS_AudioDecoderConnectorType_eMultichannel));
2275        }
2276        else
2277        {
2278            BDBG_MSG(("Multichannel PCM audio not supported for codec %s",g_audioCodecName[startSettings.codec]));
2279        }
2280
2281    }
2282#endif
2283
2284#if B_HAS_DTS_ENCODE
2285    if(audio_decode->nDtsEncoder)
2286        NEXUS_DtsEncode_RemoveAllInputs(audio_decode->nDtsEncoder);
2287#endif
2288#if B_HAS_AC3_ENCODE
2289    if(audio_decode->nAc3Encoder)
2290        NEXUS_Ac3Encode_RemoveAllInputs(audio_decode->nAc3Encoder);
2291#endif
2292
2293#if B_N_SPDIF_OUTPUTS
2294    if (window->display->settings.spdif && !window->display->settings.spdif->desired.pcm)
2295    {
2296
2297        if (window->display->settings.spdif->desired.compressed_audio_format == baudio_format_dts && bdecode_p_dts_encode_supported(startSettings.codec))
2298        {
2299            #if B_HAS_DTS_ENCODE
2300            BDBG_WRN(("DTS encoded output on spdif"));
2301            /* Send multichannel output to DTS encoder */
2302            NEXUS_DtsEncode_AddInput(audio_decode->nDtsEncoder,
2303                                     NEXUS_AudioDecoder_GetConnector(audio_decode->nAudioDecoder, NEXUS_AudioDecoderConnectorType_eMultichannel));
2304            /* Send compressed DTS data to SPDIF */
2305            NEXUS_AudioOutput_AddInput(NEXUS_SpdifOutput_GetConnector(window->display->settings.spdif->handle),
2306                                       NEXUS_DtsEncode_GetConnector(audio_decode->nDtsEncoder));
2307            spdifDts=true;
2308            #endif
2309        }
2310        else if (window->display->settings.spdif->desired.compressed_audio_format == baudio_format_ac3 && bdecode_p_ac3_encode_supported(startSettings.codec))
2311        {
2312            #if B_HAS_AC3_ENCODE
2313            BDBG_WRN(("Ac3 encoded output on spdif"));
2314            /* Send multichannel output to DTS encoder */
2315            NEXUS_Ac3Encode_AddInput(audio_decode->nAc3Encoder,
2316                                     NEXUS_AudioDecoder_GetConnector(audio_decode->nAudioDecoder, NEXUS_AudioDecoderConnectorType_eMultichannel));
2317            /* Send compressed Ac3 data to SPDIF */
2318            NEXUS_AudioOutput_AddInput(NEXUS_SpdifOutput_GetConnector(window->display->settings.spdif->handle),
2319                                       NEXUS_Ac3Encode_GetConnector(audio_decode->nAc3Encoder));
2320            spdifAc3=true;
2321        #endif
2322        }
2323    }
2324#endif /* B_N_SPDIF_OUTPUTS */
2325
2326#if B_N_DVI_OUTPUTS
2327    if(window->display->settings.dvi && nHdmiStatus.connected)
2328    {
2329        switch(window->display->settings.dvi->desired.hdmi_audio_mode)
2330        {
2331        case boutput_hdmi_audio_mode_pcm:
2332        case boutput_hdmi_audio_mode_pcm_6ch:
2333            break;
2334        default:
2335            if(window->display->settings.dvi->desired.compressed_audio_format == baudio_format_dts && bdecode_p_dts_encode_supported(startSettings.codec))
2336            {
2337                #if B_HAS_DTS_ENCODE
2338                if(bdecode_p_hdmi_audio_format_supported(window->display->settings.dvi->handle,NEXUS_AudioCodec_eDts))
2339                {
2340                    BDBG_WRN(("DTS encoded output on hdmi"));
2341                    hdmiDts=true;
2342                    if(!spdifDts)
2343                    {
2344                        /* Send multichannel output to DTS encoder */
2345                        NEXUS_DtsEncode_AddInput(audio_decode->nDtsEncoder,
2346                           NEXUS_AudioDecoder_GetConnector(audio_decode->nAudioDecoder, NEXUS_AudioDecoderConnectorType_eMultichannel));
2347                    }
2348                    /* Send compressed DTS data to HDMI */
2349                    NEXUS_AudioOutput_RemoveAllInputs(NEXUS_HdmiOutput_GetAudioConnector(window->display->settings.dvi->handle));
2350                    NEXUS_AudioOutput_AddInput(NEXUS_HdmiOutput_GetAudioConnector(window->display->settings.dvi->handle),
2351                               NEXUS_DtsEncode_GetConnector(audio_decode->nDtsEncoder));
2352
2353                }
2354                #endif
2355            }
2356            else if(window->display->settings.dvi->desired.compressed_audio_format == baudio_format_ac3 && bdecode_p_ac3_encode_supported(startSettings.codec))
2357            {
2358                #if B_HAS_AC3_ENCODE
2359                if(bdecode_p_hdmi_audio_format_supported(window->display->settings.dvi->handle,NEXUS_AudioCodec_eAc3))
2360                {
2361                    BDBG_WRN(("AC3 encoded output on hdmi"));
2362                    hdmiAc3=true;
2363                    if(!spdifAc3)
2364                    {
2365                        /* Send multichannel output to DTS encoder */
2366                        NEXUS_Ac3Encode_AddInput(audio_decode->nAc3Encoder,
2367                           NEXUS_AudioDecoder_GetConnector(audio_decode->nAudioDecoder, NEXUS_AudioDecoderConnectorType_eMultichannel));
2368                    }
2369                    /* Send compressed AC3 data to HDMI */
2370                    NEXUS_AudioOutput_RemoveAllInputs(NEXUS_HdmiOutput_GetAudioConnector(window->display->settings.dvi->handle));
2371                    NEXUS_AudioOutput_AddInput(NEXUS_HdmiOutput_GetAudioConnector(window->display->settings.dvi->handle),
2372                               NEXUS_Ac3Encode_GetConnector(audio_decode->nAc3Encoder));
2373
2374                }
2375                #endif
2376            }
2377        }
2378    }
2379#endif /* B_N_DVI_OUTPUTS */
2380
2381    /* Connect compressed outputs */
2382#if B_N_SPDIF_OUTPUTS || B_N_DVI_OUTPUTS
2383    if ( (window->display->settings.spdif && (!window->display->settings.spdif->desired.pcm
2384                                                                                          #if (BCHP_CHIP==7400)
2385                                                                                          || (startSettings.codec == NEXUS_AudioCodec_eDts)
2386                                                                                          #endif
2387                                                                                          ) )
2388#if B_N_DVI_OUTPUTS
2389         || (window->display->settings.dvi && ((window->display->settings.dvi->desired.hdmi_audio_mode == boutput_hdmi_audio_mode_compressed)
2390                                                                                          #if (BCHP_CHIP==7400)
2391                                                                                          || (startSettings.codec == NEXUS_AudioCodec_eDts)
2392                                                                                          #endif
2393                                                                                           )
2394                          && nHdmiStatus.connected )
2395#endif
2396        )
2397    {
2398        if ( NULL == g_audio_passthrough_owner )
2399        {
2400            /* g_audio_passthrough_owner = audio_decode; */
2401            switch ( startSettings.codec )
2402            {
2403            case NEXUS_AudioCodec_eAc3Plus:
2404                #if B_N_SPDIF_OUTPUTS
2405                /* Simul mode on SPDIF */
2406                if ( window->display->settings.spdif && !window->display->settings.spdif->desired.pcm && !spdifDts && !spdifAc3 )
2407                {
2408                    BDBG_MSG(("DDP-DD converted(simul) output on SPDIF"));
2409                    NEXUS_AudioOutput_RemoveAllInputs(NEXUS_SpdifOutput_GetConnector(window->display->settings.spdif->handle));
2410                    NEXUS_AudioOutput_AddInput(NEXUS_SpdifOutput_GetConnector(window->display->settings.spdif->handle),
2411                                               NEXUS_AudioDecoder_GetConnector(audio_decode->nAudioDecoder, NEXUS_AudioDecoderConnectorType_eCompressed));
2412                }
2413                #if (BCHP_CHIP == 7400)
2414                audio_decode->spdif_forced_compressed = false;
2415                #endif
2416                #endif
2417                #if B_N_DVI_OUTPUTS
2418                if ( window->display->settings.dvi && window->display->settings.dvi->desired.hdmi_audio_mode == boutput_hdmi_audio_mode_compressed
2419                     &&nHdmiStatus.connected && !hdmiDts && !hdmiAc3 )
2420                {
2421                    if(bdecode_p_hdmi_audio_format_supported(window->display->settings.dvi->handle,NEXUS_AudioCodec_eAc3Plus))
2422                    {
2423                        BDBG_MSG(("DDP passthrough on HDMI"));
2424                        g_audio_passthrough_owner = audio_decode;
2425                        NEXUS_AudioOutput_RemoveAllInputs(NEXUS_HdmiOutput_GetAudioConnector(window->display->settings.dvi->handle));
2426                        NEXUS_AudioOutput_AddInput(NEXUS_HdmiOutput_GetAudioConnector(window->display->settings.dvi->handle),
2427                                               NEXUS_AudioDecoder_GetConnector(g_audio_passthrough, NEXUS_AudioDecoderConnectorType_eCompressed));
2428                    }
2429                    else if(bdecode_p_hdmi_audio_format_supported(window->display->settings.dvi->handle,NEXUS_AudioCodec_eAc3))
2430                    {
2431                        BDBG_MSG(("DDP-DD converted(simul) output on hdmi"));
2432                        NEXUS_AudioOutput_RemoveAllInputs(NEXUS_HdmiOutput_GetAudioConnector(window->display->settings.dvi->handle));
2433                        NEXUS_AudioOutput_AddInput(NEXUS_HdmiOutput_GetAudioConnector(window->display->settings.dvi->handle),
2434                                               NEXUS_AudioDecoder_GetConnector(audio_decode->nAudioDecoder, NEXUS_AudioDecoderConnectorType_eCompressed));
2435                    }
2436                    else
2437                    {
2438                        BDBG_WRN(("DDP audio on hdmi not suppored by receiver"));
2439                    }
2440                }
2441                #if (BCHP_CHIP == 7400)
2442                audio_decode->hdmi_forced_compressed = false;
2443                #endif
2444                #endif /* B_N_DVI_OUTPUTS */
2445                break;
2446            #if (BCHP_CHIP == 7400)
2447            case NEXUS_AudioCodec_eMpeg:
2448            case NEXUS_AudioCodec_eMp3:
2449            #endif
2450            case NEXUS_AudioCodec_eWmaStd:
2451            case NEXUS_AudioCodec_eLpcmDvd:
2452            case NEXUS_AudioCodec_eLpcmHdDvd:
2453            case NEXUS_AudioCodec_eLpcmBluRay:
2454            case NEXUS_AudioCodec_ePcmWav:
2455                #if B_N_SPDIF_OUTPUTS
2456                /* katrep: Do not like to forcing PCM if compressed is request, I would rather have not audio
2457                  on hdmi and spdif, however brutus and traditional settop implementation PCM is forced forcing pcm to
2458                  maintain compatibilty of the shim layer */
2459                if ( window->display->settings.spdif && !window->display->settings.spdif->desired.pcm && !spdifDts && !spdifAc3 )
2460                {
2461                    NEXUS_AudioOutput_RemoveAllInputs(NEXUS_SpdifOutput_GetConnector(window->display->settings.spdif->handle));
2462                    NEXUS_AudioOutput_AddInput(NEXUS_SpdifOutput_GetConnector(window->display->settings.spdif->handle),
2463                                                NEXUS_AudioMixer_GetConnector(window->display->nAudioMixer));
2464                    /* window->display->settings.spdif->desired.pcm = true; */
2465                    window->display->settings.spdif->cfg.pcm = true;
2466                    BDBG_WRN(("forcing pcm on spdif for %s",g_audioCodecName[startSettings.codec]));
2467                }
2468                #if (BCHP_CHIP == 7400)
2469                audio_decode->spdif_forced_compressed = false;
2470                #endif
2471                #endif
2472                #if B_N_DVI_OUTPUTS
2473                if ( window->display->settings.dvi && window->display->settings.dvi->desired.hdmi_audio_mode == boutput_hdmi_audio_mode_compressed
2474                     && nHdmiStatus.connected &&!hdmiDts && !hdmiAc3 )
2475                {
2476                                        NEXUS_AudioOutput_RemoveAllInputs(NEXUS_HdmiOutput_GetAudioConnector(window->display->settings.dvi->handle));
2477                    NEXUS_AudioOutput_AddInput(NEXUS_HdmiOutput_GetAudioConnector(window->display->settings.dvi->handle),
2478                                                NEXUS_AudioMixer_GetConnector(window->display->nAudioMixer));
2479                    /* window->display->settings.dvi->desired.hdmi_audio_mode = boutput_hdmi_audio_mode_pcm; */
2480                    window->display->settings.dvi->cfg.hdmi_audio_mode=boutput_hdmi_audio_mode_pcm;
2481                    BDBG_WRN(("forcing pcm on hdmi for %s",g_audioCodecName[startSettings.codec]));
2482                }
2483                #if (BCHP_CHIP == 7400)
2484                audio_decode->hdmi_forced_compressed = false;
2485                #endif
2486                #endif
2487                break;
2488            #if (BCHP_CHIP == 7400)
2489            case NEXUS_AudioCodec_eDts:
2490                #if B_N_SPDIF_OUTPUTS
2491                /* 7400 can pass thru, but can't decode DTS, force compressed */
2492                if ( window->display->settings.spdif )
2493                {
2494                                        g_audio_passthrough_owner = audio_decode;
2495                                        NEXUS_AudioOutput_RemoveAllInputs(NEXUS_SpdifOutput_GetConnector(window->display->settings.spdif->handle));
2496                                        NEXUS_AudioOutput_AddInput(NEXUS_SpdifOutput_GetConnector(window->display->settings.spdif->handle),
2497                                                                                           NEXUS_AudioDecoder_GetConnector(g_audio_passthrough, NEXUS_AudioDecoderConnectorType_eCompressed));
2498                    /* window->display->settings.spdif->desired.pcm = true; */
2499                                        if (window->display->settings.spdif->cfg.pcm)
2500                                        {
2501                        window->display->settings.spdif->cfg.pcm = false;
2502                        audio_decode->spdif_forced_compressed = true;
2503                        BDBG_WRN(("forcing compressed on spdif for %s",g_audioCodecName[startSettings.codec]));
2504                                        }
2505                                        else
2506                                        {
2507                                                audio_decode->spdif_forced_compressed = false;
2508                                        }
2509                }
2510                #endif
2511                #if B_N_DVI_OUTPUTS
2512                if ( window->display->settings.dvi && nHdmiStatus.connected )
2513                {
2514                                        g_audio_passthrough_owner = audio_decode;
2515                                        NEXUS_AudioOutput_RemoveAllInputs(NEXUS_HdmiOutput_GetAudioConnector(window->display->settings.dvi->handle));
2516                                        NEXUS_AudioOutput_AddInput(NEXUS_HdmiOutput_GetAudioConnector(window->display->settings.dvi->handle),
2517                                                                                   NEXUS_AudioDecoder_GetConnector(g_audio_passthrough, NEXUS_AudioDecoderConnectorType_eCompressed));
2518                    /* window->display->settings.dvi->desired.hdmi_audio_mode = boutput_hdmi_audio_mode_pcm; */
2519                    if (window->display->settings.dvi->cfg.hdmi_audio_mode!=boutput_hdmi_audio_mode_compressed)
2520                    {
2521                        window->display->settings.dvi->cfg.hdmi_audio_mode=boutput_hdmi_audio_mode_compressed;
2522                        audio_decode->hdmi_forced_compressed = true;
2523                        BDBG_WRN(("forcing compressed on hdmi for %s",g_audioCodecName[startSettings.codec]));
2524                    }
2525                    else
2526                    {
2527                        audio_decode->hdmi_forced_compressed = false;
2528                    }
2529                }
2530                #endif
2531                break;
2532            #endif
2533            case NEXUS_AudioCodec_eWmaPro:
2534                #if B_N_SPDIF_OUTPUTS
2535                /* WMAPRO needs simul mode, passthrough is not supported */
2536                if ( window->display->settings.spdif && !window->display->settings.spdif->desired.pcm && !spdifDts && !spdifAc3 )
2537                {
2538                    BDBG_MSG(("WMAPRO simul mode on SPDIF",startSettings.codec));
2539                    NEXUS_AudioOutput_RemoveAllInputs(NEXUS_SpdifOutput_GetConnector(window->display->settings.spdif->handle));
2540                    NEXUS_AudioOutput_AddInput(NEXUS_SpdifOutput_GetConnector(window->display->settings.spdif->handle),
2541                                               NEXUS_AudioDecoder_GetConnector(audio_decode->nAudioDecoder, NEXUS_AudioDecoderConnectorType_eCompressed));
2542                }
2543                #if (BCHP_CHIP == 7400)
2544                audio_decode->spdif_forced_compressed = false;
2545                #endif
2546                #endif
2547                #if B_N_DVI_OUTPUTS
2548                if ( window->display->settings.dvi && window->display->settings.dvi->desired.hdmi_audio_mode == boutput_hdmi_audio_mode_compressed
2549                     && nHdmiStatus.connected &&!hdmiDts && !hdmiAc3 )
2550                {
2551                    if(bdecode_p_hdmi_audio_format_supported(window->display->settings.dvi->handle,NEXUS_AudioCodec_eWmaPro)||
2552                       bdecode_p_hdmi_audio_format_supported(window->display->settings.dvi->handle,NEXUS_AudioCodec_eWmaStd))
2553                    {
2554                        BDBG_MSG(("WMAPRO simul mode  on HDMI"));
2555                        NEXUS_AudioOutput_RemoveAllInputs(NEXUS_HdmiOutput_GetAudioConnector(window->display->settings.dvi->handle));
2556                        NEXUS_AudioOutput_AddInput(NEXUS_HdmiOutput_GetAudioConnector(window->display->settings.dvi->handle),
2557                                               NEXUS_AudioDecoder_GetConnector(audio_decode->nAudioDecoder, NEXUS_AudioDecoderConnectorType_eCompressed));
2558                    }
2559                    else
2560                    {
2561                        BDBG_WRN(("WMAPRO audio on hdmi not suppored by receiver"));
2562                    }
2563                }
2564                                #if (BCHP_CHIP == 7400)
2565                                audio_decode->hdmi_forced_compressed = false;
2566                                #endif
2567                #endif
2568                break;
2569
2570            default:
2571                #if B_N_SPDIF_OUTPUTS
2572                /* Standard Cases */
2573                if ( window->display->settings.spdif && !window->display->settings.spdif->desired.pcm && !spdifDts && !spdifAc3)
2574                {
2575                    BDBG_MSG(("%s passthrough on SPDIF",g_audioCodecName[startSettings.codec]));
2576                    g_audio_passthrough_owner = audio_decode;
2577                    NEXUS_AudioOutput_RemoveAllInputs(NEXUS_SpdifOutput_GetConnector(window->display->settings.spdif->handle));
2578                    NEXUS_AudioOutput_AddInput(NEXUS_SpdifOutput_GetConnector(window->display->settings.spdif->handle),
2579                                               NEXUS_AudioDecoder_GetConnector(g_audio_passthrough, NEXUS_AudioDecoderConnectorType_eCompressed));
2580                }
2581                #if (BCHP_CHIP == 7400)
2582                audio_decode->spdif_forced_compressed = false;
2583                #endif
2584                #endif
2585                #if B_N_DVI_OUTPUTS
2586                if ( window->display->settings.dvi && window->display->settings.dvi->desired.hdmi_audio_mode == boutput_hdmi_audio_mode_compressed
2587                     && nHdmiStatus.connected &&!hdmiDts && !hdmiAc3 )
2588                {
2589                    if(bdecode_p_hdmi_audio_format_supported(window->display->settings.dvi->handle,startSettings.codec))
2590                    {
2591                        BDBG_MSG((" %s passthrough on HDMI",g_audioCodecName[startSettings.codec]));
2592                        g_audio_passthrough_owner = audio_decode;
2593                        NEXUS_AudioOutput_RemoveAllInputs(NEXUS_HdmiOutput_GetAudioConnector(window->display->settings.dvi->handle));
2594                        NEXUS_AudioOutput_AddInput(NEXUS_HdmiOutput_GetAudioConnector(window->display->settings.dvi->handle),
2595                                               NEXUS_AudioDecoder_GetConnector(g_audio_passthrough, NEXUS_AudioDecoderConnectorType_eCompressed));
2596                    }
2597                    else
2598                    {
2599                        BDBG_WRN(("%s audio on hdmi not suppored by receiver",g_audioCodecName[startSettings.codec]));
2600                    }
2601                }
2602                                #if (BCHP_CHIP == 7400)
2603                                audio_decode->hdmi_forced_compressed = false;
2604                                #endif
2605                #endif
2606                break;
2607            }
2608        }
2609        else
2610        {
2611            BDBG_WRN(("Compressed passthrough not available"));
2612        }
2613    }
2614#endif
2615
2616        #if (BCHP_CHIP == 7400)
2617        /* 7400 can pass, but not decode, DTS. Undo force to compressed for non-DTS */
2618        if (startSettings.codec != NEXUS_AudioCodec_eDts)
2619        {
2620        #if B_N_SPDIF_OUTPUTS
2621        if ( window->display->settings.spdif && window->display->settings.spdif->desired.pcm && 
2622             audio_decode->spdif_forced_compressed )
2623        {
2624            NEXUS_AudioOutput_RemoveAllInputs(NEXUS_SpdifOutput_GetConnector(window->display->settings.spdif->handle));
2625            NEXUS_AudioOutput_AddInput(NEXUS_SpdifOutput_GetConnector(window->display->settings.spdif->handle),
2626                                       NEXUS_AudioMixer_GetConnector(window->display->nAudioMixer));
2627            window->display->settings.spdif->cfg.pcm = true;
2628            BDBG_MSG(("Undo forced compressed on spdif for %s",g_audioCodecName[startSettings.codec]));
2629            audio_decode->spdif_forced_compressed = false;
2630        }
2631        #endif
2632        #if B_N_DVI_OUTPUTS
2633        if ( window->display->settings.dvi && window->display->settings.dvi->desired.hdmi_audio_mode == boutput_hdmi_audio_mode_pcm
2634             && nHdmiStatus.connected && audio_decode->hdmi_forced_compressed )
2635        {
2636            NEXUS_AudioOutput_RemoveAllInputs(NEXUS_HdmiOutput_GetAudioConnector(window->display->settings.dvi->handle));
2637            NEXUS_AudioOutput_AddInput(NEXUS_HdmiOutput_GetAudioConnector(window->display->settings.dvi->handle),
2638                                       NEXUS_AudioMixer_GetConnector(window->display->nAudioMixer));
2639            window->display->settings.dvi->cfg.hdmi_audio_mode=boutput_hdmi_audio_mode_pcm;
2640            BDBG_MSG(("Undo forced on hdmi for %s",g_audioCodecName[startSettings.codec]));
2641            audio_decode->hdmi_forced_compressed = false;
2642        }
2643        #endif
2644        #else
2645        {  /* ! 7400 */
2646        #endif         
2647                /* set the sync channel for audio decoder pcm */
2648                bdecode_p_set_sync_channel(audio_decode->decode,false,true,false);
2649                bdecode_p_set_astm(audio_decode->decode,false,true,false);
2650       
2651                /* ip TSM related settings: specify additional pts offset & override decoder playback mode */
2652                bdecode_set_audio_ip_tsm_settings(audio_decode);
2653       
2654                bdecode_p_set_downmix(audio_decode->decode);
2655       
2656                if(bsettop_get_config("audio_capture"))
2657                {
2658                        baudio_capture_start(audio_decode);
2659                }
2660       
2661                /* enable/disable 96khz mode for aac streams */
2662                if( ((startSettings.codec >= NEXUS_AudioCodec_eAac) && (startSettings.codec <= NEXUS_AudioCodec_eAacPlusAdts))
2663                         &&  bsettop_get_config("decode_aac_96khz"))
2664                {
2665       
2666                        NEXUS_AudioDecoderCodecSettings codecSettings;
2667       
2668                        BDBG_WRN(("aac 96khz decode is enabled"));
2669       
2670                        NEXUS_AudioDecoder_GetCodecSettings(audio_decode->nAudioDecoder,startSettings.codec,&codecSettings);
2671                        codecSettings.codecSettings.aac.decode96Khz = true;
2672                        rc = NEXUS_AudioDecoder_SetCodecSettings(audio_decode->nAudioDecoder,&codecSettings);
2673      if(rc != BERR_SUCCESS)
2674      {
2675          BDBG_WRN(("NEXUS_AudioDecoder_SetCodecSettings failed"));
2676      }
2677       
2678                        if(g_audio_passthrough_owner == audio_decode)
2679                        {
2680                                NEXUS_AudioDecoder_GetCodecSettings(g_audio_passthrough,startSettings.codec,&codecSettings);
2681                                codecSettings.codecSettings.aac.decode96Khz = true;
2682                                rc = NEXUS_AudioDecoder_SetCodecSettings(g_audio_passthrough,&codecSettings);
2683        if(rc != BERR_SUCCESS)
2684        {
2685            BDBG_WRN(("NEXUS_AudioDecoder_SetCodecSettings failed"));
2686        }
2687                        }
2688       
2689                }
2690       
2691                audio_decode->decoderStartSettings = startSettings;
2692                rc = NEXUS_AudioDecoder_Start(audio_decode->nAudioDecoder, &startSettings);
2693                if (rc) BSETTOP_ERROR(berr_external_error);
2694                window->display->mixerInputsStarted++;
2695        }
2696
2697    if ( g_audio_passthrough_owner == audio_decode )
2698    {
2699        if ( NULL != audio_decode->nSecondaryPidChannel )
2700        {
2701            startSettings.pidChannel = audio_decode->nSecondaryPidChannel;
2702        }
2703        /* set the sync channel for audio decoder passthrough */
2704        bdecode_p_set_sync_channel(audio_decode->decode,false,false,true);
2705        bdecode_p_set_astm(audio_decode->decode,false,false,true);
2706        audio_decode->secondary_audio_decode->nAudioDecoder = g_audio_passthrough;
2707
2708        /* ip TSM related settings: specify additional pts offset & override decoder playback mode */
2709        bdecode_set_audio_ip_tsm_settings(audio_decode->secondary_audio_decode);
2710
2711        rc = NEXUS_AudioDecoder_Start(g_audio_passthrough, &startSettings);
2712        if (rc) {
2713            audio_decode->secondary_audio_decode->nAudioDecoder = NULL;
2714            BSETTOP_ERROR(berr_external_error);
2715        }
2716    }
2717
2718#if NEXUS_HAS_PLAYBACK
2719    if (source->producer.playback)
2720    {
2721        NEXUS_PlaybackPidChannelSettings settings;
2722        NEXUS_Playback_GetPidChannelSettings(source->producer.playback->nPlayback, audio_decode->nPidChannel, &settings);
2723                BDBG_ASSERT(settings.pidSettings.pidType == NEXUS_PidType_eAudio);
2724                settings.pidTypeSettings.audio.primary = audio_decode->nAudioDecoder;
2725        if ( g_audio_passthrough_owner == audio_decode && !audio_decode->nSecondaryPidChannel )
2726        {
2727            settings.pidTypeSettings.audio.secondary = g_audio_passthrough;
2728        }
2729        NEXUS_Playback_SetPidChannelSettings(source->producer.playback->nPlayback, audio_decode->nPidChannel, &settings);
2730        if ( g_audio_passthrough && audio_decode->nSecondaryPidChannel )
2731        {
2732            NEXUS_Playback_GetPidChannelSettings(source->producer.playback->nPlayback, audio_decode->nSecondaryPidChannel, &settings);
2733            BDBG_ASSERT(settings.pidSettings.pidType == NEXUS_PidType_eAudio);
2734            settings.pidTypeSettings.audio.primary = g_audio_passthrough;
2735            NEXUS_Playback_SetPidChannelSettings(source->producer.playback->nPlayback, audio_decode->nSecondaryPidChannel, &settings);
2736        }
2737    }
2738#endif
2739
2740    audio_decode->started = true;
2741    return 0;
2742}
2743
2744void bdecode_stop_audio(baudio_decode_t audio_decode)
2745{
2746    bstream_t source = audio_decode->decode->source;
2747    bdecode_window_t window = audio_decode->decode->window;
2748    if (!audio_decode->started) {
2749        return;
2750    }
2751    BDBG_MSG(("stop_audio %p",audio_decode));
2752
2753    audio_decode->secondary_audio_decode->nAudioDecoder = NULL;
2754    if (source->producer.tuner) {
2755#if B_HAS_EXTERNAL_ANALOG
2756        bdecode_p_stop_i2s_audio( audio_decode, window);
2757#endif
2758        return;
2759    }
2760
2761    if ( !audio_decode->started )
2762    {
2763        return;
2764    }
2765
2766    /* Clear this before doing anything else */
2767    audio_decode->started = false;
2768
2769    BDBG_ASSERT(window);
2770    if (audio_decode->nAudioDecoder) {
2771                #if (BCHP_CHIP==7400)
2772                /* could have passthru only DTS */
2773                if (window->display->mixerInputsStarted)
2774                #endif
2775                {
2776                        NEXUS_AudioDecoder_Stop(audio_decode->nAudioDecoder);
2777                        window->display->mixerInputsStarted--;
2778                }
2779        if ( g_audio_passthrough_owner == audio_decode )
2780        {
2781            NEXUS_AudioDecoder_Stop(g_audio_passthrough);
2782            g_audio_passthrough_owner = NULL;
2783        }
2784
2785        if(bsettop_get_config("audio_capture"))
2786        {
2787            baudio_capture_stop(audio_decode);
2788        }
2789
2790        bdecode_p_unset_sync_channel(audio_decode->decode,false,true,true);
2791        bdecode_p_unset_astm(audio_decode->decode,false,true,true);
2792
2793        if ( audio_decode->nPidChannel )
2794        {
2795            bstream_p_close_pid(source, audio_decode->nPidChannel);
2796            audio_decode->nPidChannel = NULL;
2797        }
2798        if ( audio_decode->nSecondaryPidChannel )
2799        {
2800            bstream_p_close_pid(source, audio_decode->nSecondaryPidChannel);
2801            audio_decode->nSecondaryPidChannel = NULL;
2802        }
2803
2804        if ( NULL == audio_decode->decode->settings.audio.display )
2805        {
2806            audio_decode->busy = true;
2807            bdisplay_p_enable_audio(window->display, false);
2808
2809            bdecode_p_set_audio_display(audio_decode, NULL);
2810
2811            bdisplay_p_enable_audio(window->display, true);
2812            audio_decode->busy = false;
2813        }
2814
2815        bdisplay_p_set_compressed_mute(audio_decode->decode->window->display, false);
2816
2817#if B_N_SPDIF_OUTPUTS
2818        if ( audio_decode->decode->window->display->settings.spdif &&   /* Wow, that's a lot of indirection... :) */
2819             !audio_decode->decode->window->display->settings.spdif->cfg.pcm )
2820        {
2821            /* Break compressed connection */
2822            NEXUS_AudioOutput_RemoveAllInputs(
2823                NEXUS_SpdifOutput_GetConnector(audio_decode->decode->window->display->settings.spdif->handle));
2824        }
2825#endif
2826#if B_N_DVI_OUTPUTS
2827        if ( audio_decode->decode->window->display->settings.dvi   &&   /* Wow, that's a lot of indirection... :) */
2828             (audio_decode->decode->window->display->settings.dvi->cfg.hdmi_audio_mode == boutput_hdmi_audio_mode_compressed ||
2829              audio_decode->decode->window->display->settings.dvi->cfg.hdmi_audio_mode == boutput_hdmi_audio_mode_pcm_6ch) )
2830        {
2831            /* Break compressed connection */
2832            NEXUS_AudioOutput_RemoveAllInputs(NEXUS_HdmiOutput_GetAudioConnector(audio_decode->decode->window->display->settings.dvi->handle));
2833        }
2834
2835#endif
2836
2837#if B_HAS_DTS_ENCODE
2838        if (audio_decode->nDtsEncoder) {
2839            NEXUS_DtsEncode_RemoveAllInputs(audio_decode->nDtsEncoder);
2840        }
2841#endif
2842
2843#if B_HAS_AC3_ENCODE
2844        if (audio_decode->nAc3Encoder) {
2845            NEXUS_Ac3Encode_RemoveAllInputs(audio_decode->nAc3Encoder);
2846        }
2847#endif
2848
2849#if 0
2850        if ( audio_decode->sourceChangedEventId )
2851        {
2852            BDBG_MSG(("b_event_unregister(%p)",audio_decode->sourceChangedEventId));
2853            b_event_unregister(audio_decode->sourceChangedEventId);
2854            audio_decode->sourceChangedEventId = NULL;
2855        }
2856        if ( audio_decode->sourceChangedEvent )
2857        {
2858            BDBG_MSG(("B_Event_Destroy(%p)",audio_decode->sourceChangedEvent));
2859            B_Event_Destroy(audio_decode->sourceChangedEvent);
2860            audio_decode->sourceChangedEvent = NULL;
2861        }
2862#endif
2863        if ( audio_decode->sourceChangedCallback)
2864        {
2865            BDBG_MSG(("b_callback_destroy(%p)",audio_decode->sourceChangedCallback));
2866            b_callback_destroy(audio_decode->sourceChangedCallback);
2867        }
2868    }
2869}
2870
2871void bdecode_p_still_ready(void *context, int param)
2872{
2873    bdecode_t decode = context;
2874    BSTD_UNUSED(param);
2875    BDBG_MSG(("still_ready"));
2876    /*B_Event_Set(decode->stillEvent);*/
2877    b_callback_fire(decode->stillEventCallback); 
2878}
2879
2880static void bdecode_p_still_handler(void *context,int param)
2881{
2882    bdecode_t decode = context;
2883    BDBG_ASSERT(NULL != context);
2884    BSTD_UNUSED(param);
2885    bdecode_stop(decode);
2886    if (decode->settings.still_picture_done) {
2887        /*b_unlock();*/
2888        (*decode->settings.still_picture_done)(decode->settings.callback_context);
2889        /*b_lock();*/
2890    }
2891}
2892
2893static bresult bdecode_p_set_playpump_timebase(bstream_t source, NEXUS_Timebase timebase) {
2894    if (source->producer.playpump) {
2895        bplaypump_t playpump = NULL;
2896        NEXUS_Error nrc = NEXUS_SUCCESS;
2897        NEXUS_PlaypumpSettings playpumpSettings;
2898
2899        BDBG_MSG(("Setting playpumpSettings.timestamp.timebase to: %d", timebase));
2900        playpump = source->producer.playpump;
2901        NEXUS_Playpump_GetSettings(playpump->nPlaypump, &playpumpSettings);
2902        playpumpSettings.timestamp.timebase = timebase;
2903        nrc = NEXUS_Playpump_SetSettings(playpump->nPlaypump, &playpumpSettings);
2904        if (nrc!=NEXUS_SUCCESS) return BSETTOP_ERROR(berr_external_error);
2905    }
2906
2907    return b_ok;
2908}
2909
2910/* todo: delet this once we have NEXUS_Timebase_GetDefaultSettings*/
2911void bdecode_p_set_timebase_default_settings(NEXUS_Timebase timebase)
2912{
2913    NEXUS_Error nrc = NEXUS_SUCCESS;
2914    NEXUS_TimebaseSettings timebaseSettings;
2915    NEXUS_Timebase_GetSettings(timebase, &timebaseSettings);
2916    timebaseSettings.freeze = false;
2917    timebaseSettings.sourceType = NEXUS_TimebaseSourceType_eFreeRun;
2918    timebaseSettings.sourceSettings.pcr.pidChannel = NULL;
2919    timebaseSettings.sourceSettings.pcr.trackRange = NEXUS_TimebaseTrackRange_e61ppm;
2920    timebaseSettings.sourceSettings.pcr.maxPcrError = 0xFF;
2921    nrc = NEXUS_Timebase_SetSettings(timebase, &timebaseSettings);
2922    if (nrc!=NEXUS_SUCCESS)  BSETTOP_ERROR(berr_external_error);
2923    return;
2924}
2925
2926static bresult bdecode_p_config_timebases(bdecode_t decode, bstream_t source, bdecode_stc_channel_cfg_type cfg_type) {
2927    bresult rc = b_ok;
2928    NEXUS_Error nrc = NEXUS_SUCCESS;
2929    NEXUS_StcChannelSettings stcChannelSettings;
2930    NEXUS_TimebaseSettings timebaseSettings;
2931    NEXUS_Timebase new_timebase;
2932
2933
2934    NEXUS_StcChannel_GetSettings(decode->stcChannel, &stcChannelSettings);
2935    bdecode_p_set_timebase_default_settings(stcChannelSettings.timebase);
2936
2937    /* save the output timebase for this decode */
2938    decode->output_timebase = stcChannelSettings.timebase;
2939
2940    switch (cfg_type) {
2941    case BDECODE_STC_CHANNEL_CFG_TYPE_PARSER_BAND:
2942        /* configuredecoder/output timebase */
2943        if(decode->pcrPidChannel != NULL) {
2944            NEXUS_Timebase_GetSettings(stcChannelSettings.timebase, &timebaseSettings);
2945            timebaseSettings.freeze = false;
2946            timebaseSettings.sourceType = NEXUS_TimebaseSourceType_ePcr;
2947            timebaseSettings.sourceSettings.pcr.pidChannel = decode->pcrPidChannel;
2948            timebaseSettings.sourceSettings.pcr.trackRange = NEXUS_TimebaseTrackRange_e61ppm;
2949            timebaseSettings.sourceSettings.pcr.maxPcrError = 0xFF;
2950            nrc = NEXUS_Timebase_SetSettings(stcChannelSettings.timebase, &timebaseSettings);
2951            if (nrc!=NEXUS_SUCCESS) return BSETTOP_ERROR(berr_external_error);
2952        }
2953        else {
2954            NEXUS_Timebase_GetSettings(stcChannelSettings.timebase, &timebaseSettings);
2955            timebaseSettings.freeze = true;
2956            timebaseSettings.sourceType = NEXUS_TimebaseSourceType_eFreeRun;
2957            timebaseSettings.sourceSettings.freeRun.trackRange = NEXUS_TimebaseTrackRange_e61ppm;
2958            nrc = NEXUS_Timebase_SetSettings(stcChannelSettings.timebase, &timebaseSettings);
2959            if (nrc!=NEXUS_SUCCESS) return BSETTOP_ERROR(berr_external_error);
2960        }
2961        break;
2962    case BDECODE_STC_CHANNEL_CFG_TYPE_TTS_PACING:
2963    case BDECODE_STC_CHANNEL_CFG_TYPE_PCR_PACING:
2964        /* configure shared decoder/output timebase */
2965        if(decode->pcrPidChannel != NULL) {
2966            NEXUS_Timebase_GetSettings(stcChannelSettings.timebase, &timebaseSettings);
2967            timebaseSettings.freeze = false;
2968            timebaseSettings.sourceType = NEXUS_TimebaseSourceType_ePcr;
2969            timebaseSettings.sourceSettings.pcr.pidChannel = decode->pcrPidChannel;
2970            timebaseSettings.sourceSettings.pcr.trackRange = NEXUS_TimebaseTrackRange_e61ppm;
2971            timebaseSettings.sourceSettings.pcr.maxPcrError = 0xFF;
2972            nrc = NEXUS_Timebase_SetSettings(stcChannelSettings.timebase, &timebaseSettings);
2973            if (nrc!=NEXUS_SUCCESS) return BSETTOP_ERROR(berr_external_error);
2974        }
2975        else {
2976            NEXUS_Timebase_GetSettings(stcChannelSettings.timebase, &timebaseSettings);
2977            timebaseSettings.freeze = true;
2978            timebaseSettings.sourceType = NEXUS_TimebaseSourceType_eFreeRun;
2979            timebaseSettings.sourceSettings.freeRun.trackRange = NEXUS_TimebaseTrackRange_e61ppm;
2980            timebaseSettings.sourceSettings.freeRun.centerFrequency = 0x400000;
2981            nrc = NEXUS_Timebase_SetSettings(stcChannelSettings.timebase, &timebaseSettings);
2982            if (nrc!=NEXUS_SUCCESS) return BSETTOP_ERROR(berr_external_error);
2983        }
2984        /* set and configure playpump timebase */
2985
2986#if NEXUS_NUM_TIMEBASES==1       
2987        /* Use single timebase for both decode and display */
2988        new_timebase = stcChannelSettings.timebase;
2989#else
2990        new_timebase = stcChannelSettings.timebase + B_MAX_DECODES;
2991#endif
2992
2993        rc = bdecode_p_set_playpump_timebase(source, new_timebase);
2994        if (rc != b_ok) return rc;
2995        NEXUS_Timebase_GetSettings(new_timebase, &timebaseSettings);
2996        timebaseSettings.freeze = true;
2997        timebaseSettings.sourceType = NEXUS_TimebaseSourceType_eFreeRun;
2998        timebaseSettings.sourceSettings.pcr.trackRange = NEXUS_TimebaseTrackRange_e122ppm;
2999        nrc = NEXUS_Timebase_SetSettings(new_timebase, &timebaseSettings);
3000        if (nrc!=NEXUS_SUCCESS) return BSETTOP_ERROR(berr_external_error);
3001        break;
3002    case BDECODE_STC_CHANNEL_CFG_TYPE_IP_LIVE_PB:
3003        /* configure shared playpump/decoder timebase */
3004        if(decode->pcrPidChannel != NULL) {
3005            NEXUS_Timebase_GetSettings(stcChannelSettings.timebase, &timebaseSettings);
3006            timebaseSettings.freeze = false;
3007            timebaseSettings.sourceType = NEXUS_TimebaseSourceType_ePcr;
3008            timebaseSettings.sourceSettings.pcr.pidChannel = decode->pcrPidChannel;
3009            timebaseSettings.sourceSettings.pcr.trackRange = NEXUS_TimebaseTrackRange_e244ppm;
3010            timebaseSettings.sourceSettings.pcr.maxPcrError = IP_NETWORK_JITTER * 183/2;
3011            nrc = NEXUS_Timebase_SetSettings(stcChannelSettings.timebase, &timebaseSettings);
3012            if (nrc!=NEXUS_SUCCESS) return BSETTOP_ERROR(berr_external_error);
3013        }
3014
3015        else {
3016            NEXUS_Timebase_GetSettings(stcChannelSettings.timebase, &timebaseSettings);
3017            timebaseSettings.freeze = true;
3018            timebaseSettings.sourceType = NEXUS_TimebaseSourceType_eFreeRun;
3019            timebaseSettings.sourceSettings.freeRun.trackRange = NEXUS_TimebaseTrackRange_e61ppm;
3020            nrc = NEXUS_Timebase_SetSettings(stcChannelSettings.timebase, &timebaseSettings);
3021            if (nrc!=NEXUS_SUCCESS) return BSETTOP_ERROR(berr_external_error);
3022        }
3023        /* set playpump timebase */
3024        rc = bdecode_p_set_playpump_timebase(source, stcChannelSettings.timebase);
3025        if (rc != b_ok) return rc;
3026
3027        /* set and configure outputs timebase */
3028#if NEXUS_NUM_TIMEBASES==1
3029        /* Use single timebase for both decode and display */
3030        new_timebase = stcChannelSettings.timebase;
3031#else
3032        new_timebase = stcChannelSettings.timebase + B_MAX_DECODES;
3033#endif
3034
3035        NEXUS_Timebase_GetSettings(new_timebase, &timebaseSettings);
3036        timebaseSettings.freeze = true;
3037        timebaseSettings.sourceType = NEXUS_TimebaseSourceType_eFreeRun;
3038        timebaseSettings.sourceSettings.pcr.trackRange = NEXUS_TimebaseTrackRange_e61ppm;
3039        nrc = NEXUS_Timebase_SetSettings(new_timebase, &timebaseSettings);
3040        if (nrc!=NEXUS_SUCCESS) return BSETTOP_ERROR(berr_external_error);
3041        /* save the output timebase for this decode */
3042        decode->output_timebase = new_timebase;
3043        break;
3044    case BDECODE_STC_CHANNEL_CFG_TYPE_PVR_PB:
3045        /* do nothing: STC Channel config takes care of this */
3046        break;
3047    default:
3048        return BSETTOP_ERROR(berr_invalid_parameter);
3049    }
3050
3051    return b_ok;
3052}
3053
3054static bresult bdecode_p_config_stc_channel(bdecode_t decode, bstream_t source, bdecode_stc_channel_cfg_type cfg_type) {
3055    bresult rc = b_ok;
3056    NEXUS_Error nrc = NEXUS_SUCCESS;
3057    NEXUS_StcChannelSettings stcChannelSettings;
3058
3059    NEXUS_StcChannel_GetSettings(decode->stcChannel, &stcChannelSettings);
3060
3061    switch (cfg_type) {
3062    case BDECODE_STC_CHANNEL_CFG_TYPE_PARSER_BAND:
3063        BDBG_MSG(("Setting BDECODE_STC_CHANNEL_CFG_TYPE_PARSER_BAND"));
3064        stcChannelSettings.mode = NEXUS_StcChannelMode_ePcr;
3065        stcChannelSettings.autoConfigTimebase = true;
3066        stcChannelSettings.modeSettings.pcr.offsetThreshold = 8;
3067        stcChannelSettings.modeSettings.pcr.maxPcrError = 255;
3068        stcChannelSettings.modeSettings.pcr.disableTimestampCorrection = false;
3069        stcChannelSettings.modeSettings.pcr.disableJitterAdjustment = false;
3070        stcChannelSettings.modeSettings.pcr.pidChannel = decode->pcrPidChannel;
3071        break;
3072    case BDECODE_STC_CHANNEL_CFG_TYPE_TTS_PACING:
3073        BDBG_MSG(("Setting BDECODE_STC_CHANNEL_CFG_TYPE_TTS_PACING"));
3074        stcChannelSettings.mode = NEXUS_StcChannelMode_ePcr;
3075        stcChannelSettings.autoConfigTimebase = false;
3076        stcChannelSettings.modeSettings.pcr.offsetThreshold = 8;
3077        stcChannelSettings.modeSettings.pcr.maxPcrError = 255;
3078        stcChannelSettings.modeSettings.pcr.disableTimestampCorrection = true;
3079        stcChannelSettings.modeSettings.pcr.disableJitterAdjustment = true;
3080        stcChannelSettings.modeSettings.pcr.pidChannel = decode->pcrPidChannel;
3081        break;
3082    case BDECODE_STC_CHANNEL_CFG_TYPE_PCR_PACING:
3083        BDBG_MSG(("Setting BDECODE_STC_CHANNEL_CFG_TYPE_PCR_PACING"));
3084        stcChannelSettings.mode = NEXUS_StcChannelMode_ePcr;
3085        stcChannelSettings.autoConfigTimebase = false;
3086        stcChannelSettings.modeSettings.pcr.offsetThreshold = 900;
3087        stcChannelSettings.modeSettings.pcr.maxPcrError = 450;
3088        stcChannelSettings.modeSettings.pcr.disableTimestampCorrection = true;
3089        stcChannelSettings.modeSettings.pcr.disableJitterAdjustment = true;
3090        stcChannelSettings.modeSettings.pcr.pidChannel = decode->pcrPidChannel;
3091        break;
3092    case BDECODE_STC_CHANNEL_CFG_TYPE_IP_LIVE_PB:
3093        BDBG_MSG(("Setting BDECODE_STC_CHANNEL_CFG_TYPE_IP_LIVE_PB"));
3094        stcChannelSettings.mode = NEXUS_StcChannelMode_ePcr;
3095        stcChannelSettings.autoConfigTimebase = false;
3096        stcChannelSettings.modeSettings.pcr.offsetThreshold = IP_NETWORK_JITTER * 183;
3097        stcChannelSettings.modeSettings.pcr.maxPcrError = IP_NETWORK_JITTER * 183;
3098        stcChannelSettings.modeSettings.pcr.disableTimestampCorrection = true;
3099        stcChannelSettings.modeSettings.pcr.disableJitterAdjustment = true;
3100        stcChannelSettings.modeSettings.pcr.pidChannel = decode->pcrPidChannel;
3101        break;
3102    case BDECODE_STC_CHANNEL_CFG_TYPE_PVR_PB:
3103        BDBG_MSG(("Setting BDECODE_STC_CHANNEL_CFG_TYPE_PVR_PB"));
3104        stcChannelSettings.mode = NEXUS_StcChannelMode_eAuto;
3105        stcChannelSettings.modeSettings.Auto.transportType = b_mpegtype2nexus(source->mpeg.mpeg_type);
3106        break;
3107    default:
3108        return BSETTOP_ERROR(berr_invalid_parameter);
3109        break;
3110    }
3111
3112    nrc = NEXUS_StcChannel_SetSettings(decode->stcChannel, &stcChannelSettings);
3113    if (nrc) return BSETTOP_ERROR(berr_external_error);
3114
3115    return rc;
3116}
3117
3118bresult bdecode_start(bdecode_t decode, bstream_t source, bdecode_window_t window)
3119{
3120    bresult result;
3121    NEXUS_Error rc = b_ok;
3122    bsettop_init_settings initSettings;
3123    bsettop_get_init_settings(&initSettings);
3124
3125    if (!source) {
3126        return BSETTOP_ERROR(berr_invalid_parameter);
3127    }
3128    BDBG_OBJECT_ASSERT(source, bstream);
3129
3130    BDBG_MSG(("bdecode_start decode %p src %p window %p", decode, source, window));
3131
3132    if (decode->nStillDecoder) {
3133        NEXUS_StillDecoderStartSettings startSettings;
3134        if (window) {
3135            return BSETTOP_ERROR(berr_invalid_parameter);
3136        }
3137
3138        if ( decode->stillStream ) {
3139            bdecode_stop(decode);
3140        }
3141        if ( source->consumers.still ) {
3142            BDBG_ERR(("Can only start one still decoder per stream"));
3143            return BSETTOP_ERROR(berr_invalid_parameter);
3144        }
3145
3146        NEXUS_StillDecoder_GetDefaultStartSettings(&startSettings);
3147        decode->nStillDecoderPid = bstream_p_open_pid(source, source->mpeg.video[0].pid, bstream_pid_type_other);
3148        if ( NULL == decode->nStillDecoderPid ) {
3149            BDBG_ERR(("Unable to open still decoder PID channel"));
3150            return BSETTOP_ERROR(berr_external_error);
3151        }
3152        decode->stillStream = source;
3153        source->consumers.still = decode;
3154        startSettings.pidChannel = decode->nStillDecoderPid;
3155        startSettings.codec = b_videocodec2nexus(source->mpeg.video[0].format);
3156        startSettings.stillPictureReady.callback = bdecode_p_still_ready;
3157        startSettings.stillPictureReady.context = decode;
3158        BDBG_MSG(("starting still %p %d", startSettings.pidChannel, startSettings.codec));
3159        rc = NEXUS_StillDecoder_Start(decode->nStillDecoder, &startSettings);
3160        if ( rc ) {
3161            return BSETTOP_ERROR(berr_external_error);
3162        }
3163        return b_ok;
3164    }
3165
3166    if (decode->started) {
3167        return BSETTOP_ERROR(berr_not_available);
3168    }
3169    if ( window->decode ) {
3170        return BSETTOP_ERROR(berr_not_available);
3171    }
3172
3173    decode->tsm = (initSettings.lipsync_mode == bsettop_lipsync_mode_disabled)?false:true;
3174
3175#if B_DECODE_CRC_CAPTURE || B_DECODE_USERDATA_CAPTURE
3176    decode->metadata.wptr = 0;
3177    decode->metadata.rptr = 0;
3178#endif
3179
3180    decode->window = window;
3181
3182    if (source->video_primer) {
3183        goto video_primer;
3184    }
3185
3186    if (!source->producer.tuner) {
3187                if (source->producer.fcc.videoPidChannel != NULL)
3188                {
3189                        decode->stcChannel = source->producer.fcc.stcChannel;
3190                        decode->tsm = true;
3191                        decode->pcrPidChannel = source->producer.fcc.pcrPidChannel;
3192                }
3193                else
3194                {
3195                        /* source is digital (not analog) */
3196                        uint16_t pcr_pid = source->mpeg.pcr_pid;
3197                        NEXUS_StcChannelSettings stcChannelSettings;
3198       
3199                        NEXUS_StcChannel_GetSettings(decode->stcChannel, &stcChannelSettings);
3200                        if (source->mpeg.mpeg_type == bstream_mpeg_type_es) {
3201                                decode->tsm = false;
3202                        }
3203       
3204                        /* set pid channel only for live and ip playback modes */
3205                        if (source->parser_band
3206        #ifdef B_HAS_IP
3207                                || source->producer.is_playback_ip
3208        #endif
3209                                ) {
3210                                if (pcr_pid != 0 && pcr_pid < 0x1fff) {
3211                                        decode->pcrPidChannel = bstream_p_open_pid(source, pcr_pid, bstream_pid_type_pcr);
3212                                        if (decode->pcrPidChannel == NULL) {
3213                                                BDBG_ERR(("Unable to allocate PCR Pid channel\n"));
3214                                                return BSETTOP_ERROR(berr_external_error);
3215                                        }
3216                                }
3217                                else {
3218                                        decode->pcrPidChannel = NULL;
3219                                        if (source->parser_band) {
3220                                                decode->tsm = false;
3221                                        }
3222                                }
3223                        }
3224                }
3225        if (source->parser_band) {
3226            /* Live */
3227            decode->cfg_type = BDECODE_STC_CHANNEL_CFG_TYPE_PARSER_BAND;
3228        }
3229#ifdef B_HAS_IP
3230        else if (source->producer.is_playback_ip) {
3231            /* IP */
3232            if (source->producer.timestamp_active) {
3233                if (source->producer.timestamp_enabled) {
3234                    decode->cfg_type = BDECODE_STC_CHANNEL_CFG_TYPE_TTS_PACING;
3235                }
3236                else {
3237                    decode->cfg_type = BDECODE_STC_CHANNEL_CFG_TYPE_PCR_PACING;
3238                }
3239            }
3240            else if (source->producer.use_live_playback_mode) {
3241                decode->cfg_type = BDECODE_STC_CHANNEL_CFG_TYPE_IP_LIVE_PB;
3242            }
3243            else {
3244                decode->cfg_type = BDECODE_STC_CHANNEL_CFG_TYPE_PVR_PB;
3245            }
3246        }
3247#endif
3248        else {
3249            /* PVR local playback */
3250            decode->cfg_type = BDECODE_STC_CHANNEL_CFG_TYPE_PVR_PB;
3251        }
3252
3253        rc = bdecode_p_config_timebases(decode, source, decode->cfg_type);
3254        if (rc != b_ok) return rc;
3255
3256        rc = bdecode_p_config_stc_channel(decode, source, decode->cfg_type);
3257        if (rc != b_ok) return rc;
3258    }
3259
3260    /* Have display check output timebases prior to video/audio start */
3261    bdisplay_p_decode_starting(window->display, window, decode);
3262
3263    if (decode->image_input_started) {
3264        NEXUS_VideoWindow_RemoveInput(window->nWindow, NEXUS_VideoImageInput_GetConnector(decode->video_decode->nVideoImageInput));
3265        decode->image_input_started = false;
3266    }
3267
3268    if (decode->video_decode) {
3269
3270#ifdef B_HAS_IP
3271        /* for playback ip fifo size was increased to 3*, for live and playback decode
3272            we dont need it */
3273        if (!source->producer.is_playback_ip && decode->video_decode->nVideoDecoder && NULL==bsettop_get_config("fifo_size")) {
3274            NEXUS_VideoDecoderSettings nVideoDecoderSettings;
3275            NEXUS_VideoDecoderStatus nVideoDecoderStatus;
3276            rc = NEXUS_VideoDecoder_GetStatus(decode->video_decode->nVideoDecoder,&nVideoDecoderStatus);
3277            if (rc)
3278            {
3279                rc=BERR_TRACE(rc);
3280            }
3281            else
3282            {
3283                NEXUS_VideoDecoder_GetSettings(decode->video_decode->nVideoDecoder,&nVideoDecoderSettings);
3284                BDBG_WRN(("Non IP mode,changing threshold to 1/3 of fifo_size(%d)",nVideoDecoderStatus.fifoSize));
3285                nVideoDecoderSettings.fifoThreshold=nVideoDecoderStatus.fifoSize/3;
3286                NEXUS_VideoDecoder_SetSettings(decode->video_decode->nVideoDecoder,&nVideoDecoderSettings);
3287            }
3288        }
3289#endif
3290
3291        result = bdecode_start_video(decode->video_decode, source, window);
3292        if (result) BSETTOP_ERROR(result);
3293    }
3294video_primer:
3295    if (decode->audio_decode) {
3296        result = bdecode_start_audio(decode->audio_decode, source, window);
3297        if (result) BSETTOP_ERROR(result);
3298    }
3299
3300    decode->started = true;
3301    decode->window = window;
3302    decode->source = source;
3303    source->consumers.decode = decode;
3304    window->decode = decode;
3305
3306    if (source->video_primer) {
3307        return rc;
3308    }
3309
3310    if (source->producer.playback) {
3311       rc = bplayback_p_start(source->producer.playback);
3312    }
3313
3314    result = bdecode_p_start_astm(decode);
3315    if (result) BSETTOP_ERROR(result);
3316
3317    return rc;
3318}
3319
3320void bdecode_stop(bdecode_t decode)
3321{
3322    BDBG_MSG(("bdecode_stop %p", decode));
3323
3324    if (decode->nStillDecoder) {
3325        if ( decode->stillStream )
3326        {
3327            NEXUS_StillDecoder_Stop(decode->nStillDecoder);
3328            bstream_p_close_pid(decode->stillStream, decode->nStillDecoderPid);
3329            decode->nStillDecoderPid = NULL;
3330            decode->stillStream->consumers.still = NULL;
3331            decode->stillStream = NULL;
3332            return;
3333        }
3334    }
3335
3336    if (decode->image_input_started) {
3337        NEXUS_VideoWindow_RemoveInput(decode->window->nWindow, NEXUS_VideoImageInput_GetConnector(decode->video_decode->nVideoImageInput));
3338        decode->image_input_started = false;
3339    }
3340    if (!decode->started) {
3341        return;
3342    }
3343
3344    bdecode_p_stop_astm(decode);
3345
3346    BDBG_ASSERT(decode->source->consumers.decode == decode);
3347
3348    if (decode->video_decode) {
3349        bdecode_stop_video(decode->video_decode);
3350    }
3351    if (decode->audio_decode) {
3352        bdecode_stop_audio(decode->audio_decode);
3353    }
3354
3355    if ( decode->pcrPidChannel && !decode->source->producer.fcc.pcrPidChannel )
3356    {
3357        bstream_p_close_pid(decode->source, decode->pcrPidChannel);
3358        decode->pcrPidChannel = NULL;
3359    }
3360
3361    decode->started = false;
3362    decode->window->decode = NULL;
3363    decode->window = NULL;
3364    BDBG_OBJECT_ASSERT(decode->source, bstream);
3365    decode->source->consumers.decode = NULL;
3366    decode->source = NULL;
3367}
3368
3369baudio_decode_t bdecode_detach_audio(bdecode_t decode)
3370{
3371    baudio_decode_t audio_decode;
3372    BDBG_ASSERT(NULL != decode);
3373    audio_decode = decode->audio_decode;
3374
3375    if ( decode->settings.audio.display )
3376    {
3377        if ( decode->settings.audio.display->mixerInputsStarted > decode->started )
3378        {
3379            BDBG_ERR(("Can't detach audio while other audio inputs to the display are running."));
3380            return NULL;
3381        }
3382    }
3383
3384    if (audio_decode) {
3385        if (decode->started) {
3386            bdecode_stop_audio(decode->audio_decode);
3387        }
3388        bdecode_p_set_audio_display(decode->audio_decode, NULL);
3389        audio_decode->decode = NULL;
3390        decode->audio_decode = NULL;
3391    }
3392    return audio_decode;
3393}
3394
3395bresult bdecode_attach_audio(bdecode_t decode, baudio_decode_t audio)
3396{
3397    bresult rc =0;
3398    BDBG_ASSERT(NULL != decode);
3399
3400    if(audio==NULL)
3401        return BSETTOP_ERROR(berr_invalid_parameter);
3402
3403    if (decode->audio_decode) {
3404        return BSETTOP_ERROR(berr_invalid_parameter);
3405    }
3406    if ( decode->started && decode->settings.audio.display && decode->window->display->mixerInputsStarted > 0 )
3407    {
3408        BDBG_ERR(("Can't attach to a display while other inputs are running."));
3409        return BSETTOP_ERROR(berr_busy);
3410    }
3411    decode->audio_decode = audio;
3412    audio->decode = decode;
3413    if (decode->started) {
3414        /* Have display check output timebases prior to video/audio start to refresh PLL/timebase settings (needed if only detach/attach is called) */
3415        bdisplay_p_decode_starting(decode->window->display, decode->window, decode);
3416        if ( decode->settings.audio.display )
3417        {
3418            bdecode_p_set_audio_display(audio, decode->settings.audio.display);
3419        }
3420        rc = bdecode_start_audio(decode->audio_decode, decode->source, decode->window);
3421        if (rc) return BSETTOP_ERROR(berr_external_error);
3422    }
3423    return 0;
3424}
3425
3426bresult bdecode_set_audio_program(bdecode_t decode, unsigned index)
3427{
3428    /* TODO:Add support for quick audio decode in case of playback*/
3429    baudio_decode_t audio_decode;
3430    audio_decode = decode->audio_decode;
3431
3432    BDBG_MSG(("set audio program %d",index));
3433
3434    if ( NULL == audio_decode )
3435    {
3436        return b_ok;
3437    }
3438
3439    if ( decode->started )
3440    {
3441        bdecode_stop_audio(audio_decode);
3442        decode->audio_program = index;
3443        bdecode_start_audio(audio_decode, decode->source, decode->window);
3444    }
3445    else
3446    {
3447        decode->audio_program = index;
3448    }
3449
3450    return b_ok;
3451}
3452
3453baudio_decode_t bdecode_get_audio(bdecode_t decode, bobject_t audio_id)
3454{
3455    BDBG_ASSERT(NULL != decode);
3456    if (B_ID_GET_INDEX(audio_id) == 0)
3457    {
3458        return decode->audio_decode;
3459    }
3460    else if (decode->audio_decode && decode->audio_decode->secondary_audio_decode && decode->audio_decode->secondary_audio_decode->nAudioDecoder )
3461    {
3462        return decode->audio_decode->secondary_audio_decode;
3463    }
3464    else
3465    {
3466        /* this is normal */
3467        return NULL;
3468    }
3469}
3470
3471bvideo_decode_t bdecode_get_video(bdecode_t decode, bobject_t video_id)
3472{
3473    BSTD_UNUSED(video_id);
3474    return decode->video_decode;
3475}
3476
3477bvideo_decode_t bdecode_detach_video(bdecode_t decode)
3478{
3479    bvideo_decode_t video_decode = decode->video_decode;
3480    if (video_decode) {
3481        if (decode->started) {
3482            bdecode_stop_video(decode->video_decode);
3483            bdecode_p_unset_sync_channel(decode,true,false,false);
3484            bdecode_p_unset_astm(decode,true,false,false);
3485        }
3486        decode->video_decode = NULL;
3487    }
3488    return video_decode;
3489}
3490
3491bresult bdecode_attach_video(bdecode_t decode, bvideo_decode_t video)
3492{
3493    bresult rc =0;
3494    if (decode->video_decode) {
3495        return BSETTOP_ERROR(berr_invalid_parameter);
3496    }
3497    decode->video_decode = video;
3498
3499    /* apply settings that were deferred before */
3500    rc = bdecode_set(decode, &decode->settings);
3501    if (rc) return BSETTOP_ERROR(berr_external_error);
3502
3503    if (decode->started) {
3504        rc =  bdecode_start_video(decode->video_decode, decode->source, decode->window);
3505        if (rc) return BSETTOP_ERROR(berr_external_error);
3506    }
3507    return rc;
3508}
3509
3510bresult bdecode_set_video_program(bdecode_t decode, unsigned index)
3511{
3512    decode->video_program = index;
3513    return 0;
3514}
3515
3516/* this works because the struct is already memset to 0 */
3517#define BRCM_AUD_MEMCPY(a,b) BKNI_Memcpy(a,b,strlen(b))
3518
3519static const char * audio_layer_table[] = {
3520    "AAC", /* AAC is extension of mpeg spec, and spec gives it a layer 0 value */
3521    "Layer 3",
3522    "Layer 2",
3523    "Layer 1",
3524    "Unknown"
3525};
3526/* audio sample rate table, must match enum in bavc.h */
3527static const unsigned long sr_table[] = {
3528    32000, /* BAVC_AudioSamplingRate_e32k */
3529    44100, /* BAVC_AudioSamplingRate_e44_1k */
3530    48000, /* BAVC_AudioSamplingRate_e48k */
3531    96000, /* BAVC_AudioSamplingRate_e96k */
3532    /* added to support for digital audio receiver */
3533    16000, /* BAVC_AudioSamplingRate_e16k */
3534    22050, /* BAVC_AudioSamplingRate_e22_05k */
3535    24000, /* BAVC_AudioSamplingRate_e24k */
3536    64000, /* BAVC_AudioSamplingRate_e64k */
3537    88200, /* BAVC_AudioSamplingRate_e88_2k */
3538    128960, /* BAVC_AudioSamplingRate_e128k */
3539    176400, /* BAVC_AudioSamplingRate_e176_4k */
3540    192960 /* BAVC_AudioSamplingRate_e192k */
3541};
3542
3543/* NOTE: lfe is low frequency effects, somewhat similar to subwoofer */
3544static const char * rap_ac3_chan_table[] = {
3545    "1+1", "1/0.0", "2/0.0", "3/0.0", "2/1.0", "3/1.0", "2/2.0", "3/2.0", "eMax"
3546};
3547static const char * rap_ac3_chan_table_lfe[] = {
3548    "1+1", "1/0.1", "2/0.1", "3/0.1", "2/1.1", "3/1.1", "2/2.1", "3/2.1", "eMax"
3549};
3550static const char * rap_downmix_mode_table[] = {
3551    /* based on BRAP_OutputMode, beware deprecated values */
3552/*    "1/0", "1/1", "unused", "2/0", "3/0", "2/1", "3/1", "2/2", "3/2", "eMax" */
3553/* TODO: remap BRAP_OutputMode to downmixType and dolby.stereoDownmixMode */
3554    "Auto", "1_0", "1_1", "2_0", "3_0", "2_1", "3_1", "2_2", "3_2", "3_4", "eMax"
3555};
3556
3557void baudio_decode_get_status(baudio_decode_t audio, baudio_decode_status *status)
3558{
3559    NEXUS_AudioDecoderStatus nStatus;
3560    NEXUS_Error rc;
3561    NEXUS_AudioDecoderSettings nSetting;
3562
3563    BKNI_Memset(status, 0, sizeof(*status));
3564
3565        status->common.program = audio->decode->audio_program;
3566
3567        if ( audio == g_audio_passthrough_owner || NULL == g_audio_passthrough_owner )
3568        {
3569                status->compressed_spdif_output = true;
3570        }
3571
3572    NEXUS_AudioDecoder_GetSettings(audio->nAudioDecoder, &nSetting);
3573
3574    rc = NEXUS_AudioDecoder_GetStatus(audio->nAudioDecoder, &nStatus);
3575    if (rc) return;
3576
3577    if(nStatus.codecStatus.mpeg.layer < NEXUS_AudioMpegLayer_e3 || nStatus.codecStatus.mpeg.layer > NEXUS_AudioMpegLayer_e1)
3578       nStatus.codecStatus.mpeg.layer = NEXUS_AudioMpegLayer_eMax;   /* Init to a default value */
3579
3580    if (!nStatus.started) return;
3581
3582    status->common.fifo_depth = nStatus.fifoDepth;
3583    status->common.fifo_size = nStatus.fifoSize;
3584    status->common.pts = nStatus.pts;
3585    switch (nStatus.ptsType) {
3586    case NEXUS_PtsType_eCoded:
3587        status->common.pts_type = bdecode_pts_type_coded; break;
3588    case NEXUS_PtsType_eInterpolatedFromValidPTS:
3589        status->common.pts_type = bdecode_pts_type_interpolated; break;
3590    default:
3591        status->common.pts_type = bdecode_pts_type_invalid; break;
3592    }
3593    bdecode_get_stc(audio->decode, &status->common.stc);
3594    status->common.started = nStatus.started;
3595    status->common.pts_error_cnt = nStatus.ptsErrorCount;
3596
3597    if(audio->decode->window && audio->decode->window->display && audio->decode->window->display->settings.spdif)
3598    {
3599        if(audio->decode->window->display->settings.spdif->desired.pcm)
3600            status->compressed_spdif_output = false;
3601        else
3602            status->compressed_spdif_output = true;
3603    }
3604
3605    status->codec = b_nexus2audiocodec(nStatus.codec);
3606    status->sample_rate = nStatus.sampleRate;
3607    switch(nStatus.codec)
3608    {
3609    case NEXUS_AudioCodec_eAc3:
3610    case NEXUS_AudioCodec_eAc3Plus:
3611        status->bitrate = nStatus.codecStatus.ac3.bitrate;
3612        if(nStatus.codecStatus.ac3.acmod <= NEXUS_AudioAc3Acmod_eMax)
3613        {
3614            if(nStatus.codecStatus.ac3.lfe)
3615            {
3616                BRCM_AUD_MEMCPY(status->channels, rap_ac3_chan_table_lfe[nStatus.codecStatus.ac3.acmod]);
3617            }
3618            else
3619            {
3620                BRCM_AUD_MEMCPY(status->channels, rap_ac3_chan_table[nStatus.codecStatus.ac3.acmod]);
3621            }
3622        }
3623
3624        /*status->status->channels*/
3625        break;
3626    case NEXUS_AudioCodec_eAac:
3627    case NEXUS_AudioCodec_eAacPlus:
3628        status->bitrate = nStatus.codecStatus.aac.bitrate;
3629        if(nStatus.codecStatus.aac.acmod <NEXUS_AudioAacAcmod_eMax)
3630        {
3631            if(nStatus.codecStatus.aac.lfe)
3632            {
3633                BRCM_AUD_MEMCPY(status->channels, rap_ac3_chan_table_lfe[nStatus.codecStatus.aac.acmod]);
3634            }
3635            else
3636            {
3637                BRCM_AUD_MEMCPY(status->channels, rap_ac3_chan_table[nStatus.codecStatus.aac.acmod]);
3638            }
3639        }
3640        break;
3641    case NEXUS_AudioCodec_eMpeg:
3642    case NEXUS_AudioCodec_eMp3:
3643        status->bitrate = nStatus.codecStatus.mpeg.bitrate;
3644
3645        switch(nStatus.codecStatus.mpeg.channelMode)
3646        {
3647        case NEXUS_AudioMpegChannelMode_eStereo:
3648            BRCM_AUD_MEMCPY(status->channels, "2.0");
3649            break;
3650        case NEXUS_AudioMpegChannelMode_eIntensityStereo:
3651            BRCM_AUD_MEMCPY(status->channels, "2.0!");
3652            break;
3653        case NEXUS_AudioMpegChannelMode_eDualChannel:
3654            BRCM_AUD_MEMCPY(status->channels, "1+1");
3655            break;
3656        case NEXUS_AudioMpegChannelMode_eSingleChannel:
3657            BRCM_AUD_MEMCPY(status->channels, "1.0");
3658            break;
3659        default:
3660            BDBG_ERR(("Invalid channel mode"));
3661        }
3662        break;
3663    case NEXUS_AudioCodec_eWmaStd:
3664    case NEXUS_AudioCodec_eWmaPro:
3665#if 0
3666        switch (nStatus.codecStatus.wma.acmod) {
3667        case BRAP_DSPCHN_WmaStdAcmod_eOneCh:
3668            BRCM_AUD_MEMCPY(status->channels, "1.0");
3669            break;
3670        case BRAP_DSPCHN_WmaStdAcmod_eTwoCh:
3671            BRCM_AUD_MEMCPY(status->channels, "2.0");
3672
3673            break;
3674        }
3675#endif
3676        break;
3677    case NEXUS_AudioCodec_eLpcmDvd:
3678    case NEXUS_AudioCodec_eLpcmHdDvd:
3679    case NEXUS_AudioCodec_eLpcmBluRay:
3680    case NEXUS_AudioCodec_eDts:
3681    case NEXUS_AudioCodec_ePcm:
3682    case NEXUS_AudioCodec_ePcmWav:
3683    case NEXUS_AudioCodec_eDra:
3684    case NEXUS_AudioCodec_eDtsHd:
3685        break;
3686    case NEXUS_AudioCodec_eUnknown:
3687        /* this is normal in transitions */
3688        break;
3689    default:
3690        BDBG_ERR(("Unsupported audio format %d",nStatus.codec));
3691    }
3692
3693    /* supress warning message TODO: status->downmix_mode */
3694    BRCM_AUD_MEMCPY(status->downmix_mode, rap_downmix_mode_table[nSetting.outputMode]);
3695    BRCM_AUD_MEMCPY(status->layer, audio_layer_table[nStatus.codecStatus.mpeg.layer]);
3696
3697
3698#if 0
3699    /* TODO:Need support for these */
3700    status->frame_queue;
3701    status->downmix_mode;
3702#endif
3703}
3704
3705void bvideo_decode_get_status(bvideo_decode_t video, bvideo_decode_status *status)
3706{
3707    NEXUS_VideoDecoderStatus nStatus;
3708    NEXUS_Error rc;
3709
3710    BKNI_Memset(status, 0, sizeof(*status));
3711
3712    rc = NEXUS_VideoDecoder_GetStatus(video->nVideoDecoder, &nStatus);
3713    if (rc) return;
3714
3715    status->common.fifo_depth = nStatus.fifoDepth;
3716    status->common.fifo_size = nStatus.fifoSize;
3717    status->common.pts = nStatus.pts;
3718    switch (nStatus.ptsType) {
3719    case NEXUS_PtsType_eCoded:
3720        status->common.pts_type = bdecode_pts_type_coded; break;
3721    case NEXUS_PtsType_eInterpolatedFromValidPTS:
3722        status->common.pts_type = bdecode_pts_type_interpolated; break;
3723    default:
3724        status->common.pts_type = bdecode_pts_type_invalid; break;
3725    }
3726    bdecode_get_stc(video->decode, &status->common.stc);
3727    status->common.program = video->decode->video_program;
3728    status->common.started = nStatus.started;
3729    status->common.pts_error_cnt = nStatus.ptsErrorCount;
3730
3731    if (video->decode->source) {
3732        status->codec = video->decode->source->mpeg.video[video->decode->video_program].format;
3733    }
3734    /* TODO: status->panscan_status; */
3735    status->aspect_ratio = (unsigned)nStatus.aspectRatio;
3736
3737    status->source_width = nStatus.source.width;
3738    status->source_height = nStatus.source.height;
3739    status->picture_queue = nStatus.queueDepth;
3740    status->interlaced = nStatus.interlaced;
3741    status->time_code.hours = nStatus.timeCode.hours;
3742    status->time_code.minutes = nStatus.timeCode.minutes;
3743    status->time_code.seconds = nStatus.timeCode.seconds;
3744    status->time_code.pictures = nStatus.timeCode.pictures;
3745    status->frame_rate = b_nexus2framerate(nStatus.frameRate);
3746    status->display_drops = nStatus.numDisplayDrops;
3747    status->display_underflows = nStatus.numDisplayUnderflows;
3748}
3749
3750bresult bdecode_get_status(bdecode_t decode, bdecode_status *status)
3751{
3752    BKNI_Memset(status, 0, sizeof(*status));
3753    if (decode->video_decode) {
3754        bvideo_decode_status video;
3755
3756        bvideo_decode_get_status(decode->video_decode, &video);
3757        /* copy status to legacy structure */
3758        status->source_width = video.source_width;
3759        status->source_height = video.source_height;
3760        status->interlaced = video.interlaced;
3761        status->video_codec = video.codec;
3762        status->video_frame_rate = video.frame_rate;
3763        status->video_fifo_depth = video.common.fifo_depth;
3764        status->video_fifo_size = video.common.fifo_size;
3765        status->video_pts = video.common.pts;
3766        status->video_pts_type = video.common.pts_type;
3767        status->video_stc = video.common.stc;
3768        status->video_aspect_ratio = video.aspect_ratio;
3769        status->video_program = video.common.program;
3770        status->video_picture_queue = video.picture_queue;
3771        status->video_panscan_status = video.panscan_status;
3772        status->time_code = video.time_code;
3773        status->video_pts_error_cnt = video.common.pts_error_cnt;
3774        status->video_display_underflows = video.display_underflows;
3775        status->video_display_drops = video.display_drops;
3776    }
3777    if (decode->audio_decode) {
3778        baudio_decode_status audio;
3779        baudio_decode_get_status(decode->audio_decode, &audio);
3780        status->audio_fifo_depth = audio.common.fifo_depth;
3781        status->audio_fifo_size = audio.common.fifo_size;
3782        status->audio_pts = audio.common.pts;
3783        status->audio_pts_type = audio.common.pts_type;
3784        status->audio_stc = audio.common.stc;
3785        status->audio_program = audio.common.program;
3786        status->audio_sample_rate = audio.sample_rate;
3787        status->audio_frame_queue = audio.frame_queue;
3788        BKNI_Memcpy(status->audio_channels, audio.channels, sizeof(audio.channels));
3789        BKNI_Memcpy(status->audio_downmix_mode, audio.downmix_mode, sizeof(audio.downmix_mode));
3790        BKNI_Memcpy(status->audio_layer, audio.layer, sizeof(audio.layer));
3791        status->audio_compressed_spdif_output= audio.compressed_spdif_output;
3792        status->audio_bitrate = audio.bitrate;
3793        status->audio_format = audio.codec;
3794        status->audio_pts_error_cnt = audio.common.pts_error_cnt;
3795    }
3796    return 0;
3797}
3798
3799bresult bdecode_set_audio_volume(bdecode_t decode, const baudio_volume *volume)
3800{
3801    int leftVolume;
3802    int rightVolume;
3803
3804    decode->volume = *volume;
3805    leftVolume = b_volume2nexus(volume->left, false, &decode->volume.left);
3806    rightVolume = b_volume2nexus(volume->right, false, &decode->volume.right);
3807    if (decode->window && decode->audio_decode && decode->audio_decode->nAudioDecoder) 
3808    {
3809        bdecode_p_set_downmix(decode);
3810    }
3811    return 0;
3812}
3813
3814static bresult bdecode_set_audio_ip_tsm_settings(baudio_decode_t audio_decode)
3815{
3816#ifdef B_HAS_IP
3817    if (audio_decode && audio_decode->nAudioDecoder)
3818    {
3819        NEXUS_AudioDecoderSettings  nAudioDecodeSettings;
3820
3821        NEXUS_AudioDecoder_GetSettings(audio_decode->nAudioDecoder, &nAudioDecodeSettings);
3822
3823        switch (audio_decode->decode->cfg_type) {
3824        case BDECODE_STC_CHANNEL_CFG_TYPE_PARSER_BAND:
3825            nAudioDecodeSettings.ptsOffset = 0;
3826            break;
3827        case BDECODE_STC_CHANNEL_CFG_TYPE_TTS_PACING:
3828        case BDECODE_STC_CHANNEL_CFG_TYPE_PCR_PACING:
3829            nAudioDecodeSettings.ptsOffset = 0;
3830            break;
3831        case BDECODE_STC_CHANNEL_CFG_TYPE_IP_LIVE_PB:
3832            nAudioDecodeSettings.ptsOffset = 45 * IP_NETWORK_JITTER;
3833            break;
3834        case BDECODE_STC_CHANNEL_CFG_TYPE_PVR_PB:
3835            nAudioDecodeSettings.ptsOffset = 0;
3836            break;
3837        default:
3838            return BSETTOP_ERROR(berr_invalid_parameter);
3839            break;
3840        }
3841        if(audio_decode->decode->settings.tsm.wga_mode_enable) {
3842            BDBG_WRN(("enabling WGA mode"));
3843            nAudioDecodeSettings.wideGaThreshold = true;
3844        }
3845
3846        if (NEXUS_AudioDecoder_SetSettings(audio_decode->nAudioDecoder, &nAudioDecodeSettings))
3847        {
3848            return BSETTOP_ERROR(berr_external_error);
3849        }
3850    }
3851    return b_ok;
3852#else
3853    BSTD_UNUSED(audio_decode);
3854    return (berr_not_supported);
3855#endif
3856}
3857
3858bresult bdecode_get_audio_volume(bdecode_t decode, baudio_volume *volume)
3859{
3860    *volume = decode->volume;
3861    return 0;
3862}
3863
3864bresult bdecode_get_stc(bdecode_t decode, uint32_t *stc)
3865{
3866    NEXUS_StcChannel_GetStc(decode->stcChannel, stc);
3867    return 0;
3868}
3869
3870bresult bdecode_set_stc(bdecode_t decode, uint32_t stc)
3871{
3872    NEXUS_StcChannel_SetStc(decode->stcChannel, stc);
3873    return 0;
3874}
3875
3876void bdecode_slow_clock(bdecode_t decode, bool slow)
3877{
3878    /* This function is not used in Settop API. It is deprecated. See bplaypump_set_pwm_value instead. */
3879    BSTD_UNUSED(decode);
3880    BSTD_UNUSED(slow);
3881    BSETTOP_ERROR(berr_not_supported);
3882}
3883
3884#if B_DECODE_CRC_CAPTURE || B_DECODE_USERDATA_CAPTURE
3885static void bdecode_p_add_metadata(bdecode_t decode, uint32_t *data, uint32_t size)
3886{
3887    uint32_t empty_space;
3888
3889    if(decode->metadata.wptr < decode->metadata.rptr)
3890        empty_space = decode->metadata.rptr- decode->metadata.wptr;
3891    else
3892        empty_space = B_DECODE_METADATA_CAPTURE_SIZE - decode->metadata.wptr + decode->metadata.rptr;
3893
3894    if(size <= empty_space){
3895        if((decode->metadata.wptr + size)<=B_DECODE_METADATA_CAPTURE_SIZE){
3896            BKNI_Memcpy(&decode->metadata.data[decode->metadata.wptr], data, size*sizeof(uint32_t));
3897        }
3898        else{
3899            uint32_t partial_size = B_DECODE_METADATA_CAPTURE_SIZE-decode->metadata.wptr;
3900            BKNI_Memcpy(&decode->metadata.data[decode->metadata.wptr], data, partial_size*sizeof(uint32_t));
3901            BKNI_Memcpy(&decode->metadata.data[0], data+partial_size, (size-partial_size)*sizeof(uint32_t));
3902        }
3903
3904        decode->metadata.wptr += size;
3905        decode->metadata.wptr = decode->metadata.wptr % B_DECODE_METADATA_CAPTURE_SIZE;
3906
3907    }
3908
3909    BDBG_ASSERT(decode->metadata.wptr != decode->metadata.rptr);
3910}
3911#endif
3912
3913#if B_DECODE_USERDATA_CAPTURE
3914static void check_for_userdata(bdecode_t decode)
3915{
3916    uint32_t header[4];
3917
3918    header[0] = 1; /* 1 is user data */
3919#if 0
3920    header[1] = info->ui32UserDataBufSize + 2*sizeof(uint32_t);
3921    header[2] = info->ui32PTS;
3922    header[3] = ((((uint16_t)info->bPTSValid)<<16) | ((uint16_t)info->ui32UserDataBufSize));
3923#endif
3924
3925    bdecode_p_add_metadata(decode, header, 4);
3926    bdecode_p_add_metadata(decode, (uint32_t*)info->pUserDataBuffer, info->ui32UserDataBufSize/sizeof(uint32_t));
3927    if (info->ui32UserDataBufSize % sizeof(uint32_t)) {
3928        BDBG_ERR(("user data dropped"));
3929    }
3930}
3931#endif
3932
3933#if B_DECODE_CRC_CAPTURE
3934void check_for_crcdata(bdecode_t decode)
3935{
3936    if (!decode->video_decode) return;
3937    while (1) {
3938        NEXUS_Error rc;
3939        NEXUS_VideoInputCrcData crcData;
3940        uint32_t crc_data[7];
3941        unsigned n;
3942
3943        rc = NEXUS_VideoInput_GetCrcData(NEXUS_VideoDecoder_GetConnector(decode->video_decode->nVideoDecoder), &crcData, 1, &n);
3944        if (rc) {
3945            BDBG_ERR(("NEXUS_VideoInput_GetCrcData failed %d", rc));
3946            break;
3947        }
3948        if (!n) {
3949            break;
3950        }
3951
3952        crc_data[0] = 0; /* 0 is CRC */
3953        crc_data[1] = (sizeof(uint32_t)*5);
3954        crc_data[2] = crcData.idrPictureId;
3955        crc_data[3] = crcData.pictureOrderCount;
3956        crc_data[4] = crcData.lumaCrc;
3957        crc_data[5] = crcData.chromaCrc;
3958        crc_data[6] = crcData.isField;
3959
3960        bdecode_p_add_metadata(decode, crc_data, 7);
3961    }
3962}
3963#endif
3964
3965
3966bresult bdecode_read_metadata(bdecode_t decode, void *buffer, unsigned size, unsigned *amount_read)
3967{
3968    *amount_read = 0;
3969#if B_DECODE_CRC_CAPTURE || B_DECODE_USERDATA_CAPTURE
3970#if B_DECODE_USERDATA_CAPTURE
3971    check_for_userdata(decode);
3972#endif
3973#if B_DECODE_CRC_CAPTURE
3974    check_for_crcdata(decode);
3975#endif
3976
3977    if (decode->metadata.rptr != decode->metadata.wptr) {
3978        unsigned n;
3979        uint32_t consumable_buffer_size;
3980
3981        if (decode->metadata.rptr < decode->metadata.wptr)
3982            n = decode->metadata.wptr - decode->metadata.rptr;
3983        else
3984            n = decode->metadata.wptr + B_DECODE_METADATA_CAPTURE_SIZE - decode->metadata.rptr;
3985
3986        /* calculate the buffer that's consumable */
3987        consumable_buffer_size = n * sizeof(uint32_t);
3988
3989        /* determine the final payload size */
3990        if (consumable_buffer_size > size)
3991            consumable_buffer_size = size;
3992
3993        *amount_read = consumable_buffer_size;
3994
3995        if(((B_DECODE_METADATA_CAPTURE_SIZE-decode->metadata.rptr)*sizeof(uint32_t))>=consumable_buffer_size)
3996            BKNI_Memcpy(buffer, &decode->metadata.data[decode->metadata.rptr], consumable_buffer_size);
3997        else{
3998            uint32_t patrial_size = consumable_buffer_size - (decode->metadata.wptr * sizeof(uint32_t));
3999            BKNI_Memcpy(buffer, &decode->metadata.data[decode->metadata.rptr], patrial_size);
4000            BKNI_Memcpy((uint8_t*)buffer + patrial_size, &decode->metadata.data[0], decode->metadata.wptr * sizeof(uint32_t));
4001        }
4002
4003        /* update the read pointer */
4004        decode->metadata.rptr +=  consumable_buffer_size / sizeof(uint32_t);
4005        decode->metadata.rptr = decode->metadata.rptr % B_DECODE_METADATA_CAPTURE_SIZE;
4006    }
4007#else
4008    BSTD_UNUSED(decode);
4009    BSTD_UNUSED(buffer);
4010    BSTD_UNUSED(size);
4011#endif
4012    return b_ok;
4013}
4014
4015bresult bdecode_allocate_capture_buffers(bdecode_t decode, unsigned count)
4016{
4017    /* This does nothing at the time. By default, Nexus allows 1 capture buffer. This could be
4018    increased if needed. */
4019    BSTD_UNUSED(decode);
4020    BSTD_UNUSED(count);
4021    return 0;
4022}
4023
4024bsurface_t bdecode_acquire_capture_buffer(bdecode_t decode, bgraphics_t graphics, bool *top_field)
4025{
4026    bsurface_t surface = NULL;
4027    NEXUS_SurfaceHandle nSurface;
4028
4029#if B_N_GRC
4030    if (decode->nStillDecoder) {
4031        NEXUS_StripedSurfaceHandle stripedSurface;
4032        if (NEXUS_StillDecoder_GetStripedSurface(decode->nStillDecoder, &stripedSurface)) {
4033            return NULL;
4034        }
4035        nSurface = NEXUS_Graphics2D_Destripe(graphics->graphics2d, stripedSurface);
4036    }
4037    else
4038#endif
4039    {
4040        BSTD_UNUSED(graphics);
4041        nSurface = NEXUS_VideoWindow_CaptureVideoBuffer(decode->window->nWindow);
4042    }
4043
4044    if (top_field) *top_field = true; /* TODO */
4045
4046    if (nSurface) {
4047        NEXUS_SurfaceMemory mem;
4048        NEXUS_SurfaceCreateSettings createSettings;
4049
4050        NEXUS_Surface_GetMemory(nSurface, &mem);
4051        NEXUS_Surface_GetCreateSettings(nSurface, &createSettings);
4052
4053        surface = BKNI_Malloc(sizeof(*surface));
4054        BKNI_Memset(surface, 0, sizeof(*surface));
4055        BDBG_OBJECT_SET(surface, bsurface);
4056        surface->graphics = graphics;
4057        surface->nSurface = nSurface;
4058        surface->mem.buffer = mem.buffer;
4059        surface->mem.pitch = mem.pitch;
4060        surface->is_fb = false;
4061        surface->create_settings.pixel_format = bgraphics_pixel_format_y08_cb8_y18_cr8; /* TODO */
4062        surface->create_settings.width = createSettings.width;
4063        surface->create_settings.height = createSettings.height;
4064        surface->settings.position.width = surface->create_settings.width;
4065        surface->settings.position.height = surface->create_settings.height;
4066        surface->settings.position.x = 0;
4067        surface->settings.position.y = 0;
4068        surface->settings.cliprect = surface->settings.position;
4069        surface->settings.zorder = 0;
4070        surface->settings.visible = false;
4071        surface->settings.color = 0xFF000000;
4072        surface->settings.alpha = 0xFF;
4073    }
4074
4075    return surface;
4076}
4077
4078bresult bdecode_release_capture_buffer(bdecode_t decode, bsurface_t surface)
4079{
4080    NEXUS_Error rc;
4081
4082    if (decode->nStillDecoder) {
4083        return BSETTOP_ERROR(berr_invalid_parameter);
4084    }
4085
4086    rc = NEXUS_VideoWindow_ReleaseVideoBuffer(decode->window->nWindow, surface->nSurface);
4087    BKNI_Free(surface);
4088
4089    return rc;
4090}
4091
4092void bdecode_p_enable_audio(bdecode_t decode, bool enabled)
4093{
4094    NEXUS_VideoDecoderSettings nVideoDecoderSettings;
4095    NEXUS_VideoDecoderStatus nVideoDecoderStatus;
4096    NEXUS_Error rc;
4097
4098    BKNI_Memset(&nVideoDecoderSettings,0,sizeof(nVideoDecoderSettings));
4099    BKNI_Memset(&nVideoDecoderStatus,0,sizeof(nVideoDecoderStatus));
4100    if(decode->video_decode && decode->video_decode->nVideoDecoder)
4101    {
4102        rc = NEXUS_VideoDecoder_GetStatus(decode->video_decode->nVideoDecoder,&nVideoDecoderStatus);
4103        if (rc)
4104        {
4105            rc=BERR_TRACE(rc);
4106        }
4107        NEXUS_VideoDecoder_GetSettings(decode->video_decode->nVideoDecoder,&nVideoDecoderSettings);
4108    }
4109
4110    /* Be careful how you use this function.  The asserts do their best to catch errors, but
4111       you must remember to disable only once and enable before leaving the thunk layer */
4112    B_LOCK_ASSERT();
4113    BDBG_MSG(("Checking decode %p started %d audio %p", decode, decode->started, decode->audio_decode));
4114    if ( decode->audio_decode && !decode->audio_decode->busy )
4115    {
4116        if ( enabled )
4117        {
4118            BDBG_ASSERT(true == decode->audio_disabled);
4119            decode->audio_disabled = false;
4120            BDBG_MSG(("ENABLING audio decode %p", decode->audio_decode));
4121            bdecode_start_audio(decode->audio_decode, decode->source, decode->window);
4122#if B_HAS_IP /* restore the threshold */
4123            if(nVideoDecoderSettings.fifoThreshold)
4124                nVideoDecoderSettings.fifoThreshold *=2;
4125#else
4126            nVideoDecoderSettings.fifoThreshold=0;
4127#endif
4128            if(decode->video_decode && decode->video_decode->nVideoDecoder)
4129                NEXUS_VideoDecoder_SetSettings(decode->video_decode->nVideoDecoder,&nVideoDecoderSettings);
4130        }
4131        else
4132        {
4133#if B_HAS_IP /* lower the threshold */
4134            if(nVideoDecoderSettings.fifoThreshold) 
4135            {
4136                nVideoDecoderSettings.fifoThreshold /=2;
4137            }
4138            else if (!decode->source->parser_band && !decode->source->producer.is_playback_ip)
4139            {
4140                /* only do this for the PVR playback case, delayed startup of audio is not a problem for non-playback */
4141                nVideoDecoderSettings.fifoThreshold = nVideoDecoderStatus.fifoDepth/2;
4142            }
4143#else
4144            if(nVideoDecoderSettings.fifoThreshold)
4145            {
4146                BDBG_ERR(("not using default threshold"));
4147            }
4148            if (rc == NEXUS_SUCCESS)
4149            {
4150                nVideoDecoderSettings.fifoThreshold = nVideoDecoderStatus.fifoDepth/2;
4151            }
4152#endif
4153            if(decode->video_decode && decode->video_decode->nVideoDecoder)
4154                NEXUS_VideoDecoder_SetSettings(decode->video_decode->nVideoDecoder,&nVideoDecoderSettings);
4155
4156            decode->audio_disabled = true;  /* MUST SET THIS FIRST */
4157            BDBG_MSG(("DISABLING audio decode %p", decode->audio_decode));
4158            bdecode_stop_audio(decode->audio_decode);
4159        }
4160    }
4161}
4162
4163void bdecode_p_mpeg_change(bdecode_t decode, const bstream_mpeg *new_settings)
4164{
4165    /* TODO: This currently does nothing to the decoder, based on settop api's definition of
4166       bstream_set_mpeg_parameters.  If later on we want the decoder to automatically restart,
4167       that can be done here */
4168    BSTD_UNUSED(decode);
4169    BSTD_UNUSED(new_settings);
4170}
4171
4172#if NEXUS_HAS_SYNC_CHANNEL
4173/* open and sync channel with default settings */
4174static bresult bdecode_p_open_sync_channel(bdecode_t decode)
4175{
4176    NEXUS_Error rc =0;
4177    NEXUS_SyncChannelSettings nSyncChannelSettings;
4178    bsettop_init_settings initSettings;
4179    bsettop_get_init_settings(&initSettings);
4180
4181    switch ( initSettings.lipsync_mode )
4182    {
4183    case bsettop_lipsync_mode_tsm:
4184    case bsettop_lipsync_mode_disabled:
4185        BDBG_WRN(("sync channel disabled"));
4186        return b_ok;
4187    default:
4188        break;
4189    }
4190
4191    BDBG_MSG(("Open sync channel for decode %p",decode));
4192    NEXUS_SyncChannel_GetDefaultSettings(&nSyncChannelSettings);
4193    nSyncChannelSettings.enablePrecisionLipsync = (initSettings.lipsync_mode == bsettop_lipsync_mode_precision)?true:false;
4194    decode->nSyncChannel = NEXUS_SyncChannel_Create(&nSyncChannelSettings);
4195    if (!decode->nSyncChannel) return BSETTOP_ERROR(berr_external_error);
4196    return rc;
4197}
4198
4199/* close sync channel */
4200static bresult bdecode_p_close_sync_channel(bdecode_t decode)
4201{
4202    bresult rc=0;
4203    if(decode->nSyncChannel)
4204    {
4205        NEXUS_SyncChannel_Destroy(decode->nSyncChannel);
4206        decode->nSyncChannel=NULL;
4207    }
4208    return rc;
4209}
4210/* set only the decoders we need */
4211static bresult bdecode_p_set_sync_channel(bdecode_t decode, bool video,bool audio_pcm,bool audio_passthrough)
4212{
4213
4214    NEXUS_Error rc =0;
4215    NEXUS_SyncChannelSettings nSyncChannelSettings;
4216    bsettop_init_settings initSettings;
4217    bsettop_get_init_settings(&initSettings);
4218
4219    switch ( initSettings.lipsync_mode )
4220    {
4221    case bsettop_lipsync_mode_tsm:
4222    case bsettop_lipsync_mode_disabled:
4223        BDBG_MSG(("Skipping sync channel configuration"));
4224        return b_ok;
4225    default:
4226        break;
4227    }
4228
4229    /* sync channnel must be open */
4230    BDBG_ASSERT(decode->nSyncChannel);
4231
4232    BDBG_MSG(("Set sync channel decode %p %s %s %s",decode,video?"video":"",audio_pcm?"pcm":"",audio_passthrough?"passthrough":""));
4233
4234    NEXUS_SyncChannel_GetSettings(decode->nSyncChannel,&nSyncChannelSettings);
4235    if(decode->video_decode && video)
4236            nSyncChannelSettings.videoInput = NEXUS_VideoDecoder_GetConnector(decode->video_decode->nVideoDecoder);
4237    if(decode->audio_decode)
4238    {
4239        if(audio_pcm)
4240            nSyncChannelSettings.audioInput[0] = NEXUS_AudioDecoder_GetConnector(decode->audio_decode->nAudioDecoder, NEXUS_AudioDecoderConnectorType_eStereo);
4241
4242        if(audio_passthrough && (g_audio_passthrough && g_audio_passthrough_owner == decode->audio_decode))
4243                nSyncChannelSettings.audioInput[1] = NEXUS_AudioDecoder_GetConnector(g_audio_passthrough, NEXUS_AudioDecoderConnectorType_eCompressed);
4244     }
4245
4246     rc = NEXUS_SyncChannel_SetSettings(decode->nSyncChannel,&nSyncChannelSettings);
4247     if (rc) return BSETTOP_ERROR(berr_external_error);
4248     return rc;
4249}
4250
4251static bresult bdecode_p_unset_sync_channel(bdecode_t decode,bool video,bool audio_pcm,bool audio_passthrough)
4252{
4253    bresult rc=0;
4254    NEXUS_SyncChannelSettings nSyncChannelSettings;
4255    bsettop_init_settings initSettings;
4256    bsettop_get_init_settings(&initSettings);
4257
4258    switch ( initSettings.lipsync_mode )
4259    {
4260    case bsettop_lipsync_mode_tsm:
4261    case bsettop_lipsync_mode_disabled:
4262        return b_ok;
4263    default:
4264        break;
4265    }
4266
4267    BDBG_MSG(("Unset sync channel decode %p %s %s %s",decode,video?"video":"",audio_pcm?"pcm":"",audio_passthrough?"passthrough":""));
4268
4269    /* sync channnel must be open */
4270    BDBG_ASSERT(decode->nSyncChannel);
4271
4272    if(decode->nSyncChannel)
4273    {
4274        NEXUS_SyncChannel_GetSettings(decode->nSyncChannel,&nSyncChannelSettings);
4275        if(video)
4276            nSyncChannelSettings.videoInput = NULL;
4277        if(audio_pcm)
4278            nSyncChannelSettings.audioInput[0] = NULL;
4279        if(audio_passthrough)
4280            nSyncChannelSettings.audioInput[1] = NULL;
4281        rc = NEXUS_SyncChannel_SetSettings(decode->nSyncChannel,&nSyncChannelSettings);
4282        if (rc) return BSETTOP_ERROR(berr_external_error);
4283
4284    }
4285    return rc;
4286}
4287#else
4288static bresult bdecode_p_open_sync_channel(bdecode_t decode)
4289{
4290    BSTD_UNUSED(decode);
4291    return 0;
4292}
4293static bresult bdecode_p_close_sync_channel(bdecode_t decode)
4294{
4295    BSTD_UNUSED(decode);
4296    return 0;
4297}
4298static bresult bdecode_p_set_sync_channel(bdecode_t decode, bool video,bool audio_pcm,bool audio_passthrough)
4299{
4300    BSTD_UNUSED(decode);
4301    BSTD_UNUSED(video);
4302    BSTD_UNUSED(audio_pcm);
4303    BSTD_UNUSED(audio_passthrough);
4304    return 0;
4305}
4306static bresult bdecode_p_unset_sync_channel(bdecode_t decode,bool video,bool audio_pcm,bool audio_passthrough)
4307{
4308    BSTD_UNUSED(decode);
4309    BSTD_UNUSED(video);
4310    BSTD_UNUSED(audio_pcm);
4311    BSTD_UNUSED(audio_passthrough);
4312    return 0;
4313}
4314#endif
4315
4316#if NEXUS_HAS_ASTM
4317static bresult bdecode_p_open_astm(bdecode_t decode)
4318{
4319    NEXUS_Error rc =0;
4320    NEXUS_AstmSettings nAstmSettings;
4321
4322    if ( !bsettop_get_config("astm_enabled") )
4323    {
4324        BDBG_WRN(("astm not enabled,can be enabled by export astm_enabled=y"));
4325        return b_ok;
4326    }
4327    BDBG_MSG(("Open astm for decode %p",decode));
4328    NEXUS_Astm_GetDefaultSettings(&nAstmSettings);
4329    if (decode->stcChannel)
4330        nAstmSettings.stcChannel = decode->stcChannel;
4331    if (decode->video_decode && decode->video_decode->nVideoDecoder)
4332        nAstmSettings.videoDecoder = decode->video_decode->nVideoDecoder;
4333    if (decode->audio_decode)
4334    {
4335        if (decode->audio_decode->nAudioDecoder)
4336            nAstmSettings.audioDecoder[0]=decode->audio_decode->nAudioDecoder;
4337        if (g_audio_passthrough && g_audio_passthrough_owner == decode->audio_decode)
4338            nAstmSettings.audioDecoder[1]=g_audio_passthrough;
4339    }
4340
4341    /* set STC master */
4342    if(nAstmSettings.videoDecoder && nAstmSettings.audioDecoder[0])
4343    {
4344        nAstmSettings.stcMaster = nAstmSettings.audioDecoder[0]; 
4345    }
4346    else if(nAstmSettings.videoDecoder)
4347    {
4348        nAstmSettings.stcMaster = nAstmSettings.videoDecoder;
4349    }
4350    else if(nAstmSettings.audioDecoder[0])
4351    {
4352        nAstmSettings.stcMaster = nAstmSettings.audioDecoder[0];
4353    }
4354    else if(nAstmSettings.audioDecoder[1])
4355    {
4356        nAstmSettings.stcMaster = nAstmSettings.audioDecoder[1];
4357    }
4358
4359
4360    decode->nAstm  =  NEXUS_Astm_Create(&nAstmSettings);
4361    if (!decode->nAstm) return BSETTOP_ERROR(berr_external_error);
4362    return rc;
4363
4364}
4365static bresult bdecode_p_close_astm(bdecode_t decode)
4366{
4367    bresult rc=0;
4368    if (decode->nAstm)
4369    {
4370        NEXUS_Astm_Destroy(decode->nAstm);
4371        decode->nAstm=NULL;
4372    }
4373    return rc;
4374}
4375
4376static bresult bdecode_p_set_astm(bdecode_t decode, bool video,bool audio_pcm,bool audio_passthrough)
4377{
4378    NEXUS_Error rc =0;
4379    NEXUS_AstmSettings nAstmSettings;
4380
4381    if ( !bsettop_get_config("astm_enabled") )
4382    {
4383        BDBG_MSG(("Skipping astm configuration"));
4384        return b_ok;
4385    }
4386
4387    /* astm channnel must be open */
4388    BDBG_ASSERT(decode->nAstm);
4389
4390    BDBG_MSG(("Set astm decode %p %s %s %s",decode,video?"video":"",audio_pcm?"pcm":"",audio_passthrough?"passthrough":""));
4391
4392    NEXUS_Astm_GetSettings(decode->nAstm,&nAstmSettings);
4393
4394    if (video && decode->video_decode) /* setting video */
4395    {
4396        nAstmSettings.videoDecoder = decode->video_decode->nVideoDecoder;
4397    }
4398   
4399    if (audio_pcm) /* setting audio pcm channel */
4400    {
4401            if (decode->audio_decode)
4402            {
4403                /* if 0 is not pcm ... */
4404                if (nAstmSettings.audioDecoder[0] != decode->audio_decode->nAudioDecoder)
4405                {
4406                        /* ... and it's not NULL ... */
4407                    if (nAstmSettings.audioDecoder[0] != NULL)
4408                    {
4409                        /* ... then it must be passthrough, so move passthrough to 1 because ... */
4410                        nAstmSettings.audioDecoder[1] = nAstmSettings.audioDecoder[0];
4411                    }
4412
4413                    /* pcm is always 0 when set */
4414                    nAstmSettings.audioDecoder[0] = decode->audio_decode->nAudioDecoder;
4415                }
4416        }
4417    }
4418
4419    if (audio_passthrough) /* setting passthrough channel */
4420    {
4421        if (g_audio_passthrough && g_audio_passthrough_owner == decode->audio_decode)
4422        {
4423                /* if 0 is not passthrough ... */
4424                if (nAstmSettings.audioDecoder[0] != g_audio_passthrough)
4425                {
4426                        /* ... and it's not NULL ... */
4427                    if (nAstmSettings.audioDecoder[0] != NULL)
4428                    {
4429                        /* ... then 0 must be pcm, so put passthrough at 1 */
4430                        nAstmSettings.audioDecoder[1] = g_audio_passthrough;
4431                    }
4432                    else
4433                    {
4434                        /* ... otherwise put passthrough at 0 */
4435                            nAstmSettings.audioDecoder[0]=g_audio_passthrough;
4436                            }
4437                        }
4438        }
4439    }
4440   
4441    if(nAstmSettings.videoDecoder && nAstmSettings.audioDecoder[0])
4442    {
4443        BDBG_MSG(("Decode type is %d", decode->cfg_type));
4444        switch (decode->cfg_type)
4445        {
4446            case BDECODE_STC_CHANNEL_CFG_TYPE_PVR_PB:
4447                /* if a/v and playback, prefer VMM */
4448                nAstmSettings.stcMaster = nAstmSettings.videoDecoder; 
4449                break;
4450            default:
4451                /* else prefer AMM */
4452        nAstmSettings.stcMaster = nAstmSettings.audioDecoder[0]; 
4453                break;
4454        }
4455    }
4456    else if(nAstmSettings.videoDecoder)
4457    {
4458        nAstmSettings.stcMaster = nAstmSettings.videoDecoder;
4459    }
4460    else if(nAstmSettings.audioDecoder[0])
4461    {
4462        nAstmSettings.stcMaster = nAstmSettings.audioDecoder[0];
4463    }
4464    else if(nAstmSettings.audioDecoder[1])
4465    {
4466        nAstmSettings.stcMaster = nAstmSettings.audioDecoder[1];
4467    }
4468    else
4469    {
4470        nAstmSettings.stcMaster = NULL;
4471    }
4472
4473    nAstmSettings.enableAutomaticLifecycleControl = false;
4474
4475    rc = NEXUS_Astm_SetSettings(decode->nAstm,&nAstmSettings);
4476    if (rc) return BSETTOP_ERROR(berr_external_error);
4477    return rc;
4478}
4479
4480static bresult bdecode_p_unset_astm(bdecode_t decode,bool video,bool audio_pcm,bool audio_passthrough)
4481{
4482    bresult rc=0;
4483    NEXUS_AstmSettings nAstmSettings;
4484
4485    if ( !bsettop_get_config("astm_enabled") )
4486    {
4487        return b_ok;
4488    }
4489
4490    /* astm must be open */
4491    BDBG_ASSERT(decode->nAstm);
4492    BDBG_MSG(("Unset astm decode %p %s %s %s",decode,video?"video":"",audio_pcm?"pcm":"",audio_passthrough?"passthrough":""));
4493
4494    if (decode->nAstm)
4495    {
4496        NEXUS_Astm_GetSettings(decode->nAstm,&nAstmSettings);
4497        if (video)
4498        {
4499            nAstmSettings.videoDecoder=NULL;
4500        }
4501       
4502        if (audio_pcm)
4503        {
4504            nAstmSettings.audioDecoder[0]=NULL;
4505            /* if pass is still set, move it down to 0 */
4506            if (nAstmSettings.audioDecoder[1])
4507            {
4508                nAstmSettings.audioDecoder[0] = nAstmSettings.audioDecoder[1];
4509                nAstmSettings.audioDecoder[1] = NULL;
4510            }
4511        }
4512       
4513        if (audio_passthrough)
4514        {
4515            if (nAstmSettings.audioDecoder[1])
4516            {
4517                /* pass at 1 */
4518            nAstmSettings.audioDecoder[1]=NULL;
4519            }
4520            else
4521            {
4522                /* pass at 0 */
4523                nAstmSettings.audioDecoder[0] = NULL;
4524            }
4525        }
4526
4527        if (nAstmSettings.videoDecoder && nAstmSettings.audioDecoder[0])
4528        {
4529            BDBG_MSG(("Decode type is %d", decode->cfg_type));
4530            switch (decode->cfg_type)
4531            {
4532                case BDECODE_STC_CHANNEL_CFG_TYPE_PVR_PB:
4533                    /* if a/v and playback, prefer VMM */
4534                    nAstmSettings.stcMaster = nAstmSettings.videoDecoder; 
4535                    break;
4536                default:
4537                    /* else prefer AMM */
4538            nAstmSettings.stcMaster = nAstmSettings.audioDecoder[0]; 
4539                    break;
4540            }
4541        }
4542        else if (nAstmSettings.videoDecoder)
4543        {
4544            nAstmSettings.stcMaster = nAstmSettings.videoDecoder;
4545        }
4546        else if (nAstmSettings.audioDecoder[0])
4547        {
4548            nAstmSettings.stcMaster = nAstmSettings.audioDecoder[0];
4549        }
4550        else if (nAstmSettings.audioDecoder[1])
4551        {
4552            nAstmSettings.stcMaster = nAstmSettings.audioDecoder[1];
4553        }
4554        else
4555        {
4556            nAstmSettings.stcMaster = NULL;
4557        }
4558
4559        rc = NEXUS_Astm_SetSettings(decode->nAstm,&nAstmSettings);
4560        if (rc) return BSETTOP_ERROR(berr_external_error);
4561
4562    }
4563    return rc;
4564
4565}
4566
4567static bresult bdecode_p_start_astm(bdecode_t decode)
4568{
4569    NEXUS_Error rc =0;
4570
4571    if ( !bsettop_get_config("astm_enabled") )
4572    {
4573        BDBG_MSG(("Skipping astm start"));
4574        return b_ok;
4575    }
4576
4577    /* astm channnel must be open */
4578    BDBG_ASSERT(decode->nAstm);
4579
4580    BDBG_MSG(("Start astm decode %p",decode));
4581
4582    rc = NEXUS_Astm_Start(decode->nAstm);
4583    if (rc) return BSETTOP_ERROR(berr_external_error);
4584
4585    return rc;
4586}
4587
4588static bresult bdecode_p_stop_astm(bdecode_t decode)
4589{
4590    bresult rc =0;
4591
4592    if ( !bsettop_get_config("astm_enabled") )
4593    {
4594        BDBG_MSG(("Skipping astm stop"));
4595        return b_ok;
4596    }
4597
4598    /* astm channnel must be open */
4599    BDBG_ASSERT(decode->nAstm);
4600
4601    BDBG_MSG(("Stop astm decode %p",decode));
4602
4603    NEXUS_Astm_Stop(decode->nAstm);
4604
4605    return rc;
4606}
4607
4608#else
4609static bresult bdecode_p_open_astm(bdecode_t decode)
4610{
4611     BSTD_UNUSED(decode);
4612    return 0;
4613}
4614static bresult bdecode_p_close_astm(bdecode_t decode)
4615{
4616    BSTD_UNUSED(decode);
4617    return 0;
4618}
4619
4620static bresult bdecode_p_set_astm(bdecode_t decode, bool video,bool audio_pcm,bool audio_passthrough)
4621{
4622    BSTD_UNUSED(decode);
4623    BSTD_UNUSED(video);
4624    BSTD_UNUSED(audio_pcm);
4625    BSTD_UNUSED(audio_passthrough);
4626    return 0;
4627}
4628static bresult bdecode_p_unset_astm(bdecode_t decode,bool video,bool audio_pcm,bool audio_passthrough)
4629{
4630    BSTD_UNUSED(decode);
4631    BSTD_UNUSED(video);
4632    BSTD_UNUSED(audio_pcm);
4633    BSTD_UNUSED(audio_passthrough);
4634    return 0;
4635}
4636
4637static bresult bdecode_p_start_astm(bdecode_t decode)
4638    {
4639     BSTD_UNUSED(decode);
4640    return 0;
4641}
4642
4643static bresult bdecode_p_stop_astm(bdecode_t decode)
4644    {
4645    BSTD_UNUSED(decode);
4646    return 0;
4647}
4648#endif
4649
4650static NEXUS_AudioDecoderDolbyDrcMode baudio_dolby_drc_mode_to_nexus_ac3plus_comp_mode(baudio_dolby_drc_mode drc_mode)
4651{
4652    NEXUS_AudioDecoderDolbyDrcMode eCompMode;
4653   
4654    switch (drc_mode)
4655    {
4656        case baudio_dolby_drc_mode_rf:
4657       
4658            eCompMode = NEXUS_AudioDecoderDolbyDrcMode_eRf;
4659            break;
4660
4661        case baudio_dolby_drc_mode_line:
4662        default:
4663       
4664            eCompMode = NEXUS_AudioDecoderDolbyDrcMode_eLine;
4665            break;
4666    }
4667
4668    return eCompMode;
4669}
4670
4671static NEXUS_AudioDecoderDolbyStereoDownmixMode baudio_dolby_stereo_downmix_mode_to_nexus_ac3plus_stereo_mode(baudio_dolby_stereo_downmix_mode stereo_downmix_mode)
4672{
4673    NEXUS_AudioDecoderDolbyStereoDownmixMode eStereoMode;
4674   
4675    switch (stereo_downmix_mode)
4676    {
4677        case baudio_dolby_stereo_downmix_mode_automatic:
4678       
4679            eStereoMode = NEXUS_AudioDecoderDolbyStereoDownmixMode_eAutomatic;
4680            break;
4681
4682        case baudio_dolby_stereo_downmix_mode_dolby_surround_compatible:
4683       
4684            eStereoMode = NEXUS_AudioDecoderDolbyStereoDownmixMode_eDolbySurroundCompatible;
4685            break;
4686
4687        case baudio_dolby_stereo_downmix_mode_standard:
4688        default:
4689       
4690            eStereoMode = NEXUS_AudioDecoderDolbyStereoDownmixMode_eStandard;
4691            break;
4692    }
4693
4694    return eStereoMode;
4695}
Note: See TracBrowser for help on using the repository browser.