| /* |
| * Copyright (c) 2011 Intel Corporation. All Rights Reserved. |
| * Copyright (c) Imagination Technologies Limited, UK |
| * |
| * Permission is hereby granted, free of charge, to any person obtaining a |
| * copy of this software and associated documentation files (the |
| * "Software"), to deal in the Software without restriction, including |
| * without limitation the rights to use, copy, modify, merge, publish, |
| * distribute, sub license, and/or sell copies of the Software, and to |
| * permit persons to whom the Software is furnished to do so, subject to |
| * the following conditions: |
| * |
| * The above copyright notice and this permission notice (including the |
| * next paragraph) shall be included in all copies or substantial portions |
| * of the Software. |
| * |
| * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS |
| * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF |
| * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. |
| * IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR |
| * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, |
| * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE |
| * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
| * |
| * Authors: |
| * Edward Lin <edward.lin@intel.com> |
| * |
| */ |
| |
| #include <unistd.h> |
| #include <stdio.h> |
| #include <memory.h> |
| #include <wsbm/wsbm_manager.h> |
| #include "tng_picmgmt.h" |
| #include "psb_drv_debug.h" |
| |
| #define MASK_TOPAZHP_CR_H264COMP_CUSTOM_QUANT_Q_0 0x0000007F |
| #define SHIFT_TOPAZHP_CR_H264COMP_CUSTOM_QUANT_Q_0 0 |
| #define MASK_TOPAZHP_CR_H264COMP_CUSTOM_QUANT_Q_1 0x00007F00 |
| #define SHIFT_TOPAZHP_CR_H264COMP_CUSTOM_QUANT_Q_1 8 |
| #define MASK_TOPAZHP_CR_H264COMP_CUSTOM_QUANT_Q_2 0x007F0000 |
| #define SHIFT_TOPAZHP_CR_H264COMP_CUSTOM_QUANT_Q_2 16 |
| #define MASK_TOPAZHP_CR_H264COMP_CUSTOM_QUANT_Q_3 0x7F000000 |
| #define SHIFT_TOPAZHP_CR_H264COMP_CUSTOM_QUANT_Q_3 24 |
| |
| #define MASK_TOPAZHP_CR_H264COMP_CUSTOM_QUANT_SP_0 0x00003FFF |
| #define SHIFT_TOPAZHP_CR_H264COMP_CUSTOM_QUANT_SP_0 0 |
| #define MASK_TOPAZHP_CR_H264COMP_CUSTOM_QUANT_SP_1 0x3FFF0000 |
| #define SHIFT_TOPAZHP_CR_H264COMP_CUSTOM_QUANT_SP_1 16 |
| |
| /************************* MTX_CMDID_PICMGMT *************************/ |
| VAStatus tng_picmgmt_update(context_ENC_p ctx, IMG_PICMGMT_TYPE eType, unsigned int ref) |
| { |
| //VAStatus vaStatus = VA_STATUS_SUCCESS; |
| IMG_UINT32 ui32CmdData = 0; |
| |
| //IMG_V_SetNextRefType eFrameType |
| //IMG_V_SkipFrame bProcess |
| //IMG_V_EndOfStream ui32FrameCount |
| //IMG_PICMGMT_FLUSH ui32FrameCount |
| ui32CmdData = F_ENCODE(eType, MTX_MSG_PICMGMT_SUBTYPE) | |
| F_ENCODE(ref, MTX_MSG_PICMGMT_DATA); |
| |
| /* Send PicMgmt Command */ |
| tng_cmdbuf_insert_command(ctx->obj_context, ctx->ui32StreamID, |
| MTX_CMDID_PICMGMT | MTX_CMDID_PRIORITY, |
| ui32CmdData, 0, 0); |
| |
| return VA_STATUS_SUCCESS; |
| } |
| |
| /*! |
| ****************************************************************************** |
| * |
| * Picture management functions |
| * |
| ******************************************************************************/ |
| void tng__picmgmt_long_term_refs(context_ENC_p __maybe_unused ctx, IMG_UINT32 __maybe_unused ui32FrameNum) |
| { |
| #ifdef _TNG_ENABLE_PITMGMT_ |
| IMG_BOOL bIsLongTermRef; |
| IMG_BOOL bUsesLongTermRef0; |
| IMG_BOOL bUsesLongTermRef1; |
| IMG_UINT32 ui32FrameCnt; |
| |
| // Determine frame position in source stream |
| // This assumes there are no IDR frames after the first one |
| if (ui32FrameNum == 0) { |
| // Initial IDR frame |
| ui32FrameCnt = 0; |
| } else if (((ui32FrameNum - 1) % (ctx->sRCParams.ui16BFrames + 1)) == 0) { |
| // I or P frame |
| ui32FrameCnt = ui32FrameNum + ctx->sRCParams.ui16BFrames; |
| if (ui32FrameCnt >= ctx->ui32Framecount) ui32FrameCnt = ctx->ui32Framecount - 1; |
| } else { |
| // B frame |
| // This will be incorrect for hierarchical B-pictures |
| ui32FrameCnt = ui32FrameNum - 1; |
| } |
| |
| // Decide if the current frame should be used as a long-term reference |
| bIsLongTermRef = ctx->ui32LongTermRefFreq ? |
| (ui32FrameCnt % ctx->ui32LongTermRefFreq == 0) : |
| IMG_FALSE; |
| |
| // Decide if the current frame should refer to a long-term reference |
| bUsesLongTermRef0 = ctx->ui32LongTermRefUsageFreq ? |
| (ui32FrameCnt % ctx->ui32LongTermRefUsageFreq == ctx->ui32LongTermRefUsageOffset) : |
| IMG_FALSE; |
| bUsesLongTermRef1 = IMG_FALSE; |
| |
| if (bIsLongTermRef || bUsesLongTermRef0 || bUsesLongTermRef1) { |
| // Reconstructed/reference frame to be written to host buffer |
| // Send the buffer to be used as reference |
| tng__send_ref_frames(ctx, 0, bIsLongTermRef); |
| if (bIsLongTermRef) ctx->byCurBufPointer = (ctx->byCurBufPointer + 1) % 3; |
| } |
| #endif |
| } |
| |
| static VAStatus tng__H264ES_CalcCustomQuantSp(IMG_UINT8 list, IMG_UINT8 param, IMG_UINT8 customQuantQ) |
| { |
| // Derived from sim/topaz/testbench/tests/mved1_tests.c |
| IMG_UINT32 mfflat[2][16] = { |
| { |
| 13107, 8066, 13107, 8066, |
| 8066, 5243, 8066, 5243, |
| 13107, 8066, 13107, 8066, |
| 8066, 5243, 8066, 5243 |
| }, // 4x4 |
| { |
| 13107, 12222, 16777, 12222, |
| 12222, 11428, 15481, 11428, |
| 16777, 15481, 20972, 15481, |
| 12222, 11428, 15481, 11428 |
| } // 8x8 |
| }; |
| IMG_UINT8 uVi[2][16] = { |
| { |
| 20, 26, 20, 26, |
| 26, 32, 26, 32, |
| 20, 26, 20, 26, |
| 26, 32, 26, 32 |
| }, // 4x4 |
| { |
| 20, 19, 25, 19, |
| 19, 18, 24, 18, |
| 25, 24, 32, 24, |
| 19, 18, 24, 18 |
| } // 8x8 |
| }; |
| |
| int mfnew; |
| double fSp; |
| int uSp; |
| |
| if (customQuantQ == 0) customQuantQ = 1; |
| mfnew = (mfflat[list][param] * 16) / customQuantQ; |
| fSp = ((double)(mfnew * uVi[list][param])) / (double)(1 << 22); |
| fSp = (fSp * 100000000.0f) / 100000000.0f; |
| uSp = (IMG_UINT16)(fSp * 65536); |
| |
| return uSp & 0x03FFF; |
| } |
| |
| |
| static VAStatus 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) |
| { |
| IMG_UINT8 *pui8QuantMem; |
| IMG_UINT32 *pui32QuantReg; |
| IMG_UINT8 *apui8QuantTables[8]; |
| IMG_UINT32 ui32Table, ui32Val; |
| psb_buffer_p pCustomBuf = NULL; |
| IMG_UINT32 custom_quant_size = 0; |
| |
| // Scanning order for coefficients, see section 8.5.5 of H.264 specification |
| // Note that even for interlaced mode, hardware takes the scaling values as if frame zig-zag scanning were being used |
| IMG_UINT8 aui8ZigZagScan4x4[16] = { |
| 0, 1, 5, 6, |
| 2, 4, 7, 12, |
| 3, 8, 11, 13, |
| 9, 10, 14, 15 |
| }; |
| IMG_UINT8 aui8ZigZagScan8x8[64] = { |
| 0, 1, 5, 6, 14, 15, 27, 28, |
| 2, 4, 7, 13, 16, 26, 29, 42, |
| 3, 8, 12, 17, 25, 30, 41, 43, |
| 9, 11, 18, 24, 31, 40, 44, 53, |
| 10, 19, 23, 32, 39, 45, 52, 54, |
| 20, 22, 33, 38, 46, 51, 55, 60, |
| 21, 34, 37, 47, 50, 56, 59, 61, |
| 35, 36, 48, 49, 57, 58, 62, 63 |
| }; |
| |
| |
| if (ctx == NULL) { |
| return VA_STATUS_ERROR_UNKNOWN; |
| } |
| |
| if (ctx->bCustomScaling == IMG_FALSE) { |
| return VA_STATUS_ERROR_UNKNOWN; |
| } |
| |
| pCustomBuf = &(ctx->ctx_mem[ctx->ui32StreamID].bufs_custom_quant); |
| custom_quant_size = ctx->ctx_mem_size.custom_quant; |
| |
| |
| /* Copy quantization values (in header order) */ |
| pui8QuantMem = (IMG_UINT8*)(pCustomBuf); |
| memcpy(pui8QuantMem, aui8Sl4x4IntraY, 16); |
| memcpy(pui8QuantMem + 16, aui8Sl4x4IntraCb, 16); |
| memcpy(pui8QuantMem + 32, aui8Sl4x4IntraCr, 16); |
| memcpy(pui8QuantMem + 48, aui8Sl4x4InterY, 16); |
| memcpy(pui8QuantMem + 64, aui8Sl4x4InterCb, 16); |
| memcpy(pui8QuantMem + 80, aui8Sl4x4InterCr, 16); |
| memcpy(pui8QuantMem + 96, aui8Sl8x8IntraY, 64); |
| memcpy(pui8QuantMem + 160, aui8Sl8x8InterY, 64); |
| |
| /* Create quantization register values */ |
| |
| /* Assign based on the order values are written to registers */ |
| apui8QuantTables[0] = aui8Sl4x4IntraY; |
| apui8QuantTables[1] = aui8Sl4x4InterY; |
| apui8QuantTables[2] = aui8Sl4x4IntraCb; |
| apui8QuantTables[3] = aui8Sl4x4InterCb; |
| apui8QuantTables[4] = aui8Sl4x4IntraCr; |
| apui8QuantTables[5] = aui8Sl4x4InterCr; |
| apui8QuantTables[6] = aui8Sl8x8IntraY; |
| apui8QuantTables[7] = aui8Sl8x8InterY; |
| |
| /* H264COMP_CUSTOM_QUANT_SP register values "psCustomQuantRegs4x4Sp"*/ |
| pui8QuantMem = (IMG_UINT8*)(pCustomBuf + custom_quant_size); |
| pui32QuantReg = (IMG_UINT32 *)pui8QuantMem; |
| for (ui32Table = 0; ui32Table < 6; ui32Table++) { |
| for (ui32Val = 0; ui32Val < 16; ui32Val += 4) { |
| *pui32QuantReg = F_ENCODE(tng__H264ES_CalcCustomQuantSp(0, ui32Val, apui8QuantTables[ui32Table][aui8ZigZagScan4x4[ui32Val]]), TOPAZHP_CR_H264COMP_CUSTOM_QUANT_SP_0) |
| | F_ENCODE(tng__H264ES_CalcCustomQuantSp(0, ui32Val + 1, apui8QuantTables[ui32Table][aui8ZigZagScan4x4[ui32Val + 1]]), TOPAZHP_CR_H264COMP_CUSTOM_QUANT_SP_1); |
| pui32QuantReg++; |
| *pui32QuantReg = F_ENCODE(tng__H264ES_CalcCustomQuantSp(0, ui32Val + 2, apui8QuantTables[ui32Table][aui8ZigZagScan4x4[ui32Val + 2]]), TOPAZHP_CR_H264COMP_CUSTOM_QUANT_SP_0) |
| | F_ENCODE(tng__H264ES_CalcCustomQuantSp(0, ui32Val + 3, apui8QuantTables[ui32Table][aui8ZigZagScan4x4[ui32Val + 3]]), TOPAZHP_CR_H264COMP_CUSTOM_QUANT_SP_1); |
| pui32QuantReg++; |
| } |
| } |
| |
| /*psCustomQuantRegs8x8Sp*/ |
| pui8QuantMem = (IMG_UINT8*)(pCustomBuf + custom_quant_size + custom_quant_size); |
| pui32QuantReg = (IMG_UINT32 *)pui8QuantMem; |
| for (; ui32Table < 8; ui32Table++) { |
| for (ui32Val = 0; ui32Val < 64; ui32Val += 8) { |
| *pui32QuantReg = F_ENCODE(tng__H264ES_CalcCustomQuantSp(1, ((ui32Val & 24) >> 1), apui8QuantTables[ui32Table][aui8ZigZagScan8x8[ui32Val]]), TOPAZHP_CR_H264COMP_CUSTOM_QUANT_SP_0) |
| | F_ENCODE(tng__H264ES_CalcCustomQuantSp(1, ((ui32Val & 24) >> 1) + 1, apui8QuantTables[ui32Table][aui8ZigZagScan8x8[ui32Val + 1]]), TOPAZHP_CR_H264COMP_CUSTOM_QUANT_SP_1); |
| pui32QuantReg++; |
| *pui32QuantReg = F_ENCODE(tng__H264ES_CalcCustomQuantSp(1, ((ui32Val & 24) >> 1) + 2, apui8QuantTables[ui32Table][aui8ZigZagScan8x8[ui32Val + 2]]), TOPAZHP_CR_H264COMP_CUSTOM_QUANT_SP_0) |
| | F_ENCODE(tng__H264ES_CalcCustomQuantSp(1, ((ui32Val & 24) >> 1) + 3, apui8QuantTables[ui32Table][aui8ZigZagScan8x8[ui32Val + 3]]), TOPAZHP_CR_H264COMP_CUSTOM_QUANT_SP_1); |
| pui32QuantReg++; |
| *pui32QuantReg = F_ENCODE(tng__H264ES_CalcCustomQuantSp(1, ((ui32Val & 24) >> 1), apui8QuantTables[ui32Table][aui8ZigZagScan8x8[ui32Val + 4]]), TOPAZHP_CR_H264COMP_CUSTOM_QUANT_SP_0) |
| | F_ENCODE(tng__H264ES_CalcCustomQuantSp(1, ((ui32Val & 24) >> 1) + 1, apui8QuantTables[ui32Table][aui8ZigZagScan8x8[ui32Val + 5]]), TOPAZHP_CR_H264COMP_CUSTOM_QUANT_SP_1); |
| pui32QuantReg++; |
| *pui32QuantReg = F_ENCODE(tng__H264ES_CalcCustomQuantSp(1, ((ui32Val & 24) >> 1) + 2, apui8QuantTables[ui32Table][aui8ZigZagScan8x8[ui32Val + 6]]), TOPAZHP_CR_H264COMP_CUSTOM_QUANT_SP_0) |
| | F_ENCODE(tng__H264ES_CalcCustomQuantSp(1, ((ui32Val & 24) >> 1) + 3, apui8QuantTables[ui32Table][aui8ZigZagScan8x8[ui32Val + 7]]), TOPAZHP_CR_H264COMP_CUSTOM_QUANT_SP_1); |
| pui32QuantReg++; |
| } |
| } |
| |
| /* H264COMP_CUSTOM_QUANT_Q register values "psCustomQuantRegs4x4Q" */ |
| pui8QuantMem = (IMG_UINT8*)(pCustomBuf + custom_quant_size + custom_quant_size + custom_quant_size); |
| pui32QuantReg = (IMG_UINT32 *)pui8QuantMem; |
| for (ui32Table = 0; ui32Table < 6; ui32Table++) { |
| for (ui32Val = 0; ui32Val < 16; ui32Val += 4) { |
| *pui32QuantReg = F_ENCODE(apui8QuantTables[ui32Table][aui8ZigZagScan4x4[ui32Val]], TOPAZHP_CR_H264COMP_CUSTOM_QUANT_Q_0) |
| | F_ENCODE(apui8QuantTables[ui32Table][aui8ZigZagScan4x4[ui32Val + 1]], TOPAZHP_CR_H264COMP_CUSTOM_QUANT_Q_1) |
| | F_ENCODE(apui8QuantTables[ui32Table][aui8ZigZagScan4x4[ui32Val + 2]], TOPAZHP_CR_H264COMP_CUSTOM_QUANT_Q_2) |
| | F_ENCODE(apui8QuantTables[ui32Table][aui8ZigZagScan4x4[ui32Val + 3]], TOPAZHP_CR_H264COMP_CUSTOM_QUANT_Q_3); |
| pui32QuantReg++; |
| } |
| } |
| |
| /*psCustomQuantRegs8x8Q)*/ |
| pui8QuantMem = (IMG_UINT8*)(pCustomBuf + custom_quant_size + custom_quant_size + custom_quant_size + custom_quant_size); |
| |
| pui32QuantReg = (IMG_UINT32 *)pui8QuantMem; |
| for (; ui32Table < 8; ui32Table++) { |
| for (ui32Val = 0; ui32Val < 64; ui32Val += 8) { |
| *pui32QuantReg = F_ENCODE(apui8QuantTables[ui32Table][aui8ZigZagScan8x8[ui32Val]], TOPAZHP_CR_H264COMP_CUSTOM_QUANT_Q_0) |
| | F_ENCODE(apui8QuantTables[ui32Table][aui8ZigZagScan8x8[ui32Val + 1]], TOPAZHP_CR_H264COMP_CUSTOM_QUANT_Q_1) |
| | F_ENCODE(apui8QuantTables[ui32Table][aui8ZigZagScan8x8[ui32Val + 2]], TOPAZHP_CR_H264COMP_CUSTOM_QUANT_Q_2) |
| | F_ENCODE(apui8QuantTables[ui32Table][aui8ZigZagScan8x8[ui32Val + 3]], TOPAZHP_CR_H264COMP_CUSTOM_QUANT_Q_3); |
| pui32QuantReg++; |
| *pui32QuantReg = F_ENCODE(apui8QuantTables[ui32Table][aui8ZigZagScan8x8[ui32Val + 4]], TOPAZHP_CR_H264COMP_CUSTOM_QUANT_Q_0) |
| | F_ENCODE(apui8QuantTables[ui32Table][aui8ZigZagScan8x8[ui32Val + 5]], TOPAZHP_CR_H264COMP_CUSTOM_QUANT_Q_1) |
| | F_ENCODE(apui8QuantTables[ui32Table][aui8ZigZagScan8x8[ui32Val + 6]], TOPAZHP_CR_H264COMP_CUSTOM_QUANT_Q_2) |
| | F_ENCODE(apui8QuantTables[ui32Table][aui8ZigZagScan8x8[ui32Val + 7]], TOPAZHP_CR_H264COMP_CUSTOM_QUANT_Q_3); |
| pui32QuantReg++; |
| } |
| } |
| |
| if (ctx->bPpsScaling) |
| ctx->bInsertPicHeader = IMG_TRUE; |
| |
| return VA_STATUS_SUCCESS; |
| } |
| |
| |
| void tng__picmgmt_custom_scaling(context_ENC_p ctx, IMG_UINT32 ui32FrameNum) |
| { |
| if (ui32FrameNum % ctx->ui32PpsScalingCnt == 0) { |
| // Swap inter and intra scaling lists on alternating picture parameter sets |
| if (ui32FrameNum % (ctx->ui32PpsScalingCnt * 2) == 0) { |
| tng__set_custom_scaling_values( |
| ctx, |
| ctx->aui8CustomQuantParams4x4[0], |
| ctx->aui8CustomQuantParams4x4[1], |
| ctx->aui8CustomQuantParams4x4[2], |
| ctx->aui8CustomQuantParams4x4[3], |
| ctx->aui8CustomQuantParams4x4[4], |
| ctx->aui8CustomQuantParams4x4[5], |
| ctx->aui8CustomQuantParams8x8[0], |
| ctx->aui8CustomQuantParams8x8[1]); |
| } else { |
| tng__set_custom_scaling_values( |
| ctx, |
| ctx->aui8CustomQuantParams4x4[3], |
| ctx->aui8CustomQuantParams4x4[4], |
| ctx->aui8CustomQuantParams4x4[5], |
| ctx->aui8CustomQuantParams4x4[0], |
| ctx->aui8CustomQuantParams4x4[1], |
| ctx->aui8CustomQuantParams4x4[2], |
| ctx->aui8CustomQuantParams8x8[1], |
| ctx->aui8CustomQuantParams8x8[0]); |
| } |
| } |
| } |
| |
| /************************* MTX_CMDID_PROVIDE_BUFFER *************************/ |
| IMG_UINT32 tng_send_codedbuf( |
| context_ENC_p ctx, |
| IMG_UINT32 ui32SlotIndex) |
| { |
| context_ENC_frame_buf *ps_buf = &(ctx->ctx_frame_buf); |
| object_buffer_p object_buffer = ps_buf->coded_buf; |
| IMG_UINT32 ui32Offset = 0; |
| |
| drv_debug_msg(VIDEO_DEBUG_GENERAL, |
| "%s slot 1 = %x\n", __FUNCTION__, ui32SlotIndex); |
| |
| if ((ctx->ui8PipesToUse == 2) && ((ui32SlotIndex & 1) == 1)) |
| ui32Offset = object_buffer->size >> 1; |
| |
| tng_cmdbuf_insert_command( |
| ctx->obj_context, ctx->ui32StreamID, |
| MTX_CMDID_PROVIDE_CODED_BUFFER, |
| F_ENCODE(object_buffer->size, MTX_MSG_PROVIDE_CODED_BUFFER_SIZE) | |
| F_ENCODE(ui32SlotIndex, MTX_MSG_PROVIDE_CODED_BUFFER_SLOT), |
| object_buffer->psb_buffer, tng_align_KB(ui32Offset)); |
| |
| drv_debug_msg(VIDEO_DEBUG_GENERAL, "%s end\n", __FUNCTION__); |
| return VA_STATUS_SUCCESS; |
| } |
| |
| static VAStatus tng__set_component_offsets( |
| context_ENC_p ctx, |
| object_surface_p obj_surface_p, |
| IMG_FRAME * psFrame |
| ) |
| { |
| IMG_FORMAT eFormat; |
| IMG_UINT16 ui16Width; |
| IMG_UINT16 ui16Stride; |
| IMG_UINT16 ui16PictureHeight; |
| |
| if (!ctx) |
| return VA_STATUS_ERROR_UNKNOWN; |
| // if source slot is NULL then it's just a next portion of slices |
| if (psFrame == IMG_NULL) |
| return VA_STATUS_ERROR_UNKNOWN; |
| |
| eFormat = ctx->eFormat; |
| ui16Width = obj_surface_p->width; |
| ui16PictureHeight = obj_surface_p->height; |
| ui16Stride = obj_surface_p->psb_surface->stride; |
| drv_debug_msg(VIDEO_DEBUG_GENERAL, "%s eFormat = %d, w = %d, h = %d, stride = %d\n", |
| __FUNCTION__, eFormat, ui16Width, ui16PictureHeight, ui16Stride); |
| // 3 Components: Y, U, V |
| // Y component is always at the beginning |
| psFrame->i32YComponentOffset = 0; |
| psFrame->ui16SrcYStride = ui16Stride; |
| |
| // Assume for now that field 0 comes first |
| psFrame->i32Field0YOffset = 0; |
| psFrame->i32Field0UOffset = 0; |
| psFrame->i32Field0VOffset = 0; |
| |
| |
| switch (eFormat) { |
| case IMG_CODEC_YUV: |
| psFrame->ui16SrcUVStride = ui16Stride / 2; // ui16SrcUStride |
| |
| psFrame->i32UComponentOffset = ui16Stride * ui16PictureHeight; // ui16SrcUBase |
| psFrame->i32VComponentOffset = ui16Stride * ui16PictureHeight + (ui16Stride / 2) * (ui16PictureHeight / 2); // ui16SrcVBase |
| break; |
| |
| case IMG_CODEC_PL8: |
| psFrame->ui16SrcUVStride = ui16Stride / 2; // ui16SrcUStride |
| |
| psFrame->i32UComponentOffset = 0; // ui16SrcUBase |
| psFrame->i32VComponentOffset = 0; // ui16SrcVBase |
| break; |
| |
| case IMG_CODEC_PL12: |
| psFrame->ui16SrcUVStride = ui16Stride; // ui16SrcUStride |
| //FIXME |
| psFrame->i32UComponentOffset = ui16Stride * ui16PictureHeight; // ui16SrcUBase |
| psFrame->i32VComponentOffset = ui16Stride * ui16PictureHeight; // ui16SrcVBase |
| break; |
| |
| case IMG_CODEC_YV12: /* YV12 */ |
| psFrame->ui16SrcUVStride = ui16Stride / 2; // ui16SrcUStride |
| |
| psFrame->i32UComponentOffset = ui16Stride * ui16PictureHeight + (ui16Stride / 2) * (ui16PictureHeight / 2); // ui16SrcUBase |
| psFrame->i32VComponentOffset = ui16Stride * ui16PictureHeight; // ui16SrcVBase |
| break; |
| |
| case IMG_CODEC_IMC2: /* IMC2 */ |
| psFrame->ui16SrcUVStride = ui16Stride; // ui16SrcUStride |
| |
| psFrame->i32UComponentOffset = ui16Stride * ui16PictureHeight + (ui16Stride / 2); // ui16SrcUBase |
| psFrame->i32VComponentOffset = ui16Stride * ui16PictureHeight; // ui16SrcVBase |
| break; |
| |
| case IMG_CODEC_422_YUV: |
| psFrame->ui16SrcUVStride = ui16Stride; // ui16SrcUStride |
| |
| psFrame->i32UComponentOffset = ui16Stride * ui16PictureHeight; // ui16SrcUBase |
| psFrame->i32VComponentOffset = ui16Stride * ui16PictureHeight + (ui16Stride / 2) * ui16PictureHeight; // ui16SrcVBase |
| break; |
| |
| case IMG_CODEC_422_YV12: /* YV16 */ |
| psFrame->ui16SrcUVStride = ui16Stride; // ui16SrcUStride |
| |
| psFrame->i32UComponentOffset = ui16Stride * ui16PictureHeight + (ui16Stride / 2) * ui16PictureHeight; // ui16SrcUBase |
| psFrame->i32VComponentOffset = ui16Stride * ui16PictureHeight; // ui16SrcVBase |
| break; |
| |
| case IMG_CODEC_422_PL8: |
| psFrame->ui16SrcUVStride = ui16Stride; // ui16SrcUStride |
| |
| psFrame->i32UComponentOffset = 0; // ui16SrcUBase |
| psFrame->i32VComponentOffset = 0; // ui16SrcVBase |
| break; |
| |
| case IMG_CODEC_422_IMC2: /* IMC2 */ |
| psFrame->ui16SrcUVStride = ui16Stride * 2; // ui16SrcUStride |
| |
| psFrame->i32UComponentOffset = ui16Stride * ui16PictureHeight + (ui16Stride / 2); // ui16SrcUBase |
| psFrame->i32VComponentOffset = ui16Stride * ui16PictureHeight; // ui16SrcVBase |
| break; |
| |
| case IMG_CODEC_422_PL12: |
| psFrame->ui16SrcUVStride = ui16Stride * 2; // ui16SrcUStride |
| |
| psFrame->i32UComponentOffset = 0; // ui16SrcUBase |
| psFrame->i32VComponentOffset = 0; // ui16SrcVBase |
| break; |
| |
| case IMG_CODEC_Y0UY1V_8888: |
| case IMG_CODEC_Y0VY1U_8888: |
| case IMG_CODEC_UY0VY1_8888: |
| case IMG_CODEC_VY0UY1_8888: |
| psFrame->ui16SrcUVStride = ui16Stride; // ui16SrcUStride |
| |
| psFrame->i32UComponentOffset = 0; // ui16SrcUBase |
| psFrame->i32VComponentOffset = 0; // ui16SrcVBase |
| break; |
| |
| default: |
| break; |
| } |
| |
| if (ctx->bIsInterlaced) { |
| if (ctx->bIsInterleaved) { |
| switch (eFormat) { |
| case IMG_CODEC_IMC2: |
| case IMG_CODEC_422_IMC2: |
| psFrame->i32VComponentOffset *= 2; |
| psFrame->i32UComponentOffset = psFrame->i32VComponentOffset + (ui16Stride / 2); |
| break; |
| default: |
| psFrame->i32UComponentOffset *= 2; |
| psFrame->i32VComponentOffset *= 2; |
| break; |
| } |
| |
| psFrame->i32Field1YOffset = psFrame->i32Field0YOffset + psFrame->ui16SrcYStride; |
| psFrame->i32Field1UOffset = psFrame->i32Field0UOffset + psFrame->ui16SrcUVStride; |
| psFrame->i32Field1VOffset = psFrame->i32Field0VOffset + psFrame->ui16SrcUVStride; |
| |
| psFrame->ui16SrcYStride *= 2; // ui16SrcYStride |
| psFrame->ui16SrcUVStride *= 2; // ui16SrcUStride |
| |
| if (!ctx->bTopFieldFirst) { |
| IMG_INT32 i32Temp; |
| |
| i32Temp = psFrame->i32Field1YOffset; |
| psFrame->i32Field1YOffset = psFrame->i32Field0YOffset; |
| psFrame->i32Field0YOffset = i32Temp; |
| |
| i32Temp = psFrame->i32Field1UOffset; |
| psFrame->i32Field1UOffset = psFrame->i32Field0UOffset; |
| psFrame->i32Field0UOffset = i32Temp; |
| |
| i32Temp = psFrame->i32Field1VOffset; |
| psFrame->i32Field1VOffset = psFrame->i32Field0VOffset; |
| psFrame->i32Field0VOffset = i32Temp; |
| } |
| } else { |
| IMG_UINT32 ui32YFieldSize, ui32CFieldSize; |
| |
| switch (eFormat) { |
| case IMG_CODEC_Y0UY1V_8888: |
| case IMG_CODEC_UY0VY1_8888: |
| case IMG_CODEC_Y0VY1U_8888: |
| case IMG_CODEC_VY0UY1_8888: |
| ui32YFieldSize = ui16PictureHeight * ui16Stride * 2; |
| ui32CFieldSize = ui32YFieldSize; |
| break; |
| case IMG_CODEC_PL8: |
| ui32YFieldSize = ui16PictureHeight * ui16Stride; |
| ui32CFieldSize = ui16PictureHeight * ui16Stride / 4; |
| break; |
| case IMG_CODEC_PL12: |
| ui32YFieldSize = ui16PictureHeight * ui16Stride; |
| ui32CFieldSize = ui16PictureHeight * ui16Stride / 2; |
| break; |
| case IMG_CODEC_422_YUV: |
| case IMG_CODEC_422_YV12: |
| case IMG_CODEC_422_IMC2: |
| ui32YFieldSize = ui16PictureHeight * ui16Stride * 2; |
| ui32CFieldSize = ui32YFieldSize; |
| break; |
| case IMG_CODEC_422_PL8: |
| ui32YFieldSize = ui16PictureHeight * ui16Stride; |
| ui32CFieldSize = ui16PictureHeight * ui16Stride / 2; |
| break; |
| case IMG_CODEC_422_PL12: |
| ui32YFieldSize = ui16PictureHeight * ui16Stride; |
| ui32CFieldSize = ui32YFieldSize; |
| break; |
| default: |
| ui32YFieldSize = ui16PictureHeight * ui16Stride * 3 / 2; |
| ui32CFieldSize = ui32YFieldSize; |
| break; |
| } |
| |
| psFrame->i32Field1YOffset = ui32YFieldSize; |
| psFrame->i32Field1UOffset = ui32CFieldSize; |
| psFrame->i32Field1VOffset = ui32CFieldSize; |
| } |
| } else { |
| psFrame->i32Field1YOffset = psFrame->i32Field0YOffset; |
| psFrame->i32Field1UOffset = psFrame->i32Field0UOffset; |
| psFrame->i32Field1VOffset = psFrame->i32Field0VOffset; |
| } |
| drv_debug_msg(VIDEO_DEBUG_GENERAL, "%s i32YComponentOffset = %d, i32UComponentOffset = %d, i32VComponentOffset = %d\n", |
| __FUNCTION__, (int)(psFrame->i32YComponentOffset), (int)(psFrame->i32UComponentOffset), (int)(psFrame->i32VComponentOffset)); |
| return VA_STATUS_SUCCESS; |
| } |
| |
| IMG_UINT32 tng_send_source_frame( |
| context_ENC_p ctx, |
| IMG_UINT32 ui32SlotIndex, |
| IMG_UINT32 ui32DisplayOrder) |
| { |
| VAStatus vaStatus = VA_STATUS_SUCCESS; |
| context_ENC_frame_buf *ps_buf = &(ctx->ctx_frame_buf); |
| IMG_FRAME sSrcFrame; |
| IMG_FRAME *psSrcFrame = &sSrcFrame; |
| tng_cmdbuf_p cmdbuf = ctx->obj_context->tng_cmdbuf; |
| IMG_SOURCE_BUFFER_PARAMS *psSrcBufParams = NULL; |
| object_surface_p src_surface = ps_buf->src_surface; |
| unsigned int frame_mem_index = 0; |
| unsigned int srf_buf_offset = src_surface->psb_surface->buf.buffer_ofs; |
| |
| drv_debug_msg(VIDEO_DEBUG_GENERAL, |
| "%s: ui32SlotIndex = %d, ui32DisplayOrder = %d\n", |
| __FUNCTION__, ui32SlotIndex, ui32DisplayOrder); |
| |
| if (cmdbuf->frame_mem_index >= COMM_CMD_FRAME_BUF_NUM) { |
| drv_debug_msg(VIDEO_DEBUG_ERROR, "%s: Error: frame_mem buffer index overflow\n", __FUNCTION__); |
| cmdbuf->frame_mem_index = 0; |
| } |
| |
| vaStatus = psb_buffer_map(&cmdbuf->frame_mem, &(cmdbuf->frame_mem_p)); |
| if (vaStatus) { |
| drv_debug_msg(VIDEO_DEBUG_ERROR, "%s: map frame buf\n", __FUNCTION__); |
| return vaStatus; |
| } |
| |
| frame_mem_index = cmdbuf->frame_mem_index * cmdbuf->mem_size; |
| psSrcBufParams = (IMG_SOURCE_BUFFER_PARAMS *)(cmdbuf->frame_mem_p + frame_mem_index); |
| memset(psSrcBufParams, 0, sizeof(IMG_SOURCE_BUFFER_PARAMS)); |
| memset(psSrcFrame, 0, sizeof(IMG_FRAME)); |
| tng__set_component_offsets(ctx, src_surface, psSrcFrame); |
| |
| drv_debug_msg(VIDEO_DEBUG_GENERAL, |
| "%s: cmdbuf->frame_mem_index = %d, frame_mem_index = 0x%08x, cmdbuf->frame_mem_p = 0x%08x\n", |
| __FUNCTION__, cmdbuf->frame_mem_index, frame_mem_index, cmdbuf->frame_mem_p); |
| drv_debug_msg(VIDEO_DEBUG_GENERAL, |
| "%s: frame_mem_index = %d, psBufferParams = 0x%08x\n", |
| __FUNCTION__, frame_mem_index, (unsigned int)psSrcBufParams); |
| |
| /* Prepare ProvideBuffer data */ |
| { |
| psSrcBufParams->ui8SlotNum = (IMG_UINT8)(ui32SlotIndex & 0xff); |
| psSrcBufParams->ui8DisplayOrderNum = (IMG_UINT8)(ui32DisplayOrder & 0xff); |
| psSrcBufParams->ui32HostContext = (IMG_UINT32)ctx; |
| |
| #ifdef _TNG_RELOC_ |
| TNG_RELOC_CMDBUF_FRAMES( |
| &(psSrcBufParams->ui32PhysAddrYPlane_Field0), |
| srf_buf_offset + psSrcFrame->i32YComponentOffset + psSrcFrame->i32Field0YOffset, |
| &(src_surface->psb_surface->buf)); |
| TNG_RELOC_CMDBUF_FRAMES( |
| &(psSrcBufParams->ui32PhysAddrUPlane_Field0), |
| srf_buf_offset + psSrcFrame->i32UComponentOffset + psSrcFrame->i32Field0UOffset, |
| &(src_surface->psb_surface->buf)); |
| TNG_RELOC_CMDBUF_FRAMES( |
| &(psSrcBufParams->ui32PhysAddrVPlane_Field0), |
| srf_buf_offset + psSrcFrame->i32VComponentOffset + psSrcFrame->i32Field0VOffset, |
| &(src_surface->psb_surface->buf)); |
| |
| TNG_RELOC_CMDBUF_FRAMES( |
| &(psSrcBufParams->ui32PhysAddrYPlane_Field1), |
| srf_buf_offset + psSrcFrame->i32YComponentOffset + psSrcFrame->i32Field1YOffset, |
| &(src_surface->psb_surface->buf)); |
| TNG_RELOC_CMDBUF_FRAMES( |
| &(psSrcBufParams->ui32PhysAddrUPlane_Field1), |
| srf_buf_offset + psSrcFrame->i32UComponentOffset + psSrcFrame->i32Field1UOffset, |
| &(src_surface->psb_surface->buf)); |
| TNG_RELOC_CMDBUF_FRAMES( |
| &(psSrcBufParams->ui32PhysAddrVPlane_Field1), |
| srf_buf_offset + psSrcFrame->i32VComponentOffset + psSrcFrame->i32Field1VOffset, |
| &(src_surface->psb_surface->buf)); |
| #else |
| tng_cmdbuf_set_phys(&(psSrcBufParams->ui32PhysAddrYPlane_Field0), 0, |
| &(src_surface->psb_surface->buf), |
| srf_buf_offset + psSrcFrame->i32YComponentOffset + psSrcFrame->i32Field0YOffset, 0); |
| tng_cmdbuf_set_phys(&(psSrcBufParams->ui32PhysAddrUPlane_Field0), 0, |
| &(src_surface->psb_surface->buf), |
| srf_buf_offset + psSrcFrame->i32UComponentOffset + psSrcFrame->i32Field0UOffset, 0); |
| tng_cmdbuf_set_phys(&(psSrcBufParams->ui32PhysAddrVPlane_Field0), 0, |
| &(src_surface->psb_surface->buf), |
| srf_buf_offset + psSrcFrame->i32VComponentOffset + psSrcFrame->i32Field0VOffset, 0); |
| |
| tng_cmdbuf_set_phys(&(psSrcBufParams->ui32PhysAddrYPlane_Field1), 0, |
| &(src_surface->psb_surface->buf), |
| srf_buf_offset + psSrcFrame->i32YComponentOffset + psSrcFrame->i32Field1YOffset, 0); |
| tng_cmdbuf_set_phys(&(psSrcBufParams->ui32PhysAddrUPlane_Field1), 0, |
| &(src_surface->psb_surface->buf), |
| srf_buf_offset + psSrcFrame->i32UComponentOffset + psSrcFrame->i32Field1UOffset, 0); |
| tng_cmdbuf_set_phys(&(psSrcBufParams->ui32PhysAddrVPlane_Field1), 0, |
| &(src_surface->psb_surface->buf), |
| srf_buf_offset + psSrcFrame->i32VComponentOffset + psSrcFrame->i32Field1VOffset, 0); |
| #endif |
| } |
| drv_debug_msg(VIDEO_DEBUG_GENERAL, |
| "%s slot_idx = %d, frame_count = %d\n", __FUNCTION__, |
| (int)(ui32SlotIndex), (int)(ctx->ui32FrameCount[ctx->ui32StreamID])); |
| drv_debug_msg(VIDEO_DEBUG_GENERAL, |
| "%s: YPlane_Field0 = 0x%08x, UPlane_Field0 = 0x%08x, VPlane_Field0 = 0x%08x\n", |
| __FUNCTION__, (unsigned int)(psSrcBufParams->ui32PhysAddrYPlane_Field0), |
| (unsigned int)(psSrcBufParams->ui32PhysAddrUPlane_Field0), |
| (unsigned int)(psSrcBufParams->ui32PhysAddrVPlane_Field0)); |
| drv_debug_msg(VIDEO_DEBUG_GENERAL, |
| "%s: YPlane_Field1 = 0x%08x, UPlane_Field1 = 0x%08x, VPlane_Field1 = 0x%08x\n", |
| __FUNCTION__, (unsigned int)(psSrcBufParams->ui32PhysAddrYPlane_Field1), |
| (unsigned int)(psSrcBufParams->ui32PhysAddrUPlane_Field1), |
| (unsigned int)(psSrcBufParams->ui32PhysAddrVPlane_Field1)); |
| |
| /* Send ProvideBuffer Command */ |
| tng_cmdbuf_insert_command(ctx->obj_context, ctx->ui32StreamID, |
| MTX_CMDID_PROVIDE_SOURCE_BUFFER, |
| 0, &(cmdbuf->frame_mem), frame_mem_index); |
| |
| ++(cmdbuf->frame_mem_index); |
| psb_buffer_unmap(&cmdbuf->frame_mem); |
| |
| return 0; |
| } |
| |
| |
| IMG_UINT32 tng_send_rec_frames( |
| context_ENC_p ctx, |
| IMG_INT8 i8HeaderSlotNum, |
| IMG_BOOL bLongTerm) |
| { |
| //VAStatus vaStatus = VA_STATUS_SUCCESS; |
| unsigned int srf_buf_offset; |
| context_ENC_frame_buf *ps_buf = &(ctx->ctx_frame_buf); |
| object_surface_p rec_surface = ps_buf->rec_surface; |
| IMG_UINT32 ui32CmdData = 0; |
| |
| srf_buf_offset = rec_surface->psb_surface->buf.buffer_ofs; |
| /* Send ProvideBuffer Command */ |
| ui32CmdData = F_ENCODE(IMG_BUFFER_RECON, MTX_MSG_PROVIDE_REF_BUFFER_USE) | |
| F_ENCODE(i8HeaderSlotNum, MTX_MSG_PROVIDE_REF_BUFFER_SLOT) | |
| F_ENCODE(bLongTerm, MTX_MSG_PROVIDE_REF_BUFFER_LT); |
| |
| tng_cmdbuf_insert_command(ctx->obj_context, ctx->ui32StreamID, |
| MTX_CMDID_PROVIDE_REF_BUFFER, |
| ui32CmdData, &(rec_surface->psb_surface->buf), 0); |
| |
| return 0; |
| } |
| |
| IMG_UINT32 tng_send_ref_frames( |
| context_ENC_p ctx, |
| IMG_UINT32 ui32refindex, |
| IMG_BOOL __maybe_unused bLongTerm) |
| { |
| //VAStatus vaStatus = VA_STATUS_SUCCESS; |
| unsigned int srf_buf_offset; |
| context_ENC_frame_buf *ps_buf = &(ctx->ctx_frame_buf); |
| object_surface_p ref_surface = ps_buf->ref_surface[ui32refindex]; |
| IMG_UINT32 ui32CmdData = 0; |
| |
| #ifdef _TNG_FRAMES_ |
| if (ui32RefIndex == 0) { |
| ref_surface = ps_buf->ref_surface; |
| ui32CmdData = F_ENCODE(IMG_BUFFER_REF0, MTX_MSG_PROVIDE_REF_BUFFER_USE) | |
| F_ENCODE(bLongTerm, MTX_MSG_PROVIDE_REF_BUFFER_LT); |
| } else { |
| ref_surface = ps_buf->ref_surface1; |
| ui32CmdData = F_ENCODE(IMG_BUFFER_REF1, MTX_MSG_PROVIDE_REF_BUFFER_USE) | |
| F_ENCODE(bLongTerm, MTX_MSG_PROVIDE_REF_BUFFER_LT); |
| } |
| #endif |
| srf_buf_offset = ref_surface->psb_surface->buf.buffer_ofs; |
| /* Send ProvideBuffer Command */ |
| tng_cmdbuf_insert_command(ctx->obj_context, ctx->ui32StreamID, |
| MTX_CMDID_PROVIDE_REF_BUFFER, |
| ui32CmdData, &(ref_surface->psb_surface->buf), 0); |
| |
| return VA_STATUS_SUCCESS; |
| } |
| |