您的位置:首页 > 编程语言

s3c6410使用MFC-API进行MPEG-4格式解码及LCD播放代码注释

2012-07-14 21:38 573 查看
#include <stdio.h>

#include <stdlib.h>

#include <sys/types.h>

#include <sys/stat.h>

#include <sys/ioctl.h>

#include <fcntl.h>

#include <ctype.h>

#include <unistd.h>

#include <sys/mman.h>

#include <string.h>

#include <errno.h>

#include <linux/vt.h>

#include <linux/fb.h>

#include <pthread.h>

#include "s3c_pp.h"

#include "SsbSipH264Decode.h"

#include "SsbSipMpeg4Decode.h"

#include "FrameExtractor.h"

#include "MPEG4Frames.h"

#include "LogMsg.h"

#include "performance.h"

#include "lcd.h"

#include "MfcDriver.h"

#include "FileRead.h"

#define PP_DEV_NAME "/dev/s3c-pp"

#define FB_DEV_NAME "dev/fb0"

#define INPUT_BUFFER_SIZE (204800)

#define FB0_WIDTH 480

#define FB0_HEIGHT 272

#define FB0_BPP 16

#define FB0_COLOR_SPACE RGB16

static unsigned char delimiter_mpeg4[3] = {0x00,0x00,0x01};//MPEG4解码需要用到的数组

int MPEG4_display(char in_file[20])

{

int file_size;//保存输入文件大小

struct stat s;//保存文件信息内容

int in_fd;//输入文件的文件描述符

int pp_fd;//post processor文件描述符

int fb_fd;//帧缓冲文件描述符

unsigned char* in_addr;//帧起始地址

FRAMEX_CTX *pFrameExCtx;//帧抽取上下文

FRAMEX_STRM_PTR file_strm;//类型FRAMEX_STRM_PTR保存文件映射到内存的首地址/结束地址/当前地址等内容。

void *handle,*pStrmBuf;

SSBSIP_H264_STREAM_INFO stream_info;//类型SSBSIP_H264_STREAM_INFO保存视频信息

s3c_pp_params_t pp_param;//s3c_pp_params_t结构体类型是用来专门对pp进行配置的。在s3c_pp.h里面声明。

int fb_size;//帧缓冲大小

unsigned char *fb_addr;//帧缓冲地址

s3c_win_info_t osd_info_to_driver;//显示到LCD上分屏的信息

struct fb_fix_screeninfo lcd_info;

unsigned int pYUVBuf[2];//保存YUV格式的内容

int nFrameLeng = 0;

in_fd = open(in_file,O_RDONLY);

if(in_fd < 0)

{

printf("Input file open failed.\n");

return -1;

}

fstat(in_fd,&s);//将文件内容保存到strcut stat s中。

file_size = s.st_size;//获得文件大小

in_addr = (char*)mmap(0,file_size,PROT_READ,MAP_SHARED,in_fd,0);

if(in_addr == NULL)

{

printf("Input file memory mapping failed.\n");

return -1;

}

pp_fd = open(PP_DEV_NAME,O_RDWR);

if(pp_fd<0)

{

printf("Post processor open error.\n");

return -1;

}

fb_fd = open(FB_DEV_NAME,O_RDWR|O_NDELAY);//LCD frame buffer open。打开LCD的帧缓冲

if(fb_fd<0)

{

printf("LCD frame buffer open error.\n");

return -1;

}

pFrameExCtx = FrameExtractorInit(FRAMEX_IN_TYPE_MEM,delimiter_mpeg4,sizeof(delimiter_mpeg4),1);

file_strm.p_start = file_strm.p_cur = in_addr;

file_strm.p_end = (unsigned char*)(in_addr+file_size);

FrameExtractorFirst(pFrameExCtx,&file_strm);//抽取第一帧

handle = SsbSipMPEG4DecodeInit();

if(handle == NULL)

{

printf("MPEG4 decode init failed.\n");

return -1;

}

pStrmBuf = SsbSipMPEG4DecodeGetInBuf(handle,nFrameLeng);

if(pStrmBuf == NULL)

{

printf("SsbSipMPEG4DecodeGetInBuf Failed.\n");

SsbSipMPEG4DecodeDeInit(handle);

return -1;

}

nFrameLeng = ExtractConfigStreamMpeg4(pFrameExCtx,&file_strm,pStrmBuf,INPUT_BUFFER_SIZE,NULL);

if(SsbSipMPEG4DecodeExe(handle,nFrameLeng)!= SSBSIP_MPEG4_DEC_RET_OK)

{

printf("MPEG-4 Decoder Configuration Failed.\n");

return -1;

}

SsbSipMPEG4DecodeGetConfig(handle,MPEG4_DEC_GETCONF_STREAMINFO,&stream_info);

memset(&pp_param,0,sizeof(s3c_pp_params_t));

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;

pp_param.dst_full_width = FB0_WIDTH;

pp_param.dst_full_height = FB0_HEIGHT;

pp_param.dst_start_x = 0;

pp_param.dst_start_y = 0;

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;

pp_param.out_path = DMA_ONESHOT;

ioctl(pp_fd,S3C_PP_SET_PARAMS,&pp_param);

fb_size = pp_param.dst_full_width*pp_param.dst_full_height*2;//RGB565。红色R用5位表示,绿色G用6位表示,蓝色B用5为表示,总共16位共2字节,故乘以2

fb_addr = (char*)mmap(0,fb_size,PROT_READ|PROT_WRITE,MAP_SHARED,fb_fd,0);//获得帧缓冲的首地址

if(fb_addr == NULL)

{

printf("LCD frame buffer mmap failed.\n");

return -1;

}

osd_info_to_driver.Bpp = FB0_BPP;

osd_info_to_driver.LeftTop_x = 0;

osd_info_to_driver.LeftTop_y = 0;

osd_info_to_driver.Width = FB0_WIDTH;

osd_info_to_driver.Height = FB0_HEIGHT;

//设置OSD信息(OSD=On Screen Display)

if(ioctl(fb_fd,SET_OSD_INFO,&osd_info_to_driver))

{

printf("Some problem with the ioctl SET_OSD_INFO.\n");

return -1;

}

ioctl(fb_fd,SET_OSD_START);

printf("\nMy MPEG-4 Display Info\n");

printf("Input filename : %s\n",in_file);

while(1)

{

if(SsbSipMPEG4DecodeExe(handle,nFrameLeng)!= SSBSIP_MPEG4_DEC_RET_OK)

break;

SsbSipMPEG4DecodeGetConfig(handle,MPEG4_DEC_GETCONF_PHYADDR_FRAM_BUF,pYUVBuf);

nFrameLeng = NextFrameMpeg4(pFrameExCtx,&file_strm,pStrmBuf,INPUT_BUFFER_SIZE,NULL);

if(nFrameLeng<4)

break;

pp_param.src_buf_addr_phy = pYUVBuf[0];//MFC输出的缓冲

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);

}

ioctl(fb_fd,SET_OSD_STOP);

SsbSipMPEG4DecodeDeInit(handle);

munmap(in_addr,file_size);

munmap(fb_addr,fb_size);

close(pp_fd);

close(fb_fd);

close(in_fd);

return 0;

}

int main(int argc,char **argv)

{

if(argc<1)

{

printf("Please input video file.\n");

return -1;

}

if(MPEG4_display(argv[1]))

{

printf("MPEG4_display error.\n");

}

return 0;

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐