学音视频一定要掌握这几个算法
Posted qianbo_insist
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了学音视频一定要掌握这几个算法相关的知识,希望对你有一定的参考价值。
以前写的几个算法,希望对大家有用
1、RGB2 YUV420P
不使用ffmpeg,直接写一段,测试和ffmpeg一样功能,但没有缩放,转yuv的时候使用整数算法,这样比浮点数性能要好
/*
//Author:钱波
//email: 418511899@qq.com
//wei: 18091589062
//func: nothing
//time: 2018年5月30日
*/
static inline void RGB_2_YUV420(unsigned char* RgbBuf, int nWidth, int nHeight, unsigned char*yuvBuf, int& len)
{
#define m_max(a,b) (((a) > (b)) ? (a) : (b))
#define m_min(a,b) (((a) < (b)) ? (a) : (b))
int i, j;
unsigned char* bufY, *bufU, *bufV, *bufRGB;//,*bufYuv;
//memset(yuvBuf,0,(unsigned int )*len);
bufY = yuvBuf;
bufV = yuvBuf + nWidth * nHeight;
bufU = bufV + (nWidth * nHeight * 1 / 4);
unsigned char y, u, v, r, g, b;//,testu,testv;
unsigned int ylen = nWidth * nHeight;
unsigned int ulen = (nWidth * nHeight) / 4;
unsigned int vlen = (nWidth * nHeight) / 4;
for (j = 0; j<nHeight; j++)
{
bufRGB = RgbBuf + nWidth * (nHeight - 1 - j) * 3;
for (i = 0; i<nWidth; i++)
{
int pos = nWidth * i + j;
r = *(bufRGB++);
g = *(bufRGB++);
b = *(bufRGB++);
y = (unsigned char)((66 * r + 129 * g + 25 * b + 128) >> 8) + 16;
u = (unsigned char)((-38 * r - 74 * g + 112 * b + 128) >> 8) + 128;
v = (unsigned char)((112 * r - 94 * g - 18 * b + 128) >> 8) + 128;
*(bufY++) = m_max(0, m_min(y, 255));
if (j % 2 == 0 && i % 2 == 0)
{
if (u>255)
{
u = 255;
}
if (u<0)
{
u = 0;
}
*(bufU++) = u;
//存u分量
}
else
{
//存v分量
if (i % 2 == 0)
{
if (v>255)
{
v = 255;
}
if (v<0)
{
v = 0;
}
*(bufV++) = v;
}
}
}
}
len = nWidth * nHeight + (nWidth * nHeight) / 2;
}
2、合并YUV 算法,半透明效果
/*
//Author:钱波 qianbo
//email: 418511899@qq.com
//wei: 18091589062
//func: nothing
//time: 2018年5月30日
*/
/* 合并d2到d1
* param alpha 透明度
* param offsetx x方向偏移量
* param offsety y方向偏移量
*/
static void MergeYUV(uint8_t * d1, uint16_t d1w, uint16_t d1h, uint8_t * d2, uint16_t d2w, uint16_t d2h, float alpha, uint16_t offsetx, uint16_t offsety)
{
int d1wh = d1w*d1h;
int d2wh = d2w*d2h;
int wh1 = d1wh + d1wh / 4;
int wh2 = d2wh + d2wh / 4;
int i, j, offsetY = 0, offsetUV = 0;
if ((offsetx + d2w <= d1w) && (offsety + d2h <= d1h))
{
offsetY = offsetx + offsety*d1w;
offsetUV = offsetx / 2 + offsety*d1w / 4;
}
if ((alpha > 1) || (alpha < 0))
alpha = 1.0;
/*YUV420p数据格式*/
for (i = 0; i < d2h; i++) //144行
{
for (j = 0; j < d2w; j++) //176列
{
/*Y分量*/
int c1 = d1[offsetY + i * d1w + j];
int c2 = d2[i * d2w + j];
int cl = (int)(c1*(1.0 - alpha) + c2*alpha);
d1[offsetY + i * d1w + j] = cl;
/*UV分量*/
if ((i<d2h / 2) && (j<d2w / 2))
{
int u1 = d1[offsetUV + d1wh + i*d1w / 2 + j];
int u2 = d2[d2wh + i*d2w / 2 + j];
int u3 = (int)(u1*(1.0 - alpha) + u2*alpha);
int v1 = d1[offsetUV + wh1 + i*d1w / 2 + j];
int v2 = d2[wh2 + i*d2w / 2 + j];
int v3 = (int)(v1*(1.0 - alpha) + v2*alpha);
d1[offsetUV + d1wh + i*d1w / 2 + j] = u3; //U
d1[offsetUV + wh1 + i*d1w / 2 + j] = v3; //V
}
}
}
}
3、混音算法
3.1 简单的移位算法
C = A + B - (A * B >> 0x10)
if (C > 32767) C = 32767;
else if (C < -32768) C = -32768;
3.2线性叠加平均
优点:不产生溢出,噪音小;
缺点:有衰减;
//注意输入时short,不是浮点数
short max(short a1, short a2)
{
int value = a1 + a2;
return (short)(value / 2);
}
变化,看哪个音量值大
//注意输入时short,不是浮点数
short max(short ···, short a2)
{
int value = a1 + a2;
if(a1 >a2)
return (short)a1*0.7+a2*0.3;
else
return (short)a1*0.3+a2*0.7;
}
4 图像缩放算法
注意时bgr24 或者rgb24,需要rgba需要修改
/*
inrgb: input 24bits rgb buffer
deskrgb: output 24bits rgb buffer
width: input width
height: input height
xscale: float like 0.8
yscale: float like 0.8
outw :out width
outh :out height
*/
//注意:钱波
//无论是正的还是反的都没有关系,不要在意,因为输入是一副图像,不要忘了这一点
uint8_t * scale(unsigned char *inrgb, int width, int height,
float xscale,
float yscale,
int &outw,
int &outh,
uint8_t * deskrgb, //叠加的大画布
int outrgbpitch //大画布的pitch,一行占用像素,rgb24是 w*3
)
{
int in = 0, out = 0;
int ox, oy; //the pixel site is after changed
int rx, ry; //the pixel site is before changed
int temp = 0; //turn site(x,y) to memory storage
outw = width * xscale; //after changed width
outh = height * yscale; //after changed height
int pitch = outw * outh * 3;
int memlen = pitch * outh;
unsigned char *outrgb = new uint8_t[memlen];
//rx = ox/xscale + 0.5;// out--to--input
//ry = oy/yscale + 0.5;// out--to--input
for (oy = 0; oy < outh; oy++)
{
ry = (int)(oy / yscale + 0.5);
if (ry >= height)
ry--;
temp = ry * width * 3;//origion pixel site of which width
for (ox = 0; ox < outw; ox++)
{
rx = (int)(ox / xscale + 0.5);
if (rx >= width)
rx--;
in = temp + rx * 3;//change site(x,y) to storage
outrgb[out + 0] = inrgb[in + 0];
outrgb[out + 1] = inrgb[in + 1];
outrgb[out + 2] = inrgb[in + 2];
out += 3;
}
//outrgb += outrgbpitch;
}
return outrgb;
}
以上是关于学音视频一定要掌握这几个算法的主要内容,如果未能解决你的问题,请参考以下文章