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替换为udpav_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.hqwc.cn/news/409730.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

grep 在运维中的常用可选项

一、对比两个文件 vim -d <filename1> <filename2> 演示&#xff1a; 需求&#xff1a;&#xff5e;目录下有两个文件一个test.txt 以及 text2.txt,需求对比两个文件的内容。 执行后会显示如图&#xff0c;不同会高亮。 二、两次过滤 场景&#xff1a;当需要多…

探索数据的奥秘:一份深入浅出的数据分析入门指南

数据分析 书籍推荐 入门读物 深入浅出数据分析啤酒与尿布数据之美数学之美 数据分析 Scipy and NumpyPython for Data AnalysisBad Data Handbook集体智慧编程Machine Learning in Action机器学习实战Building Machine Learning Systems with Python数据挖掘导论Machine L…

day20【LeetCode力扣】142.环形链表Ⅱ

day20【LeetCode力扣】142.环形链表Ⅱ 1.题目描述 给定一个链表的头节点 head &#xff0c;返回链表开始入环的第一个节点。 如果链表无环&#xff0c;则返回 null。 如果链表中有某个节点&#xff0c;可以通过连续跟踪 next 指针再次到达&#xff0c;则链表中存在环。 为了…

Vue3中provide,inject使用

一&#xff0c;provide,inject使用&#xff1a; 应用场景&#xff1a;向孙组件传数据 应用Vue3碎片&#xff1a; ref&#xff0c;reactive&#xff0c;isRef&#xff0c;provide, inject 1.provide,inject使用 a.爷组件引入 import {ref,provide} from vue const drinkListre…

pytest -- 进阶使用详解

pytest-html⽣成报告 Pytest-HTML 是⼀个插件&#xff0c;它可以⽣成漂亮且易于阅读的 HTML 测试报告。 pytest-html ⽣成报告的步骤 ① 安装 pytest-html 插件&#xff1a; pip install pytest-html ② 运⾏测试并⽣成报告&#xff1a; file name:main.pyimport pytest&qu…

Arduino快速上手esp8266方案开发

认识ESP8266 ESP8266 是 Espressif Systems 生产的 Wi-Fi 片上系统 (SoC)。它非常适合物联网和家庭自动化项目&#xff0c;目前有非常高的市场普及率&#xff0c;还有更加高端的同时支持wifi和蓝牙的双核心芯片ESP32&#xff0c;可以在乐鑫官网查看完整的芯片列表。 ESP8266芯…

SpringBoot框架自定义解析配置项占位符(${})获取配置

一、前言 在最近项目开发中&#xff0c;有一个需求&#xff0c;针对自定义注解中字符串属性值的设置需要支持使用”${xx}“占位符获取在SpringBoot框架配置文件中配置项对应的属性值&#xff0c;而且支持多个”${xx}“标识的配置任意拼接。 二、功能实现 从实现思路上说还是…

rust跟我学二:模块编写与使用

图为RUST吉祥物 大家好,我是get_local_info作者带剑书生,这里用一篇文章讲解get_local_info中模块的使用。 首先,先要了解get_local_info是什么? get_local_info是一个获取linux系统信息的rust三方库,并提供一些常用功能,目前版本0.2.4。详细介绍地址:[我的Rust库更新]g…

iphone 5s的充电时序原理图纸,iPAD充电讲解

上一篇写了iphone 5的时序。那是电池供电的开机时序。iphone 5s也是差不多的过程&#xff0c;不说了。现在看iphone5s手机充电时候的时序。iphone5s充电比iphone5充电简单了很多。 首先是usb接口接到手机上&#xff0c;usb线连接到J7接口上。J7接口不只是接usb&#xff0c;还能…

05-python之函数-函数的定义/函数的参数/函数返回值/函数说明文档/函数的嵌套使用/函数变量的作用域

01-函数的介绍 """ 演示&#xff1a;快速体验函数的开发及应用 ​ """ #需求&#xff0c;统计字符串的长度&#xff0c;不使用内置函数len() str1 "itheima" str2 "itcast" str3 "python" ​ #定义一个技术的变…

2-认识小程序项目

基本结构 myapp├─miniprogram┊ └──pages┊ ┊ └──index┊ ┊ ┊ ├──index.json┊ ┊ ┊ ├──index.ts┊ ┊ ┊ ├──index.wxml┊ ┊ ┊ └──index.wxss┊ ┊ └──logs┊ ┊ ├──index.json┊ ┊ ├──index.ts┊ ┊ ├…

学习JavaEE的日子 day13 封装 static private this 类加载机制

Day13 1. private – 私有化 理解&#xff1a;private是访问修饰符的一种&#xff0c;访问修饰符规定了访问权限. 作用&#xff1a; ​ 1.private修饰属性&#xff1a;该属性只能在类的内部使用 ​ 2.private修饰方法&#xff1a;该方法只能在类的内部使用 应用场景&#xff1…