4.4. 视频输出叠加接口

也称为屏幕显示 (OSD)

一些视频输出设备可以将帧缓冲区图像叠加到输出视频信号上。应用程序可以使用此接口设置此类叠加,该接口借鉴了视频叠加接口的结构和 ioctl。

OSD 功能可通过与视频输出功能相同的字符特殊文件访问。

注意

此类 /dev/video 设备的默认功能是视频捕获或输出。OSD 功能仅在调用 VIDIOC_S_FMT ioctl 后才可用。

4.4.1. 查询能力

支持视频输出叠加接口的设备会在ioctl VIDIOC_QUERYCAP ioctl 返回的 struct v4l2_capabilitycapabilities 字段中设置 V4L2_CAP_VIDEO_OUTPUT_OVERLAY 标志。

4.4.2. 帧缓冲区

视频叠加接口不同,帧缓冲区通常实现在电视卡上,而非显卡上。在 Linux 上,它作为帧缓冲区设备 (/dev/fbN) 可访问。给定一个 V4L2 设备,应用程序可以通过调用 VIDIOC_G_FBUF ioctl 来找到相应的帧缓冲区设备。它返回的信息中包括帧缓冲区在 struct v4l2_framebufferbase 字段中的物理地址。帧缓冲区设备 ioctl FBIOGET_FSCREENINFO 在 struct fb_fix_screeninfosmem_start 字段中返回相同的地址。FBIOGET_FSCREENINFO ioctl 和 struct fb_fix_screeninfolinux/fb.h 头文件中定义。

帧缓冲区的宽度和高度取决于当前视频标准。V4L2 驱动程序可能会拒绝更改视频标准(或任何其他暗示帧缓冲区大小变化的 ioctl)的尝试,直到所有应用程序关闭帧缓冲区设备,并返回 EBUSY 错误码。

4.4.2.1. 示例:查找用于 OSD 的帧缓冲区设备

#include <linux/fb.h>

struct v4l2_framebuffer fbuf;
unsigned int i;
int fb_fd;

if (-1 == ioctl(fd, VIDIOC_G_FBUF, &fbuf)) {
    perror("VIDIOC_G_FBUF");
    exit(EXIT_FAILURE);
}

for (i = 0; i < 30; i++) {
    char dev_name[16];
    struct fb_fix_screeninfo si;

    snprintf(dev_name, sizeof(dev_name), "/dev/fb%u", i);

    fb_fd = open(dev_name, O_RDWR);
    if (-1 == fb_fd) {
        switch (errno) {
        case ENOENT: /* no such file */
        case ENXIO:  /* no driver */
            continue;

        default:
            perror("open");
            exit(EXIT_FAILURE);
        }
    }

    if (0 == ioctl(fb_fd, FBIOGET_FSCREENINFO, &si)) {
        if (si.smem_start == (unsigned long)fbuf.base)
            break;
    } else {
        /* Apparently not a framebuffer device. */
    }

    close(fb_fd);
    fb_fd = -1;
}

/* fb_fd is the file descriptor of the framebuffer device
   for the video output overlay, or -1 if no device was found. */

4.4.3. 叠加窗口和缩放

叠加由源矩形和目标矩形控制。源矩形选择帧缓冲区图像中要叠加的子部分,目标矩形选择输出视频信号中图像将显示(出现)的区域。驱动程序可能支持也可能不支持缩放,以及这些矩形的任意大小和位置。此外,驱动程序可能支持 视频叠加 接口定义的任何(或不包含)裁剪/混合方法。

struct v4l2_window 定义了源矩形的大小、其在帧缓冲区中的位置以及用于叠加的裁剪/混合方法。要获取当前参数,应用程序将 struct v4l2_formattype 字段设置为 V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY 并调用 VIDIOC_G_FMT ioctl。驱动程序会填充名为 win 的 struct v4l2_window 子结构。无法检索先前编程的裁剪列表或位图。

要编程源矩形,应用程序将 struct v4l2_formattype 字段设置为 V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY,初始化 win 子结构并调用 VIDIOC_S_FMT ioctl。驱动程序会根据硬件限制调整参数,并像 VIDIOC_G_FMT 那样返回实际参数。与 VIDIOC_S_FMT 类似,VIDIOC_TRY_FMT ioctl 可用于了解驱动程序能力,而无需实际更改驱动程序状态。与 VIDIOC_S_FMT 不同的是,这在叠加启用后也有效。

struct v4l2_crop 定义了目标矩形的大小和位置。叠加的缩放因子由 struct v4l2_window 和 struct v4l2_crop 中给定的宽度和高度决定。裁剪 API 适用于视频输出视频输出叠加设备的方式与适用于视频捕获视频叠加设备的方式相同,只是数据流方向相反。更多信息请参阅图像裁剪、插入和缩放——CROP API

4.4.4. 启用叠加

没有 V4L2 ioctl 可以启用或禁用叠加,但是驱动程序的帧缓冲区接口可能支持 FBIOBLANK ioctl。