📄 avstream.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 + -