1.自己写转换方法
unsigned char* I420ToRGB(unsigned char* src, int width, int height){
const int R = 0;
const int G = 1;
const int B = 2;
int numOfPixel = width * height;
int positionOfU = numOfPixel;
int positionOfV = numOfPixel/4 + numOfPixel;
unsigned char* rgb = new unsigned char[numOfPixel*3];
for(int i=0; i<height; i++){
int startY = i*width;
int step = (i/2)*(width/2);
int startU = positionOfV + step;
int startV = positionOfU + step;
for(int j = 0; j < width; j++){
int Y = startY + j;
int V = startV + j/2;
int U = startU + j/2;
int index = Y*3;
rgb[index+B] = (unsigned char)((src[Y]&0xff) + 1.4075 * ((src[V]&0xff)-128));
rgb[index+G] = (unsigned char)((src[Y]&0xff) - 0.3455 * ((src[U]&0xff)-128) - 0.7169*((src[V]&0xff)-128));
rgb[index+R] = (unsigned char)((src[Y]&0xff) + 1.779 * ((src[U]&0xff)-128));
}
}
return rgb;
}
2.借用opencv
#include <opencv2/highgui.hpp>
#include <opencv2/opencv.hpp>
unsigned char* I420ToRGB(unsigned char* src, int width, int height){
int numOfPixel = width * height;
unsigned char* rgb = new unsigned char[numOfPixel*3];
cv::Mat yuvImg;
cv::Mat rgbImg(height, width, CV_8UC3);
yuvImg.create(height * 3/2, width, CV_8UC1);
memcpy(yuvImg.data, src, numOfPixel*3/2);
cv::cvtColor(yuvImg, rgbImg, cv::ColorConversionCodes::COLOR_YUV2RGB_I420);
memcpy_s(rgb, numOfPixel*3, rgbImg.data, numOfPixel*3);
return rgb;
}
顺便opencv实现yuv转rgb
//unsigned char *src 存的是YUYV的裸数据;
cv::Mat yuvImg;
cv::Mat rgbImg(height, width,CV_8UC3);
yuvImg.create(height, width, CV_8UC2);
memcpy(yuvImg.data, src, numOfPixel*2);
cv::cvtColor(yuvImg, rgbImg, cv::ColorConversionCodes::COLOR_YUV2BGR_YUYV);
3.ffmpeg,实际运用中发现如果编解码视频opencv太费cpu了,于是尝试了ffmpeg
unsigned char* SCVidyoInstance::I420ToRGB(unsigned char* src, int width, int height){
int numOfPixel = width * height;
unsigned char* rgba = new unsigned char[numOfPixel*4];
AVFrame *frmArgb = av_frame_alloc();
AVFrame *frm420p = av_frame_alloc();
//绑定数据缓冲区
avpicture_fill((AVPicture *)frmArgb, rgba, AV_PIX_FMT_RGBA, width, height);
avpicture_fill((AVPicture *)frm420p, src, AV_PIX_FMT_YUV420P, width, height);
//指定原数据格式,分辨率及目标数据格式,分辨率
struct SwsContext *sws = sws_getContext(width, height, AV_PIX_FMT_YUV420P, width, height, AV_PIX_FMT_RGBA,
SWS_BILINEAR, NULL, NULL, NULL);
//转换
sws_scale(sws, frm420p->data, frm420p->linesize, 0, height, frmArgb->data, frmArgb->linesize);
av_frame_free(&frmArgb);
av_frame_free(&frm420p);
sws_freeContext(sws);
return rgba;
}
cpu使用率瞬间降低了不少