123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272 |
- using CScript.Net;
- using CScript.Utilities;
- using System;
- using System.Collections;
- using System.Collections.Generic;
- using System.IO;
- using System.Runtime.InteropServices;
- using System.Threading;
- using UnityEngine;
- namespace CScript.Quick
- {
- public class QuickAudioVideoManager : MonoSingleton<QuickAudioVideoManager>
- {
- public PackageHandler packageHandler = new PackageHandler(null);
- [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
- public delegate int OnVideoFrameCallBackDelegate(IntPtr frame, int frameLen, int timestamp);
- [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
- public delegate int OnAudioFrameCallBackDelegate(IntPtr frame, int frameLen, int timestamp);
- [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
- public delegate int OnLogCallBackDelegate(int state, string msg);
- [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
- public delegate IntPtr OnWriteCallBackDelegete();
- [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
- public delegate int OnCloseCallBackDelegate();
- /**
- *
- * @param channel 传输方式 支持tcp或quic
- * @param ip 服务端 IP
- * @param port 服务端 Port
- * @param isW 是否开启 socket写入回调 1:开启写入 0:不开启写入
- * @param wInter 开启socket写入回调的循环间隔,单位毫秒 1-30000
- * @param retryCount 重连服务器的次数 0:一直重连 ,1:重连一次 2:重连2次,以此类推
- * @param retryInter 重连服务器的间隔,单位毫秒 1-30000
- * @param onVideoFrameCb 视频帧回调
- * @param onAudioFrameCb 音频帧回调
- * @param onLogCb 日志回调
- * @param onWriteCb socket写入数据回调
- * @param onCloseCb 是否关闭连接回调
- * @return
- */
- [DllImport("AvClient")]
- public static extern IntPtr AvClientConnect(string channel, string ip, int port, int isW, int wInter, int retryCount, int retryInter,
- OnVideoFrameCallBackDelegate onVideoFrameCb, OnAudioFrameCallBackDelegate onAudioFrameCb,
- OnLogCallBackDelegate onLogCb, OnWriteCallBackDelegete onWriteCb, OnCloseCallBackDelegate onCloseCb
- );
- private string _quickServerIP;
- private int _quickServerPort;
- public AudioSource audio;
- private int buffPosAudio = 0;
- int positionAudio = 0;
- private byte[] databuff;
- private MemoryStream _receiveAudioBuffer = new MemoryStream(44100 * 12);
- private Thread _quickThread;
- bool isPlay = false;
- private MemoryStream _audioBuffer = new MemoryStream(4096);
- public readonly int sampleLength = 44100 * 12;
- private int closeSign = 0;
- const int DEF_RECV_BUFFER_SIZE = 409600 * 4;
- private MemoryStream _receiveVideoBuffer = new MemoryStream(DEF_RECV_BUFFER_SIZE);
- private string serverType = "tcp";
- public void Init(string ip, int port)
- {
- _quickServerIP = ip;
- _quickServerPort = port;
- positionAudio = 0;
- closeSign = 0;
- switch (App.AppManager.Instance.connectType)
- {
- case App.ConnectType.None:
- break;
- case App.ConnectType.TCPServer:
- serverType = "tcp";
- break;
- case App.ConnectType.Quic:
- serverType = "quic";
- break;
- default:
- break;
- }
- Debug.Log("serverType:"+serverType);
- if (_quickThread == null || !_quickThread.IsAlive)
- {
- _quickThread = new Thread(StartQuick);
- _quickThread.Start();
- }
- NetDistribute.Instance.OnConnect(true, "success");
- }
- void StartQuick()
- {
- //AvClientConnect(serverType, _quickServerIP, _quickServerPort,
- // OnNewConnCallBack, OnConnClosedCallBack,
- // OnVideoFrameCallBack, OnAudioFrameCallBack,
- // OnLogCallBack
- // );
- int isW = 0;
- int wInter = 1000;
- int retryCount = 0;
- int retryInter = 1000;
- AvClientConnect(serverType, _quickServerIP, _quickServerPort, isW, wInter, retryCount, retryInter,
- OnVideoFrameCallBack, OnAudioFrameCallBack,
- OnLogCallBack, OnWriteCallBack, OnCloseCallBack);
- }
- private int OnCloseCallBack()
- {
- //检测应用层是否关闭连接
- /**
- * 返回值说明:
- * 返回值类型为 c#的Int
- * 返回 0 表示继续保持当前连接
- * 返回 100 表示关闭当前连接
- */
- return closeSign;
- }
- private IntPtr OnWriteCallBack()
- {
- //动态库回调应用层写入数据
- /**
- * 返回值说明:
- * 返回值类型为 c#的IntPtr
- * 返回值的前4个字节表示(发送字节流的长度)
- * 返回值从第4个字节之后的所有字节表示发送的内容字节流
- * 如果当前无数据,请确保前4个字节表示的值的长度为0
- */
- //int writeBufLen = 1003;// 发送字节流的长度
- //byte[] writeBufLenBytes = BitConverter.GetBytes(writeBufLen);// 内容长度转为4个字节
- byte[] writeBuf = new byte[4 + 1003];
- //for (int i = 0; i < 4; i++)
- //{
- // writeBuf[i] = writeBufLenBytes[i];
- //}
- //int size = writeBuf.Length;
- IntPtr p = Marshal.AllocHGlobal(0);
- Marshal.Copy(writeBuf, 0, p, 0);
- return p;
- }
- private int OnLogCallBack(int state, string msg)
- {
- //日志回调
- Console.WriteLine("c# OnLogCallBack state=" + state.ToString() + ",msg=" + msg);
- if (state == 100)
- {
- NetDistribute.Instance.OnConnect(true, "success");
- }
- /**
- * state=99 :开始连接
- * state=100 :连接成功
- * state=101 :连接已经断开
- */
- return 0;
- }
- private int OnVideoFrameCallBack(IntPtr frame, int frameLen, int timestamp)
- {
- Debug.Log("c# OnVideoFrameCallBack frameLen=" + frameLen.ToString() + ",timestamp=" + timestamp.ToString());
- Marshal.Copy(frame, this._receiveVideoBuffer.GetBuffer(), 0, frameLen);
- this.packageHandler.ReceiveQuicData(this._receiveVideoBuffer.GetBuffer(), 0, frameLen);
-
- return 0;
- }
- private int OnAudioFrameCallBack(IntPtr frame, int frameLen, int timestamp)
- {
- byte[] buf = new byte[frameLen];
- Marshal.Copy(frame, _audioBuffer.GetBuffer(), 0, frameLen);
- _receiveAudioBuffer.Write(_audioBuffer.GetBuffer(), 0, frameLen);
- if (!isPlay)
- {
- if (_receiveAudioBuffer.Length > 4096 * 4)
- {
- isPlay = true;
- positionAudio = 0;
- AudioClip clip = AudioClip.Create("MySinusoid1", sampleLength, 1, 44100, true, OnAudioRead);//307200/2(audioBuffer.GetBuffer().Length - buffPos) / 4
- audio.clip = clip;
- audio.Play();
- }
- }
- Debug.Log("c# OnAudioFrameCallBack frameLen=" + frameLen.ToString() + ",timestamp=" + timestamp.ToString() + "$$$ " + _receiveAudioBuffer.Length);
- return 0;
- }
- void OnAudioRead(float[] data)
- {
- int count = 0;
- float[] floatValue = null;
- // Debug.Log("开始 isPlay:" + isPlay + "buffPos:" + buffPos + " position :"+ position + " sampleLength:"+ sampleLength);
- if (!isPlay)
- {
- if (positionAudio < sampleLength)
- {
- isPlay = true;
- }
- }
- if (isPlay)
- {
- if (buffPosAudio < _receiveAudioBuffer.Length)
- {
- // Debug.LogWarning("播放中 buffPos:"+ buffPos + " data.Length: "+ data.Length);
- floatValue = GetByte2Float(_receiveAudioBuffer.GetBuffer(), buffPosAudio, data.Length * 4);
- buffPosAudio += data.Length * 4;
- }
- }
- while (count < data.Length)
- {
- // data[count] = floatValue[count];//11
- data[count] = floatValue == null ? 0 : floatValue[count]*3;
- count++;
- }
- positionAudio += data.Length;
- if (positionAudio >= sampleLength)
- {
- isPlay = false;
- long size = _receiveAudioBuffer.Position - buffPosAudio;
- if (buffPosAudio < _receiveAudioBuffer.Position)
- {
- Array.Copy(_receiveAudioBuffer.GetBuffer(), this.buffPosAudio, _receiveAudioBuffer.GetBuffer(), 0, _receiveAudioBuffer.Position - this.buffPosAudio);
- }
- _receiveAudioBuffer.Position = size;
- _receiveAudioBuffer.SetLength(size);
- buffPosAudio = 0;
- }
- //Debug.LogWarning("播放结束:"+ position + " ^^^ " + buffPos + " () " + isPlay + " " + sampleLength);
- }
- public void Close()
- {
- closeSign = 100;
- }
- private float[] GetByte2Float(byte[] rawData)
- {
- float[] samples = new float[rawData.Length / 4];
- float rescaleFactor = 32767;
- short st = 0;
- float ft = 0;
- for (int i = 0; i < rawData.Length; i += 4)
- {
- st = BitConverter.ToInt16(rawData, i);
- ft = st / rescaleFactor;
- samples[i / 4] = ft;
- }
- return samples;
- }
- private float[] GetByte2Float(byte[] buffer, int start, int count)
- {
- byte[] realBuffer = new byte[count];
- Array.Copy(buffer, start, realBuffer, 0, count);
- return GetByte2Float(realBuffer);
- }
- }
- }
|