学音视频一定要掌握这几个算法

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;
}

以上是关于学音视频一定要掌握这几个算法的主要内容,如果未能解决你的问题,请参考以下文章

Linux系统用户网络磁盘命令

掌握这几个算法题.NET初级面试算法不发愁

零基础学python需要注意哪些问题

Git很麻烦?只要掌握这几个命令,轻松将代码提交远程仓库

天天肝大厂面试题?这几个面试必考算法你掌握了吗?

javascript 要怎么去学?