source: svn/trunk/newcon3bcm2_21bu/magnum/portinginterface/xvd/7552/bxvd_decoder.c

Last change on this file was 2, checked in by jglee, 11 years ago

first commit

  • Property svn:executable set to *
File size: 184.4 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: bxvd_decoder.c $
11 * $brcm_Revision: Hydra_Software_Devel/50 $
12 * $brcm_Date: 3/16/12 11:58a $
13 *
14 * [File Description:]
15 *
16 * Revision History:
17 *
18 * $brcm_Log: /magnum/portinginterface/xvd/7401/bxvd_decoder.c $
19 *
20 * Hydra_Software_Devel/50   3/16/12 11:58a btosi
21 * SW7425-2536: added support for displayInterruptStatus_isr
22 *
23 * Hydra_Software_Devel/49   2/10/12 11:18a btosi
24 * SW7425-2247: add support for bar data
25 *
26 * Hydra_Software_Devel/48   1/13/12 9:48a btosi
27 * SW7405-4736: fixed warning on the 7630 build
28 *
29 * Hydra_Software_Devel/47   1/12/12 3:23p btosi
30 * SW7405-4736: added debug support for new PPB field flags_ext0
31 *
32 * Hydra_Software_Devel/46   1/10/12 1:32p btosi
33 * SW7425-1001: added support for bLast flag
34 *
35 * Hydra_Software_Devel/45   12/16/11 8:32a btosi
36 * SWDTV-8681: add support for VP8 display size
37 *
38 * Hydra_Software_Devel/44   12/5/11 2:54p btosi
39 * SWCHECKFRAME-80: execute the PPBReceived callback prior to processing
40 * the PPB data.
41 *
42 * Hydra_Software_Devel/43   12/1/11 1:12p pblanco
43 * SW7425-1780: Implemented picture id support for transcode userdata.
44 *
45 * Hydra_Software_Devel/42   9/20/11 3:32p btosi
46 * SW7425-1261: only clear bTruncatingGop in ..._ReleaseGopTail
47 *
48 * Hydra_Software_Devel/41   7/28/11 11:38a btosi
49 * SW7405-4736: added the PPB flags to the BXVD_UP message
50 *
51 * Hydra_Software_Devel/40   7/27/11 12:08p btosi
52 * SWDTV-7795: added support for RV9 cropping
53 *
54 * Hydra_Software_Devel/39   7/20/11 3:07p davidp
55 * SW7420-2001: Reorder header-file includes.
56 *
57 * Hydra_Software_Devel/38   6/27/11 4:18p davidp
58 * SW7425-542: Merge devel branch to mainline.
59 *
60 * Hydra_Software_Devel/SW7425-542/2   6/24/11 8:53a davidp
61 * SW7425-542: Add BXVD_P_DBG_PIC_QUES to enable queue processing log.
62 *
63 * Hydra_Software_Devel/SW7425-542/1   6/14/11 10:40a btosi
64 * SW7425-542: cleaned up warning
65 *
66 * Hydra_Software_Devel/37   6/8/11 1:04p btosi
67 * SW7425-542: moved the delivery/release queue management macros to the
68 * platform files
69 *
70 * Hydra_Software_Devel/36   6/1/11 3:15p btosi
71 * SW7425-542: added macros for accessing the AVD queue read and write
72 * offsets
73 *
74 * Hydra_Software_Devel/35   5/20/11 11:55a btosi
75 * SW7425-609: check bPictureDropped before linking the dependent to the
76 * base picture
77 *
78 * Hydra_Software_Devel/34   5/3/11 1:32p btosi
79 * SW7405-4736: reset stUnifiedContext in ..._UpdateReadOffset, fixes
80 * crash in StereoSeqError check test
81 *
82 * Hydra_Software_Devel/33   4/18/11 9:33a btosi
83 * SW7405-4736: pre increment uiPPBSerialNumber so that the Decoder and
84 * XDM debug messages match
85 *
86 * Hydra_Software_Devel/32   4/15/11 3:31p btosi
87 * SW7405-4736: backed out change for incrementing uiPPBSerialNumber
88 *
89 * Hydra_Software_Devel/31   4/15/11 10:50a btosi
90 * SW7405-4736: added support to print the SEI messages
91 *
92 * Hydra_Software_Devel/30   4/4/11 11:28a btosi
93 * SW7405-4736: added support for BXVD_DecoderDbg_P_PrintUnifiedPicture
94 *
95 * Hydra_Software_Devel/29   3/15/11 10:17a btosi
96 * SW7425-160: updated to use Broadcom standard types
97 *
98 * Hydra_Software_Devel/28   2/25/11 11:14a btosi
99 * SW7425-106: work around the issue with the DQ read offset increment
100 *
101 * Hydra_Software_Devel/27   2/17/11 2:01p btosi
102 * SW7405-5135: if the SEI arrangement_cancel flag is set, set both the
103 * Unified and MFD picture orientations to 2D
104 *
105 * Hydra_Software_Devel/26   2/8/11 12:51p btosi
106 * SW7425-82: use frame_packing_arrangement_type to determine the type of
107 * frame packing.
108 *
109 * Hydra_Software_Devel/25   2/2/11 1:41p btosi
110 * SW7125-808: fixed the issue of the drop count going negative in
111 * BXVD_Decoder_GetPictureDropPendingCount_isr when the deliver queue
112 * is empty
113 *
114 * Hydra_Software_Devel/24   1/25/11 3:56p davidp
115 * SW7422-22: Add support for SVC Picture Order Count.
116 *
117 * Hydra_Software_Devel/23   12/16/10 9:20a btosi
118 * SW7422-72: fixed warning
119 *
120 * Hydra_Software_Devel/22   12/10/10 1:22p btosi
121 * SWBLURAY-23835: added check for a picture being released multiple times
122 *
123 * Hydra_Software_Devel/21   11/24/10 1:22p btosi
124 * SW7422-72: added BXVD_LEGACY_MVC_SUPPORT and bSetNextPointer for MVC on
125 * older DVD chips
126 *
127 * Hydra_Software_Devel/20   11/23/10 10:25a btosi
128 * SW7422-72: with the exception of older DVD chips, 2D is now the default
129 * orientation for MVC streams
130 *
131 * Hydra_Software_Devel/19   10/29/10 11:39a btosi
132 * SW7422-72: merging 3D changes to mainline
133 *
134 * Hydra_Software_Devel/SW7422-72/2   10/29/10 11:34a btosi
135 * SW7422-72: added support for AVC 3D
136 *
137 * Hydra_Software_Devel/SW7422-72/1   10/19/10 10:29a btosi
138 * SW7422-72: expanded support for 3D
139 *
140 * Hydra_Software_Devel/18   10/19/10 9:08a delkert
141 * SW7405-4044: Add support for
142 * BAVC_TransferCharacteristics_eIec_61966_2_4 to support xvYCC
143 *
144 * Hydra_Software_Devel/17   8/9/10 1:24p btosi
145 * SW7405-4733: set eSequence to eInterlaced instead of defaulting to
146 * eUnknown
147 *
148 * Hydra_Software_Devel/16   7/29/10 11:22a btosi
149 * SW7405-4560: added support for the SEI "new message" flag.
150 *
151 * Hydra_Software_Devel/15   7/27/10 11:36a btosi
152 * SW7401-4426: added support for the H264 timecode
153 *
154 * Hydra_Software_Devel/14   7/7/10 2:40p btosi
155 * SWBLURAY-21461: for MPEG and VC1, use the display width/height provided
156 * in the PPB
157 *
158 * Hydra_Software_Devel/13   6/28/10 2:48p btosi
159 * SW7405-4365: added support to selectively compile the function timing
160 * code.
161 *
162 * Hydra_Software_Devel/12   6/25/10 2:13p btosi
163 * SW7405-4365: added use of local variables in
164 * BXVD_Decoder_S_UnifiedQ_ValidatePicture to
165 * improve performance
166 *
167 * Hydra_Software_Devel/11   6/16/10 12:56p btosi
168 * SW7405-4365: added support for using the new timer functions
169 *
170 * Hydra_Software_Devel/10   6/11/10 10:54a davidp
171 * SW7405-3925: Fix compiler warning.
172 *
173 * Hydra_Software_Devel/9   6/7/10 10:23a delkert
174 * SW7405-3925: When retrieving pending drop count, first check that there
175 * are pictures in the Q to avoid "ping-ponging" between vTSM and TSM
176 * selection mode.  Modify request drop API to update the request count.
177 * Removed duplicated assertion
178 *
179 * Hydra_Software_Devel/8   6/3/10 11:55a btosi
180 * SW7630-83: fixed handling of mismatched pairs of pictures as well as
181 * general cleanup
182 *
183 * Hydra_Software_Devel/7   5/12/10 2:44p btosi
184 * SWBLURAY-20606: fixed assignment of
185 * stBluRay3DGraphicsOffset.puiOffsetData
186 *
187 * Hydra_Software_Devel/6   5/4/10 10:41a btosi
188 * SW7405-3996: added support for new SEI message format
189 *
190 * Hydra_Software_Devel/5   5/4/10 9:12a pblanco
191 * SW7125-386: Fixed malformed BXVD_DBG_ERR calls.
192 *
193 * Hydra_Software_Devel/4   4/29/10 4:12p btosi
194 * SW7630-79: set stBufferInfo.bValid to false if a pictureless PPB
195 *
196 * Hydra_Software_Devel/3   4/16/10 10:50a pblanco
197 * SW7405-2993: Added some conditionalized debugging output.
198 *
199 * Hydra_Software_Devel/2   3/1/10 4:58p nilesh
200 * SW7405-2993: Fix coverity warnings
201 *
202 * Hydra_Software_Devel/1   2/25/10 4:24p nilesh
203 * SW7405-2993: XDM Merge
204 *
205 ***************************************************************************/
206
207#include "bstd.h"
208#include "bdbg.h"                /* Dbglib */
209#include "bmth_fix.h"
210
211#include "bxvd_platform.h"
212#include "bxvd_priv.h"
213#include "bxvd_reg.h"
214#include "bxdm_decoder.h"
215#include "bxvd_decoder.h"
216#include "bxvd_decoder_dbg.h"
217
218#include "bxvd_vdec_info.h"
219
220#if BXVD_DM_ENABLE_YUV_GRAB_MODE
221#include <stdio.h>
222#include <stdlib.h>
223#include "bxvd_reg.h"
224#endif
225
226
227BDBG_MODULE(BXVD_DECODER);
228
229/***************************************************************************
230 *
231 *   Local constant and type definitions.
232 *
233 ***************************************************************************/
234
235/* Number of pictures in this set. Should use the data provided with the
236 * picture, i.e. "pstPicCntxt->uiSetCount".  Waiting on the firmware.
237 */
238#define BXVD_DECODER_S_PICTURES_PER_SET      2
239
240/*
241 * Set this to non-zero for extra AVD debugging help
242 */
243#define BXVD_DECODER_AVD_DEBUG_HELP 0
244
245
246/* sAVCStripeWidthLUT maps the stripe width from XVD to the proper
247 * BAVC_StripeWidth enum
248 */
249static const BAVC_StripeWidth sAVCStripeWidthLUT[BXVD_P_STRIPE_WIDTH_NUM] =
250{
251   BAVC_StripeWidth_e64Byte,
252   BAVC_StripeWidth_e128Byte
253
254}; /* end of sAVCStripeWidthLUT[] */
255
256
257static const BXDM_Picture_Rate sFrameRateEnumToIntLUT[BAVC_FrameRateCode_eMax] =
258{
259   { 30000, 1000},   /* BAVC_FrameRateCode_eUnknown */
260   { 24000, 1001},   /* BAVC_FrameRateCode_e23_976 */
261   { 24000, 1000},   /* BAVC_FrameRateCode_e24 */
262   { 25000, 1000},   /* BAVC_FrameRateCode_e25 */
263   { 30000, 1001},   /* BAVC_FrameRateCode_e29_97 */
264   { 30000, 1000},   /* BAVC_FrameRateCode_e30 */
265   { 50000, 1000},   /* BAVC_FrameRateCode_e50 */
266   { 60000, 1001},   /* BAVC_FrameRateCode_e59_94 */
267   { 60000, 1000},   /* BAVC_FrameRateCode_e60 */
268   { 15000, 1001},   /* BAVC_FrameRateCode_e14_985 */
269   {  7500, 1001}    /* BAVC_FrameRateCode_e7_493 */
270};
271
272
273typedef struct BXVD_Decoder_S_SampleAspectRatio
274{
275      uint16_t uiSampleAspectRatioX;
276      uint16_t uiSampleAspectRatioY;
277} BXVD_Decoder_S_SampleAspectRatio;
278
279#define BXVD_DECODER_S_SAMPLE_ASPECT_RATIO_LUT_SIZE BXVD_P_PPB_AspectRatio_e221_1 + 1
280
281static const BXVD_Decoder_S_SampleAspectRatio sSampleAspectRatioLUT[BXVD_DECODER_S_SAMPLE_ASPECT_RATIO_LUT_SIZE] =
282{
283   {0,0},
284   {1,1},
285   {12,11},
286   {10,11},
287   {16,11},
288   {40,33},
289   {24,11},
290   {20,11},
291   {32,11},
292   {80,33},
293   {18,11},
294   {15,11},
295   {64,33},
296   {160,99},
297   {4,3},
298   {3,2},
299   {2,1},
300   {16,9},
301   {221,1}
302}; /* end of sSampleAspectRatioLUT[] */
303
304/* DNR Related Defines */
305#define BXVD_Decoder_S_DNR_INTRA_DEFAULT              2114
306#define BXVD_Decoder_S_DNR_INTER_DEFAULT              964
307
308#define BXVD_Decoder_S_DNR_INTRA_DEFAULT_AVC          1680
309#define BXVD_Decoder_S_DNR_INTER_DEFAULT_AVC          1507
310
311/* Lookup Tables */
312#define BXVD_DECODER_S_MATRIX_COEFFICIENTS_LUT_SIZE (BXVD_P_PPB_MatrixCoeff_eSMPTE293M + 1)
313static const BAVC_MatrixCoefficients sMatrixCoefficientsLUT[BXVD_DECODER_S_MATRIX_COEFFICIENTS_LUT_SIZE] =
314{
315   BAVC_MatrixCoefficients_eUnknown,           /* BXVD_P_PPB_MatrixCoeff_eUnknown */
316   BAVC_MatrixCoefficients_eItu_R_BT_709,      /* BXVD_P_PPB_MatrixCoeff_eBT709 */
317   BAVC_MatrixCoefficients_eUnknown,           /* BXVD_P_PPB_MatrixCoeff_eUnspecified */
318   BAVC_MatrixCoefficients_eUnknown,           /* BXVD_P_PPB_MatrixCoeff_eReserved */
319   BAVC_MatrixCoefficients_eFCC,               /* BXVD_P_PPB_MatrixCoeff_eFCC */
320   BAVC_MatrixCoefficients_eItu_R_BT_470_2_BG, /* BXVD_P_PPB_MatrixCoeff_eBT740_2BG */
321   BAVC_MatrixCoefficients_eSmpte_170M,        /* BXVD_P_PPB_MatrixCoeff_eSMPTE170M */
322   BAVC_MatrixCoefficients_eSmpte_240M,        /* BXVD_P_PPB_MatrixCoeff_eSMPTE240M */
323   BAVC_MatrixCoefficients_eUnknown            /* BXVD_P_PPB_MatrixCoeff_eSMPTE293M */
324}; /* end of sMatrixCoefficientsLUT[] */
325
326#define BXVD_DECODER_S_COLOR_PRIMARIES_LUT_SIZE (BXVD_P_PPB_ColorPrimaries_eBT1361 + 1)
327static const BAVC_ColorPrimaries sColorPrimariesLUT[BXVD_DECODER_S_COLOR_PRIMARIES_LUT_SIZE] =
328{
329   BAVC_ColorPrimaries_eUnknown,           /* BXVD_P_PPB_ColorPrimaries_eUnknown */
330   BAVC_ColorPrimaries_eItu_R_BT_709,      /* BXVD_P_PPB_ColorPrimaries_eBT709 */
331   BAVC_ColorPrimaries_eUnknown,           /* BXVD_P_PPB_ColorPrimaries_eUnspecified */
332   BAVC_ColorPrimaries_eUnknown,           /* BXVD_P_PPB_ColorPrimaries_eReserved */
333   BAVC_ColorPrimaries_eItu_R_BT_470_2_M,  /* BXVD_P_PPB_ColorPrimaries_eBT470_2M */
334   BAVC_ColorPrimaries_eItu_R_BT_470_2_BG, /* BXVD_P_PPB_ColorPrimaries_eBT470_2BG */
335   BAVC_ColorPrimaries_eSmpte_170M,        /* BXVD_P_PPB_ColorPrimaries_eSMPTE170M */
336   BAVC_ColorPrimaries_eSmpte_240M,        /* BXVD_P_PPB_ColorPrimaries_eSMPTE240M */
337   BAVC_ColorPrimaries_eGenericFilm,       /* BXVD_P_PPB_ColorPrimaries_eGenericFilm */
338   BAVC_ColorPrimaries_eUnknown            /* BXVD_P_PPB_ColorPrimaries_eBT1361 */
339}; /* end of sColorPrimariesLUT[] */
340
341#define BXVD_DECODER_S_TRANSFER_CHARACTERISICS_LUT_SIZE (BXVD_P_PPB_TransferChar_eIec_61966_2_4 + 1)
342static const BAVC_TransferCharacteristics sTransferCharacteristicsLUT[BXVD_DECODER_S_TRANSFER_CHARACTERISICS_LUT_SIZE] =
343{
344   BAVC_TransferCharacteristics_eUnknown,           /* BXVD_P_PPB_TransferChar_eUnknown */
345   BAVC_TransferCharacteristics_eItu_R_BT_709,      /* BXVD_P_PPB_TransferChar_eBT709 */
346   BAVC_TransferCharacteristics_eUnknown,           /* BXVD_P_PPB_TransferChar_eUnspecified */
347   BAVC_TransferCharacteristics_eUnknown,           /* BXVD_P_PPB_TransferChar_eReserved */
348   BAVC_TransferCharacteristics_eItu_R_BT_470_2_M,  /* BXVD_P_PPB_TransferChar_eBT479_2M */
349   BAVC_TransferCharacteristics_eItu_R_BT_470_2_BG, /* BXVD_P_PPB_TransferChar_eBT479_2BG */
350   BAVC_TransferCharacteristics_eSmpte_170M,        /* BXVD_P_PPB_TransferChar_eSMPTE170M */
351   BAVC_TransferCharacteristics_eSmpte_240M,        /* BXVD_P_PPB_TransferChar_eSMPTE240M */
352   BAVC_TransferCharacteristics_eLinear,            /* BXVD_P_PPB_TransferChar_eLinear */
353   BAVC_TransferCharacteristics_eUnknown,           /* BXVD_P_PPB_TransferChar_eLog100_1 */
354   BAVC_TransferCharacteristics_eUnknown,           /* BXVD_P_PPB_TransferChar_eLog31622777_1 */
355   BAVC_TransferCharacteristics_eIec_61966_2_4      /* BXVD_P_PPB_TransferChar_eIec_61966_2_4 */
356}; /* end of sTransferCharacteristicsLUT[] */
357
358/***************************************************************************
359 *
360 *   Function prototypes.
361 *
362 ***************************************************************************/
363
364static void BXVD_Decoder_S_Increment_0BasedOffset(
365   uint32_t * pOffset,
366   uint32_t uiCount,
367   uint32_t uiMaxValue
368   );
369
370static void BXVD_Decoder_S_Decrement_0BasedOffset(
371   uint32_t * pOffset,
372   uint32_t uiCount,
373   uint32_t uiMaxValue
374   );
375
376static void BXVD_Decoder_S_Decrement_2BasedOffset(
377   uint32_t * pOffset,
378   uint32_t uiCount,
379   uint32_t uiMaxValue
380   );
381
382static void BXVD_Decoder_S_DeliveryQ_UpdateReadOffset(
383   BXVD_ChannelHandle hXvdCh,
384   BXVD_Decoder_P_LocalState* pstLocalState,
385   uint32_t uiDeltaChange
386   );
387
388static void BXVD_Decoder_S_UnifiedQ_ValidatePicture(
389   BXVD_ChannelHandle hXvdCh,
390   BXVD_Decoder_P_PictureContext * pstPictureCntxt,
391   BXVD_Decoder_P_UnifiedPictureContext * pstUnifiedContext,
392   bool bPictureDropped
393   );
394
395static bool  BXVD_Decoder_S_DeliveryQ_CheckForDeadlock(
396   BXVD_ChannelHandle hXvdCh,
397   uint32_t uiNumPicturesToProcess
398   );
399
400static void BXVD_Decoder_S_DeliveryQ_ReleaseGopTail(
401   BXVD_ChannelHandle hXvdCh,
402   BXVD_Decoder_P_LocalState * pstLocalState
403   );
404
405static void BXVD_Decoder_S_ReleaseQ_AddPPB(
406   BXVD_ChannelHandle hXvdCh,
407   BXVD_P_PPB *pPPBPhysical
408   );
409
410static void BXVD_Decoder_S_UnifiedQ_Initialize(
411   BXVD_ChannelHandle hXvdCh
412   );
413
414static void BXVD_Decoder_S_UnifiedQ_AddPicture(
415   BXVD_ChannelHandle hXvdCh,
416   BXVD_Decoder_P_PictureContext * pstPictureCntxt,
417   bool bBasePicture
418   );
419
420static void BXVD_Decoder_S_UnifiedQ_GetNextFreeElement(
421   BXVD_ChannelHandle hXvdCh,
422   BXVD_Decoder_P_UnifiedPictureContext ** ppstUnifiedContext
423   );
424
425static void BXVD_Decoder_S_UnifiedQ_GetLastElement(
426   BXVD_ChannelHandle hXvdCh,
427   BXVD_Decoder_P_UnifiedPictureContext ** ppstUnifiedContext,
428   bool bBumpReadOffset
429   );
430
431static void BXVD_Decoder_S_UnifiedQ_DumpElement(
432   BXVD_Decoder_P_UnifiedPictureContext * pstUnifiedContext,
433   bool bDependentPicture
434   );
435
436static void BXVD_Decoder_S_UnifiedQ_ReleaseElement(
437   BXVD_ChannelHandle hXvdCh,
438   BXVD_Decoder_P_UnifiedPictureContext * pstUnifiedContext
439   );
440
441static uint32_t BXVD_Decoder_S_UnifiedQ_GetFreeCount(
442   BXVD_ChannelHandle hXvdCh
443   );
444
445static uint32_t BXVD_Decoder_S_UnifiedQ_GetPictureCount(
446   BXVD_ChannelHandle hXvdCh
447   );
448
449static void BXVD_Decoder_S_ComputeAspectRatio(
450   BXVD_P_PPB * pPPB,
451   BXDM_Picture * pstXdmPicture,
452   BAVC_VideoCompressionStd   eProtocol
453   );
454
455#if BXVD_DM_ENABLE_YUV_GRAB_MODE
456void BXVD_Decoder_S_Dbg_DumpPPB( BXVD_P_PPB *ppb );
457void BXVD_Decoder_S_Dbg_DumpRVC( BXVD_ChannelHandle hXvdCh );
458void BXVD_Decoder_S_Dbg_DumpYUV( BXVD_ChannelHandle hXvdCh, BXVD_P_PPB *ppb );
459#endif
460
461/***************************************************************************
462 *
463 *   Local macros.
464 *
465 ***************************************************************************/
466
467/***************************************************************************
468 *
469 *   Private functions.
470 *
471 ***************************************************************************/
472
473#if BXVD_P_DBG_PIC_QUES
474static void BXVD_Decoder_S_Printf( char * pszFormat, ... )
475{
476   va_list  pArg;
477
478   va_start( pArg, pszFormat );
479   BKNI_Vprintf( pszFormat, pArg );
480   va_end( pArg );
481}
482
483#else
484static void BXVD_Decoder_S_Printf( char * pszFormat, ... )
485{
486   BSTD_UNUSED( pszFormat );
487   BDBG_NOP();
488}
489#endif
490
491static void BXVD_Decoder_S_Increment_0BasedOffset(
492   uint32_t* pOffset,
493   uint32_t  uiCount,
494   uint32_t  uiMaxValue
495   )
496{
497   uint32_t i;
498
499   for ( i=0; i < uiCount; i++ )
500   {
501      /* If the offset is about to go off the end of the queue,
502       * set it back to the beginning.  Otherwise just increment it.
503       */
504      if( *pOffset >= uiMaxValue - 1/*(BXVD_P_MAX_ELEMENTS_IN_DISPLAY_QUEUE - 1)*/ )
505      {
506         *pOffset = 0;
507      }
508      else
509      {
510         (*pOffset)++;
511      }
512   }
513
514   return;
515}
516
517
518static void BXVD_Decoder_S_Decrement_0BasedOffset(
519   uint32_t* pOffset,
520   uint32_t  uiCount,
521   uint32_t  uiMaxValue
522   )
523{
524   uint32_t i;
525
526   for ( i=0; i < uiCount; i++ )
527   {
528      /* If the offset is about to go off the beginning of the queue,
529       * set it to the end.  Otherwise just decrement it.
530       */
531      if( *pOffset == 0 )
532      {
533         *pOffset = uiMaxValue - 1/*BXVD_P_MAX_ELEMENTS_IN_DISPLAY_QUEUE - 1*/;
534      }
535      else
536      {
537         (*pOffset)--;
538      }
539   }
540
541   return;
542}
543
544static void BXVD_Decoder_S_Decrement_2BasedOffset(
545   uint32_t* pOffset,
546   uint32_t  uiCount,
547   uint32_t  uiMaxValue
548   )
549{
550   uint32_t i;
551
552   for ( i=0; i < uiCount; i++ )
553   {
554      /* If the offset is about to go off the beginning of the queue,
555       * set it to the end.  Otherwise just decrement it.
556       */
557      if( *pOffset <=  BXVD_P_INITIAL_OFFSET_DISPLAY_QUEUE )
558      {
559         *pOffset = uiMaxValue - 1 /*BXVD_P_DISP_FIFO_DEPTH - 1*/;
560      }
561      else
562      {
563         (*pOffset)--;
564      }
565   }
566
567   return;
568}
569
570/***************************************************************************
571 *
572 *   Routines for managing the delivery queue.
573 *
574 ***************************************************************************/
575
576static bool BXVD_Decoder_S_ContextQ_PeekAtNextElement(
577   BXVD_ChannelHandle hXvdCh,
578   BXVD_Decoder_P_PictureContext ** pstPicCntxt
579   )
580{
581   bool bReturn;
582   uint32_t uiContextQReadOffset0Based;
583
584   BXVD_Decoder_P_PictureContextQueue * pstContextQueue = &(hXvdCh->stDecoderContext.stPictureContextQueue);
585
586   BDBG_ENTER(BXVD_Decoder_S_ContextQ_PeekAtNextElement);
587
588   /* Return the appropriate display queue read offset based on the state of DQT.
589    * If playing backwards, return "uiReverseReadOffset" which is walking backwards
590    * through each GOP.  Else, return the standard "read offset".
591    */
592   if ( true == hXvdCh->stDecoderContext.stDqtCntxt.bDqtEnabled )
593   {
594      uiContextQReadOffset0Based = hXvdCh->stDecoderContext.stDqtCntxt.uiReverseReadOffset;
595   }
596   else
597   {
598      BXVD_AVD_P_DELIVERY_QUEUE_GET_READ_OFFSET( hXvdCh, uiContextQReadOffset0Based );
599   }
600
601   uiContextQReadOffset0Based -= BXVD_P_INITIAL_OFFSET_DISPLAY_QUEUE;
602
603   /* If the read offset is equal to the context queue write offset,
604    * both the deliver and context queues are empty, i.e. all the
605    * pictures have been processed and are on the unified picture queue.
606    */
607   if ( uiContextQReadOffset0Based == pstContextQueue->uiWriteOffset )
608   {
609      bReturn = false;
610      *pstPicCntxt = NULL;
611   }
612   else
613   {
614      /* Queue has data, simply return a pointer to the next element. */
615
616      bReturn = true;
617      *pstPicCntxt = &(pstContextQueue->astPictureContext[ uiContextQReadOffset0Based ]);
618   }
619
620
621   BDBG_LEAVE(BXVD_Decoder_S_ContextQ_PeekAtNextElement);
622
623   return bReturn;
624}
625
626/****************************************************************************************************
627**
628** Local "utility" routines.
629**
630*****************************************************************************************************/
631
632static void BXVD_Decoder_S_Log_Init(
633   BXVD_ChannelHandle hXvdCh
634   )
635{
636   BDBG_ENTER( BXVD_Decoder_S_Log_Init );
637
638   BKNI_Memset( &(hXvdCh->stDecoderContext.stLogData), 0, sizeof( BXVD_Decoder_P_LogData ));
639
640   /* Want to print out the results roughly once per second.
641    * We'll count vsyncs to measure time.
642    */
643   switch ( hXvdCh->sChSettings.ui32MonitorRefreshRate )
644   {
645      case BXVD_MONITOR_REFRESH_RATE_50Hz:
646         hXvdCh->stDecoderContext.stLogData.uiVsyncsPerSecond = 50;
647         break;
648
649      case BXVD_MONITOR_REFRESH_RATE_59_94Hz:
650      case BXVD_MONITOR_REFRESH_RATE_60Hz:
651         hXvdCh->stDecoderContext.stLogData.uiVsyncsPerSecond = 60;
652         break;
653
654      case BXVD_MONITOR_REFRESH_RATE_23_976Hz:
655      case BXVD_MONITOR_REFRESH_RATE_24Hz:
656         hXvdCh->stDecoderContext.stLogData.uiVsyncsPerSecond = 24;
657         break;
658
659      case BXVD_MONITOR_REFRESH_RATE_25Hz:
660         hXvdCh->stDecoderContext.stLogData.uiVsyncsPerSecond = 25;
661         break;
662
663      case BXVD_MONITOR_REFRESH_RATE_30Hz:
664      case BXVD_MONITOR_REFRESH_RATE_29_97Hz:
665         hXvdCh->stDecoderContext.stLogData.uiVsyncsPerSecond = 30;
666         break;
667
668      case BXVD_MONITOR_REFRESH_RATE_48Hz:
669         hXvdCh->stDecoderContext.stLogData.uiVsyncsPerSecond = 48;
670         break;
671
672      case BXVD_MONITOR_REFRESH_RATE_INVALID:
673      default:
674         hXvdCh->stDecoderContext.stLogData.uiVsyncsPerSecond = 60;
675         break;
676   }
677
678   BDBG_LEAVE( BXVD_Decoder_S_Log_Init );
679
680   return;
681
682}  /* end of BXVD_Decoder_S_Log_Init */
683
684static void BXVD_Decoder_S_Log_Print(
685   BXVD_ChannelHandle hXvdCh,
686   BXVD_Decoder_P_LocalState * pstLocalState
687   )
688{
689   BXVD_Decoder_P_LogData * pstLogData = &(hXvdCh->stDecoderContext.stLogData);
690
691   BDBG_ENTER( BXVD_Decoder_S_Log_Print );
692
693   /* Print out the results roughly once per second. */
694   if ( pstLogData->uiCallbackCount >= pstLogData->uiVsyncsPerSecond  )
695   {
696      uint32_t    uiReadOffset;
697      uint32_t    uiWriteOffset;
698      uint32_t    uiDeliveryQDepth;
699      uint32_t    uiReleaseQDepth;
700      uint32_t    uiUnifiedQDepth;
701      uint32_t    uiMaskHighWord, uiMaskLowWord;
702      int32_t     i;
703
704      BXVD_P_PictureDeliveryQueue * pstDeliveryQueue;
705      BXVD_P_PictureReleaseQueue *  pstReleaseQueue;
706
707      BXVD_Decoder_P_UnifiedPictureQueue * pstUnifiedQueue;
708
709      /* Retrieve the read/write offsets for the delivery queue.
710       * Adjust them to be '0' based.
711       */
712      BXVD_AVD_P_DELIVERY_QUEUE_GET_ADDR( hXvdCh, pstDeliveryQueue );
713
714      BXVD_AVD_P_DELIVERY_QUEUE_GET_READ_OFFSET( hXvdCh, uiReadOffset );
715
716      uiReadOffset -= BXVD_P_INITIAL_OFFSET_DISPLAY_QUEUE;
717      uiWriteOffset = pstLocalState->uiDeliveryQueueWriteOffset - BXVD_P_INITIAL_OFFSET_DISPLAY_QUEUE;
718
719      BXVD_AVD_P_GET_QUEUE_DEPTH( uiReadOffset, uiWriteOffset, uiDeliveryQDepth );
720
721      /* Retrieve the read/write offsets for the release queue.
722       * Adjust them to be '0' based.
723       */
724      BXVD_AVD_P_RELEASE_QUEUE_GET_ADDR( hXvdCh, pstReleaseQueue );
725
726      BXVD_AVD_P_RELEASE_QUEUE_GET_READ_OFFSET( hXvdCh, uiReadOffset );
727      BXVD_AVD_P_RELEASE_QUEUE_GET_SHADOW_WRITE_OFFSET( hXvdCh, uiWriteOffset );
728
729      uiReadOffset -= BXVD_P_INITIAL_OFFSET_DISPLAY_QUEUE;
730      uiWriteOffset -= BXVD_P_INITIAL_OFFSET_DISPLAY_QUEUE;
731
732      BXVD_AVD_P_GET_QUEUE_DEPTH( uiReadOffset, uiWriteOffset, uiReleaseQDepth );
733
734      uiUnifiedQDepth = BXVD_Decoder_S_UnifiedQ_GetPictureCount( hXvdCh );
735
736      uiMaskHighWord = uiMaskLowWord = 0;
737      pstUnifiedQueue = &(hXvdCh->stDecoderContext.stUnifiedPictureQueue);
738
739      /* Generate a mask of the Unified Queue elements in use. */
740      for ( i = (BXVD_P_DECODER_PICTURE_QUEUE_DEPTH - 1); i >= 0; i-- )
741      {
742         if ( pstUnifiedQueue->astUnifiedContext[ i ].bInUse )
743         {
744            if ( i > 31 )
745            {
746               uiMaskHighWord |= 1;
747            }
748            else
749            {
750               uiMaskLowWord |= 1;
751            }
752         }
753
754         if ( i > 32 )
755         {
756            uiMaskHighWord <<= 1;
757         }
758         else if ( i < 32 && i > 0 )
759         {
760            uiMaskLowWord <<= 1;
761         }
762      }
763
764      BXVD_DBG_MSG( hXvdCh, ("AVD: %d/%d Dec: %d/%d Dq: %d Rq: %d Uq: %d InUse: %08x%08x",
765                  pstLogData->uiPicturesFromAvd,
766                  pstLogData->uiPicturesToAvd,
767                  pstLogData->uiPicturesToPP,
768                  pstLogData->uiPicturesFromPP,
769                  uiDeliveryQDepth,
770                  uiReleaseQDepth,
771                  uiUnifiedQDepth,
772                  uiMaskHighWord,
773                  uiMaskLowWord
774                  ));
775
776      pstLogData->uiCallbackCount = 0;
777   }
778
779   pstLogData->uiCallbackCount++;
780
781   BDBG_LEAVE( BXVD_Decoder_S_Log_Print );
782
783   return;
784
785}  /* end of BXVD_Decoder_S_Log_Print */
786
787static void BXVD_Decoder_S_OpenChannel(
788   BXVD_ChannelHandle hXvdCh
789   )
790{
791   BDBG_ENTER( BXVD_Decoder_S_OpenChannel );
792
793   hXvdCh->stDecoderContext.bHostSparseMode = false;
794
795   /* Initialize the Unified Picture Queue */
796   BXVD_Decoder_S_UnifiedQ_Initialize( hXvdCh );
797
798   BDBG_LEAVE( BXVD_Decoder_S_OpenChannel );
799
800   return;
801
802}  /* end of BXVD_Decoder_S_OpenChannel */
803
804/*
805 * A wrapper routine to be called by the still picture ISR handler.
806 */
807BERR_Code BXVD_Decoder_P_ComputeAspectRatio(
808   BXVD_P_PPB * pPPB,
809   BXDM_Picture * pstXdmPicture
810   )
811{
812   BDBG_ASSERT( pPPB );
813   BDBG_ASSERT( pstXdmPicture );
814
815   BDBG_ENTER(BXVD_Decoder_P_ComputeAspectRatio);
816
817   BXVD_Decoder_S_ComputeAspectRatio( pPPB, pstXdmPicture, pPPB->protocol );
818
819   BDBG_LEAVE(BXVD_Decoder_P_ComputeAspectRatio);
820
821   return BERR_SUCCESS;
822}
823
824/*
825 *
826 */
827static void BXVD_Decoder_S_ComputeAspectRatio(
828   BXVD_P_PPB * pPPB,
829   BXDM_Picture * pstXdmPicture,
830   BAVC_VideoCompressionStd   eProtocol
831   )
832{
833   BDBG_ENTER(BXVD_Decoder_S_ComputeAspectRatio);
834
835   BDBG_ASSERT( pPPB );
836   BDBG_ASSERT( pstXdmPicture );
837
838   pstXdmPicture->stAspectRatio.uiSampleAspectRatioX = 0;
839   pstXdmPicture->stAspectRatio.uiSampleAspectRatioY = 0;
840
841   switch ( eProtocol )
842   {
843      case BAVC_VideoCompressionStd_eMPEG2:
844      case BAVC_VideoCompressionStd_eMPEG2DTV:
845      case BAVC_VideoCompressionStd_eMPEG2_DSS_PES:
846         /* In MPEG2 streams, the decoder sends a subset of SAR
847          * values (Sample Aspect Ratio).  The subset of SAR values
848          * maps directly to explicit Display Aspect Ratio (DAR)
849          * values that the VDC supports */
850         switch ( pPPB->aspect_ratio )
851         {
852            case BXVD_P_PPB_AspectRatio_eSquare:
853               pstXdmPicture->stAspectRatio.eAspectRatio = BFMT_AspectRatio_eSquarePxl;
854               pstXdmPicture->stAspectRatio.bValid = true;
855               break;
856
857            case BXVD_P_PPB_AspectRatio_e4_3:
858               pstXdmPicture->stAspectRatio.eAspectRatio = BFMT_AspectRatio_e4_3;
859               pstXdmPicture->stAspectRatio.bValid = true;
860               break;
861
862            case BXVD_P_PPB_AspectRatio_e16_9:
863               pstXdmPicture->stAspectRatio.eAspectRatio = BFMT_AspectRatio_e16_9;
864               pstXdmPicture->stAspectRatio.bValid = true;
865               break;
866
867            case BXVD_P_PPB_AspectRatio_e221_1:
868               pstXdmPicture->stAspectRatio.eAspectRatio = BFMT_AspectRatio_e221_1;
869               pstXdmPicture->stAspectRatio.bValid = true;
870               break;
871
872            default:
873               pstXdmPicture->stAspectRatio.bValid = false;
874         }
875         break;
876
877      default:
878         /* In H.264 streams, the decoder sends SAR values (Sample
879          * Aspect Ratio). VDC normally expects DAR values (Display
880          * Aspect Ratio) that are in the MPEG2 streams, so for
881          * H.264, we need to use the BFMT_AspectRatio_eSAR aspect
882          * ratio and set the ratios explicitly */
883
884         if ( BXVD_P_PPB_AspectRatio_eOther == pPPB->aspect_ratio  )
885         {
886            pstXdmPicture->stAspectRatio.eAspectRatio = BFMT_AspectRatio_eSAR;
887            pstXdmPicture->stAspectRatio.uiSampleAspectRatioX = pPPB->custom_aspect_ratio_width_height & 0xFFFF;
888            pstXdmPicture->stAspectRatio.uiSampleAspectRatioY = (pPPB->custom_aspect_ratio_width_height >> 16) & 0xFFFF;
889            pstXdmPicture->stAspectRatio.bValid = true;
890         }
891         else if ( BXVD_P_PPB_AspectRatio_eUnknown == pPPB->aspect_ratio )
892         {
893            pstXdmPicture->stAspectRatio.eAspectRatio = BFMT_AspectRatio_eUnknown;
894            pstXdmPicture->stAspectRatio.uiSampleAspectRatioX = sSampleAspectRatioLUT[pPPB->aspect_ratio].uiSampleAspectRatioX;
895            pstXdmPicture->stAspectRatio.uiSampleAspectRatioY = sSampleAspectRatioLUT[pPPB->aspect_ratio].uiSampleAspectRatioY;
896            pstXdmPicture->stAspectRatio.bValid = true;
897         }
898         else if (( pPPB->aspect_ratio >= BXVD_P_PPB_AspectRatio_eSquare )
899                  && ( pPPB->aspect_ratio <= BXVD_P_PPB_AspectRatio_e221_1 ))
900         {
901            pstXdmPicture->stAspectRatio.eAspectRatio = BFMT_AspectRatio_eSAR;
902            pstXdmPicture->stAspectRatio.uiSampleAspectRatioX = sSampleAspectRatioLUT[pPPB->aspect_ratio].uiSampleAspectRatioX;
903            pstXdmPicture->stAspectRatio.uiSampleAspectRatioY = sSampleAspectRatioLUT[pPPB->aspect_ratio].uiSampleAspectRatioY;
904            pstXdmPicture->stAspectRatio.bValid = true;
905         }
906         else
907         {
908            pstXdmPicture->stAspectRatio.bValid = false;
909         }
910         break;
911   }
912
913   BDBG_LEAVE(BXVD_Decoder_S_ComputeAspectRatio);
914
915} /* end of BXVD_Decoder_S_ComputeAspectRatio() */
916
917static void BXVD_Decoder_S_ComputeDigitalNoiseReduction(
918   BXVD_ChannelHandle hXvdCh,
919   BXVD_P_PPB * pPPB,
920   BXDM_Picture * pUnifiedPicture,
921   BAVC_VideoCompressionStd   eProtocol
922   )
923{
924   bool                  ref_pic_flag;
925   unsigned long         avg_qp_cur;
926   unsigned long         avg_qp_ref;
927   unsigned long         intra_mb_cnt;
928   unsigned long         inter_coded_mb_cnt;
929   unsigned long         total_mb_cnt;
930   unsigned long         intra_low_sum;
931   unsigned long         intra_hi_sum;
932   unsigned long         inter_low_sum;
933   unsigned long         inter_hi_sum;
934
935   unsigned long         act_qp_ref;
936   unsigned long         adj_Qp = 0;
937   unsigned long         intra_default;
938   unsigned long         inter_default;
939
940   signed long           wf1, wf2, sf1, sf2;
941   signed long           var1,var2;
942   signed long           var3,var4,var5,var6;
943   signed long           Quo, Rem, Divd, Divs;
944
945   bool                 p_forwarding;
946   signed long          alpha;
947
948   BDBG_ENTER(BXVD_Decoder_S_ComputeDigitalNoiseReduction);
949
950   BDBG_ASSERT(pPPB);
951   BDBG_ASSERT(pUnifiedPicture);
952
953   if ( NULL == pPPB )
954   {
955      pUnifiedPicture->stDigitalNoiseReduction.bValid = false;
956   }
957   else
958   {
959      pUnifiedPicture->stDigitalNoiseReduction.bValid = true;
960
961      /* Prepare DNR parameters */
962      if (BAVC_VideoCompressionStd_eH264 == eProtocol)
963      {
964         intra_default = BXVD_Decoder_S_DNR_INTRA_DEFAULT_AVC;
965         inter_default = BXVD_Decoder_S_DNR_INTER_DEFAULT_AVC;
966      }
967      else{
968
969         intra_default = BXVD_Decoder_S_DNR_INTRA_DEFAULT;
970         inter_default = BXVD_Decoder_S_DNR_INTER_DEFAULT;
971
972      }
973
974      /* Ref Picture Flag is set if it is I or P picture */
975      if ( (pPPB->dnr.pic_flags & BXVD_P_PPB_DNR_FLAG_REFPIC) == BXVD_P_PPB_DNR_FLAG_REFPIC )
976      {
977         ref_pic_flag = 1;
978      }
979      else
980      {
981         ref_pic_flag = 0;
982      }
983
984      /* Calculate the avg QP for current picture */
985      if ( pPPB->dnr.num_mb_cur != 0 )
986      {
987         /* avg_qp_cur = (pPPB->dnr.sum_qp_cur / pPPB->dnr.num_mb_cur) ;*/
988         Divd = pPPB->dnr.sum_qp_cur;
989         Divs = pPPB->dnr.num_mb_cur;
990
991         if (Divs != 0)
992         {
993            Quo = Divd/Divs;
994         }
995         else
996         {
997            Quo = Divd;
998         }
999
1000         Rem = Divd - (Quo * Divs);
1001
1002         Quo  = BMTH_FIX_SIGNED_ITOFIX(Quo, 26, 5);
1003         Rem  = BMTH_FIX_SIGNED_ITOFIX(Rem, 16, 15);
1004         Divs = BMTH_FIX_SIGNED_ITOFIX(Divs, 31, 0);
1005
1006         if (Divs != 0)
1007         {
1008            avg_qp_cur = BMTH_FIX_SIGNED_DIV(Rem, Divs, 16, 15, 31, 0, 16, 15);
1009            avg_qp_cur = BMTH_FIX_SIGNED_CONVERT(avg_qp_cur, 16, 15, 26, 5);
1010
1011            avg_qp_cur = avg_qp_cur + Quo;
1012         }
1013         else
1014         {
1015            avg_qp_cur = Quo;
1016         }
1017
1018         /* avg_qp_cur (26,5)*/
1019
1020      }
1021      else
1022      {
1023         avg_qp_cur = 0;
1024      }
1025
1026      /* Calculate the avg QP for reference picture */
1027      if ( pPPB->dnr.num_mb_ref != 0 )
1028      {
1029         /*     avg_qp_ref = pPPB->dnr.sum_qp_ref /
1030                pPPB->dnr.num_mb_ref;*/
1031
1032         Divd = pPPB->dnr.sum_qp_ref;
1033         Divs = (pPPB->dnr.num_mb_ref);
1034
1035         if (Divs != 0)
1036         {
1037            Quo = Divd/Divs;
1038         }
1039         else
1040         {
1041            Quo = Divd;
1042         }
1043
1044         Rem = Divd - (Quo * Divs);
1045
1046         Quo  = BMTH_FIX_SIGNED_ITOFIX(Quo, 26, 5);
1047         Rem  = BMTH_FIX_SIGNED_ITOFIX(Rem, 16, 15);
1048         Divs = BMTH_FIX_SIGNED_ITOFIX(Divs, 31, 0);
1049
1050         if (Divs != 0)
1051         {
1052            avg_qp_ref = BMTH_FIX_SIGNED_DIV(Rem, Divs, 16, 15, 31, 0, 16, 15);
1053            avg_qp_ref = BMTH_FIX_SIGNED_CONVERT(avg_qp_cur, 16, 15, 26, 5);
1054
1055            avg_qp_ref = avg_qp_ref + Quo;
1056         }
1057         else
1058         {
1059            avg_qp_ref = Quo;
1060         }
1061
1062         /* avg_qp_ref (26,5) */
1063
1064      }
1065      else
1066      {
1067         avg_qp_ref = 0;
1068      }
1069
1070
1071      /* Extract the intra and inter MB count */
1072      intra_mb_cnt = pPPB->dnr.mb_count_intra_inter >> 16;
1073      inter_coded_mb_cnt = (pPPB->dnr.mb_count_intra_inter & 0xffff);
1074
1075      /* Store the total number of MB in current picture */
1076      total_mb_cnt = pPPB->dnr.num_mb_cur;
1077
1078      /* Extract the Intra sum */
1079      intra_low_sum =  pPPB->dnr.intra_qmat_sum_lo_hi >> 16;
1080      intra_hi_sum = pPPB->dnr.intra_qmat_sum_lo_hi & 0xffff;
1081
1082      /* Extract the Inter sum */
1083      inter_low_sum = pPPB->dnr.inter_qmat_sum_lo_hi >> 16;
1084      inter_hi_sum  = pPPB->dnr.inter_qmat_sum_lo_hi & 0xffff;
1085
1086
1087      /* Initializing few parameters */
1088      p_forwarding = 1;
1089      /* alpha = 0.5; */
1090      alpha = 0x8;      /* Q4 for 0.5 */
1091
1092
1093      if ( (pPPB->dnr.pic_flags & BXVD_P_PPB_DNR_FLAG_GOPHEADER) == BXVD_P_PPB_DNR_FLAG_GOPHEADER )
1094      {
1095         /* PR 36460 : XVD : DM in PI : Reset mechanism of DNR on  */
1096         /* closed GOP and /or video sequence header, is erroneous.*/
1097         /*                                                        */
1098         /* At the beginning of each video sequence or closed GOP  */
1099         /* boundary, old wrong code initializes these variables:  */
1100         /*          adj_Qp_pre = 0;                               */
1101         /*          adj_Qp_ref = 0;                               */
1102         /*                                                        */
1103         /* but the correct reset mechanism is :                   */
1104         /*                                                        */
1105         /* At the beginning of each video sequence or closed GOP  */
1106         /* boundary, initialize these variables:                  */
1107         /*       adj_Qp_pre = adj_Qp;                             */
1108         /*       adj_Qp_ref = 0;                                  */
1109         /*                                                        */
1110         /* hXdmPP->stDMContextState.stDNRInfo.adj_Qp_pre = 0; */
1111         hXvdCh->stDecoderContext.stDNRInfo.adj_Qp_ref = 0;
1112      }
1113
1114      /* To avoid Divided By Zero Exception */
1115      if ( total_mb_cnt == 0 )
1116      {
1117         total_mb_cnt = hXvdCh->stDecoderContext.stDNRInfo.saved_mb_cnt;
1118      }
1119      else
1120      {
1121         hXvdCh->stDecoderContext.stDNRInfo.saved_mb_cnt = total_mb_cnt;
1122      }
1123      if ( (1 == p_forwarding) &&
1124           (0 != hXvdCh->stDecoderContext.stDNRInfo.adj_Qp_ref) )
1125      {
1126         act_qp_ref = hXvdCh->stDecoderContext.stDNRInfo.adj_Qp_ref;
1127      }
1128      else
1129      {
1130         act_qp_ref = avg_qp_ref;
1131      }
1132
1133      if ( ref_pic_flag == 1 )
1134      {
1135         /*     w1 = (float)intra_mb_cnt / (float)total_mb_cnt;
1136                s1 = (float)(intra_low_sum + intra_hi_sum) / BXVD_P_INTRA_DEFAULT;
1137                w2 = (float)inter_coded_mb_cnt / (float)total_mb_cnt;
1138                s2 = (float)(inter_low_sum + inter_hi_sum) / BXVD_P_INTER_DEFAULT;
1139                adj_Qp   = ((float)(w1 * s1 * avg_qp_cur +w2 * s2 * avg_qp_cur +(1 - w1 - w2) * act_qp_ref)+ 0.5);
1140         */
1141
1142         var1 = BMTH_FIX_SIGNED_ITOFIX(intra_mb_cnt, 16, 15);
1143         var2 = BMTH_FIX_SIGNED_ITOFIX(total_mb_cnt, 31, 0);
1144         if ( var2 != 0 )
1145         {
1146            wf1 = BMTH_FIX_SIGNED_DIV(var1, var2, 16, 15, 31, 0, 16, 15) ;
1147         }
1148         else
1149         {
1150            wf1 = var1;
1151         }
1152
1153         var1 = BMTH_FIX_SIGNED_ITOFIX((intra_low_sum + intra_hi_sum), 17, 14);
1154         var2 = BMTH_FIX_SIGNED_ITOFIX(intra_default, 31, 0);
1155         sf1 = BMTH_FIX_SIGNED_DIV(var1, var2, 17, 14, 31, 0, 17, 14) ;
1156
1157         var1 = BMTH_FIX_SIGNED_ITOFIX(inter_coded_mb_cnt, 16, 15);
1158         var2 = BMTH_FIX_SIGNED_ITOFIX(total_mb_cnt, 31, 0);
1159         if ( var2 != 0 )
1160         {
1161            wf2 = BMTH_FIX_SIGNED_DIV(var1, var2, 16, 15, 31, 0, 16, 15) ;
1162         }
1163         else
1164         {
1165            wf2 = var1;
1166         }
1167
1168         var1 = BMTH_FIX_SIGNED_ITOFIX((inter_low_sum + inter_hi_sum), 17, 14);
1169         var2 = BMTH_FIX_SIGNED_ITOFIX(inter_default, 31, 0);
1170         sf2 = BMTH_FIX_SIGNED_DIV(var1, var2, 17, 14, 31, 0, 17, 14) ;
1171
1172         var2 = BMTH_FIX_SIGNED_MUL(wf1, avg_qp_cur, 16, 15, 26, 5, 11, 20);
1173         var2 = BMTH_FIX_SIGNED_CONVERT(var2, 11, 20, 21, 10);
1174         sf1 =  BMTH_FIX_SIGNED_CONVERT(sf1, 17, 14, 21, 10);
1175         var3 = BMTH_FIX_SIGNED_MUL(sf1, var2, 21, 10, 21, 10, 11, 20);
1176
1177         var2 = BMTH_FIX_SIGNED_MUL(wf2, avg_qp_cur, 16, 15, 26, 5, 11, 20);
1178         var2 = BMTH_FIX_SIGNED_CONVERT(var2, 11, 20, 21, 10);
1179         sf2 =  BMTH_FIX_SIGNED_CONVERT(sf2, 17, 14, 21, 10);
1180         var4 = BMTH_FIX_SIGNED_MUL(sf2, var2, 21, 10, 21, 10, 11, 20);
1181
1182         var1 = (wf1 + wf2);
1183         var2 = BMTH_FIX_SIGNED_ITOFIX(1, 16, 15);
1184         var2 = var2 - var1;
1185         var5 = BMTH_FIX_SIGNED_MUL(var2, act_qp_ref, 16, 15, 26, 5, 11, 20);
1186
1187         var6 = var3 + var4 + var5;
1188         var6 = BMTH_FIX_SIGNED_CONVERT(var6, 11, 20, 15, 16);
1189
1190         adj_Qp = var6;
1191
1192         /* hXvdCh->stDecoderContext.stDNRInfo.adj_Qp_ref = adj_Qp; */
1193         hXvdCh->stDecoderContext.stDNRInfo.adj_Qp_ref = BMTH_FIX_SIGNED_CONVERT(adj_Qp, 15, 16, 26, 5);
1194      }
1195      else
1196      {
1197         /* w1 = (float)intra_mb_cnt / (float)total_mb_cnt;
1198            s1 = (float)(intra_low_sum + intra_hi_sum) / BXVD_P_INTRA_DEFAULT;
1199            w2 = (float)inter_coded_mb_cnt / (float)total_mb_cnt;
1200            s2 = (float)(inter_low_sum + inter_hi_sum) / BXVD_P_INTER_DEFAULT;
1201            adj_Qp   = ((float)(w1 * s1 * avg_qp_cur +w2 * s2 * avg_qp_cur +(1 - w1 - w2) * act_qp_ref)+ 0.5);
1202         */
1203         var1 = BMTH_FIX_SIGNED_ITOFIX(intra_mb_cnt, 16, 15);
1204         var2 = BMTH_FIX_SIGNED_ITOFIX(total_mb_cnt, 31, 0);
1205         if ( var2 != 0 )
1206         {
1207            wf1 = BMTH_FIX_SIGNED_DIV(var1, var2, 16, 15, 31, 0, 16, 15) ;
1208         }
1209         else
1210         {
1211            wf1 = var1;
1212         }
1213
1214         var1 = BMTH_FIX_SIGNED_ITOFIX((intra_low_sum + intra_hi_sum), 17, 14);
1215         var2 = BMTH_FIX_SIGNED_ITOFIX(intra_default, 31, 0);
1216         sf1 = BMTH_FIX_SIGNED_DIV(var1, var2, 17, 14, 31, 0, 17, 14) ;
1217
1218         var1 = BMTH_FIX_SIGNED_ITOFIX(inter_coded_mb_cnt, 16, 15);
1219         var2 = BMTH_FIX_SIGNED_ITOFIX(total_mb_cnt, 31, 0);
1220         if ( var2 != 0 )
1221         {
1222            wf2 = BMTH_FIX_SIGNED_DIV(var1, var2, 16, 15, 31, 0, 16, 15) ;
1223         }
1224         else
1225         {
1226            wf2 = var1;
1227         }
1228
1229         var1 = BMTH_FIX_SIGNED_ITOFIX((inter_low_sum + inter_hi_sum), 17, 14);
1230         var2 = BMTH_FIX_SIGNED_ITOFIX(inter_default, 31, 0);
1231         sf2 = BMTH_FIX_SIGNED_DIV(var1, var2, 17, 14, 31, 0, 17, 14) ;
1232
1233         var2 = BMTH_FIX_SIGNED_MUL(wf1, avg_qp_cur, 16, 15, 26, 5, 11, 20);
1234         var2 = BMTH_FIX_SIGNED_CONVERT(var2, 11, 20, 21, 10);
1235         sf1 =  BMTH_FIX_SIGNED_CONVERT(sf1, 17, 14, 21, 10);
1236         var3 = BMTH_FIX_SIGNED_MUL(sf1, var2, 21, 10, 21, 10, 11, 20);
1237
1238         var2 = BMTH_FIX_SIGNED_MUL(wf2, avg_qp_cur, 16, 15, 26, 5, 11, 20);
1239         var2 = BMTH_FIX_SIGNED_CONVERT(var2, 11, 20, 21, 10);
1240         sf2 =  BMTH_FIX_SIGNED_CONVERT(sf2, 17, 14, 21, 10);
1241         var4 = BMTH_FIX_SIGNED_MUL(sf2, var2, 21, 10, 21, 10, 11, 20);
1242
1243         var1 = (wf1 + wf2);
1244         var2 = BMTH_FIX_SIGNED_ITOFIX(1, 16, 15);
1245         var2 = var2 - var1;
1246         var5 = BMTH_FIX_SIGNED_MUL(var2, act_qp_ref, 16, 15, 26, 5, 11, 20);
1247
1248         var6 = var3 + var4 + var5;
1249         var6 = BMTH_FIX_SIGNED_CONVERT(var6, 11, 20, 15, 16);
1250
1251         adj_Qp = var6;
1252      }
1253
1254      /* adj_Qp = (float)(alpha * adj_Qp) + (float)((1 - alpha) * (hXvdCh->stDecoderContext.stDNRInfo.adj_Qp_pre));
1255         hXvdCh->stDecoderContext.stDNRInfo.adj_Qp_pre = adj_Qp;*/
1256
1257      /* PR 36460 : XVD : DM in PI : Reset mechanism of DNR on  */
1258      /* closed GOP and /or video sequence header, is erroneous.*/
1259      /*                                                        */
1260      /* At the beginning of each video sequence or closed GOP  */
1261      /* boundary, old wrong code initializes these variables:  */
1262      /*          adj_Qp_pre = 0;                               */
1263      /*          adj_Qp_ref = 0;                               */
1264      /*                                                        */
1265      /* but the correct reset mechanism is :                   */
1266      /*                                                        */
1267      /* At the beginning of each video sequence or closed GOP  */
1268      /* boundary, initialize these variables:                  */
1269      /*       adj_Qp_pre = adj_Qp;                             */
1270      /*       adj_Qp_ref = 0;                                  */
1271      /*                                                        */
1272      if ( (pPPB->dnr.pic_flags & BXVD_P_PPB_DNR_FLAG_GOPHEADER) == BXVD_P_PPB_DNR_FLAG_GOPHEADER )
1273      {
1274         hXvdCh->stDecoderContext.stDNRInfo.adj_Qp_pre = adj_Qp;
1275      }
1276
1277      var1 = BMTH_FIX_SIGNED_MUL(alpha, adj_Qp, 27, 4, 15, 16, 11, 20);
1278      var2 = BMTH_FIX_SIGNED_CONVERT(1, 31, 0, 27, 4);
1279
1280      var2 = var2-alpha;
1281      var2 = BMTH_FIX_SIGNED_MUL(hXvdCh->stDecoderContext.stDNRInfo.adj_Qp_pre, var2, 15, 16, 27, 4, 11, 20);
1282
1283      adj_Qp = var1 + var2;
1284      hXvdCh->stDecoderContext.stDNRInfo.adj_Qp_pre = BMTH_FIX_SIGNED_CONVERT(adj_Qp, 11, 20, 15, 16);
1285      adj_Qp = BMTH_FIX_SIGNED_FIXTOI(adj_Qp, 11, 20);
1286
1287      pUnifiedPicture->stDigitalNoiseReduction.uiAdjustedQuantizationParameter = adj_Qp;
1288   }
1289
1290   BDBG_LEAVE(BXVD_Decoder_S_ComputeDigitalNoiseReduction);
1291   return;
1292} /* end of BXVD_Decoder_S_ComputeDigitalNoiseReduction() */
1293
1294/********************************************************************************
1295**
1296** Routines for managing the unified queue.
1297**
1298********************************************************************************/
1299
1300static void BXVD_Decoder_S_UnifiedQ_DumpElement(
1301   BXVD_Decoder_P_UnifiedPictureContext * pstUnifiedContext,
1302   bool bDependentPicture
1303   )
1304{
1305   BDBG_ENTER( BXVD_Decoder_S_UnifiedQ_DumpElement );
1306
1307   if ( NULL != pstUnifiedContext )
1308   {
1309      if ( true == bDependentPicture )
1310      {
1311         BXVD_Decoder_S_Printf("\t", NULL );
1312      }
1313
1314      BXVD_Decoder_S_Printf("pUniCntxt: 0x%x index %d pPPB: 0x%x\n",
1315                  pstUnifiedContext,
1316                  pstUnifiedContext->uiIndex,
1317                  pstUnifiedContext->pPPBPhysical
1318                  );
1319
1320      if ( NULL != pstUnifiedContext->pstDependentUniContext )
1321      {
1322         BXVD_Decoder_S_UnifiedQ_DumpElement( pstUnifiedContext->pstDependentUniContext, true );
1323      }
1324   }
1325
1326   BDBG_LEAVE( BXVD_Decoder_S_UnifiedQ_DumpElement );
1327
1328   return;
1329
1330}  /* end of BXVD_Decoder_S_UnifiedQ_DumpElement */
1331
1332static void BXVD_Decoder_S_UnifiedQ_Initialize(
1333   BXVD_ChannelHandle hXvdCh
1334   )
1335{
1336   BXVD_Decoder_P_UnifiedPictureQueue * pstUnifiedQueue;
1337
1338   BDBG_ENTER( BXVD_Decoder_S_UnifiedQ_Initialize );
1339
1340   /*
1341    * Initialize the Unified Picture Queue
1342    */
1343   pstUnifiedQueue = &(hXvdCh->stDecoderContext.stUnifiedPictureQueue);
1344
1345   BKNI_Memset( pstUnifiedQueue, 0, sizeof( BXVD_Decoder_P_UnifiedPictureQueue ) );
1346
1347   pstUnifiedQueue->pstContextTail = &(pstUnifiedQueue->astUnifiedContext[0]);
1348   pstUnifiedQueue->pstContextHead = &(pstUnifiedQueue->astUnifiedContext[0]);
1349
1350   BDBG_LEAVE( BXVD_Decoder_S_UnifiedQ_Initialize );
1351
1352   return;
1353
1354}  /* end of BXVD_Decoder_S_UnifiedQ_Initialize */
1355
1356static void BXVD_Decoder_S_UnifiedQ_InvalidateElement(
1357   BXVD_ChannelHandle hXvdCh,
1358   BXVD_Decoder_P_UnifiedPictureContext * pstUnifiedContext
1359   )
1360{
1361   BDBG_ENTER(BXVD_Decoder_S_UnifiedQ_InvalidateElement);
1362
1363   BDBG_ASSERT(hXvdCh);
1364   BDBG_ASSERT(pstUnifiedContext);
1365
1366   hXvdCh->stDecoderContext.stUnifiedPictureQueue.iNumUsedElements--;
1367
1368   /* The element count should never go below 0.
1369    * If it does, these is a bug in the logic.
1370    */
1371   BDBG_ASSERT(hXvdCh->stDecoderContext.stUnifiedPictureQueue.iNumUsedElements >= 0);
1372
1373   pstUnifiedContext->bInUse = false;
1374
1375   pstUnifiedContext->pstNextUniContext = NULL;
1376   pstUnifiedContext->pstPreviousUniContext = NULL;
1377   pstUnifiedContext->pstDependentUniContext = NULL;
1378
1379   BDBG_LEAVE(BXVD_Decoder_S_UnifiedQ_InvalidateElement);
1380
1381   return;
1382}
1383
1384static void BXVD_Decoder_S_UnifiedQ_ParseSeiFramePackMsg(
1385   BXVD_P_SEI_FramePacking * pstAvdSEIData,
1386   BXDM_Picture_3D * pst3D
1387   )
1388{
1389   /* (SW7405-5135) The H264 specification was not completely rigorous in the definition of the
1390    * "arrangement_cancel" bit in the flags works.  We are assuming that if this bit is set, none
1391    * of the other fields in the message are valid.   This then implies that the picture is a 2D
1392    * picture.  The orientation will be set to "2D" in both the Unified and MFD picture structures.
1393    */
1394   if ( pstAvdSEIData->flags & BXVD_P_PPB_FLAG_SEI_FRAMEPACK_ARRANGEMENT_CANCEL )
1395   {
1396      pst3D->eOrientation = BXDM_Picture_Orientation_e2D;
1397      pst3D->eFrameRelationship = BXDM_Picture_FrameRelationship_eUnknown;
1398      pst3D->uiFrameNum = 0;
1399   }
1400   else 
1401   {
1402      /* Cancel bit is NOT set, parse the message and set the picture
1403       * orientation accordingly.
1404       */
1405      switch( pstAvdSEIData->frame_packing_arrangement_type )
1406      {
1407         case BXVD_P_PPB_SEI_FRAMEPACK_TYPE_CHECKER:
1408            pst3D->eOrientation = BXDM_Picture_Orientation_e3D_Checker;
1409            break;
1410
1411         case BXVD_P_PPB_SEI_FRAMEPACK_TYPE_COLUMN:
1412            pst3D->eOrientation = BXDM_Picture_Orientation_e3D_Column;
1413            break;
1414
1415         case BXVD_P_PPB_SEI_FRAMEPACK_TYPE_ROW:
1416            pst3D->eOrientation = BXDM_Picture_Orientation_e3D_Row;
1417            break;
1418
1419         case BXVD_P_PPB_SEI_FRAMEPACK_TYPE_SIDE_BY_SIDE:
1420            pst3D->eOrientation = BXDM_Picture_Orientation_e3D_SideBySide;
1421            break;
1422
1423         case BXVD_P_PPB_SEI_FRAMEPACK_TYPE_OVER_UNDER:
1424            pst3D->eOrientation = BXDM_Picture_Orientation_e3D_TopBottom;
1425            break;
1426
1427         case BXVD_P_PPB_SEI_FRAMEPACK_TYPE_ALTERNATING:
1428            pst3D->eOrientation = BXDM_Picture_Orientation_e3D_FullFrame;
1429            break;
1430
1431         default:
1432            pst3D->eOrientation = BXDM_Picture_Orientation_e2D;
1433            break;
1434      }
1435
1436      switch( pstAvdSEIData->content_interpretation_type )
1437      {
1438         case BXVD_P_PPB_SEI_FRAMEPACK_INTERPRET_FRAME0_LEFT:
1439            pst3D->eFrameRelationship = BXDM_Picture_FrameRelationship_eFrame0Left;
1440            break;
1441
1442         case BXVD_P_PPB_SEI_FRAMEPACK_INTERPRET_FRAME0_RIGHT:
1443            pst3D->eFrameRelationship = BXDM_Picture_FrameRelationship_eFrame0Right;
1444            break;
1445
1446         case BXVD_P_PPB_SEI_FRAMEPACK_INTERPRET_UNSPECIFIED:
1447         default:
1448            pst3D->eFrameRelationship = BXDM_Picture_FrameRelationship_eUnknown;
1449            break;
1450      }
1451
1452      if ( pstAvdSEIData->flags & BXVD_P_PPB_FLAG_SEI_FRAMEPACK_CURRENT_FRAME_IS_FRAME0 )
1453      {
1454         pst3D->uiFrameNum = 0;
1455      }
1456      else
1457      {
1458         pst3D->uiFrameNum = 1;
1459      }
1460
1461   }     /* end else (cancel bit is not set ) */
1462
1463   return;
1464   
1465}     /* end of BXVD_Decoder_S_UnifiedQ_ParseSeiFramePackMsg() */
1466
1467static void BXVD_Decoder_S_UnifiedQ_ValidatePicture(
1468   BXVD_ChannelHandle hXvdCh,
1469   BXVD_Decoder_P_PictureContext * pstPictureCntxt,
1470   BXVD_Decoder_P_UnifiedPictureContext * pstUnifiedContext,
1471   bool bPictureDropped
1472   )
1473{
1474   bool     bMpegProtocol;
1475   uint32_t uiTemp;
1476   BXVD_P_PPB *   pPPB;
1477   BXDM_Picture * pstXdmPicture;
1478
1479   /* SW7405-4365: local variables to improve performance. */
1480   uint32_t                   uiFlags;
1481   uint32_t                   uiFlagsExt0=0;
1482   BXVD_P_PPB_PullDown        ePulldown;
1483   BAVC_VideoCompressionStd   eProtocol;
1484   BAVC_FrameRateCode         eFrameRate;
1485
1486   BDBG_ENTER(BXVD_Decoder_S_UnifiedQ_ValidatePicture);
1487
1488   BDBG_ASSERT(hXvdCh);
1489   BDBG_ASSERT(pstPictureCntxt);
1490   BDBG_ASSERT(pstUnifiedContext);
1491
1492   pstXdmPicture = &(pstUnifiedContext->stUnifiedPicture);
1493
1494   /* Reset the unified picture */
1495   BKNI_Memset( pstXdmPicture, 0 , sizeof( BXDM_Picture ) );
1496
1497   /* Need to preserve the PPB address for use in BXVD_Decoder_ReleasePicture_isr
1498    * when releasing the picture.
1499    */
1500   BDBG_ASSERT(pstPictureCntxt->stPPB.pPPBPhysical);
1501
1502   pstUnifiedContext->pPPBPhysical = pstPictureCntxt->stPPB.pPPBPhysical;
1503   pstUnifiedContext->pPPB = pstPictureCntxt->stPPB.pPPB;
1504   pstXdmPicture->pPrivateContext = pstUnifiedContext;
1505
1506   BDBG_ASSERT(pstPictureCntxt->stPPB.pPPB);
1507
1508   /* SW7405-4365: Originally this routine was taking 35-40 usec's.  Mapping
1509    * the PPB pointer to a cached address reduced this to ~20 usec's.  However when the
1510    * call to invalidate the cache was added, the execution time was ~26 usec's.
1511    * If the non-cached PPB address is used and the most frequently used PPB elements
1512    * are copied to local variables, the execution time is in the 28-30 usec's range.
1513    * While not the most aesthetic solution, going with the local variables avoids any
1514    * potential performance hit from invalidating the cache for every picture.
1515    */
1516#if 1
1517   pPPB = pstPictureCntxt->stPPB.pPPB;
1518#else
1519   {
1520      /* SW7405-4365: experiment with using a cached PPB address.
1521       * If this code is enabled, handle failures more gracefully.
1522       */
1523      BERR_Code berrCode;
1524
1525      /* Update the PPB pointer to use a cached address. */
1526      berrCode = BMEM_Heap_ConvertAddressToCached(
1527                        hXvdCh->hSystemHeap,
1528                        pstPictureCntxt->stPPB.pPPB,
1529                        (void *)&pPPB
1530                        );
1531
1532      BDBG_ASSERT( !berrCode );
1533
1534      /* The PPB is in shared physical memory.  The MIPS cache has no "knowledge" that
1535       * this memory will be modified by AVD.  To insure coherency, the cache must
1536       * be invalidated.  The MIPS never writes anything to the PPB address, the following
1537       * flush should only be peforming an invalidate not a write back.
1538       */
1539      berrCode = BMEM_Heap_FlushCache(
1540                        hXvdCh->hSystemHeap,
1541                        pPPB,
1542                        sizeof( BXVD_P_PPB )
1543                        );
1544
1545      BDBG_ASSERT( !berrCode );
1546
1547   }
1548#endif
1549
1550   /* SW7405-4365: Copy the most frequently used PPB elements to local variables.
1551    */
1552   uiFlags     = pPPB->flags;
1553   ePulldown   = pPPB->pulldown;
1554   eProtocol   = pPPB->protocol;
1555   eFrameRate  = pPPB->frame_rate;
1556
1557#if BXVD_P_PPB_EXTENDED
1558   uiFlagsExt0 = pPPB->flags_ext0;
1559#else
1560   uiFlagsExt0 = 0;  /* need to avoid a warning on some non-debug builds. */
1561#endif
1562
1563#if BXVD_DECODER_AVD_DEBUG_HELP
1564   BKNI_Printf("%d,%d\n",
1565               pPPB->il_perf_data.decode_cycle_count,
1566               pPPB->il_perf_data.inst_cache_miss);
1567#endif
1568
1569   /***************************/
1570   /* BXDM_Picture_BufferInfo */
1571   /***************************/
1572
1573   /* If a pictureless PPB, the buffer info will not be valid. */
1574   pstXdmPicture->stBufferInfo.bValid = ( uiFlags & BXVD_P_PPB_FLAG_PICTURE_LESS_PPB ) ? false : true ;
1575
1576   /* Set the picture heap */
1577   BDBG_ASSERT(hXvdCh->hPictureHeap);
1578   pstXdmPicture->stBufferInfo.hHeap = hXvdCh->hPictureHeap;
1579
1580   /* pLuminanceFrameBufferAddress */
1581   BMEM_ConvertOffsetToAddress(
1582      pstXdmPicture->stBufferInfo.hHeap,
1583      pPPB->luma_video_address,
1584      &(pstXdmPicture->stBufferInfo.pLumaBufferVirtualAddress)
1585      );
1586
1587   /* pChrominanceFrameBufferAddress */
1588   BMEM_ConvertOffsetToAddress(
1589      pstXdmPicture->stBufferInfo.hHeap,
1590      pPPB->chroma_video_address,
1591      &(pstXdmPicture->stBufferInfo.pChromaBufferVirtualAddress)
1592      );
1593
1594   /* source size */
1595   pstXdmPicture->stBufferInfo.stSource.bValid     = true;
1596   pstXdmPicture->stBufferInfo.stSource.uiWidth    = pPPB->video_width;
1597   pstXdmPicture->stBufferInfo.stSource.uiHeight   = pPPB->video_height;
1598
1599   /* display size
1600    * SWBLURAY-21461: handle MPEG and AVS in a similar manner as VC1.
1601    */
1602   switch ( eProtocol )
1603   {
1604      case BAVC_VideoCompressionStd_eVC1:
1605      case BAVC_VideoCompressionStd_eVC1SimpleMain:
1606         pstXdmPicture->stBufferInfo.stDisplay.bValid    = true;
1607         pstXdmPicture->stBufferInfo.stDisplay.uiWidth   = pPPB->other.vc1.display_horizontal_size;
1608         pstXdmPicture->stBufferInfo.stDisplay.uiHeight  = pPPB->other.vc1.display_vertical_size;
1609         break;
1610
1611      case BAVC_VideoCompressionStd_eMPEG2:
1612      case BAVC_VideoCompressionStd_eMPEG1:
1613      case BAVC_VideoCompressionStd_eMPEG2DTV:
1614      case BAVC_VideoCompressionStd_eMPEG2_DSS_PES:
1615         pstXdmPicture->stBufferInfo.stDisplay.bValid    = true;
1616         pstXdmPicture->stBufferInfo.stDisplay.uiWidth   = pPPB->other.mpeg.display_horizontal_size;
1617         pstXdmPicture->stBufferInfo.stDisplay.uiHeight  = pPPB->other.mpeg.display_vertical_size;
1618         break;
1619
1620      case BAVC_VideoCompressionStd_eAVS:
1621         pstXdmPicture->stBufferInfo.stDisplay.bValid    = true;
1622         pstXdmPicture->stBufferInfo.stDisplay.uiWidth   = pPPB->other.avs.display_horizontal_size;
1623         pstXdmPicture->stBufferInfo.stDisplay.uiHeight  = pPPB->other.avs.display_vertical_size;
1624         break;
1625
1626      /* SWDTV-8681: add support for VP8 display size */
1627      case BAVC_VideoCompressionStd_eVP8:
1628         pstXdmPicture->stBufferInfo.stDisplay.bValid    = true;
1629         pstXdmPicture->stBufferInfo.stDisplay.uiWidth   = pPPB->other.vp8.display_horizontal_size;
1630         pstXdmPicture->stBufferInfo.stDisplay.uiHeight  = pPPB->other.vp8.display_vertical_size;
1631         break;
1632
1633      default:
1634         pstXdmPicture->stBufferInfo.stDisplay.bValid    = false;
1635         pstXdmPicture->stBufferInfo.stDisplay.uiWidth   = 0;
1636         pstXdmPicture->stBufferInfo.stDisplay.uiHeight  = 0;
1637         break;
1638   }
1639
1640   /* BAVC_StripeWidth */
1641   pstXdmPicture->stBufferInfo.eStripeWidth = sAVCStripeWidthLUT[hXvdCh->pXvd->uiDecode_StripeWidth];
1642
1643   /* Number of macroblocks size in the vertical direction
1644    * Should the shift happen here or in the output code?
1645    */
1646   pstXdmPicture->stBufferInfo.uiLumaStripeHeight =   pPPB->luma_stripe_height /* >> 4*/;
1647   pstXdmPicture->stBufferInfo.uiChromaStripeHeight = pPPB->chroma_stripe_height /* >> 4*/;
1648
1649   /* Set the pulldown, start by range check.
1650    * (This is needed in case corrupted data is delivered.)
1651    * TODO: is the range checking appropriate?
1652    * TODO: is BXVD_DMTSM_S_ApplyCDTOverride handled in the Picture Provider?
1653    */
1654   if (( ePulldown > BXVD_P_PPB_PullDown_eFrameX4 )
1655        || ( ePulldown < BXVD_P_PPB_PullDown_eTop ) )
1656   {
1657      pstXdmPicture->stBufferInfo.ePulldown = BXVD_P_PPB_PullDown_eTopBottom;
1658   }
1659   else
1660   {
1661      pstXdmPicture->stBufferInfo.ePulldown = ePulldown;
1662   }
1663
1664   /* SW7601-180: conditionally override TB->TBT and BT->BTB,
1665    * if
1666    * - the application specified "BXVD_MPEGPulldownOverride_eRFF"
1667    * - AND an MPEG stream
1668    * - AND the video decoder set "repeat_first_field"
1669    */
1670   bMpegProtocol = ( BAVC_VideoCompressionStd_eMPEG2 == eProtocol );
1671   bMpegProtocol |= ( BAVC_VideoCompressionStd_eMPEG1 == eProtocol );
1672   bMpegProtocol |= ( BAVC_VideoCompressionStd_eMPEG2DTV == eProtocol );
1673   bMpegProtocol |= ( BAVC_VideoCompressionStd_eMPEG2_DSS_PES == eProtocol );
1674
1675   if ( BXVD_MPEGPulldownOverride_eRFF == hXvdCh->stDecoderContext.ePulldownOverride
1676         && true == bMpegProtocol )
1677   {
1678      if ( 0 != pPPB->other.mpeg.repeat_first_field )
1679      {
1680         switch( pstXdmPicture->stBufferInfo.ePulldown )
1681         {
1682         case BXVD_P_PPB_PullDown_eTopBottom:
1683            pstXdmPicture->stBufferInfo.ePulldown = BXVD_P_PPB_PullDown_eTopBottomTop;
1684            break;
1685
1686         case BXVD_P_PPB_PullDown_eBottomTop:
1687            pstXdmPicture->stBufferInfo.ePulldown = BXVD_P_PPB_PullDown_eBottomTopBottom;
1688            break;
1689
1690         default:
1691            break;
1692         }
1693      }
1694   }
1695
1696   /* Set the chroma location based on the protocol. (PR50994)
1697    * - if:: AVC and the VUI (Video Usability Information) parameters are
1698    * valid, copy the appropriate value from the PPB.
1699    * - else if:: MPEG1, use "BAVC_MpegType_eMpeg1".
1700    * - else:: default to "BAVC_MpegType_eMpeg2".
1701    */
1702    if (( BAVC_VideoCompressionStd_eH264 == eProtocol )
1703         && ( BXVD_P_PPB_H264_VALID_VUI & pPPB->other.h264.valid ))
1704   {
1705      /* If pulldown indicates
1706       * - only a bottom field, use the chroma bottom location
1707       * - an interlaced field, the Picture Provider will need to select the location based on the interrupt polarity
1708       * - only a top field or a frame, use the chroma top location
1709       */
1710      switch( pstXdmPicture->stBufferInfo.ePulldown )
1711      {
1712         case BXVD_P_PPB_PullDown_eBottom:
1713            pstXdmPicture->stBufferInfo.stChromaLocation[BAVC_Polarity_eBotField].eMpegType = pPPB->other.h264.chroma_bottom;
1714            pstXdmPicture->stBufferInfo.stChromaLocation[BAVC_Polarity_eBotField].bValid = true;
1715            break;
1716
1717         case BXVD_P_PPB_PullDown_eTop:
1718            pstXdmPicture->stBufferInfo.stChromaLocation[BAVC_Polarity_eTopField].eMpegType = pPPB->other.h264.chroma_top;
1719            pstXdmPicture->stBufferInfo.stChromaLocation[BAVC_Polarity_eTopField].bValid = true;
1720            break;
1721
1722         case BXVD_P_PPB_PullDown_eTopBottom:
1723         case BXVD_P_PPB_PullDown_eBottomTop:
1724            pstXdmPicture->stBufferInfo.stChromaLocation[BAVC_Polarity_eBotField].eMpegType = pPPB->other.h264.chroma_bottom;
1725            pstXdmPicture->stBufferInfo.stChromaLocation[BAVC_Polarity_eBotField].bValid = true;
1726
1727            pstXdmPicture->stBufferInfo.stChromaLocation[BAVC_Polarity_eTopField].eMpegType = pPPB->other.h264.chroma_top;
1728            pstXdmPicture->stBufferInfo.stChromaLocation[BAVC_Polarity_eTopField].bValid = true;
1729
1730            pstXdmPicture->stBufferInfo.stChromaLocation[BAVC_Polarity_eFrame].eMpegType = pPPB->other.h264.chroma_top;
1731            pstXdmPicture->stBufferInfo.stChromaLocation[BAVC_Polarity_eFrame].bValid = true;
1732            break;
1733
1734         default:
1735            pstXdmPicture->stBufferInfo.stChromaLocation[BAVC_Polarity_eFrame].eMpegType = pPPB->other.h264.chroma_top;
1736            pstXdmPicture->stBufferInfo.stChromaLocation[BAVC_Polarity_eFrame].bValid = true;
1737            break;
1738      }
1739   }
1740   else if ( BAVC_VideoCompressionStd_eMPEG1 == eProtocol )
1741   {
1742      pstXdmPicture->stBufferInfo.stChromaLocation[BAVC_Polarity_eFrame].eMpegType = BAVC_MpegType_eMpeg1;
1743      pstXdmPicture->stBufferInfo.stChromaLocation[BAVC_Polarity_eFrame].bValid = true;
1744   }
1745   else
1746   {
1747      pstXdmPicture->stBufferInfo.stChromaLocation[BAVC_Polarity_eFrame].eMpegType = BAVC_MpegType_eMpeg2;
1748      pstXdmPicture->stBufferInfo.stChromaLocation[BAVC_Polarity_eFrame].bValid = true;
1749   }
1750
1751   /* eYCbCrType, always the same for AVD
1752    * TODO: make this configurable?
1753    */
1754   pstXdmPicture->stBufferInfo.eYCbCrType = BAVC_YCbCrType_e4_2_0;
1755
1756
1757   /* eSourceFormat: from the AVD PPB document
1758    * Bit 3:2
1759    * - Value 00 indicates Progressive Source format
1760    * - Value 01 indicates Interlace Source format
1761    * - Value 1x indicates Unknown Source format
1762    */
1763   uiTemp = ( uiFlags & BXVD_P_PPB_FLAG_EXTRACT_SOURCE_FORMAT_MASK ) >> BXVD_P_PPB_FLAG_EXTRACT_SOURCE_FORMAT_SHIFT;
1764
1765   if ( 0 == uiTemp )
1766   {
1767      pstXdmPicture->stBufferInfo.eSourceFormat = BXDM_Picture_SourceFormat_eProgressive;
1768   }
1769   else if ( 1 == uiTemp )
1770   {
1771      pstXdmPicture->stBufferInfo.eSourceFormat = BXDM_Picture_SourceFormat_eInterlaced;
1772   }
1773   else
1774   {
1775      pstXdmPicture->stBufferInfo.eSourceFormat = BXDM_Picture_SourceFormat_eUnknown;
1776   }
1777
1778   /*************************/
1779   /* BXDM_Picture_Clipping */
1780   /*************************/
1781   if ( BAVC_VideoCompressionStd_eH264 == eProtocol )
1782   {
1783      /* In H264, clipping information may be present, so we need to
1784       * tell VDC to read in the cropped region */
1785      if ( pPPB->other.h264.valid & BXVD_P_PPB_H264_VALID_SPS_CROP )
1786      {
1787         pstXdmPicture->stClipping.bValid = true;
1788         pstXdmPicture->stClipping.uiLeft = (pPPB->other.h264.sps_crop_horiz >> 16) & 0xFFFF;
1789         pstXdmPicture->stClipping.uiRight = pPPB->other.h264.sps_crop_horiz & 0xFFFF;
1790         pstXdmPicture->stClipping.uiTop = (pPPB->other.h264.sps_crop_vert >> 16) & 0xFFFF;
1791         pstXdmPicture->stClipping.uiBottom = pPPB->other.h264.sps_crop_vert & 0xFFFF;
1792      }
1793   }
1794   else if ( BAVC_VideoCompressionStd_eRV9 == eProtocol )
1795   {
1796      /* SWDTV-7795: For RV9, clipping information will always be valid. 
1797       * Set the clipping information so that VDC will crop.
1798       */
1799      pstXdmPicture->stClipping.bValid = true;
1800      pstXdmPicture->stClipping.uiLeft = (pPPB->other.rv9.crop_horiz >> 16) & 0xFFFF;
1801      pstXdmPicture->stClipping.uiRight = pPPB->other.rv9.crop_horiz & 0xFFFF;
1802      pstXdmPicture->stClipping.uiTop = (pPPB->other.rv9.crop_vert >> 16) & 0xFFFF;
1803      pstXdmPicture->stClipping.uiBottom = pPPB->other.rv9.crop_vert & 0xFFFF;
1804   }
1805
1806
1807
1808   /*************************/
1809   /* BXDM_Picture_Protocol */
1810   /*************************/
1811   pstXdmPicture->stProtocol.eProtocol = eProtocol;
1812   pstXdmPicture->stProtocol.eLevel = (( pPPB->profile_level & BXVD_P_PPB_PROTOCOL_LEVEL_MASK ) >> BXVD_P_PPB_PROTOCOL_LEVEL_SHIFT );
1813   pstXdmPicture->stProtocol.eProfile = (( pPPB->profile_level & BXVD_P_PPB_PROTOCOL_PROFILE_MASK ) >> BXVD_P_PPB_PROTOCOL_PROFILE_SHIFT );
1814
1815   /*********************/
1816   /* BXDM_Picture_Type */
1817   /*********************/
1818   switch ( uiFlags & BXVD_P_PPB_FLAG_PICTURE_TYPE_MASK )
1819   {
1820      case BXVD_P_PPB_FLAG_I_PICTURE:
1821         pstXdmPicture->stPictureType.eCoding = BXDM_Picture_Coding_eI;
1822         break;
1823
1824      case BXVD_P_PPB_FLAG_P_PICTURE:
1825         pstXdmPicture->stPictureType.eCoding = BXDM_Picture_Coding_eP;
1826         break;
1827
1828      case BXVD_P_PPB_FLAG_B_PICTURE:
1829         pstXdmPicture->stPictureType.eCoding = BXDM_Picture_Coding_eB;
1830         break;
1831
1832      default:
1833         pstXdmPicture->stPictureType.eCoding = BXDM_Picture_Coding_eUnknown;
1834   }
1835
1836   if ( uiFlags & BXVD_P_PPB_FLAG_PROG_SEQUENCE )
1837   {
1838      pstXdmPicture->stPictureType.eSequence = BXDM_Picture_Sequence_eProgressive;
1839   }
1840   else
1841   {
1842      pstXdmPicture->stPictureType.eSequence = BXDM_Picture_Sequence_eInterlaced;
1843   }
1844
1845   if (uiFlags & BXVD_P_PPB_FLAG_REF_PICTURE)
1846   {
1847      pstXdmPicture->stPictureType.bReference = true;
1848   }
1849
1850   if (uiFlags & BXVD_P_PPB_FLAG_RAP_PICTURE)
1851   {
1852      pstXdmPicture->stPictureType.bRandomAccessPoint = true;
1853   }
1854
1855   switch ( eProtocol )
1856   {
1857      case BAVC_VideoCompressionStd_eMPEG2:
1858      case BAVC_VideoCompressionStd_eMPEG1:
1859      case BAVC_VideoCompressionStd_eMPEG2DTV:
1860      case BAVC_VideoCompressionStd_eMPEG2_DSS_PES:
1861         pstXdmPicture->stPictureType.bLowDelay = (( pPPB->other.mpeg.low_delay_video_format >> 16 ) & 0x3 ) ? true : false;
1862         break;
1863
1864      default:
1865         pstXdmPicture->stPictureType.bLowDelay = false;
1866         break;
1867   }
1868
1869#if BXVD_P_PPB_EXTENDED
1870
1871   /* SW7425-1001: effectively an EOS flag.  Currently defined to
1872    * only be delivered with a "picture-less" PPB.
1873    */
1874   if ( uiFlagsExt0 & BXVD_P_PPB_EXT0_FLAG_LAST_PICTURE )
1875   {
1876      if ( uiFlags & BXVD_P_PPB_FLAG_PICTURE_LESS_PPB ) 
1877      {
1878         pstXdmPicture->stPictureType.bLastPicture = true;
1879      }
1880      else
1881      {
1882         BXVD_DBG_ERR(hXvdCh, ("BXVD_Decoder_S_UnifiedQ_ValidatePicture:: BXVD_P_PPB_EXT0_FLAG_LAST_PICTURE set for a standard PPB"));
1883      }
1884   }
1885#endif
1886
1887   /**********************/
1888   /* BXDM_Picture_Error */
1889   /**********************/
1890   if( uiFlags & BXVD_P_PPB_FLAG_DECODE_ERROR )
1891   {
1892      pstXdmPicture->stError.bThisPicture = true;
1893   }
1894
1895   if( uiFlags & BXVD_P_PPB_FLAG_DECODE_REF_ERROR )
1896   {
1897      pstXdmPicture->stError.bPreviousRefPic = true;
1898   }
1899
1900   /* If the decoder input has overflowed, bump the count. */
1901
1902   if ( uiFlags & BXVD_P_PPB_FLAG_INPUT_OVERFLOW )
1903   {
1904      hXvdCh->stDecoderContext.stCounters.uiDecoderInputOverflow++;
1905   }
1906
1907
1908   /**********************************/
1909   /* BXDM_Picture_PictureOrderCount */
1910   /**********************************/
1911   if ( BAVC_VideoCompressionStd_eH264 == eProtocol )
1912   {
1913      int32_t iPocBottom   = pPPB->other.h264.poc_bottom;
1914      int32_t iPocTop      = pPPB->other.h264.poc_top;
1915
1916      pstXdmPicture->stPOC.uiPictureId = pPPB->other.h264.idr_pic_id;
1917      pstXdmPicture->stPOC.bValid = true;
1918
1919      if ( iPocTop < iPocBottom )
1920      {
1921         pstXdmPicture->stPOC.stPictureOrderCount[BAVC_Polarity_eFrame].iValue = iPocTop;
1922      }
1923      else
1924      {
1925         pstXdmPicture->stPOC.stPictureOrderCount[BAVC_Polarity_eFrame].iValue = iPocBottom;
1926      }
1927      pstXdmPicture->stPOC.stPictureOrderCount[BAVC_Polarity_eFrame].bValid = true;
1928
1929      pstXdmPicture->stPOC.stPictureOrderCount[BAVC_Polarity_eTopField].iValue = iPocTop;
1930      pstXdmPicture->stPOC.stPictureOrderCount[BAVC_Polarity_eTopField].bValid = true;
1931
1932      pstXdmPicture->stPOC.stPictureOrderCount[BAVC_Polarity_eBotField].iValue = iPocBottom;
1933      pstXdmPicture->stPOC.stPictureOrderCount[BAVC_Polarity_eBotField].bValid = true;
1934   }
1935   else if ( BAVC_VideoCompressionStd_eSVC == eProtocol )
1936   {
1937       int32_t iPocBottom   = pPPB->other.svc.poc_bottom;
1938       int32_t iPocTop      = pPPB->other.svc.poc_top;
1939
1940       pstXdmPicture->stPOC.uiPictureId = pPPB->other.svc.idr_pic_id;
1941       pstXdmPicture->stPOC.bValid = true;
1942
1943       if ( iPocTop < iPocBottom )
1944       {
1945          pstXdmPicture->stPOC.stPictureOrderCount[BAVC_Polarity_eFrame].iValue = iPocTop;
1946       }
1947       else
1948       {
1949          pstXdmPicture->stPOC.stPictureOrderCount[BAVC_Polarity_eFrame].iValue = iPocBottom;
1950       }
1951       pstXdmPicture->stPOC.stPictureOrderCount[BAVC_Polarity_eFrame].bValid = true;
1952
1953       pstXdmPicture->stPOC.stPictureOrderCount[BAVC_Polarity_eTopField].iValue = iPocTop;
1954       pstXdmPicture->stPOC.stPictureOrderCount[BAVC_Polarity_eTopField].bValid = true;
1955
1956       pstXdmPicture->stPOC.stPictureOrderCount[BAVC_Polarity_eBotField].iValue = iPocBottom;
1957       pstXdmPicture->stPOC.stPictureOrderCount[BAVC_Polarity_eBotField].bValid = true;
1958   }
1959
1960
1961   /**************************/
1962   /* BXDM_Picture_FrameRate */
1963   /**************************/
1964   if ( eFrameRate == BAVC_FrameRateCode_eUnknown
1965         || eFrameRate > BAVC_FrameRateCode_e7_493
1966      )
1967   {
1968      pstXdmPicture->stFrameRate.bValid = true;
1969
1970      pstXdmPicture->stFrameRate.stRate.uiNumerator = 0;
1971      pstXdmPicture->stFrameRate.stRate.uiDenominator = 0;
1972   }
1973   else
1974   {
1975      pstXdmPicture->stFrameRate.bValid = true;
1976
1977      pstXdmPicture->stFrameRate.stRate = sFrameRateEnumToIntLUT[ eFrameRate ];
1978   }
1979
1980   /* SW3556-836: dereference the fixed_frame_rate_flag */
1981   pstXdmPicture->stFrameRate.eType = ( uiFlags & BXVD_P_PPB_FLAG_FIXED_FRAME_RATE ) ? BXDM_Picture_FrameRateType_eFixed : BXDM_Picture_FrameRateType_eUnknown;
1982
1983   switch ( eProtocol )
1984   {
1985      case BAVC_VideoCompressionStd_eMPEG2:
1986      case BAVC_VideoCompressionStd_eMPEG1:
1987      case BAVC_VideoCompressionStd_eMPEG2DTV:
1988      case BAVC_VideoCompressionStd_eMPEG2_DSS_PES:
1989         /* frame_rate_extension:: [6:5]=frame_rate_extn_n, [4:0]=frame_rate_extn_d */
1990         pstXdmPicture->stFrameRate.stExtension.uiNumerator = (( pPPB->other.mpeg.frame_rate_extension >> 5 ) & 0x3 );
1991         pstXdmPicture->stFrameRate.stExtension.uiDenominator = ( pPPB->other.mpeg.frame_rate_extension & 0x1F );
1992         break;
1993
1994      default:
1995         pstXdmPicture->stFrameRate.stExtension.uiNumerator = 0;
1996         pstXdmPicture->stFrameRate.stExtension.uiDenominator = 0;
1997         break;
1998   }
1999
2000   /********************/
2001   /* BXDM_Picture_PTS */
2002   /********************/
2003   if ( uiFlags & BXVD_P_PPB_FLAG_PTS_PRESENT )
2004   {
2005      pstXdmPicture->stPTS.bValid = true;
2006      pstXdmPicture->stPTS.uiValue = pPPB->pts;;
2007
2008      /* "n_drop" is a running tally from AVD of the number of pictures dropped
2009       * in response to a request from the Picture Provider to drop pictures.
2010       * The "pending drop count" is the difference between the requested number
2011       * and "n_drop".  While the "pending drop count" is non-zero, the Picture
2012       * Provider will run in VSYNC mode.  When it does become zero, the PP will
2013       * switch to TSM mode.  For this reason, we want to hold off reporting the
2014       * "pending drop count" as zero until a coded PTS has been received.  Hence
2015       * this logic to only sample "n_drop" for pictures with a coded PTS.
2016       */
2017      if ( BXVD_Decoder_P_PictureSet_eDependent != pstPictureCntxt->eSetType )
2018      {
2019         hXvdCh->stDecoderContext.uiDropCountSnapshot = pPPB->n_drop;
2020      }
2021   }
2022
2023   /* The drop count for this picture is the one that came with the last coded PTS.
2024    */
2025   pstUnifiedContext->uiDropCount = hXvdCh->stDecoderContext.uiDropCountSnapshot;
2026
2027   /**************************/
2028   /* BXDM_Picture_PCROffset */
2029   /**************************/
2030   if ( uiFlags & BXVD_P_PPB_FLAG_PCR_OFFSET_PRESENT )
2031   {
2032      pstXdmPicture->stPCROffset.bValid = true;
2033      pstXdmPicture->stPCROffset.uiValue = pPPB->pcr_offset;
2034   }
2035
2036   if ( uiFlags & BXVD_P_PPB_FLAG_DISCONT_PCR_OFFSET )
2037   {
2038      pstXdmPicture->stPCROffset.bDiscontinuity = true;
2039   }
2040
2041   /****************************/
2042   /* BXDM_Picture_GopTimeCode */
2043   /****************************/
2044   switch ( eProtocol )
2045   {
2046      case BAVC_VideoCompressionStd_eMPEG2:
2047      case BAVC_VideoCompressionStd_eMPEG1:
2048      case BAVC_VideoCompressionStd_eMPEG2DTV:
2049      case BAVC_VideoCompressionStd_eMPEG2_DSS_PES:
2050         pstXdmPicture->stGOPTimeCode.uiHours = ( pPPB->other.mpeg.gop_time_code & BXVD_P_PPB_MPEG_GOP_HOUR_MASK ) >> BXVD_P_PPB_MPEG_GOP_HOUR_SHIFT;
2051         pstXdmPicture->stGOPTimeCode.uiMinutes = ( pPPB->other.mpeg.gop_time_code & BXVD_P_PPB_MPEG_GOP_MINUTE_MASK ) >> BXVD_P_PPB_MPEG_GOP_MINUTE_SHIFT;
2052         pstXdmPicture->stGOPTimeCode.uiSeconds = ( pPPB->other.mpeg.gop_time_code & BXVD_P_PPB_MPEG_GOP_SECOND_MASK ) >> BXVD_P_PPB_MPEG_GOP_SECOND_SHIFT;
2053         pstXdmPicture->stGOPTimeCode.uiPictures = ( pPPB->other.mpeg.gop_time_code & BXVD_P_PPB_MPEG_GOP_PICTURE_MASK );
2054         pstXdmPicture->stGOPTimeCode.bValid = true;
2055         break;
2056
2057      /* SW7401-4426: Extract the H264 time code. */
2058      case BAVC_VideoCompressionStd_eH264:
2059         pstXdmPicture->stGOPTimeCode.uiHours = ( pPPB->time_code & BXVD_P_PPB_H264_GOP_HOUR_MASK ) >> BXVD_P_PPB_H264_GOP_HOUR_SHIFT;
2060         pstXdmPicture->stGOPTimeCode.uiMinutes = ( pPPB->time_code & BXVD_P_PPB_H264_GOP_MINUTE_MASK ) >> BXVD_P_PPB_H264_GOP_MINUTE_SHIFT;
2061         pstXdmPicture->stGOPTimeCode.uiSeconds = ( pPPB->time_code & BXVD_P_PPB_H264_GOP_SECOND_MASK ) >> BXVD_P_PPB_H264_GOP_SECOND_SHIFT;
2062         pstXdmPicture->stGOPTimeCode.uiPictures = ( pPPB->time_code & BXVD_P_PPB_H264_GOP_PICTURE_MASK );
2063         pstXdmPicture->stGOPTimeCode.bValid = true;
2064         break;
2065
2066      default:
2067         pstXdmPicture->stGOPTimeCode.bValid = false;
2068         break;
2069   }
2070
2071   /********************/
2072   /* BXDM_Picture_Tag */
2073   /********************/
2074   if ( uiFlags & BXVD_P_PPB_FLAG_PIC_TAG_PRESENT )
2075   {
2076      pstXdmPicture->stPictureTag.uiValue = pPPB->picture_tag;
2077      pstXdmPicture->stPictureTag.bValid = true;
2078   }
2079
2080   if ( uiFlags & BXVD_P_PPB_NEW_PIC_TAG_AVAIL )
2081   {
2082      pstXdmPicture->stPictureTag.bNewTagAvailable = true;
2083   }
2084
2085   /***********************/
2086   /* BXDM_Picture_Marker */
2087   /***********************/
2088   pstXdmPicture->stPictureMarker.uiValue = pPPB->timing_marker;
2089   pstXdmPicture->stPictureMarker.bValid = true;
2090
2091   /*************************/
2092   /* BXDM_Picture_Overscan */
2093   /*************************/
2094   /* PR54677: Expose the overscan PPB flags to the app */
2095   pstXdmPicture->stOverscan.bValid = ( uiFlags & BXVD_P_PPB_OVERSCAN_FLAG ) ? true : false;
2096   pstXdmPicture->stOverscan.bOverscanAppropriate = ( uiFlags & BXVD_P_PPB_OVERSCAN_APPROPRIATE_FLAG ) ? true : false;
2097
2098   /****************************/
2099   /* BXDM_Picture_DisplayInfo */
2100   /****************************/
2101   pstXdmPicture->stDisplayInfo.bValid = true;
2102   {
2103      uint8_t uiMatrixCoefficients, uiColorPrimaries, uiTransferCharacteristics;
2104
2105      uiMatrixCoefficients = ((pPPB->display_info >> 24) & 0xFF);
2106      uiColorPrimaries = ((pPPB->display_info >> 16) & 0xFF);
2107      uiTransferCharacteristics = ((pPPB->display_info >> 8) & 0xFF);
2108
2109      /* Set Matrix Coefficients */
2110      if ( uiMatrixCoefficients >= BXVD_DECODER_S_MATRIX_COEFFICIENTS_LUT_SIZE )
2111      {
2112         pstXdmPicture->stDisplayInfo.eMatrixCoefficients = BAVC_MatrixCoefficients_eUnknown;
2113         BXVD_DBG_MSG(hXvdCh, ("Unknown matrix coefficients: %#x", uiMatrixCoefficients));
2114      }
2115      else
2116      {
2117         pstXdmPicture->stDisplayInfo.eMatrixCoefficients = sMatrixCoefficientsLUT[uiMatrixCoefficients];
2118      }
2119
2120      /* Set Color Primaries */
2121      if ( uiColorPrimaries >= BXVD_DECODER_S_COLOR_PRIMARIES_LUT_SIZE )
2122      {
2123         pstXdmPicture->stDisplayInfo.eColorPrimaries = BAVC_ColorPrimaries_eUnknown;
2124         BXVD_DBG_MSG(hXvdCh,("Unknown color primaries: %#x", uiColorPrimaries));
2125      }
2126      else
2127      {
2128         pstXdmPicture->stDisplayInfo.eColorPrimaries = sColorPrimariesLUT[uiColorPrimaries];
2129      }
2130
2131      /* Set Transfer Characteristics */
2132      if ( uiTransferCharacteristics >= BXVD_DECODER_S_TRANSFER_CHARACTERISICS_LUT_SIZE )
2133      {
2134         pstXdmPicture->stDisplayInfo.eTransferCharacteristics = BAVC_TransferCharacteristics_eUnknown;
2135         BXVD_DBG_MSG(hXvdCh,("Unknown transfer characterisics: %#x", uiTransferCharacteristics));
2136      }
2137      else
2138      {
2139         pstXdmPicture->stDisplayInfo.eTransferCharacteristics = sTransferCharacteristicsLUT[uiTransferCharacteristics];
2140      }
2141   }
2142
2143   switch ( eProtocol )
2144   {
2145       case BAVC_VideoCompressionStd_eMPEG2:
2146       case BAVC_VideoCompressionStd_eMPEG1:
2147       case BAVC_VideoCompressionStd_eMPEG2DTV:
2148       case BAVC_VideoCompressionStd_eMPEG2_DSS_PES:
2149         /* low_delay_video_format:: [17:16]=low_delay, [2:0]=video_format */
2150         pstXdmPicture->stDisplayInfo.eVideoFormat = ( pPPB->other.mpeg.low_delay_video_format & 0x7 );
2151         break;
2152
2153       default:
2154          pstXdmPicture->stDisplayInfo.eVideoFormat = BXDM_Picture_VideoFormat_eUnknown;
2155          break;
2156   }
2157
2158   /************************/
2159   /* BXDM_Picture_PanScan */
2160   /************************/
2161   switch ( eProtocol )
2162   {
2163      case BAVC_VideoCompressionStd_eMPEG2:
2164      case BAVC_VideoCompressionStd_eMPEG1:
2165      case BAVC_VideoCompressionStd_eMPEG2DTV:
2166      case BAVC_VideoCompressionStd_eMPEG2_DSS_PES:
2167      {
2168         if ( pPPB->other.mpeg.offset_count > 0 )
2169         {
2170            uint32_t uiPanScanIndex;
2171
2172            pstXdmPicture->stPanScan.uiCount = pPPB->other.mpeg.offset_count;
2173
2174            for ( uiPanScanIndex = 0; uiPanScanIndex < pstXdmPicture->stPanScan.uiCount; uiPanScanIndex++ )
2175            {
2176               pstXdmPicture->stPanScan.stVector[uiPanScanIndex].eType = BXDM_Picture_PanScanVectorType_eSourceWindow;
2177               pstXdmPicture->stPanScan.stVector[uiPanScanIndex].iHorizontal = pPPB->other.mpeg.horizontal_offset[uiPanScanIndex];
2178               pstXdmPicture->stPanScan.stVector[uiPanScanIndex].iVertical = pPPB->other.mpeg.vertical_offset[uiPanScanIndex];
2179               pstXdmPicture->stPanScan.stVector[uiPanScanIndex].uiWidth = pPPB->other.mpeg.display_horizontal_size;
2180               pstXdmPicture->stPanScan.stVector[uiPanScanIndex].uiHeight = pPPB->other.mpeg.display_vertical_size;
2181            }
2182         }
2183      }
2184      break;
2185
2186      case BAVC_VideoCompressionStd_eH264:
2187      {
2188         if ( pPPB->other.h264.valid & BXVD_P_PPB_H264_VALID_PANSCAN )
2189         {
2190            int16_t iLeftOffset, iRightOffset, iTopOffset, iBottomOffset;
2191
2192            /* Determine pan-scan index. According to H264 spec, the 3
2193             * sets of pan-scan values are used depending on which field
2194             * of the frame is displayed. When
2195             * BXVD_P_PPB.other.BXVD_P_PPB_H264.pan_scan_count is 1, then
2196             * the one set of values is valid for all fields displayed of
2197             * the current frame. Otherwise, the index of the values map
2198             * to the field that is displayed. In 3:2 pull-down cases,
2199             * there should be 3 values for frames which are displayed
2200             * for 3 fields. */
2201            if ( pPPB->other.h264.pan_scan_count > 0 )
2202            {
2203               uint32_t uiPanScanIndex;
2204
2205               pstXdmPicture->stPanScan.uiCount = pPPB->other.h264.pan_scan_count;
2206
2207               for ( uiPanScanIndex = 0; uiPanScanIndex < pstXdmPicture->stPanScan.uiCount; uiPanScanIndex++ )
2208               {
2209                  iLeftOffset = (int16_t) ((pPPB->other.h264.pan_scan_horiz[uiPanScanIndex] >> 16) & 0xFFFF);
2210                  iRightOffset = (int16_t) (pPPB->other.h264.pan_scan_horiz[uiPanScanIndex] & 0xFFFF);
2211                  iTopOffset = (int16_t) ((pPPB->other.h264.pan_scan_vert[uiPanScanIndex] >> 16) & 0xFFFF);
2212                  iBottomOffset = (int16_t) (pPPB->other.h264.pan_scan_vert[uiPanScanIndex] & 0xFFFF);
2213                  pstXdmPicture->stPanScan.stVector[uiPanScanIndex].eType = BXDM_Picture_PanScanVectorType_eSourceCrop;
2214                  pstXdmPicture->stPanScan.stVector[uiPanScanIndex].iHorizontal = -(iLeftOffset + iRightOffset)/2;
2215                  pstXdmPicture->stPanScan.stVector[uiPanScanIndex].iVertical = -(iTopOffset + iBottomOffset)/2;
2216                  pstXdmPicture->stPanScan.stVector[uiPanScanIndex].uiWidth = ((iLeftOffset - iRightOffset) >> 4);
2217                  pstXdmPicture->stPanScan.stVector[uiPanScanIndex].uiHeight = ((iTopOffset - iBottomOffset) >> 4);
2218               }
2219            }
2220         }
2221      }
2222      break;
2223
2224      case BAVC_VideoCompressionStd_eVC1:
2225      case BAVC_VideoCompressionStd_eVC1SimpleMain:
2226      {
2227         if ( uiFlags & BXVD_P_PPB_VC1_VALID_PANSCAN )
2228         {
2229            int32_t iDisplayHorizontalCenterSP, iDisplayVerticalCenterSP, iPanScanHorizontalCenterSP, iPanScanVerticalCenterSP;
2230            uint32_t uiPanScanWidth, uiPanScanHeight;
2231
2232            /* Determine pan-scan index. According to VC1 spec, the 4
2233             * sets of pan-scan values are used depending on which field
2234             * of the frame is displayed. When
2235             * BXVD_P_PPB.other.BXVD_P_PPB_VC1.num_panscan_windows is 1,
2236             * then the one set of values is valid for all fields
2237             * displayed of the current frame. Otherwise, the index of
2238             * the values map to the field that is displayed. In 3:2
2239             * pull-down cases, there should be 3 values for frames which
2240             * are displayed for 3 fields. */
2241            if ( pPPB->other.vc1.num_panscan_windows > 0 )
2242            {
2243               uint32_t uiPanScanIndex;
2244
2245               pstXdmPicture->stPanScan.uiCount = pPPB->other.vc1.num_panscan_windows;
2246
2247               for ( uiPanScanIndex = 0; uiPanScanIndex < pstXdmPicture->stPanScan.uiCount; uiPanScanIndex++ )
2248               {
2249                  /* Note: VC1 pan scan values are relative to the
2250                   * _display_ size and NOT the _source_ size.  VDC
2251                   * requires the latter, so we need to scale the
2252                   * values accordingly.
2253                   *
2254                   * The offsets define the upper left corner of the
2255                   * pan scan rectange, and NOT the offset from
2256                   * center, so we need to calculate the center offset
2257                   * first.
2258                   *
2259                   * The offsets are in sub pixel precision but the
2260                   * dimensions are in pixel precision, so we need to
2261                   * convert accordingly.
2262                  */
2263
2264                  /* Calculate center coordinates relative to the
2265                   * display region using 1/16 sub pixel prevision.
2266                   * We need to multiply by 16 to get sub-pixel
2267                   * precision and then divide by 2 to get the center,
2268                   * hence the resulting left shift of 3 */
2269                  iDisplayHorizontalCenterSP = pPPB->other.vc1.display_horizontal_size << 3;
2270                  iDisplayVerticalCenterSP = pPPB->other.vc1.display_vertical_size << 3;
2271                  uiPanScanWidth = (pPPB->other.vc1.ps_horiz_offset_width[uiPanScanIndex] & 0x3FFF);
2272                  uiPanScanHeight = (pPPB->other.vc1.ps_vert_offset_height[uiPanScanIndex] & 0x3FFF);
2273                  iPanScanHorizontalCenterSP = ((pPPB->other.vc1.ps_horiz_offset_width[uiPanScanIndex] >> 14) & 0x3FFFF) + (uiPanScanWidth << 3);
2274                  iPanScanVerticalCenterSP = ((pPPB->other.vc1.ps_vert_offset_height[uiPanScanIndex] >> 14) & 0x3FFFF) + (uiPanScanHeight << 3);
2275
2276                  pstXdmPicture->stPanScan.stVector[uiPanScanIndex].eType = BXDM_Picture_PanScanVectorType_eDisplayWindow;
2277                  pstXdmPicture->stPanScan.stVector[uiPanScanIndex].iHorizontal = (iPanScanHorizontalCenterSP - iDisplayHorizontalCenterSP);
2278                  pstXdmPicture->stPanScan.stVector[uiPanScanIndex].iVertical = (iPanScanVerticalCenterSP - iDisplayVerticalCenterSP);
2279                  pstXdmPicture->stPanScan.stVector[uiPanScanIndex].uiWidth = uiPanScanWidth;
2280                  pstXdmPicture->stPanScan.stVector[uiPanScanIndex].uiHeight = uiPanScanHeight;
2281               }
2282            }
2283         }
2284      }
2285      break;
2286
2287      case BAVC_VideoCompressionStd_eAVS:
2288      {
2289         if ( pPPB->other.avs.offset_count > 0 )
2290         {
2291            uint32_t uiPanScanIndex;
2292
2293            pstXdmPicture->stPanScan.uiCount = pPPB->other.avs.offset_count;
2294
2295            for ( uiPanScanIndex = 0; uiPanScanIndex < pstXdmPicture->stPanScan.uiCount; uiPanScanIndex++ )
2296            {
2297               pstXdmPicture->stPanScan.stVector[uiPanScanIndex].eType = BXDM_Picture_PanScanVectorType_eSourceWindow;
2298               pstXdmPicture->stPanScan.stVector[uiPanScanIndex].iHorizontal = pPPB->other.avs.horizontal_offset[uiPanScanIndex];
2299               pstXdmPicture->stPanScan.stVector[uiPanScanIndex].iVertical = pPPB->other.avs.vertical_offset[uiPanScanIndex];
2300               pstXdmPicture->stPanScan.stVector[uiPanScanIndex].uiWidth = pPPB->other.avs.display_horizontal_size;
2301               pstXdmPicture->stPanScan.stVector[uiPanScanIndex].uiHeight = pPPB->other.avs.display_vertical_size;
2302            }
2303         }
2304      }
2305      break;
2306
2307      default:
2308         break;
2309   }
2310
2311   /****************************/
2312   /* BXDM_Picture_AspectRatio */
2313   /****************************/
2314   BXVD_Decoder_S_ComputeAspectRatio(
2315            pPPB,
2316            pstXdmPicture,
2317            eProtocol );
2318
2319   /**************************************/
2320   /* BXDM_Picture_DigitalNoiseReduction */
2321   /**************************************/
2322   BXVD_Decoder_S_ComputeDigitalNoiseReduction(
2323            hXvdCh,
2324            pPPB,
2325            pstXdmPicture,
2326            eProtocol );
2327
2328   /* BXDM_Picture_RangeRemapping */
2329   switch ( eProtocol )
2330   {
2331      case BAVC_VideoCompressionStd_eVC1:
2332      case BAVC_VideoCompressionStd_eVC1SimpleMain:
2333         pstXdmPicture->stRangeRemapping.bValid = true;
2334         pstXdmPicture->stRangeRemapping.uiLuma = (pPPB->other.vc1.range_remapping_ratio >> 16) & 0xFFFF;
2335         pstXdmPicture->stRangeRemapping.uiChroma = pPPB->other.vc1.range_remapping_ratio & 0xFFFF;
2336         break;
2337
2338      default:
2339         pstXdmPicture->stRangeRemapping.bValid = false;
2340         break;
2341   }
2342
2343   /****************************************/
2344   /* BXDM_Picture_ActiveFormatDescription */
2345   /****************************************/
2346   if ( uiFlags & BXVD_P_PPB_FLAG_AFD_VALID )
2347   {
2348      pstXdmPicture->stActiveFormatDescription.bValid = true;
2349      pstXdmPicture->stActiveFormatDescription.uiValue = pPPB->afd_val;
2350   }
2351   else
2352   {
2353      pstXdmPicture->stActiveFormatDescription.bValid = false;
2354   }
2355
2356   /************************/
2357   /* BXDM_Picture_BarData */
2358   /************************/
2359
2360   /* SW7425-2247: support for bar data */
2361   if ( pPPB->bar_data & BXVD_P_PPB_BAR_DATA_FLAG_VALID )
2362   {
2363      pstXdmPicture->stBarData.eBarDataType = 
2364         ( pPPB->bar_data & BXVD_P_PPB_BAR_DATA_FLAG_TOP_BOTTOM ) ? BAVC_BarDataType_eTopBottom : BAVC_BarDataType_eLeftRight ;
2365
2366      pstXdmPicture->stBarData.uiTopLeftBarValue  = ( pPPB->bar_data & BXVD_P_PPB_BAR_DATA_TOP_LEFT_MASK ) >> BXVD_P_PPB_BAR_DATA_TOP_LEFT_SHIFT ;
2367      pstXdmPicture->stBarData.uiBotRightBarValue = ( pPPB->bar_data & BXVD_P_PPB_BAR_DATA_BOT_RIGHT_MASK ) >> BXVD_P_PPB_BAR_DATA_BOT_RIGHT_SHIFT ;
2368   }
2369   else
2370   {
2371      pstXdmPicture->stBarData.eBarDataType = BAVC_BarDataType_eInvalid;
2372   }
2373
2374   /**********************/
2375   /* BXDM_Picture_Stats */
2376   /**********************/
2377   pstXdmPicture->stStats.stMacroBlockCount.bValid = true;
2378   pstXdmPicture->stStats.stMacroBlockCount.uiInterCoded = ( pPPB->dnr.mb_count_intra_inter >> 16 );
2379   pstXdmPicture->stStats.stMacroBlockCount.uiIntraCoded = ( pPPB->dnr.mb_count_intra_inter & 0xffff );
2380   pstXdmPicture->stStats.stMacroBlockCount.uiTotal = pPPB->dnr.num_mb_cur;
2381
2382   if ( BAVC_VideoCompressionStd_eMPEG2 == eProtocol
2383        || BAVC_VideoCompressionStd_eMPEG1 == eProtocol
2384        || BAVC_VideoCompressionStd_eMPEG2DTV == eProtocol
2385        || BAVC_VideoCompressionStd_eMPEG2_DSS_PES  == eProtocol
2386       )
2387   {
2388      pstXdmPicture->stStats.uiBitRate = pPPB->other.mpeg.bit_rate_value;
2389   }
2390
2391   pstXdmPicture->stStats.uiDeltaPicturesSeen = pstUnifiedContext->pPPB->delta_pic_seen;
2392
2393   /* Use a pre-increment so that the serial numbers start at '1' instead of '0'. */
2394   pstXdmPicture->uiSerialNumber = ++hXvdCh->uiPPBSerialNumber;
2395
2396   /************/
2397   /* CRC Mode */
2398   /************/
2399   if ( true == hXvdCh->stDecoderContext.bCRCMode )
2400   {
2401      switch ( uiFlags & BXVD_P_PPB_FLAG_BUFFER_TYPE_MASK)
2402      {
2403         case BXVD_P_PPB_FLAG_FRAME:
2404            pstXdmPicture->stBufferInfo.ePulldown = BXDM_Picture_PullDown_eFrameX1;
2405            pstXdmPicture->stBufferInfo.eSourceFormat = BXDM_Picture_SourceFormat_eProgressive;
2406            pstXdmPicture->stPictureType.eSequence = BXDM_Picture_Sequence_eProgressive;
2407            break;
2408
2409         case BXVD_P_PPB_FLAG_FIELDPAIR:
2410            pstXdmPicture->stBufferInfo.ePulldown = BXDM_Picture_PullDown_eTopBottom;
2411            pstXdmPicture->stBufferInfo.eSourceFormat = BXDM_Picture_SourceFormat_eInterlaced;
2412            pstXdmPicture->stPictureType.eSequence = BXDM_Picture_Sequence_eInterlaced;
2413            break;
2414
2415         case BXVD_P_PPB_FLAG_TOPFIELD:
2416            pstXdmPicture->stBufferInfo.ePulldown = BXDM_Picture_PullDown_eTop;
2417            pstXdmPicture->stBufferInfo.eSourceFormat = BXDM_Picture_SourceFormat_eInterlaced;
2418            pstXdmPicture->stPictureType.eSequence = BXDM_Picture_Sequence_eInterlaced;
2419            break;
2420
2421         case BXVD_P_PPB_FLAG_BOTTOMFIELD:
2422            pstXdmPicture->stBufferInfo.ePulldown = BXDM_Picture_PullDown_eBottom;
2423            pstXdmPicture->stBufferInfo.eSourceFormat = BXDM_Picture_SourceFormat_eInterlaced;
2424            pstXdmPicture->stPictureType.eSequence = BXDM_Picture_Sequence_eInterlaced;
2425            break;
2426      }
2427   }
2428
2429   /* Linked list of dependent unified pictures
2430    * TODO: add error checking for type and pointers?
2431    * That was the motivation for saving the settype and count.
2432    */
2433   pstUnifiedContext->eSetType = pstPictureCntxt->eSetType;
2434   pstUnifiedContext->uiSetCount = pstPictureCntxt->uiSetCount;
2435
2436   /* validate any linked dependent pictures.
2437    */
2438   if ( NULL != pstPictureCntxt->pDependentPicture )
2439   {
2440      BXVD_Decoder_S_UnifiedQ_AddPicture( hXvdCh, pstPictureCntxt->pDependentPicture, false );
2441   }
2442
2443#if 0
2444   /* for debug */
2445   pstUnifiedContext->eSetType = BXVD_Decoder_P_PictureSet_eSingle;
2446   pstUnifiedContext->uiSetCount = 1;
2447#endif
2448
2449   /* link the dependent unified picture to the preceeding picture
2450    * Currently we only support picture sets of 2, the preceeding
2451    * picture should be a base picture.
2452    *
2453    * SW7425-609: With a MVC stream, it is possible to startup on the dependent
2454    * (enhanced) picture.   This is an error condition and the picture will be dropped. 
2455    * The twist here is that preceding picture context will not have been validated,
2456    * i.e. pstPreviousUniContext will be NULL.  Why is this routine being executed
2457    * if the picture is going to be dropped?  For debug, solely to fill in the
2458    * Unified Picture structure and then call BXVD_DecoderDbg_P_PrintUnifiedPicture. 
2459    * To avoid a crash if pstPreviousUniContext is NULL, check " bPictureDropped"
2460    * in the following "if" statement.
2461    */
2462   if ( BXVD_Decoder_P_PictureSet_eDependent == pstUnifiedContext->eSetType
2463         && false == bPictureDropped
2464      )
2465   {
2466      /* Link the unified pictures for use by XDM... */
2467      pstUnifiedContext->pstPreviousUniContext->stUnifiedPicture.pNextPicture = pstXdmPicture;
2468
2469      /* Link the picture context's for use by the decoder. */
2470      pstUnifiedContext->pstPreviousUniContext->pstDependentUniContext = pstUnifiedContext;
2471
2472      /* The error handling logic only looks at the base picture.  Conditionally
2473       * set the error bits on the base picture.
2474       */
2475      if( true == pstXdmPicture->stError.bThisPicture )
2476      {
2477          pstUnifiedContext->pstPreviousUniContext->stUnifiedPicture.stError.bThisPicture = true;
2478      }
2479
2480      if( true == pstXdmPicture->stError.bPreviousRefPic )
2481      {
2482         pstUnifiedContext->pstPreviousUniContext->stUnifiedPicture.stError.bPreviousRefPic = true;
2483      }
2484
2485      /* Link the dependent extension data to the base.  This will allow an application
2486       * to access both blocks of data in the ePictureExtensionData callback.
2487       */
2488      pstUnifiedContext->pstPreviousUniContext->stUnifiedPicture.stExtensionInfo.pNext = 
2489                                                &(pstUnifiedContext->stUnifiedPicture.stExtensionInfo);
2490     
2491   }
2492
2493   /******************************/
2494   /* BXDM_Picture_ExtensionInfo */
2495   /* BXDM_Picture_3D            */
2496   /******************************/
2497
2498   /* default to a 2D picture. */
2499   pstXdmPicture->st3D.eOrientation = BXDM_Picture_Orientation_e2D;
2500   pstXdmPicture->st3D.eFrameRelationship = BXDM_Picture_FrameRelationship_eUnknown;
2501
2502
2503   /* SW7405-3996: add support for SEI frame packing. */
2504   if ( BAVC_VideoCompressionStd_eH264 == eProtocol
2505         || BAVC_VideoCompressionStd_eMVC == eProtocol
2506      )
2507   {
2508      uint32_t             uiSEIOffset=0;
2509      BXVD_P_SEI_Message * pSEIMessage;
2510      uint32_t             uiSerialNumber = pstXdmPicture->uiSerialNumber; /* For debug. */
2511
2512      if ( BAVC_VideoCompressionStd_eH264 == eProtocol )
2513      {
2514         /* Check for an SEI message on a single picture. */
2515
2516         uiSEIOffset = (uint32_t)pPPB->other.h264.pstSEIMessageOffset;
2517      }
2518      else if ( BAVC_VideoCompressionStd_eMVC == eProtocol
2519                && BXVD_Decoder_P_PictureSet_eBase == pstUnifiedContext->eSetType
2520                && NULL != pstPictureCntxt->pDependentPicture
2521               )
2522      {
2523         /* This case is for retrieving graphics offsets which might be delivered in an MVC stream.
2524          * The offsets are delivered by AVD with the dependent (or extended) pictures.
2525          * The middleware is expecting the offsets to be bound to the base pictures.
2526          * We hold off parsing these messages until this routine is finishing up with the base picture.
2527          * Note: this routine is called recursively.  The preceding call to "BXVD_Decoder_S_UnifiedQ_AddPicture"
2528          * will have processed the dependent/extended picture.
2529          */
2530         uiSEIOffset = (uint32_t)pstPictureCntxt->pDependentPicture->stPPB.pPPB->other.h264.pstSEIMessageOffset;
2531
2532         /* For debug. */
2533         if ( pstXdmPicture->pNextPicture )
2534         {
2535            uiSerialNumber = ((BXDM_Picture *)(pstXdmPicture->pNextPicture))->uiSerialNumber;
2536         }
2537
2538#if BXVD_LEGACY_MVC_SUPPORT
2539         /* SW7422-72: to support the original MVC behavior on the older DVD chips, mark the set as
2540          * full frame 3D with frame 0 as the left image.  On newer chips, the application/middleware
2541          * will need to call "BXDM_PictureProvider_Set3D_isr()" to specify the orientation.  If this
2542          * call is not made, XDM will deliver the content as 2D to VDC.
2543          */
2544         pstXdmPicture->st3D.eOrientation = BXDM_Picture_Orientation_e3D_FullFrame;
2545         pstXdmPicture->st3D.eFrameRelationship = BXDM_Picture_FrameRelationship_eFrame0Left;
2546#endif
2547      }
2548
2549      while ( 0 != uiSEIOffset )
2550      {
2551         BXDM_Picture_ExtensionData * pstExtensionData;
2552         uint32_t uiIndex;
2553
2554         if ( pstXdmPicture->stExtensionInfo.uiCount >= BXDM_MAX_PICTURE_EXTENSION_INFO )
2555         {
2556            BXVD_DBG_ERR(hXvdCh, ("BXVD_Decoder_S_UnifiedQ_ValidatePicture:: number of SEI messages is greater than BXDM_MAX_PICTURE_EXTENSION_INFO"));
2557            break;
2558         }
2559
2560
2561         /* Convert the BXVD_P_SEI_Message offset to a virtual address. */
2562         BMEM_ConvertOffsetToAddress(
2563            hXvdCh->hSystemHeap,
2564            uiSEIOffset,
2565            (void *)&( pSEIMessage )
2566            );
2567
2568         switch( pSEIMessage->uiMsgType )
2569         {
2570            case BXVD_P_PPB_SEI_MSG_FRAMEPACKING:
2571            {
2572               /* Needed pstAvdSEIData to prevent the compiler warning
2573                * "dereferencing type-punned pointer will break strict-aliasing rules"
2574                */
2575               BXVD_P_SEI_FramePacking * pstAvdSEIData = (BXVD_P_SEI_FramePacking *)&(pSEIMessage->data.stSEIFramePacking);
2576
2577               /* Dereference the offset data. */
2578               uiIndex = pstXdmPicture->stExtensionInfo.uiCount;
2579               pstExtensionData = &(pstXdmPicture->stExtensionInfo.astExtensionData[uiIndex]);
2580
2581               /* Set the appropriate values. */
2582               pstExtensionData->eType = BXDM_Picture_ExtensionType_eSEIMsg_FramePacking;
2583               pstExtensionData->data.stSEIFramePacking.pstSeiData = (BXDM_Picture_Extension_SEIFramePacking *)pstAvdSEIData;
2584
2585               if ( uiFlags & BXVD_P_PPB_FLAG_NEW_SEI_MSG )
2586               {
2587                  pstExtensionData->data.stSEIFramePacking.uiFlags = BXDM_PICTURE_SEIMSG_FRAMEPACK_NEW_MESSAGE_FLAG;
2588               }
2589
2590               /* For 3D, fill in the pstXdmPicture->st3D.eOrientation
2591                * and pstXdmPicture->st3D.eFrameRelationship fields.
2592                */
2593               BXVD_Decoder_S_UnifiedQ_ParseSeiFramePackMsg( pstAvdSEIData, &(pstXdmPicture->st3D) );
2594
2595               /* Conditionally print the SEI message */
2596               BXVD_DecoderDbg_P_PrintSeiMessage( hXvdCh, pSEIMessage, uiSerialNumber );
2597
2598               /* Bump the extension count.*/
2599               pstXdmPicture->stExtensionInfo.uiCount++;
2600               break;
2601            }
2602
2603            case BXVD_P_PPB_SEI_MSG_MVC_GRAPHICS_OFFSET:
2604            {
2605
2606               /* NOTE: This code only grabs data from the first dependent picture.
2607                * Perhaps that is all we will need.
2608                */
2609               BXVD_P_MVC_Offset_Meta * pMetaData = (BXVD_P_MVC_Offset_Meta *)&(pSEIMessage->data.stOffsetMeta);
2610
2611               /* Dereference the offset data. */
2612               uiIndex = pstXdmPicture->stExtensionInfo.uiCount;
2613               pstExtensionData = &(pstXdmPicture->stExtensionInfo.astExtensionData[uiIndex]);
2614
2615
2616               /* Set the appropriate values. */
2617               pstExtensionData->eType = BXDM_Picture_ExtensionType_eBluRay3DGraphicsOffset;
2618               pstExtensionData->data.stBluRay3DGraphicsOffset.uiCount = pMetaData->size;
2619               pstExtensionData->data.stBluRay3DGraphicsOffset.puiOffsetData = &(pMetaData->offset[0]);
2620
2621               /* Conditionally print the SEI message */
2622               BXVD_DecoderDbg_P_PrintSeiMessage( hXvdCh, pSEIMessage, uiSerialNumber );
2623
2624               /* Bump the extension count.*/
2625               pstXdmPicture->stExtensionInfo.uiCount++;
2626               break;
2627            }
2628
2629            default:
2630               BXVD_DBG_ERR(hXvdCh, ("BXVD_Decoder_S_UnifiedQ_ValidatePicture:: invalid SEI message type %d", pSEIMessage->uiMsgType ));
2631               break;
2632         }
2633
2634         /* Check for another message. Note: while there are provisions to support multiple
2635          * messages per PPB, the current thinking is that this will not happen.
2636          */
2637         uiSEIOffset = (uint32_t)pSEIMessage->pstNextSEIMsgOffset;
2638
2639      }  /* end of while ( 0 != uiSEIOffset )            */
2640   }     /* end of if ( BAVC_VideoCompressionStd_eH264 ) */
2641
2642
2643   /* Conditionally print the Unified Picture.
2644    * If this is the 2nd picture of a pair of pictures, hold off printing until we hit
2645    * this point for the 1st (base) picture of the pair.  However if the picture is being
2646    * dropped, go ahead and do the print.
2647    */
2648   if ( BXVD_Decoder_P_PictureSet_eSingle == pstUnifiedContext->eSetType
2649         || BXVD_Decoder_P_PictureSet_eBase == pstUnifiedContext->eSetType
2650         || true == bPictureDropped )
2651   {
2652      BXVD_Decoder_P_UnifiedPictureContext * pstTempContext = pstUnifiedContext;
2653
2654      while ( 0 != pstTempContext )
2655      {     
2656         BXVD_DecoderDbg_P_PrintUnifiedPicture( hXvdCh, uiFlags, uiFlagsExt0, pstTempContext, bPictureDropped );
2657         pstTempContext = pstTempContext->pstDependentUniContext;
2658      }
2659   }
2660
2661   BDBG_LEAVE(BXVD_Decoder_S_UnifiedQ_ValidatePicture);
2662
2663   return;
2664
2665}  /* BXVD_Decoder_S_UnifiedQ_ValidatePicture() */
2666
2667/*
2668 * The picture count would take into account picture sets.
2669 */
2670static uint32_t BXVD_Decoder_S_UnifiedQ_GetFreeCount(
2671   BXVD_ChannelHandle hXvdCh
2672   )
2673{
2674   uint32_t uiFreeCount;
2675
2676   BDBG_ENTER( BXVD_Decoder_S_UnifiedQ_GetFreeCount );
2677
2678   uiFreeCount = BXVD_P_DECODER_PICTURE_QUEUE_DEPTH - hXvdCh->stDecoderContext.stUnifiedPictureQueue.iNumUsedElements;
2679
2680   BDBG_LEAVE( BXVD_Decoder_S_UnifiedQ_GetFreeCount );
2681
2682   return uiFreeCount;
2683}
2684
2685static uint32_t BXVD_Decoder_S_UnifiedQ_GetPictureCount(
2686   BXVD_ChannelHandle hXvdCh
2687   )
2688{
2689   return hXvdCh->stDecoderContext.stUnifiedPictureQueue.iNumPictures;
2690}
2691
2692/* Gets the entry at the tail of the unified context queue.
2693 * TODO: return a bool; false if the queue is empty?
2694 */
2695static void BXVD_Decoder_S_UnifiedQ_UnifiedContextGet(
2696   BXVD_ChannelHandle hXvdCh,
2697   BXVD_Decoder_P_UnifiedPictureContext ** ppstUnifiedContext,
2698   bool bBumpReadOffset
2699   )
2700{
2701   BDBG_ENTER( BXVD_Decoder_S_UnifiedQ_UnifiedContextGet );
2702
2703
2704   if ( true == bBumpReadOffset )
2705   {
2706      hXvdCh->stDecoderContext.stUnifiedPictureQueue.iNumPictures--;
2707   }
2708
2709   /* The picture count should never go below 0.
2710    * If it does, there is a bug in the logic.
2711    */
2712   BDBG_ASSERT( hXvdCh->stDecoderContext.stUnifiedPictureQueue.iNumPictures >= 0 );
2713
2714   BXVD_Decoder_S_UnifiedQ_GetLastElement( hXvdCh, ppstUnifiedContext, bBumpReadOffset );
2715
2716   BDBG_LEAVE( BXVD_Decoder_S_UnifiedQ_UnifiedContextGet );
2717
2718   return;
2719
2720} /* end of BXVD_Decoder_S_UnifiedQ_UnifiedContextGet() */
2721
2722static void BXVD_Decoder_S_UnifiedQ_GetLastElement(
2723   BXVD_ChannelHandle hXvdCh,
2724   BXVD_Decoder_P_UnifiedPictureContext ** ppstUnifiedContext,
2725   bool bBumpReadOffset
2726   )
2727{
2728   BXVD_Decoder_P_UnifiedPictureQueue * pstUnifiedQueue = &hXvdCh->stDecoderContext.stUnifiedPictureQueue;
2729
2730   BDBG_ENTER( BXVD_Decoder_S_UnifiedQ_GetLastElement );
2731
2732   BDBG_ASSERT( hXvdCh );
2733   BDBG_ASSERT( ppstUnifiedContext );
2734
2735   /* TODO: what to return if the queue is empty? */
2736
2737   *ppstUnifiedContext = pstUnifiedQueue->pstContextTail;
2738
2739   if ( true == bBumpReadOffset )
2740   {
2741      BXVD_Decoder_S_UnifiedQ_DumpElement( *ppstUnifiedContext, false );
2742
2743      /* Increment picture context queue read pointer */
2744
2745      /* For debug / error checking. */
2746      if ( BXVD_Decoder_P_PictureSet_eSingle == (*ppstUnifiedContext)->eSetType
2747            && 1 != (*ppstUnifiedContext)->uiSetCount
2748         )
2749      {
2750         BXVD_DBG_ERR(hXvdCh, ("BXVD_Decoder_GetNextPicture_isr:: BXVD_Decoder_P_PictureSet_eSingle uiSetCount = %d", (*ppstUnifiedContext)->uiSetCount ));
2751      }
2752      else if ( BXVD_Decoder_P_PictureSet_eBase == (*ppstUnifiedContext)->eSetType
2753                  && 2 != (*ppstUnifiedContext)->uiSetCount
2754               )
2755      {
2756         BXVD_DBG_ERR(hXvdCh, ("BXVD_Decoder_GetNextPicture_isr:: BXVD_Decoder_P_PictureSet_eBase uiSetCount = %d", (*ppstUnifiedContext)->uiSetCount ));
2757      }
2758
2759      /* Walk through all the linked dependent pictures. */
2760      while( NULL != pstUnifiedQueue->pstContextTail->pstDependentUniContext )
2761      {
2762         pstUnifiedQueue->pstContextTail = pstUnifiedQueue->pstContextTail->pstDependentUniContext;
2763      }
2764
2765      /* Move the tail pointer if there is another picture. */
2766      if ( NULL != pstUnifiedQueue->pstContextTail->pstNextUniContext )
2767      {
2768         pstUnifiedQueue->pstContextTail = pstUnifiedQueue->pstContextTail->pstNextUniContext;
2769
2770         /* Do we need to Break the link between the elements?
2771          * Note: the element is actually release in the call to BXVD_Decoder_S_UnifiedQ_UnifiedContextRelease.
2772          */
2773         pstUnifiedQueue->pstContextTail->pstPreviousUniContext->pstNextUniContext = NULL;
2774         pstUnifiedQueue->pstContextTail->pstPreviousUniContext->pstPreviousUniContext = NULL;
2775      }
2776
2777   }
2778
2779   BDBG_LEAVE( BXVD_Decoder_S_UnifiedQ_GetLastElement );
2780
2781   return;
2782
2783}  /* end of BXVD_Decoder_S_UnifiedQ_GetLastElement() */
2784#if 0
2785static void BXVD_Decoder_S_UnifiedQ_InitializeElement(
2786   BXVD_Decoder_P_UnifiedPictureContext * pstUnifiedContext
2787   )
2788{
2789   BDBG_ENTER( BXVD_Decoder_S_UnifiedQ_InitializeElement );
2790
2791   BDBG_ASSERT( pstUnifiedContext );
2792
2793   BKNI_Memset( pstUnifiedContext, 0, sizeof( BXVD_Decoder_P_UnifiedPictureContext ) );
2794
2795   BDBG_LEAVE( BXVD_Decoder_S_UnifiedQ_InitializeElement );
2796
2797   return;
2798
2799}  /* end of BXVD_Decoder_S_UnifiedQ_InitializeElement() */
2800#endif
2801
2802/*
2803 * Sets the pointer to the head of the unified picture queue.
2804 */
2805static void BXVD_Decoder_S_UnifiedQ_GetNextFreeElement(
2806   BXVD_ChannelHandle hXvdCh,
2807   BXVD_Decoder_P_UnifiedPictureContext ** ppstUnifiedContext
2808   )
2809{
2810   uint32_t uiElementsEvaluated=0;
2811   bool     bFoundFreeElement=false;
2812
2813   BXVD_Decoder_P_UnifiedPictureQueue * pstUnifiedQueue = &hXvdCh->stDecoderContext.stUnifiedPictureQueue;
2814
2815   BDBG_ENTER( BXVD_Decoder_S_UnifiedQ_GetNextFreeElement );
2816
2817   /* The call to "BXVD_Decoder_S_UnifiedQ_GetFreeCount()" in "BXVD_Decoder_S_UnifiedQ_Update()"
2818    * should ensure that the queue has enough room. Keep this check as a safety valve.
2819    */
2820   if ( !BXVD_Decoder_S_UnifiedQ_GetFreeCount( hXvdCh ) )
2821   {
2822      BXVD_DBG_ERR(hXvdCh, ("BXVD_Decoder_S_UnifiedQ_GetNextFreeElement:: queue is full.", NULL));
2823      BDBG_ASSERT( 0 );
2824   }
2825
2826   /* Set the pointer to the free element. */
2827   *ppstUnifiedContext = &(pstUnifiedQueue->astUnifiedContext[ pstUnifiedQueue->uiSearchIndex ]);
2828
2829   /* Mark the entry as used. */
2830   (*ppstUnifiedContext)->bInUse = true;
2831
2832   hXvdCh->stDecoderContext.stUnifiedPictureQueue.iNumUsedElements++;
2833   BDBG_ASSERT( hXvdCh->stDecoderContext.stUnifiedPictureQueue.iNumUsedElements <= BXVD_P_DECODER_PICTURE_QUEUE_DEPTH );
2834
2835   /* uiElementsEvaluated To check if the code has looped around,
2836    * should not happen if "iNumUsedElements" is correct.
2837    */
2838
2839   /* Step through the queue until the next free element is found. */
2840
2841   while ( uiElementsEvaluated < BXVD_P_DECODER_PICTURE_QUEUE_DEPTH )
2842   {
2843      BXVD_Decoder_S_Increment_0BasedOffset(
2844               &(pstUnifiedQueue->uiSearchIndex),
2845               1,
2846               BXVD_P_DECODER_PICTURE_QUEUE_DEPTH
2847               );
2848
2849      if ( false == pstUnifiedQueue->astUnifiedContext[ pstUnifiedQueue->uiSearchIndex ].bInUse )
2850      {
2851         bFoundFreeElement = true;
2852         break;
2853      }
2854
2855
2856      uiElementsEvaluated++;
2857   }
2858
2859   if ( true == bFoundFreeElement )
2860   {
2861      /* Set the head of the list to this new context. */
2862      pstUnifiedQueue->pstContextHead = &(pstUnifiedQueue->astUnifiedContext[ pstUnifiedQueue->uiSearchIndex ]);
2863
2864      /* for debug */
2865      pstUnifiedQueue->pstContextHead->uiIndex = pstUnifiedQueue->uiSearchIndex;
2866   }
2867   else
2868   {
2869      /* The preceeding calls to "BXVD_Decoder_S_UnifiedQ_GetFreeCount()"
2870       * should ensure that the queue has enough room. Keep this check as a safety valve.
2871       */
2872      BXVD_DBG_ERR(hXvdCh, ("BXVD_Decoder_S_UnifiedQ_GetNextFreeElement:: did not find a free element.", NULL));
2873      BDBG_ASSERT( 0 );
2874   }
2875
2876   /* Link this element to the preceeding. */
2877   pstUnifiedQueue->pstContextHead->pstPreviousUniContext = *ppstUnifiedContext;
2878
2879   /* Link the preceeding element to this one. */
2880   (*ppstUnifiedContext)->pstNextUniContext = pstUnifiedQueue->pstContextHead;
2881#if 0
2882   BXVD_Decoder_S_Printf("this: %d ", (*ppstUnifiedContext)->uiIndex );
2883
2884   if ( NULL == (*ppstUnifiedContext)->pstNextUniContext )
2885      BXVD_Decoder_S_Printf("next: NULL ", NULL );
2886   else
2887      BXVD_Decoder_S_Printf("next: %d ", (*ppstUnifiedContext)->pstNextUniContext->uiIndex );
2888
2889   if ( NULL == (*ppstUnifiedContext)->pstPreviousUniContext )
2890      BXVD_Decoder_S_Printf("prev: NULL ", NULL );
2891   else
2892      BXVD_Decoder_S_Printf("prev: %d ", (*ppstUnifiedContext)->pstPreviousUniContext->uiIndex );
2893
2894   BXVD_Decoder_S_Printf("head: %d ", pstUnifiedQueue->pstContextHead->uiIndex );
2895
2896   if ( NULL == pstUnifiedQueue->pstContextHead->pstNextUniContext )
2897      BXVD_Decoder_S_Printf("hnext: NULL ", NULL );
2898   else
2899      BXVD_Decoder_S_Printf("hnext: %d ", pstUnifiedQueue->pstContextHead->pstNextUniContext->uiIndex );
2900   if ( NULL == pstUnifiedQueue->pstContextHead->pstPreviousUniContext )
2901      BXVD_Decoder_S_Printf("hprev: NULL\n", NULL );
2902      else
2903         BXVD_Decoder_S_Printf("hprev: %d\n", pstUnifiedQueue->pstContextHead->pstPreviousUniContext->uiIndex );
2904#endif
2905
2906   BDBG_LEAVE( BXVD_Decoder_S_UnifiedQ_GetNextFreeElement );
2907
2908   return;
2909
2910}  /* end of BXVD_Decoder_S_UnifiedQ_GetNextFreeElement() */
2911
2912
2913/*
2914 *
2915 */
2916static void BXVD_Decoder_S_UnifiedQ_UnifiedContextRelease(
2917   BXVD_ChannelHandle hXvdCh,
2918   BXVD_Decoder_P_UnifiedPictureContext * pstUnifiedContext
2919   )
2920{
2921   BDBG_ENTER( BXVD_Decoder_S_UnifiedQ_UnifiedContextRelease );
2922
2923   BDBG_ASSERT( hXvdCh );
2924   BDBG_ASSERT( pstUnifiedContext );
2925
2926   BXVD_Decoder_S_UnifiedQ_DumpElement( pstUnifiedContext, false );
2927
2928   BXVD_Decoder_S_UnifiedQ_ReleaseElement( hXvdCh, pstUnifiedContext );
2929
2930   BDBG_LEAVE( BXVD_Decoder_S_UnifiedQ_UnifiedContextRelease );
2931
2932   return;
2933}
2934
2935static void BXVD_Decoder_S_UnifiedQ_ReleaseElement(
2936   BXVD_ChannelHandle hXvdCh,
2937   BXVD_Decoder_P_UnifiedPictureContext * pstUnifiedContext
2938   )
2939{
2940   BDBG_ENTER( BXVD_Decoder_S_UnifiedQ_ReleaseElement );
2941
2942   BDBG_ASSERT( hXvdCh );
2943   BDBG_ASSERT( pstUnifiedContext );
2944
2945   /* Release the unified picture(s) as well as the the associated PPB(s).
2946    * SWBLURAY-23835: Each picture should only be release once.  To
2947    * accommodate poorly behaving software, check "bInUse" to see if a
2948    * picture was previously released.
2949    */
2950   if ( true == pstUnifiedContext->bInUse )
2951   {
2952      if ( NULL != pstUnifiedContext->pstDependentUniContext )
2953      {
2954         BXVD_Decoder_S_UnifiedQ_ReleaseElement( hXvdCh, pstUnifiedContext->pstDependentUniContext );
2955      }
2956
2957      BXVD_Decoder_S_ReleaseQ_AddPPB( hXvdCh, pstUnifiedContext->pPPBPhysical );
2958      BXVD_Decoder_S_UnifiedQ_InvalidateElement( hXvdCh, pstUnifiedContext );
2959   }
2960   else
2961   {
2962      BXVD_DBG_ERR(hXvdCh,("BXVD_Decoder_S_UnifiedQ_ReleaseElement:: picture released multiple times.", NULL));
2963   }
2964
2965   BDBG_LEAVE( BXVD_Decoder_S_UnifiedQ_ReleaseElement );
2966
2967   return;
2968
2969}  /* end of BXVD_Decoder_S_UnifiedQ_ReleaseElement() */
2970
2971#if 0
2972/*
2973 *
2974 */
2975static void BXVD_Decoder_S_UnifiedQ_UnifiedContextAdd(
2976   BXVD_ChannelHandle hXvdCh,
2977   BXVD_Decoder_P_PictureContext * pstPictureCntxt
2978   )
2979{
2980   BDBG_ENTER( BXVD_Decoder_S_UnifiedQ_UnifiedContextAdd );
2981
2982   hXvdCh->stDecoderContext.stUnifiedPictureQueue.iNumPictures++;
2983
2984   /* TODO: add a return value here? */
2985   BXVD_Decoder_S_UnifiedQ_AddPicture( hXvdCh, pstPictureCntxt );
2986
2987   BDBG_LEAVE( BXVD_Decoder_S_UnifiedQ_UnifiedContextAdd );
2988
2989   return;
2990
2991} /* end of BXVD_Decoder_S_UnifiedQ_UnifiedContextAdd() */
2992#endif
2993
2994static void BXVD_Decoder_S_UnifiedQ_AddPicture(
2995   BXVD_ChannelHandle hXvdCh,
2996   BXVD_Decoder_P_PictureContext * pstPictureCntxt,
2997   bool bBasePicture
2998   )
2999{
3000   BXVD_Decoder_P_UnifiedPictureContext * pstUnifiedContext=NULL;
3001
3002   BDBG_ENTER( BXVD_Decoder_S_UnifiedQ_AddPicture );
3003
3004   BXVD_DecoderTimer_P_SnapshotFunctionStartTime( hXvdCh, BXVD_DecoderTimer_P_eFuncUQ_AddPic );
3005
3006   /* Bump the count of sets of pictures on the Unified Queue when
3007    * the base picture is added.
3008    */
3009   if ( true == bBasePicture )
3010   {
3011      hXvdCh->stDecoderContext.stUnifiedPictureQueue.iNumPictures++;
3012   }
3013
3014   /* Get the BXDM_Picture element at the head of the unified queue.
3015    * The call to "BXVD_Decoder_S_UnifiedQ_GetFreeCount()" in "BXVD_Decoder_S_UnifiedQ_Update()"
3016    * should ensure that the queue has enough room.
3017    */
3018   BXVD_Decoder_S_UnifiedQ_GetNextFreeElement( hXvdCh, &pstUnifiedContext );
3019
3020   /* This should never happen. We should only get here if there is a free
3021    * element on the Unified Queue.
3022    */
3023   if ( NULL == pstUnifiedContext )
3024   {
3025      BXVD_DBG_ERR(hXvdCh, ("BXVD_Decoder_S_UnifiedQ_AddPicture:: failed to get an element.", NULL));
3026      BDBG_ASSERT( 0 );
3027   }
3028
3029   /* Dereference the PPB and fill in the BXDM_Picture structure.
3030    */
3031   BXVD_Decoder_S_UnifiedQ_ValidatePicture( hXvdCh, pstPictureCntxt, pstUnifiedContext, false );
3032
3033   BXVD_DecoderTimer_P_SnapshotFunctionEndTime( hXvdCh, BXVD_DecoderTimer_P_eFuncUQ_AddPic );
3034
3035
3036   BDBG_LEAVE( BXVD_Decoder_S_UnifiedQ_AddPicture );
3037
3038   return;
3039
3040} /* end of BXVD_Decoder_S_UnifiedQ_AddPicture() */
3041
3042static void BXVD_Decoder_S_PPBReceived(
3043   BXVD_ChannelHandle hXvdCh,
3044   BXVD_P_PPB **pstPPB
3045   )
3046{
3047   bool bSignalPPBReceived;
3048
3049   BDBG_ENTER(BXVD_Decoder_S_PPBReceived);
3050
3051   BDBG_ASSERT( hXvdCh );
3052
3053   /* First check that a callback function has been registered */
3054   bSignalPPBReceived = ( NULL != hXvdCh->stInterruptCallbackInfo[BXVD_Interrupt_ePPBReceived].BXVD_P_pAppIntCallbackPtr );
3055
3056   /* Then check that the callback mask bit is set. */
3057   bSignalPPBReceived &= ( true == hXvdCh->stCallbackReq.bPPBReceived );
3058
3059   /* If all the conditions have been met, execute the callback. */
3060   if( bSignalPPBReceived )
3061   {
3062      BXVD_DecoderTimer_P_SnapshotCallbackStartTime( hXvdCh, BXVD_DecoderTimer_P_eCbPPBReceived );
3063
3064      hXvdCh->stInterruptCallbackInfo[BXVD_Interrupt_ePPBReceived].BXVD_P_pAppIntCallbackPtr (
3065                                 hXvdCh->stInterruptCallbackInfo[BXVD_Interrupt_ePPBReceived].pParm1,
3066                                 hXvdCh->stInterruptCallbackInfo[BXVD_Interrupt_ePPBReceived].parm2,
3067                                 pstPPB
3068                                 ) ;
3069
3070      BXVD_DecoderTimer_P_SnapshotCallbackEndTime( hXvdCh, BXVD_DecoderTimer_P_eCbPPBReceived );
3071
3072   }
3073
3074   BDBG_LEAVE(BXVD_Decoder_S_PPBReceived);
3075
3076   return;
3077
3078}    /* end of BBXVD_Decoder_S_PPBReceived() */
3079
3080static void BXVD_Decoder_S_UnifiedQ_GetSetType(
3081   BXVD_ChannelHandle hXvdCh,
3082   BXVD_Decoder_P_LocalState * pstLocalState,
3083   BXVD_Decoder_P_PictureContext * pstPicCntxt
3084   )
3085{
3086   BDBG_ENTER( BXVD_Decoder_S_UnifiedQ_GetSetType );
3087
3088   BDBG_ASSERT( hXvdCh );
3089   BDBG_ASSERT( pstPicCntxt );
3090   BSTD_UNUSED( pstLocalState );
3091
3092   if ( BAVC_VideoCompressionStd_eH264 == pstPicCntxt->stPPB.pPPB->protocol )
3093   {
3094      /* If AVC, check the SEI messages to determine if 3D. */
3095
3096      uint32_t             uiSEIOffset=0;
3097      BXVD_P_SEI_Message * pSEIMessage;
3098
3099      /* SW7405-4883: set a default of 2D. */
3100      pstPicCntxt->st3D.eOrientation = BXDM_Picture_Orientation_e2D;
3101      pstPicCntxt->st3D.eFrameRelationship = BXDM_Picture_FrameRelationship_eUnknown;
3102
3103      /* TODO: the following is a partial duplicate of the SEI parsing in
3104       * the validate routine, clean this up.
3105       */
3106      uiSEIOffset = (uint32_t)pstPicCntxt->stPPB.pPPB->other.h264.pstSEIMessageOffset;
3107
3108      while ( 0 != uiSEIOffset )
3109      {
3110         /* Convert the BXVD_P_SEI_Message offset to a virtual address. */
3111         BMEM_ConvertOffsetToAddress(
3112            hXvdCh->hSystemHeap,
3113            uiSEIOffset,
3114            (void *)&( pSEIMessage )
3115            );
3116
3117         if ( BXVD_P_PPB_SEI_MSG_FRAMEPACKING == pSEIMessage->uiMsgType )
3118         {
3119            /* Needed pstAvdSEIData to prevent the compiler warning
3120             * "dereferencing type-punned pointer will break strict-aliasing rules"
3121             */
3122            BXVD_P_SEI_FramePacking * pstAvdSEIData = (BXVD_P_SEI_FramePacking *)&(pSEIMessage->data.stSEIFramePacking);
3123
3124            /* For 3D, fill in the pstXdmPicture->st3D.eOrientation
3125             * and pstXdmPicture->st3D.eFrameRelationship fields.
3126             */
3127            BXVD_Decoder_S_UnifiedQ_ParseSeiFramePackMsg( pstAvdSEIData, &(pstPicCntxt->st3D) );
3128
3129            /* TODO: if multiple messages, break on the first?*/
3130            break;
3131         }
3132
3133         /* Check for another message. */
3134         uiSEIOffset = (uint32_t)pSEIMessage->pstNextSEIMsgOffset;
3135
3136      }  /* end of while ( 0 != uiSEIOffset )            */
3137
3138      /* Convert SEI parameters into the appropriate "set" information.
3139       */
3140      switch( pstPicCntxt->st3D.eOrientation )
3141      {
3142         case BXDM_Picture_Orientation_e3D_FullFrame:
3143            /* Frame 0 is the base picture. */ 
3144
3145            if ( 0 == pstPicCntxt->st3D.uiFrameNum )
3146            {
3147               pstPicCntxt->eSetType = BXVD_Decoder_P_PictureSet_eBase;
3148            }
3149            else
3150            {
3151               pstPicCntxt->eSetType = BXVD_Decoder_P_PictureSet_eDependent;
3152            }
3153
3154            /* Expecting two pictures for full frame 3D */
3155            pstPicCntxt->uiSetCount = 2;       
3156
3157            break;
3158
3159         case BXDM_Picture_Orientation_e2D:
3160         case BXDM_Picture_Orientation_e3D_Checker:
3161         case BXDM_Picture_Orientation_e3D_Column:
3162         case BXDM_Picture_Orientation_e3D_Row:
3163         case BXDM_Picture_Orientation_e3D_SideBySide:
3164         case BXDM_Picture_Orientation_e3D_TopBottom:
3165         default:
3166            pstPicCntxt->eSetType = BXVD_Decoder_P_PictureSet_eSingle;
3167            pstPicCntxt->uiSetCount = 1;
3168            break;
3169      }
3170
3171   }
3172   else
3173   {
3174      /* Extract the picture set type and set count. This is to support MVC and
3175       * perhaps other multipicture protocols.
3176       */
3177      if ( !(pstPicCntxt->stPPB.pPPB->flags & BXVD_P_PPB_MULTIVIEW_FIELD_MASK) )
3178      {
3179         pstPicCntxt->eSetType = BXVD_Decoder_P_PictureSet_eSingle;
3180         pstPicCntxt->uiSetCount = 1;
3181      }
3182      else
3183      {
3184         if ( pstPicCntxt->stPPB.pPPB->flags & BXVD_P_PPB_MULTIVIEW_BASE_FLAG )
3185         {
3186            pstPicCntxt->eSetType = BXVD_Decoder_P_PictureSet_eBase;
3187            pstPicCntxt->uiSetCount = (( pstPicCntxt->stPPB.pPPB->flags & BXVD_P_PPB_MULTIVIEW_COUNT_MASK ) >> BXVD_P_PPB_MULTIVIEW_COUNT_SHIFT );
3188
3189            /* Should be generalized to use "pstPicCntxt->uiSetCount", waiting on the firmware.*/
3190            pstPicCntxt->uiSetCount = BXVD_DECODER_S_PICTURES_PER_SET;
3191         }
3192         else
3193         {
3194            pstPicCntxt->eSetType = BXVD_Decoder_P_PictureSet_eDependent;
3195            pstPicCntxt->uiSetCount = BXVD_DECODER_S_PICTURES_PER_SET;
3196         }
3197      }
3198   }
3199
3200
3201   BDBG_ENTER( BXVD_Decoder_S_UnifiedQ_GetSetType );
3202
3203   return;
3204}
3205
3206
3207/*
3208 *
3209 */
3210static void BXVD_Decoder_S_UnifiedQ_Update(
3211   BXVD_ChannelHandle hXvdCh,
3212   BXVD_Decoder_P_LocalState * pstLocalState
3213   )
3214{
3215   BXVD_P_PictureDeliveryQueue * pstDeliveryQueue;
3216   BXVD_Decoder_P_UnifiedPictureQueue * pstUnifiedQueue = &hXvdCh->stDecoderContext.stUnifiedPictureQueue;
3217   uint32_t uiDeliveryQWriteOffset0Based;
3218   uint32_t uiDeliveryQReadOffset0Based;
3219   BXVD_Decoder_P_PictureContext * pstPicCntxt = NULL;
3220   BXVD_Decoder_P_PictureContext * pstPrevPicCntxt = NULL;
3221
3222   BXVD_Decoder_P_PictureContextQueue * pstContextQueue = &(hXvdCh->stDecoderContext.stPictureContextQueue);
3223
3224   uint32_t    uiNumPicturesToProcess;
3225
3226   uint32_t    uiDeliveryQ_PicturesToProcess;
3227   uint32_t  uiUniQFreeElements;
3228
3229   BXVD_Decoder_P_DQTContext * pDQTCntxt = &( hXvdCh->stDecoderContext.stDqtCntxt );
3230   bool  bSearchForStartOfNextGop;
3231   bool  bDeadlock = false;
3232   bool  bFoundEndOfGop = false;
3233   bool  bDqtMvcError = false;
3234
3235   /* Update the Unified Picture Queue.
3236    *
3237    * There are three queues in play here:
3238    * - Delivery Queue, contains the PPB's from the video decoder
3239    * - Picture Context Queue, temporary values needed for processing pictures (e.g. PPB virtual addresses)
3240    * - Unified Picture Queue, the "cooked" pictures for consumption by the Picture Provider
3241    *
3242    * The conversion of PPB's into Unified Pictures is handled in three phases.
3243    *
3244    * Phase 1: vetting of the PPB's
3245    * - calculate the virtual address of the PPB
3246    * - check that there are matched sets of base and dependent pictures (e.g. MVC protocol)
3247    * - when DQT is enabled, search for the start of the next GOP
3248    * - generate the PPBReceived callback
3249    *
3250    * Phase 2: DQT cleanup (if DQT is enabled)
3251    * - determine if a GOP needs to be truncated
3252    * - set the appropriate pointers for processing the PPB's in reverse order
3253    * - handle MVC errors
3254    *   (will this ever be supported? needs to be tested more thoroughly!!)
3255    *
3256    * Phase 3: validate Unified Picture Queue.
3257    * - interpret the PPB's fields to set appropriate Unified Picture elements
3258    * - link the dependent pictures to the base pictures
3259    */
3260
3261   BXVD_DecoderTimer_P_SnapshotFunctionStartTime( hXvdCh, BXVD_DecoderTimer_P_eFuncUQ_Vet );
3262
3263   BXVD_Decoder_S_Printf("\n> ", NULL );
3264
3265   /* Cleanup pictures at the end of a GOP that are not going to be displayed.
3266    */
3267   if ( true == pDQTCntxt->bTruncatingGop )
3268   {
3269      BXVD_Decoder_S_DeliveryQ_ReleaseGopTail( hXvdCh, pstLocalState );
3270   }
3271
3272   /* If ...
3273    * - DQT is enabled
3274    * - NOT in the middle of displaying a GOP
3275    * - NOT throwing away pictures at the end of the GOP
3276    * then it is time to look for the start of the next GOP.
3277    */
3278   bSearchForStartOfNextGop = ( true == pDQTCntxt->bDqtEnabled );
3279   bSearchForStartOfNextGop &= ( false == pDQTCntxt->bConvertGopToUniPics );
3280   bSearchForStartOfNextGop &= ( false == pDQTCntxt->bTruncatingGop );
3281
3282   if ( true == bSearchForStartOfNextGop )
3283   {
3284      BXVD_Decoder_S_Printf(" findNext ", NULL );
3285   }
3286
3287   /* Retrieve the read/write offsets for the delivery queue.
3288    * Adjust them to be '0' based.
3289    */
3290   BXVD_AVD_P_DELIVERY_QUEUE_GET_ADDR( hXvdCh, pstDeliveryQueue );
3291
3292   BXVD_AVD_P_DELIVERY_QUEUE_GET_READ_OFFSET( hXvdCh, uiDeliveryQReadOffset0Based );
3293
3294   uiDeliveryQReadOffset0Based -= BXVD_P_INITIAL_OFFSET_DISPLAY_QUEUE;
3295
3296   uiDeliveryQWriteOffset0Based = pstLocalState->uiDeliveryQueueWriteOffset - BXVD_P_INITIAL_OFFSET_DISPLAY_QUEUE;
3297
3298
3299   /* SW7405-3137: calculate the number of pictures on the delivery queue.
3300    * Hold off the processing of pictures until a complete "set" has
3301    * been delivered. (i.e. detects incomplete sets at the head of the queue.)
3302    * TODO: does this work with DQT?  Handle in the search routine?
3303    */
3304   BXVD_AVD_P_GET_QUEUE_DEPTH( uiDeliveryQReadOffset0Based, uiDeliveryQWriteOffset0Based, uiDeliveryQ_PicturesToProcess );
3305
3306   /* SW7405-3137: calculate the number of pictures to be processed on this call.
3307    * Hold off processing the one(s) at the tail of the queue until a complete
3308    * "set" has been delivered.  (i.e detects incomplete sets at the tail of the queue.)
3309    */
3310   BXVD_AVD_P_GET_QUEUE_DEPTH( pstContextQueue->uiWriteOffset, uiDeliveryQWriteOffset0Based, uiNumPicturesToProcess );
3311
3312   /* If in the middle of processing a GOP, hold off processing more pictures
3313    * until done with this GOP.  This check should not be needed since the queue's are
3314    * reconcile as soon as the next GOP is delivered. The only way this could
3315    * happen, is if the Unified Picture Queue was full and the validation
3316    * need to be stalled until the Unified Queue was drained.
3317    */
3318   if ( true == pDQTCntxt->bConvertGopToUniPics )
3319   {
3320      BXVD_Decoder_S_Printf("rPlay ", NULL );
3321      goto ProcessGop;
3322   }
3323
3324   /* If DQT is enabled, check for a dead lock condition, i.e. the DM is waiting for the next
3325    * picture to be delivered and the decoder is waiting for a picture to be freed.
3326    * Don't bother with the check if the queue is empty; this will prevent false deadlock
3327    * detections when simply waiting for the video decoder.
3328    */
3329   if ( true == bSearchForStartOfNextGop
3330       && uiDeliveryQReadOffset0Based != uiDeliveryQWriteOffset0Based
3331      )
3332   {
3333      bDeadlock = BXVD_Decoder_S_DeliveryQ_CheckForDeadlock( hXvdCh, uiNumPicturesToProcess );
3334      bFoundEndOfGop = bDeadlock;
3335   }
3336
3337
3338   BXVD_Decoder_S_Printf("start vetting:: DQrd:%d DQwr:%d CQwr:%d trnc:%d\n",
3339            uiDeliveryQReadOffset0Based,
3340            uiDeliveryQWriteOffset0Based,
3341            pstContextQueue->uiWriteOffset,
3342            pDQTCntxt->bTruncatingGop
3343            );
3344
3345   /* Phase 1: walk through the deliver queue vetting the PPB's.
3346    *
3347    * Loop through until:
3348    * - the PictureContextQueue write offset is equal to the DeliveryQueue write offset
3349    * - OR an incomplete set of pictures is encountered at either the tail or head of the DeliveryQueue.
3350    * - OR an error condition, i.e. an incomplete set of pictures is encountered in
3351    *   the middle of the DeliveryQueue.
3352    * - OR DQT is enabled and the start of the next GOP has been found
3353    *
3354    * Note: "uiNumPicturesToProcess" will equal "0" during a deadlock condtion.  Checking the
3355    * deadlock flag was added to the while statement for documentation purposes.
3356    */
3357   while ( 0 != uiNumPicturesToProcess
3358            && false == bDeadlock )
3359   {
3360      /* Get the next element on the picture context queue. */
3361      pstPicCntxt = &pstContextQueue->astPictureContext[pstContextQueue->uiWriteOffset];
3362
3363      /* Reset the picture parameters and other elements */
3364      BKNI_Memset( pstPicCntxt, 0, sizeof( BXVD_Decoder_P_PictureContext ) );
3365
3366      /* Get the PPB address */
3367      pstPicCntxt->stPPB.pPPBPhysical = (BXVD_P_PPB *)( pstDeliveryQueue->display_elements[ pstContextQueue->uiWriteOffset ]);
3368
3369      BMEM_ConvertOffsetToAddress(
3370         hXvdCh->hSystemHeap,
3371         (uint32_t)( pstPicCntxt->stPPB.pPPBPhysical ),
3372         (void *)&( pstPicCntxt->stPPB.pPPB )
3373         );
3374
3375      /* Just for debug. */
3376      if ( true == pDQTCntxt->bDqtEnabled )
3377      {
3378         BXVD_Decoder_S_Printf("\n\tsearch:: DQ:%d/%d CQ:x/%d curTag=%u  picTag=%u ",
3379                     uiDeliveryQReadOffset0Based,
3380                     uiDeliveryQWriteOffset0Based,
3381                     pstContextQueue->uiWriteOffset,
3382                     pDQTCntxt->uiCurrentPicTag,
3383                     pstPicCntxt->stPPB.pPPB->picture_tag
3384                     );
3385      }
3386
3387      /* SWCHECKFRAME-80: execute the PPBReceived callback prior to processing the PPB data.
3388       */
3389      BXVD_Decoder_S_PPBReceived( hXvdCh, &(pstPicCntxt->stPPB.pPPB) );
3390
3391      /* Extract the picture set type and set count.  This is to
3392       * support 3D and any multipicture protocol.
3393       */
3394      BXVD_Decoder_S_UnifiedQ_GetSetType( hXvdCh, pstLocalState, pstPicCntxt );
3395
3396      if ( BXVD_Decoder_P_PictureSet_eSingle == pstPicCntxt->eSetType )
3397      {
3398         BXVD_Decoder_S_Printf("S/%d ", pstContextQueue->uiWriteOffset );
3399      }
3400      else if ( BXVD_Decoder_P_PictureSet_eBase == pstPicCntxt->eSetType )
3401      {
3402         BXVD_Decoder_S_Printf("B/%d ", pstContextQueue->uiWriteOffset );
3403
3404         /* An incomplete set of pictures at the head of the delivery queue. */
3405
3406         if ( uiDeliveryQ_PicturesToProcess < pstPicCntxt->uiSetCount )
3407         {
3408            BXVD_Decoder_S_Printf("break at head\n", NULL );
3409            break;
3410         }
3411      }
3412      else if ( BXVD_Decoder_P_PictureSet_eDependent == pstPicCntxt->eSetType )
3413      {
3414         BXVD_Decoder_S_Printf("d/%d ", pstContextQueue->uiWriteOffset );
3415      }
3416      else
3417      {
3418         BXVD_DBG_ERR(hXvdCh,("BXVD_Decoder_S_UnifiedQ_Update:: unknown set type %d", pstPicCntxt->eSetType));
3419
3420         pstPicCntxt->eSetType = BXVD_Decoder_P_PictureSet_eSingle;
3421         pstPicCntxt->uiSetCount = 1;
3422      }
3423
3424
3425      /* If DQT is enabled, check for the start of the next GOP.
3426       * Don't look at the picture tag on dependent pictures.
3427       * GOP's should always start on a "base" or single picture.
3428       */
3429      if ( BXVD_Decoder_P_PictureSet_eDependent != pstPicCntxt->eSetType
3430            && true == pDQTCntxt->bDqtEnabled
3431          )
3432      {
3433         /* If "bValidPicTag" is false, the start of a GOP was detected the previous time
3434          * through this loop.  Snapshot the new picture tag.
3435          */
3436         if ( false == pDQTCntxt->bValidPicTag )
3437         {
3438            pDQTCntxt->uiCurrentPicTag = pstPicCntxt->stPPB.pPPB->picture_tag;
3439            pDQTCntxt->bValidPicTag = true;
3440            BXVD_Decoder_S_Printf(" set tag %d ", pDQTCntxt->uiCurrentPicTag );
3441         }
3442
3443         /* If the new picture tag doesn't match the old one, the start of
3444          * the next GOP has been found.  Break out of this loop and begin
3445          * displaying the GOP in reverse.
3446          */
3447         if ( true == pDQTCntxt->bValidPicTag
3448               && pDQTCntxt->uiCurrentPicTag != pstPicCntxt->stPPB.pPPB->picture_tag
3449            )
3450         {
3451            bFoundEndOfGop = true;
3452
3453            BXVD_Decoder_S_Printf("\n\tfound EOG picTagThis=%u  picTagNext=%u ",
3454                     pDQTCntxt->uiCurrentPicTag,
3455                     pstPicCntxt->stPPB.pPPB->picture_tag
3456                     );
3457
3458            break;
3459         }
3460
3461      }  /* end of if( !BXVD_Decoder_P_PictureSet_eDependent && pDQTCntxt->bDqtEnabled ) */
3462
3463
3464      /* Check for an error sequence.  If the picture sequence is fine,
3465       * generate the "BXVD_Interrupt_ePPBReceived" callback and
3466       * validate the static picture context.
3467       *
3468       * The error sequences are
3469       * - "base" followed by "single"
3470       * - "base" followed by "base"
3471       * - "single" followed by "dependent"
3472       * - "dependent" followed by "dependent"
3473       *
3474       * Note: the first two scenarios can span a call to this routine, the
3475       * last two cannot.
3476       * Note: the POC will be the same for all pictures in the set, is this of any use?
3477       */
3478      if ( BXVD_Decoder_P_PictureSet_eSingle == pstPicCntxt->eSetType
3479          || BXVD_Decoder_P_PictureSet_eBase == pstPicCntxt->eSetType
3480         )
3481      {
3482         /* Check for a bad picture sequence. A "base" picture can not be followed
3483          * by a "base" or "single" picture; this indicates a missing "dependent" picture.
3484          * Evaluation of picture sets won't span a call to this routine, don't perform
3485          * the check for the first picture, i.e. "NULL == pstPrevPicCntxt".
3486          */
3487         if ( NULL != pstPrevPicCntxt
3488               && BXVD_Decoder_P_PictureSet_eBase == pstPrevPicCntxt->eSetType
3489            )
3490         {
3491            uint32_t uiTempWriteOffset;
3492
3493            BXVD_Decoder_S_Printf("bad picture sequence Base followed by %d\n", pstPicCntxt->eSetType );
3494
3495            /* The picture in error is the previous one, backup the write pointer */
3496
3497            uiTempWriteOffset = pstContextQueue->uiWriteOffset;
3498
3499            BXVD_Decoder_S_Decrement_0BasedOffset(
3500                     &(uiTempWriteOffset),
3501                     1,
3502                     BXVD_P_MAX_ELEMENTS_IN_DISPLAY_QUEUE
3503                     );
3504
3505            pstPicCntxt = &pstContextQueue->astPictureContext[uiTempWriteOffset];
3506
3507            if ( true == pDQTCntxt->bDqtEnabled )
3508            {
3509               /* The error picture will be handled by the DQT truncation logic. */
3510               bFoundEndOfGop = true;
3511               bDqtMvcError = true;
3512               break;
3513            }
3514            else
3515            {
3516               /* Mark the picture to be dropped. By "continue-ing", the error picture
3517                * will be dealt with at the top of this loop.
3518                * Drop the picture "in line".
3519                * Mark it as dropped so that the uni validation logic ignores it.
3520                */
3521               pstPicCntxt->bDropPicture = true;
3522               break;
3523            }
3524         }
3525
3526         if ( BXVD_Decoder_P_PictureSet_eBase == pstPicCntxt->eSetType )
3527         {
3528            /* If a Base picture, check for an incomplete set of pictures at the
3529             * tail of the delivery queue.  Wait for all the pictures before
3530             * processing this set.
3531             */
3532            if ( uiNumPicturesToProcess  < BXVD_DECODER_S_PICTURES_PER_SET /*pstPicCntxt->uiSetCount*/ )
3533            {
3534               BXVD_Decoder_S_Printf("break at tail, pics on queue %d\n", uiDeliveryQ_PicturesToProcess );
3535               break;
3536            }
3537         }
3538#if 0
3539         /* Generate the PPBReceived callback */
3540         BXVD_Decoder_S_PPBReceived( hXvdCh, &(pstPicCntxt->stPPB.pPPB) );
3541#endif
3542      }
3543      else
3544      {
3545         /* Check for a bad picture sequence. A "dependent" picture can not follow either a
3546          * a "single" or a "dependent" picture; this would indicate a missing "base" picture.
3547          * Evaluation of picture sets won't span a call to this routine, if the first picture evaluated
3548          * is a "dependent" picture, the "base" picture is missing.
3549          */
3550         if ( NULL == pstPrevPicCntxt
3551              || BXVD_Decoder_P_PictureSet_eDependent == pstPrevPicCntxt->eSetType
3552              || BXVD_Decoder_P_PictureSet_eSingle == pstPrevPicCntxt->eSetType
3553            )
3554         {
3555            if ( NULL == pstPrevPicCntxt )
3556            {
3557               BXVD_Decoder_S_Printf("bad picture sequence NULL followed by Dependent\n", NULL );
3558            }
3559            else
3560            {
3561               BXVD_Decoder_S_Printf("bad picture sequence %d followed by Dependent\n", pstPrevPicCntxt->eSetType );
3562            }
3563
3564            if ( true == pDQTCntxt->bDqtEnabled )
3565            {
3566               /* The error picture will be handled by the DQT truncation logic. */
3567               bFoundEndOfGop = true;
3568               bDqtMvcError = true;
3569               break;
3570            }
3571            else
3572            {
3573               /* The picture in error is the current one, mark it to be dropped. */
3574
3575               pstPicCntxt->bDropPicture = true;
3576
3577               /* Increment PictureContextQueue write offset */
3578               BXVD_Decoder_S_Increment_0BasedOffset(
3579                        &(pstContextQueue->uiWriteOffset),
3580                        1,
3581                        BXVD_P_MAX_ELEMENTS_IN_DISPLAY_QUEUE );
3582
3583               break;
3584            }
3585         }
3586
3587         /* An extended picture, link it to the preceding base picture. "pstPrevPicCntxt" should never be
3588          * NULL when processing complete sets. The preceding error logic ensures this.
3589          */
3590         if ( NULL != pstPrevPicCntxt )
3591         {
3592            /* Link this picture to the base. */
3593            pstPrevPicCntxt->pDependentPicture = pstPicCntxt;
3594
3595            /* Line this picture to the base. */
3596            pstPicCntxt->pBasePicture = pstPrevPicCntxt;
3597         }
3598         else
3599         {
3600            BXVD_DBG_ERR(hXvdCh, ("BXVD_Decoder_S_UnifiedQ_Update:: failed to link dependent picture to base.", NULL));
3601         }
3602      }
3603
3604      /* Increment PictureContextQueue write offset */
3605      BXVD_Decoder_S_Increment_0BasedOffset(
3606               &(pstContextQueue->uiWriteOffset),
3607               1,
3608               BXVD_P_MAX_ELEMENTS_IN_DISPLAY_QUEUE );
3609
3610      /* Decrement the count of pictures needing to be processed. */
3611      uiNumPicturesToProcess--;
3612
3613      /* Save the pointer to the context in order to link base and dependent pictures. */
3614      pstPrevPicCntxt = pstPicCntxt;
3615
3616   }  /* end of while ( uiDeliveryQWriteOffset0Based != pstContextQueue->uiWriteOffset ) */
3617
3618
3619   BXVD_Decoder_S_Printf("\nend vetting:: DQrd:%d DQwr:%d CQwr:%d",
3620            uiDeliveryQReadOffset0Based,
3621            uiDeliveryQWriteOffset0Based,
3622            pstContextQueue->uiWriteOffset
3623            );
3624
3625   if ( true  == pDQTCntxt->bDqtEnabled )
3626   {
3627      BXVD_Decoder_S_Printf("   search:%d  found:%d  deadlock:%d",
3628            bSearchForStartOfNextGop,
3629            bFoundEndOfGop,
3630            bDeadlock
3631            );
3632   }
3633
3634   BXVD_Decoder_S_Printf("\n", NULL );
3635
3636   BXVD_DecoderTimer_P_SnapshotFunctionEndTime( hXvdCh, BXVD_DecoderTimer_P_eFuncUQ_Vet );
3637
3638   BXVD_DecoderTimer_P_SnapshotFunctionStartTime( hXvdCh, BXVD_DecoderTimer_P_eFuncUQ_DQT );
3639
3640   /* Phase 2:
3641    * Now that done vetting the delivery queue, deal with DQT clean up.
3642    * If the end of the GOP was found on a previous call to this routine, determining that the queue
3643    * has data is fairly straight forward. If still searching for the start of the next GOP,
3644    * it gets more involved.
3645    * If the start of the next GOP has NOT been found, the picture queue is effectively empty.
3646    */
3647   if ( true == pDQTCntxt->bDqtEnabled
3648         && true == bSearchForStartOfNextGop
3649         && true == bFoundEndOfGop )
3650   {
3651      /* If a deadlock situation, then the GOP needs to be truncated. */
3652      if ( bDeadlock )
3653      {
3654         pDQTCntxt->bTruncatingGop = true;
3655         BXVD_Decoder_S_Printf("\n\tDeadLock:: CQwr=%d ", pstContextQueue->uiWriteOffset );
3656      }
3657
3658      /* Need to acquire the picture tag of the next GOP. */
3659      pDQTCntxt->bValidPicTag = false;
3660
3661      /* "pstContextQueue->uiWriteOffset" points to the next picture on the queue.
3662       * It could be the start of the next GOP or with MVC, an error picture.
3663       * In a deadlock scenario, it simply points just beyond the last picture received.
3664       * Load the following offsets with this value.
3665       */
3666      pDQTCntxt->uiEndOfGopOffset = pstContextQueue->uiWriteOffset;
3667      pDQTCntxt->uiReverseReadOffset = pstContextQueue->uiWriteOffset;
3668
3669      /* Backup to the last picture of this GOP.
3670       * Still in picture context queue "domain", use "0" based routines.
3671       */
3672      BXVD_Decoder_S_Decrement_0BasedOffset( &(pDQTCntxt->uiReverseReadOffset), 1, BXVD_P_MAX_ELEMENTS_IN_DISPLAY_QUEUE );
3673
3674      /* Get the context of this last picture. */
3675      pstPicCntxt = &pstContextQueue->astPictureContext[pDQTCntxt->uiReverseReadOffset];
3676
3677      /* Is there only one picture in the GOP? */
3678
3679      if ( pDQTCntxt->uiReverseReadOffset == uiDeliveryQReadOffset0Based )
3680      {
3681         /* Only one picture for this GOP.
3682          * If it is a "single" picture, all is good.
3683          * If it is from an incomplete set, an error condition;
3684          * will needed to trigger the DQT truncation logic.
3685          * This error condition will not be detected in the main "while" loop.
3686          */
3687         if ( BXVD_Decoder_P_PictureSet_eSingle == pstPicCntxt->eSetType )
3688         {
3689            pDQTCntxt->bConvertGopToUniPics = true;
3690            bSearchForStartOfNextGop = false;
3691            /*pDQTCntxt->bTruncatingGop = false;*/     /* SW7425-1261: only clear bTruncatingGop in ..._ReleaseGopTail */
3692
3693            BXVD_Decoder_S_Printf("\n\tSinglePic(good):: rr=%d  eog=%d ",
3694                           pDQTCntxt->uiReverseReadOffset,
3695                           pDQTCntxt->uiEndOfGopOffset
3696                           );
3697         }
3698         else
3699         {
3700            pDQTCntxt->bConvertGopToUniPics = false;
3701            pDQTCntxt->bTruncatingGop = true;
3702
3703            /* Need to backup the EOG offset to error picture */
3704            BXVD_Decoder_S_Decrement_0BasedOffset( &(pDQTCntxt->uiEndOfGopOffset), 1, BXVD_P_MAX_ELEMENTS_IN_DISPLAY_QUEUE );
3705
3706            BXVD_Decoder_S_Printf("\n\tSinglePic(bad):: rr=%d  eog=%d ",
3707                           pDQTCntxt->uiReverseReadOffset,
3708                           pDQTCntxt->uiEndOfGopOffset
3709                           );
3710
3711         }
3712      }
3713      else
3714      {
3715         /* More than one picture in the GOP. */
3716
3717         if ( true == bDqtMvcError )
3718         {
3719            pDQTCntxt->bTruncatingGop = true;
3720            BXVD_Decoder_S_Printf("MVC error ");
3721         }
3722
3723         /* If a deadlock and a multipicture protocol, we may have left off
3724          * on a base picture.  Backup the pointers to the next picture.
3725          * If at the first picture of the GOP, the code block above will
3726          * be executed.
3727          */
3728         if ( BXVD_Decoder_P_PictureSet_eBase == pstPicCntxt->eSetType )
3729         {
3730            BXVD_Decoder_S_Decrement_0BasedOffset( &(pDQTCntxt->uiReverseReadOffset), 1, BXVD_P_MAX_ELEMENTS_IN_DISPLAY_QUEUE );
3731            BXVD_Decoder_S_Decrement_0BasedOffset( &(pDQTCntxt->uiEndOfGopOffset), 1, BXVD_P_MAX_ELEMENTS_IN_DISPLAY_QUEUE );
3732         }
3733
3734         /* If a multipicture protocol (like MVC) backup until either
3735          * - the first picture of a complete set is found
3736          * - OR the head of the queue is reached.
3737          */
3738         while ( pDQTCntxt->uiReverseReadOffset != uiDeliveryQReadOffset0Based
3739                  && BXVD_Decoder_P_PictureSet_eDependent == pstPicCntxt->eSetType
3740               )
3741         {
3742            BXVD_Decoder_S_Decrement_0BasedOffset( &(pDQTCntxt->uiReverseReadOffset), 1, BXVD_P_MAX_ELEMENTS_IN_DISPLAY_QUEUE );
3743            pstPicCntxt = &pstContextQueue->astPictureContext[pDQTCntxt->uiReverseReadOffset];
3744         }
3745
3746         pDQTCntxt->bConvertGopToUniPics = ( pDQTCntxt->uiEndOfGopOffset != uiDeliveryQReadOffset0Based );
3747         bSearchForStartOfNextGop = ( false == pDQTCntxt->bConvertGopToUniPics );
3748
3749         BXVD_Decoder_S_Printf("\n\tEndGop:: rr=%d  eog=%d\n",
3750                        pDQTCntxt->uiReverseReadOffset,
3751                        pDQTCntxt->uiEndOfGopOffset
3752                        );
3753
3754      }  /* end of else ( uiReverseReadOffset != uiReadOffset ) */
3755
3756
3757      /* Convert back to "2-based" offsets. */
3758      pDQTCntxt->uiEndOfGopOffset += BXVD_P_INITIAL_OFFSET_DISPLAY_QUEUE;
3759      pDQTCntxt->uiReverseReadOffset += BXVD_P_INITIAL_OFFSET_DISPLAY_QUEUE;
3760
3761   }  /* end of if ( true == pDQTCntxt->bDqtEnabled && .... )  */
3762
3763   BXVD_Decoder_S_Printf("start validation:: Tail:%d Head:%d ",
3764         pstUnifiedQueue->pstContextTail->uiIndex,
3765         pstUnifiedQueue->pstContextHead->uiIndex
3766         );
3767
3768   if ( true  == pDQTCntxt->bDqtEnabled )
3769   {
3770      BXVD_Decoder_S_Printf("   search:%d  found:%d  deadlock:%d ",
3771            bSearchForStartOfNextGop,
3772            bFoundEndOfGop,
3773            bDeadlock
3774            );
3775   }
3776
3777   BXVD_Decoder_S_Printf("\n", NULL );
3778
3779   BXVD_DecoderTimer_P_SnapshotFunctionEndTime( hXvdCh,  BXVD_DecoderTimer_P_eFuncUQ_DQT );
3780
3781ProcessGop:
3782
3783   BXVD_DecoderTimer_P_SnapshotFunctionStartTime( hXvdCh, BXVD_DecoderTimer_P_eFuncUQ_Val );
3784
3785   /* Phase 3: update the Unified Picture Queue, i.e. add pictures (or sets of pictures)
3786    * to the Unified Queue in display order.
3787    */
3788   while ( false == bSearchForStartOfNextGop
3789            && true == BXVD_Decoder_S_ContextQ_PeekAtNextElement( hXvdCh, &pstPicCntxt )
3790         )
3791   {
3792      /* Check that the Unified Q has enough room.
3793       */
3794      uiUniQFreeElements = BXVD_Decoder_S_UnifiedQ_GetFreeCount( hXvdCh );
3795
3796      if ( pstPicCntxt->uiSetCount > uiUniQFreeElements )
3797      {
3798         BXVD_DBG_ERR(hXvdCh, ("BXVD_Decoder_S_UnifiedQ_Update Unified Q does not have enough room."));
3799         break;
3800      }
3801
3802      /* During the vetting of the delivery queue, mismatched sets of pictures
3803       * will be marked for dropping. The actual drop occurs here.
3804       */
3805      if ( true == pstPicCntxt->bDropPicture )
3806      {
3807         BXVD_Decoder_P_UnifiedPictureContext  stUnifiedContext;
3808
3809         /* Initialize "stUnifiedContext", in particular need to be certain that
3810          * "pstDependentUniContext" is NULL. For the normal code flow, this reset
3811          * is handled in "BXVD_Decoder_S_UnifiedQ_InvalidateElement.
3812          */
3813         BKNI_Memset( &stUnifiedContext, 0, sizeof( BXVD_Decoder_P_UnifiedPictureContext ) );
3814
3815
3816         BXVD_Decoder_S_Printf("edrop ", NULL );
3817
3818
3819         BXVD_Decoder_S_UnifiedQ_ValidatePicture( hXvdCh, pstPicCntxt, &stUnifiedContext, true );
3820
3821         /* Remove the picture from the delivery queue. This could have been done in the
3822          * preceeding loop, but it is done here to keep the manipulation of the deliver
3823          * queue in as few places as possible.
3824          */
3825         BXVD_Decoder_S_DeliveryQ_UpdateReadOffset( hXvdCh, pstLocalState, 1 );
3826
3827         /* Add the PPB to the release queue. */
3828
3829         BXVD_Decoder_S_ReleaseQ_AddPPB( hXvdCh, pstPicCntxt->stPPB.pPPBPhysical );
3830
3831      }
3832      else
3833      {
3834         /* Note: will only get complete sets of pictures at this point.
3835          * The following call adds the complete set of pictures to the Unified Queue.
3836          */
3837         BXVD_Decoder_S_UnifiedQ_AddPicture( hXvdCh, pstPicCntxt, true );
3838
3839         /* Remove the picture(s) from the delivery queue. */
3840
3841         BXVD_Decoder_S_DeliveryQ_UpdateReadOffset( hXvdCh, pstLocalState, pstPicCntxt->uiSetCount );
3842
3843      }
3844
3845
3846   }  /* end of while ( pictures on the context queue ) */
3847
3848
3849   BXVD_Decoder_S_Printf("\t end validation:: Tail:%d Head:%d\n",
3850         pstUnifiedQueue->pstContextTail->uiIndex,
3851         pstUnifiedQueue->pstContextHead->uiIndex
3852         );
3853
3854   BXVD_DecoderTimer_P_SnapshotFunctionEndTime( hXvdCh, BXVD_DecoderTimer_P_eFuncUQ_Val );
3855
3856   return;
3857
3858}  /* end of BXVD_Decoder_S_UnifiedQ_Update() */
3859
3860
3861
3862static void BXVD_Decoder_S_DeliveryQ_UpdateReadOffset(
3863   BXVD_ChannelHandle hXvdCh,
3864   BXVD_Decoder_P_LocalState* pstLocalState,
3865   uint32_t uiDeltaChange
3866   )
3867{
3868   uint32_t uiReadOffset;
3869
3870   BXVD_Decoder_P_DQTContext * pDQTCntxt = &( hXvdCh->stDecoderContext.stDqtCntxt );
3871
3872   BSTD_UNUSED( pstLocalState );
3873
3874   BDBG_ENTER( BXVD_Decoder_S_DeliveryQ_UpdateReadOffset );
3875
3876   BXVD_AVD_P_DELIVERY_QUEUE_GET_READ_OFFSET( hXvdCh, uiReadOffset );
3877
3878   /* If reading backwards from the display queue, update the "uiReverseReadOffset"
3879    * Othewise just update the standard "read offset".
3880   */
3881   if ( true == pDQTCntxt->bDqtEnabled )
3882   {
3883
3884         BXVD_Decoder_S_Printf("\nUpRdOff:: Rr=%d Qr=%d revPlay %d :: ",
3885                  pDQTCntxt->uiReverseReadOffset-BXVD_P_INITIAL_OFFSET_DISPLAY_QUEUE,
3886                  uiReadOffset-BXVD_P_INITIAL_OFFSET_DISPLAY_QUEUE,
3887                  pDQTCntxt->bConvertGopToUniPics
3888                  );
3889
3890      if ( true == pDQTCntxt->bConvertGopToUniPics )
3891      {
3892         if ( pDQTCntxt->uiReverseReadOffset == uiReadOffset )
3893         {
3894            /* If "uiReverseReadOffset" is equal to "*puiReadOffset", we've processed the
3895             * entire "head" of the GOP.
3896             *
3897             * Flag that we are done and jump the read offsets ahead to the "end" of
3898             * the GOP.
3899             *
3900             * Note: we could still be cleaning up pictures at the "tail" of this GOP.
3901            */
3902            pDQTCntxt->bConvertGopToUniPics = false;
3903
3904            uiReadOffset = pDQTCntxt->uiEndOfGopOffset;
3905            BXVD_AVD_P_DELIVERY_QUEUE_SET_READ_OFFSET( hXvdCh, uiReadOffset );
3906           
3907            pDQTCntxt->uiReverseReadOffset = pDQTCntxt->uiEndOfGopOffset;
3908
3909            /* For debug. */
3910            hXvdCh->stDecoderContext.stLogData.uiPicturesFromAvd += uiDeltaChange;
3911
3912            BXVD_Decoder_S_Printf("( done Rr=%d Qr=%d ) ",
3913                  pDQTCntxt->uiReverseReadOffset-BXVD_P_INITIAL_OFFSET_DISPLAY_QUEUE,
3914                  uiReadOffset-BXVD_P_INITIAL_OFFSET_DISPLAY_QUEUE
3915                  );
3916         }
3917         else
3918         {
3919            /* Still processing this GOP, simply decrement the read ahead offset. */
3920
3921            BXVD_Decoder_S_Decrement_2BasedOffset(
3922                     &(pDQTCntxt->uiReverseReadOffset),
3923                     uiDeltaChange,
3924                     BXVD_P_DISP_FIFO_DEPTH
3925                     );
3926
3927            /* For debug. */
3928            hXvdCh->stDecoderContext.stLogData.uiPicturesFromAvd += uiDeltaChange;
3929
3930            BXVD_Decoder_S_Printf("( just inc Rr=%d ) ",
3931                  pDQTCntxt->uiReverseReadOffset-BXVD_P_INITIAL_OFFSET_DISPLAY_QUEUE
3932                  );
3933         }
3934
3935      }
3936      else
3937      {
3938         /* If "bDqtEnabled" is true and "bConvertGopToUniPics" is false,
3939          * the entire GOP has not been delivered to the display queue.
3940          * Other logic should prevent this case from being reached.
3941         */
3942         BXVD_Decoder_S_Printf("\nUpRdOff:: not supposed to be here:: Rr=%d  Qr=%d inRev = %d  ", 
3943                                    pDQTCntxt->uiReverseReadOffset, 
3944                                    uiReadOffset, 
3945                                    pDQTCntxt->bConvertGopToUniPics
3946                                    );
3947      }
3948
3949
3950   }       /* end if ( bDqtEnabled )*/
3951   else
3952   {
3953      /* Normal play, simply increment the "read offset" */
3954
3955      BXVD_Decoder_S_Printf("\nUpRdOff:: %d(%d) ", uiReadOffset-BXVD_P_INITIAL_OFFSET_DISPLAY_QUEUE, uiDeltaChange );
3956
3957      BXVD_AVD_P_INCREMENT_2BASED_OFFSET( uiReadOffset, uiDeltaChange );
3958
3959      BXVD_AVD_P_DELIVERY_QUEUE_SET_READ_OFFSET( hXvdCh, uiReadOffset );
3960
3961      /* For debug. */
3962      hXvdCh->stDecoderContext.stLogData.uiPicturesFromAvd += uiDeltaChange;
3963
3964      /* Keep these values in lock step to avoid issues when transistioning into DQT. */
3965      pDQTCntxt->uiEndOfGopOffset = uiReadOffset;
3966      pDQTCntxt->uiReverseReadOffset = uiReadOffset;
3967
3968   }
3969
3970   BDBG_LEAVE( BXVD_Decoder_S_DeliveryQ_UpdateReadOffset );
3971
3972   return;
3973
3974}
3975
3976static void BXVD_Decoder_S_ReleaseQ_AddPPB(
3977   BXVD_ChannelHandle hXvdCh,
3978   BXVD_P_PPB *pPPBPhysical
3979   )
3980{
3981   uint32_t       uiReleaseWriteOffset;
3982   uint32_t       uiTempWriteOffset;
3983
3984   BXVD_P_PictureReleaseQueue * pReleaseQue;
3985
3986   BDBG_ENTER( BXVD_Decoder_S_ReleaseQ_AddPPB );
3987
3988   BDBG_ASSERT(pPPBPhysical);
3989
3990   /*  Initialize the local variables. */
3991   BXVD_AVD_P_RELEASE_QUEUE_GET_ADDR( hXvdCh, pReleaseQue );
3992   BXVD_AVD_P_RELEASE_QUEUE_GET_SHADOW_WRITE_OFFSET( hXvdCh, uiReleaseWriteOffset )
3993
3994   /* Verify that the offset in in range */
3995
3996   if ( ( uiReleaseWriteOffset - BXVD_P_INITIAL_OFFSET_DISPLAY_QUEUE ) >= BXVD_P_MAX_ELEMENTS_IN_DISPLAY_QUEUE  )
3997   {
3998      BXVD_DBG_ERR(hXvdCh,("BXVD_Decoder_S_ReleaseQ_AddPPB: out of range offset %d", uiReleaseWriteOffset - BXVD_P_INITIAL_OFFSET_DISPLAY_QUEUE));
3999      goto Done;
4000   }
4001
4002   /* "pPPBPhysical" should always be valid. */
4003
4004   if ( ( NULL != pPPBPhysical ) )
4005   {
4006
4007      BXVD_Decoder_S_Printf("relOffset:%d 0x%x \n",
4008            uiReleaseWriteOffset - BXVD_P_INITIAL_OFFSET_DISPLAY_QUEUE,
4009            pPPBPhysical
4010            );
4011
4012      /* Add the the element  to the release queue.  */
4013
4014      pReleaseQue->display_elements[ uiReleaseWriteOffset - BXVD_P_INITIAL_OFFSET_DISPLAY_QUEUE ] = pPPBPhysical;
4015
4016      /* Increment the release queue write offset. */
4017
4018      BXVD_AVD_P_INCREMENT_2BASED_OFFSET( uiReleaseWriteOffset, 1 );
4019      BXVD_AVD_P_RELEASE_QUEUE_SET_SHADOW_WRITE_OFFSET( hXvdCh, uiReleaseWriteOffset )
4020
4021      /* Read the value back to insure that the MIPS write buffer has been flushed to memory
4022       * TODO: still needed?
4023       */
4024      uiTempWriteOffset = uiReleaseWriteOffset;
4025
4026      /* For debug. */
4027      hXvdCh->stDecoderContext.stLogData.uiPicturesToAvd++;
4028
4029   }
4030
4031Done:
4032
4033   BDBG_LEAVE( BXVD_Decoder_S_ReleaseQ_AddPPB );
4034
4035   return;
4036
4037}  /* End of BXVD_Decoder_S_ReleaseQ_AddPPB() */
4038
4039
4040void BXVD_Decoder_S_DqtInit( BXVD_ChannelHandle hXvdCh )
4041{
4042   BDBG_ASSERT(hXvdCh);
4043
4044   /*
4045    * initialize the DQTM parameters
4046    */
4047   hXvdCh->stDecoderContext.stDqtCntxt.bConvertGopToUniPics = false;
4048   hXvdCh->stDecoderContext.stDqtCntxt.uiPreviousWrOffset = 0;
4049   hXvdCh->stDecoderContext.stDqtCntxt.uiTimesOffsetRepeated = 0;
4050
4051   hXvdCh->stDecoderContext.stDqtCntxt.bDqtEnabled =  hXvdCh->stDecoderContext.bReversePlayback;
4052
4053   hXvdCh->stDecoderContext.stDqtCntxt.uiDeadlockThreshold = BXVD_DECODER_DQT_DEADLOCK_THRESHOLD;
4054   hXvdCh->stDecoderContext.stDqtCntxt.bTruncatingGop = false;
4055   hXvdCh->stDecoderContext.stDqtCntxt.uiCurrentPicTag = -1;
4056   hXvdCh->stDecoderContext.stDqtCntxt.bValidPicTag = false;
4057
4058   BXVD_AVD_P_DELIVERY_QUEUE_GET_READ_OFFSET(
4059                  hXvdCh,
4060                  hXvdCh->stDecoderContext.stDqtCntxt.uiReverseReadOffset
4061                  );
4062   return;
4063
4064}
4065
4066
4067static bool  BXVD_Decoder_S_DeliveryQ_CheckForDeadlock(
4068   BXVD_ChannelHandle hXvdCh,
4069   uint32_t uiNumPicturesToProcess
4070   )
4071{
4072   bool     bDeadLock = false;
4073   uint32_t uiPicturesOnUniQue;
4074
4075   BXVD_Decoder_P_DQTContext * pDQTCntxt = &( hXvdCh->stDecoderContext.stDqtCntxt );
4076
4077   uiPicturesOnUniQue = BXVD_Decoder_S_UnifiedQ_GetPictureCount( hXvdCh );
4078
4079   /*
4080    * There are two potential deadlock conditions.
4081    *
4082    * One is at the end of a stream.  Since we only mark the beginning of
4083    * GOPs and not their end, the DQT code will not push out the last
4084    * GOP since it doesn't see the start of the next one.
4085    *
4086    * The other could occur when the firmware is waiting for a PPB to be freed
4087    * and the DQT code is waiting for the start of the next GOP.
4088    *
4089    * The system is not deadlocked if there are more pictures to process as
4090    * indicated by "uiNumPicturesToProcess".  The system is not deadlocked
4091    * if XDM is still working on the previous GOP as indicated by "uiPicturesOnUniQue".
4092    * If "uiPicturesOnUniQue" is equal to 1, the picture could be from the previous
4093    * decode (i.e. hold last picture).
4094    * This is a crude approach, but we declare a  deadlock situation if the Display Queue
4095    * write pointer has not advanced in "uiDeadlockThreshold" vsync's.
4096    */
4097   if (( 0 != uiNumPicturesToProcess ) || ( uiPicturesOnUniQue > 1 ))
4098   {
4099      pDQTCntxt->uiTimesOffsetRepeated = 0;
4100   }
4101   else
4102   {
4103      pDQTCntxt->uiTimesOffsetRepeated++;
4104
4105      if ( pDQTCntxt->uiTimesOffsetRepeated > pDQTCntxt->uiDeadlockThreshold )
4106      {
4107         bDeadLock = true;
4108
4109         BXVD_Decoder_S_Printf("\ndeadlock!!!\n", NULL );
4110      }
4111   }
4112
4113   return bDeadLock;
4114
4115}
4116
4117static void BXVD_Decoder_S_DeliveryQ_ReleaseGopTail(
4118   BXVD_ChannelHandle hXvdCh,
4119   BXVD_Decoder_P_LocalState * pstLocalState
4120   )
4121{
4122   bool                    bDoneProcessingGop;
4123   bool                    bNonDependentPicture;
4124   BXVD_P_DisplayElement   stDisplayElement;
4125   BXVD_Decoder_P_DQTContext *  pDQTCntxt;
4126   bool bPicturesToDrop;
4127
4128   uint32_t uiDqReadOffset;
4129   uint32_t uiWriteOffset;
4130   uint32_t uiTempOffset;
4131
4132   BXVD_P_PictureDeliveryQueue *          pstDeliveryQueue;
4133
4134   BXVD_Decoder_P_PictureContextQueue *   pstContextQueue = &(hXvdCh->stDecoderContext.stPictureContextQueue);
4135
4136   BXVD_Decoder_P_PictureContext *        pstTempPicCntxt;
4137
4138   BXVD_AVD_P_DELIVERY_QUEUE_GET_READ_OFFSET( hXvdCh, uiDqReadOffset );
4139
4140   BXVD_AVD_P_DELIVERY_QUEUE_GET_ADDR( hXvdCh, pstDeliveryQueue );
4141
4142   uiWriteOffset = pstLocalState->uiDeliveryQueueWriteOffset;
4143
4144   /*
4145    * Initialize the local variables.
4146    */
4147   pDQTCntxt = &( hXvdCh->stDecoderContext.stDqtCntxt );
4148
4149
4150   /* This routine is called when a GOP is being truncated.
4151    * While the pictures at the head of the GOP are being converted to
4152    * unified pictures, this routine releases the pictures at the tail.
4153    */
4154
4155   /* Are we done processing this GOP?
4156    * If the offset used to read the queue in reverse (uiReverseReadOffset) is
4157    * equal to the Delivery Queue read offset (uiDqReadOffset), all the PPB's
4158    * have been converted to Unified Pictures.
4159    * The check of "bConvertGopToUniPics" was needed for the implementation
4160    * prior to XDM.  It should be redundant at this time, but I want to do some
4161    * more testing before I remove it.
4162    */
4163   bDoneProcessingGop = ( pDQTCntxt->uiReverseReadOffset == uiDqReadOffset );
4164   bDoneProcessingGop &= ( false == pDQTCntxt->bConvertGopToUniPics );
4165
4166   bPicturesToDrop = ( pDQTCntxt->uiEndOfGopOffset != uiWriteOffset );
4167
4168   if ( true == bPicturesToDrop ) 
4169   {
4170      BXVD_Decoder_S_Printf("\nrelTail enter: Rr=%d DQ:%d/%d CQwr=%d Eog=%d done=%d\n",
4171                        pDQTCntxt->uiReverseReadOffset-BXVD_P_INITIAL_OFFSET_DISPLAY_QUEUE,
4172                        uiDqReadOffset-BXVD_P_INITIAL_OFFSET_DISPLAY_QUEUE,
4173                        uiWriteOffset-BXVD_P_INITIAL_OFFSET_DISPLAY_QUEUE,
4174                        pstContextQueue->uiWriteOffset,
4175                        pDQTCntxt->uiEndOfGopOffset-BXVD_P_INITIAL_OFFSET_DISPLAY_QUEUE,
4176                        bDoneProcessingGop
4177                        );
4178   }
4179
4180   /*
4181   ** There are still pictures to throw away if "uiEndOfGopOffset" hasn't caught up to
4182   ** the delivery queue write offset (i.e. "ui32WrPtr")
4183   */
4184   while( pDQTCntxt->uiEndOfGopOffset != uiWriteOffset )
4185   {
4186
4187      /* Get the address of the PPB */
4188      stDisplayElement.pPPBPhysical = (BXVD_P_PPB *)pstDeliveryQueue->display_elements[ pDQTCntxt->uiEndOfGopOffset - BXVD_P_INITIAL_OFFSET_DISPLAY_QUEUE];
4189
4190      BMEM_ConvertOffsetToAddress(
4191            hXvdCh->hSystemHeap,
4192            (uint32_t)( stDisplayElement.pPPBPhysical ),
4193            (void *)&( stDisplayElement.pPPB )
4194            );
4195
4196
4197      /* Determine the picture type; only look at the picture tag for
4198       * "non-dependent" pictures.
4199       */
4200      if ( !( stDisplayElement.pPPB->flags & BXVD_P_PPB_MULTIVIEW_FIELD_MASK )
4201            || ( stDisplayElement.pPPB->flags & BXVD_P_PPB_MULTIVIEW_BASE_FLAG )
4202         )
4203      {
4204         bNonDependentPicture = true;
4205      }
4206      else
4207      {
4208         bNonDependentPicture = false;
4209      }
4210
4211      /*
4212      ** If "picture_tag" doesn't match the saved value, we've reached the start of
4213      ** the next GOP. We're done cleaning up this GOP, update the appropriate offsets.
4214      ** If a "dependent" picture, simply drop it.  GOPs always start on a "single" or base picture.
4215      */
4216      if ( pDQTCntxt->uiCurrentPicTag != stDisplayElement.pPPB->picture_tag
4217            && true == bNonDependentPicture
4218         )
4219      {
4220         pDQTCntxt->bTruncatingGop = false;
4221
4222         BXVD_Decoder_S_Printf("\t old tag = %u  new tag =%u\n", pDQTCntxt->uiCurrentPicTag, stDisplayElement.pPPB->picture_tag );
4223
4224         if ( bDoneProcessingGop )
4225         {
4226            /*
4227            ** We'll hit this block only if the entire "head" of the GOP has been processed.
4228            ** If the "head" is still being processed, the logic in "BXVD_Decoder_S_DqtReadOffsetUpdate()"
4229            ** will update the read offsets.
4230            */
4231            uiDqReadOffset = pDQTCntxt->uiEndOfGopOffset;
4232            BXVD_AVD_P_DELIVERY_QUEUE_SET_READ_OFFSET( hXvdCh, uiDqReadOffset );
4233            pDQTCntxt->uiReverseReadOffset = pDQTCntxt->uiEndOfGopOffset;
4234         }
4235
4236         break;
4237      }
4238
4239      /* Release the picture and invalidate the entry in the picture context queue. */
4240
4241      BXVD_Decoder_S_Printf("\t releaseTail:: eog %d ", pDQTCntxt->uiEndOfGopOffset-BXVD_P_INITIAL_OFFSET_DISPLAY_QUEUE );
4242
4243      BXVD_Decoder_S_ReleaseQ_AddPPB( hXvdCh, stDisplayElement.pPPBPhysical );
4244
4245      pstTempPicCntxt = &(pstContextQueue->astPictureContext[ pDQTCntxt->uiEndOfGopOffset - BXVD_P_INITIAL_OFFSET_DISPLAY_QUEUE ]);
4246
4247      /*
4248       * Increment the "uiEndOfGopOffset" offset.
4249       */
4250      BXVD_AVD_P_INCREMENT_2BASED_OFFSET( pDQTCntxt->uiEndOfGopOffset, 1 );
4251
4252      /* For debug. */
4253      hXvdCh->stDecoderContext.stLogData.uiPicturesFromAvd++;
4254
4255      /*
4256       * Jump the Picture Context Queue write pointer ahead if it is lagging.
4257       * This is the normal mode of operation once "uiEndOfGopOffset" has caught
4258       * up to "pstUnifiedQueue->uiWriteOffset".
4259       * It can also happen if a PPB is added to the delivery queue between the call
4260       * to "BXVD_Decoder_P_UpdatePictureContextQueue() and this routine.
4261       */
4262      uiTempOffset = pstContextQueue->uiWriteOffset + BXVD_P_INITIAL_OFFSET_DISPLAY_QUEUE;
4263
4264      if ( pDQTCntxt->uiEndOfGopOffset <= uiWriteOffset
4265            && ( uiTempOffset < pDQTCntxt->uiEndOfGopOffset
4266                  || uiTempOffset > uiWriteOffset )
4267         )
4268      {
4269         pstContextQueue->uiWriteOffset = pDQTCntxt->uiEndOfGopOffset - BXVD_P_INITIAL_OFFSET_DISPLAY_QUEUE;
4270      }
4271      else if ( uiTempOffset < pDQTCntxt->uiEndOfGopOffset && uiTempOffset > uiWriteOffset )
4272      {
4273         pstContextQueue->uiWriteOffset = pDQTCntxt->uiEndOfGopOffset - BXVD_P_INITIAL_OFFSET_DISPLAY_QUEUE;
4274      }
4275
4276   }
4277
4278
4279   if ( bDoneProcessingGop && ( pDQTCntxt->uiEndOfGopOffset == uiWriteOffset  ))
4280   {
4281      /*
4282      ** We'll hit this block if
4283      ** - the entire "head" of the GOP has been processed
4284      ** - the "tail" is being cleaned up
4285      ** - the first picture of the next GOP has NOT been found
4286      **
4287      ** The preceding can happen if
4288      ** - the video decoder is really slow delivering the pictures in a GOP
4289      ** - or we've made it to the beginning of the stream and need to restart at the end
4290      **
4291      ** If the "head" is still being processed, the logic in "BXVD_Decoder_S_DqtReadOffsetUpdate()"
4292      ** will update the read offsets.
4293      */
4294      uiDqReadOffset = pDQTCntxt->uiEndOfGopOffset;
4295      BXVD_AVD_P_DELIVERY_QUEUE_SET_READ_OFFSET( hXvdCh, uiDqReadOffset );
4296
4297      pDQTCntxt->uiReverseReadOffset = pDQTCntxt->uiEndOfGopOffset;
4298   }
4299
4300   if ( true == bPicturesToDrop )   
4301   {
4302      BXVD_Decoder_S_Printf("relTail exit: Rr=%d DQ:%d/%d CQwr=%d Eog=%d playRev=%d\n",
4303                        pDQTCntxt->uiReverseReadOffset-BXVD_P_INITIAL_OFFSET_DISPLAY_QUEUE,
4304                        uiDqReadOffset-BXVD_P_INITIAL_OFFSET_DISPLAY_QUEUE,
4305                        uiWriteOffset-BXVD_P_INITIAL_OFFSET_DISPLAY_QUEUE,
4306                        pstContextQueue->uiWriteOffset,
4307                        pDQTCntxt->uiEndOfGopOffset-BXVD_P_INITIAL_OFFSET_DISPLAY_QUEUE,
4308                        pDQTCntxt->bConvertGopToUniPics
4309                        );
4310   }
4311
4312
4313   return;
4314
4315}
4316
4317/***************************************************************************
4318 *
4319 *
4320 *
4321 ***************************************************************************/
4322
4323
4324
4325/***************************************************************************
4326 *
4327 *   Public Routines
4328 *
4329 ***************************************************************************/
4330
4331/*
4332 * Returns the number of pictures on the unified picture queue.  For MVC,
4333 * this will be the number of picture "sets", i.e. the dependent pictures
4334 * are not included in the count.
4335 */
4336BERR_Code BXVD_Decoder_GetPictureCount_isr(
4337   BXVD_ChannelHandle hXvdCh,
4338   uint32_t *puiPictureCount
4339   )
4340{
4341   BDBG_ENTER( BXVD_Decoder_GetPictureCount_isr );
4342
4343   BXVD_DecoderTimer_P_SnapshotFunctionStartTime( hXvdCh, BXVD_DecoderTimer_P_eFuncGetPicCount );
4344
4345
4346   if ( true == hXvdCh->stDecoderContext.bDecoderHasBeenInitialized )
4347   {
4348      *puiPictureCount = BXVD_Decoder_S_UnifiedQ_GetPictureCount( hXvdCh );
4349   }
4350   else
4351   {
4352      *puiPictureCount = 0;
4353   }
4354
4355   BXVD_Decoder_S_Printf("_GetPictureCount_isr:: count = %d\n", *puiPictureCount );
4356
4357   BXVD_DecoderTimer_P_SnapshotFunctionEndTime( hXvdCh, BXVD_DecoderTimer_P_eFuncGetPicCount );
4358
4359   BDBG_LEAVE( BXVD_Decoder_GetPictureCount_isr );
4360   return BERR_TRACE( BERR_SUCCESS );
4361
4362}  /* end of BXVD_Decoder_GetPictureCount_isr */
4363
4364
4365/*
4366 *
4367 */
4368BERR_Code BXVD_Decoder_PeekAtPicture_isr(
4369         BXVD_ChannelHandle hXvdCh,
4370         uint32_t uiIndex,
4371         BXDM_Picture **pUnifiedPicture
4372         )
4373{
4374   BXVD_Decoder_P_UnifiedPictureContext * pstUnifiedContext;
4375
4376   BDBG_ENTER( BXVD_Decoder_PeekAtPicture_isr );
4377
4378   /* TODO: add code to use the index */
4379   BSTD_UNUSED( uiIndex );
4380
4381   BXVD_DecoderTimer_P_SnapshotFunctionStartTime( hXvdCh, BXVD_DecoderTimer_P_eFuncPeekAtPic );
4382
4383   BXVD_Decoder_S_UnifiedQ_UnifiedContextGet( hXvdCh, &pstUnifiedContext, false );
4384
4385   *pUnifiedPicture = &(pstUnifiedContext->stUnifiedPicture);
4386
4387   BDBG_LEAVE( BXVD_Decoder_PeekAtPicture_isr );
4388
4389   BXVD_DecoderTimer_P_SnapshotFunctionEndTime( hXvdCh, BXVD_DecoderTimer_P_eFuncPeekAtPic );
4390
4391   return BERR_TRACE( BERR_SUCCESS );
4392
4393}  /* end of BXVD_Decoder_PeekAtPicture_isr */
4394
4395/*
4396 *
4397 */
4398BERR_Code BXVD_Decoder_GetNextPicture_isr(
4399         BXVD_ChannelHandle hXvdCh,
4400         BXDM_Picture **pUnifiedPicture
4401         )
4402{
4403   BXVD_Decoder_P_UnifiedPictureContext * pstUnifiedContext;
4404
4405   BDBG_ENTER( BXVD_Decoder_GetNextPicture_isr );
4406
4407   BXVD_DecoderTimer_P_SnapshotFunctionStartTime( hXvdCh, BXVD_DecoderTimer_P_eFuncGetNextPic );
4408
4409   BXVD_Decoder_S_Printf("_GetNextPicture_isr:: ", NULL );
4410
4411   BXVD_Decoder_S_UnifiedQ_UnifiedContextGet( hXvdCh, &pstUnifiedContext, true );
4412
4413   *pUnifiedPicture = &(pstUnifiedContext->stUnifiedPicture);
4414
4415   /*
4416    * Now that the PPB is being "processed", enqueue any user data.
4417    */
4418   if( pstUnifiedContext->pPPB->user_data )
4419   {
4420      BXVD_DecoderTimer_P_SnapshotCallbackStartTime( hXvdCh, BXVD_DecoderTimer_P_eCbUserData );
4421
4422      /*
4423       * uiSerialNumber is passed to userdata where it is stored as uiDecoderPictureId.
4424       * See Jira SW7425-1780 for an explanation.
4425       */
4426      BXVD_P_Userdata_EnqueueDataPointer(
4427               hXvdCh,
4428               pstUnifiedContext->pPPB->protocol,
4429               (unsigned long)pstUnifiedContext->pPPB->user_data ,
4430               pstUnifiedContext->pPPB->flags,
4431               pstUnifiedContext->pPPB->pulldown,
4432               pstUnifiedContext->pPPB->pts,
4433               pstUnifiedContext->stUnifiedPicture.uiSerialNumber);
4434
4435      BXVD_DecoderTimer_P_SnapshotCallbackEndTime( hXvdCh, BXVD_DecoderTimer_P_eCbUserData );
4436   }
4437
4438   /* For debug. */
4439   hXvdCh->stDecoderContext.stLogData.uiPicturesToPP++;
4440
4441#if BXVD_DM_ENABLE_YUV_GRAB_MODE
4442
4443   if( true == hXvdCh->stDecoderContext.bGrabPpb )
4444      BXVD_Decoder_S_Dbg_DumpPPB( pstUnifiedContext->pPPB );
4445
4446   if( true == hXvdCh->stDecoderContext.bGrabYuv )
4447      BXVD_Decoder_S_Dbg_DumpYUV( hXvdCh, pstUnifiedContext->pPPB );
4448
4449   if( true == hXvdCh->stDecoderContext.bGrabRvc )
4450      BXVD_Decoder_S_Dbg_DumpRVC( hXvdCh );
4451
4452#endif
4453
4454   BXVD_DecoderTimer_P_SnapshotFunctionEndTime( hXvdCh, BXVD_DecoderTimer_P_eFuncGetNextPic );
4455
4456
4457   BDBG_LEAVE( BXVD_Decoder_GetNextPicture_isr );
4458   return BERR_TRACE( BERR_SUCCESS );
4459
4460}  /* end of BXVD_Decoder_GetNextPicture_isr */
4461
4462/*
4463 *
4464 */
4465BERR_Code BXVD_Decoder_ReleasePicture_isr(
4466         BXVD_ChannelHandle hXvdCh,
4467         BXDM_Picture *pUnifiedPicture,
4468         const BXDM_Decoder_ReleasePictureInfo *pReleasePictureInfo
4469         )
4470{
4471   BXVD_Decoder_P_UnifiedPictureContext * pstUnifiedContext;
4472
4473   BDBG_ENTER( BXVD_Decoder_ReleasePicture_isr );
4474
4475   BSTD_UNUSED(pReleasePictureInfo);
4476
4477   BXVD_DecoderTimer_P_SnapshotFunctionStartTime( hXvdCh, BXVD_DecoderTimer_P_eFuncReleasePic );
4478
4479   BXVD_Decoder_S_Printf("_ReleasePicture_isr:: ", NULL );
4480
4481   pstUnifiedContext = pUnifiedPicture->pPrivateContext;
4482
4483   BXVD_Decoder_S_UnifiedQ_UnifiedContextRelease( hXvdCh, pstUnifiedContext );
4484
4485   /* For debug. */
4486   hXvdCh->stDecoderContext.stLogData.uiPicturesFromPP++;
4487
4488
4489   BXVD_DecoderTimer_P_SnapshotFunctionEndTime( hXvdCh, BXVD_DecoderTimer_P_eFuncReleasePic );
4490
4491   BDBG_LEAVE( BXVD_Decoder_ReleasePicture_isr );
4492
4493   return BERR_TRACE( BERR_SUCCESS );
4494
4495}  /* end of BXVD_Decoder_ReleasePicture_isr */
4496
4497
4498/*
4499 *
4500 */
4501BERR_Code
4502BXVD_Decoder_GetPictureDropPendingCount_isr(
4503         BXVD_ChannelHandle hXvdCh,
4504         uint32_t *puiPictureDropPendingCount
4505         )
4506{
4507   BXVD_Decoder_P_UnifiedPictureContext * pstUnifiedContext;
4508
4509   uint32_t uiNumToBeDropped;
4510
4511   BXVD_AVD_P_GET_DROP_COUNT( hXvdCh, uiNumToBeDropped );
4512
4513   BDBG_ENTER( BXVD_Decoder_GetPictureDropPendingCount_isr );
4514
4515   BDBG_ASSERT( hXvdCh );
4516   BDBG_ASSERT( puiPictureDropPendingCount );
4517
4518   /* The "pending drop count" is difference between the number of pictures
4519    * that the Picture Provider has requested to be dropped and the number
4520    * that AVD has actually dropped.
4521    * When this value transistions from non-zero to zero, the Picture Provider
4522    * will transistion from VSYNC to TSM mode.  At this point, the PP will need
4523    * a valid coded PTS.  For this reason, "uiDropCount" is a sampled version of
4524    * "n_drop" which is only updated when a PPB contains a coded PTS.
4525    *
4526    * Never allow the pending drop count to be less than '0'.  If more pictures have been
4527    * dropped than was requested, return a pending drop of '0'.
4528    *
4529    * SW7405-3929/-3925: Check that there are pictures in the queue, before asking for the context
4530    * (contents of the returned context are invalid if no pictures available)
4531    * If this is not done, pending drops can "ping-pong" between current value
4532    * and zero, causing selection mode to ping-pong between vTSM and TSM mode
4533    */
4534   if ( BXVD_Decoder_S_UnifiedQ_GetPictureCount(hXvdCh) )
4535   {
4536      BXVD_Decoder_S_UnifiedQ_UnifiedContextGet( hXvdCh, &pstUnifiedContext, false );
4537
4538      if ( uiNumToBeDropped < pstUnifiedContext->uiDropCount )
4539      {
4540         *puiPictureDropPendingCount = 0;
4541      }
4542      else
4543      {
4544         *puiPictureDropPendingCount = uiNumToBeDropped - pstUnifiedContext->uiDropCount;
4545      }
4546   }
4547   else
4548   {
4549      /* No pictures available in the unified Q, so we need to use previous data to supply the drop count ... */
4550      if ( uiNumToBeDropped < hXvdCh->stDecoderContext.uiDropCountSnapshot)
4551      {
4552         *puiPictureDropPendingCount = 0;
4553      }
4554      else
4555      {
4556         *puiPictureDropPendingCount = uiNumToBeDropped - hXvdCh->stDecoderContext.uiDropCountSnapshot;
4557      }
4558   }
4559
4560   BDBG_LEAVE( BXVD_Decoder_GetPictureDropPendingCount_isr );
4561   return BERR_TRACE( BERR_SUCCESS );
4562
4563}  /* end of BXVD_Decoder_GetPictureDropPendingCount_isr */
4564
4565/*
4566 *
4567 */
4568BERR_Code
4569BXVD_Decoder_RequestPictureDrop_isr(
4570         BXVD_ChannelHandle hXvdCh,
4571         uint32_t *puiPictureDropRequestCount
4572         )
4573{
4574   uint32_t uiDropsRequested = 0;
4575
4576   uint32_t uiDropCount;
4577
4578   BXVD_AVD_P_GET_DROP_COUNT( hXvdCh, uiDropCount );
4579
4580   BDBG_ENTER( BXVD_Decoder_RequestPictureDrop_isr );
4581
4582   BDBG_ASSERT( hXvdCh );
4583
4584   /* We only request more drops if the decoder has caught up with the previous drop request.
4585    */
4586   if ( uiDropCount <= hXvdCh->stDecoderContext.uiDropCountSnapshot )
4587   {
4588      if ( *puiPictureDropRequestCount > BXVD_DECODER_MAX_FIELDS_TO_DROP )
4589      {
4590         /* PR47521: We need to cap the max requested drop count to prevent scenarious where a
4591          * large drop@decode request would occur that would normally recover on it's own.
4592          * (e.g. a unmarked stream discontinuity or stream wrap.).
4593          * We really only want to do a drop@decode if the stream is muxed poorly and/or we're
4594          * trying to do STC fast forward trick modes.  In such scenarioes, if we still need
4595          * more drops to catch up, the Picture Provider can always request more after the
4596          * initial drop has occurred.
4597          */
4598         uiDropsRequested = BXVD_DECODER_MAX_FIELDS_TO_DROP;
4599
4600      }
4601      else
4602      {
4603         /* The decoder drops 2 fields at a time; ensure that "uiPictureDropRequestCount"
4604          * is an even value.
4605          */
4606         uiDropsRequested = *puiPictureDropRequestCount & ~0x01;
4607      }
4608     
4609      uiDropCount += uiDropsRequested;
4610      BXVD_AVD_P_SET_DROP_COUNT( hXvdCh, uiDropCount );
4611
4612   }
4613
4614   /* SE7405-3925: Update the actual number of drops requested from the decoder, to allow the caller
4615      to accurately update the drop request count status ... */
4616   *puiPictureDropRequestCount = uiDropsRequested;
4617
4618   BDBG_LEAVE( BXVD_Decoder_RequestPictureDrop_isr );
4619   return BERR_TRACE( BERR_SUCCESS );
4620
4621}  /* end of BXVD_Decoder_RequestPictureDrop_isr */
4622
4623/*
4624 *
4625 */
4626BERR_Code
4627BXVD_Decoder_DisplayInterruptEvent_isr(
4628         BXVD_ChannelHandle hXvdCh
4629         )
4630{
4631   BXVD_Decoder_P_LocalState stLocalDecoderState;
4632   BXVD_Decoder_P_LocalState * pstLocalState;
4633
4634   BDBG_ENTER( BXVD_Decoder_DisplayInterruptEvent_isr );
4635
4636   BDBG_ASSERT(hXvdCh);
4637
4638   /* Hold off processing until the queues have been intialized. */
4639
4640   if ( true == hXvdCh->stDecoderContext.bDecoderHasBeenInitialized )
4641   {
4642      BXVD_DecoderTimer_P_SnapshotFunctionStartTime( hXvdCh, BXVD_DecoderTimer_P_eFuncDisplayIsr );
4643
4644      /* Initialize the local variable(s). */
4645
4646      pstLocalState = &(stLocalDecoderState);
4647
4648      hXvdCh->stDecoderContext.stCounters.uiVsyncCount++;
4649
4650      /* Snapshot the delivery queue write offset so that it
4651       * is constant during the execution of the decoder ISR.
4652       */
4653      BXVD_AVD_P_DELIVERY_QUEUE_GET_WRITE_OFFSET( hXvdCh, pstLocalState->uiDeliveryQueueWriteOffset );
4654
4655      BXVD_Decoder_S_UnifiedQ_Update( hXvdCh, pstLocalState );
4656
4657      BXVD_Decoder_S_Log_Print( hXvdCh, pstLocalState );
4658
4659      BXVD_DecoderTimer_P_SnapshotFunctionEndTime( hXvdCh, BXVD_DecoderTimer_P_eFuncDisplayIsr );
4660      BXVD_DecoderTimer_P_PrintResults( hXvdCh );
4661
4662   }
4663
4664   BDBG_LEAVE( BXVD_Decoder_DisplayInterruptEvent_isr );
4665   return BERR_TRACE( BERR_SUCCESS );
4666
4667}  /* end of BXVD_Decoder_DisplayInterruptEvent_isr */
4668
4669/*
4670 *
4671 */
4672BERR_Code
4673BXVD_Decoder_GetDMInterface(
4674         BXVD_ChannelHandle hXvdCh,
4675         BXDM_Decoder_Interface *pstDecoderInterface,
4676         void **pPrivateContext
4677         )
4678{
4679   BDBG_ENTER( BXVD_Decoder_GetDMInterface );
4680
4681   BDBG_ASSERT( pstDecoderInterface );
4682   BDBG_ASSERT( pPrivateContext );
4683
4684   BKNI_Memset( pstDecoderInterface, 0, sizeof( BXDM_Decoder_Interface ) );
4685
4686   pstDecoderInterface->getPictureCount_isr = (BXDM_Decoder_GetPictureCount_isr) BXVD_Decoder_GetPictureCount_isr;
4687   pstDecoderInterface->peekAtPicture_isr = (BXDM_Decoder_PeekAtPicture_isr) BXVD_Decoder_PeekAtPicture_isr;
4688   pstDecoderInterface->getNextPicture_isr = (BXDM_Decoder_GetNextPicture_isr) BXVD_Decoder_GetNextPicture_isr;
4689   pstDecoderInterface->releasePicture_isr = (BXDM_Decoder_ReleasePicture_isr) BXVD_Decoder_ReleasePicture_isr;
4690   pstDecoderInterface->getPictureDropPendingCount_isr = (BXDM_Decoder_GetPictureDropPendingCount_isr) BXVD_Decoder_GetPictureDropPendingCount_isr;
4691   pstDecoderInterface->requestPictureDrop_isr = (BXDM_Decoder_RequestPictureDrop_isr) BXVD_Decoder_RequestPictureDrop_isr;
4692   pstDecoderInterface->displayInterruptEvent_isr  = (BXDM_Decoder_DisplayInterruptEvent_isr) BXVD_Decoder_DisplayInterruptEvent_isr;
4693   pstDecoderInterface->displayInterruptStatus_isr = NULL;
4694
4695   *pPrivateContext = hXvdCh;
4696
4697   BXVD_Decoder_S_OpenChannel( hXvdCh );
4698
4699   BDBG_LEAVE( BXVD_Decoder_GetDMInterface );
4700   return BERR_TRACE( BERR_SUCCESS );
4701
4702}  /* end of BXVD_Decoder_GetDMInterface */
4703
4704/*
4705 *
4706 */
4707BERR_Code BXVD_Decoder_GetPPBParameterQueueInfo_isr(
4708   BXVD_ChannelHandle hXvdCh,
4709   const BXVD_PPBParameterInfo* apstPPBParameterInfo[],
4710   uint32_t uiPPBParameterInfoCount,
4711   uint32_t *puiValidPPBParameterInfoCount
4712   )
4713{
4714   uint32_t i;
4715   BXVD_Decoder_P_UnifiedPictureQueue * pstUnifiedQueue = &hXvdCh->stDecoderContext.stUnifiedPictureQueue;
4716   BXVD_Decoder_P_UnifiedPictureContext * pstUnifiedContext;
4717
4718   BDBG_ENTER( BXVD_Decoder_GetPPBParameterQueueInfo_isr );
4719
4720   BDBG_ASSERT( hXvdCh );
4721   BDBG_ASSERT(apstPPBParameterInfo);
4722   BDBG_ASSERT(puiValidPPBParameterInfoCount);
4723   BDBG_ASSERT(uiPPBParameterInfoCount > 0);
4724
4725   *puiValidPPBParameterInfoCount = 0;
4726
4727   pstUnifiedContext = pstUnifiedQueue->pstContextTail;
4728
4729   for (i = 0; i < uiPPBParameterInfoCount; i++)
4730   {
4731      /* Note: when DQT is enabled, the pictures are returned in display order, which
4732       * is reverse.
4733       */
4734
4735      if ( NULL != pstUnifiedContext
4736         && true == pstUnifiedContext->bInUse )
4737      {
4738         apstPPBParameterInfo[i] = &(pstUnifiedContext->stUnifiedPicture);
4739         (*puiValidPPBParameterInfoCount)++;
4740
4741         /*Note: this returns the dependent pictures as well. */
4742         pstUnifiedContext = pstUnifiedContext->pstNextUniContext;
4743      }
4744      else
4745      {
4746         apstPPBParameterInfo[i] = NULL;
4747      }
4748   }
4749
4750   BDBG_LEAVE( BXVD_Decoder_GetPPBParameterQueueInfo_isr );
4751   return BERR_TRACE( BERR_SUCCESS );
4752
4753}  /* end of BXVD_Decoder_GetPPBParameterQueueInfo_isr */
4754
4755/*
4756 *
4757 */
4758BERR_Code
4759BXVD_Decoder_SetCRCMode_isr(
4760         BXVD_ChannelHandle hXvdCh,
4761         bool bEnable)
4762{
4763   BERR_Code rc = BERR_SUCCESS;
4764
4765   BDBG_ENTER(BXVD_Decoder_SetCRCMode_isr);
4766
4767   BDBG_ASSERT( hXvdCh );
4768
4769   hXvdCh->stDecoderContext.bCRCMode = bEnable;
4770
4771   BXVD_Decoder_S_Printf("BXVD_Decoder_SetCRCMode_isr(%d)\n", bEnable);
4772
4773   BDBG_LEAVE(BXVD_Decoder_SetCRCMode_isr);
4774
4775   return BERR_TRACE( rc );
4776}
4777
4778/*
4779 *
4780 */
4781BERR_Code
4782BXVD_Decoder_GetCRCMode_isr(
4783         BXVD_ChannelHandle hXvdCh,
4784         bool *pbEnable)
4785{
4786   BERR_Code rc = BERR_SUCCESS;
4787
4788   BDBG_ENTER(BXVD_Decoder_GetCRCMode_isr);
4789
4790   BDBG_ASSERT( hXvdCh );
4791   BDBG_ASSERT( pbEnable );
4792
4793   *pbEnable = hXvdCh->stDecoderContext.bCRCMode;
4794
4795   BDBG_LEAVE(BXVD_Decoder_GetCRCMode_isr);
4796
4797   return BERR_TRACE( rc );
4798}
4799
4800/*
4801 *
4802 */
4803BERR_Code BXVD_Decoder_StartDecode_isr(
4804   BXVD_ChannelHandle hXvdCh
4805   )
4806{
4807   BERR_Code rc = BERR_SUCCESS;
4808
4809   BDBG_ENTER(BXVD_Decoder_StartDecode_isr);
4810
4811   BDBG_ASSERT( hXvdCh );
4812   BSTD_UNUSED(hXvdCh);
4813
4814   BXVD_Decoder_S_Printf("BXVD_Decoder_StartDecode_isr\n", NULL );
4815
4816   /* Nothing to do for the Unified Picture Queue, it is intialized
4817    * in "BXVD_Decoder_S_OpenChannel".  Also keep in mind that XDM
4818    * could still be holding onto pictures from a previous stream.
4819    * If the queue was reset, the decoder would not be able to return
4820    * the PPB's to the decoder.
4821    */
4822
4823   /* TODO: should a snapshot be taken at start decode time instead of changing
4824    * on the fly?
4825    */
4826   /*hXvdCh->stDecoderContext.bCRCMode = hXvdCh->sDecodeSettings.bCrcMode;*/
4827
4828#if 0 /* From DM V2. */
4829   if (!hXvdCh->stDMState.stChannel.bDMVersionDisplayed)
4830   {
4831      BXVD_DBG_WRN(hXvdCh,("Display Manager: [v%02d.%02d.%04d]",
4832                                BXVD_DM_P_VERSION_MAJOR,
4833                                BXVD_DM_P_VERSION_MINOR,
4834                                BXVD_DM_P_VERSION_SUBMINOR));
4835      hXvdCh->stDMState.stChannel.bDMVersionDisplayed = true;
4836   }
4837
4838   BXVD_DMDBG_P_PrintNodes(hXvdCh);
4839
4840
4841   /* TODO: NA - We should probably remove the bPointerInitDone
4842    * variable altogether.  Right now, BXVD_INTR checks it before
4843    * calling into DM, so we'll leave it in to be compatible with the
4844    * old DM */
4845   hXvdCh->stDMStatus.bPointerInitDone = true;
4846
4847#endif
4848
4849   /* Initialize the DQT logic */
4850
4851   BXVD_Decoder_S_DqtInit( hXvdCh );
4852
4853
4854   /* Initialize the picture context queue. */
4855
4856   BXVD_AVD_P_DELIVERY_QUEUE_GET_READ_OFFSET(
4857            hXvdCh,
4858            hXvdCh->stDecoderContext.stPictureContextQueue.uiWriteOffset
4859            );
4860
4861   hXvdCh->stDecoderContext.stPictureContextQueue.uiWriteOffset -= BXVD_P_INITIAL_OFFSET_DISPLAY_QUEUE;
4862
4863   /* Need to initialize in case the first PPB(s) don't contain a coded PTS. */
4864   hXvdCh->stDecoderContext.uiDropCountSnapshot = 0;
4865
4866   /* Reset drop request count */
4867   BXVD_AVD_P_SET_DROP_COUNT( hXvdCh, 0 );
4868
4869   /* Used to hold off processing in "BXVD_Decoder_DisplayInterruptEvent_isr"
4870    * until this routine has been called.  Implicit at this point of execution
4871    * is that the AVD queues have been initialized as well.  This is
4872    * essentially the old "eVideoState = BXVD_P_VideoState_DecodeStarted".
4873    */
4874   hXvdCh->stDecoderContext.bDecoderHasBeenInitialized = true;
4875
4876
4877   /* Conditionally initialize the decoder counter(s) */
4878   if ( false == hXvdCh->bPreserveCounters )
4879   {
4880      BKNI_Memset( &(hXvdCh->stDecoderContext.stCounters), 0, sizeof( BXVD_Decoder_Counters ) );
4881   }
4882
4883   /* For debug. */
4884   BXVD_Decoder_S_Log_Init( hXvdCh );
4885
4886   BKNI_Memset( &(hXvdCh->stDecoderContext.stLogData.stTimerData), 0, sizeof(BXVD_DecoderTimer_P_Data) );
4887
4888
4889#if BXVD_DM_ENABLE_YUV_GRAB_MODE
4890
4891   hXvdCh->stDecoderContext.bGrabPpb = ( NULL == getenv("grabppb")) ? false : true;
4892   hXvdCh->stDecoderContext.bGrabYuv = ( NULL == getenv("grabyuv")) ? false : true;
4893   hXvdCh->stDecoderContext.bGrabRvc = ( NULL == getenv("grabrvc")) ? false : true;
4894
4895   if ( true == hXvdCh->stDecoderContext.bGrabRvc )
4896   {
4897      BXVD_Reg_Write32_isr (hXvdCh->pXvd, hXvdCh->pXvd->stPlatformInfo.stReg.uiDecode_RVCCtl, 0x01);
4898   }
4899#endif
4900
4901   BDBG_LEAVE(BXVD_Decoder_StartDecode_isr);
4902
4903   return BERR_TRACE( rc );
4904
4905}
4906
4907/*
4908 *
4909 */
4910BERR_Code BXVD_Decoder_StopDecode_isr(
4911   BXVD_ChannelHandle hXvdCh
4912   )
4913{
4914   BERR_Code rc = BERR_SUCCESS;
4915   BXVD_Decoder_P_UnifiedPictureContext * pstUnifiedContext;
4916   BXVD_Decoder_P_DQTContext * pDQTCntxt = &( hXvdCh->stDecoderContext.stDqtCntxt );
4917
4918
4919   BDBG_ENTER(BXVD_Decoder_StopDecode_isr);
4920
4921   BDBG_ASSERT( hXvdCh );
4922
4923   BXVD_Decoder_S_Printf("BXVD_Decoder_StopDecode_isr:: ", NULL );
4924
4925   /* Hold off processing in "BXVD_Decoder_DisplayInterruptEvent_isr"
4926    * until the queues have been reinitialized.
4927    */
4928   hXvdCh->stDecoderContext.bDecoderHasBeenInitialized = false;
4929
4930   /*
4931    * Release any pictures on the Unified Picture Queue.
4932    * XDM could still be holding onto pictures, don't reset the queue.
4933    */
4934   while ( BXVD_Decoder_S_UnifiedQ_GetPictureCount( hXvdCh ) )
4935   {
4936      BXVD_Decoder_S_UnifiedQ_UnifiedContextGet( hXvdCh, &pstUnifiedContext, true );
4937      BXVD_Decoder_S_UnifiedQ_UnifiedContextRelease( hXvdCh, pstUnifiedContext );
4938   }
4939
4940   /*
4941    * Conditionally clear the PVR state.
4942    */
4943   if ( false == hXvdCh->bPreserveState )
4944   {
4945      /* Disable the reverse playback of GOPs */
4946      hXvdCh->stDecoderContext.bReversePlayback = false;
4947
4948      hXvdCh->stDecoderContext.bHostSparseMode = false;
4949   }
4950
4951   /* In the event the Display Manager was cleaning up a "truncated" GOP,
4952    * clear the flags now.  Any pictures that remain at the end of the GOP
4953    * (in the delivery queue) will be cleaned up by the decoder.
4954    */
4955   pDQTCntxt->bTruncatingGop = false;
4956   pDQTCntxt->bValidPicTag = false;
4957
4958   BDBG_LEAVE(BXVD_Decoder_StopDecode_isr);
4959
4960   return BERR_TRACE( rc );
4961}
4962
4963/*
4964 *
4965 */
4966BERR_Code BXVD_Decoder_WatchdogReset_isr(
4967   BXVD_ChannelHandle hXvdCh
4968   )
4969{
4970   BDBG_ENTER(BXVD_Decoder_WatchdogReset_isr);
4971
4972   BDBG_ASSERT( hXvdCh );
4973
4974   BXVD_Decoder_S_Printf("BXVD_Decoder_WatchdogReset_isr:: ", NULL );
4975
4976   /* Hold off processing in "BXVD_Decoder_DisplayInterruptEvent_isr"
4977    * until the queues have been reinitialized.
4978    */
4979   hXvdCh->stDecoderContext.bDecoderHasBeenInitialized = false;
4980
4981   /*
4982    * Reset the Unified Picture Queue.
4983    */
4984   BXVD_Decoder_S_UnifiedQ_Initialize( hXvdCh );
4985
4986   BDBG_LEAVE(BXVD_Decoder_WatchdogReset_isr);
4987
4988   return BERR_SUCCESS;
4989}
4990
4991/*
4992 *
4993 */
4994BERR_Code BXVD_Decoder_GetCounters_isr(
4995   BXVD_ChannelHandle hXvdCh,
4996   BXVD_Decoder_Counters * pstCounters
4997   )
4998{
4999   BDBG_ENTER(BXVD_Decoder_GetCounters_isr);
5000
5001   BDBG_ASSERT( hXvdCh );
5002
5003   *pstCounters = hXvdCh->stDecoderContext.stCounters;
5004
5005   BDBG_LEAVE(BXVD_Decoder_GetCounters_isr);
5006
5007   return BERR_SUCCESS;
5008}
5009
5010/*
5011 * Routines to support the "grab" debug mode.
5012 */
5013#if BXVD_DM_ENABLE_YUV_GRAB_MODE
5014
5015/*
5016 * BXVD_Decoder_S_Dbg_SwapLong
5017 */
5018static uint32_t BXVD_Decoder_S_Dbg_SwapLong (
5019   uint32_t a
5020   )
5021{
5022   return ((a >> 24) & 0x000000FF)
5023            | ((a >>  8) & 0x0000FF00)
5024            | ((a <<  8) & 0x00FF0000)
5025            | ((a << 24) & 0xFF000000);
5026}
5027
5028/*
5029 * BXVD_Decoder_S_Dbg_DestripeSection
5030 */
5031static int32_t BXVD_Decoder_S_Dbg_DestripeSection (
5032   unsigned char *from,
5033   unsigned char *to,
5034   int32_t image_wid,
5035   int32_t image_hgt,
5036   int32_t stripe_wid,
5037   int32_t stripe_hgt,
5038   uint32_t ulRangeRemapping
5039   )
5040{
5041   int32_t stripe_size = stripe_wid * stripe_hgt;
5042   int32_t pixels      = image_wid  * image_hgt;
5043
5044   int32_t i;
5045   int32_t scol;
5046   int32_t icol;
5047   int32_t lpel;
5048   unsigned char *ptr, pel;
5049
5050   /* memset (to, 0, pixels); */
5051   scol = 0;
5052   icol = 0;
5053   ptr  = from;
5054
5055   for (i = 0; i < pixels; i++)
5056   {
5057      /* apply range mapping equation */
5058
5059      pel = ptr [scol];
5060      if (ulRangeRemapping != 8)
5061      {
5062         lpel = (uint32_t) pel;
5063
5064         lpel = ((((lpel - 128) *  (int32_t) ulRangeRemapping) + 4) >> 3) + 128;
5065         if (lpel > 255) pel = 255;
5066         else if (lpel < 0) pel = 0;
5067         else pel = (unsigned char) lpel;
5068      }
5069
5070      *to++ = pel;
5071
5072      /* If we reach the end of a stripe, move down to the
5073       * next strip to continue this row.
5074       */
5075      if (++scol == stripe_wid)
5076      {
5077         scol = 0;
5078         ptr += stripe_size;
5079      }
5080
5081      /* If we reach the end of a row, go back to the 1st
5082       * stripe, but move down a row.  Reset everything.
5083       */
5084      if (++icol == image_wid)
5085      {
5086         int32_t edge_pixel, cnt;
5087
5088         /* need to handle non four pixel align case */
5089
5090         edge_pixel = (icol & 3);
5091
5092         if ( edge_pixel )
5093         {
5094            to   -= edge_pixel;
5095            scol -= edge_pixel;
5096
5097            for (cnt = 0; cnt < edge_pixel; cnt++)
5098            {
5099               pel = ptr [scol+3-cnt];
5100
5101               if (ulRangeRemapping != 8)
5102               {
5103                  lpel = (uint32_t) pel;
5104
5105                  lpel = ((((lpel - 128) *  (int32_t) ulRangeRemapping) + 4) >> 3) + 128;
5106                  if (lpel > 255) pel = 255;
5107                  else if (lpel < 0) pel = 0;
5108                  else pel = (unsigned char) lpel;
5109               }
5110
5111               *to++ = pel;
5112            }
5113         }
5114
5115         from += stripe_wid;
5116         ptr   = from;
5117
5118         icol  = 0;
5119         scol  = 0;
5120      }
5121   }
5122
5123   return 0;
5124
5125}     /* end of BXVD_Decoder_S_Dbg_DestripeSection() */
5126
5127/*
5128 * BXVD_Decoder_S_Dbg_DumpYUV
5129 */
5130void BXVD_Decoder_S_Dbg_DumpYUV(
5131   BXVD_ChannelHandle hXvdCh,
5132   BXVD_P_PPB *ppb
5133   )
5134{
5135   unsigned char *pYData;
5136   unsigned char *pUVData;
5137   uint32_t ulLumaRangeRemapping, ulChromaRangeRemapping;
5138   int32_t stripe_size = BXVD_P_StripeWidthLUT[hXvdCh->pXvd->uiDecode_StripeWidth];
5139   int32_t height;
5140   int32_t width;
5141   int32_t i, j;
5142
5143   static FILE *fpYUV = NULL;
5144   static unsigned char pBuf[1920*1088], *pSwap;
5145
5146   if (fpYUV== NULL)
5147   {
5148      if ((fpYUV=fopen("/Work/output.yuv", "wb"))==NULL)
5149      {
5150         BDBG_WRN(("Could not open output.yuv"));
5151         return;
5152      }
5153   }
5154
5155   BDBG_WRN(("*** grabbing pic with width %d height %d, stripe_size: %d stripe height: %d",
5156                                ppb->video_width, ppb->video_height, stripe_size, ppb->luma_stripe_height));
5157
5158   height = ppb->video_height;
5159   width = ppb->video_width;
5160
5161   /* Support range remapping during YUV grab */
5162   ulLumaRangeRemapping   = 0x08;
5163   ulChromaRangeRemapping = 0x08;
5164
5165   if (ppb->protocol == BAVC_VideoCompressionStd_eVC1)
5166   {
5167      ulLumaRangeRemapping   = ppb->other.vc1.range_remapping_ratio >> 16;
5168      ulChromaRangeRemapping = ppb->other.vc1.range_remapping_ratio & 0xffff;
5169   }
5170
5171   BKNI_Printf("%d %d \n", ulLumaRangeRemapping, ulChromaRangeRemapping);
5172
5173   /* Convert the two video buffers to logical addresses */
5174   BMEM_ConvertOffsetToAddress( hXvdCh->hPictureHeap, (uint32_t)ppb->luma_video_address, (void *)&pYData);
5175   BMEM_ConvertOffsetToAddress( hXvdCh->hPictureHeap, (uint32_t)ppb->chroma_video_address, (void *)&pUVData);
5176
5177   BXVD_Decoder_S_Dbg_DestripeSection(pYData, pBuf, width, height, stripe_size, ppb->luma_stripe_height, ulLumaRangeRemapping);
5178
5179   /* byte swap here */
5180   /* if (bByteSwap) */
5181#if 0
5182   {
5183      for (i = 0; i < width * height; i+=4)
5184      *((uint32_t *)(pBuf + i)) = BXVD_Decoder_S_Dbg_SwapLong(*((uint32_t *)(pBuf + i)));
5185   }
5186#endif
5187    /* need to handle non four pixel align case
5188     */
5189   {
5190      pSwap = pBuf;
5191      for (i = 0; i < height; i++)
5192      {
5193         for (j = 0; j < (width & 0xfffc); j+=4)
5194         {
5195            *((uint32_t *)pSwap) = BXVD_Decoder_S_Dbg_SwapLong(*((uint32_t *)pSwap));
5196            pSwap+=4;
5197         }
5198         pSwap += (width & 0x3);
5199      }
5200   }
5201
5202    /* Write the Y data */
5203    fwrite (pBuf, 1, width * height, fpYUV);
5204
5205    BXVD_Decoder_S_Dbg_DestripeSection(pUVData, pBuf, width, height / 2, stripe_size, ppb->chroma_stripe_height, ulChromaRangeRemapping);
5206
5207    /* byte swap here */
5208#if 0
5209    /* if (bByteSwap) */
5210    {
5211        for (i = 0; i < width * height; i+=4)
5212            *((uint32_t *)(pBuf + i)) = BXVD_Decoder_S_Dbg_SwapLong(*((uint32_t *)(pBuf + i)));
5213    }
5214#endif
5215
5216   /* need to handle non four pixel align case
5217    */
5218   {
5219      pSwap = pBuf;
5220      for (i = 0; i < height/2; i++)
5221      {
5222         for (j = 0; j < (width & 0xfffc); j+=4)
5223         {
5224            *((uint32_t *)pSwap) = BXVD_Decoder_S_Dbg_SwapLong(*((uint32_t *)pSwap));
5225            pSwap+=4;
5226         }
5227         pSwap += (width & 0x3);
5228      }
5229   }
5230
5231   /* Write the UV data (this also deinterleaves the UV  writing first U than V */
5232   for (i = 0; i < (width * height) / 2; i+=2)
5233      fwrite(pBuf + i, 1, 1, fpYUV);
5234   for (i = 1; i < (width * height) / 2; i+=2)
5235      fwrite(pBuf + i, 1, 1, fpYUV);
5236   fflush(fpYUV);
5237
5238}     /* end of BXVD_Decoder_S_Dbg_DumpYUV() */
5239
5240/*
5241 * BXVD_Decoder_S_Dbg_DumpRVC
5242 */
5243void BXVD_Decoder_S_Dbg_DumpRVC(
5244   BXVD_ChannelHandle hXvdCh
5245   )
5246{
5247   uint32_t size, start, end;
5248   uint32_t  currptr, buf_start, buf_end, buf_size;
5249   int32_t         contig;
5250   uint32_t      written;
5251   static unsigned char *pRVCdata = 0;
5252   static uint32_t lastrvcptr = 0xffffffff;
5253   static FILE *fpRVC= NULL;
5254
5255   currptr    = BXVD_Reg_Read32_isr(hXvdCh->pXvd, hXvdCh->pXvd->stPlatformInfo.stReg.uiDecode_RVCPut);
5256   buf_start = BXVD_Reg_Read32_isr(hXvdCh->pXvd, hXvdCh->pXvd->stPlatformInfo.stReg.uiDecode_RVCBase);
5257   buf_end  = BXVD_Reg_Read32_isr(hXvdCh->pXvd, hXvdCh->pXvd->stPlatformInfo.stReg.uiDecode_RVCEnd);
5258   buf_end += 1;
5259
5260   /* BDBG_WRN(("rvc registers (curr, start, end): 0x%x %x %x", currptr, buf_start, buf_end ));    */
5261
5262   buf_size = buf_end - buf_start;
5263   if (buf_size <= 1)
5264      return;
5265
5266   /*  for the initial case we set it to the start */
5267   if (0xffffffff == lastrvcptr)
5268      lastrvcptr = buf_start;
5269
5270   /* check pointer */
5271   if ((currptr > buf_end) || (currptr < buf_start))
5272      return;
5273
5274   /* calculate size to read */
5275   start = lastrvcptr;
5276   end   = currptr;
5277   lastrvcptr = currptr;
5278   if (end >= start)
5279   {
5280      contig  = 1;
5281      size    = end - start;
5282   }
5283   else
5284   {
5285      contig  = 0;
5286      size    = (buf_end - start) + (end - buf_start);
5287   }
5288
5289   if (0 == size)
5290      return;
5291
5292   if (fpRVC == NULL)
5293   {
5294      if ((fpRVC=fopen("/Work/rvc.bin", "wb"))==NULL)
5295      {
5296         return;
5297      }
5298   }
5299
5300   /* pRVCdata contains a virtual pointer to the data */
5301   BMEM_ConvertOffsetToAddress( hXvdCh->hPictureHeap, start, (void *)&pRVCdata);
5302
5303   if (contig)
5304   {
5305      /* BCM_MBDL_MemRead_ToBuffer (start, size, buf, 1, D011, boardnum); */
5306      written = fwrite(pRVCdata, 1, size, fpRVC);
5307   }
5308   else
5309   {
5310      /*  get the first chunk */
5311      written = fwrite(pRVCdata, 1, buf_end - start, fpRVC);
5312
5313      /* get the second chunk */
5314      /* the seond chunks starts at the buffer beginning - get its address */
5315      BMEM_ConvertOffsetToAddress( hXvdCh->hPictureHeap, buf_start, (void *)&pRVCdata);
5316      written += fwrite(pRVCdata, 1, end - buf_start, fpRVC);
5317   }
5318
5319   /* update the Get Pointer */
5320   BXVD_Reg_Write32_isr(hXvdCh->pXvd, hXvdCh->pXvd->stPlatformInfo.stReg.uiDecode_RVCGet, end);
5321
5322   if (size != written)
5323   {
5324      BDBG_WRN (("GrabRvcFrame - error writing file size = %d written %d", size, written));
5325   }
5326   else
5327   {
5328      BDBG_WRN (("GrabRvcFrame - write %d bytes", size));
5329   }
5330
5331   return;
5332
5333}  /* end of BXVD_Decoder_S_Dbg_DumpRVC() */
5334
5335/*
5336 * BXVD_Decoder_S_Dbg_DumpPPB
5337 */
5338void BXVD_Decoder_S_Dbg_DumpPPB(
5339   BXVD_P_PPB *ppb
5340   )
5341{
5342   static FILE *fpPPB = NULL;
5343
5344   if (fpPPB == NULL)
5345   {
5346      if ((fpPPB=fopen("/Work/ppb_capture.bin", "wb"))==NULL)
5347      {
5348         return;
5349      }
5350   }
5351
5352   fwrite(ppb, sizeof(BXVD_P_PPB), 1, fpPPB);
5353
5354}  /* end of BXVD_Decoder_S_Dbg_DumpPPB() */
5355
5356#endif /* End of BXVD_DM_ENABLE_YUV_GRAB_MODE */
5357
Note: See TracBrowser for help on using the repository browser.