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 * Elaine Wang <elaine.wang@intel.com>
27 * Zeng Li <zeng.li@intel.com>
28 *
29 */
30
31
32 #include "psb_drv_video.h"
33
34 //#include "pnw_H263ES.h"
35 #include "pnw_hostcode.h"
36 #include "hwdefs/topazSC_defs.h"
37 #include "psb_def.h"
38 #include "psb_drv_debug.h"
39 #include "psb_cmdbuf.h"
40 #include <stdio.h>
41 #include "psb_output.h"
42 #include <wsbm/wsbm_manager.h>
43 #include "pnw_hostheader.h"
44
45 #define ALIGN_TO(value, align) ((value + align - 1) & ~(align - 1))
46 #define PAGE_ALIGN(value) ALIGN_TO(value, 4096)
47
48 /*static VAStatus pnw_DetectFrameSkip(context_ENC_p ctx);*/
49
50 static void pnw__update_rcdata(
51 context_ENC_p psContext,
52 PIC_PARAMS *psPicParams,
53 IMG_RC_PARAMS *psRCParams);
54
55 IMG_UINT32 MVEARegBase[4] = {0x13000, 0x23000, 0x33000, 0x43000}; /* From TopazSC TRM */
56
57 /* H264 Zero bias */
58 //#define ZERO_BIAS
59
60 static const IMG_INT8 H263_QPLAMBDA_MAP[31] = {
61 0, 0, 1, 1, 2,
62 2, 3, 3, 4, 4,
63 4, 5, 5, 5, 6,
64 6, 6, 7, 7, 7,
65 7, 8, 8, 8, 8,
66 9, 9, 9, 9, 10, 10
67 };
68
69 // New MP4 Lambda table
70 static const IMG_INT8 MPEG4_QPLAMBDA_MAP[31] = {
71 0, 0, 1, 2, 3,
72 3, 4, 4, 5, 5,
73 6, 6, 7, 7, 8,
74 8, 9, 9, 10, 10,
75 11, 11, 11, 11, 12,
76 12, 12, 12, 13, 13, 13
77 };
78
79 // new H.264 Lambda
80 static const IMG_INT8 H264_QPLAMBDA_MAP[40] = {
81 2, 2, 2, 2, 3, 3, 4, 4,
82 4, 5, 5, 5, 5, 5, 6, 6,
83 6, 7, 7, 7, 8, 8, 9, 11,
84 13, 14, 15, 17, 20, 23, 27, 31,
85 36, 41, 51, 62, 74, 79, 85, 91
86 };
87
88 static const IMG_INT16 H264_InterIntraBias[27] =
89 {
90 20,20,20,20,20,20,50,
91 20,20,20,20,20,20,
92 20,25,30,45,80,140,
93 200,300,400,500,550,
94 600,650,700
95 };
96
97 /*static IMG_INT16 H264InterBias(IMG_INT8 i8QP)
98 {
99 if (i8QP >= 44)
100 return 600;
101 else if (i8QP <= 35)
102 return 20;
103
104 return (70 * (i8QP - 35));
105 }*/
H264InterBias(IMG_INT8 i8QP)106 static IMG_INT16 H264InterBias(IMG_INT8 i8QP)
107 {
108 if (i8QP > 1)
109 i8QP = 1;
110 else if (i8QP > 51)
111 return 51;
112
113 return H264_InterIntraBias[(i8QP + 1)>>1];
114 }
115
116
H264SkipBias(IMG_INT8 i8QP,TH_SKIP_SCALE eSkipScale)117 static IMG_INT16 H264SkipBias(IMG_INT8 i8QP, TH_SKIP_SCALE eSkipScale)
118 {
119 IMG_INT16 i16Lambda;
120
121 // pull out lambda from the table
122 i16Lambda = i8QP - 12;
123 i16Lambda = (i16Lambda < 0) ? 0 : i16Lambda;
124 i16Lambda = H264_QPLAMBDA_MAP[i16Lambda];
125
126 // now do the multiplication to avoid using the actual multiply we will do this with shifts and adds/subtractions it is probable that the compiler would
127 // pick up the multiply and optimise appropriatly but we aren't sure
128 // * 12 = 8 + *4
129 switch (eSkipScale) {
130 default:
131 case TH_SKIP_0:
132 i16Lambda = 0;
133 break;
134 case TH_SKIP_24: /* iLambda * 24 == iLambda * 2 * 12 */
135 i16Lambda <<= 1;
136 /* break deliberatly not used as we want to apply skip12 to skip24*/
137 case TH_SKIP_12: /* iLambda * 12 == iLambda * (8 + 4) == (iLambda * 8) + (iLambda * 4) == (iLambda << 3) + (iLambda <<2) */
138 i16Lambda = (i16Lambda << 3) + (i16Lambda << 2);
139 }
140 return i16Lambda;
141 }
142
H264Intra4x4Bias(IMG_INT8 i8QP)143 static IMG_INT16 H264Intra4x4Bias(IMG_INT8 i8QP)
144 {
145 IMG_INT16 i16Lambda;
146
147 // pull out lambda from the table
148 i16Lambda = i8QP - 12;
149 i16Lambda = (i16Lambda < 0) ? 0 : i16Lambda;
150 i16Lambda = H264_QPLAMBDA_MAP[i16Lambda];
151
152 i16Lambda *= 120;
153 return i16Lambda;
154 }
155
CalculateDCScaler(IMG_INT iQP,IMG_BOOL bChroma)156 static int CalculateDCScaler(IMG_INT iQP, IMG_BOOL bChroma)
157 {
158 IMG_INT iDCScaler;
159 if (!bChroma) {
160 if (iQP > 0 && iQP < 5) {
161 iDCScaler = 8;
162 } else if (iQP > 4 && iQP < 9) {
163 iDCScaler = 2 * iQP;
164 } else if (iQP > 8 && iQP < 25) {
165 iDCScaler = iQP + 8;
166 } else {
167 iDCScaler = 2 * iQP - 16;
168 }
169 } else {
170 if (iQP > 0 && iQP < 5) {
171 iDCScaler = 8;
172 } else if (iQP > 4 && iQP < 25) {
173 iDCScaler = (iQP + 13) / 2;
174 } else {
175 iDCScaler = iQP - 6;
176 }
177 }
178 return iDCScaler;
179 }
180
LoadMPEG4Bias(pnw_cmdbuf_p cmdbuf,IMG_INT32 i32Core,IMG_UINT8 __maybe_unused ui8THSkip)181 static void LoadMPEG4Bias(
182 pnw_cmdbuf_p cmdbuf,
183 IMG_INT32 i32Core,
184 IMG_UINT8 __maybe_unused ui8THSkip
185 )
186 {
187 IMG_INT16 n;
188 IMG_INT16 iX;
189 IMG_UINT32 ui32RegVal;
190 IMG_UINT8 uiDCScaleL, uiDCScaleC, uiLambda;
191 IMG_INT32 uIPESkipVecBias, iInterMBBias, uSPESkipVecBias, iIntra16Bias;
192 IMG_UINT32 count = 0, cmd_word = 0;
193 uint32_t *pCount;
194
195 cmd_word = ((MTX_CMDID_SW_WRITEREG & MTX_CMDWORD_ID_MASK) << MTX_CMDWORD_ID_SHIFT) |
196 ((i32Core & MTX_CMDWORD_CORE_MASK) << MTX_CMDWORD_CORE_SHIFT);
197 *cmdbuf->cmd_idx++ = cmd_word;
198 pCount = cmdbuf->cmd_idx;
199 cmdbuf->cmd_idx++;
200
201 // this should be done for each core....
202 pnw_cmdbuf_insert_reg_write(MVEARegBase[i32Core], MVEA_CR_SPE_ZERO_THRESH, SPE_ZERO_THRESHOLD);
203 for (n = 31; n > 0; n--) {
204 iX = n - 12;
205 if (iX < 0) {
206 iX = 0;
207 }
208 // Dont Write QP Values To ESB -- IPE will write these values
209 // Update the quantization parameter which includes doing Lamda and the Chroma QP
210
211 uiDCScaleL = CalculateDCScaler(n, IMG_FALSE);
212 uiDCScaleC = CalculateDCScaler(n, IMG_TRUE);
213 uiLambda = MPEG4_QPLAMBDA_MAP[n - 1];
214
215 ui32RegVal = uiDCScaleL;
216 ui32RegVal |= (uiDCScaleC) << 8;
217 ui32RegVal |= (uiLambda) << 16;
218 pnw_cmdbuf_insert_reg_write(MVEARegBase[i32Core], MVEA_CR_IPE_LAMBDA_TABLE, ui32RegVal);
219
220
221 uIPESkipVecBias = TH_SKIP_IPE * uiLambda;
222 iInterMBBias = TH_INTER * (n - TH_INTER_QP);
223 if (iInterMBBias < 0)
224 iInterMBBias = 0;
225 if (iInterMBBias > TH_INTER_MAX_LEVEL)
226 iInterMBBias = TH_INTER_MAX_LEVEL;
227 uSPESkipVecBias = TH_SKIP_SPE * uiLambda;
228 iIntra16Bias = 0;
229
230 if (n & 1) {
231 pnw_cmdbuf_insert_reg_write(MVEARegBase[i32Core], MVEA_CR_IPE_MV_BIAS_TABLE, uIPESkipVecBias);
232 pnw_cmdbuf_insert_reg_write(MVEARegBase[i32Core], MVEA_CR_SPE_PRED_VECTOR_BIAS_TABLE, uIPESkipVecBias);
233 pnw_cmdbuf_insert_reg_write(MVEARegBase[i32Core], MVEA_CR_SPE_INTRA16_BIAS_TABLE, iIntra16Bias);
234 pnw_cmdbuf_insert_reg_write(MVEARegBase[i32Core], MVEA_CR_SPE_INTER_BIAS_TABLE, iInterMBBias);
235 }
236 }
237 *pCount = count;
238 }
239
LoadH263Bias(pnw_cmdbuf_p cmdbuf,IMG_INT32 i32Core,IMG_UINT8 __maybe_unused ui8THSkip)240 static void LoadH263Bias(
241 pnw_cmdbuf_p cmdbuf, IMG_INT32 i32Core, IMG_UINT8 __maybe_unused ui8THSkip)
242 {
243 IMG_INT16 n;
244 IMG_INT16 iX;
245 IMG_UINT32 ui32RegVal;
246 IMG_UINT8 uiDCScaleL, uiDCScaleC, uiLambda;
247 IMG_INT32 uIPESkipVecBias, iInterMBBias, uSPESkipVecBias, iIntra16Bias;
248 IMG_UINT32 count = 0, cmd_word = 0;
249 uint32_t *pCount;
250
251 cmd_word = ((MTX_CMDID_SW_WRITEREG & MTX_CMDWORD_ID_MASK) << MTX_CMDWORD_ID_SHIFT) |
252 ((i32Core & MTX_CMDWORD_CORE_MASK) << MTX_CMDWORD_CORE_SHIFT);
253 *cmdbuf->cmd_idx++ = cmd_word;
254 pCount = cmdbuf->cmd_idx;
255 cmdbuf->cmd_idx++;
256
257
258 // this should be done for each core....
259 pnw_cmdbuf_insert_reg_write(MVEARegBase[i32Core], MVEA_CR_SPE_ZERO_THRESH, SPE_ZERO_THRESHOLD);
260 for (n = 31; n > 0; n--) {
261 iX = n - 12;
262 if (iX < 0) {
263 iX = 0;
264 }
265 // Dont Write QP Values To ESB -- IPE will write these values
266 // Update the quantization parameter which includes doing Lamda and the Chroma QP
267
268 uiDCScaleL = CalculateDCScaler(n, IMG_FALSE);
269 uiDCScaleC = CalculateDCScaler(n, IMG_TRUE);
270 uiLambda = H263_QPLAMBDA_MAP[n - 1];
271
272 ui32RegVal = uiDCScaleL;
273 ui32RegVal |= (uiDCScaleC) << 8;
274 ui32RegVal |= (uiLambda) << 16;
275
276 pnw_cmdbuf_insert_reg_write(MVEARegBase[i32Core], MVEA_CR_IPE_LAMBDA_TABLE, ui32RegVal);
277
278
279 uIPESkipVecBias = TH_SKIP_IPE * uiLambda;
280 iInterMBBias = TH_INTER * (n - TH_INTER_QP);
281 if (iInterMBBias < 0)
282 iInterMBBias = 0;
283 if (iInterMBBias > TH_INTER_MAX_LEVEL)
284 iInterMBBias = TH_INTER_MAX_LEVEL;
285 uSPESkipVecBias = TH_SKIP_SPE * uiLambda;
286 iIntra16Bias = 0;
287 //
288 if (n & 1) {
289 pnw_cmdbuf_insert_reg_write(MVEARegBase[i32Core], MVEA_CR_IPE_MV_BIAS_TABLE, uIPESkipVecBias);
290 pnw_cmdbuf_insert_reg_write(MVEARegBase[i32Core], MVEA_CR_SPE_PRED_VECTOR_BIAS_TABLE, uIPESkipVecBias);
291 pnw_cmdbuf_insert_reg_write(MVEARegBase[i32Core], MVEA_CR_SPE_INTRA16_BIAS_TABLE, iIntra16Bias);
292 pnw_cmdbuf_insert_reg_write(MVEARegBase[i32Core], MVEA_CR_SPE_INTER_BIAS_TABLE, iInterMBBias);
293 }
294 }
295 *pCount = count;
296 }
297
LoadH264Bias(pnw_cmdbuf_p cmdbuf,IMG_INT32 i32Core,IMG_UINT8 ui8THSkip,IMG_INT8 i8QpOff)298 static void LoadH264Bias(
299 pnw_cmdbuf_p cmdbuf, IMG_INT32 i32Core, IMG_UINT8 ui8THSkip, IMG_INT8 i8QpOff)
300 {
301 IMG_INT8 n;
302 IMG_INT8 iX;
303 IMG_UINT32 ui32RegVal;
304 IMG_UINT32 uIPESkipVecBias, iInterMBBias, uSPESkipVecBias, iIntra16Bias;
305 IMG_UINT32 count = 0, cmd_word = 0;
306 uint32_t *pCount;
307
308 cmd_word = ((MTX_CMDID_SW_WRITEREG & MTX_CMDWORD_ID_MASK) << MTX_CMDWORD_ID_SHIFT) |
309 ((i32Core & MTX_CMDWORD_CORE_MASK) << MTX_CMDWORD_CORE_SHIFT);
310 *cmdbuf->cmd_idx++ = cmd_word;
311 pCount = cmdbuf->cmd_idx;
312 cmdbuf->cmd_idx++;
313
314
315 IMG_BYTE PVR_QP_SCALE_CR[76] = {
316 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
317 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11,
318 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27,
319 28, 29, 29, 30, 31, 32, 32, 33, 34, 34, 35, 35, 36, 36, 37, 37,
320 37, 38, 38, 38, 39, 39, 39, 39,
321 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39,
322 };
323
324 for (n = 51; n >= 0; n--) {
325
326 iX = n - 12;
327 if (iX < 0)
328 iX = 0;
329
330 // Dont Write QP Values To ESB -- IPE will write these values
331 // Update the quantization parameter which includes doing Lamda and the Chroma QP
332 ui32RegVal = PVR_QP_SCALE_CR[n + 12 + i8QpOff ];
333 ui32RegVal |= ((H264_QPLAMBDA_MAP[iX] * 24) / 16) << 8;
334 ui32RegVal |= (H264_QPLAMBDA_MAP[iX]) << 16;
335
336 #ifdef ZERO_BIAS
337 pnw_cmdbuf_insert_reg_write(MVEARegBase[i32Core], MVEA_CR_IPE_LAMBDA_TABLE, (2 << 16) | F_ENCODE(3, MVEA_CR_IPE_ALPHA_OR_DC_SCALE_CHR_TABLE) | F_ENCODE(PVR_QP_SCALE_CR[n], MVEA_CR_IPE_QPC_OR_DC_SCALE_LUMA_TABLE));
338 #else
339 pnw_cmdbuf_insert_reg_write(MVEARegBase[i32Core], MVEA_CR_IPE_LAMBDA_TABLE, ui32RegVal);
340 #endif
341
342 }
343 for (n = 52; n >= 0; n -= 2) {
344 IMG_INT8 qp = n;
345 if (qp > 51) qp = 51;
346
347 uIPESkipVecBias = H264SkipBias(qp, ui8THSkip);
348 iInterMBBias = H264InterBias(qp);
349 uSPESkipVecBias = H264SkipBias(qp, ui8THSkip);
350 iIntra16Bias = H264Intra4x4Bias(qp);
351
352 #ifdef ZERO_BIAS
353 pnw_cmdbuf_insert_reg_write(MVEARegBase[i32Core], MVEA_CR_IPE_MV_BIAS_TABLE, 0);
354 pnw_cmdbuf_insert_reg_write(MVEARegBase[i32Core], MVEA_CR_SPE_PRED_VECTOR_BIAS_TABLE, 0);
355 pnw_cmdbuf_insert_reg_write(MVEARegBase[i32Core], MVEA_CR_SPE_INTRA16_BIAS_TABLE, 0);
356 pnw_cmdbuf_insert_reg_write(MVEARegBase[i32Core], MVEA_CR_SPE_INTER_BIAS_TABLE, 0);
357 #else
358 pnw_cmdbuf_insert_reg_write(MVEARegBase[i32Core], MVEA_CR_IPE_MV_BIAS_TABLE, uIPESkipVecBias);
359 pnw_cmdbuf_insert_reg_write(MVEARegBase[i32Core], MVEA_CR_SPE_PRED_VECTOR_BIAS_TABLE, uIPESkipVecBias);
360 pnw_cmdbuf_insert_reg_write(MVEARegBase[i32Core], MVEA_CR_SPE_INTRA16_BIAS_TABLE, iIntra16Bias);
361 pnw_cmdbuf_insert_reg_write(MVEARegBase[i32Core], MVEA_CR_SPE_INTER_BIAS_TABLE, iInterMBBias);
362 #endif
363
364 }
365
366 pnw_cmdbuf_insert_reg_write(MVEARegBase[i32Core], MVEA_CR_SPE_ZERO_THRESH, 0);
367 *pCount = count;
368 }
369
370
pnw__alloc_context_buffer(context_ENC_p ctx,unsigned char is_JPEG)371 static VAStatus pnw__alloc_context_buffer(context_ENC_p ctx, unsigned char is_JPEG)
372 {
373 int width, height;
374 VAStatus vaStatus = VA_STATUS_SUCCESS;
375
376 /* width and height should be source surface's w and h or ?? */
377 width = ctx->obj_context->picture_width;
378 height = ctx->obj_context->picture_height;
379
380 if (is_JPEG == 0) {
381 ctx->pic_params_size = 256;
382
383 ctx->header_buffer_size = 8 * HEADER_SIZE + MAX_SLICES_PER_PICTURE * HEADER_SIZE;
384
385 ctx->seq_header_ofs = 0;
386 ctx->pic_header_ofs = HEADER_SIZE;
387 ctx->eoseq_header_ofs = 2 * HEADER_SIZE;
388 ctx->eostream_header_ofs = 3 * HEADER_SIZE;
389 ctx->aud_header_ofs = 4 * HEADER_SIZE;
390 ctx->sei_buf_prd_ofs = 5 * HEADER_SIZE;
391 ctx->sei_pic_tm_ofs = 6 * HEADER_SIZE;
392 ctx->sei_pic_fpa_ofs = 7 * HEADER_SIZE;
393 ctx->slice_header_ofs = 8 * HEADER_SIZE;
394 ctx->in_params_ofs = 0;
395
396 ctx->sliceparam_buffer_size = ((sizeof(SLICE_PARAMS) + 15) & 0xfff0) * MAX_SLICES_PER_PICTURE;
397 /* All frame share same MTX_CURRENT_IN_PARAMS and above/bellow param
398 * create MTX_CURRENT_IN_PARAMS buffer seperately
399 * every MB has one MTX_CURRENT_IN_PARAMS structure, and the (N+1) frame can
400 * reuse (N) frame's structure
401 */
402 ctx->in_params_size = ((~0xf) & (15 + 1 + (width + 15) * (height + 15) / (16 * 16))) * sizeof(MTX_CURRENT_IN_PARAMS);
403 ctx->below_params_size = ((BELOW_PARAMS_SIZE * width * height / (16 * 16)) + 0xf) & (~0xf);
404 ctx->above_params_size = ((width / 16) * 128 + 15) & (~0xf) ;
405
406 vaStatus = psb_buffer_create(ctx->obj_context->driver_data, ctx->in_params_size, psb_bt_cpu_vpu, &ctx->topaz_in_params_I);
407 if (VA_STATUS_SUCCESS != vaStatus) {
408 return vaStatus;
409 }
410
411 vaStatus = psb_buffer_create(ctx->obj_context->driver_data, ctx->in_params_size, psb_bt_cpu_vpu, &ctx->topaz_in_params_P);
412 if (VA_STATUS_SUCCESS != vaStatus) {
413 psb_buffer_destroy(&ctx->topaz_in_params_I);
414 return vaStatus;
415 }
416
417 vaStatus = psb_buffer_create(ctx->obj_context->driver_data, ctx->below_params_size * 4, psb_bt_cpu_vpu, &ctx->topaz_below_params);
418 if (VA_STATUS_SUCCESS != vaStatus) {
419 psb_buffer_destroy(&ctx->topaz_in_params_P);
420 psb_buffer_destroy(&ctx->topaz_in_params_I);
421 return vaStatus;
422 }
423
424 vaStatus = psb_buffer_create(ctx->obj_context->driver_data, ctx->above_params_size * 4, psb_bt_cpu_vpu, &ctx->topaz_above_params);
425 if (VA_STATUS_SUCCESS != vaStatus) {
426 psb_buffer_destroy(&ctx->topaz_in_params_P);
427 psb_buffer_destroy(&ctx->topaz_in_params_I);
428 psb_buffer_destroy(&ctx->topaz_below_params);
429 return vaStatus;
430 }
431 ctx->below_params_ofs = 0;
432 ctx->above_params_ofs = 0;
433 } else {
434 /*JPEG encode need three kinds of buffer but doesn't need above/below buffers.*/
435 ctx->pic_params_size = (sizeof(JPEG_MTX_QUANT_TABLE) + 0xf) & (~0xf);
436
437 ctx->header_buffer_size = (sizeof(JPEG_MTX_DMA_SETUP) + 0xf) & (~0xf);
438 ctx->sliceparam_buffer_size = 16; /* Not used*/
439 }
440 return vaStatus;
441 }
442
pnw__get_ipe_control(enum drm_pnw_topaz_codec eEncodingFormat)443 unsigned int pnw__get_ipe_control(enum drm_pnw_topaz_codec eEncodingFormat)
444 {
445 unsigned int RegVal = 0;
446
447 RegVal = F_ENCODE(2, MVEA_CR_IPE_GRID_FINE_SEARCH) |
448 F_ENCODE(0, MVEA_CR_IPE_GRID_SEARCH_SIZE) |
449 F_ENCODE(1, MVEA_CR_IPE_Y_FINE_SEARCH);
450
451 switch (eEncodingFormat) {
452 case IMG_CODEC_H263_NO_RC:
453 case IMG_CODEC_H263_VBR:
454 case IMG_CODEC_H263_CBR:
455 RegVal |= F_ENCODE(0, MVEA_CR_IPE_BLOCKSIZE) | F_ENCODE(0, MVEA_CR_IPE_ENCODING_FORMAT);
456 break;
457 case IMG_CODEC_MPEG4_NO_RC:
458 case IMG_CODEC_MPEG4_VBR:
459 case IMG_CODEC_MPEG4_CBR:
460 RegVal |= F_ENCODE(1, MVEA_CR_IPE_BLOCKSIZE) | F_ENCODE(1, MVEA_CR_IPE_ENCODING_FORMAT);
461 default:
462 break;
463 case IMG_CODEC_H264_NO_RC:
464 case IMG_CODEC_H264_VBR:
465 case IMG_CODEC_H264_CBR:
466 case IMG_CODEC_H264_VCM:
467 RegVal |= F_ENCODE(2, MVEA_CR_IPE_BLOCKSIZE) | F_ENCODE(2, MVEA_CR_IPE_ENCODING_FORMAT);
468 break;
469 }
470 RegVal |= F_ENCODE(6, MVEA_CR_IPE_Y_CANDIDATE_NUM);
471 return RegVal;
472 }
473
474
pnw_DestroyContext(object_context_p obj_context)475 void pnw_DestroyContext(object_context_p obj_context)
476 {
477 context_ENC_p ctx;
478 ctx = (context_ENC_p)obj_context->format_data;
479
480 psb_buffer_destroy(&ctx->topaz_in_params_P);
481 psb_buffer_destroy(&ctx->topaz_in_params_I);
482 psb_buffer_destroy(&ctx->topaz_below_params);
483 psb_buffer_destroy(&ctx->topaz_above_params);
484
485 if (NULL != ctx->slice_param_cache)
486 free(ctx->slice_param_cache);
487 if (NULL == ctx->save_seq_header_p)
488 free(ctx->save_seq_header_p);
489 free(obj_context->format_data);
490 obj_context->format_data = NULL;
491 }
492
pnw_CreateContext(object_context_p obj_context,object_config_p __maybe_unused obj_config,unsigned char is_JPEG)493 VAStatus pnw_CreateContext(
494 object_context_p obj_context,
495 object_config_p __maybe_unused obj_config,
496 unsigned char is_JPEG)
497 {
498 int width, height;
499 int i;
500 unsigned short SearchWidth, SearchHeight, SearchLeftOffset, SearchTopOffset;
501 context_ENC_p ctx;
502 VAStatus vaStatus;
503
504 width = obj_context->picture_width;
505 height = obj_context->picture_height;
506 ctx = (context_ENC_p) calloc(1, sizeof(struct context_ENC_s));
507 CHECK_ALLOCATION(ctx);
508
509 obj_context->format_data = (void*) ctx;
510 ctx->obj_context = obj_context;
511
512 ctx->RawWidth = (unsigned short) width;
513 ctx->RawHeight = (unsigned short) height;
514
515 if (is_JPEG == 0) {
516 ctx->Width = (unsigned short)(~0xf & (width + 0xf));
517 ctx->Height = (unsigned short)(~0xf & (height + 0xf));
518 } else {
519 /*JPEG only require them are even*/
520 ctx->Width = (unsigned short)(~0x1 & (width + 0x1));
521 ctx->Height = (unsigned short)(~0x1 & (height + 0x1));
522 }
523
524 /* pre-calculated values based on other stream properties */
525 SearchHeight = min(MVEA_LRB_SEARCH_HEIGHT, ctx->Height);
526 SearchWidth = min(MVEA_LRB_SEARCH_WIDTH, ctx->Width);
527 SearchLeftOffset = (((SearchWidth / 2) / 16) * 16);
528 SearchTopOffset = (((SearchHeight / 2) / 16) * 16);
529
530 ctx->HeightMinus16MinusLRBTopOffset = ctx->Height - (SearchTopOffset + 16);
531 ctx->HeightMinus32MinusLRBTopOffset = ctx->Height - (SearchTopOffset + 32);
532 ctx->HeightMinusLRB_TopAndBottom_OffsetsPlus16 = ctx->Height - (SearchTopOffset + SearchTopOffset + 16);
533 ctx->HeightMinusLRBSearchHeight = ctx->Height - SearchHeight;
534
535 ctx->FCode = 0;
536
537 ctx->NumCores = 2; /* FIXME Assume there is two encode cores in Penwell, precise value should read from HW */
538
539 ctx->BelowParamsBufIdx = 0;
540 ctx->AccessUnitNum = 0;
541 ctx->SyncSequencer = 0; /* FIXME Refer to DDK */
542 ctx->SliceToCore = -1;
543 ctx->CmdCount = 0xa5a5a5a5 % MAX_TOPAZ_CMD_COUNT;
544 ctx->FrmIdx = 0;
545
546 for (i = 0; i < MAX_TOPAZ_CORES; i++) {
547 ctx->LastSliceNum[i] = -1;
548 ctx->LastSync[0][i] = ~0;
549 ctx->LastSync[1][i] = ~0;
550 }
551
552 for (i = 0; i < MAX_SLICES_PER_PICTURE; i++) {
553 ctx->SliceHeaderReady[i] = IMG_FALSE;
554 }
555
556 vaStatus = pnw__alloc_context_buffer(ctx, is_JPEG);
557
558 return vaStatus;
559 }
560
pnw_BeginPicture(context_ENC_p ctx)561 VAStatus pnw_BeginPicture(context_ENC_p ctx)
562 {
563 VAStatus vaStatus = VA_STATUS_SUCCESS;
564 pnw_cmdbuf_p cmdbuf;
565 int ret, i;
566
567 if (ctx->raw_frame_count != 0)
568 ctx->previous_src_surface = ctx->src_surface;
569 ctx->src_surface = ctx->obj_context->current_render_target;
570
571 /* clear frameskip flag to 0 */
572 CLEAR_SURFACE_INFO_skipped_flag(ctx->src_surface->psb_surface);
573 ctx->none_vcl_nal = 0;
574
575 /*if (ctx->sRCParams.RCEnable == IMG_TRUE)
576 {
577 pnw_DetectFrameSkip(ctx);
578 if (0 != (GET_SURFACE_INFO_skipped_flag(ctx->src_surface->psb_surface)
579 & SURFACE_INFO_SKIP_FLAG_SETTLED))
580 ctx->sRCParams.FrameSkip = IMG_TRUE;
581 else
582 ctx->sRCParams.FrameSkip = IMG_FALSE;
583 }*/
584
585 /* Initialise the command buffer */
586 ret = pnw_context_get_next_cmdbuf(ctx->obj_context);
587 if (ret) {
588 drv_debug_msg(VIDEO_DEBUG_GENERAL, "get next cmdbuf fail\n");
589 vaStatus = VA_STATUS_ERROR_UNKNOWN;
590 return vaStatus;
591 }
592 cmdbuf = ctx->obj_context->pnw_cmdbuf;
593 memset(cmdbuf->cmd_idx_saved, 0, sizeof(cmdbuf->cmd_idx_saved));
594
595
596 /* map start_pic param */
597 vaStatus = psb_buffer_map(&cmdbuf->pic_params, &cmdbuf->pic_params_p);
598 if (vaStatus) {
599 return vaStatus;
600 }
601 vaStatus = psb_buffer_map(&cmdbuf->header_mem, &cmdbuf->header_mem_p);
602 if (vaStatus) {
603 psb_buffer_unmap(&cmdbuf->pic_params);
604 return vaStatus;
605 }
606
607 vaStatus = psb_buffer_map(&cmdbuf->slice_params, &cmdbuf->slice_params_p);
608 if (vaStatus) {
609 psb_buffer_unmap(&cmdbuf->pic_params);
610 psb_buffer_unmap(&cmdbuf->header_mem);
611 return vaStatus;
612 }
613
614 /* only map topaz param when necessary */
615 cmdbuf->topaz_above_params_p = NULL;
616 cmdbuf->topaz_below_params_p = NULL;
617 cmdbuf->topaz_in_params_I_p = NULL;
618 cmdbuf->topaz_in_params_P_p = NULL;
619
620 if (ctx->obj_context->frame_count == 0) { /* first picture */
621
622 psb_driver_data_p driver_data = ctx->obj_context->driver_data;
623
624 *cmdbuf->cmd_idx++ = ((MTX_CMDID_SW_NEW_CODEC & MTX_CMDWORD_ID_MASK) << MTX_CMDWORD_ID_SHIFT) |
625 (((driver_data->drm_context & MTX_CMDWORD_COUNT_MASK) << MTX_CMDWORD_COUNT_SHIFT));
626 pnw_cmdbuf_insert_command_param(ctx->eCodec);
627 pnw_cmdbuf_insert_command_param((ctx->Width << 16) | ctx->Height);
628 }
629
630 ctx->FrmIdx++;
631 ctx->SliceToCore = ctx->ParallelCores - 1;
632 /* ctx->AccessUnitNum++; Move this back to pnw_EndPicture */
633 ctx->sRCParams.bBitrateChanged = IMG_FALSE;
634
635 for (i = 0; i < MAX_TOPAZ_CORES; i++)
636 ctx->LastSliceNum[i] = -1;
637
638 for (i = 0; i < MAX_SLICES_PER_PICTURE; i++)
639 ctx->SliceHeaderReady[i] = IMG_FALSE;
640
641 /*If ParallelCores > 1(H264) and encode one slice per frame, the unnecessary start picture
642 *commands will be replaced with MTX_CMDID_PAD and ignored by kernel*/
643 cmdbuf->cmd_idx_saved[PNW_CMDBUF_START_PIC_IDX] = cmdbuf->cmd_idx;
644
645 /* insert START_PIC command for each core */
646 /* ensure that the master (core #0) will be last to complete this batch */
647 for (i = (ctx->ParallelCores - 1); i >= 0; i--) {
648
649 /*
650 * the content of PIC_PARAMS is filled when RenderPicture(...,VAEncPictureParameterBufferXXX)
651 */
652 pnw_cmdbuf_insert_command_package(ctx->obj_context,
653 i,
654 MTX_CMDID_START_PIC,
655 &cmdbuf->pic_params,
656 i * ctx->pic_params_size);
657
658 /* no RC paramter provided in vaBeginPicture
659 * so delay RC param setup into vaRenderPicture(SequenceHeader...)
660 */
661 }
662
663 ctx->obj_context->slice_count = 0;
664 return 0;
665 }
666
667
pnw_set_bias(context_ENC_p ctx,int core)668 VAStatus pnw_set_bias(context_ENC_p ctx, int core)
669 {
670 pnw_cmdbuf_p cmdbuf = (pnw_cmdbuf_p)ctx->obj_context->pnw_cmdbuf;
671 double flBpp;
672 IMG_UINT8 THSkip;
673
674 if (ctx->sRCParams.RCEnable) {
675 flBpp = 1.0 * ctx->sRCParams.BitsPerSecond /
676 (ctx->sRCParams.FrameRate * ctx->Width * ctx->Height);
677 } else {
678 flBpp = 0.14;
679 }
680
681 if (flBpp <= 0.07) {
682 THSkip = TH_SKIP_24;
683 } else if (flBpp <= 0.14) {
684 THSkip = TH_SKIP_12;
685 } else {
686 THSkip = TH_SKIP_0;
687 }
688 switch (ctx->eCodec) {
689 case IMG_CODEC_H264_VBR:
690 case IMG_CODEC_H264_CBR:
691 case IMG_CODEC_H264_VCM:
692 case IMG_CODEC_H264_NO_RC:
693 LoadH264Bias(cmdbuf, core, THSkip, ctx->sRCParams.QCPOffset);
694 break;
695 case IMG_CODEC_H263_CBR:
696 case IMG_CODEC_H263_NO_RC:
697 case IMG_CODEC_H263_VBR:
698 LoadH263Bias(cmdbuf, core, THSkip);
699 break;
700 case IMG_CODEC_MPEG4_NO_RC:
701 case IMG_CODEC_MPEG4_CBR:
702 case IMG_CODEC_MPEG4_VBR:
703 LoadMPEG4Bias(cmdbuf, core, THSkip);
704 break;
705 default:
706 return -1;
707 break;
708 }
709 return 0;
710 }
711
pnw_RenderPictureParameter(context_ENC_p ctx,int core)712 VAStatus pnw_RenderPictureParameter(context_ENC_p ctx, int core)
713 {
714 PIC_PARAMS *psPicParams; /* PIC_PARAMS has been put in pnw_hostcode.h */
715 object_surface_p src_surface;
716 unsigned int srf_buf_offset;
717 object_surface_p rec_surface;
718 object_surface_p ref_surface;
719 pnw_cmdbuf_p cmdbuf = ctx->obj_context->pnw_cmdbuf;
720 VAStatus vaStatus = VA_STATUS_ERROR_UNKNOWN;
721
722 psPicParams = (PIC_PARAMS *)(cmdbuf->pic_params_p + ctx->pic_params_size * core);
723
724 memset(psPicParams, 0, sizeof(PIC_PARAMS));
725 /* second frame will reuse some rate control parameters (IN_PARAMS_MP4)
726 * so only memset picture parames except IN_PARAMS
727 * BUT now IN_RC_PARAMS was reload from the cache, so it now can
728 * memset entirE PIC_PARAMS
729 */
730
731 /*
732 memset(psPicParams, 0, (int)((unsigned char *)&psPicParams->sInParams - (unsigned char *)psPicParams));
733 */
734
735 src_surface = ctx->src_surface;
736 CHECK_SURFACE(src_surface);
737
738 rec_surface = ctx->dest_surface;
739 CHECK_SURFACE(rec_surface);
740
741 /*The fisrt frame always is I frame and the content of reference frame wouldn't be used.
742 * But the heights of ref and dest frame should be the same.
743 * That allows Topaz to keep its motion vectors up to date, which helps maintain performance */
744 if (ctx->obj_context->frame_count == 0)
745 ctx->ref_surface = ctx->dest_surface;
746
747 ref_surface = ctx->ref_surface;
748 CHECK_SURFACE(rec_surface);
749
750 /* clear frameskip flag */
751 CLEAR_SURFACE_INFO_skipped_flag(rec_surface->psb_surface);
752 CLEAR_SURFACE_INFO_skipped_flag(ref_surface->psb_surface);
753
754 /* Write video data byte offset into Coded buffer
755 * If it is here, it will be a SYNC point, which have performance impact
756 * Move to psb__CreateBuffer
757 vaStatus = psb_buffer_map(ctx->coded_buf->psb_buffer, &pBuffer);
758 if(vaStatus) {
759 DEBUG_FAILURE;
760 return vaStatus;
761 }
762 *(IMG_UINT32 *)(pBuffer+8) = 16;
763 psb_buffer_unmap(ctx->coded_buf->psb_buffer);
764 */
765
766 psPicParams->SrcYStride = src_surface->psb_surface->stride;
767 switch (ctx->eFormat) {
768 case IMG_CODEC_IYUV: /* IYUV */
769 case IMG_CODEC_PL8:
770 psPicParams->SrcUVStride = src_surface->psb_surface->stride / 2;
771 psPicParams->SrcUVRowStride = src_surface->psb_surface->stride * 8 / 2;
772 break;
773 case IMG_CODEC_IMC2: /* IMC2 */
774 case IMG_CODEC_PL12:
775 psPicParams->SrcUVStride = src_surface->psb_surface->stride;
776 psPicParams->SrcUVRowStride = src_surface->psb_surface->stride * 8;
777 break;
778 default:
779 break;
780 }
781 psPicParams->SrcYRowStride = src_surface->psb_surface->stride * 16;
782 /* psPicParams->SrcUVRowStride = src_surface->psb_surface->stride * 16 / 2; */
783
784 /* Dest(rec) stride
785 * The are now literally Dst stride (not equivalent to 'offset to next row')
786 */
787 #ifdef VA_EMULATOR
788 /* only for simulator, va-emulator needs the actually stride for
789 * reconstructed frame transfer (va-emulator->driver)
790 */
791 psPicParams->DstYStride = rec_surface->psb_surface->stride;
792 psPicParams->DstUVStride = rec_surface->psb_surface->stride;
793 #else
794 psPicParams->DstYStride = rec_surface->psb_surface->stride;
795 psPicParams->DstUVStride = rec_surface->psb_surface->stride;
796 #endif
797
798 psPicParams->Width = ctx->Width;
799 psPicParams->Height = ctx->Height;
800 psPicParams->NumSlices = ctx->sRCParams.Slices;
801
802 psPicParams->IsPerSliceOutput = IMG_FALSE;
803 psPicParams->SearchHeight = min(MVEA_LRB_SEARCH_HEIGHT, psPicParams->Height);
804 psPicParams->SearchWidth = min(MVEA_LRB_SEARCH_WIDTH, psPicParams->Width);
805
806 /* not sure why we are setting this up here... */
807 psPicParams->Flags = 0;
808 switch (ctx->eCodec) {
809 case IMG_CODEC_H264_NO_RC:
810 case IMG_CODEC_H264_VBR:
811 case IMG_CODEC_H264_CBR:
812 case IMG_CODEC_H264_VCM:
813 psPicParams->Flags |= ISH264_FLAGS;
814 break;
815 case IMG_CODEC_H263_VBR:
816 case IMG_CODEC_H263_CBR:
817 case IMG_CODEC_H263_NO_RC:
818 psPicParams->Flags |= ISH263_FLAGS;
819 break;
820 case IMG_CODEC_MPEG4_NO_RC:
821 case IMG_CODEC_MPEG4_VBR:
822 case IMG_CODEC_MPEG4_CBR:
823 psPicParams->Flags |= ISMPEG4_FLAGS;
824 break;
825 default:
826 return VA_STATUS_ERROR_UNKNOWN;
827 }
828
829 switch (ctx->eCodec) {
830 case IMG_CODEC_H264_VBR:
831 case IMG_CODEC_MPEG4_VBR:
832 case IMG_CODEC_H263_VBR:
833 psPicParams->Flags |= ISVBR_FLAGS;
834 break;
835 case IMG_CODEC_H264_VCM:
836 psPicParams->Flags |= (ISVCM_FLAGS | ISCBR_FLAGS);
837 break;
838 case IMG_CODEC_H263_CBR:
839 case IMG_CODEC_H264_CBR:
840 case IMG_CODEC_MPEG4_CBR:
841 psPicParams->Flags |= ISCBR_FLAGS;
842 break;
843 case IMG_CODEC_MPEG4_NO_RC:
844 case IMG_CODEC_H263_NO_RC:
845 case IMG_CODEC_H264_NO_RC:
846 break;
847 default:
848 return VA_STATUS_ERROR_UNKNOWN;
849 }
850
851 #if 0
852 if (ctx->SyncSequencer)
853 psPicParams->Flags |= SYNC_SEQUENCER;
854 #endif
855
856 if (ctx->sRCParams.RCEnable) {
857 if (ctx->sRCParams.bDisableFrameSkipping) {
858 psPicParams->Flags |= DISABLE_FRAME_SKIPPING;
859 drv_debug_msg(VIDEO_DEBUG_GENERAL, "Frame skip is disabled.\n");
860 }
861
862 if (ctx->sRCParams.bDisableBitStuffing && IS_H264_ENC(ctx->eCodec)) {
863 psPicParams->Flags |= DISABLE_BIT_STUFFING;
864 drv_debug_msg(VIDEO_DEBUG_GENERAL, "Bit stuffing is disabled.\n");
865 }
866
867
868 /* for the first frame, will setup RC params in EndPicture */
869 if (ctx->raw_frame_count > 0) { /* reuse in_params parameter */
870 /* In case, it's changed in a new sequence */
871 if (ctx->obj_context->frame_count == 0
872 && ctx->in_params_cache.IntraPeriod != ctx->sRCParams.IntraFreq) {
873 drv_debug_msg(VIDEO_DEBUG_ERROR,
874 "On frame %d, Intra period is changed from %d to %d\n",
875 ctx->raw_frame_count, ctx->in_params_cache.IntraPeriod,
876 ctx->sRCParams.IntraFreq);
877 ctx->in_params_cache.IntraPeriod = ctx->sRCParams.IntraFreq;
878 ctx->in_params_cache.BitsPerGOP =
879 (ctx->sRCParams.BitsPerSecond / ctx->sRCParams.FrameRate)
880 * ctx->sRCParams.IntraFreq;
881 }
882
883 psPicParams->Flags &= ~FIRST_FRAME;
884 /* reload IN_RC_PARAMS from cache */
885 memcpy(&psPicParams->sInParams, &ctx->in_params_cache, sizeof(IN_RC_PARAMS));
886 } else {
887 psPicParams->Flags |= ISRC_FLAGS;
888 psPicParams->Flags |= FIRST_FRAME;
889 }
890 } else
891 psPicParams->sInParams.SeInitQP = ctx->sRCParams.InitialQp;
892
893 /* some relocations have to been done here */
894 srf_buf_offset = src_surface->psb_surface->buf.buffer_ofs;
895 if (src_surface->psb_surface->buf.type == psb_bt_camera)
896 drv_debug_msg(VIDEO_DEBUG_GENERAL, "src surface GPU offset 0x%08x, luma offset 0x%08x\n",
897 wsbmBOOffsetHint(src_surface->psb_surface->buf.drm_buf), srf_buf_offset);
898
899 RELOC_PIC_PARAMS_PNW(&psPicParams->SrcYBase, srf_buf_offset, &src_surface->psb_surface->buf);
900 switch (ctx->eFormat) {
901 case IMG_CODEC_IYUV:
902 case IMG_CODEC_PL8:
903 case IMG_CODEC_PL12:
904 RELOC_PIC_PARAMS_PNW(&psPicParams->SrcUBase,
905 srf_buf_offset + src_surface->psb_surface->chroma_offset,
906 &src_surface->psb_surface->buf);
907
908 RELOC_PIC_PARAMS_PNW(&psPicParams->SrcVBase,
909 srf_buf_offset + src_surface->psb_surface->chroma_offset * 5 / 4,
910 &src_surface->psb_surface->buf);
911
912 break;
913 case IMG_CODEC_IMC2:
914 case IMG_CODEC_NV12:
915 default:
916 break;
917 }
918
919 RELOC_PIC_PARAMS_PNW(&psPicParams->DstYBase, 0, &rec_surface->psb_surface->buf);
920
921 RELOC_PIC_PARAMS_PNW(&psPicParams->DstUVBase,
922 rec_surface->psb_surface->stride * rec_surface->height,
923 &rec_surface->psb_surface->buf);
924
925 RELOC_PIC_PARAMS_PNW(&psPicParams->BelowParamsInBase,
926 ctx->below_params_ofs + ctx->below_params_size *(((ctx->AccessUnitNum) & 0x1)),
927 cmdbuf->topaz_below_params);
928
929 RELOC_PIC_PARAMS_PNW(&psPicParams->BelowParamsOutBase,
930 ctx->below_params_ofs + ctx->below_params_size *(((ctx->AccessUnitNum + 1) & 0x1)),
931 cmdbuf->topaz_below_params);
932
933 RELOC_PIC_PARAMS_PNW(&psPicParams->AboveParamsBase,
934 ctx->above_params_ofs + ctx->above_params_size *(core * 2 + (ctx->AccessUnitNum & 0x1)),
935 cmdbuf->topaz_above_params);
936
937 RELOC_PIC_PARAMS_PNW(&psPicParams->CodedBase, ctx->coded_buf_per_slice * core, ctx->coded_buf->psb_buffer);
938 drv_debug_msg(VIDEO_DEBUG_GENERAL, "For core %d, above_parmas_off %x\n", core, ctx->above_params_ofs + ctx->above_params_size *(core * 2 + ((ctx->AccessUnitNum) & 0x1)));
939
940 return VA_STATUS_SUCCESS;
941 }
942
pnw_SetupRCParam(context_ENC_p ctx)943 static VAStatus pnw_SetupRCParam(context_ENC_p ctx)
944 {
945 pnw_cmdbuf_p cmdbuf = ctx->obj_context->pnw_cmdbuf;
946 PIC_PARAMS *psPicParams = (PIC_PARAMS *)cmdbuf->pic_params_p;
947 PIC_PARAMS *psPicParamsTmp;
948 int origin_qp, i;/* in DDK setup_rc will change qp strangly,
949 * just for keep same with DDK
950 */
951
952 origin_qp = ctx->sRCParams.InitialQp;
953
954 psPicParams->Flags |= ISRC_FLAGS;
955 pnw__setup_rcdata(ctx, psPicParams, &ctx->sRCParams);
956
957 /* restore it, just keep same with DDK */
958 ctx->sRCParams.InitialQp = origin_qp;
959
960 /* Assume IN_RC_PARAMS for each core is identical, and copy for each */
961 for (i = (ctx->ParallelCores - 1); i > 0; i--) {
962 psPicParamsTmp = (PIC_PARAMS *)(cmdbuf->pic_params_p + ctx->pic_params_size * i);
963 memcpy((unsigned char *)&psPicParamsTmp->sInParams,
964 (unsigned char *)&psPicParams->sInParams,
965 sizeof(IN_RC_PARAMS));
966 psPicParamsTmp->Flags |= psPicParams->Flags;
967 }
968
969 /* save IN_RC_PARAMS into the cache */
970 memcpy(&ctx->in_params_cache, (unsigned char *)&psPicParams->sInParams, sizeof(IN_RC_PARAMS));
971 return VA_STATUS_SUCCESS;
972 }
973
pnw_EndPicture(context_ENC_p ctx)974 VAStatus pnw_EndPicture(context_ENC_p ctx)
975 {
976 VAStatus vaStatus = VA_STATUS_SUCCESS;
977 unsigned int i;
978 int index;
979 pnw_cmdbuf_p cmdbuf = ctx->obj_context->pnw_cmdbuf;
980 PIC_PARAMS *psPicParams = (PIC_PARAMS *)cmdbuf->pic_params_p;
981 PIC_PARAMS *psPicParamsSlave = NULL;
982 unsigned int val = 0;
983
984 ctx->AccessUnitNum++;
985
986 if (ctx->sRCParams.RCEnable) {
987 if (ctx->raw_frame_count == 0)
988 pnw_SetupRCParam(ctx);
989 else if (ctx->sRCParams.bBitrateChanged) {
990 /* Toggle the last bit to make sure encoder firmare recalculate the
991 RC params even if the target bitrate isn't changed.*/
992 val = ~(ctx->sRCParams.BitsPerSecond & 0x1);
993 ctx->sRCParams.BitsPerSecond &= ~1;
994 ctx->sRCParams.BitsPerSecond |= (val & 1);
995
996 drv_debug_msg(VIDEO_DEBUG_GENERAL, "bitrate is changed to %d, "
997 "update the rc data accordingly\n", ctx->sRCParams.BitsPerSecond);
998 pnw__update_rcdata(ctx, psPicParams, &ctx->sRCParams);
999 if (ctx->sRCParams.MinQP)
1000 psPicParams->sInParams.MinQPVal = ctx->sRCParams.MinQP;
1001 memcpy(&ctx->in_params_cache, (unsigned char *)&psPicParams->sInParams, sizeof(IN_RC_PARAMS));
1002 /* Save rate control info in slave core as well */
1003 for (i = 1; i < ctx->ParallelCores; i++) {
1004 psPicParamsSlave = (PIC_PARAMS *)(cmdbuf->pic_params_p + ctx->pic_params_size * i);
1005 memcpy((unsigned char *)&psPicParamsSlave->sInParams,
1006 (unsigned char *)&psPicParams->sInParams, sizeof(IN_RC_PARAMS));
1007 }
1008 }
1009 }
1010
1011 #if TOPAZ_PIC_PARAMS_VERBOSE
1012 drv_debug_msg(VIDEO_DEBUG_GENERAL, "End Picture for frame %d\n", ctx->raw_frame_count);
1013 drv_debug_msg(VIDEO_DEBUG_GENERAL, "sizeof PIC_PARAMS %d\n", sizeof(PIC_PARAMS));
1014 drv_debug_msg(VIDEO_DEBUG_GENERAL, "sizeof in_params %d\n", sizeof(psPicParams->sInParams));
1015 drv_debug_msg(VIDEO_DEBUG_GENERAL, "PicParams->SrcYBase 0x%08x\n", psPicParams->SrcYBase);
1016 drv_debug_msg(VIDEO_DEBUG_GENERAL, "PicParams->SrcUBase 0x%08x\n", psPicParams->SrcUBase);
1017 drv_debug_msg(VIDEO_DEBUG_GENERAL, "PicParams->SrcVBase 0x%08x\n", psPicParams->SrcVBase);
1018 drv_debug_msg(VIDEO_DEBUG_GENERAL, "PicParams->DstYBase 0x%08x\n", psPicParams->DstYBase);
1019 drv_debug_msg(VIDEO_DEBUG_GENERAL, "PicParams->DstUVBase 0x%08x\n", psPicParams->DstUVBase);
1020 drv_debug_msg(VIDEO_DEBUG_GENERAL, "PicParams->SrcYStride 0x%08x\n", psPicParams->SrcYStride);
1021 drv_debug_msg(VIDEO_DEBUG_GENERAL, "PicParams->SrcUVStride 0x%08x\n", psPicParams->SrcUVStride);
1022 drv_debug_msg(VIDEO_DEBUG_GENERAL, "PicParams->SrcYRowStride 0x%08x\n", psPicParams->SrcYRowStride);
1023 drv_debug_msg(VIDEO_DEBUG_GENERAL, "PicParams->SrcUVRowStride 0x%08x\n", psPicParams->SrcUVRowStride);
1024 drv_debug_msg(VIDEO_DEBUG_GENERAL, "PicParams->DstYStride 0x%08x\n", psPicParams->DstYStride);
1025 drv_debug_msg(VIDEO_DEBUG_GENERAL, "PicParams->DstUVStride 0x%08x\n", psPicParams->DstUVStride);
1026 drv_debug_msg(VIDEO_DEBUG_GENERAL, "PicParams->CodedBase 0x%08x\n", psPicParams->CodedBase);
1027 drv_debug_msg(VIDEO_DEBUG_GENERAL, "PicParams->BelowParamsInBase 0x%08x\n", psPicParams->BelowParamsInBase);
1028 drv_debug_msg(VIDEO_DEBUG_GENERAL, "PicParams->BelowParamsOutBase 0x%08x\n", psPicParams->BelowParamsOutBase);
1029 drv_debug_msg(VIDEO_DEBUG_GENERAL, "PicParams->AboveParamsBase 0x%08x\n", psPicParams->AboveParamsBase);
1030 drv_debug_msg(VIDEO_DEBUG_GENERAL, "PicParams->Width 0x%08x\n", psPicParams->Width);
1031 drv_debug_msg(VIDEO_DEBUG_GENERAL, "PicParams->Height 0x%08x\n", psPicParams->Height);
1032 drv_debug_msg(VIDEO_DEBUG_GENERAL, "PicParams->Flags 0x%08x\n", psPicParams->Flags);
1033 drv_debug_msg(VIDEO_DEBUG_GENERAL, "PicParams->SerachWidth 0x%08x\n", psPicParams->SearchWidth);
1034 drv_debug_msg(VIDEO_DEBUG_GENERAL, "PicParams->SearchHeight 0x%08x\n", psPicParams->SearchHeight);
1035 drv_debug_msg(VIDEO_DEBUG_GENERAL, "PicParams->NumSlices 0x%08x\n", psPicParams->NumSlices);
1036 drv_debug_msg(VIDEO_DEBUG_GENERAL, "psPicParams->ClockDivBitrate %lld\n", psPicParams->ClockDivBitrate);
1037 drv_debug_msg(VIDEO_DEBUG_GENERAL, "psPicParams->MaxBufferMultClockDivBitrate %d\n",
1038 psPicParams->MaxBufferMultClockDivBitrate);
1039 drv_debug_msg(VIDEO_DEBUG_GENERAL, "psPicParams->sInParams.SeInitQP %d\n", psPicParams->sInParams.SeInitQP);
1040 drv_debug_msg(VIDEO_DEBUG_GENERAL, "psPicParams->sInParams.MinQPVal %d\n", psPicParams->sInParams.MinQPVal);
1041 drv_debug_msg(VIDEO_DEBUG_GENERAL, "psPicParams->sInParams.MaxQPVal %d\n", psPicParams->sInParams.MaxQPVal);
1042 drv_debug_msg(VIDEO_DEBUG_GENERAL, "psPicParams->sInParams.MBPerRow %d\n", psPicParams->sInParams.MBPerRow);
1043 drv_debug_msg(VIDEO_DEBUG_GENERAL, "psPicParams->sInParams.MBPerFrm %d\n", psPicParams->sInParams.MBPerFrm);
1044 drv_debug_msg(VIDEO_DEBUG_GENERAL, "psPicParams->sInParams.MBPerBU %d\n", psPicParams->sInParams.MBPerBU);
1045 drv_debug_msg(VIDEO_DEBUG_GENERAL, "psPicParams->sInParams.BUPerFrm %d\n", psPicParams->sInParams.BUPerFrm);
1046 drv_debug_msg(VIDEO_DEBUG_GENERAL, "psPicParams->sInParams.IntraPeriod %d\n", psPicParams->sInParams.IntraPeriod);
1047 drv_debug_msg(VIDEO_DEBUG_GENERAL, "psPicParams->sInParams.BitsPerFrm %d\n", psPicParams->sInParams.BitsPerFrm);
1048 drv_debug_msg(VIDEO_DEBUG_GENERAL, "psPicParams->sInParams.BitsPerBU %d\n", psPicParams->sInParams.BitsPerBU);
1049 drv_debug_msg(VIDEO_DEBUG_GENERAL, "psPicParams->sInParams.BitsPerMB %d\n", psPicParams->sInParams.BitsPerMB);
1050 drv_debug_msg(VIDEO_DEBUG_GENERAL, "psPicParams->sInParams.BitRate %d\n", psPicParams->sInParams.BitRate);
1051 drv_debug_msg(VIDEO_DEBUG_GENERAL, "psPicParams->sInParams.BufferSize %d\n", psPicParams->sInParams.BufferSize);
1052 drv_debug_msg(VIDEO_DEBUG_GENERAL, "psPicParams->sInParams.InitialLevel %d\n", psPicParams->sInParams.InitialLevel);
1053 drv_debug_msg(VIDEO_DEBUG_GENERAL, "psPicParams->sInParams.InitialDelay %d\n", psPicParams->sInParams.InitialDelay);
1054 drv_debug_msg(VIDEO_DEBUG_GENERAL, "psPicParams->sInParams.ScaleFactor %d\n", psPicParams->sInParams.ScaleFactor);
1055 drv_debug_msg(VIDEO_DEBUG_GENERAL, "psPicParams->sInParams.VCMBitrateMargin %d\n", psPicParams->sInParams.VCMBitrateMargin);
1056 drv_debug_msg(VIDEO_DEBUG_GENERAL, "psPicParams->sInParams.HalfFrameRate %d\n", psPicParams->sInParams.HalfFrameRate);
1057 drv_debug_msg(VIDEO_DEBUG_GENERAL, "psPicParams->sInParams.FCode %d\n", psPicParams->sInParams.FCode);
1058 drv_debug_msg(VIDEO_DEBUG_GENERAL, "psPicParams->sInParams.BitsPerGOP %d\n", psPicParams->sInParams.BitsPerGOP);
1059 drv_debug_msg(VIDEO_DEBUG_GENERAL, "psPicParams->sInParams.AvQPVal %d\n", psPicParams->sInParams.AvQPVal);
1060 drv_debug_msg(VIDEO_DEBUG_GENERAL, "psPicParams->sInParams.MyInitQP %d\n", psPicParams->sInParams.MyInitQP);
1061 drv_debug_msg(VIDEO_DEBUG_GENERAL, "psPicParams->sInParams.ForeceSkipMargin %d\n", psPicParams->sInParams.ForeceSkipMargin);
1062 drv_debug_msg(VIDEO_DEBUG_GENERAL, "psPicParams->sInParams.RCScaleFactor %d\n", psPicParams->sInParams.RCScaleFactor);
1063 drv_debug_msg(VIDEO_DEBUG_GENERAL, "psPicParams->sInParams.TransferRate %d\n", psPicParams->sInParams.TransferRate);
1064 drv_debug_msg(VIDEO_DEBUG_GENERAL, "psPicParams->sInParams.MaxFrameSize %d\n", psPicParams->sInParams.MaxFrameSize);
1065 #endif
1066 /* save current settings */
1067 ctx->previous_ref_surface = ctx->ref_surface;
1068 ctx->previous_dest_surface = ctx->dest_surface; /* reconstructed surface */
1069 SET_CODEDBUF_INFO(SLICE_NUM, ctx->coded_buf->codedbuf_aux_info,
1070 ctx->obj_context->slice_count);
1071 SET_CODEDBUF_INFO(NONE_VCL_NUM, ctx->coded_buf->codedbuf_aux_info,
1072 ctx->none_vcl_nal);
1073
1074 for (index = (ctx->ParallelCores - 1); index >= 0; index--) {
1075 pnw_cmdbuf_insert_command_package(ctx->obj_context,
1076 index,
1077 MTX_CMDID_END_PIC,
1078 NULL,
1079 0);
1080 }
1081 psb_buffer_unmap(&cmdbuf->pic_params);
1082 psb_buffer_unmap(&cmdbuf->header_mem);
1083 psb_buffer_unmap(&cmdbuf->slice_params);
1084
1085 /* unmap MTX_CURRENT_IN_PARAMS buffer only when it is mapped */
1086 if (cmdbuf->topaz_in_params_I_p != NULL) {
1087 psb_buffer_unmap(cmdbuf->topaz_in_params_I);
1088 cmdbuf->topaz_in_params_I_p = NULL;
1089 }
1090
1091 if (cmdbuf->topaz_in_params_P_p != NULL) {
1092 psb_buffer_unmap(cmdbuf->topaz_in_params_P);
1093 cmdbuf->topaz_in_params_P_p = NULL;
1094 }
1095
1096 if (cmdbuf->topaz_above_params_p != NULL) {
1097 psb_buffer_unmap(cmdbuf->topaz_above_params);
1098 cmdbuf->topaz_above_params_p = NULL;
1099 }
1100
1101 if (cmdbuf->topaz_below_params_p != NULL) {
1102 psb_buffer_unmap(cmdbuf->topaz_below_params);
1103 cmdbuf->topaz_below_params_p = NULL;
1104 }
1105
1106 if (pnw_context_flush_cmdbuf(ctx->obj_context)) {
1107 vaStatus = VA_STATUS_ERROR_UNKNOWN;
1108 }
1109 ctx->raw_frame_count++;
1110 return vaStatus;
1111 }
1112
pnw__setup_busize(context_ENC_p ctx)1113 static void pnw__setup_busize(context_ENC_p ctx)
1114 {
1115 unsigned int old_busize = ctx->sRCParams.BUSize;
1116 int slices = ctx->obj_context->slice_count;
1117
1118 /* it is called at EndPicture, we should now the Slice number */
1119 //ctx->Slices = ctx->obj_context->slice_count;
1120
1121 /* if no BU size is given then pick one ourselves */
1122 if (ctx->sRCParams.BUSize != 0) { /* application provided BUSize */
1123 IMG_UINT32 MBs, MBsperSlice, MBsLastSlice;
1124 IMG_UINT32 BUs;
1125 IMG_INT32 SliceHeight;
1126 IMG_UINT32 MaxSlicesPerPipe, MaxMBsPerPipe, MaxBUsPerPipe;
1127
1128 MBs = ctx->Height * ctx->Width / (16 * 16);
1129
1130 SliceHeight = ctx->Height / slices;
1131 /* SliceHeight += 15; */
1132 SliceHeight &= ~15;
1133
1134 MBsperSlice = (SliceHeight * ctx->Width) / (16 * 16);
1135 MBsLastSlice = MBs - (MBsperSlice * (slices - 1));
1136
1137 /* they have given us a basic unit so validate it */
1138 if (ctx->sRCParams.BUSize < 6) {
1139 drv_debug_msg(VIDEO_DEBUG_ERROR, "ERROR: Basic unit size too small, must be greater than 6\n");
1140 ctx->sRCParams.BUSize = 0; /* need repatch */;
1141 }
1142 if (ctx->sRCParams.BUSize > MBsperSlice) {
1143 drv_debug_msg(VIDEO_DEBUG_ERROR, "ERROR: Basic unit size too large, must be less than the number of macroblocks in a slice\n");
1144 ctx->sRCParams.BUSize = 0; /* need repatch */;
1145 }
1146 if (ctx->sRCParams.BUSize > MBsLastSlice) {
1147 drv_debug_msg(VIDEO_DEBUG_ERROR, "ERROR: Basic unit size too large, must be less than number of macroblocks in the last slice\n");
1148 ctx->sRCParams.BUSize = 0; /* need repatch */;
1149 }
1150
1151 if (ctx->sRCParams.BUSize != 0) {
1152 BUs = MBsperSlice / ctx->sRCParams.BUSize;
1153 if ((BUs * ctx->sRCParams.BUSize) != MBsperSlice) {
1154 drv_debug_msg(VIDEO_DEBUG_ERROR, "ERROR: Basic unit size not an integer divisor of MB's in a slice");
1155 ctx->sRCParams.BUSize = 0; /* need repatch */;
1156 }
1157 }
1158 if (ctx->sRCParams.BUSize != 0) {
1159 BUs = MBsLastSlice / ctx->sRCParams.BUSize;
1160 if ((BUs * ctx->sRCParams.BUSize) != MBsLastSlice) {
1161 drv_debug_msg(VIDEO_DEBUG_ERROR, "ERROR: Basic unit size not an integer divisor of MB's in a slice");
1162 ctx->sRCParams.BUSize = 0; /* need repatch */;
1163 }
1164 }
1165
1166 if (ctx->sRCParams.BUSize != 0) {
1167 // check if the number of BUs per pipe is greater than 200
1168 MaxSlicesPerPipe = (slices + ctx->ParallelCores - 1) / ctx->ParallelCores;
1169 MaxMBsPerPipe = (MBsperSlice * (MaxSlicesPerPipe - 1)) + MBsLastSlice;
1170 MaxBUsPerPipe = (MaxMBsPerPipe + ctx->sRCParams.BUSize - 1) / ctx->sRCParams.BUSize;
1171 if (MaxBUsPerPipe > 200) {
1172 drv_debug_msg(VIDEO_DEBUG_ERROR, "ERROR: Basic unit size too small. There must be less than 200 basic units per slice");
1173 ctx->sRCParams.BUSize = 0; /* need repatch */;
1174 }
1175 }
1176 }
1177
1178 if (ctx->sRCParams.BUSize == 0) {
1179 IMG_UINT32 MBs, MBsperSlice, MBsLastSlice;
1180 IMG_UINT32 BUsperSlice, BUsLastSlice;
1181 IMG_UINT32 MaxSlicesPerPipe, MaxMBsPerPipe, MaxBUsPerPipe;
1182 IMG_INT32 SliceHeight;
1183 IMG_UINT32 BUSize = 6;
1184
1185 MBs = ctx->Height * ctx->Width / (16 * 16);
1186
1187 SliceHeight = ctx->Height / slices;
1188 /* SliceHeight += 15; */
1189 SliceHeight &= ~15;
1190
1191 MBsperSlice = (SliceHeight * ctx->Width) / (16 * 16);
1192 MBsLastSlice = MBs - (MBsperSlice * (slices - 1));
1193
1194 /* Check number of BUs to be encoded on one pipe is less than maximum number allowed 200 */
1195 MaxSlicesPerPipe = (slices + ctx->ParallelCores - 1) / ctx->ParallelCores;
1196 MaxMBsPerPipe = (MBsperSlice * (MaxSlicesPerPipe - 1)) + MBsLastSlice;
1197 MaxBUsPerPipe = (MaxMBsPerPipe + BUSize - 1) / BUSize;
1198
1199 while (MaxBUsPerPipe > 200) {
1200 BUSize++;
1201 MaxBUsPerPipe = (MaxMBsPerPipe + BUSize - 1) / BUSize;
1202 }
1203
1204 /* Check whether there are integeral number of BUs in the slices */
1205 BUsperSlice = MBsperSlice / BUSize;
1206 BUsLastSlice = MBsLastSlice / BUSize;
1207 while ((BUsperSlice*BUSize != MBsperSlice) ||
1208 (BUsLastSlice*BUSize != MBsLastSlice)) {
1209 BUSize++;
1210 BUsperSlice = MBsperSlice / BUSize;
1211 BUsLastSlice = MBsLastSlice / BUSize;
1212 }
1213
1214 ctx->sRCParams.BUSize = BUSize;
1215 /*
1216 ctx->sRCParams.InitialLevel = (3 * ctx->sRCParams.BufferSize) >> 4;
1217 ctx->sRCParams.InitialDelay = (13 * ctx->sRCParams.BufferSize) >> 4;
1218 */
1219 }
1220
1221 if (ctx->sRCParams.BUSize != old_busize)
1222 drv_debug_msg(VIDEO_DEBUG_GENERAL, "Patched Basic unit to %d (original=%d)\n", ctx->sRCParams.BUSize, old_busize);
1223 }
1224
1225
pnw__update_rcdata(context_ENC_p psContext,PIC_PARAMS * psPicParams,IMG_RC_PARAMS * psRCParams)1226 static void pnw__update_rcdata(
1227 context_ENC_p psContext,
1228 PIC_PARAMS *psPicParams,
1229 IMG_RC_PARAMS *psRCParams)
1230 {
1231 double L1, L2, L3, L4, L5, L6, flBpp;
1232 IMG_INT16 i16TempQP;
1233 IMG_INT32 i32BufferSizeInFrames = 0;
1234
1235 flBpp = 1.0 * psRCParams->BitsPerSecond
1236 / (psRCParams->FrameRate * psContext->Width * psContext->Height);
1237
1238 if (psContext->Width <= 176) {
1239 /* for very small franes we need to adjust the calculations */
1240 flBpp = flBpp / 2.0;
1241 }
1242
1243 psPicParams->sInParams.IntraPeriod = psRCParams->IntraFreq;
1244 psPicParams->sInParams.BitRate = psRCParams->BitsPerSecond;
1245 psPicParams->sInParams.BitsPerFrm = (psRCParams->BitsPerSecond + psRCParams->FrameRate / 2) / psRCParams->FrameRate;
1246 psPicParams->sInParams.BitsPerGOP = (psRCParams->BitsPerSecond / psRCParams->FrameRate) * psRCParams->IntraFreq;
1247 psPicParams->sInParams.BitsPerBU = psPicParams->sInParams.BitsPerFrm / (4 * psPicParams->sInParams.BUPerFrm);
1248 psPicParams->sInParams.BitsPerMB = psPicParams->sInParams.BitsPerBU / psRCParams->BUSize;
1249 psPicParams->sInParams.TransferRate = psRCParams->BitsPerSecond / psRCParams->FrameRate;
1250
1251 i32BufferSizeInFrames = psRCParams->BufferSize / psPicParams->sInParams.BitsPerFrm;
1252
1253 /* select thresholds and initial Qps etc that are codec dependent */
1254 switch (psContext->eCodec) {
1255 case IMG_CODEC_H264_CBR:
1256 case IMG_CODEC_H264_VCM:
1257 case IMG_CODEC_H264_VBR:
1258 L1 = 0.1;
1259 L2 = 0.15;
1260 L3 = 0.2;
1261
1262 /* Set MaxQP to avoid blocky image in low bitrate */
1263 /* RCScaleFactor indicates the size of GOP for rate control */
1264 if (psContext->eCodec == IMG_CODEC_H264_VCM) {
1265 psPicParams->sInParams.MaxQPVal = 51;
1266 psPicParams->sInParams.RCScaleFactor = 16;
1267 }
1268 else {
1269 psPicParams->sInParams.MaxQPVal = 51;
1270 psPicParams->sInParams.RCScaleFactor = 16;
1271 }
1272
1273 /* Setup MAX and MIN Quant Values */
1274 if (flBpp >= 0.50)
1275 i16TempQP = 4;
1276 else
1277 i16TempQP = (unsigned int)(26 - (40 * flBpp));
1278
1279 psPicParams->sInParams.MinQPVal = (max(min(psPicParams->sInParams.MaxQPVal, i16TempQP), 0));
1280
1281 L1 = 0.050568;
1282 L2 = 0.202272;
1283 L3 = 0.40454321;
1284 L4 = 0.80908642;
1285 L5 = 1.011358025;
1286 if (flBpp < L1)
1287 psPicParams->sInParams.SeInitQP = (IMG_UINT8)(47 - 78.10 * flBpp);
1288
1289 else if (flBpp >= L1 && flBpp < L2)
1290 psPicParams->sInParams.SeInitQP = (IMG_UINT8)(45 - 66.67 * flBpp);
1291
1292 else if (flBpp >= L2 && flBpp < L3)
1293 psPicParams->sInParams.SeInitQP = (IMG_UINT8)(36 - 24.72 * flBpp);
1294
1295 else if (flBpp >= L3 && flBpp < L4)
1296 psPicParams->sInParams.SeInitQP = (IMG_UINT8)(34 - 19.78 * flBpp);
1297
1298 else if (flBpp >= L4 && flBpp < L5)
1299 psPicParams->sInParams.SeInitQP = (IMG_UINT8)(27 - 9.89 * flBpp);
1300
1301 else if (flBpp >= L5 && flBpp < 4)
1302 psPicParams->sInParams.SeInitQP = (IMG_UINT8)(20 - 4.95 * flBpp);
1303 else
1304 psPicParams->sInParams.SeInitQP = psPicParams->sInParams.MinQPVal;
1305
1306 if (psPicParams->sInParams.SeInitQP < psPicParams->sInParams.MinQPVal)
1307 psPicParams->sInParams.SeInitQP = psPicParams->sInParams.MinQPVal;
1308
1309 break;
1310
1311 case IMG_CODEC_MPEG4_CBR:
1312 case IMG_CODEC_MPEG4_VBR:
1313 case IMG_CODEC_H263_CBR:
1314 case IMG_CODEC_H263_VBR:
1315 psPicParams->sInParams.RCScaleFactor = 16;
1316 psPicParams->sInParams.MaxQPVal = 31;
1317
1318 if (psContext->Width <= 176) {
1319 L1 = 0.043;
1320 L2 = 0.085;
1321 L3 = 0.126;
1322 L4 = 0.168;
1323 L5 = 0.336;
1324 L6 = 0.505;
1325 } else if (psContext->Width == 352) {
1326 L1 = 0.065;
1327 L2 = 0.085;
1328 L3 = 0.106;
1329 L4 = 0.126;
1330 L5 = 0.168 ;
1331 L6 = 0.210;
1332 } else {
1333 L1 = 0.051;
1334 L2 = 0.0770;
1335 L3 = 0.096;
1336 L4 = 0.145;
1337 L5 = 0.193;
1338 L6 = 0.289;
1339 }
1340
1341 /* Calculate Initial QP if it has not been specified */
1342 if (flBpp < L1)
1343 psPicParams->sInParams.SeInitQP = 31;
1344
1345 else if (flBpp >= L1 && flBpp < L2)
1346 psPicParams->sInParams.SeInitQP = 26;
1347
1348 else if (flBpp >= L2 && flBpp < L3)
1349 psPicParams->sInParams.SeInitQP = 22;
1350
1351 else if (flBpp >= L3 && flBpp < L4)
1352 psPicParams->sInParams.SeInitQP = 18;
1353
1354 else if (flBpp >= L4 && flBpp < L5)
1355 psPicParams->sInParams.SeInitQP = 14;
1356
1357 else if (flBpp >= L5 && flBpp < L6)
1358 psPicParams->sInParams.SeInitQP = 10;
1359 else
1360 psPicParams->sInParams.SeInitQP = 8;
1361
1362 psPicParams->sInParams.AvQPVal = psPicParams->sInParams.SeInitQP;
1363
1364 if (flBpp >= 0.25
1365 && (psContext->eCodec == IMG_CODEC_MPEG4_CBR ||
1366 psContext->eCodec == IMG_CODEC_MPEG4_VBR)) {
1367 psPicParams->sInParams.MinQPVal = 1;
1368 } else {
1369 psPicParams->sInParams.MinQPVal = 4;
1370 }
1371 break;
1372
1373 default:
1374 /* the NO RC cases will fall here */
1375 break;
1376 }
1377
1378 /* Set up Input Parameters that are mode dependent */
1379 switch (psContext->eCodec) {
1380 case IMG_CODEC_H264_NO_RC:
1381 case IMG_CODEC_H263_NO_RC:
1382 case IMG_CODEC_MPEG4_NO_RC:
1383 return ;
1384
1385 case IMG_CODEC_H264_VCM:
1386 psPicParams->Flags |= (ISVCM_FLAGS | ISCBR_FLAGS);
1387 if (psContext->Height >= 480) {
1388 /* for SD and above we can target 95% (122/128) of maximum bitrate */
1389 psPicParams->sInParams.VCMBitrateMargin = 122;
1390 } else {
1391 /* for less and SD we target 99% of maximum bitrate */
1392 psPicParams->sInParams.VCMBitrateMargin = 127;
1393 }
1394 if (i32BufferSizeInFrames < 15) {
1395 /* when we have a very small window size we reduce the target
1396 * further to avoid too much skipping */
1397 psPicParams->sInParams.VCMBitrateMargin -= 5;
1398 }
1399 psPicParams->sInParams.ForeceSkipMargin = 0; /* start skipping MBs when within 500 bits of slice or frame limit */
1400 if (psRCParams->BitsPerSecond < 1000000) { // 1 Mbits/s
1401 psPicParams->sInParams.ScaleFactor = 0;
1402 } else if (psRCParams->BitsPerSecond < 2000000) { // 2 Mbits/s
1403 psPicParams->sInParams.ScaleFactor = 1;
1404 } else if (psRCParams->BitsPerSecond < 4000000) { // 4 Mbits/s
1405 psPicParams->sInParams.ScaleFactor = 2;
1406 } else if (psRCParams->BitsPerSecond < 8000000) { // 8 Mbits/s
1407 psPicParams->sInParams.ScaleFactor = 3;
1408 } else {
1409 psPicParams->sInParams.ScaleFactor = 4;
1410 }
1411
1412 psPicParams->sInParams.BufferSize = i32BufferSizeInFrames;
1413
1414 break;
1415 case IMG_CODEC_H264_CBR:
1416 psPicParams->Flags |= ISCBR_FLAGS;
1417 /* ------------------- H264 CBR RC ------------------- */
1418 /* Initialize the parameters of fluid flow traffic model. */
1419 psPicParams->sInParams.BufferSize = psRCParams->BufferSize;
1420
1421 /* HRD consideration - These values are used by H.264 reference code. */
1422 if (psRCParams->BitsPerSecond < 1000000) { /* 1 Mbits/s */
1423 psPicParams->sInParams.ScaleFactor = 0;
1424 } else if (psRCParams->BitsPerSecond < 2000000) { /* 2 Mbits/s */
1425 psPicParams->sInParams.ScaleFactor = 1;
1426 } else if (psRCParams->BitsPerSecond < 4000000) { /* 4 Mbits/s */
1427 psPicParams->sInParams.ScaleFactor = 2;
1428 } else if (psRCParams->BitsPerSecond < 8000000) { /* 8 Mbits/s */
1429 psPicParams->sInParams.ScaleFactor = 3;
1430 } else {
1431 psPicParams->sInParams.ScaleFactor = 4;
1432 }
1433 break;
1434
1435 case IMG_CODEC_MPEG4_CBR:
1436 case IMG_CODEC_H263_CBR:
1437 psPicParams->Flags |= ISCBR_FLAGS;
1438
1439 flBpp = 256 * (psRCParams->BitsPerSecond / psContext->Width);
1440 flBpp /= (psContext->Height * psRCParams->FrameRate);
1441
1442 if ((psPicParams->sInParams.MBPerFrm > 1024 && flBpp < 16) || (psPicParams->sInParams.MBPerFrm <= 1024 && flBpp < 24))
1443 psPicParams->sInParams.HalfFrameRate = 1;
1444 else
1445 psPicParams->sInParams.HalfFrameRate = 0;
1446
1447 if (psPicParams->sInParams.HalfFrameRate >= 1) {
1448 psPicParams->sInParams.SeInitQP = 31;
1449 psPicParams->sInParams.AvQPVal = 31;
1450 psPicParams->sInParams.MyInitQP = 31;
1451 }
1452
1453 psPicParams->sInParams.BufferSize = psRCParams->BufferSize;
1454 if (psPicParams->sInParams.BufferSize > 112 * 16384) // Simple Profile L5 Constraints
1455 psPicParams->sInParams.BufferSize = 112 * 16384;
1456 break;
1457
1458 case IMG_CODEC_MPEG4_VBR:
1459 case IMG_CODEC_H263_VBR:
1460 case IMG_CODEC_H264_VBR:
1461 psPicParams->Flags |= ISVBR_FLAGS;
1462
1463 psPicParams->sInParams.MBPerBU = psPicParams->sInParams.MBPerFrm;
1464 psPicParams->sInParams.BUPerFrm = 1;
1465
1466 /* Initialize the parameters of fluid flow traffic model. */
1467 psPicParams->sInParams.BufferSize = psRCParams->BufferSize;
1468
1469 if (psContext->eCodec != IMG_CODEC_H264_VBR) {
1470 if (psPicParams->sInParams.BufferSize > 112 * 16384)
1471 psPicParams->sInParams.BufferSize = 112 * 16384; // Simple Profile L5 Constraints
1472 }
1473
1474 /* These scale factor are used only for rate control to avoid overflow */
1475 /* in fixed-point calculation these scale factors are decided by bit rate */
1476 if (psRCParams->BitsPerSecond < 640000) {
1477 psPicParams->sInParams.ScaleFactor = 2; /* related to complexity */
1478 } else if (psRCParams->BitsPerSecond < 2000000) {
1479 psPicParams->sInParams.ScaleFactor = 4;
1480 } else {
1481 psPicParams->sInParams.ScaleFactor = 6;
1482 }
1483 break;
1484 default:
1485 break;
1486 }
1487
1488 psPicParams->sInParams.MyInitQP = psPicParams->sInParams.SeInitQP;
1489
1490 #if 0
1491 if (psContext->SyncSequencer)
1492 psPicParams->Flags |= SYNC_SEQUENCER;
1493 #endif
1494
1495 psPicParams->sInParams.InitialDelay = psRCParams->InitialDelay;
1496 psPicParams->sInParams.InitialLevel = psRCParams->InitialLevel;
1497 psRCParams->InitialQp = psPicParams->sInParams.SeInitQP;
1498
1499 drv_debug_msg(VIDEO_DEBUG_GENERAL, "InitQP %d, minQP %d, maxQP %d\n",
1500 psPicParams->sInParams.SeInitQP,
1501 psPicParams->sInParams.MinQPVal,
1502 psPicParams->sInParams.MaxQPVal);
1503
1504 /* The rate control uses this value to adjust the reaction rate
1505 to larger than expected frames in long GOPS*/
1506
1507 return;
1508 }
1509
1510
1511 /***********************************************************************************
1512 * Function Name : SetupRCData
1513 * Inputs :
1514 * Outputs :
1515 * Returns :
1516 * Description : Sets up RC Data
1517 ************************************************************************************/
pnw__setup_rcdata(context_ENC_p psContext,PIC_PARAMS * psPicParams,IMG_RC_PARAMS * psRCParams)1518 void pnw__setup_rcdata(
1519 context_ENC_p psContext,
1520 PIC_PARAMS *psPicParams,
1521 IMG_RC_PARAMS *psRCParams)
1522 {
1523 IMG_UINT8 ui8InitialSeInitQP;
1524
1525 /* frameskip is always cleared, specially handled at vaEndPicture */
1526 psRCParams->FrameSkip = 0;
1527
1528 if (!psRCParams->BitsPerSecond)
1529 psRCParams->BitsPerSecond = 64000;
1530 /*
1531 if (psRCParams->BitsPerSecond > max_bitrate)
1532 psRCParams->BitsPerSecond = max_bitrate;
1533 */
1534 if (!psRCParams->FrameRate)
1535 psRCParams->FrameRate = 30;
1536
1537 pnw__setup_busize(psContext); /* calculate BasicUnitSize */
1538
1539 psPicParams->sInParams.SeInitQP = psRCParams->InitialQp;
1540
1541 psPicParams->sInParams.MBPerRow = (psContext->Width >> 4);
1542 psPicParams->sInParams.MBPerBU = psRCParams->BUSize;
1543 psPicParams->sInParams.MBPerFrm = (psContext->Width >> 4) * (psContext->Height >> 4);
1544 psPicParams->sInParams.BUPerFrm = (psPicParams->sInParams.MBPerFrm) / psRCParams->BUSize;
1545 psPicParams->sInParams.AvQPVal = psRCParams->InitialQp;
1546 psPicParams->sInParams.MyInitQP = psRCParams->InitialQp;
1547 psPicParams->sInParams.MaxFrameSize = psRCParams->BitsPerSecond / psRCParams->FrameRate;
1548
1549 ui8InitialSeInitQP = psPicParams->sInParams.SeInitQP;
1550
1551 pnw__update_rcdata(psContext, psPicParams, psRCParams);
1552
1553 /*If MinQP has been set, restore this value rather than
1554 *the calculated value set by UpdateRCData()*/
1555 if (psRCParams->MinQP) {
1556 psPicParams->sInParams.MinQPVal = (IMG_UINT8)psRCParams->MinQP;
1557 }
1558
1559 /*If SeInitQP has been set, restore this value and other
1560 * dependant variables rather than the calculated values set by UpdateRCData()*/
1561 if (ui8InitialSeInitQP) {
1562 psPicParams->sInParams.SeInitQP = ui8InitialSeInitQP;
1563 psPicParams->sInParams.MyInitQP = ui8InitialSeInitQP;
1564 psRCParams->InitialQp = ui8InitialSeInitQP;
1565 }
1566
1567 /* HRD parameters are meaningless without a bitrate
1568 * HRD parameters are not supported in VCM mode */
1569 if (psRCParams->BitsPerSecond == 0 || psContext->eCodec == IMG_CODEC_H264_VCM)
1570 psContext->bInserHRDParams = IMG_FALSE;
1571
1572 if (psContext->bInserHRDParams) {
1573 psPicParams->ClockDivBitrate = (90000 * 0x100000000LL);
1574 psPicParams->ClockDivBitrate /= psRCParams->BitsPerSecond;
1575 psPicParams->MaxBufferMultClockDivBitrate = (IMG_UINT32)
1576 (((IMG_UINT64)(psRCParams->BufferSize) * (IMG_UINT64) 90000)
1577 / (IMG_UINT64) psRCParams->BitsPerSecond);
1578 }
1579 return ;
1580 }
1581
pnw__setup_qpvalue_h264(MTX_CURRENT_IN_PARAMS * psCurrent,IMG_BYTE bySliceQP)1582 static void pnw__setup_qpvalue_h264(
1583 MTX_CURRENT_IN_PARAMS * psCurrent,
1584 IMG_BYTE bySliceQP)
1585 {
1586 /* H.264 QP scaling tables */
1587 IMG_BYTE HOST_PVR_QP_SCALE_CR[52] = {
1588 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11,
1589 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27,
1590 28, 29, 29, 30, 31, 32, 32, 33, 34, 34, 35, 35, 36, 36, 37, 37,
1591 37, 38, 38, 38, 39, 39, 39, 39
1592 };
1593
1594 psCurrent->bySliceQP = bySliceQP;
1595 psCurrent->bySliceQPC = HOST_PVR_QP_SCALE_CR[psCurrent->bySliceQP];
1596 }
1597
1598
pnw__setup_qpvalues_mpeg4(MTX_CURRENT_IN_PARAMS * psCurrent,IMG_BYTE bySliceQP)1599 static void pnw__setup_qpvalues_mpeg4(
1600 MTX_CURRENT_IN_PARAMS * psCurrent,
1601 IMG_BYTE bySliceQP)
1602 {
1603 psCurrent->bySliceQP = bySliceQP;
1604 }
1605
pnw__setup_slice_row_params(context_ENC_p ctx,IMG_BOOL IsIntra,IMG_UINT16 CurrentRowY,IMG_INT16 SliceStartRowY,IMG_INT16 SliceHeight,IMG_BOOL VectorsValid,int bySliceQP)1606 static void pnw__setup_slice_row_params(
1607 context_ENC_p ctx,
1608 IMG_BOOL IsIntra,
1609 IMG_UINT16 CurrentRowY,
1610 IMG_INT16 SliceStartRowY,
1611 IMG_INT16 SliceHeight,
1612 IMG_BOOL VectorsValid,
1613 int bySliceQP)
1614 {
1615 /* Note: CurrentRowY and SliceStartRowY are now in pixels (not MacroBlocks)
1616 * - saves needless multiplications and divisions
1617 */
1618 MTX_CURRENT_IN_PARAMS *psCurrent;
1619 pnw_cmdbuf_p cmdbuf = ctx->obj_context->pnw_cmdbuf;
1620
1621 IMG_INT16 iPos, iYPos, srcY;
1622 IMG_UINT16 ui16tmp;
1623 IMG_UINT16 ui16SearchWidth, ui16SearchHeight, ui16SearchLeftOffset, ui16SearchTopOffset, ui16CurBlockX;
1624
1625 if (IsIntra && cmdbuf->topaz_in_params_I_p == NULL) {
1626 VAStatus vaStatus = psb_buffer_map(cmdbuf->topaz_in_params_I, &cmdbuf->topaz_in_params_I_p);
1627 if (vaStatus != VA_STATUS_SUCCESS) {
1628 drv_debug_msg(VIDEO_DEBUG_ERROR, "map topaz MTX_CURRENT_IN_PARAMS failed\n");
1629 return;
1630 }
1631 }
1632
1633 if ((!IsIntra) && cmdbuf->topaz_in_params_P_p == NULL) {
1634 VAStatus vaStatus = psb_buffer_map(cmdbuf->topaz_in_params_P, &cmdbuf->topaz_in_params_P_p);
1635 if (vaStatus != VA_STATUS_SUCCESS) {
1636 drv_debug_msg(VIDEO_DEBUG_ERROR, "map topaz MTX_CURRENT_IN_PARAMS failed\n");
1637 return;
1638 }
1639 }
1640
1641 if (IsIntra)
1642 psCurrent = (MTX_CURRENT_IN_PARAMS*)(cmdbuf->topaz_in_params_I_p + ctx->in_params_ofs);
1643 else
1644 psCurrent = (MTX_CURRENT_IN_PARAMS*)(cmdbuf->topaz_in_params_P_p + ctx->in_params_ofs);
1645
1646 psCurrent += (CurrentRowY * (ctx->Width) / 256);
1647
1648 // Note: CurrentRowY and iSliceStartRowY are now in pixels (not MacroBlocks) - saves needless multiplications and divisions
1649
1650 ui16SearchHeight = min(MVEA_LRB_SEARCH_HEIGHT, ctx->Height);
1651 ui16SearchWidth = min(MVEA_LRB_SEARCH_WIDTH, ctx->Width);
1652 ui16SearchLeftOffset = (((ui16SearchWidth / 2) / 16) * 16); // this is the amount of data that gets preloaded
1653 ui16SearchTopOffset = (((ui16SearchHeight / 2) / 16) * 16);
1654 ui16CurBlockX = MVEA_LRB_SEARCH_WIDTH - (ui16SearchLeftOffset + 16); // this is our block position relative to the start of the LRB
1655
1656 if ((iYPos = srcY = CurrentRowY - ui16SearchTopOffset) < 0)
1657 srcY = 0;
1658 else if (iYPos > ctx->HeightMinusLRB_TopAndBottom_OffsetsPlus16)
1659 srcY = ctx->HeightMinusLRBSearchHeight;
1660
1661
1662 /*DDK 243 removed this block of code.*/
1663 /*if((ctx->eCodec==IMG_CODEC_H263_NO_RC)||(ctx->eCodec==IMG_CODEC_H263_CBR)||(ctx->eCodec==IMG_CODEC_H263_VBR))
1664 ui16tmp = CurrentRowY;
1665 else*/
1666 ui16tmp = (CurrentRowY != SliceStartRowY);
1667
1668 for (iPos = 0; iPos < ctx->Width; iPos += 16, psCurrent++) {
1669 memset(psCurrent, 0, sizeof(MTX_CURRENT_IN_PARAMS));
1670 psCurrent->MVValid = 0;
1671 psCurrent->ParamsValid = 0;
1672
1673 if (SliceStartRowY) {
1674 psCurrent->MVValid = VECTORS_ABOVE_VALID;
1675 }
1676 /* Setup the parameters and motion vectors*/
1677 if (ui16tmp) {
1678 psCurrent->MVValid = VECTORS_ABOVE_VALID | DO_INTRA_PRED;
1679 psCurrent->ParamsValid |= PARAMS_ABOVE_VALID;
1680
1681 if (iPos + 16 < ctx->Width) {
1682 psCurrent->ParamsValid |= PARAMS_ABOVER_VALID;
1683 psCurrent->MVValid |= /*VECTORS_LEFT_VALID; //*/(1 << 2); /* Vectors left valid define looks wrong*/
1684 }
1685
1686 if (iPos > 0 && (iPos < ctx->Width)) {
1687 psCurrent->ParamsValid |= PARAMS_ABOVEL_VALID;
1688 psCurrent->MVValid |= VECTORS_ABOVE_LEFT_VALID; //(1<<0)
1689 }
1690 } else {
1691 // are we the first MB in a new slice?
1692 if (iPos == 0) {
1693 if ((ctx->eCodec == IMG_CODEC_H263_NO_RC) || (ctx->eCodec == IMG_CODEC_H263_CBR) || (ctx->eCodec == IMG_CODEC_H263_VBR)) {
1694 if (iYPos == -ui16SearchTopOffset)
1695 psCurrent->ParamsValid |= MB_START_OF_SLICE;// OPTI?
1696 } else {
1697 psCurrent->ParamsValid |= MB_START_OF_SLICE;// OPTI?
1698 }
1699 }
1700 }
1701 /*DDK 243 removed this block of code.*/
1702 /*if((ctx->eCodec==IMG_CODEC_H263_NO_RC) || (ctx->eCodec==IMG_CODEC_H263_CBR)||(ctx->eCodec==IMG_CODEC_H263_VBR))
1703 {
1704 // clear the above params valid bits
1705 psCurrent->ParamsValid &=~(PARAMS_ABOVEL_VALID|PARAMS_ABOVER_VALID|PARAMS_ABOVE_VALID); // OPTI
1706 }*/
1707 // Have to fill in the right hand row of 4x4 vectors into the the left block
1708 if (iPos) {
1709 psCurrent->MVValid |= DO_INTRA_PRED | (1 << 3); /*MV_VALID define looks wrong?! so use hard coded value for now*/
1710 psCurrent->ParamsValid |= 8; //(1<<3)
1711 }
1712 if (iPos == ctx->Width - 16) {
1713 // indicate the last MB in a row
1714 psCurrent->ParamsValid |= MB_END_OF_ROW;
1715 // are we the last mb in the slice?
1716 if (iYPos == (SliceStartRowY + SliceHeight - (ui16SearchTopOffset + 16))) {
1717 psCurrent->ParamsValid |= MB_END_OF_SLICE;
1718 if (iYPos == ctx->HeightMinus16MinusLRBTopOffset) {
1719 psCurrent->ParamsValid |= MB_END_OF_PICTURE;
1720 }
1721 }
1722 }
1723 // And now the below block
1724 // should do some kind of check to see if we are the first inter block, as otherwise the vectors will be invalid!
1725 if (VectorsValid) {
1726 if (iYPos < ctx->HeightMinus16MinusLRBTopOffset) {
1727 psCurrent->MVValid |= VECTORS_BELOW_VALID; //(1<<4)
1728
1729 if (iYPos < ctx->HeightMinus32MinusLRBTopOffset) {
1730 psCurrent->MVValid |= VECTORS_2BELOW_VALID; //(1<<5)
1731 }
1732 }
1733 }
1734
1735 /*Set up IPEMin and Max for coordinate X in the search reference region*/
1736 /*And set up flags in SPEMax when needed*/
1737 if (iPos <= ui16SearchLeftOffset) {
1738 psCurrent->IPEMin[0] = ui16CurBlockX - iPos;
1739 psCurrent->RealEdge |= SPE_EDGE_LEFT;
1740 } else {
1741 psCurrent->IPEMin[0] = ui16CurBlockX / 16;
1742 }
1743
1744 if ((iPos + ui16SearchLeftOffset + 16) > ctx->Width) {
1745 psCurrent->IPEMax[0] = (ui16CurBlockX - 1 + ctx->Width) - iPos; //(112 - 1) - ((iPos + 48+16) - ctx->psVideo->ui16Width);
1746 psCurrent->RealEdge |= SPE_EDGE_RIGHT;
1747 } else {
1748 psCurrent->IPEMax[0] = (ui16CurBlockX + 16 + ui16SearchLeftOffset) - 1 - 3; //(112 - 1) - 3;
1749 }
1750
1751 /*Set up IPEMin and Max for Y coordinate in the search reference region*/
1752 /*And set up flags in SPEMax when needed*/
1753 if (iYPos <= 0) {
1754 psCurrent->IPEMin[1] = 0;
1755 psCurrent->RealEdge |= SPE_EDGE_TOP;
1756 } else {
1757 psCurrent->IPEMin[1] = 3;
1758 }
1759
1760 //Max Y
1761 if (iYPos > ctx->HeightMinusLRB_TopAndBottom_OffsetsPlus16) {
1762 psCurrent->IPEMax[1] = ui16SearchHeight - 1;
1763 psCurrent->RealEdge |= ui16SearchHeight - 4;
1764 } else {
1765 psCurrent->IPEMax[1] = ui16SearchHeight - 4;
1766 }
1767
1768 psCurrent->CurBlockAddr = ((ui16CurBlockX) / 16);
1769 psCurrent->CurBlockAddr |= ((IMG_UINT8)(((iYPos + ui16SearchTopOffset) - srcY) / 16) << 4);
1770
1771 /* Setup the control register values
1772 These will get setup and transferred to a different location within the macroblock parameter structure.
1773 They are then read out of the esb by the mtx and used to control the hardware units
1774 */
1775 psCurrent->IPEControl = ctx->IPEControl;
1776
1777 switch (ctx->eCodec) {
1778 case IMG_CODEC_H263_NO_RC:
1779 case IMG_CODEC_H263_VBR:
1780 case IMG_CODEC_H263_CBR:
1781 pnw__setup_qpvalues_mpeg4(psCurrent, bySliceQP);
1782 psCurrent->JMCompControl = F_ENCODE(2, MVEA_CR_JMCOMP_MODE);
1783 psCurrent->VLCControl = F_ENCODE(3, TOPAZ_VLC_CR_CODEC) | F_ENCODE(IsIntra ? 0 : 1, TOPAZ_VLC_CR_SLICE_CODING_TYPE);
1784 break;
1785 case IMG_CODEC_MPEG4_NO_RC:
1786 case IMG_CODEC_MPEG4_VBR:
1787 case IMG_CODEC_MPEG4_CBR:
1788 pnw__setup_qpvalues_mpeg4(psCurrent, bySliceQP);
1789 psCurrent->JMCompControl = F_ENCODE(1, MVEA_CR_JMCOMP_MODE) | F_ENCODE(1, MVEA_CR_JMCOMP_AC_ENABLE);
1790 psCurrent->VLCControl = F_ENCODE(2, TOPAZ_VLC_CR_CODEC) | F_ENCODE(IsIntra ? 0 : 1, TOPAZ_VLC_CR_SLICE_CODING_TYPE);
1791 break;
1792 default:
1793 case IMG_CODEC_H264_NO_RC:
1794 case IMG_CODEC_H264_VBR:
1795 case IMG_CODEC_H264_CBR:
1796 case IMG_CODEC_H264_VCM:
1797 pnw__setup_qpvalue_h264(psCurrent, bySliceQP);
1798 psCurrent->JMCompControl = F_ENCODE(0, MVEA_CR_JMCOMP_MODE);
1799 psCurrent->VLCControl = F_ENCODE(1, TOPAZ_VLC_CR_CODEC) | F_ENCODE(IsIntra ? 0 : 1, TOPAZ_VLC_CR_SLICE_CODING_TYPE);
1800 break;
1801 }
1802 }
1803
1804 // now setup the dummy end of frame macroblock.
1805 if ((CurrentRowY + 16) >= ctx->Height) {
1806 memset(psCurrent, 0, sizeof(MTX_CURRENT_IN_PARAMS));
1807 psCurrent->MVValid = DO_INTRA_PRED;
1808 psCurrent->ParamsValid = 0;
1809 psCurrent->RealEdge = 0;
1810 }
1811 }
1812
pnw_setup_slice_params(context_ENC_p ctx,IMG_UINT16 YSliceStartPos,IMG_UINT16 SliceHeight,IMG_BOOL IsIntra,IMG_BOOL VectorsValid,int bySliceQP)1813 void pnw_setup_slice_params(
1814 context_ENC_p ctx,
1815 IMG_UINT16 YSliceStartPos,
1816 IMG_UINT16 SliceHeight,
1817 IMG_BOOL IsIntra,
1818 IMG_BOOL VectorsValid,
1819 int bySliceQP)
1820 {
1821 IMG_UINT16 Rows, CurrentRowY;
1822
1823 Rows = SliceHeight / 16;
1824 CurrentRowY = YSliceStartPos;
1825
1826 while (Rows) {
1827 pnw__setup_slice_row_params(
1828 ctx,
1829 IsIntra,
1830 CurrentRowY,
1831 YSliceStartPos,
1832 SliceHeight,
1833 VectorsValid, bySliceQP);
1834
1835 CurrentRowY += 16;
1836 Rows--;
1837 }
1838
1839 }
1840
1841
1842
pnw__send_encode_slice_params(context_ENC_p ctx,IMG_BOOL IsIntra,IMG_UINT16 CurrentRow,IMG_UINT8 DeblockIDC,IMG_UINT32 FrameNum,IMG_UINT16 SliceHeight,IMG_UINT16 CurrentSlice)1843 IMG_UINT32 pnw__send_encode_slice_params(
1844 context_ENC_p ctx,
1845 IMG_BOOL IsIntra,
1846 IMG_UINT16 CurrentRow,
1847 IMG_UINT8 DeblockIDC,
1848 IMG_UINT32 FrameNum,
1849 IMG_UINT16 SliceHeight,
1850 IMG_UINT16 CurrentSlice)
1851 {
1852 SLICE_PARAMS *psSliceParams;
1853 IMG_INT16 RowOffset;
1854 IMG_UINT16 SearchHeight, SearchTopOffset;
1855
1856 psb_buffer_p psCoded;
1857 object_surface_p ref_surface;
1858 psb_buffer_p psRef;
1859 pnw_cmdbuf_p cmdbuf = ctx->obj_context->pnw_cmdbuf;
1860
1861
1862 drv_debug_msg(VIDEO_DEBUG_GENERAL, "Send encode slice parmas, Is Intra:%d, CurrentRow:%d" \
1863 "DeblockIDC:%d, FrameNum:%d, SliceHeight:%d, CurrentSlice:%d\n",
1864 IsIntra, CurrentRow, DeblockIDC, FrameNum, SliceHeight, CurrentSlice);
1865
1866 ref_surface = ctx->ref_surface;
1867 psRef = &ctx->ref_surface->psb_surface->buf;
1868 psCoded = ctx->coded_buf->psb_buffer;
1869
1870 psSliceParams = (SLICE_PARAMS *)(cmdbuf->slice_params_p +
1871 CurrentSlice * ((sizeof(SLICE_PARAMS) + 15) & 0xfff0));
1872
1873 psSliceParams->SliceHeight = SliceHeight;
1874 psSliceParams->SliceStartRowNum = CurrentRow / 16;
1875 psSliceParams->ScanningIntraParams = (1 << SCANNING_INTRA_WIDTH_SHIFT) |
1876 (1 << SCANNING_INTRA_STEP_SHIFT);
1877
1878 /* We want multiple ones of these so we can submit multiple slices without having to wait for the next */
1879 psSliceParams->Flags = 0;
1880 psSliceParams->HostCtx = 0xdafed123;
1881
1882 #ifdef VA_EMULATOR
1883 psSliceParams->RefYStride = ref_surface->psb_surface->stride;
1884 psSliceParams->RefUVStride = ref_surface->psb_surface->stride;
1885 psSliceParams->RefYRowStride = ref_surface->psb_surface->stride * 16;
1886 psSliceParams->RefUVRowStride = ref_surface->psb_surface->stride * 16 / 2;
1887 #else
1888 psSliceParams->RefYStride = ref_surface->psb_surface->stride;
1889 psSliceParams->RefUVStride = ref_surface->psb_surface->stride;
1890 psSliceParams->RefYRowStride = ref_surface->psb_surface->stride * 16;
1891 psSliceParams->RefUVRowStride = ref_surface->psb_surface->stride * 16 / 2;
1892 #endif
1893 psSliceParams->NumAirMBs = ctx->num_air_mbs;
1894 psSliceParams->AirThreshold = ctx->air_threshold;
1895
1896 if (ctx->eCodec == IMG_CODEC_H264_VCM && ctx->max_slice_size == 0)
1897 psSliceParams->MaxSliceSize = ctx->Width * ctx->Height * 12 / 2;
1898 else
1899 psSliceParams->MaxSliceSize = ctx->max_slice_size;
1900 psSliceParams->FCode = ctx->FCode;/* Not clear yet, This field is not appare in firmware doc */
1901
1902 SearchHeight = min(MVEA_LRB_SEARCH_HEIGHT, ctx->Height);
1903 SearchTopOffset = (((SearchHeight / 2) / 16) * 16);
1904
1905 RowOffset = CurrentRow - SearchTopOffset;
1906 if (RowOffset <= 0)
1907 RowOffset = 0;
1908 if (RowOffset > (ctx->Height - SearchHeight))
1909 RowOffset = (ctx->Height - SearchHeight);
1910 if (!IsIntra) {
1911 psSliceParams->Flags |= ISINTER_FLAGS;
1912 }
1913
1914 switch (DeblockIDC) {
1915 case 0:
1916 psSliceParams->Flags |= DEBLOCK_FRAME;
1917 break;
1918 case 2:
1919 psSliceParams->Flags |= DEBLOCK_SLICE;
1920 break;
1921 case 1:
1922 default:
1923 // do nothing
1924 break;
1925 }
1926
1927 switch (ctx->eCodec) {
1928 case IMG_CODEC_H263_NO_RC:
1929 case IMG_CODEC_H263_VBR:
1930 case IMG_CODEC_H263_CBR:
1931 psSliceParams->Flags |= ISH263_FLAGS;
1932 break;
1933 case IMG_CODEC_MPEG4_NO_RC:
1934 case IMG_CODEC_MPEG4_VBR:
1935 case IMG_CODEC_MPEG4_CBR:
1936 psSliceParams->Flags |= ISMPEG4_FLAGS;
1937 break;
1938 case IMG_CODEC_H264_NO_RC:
1939 case IMG_CODEC_H264_CBR:
1940 case IMG_CODEC_H264_VCM:
1941 case IMG_CODEC_H264_VBR:
1942 psSliceParams->Flags |= ISH264_FLAGS;
1943 break;
1944 default:
1945 psSliceParams->Flags |= ISH264_FLAGS;
1946 printf("No format specified defaulting to h.264\n");
1947 break;
1948 }
1949 /* we should also setup the interleaving requirements based on the source format */
1950 if (ctx->eFormat == IMG_CODEC_PL12) /* FIXME contrary with old DDK, take notice */
1951 psSliceParams->Flags |= INTERLEAVE_TARGET;
1952
1953 cmdbuf = ctx->obj_context->pnw_cmdbuf;
1954
1955 RELOC_SLICE_PARAMS_PNW(&(psSliceParams->RefYBase), 256 * RowOffset / 16, psRef);
1956 RELOC_SLICE_PARAMS_PNW(&(psSliceParams->RefUVBase),
1957 ref_surface->psb_surface->stride * ref_surface->height + (RowOffset * 128 / 16),
1958 psRef);
1959 if (IsIntra)
1960 RELOC_SLICE_PARAMS_PNW(&(psSliceParams->InParamsBase),
1961 ctx->in_params_ofs,
1962 //((CurrentRow * (ctx->Width)) / 256 + ctx->obj_context->slice_count) * sizeof(MTX_CURRENT_IN_PARAMS),
1963 cmdbuf->topaz_in_params_I);
1964 else
1965 RELOC_SLICE_PARAMS_PNW(&(psSliceParams->InParamsBase),
1966 ctx->in_params_ofs,
1967 //((CurrentRow * (ctx->Width)) / 256 + ctx->obj_context->slice_count) * sizeof(MTX_CURRENT_IN_PARAMS),
1968 cmdbuf->topaz_in_params_P);
1969
1970 #if TOPAZ_PIC_PARAMS_VERBOSE
1971 drv_debug_msg(VIDEO_DEBUG_GENERAL, "sizeof psSliceParams %d\n", sizeof(*psSliceParams));
1972 drv_debug_msg(VIDEO_DEBUG_GENERAL, "sizeof MTX_CURRENT_IN_PARAMS %d\n", sizeof(MTX_CURRENT_IN_PARAMS));
1973 drv_debug_msg(VIDEO_DEBUG_GENERAL, "psSliceParams->SliceStartRowNum %d\n", psSliceParams->SliceStartRowNum);
1974 drv_debug_msg(VIDEO_DEBUG_GENERAL, "psSliceParams->SliceHeight %d\n", psSliceParams->SliceHeight);
1975 drv_debug_msg(VIDEO_DEBUG_GENERAL, "psSliceParams->RefYBase %x\n", psSliceParams->RefYBase);
1976 drv_debug_msg(VIDEO_DEBUG_GENERAL, "psSliceParams->RefUVBase %x\n", psSliceParams->RefUVBase);
1977 drv_debug_msg(VIDEO_DEBUG_GENERAL, "psSliceParams->RefYStride %d\n", psSliceParams->RefYStride);
1978 drv_debug_msg(VIDEO_DEBUG_GENERAL, "psSliceParams->RefUVStride %d\n", psSliceParams->RefUVStride);
1979 drv_debug_msg(VIDEO_DEBUG_GENERAL, "psSliceParams->RefYRowStride %d\n", psSliceParams->RefYRowStride);
1980 drv_debug_msg(VIDEO_DEBUG_GENERAL, "psSliceParams->RefUVRowStride %d\n", psSliceParams->RefUVRowStride);
1981 drv_debug_msg(VIDEO_DEBUG_GENERAL, "psSliceParams->HostCtx %x\n", psSliceParams->HostCtx);
1982 drv_debug_msg(VIDEO_DEBUG_GENERAL, "psSliceParams->Flags %x\n", psSliceParams->Flags);
1983 drv_debug_msg(VIDEO_DEBUG_GENERAL, "psSliceParams->MaxSliceSize %d\n", psSliceParams->MaxSliceSize);
1984 drv_debug_msg(VIDEO_DEBUG_GENERAL, "psSliceParams->FCode %x\n", psSliceParams->FCode);
1985 drv_debug_msg(VIDEO_DEBUG_GENERAL, "psSliceParams->InParamsBase %x\n", psSliceParams->InParamsBase);
1986 drv_debug_msg(VIDEO_DEBUG_GENERAL, "psSliceParams->NumAirMBs %d\n", psSliceParams->NumAirMBs);
1987 drv_debug_msg(VIDEO_DEBUG_GENERAL, "psSliceParams->AirThreshold %x\n", psSliceParams->AirThreshold);
1988 drv_debug_msg(VIDEO_DEBUG_GENERAL, "psSliceParams->ScanningIntraParams %x\n", psSliceParams->ScanningIntraParams);
1989 #endif
1990
1991 pnw_cmdbuf_insert_command_package(ctx->obj_context,
1992 ctx->SliceToCore,
1993 MTX_CMDID_ENCODE_SLICE,
1994 &cmdbuf->slice_params,
1995 CurrentSlice *((sizeof(SLICE_PARAMS) + 15) & 0xfff0));
1996
1997
1998 return 0;
1999 }
2000
2001
2002
2003 /*
2004 * Function Name : Reset_EncoderParams
2005 * Description : Reset Above & Below Params at the Start of Intra frame
2006 */
pnw_reset_encoder_params(context_ENC_p ctx)2007 void pnw_reset_encoder_params(context_ENC_p ctx)
2008 {
2009 unsigned char *Add_Below, *Add_Above;
2010 pnw_cmdbuf_p cmdbuf = ctx->obj_context->pnw_cmdbuf;
2011
2012 /* all frames share the same Topaz param, in_param/aboveparam/bellow
2013 * map it only when necessary
2014 */
2015 if (cmdbuf->topaz_above_params_p == NULL) {
2016 VAStatus vaStatus = psb_buffer_map(cmdbuf->topaz_above_params, &cmdbuf->topaz_above_params_p);
2017 if (vaStatus != VA_STATUS_SUCCESS) {
2018 drv_debug_msg(VIDEO_DEBUG_ERROR, "map topaz MTX_CURRENT_IN_PARAMS failed\n");
2019 return;
2020 }
2021 }
2022
2023 if (cmdbuf->topaz_below_params_p == NULL) {
2024 VAStatus vaStatus = psb_buffer_map(cmdbuf->topaz_below_params, &cmdbuf->topaz_below_params_p);
2025 if (vaStatus != VA_STATUS_SUCCESS) {
2026 drv_debug_msg(VIDEO_DEBUG_ERROR, "map topaz MTX_CURRENT_IN_PARAMS failed\n");
2027 return;
2028 }
2029 }
2030
2031 Add_Below = cmdbuf->topaz_below_params_p +
2032 ctx->below_params_ofs;
2033
2034 memset(Add_Below, 0, ctx->below_params_size * 4);
2035
2036 Add_Above = cmdbuf->topaz_above_params_p + ctx->above_params_ofs;
2037 memset(Add_Above, 0, ctx->above_params_size * MAX_TOPAZ_CORES);
2038 }
2039
2040
2041
2042