| 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_tsm.c $ |
|---|
| 11 | * $brcm_Revision: Hydra_Software_Devel/30 $ |
|---|
| 12 | * $brcm_Date: 3/16/12 11:56a $ |
|---|
| 13 | * |
|---|
| 14 | * [File Description:] |
|---|
| 15 | * |
|---|
| 16 | * Revision History: |
|---|
| 17 | * |
|---|
| 18 | * $brcm_Log: /magnum/commonutils/xdm/bxdm_pp_tsm.c $ |
|---|
| 19 | * |
|---|
| 20 | * Hydra_Software_Devel/30 3/16/12 11:56a btosi |
|---|
| 21 | * SW7425-2536: added support for displayInterruptStatus_isr |
|---|
| 22 | * |
|---|
| 23 | * Hydra_Software_Devel/29 2/16/12 9:29a btosi |
|---|
| 24 | * SW7425-2255: bind the PTS offset to the picture when it is selected for |
|---|
| 25 | * display |
|---|
| 26 | * |
|---|
| 27 | * Hydra_Software_Devel/28 2/3/12 3:04p btosi |
|---|
| 28 | * SW7425-1264: fixed a problem with virtual PTS values when playing in |
|---|
| 29 | * reverse |
|---|
| 30 | * |
|---|
| 31 | * Hydra_Software_Devel/27 1/17/12 10:42a btosi |
|---|
| 32 | * SW7405-4736: added support for frame rate type and playback rate |
|---|
| 33 | * |
|---|
| 34 | * Hydra_Software_Devel/26 1/5/12 10:48a btosi |
|---|
| 35 | * SW7405-5549: re-apply the CDT when the monitor refesh rate changes |
|---|
| 36 | * while the system is paused |
|---|
| 37 | * |
|---|
| 38 | * Hydra_Software_Devel/25 11/17/11 11:27a btosi |
|---|
| 39 | * SW7425-1721: if ePictureHandlingMode has been changed in the TSM result |
|---|
| 40 | * callback, don't generate either the PTS Error or First PTS Pass |
|---|
| 41 | * callbacks. |
|---|
| 42 | * |
|---|
| 43 | * Hydra_Software_Devel/24 11/15/11 2:14p btosi |
|---|
| 44 | * SW7425-1721: execute TSM result callback prior to performing FIC |
|---|
| 45 | * evaluation |
|---|
| 46 | * |
|---|
| 47 | * Hydra_Software_Devel/23 10/3/11 2:19p btosi |
|---|
| 48 | * SW7425-1264: support for a SW STC internal to XDM |
|---|
| 49 | * |
|---|
| 50 | * Hydra_Software_Devel/22 8/10/11 9:40a btosi |
|---|
| 51 | * SW7425-1074: use eWait in the mulligan logic |
|---|
| 52 | * |
|---|
| 53 | * Hydra_Software_Devel/21 7/26/11 11:59a btosi |
|---|
| 54 | * SW7635-51: merged BXDM_PictureProvider_PictureHandlingMode_eWait |
|---|
| 55 | * changes |
|---|
| 56 | * |
|---|
| 57 | * Hydra_Software_Devel/20 6/24/11 4:05p btosi |
|---|
| 58 | * SW7425-764: added support for eInterruptRefreshRate in the MFD |
|---|
| 59 | * structure |
|---|
| 60 | * |
|---|
| 61 | * Hydra_Software_Devel/19 6/15/11 10:17a btosi |
|---|
| 62 | * SW7405-4736: fixed typo |
|---|
| 63 | * |
|---|
| 64 | * Hydra_Software_Devel/18 6/14/11 2:36p btosi |
|---|
| 65 | * SW7405-4736: revamped frame rate override message |
|---|
| 66 | * |
|---|
| 67 | * Hydra_Software_Devel/17 4/28/11 1:58p nilesh |
|---|
| 68 | * SWDTV-5937: Fixed incorrect deltaPTS values for 7.493, 14.985, 23.976, |
|---|
| 69 | * 29.97, and 59.94 fps frame rates |
|---|
| 70 | * |
|---|
| 71 | * Hydra_Software_Devel/16 4/11/11 10:20a btosi |
|---|
| 72 | * SW7405-5231: expanded the comment |
|---|
| 73 | * |
|---|
| 74 | * Hydra_Software_Devel/15 4/8/11 3:09p btosi |
|---|
| 75 | * SW7405-5231: only use whole values for the PTS deltas when in CRC mode. |
|---|
| 76 | * |
|---|
| 77 | * Hydra_Software_Devel/14 12/21/10 4:24p delkert |
|---|
| 78 | * SW7405-5043: Split STC stored in local state into two parts: STC from |
|---|
| 79 | * decoder and STC after JTI adjustment |
|---|
| 80 | * |
|---|
| 81 | * Hydra_Software_Devel/13 10/25/10 11:22a btosi |
|---|
| 82 | * SW7405-4883: added support to scan out 1080p 50+ Hz content as |
|---|
| 83 | * progressive |
|---|
| 84 | * |
|---|
| 85 | * Hydra_Software_Devel/12 10/1/10 2:51p btosi |
|---|
| 86 | * SWDEPRECATED-1003: added support for bTreatAsSingleElement |
|---|
| 87 | * |
|---|
| 88 | * Hydra_Software_Devel/11 9/23/10 3:09p btosi |
|---|
| 89 | * SW7405-4736: add support for a XDM instance ID to help debug multi- |
|---|
| 90 | * channel issues |
|---|
| 91 | * |
|---|
| 92 | * Hydra_Software_Devel/10 9/22/10 3:11p btosi |
|---|
| 93 | * SW7405-4883: removed unused variable "bProgressiveScanout" |
|---|
| 94 | * |
|---|
| 95 | * Hydra_Software_Devel/9 9/15/10 12:06p btosi |
|---|
| 96 | * SWDEPRECATED-1003: added BXDM_PictureProvider_SetFrameRateOverride_isr |
|---|
| 97 | * and supporting logic |
|---|
| 98 | * |
|---|
| 99 | * Hydra_Software_Devel/8 8/10/10 4:16p btosi |
|---|
| 100 | * SW7405-4736: added PPB index to debug messages |
|---|
| 101 | * |
|---|
| 102 | * Hydra_Software_Devel/7 7/12/10 8:05a delkert |
|---|
| 103 | * SW7335-781: Output warning when forcing picture selection override to |
|---|
| 104 | * allow easier detection of conditions such as drop@decode and pcr |
|---|
| 105 | * discontinuity |
|---|
| 106 | * |
|---|
| 107 | * Hydra_Software_Devel/6 6/29/10 11:25a btosi |
|---|
| 108 | * SW7405-4365: revamped the timer code to selectively enable the function |
|---|
| 109 | * and callback timing |
|---|
| 110 | * |
|---|
| 111 | * Hydra_Software_Devel/5 6/23/10 1:34p btosi |
|---|
| 112 | * SW7420-666: added support for 60p up to a stream height of 736 |
|---|
| 113 | * |
|---|
| 114 | * Hydra_Software_Devel/4 6/7/10 10:20a delkert |
|---|
| 115 | * SW7405-3929: If pending drop@decode, force picture selection to vTSM |
|---|
| 116 | * mode. Removed drop PTS offset calculation & PTS update (now |
|---|
| 117 | * obsolete). Removed unused variable (bTsmMode) |
|---|
| 118 | * |
|---|
| 119 | * Hydra_Software_Devel/3 3/25/10 4:05p nilesh |
|---|
| 120 | * SW7550-349: Added comment |
|---|
| 121 | * |
|---|
| 122 | * Hydra_Software_Devel/2 3/25/10 3:56p nilesh |
|---|
| 123 | * SW7550-349: Fixed issues with STC pause/frame advance from stalling |
|---|
| 124 | * when jitter correction logic prevents next picture from being |
|---|
| 125 | * displayed |
|---|
| 126 | * |
|---|
| 127 | * Hydra_Software_Devel/1 2/16/10 10:51a nilesh |
|---|
| 128 | * SW7405-2993: Initial XDM version |
|---|
| 129 | * |
|---|
| 130 | ***************************************************************************/ |
|---|
| 131 | |
|---|
| 132 | #include "bstd.h" |
|---|
| 133 | #include "bdbg.h" /* Dbglib */ |
|---|
| 134 | |
|---|
| 135 | #include "bxdm_pp.h" |
|---|
| 136 | #include "bxdm_pp_priv.h" |
|---|
| 137 | #include "bxdm_pp_qm.h" |
|---|
| 138 | #include "bxdm_pp_tsm.h" |
|---|
| 139 | #include "bxdm_pp_vtsm.h" |
|---|
| 140 | #include "bxdm_pp_clip.h" |
|---|
| 141 | #include "bxdm_pp_fic.h" |
|---|
| 142 | #include "bxdm_pp_callback_priv.h" |
|---|
| 143 | #include "bxdm_pp_jrc.h" |
|---|
| 144 | |
|---|
| 145 | BDBG_MODULE(BXDM_PPTSM); |
|---|
| 146 | |
|---|
| 147 | const char BXDM_PictureProvider_P_DISPMGR_TSM_NODE[]="DMTSM:\t""$brcm_Revision: Hydra_Software_Devel/30 $"; |
|---|
| 148 | |
|---|
| 149 | /******************************************************************************* |
|---|
| 150 | * |
|---|
| 151 | * Local constant definitions. |
|---|
| 152 | * |
|---|
| 153 | ******************************************************************************/ |
|---|
| 154 | |
|---|
| 155 | /* Lookup Tables */ |
|---|
| 156 | |
|---|
| 157 | /* The following is a LUT for the delta PTS given a |
|---|
| 158 | * BXDM_PictureProvider_P_ClockRate, BXDM_PictureProvider_P_PictureType, and BAVC_FrameRateCode. |
|---|
| 159 | * It is calculated assuming the fractional component's denominator is |
|---|
| 160 | * 65536 */ |
|---|
| 161 | static const BXDM_PPFP_P_DataType sDeltaPtsLUT[BXDM_PictureProvider_P_ClockRate_eMax][BXDM_PictureProvider_P_PictureType_eMax][BAVC_FrameRateCode_e7_493 + 1] = |
|---|
| 162 | { |
|---|
| 163 | /* BXDM_PictureProvider_P_ClockRate_eMPEG2 (45Khz) */ |
|---|
| 164 | { |
|---|
| 165 | /* BXDM_PictureProvider_P_PictureType_eProgressive */ |
|---|
| 166 | { |
|---|
| 167 | { 1500, 0}, /* BAVC_FrameRateCode_eUnknown */ |
|---|
| 168 | { 1876, 57344}, /* BAVC_FrameRateCode_e23_976 */ |
|---|
| 169 | { 1875, 0}, /* BAVC_FrameRateCode_e24 */ |
|---|
| 170 | { 1800, 0}, /* BAVC_FrameRateCode_e25 */ |
|---|
| 171 | { 1501, 32768}, /* BAVC_FrameRateCode_e29_97 */ |
|---|
| 172 | { 1500, 0}, /* BAVC_FrameRateCode_e30 */ |
|---|
| 173 | { 900, 0}, /* BAVC_FrameRateCode_e50 */ |
|---|
| 174 | { 750, 49152}, /* BAVC_FrameRateCode_e59_94 */ |
|---|
| 175 | { 750, 0}, /* BAVC_FrameRateCode_e60 */ |
|---|
| 176 | { 3003, 0}, /* BAVC_FrameRateCode_e14_985 */ |
|---|
| 177 | { 6006, 0} /* BAVC_FrameRateCode_e7_493 */ |
|---|
| 178 | }, |
|---|
| 179 | |
|---|
| 180 | /* BXDM_PictureProvider_P_PictureType_eInterlaced */ |
|---|
| 181 | { |
|---|
| 182 | { 750, 0}, /* BAVC_FrameRateCode_eUnknown */ |
|---|
| 183 | { 938, 28672}, /* BAVC_FrameRateCode_e23_976 */ |
|---|
| 184 | { 937, 32768}, /* BAVC_FrameRateCode_e24 */ |
|---|
| 185 | { 900, 0}, /* BAVC_FrameRateCode_e25 */ |
|---|
| 186 | { 750, 49152}, /* BAVC_FrameRateCode_e29_97 */ |
|---|
| 187 | { 750, 0}, /* BAVC_FrameRateCode_e30 */ |
|---|
| 188 | { 450, 0}, /* BAVC_FrameRateCode_e50 */ |
|---|
| 189 | { 375, 24576}, /* BAVC_FrameRateCode_e59_94 */ |
|---|
| 190 | { 375, 0}, /* BAVC_FrameRateCode_e60 */ |
|---|
| 191 | { 1501, 32768}, /* BAVC_FrameRateCode_e14_985 */ |
|---|
| 192 | { 3003, 0} /* BAVC_FrameRateCode_e7_493 */ |
|---|
| 193 | } |
|---|
| 194 | }, |
|---|
| 195 | |
|---|
| 196 | /* BXDM_PictureProvider_P_ClockRate_eDirecTV (27 Mhz) */ |
|---|
| 197 | { |
|---|
| 198 | /* BXDM_PictureProvider_P_PictureType_eProgressive */ |
|---|
| 199 | { |
|---|
| 200 | { 900000, 0}, /* BAVC_FrameRateCode_eUnknown */ |
|---|
| 201 | { 1126125, 0}, /* BAVC_FrameRateCode_e23_976 */ |
|---|
| 202 | { 1125000, 0}, /* BAVC_FrameRateCode_e24 */ |
|---|
| 203 | { 1080000, 0}, /* BAVC_FrameRateCode_e25 */ |
|---|
| 204 | { 900900, 0}, /* BAVC_FrameRateCode_e29_97 */ |
|---|
| 205 | { 900000, 0}, /* BAVC_FrameRateCode_e30 */ |
|---|
| 206 | { 540000, 0}, /* BAVC_FrameRateCode_e50 */ |
|---|
| 207 | { 450450, 0}, /* BAVC_FrameRateCode_e59_94 */ |
|---|
| 208 | { 450000, 0}, /* BAVC_FrameRateCode_e60 */ |
|---|
| 209 | { 1801800, 0}, /* BAVC_FrameRateCode_e14_985 */ |
|---|
| 210 | { 3603600, 0} /* BAVC_FrameRateCode_e7_493 */ |
|---|
| 211 | }, |
|---|
| 212 | |
|---|
| 213 | /* BXDM_PictureProvider_P_PictureType_eInterlaced */ |
|---|
| 214 | { |
|---|
| 215 | { 450000, 0}, /* BAVC_FrameRateCode_eUnknown */ |
|---|
| 216 | { 563062, 32768}, /* BAVC_FrameRateCode_e23_976 */ |
|---|
| 217 | { 562500, 0}, /* BAVC_FrameRateCode_e24 */ |
|---|
| 218 | { 540000, 0}, /* BAVC_FrameRateCode_e25 */ |
|---|
| 219 | { 450450, 0}, /* BAVC_FrameRateCode_e29_97 */ |
|---|
| 220 | { 450000, 0}, /* BAVC_FrameRateCode_e30 */ |
|---|
| 221 | { 270000, 0}, /* BAVC_FrameRateCode_e50 */ |
|---|
| 222 | { 225225, 0}, /* BAVC_FrameRateCode_e59_94 */ |
|---|
| 223 | { 225000, 0}, /* BAVC_FrameRateCode_e60 */ |
|---|
| 224 | { 900900, 0}, /* BAVC_FrameRateCode_e14_985 */ |
|---|
| 225 | { 1801800, 0} /* BAVC_FrameRateCode_e7_493 */ |
|---|
| 226 | } |
|---|
| 227 | } |
|---|
| 228 | }; /* end of sDeltaPtsLUT[] */ |
|---|
| 229 | |
|---|
| 230 | |
|---|
| 231 | /* SW7405-5231: only use whole values when in CRC mode. |
|---|
| 232 | * There was an occasional dropped picture during the CRC testing for AVD. These sometimes |
|---|
| 233 | * occurred when the Delivery Queue under flowed and then two pictures were delivered on a |
|---|
| 234 | * subsequent vsync. Due to the handling of the fractional component of the virtual PTS |
|---|
| 235 | * and STC, both pictures would pass the TSM test. As a result, the first picture would |
|---|
| 236 | * be dropped. This problem goes away when whole numbers are used. In CRC mode, the |
|---|
| 237 | * delta PTS is used to interpolate the virtual STC. The goal is to scan out a new picture |
|---|
| 238 | * element on every vsync, the source and display rates don't really matter. We probably |
|---|
| 239 | * could just use '1' for the delta PTS for all content. |
|---|
| 240 | */ |
|---|
| 241 | static const BXDM_PPFP_P_DataType sCRCDeltaPtsLUT[BXDM_PictureProvider_P_PictureType_eMax][BAVC_FrameRateCode_e7_493 + 1] = |
|---|
| 242 | { |
|---|
| 243 | /* BXDM_PictureProvider_P_PictureType_eProgressive */ |
|---|
| 244 | { |
|---|
| 245 | { 1500, 0}, /* BAVC_FrameRateCode_eUnknown */ |
|---|
| 246 | { 1875, 0}, /* BAVC_FrameRateCode_e23_976 */ |
|---|
| 247 | { 1875, 0}, /* BAVC_FrameRateCode_e24 */ |
|---|
| 248 | { 1800, 0}, /* BAVC_FrameRateCode_e25 */ |
|---|
| 249 | { 1500, 0}, /* BAVC_FrameRateCode_e29_97 */ |
|---|
| 250 | { 1500, 0}, /* BAVC_FrameRateCode_e30 */ |
|---|
| 251 | { 900, 0}, /* BAVC_FrameRateCode_e50 */ |
|---|
| 252 | { 750, 0}, /* BAVC_FrameRateCode_e59_94 */ |
|---|
| 253 | { 750, 0}, /* BAVC_FrameRateCode_e60 */ |
|---|
| 254 | { 3003, 0}, /* BAVC_FrameRateCode_e14_985 */ |
|---|
| 255 | { 6006, 0} /* BAVC_FrameRateCode_e7_493 */ |
|---|
| 256 | }, |
|---|
| 257 | |
|---|
| 258 | /* BXDM_PictureProvider_P_PictureType_eInterlaced */ |
|---|
| 259 | { |
|---|
| 260 | { 750, 0}, /* BAVC_FrameRateCode_eUnknown */ |
|---|
| 261 | { 938, 0}, /* BAVC_FrameRateCode_e23_976 */ |
|---|
| 262 | { 937, 0}, /* BAVC_FrameRateCode_e24 */ |
|---|
| 263 | { 900, 0}, /* BAVC_FrameRateCode_e25 */ |
|---|
| 264 | { 750, 0}, /* BAVC_FrameRateCode_e29_97 */ |
|---|
| 265 | { 750, 0}, /* BAVC_FrameRateCode_e30 */ |
|---|
| 266 | { 450, 0}, /* BAVC_FrameRateCode_e50 */ |
|---|
| 267 | { 375, 0}, /* BAVC_FrameRateCode_e59_94 */ |
|---|
| 268 | { 375, 0}, /* BAVC_FrameRateCode_e60 */ |
|---|
| 269 | { 1501, 0}, /* BAVC_FrameRateCode_e14_985 */ |
|---|
| 270 | { 3003, 0} /* BAVC_FrameRateCode_e7_493 */ |
|---|
| 271 | } |
|---|
| 272 | |
|---|
| 273 | }; /* end of sDeltaPtsLUT[] */ |
|---|
| 274 | |
|---|
| 275 | |
|---|
| 276 | |
|---|
| 277 | /* sNumElementsLUT maps the pulldown value to a number of elements */ |
|---|
| 278 | static const uint32_t sNumElementsLUT[BXDM_Picture_PullDown_eMax] = |
|---|
| 279 | { |
|---|
| 280 | 2, /* Invalid */ |
|---|
| 281 | 1, /* BXDM_Picture_PullDown_eTop */ |
|---|
| 282 | 1, /* BXDM_Picture_PullDown_eBottom */ |
|---|
| 283 | 2, /* BXDM_Picture_PullDown_eTopBottom */ |
|---|
| 284 | 2, /* BXDM_Picture_PullDown_eBottomTop */ |
|---|
| 285 | 3, /* BXDM_Picture_PullDown_eTopBottomTop */ |
|---|
| 286 | 3, /* BXDM_Picture_PullDown_eBottomTopBottom */ |
|---|
| 287 | 2, /* BXDM_Picture_PullDown_eFrameX2 */ |
|---|
| 288 | 3, /* BXDM_Picture_PullDown_eFrameX3 */ |
|---|
| 289 | 1, /* BXDM_Picture_PullDown_eFrameX1 */ |
|---|
| 290 | 4, /* BXDM_Picture_PullDown_eFrameX4 */ |
|---|
| 291 | }; /* end of sNumElementsLUT[] */ |
|---|
| 292 | |
|---|
| 293 | /* sInitialPolarityLUT maps the pulldown value to the polarity of the |
|---|
| 294 | * first element. If bReverseFields is enabled, then the table is |
|---|
| 295 | * inverted */ |
|---|
| 296 | static const BAVC_Polarity sInitialPolarityLUT[2][BXDM_Picture_PullDown_eMax] = |
|---|
| 297 | { |
|---|
| 298 | /* bReverseFields = false */ |
|---|
| 299 | { |
|---|
| 300 | BAVC_Polarity_eTopField, /* Invalid */ |
|---|
| 301 | BAVC_Polarity_eTopField, /* BXDM_Picture_PullDown_eTop */ |
|---|
| 302 | BAVC_Polarity_eBotField, /* BXDM_Picture_PullDown_eBottom */ |
|---|
| 303 | BAVC_Polarity_eTopField, /* BXDM_Picture_PullDown_eTopBottom */ |
|---|
| 304 | BAVC_Polarity_eBotField, /* BXDM_Picture_PullDown_eBottomTop */ |
|---|
| 305 | BAVC_Polarity_eTopField, /* BXDM_Picture_PullDown_eTopBottomTop */ |
|---|
| 306 | BAVC_Polarity_eBotField, /* BXDM_Picture_PullDown_eBottomTopBottom */ |
|---|
| 307 | BAVC_Polarity_eFrame, /* BXDM_Picture_PullDown_eFrameX2 */ |
|---|
| 308 | BAVC_Polarity_eFrame, /* BXDM_Picture_PullDown_eFrameX3 */ |
|---|
| 309 | BAVC_Polarity_eFrame, /* BXDM_Picture_PullDown_eFrameX1 */ |
|---|
| 310 | BAVC_Polarity_eFrame, /* BXDM_Picture_PullDown_eFrameX4 */ |
|---|
| 311 | }, |
|---|
| 312 | |
|---|
| 313 | /* bReverseFields = true */ |
|---|
| 314 | { |
|---|
| 315 | BAVC_Polarity_eBotField, /* Invalid */ |
|---|
| 316 | BAVC_Polarity_eTopField, /* BXDM_Picture_PullDown_eTop */ |
|---|
| 317 | BAVC_Polarity_eBotField, /* BXDM_Picture_PullDown_eBottom */ |
|---|
| 318 | BAVC_Polarity_eBotField, /* BXDM_Picture_PullDown_eTopBottom */ |
|---|
| 319 | BAVC_Polarity_eTopField, /* BXDM_Picture_PullDown_eBottomTop */ |
|---|
| 320 | BAVC_Polarity_eBotField, /* BXDM_Picture_PullDown_eTopBottomTop */ |
|---|
| 321 | BAVC_Polarity_eTopField, /* BXDM_Picture_PullDown_eBottomTopBottom */ |
|---|
| 322 | BAVC_Polarity_eFrame, /* BXDM_Picture_PullDown_eFrameX2 */ |
|---|
| 323 | BAVC_Polarity_eFrame, /* BXDM_Picture_PullDown_eFrameX3 */ |
|---|
| 324 | BAVC_Polarity_eFrame, /* BXDM_Picture_PullDown_eFrameX1 */ |
|---|
| 325 | BAVC_Polarity_eFrame, /* BXDM_Picture_PullDown_eFrameX4 */ |
|---|
| 326 | } |
|---|
| 327 | }; /* end of sInitialPolarityLUT[] */ |
|---|
| 328 | |
|---|
| 329 | /* sPictureTypeLUT maps the pulldown information to whether the FRAME |
|---|
| 330 | * is interlaced or progressive for the purposes of calculating the |
|---|
| 331 | * PTS delta */ |
|---|
| 332 | static const BXDM_PictureProvider_P_PictureType sPictureTypeLUT[BXDM_Picture_PullDown_eMax] = |
|---|
| 333 | { |
|---|
| 334 | BXDM_PictureProvider_P_PictureType_eInterlaced, /* Invalid */ |
|---|
| 335 | BXDM_PictureProvider_P_PictureType_eInterlaced, /* BXDM_Picture_PullDown_eTop */ |
|---|
| 336 | BXDM_PictureProvider_P_PictureType_eInterlaced, /* BXDM_Picture_PullDown_eBottom */ |
|---|
| 337 | BXDM_PictureProvider_P_PictureType_eInterlaced, /* BXDM_Picture_PullDown_eTopBottom */ |
|---|
| 338 | BXDM_PictureProvider_P_PictureType_eInterlaced, /* BXDM_Picture_PullDown_eBottomTop */ |
|---|
| 339 | BXDM_PictureProvider_P_PictureType_eInterlaced, /* BXDM_Picture_PullDown_eTopBottomTop */ |
|---|
| 340 | BXDM_PictureProvider_P_PictureType_eInterlaced, /* BXDM_Picture_PullDown_eBottomTopBottom */ |
|---|
| 341 | BXDM_PictureProvider_P_PictureType_eProgressive, /* BXDM_Picture_PullDown_eFrameX2 */ |
|---|
| 342 | BXDM_PictureProvider_P_PictureType_eProgressive, /* BXDM_Picture_PullDown_eFrameX3 */ |
|---|
| 343 | BXDM_PictureProvider_P_PictureType_eProgressive, /* BXDM_Picture_PullDown_eFrameX1 */ |
|---|
| 344 | BXDM_PictureProvider_P_PictureType_eProgressive, /* BXDM_Picture_PullDown_eFrameX4 */ |
|---|
| 345 | }; /* end of sPictureTypeLUT[] */ |
|---|
| 346 | |
|---|
| 347 | /* sProgressiveFrameLUT maps the pulldown information to whether a |
|---|
| 348 | * FRAME is interlaced or progressive for the purposes of field |
|---|
| 349 | * inversion correction. TRUE indicates progressive. */ |
|---|
| 350 | static const bool sProgressiveFrameLUT[BXDM_Picture_PullDown_eMax] = |
|---|
| 351 | { |
|---|
| 352 | false, /* Invalid */ |
|---|
| 353 | false, /* BXDM_Picture_PullDown_eTop */ |
|---|
| 354 | false, /* BXDM_Picture_PullDown_eBottom */ |
|---|
| 355 | false, /* BXDM_Picture_PullDown_eTopBottom */ |
|---|
| 356 | false, /* BXDM_Picture_PullDown_eBottomTop */ |
|---|
| 357 | true, /* BXDM_Picture_PullDown_eTopBottomTop */ |
|---|
| 358 | true, /* BXDM_Picture_PullDown_eBottomTopBottom */ |
|---|
| 359 | true, /* BXDM_Picture_PullDown_eFrameX2 */ |
|---|
| 360 | true, /* BXDM_Picture_PullDown_eFrameX3 */ |
|---|
| 361 | true, /* BXDM_Picture_PullDown_eFrameX1 */ |
|---|
| 362 | true /* BXDM_Picture_PullDown_eFrameX4 */ |
|---|
| 363 | }; /* end of sProgressiveFrameLUT[] */ |
|---|
| 364 | |
|---|
| 365 | /* sProgressiveStreamLUT maps the pulldown information to whether a |
|---|
| 366 | * STREAM is interlaced or progressive for the purposes of reporting |
|---|
| 367 | * to the application. TRUE indicates progressive. */ |
|---|
| 368 | static const bool sProgressiveStreamLUT[BXDM_Picture_PullDown_eMax] = |
|---|
| 369 | { |
|---|
| 370 | false, /* Invalid */ |
|---|
| 371 | false, /* BXDM_Picture_PullDown_eTop */ |
|---|
| 372 | false, /* BXDM_Picture_PullDown_eBottom */ |
|---|
| 373 | false, /* BXDM_Picture_PullDown_eTopBottom */ |
|---|
| 374 | false, /* BXDM_Picture_PullDown_eBottomTop */ |
|---|
| 375 | false, /* BXDM_Picture_PullDown_eTopBottomTop */ |
|---|
| 376 | false, /* BXDM_Picture_PullDown_eBottomTopBottom */ |
|---|
| 377 | true, /* BXDM_Picture_PullDown_eFrameX2 */ |
|---|
| 378 | true, /* BXDM_Picture_PullDown_eFrameX3 */ |
|---|
| 379 | true, /* BXDM_Picture_PullDown_eFrameX1 */ |
|---|
| 380 | true /* BXDM_Picture_PullDown_eFrameX4 */ |
|---|
| 381 | }; /* end of sProgressiveStreamLUT[] */ |
|---|
| 382 | |
|---|
| 383 | /* When in CRC mode, display each picture element once and only once. |
|---|
| 384 | * Remap pulldown information that repeats a picture elemnent to |
|---|
| 385 | * a non-repeating variant. |
|---|
| 386 | */ |
|---|
| 387 | static const uint32_t sRemapPullDownLUT[ BXDM_Picture_PullDown_eMax ] = |
|---|
| 388 | { |
|---|
| 389 | 0, /* invalid */ |
|---|
| 390 | BXDM_Picture_PullDown_eTop, /* unchanged */ |
|---|
| 391 | BXDM_Picture_PullDown_eBottom, /* unchanged */ |
|---|
| 392 | BXDM_Picture_PullDown_eTopBottom, /* unchanged */ |
|---|
| 393 | BXDM_Picture_PullDown_eBottomTop, /* unchanged */ |
|---|
| 394 | BXDM_Picture_PullDown_eTopBottom, /* _eTopBottomTop -> _eTopBottom */ |
|---|
| 395 | BXDM_Picture_PullDown_eBottomTop, /* _eBottomTopBottom -> _eBottomTop */ |
|---|
| 396 | BXDM_Picture_PullDown_eFrameX1, /* _eFrameX2 -> _eFrameX1 */ |
|---|
| 397 | BXDM_Picture_PullDown_eFrameX1, /* _eFrameX3 -> _eFrameX1 */ |
|---|
| 398 | BXDM_Picture_PullDown_eFrameX1, /* unchanged */ |
|---|
| 399 | BXDM_Picture_PullDown_eFrameX1 /* _eFrameX4 -> _eFrameX1 */ |
|---|
| 400 | |
|---|
| 401 | }; /* end of sRemapPullDownLUT[] */ |
|---|
| 402 | |
|---|
| 403 | |
|---|
| 404 | /******************************************************************************* |
|---|
| 405 | * |
|---|
| 406 | * Local function prototypes. |
|---|
| 407 | * |
|---|
| 408 | ******************************************************************************/ |
|---|
| 409 | |
|---|
| 410 | static BXDM_PictureProvider_TSMResult BXDM_PPTSM_S_CompareStcAndPts( |
|---|
| 411 | BXDM_PictureProvider_Handle hXdmPP, |
|---|
| 412 | BXDM_PictureProvider_P_LocalState* pLocalState, |
|---|
| 413 | BXDM_PictureProvider_P_Picture_Context* pstPicture, |
|---|
| 414 | bool bEvaluateActualPts |
|---|
| 415 | ); |
|---|
| 416 | |
|---|
| 417 | /******************************************************************************* |
|---|
| 418 | * |
|---|
| 419 | * Local functions. |
|---|
| 420 | * |
|---|
| 421 | ******************************************************************************/ |
|---|
| 422 | |
|---|
| 423 | |
|---|
| 424 | /******************************************************************************* |
|---|
| 425 | * |
|---|
| 426 | * Public TSM functions. |
|---|
| 427 | * |
|---|
| 428 | ******************************************************************************/ |
|---|
| 429 | |
|---|
| 430 | /* |
|---|
| 431 | * SW7425-764: map BXDM_PictureProvider_MonitorRefreshRate enums to BFMT_Vert |
|---|
| 432 | */ |
|---|
| 433 | static void BXDM_PPTSM_S_BFMTVert_Enum_Lookup( |
|---|
| 434 | BXDM_PictureProvider_MonitorRefreshRate eMonitorRefreshRate, |
|---|
| 435 | BFMT_Vert * peBFMTRefreshRate |
|---|
| 436 | ) |
|---|
| 437 | { |
|---|
| 438 | switch( eMonitorRefreshRate ) |
|---|
| 439 | { |
|---|
| 440 | case BXDM_PictureProvider_MonitorRefreshRate_e23_976Hz: |
|---|
| 441 | *peBFMTRefreshRate = BFMT_Vert_e23_976Hz; |
|---|
| 442 | break; |
|---|
| 443 | |
|---|
| 444 | case BXDM_PictureProvider_MonitorRefreshRate_e24Hz: |
|---|
| 445 | *peBFMTRefreshRate = BFMT_Vert_e24Hz; |
|---|
| 446 | break; |
|---|
| 447 | |
|---|
| 448 | case BXDM_PictureProvider_MonitorRefreshRate_e25Hz: |
|---|
| 449 | *peBFMTRefreshRate = BFMT_Vert_e25Hz; |
|---|
| 450 | break; |
|---|
| 451 | |
|---|
| 452 | case BXDM_PictureProvider_MonitorRefreshRate_e29_97Hz: |
|---|
| 453 | *peBFMTRefreshRate = BFMT_Vert_e29_97Hz; |
|---|
| 454 | break; |
|---|
| 455 | |
|---|
| 456 | case BXDM_PictureProvider_MonitorRefreshRate_e30Hz: |
|---|
| 457 | *peBFMTRefreshRate = BFMT_Vert_e30Hz; |
|---|
| 458 | break; |
|---|
| 459 | |
|---|
| 460 | case BXDM_PictureProvider_MonitorRefreshRate_e50Hz: |
|---|
| 461 | *peBFMTRefreshRate = BFMT_Vert_e50Hz; |
|---|
| 462 | break; |
|---|
| 463 | |
|---|
| 464 | case BXDM_PictureProvider_MonitorRefreshRate_e59_94Hz: |
|---|
| 465 | *peBFMTRefreshRate = BFMT_Vert_e59_94Hz; |
|---|
| 466 | break; |
|---|
| 467 | |
|---|
| 468 | case BXDM_PictureProvider_MonitorRefreshRate_e60Hz: |
|---|
| 469 | *peBFMTRefreshRate = BFMT_Vert_e60Hz; |
|---|
| 470 | break; |
|---|
| 471 | |
|---|
| 472 | case BXDM_PictureProvider_MonitorRefreshRate_e48Hz: |
|---|
| 473 | *peBFMTRefreshRate = BFMT_Vert_e48Hz; |
|---|
| 474 | break; |
|---|
| 475 | |
|---|
| 476 | case BXDM_PictureProvider_MonitorRefreshRate_eUnknown: |
|---|
| 477 | default: |
|---|
| 478 | *peBFMTRefreshRate = BFMT_Vert_eInvalid; |
|---|
| 479 | break; |
|---|
| 480 | } |
|---|
| 481 | } |
|---|
| 482 | |
|---|
| 483 | |
|---|
| 484 | |
|---|
| 485 | static void BXDM_PPTSM_S_ApplyCDTOverride( |
|---|
| 486 | BXDM_PictureProvider_Handle hXdmPP, |
|---|
| 487 | BXDM_PictureProvider_P_LocalState* pLocalState, |
|---|
| 488 | BXDM_PictureProvider_P_Picture_Context* pstPicture, |
|---|
| 489 | BXDM_Picture_PullDown *pePullDown |
|---|
| 490 | ) |
|---|
| 491 | { |
|---|
| 492 | bool b50HzPlusProgressiveSource = false; /* SW7405-4883: scan out 50+ Hz progressive content as progressive */ |
|---|
| 493 | |
|---|
| 494 | BDBG_ASSERT(pePullDown); |
|---|
| 495 | BSTD_UNUSED(pLocalState); |
|---|
| 496 | |
|---|
| 497 | /* |
|---|
| 498 | * SW7425-764: save the monitor refresh rate for this picture. Will be passed to VDC in the MFD structure. |
|---|
| 499 | */ |
|---|
| 500 | BXDM_PPTSM_S_BFMTVert_Enum_Lookup( |
|---|
| 501 | hXdmPP->stDMConfig.eMonitorRefreshRate, |
|---|
| 502 | &(pstPicture->stPicParms.stDisplay.stStatic.eBFMTRefreshRate) |
|---|
| 503 | ); |
|---|
| 504 | |
|---|
| 505 | /* SW7405-5549: save a copy of the monitor refresh rate. Currently this is only used to determine if |
|---|
| 506 | * BXDM_PPTSM_S_ApplyCDTOverride needs to be called again from BXDM_PPTSM_P_EvaluateTsmState. |
|---|
| 507 | */ |
|---|
| 508 | pstPicture->stPicParms.stDisplay.stStatic.eMonitorRefreshRate = hXdmPP->stDMConfig.eMonitorRefreshRate; |
|---|
| 509 | |
|---|
| 510 | /* Set scan mode and repeat modes based on the default cases. |
|---|
| 511 | * Then override as needed to handle the special cases |
|---|
| 512 | */ |
|---|
| 513 | switch ( *pePullDown ) |
|---|
| 514 | { |
|---|
| 515 | case BXDM_Picture_PullDown_eTopBottom: |
|---|
| 516 | case BXDM_Picture_PullDown_eBottomTop: |
|---|
| 517 | case BXDM_Picture_PullDown_eTopBottomTop: |
|---|
| 518 | case BXDM_Picture_PullDown_eBottomTopBottom: |
|---|
| 519 | pstPicture->stPicParms.stDisplay.stStatic.eScanMode = BXDM_PictureProvider_P_ScanMode_eInterlaced; |
|---|
| 520 | pstPicture->stPicParms.stDisplay.stDynamic.eRateConversionRepeatMode = BXDM_PictureProvider_P_RepeatMode_eField; |
|---|
| 521 | |
|---|
| 522 | if ( pstPicture->pstUnifiedPicture->stBufferInfo.eSourceFormat == BXDM_Picture_SourceFormat_eProgressive ) |
|---|
| 523 | { |
|---|
| 524 | pstPicture->stPicParms.stDisplay.stDynamic.eTrickPlayRepeatMode = BXDM_PictureProvider_P_RepeatMode_eFrame; |
|---|
| 525 | } |
|---|
| 526 | else |
|---|
| 527 | { |
|---|
| 528 | pstPicture->stPicParms.stDisplay.stDynamic.eTrickPlayRepeatMode = BXDM_PictureProvider_P_RepeatMode_eField; |
|---|
| 529 | } |
|---|
| 530 | break; |
|---|
| 531 | |
|---|
| 532 | case BXDM_Picture_PullDown_eTop: |
|---|
| 533 | case BXDM_Picture_PullDown_eBottom: |
|---|
| 534 | pstPicture->stPicParms.stDisplay.stStatic.eScanMode = BXDM_PictureProvider_P_ScanMode_eInterlaced; |
|---|
| 535 | pstPicture->stPicParms.stDisplay.stDynamic.eRateConversionRepeatMode = BXDM_PictureProvider_P_RepeatMode_eField; |
|---|
| 536 | pstPicture->stPicParms.stDisplay.stDynamic.eTrickPlayRepeatMode = BXDM_PictureProvider_P_RepeatMode_eField; |
|---|
| 537 | break; |
|---|
| 538 | |
|---|
| 539 | case BXDM_Picture_PullDown_eFrameX1: |
|---|
| 540 | case BXDM_Picture_PullDown_eFrameX2: |
|---|
| 541 | case BXDM_Picture_PullDown_eFrameX3: |
|---|
| 542 | case BXDM_Picture_PullDown_eFrameX4: |
|---|
| 543 | pstPicture->stPicParms.stDisplay.stStatic.eScanMode = BXDM_PictureProvider_P_ScanMode_eProgressive; |
|---|
| 544 | pstPicture->stPicParms.stDisplay.stDynamic.eRateConversionRepeatMode = BXDM_PictureProvider_P_RepeatMode_eFrame; |
|---|
| 545 | pstPicture->stPicParms.stDisplay.stDynamic.eTrickPlayRepeatMode = BXDM_PictureProvider_P_RepeatMode_eFrame; |
|---|
| 546 | break; |
|---|
| 547 | |
|---|
| 548 | default: |
|---|
| 549 | BXVD_DBG_WRN(hXdmPP, ("%x: [%01x.%03x] Unknown Pulldown: %d", |
|---|
| 550 | hXdmPP->stDMState.stDecode.stDebug.uiVsyncCount, |
|---|
| 551 | hXdmPP->stDMConfig.uiInstanceID & 0xF, |
|---|
| 552 | pstPicture->stPicParms.uiPPBIndex & 0xFFF, |
|---|
| 553 | *pePullDown |
|---|
| 554 | )); |
|---|
| 555 | } |
|---|
| 556 | |
|---|
| 557 | switch ( pstPicture->stPicParms.stTSM.stStatic.eFrameRatePreFRD ) |
|---|
| 558 | { |
|---|
| 559 | /* Handle 60i->60p source override */ |
|---|
| 560 | case BAVC_FrameRateCode_e50: |
|---|
| 561 | case BAVC_FrameRateCode_e59_94: |
|---|
| 562 | case BAVC_FrameRateCode_e60: |
|---|
| 563 | if ( BXDM_PictureProvider_P_ScanMode_eProgressive != pstPicture->stPicParms.stDisplay.stStatic.eScanMode ) |
|---|
| 564 | { |
|---|
| 565 | BXVD_DBG_MSG(hXdmPP, ("%x: [%01x.%03x] Source Polarity Override: 60i->60p", |
|---|
| 566 | hXdmPP->stDMState.stDecode.stDebug.uiVsyncCount, |
|---|
| 567 | hXdmPP->stDMConfig.uiInstanceID & 0xF, |
|---|
| 568 | pstPicture->stPicParms.uiPPBIndex & 0xFFF |
|---|
| 569 | )); |
|---|
| 570 | |
|---|
| 571 | pstPicture->stPicParms.uiStateBits |= BXDM_PPDBG_State_60iTo60p; |
|---|
| 572 | |
|---|
| 573 | pstPicture->stPicParms.stDisplay.stStatic.eScanMode = BXDM_PictureProvider_P_ScanMode_eProgressive; |
|---|
| 574 | pstPicture->stPicParms.stDisplay.stDynamic.eRateConversionRepeatMode = BXDM_PictureProvider_P_RepeatMode_eFrame; |
|---|
| 575 | pstPicture->stPicParms.stDisplay.stDynamic.eTrickPlayRepeatMode = BXDM_PictureProvider_P_RepeatMode_eFrame; |
|---|
| 576 | } |
|---|
| 577 | else |
|---|
| 578 | { |
|---|
| 579 | b50HzPlusProgressiveSource = true; /* SW7405-4883: progressive content with a frame rate >= 50 Hz */ |
|---|
| 580 | } |
|---|
| 581 | break; |
|---|
| 582 | |
|---|
| 583 | default: |
|---|
| 584 | break; |
|---|
| 585 | } |
|---|
| 586 | |
|---|
| 587 | /* Handle Progressive Source --> Interlaced Scanout Overrides */ |
|---|
| 588 | if ( BXDM_PictureProvider_P_ScanMode_eProgressive == pstPicture->stPicParms.stDisplay.stStatic.eScanMode ) |
|---|
| 589 | { |
|---|
| 590 | /* Handle 1080p->1080i source override for non-1080p pass-thru cases |
|---|
| 591 | * |
|---|
| 592 | * SW7420-666: Originally the comparison below was to 720. However there are some progressive |
|---|
| 593 | * Allegro streams incorrectly coded with a frame rate of 60i and a source height of 736. |
|---|
| 594 | * These streams are actually 60p. The logic in the preceding block sets the scan out parameters |
|---|
| 595 | * correctly to progressive. However the code in this block was incorrectly setting the scan mode |
|---|
| 596 | * back to interlaced based on the height of 736. As it turns out, the height was clipped to |
|---|
| 597 | * 720 in BXDM_PPOUT_S_SetClipping. Whether clipped or not, a source height of 736 can be scanned |
|---|
| 598 | * out as progressive. |
|---|
| 599 | * |
|---|
| 600 | * SW7405-4883: if the video decoder is delivering 1080p source with a frame rate of 50Hz or greater, |
|---|
| 601 | * the assumption is that the entire system can support this content. With regard to this block of |
|---|
| 602 | * code, we're assuming that VDC has enough memory bandwidth and the stream does NOT need to be |
|---|
| 603 | * scanned out as interlaced. |
|---|
| 604 | */ |
|---|
| 605 | if ( pstPicture->pstUnifiedPicture->stBufferInfo.stSource.uiHeight > 736 |
|---|
| 606 | && false == b50HzPlusProgressiveSource ) |
|---|
| 607 | { |
|---|
| 608 | /* We have a 1080p source */ |
|---|
| 609 | switch ( hXdmPP->stDMConfig.eMonitorRefreshRate ) |
|---|
| 610 | { |
|---|
| 611 | case BXDM_PictureProvider_MonitorRefreshRate_e23_976Hz: |
|---|
| 612 | case BXDM_PictureProvider_MonitorRefreshRate_e24Hz: |
|---|
| 613 | case BXDM_PictureProvider_MonitorRefreshRate_e25Hz: |
|---|
| 614 | case BXDM_PictureProvider_MonitorRefreshRate_e29_97Hz: |
|---|
| 615 | case BXDM_PictureProvider_MonitorRefreshRate_e30Hz: |
|---|
| 616 | case BXDM_PictureProvider_MonitorRefreshRate_e48Hz: |
|---|
| 617 | /* Do not override 23.97,24,25,29.97, or 30Hz displays */ |
|---|
| 618 | break; |
|---|
| 619 | |
|---|
| 620 | default: |
|---|
| 621 | /* Do not override 1080p advanced pulldown cases */ |
|---|
| 622 | if ( !( ( hXdmPP->stDMConfig.e1080pScanMode >= BXDM_PictureProvider_1080pScanMode_eAdvanced ) |
|---|
| 623 | /* Do not override 1080p23.97/24/29.97/30 --> 59.94/60Hz Display (3:2 pulldown) */ |
|---|
| 624 | && ( ( ( ( BXDM_PictureProvider_MonitorRefreshRate_e59_94Hz == hXdmPP->stDMConfig.eMonitorRefreshRate ) |
|---|
| 625 | || ( BXDM_PictureProvider_MonitorRefreshRate_e60Hz == hXdmPP->stDMConfig.eMonitorRefreshRate ) ) |
|---|
| 626 | && ( ( BAVC_FrameRateCode_e23_976 == pstPicture->stPicParms.stTSM.stStatic.eFrameRatePreFRD ) |
|---|
| 627 | || ( BAVC_FrameRateCode_e24 == pstPicture->stPicParms.stTSM.stStatic.eFrameRatePreFRD ) |
|---|
| 628 | || ( BAVC_FrameRateCode_e29_97 == pstPicture->stPicParms.stTSM.stStatic.eFrameRatePreFRD ) |
|---|
| 629 | || ( BAVC_FrameRateCode_e30 == pstPicture->stPicParms.stTSM.stStatic.eFrameRatePreFRD ) ) ) |
|---|
| 630 | /* Do not override 1080p25 --> 50Hz Display (2:2 pulldown) */ |
|---|
| 631 | || ( ( BXDM_PictureProvider_MonitorRefreshRate_e50Hz == hXdmPP->stDMConfig.eMonitorRefreshRate ) |
|---|
| 632 | && ( BAVC_FrameRateCode_e25 == pstPicture->stPicParms.stTSM.stStatic.eFrameRatePreFRD ) ) |
|---|
| 633 | ) |
|---|
| 634 | ) |
|---|
| 635 | ) |
|---|
| 636 | { |
|---|
| 637 | /* We still need to force an interlaced scanout for this content |
|---|
| 638 | * since by default 1080p scanout at > 48Hz is not supported */ |
|---|
| 639 | pstPicture->stPicParms.stDisplay.stStatic.eScanMode = BXDM_PictureProvider_P_ScanMode_eInterlaced; |
|---|
| 640 | |
|---|
| 641 | if ( ( BXDM_PictureProvider_PulldownMode_eUseEncodedFormat != hXdmPP->stDMConfig.e1080pPulldownMode ) |
|---|
| 642 | && ( BXDM_Picture_PullDown_eFrameX1 == *pePullDown ) ) |
|---|
| 643 | { |
|---|
| 644 | /* We have an HD progressive frame (1080p) but no |
|---|
| 645 | * compatible display, so we need to force it to be |
|---|
| 646 | * interlaced (1080i) for two reasons: |
|---|
| 647 | * 1) Most flavors of VDC does not have the bandwidth to |
|---|
| 648 | * display 1080p60 |
|---|
| 649 | * 2) Many early streams were incorrectly encoded as 1080p |
|---|
| 650 | * when they were really 1080i */ |
|---|
| 651 | BXVD_DBG_MSG(hXdmPP, ("%x: [%01x.%03x] Source Polarity Override: 1080p->1080i", |
|---|
| 652 | hXdmPP->stDMState.stDecode.stDebug.uiVsyncCount, |
|---|
| 653 | hXdmPP->stDMConfig.uiInstanceID & 0xF, |
|---|
| 654 | pstPicture->stPicParms.uiPPBIndex & 0xFFF |
|---|
| 655 | )); |
|---|
| 656 | |
|---|
| 657 | pstPicture->stPicParms.uiStateBits |= BXDM_PPDBG_State_1080pTo1080i; |
|---|
| 658 | |
|---|
| 659 | pstPicture->stPicParms.stDisplay.stDynamic.eRateConversionRepeatMode = BXDM_PictureProvider_P_RepeatMode_eField; |
|---|
| 660 | |
|---|
| 661 | switch ( hXdmPP->stDMConfig.e1080pPulldownMode ) |
|---|
| 662 | { |
|---|
| 663 | case BXDM_PictureProvider_PulldownMode_eTopBottom: |
|---|
| 664 | *pePullDown = BXDM_Picture_PullDown_eTopBottom; |
|---|
| 665 | break; |
|---|
| 666 | case BXDM_PictureProvider_PulldownMode_eBottomTop: |
|---|
| 667 | *pePullDown = BXDM_Picture_PullDown_eBottomTop; |
|---|
| 668 | break; |
|---|
| 669 | default: |
|---|
| 670 | BXVD_DBG_ERR(hXdmPP, ("%x: [%01x.%03x] Unsupported 1080p Progressive Override Mode (%d)", |
|---|
| 671 | hXdmPP->stDMState.stDecode.stDebug.uiVsyncCount, |
|---|
| 672 | hXdmPP->stDMConfig.uiInstanceID & 0xF, |
|---|
| 673 | pstPicture->stPicParms.uiPPBIndex & 0xFFF, |
|---|
| 674 | hXdmPP->stDMConfig.e1080pPulldownMode |
|---|
| 675 | )); |
|---|
| 676 | } |
|---|
| 677 | } |
|---|
| 678 | } |
|---|
| 679 | break; |
|---|
| 680 | } |
|---|
| 681 | } |
|---|
| 682 | else if ( ( 480 == pstPicture->pstUnifiedPicture->stBufferInfo.stSource.uiHeight ) |
|---|
| 683 | || ( 576 == pstPicture->pstUnifiedPicture->stBufferInfo.stSource.uiHeight ) ) |
|---|
| 684 | { |
|---|
| 685 | /* Handle 480p30->480i30 source override */ |
|---|
| 686 | if ( ! /* Do not override 480p23.97/24 --> 23.97/24Hz Display (1:1 pulldown) */ |
|---|
| 687 | ( ( ( ( BAVC_FrameRateCode_e23_976 == pstPicture->stPicParms.stTSM.stStatic.eFrameRatePreFRD ) |
|---|
| 688 | || ( BAVC_FrameRateCode_e24 == pstPicture->stPicParms.stTSM.stStatic.eFrameRatePreFRD ) ) |
|---|
| 689 | && ( ( BXDM_PictureProvider_MonitorRefreshRate_e23_976Hz == hXdmPP->stDMConfig.eMonitorRefreshRate ) |
|---|
| 690 | || ( BXDM_PictureProvider_MonitorRefreshRate_e24Hz == hXdmPP->stDMConfig.eMonitorRefreshRate ) ) ) |
|---|
| 691 | /* Do not override 480p25 --> 25Hz Display (1:1 pulldown) */ |
|---|
| 692 | || ( ( BAVC_FrameRateCode_e25 == pstPicture->stPicParms.stTSM.stStatic.eFrameRatePreFRD ) |
|---|
| 693 | && ( BXDM_PictureProvider_MonitorRefreshRate_e25Hz == hXdmPP->stDMConfig.eMonitorRefreshRate ) ) |
|---|
| 694 | /* Do not override 480p29.97/30 --> 29.97/30 Hz Display (1:1 pulldown) */ |
|---|
| 695 | || ( ( ( BAVC_FrameRateCode_e29_97 == pstPicture->stPicParms.stTSM.stStatic.eFrameRatePreFRD ) |
|---|
| 696 | || ( BAVC_FrameRateCode_e30 == pstPicture->stPicParms.stTSM.stStatic.eFrameRatePreFRD ) ) |
|---|
| 697 | && ( ( BXDM_PictureProvider_MonitorRefreshRate_e29_97Hz == hXdmPP->stDMConfig.eMonitorRefreshRate ) |
|---|
| 698 | || ( BXDM_PictureProvider_MonitorRefreshRate_e30Hz == hXdmPP->stDMConfig.eMonitorRefreshRate ) ) ) |
|---|
| 699 | /* Do not override 480p50/59.94/60 ever */ |
|---|
| 700 | || ( BAVC_FrameRateCode_e50 == pstPicture->stPicParms.stTSM.stStatic.eFrameRatePreFRD ) |
|---|
| 701 | || ( BAVC_FrameRateCode_e59_94 == pstPicture->stPicParms.stTSM.stStatic.eFrameRatePreFRD ) |
|---|
| 702 | || ( BAVC_FrameRateCode_e60 == pstPicture->stPicParms.stTSM.stStatic.eFrameRatePreFRD ) |
|---|
| 703 | ) |
|---|
| 704 | ) |
|---|
| 705 | { |
|---|
| 706 | if ( BXDM_PictureProvider_PulldownMode_eUseEncodedFormat != hXdmPP->stDMConfig.e480pPulldownMode ) |
|---|
| 707 | { |
|---|
| 708 | pstPicture->stPicParms.stDisplay.stStatic.eScanMode = BXDM_PictureProvider_P_ScanMode_eInterlaced; |
|---|
| 709 | |
|---|
| 710 | switch (*pePullDown) |
|---|
| 711 | { |
|---|
| 712 | case BXDM_Picture_PullDown_eFrameX1: |
|---|
| 713 | /* We have a (480/576)p(30/29.97) frame, so we need to treat |
|---|
| 714 | * is as interlaced because many DVDs are mis-encoded as |
|---|
| 715 | * progressive. Here's Darren Neuman's explanation: |
|---|
| 716 | * |
|---|
| 717 | * For 480p24 and 480p30, we found on DVD's that this content |
|---|
| 718 | * was really intended to display on a 480i display, so |
|---|
| 719 | * scanning out interlaced makes a lot of sense. Often the |
|---|
| 720 | * content is mis-marked. |
|---|
| 721 | * |
|---|
| 722 | * Scanning out interlaced then goes into our MAD |
|---|
| 723 | * deinterlacer, which can sort out the fields/frames and |
|---|
| 724 | * construct the correct picture. |
|---|
| 725 | */ |
|---|
| 726 | BXVD_DBG_MSG(hXdmPP, ("%x: [%01x.%03x] Source Polarity Override: 480p->480i", |
|---|
| 727 | hXdmPP->stDMState.stDecode.stDebug.uiVsyncCount, |
|---|
| 728 | hXdmPP->stDMConfig.uiInstanceID & 0xF, |
|---|
| 729 | pstPicture->stPicParms.uiPPBIndex & 0xFFF |
|---|
| 730 | )); |
|---|
| 731 | pstPicture->stPicParms.uiStateBits |= BXDM_PPDBG_State_480pTo480i; |
|---|
| 732 | |
|---|
| 733 | pstPicture->stPicParms.stDisplay.stDynamic.eRateConversionRepeatMode = BXDM_PictureProvider_P_RepeatMode_eField; |
|---|
| 734 | |
|---|
| 735 | switch ( hXdmPP->stDMConfig.e480pPulldownMode ) |
|---|
| 736 | { |
|---|
| 737 | case BXDM_PictureProvider_PulldownMode_eTopBottom: |
|---|
| 738 | *pePullDown = BXDM_Picture_PullDown_eTopBottom; |
|---|
| 739 | break; |
|---|
| 740 | case BXDM_PictureProvider_PulldownMode_eBottomTop: |
|---|
| 741 | *pePullDown = BXDM_Picture_PullDown_eBottomTop; |
|---|
| 742 | break; |
|---|
| 743 | default: |
|---|
| 744 | BXVD_DBG_ERR(hXdmPP, ("%x: [%01x.%03x] Unsupported 480p Progressive Override Mode (%d)", |
|---|
| 745 | hXdmPP->stDMState.stDecode.stDebug.uiVsyncCount, |
|---|
| 746 | hXdmPP->stDMConfig.uiInstanceID & 0xF, |
|---|
| 747 | pstPicture->stPicParms.uiPPBIndex & 0xFFF, |
|---|
| 748 | hXdmPP->stDMConfig.e480pPulldownMode |
|---|
| 749 | )); |
|---|
| 750 | } |
|---|
| 751 | break; |
|---|
| 752 | default: |
|---|
| 753 | break; |
|---|
| 754 | } |
|---|
| 755 | } |
|---|
| 756 | } |
|---|
| 757 | } |
|---|
| 758 | } |
|---|
| 759 | |
|---|
| 760 | /* Handle 240i30->240p30 source override */ |
|---|
| 761 | if ( ( BXDM_PictureProvider_P_ScanMode_eProgressive != pstPicture->stPicParms.stDisplay.stStatic.eScanMode ) |
|---|
| 762 | && ( BXDM_PictureProvider_240iScanMode_eForceProgressive == hXdmPP->stDMConfig.e240iScanMode ) |
|---|
| 763 | && ( ( 240 == pstPicture->pstUnifiedPicture->stBufferInfo.stSource.uiHeight ) |
|---|
| 764 | || ( 288 == pstPicture->pstUnifiedPicture->stBufferInfo.stSource.uiHeight ) ) |
|---|
| 765 | && ( BAVC_VideoCompressionStd_eH264 != pstPicture->pstUnifiedPicture->stProtocol.eProtocol ) |
|---|
| 766 | ) |
|---|
| 767 | { |
|---|
| 768 | /* We have a (240/288)i(30/29.97) non-AVC frame, so we need |
|---|
| 769 | * to treat it as progressive because some streams are |
|---|
| 770 | * mis-encoded. Here's Darren Neuman's explanation: |
|---|
| 771 | * |
|---|
| 772 | * Basically the content on MPEG-1 and VCD used 352x240 |
|---|
| 773 | * progressive for video. The transition to MPEG-2 caused |
|---|
| 774 | * confusion to the encoders at the time, and they |
|---|
| 775 | * mis-labeled some streams 240i for some streams, but we |
|---|
| 776 | * found the content was actually progressive in almost every |
|---|
| 777 | * case we could find. It was just experimental evidence that |
|---|
| 778 | * showed better performance scaning out progressive. |
|---|
| 779 | */ |
|---|
| 780 | BXVD_DBG_MSG(hXdmPP, ("%x: [%01x.%03x] Source Polarity Override: 240i->240p (non-AVC)", |
|---|
| 781 | hXdmPP->stDMState.stDecode.stDebug.uiVsyncCount, |
|---|
| 782 | hXdmPP->stDMConfig.uiInstanceID & 0xF, |
|---|
| 783 | pstPicture->stPicParms.uiPPBIndex & 0xFFF |
|---|
| 784 | )); |
|---|
| 785 | pstPicture->stPicParms.uiStateBits |= BXDM_PPDBG_State_240iTo240p; |
|---|
| 786 | |
|---|
| 787 | pstPicture->stPicParms.stDisplay.stStatic.eScanMode = BXDM_PictureProvider_P_ScanMode_eProgressive; |
|---|
| 788 | pstPicture->stPicParms.stDisplay.stDynamic.eRateConversionRepeatMode = BXDM_PictureProvider_P_RepeatMode_eFrame; |
|---|
| 789 | pstPicture->stPicParms.stDisplay.stDynamic.eTrickPlayRepeatMode = BXDM_PictureProvider_P_RepeatMode_eFrame; |
|---|
| 790 | } |
|---|
| 791 | |
|---|
| 792 | /* Handle 24i to 24p override */ |
|---|
| 793 | if ( ( ( BAVC_FrameRateCode_e23_976 == pstPicture->stPicParms.stTSM.stStatic.eFrameRate ) |
|---|
| 794 | || ( BAVC_FrameRateCode_e24 == pstPicture->stPicParms.stTSM.stStatic.eFrameRate ) |
|---|
| 795 | || ( true == pstPicture->stPicParms.stDisplay.stStatic.b32FilmSource ) ) |
|---|
| 796 | && ( ( BXDM_PictureProvider_P_RepeatMode_eFrame != pstPicture->stPicParms.stDisplay.stDynamic.eRateConversionRepeatMode ) |
|---|
| 797 | || ( BXDM_PictureProvider_P_RepeatMode_eFrame != pstPicture->stPicParms.stDisplay.stDynamic.eTrickPlayRepeatMode ) ) ) |
|---|
| 798 | { |
|---|
| 799 | BXVD_DBG_MSG(hXdmPP,("%x: [%01x.%03x] 3:2 Source Format Override", |
|---|
| 800 | hXdmPP->stDMState.stDecode.stDebug.uiVsyncCount, |
|---|
| 801 | hXdmPP->stDMConfig.uiInstanceID & 0xF, |
|---|
| 802 | pstPicture->stPicParms.uiPPBIndex & 0xFFF |
|---|
| 803 | )); |
|---|
| 804 | |
|---|
| 805 | pstPicture->stPicParms.stDisplay.stDynamic.eRateConversionRepeatMode = BXDM_PictureProvider_P_RepeatMode_eFrame; |
|---|
| 806 | pstPicture->stPicParms.stDisplay.stDynamic.eTrickPlayRepeatMode = BXDM_PictureProvider_P_RepeatMode_eFrame; |
|---|
| 807 | } |
|---|
| 808 | } |
|---|
| 809 | |
|---|
| 810 | #define BXDM_PPTSM_P_FRAME_RATE_NORMALIZATION_FACTOR 1000 |
|---|
| 811 | |
|---|
| 812 | typedef struct BXDM_PPTSM_P_FrameRateMap |
|---|
| 813 | { |
|---|
| 814 | uint32_t uiNormalizedFrameRate; |
|---|
| 815 | BAVC_FrameRateCode eFrameRateCode; |
|---|
| 816 | } BXDM_PPTSM_P_FrameRateMap; |
|---|
| 817 | |
|---|
| 818 | static const BXDM_PPTSM_P_FrameRateMap sFrameRateLUT[] = |
|---|
| 819 | { |
|---|
| 820 | { 0, BAVC_FrameRateCode_eUnknown }, |
|---|
| 821 | { 7492, BAVC_FrameRateCode_e7_493 }, |
|---|
| 822 | { 14985, BAVC_FrameRateCode_e14_985 }, |
|---|
| 823 | { 23976, BAVC_FrameRateCode_e23_976 }, |
|---|
| 824 | { 24000, BAVC_FrameRateCode_e24 }, |
|---|
| 825 | { 25000, BAVC_FrameRateCode_e25 }, |
|---|
| 826 | { 29970, BAVC_FrameRateCode_e29_97 }, |
|---|
| 827 | { 30000, BAVC_FrameRateCode_e30 }, |
|---|
| 828 | { 50000, BAVC_FrameRateCode_e50 }, |
|---|
| 829 | { 59940, BAVC_FrameRateCode_e59_94 }, |
|---|
| 830 | { 60000, BAVC_FrameRateCode_e60 }, |
|---|
| 831 | { 60001, BAVC_FrameRateCode_eUnknown } |
|---|
| 832 | }; |
|---|
| 833 | |
|---|
| 834 | static |
|---|
| 835 | BAVC_FrameRateCode |
|---|
| 836 | BXDM_PPTSM_S_LookupFrameRate( |
|---|
| 837 | const BXDM_Picture_FrameRate *pstFrameRate |
|---|
| 838 | ) |
|---|
| 839 | { |
|---|
| 840 | BAVC_FrameRateCode eFrameRateCode = BAVC_FrameRateCode_eUnknown; |
|---|
| 841 | uint32_t uiNormalizedFrameRate; |
|---|
| 842 | uint32_t uiIndex = 0; |
|---|
| 843 | uint32_t uiMaxIndex = sizeof( sFrameRateLUT ) / sizeof( BXDM_PPTSM_P_FrameRateMap ); |
|---|
| 844 | |
|---|
| 845 | if ( ( NULL == pstFrameRate ) |
|---|
| 846 | || ( false == pstFrameRate->bValid ) |
|---|
| 847 | || ( 0 == pstFrameRate->stRate.uiNumerator ) |
|---|
| 848 | || ( 0 == pstFrameRate->stRate.uiDenominator ) |
|---|
| 849 | ) |
|---|
| 850 | { |
|---|
| 851 | return BAVC_FrameRateCode_eUnknown; |
|---|
| 852 | } |
|---|
| 853 | |
|---|
| 854 | uiNormalizedFrameRate = (BXDM_PPTSM_P_FRAME_RATE_NORMALIZATION_FACTOR * pstFrameRate->stRate.uiNumerator) / pstFrameRate->stRate.uiDenominator; |
|---|
| 855 | |
|---|
| 856 | for (uiIndex = 0; uiIndex < uiMaxIndex; uiIndex++ ) |
|---|
| 857 | { |
|---|
| 858 | if ( uiNormalizedFrameRate < sFrameRateLUT[uiIndex].uiNormalizedFrameRate ) break; |
|---|
| 859 | eFrameRateCode = sFrameRateLUT[uiIndex].eFrameRateCode; |
|---|
| 860 | } |
|---|
| 861 | |
|---|
| 862 | return eFrameRateCode; |
|---|
| 863 | } |
|---|
| 864 | |
|---|
| 865 | void BXDM_PPTSM_P_PtsCalculateParameters( |
|---|
| 866 | BXDM_PictureProvider_Handle hXdmPP, |
|---|
| 867 | BXDM_PictureProvider_P_LocalState* pLocalState, |
|---|
| 868 | BXDM_PictureProvider_P_Picture_Context* pstPicture |
|---|
| 869 | ) |
|---|
| 870 | { |
|---|
| 871 | BXDM_PictureProvider_P_Picture_Params * pstPicParms; |
|---|
| 872 | BXDM_PictureProvider_P_PictureType ePictureType; |
|---|
| 873 | BAVC_Polarity ePolarity; |
|---|
| 874 | BXDM_Picture_PullDown ePullDown; |
|---|
| 875 | BAVC_FrameRateCode eFrameRateFRD; |
|---|
| 876 | |
|---|
| 877 | uint32_t i; |
|---|
| 878 | bool bTreatAsSingleElement = false; |
|---|
| 879 | |
|---|
| 880 | BSTD_UNUSED( hXdmPP ); |
|---|
| 881 | BSTD_UNUSED( pLocalState ); |
|---|
| 882 | |
|---|
| 883 | BDBG_ENTER(BXDM_PPTSM_P_PtsCalculateParameters); |
|---|
| 884 | |
|---|
| 885 | BDBG_ASSERT( pstPicture ) ; |
|---|
| 886 | |
|---|
| 887 | /* Initialize the local variables. */ |
|---|
| 888 | pstPicParms = &( pstPicture->stPicParms ); |
|---|
| 889 | |
|---|
| 890 | /* Dereference the PPB state to make it easier to access further on in the code. |
|---|
| 891 | * By saving it in the picture context, we will also be able look at the state of preceding pictures. |
|---|
| 892 | */ |
|---|
| 893 | |
|---|
| 894 | /* SWDEPRECATED-1003: If specified use the frame rate override. |
|---|
| 895 | * Otherwise use the value from the stream. |
|---|
| 896 | */ |
|---|
| 897 | if ( true == hXdmPP->stDMConfig.stFrameRateOverride.bValid ) |
|---|
| 898 | { |
|---|
| 899 | BXDM_Picture_FrameRate stFrameRate; |
|---|
| 900 | stFrameRate.bValid = hXdmPP->stDMConfig.stFrameRateOverride.bValid; |
|---|
| 901 | stFrameRate.stRate = hXdmPP->stDMConfig.stFrameRateOverride.stRate; |
|---|
| 902 | |
|---|
| 903 | pstPicParms->stTSM.stStatic.eFrameRate = BXDM_PPTSM_S_LookupFrameRate(&stFrameRate); |
|---|
| 904 | |
|---|
| 905 | bTreatAsSingleElement = hXdmPP->stDMConfig.stFrameRateOverride.bTreatAsSingleElement; |
|---|
| 906 | |
|---|
| 907 | pstPicParms->stTSM.stStatic.eFrameRateType = BXDM_PictureProvider_P_FrameRateType_eOverride; |
|---|
| 908 | } |
|---|
| 909 | else |
|---|
| 910 | { |
|---|
| 911 | pstPicParms->stTSM.stStatic.eFrameRate = BXDM_PPTSM_S_LookupFrameRate(&pstPicture->pstUnifiedPicture->stFrameRate); |
|---|
| 912 | |
|---|
| 913 | pstPicParms->stTSM.stStatic.eFrameRateType = BXDM_PictureProvider_P_FrameRateType_eCoded; |
|---|
| 914 | } |
|---|
| 915 | |
|---|
| 916 | pstPicParms->stTSM.stStatic.eFrameRateXVD = pstPicParms->stTSM.stStatic.eFrameRate; |
|---|
| 917 | |
|---|
| 918 | /* Handle unknown/unsupported coded frame rates */ |
|---|
| 919 | if ( ( pstPicParms->stTSM.stStatic.eFrameRate == BAVC_FrameRateCode_eUnknown ) || |
|---|
| 920 | ( pstPicParms->stTSM.stStatic.eFrameRate > BAVC_FrameRateCode_e7_493 ) ) |
|---|
| 921 | { |
|---|
| 922 | if ( hXdmPP->stDMState.stDecode.eLastUnsupportedFrameRate != pstPicParms->stTSM.stStatic.eFrameRate ) |
|---|
| 923 | { |
|---|
| 924 | if ( BAVC_FrameRateCode_eUnknown == hXdmPP->stDMConfig.eDefaultFrameRate ) |
|---|
| 925 | { |
|---|
| 926 | BXVD_DBG_WRN(hXdmPP, ("%x: [%01x.%03x] Overriding unsupported frame rate of %d to default of eUnknown", |
|---|
| 927 | hXdmPP->stDMState.stDecode.stDebug.uiVsyncCount, |
|---|
| 928 | hXdmPP->stDMConfig.uiInstanceID & 0xF, |
|---|
| 929 | pstPicture->stPicParms.uiPPBIndex & 0xFFF, |
|---|
| 930 | pstPicParms->stTSM.stStatic.eFrameRate |
|---|
| 931 | )); |
|---|
| 932 | } |
|---|
| 933 | else |
|---|
| 934 | { |
|---|
| 935 | BXVD_DBG_MSG(hXdmPP, ("%x: [%01x.%03x] Overriding unsupported frame rate of %d to default of %d", |
|---|
| 936 | hXdmPP->stDMState.stDecode.stDebug.uiVsyncCount, |
|---|
| 937 | hXdmPP->stDMConfig.uiInstanceID & 0xF, |
|---|
| 938 | pstPicture->stPicParms.uiPPBIndex & 0xFFF, |
|---|
| 939 | pstPicParms->stTSM.stStatic.eFrameRate, |
|---|
| 940 | hXdmPP->stDMConfig.eDefaultFrameRate |
|---|
| 941 | )); |
|---|
| 942 | } |
|---|
| 943 | |
|---|
| 944 | hXdmPP->stDMState.stDecode.eLastUnsupportedFrameRate = pstPicParms->stTSM.stStatic.eFrameRate; |
|---|
| 945 | } |
|---|
| 946 | |
|---|
| 947 | pstPicParms->stTSM.stStatic.eFrameRate = hXdmPP->stDMConfig.eDefaultFrameRate; |
|---|
| 948 | |
|---|
| 949 | pstPicParms->stTSM.stStatic.eFrameRateType = BXDM_PictureProvider_P_FrameRateType_eDefault; |
|---|
| 950 | } |
|---|
| 951 | |
|---|
| 952 | pstPicParms->stTSM.stStatic.eFrameRatePreFRD = pstPicParms->stTSM.stStatic.eFrameRate; |
|---|
| 953 | |
|---|
| 954 | if ( false == hXdmPP->stDMConfig.bCRCMode ) |
|---|
| 955 | { |
|---|
| 956 | if ( BAVC_FrameRateCode_eUnknown == pstPicParms->stTSM.stStatic.eFrameRate ) |
|---|
| 957 | { |
|---|
| 958 | /* If the frame rate is still unknown, then we use the Frame |
|---|
| 959 | * Rate Detection (FRD) logic to get a STABLE frame rate based |
|---|
| 960 | * on the PTS values that we've seen in the past */ |
|---|
| 961 | BXDM_PPFRD_P_GetFrameRate( |
|---|
| 962 | hXdmPP, |
|---|
| 963 | pLocalState->eClockRate, |
|---|
| 964 | hXdmPP->stDMConfig.eFrameRateDetectionMode, |
|---|
| 965 | &pstPicParms->stTSM.stStatic.eFrameRate); |
|---|
| 966 | |
|---|
| 967 | pstPicParms->stTSM.stStatic.eFrameRateType = BXDM_PictureProvider_P_FrameRateType_eCalculated; |
|---|
| 968 | |
|---|
| 969 | } |
|---|
| 970 | |
|---|
| 971 | pstPicParms->stTSM.stStatic.eFrameRateXVD = pstPicParms->stTSM.stStatic.eFrameRate; |
|---|
| 972 | |
|---|
| 973 | if ( pstPicParms->stTSM.stStatic.eFrameRateXVD == BAVC_FrameRateCode_eUnknown ) |
|---|
| 974 | { |
|---|
| 975 | /* PR47456: Determine frame rate using PTS values. For XVD |
|---|
| 976 | * internal purposes, we really don't care how accurate the |
|---|
| 977 | * frame rate is, so we use the FAST frame rate detection |
|---|
| 978 | * logic */ |
|---|
| 979 | BXDM_PPFRD_P_GetFrameRate( |
|---|
| 980 | hXdmPP, |
|---|
| 981 | pLocalState->eClockRate, |
|---|
| 982 | BXDM_PictureProvider_FrameRateDetectionMode_eFast, |
|---|
| 983 | &pstPicParms->stTSM.stStatic.eFrameRateXVD); |
|---|
| 984 | |
|---|
| 985 | pstPicParms->stTSM.stStatic.eFrameRateType = BXDM_PictureProvider_P_FrameRateType_eCalculated; |
|---|
| 986 | } |
|---|
| 987 | } |
|---|
| 988 | |
|---|
| 989 | eFrameRateFRD = pstPicParms->stTSM.stStatic.eFrameRateXVD; |
|---|
| 990 | |
|---|
| 991 | if ( pstPicParms->stTSM.stStatic.eFrameRateXVD == BAVC_FrameRateCode_eUnknown ) |
|---|
| 992 | { |
|---|
| 993 | pstPicParms->stTSM.stStatic.eFrameRateType = BXDM_PictureProvider_P_FrameRateType_eForced; |
|---|
| 994 | |
|---|
| 995 | /* Set internal XVD default frame rate based on video_height. |
|---|
| 996 | * - PAL content should assume 25fps. |
|---|
| 997 | * - All other content should assume 30fps |
|---|
| 998 | */ |
|---|
| 999 | if ( 576 == pstPicture->pstUnifiedPicture->stBufferInfo.stSource.uiHeight ) |
|---|
| 1000 | { |
|---|
| 1001 | pstPicParms->stTSM.stStatic.eFrameRateXVD = BAVC_FrameRateCode_e25; |
|---|
| 1002 | } |
|---|
| 1003 | else |
|---|
| 1004 | { |
|---|
| 1005 | pstPicParms->stTSM.stStatic.eFrameRateXVD = BAVC_FrameRateCode_e30; |
|---|
| 1006 | } |
|---|
| 1007 | } |
|---|
| 1008 | |
|---|
| 1009 | /* If in CRC mode, use the "frame" bits of the "flags" variable to |
|---|
| 1010 | * override the pulldown, source format and progressive sequence flag. |
|---|
| 1011 | */ |
|---|
| 1012 | ePullDown = pstPicture->pstUnifiedPicture->stBufferInfo.ePulldown; |
|---|
| 1013 | |
|---|
| 1014 | /* Determine the pulldown */ |
|---|
| 1015 | if ((ePullDown > BXDM_Picture_PullDown_eFrameX4) || |
|---|
| 1016 | (ePullDown < BXDM_Picture_PullDown_eTop)) |
|---|
| 1017 | { |
|---|
| 1018 | ePullDown = BXDM_Picture_PullDown_eTopBottom; |
|---|
| 1019 | |
|---|
| 1020 | if ( hXdmPP->stDMState.stDecode.eLastUnsupportedPullDown != pstPicture->pstUnifiedPicture->stBufferInfo.ePulldown ) |
|---|
| 1021 | { |
|---|
| 1022 | BXVD_DBG_WRN(hXdmPP, ("%x: [%01x.%03x] Pulldown Override: Unsupported(%d->%d)", |
|---|
| 1023 | hXdmPP->stDMState.stDecode.stDebug.uiVsyncCount, |
|---|
| 1024 | hXdmPP->stDMConfig.uiInstanceID & 0xF, |
|---|
| 1025 | pstPicture->stPicParms.uiPPBIndex & 0xFFF, |
|---|
| 1026 | pstPicture->pstUnifiedPicture->stBufferInfo.ePulldown, ePullDown |
|---|
| 1027 | )); |
|---|
| 1028 | hXdmPP->stDMState.stDecode.eLastUnsupportedPullDown = pstPicture->pstUnifiedPicture->stBufferInfo.ePulldown; |
|---|
| 1029 | } |
|---|
| 1030 | } |
|---|
| 1031 | |
|---|
| 1032 | /* SW7405-5549: save a copy of the pulldown. Currently this is only used when |
|---|
| 1033 | * BXDM_PPTSM_S_ApplyCDTOverride needs to be called again from BXDM_PPTSM_P_EvaluateTsmState. |
|---|
| 1034 | */ |
|---|
| 1035 | pstPicParms->stTSM.stStatic.ePullDownRangeChecked = ePullDown; |
|---|
| 1036 | |
|---|
| 1037 | /* SW7405-2942:: move BXDM_PPFRD_P_AddPTS after range checking ePullDown */ |
|---|
| 1038 | BXDM_PPFRD_P_AddPTS( |
|---|
| 1039 | hXdmPP, |
|---|
| 1040 | pstPicture->pstUnifiedPicture->stPTS.uiValue, |
|---|
| 1041 | pstPicture->pstUnifiedPicture->stPTS.bValid, |
|---|
| 1042 | sNumElementsLUT[ePullDown]); |
|---|
| 1043 | |
|---|
| 1044 | if ( false == hXdmPP->stDMConfig.bCRCMode ) |
|---|
| 1045 | { |
|---|
| 1046 | BXDM_PPTSM_S_ApplyCDTOverride( hXdmPP, pLocalState, pstPicture, &ePullDown); |
|---|
| 1047 | } |
|---|
| 1048 | |
|---|
| 1049 | /* Determine the number of elements based on pulldown */ |
|---|
| 1050 | pstPicParms->stTSM.stStatic.uiNumElements = sNumElementsLUT[ePullDown]; |
|---|
| 1051 | |
|---|
| 1052 | /* SWDEPRECATED-1003: effectively force FrameX1 when predicting the PTS of the next picture. */ |
|---|
| 1053 | if ( true == bTreatAsSingleElement ) |
|---|
| 1054 | { |
|---|
| 1055 | pstPicParms->stTSM.stStatic.uiNumElements = 1; |
|---|
| 1056 | } |
|---|
| 1057 | |
|---|
| 1058 | /* Determine the polarity of each element based on pulldown */ |
|---|
| 1059 | ePolarity = sInitialPolarityLUT[hXdmPP->stDMConfig.bReverseFields][ePullDown]; |
|---|
| 1060 | for( i=0; i < pstPicParms->stTSM.stStatic.uiNumElements; i++ ) |
|---|
| 1061 | { |
|---|
| 1062 | BXDM_PPQM_P_SetElementPolarity( pstPicture, i, ePolarity ); |
|---|
| 1063 | |
|---|
| 1064 | if (ePolarity == BAVC_Polarity_eTopField) |
|---|
| 1065 | { |
|---|
| 1066 | ePolarity = BAVC_Polarity_eBotField; |
|---|
| 1067 | } |
|---|
| 1068 | else if (ePolarity == BAVC_Polarity_eBotField) |
|---|
| 1069 | { |
|---|
| 1070 | ePolarity = BAVC_Polarity_eTopField; |
|---|
| 1071 | } |
|---|
| 1072 | } |
|---|
| 1073 | |
|---|
| 1074 | /* Determine the picture type based on pulldown */ |
|---|
| 1075 | ePictureType = sPictureTypeLUT[ePullDown]; |
|---|
| 1076 | |
|---|
| 1077 | |
|---|
| 1078 | /* Reporting for progressive bits */ |
|---|
| 1079 | if (sProgressiveFrameLUT[ePullDown]) |
|---|
| 1080 | { |
|---|
| 1081 | pstPicParms->uiStateBits |= BXDM_PPDBG_State_ProgressiveFramePulldown; |
|---|
| 1082 | } |
|---|
| 1083 | |
|---|
| 1084 | if (sProgressiveStreamLUT[ePullDown]) |
|---|
| 1085 | { |
|---|
| 1086 | pstPicParms->uiStateBits |= BXDM_PPDBG_State_ProgressiveStreamPulldown; |
|---|
| 1087 | } |
|---|
| 1088 | |
|---|
| 1089 | if ( BXDM_Picture_SourceFormat_eProgressive == pstPicture->pstUnifiedPicture->stBufferInfo.eSourceFormat ) |
|---|
| 1090 | { |
|---|
| 1091 | pstPicParms->uiStateBits |= BXDM_PPDBG_State_ProgressiveSourceFormat; |
|---|
| 1092 | } |
|---|
| 1093 | |
|---|
| 1094 | if ( BXDM_Picture_Sequence_eProgressive == pstPicture->pstUnifiedPicture->stPictureType.eSequence ) |
|---|
| 1095 | { |
|---|
| 1096 | pstPicParms->uiStateBits |= BXDM_PPDBG_State_ProgressiveSequence; |
|---|
| 1097 | } |
|---|
| 1098 | |
|---|
| 1099 | /* Calculate the thresholds */ |
|---|
| 1100 | pstPicParms->stTSM.stStatic.uiVeryEarlyThreshold = hXdmPP->stDMConfig.stTSMThresholdSettings.uiTooEarlyThreshold; |
|---|
| 1101 | pstPicParms->stTSM.stStatic.uiVeryLateThreshold = hXdmPP->stDMConfig.stTSMThresholdSettings.uiTooLateThreshold; |
|---|
| 1102 | pstPicParms->stTSM.stStatic.uiPtsVsyncDiffThreshold = hXdmPP->stDMConfig.stTSMThresholdSettings.uiDeltaStcPtsDiffThreshold; |
|---|
| 1103 | |
|---|
| 1104 | if (pLocalState->eClockRate == BXDM_PictureProvider_P_ClockRate_eDirecTV) |
|---|
| 1105 | { |
|---|
| 1106 | /* DirectTV uses a 27Mhz clock (vs MPEG2's 45Khz) so we need to |
|---|
| 1107 | * scale the thresholds accordingly */ |
|---|
| 1108 | pstPicParms->stTSM.stStatic.uiVeryEarlyThreshold *= 600; |
|---|
| 1109 | pstPicParms->stTSM.stStatic.uiVeryLateThreshold *= 600; |
|---|
| 1110 | } |
|---|
| 1111 | |
|---|
| 1112 | /* Determine the the delta PTS based on the clock rate, picture type, and frame rate */ |
|---|
| 1113 | pstPicParms->stTSM.stStatic.stPTSDelta = sDeltaPtsLUT[pLocalState->eClockRate][ePictureType][pstPicParms->stTSM.stStatic.eFrameRateXVD]; |
|---|
| 1114 | |
|---|
| 1115 | /* SW7405-5231: only use whole values when in CRC mode. |
|---|
| 1116 | * There was an occasional dropped picture during the CRC testing for AVD. These sometimes |
|---|
| 1117 | * occurred when the Delivery Queue under flowed and then two pictures were delivered on a |
|---|
| 1118 | * subsequent vsync. Due to the handling of the fractional component of the virtual PTS |
|---|
| 1119 | * and STC, both pictures would pass the TSM test. As a result, the first picture would |
|---|
| 1120 | * be dropped. This problem goes away when whole numbers are used. In CRC mode, the |
|---|
| 1121 | * delta PTS is used to interpolate the virtual STC. The goal is to scan out a new picture |
|---|
| 1122 | * element on every vsync, the source and display rates don't really matter. We probably |
|---|
| 1123 | * could just use '1' for the delta PTS for all content. |
|---|
| 1124 | */ |
|---|
| 1125 | if ( true == hXdmPP->stDMConfig.bCRCMode ) |
|---|
| 1126 | { |
|---|
| 1127 | pstPicParms->stTSM.stStatic.stPTSDelta = sCRCDeltaPtsLUT[ePictureType][pstPicParms->stTSM.stStatic.eFrameRateXVD]; |
|---|
| 1128 | } |
|---|
| 1129 | |
|---|
| 1130 | |
|---|
| 1131 | /* SWDEPRECATED-1003: effectively force FrameX1 when predicting the PTS of the next picture. */ |
|---|
| 1132 | if ( true == bTreatAsSingleElement ) |
|---|
| 1133 | { |
|---|
| 1134 | pstPicParms->stTSM.stStatic.stPTSDelta = sDeltaPtsLUT[pLocalState->eClockRate][BXDM_PictureProvider_P_PictureType_eProgressive][pstPicParms->stTSM.stStatic.eFrameRateXVD]; |
|---|
| 1135 | } |
|---|
| 1136 | |
|---|
| 1137 | /* SW3548-2418: PTS Jitter Correction Logic |
|---|
| 1138 | * |
|---|
| 1139 | * The following cases are disabled for now: |
|---|
| 1140 | * TODO: Handle sparse PTS |
|---|
| 1141 | * TODO: Handle DirectTV clock timebase |
|---|
| 1142 | * |
|---|
| 1143 | */ |
|---|
| 1144 | /* FIXME: This condition does NOT effectively test for coded PTS every picture, it only |
|---|
| 1145 | tests for coded PTS for *THIS* picture. Ideally, it should compensate for missing pictures |
|---|
| 1146 | by counting them, and adjusting dPTS accordingly */ |
|---|
| 1147 | if ( ( true == pstPicture->pstUnifiedPicture->stPTS.bValid ) /* Coded PTS every picture */ |
|---|
| 1148 | && ( BAVC_FrameRateCode_eUnknown != eFrameRateFRD ) /* Frame rate is unknown */ |
|---|
| 1149 | ) |
|---|
| 1150 | { |
|---|
| 1151 | uint32_t uiJitterCorrectedValue; |
|---|
| 1152 | |
|---|
| 1153 | BXDM_PPJRC_P_AddValue( |
|---|
| 1154 | hXdmPP->stDMState.stChannel.hJrc, |
|---|
| 1155 | pstPicture->pstUnifiedPicture->stPTS.uiValue, |
|---|
| 1156 | &pstPicParms->stTSM.stStatic.stPTSDelta, |
|---|
| 1157 | pstPicParms->stTSM.stStatic.uiNumElements, |
|---|
| 1158 | &uiJitterCorrectedValue |
|---|
| 1159 | ); |
|---|
| 1160 | |
|---|
| 1161 | pstPicParms->stTSM.stStatic.iPTSJitterCorrection = uiJitterCorrectedValue - pstPicture->pstUnifiedPicture->stPTS.uiValue; |
|---|
| 1162 | } |
|---|
| 1163 | else |
|---|
| 1164 | { |
|---|
| 1165 | BXDM_PPJRC_P_Reset(hXdmPP->stDMState.stChannel.hJrc); |
|---|
| 1166 | } |
|---|
| 1167 | |
|---|
| 1168 | #if 0 |
|---|
| 1169 | BKNI_Printf("[eClockRate = %d, ePictureType = %d, eFrameRate = %d] --> deltaPTS=(%d, %d)\n", |
|---|
| 1170 | pLocalState->eClockRate, ePictureType, pstPicParms->stTSM.stStatic.eFrameRateXVD;, |
|---|
| 1171 | pstPicParms->stTSM.stStatic.stPTSDelta.uiWhole, |
|---|
| 1172 | pstPicParms->stTSM.stStatic.stPTSDelta.uiFractional); |
|---|
| 1173 | #endif |
|---|
| 1174 | |
|---|
| 1175 | BDBG_LEAVE(BXDM_PPTSM_P_PtsCalculateParameters); |
|---|
| 1176 | |
|---|
| 1177 | return; |
|---|
| 1178 | } /* end of BXDM_PPTSM_P_PtsCalculateParameters() */ |
|---|
| 1179 | |
|---|
| 1180 | |
|---|
| 1181 | void BXDM_PPTSM_P_PtsInterpolate( |
|---|
| 1182 | BXDM_PictureProvider_Handle hXdmPP, |
|---|
| 1183 | BXDM_PictureProvider_P_LocalState* pLocalState, |
|---|
| 1184 | BXDM_PictureProvider_P_Picture_Context* pstPicture, |
|---|
| 1185 | BXDM_PictureProvider_P_Picture_Context* pstPrevPicture |
|---|
| 1186 | ) |
|---|
| 1187 | { |
|---|
| 1188 | BXDM_PPFP_P_DataType stPTSTemp; |
|---|
| 1189 | BXDM_PPFP_P_DataType stPTSOfNextPPB; |
|---|
| 1190 | uint32_t i; |
|---|
| 1191 | |
|---|
| 1192 | BXDM_PictureProvider_PTSType eTempPtsType; |
|---|
| 1193 | |
|---|
| 1194 | BDBG_ENTER(BXDM_PPTSM_P_PtsInterpolate); |
|---|
| 1195 | |
|---|
| 1196 | BSTD_UNUSED( hXdmPP ); |
|---|
| 1197 | BSTD_UNUSED( pLocalState ); |
|---|
| 1198 | |
|---|
| 1199 | /* If the PPB contains a coded PTS, use that one. |
|---|
| 1200 | * Else grab one from the previous PPB. |
|---|
| 1201 | */ |
|---|
| 1202 | |
|---|
| 1203 | if ( true == pstPicture->pstUnifiedPicture->stPTS.bValid ) |
|---|
| 1204 | { |
|---|
| 1205 | stPTSTemp.uiWhole = pstPicture->pstUnifiedPicture->stPTS.uiValue; |
|---|
| 1206 | stPTSTemp.uiFractional = 0; |
|---|
| 1207 | |
|---|
| 1208 | pstPicture->stPicParms.stTSM.stStatic.ePtsType = BXDM_PictureProvider_PTSType_eCoded; |
|---|
| 1209 | } |
|---|
| 1210 | else |
|---|
| 1211 | { |
|---|
| 1212 | BXDM_PPQM_P_GetPredictedPtsWithFrac( pstPrevPicture, BXDM_PictureProvider_P_PTSIndex_eActual, &stPTSTemp ); |
|---|
| 1213 | |
|---|
| 1214 | BXDM_PPQM_P_GetPtsType( pstPrevPicture, &eTempPtsType ); |
|---|
| 1215 | |
|---|
| 1216 | if ( BXDM_PictureProvider_PTSType_eCoded == eTempPtsType |
|---|
| 1217 | || BXDM_PictureProvider_PTSType_eInterpolatedFromValidPTS == eTempPtsType |
|---|
| 1218 | ) |
|---|
| 1219 | { |
|---|
| 1220 | pstPicture->stPicParms.stTSM.stStatic.ePtsType = BXDM_PictureProvider_PTSType_eInterpolatedFromValidPTS; |
|---|
| 1221 | } |
|---|
| 1222 | else |
|---|
| 1223 | { |
|---|
| 1224 | pstPicture->stPicParms.stTSM.stStatic.ePtsType = BXDM_PictureProvider_PTSType_eInterpolatedFromInvalidPTS; |
|---|
| 1225 | } |
|---|
| 1226 | |
|---|
| 1227 | } |
|---|
| 1228 | |
|---|
| 1229 | /* TODO: add a debug statement here */ |
|---|
| 1230 | if ( BXDM_PictureProvider_P_MAX_ELEMENTS_PER_PPB <= pstPicture->stPicParms.stTSM.stStatic.uiNumElements ) |
|---|
| 1231 | { |
|---|
| 1232 | pstPicture->stPicParms.stTSM.stStatic.uiNumElements = BXDM_PictureProvider_P_MAX_ELEMENTS_PER_PPB; |
|---|
| 1233 | } |
|---|
| 1234 | |
|---|
| 1235 | /* Now calculate the PTS value for each element associated with this PPB. |
|---|
| 1236 | * In addition, the predicted PTS for the next PPB will be generated. |
|---|
| 1237 | * TODO: add a check that we haven't gone off the end of the array |
|---|
| 1238 | * or clamp it elsewhere? |
|---|
| 1239 | */ |
|---|
| 1240 | stPTSOfNextPPB = stPTSTemp; |
|---|
| 1241 | |
|---|
| 1242 | for( i=0; i < pstPicture->stPicParms.stTSM.stStatic.uiNumElements; i++ ) |
|---|
| 1243 | { |
|---|
| 1244 | BXDM_PPQM_P_SetPtsWithFrac( pstPicture, BXDM_PictureProvider_P_PTSIndex_eActual, i, stPTSTemp ); |
|---|
| 1245 | |
|---|
| 1246 | BXDM_PPFP_P_FixPtAdd( |
|---|
| 1247 | &stPTSTemp, |
|---|
| 1248 | &(pstPicture->stPicParms.stTSM.stStatic.stPTSDelta), |
|---|
| 1249 | &stPTSTemp |
|---|
| 1250 | ); |
|---|
| 1251 | |
|---|
| 1252 | BXDM_PPFP_P_FixPtAdd( |
|---|
| 1253 | &stPTSOfNextPPB, |
|---|
| 1254 | &(pstPicture->stPicParms.stTSM.stStatic.stPTSDelta), |
|---|
| 1255 | &stPTSOfNextPPB |
|---|
| 1256 | ); |
|---|
| 1257 | } |
|---|
| 1258 | |
|---|
| 1259 | BXDM_PPQM_P_SetPredictedPtsWithFrac( pstPicture, BXDM_PictureProvider_P_PTSIndex_eActual, stPTSOfNextPPB ); |
|---|
| 1260 | |
|---|
| 1261 | BDBG_LEAVE(BXDM_PPTSM_P_PtsInterpolate); |
|---|
| 1262 | |
|---|
| 1263 | return; |
|---|
| 1264 | |
|---|
| 1265 | } /* BXDM_PPTSM_P_PtsInterpolate() */ |
|---|
| 1266 | |
|---|
| 1267 | void BXDM_PPTSM_S_ActualTSMResultHandler( |
|---|
| 1268 | BXDM_PictureProvider_Handle hXdmPP, |
|---|
| 1269 | BXDM_PictureProvider_P_LocalState* pLocalState, |
|---|
| 1270 | BXDM_PictureProvider_P_Picture_Context* pstPicture |
|---|
| 1271 | ) |
|---|
| 1272 | { |
|---|
| 1273 | if ( BXDM_PictureProvider_DisplayMode_eTSM == hXdmPP->stDMConfig.eDisplayMode ) |
|---|
| 1274 | { |
|---|
| 1275 | if ( true == hXdmPP->stDMConfig.bPlayback |
|---|
| 1276 | && false == hXdmPP->stDMConfig.bSTCValid |
|---|
| 1277 | ) |
|---|
| 1278 | { |
|---|
| 1279 | /* PR50235: If we're: |
|---|
| 1280 | * 1) playing back from disk AND |
|---|
| 1281 | * 2) in TSM mode AND |
|---|
| 1282 | * 3) are evaluating the actual PTS AND |
|---|
| 1283 | * 4) STC is invalid AND |
|---|
| 1284 | * Then we may want to override the TSM result |
|---|
| 1285 | */ |
|---|
| 1286 | switch (pstPicture->stPicParms.stTSM.stDynamic.eTsmResult) |
|---|
| 1287 | { |
|---|
| 1288 | case BXDM_PictureProvider_TSMResult_eDrop: |
|---|
| 1289 | /* We never want to override a drop state */ |
|---|
| 1290 | break; |
|---|
| 1291 | |
|---|
| 1292 | case BXDM_PictureProvider_TSMResult_ePass: |
|---|
| 1293 | if ( true == hXdmPP->stDMState.stDecode.bAutoValidateStc ) |
|---|
| 1294 | { |
|---|
| 1295 | /* In this case, even though the STC is reported to be |
|---|
| 1296 | * invalid, the STC seems OK, so we auto-validate the STC |
|---|
| 1297 | * and use the actual TSM result */ |
|---|
| 1298 | BXDM_PictureProvider_SetSTCValid_isr( |
|---|
| 1299 | hXdmPP, |
|---|
| 1300 | true |
|---|
| 1301 | ); |
|---|
| 1302 | break; |
|---|
| 1303 | } |
|---|
| 1304 | default: |
|---|
| 1305 | /* All other states we want to override to wait until the |
|---|
| 1306 | * app sets the STC valid */ |
|---|
| 1307 | pstPicture->stPicParms.stTSM.stDynamic.eTsmResult = BXDM_PictureProvider_TSMResult_eWait; |
|---|
| 1308 | } |
|---|
| 1309 | } |
|---|
| 1310 | |
|---|
| 1311 | /* PR50235: We turn off auto validation of the STC if it is already |
|---|
| 1312 | * valid */ |
|---|
| 1313 | if ( true == hXdmPP->stDMConfig.bSTCValid ) |
|---|
| 1314 | { |
|---|
| 1315 | hXdmPP->stDMState.stDecode.bAutoValidateStc = false; |
|---|
| 1316 | } |
|---|
| 1317 | |
|---|
| 1318 | /* SW7425-1721: Execute the TSM result callback prior to determining any additional picture |
|---|
| 1319 | * or system state. Previously this callback was being executed after the FIC evaluation, |
|---|
| 1320 | * this made it impossible to get field accurate transitions with the TSM result callback. |
|---|
| 1321 | */ |
|---|
| 1322 | if ( false == pstPicture->stPicParms.stDisplay.stDynamic.bPPBRepeated ) |
|---|
| 1323 | { |
|---|
| 1324 | /* Execute the TSM Result callback. */ |
|---|
| 1325 | BXDM_PPCB_P_ExecuteSingleCallback( hXdmPP, pLocalState, BXDM_PictureProvider_Callback_eTSMResult ); |
|---|
| 1326 | |
|---|
| 1327 | /* Set picture selection mode/TSM result based on picture |
|---|
| 1328 | * handling mode and TSM Result */ |
|---|
| 1329 | switch ( pstPicture->stPicParms.stTSM.stDynamic.ePictureHandlingMode ) |
|---|
| 1330 | { |
|---|
| 1331 | case BXDM_PictureProvider_PictureHandlingMode_eHonorPTS: |
|---|
| 1332 | pstPicture->stPicParms.stTSM.stDynamic.eSelectionMode = BXDM_PictureProvider_DisplayMode_eTSM; |
|---|
| 1333 | break; |
|---|
| 1334 | |
|---|
| 1335 | case BXDM_PictureProvider_PictureHandlingMode_eIgnorePTS: |
|---|
| 1336 | pstPicture->stPicParms.stTSM.stDynamic.eSelectionMode = BXDM_PictureProvider_DisplayMode_eVirtualTSM; |
|---|
| 1337 | break; |
|---|
| 1338 | |
|---|
| 1339 | default: |
|---|
| 1340 | break; |
|---|
| 1341 | } |
|---|
| 1342 | |
|---|
| 1343 | } |
|---|
| 1344 | |
|---|
| 1345 | if ( BXDM_PictureProvider_DisplayMode_eTSM == pstPicture->stPicParms.stTSM.stDynamic.eSelectionMode ) |
|---|
| 1346 | { |
|---|
| 1347 | pstPicture->stPicParms.stDisplay.stDynamic.uiSelectedElement = pstPicture->stPicParms.stTSM.stDynamic.uiTSMSelectedElement; |
|---|
| 1348 | |
|---|
| 1349 | BXDM_PPQM_P_GetElementPolarity( |
|---|
| 1350 | pstPicture, |
|---|
| 1351 | pstPicture->stPicParms.stDisplay.stDynamic.uiSelectedElement, |
|---|
| 1352 | &pstPicture->stPicParms.stDisplay.stDynamic.eSourcePolarity); |
|---|
| 1353 | |
|---|
| 1354 | /* Perform FIC adjustment */ |
|---|
| 1355 | BXDM_PPFIC_P_CalculateFieldInversionCorrectionOffset( |
|---|
| 1356 | hXdmPP, |
|---|
| 1357 | pLocalState, |
|---|
| 1358 | pstPicture); |
|---|
| 1359 | } |
|---|
| 1360 | |
|---|
| 1361 | if ( BXDM_PictureProvider_TSMResult_ePass == pstPicture->stPicParms.stTSM.stDynamic.eTsmResult ) |
|---|
| 1362 | { |
|---|
| 1363 | /* Now that a picture has passed the TSM check, unconditionally stop prerolling. */ |
|---|
| 1364 | hXdmPP->stDMState.stDecode.bPreRolling = false; |
|---|
| 1365 | } |
|---|
| 1366 | } |
|---|
| 1367 | else |
|---|
| 1368 | { |
|---|
| 1369 | /* Conditionally generate the ASTM TSM pass callback. */ |
|---|
| 1370 | if ( ( true == hXdmPP->stDMConfig.bAstmMode ) |
|---|
| 1371 | && ( BXDM_PictureProvider_TSMResult_ePass == pstPicture->stPicParms.stTSM.stDynamic.eTsmResult ) |
|---|
| 1372 | ) |
|---|
| 1373 | { |
|---|
| 1374 | pLocalState->bASTMModeTSMPass = true; |
|---|
| 1375 | } |
|---|
| 1376 | } |
|---|
| 1377 | |
|---|
| 1378 | if ( BXDM_PictureProvider_DisplayMode_eTSM == hXdmPP->stDMConfig.eDisplayMode ) |
|---|
| 1379 | { |
|---|
| 1380 | if ( BXDM_PictureProvider_DisplayMode_eTSM == pstPicture->stPicParms.stTSM.stDynamic.eSelectionMode ) |
|---|
| 1381 | { |
|---|
| 1382 | BXDM_PPCLIP_P_ClipTimeTSMTransitionHandler( |
|---|
| 1383 | hXdmPP, |
|---|
| 1384 | pLocalState, |
|---|
| 1385 | pstPicture, |
|---|
| 1386 | &pstPicture->stPicParms.stTSM.stDynamic.eTsmResult); |
|---|
| 1387 | } |
|---|
| 1388 | |
|---|
| 1389 | if ( false == pstPicture->stPicParms.stDisplay.stDynamic.bPPBRepeated ) |
|---|
| 1390 | { |
|---|
| 1391 | /* We only generate callbacks if this is the first time we're |
|---|
| 1392 | * evaluating the picture. We don't want to generate callbacks if |
|---|
| 1393 | * we're redisplaying a picture. E.g. if we're in a time bases |
|---|
| 1394 | * slideshow, the current picture may eventually be late, but we |
|---|
| 1395 | * shouldn't generate an error at that point. |
|---|
| 1396 | * |
|---|
| 1397 | * SW7425-1721: eTooLate/eTooEarly are only considered a PTS error if "ePictureHandlingMode" |
|---|
| 1398 | * is the default. If "ePictureHandlingMode" has been set to a different value, the assumption |
|---|
| 1399 | * is that the application has evaluated the PTS and determined the disposition of the picture. |
|---|
| 1400 | * The PTSError callback is redundant in this case. In addition, executing the callback might |
|---|
| 1401 | * confuse matters. |
|---|
| 1402 | * |
|---|
| 1403 | * Similarly for bTSMPass (BXDM_PictureProvider_Callback_eFirstPTSPassed/BXVD_Interrupt_eFirstPTSPassed) |
|---|
| 1404 | * the assumption is that when the application is using the TSM result callback, it has intimate knowledge |
|---|
| 1405 | * of the system state is does not require the callback. |
|---|
| 1406 | */ |
|---|
| 1407 | pLocalState->bPtsError = false; |
|---|
| 1408 | |
|---|
| 1409 | if ( BXDM_PictureProvider_PictureHandlingMode_eDefault == pstPicture->stPicParms.stTSM.stDynamic.ePictureHandlingMode |
|---|
| 1410 | && BXDM_PictureProvider_DisplayMode_eTSM == pstPicture->stPicParms.stTSM.stDynamic.eSelectionMode |
|---|
| 1411 | ) |
|---|
| 1412 | { |
|---|
| 1413 | if ( ( BXDM_PictureProvider_TSMResult_eTooLate == pstPicture->stPicParms.stTSM.stDynamic.eTsmResult ) |
|---|
| 1414 | || ( BXDM_PictureProvider_TSMResult_eTooEarly == pstPicture->stPicParms.stTSM.stDynamic.eTsmResult ) |
|---|
| 1415 | ) |
|---|
| 1416 | { |
|---|
| 1417 | pLocalState->bPtsError = true; |
|---|
| 1418 | |
|---|
| 1419 | /* Get PTS for element */ |
|---|
| 1420 | BXDM_PPQM_P_GetPts( |
|---|
| 1421 | pstPicture, |
|---|
| 1422 | BXDM_PictureProvider_P_PTSIndex_eActual, |
|---|
| 1423 | 0, |
|---|
| 1424 | &hXdmPP->stDMState.stDecode.stErrorPts.ui32RunningPTS); |
|---|
| 1425 | |
|---|
| 1426 | BXDM_PPQM_P_GetPtsType( |
|---|
| 1427 | pstPicture, |
|---|
| 1428 | &hXdmPP->stDMState.stDecode.stErrorPts.ePTSType); |
|---|
| 1429 | |
|---|
| 1430 | hXdmPP->stDMState.stDecode.stErrorPts.ui32EffectivePTS = pstPicture->stPicParms.stTSM.stDynamic.uiEffectivePTS[BXDM_PictureProvider_P_PTSIndex_eActual]; |
|---|
| 1431 | } |
|---|
| 1432 | |
|---|
| 1433 | /* |
|---|
| 1434 | * Conditionally generate the TSM pass callback. |
|---|
| 1435 | */ |
|---|
| 1436 | if ( BXDM_PictureProvider_TSMResult_ePass == pstPicture->stPicParms.stTSM.stDynamic.eTsmResult ) |
|---|
| 1437 | { |
|---|
| 1438 | pLocalState->bTSMPass = true; |
|---|
| 1439 | } |
|---|
| 1440 | } |
|---|
| 1441 | |
|---|
| 1442 | /* PR52424: If we're in playback, and we see a picture that is |
|---|
| 1443 | * TooLate, we want to display the first TooLate picture in vTSM |
|---|
| 1444 | * mode but still generate the PTSError to give the app a chance |
|---|
| 1445 | * to recover */ |
|---|
| 1446 | if ( ( true == hXdmPP->stDMConfig.bPlayback ) |
|---|
| 1447 | && ( BXDM_PictureProvider_DisplayMode_eTSM == pstPicture->stPicParms.stTSM.stDynamic.eSelectionMode ) ) |
|---|
| 1448 | { |
|---|
| 1449 | if ( BXDM_PictureProvider_TSMResult_eTooLate == pstPicture->stPicParms.stTSM.stDynamic.eTsmResult ) |
|---|
| 1450 | { |
|---|
| 1451 | if ( ( BXDM_PictureProvider_PictureHandlingMode_eDefault == pstPicture->stPicParms.stTSM.stDynamic.ePictureHandlingMode ) |
|---|
| 1452 | && ( false == hXdmPP->stDMState.stDecode.bTooLateGimmeDone ) |
|---|
| 1453 | ) |
|---|
| 1454 | { |
|---|
| 1455 | /* SW7425-1074: The mulligan logic should use "eWait" to give the middleware/application |
|---|
| 1456 | * a chance to reseed the STC. Previously "ePictureHandlingMode" was set to "eIgnorePTS". |
|---|
| 1457 | * This resulted in the picture selection mode being changed to "vsync". |
|---|
| 1458 | * If the STC is reseeded on this vsync, the virtual STC will also be loaded with the new value. |
|---|
| 1459 | * However the virtual PTS of this picture is based on the preceding picture. Depending on how |
|---|
| 1460 | * far back in time the STC (and virtual STC) is set, it could take a long time for this |
|---|
| 1461 | * picture to mature. Better to push up the decision to switch to vsync mode rather |
|---|
| 1462 | * then forcing it here. |
|---|
| 1463 | */ |
|---|
| 1464 | pstPicture->stPicParms.stTSM.stDynamic.eTsmResult = BXDM_PictureProvider_TSMResult_eWait; |
|---|
| 1465 | hXdmPP->stDMState.stDecode.bTooLateGimmeDone = true; |
|---|
| 1466 | } |
|---|
| 1467 | } |
|---|
| 1468 | else |
|---|
| 1469 | { |
|---|
| 1470 | hXdmPP->stDMState.stDecode.bTooLateGimmeDone = false; |
|---|
| 1471 | } |
|---|
| 1472 | } |
|---|
| 1473 | |
|---|
| 1474 | } |
|---|
| 1475 | } |
|---|
| 1476 | } |
|---|
| 1477 | |
|---|
| 1478 | void BXDM_PPTSM_S_FinalTSMResultHandler( |
|---|
| 1479 | BXDM_PictureProvider_Handle hXdmPP, |
|---|
| 1480 | BXDM_PictureProvider_P_LocalState* pLocalState, |
|---|
| 1481 | BXDM_PictureProvider_P_Picture_Context* pstPicture |
|---|
| 1482 | ) |
|---|
| 1483 | { |
|---|
| 1484 | bool bDecodeErrorDrop = false; |
|---|
| 1485 | |
|---|
| 1486 | if ( BXDM_PictureProvider_DisplayMode_eVirtualTSM == pstPicture->stPicParms.stTSM.stDynamic.eSelectionMode ) |
|---|
| 1487 | { |
|---|
| 1488 | pstPicture->stPicParms.stDisplay.stDynamic.uiSelectedElement = pstPicture->stPicParms.stTSM.stDynamic.uiTSMSelectedElement; |
|---|
| 1489 | |
|---|
| 1490 | BXDM_PPQM_P_GetElementPolarity( |
|---|
| 1491 | pstPicture, |
|---|
| 1492 | pstPicture->stPicParms.stDisplay.stDynamic.uiSelectedElement, |
|---|
| 1493 | &pstPicture->stPicParms.stDisplay.stDynamic.eSourcePolarity); |
|---|
| 1494 | |
|---|
| 1495 | /* Perform FIC adjustment */ |
|---|
| 1496 | BXDM_PPFIC_P_CalculateFieldInversionCorrectionOffset( |
|---|
| 1497 | hXdmPP, |
|---|
| 1498 | pLocalState, |
|---|
| 1499 | pstPicture); |
|---|
| 1500 | } |
|---|
| 1501 | |
|---|
| 1502 | /* PR56051: the failure occurred while pictures were being dropped for error |
|---|
| 1503 | * conditions AND the delivery queue ran dry. On the next vsync, the |
|---|
| 1504 | * TSM logic would re-evaluate the current picture. This re-evaluation was |
|---|
| 1505 | * causing the Display Manager to prematurely exit the error dropping state. |
|---|
| 1506 | * The fix is to qualify "hXdmPP->stDMConfig.eErrorHandlingMode" |
|---|
| 1507 | * with "true == bFirstEvaluation" |
|---|
| 1508 | */ |
|---|
| 1509 | if ( BXDM_PictureProvider_ErrorHandlingMode_ePicture == hXdmPP->stDMConfig.eErrorHandlingMode |
|---|
| 1510 | && false == pstPicture->stPicParms.stDisplay.stDynamic.bPPBRepeated |
|---|
| 1511 | ) |
|---|
| 1512 | { |
|---|
| 1513 | if ( true == pstPicture->pstUnifiedPicture->stError.bThisPicture ) |
|---|
| 1514 | { |
|---|
| 1515 | bDecodeErrorDrop = true; |
|---|
| 1516 | } |
|---|
| 1517 | } |
|---|
| 1518 | else if ( BXDM_PictureProvider_ErrorHandlingMode_ePrognostic == hXdmPP->stDMConfig.eErrorHandlingMode |
|---|
| 1519 | && false == pstPicture->stPicParms.stDisplay.stDynamic.bPPBRepeated ) |
|---|
| 1520 | { |
|---|
| 1521 | /* Exit "drop until next RAP" mode if, |
|---|
| 1522 | * - the picture does NOT contain a decode error |
|---|
| 1523 | * - the picture IS a RAP |
|---|
| 1524 | * - and "bDropUntilNextRAP" is true |
|---|
| 1525 | * (this is redundant, but might be useful for debugging) |
|---|
| 1526 | */ |
|---|
| 1527 | if ( false == pstPicture->pstUnifiedPicture->stError.bThisPicture |
|---|
| 1528 | && true == pstPicture->pstUnifiedPicture->stPictureType.bRandomAccessPoint |
|---|
| 1529 | && true == hXdmPP->stDMState.stDecode.bDropUntilNextRAP |
|---|
| 1530 | ) |
|---|
| 1531 | { |
|---|
| 1532 | hXdmPP->stDMState.stDecode.bDropUntilNextRAP = false; |
|---|
| 1533 | } |
|---|
| 1534 | |
|---|
| 1535 | /* |
|---|
| 1536 | * Drop the picture? |
|---|
| 1537 | */ |
|---|
| 1538 | if ( true == pstPicture->pstUnifiedPicture->stError.bThisPicture |
|---|
| 1539 | || true == pstPicture->pstUnifiedPicture->stError.bPreviousRefPic |
|---|
| 1540 | ) |
|---|
| 1541 | { |
|---|
| 1542 | bDecodeErrorDrop = true; |
|---|
| 1543 | } |
|---|
| 1544 | else if ( true == hXdmPP->stDMState.stDecode.bDropUntilNextRAP ) |
|---|
| 1545 | { |
|---|
| 1546 | /* When in "bDropUntilNextRAP" mode, don't |
|---|
| 1547 | * drop error free I pictures. |
|---|
| 1548 | */ |
|---|
| 1549 | if ( BXDM_Picture_Coding_eI != pstPicture->pstUnifiedPicture->stPictureType.eCoding ) |
|---|
| 1550 | { |
|---|
| 1551 | bDecodeErrorDrop = true; |
|---|
| 1552 | } |
|---|
| 1553 | } |
|---|
| 1554 | |
|---|
| 1555 | /* Enter "drop until next RAP" mode if, |
|---|
| 1556 | * - the picture contains a decode error |
|---|
| 1557 | * - and it is a reference picture. |
|---|
| 1558 | */ |
|---|
| 1559 | if ( ( true == pstPicture->pstUnifiedPicture->stError.bThisPicture ) |
|---|
| 1560 | && ( pstPicture->pstUnifiedPicture->stPictureType.bReference ) ) |
|---|
| 1561 | { |
|---|
| 1562 | hXdmPP->stDMState.stDecode.bDropUntilNextRAP = true; |
|---|
| 1563 | } |
|---|
| 1564 | |
|---|
| 1565 | } |
|---|
| 1566 | |
|---|
| 1567 | /* Override the TSM result if the decode error flag is set */ |
|---|
| 1568 | if ( true == bDecodeErrorDrop ) |
|---|
| 1569 | { |
|---|
| 1570 | pstPicture->stPicParms.stTSM.stDynamic.eTsmResult = BXDM_PictureProvider_TSMResult_eDrop; |
|---|
| 1571 | |
|---|
| 1572 | /* bump "uiDecodeErrorDropCount" if, |
|---|
| 1573 | * - evaluating the real PTS (not the virtual) |
|---|
| 1574 | * - a new picture (TODO: is this needed?) |
|---|
| 1575 | */ |
|---|
| 1576 | if ( false == pstPicture->stPicParms.stDisplay.stDynamic.bPPBRepeated ) |
|---|
| 1577 | { |
|---|
| 1578 | hXdmPP->stDMState.stDecode.uiDecodeErrorDropCount++; |
|---|
| 1579 | } |
|---|
| 1580 | } |
|---|
| 1581 | |
|---|
| 1582 | if ( BXDM_PictureProvider_DisplayMode_eVirtualTSM == pstPicture->stPicParms.stTSM.stDynamic.eSelectionMode ) |
|---|
| 1583 | { |
|---|
| 1584 | BXDM_PPCLIP_P_ClipTimeTSMTransitionHandler( |
|---|
| 1585 | hXdmPP, |
|---|
| 1586 | pLocalState, |
|---|
| 1587 | pstPicture, |
|---|
| 1588 | &pstPicture->stPicParms.stTSM.stDynamic.eTsmResult); |
|---|
| 1589 | } |
|---|
| 1590 | |
|---|
| 1591 | /* PR52247: In the case of picture-less clips (i.e. only contains a |
|---|
| 1592 | * single dummy PPB), we won't have a valid picture displayed, so |
|---|
| 1593 | * we need to ensure the clip callback trigger handler is still |
|---|
| 1594 | * executed */ |
|---|
| 1595 | BXDM_PPCLIP_P_ClipTimeCallbackTriggerHandler( hXdmPP, pLocalState, pstPicture ); |
|---|
| 1596 | |
|---|
| 1597 | if ( BXDM_PictureProvider_PictureHandlingMode_eDrop == pstPicture->stPicParms.stTSM.stDynamic.ePictureHandlingMode ) |
|---|
| 1598 | { |
|---|
| 1599 | pstPicture->stPicParms.stTSM.stDynamic.eTsmResult = BXDM_PictureProvider_TSMResult_eDrop; |
|---|
| 1600 | } |
|---|
| 1601 | else if ( BXDM_PictureProvider_PictureHandlingMode_eWait == pstPicture->stPicParms.stTSM.stDynamic.ePictureHandlingMode |
|---|
| 1602 | && BXDM_PictureProvider_DisplayMode_eTSM == pstPicture->stPicParms.stTSM.stDynamic.eSelectionMode ) |
|---|
| 1603 | { |
|---|
| 1604 | /* SW7635-51: give the middleware/application the option to hold off processing a picture. |
|---|
| 1605 | * The TSMResult callback is only executed when eSelectionMode is eTSM. There is the potential |
|---|
| 1606 | * for a deadlock if ePictureHandlingMode is set to eWait on one vsync and then eSelectionMode changes |
|---|
| 1607 | * to eVirtual on the next vsync. This change could happen if the system were put into vsync mode, |
|---|
| 1608 | * a decoder trick mode began or there was a PCR discontinuity. To avoid this, only override the TSM |
|---|
| 1609 | * result if eSelectionMode is eTSM. |
|---|
| 1610 | */ |
|---|
| 1611 | pstPicture->stPicParms.stTSM.stDynamic.eTsmResult = BXDM_PictureProvider_TSMResult_eWait; |
|---|
| 1612 | } |
|---|
| 1613 | |
|---|
| 1614 | } |
|---|
| 1615 | |
|---|
| 1616 | void BXDM_PPTSM_P_EvaluateTsmState( |
|---|
| 1617 | BXDM_PictureProvider_Handle hXdmPP, |
|---|
| 1618 | BXDM_PictureProvider_P_LocalState* pLocalState, |
|---|
| 1619 | BXDM_PictureProvider_P_Picture_Context* pstPicture |
|---|
| 1620 | ) |
|---|
| 1621 | { |
|---|
| 1622 | BDBG_ENTER(BXDM_PPTSM_P_EvaluateTsmState); |
|---|
| 1623 | |
|---|
| 1624 | BXDM_PPTMR_P_SnapshotFunctionStartTime( hXdmPP, BXDM_PPTIMER_P_Function_eEvaluateTsmState ); |
|---|
| 1625 | |
|---|
| 1626 | /* SW7405-5549: if the monitor refresh rate changed after a picture was validated |
|---|
| 1627 | * (in BXDM_PPQM_S_ValidatePictureContext) call BXDM_PPTSM_S_ApplyCDTOverride again to |
|---|
| 1628 | * ensure that the picture is scanned out properly. This can occur if the refresh rate |
|---|
| 1629 | * is changed while the system is paused. |
|---|
| 1630 | */ |
|---|
| 1631 | if ( false == hXdmPP->stDMConfig.bCRCMode |
|---|
| 1632 | && true == pstPicture->bValidated |
|---|
| 1633 | && pstPicture->stPicParms.stDisplay.stStatic.eMonitorRefreshRate != hXdmPP->stDMConfig.eMonitorRefreshRate |
|---|
| 1634 | ) |
|---|
| 1635 | { |
|---|
| 1636 | BXDM_Picture_PullDown ePullDown = pstPicture->stPicParms.stTSM.stStatic.ePullDownRangeChecked; |
|---|
| 1637 | |
|---|
| 1638 | BXDM_PPTSM_S_ApplyCDTOverride( hXdmPP, pLocalState, pstPicture, &ePullDown ); |
|---|
| 1639 | } |
|---|
| 1640 | |
|---|
| 1641 | |
|---|
| 1642 | /* Handle removal delay */ |
|---|
| 1643 | if ( 0 != hXdmPP->stDMState.stDecode.uiRemovalDelay ) |
|---|
| 1644 | { |
|---|
| 1645 | if ( false == pstPicture->stPicParms.stDisplay.stDynamic.bPPBRepeated ) |
|---|
| 1646 | { |
|---|
| 1647 | BXDM_PPDBG_P_SelectionLog( hXdmPP, BXDM_PPDBG_Selection_eDelay ); |
|---|
| 1648 | pstPicture->stPicParms.stTSM.stDynamic.eTsmResult = BXDM_PictureProvider_TSMResult_eWait; |
|---|
| 1649 | |
|---|
| 1650 | hXdmPP->stDMState.stDecode.uiRemovalDelay--; |
|---|
| 1651 | } |
|---|
| 1652 | return; |
|---|
| 1653 | } |
|---|
| 1654 | |
|---|
| 1655 | /* Remember this pictures last dStcPts */ |
|---|
| 1656 | pstPicture->stPicParms.stTSM.stDynamic.iStcPtsDifferenceDisplayed = pstPicture->stPicParms.stTSM.stDynamic.iStcPtsDifferenceEvaluated; |
|---|
| 1657 | |
|---|
| 1658 | /* |
|---|
| 1659 | * Always perform the TSM evaluation for the real STC and PTS. |
|---|
| 1660 | */ |
|---|
| 1661 | BXDM_PPTSM_S_CompareStcAndPts( hXdmPP, pLocalState, pstPicture, true ); |
|---|
| 1662 | |
|---|
| 1663 | BXDM_PPTSM_S_ActualTSMResultHandler( hXdmPP, pLocalState, pstPicture ); |
|---|
| 1664 | |
|---|
| 1665 | /* |
|---|
| 1666 | * Conditionally perform the TSM evaluation for the "virtual" STC and PTS. |
|---|
| 1667 | */ |
|---|
| 1668 | if ( BXDM_PictureProvider_DisplayMode_eVirtualTSM == pstPicture->stPicParms.stTSM.stDynamic.eSelectionMode ) |
|---|
| 1669 | { |
|---|
| 1670 | BXDM_PPTSM_S_CompareStcAndPts( hXdmPP, pLocalState, pstPicture, false ); |
|---|
| 1671 | } |
|---|
| 1672 | |
|---|
| 1673 | BXDM_PPTSM_S_FinalTSMResultHandler( hXdmPP, pLocalState, pstPicture ); |
|---|
| 1674 | |
|---|
| 1675 | BXDM_PPTMR_P_SnapshotFunctionEndTime( hXdmPP, BXDM_PPTIMER_P_Function_eEvaluateTsmState ); |
|---|
| 1676 | |
|---|
| 1677 | BDBG_LEAVE(BXDM_PPTSM_P_EvaluateTsmState); |
|---|
| 1678 | |
|---|
| 1679 | return; |
|---|
| 1680 | } /* BXDM_PPTSM_P_EvaluateTsmState() */ |
|---|
| 1681 | |
|---|
| 1682 | static BXDM_PictureProvider_TSMResult BXDM_PPTSM_S_CompareStcAndPts( |
|---|
| 1683 | BXDM_PictureProvider_Handle hXdmPP, |
|---|
| 1684 | BXDM_PictureProvider_P_LocalState* pLocalState, |
|---|
| 1685 | BXDM_PictureProvider_P_Picture_Context* pstPicture, |
|---|
| 1686 | bool bEvaluateActualPts |
|---|
| 1687 | ) |
|---|
| 1688 | { |
|---|
| 1689 | uint32_t uiEffectiveStc; |
|---|
| 1690 | BXDM_PPFP_P_DataType stPts[BXDM_PictureProvider_P_MAX_ELEMENTS_PER_PPB]; |
|---|
| 1691 | int32_t iStcPtsDifferenceActual[BXDM_PictureProvider_P_MAX_ELEMENTS_PER_PPB]; |
|---|
| 1692 | int32_t iStcPtsDifferenceEvaluated[BXDM_PictureProvider_P_MAX_ELEMENTS_PER_PPB]; |
|---|
| 1693 | int32_t iStcPtsDifferenceEvaluatedDeltaAbs[BXDM_PictureProvider_P_MAX_ELEMENTS_PER_PPB]; |
|---|
| 1694 | BXDM_PictureProvider_P_PTSIndex ePTSIndex; |
|---|
| 1695 | uint32_t i; |
|---|
| 1696 | BXDM_PictureProvider_PTSType ePtsType = BXDM_PictureProvider_PTSType_eInterpolatedFromValidPTS; |
|---|
| 1697 | bool bStcIsRunningInReverse=false; |
|---|
| 1698 | |
|---|
| 1699 | BDBG_ENTER(BXDM_PPTSM_S_CompareStcAndPts); |
|---|
| 1700 | |
|---|
| 1701 | BDBG_ASSERT( pstPicture ); |
|---|
| 1702 | |
|---|
| 1703 | /* If the context for this picture has not been validated, simply return from this routine. |
|---|
| 1704 | * Currently the only way to get in this state is; |
|---|
| 1705 | * - the stream loops when playbacking from disk |
|---|
| 1706 | * - AND this routine is called to redisplay the currently selected picture |
|---|
| 1707 | * |
|---|
| 1708 | * The preceding prevents spurious PTSError callbacks |
|---|
| 1709 | * |
|---|
| 1710 | * In addition if in live mode, don't perform TSM evaluation until the first valid PCR |
|---|
| 1711 | * offset has been received. Prior to that, the TSM results will be random. |
|---|
| 1712 | * However, if the picture selection mode is "vsync", do perform the TSM evaluation |
|---|
| 1713 | * using the virtual STC and PTS values. ( PR53423 ) |
|---|
| 1714 | */ |
|---|
| 1715 | if ( false == pstPicture->bValidated |
|---|
| 1716 | || ( false == hXdmPP->stDMState.stDecode.bValidPcrOffsetReceived |
|---|
| 1717 | && true == bEvaluateActualPts |
|---|
| 1718 | ) |
|---|
| 1719 | ) |
|---|
| 1720 | { |
|---|
| 1721 | pstPicture->stPicParms.stTSM.stDynamic.eTsmResult = BXDM_PictureProvider_TSMResult_eDrop; |
|---|
| 1722 | goto AllDone; |
|---|
| 1723 | } |
|---|
| 1724 | else |
|---|
| 1725 | { |
|---|
| 1726 | pstPicture->stPicParms.stTSM.stDynamic.eTsmResult = BXDM_PictureProvider_TSMResult_ePass; |
|---|
| 1727 | } |
|---|
| 1728 | |
|---|
| 1729 | if ( true == bEvaluateActualPts ) |
|---|
| 1730 | { |
|---|
| 1731 | uint32_t uiPCROffset; |
|---|
| 1732 | |
|---|
| 1733 | /* TSM Mode */ |
|---|
| 1734 | ePTSIndex = BXDM_PictureProvider_P_PTSIndex_eActual; |
|---|
| 1735 | |
|---|
| 1736 | /* |
|---|
| 1737 | * Calculate the effective STC, i.e. add the PCR offset to the STC |
|---|
| 1738 | */ |
|---|
| 1739 | BXDM_PPQM_P_GetCookedPcrOffset( hXdmPP, pstPicture, &uiPCROffset ); |
|---|
| 1740 | |
|---|
| 1741 | uiEffectiveStc = pLocalState->uiAdjustedStc + uiPCROffset; |
|---|
| 1742 | |
|---|
| 1743 | BXDM_PPQM_P_GetPtsType( pstPicture, &ePtsType ); |
|---|
| 1744 | } |
|---|
| 1745 | else |
|---|
| 1746 | { |
|---|
| 1747 | /* VSYNC Mode */ |
|---|
| 1748 | ePTSIndex = BXDM_PictureProvider_P_PTSIndex_eVirtual; |
|---|
| 1749 | |
|---|
| 1750 | BXDM_PPVTSM_P_VirtualStcGet( hXdmPP, &uiEffectiveStc ); |
|---|
| 1751 | } |
|---|
| 1752 | |
|---|
| 1753 | /* SW7425-2536: save the effective STC. Currently only returned as |
|---|
| 1754 | * status in the "drop at decode" callbacks. |
|---|
| 1755 | */ |
|---|
| 1756 | pstPicture->stPicParms.stTSM.stDynamic.uiEffectiveStc[ePTSIndex] = uiEffectiveStc; |
|---|
| 1757 | |
|---|
| 1758 | if ( true == bEvaluateActualPts ) |
|---|
| 1759 | { |
|---|
| 1760 | /* We need to see if the decoder supports drop@decode */ |
|---|
| 1761 | if ( ( NULL != hXdmPP->stDMConfig.stDecoderInterface.requestPictureDrop_isr ) |
|---|
| 1762 | && ( NULL != hXdmPP->stDMConfig.stDecoderInterface.getPictureDropPendingCount_isr ) |
|---|
| 1763 | ) |
|---|
| 1764 | { |
|---|
| 1765 | /* Snapshot the start time. */ |
|---|
| 1766 | BXDM_PPTMR_P_SnapshotFunctionStartTime( hXdmPP, BXDM_PPTIMER_P_Function_eDecoderGetPictureDropPendingCountIsr ); |
|---|
| 1767 | |
|---|
| 1768 | hXdmPP->stDMConfig.stDecoderInterface.getPictureDropPendingCount_isr( |
|---|
| 1769 | hXdmPP->stDMConfig.pDecoderPrivateContext, |
|---|
| 1770 | &hXdmPP->stDMState.stDecode.uiPendingDropCount |
|---|
| 1771 | ); |
|---|
| 1772 | |
|---|
| 1773 | /* Snapshot the end time. */ |
|---|
| 1774 | BXDM_PPTMR_P_SnapshotFunctionEndTime( hXdmPP, BXDM_PPTIMER_P_Function_eDecoderGetPictureDropPendingCountIsr ); |
|---|
| 1775 | |
|---|
| 1776 | if ( 0 != hXdmPP->stDMState.stDecode.uiPendingDropCount ) |
|---|
| 1777 | { |
|---|
| 1778 | /* SW7335-781: Output warning when forcing picture selection override */ |
|---|
| 1779 | BXDM_PPDBG_P_PrintSelectionModeOverride("Drop@Decode", hXdmPP, pstPicture); |
|---|
| 1780 | /* SW7405-3929: If there is a pending drop@decode, then override selection mode to vTSM mode for this picture */ |
|---|
| 1781 | pstPicture->stPicParms.stTSM.stDynamic.eSelectionMode = BXDM_PictureProvider_DisplayMode_eVirtualTSM; |
|---|
| 1782 | } |
|---|
| 1783 | } |
|---|
| 1784 | } |
|---|
| 1785 | |
|---|
| 1786 | #if 0 |
|---|
| 1787 | BKNI_Printf("[%3x - %3x]\n", |
|---|
| 1788 | hXdmPP->stChBufferConfig.pAVD_PI2DMS_Buffer->drop_count, |
|---|
| 1789 | pstPicture->stPicParms.uiDroppedCount |
|---|
| 1790 | ); |
|---|
| 1791 | #endif |
|---|
| 1792 | |
|---|
| 1793 | /* For this picture, find the element with smallest STC/PTS |
|---|
| 1794 | * diff that has matured (i.e. the smallest positive value) |
|---|
| 1795 | */ |
|---|
| 1796 | for (i = 0; i < pstPicture->stPicParms.stTSM.stStatic.uiNumElements; i++) |
|---|
| 1797 | { |
|---|
| 1798 | uint32_t uiPtsOffset; |
|---|
| 1799 | |
|---|
| 1800 | /* Get PTS for element */ |
|---|
| 1801 | BXDM_PPQM_P_GetPtsWithFrac( pstPicture, ePTSIndex, i, &stPts[i] ); |
|---|
| 1802 | |
|---|
| 1803 | /* SW7425-2255: once a picture has been selected for display, use the |
|---|
| 1804 | * offset bound to the picture. |
|---|
| 1805 | */ |
|---|
| 1806 | BXDM_PPQM_P_GetPtsOffset( hXdmPP, pstPicture, &uiPtsOffset ); |
|---|
| 1807 | |
|---|
| 1808 | /* Add PTSOffset for lip sync when */ |
|---|
| 1809 | stPts[i].uiWhole += uiPtsOffset; |
|---|
| 1810 | |
|---|
| 1811 | /* Add the JRC jitter offset, but only when evaluating the ACTUAL PTS values, |
|---|
| 1812 | * since the virtual PTS values are already de-jittered */ |
|---|
| 1813 | if ( BXDM_PictureProvider_P_PTSIndex_eActual == ePTSIndex ) |
|---|
| 1814 | { |
|---|
| 1815 | stPts[i].uiWhole += pstPicture->stPicParms.stTSM.stStatic.iPTSJitterCorrection; |
|---|
| 1816 | } |
|---|
| 1817 | |
|---|
| 1818 | /* Save the actual PTS/STC diff BEFORE we do apply the FICPTSOffset . |
|---|
| 1819 | * SW7425-1264: if the STC is running in reverse, subtract the STC from the PTS. |
|---|
| 1820 | */ |
|---|
| 1821 | bStcIsRunningInReverse = ( BXDM_PictureProvider_P_STCTrickMode_eSlowRewind == pLocalState->eSTCTrickMode ); |
|---|
| 1822 | bStcIsRunningInReverse |= ( BXDM_PictureProvider_P_STCTrickMode_eFastRewind == pLocalState->eSTCTrickMode ); |
|---|
| 1823 | |
|---|
| 1824 | if ( true == bStcIsRunningInReverse ) |
|---|
| 1825 | { |
|---|
| 1826 | iStcPtsDifferenceActual[i] = stPts[i].uiWhole - uiEffectiveStc; |
|---|
| 1827 | } |
|---|
| 1828 | else |
|---|
| 1829 | { |
|---|
| 1830 | iStcPtsDifferenceActual[i] = uiEffectiveStc - stPts[i].uiWhole; |
|---|
| 1831 | } |
|---|
| 1832 | |
|---|
| 1833 | /* Add PTSOffset for Frame Rate Conversion */ |
|---|
| 1834 | BXDM_PPFP_P_FixPtAdd( |
|---|
| 1835 | &stPts[i], |
|---|
| 1836 | &hXdmPP->stDMState.stDecode.stFieldInversionCorrectionPTSOffset, |
|---|
| 1837 | &stPts[i]); |
|---|
| 1838 | |
|---|
| 1839 | /* SWBLURAY-18249: round the PTS value up instead of truncating. |
|---|
| 1840 | * The need for this was highlighted when playing a seamless clip. |
|---|
| 1841 | * The clip stop time was the expected first PTS of the next clip. |
|---|
| 1842 | * Since it was a seamless clip, the first picture was processed in |
|---|
| 1843 | * vsync mode, i.e. the virtual PTS was used. When the vPTS was truncated, |
|---|
| 1844 | * the picture was passing one tick too soon and the clip stop time |
|---|
| 1845 | * was not reached. |
|---|
| 1846 | */ |
|---|
| 1847 | if ( 0 != stPts[i].uiFractional |
|---|
| 1848 | && false == bStcIsRunningInReverse ) |
|---|
| 1849 | { |
|---|
| 1850 | stPts[i].uiWhole++; |
|---|
| 1851 | stPts[i].uiFractional = 0; |
|---|
| 1852 | } |
|---|
| 1853 | |
|---|
| 1854 | /* SW7425-1264: if the STC is running in reverse, subtract the STC from the PTS. */ |
|---|
| 1855 | if ( true == bStcIsRunningInReverse ) |
|---|
| 1856 | { |
|---|
| 1857 | iStcPtsDifferenceEvaluated[i] = stPts[i].uiWhole - uiEffectiveStc; |
|---|
| 1858 | } |
|---|
| 1859 | else |
|---|
| 1860 | { |
|---|
| 1861 | iStcPtsDifferenceEvaluated[i] = uiEffectiveStc - stPts[i].uiWhole; |
|---|
| 1862 | } |
|---|
| 1863 | |
|---|
| 1864 | |
|---|
| 1865 | iStcPtsDifferenceEvaluatedDeltaAbs[i] = hXdmPP->stDMState.stDecode.iPreviousStcPtsDifferenceEvaluated - iStcPtsDifferenceEvaluated[i]; |
|---|
| 1866 | |
|---|
| 1867 | #if 0 |
|---|
| 1868 | if (((BXDM_PictureProvider_DisplayMode_eTSM == pstPicture->stPicParms.stTSM.stDynamic.eSelectionMode) && bEvaluateActualPts) || |
|---|
| 1869 | ((BXDM_PictureProvider_DisplayMode_eVirtualTSM == pstPicture->stPicParms.stTSM.stDynamic.eSelectionMode) && !bEvaluateActualPts)) |
|---|
| 1870 | { |
|---|
| 1871 | |
|---|
| 1872 | BKNI_Printf("%x: [%d] stc: %lu - pts: %lu = %ld\n", |
|---|
| 1873 | hXdmPP->stDMState.stDecode.stDebug.uiVsyncCount, |
|---|
| 1874 | i, |
|---|
| 1875 | uiEffectiveStc, |
|---|
| 1876 | stPts[i].uiWhole, |
|---|
| 1877 | iStcPtsDifferenceEvaluated[i]); |
|---|
| 1878 | |
|---|
| 1879 | BKNI_Printf("%x: [%d] %ld - %ld = %ld\n", |
|---|
| 1880 | hXdmPP->stDMState.stDecode.stDebug.uiVsyncCount, |
|---|
| 1881 | i, |
|---|
| 1882 | hXdmPP->stDMState.stDecode.iPreviousStcPtsDifferenceEvaluated, |
|---|
| 1883 | iStcPtsDifferenceEvaluated[i], |
|---|
| 1884 | iStcPtsDifferenceEvaluatedDeltaAbs[i] |
|---|
| 1885 | ); |
|---|
| 1886 | } |
|---|
| 1887 | #endif |
|---|
| 1888 | |
|---|
| 1889 | if ( iStcPtsDifferenceEvaluatedDeltaAbs[i] < 0 ) |
|---|
| 1890 | { |
|---|
| 1891 | iStcPtsDifferenceEvaluatedDeltaAbs[i] = -iStcPtsDifferenceEvaluatedDeltaAbs[i]; |
|---|
| 1892 | } |
|---|
| 1893 | } |
|---|
| 1894 | |
|---|
| 1895 | /* Find the best element within the picture */ |
|---|
| 1896 | /* We need to decide which element to start with. |
|---|
| 1897 | * If the picture has already been displayed, then we start with the last displayed element. |
|---|
| 1898 | * However, if it has not been displayed, then we start from the beginning. |
|---|
| 1899 | * |
|---|
| 1900 | * We need to make this distinction because even though the previous TSM result may have been ePass/eLate, |
|---|
| 1901 | * it may have been overridden to eWait. This is likely in playback when the STC hasn't been validated, yet, |
|---|
| 1902 | * and a non-ePass TSM result is always overridden to eWait. So, we always want to start from |
|---|
| 1903 | * the first element of the PPB. |
|---|
| 1904 | */ |
|---|
| 1905 | if ( false == pstPicture->stPicParms.stDisplay.stDynamic.bPPBRepeated ) |
|---|
| 1906 | { |
|---|
| 1907 | pstPicture->stPicParms.stDisplay.stDynamic.uiSelectedElement = 0; |
|---|
| 1908 | } |
|---|
| 1909 | |
|---|
| 1910 | pstPicture->stPicParms.stTSM.stDynamic.uiTSMSelectedElement = pstPicture->stPicParms.stDisplay.stDynamic.uiSelectedElement; |
|---|
| 1911 | for (i = pstPicture->stPicParms.stDisplay.stDynamic.uiSelectedElement; i < pstPicture->stPicParms.stTSM.stStatic.uiNumElements; i++) |
|---|
| 1912 | { |
|---|
| 1913 | /* Never select an element with a negative actual STC/PTS diff */ |
|---|
| 1914 | if (iStcPtsDifferenceActual[i] < 0) |
|---|
| 1915 | { |
|---|
| 1916 | break; |
|---|
| 1917 | } |
|---|
| 1918 | |
|---|
| 1919 | /* PR47453: We pick the element to minimize the |
|---|
| 1920 | * |deltaPtsStcOffset| between vsyncs to account for any STC/PTS |
|---|
| 1921 | * jitter that we may have */ |
|---|
| 1922 | |
|---|
| 1923 | /* PR51148: With the original jitter correction logic, it was |
|---|
| 1924 | * possible to lock to large dStcPts diff values after trick |
|---|
| 1925 | * modes. E.g. the upper dStcPts diff wasn't bounded, so after |
|---|
| 1926 | * a trick mode, the jitter correction logic would try to |
|---|
| 1927 | * maintain an possibly larger dStcPts. The goal of the jitter |
|---|
| 1928 | * correction TSM is to pick the best picture that results in an |
|---|
| 1929 | * effective dStcPts of between [-jitter, dPTS] with the most |
|---|
| 1930 | * stable dStcPts. The picture selection logic has been updated |
|---|
| 1931 | * as follows: |
|---|
| 1932 | * |
|---|
| 1933 | * 1) A picture's evaluated dStcPts must be greater than |
|---|
| 1934 | * -(jitter threshold) -- this is the lower bound |
|---|
| 1935 | * |
|---|
| 1936 | * 2) If the picture's evaluated dStcPts is greater than dPTS, |
|---|
| 1937 | * always select the picture for display. -- this is the |
|---|
| 1938 | * upper bound |
|---|
| 1939 | * |
|---|
| 1940 | * 3) if the picture evaluated dStcPts is less than one picture |
|---|
| 1941 | * time, then we pick the picture that results in the |
|---|
| 1942 | * smallest change in the dStcPts. -- this is the jitter |
|---|
| 1943 | * correction portion |
|---|
| 1944 | * |
|---|
| 1945 | */ |
|---|
| 1946 | if ( ( iStcPtsDifferenceEvaluated[i] >= 0 ) |
|---|
| 1947 | && ( ( pLocalState->iStcPtsDifferenceEvaluatedBest[ePTSIndex] >= (int32_t) pstPicture->stPicParms.stTSM.stStatic.stPTSDelta.uiWhole ) |
|---|
| 1948 | || ( pLocalState->iStcPtsDifferenceEvaluatedDeltaAbsMin[ePTSIndex] + 1 >= iStcPtsDifferenceEvaluatedDeltaAbs[i] ) |
|---|
| 1949 | || ( iStcPtsDifferenceEvaluated[i] > (int32_t) pstPicture->stPicParms.stTSM.stStatic.uiVeryLateThreshold ) |
|---|
| 1950 | |
|---|
| 1951 | /* SW7550-349: When in STC pause, we don't want jitter correction because it can cause |
|---|
| 1952 | * issues with STC frame advance preventing the next picture from getting selected. |
|---|
| 1953 | */ |
|---|
| 1954 | || ( ( true == bEvaluateActualPts ) |
|---|
| 1955 | && ( BXDM_PictureProvider_P_STCTrickMode_ePause == pLocalState->eSTCTrickMode ) ) |
|---|
| 1956 | ) |
|---|
| 1957 | ) |
|---|
| 1958 | { |
|---|
| 1959 | /* Save the smallest jitter compensated StcPtsDifference for |
|---|
| 1960 | * this vsync */ |
|---|
| 1961 | pLocalState->iStcPtsDifferenceEvaluatedDeltaAbsMin[ePTSIndex] = iStcPtsDifferenceEvaluatedDeltaAbs[i]; |
|---|
| 1962 | pLocalState->iStcPtsDifferenceEvaluatedBest[ePTSIndex] = iStcPtsDifferenceEvaluated[i]; |
|---|
| 1963 | pstPicture->stPicParms.stTSM.stDynamic.uiTSMSelectedElement = i; |
|---|
| 1964 | } |
|---|
| 1965 | } |
|---|
| 1966 | |
|---|
| 1967 | pstPicture->stPicParms.stTSM.stDynamic.uiEffectivePTS[ePTSIndex] = stPts[pstPicture->stPicParms.stTSM.stDynamic.uiTSMSelectedElement].uiWhole; |
|---|
| 1968 | pstPicture->stPicParms.stTSM.stDynamic.iStcPtsDifferenceEvaluated = iStcPtsDifferenceEvaluated[pstPicture->stPicParms.stTSM.stDynamic.uiTSMSelectedElement]; |
|---|
| 1969 | pstPicture->stPicParms.stTSM.stDynamic.iStcPtsDifferenceActual = iStcPtsDifferenceActual[pstPicture->stPicParms.stTSM.stDynamic.uiTSMSelectedElement]; |
|---|
| 1970 | pstPicture->stPicParms.stTSM.stDynamic.iStcPtsDifferenceEvaluatedDeltaAbs = iStcPtsDifferenceEvaluatedDeltaAbs[pstPicture->stPicParms.stTSM.stDynamic.uiTSMSelectedElement]; |
|---|
| 1971 | |
|---|
| 1972 | /* |
|---|
| 1973 | * Now that the necessary values have been calculated, perform the TSM evaluation. |
|---|
| 1974 | */ |
|---|
| 1975 | if ( ( BXDM_PictureProvider_PTSType_eInterpolatedFromInvalidPTS == ePtsType ) |
|---|
| 1976 | && ( true == pstPicture->pstUnifiedPicture->stBufferInfo.bValid ) |
|---|
| 1977 | ) |
|---|
| 1978 | |
|---|
| 1979 | { |
|---|
| 1980 | /* We have an invalid PTS, we don't know when to display the |
|---|
| 1981 | * picture, so we just drop it */ |
|---|
| 1982 | |
|---|
| 1983 | pstPicture->stPicParms.stTSM.stDynamic.eTsmResult = BXDM_PictureProvider_TSMResult_eDrop; |
|---|
| 1984 | } |
|---|
| 1985 | else if ( true == BXDM_PPCLIP_P_ClipTimeTSMHandler( |
|---|
| 1986 | hXdmPP, |
|---|
| 1987 | pLocalState, |
|---|
| 1988 | pstPicture, |
|---|
| 1989 | bEvaluateActualPts, |
|---|
| 1990 | &pstPicture->stPicParms.stTSM.stDynamic.eTsmResult |
|---|
| 1991 | )) |
|---|
| 1992 | { |
|---|
| 1993 | /* Done */ |
|---|
| 1994 | } |
|---|
| 1995 | |
|---|
| 1996 | /* handle too late case */ |
|---|
| 1997 | else if ( pstPicture->stPicParms.stTSM.stDynamic.iStcPtsDifferenceEvaluated > (int32_t)pstPicture->stPicParms.stTSM.stStatic.uiVeryLateThreshold ) |
|---|
| 1998 | { |
|---|
| 1999 | pstPicture->stPicParms.stTSM.stDynamic.eTsmResult = BXDM_PictureProvider_TSMResult_eTooLate; |
|---|
| 2000 | } |
|---|
| 2001 | /* handle too early case */ |
|---|
| 2002 | else if ( -pstPicture->stPicParms.stTSM.stDynamic.iStcPtsDifferenceEvaluated > (int32_t)pstPicture->stPicParms.stTSM.stStatic.uiVeryEarlyThreshold ) |
|---|
| 2003 | { |
|---|
| 2004 | pstPicture->stPicParms.stTSM.stDynamic.eTsmResult = BXDM_PictureProvider_TSMResult_eTooEarly; |
|---|
| 2005 | } |
|---|
| 2006 | /* PR47453: We only want to pass an element if it produces the |
|---|
| 2007 | * smallest |deltaPtsStcOffset| of all elements selected so far */ |
|---|
| 2008 | else if ( ( pstPicture->stPicParms.stTSM.stDynamic.iStcPtsDifferenceActual >= 0 ) |
|---|
| 2009 | && ( pstPicture->stPicParms.stTSM.stDynamic.iStcPtsDifferenceEvaluatedDeltaAbs == pLocalState->iStcPtsDifferenceEvaluatedDeltaAbsMin[ePTSIndex] ) |
|---|
| 2010 | && ( pstPicture->stPicParms.stTSM.stDynamic.iStcPtsDifferenceEvaluated == pLocalState->iStcPtsDifferenceEvaluatedBest[ePTSIndex] ) ) |
|---|
| 2011 | { |
|---|
| 2012 | /* |
|---|
| 2013 | * The picture has matured |
|---|
| 2014 | */ |
|---|
| 2015 | pstPicture->stPicParms.stTSM.stDynamic.eTsmResult = BXDM_PictureProvider_TSMResult_ePass; |
|---|
| 2016 | } |
|---|
| 2017 | else |
|---|
| 2018 | { |
|---|
| 2019 | /* |
|---|
| 2020 | * The picture is early. |
|---|
| 2021 | */ |
|---|
| 2022 | pstPicture->stPicParms.stTSM.stDynamic.eTsmResult = BXDM_PictureProvider_TSMResult_eWait; |
|---|
| 2023 | } |
|---|
| 2024 | |
|---|
| 2025 | if (((BXDM_PictureProvider_DisplayMode_eTSM == pstPicture->stPicParms.stTSM.stDynamic.eSelectionMode) && bEvaluateActualPts) || |
|---|
| 2026 | ((BXDM_PictureProvider_DisplayMode_eVirtualTSM == pstPicture->stPicParms.stTSM.stDynamic.eSelectionMode) && !bEvaluateActualPts)) |
|---|
| 2027 | { |
|---|
| 2028 | char cTsmResult; |
|---|
| 2029 | |
|---|
| 2030 | switch ( pstPicture->stPicParms.stTSM.stDynamic.eTsmResult ) |
|---|
| 2031 | { |
|---|
| 2032 | case 0: cTsmResult = 'e'; break; |
|---|
| 2033 | case 1: cTsmResult = 'w'; break; |
|---|
| 2034 | case 2: cTsmResult = 'p'; break; |
|---|
| 2035 | case 3: cTsmResult = 'l'; break; |
|---|
| 2036 | case 4: cTsmResult = 'd'; break; |
|---|
| 2037 | default: cTsmResult = 'u'; break; |
|---|
| 2038 | } |
|---|
| 2039 | |
|---|
| 2040 | if ( true == bStcIsRunningInReverse ) |
|---|
| 2041 | { |
|---|
| 2042 | BXVD_DBG_MSG(hXdmPP,("%x:[%01x.%03x] %c:%c pts:%08x - stc:%08x =%8ld slt:%c elm:%d %s", |
|---|
| 2043 | hXdmPP->stDMState.stDecode.stDebug.uiVsyncCount, |
|---|
| 2044 | hXdmPP->stDMConfig.uiInstanceID & 0xF, |
|---|
| 2045 | pstPicture->stPicParms.uiPPBIndex & 0xFFF, |
|---|
| 2046 | ( BXDM_PictureProvider_DisplayMode_eTSM == pstPicture->stPicParms.stTSM.stDynamic.eSelectionMode ) ? 't' : 'v', |
|---|
| 2047 | cTsmResult, |
|---|
| 2048 | pstPicture->stPicParms.stTSM.stDynamic.uiEffectivePTS[ePTSIndex], |
|---|
| 2049 | uiEffectiveStc, |
|---|
| 2050 | pstPicture->stPicParms.stTSM.stDynamic.iStcPtsDifferenceEvaluated, |
|---|
| 2051 | hXdmPP->stDMState.stDecode.stFieldInversionCorrectionPTSOffset.uiWhole ? '2' : '1', |
|---|
| 2052 | pstPicture->stPicParms.stTSM.stDynamic.uiTSMSelectedElement, |
|---|
| 2053 | ( pstPicture->stPicParms.stDisplay.stDynamic.bPPBRepeated ) ? "rp" : " " |
|---|
| 2054 | )); |
|---|
| 2055 | } |
|---|
| 2056 | else |
|---|
| 2057 | { |
|---|
| 2058 | BXVD_DBG_MSG(hXdmPP,("%x:[%01x.%03x] %c:%c stc:%08x - pts:%08x =%8ld slt:%c elm:%d %s", |
|---|
| 2059 | hXdmPP->stDMState.stDecode.stDebug.uiVsyncCount, |
|---|
| 2060 | hXdmPP->stDMConfig.uiInstanceID & 0xF, |
|---|
| 2061 | pstPicture->stPicParms.uiPPBIndex & 0xFFF, |
|---|
| 2062 | ( BXDM_PictureProvider_DisplayMode_eTSM == pstPicture->stPicParms.stTSM.stDynamic.eSelectionMode ) ? 't' : 'v', |
|---|
| 2063 | cTsmResult, |
|---|
| 2064 | uiEffectiveStc, |
|---|
| 2065 | pstPicture->stPicParms.stTSM.stDynamic.uiEffectivePTS[ePTSIndex], |
|---|
| 2066 | pstPicture->stPicParms.stTSM.stDynamic.iStcPtsDifferenceEvaluated, |
|---|
| 2067 | hXdmPP->stDMState.stDecode.stFieldInversionCorrectionPTSOffset.uiWhole ? '2' : '1', |
|---|
| 2068 | pstPicture->stPicParms.stTSM.stDynamic.uiTSMSelectedElement, |
|---|
| 2069 | ( pstPicture->stPicParms.stDisplay.stDynamic.bPPBRepeated ) ? "rp" : " " |
|---|
| 2070 | )); |
|---|
| 2071 | } |
|---|
| 2072 | } |
|---|
| 2073 | |
|---|
| 2074 | /* SW7425-1264: track which STC was selected, currently only used for debug. |
|---|
| 2075 | */ |
|---|
| 2076 | if ( true == hXdmPP->stDMConfig.stClockOverride.bEnableClockOverride ) |
|---|
| 2077 | { |
|---|
| 2078 | pstPicture->stPicParms.stTSM.stDynamic.bEvaluatedWithSwStc = true; |
|---|
| 2079 | } |
|---|
| 2080 | else |
|---|
| 2081 | { |
|---|
| 2082 | pstPicture->stPicParms.stTSM.stDynamic.bEvaluatedWithSwStc = false; |
|---|
| 2083 | } |
|---|
| 2084 | |
|---|
| 2085 | |
|---|
| 2086 | AllDone: |
|---|
| 2087 | BDBG_LEAVE(BXDM_PPTSM_S_CompareStcAndPts); |
|---|
| 2088 | |
|---|
| 2089 | return pstPicture->stPicParms.stTSM.stDynamic.eTsmResult; |
|---|
| 2090 | |
|---|
| 2091 | } /* end of BXDM_PPTSM_S_CompareStcAndPts() */ |
|---|
| 2092 | |
|---|
| 2093 | |
|---|