S3C6410 MFC decode H.264流程

来源:互联网 发布:重庆sem优化 编辑:程序博客网 时间:2024/05/01 01:01

  自己的MID平台播放视频支持的格式有限,按照应用要求需要扩展更多的格式。6410自己是带MFC(multi format codec),支持MPEG4,H263,H264的硬解码。通过ls -l /dev可以得知s3c-mfc的驱动模块已经加载了,在android中操纵MFC的编解码部分是在external/opencore/codecs_v2/video/s3c_mfc目录下,发出IO控制。在SD卡中拷贝了.mp4视频文件,的确可以播放,下面跟踪下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

 

 

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;

 

今天用三星的测试程序跑了一下H.264,发现颜色正常,打印出的信息有所不同。
covia android解码时的ioctrl命令为
s3c_mfc_ioctl: cmd = 800007
s3c_mfc_ioctl: cmd = 800011

测试程序解码为
s3c_mfc_ioctl: cmd = 800007
s3c_mfc_ioctl: cmd = 800013

前面分析过s3c_mfc_ioctl: cmd = 800011是将YUV数据返回用户
而s3c_mfc_ioctl: cmd = 800013和前者不一样的地方在于:
1)databuf_paddr = (unsigned int)S3C_MFC_BASEADDR_DATA_BUF;
//直接用寄存器(Physical Base Address for the MFC Data Buffer )地址填充
2)args.get_buf_addr.out_buf_addr = databuf_paddr + offset;
//输出地址用paddr填充,databuf_paddr

分析:
MFC转换出的数据格式是YUV的。
三星的测试程序使用了Post Processor驱动,800013命令返回物理地址给pp使用,直接刷到fb上。
推测covia的驱动可能没有使用pp,而是手动做的YUV2RGB再刷到fb,仅仅是推测,因为q5的内核也含有pp驱动。


附录:一些代码及调试信息
case S3C_MFC_IOCTL_MFC_GET_PHY_FRAM_BUF_ADDR:
   mutex_lock(s3c_mfc_mutex);

   out = copy_from_user(&args.get_buf_addr,
    (s3c_mfc_get_buf_addr_arg_t *)arg,
    sizeof(s3c_mfc_get_buf_addr_arg_t));

   yuv_size = (pMfcInst->buf_width * pMfcInst->buf_height * 3) >> 1;
   args.get_buf_addr.out_buf_size = yuv_size;
   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();
   databuf_paddr = (unsigned int)S3C_MFC_BASEADDR_DATA_BUF;
   offset = yuv_buffer + run_index * out_buf_size - databuf_vaddr;  
  
   args.get_buf_addr.out_buf_addr = databuf_paddr + offset;
   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));

   mutex_unlock(s3c_mfc_mutex);
   break;


========= S3C6400/6410 Demo Application ==========
=                                                =
= 1.   H.264 display                            =
= 2.   MPEG4 display                            =
= 3.   H.263 display                            =
= 4.   VC-1 display                            =
= 5.   4-windows display                        =
= 6.   Display using local path                 =
= 7.   Display using double buffering           =
= 8.   Camera preview & MFC encoding            =
= 9.   MFC decoding & Camera preview            =
= 10. Camera preview & MFC encoding/decoding   =
= 11. Camera input and JPEG encoding           =
= 12. JPEG decoding and display                =
= 13. Exit                                     =
=                                                =
==================================================
Select number --> 1
s3c_mfc_yuv_buffer_mgr_final
address of segment_info=c141c400, address of commit_info =c1426040
s3c_mfc_init_hw: downloading firmware into bitprocessor
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
s3c_mfc_get_stream_buffer_addr: ctx->stream_buffer address 0xc0f46000
s3c_mfc_get_stream_buffer_addr: ctx->phys_addr_stream_buffer address 0x50f46000
s3c_mfc_inst_create: state = 10
s3c_mfc_open: mfc open success
s3c_mfc_ioctl: cmd = 80000f
s3c_mfc_ioctl: cmd = 800005
s3c_mfc_inst_init_dec: strm_leng = 7956
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 = 327920
s3c_mfc_inst_init_dec: RET_DEC_SEQ_SRC_FRAME_RATE   = 0
s3c_mfc_inst_init_dec: RET_DEC_SEQ_FRAME_NEED_COUNT = 4
s3c_mfc_inst_init_dec: RET_DEC_SEQ_FRAME_DELAY = 0
s3c_mfc_inst_init_dec: width = 320, height = 240, buf_width = 320, buf_height = 240
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 = 509
s3c_mfc_get_yuv_buffer_addr: ctx->inst_no : 0
s3c_mfc_get_yuv_buffer_addr: ctx->yuv_buffer : 0xc1040000
s3c_mfc_get_yuv_buffer_addr: ctx->phys_addr_yuv_buffer : 0x51040000
s3c_mfc_ioctl: cmd = 800007
        ########<STREAMINFO> width=320   height=240.
s3c_mfc_ioctl: cmd = 800013
s3c_mfc_ioctl: cmd = 800007
s3c_mfc_ioctl: cmd = 800013
s3c_mfc_ioctl: cmd = 800007
s3c_mfc_ioctl: cmd = 800013
s3c_mfc_ioctl: cmd = 800007
s3c_mfc_ioctl: cmd = 800013
s3c_mfc_ioctl: cmd = 800007
s3c_mfc_ioctl: cmd = 800013

 

 

梳理了一下Android硬解的流程,还是有很多不清楚,比如eclair里出现的gralloc。

 

 

 


Test_Display_H264()
{
// file open
in_fd = open(H264_INPUT_FILE, O_RDONLY);

// get input file size
fstat(in_fd, &s);
file_size = s.st_size;

// mapping input file to memory
in_addr = (char *)mmap(0, file_size, PROT_READ, MAP_SHARED, in_fd, 0);

// Post processor open
pp_fd = open(PP_DEV_NAME, O_RDWR);

// LCD frame buffer open
fb_fd = open(FB_DEV_NAME, O_RDWR|O_NDELAY);

//////////////////////////////////////////////
// FrameExtractor Initialization 帧解压初始化//
//////////////////////////////////////////////
pFrameExCtx = FrameExtractorInit(FRAMEX_IN_TYPE_MEM, delimiter_h264, sizeof(delimiter_h264), 1);  
file_strm.p_start = file_strm.p_cur = (unsigned char *)in_addr;
file_strm.p_end = (unsigned char *)(in_addr + file_size);
FrameExtractorFirst(pFrameExCtx, &file_strm);

//////////////////////////////////////
///    1. Create new instance      ///
///      (SsbSipH264DecodeInit)    ///
//////////////////////////////////////
handle = SsbSipH264DecodeInit();

    //////////////////////////////
    /////     1.1 CreateFile     /////
    //////////////////////////////
    hOpen = open(MFC_DEV_NAME, O_RDWR|O_NDELAY);
   
    //////////////////////////////////////////
    // 1.2 Mapping the MFC Input/Output Buffer //
    //////////////////////////////////////////
    // mapping shared in/out buffer between application and MFC device driver
    addr = (unsigned char *) mmap(0, BUF_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, hOpen, 0);
    pCTX = (_MFCLIB_H264_DEC *) malloc(sizeof(_MFCLIB_H264_DEC));
   
   
/////////////////////////////////////////////
///    2. Obtaining the Input Buffer      ///
///      (SsbSipH264DecodeGetInBuf)        ///
/////////////////////////////////////////////
pStrmBuf = SsbSipH264DecodeGetInBuf(handle, nFrameLeng);

    /////////////////////////////////////////////////
    ///// 2.1    (DeviceIoControl)           /////
    ///// IOCTL_MFC_GET_STRM_BUF_ADDR 0x0080000F   /////
    /////////////////////////////////////////////////
    mfc_args.get_buf_addr.in_usr_data = (int)pCTX->mapped_addr;
    r = ioctl(pCTX->hOpen, IOCTL_MFC_GET_LINE_BUF_ADDR, &mfc_args);

///////////////////////////////////////////////
// 2.2 H264 CONFIG stream extraction 帧解压配置 //
//////////////////////////////////////////////
nFrameLeng = ExtractConfigStreamH264(pFrameExCtx, &file_strm, pStrmBuf, INPUT_BUFFER_SIZE, NULL);


////////////////////////////////////////////////////////////////
///    3. Configuring the instance with the config stream    ///
///       (SsbSipH264DecodeExe)                             ///
////////////////////////////////////////////////////////////////
SsbSipH264DecodeExe(handle, nFrameLeng);
   
    /////////////////////////////////////////////////
    ///// 3.1       (DeviceIoControl)           /////
    ///// IOCTL_MFC_H264_DEC_INIT 0x00800005   /////
    /////////////////////////////////////////////////
    mfc_args.dec_init.in_strmSize = lengthBufFill;
    r = ioctl(pCTX->hOpen, IOCTL_MFC_H264_DEC_INIT, &mfc_args);

/////////////////////////////////////
///   4. Get stream information   ///
/////////////////////////////////////
SsbSipH264DecodeGetConfig(handle, H264_DEC_GETCONF_STREAMINFO, &stream_info);

    //4.1 case H264_DEC_GETCONF_STREAMINFO
    g_stream_info.width      = pCTX->width;
    g_stream_info.height     = pCTX->height;
    g_stream_info.buf_width = pCTX->buf_width;
    g_stream_info.buf_height = pCTX->buf_height;

// set post processor configuration
// Structure type for IOCTL commands S3C_PP_SET_PARAMS, S3C_PP_SET_INPUT_BUF_START_ADDR_PHY,
// S3C_PP_SET_INPUT_BUF_NEXT_START_ADDR_PHY, S3C_PP_SET_OUTPUT_BUF_START_ADDR_PHY.
pp_param.src_full_width     = stream_info.buf_width;
pp_param.src_full_height = stream_info.buf_height;
pp_param.src_start_x   = 0;
pp_param.src_start_y   = 0;
pp_param.src_width    = pp_param.src_full_width;
pp_param.src_height    = pp_param.src_full_height;
pp_param.src_color_space = YC420;    //MFC decode数据为YUV420格式
pp_param.dst_start_x   = 0;
pp_param.dst_start_y   = 0;
pp_param.dst_full_width     = FB0_WIDTH;   // destination width
pp_param.dst_full_height = FB0_HEIGHT;   // destination height
pp_param.dst_width    = pp_param.dst_full_width;
pp_param.dst_height    = pp_param.dst_full_height;
pp_param.dst_color_space = FB0_COLOR_SPACE; // RGB565
pp_param.out_path           = DMA_ONESHOT;

ioctl(pp_fd, S3C_PP_SET_PARAMS, &pp_param);

// get LCD frame buffer address
fb_size = pp_param.dst_full_width * pp_param.dst_full_height * 2; // RGB565
fb_addr = (char *)mmap(0, fb_size, PROT_READ | PROT_WRITE, MAP_SHARED, fb_fd, 0);

//循环解压每一帧,直到播放完毕
while(1)
{

   //////////////////////////////////
   ///       5. DECODE            ///
   ///    (SsbSipH264DecodeExe)   ///
   //////////////////////////////////
   if (SsbSipH264DecodeExe(handle, nFrameLeng) != SSBSIP_H264_DEC_RET_OK)
    break;
     /////////////////////////////////////////////////
     ///// 5.1      (DeviceIoControl)           /////
     ///// IOCTL_MFC_H264_DEC_EXE   0x00800007 /////
     /////////////////////////////////////////////////
     mfc_args.dec_exe.in_strmSize = lengthBufFill;
     r = ioctl(pCTX->hOpen, IOCTL_MFC_H264_DEC_EXE, &mfc_args);

   //////////////////////////////////////////////
   ///    6. Obtaining the Output Buffer      ///
   ///      (SsbSipH264DecodeGetOutBuf)       ///
   //////////////////////////////////////////////
   SsbSipH264DecodeGetConfig(handle, H264_DEC_GETCONF_PHYADDR_FRAM_BUF, pYUVBuf);
  
     //6.1 IOCTL_MFC_GET_PHY_FRAM_BUF_ADDR 0x00800013
     //获取物理地址给pp使用
     case H264_DEC_GETCONF_PHYADDR_FRAM_BUF:
     r = ioctl(pCTX->hOpen, IOCTL_MFC_GET_PHY_FRAM_BUF_ADDR, &mfc_args);


   ///////////////////////////////////////
   // Next H.264 VIDEO stream 获取下一帧//
   //////////////////////////////////////
   nFrameLeng = NextFrameH264(pFrameExCtx, &file_strm, pStrmBuf, INPUT_BUFFER_SIZE, NULL);
   if (nFrameLeng < 4) //循环结束条件
    break;

   // Post processing
   // pp_param.SrcFrmSt MFC output buffer physical address
   // pp_param.DstFrmSt LCD frame buffer physical address.
   pp_param.src_buf_addr_phy   = pYUVBuf[0]; // MFC output buffer
   ioctl(pp_fd, S3C_PP_SET_SRC_BUF_ADDR_PHY, &pp_param);

   ioctl(fb_fd, FBIOGET_FSCREENINFO, &lcd_info);
   pp_param.dst_buf_addr_phy   = lcd_info.smem_start;    // LCD frame buffer
   ioctl(pp_fd, S3C_PP_SET_DST_BUF_ADDR_PHY, &pp_param);
   ioctl(pp_fd, S3C_PP_START); //pp参数设置完毕,启动pp
}

SsbSipH264DecodeDeInit(handle);
munmap(in_addr, file_size);
munmap(fb_addr, fb_size);
close(pp_fd);
close(fb_fd);
close(in_fd);

return 0;
}

question:为什么android没有使用pp?

 

 

原创粉丝点击