NV21、NV12、YV12、RGB565、YUV等颜色编码格式区别和接口设计探讨

简介: NV21、NV12、YV12、RGB565、YUV分别是不同的颜色编码格式,这些颜色编码格式各有特点,适用于不同的应用场景。选择合适的颜色编码格式取决于具体的需求和环境:

NV21、NV12、YV12、RGB565、YUV扫盲

NV21、NV12、YV12、RGB565、YUV分别是不同的颜色编码格式,这些颜色编码格式各有特点,适用于不同的应用场景。选择合适的颜色编码格式取决于具体的需求和环境:


1.NV21:NV21是一种用于Android系统的图像颜色编码格式。它使用YUV 4:2:0的采样方式,即垂直方向上每两个像素采样一次,水平方向上每个像素采样两次。NV21的Y分量是亮度信息,V和U分量是色度信息(分别代表饱和度和色调)。这种格式主要应用于前置摄像头和Android的Camera API。


2.NV12:NV12是一种用于视频编解码的颜色编码格式,同样采用了YUV 4:2:0的采样方式。NV12的Y分量是亮度信息,V和U分量也是色度信息。不同的是,与NV21不同的是,NV12的Y、V、U三个分量分别采用了不同的采样率,即垂直方向上每两个像素采样一次,水平方向上每隔一个像素采样一次。


3.YV12:YV12是一种用于视频编解码的颜色编码格式。它同样采用了YUV 4:2:0的采样方式。YV12的Y分量是亮度信息,V和U分量也是色度信息。与NV12不同的是,YV12的V和U分量交换了位置。这种格式主要应用于软件编解码器,如FFmpeg。


4.RGB565:RGB565是一种颜色编码格式,它有3个通道,分别是红色、绿色和蓝色,由这三个通道的强度值共同决定一个颜色。在RGB565中,每个通道的精度为5位(红色)、6位(绿色)和5位(蓝色)。因此,RGB565能够表示的颜色数量有限。


5.YUV:YUV是一种将亮度信息和色度信息分开的颜色编码格式。在YUV格式中,Y是亮度分量,而UV是色度分量。UV分量又进一步分为U和V,分别代表饱和度和色调。这种格式主要用于优化彩色视频信号的传输,因为可以对亮度信息进行更高效的压缩。

如何对接上述颜色编码格式

大牛直播SDK在做Android平台RTMP推送、轻量级RTSP服务和GB28181设备接入模块的时候,对接过上述的颜色编码格式,下面分别探讨下不同格式设计的数据接口。

4899d1dd3d5946acaf3d9c13fd054b7f.jpg

YV12的数据接口

YV12的数据接口,主要是用于第三方的设备对接居多,这个接口的u_stride, v_stride分别是(width+1)/2,如果出来的数据需要旋转,通过rotation_degree来控制旋转角度即可。

    /**
     * YV12数据接口
     *
     * @param data: YV12 data
     *
     * @param width: 图像宽
     *
     * @param height: 图像高
     *
     * @param y_stride:  y面步长
     *
     * @param v_stride: v面步长
     *
     * @param u_stride: u面步长
     *
     * rotation_degree: 顺时针旋转, 必须是0, 90, 180, 270
     *
     * @return {0} if successful
     */
    public native int SmartPublisherOnYV12Data(long handle, byte[] data, int width, int height, int y_stride,  int v_stride, int u_stride, int rotation_degree);

YUV数据接口

支持标准的I420数据接口对接,不再赘述:

  /**
   * 投递层I420图像
   *
   * @param index: 层索引, 必须大于等于0
   *
   * @param left: 层叠加的左上角坐标, 对于第0层的话传0
   *
   * @param top: 层叠加的左上角坐标, 对于第0层的话传0
   *
   * @param y_plane: y平面图像数据
   *
   * @param y_offset: 图像偏移, 这个主要目的是用来做clip的,一般传0
   *
   * @param y_row_stride: stride information
   *
   * @param u_plane: u平面图像数据
   *
   * @param u_offset: 图像偏移, 这个主要目的是用来做clip的,一般传0
   *
   * @param u_row_stride: stride information
   *                    *
   * @param v_plane: v平面图像数据
   *
   * @param v_offset: 图像偏移, 这个主要目的是用来做clip的,一般传0
   *
   * @param v_row_stride: stride information
   *
   * @param width: width, 必须大于1, 且必须是偶数
   *
   * @param height: height, 必须大于1, 且必须是偶数
   *
   * @param  is_vertical_flip: 是否垂直翻转, 0不翻转, 1翻转
   *
   * @param  is_horizontal_flip:是否水平翻转, 0不翻转, 1翻转
   *
   * @param  scale_width: 缩放宽,必须是偶数, 0或负数不缩放
   *
   * @param  scale_height: 缩放高, 必须是偶数, 0或负数不缩放
   *
   * @param  scale_filter_mode: 缩放质量, 传0使用默认速度,可选等级范围是:[1,3],值越大缩放质量越好, 但速度越慢
   *
   * @param  rotation_degree: 顺时针旋转, 必须是0, 90, 180, 270, 注意:旋转是在缩放, 垂直/水品反转之后再做, 请留意顺序
   *
   * @return {0} if successful
   */
  public native int PostLayerImageI420ByteBuffer(long handle, int index, int left, int top,
                           ByteBuffer y_plane, int y_offset, int y_row_stride,
                           ByteBuffer u_plane, int u_offset, int u_row_stride,
                           ByteBuffer v_plane, int v_offset, int v_row_stride,
                           int width, int height, int is_vertical_flip,  int is_horizontal_flip,
                           int scale_width,  int scale_height, int scale_filter_mode,
                           int rotation_degree);

NV21转I420并旋转接口

这个接口也是主要用于特定的数据类型对接,NV21的数据,直接转I420后,对接即可,接口参数比较简单,不再赘述。

  /**
   * NV21转换到I420并旋转
   *
   * @param src: nv21 data
   *
   * @param dst: 输出I420 data
   *
   * @param width: 图像宽
   *
   * @param height: 图像高
   *
   * rotation_degree: 顺时针旋转, 必须是0, 90, 180, 270
   *
   * @return {0} if successful
   */
  public native int SmartPublisherNV21ToI420Rotate(long handle, byte[] src, int src_y_stride, int src_uv_stride, byte[] dst,
                           int dst_y_stride, int dst_u_stride, int dst_v_stride,
                           int width, int height,
                           int rotation_degree);

支持RGBA数据接入

RGBA的主要用于屏幕共享场景下。

   /**
    * Set live video data(no encoded data).
    *
    * @param data: RGBA data
    * 
    * @param rowStride: stride information
    * 
    * @param width: width
    * 
    * @param height: height
    *
    * @return {0} if successful
    */
    public native int SmartPublisherOnCaptureVideoRGBAData(long handle,  ByteBuffer data, int rowStride, int width, int height);
    /**
     * 投递裁剪过的RGBA数据
     *
     * @param data: RGBA data
     *
     * @param rowStride: stride information
     *
     * @param width: width
     *
     * @param height: height
     *
     * @param clipedLeft: 左;  clipedTop: 上; clipedwidth: 裁剪后的宽; clipedHeight: 裁剪后的高; 确保传下去裁剪后的宽、高均为偶数
     *
     * @return {0} if successful
     */
    public native int SmartPublisherOnCaptureVideoClipedRGBAData(long handle,  ByteBuffer data, int rowStride, int width, int height, int clipedLeft, int clipedTop, int clipedWidth, int clipedHeight);
    /**
     * Set live video data(no encoded data).
     *
     * @param data: ABGR flip vertical(垂直翻转) data
     *
     * @param rowStride: stride information
     *
     * @param width: width
     *
     * @param height: height
     *
     * @return {0} if successful
     */
    public native int SmartPublisherOnCaptureVideoABGRFlipVerticalData(long handle,  ByteBuffer data, int rowStride, int width, int height);

支持RGB565数据接入(主要用于同屏场景)

RGB565数据类型也主要用于屏幕采集这块。

    /**
     * Set live video data(no encoded data).
     *
     * @param data: RGB565 data
     *
     * @param row_stride: stride information
     *
     * @param width: width
     *
     * @param height: height
     *
     * @return {0} if successful
     */
    public native int SmartPublisherOnCaptureVideoRGB565Data(long handle,ByteBuffer data, int row_stride, int width, int height);

NV12、NV21格式

  /**
   * 投递层NV21图像
   *
   * @param index: 层索引, 必须大于等于0
   *
   * @param left: 层叠加的左上角坐标, 对于第0层的话传0
   *
   * @param top: 层叠加的左上角坐标, 对于第0层的话传0
   *
   * @param y_plane: y平面图像数据
   *
   * @param y_offset: 图像偏移, 这个主要目的是用来做clip的,一般传0
   *
   * @param y_row_stride: stride information
   *
   * @param uv_plane: uv平面图像数据
   *
   * @param uv_offset: 图像偏移, 这个主要目的是用来做clip的,一般传0
   *
   * @param uv_row_stride: stride information
   *
   * @param width: width, 必须大于1, 且必须是偶数
   *
   * @param height: height, 必须大于1, 且必须是偶数
   *
   * @param  is_vertical_flip: 是否垂直翻转, 0不翻转, 1翻转
   *
   * @param  is_horizontal_flip:是否水平翻转, 0不翻转, 1翻转
   *
   * @param  scale_width: 缩放宽,必须是偶数, 0或负数不缩放
   *
   * @param  scale_height: 缩放高, 必须是偶数, 0或负数不缩放
   *
   * @param  scale_filter_mode: 缩放质量, 传0使用默认速度,可选等级范围是:[1,3],值越大缩放质量越好, 但速度越慢
   *
   * @param  rotation_degree: 顺时针旋转, 必须是0, 90, 180, 270, 注意:旋转是在缩放, 垂直/水品反转之后再做, 请留意顺序
   *
   * @return {0} if successful
   */
  public native int PostLayerImageNV21ByteBuffer(long handle, int index, int left, int top,
                             ByteBuffer y_plane, int y_offset, int y_row_stride,
                               ByteBuffer uv_plane, int uv_offset, int uv_row_stride,
                               int width, int height, int is_vertical_flip,  int is_horizontal_flip,
                             int scale_width,  int scale_height, int scale_filter_mode,
                             int rotation_degree);
  /**
   * 投递层NV21图像, 详细说明请参考PostLayerImageNV21ByteBuffer
   *
   * @return {0} if successful
   */
  public native int PostLayerImageNV21ByteArray(long handle, int index, int left, int top,
                           byte[] y_plane, int y_offset, int y_row_stride,
                           byte[] uv_plane, int uv_offset, int uv_row_stride,
                           int width, int height, int is_vertical_flip,  int is_horizontal_flip,
                           int scale_width,  int scale_height, int scale_filter_mode,
                           int rotation_degree);
  /**
   * 投递层NV12图像, 详细说明请参考PostLayerImageNV21ByteBuffer
   *
   * @return {0} if successful
   */
  public native int PostLayerImageNV12ByteBuffer(long handle, int index, int left, int top,
                           ByteBuffer y_plane, int y_offset, int y_row_stride,
                           ByteBuffer uv_plane, int uv_offset, int uv_row_stride,
                           int width, int height, int is_vertical_flip,  int is_horizontal_flip,
                           int scale_width,  int scale_height, int scale_filter_mode,
                           int rotation_degree);
  /**
   * 投递层NV12图像, 详细说明请参考PostLayerImageNV21ByteBuffer
   *
   * @return {0} if successful
   */
  public native int PostLayerImageNV12ByteArray(long handle, int index, int left, int top,
                          byte[] y_plane, int y_offset, int y_row_stride,
                          byte[] uv_plane, int uv_offset, int uv_row_stride,
                          int width, int height, int is_vertical_flip,  int is_horizontal_flip,
                          int scale_width,  int scale_height, int scale_filter_mode,
                          int rotation_degree);

RGBA8888、RGBX8888接口

  /**
   * 投递层RGBA8888图像,如果不需要Aplpha通道的话, 请使用RGBX8888接口, 效率高
   *
   * @param index: 层索引, 必须大于等于0, 注意:如果index是0的话,将忽略Alpha通道
   *
   * @param left: 层叠加的左上角坐标, 对于第0层的话传0
   *
   * @param top: 层叠加的左上角坐标, 对于第0层的话传0
   *
   * @param rgba_plane: rgba 图像数据
   *
   * @param offset: 图像偏移, 这个主要目的是用来做clip的, 一般传0
   *
   * @param row_stride: stride information
   *
   * @param width: width, 必须大于1, 如果是奇数, 将减1
   *
   * @param height: height, 必须大于1, 如果是奇数, 将减1
   *
   * @param  is_vertical_flip: 是否垂直翻转, 0不翻转, 1翻转
   *
   * @param  is_horizontal_flip:是否水平翻转, 0不翻转, 1翻转
   *
   * @param  scale_width: 缩放宽,必须是偶数, 0或负数不缩放
   *
   * @param  scale_height: 缩放高, 必须是偶数, 0或负数不缩放
   *
   * @param  scale_filter_mode: 缩放质量, 传0使用默认速度,可选等级范围是:[1,3],值越大缩放质量越好, 但速度越慢
   *
   * @param  rotation_degree: 顺时针旋转, 必须是0, 90, 180, 270, 注意:旋转是在缩放, 垂直/水品反转之后再做, 请留意顺序
   *
   * @return {0} if successful
   */
  public native int PostLayerImageRGBA8888ByteBuffer(long handle, int index, int left, int top,
                       ByteBuffer rgba_plane, int offset, int row_stride, int width, int height,
                       int is_vertical_flip,  int is_horizontal_flip,
                       int scale_width,  int scale_height, int scale_filter_mode,
                       int rotation_degree);
  /**
   * 投递层RGBA8888图像, 详细说明请参考PostLayerImageRGBA8888ByteBuffer
   *
   * @return {0} if successful
   */
  public native int PostLayerImageRGBA8888ByteArray(long handle, int index, int left, int top,
                            byte[] rgba_plane, int offset, int row_stride, int width, int height,
                            int is_vertical_flip,  int is_horizontal_flip,
                            int scale_width,  int scale_height, int scale_filter_mode,
                            int rotation_degree);
  /**
   * 投递层RGBA8888图像, 详细说明请参考PostLayerImageRGBA8888ByteBuffer
   *
   * @return {0} if successful
   */
  public native int PostLayerImageRGBA8888Native(long handle, int index, int left, int top,
                           long rgba_plane, int offset, int row_stride, int width, int height,
                           int is_vertical_flip,  int is_horizontal_flip,
                           int scale_width,  int scale_height, int scale_filter_mode,
                           int rotation_degree);
  /**
   * 投递层RGBX8888图像
   *
   * @param index: 层索引, 必须大于等于0
   *
   * @param left: 层叠加的左上角坐标, 对于第0层的话传0
   *
   * @param top: 层叠加的左上角坐标, 对于第0层的话传0
   *
   * @param rgbx_plane: rgbx 图像数据
   *
   * @param offset: 图像偏移, 这个主要目的是用来做clip的,一般传0
   *
   * @param row_stride: stride information
   *
   * @param width: width, 必须大于1, 如果是奇数, 将减1
   *
   * @param height: height, 必须大于1, 如果是奇数, 将减1
   *
   * @param  is_vertical_flip: 是否垂直翻转, 0不翻转, 1翻转
   *
   * @param  is_horizontal_flip:是否水平翻转, 0不翻转, 1翻转
   *
   * @param  scale_width: 缩放宽,必须是偶数, 0或负数不缩放
   *
   * @param  scale_height: 缩放高, 必须是偶数, 0或负数不缩放
   *
   * @param  scale_filter_mode: 缩放质量, 传0使用默认速度,可选等级范围是:[1,3],值越大缩放质量越好, 但速度越慢
   *
   * @param  rotation_degree: 顺时针旋转, 必须是0, 90, 180, 270, 注意:旋转是在缩放, 垂直/水品反转之后再做, 请留意顺序
   *
   * @return {0} if successful
   */
  public native int PostLayerImageRGBX8888ByteBuffer(long handle, int index, int left, int top,
                             ByteBuffer rgbx_plane, int offset, int row_stride, int width, int height,
                             int is_vertical_flip,  int is_horizontal_flip,
                             int scale_width,  int scale_height, int scale_filter_mode,
                             int rotation_degree);
  /**
   * 投递层RGBX8888图像, 详细说明请参考PostLayerImageRGBX8888ByteBuffer
   *
   * @return {0} if successful
   */
  public native int PostLayerImageRGBX8888ByteArray(long handle, int index, int left, int top,
                            byte[] rgbx_plane, int offset, int row_stride, int width, int height,
                            int is_vertical_flip,  int is_horizontal_flip,
                            int scale_width,  int scale_height, int scale_filter_mode,
                            int rotation_degree);
  /**
   * 投递层RGBX8888图像, 详细说明请参考PostLayerImageRGBX8888ByteBuffer
   *
   * @return {0} if successful
   */
  public native int PostLayerImageRGBX8888Native(long handle, int index, int left, int top,
                           long rgbx_plane, int offset, int row_stride, int width, int height,
                           int is_vertical_flip,  int is_horizontal_flip,
                           int scale_width,  int scale_height, int scale_filter_mode,
                           int rotation_degree);
  /**
   * 投递层RGB888图像
   *
   * @param index: 层索引, 必须大于等于0
   *
   * @param left: 层叠加的左上角坐标, 对于第0层的话传0
   *
   * @param top: 层叠加的左上角坐标, 对于第0层的话传0
   *
   * @param rgb_plane: rgb888 图像数据
   *
   * @param offset: 图像偏移, 这个主要目的是用来做clip的,一般传0
   *
   * @param row_stride: stride information
   *
   * @param width: width, 必须大于1, 如果是奇数, 将减1
   *
   * @param height: height, 必须大于1, 如果是奇数, 将减1
   *
   * @param  is_vertical_flip: 是否垂直翻转, 0不翻转, 1翻转
   *
   * @param  is_horizontal_flip:是否水平翻转, 0不翻转, 1翻转
   *
   * @param  scale_width: 缩放宽,必须是偶数, 0或负数不缩放
   *
   * @param  scale_height: 缩放高, 必须是偶数, 0或负数不缩放
   *
   * @param  scale_filter_mode: 缩放质量, 传0使用默认速度,可选等级范围是:[1,3],值越大缩放质量越好, 但速度越慢
   *
   * @param  rotation_degree: 顺时针旋转, 必须是0, 90, 180, 270, 注意:旋转是在缩放, 垂直/水品反转之后再做, 请留意顺序
   *
   * @return {0} if successful
   */
  public native int PostLayerImageRGB888Native(long handle, int index, int left, int top,
                             long rgb_plane, int offset, int row_stride, int width, int height,
                             int is_vertical_flip,  int is_horizontal_flip,
                             int scale_width,  int scale_height, int scale_filter_mode,
                             int rotation_degree);

技术总结

上面大概介绍了颜色编码格式常用的类型区别和接口设计,基本上涵盖了可能用到的所有类型,如果是编码后的H.264、H.265数据,我们也做了相关的设计,不管是自带的数据类型还是第三方外部数据对接(如Unity采集的数据),都可以很容易对接进来。

相关文章
|
存储 计算机视觉
10位和16位YUV视频格式
10位和16位YUV视频格式
719 0
|
存储 编解码 Cloud Native
FFmpeg修复受损视频
FFmpeg修复受损视频
|
9月前
|
人工智能 安全 Ubuntu
保姆级教程 | 在Ubuntu上部署Claude CodeUI全过程
Claude Code Plan Mode 是 Anthropic 推出的智能编程助手功能,采用只读分析模式,保障代码安全的同时提供AI驱动的项目规划与风险评估。该模式平均每周为开发者节省27小时,显著提升开发效率与项目成功率,是AI编程领域的重要创新。
12913 10
|
安全
电机控制中对地的处理
1.当电路中有电机时,尤其是电压比较高的电机,一定要将控制电和动力电的地隔离开。如果不隔离,电机一启动,控制电路就可能不正常,比如复位、通信不正常等。 2.如果是有单独的电机驱动,那么主控板和驱动器的地最好也分开,实在不行也可以共地。
738 0
电机控制中对地的处理
|
存储 机器学习/深度学习 并行计算
【AI系统】Tensor Core 深度剖析
Tensor Core 是英伟达 GPU 的关键技术,专为加速深度学习计算设计,尤其擅长矩阵乘法和卷积运算。通过混合精度计算,Tensor Core 使用半精度(FP16)输入输出,内部以全精度(FP32)计算,确保精度同时提高效率。相比传统 CUDA Core,Tensor Core 每个时钟周期可执行 64 个浮点运算,大幅提升计算速度。其工作原理包括指令流水线、线程执行等多级优化,确保高效并行处理。通过分块、分配和并行执行策略,Tensor Core 能有效处理大规模矩阵计算,极大加速神经网络模型的训练和推断。
1542 1
【AI系统】Tensor Core 深度剖析
|
API 开发工具 Android开发
从安装到打包,手把手教你如何在Uno Platform上部署跨平台应用——一篇详尽的开发者指南
【9月更文挑战第7天】Uno Platform 是一个跨平台应用开发框架,利用UWP API构建Web、iOS、Android等多平台应用。本文详述了安装Uno Platform SDK、配置项目支持跨平台、添加主方法以及使用命令行工具进行应用打包的过程,助您快速上手 Uno Platform 并部署应用。通过简单的代码示例,让开发者轻松掌握从安装到发布的核心步骤。
1201 2
|
SQL 安全 前端开发
全栈开发者必看!前后端表单交互的最佳实践与安全考量,开启高效稳定开发之旅!
【8月更文挑战第31天】全栈开发者在软件开发中扮演着重要角色,需精通前端与后端技术。表单交互是常见的开发场景,涉及从设计直观表单到处理数据等多个环节。前端应使用清晰标签和验证提示提升用户体验,如用红色星号标示必填项;后端需严格验证数据并处理细节,如去除空格和转换类型。此外,安全防护同样关键,包括防止脚本注入和SQL攻击。遵循这些最佳实践,全栈开发者能构建稳定、安全的应用程序,不断提升用户体验。
393 1
|
编译器 PHP
php8开启jit,php8配置jit,如何在PHP8中设置开启JIT
php8开启jit,php8配置jit,如何在PHP8中设置开启JIT
1511 0
|
机器学习/深度学习 数据可视化 PyTorch
TensorFlow与PyTorch框架的深入对比:特性、优势与应用场景
【5月更文挑战第4天】本文对比了深度学习主流框架TensorFlow和PyTorch的特性、优势及应用场景。TensorFlow以其静态计算图、高性能及TensorBoard可视化工具适合大规模数据处理和复杂模型,但学习曲线较陡峭。PyTorch则以动态计算图、易用性和灵活性见长,便于研究和原型开发,但在性能和部署上有局限。选择框架应根据具体需求和场景。
2189 4

热门文章

最新文章