Beispiel #1
0
        /// <summary>
        /// 发送视频码流,
        /// 对于H264的帧数据,如果监控平台回调的码流,SPS PPS IDR是分开发送的,则需要进行拼帧处理,将SPS+PPS+IDR拼接在一起发送
        /// </summary>
        /// <param name="mediaData"></param>
        /// <param name="sender"></param>
        public void SendVideoData(MediaData mediaData, string sender)
        {
            //对于H264的帧数据,如果监控平台回调的码流,SPS PPS IDR是分开发送的,则需要进行拼帧处理,将SPS+PPS+IDR拼接在一起发送
            if (mediaData.DataType == MediaDataType.FRAME_DATA)
            {
                switch (mediaData.FrameType)
                {
                    case FrameDataType.H264_SEI_NALU_TYPE:
                        //SEI的包,直接丢弃
                        return;

                    case FrameDataType.H264_SPS_NALU_TYPE:
                        //SPS的类型,先清空缓存
                        //this.CacheData = new byte[mediaData.Size];
                        //将SPS的数据缓存
                        this.CacheData = mediaData.Data;
                        this.LastCacheFrameType = mediaData.FrameType;

                        //直接return,暂不发送
                        return;

                    case FrameDataType.H264_PPS_NALU_TYPE:
                        //如果缓存最后一帧数据不为SPS或者PPS,说明数据乱序,舍弃。
                        if ((this.LastCacheFrameType != FrameDataType.H264_SPS_NALU_TYPE) && (this.LastCacheFrameType != FrameDataType.H264_PPS_NALU_TYPE))
                        {
                            return;
                        }

                        //将PPS的数据缓存,暂不发送
                        byte[] byteTemp = new byte[this.CacheData.Length + mediaData.Data.Length];
                        this.CacheData.CopyTo(byteTemp, 0);
                        mediaData.Data.CopyTo(byteTemp, this.CacheData.Length);
                        this.CacheData = byteTemp;

                        this.LastCacheFrameType = mediaData.FrameType;

                        //直接return,暂不发送
                        return;

                    case FrameDataType.H264_IDR_NALU_TYPE:
                        //如果缓存是上最后一帧数据不为PPS,说明数据乱序,舍弃
                        if (this.LastCacheFrameType != FrameDataType.H264_PPS_NALU_TYPE)
                        {
                            return;
                        }

                        byteTemp = new byte[this.CacheData.Length + mediaData.Data.Length];
                        this.CacheData.CopyTo(byteTemp, 0);
                        mediaData.Data.CopyTo(byteTemp, this.CacheData.Length);
                        mediaData.Data = byteTemp;
                        mediaData.Size = (uint)mediaData.Data.Length;
                        //break跳出 switch,进行发送
                        break;

                    default:
                        //其他类型的数据,直接发送
                        break;
                }
            }

            //if (writeCount1 < 1200)
            //{
            //    fs1.Write(mediaData.Data, 0, (int)mediaData.Size);
            //    writeCount1++;
            //}

            this.DataCallBack(this.CameraNo, mediaData, sender);
        }
Beispiel #2
0
        /// <summary>
        /// 码流回调函数,
        /// 1、根据预览句柄handle从videoHandleCameraDic中获取摄像头编号,
        /// 2、根据摄像头编号,获取mic状态
        /// 3、判断码流是否是音频,如果是音频,根据mic状态判断是否需要转发
        /// </summary>
        /// <param name="handle">播放句柄</param>
        /// <param name="pRawFrameInfo">实况参数</param>
        /// <param name="pBuf">码流</param>
        /// <param name="uiBufSize">大小</param>
        /// <param name="cameraNo">摄像头编号</param>
        private void IvsRealPlayCallBackRaw(int handle, IvsRawFrameInfo pRawFrameInfo, byte[] pBuf, UInt32 uiBufSize, string pUserData)
        {
            NLogEx.LoggerEx logEx = new NLogEx.LoggerEx(log);
            //logEx.Trace("Enter:IvsRealPlayCallBackRaw(),{0}", pUserData);

            MediaDataSender mediaDataSender = null;

            try
            {
                if (this.handelOperateLock.TryEnterReadLock(CgwConst.ENTER_LOCK_WAIT_TIME))
                {
                    try
                    {
                        if (!this.videoHandleCameraDic.ContainsKey(handle))
                        {
                            logEx.Error("The video data handle is not found.Handle:{0}", handle);
                            return;
                        }
                        mediaDataSender = this.videoHandleCameraDic[handle];
                    }
                    finally
                    {
                        this.handelOperateLock.ExitReadLock();
                    }
                }

                if (mediaDataSender == null)
                {
                    return;
                }

                StreamType streamType = StreamType.VIDEO_H264;
                //判断码流类型,因为码流回调访问频频非常高,不单独抽成一个方法,减少方法访问开销
                //对于支持的码流类型,用break退出switch,对于不支持的码流类型直接舍弃,用return返回
                switch (pRawFrameInfo.StreamType)
                {
                //对于音频只接收G711A和G711U,其他舍弃
                case (int)IvsStreamType.PAY_LOAD_TYPE_PCMU:
                    streamType = StreamType.AUDIO_G711U;
                    break;

                case (int)IvsStreamType.PAY_LOAD_TYPE_PCMA:
                    streamType = StreamType.AUDIO_G711A;
                    break;

                //只接收H264的视频码流
                case (int)IvsStreamType.PAY_LOAD_TYPE_H264:
                    //H264的标准视频流,作为视频流处理
                    streamType = StreamType.VIDEO_H264;
                    break;

                default:
                    //不支持的类型,直接舍弃,返回
                    //logEx.Warn("This stream type is not support. Chuck the data.StreamType:{0};Camera no:{1}",
                    //            Enum.GetName(typeof(IvsStreamType), pRawFrameInfo.StreamType),
                    //            cameraNo);
                    return;
                }

                if (streamType == StreamType.AUDIO_G711A || streamType == StreamType.AUDIO_G711U)
                {
                    //如果是音频流,需要判断mic的状态,开启时才发送音频流
                    if (this.micOperateLock.TryEnterReadLock(CgwConst.ENTER_LOCK_WAIT_TIME))
                    {
                        try
                        {
                            if (this.cameraMicStatusDic.ContainsKey(mediaDataSender.CameraNo))
                            {
                                //如果mic为非开启状态,则不发送音频码流,
                                if (!this.cameraMicStatusDic[mediaDataSender.CameraNo])
                                {
                                    //logEx.Warn("This data is audio,but the mic is off.Chuck the data.Camera no:{0}", mediaDataSender.CameraNo);
                                    return;
                                }
                            }
                            else
                            {
                                //默认为关闭状态,因此如果cameraMicStatusDic不包含该摄像头,则认为处于关闭状态,舍弃音频码流
                                //logEx.Warn("This data is audio,but the mic is off.Chuck the data.Camera no:{0}", mediaDataSender.CameraNo);
                                return;
                            }
                        }
                        finally
                        {
                            this.micOperateLock.ExitReadLock();
                        }
                    }
                }

                MediaData mediaData = new MediaData();
                mediaData.Data = pBuf;
                //IVS 目前为裸码流
                mediaData.DataType   = MediaDataType.FRAME_DATA;
                mediaData.StreamType = streamType;
                mediaData.Size       = uiBufSize;

                //将Ivs帧类型转换成各融合网关统一的帧类型
                string name = Enum.GetName(typeof(IvsH264NaluType), pRawFrameInfo.FrameType);

                //帧类型判断,偶现IVS返回的帧类型,在融合网关中未记录,返回值为null
                if (string.IsNullOrEmpty(name))
                {
                    logEx.Warn("IvsRealPlayCallBackRaw FrameType Is Not Defined ,FrameType:{0}", pRawFrameInfo.FrameType);
                    mediaData.FrameType = FrameDataType.H264_NALU_TYPE_UNDEFINED;
                }
                else
                {
                    if (Enum.IsDefined(typeof(FrameDataType), name))
                    {
                        FrameDataType frameDataType = (FrameDataType)Enum.Parse(typeof(FrameDataType), name);
                        mediaData.FrameType = frameDataType;
                    }
                    else
                    {
                        mediaData.FrameType = FrameDataType.H264_NALU_TYPE_UNDEFINED;
                    }
                }

                //向回调函数转发码流
                //this.videoDataCallBack(cameraNo, mediaData, this.sender);

                //logEx.Debug("FrameDataCallBackFun.mediaData.DataType={0},FrameType = {1},StreamType = {2},Size = {3}", Enum.GetName(typeof(MediaDataType), mediaData.DataType),
                //         Enum.GetName(typeof(FrameDataType), mediaData.FrameType), Enum.GetName(typeof(StreamType), mediaData.StreamType), mediaData.Size);
                mediaDataSender.SendData(mediaData, this.sender);
            }
            catch (Exception e)
            {
                logEx.Error("Send the media data failed.Execption message:{0}", e.ToString());
            }
        }
        /// <summary>
        /// rtp码流回调处理
        /// </summary>
        /// <param name="pBuf">帧数据字节数组</param>
        /// <param name="pFrameData">帧数据类型</param>
        /// <param name="uiChannel">通道</param>
        /// <param name="uiBufSize">帧数据字节数组长度</param>
        private void FrameDataCallBackFun(IntPtr pBuf, uint uiBufSize, ref ST_FRAME_DATA pFrameData, uint uiChannel)
        {
            NLogEx.LoggerEx logEx     = new NLogEx.LoggerEx(log);
            ST_FRAME_DATA   frameData = pFrameData;

            MediaDataSender mediaDataSender = null;

            if (this.handelOperateLock.TryEnterReadLock(CgwConst.ENTER_LOCK_WAIT_TIME))
            {
                try
                {
                    if (this.videoChannelDataSenderDic.ContainsKey(uiChannel))
                    {
                        mediaDataSender = this.videoChannelDataSenderDic[uiChannel];
                    }
                }
                finally
                {
                    this.handelOperateLock.ExitReadLock();
                }
            }

            if (mediaDataSender == null)
            {
                logEx.Warn("FrameDataCallBackFun mediaDataSender = NULL");
                return;
            }

            StreamType streamType = StreamType.VIDEO_H264;

            //对于支持的码流类型,用break退出switch,对于不支持的码流类型直接舍弃,用return返回
            switch (frameData.iStreamType)
            {
            //对于音频只接收G711A和G711U,其他舍弃
            case (int)IvsStreamType.PAY_LOAD_TYPE_PCMU:
                streamType = StreamType.AUDIO_G711U;
                break;

            case (int)IvsStreamType.PAY_LOAD_TYPE_PCMA:
                streamType = StreamType.AUDIO_G711A;
                break;

            //只接收H264的视频码流
            case (int)IvsStreamType.PAY_LOAD_TYPE_H264:
                //H264的标准视频流,作为视频流处理
                streamType = StreamType.VIDEO_H264;
                break;

            default:
                //不支持的类型,直接舍弃,返回
                return;
            }

            if (streamType == StreamType.AUDIO_G711A || streamType == StreamType.AUDIO_G711U)
            {
                //如果是音频流,需要判断mic的状态,开启时才发送音频流
                if (this.micOperateLock.TryEnterReadLock(CgwConst.ENTER_LOCK_WAIT_TIME))
                {
                    try
                    {
                        if (this.cameraMicStatusDic.ContainsKey(mediaDataSender.CameraNo))
                        {
                            //如果mic为非开启状态,则不发送音频码流,
                            if (!this.cameraMicStatusDic[mediaDataSender.CameraNo])
                            {
                                logEx.Warn("This data is audio,but the mic is off.Chuck the data.Camera no:{0}", mediaDataSender.CameraNo);
                                return;
                            }
                        }
                        else
                        {
                            //默认为关闭状态,因此如果cameraMicStatusDic不包含该摄像头,则认为处于关闭状态,舍弃音频码流
                            logEx.Warn("This data is audio,but the mic is off.Chuck the data.Camera no:{0}", mediaDataSender.CameraNo);
                            return;
                        }
                    }
                    finally
                    {
                        this.micOperateLock.ExitReadLock();
                    }
                }
            }

            try
            {
                MediaData mediaData = new MediaData();
                //获取非托管的数据
                byte[] datagram = new byte[uiBufSize];

                if (!(streamType == StreamType.AUDIO_G711A || streamType == StreamType.AUDIO_G711U))
                {
                    Marshal.Copy(pBuf, datagram, 0, (int)uiBufSize);
                    //视频帧数据头部增加四个四节的开始表实0x000001
                    byte[] newDatagram = new byte[uiBufSize + 4];
                    datagram.CopyTo(newDatagram, 4);
                    newDatagram[3] = 1;
                    mediaData.Data = newDatagram;
                    mediaData.Size = (uint)(uiBufSize + 4);
                }
                else
                {
                    mediaData.Data = datagram;
                    mediaData.Size = (uiBufSize);
                }

                //裸码流
                mediaData.DataType   = MediaDataType.FRAME_DATA;
                mediaData.StreamType = streamType;

                //将帧类型转换成各融合网关统一的帧类型
                string name = Enum.GetName(typeof(IvsH264NaluType), frameData.iFrameDataType);
                if (Enum.IsDefined(typeof(FrameDataType), name))
                {
                    FrameDataType frameDataType = (FrameDataType)Enum.Parse(typeof(FrameDataType), name);
                    mediaData.FrameType = frameDataType;
                }
                else
                {
                    mediaData.FrameType = FrameDataType.H264_NALU_TYPE_UNDEFINED;
                }

                //向回调函数转发码流
                mediaDataSender.SendData(mediaData, this.sender);
            }
            catch (System.Exception ex)
            {
                logEx.Error("FrameDataCallBackFun failed.Execption message:{0}", ex.Message);
            }
        }