source: svn/newcon3bcm2_21bu/magnum/commonutils/xdm/bxdm_pp_v2.c @ 74

Last change on this file since 74 was 74, checked in by phkim, 10 years ago
  1. phkim
  2. zasc
  3. 변경 내용
    • CT_ChMapUpdatePMTAC3AudioDescriptor 메모리 leak 버그 수정
  • Property svn:executable set to *
File size: 102.0 KB
Line 
1/***************************************************************************
2 *     Copyright (c) 2003-2012, Broadcom Corporation
3 *     All Rights Reserved
4 *     Confidential Property of Broadcom Corporation
5 *
6 *  THIS SOFTWARE MAY ONLY BE USED SUBJECT TO AN EXECUTED SOFTWARE LICENSE
7 *  AGREEMENT  BETWEEN THE USER AND BROADCOM.  YOU HAVE NO RIGHT TO USE OR
8 *  EXPLOIT THIS MATERIAL EXCEPT SUBJECT TO THE TERMS OF SUCH AN AGREEMENT.
9 *
10 * $brcm_Workfile: bxdm_pp_v2.c $
11 * $brcm_Revision: Hydra_Software_Devel/32 $
12 * $brcm_Date: 3/22/12 8:42a $
13 *
14 * [File Description:]
15 *
16 * Revision History:
17 *
18 * $brcm_Log: /magnum/commonutils/xdm/bxdm_pp_v2.c $
19 *
20 * Hydra_Software_Devel/32   3/22/12 8:42a btosi
21 * SW7425-2656: when paused during a flush, prevent the next picture from
22 * being displayed until unpaused
23 *
24 * Hydra_Software_Devel/31   3/16/12 11:56a btosi
25 * SW7425-2536: added support for displayInterruptStatus_isr
26 *
27 * Hydra_Software_Devel/30   12/15/11 1:19p btosi
28 * SW7635-51: update the current PTS info with the SW PCR offset
29 * associated with the selected picture.
30 *
31 * Hydra_Software_Devel/29   12/7/11 1:38p btosi
32 * SW7405-3984: to handle FlushDecode properly, check if a picture should
33 * be released prior to restoring the channel change mode
34 *
35 * Hydra_Software_Devel/28   12/6/11 3:53p btosi
36 * SW7405-3984: if the ChannelChangeMode changed from hold to mute,
37 * release the held picture in BXDM_PictureProvider_StartDecode_isr
38 *
39 * Hydra_Software_Devel/27   10/3/11 2:19p btosi
40 * SW7425-1264:  support for a SW STC internal to XDM
41 *
42 * Hydra_Software_Devel/26   8/17/11 5:02p davidp
43 * SW7425-1134: Only toggle picture polarity for MVC pictures on DVD
44 * platforms.
45 *
46 * Hydra_Software_Devel/25   7/8/11 2:53p btosi
47 * SW7425-875: update stNextPTS.uiSTCSnapShot at the beginning of
48 * BXDM_PP_S_SelectPicture
49 *
50 * Hydra_Software_Devel/24   5/10/11 1:41p btosi
51 * SW7405-4736: added range checking and debug messages for the input
52 * parameters
53 *
54 * Hydra_Software_Devel/23   5/2/11 9:14a btosi
55 * SW7405-4736: moved location of BXDM_PPDBG_P_PrintMFD
56 *
57 * Hydra_Software_Devel/22   4/28/11 1:57p nilesh
58 * SWDTV-5937: Fixed incorrect deltaSTC values for 23.976, 29.97, and
59 * 59.94 Hz monitor refresh rates
60 *
61 * Hydra_Software_Devel/21   4/21/11 1:53p btosi
62 * SW7405-4736: moved BXDM_PPQM_P_PrintUnifiedPicture to bxdm_pp_dbg.c,
63 * tweaked the BXDM_PPQM message
64 *
65 * Hydra_Software_Devel/20   4/18/11 1:04p btosi
66 * SW7405-4736: save the average STC delta for use in the debug messages
67 *
68 * Hydra_Software_Devel/19   4/12/11 2:19p btosi
69 * SW7405-4736: added support for MFD debug messages
70 *
71 * Hydra_Software_Devel/18   4/5/11 2:26p btosi
72 * SW7405-4736: removed BXDM_PP_ENABLE_YUV_GRAB_MODE, grab is implemented
73 * in bxvd_decoder.c
74 *
75 * Hydra_Software_Devel/17   12/21/10 4:28p delkert
76 * SW7405-5043: Fix rate match detection to compare avg dPTS to avg dSTC
77 * and not use diff between deltas, to make it more immune to jitter and
78 * false matching
79 * Move JTI adjustment so it applies to STC trick mode also
80 * Made STC trick mode detection a sub-routine
81 * Split STC stored in local state into two parts: STC from decoder and
82 * STC after JTI adjustment
83 *
84 * Hydra_Software_Devel/16   10/20/10 11:47a btosi
85 * SW7405-4804: deliver the SEI messages for pictures that are dropped
86 *
87 * Hydra_Software_Devel/15   9/23/10 3:09p btosi
88 * SW7405-4736: add support for a XDM instance ID to help debug multi-
89 * channel issues
90 *
91 * Hydra_Software_Devel/14   8/26/10 3:14p btosi
92 * SWBLURAY-22286: don't reloaded the virtual STC on the dependent
93 * interrupt
94 *
95 * Hydra_Software_Devel/13   8/12/10 9:38a btosi
96 * SW7405-4736: modified QM debug messages
97 *
98 * Hydra_Software_Devel/12   8/10/10 4:29p btosi
99 * SW7405-4736: added uiVsyncCount to debug messages
100 *
101 * Hydra_Software_Devel/11   7/12/10 8:05a delkert
102 * SW7335-781: Output warning when forcing picture selection override to
103 * allow easier detection of conditions such as drop@decode and pcr
104 * discontinuity
105 *
106 * Hydra_Software_Devel/10   7/6/10 2:31p btosi
107 * SW7630-85: initialize the bMute flag in BXDM_PictureProvider_Create
108 *
109 * Hydra_Software_Devel/9   7/2/10 9:15a delkert
110 * SW7405-4563: Qualify PTS error with First Coded PTS flag instead of
111 * FirstPTSReady (FirstPTSReady can occur without a valid PTS!).
112 *
113 * Hydra_Software_Devel/8   6/30/10 12:00p delkert
114 * SW7405-4563: Don't force PTS Error callback if FirstPTSReady hasn't yet
115 * been called
116 *
117 * Hydra_Software_Devel/7   6/29/10 11:25a btosi
118 * SW7405-4365: revamped the timer code to selectively enable the function
119 * and callback timing
120 *
121 * Hydra_Software_Devel/6   6/18/10 4:25p delkert
122 * SW7405-3895: Re-enable RequestSTC callback if handler installed upon
123 * trick->play transition
124 *
125 * Hydra_Software_Devel/5   6/8/10 3:14p btosi
126 * SW7405-4378: fixed reporting of source size by the PictureParameter
127 * callback when the first picture(s) is dropped
128 *
129 * Hydra_Software_Devel/4   6/7/10 10:21a delkert
130 * SW7405-3925: For progressive content, send drop@decode request in
131 * fields, not elements.  Modify request to update request count
132 * accordingly.
133 *
134 * Hydra_Software_Devel/3   5/6/10 3:13p btosi
135 * SWBLURAY-20436: toggle the source and interrupt polarity on the
136 * dependent interrupt.
137 *
138 * Hydra_Software_Devel/2   3/1/10 5:10p nilesh
139 * SW7405-2993: Fixed coverity warnings
140 *
141 * Hydra_Software_Devel/1   2/16/10 10:51a nilesh
142 * SW7405-2993: Initial XDM version
143 *
144 ***************************************************************************/
145
146#include "bstd.h"
147#include "bkni.h"
148#include "bdbg.h"
149
150#include "bxdm_pp.h"
151#include "bxdm_pp_priv.h"
152#include "bxdm_pp_qm.h"
153#include "bxdm_pp_output.h"
154#include "bxdm_pp_tsm.h"
155#include "bxdm_pp_vtsm.h"
156#include "bxdm_pp_callback_priv.h"
157#include "bxdm_pp_dbg.h"
158#include "bxdm_pp_clip.h"
159#include "bxdm_pp_fic.h"
160#include "bxdm_pp_jrc.h"
161#include "bxdm_pp_avg.h"
162#include "bxdm_pp_ver.h"
163
164BDBG_MODULE(BXDM_PPV2); /* Register software module with debug interface */
165
166const char BXDM_PictureProvider_P_DISPMGR_V2_NODE[]="DMV2:\t""$brcm_Revision: Hydra_Software_Devel/32 $";
167
168extern uint32_t BXDM_PPTMR_lutVsyncsPersSecond[];
169
170/*
171** Local function prototypes.
172*/
173static void BXDM_PP_S_ResetCommon(
174   BXDM_PictureProvider_Handle hXdmPP
175   );
176
177static void BXDM_PP_S_InitPerVsync(
178   BXDM_PictureProvider_Handle hXdmPP,
179   BXDM_PictureProvider_P_LocalState* pLocalState,
180   const BXDM_DisplayInterruptInfo *pstDisplayInterruptInfo
181   );
182
183static bool BXDM_PP_S_RateMatchDetection(
184   BXDM_PictureProvider_Handle hXdmPP,
185   BXDM_PictureProvider_P_LocalState* pLocalState
186   );
187
188static void BXDM_PP_S_STCTrickModeDetection(
189   BXDM_PictureProvider_Handle hXdmPP,
190   BXDM_PictureProvider_P_LocalState* pLocalState
191   );
192
193static void BXDM_PP_S_SnapShotXvdState(
194   BXDM_PictureProvider_Handle hXdmPP,
195   BXDM_PictureProvider_P_LocalState* pLocalState
196   );
197
198static void BXDM_PP_S_SnapShotFirmwareState(
199   BXDM_PictureProvider_Handle hXdmPP,
200   BXDM_PictureProvider_P_LocalState* pLocalState,
201   const BXDM_DisplayInterruptInfo *pstDisplayInterruptInfo
202   );
203
204static void BXDM_PP_S_SelectPicture(
205   BXDM_PictureProvider_Handle hXdmPP,
206   BXDM_PictureProvider_P_LocalState* pLocalState
207   );
208
209static void BXDM_PP_S_SelectElement(
210   BXDM_PictureProvider_Handle hXdmPP,
211   BXDM_PictureProvider_P_LocalState* pLocalState
212   );
213
214static void BXDM_PP_S_UpdatePublicStatus(
215   BXDM_PictureProvider_Handle hXdmPP,
216   BXDM_PictureProvider_P_LocalState* pLocalState
217   );
218
219static void BXDM_PP_S_PostIsr(
220   BXDM_PictureProvider_Handle hXdmPP,
221   BXDM_PictureProvider_P_LocalState* pLocalState,
222   bool bPrimaryPicture
223   );
224
225/* sDeltaStcLUT is a lookup table for the delta STC per vsync based on
226 * the clock rate type (MPEG or DTV) and the monitor refresh rate. It
227 * is calculated assuming the fractional component's denominator is
228 * 65536 */
229static const BXDM_PPFP_P_DataType sDeltaStcLUT[BXDM_PictureProvider_P_ClockRate_eMax][BXDM_PictureProvider_MonitorRefreshRate_eMax]=
230{
231   /* BXDM_PictureProvider_P_ClockRate_eMPEG2 (45Khz) */
232   {
233      {    0,     0},   /* BXDM_PictureProvider_MonitorRefreshRate_eUnknown - NOT POSSIBLE */
234      { 1876, 57344},   /* BXDM_PictureProvider_MonitorRefreshRate_e23_97 */
235      { 1875,     0},   /* BXDM_PictureProvider_MonitorRefreshRate_e24 */
236      { 1800,     0},   /* BXDM_PictureProvider_MonitorRefreshRate_e25 */
237      { 1501, 32768},   /* BXDM_PictureProvider_MonitorRefreshRate_e29_97 */
238      { 1500,     0},   /* BXDM_PictureProvider_MonitorRefreshRate_e30 */
239      {  900,     0},   /* BXDM_PictureProvider_MonitorRefreshRate_e50 */
240      {  750, 49152},   /* BXDM_PictureProvider_MonitorRefreshRate_e59_94 */
241      {  750,     0},   /* BXDM_PictureProvider_MonitorRefreshRate_e60 */
242      {  937, 32768}    /* BXDM_PictureProvider_MonitorRefreshRate_e48 */
243   },
244
245   /* BXDM_PictureProvider_P_ClockRate_eDirecTV (27 Mhz) */
246   {
247      {       0,     0},   /* BXDM_PictureProvider_MonitorRefreshRate_eUnknown - NOT POSSIBLE */
248      { 1126125,     0},   /* BXDM_PictureProvider_MonitorRefreshRate_e23_97 */
249      { 1125000,     0},   /* BXDM_PictureProvider_MonitorRefreshRate_e24 */
250      { 1080000,     0},   /* BXDM_PictureProvider_MonitorRefreshRate_e25 */
251      {  900900,     0},   /* BXDM_PictureProvider_MonitorRefreshRate_e29_97 */
252      {  900000,     0},   /* BXDM_PictureProvider_MonitorRefreshRate_e30 */
253      {  540000,     0},   /* BXDM_PictureProvider_MonitorRefreshRate_e50 */
254      {  450450,     0},   /* BXDM_PictureProvider_MonitorRefreshRate_e59_94 */
255      {  450000,     0},   /* BXDM_PictureProvider_MonitorRefreshRate_e60 */
256      {  562500,     0}    /* BXDM_PictureProvider_MonitorRefreshRate_e48 */
257   }
258}; /* end of sDeltaStcLUT[] */
259
260#define BXDM_PictureProvider_P_FRAMERATE_UNINITIALIZED ((BAVC_FrameRateCode) 0xFFFFFFFF)
261#define BXDM_PictureProvider_P_PULLDOWN_UNINITIALIZED ((BXDM_Picture_PullDown) 0xFFFFFFFF)
262#define BXDM_PictureProvider_P_PTS_JITTER_LOWER_THRESHOLD 1
263#define BXDM_PictureProvider_P_PTS_JITTER_UPPER_THRESHOLD 45
264#define BXDM_PictureProvider_P_RATE_MATCH_DETECTION_SAMPLES 30
265
266/*
267** Local function implementations
268*/
269static void BXDM_PP_S_ResetCommon(
270   BXDM_PictureProvider_Handle hXdmPP
271   )
272{
273   BXDM_PictureProvider_P_Picture_Context *pstPictureUnderEvaluation;
274
275   BDBG_ENTER(BXDM_PP_S_ResetCommon);
276
277   /* Reset picture parameter info struct */
278   BKNI_Memset( &(hXdmPP->stDMStatus.stPictureParameterInfo), 0, sizeof( BXDM_PictureProvider_Callback_PictureParameterInfo ) );
279
280   /* SW7405-4378: reset the cached the picture parameters */
281   BKNI_Memset( &(hXdmPP->stDMStatus.stCachedPictureParameters), 0, sizeof( BXDM_PictureProvider_P_PictureParameterInfo ) );
282
283   /* Reset the decode persistent state */
284   BKNI_Memset( &(hXdmPP->stDMState.stDecode), 0, sizeof( BXDM_PictureProvider_P_State_Decode ) );
285
286   hXdmPP->stDMState.stDecode.stLatestCodedPts.ePTSType = BXDM_PictureProvider_PTSType_eInterpolatedFromInvalidPTS ;
287   hXdmPP->stDMState.stDecode.stFirstCodedPts.ePTSType = BXDM_PictureProvider_PTSType_eInterpolatedFromInvalidPTS ;
288
289   hXdmPP->stDMState.stDecode.stErrorPts.ePTSType = BXDM_PictureProvider_PTSType_eInterpolatedFromInvalidPTS ;
290   hXdmPP->stDMState.stDecode.eLastUnsupportedFrameRate = BXDM_PictureProvider_P_FRAMERATE_UNINITIALIZED;
291   hXdmPP->stDMState.stDecode.eLastIncorrectMonitorRefreshRate = 0xFFFFFFFF;
292   hXdmPP->stDMState.stDecode.eLastUnsupportedPullDown = BXDM_PictureProvider_P_PULLDOWN_UNINITIALIZED;
293   hXdmPP->stDMState.stDecode.eLastSelectionModeOverride = BXDM_PictureProvider_DisplayMode_eTSM;
294
295   hXdmPP->stDMState.stDecode.bRateMatchedLastReported = true;
296
297   /* Reset Removal Delay */
298   hXdmPP->stDMState.stDecode.uiRemovalDelay = hXdmPP->stDMConfig.uiRemovalDelay;
299
300   /* eChannelChangeMode: Handle first picture preview feature of
301    * channel change - BXVD_StartDecode() */
302   hXdmPP->stDMState.stDecode.bForceDisplayFirstPPB = hXdmPP->stDMConfig.stChannelChangeSettings.bFirstPicturePreview;
303
304   /* We set STC to invalid */
305   hXdmPP->stDMConfig.bSTCValid = false;
306
307   /* Set the current selected picture's PTS to invalid, so that we
308    * don't interpolate from it */
309   hXdmPP->stDMState.stChannel.stSelectedPicture.stPicParms.stTSM.stStatic.ePtsType = BXDM_PictureProvider_PTSType_eInterpolatedFromInvalidPTS;
310   hXdmPP->stDMState.stChannel.stSelectedPicture.bValidated = false;
311
312   BKNI_Memset( &hXdmPP->stDMState.stChannel.stPreviousPictureUnderEvaluation, 0, sizeof ( BXDM_PictureProvider_P_Picture_Context ) );
313   hXdmPP->stDMState.stChannel.stPreviousPictureUnderEvaluation.stPicParms.stTSM.stStatic.ePtsType = BXDM_PictureProvider_PTSType_eInterpolatedFromInvalidPTS;
314   hXdmPP->stDMState.stChannel.stPreviousPictureUnderEvaluation.bValidated = false;
315
316   /* Reset the picture tag. */
317   hXdmPP->stDMStatus.uiPictureTag = 0;
318
319   /* Reset clip info structure */
320   BXDM_PPCLIP_P_Reset(hXdmPP);
321
322   /* Disable clip interrupts */
323   hXdmPP->stCallbacks[BXDM_PictureProvider_Callback_eClipStart].bEnable = false;
324   hXdmPP->stCallbacks[BXDM_PictureProvider_Callback_eClipStop].bEnable = false;
325   hXdmPP->stCallbacks[BXDM_PictureProvider_Callback_ePictureMarker].bEnable = false;
326
327   /* Enable the default callbacks */
328   BXDM_PPCB_P_EnableAutomaticCallbacks( hXdmPP );
329
330   /*
331   ** "stLastDispCodedPTS" and "stCurrentPTSInfo" are accessed outsided of the DM.
332   ** For now we'll keep supporting these structures.
333   ** We should be able to simply update them whenever a picture is promoted
334   ** to display status.
335   */
336   BKNI_Memset( &(hXdmPP->stDMStatus.stCodedPTS), 0, sizeof( BXDM_PictureProvider_PTSInfo ) );
337   hXdmPP->stDMStatus.stCodedPTS.ePTSType = BXDM_PictureProvider_PTSType_eInterpolatedFromInvalidPTS ;
338
339   BKNI_Memset( &(hXdmPP->stDMStatus.stCurrentPTS), 0, sizeof( BXDM_PictureProvider_PTSInfo ) );
340   hXdmPP->stDMStatus.stCurrentPTS.ePTSType = BXDM_PictureProvider_PTSType_eInterpolatedFromInvalidPTS ;
341
342   BKNI_Memset( &(hXdmPP->stDMStatus.stNextPTS), 0, sizeof( BXDM_PictureProvider_PTSInfo ) );
343   hXdmPP->stDMStatus.stNextPTS.ePTSType = BXDM_PictureProvider_PTSType_eInterpolatedFromInvalidPTS ;
344
345   /* forces a STC/PTS offset callback for the first picture with a TSM pass */
346   hXdmPP->stDMState.stDecode.uiStcPtsDeltaSentToApp = (uint32_t)(-1);
347
348   /* Reset the "I" picture flag, this will be set when the first I picture passes TSM. */
349   hXdmPP->stDMStatus.bIPictureFound = false;
350
351   /* Base the "prerolling" state on the pre-roll rate.
352    * If it is greater than '1', then "pre-roll" until a picture
353    * passes the TSM test.
354    * "pre-roll" means two things
355    * - run in vsync mode
356    * - use the "pre-roll" rate as a slow motion rate
357    */
358   if ( hXdmPP->stDMConfig.stPreRollRate.uiNumerator <  hXdmPP->stDMConfig.stPreRollRate.uiDenominator )
359   {
360      hXdmPP->stDMState.stDecode.bPreRolling = true;
361      hXdmPP->stDMState.stDecode.uiPreRollPlaybackRate = (hXdmPP->stDMConfig.stPreRollRate.uiNumerator * BXDM_PICTUREPROVIDER_NORMAL_PLAYBACK_RATE) / hXdmPP->stDMConfig.stPreRollRate.uiDenominator;
362   }
363   else
364   {
365      hXdmPP->stDMState.stDecode.uiPreRollPlaybackRate = BXDM_PICTUREPROVIDER_NORMAL_PLAYBACK_RATE;
366   }
367
368   /* If "BXDM_PictureProvider_ErrorHandlingMode_ePrognostic" error handling mode is set, drop pictures
369    * at start decode time until the first error free RAP picture is found.
370    */
371   if ( BXDM_PictureProvider_ErrorHandlingMode_ePrognostic == hXdmPP->stDMConfig.eErrorHandlingMode )
372   {
373      hXdmPP->stDMState.stDecode.bDropUntilNextRAP = true;
374   }
375
376   hXdmPP->stDMConfig.eFrameAdvanceMode = BXDM_PictureProvider_FrameAdvanceMode_eOff;
377   hXdmPP->stDMConfig.uiFrameAdvanceByFieldCount = 0;
378
379   /* Initialized the first element in the Picture Context Queue. */
380   pstPictureUnderEvaluation = BXDM_PPQM_P_GetFirstPictureContext(hXdmPP);
381   pstPictureUnderEvaluation->stPicParms.stTSM.stStatic.ePtsType = BXDM_PictureProvider_PTSType_eInterpolatedFromInvalidPTS;
382   pstPictureUnderEvaluation->bValidated = false;
383
384   BXDM_PPJRC_P_Reset( hXdmPP->stDMState.stChannel.hJrc );
385   BXDM_PPAVG_P_Reset( hXdmPP->stDMState.stChannel.hDeltaSTCAvg );
386   if ( (BAVC_VideoCompressionStd_eMPEG2DTV == hXdmPP->stDMConfig.eProtocol)
387        || (BAVC_VideoCompressionStd_eMPEG2_DSS_PES == hXdmPP->stDMConfig.eProtocol)
388      )
389   {
390      BXDM_PPJRC_P_SetLowerThreshold(
391               hXdmPP->stDMState.stChannel.hJrc,
392               BXDM_PictureProvider_P_PTS_JITTER_LOWER_THRESHOLD*600);
393
394      BXDM_PPJRC_P_SetUpperThreshold(
395               hXdmPP->stDMState.stChannel.hJrc,
396               BXDM_PictureProvider_P_PTS_JITTER_UPPER_THRESHOLD*600);
397   }
398   else
399   {
400      BXDM_PPJRC_P_SetLowerThreshold(
401               hXdmPP->stDMState.stChannel.hJrc,
402               BXDM_PictureProvider_P_PTS_JITTER_LOWER_THRESHOLD);
403
404      BXDM_PPJRC_P_SetUpperThreshold(
405               hXdmPP->stDMState.stChannel.hJrc,
406               BXDM_PictureProvider_P_PTS_JITTER_UPPER_THRESHOLD);
407   }
408
409   /* SW7405-4736: To force the debug messages to be printed at start decode time. */
410   hXdmPP->stDMConfig.uiDirtyBits_1 = BXDM_PictureProvider_P_DIRTY_ALL;
411   hXdmPP->stDMConfig.uiDirtyBits_2 = BXDM_PictureProvider_P_DIRTY_ALL;
412   
413   BDBG_LEAVE(BXDM_PP_S_ResetCommon);
414   return;
415} /* end of BXDM_PP_S_ResetCommon() */
416
417/*
418 * SW7425-2536: map the BAVC_FrameRateCode_eMax enum to a numerator/denominator pair.
419 */
420static const BXDM_Picture_Rate s_aFrameRateCodeToValue[BAVC_FrameRateCode_eMax] =
421{
422   { 60000, 1000 },   /* BAVC_FrameRateCode_eUnknown */
423   { 24000, 1001 },   /* BAVC_FrameRateCode_e23_976 */
424   { 24000, 1000 },   /* BAVC_FrameRateCode_e24 */
425   { 25000, 1000 },   /* BAVC_FrameRateCode_e25 */
426   { 30000, 1001 },   /* BAVC_FrameRateCode_e29_97 */
427   { 30000, 1000 },   /* BAVC_FrameRateCode_e30 */
428   { 50000, 1000 },   /* BAVC_FrameRateCode_e50 */
429   { 60000, 1001 },   /* BAVC_FrameRateCode_e59_94 */
430   { 60000, 1000 },   /* BAVC_FrameRateCode_e60 */
431   { 15000, 1001 },   /* BAVC_FrameRateCode_e14_985 */
432   { 15000, 2002 }    /* BAVC_FrameRateCode_e7_493 */
433};
434
435/*
436 * SW7425-2536: Currently for updating status returned by the "displayInterruptStatus_isr" callback.
437 */
438static void BXDM_PP_S_UpdateStatus(
439   BXDM_PictureProvider_Handle hXdmPP,
440   BXDM_PictureProvider_P_LocalState* pLocalState,
441   BXDM_PictureProvider_Status * pstStatus
442   )
443{
444   BXDM_PictureProvider_P_TSM_Picture_Parms * pstTsm;
445   const BXDM_Picture *pstUnifiedPicture;
446
447   BDBG_ENTER(BXDM_PP_S_UpdateStatus);
448
449   BDBG_ASSERT(hXdmPP);
450   BDBG_ASSERT(pstStatus);
451
452   BKNI_Memset( pstStatus, 0, sizeof( BXDM_PictureProvider_Status ) );
453
454   /* Grab the vsync count from the counters. */
455   pstStatus->uiVsyncCount = hXdmPP->stDMStatus.stCounters.uiVsyncCount;
456
457   /* Get the state of the delivery queue. */
458   pstStatus->bPictureQueueIsEmpty = pLocalState->bPictureQueueIsEmpty;
459
460   /* Set the parameters for the currently selected picture. */
461   pstTsm = &(hXdmPP->stDMState.stChannel.stSelectedPicture.stPicParms.stTSM);
462
463   pstStatus->stCurrentPicture.stFrameRate.eType   = BXDM_Picture_FrameRateType_eFixed;
464   pstStatus->stCurrentPicture.stFrameRate.bValid  = true;
465   pstStatus->stCurrentPicture.stFrameRate.stRate  = s_aFrameRateCodeToValue[pstTsm->stStatic.eFrameRateXVD];
466
467   pstStatus->stCurrentPicture.uiEffectivePts = pstTsm->stDynamic.uiEffectivePTS[BXDM_PictureProvider_P_PTSIndex_eActual];
468   pstStatus->stCurrentPicture.uiEffectiveStc = pstTsm->stDynamic.uiEffectiveStc[BXDM_PictureProvider_P_PTSIndex_eActual];
469
470   pstStatus->stCurrentPicture.bSelectionModeTsm = ( BXDM_PictureProvider_DisplayMode_eTSM == pstTsm->stDynamic.eSelectionMode );
471
472   pstUnifiedPicture = hXdmPP->stDMState.stChannel.stSelectedPicture.pstUnifiedPicture;
473
474   if ( NULL != pstUnifiedPicture )
475   {
476      pstStatus->stCurrentPicture.bValid = true;
477      pstStatus->stCurrentPicture.uiSerialNumber = pstUnifiedPicture->uiSerialNumber;
478   }
479
480   BDBG_LEAVE(BXDM_PP_S_UpdateStatus);
481
482   return;
483
484} /* end of BXDM_PP_S_UpdateStatus() */
485
486
487static void BXDM_PP_S_InitPerVsync(
488   BXDM_PictureProvider_Handle hXdmPP,
489   BXDM_PictureProvider_P_LocalState* pLocalState,
490   const BXDM_DisplayInterruptInfo *pstDisplayInterruptInfo
491   )
492{
493   BDBG_ENTER(BXDM_PP_S_InitPerVsync);
494
495   /* the count of vsync's since BXVD_StartDecode() was called */
496   hXdmPP->stDMStatus.stCounters.uiVsyncCount++;
497
498   /* SW7405-4736: a vsync count that is reset about once per second.
499    * Used to conditionally print QM debug messages.
500    */
501   hXdmPP->stDMState.stDecode.uiVsyncCountQM++;
502
503   /* Call the Decoder Display Interrupt Event callback if one is registered */
504   if ( NULL != hXdmPP->stDMConfig.stDecoderInterface.displayInterruptEvent_isr )
505   {
506      /* Snapshot the start time. */
507      BXDM_PPTMR_P_SnapshotFunctionStartTime( hXdmPP, BXDM_PPTIMER_P_Function_eDecoderDisplayInterruptEventIsr );
508
509      hXdmPP->stDMConfig.stDecoderInterface.displayInterruptEvent_isr(
510               hXdmPP->stDMConfig.pDecoderPrivateContext
511               );
512
513      /* Snapshot the end time. */
514      BXDM_PPTMR_P_SnapshotFunctionEndTime( hXdmPP, BXDM_PPTIMER_P_Function_eDecoderDisplayInterruptEventIsr );
515   }
516
517   /* BXDM_PP_S_SnapShotFirmwareState sets internal DM state based on
518    * the AVD state */
519   BXDM_PP_S_SnapShotFirmwareState( hXdmPP, pLocalState, pstDisplayInterruptInfo );
520
521   if ( BXDM_PictureProvider_P_InterruptType_eDependent != pLocalState->eInterruptType )
522   {
523   /* BXDM_PP_S_SnapShotXvdState sets internal DM state based on the
524    * XVD state */
525      BXDM_PP_S_SnapShotXvdState( hXdmPP, pLocalState );
526   }
527
528   BDBG_LEAVE(BXDM_PP_S_InitPerVsync);
529   return;
530} /* end of BXDM_PP_S_InitPerVsync() */
531
532
533/* SW7405-5043: Perform rate matching based on average deltaPTS vs average deltaSTC.
534
535   If they are within .05% then they are considered matched.
536   Note: here dPTS and dSTC are the raw dPTS from the stream (after interpolation), and the raw dSTC from the decoder
537   before any manipulation/correction.
538
539   NOTE: Rate matching only affects application of the JTI.
540
541   For purposes of JTI, 29.97 != 30, 59.94 != 60 and 23.98 != 24 (i.e. expect a .1% diff)
542   So rate match is true if diff between dPTSAvg and dSTCAvg is < .05% of the smaller of the two values
543   Note: 1/2048 ~ 0.05%, so >> by 11 bits (keeping in mind that the averages are always positive values)
544
545   TODO: What about 30fps progressive on a 60Hz display?  Ideally, JTI should be applied for any integer multiple of the
546   source rate, since the same STC jitter problem can occur.
547   It is questionable whether we need to even do rate match at all - seems we should be doing this always!
548*/
549static bool BXDM_PP_S_RateMatchDetection(
550   BXDM_PictureProvider_Handle hXdmPP,
551   BXDM_PictureProvider_P_LocalState* pLocalState
552   )
553{
554   /* default to true, since we want to perform JTI as soon as possible if necessary.  If rate is NOT matched, it will soon
555      figure it out and change settings */
556   bool bRateMatched = true;
557   /* get raw dSTC (does not include PCR Offsets etc) */
558   int32_t iDeltaSTC = pLocalState->uiStcSnapshot - hXdmPP->stDMState.stDecode.uiLastStcSnapshot;
559
560   if ( true == hXdmPP->stDMConfig.stClockOverride.bEnableClockOverride )
561   {
562      /* SW7425-1264: this is a bit heavy handed, but for now assume that when the SW STC
563       * is being used, the system is in a STC trick mode and the rates do not match.
564       */
565      bRateMatched = false;
566   }
567   else if (hXdmPP->stDMConfig.bSTCValid == false)
568   {
569      /* STC not yet valid, so can't determine avg. dSTC */
570      bRateMatched = hXdmPP->stDMState.stDecode.bRateMatchedLastReported;
571   }
572   else if (iDeltaSTC > 0)
573   {
574      /* STC is advancing ... */
575      BXDM_PPFP_P_DataType * pstDeltaSTCAvg = &(pLocalState->stDeltaSTCAvg);
576      uint32_t * puiNumSamples = &(pLocalState->uiNumSTCSamples);
577      BXDM_PPFP_P_DataType stDeltaPTSAvg;
578      BXDM_PPFP_P_DataType stDiff;
579      uint32_t uiHi, uiLo;
580
581      /* determine Average dSTC ... */
582      BXDM_PPAVG_P_AddValueInteger(hXdmPP->stDMState.stChannel.hDeltaSTCAvg, iDeltaSTC);
583      BXDM_PPAVG_P_GetAverage(hXdmPP->stDMState.stChannel.hDeltaSTCAvg, pstDeltaSTCAvg, puiNumSamples);
584
585      /* NOTE: Don't do FixPtDiv until at least ONE picture is accounted for (else divide-by-zero error!). */
586      if ((*puiNumSamples < BXDM_PictureProvider_P_RATE_MATCH_DETECTION_SAMPLES)
587            || (hXdmPP->stDMState.stDecode.stFRDStats.uiDeltaPTSCount == 0))
588         /* not enough samples to get a stable average */
589         return bRateMatched;
590
591      /* determine Average dPTS (using FRD parameters) ... */
592      BXDM_PPFP_P_FixPtDiv(
593               &hXdmPP->stDMState.stDecode.stFRDStats.stDeltaPTSRunningSum,
594               hXdmPP->stDMState.stDecode.stFRDStats.uiDeltaPTSCount,
595               &stDeltaPTSAvg
596               );
597
598      /* determine the difference between Avg. dPTS and Avg. dSTC ... */
599      /* since there is a flaw in the Fixed point math, determine which is larger, then subtract to ensure result is positive */
600      if ((stDeltaPTSAvg.uiWhole > pstDeltaSTCAvg->uiWhole)
601         || ((stDeltaPTSAvg.uiWhole == pstDeltaSTCAvg->uiWhole) && (stDeltaPTSAvg.uiFractional > pstDeltaSTCAvg->uiFractional)))
602      {
603         /* Avg PTS > Avg STC */
604         BXDM_PPFP_P_FixPtSub(&stDeltaPTSAvg, pstDeltaSTCAvg, &stDiff);
605         /* determine 0.05% of dSTC */
606         uiHi = pstDeltaSTCAvg->uiWhole >> 11;
607         uiLo = (pstDeltaSTCAvg->uiFractional >> 11) | ((pstDeltaSTCAvg->uiWhole & 0x7FF) << 5);
608         /* rate matched if diff <= 0.05% of dSTC */
609      }
610      else
611      {
612         /* Avg PTS <= Avg PTS */
613         BXDM_PPFP_P_FixPtSub(pstDeltaSTCAvg, &stDeltaPTSAvg, &stDiff);
614         /* determine 0.05% of dPTS */
615         uiHi = stDeltaPTSAvg.uiWhole >> 11;
616         uiLo = (stDeltaPTSAvg.uiFractional >> 11) | ((stDeltaPTSAvg.uiWhole & 0x7FF) << 5);
617         /* rate matched if diff <= 0.05% of dPTS */
618      }
619      bRateMatched = (stDiff.uiWhole <= uiHi) && ((stDiff.uiWhole != uiHi) || (stDiff.uiFractional <= uiLo));
620
621#if 0
622      BKNI_Printf("Avg dPTS: %d.%d [%03d], Avg dSTC: %d.%d [%03d] (%smatched)\n",
623         stDeltaPTSAvg.uiWhole,
624         stDeltaPTSAvg.uiFractional,
625         hXdmPP->stDMState.stDecode.stFRDStats.uiDeltaPTSCount,
626         pstDeltaSTCAvg->uiWhole,
627         pstDeltaSTCAvg->uiFractional,
628         uiNumSamples,
629         (bRateMatched)?"":"not ");
630#endif
631      /* TODO: Nilesh says rate is also considered to be matched if they are integer multiples of each other.
632         e.g. 30fps progressive is rate-matched to 60Hz display (dPTS = 2 * dSTC) */
633   }
634   else
635   {
636      /* else, STC not advancing (or there is a discontinuity - i.e. stream has "wrapped"), so cannot be rate matched */
637      bRateMatched = false;
638   }
639
640   hXdmPP->stDMState.stDecode.bRateMatchedLastReported = bRateMatched;
641   return bRateMatched;
642}
643
644static void BXDM_PP_S_STCTrickModeDetection(
645   BXDM_PictureProvider_Handle hXdmPP,
646   BXDM_PictureProvider_P_LocalState* pLocalState
647   )
648{
649   pLocalState->eSTCTrickMode = BXDM_PictureProvider_P_STCTrickMode_eOff;
650   pLocalState->stEffectiveSTCDelta[BXDM_PictureProvider_DisplayMode_eTSM] = pLocalState->stSTCDelta;
651   pLocalState->stEffectiveSTCDelta[BXDM_PictureProvider_DisplayMode_eVirtualTSM] = pLocalState->stSTCDelta;
652
653   if ( true == hXdmPP->stDMConfig.stClockOverride.bEnableClockOverride )
654   {
655      /*
656       * SW7425-1264: set the STC trick mode based on the sign and magnitude of "stClockOverride.iStcDelta".
657       */
658      if ( hXdmPP->stDMConfig.stClockOverride.iStcDelta == 0 )
659      {
660         pLocalState->eSTCTrickMode = BXDM_PictureProvider_P_STCTrickMode_ePause;
661
662         pLocalState->stSTCDelta.uiWhole = hXdmPP->stDMConfig.stClockOverride.iStcDelta;
663      }
664      else if ( hXdmPP->stDMConfig.stClockOverride.iStcDelta < 0 )
665      {
666         uint32_t uiTempStcDelta;
667
668         uiTempStcDelta = -hXdmPP->stDMConfig.stClockOverride.iStcDelta;
669
670         if ( uiTempStcDelta < pLocalState->stSTCDelta.uiWhole )
671            pLocalState->eSTCTrickMode = BXDM_PictureProvider_P_STCTrickMode_eSlowRewind;
672         else
673            pLocalState->eSTCTrickMode = BXDM_PictureProvider_P_STCTrickMode_eFastRewind;
674
675         pLocalState->stSTCDelta.uiWhole = uiTempStcDelta;
676      }
677      else
678      {
679         if ( (uint32_t)hXdmPP->stDMConfig.stClockOverride.iStcDelta < pLocalState->stSTCDelta.uiWhole )
680            pLocalState->eSTCTrickMode = BXDM_PictureProvider_P_STCTrickMode_eSlowMotion;
681         else
682            pLocalState->eSTCTrickMode = BXDM_PictureProvider_P_STCTrickMode_eFastForward;
683
684         pLocalState->stSTCDelta.uiWhole = hXdmPP->stDMConfig.stClockOverride.iStcDelta;
685      }
686
687      /*  SW7425-1264: "stClockOverride.iStcDelta" is a whole number, clear the fractional component of "stSTCDelta".
688       */
689      pLocalState->stSTCDelta.uiFractional = 0;
690
691      pLocalState->stEffectiveSTCDelta[BXDM_PictureProvider_DisplayMode_eTSM] = pLocalState->stSTCDelta;
692      pLocalState->stEffectiveSTCDelta[BXDM_PictureProvider_DisplayMode_eVirtualTSM] = pLocalState->stSTCDelta;
693
694      hXdmPP->stDMState.stDecode.eLastCalculatedSTCTrickMode = pLocalState->eSTCTrickMode;
695
696   }
697   else if ( ( BXDM_PictureProvider_DisplayMode_eTSM == pLocalState->eDisplayMode ) /* In TSM mode */
698            && ( true == hXdmPP->stDMState.stDecode.bLastStcValid ) /* Last STC was valid */
699            && ( true == hXdmPP->stDMConfig.bSTCValid ) /* Current STC is valid */
700           )
701   {
702      int32_t iDeltaStcDiff;
703      uint32_t uiDeltaStcDiffAbs;
704      BXDM_PictureProvider_P_STCTrickMode eCalculatedSTCTrickMode = pLocalState->eSTCTrickMode;
705
706      /* Note: the following can only be NOT true if stream wrap occurs ... */
707      if ( pLocalState->uiStcSnapshot >= hXdmPP->stDMState.stDecode.uiLastStcSnapshot )
708      {
709         pLocalState->stEffectiveSTCDelta[BXDM_PictureProvider_DisplayMode_eTSM].uiWhole = pLocalState->uiStcSnapshot - hXdmPP->stDMState.stDecode.uiLastStcSnapshot;
710         pLocalState->stEffectiveSTCDelta[BXDM_PictureProvider_DisplayMode_eTSM].uiFractional = 0;
711
712         if ( pLocalState->stEffectiveSTCDelta[BXDM_PictureProvider_DisplayMode_eTSM].uiWhole == 0 )
713         {
714            /* The STC has not changed, so we're in an STC pause */
715            eCalculatedSTCTrickMode = BXDM_PictureProvider_P_STCTrickMode_ePause;
716            BXVD_DBG_MSG(hXdmPP,("%x: STC Pause Detected", hXdmPP->stDMState.stDecode.stDebug.uiVsyncCount) );
717         }
718         else
719         {
720            if (pLocalState->stEffectiveSTCDelta[BXDM_PictureProvider_DisplayMode_eTSM].uiWhole >= pLocalState->stSTCDelta.uiWhole)
721            {
722               uiDeltaStcDiffAbs = pLocalState->stEffectiveSTCDelta[BXDM_PictureProvider_DisplayMode_eTSM].uiWhole - pLocalState->stSTCDelta.uiWhole;
723               iDeltaStcDiff = uiDeltaStcDiffAbs;
724            }
725            else
726            {
727               uiDeltaStcDiffAbs = pLocalState->stSTCDelta.uiWhole - pLocalState->stEffectiveSTCDelta[BXDM_PictureProvider_DisplayMode_eTSM].uiWhole;
728               iDeltaStcDiff = -uiDeltaStcDiffAbs;
729            }
730
731            if ( uiDeltaStcDiffAbs <= pLocalState->uiSTCJitterThreshold )
732            {
733               /* The STC is within +/- of the STC jitter threshold, so
734                * we're not in an STC trick mode */
735               eCalculatedSTCTrickMode = BXDM_PictureProvider_P_STCTrickMode_eOff;
736
737               /* SW7601-179: We set the effective STC delta to the
738                * expected STC delta to prevent any issues with STC
739                * jitter when using the effective STC delta (e.g. for
740                * computing the display duration for the currently
741                * selected picture) */
742               pLocalState->stEffectiveSTCDelta[BXDM_PictureProvider_DisplayMode_eTSM] = pLocalState->stSTCDelta;
743
744            }
745            else if ( iDeltaStcDiff < 0 )
746            {
747               /* The STC has incremented slower than expected, so we
748                * are in STC slow motion */
749               eCalculatedSTCTrickMode = BXDM_PictureProvider_P_STCTrickMode_eSlowMotion;
750               BXVD_DBG_MSG(hXdmPP,("%x: STC Slow Motion Detected", hXdmPP->stDMState.stDecode.stDebug.uiVsyncCount));
751            }
752            else if ( iDeltaStcDiff > 0 )
753            {
754               /* The STC has incremented faster than expected, so we
755                * are in STC fast forward */
756               eCalculatedSTCTrickMode = BXDM_PictureProvider_P_STCTrickMode_eFastForward;
757               BXVD_DBG_MSG(hXdmPP,("%x: STC Fast Forward Detected", hXdmPP->stDMState.stDecode.stDebug.uiVsyncCount));
758            }
759         }
760      }
761      pLocalState->eSTCTrickMode = eCalculatedSTCTrickMode;
762
763      /* PR54680: We need to differentiate between "pause -> frame
764       * advance -> pause" and pause -> normal/fast forward cases.  We
765       * assume we're in a frame advance until we determine that we're
766       * in a normal/fast forward for more than 2 vsyncs in a row. */
767      if ( ( BXDM_PictureProvider_P_STCTrickMode_ePause == hXdmPP->stDMState.stDecode.eLastReportedSTCTrickMode ) /* In pause last vsync */
768           && ( ( BXDM_PictureProvider_P_STCTrickMode_eFastForward == pLocalState->eSTCTrickMode ) /* We seem to be in fast forward or normal on this vsync */
769                || ( BXDM_PictureProvider_P_STCTrickMode_eOff == pLocalState->eSTCTrickMode ) ) )
770      {
771         if ( pLocalState->eSTCTrickMode != hXdmPP->stDMState.stDecode.eLastCalculatedSTCTrickMode )
772         {
773            /* We haven't calculated the same STC trick mode for 2
774             * vsyncs in a row, so override the reported stc trick
775             * mode to be the same as the previous vsync */
776            BXVD_DBG_MSG(hXdmPP, ("%x: STC Trick Mode Override (%d -> %d)",
777                                       hXdmPP->stDMState.stDecode.stDebug.uiVsyncCount,
778                                       pLocalState->eSTCTrickMode,
779                                       hXdmPP->stDMState.stDecode.eLastReportedSTCTrickMode
780                                 ));
781            pLocalState->eSTCTrickMode = hXdmPP->stDMState.stDecode.eLastReportedSTCTrickMode;
782         }
783      }
784      hXdmPP->stDMState.stDecode.eLastCalculatedSTCTrickMode = eCalculatedSTCTrickMode;
785   }
786   else
787   {
788      hXdmPP->stDMState.stDecode.eLastCalculatedSTCTrickMode = pLocalState->eSTCTrickMode;
789   }
790   hXdmPP->stDMState.stDecode.eLastReportedSTCTrickMode = pLocalState->eSTCTrickMode;
791}
792
793static void BXDM_PP_S_SnapShotXvdState(
794   BXDM_PictureProvider_Handle hXdmPP,
795   BXDM_PictureProvider_P_LocalState* pLocalState
796   )
797{
798   bool bRateMatched = false;
799
800   BDBG_ENTER(BXDM_PP_S_SnapShotXvdState);
801
802   /* Operate in VSYNC mode if the application has set the "DisplayMode"
803    * to VSYNC or if either CRC or DQT mode has been enabled.
804    */
805   if ( BXDM_PictureProvider_DisplayMode_eVirtualTSM == hXdmPP->stDMConfig.eDisplayMode
806         || true == hXdmPP->stDMConfig.bCRCMode
807      )
808   {
809      pLocalState->eDisplayMode = BXDM_PictureProvider_DisplayMode_eVirtualTSM;
810
811      /* Don't perform "preroll" if in vsync mode. */
812      hXdmPP->stDMState.stDecode.bPreRolling = false;
813   }
814   else
815   {
816      pLocalState->eDisplayMode = BXDM_PictureProvider_DisplayMode_eTSM;
817   }
818   /* Set global picture selection mode equal to the display mode by
819    * default */
820   pLocalState->eSelectionMode = pLocalState->eDisplayMode;
821
822   /* Determine if a decoder trick mode is enabled */
823   pLocalState->uiSlowMotionRate = BXDM_PICTUREPROVIDER_NORMAL_PLAYBACK_RATE;
824
825   if ( 0 == hXdmPP->stDMConfig.stPlaybackRate.uiNumerator  )
826   {
827      pLocalState->uiSlowMotionRate = 0;
828   }
829   else if ( BXDM_PICTUREPROVIDER_NORMAL_PLAYBACK_RATE != hXdmPP->stDMState.stDecode.uiPreRollPlaybackRate
830            && true == hXdmPP->stDMState.stDecode.bPreRolling )
831   {
832      /* If "prerolling",  use the preroll rate as a slow motion rate. */
833      pLocalState->uiSlowMotionRate = hXdmPP->stDMState.stDecode.uiPreRollPlaybackRate;
834   }
835   else if ( hXdmPP->stDMConfig.stPlaybackRate.uiNumerator != hXdmPP->stDMConfig.stPlaybackRate.uiDenominator )
836   {
837      pLocalState->uiSlowMotionRate = (hXdmPP->stDMConfig.stPlaybackRate.uiNumerator * BXDM_PICTUREPROVIDER_NORMAL_PLAYBACK_RATE) / hXdmPP->stDMConfig.stPlaybackRate.uiDenominator;
838   }
839
840   /* Set selection mode to VSYNC if we're in a decoder or vsync trick mode. */
841   if ( BXDM_PICTUREPROVIDER_NORMAL_PLAYBACK_RATE != pLocalState->uiSlowMotionRate )
842   {
843      /* We're in a decoder or vsync trick mode */
844      pLocalState->eSelectionMode = BXDM_PictureProvider_DisplayMode_eVirtualTSM;
845      hXdmPP->stDMState.stChannel.stSelectedPicture.stPicParms.stTSM.stDynamic.eSelectionMode = BXDM_PictureProvider_DisplayMode_eVirtualTSM;
846
847      /* PR50235: We invalidate the STC when in a decoder or vsync trick mode.
848       * One result of this action is that "bForcePtsError" will be set
849       * to "true" upon exiting trick mode.
850       *
851       * Only invalidate the STC if the following are true.
852       * - have not already transistioned into trick mode, i.e. only set
853       *   the flag to false once
854       * - not in preroll mode (looking for TSM lock to exit preroll)
855       * - in playback mode
856       */
857      if ( false == hXdmPP->stDMState.stDecode.bPreviousVsyncWasTrickMode
858          && false == hXdmPP->stDMState.stDecode.bPreRolling
859          && true == hXdmPP->stDMConfig.bPlayback )
860      {
861         BXDM_PictureProvider_SetSTCValid_isr(hXdmPP, false);
862      }
863
864      /* We keep track of when we're in VSYNC mode to detect
865       * transitions from VSYNC --> TSM mode and handle features such
866       * as bAutoValidateStcOnPause */
867      hXdmPP->stDMState.stDecode.bPreviousVsyncWasTrickMode = true;
868   }
869   else
870   {
871      /* We're not in a decoder trick mode */
872
873      /* Reset the default frame advance mode */
874      hXdmPP->stDMConfig.eFrameAdvanceMode = BXDM_PictureProvider_FrameAdvanceMode_eOff;
875      hXdmPP->stDMConfig.uiFrameAdvanceByFieldCount = 0;
876
877      if ( (BXDM_PictureProvider_DisplayMode_eTSM == pLocalState->eDisplayMode)
878           && hXdmPP->stDMState.stDecode.bPreviousVsyncWasTrickMode
879         )
880      {
881         /* TSM mode transition: trick -> play (i.e. exit trick mode) ... */
882         BXDM_PictureProvider_P_Picture_Context *pstPictureUnderEvaluation;
883
884         /* SW7405-3895:
885               if STC not valid
886                  if RequestSTC handler installed
887                     re-enable STC handler
888                  else
889                     force PTS error */
890         if (false == hXdmPP->stDMConfig.bSTCValid)
891         {
892            /* STC is not valid, so request an update from the app ... */
893            if (NULL != hXdmPP->stCallbacks[BXDM_PictureProvider_Callback_eRequestSTC].stFunction.fRequestSTC)
894            {
895               /* RequestSTC handler is installed, so re-enable RequestSTC callback ... */
896               hXdmPP->stCallbacks[BXDM_PictureProvider_Callback_eRequestSTC].bEnable = true;
897            }
898            else
899            {
900               /* We force a PTS error callback when we first transition
901                * from trick mode --> play so that the app can set the STC
902                * accordingly */
903               /* SW7405-4563: Only force the PTS Error if a valid coded PTS
904                  has been seen.  If no valid PTS has been seen, it is assumed
905                  that this transition occurs due to decoder flush, and hence
906                  FirstPTSReady will be triggered (when appropriate) instead. */
907               if (true == hXdmPP->stDMState.stDecode.bFirstCodedPtsReceived)
908                  pLocalState->bForcePtsError = true;
909            }
910         }
911         /* else, STC is valid, so do nothing (TSM evaluation will proceed as normal) */
912
913         if ( true == hXdmPP->stDMConfig.bAutoValidateStcOnPause )
914         {
915            /* PR50235: bAutoValidateStcOnPause - If we're in TSM
916             * mode, and the auto validate stc on pause feature is
917             * enabled, and the previous vsync was a decoder trick
918             * mode, and the current vsync is not a trick mode, we
919             * enable auto STC validation */
920            hXdmPP->stDMState.stDecode.bAutoValidateStc = true;
921         }
922
923         /* Reset the selection mode for the picture under evaluation.
924          * If the picture under evaluation was looked at during the
925          * previous vsync, which was a trick mode, then it's
926          * selection mode will be VSYNC mode.  We want to reset it if
927          * we're exiting trick mode.  If we don't then the picture
928          * may advance for one frame and pause briefly (stutter)
929          * until the actual TSM passed on the next picture.  */
930         pstPictureUnderEvaluation = BXDM_PPQM_P_GetFirstPictureContext(hXdmPP);
931            pstPictureUnderEvaluation->stPicParms.stTSM.stDynamic.eSelectionMode = pLocalState->eSelectionMode;
932
933         hXdmPP->stDMState.stChannel.stSelectedPicture.stPicParms.stTSM.stDynamic.eSelectionMode = pLocalState->eSelectionMode;
934
935         BXDM_PPFIC_P_ResetFieldInversionCorrectionOffset(
936            hXdmPP,
937            pLocalState);
938
939         BXDM_PPCLIP_P_ClipTimeTrickModeTransitionHandler(
940            hXdmPP,
941            pLocalState);
942
943         BXDM_PPVTSM_P_ClipTimeTrickModeTransitionHandler(
944            hXdmPP,
945            pLocalState);
946
947         /* We need to update bPreviousVsyncWasTrickMode at the END of
948          * this code block because the flag is used to determine if a
949          * trick mode transition has occurred, so we don't want to
950          * reset it until the previous value has been evaluated */
951         hXdmPP->stDMState.stDecode.bPreviousVsyncWasTrickMode = false;
952      }
953   }
954
955   /* Determine the clock rate */
956   if ( (BAVC_VideoCompressionStd_eMPEG2DTV == hXdmPP->stDMConfig.eProtocol)
957        || (BAVC_VideoCompressionStd_eMPEG2_DSS_PES == hXdmPP->stDMConfig.eProtocol)
958      )
959   {
960      pLocalState->eClockRate = BXDM_PictureProvider_P_ClockRate_eDirecTV;
961   }
962   else
963   {
964      pLocalState->eClockRate = BXDM_PictureProvider_P_ClockRate_eMPEG2;
965   }
966
967   /* Determine the expected delta STC for the specified monitor rate */
968   /* NOTE: a monitor rate of "unknown" cannot occur via the configuration API.  See BXDM_PictureProvider_SetMonitorRefreshRate_isr */
969   pLocalState->stSTCDelta = sDeltaStcLUT[pLocalState->eClockRate][hXdmPP->stDMConfig.eMonitorRefreshRate];
970
971   bRateMatched = BXDM_PP_S_RateMatchDetection(
972      hXdmPP,
973      pLocalState);
974
975   pLocalState->uiSTCJitterThreshold = BXDM_PictureProvider_P_STC_JITTER_THRESHOLD;
976   if ( BXDM_PictureProvider_P_ClockRate_eDirecTV == pLocalState->eClockRate )
977   {
978      pLocalState->uiSTCJitterThreshold *= 600;
979   }
980
981   /* Determine if we're in an STC trick mode */
982   BXDM_PP_S_STCTrickModeDetection(hXdmPP, pLocalState);
983
984   hXdmPP->stDMState.stDecode.uiLastStcSnapshot = pLocalState->uiStcSnapshot;
985   hXdmPP->stDMState.stDecode.bLastStcValid = ( true == hXdmPP->stDMConfig.bSTCValid );
986
987   /* SW7405-5043: JTI should be applied for STC trick modes also, since for example 50p content on a 60Hz
988      display will rate match when an STC trick rate of 1.2 is applied
989      This correction will NOT activate for STC pause, since this cannot be rate-matched */
990
991   /* SW7405-3358: Adjust STC snapshot to move (STC-PTS)
992    * away from 0 and deltaPTS so that STC/PTS jitter
993    * doesn't affect the scan cadence */
994   if ( ( true == hXdmPP->stDMConfig.bJitterToleranceImprovement )
995        && ( true == hXdmPP->stDMState.stChannel.stPreviousPicture.bValidated )
996        && ( false == hXdmPP->stDMState.stChannel.stPreviousPicture.stPicParms.stDisplay.stDynamic.bPPBRepeated )
997        /* Picture was selected in TSM mode */
998        && ( BXDM_PictureProvider_DisplayMode_eTSM == hXdmPP->stDMState.stChannel.stPreviousPicture.stPicParms.stTSM.stDynamic.eSelectionMode )
999        /* The dStcPts is within the jitter threshold */
1000        && ( hXdmPP->stDMState.stChannel.stPreviousPicture.stPicParms.stTSM.stDynamic.iStcPtsDifferenceEvaluated >= 0 )
1001        && ( ( hXdmPP->stDMState.stChannel.stPreviousPicture.stPicParms.stTSM.stDynamic.iStcPtsDifferenceEvaluated < (int32_t) pLocalState->uiSTCJitterThreshold )
1002             || ( ( hXdmPP->stDMState.stChannel.stPreviousPicture.stPicParms.stTSM.stDynamic.iStcPtsDifferenceEvaluated <= (int32_t) hXdmPP->stDMState.stChannel.stPreviousPicture.stPicParms.stTSM.stStatic.stPTSDelta.uiWhole )
1003                  && ( ( hXdmPP->stDMState.stChannel.stPreviousPicture.stPicParms.stTSM.stStatic.stPTSDelta.uiWhole - hXdmPP->stDMState.stChannel.stPreviousPicture.stPicParms.stTSM.stDynamic.iStcPtsDifferenceEvaluated ) < pLocalState->uiSTCJitterThreshold ) ) )
1004        && ( true == bRateMatched )
1005      )
1006    {
1007      if ( 0 == hXdmPP->stDMState.stDecode.iStcJitterCorrectionOffset )
1008      {
1009         BXVD_DBG_WRN(hXdmPP, ("%x: Adding STC jitter correction offset (dStcPts = %d/%d, stc=%08x)",
1010                                    hXdmPP->stDMState.stDecode.stDebug.uiVsyncCount,
1011                                    hXdmPP->stDMState.stChannel.stPreviousPicture.stPicParms.stTSM.stDynamic.iStcPtsDifferenceEvaluated,
1012                                    hXdmPP->stDMState.stChannel.stPreviousPicture.stPicParms.stTSM.stDynamic.iStcPtsDifferenceActual,
1013                                    pLocalState->uiStcSnapshot
1014                              ));
1015         hXdmPP->stDMState.stDecode.iStcJitterCorrectionOffset = -(4*pLocalState->uiSTCJitterThreshold);
1016      }
1017      else
1018      {
1019         BXVD_DBG_WRN(hXdmPP, ("%x: Removing STC jitter correction offset (dStcPts = %d/%d, stc=%08x)",
1020                                    hXdmPP->stDMState.stDecode.stDebug.uiVsyncCount,
1021                                    hXdmPP->stDMState.stChannel.stPreviousPicture.stPicParms.stTSM.stDynamic.iStcPtsDifferenceEvaluated,
1022                                    hXdmPP->stDMState.stChannel.stPreviousPicture.stPicParms.stTSM.stDynamic.iStcPtsDifferenceActual,
1023                                    pLocalState->uiStcSnapshot
1024                              ));
1025         hXdmPP->stDMState.stDecode.iStcJitterCorrectionOffset = 0;
1026      }
1027    }
1028
1029   /* SW7405-3358: Apply STC Snapshot offset AFTER we record the
1030    * original value so that we don't disturb the STC trick mode
1031    * detection */
1032   pLocalState->uiAdjustedStc = pLocalState->uiStcSnapshot + hXdmPP->stDMState.stDecode.iStcJitterCorrectionOffset;
1033
1034   /* PR56325: Try to detect an incorrect monitor refresh rate setting and print a warning */
1035   if ( ( false == hXdmPP->stDMConfig.bPlayback ) /* In live mode */
1036        && ( BXDM_PictureProvider_P_STCTrickMode_eOff != pLocalState->eSTCTrickMode )
1037      )
1038   {
1039      /* SW7405-3113: Add 30 vsync hysteresis to incorrect monitor refresh rate
1040       * setting to prevent false detection during display reconfiguration
1041       * (e.g. 1080i to 720p).
1042       */
1043      hXdmPP->stDMState.stDecode.ui32IncorrectMonitorRefreshRateCount++;
1044
1045      if ( hXdmPP->stDMState.stDecode.ui32IncorrectMonitorRefreshRateCount > 30 )
1046      {
1047         if ( hXdmPP->stDMState.stDecode.eLastIncorrectMonitorRefreshRate != hXdmPP->stDMConfig.eMonitorRefreshRate )
1048         {
1049            BXVD_DBG_WRN(hXdmPP, ("%x: The STC advanced by an unexpected amount since the previous vsync (%d ticks instead of %d ticks). The monitor refresh rate (%08x) may not be set correctly!",
1050                     hXdmPP->stDMState.stDecode.stDebug.uiVsyncCount,
1051                     pLocalState->stEffectiveSTCDelta[BXDM_PictureProvider_DisplayMode_eTSM].uiWhole,
1052                     pLocalState->stSTCDelta.uiWhole,
1053                     hXdmPP->stDMConfig.eMonitorRefreshRate));
1054            hXdmPP->stDMState.stDecode.eLastIncorrectMonitorRefreshRate = hXdmPP->stDMConfig.eMonitorRefreshRate;
1055         }
1056      }
1057   }
1058   else
1059   {
1060      hXdmPP->stDMState.stDecode.ui32IncorrectMonitorRefreshRateCount = 0;
1061   }
1062
1063   /* Set the vSTC on this vsync */
1064   BXDM_PPVTSM_P_VirtualStcIncrement(
1065      hXdmPP,
1066      pLocalState
1067      );
1068
1069   /* We set the repeated flags in the selected PPB to true on every
1070    * vsync, because they are changed by picture/element selection
1071    * accordingly */
1072   hXdmPP->stDMState.stChannel.stSelectedPicture.stPicParms.stDisplay.stDynamic.bPPBRepeated = true;
1073   hXdmPP->stDMState.stChannel.stSelectedPicture.stPicParms.stDisplay.stDynamic.bElementRepeated = true;
1074
1075   /* Add to the currently displayed PPB's display duration */
1076   BXDM_PPFP_P_FixPtAdd(
1077      &hXdmPP->stDMState.stChannel.stSelectedPicture.stPicParms.stDisplay.stDynamic.stDisplayDuration,
1078      &pLocalState->stEffectiveSTCDelta[hXdmPP->stDMState.stChannel.stSelectedPicture.stPicParms.stTSM.stDynamic.eSelectionMode],
1079      &hXdmPP->stDMState.stChannel.stSelectedPicture.stPicParms.stDisplay.stDynamic.stDisplayDuration
1080      );
1081
1082   /* Reset the picture's local SPIM mode if the global SPIM is
1083    * "both" */
1084   if ( hXdmPP->stDMState.stChannel.stSelectedPicture.stPicParms.stDisplay.stDynamic.eSourceFormatOverride != BXDM_PictureProvider_SourceFormatOverride_eProgressive )
1085   {
1086      hXdmPP->stDMState.stChannel.stSelectedPicture.stPicParms.stDisplay.stDynamic.eSourceFormatOverride = hXdmPP->stDMConfig.eSourceFormatOverride;
1087   }
1088
1089   BDBG_LEAVE(BXDM_PP_S_SnapShotXvdState);
1090   return;
1091} /* end of BXDM_PP_S_SnapShotXvdState() */
1092
1093static void BXDM_PP_S_SnapShotFirmwareState(
1094   BXDM_PictureProvider_Handle hXdmPP,
1095   BXDM_PictureProvider_P_LocalState* pLocalState,
1096   const BXDM_DisplayInterruptInfo *pstDisplayInterruptInfo
1097   )
1098{
1099   BDBG_ENTER(BXDM_PP_S_SnapShotFirmwareState);
1100
1101   pLocalState->eVsyncPolarity = pstDisplayInterruptInfo->eInterruptPolarity;
1102
1103   /* SW7405-3137: initially set "eInterruptType" assuming that VDC is expecting a single picture
1104    * to be delivered.
1105    * If the video protocol is "BAVC_VideoCompressionStd_eMVC", override "eInterruptType" based on
1106    * the interrupt polarity.  For now, assume that "BAVC_Polarity_eTopField" is the base interrupt
1107    * and "BAVC_Polarity_eBotField" is the dependent interrupt.  TODO: the interrupt masks should
1108    * be changed to base/dependent when playing MVC streams.
1109    */
1110   pLocalState->eInterruptType = BXDM_PictureProvider_P_InterruptType_eSingle;
1111   if (( BAVC_VideoCompressionStd_eMVC == hXdmPP->stDMConfig.eProtocol )
1112        && ( true == hXdmPP->stDMConfig.st3DSettings.bSetNextPointer ))
1113   {
1114      switch ( pLocalState->eVsyncPolarity )
1115      {
1116         case BAVC_Polarity_eTopField:
1117            pLocalState->eInterruptType = BXDM_PictureProvider_P_InterruptType_eBase;
1118            break;
1119
1120         case BAVC_Polarity_eBotField:
1121            pLocalState->eInterruptType = BXDM_PictureProvider_P_InterruptType_eDependent;
1122            break;
1123
1124         default:
1125            break;
1126      }
1127   }
1128
1129   if ( true == hXdmPP->stDMState.stDecode.bPreviousVsyncPolarityValid )
1130   {
1131      if ( ( BAVC_Polarity_eFrame != hXdmPP->stDMState.stDecode.ePreviousVsyncPolarity )
1132           && ( BAVC_Polarity_eFrame != pLocalState->eVsyncPolarity )
1133           && ( hXdmPP->stDMState.stDecode.ePreviousVsyncPolarity == pLocalState->eVsyncPolarity ) )
1134      {
1135         BXVD_DBG_WRN(hXdmPP,("%x: Same vsync polarity seen in a row", hXdmPP->stDMState.stDecode.stDebug.uiVsyncCount));
1136      }
1137   }
1138   hXdmPP->stDMState.stDecode.bPreviousVsyncPolarityValid = true;
1139   hXdmPP->stDMState.stDecode.ePreviousVsyncPolarity = pLocalState->eVsyncPolarity;
1140
1141   BDBG_ASSERT( hXdmPP->stDMConfig.uiSTCIndex < pstDisplayInterruptInfo->uiSTCCount );
1142
1143   /* SW7425-1264: support for a synthesized STC; can create a clock that run backwards.
1144    * If enabled, use and interpolated the synthesized STC , otherwise use the HW STC.
1145    */
1146   if ( true == hXdmPP->stDMConfig.stClockOverride.bEnableClockOverride )
1147   {
1148      /* SW7425-1264: if a new SW STC value has been specified, load it at this time.*/
1149
1150      if ( true == hXdmPP->stDMConfig.bInitializeSwStc )
1151      {
1152         hXdmPP->stDMState.stChannel.uiSwStc = hXdmPP->stDMConfig.stClockOverride.uiStcValue;
1153         hXdmPP->stDMConfig.bInitializeSwStc = false;
1154      }
1155
1156      pLocalState->uiStcSnapshot = hXdmPP->stDMState.stChannel.uiSwStc;
1157
1158      /* Interpolate the SW STC. */
1159      hXdmPP->stDMState.stChannel.uiSwStc += hXdmPP->stDMConfig.stClockOverride.iStcDelta;
1160
1161   }
1162   else
1163   {
1164      pLocalState->uiStcSnapshot = pstDisplayInterruptInfo->astSTC[hXdmPP->stDMConfig.uiSTCIndex].uiValue;
1165   }
1166
1167   /* SW7405-3085: Channel Synchronization */
1168   pLocalState->uiDisplayInterruptCount = pstDisplayInterruptInfo->stInterruptCount.uiValue;
1169   pLocalState->bDisplayInterruptCountValid = pstDisplayInterruptInfo->stInterruptCount.bValid && hXdmPP->stDMConfig.bChannelSyncMode;
1170
1171   BDBG_LEAVE(BXDM_PP_S_SnapShotFirmwareState);
1172   return;
1173} /* end of BXDM_PP_S_SnapShotFirmwareState() */
1174
1175static void BXDM_PP_S_UpdatePublicStatus(
1176   BXDM_PictureProvider_Handle hXdmPP,
1177   BXDM_PictureProvider_P_LocalState* pLocalState
1178   )
1179{
1180   BXDM_PictureProvider_P_Picture_Context* pstPicCntxt;
1181   BXDM_PictureProvider_PTSInfo* pstCurPtsInfo;
1182
1183   BDBG_ENTER(BXDM_PP_S_UpdatePublicStatus);
1184
1185   pstPicCntxt = &(hXdmPP->stDMState.stChannel.stSelectedPicture);
1186
1187   pstCurPtsInfo = &(hXdmPP->stDMStatus.stCurrentPTS);
1188
1189   /* Update "stCurrentPTSInfo".
1190    * If a picture has been delivered to VDC, use that PTS data.
1191    * Otherwise use the most recently received coded PTS; the need for
1192    * this became apparent when debugging  the watch dog reset.  The
1193    * system had trouble dealing with a very large delta between the audio
1194    * and video PTS values.
1195    * Note: "bFirstPPBHasBeenDisplayed" simply means a picture has been
1196    * displayed.  It may or may not have passed the TSM test.
1197    */
1198   if ( true == hXdmPP->stDMState.stDecode.bFirstPPBHasBeenDisplayed )
1199   {
1200      /* PR53039: return the actual PTS value and type.
1201       *
1202       * After calling "BXVD_StopDecode()", the intent is to return the PTS value and type of
1203       * the last displayed picture until "BXVD_StartDecode()" is called.  However, the values
1204       * returned by "..._GetPts()" and "..._GetPtsType()" are qualified by "pstPicCntxt->bValidated".
1205       *
1206       * This presented a problem after "BXVD_StopDecode()" was called when the last picture
1207       * was not being "held".  Several vsync callbacks were processed before the decoder
1208       * stopped.  During that period, "stCurrentPTS.ui32RunningPTS" was being incorrectly
1209       * returned as "0" and "stCurrentPTS.ePTSType" as "BXDM_PictureProvider_PTSType_eInterpolatedFromInvalidPTS".
1210       */
1211      BXDM_PPQM_P_GetPtsUnfiltered(
1212            pstPicCntxt,
1213            BXDM_PictureProvider_P_PTSIndex_eActual,
1214            0,
1215            &(pstCurPtsInfo->ui32RunningPTS)
1216            );
1217
1218      BXDM_PPQM_P_GetPtsTypeUnfiltered( pstPicCntxt, &(pstCurPtsInfo->ePTSType) );
1219
1220      pstCurPtsInfo->ui32EffectivePTS = pstPicCntxt->stPicParms.stTSM.stDynamic.uiEffectivePTS[BXDM_PictureProvider_P_PTSIndex_eActual];
1221
1222      /* PR39962: save the PCR offset and associated flags for the picture being delivered to VDC. */
1223      pstCurPtsInfo->uiPCROffset = pstPicCntxt->stPicParms.stTSM.stStatic.stPCROffsetXDM.stPCROffsetCopy.uiValue;
1224      pstCurPtsInfo->bPcrOffsetValid = pstPicCntxt->stPicParms.stTSM.stStatic.stPCROffsetXDM.stPCROffsetCopy.bValid;
1225      pstCurPtsInfo->bPcrDiscontinuity = pstPicCntxt->stPicParms.stTSM.stStatic.stPCROffsetXDM.stPCROffsetCopy.bDiscontinuity;
1226   }
1227   else
1228   {
1229      *pstCurPtsInfo = hXdmPP->stDMState.stDecode.stLatestCodedPts;
1230   }
1231
1232   /* TODO: from DM V1, PR34979
1233    * Does this happen with the correct frequency, i.e. does it need to happen every vsync?
1234    */
1235   pstCurPtsInfo->uiDisplayManagerDroppedCount = hXdmPP->stDMStatus.stCounters.uiDisplayManagerDroppedCount;
1236   pstCurPtsInfo->uiPicturesDecodedCount = hXdmPP->stDMStatus.stCounters.uiPicturesDecodedCount;
1237
1238   /* PR39962: Save the STC for the picture being delivered to VDC. */
1239   pstCurPtsInfo->uiSTCSnapShot = pLocalState->uiAdjustedStc;
1240
1241   /* PR50623: Do the following need to be sampled on a per TSM evaluation basis? */
1242   pstCurPtsInfo->bUseHwPcrOffset = hXdmPP->stDMConfig.bUseHardwarePCROffset;
1243
1244   /* SW7635-51: if a picture has been displayed, report the associated
1245    * software PCR offset. Othewise use the "global" value.
1246    */
1247   if ( true == pstPicCntxt->stPicParms.stDisplay.stDynamic.bSwPcrOffsetValid  )
1248   {
1249      pstCurPtsInfo->uiSwPcrOffset = pstPicCntxt->stPicParms.stDisplay.stDynamic.uiSoftwarePCROffset;
1250   }
1251   else
1252   {
1253      pstCurPtsInfo->uiSwPcrOffset = hXdmPP->stDMConfig.uiSoftwarePCROffset;
1254   }
1255
1256   /* PR53013: Updated reported picture tag with the one from the
1257    * currently displayed picture */
1258   if ( ( true == pstPicCntxt->bValidated )
1259        && ( true == pstPicCntxt->pstUnifiedPicture->stPictureTag.bValid )
1260      )
1261   {
1262      hXdmPP->stDMStatus.uiPictureTag = pstPicCntxt->pstUnifiedPicture->stPictureTag.uiValue;
1263   }
1264
1265   /* PR54677: Update reported PPBParameterInfo */
1266   if ( true == pstPicCntxt->bValidated )
1267   {
1268      hXdmPP->stDMStatus.stCurrentPPBParameterInfo = *(pstPicCntxt->pstUnifiedPicture);
1269      hXdmPP->stDMStatus.bCurrentPPBParameterInfoValid = true;
1270   }
1271   else
1272   {
1273      hXdmPP->stDMStatus.bCurrentPPBParameterInfoValid = false;
1274   }
1275
1276   BDBG_LEAVE(BXDM_PP_S_UpdatePublicStatus);
1277
1278   return;
1279} /* end of BXDM_PP_S_UpdatePublicStatus() */
1280
1281static void
1282BXDM_PP_S_PostIsr(BXDM_PictureProvider_Handle hXdmPP,
1283                  BXDM_PictureProvider_P_LocalState* pLocalState,
1284                  bool bPrimaryPicture)
1285{
1286   uint32_t uiStateBits = hXdmPP->stDMState.stChannel.stSelectedPicture.stPicParms.uiStateBits;
1287
1288   BDBG_ENTER(BXDM_PP_S_PostIsr);
1289
1290   if ( true == bPrimaryPicture )
1291   {
1292      /* Keep track of previous PPB */
1293      hXdmPP->stDMState.stChannel.stPreviousPicture = hXdmPP->stDMState.stChannel.stSelectedPicture;
1294
1295      /* Save last evaluated Stc/Pts Offset */
1296      if ( false == hXdmPP->stDMState.stChannel.stSelectedPicture.stPicParms.stDisplay.stDynamic.bElementRepeated )
1297      {
1298         hXdmPP->stDMState.stDecode.iPreviousStcPtsDifferenceEvaluated
1299                  = hXdmPP->stDMState.stChannel.stPreviousPicture.stPicParms.stTSM.stDynamic.iStcPtsDifferenceEvaluated;
1300
1301         /* SWBLURAY-18143: In order for the clip stop time to be
1302          * triggered at the correct time, we need to assume the
1303          * picture's initial dStcPts as counting towards the display
1304          * duration.  This is needed specifically for 24p content
1305          * displayed at 60Hz where implicit 3:2 pulldown is applied and
1306          * the dStcPts oscillates between two values. */
1307         if ( false == hXdmPP->stDMState.stChannel.stSelectedPicture.stPicParms.stDisplay.stDynamic.bPPBRepeated )
1308         {
1309            hXdmPP->stDMState.stChannel.stSelectedPicture.stPicParms.stDisplay.stDynamic.stDisplayDuration.uiWhole
1310                     += hXdmPP->stDMState.stDecode.iPreviousStcPtsDifferenceEvaluated;
1311         }
1312      }
1313
1314      if ( hXdmPP->stDMState.stChannel.stSelectedPicture.bValidated )
1315      {
1316         /* We need to set the STCinvalid flag to false if ALL of the following are true:
1317          *
1318          * 1) We'e in LIVE mode AND
1319          * 2) The selected picture has a PCR that is not discontinuous
1320          * 3) The selected picture has a PCR that is valid
1321          *
1322          * In PLAYBACK mode, the STCinvalid flag is set to false by the
1323          * application after it jams the STC with the proper value.
1324          *
1325          */
1326         if ( !hXdmPP->stDMConfig.bPlayback
1327                  && !hXdmPP->stDMState.stChannel.stSelectedPicture.stPicParms.stTSM.stStatic.stPCROffsetXDM.bDiscontinuityOverloaded
1328                  && hXdmPP->stDMState.stChannel.stSelectedPicture.stPicParms.stTSM.stStatic.stPCROffsetXDM.bValidOverloaded )
1329         {
1330            if ( false == hXdmPP->stDMConfig.bSTCValid )
1331            {
1332               /* SW7405-4736: triggers the debug message the first time bSTCValid is set to true.
1333                */
1334               hXdmPP->stDMConfig.uiDirtyBits_1 |= BXDM_PictureProvider_P_DIRTY_1_STC_VALID;
1335            }
1336
1337            hXdmPP->stDMConfig.bSTCValid = true;
1338         }
1339      }
1340   }
1341
1342   /* SWBLURAY-22286: don't reloaded the virtual STC on the dependent interrupt. */
1343   if ( true == bPrimaryPicture )
1344   {
1345      /* vSTC tracks actual STC on every vsync (in TSM mode) */
1346      BXDM_PPVTSM_P_VirtualStcSet(hXdmPP, pLocalState);
1347   }
1348
1349   /* Keep track of various DM state for reporting */
1350   BXDM_PPDBG_P_DecoderDropLog(hXdmPP, hXdmPP->stDMState.stDecode.uiPendingDropCount);
1351
1352   switch ( pLocalState->eDisplayMode )
1353   {
1354      case BXDM_PictureProvider_DisplayMode_eVirtualTSM:
1355         uiStateBits |= BXDM_PPDBG_State_DisplayMode_VSYNC;
1356         break;
1357      case BXDM_PictureProvider_DisplayMode_eTSM:
1358         uiStateBits |= BXDM_PPDBG_State_DisplayMode_TSM;
1359         break;
1360      default:
1361         break;
1362   }
1363
1364   switch ( hXdmPP->stDMState.stChannel.stSelectedPicture.stPicParms.stTSM.stDynamic.eSelectionMode )
1365   {
1366      case BXDM_PictureProvider_DisplayMode_eVirtualTSM:
1367         uiStateBits |= BXDM_PPDBG_State_SelectionMode_VSYNC;
1368         break;
1369      case BXDM_PictureProvider_DisplayMode_eTSM:
1370         uiStateBits |= BXDM_PPDBG_State_SelectionMode_TSM;
1371         break;
1372      default:
1373         break;
1374   }
1375
1376   if ( true == hXdmPP->stDMState.stChannel.stSelectedPicture.stPicParms.stDisplay.stDynamic.bIgnoreCadenceMatch )
1377   {
1378      uiStateBits |= BXDM_PPDBG_State_IgnoreCadenceMatch;
1379   }
1380
1381   if ( hXdmPP->stDMState.stChannel.stSelectedPicture.stPicParms.stTSM.stStatic.stPCROffsetXDM.stPCROffsetCopy.bDiscontinuity )
1382   {
1383      uiStateBits |= BXDM_PPDBG_State_PCRDiscontinuity;
1384   }
1385
1386   if ( hXdmPP->stDMState.stChannel.stSelectedPicture.stPicParms.stTSM.stStatic.stPCROffsetXDM.stPCROffsetCopy.bValid )
1387   {
1388      uiStateBits |= BXDM_PPDBG_State_PCRPresent;
1389   }
1390
1391   if ( !hXdmPP->stDMConfig.bSTCValid )
1392   {
1393      uiStateBits |= BXDM_PPDBG_State_STCInvalid;
1394   }
1395
1396   if ( hXdmPP->stDMConfig.bUseHardwarePCROffset )
1397   {
1398      uiStateBits |= BXDM_PPDBG_State_UseHwPcrOffset;
1399   }
1400
1401   BXDM_PPDBG_P_StateLog(hXdmPP, uiStateBits);
1402
1403   /* SW7405-4736: conditionally dump the MFD structure */
1404   BXDM_PPDBG_P_PrintMFD( hXdmPP, pLocalState, &(hXdmPP->astMFDPicture[0]) );
1405
1406   /* SW7405-4736: look to print the input parameters now that we are all done.
1407    * Only those that have changed during the execution of this event handler will be printed.
1408    */
1409   BXDM_PPDBG_P_PrintDMConfig( hXdmPP, pLocalState, true );
1410
1411   /* We print the DM Debug logs */
1412   BXDM_PPDBG_P_Print(hXdmPP, pLocalState);
1413
1414   BDBG_LEAVE(BXDM_PP_S_PostIsr);
1415   return;
1416} /* end of BXDM_PP_S_PostIsr() */
1417
1418static void BXDM_PP_S_SelectPicture(
1419   BXDM_PictureProvider_Handle hXdmPP,
1420   BXDM_PictureProvider_P_LocalState* pLocalState
1421   )
1422{
1423   bool bDispQueueHasData = false;
1424   bool bFindNextPPB = true;
1425   bool bDisplayPPB = false;
1426   bool bDropPPB = false;
1427   bool bForceDisplayPPB = false;
1428   uint32_t uiLoopCount=0;
1429   BXDM_PictureProvider_P_Picture_Context *  pstPictureUnderEvaluation;
1430   BXDM_PictureProvider_P_Picture_Context *  pstPreviousPictureUnderEvaluation;
1431   BXDM_PictureProvider_P_Picture_Context *  pstSelectedPicture;
1432
1433   BXDM_PictureProvider_PTSInfo * pstNextPTSInfo;
1434
1435   BDBG_ENTER(BXDM_PP_S_SelectPicture);
1436
1437   pstPictureUnderEvaluation = BXDM_PPQM_P_GetFirstPictureContext(hXdmPP);
1438   pstPreviousPictureUnderEvaluation = &(hXdmPP->stDMState.stChannel.stPreviousPictureUnderEvaluation);
1439   pstSelectedPicture = &(hXdmPP->stDMState.stChannel.stSelectedPicture);
1440   pstNextPTSInfo = &(hXdmPP->stDMStatus.stNextPTS);
1441
1442   /* Previously the first time through the "while( bFindNextPPB )" loop,  the value of
1443    * stNextPTS.uiSTCSnapShot would be stale.  It contained uiAdjustedStc from the previous vsync. 
1444    * This might be an issue if BXDM_PictureProvider_GetNextPTSInfo_isr were called during the
1445    * execution of BXDM_PPTSM_P_EvaluateTsmState, say in response to the TSM result callback.  To get
1446    * around this problem, stNextPTS.uiSTCSnapShot in now updated before jumping into the loop.
1447    */
1448   pstNextPTSInfo->uiSTCSnapShot = pLocalState->uiAdjustedStc;
1449
1450   /* Re-display the current picture; re-evaluate TSM to select the
1451    * best element within the picture.
1452    */
1453   BXDM_PPTSM_P_EvaluateTsmState(
1454      hXdmPP,
1455      pLocalState,
1456      pstSelectedPicture
1457      );
1458
1459   if ( BXDM_PictureProvider_P_DecodeState_eStarted == hXdmPP->stDMState.stChannel.eDecodeState )
1460   {
1461      /* We select the best PPB in this loop.  If a new picture is not found,
1462       * the old one will continue to be displayed.
1463       */
1464      while ( bFindNextPPB )
1465      {
1466         BXDM_PPTMR_P_SnapshotFunctionStartTime( hXdmPP, BXDM_PPTIMER_P_Function_eSelPic1 );
1467
1468         /* By default:
1469          * 1) we do want the loop to wrap
1470          * 2) We don't want to display a new PPB
1471          * 3) We don't want to drop a new PPB
1472          */
1473         bDisplayPPB = false;
1474         bForceDisplayPPB = false;
1475         bDropPPB = false;
1476
1477         /*
1478         ** Update "pstPictureUnderEvaluation" with the data of the next picture in the display queue.
1479         ** If the display queue is empty, "bDispQueueHasData" will be set to false.
1480         */
1481         bDispQueueHasData = BXDM_PPQM_P_PeekAtNextPicture(
1482            hXdmPP,
1483            pLocalState,
1484            pstPictureUnderEvaluation,
1485            pstPreviousPictureUnderEvaluation,
1486            pstSelectedPicture
1487            );
1488
1489         if ( false == bDispQueueHasData )
1490         {
1491            pLocalState->bPictureQueueIsEmpty = true;
1492
1493            BXDM_PPDBG_P_SelectionLog( hXdmPP, BXDM_PPDBG_Selection_ePPBNotFound );
1494
1495            /* The delivery queue has underflowed if...
1496             * - this is the first time through the while loop on this vsync
1497             * - AND the first PPB has been displayed.
1498             */
1499            if ( 0 == uiLoopCount && true == hXdmPP->stDMState.stDecode.bFirstPPBHasBeenDisplayed )
1500            {
1501              hXdmPP->stDMStatus.stCounters.uiVsyncUnderflowCount++;
1502
1503               /* Count the number of times the system has gotten into an
1504                * underflow "state" (as opposed to the number of vsync's
1505                * with an underflow).
1506                */
1507               if ( false == hXdmPP->stDMState.stDecode.bDqUnderflowPrevVsync )
1508               {
1509                  hXdmPP->stDMStatus.stCounters.uiUnderflowCount++;
1510               }
1511
1512               hXdmPP->stDMState.stDecode.bDqUnderflowPrevVsync = true;
1513            }
1514
1515            /* Force a wait state, so that we re-display the current
1516             * picture */
1517            pstPictureUnderEvaluation->stPicParms.stTSM.stDynamic.eTsmResult = BXDM_PictureProvider_TSMResult_eWait;
1518
1519            /* Reset GetNextPTS() values since we don't have a "next"
1520             * picture in the queue */
1521            hXdmPP->stDMStatus.bNextPTSInfoValid = false;
1522            pstNextPTSInfo->ePTSType = BXDM_PictureProvider_PTSType_eInterpolatedFromInvalidPTS;
1523            pstNextPTSInfo->ui32RunningPTS = 0;
1524            pstNextPTSInfo->ui32EffectivePTS = 0;
1525            /* SW7425-875: pstNextPTSInfo->uiSTCSnapShot = pLocalState->uiAdjustedStc;*/
1526            pstNextPTSInfo->bPcrOffsetValid = false;
1527            pstNextPTSInfo->bPcrDiscontinuity = false;
1528
1529            /* We need to see if the decoder supports drop@decode */
1530            if ( ( NULL != hXdmPP->stDMConfig.stDecoderInterface.requestPictureDrop_isr )
1531                 && ( NULL != hXdmPP->stDMConfig.stDecoderInterface.getPictureDropPendingCount_isr )
1532               )
1533            {
1534            /* In an attempt to catch up, we start dropping late
1535             * pictures after XX consecutive "too late" results in a
1536             * row and the delivery queue is dry */
1537               if ( hXdmPP->stDMState.stDecode.uiPPBConsecutiveLateCount >= BXDM_PictureProvider_P_MAX_LATE_BEFORE_DECODER_DROP )
1538               {
1539                  /* Snapshot the start time. */
1540                  BXDM_PPTMR_P_SnapshotFunctionStartTime( hXdmPP, BXDM_PPTIMER_P_Function_eDecoderGetPictureDropPendingCountIsr );
1541
1542                  hXdmPP->stDMConfig.stDecoderInterface.getPictureDropPendingCount_isr(
1543                           hXdmPP->stDMConfig.pDecoderPrivateContext,
1544                           &hXdmPP->stDMState.stDecode.uiPendingDropCount
1545                           );
1546
1547                  /* Snapshot the end time. */
1548                  BXDM_PPTMR_P_SnapshotFunctionEndTime( hXdmPP, BXDM_PPTIMER_P_Function_eDecoderGetPictureDropPendingCountIsr );
1549
1550                  /* We've been late XX vsync in a row, so we try to recover
1551                   * by asking the decoder to drop pictures */
1552
1553                  /* We only request more drops if the decoder has caught up
1554                   * with the previous drop request */
1555                  if ( 0 == hXdmPP->stDMState.stDecode.uiPendingDropCount )
1556                  {
1557                     uint32_t uiNumToDrop = 0;
1558
1559                     /* We request dropping of fields such that after the
1560                     * decoder performs the drop the STC/PTS diff will be
1561                     * close to 0 */
1562                     uiNumToDrop = ( pstSelectedPicture->stPicParms.stTSM.stDynamic.iStcPtsDifferenceActual / pstSelectedPicture->stPicParms.stTSM.stStatic.stPTSDelta.uiWhole );
1563
1564                     /* SW7405-3925: For progressive content, uiNumToDrop value needs to be converted to fields since the decoder
1565                        always expects drop count in fields, yet the DeltaPTS yields a value in elements (hences uiNumToDrop is
1566                        half what it should be).
1567                        It also needs to account for the extended duration of the frames if pulldown is set to FX1...FX4
1568                        (e.g. if STC-PTS is 6000, and deltaPTS is 1500, this would indicate 4 elements (8 fields) need to be dropped,
1569                         but if pulldown is FX4, then we really only need to drop 1 element (2 fields) to achieve the desired catchup)
1570
1571                        Thus desired #fields to drop = uiNumToDrop (progressive elements) * 2 / #elements frame repeated
1572                     */
1573                     switch (pstSelectedPicture->pstUnifiedPicture->stBufferInfo.ePulldown)
1574                     {
1575                        case BXDM_Picture_PullDown_eFrameX4:
1576                           uiNumToDrop /= 2;
1577                           break;
1578                        case BXDM_Picture_PullDown_eFrameX3:
1579                           uiNumToDrop *= 2;
1580                           uiNumToDrop /= 3;
1581                           break;
1582                        case BXDM_Picture_PullDown_eFrameX2:
1583                           /* Do nothing - required #fields already correct due to artifical scaling introduced by deltaPTS
1584                              being in frames not fields */
1585                           break;
1586                        case BXDM_Picture_PullDown_eFrameX1:
1587                           uiNumToDrop *= 2;
1588                           break;
1589                        default:
1590                           /* Do nothing for non-progressive pulldowns - uiNumToDrop already specifies fields */
1591                           break;
1592                     }
1593
1594                     /* Snapshot the start time. */
1595                     BXDM_PPTMR_P_SnapshotFunctionStartTime( hXdmPP, BXDM_PPTIMER_P_Function_eDecoderRequestPictureDropIsr );
1596
1597                     /* We update the actual drop count */
1598                     /* SW7405-3925: This function must return the modified drop count, since the requested amount may not match the
1599                        amount requested from the decoder due to truncation, clipping of the request, or simply not performing the
1600                        request if the decoder is not ready.  This ensures the uiDecoderDroppedCoun, below, is kept up-to-date. */
1601                     hXdmPP->stDMConfig.stDecoderInterface.requestPictureDrop_isr(
1602                           hXdmPP->stDMConfig.pDecoderPrivateContext,
1603                              &uiNumToDrop
1604                           );
1605
1606                     /* Snapshot the end time. */
1607                     BXDM_PPTMR_P_SnapshotFunctionEndTime( hXdmPP, BXDM_PPTIMER_P_Function_eDecoderRequestPictureDropIsr );
1608
1609                     /* Update the drop count visible to the application */
1610                     hXdmPP->stDMStatus.stCounters.uiDecoderDroppedCount += uiNumToDrop;
1611                  }
1612               }
1613            }
1614         }     /* end of if ( false == bDispQueueHasData ) */
1615         else
1616         {
1617            /* If a picture is available, no underflow on this vsync. */
1618            hXdmPP->stDMState.stDecode.bDqUnderflowPrevVsync = false;
1619
1620            BXDM_PPDBG_P_SelectionLog( hXdmPP, BXDM_PPDBG_Selection_ePPBFound );
1621
1622            /* PR47521: Keep track of actual new PPBs that were
1623             * evaluated on this vsync */
1624            pLocalState->uiPicturesEvaluated++;
1625
1626            /* eChannelChangeMode: First picture preview.
1627             * bForceDisplayFirstPPB is a one-shot flag, so we keep a
1628             * local copy and reset the persistent one */
1629            bForceDisplayPPB = hXdmPP->stDMState.stDecode.bForceDisplayFirstPPB;
1630            hXdmPP->stDMState.stDecode.bForceDisplayFirstPPB = false;
1631
1632            /* Get the TSM result for the new picture
1633             * Note: the result will be stored in
1634             *    "pstPictureUnderEvaluation->stPicParms.stTSM.stDynamic.eTsmResult"
1635             */
1636            BXDM_PPTSM_P_EvaluateTsmState(
1637               hXdmPP,
1638               pLocalState,
1639               pstPictureUnderEvaluation
1640               );
1641
1642
1643            /* Update GetNextPTS() values w/ values from this picture */
1644            /* Set the next PTS to be the actual PTS from the next
1645             * picture in the queue */
1646            hXdmPP->stDMStatus.bNextPTSInfoValid = true;
1647            pstNextPTSInfo->ePTSType = pstPictureUnderEvaluation->stPicParms.stTSM.stStatic.ePtsType;
1648            BXDM_PPQM_P_GetPts(
1649               pstPictureUnderEvaluation,
1650               BXDM_PictureProvider_P_PTSIndex_eActual,
1651               0,
1652               &(pstNextPTSInfo->ui32RunningPTS)
1653               );
1654            pstNextPTSInfo->ui32EffectivePTS = pstPictureUnderEvaluation->stPicParms.stTSM.stDynamic.uiEffectivePTS[BXDM_PictureProvider_P_PTSIndex_eActual];
1655            /* SW7425-875: pstNextPTSInfo->uiSTCSnapShot = pLocalState->uiAdjustedStc;*/
1656            pstNextPTSInfo->uiPCROffset =  pstPictureUnderEvaluation->stPicParms.stTSM.stStatic.stPCROffsetXDM.stPCROffsetCopy.uiValue;
1657            pstNextPTSInfo->bPcrOffsetValid =  pstPictureUnderEvaluation->stPicParms.stTSM.stStatic.stPCROffsetXDM.stPCROffsetCopy.bValid;
1658            pstNextPTSInfo->bPcrDiscontinuity = pstPictureUnderEvaluation->stPicParms.stTSM.stStatic.stPCROffsetXDM.stPCROffsetCopy.bDiscontinuity;
1659         }     /* end of else ( true == bDispQueueHasData ) */
1660
1661         BXDM_PPTMR_P_SnapshotFunctionEndTime( hXdmPP, BXDM_PPTIMER_P_Function_eSelPic1 );
1662
1663         BXDM_PPTMR_P_SnapshotFunctionStartTime( hXdmPP, BXDM_PPTIMER_P_Function_eSelPic2 );
1664
1665         /* We decide what to do with the picture based on the TSM
1666          * result */
1667         switch ( pstPictureUnderEvaluation->stPicParms.stTSM.stDynamic.eTsmResult )
1668         {
1669            case BXDM_PictureProvider_TSMResult_ePass:
1670               /* The NEW picture has PASSED TSM */
1671               BXDM_PPDBG_P_SelectionLog( hXdmPP, BXDM_PPDBG_Selection_ePass );
1672
1673               /* We should display this picture */
1674               bDisplayPPB = true;
1675               break;
1676
1677            case BXDM_PictureProvider_TSMResult_eTooEarly:
1678               /* The NEW picture is TOO EARLY */
1679               BXDM_PPDBG_P_SelectionLog( hXdmPP, BXDM_PPDBG_Selection_eTooEarly );
1680
1681               /* In an attempt to catch up, we start dropping early
1682                * pictures after XX consecutive "too early" results in a
1683                * row. Otherwise, we don't do anything with this
1684                * picture */
1685               if ( ( ( hXdmPP->stDMState.stDecode.uiPPBConsecutiveTooEarlyCount >= BXDM_PictureProvider_P_MAX_EARLY_BEFORE_DROP )
1686                      || ( false == hXdmPP->stDMConfig.bPlayback ) )
1687                    && ( BXDM_PictureProvider_PictureHandlingMode_eHonorPTS != pstPictureUnderEvaluation->stPicParms.stTSM.stDynamic.ePictureHandlingMode )
1688                  )
1689               {
1690                  bDropPPB = true;
1691               }
1692               else
1693               {
1694                  bFindNextPPB = false;
1695               }
1696               break;
1697
1698            case BXDM_PictureProvider_TSMResult_eTooLate:
1699               /* The NEW picture is TOO LATE */
1700               BXDM_PPDBG_P_SelectionLog( hXdmPP, BXDM_PPDBG_Selection_eLate );
1701
1702               /* We always display pictures that are late because it is
1703                * less late that the currently displayed picture.  We
1704                * also loop back around evaluate the NEXT picture in the
1705                * queue in an attempt to fine a better picture for
1706                * display */
1707               bDisplayPPB = true;
1708               break;
1709
1710            case BXDM_PictureProvider_TSMResult_eWait:
1711               /* The NEW picture is EARLY */
1712               BXDM_PPDBG_P_SelectionLog( hXdmPP, BXDM_PPDBG_Selection_eWait );
1713
1714               /* We don't do anything with the queues */
1715               bFindNextPPB = false;
1716
1717               /* SW7405-4736: when QM debug enabled, dump the picture state if an eWait
1718                * result for roughly a second.
1719                */
1720               pstPictureUnderEvaluation->stPicParms.uiNumTimesWait++;
1721
1722               if ( pstPictureUnderEvaluation->stPicParms.uiNumTimesWait >= BXDM_PPTMR_lutVsyncsPersSecond[ hXdmPP->stDMConfig.eMonitorRefreshRate ] )
1723               {
1724                  BXDM_PPDBG_P_PrintUnifiedPicture( hXdmPP, pLocalState, pstPictureUnderEvaluation );
1725                  pstPictureUnderEvaluation->stPicParms.uiNumTimesWait = 0;
1726               }
1727               break;
1728
1729            case BXDM_PictureProvider_TSMResult_eDrop:
1730               /* The NEW picture is DROP */
1731               BXDM_PPDBG_P_SelectionLog( hXdmPP, BXDM_PPDBG_Selection_eDrop );
1732
1733               /* We indicate that we need to drop the picture.  We also
1734                * loop back around and evaluate the NEXT picture in the
1735                * queue in an attempt to find a better picture for
1736                * displayq */
1737               bDropPPB = true;
1738               break;
1739
1740            default:
1741               BXVD_DBG_WRN(hXdmPP, ("%x: [%01x.%03x] Unrecognized TSM Result (%d)",
1742                                          hXdmPP->stDMState.stDecode.stDebug.uiVsyncCount,
1743                                          hXdmPP->stDMConfig.uiInstanceID & 0xF,
1744                                          pstPictureUnderEvaluation->stPicParms.uiPPBIndex & 0xFFF,
1745                                          pstPictureUnderEvaluation->stPicParms.stTSM.stDynamic.eTsmResult));
1746               break;
1747         }
1748
1749         /* PR47521: Reset late count if we ever evaluate a non-late
1750          * picture.  We could run into a scenario where pictures are
1751          * +P+L+W which would cause the late count to always increment,
1752          * when it really shouldn't */
1753         if ( BXDM_PictureProvider_TSMResult_eTooLate != pstPictureUnderEvaluation->stPicParms.stTSM.stDynamic.eTsmResult )
1754         {
1755            if ( BXDM_PictureProvider_TSMResult_eWait == pstPictureUnderEvaluation->stPicParms.stTSM.stDynamic.eTsmResult )
1756            {
1757               if ( bDispQueueHasData )
1758               {
1759                  hXdmPP->stDMState.stDecode.uiPPBConsecutiveLateCount=0;
1760               }
1761            }
1762            else
1763            {
1764               hXdmPP->stDMState.stDecode.uiPPBConsecutiveLateCount=0;
1765            }
1766         }
1767
1768         /* Keep track of too early PPBs */
1769         if (BXDM_PictureProvider_TSMResult_eTooEarly == pstPictureUnderEvaluation->stPicParms.stTSM.stDynamic.eTsmResult )
1770         {
1771            hXdmPP->stDMState.stDecode.uiPPBConsecutiveTooEarlyCount++;
1772         }
1773         else
1774         {
1775            hXdmPP->stDMState.stDecode.uiPPBConsecutiveTooEarlyCount=0;
1776         }
1777
1778         /* Handle Freeze */
1779         if ( hXdmPP->stDMConfig.bFreeze )
1780         {
1781            if ( bDisplayPPB )
1782            {
1783               /* We're in a frozen state, so instead of displaying the
1784                * PPB, we force drop the PPB */
1785               BXDM_PPDBG_P_SelectionLog( hXdmPP, BXDM_PPDBG_Selection_eFreeze );
1786
1787               bDisplayPPB = false;
1788               bDropPPB = true;
1789            }
1790         }
1791
1792         /* Handle Force Display - overrides freeze */
1793         if ( bForceDisplayPPB )
1794         {
1795            /* We're in a force display mode */
1796            BXDM_PPDBG_P_SelectionLog( hXdmPP, BXDM_PPDBG_Selection_eForce );
1797
1798            /* eChannelChangeMode: We set auto-freeze to true, because we
1799             * want to keep this picture frozen until we achieve TSM
1800             * Pass */
1801            bDisplayPPB = true;
1802            bDropPPB = false;
1803
1804            /* SW7405-3873: We set bHolding = true during first picture preview so
1805             * that the bIgnoreCadenceMatch is set properly to prevent display bounce
1806             * with interlaced content on non-MAD display path
1807             */
1808            pstPictureUnderEvaluation->stPicParms.stDisplay.stDynamic.bHolding = true;
1809         }
1810
1811         BXDM_PPTMR_P_SnapshotFunctionEndTime( hXdmPP, BXDM_PPTIMER_P_Function_eSelPic2 );
1812
1813         BXDM_PPTMR_P_SnapshotFunctionStartTime( hXdmPP, BXDM_PPTIMER_P_Function_eSelPic3 );
1814
1815         /* See if we need to pull the picture off the queue or not */
1816         if ( bDisplayPPB || bDropPPB )
1817         {
1818            /* Get the picture from the queue */
1819            BXDM_PPQM_P_GetNextPicture(
1820               hXdmPP,
1821               pLocalState,
1822               pstPictureUnderEvaluation
1823               );
1824
1825            *pstPreviousPictureUnderEvaluation = *pstPictureUnderEvaluation;
1826
1827            /* Decide what to do with the picture */
1828            if ( bDropPPB )
1829            {
1830               hXdmPP->stDMStatus.stCounters.uiDisplayManagerDroppedCount++;
1831
1832               /* Release the NEW picture */
1833               BXDM_PPQM_P_ReleasePictureExt( hXdmPP, pLocalState, pstPictureUnderEvaluation );
1834
1835               BXDM_PPQM_P_InvalidatePictureContext( pstPictureUnderEvaluation );
1836            }
1837            else
1838            {
1839               /* Release the OLD picture and display the NEW picture */
1840               BXDM_PPQM_P_ReleasePictureExt( hXdmPP, pLocalState, pstSelectedPicture );
1841
1842               BXDM_PPQM_P_PromotePictureToDisplayStatus(
1843                  hXdmPP,
1844                  pLocalState,
1845                  pstPictureUnderEvaluation
1846                  );
1847
1848               BXDM_PPQM_P_InvalidatePictureContext( pstPictureUnderEvaluation );
1849            }
1850         }
1851
1852         /* Currently only used to know if the delivery queue has underflowed. */
1853         uiLoopCount++;
1854
1855         BXDM_PPTMR_P_SnapshotFunctionEndTime( hXdmPP, BXDM_PPTIMER_P_Function_eSelPic3 );
1856
1857      }  /* end of while() */
1858   }
1859
1860   /* If the FIC changed and we're re-displaying the selected picture
1861    * (i.e. we haven't selected a new picture), we need to re-evaluate
1862    * TSM using the new FIC offset so that the TSM values are accurate
1863    * for logic that relies on it.  E.g. dStcPtsEvaluated will change
1864    * if FIC changes.
1865    */
1866   if ( ( true == pLocalState->bFICChanged )
1867        && ( true == pstSelectedPicture->stPicParms.stDisplay.stDynamic.bPPBRepeated ) )
1868   {
1869      BXDM_PPTSM_P_EvaluateTsmState(
1870         hXdmPP,
1871         pLocalState,
1872         pstSelectedPicture
1873         );
1874   }
1875
1876   /* SW7335-781: Output warning when picture selection override ceases */
1877   BXDM_PPDBG_P_PrintEndSelectionModeOverride(hXdmPP, pstSelectedPicture);
1878
1879   BDBG_LEAVE(BXDM_PP_S_SelectPicture);
1880   return;
1881} /* end of BXDM_PP_S_SelectPicture() */
1882
1883static void BXDM_PP_S_SelectElement(
1884   BXDM_PictureProvider_Handle hXdmPP,
1885   BXDM_PictureProvider_P_LocalState* pLocalState
1886   )
1887{
1888   BXDM_PictureProvider_P_Picture_Params* pstPicParms= &(hXdmPP->stDMState.stChannel.stSelectedPicture.stPicParms);
1889
1890   BDBG_ENTER(BXDM_PP_S_SelectElement);
1891
1892   /*
1893   ** Selects best PPB from pictures in delivery queue using TSM */
1894   BXDM_PP_S_SelectPicture( hXdmPP, pLocalState );
1895
1896   /* Keep track of consecutively late unique PPBs */
1897   if ( !pstPicParms->stDisplay.stDynamic.bPPBRepeated )
1898   {
1899      if ( BXDM_PictureProvider_TSMResult_eTooLate == pstPicParms->stTSM.stDynamic.eTsmResult )
1900      {
1901         hXdmPP->stDMState.stDecode.uiPPBConsecutiveLateCount++;
1902      }
1903      else
1904      {
1905         hXdmPP->stDMState.stDecode.uiPPBConsecutiveLateCount=0;
1906      }
1907   }
1908
1909   /* PR47521: We reset the late count also if the queue was
1910    * completely empty during this vsync.  An empty queue is an
1911    * indication of packet loss or other stream discontinuity, so we
1912    * don't want to prematurely trigger the drop@decode logic in these
1913    * cases because after a few pictures, the system should settle
1914    * down */
1915   if ( pLocalState->uiPicturesEvaluated == 0)
1916   {
1917      hXdmPP->stDMState.stDecode.uiPPBConsecutiveLateCount=0;
1918   }
1919
1920   /* We reset the late count if the PCR is discontinuous */
1921   if ( ( false == hXdmPP->stDMConfig.bPlayback )
1922        && pstPicParms->stTSM.stStatic.stPCROffsetXDM.bDiscontinuityOverloaded
1923      )
1924   {
1925      hXdmPP->stDMState.stDecode.uiPPBConsecutiveLateCount=0;
1926   }
1927
1928   /* Set the bElementRepeated flag */
1929   if ( pstPicParms->stDisplay.stDynamic.bPPBRepeated
1930        && (hXdmPP->stDMState.stChannel.stPreviousPicture.stPicParms.stDisplay.stDynamic.uiSelectedElement != pstPicParms->stDisplay.stDynamic.uiSelectedElement)
1931      )
1932   {
1933      pstPicParms->stDisplay.stDynamic.bElementRepeated = false;
1934   }
1935
1936   BDBG_LEAVE(BXDM_PP_S_SelectElement);
1937   return;
1938} /* end of BXDM_PP_S_SelectElement() */
1939
1940/*******************************************************************************
1941 **
1942 ** Public functions
1943 **
1944 *******************************************************************************/
1945BERR_Code
1946BXDM_PictureProvider_GetPicture_isr(
1947   void* pPrivateContext,
1948   const BXDM_DisplayInterruptInfo *pstDisplayInterruptInfo,
1949   BAVC_MVD_Picture **pDispMgrToVDC
1950   )
1951{
1952   BXDM_PictureProvider_Handle hXdmPP = (BXDM_PictureProvider_Handle) pPrivateContext;
1953   BXDM_PictureProvider_P_LocalState stLocalDmState;
1954   BXDM_PictureProvider_P_LocalState* pLocalState;
1955   bool bPrimaryPicture;
1956   uint32_t i;
1957
1958   BDBG_ASSERT(pDispMgrToVDC);
1959
1960   BDBG_ENTER(BXDM_PictureProvider_GetPicture_isr);
1961
1962   /* Snapshot the start time. */
1963   BXDM_PPTMR_P_SnapshotFunctionStartTime( hXdmPP, BXDM_PPTIMER_P_Function_eMainIsr );
1964
1965   /*
1966    * Initialize the local variables.
1967    */
1968   pLocalState = &(stLocalDmState);
1969
1970   BKNI_Memset( pLocalState, 0, sizeof( BXDM_PictureProvider_P_LocalState ) );
1971   for (i = 0; i < BXDM_PictureProvider_P_PTSIndex_eMax; i++)
1972   {
1973      pLocalState->iStcPtsDifferenceEvaluatedDeltaAbsMin[i] = 0x7FFFFFFE;
1974      pLocalState->iStcPtsDifferenceEvaluatedBest[i] = 0x7FFFFFFF;
1975   }
1976
1977   /* SW7405-4736: print the input parameters before getting started.
1978    * Only those that have changed since the last execution will be printed.
1979    */
1980   BXDM_PPDBG_P_PrintDMConfig( hXdmPP, pLocalState, false );
1981
1982   /*
1983    * Perform per vsync validation; primarily evaluating the XVD and firmware state.
1984    */
1985   BXDM_PP_S_InitPerVsync( hXdmPP, pLocalState, pstDisplayInterruptInfo );
1986
1987   /* SW7405-3137: "pLocalState->eInterruptType" indicates what type of picture VDC is
1988    * expecting to have delivered.  If VDC is NOT expecting the dependent picture of
1989    * a set, then perform TSM, generate the MFD data, update status ...
1990    */
1991   bPrimaryPicture = ( BXDM_PictureProvider_P_InterruptType_eDependent != pLocalState->eInterruptType );
1992
1993   if ( true == bPrimaryPicture )
1994   {
1995      /*
1996       * Select the best element from a PPB using TSM, polarity inversion correction, and repeat modes.
1997       * But only if the delivery queue is in a known state, i.e. when the decoder is up and running.
1998       *
1999       * Note:
2000       * - "eVideoState" is set to "BXVD_P_VideoState_DecodeStopped" in "BXVD_StopDecode()".
2001       * - it is set to "BXVD_P_VideoState_DecodeStarted" at the end of "BXVD_P_DisplayManager_StartDecode()"
2002       *       ("BXVD_P_DisplayManager_StartDecode()" is called from "BXVD_StartDecode()".
2003       */
2004      BXDM_PP_S_SelectElement( hXdmPP, pLocalState );
2005
2006      /*
2007       * Now that a picture has been selected, generate the picture data for VDC.
2008       */
2009      BXDM_PPOUT_P_CalculateVdcData( hXdmPP, pLocalState, pDispMgrToVDC );
2010
2011      /*
2012       * Update the status that is visible to the application, e.g. "stCurrentPTSInfo"
2013       */
2014      BXDM_PP_S_UpdatePublicStatus( hXdmPP,  pLocalState );
2015
2016      /*
2017       * Conditionally execute the callbacks.
2018       */
2019      BXDM_PPTMR_P_SnapshotFunctionStartTime( hXdmPP, BXDM_PPTIMER_P_Function_eMainCallbacks );
2020
2021      BXDM_PPCB_P_ExecuteCallbacks( hXdmPP, pLocalState );
2022
2023      BXDM_PPTMR_P_SnapshotFunctionEndTime( hXdmPP, BXDM_PPTIMER_P_Function_eMainCallbacks );
2024
2025      /* SW7425-2536: if registered, execute "displayInterruptStatus_isr" to return
2026       * the status of the currently selected picture and other assorted information.
2027       */
2028      if ( NULL != hXdmPP->stDMConfig.stDecoderInterface.displayInterruptStatus_isr )
2029      {
2030         BXDM_PictureProvider_Status stStatus;
2031
2032         BXDM_PP_S_UpdateStatus( hXdmPP, pLocalState, &(stStatus) );
2033
2034         hXdmPP->stDMConfig.stDecoderInterface.displayInterruptStatus_isr(
2035                           hXdmPP->stDMConfig.pDecoderPrivateContext,
2036                           &stStatus
2037                           );
2038      }
2039
2040      /* Handle bMute AFTER the callbacks have occurred to ensure the
2041       * app hasn't requested a mute in one of the callbacks */
2042      if ( true == hXdmPP->stDMConfig.bMute )
2043      {
2044         BAVC_MVD_Picture *pMFDPicture = *pDispMgrToVDC;
2045         while ( NULL != pMFDPicture )
2046         {
2047            pMFDPicture->bMute = hXdmPP->stDMConfig.bMute;
2048            pMFDPicture = (BAVC_MVD_Picture *) pMFDPicture->pNext;
2049         }
2050      }
2051   }
2052   else
2053   {
2054      *pDispMgrToVDC = &(hXdmPP->astMFDPicture[0]);
2055
2056      {
2057         BAVC_MVD_Picture *pMFDPicture = *pDispMgrToVDC;
2058         while ( NULL != pMFDPicture )
2059         {
2060            pMFDPicture->eInterruptPolarity = pLocalState->eVsyncPolarity;
2061
2062            /* SWBLURAY-20436: toggle the source polarity on the dependent interrupt. */
2063            if ( BAVC_Polarity_eTopField == pMFDPicture->eSourcePolarity )
2064            {
2065               pMFDPicture->eSourcePolarity = BAVC_Polarity_eBotField;
2066            }
2067            else if ( BAVC_Polarity_eBotField == pMFDPicture->eSourcePolarity )
2068            {
2069               pMFDPicture->eSourcePolarity = BAVC_Polarity_eTopField;
2070            }
2071
2072            pMFDPicture = (BAVC_MVD_Picture *) pMFDPicture->pNext;
2073         }
2074      }
2075
2076      BXDM_PPDBG_P_SelectionLog( hXdmPP, BXDM_PPDBG_Selection_eDependentPicture );  /* TSM */
2077      BXDM_PPDBG_P_OutputLog( hXdmPP, pLocalState, *pDispMgrToVDC );                /* T/B/F: */
2078      BXDM_PPDBG_P_OutputSPOLog( hXdmPP, 0 );                                       /* SPO */
2079      BXDM_PPDBG_P_CallbackTriggeredLog(hXdmPP, pLocalState->uiCallbackTriggered);  /* CB */
2080   }
2081
2082   /*
2083    * Update the post run state and status.
2084    */
2085   BXDM_PP_S_PostIsr( hXdmPP, pLocalState, bPrimaryPicture );
2086
2087   /* Snapshot the end time. */
2088   BXDM_PPTMR_P_SnapshotFunctionEndTime( hXdmPP, BXDM_PPTIMER_P_Function_eMainIsr );
2089
2090   BXDM_PPTMR_P_PrintResults( hXdmPP );
2091
2092   BDBG_LEAVE(BXDM_PictureProvider_GetPicture_isr);
2093   return BERR_TRACE(BERR_SUCCESS);
2094} /* end of BXDM_PictureProvider_GetPicture_isr() */
2095
2096BERR_Code
2097BXDM_PictureProvider_StartDecode_isr(
2098   BXDM_PictureProvider_Handle hXdmPP
2099   )
2100{
2101   BDBG_ENTER(BXDM_PictureProvider_StartDecode_isr);
2102
2103   if (!hXdmPP->stDMState.stChannel.bDMVersionDisplayed)
2104   {
2105      BXVD_DBG_WRN(hXdmPP,("Display Manager: [v%02d.%02d.%04d]",
2106                                BXDM_PictureProvider_P_VERSION_MAJOR,
2107                                BXDM_PictureProvider_P_VERSION_MINOR,
2108                                BXDM_PictureProvider_P_VERSION_SUBMINOR));
2109      hXdmPP->stDMState.stChannel.bDMVersionDisplayed = true;
2110   }
2111
2112   BXDM_PPDBG_P_PrintNodes(hXdmPP);
2113
2114   /* SW7405-3984: if the "last" picture is being held but the channel change mode
2115    * does not indicate to "hold last picture", the mode changed from "hold" to "mute" after
2116    * StopDecode was called.  Release the picture at this point to avoid redisplaying it.
2117    *
2118    * Note: to avoid releasing a picture on a "flush decode", this test needs to happen prior to the
2119    * logic below which copies "stSavedChannelChangeSettings" to "stChannelChangeSettings".
2120    * The call to BXVD_DisableForFlush results in "bHoldLastPicture" being set to "true"
2121    * in BXDM_PictureProvider_StopDecode_isr. In turn, the restore below could result in
2122    * "bHoldLastPicture" being set to "false".  In that situation, the held picture would be
2123    * release prematurely.
2124    */
2125   if ( true == hXdmPP->stDMState.stChannel.stSelectedPicture.stPicParms.stDisplay.stDynamic.bHolding
2126        && false == hXdmPP->stDMConfig.stChannelChangeSettings.bHoldLastPicture
2127      )
2128   {
2129      /* This check should be redundant.  Keep here in the event I've missed a corner case.
2130       */
2131      if ( NULL != hXdmPP->stDMState.stChannel.stSelectedPicture.pstUnifiedPicture )
2132      {
2133         BXDM_PPQM_P_ReleasePicture( hXdmPP, &hXdmPP->stDMState.stChannel.stSelectedPicture );
2134      }
2135   }
2136
2137   /* SW7425-2656: both of the following will only be true if a "flush" has occured,
2138    * i.e. BXVD_DisableForFlush, BXVD_SetSkipPictureModeDecode or BXVD_PVR_SetHostSparseMode
2139    * has been called.  Used in BXDM_PPVTSM_P_VirtualPtsInterpolate to determine how to reset
2140    * the virtual PTS.
2141    */
2142   hXdmPP->stDMState.stChannel.bPostFlushDecode = ( true == hXdmPP->stDMConfig.stPreserveStateSettings.bDisplay );
2143   hXdmPP->stDMState.stChannel.bPostFlushDecode &= ( true == hXdmPP->stDMState.stChannel.bSavedChannelChangeSettingsValid );
2144
2145   if ( false == hXdmPP->stDMConfig.stPreserveStateSettings.bDisplay )
2146   {
2147      /* Discard threshold defaults. PR: 26199 */
2148      switch (hXdmPP->stDMConfig.eProtocol)
2149      {
2150         case BAVC_VideoCompressionStd_eH264:
2151            hXdmPP->stDMConfig.stTSMThresholdSettings.uiTooEarlyThreshold =
2152               BXDM_PictureProvider_P_DISCARD_THRESHOLD_AVC;
2153            break;
2154         case BAVC_VideoCompressionStd_eMPEG2:
2155         case BAVC_VideoCompressionStd_eMPEG1:
2156         case BAVC_VideoCompressionStd_eMPEG2DTV:
2157         case BAVC_VideoCompressionStd_eMPEG4Part2:
2158         case BAVC_VideoCompressionStd_eH263:
2159            hXdmPP->stDMConfig.stTSMThresholdSettings.uiTooEarlyThreshold =
2160               BXDM_PictureProvider_P_DISCARD_THRESHOLD_MPEG;
2161            break;
2162         case BAVC_VideoCompressionStd_eVC1:
2163         case BAVC_VideoCompressionStd_eVC1SimpleMain:
2164            hXdmPP->stDMConfig.stTSMThresholdSettings.uiTooEarlyThreshold =
2165               BXDM_PictureProvider_P_DISCARD_THRESHOLD_VC1;
2166            break;
2167         default:
2168            hXdmPP->stDMConfig.stTSMThresholdSettings.uiTooEarlyThreshold =
2169               BXDM_PictureProvider_P_DISCARD_THRESHOLD_MPEG;
2170            break;
2171      }
2172
2173      hXdmPP->stDMConfig.stTSMThresholdSettings.uiTooLateThreshold =
2174         BXDM_PictureProvider_P_VERYLATE_THRESHOLD;
2175   } else {
2176      if ( true == hXdmPP->stDMState.stChannel.bSavedChannelChangeSettingsValid )
2177      {
2178         hXdmPP->stDMConfig.stChannelChangeSettings = hXdmPP->stDMState.stChannel.stSavedChannelChangeSettings;
2179      }
2180   }
2181   hXdmPP->stDMState.stChannel.bSavedChannelChangeSettingsValid = false;
2182
2183   hXdmPP->stDMStatus.bNextPTSInfoValid = false;
2184
2185   /* Conditionally Reset all the status counters */
2186   if ( false == hXdmPP->stDMConfig.stPreserveStateSettings.bCounters )
2187   {
2188      BKNI_Memset( &(hXdmPP->stDMStatus.stCounters), 0, sizeof( BXDM_PictureProvider_Counters ) );
2189   }
2190
2191   /* Reset the preserve state settings to the defaults */
2192   BXDM_PictureProvider_GetDefaultPreserveStateSettings(
2193            hXdmPP,
2194            &hXdmPP->stDMConfig.stPreserveStateSettings
2195            );
2196
2197   BXDM_PP_S_ResetCommon( hXdmPP );
2198
2199   hXdmPP->stDMState.stChannel.eDecodeState = BXDM_PictureProvider_P_DecodeState_eStarted;
2200
2201   BDBG_LEAVE(BXDM_PictureProvider_StartDecode_isr);
2202
2203   return BERR_TRACE(BERR_SUCCESS);
2204} /* end of BXVD_P_DisplayManager_StartDecode() */
2205
2206
2207BERR_Code
2208BXDM_PictureProvider_WatchdogReset_isr(
2209   BXDM_PictureProvider_Handle hXdmPP
2210   )
2211{
2212   BDBG_ENTER(BXDM_PictureProvider_WatchdogReset_isr);
2213
2214   /* Re-initialize the "stSelectedPicture" structure to be certain we don't try to do use the PPB pointers. */
2215
2216   BKNI_Memset( &(hXdmPP->stDMState.stChannel.stSelectedPicture), 0, sizeof ( BXDM_PictureProvider_P_Picture_Context ));
2217
2218   /* PR53039: also be certain that the PTS type is "invalid" */
2219   hXdmPP->stDMState.stChannel.stSelectedPicture.stPicParms.stTSM.stStatic.ePtsType = BXDM_PictureProvider_PTSType_eInterpolatedFromInvalidPTS;
2220
2221   hXdmPP->stDMState.stChannel.eDecodeState = BXDM_PictureProvider_P_DecodeState_eStopped;
2222
2223   BDBG_LEAVE(BXDM_PictureProvider_WatchdogReset_isr);
2224
2225   return BERR_TRACE( BERR_SUCCESS );
2226} /* end of BXDM_PictureProvider_WatchdogReset_isr() */
2227
2228BERR_Code
2229BXDM_PictureProvider_StopDecode_isr(
2230   BXDM_PictureProvider_Handle hXdmPP
2231   )
2232{
2233   BDBG_ENTER(BXDM_PictureProvider_StopDecode_isr);
2234
2235   hXdmPP->stDMState.stChannel.eDecodeState = BXDM_PictureProvider_P_DecodeState_eStopped;
2236
2237   if ( true == hXdmPP->stDMConfig.stPreserveStateSettings.bDisplay )
2238   {
2239      hXdmPP->stDMState.stChannel.stSavedChannelChangeSettings = hXdmPP->stDMConfig.stChannelChangeSettings;
2240      hXdmPP->stDMState.stChannel.bSavedChannelChangeSettingsValid = true;
2241
2242      hXdmPP->stDMConfig.stChannelChangeSettings.bHoldLastPicture = true;
2243   }
2244
2245   /* eChannelChangeMode: Handle hold last picture feature of channel
2246    * change - BXVD_StopDecode() */
2247   if ( true == hXdmPP->stDMConfig.stChannelChangeSettings.bHoldLastPicture )
2248   {
2249      hXdmPP->stDMState.stChannel.stSelectedPicture.stPicParms.stDisplay.stDynamic.bHolding = true;
2250   }
2251   else
2252   {
2253      if ( NULL != hXdmPP->stDMState.stChannel.stSelectedPicture.pstUnifiedPicture )
2254      {
2255         BXDM_PPQM_P_ReleasePicture( hXdmPP, &hXdmPP->stDMState.stChannel.stSelectedPicture );
2256      }
2257   }
2258
2259   /* PR55616: setting "bFirstPPBSeen" to false will disable the
2260    * "BXVD_Interrupt_ePictureParameters" callback until the first picture
2261    * the next stream is delivered to the DM.
2262    */
2263   hXdmPP->stDMState.stDecode.bFirstPPBSeen = false;
2264
2265   if (hXdmPP->stDMConfig.stPreserveStateSettings.bDisplay == false)
2266   {
2267      hXdmPP->stDMConfig.bAutoValidateStcOnPause = true;
2268      hXdmPP->stDMConfig.stPlaybackRate.uiNumerator = 1;
2269      hXdmPP->stDMConfig.stPlaybackRate.uiDenominator = 1;
2270      hXdmPP->stDMConfig.bReverseFields = false;
2271
2272      /* PR21416: Make sure DM is displaying both top and bottom fields */
2273      hXdmPP->stDMConfig.eDisplayFieldMode = BXDM_PictureProvider_DisplayFieldMode_eBothField;
2274
2275      hXdmPP->stDMConfig.uiPTSOffset = 0;
2276   }
2277
2278   BDBG_LEAVE(BXDM_PictureProvider_StopDecode_isr);
2279
2280   return BERR_TRACE( BERR_SUCCESS );
2281
2282} /* end of BXDM_PictureProvider_StopDecode_isr() */
2283
2284static const BXDM_PictureProvider_Settings s_stDefaultPictureProviderSettings =
2285{
2286    2 /* uiMaxBuffersPerPicture */
2287};
2288
2289BERR_Code
2290BXDM_PictureProvider_GetDefaultSettings(
2291         BXDM_PictureProvider_Settings *pstPictureProviderSettings
2292         )
2293{
2294   BDBG_ENTER( BXDM_PictureProvider_GetDefaultSettings );
2295   BDBG_ASSERT( pstPictureProviderSettings );
2296
2297   *pstPictureProviderSettings = s_stDefaultPictureProviderSettings;
2298
2299   BDBG_LEAVE( BXDM_PictureProvider_GetDefaultSettings );
2300
2301   return BERR_TRACE( BERR_SUCCESS );
2302}
2303
2304/*
2305 * Handle any initialization that only needs to be done once
2306 * on "OpenChannel"
2307 */
2308BERR_Code
2309BXDM_PictureProvider_Create(
2310         BXDM_PictureProvider_Handle *phXdmPP,
2311         const BXDM_PictureProvider_Settings *pstPictureProviderSettings
2312         )
2313{
2314   BERR_Code rc;
2315   uint32_t i;
2316   BXDM_PictureProvider_P_Context *pXdmPP = NULL;
2317   BXDM_PPJRC_P_Settings stJrcSettings;
2318   BXDM_PPAVG_P_Settings stAvgSettings;
2319
2320   BDBG_ENTER( BXDM_PictureProvider_Create );
2321
2322   BDBG_ASSERT( phXdmPP );
2323   BDBG_ASSERT( pstPictureProviderSettings );
2324
2325   /* Set the handle to NULL in case the allocation fails */
2326   *phXdmPP = NULL;
2327
2328   pXdmPP = ( BXDM_PictureProvider_P_Context* ) BKNI_Malloc( sizeof( BXDM_PictureProvider_P_Context ) );
2329   if ( NULL == pXdmPP )
2330   {
2331      return BERR_TRACE( BERR_OUT_OF_SYSTEM_MEMORY );
2332   }
2333
2334   /* Zero out the newly allocated context */
2335   BKNI_Memset( ( void * ) pXdmPP, 0, sizeof( BXDM_PictureProvider_P_Context ) );
2336
2337   /* Allocate MFD Pictures */
2338   pXdmPP->uiMFDPictureCount = pstPictureProviderSettings->uiMaxBuffersPerPicture;
2339   pXdmPP->astMFDPicture = (BAVC_MFD_Picture *) BKNI_Malloc( sizeof ( BAVC_MFD_Picture ) * pXdmPP->uiMFDPictureCount );
2340   if ( NULL == pXdmPP->astMFDPicture )
2341   {
2342      BXDM_PictureProvider_Destroy( pXdmPP );
2343      return BERR_TRACE( BERR_OUT_OF_SYSTEM_MEMORY );
2344   }
2345   BKNI_Memset( pXdmPP->astMFDPicture, 0, sizeof ( BAVC_MFD_Picture ) * pXdmPP->uiMFDPictureCount );
2346
2347   /* This issue was found while trying to reproduce SW7630-85 with a check
2348    * test program. At startup, the mute flag was not set on the dependent picture.
2349    * As a result, VDC was going off the rails with the NULL picture pointers.
2350    */
2351   for ( i=0; i < pXdmPP->uiMFDPictureCount; i++ )
2352   {
2353      pXdmPP->astMFDPicture[ i ].bMute = true;
2354   }
2355
2356   BXDM_PPOUT_P_OpenChannel( pXdmPP );
2357
2358   /* Initialize GOP timecode */
2359   pXdmPP->stDMStatus.stGOPTimeCode.bValid = false;
2360
2361   /* Initialize PVR defaults */
2362   pXdmPP->stDMConfig.bFreeze = false;
2363   pXdmPP->stDMConfig.bAutoValidateStcOnPause = true;
2364   pXdmPP->stDMConfig.stPlaybackRate.uiNumerator = 1;
2365   pXdmPP->stDMConfig.stPlaybackRate.uiDenominator = 1;
2366   pXdmPP->stDMConfig.eFrameAdvanceMode = BXDM_PictureProvider_FrameAdvanceMode_eFrame;
2367   pXdmPP->stDMConfig.bReverseFields = false;
2368
2369   pXdmPP->stDMConfig.eDisplayMode = BXDM_PictureProvider_DisplayMode_eVirtualTSM;
2370
2371   pXdmPP->stDMConfig.eDisplayFieldMode = BXDM_PictureProvider_DisplayFieldMode_eBothField;
2372   pXdmPP->stDMConfig.eSourceFormatOverride = BXDM_PictureProvider_SourceFormatOverride_eDefault;
2373
2374   /* ensure we have a valid refresh rate */
2375   pXdmPP->stDMConfig.eMonitorRefreshRate = BXDM_PictureProvider_MonitorRefreshRate_e59_94Hz;
2376
2377   /* PR50623: the default is to use the HW PCR Offset */
2378   pXdmPP->stDMConfig.bUseHardwarePCROffset = true;
2379
2380   pXdmPP->stDMConfig.e240iScanMode = BXDM_PictureProvider_240iScanMode_eForceProgressive;
2381
2382   pXdmPP->stDMConfig.bJitterToleranceImprovement = true;
2383
2384   BXDM_PPJRC_P_GetDefaultSettings(&stJrcSettings);
2385   rc = BXDM_PPJRC_P_Create(
2386            &pXdmPP->stDMState.stChannel.hJrc,
2387            &stJrcSettings);
2388
2389   if ( BERR_SUCCESS != rc )
2390   {
2391      BXDM_PictureProvider_Destroy( pXdmPP );
2392      return BERR_TRACE( rc );
2393   }
2394
2395   BXDM_PPAVG_P_GetDefaultSettings(&stAvgSettings);
2396   stAvgSettings.uiNumSamples = BXDM_PictureProvider_P_RATE_MATCH_DETECTION_SAMPLES;
2397   rc = BXDM_PPAVG_P_Create(
2398            &pXdmPP->stDMState.stChannel.hDeltaSTCAvg,
2399            &stAvgSettings);
2400
2401   if ( BERR_SUCCESS != rc )
2402   {
2403      BXDM_PictureProvider_Destroy( pXdmPP );
2404      return BERR_TRACE( rc );
2405   }
2406
2407   *phXdmPP = pXdmPP;
2408
2409   BDBG_LEAVE( BXDM_PictureProvider_Create );
2410   return BERR_TRACE( BERR_SUCCESS );
2411}
2412
2413BERR_Code
2414BXDM_PictureProvider_Destroy(
2415         BXDM_PictureProvider_Handle hXdmPP
2416         )
2417{
2418   BDBG_ENTER( BXDM_PictureProvider_Destroy );
2419
2420   BDBG_ASSERT(hXdmPP);
2421
2422   if ( NULL != hXdmPP->stDMState.stChannel.hDeltaSTCAvg )
2423   {
2424      BXDM_PPAVG_P_Destroy( hXdmPP->stDMState.stChannel.hDeltaSTCAvg );
2425   }
2426
2427   if ( NULL != hXdmPP->stDMState.stChannel.hJrc )
2428   {
2429      BXDM_PPJRC_P_Destroy( hXdmPP->stDMState.stChannel.hJrc );
2430   }
2431
2432   if ( NULL != hXdmPP->astMFDPicture )
2433   {
2434      BKNI_Free( hXdmPP->astMFDPicture );
2435   }
2436
2437   BKNI_Free( hXdmPP );
2438
2439   BDBG_LEAVE( BXDM_PictureProvider_Destroy );
2440
2441   return BERR_TRACE( BERR_SUCCESS );
2442}
2443
2444/*******************************************************************************
2445 **
2446 ** end public functions
2447 **
2448 *******************************************************************************/
2449
Note: See TracBrowser for help on using the repository browser.