⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 avstream.cs

📁 该即时通讯系统系统能够实现像QQ一样的通讯功能
💻 CS
字号:
using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;using System.IO;
using LanMsg.AV;
using System.Runtime.InteropServices;
using System.Net.Sockets;
using System.Net;

namespace LanMsg.AV
{
	/// <summary>
	/// AVChanel 的摘要说明。
	/// </summary>
	public class AVChanel
	{
		private Socket sock;
		private byte[] buffer;
		private ICCompressor cp;//视频编码器
		private ICDecompressor dp;//视频解码器
		
		private G729 g729;
		private EndPoint rmtEP;
		private int localPort=2469;

		private bool connected;

		public bool Connected
		{
			get{return this.connected;}
		}


		public event AVChanelEventHandler AudioData,VideoData,SteamStart,StreamEnd,StreamError;
		public AVChanel()
		{
			this.rmtEP=new IPEndPoint(IPAddress.Any,0);
		}
		public void Open()//打开scck
		{
			this.sock=new Socket(AddressFamily.InterNetwork,SocketType.Dgram,ProtocolType.Udp);
			while(true)
			{
				try
				{
					this.sock.Bind(new IPEndPoint(IPAddress.Any,this.localPort));
					break;
				}
				catch(System.Exception ex)
				{
					System.Diagnostics.Trace.WriteLine(ex.Message);
					this.localPort++;
				}
			}
			this.ReceiveInternal();//初始化数据接收进程
			this.IniVideoCompress();//初始化视频
			this.IniAudioCompress();//初始化音频
		}

		byte[] UDPbuf=System.Text.Encoding.Default.GetBytes("9");
		public void UDPBurrowNat(System.Net.IPAddress ServerIp,int ServerPort)//UDP打洞
		{
			IPEndPoint server = new IPEndPoint( ServerIp , ServerPort); 
			this.sock.SendTo(UDPbuf,server);
		}


		public void BeginAV(byte[] buf,System.Net.IPAddress ServerIp,int ServerPort)//告诉对方开始视频(执行联接到本地的操作)
		{
			IPEndPoint server = new IPEndPoint( ServerIp , ServerPort); 
			this.sock.SendTo(buf,server);
		}


		public void SendAVtoServerRequest(byte[] buf,System.Net.IPAddress ServerIp,int ServerPort)//发送AV请求到对方,要求视频对话
		{
			IPEndPoint server = new IPEndPoint( ServerIp , ServerPort); 
            this.sock.SendTo(buf,server);//发送视频对话的请求到对方
		}

		public void Connect(string rmtip,int port)//连接到对方IP及端口,要求对方视频对话
		{
			this.rmtEP=new IPEndPoint(IPAddress.Parse(rmtip),port);	
			this.SendRequest();//发送视频请求
		}

		private void ReceiveInternal()
		{
			this.buffer=new byte[65535];//缓冲区数据接收块最大值为65535Mtu
			try
			{
				if(this.sock==null)return;
				this.sock.BeginReceiveFrom(buffer,0,buffer.Length,SocketFlags.None,ref this.rmtEP,new AsyncCallback(this.ACB),null);
			}
			catch
			{
				this.OnStreamError(new AVChanelEventArgs(null));
			}
		}
		private void ACB(System.IAsyncResult iar)//控制块
		{
			int cnt=0;
			try
			{
				if(this.sock==null)return;
				cnt=this.sock.EndReceiveFrom(iar,ref this.rmtEP);
			}
			catch
			{
				this.OnStreamError(new AVChanelEventArgs(null));
			}
			if(cnt>0)
			{
				byte[] n=new byte[cnt-1];
				Buffer.BlockCopy(this.buffer,1,n,0,cnt-1);
				switch(this.buffer[0])
				{
					case 0://收到对方发送过来的音频数据,触发音频数据到达事件
						this.OnAudioData(new AVChanelEventArgs(n));
						break;
					case 1://收到对方发送过来的视频数据,触发视频数据到达事件
						this.OnVideoData(new AVChanelEventArgs(n));
						break;
					case 2:
						if(this.rmtEP==null)
						{
							IPEndPoint rmt=(IPEndPoint)iar.AsyncState;
							this.rmtEP=rmt;
						}
						this.OnStreamStart(new AVChanelEventArgs(null));//开始视频对话在,并触发事件
						break;
					case 3:
						this.OnStreamEnd(new AVChanelEventArgs(null));//开始视频对话,并触发事件
						break;
				}
			}
			this.ReceiveInternal();
		}

		private void OnAudioData(AVChanelEventArgs e)//音频到达事件
		{
			byte[] dst=this.g729.Decode(e.Data);
			if(this.AudioData!=null)this.AudioData(this,new AVChanelEventArgs(dst));
		}

		public byte[] en(byte[] data)//将要发送的音频数据采用g729标准编码
		{
			return this.g729.Encode(data);
		}
		public byte[] de(byte[] data)//将收到的音频数据采用g729标准解码
		{
			return this.g729.Decode(data);
		}

		private void OnVideoData(AVChanelEventArgs e)//视频到达事件
		{
			byte[] decompressdata=this.dp.Process(e.Data);//解压缩
			if(this.VideoData!=null)this.VideoData(this,new AVChanelEventArgs(decompressdata));
		}

		private void OnStreamStart(AVChanelEventArgs e)
		{
			if(!this.Connected)
			{
				this.connected=true;
				if(this.SteamStart!=null)this.SteamStart(this,e);
				this.SendRequest();//发送视频对话要求
			}
		}

		private void SendRequest()//发送视频对话要求
		{
			byte[] b=new byte[1];
			b[0]=2;
			this.Send(b);	
		}

		private void SendBye()
		{
			byte[] b=new byte[1];
			b[0]=3;
			this.Send(b);	
		}

		public void Disconnect()//关闭联接
		{
			if(!this.Connected)return;
			this.SendBye();
			System.Threading.Thread.Sleep(50);
			this.connected=false;
		}
		public void Close()//关闭SOCK
		{
			if(this.sock!=null)
			{
				lock(this.sock)
				{
					this.sock.Close();
					this.sock=null;
				}
			}
			if(this.dp!=null)
			{
				this.dp.Close();
			}
			if(this.cp!=null)
			{
				this.cp.Close();
			}
		}
		private void OnStreamEnd(AVChanelEventArgs e)//数据流结束事件
		{
			this.connected=false;
			if(this.StreamEnd!=null)this.StreamEnd(this,e);
		}
		private void OnStreamError(AVChanelEventArgs e)
		{
			this.connected=false;
			if(this.StreamError!=null)this.StreamError(this,e);
		}


		private void Send(byte[] bs)//发送音视频混合数据到对方
		{
			try
			{
				this.sock.BeginSendTo(bs,0,bs.Length,SocketFlags.None,this.rmtEP,new AsyncCallback(this.SendCallback),null);
			}
			catch
			{
				this.OnStreamError(new AVChanelEventArgs(null));
			}
		}

		public int LocalPort//设置或获取本地UDP端口
		{
			get{return this.localPort;}
			set{this.localPort=value;}
		}

		public void SendCallback(System.IAsyncResult iar)
		{
			try
			{
				int cnt=this.sock.EndSendTo(iar);
			}
			catch
			{
				this.OnStreamError(new AVChanelEventArgs(null));
			}
		}
		public void SendAudio(byte[] bs)//发送音频数据到对方
		{
			byte[] compresseddata=this.g729.Encode(bs);
			byte[] buf=new byte[compresseddata.Length+1];
			buf[0]=0;
			Buffer.BlockCopy(compresseddata,0,buf,1,compresseddata.Length);
			this.Send(buf);
		}
		public void SendVideo(byte[] bs)//发送视频数据到对方
		{
//			byte[] compresseddata=this.cp.Process(bs);
//			MessageBox.Show(compresseddata.Length.ToString());
//			if(compresseddata==null)return;
//			byte[] buf=new byte[compresseddata.Length+1]; 
			byte[] buf=new byte[bs.Length+1];
			buf[0]=1;
//			Buffer.BlockCopy(compresseddata,0,buf,1,compresseddata.Length);
			Buffer.BlockCopy(bs,0,buf,1,bs.Length);
			this.Send (buf);
		}

		private void IniVideoCompress()
		{
			COMPVARS pp=new COMPVARS();
			pp.cbSize=Marshal.SizeOf(pp);
			pp.dwFlags=1;
			pp.fccHandler=FOURCC.MP42;;
			pp.fccType=FOURCC.ICTYPE_VIDEO;
			pp.lDataRate=120;
			pp.lKey=15;
			pp.lQ=-1;
			pp.lQ=1000;

			COMPVARS p2=pp;
			
			BITMAPINFOHEADER bmi=new BITMAPINFOHEADER();

			bmi.biCompression =(int) BI.BI_RGB;
			bmi.biWidth = 160;
			bmi.biHeight = 120;
			bmi.biPlanes = 1;
			bmi.biBitCount = 24;
			bmi.biXPelsPerMeter = 0;
			bmi.biYPelsPerMeter = 0;
			bmi.biClrUsed = 0;
			bmi.biClrImportant = 0;
			bmi.biSizeImage=115200;
			bmi.biSize=Marshal.SizeOf(bmi);
			BITMAPINFO bi=new BITMAPINFO();
			bi.bmiHeader=bmi;
			
			BITMAPINFOHEADER bmi2=new BITMAPINFOHEADER();
			bmi2.biCompression =FOURCC.MP42;
			bmi2.biWidth = 160;
			bmi2.biHeight = 120;
			bmi2.biPlanes = 1;
			bmi2.biBitCount = 24;
			bmi2.biXPelsPerMeter = 0;
			bmi2.biYPelsPerMeter = 0;
			bmi2.biClrUsed = 0;
			bmi2.biClrImportant = 0;
			bmi2.biSize=40;
			bmi2.biSizeImage=115200;
			BITMAPINFO bi2=new BITMAPINFO();
			bi2.bmiHeader=bmi2;

			this.dp=new ICDecompressor(new COMPVARS(),bi2,FOURCC.MP42);
			this.dp.Open();
			
			this.cp=new ICCompressor(pp,bi,FOURCC.MP42);
			this.cp.Open();
		}


		private void IniAudioCompress()//初始化G729编码标准的音频编码器
		{
			this.g729=new G729();
			this.g729.InitalizeDecode();
			this.g729.InitalizeEncode();
		}
		public delegate void AVChanelEventHandler(object sender,AVChanelEventArgs e);
		public class AVChanelEventArgs:System.EventArgs
		{
			public byte[] Data;
			public AVChanelEventArgs(byte[] data)
			{
				this.Data=data;
			}
		}
	}
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -