我有一个 YUV422 的一纬数组 知道长宽 怎么计算出 linesize 并 使用 sws_scale 转换成 YUV420P
时间: 2023-12-03 07:44:35 浏览: 120
假设你的 YUV422 数据是存储在一个名为 `yuv422_data` 的一维数组中,长为 `width`,宽为 `height`,那么可以通过下面的公式计算出 `linesize`:
```c++
int linesize = width * 2; // 因为每个像素占用 2 字节
```
接下来,你可以使用 FFmpeg 中的 `libswscale` 库来进行 YUV422 到 YUV420P 的转换。下面是一个简单的代码示例:
```c++
#include <iostream>
#include <fstream>
#include <cstring>
#include <cmath>
extern "C" {
#include <libswscale/swscale.h>
}
int main()
{
// 输入参数
const int width = 640;
const int height = 480;
const int linesize = width * 2;
// YUV422 数据
std::ifstream ifs("input.yuv422", std::ios::binary);
std::vector<uint8_t> yuv422_data(linesize * height);
ifs.read(reinterpret_cast<char*>(yuv422_data.data()), yuv422_data.size());
// 初始化 sws 上下文
SwsContext* sws_ctx = sws_getContext(width, height, AV_PIX_FMT_YUYV422, width, height, AV_PIX_FMT_YUV420P, 0, nullptr, nullptr, nullptr);
if (!sws_ctx) {
std::cerr << "Failed to create SwsContext" << std::endl;
return -1;
}
// 转换为 YUV420P
std::vector<uint8_t> yuv420p_data(width * height * 3 / 2);
uint8_t* src_data[1] = { yuv422_data.data() };
int src_linesize[1] = { linesize };
uint8_t* dst_data[3] = { yuv420p_data.data(), yuv420p_data.data() + width * height, yuv420p_data.data() + width * height * 5 / 4 };
int dst_linesize[3] = { width, width / 2, width / 2 };
int ret = sws_scale(sws_ctx, src_data, src_linesize, 0, height, dst_data, dst_linesize);
if (ret < 0) {
std::cerr << "Failed to sws_scale" << std::endl;
return -1;
}
// 输出 YUV420P 数据
std::ofstream ofs("output.yuv420p", std::ios::binary);
ofs.write(reinterpret_cast<const char*>(yuv420p_data.data()), yuv420p_data.size());
// 释放资源
sws_freeContext(sws_ctx);
return 0;
}
```
上述代码中,我们首先读取 YUV422 数据,并计算出 `linesize`。接着,我们初始化一个 `SwsContext` 对象,用于进行格式转换。这里我们将 YUV422 转换为 YUV420P,因此输入格式为 `AV_PIX_FMT_YUYV422`,输出格式为 `AV_PIX_FMT_YUV420P`。然后我们定义输入和输出的数据指针和行宽数组,并调用 `sws_scale` 函数进行转换。最后,我们将转换后的 YUV420P 数据保存到文件中,并释放资源。
阅读全文