i don`t know this issue.
anyone help me.
r7 = C004ED84 r6 = C0B1C5A0 r5 = 00000000 r4 = C5626000
[<c0053968>] (do_exit+0x0/0xda0) from [<c003b6a8>] (die+0x350/0x3a0)
[<c003b358>] (die+0x0/0x3a0) from [<c003dcec>] (__do_kernel_fault+0x6c/0x7c)
[<c003dc80>] (__do_kernel_fault+0x0/0x7c) from [<c003df88>] (do_page_fault+0x1d4/0x1ec)
r7 = 00000000 r6 = C0B1C5A0 r5 = C56279DC r4 = 00000017
[<c003ddb4>] (do_page_fault+0x0/0x1ec) from [<c003e0ec>] (do_DataAbort+0x40/0xa4)
[<c003e0ac>] (do_DataAbort+0x0/0xa4) from [<c0035728>] (__dabt_svc+0x48/0x60)
r8 = 00000000 r7 = 00000000 r6 = C0B1C5A0 r5 = C56279DC
r4 = FFFFFFFF
[<c004ed48>] (mm_release+0x0/0x80) from [<c0053a7c>] (do_exit+0x114/0xda0)
r7 = C004ED84 r6 = C0B1C5A0 r5 = 00000000 r4 = C5626000
[<c0053968>] (do_exit+0x0/0xda0) from [<c003b6a8>] (die+0x350/0x3a0)
[<c003b358>] (die+0x0/0x3a0) from [<c003dcec>] (__do_kernel_fault+0x6c/0x7c)
[<c003dc80>] (__do_kernel_fault+0x0/0x7c) from [<c003df88>] (do_page_fault+0x1d4/0x1ec)
r7 = 00000000 r6 = C0B1C5A0 r5 = C5627B0C r4 = 00000017
[<c003ddb4>] (do_page_fault+0x0/0x1ec) from [<c003e0ec>] (do_DataAbort+0x40/0xa4)
[<c003e0ac>] (do_DataAbort+0x0/0xa4) from [<c0035728>] (__dabt_svc+0x48/0x60)
r8 = 00000000 r7 = 00000000 r6 = C0B1C5A0 r5 = C5627B0C
r4 = FFFFFFFF
[<c004ed48>] (mm_release+0x0/0x80) from [<c0053a7c>] (do_exit+0x114/0xda0)
r7 = C004ED84 r6 = C0B1C5A0 r5 = 00000000 r4 = C5626000
[<c0053968>] (do_exit+0x0/0xda0) from [<c003b6a8>] (die+0x350/0x3a0)
[<c003b358>] (die+0x0/0x3a0) from [<c003dcec>] (__do_kernel_fault+0x6c/0x7c)
[<c003dc80>] (__do_kernel_fault+0x0/0x7c) from [<c003df88>] (do_page_fault+0x1d4/0x1ec)
r7 = 00000000 r6 = C0B1C5A0 r5 = C5627C3C r4 = 00000017
[<c003ddb4>] (do_page_fault+0x0/0x1ec) from [<c003e0ec>] (do_DataAbort+0x40/0xa4)
[<c003e0ac>] (do_DataAbort+0x0/0xa4) from [<c0035728>] (__dabt_svc+0x48/0x60)
r8 = 00000000 r7 = 00000000 r6 = C0B1C5A0 r5 = C5627C3C
r4 = FFFFFFFF
[<c004ed48>] (mm_release+0x0/0x80) from [<c0053a7c>] (do_exit+0x114/0xda0)
r7 = C0087378 r6 = C0B1C5A0 r5 = 00000000 r4 = C5626000
[<c0053968>] (do_exit+0x0/0xda0) from [<c003b6a8>] (die+0x350/0x3a0)
[<c003b358>] (die+0x0/0x3a0) from [<c003dcec>] (__do_kernel_fault+0x6c/0x7c)
[<c003dc80>] (__do_kernel_fault+0x0/0x7c) from [<c003df88>] (do_page_fault+0x1d4/0x1ec)
r7 = 00000000 r6 = C0B1C5A0 r5 = C5627D6C r4 = 00000817
[<c003ddb4>] (do_page_fault+0x0/0x1ec) from [<c003e0ec>] (do_DataAbort+0x40/0xa4)
[<c003e0ac>] (do_DataAbort+0x0/0xa4) from [<c0035728>] (__dabt_svc+0x48/0x60)
r8 = C513F178 r7 = 00004000 r6 = C03D0D20 r5 = C5627D6C
r4 = FFFFFFFF
[<c0087330>] (page_remove_rmap+0x0/0x74) from [<c00803bc>] (unmap_vmas+0x3a0/0x550)
[<c008001c>] (unmap_vmas+0x0/0x550) from [<c0085330>] (exit_mmap+0x7c/0x178)
[<c00852b4>] (exit_mmap+0x0/0x178) from [<c004ec08>] (mmput+0x44/0x104)
r7 = C5695D70 r6 = C0B1C5A0 r5 = C5695D40 r4 = C5695D40
[<c004ebc4>] (mmput+0x0/0x104) from [<c0053b74>] (do_exit+0x20c/0xda0)
r4 = C5626000
[<c0053968>] (do_exit+0x0/0xda0) from [<c0054824>] (sys_exit_group+0x0/0x1c)
[<c0054744>] (do_group_exit+0x0/0xe0) from [<c005eaac>] (get_signal_to_deliver+0x51c/0x564)
r5 = 0000000B r4 = C5626000
[<c005e590>] (get_signal_to_deliver+0x0/0x564) from [<c0039ee0>] (do_signal+0x78/0x538)
[<c0039e68>] (do_signal+0x0/0x538) from [<c0035bac>] (work_pending+0x1c/0x24)
Code: ebfff9cd e5954114 e3540000 0a00000e (e5973024)
<6>note: app[1001] exited with preempt_count 1
Unable to handle kernel NULL pointer dereference at virtual address 00000024
pgd = c0004000
[00000024] *pgd=00000000
Internal error: Oops: 17 [#23]
Modules linked in: dm350mmap cmemk
CPU: 0
PC is at mm_release+0x3c/0x80
LR is at do_exit+0x114/0xda0
pc : [<c004ed84>] lr : [<c0053a7c>] Not tainted
sp : c5626360 ip : c5626388 fp : c5626384
r10: 0000000b r9 : 00000008 r8 : 00000000
r7 : 00000000 r6 : c0b1c5a0 r5 : c0b1c5a0 r4 : 40018520
r3 : ffffffea r2 : c048fa60 r1 : 00000000 r0 : 00000000
Flags: nzCv IRQs on FIQs on Mode SVC_32 Segment user
Control: 5317F Table: 80EF0000 DAC: 00000015
Process app (pid: 1001, stack limit = 0xc56261a0)
---------------------------------------------------------------------
// ======== app.c ========
#include <xdc/std.h>
#include <ti/sdo/ce/Engine.h>
#include <ti/sdo/ce/osal/Memory.h>
//#include <ti/sdo/ce/image/imgdec.h>
//#include <ti/sdo/ce/image/imgenc.h>
#include <ti/sdo/ce/image1/imgenc1.h>
#include <ti/sdo/ce/trace/gt.h>
#include <stdio.h>
#include <fcntl.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <pthread.h>
#include <sys/mman.h>
#include <sys/ioctl.h>
#include <asm/types.h>
#include <linux/videodev2.h>
#include <linux/fb.h>
#include <signal.h>
#include <sys/time.h>
#include <time.h>
#include <sys/file.h>
#include <fcntl.h>
// Davinci specific kernel headers
#include <media/davinci/davinci_vpfe.h>
#include <media/davinci/tvp5146.h>
//#include <video/davincifb.h>
// ************************************************************************
// Defined Macros
// ************************************************************************
//#define DEBUG_PRINT // Enables or disables debug output
//#define TIMING
#ifdef DEBUG_PRINT
#define DBG(fmt, args...) fprintf(stderr, "Encode Debug: " fmt, ## args)
#else
#define DBG(fmt, args...)
#endif
// always print error message
#define ERR(fmt, args...) fprintf(stderr, "Encode Error: " fmt, ## args)
// video capture device
#define V4L2_DEVICE "/dev/video0"
// Black color in UYVY format
#define UYVY_BLACK 0x10801080
// Scaling factors for the video standards
#define NOSTD 0
#define PALSTD 12
#define NTSCSTD 10
#define NUM_BUFS 3
// Frame size information
int D1_WIDTH = 720;
int D1_HEIGHT = 480;
int D1_FRAME_PIXELS = 345600; // 720*480;
int D1_FRAME_SIZE = 691200; // 720*480*2
// ************************************************************************
// Defined Data Structures
// ************************************************************************
typedef struct {
unsigned int numBufs;
char *bufs[3];
int bufSizes[3];
} BufferDesc;
// Describes a capture frame buffer
typedef struct VideoBuffer {
void *start;
size_t length;
} VideoBuffer;
// *************************************************************************
// Global variabls
// *************************************************************************
// engine name and codec name
static String encoderName = "jpegenc";
static String engineName = "image";
// buffer descriptor
BufferDesc inBufs;
BufferDesc outBufs;
// XDM buffer descriptor
XDM1_BufDesc inBufDesc;
XDM1_BufDesc outBufDesc;
// XDM input/output args
IMGENC1_InArgs inArgs;
IMGENC1_OutArgs outArgs;
// image parameters
IMGENC1_Params imgParams = {
sizeof(IMGENC1_Params), // size
480, // maxHeight
720, // maxWidth
3, // maxScans
XDM_DEFAULT, // dataEndianness
XDM_YUV_422ILE // forceChromaFormat
};
// image dynamic parameters
IMGENC1_DynamicParams dynParams = {
sizeof(IMGENC1_DynamicParams), // size
0, // numAU
XDM_YUV_422ILE, // inputChromaFormat
480, // inputHeight
720, // inputWidth
0, // captureWidth
XDM_ENCODE_AU, // generateHeader
73 // qValue
};
// status
IMGENC1_Status imgStatus;
// engine and codec handle
Engine_Handle ce;
IMGENC1_Handle enc;
// input/output files and file pointers
char outFile[] = "image1.jpg";
char outFile1[] = "image10.jpg";
char qFile[] = "Qfile";
FILE *outFp;
FILE *qFp;
// pointer to video capture buffer managerment structure
VideoBuffer *vidBufs;
// input capture device handler
int inputFd;
int numVidBufs;
#ifdef TIMING
struct timeval ts;
struct timeval te;
int numFramesToTiming = 1000;
#endif
// *************************************************************************
// Function declarations
// *************************************************************************
int initCaptureDevice( VideoBuffer **vidBufsPtr, int *numVidBufsPtr,
int svideoInput, int captureWidth, int captureHeight);
void cleanupCaptureDevice(int fd, VideoBuffer *vidBufs, int numVidBufs);
void cleanup();
void INThandler( int sig );
// ======== smain ========
Int smain(Int argc, String argv[]) {
int i,j, imgIdx;
#ifdef TIMING
int numFrames = 0;
double t1, t2;
#endif
XDAS_Int32 status;
struct v4l2_buffer v4l2buf;
if ( argc > 1 && !strcmp(argv[1], "-PAL") ) {
D1_HEIGHT = 576;
D1_FRAME_PIXELS = 414720; // 720*576;
D1_FRAME_SIZE = 829440; // 720*576*2
imgParams.maxHeight = D1_HEIGHT;
dynParams.inputHeight = D1_HEIGHT;
DBG( "App-> Application started for PAL signal.\n");
} else {
DBG( "App-> Application started for NTSC signal.\n");
}
// init variables;
ce = NULL;
enc = NULL;
imgStatus.size = sizeof(IMGENC1_Status);
outFp = NULL;
qFp = NULL;
inArgs.size = sizeof(IMGENC1_InArgs);
outArgs.size = sizeof(IMGENC1_OutArgs);
// out bufers
outBufs.numBufs = outBufDesc.numBufs = 1;
outBufs.bufs[0] = NULL;
outBufs.bufSizes[0] = D1_FRAME_PIXELS*3;
/*outBufDesc.bufSizes = outBufs.bufSizes;
outBufDesc.bufs = outBufs.bufs;
*/
outBufDesc.descs[0].bufSize = (XDAS_Int32*)outBufs.bufSizes;
outBufDesc.descs[0].buf = (XDAS_Int8**)outBufs.bufs;
// init capture device
inputFd = initCaptureDevice( &vidBufs, &numVidBufs, FALSE,
D1_WIDTH, D1_HEIGHT );
if (inputFd == -1) {
goto end;
}
inBufs.numBufs = inBufDesc.numBufs = 1;
inBufs.bufSizes[0] = D1_FRAME_PIXELS<<1;
/*inBufDesc.bufSizes = inBufs.bufSizes;
inBufDesc.bufs = inBufs.bufs;
*/
inBufDesc.descs[0].bufSize = (XDAS_Int32*)inBufs.bufSizes;
inBufDesc.descs[0].buf = (XDAS_Int8**)inBufs.bufs;
// allocate output buffer
outBufs.bufs[0] = Memory_contigAlloc( outBufs.bufSizes[0],
Memory_DEFAULTALIGNMENT );
DBG("alloc outbuf 0x%x, %d\n", outBufs.bufs[0], outBufs.bufSizes[0] );
if ( outBufs.bufs[0] == NULL ) {
ERR("Failed to allocate contiguous memory block for output.\n");
goto end;
}
// reset, load, and start DSP Engine
ce = Engine_open(engineName, NULL, NULL );
if ( ce == NULL ) {
ERR("error: can't open engine %s\n", engineName);
goto end;
}
// allocate and initialize image encoder on the engine
enc = IMGENC1_create( ce, encoderName, &imgParams );
if ( enc == NULL ) {
ERR("error: can't open codec %s\n", encoderName);
goto end;
}
status = IMGENC1_control( enc, XDM_SETPARAMS,
(IMGENC1_DynamicParams*)(&dynParams),
(IMGENC1_Status*)(&imgStatus) );
if ( status == IALG_EFAIL ) {
ERR("error: can't set dyn params 0x%x\n", (int)(imgStatus.extendedError) );
goto end;
}
status = IMGENC1_control( enc, XDM_GETBUFINFO,
(IMGENC1_DynamicParams*)(&dynParams),
(IMGENC1_Status*)(&imgStatus) );
if ( status != IMGENC1_EOK ) {
ERR("error: can't get buf info 0x%x\n", (int)(imgStatus.extendedError) );
goto end;
}
DBG( "min inBuf num: %d\n", imgStatus.bufInfo.minNumInBufs );
for ( j = 0; j < imgStatus.bufInfo.minNumInBufs; j++ ) {
DBG( "inBuf[%d] size %d\n", j, imgStatus.bufInfo.minInBufSize[j] );
}
DBG( "min outBuf num: %d\n", imgStatus.bufInfo.minNumOutBufs );
for ( j = 0; j < imgStatus.bufInfo.minNumOutBufs; j++ ) {
DBG( "outBuf[%d] size %d\n", j, imgStatus.bufInfo.minOutBufSize[j] );
}
// ctrlC will terminate and clean up
signal( SIGINT, INThandler );
i = 0;
imgIdx = 1;
#ifdef TIMING
gettimeofday( &ts, NULL );
#endif
while ( 1 ) {
DBG("process frame %d\n", i++ );
// open file streams for output
if ( imgIdx >= 10 ) {
j = imgIdx/10;
outFile1[5] = '0'+j;
outFile1[6] = '0'+ imgIdx-j*10;
if ( (outFp = fopen(outFile1, "wb") ) == NULL) {
ERR( "App-> : can't write to file %s\n", outFile1 );
goto end;
}
}else {
outFile[5] = '0'+imgIdx;
if ( (outFp = fopen(outFile, "wb") ) == NULL) {
ERR( "App-> ERROR: can't write to file %s\n", outFile );
goto end;
}
}
imgIdx++;
if ( D1_HEIGHT == 480 ) {
if ( imgIdx > 30 ) {
imgIdx = 1;
qFp = fopen( qFile, "rb" );
if ( qFp ) {
status = fread( &j, 1, 1, qFp );
if ( status == 1 && j > 1 && j <= 100 )
dynParams.qValue = j;
fclose(qFp);
qFp = 0;
}
}
} else {
if ( imgIdx > 25 ) {
imgIdx = 1;
qFp = fopen( qFile, "rb" );
if ( qFp ) {
status = fread( &j, 1, 1, qFp );
if ( status == 1 && j > 1 && j <= 100 )
dynParams.qValue = j;
fclose(qFp);
qFp = 0;
}
}
}
// lock the file
do {
j = lockf( fileno(outFp), F_LOCK, 0 );
if ( !j )
break;
sleep ( 1 );
} while ( 1 );
// Get a frame buffer with captured data
memset( &v4l2buf, 0, sizeof(v4l2buf) );
v4l2buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
v4l2buf.memory = V4L2_MEMORY_MMAP;
if ( ioctl(inputFd, VIDIOC_DQBUF, &v4l2buf) == -1 ) {
if (errno == EAGAIN) {
continue;
}
ERR("VIDIOC_DQBUF failed (%s)\n", strerror(errno) );
goto end;
}
inBufs.bufs[0] = vidBufs[v4l2buf.index].start;
// Encode
status = IMGENC1_process( enc, &inBufDesc, &outBufDesc, &inArgs, &outArgs);
if ( status != IMGENC1_EOK ) {
ERR( "IMGENC_process() failed with a fatal error (%ld ext: %#lx\n",
status, outArgs.extendedError);
goto end;
}
// Issue captured frame buffer back to device driver
if (ioctl(inputFd, VIDIOC_QBUF, &v4l2buf) == -1) {
ERR("VIDIOC_QBUF failed (%s)\n", strerror(errno));
goto end;
}
DBG( "%d bytes generated\n", outArgs.bytesGenerated );
status = fwrite( outBufs.bufs[0], 1, outArgs.bytesGenerated, outFp );
fclose( outFp );
outFp = 0;
status = IMGENC1_control( enc, XDM_SETPARAMS,
(IMGENC1_DynamicParams*)(&dynParams),
(IMGENC1_Status*)(&imgStatus) );
if ( status == IALG_EFAIL ) {
ERR("error: can't set dyn params 0x%x\n", (int)(imgStatus.extendedError) );
goto end;
}
// usleep( 5000 );
#ifdef TIMING
numFrames++;
if ( numFrames >= numFramesToTiming ) {
gettimeofday( &te, NULL );
printf("%d frames encoded\n", numFramesToTiming );
t1 = ts.tv_sec*1000.0 + (ts.tv_usec/1000.0);
t2 = te.tv_sec*1000.0 + (te.tv_usec/1000.0);
t2 -= t1;
printf("Total time: %.3f ms, Average: %.3fms\n",
t2, t2/numFramesToTiming );
cleanup();
break;
}
#endif
}
end:
return (0);
}
void cleanup() {
// teardown the codecs
if (enc) {
DBG("delete encode\n");
IMGENC1_delete(enc);
}
// close the engine
if (ce) {
DBG("delete engine\n");
Engine_close(ce);
}
// close the files
if ( outFp ) {
DBG("close outfp\n" );
fclose(outFp);
}
if ( qFp ) {
DBG("close qFp\n");
fclose( qFp );
}
if ( outBufs.bufs[0] ) {
DBG("free outbuf 0x%x, %d\n", outBufs.bufs[0], outBufs.bufSizes[0] );
Memory_contigFree( outBufs.bufs[0], outBufs.bufSizes[0] );
}
if ( inputFd != -1 ) {
DBG("clean capture device\n");
cleanupCaptureDevice(inputFd, vidBufs, numVidBufs );
}
DBG("app done.\n");
}
void INThandler( int sig ) {
cleanup();
exit(0);
}
// initCaptureDevice
int initCaptureDevice( VideoBuffer **vidBufsPtr, int *numVidBufsPtr,
int svideoInput, int captureWidth, int captureHeight) {
struct v4l2_requestbuffers req;
struct v4l2_capability cap;
struct v4l2_cropcap cropCap;
struct v4l2_crop crop;
struct v4l2_format fmt;
struct v4l2_buffer buf;
enum v4l2_buf_type type;
v4l2_std_id std;
int input;
int fd;
int ret;
VideoBuffer *buffers;
int numBufs;
DBG("captureWidth = %d, captureHeight = %d\n", captureWidth, captureHeight);
// Open video capture device
fd = open(V4L2_DEVICE, O_RDWR | O_NONBLOCK, 0);
if (fd == -1) {
ERR("Cannot open %s (%s)\n", V4L2_DEVICE, strerror(errno));
return -1;
}
// Select the video input
if (svideoInput == TRUE) {
input = TVP5146_AMUX_SVIDEO;
} else {
input = TVP5146_AMUX_COMPOSITE;
}
if (ioctl(fd, VIDIOC_S_INPUT, &input) == -1) {
ERR("Failed to set video input to %d\n", input);
return -1;
}
DBG("Set the capture input to id %d\n", input);
// Query for capture device capabilities
if (ioctl(fd, VIDIOC_QUERYCAP, &cap) == -1) {
if (errno == EINVAL) {
ERR("%s is no V4L2 device\n", V4L2_DEVICE);
return -1;
}
ERR("Failed VIDIOC_QUERYCAP on %s (%s)\n", V4L2_DEVICE,
strerror(errno));
return -1;
}
if (!(cap.capabilities & V4L2_CAP_VIDEO_CAPTURE)) {
ERR("%s is no video capture device\n", V4L2_DEVICE);
return -1;
}
if (!(cap.capabilities & V4L2_CAP_STREAMING)) {
ERR("%s does not support streaming i/o\n", V4L2_DEVICE);
return -1;
}
cropCap.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
if (ioctl(fd, VIDIOC_CROPCAP, &cropCap) == -1) {
ERR("VIDIOC_CROPCAP failed %d, %s\n", errno, strerror(errno));
return -1;
}
// Auto detect PAL or NTSC using the capture driver as sanity check
std = VPFE_STD_AUTO;
if(ioctl(fd, VIDIOC_S_STD, &std) == -1) {
ERR( "VIDIOC_S_STD (auto) failed on %s (%s)\n", V4L2_DEVICE,
strerror(errno));
return -1;
}
DBG("Checking video standard\n");
do {
ret = ioctl(fd, VIDIOC_QUERYSTD, &std);
} while (ret == -1 && errno == EAGAIN);
if (ret == -1) {
ERR("VIDIOC_QUERYSTD failed on %s (%s)\n", V4L2_DEVICE,
strerror(errno));
return -1;
}
switch (std) {
case V4L2_STD_NTSC:
DBG("NTSC camera detected\n");
if ( captureHeight == 576 ) {
ERR("NTSC camera connected but PAL selected.\n");
return -1;
}
break;
case V4L2_STD_PAL:
DBG("PAL camera detected\n");
if ( captureHeight == 480 ) {
ERR("PAL camera connected but NTSC selected.\n");
return -1;
}
break;
default:
ERR("Camera (%s) using unsupported video standard\n", V4L2_DEVICE);
return -1;
}
if(ioctl(fd, VIDIOC_S_STD, &std) == -1) {
ERR("VIDIOC_S_STD failed on %s (%s)\n", V4L2_DEVICE,
strerror(errno));
return -1;
}
// Set the video capture image format
memset ( &fmt, 0, sizeof(fmt) );
fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
fmt.fmt.pix.width = D1_WIDTH;
fmt.fmt.pix.height = D1_HEIGHT;
fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_UYVY;
fmt.fmt.pix.field = V4L2_FIELD_INTERLACED;
DBG("Setting capture video format\n");
// Set the video capture format
if (ioctl(fd, VIDIOC_S_FMT, &fmt) == -1) {
ERR("VIDIOC_S_FMT failed on %s (%s)\n", V4L2_DEVICE,
strerror(errno));
return -1;
}
crop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
crop.c.left = D1_WIDTH / 2 - captureWidth / 2;
crop.c.top = D1_HEIGHT / 2 - captureHeight / 2;
crop.c.width = captureWidth;
crop.c.height = captureHeight;
DBG("Setting capture cropping (%dx%d)\n", crop.c.width, crop.c.height);
// Crop the image depending on requested image size
if (ioctl(fd, VIDIOC_S_CROP, &crop) == -1) {
ERR("VIDIOC_S_CROP failed %d, %s\n", errno, strerror(errno));
return -1;
}
DBG( "Capturing %dx%d video (cropped to %dx%d)\n",
fmt.fmt.pix.width, fmt.fmt.pix.height, crop.c.width, crop.c.height);
memset( &req, 0, sizeof(req) );
req.count = NUM_BUFS;
req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
req.memory = V4L2_MEMORY_MMAP;
// Allocate buffers in the capture device driver
if (ioctl(fd, VIDIOC_REQBUFS, &req) == -1) {
ERR("VIDIOC_REQBUFS failed on %s (%s)\n", V4L2_DEVICE,
strerror(errno));
return -1;
}
DBG("%d capture buffers were successfully allocated.\n", req.count);
if (req.count < NUM_BUFS) {
ERR("Insufficient buffer memory on %s\n", V4L2_DEVICE);
return -1;
}
buffers = calloc( req.count, sizeof(*buffers) );
if (!buffers) {
ERR("Failed to allocate memory for capture buffer structs.\n");
return -1;
}
// Map the allocated buffers to user space
for (numBufs = 0; numBufs < req.count; numBufs++) {
memset( &buf, 0, sizeof(buf) );
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
buf.memory = V4L2_MEMORY_MMAP;
buf.index = numBufs;
if (ioctl(fd, VIDIOC_QUERYBUF, &buf) == -1) {
ERR("Failed VIDIOC_QUERYBUF on %s (%s)\n", V4L2_DEVICE,
strerror(errno));
return -1;
}
buffers[numBufs].length = buf.length;
buffers[numBufs].start = mmap(NULL, buf.length,
PROT_READ | PROT_WRITE,
MAP_SHARED,
fd, buf.m.offset);
if (buffers[numBufs].start == MAP_FAILED) {
ERR("Failed to mmap buffer on %s (%s)\n", V4L2_DEVICE,
strerror(errno));
return -1;
}
DBG("Capture buffer %d mapped to address %#lx\n", numBufs,
(unsigned long) buffers[numBufs].start);
if (ioctl(fd, VIDIOC_QBUF, &buf) == -1) {
ERR("VIODIOC_QBUF failed on %s (%s)\n", V4L2_DEVICE,
strerror(errno));
return -1;
}
}
// Start the video streaming
type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
if (ioctl(fd, VIDIOC_STREAMON, &type) == -1) {
ERR("VIDIOC_STREAMON failed on %s (%s)\n", V4L2_DEVICE,
strerror(errno));
return -1;
}
*vidBufsPtr = buffers;
*numVidBufsPtr = numBufs;
return fd;
}
// cleanupCaptureDevice
void cleanupCaptureDevice(int fd, VideoBuffer *vidBufs, int numVidBufs) {
enum v4l2_buf_type type;
unsigned int i;
// Shut off the video capture
type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
if (ioctl(fd, VIDIOC_STREAMOFF, &type) == -1) {
ERR("VIDIOC_STREAMOFF failed (%s)\n", strerror(errno));
}
if (close(fd) == -1) {
ERR("Failed to close capture device (%s)\n", strerror(errno));
}
for (i = 0; i < numVidBufs; ++i) {
if (munmap(vidBufs[i].start, vidBufs[i].length) == -1) {
ERR("Failed to unmap capture buffer %d\n", i);
}
}
free(vidBufs);
}