• «
  • 1
  • 2
  • »
  • Pages: 1/2     Go
主题 : s3c 210 jpeg 硬解码的分享! 复制链接 | 浏览器收藏 | 打印
级别: 新手上路
UID: 93240
精华: 0
发帖: 48
金钱: 240 两
威望: 48 点
贡献值: 0 点
综合积分: 96 分
注册时间: 2013-06-18
最后登录: 2017-09-13
楼主  发表于: 2013-07-03 17:26

 s3c 210 jpeg 硬解码的分享!

最近一直使用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, &param_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, &param);
    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;    
    
}
级别: 新手上路
UID: 38447
精华: 0
发帖: 19
金钱: 95 两
威望: 19 点
贡献值: 0 点
综合积分: 38 分
注册时间: 2011-02-25
最后登录: 2017-09-17
1楼  发表于: 2013-07-13 00:25
可以請教 ENCODE 放進去的檔案 是為 YCBCR 422影像 是需要 RAW RGB檔嗎 還是YUV呢

感恩
级别: 新手上路
UID: 38447
精华: 0
发帖: 19
金钱: 95 两
威望: 19 点
贡献值: 0 点
综合积分: 38 分
注册时间: 2011-02-25
最后登录: 2017-09-17
2楼  发表于: 2013-07-13 00:56
請教 LZ YUV422 圖檔要怎樣才弄得到

感恩
级别: 新手上路
UID: 93240
精华: 0
发帖: 48
金钱: 240 两
威望: 48 点
贡献值: 0 点
综合积分: 96 分
注册时间: 2013-06-18
最后登录: 2017-09-13
3楼  发表于: 2013-07-15 13:20

 回 1楼(kib0092) 的帖子

视频这边采用相机采过来的数据就是yuv的。
级别: 新手上路
UID: 38447
精华: 0
发帖: 19
金钱: 95 两
威望: 19 点
贡献值: 0 点
综合积分: 38 分
注册时间: 2011-02-25
最后登录: 2017-09-17
4楼  发表于: 2013-07-15 15:19

 Re:回 1楼(kib0092) 的帖子

引用第3楼阿阳于2013-07-15 13:20发表的 回 1楼(kib0092) 的帖子 :
视频这边采用相机采过来的数据就是yuv的。


抱歉再請教
1.是用什麼樣的 模式截取 V4L2_PIX_FMT_YUV422P 還是 V4L2_PIX_FMT_YUYV 呢??

2.擷取一個 FRAME 下來做 JPG的壓縮 就好嗎??

可以加我QQ 請教您嗎 感恩

QQ: 1409072493
级别: 新手上路
UID: 93240
精华: 0
发帖: 48
金钱: 240 两
威望: 48 点
贡献值: 0 点
综合积分: 96 分
注册时间: 2013-06-18
最后登录: 2017-09-13
5楼  发表于: 2013-07-16 13:22

 回 4楼(kib0092) 的帖子

1. V4L2_PIX_FMT_YUYV  我在驱动中配置的是yuv422 1plane 的。
2.可以的,没有什么问题,我测试通过的!
级别: 新手上路
UID: 95502
精华: 0
发帖: 10
金钱: 50 两
威望: 10 点
贡献值: 0 点
综合积分: 20 分
注册时间: 2013-08-15
最后登录: 2014-01-17
6楼  发表于: 2013-08-19 17:51
IOCTL_JPG_DECODE 你的 ioctl参数 我的驱动里没有  是
IOCTL_JPEG_DEC_EXE 这个 不知道是怎么回事 我的是 exynos4412  A9 的
级别: 新手上路
UID: 95434
精华: 0
发帖: 9
金钱: 45 两
威望: 9 点
贡献值: 0 点
综合积分: 18 分
注册时间: 2013-08-13
最后登录: 2014-02-20
7楼  发表于: 2013-09-04 14:56
按照楼主的程序跑了一下,解码输出大小为0,不知道为什么?
级别: 新手上路
UID: 93240
精华: 0
发帖: 48
金钱: 240 两
威望: 48 点
贡献值: 0 点
综合积分: 96 分
注册时间: 2013-06-18
最后登录: 2017-09-13
8楼  发表于: 2013-09-17 15:06

 回 6楼(zhanglu110) 的帖子

有可能是一样的,我的那个是基于2.6.35.7的内核编写的。3.0.8的内核里面的接口貌似都不一样,具体的估计得研究下驱动了!
级别: 新手上路
UID: 93240
精华: 0
发帖: 48
金钱: 240 两
威望: 48 点
贡献值: 0 点
综合积分: 96 分
注册时间: 2013-06-18
最后登录: 2017-09-13
9楼  发表于: 2013-09-17 15:08

 回 7楼(pmsvq) 的帖子

你的这个现象,看着应该是地址分配的问题,内核平台那边的jpeg同样需要修正的。具体的的看看驱动了。我这边在2.6.35.7的内核中可以正常跑下来,我更改了驱动中的部分内容!
  • «
  • 1
  • 2
  • »
  • Pages: 1/2     Go