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  *    Edward Lin <edward.lin@intel.com>
27  *
28  */
29 
30 #include <unistd.h>
31 #include <stdio.h>
32 #include <memory.h>
33 #include <wsbm/wsbm_manager.h>
34 #include "tng_picmgmt.h"
35 #include "psb_drv_debug.h"
36 
37 #define MASK_TOPAZHP_CR_H264COMP_CUSTOM_QUANT_Q_0 0x0000007F
38 #define SHIFT_TOPAZHP_CR_H264COMP_CUSTOM_QUANT_Q_0 0
39 #define MASK_TOPAZHP_CR_H264COMP_CUSTOM_QUANT_Q_1 0x00007F00
40 #define SHIFT_TOPAZHP_CR_H264COMP_CUSTOM_QUANT_Q_1 8
41 #define MASK_TOPAZHP_CR_H264COMP_CUSTOM_QUANT_Q_2 0x007F0000
42 #define SHIFT_TOPAZHP_CR_H264COMP_CUSTOM_QUANT_Q_2 16
43 #define MASK_TOPAZHP_CR_H264COMP_CUSTOM_QUANT_Q_3 0x7F000000
44 #define SHIFT_TOPAZHP_CR_H264COMP_CUSTOM_QUANT_Q_3 24
45 
46 #define MASK_TOPAZHP_CR_H264COMP_CUSTOM_QUANT_SP_0 0x00003FFF
47 #define SHIFT_TOPAZHP_CR_H264COMP_CUSTOM_QUANT_SP_0 0
48 #define MASK_TOPAZHP_CR_H264COMP_CUSTOM_QUANT_SP_1 0x3FFF0000
49 #define SHIFT_TOPAZHP_CR_H264COMP_CUSTOM_QUANT_SP_1 16
50 
51 /************************* MTX_CMDID_PICMGMT *************************/
tng_picmgmt_update(context_ENC_p ctx,IMG_PICMGMT_TYPE eType,unsigned int ref)52 VAStatus tng_picmgmt_update(context_ENC_p ctx, IMG_PICMGMT_TYPE eType, unsigned int ref)
53 {
54     //VAStatus vaStatus = VA_STATUS_SUCCESS;
55     IMG_UINT32 ui32CmdData = 0;
56 
57     //IMG_V_SetNextRefType  eFrameType
58     //IMG_V_SkipFrame       bProcess
59     //IMG_V_EndOfStream     ui32FrameCount
60     //IMG_PICMGMT_FLUSH     ui32FrameCount
61     ui32CmdData = F_ENCODE(eType, MTX_MSG_PICMGMT_SUBTYPE) |
62         F_ENCODE(ref, MTX_MSG_PICMGMT_DATA);
63 
64     /* Send PicMgmt Command */
65     tng_cmdbuf_insert_command(ctx->obj_context, ctx->ui32StreamID,
66         MTX_CMDID_PICMGMT | MTX_CMDID_PRIORITY,
67         ui32CmdData, 0, 0);
68 
69     return VA_STATUS_SUCCESS;
70 }
71 
72 /*!
73 ******************************************************************************
74 *
75 * Picture management functions
76 *
77 ******************************************************************************/
tng__picmgmt_long_term_refs(context_ENC_p __maybe_unused ctx,IMG_UINT32 __maybe_unused ui32FrameNum)78 void tng__picmgmt_long_term_refs(context_ENC_p __maybe_unused ctx, IMG_UINT32 __maybe_unused ui32FrameNum)
79 {
80 #ifdef _TNG_ENABLE_PITMGMT_
81     IMG_BOOL                bIsLongTermRef;
82     IMG_BOOL                bUsesLongTermRef0;
83     IMG_BOOL                bUsesLongTermRef1;
84     IMG_UINT32              ui32FrameCnt;
85 
86     // Determine frame position in source stream
87     // This assumes there are no IDR frames after the first one
88     if (ui32FrameNum == 0) {
89         // Initial IDR frame
90         ui32FrameCnt = 0;
91     } else if (((ui32FrameNum - 1) % (ctx->sRCParams.ui16BFrames + 1)) == 0) {
92         // I or P frame
93         ui32FrameCnt = ui32FrameNum + ctx->sRCParams.ui16BFrames;
94         if (ui32FrameCnt >= ctx->ui32Framecount) ui32FrameCnt = ctx->ui32Framecount - 1;
95     } else {
96         // B frame
97         // This will be incorrect for hierarchical B-pictures
98         ui32FrameCnt = ui32FrameNum - 1;
99     }
100 
101     // Decide if the current frame should be used as a long-term reference
102     bIsLongTermRef = ctx->ui32LongTermRefFreq ?
103                      (ui32FrameCnt % ctx->ui32LongTermRefFreq == 0) :
104                      IMG_FALSE;
105 
106     // Decide if the current frame should refer to a long-term reference
107     bUsesLongTermRef0 = ctx->ui32LongTermRefUsageFreq ?
108                         (ui32FrameCnt % ctx->ui32LongTermRefUsageFreq == ctx->ui32LongTermRefUsageOffset) :
109                         IMG_FALSE;
110     bUsesLongTermRef1 = IMG_FALSE;
111 
112     if (bIsLongTermRef || bUsesLongTermRef0 || bUsesLongTermRef1) {
113         // Reconstructed/reference frame to be written to host buffer
114         // Send the buffer to be used as reference
115         tng__send_ref_frames(ctx, 0, bIsLongTermRef);
116         if (bIsLongTermRef) ctx->byCurBufPointer = (ctx->byCurBufPointer + 1) % 3;
117     }
118 #endif
119 }
120 
tng__H264ES_CalcCustomQuantSp(IMG_UINT8 list,IMG_UINT8 param,IMG_UINT8 customQuantQ)121 static VAStatus tng__H264ES_CalcCustomQuantSp(IMG_UINT8 list, IMG_UINT8 param, IMG_UINT8 customQuantQ)
122 {
123     // Derived from sim/topaz/testbench/tests/mved1_tests.c
124     IMG_UINT32 mfflat[2][16] = {
125         {
126             13107, 8066,   13107,  8066,
127             8066,   5243,   8066,   5243,
128             13107,  8066,   13107,  8066,
129             8066,   5243,   8066,   5243
130         }, // 4x4
131         {
132             13107, 12222,  16777,  12222,
133             12222,  11428,  15481,  11428,
134             16777,  15481,  20972,  15481,
135             12222,  11428,  15481,  11428
136         } // 8x8
137     };
138     IMG_UINT8 uVi[2][16] = {
139         {
140             20, 26,  20,  26,
141             26,  32,  26,  32,
142             20,  26,  20,  26,
143             26,  32,  26,  32
144         }, // 4x4
145         {
146             20, 19,  25,  19,
147             19,  18,  24,  18,
148             25,  24,  32,  24,
149             19,  18,  24,  18
150         } // 8x8
151     };
152 
153     int mfnew;
154     double fSp;
155     int uSp;
156 
157     if (customQuantQ == 0) customQuantQ = 1;
158     mfnew = (mfflat[list][param] * 16) / customQuantQ;
159     fSp = ((double)(mfnew * uVi[list][param])) / (double)(1 << 22);
160     fSp = (fSp * 100000000.0f) / 100000000.0f;
161     uSp = (IMG_UINT16)(fSp * 65536);
162 
163     return uSp & 0x03FFF;
164 }
165 
166 
tng__set_custom_scaling_values(context_ENC_p ctx,IMG_UINT8 * aui8Sl4x4IntraY,IMG_UINT8 * aui8Sl4x4IntraCb,IMG_UINT8 * aui8Sl4x4IntraCr,IMG_UINT8 * aui8Sl4x4InterY,IMG_UINT8 * aui8Sl4x4InterCb,IMG_UINT8 * aui8Sl4x4InterCr,IMG_UINT8 * aui8Sl8x8IntraY,IMG_UINT8 * aui8Sl8x8InterY)167 static VAStatus tng__set_custom_scaling_values(
168     context_ENC_p ctx,
169     IMG_UINT8* aui8Sl4x4IntraY,
170     IMG_UINT8* aui8Sl4x4IntraCb,
171     IMG_UINT8* aui8Sl4x4IntraCr,
172     IMG_UINT8* aui8Sl4x4InterY,
173     IMG_UINT8* aui8Sl4x4InterCb,
174     IMG_UINT8* aui8Sl4x4InterCr,
175     IMG_UINT8* aui8Sl8x8IntraY,
176     IMG_UINT8* aui8Sl8x8InterY)
177 {
178     IMG_UINT8  *pui8QuantMem;
179     IMG_UINT32 *pui32QuantReg;
180     IMG_UINT8  *apui8QuantTables[8];
181     IMG_UINT32  ui32Table, ui32Val;
182     psb_buffer_p pCustomBuf = NULL;
183     IMG_UINT32  custom_quant_size = 0;
184 
185     // Scanning order for coefficients, see section 8.5.5 of H.264 specification
186     // Note that even for interlaced mode, hardware takes the scaling values as if frame zig-zag scanning were being used
187     IMG_UINT8 aui8ZigZagScan4x4[16] = {
188         0,  1,  5,  6,
189         2,  4,  7,  12,
190         3,  8,  11, 13,
191         9,  10, 14, 15
192     };
193     IMG_UINT8 aui8ZigZagScan8x8[64] = {
194         0,  1,  5,  6,  14, 15, 27, 28,
195         2,  4,  7,  13, 16, 26, 29, 42,
196         3,  8,  12, 17, 25, 30, 41, 43,
197         9,  11, 18, 24, 31, 40, 44, 53,
198         10, 19, 23, 32, 39, 45, 52, 54,
199         20, 22, 33, 38, 46, 51, 55, 60,
200         21, 34, 37, 47, 50, 56, 59, 61,
201         35, 36, 48, 49, 57, 58, 62, 63
202     };
203 
204 
205     if (ctx == NULL) {
206         return VA_STATUS_ERROR_UNKNOWN;
207     }
208 
209     if (ctx->bCustomScaling == IMG_FALSE) {
210         return VA_STATUS_ERROR_UNKNOWN;
211     }
212 
213     pCustomBuf = &(ctx->ctx_mem[ctx->ui32StreamID].bufs_custom_quant);
214     custom_quant_size = ctx->ctx_mem_size.custom_quant;
215 
216 
217     /* Copy quantization values (in header order) */
218     pui8QuantMem = (IMG_UINT8*)(pCustomBuf);
219     memcpy(pui8QuantMem, aui8Sl4x4IntraY, 16);
220     memcpy(pui8QuantMem + 16, aui8Sl4x4IntraCb, 16);
221     memcpy(pui8QuantMem + 32, aui8Sl4x4IntraCr, 16);
222     memcpy(pui8QuantMem + 48, aui8Sl4x4InterY, 16);
223     memcpy(pui8QuantMem + 64, aui8Sl4x4InterCb, 16);
224     memcpy(pui8QuantMem + 80, aui8Sl4x4InterCr, 16);
225     memcpy(pui8QuantMem + 96, aui8Sl8x8IntraY, 64);
226     memcpy(pui8QuantMem + 160, aui8Sl8x8InterY, 64);
227 
228     /* Create quantization register values */
229 
230     /* Assign based on the order values are written to registers */
231     apui8QuantTables[0] = aui8Sl4x4IntraY;
232     apui8QuantTables[1] = aui8Sl4x4InterY;
233     apui8QuantTables[2] = aui8Sl4x4IntraCb;
234     apui8QuantTables[3] = aui8Sl4x4InterCb;
235     apui8QuantTables[4] = aui8Sl4x4IntraCr;
236     apui8QuantTables[5] = aui8Sl4x4InterCr;
237     apui8QuantTables[6] = aui8Sl8x8IntraY;
238     apui8QuantTables[7] = aui8Sl8x8InterY;
239 
240     /* H264COMP_CUSTOM_QUANT_SP register values "psCustomQuantRegs4x4Sp"*/
241     pui8QuantMem = (IMG_UINT8*)(pCustomBuf + custom_quant_size);
242     pui32QuantReg = (IMG_UINT32 *)pui8QuantMem;
243     for (ui32Table = 0; ui32Table < 6; ui32Table++) {
244         for (ui32Val = 0; ui32Val < 16; ui32Val += 4) {
245             *pui32QuantReg = F_ENCODE(tng__H264ES_CalcCustomQuantSp(0, ui32Val, apui8QuantTables[ui32Table][aui8ZigZagScan4x4[ui32Val]]), TOPAZHP_CR_H264COMP_CUSTOM_QUANT_SP_0)
246                              | F_ENCODE(tng__H264ES_CalcCustomQuantSp(0, ui32Val + 1, apui8QuantTables[ui32Table][aui8ZigZagScan4x4[ui32Val + 1]]), TOPAZHP_CR_H264COMP_CUSTOM_QUANT_SP_1);
247             pui32QuantReg++;
248             *pui32QuantReg = F_ENCODE(tng__H264ES_CalcCustomQuantSp(0, ui32Val + 2, apui8QuantTables[ui32Table][aui8ZigZagScan4x4[ui32Val + 2]]), TOPAZHP_CR_H264COMP_CUSTOM_QUANT_SP_0)
249                              | F_ENCODE(tng__H264ES_CalcCustomQuantSp(0, ui32Val + 3, apui8QuantTables[ui32Table][aui8ZigZagScan4x4[ui32Val + 3]]), TOPAZHP_CR_H264COMP_CUSTOM_QUANT_SP_1);
250             pui32QuantReg++;
251         }
252     }
253 
254     /*psCustomQuantRegs8x8Sp*/
255     pui8QuantMem = (IMG_UINT8*)(pCustomBuf + custom_quant_size + custom_quant_size);
256     pui32QuantReg = (IMG_UINT32 *)pui8QuantMem;
257     for (; ui32Table < 8; ui32Table++) {
258         for (ui32Val = 0; ui32Val < 64; ui32Val += 8) {
259             *pui32QuantReg = F_ENCODE(tng__H264ES_CalcCustomQuantSp(1, ((ui32Val & 24) >> 1), apui8QuantTables[ui32Table][aui8ZigZagScan8x8[ui32Val]]), TOPAZHP_CR_H264COMP_CUSTOM_QUANT_SP_0)
260                              | F_ENCODE(tng__H264ES_CalcCustomQuantSp(1, ((ui32Val & 24) >> 1) + 1, apui8QuantTables[ui32Table][aui8ZigZagScan8x8[ui32Val + 1]]), TOPAZHP_CR_H264COMP_CUSTOM_QUANT_SP_1);
261             pui32QuantReg++;
262             *pui32QuantReg = F_ENCODE(tng__H264ES_CalcCustomQuantSp(1, ((ui32Val & 24) >> 1) + 2, apui8QuantTables[ui32Table][aui8ZigZagScan8x8[ui32Val + 2]]), TOPAZHP_CR_H264COMP_CUSTOM_QUANT_SP_0)
263                              | F_ENCODE(tng__H264ES_CalcCustomQuantSp(1, ((ui32Val & 24) >> 1) + 3, apui8QuantTables[ui32Table][aui8ZigZagScan8x8[ui32Val + 3]]), TOPAZHP_CR_H264COMP_CUSTOM_QUANT_SP_1);
264             pui32QuantReg++;
265             *pui32QuantReg = F_ENCODE(tng__H264ES_CalcCustomQuantSp(1, ((ui32Val & 24) >> 1), apui8QuantTables[ui32Table][aui8ZigZagScan8x8[ui32Val + 4]]), TOPAZHP_CR_H264COMP_CUSTOM_QUANT_SP_0)
266                              | F_ENCODE(tng__H264ES_CalcCustomQuantSp(1, ((ui32Val & 24) >> 1) + 1, apui8QuantTables[ui32Table][aui8ZigZagScan8x8[ui32Val + 5]]), TOPAZHP_CR_H264COMP_CUSTOM_QUANT_SP_1);
267             pui32QuantReg++;
268             *pui32QuantReg = F_ENCODE(tng__H264ES_CalcCustomQuantSp(1, ((ui32Val & 24) >> 1) + 2, apui8QuantTables[ui32Table][aui8ZigZagScan8x8[ui32Val + 6]]), TOPAZHP_CR_H264COMP_CUSTOM_QUANT_SP_0)
269                              | F_ENCODE(tng__H264ES_CalcCustomQuantSp(1, ((ui32Val & 24) >> 1) + 3, apui8QuantTables[ui32Table][aui8ZigZagScan8x8[ui32Val + 7]]), TOPAZHP_CR_H264COMP_CUSTOM_QUANT_SP_1);
270             pui32QuantReg++;
271         }
272     }
273 
274     /* H264COMP_CUSTOM_QUANT_Q register values "psCustomQuantRegs4x4Q" */
275     pui8QuantMem = (IMG_UINT8*)(pCustomBuf + custom_quant_size + custom_quant_size + custom_quant_size);
276     pui32QuantReg = (IMG_UINT32 *)pui8QuantMem;
277     for (ui32Table = 0; ui32Table < 6; ui32Table++) {
278         for (ui32Val = 0; ui32Val < 16; ui32Val += 4) {
279             *pui32QuantReg = F_ENCODE(apui8QuantTables[ui32Table][aui8ZigZagScan4x4[ui32Val]], TOPAZHP_CR_H264COMP_CUSTOM_QUANT_Q_0)
280                              | F_ENCODE(apui8QuantTables[ui32Table][aui8ZigZagScan4x4[ui32Val + 1]], TOPAZHP_CR_H264COMP_CUSTOM_QUANT_Q_1)
281                              | F_ENCODE(apui8QuantTables[ui32Table][aui8ZigZagScan4x4[ui32Val + 2]], TOPAZHP_CR_H264COMP_CUSTOM_QUANT_Q_2)
282                              | F_ENCODE(apui8QuantTables[ui32Table][aui8ZigZagScan4x4[ui32Val + 3]], TOPAZHP_CR_H264COMP_CUSTOM_QUANT_Q_3);
283             pui32QuantReg++;
284         }
285     }
286 
287     /*psCustomQuantRegs8x8Q)*/
288     pui8QuantMem = (IMG_UINT8*)(pCustomBuf + custom_quant_size + custom_quant_size + custom_quant_size + custom_quant_size);
289 
290     pui32QuantReg = (IMG_UINT32 *)pui8QuantMem;
291     for (; ui32Table < 8; ui32Table++) {
292         for (ui32Val = 0; ui32Val < 64; ui32Val += 8) {
293             *pui32QuantReg = F_ENCODE(apui8QuantTables[ui32Table][aui8ZigZagScan8x8[ui32Val]], TOPAZHP_CR_H264COMP_CUSTOM_QUANT_Q_0)
294                              | F_ENCODE(apui8QuantTables[ui32Table][aui8ZigZagScan8x8[ui32Val + 1]], TOPAZHP_CR_H264COMP_CUSTOM_QUANT_Q_1)
295                              | F_ENCODE(apui8QuantTables[ui32Table][aui8ZigZagScan8x8[ui32Val + 2]], TOPAZHP_CR_H264COMP_CUSTOM_QUANT_Q_2)
296                              | F_ENCODE(apui8QuantTables[ui32Table][aui8ZigZagScan8x8[ui32Val + 3]], TOPAZHP_CR_H264COMP_CUSTOM_QUANT_Q_3);
297             pui32QuantReg++;
298             *pui32QuantReg = F_ENCODE(apui8QuantTables[ui32Table][aui8ZigZagScan8x8[ui32Val + 4]], TOPAZHP_CR_H264COMP_CUSTOM_QUANT_Q_0)
299                              | F_ENCODE(apui8QuantTables[ui32Table][aui8ZigZagScan8x8[ui32Val + 5]], TOPAZHP_CR_H264COMP_CUSTOM_QUANT_Q_1)
300                              | F_ENCODE(apui8QuantTables[ui32Table][aui8ZigZagScan8x8[ui32Val + 6]], TOPAZHP_CR_H264COMP_CUSTOM_QUANT_Q_2)
301                              | F_ENCODE(apui8QuantTables[ui32Table][aui8ZigZagScan8x8[ui32Val + 7]], TOPAZHP_CR_H264COMP_CUSTOM_QUANT_Q_3);
302             pui32QuantReg++;
303         }
304     }
305 
306     if (ctx->bPpsScaling)
307         ctx->bInsertPicHeader = IMG_TRUE;
308 
309     return VA_STATUS_SUCCESS;
310 }
311 
312 
tng__picmgmt_custom_scaling(context_ENC_p ctx,IMG_UINT32 ui32FrameNum)313 void tng__picmgmt_custom_scaling(context_ENC_p ctx, IMG_UINT32 ui32FrameNum)
314 {
315     if (ui32FrameNum % ctx->ui32PpsScalingCnt == 0) {
316         // Swap inter and intra scaling lists on alternating picture parameter sets
317         if (ui32FrameNum % (ctx->ui32PpsScalingCnt * 2) == 0) {
318             tng__set_custom_scaling_values(
319                 ctx,
320                 ctx->aui8CustomQuantParams4x4[0],
321                 ctx->aui8CustomQuantParams4x4[1],
322                 ctx->aui8CustomQuantParams4x4[2],
323                 ctx->aui8CustomQuantParams4x4[3],
324                 ctx->aui8CustomQuantParams4x4[4],
325                 ctx->aui8CustomQuantParams4x4[5],
326                 ctx->aui8CustomQuantParams8x8[0],
327                 ctx->aui8CustomQuantParams8x8[1]);
328         } else {
329             tng__set_custom_scaling_values(
330                 ctx,
331                 ctx->aui8CustomQuantParams4x4[3],
332                 ctx->aui8CustomQuantParams4x4[4],
333                 ctx->aui8CustomQuantParams4x4[5],
334                 ctx->aui8CustomQuantParams4x4[0],
335                 ctx->aui8CustomQuantParams4x4[1],
336                 ctx->aui8CustomQuantParams4x4[2],
337                 ctx->aui8CustomQuantParams8x8[1],
338                 ctx->aui8CustomQuantParams8x8[0]);
339         }
340     }
341 }
342 
343 /************************* MTX_CMDID_PROVIDE_BUFFER *************************/
tng_send_codedbuf(context_ENC_p ctx,IMG_UINT32 ui32SlotIndex)344 IMG_UINT32 tng_send_codedbuf(
345     context_ENC_p ctx,
346     IMG_UINT32 ui32SlotIndex)
347 {
348     context_ENC_frame_buf *ps_buf = &(ctx->ctx_frame_buf);
349     object_buffer_p object_buffer  = ps_buf->coded_buf;
350     IMG_UINT32 ui32Offset = 0;
351 
352     drv_debug_msg(VIDEO_DEBUG_GENERAL,
353         "%s slot 1 = %x\n", __FUNCTION__, ui32SlotIndex);
354 
355     if ((ctx->ui8PipesToUse == 2) && ((ui32SlotIndex & 1) == 1))
356 	ui32Offset = object_buffer->size >> 1;
357 
358     tng_cmdbuf_insert_command(
359         ctx->obj_context, ctx->ui32StreamID,
360         MTX_CMDID_PROVIDE_CODED_BUFFER,
361         F_ENCODE(object_buffer->size, MTX_MSG_PROVIDE_CODED_BUFFER_SIZE) |
362         F_ENCODE(ui32SlotIndex, MTX_MSG_PROVIDE_CODED_BUFFER_SLOT),
363         object_buffer->psb_buffer, tng_align_KB(ui32Offset));
364 
365     drv_debug_msg(VIDEO_DEBUG_GENERAL, "%s end\n", __FUNCTION__);
366     return  VA_STATUS_SUCCESS;
367 }
368 
tng__set_component_offsets(context_ENC_p ctx,object_surface_p obj_surface_p,IMG_FRAME * psFrame)369 static VAStatus tng__set_component_offsets(
370     context_ENC_p ctx,
371     object_surface_p obj_surface_p,
372     IMG_FRAME * psFrame
373 )
374 {
375     IMG_FORMAT eFormat;
376     IMG_UINT16 ui16Width;
377     IMG_UINT16 ui16Stride;
378     IMG_UINT16 ui16PictureHeight;
379 
380     if (!ctx)
381         return VA_STATUS_ERROR_UNKNOWN;
382     // if source slot is NULL then it's just a next portion of slices
383     if (psFrame == IMG_NULL)
384         return VA_STATUS_ERROR_UNKNOWN;
385 
386     eFormat = ctx->eFormat;
387     ui16Width = obj_surface_p->width;
388     ui16PictureHeight = obj_surface_p->height;
389     ui16Stride = obj_surface_p->psb_surface->stride;
390     drv_debug_msg(VIDEO_DEBUG_GENERAL, "%s eFormat = %d, w = %d, h = %d, stride = %d\n",
391         __FUNCTION__, eFormat, ui16Width, ui16PictureHeight, ui16Stride);
392     // 3 Components: Y, U, V
393     // Y component is always at the beginning
394     psFrame->i32YComponentOffset = 0;
395     psFrame->ui16SrcYStride = ui16Stride;
396 
397     // Assume for now that field 0 comes first
398     psFrame->i32Field0YOffset = 0;
399     psFrame->i32Field0UOffset = 0;
400     psFrame->i32Field0VOffset = 0;
401 
402 
403     switch (eFormat) {
404     case IMG_CODEC_YUV:
405         psFrame->ui16SrcUVStride = ui16Stride / 2;              // ui16SrcUStride
406 
407         psFrame->i32UComponentOffset = ui16Stride * ui16PictureHeight;   // ui16SrcUBase
408         psFrame->i32VComponentOffset = ui16Stride * ui16PictureHeight + (ui16Stride / 2) * (ui16PictureHeight / 2); // ui16SrcVBase
409         break;
410 
411     case IMG_CODEC_PL8:
412         psFrame->ui16SrcUVStride = ui16Stride / 2;              // ui16SrcUStride
413 
414         psFrame->i32UComponentOffset = 0;   // ui16SrcUBase
415         psFrame->i32VComponentOffset = 0; // ui16SrcVBase
416         break;
417 
418     case IMG_CODEC_PL12:
419         psFrame->ui16SrcUVStride = ui16Stride;                         // ui16SrcUStride
420         //FIXME
421         psFrame->i32UComponentOffset = ui16Stride * ui16PictureHeight; // ui16SrcUBase
422         psFrame->i32VComponentOffset = ui16Stride * ui16PictureHeight; // ui16SrcVBase
423         break;
424 
425     case IMG_CODEC_YV12:    /* YV12 */
426         psFrame->ui16SrcUVStride = ui16Stride / 2;              // ui16SrcUStride
427 
428         psFrame->i32UComponentOffset = ui16Stride * ui16PictureHeight + (ui16Stride / 2) * (ui16PictureHeight / 2);   // ui16SrcUBase
429         psFrame->i32VComponentOffset = ui16Stride * ui16PictureHeight; // ui16SrcVBase
430         break;
431 
432     case IMG_CODEC_IMC2:    /* IMC2 */
433         psFrame->ui16SrcUVStride = ui16Stride;                  // ui16SrcUStride
434 
435         psFrame->i32UComponentOffset = ui16Stride * ui16PictureHeight + (ui16Stride / 2);   // ui16SrcUBase
436         psFrame->i32VComponentOffset = ui16Stride * ui16PictureHeight; // ui16SrcVBase
437         break;
438 
439     case IMG_CODEC_422_YUV:
440         psFrame->ui16SrcUVStride = ui16Stride;          // ui16SrcUStride
441 
442         psFrame->i32UComponentOffset = ui16Stride * ui16PictureHeight;   // ui16SrcUBase
443         psFrame->i32VComponentOffset = ui16Stride * ui16PictureHeight + (ui16Stride / 2) * ui16PictureHeight; // ui16SrcVBase
444         break;
445 
446     case IMG_CODEC_422_YV12:        /* YV16 */
447         psFrame->ui16SrcUVStride = ui16Stride;          // ui16SrcUStride
448 
449         psFrame->i32UComponentOffset = ui16Stride * ui16PictureHeight + (ui16Stride / 2) * ui16PictureHeight;   // ui16SrcUBase
450         psFrame->i32VComponentOffset = ui16Stride * ui16PictureHeight; // ui16SrcVBase
451         break;
452 
453     case IMG_CODEC_422_PL8:
454         psFrame->ui16SrcUVStride = ui16Stride;          // ui16SrcUStride
455 
456         psFrame->i32UComponentOffset = 0;   // ui16SrcUBase
457         psFrame->i32VComponentOffset = 0; // ui16SrcVBase
458         break;
459 
460     case IMG_CODEC_422_IMC2:        /* IMC2 */
461         psFrame->ui16SrcUVStride = ui16Stride * 2;                      // ui16SrcUStride
462 
463         psFrame->i32UComponentOffset = ui16Stride * ui16PictureHeight + (ui16Stride / 2);   // ui16SrcUBase
464         psFrame->i32VComponentOffset = ui16Stride * ui16PictureHeight; // ui16SrcVBase
465         break;
466 
467     case IMG_CODEC_422_PL12:
468         psFrame->ui16SrcUVStride = ui16Stride * 2;                      // ui16SrcUStride
469 
470         psFrame->i32UComponentOffset = 0;   // ui16SrcUBase
471         psFrame->i32VComponentOffset = 0; // ui16SrcVBase
472         break;
473 
474     case IMG_CODEC_Y0UY1V_8888:
475     case IMG_CODEC_Y0VY1U_8888:
476     case IMG_CODEC_UY0VY1_8888:
477     case IMG_CODEC_VY0UY1_8888:
478         psFrame->ui16SrcUVStride = ui16Stride;                  // ui16SrcUStride
479 
480         psFrame->i32UComponentOffset = 0;   // ui16SrcUBase
481         psFrame->i32VComponentOffset = 0; // ui16SrcVBase
482         break;
483 
484     default:
485         break;
486     }
487 
488     if (ctx->bIsInterlaced) {
489         if (ctx->bIsInterleaved) {
490             switch (eFormat) {
491             case IMG_CODEC_IMC2:
492             case IMG_CODEC_422_IMC2:
493                 psFrame->i32VComponentOffset *= 2;
494                 psFrame->i32UComponentOffset = psFrame->i32VComponentOffset + (ui16Stride / 2);
495                 break;
496             default:
497                 psFrame->i32UComponentOffset *= 2;
498                 psFrame->i32VComponentOffset *= 2;
499                 break;
500             }
501 
502             psFrame->i32Field1YOffset = psFrame->i32Field0YOffset + psFrame->ui16SrcYStride;
503             psFrame->i32Field1UOffset = psFrame->i32Field0UOffset + psFrame->ui16SrcUVStride;
504             psFrame->i32Field1VOffset = psFrame->i32Field0VOffset + psFrame->ui16SrcUVStride;
505 
506             psFrame->ui16SrcYStride *= 2;                           // ui16SrcYStride
507             psFrame->ui16SrcUVStride *= 2;                  // ui16SrcUStride
508 
509             if (!ctx->bTopFieldFirst)       {
510                 IMG_INT32 i32Temp;
511 
512                 i32Temp = psFrame->i32Field1YOffset;
513                 psFrame->i32Field1YOffset = psFrame->i32Field0YOffset;
514                 psFrame->i32Field0YOffset = i32Temp;
515 
516                 i32Temp = psFrame->i32Field1UOffset;
517                 psFrame->i32Field1UOffset = psFrame->i32Field0UOffset;
518                 psFrame->i32Field0UOffset = i32Temp;
519 
520                 i32Temp = psFrame->i32Field1VOffset;
521                 psFrame->i32Field1VOffset = psFrame->i32Field0VOffset;
522                 psFrame->i32Field0VOffset = i32Temp;
523             }
524         } else {
525             IMG_UINT32 ui32YFieldSize, ui32CFieldSize;
526 
527             switch (eFormat) {
528             case IMG_CODEC_Y0UY1V_8888:
529             case IMG_CODEC_UY0VY1_8888:
530             case IMG_CODEC_Y0VY1U_8888:
531             case IMG_CODEC_VY0UY1_8888:
532                 ui32YFieldSize = ui16PictureHeight * ui16Stride * 2;
533                 ui32CFieldSize = ui32YFieldSize;
534                 break;
535             case IMG_CODEC_PL8:
536                 ui32YFieldSize = ui16PictureHeight * ui16Stride;
537                 ui32CFieldSize = ui16PictureHeight * ui16Stride / 4;
538                 break;
539             case IMG_CODEC_PL12:
540                 ui32YFieldSize = ui16PictureHeight * ui16Stride;
541                 ui32CFieldSize = ui16PictureHeight * ui16Stride / 2;
542                 break;
543             case IMG_CODEC_422_YUV:
544             case IMG_CODEC_422_YV12:
545             case IMG_CODEC_422_IMC2:
546                 ui32YFieldSize = ui16PictureHeight * ui16Stride * 2;
547                 ui32CFieldSize = ui32YFieldSize;
548                 break;
549             case IMG_CODEC_422_PL8:
550                 ui32YFieldSize = ui16PictureHeight * ui16Stride;
551                 ui32CFieldSize = ui16PictureHeight * ui16Stride / 2;
552                 break;
553             case IMG_CODEC_422_PL12:
554                 ui32YFieldSize = ui16PictureHeight * ui16Stride;
555                 ui32CFieldSize = ui32YFieldSize;
556                 break;
557             default:
558                 ui32YFieldSize = ui16PictureHeight * ui16Stride * 3 / 2;
559                 ui32CFieldSize = ui32YFieldSize;
560                 break;
561             }
562 
563             psFrame->i32Field1YOffset = ui32YFieldSize;
564             psFrame->i32Field1UOffset = ui32CFieldSize;
565             psFrame->i32Field1VOffset = ui32CFieldSize;
566         }
567     } else {
568         psFrame->i32Field1YOffset = psFrame->i32Field0YOffset;
569         psFrame->i32Field1UOffset = psFrame->i32Field0UOffset;
570         psFrame->i32Field1VOffset = psFrame->i32Field0VOffset;
571     }
572     drv_debug_msg(VIDEO_DEBUG_GENERAL, "%s i32YComponentOffset = %d, i32UComponentOffset = %d, i32VComponentOffset = %d\n",
573         __FUNCTION__, (int)(psFrame->i32YComponentOffset), (int)(psFrame->i32UComponentOffset), (int)(psFrame->i32VComponentOffset));
574      return VA_STATUS_SUCCESS;
575 }
576 
tng_send_source_frame(context_ENC_p ctx,IMG_UINT32 ui32SlotIndex,IMG_UINT32 ui32DisplayOrder)577 IMG_UINT32 tng_send_source_frame(
578     context_ENC_p ctx,
579     IMG_UINT32 ui32SlotIndex,
580     IMG_UINT32 ui32DisplayOrder)
581 {
582     VAStatus vaStatus = VA_STATUS_SUCCESS;
583     context_ENC_frame_buf *ps_buf = &(ctx->ctx_frame_buf);
584     IMG_FRAME  sSrcFrame;
585     IMG_FRAME  *psSrcFrame = &sSrcFrame;
586     tng_cmdbuf_p cmdbuf = ctx->obj_context->tng_cmdbuf;
587     IMG_SOURCE_BUFFER_PARAMS  *psSrcBufParams = NULL;
588     object_surface_p src_surface = ps_buf->src_surface;
589     unsigned int frame_mem_index = 0;
590     unsigned int srf_buf_offset = src_surface->psb_surface->buf.buffer_ofs;
591 
592     drv_debug_msg(VIDEO_DEBUG_GENERAL,
593         "%s: ui32SlotIndex = %d, ui32DisplayOrder = %d\n",
594         __FUNCTION__, ui32SlotIndex, ui32DisplayOrder);
595 
596     if (cmdbuf->frame_mem_index >= COMM_CMD_FRAME_BUF_NUM) {
597         drv_debug_msg(VIDEO_DEBUG_ERROR, "%s: Error: frame_mem buffer index overflow\n", __FUNCTION__);
598         cmdbuf->frame_mem_index = 0;
599     }
600 
601     vaStatus = psb_buffer_map(&cmdbuf->frame_mem, &(cmdbuf->frame_mem_p));
602     if (vaStatus) {
603         drv_debug_msg(VIDEO_DEBUG_ERROR, "%s: map frame buf\n", __FUNCTION__);
604         return vaStatus;
605     }
606 
607     frame_mem_index = cmdbuf->frame_mem_index * cmdbuf->mem_size;
608     psSrcBufParams = (IMG_SOURCE_BUFFER_PARAMS *)(cmdbuf->frame_mem_p + frame_mem_index);
609     memset(psSrcBufParams, 0, sizeof(IMG_SOURCE_BUFFER_PARAMS));
610     memset(psSrcFrame, 0, sizeof(IMG_FRAME));
611     tng__set_component_offsets(ctx, src_surface, psSrcFrame);
612 
613     drv_debug_msg(VIDEO_DEBUG_GENERAL,
614         "%s: cmdbuf->frame_mem_index = %d, frame_mem_index = 0x%08x, cmdbuf->frame_mem_p = 0x%08x\n",
615         __FUNCTION__, cmdbuf->frame_mem_index, frame_mem_index, cmdbuf->frame_mem_p);
616     drv_debug_msg(VIDEO_DEBUG_GENERAL,
617         "%s: frame_mem_index = %d, psBufferParams = 0x%08x\n",
618         __FUNCTION__, frame_mem_index, (unsigned int)psSrcBufParams);
619 
620     /* Prepare ProvideBuffer data */
621     {
622         psSrcBufParams->ui8SlotNum = (IMG_UINT8)(ui32SlotIndex & 0xff);
623         psSrcBufParams->ui8DisplayOrderNum = (IMG_UINT8)(ui32DisplayOrder & 0xff);
624         psSrcBufParams->ui32HostContext = (IMG_UINT32)ctx;
625 
626 #ifdef _TNG_RELOC_
627         TNG_RELOC_CMDBUF_FRAMES(
628             &(psSrcBufParams->ui32PhysAddrYPlane_Field0),
629             srf_buf_offset + psSrcFrame->i32YComponentOffset + psSrcFrame->i32Field0YOffset,
630             &(src_surface->psb_surface->buf));
631         TNG_RELOC_CMDBUF_FRAMES(
632             &(psSrcBufParams->ui32PhysAddrUPlane_Field0),
633             srf_buf_offset + psSrcFrame->i32UComponentOffset + psSrcFrame->i32Field0UOffset,
634             &(src_surface->psb_surface->buf));
635         TNG_RELOC_CMDBUF_FRAMES(
636             &(psSrcBufParams->ui32PhysAddrVPlane_Field0),
637             srf_buf_offset + psSrcFrame->i32VComponentOffset + psSrcFrame->i32Field0VOffset,
638             &(src_surface->psb_surface->buf));
639 
640         TNG_RELOC_CMDBUF_FRAMES(
641             &(psSrcBufParams->ui32PhysAddrYPlane_Field1),
642             srf_buf_offset + psSrcFrame->i32YComponentOffset + psSrcFrame->i32Field1YOffset,
643             &(src_surface->psb_surface->buf));
644         TNG_RELOC_CMDBUF_FRAMES(
645             &(psSrcBufParams->ui32PhysAddrUPlane_Field1),
646             srf_buf_offset + psSrcFrame->i32UComponentOffset + psSrcFrame->i32Field1UOffset,
647             &(src_surface->psb_surface->buf));
648         TNG_RELOC_CMDBUF_FRAMES(
649             &(psSrcBufParams->ui32PhysAddrVPlane_Field1),
650             srf_buf_offset + psSrcFrame->i32VComponentOffset + psSrcFrame->i32Field1VOffset,
651             &(src_surface->psb_surface->buf));
652 #else
653         tng_cmdbuf_set_phys(&(psSrcBufParams->ui32PhysAddrYPlane_Field0), 0,
654             &(src_surface->psb_surface->buf),
655             srf_buf_offset + psSrcFrame->i32YComponentOffset + psSrcFrame->i32Field0YOffset, 0);
656         tng_cmdbuf_set_phys(&(psSrcBufParams->ui32PhysAddrUPlane_Field0), 0,
657             &(src_surface->psb_surface->buf),
658             srf_buf_offset + psSrcFrame->i32UComponentOffset + psSrcFrame->i32Field0UOffset, 0);
659         tng_cmdbuf_set_phys(&(psSrcBufParams->ui32PhysAddrVPlane_Field0), 0,
660             &(src_surface->psb_surface->buf),
661             srf_buf_offset + psSrcFrame->i32VComponentOffset + psSrcFrame->i32Field0VOffset, 0);
662 
663         tng_cmdbuf_set_phys(&(psSrcBufParams->ui32PhysAddrYPlane_Field1), 0,
664             &(src_surface->psb_surface->buf),
665             srf_buf_offset + psSrcFrame->i32YComponentOffset + psSrcFrame->i32Field1YOffset, 0);
666         tng_cmdbuf_set_phys(&(psSrcBufParams->ui32PhysAddrUPlane_Field1), 0,
667             &(src_surface->psb_surface->buf),
668             srf_buf_offset + psSrcFrame->i32UComponentOffset + psSrcFrame->i32Field1UOffset, 0);
669         tng_cmdbuf_set_phys(&(psSrcBufParams->ui32PhysAddrVPlane_Field1), 0,
670             &(src_surface->psb_surface->buf),
671             srf_buf_offset + psSrcFrame->i32VComponentOffset + psSrcFrame->i32Field1VOffset, 0);
672 #endif
673     }
674     drv_debug_msg(VIDEO_DEBUG_GENERAL,
675         "%s slot_idx = %d, frame_count = %d\n", __FUNCTION__,
676         (int)(ui32SlotIndex), (int)(ctx->ui32FrameCount[ctx->ui32StreamID]));
677     drv_debug_msg(VIDEO_DEBUG_GENERAL,
678         "%s: YPlane_Field0 = 0x%08x, UPlane_Field0 = 0x%08x, VPlane_Field0 = 0x%08x\n",
679         __FUNCTION__, (unsigned int)(psSrcBufParams->ui32PhysAddrYPlane_Field0),
680         (unsigned int)(psSrcBufParams->ui32PhysAddrUPlane_Field0),
681         (unsigned int)(psSrcBufParams->ui32PhysAddrVPlane_Field0));
682     drv_debug_msg(VIDEO_DEBUG_GENERAL,
683         "%s: YPlane_Field1 = 0x%08x, UPlane_Field1 = 0x%08x, VPlane_Field1 = 0x%08x\n",
684         __FUNCTION__, (unsigned int)(psSrcBufParams->ui32PhysAddrYPlane_Field1),
685         (unsigned int)(psSrcBufParams->ui32PhysAddrUPlane_Field1),
686         (unsigned int)(psSrcBufParams->ui32PhysAddrVPlane_Field1));
687 
688     /* Send ProvideBuffer Command */
689     tng_cmdbuf_insert_command(ctx->obj_context, ctx->ui32StreamID,
690         MTX_CMDID_PROVIDE_SOURCE_BUFFER,
691         0, &(cmdbuf->frame_mem), frame_mem_index);
692 
693     ++(cmdbuf->frame_mem_index);
694     psb_buffer_unmap(&cmdbuf->frame_mem);
695 
696     return 0;
697 }
698 
699 
tng_send_rec_frames(context_ENC_p ctx,IMG_INT8 i8HeaderSlotNum,IMG_BOOL bLongTerm)700 IMG_UINT32 tng_send_rec_frames(
701     context_ENC_p ctx,
702     IMG_INT8 i8HeaderSlotNum,
703     IMG_BOOL bLongTerm)
704 {
705     //VAStatus vaStatus = VA_STATUS_SUCCESS;
706     unsigned int srf_buf_offset;
707     context_ENC_frame_buf *ps_buf = &(ctx->ctx_frame_buf);
708     object_surface_p rec_surface = ps_buf->rec_surface;
709     IMG_UINT32 ui32CmdData = 0;
710 
711     srf_buf_offset = rec_surface->psb_surface->buf.buffer_ofs;
712     /* Send ProvideBuffer Command */
713     ui32CmdData = F_ENCODE(IMG_BUFFER_RECON, MTX_MSG_PROVIDE_REF_BUFFER_USE) |
714         F_ENCODE(i8HeaderSlotNum, MTX_MSG_PROVIDE_REF_BUFFER_SLOT) |
715         F_ENCODE(bLongTerm, MTX_MSG_PROVIDE_REF_BUFFER_LT);
716 
717     tng_cmdbuf_insert_command(ctx->obj_context, ctx->ui32StreamID,
718         MTX_CMDID_PROVIDE_REF_BUFFER,
719         ui32CmdData, &(rec_surface->psb_surface->buf), 0);
720 
721     return 0;
722 }
723 
tng_send_ref_frames(context_ENC_p ctx,IMG_UINT32 ui32refindex,IMG_BOOL __maybe_unused bLongTerm)724 IMG_UINT32 tng_send_ref_frames(
725     context_ENC_p ctx,
726     IMG_UINT32    ui32refindex,
727     IMG_BOOL      __maybe_unused bLongTerm)
728 {
729     //VAStatus vaStatus = VA_STATUS_SUCCESS;
730     unsigned int srf_buf_offset;
731     context_ENC_frame_buf *ps_buf = &(ctx->ctx_frame_buf);
732     object_surface_p ref_surface = ps_buf->ref_surface[ui32refindex];
733     IMG_UINT32 ui32CmdData = 0;
734 
735 #ifdef _TNG_FRAMES_
736     if (ui32RefIndex == 0) {
737         ref_surface = ps_buf->ref_surface;
738         ui32CmdData = F_ENCODE(IMG_BUFFER_REF0, MTX_MSG_PROVIDE_REF_BUFFER_USE) |
739             F_ENCODE(bLongTerm, MTX_MSG_PROVIDE_REF_BUFFER_LT);
740     } else {
741         ref_surface = ps_buf->ref_surface1;
742         ui32CmdData = F_ENCODE(IMG_BUFFER_REF1, MTX_MSG_PROVIDE_REF_BUFFER_USE) |
743         F_ENCODE(bLongTerm, MTX_MSG_PROVIDE_REF_BUFFER_LT);
744     }
745 #endif
746     srf_buf_offset = ref_surface->psb_surface->buf.buffer_ofs;
747     /* Send ProvideBuffer Command */
748     tng_cmdbuf_insert_command(ctx->obj_context, ctx->ui32StreamID,
749         MTX_CMDID_PROVIDE_REF_BUFFER,
750         ui32CmdData, &(ref_surface->psb_surface->buf), 0);
751 
752     return VA_STATUS_SUCCESS;
753 }
754 
755