Hi Nvidia:
Use tegra_multimedia_API to dq buffer from encoder output_plane, but it can not completed.
detail description:
JetPack:3.2 release date: 2018/03/08
Base code example: 12_camera_v4l2_cuda /tegra_multimedia_API/sample
Function: start_capture(context_t * ctx)
NvBufferTransform(ctx->g_buff[v4l2_buf.index].dmabuff_fd, ctx->render_dmabuf_fd,
&transParams) is used to convert YUV422 data in g_buff[v4l2_buf.index].dmabuff_fd to YUV420 data and save the result data to ctx->render_dmabuf_fd.
I am trying to convert YUV422 data to YUV420 data, then encode YUV420 data to H264 data with encoder, so encoder is added to my code, reference initial code as below:
static bool encoder_initialize(context_t * ctx)
{
int ret = 0;
ctx->enc = NvVideoEncoder::createVideoEncoder("enc0");
if(!ctx->enc)
ERROR_RETURN("Could not create encoder");
// It is necessary that Capture Plane format be set before Output Planeformat.
// Set encoder capture plane format. It is necessary to set width and height on thr capture plane as well
// Set encoder output plane format
ret = ctx->enc->setCapturePlaneFormat(V4L2_PIX_FMT_H264, 640,480, 4 * 640 * 480);
if(ret < 0)
ERROR_RETURN("Could not set Capture plane format");
ret = ctx->enc->setOutputPlaneFormat(V4L2_PIX_FMT_YUV420M, 640,480);
if(ret < 0)
ERROR_RETURN("Could not set output plane format");
ret = ctx->enc->setBitrate(ctx->enc_bitrate);
if(ret < 0)
ERROR_RETURN("Could not set bitrate");
ret = ctx->enc->setProfile(V4L2_MPEG_VIDEO_H264_PROFILE_HIGH);
if(ret < 0)
ERROR_RETURN("Could not set encoder profile");
ret = ctx->enc->setLevel(V4L2_MPEG_VIDEO_H264_LEVEL_5_0);
if(ret < 0)
ERROR_RETURN("Could not set encoder level");
ret = ctx->enc->setFrameRate(ctx->enc_fps_n, ctx->enc_fps_d);
if(ret < 0)
ERROR_RETURN("Could not set framerate");
// Query, Export and Map the output plane buffers so that we can read raw data into the buffers
ret = ctx->enc->output_plane.setupPlane(V4L2_MEMORY_DMABUF, V4L2_BUFFERS_NUM, true, false);
if(ret < 0)
ERROR_RETURN("Could not setup output plane");
// Query, Export and Map the output plane buffers so that we can write encoded data from the buffers
ret = ctx->enc->capture_plane.setupPlane(V4L2_MEMORY_MMAP, V4L2_BUFFERS_NUM, true, false);
if(ret < 0)
ERROR_RETURN("Could not setup capture plane");
return true;
}
static bool enqueue_encoder_buff(context_t *ctx)
{
// Enqueue empty buffer into encoder output plane
for (unsigned int index = 0; index < ctx->enc->output_plane.getNumBuffers(); index++)
{
struct v4l2_buffer v4l2_buf;
struct v4l2_plane planes[MAX_PLANES];
memset(&v4l2_buf, 0, sizeof(v4l2_buf));
memset(planes, 0, MAX_PLANES * sizeof(struct v4l2_plane));
v4l2_buf.index = index;
v4l2_buf.m.planes = planes;
if (ctx->enc->output_plane.qBuffer(v4l2_buf, NULL) < 0)
INFO("Failed to enqueue empty buffer into encoder output plane");
}
// Enqueue empty buffer into encoder capture plane
for (unsigned int index = 0; index < ctx->enc->capture_plane.getNumBuffers(); index++)
{
struct v4l2_buffer v4l2_buf;
struct v4l2_plane planes[MAX_PLANES];
memset(&v4l2_buf, 0, sizeof(v4l2_buf));
memset(planes, 0, MAX_PLANES * sizeof(struct v4l2_plane));
v4l2_buf.index = index;
v4l2_buf.m.planes = planes;
if (ctx->enc->capture_plane.qBuffer(v4l2_buf, NULL) < 0)
INFO("Failed to enqueue empty buffer into encoder capture plane");
}
return true;
}
And function start_capture changed in my program, code as below:
start_capture(context_t * ctx)
{
struct sigaction sig_action;
struct pollfd fds[1];
NvBufferTransformParams transParams;
// Ensure a clean shutdown if user types <ctrl+c>
sig_action.sa_handler = signal_handle;
sigemptyset(&sig_action.sa_mask);
sig_action.sa_flags = 0;
sigaction(SIGINT, &sig_action, NULL);
ctx->enc->capture_plane.setDQThreadCallback(encoder_capture_plane_dq_callback);
ctx->enc->capture_plane.startDQThread(&ctx);
// Init the NvBufferTransformParams
memset(&transParams, 0, sizeof(transParams));
transParams.transform_flag = NVBUFFER_TRANSFORM_FILTER;
transParams.transform_filter = NvBufferTransform_Filter_Smart;
// Enable render profiling information
//ctx->renderer->enableProfiling();
fds[0].fd = ctx->cam_fd;
fds[0].events = POLLIN;
while (poll(fds, 1, 5000) > 0 && !quit)
{
if (fds[0].revents & POLLIN) {
struct v4l2_buffer v4l2_buf;
// Dequeue camera buff
memset(&v4l2_buf, 0, sizeof(v4l2_buf));
v4l2_buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
v4l2_buf.memory = V4L2_MEMORY_DMABUF;
if (ioctl(ctx->cam_fd, VIDIOC_DQBUF, &v4l2_buf) < 0)
ERROR_RETURN("Failed to dequeue camera buff: %s (%d)",
strerror(errno), errno);
ctx->frame++;
if (ctx->frame == ctx->save_n_frame)
save_frame_to_file(ctx, &v4l2_buf);
// Cache sync for VIC operation
NvBufferMemSyncForDevice(ctx->g_buff[v4l2_buf.index].dmabuff_fd, 0,
(void**)&ctx->g_buff[v4l2_buf.index].start);
struct v4l2_buffer v4l2_buf1;
struct v4l2_plane planes[MAX_PLANES];
NvBuffer *buffer;
memset(&v4l2_buf1, 0, sizeof(v4l2_buf1));
memset(planes, 0, sizeof(planes));
v4l2_buf1.m.planes = planes;
printf("123\n");
if(ctx->enc->output_plane.dqBuffer(v4l2_buf1, &buffer, NULL, V4L2_BUFFERS_NUM) < 0)
printf("ERROR while DQing buffer at output plane\n");
printf(“234\n”);
// Convert the camera buffer from YUV422 to YUV420P
if (-1 == NvBufferTransform(ctx->g_buff[v4l2_buf.index].dmabuff_fd, buffer->planes[0].fd, &transParams))
ERROR_RETURN(“Failed to convert the buffer”);
if (ctx->enc->output_plane.qBuffer(v4l2_buf, NULL) < 0)
printf(“Error while Qing buffer at output plane”);
/if (-1 == NvBufferTransform(ctx->g_buff[v4l2_buf.index].dmabuff_fd, ctx->render_dmabuf_fd,
&transParams))
ERROR_RETURN(“Failed to convert the buffer”);/
//cuda_postprocess(ctx, ctx->render_dmabuf_fd);
//ctx->renderer->render(ctx->render_dmabuf_fd);
// Enqueue camera buff
if (ioctl(ctx->cam_fd, VIDIOC_QBUF, &v4l2_buf))
ERROR_RETURN("Failed to queue camera buffers: %s (%d)",
strerror(errno), errno);
}
}
// Print profiling information when streaming stops.
//ctx->renderer->printProfilingStats();
return true;
}
Run my program, “123” printed once, any other not printed. Is there any problem in my program?
Expected your reply ! Thanks a lot!