blob: c4063714fcce82b01f7f82a68141d07a3f5bbe4b [file] [log] [blame]
/* Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
* only version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
#include "vcd_ddl.h"
#include "vcd_ddl_metadata.h"
#include "vcd_ddl_shared_mem.h"
#include "vcd_core.h"
#if defined(PIX_CACHE_DISABLE)
#define DDL_PIX_CACHE_ENABLE false
#else
#define DDL_PIX_CACHE_ENABLE true
#endif
void ddl_vidc_core_init(struct ddl_context *ddl_context)
{
struct vidc_1080P_pix_cache_config pixel_cache_config;
vidc_1080p_do_sw_reset(VIDC_1080P_RESET_IN_SEQ_FIRST_STAGE);
msleep(DDL_SW_RESET_SLEEP);
vidc_1080p_do_sw_reset(VIDC_1080P_RESET_IN_SEQ_SECOND_STAGE);
vidc_1080p_init_memory_controller(
(u32) ddl_context->dram_base_a.align_physical_addr,
(u32) ddl_context->dram_base_b.align_physical_addr);
vidc_1080p_clear_returned_channel_inst_id();
ddl_context->vidc_decode_seq_start[0] =
vidc_1080p_decode_seq_start_ch0;
ddl_context->vidc_decode_seq_start[1] =
vidc_1080p_decode_seq_start_ch1;
ddl_context->vidc_decode_init_buffers[0] =
vidc_1080p_decode_init_buffers_ch0;
ddl_context->vidc_decode_init_buffers[1] =
vidc_1080p_decode_init_buffers_ch1;
ddl_context->vidc_decode_frame_start[0] =
vidc_1080p_decode_frame_start_ch0;
ddl_context->vidc_decode_frame_start[1] =
vidc_1080p_decode_frame_start_ch1;
ddl_context->vidc_set_dec_resolution[0] =
vidc_1080p_set_dec_resolution_ch0;
ddl_context->vidc_set_dec_resolution[1] =
vidc_1080p_set_dec_resolution_ch1;
ddl_context->vidc_encode_seq_start[0] =
vidc_1080p_encode_seq_start_ch0;
ddl_context->vidc_encode_seq_start[1] =
vidc_1080p_encode_seq_start_ch1;
ddl_context->vidc_encode_frame_start[0] =
vidc_1080p_encode_frame_start_ch0;
ddl_context->vidc_encode_frame_start[1] =
vidc_1080p_encode_frame_start_ch1;
vidc_1080p_release_sw_reset();
ddl_context->pix_cache_enable = DDL_PIX_CACHE_ENABLE;
if (ddl_context->pix_cache_enable) {
vidc_pix_cache_sw_reset();
pixel_cache_config.cache_enable = true;
pixel_cache_config.prefetch_en = true;
pixel_cache_config.port_select = VIDC_1080P_PIX_CACHE_PORT_B;
pixel_cache_config.statistics_off = true;
pixel_cache_config.page_size =
VIDC_1080P_PIX_CACHE_PAGE_SIZE_1K;
vidc_pix_cache_init_config(&pixel_cache_config);
}
}
void ddl_vidc_core_term(struct ddl_context *ddl_context)
{
if (ddl_context->pix_cache_enable) {
u32 pix_cache_idle = false;
u32 counter = 0;
vidc_pix_cache_set_halt(true);
do {
msleep(DDL_SW_RESET_SLEEP);
vidc_pix_cache_get_status_idle(&pix_cache_idle);
counter++;
} while (!pix_cache_idle &&
counter < DDL_PIXEL_CACHE_STATUS_READ_RETRY);
if (!pix_cache_idle) {
ddl_context->cmd_err_status =
DDL_PIXEL_CACHE_NOT_IDLE;
ddl_handle_core_errors(ddl_context);
}
}
}
void ddl_vidc_channel_set(struct ddl_client_context *ddl)
{
struct ddl_context *ddl_context = ddl->ddl_context;
enum vcd_codec *vcd_codec;
enum vidc_1080p_codec codec = VIDC_1080P_H264_DECODE;
const enum vidc_1080p_decode_p_cache_enable
dec_pix_cache = VIDC_1080P_DECODE_PCACHE_DISABLE;
const enum vidc_1080p_encode_p_cache_enable
enc_pix_cache = VIDC_1080P_ENCODE_PCACHE_ENABLE;
u32 pix_cache_ctrl, ctxt_mem_offset, ctxt_mem_size;
if (ddl->decoding) {
if (vidc_msg_timing)
ddl_set_core_start_time(__func__, DEC_OP_TIME);
vcd_codec = &(ddl->codec_data.decoder.codec.codec);
pix_cache_ctrl = (u32)dec_pix_cache;
ctxt_mem_offset = DDL_ADDR_OFFSET(ddl_context->dram_base_a,
ddl->codec_data.decoder.hw_bufs.context) >> 11;
ctxt_mem_size =
ddl->codec_data.decoder.hw_bufs.context.buffer_size;
} else {
vcd_codec = &(ddl->codec_data.encoder.codec.codec);
pix_cache_ctrl = (u32)enc_pix_cache;
ctxt_mem_offset = DDL_ADDR_OFFSET(ddl_context->dram_base_a,
ddl->codec_data.encoder.hw_bufs.context) >> 11;
ctxt_mem_size =
ddl->codec_data.encoder.hw_bufs.context.buffer_size;
}
switch (*vcd_codec) {
default:
case VCD_CODEC_MPEG4:
if (ddl->decoding)
codec = VIDC_1080P_MPEG4_DECODE;
else
codec = VIDC_1080P_MPEG4_ENCODE;
break;
case VCD_CODEC_H264:
if (ddl->decoding)
codec = VIDC_1080P_H264_DECODE;
else
codec = VIDC_1080P_H264_ENCODE;
break;
case VCD_CODEC_DIVX_3:
if (ddl->decoding)
codec = VIDC_1080P_DIVX311_DECODE;
break;
case VCD_CODEC_DIVX_4:
if (ddl->decoding)
codec = VIDC_1080P_DIVX412_DECODE;
break;
case VCD_CODEC_DIVX_5:
if (ddl->decoding)
codec = VIDC_1080P_DIVX502_DECODE;
break;
case VCD_CODEC_DIVX_6:
if (ddl->decoding)
codec = VIDC_1080P_DIVX503_DECODE;
break;
case VCD_CODEC_XVID:
if (ddl->decoding)
codec = VIDC_1080P_MPEG4_DECODE;
break;
case VCD_CODEC_H263:
if (ddl->decoding)
codec = VIDC_1080P_H263_DECODE;
else
codec = VIDC_1080P_H263_ENCODE;
break;
case VCD_CODEC_MPEG1:
case VCD_CODEC_MPEG2:
if (ddl->decoding)
codec = VIDC_1080P_MPEG2_DECODE;
break;
case VCD_CODEC_VC1:
if (ddl->decoding)
codec = VIDC_1080P_VC1_DECODE;
break;
case VCD_CODEC_VC1_RCV:
if (ddl->decoding)
codec = VIDC_1080P_VC1_RCV_DECODE;
break;
}
ddl->cmd_state = DDL_CMD_CHANNEL_SET;
DDL_MSG_LOW("ddl_state_transition: %s ~~> DDL_CLIENT_WAIT_FOR_CHDONE",
ddl_get_state_string(ddl->client_state));
ddl->client_state = DDL_CLIENT_WAIT_FOR_CHDONE;
vidc_1080p_set_host2risc_cmd(VIDC_1080P_HOST2RISC_CMD_OPEN_CH,
(u32)codec, pix_cache_ctrl, ctxt_mem_offset,
ctxt_mem_size);
}
void ddl_vidc_decode_init_codec(struct ddl_client_context *ddl)
{
struct ddl_context *ddl_context = ddl->ddl_context;
struct ddl_decoder_data *decoder = &(ddl->codec_data.decoder);
struct vidc_1080p_dec_seq_start_param seq_start_param;
u32 seq_size;
if (vidc_msg_timing)
ddl_set_core_start_time(__func__, DEC_OP_TIME);
vidc_1080p_set_decode_mpeg4_pp_filter(decoder->post_filter.post_filter);
vidc_sm_set_concealment_color(&ddl->shared_mem[ddl->command_channel],
DDL_CONCEALMENT_Y_COLOR, DDL_CONCEALMENT_C_COLOR);
vidc_sm_set_error_concealment_config(
&ddl->shared_mem[ddl->command_channel],
VIDC_SM_ERR_CONCEALMENT_INTER_SLICE_MB_COPY,
VIDC_SM_ERR_CONCEALMENT_INTRA_SLICE_COLOR_CONCEALMENT,
VIDC_SM_ERR_CONCEALMENT_ENABLE);
ddl_vidc_metadata_enable(ddl);
vidc_sm_set_metadata_start_address(&ddl->shared_mem
[ddl->command_channel],
DDL_ADDR_OFFSET(ddl_context->dram_base_a,
ddl->codec_data.decoder.meta_data_input));
vidc_sm_set_idr_decode_only(&ddl->shared_mem[ddl->command_channel],
decoder->idr_only_decoding);
if ((decoder->codec.codec == VCD_CODEC_DIVX_3) ||
(decoder->codec.codec == VCD_CODEC_VC1_RCV ||
decoder->codec.codec == VCD_CODEC_VC1))
ddl_context->vidc_set_dec_resolution
[ddl->command_channel](decoder->client_frame_size.width,
decoder->client_frame_size.height);
else
ddl_context->vidc_set_dec_resolution
[ddl->command_channel](0x0, 0x0);
DDL_MSG_LOW("HEADER-PARSE-START");
DDL_MSG_LOW("ddl_state_transition: %s ~~>"
"DDL_CLIENT_WAIT_FOR_INITCODECDONE",
ddl_get_state_string(ddl->client_state));
ddl->client_state = DDL_CLIENT_WAIT_FOR_INITCODECDONE;
ddl->cmd_state = DDL_CMD_HEADER_PARSE;
seq_start_param.cmd_seq_num = ++ddl_context->cmd_seq_num;
seq_start_param.inst_id = ddl->instance_id;
seq_start_param.shared_mem_addr_offset = DDL_ADDR_OFFSET(
ddl_context->dram_base_a, ddl->shared_mem
[ddl->command_channel]);
seq_start_param.stream_buffer_addr_offset =
DDL_OFFSET(ddl_context->dram_base_a.align_physical_addr,
decoder->decode_config.sequence_header);
seq_start_param.stream_buffersize =
decoder->client_input_buf_req.sz;
seq_size = decoder->decode_config.sequence_header_len +
DDL_LINEAR_BUFFER_ALIGN_BYTES + VCD_SEQ_HDR_PADDING_BYTES;
if (seq_start_param.stream_buffersize < seq_size)
seq_start_param.stream_buffersize = seq_size;
seq_start_param.stream_frame_size =
decoder->decode_config.sequence_header_len;
seq_start_param.descriptor_buffer_addr_offset =
DDL_ADDR_OFFSET(ddl_context->dram_base_a,
decoder->hw_bufs.desc),
seq_start_param.descriptor_buffer_size =
decoder->hw_bufs.desc.buffer_size;
if ((decoder->codec.codec == VCD_CODEC_MPEG4) ||
(decoder->codec.codec == VCD_CODEC_DIVX_4) ||
(decoder->codec.codec == VCD_CODEC_DIVX_5) ||
(decoder->codec.codec == VCD_CODEC_DIVX_6) ||
(decoder->codec.codec == VCD_CODEC_XVID))
vidc_sm_set_mpeg4_profile_override(
&ddl->shared_mem[ddl->command_channel],
VIDC_SM_PROFILE_INFO_ASP);
if (VCD_CODEC_H264 == decoder->codec.codec)
vidc_sm_set_decoder_sei_enable(
&ddl->shared_mem[ddl->command_channel],
VIDC_SM_RECOVERY_POINT_SEI);
ddl_context->vidc_decode_seq_start[ddl->command_channel](
&seq_start_param);
}
void ddl_vidc_decode_dynamic_property(struct ddl_client_context *ddl,
u32 enable)
{
struct ddl_decoder_data *decoder = &(ddl->codec_data.decoder);
struct vcd_frame_data *bit_stream =
&(ddl->input_frame.vcd_frm);
struct ddl_context *ddl_context = ddl->ddl_context;
if (!enable) {
if (decoder->dynmic_prop_change_req)
decoder->dynmic_prop_change_req = false;
return;
}
if ((decoder->dynamic_prop_change & DDL_DEC_REQ_OUTPUT_FLUSH)) {
decoder->dynmic_prop_change_req = true;
decoder->dynamic_prop_change &= ~(DDL_DEC_REQ_OUTPUT_FLUSH);
decoder->dpb_mask.hw_mask = 0;
decoder->flush_pending = true;
}
if (((decoder->meta_data_enable_flag & VCD_METADATA_PASSTHROUGH)) &&
((VCD_FRAME_FLAG_EXTRADATA & bit_stream->flags))) {
u32 extradata_presence = true;
u8* tmp = ((u8 *) bit_stream->physical +
bit_stream->offset +
bit_stream->data_len + 3);
u32 extra_data_start = (u32) ((u32)tmp & ~3);
extra_data_start = extra_data_start -
(u32)ddl_context->dram_base_a.align_physical_addr;
decoder->dynmic_prop_change_req = true;
vidc_sm_set_extradata_addr(&ddl->shared_mem
[ddl->command_channel], extra_data_start);
vidc_sm_set_extradata_presence(&ddl->shared_mem
[ddl->command_channel], extradata_presence);
}
}
void ddl_vidc_encode_dynamic_property(struct ddl_client_context *ddl,
u32 enable)
{
struct ddl_encoder_data *encoder = &(ddl->codec_data.encoder);
u32 frame_rate_change = false, bit_rate_change = false;
u32 i_period_change = false, reset_req = false;
if (!enable) {
if (encoder->dynmic_prop_change_req) {
reset_req = true;
encoder->dynmic_prop_change_req = false;
}
} else {
if ((encoder->dynamic_prop_change & DDL_ENC_REQ_IFRAME)) {
encoder->intra_frame_insertion = true;
encoder->dynamic_prop_change &=
~(DDL_ENC_REQ_IFRAME);
}
if ((encoder->dynamic_prop_change &
DDL_ENC_CHANGE_BITRATE)) {
bit_rate_change = true;
vidc_sm_set_encoder_new_bit_rate(
&ddl->shared_mem[ddl->command_channel],
encoder->target_bit_rate.target_bitrate);
encoder->dynamic_prop_change &=
~(DDL_ENC_CHANGE_BITRATE);
}
if ((encoder->dynamic_prop_change
& DDL_ENC_CHANGE_IPERIOD)) {
i_period_change = true;
vidc_sm_set_encoder_new_i_period(
&ddl->shared_mem[ddl->command_channel],
encoder->i_period.p_frames);
encoder->dynamic_prop_change &=
~(DDL_ENC_CHANGE_IPERIOD);
}
if ((encoder->dynamic_prop_change
& DDL_ENC_CHANGE_FRAMERATE)) {
frame_rate_change = true;
vidc_sm_set_encoder_new_frame_rate(
&ddl->shared_mem[ddl->command_channel],
(u32)(DDL_FRAMERATE_SCALE(encoder->\
frame_rate.fps_numerator) /
encoder->frame_rate.fps_denominator));
encoder->dynamic_prop_change &=
~(DDL_ENC_CHANGE_FRAMERATE);
}
}
if ((enable) || (reset_req)) {
vidc_sm_set_encoder_param_change(
&ddl->shared_mem[ddl->command_channel],
bit_rate_change, frame_rate_change,
i_period_change);
}
}
static void ddl_vidc_encode_set_profile_level(
struct ddl_client_context *ddl)
{
struct ddl_encoder_data *encoder = &(ddl->codec_data.encoder);
u32 encode_profile, level = 0;
switch (encoder->profile.profile) {
default:
case VCD_PROFILE_MPEG4_SP:
encode_profile = VIDC_1080P_PROFILE_MPEG4_SIMPLE;
break;
case VCD_PROFILE_MPEG4_ASP:
encode_profile = VIDC_1080P_PROFILE_MPEG4_ADV_SIMPLE;
break;
case VCD_PROFILE_H264_BASELINE:
encode_profile = VIDC_1080P_PROFILE_H264_BASELINE;
break;
case VCD_PROFILE_H264_MAIN:
encode_profile = VIDC_1080P_PROFILE_H264_MAIN;
break;
case VCD_PROFILE_H264_HIGH:
encode_profile = VIDC_1080P_PROFILE_H264_HIGH;
break;
}
switch (encoder->level.level) {
default:
case VCD_LEVEL_MPEG4_0:
level = VIDC_1080P_MPEG4_LEVEL0;
break;
case VCD_LEVEL_MPEG4_0b:
level = VIDC_1080P_MPEG4_LEVEL0b;
break;
case VCD_LEVEL_MPEG4_1:
level = VIDC_1080P_MPEG4_LEVEL1;
break;
case VCD_LEVEL_MPEG4_2:
level = VIDC_1080P_MPEG4_LEVEL2;
break;
case VCD_LEVEL_MPEG4_3:
level = VIDC_1080P_MPEG4_LEVEL3;
break;
case VCD_LEVEL_MPEG4_3b:
level = VIDC_1080P_MPEG4_LEVEL3b;
break;
case VCD_LEVEL_MPEG4_4:
level = VIDC_1080P_MPEG4_LEVEL4;
break;
case VCD_LEVEL_MPEG4_4a:
level = VIDC_1080P_MPEG4_LEVEL4a;
break;
case VCD_LEVEL_MPEG4_5:
level = VIDC_1080P_MPEG4_LEVEL5;
break;
case VCD_LEVEL_MPEG4_6:
level = VIDC_1080P_MPEG4_LEVEL6;
break;
case VCD_LEVEL_MPEG4_7:
level = VIDC_1080P_MPEG4_LEVEL7;
break;
case VCD_LEVEL_H264_1:
level = VIDC_1080P_H264_LEVEL1;
break;
case VCD_LEVEL_H264_1b:
level = VIDC_1080P_H264_LEVEL1b;
break;
case VCD_LEVEL_H264_1p1:
level = VIDC_1080P_H264_LEVEL1p1;
break;
case VCD_LEVEL_H264_1p2:
level = VIDC_1080P_H264_LEVEL1p2;
break;
case VCD_LEVEL_H264_1p3:
level = VIDC_1080P_H264_LEVEL1p3;
break;
case VCD_LEVEL_H264_2:
level = VIDC_1080P_H264_LEVEL2;
break;
case VCD_LEVEL_H264_2p1:
level = VIDC_1080P_H264_LEVEL2p1;
break;
case VCD_LEVEL_H264_2p2:
level = VIDC_1080P_H264_LEVEL2p2;
break;
case VCD_LEVEL_H264_3:
level = VIDC_1080P_H264_LEVEL3;
break;
case VCD_LEVEL_H264_3p1:
level = VIDC_1080P_H264_LEVEL3p1;
break;
case VCD_LEVEL_H264_3p2:
level = VIDC_1080P_H264_LEVEL3p2;
break;
case VCD_LEVEL_H264_4:
level = VIDC_1080P_H264_LEVEL4;
break;
case VCD_LEVEL_H263_10:
level = VIDC_1080P_H263_LEVEL10;
break;
case VCD_LEVEL_H263_20:
level = VIDC_1080P_H263_LEVEL20;
break;
case VCD_LEVEL_H263_30:
level = VIDC_1080P_H263_LEVEL30;
break;
case VCD_LEVEL_H263_40:
level = VIDC_1080P_H263_LEVEL40;
break;
case VCD_LEVEL_H263_45:
level = VIDC_1080P_H263_LEVEL45;
break;
case VCD_LEVEL_H263_50:
level = VIDC_1080P_H263_LEVEL50;
break;
case VCD_LEVEL_H263_60:
level = VIDC_1080P_H263_LEVEL60;
break;
case VCD_LEVEL_H263_70:
level = VIDC_1080P_H263_LEVEL70;
break;
}
vidc_1080p_set_encode_profile_level(encode_profile, level);
}
static void ddl_vidc_encode_set_multi_slice_info(
struct ddl_encoder_data *encoder)
{
enum vidc_1080p_MSlice_selection m_slice_sel;
u32 i_multi_slice_size = 0, i_multi_slice_byte = 0;
if (!encoder) {
DDL_MSG_ERROR("Invalid Parameter");
return;
}
switch (encoder->multi_slice.m_slice_sel) {
default:
case VCD_MSLICE_OFF:
m_slice_sel = VIDC_1080P_MSLICE_DISABLE;
break;
case VCD_MSLICE_BY_GOB:
case VCD_MSLICE_BY_MB_COUNT:
m_slice_sel = VIDC_1080P_MSLICE_BY_MB_COUNT;
i_multi_slice_size = encoder->multi_slice.m_slice_size;
break;
case VCD_MSLICE_BY_BYTE_COUNT:
m_slice_sel = VIDC_1080P_MSLICE_BY_BYTE_COUNT;
i_multi_slice_byte = encoder->multi_slice.m_slice_size;
break;
}
vidc_1080p_set_encode_multi_slice_control(m_slice_sel,
i_multi_slice_size, i_multi_slice_byte);
}
void ddl_vidc_encode_init_codec(struct ddl_client_context *ddl)
{
struct ddl_context *ddl_context = ddl->ddl_context;
struct ddl_encoder_data *encoder = &(ddl->codec_data.encoder);
struct ddl_enc_buffers *enc_buffers = &encoder->hw_bufs;
struct vidc_1080p_enc_seq_start_param seq_start_param;
enum vidc_1080p_memory_access_method mem_access_method;
enum vidc_1080p_DBConfig db_config;
enum VIDC_SM_frame_skip r_cframe_skip =
VIDC_SM_FRAME_SKIP_DISABLE;
u32 index, luma[4], chroma[4], hdr_ext_control = false;
const u32 recon_bufs = 4;
u32 h263_cpfc_enable = false;
u32 scaled_frame_rate;
ddl_vidc_encode_set_profile_level(ddl);
vidc_1080p_set_encode_frame_size(encoder->frame_size.width,
encoder->frame_size.height);
vidc_1080p_encode_set_qp_params(encoder->qp_range.max_qp,
encoder->qp_range.min_qp);
vidc_1080p_encode_set_rc_config(encoder->rc_level.frame_level_rc,
encoder->rc_level.mb_level_rc,
encoder->session_qp.i_frame_qp);
if (encoder->hdr_ext_control > 0)
hdr_ext_control = true;
if (encoder->r_cframe_skip > 0)
r_cframe_skip = VIDC_SM_FRAME_SKIP_ENABLE_LEVEL;
scaled_frame_rate = DDL_FRAMERATE_SCALE(encoder->\
frame_rate.fps_numerator) /
encoder->frame_rate.fps_denominator;
if ((encoder->codec.codec == VCD_CODEC_H263) &&
(DDL_FRAMERATE_SCALE(DDL_INITIAL_FRAME_RATE)
!= scaled_frame_rate))
h263_cpfc_enable = true;
vidc_sm_set_extended_encoder_control(&ddl->shared_mem
[ddl->command_channel], hdr_ext_control,
r_cframe_skip, false, 0,
h263_cpfc_enable, encoder->closed_gop);
vidc_sm_set_encoder_init_rc_value(&ddl->shared_mem
[ddl->command_channel],
encoder->target_bit_rate.target_bitrate);
vidc_sm_set_encoder_hec_period(&ddl->shared_mem
[ddl->command_channel], encoder->hdr_ext_control);
vidc_sm_set_encoder_vop_time(&ddl->shared_mem
[ddl->command_channel], true,
encoder->vop_timing.vop_time_resolution, 0);
if (encoder->rc_level.frame_level_rc)
vidc_1080p_encode_set_frame_level_rc_params(
scaled_frame_rate,
encoder->target_bit_rate.target_bitrate,
encoder->frame_level_rc.reaction_coeff);
if (encoder->rc_level.mb_level_rc)
vidc_1080p_encode_set_mb_level_rc_params(
encoder->adaptive_rc.disable_dark_region_as_flag,
encoder->adaptive_rc.disable_smooth_region_as_flag,
encoder->adaptive_rc.disable_static_region_as_flag,
encoder->adaptive_rc.disable_activity_region_flag);
if ((!encoder->rc_level.frame_level_rc) &&
(!encoder->rc_level.mb_level_rc))
vidc_sm_set_pand_b_frame_qp(
&ddl->shared_mem[ddl->command_channel],
encoder->session_qp.b_frame_qp,
encoder->session_qp.p_frame_qp);
if (encoder->codec.codec == VCD_CODEC_MPEG4) {
vidc_1080p_set_mpeg4_encode_quarter_pel_control(false);
vidc_1080p_set_encode_field_picture_structure(false);
}
if (encoder->codec.codec == VCD_CODEC_H264) {
enum vidc_1080p_entropy_sel entropy_sel;
switch (encoder->entropy_control.entropy_sel) {
default:
case VCD_ENTROPY_SEL_CAVLC:
entropy_sel = VIDC_1080P_ENTROPY_SEL_CAVLC;
break;
case VCD_ENTROPY_SEL_CABAC:
entropy_sel = VIDC_1080P_ENTROPY_SEL_CABAC;
break;
}
vidc_1080p_set_h264_encode_entropy(entropy_sel);
switch (encoder->db_control.db_config) {
default:
case VCD_DB_ALL_BLOCKING_BOUNDARY:
db_config = VIDC_1080P_DB_ALL_BLOCKING_BOUNDARY;
break;
case VCD_DB_DISABLE:
db_config = VIDC_1080P_DB_DISABLE;
break;
case VCD_DB_SKIP_SLICE_BOUNDARY:
db_config = VIDC_1080P_DB_SKIP_SLICE_BOUNDARY;
break;
}
vidc_1080p_set_h264_encode_loop_filter(db_config,
encoder->db_control.slice_alpha_offset,
encoder->db_control.slice_beta_offset);
vidc_1080p_set_h264_encoder_p_frame_ref_count(encoder->\
num_references_for_p_frame);
if (encoder->profile.profile == VCD_PROFILE_H264_HIGH)
vidc_1080p_set_h264_encode_8x8transform_control(true);
}
vidc_1080p_set_encode_picture(encoder->i_period.p_frames,
encoder->i_period.b_frames);
vidc_1080p_set_encode_circular_intra_refresh(
encoder->intra_refresh.cir_mb_number);
ddl_vidc_encode_set_multi_slice_info(encoder);
ddl_vidc_metadata_enable(ddl);
if (encoder->meta_data_enable_flag)
vidc_sm_set_metadata_start_address(&ddl->shared_mem
[ddl->command_channel], DDL_ADDR_OFFSET(
ddl_context->dram_base_a,
ddl->codec_data.encoder.meta_data_input));
luma[0] = DDL_ADDR_OFFSET(ddl_context->dram_base_a,
enc_buffers->dpb_y[0]);
luma[1] = DDL_ADDR_OFFSET(ddl_context->dram_base_a,
enc_buffers->dpb_y[1]);
if (encoder->hw_bufs.dpb_count == DDL_ENC_MAX_DPB_BUFFERS) {
luma[2] = DDL_ADDR_OFFSET(ddl_context->dram_base_b,
enc_buffers->dpb_y[2]);
luma[3] = DDL_ADDR_OFFSET(ddl_context->dram_base_b,
enc_buffers->dpb_y[3]);
}
for (index = 0; index < recon_bufs; index++)
chroma[index] = DDL_ADDR_OFFSET(ddl_context->dram_base_b,
enc_buffers->dpb_c[index]);
vidc_1080p_set_encode_recon_buffers(recon_bufs, luma, chroma);
switch (encoder->codec.codec) {
case VCD_CODEC_MPEG4:
vidc_1080p_set_mpeg4_encode_work_buffers(
DDL_ADDR_OFFSET(ddl_context->dram_base_a,
enc_buffers->col_zero),
DDL_ADDR_OFFSET(ddl_context->dram_base_a,
enc_buffers->acdc_coef),
DDL_ADDR_OFFSET(ddl_context->dram_base_a,
enc_buffers->mv));
break;
case VCD_CODEC_H263:
vidc_1080p_set_h263_encode_work_buffers(
DDL_ADDR_OFFSET(ddl_context->dram_base_a,
enc_buffers->mv),
DDL_ADDR_OFFSET(ddl_context->dram_base_a,
enc_buffers->acdc_coef));
break;
case VCD_CODEC_H264:
vidc_1080p_set_h264_encode_work_buffers(
DDL_ADDR_OFFSET(ddl_context->dram_base_a,
enc_buffers->mv),
DDL_ADDR_OFFSET(ddl_context->dram_base_a,
enc_buffers->col_zero),
DDL_ADDR_OFFSET(ddl_context->dram_base_a,
enc_buffers->md),
DDL_ADDR_OFFSET(ddl_context->dram_base_b,
enc_buffers->pred),
DDL_ADDR_OFFSET(ddl_context->dram_base_a,
enc_buffers->nbor_info),
DDL_ADDR_OFFSET(ddl_context->dram_base_a,
enc_buffers->mb_info));
break;
default:
break;
}
if (encoder->buf_format.buffer_format ==
VCD_BUFFER_FORMAT_NV12_16M2KA)
mem_access_method = VIDC_1080P_TILE_LINEAR;
else
mem_access_method = VIDC_1080P_TILE_64x32;
vidc_1080p_set_encode_input_frame_format(mem_access_method);
vidc_1080p_set_encode_padding_control(0, 0, 0, 0);
DDL_MSG_LOW("ddl_state_transition: %s ~~>"
"DDL_CLIENT_WAIT_FOR_INITCODECDONE",
ddl_get_state_string(ddl->client_state));
ddl->client_state = DDL_CLIENT_WAIT_FOR_INITCODECDONE;
ddl->cmd_state = DDL_CMD_INIT_CODEC;
vidc_1080p_set_encode_field_picture_structure(false);
seq_start_param.cmd_seq_num = ++ddl_context->cmd_seq_num;
seq_start_param.inst_id = ddl->instance_id;
seq_start_param.shared_mem_addr_offset = DDL_ADDR_OFFSET(
ddl_context->dram_base_a, ddl->shared_mem
[ddl->command_channel]);
seq_start_param.stream_buffer_addr_offset = DDL_ADDR_OFFSET(
ddl_context->dram_base_a, encoder->seq_header);
seq_start_param.stream_buffer_size =
encoder->seq_header.buffer_size;
encoder->seq_header_length = 0;
ddl_context->vidc_encode_seq_start[ddl->command_channel](
&seq_start_param);
}
void ddl_vidc_channel_end(struct ddl_client_context *ddl)
{
DDL_MSG_LOW("ddl_state_transition: %s ~~> DDL_CLIENT_WAIT_FOR_CHEND",
ddl_get_state_string(ddl->client_state));
ddl->client_state = DDL_CLIENT_WAIT_FOR_CHEND;
ddl->cmd_state = DDL_CMD_CHANNEL_END;
vidc_1080p_set_host2risc_cmd(VIDC_1080P_HOST2RISC_CMD_CLOSE_CH,
ddl->instance_id, 0, 0, 0);
}
void ddl_vidc_encode_frame_run(struct ddl_client_context *ddl)
{
struct vidc_1080p_enc_frame_start_param enc_param;
struct ddl_context *ddl_context = ddl->ddl_context;
struct ddl_encoder_data *encoder = &(ddl->codec_data.encoder);
struct ddl_enc_buffers *enc_buffers = &(encoder->hw_bufs);
struct vcd_frame_data *stream = &(ddl->output_frame.vcd_frm);
struct vcd_frame_data *input_vcd_frm =
&(ddl->input_frame.vcd_frm);
u32 dpb_addr_y[4], dpb_addr_c[4];
u32 index, y_addr, c_addr;
ddl_vidc_encode_set_metadata_output_buf(ddl);
encoder->enc_frame_info.meta_data_exists = false;
y_addr = DDL_OFFSET(ddl_context->dram_base_b.align_physical_addr,
input_vcd_frm->physical);
c_addr = (y_addr + encoder->input_buf_size.size_y);
if (input_vcd_frm->flags & VCD_FRAME_FLAG_EOS) {
enc_param.encode = VIDC_1080P_ENC_TYPE_LAST_FRAME_DATA;
DDL_MSG_LOW("ddl_state_transition: %s ~~>"
"DDL_CLIENT_WAIT_FOR_EOS_DONE",
ddl_get_state_string(ddl->client_state));
ddl->client_state = DDL_CLIENT_WAIT_FOR_EOS_DONE;
} else {
enc_param.encode = VIDC_1080P_ENC_TYPE_FRAME_DATA;
DDL_MSG_LOW("ddl_state_transition: %s ~~>"
"DDL_CLIENT_WAIT_FOR_FRAME_DONE",
ddl_get_state_string(ddl->client_state));
ddl->client_state = DDL_CLIENT_WAIT_FOR_FRAME_DONE;
}
ddl->cmd_state = DDL_CMD_ENCODE_FRAME;
if (encoder->dynamic_prop_change) {
encoder->dynmic_prop_change_req = true;
ddl_vidc_encode_dynamic_property(ddl, true);
}
vidc_1080p_set_encode_circular_intra_refresh(
encoder->intra_refresh.cir_mb_number);
ddl_vidc_encode_set_multi_slice_info(encoder);
enc_param.cmd_seq_num = ++ddl_context->cmd_seq_num;
enc_param.inst_id = ddl->instance_id;
enc_param.shared_mem_addr_offset = DDL_ADDR_OFFSET(
ddl_context->dram_base_a,
ddl->shared_mem[ddl->command_channel]);
enc_param.current_y_addr_offset = y_addr;
enc_param.current_c_addr_offset = c_addr;
enc_param.stream_buffer_addr_offset = DDL_OFFSET(
ddl_context->dram_base_a.align_physical_addr, stream->physical);
enc_param.stream_buffer_size =
encoder->client_output_buf_req.sz;
enc_param.intra_frame = encoder->intra_frame_insertion;
if (encoder->intra_frame_insertion)
encoder->intra_frame_insertion = false;
enc_param.input_flush = false;
vidc_sm_set_encoder_vop_time(
&ddl->shared_mem[ddl->command_channel], true,
encoder->vop_timing.vop_time_resolution,
ddl->input_frame.frm_delta);
vidc_sm_set_frame_tag(&ddl->shared_mem[ddl->command_channel],
ddl->input_frame.vcd_frm.ip_frm_tag);
if (ddl_context->pix_cache_enable) {
for (index = 0; index < enc_buffers->dpb_count;
index++) {
dpb_addr_y[index] =
(u32) VIDC_1080P_DEC_DPB_RESET_VALUE;
dpb_addr_c[index] = (u32) enc_buffers->dpb_c
[index].align_physical_addr;
}
dpb_addr_y[index] = (u32) input_vcd_frm->physical;
dpb_addr_c[index] = (u32) input_vcd_frm->physical +
encoder->input_buf_size.size_y;
vidc_pix_cache_init_luma_chroma_base_addr(
enc_buffers->dpb_count + 1, dpb_addr_y, dpb_addr_c);
vidc_pix_cache_set_frame_size(encoder->frame_size.width,
encoder->frame_size.height);
vidc_pix_cache_set_frame_range(enc_buffers->sz_dpb_y,
enc_buffers->sz_dpb_c);
vidc_pix_cache_clear_cache_tags();
}
ddl_context->vidc_encode_frame_start[ddl->command_channel] (
&enc_param);
}
u32 ddl_vidc_decode_set_buffers(struct ddl_client_context *ddl)
{
struct ddl_context *ddl_context = ddl->ddl_context;
struct ddl_decoder_data *decoder = &(ddl->codec_data.decoder);
u32 vcd_status = VCD_S_SUCCESS;
struct vidc_1080p_dec_init_buffers_param init_buf_param;
u32 size_y = 0;
u32 size_c = 0;
if (!DDLCLIENT_STATE_IS(ddl, DDL_CLIENT_WAIT_FOR_DPB)) {
DDL_MSG_ERROR("STATE-CRITICAL");
return VCD_ERR_FAIL;
}
ddl_vidc_decode_set_metadata_output(decoder);
if (decoder->dp_buf.no_of_dec_pic_buf <
decoder->client_output_buf_req.actual_count)
return VCD_ERR_BAD_STATE;
if (decoder->codec.codec == VCD_CODEC_H264) {
vidc_sm_set_allocated_h264_mv_size(
&ddl->shared_mem[ddl->command_channel],
decoder->hw_bufs.h264_mv[0].buffer_size);
}
if (vcd_status)
return vcd_status;
#ifdef DDL_BUF_LOG
ddl_list_buffers(ddl);
#endif
if (vidc_msg_timing)
ddl_set_core_start_time(__func__, DEC_OP_TIME);
ddl_decoder_dpb_transact(decoder, NULL, DDL_DPB_OP_INIT);
if (ddl_decoder_dpb_init(ddl) == VCD_ERR_FAIL)
return VCD_ERR_FAIL;
DDL_MSG_LOW("ddl_state_transition: %s ~~> DDL_CLIENT_WAIT_FOR_DPBDONE",
ddl_get_state_string(ddl->client_state));
ddl->client_state = DDL_CLIENT_WAIT_FOR_DPBDONE;
ddl->cmd_state = DDL_CMD_DECODE_SET_DPB;
if (decoder->cont_mode) {
size_y = ddl_get_yuv_buf_size(decoder->client_frame_size.width,
decoder->client_frame_size.height,
DDL_YUV_BUF_TYPE_TILE);
size_c = ddl_get_yuv_buf_size(decoder->client_frame_size.width,
(decoder->client_frame_size.height >> 1),
DDL_YUV_BUF_TYPE_TILE);
vidc_sm_set_allocated_dpb_size(
&ddl->shared_mem[ddl->command_channel],
size_y,
size_c);
} else {
vidc_sm_set_allocated_dpb_size(
&ddl->shared_mem[ddl->command_channel],
decoder->dpb_buf_size.size_y,
decoder->dpb_buf_size.size_c);
}
init_buf_param.cmd_seq_num = ++ddl_context->cmd_seq_num;
init_buf_param.inst_id = ddl->instance_id;
init_buf_param.shared_mem_addr_offset = DDL_ADDR_OFFSET(
ddl_context->dram_base_a, ddl->shared_mem
[ddl->command_channel]);
init_buf_param.dpb_count = decoder->dp_buf.no_of_dec_pic_buf;
init_buf_param.dmx_disable = decoder->dmx_disable;
ddl_context->vidc_decode_init_buffers[ddl->command_channel] (
&init_buf_param);
return VCD_S_SUCCESS;
}
void ddl_vidc_decode_frame_run(struct ddl_client_context *ddl)
{
struct ddl_context *ddl_context = ddl->ddl_context;
struct ddl_decoder_data *decoder = &(ddl->codec_data.decoder);
struct vcd_frame_data *bit_stream =
&(ddl->input_frame.vcd_frm);
struct ddl_dec_buffers *dec_buffers = &decoder->hw_bufs;
struct ddl_mask *dpb_mask = &ddl->codec_data.decoder.dpb_mask;
struct vidc_1080p_dec_frame_start_param dec_param;
u32 dpb_addr_y[32], index;
if (vidc_msg_timing) {
ddl_set_core_start_time(__func__, DEC_OP_TIME);
ddl_set_core_start_time(__func__, DEC_IP_TIME);
}
if ((!bit_stream->data_len) || (!bit_stream->physical)) {
ddl_vidc_decode_eos_run(ddl);
return;
}
DDL_MSG_LOW("ddl_state_transition: %s ~~"
"DDL_CLIENT_WAIT_FOR_FRAME_DONE",
ddl_get_state_string(ddl->client_state));
ddl->client_state = DDL_CLIENT_WAIT_FOR_FRAME_DONE;
ddl_vidc_decode_dynamic_property(ddl, true);
ddl_decoder_dpb_transact(decoder, NULL, DDL_DPB_OP_SET_MASK);
ddl->cmd_state = DDL_CMD_DECODE_FRAME;
dec_param.cmd_seq_num = ++ddl_context->cmd_seq_num;
dec_param.inst_id = ddl->instance_id;
dec_param.shared_mem_addr_offset = DDL_ADDR_OFFSET(
ddl_context->dram_base_a, ddl->shared_mem
[ddl->command_channel]);
dec_param.stream_buffer_addr_offset = DDL_OFFSET(
ddl_context->dram_base_a.align_physical_addr,
bit_stream->physical);
dec_param.stream_frame_size = bit_stream->data_len;
dec_param.stream_buffersize = decoder->client_input_buf_req.sz;
dec_param.descriptor_buffer_addr_offset = DDL_ADDR_OFFSET(
ddl_context->dram_base_a, dec_buffers->desc);
dec_param.descriptor_buffer_size = dec_buffers->desc.buffer_size;
dec_param.release_dpb_bit_mask = dpb_mask->hw_mask;
dec_param.decode = VIDC_1080P_DEC_TYPE_FRAME_DATA;
dec_param.dpb_count = decoder->dp_buf.no_of_dec_pic_buf;
dec_param.dmx_disable = decoder->dmx_disable;
if (decoder->dmx_disable)
ddl_fill_dec_desc_buffer(ddl);
if (decoder->flush_pending) {
dec_param.dpb_flush = true;
decoder->flush_pending = false;
} else
dec_param.dpb_flush = false;
vidc_sm_set_frame_tag(&ddl->shared_mem[ddl->command_channel],
bit_stream->ip_frm_tag);
if (ddl_context->pix_cache_enable) {
for (index = 0; index <
decoder->dp_buf.no_of_dec_pic_buf; index++) {
dpb_addr_y[index] = (u32)
decoder->dp_buf.dec_pic_buffers
[index].vcd_frm.physical;
}
vidc_pix_cache_init_luma_chroma_base_addr(
decoder->dp_buf.no_of_dec_pic_buf,
dpb_addr_y, NULL);
vidc_pix_cache_set_frame_range(decoder->dpb_buf_size.size_y,
decoder->dpb_buf_size.size_c);
vidc_pix_cache_clear_cache_tags();
}
ddl_context->vidc_decode_frame_start[ddl->command_channel] (
&dec_param);
}
void ddl_vidc_decode_eos_run(struct ddl_client_context *ddl)
{
struct ddl_context *ddl_context = ddl->ddl_context;
struct ddl_decoder_data *decoder = &(ddl->codec_data.decoder);
struct vcd_frame_data *bit_stream =
&(ddl->input_frame.vcd_frm);
struct ddl_dec_buffers *dec_buffers = &(decoder->hw_bufs);
struct ddl_mask *dpb_mask =
&(ddl->codec_data.decoder.dpb_mask);
struct vidc_1080p_dec_frame_start_param dec_param;
DDL_MSG_LOW("ddl_state_transition: %s ~~> DDL_CLIENT_WAIT_FOR_EOS_DONE",
ddl_get_state_string(ddl->client_state));
ddl->client_state = DDL_CLIENT_WAIT_FOR_EOS_DONE;
if (decoder->output_order == VCD_DEC_ORDER_DECODE)
decoder->dynamic_prop_change |= DDL_DEC_REQ_OUTPUT_FLUSH;
ddl_vidc_decode_dynamic_property(ddl, true);
ddl_decoder_dpb_transact(decoder, NULL, DDL_DPB_OP_SET_MASK);
decoder->dynmic_prop_change_req = true;
ddl->cmd_state = DDL_CMD_EOS;
memset(&dec_param, 0, sizeof(dec_param));
dec_param.cmd_seq_num = ++ddl_context->cmd_seq_num;
dec_param.inst_id = ddl->instance_id;
dec_param.shared_mem_addr_offset = DDL_ADDR_OFFSET(
ddl_context->dram_base_a,
ddl->shared_mem[ddl->command_channel]);
dec_param.descriptor_buffer_addr_offset = DDL_ADDR_OFFSET(
ddl_context->dram_base_a, dec_buffers->desc);
dec_param.descriptor_buffer_size = dec_buffers->desc.buffer_size;
dec_param.release_dpb_bit_mask = dpb_mask->hw_mask;
dec_param.decode = VIDC_1080P_DEC_TYPE_LAST_FRAME_DATA;
dec_param.dpb_count = decoder->dp_buf.no_of_dec_pic_buf;
if (decoder->flush_pending) {
dec_param.dpb_flush = true;
decoder->flush_pending = false;
} else
dec_param.dpb_flush = false;
vidc_sm_set_frame_tag(&ddl->shared_mem[ddl->command_channel],
bit_stream->ip_frm_tag);
ddl_context->vidc_decode_frame_start[ddl->command_channel] (
&dec_param);
}