source: svn/trunk/newcon3bcm2_21bu/nexus/modules/playback/src/nexus_playback_trick.c

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

first commit

  • Property svn:executable set to *
File size: 38.6 KB
Line 
1/***************************************************************************
2 *     (c)2007-2011 Broadcom Corporation
3 *
4 *  This program is the proprietary software of Broadcom Corporation and/or its licensors,
5 *  and may only be used, duplicated, modified or distributed pursuant to the terms and
6 *  conditions of a separate, written license agreement executed between you and Broadcom
7 *  (an "Authorized License").  Except as set forth in an Authorized License, Broadcom grants
8 *  no license (express or implied), right to use, or waiver of any kind with respect to the
9 *  Software, and Broadcom expressly reserves all rights in and to the Software and all
10 *  intellectual property rights therein.  IF YOU HAVE NO AUTHORIZED LICENSE, THEN YOU
11 *  HAVE NO RIGHT TO USE THIS SOFTWARE IN ANY WAY, AND SHOULD IMMEDIATELY
12 *  NOTIFY BROADCOM AND DISCONTINUE ALL USE OF THE SOFTWARE.
13 *
14 *  Except as expressly set forth in the Authorized License,
15 *
16 *  1.     This program, including its structure, sequence and organization, constitutes the valuable trade
17 *  secrets of Broadcom, and you shall use all reasonable efforts to protect the confidentiality thereof,
18 *  and to use this information only in connection with your use of Broadcom integrated circuit products.
19 *
20 *  2.     TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS"
21 *  AND WITH ALL FAULTS AND BROADCOM MAKES NO PROMISES, REPRESENTATIONS OR
22 *  WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT TO
23 *  THE SOFTWARE.  BROADCOM SPECIFICALLY DISCLAIMS ANY AND ALL IMPLIED WARRANTIES
24 *  OF TITLE, MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR PURPOSE,
25 *  LACK OF VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT, QUIET POSSESSION
26 *  OR CORRESPONDENCE TO DESCRIPTION. YOU ASSUME THE ENTIRE RISK ARISING OUT OF
27 *  USE OR PERFORMANCE OF THE SOFTWARE.
28 *
29 *  3.     TO THE MAXIMUM EXTENT PERMITTED BY LAW, IN NO EVENT SHALL BROADCOM OR ITS
30 *  LICENSORS BE LIABLE FOR (i) CONSEQUENTIAL, INCIDENTAL, SPECIAL, INDIRECT, OR
31 *  EXEMPLARY DAMAGES WHATSOEVER ARISING OUT OF OR IN ANY WAY RELATING TO YOUR
32 *  USE OF OR INABILITY TO USE THE SOFTWARE EVEN IF BROADCOM HAS BEEN ADVISED OF
33 *  THE POSSIBILITY OF SUCH DAMAGES; OR (ii) ANY AMOUNT IN EXCESS OF THE AMOUNT
34 *  ACTUALLY PAID FOR THE SOFTWARE ITSELF OR U.S. $1, WHICHEVER IS GREATER. THESE
35 *  LIMITATIONS SHALL APPLY NOTWITHSTANDING ANY FAILURE OF ESSENTIAL PURPOSE OF
36 *  ANY LIMITED REMEDY.
37 *
38 * $brcm_Workfile: nexus_playback_trick.c $
39 * $brcm_Revision: 62 $
40 * $brcm_Date: 11/4/11 1:46p $
41 *
42 * Module Description:
43 *
44 * Revision History:
45 *
46 * $brcm_Log: /nexus/modules/playback/src/nexus_playback_trick.c $
47 *
48 * 62   11/4/11 1:46p jgarrett
49 * SW7344-221: Resetting audio mute when leaving pause for another trick
50 *  mode
51 *
52 * 61   11/4/11 1:07p erickson
53 * SW7231-442: audio trick state must be applied to all decoders
54 *  associated with a pid channel
55 *
56 * 60   9/30/11 9:09a erickson
57 * SW7405-5059: set decoder trick, then STC trick. allows STC trick to
58 *  correctly verify decoder's TSM state.
59 *
60 * 59   9/29/11 3:29p ahulse
61 * SW7425-1297: accurate calc of stc trick rate, mute doen by audio
62 *  decoder
63 *
64 * 58   9/27/11 4:42p vsilyaev
65 * SW7420-1965: Fixed code to fetch the audio decoder state
66 *
67 * 57   9/22/11 4:43p erickson
68 * SW7420-1965: add simple decoder support to nexus playback module
69 *
70 * 56   9/7/11 11:41a erickson
71 * SW7405-5059: fail stc trick if any decoder not in TSM mode
72 *
73 * 55   8/29/11 10:33a erickson
74 * SW7425-1205: clarify trick DBG
75 *
76 * 54   5/24/11 4:53p vsilyaev
77 * SWDTV-7161: Properly adjust the decoder_rate prior to applying STC rate
78 *
79 * 53   5/13/11 5:12p erickson
80 * SW7125-823: add support for decoder-less host trick modes with
81 *  nexus_playback
82 *
83 * 52   4/18/11 4:56p dlwin
84 * SW7425-200: Fixed STC Trickmode, transition from Pause->HostPaced
85 *  trickmode caused frozen video.
86 *
87 * 51   3/29/11 2:49p vsilyaev
88 * SW7335-1214: Remove manual ModuleLock/Unlock
89 *
90 * 50   3/28/11 3:45p vsilyaev
91 * SW7335-1214: Added NEXUS_CallbackHandler framework
92 *
93 * 49   2/10/11 5:14p erickson
94 * SW7405-5059: only fail stc trick modes on ES streams when trick mode
95 *  invoked
96 *
97 * 48   2/7/11 10:16a erickson
98 * SW7405-5059: fail stc trick modes on ES streams
99 *
100 * 46   11/12/10 6:35p dlwin
101 * SW35230-2135: Added code invalidate the STC channel on transition
102 *  between non-STC trick modes.
103 *
104 * 45   9/28/10 1:57p erickson
105 * SWDEPRECATED-1003: pass force source frame rate from media framework to
106 *  VideoDecoder
107 *
108 * 44   8/17/10 12:24p erickson
109 * SW3548-3051: add warning if trick mode performed with missing decoder
110 *  handle
111 *
112 * 43   7/20/10 4:03p vsilyaev
113 * SW7400-2853: Removed test that blocks decoder based fast forward
114 *
115 * 42   6/29/10 3:20p erickson
116 * SW7405-4367: playback should flush when transitioning decoder skip
117 *  modes. also added NEXUS_PlaybackTrickModeSettings.avoidFlush option to
118 *  disable this behavior.
119 *
120 * 41   6/11/10 5:39p vsilyaev
121 * SW3556-1123: Fixed warning
122 *
123 * 40   6/11/10 4:57p vsilyaev
124 * SW3556-1123: use topFieldOnly mode when using host paced mode
125 *
126 * 39   3/26/10 1:00p vsilyaev
127 * SW7550-349: Use offsetThreshold to guarantee STC update
128 *
129 * 38   12/3/09 11:18a mward
130 * SW7125-58: SW7342-64: No longer mute audio with 0.8, 1.2x trick modes
131 *  for 7125, 7342 RAP supports now DSOLA.
132 *
133 * 37   11/5/09 2:31p mward
134 * SW7125-58: SW7342-64: Mute audio with 0.8, 1.2x trick modes for 7125,
135 *  7342 until RAP supports DSOLA.
136 *
137 * 36   8/10/09 3:36p ahulse
138 * PR56762: firstPts/Passed callbacks not registered in settop API mode,
139 *  move registration into b_play_trick_set_pid
140 *
141 * 35   7/31/09 4:25p erickson
142 * PR57235: rename Settop API names, remove unused code
143 *
144 * 34   7/21/09 5:57p vsilyaev
145 * PR 56977: Nexus playback always control audio and video decoder.
146 *  Provided way for the user to control the decoder slowmotion factor
147 *  using the playback trick API.
148 *
149 * 33   7/8/09 11:59a vsilyaev
150 * PR 55989: Added support for OTF trickmodes
151 *
152 * 32   6/19/09 4:11p vsilyaev
153 * PR 56169: PR 53824: Allow user to sepcify max decodder rate. This
154 *  superceeds overrideStcTrick.
155 *
156 * 31   3/6/09 1:58p erickson
157 * PR52891: don't call decoders SetTrickState functions when they are not
158 *  started
159 *
160 * 30   3/5/09 5:58p vsilyaev
161 * PR 52171: Use special sequence to get the video PTS (b_play_getpts
162 *  could return either audio or video PTS)
163 *
164 * 29   2/26/09 9:03a erickson
165 * PR52099: block all TrickState calls to AudioDecoder and VideoDecoder if
166 *  NEXUS_PlaybackHostTrickMode_eNormal is set. also removed some old,
167 *  unused code.
168 *
169 * 28   2/25/09 11:19a katrep
170 * PR52099: Need to take into account decoder trick modes. Audio needs to
171 *  be muted.
172 *
173 * 27   2/18/09 4:43p katrep
174 * PR51989: Fiorcing strict error check,reverting previous checkin. If
175 *  audio decode has an error dont allow playback to continue.
176 *
177 * 26   2/10/09 12:00p katrep
178 * PR51989: Do not stop video playback if audio decode fails for any
179 *  reason.
180 *
181 * 25   1/27/09 4:04p erickson
182 * PR51377: NEXUS_Playback_Start or NEXUS_Playback_OpenPidChannel should
183 *  reset VideoDecoder's trick state
184 *
185 * 24   1/26/09 11:38a vsilyaev
186 * PR 51579: Added ES to PES packetization and support for capturing of
187 *  streams produced by the playback module
188 *
189 * 23   1/9/09 4:53p jgarrett
190 * PR 49714: Fixing audio STC pause
191 *
192 * 22   1/9/09 1:55a erickson
193 * PR49294: clean up WRN message
194 *
195 * 21   12/18/08 3:43p erickson
196 * PR49605: fix playpump rate when leaving host paced trick mode to 1.2x
197 *
198 * 20   12/18/08 3:25p erickson
199 * PR50541: fix vdecState.hostTrickModesEnabled assignment
200 *
201 * 19   12/16/08 7:09a erickson
202 * PR49930: init everything in b_play_trick_init
203 *
204 * 18   12/10/08 11:05a erickson
205 * PR49930: added NEXUS_Playback_AccurateSeekInProcess test api, added
206 *  required flush before calling NEXUS_VideoDecoder_SetStartPts
207 *
208 * 17   11/19/08 1:30p erickson
209 * PR47758: NEXUS_VideoDecoder_GetNextPts may fail on transitions. don't
210 *  propogate failure to app. next call should work.
211 *
212 * 16   10/23/08 4:21p jtna
213 * PR47758: NEXUS_VideoDecoder_GetNextPts() now returns nextPTS, not PTS
214 *  increment
215 *
216 * 15   10/16/08 3:38p erickson
217 * PR47673: mute decoder for STC trick modes other than 0.8 and 1.2
218 *
219 * 14   10/14/08 3:36p erickson
220 * PR47407: reapply audio decoder trick mode settings when pid channel is
221 *  opened or set
222 *
223 * 13   10/13/08 10:44a erickson
224 * PR47572: downgrade DBG to MSG
225 *
226 * 12   10/9/08 5:30p erickson
227 * PR47758: added temp workaround. also added one more stc trick state
228 *  fix.
229 *
230 * 11   10/9/08 5:19p erickson
231 * PR47608: must set decoder trick state even when in stc trick mode
232 *
233 * 10   10/9/08 2:54p erickson
234 * PR47608: move location of stcChannel test
235 *
236 * 9   10/9/08 2:23p erickson
237 * PR47608: NEXUS_PlaybackSettings.stcChannel is now required for TSM
238 *  playback. NEXUS_PlaybackSettings.stcTrick was added for stc trick
239 *  modes.
240 *
241 * 8   10/6/08 11:48a gmohile
242 * PR 47608 : Invalidate STC channel during flush
243 *
244 * 7   10/1/08 4:43p jtna
245 * PR37222: Use NEXUS_VideoDecoder_GetNextPts for STC trickmode frame
246 *  advance
247 *
248 * 6   9/23/08 7:16p katrep
249 * PR45880: Fixed 80% STC increment/prescal ratio for correct 80% STC
250 *  clock
251 *
252 * 5   9/18/08 6:28p katrep
253 * PR45880: Add support for FSPB(80/120 playback)
254 *
255 * 4   5/30/08 2:56p erickson
256 * PR43000: improve BDBG_MSG
257 *
258 * 3   5/22/08 8:28p jgarrett
259 * PR 42974: Adding audio mute flag
260 *
261 * 2   5/5/08 4:46p vsilyaev
262 * PR 42355: Fixed rewind for AVI files
263 *
264 * 1   1/18/08 2:36p jgarrett
265 * PR 38808: Merging to main branch
266 *
267 * Nexus_Devel/15   1/8/08 2:23p vsilyaev
268 * PR 35824: Fixed resync on transition between modes
269 *
270 * Nexus_Devel/14   12/20/07 5:24p vsilyaev
271 * PR 38073: Improved handling of trickmodes
272 *
273 * Nexus_Devel/13   12/20/07 3:41p vsilyaev
274 * PR 38073: Improving use of bmedia_player
275 *
276 * Nexus_Devel/12   12/20/07 10:29a vsilyaev
277 * PR 38073: Updated to work with new bmedia_player
278 *
279 * Nexus_Devel/PR38073/1   12/19/07 5:01p vsilyaev
280 * PR 38073: Moved time tracking code for host paced mode into the
281 * bmedia_player
282 *
283 * Nexus_Devel/11   12/4/07 2:12p vsilyaev
284 * PR 36404: Use structure to conrol audio trickmodes
285 *
286 * Nexus_Devel/10   12/4/07 10:23a erickson
287 * PR35825: fix warning
288 *
289 * Nexus_Devel/9   12/3/07 4:42p erickson
290 * PR35825: restore normal rate STC on shutdown. keep video_decoder in TSM
291 * when doing STC trick modes
292 *
293 * Nexus_Devel/8   11/16/07 12:38p vsilyaev
294 * PR 35824: Added STC trickmodes
295 *
296 * Nexus_Devel/7   10/30/07 5:05p vsilyaev
297 * PR 36404: Added audio tracking for slow motion modes
298 *
299 * Nexus_Devel/6   10/24/07 5:40p vsilyaev
300 * PR 36404: Added audio decode trick mode
301 *
302 * Nexus_Devel/5   10/24/07 1:19p vsilyaev
303 * PR 36404: Added audio flush
304 *
305 * Nexus_Devel/4   10/19/07 11:21a vsilyaev
306 * PR 35824: Fixed data corruption on trick modes
307 *
308 * Nexus_Devel/3   10/17/07 5:38p vsilyaev
309 * PR 35824: Added trickmode test
310 *
311 * Nexus_Devel/2   10/17/07 1:05p vsilyaev
312 * PR 35824: Added playpump_trick
313 *
314 * Nexus_Devel/1   10/16/07 12:56p vsilyaev
315 * PR 35824: Splitting playback into managable piexies
316 *
317 * $copied_brcm_Log: /BSEAV/api/src/pvr/bsettop_playback.c $
318 * $copied_brcm_Revision: 172 $
319 * $copied_brcm_Date: 10/1/07 11:13a $
320 *
321 * $copied_brcm_Log: /BSEAV/api/src/7401/bsettop_playpump_trick.c $
322 * $copied_brcm_Revision: 19 $
323 * $copied_brcm_Date: 9/17/07 9:15a $
324 **************************************************************************/
325#include "nexus_playback_module.h"
326#include "nexus_playback_impl.h"
327#include "nexus_audio_decoder_trick.h"
328
329BDBG_MODULE(nexus_playback_trick);
330
331static void
332b_play_trick_monitor(void *p_)
333{
334    NEXUS_PlaybackHandle p = p_;
335    BERR_Code rc;
336    uint32_t video_pts;
337    const NEXUS_Playback_P_PidChannel *pid;
338    const NEXUS_Playback_P_PidChannel *decode;
339    NEXUS_VideoDecoderStatus status;
340
341    BDBG_OBJECT_ASSERT(p, NEXUS_Playback);
342    p->trick.rap_monitor_timer = NULL;
343   
344    decode = b_play_get_video_decoder(p);
345    if(!decode) { goto done; }
346    rc = NEXUS_P_Playback_VideoDecoder_GetStatus(decode, &status);
347    if(rc!=NEXUS_SUCCESS) {goto done;}
348    if(status.ptsType == NEXUS_PtsType_eCoded || status.ptsType == NEXUS_PtsType_eInterpolatedFromValidPTS || p->params.playpumpSettings.transportType==NEXUS_TransportType_eEs) {
349        video_pts = status.pts;
350    } else {goto done; }
351    BDBG_MSG(("b_play_trick_monitor: %#x, video pts %#x", (unsigned)p, video_pts));
352
353    for(pid = BLST_S_FIRST(&p->pid_list); pid ; pid = BLST_S_NEXT(pid, link)) {
354        if(pid->cfg.pidSettings.pidType==NEXUS_PidType_eAudio) {
355            rc = NEXUS_Playback_P_AudioDecoder_Advance(pid, video_pts);
356            if(rc!=BERR_SUCCESS) {rc=BERR_TRACE(rc);}
357        }
358    }
359
360done: /* keep going anyway */
361    p->trick.rap_monitor_timer = NEXUS_ScheduleTimer(100, b_play_trick_monitor, p);
362    return;
363}
364
365void
366b_play_flush(NEXUS_PlaybackHandle playback)
367{
368    NEXUS_Error rc;
369    const NEXUS_Playback_P_PidChannel *pid;
370
371    BDBG_MSG(("b_play_flush:> %#lx", (unsigned long)playback));
372
373    playback->state.decoder_flushed = true;
374    BDBG_ASSERT(playback->params.playpump);
375    rc = NEXUS_Playpump_Flush(playback->params.playpump);
376    if(rc!=NEXUS_SUCCESS) {rc = BERR_TRACE(rc);}
377
378    if(playback->params.stcChannel) {
379        rc = NEXUS_StcChannel_Invalidate(playback->params.stcChannel);
380        if(rc!=NEXUS_SUCCESS) { rc = BERR_TRACE(rc);}
381    }
382
383    for(pid = BLST_S_FIRST(&playback->pid_list); pid ; pid = BLST_S_NEXT(pid, link)) {
384        switch(pid->cfg.pidSettings.pidType) {
385        default: break;
386        case NEXUS_PidType_eVideo: NEXUS_P_Playback_VideoDecoder_Flush(pid); break;
387        case NEXUS_PidType_eAudio: NEXUS_P_Playback_AudioDecoder_Flush(pid); break;
388        }
389    }
390#if B_PLAYBACK_CAPTURE
391    if(playback->capture.has_data) {
392        b_play_capture_close(playback);
393        b_play_capture_open(playback);
394    }
395#endif
396
397    BDBG_MSG(("b_play_flush:< %#lx", (unsigned long)playback));
398    return;
399}
400
401void
402b_play_trick_init(NEXUS_PlaybackHandle p)
403{
404    BKNI_Memset(&p->trick.settings, 0, sizeof(p->trick.settings));
405    p->trick.settings.state = b_trick_state_normal;
406    p->trick.settings.forward = true;
407    p->trick.settings.decode_rate = NEXUS_NORMAL_PLAY_SPEED;
408    p->trick.settings.decode_mode = NEXUS_VideoDecoderDecodeMode_eAll;
409    p->trick.settings.fragmented = false;
410    p->trick.settings.reordering_mode = NEXUS_VideoDecoderReorderingMode_eNone;
411    p->trick.rap_monitor_timer = NULL;
412    return;
413}
414
415void
416b_play_trick_shutdown(NEXUS_PlaybackHandle p)
417{
418    if (p->trick.rap_monitor_timer) {
419        NEXUS_CancelTimer(p->trick.rap_monitor_timer);
420        p->trick.rap_monitor_timer = NULL;
421    }
422
423    /* normal rate STC */
424    if (p->params.stcChannel) {
425        NEXUS_StcChannel_SetRate(p->params.stcChannel, 1, 0 /* HW adds one */ );
426    }
427    return;
428}
429
430void
431b_play_trick_get(NEXUS_PlaybackHandle p, b_trick_settings *cfg)
432{
433    BDBG_OBJECT_ASSERT(p, NEXUS_Playback);
434    *cfg = p->trick.settings;
435}
436
437static NEXUS_Error
438b_play_trick_set_each_audio(NEXUS_PlaybackHandle p, const NEXUS_Playback_P_PidChannel *pid, const b_trick_settings *settings)
439{
440    NEXUS_Error rc;
441    NEXUS_AudioDecoderTrickState audioState;
442    NEXUS_AudioDecoderStatus status;
443
444    rc = NEXUS_P_Playback_AudioDecoder_GetStatus(pid, &status);
445    if (rc) return BERR_TRACE(rc);
446    if (!status.started) {
447        BDBG_MSG(("Playback unable to set AudioDecoder trick state because it has not been started. Playback will continue, but you may not get desired results."));
448        /* TODO: consider a callback from VideoDecoder to apply Playback's trick state when it is started */
449        return 0;
450    }
451
452    NEXUS_P_Playback_AudioDecoder_GetTrickState(pid, &audioState);
453
454    if(!settings->stc_trick) {
455        /* decoder trick modes */
456        if(settings->decode_rate < NEXUS_NORMAL_PLAY_SPEED) {
457            audioState.rate = 0;
458        }
459        else {
460            audioState.rate = settings->decode_rate;
461        }
462    }
463    else {
464        /* stc trick modes */
465        if (settings->decode_rate != 0) {
466            /* for non-0, we pass down the rate for DSOLA trick modes. */
467            audioState.rate = settings->decode_rate;
468        }
469        else {
470            /* if 0, just do an STC pause, no RAP pause. but we also have to return to mute. */
471            audioState.rate = NEXUS_NORMAL_PLAY_SPEED;
472        }
473    }
474    if (settings->audio_only_pause) {
475        audioState.rate = 0;
476    }
477
478    audioState.forceStopped = settings->state != b_trick_state_normal;
479    if(settings->decode_mode!=NEXUS_VideoDecoderDecodeMode_eAll) {
480        audioState.forceStopped = true;
481    }
482
483    if(audioState.forceStopped) {
484        audioState.rate = NEXUS_NORMAL_PLAY_SPEED;
485    }
486
487    /* mute for stc based pause */
488    if ((settings->stc_trick && settings->decode_rate == 0)) {
489        audioState.muted = true;
490    }
491    else {
492        audioState.muted = false;
493    }
494
495    BDBG_MSG(("audio trick muted=%d, rate=%d", audioState.muted, audioState.rate));
496
497    rc = NEXUS_P_Playback_AudioDecoder_SetTrickState(pid, &audioState);
498    if(rc!=NEXUS_SUCCESS) { rc = BERR_TRACE(rc); goto error;}
499
500    if((audioState.rate==0 || settings->audio_only_pause) && !settings->stc_trick) {
501        if(!p->trick.rap_monitor_timer) {
502            p->trick.rap_monitor_timer = NEXUS_ScheduleTimer(100, b_play_trick_monitor, p);
503        }
504    } else {
505        if (p->trick.rap_monitor_timer) {
506            NEXUS_CancelTimer(p->trick.rap_monitor_timer);
507            p->trick.rap_monitor_timer = NULL;
508        }
509    }
510
511    return NEXUS_SUCCESS;
512
513error:
514    return rc;
515}
516
517void NEXUS_Playback_P_VideoDecoderFirstPts(void *context)
518{
519    NEXUS_PlaybackHandle playback = context;
520
521    BDBG_OBJECT_ASSERT(playback, NEXUS_Playback);
522
523    if (playback->state.inAccurateSeek) {
524        b_trick_settings settings;
525        /* video has found its first pts, so now audio can chase */
526        /* NOTE: Due to XVD callback order, FirstPtsPassed cback can occur before FirstPts */
527        /*       So check if we are in audio pause mode */
528        b_play_trick_get(playback, &settings);
529        if( settings.audio_only_pause ) {
530           /* We got FirstPtsPassed first ! */
531           settings.audio_only_pause = false;
532           b_play_trick_set(playback, &settings);
533           playback->state.inAccurateSeek = false;
534           BDBG_WRN(("accurate seek: first pts passed, audio seek done FirstPts"));
535        }
536        else {
537            BDBG_WRN(("accurate seek: first pts, starting audio seek FirstPts"));
538            settings.audio_only_pause = true;
539        }
540        b_play_trick_set(playback, &settings);
541    }
542    return;
543}
544
545void NEXUS_Playback_P_VideoDecoderFirstPtsPassed(void *context)
546{
547    NEXUS_PlaybackHandle playback = context;
548
549    BDBG_OBJECT_ASSERT(playback, NEXUS_Playback);
550
551    if (playback->state.inAccurateSeek) {
552        b_trick_settings settings;
553        b_play_trick_get(playback, &settings);
554        if( settings.audio_only_pause ) {
555            /* we're done. video has arrived. now audio can start. */
556            settings.audio_only_pause = false;
557            b_play_trick_set(playback, &settings);
558            playback->state.inAccurateSeek = false;
559            BDBG_WRN(("accurate seek: first pts passed, audio seek done PtsPassed"));
560        }
561        else {
562            BDBG_WRN(("accurate seek: first pts, starting audio seek PtsPassed"));
563            settings.audio_only_pause = true;
564            b_play_trick_set(playback, &settings);
565        }
566    }
567    return;
568}
569
570NEXUS_Error
571b_play_trick_set_pid(NEXUS_PlaybackHandle p, const NEXUS_Playback_P_PidChannel *pid, const b_trick_settings *settings)
572{
573    NEXUS_Error rc;
574    bool slowMotion;
575
576    if (!settings) {
577        /* reapply previous settings */
578        settings = &p->trick.settings;
579    }
580
581    switch (pid->cfg.pidSettings.pidType) {
582    case NEXUS_PidType_eVideo:
583        {
584        NEXUS_VideoDecoderTrickState vdecState;
585        NEXUS_VideoDecoderStatus status;
586        NEXUS_VideoDecoderPlaybackSettings playbackSettings;
587
588        if (!pid->cfg.pidTypeSettings.video.decoder && !pid->cfg.pidTypeSettings.video.simpleDecoder) {
589            /* no decoder can be normal. already checked at NEXUS_Playback_TrickMode. */
590            return 0;
591        }
592
593        NEXUS_P_Playback_VideoDecoder_GetPlaybackSettings(pid, &playbackSettings);
594        if( playbackSettings.firstPts.callback == NULL ) {
595            NEXUS_CallbackHandler_PrepareCallback(p->videoDecoderFirstPts, playbackSettings.firstPts);
596            NEXUS_CallbackHandler_PrepareCallback(p->videoDecoderFirstPtsPassed, playbackSettings.firstPtsPassed);
597            rc = NEXUS_P_Playback_VideoDecoder_SetPlaybackSettings(pid, &playbackSettings);
598            if (rc) return BERR_TRACE(rc);
599        }
600
601        rc = NEXUS_P_Playback_VideoDecoder_GetStatus(pid, &status);
602        if (rc) return BERR_TRACE(rc);
603        if (status.tsm && !p->params.stcChannel && pid->cfg.pidTypeSettings.video.decoder) {
604            /* This was a recent change. Apps must be fixed. Without this, certain trick mode transitions will fail
605            because Playback will be unable to invalidate the STC. */
606            BDBG_ERR(("Playback with TSM requires NEXUS_PlaybackSettings.stcChannel."));
607            return BERR_TRACE(NEXUS_UNKNOWN);
608        }
609        if (!status.started) {
610            BDBG_MSG(("Playback unable to set VideoDecoder trick state because it has not been started. Playback will continue, but you may not get desired results."));
611            /* TODO: consider a callback from VideoDecoder to apply Playback's trick state when it is started */
612            return 0;
613        }
614
615        NEXUS_P_Playback_VideoDecoder_GetTrickState(pid, &vdecState);
616        if((settings->decode_rate!=0 && settings->state == b_trick_state_host_paced) || (settings->stc_trick && settings->state == b_trick_state_normal)) {
617            vdecState.rate = NEXUS_NORMAL_PLAY_SPEED;
618        } else {
619            vdecState.rate = settings->decode_rate;
620        }
621        vdecState.reorderingMode = settings->reordering_mode;
622        vdecState.decodeMode = settings->decode_mode;
623        vdecState.brcmTrickModesEnabled = settings->state == b_trick_state_brcm_trick_mode;
624        vdecState.hostTrickModesEnabled = settings->state == b_trick_state_host_paced || settings->state == b_trick_state_host_trick_mode;
625        vdecState.dqtEnabled = settings->state == b_trick_state_display_queue_trick_mode;
626        slowMotion = (-NEXUS_NORMAL_PLAY_SPEED < (int)settings->decode_rate && settings->decode_rate < NEXUS_NORMAL_PLAY_SPEED);
627        vdecState.topFieldOnly = slowMotion || settings->state == b_trick_state_host_paced; /* show only top field if decoder expected to repeat frames, this is for slow motion or when using host paced trickmodes */
628        vdecState.reverseFields = !settings->forward;
629        vdecState.tsmEnabled = (settings->decode_rate!=0 && settings->state == b_trick_state_host_paced) ||
630            (settings->state == b_trick_state_normal &&
631             ((settings->decode_rate >= NEXUS_NORMAL_PLAY_SPEED && settings->decode_mode==NEXUS_VideoDecoderDecodeMode_eAll)
632              || settings->stc_trick)
633            );
634        vdecState.forceSourceFrameRate = settings->force_source_frame_rate;
635        BDBG_MSG(("calling NEXUS_VideoDecoder_SetTrickState: rate=%d %s %s %s %s %s %s %s", (int)vdecState.rate, B_DECODE_MODE_STR(vdecState.decodeMode), 
636            vdecState.brcmTrickModesEnabled?"brcm-trick":"", vdecState.hostTrickModesEnabled?"host-trick":"", vdecState.dqtEnabled?"dqt":"", 
637            vdecState.topFieldOnly?"top-field-only":"", vdecState.reverseFields?"reverse-field":"", vdecState.tsmEnabled?"tsm":"vsync"));
638        rc = NEXUS_P_Playback_VideoDecoder_SetTrickState(pid, &vdecState);
639        if (rc) return BERR_TRACE(rc);
640        }
641        break;
642
643    case NEXUS_PidType_eAudio:
644        rc = b_play_trick_set_each_audio(p, pid, settings);
645        if (rc)  return BERR_TRACE(rc);
646        break;
647
648    default:
649        break;
650    }
651
652    return 0;
653}
654
655static void remove_common_factors(unsigned val1, unsigned val2, unsigned *pResult1, unsigned *pResult2)
656{
657    static const unsigned factors[] = {5, 3};
658    static const unsigned numFactors = sizeof(factors)/sizeof(unsigned);
659    unsigned factor, index;
660
661    /* Remove factors of 2 first to use AND/shift operations instead of div/mod */
662    while ( val1 >= 2 && val2 >= 2 )
663    {
664        if ( (val1 & 1) || (val2 & 1) )
665        {
666            break;
667        }
668
669        val1 >>= 1;
670        val2 >>= 1;
671    }
672
673    /* Now go through remaining factors */
674    for ( index = 0; index < numFactors; index++ )
675    {
676        factor = factors[index];
677        while ( val1 >= factor && val2 >= factor )
678        {
679            if ( (val1 % factor) || (val2 % factor) )
680            {
681                break;
682            }
683
684            val1 /= factor;
685            val2 /= factor;
686        }
687    }
688
689    *pResult1 = val1;
690    *pResult2 = val2;
691}
692
693
694static NEXUS_Error
695b_play_trick_stc_set_state(NEXUS_PlaybackHandle p, const b_trick_settings *settings)
696{
697    NEXUS_StcChannelHandle stcChannel;
698    NEXUS_Error rc;
699    unsigned decode_rate = settings->decode_rate;
700    unsigned denominator,numerator;
701
702    if(settings->state == b_trick_state_host_paced) {
703        decode_rate = NEXUS_NORMAL_PLAY_SPEED;
704    }
705
706    BDBG_MSG(("b_play_trick_stc_set_state %d", decode_rate));
707
708    if (decode_rate != NEXUS_NORMAL_PLAY_SPEED && !b_play_decoders_in_tsm_mode(p)) {
709        BDBG_ERR(("STC trick modes require decoder(s) to be in TSM mode"));
710        return BERR_TRACE(BERR_NOT_SUPPORTED);
711    }
712
713    stcChannel = p->params.stcChannel;
714   
715    if (!stcChannel) {
716        return BERR_TRACE(BERR_NOT_SUPPORTED);
717    }
718
719    remove_common_factors( decode_rate, NEXUS_NORMAL_PLAY_SPEED, &numerator, &denominator);
720    if ( numerator && (numerator > 255 || denominator > 255) ) {
721        /* This will occur for prime number numerators between min decode rate and max decode rate, eg 1009/1000 */
722        BDBG_MSG(("common Factors > 255, stcTrickmode decode rate not optimal numr=%d denr=%d!", numerator, denominator ));
723    }
724
725    rc = NEXUS_StcChannel_SetRate(stcChannel, numerator, denominator - 1 /* -1 because HW uses denom+1 for prescale val */ );
726    if(rc!=NEXUS_SUCCESS) {rc=BERR_TRACE(rc);goto error;}
727
728    return NEXUS_SUCCESS;
729
730error:
731    return rc;
732}
733
734NEXUS_Error
735b_play_trick_set(NEXUS_PlaybackHandle p, const b_trick_settings *settings)
736{
737    NEXUS_Error rc;
738    const NEXUS_Playback_P_PidChannel *pid;
739
740    BDBG_CASSERT(NEXUS_NORMAL_PLAY_SPEED == NEXUS_NORMAL_DECODE_RATE);
741
742    if (!settings) {
743        /* reapply previous settings */
744        settings = &p->trick.settings;
745    }
746
747    BDBG_MSG(("b_play_trick_set: %#lx %s->%s %s->%s %d->%d %d->%d %s->%s", (unsigned long)p,
748        B_TRICK_STATE_STR(p->trick.settings.state), B_TRICK_STATE_STR(settings->state),
749        B_FORWARD_STR(p->trick.settings.forward), B_FORWARD_STR(settings->forward),
750        p->trick.settings.decode_rate, settings->decode_rate,
751        p->trick.settings.stc_trick, settings->stc_trick,
752        B_DECODE_MODE_STR(p->trick.settings.decode_mode), B_DECODE_MODE_STR(settings->decode_mode) ));
753
754    /* fail invalid trick modes */
755    if (settings->state == b_trick_state_normal && !settings->forward) {
756        rc = BERR_TRACE(BERR_NOT_SUPPORTED);
757        goto err_settings;
758    }
759
760    /* if the state and direction aren't changing, we don't need to flush. just jump over. */
761    if (p->trick.settings.state == settings->state &&
762        p->trick.settings.forward == settings->forward &&
763        (p->trick.settings.decode_mode == settings->decode_mode || p->trick.settings.avoid_flush))
764    {
765        goto set_decoder_state;
766    }
767
768    /* this flushes both playback and decoders. this must occur before changing decoder state.
769    if not, the new decoder state might be applied to a small amount of the old data and undesired
770    results may be seen. if the interface to the decoder is slow (which it is), the likelihood
771    increases. */
772    b_play_flush(p);
773
774set_decoder_state:
775
776    if(p->trick.settings.state==b_trick_state_host_paced  || settings->state == b_trick_state_host_paced) {
777        NEXUS_PlaypumpSettings pumpCfg;
778
779        NEXUS_Playpump_GetSettings(p->params.playpump, &pumpCfg);
780        BDBG_CASSERT(NEXUS_NORMAL_DECODE_RATE==NEXUS_NORMAL_PLAY_SPEED);
781        if(settings->decode_rate!=0 && settings->state == b_trick_state_host_paced) {
782            pumpCfg.playRate = settings->decode_rate;
783        } else {
784            if(settings->forward) {
785                pumpCfg.playRate = NEXUS_NORMAL_DECODE_RATE;
786            } else {
787                pumpCfg.playRate = -NEXUS_NORMAL_DECODE_RATE;
788            }
789        }
790        rc = NEXUS_Playpump_SetSettings(p->params.playpump, &pumpCfg);
791        if(rc!=NEXUS_SUCCESS) { rc = BERR_TRACE(rc); goto err_settings;}
792    }
793
794    /* SW35230-2125, invalidate STC channel to force the STC to get reloaded. This is
795    required to minimize the lost of audio/video data when transitioning from
796    decoder_pause-->play or decoder_pause->seek->play.  The problem shows up if the
797    time period between transition is long. */
798    if(p->params.stcChannel) {
799        rc = NEXUS_StcChannel_Invalidate(p->params.stcChannel);
800        if(rc!=NEXUS_SUCCESS) { rc = BERR_TRACE(rc); goto err_settings;}
801    }
802
803    for (pid = BLST_S_FIRST(&p->pid_list); pid ; pid = BLST_S_NEXT(pid, link)) {
804        rc = b_play_trick_set_pid(p, pid, settings);
805        if(rc!=NEXUS_SUCCESS) {rc=BERR_TRACE(rc);goto err_set_pid;}
806    }
807
808    /* decoders must already be set into their state before setting STC */
809    if (settings->stc_trick && (settings->state == b_trick_state_normal || settings->state == b_trick_state_host_paced)) {
810        /* stc trick modes */
811        rc = b_play_trick_stc_set_state(p, settings);
812        if(rc!=NEXUS_SUCCESS) { rc = BERR_TRACE(rc); goto err_settings;}
813    }
814
815    p->trick.settings = *settings;
816    return NEXUS_SUCCESS;
817
818err_set_pid:
819err_settings:
820    return rc;
821}
822
823NEXUS_Error
824b_play_trick_frameadvance(NEXUS_PlaybackHandle p)
825{
826    const NEXUS_Playback_P_PidChannel *pid;
827    NEXUS_Error rc;
828
829    pid = b_play_get_video_decoder(p);
830    if (!pid) {
831        BDBG_WRN(("Can't do frame advance without Nexus_VideoDecoderHandle"));
832        BDBG_WRN(("Please set NEXUS_PlaybackPidChannelSettings.pidTypeSettings.video.decoder before calling NEXUS_Playback_OpenPidChannel()"));
833        rc = BERR_TRACE(BERR_INVALID_PARAMETER);
834        goto err_advance;
835    }
836
837    if (pid->cfg.pidTypeSettings.video.decoder) {
838        if (p->trick.settings.stc_trick && p->trick.settings.forward) {
839            uint32_t next_pts, stc;
840            NEXUS_StcChannelSettings stcSettings;
841   
842            NEXUS_StcChannel_GetStc(p->params.stcChannel, &stc);
843            rc = NEXUS_VideoDecoder_GetNextPts(pid->cfg.pidTypeSettings.video.decoder, &next_pts);
844            if (rc!=NEXUS_SUCCESS) {
845                BDBG_WRN(("cannot frame advance. PTS not available yet."));
846                /* don't fail. this is normal on transition. app should simply call again. */
847                return BERR_SUCCESS;
848            }
849            NEXUS_StcChannel_GetSettings(p->params.stcChannel, &stcSettings);
850   
851            BDBG_MSG(("b_play_trick_frameadvance: STC=%08X, Next PTS=%08X", stc, next_pts));
852            stc = next_pts + stcSettings.modeSettings.Auto.offsetThreshold;
853            rc = NEXUS_StcChannel_SetStc(p->params.stcChannel, stc);
854            if(rc!=NEXUS_SUCCESS) {rc=BERR_TRACE(rc);goto err_advance;}
855        }
856        else {
857            BDBG_MSG(("b_play_trick_frameadvance: video frame advance"));
858            rc = NEXUS_VideoDecoder_FrameAdvance(pid->cfg.pidTypeSettings.video.decoder);
859            if(rc!=BERR_SUCCESS) {rc=BERR_TRACE(rc);goto err_advance;}
860        }
861    }
862#if NEXUS_HAS_SIMPLE_DECODER
863    else if (pid->cfg.pidTypeSettings.video.simpleDecoder) {
864        BDBG_MSG(("b_play_trick_frameadvance: video frame advance"));
865        rc = NEXUS_SimpleVideoDecoder_FrameAdvance(pid->cfg.pidTypeSettings.video.simpleDecoder);
866        if(rc!=BERR_SUCCESS) {rc=BERR_TRACE(rc);goto err_advance;}
867    }
868#endif
869   
870    return NEXUS_SUCCESS;
871err_advance:
872    return rc;
873}
874
875NEXUS_Error NEXUS_P_Playback_VideoDecoder_GetStatus(const NEXUS_Playback_P_PidChannel *pid, NEXUS_VideoDecoderStatus *pStatus)
876{
877    if (pid->cfg.pidTypeSettings.video.decoder) {
878        return NEXUS_VideoDecoder_GetStatus(pid->cfg.pidTypeSettings.video.decoder, pStatus);
879    }
880#if NEXUS_HAS_SIMPLE_DECODER
881    else if (pid->cfg.pidTypeSettings.video.simpleDecoder) {
882        return NEXUS_SimpleVideoDecoder_GetStatus(pid->cfg.pidTypeSettings.video.simpleDecoder, pStatus);
883    }
884#endif
885    return BERR_TRACE(NEXUS_NOT_AVAILABLE);
886}
887
888void NEXUS_P_Playback_VideoDecoder_Flush(const NEXUS_Playback_P_PidChannel *pid)
889{
890    /* only apply to one. there will never be >1 at a time. */
891    if(pid->cfg.pidTypeSettings.video.decoder) {
892        NEXUS_VideoDecoder_Flush(pid->cfg.pidTypeSettings.video.decoder);
893    }
894#if NEXUS_HAS_SIMPLE_DECODER
895    else if(pid->cfg.pidTypeSettings.video.simpleDecoder) {
896        NEXUS_SimpleVideoDecoder_Flush(pid->cfg.pidTypeSettings.video.simpleDecoder);
897    }
898#endif
899}
900
901void NEXUS_P_Playback_VideoDecoder_GetTrickState(const NEXUS_Playback_P_PidChannel *pid, NEXUS_VideoDecoderTrickState *pState)
902{
903    if (pid->cfg.pidTypeSettings.video.decoder) {
904        NEXUS_VideoDecoder_GetTrickState(pid->cfg.pidTypeSettings.video.decoder, pState);
905        return;
906    }
907#if NEXUS_HAS_SIMPLE_DECODER
908    else if (pid->cfg.pidTypeSettings.video.simpleDecoder) {
909        NEXUS_SimpleVideoDecoder_GetTrickState(pid->cfg.pidTypeSettings.video.simpleDecoder, pState);
910        return;
911    }
912#endif
913    BKNI_Memset(pState, 0, sizeof(*pState));
914    return;
915}
916
917NEXUS_Error NEXUS_P_Playback_VideoDecoder_SetTrickState(const NEXUS_Playback_P_PidChannel *pid, const NEXUS_VideoDecoderTrickState *pState)
918{
919    /* only apply to one. there will never be >1 at a time. */
920    if (pid->cfg.pidTypeSettings.video.decoder) {
921        return NEXUS_VideoDecoder_SetTrickState(pid->cfg.pidTypeSettings.video.decoder, pState);
922    }
923#if NEXUS_HAS_SIMPLE_DECODER
924    else if (pid->cfg.pidTypeSettings.video.simpleDecoder) {
925        return NEXUS_SimpleVideoDecoder_SetTrickState(pid->cfg.pidTypeSettings.video.simpleDecoder, pState);
926    }
927#endif
928    return BERR_TRACE(NEXUS_NOT_AVAILABLE);
929}
930
931void NEXUS_P_Playback_VideoDecoder_GetPlaybackSettings(const NEXUS_Playback_P_PidChannel *pid, NEXUS_VideoDecoderPlaybackSettings *pSettings)
932{
933    if (pid->cfg.pidTypeSettings.video.decoder) {
934        NEXUS_VideoDecoder_GetPlaybackSettings(pid->cfg.pidTypeSettings.video.decoder, pSettings);
935        return;
936    }
937#if NEXUS_HAS_SIMPLE_DECODER
938    else if (pid->cfg.pidTypeSettings.video.simpleDecoder) {
939        NEXUS_SimpleVideoDecoder_GetPlaybackSettings(pid->cfg.pidTypeSettings.video.simpleDecoder, pSettings);
940        return;
941    }
942#endif
943    BKNI_Memset(pSettings, 0, sizeof(*pSettings));
944    return;
945}
946
947NEXUS_Error NEXUS_P_Playback_VideoDecoder_SetPlaybackSettings(const NEXUS_Playback_P_PidChannel *pid, const NEXUS_VideoDecoderPlaybackSettings *pSettings)
948{
949    /* only apply to one. there will never be >1 at a time. */
950    if (pid->cfg.pidTypeSettings.video.decoder) {
951        return NEXUS_VideoDecoder_SetPlaybackSettings(pid->cfg.pidTypeSettings.video.decoder, pSettings);
952    }
953#if NEXUS_HAS_SIMPLE_DECODER
954    else if (pid->cfg.pidTypeSettings.video.simpleDecoder) {
955        return NEXUS_SimpleVideoDecoder_SetPlaybackSettings(pid->cfg.pidTypeSettings.video.simpleDecoder, pSettings);
956    }
957#endif
958    return BERR_TRACE(NEXUS_NOT_AVAILABLE);
959}
960
961NEXUS_Error NEXUS_P_Playback_AudioDecoder_GetStatus(const NEXUS_Playback_P_PidChannel *pid, NEXUS_AudioDecoderStatus *pStatus)
962{
963    if (pid->cfg.pidTypeSettings.audio.primary) {
964        return NEXUS_AudioDecoder_GetStatus(pid->cfg.pidTypeSettings.audio.primary, pStatus);
965    }
966    else if (pid->cfg.pidTypeSettings.audio.secondary) {
967        return NEXUS_AudioDecoder_GetStatus(pid->cfg.pidTypeSettings.audio.secondary, pStatus);
968    }
969#if NEXUS_HAS_SIMPLE_DECODER
970    else if (pid->cfg.pidTypeSettings.audio.simpleDecoder) {
971        return NEXUS_SimpleAudioDecoder_GetStatus(pid->cfg.pidTypeSettings.audio.simpleDecoder, pStatus);
972    }
973#endif
974    return BERR_TRACE(NEXUS_NOT_AVAILABLE);
975}
976
977void NEXUS_P_Playback_AudioDecoder_Flush(const NEXUS_Playback_P_PidChannel *pid)
978{
979    NEXUS_Error rc;
980    if(pid->cfg.pidTypeSettings.audio.primary) {
981        rc = NEXUS_AudioDecoder_Flush(pid->cfg.pidTypeSettings.audio.primary);
982        if(rc!=BERR_SUCCESS) { rc = BERR_TRACE(rc);}
983    }
984    if(pid->cfg.pidTypeSettings.audio.secondary) {
985        rc = NEXUS_AudioDecoder_Flush(pid->cfg.pidTypeSettings.audio.secondary);
986        if(rc!=BERR_SUCCESS) { rc = BERR_TRACE(rc);}
987    }
988#if NEXUS_HAS_SIMPLE_DECODER
989    if (pid->cfg.pidTypeSettings.audio.simpleDecoder) {
990        NEXUS_SimpleAudioDecoder_Flush(pid->cfg.pidTypeSettings.audio.simpleDecoder);
991    }
992#endif
993}
994
995NEXUS_Error NEXUS_Playback_P_AudioDecoder_Advance(const NEXUS_Playback_P_PidChannel *pid, uint32_t video_pts)
996{
997    NEXUS_Error rc;
998    if(pid->cfg.pidTypeSettings.audio.primary) {
999        rc = NEXUS_AudioDecoder_Advance(pid->cfg.pidTypeSettings.audio.primary, video_pts);
1000        if(rc!=BERR_SUCCESS) {rc=BERR_TRACE(rc);}
1001    }
1002    if(pid->cfg.pidTypeSettings.audio.secondary) {
1003        rc = NEXUS_AudioDecoder_Advance(pid->cfg.pidTypeSettings.audio.secondary, video_pts);
1004        if(rc!=BERR_SUCCESS) {rc=BERR_TRACE(rc);}
1005    }
1006#if NEXUS_HAS_SIMPLE_DECODER
1007    if (pid->cfg.pidTypeSettings.audio.simpleDecoder) {
1008        rc = NEXUS_SimpleAudioDecoder_Advance(pid->cfg.pidTypeSettings.audio.simpleDecoder, video_pts);
1009        if(rc!=BERR_SUCCESS) { rc = BERR_TRACE(rc);}
1010    }
1011#endif
1012    return 0;
1013}
1014
1015void NEXUS_P_Playback_AudioDecoder_GetTrickState(const NEXUS_Playback_P_PidChannel *pid, NEXUS_AudioDecoderTrickState *pState)
1016{
1017    /* get the first one */
1018    if (pid->cfg.pidTypeSettings.audio.primary) {
1019        NEXUS_AudioDecoder_GetTrickState(pid->cfg.pidTypeSettings.audio.primary, pState);
1020        return;
1021    }
1022    else if (pid->cfg.pidTypeSettings.audio.secondary) {
1023        NEXUS_AudioDecoder_GetTrickState(pid->cfg.pidTypeSettings.audio.secondary, pState);
1024        return;
1025    }
1026#if NEXUS_HAS_SIMPLE_DECODER
1027    else if (pid->cfg.pidTypeSettings.audio.simpleDecoder) {
1028        NEXUS_SimpleAudioDecoder_GetTrickState(pid->cfg.pidTypeSettings.audio.simpleDecoder, pState);
1029        return;
1030    }
1031#endif
1032    BKNI_Memset(pState, 0, sizeof(*pState));
1033    return;
1034}
1035
1036NEXUS_Error NEXUS_P_Playback_AudioDecoder_SetTrickState(const NEXUS_Playback_P_PidChannel *pid, NEXUS_AudioDecoderTrickState *pState)
1037{
1038    NEXUS_Error rc;
1039    /* set any available */
1040    if (pid->cfg.pidTypeSettings.audio.primary) {
1041        rc = NEXUS_AudioDecoder_SetTrickState(pid->cfg.pidTypeSettings.audio.primary, pState);
1042        if (rc) return BERR_TRACE(rc);
1043    }
1044    if (pid->cfg.pidTypeSettings.audio.secondary) {
1045        rc = NEXUS_AudioDecoder_SetTrickState(pid->cfg.pidTypeSettings.audio.secondary, pState);
1046        if (rc) return BERR_TRACE(rc);
1047    }
1048#if NEXUS_HAS_SIMPLE_DECODER
1049    if (pid->cfg.pidTypeSettings.audio.simpleDecoder) {
1050        rc = NEXUS_SimpleAudioDecoder_SetTrickState(pid->cfg.pidTypeSettings.audio.simpleDecoder, pState);
1051        if (rc) return BERR_TRACE(rc);
1052    }
1053#endif
1054    return 0;
1055}
1056
Note: See TracBrowser for help on using the repository browser.