本节分析所使用的应用程序的源代码
/*
* Copyright 2004-2013 Freescale Semiconductor, Inc. All rights reserved.
*/
/*
* The code contained herein is licensed under the GNU General Public
* License. You may obtain a copy of the GNU General Public License
* Version 2 or later at the following locations:
*
* http://www.opensource.org/licenses/gpl-license.html
* http://www.gnu.org/copyleft/gpl.html
*/
/*
* @file mxc_v4l2_capture.c
*
* @brief Mxc Video For Linux 2 driver test application
*
*/
#ifdef __cplusplus
extern "C"{
#endif
/*=======================================================================
INCLUDE FILES
=======================================================================*/
/* Standard Include Files */
#include
/* Verification Test Environment Include Files */
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
struct v4l2_mxc_offset {
uint32_t u_offset;
uint32_t v_offset;
};
#define TEST_BUFFER_NUM 3
struct testbuffer
{
unsigned char *start;
size_t offset;
unsigned int length;
};
struct testbuffer buffers[TEST_BUFFER_NUM];
int g_in_width = 176;
int g_in_height = 144;
int g_out_width = 176;
int g_out_height = 144;
int g_top = 0;
int g_left = 0;
int g_input = 0;
int g_capture_count = 100;
int g_rotate = 0;
int g_cap_fmt = V4L2_PIX_FMT_YUV420;
int g_camera_framerate = 30;
int g_extra_pixel = 0;
int g_capture_mode = 0;
int g_usb_camera = 0;
char g_v4l_device[100] = "/dev/video0";
static void print_pixelformat(char *prefix, int val)
{
printf("%s: %c%c%c%c
", prefix ? prefix : "pixelformat",
val & 0xff,
(val >> 8) & 0xff,
(val >> 16) & 0xff,
(val >> 24) & 0xff);
}
int start_capturing(int fd_v4l)
{
unsigned int i;
struct v4l2_buffer buf;
enum v4l2_buf_type type;
for (i = 0; i < TEST_BUFFER_NUM; i++)
{
memset(&buf, 0, sizeof (buf));
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
buf.memory = V4L2_MEMORY_MMAP;
buf.index = i;
if (ioctl(fd_v4l, VIDIOC_QUERYBUF, &buf) < 0)
{
printf("VIDIOC_QUERYBUF error
");
return -1;
}
buffers[i].length = buf.length;
buffers[i].offset = (size_t) buf.m.offset;
buffers[i].start = mmap (NULL, buffers[i].length,
PROT_READ | PROT_WRITE, MAP_SHARED,
fd_v4l, buffers[i].offset);
memset(buffers[i].start, 0xFF, buffers[i].length);
}
for (i = 0; i < TEST_BUFFER_NUM; i++)
{
memset(&buf, 0, sizeof (buf));
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
buf.memory = V4L2_MEMORY_MMAP;
buf.index = i;
buf.m.offset = buffers[i].offset;
if (g_extra_pixel){
buf.m.offset += g_extra_pixel *
(g_out_width + 2 * g_extra_pixel) + g_extra_pixel;
}
if (ioctl (fd_v4l, VIDIOC_QBUF, &buf) < 0) {
printf("VIDIOC_QBUF error
");
return -1;
}
}
type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
if (ioctl (fd_v4l, VIDIOC_STREAMON, &type) < 0) {
printf("VIDIOC_STREAMON error
");
return -1;
}
return 0;
}
int stop_capturing(int fd_v4l)
{
enum v4l2_buf_type type;
type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
return ioctl (fd_v4l, VIDIOC_STREAMOFF, &type);
}
int v4l_capture_setup(void)
{
struct v4l2_format fmt;
struct v4l2_control ctrl;
struct v4l2_streamparm parm;
struct v4l2_crop crop;
int fd_v4l = 0;
struct v4l2_mxc_offset off;
struct v4l2_dbg_chip_ident chip;
struct v4l2_frmsizeenum fsize;
struct v4l2_fmtdesc ffmt;
if ((fd_v4l = open(g_v4l_device, O_RDWR, 0)) < 0)
{
printf("Unable to open %s
", g_v4l_device);
return 0;
}
/* UVC driver does not support this ioctl */
if (g_usb_camera != 1) {
if (ioctl(fd_v4l, VIDIOC_DBG_G_CHIP_IDENT, &chip))
{
printf("VIDIOC_DBG_G_CHIP_IDENT failed.
");
return -1;
}
printf("sensor chip is %s
", chip.match.name);
}
printf("sensor supported frame size:
");
fsize.index = 0;
while (ioctl(fd_v4l, VIDIOC_ENUM_FRAMESIZES, &fsize) >= 0) {
printf(" %dx%d
", fsize.discrete.width,
fsize.discrete.height);
fsize.index++;
}
ffmt.index = 0;
while (ioctl(fd_v4l, VIDIOC_ENUM_FMT, &ffmt) >= 0) {
print_pixelformat("sensor frame format", ffmt.pixelformat);
ffmt.index++;
}
parm.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
parm.parm.capture.timeperframe.numerator = 1;
parm.parm.capture.timeperframe.denominator = g_camera_framerate;
parm.parm.capture.capturemode = g_capture_mode;
if (ioctl(fd_v4l, VIDIOC_S_PARM, &parm) < 0)
{
printf("VIDIOC_S_PARM failed
");
return -1;
}
if (ioctl(fd_v4l, VIDIOC_S_INPUT, &g_input) < 0)
{
printf("VIDIOC_S_INPUT failed
");
return -1;
}
/* UVC driver does not implement CROP */
if (g_usb_camera != 1) {
crop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
if (ioctl(fd_v4l, VIDIOC_G_CROP, &crop) < 0)
{
printf("VIDIOC_G_CROP failed
");
return -1;
}
crop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
crop.c.width = g_in_width;
crop.c.height = g_in_height;
crop.c.top = g_top;
crop.c.left = g_left;
if (ioctl(fd_v4l, VIDIOC_S_CROP, &crop) < 0)
{
printf("VIDIOC_S_CROP failed
");
return -1;
}
}
fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
fmt.fmt.pix.pixelformat = g_cap_fmt;
fmt.fmt.pix.width = g_out_width;
fmt.fmt.pix.height = g_out_height;
if (g_extra_pixel){
off.u_offset = (2 * g_extra_pixel + g_out_width) * (g_out_height + g_extra_pixel)
- g_extra_pixel + (g_extra_pixel / 2) * ((g_out_width / 2)
+ g_extra_pixel) + g_extra_pixel / 2;
off.v_offset = off.u_offset + (g_extra_pixel + g_out_width / 2) *
((g_out_height / 2) + g_extra_pixel);
fmt.fmt.pix.bytesperline = g_out_width + g_extra_pixel * 2;
fmt.fmt.pix.priv = (uint32_t) &off;
fmt.fmt.pix.sizeimage = (g_out_width + g_extra_pixel * 2 )
* (g_out_height + g_extra_pixel * 2) * 3 / 2;
} else {
fmt.fmt.pix.bytesperline = g_out_width;
fmt.fmt.pix.priv = 0;
fmt.fmt.pix.sizeimage = 0;
}
if (ioctl(fd_v4l, VIDIOC_S_FMT, &fmt) < 0)
{
printf("set format failed
");
return 0;
}
/*
* Set rotation
* It's mxc-specific definition for rotation.
*/
if (g_usb_camera != 1) {
ctrl.id = V4L2_CID_PRIVATE_BASE + 0;
ctrl.value = g_rotate;
if (ioctl(fd_v4l, VIDIOC_S_CTRL, &ctrl) < 0)
{
printf("set ctrl failed
");
return 0;
}
}
struct v4l2_requestbuffers req;
memset(&req, 0, sizeof (req));
req.count = TEST_BUFFER_NUM;
req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
req.memory = V4L2_MEMORY_MMAP;
if (ioctl(fd_v4l, VIDIOC_REQBUFS, &req) < 0)
{
printf("v4l_capture_setup: VIDIOC_REQBUFS failed
");
return 0;
}
return fd_v4l;
}
int v4l_capture_test(int fd_v4l, const char * file)
{
struct v4l2_buffer buf;
#if TEST_OUTSYNC_ENQUE
struct v4l2_buffer temp_buf;
#endif
struct v4l2_format fmt;
FILE * fd_y_file = 0;
int count = g_capture_count;
if ((fd_y_file = fopen(file, "wb")) ==NULL)
{
printf("Unable to create y frame recording file
");
return -1;
}
fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
if (ioctl(fd_v4l, VIDIOC_G_FMT, &fmt) < 0)
{
printf("get format failed
");
return -1;
}
else
{
printf(" Width = %d", fmt.fmt.pix.width);
printf(" Height = %d", fmt.fmt.pix.height);
printf(" Image size = %d
", fmt.fmt.pix.sizeimage);
print_pixelformat(0, fmt.fmt.pix.pixelformat);
}
if (start_capturing(fd_v4l) < 0)
{
printf("start_capturing failed
");
return -1;
}
while (count-- > 0) {
memset(&buf, 0, sizeof (buf));
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
buf.memory = V4L2_MEMORY_MMAP;
if (ioctl (fd_v4l, VIDIOC_DQBUF, &buf) < 0) {
printf("VIDIOC_DQBUF failed.
");
}
fwrite(buffers[buf.index].start, fmt.fmt.pix.sizeimage, 1, fd_y_file);
#if TEST_OUTSYNC_ENQUE
/* Testing out of order enque */
if (count == 25) {
temp_buf = buf;
printf("buf.index %d
", buf.index);
continue;
}
if (count == 15) {
if (ioctl (fd_v4l, VIDIOC_QBUF, &temp_buf) < 0) {
printf("VIDIOC_QBUF failed
");
break;
}
}
#endif
if (count >= TEST_BUFFER_NUM) {
if (ioctl (fd_v4l, VIDIOC_QBUF, &buf) < 0) {
printf("VIDIOC_QBUF failed
");
break;
}
}
else
printf("buf.index %d
", buf.index);
}
if (stop_capturing(fd_v4l) < 0)
{
printf("stop_capturing failed
");
return -1;
}
fclose(fd_y_file);
close(fd_v4l);
return 0;
}
int process_cmdline(int argc, char **argv)
{
int i;
for (i = 1; i < argc; i++) {
if (strcmp(argv[i], "-iw") == 0) {
g_in_width = atoi(argv[++i]);
}
else if (strcmp(argv[i], "-ih") == 0) {
g_in_height = atoi(argv[++i]);
}
else if (strcmp(argv[i], "-ow") == 0) {
g_out_width = atoi(argv[++i]);
}
else if (strcmp(argv[i], "-oh") == 0) {
g_out_height = atoi(argv[++i]);
}
else if (strcmp(argv[i], "-t") == 0) {
g_top = atoi(argv[++i]);
}
else if (strcmp(argv[i], "-l") == 0) {
g_left = atoi(argv[++i]);
}
else if (strcmp(argv[i], "-i") == 0) {
g_input = atoi(argv[++i]);
}
else if (strcmp(argv[i], "-r") == 0) {
g_rotate = atoi(argv[++i]);
}
else if (strcmp(argv[i], "-c") == 0) {
g_capture_count = atoi(argv[++i]);
}
else if (strcmp(argv[i], "-fr") == 0) {
g_camera_framerate = atoi(argv[++i]);
}
else if (strcmp(argv[i], "-e") == 0) {
g_extra_pixel = atoi(argv[++i]);
}
else if (strcmp(argv[i], "-m") == 0) {
g_capture_mode = atoi(argv[++i]);
}
else if (strcmp(argv[i], "-d") == 0) {
strcpy(g_v4l_device, argv[++i]);
}
else if (strcmp(argv[i], "-f") == 0) {
i++;
g_cap_fmt = v4l2_fourcc(argv[i][0], argv[i][1],argv[i][2],argv[i][3]);
if ( (g_cap_fmt != V4L2_PIX_FMT_BGR24) &&
(g_cap_fmt != V4L2_PIX_FMT_BGR32) &&
(g_cap_fmt != V4L2_PIX_FMT_RGB565) &&
(g_cap_fmt != V4L2_PIX_FMT_NV12) &&
(g_cap_fmt != V4L2_PIX_FMT_YUV422P) &&
(g_cap_fmt != V4L2_PIX_FMT_UYVY) &&
(g_cap_fmt != V4L2_PIX_FMT_YUYV) &&
(g_cap_fmt != V4L2_PIX_FMT_YVU420) &&
(g_cap_fmt != V4L2_PIX_FMT_YUV420) )
{
return -1;
}
}
else if (strcmp(argv[i], "-uvc") == 0) {
g_usb_camera = 1;
}
else if (strcmp(argv[i], "-help") == 0) {
printf("MXC Video4Linux capture Device Test
"
"Syntax: mxc_v4l2_capture.out -iw
"
" -ih
"
" -ow
"
" -oh
"
" -t
"
" -l
"
" -i prp_enc->mem, 1-use csi->mem>
"
" -r -c
"
" -e
"
" -m
"
" -d
"
" -uvc (for USB camera test)
"
" -f -fr
");
return -1;
}
}
printf("in_width = %d, in_height = %d
", g_in_width, g_in_height);
printf("out_width = %d, out_height = %d
", g_out_width, g_out_height);
printf("top = %d, left = %d
", g_top, g_left);
if ((g_in_width == 0) || (g_in_height == 0)) {
return -1;
}
return 0;
}
int main(int argc, char **argv)
{
int fd_v4l;
if (process_cmdline(argc, argv) < 0) {
return -1;
}
fd_v4l = v4l_capture_setup();
return v4l_capture_test(fd_v4l, argv[argc-1]);
}
执行应用程序所使用的命令如下:
xxxxxxxxxx
后面再补充