解码及显示

解码

  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);

基于FFmpeg的Dxva2硬解码及Direct3D显示(五)的更多相关文章

  1. 基于FFmpeg的Dxva2硬解码及Direct3D显示(四)

    初始化硬解码上下文 目录 初始化硬解码上下文 创建解码数据缓冲区 创建IDirectXVideoDecoder视频解码器 设置硬解码上下文 解码回调函数 创建解码数据缓冲区 这一步为了得到 LPDIR ...

  2. 基于FFmpeg的Dxva2硬解码及Direct3D显示(一)

    目录 前言 名词解释 代码实现逻辑 前言 关于视频软解码的资料网上比较多了,但是关于硬解可供参考的资料非常之有限,虽然总得来说软解和硬解的基本逻辑一样,但是实现细节上的差别还是比较多的.虽然目前功能已 ...

  3. 基于FFmpeg的Dxva2硬解码及Direct3D显示(三)

    初始化Direct3D 目录 初始化Direct3D 创建Direct3D物理设备对象实例 创建Direct3D渲染设备实例 创建Direct3D视频解码服务 Direct3D渲染可以通过Surfac ...

  4. 基于FFmpeg的Dxva2硬解码及Direct3D显示(二)

    解析视频源 目录 解析视频源 获取视频流 解析视频流 说明:这篇博文分为"获取视频流"和"解析视频流"两个部分,使用的是FFmpeg4.1的版本,与网上流传的低 ...

  5. 使用C#+FFmpeg+DirectX+dxva2硬件解码播放h264流

    本文门槛较高,因此行文看起来会乱一些,如果你看到某处能会心一笑请马上联系我开始摆龙门阵 如果你跟随这篇文章实现了播放器,那你会得到一个高效率,低cpu占用(单路720p视频解码播放占用1%左右cpu) ...

  6. 【视频开发】 ffmpeg支持的硬解码接口

    To enable DXVA2, use the --enable-dxva2 ffmpeg configure switch. To test decoding, use the following ...

  7. [原]ffmpeg编译android 硬解码支持库 libstagefright

    最近花了一天时间将ffmpeg/tools/build_stagefright执行成功,主要是交叉编译所需要的各种动态库的支持没链接上,导致各种报错,基本上网络上问到的问题我都碰到了,特此记录下来. ...

  8. 【并行计算与CUDA开发】基于NVIDIA显卡的硬编解码的一点心得 (完结)

    原文:基于NVIDIA显卡的硬编解码的一点心得 (完结) 1.硬解码软编码方法:大体流程,先用ffmpeg来读取视频文件的包,接着开启两个线程,一个用于硬解码,一个用于软编码,然后将读取的包传给解码器 ...

  9. 最简单的基于FFMPEG的封装格式转换器(无编解码)

    本文介绍一个基于FFMPEG的封装格式转换器.所谓的封装格式转换,就是在AVI,FLV,MKV,MP4这些格式之间转换(相应.avi,.flv,.mkv,.mp4文件).须要注意的是,本程序并不进行视 ...

随机推荐

  1. openstack 高可用环境部署(8节点)(一)

  2. Shell Scripting 笔记

    Shell Scripting Tutorial Variables in the Bourne shell do not have to be declared, as they do in lan ...

  3. 5G-第五代移动通信系统(5th generation mobile/wireless/cellular system)

    通信系统 有意义的信息交流被称为通讯. 自然界:狼嚎.狗叫.虫鸣.鸡叫. 人类社会:说话.眼神.写信.烽火台. 目的:信息的传递. 人类发明电以后,开始使用电来传递信息,特别快. 于是有了电报.电话以 ...

  4. matplotlib中文标签乱码

    在python的安装目录下 找到~\Lib\site-packages\matplotlib\mpl-data 将字体文件(例如黑体SimHei.ttf,一般C:\Windows\Fonts路径下就有 ...

  5. 对象部分初始化:原理以及验证代码(双重检查锁与volatile相关)

    对象部分初始化:原理以及验证代码(双重检查锁与volatile相关) 对象部分初始化被称为 Partially initialized objects / Partially constructed ...

  6. 19. [链表][双指针]删除链表的倒数第N个节点

    19. 删除链表的倒数第N个节点 方法一:哨兵节点+快慢指针 在本题中,快慢指针的用法为:让快指针先走几步,步数由 \(n\) 决定. 使用哨兵节点的理由是为了避免删除节点为头结点引发的空指针异常. ...

  7. Docker指令整理

    date: 2018-11-18 11:09:28 updated: 2018-11-18 11:09:28 Docker指令整理 管理员权限!!! 查看docker版本 docker -v 启动 s ...

  8. java安全编码指南之:文件IO操作

    目录 简介 创建文件的时候指定合适的权限 注意检查文件操作的返回值 删除使用过后的临时文件 释放不再被使用的资源 注意Buffer的安全性 注意 Process 的标准输入输出 InputStream ...

  9. 群晖DS218+部署mysql

    欢迎访问我的GitHub https://github.com/zq2599/blog_demos 内容:所有原创文章分类汇总及配套源码,涉及Java.Docker.Kubernetes.DevOPS ...

  10. git版本管理系统使用

    版本管理系统Git 关注公众号"轻松学编程"了解更多. git下载链接:https://pan.baidu.com/s/12vJn-K0lK9XlkVQbNe8S-A 密码:m4m ...