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 * Shengquan Yuan <shengquan.yuan@intel.com>
27 *
28 */
29
30 #include "psb_MPEG2.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_vdmc_reg_io2.h"
40 #include "hwdefs/msvdx_vec_reg_io2.h"
41 #include "hwdefs/msvdx_vec_mpeg2_reg_io2.h"
42 #include "hwdefs/dxva_fw_ctrl.h"
43
44 #include <stdlib.h>
45 #include <stdint.h>
46 #include <string.h>
47
48
49 /* TODO: for interlace
50 * bit 0: first vector forward
51 * bit 1: first vector backward
52 * bit 2: second vector forward
53 * bit 3: second vector backward
54 */
55 #define MBPARAM_MvertFieldSel_3(ptr) (((ptr)->motion_vertical_field_select & 0x8) >> 3)
56 #define MBPARAM_MvertFieldSel_2(ptr) (((ptr)->motion_vertical_field_select & 0x4) >> 2)
57 #define MBPARAM_MvertFieldSel_1(ptr) (((ptr)->motion_vertical_field_select & 0x2) >> 1)
58 #define MBPARAM_MvertFieldSel_0(ptr) (((ptr)->motion_vertical_field_select & 0x1) >> 0)
59 #define MBPARAM_MotionType(ptr) (((ptr)->macroblock_modes.bits.frame_motion_type << 1) | (ptr)->macroblock_modes.bits.field_motion_type)
60 #define MBPARAM_MotionBackward(ptr) (((ptr)->macroblock_type & VA_MB_TYPE_MOTION_BACKWARD)?1:0)
61 #define MBPARAM_MotionForward(ptr) (((ptr)->macroblock_type & VA_MB_TYPE_MOTION_FORWARD)?1:0)
62 #define MBPARAM_IntraMacroblock(ptr) ((ptr)->macroblock_type & VA_MB_TYPE_MOTION_INTRA )
63 #define MBPARAM_CodedBlockPattern(ptr) ((ptr)->coded_block_pattern << 6) /* align with VA code */
64 #define MBPARAM_MBskipsFollowing(ptr) ((ptr)->num_skipped_macroblocks)
65
66 typedef enum { MB_CODE_TYPE_I , MB_CODE_TYPE_P , MB_CODE_TYPE_B , MB_CODE_TYPE_GMC } eMB_CODE_TYPE;
67
68 /* Constants */
69 #define PICTURE_CODING_I 0x01
70 #define PICTURE_CODING_P 0x02
71 #define PICTURE_CODING_B 0x03
72
73 #define CODEC_MODE_MPEG2 3
74 #define CODEC_PROFILE_MPEG2_MAIN 1
75
76 /* picture structure */
77 #define TOP_FIELD 1
78 #define BOTTOM_FIELD 2
79 #define FRAME_PICTURE 3
80
81 #define INTRA_MB_WORST_CASE 6
82 #define INTER_MB_WORST_CASE 100
83
84 static const uint32_t pict_libva2msvdx[] = {0,/* Invalid picture type */
85 0,/* I picture */
86 1,/* P picture */
87 2,/* B pricture */
88 3
89 };/* Invalid picture type */
90
91
92 static const uint32_t ft_libva2msvdx[] = {0,/* Invalid picture type */
93 0,/* Top field */
94 1,/* Bottom field */
95 2
96 };/* Frame picture */
97
98
99 struct context_MPEG2MC_s {
100 object_context_p obj_context; /* back reference */
101
102 VAMacroblockParameterBufferMPEG2 *mb_param ; /* Pointer to the mbCtrl structure */
103 uint32_t mb_in_buffer; /* Number of MBs in current buffer */
104 uint32_t mb_first_addr; /* MB address of first mb in buffer */
105
106 uint32_t picture_coding_type;
107 uint32_t picture_structure;
108
109 uint32_t coded_picture_width;
110 uint32_t coded_picture_height;
111
112 uint32_t picture_width_mb; /* in macroblocks */
113 uint32_t picture_height_mb; /* in macroblocks */
114 uint32_t size_mb; /* in macroblocks */
115
116 VAPictureParameterBufferMPEG2 *pic_params;
117
118 object_surface_p forward_ref_surface;
119 object_surface_p backward_ref_surface;
120
121 uint32_t ref_indexA;
122 uint32_t ref_indexB;
123
124 uint32_t coded_picture_size;
125 uint32_t display_picture_size;
126 uint32_t operation_mode;
127
128 uint32_t *lldma_idx; /* Index in command stream for LLDMA pointer */
129 uint32_t residual_pendingDMA;
130 IMG_INT32 residual_sent;
131
132 psb_buffer_p residual_buf;
133 uint32_t blk_in_buffer;/* buffer elements */
134 uint32_t blk_size;/* buffer elements size */
135
136 uint32_t fstmb_slice;
137 };
138
139 typedef struct context_MPEG2MC_s *context_MPEG2MC_p;
140
141 #define INIT_CONTEXT_MPEG2MC context_MPEG2MC_p ctx = (context_MPEG2MC_p) obj_context->format_data
142 #define SURFACE(id) ((object_surface_p) object_heap_lookup( &ctx->obj_context->driver_data->surface_heap, id ))
143
psb__MPEG2MC_send_interPB_prediction(context_MPEG2MC_p ctx,psb_cmdbuf_p const cmdbuf,VAMacroblockParameterBufferMPEG2 * const mb_param,int second_pred)144 static void psb__MPEG2MC_send_interPB_prediction(
145 context_MPEG2MC_p ctx,
146 psb_cmdbuf_p const cmdbuf,
147 VAMacroblockParameterBufferMPEG2 * const mb_param,
148 int second_pred
149 )
150 {
151 uint32_t cmd;
152 uint32_t blk_size;
153 uint32_t pred_offset;
154
155 /* Determine residual data's block size (16x8 or 16x16) */
156 if (FRAME_PICTURE == ctx->picture_structure) {
157 if ((1 == MBPARAM_MotionType(mb_param)) || /* Field MC */
158 (3 == MBPARAM_MotionType(mb_param))) { /* Dual Prime */
159 blk_size = 1; /* 16 x 8 */
160 } else {
161 blk_size = 0; /* 16 x 16 */
162 }
163 } else {
164 if (2 == MBPARAM_MotionType(mb_param)) { /* Non-Frame MC */
165 blk_size = 1; /* 16 x 8 */
166 } else {
167 blk_size = 0; /* 16 x 16 */
168 }
169 }
170
171 /* Determine whether this is for 1st MV or 2nd MV */
172 if (TRUE == second_pred) {
173 pred_offset = 8;
174 } else {
175 pred_offset = 0;
176 }
177
178 cmd = 0;
179
180 REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, INTER_BLOCK_PREDICTION, INTER_PRED_BLOCK_SIZE, blk_size);
181
182 REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, INTER_BLOCK_PREDICTION, REF_INDEX_A, ctx->ref_indexA);
183 REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, INTER_BLOCK_PREDICTION, REF_INDEX_B, ctx->ref_indexB);
184
185 if (3 == MBPARAM_MotionType(mb_param)) { /* Dual Prime */
186 REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, INTER_BLOCK_PREDICTION, REF_INDEX_A_VALID, 1);
187 REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, INTER_BLOCK_PREDICTION, REF_INDEX_B_VALID, 1);
188 } else {
189 REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, INTER_BLOCK_PREDICTION, REF_INDEX_A_VALID,
190 MBPARAM_MotionForward(mb_param));
191 REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, INTER_BLOCK_PREDICTION, REF_INDEX_B_VALID,
192 MBPARAM_MotionBackward(mb_param));
193 }
194
195 if (FRAME_PICTURE == ctx->picture_structure) {
196 /* Frame picture processing */
197 if ((1 == MBPARAM_MotionType(mb_param)) || /* Field MC */
198 (3 == MBPARAM_MotionType(mb_param))) { /* Dual Prime */
199 if ((1 == MBPARAM_MotionForward(mb_param)) ||
200 (3 == MBPARAM_MotionType(mb_param))) { /* Dual Prime */
201 if (second_pred) {
202 REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, INTER_BLOCK_PREDICTION,
203 REF_INDEX_FIELD_A, MBPARAM_MvertFieldSel_2(mb_param));
204 } else {
205 REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, INTER_BLOCK_PREDICTION,
206 REF_INDEX_FIELD_A, MBPARAM_MvertFieldSel_0(mb_param));
207 }
208 }
209
210 if ((1 == MBPARAM_MotionBackward(mb_param)) ||
211 (3 == MBPARAM_MotionType(mb_param))) { /* Dual Prime */
212 if (second_pred) {
213 REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, INTER_BLOCK_PREDICTION,
214 REF_INDEX_FIELD_B, MBPARAM_MvertFieldSel_3(mb_param));
215 } else {
216 REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, INTER_BLOCK_PREDICTION,
217 REF_INDEX_FIELD_B, MBPARAM_MvertFieldSel_1(mb_param));
218 }
219 }
220 }
221 } else {
222 /* Field picture processing */
223 if ((0 == MBPARAM_MotionForward(mb_param)) &&
224 (0 == MBPARAM_MotionBackward(mb_param))) {
225 REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, INTER_BLOCK_PREDICTION, REF_INDEX_A, ctx->ref_indexA);
226 REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, INTER_BLOCK_PREDICTION, REF_INDEX_B, ctx->ref_indexB);
227 }
228
229 if (1 == MBPARAM_MotionForward(mb_param)) {
230 if (second_pred) {
231 if ((0 == MBPARAM_MvertFieldSel_2(mb_param)) &&
232 (PICTURE_CODING_P == ctx->picture_coding_type)) { /* Top field of this frame */
233 REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, INTER_BLOCK_PREDICTION, REF_INDEX_A, ctx->ref_indexB);
234 } else { /* Bottom field of previous frame*/
235 REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, INTER_BLOCK_PREDICTION, REF_INDEX_A, ctx->ref_indexA);
236 }
237
238 REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, INTER_BLOCK_PREDICTION, REF_INDEX_FIELD_A,
239 MBPARAM_MvertFieldSel_2(mb_param));
240 } else {
241 if (((ctx->picture_structure == BOTTOM_FIELD) != MBPARAM_MvertFieldSel_0(mb_param)) &&
242 (PICTURE_CODING_P == ctx->picture_coding_type)) { /* Top field of this frame */
243 REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, INTER_BLOCK_PREDICTION, REF_INDEX_A, ctx->ref_indexB);
244 } else { /* Bottom field of previous frame*/
245 REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, INTER_BLOCK_PREDICTION, REF_INDEX_A, ctx->ref_indexA);
246 }
247
248 REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, INTER_BLOCK_PREDICTION, REF_INDEX_FIELD_A,
249 MBPARAM_MvertFieldSel_0(mb_param));
250 }
251 }
252
253
254 if (1 == MBPARAM_MotionBackward(mb_param)) {
255 if (second_pred) {
256 if ((1 == MBPARAM_MvertFieldSel_3(mb_param)) &&
257 (PICTURE_CODING_P == ctx->picture_coding_type)) { /* Top field of this frame */
258 REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, INTER_BLOCK_PREDICTION, REF_INDEX_B, ctx->ref_indexA);
259 } else { /* Bottom field of previous frame*/
260 REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, INTER_BLOCK_PREDICTION, REF_INDEX_B, ctx->ref_indexB);
261 }
262
263 REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, INTER_BLOCK_PREDICTION, REF_INDEX_FIELD_B,
264 MBPARAM_MvertFieldSel_3(mb_param));
265 } else {
266 if ((1 == MBPARAM_MvertFieldSel_1(mb_param)) &&
267 (PICTURE_CODING_P == ctx->picture_coding_type)) { /* Top field of this frame */
268 REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, INTER_BLOCK_PREDICTION, REF_INDEX_B, ctx->ref_indexA);
269 } else { /* Bottom field of previous frame*/
270 REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, INTER_BLOCK_PREDICTION, REF_INDEX_B, ctx->ref_indexB);
271 }
272
273 REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, INTER_BLOCK_PREDICTION, REF_INDEX_FIELD_B,
274 MBPARAM_MvertFieldSel_1(mb_param));
275 }
276 }
277 }
278
279 /* Dual Prime */
280 if (3 == MBPARAM_MotionType(mb_param) && (ctx->picture_structure != FRAME_PICTURE)) {
281 if (ctx->picture_structure == TOP_FIELD) {
282 REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, INTER_BLOCK_PREDICTION, REF_INDEX_A, 0);
283 REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, INTER_BLOCK_PREDICTION, REF_INDEX_FIELD_A, 0);
284 REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, INTER_BLOCK_PREDICTION, REF_INDEX_FIELD_B, 1);
285 } else {
286 REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, INTER_BLOCK_PREDICTION, REF_INDEX_A, 1);
287 REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, INTER_BLOCK_PREDICTION, REF_INDEX_FIELD_A, 1);
288 REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, INTER_BLOCK_PREDICTION, REF_INDEX_FIELD_B, 0);
289 }
290 }
291
292 psb_cmdbuf_reg_set(cmdbuf , REGISTER_OFFSET(MSVDX_CMDS, INTER_BLOCK_PREDICTION) + pred_offset, cmd);
293 }
294
295 typedef struct _PSB_MVvalue {
296 short horz;
297 short vert;
298 } psb_MVvalue, *psb_MVvalue_p;
299
300 #define MV_LIBVA2PSB(mb_param) \
301 do { \
302 MVector[0].horz = mb_param->PMV[0][0][0]; \
303 MVector[0].vert = mb_param->PMV[0][0][1]; \
304 \
305 MVector[1].horz = mb_param->PMV[0][1][0]; \
306 MVector[1].vert = mb_param->PMV[0][1][1]; \
307 \
308 MVector[2].horz = mb_param->PMV[1][0][0]; \
309 MVector[2].vert = mb_param->PMV[1][0][1]; \
310 \
311 MVector[3].horz = mb_param->PMV[1][1][0]; \
312 MVector[3].vert = mb_param->PMV[1][1][1]; \
313 } while (0)
314
psb__MPEG2MC_send_motion_vectores(context_MPEG2MC_p const ctx,psb_cmdbuf_p cmdbuf,VAMacroblockParameterBufferMPEG2 * const mb_param)315 static void psb__MPEG2MC_send_motion_vectores(
316 context_MPEG2MC_p const ctx,
317 psb_cmdbuf_p cmdbuf,
318 VAMacroblockParameterBufferMPEG2 * const mb_param
319 )
320 {
321 uint32_t cmd = 0;
322 uint32_t MV1Address = 0;
323 uint32_t MV2Address = 0;
324
325 psb_MVvalue MVector[4];
326
327 MV_LIBVA2PSB(mb_param);
328
329 MV1Address = 0x00;
330 MV2Address = 0x00;
331
332 if (FRAME_PICTURE == ctx->picture_structure) {
333 /* FRAME PICTURE PROCESSING */
334 if (2 == MBPARAM_MotionType(mb_param)) { /* Frame MC */
335 if ((0 == MBPARAM_MotionForward(mb_param)) &&
336 (0 == MBPARAM_MotionBackward(mb_param))) {
337 cmd = 0;
338 REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, MOTION_VECTOR, MV_X, 0);
339 REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, MOTION_VECTOR, MV_Y, 0);
340 psb_cmdbuf_reg_set(cmdbuf , REGISTER_OFFSET(MSVDX_CMDS, MOTION_VECTOR) , cmd);
341 } else {
342 if (1 == MBPARAM_MotionForward(mb_param)) {
343 cmd = 0;
344 REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, MOTION_VECTOR, MV_X, MVector[0].horz << 1);
345 REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, MOTION_VECTOR, MV_Y, MVector[0].vert << 1);
346 psb_cmdbuf_reg_set(cmdbuf , REGISTER_OFFSET(MSVDX_CMDS, MOTION_VECTOR) , cmd);
347 }
348
349 if (1 == MBPARAM_MotionBackward(mb_param)) {
350 cmd = 0;
351 REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, MOTION_VECTOR, MV_X, MVector[1].horz << 1);
352 REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, MOTION_VECTOR, MV_Y, MVector[1].vert << 1);
353 psb_cmdbuf_reg_set(cmdbuf , REGISTER_OFFSET(MSVDX_CMDS, MOTION_VECTOR) + 0x10 , cmd);
354 }
355 }
356 } else {
357 if ((1 == MBPARAM_MotionType(mb_param)) || /* Field MC */
358 (3 == MBPARAM_MotionType(mb_param))) { /* Dual Prime */
359 /*
360 * Vertical motion vectors for fields located in frame pictures
361 * should be divided by 2 (MPEG-2 7.6.3.1). Thus the original value
362 * contained in the stream is equivalent to 1/4-pel format; the
363 * resolution required by MSVDX.
364 */
365 if ((1 == MBPARAM_MotionForward(mb_param)) ||
366 (3 == MBPARAM_MotionType(mb_param))) { /* Dual Prime */
367 cmd = 0;
368 REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, MOTION_VECTOR, MV_X, MVector[0].horz << 1);
369 REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, MOTION_VECTOR, MV_Y, MVector[0].vert);
370 psb_cmdbuf_reg_set(cmdbuf , REGISTER_OFFSET(MSVDX_CMDS, MOTION_VECTOR) , cmd);
371 }
372
373 if ((1 == MBPARAM_MotionBackward(mb_param)) ||
374 (3 == MBPARAM_MotionType(mb_param))) { /* Dual Prime */
375 cmd = 0;
376
377 REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, MOTION_VECTOR, MV_X, MVector[1].horz << 1);
378
379 if (3 == MBPARAM_MotionType(mb_param)) { /* Dual Prime */
380 REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, MOTION_VECTOR, MV_Y, MVector[1].vert << 1);
381 } else {
382 REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, MOTION_VECTOR, MV_Y, MVector[1].vert);
383 }
384 psb_cmdbuf_reg_set(cmdbuf , REGISTER_OFFSET(MSVDX_CMDS, MOTION_VECTOR) + 0x10 , cmd);
385 }
386
387 /* Fields and Dual Prime are 16x8 and need 2nd inter_block_pred cmd */
388 psb__MPEG2MC_send_interPB_prediction(ctx, cmdbuf, mb_param, IMG_TRUE);
389
390 if ((1 == MBPARAM_MotionForward(mb_param)) ||
391 (3 == MBPARAM_MotionType(mb_param))) { /* Dual Prime */
392 cmd = 0;
393 REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, MOTION_VECTOR, MV_X, MVector[2].horz << 1);
394 REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, MOTION_VECTOR, MV_Y, MVector[2].vert);
395 psb_cmdbuf_reg_set(cmdbuf , REGISTER_OFFSET(MSVDX_CMDS, MOTION_VECTOR) + 0x40 , cmd);
396 }
397
398 if ((1 == MBPARAM_MotionBackward(mb_param)) ||
399 (3 == MBPARAM_MotionType(mb_param))) { /* Dual Prime */
400 cmd = 0;
401 REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, MOTION_VECTOR, MV_X, MVector[3].horz << 1);
402 if (3 == MBPARAM_MotionType(mb_param)) { /* Dual Prime */
403 REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, MOTION_VECTOR, MV_Y, MVector[3].vert << 1);
404 } else {
405 REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, MOTION_VECTOR, MV_Y, MVector[3].vert);
406 }
407 psb_cmdbuf_reg_set(cmdbuf , REGISTER_OFFSET(MSVDX_CMDS, MOTION_VECTOR) + 0x50 , cmd);
408 }
409 }
410 }
411 } else {
412 /* FIELD PICTURE PROCESSING */
413 int MV0index = 0, MV1index = 1;
414
415 if ((ctx->picture_structure == BOTTOM_FIELD) && (3 == MBPARAM_MotionType(mb_param))) {
416 MV0index = 1;
417 MV1index = 0;
418 }
419
420 if ((1 == MBPARAM_MotionForward(mb_param)) || /* Forward MV */
421 (3 == MBPARAM_MotionType(mb_param))) { /* Dual Prime */
422 cmd = 0;
423 REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, MOTION_VECTOR, MV_X, MVector[MV0index].horz << 1);
424 REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, MOTION_VECTOR, MV_Y, MVector[MV0index].vert << 1);
425 psb_cmdbuf_reg_set(cmdbuf , REGISTER_OFFSET(MSVDX_CMDS, MOTION_VECTOR) , cmd);
426
427 }
428
429 if ((1 == MBPARAM_MotionBackward(mb_param)) || /* Backward MV */
430 (3 == MBPARAM_MotionType(mb_param))) { /* Dual Prime */
431 cmd = 0;
432 REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, MOTION_VECTOR, MV_X, MVector[MV1index].horz << 1);
433 REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, MOTION_VECTOR, MV_Y, MVector[MV1index].vert << 1);
434 psb_cmdbuf_reg_set(cmdbuf , REGISTER_OFFSET(MSVDX_CMDS, MOTION_VECTOR) + 0x10, cmd);
435 }
436
437 if (2 == MBPARAM_MotionType(mb_param)) { /* 16x8 MC */
438 psb__MPEG2MC_send_interPB_prediction(ctx, cmdbuf, mb_param, IMG_TRUE);
439
440 if ((1 == MBPARAM_MotionForward(mb_param)) || /* Forward MV */
441 (3 == MBPARAM_MotionType(mb_param))) { /* Dual Prime */
442 cmd = 0;
443 REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, MOTION_VECTOR, MV_X, MVector[2].horz << 1);
444 REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, MOTION_VECTOR, MV_Y, MVector[2].vert << 1);
445 psb_cmdbuf_reg_set(cmdbuf , REGISTER_OFFSET(MSVDX_CMDS, MOTION_VECTOR) + 0x40, cmd);
446 }
447
448 if ((1 == MBPARAM_MotionBackward(mb_param)) || /* Backward MV */
449 (3 == MBPARAM_MotionType(mb_param))) { /* Dual Prime */
450 cmd = 0;
451 REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, MOTION_VECTOR, MV_X, MVector[3].horz << 1);
452 REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, MOTION_VECTOR, MV_Y, MVector[3].vert << 1);
453
454 psb_cmdbuf_reg_set(cmdbuf , REGISTER_OFFSET(MSVDX_CMDS, MOTION_VECTOR) + 0x50, cmd);
455 }
456 }
457 }
458 }
459
460
461 /* Send macroblock_number command to MSVDX. */
psb__MPEG2MC_send_mb_number(context_MPEG2MC_p const ctx,psb_cmdbuf_p cmdbuf,const uint32_t mb_addr,const uint32_t motion_type,const eMB_CODE_TYPE MB_coding_type)462 static void psb__MPEG2MC_send_mb_number(
463 context_MPEG2MC_p const ctx,
464 psb_cmdbuf_p cmdbuf,
465 const uint32_t mb_addr,
466 const uint32_t motion_type,
467 const eMB_CODE_TYPE MB_coding_type
468 )
469 {
470 uint32_t cmd;
471 uint32_t mb_x;
472
473 /* 3.3.21. Macroblock Number */
474 cmd = 0;
475
476 REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, MACROBLOCK_NUMBER, MB_ERROR_FLAG, 0);
477
478 /*
479 MB_FIELD_CODE (MC + VDEB): Indicate if the macroblock is field predicted (when = 1),
480 or frame predicted (when VDEB = 0).
481 MPEG2: For Interlaced frame, derived from ‘frame_motion_type’, else same
482 frame/filed type as SLICE_FIELD_TYPE
483
484 */
485 if (FRAME_PICTURE == ctx->picture_structure) {
486 if ((0 == motion_type) ||
487 (2 == motion_type)) {
488 /* MB is frame predicted */
489 REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, MACROBLOCK_NUMBER, MB_FIELD_CODE, 0);
490 } else { /* MB is field predicted */
491 REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, MACROBLOCK_NUMBER, MB_FIELD_CODE, 1);
492 }
493 } else { /* MB is field predicted */
494 REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, MACROBLOCK_NUMBER, MB_FIELD_CODE, 1);
495 }
496
497 ASSERT((0 != ctx->picture_coding_type) && (4 != ctx->picture_coding_type));
498
499 /*
500 MB_CODE_TYPE (MC + VDEB): Indicate macroblock type is I, P, B or MPEG4 S(GMC).
501 0x0: I or SI macroblock
502 0x1: P or SP macroblock
503 0x2: B macroblock
504 0x3: MPEG4 GMC
505 MPEG2: Derived from ‘macroblock_type’
506 */
507 REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, MACROBLOCK_NUMBER, MB_CODE_TYPE, (uint32_t) MB_coding_type);
508
509
510 /*
511 MB_NO_Y (MC + VDEB): Vertical offset of current Macroblock (where 0 = topmost macroblock of picture)
512 Derived from macroblock number divided by picture width in macroblocks.
513 MB_NO_X (MC + VDEB): Horizontal offset of current Macroblock (where 0 = leftmost macroblock of picture)
514 Derived from macroblock number mod picture width in macroblocks.
515 */
516 if ((FRAME_PICTURE != ctx->picture_structure) &&
517 (mb_addr / ctx->picture_width_mb)) {
518 REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, MACROBLOCK_NUMBER, MB_NO_Y, (mb_addr / ctx->picture_width_mb) * 2);
519 } else {
520 REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, MACROBLOCK_NUMBER, MB_NO_Y, mb_addr / ctx->picture_width_mb);
521 }
522
523 mb_x = mb_addr % ctx->picture_width_mb;
524 REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, MACROBLOCK_NUMBER, MB_NO_X, mb_x);
525 /*
526 Only defined for current MB, set to 0 for above1 and above2.
527 Indicate if MB is on Left Hand Side of slice or picture
528 0: MB is not on left hand side of slice or picture
529 1: MB is on left hand side of slice or picture
530 */
531 REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, MACROBLOCK_NUMBER , MB_SLICE_LHS, ctx->fstmb_slice || (mb_x == 0));
532 REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, MACROBLOCK_NUMBER , MB_SLICE_TOP, 1);
533
534 psb_cmdbuf_reg_set(cmdbuf, REGISTER_OFFSET(MSVDX_CMDS, MACROBLOCK_NUMBER) , cmd);
535 }
536
psb__MPEG2MC_finalise_residDMA(context_MPEG2MC_p const ctx)537 static void psb__MPEG2MC_finalise_residDMA(
538 context_MPEG2MC_p const ctx
539 )
540 {
541 uint32_t *save_idx = ctx->obj_context->cmdbuf->cmd_idx;
542 ctx->obj_context->cmdbuf->cmd_idx = ctx->lldma_idx;
543 if (ctx->residual_pendingDMA) {
544 #if 0
545 if (ctx->residual_pendingDMA != (ctx->blk_size * ctx->blk_in_buffer)) {
546 drv_debug_msg(VIDEO_DEBUG_ERROR, "psb__MPEG2MC_finalise_residDMA:residual_pendingDMA=%d(block:%d),"
547 "actual data size=%d (block:%d)\n",
548 ctx->residual_pendingDMA, ctx->residual_pendingDMA / ctx->blk_size,
549 ctx->blk_size * ctx->blk_in_buffer,
550 ctx->blk_in_buffer);
551 }
552 #endif
553
554 psb_cmdbuf_lldma_write_cmdbuf(ctx->obj_context->cmdbuf,
555 ctx->residual_buf,
556 ctx->residual_sent,
557 ctx->residual_pendingDMA,
558 0,
559 LLDMA_TYPE_RESIDUAL);
560 } else {
561 //*ctx->obj_context->cmdbuf->cmd_idx = CMD_NOP;
562 *ctx->obj_context->cmdbuf->cmd_idx = 0xf000000;
563 }
564 ctx->obj_context->cmdbuf->cmd_idx = save_idx;
565 ctx->residual_sent += ctx->residual_pendingDMA;
566 ctx->residual_pendingDMA = 0;
567 }
568
psb__MPEG2MC_check_segment_residDMA(context_MPEG2MC_p const ctx,uint32_t min_space)569 static void psb__MPEG2MC_check_segment_residDMA(
570 context_MPEG2MC_p const ctx,
571 uint32_t min_space
572 )
573 {
574 if (psb_cmdbuf_segment_space(ctx->obj_context->cmdbuf) < min_space) {
575 psb__MPEG2MC_finalise_residDMA(ctx);
576
577 psb_cmdbuf_next_segment(ctx->obj_context->cmdbuf);
578
579 ctx->lldma_idx = ctx->obj_context->cmdbuf->cmd_idx++; /* Insert the LLDMA record here later */
580 }
581 }
582
583
584 /* Send residual difference data to MSVDX. */
psb__MPEG2MC_send_residual(context_MPEG2MC_p ctx,uint32_t pattern_code)585 static void psb__MPEG2MC_send_residual(
586 context_MPEG2MC_p ctx,
587 uint32_t pattern_code)
588 {
589 uint8_t pattern_code_byte = (uint8_t)(pattern_code >> 6);
590 uint8_t blocks = 0;
591
592 while (pattern_code_byte) {
593 blocks += (pattern_code_byte & 1);
594 pattern_code_byte >>= 1;
595 }
596
597 if (PICTURE_CODING_I == ctx->picture_coding_type) {
598 ctx->residual_pendingDMA += blocks * (8 * 8); /* 8bit */
599 } else {
600 /* We do not suport ConfigSpatialResid8==1 */
601 /* ASSERT(ConfigSpatialResid8 == 0); */
602 ctx->residual_pendingDMA += blocks * (8 * 8) * 2;/* 16 bit */
603 }
604 }
605
606
psb__MPEG2MC_send_slice_parameters(context_MPEG2MC_p const ctx)607 static void psb__MPEG2MC_send_slice_parameters(
608 context_MPEG2MC_p const ctx
609 )
610 {
611 psb_cmdbuf_p cmdbuf = ctx->obj_context->cmdbuf;
612 uint32_t cmd;
613
614 ctx->lldma_idx = ctx->obj_context->cmdbuf->cmd_idx++; /* Insert the LLDMA record here later */
615
616 psb_cmdbuf_reg_start_block(cmdbuf, 0);
617
618 /* 3.3.19. Slice Params*/
619 /*
620 3:2 SLICE_FIELD_TYPE (MC+VDEB) Indicate if slice is a frame, top fie
621 0x0: Top field picture
622 0x1: Bottom field picture
623 0x2: Frame picture
624 1:0 SLICE_CODE_TYPE (MC+VDEB) Indicate if it is an I, P, B slice
625 0x0: I slice
626 0x1: P slice
627 0x2: B slice
628 0x3: S(GMC) (MPEG4 only)
629 */
630 cmd = 0;
631 REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, SLICE_PARAMS, SLICE_FIELD_TYPE,
632 ft_libva2msvdx[ctx->picture_structure]);
633 REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, SLICE_PARAMS, SLICE_CODE_TYPE,
634 pict_libva2msvdx[ctx->picture_coding_type]);
635 psb_cmdbuf_reg_set(cmdbuf , REGISTER_OFFSET(MSVDX_CMDS, SLICE_PARAMS), cmd);
636
637 psb_cmdbuf_reg_end_block(cmdbuf);
638 }
639
psb__MPEG2MC_send_slice_picture_endcommand(context_MPEG2MC_p const ctx,int end_picture)640 static void psb__MPEG2MC_send_slice_picture_endcommand(
641 context_MPEG2MC_p const ctx,
642 int end_picture
643 )
644 {
645 psb_cmdbuf_p cmdbuf = ctx->obj_context->cmdbuf;
646 uint32_t cmd;
647
648 /*
649 3.3.22. End Slice/Picture
650 Offset: 0x0404
651 This command is sent at the end of a slice or picture. The final macroblock of slice/picture will not be
652 processed until this command is sent. The End Slice/Picture commands can be sent more than once
653 at the end of a slice (provided no other commands are interleaved).
654 If the command is sent more than once at the end of a slice, the first command should indicate the
655 end of the slice (no data bits set) with repeat commands used to indicate end of slice, flushing VDEB
656 buffers or picture end. The FLUSH_VDEB_BUFFERS bit should not be set in any repeat commands
657 sent after a command in which the PICTURE_END bit is set.
658 31:2 - Reserved
659 1 FLUSH_VDEB_BUFFERS(VDEB) If set, indicates VDEB should flush its internal buffers to system memory
660 when slice processing is complete
661 0 PICTURE_END(MC + VDEB) If set, indicates both Picture and Slice end, otherwise Slice end
662 */
663 psb_cmdbuf_reg_start_block(cmdbuf, 0);
664
665 psb_cmdbuf_reg_set(cmdbuf , REGISTER_OFFSET(MSVDX_CMDS, END_SLICE_PICTURE), 0);
666
667 if (end_picture) {
668 cmd = 0;
669 REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, END_SLICE_PICTURE, PICTURE_END, end_picture);
670 psb_cmdbuf_reg_set(cmdbuf, REGISTER_OFFSET(MSVDX_CMDS, END_SLICE_PICTURE), cmd);
671 }
672
673 psb_cmdbuf_reg_end_block(cmdbuf);
674 }
675
psb__MPEG2MC_send_highlevel_commands(context_MPEG2MC_p const ctx)676 static void psb__MPEG2MC_send_highlevel_commands(
677 context_MPEG2MC_p const ctx
678 )
679 {
680 psb_cmdbuf_p cmdbuf = ctx->obj_context->cmdbuf;
681 psb_surface_p target_surface = ctx->obj_context->current_render_target->psb_surface;
682
683 psb_cmdbuf_reg_start_block(cmdbuf, 0);
684
685 /* 3.3.1. Display Picture Size */
686 psb_cmdbuf_reg_set(cmdbuf , REGISTER_OFFSET(MSVDX_CMDS, DISPLAY_PICTURE_SIZE), ctx->display_picture_size);
687
688 /* 3.3.2. Coded Picture Size*/
689 psb_cmdbuf_reg_set(cmdbuf , REGISTER_OFFSET(MSVDX_CMDS, CODED_PICTURE_SIZE), ctx->coded_picture_size);
690
691 /* 3.3.3. Operating Mode */
692 psb_cmdbuf_reg_set(cmdbuf , REGISTER_OFFSET(MSVDX_CMDS, OPERATING_MODE), ctx->obj_context->operating_mode);
693
694 /* 3.3.4. Luma Reconstructed Picture Base Address */
695 psb_cmdbuf_reg_set_RELOC(cmdbuf , REGISTER_OFFSET(MSVDX_CMDS, LUMA_RECONSTRUCTED_PICTURE_BASE_ADDRESSES),
696 &target_surface->buf, 0);
697
698 /* 3.3.5. Chroma Reconstructed Picture Base Address */
699 psb_cmdbuf_reg_set_RELOC(cmdbuf , REGISTER_OFFSET(MSVDX_CMDS, CHROMA_RECONSTRUCTED_PICTURE_BASE_ADDRESSES),
700 &target_surface->buf, target_surface->chroma_offset);
701
702 /* 3.3.13. Reference Picture Base Addresses */
703 /*
704 Reference Picture Base Addresses
705 Offset: 0x0100 + N*8 = Luma base addresses
706 Offset: 0x0104 + N*8 = Chroma base addresses
707 This register can store up to 16 luma picture base addresses and 16 chroma picture base addresses.
708 Luma and chroma ref base registers are interleaved.
709
710 Bit Symbol Used Description
711 31:12 LUMA_REF_BASE_ADDR MC Luma picture base byte address [31:12]
712 11:0 - Reserved
713 Bit Symbol Used Description
714 31:12 CHROMA_REF_BASE_ADDR MC Chroma picture base byte address [31:12]
715 11:0 - Reserved
716 - In MPEG2, the registers at N=0 are always used to store the base address of the luma and
717 chroma buffers of the most recently decoded reference picture. The registers at N=1 are used
718 to store the base address of the luma and chroma buffers of the older reference picture, if
719 more than one reference picture is used. This means that when decoding a P picture the
720 forward reference picture’s address is at index 0. When decoding a B-picture the backward
721 reference picture’s address is at index 0 and the address of the forward reference picture –
722 which was decoded earlier than the backward reference – is at index 1.
723 */
724
725 /* WABA: backward / forward refs are always set, even when they aren't strictly needed */
726 psb_surface_p forward_surface = ctx->forward_ref_surface->psb_surface;
727 psb_surface_p backward_surface = ctx->backward_ref_surface->psb_surface;
728
729 if (backward_surface) {
730 psb_cmdbuf_reg_set_RELOC(cmdbuf , REGISTER_OFFSET(MSVDX_CMDS, REFERENCE_PICTURE_BASE_ADDRESSES) + (0 * 8),
731 &backward_surface->buf, 0);
732
733 psb_cmdbuf_reg_set_RELOC(cmdbuf , REGISTER_OFFSET(MSVDX_CMDS, REFERENCE_PICTURE_BASE_ADDRESSES) + 4 + (0 * 8),
734 &backward_surface->buf, backward_surface->chroma_offset);
735 }
736 if (forward_surface) {
737 psb_cmdbuf_reg_set_RELOC(cmdbuf , REGISTER_OFFSET(MSVDX_CMDS, REFERENCE_PICTURE_BASE_ADDRESSES) + (1 * 8),
738 &forward_surface->buf, 0);
739
740 psb_cmdbuf_reg_set_RELOC(cmdbuf , REGISTER_OFFSET(MSVDX_CMDS, REFERENCE_PICTURE_BASE_ADDRESSES) + 4 + (1 * 8),
741 &forward_surface->buf, forward_surface->chroma_offset);
742 }
743
744 /*
745 * VDMC_RESIDUAL_DIRECT_INSERT_CONTROL, spec p 159
746 * 0 VDMC_RESIDUAL_DIRECT_CONTROL (VDMC) residual direct insert control.
747 * Control insertion of spatial residual data. When set to 1 residual
748 * data taken from writes to VDMC_RESIDUAL_DIRECT_INSERT_DATA
749 * when set to 0, residual data taken from vEC
750 */
751 psb_cmdbuf_reg_set(cmdbuf , REGISTER_OFFSET(MSVDX_VDMC, CR_VDMC_RESIDUAL_DIRECT_INSERT_CONTROL), 1);
752
753 psb_cmdbuf_reg_end_block(cmdbuf);
754 }
755
756
757
758 /* Control building of the MSVDX command buffer for a B and P pictures.*/
psb__MPEG2MC_interPB_mb(context_MPEG2MC_p const ctx,VAMacroblockParameterBufferMPEG2 * const mb_param)759 static void psb__MPEG2MC_interPB_mb(
760 context_MPEG2MC_p const ctx,
761 VAMacroblockParameterBufferMPEG2 * const mb_param
762 )
763 {
764 psb_cmdbuf_p cmdbuf = ctx->obj_context->cmdbuf;
765 uint32_t cmd;
766
767 psb_cmdbuf_reg_start_block(cmdbuf, 0);
768
769 /* 3.3.21. Macroblock Number */
770 psb__MPEG2MC_send_mb_number(ctx, cmdbuf, mb_param->macroblock_address, MBPARAM_MotionType(mb_param),
771 MBPARAM_IntraMacroblock(mb_param) ? MB_CODE_TYPE_I : pict_libva2msvdx[ctx->picture_coding_type]
772 );
773
774 cmd = 0;
775 /* Only used for direct insert of residual data;-
776 00 = 8-bit signed data
777 01 = 8-bit unsigned data
778 10 = 16-bit signed
779 11 = Reserved
780 */
781 /* TODO:: ASSERT(ConfigSpatialResid8==0 ); */
782 if (MBPARAM_IntraMacroblock(mb_param)) {
783 if (1/* TODO:: ConfigIntraResidUnsigned == 0 */) {
784 /* sent as as 16 bit signed relative to 128*/
785 REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, MACROBLOCK_RESIDUAL_FORMAT, VA_ADD_128, 1);
786 REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, MACROBLOCK_RESIDUAL_FORMAT, VA_DATA_FORMAT, 2);
787 } else { /* ConfigIntraResidUnsigned == 1 */
788 /* 16 bit unsigned unsigned relative to 0*/
789 REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, MACROBLOCK_RESIDUAL_FORMAT, VA_ADD_128, 0);
790 REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, MACROBLOCK_RESIDUAL_FORMAT, VA_DATA_FORMAT, 2);
791 }
792 } else {
793 /* For non-intra in Inter frames : 16 bit signed */
794 REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, MACROBLOCK_RESIDUAL_FORMAT, VA_ADD_128, 0);
795 REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, MACROBLOCK_RESIDUAL_FORMAT, VA_DATA_FORMAT, 2);
796 }
797
798
799 if (FRAME_PICTURE == ctx->picture_structure) {
800 /* mb_param->macroblock_modes.bits.dct_type =1: field DCT */
801 REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, MACROBLOCK_RESIDUAL_FORMAT, RESIDUAL_FIELD_CODED, mb_param->macroblock_modes.bits.dct_type ? 1 : 0);
802 } else {
803 REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, MACROBLOCK_RESIDUAL_FORMAT, RESIDUAL_FIELD_CODED, 1);
804 }
805
806 REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, MACROBLOCK_RESIDUAL_FORMAT, CR_FROM_VEC,
807 ((MBPARAM_CodedBlockPattern(mb_param) & 0x40) ? 1 : 0));
808 REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, MACROBLOCK_RESIDUAL_FORMAT, CB_FROM_VEC,
809 ((MBPARAM_CodedBlockPattern(mb_param) & 0x80) ? 1 : 0));
810 REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, MACROBLOCK_RESIDUAL_FORMAT, Y3_FROM_VEC,
811 ((MBPARAM_CodedBlockPattern(mb_param) & 0x100) ? 1 : 0));
812 REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, MACROBLOCK_RESIDUAL_FORMAT, Y2_FROM_VEC,
813 ((MBPARAM_CodedBlockPattern(mb_param) & 0x200) ? 1 : 0));
814 REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, MACROBLOCK_RESIDUAL_FORMAT, Y1_FROM_VEC,
815 ((MBPARAM_CodedBlockPattern(mb_param) & 0x400) ? 1 : 0));
816 REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, MACROBLOCK_RESIDUAL_FORMAT, Y0_FROM_VEC,
817 ((MBPARAM_CodedBlockPattern(mb_param) & 0x800) ? 1 : 0));
818 psb_cmdbuf_reg_set(cmdbuf, REGISTER_OFFSET(MSVDX_CMDS, MACROBLOCK_RESIDUAL_FORMAT) , cmd);
819
820 /* Send Residuals */
821 if (MBPARAM_IntraMacroblock(mb_param)) {
822 cmd = 0;
823 REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, INTRA_BLOCK_PREDICTION, INTRA_PRED_MODE0, 0);
824 REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, INTRA_BLOCK_PREDICTION, INTRA_PRED_MODE1, 0);
825 REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, INTRA_BLOCK_PREDICTION, INTRA_PRED_MODE2, 0);
826 REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, INTRA_BLOCK_PREDICTION, INTRA_PRED_MODE3, 0);
827 psb_cmdbuf_reg_set(cmdbuf, REGISTER_OFFSET(MSVDX_CMDS, INTRA_BLOCK_PREDICTION) , cmd);
828
829 psb__MPEG2MC_send_residual(ctx, MBPARAM_CodedBlockPattern(mb_param));
830 } else {
831 psb__MPEG2MC_send_interPB_prediction(ctx, cmdbuf, mb_param, IMG_FALSE);
832
833 /* Send motion vectors */
834 psb__MPEG2MC_send_motion_vectores(ctx, cmdbuf, mb_param);
835
836 psb__MPEG2MC_send_residual(ctx, MBPARAM_CodedBlockPattern(mb_param));
837 }
838
839 psb_cmdbuf_reg_end_block(cmdbuf);
840 }
841
842
843
844 /* Process Macroblocks of a B or P picture.*/
psb__MPEG2MC_process_mbs_interPB(context_MPEG2MC_p const ctx)845 static VAStatus psb__MPEG2MC_process_mbs_interPB(
846 context_MPEG2MC_p const ctx
847 )
848 {
849 uint32_t skip_count = 0;
850 VAMacroblockParameterBufferMPEG2 *mb_param = NULL;
851 VAMacroblockParameterBufferMPEG2 mbparam_skip;
852
853 uint32_t mb_pending = ctx->mb_in_buffer;
854 uint32_t mb_addr = ctx->mb_first_addr;
855 uint32_t mb_last = mb_addr + mb_pending;
856 mb_param = (VAMacroblockParameterBufferMPEG2 *) ctx->mb_param;
857
858 /* Proccess all VA_MBctrl_P_HostResidDiff_1 structure in the buffer
859 * - this may genererate more macroblocks due to skipped
860 */
861 while (mb_pending || skip_count) {
862 uint32_t mb_in_buffer = (ctx->picture_width_mb);
863 psb_cmdbuf_p cmdbuf;
864 unsigned char *cmd_start;
865
866 ctx->fstmb_slice = IMG_TRUE;
867
868 psb_context_get_next_cmdbuf(ctx->obj_context);
869 cmdbuf = ctx->obj_context->cmdbuf;
870 cmd_start = (unsigned char *) cmdbuf->cmd_idx;
871
872 /* Build the high-level commands */
873 psb__MPEG2MC_send_highlevel_commands(ctx);
874
875 psb__MPEG2MC_send_slice_parameters(ctx);
876
877 /* Process all the macroblocks in the slice */
878 while ((mb_pending || skip_count) && mb_in_buffer--) {
879 /* Check for segment space - do we have space for at least one more
880 * worst case InterMB plus completion
881 */
882 psb__MPEG2MC_check_segment_residDMA(ctx, INTER_MB_WORST_CASE + 2);
883
884 if (skip_count) { /* Skipped macroblock processing */
885 mbparam_skip.macroblock_address++;
886
887 ASSERT(mb_param->macroblock_address < ctx->size_mb);
888 ASSERT(mbparam_skip.macroblock_address == mb_addr);
889
890 psb__MPEG2MC_interPB_mb(ctx, &mbparam_skip);
891
892 skip_count--;
893 } else {
894 ASSERT(mb_pending);
895 ASSERT(mb_param->macroblock_address < ctx->size_mb);
896 ASSERT(mb_param->macroblock_address == mb_addr);
897
898 psb__MPEG2MC_interPB_mb(ctx, mb_param);
899
900 skip_count = MBPARAM_MBskipsFollowing(mb_param);
901 if (skip_count) {
902 memcpy(&mbparam_skip, mb_param, sizeof(mbparam_skip));
903 }
904
905 mb_param++;
906 mb_pending--;
907 }
908
909 ctx->fstmb_slice = IMG_FALSE;
910
911 mb_addr++;
912 }
913
914 /* Tell hardware we're done */
915 psb__MPEG2MC_send_slice_picture_endcommand(ctx, (mb_pending == 0) && (skip_count == 0) && (ctx->size_mb == mb_last));
916 psb__MPEG2MC_finalise_residDMA(ctx);
917
918 /* write_kick */
919 *cmdbuf->cmd_idx++ = CMD_COMPLETION;
920
921 ctx->obj_context->video_op = psb_video_mc;
922 ctx->obj_context->flags = (mb_pending == 0) && (skip_count == 0) && (ctx->size_mb == mb_last) ? FW_VA_RENDER_IS_LAST_SLICE : 0;
923 ctx->obj_context->first_mb = 0;
924 ctx->obj_context->last_mb = 0;
925 psb_context_submit_cmdbuf(ctx->obj_context);
926
927 /* check if the remained cmdbuf size can fill the commands of next slice */
928 if (1 || (cmdbuf->lldma_base - (unsigned char *) cmdbuf->cmd_idx) < ((unsigned char *) cmdbuf->cmd_idx - cmd_start))
929 psb_context_flush_cmdbuf(ctx->obj_context);
930 }
931
932 return VA_STATUS_SUCCESS;
933 }
934
935
psb__MPEG2MC_intra_mb(context_MPEG2MC_p const ctx,const VAMacroblockParameterBufferMPEG2 * const mb_param)936 static void psb__MPEG2MC_intra_mb(
937 context_MPEG2MC_p const ctx,
938 const VAMacroblockParameterBufferMPEG2* const mb_param
939 )
940 {
941 psb_cmdbuf_p cmdbuf = ctx->obj_context->cmdbuf;
942 uint32_t cmd;
943
944 psb_cmdbuf_reg_start_block(cmdbuf, 0);
945
946 /* 3.3.21. Macroblock Number */
947 psb__MPEG2MC_send_mb_number(ctx, cmdbuf, mb_param->macroblock_address, MBPARAM_MotionType(mb_param), MB_CODE_TYPE_I);
948
949 /*3.3.25. Macroblock Residual Format */
950 cmd = 0;
951
952 /* In INTRA pictures, spatial-blocks are always 8bit when BBP is 8 */
953 /* 00 = 8-bit signed data
954 * 01 = 8-bit unsigned data
955 */
956 if (1/* TODO:: ConfigIntraResidUnsigned==0 */) {
957 /* spec p67:
958 * VA_ADD_128 MC Only used for direct insert of residual data;-
959 * 0: add 0 to residual data input
960 * 1: indicates 128 should be added to residual data input
961 *
962 * VA_DATA_FORMAT:Only used for direct insert of residual data;-
963 * 0x0: 8-bit signed data
964 * 0x1: 8-bit unsigned data
965 * 0x2: 16-bit signed
966 */
967 /* Sent as 8 bit signed relative to 128 */
968 REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, MACROBLOCK_RESIDUAL_FORMAT, VA_DATA_FORMAT, 0); /* ok ish */
969 REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, MACROBLOCK_RESIDUAL_FORMAT, VA_ADD_128, 1); /* ok ish */
970 } else {
971 /* Sent as 8 bit unsigned relative to 0 */
972 REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, MACROBLOCK_RESIDUAL_FORMAT, VA_DATA_FORMAT, 1);
973 REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, MACROBLOCK_RESIDUAL_FORMAT, VA_ADD_128, 0);
974 }
975
976 if (FRAME_PICTURE == ctx->picture_structure) {
977 /*
978 * RESIDUAL_FIELD_CODED MC
979 * 0: residual data frame coded
980 * 1: (luma)residual data field coded
981 * N.B. For VC1, MPEG4 and MPEG2, if SLICE_FIELD_TYPE =
982 * frame, chroma residual will be frame coded, even if the luma
983 * residual is field coded.
984 */
985 /*
986 * (VA:wMBType bit 5: FieldResidual, wMBtype & 0x20)/libVA(dct_type:1 field DCT):
987 * Indicates whether the residual difference blocks use a field IDCT structure as specified in MPEG-2.
988 *
989 * Must be 1 if the bPicStructure member of VA_PictureParameters is 1 or 2. When used for MPEG-2,
990 * FieldResidual must be zero if the frame_pred_frame_DCT variable in the MPEG-2 syntax is 1, and
991 * must be equal to the dct_type variable in the MPEG-2 syntax if dct_type is present for the macroblock.
992 */
993 REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, MACROBLOCK_RESIDUAL_FORMAT,
994 RESIDUAL_FIELD_CODED, ((mb_param->macroblock_modes.bits.dct_type) ? 1 : 0));
995 } else {
996 REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, MACROBLOCK_RESIDUAL_FORMAT, RESIDUAL_FIELD_CODED, 1);
997 }
998
999 /* CR_FROM_VEC MC 0: constant zero residual
1000 1: block Cr provided by VEC
1001 (If REVERSE_FLAG_ORDER=1, this bit indicates if Y0 provided)
1002 CB_FROM_VEC MC 0: constant zero residual
1003 1: block Cb provided by VEC
1004 (If REVERSE_FLAG_ORDER=1, this bit indicates if Y1 provided)
1005 Y3_FROM_VEC MC 0: constant zero residual
1006 1: block Y3 provided by VEC
1007 (If REVERSE_FLAG_ORDER=1, this bit indicates if Y2 provided)
1008 Y2_FROM_VEC MC 0: constant zero residual
1009 1: block Y2 provided by VEC
1010 (If REVERSE_FLAG_ORDER=1, this bit indicates if Y3 provided)
1011 Y1_FROM_VEC MC 0: constant zero residual
1012 1: block Y1 provided by VEC
1013 (If REVERSE_FLAG_ORDER=1, this bit indicates if Cb provided)
1014 Y0_FROM_VEC MC 0: constant zero residual
1015 1: block Y0 provided by VEC
1016 (If REVERSE_FLAG_ORDER=1, this bit indicates if Cr provided)
1017 */
1018 REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, MACROBLOCK_RESIDUAL_FORMAT, CR_FROM_VEC,
1019 ((MBPARAM_CodedBlockPattern(mb_param) & 0x40) ? 1 : 0));
1020 REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, MACROBLOCK_RESIDUAL_FORMAT, CB_FROM_VEC,
1021 ((MBPARAM_CodedBlockPattern(mb_param) & 0x80) ? 1 : 0));
1022 REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, MACROBLOCK_RESIDUAL_FORMAT, Y3_FROM_VEC,
1023 ((MBPARAM_CodedBlockPattern(mb_param) & 0x100) ? 1 : 0));
1024 REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, MACROBLOCK_RESIDUAL_FORMAT, Y2_FROM_VEC,
1025 ((MBPARAM_CodedBlockPattern(mb_param) & 0x200) ? 1 : 0));
1026 REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, MACROBLOCK_RESIDUAL_FORMAT, Y1_FROM_VEC,
1027 ((MBPARAM_CodedBlockPattern(mb_param) & 0x400) ? 1 : 0));
1028 REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, MACROBLOCK_RESIDUAL_FORMAT, Y0_FROM_VEC,
1029 ((MBPARAM_CodedBlockPattern(mb_param) & 0x800) ? 1 : 0));
1030 psb_cmdbuf_reg_set(cmdbuf, REGISTER_OFFSET(MSVDX_CMDS, MACROBLOCK_RESIDUAL_FORMAT) , cmd);
1031
1032 /* Send Residuals, spec p69,h264 only */
1033 cmd = 0;
1034 REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, INTRA_BLOCK_PREDICTION, INTRA_PRED_MODE0, 0);
1035 REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, INTRA_BLOCK_PREDICTION, INTRA_PRED_MODE1, 0);
1036 REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, INTRA_BLOCK_PREDICTION, INTRA_PRED_MODE2, 0);
1037 REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, INTRA_BLOCK_PREDICTION, INTRA_PRED_MODE3, 0);
1038 psb_cmdbuf_reg_set(cmdbuf, REGISTER_OFFSET(MSVDX_CMDS, INTRA_BLOCK_PREDICTION) , cmd);
1039
1040 psb__MPEG2MC_send_residual(ctx, MBPARAM_CodedBlockPattern(mb_param));
1041
1042 psb_cmdbuf_reg_end_block(cmdbuf);
1043 }
1044
1045
psb__MPEG2MC_process_mbs_intra(context_MPEG2MC_p const ctx)1046 static VAStatus psb__MPEG2MC_process_mbs_intra(
1047 context_MPEG2MC_p const ctx
1048 )
1049 {
1050 const VAMacroblockParameterBufferMPEG2* mb_param = NULL;
1051 uint32_t mb_pending = ctx->mb_in_buffer;
1052 uint32_t mb_addr = ctx->mb_first_addr;
1053 uint32_t mb_last = mb_addr + mb_pending;
1054
1055 mb_param = (VAMacroblockParameterBufferMPEG2*) ctx->mb_param;
1056
1057 while (mb_pending) { /* one slice per loop */
1058 uint32_t mb_in_buffer = min(mb_pending, ctx->picture_width_mb);
1059 psb_cmdbuf_p cmdbuf;
1060 unsigned char *cmd_start;
1061
1062 mb_pending -= mb_in_buffer;
1063
1064 psb_context_get_next_cmdbuf(ctx->obj_context);
1065 cmdbuf = ctx->obj_context->cmdbuf;
1066 cmd_start = (unsigned char *) cmdbuf->cmd_idx;
1067
1068 ctx->fstmb_slice = IMG_TRUE;
1069
1070 /* Build the high-level commands */
1071 psb__MPEG2MC_send_highlevel_commands(ctx);
1072
1073 psb__MPEG2MC_send_slice_parameters(ctx);
1074
1075 /* Process all the macroblocks in the slice */
1076 while (mb_in_buffer--) { /* for every MB */
1077 ASSERT(mb_param->macroblock_address < ctx->size_mb);
1078 ASSERT(mb_param->macroblock_address == mb_addr);
1079
1080 /* Check for segment space - do we have space for at least one more
1081 * worst case IntraMB plus completion
1082 */
1083 psb__MPEG2MC_check_segment_residDMA(ctx, INTRA_MB_WORST_CASE + 2);
1084
1085 psb__MPEG2MC_intra_mb(ctx, mb_param);
1086
1087 mb_param++; /* next macroblock parameter */
1088 mb_addr++;
1089
1090 ctx->fstmb_slice = IMG_FALSE;
1091 }
1092
1093 psb__MPEG2MC_send_slice_picture_endcommand(ctx, (mb_pending == 0) && (ctx->size_mb == mb_last)); /* Tell hardware we're done */
1094
1095 psb__MPEG2MC_finalise_residDMA(ctx);
1096
1097 /* write_kick */
1098 *cmdbuf->cmd_idx++ = CMD_COMPLETION;
1099
1100 ctx->obj_context->video_op = psb_video_mc;
1101 ctx->obj_context->flags = (mb_pending == 0) && (ctx->size_mb == mb_last) ? FW_VA_RENDER_IS_LAST_SLICE : 0;
1102 ctx->obj_context->first_mb = 0;
1103 ctx->obj_context->last_mb = 0;
1104 psb_context_submit_cmdbuf(ctx->obj_context);
1105
1106 /* check if the remained cmdbuf size can fill the commands of next slice */
1107 if (1 || (cmdbuf->lldma_base - (unsigned char *) cmdbuf->cmd_idx) < ((unsigned char *) cmdbuf->cmd_idx - cmd_start))
1108 psb_context_flush_cmdbuf(ctx->obj_context);
1109 }
1110
1111 //ASSERT(ctx->residual_bytes == 0); /* There should be no more data left */
1112
1113 return VA_STATUS_SUCCESS;
1114 }
1115
1116
psb__MPEG2MC_process_picture_param(context_MPEG2MC_p ctx,object_buffer_p obj_buffer)1117 static VAStatus psb__MPEG2MC_process_picture_param(context_MPEG2MC_p ctx, object_buffer_p obj_buffer)
1118 {
1119 int coded_pic_height;
1120
1121 /* Take a copy of the picture parameters */
1122 ctx->pic_params = (VAPictureParameterBufferMPEG2 *) obj_buffer->buffer_data;
1123 obj_buffer->buffer_data = NULL;
1124 obj_buffer->size = 0;
1125
1126 ctx->picture_coding_type = ctx->pic_params->picture_coding_type;
1127 ctx->picture_structure = ctx->pic_params->picture_coding_extension.bits.picture_structure;
1128
1129 ctx->forward_ref_surface = SURFACE(ctx->pic_params->forward_reference_picture);
1130 ctx->backward_ref_surface = SURFACE(ctx->pic_params->backward_reference_picture);
1131
1132 /* Set picture type and reference indices for reference frames */
1133 if (ctx->picture_coding_type != PICTURE_CODING_I) {
1134 if (ctx->pic_params->picture_coding_extension.bits.is_first_field) { /* first field */
1135 if (ctx->backward_ref_surface) {
1136 ctx->picture_coding_type = PICTURE_CODING_B;
1137 ctx->ref_indexA = 0x01;/* Forward reference frame*/
1138 ctx->ref_indexB = 0x00;/* Backward reference frame*/
1139 } else {
1140 ctx->picture_coding_type = PICTURE_CODING_P;
1141 ctx->ref_indexA = 0x00; /* Always reference frame 0*/
1142 }
1143 } else {
1144 if ((PICTURE_CODING_B == ctx->picture_coding_type) && (ctx->backward_ref_surface)) {
1145 ctx->picture_coding_type = PICTURE_CODING_B;
1146 ctx->ref_indexA = 0x01; /* Forward reference frame*/
1147 ctx->ref_indexB = 0x00;/* Backward reference frame */
1148 } else {
1149 ctx->picture_coding_type = PICTURE_CODING_P;
1150 if (ctx->forward_ref_surface) {
1151 ctx->ref_indexA = 0x00;
1152 } else {
1153 ctx->ref_indexA = 0x01;
1154 ctx->ref_indexB = 0x00;
1155 }
1156 }
1157 }
1158 }
1159 ctx->pic_params->picture_coding_type = ctx->picture_coding_type;
1160
1161 /* residual data size per element */
1162 if (ctx->picture_coding_type == PICTURE_CODING_I) {
1163 ctx->blk_size = 64; /* unsigned char */
1164 } else {
1165 ctx->blk_size = 2 * 64; /* unsigned short */
1166 }
1167
1168 if (ctx->picture_coding_type != PICTURE_CODING_I) {
1169 if (ctx->backward_ref_surface) {
1170 if (ctx->forward_ref_surface == NULL)
1171 ctx->forward_ref_surface = ctx->backward_ref_surface;
1172 } else {
1173 ctx->backward_ref_surface = ctx->forward_ref_surface;
1174 }
1175 }
1176 if (NULL == ctx->backward_ref_surface) {
1177 ctx->backward_ref_surface = ctx->obj_context->current_render_target;
1178 }
1179 if (NULL == ctx->forward_ref_surface) {
1180 ctx->forward_ref_surface = ctx->obj_context->current_render_target;
1181 }
1182
1183 ctx->coded_picture_width = ctx->pic_params->horizontal_size;
1184 ctx->coded_picture_height = ctx->pic_params->vertical_size;
1185 ctx->picture_width_mb = ctx->pic_params->horizontal_size / 16;
1186 if (ctx->pic_params->picture_coding_extension.bits.progressive_frame == 1) /* should be progressive_sequence? */
1187 ctx->picture_height_mb = (ctx->coded_picture_height + 15) / 16;
1188 else {
1189 if (FRAME_PICTURE != ctx->picture_structure) { /*Interlaced Field Pictures */
1190 ctx->picture_height_mb = ((ctx->coded_picture_height + 31) / 32);
1191 } else {
1192 ctx->picture_height_mb = 2 * ((ctx->coded_picture_height + 31) / 32);
1193 }
1194 }
1195 coded_pic_height = (ctx->picture_structure != FRAME_PICTURE) ?
1196 ((ctx->picture_height_mb) * 32) : ((ctx->picture_height_mb) * 16);
1197 ctx->size_mb = ctx->picture_width_mb * (coded_pic_height >> 4);
1198
1199 ctx->display_picture_size = 0;
1200 REGIO_WRITE_FIELD_LITE(ctx->display_picture_size, MSVDX_CMDS,
1201 DISPLAY_PICTURE_SIZE, DISPLAY_PICTURE_HEIGHT, ctx->coded_picture_height - 1);
1202 REGIO_WRITE_FIELD_LITE(ctx->display_picture_size, MSVDX_CMDS,
1203 DISPLAY_PICTURE_SIZE, DISPLAY_PICTURE_WIDTH, ctx->coded_picture_width - 1);
1204
1205 ctx->coded_picture_size = 0;
1206 REGIO_WRITE_FIELD_LITE(ctx->coded_picture_size, MSVDX_CMDS,
1207 CODED_PICTURE_SIZE, CODED_PICTURE_HEIGHT, ctx->coded_picture_height - 1);
1208 REGIO_WRITE_FIELD_LITE(ctx->coded_picture_size, MSVDX_CMDS,
1209 CODED_PICTURE_SIZE, CODED_PICTURE_WIDTH, ctx->coded_picture_width - 1);
1210
1211 ctx->obj_context->operating_mode = 0;
1212 REGIO_WRITE_FIELD(ctx->obj_context->operating_mode, MSVDX_CMDS, OPERATING_MODE, CHROMA_FORMAT, 1);
1213 REGIO_WRITE_FIELD(ctx->obj_context->operating_mode, MSVDX_CMDS, OPERATING_MODE, ASYNC_MODE, 1);
1214 /* 0 = VDMC and VDEB active. 1 = VDEB pass-thru. */
1215 REGIO_WRITE_FIELD(ctx->obj_context->operating_mode, MSVDX_CMDS, OPERATING_MODE,
1216 CODEC_MODE, CODEC_MODE_MPEG2);
1217 REGIO_WRITE_FIELD(ctx->obj_context->operating_mode, MSVDX_CMDS, OPERATING_MODE,
1218 CODEC_PROFILE, CODEC_PROFILE_MPEG2_MAIN);
1219 REGIO_WRITE_FIELD(ctx->obj_context->operating_mode, MSVDX_CMDS, OPERATING_MODE,
1220 ROW_STRIDE, (ctx->obj_context->current_render_target->psb_surface->stride_mode));
1221
1222 return VA_STATUS_SUCCESS;
1223 }
1224
1225
1226
psb_MPEG2MC_QueryConfigAttributes(VAProfile profile,VAEntrypoint entrypoint,VAConfigAttrib * attrib_list,int num_attribs)1227 static void psb_MPEG2MC_QueryConfigAttributes(
1228 VAProfile profile,
1229 VAEntrypoint entrypoint,
1230 VAConfigAttrib *attrib_list,
1231 int num_attribs)
1232 {
1233 /* No MPEG2 specific attributes */
1234 }
1235
psb_MPEG2MC_ValidateConfig(object_config_p obj_config)1236 static VAStatus psb_MPEG2MC_ValidateConfig(
1237 object_config_p obj_config)
1238 {
1239 int i;
1240 /* Check all attributes */
1241 for (i = 0; i < obj_config->attrib_count; i++) {
1242 switch (obj_config->attrib_list[i].type) {
1243 case VAConfigAttribRTFormat:
1244 /* Ignore */
1245 break;
1246
1247 default:
1248 return VA_STATUS_ERROR_ATTR_NOT_SUPPORTED;
1249 }
1250 }
1251
1252 return VA_STATUS_SUCCESS;
1253 }
1254
psb__MPEG2MC_check_legal_picture(object_context_p obj_context,object_config_p obj_config)1255 static VAStatus psb__MPEG2MC_check_legal_picture(object_context_p obj_context, object_config_p obj_config)
1256 {
1257 VAStatus vaStatus = VA_STATUS_SUCCESS;
1258
1259 if (NULL == obj_context) {
1260 vaStatus = VA_STATUS_ERROR_INVALID_CONTEXT;
1261 DEBUG_FAILURE;
1262 return vaStatus;
1263 }
1264
1265 if (NULL == obj_config) {
1266 vaStatus = VA_STATUS_ERROR_INVALID_CONFIG;
1267 DEBUG_FAILURE;
1268 return vaStatus;
1269 }
1270
1271 /* MSVDX decode capability for MPEG2:
1272 * MP@HL
1273 *
1274 * Refer to Table 8-11 (Upper bounds for luminance sample rate) of ISO/IEC 13818-2: 1995(E),
1275 * and the "MSVDX MPEG2 decode capability" table of "Poulsbo Media Software Overview"
1276 */
1277
1278 switch (obj_config->profile) {
1279 case VAProfileMPEG2Simple:
1280 if ((obj_context->picture_width <= 0) || (obj_context->picture_width > 352)
1281 || (obj_context->picture_height <= 0) || (obj_context->picture_height > 288)) {
1282 vaStatus = VA_STATUS_ERROR_RESOLUTION_NOT_SUPPORTED;
1283 }
1284 break;
1285
1286 case VAProfileMPEG2Main:
1287 if ((obj_context->picture_width <= 0) || (obj_context->picture_width > 1920)
1288 || (obj_context->picture_height <= 0) || (obj_context->picture_height > 1088)) {
1289 vaStatus = VA_STATUS_ERROR_RESOLUTION_NOT_SUPPORTED;
1290 }
1291 break;
1292
1293 default:
1294 vaStatus = VA_STATUS_ERROR_UNSUPPORTED_PROFILE;
1295 break;
1296 }
1297
1298 return vaStatus;
1299 }
1300
psb_MPEG2MC_CreateContext(object_context_p obj_context,object_config_p obj_config)1301 static VAStatus psb_MPEG2MC_CreateContext(
1302 object_context_p obj_context,
1303 object_config_p obj_config)
1304 {
1305 VAStatus vaStatus = VA_STATUS_SUCCESS;
1306 context_MPEG2MC_p ctx;
1307
1308 /* Validate flag */
1309 /* Validate picture dimensions */
1310 vaStatus = psb__MPEG2MC_check_legal_picture(obj_context, obj_config);
1311 if (VA_STATUS_SUCCESS != vaStatus) {
1312 DEBUG_FAILURE;
1313 return vaStatus;
1314 }
1315
1316 if (obj_context->num_render_targets < 1) {
1317 vaStatus = VA_STATUS_ERROR_UNKNOWN;
1318 DEBUG_FAILURE;
1319 return vaStatus;
1320 }
1321
1322 ctx = (context_MPEG2MC_p) calloc(1, sizeof(struct context_MPEG2MC_s));
1323 if (NULL == ctx) {
1324 vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;
1325 DEBUG_FAILURE;
1326 return vaStatus;
1327 }
1328
1329 /* TODO: initialize ctx content */
1330 obj_context->format_data = (void*) ctx;
1331 ctx->obj_context = obj_context;
1332 ctx->pic_params = NULL;
1333 /* TODO create and map buffer */
1334
1335 return vaStatus;
1336 }
1337
1338
psb_MPEG2MC_DestroyContext(object_context_p obj_context)1339 static void psb_MPEG2MC_DestroyContext(
1340 object_context_p obj_context)
1341 {
1342 INIT_CONTEXT_MPEG2MC;
1343
1344 /* TODO:unmap and destroy buffers */
1345 if (ctx->pic_params) {
1346 free(ctx->pic_params);
1347 ctx->pic_params = NULL;
1348 }
1349
1350 free(obj_context->format_data);
1351 obj_context->format_data = NULL;
1352 }
1353
psb_MPEG2MC_BeginPicture(object_context_p obj_context)1354 static VAStatus psb_MPEG2MC_BeginPicture(
1355 object_context_p obj_context)
1356 {
1357 INIT_CONTEXT_MPEG2MC;
1358
1359 #if 0 /* clear surface for debugging */
1360 unsigned char *surface_data = NULL;
1361 static psb_surface_p target_surface = NULL;
1362 psb_surface_p tmp = ctx->obj_context->current_render_target->psb_surface;
1363 if (target_surface != tmp) { /* for field picture, only reset one time */
1364 target_surface = tmp;
1365
1366 int ret = psb_buffer_map(&target_surface->buf, &surface_data);
1367 if (ret) {
1368 goto out;
1369 }
1370 memset(surface_data, 0x33, target_surface->size);
1371 psb_buffer_unmap(&target_surface->buf);
1372 }
1373 out:
1374 #endif
1375
1376 if (ctx->pic_params) {
1377 free(ctx->pic_params);
1378 ctx->pic_params = NULL;
1379 }
1380
1381 /* TODO: others */
1382 return VA_STATUS_SUCCESS;
1383 }
1384
1385
psb_MPEG2MC_RenderPicture(object_context_p obj_context,object_buffer_p * buffers,int num_buffers)1386 static VAStatus psb_MPEG2MC_RenderPicture(
1387 object_context_p obj_context,
1388 object_buffer_p *buffers,
1389 int num_buffers)
1390 {
1391 int i;
1392 INIT_CONTEXT_MPEG2MC;
1393 VAStatus vaStatus = VA_STATUS_SUCCESS;
1394
1395 ctx->mb_param = NULL; /* Init. compressed buffer pointers */
1396 ctx->residual_buf = NULL;
1397
1398 for (i = 0; i < num_buffers; i++) {
1399 object_buffer_p obj_buffer = buffers[i];
1400
1401 switch (obj_buffer->type) {
1402 /* Picture parameters processing */
1403 case VAPictureParameterBufferType: {
1404 vaStatus = psb__MPEG2MC_process_picture_param(ctx, obj_buffer);
1405 DEBUG_FAILURE;
1406 break;
1407 }
1408 /* Macroblock Data processing */
1409 case VAMacroblockParameterBufferType: {
1410 ctx->mb_param = (VAMacroblockParameterBufferMPEG2 *)obj_buffer->buffer_data;
1411 ctx->mb_first_addr = ctx->mb_param->macroblock_address;
1412 ctx->mb_in_buffer = obj_buffer->num_elements;
1413 /* drv_debug_msg(VIDEO_DEBUG_GENERAL, "Macroblock count %d\n",ctx->mb_in_buffer); */
1414 break;
1415 }
1416 /* Residual Difference Data processing */
1417 case VAResidualDataBufferType: {
1418 /* store the data after VLD+IDCT */
1419 ctx->residual_buf = obj_buffer->psb_buffer;
1420 ctx->blk_in_buffer = obj_buffer->num_elements;
1421 break;
1422 }
1423 default:
1424 drv_debug_msg(VIDEO_DEBUG_GENERAL, "Unhandled buffer type 0x%x\n", obj_buffer->type);
1425 break;
1426 }
1427 }
1428
1429 /* Assuming residual and MB control buffers have been located */
1430 if (ctx->residual_buf && ctx->mb_param) {
1431 ctx->residual_sent = 0;
1432 ctx->residual_pendingDMA = 0;
1433
1434 if (ctx->picture_coding_type == PICTURE_CODING_I) {
1435 psb__MPEG2MC_process_mbs_intra(ctx);
1436 } else {
1437 psb__MPEG2MC_process_mbs_interPB(ctx);
1438 }
1439 ctx->mb_param = NULL;
1440 }
1441
1442 return VA_STATUS_SUCCESS;
1443 }
1444
1445
psb_MPEG2MC_EndPicture(object_context_p obj_context)1446 static VAStatus psb_MPEG2MC_EndPicture(
1447 object_context_p obj_context)
1448 {
1449 VAStatus vaStatus = VA_STATUS_SUCCESS;
1450 INIT_CONTEXT_MPEG2MC;
1451
1452 drv_debug_msg(VIDEO_DEBUG_GENERAL, "psb_MPEG2MC_EndPicture\n");
1453
1454 if (psb_context_flush_cmdbuf(ctx->obj_context)) {
1455 vaStatus = VA_STATUS_ERROR_UNKNOWN;
1456 }
1457
1458 return vaStatus;
1459 }
1460
1461 /* TODO: integrate with VLD */
1462 struct format_vtable_s psb_MPEG2MC_vtable = {
1463 queryConfigAttributes:
1464 psb_MPEG2MC_QueryConfigAttributes,
1465 validateConfig:
1466 psb_MPEG2MC_ValidateConfig,
1467 createContext:
1468 psb_MPEG2MC_CreateContext,
1469 destroyContext:
1470 psb_MPEG2MC_DestroyContext,
1471 beginPicture:
1472 psb_MPEG2MC_BeginPicture,
1473 renderPicture:
1474 psb_MPEG2MC_RenderPicture,
1475 endPicture:
1476 psb_MPEG2MC_EndPicture
1477 };
1478