作者:
嵌入式领域著名讲师O(∩_∩)O牛牛猛 华清远见金牌讲师
点击链接加我好友!
http://student.csdn.net/invite.php?u=111047&c=758a60d66d3a92d1
欢迎大家去我CSDN博客上踩踩
我的个人主页
在代码分析开始前需要对一个概念进行解释,就是MFC。
Multi Format Codec的缩写,是ARM微处理器内部一种支持多种硬件编码方式的硬件电路,能够编码/解码 MPEG-4/H.263/H.264(30fps)等多种格式的多媒体影像。
TOP6410开发板使用的是ARM11的核,我们现在要利用这个ARM内部的硬件编解码电路来直接对摄像头采集到的图像进行基于硬件的编解码。首先在项目开始前需要对TOP6410的性能做大体的测试,现在我们使用的是三星提供的测试程序,通过对这个测试程序的分析可以很好地让我们了解基于系统级的图像编解码函数的调用机制,有利于我们顺利的提取图像并且进行进一步的处理。
要使用MFC,首先要了解如何使用这种机制,在我们的代码中首先要定义一个MFC的句柄(handle),所有的MFC操作都是需要通过传递这个handle作为参数来执行的,它的重要性就跟main 函数差不多,是整个编解码过程的掌舵者。在源码中是这样定义的:
/***************** MFC *******************/
static void *handle;
/* MFC functions */
static void *mfc_encoder_init(int width, int height, int frame_rate, int bitrate, int gop_num);
static void *mfc_encoder_exe(void *handle, unsigned char *yuv_buf, int frame_size, int first_frame, long *size);
static void mfc_encoder_free(void *handle);
看到我们这里定义了三个函数分别是初始化函数,执行函数,还有句柄释放函数。我们就是要利用这三个函数进行我们的编解码操作,我们再来看看init函数的实现:
void *mfc_encoder_init(int width, int height, int frame_rate, int bitrate, int gop_num)
{
int frame_size;
void *handle;
int ret;
frame_size = (width * height * 3) >> 1;//这里的意思是把width*height*3的值除以2
handle = SsbSipH264EncodeInit(width, height, frame_rate, bitrate, gop_num);
if (handle == NULL) {
LOG_MSG(LOG_ERROR, "Test_Encoder", "SsbSipH264EncodeInit Failed/n");
return NULL;
}
ret = SsbSipH264EncodeExe(handle);
return handle;
}
首先要注意的是传入的参数,它们分别定义了每一帧图像的长宽,帧的速度,比特率,GOP(Group of Pictures)策略影响编码质量(设置编码的质量系数)。
函数的作用是对整个MFC的参数进行设置
这里有一个frame_size,有人问为什么要定义成那么大,我们需要的图像每一帧的大小是我们可以自己定义的,我们在代码执行前一般都会开一个缓冲区来存放每一帧的数据,由于我们开的缓冲区给每帧的大小就是那么大,所以这里也好配合我们之前开辟的缓冲区大小进行编码。
SsbSipH264EncodeInit()这个函数可以说是真正的开始进入编码的初始化过程,现在让我们进去看看。
现在我们来看看代码里的关键的几个地方:
hOpen = open(MFC_DEV_NAME, O_RDWR|O_NDELAY);//打开设备节点
// 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);
这里是进行内存映射,我想做过摄像头项目的人对这个肯定特别有体会,这个函数的作用其实就是把MFC设备工作后写入的那部分内存映射到我的应用程序开的缓冲区中,也就是说我只要对应用程序中的buffer进行读写其实就是对部分内存的读写。内存映射是linux内核当中一个非常重要的机制,希望能够引起大家足够多的重视。
pCTX = (_MFCLIB_H264_ENC *) malloc(sizeof(_MFCLIB_H264_ENC));
看到这里我想有必要展示一下这个_MFCLIB_H264_ENC的结构体:
typedef struct
{
int magic;
int hOpen;
int fInit;
int enc_strm_size;
int enc_hdr_size;
unsigned int width, height;
unsigned int framerate, bitrate;
unsigned int gop_num;
unsigned char *mapped_addr;
} _MFCLIB_H264_ENC;
这个是为MFC设备定义的结构体,至于这样定义主要是为了能够和内核中的定义进行匹配,相关代码可以参看内核。这里主要是定义了编码需要的参数。
之后的工作就是要把这个结构体填满(定义好各项初始化参数),主要的作用就是完成初始化的工作。到这里SsbSipH264EncodeInit()结束,但是初始化工作并没有完成。
其实这里你会发现handle是什么?handle其实在这里被定义为了指向_MFCLIB_H264_ENC这个结构体的指针。其实仔细的朋友你会发现handle这个指针在每一次函数调用过程当中都会指向不同的结构体或者是内存地址,读者可以把它理解成贯穿于整个MFC硬件解码的过程当中的中间变量,就相当于指向贯穿于我们程序主干部分的指针,通过它可以得到整个硬解码过程的清晰函数结构。
要执行SsbSipH264EncodeExe()函数。要做的是对MFC内部的一些结构体进行初始化,然后就到了很关键的一步:
r = ioctl(pCTX->hOpen, IOCTL_MFC_H264_ENC_INIT, &mfc_args);
这一步其实就是把我们刚才设置好的关于MFC的初始化参数传递到我们内核的驱动程序中,使得驱动程序能够根据我们提供的这些参数对设备进行相应的初始化工作。
在这里IOCTL_MFC_H264_ENC_INIT是制定设备的编码格式,pCTX->hOpen是设备的描述符,mfc_args里转载了MFC所有的参数。完成了这些才算是真正的完成了初始化的工作。
总结一下我们刚才经过的步骤:
1. 打开设备节点
2. 进行内存到应用的内存映射
3. 初始化关于MFC设备的机构体,并且提供相应的参数
4. 把_MFCLIB_H264_ENC参数传入MFC跟深层次的结构体当中
5. 通过ioctl函数把这些参数传入到内核当中
初始化完成以后我们就要正式开始编码了,现在看一下mfc_encoder_exe()函数的实现大致过程。其实运行的过程非常的简单:
SsbSipH264EncodeGetInBuf(handle, 0);
SsbSipH264EncodeExe(handle);
SsbSipH264EncodeGetConfig(handle, H264_ENC_GETCONF_HEADER_SIZE, &hdr_size);
SsbSipH264EncodeGetOutBuf(handle, size);
看以上这几个函数,其作用通过读函数名字我想就已经非常清楚了,步骤如下:
1. 首先得到输入图像的地址buffer
2. 然后进行编码
3. 第一次的编码需要传入配置参数
4. 得到输出的经过编码的图像的地址(通过内部结构体传递)和大小
分析完以上过程之后,最后就是完成编码后的处理函数
static void mfc_encoder_free(void *handle);
其实它当中就是调用了一个SsbSipH264EncodeDeInit(handle);函数
里面其实只是做了一件事:munmap(pCTX->mapped_addr, BUF_SIZE);
其实这就是一个解除映射的过程。
分享到:
相关推荐
《mini2440摄像头测试程序详解》 在嵌入式系统开发中,摄像头的应用日益广泛,而mini2440作为一款经典的S3C2440开发板,其摄像头接口功能的测试与开发是许多学习者关注的重点。本文将深入探讨mini2440摄像头测试...
本文介绍了 USB摄像头驱动开发的过程,包括 USB 驱动程序的功能、OV511+ 芯片的控制、开发工具和测试系统、流接口 USB 驱动程序步骤、流接口 USB 驱动程序加载的流程和流接口驱动程序的实现。通过了解这些知识点,...
测试程序的主要目的是验证S3C 2440与OV9650之间的通信和数据传输功能,同时将摄像头采集的图像数据实时显示在液晶屏上。这个过程涉及到了以下几个关键知识点: 1. **硬件接口**:S3C 2440与OV9650之间的连接通常...
标题中的“WINCE2440USB摄像头照相机”指的是基于Windows CE(简称WINCE)操作系统的Samsung S3C2440处理器上的USB摄像头设备,通常用于开发板或者嵌入式系统中,提供图像捕捉功能。这类摄像头常用于物联网(IoT)设备...
为了更好地理解和实现基于s3c2440处理器的Linux摄像头驱动开发,本文将深入探讨其硬件环境、软件环境以及具体的开发流程。 #### 一、s3c2440处理器简介 s3c2440是Samsung公司生产的一款基于ARM920T内核的高性能微...
标题“testUsbCamera_ok6410B_linux3.0.1”表明这是一个与USB摄像头测试相关的项目,特别适用于OK6410B开发板,并且是在Linux 3.0.1操作系统环境下运行的。这里有几个关键知识点,我们将逐一进行深入探讨。 1. **...
6. 应用程序:有时,BSP还可能包含一些预装的应用程序或示例代码,帮助开发者快速上手和测试硬件功能。 对于“i8000可用”的描述,这可能指的是S3C6410 BSP经过了在名为“i8000”的开发板上的验证和优化,确保在该...
S3C6410 是一款由三星电子公司生产的高性能 ARM11 架构处理器,主要用于移动设备和嵌入式系统。该处理器集成了强大的图形处理单元 (GPU) 和多媒体引擎,支持高清视频播放,并且拥有丰富的外设接口,适用于多种应用...
5. 驱动程序开发:针对S3C6410的特定外设,如GPIO、UART、I2C等,讲解驱动编写和测试流程。 6. 应用程序开发:介绍如何在Linux环境下编写和运行C/C++程序,以及移植和调试第三方软件。 四、实用教程与实战案例 手册...
为了完成zc301摄像头的V4L采集图像,你需要将这些文件解压并集成到你的项目中,然后根据驱动开发流程进行编译和测试。编译时使用了2.95.3的交叉编译工具,这意味着你需要一个适合目标平台的交叉编译环境,以便生成...
7. **测试用例设计**:理解测试程序的设计思路,如何覆盖各种使用场景,验证驱动的正确性和稳定性。 通过这些知识点的学习,开发者可以掌握在S3C2440平台上实现摄像头功能的完整流程,从而在自己的项目中实现类似的...
《Tiny6410 Linux开发指南》是一份详尽的文档,主要针对使用Tiny6410开发板的用户,提供了全面的Linux开发环境搭建、系统配置、硬件接口测试以及软件开发指导。以下是对该指南中提及的关键知识点的深度解析。 ### ...
综上所述,OK6410-A开发板Linux用户手册是一份全面的指导文档,涵盖了从硬件到软件,从开发环境搭建到系统测试的全部流程,是开发者进行产品开发和功能测试的强有力参考。由于开发板的更新换代,本手册适用于2014年9...
4. **测试与调试**:移植完成后,需要对系统进行详尽的测试,确保所有功能正常运行,包括基本的启动流程、系统服务、用户界面、硬件功能等。调试过程中可能会遇到各种问题,如内存泄漏、系统崩溃等,需要借助日志...
《Tiny6410 Android开发指南》是一本专注于在基于Samsung S5PC110(又称Tiny6410)平台进行Android系统开发的专业指导资料。该资源是友善公司在2011年1月12日发布的一份光盘资料,旨在帮助开发者深入理解和实践在...
5. **驱动程序开发**:由于Android是基于Linux内核的,因此需要为Mini6410的各个硬件组件编写或适配驱动程序,如触摸屏、摄像头、无线网卡等。这部分知识涉及Linux内核编程和设备驱动模型。 6. **应用程序开发**:...
标题中的“s3c6410-h264-encode-ok.rar_encode_h264_ov9650 6410_s3c6410_s3c64”指的是一个基于S3C6410处理器的H264编码实现,该实现已经过产品化验证,能够成功地将视频数据从OV9650摄像头采集并编码为H264格式。...