基于FFmpeg的Dxva2硬解码及Direct3D显示(五)
解码及显示
解码
循环读取视频帧
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);
解码
两个重要的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显示(五)的更多相关文章
- 基于FFmpeg的Dxva2硬解码及Direct3D显示(四)
初始化硬解码上下文 目录 初始化硬解码上下文 创建解码数据缓冲区 创建IDirectXVideoDecoder视频解码器 设置硬解码上下文 解码回调函数 创建解码数据缓冲区 这一步为了得到 LPDIR ...
- 基于FFmpeg的Dxva2硬解码及Direct3D显示(一)
目录 前言 名词解释 代码实现逻辑 前言 关于视频软解码的资料网上比较多了,但是关于硬解可供参考的资料非常之有限,虽然总得来说软解和硬解的基本逻辑一样,但是实现细节上的差别还是比较多的.虽然目前功能已 ...
- 基于FFmpeg的Dxva2硬解码及Direct3D显示(三)
初始化Direct3D 目录 初始化Direct3D 创建Direct3D物理设备对象实例 创建Direct3D渲染设备实例 创建Direct3D视频解码服务 Direct3D渲染可以通过Surfac ...
- 基于FFmpeg的Dxva2硬解码及Direct3D显示(二)
解析视频源 目录 解析视频源 获取视频流 解析视频流 说明:这篇博文分为"获取视频流"和"解析视频流"两个部分,使用的是FFmpeg4.1的版本,与网上流传的低 ...
- 使用C#+FFmpeg+DirectX+dxva2硬件解码播放h264流
本文门槛较高,因此行文看起来会乱一些,如果你看到某处能会心一笑请马上联系我开始摆龙门阵 如果你跟随这篇文章实现了播放器,那你会得到一个高效率,低cpu占用(单路720p视频解码播放占用1%左右cpu) ...
- 【视频开发】 ffmpeg支持的硬解码接口
To enable DXVA2, use the --enable-dxva2 ffmpeg configure switch. To test decoding, use the following ...
- [原]ffmpeg编译android 硬解码支持库 libstagefright
最近花了一天时间将ffmpeg/tools/build_stagefright执行成功,主要是交叉编译所需要的各种动态库的支持没链接上,导致各种报错,基本上网络上问到的问题我都碰到了,特此记录下来. ...
- 【并行计算与CUDA开发】基于NVIDIA显卡的硬编解码的一点心得 (完结)
原文:基于NVIDIA显卡的硬编解码的一点心得 (完结) 1.硬解码软编码方法:大体流程,先用ffmpeg来读取视频文件的包,接着开启两个线程,一个用于硬解码,一个用于软编码,然后将读取的包传给解码器 ...
- 最简单的基于FFMPEG的封装格式转换器(无编解码)
本文介绍一个基于FFMPEG的封装格式转换器.所谓的封装格式转换,就是在AVI,FLV,MKV,MP4这些格式之间转换(相应.avi,.flv,.mkv,.mp4文件).须要注意的是,本程序并不进行视 ...
随机推荐
- boost之asio
asio asio是C++的准标准网络库,并且C++20标准库的网络部分将基于ASIO,需引入头文件#include <boost/asio.hpp>. ip地址 boost定义了表示ip ...
- elasticsearch要点及常用查询
目录 elasticsearch要点及常用查询 查询与过滤 明确查询和过滤各自的优缺点,以及适用场景. 性能上的差异 适用场景 1.kibana 中操作es-查询 Mapping映射基础 mappin ...
- 16.深入k8s:Informer使用及其源码分析
转载请声明出处哦~,本篇文章发布于luozhiyun的博客:https://www.luozhiyun.com 由于这部分的代码是在client-go 中,所以使用的源码版本是client-go 1. ...
- docker系统化学习图文教程
1.背景 在实际开发中我们经常遇到这样的情况: 1.开发的时候测试好的程序已发布到线上就出问题: 2.线上的集群环境需要扩容时非常麻烦,比如说要装jdk.mysql.redis等,如果扩容100台服务 ...
- go http爬虫
1 package main import ( "fmt" "io/ioutil" "net/http" ) func main() { r ...
- spring boot:spring security整合jwt实现登录和权限验证(spring boot 2.3.3)
一,为什么使用jwt? 1,什么是jwt? Json Web Token, 它是JSON风格的轻量级的授权和身份认证规范, 可以实现无状态.分布式的Web应用授权 2,jwt的官网: https:// ...
- spring-boot-route(二十三)开发微信公众号
在讲微信公众号开发之前,先来大概了解一下微信公众号.微信公众号大体上可以分为服务号和订阅号,订阅号和服务号的区别如下: 服务号可以申请微信支付功能. 服务号只能由企业申请,订阅号可以有企业或个人申请. ...
- App在后台运行时如何保存数据到sqlite数据库
iOS程序进入后台后,是不允许读写任何文件和数据库(sqlite),但是允许读写NSUserDefault中的数据. 因此在后台时如果想存储数据,则可使用NSUserDefault(偏好设置)临时保存 ...
- drf Serializer使用
drf序列化 在前后端不分离的项目中,可以使用Django自带的forms组件进行数据验证,也可以使用Django自带的序列化组件对模型表数据进行序列化. 那么在前后端分离的项目中,drf也提供了数据 ...
- ssm整合所用全部依赖pom.xml(idea版)
<?xml version="1.0" encoding="UTF-8"?><project xmlns="http://maven ...