WEB开发网
开发学院软件开发C语言 C# 视频监控系列(9):服务器端——数据捕获(抓图... 阅读

C# 视频监控系列(9):服务器端——数据捕获(抓图 + 录像)

 2009-04-08 08:23:40 来源:WEB开发网   
核心提示: 代码说明: 1. 从StartCap和StopCap的按钮事件可以看得出主要实现写文件头和文件尾的功能,注意_write函数,C# 视频监控系列(9):服务器端——数据捕获(抓图 + 录像)(3), 2. 而上一章我们讲到了回调函数StreamDirectReadCallback,主要是

代码说明:

1.     从StartCap和StopCap的按钮事件可以看得出主要实现写文件头和文件尾的功能,注意_write函数。

2.     而上一章我们讲到了回调函数StreamDirectReadCallback,主要是将数据写到内存中,从代码能看出回调中是边写内存边写文件的代码,而且输出就是.264文件。由于回调从启动开始(允许被客户端访问),就一直不停的在调用这个回调,根据断点调试可以看得出当frameType == PktSysHeader时表示的就是文件头,并且只执行一次,这样在点击StartCap按钮时就直接将这个保存的文件头的数据写入文件了,用UE打开.264的文件可以发现前几个字符总是以4HKH开头的文件。

3.     注意gFileHandle是一个文件指针数组,文件被打开后回调中就一直往这个文件指针写数据!!

C#:

        //用于存放头文件
        byte[] FileHeader;
        //文件头长度
        int FileHeaderLen;
        //是否开始捕获文件 0 未启用 1 启用
        volatile int CaptureState;

        /// <summary>
        /// 开始录像
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnStart_Click(object sender, EventArgs e)
        {
            //写入头文件
            using (FileStream fs = new FileStream("C:hik.264", FileMode.Create))
            {
                BinaryWriter bw = new BinaryWriter(fs);
                bw.Write(FileHeader);
                bw.Flush();
                bw.Close();
            }

            CaptureState = 1;
        }

        uint endCode = 0x00000002;

        /// <summary>
        /// 停止录像
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnStop_Click(object sender, EventArgs e)
        {
            CaptureState = 0;
            using (FileStream fs = new FileStream("C:hik.264", FileMode.Append))
            {
                BinaryWriter bw = new BinaryWriter(fs);
                bw.Write(endCode);
                bw.Close();
            }
        }

        public int STREAM_DIRECT_READ_CALLBACK1(int channelNum, IntPtr DataBuf, int Length, FrameType_t frameType, IntPtr context)
        {
            //int status = 0;
            //HikServer.MP4_ServerWriteDataEx(channelNum, DataBuf, Length, (int)frameType, status, 0);
            //return 0;

            int status = 0;

            if (frameType > 0)
            {
                if (frameType == FrameType_t.PktSysHeader)
                {
                    FileHeader = new byte[Length];
                    Marshal.Copy(DataBuf, FileHeader, 0, Length);
                    FileHeaderLen = Length;
                }

                if (frameType == FrameType_t.PktIFrames || frameType == FrameType_t.PktSubIFrames)
                    status = 1;
                else
                    status = 0;

                if (frameType == FrameType_t.PktMotionDetection || frameType == FrameType_t.PktOrigImage)
                    return 0;
            }

            if (Length == 0)
            {
                //TRACE("no data ?n");
                return 0;
            }

            if (frameType == FrameType_t.PktAudioFrames)
            {
                WriterVideoCapture(Length, DataBuf);
                //写文件
                //    _write(gFileHandleQcif[channelNum],DataBuf,Length);
                //HikServer.MP4_ServerWriteDataEx(channelNum, DataBuf, Length, (int)frameType, status, 1);
                //    _write(gFileHandle[channelNum], DataBuf, Length);
                HikServer.MP4_ServerWriteDataEx(channelNum, DataBuf, Length, (int)frameType, status, 0);
            }
            else if (frameType == FrameType_t.PktSubIFrames || frameType == FrameType_t.PktSubPFrames || frameType == FrameType_t.PktSubBBPFrames || frameType == FrameType_t.PktSubSysHeader)
            {
                //    _write(gFileHandleQcif[channelNum],DataBuf,Length);
                HikServer.MP4_ServerWriteDataEx(channelNum, DataBuf, Length, (int)frameType, status, 1);
            }
            else
            {
                WriterVideoCapture(Length, DataBuf);
                HikServer.MP4_ServerWriteDataEx(channelNum, DataBuf, Length, (int)frameType, status, 0);
            }

            return 0;

        }

        /// <summary>
        /// 将数据流写入视频文件
        /// </summary>
        /// <param name="length"></param>
        /// <param name="dataBuf"></param>
        private void WriterVideoCapture(int length, IntPtr dataBuf)
        {
            if (CaptureState == 1)
            {
                using (FileStream fs = new FileStream("C:hik.264", FileMode.Append))
                {
                    BinaryWriter bw = new BinaryWriter(fs);

                    byte[] byteBuf = new byte[length];
                    Marshal.Copy(dataBuf, byteBuf, 0, length);
                    bw.Write(byteBuf);
                    bw.Flush();
                    bw.Close();
                }
            }
        }

代码说明:

1.     回调函数STREAM_DIRECT_READ_CALLBACK1是在上篇文章的基础上修改的,也主要是参照的VC++的源代码改写的。

2.     CaptureState变量主要用于STREAM_DIRECT_READ_CALLBACK1中控制是否写文件。

3.     btnStart_Click与btnStop_Click分别代表界面上的开始录像和停止录像按钮。

4.     注意写文件的方式,开始录像用FileMode.Create,持续写入用FileMode.Append。

补充:

1.     录像的时候务必考虑单录像文件的大小以及磁盘空间不够的问题,最好还能考虑下分时段监控等。

2.     注意保存文件头的变量FileHeader,如果分文件连续保存的话有可能出现第一个文件能播放,后面的都不能播放了,可能是文件头变量的数据类型问题,你可以换byte[] -> IntPtr保存试试看。

3.     自带的示例里面有播放器极其源码,打开播放器,直接将.264文件拖拽到里面就可以播放了;如果报错那么说明你的录像有问题!!

结束

虽然代码都给出来了,但是里面整个过程还是需要理解的,一定要配合VC++自带的例子进行调试编写。

上一页  1 2 3 

Tags:视频监控 系列 服务器

编辑录入:爽爽 [复制链接] [打 印]
赞助商链接