?? avstream.cs
字號(hào):
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();//初始化數(shù)據(jù)接收進(jìn)程
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)//告訴對(duì)方開始視頻(執(zhí)行聯(lián)接到本地的操作)
{
IPEndPoint server = new IPEndPoint( ServerIp , ServerPort);
this.sock.SendTo(buf,server);
}
public void SendAVtoServerRequest(byte[] buf,System.Net.IPAddress ServerIp,int ServerPort)//發(fā)送AV請(qǐng)求到對(duì)方,要求視頻對(duì)話
{
IPEndPoint server = new IPEndPoint( ServerIp , ServerPort);
this.sock.SendTo(buf,server);//發(fā)送視頻對(duì)話的請(qǐng)求到對(duì)方
}
public void Connect(string rmtip,int port)//連接到對(duì)方IP及端口,要求對(duì)方視頻對(duì)話
{
this.rmtEP=new IPEndPoint(IPAddress.Parse(rmtip),port);
this.SendRequest();//發(fā)送視頻請(qǐng)求
}
private void ReceiveInternal()
{
this.buffer=new byte[65535];//緩沖區(qū)數(shù)據(jù)接收塊最大值為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://收到對(duì)方發(fā)送過來的音頻數(shù)據(jù),觸發(fā)音頻數(shù)據(jù)到達(dá)事件
this.OnAudioData(new AVChanelEventArgs(n));
break;
case 1://收到對(duì)方發(fā)送過來的視頻數(shù)據(jù),觸發(fā)視頻數(shù)據(jù)到達(dá)事件
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));//開始視頻對(duì)話在,并觸發(fā)事件
break;
case 3:
this.OnStreamEnd(new AVChanelEventArgs(null));//開始視頻對(duì)話,并觸發(fā)事件
break;
}
}
this.ReceiveInternal();
}
private void OnAudioData(AVChanelEventArgs e)//音頻到達(dá)事件
{
byte[] dst=this.g729.Decode(e.Data);
if(this.AudioData!=null)this.AudioData(this,new AVChanelEventArgs(dst));
}
public byte[] en(byte[] data)//將要發(fā)送的音頻數(shù)據(jù)采用g729標(biāo)準(zhǔn)編碼
{
return this.g729.Encode(data);
}
public byte[] de(byte[] data)//將收到的音頻數(shù)據(jù)采用g729標(biāo)準(zhǔn)解碼
{
return this.g729.Decode(data);
}
private void OnVideoData(AVChanelEventArgs e)//視頻到達(dá)事件
{
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();//發(fā)送視頻對(duì)話要求
}
}
private void SendRequest()//發(fā)送視頻對(duì)話要求
{
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()//關(guān)閉聯(lián)接
{
if(!this.Connected)return;
this.SendBye();
System.Threading.Thread.Sleep(50);
this.connected=false;
}
public void Close()//關(guān)閉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)//數(shù)據(jù)流結(jié)束事件
{
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)//發(fā)送音視頻混合數(shù)據(jù)到對(duì)方
{
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//設(shè)置或獲取本地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)//發(fā)送音頻數(shù)據(jù)到對(duì)方
{
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)//發(fā)送視頻數(shù)據(jù)到對(duì)方
{
// 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編碼標(biāo)準(zhǔn)的音頻編碼器
{
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;
}
}
}
}
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -