Skip to content

V4L2_FormatTool

SweerItTer edited this page Feb 1, 2026 · 3 revisions

V4L2 FormatTool API 文档

概述

FormatTool 是 utilsCore V4L2 模块的命名空间,提供 V4L2 格式平面信息映射功能。

职责

  • 提供格式平面比例映射

适用场景

  • 平面信息查询
  • 格式验证
  • 平面计算

依赖关系

  • 依赖: V4L2 库
  • 被依赖: CameraController、Frame 等模块

结构体

PlaneScale - 平面比例

struct PlaneScale {
    float width_scale;
    float height_scale;
};

字段说明:

  • width_scale: 宽度比例(相对于完整分辨率)
  • height_scale: 高度比例(相对于完整分辨率)

说明:

  • 用于计算每个平面的实际大小
  • 例如 NV12 格式:Y 平面为 (1.0, 1.0),UV 平面为 (1.0, 0.5)

全局映射表

formatPlaneMap - 格式平面映射表

const static std::unordered_map<uint32_t, std::vector<PlaneScale>> formatPlaneMap = {
    // NV12/NV21: 也按双平面处理, 有的驱动只报告单平面
    { V4L2_PIX_FMT_NV12,  { {1.0f, 1.0f}, {1.0f, 0.5f} } },
    { V4L2_PIX_FMT_NV21,  { {1.0f, 1.0f}, {1.0f, 0.5f} } },
    { V4L2_PIX_FMT_NV16,  { {1.0f, 1.0f}, {1.0f, 1.0f} } },
    { V4L2_PIX_FMT_NV61,  { {1.0f, 1.0f}, {1.0f, 1.0f} } },
    { V4L2_PIX_FMT_NV24,  { {1.0f, 1.0f}, {1.0f, 1.0f} } },
    { V4L2_PIX_FMT_NV42,  { {1.0f, 1.0f}, {1.0f, 1.0f} } },

    // NV12M / NV21M
    { V4L2_PIX_FMT_NV12M, { {1.0f, 1.0f}, {1.0f, 0.5f} } },
    { V4L2_PIX_FMT_NV21M, { {1.0f, 1.0f}, {1.0f, 0.5f} } },

    // NV16M / NV61M
    { V4L2_PIX_FMT_NV16M, { {1.0f, 1.0f}, {1.0f, 1.0f} } },
    { V4L2_PIX_FMT_NV61M, { {1.0f, 1.0f}, {1.0f, 1.0f} } },

    // YUV420M / YVU420M
    { V4L2_PIX_FMT_YUV420M, { {1.0f, 1.0f}, {0.5f, 0.5f}, {0.5f, 0.5f} } },
    { V4L2_PIX_FMT_YVU420M, { {1.0f, 1.0f}, {0.5f, 0.5f}, {0.5f, 0.5f} } },

    // YUV422M / YVU422M
    { V4L2_PIX_FMT_YUV422M, { {1.0f, 1.0f}, {0.5f, 1.0f}, {0.5f, 1.0f} } },
    { V4L2_PIX_FMT_YVU422M, { {1.0f, 1.0f}, {0.5f, 1.0f}, {0.5f, 1.0f} } },

    // YUV444M
    { V4L2_PIX_FMT_YUV444M, { {1.0f, 1.0f}, {1.0f, 1.0f}, {1.0f, 1.0f} } },
};

格式平面信息表

格式 平面数 平面信息 说明
V4L2_PIX_FMT_NV12 2 (1.0, 1.0), (1.0, 0.5) YUV 420 Semi-Planar
V4L2_PIX_FMT_NV21 2 (1.0, 1.0), (1.0, 0.5) YUV 420 Semi-Planar
V4L2_PIX_FMT_NV16 2 (1.0, 1.0), (1.0, 1.0) YUV 422 Semi-Planar
V4L2_PIX_FMT_NV61 2 (1.0, 1.0), (1.0, 1.0) YUV 422 Semi-Planar
V4L2_PIX_FMT_NV12M 2 (1.0, 1.0), (1.0, 0.5) YUV 420 Multi-Planar
V4L2_PIX_FMT_YUV420M 3 (1.0, 1.0), (0.5, 0.5), (0.5, 0.5) YUV 420 Multi-Planar
V4L2_PIX_FMT_YUV422M 3 (1.0, 1.0), (0.5, 1.0), (0.5, 1.0) YUV 422 Multi-Planar
V4L2_PIX_FMT_YUV444M 3 (1.0, 1.0), (1.0, 1.0), (1.0, 1.0) YUV 444 Multi-Planar

典型使用场景

场景 1: 查询平面信息

uint32_t format = V4L2_PIX_FMT_NV12;

auto it = FormatTool::formatPlaneMap.find(format);
if (it != FormatTool::formatPlaneMap.end()) {
    const auto& planes = it->second;
    printf("Format has %zu planes\n", planes.size());
    
    for (size_t i = 0; i < planes.size(); ++i) {
        printf("Plane %zu: width_scale=%.2f, height_scale=%.2f\n",
               i, planes[i].width_scale, planes[i].height_scale);
    }
}

场景 2: 计算平面大小

uint32_t width = 1920;
uint32_t height = 1080;
uint32_t format = V4L2_PIX_FMT_NV12;

auto it = FormatTool::formatPlaneMap.find(format);
if (it != FormatTool::formatPlaneMap.end()) {
    const auto& planes = it->second;
    
    for (size_t i = 0; i < planes.size(); ++i) {
        uint32_t plane_width = width * planes[i].width_scale;
        uint32_t plane_height = height * planes[i].height_scale;
        printf("Plane %zu: %ux%u\n", i, plane_width, plane_height);
    }
}

场景 3: 检查格式是否支持

uint32_t format = V4L2_PIX_FMT_NV12;

if (FormatTool::formatPlaneMap.find(format) != FormatTool::formatPlaneMap.end()) {
    printf("Format supported\n");
} else {
    printf("Format not supported\n");
}

场景 4: 计算内存布局

uint32_t width = 1920;
uint32_t height = 1080;
uint32_t format = V4L2_PIX_FMT_NV12M;
uint32_t bytes_per_pixel = 1;  // 对于 YUV 格式

auto it = FormatTool::formatPlaneMap.find(format);
if (it != FormatTool::formatPlaneMap.end()) {
    const auto& planes = it->second;
    uint32_t offset = 0;
    
    for (size_t i = 0; i < planes.size(); ++i) {
        uint32_t plane_width = width * planes[i].width_scale;
        uint32_t plane_height = height * planes[i].height_scale;
        uint32_t plane_size = plane_width * plane_height * bytes_per_pixel;
        
        printf("Plane %zu: offset=%u, size=%u\n", i, offset, plane_size);
        offset += plane_size;
    }
}

场景 5: 格式验证

uint32_t format = V4L2_PIX_FMT_NV12;
uint32_t expected_planes = 2;

auto it = FormatTool::formatPlaneMap.find(format);
if (it != FormatTool::formatPlaneMap.end()) {
    if (it->second.size() == expected_planes) {
        printf("Format has expected number of planes\n");
    } else {
        printf("Format has %zu planes, expected %u\n", 
               it->second.size(), expected_planes);
    }
}

注意事项

  1. 静态映射表: formatPlaneMap 是静态常量映射表
  2. 命名空间: 使用 FormatTool 命名空间
  3. 平面比例: width_scale 和 height_scale 是相对于完整分辨率的比例
  4. 格式支持: 只支持常见格式,不支持所有格式
  5. 内存布局: 平面大小 = width * width_scale * height * height_scale * bytes_per_pixel
  6. M 格式: M 格式表示 Multi-Planar(多平面)
  7. 线程安全: 映射表是静态常量,线程安全

相关文档


参考资料

主页

API 文档

DMA 模块

DRM 模块

NET 模块

V4L2 模块

V4L2Param 模块

RGA 模块

MPP 模块

Sys 模块

Mouse 模块

Utils 模块

Clone this wiki locally