FFMPEG解码实时流,支持cpu、gpu解码

官网下载的ffmpeg目前只能下载到X64版本的库,具体编译请参考windows编译ffmpeg源码(32位库)_windows 32位ffmpeg动态库-CSDN博客

直接上代码

int VideoDecodeModule::Open(std::string strUrl)
{
	AVFormatContext *pFormatCtx = nullptr;
	AVCodec *pCodec = nullptr;
	AVCodecContext* pCodecCtx = nullptr;
	AVDictionary *opt = nullptr;
	std::string decodeName = "";
	AVBufferRef* pBufferRef = nullptr;
	int ret = 0;
	int videoStream = -1;
	char errorbuf[1024] = { 0 };
	av_dict_set(&opt, "buffer_size", "1024000", 0);        // 缓冲区大小 单位字节 解决高画质模糊的问题
	av_dict_set(&opt, "max_delay", "100", 0);              // 最大延时 单位微妙
	av_dict_set(&opt, "stimeout", "3000000", 0);           // 设置超时断开连接时间 3s 单位微妙
	av_dict_set(&opt, "rtsp_transport", "tcp", 0);         // 以tcp方式打开,如果以udp方式打开将tcp替换为udp
	av_dict_set(&opt, "fflags", "nobuffer", 0);
	av_dict_set(&opt, "rtbufsize", "6", 0);
	av_dict_set(&opt, "start_time_realtime", 0, 0);

	if ((ret = avformat_open_input(&pFormatCtx, strUrl.data(), nullptr, &opt)) != 0)
	{
		av_strerror(ret, errorbuf, sizeof(errorbuf));
		return -1;
	}
	
	m_spFormatContext = std::shared_ptr<AVFormatContext>(pFormatCtx, [](AVFormatContext* ctx){
		avformat_close_input(&ctx);
	});

	if ((ret = avformat_find_stream_info(pFormatCtx, nullptr)) < 0)
	{
		av_strerror(ret, errorbuf, sizeof(errorbuf));
		return -1;
	}

	if ((ret = av_find_best_stream(pFormatCtx, AVMEDIA_TYPE_VIDEO, -1, -1, &pCodec, 0)) < 0)
	{
		av_strerror(ret, errorbuf, sizeof(errorbuf));
		return -1;
	}
	videoStream = ret;
	m_video = pFormatCtx->streams[videoStream];

	if (m_decodeType == DT_CPU)
	{
		if (!(pCodec = avcodec_find_decoder(m_video->codecpar->codec_id)))
		{
			int error = AVERROR(ENOMEM);
			return -1;
		}
	}
	else if (m_decodeType == DT_INTER_QSV)
	{
		decodeName = GetCodeName(m_video->codecpar->codec_id, DT_INTER_QSV);
		if (av_hwdevice_ctx_create(&pBufferRef, AV_HWDEVICE_TYPE_QSV, "auto", nullptr, 0) != 0)
		{
			return -1;
		}
		if (!(pCodec = avcodec_find_decoder_by_name(decodeName.data())))
		{
			int error = AVERROR(ENOMEM);
			return -1;
		}
	}
	else if (m_decodeType == DT_NVIDIA_CUDA)
	{
		decodeName = GetCodeName(m_video->codecpar->codec_id, DT_NVIDIA_CUDA);
		if (av_hwdevice_ctx_create(&pBufferRef, AV_HWDEVICE_TYPE_CUDA, "auto", nullptr, 0) != 0)
		{
			return -1;
		}
		if (!(pCodec = avcodec_find_decoder_by_name(decodeName.data())))
		{
			int error = AVERROR(ENOMEM);
			return -1;
		}
	}

	if (auto frame = av_frame_alloc())
	{
		m_spSwFrame = std::shared_ptr<AVFrame>(frame, [](AVFrame* p) {av_frame_free(&p); });
	}
	
	if (!(pCodecCtx = avcodec_alloc_context3(pCodec)))
	{
		return -1;
	}

	m_spCodecContext = std::shared_ptr<AVCodecContext>(pCodecCtx, [](AVCodecContext* ctx)
	{
		avcodec_free_context(&ctx);
	});

	m_spCodecContext->codec_id = m_video->codecpar->codec_id;
	if (m_video->codecpar->extradata_size)
	{
		m_spCodecContext->extradata = (uint8_t*)av_mallocz(m_video->codecpar->extradata_size + AV_INPUT_BUFFER_PADDING_SIZE);
		if (!m_spCodecContext->extradata)
		{
			return -1;
		}
		memcpy(m_spCodecContext->extradata, m_video->codecpar->extradata, m_video->codecpar->extradata_size);
		m_spCodecContext->extradata_size = m_video->codecpar->extradata_size;
	}

	m_spCodecContext->flags2 |= AV_CODEC_FLAG2_FAST;    // 允许不符合规范的加速技巧。
	m_spCodecContext->thread_count = 8;                 // 使用8线程解码

	if ((ret = avcodec_parameters_to_context(m_spCodecContext.get(), m_video->codecpar)) < 0)
	{
		av_strerror(ret, errorbuf, sizeof(errorbuf));
		return -1;
	}
	
	if (m_decodeType == DT_INTER_QSV)
	{
		m_spCodecContext->opaque = pBufferRef;
		m_spCodecContext->get_format = GetHWQsvFormat;
	}
	else if (m_decodeType == DT_NVIDIA_CUDA)
	{
		m_spCodecContext->hw_device_ctx = av_buffer_ref(pBufferRef);
		m_spCodecContext->opaque = this;
		m_spCodecContext->get_format = GetHWCudaFormat;
	}

	if ((ret = avcodec_open2(m_spCodecContext.get(), pCodec, nullptr)) < 0)
	{
		av_strerror(ret, errorbuf, sizeof(errorbuf));
		return -1;
	}
	m_isConnect = true;
	return ret;
}
if (!spFrame)
		return;
	/// 解码的图片宽
	int width = spFrame->width;
	/// 解码的图片高
	int height = spFrame->height;
	// 计算转码后的图片裸数据需要的大小
	int nSrcbuffSize = av_image_get_buffer_size(m_pixelFormat, width, height, 1);
	if (nSrcbuffSize > m_dstBuffer.size())
	{
		m_dstBuffer.resize(nSrcbuffSize, '\0');
	}
	std::shared_ptr<SwsContext>	spSwsContext = nullptr;
	/// 判断是否需要格式转换
	if (m_pixelFormat != (AVPixelFormat)spFrame->format)
	{
		AVPixelFormat srcFmt = (AVPixelFormat)spFrame->format;
		SwsContext* image_sws_ctx = sws_getContext(width, height, srcFmt,
			width, height, m_pixelFormat, SWS_FAST_BILINEAR, nullptr, nullptr, nullptr);
		spSwsContext = std::shared_ptr<SwsContext>(image_sws_ctx, [](SwsContext* p) {sws_freeContext(p); });
		uint8_t* data[4] = { nullptr };
		int linesize[4] = { 0 };
		av_image_fill_arrays(data, linesize, m_dstBuffer.data(), m_pixelFormat, width, height, 1);

		int ret = sws_scale(spSwsContext.get(), (uint8_t const* const*)spFrame->data, spFrame->linesize, 0, height, data, linesize);
		if (ret < 0)
			return;
	}

	if (m_pFrameDataCallBack)
	{
		FrameInfo info;
		info.format = GetVideoFormatByAVPixelFormat(m_pixelFormat);
		info.width = width;
		info.height = height;
		info.pts = spFrame->pts / 1000;

		m_pFrameDataCallBack->cbFrameDataCallBack(m_dstBuffer.data(), m_dstBuffer.size(), info, m_pFrameDataCallBack->pUser);
	}

解码显示效果图

英伟达显卡播放效果因本人没有显卡不在这里展示,可以看出通过硬解降低将近一半的cpu。

代码参考 https://download.csdn.net/download/weixin_38887743/88748651

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/327690.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Next.js 开发指​南(GitHub 115k star​)

Next.js 是一个构建于 Node.js 之上的开源 Web 开发框架&#xff0c;它扩展了最新的 React 特性&#xff0c;集成了基于 Rust 的 JavaScript 工具&#xff0c;可以帮助你快速创建全栈 Web 应用 &#xff08;full-stack Web applications&#xff09; 。 对于有一定 React 基础…

虚拟机 以及 Centos 7的 安装全过程

目录 安装VMwere Workstion 虚拟机的操作过程 CentOS 7 安装过程 install CentOS 7 安装操作系统 安装VMwere Workstion 虚拟机的操作过程 更改安装位置 到下面图片中的这一个步骤&#xff0c;可以点击许可证&#xff0c;输入密钥就可以使用了&#xff0c; 密钥可以去某度或…

网络安全B模块(笔记详解)- 文件包含

文件包含的渗透与加固 1.使用渗透机场景kali中工具扫描服务器,将服务器上 File Inclusion首页概述页中的Flag提交; Flag:iloveu 2.使用渗透机场景windows7访问服务器场景网站中的File Inclusion(local)页面,找到根目录下Flag文件夹下的Flag.txt文件并将其内容提交; Flag:…

Linux中SSH远程管理服务

一、SSH服务 1.1.什么是SSH服务器&#xff1f; SSH&#xff08;Secure Shell&#xff09;是一种安全通道协议&#xff0c;主要用来实现字符界面的远程登录、远程 复制等功能。SSH 协议对通信双方的数据传输进行了加密处理&#xff0c;其中包括用户登录时输入的用户口令&#…

回环检测算法:Stable Trangle Descriptor

回环检测是指检测传感器的两次测量&#xff08;如图像、激光雷达扫描&#xff09;是否发生在同一场景&#xff0c;它是对于SLAM问题至关重要。基于激光雷达的回环检测应该满足如下要求&#xff1a; 无论视点如何变化&#xff0c;回环检测方法应该实现旋转和平移不变性&#xf…

从零开始:Golang中JSON解析与生成的完全指南

从零开始&#xff1a;Golang中JSON解析与生成的完全指南 引言Golang与JSON&#xff1a;基础概念JSON简介为何在Golang中使用JSON Golang中JSON数据的解析使用encoding/json解析JSON解析成基本数据类型解析成自定义结构体错误处理和常见问题 Golang中生成JSON数据将Golang对象转…

两数之和(Hash表)[简单]

优质博文&#xff1a;IT-BLOG-CN 一、题目 给定一个整数数组nums和一个整数目标值target&#xff0c;请你在该数组中找出"和"为目标值target的那两个整数&#xff0c;并返回它们的数组下标。 你可以假设每种输入只会对应一个答案。但是&#xff0c;数组中同一个元…

Elasticsearch 7.8.0从入门到精通

安装Elasticsearch 7.8.0 官网&#xff1a;Elasticsearch 7.8.0 | Elastic 大家下载所需要的安装包即可。然后解压缩&#xff1a; Elasticsearch是通过java编写的&#xff0c;所以自带jdk。多好&#xff0c;下载Elasticsearch赠送jdk 0.0&#xff0c;不过一般我们用自己的jdk…

java发送邮件(注:本章以163邮箱为例)

目录 前言 一邮件服务器与传输协议 二.发送邮件思路 2.1注册163邮箱: 2.2、打开邮箱服务获取授权码 三.代码实现邮件发送 3.1第三方jar包 3.2创建邮件工具类 3.3编写测试类 前言 电子邮件的应用非常广泛&#xff0c;例如在某网站注册了一个账户&#xff0c;自动发送一…

C#/WPF 设置和启动Windows屏保程序

前言 我们平时电脑启动的屏保程序其本质也是应用程序&#xff0c;只是后缀名为.scr。所以我们只需要把应用程序后缀改为.scr&#xff0c;然后右键选择安装即可启动我们自己的屏保程序。 屏保注册表参数 设置电脑屏保参数&#xff0c;在个性化设置>锁屏界面>屏幕保护程序设…

解决若依Vue3前后端分离---路由切换时显示白屏

解决若依Vue3前后端分离---路由切换时显示白屏 1.问题重述 解决基于Vue3若依前后端分离项目中出现的路由正常切换但是就是不显示数据的问题&#xff0c;也就是不发起网络请求的问题。 找到如下位置中AppMain.vue文件 将除了css中的代码进行替换成如下的代码。 <template&g…

element-ui表单验证同时用change与blur一起验证

项目场景&#xff1a; 提示&#xff1a;这里简述项目相关背景&#xff1a; 当审批时不通过审批意见要必须输入&#xff0c; 1&#xff1a;如果用change验证的话删除所有内容时报错是massage的提示&#xff0c;但是在失去焦点的时候报错就成了英文&#xff0c;如下图&#xf…

K8S--Ingress的作用

原文网址&#xff1a;K8S--Ingress的作用-CSDN博客 简介 本文介绍K8S的Ingress的作用。 ----------------------------------------------------------------------------------------------- 分享Java真实高频面试题&#xff0c;吊打面试官&#xff1a; Java后端真实面试题…

【MIdjourney】几种独特的艺术风格

1.合成器波(Synthwave) Synthwave是一种音乐风格&#xff0c;起源于20世纪80年代电子音乐和电影的复古元素。这种音乐风格通常包括合成器音乐、电子鼓声和强烈的电子声效&#xff0c;以模拟80年代电影和视频游戏的声音。Synthwave的特点包括浓厚的合成器声音、强烈的节奏和对复…

代码随想录 Leetcode541. 反转字符串 II

题目&#xff1a; 代码(首刷自解 2024年1月16日&#xff09;&#xff1a; class Solution { public:void reverse(string& s,int left,int right) {char temp;while (left < right) {temp s[left];s[left] s[right];s[right] temp;left;--right;}return;}string rev…

[NSSCTF Round#16 Basic]了解过PHP特性吗

了解过PHP特性吗 wp 第一页题目代码&#xff1a; <?php error_reporting(0); highlight_file(__FILE__); include("rce.php"); $checker_1 FALSE; $checker_2 FALSE; $checker_3 FALSE; $checker_4 FALSE; $num $_GET[num]; if (preg_match("/[0-9]/…

基于Yolov5+Deepsort+SlowFast算法实现视频目标识别、追踪与行为实时检测

前言 前段时间打算做一个目标行为检测的项目&#xff0c;翻阅了大量资料&#xff0c;也借鉴了不少项目&#xff0c;最终感觉Yolov5DeepsortSlowfast实现实时动作检测这个项目不错&#xff0c;因此进行了实现。 一、核心功能设计 总的来说&#xff0c;我们需要能够实现实时检测视…

pyhton实现录屏

python代码录屏录音 写的不是很好&#xff0c;不如那些obs的录屏软件&#xff0c;而且没有实现音频和视频的合并&#xff0c;请多见谅。 def audio_record() 实现音频录制 def video_record() 实现视频录制 def on_press(key) 按键监听 import time,threading from datetime i…

【project】estimate Aβ-PET pattern

1.17 1.16 1.14 写一个函数&#xff0c;输入是每个文件的地址&#xff0c;然后能做这一系列的操作 用AFM0095进行bbr的配准 方法一&#xff0c;间接配准&#xff0c;frmi先到str&#xff0c;再到mni&#xff08;str2fmri后再fmri2str&#xff09; fmri2str 只需要dof 6,6个自…

ROS第 2 课 ROS 系统安装和环境搭建

文章目录 方法一&#xff1a;一键安装&#xff08;推荐&#xff09;方法二&#xff1a;逐步安装&#xff08;常规安装方式&#xff09;1.版本选择2.检查 Ubuntu 的软件和更新源3.设置 ROS 的下载源3.1 设置国内下载源3.2 设置公匙3.3 更新软件包 4. 安装 ROS5. 设置环境变量6. …