前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【分享】MPSoC VCU Ctrl-SW 2020.2 编码不同Stride的YUV文件

【分享】MPSoC VCU Ctrl-SW 2020.2 编码不同Stride的YUV文件

作者头像
hankfu
发布2021-05-20 14:39:29
8380
发布2021-05-20 14:39:29
举报
文章被收录于专栏:hankhank

MPSoC VCU Ctrl-SW 2020.2 编码不同Stride的YUV文件

付汉杰 hankf@xilinx.com

目录

1. 介绍

Xilinx提供超低延时编解码方案,并提供了全套软件。MPSoC Video Codec Unit提供了详细说明。其中的底层应用软件是VCU Control-Software(Ctrl-SW)

本文主要说明为Ctrl-SW增加功能,支持不同Stride/Pitch(步长)的YUV文件的编码。

1.1. VCU输入和输出格式

Video Codec Unit(VCU) 输入和输出都是是NV12/NV16格式的视频,Y分量存放在一块连续内存区,UV分量交替存放在Y分量后面的连续内存。具体信息,可以参考VCU Product Guide中的“Source Frame Format”和“Memory Format”。

1.2. VCU内存的pitch

视频数据在内存区中存放时,两行之间的数据可以有间隔。对于每个像素的Y分量用8-bit表示的图像,每个像素的Y分量对应内存的一个字节,图像Y分量的每一行对应的内存大小就是其宽度代表的字节数。比如1920x1080,每一行图像的Y分量需要1920字节内存。如果以2048字节来存储一行1920x1080的图像数据,则在前面存放图像数据,后面的数据被VCU忽略。也可以参考PG252的“Figure 7: Frame Buffer Pitch”。

2. 输入文件分辨率

与视频数据在内存区中存放一样,视频数据在文件中存放时也有类似的情况。

Ctrl-SW假设输入文件的分辨率一般和实际图像分辨率一致,也就是pitch和图像宽度一致。但是实际应用时,输入文件的分辨率、实际图像分辨率并不一致。在文件里,有一部分数据是真实图像数据,有一部分是无用数据。比如有YUV NV12文件的文件分辨率是3840x1080,实际图像的分辨率是1920x1080。每一行的数据中,只有前面1920字节是有效图像数据,后面的1920字节是冗余数据。

3. 代码

为了支持这种场景,需要修改代码。Ctrl-SW的读YUV文件的代码,在文件YuvIO.cpp里的函数ReadOneFrameYuv()里。下面是基于Ctrl-SW 2020.2的修改。

首先定义一个全局变量,用于存储输入文件的Stride/Pitch(步长)。

代码语言:javascript
复制
    int gi_encoder_input_stride=0;

接下来增加的ctrlsw_encoder的命令行选项。这样命令行选项里可以对图像步长gi_encoder_input_stride赋值。

代码语言:javascript
复制
	opt.addInt("--input-stride", &gi_encoder_input_stride, "Stride in input YUV file.");

最后修改函数ReadOneFrameYuv()。原来的代码,直接使用真实图像宽度计算YUV文件里每行的数据的字节数,代码是“uRowSizeLuma = GetIOLumaRowSize(tFourCC, tDim.iWidth)”。修改后的代码,使用真实图像宽度作为YUV文件里图像步长iYuvStride的缺省值。另外增加代码,检查命令行选项里赋值的图像步长gi_encoder_input_stride。如果gi_encoder_input_stride不为0,则将gi_encoder_input_stride赋值给图像步长iYuvStride。接下来使用图像步长iYuvStride计算YUV文件里,每行的数据的字节数。

代码语言:javascript
复制
bool ReadOneFrameYuv(std::ifstream& File, AL_TBuffer* pBuf, bool bLoop)
{
  if(!pBuf || !File.is_open())
    throw std::runtime_error("invalid argument");

  if((File.peek() == EOF) && !bLoop)
    return false;

  TFourCC tFourCC = AL_PixMapBuffer_GetFourCC(pBuf);
  AL_TDimension tDim = AL_PixMapBuffer_GetDimension(pBuf);

  int32_t iYuvStride = tDim.iWidth;  
  if( 0 != gi_encoder_input_stride )
  {
	  iYuvStride = gi_encoder_input_stride;
	  LogVerbose("New YUV width size:%d at %s:%d.\n", iYuvStride, __func__, __LINE__ );
  }

  //uint32_t uRowSizeLuma = GetIOLumaRowSize(tFourCC, tDim.iWidth);
  uint32_t uRowSizeLuma = GetIOLumaRowSize(tFourCC, iYuvStride);
  LogVerbose("YUV Luma row size:%d at %s:%d.\n", uRowSizeLuma, __func__, __LINE__ );

  ReadFile(File, pBuf, uRowSizeLuma, tDim.iHeight);

  if((File.rdstate() & std::ios::failbit) && bLoop)
  {
    File.clear();
    File.seekg(0, std::ios::beg);
    ReadFile(File, pBuf, uRowSizeLuma, tDim.iHeight);
  }

  if(File.rdstate() & std::ios::failbit)
    throw std::runtime_error("not enough data for a complete frame");

  return true;
}

其它的代码,不需要修改。

注意,YUV文件里图像步长(stride/pitch),要不小于内存里的图像步长(stride/pitch)。因此,测试时,同时使用了选项“--stride”和选项“--input-stride”。

4. 测试

测试了输入分辨率是3840x1080的NV12 yuv文件,编码图像分辨率1920x1080,得到了正确的265文件。命令如下:

代码语言:javascript
复制
./ctrlsw_encoder -cfg test-1920x1080-3840x1080.cfg  --stride 3840 --input-stride 3840

有意思的是,结合选项“--stride”、选项“--stride-height”、和选项“--input-stride”,相等于在编码前对图像实现了裁剪(crop)功能。

5. 其它

5.1. 命令行选项“--input-width”,和“--input-height”

Ctrl-SW 2020.2里有两个命令行选项,“--input-width”,和“--input-height”。这两个选用用于指定实际图像分辨率,可以取代配置文件里的图像分辨率。这个选项并不能指定输入文件的分辨率。

代码语言:javascript
复制
  opt.addInt("--input-width", &cfg.MainInput.FileInfo.PictWidth, "Specifies YUV input width");
  opt.addInt("--input-height", &cfg.MainInput.FileInfo.PictHeight, "Specifies YUV input height");

6. 未来工作

未来可以继续测试NV16的图像,也可以测试其它分辨率的图像。

7. 参考文档

XilinxPG252 (v2020.2) H.264/H.265 Video Codec Unit v1.2 Solution

MPSoC VCU Ctrl-SW 2020.2 输出NV12的YUV文件

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2021-05-18 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • MPSoC VCU Ctrl-SW 2020.2 编码不同Stride的YUV文件
  • 1. 介绍
    • 1.1. VCU输入和输出格式
      • 1.2. VCU内存的pitch
      • 2. 输入文件分辨率
      • 3. 代码
      • 4. 测试
      • 5. 其它
        • 5.1. 命令行选项“--input-width”,和“--input-height”
        • 6. 未来工作
        • 7. 参考文档
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档