Hello, I want to send the detection result picture containing the target box or the bounding box to the network, what is the general method??
What I’m doing now is taking the raw frame data from the SurfaceList, drawing the bounding box with OpenCV, and encoding it with NVJPEG. However, there are two problems:
1) Segmentation fault occurs during OpenCV Imwrite/Imread !
2) The original frame from the surfacelist is in NV12 format, the image generated by 05_jpeg_encode in JETSON_MULTIMEDIA_API has color space problem.
How do I pass NV12 data on the Surface to NVJPEG for proper encoding ?
This problem has been bothering me for more than two weeks. Please give me some advice. Thank you very much !
- My main code is as follows:
cudaMemcpy((void*)src_data,
(void*)surface->surfaceList[frame_meta->batch_id].dataPtr,
surface->surfaceList[frame_meta->batch_id].dataSize,
cudaMemcpyDeviceToHost);
gint frame_width = (gint)surface->surfaceList[frame_meta->batch_id].width;
gint frame_height = (gint)surface->surfaceList[frame_meta->batch_id].height;
gint frame_step = surface->surfaceList[frame_meta->batch_id].pitch;
gint color_format = surface->surfaceList[frame_meta->batch_id].colorFormat;
JpegEncoder::instance()->encode(frame_meta->source_id, src_data, frame_data_size, frame_width, frame_height);
* Here is the main code in the encode :
ctx->jpegenc = NvJPEGEncoder::createJPEGEncoder("jpenenc");
TEST_ERROR(!ctx->jpegenc, "Could not create Jpeg Encoder", cleanup);
ctx->convert = NvVideoConverter::createVideoConverter("conv");
TEST_ERROR(!ctx->convert, "Could not create Video Converter", cleanup);
/* Set conv output plane format */ // V4L2_PIX_FMT_YUV420M
ret = ctx->convert->setOutputPlaneFormat(V4L2_PIX_FMT_YUV420M, ctx->in_width,
ctx->in_height,
V4L2_NV_BUFFER_LAYOUT_PITCH);
TEST_ERROR(ret < 0, "Could not set output plane format for conv", cleanup);
/* Set conv capture plane format, YUV420 or NV12 */
ret = ctx->convert->setCapturePlaneFormat(ctx->in_pixfmt, ctx->in_width,
ctx->in_height,
V4L2_NV_BUFFER_LAYOUT_BLOCKLINEAR);
TEST_ERROR(ret < 0, "Could not set capture plane format for conv", cleanup);
/* REQBUF, EXPORT and MAP conv output plane buffers */
ret = ctx->convert->output_plane.setupPlane(V4L2_MEMORY_MMAP, 1, true, false);
TEST_ERROR(ret < 0, "Error while setting up output plane for conv", cleanup);
/* REQBUF and EXPORT conv capture plane buffers
* No need to MAP since buffer will be shared to next component and not read in application */
ret = ctx->convert->capture_plane.setupPlane(V4L2_MEMORY_MMAP, 1, !ctx->use_fd, false);
TEST_ERROR(ret < 0, "Error while setting up capture plane for conv", cleanup);
/* conv output plane STREAMON */
ret = ctx->convert->output_plane.setStreamStatus(true);
TEST_ERROR(ret < 0, "Error in output plane streamon for conv", cleanup);
/* conv capture plane STREAMON */
ret = ctx->convert->capture_plane.setStreamStatus(true);
TEST_ERROR(ret < 0, "Error in capture plane streamon for conv", cleanup);
/* Register callback for dequeue thread on conv capture plane, this callback
* will encode YUV420 or NV12 image to JPEG and write to file system. */
ctx->convert->capture_plane.setDQThreadCallback(conv_capture_dqbuf_thread_callback);
// Start threads to dequeue buffers on conv capture plane
ctx->convert->capture_plane.startDQThread(ctx);
/* Enqueue all empty conv capture plane buffers, actually in this case, 1 buffer will be enqueued. */
for (uint32_t i = 0; i < ctx->convert->capture_plane.getNumBuffers(); i++) // getNumBuffers() = 1
{
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 = i;
v4l2_buf.m.planes = planes;
ret = ctx->convert->capture_plane.qBuffer(v4l2_buf, NULL);
if (ret < 0){
std::cerr << "Error while queueing buffer at conv capture plane" << std::endl;
abort(ctx);
goto cleanup;
}
}
/* Read YUV420 image to conv output plane buffer and enqueue so conv can start processing. */
{
struct v4l2_buffer v4l2_buf;
struct v4l2_plane planes[MAX_PLANES];
NvBuffer *buffer = ctx->convert->output_plane.getNthBuffer(0);
memset(&v4l2_buf, 0, sizeof(v4l2_buf));
memset(planes, 0, MAX_PLANES * sizeof(struct v4l2_plane));
v4l2_buf.index = 0;
v4l2_buf.m.planes = planes;
for (uint32_t i = 0; i < buffer->n_planes; i++)
{
NvBuffer::NvBufferPlane &plane = buffer->planes[i];
plane.bytesused = 0;
uint32_t bytes_writed = plane.fmt.bytesperpixel * plane.fmt.width;
unsigned char* dstdata = plane.data;
unsigned char* srcdata = src_yuv_data;
for (uint32_t j = 0; j < plane.fmt.height; j++)
{
memcpy(dstdata, srcdata, bytes_writed); // ???
srcdata += bytes_writed; // ???
dstdata += plane.fmt.stride;
}
plane.bytesused = plane.fmt.stride * plane.fmt.height;
}
ret = ctx->convert->output_plane.qBuffer(v4l2_buf, NULL);
if (ret < 0){
std::cerr << "Error while queueing buffer at conv output plane" << std::endl;
abort(ctx);
goto cleanup;
}
}
/* Wait till all capture plane buffers on conv are dequeued */
ctx->convert->capture_plane.waitForDQThread(2000);