| /* |
| * 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: |
| * Elaine Wang <elaine.wang@intel.com> |
| * Zeng Li <zeng.li@intel.com> |
| * Edward Lin <edward.lin@intel.com> |
| * |
| */ |
| |
| #include "psb_drv_video.h" |
| //#include "tng_H263ES.h" |
| #include "tng_hostheader.h" |
| #include "tng_hostcode.h" |
| #include "psb_def.h" |
| #include "psb_drv_debug.h" |
| #include "psb_cmdbuf.h" |
| #include "psb_buffer.h" |
| #include <stdio.h> |
| #include "psb_output.h" |
| #include "tng_picmgmt.h" |
| #include "tng_hostbias.h" |
| #include "tng_hostair.h" |
| #ifdef _TOPAZHP_PDUMP_ |
| #include "tng_trace.h" |
| #endif |
| #include <wsbm/wsbm_manager.h> |
| |
| #include "hwdefs/topazhp_core_regs.h" |
| #include "hwdefs/topazhp_multicore_regs_old.h" |
| #include "hwdefs/topaz_db_regs.h" |
| #include "hwdefs/topaz_vlc_regs.h" |
| #include "hwdefs/mvea_regs.h" |
| #include "hwdefs/topazhp_default_params.h" |
| |
| #define ALIGN_TO(value, align) ((value + align - 1) & ~(align - 1)) |
| #define PAGE_ALIGN(value) ALIGN_TO(value, 4096) |
| #define DEFAULT_MVCALC_CONFIG ((0x00040303)|(MASK_TOPAZHP_CR_MVCALC_JITTER_POINTER_RST)) |
| #define DEFAULT_MVCALC_COLOCATED (0x00100100) |
| #define MVEA_MV_PARAM_REGION_SIZE 16 |
| #define MVEA_ABOVE_PARAM_REGION_SIZE 96 |
| #define QUANT_LISTS_SIZE (224) |
| #define _1080P_30FPS (((1920*1088)/256)*30) |
| #define tng_align_64(X) (((X)+63) &~63) |
| #define tng_align_4(X) (((X)+3) &~3) |
| |
| /* #define MTX_CONTEXT_ITEM_OFFSET(type, member) (size_t)&(((type*)0)->member) */ |
| |
| #define DEFAULT_CABAC_DB_MARGIN (0x190) |
| #define NOT_USED_BY_TOPAZ 0 |
| /* |
| #define _TOPAZHP_CMDBUF_ |
| */ |
| #ifdef _TOPAZHP_CMDBUF_ |
| static void tng__trace_cmdbuf_words(tng_cmdbuf_p cmdbuf) |
| { |
| int i = 0; |
| IMG_UINT32 *ptmp = (IMG_UINT32 *)(cmdbuf->cmd_start); |
| IMG_UINT32 *pend = (IMG_UINT32 *)(cmdbuf->cmd_idx); |
| do { |
| drv_debug_msg(VIDEO_DEBUG_GENERAL, "%s: command words [%d] = 0x%08x\n", __FUNCTION__, i++, (unsigned int)(*ptmp++)); |
| } while(ptmp < pend); |
| return ; |
| } |
| #endif |
| |
| #if 0 |
| static IMG_UINT32 tng__get_codedbuffer_size( |
| IMG_STANDARD eStandard, |
| IMG_UINT16 ui16MBWidth, |
| IMG_UINT16 ui16MBHeight, |
| IMG_RC_PARAMS * psRCParams |
| ) |
| { |
| if (eStandard == IMG_STANDARD_H264) { |
| // allocate based on worst case qp size |
| return ((IMG_UINT32)ui16MBWidth * (IMG_UINT32)ui16MBHeight * 400); |
| } |
| |
| if (psRCParams->ui32InitialQp <= 5) |
| return ((IMG_UINT32)ui16MBWidth * (IMG_UINT32)ui16MBHeight * 1600); |
| |
| return ((IMG_UINT32)ui16MBWidth * (IMG_UINT32)ui16MBHeight * 900); |
| } |
| |
| |
| static IMG_UINT32 tng__get_codedbuf_size_according_bitrate( |
| IMG_RC_PARAMS * psRCParams |
| ) |
| { |
| return ((psRCParams->ui32BitsPerSecond + psRCParams->ui32FrameRate / 2) / psRCParams->ui32FrameRate) * 2; |
| } |
| |
| static IMG_UINT32 tng__get_buffer_size(IMG_UINT32 src_size) |
| { |
| return (src_size + 0x1000) & (~0xfff); |
| } |
| #endif |
| |
| //static inline |
| VAStatus tng__alloc_init_buffer( |
| psb_driver_data_p driver_data, |
| unsigned int size, |
| psb_buffer_type_t type, |
| psb_buffer_p buf) |
| { |
| unsigned char *pch_virt_addr; |
| VAStatus vaStatus = VA_STATUS_SUCCESS; |
| vaStatus = psb_buffer_create(driver_data, size, type, buf); |
| if (VA_STATUS_SUCCESS != vaStatus) { |
| drv_debug_msg(VIDEO_DEBUG_ERROR, "alloc mem params buffer"); |
| return vaStatus; |
| } |
| |
| vaStatus = psb_buffer_map(buf, &pch_virt_addr); |
| drv_debug_msg(VIDEO_DEBUG_GENERAL, "%s: phy addr 0x%08x, vir addr 0x%08x\n", __FUNCTION__, buf->drm_buf, pch_virt_addr); |
| if ((vaStatus) || (pch_virt_addr == NULL)) { |
| drv_debug_msg(VIDEO_DEBUG_ERROR, "%s: map buf 0x%08x\n", __FUNCTION__, (IMG_UINT32)pch_virt_addr); |
| psb_buffer_destroy(buf); |
| } else { |
| memset(pch_virt_addr, 0, size); |
| psb_buffer_unmap(buf); |
| } |
| |
| return vaStatus; |
| } |
| |
| static VAStatus tng__alloc_context_buffer(context_ENC_p ctx, IMG_UINT8 ui8IsJpeg, IMG_UINT32 ui32StreamID) |
| { |
| VAStatus vaStatus = VA_STATUS_SUCCESS; |
| IMG_UINT32 ui32_pic_width, ui32_pic_height; |
| IMG_UINT32 ui32_mb_per_row, ui32_mb_per_column; |
| IMG_UINT32 ui32_adj_mb_per_row = 0; |
| IMG_RC_PARAMS *psRCParams = &(ctx->sRCParams); |
| psb_driver_data_p ps_driver_data = ctx->obj_context->driver_data; |
| context_ENC_mem *ps_mem = &(ctx->ctx_mem[ui32StreamID]); |
| context_ENC_mem_size *ps_mem_size = &(ctx->ctx_mem_size); |
| |
| if (ctx->eStandard == IMG_STANDARD_H264) { |
| ctx->ui8PipesToUse = tng__min(ctx->ui8PipesToUse, ctx->ui8SlicesPerPicture); |
| } else { |
| ctx->ui8PipesToUse = 1; |
| } |
| |
| ctx->i32PicNodes = (psRCParams->b16Hierarchical ? MAX_REF_B_LEVELS : 0) + 4; |
| ctx->i32MVStores = (ctx->i32PicNodes * 2); |
| ctx->i32CodedBuffers = (IMG_INT32)(ctx->ui8PipesToUse) * (ctx->bIsInterlaced ? 3 : 2); |
| ctx->ui8SlotsInUse = psRCParams->ui16BFrames + 2; |
| |
| if (0 != ui8IsJpeg) { |
| ctx->jpeg_pic_params_size = (sizeof(JPEG_MTX_QUANT_TABLE) + 0x3f) & (~0x3f); |
| ctx->jpeg_header_mem_size = (sizeof(JPEG_MTX_DMA_SETUP) + 0x3f) & (~0x3f); |
| ctx->jpeg_header_interface_mem_size = (sizeof(JPEG_MTX_WRITEBACK_MEMORY) + 0x3f) & (~0x3f); |
| |
| //write back region |
| ps_mem_size->writeback = tng_align_KB(COMM_WB_DATA_BUF_SIZE); |
| tng__alloc_init_buffer(ps_driver_data, WB_FIFO_SIZE * ps_mem_size->writeback, psb_bt_cpu_vpu, &(ctx->bufs_writeback)); |
| |
| drv_debug_msg(VIDEO_DEBUG_GENERAL, "%s: end\n", __FUNCTION__); |
| return vaStatus; |
| } |
| |
| /* width and height should be source surface's w and h or ?? */ |
| ui32_pic_width = ctx->obj_context->picture_width; |
| ui32_mb_per_row = (ctx->obj_context->picture_width + 15) >> 4; |
| ui32_pic_height = ctx->obj_context->picture_height; |
| ui32_mb_per_column = (ctx->obj_context->picture_height + 15) >> 4; |
| ui32_adj_mb_per_row = ((ui32_mb_per_row + 7)>>3)<<3; // Ensure multiple of 8 MBs per row |
| |
| //command buffer use |
| ps_mem_size->pic_template = ps_mem_size->slice_template = |
| ps_mem_size->seq_header = tng_align_KB(TNG_HEADER_SIZE); |
| tng__alloc_init_buffer(ps_driver_data, ps_mem_size->seq_header, |
| psb_bt_cpu_vpu, &(ps_mem->bufs_seq_header)); |
| |
| if (ctx->bEnableMVC) |
| tng__alloc_init_buffer(ps_driver_data, ps_mem_size->seq_header, |
| psb_bt_cpu_vpu, &(ps_mem->bufs_sub_seq_header)); |
| |
| tng__alloc_init_buffer(ps_driver_data, 4 * ps_mem_size->pic_template, |
| psb_bt_cpu_vpu, &(ps_mem->bufs_pic_template)); |
| |
| tng__alloc_init_buffer(ps_driver_data, NUM_SLICE_TYPES * ps_mem_size->slice_template, |
| psb_bt_cpu_vpu, &(ps_mem->bufs_slice_template)); |
| |
| ps_mem_size->mtx_context = tng_align_KB(MTX_CONTEXT_SIZE); |
| tng__alloc_init_buffer(ps_driver_data, ps_mem_size->mtx_context, |
| psb_bt_cpu_vpu, &(ps_mem->bufs_mtx_context)); |
| |
| //sei header(AUDHeader+SEIBufferPeriodMem+SEIPictureTimingHeaderMem) |
| ps_mem_size->sei_header = tng_align_KB(64); |
| tng__alloc_init_buffer(ps_driver_data, 3 * ps_mem_size->sei_header, |
| psb_bt_cpu_vpu, &(ps_mem->bufs_sei_header)); |
| |
| //gop header |
| ps_mem_size->flat_gop = ps_mem_size->hierar_gop = tng_align_KB(64); |
| tng__alloc_init_buffer(ps_driver_data, ps_mem_size->flat_gop, |
| psb_bt_cpu_vpu, &(ps_mem->bufs_flat_gop)); |
| tng__alloc_init_buffer(ps_driver_data, ps_mem_size->hierar_gop, |
| psb_bt_cpu_vpu, &(ps_mem->bufs_hierar_gop)); |
| |
| //above params |
| ps_mem_size->above_params = tng_align_KB(MVEA_ABOVE_PARAM_REGION_SIZE * tng_align_64(ui32_mb_per_row)); |
| tng__alloc_init_buffer(ps_driver_data, (IMG_UINT32)(ctx->ui8PipesToUse) * ps_mem_size->above_params, |
| psb_bt_cpu_vpu, &(ps_mem->bufs_above_params)); |
| |
| //ctx->mv_setting_btable_size = tng_align_KB(MAX_BFRAMES * (tng_align_64(sizeof(IMG_MV_SETTINGS) * MAX_BFRAMES))); |
| ps_mem_size->mv_setting_btable = tng_align_KB(MAX_BFRAMES * MV_ROW_STRIDE); |
| tng__alloc_init_buffer(ps_driver_data, ps_mem_size->mv_setting_btable, |
| psb_bt_cpu_vpu, &(ps_mem->bufs_mv_setting_btable)); |
| |
| ps_mem_size->mv_setting_hierar = tng_align_KB(MAX_BFRAMES * sizeof(IMG_MV_SETTINGS)); |
| tng__alloc_init_buffer(ps_driver_data, ps_mem_size->mv_setting_hierar, |
| psb_bt_cpu_vpu, &(ps_mem->bufs_mv_setting_hierar)); |
| |
| //colocated params |
| ps_mem_size->colocated = tng_align_KB(MVEA_MV_PARAM_REGION_SIZE * tng_align_4(ui32_mb_per_row * ui32_mb_per_column)); |
| tng__alloc_init_buffer(ps_driver_data, ctx->i32PicNodes * ps_mem_size->colocated, |
| psb_bt_cpu_vpu, &(ps_mem->bufs_colocated)); |
| |
| ps_mem_size->interview_mv = ps_mem_size->mv = ps_mem_size->colocated; |
| tng__alloc_init_buffer(ps_driver_data, ctx->i32MVStores * ps_mem_size->mv, |
| psb_bt_cpu_vpu, &(ps_mem->bufs_mv)); |
| |
| if (ctx->bEnableMVC) { |
| tng__alloc_init_buffer(ps_driver_data, 2 * ps_mem_size->interview_mv, |
| psb_bt_cpu_vpu, &(ps_mem->bufs_interview_mv)); |
| } |
| |
| //write back region |
| ps_mem_size->writeback = tng_align_KB(COMM_WB_DATA_BUF_SIZE); |
| tng__alloc_init_buffer(ps_driver_data, WB_FIFO_SIZE * ps_mem_size->writeback, |
| psb_bt_cpu_vpu, &(ctx->bufs_writeback)); |
| |
| ps_mem_size->slice_map = tng_align_KB(0x1500); //(1 + MAX_SLICESPERPIC * 2 + 15) & ~15); |
| tng__alloc_init_buffer(ps_driver_data, ctx->ui8SlotsInUse * ps_mem_size->slice_map, |
| psb_bt_cpu_vpu, &(ps_mem->bufs_slice_map)); |
| |
| ps_mem_size->weighted_prediction = tng_align_KB(sizeof(WEIGHTED_PREDICTION_VALUES)); |
| tng__alloc_init_buffer(ps_driver_data, ctx->ui8SlotsInUse * ps_mem_size->weighted_prediction, |
| psb_bt_cpu_vpu, &(ps_mem->bufs_weighted_prediction)); |
| |
| #ifdef LTREFHEADER |
| ps_mem_size->lt_ref_header = tng_align_KB((sizeof(MTX_HEADER_PARAMS)+63)&~63); |
| tng__alloc_init_buffer(ps_driver_data, ctx->ui8SlotsInUse * ps_mem_size->lt_ref_header, |
| psb_bt_cpu_vpu, &(ps_mem->bufs_lt_ref_header)); |
| #endif |
| |
| ps_mem_size->recon_pictures = tng_align_KB((tng_align_64(ui32_pic_width)*tng_align_64(ui32_pic_height))*3/2); |
| tng__alloc_init_buffer(ps_driver_data, ctx->i32PicNodes * ps_mem_size->recon_pictures, |
| psb_bt_cpu_vpu, &(ps_mem->bufs_recon_pictures)); |
| |
| ctx->ctx_mem_size.first_pass_out_params = tng_align_KB(sizeof(IMG_FIRST_STAGE_MB_PARAMS) * ui32_mb_per_row * ui32_mb_per_column); |
| tng__alloc_init_buffer(ps_driver_data, ctx->ui8SlotsInUse * ctx->ctx_mem_size.first_pass_out_params, |
| psb_bt_cpu_vpu, &(ps_mem->bufs_first_pass_out_params)); |
| |
| #ifndef EXCLUDE_BEST_MP_DECISION_DATA |
| ctx->ctx_mem_size.first_pass_out_best_multipass_param = tng_align_KB(ui32_mb_per_column * (((5*ui32_mb_per_row)+3)>>2) * 64); |
| tng__alloc_init_buffer(ps_driver_data, ctx->ui8SlotsInUse * ctx->ctx_mem_size.first_pass_out_best_multipass_param, |
| psb_bt_cpu_vpu, &(ps_mem->bufs_first_pass_out_best_multipass_param)); |
| #endif |
| |
| ctx->ctx_mem_size.mb_ctrl_in_params = tng_align_KB(sizeof(IMG_FIRST_STAGE_MB_PARAMS) * ui32_adj_mb_per_row * ui32_mb_per_column); |
| tng__alloc_init_buffer(ps_driver_data, ctx->ui8SlotsInUse * ctx->ctx_mem_size.mb_ctrl_in_params, |
| psb_bt_cpu_vpu, &(ps_mem->bufs_mb_ctrl_in_params)); |
| |
| ctx->ctx_mem_size.lowpower_params = tng_align_KB(TNG_HEADER_SIZE); |
| tng__alloc_init_buffer(ps_driver_data, ps_mem_size->lowpower_params, |
| psb_bt_cpu_vpu, &(ps_mem->bufs_lowpower_params)); |
| |
| ctx->ctx_mem_size.lowpower_data = tng_align_KB(0x10000); |
| |
| return vaStatus; |
| } |
| |
| static void tng__free_context_buffer(context_ENC_p ctx, unsigned char is_JPEG, unsigned int stream_id) |
| { |
| context_ENC_mem *ps_mem = &(ctx->ctx_mem[stream_id]); |
| |
| if (0 != is_JPEG) { |
| psb_buffer_destroy(&(ctx->bufs_writeback)); |
| return; |
| } |
| psb_buffer_destroy(&(ps_mem->bufs_seq_header)); |
| if (ctx->bEnableMVC) |
| psb_buffer_destroy(&(ps_mem->bufs_sub_seq_header)); |
| psb_buffer_destroy(&(ps_mem->bufs_pic_template)); |
| psb_buffer_destroy(&(ps_mem->bufs_slice_template)); |
| psb_buffer_destroy(&(ps_mem->bufs_mtx_context)); |
| psb_buffer_destroy(&(ps_mem->bufs_sei_header)); |
| |
| psb_buffer_destroy(&(ps_mem->bufs_flat_gop)); |
| psb_buffer_destroy(&(ps_mem->bufs_hierar_gop)); |
| psb_buffer_destroy(&(ps_mem->bufs_above_params)); |
| psb_buffer_destroy(&(ps_mem->bufs_mv_setting_btable)); |
| psb_buffer_destroy(&(ps_mem->bufs_mv_setting_hierar)); |
| psb_buffer_destroy(&(ps_mem->bufs_colocated)); |
| psb_buffer_destroy(&(ps_mem->bufs_mv)); |
| if (ctx->bEnableMVC) |
| psb_buffer_destroy(&(ps_mem->bufs_interview_mv)); |
| |
| psb_buffer_destroy(&(ctx->bufs_writeback)); |
| psb_buffer_destroy(&(ps_mem->bufs_slice_map)); |
| psb_buffer_destroy(&(ps_mem->bufs_weighted_prediction)); |
| #ifdef LTREFHEADER |
| psb_buffer_destroy(&(ps_mem->bufs_lt_ref_header)); |
| #endif |
| psb_buffer_destroy(&(ps_mem->bufs_recon_pictures)); |
| psb_buffer_destroy(&(ps_mem->bufs_first_pass_out_params)); |
| #ifndef EXCLUDE_BEST_MP_DECISION_DATA |
| psb_buffer_destroy(&(ps_mem->bufs_first_pass_out_best_multipass_param)); |
| #endif |
| psb_buffer_destroy(&(ps_mem->bufs_mb_ctrl_in_params)); |
| psb_buffer_destroy(&(ps_mem->bufs_lowpower_params)); |
| |
| return ; |
| } |
| |
| unsigned int tng__get_ipe_control(IMG_CODEC eEncodingFormat) |
| { |
| unsigned int RegVal = 0; |
| |
| RegVal = F_ENCODE(2, MVEA_CR_IPE_GRID_FINE_SEARCH) | |
| F_ENCODE(0, MVEA_CR_IPE_GRID_SEARCH_SIZE) | |
| F_ENCODE(1, MVEA_CR_IPE_Y_FINE_SEARCH); |
| |
| switch (eEncodingFormat) { |
| case IMG_CODEC_H263_NO_RC: |
| case IMG_CODEC_H263_VBR: |
| case IMG_CODEC_H263_CBR: |
| RegVal |= F_ENCODE(0, MVEA_CR_IPE_BLOCKSIZE) | F_ENCODE(0, MVEA_CR_IPE_ENCODING_FORMAT); |
| break; |
| case IMG_CODEC_MPEG4_NO_RC: |
| case IMG_CODEC_MPEG4_VBR: |
| case IMG_CODEC_MPEG4_CBR: |
| RegVal |= F_ENCODE(1, MVEA_CR_IPE_BLOCKSIZE) | F_ENCODE(1, MVEA_CR_IPE_ENCODING_FORMAT); |
| default: |
| break; |
| case IMG_CODEC_H264_NO_RC: |
| case IMG_CODEC_H264_VBR: |
| case IMG_CODEC_H264_CBR: |
| case IMG_CODEC_H264_VCM: |
| RegVal |= F_ENCODE(2, MVEA_CR_IPE_BLOCKSIZE) | F_ENCODE(2, MVEA_CR_IPE_ENCODING_FORMAT); |
| break; |
| } |
| RegVal |= F_ENCODE(6, MVEA_CR_IPE_Y_CANDIDATE_NUM); |
| return RegVal; |
| } |
| |
| void tng__setup_enc_profile_features(context_ENC_p ctx, IMG_UINT32 ui32EncProfile) |
| { |
| IMG_ENCODE_FEATURES * pEncFeatures = &ctx->sEncFeatures; |
| /* Set the default values first */ |
| pEncFeatures->bDisableBPicRef_0 = IMG_FALSE; |
| pEncFeatures->bDisableBPicRef_1 = IMG_FALSE; |
| |
| pEncFeatures->bDisableInter8x8 = IMG_FALSE; |
| pEncFeatures->bRestrictInter4x4 = IMG_FALSE; |
| |
| pEncFeatures->bDisableIntra4x4 = IMG_FALSE; |
| pEncFeatures->bDisableIntra8x8 = IMG_FALSE; |
| pEncFeatures->bDisableIntra16x16 = IMG_FALSE; |
| |
| pEncFeatures->bEnable8x16MVDetect = IMG_TRUE; |
| pEncFeatures->bEnable16x8MVDetect = IMG_TRUE; |
| pEncFeatures->bDisableBFrames = IMG_FALSE; |
| |
| pEncFeatures->eMinBlkSz = BLK_SZ_DEFAULT; |
| |
| switch (ui32EncProfile) { |
| case ENC_PROFILE_LOWCOMPLEXITY: |
| pEncFeatures->bDisableInter8x8 = IMG_TRUE; |
| pEncFeatures->bRestrictInter4x4 = IMG_TRUE; |
| pEncFeatures->bDisableIntra4x4 = IMG_TRUE; |
| pEncFeatures->bDisableIntra8x8 = IMG_TRUE; |
| pEncFeatures->bRestrictInter4x4 = IMG_TRUE; |
| pEncFeatures->eMinBlkSz = BLK_SZ_16x16; |
| pEncFeatures->bDisableBFrames = IMG_TRUE; |
| break; |
| |
| case ENC_PROFILE_HIGHCOMPLEXITY: |
| pEncFeatures->bDisableBPicRef_0 = IMG_FALSE; |
| pEncFeatures->bDisableBPicRef_1 = IMG_FALSE; |
| |
| pEncFeatures->bDisableInter8x8 = IMG_FALSE; |
| pEncFeatures->bRestrictInter4x4 = IMG_FALSE; |
| |
| pEncFeatures->bDisableIntra4x4 = IMG_FALSE; |
| pEncFeatures->bDisableIntra8x8 = IMG_FALSE; |
| pEncFeatures->bDisableIntra16x16 = IMG_FALSE; |
| |
| pEncFeatures->bEnable8x16MVDetect = IMG_TRUE; |
| pEncFeatures->bEnable16x8MVDetect = IMG_TRUE; |
| break; |
| } |
| |
| if (ctx->eStandard != IMG_STANDARD_H264) { |
| pEncFeatures->bEnable8x16MVDetect = IMG_FALSE; |
| pEncFeatures->bEnable16x8MVDetect = IMG_FALSE; |
| } |
| |
| return; |
| } |
| |
| VAStatus tng__patch_hw_profile(context_ENC_p ctx) |
| { |
| IMG_UINT32 ui32IPEControl = 0; |
| IMG_UINT32 ui32PredCombControl = 0; |
| IMG_ENCODE_FEATURES * psEncFeatures = &(ctx->sEncFeatures); |
| |
| // bDisableIntra4x4 |
| if (psEncFeatures->bDisableIntra4x4) |
| ui32PredCombControl |= F_ENCODE(1, TOPAZHP_CR_INTRA4X4_DISABLE); |
| |
| //bDisableIntra8x8 |
| if (psEncFeatures->bDisableIntra8x8) |
| ui32PredCombControl |= F_ENCODE(1, TOPAZHP_CR_INTRA8X8_DISABLE); |
| |
| //bDisableIntra16x16, check if atleast one of the other Intra mode is enabled |
| if ((psEncFeatures->bDisableIntra16x16) && |
| (!(psEncFeatures->bDisableIntra8x8) || !(psEncFeatures->bDisableIntra4x4))) { |
| ui32PredCombControl |= F_ENCODE(1, TOPAZHP_CR_INTRA16X16_DISABLE); |
| } |
| |
| if (psEncFeatures->bRestrictInter4x4) { |
| // ui32PredCombControl |= F_ENCODE(1, TOPAZHP_CR_INTER4X4_RESTRICT); |
| ui32IPEControl |= F_ENCODE(1, TOPAZHP_CR_IPE_MV_NUMBER_RESTRICTION); |
| } |
| |
| if (psEncFeatures->bDisableInter8x8) |
| ui32PredCombControl |= F_ENCODE(1, TOPAZHP_CR_INTER8X8_DISABLE); |
| |
| if (psEncFeatures->bDisableBPicRef_1) |
| ui32PredCombControl |= F_ENCODE(1, TOPAZHP_CR_B_PIC1_DISABLE); |
| else if (psEncFeatures->bDisableBPicRef_0) |
| ui32PredCombControl |= F_ENCODE(1, TOPAZHP_CR_B_PIC0_DISABLE); |
| |
| // save predictor combiner control in video encode parameter set |
| ctx->ui32PredCombControl = ui32PredCombControl; |
| |
| // set blocksize |
| ui32IPEControl |= F_ENCODE(psEncFeatures->eMinBlkSz, TOPAZHP_CR_IPE_BLOCKSIZE); |
| |
| if (psEncFeatures->bEnable8x16MVDetect) |
| ui32IPEControl |= F_ENCODE(1, TOPAZHP_CR_IPE_8X16_ENABLE); |
| |
| if (psEncFeatures->bEnable16x8MVDetect) |
| ui32IPEControl |= F_ENCODE(1, TOPAZHP_CR_IPE_16X8_ENABLE); |
| |
| if (psEncFeatures->bDisableBFrames) |
| ctx->sRCParams.ui16BFrames = 0; |
| |
| //save IPE-control register |
| ctx->ui32IPEControl = ui32IPEControl; |
| |
| return VA_STATUS_SUCCESS; |
| } |
| |
| #ifdef _TOPAZHP_CMDBUF_ |
| static void tng__trace_cmdbuf(tng_cmdbuf_p cmdbuf, int idx) |
| { |
| IMG_UINT32 ui32CmdTmp[4]; |
| IMG_UINT32 *ptmp = (IMG_UINT32 *)(cmdbuf->cmd_start); |
| IMG_UINT32 *pend = (IMG_UINT32 *)(cmdbuf->cmd_idx); |
| IMG_UINT32 ui32Len; |
| |
| drv_debug_msg(VIDEO_DEBUG_GENERAL, "%s: start, stream (%d), ptmp (0x%08x), pend (0x%08x}\n", __FUNCTION__, idx, (unsigned int)ptmp, (unsigned int)pend); |
| |
| if (idx) |
| return ; |
| |
| while (ptmp < pend) { |
| drv_debug_msg(VIDEO_DEBUG_GENERAL, "%s: ptmp (0x%08x}\n", __FUNCTION__, *ptmp); |
| if ((*ptmp & 0x7f) == MTX_CMDID_SW_NEW_CODEC) { |
| ptmp += 4; |
| } else if ((*ptmp & 0x7f) == MTX_CMDID_SW_LEAVE_LOWPOWER) { |
| ptmp += 2; |
| } else if ((*ptmp & 0x7f) == MTX_CMDID_SW_WRITEREG) { |
| ui32Len = *(++ptmp); |
| drv_debug_msg(VIDEO_DEBUG_GENERAL, "%s: len = %d\n", __FUNCTION__, ui32Len); |
| ptmp += (ui32Len * 3) + 1; |
| drv_debug_msg(VIDEO_DEBUG_GENERAL, "%s: reg ptmp (0x%08x}\n", __FUNCTION__, *ptmp); |
| } else if ((*ptmp & 0x7f) == MTX_CMDID_DO_HEADER) { |
| ui32CmdTmp[0] = *ptmp++; |
| ui32CmdTmp[1] = *ptmp++; |
| ui32CmdTmp[2] = *ptmp++; |
| ui32CmdTmp[3] = 0; |
| //topazhp_dump_command((unsigned int*)ui32CmdTmp); |
| ptmp += 2; |
| } else if ( |
| ((*ptmp & 0x7f) == MTX_CMDID_SETVIDEO)|| |
| ((*ptmp & 0x7f) == MTX_CMDID_SHUTDOWN)) { |
| ui32CmdTmp[0] = *ptmp++; |
| ui32CmdTmp[1] = *ptmp++; |
| ui32CmdTmp[2] = *ptmp++; |
| ui32CmdTmp[3] = *ptmp++; |
| //topazhp_dump_command((unsigned int*)ui32CmdTmp); |
| } else if ( |
| ((*ptmp & 0x7f) == MTX_CMDID_PROVIDE_SOURCE_BUFFER) || |
| ((*ptmp & 0x7f) == MTX_CMDID_PROVIDE_REF_BUFFER) || |
| ((*ptmp & 0x7f) == MTX_CMDID_PROVIDE_CODED_BUFFER) || |
| ((*ptmp & 0x7f) == MTX_CMDID_PICMGMT) || |
| ((*ptmp & 0x7f) == MTX_CMDID_ENCODE_FRAME)) { |
| ui32CmdTmp[0] = *ptmp++; |
| ui32CmdTmp[1] = *ptmp++; |
| ui32CmdTmp[2] = *ptmp++; |
| ui32CmdTmp[3] = 0; |
| //topazhp_dump_command((unsigned int*)ui32CmdTmp); |
| } else { |
| drv_debug_msg(VIDEO_DEBUG_ERROR, "%s: error leave lowpower = 0x%08x\n", __FUNCTION__, *ptmp++); |
| } |
| } |
| |
| drv_debug_msg(VIDEO_DEBUG_GENERAL, "%s: end\n", __FUNCTION__); |
| |
| return ; |
| } |
| #endif |
| |
| void tng_DestroyContext(object_context_p obj_context, unsigned char is_JPEG) |
| { |
| context_ENC_p ctx; |
| // tng_cmdbuf_p cmdbuf = ctx->obj_context->tng_cmdbuf; |
| ctx = (context_ENC_p)obj_context->format_data; |
| FRAME_ORDER_INFO *psFrameInfo = &(ctx->sFrameOrderInfo); |
| |
| if (psFrameInfo->slot_consume_dpy_order != NULL) |
| free(psFrameInfo->slot_consume_dpy_order); |
| if (psFrameInfo->slot_consume_enc_order != NULL) |
| free(psFrameInfo->slot_consume_enc_order); |
| |
| tng_air_buf_free(ctx); |
| |
| tng__free_context_buffer(ctx, is_JPEG, 0); |
| |
| if (ctx->bEnableMVC) |
| tng__free_context_buffer(ctx, is_JPEG, 1); |
| |
| free(obj_context->format_data); |
| obj_context->format_data = NULL; |
| } |
| |
| static VAStatus tng__init_rc_params(context_ENC_p ctx, object_config_p obj_config) |
| { |
| IMG_RC_PARAMS *psRCParams = &(ctx->sRCParams); |
| unsigned int eRCmode = 0; |
| memset(psRCParams, 0, sizeof(IMG_RC_PARAMS)); |
| IMG_INT32 i; |
| |
| //set RC mode |
| for (i = 0; i < obj_config->attrib_count; i++) { |
| if (obj_config->attrib_list[i].type == VAConfigAttribRateControl) |
| break; |
| } |
| |
| if (i >= obj_config->attrib_count) { |
| eRCmode = VA_RC_NONE; |
| } else { |
| eRCmode = obj_config->attrib_list[i].value; |
| } |
| |
| ctx->sRCParams.bRCEnable = IMG_TRUE; |
| ctx->sRCParams.bDisableBitStuffing = IMG_FALSE; |
| |
| if (eRCmode == VA_RC_NONE) { |
| ctx->sRCParams.bRCEnable = IMG_FALSE; |
| ctx->sRCParams.eRCMode = IMG_RCMODE_NONE; |
| } else if (eRCmode == VA_RC_CBR) { |
| ctx->sRCParams.eRCMode = IMG_RCMODE_CBR; |
| } else if (eRCmode == VA_RC_VBR) { |
| ctx->sRCParams.eRCMode = IMG_RCMODE_VBR; |
| } else if (eRCmode == VA_RC_VCM) { |
| ctx->sRCParams.eRCMode = IMG_RCMODE_VCM; |
| } else { |
| ctx->sRCParams.bRCEnable = IMG_FALSE; |
| drv_debug_msg(VIDEO_DEBUG_ERROR, "not support this RT Format\n"); |
| return VA_STATUS_ERROR_UNSUPPORTED_RT_FORMAT; |
| } |
| |
| psRCParams->bScDetectDisable = IMG_FALSE; |
| psRCParams->ui32SliceByteLimit = 0; |
| psRCParams->ui32SliceMBLimit = 0; |
| psRCParams->bIsH264Codec = (ctx->eStandard == IMG_STANDARD_H264) ? IMG_TRUE : IMG_FALSE; |
| return VA_STATUS_SUCCESS; |
| } |
| |
| /************************************************************************************************** |
| * Function: IMG_C_GetEncoderCaps |
| * Description: Get the capabilities of the encoder for the given codec |
| * |
| ***************************************************************************************************/ |
| //FIXME |
| static const IMG_UINT32 g_ui32PipesAvailable = TOPAZHP_PIPE_NUM; |
| static const IMG_UINT32 g_ui32CoreDes1 = TOPAZHP_PIPE_NUM; |
| static const IMG_UINT32 g_ui32CoreRev = 0x00030401; |
| |
| static IMG_UINT32 tng__get_num_pipes() |
| { |
| return g_ui32PipesAvailable; |
| } |
| |
| static IMG_UINT32 tng__get_core_des1() |
| { |
| return g_ui32CoreDes1; |
| } |
| |
| static IMG_UINT32 tng__get_core_rev() |
| { |
| return g_ui32CoreRev; |
| } |
| |
| static VAStatus tng__get_encoder_caps(context_ENC_p ctx) |
| { |
| IMG_ENC_CAPS *psCaps = &(ctx->sCapsParams); |
| IMG_UINT16 ui16Height = ctx->ui16FrameHeight; |
| IMG_UINT32 ui32NumCores = 0; |
| IMG_UINT16 ui16MBRows = 0; //MB Rows in a GOB(slice); |
| |
| ctx->ui32CoreRev = tng__get_core_rev(); |
| psCaps->ui32CoreFeatures = tng__get_core_des1(); |
| |
| /* get the actual number of cores */ |
| ui32NumCores = tng__get_num_pipes(); |
| |
| switch (ctx->eStandard) { |
| case IMG_STANDARD_JPEG: |
| psCaps->ui16MaxSlices = ui16Height / 8; |
| psCaps->ui16MinSlices = 1; |
| psCaps->ui16RecommendedSlices = ui32NumCores; |
| break; |
| case IMG_STANDARD_H264: |
| psCaps->ui16MaxSlices = ui16Height / 16; |
| psCaps->ui16MinSlices = 1; |
| psCaps->ui16RecommendedSlices = ui32NumCores; |
| break; |
| case IMG_STANDARD_MPEG2: |
| psCaps->ui16MaxSlices = 174; // Slice labelling dictates a maximum of 174 slices |
| psCaps->ui16MinSlices = 1; |
| psCaps->ui16RecommendedSlices = (ui16Height + 15) / 16; |
| break; |
| case IMG_STANDARD_H263: |
| // if the original height of the pic is less than 400 , k is 1. refer standard. |
| if (ui16Height <= 400) { |
| ui16MBRows = 1; |
| } else if (ui16Height < 800) { // if between 400 and 800 it's 2. |
| ui16MBRows = 2; |
| } else { |
| ui16MBRows = 4; |
| } |
| // before rounding is done for the height. |
| // get the GOB's based on this MB Rows and not vice-versa. |
| psCaps->ui16RecommendedSlices = (ui16Height + 15) >> (4 + (ui16MBRows >> 1)); |
| psCaps->ui16MaxSlices = psCaps->ui16MinSlices = psCaps->ui16RecommendedSlices; |
| break; |
| case IMG_STANDARD_MPEG4: |
| psCaps->ui16MaxSlices = 1; |
| psCaps->ui16MinSlices = 1; |
| psCaps->ui16RecommendedSlices = 1; |
| break; |
| default: |
| break; |
| } |
| return VA_STATUS_SUCCESS; |
| } |
| |
| static VAStatus tng__init_context(context_ENC_p ctx) |
| { |
| VAStatus vaStatus = 0; |
| |
| /* Mostly sure about the following video parameters */ |
| //ctx->ui32HWProfile = pParams->ui32HWProfile; |
| ctx->ui32FrameCount[0] = ctx->ui32FrameCount[1] = 0; |
| /* Using Extended parameters */ |
| ctx->ui8PipesToUse = (IMG_UINT8)(tng__get_num_pipes() & (IMG_UINT32)0xff); |
| //carc params |
| ctx->sCARCParams.bCARC = 0; |
| ctx->sCARCParams.i32CARCBaseline = 0; |
| ctx->sCARCParams.ui32CARCThreshold = TOPAZHP_DEFAULT_uCARCThreshold; |
| ctx->sCARCParams.ui32CARCCutoff = TOPAZHP_DEFAULT_uCARCCutoff; |
| ctx->sCARCParams.ui32CARCNegRange = TOPAZHP_DEFAULT_uCARCNegRange; |
| ctx->sCARCParams.ui32CARCNegScale = TOPAZHP_DEFAULT_uCARCNegScale; |
| ctx->sCARCParams.ui32CARCPosRange = TOPAZHP_DEFAULT_uCARCPosRange; |
| ctx->sCARCParams.ui32CARCPosScale = TOPAZHP_DEFAULT_uCARCPosScale; |
| ctx->sCARCParams.ui32CARCShift = TOPAZHP_DEFAULT_uCARCShift; |
| |
| ctx->bUseDefaultScalingList = IMG_FALSE; |
| ctx->ui32CabacBinLimit = TOPAZHP_DEFAULT_uCABACBinLimit; //This parameter need not be exposed |
| if (ctx->ui32CabacBinLimit == 0) |
| ctx->ui32CabacBinFlex = 0;//This parameter need not be exposed |
| else |
| ctx->ui32CabacBinFlex = TOPAZHP_DEFAULT_uCABACBinFlex;//This parameter need not be exposed |
| |
| ctx->ui32FCode = 4; //This parameter need not be exposed |
| ctx->iFineYSearchSize = 2;//This parameter need not be exposed |
| ctx->ui32VopTimeResolution = 15;//This parameter need not be exposed |
| // ctx->bEnabledDynamicBPic = IMG_FALSE;//Related to Rate Control,which is no longer needed. |
| ctx->bH264IntraConstrained = IMG_FALSE;//This parameter need not be exposed |
| ctx->bEnableInpCtrl = IMG_FALSE;//This parameter need not be exposed |
| ctx->bEnableAIR = 0; |
| ctx->bEnableCIR = 0; |
| ctx->bEnableHostBias = (ctx->bEnableAIR != 0);//This parameter need not be exposed |
| ctx->bEnableHostQP = IMG_FALSE; //This parameter need not be exposed |
| ctx->ui8CodedSkippedIndex = 3;//This parameter need not be exposed |
| ctx->ui8InterIntraIndex = 3;//This parameter need not be exposed |
| ctx->uMaxChunks = 0xA0;//This parameter need not be exposed |
| ctx->uChunksPerMb = 0x40;//This parameter need not be exposed |
| ctx->uPriorityChunks = (0xA0 - 0x60);//This parameter need not be exposed |
| ctx->bWeightedPrediction = IMG_FALSE;//Weighted Prediction is not supported in TopazHP Version 3.0 |
| ctx->ui8VPWeightedImplicitBiPred = 0;//Weighted Prediction is not supported in TopazHP Version 3.0 |
| ctx->bSkipDuplicateVectors = IMG_FALSE;//By default false Newly Added |
| ctx->bEnableCumulativeBiases = IMG_FALSE;//By default false Newly Added |
| ctx->ui16UseCustomScalingLists = 0;//By default false Newly Added |
| ctx->bPpsScaling = IMG_FALSE;//By default false Newly Added |
| ctx->ui8MPEG2IntraDCPrecision = 0;//By default 0 Newly Added |
| ctx->uMBspS = 0;//By default 0 Newly Added |
| ctx->bMultiReferenceP = IMG_FALSE;//By default false Newly Added |
| ctx->ui8RefSpacing=0;//By default 0 Newly Added |
| ctx->bSpatialDirect = 0;//By default 0 Newly Added |
| ctx->ui32DebugCRCs = 0;//By default false Newly Added |
| ctx->bEnableMVC = IMG_FALSE;//By default false Newly Added |
| ctx->ui16MVCViewIdx = (IMG_UINT16)(NON_MVC_VIEW);//Newly Added |
| ctx->bSrcAllocInternally = IMG_FALSE;//By default false Newly Added |
| ctx->bCodedAllocInternally = IMG_FALSE;//By default true Newly Added |
| ctx->bHighLatency = IMG_TRUE;//Newly Added |
| ctx->i32NumAIRMBs = -1; |
| ctx->i32AIRThreshold = -1; |
| ctx->i16AIRSkipCnt = -1; |
| ctx->i32LastCIRIndex = -1; |
| //Need to check on the following parameters |
| ctx->ui8EnableSelStatsFlags = IMG_FALSE;//Default Value ?? Extended Parameter ?? |
| ctx->bH2648x8Transform = IMG_FALSE;//Default Value ?? Extended Parameter or OMX_VIDEO_PARAM_AVCTYPE -> bDirect8x8Inference?? |
| //FIXME: Zhaohan, eStandard is always 0 here. |
| ctx->bNoOffscreenMv = (ctx->eStandard == IMG_STANDARD_H263) ? IMG_TRUE : IMG_FALSE; //Default Value ?? Extended Parameter and bUseOffScreenMVUserSetting |
| ctx->bNoSequenceHeaders = IMG_FALSE; |
| ctx->bTopFieldFirst = IMG_TRUE; |
| ctx->sBiasTables.ui32FCode = ctx->ui32FCode; |
| ctx->ui32pseudo_rand_seed = UNINIT_PARAM; |
| ctx->bVPAdaptiveRoundingDisable = IMG_TRUE; |
| |
| //Default fcode is 4 |
| if (!ctx->sBiasTables.ui32FCode) |
| ctx->sBiasTables.ui32FCode = 4; |
| |
| ctx->uiCbrBufferTenths = TOPAZHP_DEFAULT_uiCbrBufferTenths; |
| |
| tng__setup_enc_profile_features(ctx, ENC_PROFILE_DEFAULT); |
| |
| vaStatus = tng__patch_hw_profile(ctx); |
| if (vaStatus != VA_STATUS_SUCCESS) { |
| drv_debug_msg(VIDEO_DEBUG_ERROR, "%s: tng__patch_hw_profile\n", __FUNCTION__); |
| } |
| |
| return VA_STATUS_SUCCESS; |
| } |
| |
| VAStatus tng_CreateContext( |
| object_context_p obj_context, |
| object_config_p obj_config, |
| unsigned char is_JPEG) |
| { |
| VAStatus vaStatus = 0; |
| unsigned short ui16Width, ui16Height; |
| context_ENC_p ctx; |
| |
| ui16Width = obj_context->picture_width; |
| ui16Height = obj_context->picture_height; |
| ctx = (context_ENC_p) calloc(1, sizeof(struct context_ENC_s)); |
| if (NULL == ctx) { |
| vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED; |
| DEBUG_FAILURE; |
| return vaStatus; |
| } |
| |
| memset((void*)ctx, 0, sizeof(struct context_ENC_s)); |
| |
| obj_context->format_data = (void*) ctx; |
| ctx->obj_context = obj_context; |
| |
| if (is_JPEG == 0) { |
| ctx->ui16Width = (unsigned short)(~0xf & (ui16Width + 0xf)); |
| ctx->ui16FrameHeight = (unsigned short)(~0xf & (ui16Height + 0xf)); |
| |
| vaStatus = tng__init_context(ctx); |
| if (vaStatus != VA_STATUS_SUCCESS) { |
| drv_debug_msg(VIDEO_DEBUG_ERROR, "init Context params"); |
| } |
| |
| vaStatus = tng__init_rc_params(ctx, obj_config); |
| if (vaStatus != VA_STATUS_SUCCESS) { |
| drv_debug_msg(VIDEO_DEBUG_ERROR, "init rc params"); |
| } |
| } else { |
| /*JPEG only require them are even*/ |
| ctx->ui16Width = (unsigned short)(~0x1 & (ui16Width + 0x1)); |
| ctx->ui16FrameHeight = (unsigned short)(~0x1 & (ui16Height + 0x1)); |
| } |
| |
| ctx->eFormat = IMG_CODEC_PL12; // use default |
| |
| tng__setup_enc_profile_features(ctx, ENC_PROFILE_DEFAULT); |
| |
| if (is_JPEG) { |
| vaStatus = tng__alloc_context_buffer(ctx, is_JPEG, 0); |
| if (vaStatus != VA_STATUS_SUCCESS) { |
| drv_debug_msg(VIDEO_DEBUG_ERROR, "setup enc profile"); |
| } |
| } |
| |
| return vaStatus; |
| } |
| |
| VAStatus tng_BeginPicture(context_ENC_p ctx) |
| { |
| VAStatus vaStatus = VA_STATUS_SUCCESS; |
| context_ENC_frame_buf *ps_buf = &(ctx->ctx_frame_buf); |
| tng_cmdbuf_p cmdbuf; |
| int ret; |
| |
| ctx->ui32StreamID = 0; |
| |
| if (ctx->ui32RawFrameCount != 0) |
| ps_buf->previous_src_surface = ps_buf->src_surface; |
| ps_buf->src_surface = ctx->obj_context->current_render_target; |
| |
| vaStatus = tng__get_encoder_caps(ctx); |
| if (vaStatus != VA_STATUS_SUCCESS) { |
| drv_debug_msg(VIDEO_DEBUG_ERROR, "%s: tng__get_encoder_caps\n", __FUNCTION__); |
| } |
| |
| /* clear frameskip flag to 0 */ |
| CLEAR_SURFACE_INFO_skipped_flag(ps_buf->src_surface->psb_surface); |
| |
| /* Initialise the command buffer */ |
| ret = tng_context_get_next_cmdbuf(ctx->obj_context); |
| if (ret) { |
| drv_debug_msg(VIDEO_DEBUG_ERROR, "get next cmdbuf fail\n"); |
| vaStatus = VA_STATUS_ERROR_UNKNOWN; |
| return vaStatus; |
| } |
| cmdbuf = ctx->obj_context->tng_cmdbuf; |
| |
| //FIXME |
| /* only map topaz param when necessary */ |
| cmdbuf->topaz_in_params_I_p = NULL; |
| cmdbuf->topaz_in_params_P_p = NULL; |
| ctx->obj_context->slice_count = 0; |
| |
| tng_cmdbuf_buffer_ref(cmdbuf, &(ctx->obj_context->current_render_target->psb_surface->buf)); |
| |
| return vaStatus; |
| } |
| |
| static VAStatus tng__provide_buffer_BFrames(context_ENC_p ctx, IMG_UINT32 ui32StreamIndex) |
| { |
| IMG_RC_PARAMS * psRCParams = &(ctx->sRCParams); |
| FRAME_ORDER_INFO *psFrameInfo = &(ctx->sFrameOrderInfo); |
| int slot_index = 0; |
| unsigned long long display_order = 0; |
| IMG_INT32 i32SlotBuf = (IMG_INT32)(psRCParams->ui16BFrames + 2); |
| IMG_UINT32 ui32SlotBuf = (IMG_UINT32)(psRCParams->ui16BFrames + 2); |
| IMG_UINT32 ui32FrameIdx = ctx->ui32FrameCount[ui32StreamIndex]; |
| |
| if (ui32StreamIndex == 0) |
| getFrameDpyOrder(ui32FrameIdx, psRCParams->ui16BFrames, ctx->ui32IntraCnt, |
| ctx->ui32IdrPeriod, psFrameInfo, &display_order); |
| |
| slot_index = psFrameInfo->last_slot; |
| |
| drv_debug_msg(VIDEO_DEBUG_GENERAL, |
| "%s: (int)ui32FrameIdx = %d, psRCParams->ui16BFrames = %d, psRCParams->ui32IntraFreq = %d, ctx->ui32IdrPeriod = %d\n", |
| __FUNCTION__, (int)ui32FrameIdx, (int)psRCParams->ui16BFrames, (int)psRCParams->ui32IntraFreq, ctx->ui32IdrPeriod); |
| |
| drv_debug_msg(VIDEO_DEBUG_GENERAL, |
| "%s: last_slot = %d, last_frame_type = %d, display_order = %d\n", |
| __FUNCTION__, psFrameInfo->last_slot, psFrameInfo->last_frame_type, display_order); |
| |
| if (ui32FrameIdx < ui32SlotBuf) { |
| if (ui32FrameIdx == 0) { |
| tng_send_source_frame(ctx, 0, 0); |
| } else if (ui32FrameIdx == 1) { |
| slot_index = 1; |
| do { |
| tng_send_source_frame(ctx, slot_index, slot_index); |
| ++slot_index; |
| } while(slot_index < i32SlotBuf); |
| } else { |
| slot_index = ui32FrameIdx - 1; |
| tng_send_source_frame(ctx, slot_index, slot_index); |
| } |
| } else { |
| tng_send_source_frame(ctx, slot_index , display_order); |
| } |
| |
| return VA_STATUS_SUCCESS; |
| } |
| |
| VAStatus tng__provide_buffer_PFrames(context_ENC_p ctx, IMG_UINT32 ui32StreamIndex) |
| { |
| IMG_UINT32 ui32FrameIdx = ctx->ui32FrameCount[ui32StreamIndex]; |
| |
| drv_debug_msg(VIDEO_DEBUG_GENERAL, |
| "%s: frame count = %d, SlotsInUse = %d, ui32FrameIdx = %d\n", |
| __FUNCTION__, (int)ui32FrameIdx, ctx->ui8SlotsInUse, ui32FrameIdx); |
| |
| tng_send_source_frame(ctx, ctx->ui8SlotsCoded, ui32FrameIdx); |
| /* |
| if (ctx->ui32IntraCnt == 0) |
| ctx->eFrameType = IMG_INTRA_FRAME; |
| else |
| if (ui32FrameIdx % ctx->ui32IntraCnt == 0) |
| ctx->eFrameType = IMG_INTRA_FRAME; |
| else |
| ctx->eFrameType = IMG_INTER_P; |
| |
| if (ctx->ui32IdrPeriod == 0) { |
| if (ui32FrameIdx == 0) |
| ctx->eFrameType = IMG_INTRA_IDR; |
| } else { |
| if (ctx->ui32IntraCnt == 0) { |
| if (ui32FrameIdx % ctx->ui32IdrPeriod == 0) |
| ctx->eFrameType = IMG_INTRA_IDR; |
| } else { |
| if (ui32FrameIdx % (ctx->ui32IntraCnt * ctx->ui32IdrPeriod) == 0) |
| ctx->eFrameType = IMG_INTRA_IDR; |
| } |
| } |
| */ |
| ctx->eFrameType = IMG_INTER_P; |
| |
| if (ui32FrameIdx % ctx->ui32IntraCnt == 0) |
| ctx->eFrameType = IMG_INTRA_FRAME; |
| |
| if (ui32FrameIdx % (ctx->ui32IdrPeriod * ctx->ui32IntraCnt) == 0) |
| ctx->eFrameType = IMG_INTRA_IDR; |
| |
| drv_debug_msg(VIDEO_DEBUG_GENERAL,"%s: ctx->eFrameType = %d\n", __FUNCTION__, ctx->eFrameType); |
| |
| return VA_STATUS_SUCCESS; |
| } |
| |
| static IMG_UINT16 H264_ROUNDING_OFFSETS[18][4] = { |
| { 683, 683, 683, 683 }, /* 0 I-Slice - INTRA4 LUMA */ |
| { 683, 683, 683, 683 }, /* 1 P-Slice - INTRA4 LUMA */ |
| { 683, 683, 683, 683 }, /* 2 B-Slice - INTRA4 LUMA */ |
| |
| { 683, 683, 683, 683 }, /* 3 I-Slice - INTRA8 LUMA */ |
| { 683, 683, 683, 683 }, /* 4 P-Slice - INTRA8 LUMA */ |
| { 683, 683, 683, 683 }, /* 5 B-Slice - INTRA8 LUMA */ |
| { 341, 341, 341, 341 }, /* 6 P-Slice - INTER8 LUMA */ |
| { 341, 341, 341, 341 }, /* 7 B-Slice - INTER8 LUMA */ |
| |
| { 683, 683, 683, 000 }, /* 8 I-Slice - INTRA16 LUMA */ |
| { 683, 683, 683, 000 }, /* 9 P-Slice - INTRA16 LUMA */ |
| { 683, 683, 683, 000 }, /* 10 B-Slice - INTRA16 LUMA */ |
| { 341, 341, 341, 341 }, /* 11 P-Slice - INTER16 LUMA */ |
| { 341, 341, 341, 341 }, /* 12 B-Slice - INTER16 LUMA */ |
| |
| { 683, 683, 683, 000 }, /* 13 I-Slice - INTRA16 CHROMA */ |
| { 683, 683, 683, 000 }, /* 14 P-Slice - INTRA16 CHROMA */ |
| { 683, 683, 683, 000 }, /* 15 B-Slice - INTRA16 CHROMA */ |
| { 341, 341, 341, 000 }, /* 16 P-Slice - INTER16 CHROMA */ |
| { 341, 341, 341, 000 } /* 17 B-Slice - INTER16 CHROMA */ |
| }; |
| |
| static IMG_UINT16 tng__create_gop_frame( |
| IMG_UINT8 * pui8Level, IMG_BOOL bReference, |
| IMG_UINT8 ui8Pos, IMG_UINT8 ui8Ref0Level, |
| IMG_UINT8 ui8Ref1Level, IMG_FRAME_TYPE eFrameType) |
| { |
| *pui8Level = ((ui8Ref0Level > ui8Ref1Level) ? ui8Ref0Level : ui8Ref1Level) + 1; |
| |
| return F_ENCODE(bReference, GOP_REFERENCE) | |
| F_ENCODE(ui8Pos, GOP_POS) | |
| F_ENCODE(ui8Ref0Level, GOP_REF0) | |
| F_ENCODE(ui8Ref1Level, GOP_REF1) | |
| F_ENCODE(eFrameType, GOP_FRAMETYPE); |
| } |
| |
| static void tng__minigop_generate_flat(void* buffer_p, IMG_UINT32 ui32BFrameCount, IMG_UINT32 ui32RefSpacing, IMG_UINT8 aui8PicOnLevel[]) |
| { |
| /* B B B B P */ |
| IMG_UINT8 ui8EncodeOrderPos; |
| IMG_UINT8 ui8Level; |
| IMG_UINT16 * psGopStructure = (IMG_UINT16 *)buffer_p; |
| |
| psGopStructure[0] = tng__create_gop_frame(&ui8Level, IMG_TRUE, MAX_BFRAMES, ui32RefSpacing, 0, IMG_INTER_P); |
| aui8PicOnLevel[ui8Level]++; |
| |
| for (ui8EncodeOrderPos = 1; ui8EncodeOrderPos < MAX_GOP_SIZE; ui8EncodeOrderPos++) { |
| psGopStructure[ui8EncodeOrderPos] = tng__create_gop_frame(&ui8Level, IMG_FALSE, |
| ui8EncodeOrderPos - 1, ui32RefSpacing, ui32RefSpacing + 1, IMG_INTER_B); |
| aui8PicOnLevel[ui8Level] = ui32BFrameCount; |
| } |
| |
| for( ui8EncodeOrderPos = 0; ui8EncodeOrderPos < MAX_GOP_SIZE; ui8EncodeOrderPos++) { |
| drv_debug_msg(VIDEO_DEBUG_GENERAL, |
| "%s: psGopStructure = 0x%06x\n", __FUNCTION__, psGopStructure[ui8EncodeOrderPos]); |
| } |
| |
| return ; |
| } |
| |
| static void tng__gop_split(IMG_UINT16 ** pasGopStructure, IMG_INT8 i8Ref0, IMG_INT8 i8Ref1, |
| IMG_UINT8 ui8Ref0Level, IMG_UINT8 ui8Ref1Level, IMG_UINT8 aui8PicOnLevel[]) |
| { |
| IMG_UINT8 ui8Distance = i8Ref1 - i8Ref0; |
| IMG_UINT8 ui8Position = i8Ref0 + (ui8Distance >> 1); |
| IMG_UINT8 ui8Level; |
| |
| if (ui8Distance == 1) |
| return; |
| |
| /* mark middle as this level */ |
| |
| (*pasGopStructure)++; |
| **pasGopStructure = tng__create_gop_frame(&ui8Level, ui8Distance >= 3, ui8Position, ui8Ref0Level, ui8Ref1Level, IMG_INTER_B); |
| aui8PicOnLevel[ui8Level]++; |
| |
| if (ui8Distance >= 4) |
| tng__gop_split(pasGopStructure, i8Ref0, ui8Position, ui8Ref0Level, ui8Level, aui8PicOnLevel); |
| |
| if (ui8Distance >= 3) |
| tng__gop_split(pasGopStructure, ui8Position, i8Ref1, ui8Level, ui8Ref1Level, aui8PicOnLevel); |
| } |
| |
| static void tng_minigop_generate_hierarchical(void* buffer_p, IMG_UINT32 ui32BFrameCount, |
| IMG_UINT32 ui32RefSpacing, IMG_UINT8 aui8PicOnLevel[]) |
| { |
| IMG_UINT8 ui8Level; |
| IMG_UINT16 * psGopStructure = (IMG_UINT16 *)buffer_p; |
| |
| psGopStructure[0] = tng__create_gop_frame(&ui8Level, IMG_TRUE, ui32BFrameCount, ui32RefSpacing, 0, IMG_INTER_P); |
| aui8PicOnLevel[ui8Level]++; |
| |
| tng__gop_split(&psGopStructure, -1, ui32BFrameCount, ui32RefSpacing, ui32RefSpacing + 1, aui8PicOnLevel); |
| } |
| |
| static void tng__generate_scale_tables(IMG_MTX_VIDEO_CONTEXT* psMtxEncCtx) |
| { |
| psMtxEncCtx->ui32InterIntraScale[0] = 0x0004; // Force intra by scaling its cost by 0 |
| psMtxEncCtx->ui32InterIntraScale[1] = 0x0103; // favour intra by a factor 3 |
| psMtxEncCtx->ui32InterIntraScale[2] = 0x0102; // favour intra by a factor 2 |
| psMtxEncCtx->ui32InterIntraScale[3] = 0x0101; // no bias |
| psMtxEncCtx->ui32InterIntraScale[4] = 0x0101; // no bias |
| psMtxEncCtx->ui32InterIntraScale[5] = 0x0201; // favour inter by a factor 2 |
| psMtxEncCtx->ui32InterIntraScale[6] = 0x0301; // favour inter by a factor 3 |
| psMtxEncCtx->ui32InterIntraScale[7] = 0x0400; // Force inter by scaling it's cost by 0 |
| |
| psMtxEncCtx->ui32SkippedCodedScale[0] = 0x0004; // Force coded by scaling its cost by 0 |
| psMtxEncCtx->ui32SkippedCodedScale[1] = 0x0103; // favour coded by a factor 3 |
| psMtxEncCtx->ui32SkippedCodedScale[2] = 0x0102; // favour coded by a factor 2 |
| psMtxEncCtx->ui32SkippedCodedScale[3] = 0x0101; // no bias |
| psMtxEncCtx->ui32SkippedCodedScale[4] = 0x0101; // no bias |
| psMtxEncCtx->ui32SkippedCodedScale[5] = 0x0201; // favour skipped by a factor 2 |
| psMtxEncCtx->ui32SkippedCodedScale[6] = 0x0301; // favour skipped by a factor 3 |
| psMtxEncCtx->ui32SkippedCodedScale[7] = 0x0400; // Force skipped by scaling it's cost by 0 |
| return ; |
| } |
| |
| /*! |
| ****************************************************************************** |
| @Function tng_update_driver_mv_scaling |
| @details |
| Setup the registers for scaling candidate motion vectors to take into account |
| how far away (temporally) the reference pictures are |
| ******************************************************************************/ |
| |
| static IMG_INT tng__abs(IMG_INT a) |
| { |
| if (a < 0) |
| return -a; |
| else |
| return a; |
| } |
| |
| static IMG_INT tng__abs32(IMG_INT32 a) |
| { |
| if (a < 0) |
| return -a; |
| else |
| return a; |
| } |
| |
| void tng_update_driver_mv_scaling( |
| IMG_UINT32 uFrameNum, |
| IMG_UINT32 uRef0Num, |
| IMG_UINT32 uRef1Num, |
| IMG_UINT32 ui32PicFlags, |
| IMG_BOOL bSkipDuplicateVectors, |
| IMG_UINT32 * pui32MVCalc_Below, |
| IMG_UINT32 * pui32MVCalc_Colocated, |
| IMG_UINT32 * pui32MVCalc_Config) |
| { |
| IMG_UINT32 uMvCalcConfig = 0; |
| IMG_UINT32 uMvCalcColocated = F_ENCODE(0x10, TOPAZHP_CR_TEMPORAL_BLEND); |
| IMG_UINT32 uMvCalcBelow = 0; |
| |
| //If b picture calculate scaling factor for colocated motion vectors |
| if (ui32PicFlags & ISINTERB_FLAGS) { |
| IMG_INT tb, td, tx; |
| IMG_INT iDistScale; |
| |
| //calculation taken from H264 spec |
| tb = (uFrameNum * 2) - (uRef1Num * 2); |
| td = (uRef0Num * 2) - (uRef1Num * 2); |
| tx = (16384 + tng__abs(td / 2)) / td; |
| iDistScale = (tb * tx + 32) >> 6; |
| if (iDistScale > 1023) iDistScale = 1023; |
| if (iDistScale < -1024) iDistScale = -1024; |
| uMvCalcColocated |= F_ENCODE(iDistScale, TOPAZHP_CR_COL_DIST_SCALE_FACT); |
| |
| //We assume the below temporal mvs are from the latest reference frame |
| //rather then the most recently encoded B frame (as Bs aren't reference) |
| |
| //Fwd temporal is same as colocated mv scale |
| uMvCalcBelow |= F_ENCODE(iDistScale, TOPAZHP_CR_PIC0_DIST_SCALE_FACTOR); |
| |
| //Bkwd temporal needs to be scaled by the recipricol amount in the other direction |
| tb = (uFrameNum * 2) - (uRef0Num * 2); |
| td = (uRef0Num * 2) - (uRef1Num * 2); |
| tx = (16384 + tng__abs(td / 2)) / td; |
| iDistScale = (tb * tx + 32) >> 6; |
| if (iDistScale > 1023) iDistScale = 1023; |
| if (iDistScale < -1024) iDistScale = -1024; |
| uMvCalcBelow |= F_ENCODE(iDistScale, TOPAZHP_CR_PIC1_DIST_SCALE_FACTOR); |
| } else { |
| //Don't scale the temporal below mvs |
| uMvCalcBelow |= F_ENCODE(1 << 8, TOPAZHP_CR_PIC0_DIST_SCALE_FACTOR); |
| |
| if (uRef0Num != uRef1Num) { |
| IMG_INT iRef0Dist, iRef1Dist; |
| IMG_INT iScale; |
| |
| //Distance to second reference picture may be different when |
| //using multiple reference frames on P. Scale based on difference |
| //in temporal distance to ref pic 1 compared to distance to ref pic 0 |
| iRef0Dist = (uFrameNum - uRef0Num); |
| iRef1Dist = (uFrameNum - uRef1Num); |
| iScale = (iRef1Dist << 8) / iRef0Dist; |
| |
| if (iScale > 1023) iScale = 1023; |
| if (iScale < -1024) iScale = -1024; |
| |
| uMvCalcBelow |= F_ENCODE(iScale, TOPAZHP_CR_PIC1_DIST_SCALE_FACTOR); |
| } else |
| uMvCalcBelow |= F_ENCODE(1 << 8, TOPAZHP_CR_PIC1_DIST_SCALE_FACTOR); |
| } |
| |
| if (uFrameNum > 0) { |
| IMG_INT ref0_distance, ref1_distance; |
| IMG_INT jitter0, jitter1; |
| |
| ref0_distance = tng__abs32((IMG_INT32)uFrameNum - (IMG_INT32)uRef0Num); |
| ref1_distance = tng__abs32((IMG_INT32)uFrameNum - (IMG_INT32)uRef1Num); |
| |
| if (!(ui32PicFlags & ISINTERB_FLAGS)) { |
| jitter0 = ref0_distance * 1; |
| jitter1 = jitter0 > 1 ? 1 : 2; |
| } else { |
| jitter0 = ref1_distance * 1; |
| jitter1 = ref0_distance * 1; |
| } |
| |
| //Hardware can only cope with 1 - 4 jitter factors |
| jitter0 = (jitter0 > 4) ? 4 : (jitter0 < 1) ? 1 : jitter0; |
| jitter1 = (jitter1 > 4) ? 4 : (jitter1 < 1) ? 1 : jitter1; |
| |
| //Hardware can only cope with 1 - 4 jitter factors |
| assert(jitter0 > 0 && jitter0 <= 4 && jitter1 > 0 && jitter1 <= 4); |
| |
| uMvCalcConfig |= F_ENCODE(jitter0 - 1, TOPAZHP_CR_MVCALC_IPE0_JITTER_FACTOR) | |
| F_ENCODE(jitter1 - 1, TOPAZHP_CR_MVCALC_IPE1_JITTER_FACTOR); |
| } |
| |
| uMvCalcConfig |= F_ENCODE(1, TOPAZHP_CR_MVCALC_DUP_VEC_MARGIN); |
| uMvCalcConfig |= F_ENCODE(7, TOPAZHP_CR_MVCALC_GRID_MB_X_STEP); |
| uMvCalcConfig |= F_ENCODE(13, TOPAZHP_CR_MVCALC_GRID_MB_Y_STEP); |
| uMvCalcConfig |= F_ENCODE(3, TOPAZHP_CR_MVCALC_GRID_SUB_STEP); |
| uMvCalcConfig |= F_ENCODE(1, TOPAZHP_CR_MVCALC_GRID_DISABLE); |
| |
| if (bSkipDuplicateVectors) |
| uMvCalcConfig |= F_ENCODE(1, TOPAZHP_CR_MVCALC_NO_PSEUDO_DUPLICATES); |
| |
| * pui32MVCalc_Below = uMvCalcBelow; |
| * pui32MVCalc_Colocated = uMvCalcColocated; |
| * pui32MVCalc_Config = uMvCalcConfig; |
| } |
| |
| static void tng__prepare_mv_estimates(context_ENC_p ctx, IMG_UINT32 ui32StreamIndex) |
| { |
| context_ENC_mem* ps_mem = &(ctx->ctx_mem[ui32StreamIndex]); |
| IMG_MTX_VIDEO_CONTEXT* psMtxEncCtx = NULL; |
| IMG_UINT32 ui32Distance; |
| |
| psb_buffer_map(&(ps_mem->bufs_mtx_context), &(ps_mem->bufs_mtx_context.virtual_addr)); |
| if (ps_mem->bufs_mtx_context.virtual_addr == NULL) { |
| drv_debug_msg(VIDEO_DEBUG_ERROR, "%s error: mapping mtx context\n", __FUNCTION__); |
| return ; |
| } |
| |
| psMtxEncCtx = (IMG_MTX_VIDEO_CONTEXT*)(ps_mem->bufs_mtx_context.virtual_addr); |
| |
| /* IDR */ |
| psMtxEncCtx->sMVSettingsIdr.ui32MVCalc_Config = DEFAULT_MVCALC_CONFIG; // default based on TRM |
| psMtxEncCtx->sMVSettingsIdr.ui32MVCalc_Colocated = 0x00100100;// default based on TRM |
| psMtxEncCtx->sMVSettingsIdr.ui32MVCalc_Below = 0x01000100; // default based on TRM |
| |
| tng_update_driver_mv_scaling( |
| 0, 0, 0, 0, IMG_FALSE, //psMtxEncCtx->bSkipDuplicateVectors, //By default false Newly Added |
| &psMtxEncCtx->sMVSettingsIdr.ui32MVCalc_Below, |
| &psMtxEncCtx->sMVSettingsIdr.ui32MVCalc_Colocated, |
| &psMtxEncCtx->sMVSettingsIdr.ui32MVCalc_Config); |
| |
| /* NonB (I or P) */ |
| for (ui32Distance = 1; ui32Distance <= MAX_BFRAMES + 1; ui32Distance++) { |
| psMtxEncCtx->sMVSettingsNonB[ui32Distance - 1].ui32MVCalc_Config = DEFAULT_MVCALC_CONFIG; // default based on TRM |
| psMtxEncCtx->sMVSettingsNonB[ui32Distance - 1].ui32MVCalc_Colocated = 0x00100100;// default based on TRM |
| psMtxEncCtx->sMVSettingsNonB[ui32Distance - 1].ui32MVCalc_Below = 0x01000100; // default based on TRM |
| |
| |
| tng_update_driver_mv_scaling(ui32Distance, 0, 0, 0, IMG_FALSE, //psMtxEncCtx->bSkipDuplicateVectors, |
| &psMtxEncCtx->sMVSettingsNonB[ui32Distance - 1].ui32MVCalc_Below, |
| &psMtxEncCtx->sMVSettingsNonB[ui32Distance - 1].ui32MVCalc_Colocated, |
| &psMtxEncCtx->sMVSettingsNonB[ui32Distance - 1].ui32MVCalc_Config); |
| } |
| |
| { |
| IMG_UINT32 ui32DistanceB; |
| IMG_UINT32 ui32Position; |
| context_ENC_mem *ps_mem = &(ctx->ctx_mem[ui32StreamIndex]); |
| IMG_MV_SETTINGS *pHostMVSettingsHierarchical = NULL; |
| IMG_MV_SETTINGS *pMvElement = NULL; |
| IMG_MV_SETTINGS *pHostMVSettingsBTable = NULL; |
| |
| psb_buffer_map(&(ps_mem->bufs_mv_setting_btable), &(ps_mem->bufs_mv_setting_btable.virtual_addr)); |
| if (ps_mem->bufs_mv_setting_btable.virtual_addr == NULL) { |
| drv_debug_msg(VIDEO_DEBUG_ERROR, "%s error: mapping mv setting btable\n", __FUNCTION__); |
| return ; |
| } |
| |
| pHostMVSettingsBTable = (IMG_MV_SETTINGS *)(ps_mem->bufs_mv_setting_btable.virtual_addr); |
| |
| for (ui32DistanceB = 0; ui32DistanceB < MAX_BFRAMES; ui32DistanceB++) { |
| for (ui32Position = 1; ui32Position <= ui32DistanceB + 1; ui32Position++) { |
| pMvElement = (IMG_MV_SETTINGS * ) ((IMG_UINT8 *) pHostMVSettingsBTable + MV_OFFSET_IN_TABLE(ui32DistanceB, ui32Position - 1)); |
| pMvElement->ui32MVCalc_Config= (DEFAULT_MVCALC_CONFIG|MASK_TOPAZHP_CR_MVCALC_GRID_DISABLE); // default based on TRM |
| pMvElement->ui32MVCalc_Colocated=0x00100100;// default based on TRM |
| pMvElement->ui32MVCalc_Below=0x01000100; // default based on TRM |
| |
| tng_update_driver_mv_scaling( |
| ui32Position, ui32DistanceB + 2, 0, ISINTERB_FLAGS, IMG_FALSE, |
| &pMvElement->ui32MVCalc_Below, |
| &pMvElement->ui32MVCalc_Colocated, |
| &pMvElement->ui32MVCalc_Config); |
| } |
| } |
| |
| if (ctx->b_is_mv_setting_hierar){ |
| pHostMVSettingsHierarchical = (IMG_MV_SETTINGS *)(ps_mem->bufs_mv_setting_hierar.virtual_addr); |
| |
| for (ui32DistanceB = 0; ui32DistanceB < MAX_BFRAMES; ui32DistanceB++) { |
| pMvElement = (IMG_MV_SETTINGS * ) ((IMG_UINT8 *)pHostMVSettingsBTable + MV_OFFSET_IN_TABLE(ui32DistanceB, ui32DistanceB >> 1)); |
| //memcpy(pHostMVSettingsHierarchical + ui32DistanceB, , sizeof(IMG_MV_SETTINGS)); |
| pHostMVSettingsHierarchical[ui32DistanceB].ui32MVCalc_Config = pMvElement->ui32MVCalc_Config; |
| pHostMVSettingsHierarchical[ui32DistanceB].ui32MVCalc_Colocated = pMvElement->ui32MVCalc_Colocated; |
| pHostMVSettingsHierarchical[ui32DistanceB].ui32MVCalc_Below = pMvElement->ui32MVCalc_Below; |
| } |
| } |
| psb_buffer_unmap(&(ps_mem->bufs_mv_setting_btable)); |
| } |
| |
| psb_buffer_unmap(&(ps_mem->bufs_mtx_context)); |
| |
| return ; |
| } |
| |
| static void tng__adjust_picflags( |
| context_ENC_p ctx, |
| IMG_RC_PARAMS * psRCParams, |
| IMG_BOOL bFirstPic, |
| IMG_UINT32 * pui32Flags) |
| { |
| IMG_UINT32 ui32Flags; |
| PIC_PARAMS * psPicParams = &ctx->sPicParams; |
| ui32Flags = psPicParams->ui32Flags; |
| |
| if (!psRCParams->bRCEnable || (!bFirstPic)) |
| ui32Flags = 0; |
| |
| switch (ctx->eStandard) { |
| case IMG_STANDARD_NONE: |
| break; |
| case IMG_STANDARD_H264: |
| break; |
| case IMG_STANDARD_H263: |
| ui32Flags |= ISH263_FLAGS; |
| break; |
| case IMG_STANDARD_MPEG4: |
| ui32Flags |= ISMPEG4_FLAGS; |
| break; |
| case IMG_STANDARD_MPEG2: |
| ui32Flags |= ISMPEG2_FLAGS; |
| break; |
| default: |
| break; |
| } |
| * pui32Flags = ui32Flags; |
| } |
| |
| #define gbLowLatency 0 |
| |
| static void tng__setup_rcdata(context_ENC_p ctx) |
| { |
| IMG_RC_PARAMS *psRCParams = &(ctx->sRCParams); |
| PIC_PARAMS *psPicParams = &(ctx->sPicParams); |
| |
| IMG_INT32 i32FrameRate, i32TmpQp; |
| double L1, L2, L3,L4, L5, L6, flBpp; |
| IMG_INT32 i32BufferSizeInFrames; |
| |
| if (ctx->bInsertHRDParams && |
| (ctx->eStandard == IMG_STANDARD_H264)) { |
| psRCParams->ui32BufferSize = ctx->buffer_size; |
| psRCParams->i32InitialLevel = ctx->buffer_size - ctx->initial_buffer_fullness; |
| psRCParams->i32InitialDelay = ctx->initial_buffer_fullness; |
| } |
| |
| // If Bit Rate and Basic Units are not specified then set to default values. |
| if (psRCParams->ui32BitsPerSecond == 0 && !ctx->bEnableMVC) { |
| psRCParams->ui32BitsPerSecond = 640000; // kbps |
| } |
| |
| if (!psRCParams->ui32BUSize) { |
| psRCParams->ui32BUSize = (ctx->ui16PictureHeight>>4) * (ctx->ui16Width>>4); // BU = 1 Frame |
| } |
| |
| if (!psRCParams->ui32FrameRate) { |
| psRCParams->ui32FrameRate = 30; // fps |
| } |
| |
| // Calculate Bits Per Pixel |
| if (ctx->ui16Width <= 176 ) { |
| i32FrameRate = 30; |
| } else { |
| i32FrameRate = psRCParams->ui32FrameRate; |
| } |
| |
| flBpp = 1.0 * psRCParams->ui32BitsPerSecond / (i32FrameRate * ctx->ui16Width * ctx->ui16FrameHeight); |
| |
| psPicParams->sInParams.ui8SeInitQP = psRCParams->ui32InitialQp; |
| psPicParams->sInParams.ui8MBPerRow = (ctx->ui16Width>>4); |
| psPicParams->sInParams.ui16MBPerBU = psRCParams->ui32BUSize; |
| psPicParams->sInParams.ui16MBPerFrm = (ctx->ui16Width>>4) * (ctx->ui16PictureHeight>>4); |
| psPicParams->sInParams.ui16BUPerFrm = (psPicParams->sInParams.ui16MBPerFrm) / psRCParams->ui32BUSize; |
| |
| psPicParams->sInParams.ui16IntraPeriod = psRCParams->ui32IntraFreq; |
| psPicParams->sInParams.ui16BFrames = psRCParams->ui16BFrames; |
| psPicParams->sInParams.i32BitRate = psRCParams->ui32BitsPerSecond; |
| |
| psPicParams->sInParams.bFrmSkipDisable = psRCParams->bDisableFrameSkipping; |
| psPicParams->sInParams.i32BitsPerFrm = (psRCParams->ui32BitsPerSecond + psRCParams->ui32FrameRate/2) / psRCParams->ui32FrameRate; |
| psPicParams->sInParams.i32BitsPerBU = psPicParams->sInParams.i32BitsPerFrm / (4 * psPicParams->sInParams.ui16BUPerFrm); |
| |
| // Codec-dependant fields |
| if (ctx->eStandard == IMG_STANDARD_H264) { |
| psPicParams->sInParams.mode.h264.i32TransferRate = (psRCParams->ui32TransferBitsPerSecond + psRCParams->ui32FrameRate/2) / psRCParams->ui32FrameRate; |
| psPicParams->sInParams.mode.h264.bHierarchicalMode = psRCParams->b16Hierarchical; |
| } else { |
| psPicParams->sInParams.mode.other.i32BitsPerGOP = (psRCParams->ui32BitsPerSecond / psRCParams->ui32FrameRate) * psRCParams->ui32IntraFreq; |
| psPicParams->sInParams.mode.other.ui16AvQPVal = psRCParams->ui32InitialQp; |
| psPicParams->sInParams.mode.other.ui16MyInitQP = psRCParams->ui32InitialQp; |
| } |
| |
| |
| if (psPicParams->sInParams.i32BitsPerFrm) { |
| i32BufferSizeInFrames = (psRCParams->ui32BufferSize + (psPicParams->sInParams.i32BitsPerFrm/2))/psPicParams->sInParams.i32BitsPerFrm; |
| } else { |
| IMG_ASSERT(ctx->bEnableMvc && "Can happen only in MVC mode"); |
| /* Asigning more or less `normal` value. To be overriden by MVC RC module */ |
| i32BufferSizeInFrames = 30; |
| } |
| |
| // select thresholds and initial Qps etc that are codec dependent |
| switch (ctx->eStandard) { |
| case IMG_STANDARD_H264: |
| L1 = 0.1; L2 = 0.15; L3 = 0.2; |
| psPicParams->sInParams.ui8MaxQPVal = 51; |
| ctx->ui32KickSize = psPicParams->sInParams.ui16MBPerBU; |
| |
| // Setup MAX and MIN Quant Values |
| if (psRCParams->iMinQP == 0) { |
| if (flBpp >= 0.50) |
| i32TmpQp = 4; |
| else if (flBpp > 0.133) |
| i32TmpQp = (IMG_INT32)(22 - (40*flBpp)); |
| else |
| i32TmpQp = (IMG_INT32)(30 - (100 * flBpp)); |
| |
| /* Adjust minQp up for small buffer size and down for large buffer size */ |
| if (i32BufferSizeInFrames < 5) { |
| i32TmpQp += 2; |
| } |
| |
| if (i32BufferSizeInFrames > 40) { |
| if(i32TmpQp>=1) |
| i32TmpQp -= 1; |
| } |
| /* for HD content allow a lower minQp as bitrate is more easily controlled in this case */ |
| if (psPicParams->sInParams.ui16MBPerFrm > 2000) { |
| i32TmpQp -= 6; |
| } |
| } else |
| i32TmpQp = psRCParams->iMinQP; |
| |
| if (i32TmpQp < 2) { |
| psPicParams->sInParams.ui8MinQPVal = 2; |
| } else { |
| psPicParams->sInParams.ui8MinQPVal = i32TmpQp; |
| } |
| |
| // Calculate Initial QP if it has not been specified |
| i32TmpQp = psPicParams->sInParams.ui8SeInitQP; |
| if (psPicParams->sInParams.ui8SeInitQP==0) { |
| L1 = 0.050568; |
| L2 = 0.202272; |
| L3 = 0.40454321; |
| L4 = 0.80908642; |
| L5 = 1.011358025; |
| |
| if (flBpp < L1) |
| i32TmpQp = (IMG_INT32)(45 - 78.10*flBpp); |
| else if (flBpp>=L1 && flBpp<L2) |
| i32TmpQp = (IMG_INT32)(44 - 72.51*flBpp); |
| else if (flBpp>=L2 && flBpp<L3) |
| i32TmpQp = (IMG_INT32)(34 - 24.72*flBpp); |
| else if (flBpp>=L3 && flBpp<L4) |
| i32TmpQp = (IMG_INT32)(32 - 19.78*flBpp); |
| else if (flBpp>=L4 && flBpp<L5) |
| i32TmpQp = (IMG_INT32)(25 - 9.89*flBpp); |
| else if (flBpp>=L5) |
| i32TmpQp = (IMG_INT32)(18 - 4.95*flBpp); |
| |
| /* Adjust ui8SeInitQP up for small buffer size or small fps */ |
| /* Adjust ui8SeInitQP up for small gop size */ |
| if ((i32BufferSizeInFrames < 20) || (psRCParams->ui32IntraFreq < 20)) { |
| i32TmpQp += 2; |
| } |
| |
| /* for very small buffers increase initial Qp even more */ |
| if(i32BufferSizeInFrames < 5) |
| { |
| i32TmpQp += 8; |
| } |
| |
| /* start on a lower initial Qp for HD content as the coding is more efficient */ |
| if (psPicParams->sInParams.ui16MBPerFrm > 2000) { |
| i32TmpQp -= 2; |
| } |
| |
| if(psPicParams->sInParams.ui16IntraPeriod ==1) |
| { |
| /* for very small GOPS start with a much higher initial Qp */ |
| i32TmpQp += 12; |
| } else if (psPicParams->sInParams.ui16IntraPeriod<5) { |
| /* for very small GOPS start with a much higher initial Qp */ |
| i32TmpQp += 6; |
| } |
| } |
| if (i32TmpQp>49) { |
| i32TmpQp = 49; |
| } |
| if (i32TmpQp < psPicParams->sInParams.ui8MinQPVal) { |
| i32TmpQp = psPicParams->sInParams.ui8MinQPVal; |
| } |
| psPicParams->sInParams.ui8SeInitQP = i32TmpQp; |
| |
| if(flBpp <= 0.3) |
| psPicParams->ui32Flags |= ISRC_I16BIAS; |
| |
| break; |
| |
| case IMG_STANDARD_MPEG4: |
| case IMG_STANDARD_MPEG2: |
| case IMG_STANDARD_H263: |
| psPicParams->sInParams.ui8MaxQPVal = 31; |
| if (ctx->ui16Width == 176) { |
| L1 = 0.042; L2 = 0.084; L3 = 0.126; L4 = 0.168; L5 = 0.336; L6=0.505; |
| } else if (ctx->ui16Width == 352) { |
| L1 = 0.064; L2 = 0.084; L3 = 0.106; L4 = 0.126; L5 = 0.168; L6=0.210; |
| } else { |
| L1 = 0.050; L2 = 0.0760; L3 = 0.096; L4 = 0.145; L5 = 0.193; L6=0.289; |
| } |
| |
| if (psPicParams->sInParams.ui8SeInitQP==0) { |
| if (flBpp < L1) |
| psPicParams->sInParams.ui8SeInitQP = 31; |
| else if (flBpp>=L1 && flBpp<L2) |
| psPicParams->sInParams.ui8SeInitQP = 26; |
| else if (flBpp>=L2 && flBpp<L3) |
| psPicParams->sInParams.ui8SeInitQP = 22; |
| else if (flBpp>=L3 && flBpp<L4) |
| psPicParams->sInParams.ui8SeInitQP = 18; |
| else if (flBpp>=L4 && flBpp<L5) |
| psPicParams->sInParams.ui8SeInitQP = 14; |
| else if (flBpp>=L5 && flBpp<L6) |
| psPicParams->sInParams.ui8SeInitQP = 10; |
| else |
| psPicParams->sInParams.ui8SeInitQP = 8; |
| |
| /* Adjust ui8SeInitQP up for small buffer size or small fps */ |
| /* Adjust ui8SeInitQP up for small gop size */ |
| if ((i32BufferSizeInFrames < 20) || (psRCParams->ui32IntraFreq < 20)) { |
| psPicParams->sInParams.ui8SeInitQP += 2; |
| } |
| |
| if (psPicParams->sInParams.ui8SeInitQP > psPicParams->sInParams.ui8MaxQPVal) { |
| psPicParams->sInParams.ui8SeInitQP = psPicParams->sInParams.ui8MaxQPVal; |
| } |
| psPicParams->sInParams.mode.other.ui16AvQPVal = psPicParams->sInParams.ui8SeInitQP; |
| } |
| psPicParams->sInParams.ui8MinQPVal = 2; |
| |
| /* Adjust minQp up for small buffer size and down for large buffer size */ |
| if (i32BufferSizeInFrames < 20) { |
| psPicParams->sInParams.ui8MinQPVal += 1; |
| } |
| break; |
| |
| default: |
| /* the NO RC cases will fall here */ |
| break; |
| } |
| |
| if (ctx->sRCParams.eRCMode == IMG_RCMODE_VBR) { |
| psPicParams->sInParams.ui16MBPerBU = psPicParams->sInParams.ui16MBPerFrm; |
| psPicParams->sInParams.ui16BUPerFrm = 1; |
| |
| // Initialize the parameters of fluid flow traffic model. |
| psPicParams->sInParams.i32BufferSize = psRCParams->ui32BufferSize; |
| |
| |
| // These scale factor are used only for rate control to avoid overflow |
| // in fixed-point calculation these scale factors are decided by bit rate |
| if (psRCParams->ui32BitsPerSecond < 640000) { |
| psPicParams->sInParams.ui8ScaleFactor = 2; // related to complexity |
| } |
| else if (psRCParams->ui32BitsPerSecond < 2000000) { |
| // 2 Mbits |
| psPicParams->sInParams.ui8ScaleFactor = 4; |
| } |
| else if(psRCParams->ui32BitsPerSecond < 8000000) { |
| // 8 Mbits |
| psPicParams->sInParams.ui8ScaleFactor = 6; |
| } else |
| psPicParams->sInParams.ui8ScaleFactor = 8; |
| } else { |
| // Set up Input Parameters that are mode dependent |
| switch (ctx->eStandard) { |
| case IMG_STANDARD_H264: |
| // ------------------- H264 CBR RC ------------------- // |
| // Initialize the parameters of fluid flow traffic model. |
| psPicParams->sInParams.i32BufferSize = psRCParams->ui32BufferSize; |
| |
| // HRD consideration - These values are used by H.264 reference code. |
| if (psRCParams->ui32BitsPerSecond < 1000000) { |
| // 1 Mbits/s |
| psPicParams->sInParams.ui8ScaleFactor = 0; |
| } else if (psRCParams->ui32BitsPerSecond < 2000000) { |
| // 2 Mbits/s |
| psPicParams->sInParams.ui8ScaleFactor = 1; |
| } else if (psRCParams->ui32BitsPerSecond < 4000000) { |
| // 4 Mbits/s |
| psPicParams->sInParams.ui8ScaleFactor = 2; |
| } else if (psRCParams->ui32BitsPerSecond < 8000000) { |
| // 8 Mbits/s |
| psPicParams->sInParams.ui8ScaleFactor = 3; |
| } else { |
| psPicParams->sInParams.ui8ScaleFactor = 4; |
| } |
| |
| if (ctx->sRCParams.eRCMode == IMG_RCMODE_VCM) { |
| psPicParams->sInParams.i32BufferSize = i32BufferSizeInFrames; |
| } |
| break; |
| case IMG_STANDARD_MPEG4: |
| case IMG_STANDARD_MPEG2: |
| case IMG_STANDARD_H263: |
| flBpp = 256 * (psRCParams->ui32BitsPerSecond/ctx->ui16Width); |
| flBpp /= (ctx->ui16FrameHeight * psRCParams->ui32FrameRate); |
| |
| if ((psPicParams->sInParams.ui16MBPerFrm > 1024 && flBpp < 16) || (psPicParams->sInParams.ui16MBPerFrm <= 1024 && flBpp < 24)) |
| psPicParams->sInParams.mode.other.ui8HalfFrameRate = 1; |
| else |
| psPicParams->sInParams.mode.other.ui8HalfFrameRate = 0; |
| |
| if (psPicParams->sInParams.mode.other.ui8HalfFrameRate >= 1) { |
| psPicParams->sInParams.ui8SeInitQP = 31; |
| psPicParams->sInParams.mode.other.ui16AvQPVal = 31; |
| psPicParams->sInParams.mode.other.ui16MyInitQP = 31; |
| } |
| |
| psPicParams->sInParams.i32BufferSize = psRCParams->ui32BufferSize; |
| break; |
| default: |
| break; |
| } |
| } |
| |
| if (psRCParams->bScDetectDisable) |
| psPicParams->ui32Flags |= ISSCENE_DISABLED; |
| |
| psPicParams->sInParams.i32InitialDelay = psRCParams->i32InitialDelay; |
| psPicParams->sInParams.i32InitialLevel = psRCParams->i32InitialLevel; |
| psRCParams->ui32InitialQp = psPicParams->sInParams.ui8SeInitQP; |
| |
| /* The rate control uses this value to adjust the reaction rate to larger than expected frames */ |
| if (ctx->eStandard == IMG_STANDARD_H264) { |
| if (psPicParams->sInParams.i32BitsPerFrm) { |
| const IMG_INT32 bitsPerGop = (psRCParams->ui32BitsPerSecond / psRCParams->ui32FrameRate) * psRCParams->ui32IntraFreq; |
| psPicParams->sInParams.mode.h264.ui32RCScaleFactor = (bitsPerGop * 256) / |
| (psPicParams->sInParams.i32BufferSize - psPicParams->sInParams.i32InitialLevel); |
| } else { |
| psPicParams->sInParams.mode.h264.ui32RCScaleFactor = 0; |
| } |
| } else { |
| psPicParams->sInParams.mode.other.ui16MyInitQP = psPicParams->sInParams.ui8SeInitQP; |
| } |
| |
| return ; |
| } |
| |
| static void tng__save_slice_params_template( |
| context_ENC_p ctx, |
| IMG_UINT32 ui32SliceBufIdx, |
| IMG_UINT32 ui32SliceType, |
| IMG_UINT32 ui32IPEControl, |
| IMG_UINT32 ui32Flags, |
| IMG_UINT32 ui32SliceConfig, |
| IMG_UINT32 ui32SeqConfig, |
| IMG_UINT32 ui32StreamIndex |
| ) |
| { |
| IMG_FRAME_TEMPLATE_TYPE eSliceType = (IMG_FRAME_TEMPLATE_TYPE)ui32SliceType; |
| context_ENC_mem *ps_mem = &(ctx->ctx_mem[ui32StreamIndex]); |
| SLICE_PARAMS *slice_temp_p = NULL; |
| |
| psb_buffer_map(&(ps_mem->bufs_slice_template), &(ps_mem->bufs_slice_template.virtual_addr)); |
| if (ps_mem->bufs_slice_template.virtual_addr == NULL) { |
| drv_debug_msg(VIDEO_DEBUG_ERROR, "%s error: mapping slice template\n", __FUNCTION__); |
| return ; |
| } |
| |
| slice_temp_p = (SLICE_PARAMS*)(ps_mem->bufs_slice_template.virtual_addr + (ctx->ctx_mem_size.slice_template * ui32SliceBufIdx)); |
| |
| slice_temp_p->eTemplateType = eSliceType; |
| slice_temp_p->ui32Flags = ui32Flags; |
| slice_temp_p->ui32IPEControl = ui32IPEControl; |
| slice_temp_p->ui32SliceConfig = ui32SliceConfig; |
| slice_temp_p->ui32SeqConfig = ui32SeqConfig; |
| |
| psb_buffer_unmap(&(ps_mem->bufs_slice_template)); |
| |
| return ; |
| } |
| |
| |
| /***************************************************************************** |
| * Function Name : PrepareEncodeSliceParams |
| * |
| ****************************************************************************/ |
| static IMG_UINT32 tng__prepare_encode_sliceparams( |
| context_ENC_p ctx, |
| IMG_UINT32 ui32SliceBufIdx, |
| IMG_UINT32 ui32SliceType, |
| IMG_UINT16 __maybe_unused ui16CurrentRow, |
| IMG_UINT16 ui16SliceHeight, |
| IMG_UINT8 uiDeblockIDC, |
| IMG_BOOL bFieldMode, |
| IMG_INT iFineYSearchSize, |
| IMG_UINT32 ui32StreamIndex |
| ) |
| { |
| IMG_UINT32 ui32FrameStoreFormat; |
| IMG_UINT8 ui8SwapChromas; |
| IMG_UINT32 ui32MBsPerKick, ui32KicksPerSlice; |
| IMG_UINT32 ui32IPEControl; |
| IMG_UINT32 ui32Flags = 0; |
| IMG_UINT32 ui32SliceConfig = 0; |
| IMG_UINT32 ui32SeqConfig = 0; |
| IMG_BOOL bIsIntra = IMG_FALSE; |
| IMG_BOOL bIsBPicture = IMG_FALSE; |
| IMG_BOOL bIsIDR = IMG_FALSE; |
| IMG_IPE_MINBLOCKSIZE blkSz; |
| IMG_FRAME_TEMPLATE_TYPE eSliceType = (IMG_FRAME_TEMPLATE_TYPE)ui32SliceType; |
| |
| if (!ctx) { |
| return VA_STATUS_ERROR_INVALID_CONTEXT; |
| } |
| |
| /* We want multiple ones of these so we can submit multiple slices without having to wait for the next*/ |
| ui32IPEControl = ctx->ui32IPEControl; |
| bIsIntra = ((eSliceType == IMG_FRAME_IDR) || (eSliceType == IMG_FRAME_INTRA)); |
| bIsBPicture = (eSliceType == IMG_FRAME_INTER_B); |
| bIsIDR = ((eSliceType == IMG_FRAME_IDR) || (eSliceType == IMG_FRAME_INTER_P_IDR)); |
| |
| drv_debug_msg(VIDEO_DEBUG_GENERAL, "%s PTG bIsIntra = %x\n", __FUNCTION__, bIsIntra); |
| drv_debug_msg(VIDEO_DEBUG_GENERAL, "%s PTG bIsBFrame = %x\n", __FUNCTION__, bIsBPicture); |
| drv_debug_msg(VIDEO_DEBUG_GENERAL, "%s PTG bIsIDR = %x\n", __FUNCTION__, bIsIDR); |
| /* extract block size */ |
| blkSz = F_EXTRACT(ui32IPEControl, TOPAZHP_CR_IPE_BLOCKSIZE); |
| /* mask-out the block size bits from ui32IPEControl */ |
| ui32IPEControl &= ~(F_MASK(TOPAZHP_CR_IPE_BLOCKSIZE)); |
| switch (ctx->eStandard) { |
| case IMG_STANDARD_NONE: |
| case IMG_STANDARD_JPEG: |
| break; |
| |
| case IMG_STANDARD_H264: |
| if (blkSz > 2) blkSz = 2; |
| if (bIsBPicture) { |
| if (blkSz > 1) blkSz = 1; |
| } |
| #ifdef BRN_30322 |
| else if (bIsIntra) { |
| if (blkSz == 0) blkSz = 1; // Workaround for BRN 30322 |
| } |
| #endif |
| |
| #ifdef BRN_30550 |
| if (ctx->bCabacEnabled) |
| if (blkSz == 0) blkSz = 1; |
| #endif |
| if (ctx->uMBspS >= _1080P_30FPS) { |
| ui32IPEControl |= F_ENCODE(iFineYSearchSize, TOPAZHP_CR_IPE_LRITC_BOUNDARY) | |
| F_ENCODE(iFineYSearchSize, TOPAZHP_CR_IPE_Y_FINE_SEARCH); |
| } else { |
| ui32IPEControl |= F_ENCODE(iFineYSearchSize + 1, TOPAZHP_CR_IPE_LRITC_BOUNDARY) | |
| F_ENCODE(iFineYSearchSize, TOPAZHP_CR_IPE_Y_FINE_SEARCH); |
| |
| } |
| if (ctx->bLimitNumVectors) |
| ui32IPEControl |= F_ENCODE(1, TOPAZHP_CR_IPE_MV_NUMBER_RESTRICTION); |
| break; |
| |
| case IMG_STANDARD_H263: |
| blkSz = 0; |
| ui32IPEControl = F_ENCODE(iFineYSearchSize + 1, TOPAZHP_CR_IPE_LRITC_BOUNDARY) | |
| F_ENCODE(iFineYSearchSize, TOPAZHP_CR_IPE_Y_FINE_SEARCH) | |
| F_ENCODE(0, TOPAZHP_CR_IPE_4X4_SEARCH); |
| //We only support a maxium vector of 15.5 pixels in H263 |
| break; |
| |
| case IMG_STANDARD_MPEG4: |
| if (blkSz > BLK_SZ_8x8) blkSz = BLK_SZ_8x8; |
| ui32IPEControl |= F_ENCODE(iFineYSearchSize + 1, TOPAZHP_CR_IPE_LRITC_BOUNDARY) | |
| F_ENCODE(iFineYSearchSize, TOPAZHP_CR_IPE_Y_FINE_SEARCH) | |
| F_ENCODE(0, TOPAZHP_CR_IPE_4X4_SEARCH); |
| // FIXME Should be 1, set to zero for hardware testing. |
| break; |
| case IMG_STANDARD_MPEG2: |
| if (blkSz != BLK_SZ_16x16) blkSz = BLK_SZ_16x16; |
| ui32IPEControl |= F_ENCODE(iFineYSearchSize + 1, TOPAZHP_CR_IPE_LRITC_BOUNDARY) | |
| F_ENCODE(iFineYSearchSize, TOPAZHP_CR_IPE_Y_FINE_SEARCH) | |
| F_ENCODE(0, TOPAZHP_CR_IPE_4X4_SEARCH); |
| // FIXME Should be 1, set to zero for hardware testing. |
| break; |
| } |
| |
| { |
| IMG_BOOL bRestrict4x4SearchSize; |
| IMG_UINT32 uLritcBoundary; |
| |
| if (ctx->uMBspS >= _1080P_30FPS) |
| bRestrict4x4SearchSize = 1; |
| else |
| bRestrict4x4SearchSize = 0; |
| |
| ui32IPEControl |= F_ENCODE(blkSz, TOPAZHP_CR_IPE_BLOCKSIZE); |
| uLritcBoundary = (blkSz != BLK_SZ_16x16) ? (iFineYSearchSize + (bRestrict4x4SearchSize ? 0 : 1)) : 1; |
| if (uLritcBoundary > 3) { |
| return VA_STATUS_ERROR_UNKNOWN; |
| } |
| |
| /* Minium sub block size to calculate motion vectors for. 0=16x16, 1=8x8, 2=4x4 */ |
| ui32IPEControl = F_INSERT(ui32IPEControl, blkSz, TOPAZHP_CR_IPE_BLOCKSIZE); |
| ui32IPEControl = F_INSERT(ui32IPEControl, iFineYSearchSize, TOPAZHP_CR_IPE_Y_FINE_SEARCH); |
| ui32IPEControl = F_INSERT(ui32IPEControl, ctx->bLimitNumVectors, TOPAZHP_CR_IPE_MV_NUMBER_RESTRICTION); |
| |
| ui32IPEControl = F_INSERT(ui32IPEControl, uLritcBoundary, TOPAZHP_CR_IPE_LRITC_BOUNDARY); // 8x8 search |
| ui32IPEControl = F_INSERT(ui32IPEControl, bRestrict4x4SearchSize ? 0 : 1, TOPAZHP_CR_IPE_4X4_SEARCH); |
| |
| } |
| ui32IPEControl = F_INSERT(ui32IPEControl, ctx->bHighLatency, TOPAZHP_CR_IPE_HIGH_LATENCY); |
| // psSliceParams->ui32IPEControl = ui32IPEControl; |
| |
| if (!bIsIntra) { |
| if (bIsBPicture) |
| ui32Flags |= ISINTERB_FLAGS; |
| else |
| ui32Flags |= ISINTERP_FLAGS; |
| } |
| switch (ctx->eStandard) { |
| case IMG_STANDARD_NONE: |
| break; |
| case IMG_STANDARD_H263: |
| ui32Flags |= ISH263_FLAGS; |
| break; |
| case IMG_STANDARD_MPEG4: |
| ui32Flags |= ISMPEG4_FLAGS; |
| break; |
| case IMG_STANDARD_MPEG2: |
| ui32Flags |= ISMPEG2_FLAGS; |
| break; |
| default: |
| break; |
| } |
| |
| if (ctx->bMultiReferenceP && !(bIsIntra || bIsBPicture)) |
| ui32Flags |= ISMULTIREF_FLAGS; |
| if (ctx->bSpatialDirect && bIsBPicture) |
| ui32Flags |= SPATIALDIRECT_FLAGS; |
| |
| if (bIsIntra) { |
| ui32SliceConfig = F_ENCODE(TOPAZHP_CR_SLICE_TYPE_I_SLICE, TOPAZHP_CR_SLICE_TYPE); |
| } else { |
| if (bIsBPicture) { |
| ui32SliceConfig = F_ENCODE(TOPAZHP_CR_SLICE_TYPE_B_SLICE, TOPAZHP_CR_SLICE_TYPE); |
| } else { |
| // p frame |
| ui32SliceConfig = F_ENCODE(TOPAZHP_CR_SLICE_TYPE_P_SLICE, TOPAZHP_CR_SLICE_TYPE); |
| } |
| } |
| |
| ui32MBsPerKick = ctx->ui32KickSize; |
| // we need to figure out the number of kicks and mb's per kick to use. |
| // on H.264 we will use a MB's per kick of basic unit |
| // on other rc varients we will use mb's per kick of width |
| ui32KicksPerSlice = ((ui16SliceHeight / 16) * (ctx->ui16Width / 16)) / ui32MBsPerKick; |
| assert((ui32KicksPerSlice * ui32MBsPerKick) == ((ui16SliceHeight / 16)*(ctx->ui16Width / 16))); |
| |
| // need some sensible ones don't look to be implemented yet... |
| // change per stream |
| |
| if ((ctx->eFormat == IMG_CODEC_UY0VY1_8888) || (ctx->eFormat == IMG_CODEC_VY0UY1_8888)) |
| ui32FrameStoreFormat = 3; |
| else if ((ctx->eFormat == IMG_CODEC_Y0UY1V_8888) || (ctx->eFormat == IMG_CODEC_Y0VY1U_8888)) |
| ui32FrameStoreFormat = 2; |
| else if ((ctx->eFormat == IMG_CODEC_PL12) || (ctx->eFormat == IMG_CODEC_422_PL12)) |
| ui32FrameStoreFormat = 1; |
| else |
| ui32FrameStoreFormat = 0; |
| |
| if ((ctx->eFormat == IMG_CODEC_VY0UY1_8888) || (ctx->eFormat == IMG_CODEC_Y0VY1U_8888)) |
| ui8SwapChromas = 1; |
| else |
| ui8SwapChromas = 0; |
| |
| switch (ctx->eStandard) { |
| case IMG_STANDARD_NONE: |
| case IMG_STANDARD_JPEG: |
| break; |
| case IMG_STANDARD_H264: |
| /* H264 */ |
| |
| ui32SeqConfig = F_ENCODE(0, TOPAZHP_CR_TEMPORAL_PIC0_BELOW_IN_VALID) |
| | F_ENCODE(0, TOPAZHP_CR_TEMPORAL_PIC1_BELOW_IN_VALID) |
| | F_ENCODE(0, TOPAZHP_CR_ABOVE_OUT_OF_SLICE_VALID) |
| | F_ENCODE(1, TOPAZHP_CR_WRITE_TEMPORAL_PIC0_BELOW_VALID) |
| | F_ENCODE(0, TOPAZHP_CR_REF_PIC0_VALID) |
| | F_ENCODE(0, TOPAZHP_CR_REF_PIC1_VALID) |
| | F_ENCODE(!bIsBPicture, TOPAZHP_CR_REF_PIC1_EQUAL_PIC0) |
| | F_ENCODE(bFieldMode ? 1 : 0 , TOPAZHP_CR_FIELD_MODE) |
| | F_ENCODE(ui8SwapChromas, TOPAZHP_CR_FRAME_STORE_CHROMA_SWAP) |
| | F_ENCODE(ui32FrameStoreFormat, TOPAZHP_CR_FRAME_STORE_FORMAT) |
| | F_ENCODE(TOPAZHP_CR_ENCODER_STANDARD_H264, TOPAZHP_CR_ENCODER_STANDARD) |
| | F_ENCODE(uiDeblockIDC == 1 ? 0 : 1, TOPAZHP_CR_DEBLOCK_ENABLE); |
| |
| if (ctx->sRCParams.ui16BFrames) { |
| ui32SeqConfig |= F_ENCODE(1, TOPAZHP_CR_WRITE_TEMPORAL_COL_VALID); |
| if ((ui32Flags & ISINTERB_FLAGS) == ISINTERB_FLAGS) |
| ui32SeqConfig |= F_ENCODE(1, TOPAZHP_CR_TEMPORAL_COL_IN_VALID); |
| } |
| |
| if (!bIsBPicture) { |
| ui32SeqConfig |= F_ENCODE(1, TOPAZHP_CR_WRITE_TEMPORAL_COL_VALID); |
| } |
| |
| break; |
| case IMG_STANDARD_MPEG4: |
| /* MPEG4 */ |
| ui32SeqConfig = F_ENCODE(1, TOPAZHP_CR_WRITE_RECON_PIC) |
| | F_ENCODE(0, TOPAZHP_CR_DEBLOCK_ENABLE) |
| | F_ENCODE(0, TOPAZHP_CR_TEMPORAL_PIC0_BELOW_IN_VALID) |
| | F_ENCODE(0, TOPAZHP_CR_TEMPORAL_PIC1_BELOW_IN_VALID) |
| | F_ENCODE(0, TOPAZHP_CR_ABOVE_OUT_OF_SLICE_VALID) |
| | F_ENCODE(((ui32Flags & ISINTERP_FLAGS) == ISINTERP_FLAGS), TOPAZHP_CR_WRITE_TEMPORAL_PIC0_BELOW_VALID) |
| | F_ENCODE(0, TOPAZHP_CR_REF_PIC0_VALID) |
| | F_ENCODE(0, TOPAZHP_CR_REF_PIC1_VALID) |
| | F_ENCODE(1, TOPAZHP_CR_REF_PIC1_EQUAL_PIC0) |
| | F_ENCODE(0, TOPAZHP_CR_FIELD_MODE) |
| | F_ENCODE(ui8SwapChromas, TOPAZHP_CR_FRAME_STORE_CHROMA_SWAP) |
| | F_ENCODE(ui32FrameStoreFormat, TOPAZHP_CR_FRAME_STORE_FORMAT) |
| | F_ENCODE(TOPAZHP_CR_ENCODER_STANDARD_MPEG4, TOPAZHP_CR_ENCODER_STANDARD); |
| break; |
| case IMG_STANDARD_MPEG2: |
| /* MPEG2 */ |
| ui32SeqConfig = F_ENCODE(1, TOPAZHP_CR_WRITE_RECON_PIC) |
| | F_ENCODE(0, TOPAZHP_CR_DEBLOCK_ENABLE) |
| | F_ENCODE(0, TOPAZHP_CR_TEMPORAL_PIC0_BELOW_IN_VALID) |
| | F_ENCODE(0, TOPAZHP_CR_TEMPORAL_PIC1_BELOW_IN_VALID) |
| | F_ENCODE(0, TOPAZHP_CR_ABOVE_OUT_OF_SLICE_VALID) |
| | F_ENCODE(((ui32Flags & ISINTERP_FLAGS) == ISINTERP_FLAGS), TOPAZHP_CR_WRITE_TEMPORAL_PIC0_BELOW_VALID) |
| | F_ENCODE(1, TOPAZHP_CR_REF_PIC0_VALID) |
| | F_ENCODE(0, TOPAZHP_CR_REF_PIC1_VALID) |
| | F_ENCODE(1, TOPAZHP_CR_REF_PIC1_EQUAL_PIC0) |
| | F_ENCODE(bFieldMode ? 1 : 0 , TOPAZHP_CR_FIELD_MODE) |
| | F_ENCODE(ui8SwapChromas, TOPAZHP_CR_FRAME_STORE_CHROMA_SWAP) |
| | F_ENCODE(ui32FrameStoreFormat, TOPAZHP_CR_FRAME_STORE_FORMAT) |
| | F_ENCODE(TOPAZHP_CR_ENCODER_STANDARD_MPEG2, TOPAZHP_CR_ENCODER_STANDARD); |
| break; |
| case IMG_STANDARD_H263: |
| /* H263 */ |
| ui32SeqConfig = F_ENCODE(1, TOPAZHP_CR_WRITE_RECON_PIC) |
| | F_ENCODE(0, TOPAZHP_CR_DEBLOCK_ENABLE) |
| | F_ENCODE(0, TOPAZHP_CR_TEMPORAL_PIC0_BELOW_IN_VALID) |
| | F_ENCODE(0, TOPAZHP_CR_TEMPORAL_PIC1_BELOW_IN_VALID) |
| | F_ENCODE(0, TOPAZHP_CR_ABOVE_OUT_OF_SLICE_VALID) |
| | F_ENCODE(((ui32Flags & ISINTERP_FLAGS) == ISINTERP_FLAGS), TOPAZHP_CR_WRITE_TEMPORAL_PIC0_BELOW_VALID) |
| | F_ENCODE(0, TOPAZHP_CR_REF_PIC0_VALID) |
| | F_ENCODE(0, TOPAZHP_CR_REF_PIC1_VALID) |
| | F_ENCODE(1, TOPAZHP_CR_REF_PIC1_EQUAL_PIC0) |
| | F_ENCODE(0, TOPAZHP_CR_FIELD_MODE) |
| | F_ENCODE(ui8SwapChromas, TOPAZHP_CR_FRAME_STORE_CHROMA_SWAP) |
| | F_ENCODE(ui32FrameStoreFormat, TOPAZHP_CR_FRAME_STORE_FORMAT) |
| | F_ENCODE(TOPAZHP_CR_ENCODER_STANDARD_H263, TOPAZHP_CR_ENCODER_STANDARD); |
| break; |
| } |
| |
| if (bIsBPicture) { |
| ui32SeqConfig |= F_ENCODE(0, TOPAZHP_CR_TEMPORAL_PIC1_BELOW_IN_VALID) |
| | F_ENCODE(0, TOPAZHP_CR_WRITE_TEMPORAL_PIC1_BELOW_VALID) |
| | F_ENCODE(1, TOPAZHP_CR_REF_PIC1_VALID) |
| | F_ENCODE(1, TOPAZHP_CR_TEMPORAL_COL_IN_VALID); |
| } |
| |
| if (ctx->ui8EnableSelStatsFlags & ESF_FIRST_STAGE_STATS) { |
| ui32SeqConfig |= F_ENCODE(1, TOPAZHP_CR_WRITE_MB_FIRST_STAGE_VALID); |
| } |
| |
| if (ctx->ui8EnableSelStatsFlags & ESF_MP_BEST_MB_DECISION_STATS || |
| ctx->ui8EnableSelStatsFlags & ESF_MP_BEST_MOTION_VECTOR_STATS) { |
| ui32SeqConfig |= F_ENCODE(1, TOPAZHP_CR_BEST_MULTIPASS_OUT_VALID); |
| |
| if (!(ctx->ui8EnableSelStatsFlags & ESF_MP_BEST_MOTION_VECTOR_STATS)) { |
| ui32SeqConfig |= F_ENCODE(1, TOPAZHP_CR_BEST_MVS_OUT_DISABLE);// 64 Byte Best Multipass Motion Vector output disabled by default |
| } |
| } |
| |
| if (ctx->bEnableInpCtrl) { |
| ui32SeqConfig |= F_ENCODE(1, TOPAZHP_CR_MB_CONTROL_IN_VALID); |
| } |
| |
| if (eSliceType == IMG_FRAME_IDR) { |
| ctx->sBiasTables.ui32SeqConfigInit = ui32SeqConfig; |
| } |
| |
| tng__save_slice_params_template(ctx, ui32SliceBufIdx, eSliceType, |
| ui32IPEControl, ui32Flags, ui32SliceConfig, ui32SeqConfig, ui32StreamIndex); |
| |
| return 0; |
| } |
| |
| void tng__mpeg4_generate_pic_hdr_template( |
| context_ENC_p ctx, |
| IMG_FRAME_TEMPLATE_TYPE ui8SliceType, |
| IMG_UINT8 ui8Search_range) |
| { |
| context_ENC_mem *ps_mem = &(ctx->ctx_mem[ctx->ui32StreamID]); |
| MTX_HEADER_PARAMS * pPicHeaderMem; |
| VOP_CODING_TYPE eVop_Coding_Type; |
| IMG_BOOL8 b8IsVopCoded; |
| IMG_UINT8 ui8OriginalSliceType = ui8SliceType; |
| |
| /* MPEG4: We do not support B-frames at the moment, so we use a spare slot, to store a template for the skipped frame */ |
| if (ui8SliceType == IMG_FRAME_INTER_B) |
| { |
| ui8SliceType = IMG_FRAME_INTER_P; |
| b8IsVopCoded = IMG_FALSE; |
| } else { |
| b8IsVopCoded = IMG_TRUE; |
| } |
| |
| eVop_Coding_Type = (ui8SliceType == IMG_FRAME_INTER_P) ? P_FRAME : I_FRAME; |
| |
| psb_buffer_map(&(ps_mem->bufs_pic_template), &(ps_mem->bufs_pic_template.virtual_addr)); |
| if (ps_mem->bufs_pic_template.virtual_addr == NULL) { |
| drv_debug_msg(VIDEO_DEBUG_ERROR, "%s error: mapping pic template\n", __FUNCTION__); |
| return ; |
| } |
| |
| pPicHeaderMem = (MTX_HEADER_PARAMS *)((IMG_UINT8*)(ps_mem->bufs_pic_template.virtual_addr + (ctx->ctx_mem_size.pic_template * ui8OriginalSliceType))); |
| //todo fix time resolution |
| tng__MPEG4_notforsims_prepare_vop_header(pPicHeaderMem, b8IsVopCoded, ui8Search_range, eVop_Coding_Type); |
| psb_buffer_unmap(&(ps_mem->bufs_pic_template)); |
| |
| } |
| |
| void tng__h263_generate_pic_hdr_template( |
| context_ENC_p ctx, |
| IMG_FRAME_TEMPLATE_TYPE eFrameType, |
| IMG_UINT16 ui16Width, |
| IMG_UINT16 ui16Heigh) |
| |
| { |
| context_ENC_mem *ps_mem = &(ctx->ctx_mem[ctx->ui32StreamID]); |
| MTX_HEADER_PARAMS * pPicHeaderMem = NULL; |
| H263_PICTURE_CODING_TYPE ePictureCodingType = ((eFrameType == IMG_FRAME_INTRA)|| (eFrameType == IMG_FRAME_IDR)) ? I_FRAME : P_FRAME; |
| |
| psb_buffer_map(&(ps_mem->bufs_pic_template), &(ps_mem->bufs_pic_template.virtual_addr)); |
| if (ps_mem->bufs_pic_template.virtual_addr == NULL) { |
| drv_debug_msg(VIDEO_DEBUG_ERROR, "%s error: mapping pic template\n", __FUNCTION__); |
| return ; |
| } |
| |
| pPicHeaderMem = (MTX_HEADER_PARAMS *)((IMG_UINT8*)(ps_mem->bufs_pic_template.virtual_addr + (ctx->ctx_mem_size.pic_template * eFrameType))); |
| |
| IMG_UINT8 ui8FrameRate = (IMG_UINT8)ctx->sRCParams.ui32FrameRate; |
| |
| // Get a pointer to the memory the header will be written to |
| tng__H263_notforsims_prepare_video_pictureheader( |
| pPicHeaderMem, |
| ePictureCodingType, |
| ctx->ui8H263SourceFormat, |
| ui8FrameRate, |
| ui16Width, |
| ui16Heigh); |
| |
| psb_buffer_unmap(&(ps_mem->bufs_pic_template)); |
| |
| } |
| |
| |
| static void tng__MPEG4ES_send_seq_header(context_ENC_p ctx, IMG_UINT32 ui32StreamIndex) |
| { |
| context_ENC_mem *ps_mem = &(ctx->ctx_mem[ui32StreamIndex]); |
| tng_cmdbuf_p cmdbuf = ctx->obj_context->tng_cmdbuf; |
| |
| psb_buffer_map(&(ps_mem->bufs_seq_header), &(ps_mem->bufs_seq_header.virtual_addr)); |
| if (ps_mem->bufs_seq_header.virtual_addr == NULL) { |
| drv_debug_msg(VIDEO_DEBUG_ERROR, "%s error: mapping seq template\n", __FUNCTION__); |
| return ; |
| } |
| |
| tng__MPEG4_prepare_sequence_header(ps_mem->bufs_seq_header.virtual_addr, |
| IMG_FALSE,//FIXME: Zhaohan bFrame |
| ctx->ui8ProfileIdc,//profile |
| ctx->ui8LevelIdc,//ui8Profile_lvl_indication |
| 3,//ui8Fixed_vop_time_increment |
| ctx->obj_context->picture_width,//ui8Fixed_vop_time_increment |
| ctx->obj_context->picture_height,//ui32Picture_Height_Pixels |
| NULL,//VBVPARAMS |
| ctx->ui32VopTimeResolution); |
| psb_buffer_unmap(&(ps_mem->bufs_seq_header)); |
| |
| cmdbuf->cmd_idx_saved[TNG_CMDBUF_SEQ_HEADER_IDX] = cmdbuf->cmd_idx; |
| } |
| |
| static void tng__H264ES_send_seq_header(context_ENC_p ctx, IMG_UINT32 ui32StreamIndex) |
| { |
| context_ENC_mem *ps_mem = &(ctx->ctx_mem[ui32StreamIndex]); |
| tng_cmdbuf_p cmdbuf = ctx->obj_context->tng_cmdbuf; |
| IMG_RC_PARAMS *psRCParams = &(ctx->sRCParams); |
| H264_VUI_PARAMS *psVuiParams = &(ctx->sVuiParams); |
| |
| // memset(psVuiParams, 0, sizeof(H264_VUI_PARAMS)); |
| |
| if (psRCParams->eRCMode != IMG_RCMODE_NONE) { |
| psVuiParams->vui_flag = 1; |
| if (psVuiParams->num_units_in_tick == 0 || psVuiParams->Time_Scale == 0) { |
| psVuiParams->num_units_in_tick = 1; |
| psVuiParams->Time_Scale = psRCParams->ui32FrameRate * 2; |
| } |
| psVuiParams->bit_rate_value_minus1 = psRCParams->ui32BitsPerSecond / 64 - 1; |
| psVuiParams->cbp_size_value_minus1 = psRCParams->ui32BufferSize / 64 - 1; |
| psVuiParams->CBR = ((psRCParams->eRCMode == IMG_RCMODE_CBR) && (!psRCParams->bDisableBitStuffing)) ? 1 : 0; |
| psVuiParams->initial_cpb_removal_delay_length_minus1 = BPH_SEI_NAL_INITIAL_CPB_REMOVAL_DELAY_SIZE - 1; |
| psVuiParams->cpb_removal_delay_length_minus1 = PTH_SEI_NAL_CPB_REMOVAL_DELAY_SIZE - 1; |
| psVuiParams->dpb_output_delay_length_minus1 = PTH_SEI_NAL_DPB_OUTPUT_DELAY_SIZE - 1; |
| psVuiParams->time_offset_length = 24; |
| } |
| drv_debug_msg(VIDEO_DEBUG_GENERAL, "%s psVuiParams->vui_flag = %d\n", __FUNCTION__, psVuiParams->vui_flag); |
| |
| psb_buffer_map(&(ps_mem->bufs_seq_header), &(ps_mem->bufs_seq_header.virtual_addr)); |
| if (ps_mem->bufs_seq_header.virtual_addr == NULL) { |
| drv_debug_msg(VIDEO_DEBUG_ERROR, "%s error: mapping seq header\n", __FUNCTION__); |
| return ; |
| } |
| |
| tng__H264ES_prepare_sequence_header( |
| ps_mem->bufs_seq_header.virtual_addr, |
| &(ctx->sVuiParams), |
| &(ctx->sCropParams), |
| ctx->ui16Width, //ui8_picture_width_in_mbs |
| ctx->ui16PictureHeight, //ui8_picture_height_in_mbs |
| ctx->ui32CustomQuantMask, //0, ui8_custom_quant_mask |
| ctx->ui8ProfileIdc, //ui8_profile |
| ctx->ui8LevelIdc, //ui8_level |
| ctx->ui8FieldCount, //1, ui8_field_count |
| ctx->ui8MaxNumRefFrames, //1, ui8_max_num_ref_frames |
| ctx->bPpsScaling, //0 ui8_pps_scaling_cnt |
| ctx->bUseDefaultScalingList, //0, b_use_default_scaling_list |
| ctx->bEnableLossless, //0, blossless |
| ctx->bArbitrarySO |
| ); |
| psb_buffer_unmap(&(ps_mem->bufs_seq_header)); |
| |
| if (ctx->bEnableMVC) { |
| psb_buffer_map(&(ps_mem->bufs_sub_seq_header), &(ps_mem->bufs_sub_seq_header.virtual_addr)); |
| if (ps_mem->bufs_sub_seq_header.virtual_addr == NULL) { |
| drv_debug_msg(VIDEO_DEBUG_ERROR, "%s error: mapping sub seq header\n", __FUNCTION__); |
| return ; |
| } |
| tng__H264ES_prepare_mvc_sequence_header( |
| ps_mem->bufs_sub_seq_header.virtual_addr, |
| &(ctx->sCropParams), |
| ctx->ui16Width, //ui8_picture_width_in_mbs |
| ctx->ui16PictureHeight, //ui8_picture_height_in_mbs |
| ctx->ui32CustomQuantMask, //0, ui8_custom_quant_mask |
| ctx->ui8ProfileIdc, //ui8_profile |
| ctx->ui8LevelIdc, //ui8_level |
| ctx->ui8FieldCount, //1, ui8_field_count |
| ctx->ui8MaxNumRefFrames, //1, ui8_max_num_ref_frames |
| ctx->bPpsScaling, //0 ui8_pps_scaling_cnt |
| ctx->bUseDefaultScalingList, //0, b_use_default_scaling_list |
| ctx->bEnableLossless, //0, blossless |
| ctx->bArbitrarySO |
| ); |
| psb_buffer_unmap(&(ps_mem->bufs_sub_seq_header)); |
| } |
| |
| cmdbuf->cmd_idx_saved[TNG_CMDBUF_SEQ_HEADER_IDX] = cmdbuf->cmd_idx; |
| |
| return ; |
| } |
| |
| static void tng__H264ES_send_pic_header(context_ENC_p ctx, IMG_UINT32 ui32StreamIndex) |
| { |
| context_ENC_mem *ps_mem = &(ctx->ctx_mem[ui32StreamIndex]); |
| IMG_BOOL bDepViewPPS = IMG_FALSE; |
| |
| if ((ctx->bEnableMVC) && (ctx->ui16MVCViewIdx != 0) && |
| (ctx->ui16MVCViewIdx != (IMG_UINT16)(NON_MVC_VIEW))) { |
| bDepViewPPS = IMG_TRUE; |
| } |
| |
| psb_buffer_map(&(ps_mem->bufs_pic_template), &(ps_mem->bufs_pic_template.virtual_addr)); |
| if (ps_mem->bufs_pic_template.virtual_addr == NULL) { |
| drv_debug_msg(VIDEO_DEBUG_ERROR, "%s error: mapping pic template\n", __FUNCTION__); |
| return ; |
| } |
| |
| tng__H264ES_prepare_picture_header( |
| ps_mem->bufs_pic_template.virtual_addr, |
| ctx->bCabacEnabled, |
| ctx->bH2648x8Transform, //IMG_BOOL b_8x8transform, |
| ctx->bH264IntraConstrained, //IMG_BOOL bIntraConstrained, |
| 0, //IMG_INT8 i8CQPOffset, |
| 0, //IMG_BOOL bWeightedPrediction, |
| 0, //IMG_UINT8 ui8WeightedBiPred, |
| bDepViewPPS, //IMG_BOOL bMvcPPS, |
| 0, //IMG_BOOL bScalingMatrix, |
| 0 //IMG_BOOL bScalingLists |
| ); |
| |
| psb_buffer_unmap(&(ps_mem->bufs_pic_template)); |
| return ; |
| } |
| |
| static void tng__H264ES_send_hrd_header(context_ENC_p ctx, IMG_UINT32 ui32StreamIndex) |
| { |
| unsigned int ui32nal_initial_cpb_removal_delay; |
| unsigned int ui32nal_initial_cpb_removal_delay_offset; |
| uint32_t ui32cpb_removal_delay; |
| IMG_RC_PARAMS *psRCParams = &(ctx->sRCParams); |
| context_ENC_mem *ps_mem = &(ctx->ctx_mem[ui32StreamIndex]); |
| H264_VUI_PARAMS *psVuiParams = &(ctx->sVuiParams); |
| IMG_UINT8 aui8clocktimestampflag[1]; |
| aui8clocktimestampflag[0] = IMG_FALSE; |
| |
| ui32nal_initial_cpb_removal_delay = |
| 90000 * (1.0 * psRCParams->i32InitialDelay / psRCParams->ui32BitsPerSecond); |
| ui32nal_initial_cpb_removal_delay_offset = |
| 90000 * (1.0 * ctx->buffer_size / psRCParams->ui32BitsPerSecond) |
| - ui32nal_initial_cpb_removal_delay; |
| |
| drv_debug_msg(VIDEO_DEBUG_GENERAL, "Insert SEI buffer period message with " |
| "ui32nal_initial_cpb_removal_delay(%d) and " |
| "ui32nal_initial_cpb_removal_delay_offset(%d)\n", |
| ui32nal_initial_cpb_removal_delay, |
| ui32nal_initial_cpb_removal_delay_offset); |
| |
| psb_buffer_map(&(ps_mem->bufs_sei_header), &(ps_mem->bufs_sei_header.virtual_addr)); |
| if (ps_mem->bufs_sei_header.virtual_addr == NULL) { |
| drv_debug_msg(VIDEO_DEBUG_ERROR, "%s error: mapping sei header\n", __FUNCTION__); |
| return ; |
| } |
| |
| if ((!ctx->bEnableMVC) || (ctx->ui16MVCViewIdx == 0)) { |
| tng__H264ES_prepare_AUD_header(ps_mem->bufs_sei_header.virtual_addr); |
| } |
| |
| tng__H264ES_prepare_SEI_buffering_period_header( |
| ps_mem->bufs_sei_header.virtual_addr + (ctx->ctx_mem_size.sei_header), |
| 0,// ui8cpb_cnt_minus1, |
| psVuiParams->initial_cpb_removal_delay_length_minus1+1, //ui8initial_cpb_removal_delay_length, |
| 1, //ui8NalHrdBpPresentFlag, |
| ui32nal_initial_cpb_removal_delay, // ui32nal_initial_cpb_removal_delay, |
| ui32nal_initial_cpb_removal_delay_offset, //ui32nal_initial_cpb_removal_delay_offset, |
| 0, //ui8VclHrdBpPresentFlag - CURRENTLY HARD CODED TO ZERO IN TOPAZ |
| NOT_USED_BY_TOPAZ, // ui32vcl_initial_cpb_removal_delay, (not used when ui8VclHrdBpPresentFlag = 0) |
| NOT_USED_BY_TOPAZ); // ui32vcl_initial_cpb_removal_delay_offset (not used when ui8VclHrdBpPresentFlag = 0) |
| |
| /* ui32cpb_removal_delay is zero for 1st frame and will be reset |
| * after a IDR frame */ |
| if (ctx->ui32FrameCount[ui32StreamIndex] == 0) { |
| if (ctx->ui32RawFrameCount == 0) |
| ui32cpb_removal_delay = 0; |
| else |
| ui32cpb_removal_delay = |
| ctx->ui32IdrPeriod * ctx->ui32IntraCnt * 2; |
| } else |
| ui32cpb_removal_delay = 2 * ctx->ui32FrameCount[ui32StreamIndex]; |
| |
| tng__H264ES_prepare_SEI_picture_timing_header( |
| ps_mem->bufs_sei_header.virtual_addr + (ctx->ctx_mem_size.sei_header * 2), |
| 1, //ui8CpbDpbDelaysPresentFlag, |
| psVuiParams->cpb_removal_delay_length_minus1, //cpb_removal_delay_length_minus1, |
| psVuiParams->dpb_output_delay_length_minus1, //dpb_output_delay_length_minus1, |
| ui32cpb_removal_delay, //ui32cpb_removal_delay, |
| 2, //ui32dpb_output_delay, |
| 0, //ui8pic_struct_present_flag (contained in the sequence header, Topaz hard-coded default to 0) |
| NOT_USED_BY_TOPAZ, //ui8pic_struct, (not used when ui8pic_struct_present_flag = 0) |
| NOT_USED_BY_TOPAZ, //NumClockTS, (not used when ui8pic_struct_present_flag = 0) |
| aui8clocktimestampflag, //abclock_timestamp_flag, (not used when ui8pic_struct_present_flag = 0) |
| NOT_USED_BY_TOPAZ, //ui8full_timestamp_flag, (not used when ui8pic_struct_present_flag = 0) |
| NOT_USED_BY_TOPAZ, //ui8seconds_flag, (not used when ui8pic_struct_present_flag = 0) |
| NOT_USED_BY_TOPAZ, //ui8minutes_flag, (not used when ui8pic_struct_present_flag = 0) |
| NOT_USED_BY_TOPAZ, //ui8hours_flag, (not used when ui8pic_struct_present_flag = 0) |
| NOT_USED_BY_TOPAZ, //seconds_value, (not used when ui8pic_struct_present_flag = 0) |
| NOT_USED_BY_TOPAZ, //minutes_value, (not used when ui8pic_struct_present_flag = 0) |
| NOT_USED_BY_TOPAZ, //hours_value, (not used when ui8pic_struct_present_flag = 0) |
| NOT_USED_BY_TOPAZ, //ct_type (2=Unknown) See TRM Table D 2 ?Mapping of ct_type to source picture scan (not used when ui8pic_struct_present_flag = 0) |
| NOT_USED_BY_TOPAZ, //nuit_field_based_flag, (not used when ui8pic_struct_present_flag = 0) |
| NOT_USED_BY_TOPAZ, //counting_type (See TRM Table D 3 ?Definition of counting_type values) (not used when ui8pic_struct_present_flag = 0) |
| NOT_USED_BY_TOPAZ, //ui8discontinuity_flag, (not used when ui8pic_struct_present_flag = 0) |
| NOT_USED_BY_TOPAZ, //ui8cnt_dropped_flag, (not used when ui8pic_struct_present_flag = 0) |
| NOT_USED_BY_TOPAZ, //n_frames, (not used when ui8pic_struct_present_flag = 0) |
| NOT_USED_BY_TOPAZ, //time_offset_length, (not used when ui8pic_struct_present_flag = 0) |
| NOT_USED_BY_TOPAZ); //time_offset (not used when ui8pic_struct_present_flag = 0) |
| psb_buffer_unmap(&(ps_mem->bufs_sei_header)); |
| |
| return ; |
| } |
| |
| static void tng__generate_slice_params_template( |
| context_ENC_p ctx, |
| IMG_UINT32 slice_buf_idx, |
| IMG_UINT32 slice_type, |
| IMG_UINT32 ui32StreamIndex |
| ) |
| { |
| context_ENC_mem *ps_mem = &(ctx->ctx_mem[ui32StreamIndex]); |
| IMG_UINT8 *slice_mem_temp_p = NULL; |
| IMG_UINT32 ui32SliceHeight = 0; |
| IMG_FRAME_TEMPLATE_TYPE slice_temp_type = (IMG_FRAME_TEMPLATE_TYPE)slice_type; |
| IMG_FRAME_TEMPLATE_TYPE buf_idx = (IMG_FRAME_TEMPLATE_TYPE)slice_buf_idx; |
| |
| if (ctx->ui8SlicesPerPicture != 0) |
| ui32SliceHeight = ctx->ui16PictureHeight / ctx->ui8SlicesPerPicture; |
| else |
| drv_debug_msg(VIDEO_DEBUG_GENERAL, "%s slice height\n", __FUNCTION__); |
| |
| ui32SliceHeight &= ~15; |
| |
| drv_debug_msg(VIDEO_DEBUG_GENERAL, "%s PTG ui8DeblockIDC = %x\n", __FUNCTION__, ctx->ui8DeblockIDC ); |
| drv_debug_msg(VIDEO_DEBUG_GENERAL, "%s PTG ui32SliceHeight = %x\n", __FUNCTION__, ui32SliceHeight ); |
| drv_debug_msg(VIDEO_DEBUG_GENERAL, "%s PTG bIsInterlaced = %x\n", __FUNCTION__, ctx->bIsInterlaced ); |
| drv_debug_msg(VIDEO_DEBUG_GENERAL, "%s PTG iFineYSearchSize = %x\n", __FUNCTION__, ctx->iFineYSearchSize); |
| |
| tng__prepare_encode_sliceparams( |
| ctx, |
| slice_buf_idx, |
| slice_temp_type, |
| 0, // ui16CurrentRow, |
| ui32SliceHeight, |
| ctx->ui8DeblockIDC, // uiDeblockIDC |
| ctx->bIsInterlaced, // bFieldMode |
| ctx->iFineYSearchSize, |
| ui32StreamIndex |
| ); |
| |
| drv_debug_msg(VIDEO_DEBUG_GENERAL, "%s PTG bCabacEnabled = %x\n", __FUNCTION__, ctx->bCabacEnabled ); |
| drv_debug_msg(VIDEO_DEBUG_GENERAL, "%s PTG ui16MVCViewIdx = %x\n", __FUNCTION__, ctx->ui16MVCViewIdx); |
| |
| if(ctx->bEnableMVC) |
| ctx->ui16MVCViewIdx = (IMG_UINT16)ui32StreamIndex; |
| |
| if (ps_mem->bufs_slice_template.virtual_addr == NULL) { |
| drv_debug_msg(VIDEO_DEBUG_ERROR, "%s error: mapping slice template\n", __FUNCTION__); |
| return ; |
| } |
| |
| slice_mem_temp_p = (IMG_UINT8*)(ps_mem->bufs_slice_template.virtual_addr + (ctx->ctx_mem_size.slice_template * buf_idx)); |
| drv_debug_msg(VIDEO_DEBUG_GENERAL, "%s: addr 0x%08x, virtual 0x%08x, size = 0x%08x, buf_idx = %x\n", |
| __FUNCTION__, slice_mem_temp_p, ps_mem->bufs_slice_template.virtual_addr, ctx->ctx_mem_size.slice_template, buf_idx); |
| |
| /* Prepare Slice Header Template */ |
| switch (ctx->eStandard) { |
| case IMG_STANDARD_NONE: |
| case IMG_STANDARD_JPEG: |
| case IMG_STANDARD_MPEG4: |
| break; |
| case IMG_STANDARD_H264: |
| //H264_NOTFORSIMS_PrepareSliceHeader |
| tng__H264ES_notforsims_prepare_sliceheader( |
| slice_mem_temp_p, |
| slice_temp_type, |
| ctx->ui8DeblockIDC, |
| 0, // ui32FirstMBAddress |
| 0, // uiMBSkipRun |
| ctx->bCabacEnabled, |
| ctx->bIsInterlaced, |
| ctx->ui16MVCViewIdx, //(IMG_UINT16)(NON_MVC_VIEW); |
| IMG_FALSE // bIsLongTermRef |
| ); |
| break; |
| |
| case IMG_STANDARD_H263: |
| tng__H263ES_notforsims_prepare_gobsliceheader(slice_mem_temp_p); |
| break; |
| |
| case IMG_STANDARD_MPEG2: |
| tng__MPEG2_prepare_sliceheader(slice_mem_temp_p); |
| break; |
| } |
| |
| psb_buffer_unmap(&(ps_mem->bufs_slice_template)); |
| |
| drv_debug_msg(VIDEO_DEBUG_GENERAL, "%s: end \n", __FUNCTION__); |
| |
| return ; |
| } |
| |
| //H264_PrepareTemplates |
| static VAStatus tng__prepare_templates(context_ENC_p ctx, IMG_UINT32 ui32StreamIndex) |
| { |
| IMG_RC_PARAMS *psRCParams = &(ctx->sRCParams); |
| PIC_PARAMS *psPicParams = &(ctx->sPicParams); |
| IN_RC_PARAMS* psInParams = &(psPicParams->sInParams); |
| psPicParams->ui32Flags = 0; |
| |
| tng__prepare_mv_estimates(ctx, ui32StreamIndex); |
| |
| switch (ctx->eStandard) { |
| case IMG_STANDARD_H263: |
| psPicParams->ui32Flags |= ISH263_FLAGS; |
| break; |
| case IMG_STANDARD_MPEG4: |
| psPicParams->ui32Flags |= ISMPEG4_FLAGS; |
| break; |
| case IMG_STANDARD_MPEG2: |
| psPicParams->ui32Flags |= ISMPEG2_FLAGS; |
| break; |
| default: |
| break; |
| } |
| |
| if (psRCParams->eRCMode) { |
| psPicParams->ui32Flags |= ISRC_FLAGS; |
| tng__setup_rcdata(ctx); |
| } else { |
| psInParams->ui8SeInitQP = psRCParams->ui32InitialQp; |
| psInParams->ui8MBPerRow = (ctx->ui16Width >> 4); |
| psInParams->ui16MBPerFrm = (ctx->ui16Width >> 4) * (ctx->ui16PictureHeight >> 4); |
| psInParams->ui16MBPerBU = psRCParams->ui32BUSize; |
| psInParams->ui16BUPerFrm = (psInParams->ui16MBPerFrm) / psRCParams->ui32BUSize; |
| ctx->ui32KickSize = psInParams->ui16MBPerBU; |
| } |
| |
| // Prepare Slice header templates |
| tng__generate_slice_params_template(ctx, (IMG_UINT32)IMG_FRAME_IDR, (IMG_UINT32)IMG_FRAME_IDR, ui32StreamIndex); |
| tng__generate_slice_params_template(ctx, (IMG_UINT32)IMG_FRAME_INTRA, (IMG_UINT32)IMG_FRAME_INTRA, ui32StreamIndex); |
| tng__generate_slice_params_template(ctx, (IMG_UINT32)IMG_FRAME_INTER_P, (IMG_UINT32)IMG_FRAME_INTER_P, ui32StreamIndex); |
| switch(ctx->eStandard) { |
| case IMG_STANDARD_H264: |
| tng__generate_slice_params_template(ctx, (IMG_UINT32)IMG_FRAME_INTER_B, (IMG_UINT32)IMG_FRAME_INTER_B, ui32StreamIndex); |
| if (ctx->bEnableMVC) |
| tng__generate_slice_params_template(ctx, (IMG_UINT32)IMG_FRAME_INTER_P_IDR, (IMG_UINT32)IMG_FRAME_INTER_P_IDR, ui32StreamIndex); |
| tng__H264ES_send_seq_header(ctx, 0); |
| tng__H264ES_send_pic_header(ctx, 0); |
| if (ctx->bInsertHRDParams) |
| tng__H264ES_send_hrd_header(ctx, 0); |
| break; |
| case IMG_STANDARD_H263: |
| tng__generate_slice_params_template(ctx, (IMG_UINT32)IMG_FRAME_INTER_B, (IMG_UINT32)IMG_FRAME_INTER_B, ui32StreamIndex); |
| /* Here H263 uses the actual width and height */ |
| tng__h263_generate_pic_hdr_template(ctx, IMG_FRAME_IDR, ctx->h263_actual_width, ctx->h263_actual_height); |
| tng__h263_generate_pic_hdr_template(ctx, IMG_FRAME_INTRA, ctx->h263_actual_width, ctx->h263_actual_height); |
| tng__h263_generate_pic_hdr_template(ctx, IMG_FRAME_INTER_P, ctx->h263_actual_width, ctx->h263_actual_height); |
| break; |
| case IMG_STANDARD_MPEG4: |
| tng__generate_slice_params_template(ctx, (IMG_UINT32)IMG_FRAME_INTER_B, (IMG_UINT32)IMG_FRAME_INTER_P, ui32StreamIndex); |
| tng__mpeg4_generate_pic_hdr_template(ctx, IMG_FRAME_IDR, 4); |
| tng__mpeg4_generate_pic_hdr_template(ctx, IMG_FRAME_INTRA, 4); |
| tng__mpeg4_generate_pic_hdr_template(ctx, IMG_FRAME_INTER_P, 4); |
| tng__mpeg4_generate_pic_hdr_template(ctx, IMG_FRAME_INTER_B, 4); |
| break; |
| default: |
| break; |
| } |
| |
| //FIXME: Zhaohan tng__mpeg2/mpeg4_generate_pic_hdr_template(IMG_FRAME_IDR\IMG_FRAME_INTRA\IMG_FRAME_INTER_P\IMG_FRAME_INTER_B); |
| |
| /* |
| else { |
| slice_mem_temp_p = (IMG_UINT8*)cmdbuf->slice_mem_p + (((IMG_UINT32)IMG_FRAME_INTER_P_IDR) * cmdbuf->mem_size); |
| memset(slice_mem_temp_p, 0, 128); |
| } |
| */ |
| // Prepare Pic Params Templates |
| tng__adjust_picflags(ctx, psRCParams, IMG_TRUE, &(ctx->ui32FirstPicFlags)); |
| tng__adjust_picflags(ctx, psRCParams, IMG_FALSE, &(ctx->ui32NonFirstPicFlags)); |
| |
| return VA_STATUS_SUCCESS; |
| } |
| |
| #if INPUT_SCALER_SUPPORTED |
| static IMG_FLOAT VIDEO_CalculateBessel0 (IMG_FLOAT fX) |
| { |
| IMG_FLOAT fAX, fY; |
| |
| fAX = (IMG_FLOAT)IMG_FABS(fX); |
| |
| if (fAX < 3.75) { |
| fY = (IMG_FLOAT)(fX / 3.75); |
| fY *= fY; |
| |
| return (IMG_FLOAT)(1.0 + fY * |
| (3.5156229 + fY * |
| (3.0899424 + fY * |
| (1.2067492 + fY * |
| (0.2659732 + fY * |
| (0.360768e-1 + fY * 0.45813e-2)))))); |
| } |
| |
| fY = (IMG_FLOAT)(3.75 / fAX); |
| |
| return (IMG_FLOAT)((IMG_EXP(fAX) / IMG_SQRT(fAX)) * |
| (0.39894228 + fY * |
| (0.1328592e-1 + fY * |
| (0.225319e-2 + fY * |
| (-0.157565e-2 + fY * |
| (0.916281e-2 + fY * |
| (-0.2057706e-1 + fY * |
| (0.2635537e-1 + fY * |
| (-0.1647633e-1 + fY * 0.392377e-2))))))))); |
| } |
| |
| static IMG_FLOAT VIDEO_SincFunc (IMG_FLOAT fInput, IMG_FLOAT fScale) |
| { |
| IMG_FLOAT fX; |
| IMG_FLOAT fKaiser; |
| |
| /* Kaiser window */ |
| fX = fInput / (4.0f / 2.0f) - 1.0f; |
| fX = (IMG_FLOAT)IMG_SQRT(1.0f - fX * fX); |
| fKaiser = VIDEO_CalculateBessel0(2.0f * fX) / VIDEO_CalculateBessel0(2.0f); |
| |
| /* Sinc function */ |
| fX = 4.0f / 2.0f - fInput; |
| if (fX == 0) { |
| return fKaiser; |
| } |
| |
| fX *= 0.9f * fScale * 3.1415926535897f; |
| |
| return fKaiser * (IMG_FLOAT)(IMG_SIN(fX) / fX); |
| } |
| |
| static void VIDEO_CalcCoefs_FromPitch (IMG_FLOAT fPitch, IMG_UINT8 aui8Table[4][16]) |
| { |
| /* Based on sim code */ |
| /* The function is symmetrical, so we only need to calculate the first half of the taps, and the middle value. */ |
| |
| IMG_FLOAT fScale; |
| IMG_UINT32 ui32I, ui32Tap; |
| IMG_FLOAT afTable[4][16]; |
| IMG_INT32 i32Total; |
| IMG_FLOAT fTotal; |
| IMG_INT32 i32MiddleTap, i32MiddleI; /* Mirrored / middle Values for I and T */ |
| |
| if (fPitch < 1.0f) { |
| fScale = 1.0f; |
| } else { |
| fScale = 1.0f / fPitch; |
| } |
| |
| for (ui32I = 0; ui32I < 16; ui32I++) { |
| for (ui32Tap = 0; ui32Tap < 4; ui32Tap++) { |
| afTable[ui32Tap][ui32I] = VIDEO_SincFunc(((IMG_FLOAT)ui32Tap) + ((IMG_FLOAT)ui32I) / 16.0f, fScale); |
| } |
| } |
| |
| for (ui32Tap = 0; ui32Tap < 2; ui32Tap++) { |
| for (ui32I = 0; ui32I < 16; ui32I++) { |
| /* Copy the table around the centre point */ |
| i32MiddleTap = (3 - ui32Tap) + (16 - ui32I) / 16; |
| i32MiddleI = (16 - ui32I) & 15; |
| if ((IMG_UINT32)i32MiddleTap < 4) { |
| afTable[i32MiddleTap][i32MiddleI] = afTable[ui32Tap][ui32I]; |
| } |
| } |
| } |
| |
| /* The middle value */ |
| afTable[2][0] = VIDEO_SincFunc(2.0f, fScale); |
| |
| /* Normalize this interpolation point, and convert to 2.6 format, truncating the result */ |
| for (ui32I = 0; ui32I < 16; ui32I++) { |
| fTotal = 0.0f; |
| i32Total = 0; |
| |
| for (ui32Tap = 0; ui32Tap < 4; ui32Tap++) { |
| fTotal += afTable[ui32Tap][ui32I]; |
| } |
| |
| for (ui32Tap = 0; ui32Tap < 4; ui32Tap++) { |
| aui8Table[ui32Tap][ui32I] = (IMG_UINT8)((afTable[ui32Tap][ui32I] * 64.0f) / fTotal); |
| i32Total += aui8Table[ui32Tap][ui32I]; |
| } |
| |
| if (ui32I <= 8) { /* normalize any floating point errors */ |
| i32Total -= 64; |
| if (ui32I == 8) { |
| i32Total /= 2; |
| } |
| /* Subtract the error from the I Point in the first tap ( this will not get |
| mirrored, as it would go off the end). */ |
| aui8Table[0][ui32I] = (IMG_UINT8)(aui8Table[0][ui32I] - (IMG_UINT8)i32Total); |
| } |
| } |
| |
| /* Copy the normalised table around the centre point */ |
| for (ui32Tap = 0; ui32Tap < 2; ui32Tap++) { |
| for (ui32I = 0; ui32I < 16; ui32I++) { |
| i32MiddleTap = (3 - ui32Tap) + (16 - ui32I) / 16; |
| i32MiddleI = (16 - ui32I) & 15; |
| if ((IMG_UINT32)i32MiddleTap < 4) { |
| aui8Table[i32MiddleTap][i32MiddleI] = aui8Table[ui32Tap][ui32I]; |
| } |
| } |
| } |
| return ; |
| } |
| #endif |
| |
| static void tng__setvideo_params(context_ENC_p ctx, IMG_UINT32 ui32StreamIndex) |
| { |
| context_ENC_mem *ps_mem = &(ctx->ctx_mem[ui32StreamIndex]); |
| context_ENC_frame_buf *ps_buf = &(ctx->ctx_frame_buf); |
| IMG_MTX_VIDEO_CONTEXT* psMtxEncContext = NULL; |
| IMG_RC_PARAMS * psRCParams = &(ctx->sRCParams); |
| //IMG_UINT16 ui16WidthInMbs = (ctx->ui16Width + 15) >> 4; |
| //IMG_UINT16 ui16FrameHeightInMbs = (ctx->ui16FrameHeight + 15) >> 4; |
| IMG_INT nIndex; |
| IMG_UINT8 ui8Flag; |
| #ifndef EXCLUDE_ADAPTIVE_ROUNDING |
| IMG_INT32 i, j; |
| #endif |
| |
| psb_buffer_map(&(ps_mem->bufs_mtx_context), &(ps_mem->bufs_mtx_context.virtual_addr)); |
| if (ps_mem->bufs_mtx_context.virtual_addr == NULL) { |
| drv_debug_msg(VIDEO_DEBUG_ERROR, "%s error: mapping slice template\n", __FUNCTION__); |
| return ; |
| } |
| |
| psMtxEncContext = (IMG_MTX_VIDEO_CONTEXT*)(ps_mem->bufs_mtx_context.virtual_addr); |
| |
| ctx->i32PicNodes = (psRCParams->b16Hierarchical ? MAX_REF_B_LEVELS : 0) + ctx->ui8RefSpacing + 4; |
| ctx->i32MVStores = (ctx->i32PicNodes * 2); |
| ctx->ui8SlotsInUse = psRCParams->ui16BFrames + 2; |
| |
| psMtxEncContext->ui32InitialQp = ctx->sRCParams.ui32InitialQp; |
| psMtxEncContext->ui32BUSize = ctx->sRCParams.ui32BUSize; |
| psMtxEncContext->ui16CQPOffset = (ctx->sRCParams.i8QCPOffset & 0x1f) | ((ctx->sRCParams.i8QCPOffset & 0x1f) << 8); |
| psMtxEncContext->eStandard = ctx->eStandard; |
| psMtxEncContext->ui32WidthInMbs = ctx->ui16Width >> 4; |
| psMtxEncContext->ui32PictureHeightInMbs = ctx->ui16PictureHeight >> 4; |
| psMtxEncContext->bOutputReconstructed = (ps_buf->rec_surface != NULL) ? IMG_TRUE : IMG_FALSE; |
| psMtxEncContext->ui32VopTimeResolution = ctx->ui32VopTimeResolution; |
| psMtxEncContext->ui8MaxSlicesPerPicture = ctx->ui8SlicesPerPicture; |
| psMtxEncContext->ui8NumPipes = ctx->ui8PipesToUse; |
| psMtxEncContext->eFormat = ctx->eFormat; |
| |
| psMtxEncContext->b8IsInterlaced = ctx->bIsInterlaced; |
| psMtxEncContext->b8TopFieldFirst = ctx->bTopFieldFirst; |
| psMtxEncContext->b8ArbitrarySO = ctx->bArbitrarySO; |
| |
| psMtxEncContext->ui32IdrPeriod = ctx->ui32IdrPeriod * ctx->ui32IntraCnt; |
| psMtxEncContext->ui32BFrameCount = ctx->sRCParams.ui16BFrames; |
| psMtxEncContext->b8Hierarchical = (IMG_BOOL8) ctx->sRCParams.b16Hierarchical; |
| psMtxEncContext->ui32IntraLoopCnt = ctx->ui32IntraCnt; |
| psMtxEncContext->ui8RefSpacing = ctx->ui8RefSpacing; |
| psMtxEncContext->ui32DebugCRCs = ctx->ui32DebugCRCs; |
| |
| psMtxEncContext->ui8FirstPipe = ctx->ui8BasePipe; |
| psMtxEncContext->ui8LastPipe = ctx->ui8BasePipe + ctx->ui8PipesToUse - 1; |
| psMtxEncContext->ui8PipesToUseFlags = 0; |
| ui8Flag = 0x1 << psMtxEncContext->ui8FirstPipe; |
| for (nIndex = 0; nIndex < psMtxEncContext->ui8NumPipes; nIndex++, ui8Flag<<=1) |
| psMtxEncContext->ui8PipesToUseFlags |= ui8Flag; //Pipes used MUST be contiguous from the BasePipe offset |
| |
| // Only used in MPEG2, 2 bit field (0 = 8 bit, 1 = 9 bit, 2 = 10 bit and 3=11 bit precision) |
| if (ctx->eStandard == IMG_STANDARD_MPEG2) |
| psMtxEncContext->ui8MPEG2IntraDCPrecision = ctx->ui8MPEG2IntraDCPrecision; |
| |
| psMtxEncContext->b16EnableMvc = ctx->bEnableMVC; |
| psMtxEncContext->ui16MvcViewIdx = ctx->ui16MVCViewIdx; |
| if (ctx->eStandard == IMG_STANDARD_H264) |
| psMtxEncContext->b16NoSequenceHeaders = ctx->bNoSequenceHeaders; |
| |
| { |
| IMG_UINT16 ui16SrcYStride = 0, ui16SrcUVStride = 0; |
| // 3 Components: Y, U, V |
| ctx->ui16BufferStride = ps_buf->src_surface->psb_surface->stride; |
| ui16SrcUVStride = ui16SrcYStride = ctx->ui16BufferStride; |
| ctx->ui16BufferHeight = ctx->ui16FrameHeight; |
| switch (ctx->eFormat) { |
| case IMG_CODEC_YUV: |
| case IMG_CODEC_PL8: |
| case IMG_CODEC_YV12: |
| ui16SrcUVStride = ui16SrcYStride / 2; |
| break; |
| |
| case IMG_CODEC_PL12: // Interleaved chroma pixels |
| case IMG_CODEC_IMC2: // Interleaved chroma rows |
| case IMG_CODEC_422_YUV: // Odd-numbered chroma rows unused |
| case IMG_CODEC_422_YV12: // Odd-numbered chroma rows unused |
| case IMG_CODEC_422_PL8: // Odd-numbered chroma rows unused |
| case IMG_CODEC_Y0UY1V_8888: // Interleaved luma and chroma pixels |
| case IMG_CODEC_Y0VY1U_8888: // Interleaved luma and chroma pixels |
| case IMG_CODEC_UY0VY1_8888: // Interleaved luma and chroma pixels |
| case IMG_CODEC_VY0UY1_8888: // Interleaved luma and chroma pixels |
| ui16SrcUVStride = ui16SrcYStride; |
| break; |
| |
| case IMG_CODEC_422_IMC2: // Interleaved chroma pixels and unused odd-numbered chroma rows |
| case IMG_CODEC_422_PL12: // Interleaved chroma rows and unused odd-numbered chroma rows |
| ui16SrcUVStride = ui16SrcYStride * 2; |
| break; |
| |
| default: |
| break; |
| } |
| |
| if ((ctx->bIsInterlaced) && (ctx->bIsInterleaved)) { |
| ui16SrcYStride *= 2; // ui16SrcYStride |
| ui16SrcUVStride *= 2; // ui16SrcUStride |
| } |
| |
| psMtxEncContext->ui32PicRowStride = F_ENCODE(ui16SrcYStride >> 6, TOPAZHP_CR_CUR_PIC_LUMA_STRIDE) | |
| F_ENCODE(ui16SrcUVStride >> 6, TOPAZHP_CR_CUR_PIC_CHROMA_STRIDE); |
| } |
| |
| psMtxEncContext->eRCMode = ctx->sRCParams.eRCMode; |
| psMtxEncContext->b8DisableBitStuffing = ctx->sRCParams.bDisableBitStuffing; |
| psMtxEncContext->b8FirstPic = IMG_TRUE; |
| |
| /*Contents Adaptive Rate Control Parameters*/ |
| psMtxEncContext->bCARC = ctx->sCARCParams.bCARC; |
| psMtxEncContext->iCARCBaseline = ctx->sCARCParams.i32CARCBaseline; |
| psMtxEncContext->uCARCThreshold = ctx->sCARCParams.ui32CARCThreshold; |
| psMtxEncContext->uCARCCutoff = ctx->sCARCParams.ui32CARCCutoff; |
| psMtxEncContext->uCARCNegRange = ctx->sCARCParams.ui32CARCNegRange; |
| psMtxEncContext->uCARCNegScale = ctx->sCARCParams.ui32CARCNegScale; |
| psMtxEncContext->uCARCPosRange = ctx->sCARCParams.ui32CARCPosRange; |
| psMtxEncContext->uCARCPosScale = ctx->sCARCParams.ui32CARCPosScale; |
| psMtxEncContext->uCARCShift = ctx->sCARCParams.ui32CARCShift; |
| psMtxEncContext->ui32MVClip_Config = F_ENCODE(ctx->bNoOffscreenMv, TOPAZHP_CR_MVCALC_RESTRICT_PICTURE); |
| psMtxEncContext->ui32LRITC_Tile_Use_Config = 0; |
| psMtxEncContext->ui32LRITC_Cache_Chunk_Config = 0; |
| |
| psMtxEncContext->ui32IPCM_0_Config = F_ENCODE(ctx->ui32CabacBinFlex, TOPAZ_VLC_CR_CABAC_BIN_FLEX) | |
| F_ENCODE(DEFAULT_CABAC_DB_MARGIN, TOPAZ_VLC_CR_CABAC_DB_MARGIN); |
| |
| psMtxEncContext->ui32IPCM_1_Config = F_ENCODE(3200, TOPAZ_VLC_CR_IPCM_THRESHOLD) | |
| F_ENCODE(ctx->ui32CabacBinLimit, TOPAZ_VLC_CR_CABAC_BIN_LIMIT); |
| |
| // leave alone until high profile and constrained modes are defined. |
| psMtxEncContext->ui32H264CompControl = F_ENCODE((ctx->bCabacEnabled ? 0 : 1), TOPAZHP_CR_H264COMP_8X8_CAVLC); |
| |
| psMtxEncContext->ui32H264CompControl |= F_ENCODE(ctx->bUseDefaultScalingList ? 1 : 0, TOPAZHP_CR_H264COMP_DEFAULT_SCALING_LIST); |
| |
| psMtxEncContext->ui32H264CompControl |= F_ENCODE(ctx->bH2648x8Transform ? 1 : 0, TOPAZHP_CR_H264COMP_8X8_TRANSFORM); |
| |
| psMtxEncContext->ui32H264CompControl |= F_ENCODE(ctx->bH264IntraConstrained ? 1 : 0, TOPAZHP_CR_H264COMP_CONSTRAINED_INTRA); |
| |
| |
| #ifndef EXCLUDE_ADAPTIVE_ROUNDING |
| psMtxEncContext->bMCAdaptiveRoundingDisable = ctx->bVPAdaptiveRoundingDisable; |
| psMtxEncContext->ui32H264CompControl |= F_ENCODE(psMtxEncContext->bMCAdaptiveRoundingDisable ? 0 : 1, TOPAZHP_CR_H264COMP_ADAPT_ROUND_ENABLE); |
| |
| if (!psMtxEncContext->bMCAdaptiveRoundingDisable) |
| for (i = 0; i < 4; i++) |
| for (j = 0; j < 18; j++) |
| psMtxEncContext->ui16MCAdaptiveRoundingOffsets[j][i] = H264_ROUNDING_OFFSETS[j][i]; |
| #endif |
| |
| if ((ctx->eStandard == IMG_STANDARD_H264) && (ctx->ui32CoreRev >= MIN_34_REV)) { |
| psMtxEncContext->ui32H264CompControl |= F_ENCODE(USE_VCM_HW_SUPPORT, TOPAZHP_CR_H264COMP_VIDEO_CONF_ENABLE); |
| } |
| |
| psMtxEncContext->ui32H264CompControl |= |
| F_ENCODE(ctx->ui16UseCustomScalingLists & 0x01 ? 1 : 0, TOPAZHP_CR_H264COMP_CUSTOM_QUANT_4X4_INTRA_LUMA_ENABLE) |
| | F_ENCODE(ctx->ui16UseCustomScalingLists & 0x02 ? 1 : 0, TOPAZHP_CR_H264COMP_CUSTOM_QUANT_4X4_INTRA_CB_ENABLE) |
| | F_ENCODE(ctx->ui16UseCustomScalingLists & 0x04 ? 1 : 0, TOPAZHP_CR_H264COMP_CUSTOM_QUANT_4X4_INTRA_CR_ENABLE) |
| | F_ENCODE(ctx->ui16UseCustomScalingLists & 0x08 ? 1 : 0, TOPAZHP_CR_H264COMP_CUSTOM_QUANT_4X4_INTER_LUMA_ENABLE) |
| | F_ENCODE(ctx->ui16UseCustomScalingLists & 0x10 ? 1 : 0, TOPAZHP_CR_H264COMP_CUSTOM_QUANT_4X4_INTER_CB_ENABLE) |
| | F_ENCODE(ctx->ui16UseCustomScalingLists & 0x20 ? 1 : 0, TOPAZHP_CR_H264COMP_CUSTOM_QUANT_4X4_INTER_CR_ENABLE) |
| | F_ENCODE(ctx->ui16UseCustomScalingLists & 0x40 ? 1 : 0, TOPAZHP_CR_H264COMP_CUSTOM_QUANT_8X8_INTRA_LUMA_ENABLE) |
| | F_ENCODE(ctx->ui16UseCustomScalingLists & 0x80 ? 1 : 0, TOPAZHP_CR_H264COMP_CUSTOM_QUANT_8X8_INTER_LUMA_ENABLE); |
| |
| psMtxEncContext->ui32H264CompControl |= |
| F_ENCODE(ctx->bEnableLossless ? 1 : 0, INTEL_H264_LL) |
| | F_ENCODE(ctx->bLossless8x8Prefilter ? 1 : 0, INTEL_H264_LL8X8P); |
| |
| psMtxEncContext->ui32H264CompIntraPredModes = 0x3ffff;// leave at default for now. |
| psMtxEncContext->ui32PredCombControl = ctx->ui32PredCombControl; |
| psMtxEncContext->ui32SkipCodedInterIntra = F_ENCODE(ctx->ui8InterIntraIndex, TOPAZHP_CR_INTER_INTRA_SCALE_IDX) |
| |F_ENCODE(ctx->ui8CodedSkippedIndex, TOPAZHP_CR_SKIPPED_CODED_SCALE_IDX); |
| |
| if (ctx->bEnableInpCtrl) { |
| psMtxEncContext->ui32MBHostCtrl = F_ENCODE(ctx->bEnableHostQP, TOPAZHP_CR_MB_HOST_QP) |
| |F_ENCODE(ctx->bEnableHostBias, TOPAZHP_CR_MB_HOST_SKIPPED_CODED_SCALE) |
| |F_ENCODE(ctx->bEnableHostBias, TOPAZHP_CR_MB_HOST_INTER_INTRA_SCALE); |
| psMtxEncContext->ui32PredCombControl |= F_ENCODE(1, TOPAZHP_CR_INTER_INTRA_SCALE_ENABLE) |
| |F_ENCODE(1, TOPAZHP_CR_SKIPPED_CODED_SCALE_ENABLE); |
| } |
| |
| if (ctx->bEnableCumulativeBiases) |
| psMtxEncContext->ui32PredCombControl |= F_ENCODE(1, TOPAZHP_CR_CUMULATIVE_BIASES_ENABLE); |
| |
| psMtxEncContext->ui32PredCombControl |= |
| F_ENCODE((((ctx->ui8InterIntraIndex == 3) && (ctx->ui8CodedSkippedIndex == 3)) ? 0 : 1), TOPAZHP_CR_INTER_INTRA_SCALE_ENABLE) | |
| F_ENCODE((ctx->ui8CodedSkippedIndex == 3 ? 0 : 1), TOPAZHP_CR_SKIPPED_CODED_SCALE_ENABLE); |
| // workaround for BRN 33252, if the Skip coded scale is set then we also have to set the inter/inter enable. We set it enabled and rely on the default value of 3 (unbiased) to keep things behaving. |
| // psMtxEncContext->ui32PredCombControl |= F_ENCODE((ctx->ui8InterIntraIndex==3?0:1), TOPAZHP_CR_INTER_INTRA_SCALE_ENABLE) | F_ENCODE((ctx->ui8CodedSkippedIndex==3?0:1), TOPAZHP_CR_SKIPPED_CODED_SCALE_ENABLE); |
| //psMtxEncContext->ui32PredCombControl |= F_ENCODE(1, TOPAZHP_CR_INTER_INTRA_SCALE_ENABLE) | F_ENCODE(1, TOPAZHP_CR_SKIPPED_CODED_SCALE_ENABLE); |
| psMtxEncContext->ui32DeblockCtrl = F_ENCODE(ctx->ui8DeblockIDC, TOPAZ_DB_CR_DISABLE_DEBLOCK_IDC); |
| psMtxEncContext->ui32VLCControl = 0; |
| |
| switch (ctx->eStandard) { |
| case IMG_STANDARD_H264: |
| psMtxEncContext->ui32VLCControl |= F_ENCODE(1, TOPAZ_VLC_CR_CODEC); // 1 for H.264 note this is inconsistant with the sequencer value |
| psMtxEncContext->ui32VLCControl |= F_ENCODE(0, TOPAZ_VLC_CR_CODEC_EXTEND); |
| |
| break; |
| case IMG_STANDARD_H263: |
| psMtxEncContext->ui32VLCControl |= F_ENCODE(3, TOPAZ_VLC_CR_CODEC); // 3 for H.263 note this is inconsistant with the sequencer value |
| psMtxEncContext->ui32VLCControl |= F_ENCODE(0, TOPAZ_VLC_CR_CODEC_EXTEND); |
| |
| break; |
| case IMG_STANDARD_MPEG4: |
| psMtxEncContext->ui32VLCControl |= F_ENCODE(2, TOPAZ_VLC_CR_CODEC); // 2 for Mpeg4 note this is inconsistant with the sequencer value |
| psMtxEncContext->ui32VLCControl |= F_ENCODE(0, TOPAZ_VLC_CR_CODEC_EXTEND); |
| break; |
| case IMG_STANDARD_MPEG2: |
| psMtxEncContext->ui32VLCControl |= F_ENCODE(0, TOPAZ_VLC_CR_CODEC); |
| psMtxEncContext->ui32VLCControl |= F_ENCODE(1, TOPAZ_VLC_CR_CODEC_EXTEND); |
| break; |
| default: |
| break; |
| } |
| |
| if (ctx->bCabacEnabled) { |
| psMtxEncContext->ui32VLCControl |= F_ENCODE(1, TOPAZ_VLC_CR_CABAC_ENABLE); // 2 for Mpeg4 note this is inconsistant with the sequencer value |
| } |
| |
| psMtxEncContext->ui32VLCControl |= F_ENCODE(ctx->bIsInterlaced ? 1 : 0, TOPAZ_VLC_CR_VLC_FIELD_CODED); |
| psMtxEncContext->ui32VLCControl |= F_ENCODE(ctx->bH2648x8Transform ? 1 : 0, TOPAZ_VLC_CR_VLC_8X8_TRANSFORM); |
| psMtxEncContext->ui32VLCControl |= F_ENCODE(ctx->bH264IntraConstrained ? 1 : 0, TOPAZ_VLC_CR_VLC_CONSTRAINED_INTRA); |
| |
| psMtxEncContext->ui32VLCSliceControl = F_ENCODE(ctx->sRCParams.ui32SliceByteLimit, TOPAZ_VLC_CR_SLICE_SIZE_LIMIT); |
| psMtxEncContext->ui32VLCSliceMBControl = F_ENCODE(ctx->sRCParams.ui32SliceMBLimit, TOPAZ_VLC_CR_SLICE_MBS_LIMIT); |
| |
| switch (ctx->eStandard) { |
| case IMG_STANDARD_H264: { |
| IMG_UINT32 ui32VertMVLimit = 255; // default to no clipping |
| if (ctx->ui32VertMVLimit) |
| ui32VertMVLimit = ctx->ui32VertMVLimit; |
| // as topaz can only cope with at most 255 (in the register field) |
| ui32VertMVLimit = tng__min(255,ui32VertMVLimit); |
| // workaround for BRN 29973 and 30032 |
| { |
| #if defined(BRN_29973) || defined(BRN_30032) |
| if (ctx->ui32CoreRev <= 0x30006) { |
| if ((ctx->ui16Width / 16) & 1) // BRN 30032, if odd number of macroblocks we need to limit vector to +-112 |
| psMtxEncContext->ui32IPEVectorClipping = F_ENCODE(1, TOPAZHP_CR_IPE_VECTOR_CLIPPING_ENABLED) |
| |F_ENCODE(112, TOPAZHP_CR_IPE_VECTOR_CLIPPING_X) |
| |F_ENCODE(ui32VertMVLimit, TOPAZHP_CR_IPE_VECTOR_CLIPPING_Y); |
| else // for 29973 we need to limit vector to +-120 |
| if (ctx->ui16Width >= 1920) |
| psMtxEncContext->ui32IPEVectorClipping = F_ENCODE(1, TOPAZHP_CR_IPE_VECTOR_CLIPPING_ENABLED) |
| |F_ENCODE(120, TOPAZHP_CR_IPE_VECTOR_CLIPPING_X) |
| |F_ENCODE(ui32VertMVLimit, TOPAZHP_CR_IPE_VECTOR_CLIPPING_Y); |
| else |
| psMtxEncContext->ui32IPEVectorClipping = F_ENCODE(1, TOPAZHP_CR_IPE_VECTOR_CLIPPING_ENABLED) |
| |F_ENCODE(255, TOPAZHP_CR_IPE_VECTOR_CLIPPING_X) |
| |F_ENCODE(ui32VertMVLimit, TOPAZHP_CR_IPE_VECTOR_CLIPPING_Y); |
| } else |
| #endif |
| { |
| psMtxEncContext->ui32IPEVectorClipping = |
| F_ENCODE(1, TOPAZHP_CR_IPE_VECTOR_CLIPPING_ENABLED) | |
| F_ENCODE(255, TOPAZHP_CR_IPE_VECTOR_CLIPPING_X) | |
| F_ENCODE(ui32VertMVLimit, TOPAZHP_CR_IPE_VECTOR_CLIPPING_Y); |
| } |
| } |
| psMtxEncContext->ui32SPEMvdClipRange = F_ENCODE(0, TOPAZHP_CR_SPE_MVD_CLIP_ENABLE); |
| } |
| break; |
| case IMG_STANDARD_H263: |
| { |
| psMtxEncContext->ui32IPEVectorClipping = F_ENCODE(1, TOPAZHP_CR_IPE_VECTOR_CLIPPING_ENABLED) |
| | F_ENCODE(16 - 1, TOPAZHP_CR_IPE_VECTOR_CLIPPING_X) |
| | F_ENCODE(16 - 1, TOPAZHP_CR_IPE_VECTOR_CLIPPING_Y); |
| |
| psMtxEncContext->ui32SPEMvdClipRange = F_ENCODE(1, TOPAZHP_CR_SPE_MVD_CLIP_ENABLE) |
| | F_ENCODE( 62, TOPAZHP_CR_SPE_MVD_POS_CLIP) |
| | F_ENCODE((uint32_t)(-64), TOPAZHP_CR_SPE_MVD_NEG_CLIP); |
| } |
| break; |
| case IMG_STANDARD_MPEG4: |
| case IMG_STANDARD_MPEG2: |
| { |
| IMG_UINT8 uX, uY, uResidualSize; |
| //The maximum MPEG4 and MPEG2 motion vector differential in 1/2 pixels is |
| //calculated as 1 << (fcode - 1) * 32 or *16 in MPEG2 |
| |
| uResidualSize=(ctx->eStandard == IMG_STANDARD_MPEG4 ? 32 : 16); |
| |
| uX = tng__min(128 - 1, (((1<<(ctx->sBiasTables.ui32FCode - 1)) * uResidualSize)/4) - 1); |
| uY = tng__min(104 - 1, (((1<<(ctx->sBiasTables.ui32FCode - 1)) * uResidualSize)/4) - 1); |
| |
| //Write to register |
| psMtxEncContext->ui32IPEVectorClipping = F_ENCODE(1, TOPAZHP_CR_IPE_VECTOR_CLIPPING_ENABLED) |
| | F_ENCODE(uX, TOPAZHP_CR_IPE_VECTOR_CLIPPING_X) |
| | F_ENCODE(uY, TOPAZHP_CR_IPE_VECTOR_CLIPPING_Y); |
| |
| psMtxEncContext->ui32SPEMvdClipRange = F_ENCODE(0, TOPAZHP_CR_SPE_MVD_CLIP_ENABLE); |
| } |
| break; |
| case IMG_STANDARD_JPEG: |
| case IMG_STANDARD_NONE: |
| default: |
| break; |
| } |
| #ifdef FIRMWARE_BIAS |
| //copy the bias tables |
| { |
| int n; |
| for (n = 52; n >= 0; n -= 2) { |
| psMtxEncContext->aui32DirectBias_P[n >> 1] = ctx->sBiasTables.aui32DirectBias_P[n]; |
| psMtxEncContext->aui32InterBias_P[n >> 1] = ctx->sBiasTables.aui32InterBias_P[n]; |
| psMtxEncContext->aui32DirectBias_B[n >> 1] = ctx->sBiasTables.aui32DirectBias_B[n]; |
| psMtxEncContext->aui32InterBias_B[n >> 1] = ctx->sBiasTables.aui32InterBias_B[n]; |
| } |
| } |
| #endif |
| |
| //copy the scale-tables |
| tng__generate_scale_tables(psMtxEncContext); |
| // memcpy(psMtxEncContext->ui32InterIntraScale, ctx->ui32InterIntraScale, sizeof(IMG_UINT32)*SCALE_TBL_SZ); |
| // memcpy(psMtxEncContext->ui32SkippedCodedScale, ctx->ui32SkippedCodedScale, sizeof(IMG_UINT32)*SCALE_TBL_SZ); |
| |
| // WEIGHTED PREDICTION |
| psMtxEncContext->b8WeightedPredictionEnabled = ctx->bWeightedPrediction; |
| psMtxEncContext->ui8MTXWeightedImplicitBiPred = ctx->ui8VPWeightedImplicitBiPred; |
| |
| // SEI_INSERTION |
| psMtxEncContext->b8InsertHRDparams = ctx->bInsertHRDParams; |
| if (psMtxEncContext->b8InsertHRDparams & !ctx->sRCParams.ui32BitsPerSecond) { //ctx->uBitRate |
| /* HRD parameters are meaningless without a bitrate */ |
| psMtxEncContext->b8InsertHRDparams = IMG_FALSE; |
| } |
| if (psMtxEncContext->b8InsertHRDparams) { |
| psMtxEncContext->ui64ClockDivBitrate = (90000 * 0x100000000LL); |
| psMtxEncContext->ui64ClockDivBitrate /= ctx->sRCParams.ui32BitsPerSecond; //ctx->uBitRate; |
| psMtxEncContext->ui32MaxBufferMultClockDivBitrate = (IMG_UINT32)(((IMG_UINT64)(ctx->sRCParams.ui32BufferSize) * |
| (IMG_UINT64) 90000) / (IMG_UINT64) ctx->sRCParams.ui32BitsPerSecond); |
| } |
| |
| memcpy(&psMtxEncContext->sInParams, &ctx->sPicParams.sInParams, sizeof(IN_RC_PARAMS)); |
| // Update MV Scaling settings |
| // IDR |
| // memcpy(&psMtxEncContext->sMVSettingsIdr, &ctx->sMVSettingsIdr, sizeof(IMG_MV_SETTINGS)); |
| // NonB (I or P) |
| // for (i = 0; i <= MAX_BFRAMES; i++) |
| // memcpy(&psMtxEncContext->sMVSettingsNonB[i], &ctx->sMVSettingsNonB[i], sizeof(IMG_MV_SETTINGS)); |
| |
| psMtxEncContext->ui32LRITC_Cache_Chunk_Config = |
| F_ENCODE(ctx->uChunksPerMb, INTEL_CH_PM) | |
| F_ENCODE(ctx->uMaxChunks, INTEL_CH_MX) | |
| F_ENCODE(ctx->uMaxChunks - ctx->uPriorityChunks, INTEL_CH_PY); |
| |
| |
| //they would be set in function tng__prepare_templates() |
| psMtxEncContext->ui32FirstPicFlags = ctx->ui32FirstPicFlags; |
| psMtxEncContext->ui32NonFirstPicFlags = ctx->ui32NonFirstPicFlags; |
| |
| #ifdef LTREFHEADER |
| psMtxEncContext->i8SliceHeaderSlotNum = -1; |
| #endif |
| |
| { |
| memset(psMtxEncContext->aui8PicOnLevel, 0, sizeof(psMtxEncContext->aui8PicOnLevel)); |
| psb_buffer_map(&(ps_mem->bufs_flat_gop), &(ps_mem->bufs_flat_gop.virtual_addr)); |
| if (ps_mem->bufs_flat_gop.virtual_addr == NULL) { |
| drv_debug_msg(VIDEO_DEBUG_ERROR, "%s error: mapping flat gop\n", __FUNCTION__); |
| return ; |
| } |
| tng__minigop_generate_flat(ps_mem->bufs_flat_gop.virtual_addr, psMtxEncContext->ui32BFrameCount, |
| psMtxEncContext->ui8RefSpacing, psMtxEncContext->aui8PicOnLevel); |
| psb_buffer_unmap(&(ps_mem->bufs_flat_gop)); |
| |
| if (ctx->sRCParams.b16Hierarchical) { |
| memset(psMtxEncContext->aui8PicOnLevel, 0, sizeof(psMtxEncContext->aui8PicOnLevel)); |
| psb_buffer_map(&(ps_mem->bufs_hierar_gop), &(ps_mem->bufs_hierar_gop.virtual_addr)); |
| if (ps_mem->bufs_hierar_gop.virtual_addr == NULL) { |
| drv_debug_msg(VIDEO_DEBUG_ERROR, "%s error: mapping sei header\n", __FUNCTION__); |
| return ; |
| } |
| tng_minigop_generate_hierarchical(ps_mem->bufs_hierar_gop.virtual_addr, psMtxEncContext->ui32BFrameCount, |
| psMtxEncContext->ui8RefSpacing, psMtxEncContext->aui8PicOnLevel); |
| psb_buffer_unmap(&(ps_mem->bufs_hierar_gop)); |
| } |
| } |
| |
| #if INPUT_SCALER_SUPPORTED |
| if (ctx->bEnableScaler) { |
| IMG_UINT8 sccCoeffs[4][16]; |
| IMG_UINT32 ui32PitchX, ui32PitchY; |
| IMG_INT32 i32Phase, i32Tap; |
| |
| ui32PitchX = (((IMG_UINT32)(psVideoParams->ui16SourceWidth - psVideoParams->ui8CropLeft - psVideoParams->ui8CropRight)) << 12) / psVideoParams->ui16Width; |
| ui32PitchY = (((IMG_UINT32)(psVideoParams->ui16SourceFrameHeight - psVideoParams->ui8CropTop - psVideoParams->ui8CropBottom)) << 12) / psVideoParams->ui16FrameHeight; |
| |
| // Input size |
| psMtxEncContext->ui32ScalerInputSizeReg = F_ENCODE(psVideoParams->ui16SourceWidth - 1, TOPAZHP_EXT_CR_SCALER_INPUT_WIDTH_MIN1) | |
| F_ENCODE((psVideoParams->ui16SourceFrameHeight >> (psVideo->bIsInterlaced ? 1 : 0)) - 1, TOPAZHP_EXT_CR_SCALER_INPUT_HEIGHT_MIN1); |
| |
| psMtxEncContext->ui32ScalerCropReg = F_ENCODE(psVideoParams->ui8CropLeft, TOPAZHP_EXT_CR_SCALER_INPUT_CROP_HOR) | |
| F_ENCODE(psVideoParams->ui8CropTop, TOPAZHP_EXT_CR_SCALER_INPUT_CROP_VER); |
| |
| // Scale factors |
| psMtxEncContext->ui32ScalerPitchReg = 0; |
| |
| if (ui32PitchX > 0x3FFF) { |
| psMtxEncContext->ui32ScalerPitchReg |= F_ENCODE(1, TOPAZHP_EXT_CR_SCALER_HOR_BILINEAR_FILTER); |
| ui32PitchX >>= 1; |
| } |
| |
| if (ui32PitchX > 0x3FFF) { |
| ui32PitchX = 0x3FFF; |
| } |
| |
| if (ui32PitchY > 0x3FFF) { |
| psMtxEncContext->ui32ScalerPitchReg |= F_ENCODE(1, TOPAZHP_EXT_CR_SCALER_VER_BILINEAR_FILTER); |
| ui32PitchY >>= 1; |
| } |
| |
| if (ui32PitchY > 0x3FFF) { |
| ui32PitchY = 0x3FFF; |
| } |
| |
| psMtxEncContext->ui32ScalerPitchReg |= F_ENCODE(ui32PitchX, TOPAZHP_EXT_CR_SCALER_INPUT_HOR_PITCH) | |
| F_ENCODE(ui32PitchY, TOPAZHP_EXT_CR_SCALER_INPUT_VER_PITCH); |
| |
| |
| // Coefficients |
| VIDEO_CalcCoefs_FromPitch(((IMG_FLOAT)ui32PitchX) / 4096.0f, sccCoeffs); |
| |
| for (i32Phase = 0; i32Phase < 4; i32Phase++) { |
| psMtxEncContext->asHorScalerCoeffRegs[i32Phase] = 0; |
| for (i32Tap = 0; i32Tap < 4; i32Tap++) { |
| psMtxEncContext->asHorScalerCoeffRegs[i32Phase] |= F_ENCODE(sccCoeffs[3 - i32Tap][(i32Phase * 2) + 1], TOPAZHP_EXT_CR_SCALER_HOR_LUMA_COEFF(i32Tap)); |
| } |
| } |
| |
| VIDEO_CalcCoefs_FromPitch(((IMG_FLOAT)ui32PitchY) / 4096.0f, sccCoeffs); |
| |
| for (i32Phase = 0; i32Phase < 4; i32Phase++) { |
| psMtxEncContext->asVerScalerCoeffRegs[i32Phase] = 0; |
| for (i32Tap = 0; i32Tap < 4; i32Tap++) { |
| psMtxEncContext->asVerScalerCoeffRegs[i32Phase] |= F_ENCODE(sccCoeffs[3 - i32Tap][(i32Phase * 2) + 1], TOPAZHP_EXT_CR_SCALER_VER_LUMA_COEFF(i32Tap)); |
| } |
| } |
| } else { |
| // Disable scaling |
| psMtxEncContext->ui32ScalerInputSizeReg = 0; |
| } |
| #endif // INPUT_SCALER_SUPPORTED |
| |
| psb_buffer_unmap(&(ps_mem->bufs_mtx_context)); |
| |
| return ; |
| } |
| |
| static void tng__setvideo_cmdbuf(context_ENC_p ctx, IMG_UINT32 ui32StreamIndex) |
| { |
| context_ENC_mem *ps_mem = &(ctx->ctx_mem[ui32StreamIndex]); |
| context_ENC_mem_size *ps_mem_size = &(ctx->ctx_mem_size); |
| #ifndef _TNG_FRAMES_ |
| context_ENC_frame_buf *ps_buf = &(ctx->ctx_frame_buf); |
| #endif |
| IMG_MTX_VIDEO_CONTEXT* psMtxEncContext = NULL; |
| IMG_INT32 i; |
| |
| psb_buffer_map(&(ps_mem->bufs_mtx_context), &(ps_mem->bufs_mtx_context.virtual_addr)); |
| if (ps_mem->bufs_mtx_context.virtual_addr == NULL) { |
| drv_debug_msg(VIDEO_DEBUG_ERROR, "%s error: mapping sei header\n", __FUNCTION__); |
| return ; |
| } |
| psMtxEncContext = (IMG_MTX_VIDEO_CONTEXT*)(ps_mem->bufs_mtx_context.virtual_addr); |
| |
| tng_cmdbuf_set_phys(&(psMtxEncContext->ui32MVSettingsBTable), 0, |
| &(ps_mem->bufs_mv_setting_btable), 0, 0); |
| if (ctx->sRCParams.b16Hierarchical) |
| tng_cmdbuf_set_phys(&psMtxEncContext->ui32MVSettingsHierarchical, 0, |
| &(ps_mem->bufs_mv_setting_hierar), 0, 0); |
| #ifdef _TNG_FRAMES_ |
| tng_cmdbuf_set_phys(psMtxEncContext->apReconstructured, ctx->i32PicNodes, |
| &(ps_mem->bufs_recon_pictures), 0, ps_mem_size->recon_pictures); |
| #else |
| for (i = 0; i < ctx->i32PicNodes; i++) { |
| tng_cmdbuf_set_phys(&(psMtxEncContext->apReconstructured[i]), 0, |
| &(ps_buf->ref_surface[i]->psb_surface->buf), 0, 0); |
| } |
| #endif |
| |
| tng_cmdbuf_set_phys(psMtxEncContext->apColocated, ctx->i32PicNodes, |
| &(ps_mem->bufs_colocated), 0, ps_mem_size->colocated); |
| |
| tng_cmdbuf_set_phys(psMtxEncContext->apMV, ctx->i32MVStores, |
| &(ps_mem->bufs_mv), 0, ps_mem_size->mv); |
| |
| if (ctx->bEnableMVC) { |
| tng_cmdbuf_set_phys(psMtxEncContext->apInterViewMV, 2, |
| &(ps_mem->bufs_interview_mv), 0, ps_mem_size->interview_mv); |
| } |
| |
| tng_cmdbuf_set_phys(psMtxEncContext->apWritebackRegions, WB_FIFO_SIZE, |
| &(ctx->bufs_writeback), 0, ps_mem_size->writeback); |
| |
| tng_cmdbuf_set_phys(psMtxEncContext->apAboveParams, (IMG_UINT32)(ctx->ui8PipesToUse), |
| &(ps_mem->bufs_above_params), 0, ps_mem_size->above_params); |
| |
| // SEI_INSERTION |
| if (ctx->bInsertHRDParams) { |
| tng_cmdbuf_set_phys(&psMtxEncContext->pSEIBufferingPeriodTemplate, 0, |
| &(ps_mem->bufs_sei_header), ps_mem_size->sei_header, ps_mem_size->sei_header); |
| tng_cmdbuf_set_phys(&psMtxEncContext->pSEIPictureTimingTemplate, 0, |
| &(ps_mem->bufs_sei_header), ps_mem_size->sei_header * 2, ps_mem_size->sei_header); |
| } |
| |
| tng_cmdbuf_set_phys(psMtxEncContext->apSliceParamsTemplates, NUM_SLICE_TYPES, |
| &(ps_mem->bufs_slice_template), 0, ps_mem_size->slice_template); |
| |
| tng_cmdbuf_set_phys(psMtxEncContext->aui32SliceMap, ctx->ui8SlotsInUse, |
| &(ps_mem->bufs_slice_map), 0, ps_mem_size->slice_map); |
| |
| // WEIGHTED PREDICTION |
| if (ctx->bWeightedPrediction || (ctx->ui8VPWeightedImplicitBiPred == WBI_EXPLICIT)) { |
| tng_cmdbuf_set_phys(psMtxEncContext->aui32WeightedPredictionVirtAddr, ctx->ui8SlotsInUse, |
| &(ps_mem->bufs_weighted_prediction), 0, ps_mem_size->weighted_prediction); |
| } |
| |
| tng_cmdbuf_set_phys(&psMtxEncContext->ui32FlatGopStruct, 0, &(ps_mem->bufs_flat_gop), 0, 0); |
| if (psMtxEncContext->b8Hierarchical) |
| tng_cmdbuf_set_phys(&psMtxEncContext->ui32HierarGopStruct, 0, &(ps_mem->bufs_hierar_gop), 0, 0); |
| |
| #ifdef LTREFHEADER |
| tng_cmdbuf_set_phys(psMtxEncContext->aui32LTRefHeader, ctx->ui8SlotsInUse, |
| &(ps_mem->bufs_lt_ref_header), 0, ps_mem_size->lt_ref_header); |
| #endif |
| |
| tng_cmdbuf_set_phys(psMtxEncContext->apPicHdrTemplates, 4, |
| &(ps_mem->bufs_pic_template), 0, ps_mem_size->pic_template); |
| |
| if (ctx->eStandard == IMG_STANDARD_H264) { |
| tng_cmdbuf_set_phys(&(psMtxEncContext->apSeqHeader), 0, |
| &(ps_mem->bufs_seq_header), 0, ps_mem_size->seq_header); |
| if (ctx->bEnableMVC) |
| tng_cmdbuf_set_phys(&(psMtxEncContext->apSubSetSeqHeader), 0, |
| &(ps_mem->bufs_sub_seq_header), 0, ps_mem_size->seq_header); |
| } |
| |
| if (ctx->ui8EnableSelStatsFlags & ESF_FIRST_STAGE_STATS) { |
| tng_cmdbuf_set_phys(psMtxEncContext->pFirstPassOutParamAddr, ctx->ui8SlotsInUse, |
| &(ps_mem->bufs_first_pass_out_params), 0, ps_mem_size->first_pass_out_params); |
| } |
| |
| #ifndef EXCLUDE_BEST_MP_DECISION_DATA |
| // Store the feedback memory address for all "5" slots in the context |
| if (ctx->ui8EnableSelStatsFlags & ESF_MP_BEST_MB_DECISION_STATS |
| || ctx->ui8EnableSelStatsFlags & ESF_MP_BEST_MOTION_VECTOR_STATS) { |
| tng_cmdbuf_set_phys(psMtxEncContext->pFirstPassOutBestMultipassParamAddr, ctx->ui8SlotsInUse, |
| &(ps_mem->bufs_first_pass_out_best_multipass_param), 0, ps_mem_size->first_pass_out_best_multipass_param); |
| } |
| #endif |
| |
| //Store the MB-Input control parameter memory for all the 5-slots in the context |
| if (ctx->bEnableInpCtrl) { |
| tng_cmdbuf_set_phys(psMtxEncContext->pMBCtrlInParamsAddr, ctx->ui8SlotsInUse, |
| &(ps_mem->bufs_mb_ctrl_in_params), 0, ps_mem_size->mb_ctrl_in_params); |
| } |
| |
| psb_buffer_unmap(&(ps_mem->bufs_mtx_context)); |
| |
| drv_debug_msg(VIDEO_DEBUG_GENERAL, "%s end\n", __FUNCTION__); |
| |
| return ; |
| } |
| |
| static VAStatus tng__validate_params(context_ENC_p ctx) |
| { |
| VAStatus vaStatus = VA_STATUS_SUCCESS; |
| IMG_UINT16 ui16WidthInMbs = (ctx->ui16Width + 15) >> 4; |
| IMG_UINT16 ui16PictureHeight = ((ctx->ui16FrameHeight >> (ctx->bIsInterlaced ? 1 : 0)) + 15) & ~15; |
| IMG_UINT16 ui16FrameHeightInMbs = (ctx->ui16FrameHeight + 15) >> 4; |
| |
| if ((ctx->ui16Width & 0xf) != 0) { |
| return VA_STATUS_ERROR_INVALID_PARAMETER; |
| } |
| |
| if ((ctx->ui16FrameHeight & 0xf) != 0) { |
| return VA_STATUS_ERROR_INVALID_PARAMETER; |
| } |
| |
| ctx->uMBspS = ui16WidthInMbs * ui16FrameHeightInMbs * ctx->sRCParams.ui32FrameRate; |
| |
| if (ctx->ui32CoreRev >= MIN_36_REV) { |
| if ((ctx->ui16Width > 4096) || (ctx->ui16PictureHeight > 4096)) { |
| return VA_STATUS_ERROR_INVALID_PARAMETER; |
| } |
| if ((ui16WidthInMbs << 4) * ui16PictureHeight > 2048 * 2048) { |
| return VA_STATUS_ERROR_INVALID_PARAMETER; |
| } |
| } else { |
| if ((ctx->ui16Width > 2048) || (ui16PictureHeight > 2048)) { |
| return VA_STATUS_ERROR_INVALID_PARAMETER; |
| } |
| } |
| |
| if (ctx->eStandard == IMG_STANDARD_H264) { |
| if ((ctx->ui8DeblockIDC == 0) && (ctx->bArbitrarySO)) |
| ctx->ui8DeblockIDC = 2; |
| |
| if ((ctx->ui8DeblockIDC == 0) && ((IMG_UINT32)(ctx->ui8PipesToUse) > 1) && (ctx->ui8SlicesPerPicture > 1)) { |
| drv_debug_msg(VIDEO_DEBUG_GENERAL, "WARNING: Full deblocking with multiple pipes will cause a mismatch between reconstructed and encoded video\n"); |
| drv_debug_msg(VIDEO_DEBUG_GENERAL, "Consider using -deblockIDC 2 or -deblockIDC 1 instead if matching reconstructed video is required.\n"); |
| drv_debug_msg(VIDEO_DEBUG_GENERAL, "WARNING: Forcing -deblockIDC = 2 for HW verification.\n"); |
| ctx->ui8DeblockIDC = 2; |
| } |
| } else if (ctx->eStandard == IMG_STANDARD_H263) { |
| ctx->bArbitrarySO = IMG_FALSE; |
| ctx->ui8DeblockIDC = 1; |
| } else { |
| ctx->ui8DeblockIDC = 1; |
| } |
| |
| //ctx->sRCParams.ui32SliceByteLimit = 0; |
| ctx->sRCParams.ui32SliceMBLimit = 0; |
| //slice params |
| if (ctx->ui8SlicesPerPicture == 0) |
| ctx->ui8SlicesPerPicture = ctx->sCapsParams.ui16RecommendedSlices; |
| else { |
| if (ctx->ui8SlicesPerPicture > ctx->sCapsParams.ui16MaxSlices) |
| ctx->ui8SlicesPerPicture = ctx->sCapsParams.ui16MaxSlices; |
| else if (ctx->ui8SlicesPerPicture < ctx->sCapsParams.ui16MinSlices) |
| ctx->ui8SlicesPerPicture = ctx->sCapsParams.ui16MinSlices; |
| } |
| |
| if (ctx->ui32pseudo_rand_seed == UNINIT_PARAM) { |
| // When -randseed is uninitialised, initialise seed using other commandline values |
| ctx->ui32pseudo_rand_seed = (IMG_UINT32) ((ctx->sRCParams.ui32InitialQp + |
| ctx->ui16PictureHeight + ctx->ui16Width + ctx->sRCParams.ui32BitsPerSecond) & 0xffffffff); |
| // iQP_Luma + pParams->uHeight + pParams->uWidth + pParams->uBitRate) & 0xffffffff); |
| } |
| |
| if (ctx->eStandard == IMG_STANDARD_H264) { |
| ctx->ui8PipesToUse = tng__min(ctx->ui8PipesToUse, ctx->ui8SlicesPerPicture); |
| } else { |
| ctx->ui8PipesToUse = 1; |
| } |
| |
| return vaStatus; |
| } |
| |
| static VAStatus tng__validate_busize(context_ENC_p ctx) |
| { |
| //IMG_RC_PARAMS *psRCParams = &(ctx->sRCParams); |
| // if no BU size is given then pick one ourselves, if doing arbitrary slice order then make BU = width in bu's |
| // forces slice boundaries to no be mid-row |
| if (ctx->bArbitrarySO || (ctx->ui32BasicUnit == 0)) { |
| ctx->ui32BasicUnit = (ctx->ui16Width / 16); |
| drv_debug_msg(VIDEO_DEBUG_GENERAL, "Patched Basic unit to %d\n", ctx->ui32BasicUnit); |
| } else { |
| IMG_UINT32 ui32MBs, ui32MBsperSlice, ui32MBsLastSlice; |
| IMG_UINT32 ui32BUs; |
| IMG_INT32 i32SliceHeight; |
| IMG_UINT32 ui32MaxSlicesPerPipe, ui32MaxMBsPerPipe, ui32MaxBUsPerPipe; |
| |
| ui32MBs = ctx->ui16PictureHeight * ctx->ui16Width / (16 * 16); |
| |
| i32SliceHeight = ctx->ui16PictureHeight / ctx->ui8SlicesPerPicture; |
| i32SliceHeight &= ~15; |
| |
| ui32MBsperSlice = (i32SliceHeight * ctx->ui16Width) / (16 * 16); |
| ui32MBsLastSlice = ui32MBs - (ui32MBsperSlice * (ctx->ui8SlicesPerPicture - 1)); |
| |
| // they have given us a basic unit so validate it |
| if (ctx->ui32BasicUnit < 6) { |
| drv_debug_msg(VIDEO_DEBUG_GENERAL, "\nERROR: Basic unit size too small, must be greater than 6\n"); |
| return VA_STATUS_ERROR_UNKNOWN; |
| } |
| |
| if (ctx->ui32BasicUnit > ui32MBsperSlice) { |
| drv_debug_msg(VIDEO_DEBUG_GENERAL, "\nERROR: Basic unit size(%d) too large", ctx->ui32BasicUnit); |
| drv_debug_msg(VIDEO_DEBUG_GENERAL, " must not be greater than the number of macroblocks in a slice (%d)\n", ui32MBsperSlice); |
| return VA_STATUS_ERROR_UNKNOWN; |
| } |
| if (ctx->ui32BasicUnit > ui32MBsLastSlice) { |
| drv_debug_msg(VIDEO_DEBUG_GENERAL, "\nERROR: Basic unit size(%d) too large", ctx->ui32BasicUnit); |
| drv_debug_msg(VIDEO_DEBUG_GENERAL, " must not be greater than the number of macroblocks in a slice (%d)\n", ui32MBsLastSlice); |
| return VA_STATUS_ERROR_UNKNOWN; |
| } |
| |
| ui32BUs = ui32MBsperSlice / ctx->ui32BasicUnit; |
| if ((ui32BUs * ctx->ui32BasicUnit) != ui32MBsperSlice) { |
| drv_debug_msg(VIDEO_DEBUG_GENERAL, "\nERROR: Basic unit size(%d) not an integer divisor of MB's in a slice(%d)", |
| ctx->ui32BasicUnit, ui32MBsperSlice); |
| return VA_STATUS_ERROR_UNKNOWN; |
| } |
| |
| ui32BUs = ui32MBsLastSlice / ctx->ui32BasicUnit; |
| if ((ui32BUs * ctx->ui32BasicUnit) != ui32MBsLastSlice) { |
| drv_debug_msg(VIDEO_DEBUG_GENERAL, "\nERROR: Basic unit size(%d) not an integer divisor of MB's in the last slice(%d)", |
| ctx->ui32BasicUnit, ui32MBsLastSlice); |
| return VA_STATUS_ERROR_UNKNOWN; |
| } |
| |
| // check if the number of BUs per pipe is greater than 200 |
| ui32MaxSlicesPerPipe = (IMG_UINT32)(ctx->ui8SlicesPerPicture + ctx->ui8PipesToUse - 1) / (IMG_UINT32)(ctx->ui8PipesToUse); |
| ui32MaxMBsPerPipe = (ui32MBsperSlice * (ui32MaxSlicesPerPipe - 1)) + ui32MBsLastSlice; |
| ui32MaxBUsPerPipe = (ui32MaxMBsPerPipe + ctx->ui32BasicUnit - 1) / ctx->ui32BasicUnit; |
| if (ui32MaxBUsPerPipe > 200) { |
| drv_debug_msg(VIDEO_DEBUG_GENERAL, "\nERROR: Basic unit size too small. There must be less than 201 basic units per slice"); |
| return VA_STATUS_ERROR_UNKNOWN; |
| } |
| } |
| |
| ctx->sRCParams.ui32BUSize = ctx->ui32BasicUnit; |
| return VA_STATUS_SUCCESS; |
| } |
| |
| static VAStatus tng__cmdbuf_new_codec(context_ENC_p ctx) |
| { |
| VAStatus vaStatus = VA_STATUS_SUCCESS; |
| tng_cmdbuf_p cmdbuf = ctx->obj_context->tng_cmdbuf; |
| psb_driver_data_p driver_data = ctx->obj_context->driver_data; |
| context_ENC_mem *ps_mem = &(ctx->ctx_mem[0]); |
| |
| *cmdbuf->cmd_idx++ = |
| ((MTX_CMDID_SW_NEW_CODEC & MTX_CMDWORD_ID_MASK) << MTX_CMDWORD_ID_SHIFT) | |
| ((ctx->eCodec & MTX_CMDWORD_CORE_MASK) << MTX_CMDWORD_CORE_SHIFT) | |
| (((driver_data->context_id & MTX_CMDWORD_COUNT_MASK) << MTX_CMDWORD_COUNT_SHIFT)); |
| // (((driver_data->drm_context & MTX_CMDWORD_COUNT_MASK) << MTX_CMDWORD_COUNT_SHIFT)); |
| |
| tng_cmdbuf_insert_command_param((ctx->ui16Width << 16) | ctx->ui16PictureHeight); |
| |
| return vaStatus; |
| } |
| |
| static VAStatus tng__cmdbuf_doheader(context_ENC_p ctx) |
| { |
| VAStatus vaStatus = VA_STATUS_SUCCESS; |
| context_ENC_mem *ps_mem = &(ctx->ctx_mem[ctx->ui32StreamID]); |
| tng_cmdbuf_p cmdbuf = ctx->obj_context->tng_cmdbuf; |
| |
| cmdbuf->cmd_idx_saved[TNG_CMDBUF_PIC_HEADER_IDX] = cmdbuf->cmd_idx; |
| tng_cmdbuf_insert_command(ctx->obj_context, 0, |
| MTX_CMDID_DO_HEADER, |
| 0, |
| &(ps_mem->bufs_seq_header), |
| 0); |
| return vaStatus; |
| } |
| |
| static VAStatus tng__cmdbuf_lowpower(context_ENC_p ctx) |
| { |
| VAStatus vaStatus = VA_STATUS_SUCCESS; |
| tng_cmdbuf_p cmdbuf = ctx->obj_context->tng_cmdbuf; |
| psb_driver_data_p driver_data = ctx->obj_context->driver_data; |
| |
| *cmdbuf->cmd_idx++ = |
| ((MTX_CMDID_SW_LEAVE_LOWPOWER & MTX_CMDWORD_ID_MASK) << MTX_CMDWORD_ID_SHIFT) | |
| (((ctx->ui32RawFrameCount == 0 ? 1 : 0) & MTX_CMDWORD_CORE_MASK) << MTX_CMDWORD_CORE_SHIFT) | |
| (((driver_data->context_id & MTX_CMDWORD_COUNT_MASK) << MTX_CMDWORD_COUNT_SHIFT)); |
| |
| tng_cmdbuf_insert_command_param(ctx->eCodec); |
| |
| return vaStatus; |
| } |
| |
| static VAStatus tng__cmdbuf_load_bias(context_ENC_p ctx) |
| { |
| VAStatus vaStatus = VA_STATUS_SUCCESS; |
| |
| //init bias parameters |
| tng_init_bias_params(ctx); |
| |
| vaStatus = tng__generate_bias(ctx); |
| if (vaStatus != VA_STATUS_SUCCESS) { |
| drv_debug_msg(VIDEO_DEBUG_ERROR, "%s: generate bias params\n", __FUNCTION__, vaStatus); |
| } |
| |
| vaStatus = tng_load_bias(ctx, IMG_INTER_P); |
| if (vaStatus != VA_STATUS_SUCCESS) { |
| drv_debug_msg(VIDEO_DEBUG_ERROR, "%s: load bias params\n", __FUNCTION__, vaStatus); |
| } |
| return vaStatus; |
| } |
| |
| static VAStatus tng__cmdbuf_setvideo(context_ENC_p ctx, IMG_UINT32 ui32StreamIndex) |
| { |
| VAStatus vaStatus = VA_STATUS_SUCCESS; |
| context_ENC_mem *ps_mem = &(ctx->ctx_mem[ui32StreamIndex]); |
| |
| tng__setvideo_params(ctx, ui32StreamIndex); |
| tng__setvideo_cmdbuf(ctx, ui32StreamIndex); |
| |
| tng_cmdbuf_insert_command(ctx->obj_context, ctx->ui32StreamID, |
| MTX_CMDID_SETVIDEO, 0, &(ps_mem->bufs_mtx_context), 0); |
| |
| return vaStatus; |
| } |
| |
| static void tng__rc_update( |
| context_ENC_p ctx, |
| IMG_UINT32 ui32NewBitrate, |
| IMG_UINT8 ui8NewFrameQP, |
| IMG_UINT8 ui8NewFrameMinQP, |
| IMG_UINT8 ui8NewFrameMaxQP, |
| IMG_UINT16 ui16NewIntraPeriod) |
| { |
| psb_buffer_p buf = (psb_buffer_p)(F_ENCODE(ui8NewFrameMinQP, MTX_MSG_RC_UPDATE_MIN_QP) | |
| F_ENCODE(ui8NewFrameMaxQP, MTX_MSG_RC_UPDATE_MAX_QP) | |
| F_ENCODE(ui16NewIntraPeriod, MTX_MSG_RC_UPDATE_INTRA)); |
| tng_cmdbuf_insert_command( |
| ctx->obj_context, |
| ctx->ui32StreamID, |
| MTX_CMDID_RC_UPDATE, |
| F_ENCODE(ui8NewFrameQP, MTX_MSG_RC_UPDATE_QP) | |
| F_ENCODE(ui32NewBitrate, MTX_MSG_RC_UPDATE_BITRATE), |
| buf, |
| 0); |
| } |
| |
| static VAStatus tng__update_ratecontrol(context_ENC_p ctx, IMG_UINT32 ui32StreamIndex) |
| { |
| VAStatus vaStatus = VA_STATUS_SUCCESS; |
| IMG_RC_PARAMS *psRCParams = &(ctx->sRCParams); |
| IMG_UINT32 ui32CmdData = 0; |
| IMG_UINT32 ui32NewBitsPerFrame = 0; |
| IMG_UINT8 ui8NewVCMIFrameQP = 0; |
| |
| if (!(ctx->rc_update_flag)) |
| return vaStatus; |
| |
| tng__setup_rcdata(ctx); |
| |
| drv_debug_msg(VIDEO_DEBUG_GENERAL, |
| "%s: frame[%d] bits_per_second = %d, min_qp = %d, max_qp = %d, initial_qp = %d\n", |
| __FUNCTION__, ctx->ui32FrameCount[ui32StreamIndex], psRCParams->ui32BitsPerSecond, |
| psRCParams->iMinQP, ctx->max_qp, psRCParams->ui32InitialQp); |
| |
| if (ctx->rc_update_flag & RC_MASK_frame_rate) { |
| tng__rc_update(ctx, psRCParams->ui32BitsPerSecond, -1, -1, -1, -1); |
| ctx->rc_update_flag &= ~RC_MASK_frame_rate; |
| } |
| |
| if (ctx->rc_update_flag & RC_MASK_bits_per_second) { |
| tng__rc_update(ctx, psRCParams->ui32BitsPerSecond, -1, -1, -1, -1); |
| ctx->rc_update_flag &= ~RC_MASK_bits_per_second; |
| } |
| |
| if (ctx->rc_update_flag & RC_MASK_min_qp) { |
| tng__rc_update(ctx, -1, -1, psRCParams->iMinQP, -1, -1); |
| ctx->rc_update_flag &= ~RC_MASK_min_qp; |
| } |
| |
| if (ctx->rc_update_flag & RC_MASK_max_qp) { |
| tng__rc_update(ctx, -1, -1, -1, ctx->max_qp, -1); |
| ctx->rc_update_flag &= ~RC_MASK_max_qp; |
| } |
| |
| if (ctx->rc_update_flag & RC_MASK_initial_qp) { |
| tng__rc_update(ctx, -1, psRCParams->ui32InitialQp, -1, -1, -1); |
| ctx->rc_update_flag &= ~RC_MASK_initial_qp; |
| } |
| |
| if (ctx->rc_update_flag & RC_MASK_intra_period) { |
| tng__rc_update(ctx, -1, -1, -1, -1, ctx->ui32IntraCnt); |
| ctx->rc_update_flag &= ~RC_MASK_intra_period; |
| } |
| |
| return vaStatus; |
| } |
| |
| static VAStatus tng__update_frametype(context_ENC_p ctx, IMG_FRAME_TYPE eFrameType) |
| { |
| VAStatus vaStatus = VA_STATUS_SUCCESS; |
| IMG_UINT32 ui32CmdData = 0; |
| |
| ui32CmdData = F_ENCODE(IMG_PICMGMT_REF_TYPE, MTX_MSG_PICMGMT_SUBTYPE) | |
| F_ENCODE(eFrameType, MTX_MSG_PICMGMT_DATA); |
| |
| tng_cmdbuf_insert_command(ctx->obj_context, ctx->ui32StreamID, |
| MTX_CMDID_PICMGMT , |
| ui32CmdData, 0, 0); |
| |
| return vaStatus; |
| } |
| |
| static VAStatus tng__cmdbuf_send_picmgmt(context_ENC_p ctx, IMG_UINT32 ui32StreamIndex) |
| { |
| VAStatus vaStatus = VA_STATUS_SUCCESS; |
| IMG_RC_PARAMS *psRCParams = &(ctx->sRCParams); |
| |
| if (!(ctx->rc_update_flag)) |
| return vaStatus; |
| |
| //tng__setup_rcdata(ctx); |
| drv_debug_msg(VIDEO_DEBUG_GENERAL, |
| "%s: ui32BitsPerSecond = %d, ui32FrameRate = %d, ui32InitialQp = %d\n", |
| __FUNCTION__, psRCParams->ui32BitsPerSecond, |
| psRCParams->ui32FrameRate, psRCParams->ui32InitialQp); |
| drv_debug_msg(VIDEO_DEBUG_GENERAL, |
| "%s: frame_count[%d] = %d\n", __FUNCTION__, |
| ui32StreamIndex, ctx->ui32FrameCount[ui32StreamIndex]); |
| |
| return vaStatus; |
| } |
| |
| |
| static VAStatus tng__cmdbuf_provide_buffer(context_ENC_p ctx, IMG_UINT32 ui32StreamIndex) |
| { |
| VAStatus vaStatus = VA_STATUS_SUCCESS; |
| |
| if (ctx->ui8PipesToUse == 1) { |
| tng_send_codedbuf(ctx, ctx->ui8SlotsCoded); |
| } else { |
| /*Make sure DMA start is 128bits alignment*/ |
| tng_send_codedbuf(ctx, ctx->ui8SlotsCoded * 2); |
| tng_send_codedbuf(ctx, ctx->ui8SlotsCoded * 2 + 1); |
| } |
| |
| if (ctx->sRCParams.ui16BFrames > 0) |
| tng__provide_buffer_BFrames(ctx, ui32StreamIndex); |
| else |
| tng__provide_buffer_PFrames(ctx, ui32StreamIndex); |
| /* |
| if (ctx->ui32LastPicture != 0) { |
| drv_debug_msg(VIDEO_DEBUG_GENERAL, |
| "%s: frame_count[%d] = %d\n", __FUNCTION__, |
| ui32StreamIndex, ctx->ui32FrameCount[ui32StreamIndex]); |
| tng_picmgmt_update(ctx,IMG_PICMGMT_EOS, ctx->ui32LastPicture); |
| } |
| */ |
| #ifdef _TOPAZHP_REC_ |
| tng_send_rec_frames(ctx, -1, 0); |
| tng_send_ref_frames(ctx, 0, 0); |
| tng_send_ref_frames(ctx, 1, 0); |
| #endif |
| |
| ctx->ui8SlotsCoded = (ctx->ui8SlotsCoded + 1) & 1; |
| |
| return vaStatus; |
| } |
| |
| VAStatus tng__set_ctx_buf(context_ENC_p ctx, IMG_UINT32 __maybe_unused ui32StreamID) |
| { |
| VAStatus vaStatus = VA_STATUS_SUCCESS; |
| IMG_UINT8 ui8IsJpeg; |
| |
| vaStatus = tng__validate_params(ctx); |
| if (vaStatus != VA_STATUS_SUCCESS) { |
| drv_debug_msg(VIDEO_DEBUG_ERROR, "validate params"); |
| } |
| |
| vaStatus = tng__validate_busize(ctx); |
| if (vaStatus != VA_STATUS_SUCCESS) { |
| drv_debug_msg(VIDEO_DEBUG_ERROR, "validate busize"); |
| } |
| ctx->ctx_cmdbuf[0].ui32LowCmdCount = 0xa5a5a5a5 % MAX_TOPAZ_CMD_COUNT; |
| ctx->ctx_cmdbuf[0].ui32HighCmdCount = 0; |
| ctx->ctx_cmdbuf[0].ui32HighWBReceived = 0; |
| |
| ui8IsJpeg = (ctx->eStandard == IMG_STANDARD_JPEG) ? 1 : 0; |
| vaStatus = tng__alloc_context_buffer(ctx, ui8IsJpeg, 0); |
| if (vaStatus != VA_STATUS_SUCCESS) { |
| drv_debug_msg(VIDEO_DEBUG_ERROR, "setup enc profile"); |
| } |
| return vaStatus; |
| } |
| |
| static VAStatus tng__set_headers (context_ENC_p ctx, IMG_UINT32 __maybe_unused ui32StreamID) |
| { |
| VAStatus vaStatus = VA_STATUS_SUCCESS; |
| IMG_UINT8 ui8SlotIdx = 0; |
| |
| vaStatus = tng__prepare_templates(ctx, 0); |
| if (vaStatus != VA_STATUS_SUCCESS) { |
| drv_debug_msg(VIDEO_DEBUG_ERROR, "prepare_templates\n"); |
| } |
| |
| for (ui8SlotIdx = 0; ui8SlotIdx < ctx->ui8SlotsInUse; ui8SlotIdx++) |
| tng_fill_slice_map(ctx, (IMG_UINT32)ui8SlotIdx, 0); |
| |
| return vaStatus; |
| } |
| |
| static VAStatus tng__set_cmd_buf(context_ENC_p ctx, IMG_UINT32 __maybe_unused ui32StreamID) |
| { |
| VAStatus vaStatus = VA_STATUS_SUCCESS; |
| |
| vaStatus = tng__cmdbuf_new_codec(ctx); |
| if (vaStatus != VA_STATUS_SUCCESS) { |
| drv_debug_msg(VIDEO_DEBUG_ERROR, "cmdbuf new codec\n"); |
| } |
| |
| vaStatus = tng__cmdbuf_lowpower(ctx); |
| if (vaStatus != VA_STATUS_SUCCESS) { |
| drv_debug_msg(VIDEO_DEBUG_ERROR, "cmdbuf lowpower\n"); |
| } |
| |
| vaStatus = tng__cmdbuf_load_bias(ctx); |
| if (vaStatus != VA_STATUS_SUCCESS) { |
| drv_debug_msg(VIDEO_DEBUG_ERROR, "cmdbuf load bias\n"); |
| } |
| |
| vaStatus = tng__cmdbuf_setvideo(ctx, 0); |
| if (vaStatus != VA_STATUS_SUCCESS) { |
| drv_debug_msg(VIDEO_DEBUG_ERROR, "cmdbuf setvideo\n"); |
| } |
| return vaStatus; |
| } |
| |
| VAStatus tng__end_one_frame(context_ENC_p ctx, IMG_UINT32 ui32StreamID) |
| { |
| VAStatus vaStatus = VA_STATUS_SUCCESS; |
| context_ENC_frame_buf *ps_buf = &(ctx->ctx_frame_buf); |
| |
| drv_debug_msg(VIDEO_DEBUG_GENERAL, "ui32StreamID is %d.\n", ui32StreamID); |
| |
| /* save current settings */ |
| ps_buf->previous_src_surface = ps_buf->src_surface; |
| #ifdef _TNG_FRAMES_ |
| ps_buf->previous_ref_surface = ps_buf->ref_surface; |
| #else |
| ps_buf->previous_ref_surface = ps_buf->ref_surface[0]; |
| #endif |
| |
| /*Frame Skip flag in Coded Buffer of frame N determines if frame N+2 |
| * should be skipped, which means sending encoding commands of frame N+1 doesn't |
| * have to wait until frame N is completed encoded. It reduces the precision of |
| * rate control but improves HD encoding performance a lot.*/ |
| ps_buf->pprevious_coded_buf = ps_buf->previous_coded_buf; |
| ps_buf->previous_coded_buf = ps_buf->coded_buf; |
| |
| ctx->ePreFrameType = ctx->eFrameType; |
| |
| return vaStatus; |
| } |
| |
| VAStatus tng_EndPicture(context_ENC_p ctx) |
| { |
| VAStatus vaStatus = VA_STATUS_SUCCESS; |
| tng_cmdbuf_p cmdbuf = ctx->obj_context->tng_cmdbuf; |
| context_ENC_mem *ps_mem = &(ctx->ctx_mem[0]); |
| unsigned int offset; |
| int value; |
| |
| drv_debug_msg(VIDEO_DEBUG_GENERAL,"%s: ctx->ui8SlicesPerPicture = %d, ctx->ui32FrameCount[0] = %d\n", |
| __FUNCTION__, ctx->ui8SlicesPerPicture, ctx->ui32FrameCount[0]); |
| |
| if (ctx->ui32FrameCount[0] == 0) { |
| vaStatus = tng__set_ctx_buf(ctx, 0); |
| if (vaStatus != VA_STATUS_SUCCESS) { |
| drv_debug_msg(VIDEO_DEBUG_ERROR, "set ctx buf \n"); |
| } |
| vaStatus = tng__set_headers(ctx, 0); |
| if (vaStatus != VA_STATUS_SUCCESS) { |
| drv_debug_msg(VIDEO_DEBUG_ERROR, "set headers \n"); |
| } |
| |
| vaStatus = tng__set_cmd_buf(ctx, 0); |
| if (vaStatus != VA_STATUS_SUCCESS) { |
| drv_debug_msg(VIDEO_DEBUG_ERROR, "set cmd buf \n"); |
| } |
| |
| #ifdef _TOPAZHP_PDUMP_ |
| tng_trace_setvideo(ctx, 0); |
| #endif |
| } else { |
| vaStatus = tng__cmdbuf_lowpower(ctx); |
| if (vaStatus != VA_STATUS_SUCCESS) { |
| drv_debug_msg(VIDEO_DEBUG_ERROR, "cmdbuf lowpower\n"); |
| } |
| } |
| |
| if (ctx->sRCParams.eRCMode != IMG_RCMODE_NONE || |
| ctx->rc_update_flag) { |
| vaStatus = tng__update_ratecontrol(ctx, ctx->ui32StreamID); |
| if (vaStatus != VA_STATUS_SUCCESS) { |
| drv_debug_msg(VIDEO_DEBUG_ERROR, "send picmgmt"); |
| } |
| } |
| |
| if ((ctx->idr_force_flag == 1) && (ctx->sRCParams.ui16BFrames == 0)){ |
| vaStatus = tng__update_frametype(ctx, IMG_FRAME_IDR); |
| if (vaStatus != VA_STATUS_SUCCESS) { |
| drv_debug_msg(VIDEO_DEBUG_ERROR, "send picmgmt IDR"); |
| } |
| ctx->idr_force_flag =0; |
| } |
| |
| vaStatus = tng__cmdbuf_provide_buffer(ctx, ctx->ui32StreamID); |
| if (vaStatus != VA_STATUS_SUCCESS) { |
| drv_debug_msg(VIDEO_DEBUG_ERROR, "provide buffer"); |
| } |
| |
| if (ctx->bEnableAIR == IMG_TRUE || |
| ctx->bEnableCIR == IMG_TRUE) { |
| tng_air_set_input_control(ctx, 0); |
| |
| if (ctx->bEnableAIR == IMG_TRUE) |
| tng_air_set_output_control(ctx, 0); |
| } |
| |
| if (ctx->eStandard == IMG_STANDARD_MPEG4) { |
| if (ctx->ui32FrameCount[0] == 0) { |
| vaStatus = tng__cmdbuf_doheader(ctx); |
| if (vaStatus != VA_STATUS_SUCCESS) { |
| drv_debug_msg(VIDEO_DEBUG_ERROR, "cmdbuf doheader\n"); |
| } |
| } |
| tng__MPEG4ES_send_seq_header(ctx, ctx->ui32StreamID); |
| } |
| |
| if (ctx->bInsertHRDParams) |
| tng_cmdbuf_insert_command(ctx->obj_context, ctx->ui32StreamID, |
| MTX_CMDID_DO_HEADER, 0, &(ps_mem->bufs_sei_header), 0); |
| |
| tng_cmdbuf_insert_command(ctx->obj_context, ctx->ui32StreamID, |
| MTX_CMDID_ENCODE_FRAME, 0, 0, 0); |
| |
| #ifdef _TOPAZHP_CMDBUF_ |
| drv_debug_msg(VIDEO_DEBUG_GENERAL, "%s addr = 0x%08x \n", __FUNCTION__, cmdbuf); |
| tng__trace_cmdbuf_words(cmdbuf); |
| tng__trace_cmdbuf(cmdbuf, ctx->ui32StreamID); |
| #endif |
| |
| // tng_buffer_unmap(ctx, ctx->ui32StreamID); |
| tng_cmdbuf_mem_unmap(cmdbuf); |
| |
| vaStatus = tng__end_one_frame(ctx, 0); |
| if (vaStatus != VA_STATUS_SUCCESS) { |
| drv_debug_msg(VIDEO_DEBUG_ERROR, "setting when one frame ends\n"); |
| } |
| |
| if (tng_context_flush_cmdbuf(ctx->obj_context)) { |
| vaStatus = VA_STATUS_ERROR_UNKNOWN; |
| } |
| |
| |
| ++(ctx->ui32FrameCount[ctx->ui32StreamID]); |
| ++(ctx->ui32RawFrameCount); |
| return vaStatus; |
| } |