| 1 | /*************************************************************************** |
|---|
| 2 | * Copyright (c) 2003-2010, 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_frd.c $ |
|---|
| 11 | * $brcm_Revision: Hydra_Software_Devel/1 $ |
|---|
| 12 | * $brcm_Date: 2/16/10 10:51a $ |
|---|
| 13 | * |
|---|
| 14 | * [File Description:] |
|---|
| 15 | * |
|---|
| 16 | * Revision History: |
|---|
| 17 | * |
|---|
| 18 | * $brcm_Log: /magnum/commonutils/xdm/bxdm_pp_frd.c $ |
|---|
| 19 | * |
|---|
| 20 | * Hydra_Software_Devel/1 2/16/10 10:51a nilesh |
|---|
| 21 | * SW7405-2993: Initial XDM version |
|---|
| 22 | * |
|---|
| 23 | ***************************************************************************/ |
|---|
| 24 | |
|---|
| 25 | #include "bstd.h" |
|---|
| 26 | #include "bdbg.h" /* Dbglib */ |
|---|
| 27 | |
|---|
| 28 | #include "bxdm_pp.h" |
|---|
| 29 | #include "bxdm_pp_priv.h" |
|---|
| 30 | #include "bxdm_pp_frd.h" |
|---|
| 31 | |
|---|
| 32 | |
|---|
| 33 | BDBG_MODULE(BXDM_PPFRD); |
|---|
| 34 | |
|---|
| 35 | const char BXDM_PictureProvider_P_DISPMGR_FRD_NODE[]="DMFRD:\t""$brcm_Revision: Hydra_Software_Devel/1 $"; |
|---|
| 36 | |
|---|
| 37 | static void BXDM_PPFRD_S_AddDeltaPTS( |
|---|
| 38 | BXDM_PictureProvider_Handle hXdmPP, |
|---|
| 39 | const BXDM_PPFP_P_DataType *pstDeltaPTS |
|---|
| 40 | ) |
|---|
| 41 | { |
|---|
| 42 | |
|---|
| 43 | if ( hXdmPP->stDMState.stDecode.stFRDStats.uiDeltaPTSCount < BXDM_PPFRD_P_MAX_DELTAPTS_SAMPLES ) |
|---|
| 44 | { |
|---|
| 45 | /* Increment the PTS count */ |
|---|
| 46 | hXdmPP->stDMState.stDecode.stFRDStats.uiDeltaPTSCount++; |
|---|
| 47 | } |
|---|
| 48 | else |
|---|
| 49 | { |
|---|
| 50 | /* Subtract old entry from the running sum */ |
|---|
| 51 | BXDM_PPFP_P_FixPtSub( |
|---|
| 52 | &hXdmPP->stDMState.stDecode.stFRDStats.stDeltaPTSRunningSum, |
|---|
| 53 | &hXdmPP->stDMState.stDecode.stFRDStats.astDeltaPTS[hXdmPP->stDMState.stDecode.stFRDStats.uiDeltaPTSIndex], |
|---|
| 54 | &hXdmPP->stDMState.stDecode.stFRDStats.stDeltaPTSRunningSum |
|---|
| 55 | ); |
|---|
| 56 | } |
|---|
| 57 | |
|---|
| 58 | BXVD_DBG_MSG(hXdmPP, ("BXDM_PPFRD_S_AddDeltaPTS(%d.%d)[%d]", |
|---|
| 59 | pstDeltaPTS->uiWhole, |
|---|
| 60 | pstDeltaPTS->uiFractional, |
|---|
| 61 | hXdmPP->stDMState.stDecode.stFRDStats.uiDeltaPTSCount)); |
|---|
| 62 | |
|---|
| 63 | /* Replace the old entry with the new entry */ |
|---|
| 64 | hXdmPP->stDMState.stDecode.stFRDStats.astDeltaPTS[hXdmPP->stDMState.stDecode.stFRDStats.uiDeltaPTSIndex] = *pstDeltaPTS; |
|---|
| 65 | |
|---|
| 66 | /* Update running sum */ |
|---|
| 67 | BXDM_PPFP_P_FixPtAdd( |
|---|
| 68 | &hXdmPP->stDMState.stDecode.stFRDStats.stDeltaPTSRunningSum, |
|---|
| 69 | &hXdmPP->stDMState.stDecode.stFRDStats.astDeltaPTS[hXdmPP->stDMState.stDecode.stFRDStats.uiDeltaPTSIndex], |
|---|
| 70 | &hXdmPP->stDMState.stDecode.stFRDStats.stDeltaPTSRunningSum); |
|---|
| 71 | |
|---|
| 72 | /* Increment PTS index */ |
|---|
| 73 | hXdmPP->stDMState.stDecode.stFRDStats.uiDeltaPTSIndex++; |
|---|
| 74 | if ( hXdmPP->stDMState.stDecode.stFRDStats.uiDeltaPTSIndex >= BXDM_PPFRD_P_MAX_DELTAPTS_SAMPLES ) |
|---|
| 75 | { |
|---|
| 76 | hXdmPP->stDMState.stDecode.stFRDStats.uiDeltaPTSIndex = 0; |
|---|
| 77 | } |
|---|
| 78 | } |
|---|
| 79 | |
|---|
| 80 | static void BXDM_PPFRD_S_AddNumElements( |
|---|
| 81 | BXDM_PictureProvider_Handle hXdmPP, |
|---|
| 82 | const uint32_t uiNumElements |
|---|
| 83 | ) |
|---|
| 84 | { |
|---|
| 85 | if ( hXdmPP->stDMState.stDecode.stFRDStats.uiNumPicturesCount < BXDM_PPFRD_P_MAX_NUMELEMENTS_SAMPLES ) |
|---|
| 86 | { |
|---|
| 87 | /* Increment the PTS count */ |
|---|
| 88 | hXdmPP->stDMState.stDecode.stFRDStats.uiNumPicturesCount++; |
|---|
| 89 | } |
|---|
| 90 | else |
|---|
| 91 | { |
|---|
| 92 | /* Subtract old entry from the running sum */ |
|---|
| 93 | hXdmPP->stDMState.stDecode.stFRDStats.uiNumElementsRunningSum -= hXdmPP->stDMState.stDecode.stFRDStats.auiNumElements[hXdmPP->stDMState.stDecode.stFRDStats.uiNumElementsIndex]; |
|---|
| 94 | } |
|---|
| 95 | |
|---|
| 96 | BXVD_DBG_MSG(hXdmPP, ("BXDM_PPFRD_S_AddNumElements(%d)[%d]", |
|---|
| 97 | uiNumElements, |
|---|
| 98 | hXdmPP->stDMState.stDecode.stFRDStats.uiNumPicturesCount)); |
|---|
| 99 | |
|---|
| 100 | /* Replace the old entry with the new entry */ |
|---|
| 101 | hXdmPP->stDMState.stDecode.stFRDStats.auiNumElements[hXdmPP->stDMState.stDecode.stFRDStats.uiNumElementsIndex] = uiNumElements; |
|---|
| 102 | |
|---|
| 103 | /* Update running sum */ |
|---|
| 104 | hXdmPP->stDMState.stDecode.stFRDStats.uiNumElementsRunningSum += hXdmPP->stDMState.stDecode.stFRDStats.auiNumElements[hXdmPP->stDMState.stDecode.stFRDStats.uiNumElementsIndex]; |
|---|
| 105 | |
|---|
| 106 | /* Increment PTS index */ |
|---|
| 107 | hXdmPP->stDMState.stDecode.stFRDStats.uiNumElementsIndex++; |
|---|
| 108 | if ( hXdmPP->stDMState.stDecode.stFRDStats.uiNumElementsIndex >= BXDM_PPFRD_P_MAX_NUMELEMENTS_SAMPLES ) |
|---|
| 109 | { |
|---|
| 110 | hXdmPP->stDMState.stDecode.stFRDStats.uiNumElementsIndex = 0; |
|---|
| 111 | } |
|---|
| 112 | } |
|---|
| 113 | |
|---|
| 114 | #define BXDM_PPFRD_P_DISCONTINUITY_DELTA_PTS_THRESHOLD 45000 |
|---|
| 115 | |
|---|
| 116 | BERR_Code BXDM_PPFRD_P_AddPTS( |
|---|
| 117 | BXDM_PictureProvider_Handle hXdmPP, |
|---|
| 118 | uint32_t uiPTS, |
|---|
| 119 | bool bPTSValid, |
|---|
| 120 | uint32_t uiNumElements |
|---|
| 121 | ) |
|---|
| 122 | { |
|---|
| 123 | BXDM_PPFP_P_DataType stDeltaPTS; |
|---|
| 124 | uint32_t i; |
|---|
| 125 | |
|---|
| 126 | BXVD_DBG_MSG(hXdmPP, ("BXDM_PPFRD_P_AddPTS(%d, %d)", |
|---|
| 127 | uiPTS, |
|---|
| 128 | bPTSValid)); |
|---|
| 129 | |
|---|
| 130 | if ( true == bPTSValid ) |
|---|
| 131 | { |
|---|
| 132 | /* We have a valid PTS */ |
|---|
| 133 | if ( true == hXdmPP->stDMState.stDecode.stFRDStats.bLastPTSValid ) |
|---|
| 134 | { |
|---|
| 135 | /* We have another valid PTS, so we can compute and insert |
|---|
| 136 | * the delta PTS value(s) into the dPTS queue */ |
|---|
| 137 | if ( uiPTS > hXdmPP->stDMState.stDecode.stFRDStats.uiLastPTS ) |
|---|
| 138 | { |
|---|
| 139 | stDeltaPTS.uiWhole = uiPTS - hXdmPP->stDMState.stDecode.stFRDStats.uiLastPTS; |
|---|
| 140 | stDeltaPTS.uiFractional = 0; |
|---|
| 141 | BXDM_PPFP_P_FixPtDiv(&stDeltaPTS, |
|---|
| 142 | hXdmPP->stDMState.stDecode.stFRDStats.uiPicturesSinceLastValidPTS, |
|---|
| 143 | &stDeltaPTS); |
|---|
| 144 | |
|---|
| 145 | /* Handle PTS discontinuity scenario */ |
|---|
| 146 | if ( stDeltaPTS.uiWhole < BXDM_PPFRD_P_DISCONTINUITY_DELTA_PTS_THRESHOLD ) |
|---|
| 147 | { |
|---|
| 148 | for (i = 0; i < hXdmPP->stDMState.stDecode.stFRDStats.uiPicturesSinceLastValidPTS; i++) |
|---|
| 149 | { |
|---|
| 150 | /* Add new deltaPTS to queue. We add one deltaPTS entry |
|---|
| 151 | * per picture. */ |
|---|
| 152 | BXDM_PPFRD_S_AddDeltaPTS( |
|---|
| 153 | hXdmPP, |
|---|
| 154 | &stDeltaPTS); |
|---|
| 155 | } |
|---|
| 156 | } |
|---|
| 157 | else |
|---|
| 158 | { |
|---|
| 159 | BXVD_DBG_MSG(hXdmPP, ("Warning, PTS discontinuity detected (dPTS=%d). Ignoring deltaPTS during discontinuity.", stDeltaPTS.uiWhole)); |
|---|
| 160 | } |
|---|
| 161 | } |
|---|
| 162 | else |
|---|
| 163 | { |
|---|
| 164 | BXVD_DBG_MSG(hXdmPP, ("Warning, PTS wrap/discontinuity detected (%08x -> %08x). Ignoring deltaPTS during wrap/discontinuity.", |
|---|
| 165 | hXdmPP->stDMState.stDecode.stFRDStats.uiLastPTS, |
|---|
| 166 | uiPTS)); |
|---|
| 167 | } |
|---|
| 168 | } |
|---|
| 169 | |
|---|
| 170 | hXdmPP->stDMState.stDecode.stFRDStats.uiLastPTS = uiPTS; |
|---|
| 171 | hXdmPP->stDMState.stDecode.stFRDStats.bLastPTSValid = true; |
|---|
| 172 | hXdmPP->stDMState.stDecode.stFRDStats.uiPicturesSinceLastValidPTS = uiNumElements; |
|---|
| 173 | } |
|---|
| 174 | else |
|---|
| 175 | { |
|---|
| 176 | hXdmPP->stDMState.stDecode.stFRDStats.uiPicturesSinceLastValidPTS += uiNumElements; |
|---|
| 177 | } |
|---|
| 178 | |
|---|
| 179 | /* Add new deltaPTS to queue. We add one deltaPTS entry |
|---|
| 180 | * per picture. */ |
|---|
| 181 | BXDM_PPFRD_S_AddNumElements( |
|---|
| 182 | hXdmPP, |
|---|
| 183 | uiNumElements); |
|---|
| 184 | |
|---|
| 185 | return BERR_SUCCESS; |
|---|
| 186 | } |
|---|
| 187 | |
|---|
| 188 | typedef struct BXDM_PPFRD_P_DeltaPtsToFrameRateMap |
|---|
| 189 | { |
|---|
| 190 | BXDM_PPFP_P_DataType stDeltaPTS; |
|---|
| 191 | BAVC_FrameRateCode eFrameRate; |
|---|
| 192 | } BXDM_PPFRD_P_DeltaPtsToFrameRateMap; |
|---|
| 193 | |
|---|
| 194 | static const BXDM_PPFRD_P_DeltaPtsToFrameRateMap sFrameRateLUT[] = |
|---|
| 195 | { |
|---|
| 196 | { { 6051, 1 }, BAVC_FrameRateCode_eUnknown }, |
|---|
| 197 | { { 5961, 1 }, BAVC_FrameRateCode_e7_493 }, |
|---|
| 198 | { { 2958, 1 }, BAVC_FrameRateCode_e14_985 }, |
|---|
| 199 | { { 1875, 1 }, BAVC_FrameRateCode_e23_976 }, |
|---|
| 200 | { { 1830, 1 }, BAVC_FrameRateCode_e24 }, |
|---|
| 201 | { { 1755, 1 }, BAVC_FrameRateCode_e25 }, |
|---|
| 202 | { { 1500, 1 }, BAVC_FrameRateCode_e29_97 }, |
|---|
| 203 | { { 1455, 1 }, BAVC_FrameRateCode_e30 }, |
|---|
| 204 | { { 855, 1 }, BAVC_FrameRateCode_e50 }, |
|---|
| 205 | { { 750, 1 }, BAVC_FrameRateCode_e59_94 }, |
|---|
| 206 | { { 705, 1 }, BAVC_FrameRateCode_e60 }, |
|---|
| 207 | { { 0, 0 }, BAVC_FrameRateCode_eUnknown } |
|---|
| 208 | }; |
|---|
| 209 | |
|---|
| 210 | static const uint32_t sFrameRateStabiltyLUT[BAVC_FrameRateCode_e7_493 + 1] = |
|---|
| 211 | { |
|---|
| 212 | 30, /* BAVC_FrameRateCode_eUnknown */ |
|---|
| 213 | 24, /* BAVC_FrameRateCode_e23_976 */ |
|---|
| 214 | 24, /* BAVC_FrameRateCode_e24 */ |
|---|
| 215 | 25, /* BAVC_FrameRateCode_e25 */ |
|---|
| 216 | 30, /* BAVC_FrameRateCode_e29_97 */ |
|---|
| 217 | 30, /* BAVC_FrameRateCode_e30 */ |
|---|
| 218 | 50, /* BAVC_FrameRateCode_e50 */ |
|---|
| 219 | 60, /* BAVC_FrameRateCode_e59_94 */ |
|---|
| 220 | 60, /* BAVC_FrameRateCode_e60 */ |
|---|
| 221 | 15, /* BAVC_FrameRateCode_e14_985 */ |
|---|
| 222 | 8 /* BAVC_FrameRateCode_e7_493 */ |
|---|
| 223 | }; |
|---|
| 224 | |
|---|
| 225 | BERR_Code BXDM_PPFRD_P_GetFrameRate( |
|---|
| 226 | BXDM_PictureProvider_Handle hXdmPP, |
|---|
| 227 | BXDM_PictureProvider_P_ClockRate eClockRate, |
|---|
| 228 | BXDM_PictureProvider_FrameRateDetectionMode eFrameRateDetectionMode, |
|---|
| 229 | BAVC_FrameRateCode *peFrameRate |
|---|
| 230 | ) |
|---|
| 231 | { |
|---|
| 232 | BXDM_PPFP_P_DataType stAverageDeltaPTS; |
|---|
| 233 | uint32_t uiFrameRateIndex = 0; |
|---|
| 234 | |
|---|
| 235 | *peFrameRate = BAVC_FrameRateCode_eUnknown; |
|---|
| 236 | stAverageDeltaPTS.uiWhole = 0; |
|---|
| 237 | stAverageDeltaPTS.uiFractional = 0; |
|---|
| 238 | |
|---|
| 239 | if ( BXDM_PictureProvider_FrameRateDetectionMode_eOff != eFrameRateDetectionMode ) |
|---|
| 240 | { |
|---|
| 241 | /* Calculate the average deltaPTS */ |
|---|
| 242 | if ( hXdmPP->stDMState.stDecode.stFRDStats.uiDeltaPTSCount > 0 ) |
|---|
| 243 | { |
|---|
| 244 | if ( BXDM_PictureProvider_P_ClockRate_eDirecTV == eClockRate ) |
|---|
| 245 | { |
|---|
| 246 | /* Scale down by 600 if we have a DirecTV clock rate */ |
|---|
| 247 | BXDM_PPFP_P_FixPtDiv( |
|---|
| 248 | &hXdmPP->stDMState.stDecode.stFRDStats.stDeltaPTSRunningSum, |
|---|
| 249 | hXdmPP->stDMState.stDecode.stFRDStats.uiDeltaPTSCount*600, |
|---|
| 250 | &stAverageDeltaPTS |
|---|
| 251 | ); |
|---|
| 252 | } |
|---|
| 253 | else |
|---|
| 254 | { |
|---|
| 255 | BXDM_PPFP_P_FixPtDiv( |
|---|
| 256 | &hXdmPP->stDMState.stDecode.stFRDStats.stDeltaPTSRunningSum, |
|---|
| 257 | hXdmPP->stDMState.stDecode.stFRDStats.uiDeltaPTSCount, |
|---|
| 258 | &stAverageDeltaPTS |
|---|
| 259 | ); |
|---|
| 260 | } |
|---|
| 261 | |
|---|
| 262 | /* The average delta PTS we've computed so far is the avg dPTS |
|---|
| 263 | * per _field_. We need to convert it to the avg dPTS per |
|---|
| 264 | * _frame_. We assume that 2 interlaced fields equals 1 frame. |
|---|
| 265 | * So, we calculate the following: |
|---|
| 266 | * |
|---|
| 267 | * (avg dPTS)/picture = (avg dPTS/field)*(floor(avg fields/picture)) |
|---|
| 268 | * |
|---|
| 269 | * This equation accounts for 3:2 pulldown content which has 2.5 |
|---|
| 270 | * fields/picture. |
|---|
| 271 | */ |
|---|
| 272 | BXDM_PPFP_P_FixPtMult( |
|---|
| 273 | &stAverageDeltaPTS, |
|---|
| 274 | hXdmPP->stDMState.stDecode.stFRDStats.uiNumElementsRunningSum/hXdmPP->stDMState.stDecode.stFRDStats.uiNumPicturesCount, |
|---|
| 275 | &stAverageDeltaPTS); |
|---|
| 276 | |
|---|
| 277 | /* Map the average deltaPTS to a known frame rate */ |
|---|
| 278 | while ( ( stAverageDeltaPTS.uiWhole < sFrameRateLUT[uiFrameRateIndex].stDeltaPTS.uiWhole ) |
|---|
| 279 | || ( ( stAverageDeltaPTS.uiWhole == sFrameRateLUT[uiFrameRateIndex].stDeltaPTS.uiWhole ) |
|---|
| 280 | && ( stAverageDeltaPTS.uiFractional < sFrameRateLUT[uiFrameRateIndex].stDeltaPTS.uiFractional ) ) ) |
|---|
| 281 | { |
|---|
| 282 | uiFrameRateIndex++; |
|---|
| 283 | } |
|---|
| 284 | |
|---|
| 285 | /* Determine which frame rate type to return */ |
|---|
| 286 | switch ( eFrameRateDetectionMode ) |
|---|
| 287 | { |
|---|
| 288 | case BXDM_PictureProvider_FrameRateDetectionMode_eStable: |
|---|
| 289 | { |
|---|
| 290 | /* Keep track of how many pictures the frame rate is stable for */ |
|---|
| 291 | if (sFrameRateLUT[uiFrameRateIndex].eFrameRate == hXdmPP->stDMState.stDecode.stFRDStats.eLastCalculatedFrameRate) |
|---|
| 292 | { |
|---|
| 293 | hXdmPP->stDMState.stDecode.stFRDStats.uiNumPicturesCalculatedFrameRateWasStable++; |
|---|
| 294 | } |
|---|
| 295 | else |
|---|
| 296 | { |
|---|
| 297 | hXdmPP->stDMState.stDecode.stFRDStats.uiNumPicturesCalculatedFrameRateWasStable = 0; |
|---|
| 298 | } |
|---|
| 299 | hXdmPP->stDMState.stDecode.stFRDStats.eLastCalculatedFrameRate = sFrameRateLUT[uiFrameRateIndex].eFrameRate; |
|---|
| 300 | |
|---|
| 301 | if ( hXdmPP->stDMState.stDecode.stFRDStats.uiNumPicturesCalculatedFrameRateWasStable >= sFrameRateStabiltyLUT[sFrameRateLUT[uiFrameRateIndex].eFrameRate] ) |
|---|
| 302 | { |
|---|
| 303 | hXdmPP->stDMState.stDecode.stFRDStats.eLastReportedStableFrameRate = sFrameRateLUT[uiFrameRateIndex].eFrameRate; |
|---|
| 304 | } |
|---|
| 305 | |
|---|
| 306 | *peFrameRate = hXdmPP->stDMState.stDecode.stFRDStats.eLastReportedStableFrameRate; |
|---|
| 307 | } |
|---|
| 308 | break; |
|---|
| 309 | |
|---|
| 310 | case BXDM_PictureProvider_FrameRateDetectionMode_eFast: |
|---|
| 311 | *peFrameRate = sFrameRateLUT[uiFrameRateIndex].eFrameRate; |
|---|
| 312 | break; |
|---|
| 313 | |
|---|
| 314 | default: |
|---|
| 315 | *peFrameRate = BAVC_FrameRateCode_eUnknown; |
|---|
| 316 | } |
|---|
| 317 | } |
|---|
| 318 | else |
|---|
| 319 | { |
|---|
| 320 | /* We don't have enough data to compute a frame rate */ |
|---|
| 321 | *peFrameRate = BAVC_FrameRateCode_eUnknown; |
|---|
| 322 | } |
|---|
| 323 | } |
|---|
| 324 | |
|---|
| 325 | BXVD_DBG_MSG(hXdmPP, ("BXDM_PPFRD_P_GetFrameRate((%d.%d)/%d = %d.%d --> %d [%d])", |
|---|
| 326 | hXdmPP->stDMState.stDecode.stFRDStats.stDeltaPTSRunningSum.uiWhole, |
|---|
| 327 | hXdmPP->stDMState.stDecode.stFRDStats.stDeltaPTSRunningSum.uiFractional, |
|---|
| 328 | hXdmPP->stDMState.stDecode.stFRDStats.uiDeltaPTSCount, |
|---|
| 329 | stAverageDeltaPTS.uiWhole, |
|---|
| 330 | stAverageDeltaPTS.uiFractional, |
|---|
| 331 | *peFrameRate, |
|---|
| 332 | eFrameRateDetectionMode |
|---|
| 333 | )); |
|---|
| 334 | |
|---|
| 335 | return BERR_SUCCESS; |
|---|
| 336 | } |
|---|