int SendDataBuff(byte[] data, int startIndex, int size, Data_Info_s pPacker)
 {
     try
     {
         int sendedCount = 0;
         if (pPacker != null && pPacker.sendSOcket != null)
         {
             //var start = DateTime.Now;
             sendedCount = pPacker.sendSOcket.SendTo(data, startIndex, size, SocketFlags.None, pPacker.remotePoint);
             //if (sendedCount != 12)
             //    Console.WriteLine(sendedCount);
             //Thread.Sleep(40);
             //Thread.Sleep(40);
             //var end = DateTime.Now.Subtract(start).Milliseconds;
             //Console.WriteLine("send audio to soldier  " + end);
         }
         return(sendedCount);
     }
     catch (Exception ex)
     {
         Console.WriteLine(ex.Message + ex.StackTrace);
         return(0);
     }
 }
        /***
         *@remark:  音视频数据的打包成ps流,并封装成rtp
         *@param :  pData      [in] 需要发送的音视频数据
         *          nFrameLen  [in] 发送数据的长度
         *          pPacker    [in] 数据包的一些信息,包括时间戳,rtp数据buff,发送的socket相关信息
         *          stream_type[in] 数据类型 0 视频 1 音频
         *@return:  0 success others failed
         */

        public int Gb28181_streampackageForH264(byte[] pData, int nFrameLen, Data_Info_s pPacker, int stream_type)
        {
            try
            {
                byte[] szTempPacketHead = new byte[PS_HDR_LEN + SYS_HDR_LEN + PSM_HDR_LEN];
                int    nSizePos         = 0;
                int    nSize            = 0;
                byte[] pBuff            = null;
                Array.Clear(szTempPacketHead, 0, szTempPacketHead.Length);

                // 1 package for ps header
                Gb28181_make_ps_header(szTempPacketHead, nSizePos, pPacker.s64CurPts);



                nSizePos += PS_HDR_LEN;
                //2 system header
                //if (pPacker.IFrame == 1)
                //{
                // 如果是I帧的话,则添加系统头
                Gb28181_make_sys_header(szTempPacketHead, nSizePos);

                nSizePos += SYS_HDR_LEN;
                //这个地方我是不管是I帧还是p帧都加上了map的,貌似只是I帧加也没有问题
                //      gb28181_make_psm_header(szTempPacketHead + nSizePos);
                //      nSizePos += PSM_HDR_LEN;
                //}
                // 3 psm头 (也是map)
                Gb28181_make_psm_header(szTempPacketHead, nSizePos);

                nSizePos += PSM_HDR_LEN;

                //加上rtp发送出去,这样的话,后面的数据就只要分片分包就只有加上pes头和rtp头了
                //if (gb28181_send_rtp_pack(szTempPacketHead, 0, nSizePos, 0, pPacker) != 0)
                //    return -1;

                // 这里向后移动是为了方便拷贝pes头
                //这里是为了减少后面音视频裸数据的大量拷贝浪费空间,所以这里就向后移动,在实际处理的时候,要注意地址是否越界以及覆盖等问题
                pBuff = new byte[szTempPacketHead.Length + pData.Length + PES_HDR_LEN];

                Array.Copy(szTempPacketHead, pBuff, szTempPacketHead.Length);

                Array.Copy(pData, 0, pBuff, szTempPacketHead.Length + PES_HDR_LEN, pData.Length);

                int startIndex = 0;



                //含有有效数据
                //  bHasPayload = true;
                while (nFrameLen > 0)
                {
                    //每次帧的长度不要超过short类型,过了就得分片进循环行发送
                    nSize = (nFrameLen > PS_PES_PAYLOAD_SIZE) ? PS_PES_PAYLOAD_SIZE : nFrameLen;
                    // 添加pes头
                    Gb28181_make_pes_header(pBuff, szTempPacketHead.Length, stream_type == 1 ? 0xC0 : 0xE0, nSize, (pPacker.s64CurPts / 1), (pPacker.s64CurPts / 3));


                    //最后在添加rtp头并发送数据
                    if (Gb28181_send_rtp_pack(pBuff, startIndex, szTempPacketHead.Length + nSize + PES_HDR_LEN, ((nSize == nFrameLen) ? 1 : 0), pPacker) != 0)
                    {
                        Console.WriteLine("gb28181_send_pack failed!\n");
                        return(-1);
                    }

                    //分片后每次发送的数据移动指针操作
                    nFrameLen -= nSize;
                    //这里也只移动nSize,因为在while向后移动的pes头长度,正好重新填充pes头数据
                    startIndex += nSize;
                }
                //  bHasPayload = false;
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message + ex.StackTrace);
            }
            return(0);
        }
        int Gb28181_send_rtp_pack(byte[] databuff, int index, int nDataLen, int mark_flag, Data_Info_s pPacker)
        {
            try
            {
                int nRet         = 0;
                int nPlayLoadLen = 0;
                int nSendSize    = 0;

                byte[] szRtpHdr = new byte[RTP_HDR_LEN];
                Array.Clear(szRtpHdr, 0, RTP_HDR_LEN);

                if (nDataLen + RTP_HDR_LEN <= RTP_MAX_PACKET_BUFF)// 1460 pPacker指针本来有一个1460大小的buffer数据缓存
                {
                    // 一帧数据发送完后,给mark标志位置1
                    Gb28181_make_rtp_header(szRtpHdr, 0, ((mark_flag == 1) ? 1 : 0), ++pPacker.u16CSeq, (pPacker.s64CurPts / 1), pPacker.u32Ssrc);

                    Array.Copy(szRtpHdr, pPacker.szBuff, RTP_HDR_LEN);
                    Array.Copy(databuff, index, pPacker.szBuff, RTP_HDR_LEN, nDataLen);
                    nRet = SendDataBuff(pPacker.szBuff, 0, RTP_HDR_LEN + nDataLen, pPacker);//ZXB: 发送数据 为什么加databuff参数  需不需要加上index
                    if (nRet != (RTP_HDR_LEN + nDataLen))
                    {
                        Console.WriteLine(" udp send error !\n");
                        return(-1);
                    }
                    //录制mf
                    //outputData(pPacker.szBuff, 0, RTP_HDR_LEN + nDataLen, bHasPayload, true, true);
                }
                else
                {
                    nPlayLoadLen = RTP_MAX_PACKET_BUFF - RTP_HDR_LEN; // 每次只能发送的数据长度 除去rtp头
                    Gb28181_make_rtp_header(pPacker.szBuff, 0, 0, ++pPacker.u16CSeq, (pPacker.s64CurPts / 1), pPacker.u32Ssrc);

                    //memcpy(pPacker->szBuff + RTP_HDR_LEN, databuff, nPlayLoadLen);
                    Array.Copy(databuff, index, pPacker.szBuff, RTP_HDR_LEN, nPlayLoadLen);

                    nRet = SendDataBuff(pPacker.szBuff, 0, RTP_HDR_LEN + nPlayLoadLen, pPacker);//ZXB: 发送数据 为什么加databuff参数需不需要加上index
                    if (nRet != (RTP_HDR_LEN + nPlayLoadLen))
                    {
                        Console.WriteLine(" udp send error !\n");
                        return(-1);
                    }
                    //录制mf
                    //outputData(pPacker.szBuff, 0, RTP_HDR_LEN + nPlayLoadLen, bHasPayload, true, true);

                    nDataLen -= nPlayLoadLen;
                    index    += nPlayLoadLen; // 表明前面到数据已经发送出去
                    index    -= RTP_HDR_LEN;  // 用来存放rtp头
                    while (nDataLen > 0)
                    {
                        if (nDataLen <= nPlayLoadLen)
                        {
                            //一帧数据发送完,置mark标志位
                            Gb28181_make_rtp_header(databuff, index, mark_flag, ++pPacker.u16CSeq, (pPacker.s64CurPts / 1), pPacker.u32Ssrc);
                            nSendSize = nDataLen;
                        }
                        else
                        {
                            Gb28181_make_rtp_header(databuff, index, 0, ++pPacker.u16CSeq, (pPacker.s64CurPts / 1), pPacker.u32Ssrc);
                            nSendSize = nPlayLoadLen;
                        }
                        nRet = SendDataBuff(databuff, index, RTP_HDR_LEN + nSendSize, pPacker);//ZXB: 发送数据 为什么加databuff参数需不需要加上index
                        if (nRet != (RTP_HDR_LEN + nSendSize))
                        {
                            Console.WriteLine(" udp send error !\n");
                            return(-1);
                        }
                        //录制mf
                        //outputData(databuff, index, RTP_HDR_LEN + nSendSize, bHasPayload, true, false);

                        nDataLen -= nSendSize;
                        index    += nSendSize;
                        //因为buffer指针已经向后移动一次rtp头长度后,
                        //所以每次循环发送rtp包时,只要向前移动裸数据到长度即可,这是buffer指针实际指向到位置是
                        //databuff向后重复的rtp长度的裸数据到位置上
                    }
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message + ex.StackTrace);
            }

            return(0);
        }