打印

ARM11硬件编解码例程——发给大家看看(华恒出的)。

[复制链接]
7216|2
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
kissring|  楼主 | 2008-11-17 13:40 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
华恒出的——ARM11硬件编解码例程,发给大家看看。


摘要:介绍基于华恒科技HHS3C6410平台,将摄像头采集的数据通过硬件编码后通过网络发送,客户端(Linux)通过网络实时接收并显示的具体实现;主要介绍S3C6410的H264硬件编码特性和V4L2编程。

关键词:S3C6410 H.264 视频监控 V4L2

0 引言
    HHS3C6410是华恒科技推出的一款针对高性能手持设备和通用视频处理应用的低功率, 高性能的嵌入式开发板,采用三星S3C6410 ARM1176JZF-S处理器,最高主频可达667MHz;S3C6410内部集成的多媒体编解码器(MFC)支持mpeg4/h.263/h.264的编码与解码,并支持VC1解码,性能可以达到全双工30fps@640x480同时编解码和半双工30fps@720x480或25fps@720x576编解码。
    H.264/AVC标准是一套兼顾广播和电信,覆盖从低码率通信到高清晰电视的广域标准,相比以前的标准,具有更高的压缩率,高质量图像,容错功能,并有很强的网络适应性。

1 总体设计
    监控系统由监控前端,监控终端,网络三部分组成,监控前端是一个嵌入式Linux系统,它通过S3C6410的Camera IF接收摄像头(SAA7113)采集的数据,并传送给硬件编解码(MFC)模块,并把得到的经过H264压缩的数据打包发送到IP网络上,监控终端(Linux)通过网络接收数据包,经过解码实时播放。总体框架如图1:
 
图1. 总体框架图
整个嵌入式视频采集系统由软件和硬件两部分组成。硬件方面,以S3C6410处理器为核心通过Camera IF接口接收摄像头数据,经过MFC硬件编码后通过DM9000发送,UART作为开发调试接口;软件方面,引导程序和Linux内核,设备驱动程序形成基本的嵌入式运行环境,应用层负责视频采集,压缩及传输。

2 软件设计
    软件设计包括嵌入式系统构建和应用软件两部分,其中嵌入式系统部分按照华恒科技S3C6410用户手册构建,其中包括了Bootloader,Linux内核,交叉编译器,驱动等;下面介绍应用软件设计:

    监控前端:
    监控前端主要包括视频采集模块和视频压缩编码模块。
    视频采集模块使用V4L2接口收集摄像头数据到缓冲区中,视频压缩模块调用MFC驱动把YUV420数据压缩编码,同时可以指定编码参数。示例代码如下:
    
cam_fp = open(cam_name, O_RDWR);        //打开camera设备
    ...
    mfc_fd = open(MFC_DEV_NAME, O_RDWR|O_NDELAY);    //打开MFC设备
    ...
    addr = (char *) mmap(0,BUF_SIZE,PROT_READ | PROT_WRITE,MAP_SHARED,mfc_fd,0);        //mmap MFC
    //设置编码参数
    enc_init.in_width        =    out_width;
    enc_init.in_height        =    out_height;
    enc_init.in_frameRateRes    =    atoi(argv[2]);
    enc_init.in_frameRateDiv    =    0;
    enc_init.in_bitrate         =    atoi(argv[3]);
    enc_init.in_gopNum        =    atoi(argv[4]);
    
    ioctl(mfc_fd, IOCTL_MFC_H264_ENC_INIT, &enc_init);

    frame_size  = (enc_init.in_width * enc_init.in_height * 3) >> 1;
    //得到MFC输入缓冲区地址
    get_buf_addr.in_usr_data = (int)addr;
    ioctl(mfc_fd, IOCTL_MFC_GET_FRAM_BUF_ADDR, &get_buf_addr);
    in_buf = (char *)get_buf_addr.out_buf_addr;
    //得到MFC输出缓冲区地址
    get_buf_addr.in_usr_data = (int)addr;
    ioctl(mfc_fd, IOCTL_MFC_GET_LINE_BUF_ADDR, &get_buf_addr);
    out_buf = (char *)get_buf_addr.out_buf_addr;
    //V4L2编程
    ioctl(cam_fp, VIDIOC_QUERYCAP, &cap);
    //选择输入/输出
    ioctl(cam_fp, VIDIOC_S_INPUT, &index);
    ioctl(cam_fp, VIDIOC_S_OUTPUT, &index);
    //设置格式,注意必须设置输出为YUV420格式
    ioctl(cam_fp, VIDIOC_G_FBUF, &fb);
    fb.capability = cap.capabilities;
    fb.fmt.width = out_width;
    fb.fmt.height = out_height;
    fb.fmt.pixelformat = V4L2_PIX_FMT_YUV420;
    ioctl(cam_fp, VIDIOC_S_FBUF, &fb);
    
    on = 1;
    ioctl(cam_fp, VIDIOC_OVERLAY, &on);

    while(1)
    {
        ...
        //接收摄像头数据到MFC的输入缓冲区
        read(cam_fp,  in_buf,  (out_width * out_height * 3 / 2));
        //控制MFC开始编码
        ioctl(mfc_fd, IOCTL_MFC_H264_ENC_EXE, &enc_exe);
        //把编码后帧的大小及数据发送出去
        send(net_fd, &enc_exe.out_encoded_size, 2, 0);
        send(net_fd, out_buf, enc_exe.out_encoded_size, 0);
        ...
    }
把摄像头的输出直接设为MFC的输入可以节省一次内存操作。

监控终端:
监控终端是一台运行Linux的PC机,主要负责从网络接收压缩包,使用SDL和Avcodec解码并显示,示例代码如下:
...
While(1)
{
    ...
    //接收压缩包
    recv(sock_fd, &size, 2, MSG_WAITALL);
    recv(sock_fd, &frame_buf[0], size, MSG_WAITALL);
    //初始化avcodec
    if (!pCodecCtx)
    {
        avcodec_init();
        pCodecCtx = avcodec_alloc_context();
        avcodec_open(pCodecCtx, pCodec);
        //设置参数
        if (pCodec->capabilities & CODEC_CAP_TRUNCATED)
        {
            pCodecCtx->flags |=   CODEC_FLAG_TRUNCATED;
            pCodecCtx->height = 480;
            pCodecCtx->width  = 640;
        }
        pFrame = avcodec_alloc_frame();
        avcodec_decode_video(pCodecCtx, pFrame, &frame_finishd, sps_buf, sizeof(sps_buf));
        //初始化SDL
        SDL_Init(SDL_INIT_VIDEO);
        screen = SDL_SetVideoMode (pCodecCtx->width, pCodecCtx->height, 0, 0);
        yuv = SDL_CreateYUVOverlay(pCodecCtx->width, pCodecCtx->height, SDL_YV12_OVERLAY, screen);
        
        SDL_WM_SetCaption(buf, "H264/TCP");
        rect.y = rect.x = 0;
        rect.w = pCodecCtx->width;
        rect.h = pCodecCtx->height;

        pict.data[0]     = yuv->pixels[0];
        pict.data[1]     = yuv->pixels[2];
        pict.data[2]     = yuv->pixels[1];

        pict.linesize[0] = yuv->pitches[0];
        pict.linesize[1] = yuv->pitches[2];
        pict.linesize[2] = yuv->pitches[1];
    }

    if (pCodecCtx)
    {
        //解码视频流
        avcodec_decode_video(pCodecCtx, pFrame, &frame_finishd, frame_buf, size);
        if (frame_finishd && yuv)
        {
            SDL_LockYUVOverlay(yuv);
            if ((!swsctx && !(swsctx = sws_getContext(pCodecCtx->width,
                pCodecCtx->height, pCodecCtx->pix_fmt,
                pCodecCtx->width,  pCodecCtx->height,
                PIX_FMT_YUV420P, SWS_BICUBIC, NULL, NULL, NULL))) ||
            sws_scale(swsctx, pFrame->data, pFrame->linesize, 0,
                pCodecCtx->height, pict.data, pict.linesize))
                    perror("sws ");
            
            SDL_UnlockYUVOverlay (yuv);
            //显示
            SDL_DisplayYUVOverlay(yuv, &rect);
        }
    }
}
以上程序编译需要libSDL, libavcodec, libswscale。

3 小结
本系统基于S3C6410实时采集,编码,传输数据,基本实现了视频监控的功能,测试采集,编码,传输VGA的图像可以达到25fps,使用多线程优化后应该可以更高,VGA分辨率图像经过H.264编码后平均每帧只有12k左右,占用网络带宽很少。


参考文献
[1]    S3C6410X_UM_Rev1.10_080822.pdf
[2]    Video for Linux Two API Specification Revision 0.23.pdf
[3]    http://ffmpeg.mplayerhq.hu/

相关帖子

沙发
芯行天下| | 2008-11-18 14:58 | 只看该作者

OK2440-II开发板,100M网卡,128M FLASH

OK2440-II开发板,性能强大,价格便宜。
最新升级100M 网卡,128M NAND FLASH。
门户网站:http://magicchip.siteem.com
QQ: 836596330
 
硬件特性:

CPU:三星S3C2440A,主频400MHz,可倍频至533MHz 
内存:64M,可根据需要扩展到128M 
NAND Flash: 128M,可更换为16M、32M、64M,更大 
串口: 一个五线异步串口,一个三线串口,一个三线扩展引出 
网口: 一个100M网口,带联接和传输指示灯 
USB接口: 一个USB1.1 HOST接口
          一个USB1.1 Device接口 
音频接口: 一路立体声音频输出接口可接耳机
           另一路音频输入可接麦克风 
存储接口: 一个SD卡接口
           一个IDE接口可直接挂接硬盘 
LCD和触摸屏接口: 集成了4线电阻式触摸屏接口的相关电路
                  目前支持3.5寸、5.6寸、5.7寸、8寸TFT液晶屏
                  3.3V/5V电源供电,可为多款液晶提供电压支持 
摄像头接口: 板上带有一个2mm间距的20P插座做为扩展,用户可使用此扩展口连接 各种摄像头 
时钟源: 内部实时时钟(带有后备锂电池(奥运期间快递属于禁口品暂时不带)) 
复位电路: 一个复位按键;采用专用复位芯片进行复位,稳定可靠 
调试下载接口: 一个20芯Multi-ICE标准JTAG接口
               配有一块儿下载调试板,支持WIGGLER调试及JTAG下载 
电源接口: 5V电源供电,带电源开关和指示灯 
温度测量: 一个高精度温度传感器,如果您感兴趣,可以做一个多点的温度采集系统。 
红外: 一个一体化红外遥控接收头 
AD转换: 一个可调电阻接到ADC引脚上用来验证模数转换 
EEPROM: 一片IIC接口的EEPROM 
其他: 五个用户按键
       五个用户LED
       一个PWM控制蜂鸣器

软件特性:
Bootloader:
 
启动时间: 可以设置启动时间
 
启动方式: 可设置默认启动方式,WINCE或Linux
 
下载调试: 支持USB及串口方式下载,可以通过USB将OS或者应用程序下载到内存进行调试
 
FLASH管理: 支持FLASH的烧写、擦除、坏块管理等功能
 
其他: 支持双操作系统(同时安装WINCE和LINUX)
       Linux可自行设置添加启动参数
       支持cramfs、yaffs两种文件系统的烧写


内核: Linux 2.6.12内核
       支持cramfs/ramfs/etx2/fat32/nfs/yaffs等文件系统
 
文件系统: 目前提供cramfs和yaffs两种格式的文件系统
 
驱动支持: 系统中断和系统时钟驱动
           串口驱动(Serial device driver)
           块设备驱动(包括IDE硬盘,SD卡)
           Nand Flash驱动
           网卡驱动
           实时时钟驱动
           USB Host驱动
           液晶(LCD)驱动,触摸屏驱动
           CMOS摄像头驱动
           USB摄像头驱动
           温度传感器驱动
           LED驱动
 
网络协议及网络应用程序: 完整的TCP/IP协议
                         Telnet服务器
                         Telnet远程登录
                         FTP服务器
                         Web Server
 
图形界面: QT/Embedded 支持文件浏览器、mediaplay播放器等
 
USB设备支持: 优盘、移动硬盘、USB鼠标、键盘、USB HUB、
              USB 摄像头(中芯微301系列芯片)
 
常用命令: cat,chmod,discard,echo,flashfsd,flashwrite, free,genhtml,hostname,init,kill,   

        loader,ls,mkdir,mount,ps,reboot,rm, smanaged,sysconf, yes,insmod,lsmod,rmmod
 
编译工具: 交叉编译环境链:2.95.3、3.3.2、3.4.1
 
其他: 提供环境搭建、内核配置、应用程序开发、驱动程序开发等教程及例程源码。

WINCE操作系统:

版本: Windows CE 5.0
 
驱动支持: 系统中断和系统时钟驱动
          串口驱动(Serial device driver)
          块设备驱动(SD卡)
          Nand Flash驱动
          以太网卡驱动(CS8000A)
          实时时钟驱动
          USB Host驱动
          USB Slave驱动
          液晶(LCD)驱动
          触摸屏驱动
 
显示: 支持320×240、640×480两种分辨率,并可动态调整
 
其他: 支持MediaPlayer播放器、IE浏览器等。
      支持注册表保存功能
      支持MFC、.NET2.0

使用特权

评论回复
板凳
taolei728| | 2011-7-18 12:34 | 只看该作者
xiexie!!!!!!!!!

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

2

主题

21

帖子

0

粉丝