| 1 | /*************************************************************************** |
|---|
| 2 | * Copyright (c) 2003-2011, 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_fic.c $ |
|---|
| 11 | * $brcm_Revision: Hydra_Software_Devel/12 $ |
|---|
| 12 | * $brcm_Date: 10/3/11 2:19p $ |
|---|
| 13 | * |
|---|
| 14 | * [File Description:] |
|---|
| 15 | * |
|---|
| 16 | * Revision History: |
|---|
| 17 | * |
|---|
| 18 | * $brcm_Log: /magnum/commonutils/xdm/bxdm_pp_fic.c $ |
|---|
| 19 | * |
|---|
| 20 | * Hydra_Software_Devel/12 10/3/11 2:19p btosi |
|---|
| 21 | * SW7425-1264: support for a SW STC internal to XDM |
|---|
| 22 | * |
|---|
| 23 | * Hydra_Software_Devel/11 10/1/10 2:50p btosi |
|---|
| 24 | * SWDEPRECATED-1003: added support for bTreatAsSingleElement |
|---|
| 25 | * |
|---|
| 26 | * Hydra_Software_Devel/10 9/23/10 3:09p btosi |
|---|
| 27 | * SW7405-4736: add support for a XDM instance ID to help debug multi- |
|---|
| 28 | * channel issues |
|---|
| 29 | * |
|---|
| 30 | * Hydra_Software_Devel/9 9/21/10 3:06p btosi |
|---|
| 31 | * SWBLURAY-22573: Turn off the FIC logic for MVC streams |
|---|
| 32 | * |
|---|
| 33 | * Hydra_Software_Devel/8 9/15/10 12:06p btosi |
|---|
| 34 | * SWDEPRECATED-1003: added BXDM_PictureProvider_SetFrameRateOverride_isr |
|---|
| 35 | * and supporting logic |
|---|
| 36 | * |
|---|
| 37 | * Hydra_Software_Devel/7 9/14/10 11:56a btosi |
|---|
| 38 | * SWDEPRECATED-1003: added BXDM_PictureProvider_SetTrickMode_isr to |
|---|
| 39 | * primarily disable the FIC logic when receiving video with sparse |
|---|
| 40 | * pictures |
|---|
| 41 | * |
|---|
| 42 | * Hydra_Software_Devel/6 8/10/10 4:16p btosi |
|---|
| 43 | * SW7405-4736: added PPB index to debug messages |
|---|
| 44 | * |
|---|
| 45 | * Hydra_Software_Devel/5 8/4/10 1:22p btosi |
|---|
| 46 | * SWBLURAY-21565: to aid debug, added uiPPBIndex to debug messages |
|---|
| 47 | * |
|---|
| 48 | * Hydra_Software_Devel/4 7/16/10 9:41a delkert |
|---|
| 49 | * SW7405-4632: Replace missing single field display mode check in |
|---|
| 50 | * IgnoreCadenceMatch calculation |
|---|
| 51 | * |
|---|
| 52 | * Hydra_Software_Devel/3 3/25/10 3:55p nilesh |
|---|
| 53 | * SW7550-349: Fixed issue with STC pause/frame advance from occasionally |
|---|
| 54 | * not occurring |
|---|
| 55 | * |
|---|
| 56 | * Hydra_Software_Devel/2 3/24/10 3:06p btosi |
|---|
| 57 | * SW7340-116: only perform FIC if the CDT logic set the scan mode to |
|---|
| 58 | * interlaced. |
|---|
| 59 | * |
|---|
| 60 | * Hydra_Software_Devel/1 2/16/10 10:51a nilesh |
|---|
| 61 | * SW7405-2993: Initial XDM version |
|---|
| 62 | * |
|---|
| 63 | ***************************************************************************/ |
|---|
| 64 | |
|---|
| 65 | #include "bstd.h" |
|---|
| 66 | #include "bdbg.h" /* Dbglib */ |
|---|
| 67 | |
|---|
| 68 | #include "bxdm_pp.h" |
|---|
| 69 | #include "bxdm_pp_priv.h" |
|---|
| 70 | #include "bxdm_pp_fic.h" |
|---|
| 71 | #include "bxdm_pp_qm.h" |
|---|
| 72 | |
|---|
| 73 | BDBG_MODULE(BXDM_PPFIC); /* Register software module with debug interface */ |
|---|
| 74 | |
|---|
| 75 | const char BXDM_PictureProvider_P_DISPMGR_FIC_NODE[]="DMFIC:\t""$brcm_Revision: Hydra_Software_Devel/12 $"; |
|---|
| 76 | |
|---|
| 77 | BERR_Code BXDM_PPFIC_P_CalculateIgnoreCadenceMatch( |
|---|
| 78 | BXDM_PictureProvider_Handle hXdmPP, |
|---|
| 79 | BXDM_PictureProvider_P_LocalState* pLocalState, |
|---|
| 80 | BXDM_PictureProvider_P_Picture_Context* pstPicture |
|---|
| 81 | ) |
|---|
| 82 | { |
|---|
| 83 | BSTD_UNUSED(pLocalState); |
|---|
| 84 | |
|---|
| 85 | /* PR49634: In order to prevent VDC's sync-slipped multi-buffer |
|---|
| 86 | * path from bouncing caused by regular field inversions, we |
|---|
| 87 | * tell VDC to ignore cadence match if ALL of the following are |
|---|
| 88 | * true: |
|---|
| 89 | * |
|---|
| 90 | * 1) the content is not frame AND |
|---|
| 91 | * 2) We don't expect source -> display polarity match |
|---|
| 92 | * a) FIC and progressive override are not enabled OR |
|---|
| 93 | * b) we're in a single field display mode OR |
|---|
| 94 | * c) we've stopped decode |
|---|
| 95 | * d) we're holding the last picture and/or previewing the first picture |
|---|
| 96 | * e) we're frozen |
|---|
| 97 | * f) the deltaStcPts is negative (E.g. PTSOffset has increased causing repeat of current picture) |
|---|
| 98 | */ |
|---|
| 99 | if ( ( BAVC_Polarity_eFrame != pstPicture->stPicParms.stDisplay.stDynamic.eSourcePolarity ) /* content is truly interlaced */ |
|---|
| 100 | /* we don't expect polarity match */ |
|---|
| 101 | && ( ( ( false == pstPicture->stPicParms.stDisplay.stDynamic.bFICEnabled ) /* FIC is not enabled */ |
|---|
| 102 | && ( BXDM_PictureProvider_P_RepeatMode_eField == pstPicture->stPicParms.stDisplay.stDynamic.eRateConversionRepeatMode ) ) /* Progressive Override not enabled */ |
|---|
| 103 | || ( BXDM_PictureProvider_P_DecodeState_eStopped == hXdmPP->stDMState.stChannel.eDecodeState ) |
|---|
| 104 | || ( true == pstPicture->stPicParms.stDisplay.stDynamic.bHolding ) |
|---|
| 105 | || ( hXdmPP->stDMConfig.bFreeze ) |
|---|
| 106 | || ( ( ( pstPicture->stPicParms.stTSM.stDynamic.iStcPtsDifferenceEvaluated > (int32_t) pstPicture->stPicParms.stTSM.stStatic.stPTSDelta.uiWhole ) |
|---|
| 107 | || ( pstPicture->stPicParms.stTSM.stDynamic.iStcPtsDifferenceEvaluated < 0 ) ) |
|---|
| 108 | && ( BXDM_PictureProvider_P_RepeatMode_eField == pstPicture->stPicParms.stDisplay.stDynamic.eTrickPlayRepeatMode ) ) /* Progressive Override not enabled */ |
|---|
| 109 | || ( BXDM_PictureProvider_DisplayFieldMode_eBothField != pstPicture->stPicParms.stDisplay.stDynamic.eDisplayFieldMode) /* Single-field display mode */ |
|---|
| 110 | ) |
|---|
| 111 | ) |
|---|
| 112 | { |
|---|
| 113 | BXVD_DBG_MSG(hXdmPP,("%x: [%01x.%03x] VDC Cadence Matching Disabled", |
|---|
| 114 | hXdmPP->stDMState.stDecode.stDebug.uiVsyncCount, |
|---|
| 115 | hXdmPP->stDMConfig.uiInstanceID & 0xF, |
|---|
| 116 | pstPicture->stPicParms.uiPPBIndex & 0xFFF)); |
|---|
| 117 | pstPicture->stPicParms.stDisplay.stDynamic.bIgnoreCadenceMatch = true; |
|---|
| 118 | } |
|---|
| 119 | |
|---|
| 120 | return BERR_SUCCESS; |
|---|
| 121 | } |
|---|
| 122 | |
|---|
| 123 | /* PR55439: It is better to prevent inversion than to maintain tight TSM. |
|---|
| 124 | * In light of this, if we have uncorrectable field inversion caused by |
|---|
| 125 | * stream errors (e.g. decoder errors, stream corruption, PCR discontinuities, etc.), |
|---|
| 126 | * we try to deliver the previous element if it was never displayed. If the |
|---|
| 127 | * PPB was already displayed, then we repeat the previously displayed element |
|---|
| 128 | * instead of displaying a new one, since the MAD can at least do a better |
|---|
| 129 | * job with preventing jitter if an element is repeated. |
|---|
| 130 | */ |
|---|
| 131 | static void BXDM_PPFIC_S_SelectPreviousElement(BXDM_PictureProvider_Handle hXdmPP, |
|---|
| 132 | BXDM_PictureProvider_P_LocalState* pLocalState, |
|---|
| 133 | BXDM_PictureProvider_P_Picture_Context* pstPicture) |
|---|
| 134 | { |
|---|
| 135 | BSTD_UNUSED(pLocalState); |
|---|
| 136 | |
|---|
| 137 | if ( pstPicture->stPicParms.stDisplay.stDynamic.uiSelectedElement ) |
|---|
| 138 | { |
|---|
| 139 | if ( 0 == pstPicture->stPicParms.stDisplay.stDynamic.stDisplayDuration.uiWhole ) |
|---|
| 140 | { |
|---|
| 141 | /* If this PPB has not been displayed yet, then we can |
|---|
| 142 | * just select the previous element for display |
|---|
| 143 | */ |
|---|
| 144 | pstPicture->stPicParms.stDisplay.stDynamic.uiSelectedElement--; |
|---|
| 145 | BXDM_PPDBG_P_SelectionLog( hXdmPP, BXDM_PPDBG_Selection_PolarityOverride_eSelectPrevious ); |
|---|
| 146 | } |
|---|
| 147 | else |
|---|
| 148 | { |
|---|
| 149 | /* We've already started displaying this PPB, so it's better |
|---|
| 150 | * to repeat the same field we sent before |
|---|
| 151 | */ |
|---|
| 152 | pstPicture->stPicParms.stDisplay.stDynamic.uiSelectedElement = hXdmPP->stDMState.stChannel.stPreviousPicture.stPicParms.stDisplay.stDynamic.uiSelectedElement; |
|---|
| 153 | BXDM_PPDBG_P_SelectionLog( hXdmPP, BXDM_PPDBG_Selection_PolarityOverride_eRepeatPrevious ); |
|---|
| 154 | } |
|---|
| 155 | } |
|---|
| 156 | } |
|---|
| 157 | |
|---|
| 158 | BERR_Code BXDM_PPFIC_P_CalculateFieldInversionCorrectionOffset( |
|---|
| 159 | BXDM_PictureProvider_Handle hXdmPP, |
|---|
| 160 | BXDM_PictureProvider_P_LocalState* pLocalState, |
|---|
| 161 | BXDM_PictureProvider_P_Picture_Context* pstPicture |
|---|
| 162 | ) |
|---|
| 163 | { |
|---|
| 164 | BAVC_Polarity eTargetSourcePolarity; |
|---|
| 165 | bool bTargetSourcePolarityIsStatic = false; |
|---|
| 166 | |
|---|
| 167 | /* PR51644: If we're on an interlaced display, we want the target |
|---|
| 168 | * polarity to be the same as the vsync polarity. However, if |
|---|
| 169 | * we're on a progressive display, then we want to try guarantee |
|---|
| 170 | * alternating T/B cadence to keep the MAD happy */ |
|---|
| 171 | if ( BAVC_Polarity_eFrame == pLocalState->eVsyncPolarity ) |
|---|
| 172 | { |
|---|
| 173 | if ( true == pLocalState->bDisplayInterruptCountValid ) |
|---|
| 174 | { |
|---|
| 175 | /* SW7405-3085: Use the display interrupt count to determine |
|---|
| 176 | * the target polarity so that we are synced across all mosaic |
|---|
| 177 | * channels on the same display interrupt */ |
|---|
| 178 | switch ( pLocalState->uiDisplayInterruptCount & 0x1 ) |
|---|
| 179 | { |
|---|
| 180 | case 0: |
|---|
| 181 | eTargetSourcePolarity = BAVC_Polarity_eBotField; |
|---|
| 182 | break; |
|---|
| 183 | |
|---|
| 184 | case 1: |
|---|
| 185 | default: |
|---|
| 186 | eTargetSourcePolarity = BAVC_Polarity_eTopField; |
|---|
| 187 | break; |
|---|
| 188 | } |
|---|
| 189 | } |
|---|
| 190 | else |
|---|
| 191 | { |
|---|
| 192 | if ( ( false == hXdmPP->stDMState.stDecode.bFirstPPBHasBeenDisplayed ) |
|---|
| 193 | && ( false == hXdmPP->stDMState.stChannel.stSelectedPicture.stPicParms.stDisplay.stDynamic.bHolding ) |
|---|
| 194 | ) |
|---|
| 195 | { |
|---|
| 196 | /* We don't want to start FIC if we haven't displayed the |
|---|
| 197 | * first picture, yet */ |
|---|
| 198 | return BERR_SUCCESS; |
|---|
| 199 | } |
|---|
| 200 | |
|---|
| 201 | switch ( hXdmPP->stDMState.stChannel.ePrevSourcePolarity ) |
|---|
| 202 | { |
|---|
| 203 | case BAVC_Polarity_eTopField: |
|---|
| 204 | eTargetSourcePolarity = BAVC_Polarity_eBotField; |
|---|
| 205 | break; |
|---|
| 206 | |
|---|
| 207 | case BAVC_Polarity_eBotField: |
|---|
| 208 | case BAVC_Polarity_eFrame: |
|---|
| 209 | default: |
|---|
| 210 | eTargetSourcePolarity = BAVC_Polarity_eTopField; |
|---|
| 211 | break; |
|---|
| 212 | } |
|---|
| 213 | |
|---|
| 214 | bTargetSourcePolarityIsStatic = true; |
|---|
| 215 | } |
|---|
| 216 | } |
|---|
| 217 | else |
|---|
| 218 | { |
|---|
| 219 | eTargetSourcePolarity = pLocalState->eVsyncPolarity; |
|---|
| 220 | } |
|---|
| 221 | |
|---|
| 222 | /* Determine if FIC should be enabled or not. We only perform FIC |
|---|
| 223 | * if: |
|---|
| 224 | * 1) we're not in decoder trick mode AND |
|---|
| 225 | * 2) we're not frozen AND |
|---|
| 226 | * 3) we're not in an STC trick mode |
|---|
| 227 | * 4) We're doing an FIC compatible rate conversion |
|---|
| 228 | * 5) The source is interlaced |
|---|
| 229 | * 6) We're not repeating the element (we only perform FIC on new elements) |
|---|
| 230 | * 7) The TSM result is PASS |
|---|
| 231 | * 8) The dStcPtsDiff is within a dPTS (we've achieved tight TSM) |
|---|
| 232 | * 9) The source is not coded progressive AND |
|---|
| 233 | * 10) The source polarity doesn't match the vsync polarity AND |
|---|
| 234 | * 11) CRC mode is not enabled |
|---|
| 235 | */ |
|---|
| 236 | |
|---|
| 237 | /* SW7340-116: only perform FIC if the CDT logic set the scan mode to interlaced. */ |
|---|
| 238 | |
|---|
| 239 | pstPicture->stPicParms.stDisplay.stDynamic.bFICEnabled = false; |
|---|
| 240 | if ( ( BXDM_PictureProvider_P_ScanMode_eInterlaced == pstPicture->stPicParms.stDisplay.stStatic.eScanMode ) |
|---|
| 241 | && ( 0 != pLocalState->stEffectiveSTCDelta[pstPicture->stPicParms.stTSM.stDynamic.eSelectionMode].uiWhole ) ) |
|---|
| 242 | { |
|---|
| 243 | bool bTrickMode=false; |
|---|
| 244 | |
|---|
| 245 | /* PR55297: We want to calculate the effective PTS after a |
|---|
| 246 | * trick mode to determine if we need to enable FIC. |
|---|
| 247 | * E.g. 50->60Hz conversion normally does not have FIC enabled, |
|---|
| 248 | * however if in 1.2x or faster trick mode, we DO want to enable |
|---|
| 249 | * FIC to prevent inversion. |
|---|
| 250 | */ |
|---|
| 251 | bool bFICRequired = false; |
|---|
| 252 | |
|---|
| 253 | /* SW7550-349: When in STC pause, the FIC logic is expected to be disabled. |
|---|
| 254 | * However on content that is source/display rate matched, when a |
|---|
| 255 | * frame advance occurs, via the STC being set to GetNextPTSInfo.ui32EffectivePTS, |
|---|
| 256 | * XDM doesn't know if normal playback has resumed or if a frame advance occurred |
|---|
| 257 | * because the stEffectiveSTCDelta is identical for a single vsync. This caused the |
|---|
| 258 | * FIC logic to be enabled on the same vsync that the STC frame advance occurred, |
|---|
| 259 | * which could cause the "effectivePTS" value to change if the FICOffset happened to |
|---|
| 260 | * change. This could prevent the frame advance from actually occurring. To prevent |
|---|
| 261 | * this, the following logic turns off FIC if: |
|---|
| 262 | * 1) The picture's selection mode is TSM |
|---|
| 263 | * 2) The STC Trick Mode (which has hysteresis) is pause |
|---|
| 264 | */ |
|---|
| 265 | bTrickMode = ( ( BXDM_PictureProvider_P_STCTrickMode_ePause == pLocalState->eSTCTrickMode ) |
|---|
| 266 | && ( BXDM_PictureProvider_DisplayMode_eTSM == pstPicture->stPicParms.stTSM.stDynamic.eSelectionMode )); |
|---|
| 267 | |
|---|
| 268 | |
|---|
| 269 | /* SWDEPRECATED-1003: turns off the FIC logic if the middleware/application has specified |
|---|
| 270 | * that the system is in a trick mode. For example, I or IP only mode. This is not required for |
|---|
| 271 | * STC trick modes since they are detected automatically. The default setting for "eTrickMode" |
|---|
| 272 | * is "BXDM_PictureProvider_TrickMode_eAuto". |
|---|
| 273 | */ |
|---|
| 274 | bTrickMode |= ( !( BXDM_PictureProvider_TrickMode_eAuto == hXdmPP->stDMConfig.eTrickMode ) |
|---|
| 275 | && !( BXDM_PictureProvider_TrickMode_eNormal == hXdmPP->stDMConfig.eTrickMode ) ); |
|---|
| 276 | |
|---|
| 277 | |
|---|
| 278 | |
|---|
| 279 | /* SWBLURAY-22573: Turn off the FIC logic for MVC streams, the content will always be progress |
|---|
| 280 | * (well at least for the near term) and the interrupt polarity will always be frame. |
|---|
| 281 | * However the logic can get fooled due to "overloading". The CDT logic could set "eScanMode" |
|---|
| 282 | * to interlaced even though the content is progressive. The interrupt polarity will be " eTopField" |
|---|
| 283 | * for base/left and " eBottomField" for dependent/right. |
|---|
| 284 | */ |
|---|
| 285 | bTrickMode |= ( BAVC_VideoCompressionStd_eMVC == hXdmPP->stDMConfig.eProtocol ); |
|---|
| 286 | |
|---|
| 287 | /* SWDEPRECATED-1003: turn off FIC if forcing everthing to be treated as FrameX1. */ |
|---|
| 288 | bTrickMode |= ( true == hXdmPP->stDMConfig.stFrameRateOverride.bTreatAsSingleElement ); |
|---|
| 289 | |
|---|
| 290 | /* SW7425-1264: If using the SW STC, disable FIC. We should be able to use FIC |
|---|
| 291 | * if the display rate is 1:1, but the assumption is that the SW STC will be used for |
|---|
| 292 | * fast rewind. |
|---|
| 293 | */ |
|---|
| 294 | bTrickMode |= ( true == hXdmPP->stDMConfig.stClockOverride.bEnableClockOverride ); |
|---|
| 295 | |
|---|
| 296 | if ( true == bTrickMode ) |
|---|
| 297 | { |
|---|
| 298 | bFICRequired = false; |
|---|
| 299 | } |
|---|
| 300 | else |
|---|
| 301 | { |
|---|
| 302 | BXDM_PPFP_P_DataType stDisplayRate; |
|---|
| 303 | |
|---|
| 304 | BXDM_PPFP_P_FixPtDiv( |
|---|
| 305 | &pstPicture->stPicParms.stTSM.stStatic.stPTSDelta, |
|---|
| 306 | pLocalState->stEffectiveSTCDelta[pstPicture->stPicParms.stTSM.stDynamic.eSelectionMode].uiWhole, |
|---|
| 307 | &stDisplayRate); |
|---|
| 308 | |
|---|
| 309 | /* We always require FIC if the source -> display rate is 1:1 */ |
|---|
| 310 | bFICRequired = ( ( stDisplayRate.uiWhole == 1 ) |
|---|
| 311 | && ( stDisplayRate.uiFractional <= ( BXDM_PictureProvider_P_FixedPoint_FractionalOverflow / 100 ) ) ); |
|---|
| 312 | |
|---|
| 313 | switch ( hXdmPP->stDMConfig.ePictureDropMode ) |
|---|
| 314 | { |
|---|
| 315 | case BXDM_PictureProvider_PictureDropMode_eFrame: |
|---|
| 316 | /* In frame drop mode, we always want to enable FIC if the |
|---|
| 317 | * STC is moving faster or same as the PTS values. |
|---|
| 318 | * I.e. there's 1 or more fields delivered per vsync. |
|---|
| 319 | */ |
|---|
| 320 | bFICRequired |= ( stDisplayRate.uiWhole == 0 ); |
|---|
| 321 | break; |
|---|
| 322 | |
|---|
| 323 | case BXDM_PictureProvider_PictureDropMode_eField: |
|---|
| 324 | default: |
|---|
| 325 | /* In field drop mode, we want to enable FIC only if the |
|---|
| 326 | * STC is moving at the same rate as the PTS values. |
|---|
| 327 | * I.e there's 1 field delivered per vsync. |
|---|
| 328 | * |
|---|
| 329 | * We also treat close rates the same, so we have |
|---|
| 330 | * a +/- 1% window around 1 |
|---|
| 331 | * |
|---|
| 332 | * E.g. 29.97 -> 30 and 30->29.97 are considered 1:1 |
|---|
| 333 | */ |
|---|
| 334 | bFICRequired |= ( ( stDisplayRate.uiWhole == 0 ) |
|---|
| 335 | && ( stDisplayRate.uiFractional >= ( BXDM_PictureProvider_P_FixedPoint_FractionalOverflow - ( BXDM_PictureProvider_P_FixedPoint_FractionalOverflow / 100 ) ) ) ); |
|---|
| 336 | break; |
|---|
| 337 | } |
|---|
| 338 | } |
|---|
| 339 | #if 0 |
|---|
| 340 | BKNI_Printf("bFICRequired = %d (display rate = %d.%d = (%d.%d / %d)\n", |
|---|
| 341 | bFICRequired, |
|---|
| 342 | stDisplayRate.uiWhole, |
|---|
| 343 | stDisplayRate.uiFractional, |
|---|
| 344 | pstPicture->stPicParms.stPTSDelta.uiWhole, |
|---|
| 345 | pstPicture->stPicParms.stPTSDelta.uiFractional, |
|---|
| 346 | pLocalState->stEffectiveSTCDelta[pLocalState->eDisplayMode].uiWhole); |
|---|
| 347 | #endif |
|---|
| 348 | |
|---|
| 349 | if ( ( true == bFICRequired ) |
|---|
| 350 | && ( false == hXdmPP->stDMConfig.bFreeze ) /* We're not in a freeze state */ |
|---|
| 351 | && ( false == hXdmPP->stDMConfig.bCRCMode ) |
|---|
| 352 | ) |
|---|
| 353 | { |
|---|
| 354 | pstPicture->stPicParms.stDisplay.stDynamic.bFICEnabled = true; |
|---|
| 355 | |
|---|
| 356 | if ( ( ( false == pstPicture->stPicParms.stDisplay.stDynamic.bPPBRepeated ) |
|---|
| 357 | || ( ( true == pstPicture->stPicParms.stDisplay.stDynamic.bPPBRepeated ) |
|---|
| 358 | && ( true == hXdmPP->stDMState.stChannel.stPreviousPictureUnderEvaluation.bValidated ) |
|---|
| 359 | && ( hXdmPP->stDMState.stChannel.stPreviousPicture.stPicParms.stDisplay.stDynamic.uiSelectedElement != pstPicture->stPicParms.stDisplay.stDynamic.uiSelectedElement ) /* We're repeating the element */ ) ) |
|---|
| 360 | && ( BXDM_PictureProvider_TSMResult_eWait != pstPicture->stPicParms.stTSM.stDynamic.eTsmResult ) |
|---|
| 361 | && ( BXDM_PictureProvider_TSMResult_eTooEarly != pstPicture->stPicParms.stTSM.stDynamic.eTsmResult ) |
|---|
| 362 | && ( BXDM_PictureProvider_TSMResult_eDrop != pstPicture->stPicParms.stTSM.stDynamic.eTsmResult ) |
|---|
| 363 | && ( pstPicture->stPicParms.stDisplay.stDynamic.eSourcePolarity != eTargetSourcePolarity ) |
|---|
| 364 | |
|---|
| 365 | ) |
|---|
| 366 | { |
|---|
| 367 | /* PR51134: To prevent jitter, we need to reset the FIC offset if |
|---|
| 368 | * the queue runs dry. This is to prevent jitter on the display */ |
|---|
| 369 | if ( ( pstPicture->stPicParms.stTSM.stDynamic.iStcPtsDifferenceEvaluated > (int32_t) pstPicture->stPicParms.stTSM.stStatic.stPTSDelta.uiWhole ) |
|---|
| 370 | && ( false == bTargetSourcePolarityIsStatic ) |
|---|
| 371 | ) |
|---|
| 372 | { |
|---|
| 373 | BXDM_PPFIC_P_ResetFieldInversionCorrectionOffset( |
|---|
| 374 | hXdmPP, |
|---|
| 375 | pLocalState); |
|---|
| 376 | } |
|---|
| 377 | |
|---|
| 378 | if ( (0 == hXdmPP->stDMState.stDecode.stFieldInversionCorrectionPTSOffset.uiWhole ) |
|---|
| 379 | && (0 == hXdmPP->stDMState.stDecode.stFieldInversionCorrectionPTSOffset.uiFractional ) |
|---|
| 380 | ) |
|---|
| 381 | { |
|---|
| 382 | /* We have a first pass slot, so offset the PTS by |
|---|
| 383 | * deltaPTS so that next time we pick the same |
|---|
| 384 | * element which should correct field inversion */ |
|---|
| 385 | hXdmPP->stDMState.stDecode.stFieldInversionCorrectionPTSOffset = pstPicture->stPicParms.stTSM.stStatic.stPTSDelta; |
|---|
| 386 | pLocalState->bFICChanged = true; |
|---|
| 387 | |
|---|
| 388 | BXDM_PPDBG_P_SelectionLog( hXdmPP, BXDM_PPDBG_Selection_PolarityOverride_e1stSlotRepeat ); |
|---|
| 389 | if ( pstPicture->stPicParms.stDisplay.stDynamic.uiSelectedElement ) |
|---|
| 390 | { |
|---|
| 391 | BXDM_PPFIC_S_SelectPreviousElement(hXdmPP, |
|---|
| 392 | pLocalState, |
|---|
| 393 | pstPicture); |
|---|
| 394 | |
|---|
| 395 | BXVD_DBG_MSG(hXdmPP,("%x: [%01x.%03x] Polarity Override: 1st slot, selected element %d", |
|---|
| 396 | hXdmPP->stDMState.stDecode.stDebug.uiVsyncCount, |
|---|
| 397 | hXdmPP->stDMConfig.uiInstanceID & 0xF, |
|---|
| 398 | pstPicture->stPicParms.uiPPBIndex & 0xFFF, |
|---|
| 399 | pstPicture->stPicParms.stDisplay.stDynamic.uiSelectedElement)); |
|---|
| 400 | } |
|---|
| 401 | else |
|---|
| 402 | { |
|---|
| 403 | BXVD_DBG_MSG(hXdmPP,("%x: [%01x.%03x] Polarity Override: 1st slot, TSM eWait", |
|---|
| 404 | hXdmPP->stDMState.stDecode.stDebug.uiVsyncCount, |
|---|
| 405 | hXdmPP->stDMConfig.uiInstanceID & 0xF, |
|---|
| 406 | pstPicture->stPicParms.uiPPBIndex & 0xFFF)); |
|---|
| 407 | |
|---|
| 408 | pstPicture->stPicParms.stTSM.stDynamic.eTsmResult = BXDM_PictureProvider_TSMResult_eWait; |
|---|
| 409 | } |
|---|
| 410 | } |
|---|
| 411 | else |
|---|
| 412 | { |
|---|
| 413 | /* We have a second pass slot, so we reset the PTS |
|---|
| 414 | * offset to zero so that next time we pick the |
|---|
| 415 | * element with the proper polarity */ |
|---|
| 416 | hXdmPP->stDMState.stDecode.stFieldInversionCorrectionPTSOffset.uiWhole = 0; |
|---|
| 417 | hXdmPP->stDMState.stDecode.stFieldInversionCorrectionPTSOffset.uiFractional = 0; |
|---|
| 418 | pLocalState->bFICChanged = true; |
|---|
| 419 | |
|---|
| 420 | if ( pstPicture->stPicParms.stTSM.stStatic.uiNumElements > (pstPicture->stPicParms.stDisplay.stDynamic.uiSelectedElement + 1) ) |
|---|
| 421 | { |
|---|
| 422 | /* If we're in a 2nd slot TSM pass AND there is |
|---|
| 423 | * more than one element, we can pick the NEXT |
|---|
| 424 | * element for display which should be in the 1st |
|---|
| 425 | * TSM slot which should prevent field inversion |
|---|
| 426 | * on THIS vsync */ |
|---|
| 427 | pstPicture->stPicParms.stDisplay.stDynamic.uiSelectedElement++; |
|---|
| 428 | BXVD_DBG_MSG(hXdmPP,("%x: [%01x.%03x] Polarity Override: 2nd slot (next element)", |
|---|
| 429 | hXdmPP->stDMState.stDecode.stDebug.uiVsyncCount, |
|---|
| 430 | hXdmPP->stDMConfig.uiInstanceID & 0xF, |
|---|
| 431 | pstPicture->stPicParms.uiPPBIndex & 0xFFF)); |
|---|
| 432 | BXDM_PPDBG_P_SelectionLog( hXdmPP, BXDM_PPDBG_Selection_PolarityOverride_e2ndSlotNextElement ); |
|---|
| 433 | } |
|---|
| 434 | else |
|---|
| 435 | { |
|---|
| 436 | BXVD_DBG_MSG(hXdmPP,("%x: [%01x.%03x] Polarity Override: 2nd slot (next ppb)", |
|---|
| 437 | hXdmPP->stDMState.stDecode.stDebug.uiVsyncCount, |
|---|
| 438 | hXdmPP->stDMConfig.uiInstanceID & 0xF, |
|---|
| 439 | pstPicture->stPicParms.uiPPBIndex & 0xFFF)); |
|---|
| 440 | BXDM_PPDBG_P_SelectionLog( hXdmPP, BXDM_PPDBG_Selection_PolarityOverride_e2ndSlotNextPPB ); |
|---|
| 441 | |
|---|
| 442 | BXDM_PPFIC_S_SelectPreviousElement(hXdmPP, |
|---|
| 443 | pLocalState, |
|---|
| 444 | pstPicture); |
|---|
| 445 | } |
|---|
| 446 | } |
|---|
| 447 | |
|---|
| 448 | /* We need to reset the source polarity if FIC has |
|---|
| 449 | * changed the originally selected element */ |
|---|
| 450 | BXDM_PPQM_P_GetElementPolarity( |
|---|
| 451 | pstPicture, |
|---|
| 452 | pstPicture->stPicParms.stDisplay.stDynamic.uiSelectedElement, |
|---|
| 453 | &(pstPicture->stPicParms.stDisplay.stDynamic.eSourcePolarity) |
|---|
| 454 | ); |
|---|
| 455 | } |
|---|
| 456 | } |
|---|
| 457 | } |
|---|
| 458 | |
|---|
| 459 | return BERR_SUCCESS; |
|---|
| 460 | } |
|---|
| 461 | |
|---|
| 462 | BERR_Code BXDM_PPFIC_P_ResetFieldInversionCorrectionOffset( |
|---|
| 463 | BXDM_PictureProvider_Handle hXdmPP, |
|---|
| 464 | BXDM_PictureProvider_P_LocalState* pLocalState |
|---|
| 465 | ) |
|---|
| 466 | { |
|---|
| 467 | /* Determine if the FIC offset should be reset */ |
|---|
| 468 | if ( ( 0 != hXdmPP->stDMState.stDecode.stFieldInversionCorrectionPTSOffset.uiWhole ) |
|---|
| 469 | && ( 0 != hXdmPP->stDMState.stDecode.stFieldInversionCorrectionPTSOffset.uiFractional ) |
|---|
| 470 | ) |
|---|
| 471 | { |
|---|
| 472 | BXVD_DBG_MSG(hXdmPP,("%x: FIC Reset", hXdmPP->stDMState.stDecode.stDebug.uiVsyncCount)); |
|---|
| 473 | BXDM_PPDBG_P_SelectionLog( hXdmPP, BXDM_PPDBG_Selection_PolarityOverride_eFICReset ); |
|---|
| 474 | hXdmPP->stDMState.stDecode.stFieldInversionCorrectionPTSOffset.uiWhole = 0; |
|---|
| 475 | hXdmPP->stDMState.stDecode.stFieldInversionCorrectionPTSOffset.uiFractional = 0; |
|---|
| 476 | pLocalState->bFICChanged = true; |
|---|
| 477 | } |
|---|
| 478 | |
|---|
| 479 | return BERR_SUCCESS; |
|---|
| 480 | } |
|---|