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

Last change on this file since 74 was 74, checked in by phkim, 10 years ago
  1. phkim
  2. zasc
  3. 변경 내용
    • CT_ChMapUpdatePMTAC3AudioDescriptor 메모리 leak 버그 수정
  • Property svn:executable set to *
File size: 91.2 KB
Line 
1/***************************************************************************
2 *     Copyright (c) 2003-2012, Broadcom Corporation
3 *     All Rights Reserved
4 *     Confidential Property of Broadcom Corporation
5 *
6 *  THIS SOFTWARE MAY ONLY BE USED SUBJECT TO AN EXECUTED SOFTWARE LICENSE
7 *  AGREEMENT  BETWEEN THE USER AND BROADCOM.  YOU HAVE NO RIGHT TO USE OR
8 *  EXPLOIT THIS MATERIAL EXCEPT SUBJECT TO THE TERMS OF SUCH AN AGREEMENT.
9 *
10 * $brcm_Workfile: bxdm_pp_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
145BDBG_MODULE(BXDM_PPTSM);
146
147const 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 */
161static 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 */
241static 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 */
278static 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 */
296static 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 */
332static 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. */
350static 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. */
368static 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 */
387static 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
410static 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 */
433static 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
485static 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
812typedef struct BXDM_PPTSM_P_FrameRateMap
813{
814      uint32_t uiNormalizedFrameRate;
815      BAVC_FrameRateCode eFrameRateCode;
816} BXDM_PPTSM_P_FrameRateMap;
817
818static 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
834static
835BAVC_FrameRateCode
836BXDM_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
865void 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
1181void 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
1267void 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
1478void 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
1616void 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
1682static 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
Note: See TracBrowser for help on using the repository browser.