本示例演示了如何使用 libv4l2 组件分配的缓冲区来解码 H.265/H.264 视频流,以及如何使用 CUDA 辅助渲染图像,而无需额外的内存复制操作。
支持的视频格式
$ cd /usr/src/jetson_multimedia_api/samples/02_video_dec_cuda $ make
$ ./video_dec_cuda <in-file> <in-format> [options]
$ ./video_dec_cuda ../../data/Video/sample_outdoor_car_1080p_10fps.h264 H264
下图显示了数据在示例中的流程。
本示例的主要流程如下
Tegra 在输入和输出上提供 pitch linear 和 block linear 内存格式支持。输入和输出内存格式不需要匹配。
ret = ctx->conv->setOutputPlaneFormat(format.fmt.pix_mp.pixelformat, format.fmt.pix_mp.width, format.fmt.pix_mp.height, NvVideoConverter::LAYOUT_BLOCK);
此调用设置 libv4l2 输出平面,即,用于接收解码器的 YUV 数据输入,采用 block linear 格式。这是符合 Tegra 硬件的格式。
ret = ctx->conv->setCapturePlaneFormat(format.fmt.pix_mp.pixelformat, format.fmt.pix_mp.width, format.fmt.pix_mp.height, NvVideoConverter::LAYOUT_PITCH);
此调用设置 libv4l2 捕获平面,采用 pitch linear 格式。这是软件实现常用的格式。
NvEGLImageFromFd
是语法错误,它从 NvVideoDecoder 基类的成员函数分配的文件描述符缓冲区返回 EGLImage 指针。然后 CUDA 使用 EGLImage 缓冲区在显示器上渲染一个黑色方框。这是在一个单独的通用例程中使用 EGLImage 实现的。
本示例使用以下主要结构和类
元素 | 描述 |
---|---|
NvVideoDecoder | 包含所有视频解码相关的元素和函数。 |
NvVideoConverter | 包含用于视频格式转换的元素和函数。 |
NvEglRenderer | 包含所有 EGL 显示渲染相关函数。 |
egl_image | 用于 CUDA 处理的 EGLImage。 |
conv_output_plane_buf_queue | 视频转换的输出平面队列。 |
dec_capture_loop | 用于解码捕获循环的线程处理程序。 |
NvVideoDecoder 打包了所有视频解码相关的元素和函数。示例中使用的主要成员是
成员 | 描述 |
---|---|
output_plane | V4l2 输出平面。 |
capture_plane | V4l2 捕获平面。 |
createVideoDecoder | 用于创建视频解码器对象的静态函数。 |
subscribeEvent | 订阅事件。 |
setExtControls | 设置 V4l2 设备的外部控制。 |
setOutputPlaneFormat | 设置输出平面格式。 |
setCapturePlaneFormat | 设置捕获平面格式。 |
getControl | 待定 |
dqEvent | 出队 V4l2 设备报告的事件。 |
isInError | 检查是否处于错误状态。 |
NvVideoConverter 打包了所有视频转换相关的元素和函数。示例中使用的主要成员是
成员 | 描述 |
---|---|
output_plane | 输出平面。 |
capture_plane | 捕获平面。 |
waitForIdle | 待定 |
setOutputPlaneFormat | 设置输出平面格式。 |
setCapturePlaneFormat | 设置捕获平面格式。 |
NvVideoDecoder 和 NvVideoConverter 都包含 2 个关键元素:output_plane
和 capture_plane
。 这 2 个对象属于同一类类型 NvV4l2ElementPlane。示例中使用的主要成员是
元素 | 描述 |
---|---|
setupPlane | 设置 V4l2 元素的平面。 |
deinitPlane | 销毁 V4l2 元素的平面。 |
setStreamStatus | 启动/停止流。 |
setDQThreadCallback | 设置出队缓冲区线程的回调函数。 |
startDQThread | 启动出队缓冲区线程。 |
stopDQThread | 停止出队缓冲区线程。 |
qBuffer | 队列 V4l2 缓冲区。 |
dqBuffer | 出队 V4l2 缓冲区。 |
getNumBuffers | 获取 V4l2 缓冲区的数量。 |
getNumQueuedBuffers | 获取队列中 V4l2 缓冲区的数量。 |
getNthBuffer | 待定 |
使用两个全局函数从 dmabuf 文件描述符创建和销毁 EGLImage
函数 | 描述 |
---|---|
NvEGLImageFromFd | 从 dmabuf 文件描述符创建 EGLImage。 |
NvDestroyEGLImage | 销毁 EGLImage。 |