zoukankan      html  css  js  c++  java
  • 基于FFmpeg的Dxva2硬解码及Direct3D显示(五)

    解码及显示

    解码

    1. 循环读取视频帧

      AVPacket packet = { 0 };
      while (av_read_frame(m_pFmtCtx, &packet) >= 0)
      {
          if (m_videoIndex == packet.stream_index)
          {
              Decode(m_pDecoderCtx, &packet);	
              av_packet_unref(&packet);
          }
      }
      
      // 缓冲中的可能还有数据,所以需要将剩下的数据一并解码
      packet.data = NULL;
      packet.size = 0;
      
      Decode(m_pDecoderCtx, &packet);
      av_packet_unref(&packet);
      
    2. 解码

      两个重要的FFmpeg接口:

      avcodec_send_packet,发送一个包给解码器;

      avcodec_receive_frame,从解码器取回解码后的数据。

      void Decode(AVCodecContext * pDecodeCtx, AVPacket * pPacket)
      {
      	if (avcodec_send_packet(pDecodeCtx, pPacket) < 0)
      	{
      		return;
      	}
      
      	while (TRUE)
      	{
      		if (avcodec_receive_frame(pDecodeCtx, m_pFrame) != 0)
      		{
      			break;
      		}
      
      		DisplayVideo(m_pFrame);
      	}
      }
      

    显示

    关于D3D显示的大概步骤是解码数据放在缓冲区,也就是这里离屏的概念,然后将离屏数据拷贝到后台缓冲表面,后台表面和前台表面不停的交替实现显示。

    // 离屏
    LPDIRECT3DSURFACE9 surface = (LPDIRECT3DSURFACE9)pFrame->data[3];
    
    // D3DCLEAR_TARGET		清除要渲染目标(帧缓存)的颜色为D3DCOLOR_XRGB(0, 0, 0)的值
    // D3DCLEAR_ZBUFFER		清除深度缓冲(确定像素遮挡关系)的值为1.0f
    // D3DCLEAR_STENCIL     清除模板缓冲区(用于特效)为0
    // 此时1.0f和0均会被忽略
    m_pD3d9Dev->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0, 0, 0), 1.0f, 0);
    m_pD3d9Dev->BeginScene();
    
    IDirect3DSurface9 *	pBackBuffer = nullptr;
    if (pBackBuffer)
    {
        pBackBuffer->Release();
        pBackBuffer = NULL;
    }
    
    // 获取第1个交换链上的第一个后台缓冲区的地址
    m_pD3d9Dev->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO, &pBackBuffer);
    
    GetClientRect(m_hWnd, &m_renderRect);
    
    // 将待显示的数据拷贝到后台缓冲区,通过线性插值的方式显示到指定窗口区域
    m_pD3d9Dev->StretchRect(surface, NULL, pBackBuffer, &m_renderRect, D3DTEXF_LINEAR);
    m_pD3d9Dev->EndScene();
    m_pD3d9Dev->Present(NULL, NULL, NULL, NULL);
    
    #if !CAMERA
    Sleep(1000 / m_frameRate);
    #endif
    

    资源清理

    if (m_hD3dDll)
    {
        FreeLibrary(m_hD3dDll);
        m_hD3dDll = nullptr;
    }
    
    if (m_hDxva2Dll)
    {
        FreeLibrary(m_hDxva2Dll);
        m_hDxva2Dll = nullptr;
    }
    
    if (m_pD3d9Dev)
    {
        m_pD3d9Dev->Release();
    }
    
    if (m_pD3d9DevMgr && m_hDev != INVALID_HANDLE_VALUE)
    {
        m_pD3d9DevMgr->CloseDeviceHandle(m_hDev);
    }
    
    if (m_pDecoderService)
    {
        m_pDecoderService->Release();
    }
    
    if (m_pD3d9DevMgr)
    {
        m_pD3d9DevMgr->Release();
    }
    
    // 释放缓冲区
    if (m_pSurface)
    {
        for (uint32_t i = 0; i < m_surfaceNums; i++)
        {
            if (m_pSurface[i])
                m_pSurface[i]->Release();
        }
    }
    
    // 释放DirectX解码器
    if (m_pDecoder)
    {
        m_pDecoder->Release();
        m_pDecoder = nullptr;
    }
    
    av_freep(&pCodecCtx->hwaccel_context);
    
  • 相关阅读:
    Bootstrap Alert Auto Close
    event.preventDefault()
    jquery click & get value of attributes of a href
    TFS build dotCover StyleCop
    Asp.net MVC4 Knockoutjs BootStrap Ace NinJect Jqgrid sqlserver2008
    Rendering a simple ASP.NET MVC PartialView using JQuery Ajax Post call
    asp.net mvc JQGrid
    Knockoutjs lostfocus event
    Dota2 demo手游项目历程
    龙之森林项目进程
  • 原文地址:https://www.cnblogs.com/huluwa508/p/10331525.html
Copyright © 2011-2022 走看看