三星6410摄像头测试程序流程分析

版权声明:本文为博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/niuniumenghua/article/details/6509327

 作者:

嵌入式领域著名讲师  O(_)O  牛牛猛  华清远见金牌讲师

                                     

 

点击链接加我好友!

http://student.csdn.net/invite.php?u=111047&c=758a60d66d3a92d1

欢迎大家去CSDN博客上踩踩

我的个人主页

 

在代码分析开始前需要对一个概念进行解释,就是MFC

Multi Format Codec的缩写,是ARM微处理器内部一种支持多种硬件编码方式的硬件电路,能够编码/解码 MPEG-4/H.263/H.26430fps)等多种格式的多媒体影像。

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;

}

首先要注意的是传入的参数,它们分别定义了每一帧图像的长宽,帧的速度,比特率,GOPGroup 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)

其实这就是一个解除映射的过程。

 

展开阅读全文

关于6410开发板摄像头的问题

03-19

开发板装的是内核版本是3.0.1,插上中星微301P摄像头,有反应,如下:rn[root@FORLINX6410]# usb 1-1: new full speed USB device number 2 using s3c2410-oirnusb 1-1: New USB device found, idVendor=0ac8, idProduct=301b rnusb 1-1: New USB device strings: Mfr=1, Product=2, SerialNumber=0 rnusb 1-1: Product: PC Camera rnusb 1-1: Manufacturer: Vimicro Corp. rngspca: probing 0ac8:301b rnzc3xx: probe 2wr ov vga 0x0000 rnzc3xx: probe sensor -> 0011 rnzc3xx: Find Sensor HV7131R rninput: zc3xx as /devices/platform/s3c2410-ohci/usb1/1-1/input/input3 rngspca: video2 created rn新创建的video2也能在/dev下找到,但是我想测试下摄像头,当执行命令:cat /dev/video2 >a.jpg后,出现错误如下:rnUnable to handle kernel NULL pointer dereference at virtual address 00000060 rnpgd = c3d14000 rn[00000060] *pgd=53d5d831, *pte=00000000, *ppte=00000000 rnInternal error: Oops: 17 [#1] rnModules linked in: rnCPU: 0 Tainted: G W (3.0.1 #425) rnPC is at video_devdata+0x18/0x30 rnLR is at dev_open+0x28/0x194 rnpc : [] lr : [] psr: 60000013 rnsp : c3d4bd30 ip : c3d4bd40 fp : c3d4bd3c rnr10: c0733038 r9 : 00000024 r8 : c42134e0 rnr7 : c3c66008 r6 : c42134e0 r5 : c3d52900 r4 : c3c66000 rnr3 : 00000003 r2 : c07b0350 r1 : 00000000 r0 : c42134e0 rnFlags: nZCv IRQs on FIQs on Mode SVC_32 ISA ARM Segment user rnControl: 00c5387d Table: 53d14008 DAC: 00000015 rnProcess cat (pid: 179, stack limit = 0xc3d4a268) rnStack: (0xc3d4bd30 to 0xc3d4c000) rnbd20: c3d4bd6c c3d4bd40 c030a118 c02f9b2c rnbd40: c030a0f0 c3c66000 c3d52900 c42134e0 c3c66008 c3d52900 00000024 c4212880 rnbd60: c3d4bd8c c3d4bd70 c02f9eb8 c030a0fc 00000000 00000000 c47428c0 c42134e0 rnbd80: c3d4bdbc c3d4bd90 c00ed5b0 c02f9e14 c3d4be2c 00000000 c3d4bed0 c3d52900 rnbda0: 00000000 c42134e0 c00ed490 c4212880 c3d4bdf4 c3d4bdc0 c00e8d14 c00ed49c rnbdc0: c407bd00 c440fb40 c42134e0 c3d4bed0 c3d52900 00000000 c3d52880 00020000 rnbde0: 00000024 00000000 c3d4be1c c3d4bdf8 c00e8f50 c00e8bb4 c3d52880 c3d4be8c rnbe00: c42134e0 c3d4bed0 00000000 c3d4be8c c3d4be64 c3d4be20 c00f6488 c00e8ef4 rnbe20: c3d60005 c079fcc0 c3d4be64 c440fb40 c407bd00 c42134e0 c3d4be64 c3d4bed0 rnbe40: ffffff9c c3d4bf60 c3d4a000 c3d60000 c3d4a000 c3d4be8c c3d4bec4 c3d4be68 rnbe60: c00f792c c00f630c c3d4be94 40102000 c3cf6c00 c407acf8 00000000 80000007 rnbe80: c3d1af00 00000200 c3cf6c00 c440fb40 c4212880 00000000 00000000 00000001 rnbea0: c3d4bf60 c3d4bed0 ffffff9c c3d60000 c3d4a000 ffffff9c c3d4bf54 c3d4bec8 rnbec0: c00f7d04 c00f7874 00000041 dde53737 c440fb40 c4212880 d9d3cea0 00000006 rnbee0: c3d60005 00000000 c4078b00 c42134e0 00000101 00000004 00000000 00000000 rnbf00: 00000000 00000000 00000003 c3c75600 c3c75608 c3c75604 00000000 c3d4a000 rnbf20: c3d4bf54 00020001 00000000 00000000 00000001 00000001 00020000 00000000 rnbf40: 00000003 c3d60000 c3d4bf94 c3d4bf58 c00e8a78 c00f7cd8 c3d4bfa4 c3d4bf68 rnbf60: 00020000 00000000 00000024 00000100 00000000 00000000 be85ff63 00000005 rnbf80: c0034ce8 00000000 c3d4bfa4 c3d4bf98 c00e8b84 c00e8988 00000000 c3d4bfa8 rnbfa0: c0034b40 c00e8b6c 00000000 00000000 be85ff63 00020000 00000000 000030dc rnbfc0: 00000000 00000000 be85ff63 00000005 00000000 00000000 40103000 00000002 rnbfe0: 402a18e0 be85fc90 0000f808 402a1930 60000010 be85ff63 57ffe821 57ffec21 rn[] (video_devdata+0x18/0x30) from [] (dev_open+0x28/0x194) rn[] (dev_open+0x28/0x194) from [] (v4l2_open+0xb0/0xd8) rn[] (v4l2_open+0xb0/0xd8) from [] (chrdev_open+0x120/0x1a4) rn[] (chrdev_open+0x120/0x1a4) from [] (__dentry_open+0x16c/0)rn[] (__dentry_open+0x16c/0x2c4) from [] (nameidata_to_filp+0)rn[] (nameidata_to_filp+0x68/0x70) from [] (do_last+0x188/0x6)rn[] (do_last+0x188/0x6b0) from [] (path_openat+0xc4/0x3a4) rn[] (path_openat+0xc4/0x3a4) from [] (do_filp_open+0x38/0x8c)rn[] (do_filp_open+0x38/0x8c) from [] (do_sys_open+0xfc/0x1d0)rn[] (do_sys_open+0xfc/0x1d0) from [] (sys_open+0x24/0x28) rn[] (sys_open+0x24/0x28) from [] (ret_fast_syscall+0x0/0x30)rnCode: e24cb004 e590200c e5921020 e59f2010 (e5913060) rn---[ end trace da227214a82491b9 ]--- rnSegmentation faultrn请各位指示,谢谢~~rnrn 论坛

用jlink 烧写三星6410程序的问题

01-06

小弟做了一块6410的电路板。电源、晶振、复位均正常。下载程序时遇到些问题,无法把程序下载到CPU内。那位DX肯伸出援手,不胜感激。rnrn我是用命令行模式下载程序的,以下是下载时的信息:rnSEGGER J-Link Commander V4.20h ('?' for help)rnCompiled Oct 5 2010 19:11:57rnDLL version V4.20h, compiled Oct 5 2010 19:11:41rnFirmware: J-Link ARM V8 compiled Oct 7 2010 10:56:54rnHardware: V8.00rnS/N: 68000149rnOEM: J-Link-CErnVTarget = 3.267VrnInfo: TotalIRLen = 9, IRPrint = 0x0011rnFound 2 JTAG devices, Total IRLen = 5:rn #0 Id: 0x2B900F0F, IRLen: 04, IRPrint: 0x0, ARM ETBrn #1 Id: 0x07B76F0F, IRLen: 05, IRPrint: 0x1, ARM1176 CorernARM11 identified.rnJTAG speed: 100 kHzrnJ-Link>rrnReset delay: 0 msrnReset type NORMAL: Using RESET pin.rnInfo: TotalIRLen = 9, IRPrint = 0x0011rnJ-Link: ARM11 CP15 Settings changed: 0x00451078 from 0x00001002, MMU Off, ICachern On, DCache OffrnInfo: CP15.0.0: 0x410FB766: ARM, Architecture Unknown architecturernInfo: CP15.0.1: 0x1D152152: ICache: 16kB (4*128*32), DCache: 16kB (4*128*32)rnDIDR: 6 Breakpoints available and 2 Watchpoints available.rnJ-Link>loadbin e:\output.bin 0rnLoading binary file... [e:\output.bin]rnWriting bin data into target memory @ 0x00000000.rnInfo: CP15.0.0: 0x410FB766: ARM, Architecture Unknown architecturernInfo: CP15.0.1: 0x1D152152: ICache: 16kB (4*128*32), DCache: 16kB (4*128*32)rnDIDR: 6 Breakpoints available and 2 Watchpoints available.rnJ-Link>setpc 0rnCPU is not halted !rnrnrn 论坛

没有更多推荐了,返回首页