| 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_clip.c $ |
|---|
| 11 | * $brcm_Revision: Hydra_Software_Devel/12 $ |
|---|
| 12 | * $brcm_Date: 5/10/11 1:41p $ |
|---|
| 13 | * |
|---|
| 14 | * [File Description:] |
|---|
| 15 | * |
|---|
| 16 | * Revision History: |
|---|
| 17 | * |
|---|
| 18 | * $brcm_Log: /magnum/commonutils/xdm/bxdm_pp_clip.c $ |
|---|
| 19 | * |
|---|
| 20 | * Hydra_Software_Devel/12 5/10/11 1:41p btosi |
|---|
| 21 | * SW7405-4736: added range checking and debug messages for the input |
|---|
| 22 | * parameters |
|---|
| 23 | * |
|---|
| 24 | * Hydra_Software_Devel/11 12/21/10 4:24p delkert |
|---|
| 25 | * SW7405-5043: Split STC stored in local state into two parts: STC from |
|---|
| 26 | * decoder and STC after JTI adjustment |
|---|
| 27 | * |
|---|
| 28 | * Hydra_Software_Devel/10 11/5/10 11:15a btosi |
|---|
| 29 | * SWBLURAY-23188: under certain conditions, reset bClipActive sooner |
|---|
| 30 | * |
|---|
| 31 | * Hydra_Software_Devel/9 9/28/10 3:04p btosi |
|---|
| 32 | * SWBLURAY-22390: for BD, don't load parameters for the next clip until |
|---|
| 33 | * both the stop event has occurred and the marker has been seen. |
|---|
| 34 | * |
|---|
| 35 | * Hydra_Software_Devel/8 9/23/10 3:09p btosi |
|---|
| 36 | * SW7405-4736: add support for a XDM instance ID to help debug multi- |
|---|
| 37 | * channel issues |
|---|
| 38 | * |
|---|
| 39 | * Hydra_Software_Devel/7 8/10/10 4:16p btosi |
|---|
| 40 | * SW7405-4736: added PPB index to debug messages |
|---|
| 41 | * |
|---|
| 42 | * Hydra_Software_Devel/6 8/4/10 1:22p btosi |
|---|
| 43 | * SWBLURAY-21565: to aid debug, added uiPPBIndex to debug messages |
|---|
| 44 | * |
|---|
| 45 | * Hydra_Software_Devel/5 7/20/10 2:57p btosi |
|---|
| 46 | * SWBLURAY-21565: only allow the last picture of a clip to generate one |
|---|
| 47 | * stop event |
|---|
| 48 | * |
|---|
| 49 | * Hydra_Software_Devel/4 7/12/10 8:04a delkert |
|---|
| 50 | * SW7335-781: Output warning when forcing picture selection override to |
|---|
| 51 | * allow easier detection of conditions such as drop@decode and pcr |
|---|
| 52 | * discontinuity |
|---|
| 53 | * |
|---|
| 54 | * Hydra_Software_Devel/3 5/4/10 2:40p delkert |
|---|
| 55 | * SWBLURAY-19994: Override clip stop time of 0xFFFFFFFF with predicted |
|---|
| 56 | * start time of next clip - 1, to allow seamless transition between |
|---|
| 57 | * clips |
|---|
| 58 | * |
|---|
| 59 | * Hydra_Software_Devel/2 4/12/10 2:14p btosi |
|---|
| 60 | * SW7630-76: add support for a seamless connection with a clip stop time |
|---|
| 61 | * of 0xFFFFFFFF |
|---|
| 62 | * |
|---|
| 63 | * Hydra_Software_Devel/1 2/16/10 10:51a nilesh |
|---|
| 64 | * SW7405-2993: Initial XDM version |
|---|
| 65 | * |
|---|
| 66 | ***************************************************************************/ |
|---|
| 67 | |
|---|
| 68 | #include "bstd.h" |
|---|
| 69 | #include "bkni.h" |
|---|
| 70 | #include "bdbg.h" /* Dbglib */ |
|---|
| 71 | |
|---|
| 72 | #include "bxdm_pp.h" |
|---|
| 73 | #include "bxdm_pp_priv.h" |
|---|
| 74 | #include "bxdm_pp_qm.h" |
|---|
| 75 | |
|---|
| 76 | BDBG_MODULE(BXDM_PPCLIP); /* Register software module with debug interface */ |
|---|
| 77 | |
|---|
| 78 | const char BXDM_PictureProvider_P_DISPMGR_CLIP_NODE[]="DMCLIP:\t""$brcm_Revision: Hydra_Software_Devel/12 $"; |
|---|
| 79 | |
|---|
| 80 | #define BXDM_PictureProvider_P_CLIPTIME_PTS_WRAP_THRESHOLD (0x80000000) |
|---|
| 81 | #define BXDM_PictureProvider_P_CLIPTIME_STC_WRAP_THRESHOLD (0x80000000) |
|---|
| 82 | |
|---|
| 83 | void BXDM_PPCLIP_P_ClipTimeCallbackTriggerHandler( |
|---|
| 84 | BXDM_PictureProvider_Handle hXdmPP, |
|---|
| 85 | BXDM_PictureProvider_P_LocalState * pLocalState, |
|---|
| 86 | BXDM_PictureProvider_P_Picture_Context * pstPicture |
|---|
| 87 | ) |
|---|
| 88 | { |
|---|
| 89 | BXDM_PictureProvider_P_ClipTimeV2 * pstCurrentClip = &( hXdmPP->stDMState.stChannel.stClipInfo.stCurrentClip ); |
|---|
| 90 | |
|---|
| 91 | /* Check for clip start */ |
|---|
| 92 | if ( ( true == hXdmPP->stCallbacks[BXDM_PictureProvider_Callback_eClipStart].bEnable ) |
|---|
| 93 | && ( true == pstCurrentClip->stTime.bValid ) |
|---|
| 94 | && ( ( BXDM_PictureProvider_ClipTimeType_eEnableBothWithDVDCompatibility == pstCurrentClip->stTime.eType ) |
|---|
| 95 | || ( BXDM_PictureProvider_ClipTimeType_eEnableBoth == pstCurrentClip->stTime.eType ) |
|---|
| 96 | || ( BXDM_PictureProvider_ClipTimeType_eClipStartOnly == pstCurrentClip->stTime.eType ) |
|---|
| 97 | ) |
|---|
| 98 | && ( true == pstCurrentClip->stStartEvent.bOccurred ) |
|---|
| 99 | && ( true == pstCurrentClip->stDisplayEvent.bOccurred ) |
|---|
| 100 | ) |
|---|
| 101 | { |
|---|
| 102 | BXVD_DBG_MSG(hXdmPP,("%x: [%01x.%03x] Trigger Clip Start", |
|---|
| 103 | hXdmPP->stDMState.stDecode.stDebug.uiVsyncCount, |
|---|
| 104 | hXdmPP->stDMConfig.uiInstanceID & 0xF, |
|---|
| 105 | pstPicture->stPicParms.uiPPBIndex & 0xFFF)); |
|---|
| 106 | hXdmPP->stCallbacks[BXDM_PictureProvider_Callback_eClipStart].bEnable = false; |
|---|
| 107 | pLocalState->stCallbackInfo.stClipStart.bTriggered = true; |
|---|
| 108 | pLocalState->stCallbackInfo.stClipStart.stClipEventInfo.uiPTS = pstCurrentClip->stStartEvent.uiTime; |
|---|
| 109 | pLocalState->stCallbackInfo.stClipStart.stClipEventInfo.uiClipId = pstCurrentClip->stTime.uiId; |
|---|
| 110 | |
|---|
| 111 | if ( BXDM_PictureProvider_ClipTimeType_eClipStartOnly == pstCurrentClip->stTime.eType ) |
|---|
| 112 | { |
|---|
| 113 | /* Auto disable clip logic in start only mode */ |
|---|
| 114 | BXVD_DBG_MSG(hXdmPP,("%x: [%01x.%03x] Auto-Disable Clip Logic (ClipStartOnly)", |
|---|
| 115 | hXdmPP->stDMState.stDecode.stDebug.uiVsyncCount, |
|---|
| 116 | hXdmPP->stDMConfig.uiInstanceID & 0xF, |
|---|
| 117 | pstPicture->stPicParms.uiPPBIndex & 0xFFF)); |
|---|
| 118 | BKNI_Memset( &hXdmPP->stDMState.stChannel.stClipInfo.stCurrentClip, |
|---|
| 119 | 0, |
|---|
| 120 | sizeof( BXDM_PictureProvider_P_ClipTimeV2 ) ); |
|---|
| 121 | } |
|---|
| 122 | } |
|---|
| 123 | else if ( false == pLocalState->stCallbackInfo.stClipStart.bTriggered ) |
|---|
| 124 | { |
|---|
| 125 | /* Check for clip stop */ |
|---|
| 126 | if ( ( true == hXdmPP->stCallbacks[BXDM_PictureProvider_Callback_eClipStop].bEnable ) |
|---|
| 127 | && ( true == pstCurrentClip->stTime.bValid ) |
|---|
| 128 | && ( ( BXDM_PictureProvider_ClipTimeType_eEnableBothWithDVDCompatibility == pstCurrentClip->stTime.eType ) |
|---|
| 129 | || ( BXDM_PictureProvider_ClipTimeType_eEnableBoth == pstCurrentClip->stTime.eType ) |
|---|
| 130 | || ( BXDM_PictureProvider_ClipTimeType_eClipStopOnly == pstCurrentClip->stTime.eType ) |
|---|
| 131 | ) |
|---|
| 132 | && ( true == pstCurrentClip->stStartEvent.bOccurred ) |
|---|
| 133 | && ( true == pstCurrentClip->stDisplayEvent.bOccurred ) |
|---|
| 134 | && ( true == pstCurrentClip->stStopEvent.bOccurred ) |
|---|
| 135 | ) |
|---|
| 136 | { |
|---|
| 137 | BXVD_DBG_MSG(hXdmPP,("%x: [%01x.%03x] Trigger Clip Stop", |
|---|
| 138 | hXdmPP->stDMState.stDecode.stDebug.uiVsyncCount, |
|---|
| 139 | hXdmPP->stDMConfig.uiInstanceID & 0xF, |
|---|
| 140 | pstPicture->stPicParms.uiPPBIndex & 0xFFF)); |
|---|
| 141 | hXdmPP->stCallbacks[BXDM_PictureProvider_Callback_eClipStop].bEnable = false; |
|---|
| 142 | pLocalState->stCallbackInfo.stClipStop.bTriggered = true; |
|---|
| 143 | pLocalState->stCallbackInfo.stClipStop.stClipEventInfo.uiPTS = pstCurrentClip->stStopEvent.uiTime; |
|---|
| 144 | pLocalState->stCallbackInfo.stClipStop.stClipEventInfo.uiClipId = pstCurrentClip->stTime.uiId; |
|---|
| 145 | /* SWBLURAY-22390: see code block below hXdmPP->stDMState.stChannel.stClipInfo.bClipActive = false;*/ |
|---|
| 146 | } |
|---|
| 147 | |
|---|
| 148 | /* Check for picture marker */ |
|---|
| 149 | if ( ( true == hXdmPP->stCallbacks[BXDM_PictureProvider_Callback_ePictureMarker].bEnable ) |
|---|
| 150 | && ( true == pstCurrentClip->stTime.bValid ) |
|---|
| 151 | && ( true == pstCurrentClip->stMarkerEvent.bOccurred ) |
|---|
| 152 | && ( ( false == pstCurrentClip->stMarkerEvent.bDelayedCallback ) |
|---|
| 153 | || ( true == pstCurrentClip->stStopEvent.bOccurred ) |
|---|
| 154 | /* PR56292: Trigger the marker callback if the first |
|---|
| 155 | * picture containing the marker is displayed */ |
|---|
| 156 | || ( ( BXDM_PictureProvider_TSMResult_ePass == pstPicture->stPicParms.stTSM.stDynamic.eTsmResult ) |
|---|
| 157 | && ( pstCurrentClip->stMarkerEvent.uiTime == pstPicture->pstUnifiedPicture->stPictureMarker.uiValue ) ) |
|---|
| 158 | ) |
|---|
| 159 | ) |
|---|
| 160 | { |
|---|
| 161 | BXVD_DBG_MSG(hXdmPP,("%x: [%01x.%03x] Trigger Marker", |
|---|
| 162 | hXdmPP->stDMState.stDecode.stDebug.uiVsyncCount, |
|---|
| 163 | hXdmPP->stDMConfig.uiInstanceID & 0xF, |
|---|
| 164 | pstPicture->stPicParms.uiPPBIndex & 0xFFF)); |
|---|
| 165 | hXdmPP->stCallbacks[BXDM_PictureProvider_Callback_ePictureMarker].bEnable = false; |
|---|
| 166 | pLocalState->stCallbackInfo.stPictureMarker.bTriggered = true; |
|---|
| 167 | pLocalState->stCallbackInfo.stPictureMarker.stClipEventInfo.uiPTS = pstCurrentClip->stMarkerEvent.uiTime; |
|---|
| 168 | pLocalState->stCallbackInfo.stPictureMarker.stClipEventInfo.uiClipId = pstCurrentClip->stTime.uiId; |
|---|
| 169 | } |
|---|
| 170 | |
|---|
| 171 | /* SWBLURAY-22390: The problem was observed when playing the PIP from USB and main from optical disk. |
|---|
| 172 | * The video clips are in sync and transition to the next clip at the same time. At the end of the |
|---|
| 173 | * PIP clip, two vsync's were not delivered to XDM. This was probably due to accessing video data on |
|---|
| 174 | * the USB drive. The failure was as follows; |
|---|
| 175 | * - due to the two missing vsync's, the next to the last picture of the 1st clip triggers the 1st clip stop |
|---|
| 176 | * - the occurrence of the clip stop results in the loading of the start/stop parameters for the 2nd clip |
|---|
| 177 | * - the last picture of the 1st clip is within one picture time of the end of the 2nd clip, this results in |
|---|
| 178 | * the 2nd clip start and stop callbacks being generated off this picture |
|---|
| 179 | * |
|---|
| 180 | * The fix is to not load the parameters for the next clip until both the stop event has occurred |
|---|
| 181 | * and the marker has been seen. |
|---|
| 182 | */ |
|---|
| 183 | if ( BXDM_PictureProvider_ClipTimeType_eEnableBothWithDVDCompatibility == pstCurrentClip->stTime.eType ) |
|---|
| 184 | { |
|---|
| 185 | if ( ( true == pstCurrentClip->stStopEvent.bOccurred ) |
|---|
| 186 | && ( true == pstCurrentClip->stMarkerEvent.bOccurred ) |
|---|
| 187 | ) |
|---|
| 188 | { |
|---|
| 189 | hXdmPP->stDMState.stChannel.stClipInfo.bClipActive = false; |
|---|
| 190 | } |
|---|
| 191 | } |
|---|
| 192 | else |
|---|
| 193 | { |
|---|
| 194 | if ( true == pstCurrentClip->stStopEvent.bOccurred ) |
|---|
| 195 | { |
|---|
| 196 | hXdmPP->stDMState.stChannel.stClipInfo.bClipActive = false; |
|---|
| 197 | } |
|---|
| 198 | } |
|---|
| 199 | |
|---|
| 200 | } |
|---|
| 201 | |
|---|
| 202 | } /* end of BXDM_PPCLIP_P_ClipTimeCallbackTriggerHandler() */ |
|---|
| 203 | |
|---|
| 204 | void BXDM_PPCLIP_P_Reset( |
|---|
| 205 | BXDM_PictureProvider_Handle hXdmPP |
|---|
| 206 | ) |
|---|
| 207 | { |
|---|
| 208 | /* Reset clip info structure */ |
|---|
| 209 | BKNI_Memset( &hXdmPP->stDMState.stChannel.stClipInfo, 0, sizeof (BXDM_PictureProvider_P_ClipInfo) ); |
|---|
| 210 | /* Initialize last timing marker default start value in AVD */ |
|---|
| 211 | hXdmPP->stDMState.stChannel.stClipInfo.uiLastMarker = 0xFFFFFFFF; |
|---|
| 212 | } |
|---|
| 213 | |
|---|
| 214 | bool BXDM_PPCLIP_P_ClipTimeTSMHandler( |
|---|
| 215 | BXDM_PictureProvider_Handle hXdmPP, |
|---|
| 216 | BXDM_PictureProvider_P_LocalState* pLocalState, |
|---|
| 217 | BXDM_PictureProvider_P_Picture_Context* pstPicture, |
|---|
| 218 | bool bEvaluateActualPts, |
|---|
| 219 | BXDM_PictureProvider_TSMResult *peTsmState |
|---|
| 220 | ) |
|---|
| 221 | { |
|---|
| 222 | BXDM_PictureProvider_P_ClipTimeV2 * pstCurrentClip = &( hXdmPP->stDMState.stChannel.stClipInfo.stCurrentClip ); |
|---|
| 223 | bool bResult = false; |
|---|
| 224 | BXDM_PPFP_P_DataType stPts; |
|---|
| 225 | |
|---|
| 226 | /* Get Actual PTS value for this picture for ClipStart/ClipStop |
|---|
| 227 | * calculations */ |
|---|
| 228 | BXDM_PPQM_P_GetPtsWithFrac( pstPicture, |
|---|
| 229 | BXDM_PictureProvider_P_PTSIndex_eActual, |
|---|
| 230 | 0, |
|---|
| 231 | &stPts ); |
|---|
| 232 | |
|---|
| 233 | /* Check for clip start event */ |
|---|
| 234 | if ( ( true == pstCurrentClip->stTime.bValid ) |
|---|
| 235 | && ( ( BXDM_PictureProvider_ClipTimeType_eEnableBothWithDVDCompatibility == pstCurrentClip->stTime.eType ) |
|---|
| 236 | || ( BXDM_PictureProvider_ClipTimeType_eEnableBoth == pstCurrentClip->stTime.eType ) |
|---|
| 237 | || ( BXDM_PictureProvider_ClipTimeType_eClipStartOnly == pstCurrentClip->stTime.eType ) |
|---|
| 238 | ) |
|---|
| 239 | && ( false == pstCurrentClip->stStartEvent.bOccurred ) |
|---|
| 240 | && ( false == pstPicture->stPicParms.stTSM.stDynamic.bClipTransition ) |
|---|
| 241 | && ( false == pstPicture->stPicParms.stDisplay.stDynamic.bPPBRepeated ) |
|---|
| 242 | && ( true == bEvaluateActualPts ) |
|---|
| 243 | && ( false == pstPicture->stPicParms.stDisplay.stDynamic.bGeneratedClipStop ) /* SWBLURAY-21565: only allow the last picture of a clip to generate one stop event */ |
|---|
| 244 | /* PR50077: Handle PTS wrap scenarios for clip start event. |
|---|
| 245 | * We need to handle all of the following start scenarios |
|---|
| 246 | * since both the PTS and clip start times are unsigned values |
|---|
| 247 | * and PTS wraps are allowed: |
|---|
| 248 | * |
|---|
| 249 | * 0) (clip start = 0) - a clip start of 0 indicates the clip |
|---|
| 250 | * start event should occur on the very first picture of the |
|---|
| 251 | * clip |
|---|
| 252 | * |
|---|
| 253 | * 1) (pts >= clip start) - this is a normal scenario, where |
|---|
| 254 | * the first pts value is larger than the clip start time |
|---|
| 255 | * and we don't want to drop anything. E.g. |
|---|
| 256 | * - clip start = 3000 |
|---|
| 257 | * - clip pts values = [4500, 6000, 7500, ...] |
|---|
| 258 | * - we want to trigger the clip start on pts=4500 and not |
|---|
| 259 | * drop anything |
|---|
| 260 | * |
|---|
| 261 | * 2) (pts >> clip start) - this is a pts wrap scenario, |
|---|
| 262 | * where the clip start is very small, but the first pts |
|---|
| 263 | * values are very large. In this scenario, we want to drop |
|---|
| 264 | * all picture until the wrap and then use clip start to |
|---|
| 265 | * filter out the rest. E.g. |
|---|
| 266 | * - clip start = 3000 |
|---|
| 267 | * - clip pts values = [-3000, -1500, 0, 1500, 3000, ...] |
|---|
| 268 | * - we want to drop pictures with pts = [-3000, -1500, 0, |
|---|
| 269 | * 1500] and trigger the clip start on pts=3000 |
|---|
| 270 | * |
|---|
| 271 | * 3) (pts < clip start) - this is the typical scenario, |
|---|
| 272 | * where we want to drop all pts values that are less than |
|---|
| 273 | * the clip start time. E.g. |
|---|
| 274 | * - clip start = 3000 |
|---|
| 275 | * - clip pts values = [0, 1500, 3000, ...] |
|---|
| 276 | * - we want to drop pictures with pts=[0, 1500] and |
|---|
| 277 | * trigger the clip start on pts=3000 |
|---|
| 278 | * |
|---|
| 279 | * 4) (pts << clip start) - this is a pts wrap scenario, |
|---|
| 280 | * where the clip start is very large, but the first pts |
|---|
| 281 | * values are very small. In this scenario, we don't want |
|---|
| 282 | * to drop anything. E.g. |
|---|
| 283 | * - clip start = -3000 (0xFFFFF448) |
|---|
| 284 | * - clip pts values = [4500, 6000, 7500, ...] |
|---|
| 285 | * - we want to trigger the clip start on pts=4500 and not |
|---|
| 286 | * drop anything |
|---|
| 287 | * |
|---|
| 288 | * In the end, we want to trigger the start event if only |
|---|
| 289 | * cases 1) or 4) occur. |
|---|
| 290 | */ |
|---|
| 291 | && ( ( ( 0 == pstCurrentClip->stTime.uiStart ) /* Case 0: start time is 0 */ |
|---|
| 292 | && ( BXDM_PictureProvider_ClipTimeType_eEnableBothWithDVDCompatibility == pstCurrentClip->stTime.eType ) ) |
|---|
| 293 | || ( ( stPts.uiWhole >= pstCurrentClip->stTime.uiStart ) /* Case 1: pts is larger than start time, but not too large */ |
|---|
| 294 | && ( ( stPts.uiWhole - pstCurrentClip->stTime.uiStart ) < BXDM_PictureProvider_P_CLIPTIME_PTS_WRAP_THRESHOLD ) ) |
|---|
| 295 | || ( ( stPts.uiWhole < pstCurrentClip->stTime.uiStart ) /* Case 4: pts is less than the start time, but much lesser */ |
|---|
| 296 | && ( ( pstCurrentClip->stTime.uiStart - stPts.uiWhole ) > BXDM_PictureProvider_P_CLIPTIME_PTS_WRAP_THRESHOLD ) ) |
|---|
| 297 | ) |
|---|
| 298 | ) |
|---|
| 299 | { |
|---|
| 300 | BXVD_DBG_MSG(hXdmPP,("%x: [%01x.%03x] Start Event:: Start Time:%08x PTS:%08x", |
|---|
| 301 | hXdmPP->stDMState.stDecode.stDebug.uiVsyncCount, |
|---|
| 302 | hXdmPP->stDMConfig.uiInstanceID & 0xF, |
|---|
| 303 | pstPicture->stPicParms.uiPPBIndex & 0xFFF, |
|---|
| 304 | pstCurrentClip->stTime.uiStart, |
|---|
| 305 | stPts.uiWhole)); |
|---|
| 306 | pstCurrentClip->stStartEvent.bOccurred = true; |
|---|
| 307 | |
|---|
| 308 | /* We send the coded PTS if it exists, otherwise, we send the start time */ |
|---|
| 309 | if ( true == pstPicture->pstUnifiedPicture->stPTS.bValid ) |
|---|
| 310 | { |
|---|
| 311 | pstCurrentClip->stStartEvent.uiTime = stPts.uiWhole; |
|---|
| 312 | } |
|---|
| 313 | else |
|---|
| 314 | { |
|---|
| 315 | pstCurrentClip->stStartEvent.uiTime = pstCurrentClip->stTime.uiStart; |
|---|
| 316 | } |
|---|
| 317 | } |
|---|
| 318 | |
|---|
| 319 | /* Check for clip start/stop scenario */ |
|---|
| 320 | if ( ( true == pstCurrentClip->stTime.bValid ) |
|---|
| 321 | && ( false == pstPicture->stPicParms.stTSM.stDynamic.bClipTransition ) |
|---|
| 322 | && ( false == pstPicture->stPicParms.stDisplay.stDynamic.bPPBRepeated ) |
|---|
| 323 | && ( ( ( true == bEvaluateActualPts ) |
|---|
| 324 | && ( BXDM_PictureProvider_DisplayMode_eTSM == pLocalState->eSelectionMode ) ) || |
|---|
| 325 | ( ( false == bEvaluateActualPts ) |
|---|
| 326 | && ( BXDM_PictureProvider_DisplayMode_eVirtualTSM == pLocalState->eSelectionMode ) ) |
|---|
| 327 | ) |
|---|
| 328 | ) |
|---|
| 329 | { |
|---|
| 330 | /* Drop pictures that are either before the clip start or after |
|---|
| 331 | * the clip stop */ |
|---|
| 332 | if ( ( false == pstCurrentClip->stStartEvent.bOccurred ) |
|---|
| 333 | && ( ( BXDM_PictureProvider_ClipTimeType_eEnableBothWithDVDCompatibility == pstCurrentClip->stTime.eType ) |
|---|
| 334 | || ( BXDM_PictureProvider_ClipTimeType_eEnableBoth == pstCurrentClip->stTime.eType ) |
|---|
| 335 | || ( BXDM_PictureProvider_ClipTimeType_eClipStartOnly == pstCurrentClip->stTime.eType ) |
|---|
| 336 | ) ) |
|---|
| 337 | { |
|---|
| 338 | BXVD_DBG_MSG(hXdmPP,("%x: [%01x.%03x] Drop pre-start:: Start Time:%08x PTS:%08x", |
|---|
| 339 | hXdmPP->stDMState.stDecode.stDebug.uiVsyncCount, |
|---|
| 340 | hXdmPP->stDMConfig.uiInstanceID & 0xF, |
|---|
| 341 | pstPicture->stPicParms.uiPPBIndex & 0xFFF, |
|---|
| 342 | pstCurrentClip->stTime.uiStart, |
|---|
| 343 | stPts.uiWhole)); |
|---|
| 344 | bResult = true; |
|---|
| 345 | *peTsmState = BXDM_PictureProvider_TSMResult_eDrop; |
|---|
| 346 | } |
|---|
| 347 | else if ( ( true == pstCurrentClip->stStopEvent.bOccurred ) |
|---|
| 348 | && ( ( BXDM_PictureProvider_ClipTimeType_eEnableBothWithDVDCompatibility == pstCurrentClip->stTime.eType ) |
|---|
| 349 | || ( BXDM_PictureProvider_ClipTimeType_eEnableBoth == pstCurrentClip->stTime.eType ) |
|---|
| 350 | || ( BXDM_PictureProvider_ClipTimeType_eClipStopOnly == pstCurrentClip->stTime.eType ) |
|---|
| 351 | ) ) |
|---|
| 352 | { |
|---|
| 353 | /* Drop pictures after a stop event has occurred */ |
|---|
| 354 | BXVD_DBG_MSG(hXdmPP,("%x: [%01x.%03x] Drop post-stop:: Stop Time:%08x PTS:%08x", |
|---|
| 355 | hXdmPP->stDMState.stDecode.stDebug.uiVsyncCount, |
|---|
| 356 | hXdmPP->stDMConfig.uiInstanceID & 0xF, |
|---|
| 357 | pstPicture->stPicParms.uiPPBIndex & 0xFFF, |
|---|
| 358 | pstCurrentClip->stTime.uiStop, |
|---|
| 359 | stPts.uiWhole)); |
|---|
| 360 | bResult = true; |
|---|
| 361 | *peTsmState = BXDM_PictureProvider_TSMResult_eDrop; |
|---|
| 362 | } |
|---|
| 363 | } |
|---|
| 364 | |
|---|
| 365 | /* Handle dummy PPBs */ |
|---|
| 366 | if ( false == pstPicture->pstUnifiedPicture->stBufferInfo.bValid ) |
|---|
| 367 | { |
|---|
| 368 | BXVD_DBG_MSG(hXdmPP,("%x: [%01x.%03x] Dummy PPB", |
|---|
| 369 | hXdmPP->stDMState.stDecode.stDebug.uiVsyncCount, |
|---|
| 370 | hXdmPP->stDMConfig.uiInstanceID & 0xF, |
|---|
| 371 | pstPicture->stPicParms.uiPPBIndex & 0xFFF)); |
|---|
| 372 | /* PR47517: If the start event has already occurred, and we're |
|---|
| 373 | * seeing a dummy PPB, we should assume the display event has |
|---|
| 374 | * occurred because a dummy PPB indicates the end of a clip. |
|---|
| 375 | * The display event gates the generation of the clip |
|---|
| 376 | * start/stop/marker interrupts. This logic is needed in the |
|---|
| 377 | * case where the clip only contains a dummy PPB which actually |
|---|
| 378 | * won't go out to the display. */ |
|---|
| 379 | /* SW7601-175: To handle picture-less clips, we need to assume |
|---|
| 380 | * the start and display event have occurred as soon as we see |
|---|
| 381 | * a dummy PPB. */ |
|---|
| 382 | if ( ( true == pstCurrentClip->stTime.bValid ) |
|---|
| 383 | && ( BXDM_PictureProvider_ClipTimeType_eEnableBothWithDVDCompatibility == pstCurrentClip->stTime.eType ) |
|---|
| 384 | ) |
|---|
| 385 | { |
|---|
| 386 | pstCurrentClip->stStartEvent.bOccurred = true; |
|---|
| 387 | pstCurrentClip->stDisplayEvent.bOccurred = true; |
|---|
| 388 | } |
|---|
| 389 | |
|---|
| 390 | bResult = true; |
|---|
| 391 | *peTsmState = BXDM_PictureProvider_TSMResult_eDrop; |
|---|
| 392 | } |
|---|
| 393 | |
|---|
| 394 | return bResult; |
|---|
| 395 | } |
|---|
| 396 | |
|---|
| 397 | void BXDM_PPCLIP_P_ClipTimeTSMTransitionHandler( |
|---|
| 398 | BXDM_PictureProvider_Handle hXdmPP, |
|---|
| 399 | BXDM_PictureProvider_P_LocalState* pLocalState, |
|---|
| 400 | BXDM_PictureProvider_P_Picture_Context* pstPicture, |
|---|
| 401 | BXDM_PictureProvider_TSMResult *peTsmState |
|---|
| 402 | ) |
|---|
| 403 | { |
|---|
| 404 | BXDM_PictureProvider_P_ClipTimeV2 * pstCurrentClip = &( hXdmPP->stDMState.stChannel.stClipInfo.stCurrentClip ); |
|---|
| 405 | |
|---|
| 406 | /* Handle ClipStop */ |
|---|
| 407 | if ( ( true == pstCurrentClip->stTime.bValid ) /* We're in a valid clip */ |
|---|
| 408 | && ( ( BXDM_PictureProvider_ClipTimeType_eEnableBothWithDVDCompatibility == pstCurrentClip->stTime.eType ) |
|---|
| 409 | || ( BXDM_PictureProvider_ClipTimeType_eEnableBoth == pstCurrentClip->stTime.eType ) |
|---|
| 410 | || ( BXDM_PictureProvider_ClipTimeType_eClipStopOnly == pstCurrentClip->stTime.eType ) |
|---|
| 411 | ) |
|---|
| 412 | && ( true == pstCurrentClip->stStartEvent.bOccurred ) /* A clip has started */ |
|---|
| 413 | && ( true == pstCurrentClip->stDisplayEvent.bOccurred ) |
|---|
| 414 | && ( false == pstCurrentClip->stStopEvent.bOccurred ) /* The clip has not already stopped */ |
|---|
| 415 | && ( false == pstPicture->stPicParms.stDisplay.stDynamic.bGeneratedClipStop ) ) /* SWBLURAY-21565: only allow the last picture of a clip to generate one stop event */ |
|---|
| 416 | { |
|---|
| 417 | /* Handle "faking" clip stop time for End-of-clip (EOC) Mode (stop time not provided by "app") */ |
|---|
| 418 | if ( ( 0xFFFFFFFF == pstCurrentClip->stTime.uiStop ) |
|---|
| 419 | && ( BXDM_PictureProvider_ClipTimeType_eEnableBothWithDVDCompatibility == pstCurrentClip->stTime.eType ) |
|---|
| 420 | && ( 0 != pLocalState->uiSlowMotionRate ) /* We're not in a pause state */ |
|---|
| 421 | && ( true == pstCurrentClip->stMarkerEvent.bOccurred )) /* The marker has been seen */ |
|---|
| 422 | { |
|---|
| 423 | BXDM_PictureProvider_P_Picture_Context* pstPrevPicEvaluated = &(hXdmPP->stDMState.stChannel.stPreviousPictureUnderEvaluation); |
|---|
| 424 | uint32_t uiPredPTS; |
|---|
| 425 | |
|---|
| 426 | /* Use previous picture under evaluation to predict the end, since the selected picture may not be the end if |
|---|
| 427 | intervening frames are dropped */ |
|---|
| 428 | BXDM_PPQM_P_GetPredictedPts(pstPrevPicEvaluated, |
|---|
| 429 | BXDM_PictureProvider_P_PTSIndex_eActual, |
|---|
| 430 | &uiPredPTS ); |
|---|
| 431 | |
|---|
| 432 | /* Set clip stop time to be the predicted PTS of the next picture from the currently selected picture (i.e. the |
|---|
| 433 | expected start time of the next clip) - 1 */ |
|---|
| 434 | pstCurrentClip->stTime.uiStop = uiPredPTS - 1; |
|---|
| 435 | BXVD_DBG_MSG(hXdmPP,("%x: [%01x.%03x] Stop Time Override: 0xFFFFFFFF -> 0x%8.8x\n", |
|---|
| 436 | hXdmPP->stDMState.stDecode.stDebug.uiVsyncCount, |
|---|
| 437 | hXdmPP->stDMConfig.uiInstanceID & 0xF, |
|---|
| 438 | pstPicture->stPicParms.uiPPBIndex & 0xFFF, |
|---|
| 439 | pstCurrentClip->stTime.uiStop)); |
|---|
| 440 | } |
|---|
| 441 | /* Handle Clipstop in conditions other than EOC mode |
|---|
| 442 | NOTE: The above override will result in a fall-through to the following code |
|---|
| 443 | (non-EOC mode, or non-DVD mode) */ |
|---|
| 444 | if ( ( 0xFFFFFFFF != pstCurrentClip->stTime.uiStop ) |
|---|
| 445 | || ( BXDM_PictureProvider_ClipTimeType_eEnableBothWithDVDCompatibility != pstCurrentClip->stTime.eType )) |
|---|
| 446 | { |
|---|
| 447 | if ( ( BXDM_PictureProvider_DisplayMode_eTSM == pLocalState->eDisplayMode ) |
|---|
| 448 | || ( BXDM_PictureProvider_ClipTimeType_eEnableBothWithDVDCompatibility != pstCurrentClip->stTime.eType ) |
|---|
| 449 | ) |
|---|
| 450 | { |
|---|
| 451 | /* Handle ClipStop xTSM modes based on actual PTS |
|---|
| 452 | * values */ |
|---|
| 453 | |
|---|
| 454 | /* PR51946: We need to account for STC/PTS jitter, so |
|---|
| 455 | * we offset the stop time by the jitter threshold */ |
|---|
| 456 | BXDM_PPFP_P_DataType stPts; |
|---|
| 457 | BXDM_PPFP_P_DataType stEffectivePTS; |
|---|
| 458 | |
|---|
| 459 | /* Handle ClipStop in vTSM mode */ |
|---|
| 460 | /* PR50077: Handle PTS wrap scenarios for clip stop |
|---|
| 461 | * event (vTSM). We need to handle all of the following |
|---|
| 462 | * stop scenarios since both the PTS and clip stop |
|---|
| 463 | * times are unsigned values and PTS wraps are allowed: |
|---|
| 464 | * |
|---|
| 465 | * 1) (pts >= clip stop) - this is a normal scenario, |
|---|
| 466 | * where the pts value is larger than the clip stop |
|---|
| 467 | * time and we want to trigger the stop event right |
|---|
| 468 | * away. E.g. |
|---|
| 469 | * - clip stop = 3000 |
|---|
| 470 | * - clip pts values = [4500, 6000, 7500, ...] |
|---|
| 471 | * - we want to trigger the clip stop event on pts >= 4500 |
|---|
| 472 | * |
|---|
| 473 | * 2) (pts >> clip stop) - this is a pts wrap |
|---|
| 474 | * scenario, where the clip stop is very small, but |
|---|
| 475 | * the pts values are very large. In this scenario, |
|---|
| 476 | * we want trigger the clip stop event only after the |
|---|
| 477 | * pts wraps. E.g. |
|---|
| 478 | * - clip stop = 3000 |
|---|
| 479 | * - clip pts values = [-3000, -1500, 0, 1500, 3000, ...] |
|---|
| 480 | * - we want to trigger the clip stop event on |
|---|
| 481 | * pts >= 3000, and not on -3000. |
|---|
| 482 | * |
|---|
| 483 | * 3) (pts < clip stop) - this is the typical |
|---|
| 484 | * scenario, where the pts is less than the clip |
|---|
| 485 | * stop, so we don't want to do anything until the |
|---|
| 486 | * pts matures in case #1. E.g. |
|---|
| 487 | * - clip stop = 3000 |
|---|
| 488 | * - clip pts values = [0, 1500, 3000, ...] |
|---|
| 489 | * - we wait for the stc to mature where we will |
|---|
| 490 | * trigger the clip stop event on pts >= 3000 |
|---|
| 491 | * |
|---|
| 492 | * 4) (pts << clip stop) - this is a pts wrap |
|---|
| 493 | * scenario, where the clip stop is very large, but |
|---|
| 494 | * the pts values are very small. In this scenario, |
|---|
| 495 | * we want to trigger the clip stop event right |
|---|
| 496 | * away. E.g. |
|---|
| 497 | * - clip stop = -3000 (0xFFFFF448) |
|---|
| 498 | * - clip pts values = [4500, 6000, 7500, ...] |
|---|
| 499 | * - we want to trigger the clip stop on pts >= 4500 |
|---|
| 500 | * |
|---|
| 501 | * In the end, we want to trigger the stop event if |
|---|
| 502 | * only cases 1) or 4) occur. |
|---|
| 503 | */ |
|---|
| 504 | |
|---|
| 505 | /* Get Actual PTS value for this picture for ClipStart/ClipStop |
|---|
| 506 | * calculations */ |
|---|
| 507 | BXDM_PPQM_P_GetPtsWithFrac( pstPicture, |
|---|
| 508 | BXDM_PictureProvider_P_PTSIndex_eActual, |
|---|
| 509 | 0, |
|---|
| 510 | &stPts ); |
|---|
| 511 | |
|---|
| 512 | BXDM_PPFP_P_FixPtAdd( |
|---|
| 513 | &stPts, |
|---|
| 514 | &pstPicture->stPicParms.stDisplay.stDynamic.stDisplayDuration, |
|---|
| 515 | &stEffectivePTS |
|---|
| 516 | ); |
|---|
| 517 | |
|---|
| 518 | if ( false == pstPicture->stPicParms.stDisplay.stDynamic.bPPBRepeated ) |
|---|
| 519 | { |
|---|
| 520 | /* PR56062: We want to trigger the stop event now if the |
|---|
| 521 | * stop time will be reached before the next vsync */ |
|---|
| 522 | BXDM_PPFP_P_FixPtAdd( |
|---|
| 523 | &stEffectivePTS, |
|---|
| 524 | &pLocalState->stSTCDelta, |
|---|
| 525 | &stEffectivePTS |
|---|
| 526 | ); |
|---|
| 527 | |
|---|
| 528 | /* PR56062: We don't want to trigger the stop event if |
|---|
| 529 | * the next picture will trigger it exactly, so we subtract |
|---|
| 530 | * 1 from the expected display duration. */ |
|---|
| 531 | if ( pLocalState->stSTCDelta.uiWhole != 0 ) |
|---|
| 532 | { |
|---|
| 533 | stEffectivePTS.uiWhole -= 1; |
|---|
| 534 | } |
|---|
| 535 | } |
|---|
| 536 | |
|---|
| 537 | /* SW7601-179: Round the effective PTS up, so that we don't miss |
|---|
| 538 | * a stop event if we're off by a fractional */ |
|---|
| 539 | if ( 0 != stEffectivePTS.uiFractional ) |
|---|
| 540 | { |
|---|
| 541 | stEffectivePTS.uiWhole++; |
|---|
| 542 | stEffectivePTS.uiFractional = 0; |
|---|
| 543 | } |
|---|
| 544 | |
|---|
| 545 | if ( ( ( true == pstPicture->stPicParms.stDisplay.stDynamic.bPPBRepeated ) |
|---|
| 546 | || ( BXDM_PictureProvider_TSMResult_eWait != *peTsmState ) ) |
|---|
| 547 | && ( ( BXDM_PictureProvider_ClipTimeType_eEnableBothWithDVDCompatibility != pstCurrentClip->stTime.eType ) |
|---|
| 548 | || ( false == pstPicture->stPicParms.stTSM.stDynamic.bClipTransition ) ) |
|---|
| 549 | && ( ( ( stEffectivePTS.uiWhole >= pstCurrentClip->stTime.uiStop ) /* Case 1: PTS is greater than or equal to the stop time, but not too large */ |
|---|
| 550 | && ( ( stEffectivePTS.uiWhole - pstCurrentClip->stTime.uiStop ) < BXDM_PictureProvider_P_CLIPTIME_PTS_WRAP_THRESHOLD ) ) |
|---|
| 551 | || ( ( stEffectivePTS.uiWhole < pstCurrentClip->stTime.uiStop ) /* Case 4: PTS is less than the stop time, but much lesser */ |
|---|
| 552 | && ( ( pstCurrentClip->stTime.uiStop - stEffectivePTS.uiWhole ) > BXDM_PictureProvider_P_CLIPTIME_PTS_WRAP_THRESHOLD ) ) ) ) |
|---|
| 553 | { |
|---|
| 554 | BXVD_DBG_MSG(hXdmPP,("%x: [%01x.%03x] Stop Event (TSM/vTSM):: Stop Time:%08x PTS:%08x OrigPTS:%08x Duration:%08x", |
|---|
| 555 | hXdmPP->stDMState.stDecode.stDebug.uiVsyncCount, |
|---|
| 556 | hXdmPP->stDMConfig.uiInstanceID & 0xF, |
|---|
| 557 | pstPicture->stPicParms.uiPPBIndex & 0xFFF, |
|---|
| 558 | pstCurrentClip->stTime.uiStop, |
|---|
| 559 | stEffectivePTS.uiWhole, |
|---|
| 560 | stPts.uiWhole, |
|---|
| 561 | pstPicture->stPicParms.stDisplay.stDynamic.stDisplayDuration.uiWhole)); |
|---|
| 562 | pstCurrentClip->stStopEvent.bOccurred = true; |
|---|
| 563 | pstCurrentClip->stStopEvent.uiTime = pstCurrentClip->stTime.uiStop; |
|---|
| 564 | /* SWBLURAY-21565: only allow the last picture of a clip to generate one stop event */ |
|---|
| 565 | pstPicture->stPicParms.stDisplay.stDynamic.bGeneratedClipStop = true; |
|---|
| 566 | } |
|---|
| 567 | } |
|---|
| 568 | else |
|---|
| 569 | { |
|---|
| 570 | /* Handle ClipStop in VSYNC mode */ |
|---|
| 571 | if ( ( true == pstCurrentClip->stMarkerEvent.bOccurred ) /* The marker event has occurred */ |
|---|
| 572 | && ( 0 != pLocalState->uiSlowMotionRate ) ) /* We're not in a pause state */ |
|---|
| 573 | { |
|---|
| 574 | BXVD_DBG_MSG(hXdmPP,("%x: [%01x.%03x] Stop Event (VSYNC) Stop Time %08x", |
|---|
| 575 | hXdmPP->stDMState.stDecode.stDebug.uiVsyncCount, |
|---|
| 576 | hXdmPP->stDMConfig.uiInstanceID & 0xF, |
|---|
| 577 | pstPicture->stPicParms.uiPPBIndex & 0xFFF, |
|---|
| 578 | pstCurrentClip->stTime.uiStop)); |
|---|
| 579 | pstCurrentClip->stStopEvent.bOccurred = true; |
|---|
| 580 | pstCurrentClip->stStopEvent.uiTime = pstCurrentClip->stTime.uiStop; |
|---|
| 581 | /* SWBLURAY-21565: only allow the last picture of a clip to generate one stop event */ |
|---|
| 582 | pstPicture->stPicParms.stDisplay.stDynamic.bGeneratedClipStop = true; |
|---|
| 583 | } |
|---|
| 584 | } |
|---|
| 585 | } /* End: Handle clip stop in Non-EOC or Non-DVD mode */ |
|---|
| 586 | |
|---|
| 587 | /* PR50381: The DVD-VR VR100 title 11 has the following |
|---|
| 588 | * properties: |
|---|
| 589 | * - many single picture clips in a row |
|---|
| 590 | * - each picture has the same PTS value |
|---|
| 591 | * |
|---|
| 592 | * These properties coupled with the application setting the |
|---|
| 593 | * clip stop time to EOC Marker mode (0xFFFFFFFF) was resulting |
|---|
| 594 | * in DM displaying the next picture of the clip without |
|---|
| 595 | * generating a ClipStart event for the next clip. |
|---|
| 596 | * |
|---|
| 597 | * Since the PTS values of each picture are identical, the next |
|---|
| 598 | * clip's picture's TSM result is always ePass, so we end up |
|---|
| 599 | * displaying the picture from the next clip. We were not |
|---|
| 600 | * generating a ClipStart event because the clip time transition |
|---|
| 601 | * handling occurs when we first look at the picture in the |
|---|
| 602 | * queue (before TSM is performed). It was never expected that |
|---|
| 603 | * a ClipStop event would occur at the same time as a picture |
|---|
| 604 | * passing. |
|---|
| 605 | * |
|---|
| 606 | * To prevent this issue, we always override a ePass TSM result |
|---|
| 607 | * to eWait when the stop event first occurs to allow the clip |
|---|
| 608 | * time transition handler to execute |
|---|
| 609 | */ |
|---|
| 610 | if ( ( true == pstCurrentClip->stStopEvent.bOccurred ) |
|---|
| 611 | && ( BXDM_PictureProvider_ClipTimeType_eEnableBothWithDVDCompatibility == pstCurrentClip->stTime.eType ) |
|---|
| 612 | && ( BXDM_PictureProvider_TSMResult_ePass == *peTsmState ) ) |
|---|
| 613 | { |
|---|
| 614 | *peTsmState = BXDM_PictureProvider_TSMResult_eWait; |
|---|
| 615 | } |
|---|
| 616 | } /* End: Handle Clip Stop */ |
|---|
| 617 | |
|---|
| 618 | /* Override TSM state if PTSError occurs during playback of a |
|---|
| 619 | * clip */ |
|---|
| 620 | if ( ( true == hXdmPP->stDMConfig.bPlayback ) |
|---|
| 621 | && ( true == pstCurrentClip->stTime.bValid ) |
|---|
| 622 | && ( BXDM_PictureProvider_ClipTimeType_eEnableBothWithDVDCompatibility == pstCurrentClip->stTime.eType ) |
|---|
| 623 | && ( true == pstCurrentClip->stStartEvent.bOccurred ) |
|---|
| 624 | ) |
|---|
| 625 | { |
|---|
| 626 | /* We're in the middle of playing back a clip */ |
|---|
| 627 | if ( ( false == pstPicture->stPicParms.stDisplay.stDynamic.bPPBRepeated ) |
|---|
| 628 | && ( ( BXDM_PictureProvider_TSMResult_eTooLate == pstPicture->stPicParms.stTSM.stDynamic.eTsmResult ) |
|---|
| 629 | || ( BXDM_PictureProvider_TSMResult_eTooEarly == pstPicture->stPicParms.stTSM.stDynamic.eTsmResult ) ) |
|---|
| 630 | && ( BXDM_PictureProvider_DisplayMode_eTSM == pstPicture->stPicParms.stTSM.stDynamic.eSelectionMode ) ) |
|---|
| 631 | { |
|---|
| 632 | /* SW7335-781: Output warning when forcing picture selection override */ |
|---|
| 633 | BXDM_PPDBG_P_PrintSelectionModeOverride("PTS Error Override", hXdmPP, pstPicture); |
|---|
| 634 | |
|---|
| 635 | /* To ensure a smooth seamless clip transition, we set the |
|---|
| 636 | * selection mode for this picture to be VSYNC so that we end up |
|---|
| 637 | * using vTSM mode to evaluate it */ |
|---|
| 638 | pstPicture->stPicParms.stTSM.stDynamic.eSelectionMode = BXDM_PictureProvider_DisplayMode_eVirtualTSM; |
|---|
| 639 | |
|---|
| 640 | /* We will want to generate a PTS error, but only when this |
|---|
| 641 | * picture is actually displayed */ |
|---|
| 642 | hXdmPP->stDMState.stChannel.stClipInfo.bForcePTSError = true; |
|---|
| 643 | } |
|---|
| 644 | |
|---|
| 645 | /* We handle the bForcePTSError flag */ |
|---|
| 646 | if ( true == hXdmPP->stDMState.stChannel.stClipInfo.bForcePTSError ) |
|---|
| 647 | { |
|---|
| 648 | /* We need to send the next coded PTS */ |
|---|
| 649 | if ( ( BXDM_PictureProvider_TSMResult_ePass == *peTsmState ) |
|---|
| 650 | && ( false == pstPicture->stPicParms.stDisplay.stDynamic.bPPBRepeated ) |
|---|
| 651 | && ( true == pstPicture->pstUnifiedPicture->stPTS.bValid ) |
|---|
| 652 | ) |
|---|
| 653 | { |
|---|
| 654 | /* We are in a TSM Pass and have a coded PTS, so this |
|---|
| 655 | * picture will be displayed next, so we force the PTS |
|---|
| 656 | * error */ |
|---|
| 657 | pLocalState->bForcePtsError = true; |
|---|
| 658 | hXdmPP->stDMState.stChannel.stClipInfo.bForcePTSError = false; |
|---|
| 659 | |
|---|
| 660 | hXdmPP->stDMConfig.bSTCValid = false; |
|---|
| 661 | /* To trigger the config debug message. */ |
|---|
| 662 | hXdmPP->stDMConfig.uiDirtyBits_1 |= BXDM_PictureProvider_P_DIRTY_1_STC_VALID; |
|---|
| 663 | |
|---|
| 664 | BXVD_DBG_MSG(hXdmPP,("%x: [%01x.%03x] Trigger Force PTS Error", |
|---|
| 665 | hXdmPP->stDMState.stDecode.stDebug.uiVsyncCount, |
|---|
| 666 | hXdmPP->stDMConfig.uiInstanceID & 0xF, |
|---|
| 667 | pstPicture->stPicParms.uiPPBIndex & 0xFFF)); |
|---|
| 668 | } |
|---|
| 669 | } |
|---|
| 670 | } |
|---|
| 671 | |
|---|
| 672 | if ( ( BXDM_PictureProvider_TSMResult_ePass == *peTsmState ) |
|---|
| 673 | && ( true == hXdmPP->stDMState.stChannel.stClipInfo.stCurrentClip.stTime.bValid ) |
|---|
| 674 | && ( true == hXdmPP->stDMState.stChannel.stClipInfo.stCurrentClip.stStartEvent.bOccurred ) |
|---|
| 675 | && ( false == hXdmPP->stDMState.stChannel.stClipInfo.stCurrentClip.stDisplayEvent.bOccurred ) |
|---|
| 676 | && ( false == pstPicture->stPicParms.stTSM.stDynamic.bClipTransition ) |
|---|
| 677 | && ( false == pstPicture->stPicParms.stDisplay.stDynamic.bGeneratedClipStop ) /* SWBLURAY-21565: only allow the last picture of a clip to generate one stop event */ |
|---|
| 678 | ) |
|---|
| 679 | { |
|---|
| 680 | /* We set the display event to true because we've achieved TSM |
|---|
| 681 | * pass and we'll start displaying the next picture */ |
|---|
| 682 | BXVD_DBG_MSG(hXdmPP,("%x: [%01x.%03x] Display Event", |
|---|
| 683 | hXdmPP->stDMState.stDecode.stDebug.uiVsyncCount, |
|---|
| 684 | hXdmPP->stDMConfig.uiInstanceID & 0xF, |
|---|
| 685 | pstPicture->stPicParms.uiPPBIndex & 0xFFF)); |
|---|
| 686 | hXdmPP->stDMState.stChannel.stClipInfo.stCurrentClip.stDisplayEvent.bOccurred = true; |
|---|
| 687 | } |
|---|
| 688 | } |
|---|
| 689 | |
|---|
| 690 | void BXDM_PPCLIP_P_ClipTimeQueueTransitionHandler( |
|---|
| 691 | BXDM_PictureProvider_Handle hXdmPP, |
|---|
| 692 | BXDM_PictureProvider_P_LocalState * pLocalState, |
|---|
| 693 | BXDM_PictureProvider_P_Picture_Context * pstPicCntxt |
|---|
| 694 | ) |
|---|
| 695 | { |
|---|
| 696 | BXDM_PictureProvider_P_ClipTimeV2 * pstCurrentClip = &( hXdmPP->stDMState.stChannel.stClipInfo.stCurrentClip ); |
|---|
| 697 | |
|---|
| 698 | BSTD_UNUSED(pLocalState); |
|---|
| 699 | |
|---|
| 700 | if ( (true == pstPicCntxt->pstUnifiedPicture->stPTS.bValid) |
|---|
| 701 | && ( true == hXdmPP->stDMState.stChannel.stClipInfo.bClipTransition ) ) |
|---|
| 702 | { |
|---|
| 703 | BXVD_DBG_MSG(hXdmPP,("%x: [%01x.%03x] Exit Clip Transition Mode", |
|---|
| 704 | hXdmPP->stDMState.stDecode.stDebug.uiVsyncCount, |
|---|
| 705 | hXdmPP->stDMConfig.uiInstanceID & 0xF, |
|---|
| 706 | pstPicCntxt->stPicParms.uiPPBIndex & 0xFFF)); |
|---|
| 707 | |
|---|
| 708 | /* We turn off the clip transition mode when we first get a coded PTS */ |
|---|
| 709 | hXdmPP->stDMState.stChannel.stClipInfo.bClipTransition = false; |
|---|
| 710 | } |
|---|
| 711 | |
|---|
| 712 | /* SWBLURAY-23188: The failure was a 24p stream going to a 24Hz display, the 60Hz output was fine. |
|---|
| 713 | * It just so happened that the last picture of the current clip was being dropped. Then due to the |
|---|
| 714 | * pipelining of the logic, the first picture of the next clip was dropped as well. For both pictures, |
|---|
| 715 | * the TSM result was overridden to "drop" from "pass". The TSM result was feeding back into the vTSM |
|---|
| 716 | * logic and resetting the vPTS. The vPTS was set to the coded PTS of the second picture in the new clip. |
|---|
| 717 | * However the vSTC was still based on the old time base. This resulted in all the pictures in the new |
|---|
| 718 | * clip being late, hence they were dropped. |
|---|
| 719 | * |
|---|
| 720 | * The solution is to load the parameters for the next clip sooner. This loading is gated by the variable |
|---|
| 721 | * "bClipActive". Now the new clip will be loaded ("bClipActive" set to true) when: |
|---|
| 722 | * - a DVD clip |
|---|
| 723 | * - AND the stop event has occurred |
|---|
| 724 | * - AND not a picture less clip, i.e. not a dummy PPB |
|---|
| 725 | * - AND a new maker has been seen |
|---|
| 726 | * |
|---|
| 727 | * For now this is only being done for the DVD clips. For the other modes "bClipActive" is cleared |
|---|
| 728 | * in " BXDM_PPCLIP_P_ClipTimeCallbackTriggerHandler". |
|---|
| 729 | */ |
|---|
| 730 | if ( ( BXDM_PictureProvider_ClipTimeType_eEnableBothWithDVDCompatibility == pstCurrentClip->stTime.eType ) |
|---|
| 731 | && ( true == pstCurrentClip->stStopEvent.bOccurred ) |
|---|
| 732 | && ( true == pstPicCntxt->pstUnifiedPicture->stBufferInfo.bValid ) |
|---|
| 733 | && ( hXdmPP->stDMState.stChannel.stClipInfo.uiLastMarker != pstPicCntxt->pstUnifiedPicture->stPictureMarker.uiValue ) |
|---|
| 734 | ) |
|---|
| 735 | { |
|---|
| 736 | hXdmPP->stDMState.stChannel.stClipInfo.bClipActive = false; |
|---|
| 737 | } |
|---|
| 738 | |
|---|
| 739 | /* Handle a clip transition */ |
|---|
| 740 | if ( true == hXdmPP->stDMConfig.stClipTimeSettings.bValid ) |
|---|
| 741 | { |
|---|
| 742 | if ( BXDM_PictureProvider_ClipTimeType_eDisable == hXdmPP->stDMConfig.stClipTimeSettings.eType ) |
|---|
| 743 | { |
|---|
| 744 | /* We want to disable any clipping that may be active, so we |
|---|
| 745 | * invalidate the local current clip info */ |
|---|
| 746 | BKNI_Memset( &hXdmPP->stDMState.stChannel.stClipInfo.stCurrentClip, |
|---|
| 747 | 0, |
|---|
| 748 | sizeof( BXDM_PictureProvider_P_ClipTimeV2 ) ); |
|---|
| 749 | |
|---|
| 750 | /* We disable all clip related callbacks */ |
|---|
| 751 | hXdmPP->stCallbacks[BXDM_PictureProvider_Callback_eClipStart].bEnable = false; |
|---|
| 752 | hXdmPP->stCallbacks[BXDM_PictureProvider_Callback_eClipStop].bEnable = false; |
|---|
| 753 | hXdmPP->stCallbacks[BXDM_PictureProvider_Callback_ePictureMarker].bEnable = false; |
|---|
| 754 | |
|---|
| 755 | /* We invalidate the public clip info */ |
|---|
| 756 | BKNI_Memset( &hXdmPP->stDMConfig.stClipTimeSettings, |
|---|
| 757 | 0, |
|---|
| 758 | sizeof( BXDM_PictureProvider_ClipTimeSettings ) ); |
|---|
| 759 | } |
|---|
| 760 | else if ( ( false == hXdmPP->stDMState.stChannel.stClipInfo.bClipActive ) |
|---|
| 761 | || ( BXDM_PictureProvider_ClipTimeType_eClipStopOnly == hXdmPP->stDMConfig.stClipTimeSettings.eType ) ) |
|---|
| 762 | { |
|---|
| 763 | /* If the next clip and current clip are both valid, then we are |
|---|
| 764 | * in a seamless clip transition, so we need to override an |
|---|
| 765 | * invalid PTS of this picture to be equal to the next clip's |
|---|
| 766 | * start time to prevent it from being dropped */ |
|---|
| 767 | if ( ( true == hXdmPP->stDMState.stChannel.stClipInfo.stCurrentClip.stTime.bValid ) |
|---|
| 768 | && ( BXDM_PictureProvider_ClipTimeType_eEnableBothWithDVDCompatibility == hXdmPP->stDMState.stChannel.stClipInfo.stCurrentClip.stTime.eType ) |
|---|
| 769 | && ( BXDM_PictureProvider_ClipTimeType_eEnableBothWithDVDCompatibility == hXdmPP->stDMConfig.stClipTimeSettings.eType ) |
|---|
| 770 | && ( false == pstPicCntxt->pstUnifiedPicture->stPTS.bValid ) |
|---|
| 771 | ) |
|---|
| 772 | { |
|---|
| 773 | BXVD_DBG_MSG(hXdmPP,("%x: [%01x.%03x] Enter Clip Transition", |
|---|
| 774 | hXdmPP->stDMState.stDecode.stDebug.uiVsyncCount, |
|---|
| 775 | hXdmPP->stDMConfig.uiInstanceID & 0xF, |
|---|
| 776 | pstPicCntxt->stPicParms.uiPPBIndex & 0xFFF)); |
|---|
| 777 | |
|---|
| 778 | BXVD_DBG_MSG(hXdmPP,("%x: [%01x.%03x] Clip Transition PTS Override", |
|---|
| 779 | hXdmPP->stDMState.stDecode.stDebug.uiVsyncCount, |
|---|
| 780 | hXdmPP->stDMConfig.uiInstanceID & 0xF, |
|---|
| 781 | pstPicCntxt->stPicParms.uiPPBIndex & 0xFFF)); |
|---|
| 782 | /* Override PTS of this picture if it is not coded, so |
|---|
| 783 | * that the clip start will return the proper PTS. We |
|---|
| 784 | * assume the PTS of the first picture of the next clip |
|---|
| 785 | * is the same as the start time for seamless cases */ |
|---|
| 786 | hXdmPP->stDMState.stChannel.stClipInfo.bClipTransition = true; |
|---|
| 787 | } |
|---|
| 788 | |
|---|
| 789 | /* We copy the next clip info to the current clip info */ |
|---|
| 790 | |
|---|
| 791 | /* We invalidate the local current clip info */ |
|---|
| 792 | BKNI_Memset( &hXdmPP->stDMState.stChannel.stClipInfo.stCurrentClip, |
|---|
| 793 | 0, |
|---|
| 794 | sizeof( BXDM_PictureProvider_P_ClipTimeV2 ) ); |
|---|
| 795 | |
|---|
| 796 | hXdmPP->stDMState.stChannel.stClipInfo.stCurrentClip.stTime = hXdmPP->stDMConfig.stClipTimeSettings; |
|---|
| 797 | |
|---|
| 798 | /* We invalidate the public clip info */ |
|---|
| 799 | BKNI_Memset( &hXdmPP->stDMConfig.stClipTimeSettings, |
|---|
| 800 | 0, |
|---|
| 801 | sizeof( BXDM_PictureProvider_ClipTimeSettings ) ); |
|---|
| 802 | |
|---|
| 803 | BXVD_DBG_MSG(hXdmPP,("%x: [%01x.%03x] New Clip (%d: %08x -> %08x)", |
|---|
| 804 | hXdmPP->stDMState.stDecode.stDebug.uiVsyncCount, |
|---|
| 805 | hXdmPP->stDMConfig.uiInstanceID & 0xF, |
|---|
| 806 | pstPicCntxt->stPicParms.uiPPBIndex & 0xFFF, |
|---|
| 807 | hXdmPP->stDMState.stChannel.stClipInfo.stCurrentClip.stTime.eType, |
|---|
| 808 | hXdmPP->stDMState.stChannel.stClipInfo.stCurrentClip.stTime.uiStart, |
|---|
| 809 | hXdmPP->stDMState.stChannel.stClipInfo.stCurrentClip.stTime.uiStop |
|---|
| 810 | )); |
|---|
| 811 | |
|---|
| 812 | /* We re-enable the clip callbacks */ |
|---|
| 813 | switch ( hXdmPP->stDMState.stChannel.stClipInfo.stCurrentClip.stTime.eType ) |
|---|
| 814 | { |
|---|
| 815 | case BXDM_PictureProvider_ClipTimeType_eEnableBothWithDVDCompatibility: |
|---|
| 816 | hXdmPP->stCallbacks[BXDM_PictureProvider_Callback_eClipStart].bEnable = true; |
|---|
| 817 | hXdmPP->stCallbacks[BXDM_PictureProvider_Callback_eClipStop].bEnable = true; |
|---|
| 818 | hXdmPP->stCallbacks[BXDM_PictureProvider_Callback_ePictureMarker].bEnable = true; |
|---|
| 819 | break; |
|---|
| 820 | |
|---|
| 821 | case BXDM_PictureProvider_ClipTimeType_eEnableBoth: |
|---|
| 822 | hXdmPP->stCallbacks[BXDM_PictureProvider_Callback_eClipStart].bEnable = true; |
|---|
| 823 | hXdmPP->stCallbacks[BXDM_PictureProvider_Callback_eClipStop].bEnable = true; |
|---|
| 824 | break; |
|---|
| 825 | |
|---|
| 826 | case BXDM_PictureProvider_ClipTimeType_eClipStartOnly: |
|---|
| 827 | hXdmPP->stCallbacks[BXDM_PictureProvider_Callback_eClipStart].bEnable = true; |
|---|
| 828 | break; |
|---|
| 829 | |
|---|
| 830 | case BXDM_PictureProvider_ClipTimeType_eClipStopOnly: |
|---|
| 831 | hXdmPP->stCallbacks[BXDM_PictureProvider_Callback_eClipStop].bEnable = true; |
|---|
| 832 | |
|---|
| 833 | /* We assume the start event has already occurred */ |
|---|
| 834 | hXdmPP->stDMState.stChannel.stClipInfo.stCurrentClip.stStartEvent.bOccurred = true; |
|---|
| 835 | hXdmPP->stDMState.stChannel.stClipInfo.stCurrentClip.stDisplayEvent.bOccurred = true; |
|---|
| 836 | break; |
|---|
| 837 | |
|---|
| 838 | default: |
|---|
| 839 | break; |
|---|
| 840 | } |
|---|
| 841 | |
|---|
| 842 | /* We set bClipActive to true */ |
|---|
| 843 | hXdmPP->stDMState.stChannel.stClipInfo.bClipActive = true; |
|---|
| 844 | } |
|---|
| 845 | } |
|---|
| 846 | |
|---|
| 847 | /* Handle Auto-Vsync Mode Cases */ |
|---|
| 848 | if (true == hXdmPP->stDMState.stChannel.stClipInfo.bClipTransition) |
|---|
| 849 | { |
|---|
| 850 | pstPicCntxt->stPicParms.stTSM.stDynamic.eSelectionMode = BXDM_PictureProvider_DisplayMode_eVirtualTSM; |
|---|
| 851 | pstPicCntxt->stPicParms.stTSM.stDynamic.bClipTransition = true; |
|---|
| 852 | } |
|---|
| 853 | |
|---|
| 854 | /* PR51920: If the STC is valid, then we can turn off the trick |
|---|
| 855 | * mode transition bit. */ |
|---|
| 856 | if ( ( true == hXdmPP->stDMState.stChannel.stClipInfo.bTrickModeTransition ) |
|---|
| 857 | && ( ( true == hXdmPP->stDMConfig.bSTCValid ) /* The STC is valid */ |
|---|
| 858 | || ( BXDM_PictureProvider_DisplayMode_eVirtualTSM == pLocalState->eDisplayMode ) /* We're in VSYNC display mode */ |
|---|
| 859 | || ( BXDM_PICTUREPROVIDER_NORMAL_PLAYBACK_RATE != pLocalState->uiSlowMotionRate ) /* We've entered into another trick mode */ |
|---|
| 860 | ) |
|---|
| 861 | ) |
|---|
| 862 | { |
|---|
| 863 | BXVD_DBG_MSG(hXdmPP, ("%x: [%01x.%03x] Exiting trick mode transition (stc: %x)", |
|---|
| 864 | hXdmPP->stDMState.stDecode.stDebug.uiVsyncCount, |
|---|
| 865 | hXdmPP->stDMConfig.uiInstanceID & 0xF, |
|---|
| 866 | pstPicCntxt->stPicParms.uiPPBIndex & 0xFFF, |
|---|
| 867 | pLocalState->uiAdjustedStc)); |
|---|
| 868 | hXdmPP->stDMState.stChannel.stClipInfo.bTrickModeTransition = false; |
|---|
| 869 | } |
|---|
| 870 | |
|---|
| 871 | /* If the STC becomes invalid in the middle of playing back a clip, |
|---|
| 872 | * then we go into VSYNC mode */ |
|---|
| 873 | if ( true == hXdmPP->stDMConfig.bPlayback |
|---|
| 874 | && false == hXdmPP->stDMConfig.bSTCValid |
|---|
| 875 | && true == hXdmPP->stDMState.stChannel.stClipInfo.stCurrentClip.stTime.bValid |
|---|
| 876 | && ( BXDM_PictureProvider_ClipTimeType_eEnableBothWithDVDCompatibility == hXdmPP->stDMState.stChannel.stClipInfo.stCurrentClip.stTime.eType ) |
|---|
| 877 | && false == hXdmPP->stDMState.stChannel.stClipInfo.bTrickModeTransition |
|---|
| 878 | && true == hXdmPP->stDMState.stChannel.stClipInfo.stCurrentClip.stStartEvent.bOccurred |
|---|
| 879 | && true == hXdmPP->stDMState.stChannel.stClipInfo.stCurrentClip.stDisplayEvent.bOccurred |
|---|
| 880 | && false == hXdmPP->stDMState.stChannel.stClipInfo.stCurrentClip.stStopEvent.bOccurred |
|---|
| 881 | ) |
|---|
| 882 | { |
|---|
| 883 | /* SW7335-781: Output warning when forcing picture selection override */ |
|---|
| 884 | BXDM_PPDBG_P_PrintSelectionModeOverride("Clip STC Invalid", hXdmPP, pstPicCntxt); |
|---|
| 885 | pstPicCntxt->stPicParms.stTSM.stDynamic.eSelectionMode = BXDM_PictureProvider_DisplayMode_eVirtualTSM; |
|---|
| 886 | } |
|---|
| 887 | |
|---|
| 888 | /* Handle Picture Marker */ |
|---|
| 889 | /* PR52247: We need to handle the marker event AFTER the clip |
|---|
| 890 | * transition code to handle picture-less clips (i.e. only contains |
|---|
| 891 | * a single dummy PPB). Picture-less clips will trigger a |
|---|
| 892 | * transition, start, stop, and marker event all on the same |
|---|
| 893 | * vsync */ |
|---|
| 894 | if ( hXdmPP->stDMState.stChannel.stClipInfo.uiLastMarker != pstPicCntxt->pstUnifiedPicture->stPictureMarker.uiValue ) |
|---|
| 895 | { |
|---|
| 896 | /* We set the marker event */ |
|---|
| 897 | BXVD_DBG_MSG(hXdmPP,("%x: [%01x.%03x] Marker Event Old:%08x New:%08x", |
|---|
| 898 | hXdmPP->stDMState.stDecode.stDebug.uiVsyncCount, |
|---|
| 899 | hXdmPP->stDMConfig.uiInstanceID & 0xF, |
|---|
| 900 | pstPicCntxt->stPicParms.uiPPBIndex & 0xFFF, |
|---|
| 901 | hXdmPP->stDMState.stChannel.stClipInfo.uiLastMarker, |
|---|
| 902 | pstPicCntxt->pstUnifiedPicture->stPictureMarker.uiValue)); |
|---|
| 903 | hXdmPP->stCallbacks[BXDM_PictureProvider_Callback_ePictureMarker].bEnable = true; |
|---|
| 904 | hXdmPP->stDMState.stChannel.stClipInfo.stCurrentClip.stMarkerEvent.bOccurred = true; |
|---|
| 905 | hXdmPP->stDMState.stChannel.stClipInfo.stCurrentClip.stMarkerEvent.uiTime = pstPicCntxt->pstUnifiedPicture->stPictureMarker.uiValue; |
|---|
| 906 | hXdmPP->stDMState.stChannel.stClipInfo.stCurrentClip.stMarkerEvent.bDelayedCallback = ( true == pstPicCntxt->pstUnifiedPicture->stBufferInfo.bValid ); |
|---|
| 907 | |
|---|
| 908 | /* We save the new marker */ |
|---|
| 909 | hXdmPP->stDMState.stChannel.stClipInfo.uiLastMarker = pstPicCntxt->pstUnifiedPicture->stPictureMarker.uiValue; |
|---|
| 910 | |
|---|
| 911 | /* TODO: handle multiple markers */ |
|---|
| 912 | } |
|---|
| 913 | } |
|---|
| 914 | |
|---|
| 915 | void BXDM_PPCLIP_P_ClipTimeTrickModeTransitionHandler( |
|---|
| 916 | BXDM_PictureProvider_Handle hXdmPP, |
|---|
| 917 | BXDM_PictureProvider_P_LocalState * pLocalState |
|---|
| 918 | ) |
|---|
| 919 | { |
|---|
| 920 | BSTD_UNUSED(pLocalState); |
|---|
| 921 | |
|---|
| 922 | BXVD_DBG_MSG(hXdmPP, ("%x: Entering trick mode transition (stc: %x)", |
|---|
| 923 | hXdmPP->stDMState.stDecode.stDebug.uiVsyncCount, |
|---|
| 924 | pLocalState->uiAdjustedStc)); |
|---|
| 925 | |
|---|
| 926 | /* PR51920: We set the trick mode transition bit so that we don't |
|---|
| 927 | * go into auto-vsync mode which gets triggered if the STC is |
|---|
| 928 | * invalidated during the middle of a clip. */ |
|---|
| 929 | hXdmPP->stDMState.stChannel.stClipInfo.bTrickModeTransition = true; |
|---|
| 930 | } |
|---|