标签:turn erp hal 成功 ansi user 连接失败 poi eof
本文是在使用由 EasyDarwin 团队开发的EasyPusher时导出的C++接口的.NET实现
public class EasyPushSDK { public EasyPushSDK() { } [StructLayoutAttribute(LayoutKind.Sequential)] public struct EASY_AV_Frame { public uint u32AVFrameFlag; /* 帧标志 视频 or 音频 */ public uint u32AVFrameLen; /* 帧的长度 */ public uint u32VFrameType; /* 视频的类型,I帧或P帧 */ public IntPtr pBuffer; /* 数据 */ public uint u32TimestampSec; /* 时间戳(秒)*/ public uint u32TimestampUsec; /* 时间戳(微秒) */ } public enum EASY_PUSH_STATE_T { EASY_PUSH_STATE_CONNECTING = 1, /* 连接中 */ EASY_PUSH_STATE_CONNECTED, /* 连接成功 */ EASY_PUSH_STATE_CONNECT_FAILED, /* 连接失败 */ EASY_PUSH_STATE_CONNECT_ABORT, /* 连接异常中断 */ EASY_PUSH_STATE_PUSHING, /* 推流中 */ EASY_PUSH_STATE_DISCONNECTED, /* 断开连接 */ EASY_PUSH_STATE_ERROR } [StructLayoutAttribute(LayoutKind.Sequential)] public struct EASY_MEDIA_INFO_T { public uint u32VideoCodec; /* 视频编码类型 */ public uint u32VideoFps; /* 视频帧率 */ public uint u32AudioCodec; /* 音频编码类型 */ public uint u32AudioSamplerate; /* 音频采样率 */ public uint u32AudioChannel; /* 音频通道数 */ public uint u32AudioBitsPerSample; /* 音频采样精度 */ public uint u32H264SpsLength; /* 视频sps帧长度 */ public uint u32H264PpsLength; /* 视频pps帧长度 */ [MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 128)] public char[] u8H264Sps; /* 视频sps帧内容 */ [MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 36)] public char[] u8H264Pps; /* 视频sps帧内容 */ } /// <summary> /// Easies the pusher_ activate. /// </summary> /// <param name="license">The license.</param> /// <returns>System.Int32.</returns> /// <remarks> /// <para>创建:***</para> /// <para>日期:2016/11/22</para> /// </remarks> [DllImport(@"..\bin\libEasyPusher.dll")] // -1, /* 无效Key */ // -2, /* 时间错误 */ // -3, /* 进程名称长度不匹配 */ // -4, /* 进程名称不匹配 */ // -5, /* 有效期校验不一致 */ //-6, /* 平台不匹配 */ // -7, /* 授权使用商不匹配 */ // 0, /* 激活成功 */ public static extern int EasyPusher_Activate(string license); [DllImport(@"..\bin\libEasyPusher.dll")] /* 创建推送句柄 返回为句柄值 */ public static extern IntPtr EasyPusher_Create(); [DllImport(@"..\bin\libEasyPusher.dll")] /* 释放推送句柄 */ public static extern uint EasyPusher_Release(IntPtr pushPtr); [UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl, CharSet = CharSet.Ansi)] public delegate int EasyPusher_Callback(int _id, EASY_PUSH_STATE_T _state, ref EASY_AV_Frame _frame, IntPtr _userptr); [DllImport(@"..\bin\libEasyPusher.dll", CallingConvention = CallingConvention.Cdecl)] /* 设置流传输事件回调 userptr传输自定义对象指针*/ public static extern uint EasyPusher_SetEventCallback(IntPtr handle, EasyPusher_Callback callback, int id, IntPtr userptr); /* 开始流传输 serverAddr:流媒体服务器地址、port:流媒体端口、streamName:流名称<xxx.sdp>、username/password:推送携带的用户名密码、pstruStreamInfo:推送的媒体定义、bufferKSize:以k为单位的缓冲区大小<512~2048之间,默认512> bool createlogfile:创建日志文件*/ [DllImport(@"..\bin\libEasyPusher.dll")] public static extern uint EasyPusher_StartStream(IntPtr handle, string serverAddr, uint port, string streamName, string username, string password, ref EASY_MEDIA_INFO_T pstruStreamInfo, uint bufferKSize, bool createlogfile); [DllImport(@"..\bin\libEasyPusher.dll")] /* 停止流传输 */ public static extern uint EasyPusher_StopStream(IntPtr pushPtr); [DllImport(@"..\bin\libEasyPusher.dll")] /* 推流 frame:具体推送的流媒体帧 */ public static extern uint EasyPusher_PushFrame(IntPtr pushPtr, ref EASY_AV_Frame frame); }
附加将海康的PS流转换为H264流的.NET实现GetH246FromPS
public static class Utils { public static bool IsIFrame(byte[] buf) { int naltype = (buf[4] & 0x1F); switch (naltype) { case 7: //sps case 8: // pps case 6: // i case 5: //idr return true; case 1: // slice case 9: // unknown ??? default: return false; } } /// <summary> /// Gets the H246 from ps. /// </summary> /// <param name="pBuffer">PS 流数据</param> /// <param name="pH264">转换后的H264流数据(音视频)</param> /// <param name="bVideo">if set to <c>true</c> [b video].</param> /// <param name="bAudio">if set to <c>true</c> [b audio].</param> /// <returns><c>true</c> if XXXX, <c>false</c> otherwise</returns> /// <remarks> /// <para>创建:***</para> /// <para>日期:2016/11/25</para> /// </remarks> public static bool GetH246FromPS(byte[] pBuffer, ref byte[] pH264, out bool bVideo, out bool bAudio) { var _nBufLenth = (int)pBuffer.Length; if (pBuffer == null || _nBufLenth <= 0) { bVideo = bAudio = false; return false; } int nHerderLen = 0; if (pBuffer != null && pBuffer[0] == 0x00 && pBuffer[1] == 0x00 && pBuffer[2] == 0x01 && pBuffer[3] == 0xE0)//E==视频数据(此处E0标识为视频) { bVideo = true; bAudio = false; nHerderLen = 9 + (int)pBuffer[8];//9个为固定的数据包头长度,pBuffer[8]为填充头部分的长度 var nH264Lenth = _nBufLenth - nHerderLen; if (pH264 == null) { pH264 = new byte[nH264Lenth]; } if (pH264 != null && nH264Lenth > 0) { pH264 = pBuffer.Skip(nHerderLen).Take(nH264Lenth).ToArray(); } return true; } else if (pBuffer != null && pBuffer[0] == 0x00 && pBuffer[1] == 0x00 && pBuffer[2] == 0x01 && pBuffer[3] == 0xC0) //C==音频数据? { pH264 = null; bVideo = false; bAudio = true; var nH264Lenth = _nBufLenth - nHerderLen; nHerderLen = 9 + (int)pBuffer[8];//9个为固定的数据包头长度,pBuffer[8]为填充头部分的长度 if (pH264 == null) { pH264 = new byte[nH264Lenth]; } if (pH264 != null && nH264Lenth > 0) { pH264 = pBuffer.Skip(nHerderLen).Take(nH264Lenth).ToArray(); } return true; } else if (pBuffer != null && pBuffer[0] == 0x00 && pBuffer[1] == 0x00 && pBuffer[2] == 0x01 && pBuffer[3] == 0xBA)//视频流数据包 包头 { bVideo = true; bAudio = false; pH264 = null; return false; } bVideo = bAudio = false; return false; } }
TIPS:
把.NET 数组数据转为指针的方法
Byte[] _h264Buf = new Byte[1000]; //申请内存并返回指针 IntPtr fStreamAudioHandle = Marshal.AllocHGlobal(_h264Buf.Length); Marshal.Copy(_h264Buf, 0, fStreamAudioHandle, _h264Buf.Length); Marshal.FreeHGlobal(fStreamAudioHandle);//使用过后释放内存
取出指针处的数据到.NET数组
//取出指针处数据 //pBuffer 指针 //dwBufSize 指针缓存区大小 byte[] byx = new byte[(int)dwBufSize]; Marshal.Copy(pBuffer, byx, 0, (int)dwBufSize);
小建议:在导出C++接口的时候,最好自己使用C++再一次封装原有接口。这样导出自己实现的C++接口的时候就可以打断点,会比较方便的知道导出的.NET方法/传入的参数是否正确,总之可以自己有调试的手段了
参考:http://www.voidcn.com/blog/bigpudding24/article/p-5036339.html
标签:turn erp hal 成功 ansi user 连接失败 poi eof
原文地址:http://www.cnblogs.com/wipphj/p/6114762.html