FFMPEG C++封装(二)

news/2024/6/16 10:45:30/文章来源:https://blog.csdn.net/flysnow010/article/details/137096728

4 详细设计

这章是FFMPEG C++封装库的详细设计。

4.1 Init

该模块初始化FFMPEG库。

4.1.1 Init定义

namespace media
{
namespace sdk
{
void  MEDIASDK_EXPORT Init();
}
}

函数说明:

  • Init 初始化FFMPEG库,该函数可调用多次。

4.1.2 Init实现

namespace media
{
namespace sdk
{
void Init()
{static bool isInit = false;if(isInit)return;isInit = true;avcodec_register_all();avfilter_register_all();av_register_all();avformat_network_init();Report(false);
}
}
}

函数流程:

  • 注册支持的全部编码器(codec)。
  • 注册支持的全部过滤器(filter)。
  • 注册支持的全部封包格式(format)。
  • 初始化支持的网络。
  • 默认关闭打印输出。

4.2 Utils

该模块提供FFMPEG库的工具函数。

4.2.1 Utils定义

namespace media
{
namespace sdk
{
void MEDIASDK_EXPORT Report(bool on);void MEDIASDK_EXPORT Formats();
void MEDIASDK_EXPORT Codecs(bool encoder);
void MEDIASDK_EXPORT Bsfs();
void MEDIASDK_EXPORT Protocols();
void MEDIASDK_EXPORT Filters();
void MEDIASDK_EXPORT PixFmts();
void MEDIASDK_EXPORT SampleFmts();int64_t MEDIASDK_EXPORT Time();
int64_t MEDIASDK_EXPORT NoPtsValue();
int64_t MEDIASDK_EXPORT ToTime(int64_t const& pts, Rational const& timebase);std::vector<std::string> MEDIASDK_EXPORT DisplayCardNames();
}
}

4.2.2 Utils实现

4.2.2.1 Report
void Report(bool on)
{if(on)av_log_set_callback(log_callback_help);		elseav_log_set_callback(log_callback_null);
}

函数说明:

  • 如果需要打印,设置一个可打印新的callback.
  • 如果不要打印,设置一个不可打印的callback.
4.2.2.2 Formats
void Formats()
{AVInputFormat *ifmt  = NULL;AVOutputFormat *ofmt = NULL;const char *last_name;printf("File formats:\n"" D. = Demuxing supported\n"" .E = Muxing supported\n"" --\n");last_name = "000";for (;;) {int decode = 0;int encode = 0;const char *name      = NULL;const char *long_name = NULL;while ((ofmt = (AVOutputFormat *)av_oformat_next(ofmt))) {if ((name == NULL || strcmp(ofmt->name, name) < 0) &&strcmp(ofmt->name, last_name) > 0) {name      = ofmt->name;long_name = ofmt->long_name;encode    = 1;}}while ((ifmt = (AVInputFormat *)av_iformat_next(ifmt))) {if ((name == NULL || strcmp(ifmt->name, name) < 0) &&strcmp(ifmt->name, last_name) > 0) {name      = ifmt->name;long_name = ifmt->long_name;encode    = 0;}if (name && strcmp(ifmt->name, name) == 0)decode = 1;}if (name == NULL)break;last_name = name;printf(" %s%s %-15s %s\n",decode ? "D" : " ",encode ? "E" : " ",name,long_name ? long_name:" ");}
}

函数流程:

  • 遍历输出格式和输入格式
  • 打印名字和长名字
  • 输入格式作为解复用(Demux)打印
  • 输出格式作为复用(Mux)打印
4.2.2.3 Codecs
void Codecs(bool encoder)
{const AVCodecDescriptor **codecs;unsigned i, nb_codecs = get_codecs_sorted(&codecs);printf("%s:\n"" V..... = Video\n"" A..... = Audio\n"" S..... = Subtitle\n"" .F.... = Frame-level multithreading\n"" ..S... = Slice-level multithreading\n"" ...X.. = Codec is experimental\n"" ....B. = Supports draw_horiz_band\n"" .....D = Supports direct rendering method 1\n"" ------\n",encoder ? "Encoders" : "Decoders");for (i = 0; i < nb_codecs; i++) {const AVCodecDescriptor *desc = codecs[i];const AVCodec *codec = NULL;while ((codec = next_codec_for_id(desc->id, codec, encoder))) {printf(" %c", get_media_type_char(desc->type));printf((codec->capabilities & AV_CODEC_CAP_FRAME_THREADS) ? "F" : ".");printf((codec->capabilities & AV_CODEC_CAP_SLICE_THREADS) ? "S" : ".");printf((codec->capabilities & AV_CODEC_CAP_EXPERIMENTAL)  ? "X" : ".");printf((codec->capabilities & AV_CODEC_CAP_DRAW_HORIZ_BAND)?"B" : ".");printf((codec->capabilities & AV_CODEC_CAP_DR1)           ? "D" : ".");printf(" %-20s %s", codec->name, codec->long_name ? codec->long_name : "");if (strcmp(codec->name, desc->name))printf(" (codec %s)", desc->name);printf("\n");}}av_free(codecs);
}

函数流程:

  • 遍历支持的编解码器
  • 按照视频,音频,字幕,帧级多线程,切片级多线程,实验性,支持画横条,支持直接渲染等格式打印
4.2.2.4 Bsfs
void Bsfs()
{const AVBitStreamFilter *bsf = 0;void *opaque = NULL;printf("Bitstream filters:\n");while ((bsf = av_bsf_iterate(&opaque)))printf("%s\n", bsf->name);printf("\n");
}

函数流程:

  • 遍历支持的Bitstream过滤器
  • 打印过滤器名称
4.2.2.5 Protocols
void Protocols()
{void *opaque = NULL;const char *name;printf("Supported file protocols:\n""Input:\n");while ((name = avio_enum_protocols(&opaque, 0)))printf("%s\n", name);printf("Output:\n");while ((name = avio_enum_protocols(&opaque, 1)))printf("%s\n", name);
}

函数流程:

  • 遍历支持的输入/输出协议
  • 打印协议名称
4.2.2.6 Filters
void Filters()
{const AVFilter *filter = NULL;char descr[64], *descr_cur;void *opaque = NULL;int i, j;const AVFilterPad *pad;printf("Filters:\n""  T.. = Timeline support\n""  .S. = Slice threading\n""  ..C = Command support\n""  A = Audio input/output\n""  V = Video input/output\n""  N = Dynamic number and/or type of input/output\n""  | = Source or sink filter\n");while ((filter = av_filter_iterate(&opaque))) {descr_cur = descr;for (i = 0; i < 2; i++) {if (i) {*(descr_cur++) = '-';*(descr_cur++) = '>';}pad = i ? filter->outputs : filter->inputs;for (j = 0; pad && avfilter_pad_get_name(pad, j); j++) {if (descr_cur >= descr + sizeof(descr) - 4)break;*(descr_cur++) = get_media_type_char(avfilter_pad_get_type(pad, j));}if (!j)*(descr_cur++) = ((!i && (filter->flags & AVFILTER_FLAG_DYNAMIC_INPUTS)) ||( i && (filter->flags & AVFILTER_FLAG_DYNAMIC_OUTPUTS))) ? 'N' : '|';}*descr_cur = 0;printf(" %c%c%c %-17s %-10s %s\n",filter->flags & AVFILTER_FLAG_SUPPORT_TIMELINE ? 'T' : '.',filter->flags & AVFILTER_FLAG_SLICE_THREADS    ? 'S' : '.',filter->process_command                        ? 'C' : '.',filter->name, descr, filter->description);}
}

函数流程:

  • 遍历支持的过滤器
  • 按照时间线,切片线程,命令支持,音频输入/输出,视频输入/输出和源/显示类型打印。
4.2.2.7 PixFmts
void PixFmts()
{const AVPixFmtDescriptor *pix_desc = NULL;printf("Pixel formats:\n""I.... = Supported Input  format for conversion\n"".O... = Supported Output format for conversion\n""..H.. = Hardware accelerated format\n""...P. = Paletted format\n""....B = Bitstream format\n""FLAGS NAME            NB_COMPONENTS BITS_PER_PIXEL\n""-----\n");#if !CONFIG_SWSCALE
#   define sws_isSupportedInput(x)  0
#   define sws_isSupportedOutput(x) 0
#endifwhile ((pix_desc = av_pix_fmt_desc_next(pix_desc))) {enum AVPixelFormat av_unused pix_fmt = av_pix_fmt_desc_get_id(pix_desc);printf("%c%c%c%c%c %-16s       %d            %2d\n",sws_isSupportedInput (pix_fmt)              ? 'I' : '.',sws_isSupportedOutput(pix_fmt)              ? 'O' : '.',pix_desc->flags & AV_PIX_FMT_FLAG_HWACCEL   ? 'H' : '.',pix_desc->flags & AV_PIX_FMT_FLAG_PAL       ? 'P' : '.',pix_desc->flags & AV_PIX_FMT_FLAG_BITSTREAM ? 'B' : '.',pix_desc->name,pix_desc->nb_components,av_get_bits_per_pixel(pix_desc));}
}

函数流程:

  • 遍历支持的像素格式
  • 按照输入,输出,硬件支持,调色板和位流类型打印。
4.2.2.8 SampleFmts
void SampleFmts()
{int i;char fmt_str[128];for (i = -1; i < AV_SAMPLE_FMT_NB; i++)printf("%s\n", av_get_sample_fmt_string(fmt_str, sizeof(fmt_str), (enum AVSampleFormat)i));
}

函数流程:

  • 遍历支持的音频采样格式
  • 打印音频采样格式
4.2.2.9 Time
int64_t Time()
{return av_gettime();
}
4.2.2.10 NoPtsValue
int64_t NoPtsValue()
{return AV_NOPTS_VALUE;
}

函数说明:

  • 返回无效时间戳
4.2.2.11 ToTime
int64_t ToTime(int64_t const& pts, Rational const& timebase)
{AVRational tb1 = {timebase.num, timebase.den};AVRational tb2 = {1, AV_TIME_BASE};return av_rescale_q(pts, tb1, tb2);
}

函数说明:

  • 将以1/AV_TIME_BASE秒为单位的时间戳转换位以timebase为单位的时间戳
  • AV_TIME_BASE值为1000000
4.2.2.12 DisplayCardNames
std::vector<std::string> DisplayCardNames()
{std::vector<std::string> displayNames;IDXGIFactory * pFactory;HRESULT hr = CreateDXGIFactory(__uuidof(IDXGIFactory), (void**)(&pFactory));if(FAILED(hr))return displayNames;IDXGIAdapter * pAdapter;int iAdapterNum = 0;while(pFactory->EnumAdapters(iAdapterNum, &pAdapter) != DXGI_ERROR_NOT_FOUND){DXGI_ADAPTER_DESC desc;pAdapter->GetDesc(&desc);std::wstring aa(desc.Description);displayNames.push_back(WStringToString(aa));++iAdapterNum;}return displayNames;
}

函数流程:

  • 遍历系统中显卡名称
  • 将显卡名称放入数组并返回

示例

namespace mediasdk = media::sdk;
int main(int argc, char* argv[])
{mediasdk::Init();mediasdk::Formats();//打印支持的文件格式(封包格式).mediasdk::Codecs(true);//打印支持编码器.mediasdk::Codecs(false);//打印支持的解码器.mediasdk::Protocols();//打印支持的协议.mediasdk::Filters();//打印支持过滤器.mediasdk::PixFmts();//打印支持像素格式.mediasdk::SampleFmts();//打印支持采样格式.std::vector<std::string> names = media::sdk::DisplayCardNames();for(name: names)std::cout << "Display card: " << name << std::endl;return 0;
}

未完待续…

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

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

相关文章

Fastjson配置消息转换器(时间格式问题)

问题&#xff1a; 我们可以看见&#xff0c;日期的格式有点问题。 由于ArticleListVO类的createTime成员变量是Date类型&#xff0c;默认是由java的Jackson来处理&#xff0c;使用 ISO-8601 规范来处理日期时间格式。ISO-8601 是一种国际标准的日期时间表示法&#xff0c;例如&…

是否应该升级到ChatGPT 4.0?深度对比ChatGPT 3.5与4.0的差异

如果只是想简单地体验AI的魅力&#xff0c;感受大模型的独特之处&#xff0c;或是玩一玩文字游戏&#xff0c;那么升级至ChatGPT 4.0可能并非必需。然而&#xff0c;若你期望将AI作为提升工作学习效率的得力助手&#xff0c;那么我强烈建议你升级到ChatGPT 4.0。 如果你不知道…

【网站项目】面向社区健康服务的医疗平台

&#x1f64a;作者简介&#xff1a;拥有多年开发工作经验&#xff0c;分享技术代码帮助学生学习&#xff0c;独立完成自己的项目或者毕业设计。 代码可以私聊博主获取。&#x1f339;赠送计算机毕业设计600个选题excel文件&#xff0c;帮助大学选题。赠送开题报告模板&#xff…

从原理图到PCB全过程(嘉立创)1

1 将已经画好的原理图更新到PCB中&#xff08;点击应用修改&#xff09; 2 一开始PCB是杂乱的&#xff0c;需要回到原理图&#xff0c;框选各个模块&#xff0c;然后按住CtrlShiftX会自动在PCB显示这个部分&#xff0c;然后把各个部分分开 3 PCB画板需要有板框(嘉立创每个月都i…

Go语言学习Day6:数组与切片

名人说&#xff1a;莫愁千里路&#xff0c;自有到来风。 ——钱珝 创作者&#xff1a;Code_流苏(CSDN)&#xff08;一个喜欢古诗词和编程的Coder&#x1f60a;&#xff09; 目录 1. 数组① 什么是数组② 数组的声明③ 初始化数组的几种方式④ 遍历数组元素⑤ 数组为值类型⑥ 数…

A New Image Contrast Enhancement Algorithmusing Exposure Fusion Framework

Abstract 弱光图像由于能见度低&#xff0c;不利于人类观察和计算机视觉算法。为了解决这一问题&#xff0c;人们提出了许多图像增强技术&#xff0c;但现有的方法不可避免地会出现对比度增强不足和过度增强的问题。在本文中&#xff0c;我们提出了一种图像对比度增强算法来提…

瑞吉外卖实战学习--8、人员编辑更新

人员编辑更新 前言1、进入编辑窗口需要先获取用户信息2、通过上篇文章的update的方法来改变数据3、测试效果 前言 1、进入编辑窗口需要先获取用户信息 通过注解PathVariable 来获取路径需要携带的id然后赋值到路径上&#xff0c;再通过id查询用户信息 /*** 通过id查询用户信…

VUE3极速上手手册

文章目录 Vue3简介一、整体认识Vue3项目1、创建Vue3工程2、主要工程结构 二、数据双向绑定1、vue2语法的双向绑定2、OptionsAPI和CompositionAPI3、Vue3中的数据双向绑定3.1 ref定义基础类型响应式数据3.2 reactive定义对象型响应式数据3.3 ref对比reactive3.4 标签的ref属性3.…

Android 开发 Spinner setSelection 不起作用

问题 Android 开发 Spinner setSelection 不起作用 详细问题 笔者进行Android项目开发&#xff0c;根据上一个页面用户选择数据&#xff0c;显示当前页面Spinner选项&#xff0c;调用 Spinner setSelection 不起作用。 相关java代码 spinner.setAdapter(adapter); …

uniapp点击按钮连接wifi?

<view><button class"but" bindtap"connectToWifi">点击连接WiFi</button> </view> js: Page({// 页面数据data: {wifiConnected: false},onLoad: function () {this.checkWifiPermission();},// 检查 WiFi 权限checkWif…

不同设备使用同一个Git账号

想要在公司和家里的电脑上用同一个git账号来pull, push代码 1. 查看原设备的用户名和邮箱 第1种方法&#xff0c; 依次输入 git config user.name git config user.email第2种方法&#xff0c; 输入 cat ~/.gitconfig2. 配置新设备的用户名和邮箱 用户名和邮箱与原设备保持…

uniApp——零基础App的快速开发记录

公司需要使用移动端App来接受云平台的数据&#xff0c;记录一下学习过程。因水平有限&#xff0c;在学习的过程中不能完整、准确、全面的发现错误&#xff0c;如有错误&#xff0c;请评论指教&#xff0c;谢谢&#xff01; 需求分析 总体需求目标&#xff1a;开发一款android的…

文件传输升级!如何让你的MacBook与安卓设备快速共享大文件?

在现代工作环境中&#xff0c;跨设备、跨平台的文件传输已成为日常办公不可避免的一部分。尤其是MacBook和安卓手机之间的大文件传输&#xff0c;由于两者系统的差异&#xff0c;可能会遇到一些效率上的挑战。为了优化这一过程&#xff0c;以下是一些提升传输效率的新技巧。 1&…

搜索与图论——Prim算法求最小生成树

在最小生成树问题里&#xff0c;正边和负边都没问题 朴素版prim算法 时间复杂度O(n^2) 生成树&#xff1a;每一次选中的t点&#xff0c;它和集合的距离对应的那条边&#xff0c;就是生成树的一条边 算法流程和dijkstra算法非常相似 #include<iostream> #include<cs…

稀碎从零算法笔记Day33-LeetCode:生命游戏

今天是“耶稣受难人”&#xff0c;笔者给自己放了天假hhh 且慢&#xff0c;还是会写一点的。 根据 百度百科 &#xff0c; 生命游戏 &#xff0c;简称为 生命 &#xff0c;是英国数学家约翰何顿康威在 1970 年发明的细胞自动机。 题型&#xff1a;矩阵、原地实现、位运算 链…

Pytorch for training1——read data/image

blog torch.utils.data.Dataset create dataset with class torch.utils.data.Dataset automaticly import torch from torch.utils.data import Datasetclass MyDataset(Dataset):def __init__(self, data):self.data datadef __getitem__(self, index):# 根据索引获取样本…

紫光展锐P7885核心板详细参数介绍_5G安卓智能模块开发方案

紫光展锐P7885核心板采用了先进的6nm EUV制程工艺&#xff0c;集成了高性能的应用处理器和金融级安全解决方案&#xff0c;为用户带来了全新的性能体验。 P7885核心板搭载了先进的6nm制程工艺SoC P7885&#xff0c;其中包含四核A76和四核A55&#xff0c;主频可达2.7Ghz&#xf…

计算机网络面试问题(一)

1.在浏览器中输⼊URL并按下回⻋之后会发⽣什么 2.TCP三次握⼿的过程,为什么三次握手 TCP&#xff08;传输控制协议&#xff09;的三次握⼿是建⽴⽹络连接的过程&#xff0c;确保通信双⽅能够正确地进⾏数据传输。 第⼀次握⼿&#xff08;SYN&#xff09;&#xff1a; 客户端&am…

【THM】SQL Injection(SQL注入)-初级渗透测试

简介 SQL(结构化查询语言)注入,通常称为 SQLi,是对 Web 应用程序数据库服务器的攻击,导致执行恶意查询。当 Web 应用程序使用未经正确验证的用户输入与数据库进行通信时,攻击者有可能窃取、删除或更改私人数据和客户数据,并攻击 Web 应用程序身份验证方法以获取私有数据…

风险与收益

风险与收益 影响资产需求的主要因素财富总量预期收益率资产的流动性影响流动性的主要因素 风险 如何降低风险系统风险和非系统风险机会集合与有效集合资产组合理论 影响资产需求的主要因素 影响资产需求的主要因素包括&#xff1a;财富总量、预期收益率、资产的流动性和风险。…