最近一直使用s3c21 做jpeg硬解码方面。之前也查了很多资料,在各个论坛搜寻,找资料找的痛苦呀!前几天终于完成了这部分的测试代码,可以正常使用,跟大家分享一下,希望能对后面做这部分研究的朋友们,有点帮助~ 最近开始做yuv --rgb 的相互转换,使用软件转换也已经完成了,可是太耗时了,现在想尝试用硬件来完成,可是发现210 上面没有这个单独的硬件,6410有这个tv 定标器硬件可以完成,而我在210中没有找到相关的资料,在210多媒体部分貌似只有camerif接口中的DMA通道能完成,手册中描述的太不清楚了,如果大家那位之前做过这部分的东西,还请麻烦跟小弟,分享下咯~~~
下面贴出jpeg的测试,可以直接使用!
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/select.h>
#include <sys/time.h>
#include <errno.h>
#include <sys/mman.h>
#include "test_jpeg.h"
#include "s3c-jpeg.h"
#define CTRL_FILE_NAME "./640_480.yuv422"
#define JESULT_NG 0
#define JESULT_OK 1
static int phy_addr_base;
static void *vir_addr_base = NULL;
static int jpg_fd;
static int init_jpeg(void)
{
int mem_fd;
jpg_fd = open("/dev/s3c-jpg", O_RDWR, 0655);
if(jpg_fd < 0){
return -1;
}
mem_fd = open("/dev/mem", O_RDWR, 0655);
if(mem_fd < 0){
return 0;
}
printf("11111111\n");
phy_addr_base = ioctl(jpg_fd, IOCTL_JPG_GET_PHY_ADDR, 0);
printf("2222222\n");
vir_addr_base = mmap(NULL, 0x1000000, PROT_READ | PROT_WRITE, MAP_SHARED, mem_fd, phy_addr_base);
printf("33333333\n");
return 0;
}
static int jpeg_decode(void *src, void *dst, int size)
{
struct jpg_dec_proc_param dec_param, *p = &dec_param;
struct timeval decode_start, decode_end;
char *img_buffer;
p->sample_mode = JPG_422;
p->dec_type = JPG_MAIN;
p->out_format = YCBCR_422;
p->width = 0;
p->height = 0;
p->data_size = 0;
p->file_size = size;
p->stream_phy_addr = phy_addr_base+ 0x100000;
p->raw_phy_addr = phy_addr_base ;
memcpy(vir_addr_base+ 0x100000 , src, size);
//ttimeofday(&decode_start, NULL);
if(ioctl(jpg_fd, IOCTL_JPG_DECODE, p) < 0){
printf("jpeg_decode -->ioctl IOCTL_JPG_DECODE failed\n");
return -1;
}
//decode(frame->data, out_frame->data, frame->type, frame->frame_size, &frame->width, &frame->height, NULL, 0);
//ttimeofday(&decode_end, NULL);
memcpy(dst, vir_addr_base , p->data_size);
return 0;
}
int main_dnc(void)
{
FILE * in_fp,*out_fp;
int jpg_size,fileSize;
int ret ;
char *jpg_buffer,*img_buffer;
/*初始化打开jpeg 设备*/
init_jpeg();
/*读取需要解码的数据*/
jpg_buffer = malloc(0x100000);
if(NULL == jpg_buffer)
{
printf("malloc jpg_buffer failed\n");
goto ERR1;
}
memset(jpg_buffer,0,0x100000);
in_fp = fopen("640_480.jpg", "rb");
if(in_fp == NULL)
{
printf("4444444\n");
}
printf("555555555 \n");
fseek(in_fp, 0, SEEK_END);
fileSize = ftell(in_fp);
fseek(in_fp, 0, SEEK_SET);
printf("56666666 \n");
jpg_size = fread(jpg_buffer,1,fileSize , in_fp);
printf("77777777\n");
printf("------------------>jpg_size = %d, fileSize =%d\n", jpg_size,fileSize);
fclose(in_fp);
img_buffer = malloc(0x100000);
if(NULL == img_buffer){
printf("malloc img_buffer failed\n");
goto ERR2;
}
memset(img_buffer,0,0x100000);
ret = jpeg_decode(jpg_buffer,img_buffer,jpg_size);
if(ret < 0){
printf("jpeg_decode failed\n");
goto ERR3;
}
/*打开解码完成后存储图像文件*/
out_fp = fopen("640_480", "wb");
ret = fwrite(img_buffer, 1,640*480*2 , out_fp);
free(img_buffer);
free(jpg_buffer);
return JESULT_OK;
ERR3:
free(img_buffer);
ERR2:
free(jpg_buffer);
ERR1:
return JESULT_NG;
}
int main_mydnc(void)
{
int jpeg_fd,fileSize=0;
int ret = 0,result;
char *InBuf,*OutBuf;
FILE * inbuf_fp,*outdnc_fp;
int addr_base;
int addr_offer;
int i;
int tmp_addr;
struct jpg_args param_dnc;
struct jpg_dec_proc_param *my_dnc_param;
// 打开jpeg 设备
printf("@@@@@APP@@@@@open start \n");
jpeg_fd = open("/dev/s3c-jpg", O_RDWR);
if (jpeg_fd < 0) {
perror("open device jpeg");
}
addr_base = mmap(NULL,1024*1024*8,PROT_READ|PROT_WRITE,MAP_SHARED,jpeg_fd,0);
if(addr_base == MAP_FAILED){
printf(" mmap InBuf failed\n");
goto ERR1;
}
addr_offer = ioctl(jpeg_fd, IOCTL_JPG_GET_FRMBUF, 0);
if(!addr_offer){
printf("s3c_jpeg_ioctl OutBuf NG \n");
goto ERR2;
}
#if 0
tmp_addr = ioctl(jpeg_fd, IOCTL_JPG_GET_STRBUF,addr_base);
printf("####tmp_addr = 0x%08x\n",tmp_addr);
#endif
#if 0
addr_phy_offer = ioctl(jpeg_fd, IOCTL_JPG_GET_PHY_FRMBUF);
if(!addr_phy_offer){
printf("s3c_jpeg_ioctl addr_phy_offer NG \n");
goto ERR2;
}
#endif
printf("@@@@@APP@@@@@ addr_base = 0x%x ,addr_offer +addr_base= 0x%x \n",addr_base ,addr_offer +addr_base);
my_dnc_param = (struct jpg_dec_proc_param *)malloc(sizeof(struct jpg_dec_proc_param));
if(NULL == my_dnc_param){
printf("malloc my_dnc_param failed\n");
goto ERR2;
}
memset(my_dnc_param, 0, sizeof(struct jpg_dec_proc_param));
InBuf = (char *)addr_base;
OutBuf = (char *)(addr_base+addr_offer);
if (addr_offer % 16 !=0)
{
printf("addr_offer is not 16 bit addr\n");
goto ERR2;
}
printf("is good\n");
// 打开图像文件
inbuf_fp = fopen("./640_480.jpg","rb");
if(inbuf_fp == NULL)
{
perror("./JPEG_data.jpg\n");
goto ERR3;
}
// 在这里用于计算打开的JTAG图像文件的大小(byte)
fseek(inbuf_fp, 0, SEEK_END);
fileSize = ftell(inbuf_fp);
fseek(inbuf_fp, 0, SEEK_SET);
printf("@@@filesize =%d\n",fileSize);
ret = fread(OutBuf, 1, fileSize, inbuf_fp);
for(i=0;i<5;i++){
printf("@@@@@OutBuf = 0x%08x\n",OutBuf);
}
fclose (inbuf_fp);
printf("@@@@@APP@@@@@file Inbuf file open ok ret =%d\n\n",ret);
param_dnc.in_buf = InBuf;
param_dnc.out_buf = OutBuf;
param_dnc.dec_param = my_dnc_param;
my_dnc_param->out_format=YCBCR_422;
#if 0
my_dnc_param->width =640;
my_dnc_param->height = 480;
my_dnc_param->sample_mode = JPG_422;
#endif
// ioctl 开始进行编解码处理
printf("@@@@@APP@@@@@ioctl start \n");
result = ioctl(jpeg_fd, IOCTL_JPG_DECODE, ¶m_dnc);
if(!result){
printf("s3c_jpeg_ioctl:decode NG \n");
goto ERR4;
}
printf("end decode my_dnc_param->data_size = %d\n",my_dnc_param->data_size);
outdnc_fp= fopen("./JPEG_data_dnc","wb");
if(outdnc_fp < 0)
{
printf("file open ./JPEG_data error \n");
goto ERR4;
}
ret = fwrite(OutBuf, 1,20 , outdnc_fp);
ret = fwrite(InBuf, 1,my_dnc_param->data_size , outdnc_fp);
if(ret < 0){
printf("fwrite failed ret = %d",ret);
goto ERR5;
}
printf("@@@@@APP@@@@@JPG_DECODE END ret = %d!\n ",ret);
fclose(outdnc_fp);
free(my_dnc_param);
munmap(addr_base,1024*1024*8);
close(jpeg_fd);
return JESULT_OK;
ERR5:
fclose(outdnc_fp);
ERR4:
fclose(inbuf_fp);
ERR3:
free(my_dnc_param);
ERR2:
munmap(addr_base,1024*1024*8);
ERR1:
close(jpeg_fd);
return JESULT_NG;
}
/*********************************** 编码测试 yuv422 *********************/
int main(void)
{
int fileSize = 0,jpeg_fd;
int ret = 0,result,timecount=0;
FILE * inbuf_fp,*outbuf_fp,*outdnc_fp;
char *InBuf,*OutBuf;
int cnt;
struct jpg_args param , param_dnc;
struct jpg_enc_proc_param *my_enc_param;
struct jpg_dec_proc_param *my_dnc_param;
struct timeval cur_time,pre_time;
int addr_base;
int addr_offer;
// 打开jpeg 设备
printf("@@@@@APP@@@@@open start \n");
jpeg_fd = open("/dev/s3c-jpg", O_RDWR);
if (jpeg_fd < 0) {
perror("open device jpeg");
//goto ERR1;
}
addr_base = mmap(NULL,1024*1024*8,PROT_READ|PROT_WRITE,MAP_SHARED,jpeg_fd,0);
if(addr_base == MAP_FAILED){
printf(" mmap InBuf failed\n");
goto ERR1;
}
addr_offer = ioctl(jpeg_fd, IOCTL_JPG_GET_FRMBUF, 0);
if(!addr_offer){
printf("s3c_jpeg_ioctl OutBuf NG \n");
goto ERR2;
}
printf("@@@@@APP@@@@@ addr_base = 0x%x ,addr_offer +addr_base = 0x%x \n",addr_base ,addr_offer+addr_base);
my_enc_param = (struct jpg_enc_proc_param *)malloc(sizeof(struct jpg_enc_proc_param));
if(NULL == my_enc_param){
printf("malloc my_enc_param failed\n");
goto ERR2;
}
memset(my_enc_param, 0, sizeof(struct jpg_enc_proc_param));
InBuf = (char *)addr_base;
OutBuf = (char *)(addr_base+addr_offer);
// 开始对一桢数据进行编码
param.in_buf = InBuf;
param.in_buf_size = 1024*1024*2;
param.out_buf = OutBuf;
param.out_buf_size =800*600*2;
param.enc_param = my_enc_param;
my_enc_param->sample_mode = JPG_422;
my_enc_param->enc_type = JPG_MAIN;
my_enc_param->in_format = JPG_MODESEL_YCBCR;
my_enc_param->width = 640;
my_enc_param->height =480;
my_enc_param->quality = JPG_QUALITY_LEVEL_1;
//my_enc_param->data_size = 640*480*2;
//my_enc_param->file_size = 640*480*2;
// 打开图像文件
inbuf_fp = fopen("./640_480","rb");
if(inbuf_fp == NULL)
{
perror("./640_480.yuv422");
goto ERR3;
}
// 在这里用于计算打开的JTAG图像文件的大小(byte)
fseek(inbuf_fp, 0, SEEK_END);
fileSize = ftell(inbuf_fp);
fseek(inbuf_fp, 0, SEEK_SET);
ret = fread(InBuf, 1, fileSize, inbuf_fp);
fclose (inbuf_fp);
printf("@@@@@APP@@@@@file Inbuf file open ok ret =%d\n\n",ret);
// ioctl 开始进行编解码处理
printf("@@@@@APP@@@@@ioctl start \n");
param.in_buf_size = fileSize;
gettimeofday(&pre_time,NULL);
result = ioctl(jpeg_fd, IOCTL_JPG_ENCODE, ¶m);
if(!result){
printf("s3c_jpeg_ioctl NG \n");
goto ERR4;
}
gettimeofday(&cur_time,NULL);
if(pre_time.tv_sec == cur_time.tv_sec)
timecount = cur_time.tv_usec - pre_time.tv_usec;
else
timecount = (cur_time.tv_usec - pre_time.tv_usec)/1000+1;
printf("~@@@@~~~~~~~timecount=%d\n",timecount);
//printf("my_enc_param->data_size = %d\n",my_enc_param->data_size);
printf("@@@@@APP@@@@@my_enc_param->file_size = %d\n",my_enc_param->file_size);
//编解码完成后,图像进行写处理
//write(jpeg_fd,(char*)OutBuf,file_size);
outbuf_fp= fopen("./JPEG_data","wb");
if(outbuf_fp < 0)
{
printf("file open ./JPEG_data error \n");
goto ERR5;
}
ret = fwrite(OutBuf, 1,my_enc_param->file_size , outbuf_fp);
if(ret < 0){
printf("fwrite failed ret = %d",ret);
goto ERR5;
}
fclose (outbuf_fp);
free(my_enc_param);
munmap(InBuf,1024*1024*8);
close(jpeg_fd);
return JESULT_OK;
#if 0
ERR7:
free(my_dnc_param);
ERR6:
fclose(outdnc_fp);
#endif
ERR5:
fclose(outbuf_fp);
ERR4:
fclose (inbuf_fp);
ERR3:
free(my_enc_param);
ERR2:
munmap(InBuf,1024*1024*8);
ERR1:
close(jpeg_fd);
return JESULT_NG;
}