概述
最新需要将ffmpeg对视频硬解码之后的NV12格式通过操作像素的方式转换成RGB24,不是使用sws_getContext函数直接转换。网上找到了两个方法,分别测试可用但是效率大不相同
方式一:耗时:210ms左右
/*
功能:NV12 转 RGB24
耗时:210ms左右
使用举例:NV12_to_rgb24(0, srcSlice[0], RGB24, tex_w, tex_h) ;
因为没有区分 格式,因此第一个参数 随便写,
同时定义一个转换之后的指针:
unsigned char RGB24[1920*1080*10] = {0};
*/
static long int crv_tab[256];
static long int cbu_tab[256];
static long int cgu_tab[256];
static long int cgv_tab[256];
static long int tab_76309[256];
static unsigned char clp[1024]; //for clip in CCIR601
void init_yuv420p_table()
{
long int crv,cbu,cgu,cgv;
int i,ind;
static int init = 0;
if (init == 1) return;
crv = 104597; cbu = 132201; /* fra matrise i global.h */
cgu = 25675; cgv = 53279;
for (i = 0; i < 256; i++)
{
crv_tab[i] = (i-128) * crv;
cbu_tab[i] = (i-128) * cbu;
cgu_tab[i] = (i-128) * cgu;
cgv_tab[i] = (i-128) * cgv;
tab_76309[i] = 76309*(i-16);
}
for (i = 0; i < 384; i++)
clp[i] = 0;
ind = 384;
for (i = 0;i < 256; i++)
clp[ind++] = i;
ind = 640;
for (i = 0;i < 384; i++)
clp[ind++] = 255;
init = 1;
}
/*
函数功能:将NV12或者NV21格式数据 转换成RGB24
参数说明:
frame_type:指的是pixfmt.h中结构体 AVPixelFormat 中对应的帧格式
*/
void NV12_or_NV21_to_rgb24(int frame_type, unsigned char* yuvbuffer,unsigned char* rgbbuffer, int width,int height)
{
int y1, y2, u, v;
unsigned char *py1, *py2;
int i, j, c1, c2, c3, c4;
unsigned char *d1, *d2;
unsigned char *src_u;
static int init_yuv420p = 0;
src_u = yuvbuffer + width * height; // u
py1 = yuvbuffer; // y
py2 = py1 + width;
d1 = rgbbuffer;
d2 = d1 + 3 * width;
init_yuv420p_table();
for (j = 0; j < height; j += 2)
{
for (i = 0; i < width; i += 2)
{
if (frame_type == AV_PIX_FMT_NV12)
{
u = *src_u++;
v = *src_u++; // v紧跟u,在u的下一个位置
}
if (frame_type == AV_PIX_FMT_NV21)
{
v = *src_u++;
u = *src_u++; // u紧跟v,在v的下一个位置
}
c1 = crv_tab[v];
c2 = cgu_tab[u];
c3 = cgv_tab[v];
c4 = cbu_tab[u];
//up-left
y1 = tab_76309[*py1++];
*d1++ = clp[384+((y1 + c1)>>16)];
*d1++ = clp[384+((y1 - c2 - c3)>>16)];
*d1++ = clp[384+((y1 + c4)>>16)];
//down-left
y2 = tab_76309[*py2++];
*d2++ = clp[384+((y2 + c1)>>16)];
*d2++ = clp[384+((y2 - c2 - c3)>>16)];
*d2++ = clp[384+((y2 + c4)>>16)];
//up-right
y1 = tab_76309[*py1++];
*d1++ = clp[384+((y1 + c1)>>16)];
*d1++ = clp[384+((y1 - c2 - c3)>>16)];
*d1++ = clp[384+((y1 + c4)>>16)];
//down-right
y2 = tab_76309[*py2++];
*d2++ = clp[384+((y2 + c1)>>16)];
*d2++ = clp[384+((y2 - c2 - c3)>>16)];
*d2++ = clp[384+((y2 + c4)>>16)];
}
d1 += 3*width;
d2 += 3*width;
py1 += width;
py2 += width;
}
}
方法二:耗时700ms,但是该方法转换之后RGB24图像是上下翻转的。
该函数转换出来的RGB24函数是上下翻转的,因此可以采取以下任一方案补救
1、在执行该函数之前将NV12 翻转180°
2、在执行该函数之后将RGB24 翻转180°
这里采取的方法一,翻转函数在后面
/*
函数功能:NV12 转RGB24
* 注意:
该函数转换出来的RGB24函数是上下翻转的,因此可以采取以下任一方案补救
1、在执行该函数之前将NV12 翻转180°
2、在执行该函数之后将RGB24 翻转180°
这里采取的方法一,翻转函数在后面
*/
void NV12_T_RGB24(unsigned int width, unsigned int height, unsigned char *NV12_data, unsigned char *bgr_data) {
const int nv_start = width * height;
int i, j, index = 0, rgb_index = 0;
unsigned char y, u, v;
int r, g, b, nv_index = 0;
for (i = 0; i < height; i++) {
for (j = 0; j < width; j++) {
nv_index = i / 2 * width + j - j % 2;
y = NV12_data[rgb_index];
v = NV12_data[nv_start + nv_index];
u = NV12_data[nv_start + nv_index + 1];
r = y + (140 * (v - 128)) / 100; //r
g = y - (34 * (u - 128)) / 100 - (71 * (v - 128)) / 100; //g
b = y + (177 * (u - 128)) / 100; //b
if (r > 255)
r = 255;
if (g > 255)
g = 255;
if (b > 255)
b = 255;
if (r < 0)
r = 0;
if (g < 0)
g = 0;
if (b < 0)
b = 0;
index = rgb_index % width + (height - i - 1) * width;
bgr_data[index * 3 + 2] = r;
bgr_data[index * 3 + 1] = g;
bgr_data[index * 3 + 0] = b;
rgb_index++;
}
}
}
NV12翻转180°函数:
/*
函数功能:NV12 翻转180°
*/
int nv12rote180(unsigned char * src, unsigned char * dst, int srcW, int srcH)
{
int wide = srcW;
int high = srcH;
unsigned char * srcUV = src + wide * high;
unsigned char * destUV = dst + wide * high;
int i, j;
for(i = 0; i < high; i++){
for(j = 0; j < wide; j++){
dst[((high-1-i) * wide+wide-1-j)] = src[i * wide+j];
destUV[(((( high-1-i) / 2) * (wide / 2)+((wide-1-j) / 2)) * 2+0)] = srcUV[(((i / 2) * (wide / 2)+(j / 2)) * 2+ 0)];
destUV[(((( high-1-i) / 2) * (wide / 2)+((wide-1-j) / 2)) * 2+1)] = srcUV[(((i / 2) * (wide / 2)+(j / 2)) * 2+1)];
}
}
return 0;
}
参考链接:
1、http://www.cnblogs.com/lance-ehf/p/5310092.html
参考的其他文章记不清了,如有侵权请联系!
最后
以上就是怕黑时光为你收集整理的YUV格式初探(一)---NV12格式转RGB24的两种方式的全部内容,希望文章能够帮你解决YUV格式初探(一)---NV12格式转RGB24的两种方式所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复