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