zoukankan      html  css  js  c++  java
  • 【转】C# 视频监控系列(13):H264播放器——控制播放和截图

    本文原文地址:http://www.cnblogs.com/over140/archive/2009/03/30/1421531.html

    阿里云栖社区也有相关的视频开发案例:https://yq.aliyun.com/articles/51182

    注意

         本系列文章限于学习交流,注重过程,由于涉及公司,所以不提供源代码下载,非常抱歉!!但是请大家放心,核心、实现以及其他能够贴出来的代码我都会贴出来,并且争取尽所能的回答留言里的每一个问题,感谢大家关注,欢迎交流 :)

    系列

         1.     C# 视频监控系列(1):准备

         2.     C# 视频监控系列(2):客户端——封装API

         3.     C# 视频监控系列(3):客户端——连接服务器

         4.     C# 视频监控系列(4):客户端——音频接收和抓图

         5.     C# 视频监控系列(5):客户端——给服务器端发送字符串和录像(数据捕获)

         6.     C# 视频监控系列(6):服务器端——封装API(上) [HikServer.dll]

         7.     C# 视频监控系列(7):服务器端——封装API(下) [DS40xxSDK.dll]

         8.     C# 视频监控系列(8):服务器端——预览和可被客户端连接

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

         10.     C# 视频监控系列(10):服务器端——验证、设置画面质量、字幕叠加、板卡序列号

         11.     C# 视频监控系列(11):H264播放器——封装API[HikPlayM4.dll]

         12.     C# 视频监控系列(12):H264播放器——播放录像文件

         13.     C# 视频监控系列(13):H264播放器——控制播放和截图 

    正文

         一、控制播放

              1.1     暂停/播放/停止

                   VC++ Code:

    复制代码
    ////////////////////////////////////////////////////////////////////////////////
    //Funtion:Play or change the play speed to normal;
    ///////////////////////////////////////////////////////////////////////////////
    void CPlayerDlg::OnPlay() 
    {
        // TODO: Add your control notification handler code here
        Play();
    }

    void CPlayerDlg::Play()
    {
        m_nSpeed=0;
        OnThrow0();
    //#ifdef _TEST_CALLBACK
        if(m_bConvert)       
           Hik_PlayM4_SetDecCallBack(PORT,DecCBFun);
        else
            m_pMainMenu->EnableMenuItem(ID_FILE_CLOSE, FALSE);
    //#endif
        if(m_bPlaying)
        {
            Hik_PlayM4_Play(PORT,GetDlgItem(IDC_SHOW)->m_hWnd);
        }
        else
        {
            if(m_bStreamType)
            {
                ::SetFilePointer(m_hStreamFile,m_nHeadSize,0,FILE_BEGIN);
                Hik_PlayM4_ResetSourceBuffer(PORT);
                SetEvent(m_hEventInput);
            }
            m_bPlaying = Hik_PlayM4_Play(PORT,GetDlgItem(IDC_SHOW)->m_hWnd);
            m_bSound=Hik_PlayM4_PlaySound(PORT);
            if(m_bPlaying)
                SetTimer(PLAY_TIMER,500,NULL);
            
        }
        if(m_bPlaying)

            SetPlayState();
        else
        {
            CString csError;
            csError.Format("Play the file faild.(%d)",Hik_PlayM4_GetLastError(PORT));
            AfxMessageBox(csError);
        }
        
    }
    //////////////////////////////////////////////////////////////////////////////
    //Funtion:pause.
    //////////////////////////////////////////////////////////////////////////////
    void CPlayerDlg::OnPause() 
    {
        // TODO: Add your control notification handler code here
        if(m_bPlaying)
        {
            m_bPause=!m_bPause;
            Pause(m_bPause);
        }
    }
    void CPlayerDlg::Pause(BOOL bPause)
    {
        if(m_bPaused == bPause)
            return;
        m_bPaused=bPause;
        Hik_PlayM4_Pause(PORT,bPause);
        TRACE("PAUSE %d ",m_bPaused);
    }
    /////////////////////////////////////////////////////////////////////////////
    //Function: Stop
    /////////////////////////////////////////////////////////////////////////////
    void CPlayerDlg::OnStop() 
    {
        // TODO: Add your control notification handler code here
        
        if(m_bPlaying)
        {
            Stop();
        }
        if(m_bConvert)
        {
           if(outFile!=NULL)
              closeWriffFiles();    
           if(yuvBuf!=NULL)
           {
               free(yuvBuf);
               yuvBuf=NULL;
           }
           m_bConvert=0;    

           //
        }
    }
    void CPlayerDlg::Stop()
    {
        CButton *pButton;
        if(!m_bPlaying)
            return;
        KillTimer(PLAY_TIMER);
        if(Hik_PlayM4_StopSound())
        {
            m_bSound=FALSE;
            pButton = (CButton *)GetDlgItem(IDC_SOUND);
            pButton->SetIcon(m_hSoundStopIcon);
        }
        //continue before stop.Add by lgl at 9-19;
        m_bPause=FALSE;
        
        //stop
        m_bPlaying = !Hik_PlayM4_Stop(PORT);
        if(!m_bPlaying)    
        {
            SetStopState();
            if(m_bStreamType)
                ResetEvent(m_hEventInput);
        }

        
    }
    复制代码

                   C#     Code:

    复制代码
            //是否暂停
            private bool isPause;

            /// <summary>
            /// 播放
            /// </summary>
            /// <param name="sender"></param>
            /// <param name="e"></param>
            private void btnPlay_Click(object sender, EventArgs e)
            {
                if (!string.IsNullOrEmpty(m_strPlayFileName))
                {
                    //是否暂停->播放
                    if (isPause)
                    {
                        HikPlayer.Hik_PlayM4_Pause(PORT, false);
                        isPause = false;
                    }
                    else
                        OpenFile();
                }
            }

            /// <summary>
            /// 暂停
            /// </summary>
            /// <param name="sender"></param>
            /// <param name="e"></param>
            private void btnPause_Click(object sender, EventArgs e)
            {
                HikPlayer.Hik_PlayM4_Pause(PORT, true);
                isPause = true;
            }

            /// <summary>
            /// 停止
            /// </summary>
            /// <param name="sender"></param>
            /// <param name="e"></param>
            private void btnStop_Click(object sender, EventArgs e)
            {
                HikPlayer.Hik_PlayM4_Stop(PORT);
                HikPlayer.Hik_PlayM4_CloseFile(PORT);
                HikPlayer.Hik_PlayM4_RealeseDDraw();

                pVideo.Invalidate(true);
            }
    复制代码

                   代码说明:

                        1.     关于变量PORT、m_strPlayFileName和方法OpenFile可以看上篇文章的代码。

                        2.     注意Hik_PlayM4_Pause的第二个参数用法。

              1.2     快进/慢进

                   VC++ Code:

    复制代码
    //////////////////////////////////////////////////////////////////////////////
    //Funtion: Fast
    //////////////////////////////////////////////////////////////////////////////
    void CPlayerDlg::OnFastForward() 
    {
        // TODO: Add your control notification handler code here
        //Throw B-Frame ,improve the performance;
        
        if(Hik_PlayM4_Fast(PORT))
        {
            m_nSpeed++;
            if(m_nSpeed>0)
                OnThrow2();
            SetFastForwardState();        
        }    
    }
    //////////////////////////////////////////////////////////////////////////////
    //Funtion: Slow;
    //////////////////////////////////////////////////////////////////////////////
    void CPlayerDlg::OnFastBackward() 
    {
        // TODO: Add your control notification handler code here
        if(Hik_PlayM4_Slow(PORT))
        {
            m_nSpeed--;
            if(m_nSpeed<=0)
                OnThrow0();
            SetFastBackWardState();
        }
    }
    复制代码

                    C#     Code:

    复制代码
            int m_nSpeed;

            /// <summary>
            /// 快进
            /// </summary>
            /// <param name="sender"></param>
            /// <param name="e"></param>
            private void btnFastForward_Click(object sender, EventArgs e)
            {
                if (HikPlayer.Hik_PlayM4_Fast(PORT))
                {
                    m_nSpeed++;
                    if (m_nSpeed > 0)
                        OnThrow2();
                }
            }

            /// <summary>
            /// 慢放
            /// </summary>
            /// <param name="sender"></param>
            /// <param name="e"></param>
            private void btnFastBackward_Click(object sender, EventArgs e)
            {
                //慢速播放
                if (HikPlayer.Hik_PlayM4_Slow(PORT))
                {
                    //timer1.Interval
                    m_nSpeed--;
                    if (m_nSpeed <= 0)
                        OnThrow0();
                }
            }

            public void OnThrow0()
            {
                HikPlayer.Hik_PlayM4_ThrowBFrameNum(PORT, 0);
            }

            public void OnThrow2()
            {
                HikPlayer.Hik_PlayM4_ThrowBFrameNum(PORT, 2);
            }
    复制代码

                   代码说明:

                        1.     注意关于这两个函数API的说明:

                             Hik_PlayM4_Fast:快速播放,每次调用将使当前播放速度加快一倍,最多调用4次;要恢复正常播放调用Hik_PlayM4_Play(),从当前位置开始正常播放。

                             Hik_PlayM4_Slow:慢速播放,每次调用将使当前播放速度慢一倍;最多调用4次;要恢复正常播放调用Hik_PlayM4_Play。

              1.3     开始/末尾

                   VC++ Code:

    复制代码
    ///////////////////////////////////////////////////////////////////////////////
    //Funtion:Locate to the file head.
    //////////////////////////////////////////////////////////////////////////////
    void CPlayerDlg::OnGotoStart() 
    {
        // TODO: Add your control notification handler code here
        if(m_bFileRefCreated)
            Hik_PlayM4_SetCurrentFrameNum(PORT,0);
        else
            Hik_PlayM4_SetPlayPos(PORT,0);
    }
    ///////////////////////////////////////////////////////////////////////////////
    //Funtion:Locate to the end.
    //////////////////////////////////////////////////////////////////////////////
    void CPlayerDlg::OnGotoEnd() 
    {
        // TODO: Add your control notification handler code here
        if(m_bFileRefCreated)
        {
            //Note: May create many WM_FILE_END message. The best way is to synchronize the option;
            
            int nEndFrame=m_nTotalFrames;
            while(!Hik_PlayM4_SetCurrentFrameNum(PORT,nEndFrame--))
            {
                //TRACE("FrameNum is :%d ",nEndFrame);
                if(nEndFrame==0)
                    break;
            }
        }
        else
            Hik_PlayM4_SetPlayPos(PORT,1);

    }
    复制代码

                   C#     Code:

    复制代码
            /// <summary>
            /// 开始位置
            /// </summary>
            /// <param name="sender"></param>
            /// <param name="e"></param>
            private void btnGotoStart_Click(object sender, EventArgs e)
            {
                HikPlayer.Hik_PlayM4_SetPlayPos(PORT, 0);
            }

            /// <summary>
            /// 末尾位置
            /// </summary>
            /// <param name="sender"></param>
            /// <param name="e"></param>
            private void btnGotoEnd_Click(object sender, EventArgs e)
            {
                HikPlayer.Hik_PlayM4_SetPlayPos(PORT, 1);
            }
    复制代码

               代码说明:

                   1.     注意Hik_PlayM4_SetPlayPos的第二个参数取值范围是0-1之间,即可以理解0是开始位置,1是结束位置;但是有一点比较奇怪,每次都会延迟3秒,即到末尾后还播放3秒钟!

         二、截图

                   VC++ Code:

    复制代码
    //////////////////////////////////////////////////////////////////
    //Function:The call back funtion for capture image!
    /////////////////////////////////////////////////////////////////
    void CALLBACK DisplayCBFun(long nPort,
                               char * pBuf,long nSize,
                               long nWidth,long nHeight,
                               long nStamp,long nType,long nReceaved)
    {
        if(!g_bCapPic)
            return;
        CString csFile;
        csFile.Format("capture%02d.bmp",pic);
        /*    switch(nType)
        {
        case T_UYVY:
        csFile="uyvy.bmp";
        break;
        case T_YV12:
        csFile="yv12.bmp";
        break;
        case T_RGB32:
        csFile="rgb.bmp";
        break;
        default: 
        return ;
    }*/
        //Note:this funtion is slow,so if you want to save as a .bmp file,don't call! 
        if(!Hik_PLayM4_ConvertToBmpFile(pBuf,nSize,nWidth,nHeight,nType,csFile.GetBuffer(csFile.GetLength())))
        {
            CString csErr;
            csErr.Format("Convert to bmp faild(%d).",Hik_PlayM4_GetLastError(nPort));
            AfxMessageBox(csErr);
        }
        pic++;
        g_bCapPic=FALSE;
        
    }
    复制代码

                   C#     Code:

    复制代码
            DisplayCBFun DisCB;

            /// <summary>
            /// 截图
            /// </summary>
            /// <param name="sender"></param>
            /// <param name="e"></param>
            private void btnCapImage_Click(object sender, EventArgs e)
            {
                DisCB = new DisplayCBFun(DisplayCBFun);
                HikPlayer.Hik_PlayM4_SetDisplayCallBack(PORT, DisCB);
            }

            /// <summary>
            /// 截图回调函数
            /// </summary>
            /// <param name="nPort"></param>
            /// <param name="pBuf"></param>
            /// <param name="nSize"></param>
            /// <param name="nWidth"></param>
            /// <param name="nHeight"></param>
            /// <param name="nStamp"></param>
            /// <param name="nType"></param>
            /// <param name="nReceaved"></param>
            public void DisplayCBFun(int nPort, IntPtr pBuf, int nSize, int nWidth, int nHeight, int nStamp, int nType, int nReceaved)
            {
                if (HikPlayer.Hik_PLayM4_ConvertToBmpFile(pBuf, nSize, nWidth, nHeight, nType, string.Format("C:\capture{0}.bmp", nPort)))
                {
                    MessageBox.Show("转换bmp失败!");
                }
                //停止回调
                HikPlayer.Hik_PlayM4_SetDisplayCallBack(PORT, null);
            }
    复制代码

              代码说明:

                   1.     这里和源代码有点出入,他用的是g_bCapPic变量来控制是否捕获图片,我用的是设置委托实例和null来达到。API说明:设置抓图回调函数;注意要尽快返回,如果要停止回调,可以把回调函数指针DisplayCBFun设为NULL。

    结束

         现在在做语音部分,受阻中...

  • 相关阅读:
    inner join on, left join on, right join on讲解(转载)
    ref 与 out
    Shell基础01
    Python 基础01
    linux基础03
    Shell基础02
    linux基础02
    Linux基础01
    linux基础05
    linux基础04
  • 原文地址:https://www.cnblogs.com/boonya/p/8249802.html
Copyright © 2011-2022 走看看