Hello,
I am trying to change the output format of the VPE without closing the handle to the VPE. I am using the 04/2016 release of the Linux Processor SDK for the AM57XX EVM.
My goal is to do the following:
Open VPE -> Configure VPE -> Stream On -> Queue NV12 Frame -> VPE -> Deqeue NV12 Frame -> Stream Off -> Reconfigure VPE -> Stream On -> Queue NV12 Frame -> VPE -> Deqeue RGB24 -> Stream Off -> Cleanup
I've modified the vpetest.c main function but it always fails on the second call to allocBuffers at the "VIDIOC_S_FMT" ioctl call ( after describeFormat("rgb24") ).
The application prints:
Cant set color format : Device or resource busy
The linux console complains:
vpe 489d0000.vpe: queue busy
When I look in the driver source, I see that it still thinks the queue is busy:
if (vb2_is_busy(vq)) {
vpe_err(ctx->dev, "queue busy\n");
return -EBUSY;
}
/**
* vb2_is_busy() - return busy status of the queue
* @q: videobuf queue
*
* This function checks if queue has any buffers allocated.
*/
static inline bool vb2_is_busy(struct vb2_queue *q)
{
return (q->num_buffers > 0);
}
How can I change the format of the V4L2 Driver without closing the VPE and re-opening it? Thank you for any support.
Here is my modified code for vpetest.c:
int main ( int argc, char *argv[]) {
int i, ret = 0;
int srcHeight = 0, dstHeight = 0;
int srcWidth = 0, dstWidth = 0;
int srcSize = 0, dstSize = 0, srcSize_uv = 0, dstSize_uv = 0;
int srcFourcc = 0, dstFourcc = 0;
int src_coplanar = 0, dst_coplanar = 0;
enum v4l2_colorspace src_colorspace, dst_colorspace;
void *srcBuffers[1];
void *dstBuffers[1];
void *srcBuffers_uv[1];
void *dstBuffers_uv[1];
int src_numbuf = 1;
int dst_numbuf = 1;
int num_frames = 20;
int dequeued_frames = 0;
int interlace = 0;
int translen = 3;
struct v4l2_control ctrl;
struct v4l2_crop crop;
int field;
off_t file_size;
// Open input file in read only mode
fin = open ("/input.nv12", O_RDONLY);
srcWidth = 800;
srcHeight = 480;
describeFormat ("nv12", srcWidth, srcHeight, &srcSize, &srcFourcc, &src_coplanar, &src_colorspace);
// Open output file in write mode Create the file if not present
fout = open ("/output.nv12", O_WRONLY | O_CREAT | O_TRUNC, 777);
dstWidth = 800;
dstHeight = 480;
describeFormat ("nv12", dstWidth, dstHeight, &dstSize, &dstFourcc, &dst_coplanar, &dst_colorspace);
// no interlace
interlace = 0;
// Calculate number of frames
num_frames = 1;
// Debug
printf ("Input @ %d = %d x %d , %d\nOutput @ %d = %d x %d , %d\n",
fin, srcWidth, srcHeight, srcFourcc,
fout, dstWidth, dstHeight, dstFourcc);
/*************************************
Files are ready Now
*************************************/
// Open VPE
fd = open("/dev/video0",O_RDWR);
if(fd < 0) {
pexit("Cant open /device\n");
}
// Init device
memset(&ctrl, 0, sizeof(ctrl));
ctrl.id = V4L2_CID_TRANS_NUM_BUFS;
ctrl.value = translen;
ret = ioctl(fd, VIDIOC_S_CTRL, &ctrl);
if (ret < 0)
pexit("ioctl");
// Allocate buffers for input
ret = allocBuffers (V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, srcWidth,
srcHeight, src_coplanar, src_colorspace, &srcSize, &srcSize_uv,
srcFourcc, srcBuffers, srcBuffers_uv, &src_numbuf, interlace,
crop);
if(ret < 0) {
pexit("Cant Allocate buffurs for OUTPUT device\n");
}
// Allocate buffers for output
ret = allocBuffers (V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE, dstWidth,
dstHeight, dst_coplanar, dst_colorspace, &dstSize, &dstSize_uv,
dstFourcc, dstBuffers, dstBuffers_uv, &dst_numbuf, interlace,
crop);
if(ret < 0) {
pexit("Cant Allocate buffurs for CAPTURE device\n");
}
// Queue All empty buffers (Available to capture in)
ret = queueAllBuffers (V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE, dst_numbuf);
if(ret < 0) {
pexit("Error queueing buffers for CAPTURE device\n");
}
// Debug
printf ("Input Buffers = %d each of size %d\nOutput Buffers = %d each of size %d\n",
src_numbuf, srcSize, dst_numbuf, dstSize);
/*************************************
Driver is ready Now
*************************************/
// Read into the OUTPUT buffers from fin file
field = V4L2_FIELD_TOP;
for (i = 0; i < src_numbuf; i++) {
do_read("Y plane", fin, srcBuffers[i], srcSize);
if (src_coplanar)
do_read("UV plane", fin, srcBuffers_uv[i], srcSize_uv);
queue(V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, i, field, srcSize, srcSize_uv);
if (field == V4L2_FIELD_TOP)
field = V4L2_FIELD_BOTTOM;
else
field = V4L2_FIELD_TOP;
}
/*************************************
Data is ready Now
*************************************/
// Turn on streaming
streamON (V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE);
streamON (V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE);
// Convert the frame
fprintf(stderr,"Number frames: %d\n",num_frames);
while (num_frames) {
struct v4l2_buffer buf;
struct v4l2_plane buf_planes[2];
int last = num_frames == 1 ? 1 : 0;
dequeue(V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, &buf, buf_planes);
printf("dequeued source buffer with index %d\n", buf.index);
if (!last) {
do_read ("Y plane", fin, srcBuffers[buf.index], srcSize);
if (src_coplanar)
do_read ("UV plane", fin, srcBuffers_uv[buf.index], srcSize_uv);
queue(V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, buf.index, field, srcSize, srcSize_uv);
if (field == V4L2_FIELD_TOP)
field = V4L2_FIELD_BOTTOM;
else
field = V4L2_FIELD_TOP;
}
dequeue(V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE, &buf, buf_planes);
printf("dequeued dest buffer with index %d\n", buf.index);
printf("dequed_frames %d\n", ++dequeued_frames);
do_write("Y plane", fout, dstBuffers[buf.index], dstSize);
if (dst_coplanar)
do_write("UV plane", fout, dstBuffers_uv[buf.index], dstSize_uv);
if (!last)
queue(V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE, buf.index, V4L2_FIELD_NONE, dstSize, dstSize_uv);
num_frames--;
printf("frames left %d\n", num_frames);
}
// Driver cleanup
streamOFF (V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE);
streamOFF (V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE);
releaseBuffers (srcBuffers, src_numbuf, srcSize);
releaseBuffers (dstBuffers, dst_numbuf, dstSize);
if (src_coplanar)
releaseBuffers (srcBuffers_uv, src_numbuf, srcSize_uv);
if (dst_coplanar)
releaseBuffers (dstBuffers_uv, dst_numbuf, dstSize_uv);
// Open output file in write mode Create the file if not present
fout = open ("/test2.nv12", O_WRONLY | O_CREAT | O_TRUNC, 777);
describeFormat ("rgb24", dstWidth, dstHeight, &dstSize, &dstFourcc, &dst_coplanar, &dst_colorspace);
// Allocate input buffers
ret = allocBuffers (V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, srcWidth,
srcHeight, src_coplanar, src_colorspace, &srcSize, &srcSize_uv,
srcFourcc, srcBuffers, srcBuffers_uv, &src_numbuf, interlace,
crop);
if(ret < 0) {
pexit("Cant Allocate buffurs for OUTPUT device\n");
}
// Allocate output buffers
ret = allocBuffers (V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE, dstWidth,
dstHeight, dst_coplanar, dst_colorspace, &dstSize, &dstSize_uv,
dstFourcc, dstBuffers, dstBuffers_uv, &dst_numbuf, interlace,
crop);
if(ret < 0) {
pexit("Cant Allocate buffurs for CAPTURE device\n");
}
// Queue All empty buffers (Available to capture in)
ret = queueAllBuffers (V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE, dst_numbuf);
if(ret < 0) {
pexit("Error queueing buffers for CAPTURE device\n");
}
// Read in the data
field = V4L2_FIELD_TOP;
for (i = 0; i < src_numbuf; i++) {
do_read("Y plane", fin, srcBuffers[i], srcSize);
if (src_coplanar)
do_read("UV plane", fin, srcBuffers_uv[i], srcSize_uv);
queue(V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, i, field, srcSize, srcSize_uv);
if (field == V4L2_FIELD_TOP)
field = V4L2_FIELD_BOTTOM;
else
field = V4L2_FIELD_TOP;
}
// Enable streaming
streamON (V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE);
streamON (V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE);
// Convert the frames
num_frames = 1;
while (num_frames) {
struct v4l2_buffer buf;
struct v4l2_plane buf_planes[2];
int last = num_frames == 1 ? 1 : 0;
dequeue(V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, &buf, buf_planes);
printf("dequeued source buffer with index %d\n", buf.index);
if (!last) {
do_read ("Y plane", fin, srcBuffers[buf.index], srcSize);
if (src_coplanar)
do_read ("UV plane", fin, srcBuffers_uv[buf.index], srcSize_uv);
queue(V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, buf.index, field, srcSize, srcSize_uv);
if (field == V4L2_FIELD_TOP)
field = V4L2_FIELD_BOTTOM;
else
field = V4L2_FIELD_TOP;
}
dequeue(V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE, &buf, buf_planes);
printf("dequeued dest buffer with index %d\n", buf.index);
printf("dequed_frames %d\n", ++dequeued_frames);
do_write("Y plane", fout, dstBuffers[buf.index], dstSize);
if (dst_coplanar)
do_write("UV plane", fout, dstBuffers_uv[buf.index], dstSize_uv);
if (!last)
queue(V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE, buf.index, V4L2_FIELD_NONE, dstSize, dstSize_uv);
num_frames--;
printf("frames left %d\n", num_frames);
}
// Driver cleanup
streamOFF (V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE);
streamOFF (V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE);
releaseBuffers (srcBuffers, src_numbuf, srcSize);
releaseBuffers (dstBuffers, dst_numbuf, dstSize);
if (src_coplanar)
releaseBuffers (srcBuffers_uv, src_numbuf, srcSize_uv);
if (dst_coplanar)
releaseBuffers (dstBuffers_uv, dst_numbuf, dstSize_uv);
close(fin);
close(fout);
close(fd);
return 0;
}