1/*
2 * Copyright (c) 2011 Intel Corporation. All Rights Reserved.
3 * Copyright (c) Imagination Technologies Limited, UK
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the
7 * "Software"), to deal in the Software without restriction, including
8 * without limitation the rights to use, copy, modify, merge, publish,
9 * distribute, sub license, and/or sell copies of the Software, and to
10 * permit persons to whom the Software is furnished to do so, subject to
11 * the following conditions:
12 *
13 * The above copyright notice and this permission notice (including the
14 * next paragraph) shall be included in all copies or substantial portions
15 * of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
20 * IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
21 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
22 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
23 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 *
25 * Authors:
26 *    Waldo Bastian <waldo.bastian@intel.com>
27 *    Li Zeng <li.zeng@intel.com>
28 *
29 */
30
31#include "pnw_H264.h"
32#include "tng_vld_dec.h"
33#include "psb_def.h"
34#include "psb_drv_debug.h"
35#include "pnw_rotate.h"
36
37#include "hwdefs/reg_io2.h"
38#include "hwdefs/msvdx_offsets.h"
39#include "hwdefs/msvdx_cmds_io2.h"
40#include "hwdefs/msvdx_core_regs_io2.h"
41#include "hwdefs/msvdx_vec_reg_io2.h"
42#include "hwdefs/msvdx_vec_h264_reg_io2.h"
43#include "hwdefs/dxva_fw_ctrl.h"
44#ifdef SLICE_HEADER_PARSING
45#include "hwdefs/dxva_cmdseq_msg.h"
46#include "hwdefs/dxva_msg.h"
47#endif
48#include <stdlib.h>
49#include <stdint.h>
50#include <string.h>
51
52#include <wsbm/wsbm_manager.h>
53
54#define BUFFER(id)  ((object_buffer_p) object_heap_lookup( &ctx->obj_context->driver_data->buffer_heap, id ))
55
56#define GET_SURFACE_INFO_is_used(psb_surface) ((int) (psb_surface->extra_info[0]))
57#define SET_SURFACE_INFO_is_used(psb_surface, val) psb_surface->extra_info[0] = (uint32_t) val;
58#define GET_SURFACE_INFO_col_pic_params(psb_surface) (psb_surface->extra_info[1])
59#define SET_SURFACE_INFO_col_pic_params(psb_surface, val) psb_surface->extra_info[1] = val;
60#define GET_SURFACE_INFO_dpb_idx(psb_surface) (psb_surface->extra_info[2])
61#define SET_SURFACE_INFO_dpb_idx(psb_surface, val) psb_surface->extra_info[2] = val;
62
63#define IS_USED_AS_REFERENCE(pic_flags)         ( pic_flags & (VA_PICTURE_H264_SHORT_TERM_REFERENCE | VA_PICTURE_H264_LONG_TERM_REFERENCE) )
64
65/* Truncates a signed integer to 17 bits */
66#define SIGNTRUNC( x ) ((( (x)  >> 15) & 0x10000) | ( (x) & 0xffff))
67
68#define MSVDX_VEC_REGS_BASE_MTX 0x0800
69#define MSVDX_COMMANDS_BASE_MTX 0x1000
70#define MSVDX_IQRAM_BASE_MTX    0x700
71
72#define HW_SUPPORTED_MAX_PICTURE_WIDTH_H264   4096
73#define HW_SUPPORTED_MAX_PICTURE_HEIGHT_H264  4096
74
75#define SLICEDATA_BUFFER_TYPE(type) ((type==VASliceDataBufferType)?"VASliceDataBufferType":"VAProtectedSliceDataBufferType")
76
77typedef enum {
78    PICT_NONE,
79    PICT_FRAME,
80    PICT_TOP,
81    PICT_BOTTOM,
82    PICT_PAIR
83} PICTYPE;
84
85typedef enum {
86    H264_BASELINE_PROFILE = 0,
87    H264_MAIN_PROFILE = 1,
88    H264_HIGH_PROFILE = 2
89} PROFILE;
90
91static const char *profile2str[] = {
92    "H264_BASELINE_PROFILE",
93    "H264_MAIN_PROFILE",
94    "H264_HIGH_PROFILE"
95};
96
97typedef enum {
98    ST_P,
99    ST_B ,
100    ST_I ,
101    ST_SP ,
102    ST_SI
103} SLICE_TYPE;
104
105static IMG_UINT8 aSliceTypeVAtoMsvdx[] = { 1 , 2 , 0, 1, 0 };
106
107static const char *slice2str[] = {
108    "ST_P",
109    "ST_B",
110    "ST_I",
111    "ST_SP",
112    "ST_SI"
113};
114
115typedef enum {
116    DEBLOCK_NONE,
117    DEBLOCK_STD,
118    DEBLOCK_INTRA_OOLD
119} DEBLOCK_MODE_2NDPASS;
120
121struct context_H264_s {
122    struct context_DEC_s dec_ctx;
123    object_context_p obj_context; /* back reference */
124
125    uint32_t profile; // ENTDEC BE_PROFILE & FE_PROFILE
126    uint32_t profile_idc; // BE_PROFILEIDC
127
128    /* Picture parameters */
129    VAPictureParameterBufferH264 *pic_params;
130    object_surface_p forward_ref_surface;
131    object_surface_p backward_ref_surface;
132
133    uint32_t coded_picture_width;    /* in pixels */
134    uint32_t coded_picture_height;    /* in pixels */
135
136    uint32_t picture_width_mb;        /* in macroblocks */
137    uint32_t picture_height_mb;        /* in macroblocks */
138    uint32_t size_mb;                /* in macroblocks */
139
140    uint32_t first_mb_x;
141    uint32_t first_mb_y;
142
143    uint32_t mb_width_c;                /* Chroma macroblock width */
144    uint32_t mb_height_c;               /* Chroma macroblock height */
145
146    uint32_t bit_depth_l;               /* Luma bit depth */
147    uint32_t qp_bd_offset_l;
148    uint32_t bit_depth_c;               /* Chroma bit depth */
149    uint32_t qp_bd_offset_c;
150
151    uint32_t raw_mb_bits;               /* Number of bits per macroblock */
152
153    uint32_t picture_width_samples_l;
154    uint32_t picture_height_samples_l;
155    uint32_t picture_width_samples_c;
156    uint32_t picture_height_samples_c;
157
158    uint32_t picture_height_map_units;
159    uint32_t picture_size_map_units;
160
161    PICTYPE pic_type;
162    uint32_t field_type;
163
164    uint32_t long_term_frame_flags;
165    uint32_t two_pass_mode;
166    uint32_t deblock_mode;
167    uint32_t slice_count;
168
169    /* Registers */
170    uint32_t reg_SPS0;
171    uint32_t reg_PPS0;
172    uint32_t reg_PIC0;
173
174    uint32_t slice0_params;
175    uint32_t slice1_params;
176
177    /* VLC packed data */
178    struct psb_buffer_s vlc_packed_table;
179
180    /* Preload buffer */
181    struct psb_buffer_s preload_buffer;
182
183    /* Slice Group Map buffer */
184    psb_buffer_p slice_group_map_buffer;
185
186    /* IQ matrix */
187    VAIQMatrixBufferH264 *iq_matrix;
188    VASliceParameterBufferH264 *slice_param;
189
190    /* Reference Cache */
191    struct psb_buffer_s reference_cache;
192
193    /* map picture_id to dpbidx consistently between pictures */
194    uint32_t map_dpbidx_to_picture_id[16];
195    uint32_t map_dpbidx_to_refidx[16];
196
197};
198
199typedef struct context_H264_s *context_H264_p;
200
201#define INIT_CONTEXT_H264    context_H264_p ctx = (context_H264_p) obj_context->format_data;
202
203#define SURFACE(id)    ((object_surface_p) object_heap_lookup( &ctx->obj_context->driver_data->surface_heap, id ))
204
205#define CACHE_REF_OFFSET        72
206#define CACHE_ROW_OFFSET        4
207
208#define REFERENCE_CACHE_SIZE    (512 * 1024)
209
210#define MAX_PRELOAD_CMDS                                (40*2)
211typedef struct {
212    IMG_UINT8           ui8Address[MAX_PRELOAD_CMDS]; /* Address = (ui8Address << 1 | 0x400 ) */
213    IMG_UINT32          ui32Value[MAX_PRELOAD_CMDS];
214} ADDRDATA;
215
216typedef struct {
217    IMG_UINT32          ui32ContextId;
218    IMG_UINT32          ui32PreloadBufferSize;
219    ADDRDATA            aData;
220} PRELOAD;
221
222
223
224/* **************************************************************************************************************** */
225/* Prepacked H264 VLC Tables */
226/* **************************************************************************************************************** */
227static const IMG_UINT16 ui16H264VLCTableData[] = {
228    0x4000, 0x4205, 0x440a, 0x2204, 0x2206, 0x0208, 0x040b, 0x400f,
229    0x4204, 0x4209, 0x4013, 0x420e, 0x4217, 0x421b, 0x4212, 0x420d,
230    0x4208, 0x2a08, 0x0232, 0x0035, 0x0036, 0x441f, 0x4416, 0x4411,
231    0x440c, 0x0407, 0x040e, 0x0415, 0x041c, 0x0223, 0x4a35, 0x3a00,
232    0x4420, 0x4426, 0x4421, 0x441c, 0x442b, 0x4422, 0x441d, 0x4418,
233    0x4433, 0x442e, 0x4429, 0x4428, 0x442f, 0x442a, 0x4425, 0x4424,
234    0x443b, 0x4436, 0x4431, 0x4430, 0x4437, 0x4432, 0x442d, 0x442c,
235    0x4443, 0x443e, 0x443d, 0x4438, 0x443f, 0x443a, 0x4439, 0x4434,
236    0x4240, 0x4242, 0x4241, 0x423c, 0x4227, 0x421e, 0x4219, 0x4214,
237    0x4023, 0x401a, 0x4015, 0x4010, 0x0410, 0x0249, 0x024c, 0x004f,
238    0x4613, 0x460f, 0x440a, 0x440a, 0x4205, 0x4205, 0x4205, 0x4205,
239    0x4200, 0x4200, 0x4200, 0x4200, 0x2a08, 0x0231, 0x0034, 0x0035,
240    0x4423, 0x4416, 0x4415, 0x440c, 0x0407, 0x040e, 0x0415, 0x121c,
241    0x0222, 0x4a3f, 0x3a00, 0x442f, 0x4426, 0x4425, 0x4420, 0x442b,
242    0x4422, 0x4421, 0x441c, 0x442c, 0x442e, 0x442d, 0x4428, 0x4433,
243    0x442a, 0x4429, 0x4424, 0x443b, 0x4436, 0x4435, 0x4434, 0x4437,
244    0x4432, 0x4431, 0x4430, 0x0203, 0x423a, 0x4238, 0x423d, 0x423c,
245    0x423e, 0x4239, 0x4243, 0x4242, 0x4241, 0x4240, 0x4227, 0x421e,
246    0x421d, 0x4218, 0x4014, 0x401a, 0x4019, 0x4010, 0x421f, 0x4212,
247    0x4211, 0x4208, 0x421b, 0x420e, 0x420d, 0x4204, 0x4017, 0x4009,
248    0x2210, 0x0432, 0x0239, 0x023c, 0x600a, 0x6008, 0x003d, 0x003e,
249    0x461f, 0x461b, 0x4617, 0x4613, 0x460f, 0x460a, 0x4605, 0x4600,
250    0x0403, 0x040a, 0x0611, 0x4433, 0x442e, 0x4429, 0x4424, 0x442f,
251    0x442a, 0x4425, 0x4420, 0x4430, 0x4436, 0x4431, 0x442c, 0x4437,
252    0x4432, 0x442d, 0x4428, 0x3600, 0x4640, 0x4643, 0x4642, 0x4641,
253    0x463c, 0x463f, 0x463e, 0x463d, 0x4638, 0x463b, 0x463a, 0x4639,
254    0x4634, 0x4435, 0x4435, 0x441c, 0x4418, 0x4426, 0x4414, 0x442b,
255    0x4422, 0x4421, 0x4410, 0x420c, 0x421e, 0x421d, 0x4208, 0x4227,
256    0x421a, 0x4219, 0x4204, 0x400d, 0x4023, 0x400e, 0x4009, 0x2208,
257    0x5406, 0x540a, 0x540e, 0x5412, 0x5416, 0x541a, 0x541e, 0x5204,
258    0x0002, 0x5002, 0x3000, 0x4000, 0x4005, 0x4200, 0x440a, 0x0401,
259    0x1208, 0x000a, 0x4410, 0x440c, 0x4408, 0x440f, 0x4409, 0x4404,
260    0x4013, 0x4212, 0x4211, 0x400e, 0x400d, 0x4000, 0x4205, 0x440a,
261    0x0404, 0x480f, 0x4a13, 0x2609, 0x441b, 0x4417, 0x4412, 0x440e,
262    0x440d, 0x4409, 0x4408, 0x4404, 0x0205, 0x0208, 0x020b, 0x020e,
263    0x1411, 0x4216, 0x4211, 0x4210, 0x420c, 0x421f, 0x421a, 0x4215,
264    0x4214, 0x4223, 0x421e, 0x4219, 0x4218, 0x4222, 0x4221, 0x421d,
265    0x421c, 0x3400, 0x3400, 0x3400, 0x4420, 0x4000, 0x0006, 0x0007,
266    0x0008, 0x0009, 0x000a, 0x040b, 0x4002, 0x4001, 0x4004, 0x4003,
267    0x4006, 0x4005, 0x4008, 0x4007, 0x400a, 0x4009, 0x3400, 0x440f,
268    0x440e, 0x440d, 0x420c, 0x420c, 0x420b, 0x420b, 0x1208, 0x000e,
269    0x000f, 0x4404, 0x4403, 0x4402, 0x4401, 0x4400, 0x0203, 0x420a,
270    0x4209, 0x420e, 0x420d, 0x420c, 0x420b, 0x4008, 0x4007, 0x4006,
271    0x4005, 0x0208, 0x000d, 0x000e, 0x4407, 0x4406, 0x4403, 0x4402,
272    0x4401, 0x0004, 0x420c, 0x420a, 0x4209, 0x400d, 0x400b, 0x4008,
273    0x4005, 0x4004, 0x4000, 0x0208, 0x000b, 0x000c, 0x4408, 0x4406,
274    0x4405, 0x4404, 0x4401, 0x420c, 0x420b, 0x420a, 0x4200, 0x4009,
275    0x4007, 0x4003, 0x4002, 0x2208, 0x000a, 0x000b, 0x4407, 0x4406,
276    0x4405, 0x4404, 0x4403, 0x400a, 0x4209, 0x420b, 0x4008, 0x4002,
277    0x4001, 0x4000, 0x2408, 0x4409, 0x4407, 0x4406, 0x4405, 0x4404,
278    0x4403, 0x4402, 0x4008, 0x4201, 0x4400, 0x440a, 0x2408, 0x4408,
279    0x4406, 0x4404, 0x4403, 0x4402, 0x4205, 0x4205, 0x4007, 0x4201,
280    0x4400, 0x4409, 0x2604, 0x0008, 0x4205, 0x4204, 0x4007, 0x4201,
281    0x4402, 0x4600, 0x4608, 0x4006, 0x4003, 0x2604, 0x4206, 0x4204,
282    0x4203, 0x4005, 0x4202, 0x4407, 0x4600, 0x4601, 0x2404, 0x4205,
283    0x4204, 0x4203, 0x4002, 0x4206, 0x4400, 0x4401, 0x4004, 0x0003,
284    0x4402, 0x5000, 0x4003, 0x4005, 0x4003, 0x4202, 0x4404, 0x5000,
285    0x4002, 0x4203, 0x5000, 0x5000, 0x4002, 0x4000, 0x4001, 0x4000,
286    0x4201, 0x4402, 0x4403, 0x4000, 0x4201, 0x4202, 0x4001, 0x4000,
287    0x4001, 0x4000, 0x4000, 0x4201, 0x4202, 0x4203, 0x4202, 0x4201,
288    0x4200, 0x0004, 0x4202, 0x4201, 0x4200, 0x4004, 0x4003, 0x0203,
289    0x4201, 0x4200, 0x4205, 0x4204, 0x4203, 0x4202, 0x4401, 0x4402,
290    0x4404, 0x4403, 0x4406, 0x4405, 0x4200, 0x4200, 0x2a08, 0x4406,
291    0x4405, 0x4404, 0x4403, 0x4402, 0x4401, 0x4400, 0x4007, 0x4208,
292    0x4409, 0x460a, 0x480b, 0x4a0c, 0x2201, 0x400d, 0x420e, 0x3200,
293};
294
295/* Set bottom field flag in bit 7 and DPB index in bits 0:3 */
296static uint32_t PICTURE2INDEX(context_H264_p ctx, VAPictureH264 *pic)
297{
298    uint32_t result = 0xff; /* unused */
299    object_surface_p ref_surface = SURFACE(pic->picture_id);
300    if (ref_surface) {
301        result = GET_SURFACE_INFO_dpb_idx(ref_surface->psb_surface);
302    }
303    if (pic->flags & VA_PICTURE_H264_BOTTOM_FIELD) {
304        result |= 0x80; /* Set bit 7 */
305    }
306    return result;
307}
308
309static void pnw_H264_QueryConfigAttributes(
310    VAProfile profile,
311    VAEntrypoint entrypoint,
312    VAConfigAttrib *attrib_list,
313    int num_attribs)
314{
315    int i;
316    drv_debug_msg(VIDEO_DEBUG_GENERAL, "pnw_H264_QueryConfigAttributes\n");
317
318    for (i = 0; i < num_attribs; i++) {
319        switch (attrib_list[i].type) {
320        case VAConfigAttribMaxPictureWidth:
321            if ((entrypoint == VAEntrypointVLD) &&
322                (profile == VAProfileH264High))
323                attrib_list[i].value = HW_SUPPORTED_MAX_PICTURE_WIDTH_H264;
324            else
325                attrib_list[i].value = VA_ATTRIB_NOT_SUPPORTED;
326            break;
327        case VAConfigAttribMaxPictureHeight:
328            if ((entrypoint == VAEntrypointVLD) &&
329                (profile == VAProfileH264High))
330                attrib_list[i].value = HW_SUPPORTED_MAX_PICTURE_HEIGHT_H264;
331            else
332                attrib_list[i].value = VA_ATTRIB_NOT_SUPPORTED;
333            break;
334        default:
335            break;
336        }
337    }
338
339}
340
341static VAStatus pnw_H264_ValidateConfig(
342    object_config_p obj_config)
343{
344    int i;
345    /* Check all attributes */
346    for (i = 0; i < obj_config->attrib_count; i++) {
347        switch (obj_config->attrib_list[i].type) {
348        case VAConfigAttribRTFormat:
349        case VAConfigAttribDecSliceMode:
350            /* Ignore */
351            break;
352
353        default:
354            return VA_STATUS_ERROR_ATTR_NOT_SUPPORTED;
355        }
356    }
357
358    return VA_STATUS_SUCCESS;
359}
360
361static VAStatus psb__H264_check_legal_picture(object_context_p obj_context, object_config_p obj_config)
362{
363    VAStatus vaStatus = VA_STATUS_SUCCESS;
364
365    CHECK_CONTEXT(obj_context);
366
367    CHECK_CONFIG(obj_config);
368
369    /* MSVDX decode capability for H.264:
370     *     BP@L3
371     *     MP@L4.1
372     *     HP@L4.1
373     *
374     * Refer to Table A-6 (Maximum frame rates for some example frame sizes) of ISO/IEC 14496-10:2005 (E).
375     */
376    switch (obj_config->profile) {
377    case VAProfileH264Baseline:
378        if ((obj_context->picture_width <= 0) || (obj_context->picture_width > 720)
379            || (obj_context->picture_height <= 0) || (obj_context->picture_height > 576)) {
380            vaStatus = VA_STATUS_ERROR_RESOLUTION_NOT_SUPPORTED;
381        }
382        break;
383
384    case VAProfileH264Main:
385    case VAProfileH264High:
386    case VAProfileH264ConstrainedBaseline:
387        if ((obj_context->picture_width <= 0) || (obj_context->picture_width > 1920)
388            || (obj_context->picture_height <= 0) || (obj_context->picture_height > 1088)) {
389            vaStatus = VA_STATUS_ERROR_RESOLUTION_NOT_SUPPORTED;
390        }
391        break;
392
393    default:
394        vaStatus = VA_STATUS_ERROR_UNSUPPORTED_PROFILE;
395        break;
396    }
397
398    return vaStatus;
399}
400
401static void pnw_H264_DestroyContext(object_context_p obj_context);
402static void psb__H264_process_slice_data(context_DEC_p dec_ctx, VASliceParameterBufferBase *vld_slice_param);
403static void psb__H264_end_slice(context_DEC_p dec_ctx);
404static void psb__H264_begin_slice(context_DEC_p dec_ctx, VASliceParameterBufferBase *vld_slice_param);
405static VAStatus pnw_H264_process_buffer(context_DEC_p dec_ctx, object_buffer_p buffer);
406
407static VAStatus pnw_H264_CreateContext(
408    object_context_p obj_context,
409    object_config_p obj_config)
410{
411    VAStatus vaStatus = VA_STATUS_SUCCESS;
412    context_H264_p ctx;
413    int i = 0;
414    /* Validate flag */
415    /* Validate picture dimensions */
416    //vaStatus = psb__H264_check_legal_picture(obj_context, obj_config);
417    CHECK_VASTATUS();
418
419    ctx = (context_H264_p) calloc(1, sizeof(struct context_H264_s));
420    CHECK_ALLOCATION(ctx);
421
422    obj_context->format_data = (void*) ctx;
423    ctx->obj_context = obj_context;
424    ctx->pic_params = NULL;
425
426    ctx->dec_ctx.begin_slice = psb__H264_begin_slice;
427    ctx->dec_ctx.process_slice = psb__H264_process_slice_data;
428    ctx->dec_ctx.end_slice = psb__H264_end_slice;
429    ctx->dec_ctx.process_buffer = pnw_H264_process_buffer;
430
431    for(i = 0; i < 16; i++) {
432        ctx->map_dpbidx_to_picture_id[i] = VA_INVALID_SURFACE;
433    }
434
435    switch (obj_config->profile) {
436    case VAProfileH264Baseline:
437        ctx->profile = H264_BASELINE_PROFILE;
438        ctx->profile_idc = 0;
439        break;
440
441    case VAProfileH264Main:
442        ctx->profile = H264_MAIN_PROFILE;
443        ctx->profile_idc = 1;
444        break;
445
446    case VAProfileH264High:
447    case VAProfileH264ConstrainedBaseline:
448        ctx->profile = H264_HIGH_PROFILE;
449        ctx->profile_idc = 3;
450        break;
451
452    default:
453        ASSERT(0);
454        vaStatus = VA_STATUS_ERROR_UNKNOWN;
455    }
456
457    // TODO
458    if (vaStatus == VA_STATUS_SUCCESS) {
459        vaStatus = psb_buffer_create(obj_context->driver_data,
460                                     sizeof(PRELOAD),
461                                     psb_bt_vpu_only,
462                                     &ctx->preload_buffer);
463        DEBUG_FAILURE;
464    }
465    ctx->dec_ctx.preload_buffer = &ctx->preload_buffer;
466
467    if (vaStatus == VA_STATUS_SUCCESS) {
468        vaStatus = psb_buffer_create(obj_context->driver_data,
469                                     REFERENCE_CACHE_SIZE,
470                                     psb_bt_vpu_only,
471                                     &ctx->reference_cache);
472        DEBUG_FAILURE;
473    }
474
475    if (vaStatus == VA_STATUS_SUCCESS) {
476        vaStatus = psb_buffer_create(obj_context->driver_data,
477                                     sizeof(ui16H264VLCTableData),
478                                     psb_bt_cpu_vpu,
479                                     &ctx->vlc_packed_table);
480        DEBUG_FAILURE;
481    }
482    if (vaStatus == VA_STATUS_SUCCESS) {
483        unsigned char *vlc_packed_data_address;
484        if (0 ==  psb_buffer_map(&ctx->vlc_packed_table, &vlc_packed_data_address)) {
485            memcpy(vlc_packed_data_address, ui16H264VLCTableData, sizeof(ui16H264VLCTableData));
486            psb_buffer_unmap(&ctx->vlc_packed_table);
487        } else {
488            vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;
489            DEBUG_FAILURE;
490        }
491    }
492
493    if (vaStatus == VA_STATUS_SUCCESS) {
494        vaStatus = vld_dec_CreateContext(&ctx->dec_ctx, obj_context);
495        DEBUG_FAILURE;
496    }
497
498    if (vaStatus != VA_STATUS_SUCCESS) {
499        pnw_H264_DestroyContext(obj_context);
500    }
501
502    return vaStatus;
503}
504
505static void pnw_H264_DestroyContext(
506    object_context_p obj_context)
507{
508    INIT_CONTEXT_H264
509    int i;
510
511    vld_dec_DestroyContext(&ctx->dec_ctx);
512
513    psb_buffer_destroy(&ctx->reference_cache);
514    psb_buffer_destroy(&ctx->preload_buffer);
515    psb_buffer_destroy(&ctx->vlc_packed_table);
516
517    if (ctx->pic_params) {
518        free(ctx->pic_params);
519        ctx->pic_params = NULL;
520    }
521    if (ctx->iq_matrix) {
522        free(ctx->iq_matrix);
523        ctx->iq_matrix = NULL;
524    }
525
526    free(obj_context->format_data);
527    obj_context->format_data = NULL;
528}
529
530#define P(x)    psb__trace_message("PARAMS: " #x "\t= %08x (%d)\n", p->x, p->x)
531static void psb__H264_trace_pic_params(VAPictureParameterBufferH264 *p)
532{
533    P(CurrPic);
534    P(picture_width_in_mbs_minus1);
535    P(picture_height_in_mbs_minus1);
536    P(bit_depth_luma_minus8);
537    P(bit_depth_chroma_minus8);
538    P(num_ref_frames);
539    P(seq_fields);
540    P(num_slice_groups_minus1);
541    P(slice_group_map_type);
542    P(pic_init_qp_minus26);
543    P(chroma_qp_index_offset);
544    P(second_chroma_qp_index_offset);
545    P(pic_fields);
546    P(frame_num);
547}
548
549static VAStatus psb__H264_process_picture_param(context_H264_p ctx, object_buffer_p obj_buffer)
550{
551    psb_surface_p target_surface = ctx->obj_context->current_render_target->psb_surface;
552    object_surface_p obj_surface = ctx->obj_context->current_render_target;
553    uint32_t reg_value;
554    VAStatus vaStatus;
555
556    ASSERT(obj_buffer->type == VAPictureParameterBufferType);
557    ASSERT(obj_buffer->num_elements == 1);
558    ASSERT(obj_buffer->size == sizeof(VAPictureParameterBufferH264));
559    ASSERT(target_surface);
560
561    if ((obj_buffer->num_elements != 1) ||
562        (obj_buffer->size != sizeof(VAPictureParameterBufferH264)) ||
563        (NULL == target_surface)) {
564        return VA_STATUS_ERROR_UNKNOWN;
565    }
566
567    /* Transfer ownership of VAPictureParameterBufferH264 data */
568    VAPictureParameterBufferH264 *pic_params = (VAPictureParameterBufferH264 *) obj_buffer->buffer_data;
569    if (ctx->pic_params) {
570        free(ctx->pic_params);
571    }
572    ctx->pic_params = pic_params;
573    obj_buffer->buffer_data = NULL;
574    obj_buffer->size = 0;
575
576    if (psb_video_trace_fp && (psb_video_trace_level & VABUF_TRACE))
577        psb__H264_trace_pic_params(pic_params);
578
579    /* Table 6-1 */
580    uint32_t sub_width_c  = (pic_params->seq_fields.bits.chroma_format_idc > 2) ? 1 : 2;
581    uint32_t sub_height_c = (pic_params->seq_fields.bits.chroma_format_idc > 1) ? 1 : 2;
582
583    if (pic_params->seq_fields.bits.chroma_format_idc == 0) {
584        ctx->mb_width_c = 0;
585        ctx->mb_height_c = 0;
586    } else {
587        ctx->mb_width_c = 16 / sub_width_c;             /* 6-1 */
588        ctx->mb_height_c = 16 / sub_height_c;           /* 6-2 */
589    }
590
591    ctx->bit_depth_l = 8 + pic_params->bit_depth_luma_minus8;                   /* (7-1) */
592    ctx->qp_bd_offset_l = 6 * pic_params->bit_depth_luma_minus8;                /* (7-2) */
593
594    ctx->bit_depth_c = 8 + pic_params->bit_depth_chroma_minus8;                 /* (7-3) */
595    ctx->qp_bd_offset_c = 6 * (pic_params->bit_depth_chroma_minus8 + pic_params->seq_fields.bits.residual_colour_transform_flag);       /* (7-4) */
596
597    ctx->picture_width_mb = pic_params->picture_width_in_mbs_minus1 + 1;
598    ctx->picture_height_mb = pic_params->picture_height_in_mbs_minus1 + 1;
599
600    ctx->size_mb = ctx->picture_width_mb * ctx->picture_height_mb;              /* (7-25) */
601
602    //uint32_t colocated_size = (ctx->picture_width_mb + extra_size) * (ctx->picture_height_mb + extra_size) * 192;
603    uint32_t colocated_size = ((ctx->size_mb + 100) * 128 + 0xfff) & ~0xfff;
604
605    vaStatus = vld_dec_allocate_colocated_buffer(&ctx->dec_ctx, ctx->obj_context->current_render_target, colocated_size);
606    CHECK_VASTATUS();
607
608    ctx->raw_mb_bits = 256 * ctx->bit_depth_l + 2 * ctx->mb_width_c * ctx->mb_height_c * ctx->bit_depth_c;      /* (7-5) */
609
610    ctx->picture_width_samples_l = ctx->picture_width_mb * 16;
611    ctx->picture_width_samples_c = ctx->picture_width_mb * ctx->mb_width_c;
612
613    ctx->picture_height_samples_l = ctx->picture_height_mb * 16;
614    ctx->picture_height_samples_c = ctx->picture_height_mb * ctx->mb_height_c;
615
616    if (obj_surface->share_info) {
617        obj_surface->share_info->coded_width = ctx->picture_width_samples_l;
618        obj_surface->share_info->coded_height = ctx->picture_height_samples_l;
619    }
620
621    // BECAUSE OF
622    //  sps->FrameHeightInMbs   = ( 2 - sps->seq_fields.bits.frame_mbs_only_flag ) * sps->PicHeightInMapUnits;  /* (7-15) */
623    ctx->picture_height_map_units = 1 + ctx->picture_height_mb / (2 - pic_params->seq_fields.bits.frame_mbs_only_flag);
624    ctx->picture_size_map_units = ctx->picture_width_mb * ctx->picture_height_map_units;/* (7-14) */
625
626    pic_params->seq_fields.bits.mb_adaptive_frame_field_flag = (pic_params->seq_fields.bits.mb_adaptive_frame_field_flag &&
627                                                               !pic_params->pic_fields.bits.field_pic_flag);
628    /* record just what type of picture we are */
629    if (pic_params->pic_fields.bits.field_pic_flag) {
630        if (pic_params->CurrPic.flags & VA_PICTURE_H264_BOTTOM_FIELD) {
631            ctx->pic_type = PICT_BOTTOM;
632            ctx->field_type = 1;
633        } else {
634            ctx->pic_type = PICT_TOP;
635            ctx->field_type = 0;
636        }
637    } else {
638        ctx->pic_type = PICT_FRAME;
639        ctx->field_type = pic_params->seq_fields.bits.mb_adaptive_frame_field_flag ? 3 : 2;
640    }
641
642    uint32_t i;
643    uint32_t dpbidx;
644    uint32_t num_new_pics = 0;
645    uint32_t new_pic_ids[16];
646    uint32_t dpbidx_used_this_pic_flags = 0;
647    ctx->long_term_frame_flags = 0;
648
649    if (pic_params->num_ref_frames > 16) {
650        drv_debug_msg(VIDEO_DEBUG_ERROR, "%s:%d Too many ref frames %d",__FILE__, __LINE__,pic_params->num_ref_frames);
651        // error here
652        pic_params->num_ref_frames = 16;
653    }
654    /* find new reference picture */
655    for (i = 0; i < pic_params->num_ref_frames; i++) {
656        if (pic_params->ReferenceFrames[i].flags == VA_PICTURE_H264_INVALID) {
657            // warning here
658            continue;
659        }
660        for (dpbidx = 0; dpbidx < 16; dpbidx++) {
661            if (ctx->map_dpbidx_to_picture_id[dpbidx] == pic_params->ReferenceFrames[i].picture_id) {
662                dpbidx_used_this_pic_flags |= (0x1 << dpbidx);
663                break;
664            }
665        }
666        if (16 == dpbidx) {
667            new_pic_ids[num_new_pics] = pic_params->ReferenceFrames[i].picture_id;
668            num_new_pics++;
669        }
670    }
671
672    /* invalidate unused dpb entries */
673    for (i = 0; i < 16; i++) {
674        if (!(dpbidx_used_this_pic_flags & (1 << i))) {
675            ctx->map_dpbidx_to_picture_id[i] = VA_INVALID_SURFACE;
676        }
677    }
678
679    /* find an empty dpb location for new entries */
680    dpbidx = 0;
681    for (i = 0; i < num_new_pics; i++) {
682        for (; dpbidx < 16; dpbidx++) {
683            if (VA_INVALID_SURFACE == ctx->map_dpbidx_to_picture_id[dpbidx]) {
684                ctx->map_dpbidx_to_picture_id[dpbidx] = new_pic_ids[i];
685                break;
686            }
687        }
688        if (16 == dpbidx) {
689            drv_debug_msg(VIDEO_DEBUG_ERROR, "%s:%d No empty space for new frame %d (%08x)",__FILE__, __LINE__,i,dpbidx_used_this_pic_flags);
690            // error here
691            break;
692        }
693    }
694
695    /* update surfaces with dpbidx */
696    for (dpbidx = 0; dpbidx < 16; dpbidx++) {
697        if (VA_INVALID_SURFACE != ctx->map_dpbidx_to_picture_id[dpbidx]) {
698            object_surface_p ref_surface = SURFACE(ctx->map_dpbidx_to_picture_id[dpbidx]);
699            if (!ref_surface) {
700                drv_debug_msg(VIDEO_DEBUG_ERROR, "%s:%d No surface for refernce frame",__FILE__, __LINE__);
701                // error here
702                continue;
703            }
704            SET_SURFACE_INFO_dpb_idx(ref_surface->psb_surface, dpbidx);
705        }
706    }
707
708    /* get the reference location and long term flag for each dpb location */
709    memset(ctx->map_dpbidx_to_refidx, 0xff, sizeof(ctx->map_dpbidx_to_refidx));
710    for (i = 0; i < pic_params->num_ref_frames; i++) {
711        if (pic_params->ReferenceFrames[i].flags == VA_PICTURE_H264_INVALID) {
712            continue;
713        }
714        object_surface_p ref_surface = SURFACE(pic_params->ReferenceFrames[i].picture_id);
715        if (ref_surface) {
716            dpbidx = GET_SURFACE_INFO_dpb_idx(ref_surface->psb_surface);
717            if (dpbidx < 16) {
718                ctx->map_dpbidx_to_refidx[dpbidx] = i;
719                if (pic_params->ReferenceFrames[i].flags & VA_PICTURE_H264_BOTTOM_FIELD) {
720                    ctx->long_term_frame_flags |= 0x01 << dpbidx;
721                }
722            }
723            else {
724                drv_debug_msg(VIDEO_DEBUG_ERROR, "%s:%d No invalid dpbidx stored with surface %d",__FILE__, __LINE__,dpbidx);
725                // error here
726                continue;
727            }
728        }
729    }
730
731    /* If the MB are not guarenteed to be consecutive - we must do a 2pass */
732    ctx->two_pass_mode = (pic_params->num_slice_groups_minus1 > 0) && (!ctx->pic_params->seq_fields.bits.mb_adaptive_frame_field_flag);
733
734    ctx->reg_SPS0 = 0;
735    REGIO_WRITE_FIELD_LITE(ctx->reg_SPS0, MSVDX_VEC_H264, CR_VEC_H264_BE_SPS0, H264_BE_SPS0_DEFAULT_MATRIX_FLAG, (ctx->profile == H264_BASELINE_PROFILE));    /* Always use suplied matrix non baseline otherwise use default*/
736    REGIO_WRITE_FIELD_LITE(ctx->reg_SPS0, MSVDX_VEC_H264, CR_VEC_H264_BE_SPS0, H264_BE_SPS0_2PASS_FLAG,         ctx->two_pass_mode);                    /* Always 0 for VA - we cant handle otherwise yet */
737    /* Assume SGM_8BIT */
738    REGIO_WRITE_FIELD_LITE(ctx->reg_SPS0, MSVDX_VEC_H264, CR_VEC_H264_FE_SPS0, H264_FE_SPS0_4BIT_SGM_FLAG,      0);
739    REGIO_WRITE_FIELD_LITE(ctx->reg_SPS0, MSVDX_VEC_H264, CR_VEC_H264_BE_SPS0, BE_PROFILEIDC,                   ctx->profile_idc);
740    REGIO_WRITE_FIELD_LITE(ctx->reg_SPS0, MSVDX_VEC_H264, CR_VEC_H264_FE_SPS0, MIN_LUMA_BIPRED_SIZE_8X8, (ctx->picture_width_mb > 80));
741    REGIO_WRITE_FIELD_LITE(ctx->reg_SPS0, MSVDX_VEC_H264, CR_VEC_H264_FE_SPS0, DIRECT_8X8_INFERENCE_FLAG,       pic_params->seq_fields.bits.direct_8x8_inference_flag);
742    REGIO_WRITE_FIELD_LITE(ctx->reg_SPS0, MSVDX_VEC_H264, CR_VEC_H264_FE_SPS0, CHROMA_FORMAT_IDC,               pic_params->seq_fields.bits.chroma_format_idc);
743    REGIO_WRITE_FIELD_LITE(ctx->reg_SPS0, MSVDX_VEC_H264, CR_VEC_H264_FE_SPS0, FRAME_MBS_ONLY_FLAG,             pic_params->seq_fields.bits.frame_mbs_only_flag);
744    REGIO_WRITE_FIELD_LITE(ctx->reg_SPS0, MSVDX_VEC_H264, CR_VEC_H264_FE_SPS0, PICWIDTHINMBSLESS1,              ctx->picture_width_mb - 1);
745
746    ctx->reg_PPS0 = 0;
747    REGIO_WRITE_FIELD_LITE(ctx->reg_PPS0, MSVDX_VEC_H264, CR_VEC_H264_FE_PPS0, TRANSFORM_8X8_MODE_FLAG,         pic_params->pic_fields.bits.transform_8x8_mode_flag);
748    REGIO_WRITE_FIELD_LITE(ctx->reg_PPS0, MSVDX_VEC_H264, CR_VEC_H264_FE_PPS0, CONSTRAINED_INTRA_PRED_FLAG,     pic_params->pic_fields.bits.constrained_intra_pred_flag);
749    REGIO_WRITE_FIELD_LITE(ctx->reg_PPS0, MSVDX_VEC_H264, CR_VEC_H264_FE_PPS0, ENTROPY_CODING_MODE_FLAG,        pic_params->pic_fields.bits.entropy_coding_mode_flag);
750    REGIO_WRITE_FIELD_LITE(ctx->reg_PPS0, MSVDX_VEC_H264, CR_VEC_H264_FE_PPS0, NUM_SLICE_GROUPS_MINUS1,         pic_params->num_slice_groups_minus1);
751    REGIO_WRITE_FIELD_LITE(ctx->reg_PPS0, MSVDX_VEC_H264, CR_VEC_H264_BE_PPS0, BE_WEIGHTED_BIPRED_IDC,          pic_params->pic_fields.bits.weighted_bipred_idc);
752    REGIO_WRITE_FIELD_MASKEDLITE(ctx->reg_PPS0, MSVDX_VEC_H264, CR_VEC_H264_BE_PPS0, BE_CHROMA_QP_INDEX_OFFSET, pic_params->chroma_qp_index_offset);
753    REGIO_WRITE_FIELD_MASKEDLITE(ctx->reg_PPS0, MSVDX_VEC_H264, CR_VEC_H264_BE_PPS0, BE_SECOND_CHROMA_QP_INDEX_OFFSET,  pic_params->second_chroma_qp_index_offset);
754
755    uint32_t PicHeightInMbs     = ctx->picture_height_mb >> pic_params->pic_fields.bits.field_pic_flag;         /* (7-23) */
756    uint32_t PicSizeInMbs       = ctx->picture_width_mb * PicHeightInMbs;                       /* (7-26) */
757
758    ctx->reg_PIC0 = 0;
759    REGIO_WRITE_FIELD_LITE(ctx->reg_PIC0, MSVDX_VEC_H264, CR_VEC_H264_FE_CUR_PIC0, PICSIZEINMBSLESS1,           PicSizeInMbs - 1);
760    REGIO_WRITE_FIELD_LITE(ctx->reg_PIC0, MSVDX_VEC_H264, CR_VEC_H264_FE_CUR_PIC0, PICHEIGHTINMBSLESS1,         PicHeightInMbs - 1);
761    /* TODO */
762    REGIO_WRITE_FIELD_LITE(ctx->reg_PIC0, MSVDX_VEC_H264, CR_VEC_H264_BE_CUR_PIC0, BE_REFERENCE_FLAG,           IS_USED_AS_REFERENCE(pic_params->CurrPic.flags) ? 1 : 0);
763    REGIO_WRITE_FIELD_LITE(ctx->reg_PIC0, MSVDX_VEC_H264, CR_VEC_H264_FE_CUR_PIC0, MBAFFFRAMEFLAG,              pic_params->seq_fields.bits.mb_adaptive_frame_field_flag);
764    REGIO_WRITE_FIELD_LITE(ctx->reg_PIC0, MSVDX_VEC_H264, CR_VEC_H264_FE_CUR_PIC0, FIELD_PIC_FLAG,              pic_params->pic_fields.bits.field_pic_flag);
765    REGIO_WRITE_FIELD_LITE(ctx->reg_PIC0, MSVDX_VEC_H264, CR_VEC_H264_FE_CUR_PIC0, BOTTOM_FIELD_FLAG,           pic_params->CurrPic.flags & VA_PICTURE_H264_BOTTOM_FIELD ? 1 : 0);
766
767    /* Record some info about current picture */
768    reg_value = 0;
769    REGIO_WRITE_FIELD(reg_value, MSVDX_VEC_H264, CR_VEC_H264_BE_COL_PIC0, COL_NOTFRAMEFLAG, (PICT_FRAME != ctx->pic_type) ? 1 : 0);
770    REGIO_WRITE_FIELD(reg_value, MSVDX_VEC_H264, CR_VEC_H264_BE_COL_PIC0, COL_MBAFFFRAMEFLAG, pic_params->seq_fields.bits.mb_adaptive_frame_field_flag);
771    SET_SURFACE_INFO_col_pic_params(target_surface, reg_value);
772
773    if (pic_params->seq_fields.bits.chroma_format_idc == 0) {
774        vaStatus = psb_surface_set_chroma(target_surface, 128);
775        CHECK_VASTATUS();
776    }
777
778    psb_CheckInterlaceRotate(ctx->obj_context, (unsigned char *)pic_params);
779
780
781#ifdef PSBVIDEO_MSVDX_EC
782    /* tell the driver to save the frame info for Error Concealment */
783    /*
784    if (driver_data->ec_enabled) {
785        psb_context_get_next_cmdbuf(ctx->obj_context);
786        psb_context_submit_frame_info(ctx->obj_context, &target_surface->buf,
787                                      target_surface->stride, target_surface->size,
788                                      ctx->picture_width_mb, ctx->size_mb);
789    }
790    */
791#endif
792    if ((ctx->picture_width_mb * 16) > 2048)
793        ctx->obj_context->driver_data->ec_enabled = 0;
794
795    return VA_STATUS_SUCCESS;
796}
797
798static VAStatus psb__H264_process_iq_matrix(context_H264_p ctx, object_buffer_p obj_buffer)
799{
800    ASSERT(obj_buffer->type == VAIQMatrixBufferType);
801    ASSERT(obj_buffer->num_elements == 1);
802    ASSERT(obj_buffer->size == sizeof(VAIQMatrixBufferH264));
803
804    if ((obj_buffer->num_elements != 1) ||
805        (obj_buffer->size != sizeof(VAIQMatrixBufferH264))) {
806        return VA_STATUS_ERROR_UNKNOWN;
807    }
808
809    /* Transfer ownership of VAIQMatrixBufferH264 data */
810    if (ctx->iq_matrix) {
811        free(ctx->iq_matrix);
812    }
813    ctx->iq_matrix = (VAIQMatrixBufferH264 *) obj_buffer->buffer_data;
814    obj_buffer->buffer_data = NULL;
815    obj_buffer->size = 0;
816
817    return VA_STATUS_SUCCESS;
818}
819
820static VAStatus psb__H264_process_slice_group_map(context_H264_p ctx, object_buffer_p obj_buffer)
821{
822    ASSERT(obj_buffer->type == VASliceGroupMapBufferType);
823    ASSERT(obj_buffer->num_elements == 1);
824//    ASSERT(obj_buffer->size == ...);
825
826    if (obj_buffer->num_elements != 1) {
827        return VA_STATUS_ERROR_UNKNOWN;
828    }
829
830    ctx->slice_group_map_buffer = obj_buffer->psb_buffer;
831
832    return VA_STATUS_SUCCESS;
833}
834
835#ifdef SLICE_HEADER_PARSING
836static VAStatus psb__H264_process_slice_header_group(context_H264_p ctx, object_buffer_p obj_buffer)
837{
838    ASSERT(obj_buffer->type == VAParsePictureParameterBufferType);
839    object_context_p obj_context = ctx->obj_context;
840    VAStatus vaStatus = VA_STATUS_SUCCESS;
841    /* Transfer ownership of VAPictureParameterBufferH264 data */
842    VAParsePictureParameterBuffer *pic_param_buf = (VAParsePictureParameterBuffer *) obj_buffer->buffer_data;
843    psb_driver_data_p driver_data = obj_context->driver_data;
844
845    object_buffer_p frame_obj_buffer = BUFFER(pic_param_buf->frame_buf_id);
846    if (NULL == frame_obj_buffer) {
847        vaStatus = VA_STATUS_ERROR_INVALID_BUFFER;
848        DEBUG_FAILURE;
849        return vaStatus;
850    }
851
852    object_buffer_p slice_header_obj_buffer = BUFFER(pic_param_buf->slice_headers_buf_id);
853    if (NULL == slice_header_obj_buffer) {
854        vaStatus = VA_STATUS_ERROR_INVALID_BUFFER;
855        DEBUG_FAILURE;
856        return vaStatus;
857    }
858
859    psb_context_get_next_cmdbuf(obj_context);
860    psb_cmdbuf_p cmdbuf = obj_context->cmdbuf;
861
862    uint32_t msg_size = sizeof(struct fw_slice_header_extract_msg);
863    uint32_t *msg = (uint32_t *)cmdbuf->MTX_msg;
864    memset(msg, 0, msg_size);
865    struct fw_slice_header_extract_msg *extract_msg;
866
867    drv_debug_msg(VIDEO_DEBUG_GENERAL, "Send nal parse cmd\n");
868    if (cmdbuf->cmd_count) {
869        drv_debug_msg(VIDEO_DEBUG_GENERAL, "nal parse cmdbuf has other msgs!\n");
870    }
871    extract_msg = (struct fw_slice_header_extract_msg *)msg;
872    extract_msg->header.bits.msg_size = sizeof(struct fw_slice_header_extract_msg);
873    extract_msg->header.bits.msg_type = VA_MSGID_SLICE_HEADER_EXTRACT;
874    extract_msg->flags.bits.flags = FW_VA_RENDER_HOST_INT;
875
876    extract_msg->src_size = pic_param_buf->frame_size;
877    extract_msg->dst_size = pic_param_buf->slice_headers_size;
878    extract_msg->flag_bitfield.bits.expected_pps_id =
879        pic_param_buf->expected_pic_parameter_set_id;
880
881    if (obj_context->modular_drm) {
882        extract_msg->flag_bitfield.bits.nalu_header_unit_type =
883            pic_param_buf->nalu_header.bits.nalu_header_unit_type;
884        extract_msg->flag_bitfield.bits.nalu_header_ref_idc =
885            pic_param_buf->nalu_header.bits.nalu_header_ref_idc;
886        extract_msg->header.bits.msg_type = VA_MSGID_MODULAR_SLICE_HEADER_EXTRACT;
887    }
888
889    extract_msg->flag_bitfield.bits.continue_parse_flag = 0;
890    extract_msg->flag_bitfield.bits.frame_mbs_only_flag =
891        pic_param_buf->flags.bits.frame_mbs_only_flag;
892    extract_msg->flag_bitfield.bits.pic_order_present_flag =
893        pic_param_buf->flags.bits.pic_order_present_flag;
894    extract_msg->flag_bitfield.bits.delta_pic_order_always_zero_flag =
895        pic_param_buf->flags.bits.delta_pic_order_always_zero_flag;
896    extract_msg->flag_bitfield.bits.redundant_pic_cnt_present_flag =
897        pic_param_buf->flags.bits.redundant_pic_cnt_present_flag;
898    extract_msg->flag_bitfield.bits.weighted_pred_flag =
899        pic_param_buf->flags.bits.weighted_pred_flag;
900    extract_msg->flag_bitfield.bits.entropy_coding_mode_flag =
901        pic_param_buf->flags.bits.entropy_coding_mode_flag;
902    extract_msg->flag_bitfield.bits.deblocking_filter_control_present_flag =
903        pic_param_buf->flags.bits.deblocking_filter_control_present_flag;
904    extract_msg->flag_bitfield.bits.weighted_bipred_idc =
905        pic_param_buf->flags.bits.weighted_bipred_idc;
906    extract_msg->flag_bitfield.bits.residual_colour_transform_flag =
907        pic_param_buf->residual_colour_transform_flag;
908    extract_msg->flag_bitfield.bits.chroma_format_idc =
909        pic_param_buf->chroma_format_idc;
910    extract_msg->flag_bitfield.bits.idr_flag =
911        pic_param_buf->idr_flag;
912    extract_msg->flag_bitfield.bits.pic_order_cnt_type =
913        pic_param_buf->pic_order_cnt_type;
914
915    extract_msg->pic_param0.bits.num_slice_groups_minus1 =
916        pic_param_buf->num_slice_groups_minus1;
917    extract_msg->pic_param0.bits.slice_group_map_type =
918        pic_param_buf->slice_group_map_type;
919    extract_msg->pic_param0.bits.log2_slice_group_change_cycle =
920        pic_param_buf->log2_slice_group_change_cycle;
921    extract_msg->pic_param0.bits.num_ref_idc_l0_active_minus1 =
922        pic_param_buf->num_ref_idc_l0_active_minus1;
923
924    extract_msg->pic_param0.bits.log2_max_pic_order_cnt_lsb_minus4 =
925        pic_param_buf->log2_max_pic_order_cnt_lsb_minus4;
926    extract_msg->pic_param0.bits.log2_max_frame_num_minus4 =
927        pic_param_buf->log2_max_frame_num_minus4;
928    extract_msg->pic_param0.bits.num_ref_idc_l1_active_minus1 =
929        pic_param_buf->num_ref_idc_l1_active_minus1;
930    extract_msg->pic_param0.bits.slice_header_bit_offset =
931        pic_param_buf->slice_offset;
932
933
934    RELOC_MSG(extract_msg->src, frame_obj_buffer->psb_buffer->buffer_ofs, frame_obj_buffer->psb_buffer);
935    RELOC_MSG(extract_msg->dst, slice_header_obj_buffer->psb_buffer->buffer_ofs, slice_header_obj_buffer->psb_buffer);
936
937    cmdbuf->parse_count++;
938
939    psb__suspend_buffer(driver_data, frame_obj_buffer);
940    psb__suspend_buffer(driver_data, slice_header_obj_buffer);
941
942    wsbmBOWaitIdle(ctx->reference_cache.drm_buf, 0);
943
944    if (psb_context_flush_cmdbuf(obj_context)) {
945        drv_debug_msg(VIDEO_DEBUG_ERROR, "psb_H264: flush parse cmdbuf error\n");
946        return VA_STATUS_ERROR_UNKNOWN;
947    }
948
949    return vaStatus;
950}
951#endif
952
953#define SCALING_LIST_4x4_SIZE   ((4*4))
954#define SCALING_LIST_8x8_SIZE   ((8*8))
955
956static void psb__H264_build_SCA_chunk(context_H264_p ctx)
957{
958    VAIQMatrixBufferH264 dummy_iq_matrix;
959    psb_cmdbuf_p cmdbuf = ctx->obj_context->cmdbuf;
960
961    VAIQMatrixBufferH264 *iq_matrix = ctx->iq_matrix;
962
963    if (!iq_matrix) {
964        drv_debug_msg(VIDEO_DEBUG_GENERAL, "H264: No IQ matrix received for frame. Sending dummy IQ matrix.\n");
965        iq_matrix = &dummy_iq_matrix;
966        memset(iq_matrix, 0, sizeof(VAIQMatrixBufferH264));
967    }
968
969    psb_cmdbuf_rendec_start(cmdbuf, REG_MSVDX_VEC_IQRAM_OFFSET);
970
971    /* 8x8 Inter Y */
972    psb_cmdbuf_rendec_write_block(cmdbuf, iq_matrix->ScalingList8x8[1], SCALING_LIST_8x8_SIZE);
973
974    /* 8x8 Intra Y */
975    psb_cmdbuf_rendec_write_block(cmdbuf, iq_matrix->ScalingList8x8[0], SCALING_LIST_8x8_SIZE);
976
977    /* 4x4 Intra Y */
978    psb_cmdbuf_rendec_write_block(cmdbuf, iq_matrix->ScalingList4x4[0], SCALING_LIST_4x4_SIZE);
979
980    /* 4x4 Inter Y */
981    psb_cmdbuf_rendec_write_block(cmdbuf, iq_matrix->ScalingList4x4[3], SCALING_LIST_4x4_SIZE);
982
983    /* 4x4 Inter Cb */
984    psb_cmdbuf_rendec_write_block(cmdbuf, iq_matrix->ScalingList4x4[4], SCALING_LIST_4x4_SIZE);
985
986    /* 4x4 Intra Cb */
987    psb_cmdbuf_rendec_write_block(cmdbuf, iq_matrix->ScalingList4x4[1], SCALING_LIST_4x4_SIZE);
988
989    /* 4x4 Inter Cr */
990    psb_cmdbuf_rendec_write_block(cmdbuf, iq_matrix->ScalingList4x4[5], SCALING_LIST_4x4_SIZE);
991
992    /* 4x4 Intra Cr */
993    psb_cmdbuf_rendec_write_block(cmdbuf, iq_matrix->ScalingList4x4[2], SCALING_LIST_4x4_SIZE);
994
995    psb_cmdbuf_rendec_end(cmdbuf);
996}
997
998static void psb__H264_build_picture_order_chunk(context_H264_p ctx)
999{
1000    psb_cmdbuf_p cmdbuf = ctx->obj_context->cmdbuf;
1001    VAPictureParameterBufferH264 *pic_params = ctx->pic_params;
1002    uint32_t reg_value;
1003    int i;
1004
1005    /* CHUNK: POC */
1006    /* send Picture Order Counts (b frame only?) */
1007    /* maybe need a state variable to track if this has already been sent for the frame */
1008    psb_cmdbuf_rendec_start(cmdbuf, RENDEC_REGISTER_OFFSET(MSVDX_VEC, H264_CR_VEC_H264_BE_FOC0));
1009
1010    reg_value = 0;
1011    REGIO_WRITE_FIELD_LITE(reg_value, MSVDX_VEC_H264, CR_VEC_H264_BE_FOC0, TOPFIELDORDERCNT_CURR,
1012                           SIGNTRUNC(pic_params->CurrPic.TopFieldOrderCnt));
1013    psb_cmdbuf_rendec_write(cmdbuf, reg_value);
1014
1015    reg_value = 0;
1016    REGIO_WRITE_FIELD_LITE(reg_value, MSVDX_VEC_H264, CR_VEC_H264_BE_FOC1, BOTTOMFIELDORDERCNT_CURR,
1017                           SIGNTRUNC(pic_params->CurrPic.BottomFieldOrderCnt));
1018    psb_cmdbuf_rendec_write(cmdbuf, reg_value);
1019
1020    if (pic_params->num_ref_frames > 16) {
1021        drv_debug_msg(VIDEO_DEBUG_ERROR, "Invalid reference number %d, set to 16\n", pic_params->num_ref_frames);
1022        pic_params->num_ref_frames = 16;
1023    }
1024
1025    for (i = 0; i < 16; i++) {
1026        uint32_t refidx = ctx->map_dpbidx_to_refidx[i];
1027        if (refidx < 16) {
1028            reg_value = 0;
1029            REGIO_WRITE_FIELD_LITE(reg_value, MSVDX_VEC_H264, CR_VEC_H264_BE_TOP_FOC, TOPFIELDORDERCNT,
1030                                   SIGNTRUNC(pic_params->ReferenceFrames[refidx].TopFieldOrderCnt));
1031            psb_cmdbuf_rendec_write(cmdbuf, reg_value);
1032
1033            reg_value = 0;
1034            REGIO_WRITE_FIELD_LITE(reg_value, MSVDX_VEC_H264, CR_VEC_H264_BE_BOT_FOC, BOTTOMFIELDORDERCNT,
1035                               SIGNTRUNC(pic_params->ReferenceFrames[refidx].BottomFieldOrderCnt));
1036            psb_cmdbuf_rendec_write(cmdbuf, reg_value);
1037        }
1038        else {
1039            psb_cmdbuf_rendec_write(cmdbuf, 0);
1040            psb_cmdbuf_rendec_write(cmdbuf, 0);
1041        }
1042    }
1043
1044    psb_cmdbuf_rendec_end(cmdbuf);
1045}
1046
1047static void psb__H264_build_B_slice_chunk(context_H264_p ctx, VASliceParameterBufferH264 *slice_param)
1048{
1049    psb_cmdbuf_p cmdbuf = ctx->obj_context->cmdbuf;
1050    VAPictureParameterBufferH264 *pic_params = ctx->pic_params;
1051    uint32_t reg_value;
1052    int i;
1053
1054    psb_cmdbuf_rendec_start(cmdbuf, RENDEC_REGISTER_OFFSET(MSVDX_VEC, H264_CR_VEC_H264_BE_COL_PIC0));
1055
1056    /* Colocated picture is picture 0 in list 1*/
1057    object_surface_p colocated_surface = SURFACE(slice_param->RefPicList1[0].picture_id);
1058    if (colocated_surface) {
1059        uint32_t bottom_field_flag;
1060        if (pic_params->pic_fields.bits.field_pic_flag) {
1061            bottom_field_flag  = (slice_param->RefPicList1[0].flags & VA_PICTURE_H264_BOTTOM_FIELD) ? 1 : 0;
1062        } else {
1063            /* when current pic is a frame col bottom field flag is different */
1064            IMG_INT32   i32Cur;
1065            IMG_INT32   i32Top, i32Bot;
1066            IMG_INT32   i32TopAbsDiffPoc, i32BotAbsDiffPoc;
1067
1068            /* current pic */
1069            i32Top = pic_params->CurrPic.TopFieldOrderCnt;
1070            i32Bot = pic_params->CurrPic.BottomFieldOrderCnt;
1071            i32Cur = (i32Top < i32Bot) ? i32Top : i32Bot;
1072
1073            /* col pic */
1074            i32Top = slice_param->RefPicList1[0].TopFieldOrderCnt;
1075            i32Bot = slice_param->RefPicList1[0].BottomFieldOrderCnt;
1076
1077            i32TopAbsDiffPoc = (i32Cur < i32Top) ? i32Top - i32Cur : i32Cur - i32Top;
1078            i32BotAbsDiffPoc = (i32Cur < i32Bot) ? i32Bot - i32Cur : i32Cur - i32Bot;
1079
1080            bottom_field_flag = (i32TopAbsDiffPoc < i32BotAbsDiffPoc) ? 0 : 1;
1081        }
1082
1083        reg_value = GET_SURFACE_INFO_col_pic_params(colocated_surface->psb_surface);
1084        REGIO_WRITE_FIELD(reg_value, MSVDX_VEC_H264, CR_VEC_H264_BE_COL_PIC0, COL_BOTTOM_FIELD_FLAG, bottom_field_flag);
1085        psb_cmdbuf_rendec_write(cmdbuf, reg_value);
1086
1087        psb_buffer_p colocated_target_buffer = vld_dec_lookup_colocated_buffer(&ctx->dec_ctx, colocated_surface->psb_surface);
1088        ASSERT(colocated_target_buffer);
1089        if (colocated_target_buffer) {
1090            psb_cmdbuf_rendec_write_address(cmdbuf, colocated_target_buffer, 0);
1091        } else {
1092            /* This is an error */
1093            psb_cmdbuf_rendec_write(cmdbuf, 0);
1094        }
1095    } else {
1096        /* Need some better error handling here */
1097        psb_cmdbuf_rendec_write(cmdbuf, 0);
1098        psb_cmdbuf_rendec_write(cmdbuf, 0xDEADBEEF);
1099    }
1100
1101    /* Calculate inverse index for reference pictures */
1102    {
1103        IMG_UINT8 list0_inverse[32];
1104        memset(list0_inverse, 0xff, 32); /* Unused entries get 0xff */
1105
1106        if (slice_param->num_ref_idx_l0_active_minus1 + 1 > 32) {
1107            drv_debug_msg(VIDEO_DEBUG_ERROR, "num_ref_idx_l0_active_minus1(%d) is too big. Set it with 31\n",
1108                               slice_param->num_ref_idx_l0_active_minus1);
1109            slice_param->num_ref_idx_l0_active_minus1 = 31;
1110        }
1111
1112        if (slice_param->num_ref_idx_l0_active_minus1 > 30)
1113            slice_param->num_ref_idx_l0_active_minus1 = 30;
1114        for (i = slice_param->num_ref_idx_l0_active_minus1 + 1; i--;) {
1115            object_surface_p surface = SURFACE(slice_param->RefPicList0[i].picture_id);
1116            if (surface) {
1117                uint32_t dpb_idx = GET_SURFACE_INFO_dpb_idx(surface->psb_surface);
1118                if (dpb_idx < 16) {
1119                    if (slice_param->RefPicList0[i].flags & VA_PICTURE_H264_BOTTOM_FIELD) {
1120                        dpb_idx |= 0x10;
1121                    }
1122                    list0_inverse[dpb_idx] = i;
1123                }
1124            }
1125        }
1126        for (i = 0; i < 32; i += 4) {
1127            reg_value = 0;
1128            reg_value |= list0_inverse[i];
1129            reg_value |= list0_inverse[i+1] << 8;
1130            reg_value |= list0_inverse[i+2] << 16;
1131            reg_value |= list0_inverse[i+3] << 24;
1132            psb_cmdbuf_rendec_write(cmdbuf, reg_value);
1133        }
1134    }
1135
1136    if (slice_param->num_ref_idx_l1_active_minus1 > 28)
1137        slice_param->num_ref_idx_l1_active_minus1 = 28;
1138
1139    /* Write Ref List 1 - but only need the valid ones */
1140    for (i = 0; i <= slice_param->num_ref_idx_l1_active_minus1; i += 4) {
1141        reg_value = 0;
1142        reg_value |= PICTURE2INDEX(ctx, &slice_param->RefPicList1[i]);
1143        reg_value |= PICTURE2INDEX(ctx, &slice_param->RefPicList1[i+1]) << 8;
1144        reg_value |= PICTURE2INDEX(ctx, &slice_param->RefPicList1[i+2]) << 16;
1145        reg_value |= PICTURE2INDEX(ctx, &slice_param->RefPicList1[i+3]) << 24;
1146        psb_cmdbuf_rendec_write(cmdbuf, reg_value);
1147    }
1148
1149    psb_cmdbuf_rendec_end(cmdbuf);
1150}
1151
1152static void psb__H264_build_register(context_H264_p ctx, VASliceParameterBufferH264 *slice_param)
1153{
1154    psb_cmdbuf_p cmdbuf = ctx->obj_context->cmdbuf;
1155    uint32_t reg_value;
1156
1157    psb_cmdbuf_reg_start_block(cmdbuf, 0);
1158
1159    reg_value = 0;
1160    REGIO_WRITE_FIELD_LITE(reg_value, MSVDX_VEC, CR_VEC_ENTDEC_FE_CONTROL, ENTDEC_FE_PROFILE, ctx->profile);
1161    REGIO_WRITE_FIELD_LITE(reg_value, MSVDX_VEC, CR_VEC_ENTDEC_FE_CONTROL, ENTDEC_FE_MODE, 1); /* 1 - H.264 */
1162
1163    psb_cmdbuf_reg_set(cmdbuf, REGISTER_OFFSET(MSVDX_VEC, CR_VEC_ENTDEC_FE_CONTROL), reg_value);
1164
1165    /* write the FE registers */
1166    psb_cmdbuf_reg_set(cmdbuf, REGISTER_OFFSET(MSVDX_VEC_H264, CR_VEC_H264_FE_SPS0),    ctx->reg_SPS0);
1167    psb_cmdbuf_reg_set(cmdbuf, REGISTER_OFFSET(MSVDX_VEC_H264, CR_VEC_H264_FE_PPS0),    ctx->reg_PPS0);
1168    psb_cmdbuf_reg_set(cmdbuf, REGISTER_OFFSET(MSVDX_VEC_H264, CR_VEC_H264_FE_CUR_PIC0),        ctx->reg_PIC0);
1169    psb_cmdbuf_reg_set(cmdbuf, REGISTER_OFFSET(MSVDX_VEC_H264, CR_VEC_H264_FE_SLICE0),  ctx->slice0_params);
1170    psb_cmdbuf_reg_set(cmdbuf, REGISTER_OFFSET(MSVDX_VEC_H264, CR_VEC_H264_FE_SLICE1),  ctx->slice1_params);
1171
1172    reg_value = 0;
1173    REGIO_WRITE_FIELD_LITE(reg_value, MSVDX_VEC_H264, CR_VEC_H264_FE_SLICE2, FIRST_MB_IN_SLICE, slice_param->first_mb_in_slice);
1174    psb_cmdbuf_reg_set(cmdbuf, REGISTER_OFFSET(MSVDX_VEC_H264, CR_VEC_H264_FE_SLICE2), reg_value);
1175
1176    if (ctx->pic_params->num_slice_groups_minus1 >= 1) {
1177        ctx->obj_context->driver_data->ec_enabled = 0;
1178        ASSERT(ctx->slice_group_map_buffer);
1179        if (ctx->slice_group_map_buffer) {
1180            psb_cmdbuf_reg_set_address(cmdbuf, REGISTER_OFFSET(MSVDX_VEC_H264, CR_VEC_H264_FE_BASE_ADDR_SGM),
1181                                       ctx->slice_group_map_buffer, 0);
1182        }
1183    }
1184    psb_cmdbuf_reg_end_block(cmdbuf);
1185}
1186
1187static void psb__H264_build_rendec_params(context_H264_p ctx, VASliceParameterBufferH264 *slice_param)
1188{
1189    psb_cmdbuf_p cmdbuf = ctx->obj_context->cmdbuf;
1190    psb_surface_p target_surface = ctx->obj_context->current_render_target->psb_surface;
1191    VAPictureParameterBufferH264 *pic_params = ctx->pic_params;
1192    uint32_t reg_value;
1193    unsigned int i;
1194
1195    /* psb_cmdbuf_rendec_start_block( cmdbuf ); */
1196
1197    /* CHUNK: Entdec back-end profile and level */
1198    {
1199        psb_cmdbuf_rendec_start(cmdbuf, RENDEC_REGISTER_OFFSET(MSVDX_VEC, CR_VEC_ENTDEC_BE_CONTROL));
1200
1201        reg_value = 0;
1202        REGIO_WRITE_FIELD_LITE(reg_value, MSVDX_VEC, CR_VEC_ENTDEC_BE_CONTROL, ENTDEC_BE_PROFILE, ctx->profile);
1203        REGIO_WRITE_FIELD_LITE(reg_value, MSVDX_VEC, CR_VEC_ENTDEC_BE_CONTROL, ENTDEC_BE_MODE, 1); /* 1 - H.264 */
1204        psb_cmdbuf_rendec_write(cmdbuf, reg_value);
1205
1206        psb_cmdbuf_rendec_end(cmdbuf);
1207    }
1208
1209    /* CHUNK: SEQ Registers */
1210    /* send Slice Data for every slice */
1211    /* MUST be the last slice sent */
1212    psb_cmdbuf_rendec_start(cmdbuf, RENDEC_REGISTER_OFFSET(MSVDX_VEC, H264_CR_VEC_H264_BE_SPS0));
1213
1214    psb_cmdbuf_rendec_write(cmdbuf, ctx->reg_SPS0);
1215    psb_cmdbuf_rendec_write(cmdbuf, ctx->reg_PPS0);
1216    psb_cmdbuf_rendec_write(cmdbuf, ctx->reg_PIC0);
1217    psb_cmdbuf_rendec_write(cmdbuf, ctx->slice0_params);
1218    psb_cmdbuf_rendec_write(cmdbuf, ctx->slice1_params);
1219
1220    /* 5.5.75. VEC_H264_BE_BASE_ADDR_CUR_PIC */
1221    psb_buffer_p colocated_target_buffer = vld_dec_lookup_colocated_buffer(&ctx->dec_ctx, target_surface);
1222    ASSERT(colocated_target_buffer);
1223    if (colocated_target_buffer) {
1224        psb_cmdbuf_rendec_write_address(cmdbuf, colocated_target_buffer, colocated_target_buffer->buffer_ofs);
1225    } else {
1226        /* This is an error */
1227        psb_cmdbuf_rendec_write(cmdbuf, 0);
1228    }
1229
1230    reg_value = 0;
1231    REGIO_WRITE_FIELD(reg_value, MSVDX_VEC_H264, CR_VEC_H264_BE_REF0, BE_LONGTERMFRAMEFLAG, ctx->long_term_frame_flags);
1232    psb_cmdbuf_rendec_write(cmdbuf, reg_value);
1233
1234    psb_cmdbuf_rendec_end(cmdbuf);
1235
1236    //#warning "TODO: MUST be done after fe slice1 (which gives MB address) "
1237    /*          REGIO_WRITE_REGISTER(0, MSVDX_VEC_H264, CR_VEC_H264_FE_BASE_ADDR_SGM, gui32SliceGroupType6BaseAddressHack); */
1238
1239    /* CHUNK: SCA */
1240    /* send Scaling Lists in High Profile for first slice*/
1241    if (ctx->profile == H264_HIGH_PROFILE) {
1242        psb__H264_build_SCA_chunk(ctx);
1243    }
1244
1245    /* CHUNK: POC */
1246    /* send Picture Order Counts (b frame only?) */
1247    /* maybe need a state variable to track if this has already been sent for the frame */
1248    if (slice_param->slice_type == ST_B) {
1249        psb__H264_build_picture_order_chunk(ctx);
1250    }
1251
1252    /* CHUNK: BIN */
1253    /* send B-slice information for B-slices */
1254    if (slice_param->slice_type == ST_B) {
1255        psb__H264_build_B_slice_chunk(ctx, slice_param);
1256    }
1257
1258    /* CHUNK: PIN */
1259    /* send P+B-slice information for P and B slices */
1260    if (slice_param->slice_type == ST_B ||  slice_param->slice_type == ST_P) {
1261        psb_cmdbuf_rendec_start(cmdbuf, RENDEC_REGISTER_OFFSET(MSVDX_VEC, H264_CR_VEC_H264_BE_LIST0));
1262
1263        if (slice_param->num_ref_idx_l0_active_minus1 > 31) {
1264            drv_debug_msg(VIDEO_DEBUG_ERROR, "num_ref_idx_l0_active_minus1(%d) is too big, limit it to 31.\n",
1265                               slice_param->num_ref_idx_l0_active_minus1);
1266            slice_param->num_ref_idx_l0_active_minus1 = 28;
1267        }
1268
1269        for (i = 0; i <= slice_param->num_ref_idx_l0_active_minus1; i += 4) {
1270            reg_value = 0;
1271            reg_value |= PICTURE2INDEX(ctx, &slice_param->RefPicList0[i]);
1272            reg_value |= PICTURE2INDEX(ctx, &slice_param->RefPicList0[i+1]) << 8;
1273            reg_value |= PICTURE2INDEX(ctx, &slice_param->RefPicList0[i+2]) << 16;
1274            reg_value |= PICTURE2INDEX(ctx, &slice_param->RefPicList0[i+3]) << 24;
1275            psb_cmdbuf_rendec_write(cmdbuf, reg_value);
1276        }
1277
1278        psb_cmdbuf_rendec_end(cmdbuf);
1279    }
1280
1281    /* CHUNK: DPB */
1282    /* send DPB information (for P and B slices?) only needed once per frame */
1283//      if ( sh->slice_type == ST_B || sh->slice_type == ST_P )
1284    if (pic_params->num_ref_frames > 0 && (slice_param->slice_type == ST_B || slice_param->slice_type == ST_P)) {
1285        psb_cmdbuf_rendec_start(cmdbuf, RENDEC_REGISTER_OFFSET(MSVDX_CMDS, REFERENCE_PICTURE_BASE_ADDRESSES));
1286
1287        uint32_t dpbidx = 0;
1288        for (dpbidx = 0; dpbidx < 16; dpbidx++) {
1289        /* Only load used surfaces */
1290            if (VA_INVALID_SURFACE != ctx->map_dpbidx_to_picture_id[dpbidx]) {
1291                object_surface_p ref_surface = SURFACE(ctx->map_dpbidx_to_picture_id[dpbidx]);
1292                psb_buffer_p buffer;
1293
1294                if (NULL == ref_surface) {
1295                    drv_debug_msg(VIDEO_DEBUG_ERROR, "%s L%d Invalide reference surface handle\n",
1296                                       __FUNCTION__, __LINE__);
1297                    return;
1298                }
1299
1300                buffer = ref_surface->psb_surface->ref_buf;
1301            /*
1302            drv_debug_msg(VIDEO_DEBUG_GENERAL, "pic_params->ReferenceFrames[%d] = %08x --> %08x frame_idx:0x%08x flags:%02x TopFieldOrderCnt: 0x%08x BottomFieldOrderCnt: 0x%08x %s\n",
1303                                     i,
1304                                     pic_params->ReferenceFrames[i].picture_id,
1305                                     ref_surface,
1306                                     pic_params->ReferenceFrames[i].frame_idx,
1307                                     pic_params->ReferenceFrames[i].flags,
1308                                     pic_params->ReferenceFrames[i].TopFieldOrderCnt,
1309                                     pic_params->ReferenceFrames[i].BottomFieldOrderCnt,
1310                                     is_used[i] ? "used" : "");
1311            */
1312                if (ref_surface && buffer) {
1313                    psb_cmdbuf_rendec_write_address(cmdbuf, buffer,
1314                                                    buffer->buffer_ofs);
1315                    psb_cmdbuf_rendec_write_address(cmdbuf, buffer,
1316                                                    buffer->buffer_ofs +
1317                                                    ref_surface->psb_surface->chroma_offset);
1318                    buffer->unfence_flag = 1;
1319                } else {
1320                    // error here
1321                    drv_debug_msg(VIDEO_DEBUG_ERROR, "%s:%d No valid buffer for DPB",__FILE__, __LINE__);
1322                    psb_cmdbuf_rendec_write(cmdbuf, 0xdeadbeef);
1323                    psb_cmdbuf_rendec_write(cmdbuf, 0xdeadbeef);
1324                }
1325            } else {
1326                psb_cmdbuf_rendec_write(cmdbuf, 0xdeadbeef);
1327                psb_cmdbuf_rendec_write(cmdbuf, 0xdeadbeef);
1328            }
1329        }
1330        psb_cmdbuf_rendec_end(cmdbuf);
1331    }
1332
1333    /** fixed partial crc error in h264 case **/
1334    target_surface->buf.unfence_flag = 0;
1335
1336    /* CHUNK: MVA and MVB */
1337    /* works as long as weighted factors A and B commands remain the same */
1338    if ((pic_params->pic_fields.bits.weighted_pred_flag && (slice_param->slice_type == ST_P)) ||
1339        ((pic_params->pic_fields.bits.weighted_bipred_idc != 0) && (slice_param->slice_type == ST_B))) {
1340        IMG_UINT32 num_ref_0 = slice_param->num_ref_idx_l0_active_minus1;
1341
1342        psb_cmdbuf_rendec_start(cmdbuf, RENDEC_REGISTER_OFFSET(MSVDX_CMDS, H264_WEIGHTED_FACTORS_A));
1343
1344        if (num_ref_0 > 31)
1345            num_ref_0 = 31;
1346
1347        /* weighted factors */
1348        for (i = 0; i <= num_ref_0; i++) {
1349            reg_value = 0;
1350            REGIO_WRITE_FIELD_MASKEDLITE(reg_value, MSVDX_CMDS, H264_WEIGHTED_FACTORS_A, CR_WEIGHT_A,   slice_param->chroma_weight_l0[i][1]);/* Cr - 1 */
1351            REGIO_WRITE_FIELD_MASKEDLITE(reg_value, MSVDX_CMDS, H264_WEIGHTED_FACTORS_A, CB_WEIGHT_A,   slice_param->chroma_weight_l0[i][0]);/* Cb - 0 */
1352            REGIO_WRITE_FIELD_MASKEDLITE(reg_value, MSVDX_CMDS, H264_WEIGHTED_FACTORS_A, Y_WEIGHT_A,    slice_param->luma_weight_l0[i]);
1353
1354            psb_cmdbuf_rendec_write(cmdbuf, reg_value);
1355        }
1356        /* pad remainder */
1357        for (; i < 32; i++) {
1358            psb_cmdbuf_rendec_write(cmdbuf, 0);
1359        }
1360
1361        /* weighted offsets */
1362        for (i = 0; i <= num_ref_0; i++) {
1363            reg_value = 0;
1364            REGIO_WRITE_FIELD_MASKEDLITE(reg_value, MSVDX_CMDS, H264_WEIGHTED_OFFSET_A, CR_OFFSET_A,    slice_param->chroma_offset_l0[i][1]);/* Cr - 1 */
1365            REGIO_WRITE_FIELD_MASKEDLITE(reg_value, MSVDX_CMDS, H264_WEIGHTED_OFFSET_A, CB_OFFSET_A,    slice_param->chroma_offset_l0[i][0]);/* Cb - 0 */
1366            REGIO_WRITE_FIELD_MASKEDLITE(reg_value, MSVDX_CMDS, H264_WEIGHTED_OFFSET_A, Y_OFFSET_A,     slice_param->luma_offset_l0[i]);
1367
1368            psb_cmdbuf_rendec_write(cmdbuf, reg_value);
1369        }
1370        /* pad remainder */
1371        for (; i < 32; i++) {
1372            psb_cmdbuf_rendec_write(cmdbuf, 0);
1373        }
1374        psb_cmdbuf_rendec_end(cmdbuf);
1375
1376        if (slice_param->slice_type == ST_B) {
1377            IMG_UINT32 num_ref_1 = slice_param->num_ref_idx_l1_active_minus1;
1378
1379            psb_cmdbuf_rendec_start(cmdbuf, RENDEC_REGISTER_OFFSET(MSVDX_CMDS, H264_WEIGHTED_FACTORS_B));
1380
1381            if (num_ref_1 > 31) {
1382                drv_debug_msg(VIDEO_DEBUG_ERROR, "num_ref_1 shouldn't be larger than 31\n");
1383                num_ref_1 = 31;
1384            }
1385
1386            /* weighted factors */
1387            for (i = 0; i <= num_ref_1; i++) {
1388                reg_value = 0;
1389                REGIO_WRITE_FIELD_MASKEDLITE(reg_value, MSVDX_CMDS, H264_WEIGHTED_FACTORS_B, CR_WEIGHT_B,       slice_param->chroma_weight_l1[i][1]);/* Cr - 1 */
1390                REGIO_WRITE_FIELD_MASKEDLITE(reg_value, MSVDX_CMDS, H264_WEIGHTED_FACTORS_B, CB_WEIGHT_B,       slice_param->chroma_weight_l1[i][0]);/* Cb - 0 */
1391                REGIO_WRITE_FIELD_MASKEDLITE(reg_value, MSVDX_CMDS, H264_WEIGHTED_FACTORS_B, Y_WEIGHT_B,        slice_param->luma_weight_l1[i]);
1392
1393                psb_cmdbuf_rendec_write(cmdbuf, reg_value);
1394            }
1395            /* pad remainder */
1396            for (; i < 32; i++) {
1397                psb_cmdbuf_rendec_write(cmdbuf, 0);
1398            }
1399
1400            /* weighted offsets */
1401            for (i = 0; i <= num_ref_1; i++) {
1402                reg_value = 0;
1403                REGIO_WRITE_FIELD_MASKEDLITE(reg_value, MSVDX_CMDS, H264_WEIGHTED_OFFSET_B, CR_OFFSET_B,        slice_param->chroma_offset_l1[i][1]);/* Cr - 1 */
1404                REGIO_WRITE_FIELD_MASKEDLITE(reg_value, MSVDX_CMDS, H264_WEIGHTED_OFFSET_B, CB_OFFSET_B,        slice_param->chroma_offset_l1[i][0]);/* Cb - 0 */
1405                REGIO_WRITE_FIELD_MASKEDLITE(reg_value, MSVDX_CMDS, H264_WEIGHTED_OFFSET_B, Y_OFFSET_B, slice_param->luma_offset_l1[i]);
1406
1407                psb_cmdbuf_rendec_write(cmdbuf, reg_value);
1408            }
1409            /* pad remainder */
1410            for (; i < 32; i++) {
1411                psb_cmdbuf_rendec_write(cmdbuf, 0);
1412            }
1413            psb_cmdbuf_rendec_end(cmdbuf);
1414        }
1415    }
1416
1417
1418    /* CHUNK: SEQ Commands 1 */
1419    /* send Slice Data for every slice */
1420    /* MUST be the last slice sent */
1421    psb_cmdbuf_rendec_start(cmdbuf, RENDEC_REGISTER_OFFSET(MSVDX_CMDS, DISPLAY_PICTURE_SIZE));
1422
1423    reg_value = 0;
1424    REGIO_WRITE_FIELD_LITE(reg_value, MSVDX_CMDS, DISPLAY_PICTURE_SIZE, DISPLAY_PICTURE_HEIGHT, (ctx->picture_height_mb * 16) - 1);
1425    REGIO_WRITE_FIELD_LITE(reg_value, MSVDX_CMDS, DISPLAY_PICTURE_SIZE, DISPLAY_PICTURE_WIDTH, (ctx->picture_width_mb * 16) - 1);
1426    psb_cmdbuf_rendec_write(cmdbuf, reg_value);
1427
1428    reg_value = 0;
1429    REGIO_WRITE_FIELD_LITE(reg_value, MSVDX_CMDS, CODED_PICTURE_SIZE, CODED_PICTURE_HEIGHT, (ctx->picture_height_mb * 16) - 1);
1430    REGIO_WRITE_FIELD_LITE(reg_value, MSVDX_CMDS, CODED_PICTURE_SIZE, CODED_PICTURE_WIDTH, (ctx->picture_width_mb * 16) - 1);
1431    psb_cmdbuf_rendec_write(cmdbuf, reg_value);
1432
1433    reg_value = 0;
1434    // TODO: Must check how these should be set
1435    REGIO_WRITE_FIELD_LITE(reg_value, MSVDX_CMDS, OPERATING_MODE, CHROMA_INTERLEAVED, 0);
1436    REGIO_WRITE_FIELD_LITE(reg_value, MSVDX_CMDS, OPERATING_MODE, ROW_STRIDE, target_surface->stride_mode);
1437    REGIO_WRITE_FIELD_LITE(reg_value, MSVDX_CMDS, OPERATING_MODE, CODEC_PROFILE, ctx->profile);
1438    REGIO_WRITE_FIELD_LITE(reg_value, MSVDX_CMDS, OPERATING_MODE, CODEC_MODE, 1);       /* H.264 */
1439    REGIO_WRITE_FIELD_LITE(reg_value, MSVDX_CMDS, OPERATING_MODE, ASYNC_MODE, (ctx->two_pass_mode && !ctx->pic_params->seq_fields.bits.mb_adaptive_frame_field_flag));
1440    REGIO_WRITE_FIELD_LITE(reg_value, MSVDX_CMDS, OPERATING_MODE, CHROMA_FORMAT, pic_params->seq_fields.bits.chroma_format_idc);
1441    psb_cmdbuf_rendec_write(cmdbuf, reg_value);
1442
1443    ctx->obj_context->operating_mode = reg_value;
1444
1445    if ((ctx->deblock_mode ==  DEBLOCK_INTRA_OOLD) && ctx->two_pass_mode) { /* Need to mark which buf is to be used as ref*/
1446        /* LUMA_RECONSTRUCTED_PICTURE_BASE_ADDRESSES */
1447        psb_cmdbuf_rendec_write_address(cmdbuf, target_surface->in_loop_buf, target_surface->in_loop_buf->buffer_ofs);
1448
1449        /* CHROMA_RECONSTRUCTED_PICTURE_BASE_ADDRESSES */
1450        psb_cmdbuf_rendec_write_address(cmdbuf, target_surface->in_loop_buf, target_surface->in_loop_buf->buffer_ofs + target_surface->chroma_offset);
1451        target_surface->ref_buf = target_surface->in_loop_buf;
1452        //target_surface->in_loop_buf->unfence_flag |= 2;
1453    } else {
1454        psb_cmdbuf_rendec_write_address(cmdbuf, &target_surface->buf, target_surface->buf.buffer_ofs);
1455        psb_cmdbuf_rendec_write_address(cmdbuf, &target_surface->buf, target_surface->buf.buffer_ofs + target_surface->chroma_offset);
1456        target_surface->ref_buf = &target_surface->buf;
1457        //target_surface->buf.unfence_flag = 2;
1458    }
1459
1460    /* Aux Msb Buffer base address: H.264 does not use this command */
1461    reg_value = 0;
1462    psb_cmdbuf_rendec_write(cmdbuf, reg_value);
1463
1464    /* Intra Reference Cache */
1465    psb_cmdbuf_rendec_write_address(cmdbuf, &ctx->reference_cache, 0);
1466
1467    reg_value = 0;
1468    REGIO_WRITE_FIELD_LITE(reg_value, MSVDX_CMDS, MC_CACHE_CONFIGURATION, CONFIG_REF_OFFSET, CACHE_REF_OFFSET);
1469    REGIO_WRITE_FIELD_LITE(reg_value, MSVDX_CMDS, MC_CACHE_CONFIGURATION, CONFIG_ROW_OFFSET, CACHE_ROW_OFFSET);
1470    psb_cmdbuf_rendec_write(cmdbuf, reg_value);
1471
1472    /* Vc1 Intensity compensation: H.264 does not use this command */
1473    reg_value = 0;
1474    psb_cmdbuf_rendec_write(cmdbuf, reg_value);
1475
1476    reg_value = 0;
1477    REGIO_WRITE_FIELD_LITE(reg_value, MSVDX_CMDS, H264_WEIGHTED_FACTOR_DENOMINATOR, C_LOG2_WEIGHT_DENOM, slice_param->chroma_log2_weight_denom);
1478    REGIO_WRITE_FIELD_LITE(reg_value, MSVDX_CMDS, H264_WEIGHTED_FACTOR_DENOMINATOR, Y_LOG2_WEIGHT_DENOM, slice_param->luma_log2_weight_denom);
1479    psb_cmdbuf_rendec_write(cmdbuf, reg_value);
1480
1481    psb_cmdbuf_rendec_end(cmdbuf);
1482
1483    /* CHUNK: SEQ Commands 2 */
1484    /* send Slice Data for every slice */
1485    /* MUST be the last slice sent */
1486    {
1487        IMG_UINT32 ui32Mode  = pic_params->pic_fields.bits.weighted_pred_flag | (pic_params->pic_fields.bits.weighted_bipred_idc << 1);
1488
1489        psb_cmdbuf_rendec_start(cmdbuf, RENDEC_REGISTER_OFFSET(MSVDX_CMDS, SLICE_PARAMS));
1490
1491        reg_value = 0;
1492        REGIO_WRITE_FIELD_LITE(reg_value, MSVDX_CMDS, SLICE_PARAMS, CONSTRAINED_INTRA_PRED, pic_params->pic_fields.bits.constrained_intra_pred_flag);
1493        REGIO_WRITE_FIELD_LITE(reg_value, MSVDX_CMDS, SLICE_PARAMS, MODE_CONFIG, ui32Mode);
1494        REGIO_WRITE_FIELD_LITE(reg_value, MSVDX_CMDS, SLICE_PARAMS, DISABLE_DEBLOCK_FILTER_IDC, slice_param->disable_deblocking_filter_idc);
1495        REGIO_WRITE_FIELD_MASKEDLITE(reg_value, MSVDX_CMDS, SLICE_PARAMS, SLICE_ALPHA_CO_OFFSET_DIV2, slice_param->slice_alpha_c0_offset_div2);
1496        REGIO_WRITE_FIELD_MASKEDLITE(reg_value, MSVDX_CMDS, SLICE_PARAMS, SLICE_BETA_OFFSET_DIV2, slice_param->slice_beta_offset_div2);
1497        REGIO_WRITE_FIELD_LITE(reg_value, MSVDX_CMDS, SLICE_PARAMS, SLICE_FIELD_TYPE, ctx->field_type);
1498        REGIO_WRITE_FIELD_LITE(reg_value, MSVDX_CMDS, SLICE_PARAMS, SLICE_CODE_TYPE, aSliceTypeVAtoMsvdx[slice_param->slice_type % 5]);
1499        psb_cmdbuf_rendec_write(cmdbuf, reg_value);
1500
1501        /* Store slice parameters in header */
1502        *(ctx->dec_ctx.p_slice_params) = reg_value;
1503
1504        psb_cmdbuf_rendec_end(cmdbuf);
1505    }
1506
1507    /*          If this a two pass mode deblock, then we will perform the rotation as part of the
1508     *          2nd pass deblock procedure
1509     */
1510    if (!ctx->two_pass_mode)
1511        vld_dec_setup_alternative_frame(ctx->obj_context);
1512}
1513
1514static void psb__H264_preprocess_slice(context_H264_p ctx,
1515                                       VASliceParameterBufferH264 *slice_param)
1516{
1517    VAPictureParameterBufferH264 *pic_params = ctx->pic_params;
1518    uint32_t slice_qpy;
1519
1520    ctx->first_mb_x = slice_param->first_mb_in_slice % ctx->picture_width_mb;
1521    ctx->first_mb_y = slice_param->first_mb_in_slice / ctx->picture_width_mb;
1522    ctx->slice0_params = 0;
1523    ctx->slice1_params = 0;
1524
1525    ASSERT(pic_params);
1526    if (!pic_params) {
1527        /* This is an error */
1528        return;
1529    }
1530
1531    if (!pic_params->pic_fields.bits.field_pic_flag && pic_params->seq_fields.bits.mb_adaptive_frame_field_flag) {
1532        /* If in MBAFF mode multiply MB y-address by 2 */
1533        ctx->first_mb_y *= 2;
1534    }
1535
1536    slice_qpy = 26 + pic_params->pic_init_qp_minus26 + slice_param->slice_qp_delta;     /* (7-27) */
1537
1538    REGIO_WRITE_FIELD_LITE(ctx->slice0_params, MSVDX_VEC_H264, CR_VEC_H264_BE_SLICE0, BE_DIRECT_SPATIAL_MV_PRED_FLAG,                   slice_param->direct_spatial_mv_pred_flag);
1539    REGIO_WRITE_FIELD_LITE(ctx->slice0_params, MSVDX_VEC_H264, CR_VEC_H264_BE_SLICE0, H264_BE_SLICE0_DISABLE_DEBLOCK_FILTER_IDC,        slice_param->disable_deblocking_filter_idc);
1540    REGIO_WRITE_FIELD_MASKEDLITE(ctx->slice0_params, MSVDX_VEC_H264, CR_VEC_H264_BE_SLICE0, H264_BE_SLICE0_ALPHA_CO_OFFSET_DIV2,        slice_param->slice_alpha_c0_offset_div2);
1541    REGIO_WRITE_FIELD_MASKEDLITE(ctx->slice0_params, MSVDX_VEC_H264, CR_VEC_H264_BE_SLICE0, H264_BE_SLICE0_BETA_OFFSET_DIV2,            slice_param->slice_beta_offset_div2);
1542    REGIO_WRITE_FIELD_LITE(ctx->slice0_params, MSVDX_VEC_H264, CR_VEC_H264_BE_SLICE0, H264_BE_SLICE0_FIELD_TYPE,                        ctx->field_type);
1543    REGIO_WRITE_FIELD_LITE(ctx->slice0_params, MSVDX_VEC_H264, CR_VEC_H264_FE_SLICE0, SLICETYPE,                                        aSliceTypeVAtoMsvdx[ slice_param->slice_type % 5]);
1544    REGIO_WRITE_FIELD_LITE(ctx->slice0_params, MSVDX_VEC_H264, CR_VEC_H264_FE_SLICE0, CABAC_INIT_IDC,                                   slice_param->cabac_init_idc);
1545    REGIO_WRITE_FIELD_LITE(ctx->slice0_params, MSVDX_VEC_H264, CR_VEC_H264_FE_SLICE0, SLICECOUNT,                                       ctx->slice_count);
1546
1547    REGIO_WRITE_FIELD_LITE(ctx->slice1_params, MSVDX_VEC_H264, CR_VEC_H264_FE_SLICE1, FIRST_MB_IN_SLICE_X,      ctx->first_mb_x);
1548    REGIO_WRITE_FIELD_LITE(ctx->slice1_params, MSVDX_VEC_H264, CR_VEC_H264_FE_SLICE1, FIRST_MB_IN_SLICE_Y,      ctx->first_mb_y);
1549    REGIO_WRITE_FIELD_LITE(ctx->slice1_params, MSVDX_VEC_H264, CR_VEC_H264_FE_SLICE1, SLICEQPY,                 slice_qpy);
1550    REGIO_WRITE_FIELD_LITE(ctx->slice1_params, MSVDX_VEC_H264, CR_VEC_H264_FE_SLICE1, NUM_REF_IDX_L0_ACTIVE_MINUS1, slice_param->num_ref_idx_l0_active_minus1);
1551    REGIO_WRITE_FIELD_LITE(ctx->slice1_params, MSVDX_VEC_H264, CR_VEC_H264_FE_SLICE1, NUM_REF_IDX_L1_ACTIVE_MINUS1, slice_param->num_ref_idx_l1_active_minus1);
1552
1553    IMG_BOOL deblocker_disable = (slice_param->disable_deblocking_filter_idc  == 1);
1554
1555    if (deblocker_disable) {
1556        if (ctx->obj_context->is_oold) {
1557            ctx->deblock_mode = DEBLOCK_INTRA_OOLD;
1558            ctx->two_pass_mode = 1;
1559            REGIO_WRITE_FIELD_LITE(ctx->reg_SPS0, MSVDX_VEC_H264, CR_VEC_H264_BE_SPS0, H264_BE_SPS0_2PASS_FLAG, ctx->two_pass_mode);
1560        } else
1561            ctx->deblock_mode = DEBLOCK_STD;
1562    } else {
1563        ctx->deblock_mode = DEBLOCK_STD;
1564    }
1565}
1566
1567/* **************************************************************************************************************** */
1568/* Prepacked calculates VLC table offsets and reg address                                                           */
1569/* **************************************************************************************************************** */
1570static const  IMG_UINT32 ui32H264VLCTableRegValPair[] = {
1571    (REGISTER_OFFSET(MSVDX_VEC, CR_VEC_VLC_TABLE_ADDR0) + 0x00000000), 0x00026000,
1572    (REGISTER_OFFSET(MSVDX_VEC, CR_VEC_VLC_TABLE_ADDR0) + 0x00000004), 0x000738a0,
1573    (REGISTER_OFFSET(MSVDX_VEC, CR_VEC_VLC_TABLE_ADDR0) + 0x00000008), 0x000828f4,
1574    (REGISTER_OFFSET(MSVDX_VEC, CR_VEC_VLC_TABLE_ADDR0) + 0x0000000c), 0x000a312d,
1575    (REGISTER_OFFSET(MSVDX_VEC, CR_VEC_VLC_TABLE_ADDR0) + 0x00000010), 0x000b5959,
1576    (REGISTER_OFFSET(MSVDX_VEC, CR_VEC_VLC_TABLE_ADDR0) + 0x00000014), 0x000c517b,
1577    (REGISTER_OFFSET(MSVDX_VEC, CR_VEC_VLC_TABLE_ADDR0) + 0x00000018), 0x000d1196,
1578    (REGISTER_OFFSET(MSVDX_VEC, CR_VEC_VLC_TABLE_ADDR0) + 0x0000001c), 0x000db1ad,
1579    (REGISTER_OFFSET(MSVDX_VEC, CR_VEC_VLC_TABLE_ADDR0) + 0x00000020), 0x000e21be,
1580    (REGISTER_OFFSET(MSVDX_VEC, CR_VEC_VLC_TABLE_ADDR0) + 0x00000024), 0x000e59c8,
1581    (REGISTER_OFFSET(MSVDX_VEC, CR_VEC_VLC_TABLE_ADDR0) + 0x00000028), 0x000e79cd,
1582    (REGISTER_OFFSET(MSVDX_VEC, CR_VEC_VLC_TABLE_ADDR0) + 0x0000002c), 0x000eb1d3,
1583    (REGISTER_OFFSET(MSVDX_VEC, CR_VEC_VLC_TABLE_ADDR0) + 0x00000030), 0x000ed1d8,
1584    (REGISTER_OFFSET(MSVDX_VEC, CR_VEC_VLC_TABLE_ADDR0) + 0x00000034), 0x000f09dd,
1585    (REGISTER_OFFSET(MSVDX_VEC, CR_VEC_VLC_TABLE_ADDR0) + 0x00000038), 0x000f71e7,
1586    (REGISTER_OFFSET(MSVDX_VEC, CR_VEC_VLC_TABLE_ADDR0) + 0x0000003c), 0x000001f6,
1587    (REGISTER_OFFSET(MSVDX_VEC, CR_VEC_VLC_TABLE_ADDR0) + 0x00000040), 0x1256a4dd,
1588    (REGISTER_OFFSET(MSVDX_VEC, CR_VEC_VLC_TABLE_ADDR0) + 0x00000044), 0x01489292,
1589    (REGISTER_OFFSET(MSVDX_VEC, CR_VEC_VLC_TABLE_ADDR0) + 0x00000048), 0x11248050,
1590    (REGISTER_OFFSET(MSVDX_VEC, CR_VEC_VLC_TABLE_ADDR0) + 0x0000004c), 0x00000002,
1591    (REGISTER_OFFSET(MSVDX_VEC, CR_VEC_VLC_TABLE_ADDR0) + 0x00000050), 0x00002a02,
1592    (REGISTER_OFFSET(MSVDX_VEC, CR_VEC_VLC_TABLE_ADDR0) + 0x00000054), 0x0108282a,
1593};
1594
1595
1596static void psb__H264_write_VLC_tables(context_H264_p ctx)
1597{
1598    psb_cmdbuf_p cmdbuf = ctx->obj_context->cmdbuf;
1599    unsigned int i;
1600
1601    psb_cmdbuf_skip_start_block(cmdbuf, SKIP_ON_CONTEXT_SWITCH);
1602
1603    /* VLC Table */
1604    /* Write a LLDMA Cmd to transfer VLD Table data */
1605    psb_cmdbuf_dma_write_cmdbuf(cmdbuf, &ctx->vlc_packed_table, 0,
1606                                  sizeof(ui16H264VLCTableData), 0,
1607                                  DMA_TYPE_VLC_TABLE);
1608
1609    /* Writes the VLD offsets.  mtx need only do this on context switch*/
1610    psb_cmdbuf_reg_start_block(cmdbuf, 0);
1611
1612    for (i = 0; i < (sizeof(ui32H264VLCTableRegValPair) / sizeof(ui32H264VLCTableRegValPair[0])) ; i += 2) {
1613        psb_cmdbuf_reg_set(cmdbuf, ui32H264VLCTableRegValPair[i] , ui32H264VLCTableRegValPair[i + 1]);
1614    }
1615
1616    psb_cmdbuf_reg_end_block(cmdbuf);
1617
1618    psb_cmdbuf_skip_end_block(cmdbuf);
1619}
1620
1621static void psb__H264_begin_slice(context_DEC_p dec_ctx, VASliceParameterBufferBase *vld_slice_param)
1622{
1623    VASliceParameterBufferH264 *slice_param = (VASliceParameterBufferH264 *) vld_slice_param;
1624    context_H264_p ctx = (context_H264_p)dec_ctx;
1625#ifdef SLICE_HEADER_PARSING
1626    if (dec_ctx->parse_enabled == 1)
1627        dec_ctx->parse_key = slice_param->slice_data_bit_offset;
1628#endif
1629    psb__H264_preprocess_slice(ctx, slice_param);
1630    psb__H264_write_VLC_tables(ctx);
1631
1632    dec_ctx->bits_offset = slice_param->slice_data_bit_offset;
1633
1634    /* CMD_SR_VERIFY_STARTCODE, clean this flag to work when no start code in slice data */
1635#ifdef SLICE_HEADER_PARSING
1636    if (dec_ctx->parse_enabled == 1)
1637        dec_ctx->SR_flags = CMD_ENABLE_RBDU_EXTRACTION | CMD_SR_BITSTR_PARSE_KEY;
1638    else
1639#endif
1640        dec_ctx->SR_flags = CMD_ENABLE_RBDU_EXTRACTION;
1641    ctx->slice_param = slice_param;
1642}
1643
1644static void psb__H264_process_slice_data(context_DEC_p dec_ctx, VASliceParameterBufferBase *vld_slice_param)
1645{
1646    VASliceParameterBufferH264 *slice_param = (VASliceParameterBufferH264 *) vld_slice_param;
1647    context_H264_p ctx = (context_H264_p)dec_ctx;
1648
1649    psb__H264_build_register(ctx, slice_param);
1650    psb__H264_build_rendec_params(ctx, slice_param);
1651}
1652
1653static void psb__H264_end_slice(context_DEC_p dec_ctx)
1654{
1655    context_H264_p ctx = (context_H264_p)dec_ctx;
1656    if (ctx->slice_count == 0) {
1657        ctx->obj_context->flags |= FW_VA_RENDER_IS_FIRST_SLICE;
1658    }
1659    if (ctx->pic_params->seq_fields.bits.mb_adaptive_frame_field_flag) {
1660        ctx->obj_context->flags |= FW_VA_RENDER_IS_H264_MBAFF;
1661    }
1662    if (ctx->two_pass_mode) {
1663        ctx->obj_context->flags |= FW_VA_RENDER_IS_TWO_PASS_DEBLOCK;
1664    }
1665    ctx->obj_context->flags |= FW_VA_RENDER_IS_VLD_NOT_MC; /* FW_ERROR_DETECTION_AND_RECOVERY */
1666
1667#ifdef PSBVIDEO_MSVDX_EC
1668    if (ctx->obj_context->driver_data->ec_enabled)
1669        ctx->obj_context->flags |= (FW_ERROR_DETECTION_AND_RECOVERY); /* FW_ERROR_DETECTION_AND_RECOVERY */
1670#endif
1671
1672    ctx->obj_context->first_mb = (ctx->first_mb_y << 8) | ctx->first_mb_x;
1673    ctx->obj_context->last_mb = (((ctx->picture_height_mb >> ctx->pic_params->pic_fields.bits.field_pic_flag) - 1) << 8) | (ctx->picture_width_mb - 1);
1674    *(dec_ctx->slice_first_pic_last) = (ctx->obj_context->first_mb << 16) | (ctx->obj_context->last_mb);
1675
1676    ctx->slice_count++;
1677}
1678
1679#ifdef PSBVIDEO_MSVDX_EC
1680static void psb__H264_choose_ec_frames(context_H264_p ctx)
1681{
1682    ctx->obj_context->ec_target = NULL;
1683    if (ctx->slice_param == NULL)
1684        return;
1685    /* If reference picture list has a valid entry, this is a P or B frame and we conceal from the frame that is at the top of the list*/
1686    object_surface_p ref_surface = SURFACE(ctx->slice_param->RefPicList0[0].picture_id);
1687    ctx->obj_context->ec_target = ref_surface;
1688
1689    /* Otherwise we conceal from the previous I or P frame*/
1690    if (!ctx->obj_context->ec_target)
1691    {
1692        ctx->obj_context->ec_target = ctx->obj_context->ec_candidate;
1693    }
1694
1695    if (ctx->slice_param->slice_type != ST_B)
1696    {
1697        ctx->obj_context->ec_candidate = ctx->obj_context->current_render_target; /* in case the next frame is an I frame we will need this */
1698    }
1699    if (!ctx->obj_context->ec_target) {
1700        ctx->obj_context->ec_target = ctx->obj_context->current_render_target;
1701    }
1702}
1703#endif
1704
1705static VAStatus pnw_H264_BeginPicture(
1706    object_context_p obj_context)
1707{
1708    INIT_CONTEXT_H264
1709
1710#ifdef SLICE_HEADER_PARSING
1711    obj_context->msvdx_frame_end = 0;
1712#endif
1713
1714    if (ctx->pic_params) {
1715        free(ctx->pic_params);
1716        ctx->pic_params = NULL;
1717    }
1718    if (ctx->iq_matrix) {
1719        free(ctx->iq_matrix);
1720        ctx->iq_matrix = NULL;
1721    }
1722    ctx->slice_count = 0;
1723    ctx->slice_group_map_buffer = NULL;
1724    ctx->deblock_mode = DEBLOCK_NONE;
1725
1726    return VA_STATUS_SUCCESS;
1727}
1728
1729static VAStatus pnw_H264_process_buffer(
1730    context_DEC_p dec_ctx,
1731    object_buffer_p buffer)
1732{
1733    context_H264_p ctx = (context_H264_p)dec_ctx;
1734    VAStatus vaStatus = VA_STATUS_SUCCESS;
1735    object_buffer_p obj_buffer = buffer;
1736
1737    {
1738        switch (obj_buffer->type) {
1739        case VAPictureParameterBufferType:
1740            vaStatus = psb__H264_process_picture_param(ctx, obj_buffer);
1741            DEBUG_FAILURE;
1742            break;
1743
1744        case VAIQMatrixBufferType:
1745            vaStatus = psb__H264_process_iq_matrix(ctx, obj_buffer);
1746            DEBUG_FAILURE;
1747            break;
1748
1749        case VASliceGroupMapBufferType:
1750            vaStatus = psb__H264_process_slice_group_map(ctx, obj_buffer);
1751            DEBUG_FAILURE;
1752            break;
1753#ifdef SLICE_HEADER_PARSING
1754        case VAParsePictureParameterBufferType:
1755            dec_ctx->parse_enabled = 1;
1756            vaStatus = psb__H264_process_slice_header_group(ctx, obj_buffer);
1757            DEBUG_FAILURE;
1758            break;
1759#endif
1760        default:
1761            vaStatus = VA_STATUS_ERROR_UNKNOWN;
1762            DEBUG_FAILURE;
1763        }
1764    }
1765
1766    return vaStatus;
1767}
1768
1769static VAStatus pnw_H264_EndPicture(
1770    object_context_p obj_context)
1771{
1772    INIT_CONTEXT_H264
1773    psb_surface_p target_surface = ctx->obj_context->current_render_target->psb_surface;
1774    psb_driver_data_p driver_data = obj_context->driver_data;
1775    VAStatus vaStatus = VA_STATUS_SUCCESS;
1776
1777    if (ctx->two_pass_mode) {
1778        psb_buffer_p colocated_target_buffer = vld_dec_lookup_colocated_buffer(&ctx->dec_ctx, target_surface);
1779        psb_surface_p rotate_surface = ctx->obj_context->current_render_target->out_loop_surface;
1780        uint32_t rotation_flags = 0;
1781        uint32_t ext_stride_a = 0;
1782
1783        drv_debug_msg(VIDEO_DEBUG_GENERAL, "pnw_H264_EndPicture got two pass mode frame\n");
1784        CHECK_BUFFER(colocated_target_buffer);
1785        if (CONTEXT_ROTATE(ctx->obj_context)) {
1786            ASSERT(rotate_surface);
1787            REGIO_WRITE_FIELD_LITE(rotation_flags, MSVDX_CMDS, ALTERNATIVE_OUTPUT_PICTURE_ROTATION , ALT_PICTURE_ENABLE, 1);
1788            REGIO_WRITE_FIELD_LITE(rotation_flags, MSVDX_CMDS, ALTERNATIVE_OUTPUT_PICTURE_ROTATION , ROTATION_ROW_STRIDE, rotate_surface->stride_mode);
1789            REGIO_WRITE_FIELD_LITE(rotation_flags, MSVDX_CMDS, ALTERNATIVE_OUTPUT_PICTURE_ROTATION , RECON_WRITE_DISABLE, 0); /* FIXME Always generate Rec */
1790            REGIO_WRITE_FIELD_LITE(rotation_flags, MSVDX_CMDS, ALTERNATIVE_OUTPUT_PICTURE_ROTATION , ROTATION_MODE, GET_SURFACE_INFO_rotate(rotate_surface));
1791        }
1792
1793        REGIO_WRITE_FIELD_LITE(ext_stride_a, MSVDX_CMDS, EXTENDED_ROW_STRIDE, EXT_ROW_STRIDE, target_surface->stride / 64);
1794
1795        /* Issue two pass deblock cmd, HW can handle deblock instead of host when using DE2.x firmware */
1796        if (ctx->deblock_mode == DEBLOCK_STD) {
1797            if (psb_context_submit_hw_deblock(ctx->obj_context,
1798                                              &target_surface->buf,
1799                                              rotate_surface ? (&rotate_surface->buf) : NULL,
1800                                              colocated_target_buffer,
1801                                              ctx->picture_width_mb,
1802                                              ctx->picture_height_mb,
1803                                              rotation_flags,
1804                                              ctx->field_type,
1805                                              ext_stride_a,
1806                                              target_surface->chroma_offset + target_surface->buf.buffer_ofs,
1807                                              rotate_surface ? (rotate_surface->chroma_offset + rotate_surface->buf.buffer_ofs) : 0,
1808                                              ctx->deblock_mode == DEBLOCK_INTRA_OOLD)) {
1809                return VA_STATUS_ERROR_UNKNOWN;
1810            }
1811        } else if (ctx->deblock_mode == DEBLOCK_INTRA_OOLD) {
1812            psb_buffer_p buffer_dst;
1813            uint32_t chroma_offset_dst;
1814
1815            if (CONTEXT_ROTATE(ctx->obj_context) == 0) {
1816                buffer_dst = &target_surface->buf;
1817                chroma_offset_dst = target_surface->chroma_offset;
1818            } else {
1819                if (!rotate_surface) {
1820                    return VA_STATUS_ERROR_UNKNOWN;
1821                }
1822
1823                buffer_dst = &rotate_surface->buf;
1824                chroma_offset_dst = rotate_surface->chroma_offset;
1825            }
1826
1827            if (psb_context_submit_hw_deblock(ctx->obj_context,
1828                                              target_surface->in_loop_buf,
1829                                              buffer_dst,
1830                                              colocated_target_buffer,
1831                                              ctx->picture_width_mb,
1832                                              ctx->picture_height_mb,
1833                                              rotation_flags,
1834                                              ctx->field_type,
1835                                              ext_stride_a,
1836                                              target_surface->chroma_offset + target_surface->buf.buffer_ofs,
1837                                              chroma_offset_dst,
1838                                              ctx->deblock_mode == DEBLOCK_INTRA_OOLD)) {
1839                return VA_STATUS_ERROR_UNKNOWN;
1840            }
1841        }
1842    }
1843
1844#ifdef PSBVIDEO_MSVDX_EC
1845    /* Sent the HOST_BE_OPP command to detect slice error */
1846    if (driver_data->ec_enabled) {
1847        uint32_t rotation_flags = 0;
1848        uint32_t ext_stride_a = 0;
1849        object_surface_p ec_target;
1850
1851        psb__H264_choose_ec_frames(ctx);
1852        ec_target = ctx->obj_context->ec_target;
1853        REGIO_WRITE_FIELD_LITE(ext_stride_a, MSVDX_CMDS, EXTENDED_ROW_STRIDE, EXT_ROW_STRIDE, target_surface->stride / 64);
1854
1855    /* FIXME ec ignor rotate condition */
1856        if(ec_target) {
1857	    if (psb_context_get_next_cmdbuf(ctx->obj_context)) {
1858                vaStatus = VA_STATUS_ERROR_UNKNOWN;
1859                DEBUG_FAILURE;
1860                return vaStatus;
1861            }
1862
1863            if (psb_context_submit_host_be_opp(ctx->obj_context,
1864                                          &target_surface->buf,
1865                                          &ec_target->psb_surface->buf,
1866                                          NULL,
1867                                          ctx->picture_width_mb,
1868                                          ctx->picture_height_mb,
1869                                          rotation_flags,
1870                                          ctx->field_type,
1871                                          ext_stride_a,
1872                                          target_surface->chroma_offset + target_surface->buf.buffer_ofs,
1873                                          ec_target->psb_surface->chroma_offset + ec_target->psb_surface->buf.buffer_ofs)) {
1874                return VA_STATUS_ERROR_UNKNOWN;
1875            }
1876        }
1877    }
1878#endif
1879#ifdef SLICE_HEADER_PARSING
1880    if (driver_data->protected)
1881        obj_context->msvdx_frame_end = 1;
1882#endif
1883
1884    if (psb_context_flush_cmdbuf(ctx->obj_context)) {
1885        return VA_STATUS_ERROR_UNKNOWN;
1886    }
1887
1888    if (CONTEXT_ROTATE(obj_context) && CONTEXT_SCALING(obj_context))
1889    {
1890        CONTEXT_SCALING(obj_context) = 0;
1891        vld_dec_yuv_rotate(obj_context);
1892        CONTEXT_SCALING(obj_context) = 1;
1893        ctx->dec_ctx.process_buffer = pnw_H264_process_buffer;
1894
1895        if (psb_context_flush_cmdbuf(ctx->obj_context)) {
1896            return VA_STATUS_ERROR_UNKNOWN;
1897        }
1898    }
1899
1900    if (ctx->pic_params) {
1901        free(ctx->pic_params);
1902        ctx->pic_params = NULL;
1903    }
1904
1905    if (ctx->iq_matrix) {
1906        free(ctx->iq_matrix);
1907        ctx->iq_matrix = NULL;
1908    }
1909
1910    return VA_STATUS_SUCCESS;
1911}
1912
1913struct format_vtable_s pnw_H264_vtable = {
1914queryConfigAttributes:
1915    pnw_H264_QueryConfigAttributes,
1916validateConfig:
1917    pnw_H264_ValidateConfig,
1918createContext:
1919    pnw_H264_CreateContext,
1920destroyContext:
1921    pnw_H264_DestroyContext,
1922beginPicture:
1923    pnw_H264_BeginPicture,
1924renderPicture:
1925    vld_dec_RenderPicture,
1926endPicture:
1927    pnw_H264_EndPicture
1928};
1929