郁闷的,用MFC放出来的H.264视屏竟然是黑白的,无奈跟踪下MFC的调用流程:
内核启动初始化:
1)执行s3c_mfc_init(),打印“S3C6400 MFC Driver, (c) 2007 Samsung Electronics”;
2)注册平台设备platform_driver_register(&s3c_mfc_driver);
3)进入s3c_mfc_probe();
4)获取时钟、打开时钟,映射寄存器物理地址,获取中断、注册中断;
5)调用s3c_get_media_memory(S3C_MDEV_MFC),获取显存空间;
6)调用s3c_mfc_setup_memory(),设置Bitprocessor buffer, Data buffer;
7)调用s3c_mfc_memmap_databuf,打印以下信息“s3c_mfc_memmap_databuf: virtual address of data buffer = 0xc0700000”;
8)调用s3c_mfc_init_yuvbuf_mgr(),This function initializes the MfcFramBufMgr(Buffer Segment Manager);
最后打印“address of segment_info=c0bd6400, address of commit_info =c0be0040”
9)调用s3c_mfc_init_hw(),初始化硬件;
1. Reset the MFC IP
2. Download Firmware code into MFC
输出:“s3c_mfc_init_hw: downloading firmware into bitprocessor”;
3. Start Bit Processor
4. Set the Base Address Registers for the following 3 buffers(CODE_BUF, WORKING_BUF, PARAMETER_BUF)
5. Set the Control Registers
输出:
s3c_mfc_get_firmware_ver: GET_FW_VER command was issued
s3c_mfc_get_firmware_ver: GET_FW_VER => 0xf202, 0x130e
s3c_mfc_get_firmware_ver: BUSY_FLAG => 0
10)最后再次输出banner:S3C6400 MFC Driver, (c) 2007 Samsung Electronics。
H.264 decode时:
0)上层调用s3c_mfc_open();
1)调用s3c_mfc_init_yuvbuf_mgr();
2)调用s3c_mfc_yuv_buffer_mgr_final(),表示不需要重新分配yuv buffer;
3)调用s3c_mfc_init_hw(),重新初始化硬件;
4)调用s3c_mfc_inst_create创建一个实例->s3c_mfc_get_stream_buffer_addr()获取流地址;
输出:
s3c_mfc_get_stream_buffer_addr: ctx->stream_buffer address 0xc0700000
s3c_mfc_get_stream_buffer_addr: ctx->phys_addr_stream_buffer address 0x50700000
s3c_mfc_inst_create: state = 10 /* instance is created but not initialized */
5)输出s3c_mfc_open: mfc open success,open结束。
6)调用s3c_mfc_ioctl,发送命令: cmd = 80000f,S3C_MFC_IOCTL_MFC_GET_LINE_BUF_ADDR
copy_from_user
处理XXXXXX
copy_to_user
7)调用s3c_mfc_ioctl,发送命令: cmd = 800005,S3C_MFC_IOCTL_MFC_H264_DEC_INIT
copy_from_user
codec_mode = AVC_DEC;
Initialize MFC Instance
——>s3c_mfc_inst_init_dec
(1)checking state
(2)codec_mode
(3)stream size checking
(4)判断instance序列号
(5)s3c_mfc_set_eos(0);
(6)s3c_mfc_issue_command();
(7)s3c_mfc_stream_end();
(8)获取视屏参数
(9)s3c_mfc_get_yuv_buffer_addr——>s3c_mfc_print_commit_yuv_buffer_info();
(10)s3c_mfc_get_param_buff_virt_addr();
/*
* set the parameters in the parameters buffer for SET_FRAME_BUF command.
* buffer address of y, cb, cr will be set in parameters buffer before issuing SET_FRAME_BUF command
*/
(11)s3c_mfc_issue_command(ctx->inst_no, ctx->codec_mode, SET_FRAME_BUF);
(12)changing state to 20;
输出信息:
s3c_mfc_inst_init_dec: strm_leng = 7767
s3c_mfc_inst_init_dec: ctx->inst_no = 0
s3c_mfc_inst_init_dec: ctx->codec_mode = 2
s3c_mfc_inst_init_dec: sequece bit buffer size = 500 (kb)
s3c_mfc_inst_init_dec: RET_DEC_SEQ_SRC_SIZE = 737680
s3c_mfc_inst_init_dec: RET_DEC_SEQ_SRC_FRAME_RATE = 0
s3c_mfc_inst_init_dec: RET_DEC_SEQ_FRAME_NEED_COUNT = 3
s3c_mfc_inst_init_dec: RET_DEC_SEQ_FRAME_DELAY = 0
s3c_mfc_inst_init_dec: width = 720, height = 400, buf_width = 720, buf_height = 400
s3c_mfc_print_commit_yuv_buffer_info: commit index = 000, base segment index = 0
s3c_mfc_print_commit_yuv_buffer_info: commit index = 000, number of segment = 1325
s3c_mfc_get_yuv_buffer_addr: ctx->inst_no : 0
s3c_mfc_get_yuv_buffer_addr: ctx->yuv_buffer : 0xc07fa000
s3c_mfc_get_yuv_buffer_addr: ctx->phys_addr_yuv_buffer : 0x507fa000
回到ioctrl
将初始化信息copy_to_user
8)视屏播放过程中,反复调用
s3c_mfc_ioctl: cmd = 800007
s3c_mfc_ioctl: cmd = 800011
9)cmd = 800007,S3C_MFC_IOCTL_MFC_H264_DEC_EXE
copy_from_user从用户态获取数据,sizeof(s3c_mfc_enc_exe_arg_t)
s3c_mfc_inst_dec 对数据进行decode,真正decode函数,此函数需要重点关注
copy_to_user将数据返回用户态
难道直接将YUV数据返回用户?然后用户态再操作Framebuffer???
10)cmd = 800011,S3C_MFC_IOCTL_MFC_GET_YUV_BUF_ADDR
copy_from_user,sizeof(s3c_mfc_enc_exe_arg_t)
yuv_size = (pMfcInst->buf_width * pMfcInst->buf_height * 3) >> 1;
args.get_buf_addr.out_buf_size = yuv_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;
copy_to_user
11)解码完毕,调用s3c_mfc_release释放instance
s3c_mfc_release: deleting instance number = 0
仅仅分析了调用过程,下一步需要研究解码过程这两个操作究竟是干什么的,有什么区别
cmd = 800007,S3C_MFC_IOCTL_MFC_H264_DEC_EXE
cmd = 800011,S3C_MFC_IOCTL_MFC_GET_YUV_BUF_ADDR