針對監控攝像機(海康、大華等)錄像 .h264 文件的流媒體播放設計


監控攝像機(海康、大華等)內部帶的錄像功能一般錄制的是h264文件,這種文件格式簡單的把每一幀h264字節數據保存到文件里。

實際使用中,可能需要對特定錄像進行反復檢測,以訓練、改進視頻檢測算法的准確性。

 

這里介紹兩種方法。

 

1.使用RTSP流

服務端1:live555 使用C++代碼開發容易些,網上代碼較多

服務端2:vlc播放器,參考 使用vlc播放器做rtsp服務器

 

客戶端:使用vlc播放器播放rtsp視頻

            使用vlc進行二次開發做自己的播放器

            web網頁中使用vlc插件播放相機rtsp流視頻

            Emgu.CV 播放視頻-本地文件/RTSP流

 

2.自定義格式

使用UDP數據包

 

服務端針對.h264視頻一幀幀發送給客戶端,使用UDP協議

h264幀,尤其是I幀大小可能超過64K,即udp數據包的上限,需要考慮分包

分包:可以在第一字節=0表示不分包,=1表示分包這是第一包,=2這是第二包

 

視頻清晰度暫定為480P,此時P幀一般小於64k,而I幀部分大於64k。這樣可以不考慮數據包會先發后到導致亂序

 

客戶端:

示例代碼如下

IPEndPoint ipep = new IPEndPoint(IPAddress.Any, 6000);
            udpsockVideo = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
            udpsockVideo.ReceiveBufferSize = 1000000;
            try
            {
                //綁定網絡地址
                udpsockVideo.Bind(ipep);

                IPAddress ip = IPAddress.Any;

                //得到客戶機IP
                IPEndPoint sender = new IPEndPoint(ip, 0);
                EndPoint Remote = (EndPoint)(sender);

                log.ErrorFormat("udp開始接收視頻幀");

                bool bIframe = false;
                unAvailableCnt = 0;
                while (!bAbortvehicleEventThread)
                {
                    if (udpsockVideo == null)
                    {
                        log.ErrorFormat("udp接收視頻幀 Socket 為空!");
                        return;
                    }

                    if (udpsockVideo.Available <= 0)
                    {
                        unAvailableCnt++;
                        if (unAvailableCnt > 10000)
                        {
                            log.ErrorFormat("udp接收視頻幀:連續未接收到視頻"); //實際比10秒多
                            unAvailableCnt = 0;
                        }
                        //TimeSpan ts = new TimeSpan(100000);//0.1毫秒 1 ticks =十億分之一秒 百萬分之一毫秒 千分之一微秒,1納秒
                        Thread.Sleep(1); //sleep 1時,由於精度問題,經常耗時10-16毫秒
                        continue;
                    }

                    byte[] data = new byte[100000];
                    int recv = udpsockVideo.Receive(data);
                    if (recv < 4)
                    {
                        continue;
                    }

                    if (ip != IPAddress.Any && (Remote as IPEndPoint).Address.ToString().Trim() != ip.ToString().Trim())
                    {
                        continue;
                    }

                    unAvailableCnt = 0;

                    try
                    {
                        if (data[0] != 0x00)
                        {
                            bIframe = true;

                            byte b = data[0];
                            if (b == 0x01) 
                            {
                                iframe1 = new byte[recv - 2];
                                Array.Copy(data, 2, iframe1, 0, recv - 2);
                            }
                            log.ErrorFormat(b.ToString());
                            if (b == 0x02)
                            {
                                iframe2 = new byte[recv - 1];
                                Array.Copy(data, 1, iframe2, 0, recv - 1);
                                log.ErrorFormat(iframe2.Length.ToString());
                            }

                            if (iframe1.Length < 100000 && iframe2.Length < 100000)
                            {
                                int iframeLen = iframe1.Length + iframe2.Length;

                                byte[] Iframe = new byte[iframeLen];
                                Array.Copy(iframe1, 0, Iframe, 0, iframe1.Length);
                                Array.Copy(iframe2, 0, Iframe, iframe1.Length, iframe2.Length);

                                DecH264Frame(Iframe);

                                iframe1 = new byte[100000];
                                iframe2 = new byte[100000];
                                bIframe = false;
                            }
                        }
                        else
                        {
                            if (bIframe)
                            {
                                bIframe = false;
                                iframe1 = new byte[100000];
                                iframe2 = new byte[100000];
                            }

                            byte[] frame = new byte[recv - 1];
                            Array.Copy(data, 1, frame, 0, recv - 1);
                            DecH264Frame(frame);
                        }
                    }
                    catch (System.Exception ex)
                    {
                        log.ErrorFormat("udp接收視頻幀 解碼/錄像出錯:" + ex.Message);
                    }

                }
            }
            catch (Exception e)
            {
                log.ErrorFormat("udp接收視頻幀出錯。端口:{0},出錯信息:{1}", 6000, e.Message);
            }
            finally
            {
                if (udpsockVideo != null)
                {
                    udpsockVideo.Close();
                }
            }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM