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