2023-04-06:拥抱Golang,优化FFmpeg音频编码器,探究encode_audio.c的内部结构。
2023-04-06:拥抱Golang,优化FFmpeg音频编码器,探究encode_audio.c的内部结构。
答案2023-04-06:
见moonfdd/ffmpeg-go库。
这段代码是一个示例程序,用于将音频 PCM 数据编码为 MP2 格式的音频文件。下面是代码的详细步骤:
1.导入 ffmpeg-go 和 os 等 Go 库;
2.定义一些变量,包括输出文件名、音频编解码器、音频编解码上下文、音频帧、音频数据包等;
3.查找 MP2 编码器并分配音频编解码上下文;
4.配置音频编解码参数,设置音频采样率、通道数、位率等;
5.打开音频编解码器;
6.创建输出文件;
7.开始编码过程,并将编码后的音频数据写入输出文件中。
具体地,编码过程包括以下几个步骤:
1.初始化音频帧;
2.将音频 PCM 数据填充到音频帧中;
3.发送音频帧到编解码器中进行编码;
4.从编解码器中读取编码后的音频数据包;
5.将编码后的音频数据包写入输出文件中。
最后,释放内存空间并关闭文件和编码器。在该示例程序中,我们需要手动设置 FFmpeg 库的路径,以便正确加载库文件。
命令如下:
go run ./examples/internalexamples/encode_audio/main.go ./out/encode_audio.mp2./lib/ffplay ./out/encode_audio.mp2
golang代码如下:
package mainimport ("fmt""math""os""unsafe""github.com/moonfdd/ffmpeg-go/ffcommon""github.com/moonfdd/ffmpeg-go/libavcodec""github.com/moonfdd/ffmpeg-go/libavutil"
)func main0() (ret ffcommon.FInt) {var filename stringvar codec *libavcodec.AVCodecvar c *libavcodec.AVCodecContextvar frame *libavutil.AVFramevar pkt *libavcodec.AVPacketvar i, j, k ffcommon.FIntvar f *os.Filevar samples *ffcommon.FUint16Tvar t, tincr ffcommon.FFloatif len(os.Args) <= 1 {fmt.Printf("Usage: %s <output file>\n", os.Args[0])return 0}filename = os.Args[1]/* find the MP2 encoder */codec = libavcodec.AvcodecFindEncoder(libavcodec.AV_CODEC_ID_MP2)if codec == nil {fmt.Printf("Codec not found\n")os.Exit(1)}c = codec.AvcodecAllocContext3()if c == nil {fmt.Printf("Could not allocate audio codec context\n")os.Exit(1)}/* put sample parameters */c.BitRate = 64000/* check that the encoder supports s16 pcm input */c.SampleFmt = libavutil.AV_SAMPLE_FMT_S16if check_sample_fmt(codec, c.SampleFmt) == 0 {fmt.Printf("Encoder does not support sample format %s",libavutil.AvGetSampleFmtName(c.SampleFmt))os.Exit(1)}/* select other audio parameters supported by the encoder */c.SampleRate = select_sample_rate(codec)c.ChannelLayout = uint64(select_channel_layout(codec))c.Channels = libavutil.AvGetChannelLayoutNbChannels(c.ChannelLayout)/* open it */if c.AvcodecOpen2(codec, nil) < 0 {fmt.Printf("Could not open codec\n")os.Exit(1)}f, _ = os.Create(filename)if f == nil {fmt.Printf("Could not open %s\n", filename)os.Exit(1)}/* packet for holding encoded output */pkt = libavcodec.AvPacketAlloc()if pkt == nil {fmt.Printf("could not allocate the packet\n")os.Exit(1)}/* frame containing input raw audio */frame = libavutil.AvFrameAlloc()if frame == nil {fmt.Printf("Could not allocate audio frame\n")os.Exit(1)}frame.NbSamples = c.FrameSizeframe.Format = int32(c.SampleFmt)frame.ChannelLayout = c.ChannelLayout/* allocate the data buffers */ret = frame.AvFrameGetBuffer(0)if ret < 0 {fmt.Printf("Could not allocate audio data buffers\n")os.Exit(1)}/* encode a single tone sound */t = 0tincr = float32(2 * libavutil.M_PI * 440.0 / float64(c.SampleRate))for i = 0; i < 200; i++ {/* make sure the frame is writable -- makes a copy if the encoder* kept a reference internally */ret = frame.AvFrameMakeWritable()if ret < 0 {os.Exit(1)}samples = (*ffcommon.FUint16T)(unsafe.Pointer(frame.Data[0]))for j = 0; j < c.FrameSize; j++ {*(*ffcommon.FUint16T)(unsafe.Pointer(uintptr(unsafe.Pointer(samples)) + uintptr(2*j*2))) = ffcommon.FUint16T(math.Sin(float64(t)) * 10000)for k = 1; k < c.Channels; k++ {*(*ffcommon.FUint16T)(unsafe.Pointer(uintptr(unsafe.Pointer(samples)) + uintptr((2*j+k)*2))) = *(*ffcommon.FUint16T)(unsafe.Pointer(uintptr(unsafe.Pointer(samples)) + uintptr(2*j*2)))}t += tincr}encode(c, frame, pkt, f)}/* flush the encoder */encode(c, nil, pkt, f)f.Close()libavutil.AvFrameFree(&frame)libavcodec.AvPacketFree(&pkt)libavcodec.AvcodecFreeContext(&c)return 0
}/* check that a given sample format is supported by the encoder */
func check_sample_fmt(codec *libavcodec.AVCodec, sample_fmt libavutil.AVSampleFormat) ffcommon.FInt {p := codec.SampleFmtsfor *p != libavutil.AV_SAMPLE_FMT_NONE {if *p == sample_fmt {return 1}p = (*libavutil.AVSampleFormat)(unsafe.Pointer(uintptr(unsafe.Pointer(p)) + uintptr(8)))}return 0
}/* just pick the highest supported samplerate */
func select_sample_rate(codec *libavcodec.AVCodec) ffcommon.FInt {var p *ffcommon.FIntvar best_samplerate ffcommon.FIntif codec.SupportedSamplerates == nil {return 44100}p = codec.SupportedSampleratesfor *p != 0 {if best_samplerate == 0 || int32(math.Abs(float64(44100-*p))) < int32(math.Abs(float64(44100-best_samplerate))) {best_samplerate = *p}p = (*int32)(unsafe.Pointer(uintptr(unsafe.Pointer(p)) + uintptr(4)))}return best_samplerate
}/* select layout with the highest channel count */
func select_channel_layout(codec *libavcodec.AVCodec) ffcommon.FInt {var p *ffcommon.FUint64Tvar best_ch_layout ffcommon.FUint64Tvar best_nb_channels ffcommon.FIntif codec.ChannelLayouts == nil {return libavutil.AV_CH_LAYOUT_STEREO}p = codec.ChannelLayoutsfor *p != 0 {nb_channels := libavutil.AvGetChannelLayoutNbChannels(*p)if nb_channels > best_nb_channels {best_ch_layout = *pbest_nb_channels = nb_channels}p = (*uint64)(unsafe.Pointer(uintptr(unsafe.Pointer(p)) + uintptr(8)))}return ffcommon.FInt(best_ch_layout)
}func encode(ctx *libavcodec.AVCodecContext, frame *libavutil.AVFrame, pkt *libavcodec.AVPacket, output *os.File) {var ret ffcommon.FInt/* send the frame for encoding */ret = ctx.AvcodecSendFrame(frame)if ret < 0 {fmt.Printf("Error sending the frame to the encoder\n")os.Exit(1)}/* read all the available output packets (in general there may be any* number of them */for ret >= 0 {ret = ctx.AvcodecReceivePacket(pkt)if ret == -libavutil.EAGAIN || ret == libavutil.AVERROR_EOF {return} else if ret < 0 {fmt.Printf("Error encoding audio frame\n")os.Exit(1)}output.Write(ffcommon.ByteSliceFromByteP(pkt.Data, int(pkt.Size)))pkt.AvPacketUnref()}
}func main() {os.Setenv("Path", os.Getenv("Path")+";./lib")ffcommon.SetAvutilPath("./lib/avutil-56.dll")ffcommon.SetAvcodecPath("./lib/avcodec-58.dll")ffcommon.SetAvdevicePath("./lib/avdevice-58.dll")ffcommon.SetAvfilterPath("./lib/avfilter-56.dll")ffcommon.SetAvformatPath("./lib/avformat-58.dll")ffcommon.SetAvpostprocPath("./lib/postproc-55.dll")ffcommon.SetAvswresamplePath("./lib/swresample-3.dll")ffcommon.SetAvswscalePath("./lib/swscale-5.dll")genDir := "./out"_, err := os.Stat(genDir)if err != nil {if os.IsNotExist(err) {os.Mkdir(genDir, 0777) // Everyone can read write and execute}}main0()
}

相关文章:
2023-04-06:拥抱Golang,优化FFmpeg音频编码器,探究encode_audio.c的内部结构。
2023-04-06:拥抱Golang,优化FFmpeg音频编码器,探究encode_audio.c的内部结构。 答案2023-04-06: 见moonfdd/ffmpeg-go库。 这段代码是一个示例程序,用于将音频 PCM 数据编码为 MP2 格式的音频文件。下面是代码的详细…...
归排、计排深度理解
归并排序:是创建在归并操作上的一种有效的排序算法。算法是采用分治法(Divide and Conquer)的一个非常典型的应用,且各层分治递归可以同时进行。归并排序思路简单,速度仅次于快速排序,为稳定排序算法&#…...
设计原则(单一职责原则 开放封闭原则 里氏替换原则 依赖倒置原则 接口隔离原则 迪米特法则)
设计原则单一职责原则(SRP)从三大特性角度看原则:应用的设计模式:开放封闭原则(OCP)从三大特性角度看原则:应用的设计模式:里氏替换原则(LSP)从三大特性角度看原则:应用的设计模式:依赖倒置原则(DIP)从三大特性角度看原则:应用的设计模式&…...
好像模拟了一个引力场
( A, B )---3*30*2---( 1, 0 )( 0, 1 ) 做一个网络让输入只有3个节点,每个训练集里有4张图片,让B的训练集全为0,排列组合A,观察迭代次数平均值的变化。 A-B 迭代次数 0 1 0 2*0*0*7-0*0*0*0 12957.31 0 0 0 2*0*0*7-0*0…...
MySQL优化——Explain分析执行计划详解
文章目录前言一. 查看SQL执行频率二. 定位低效率执行SQL三. explain分析执行计划3.1 id3.2 select_type3.3 table3.4 type3.5 key3.6 rows3.7 extra四. show profile分析SQL前言 在应用的的开发过程中,由于初期数据量小,开发人员写 SQL 语句时更重视功能…...
xcode 14.3 file not found libarclite_iphoneos.a
最近升级到xcode 14.3 版本的同学,会遇到这个一个问题 File not found: /Users/johnson/Downloads/Xcode-beta.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/arc/libarclite_iphoneos.a 解决方法(亲测有效) 在podfile文件中,增…...
基于AI+数据驱动的慢查询索引推荐
目前,美团内部每天产生的慢查询数量已经超过上亿条。如何高效准确地为慢查询推荐缺失的索引来改善其执行性能,是美团数据库研发中心面临的一项挑战。为此,我们与华东师范大学开展了科研合作,在AI领域对索引推荐进行了探索和实践&a…...
【ESP32】嵌入式FreeRtos--Task
FreeRTOS中文数据手册:https://www.freertos.org/zh-cn-cmn-s/RTOS.html 任务函数 任务函数描述xTaskCreate()使用动态的方法创建一个任务xTaskCreateStatic()使用静态的方法创建一个任务xTaskCreatePinnedToCore指定任务运行的核心(最后一个参数)vTaskDelete()删…...
【操作系统】面试官都爱问的进程调度算法
【操作系统】面试官都爱问的进程调度算法 文章目录【操作系统】面试官都爱问的进程调度算法先来先服务调度算法最短作业优先调度算法高响应比优先调度算法时间片轮转调度算法最高优先级调度算法多级反馈队列调度算法进程调度算法也称 CPU 调度算法,毕竟进程是由 CPU…...
Spring-Web spi机制解析
org.springframework.web.SpringServletContainerInitializer#onStartup 在这里打个断点,查看程序是否会进来 可以发现程序进来了:主要spi机制,看看这里做了什么操作? 去寻找所有实现了WebApplicationInitializer的类 将符合条件…...
数据结构|将链表中小于0的数全部放在大于0的数的前面
题1: 某带头结点的非空单链表L中所有元素为整数,结点类型定义如下: typedef struct node { int data; struct node *next; } LinkNode; 设计一个尽可能高效的算法,将所有小于零的结点移到所有大于等于零的结点的前面。 分…...
分享106个ASP影音娱乐源码,总有一款适合您
分享106个ASP影音娱乐源码,总有一款适合您 106个ASP影音娱乐源码下载链接:https://pan.baidu.com/s/13k8UaJrCci_z4Q0gQbtDtg?pwdjq44 提取码:jq44 Python采集代码下载链接:采集代码.zip - 蓝奏云 我的博客地址:亚…...
win10 PyCharm Anaconda过程记录
1、Anaconda用来配置不同的虚拟环境 进入 Anaconda Prompt 输入conda activate Hui(此为自己创建的放置虚拟环境的文件夹) 编译运行过程中出现No module named seaborn后 pip install seaborn...
Chrome扩展程序导出备份与本地导入浏览器
现在即使在国内下载个chrome,转个插件也千难万难。现在科学上网也越来越难,由于众所周知的原因,连qiang这个话题都是敏感词。哀默于心死,还是回避这个话题 只要把之前装的chrome打包,然后再重新安装一遍。操作步骤如下…...
mysql常用运算符
mysql常用运算符一、去重和空值1.distinct2.null参与运算3.用ifnull函数解决问题二、比较运算符三、dual伪表和数值运算1.常规运算2.比较运算符3.<>安全相等四、常用正则相关的比较运算符1.基本运算符2.模糊查询3.正则表达式五、逻辑运算符六、位运算总结一、去重和空值 …...
PyTorch 深度学习框架:优雅而简洁的代码实现
PyTorch 是由 Facebook 发布的深度学习框架,旨在为研究人员和工程师提供快速、灵活和简单的实验平台。与其他框架相比,PyTorch 具有简洁的 API 和灵活的动态计算图,使得构建和训练深度神经网络变得更加优雅和简洁。本文将介绍 PyTorch 的基本…...
【SpringMVC】请求重定向和转发
forward:表示转发 处理器方法返回ModelAndView,实现转发forward 语法: setViewName("forward:视图文件完整路径") forward特点: 不和视图解析器一同使用,就当项目中没有视图解析器redirect:表示重定向 处理…...
Vue中@click的常见修饰符
在 Vue 的click事件中,可以使用以下修饰符: .stop:阻止事件继续传播。.prevent:阻止默认事件。.capture:使用事件捕获模式。.self:只当事件是从侦听器绑定的元素本身触发时才触发回调。.once:只…...
软件测试面试复盘:技术面没有难倒我,hr面被虐的体无完肤
一般提到面试,肯定都会想问一下面试结果,我就大概的说一下面试结果,哈哈,其实不太想说,因为挺惨的,并没有像很多大佬一样 ”已拿字节阿里腾讯各大厂offer”,但是毕竟是自己的经历,无…...
vue实现鼠标移入移出事件+解决鼠标事件没有反应
鼠标移入移出事件代码 <div mouseenter"onMouseOver(item)" mouseleave"onMouseOut"></div> methods methods:{// 鼠标移入onMouseOver(item){console.log(item, 鼠标进来了);},// 鼠标移出onMouseOut(){console.log(鼠标出去了);}, }, 这…...
手把手教你用Python/Node.js快速接入抖音开放平台,实现用户信息获取
Python/Node.js实战:抖音开放平台用户信息获取全流程解析 抖音开放平台为开发者提供了丰富的用户数据接口,但很多技术团队在对接过程中常因OAuth2.0流程复杂而卡在授权环节。本文将用两种主流技术栈演示如何快速完成从授权到获取用户信息的完整闭环。 1.…...
基于插件化架构的OBS实时音乐信息集成系统技术解析
基于插件化架构的OBS实时音乐信息集成系统技术解析 【免费下载链接】tuna Song information plugin for obs-studio 项目地址: https://gitcode.com/gh_mirrors/tuna1/tuna Tuna是一款面向OBS Studio的高性能插件化实时音乐信息集成系统,采用模块化架构设计&…...
自动化测试(十) 微服务测试策略-单元到集成到契约到端到端分层实战
微服务测试策略:单元→集成→契约→端到端分层实战前面咱们分别聊了单元测试、接口测试、契约测试。今天把它们串起来,聊聊微服务架构下怎么设计完整的测试策略——每一层测什么、怎么测、用什么工具。一、微服务测试的"金字塔"变体 单体应用的…...
learn claude code S12 Worktree 任务隔离详解笔记
S12 Worktree 任务隔离详解笔记基于 s12_worktree_task_isolation.py 源码逐行分析,配合 s12-worktree-task-isolation.md 设计思路。一、问题:多个任务共享一个工作目录,互相踩踏 前面 11 章的 agent 都在同一个工作目录下操作。当只有一个 …...
【高光谱图像数据处理实战】基于Python的ENVI图像交互式裁剪与光谱数据预处理
前言在处理高光谱图像数据(Hyperspectral Imaging, HSI)时,我们常常需要面对两个核心问题:一是如何从庞大的三维数据立方体(Data Cube)中高效、准确地提取感兴趣区域(ROI)…...
Windows右键菜单为何变得臃肿?ContextMenuManager帮你重新掌控
Windows右键菜单为何变得臃肿?ContextMenuManager帮你重新掌控 【免费下载链接】ContextMenuManager 🖱️ 纯粹的Windows右键菜单管理程序 项目地址: https://gitcode.com/gh_mirrors/co/ContextMenuManager 你是否曾为Windows右键菜单的混乱而烦…...
迭代式代码进化:基于进化算法与LLM的自动化代码优化系统
1. 项目概述:当代码学会自我进化最近在GitHub上看到一个挺有意思的项目,叫aaronjmars/iterative-code-evolution。光看名字,你可能会觉得这又是一个关于“代码生成”或者“AI编程”的常规项目。但当我深入进去,把玩了一番之后&…...
避开学术‘红线’:手把手教你用AI+ArcMap合法合规处理论文中的中国地图
科研地图合规处理全流程:从标准地图到安全应用的实战指南 在学术研究中,地图作为重要的空间表达工具,其规范使用直接关系到研究成果的合法性和可信度。近年来,随着科研管理日趋严格,地图使用不当导致的论文撤稿、项目终…...
OptiSearch:浏览器扩展实现AI与搜索引擎的无缝集成
1. 项目概述:当搜索遇到AI,一次查询,双重答案作为一名长期在信息检索和效率工具领域折腾的开发者,我一直在思考一个问题:我们每天在搜索引擎和AI聊天机器人之间要切换多少次标签页?搜索一个技术问题&#x…...
千问 LeetCode 2281.巫师的总力量和 Python3实现
LeetCode 2281. 巫师的总力量和(Sum of Total Strength of Wizards) 是一道难度较高的题目,核心在于 贡献法 单调栈 前缀和的前缀和(prefix sum of prefix sums)。下面给出 清晰、高效、符合 Python3 习惯 的实现&am…...
