S3C6410 MFC decode H.264流程(续)
cmd = 800007,S3C_MFC_IOCTL_MFC_H264_DEC_EXE
s3c_mfc_inst_dec 对数据进行decode
s3c_mfc_inst_dec函数分析
简介: this function decodes the input stream and put the decoded frame into the yuv buffer
输入参数
s3c_mfc_inst_context_t *ctx 结构体包含instance number,stream buffer和yuv buffer
unsigned long strm_leng stream长度
1) checking state(忽略所有涉及到旋转的代码)
2)大部分情况下,根据inst_no选择对应的MFC物理端口(8个)
3)计算size:frm_size = ctx->buf_width * ctx->buf_height;
4)
/* DEC_PIC_OPTION was newly added for MP4ASP */
writel(0x7, s3c_mfc_sfr_base_virt_addr + S3C_MFC_PARAM_DEC_PIC_OPTION);
writel(ctx->mv_mbyte_addr, s3c_mfc_sfr_base_virt_addr + S3C_MFC_PARAM_DEC_PIC_MV_ADDR);
writel(ctx->mv_mbyte_addr + 25920, s3c_mfc_sfr_base_virt_addr + S3C_MFC_PARAM_DEC_PIC_MBTYPE_ADDR);
这段代码中的寄存器我的数据手册里面竟然没有,看来应该更新了
5)将stream物理地址写入CMD_DEC_PIC_BB_START (0x1AC)
需要4byte对齐
4-byte aligned byte address of the decoder input picture stream buffer
6)不对齐的数据写入CMD_DEC_PIC_START_BYTE (0x1B0)
Byte Address of valid bitstream in input picture stream buffer
7)将stream length写入CMD_DEC_PIC_CHUNK_SIZE (0x1A8)
Byte size of picture stream data
8)s3c_mfc_issue_command(ctx->inst_no, ctx->codec_mode, PIC_RUN)
启动解码函数
根据S3C_MFC_IOCTL_MFC_H264_DEC_INIT的配置,codec_mode应该为2
将inst_no写入RunIndex (0x168)
将codec_mode = 2写入RunCodStd (0x16C)
将run命令写入RunCommand (0x164),启动解码
挂起interruptible_sleep_on_timeout(&s3c_mfc_wait_queue, 500)
9)读取命令执行结果状态寄存器RET_DEC_PIC_SUCCESS (0x1D8)
10)读取RET_DEC_PIC_IDX (0x1C4)
Display frame index
After BIT decodes one frame, BIT return display frame index to this register.
并判断帧情况,是否结尾,是否失败等等
11)转换inst_no的状态
//* changing state
//* state change to S3C_MFC_INST_STATE_DEC_PIC_RUN_LINE_BUF
S3C_MFC_INST_STATE_TRANSITION(ctx, S3C_MFC_INST_STATE_DEC_PIC_RUN_LINE_BUF);
12)返回OK
===========================================================================
IOCTRL:cmd = 800011,S3C_MFC_IOCTL_MFC_GET_YUV_BUF_ADDR
DEC部分分析,这一段并没有设计到解码,解码主要在上面完成
out = copy_from_user(&args.get_buf_addr,
(s3c_mfc_get_buf_addr_arg_t *)arg,
sizeof(s3c_mfc_get_buf_addr_arg_t));
if (pMfcInst->yuv_buffer == NULL) {
mfc_err("mfc frame buffer is not internally allocated yet\n");
mutex_unlock(s3c_mfc_mutex);
return -EFAULT;
}
/* FRAM_BUF address is calculated differently for Encoder and Decoder. */
switch (pMfcInst->codec_mode) {
case MP4_DEC:
case AVC_DEC:
case VC1_DEC:
case H263_DEC:
/* Decoder case */
yuv_size = (pMfcInst->buf_width * pMfcInst->buf_height * 3) >> 1; //计算YUV的大小
args.get_buf_addr.out_buf_size = yuv_size;//填充out_buf_size尺寸
in_usr_data = (unsigned int)args.get_buf_addr.in_usr_data;
yuv_buffer = (unsigned int)pMfcInst->yuv_buffer;
run_index = pMfcInst->run_index;
out_buf_size = args.get_buf_addr.out_buf_size;
databuf_vaddr = (unsigned int)s3c_mfc_get_databuf_virt_addr();
offset = yuv_buffer + run_index * out_buf_size - databuf_vaddr;//计算偏移量
args.get_buf_addr.out_buf_addr = in_usr_data + offset;//填充out_buf地址
break;
} /* end of switch (codec_mode) */
args.get_buf_addr.ret_code = S3C_MFC_INST_RET_OK;
out = copy_to_user((s3c_mfc_get_buf_addr_arg_t *)arg, &args.get_buf_addr, sizeof(s3c_mfc_get_buf_addr_arg_t));
break;