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