因为需要把NV21的1080p视频转成YV12,又不知道用什么工具,所以直接写了代码
可能代码有点问题,不过能实现我的要求,但还是希望各位大手子在留言区点评下。
这是Ubuntu系统下的代码,可能在windows上有所不同。因为懒得弄输入法,所以当时写的是英文的注释,见谅
#include <QCoreApplication>
#include <opencv2/world.hpp>
#include <opencv2/core.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/imgproc.hpp>
#include <memory>
#include <fstream>
#include <cstdlib>
#include <stdio.h>
using namespace std;
using namespace cv;
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
// 1080p
uint64_t lenth = 1080 * 1920 * 3 / 2;
string read_file_name = "/newSpace/200_1080p.nv21";
ifstream ifs(read_file_name);
FILE *save_file;
save_file = fopen("/newSpace/result.YUV", "ab+");
// 获取文件大小
ifs.seekg(0, ifs.end);
uint64_t src_size = static_cast<uint64_t>(ifs.tellg());
ifs.seekg(0, ifs.beg); //一定要把它移回开头
// max index of the file
uint64_t max_index = src_size / lenth;
uint8_t *result = new uint8_t[lenth];
// loop
for (uint64_t index = 0; index < max_index; index++) {
uint8_t *p = new uint8_t[lenth];
uint8_t *head = p;
uint8_t c;
uint64_t count = lenth * index;
// get bytes from file
while (count < lenth * (index + 1) ) {
c = static_cast<uint8_t>(ifs.get());
count++;
if (count < lenth * index) {
continue;
}
*p = c;
p++;
}
// convert I420 to YV12
Mat pic1(1080 * 3 / 2, 1920, CV_8UC1, head);
Mat pic2(1080, 1920, CV_8UC3);
Mat pic3;
cvtColor(pic1, pic2, CV_YUV2BGRA_NV21);
cvtColor(pic2, pic3, CV_BGRA2YUV_YV12);
// 这个是为了deubg
// imwrite("/newSpace/" + to_string(index) + "-0.jpg", pic1);
// imwrite("/newSpace/" + to_string(index) + "-1.jpg", pic2);
// imwrite("/newSpace/" + to_string(index) + "-2.jpg", pic3);
// copy the picture to result
::memcpy(result, pic3.data, lenth);
// delete[] p;
// save
fwrite(result, 1, lenth, save_file);
}
return a.exec();
}