码迷,mamicode.com
首页 > Web开发 > 详细

EasyPusher推流服务接口的.NET导出

时间:2016-11-29 19:21:38      阅读:540      评论:0      收藏:0      [点我收藏+]

标签: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

EasyPusher推流服务接口的.NET导出

标签:turn   erp   hal   成功   ansi   user   连接失败   poi   eof   

原文地址:http://www.cnblogs.com/wipphj/p/6114762.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!