JCHub

  • Home
  • Category
    • A/V
    • WebRTC
    • Beauty of Programming
    • Linux
    • Windows
    • Moments of Life
    • Campus Life
  • Reference
    • API Reference
    • Utilities
    • AV Test
    • Doc
  • Message Board
  • About
JCHub
Code as My Sword, Lost in Obsession
音视频

PCM音量控制(高级篇)

去年写过一篇文章,有关PCM的音量控制:http://blog.jianchihu.net/pcm-volume-control.html。那时阐述了一些概念,对一些细节没有详细描述。因为有人问到使用对数关系调节音量,故开此篇文章。 声学中的分贝 因为人耳的特性,我们对声音的大小感知呈对数关系。所以我们通常用分贝描述声音大小,分贝(decibel)是量度两个相同单位之数量比例的单位,主要用于度量声音强度,常用dB表示。声学中,声音的强度定义为声压。计算分贝值时采用20微帕斯卡为参考值(通常被认为是人类的最少听觉响应值,大约是3米以外飞行的蚊子声音)。这一参考值是人类对声音能够感知的阈值下限。声压是场量,因此使用声压计算分贝时使用下述版本的公式: 其中的pref是标准参考声压值20微帕。 分贝声音变化范围 在编程中,我们可以用以下公式计算两个声音之间的动态范围,单位为分贝: [crayon-69c4086f1a938063049939/] 其中 A1 和 A2 是两个声音的振幅,在程序中表示每个声音样本的大小。声音采样大小(也就是量化深度)为1bit时,动态范围为0,因为只可能有一个振幅。采样大小为8bit也就是一个字节时,最大振幅是最小振幅的 256 倍。因此,动态范围是 48 分贝,计算公式如下: dB = 20 * log(256) 48 分贝的动态范围大约是一个安静房间和一台运行着电动割草机之间的区别。如果将声音采样大小增加一倍到16bit,产生的动态范围则为 96 分贝,计算公式如下: dB = 20 * log(65536) 这非常接近听力最低阈值和产生痛感之间的区别,这个范围被认为非常适合还原音乐。 了解了分贝的相关概念我们通过图表说下为什么要用对数关系描述声音大小。 1)音量滑块与声音增幅大小线性变化。 上述左图中,音量滑块位置与声音振幅为线性增长关系,右图是我们人耳感受的音量大小与滑块位置关系。可知,在左侧移动相同距离的滑块,感知到的声音变化范围很大,在右侧接近声音最大值移动相同距离滑块,感知到的声音大小变化就很小了。 2)音量滑块与声音振幅大小对数关系变化。 左图中,音量滑块位置与声音振幅对数关系增长。右图中无论哪个位置,移动相同距离滑块,感知到的声音变化都是相同的。 需要说明的是滑块最小位置只是接近0,不能为0,因为对数函数y=logx中x>0。 windows系统中音量滑块控制的声音变化范围 在最新版的windows系统中,音量滑块控制的声音变化范围也是96分贝。如下表所示,是不同版本windows的音量范围以及默认音量值。 从表中我们可以看到默认值都是0分贝,根据分贝公式:dB = 20 * log(A1 / A2),当A1,A2相等时,db为0。 程序实现 了解了分贝以及Windows中音量滑块是在哪个范围变化,我们的程序实现起来也很简单。 这里我们规定音量大小变化范围也是96分贝,每个声音采样大小为16位。对于分贝公式:dB = 20 * log(A1 / A2),我们取参考声音振幅A2为原始声音振幅,A1为调节后的声音振幅大小。可知调节后的声音: [crayon-69c4086f1a93e789797789/] 看过一篇文章说理想的声音调节步长最好是2db,对于96db范围,我们按2db步长进行分割,可以分成48份,这样我们得到的声音变化为[-96db,-94db,-92db,...-4db.-2db,0db],假设我们要调节一半音量大小,也就是-48db,由上述公式可知:调节后音量A1大小: [crayon-69c4086f1a941029552107/] 程序伪代码如下,具体db大小与滑块位置对应关系的实现这里就不写出: [crayon-69c4086f1a942478162017/] 参考 [1] Audio-Tapered Volume Controls.https://docs.microsoft.com/en-us/windows/win32/coreaudio/audio-tapered-volume-controls

2017年5月14日 25comments 19866hotness 25likes Jeff Read all
Windows

为什么Windows下无法实现ptp协议

前段时间,要写一个windows下的分布式软件,刚开始的方案是需要一个精确的时钟同步,误差必须控制在1毫秒内。也许很多人都知道有NTP以及PTP 时间同步协议。windows本身自带NTP协议的服务,通过注册表配置即可实现,但是误差无法满足要求,而且每次配置都要重启W32Time服务。也只有PTP这个精确时钟同步协议满足要求,后面想自己实现PTP协议,不过查了些资料,发现想的太简单了。 PTP协议的原理虽然简单,不过实现起来不简单,需要确定最佳主时钟,而且需要获取高精度的本地时钟(后面查到win8以上系统可以通过GetSystemTimePreciseAsFileTime获取<1us的高精度时钟)。后来发现有个著名的开源ptp协议实现:ptpd(Precision Time Protocol daemon)。不过该代码只针对linux系统,至于为什么没有在windows下的实现,大概有如下的原因: 1)windows不提供带时间戳的网络包,不像linux下socket有SO_TIMESTAMP选项,而且也不提供高精度时钟的内核api(win8以下系统); 2)部分windwos系统存在时钟调整Bug,比如你调整的系统时间低于16个tick(系统的时基)单位,将会被忽略。 由于以上原因,后面也没去做windows上的ptp协议实现。

2017年3月27日 1comments 5621hotness 11likes Jeff Read all
音视频

音视频提取工具

以前搞过播放器的Demuxer模块,业余时间重写了个简单音视频提取工具。可以从视频编码格式为h264+音频编码格式为aac的mp4以及flv封装文件中提取出音视频。写这个工具其实是为了方便自己听歌。因为现在很多音乐都开始注重版权,很多歌下载都要钱,比如网易云音乐,我很喜欢听泰勒的歌曲,以前花钱买过,后面换了部设备,重新下载又得要花钱。不过大部分要花钱的歌曲都有MV可以免费下载,网易云的MV都是mp4格式,现在的mp4基本都是h264+aac,所以我就想从mv中把音频提取出来,这样就可以随便听了。说完这些介绍下这个工具的使用。 工具下载链接在文章末尾,只有几十K,没有用到大多数播放器都用到的ffmpeg,ffmpeg都几十兆了。这个工具是个简单的命令行工具。界面如下: 1)第一步按提示输入提取类型,输入1只提取音频文件,输入2只提取视频文件,输入3提取音视频; 2)第二步输入视频文件名(如果视频文件与程序不在一个目录还要输入路径),最简单的方法是直接拖放视频文件到程序。 3)回车等待解析。提取结束会在程序目录生成对应文件。音频为audio.aac,视频为video.h264。 下载地址:http://jchblog.u.qiniudn.com/201703/ExtratTool.zip 由于之前写的这个软件找不到了,地址也失效了,故提供一个ffmpeg版本的,下载解压后,运行bat文件,输入要操作mp4文件名即可。 ffmpeg版本下载地址:https://gitee.com/jianchihu/jchcdn/raw/master/download/mp4toaac.zip

2017年3月18日 7comments 4957hotness 1likes Jeff Read all
Linux

Ubuntu添加2560x1440分辨率

前段时间购入了戴尔U2515 2K显示器,分辨率为2560x1440,不过发现在Ubuntu中找不到2560x1440分辨率设置,最大的只有2560x1600分辨率。查了下,通过xrandr命令可解决。 1)通过xrandr即可查看当前显示器所有分辨率,其中Virtual1是是当前显示器名称: [crayon-69c4086f1cf31763216041/] 2)接着敲入: [crayon-69c4086f1cf37019669774/] 添加我们的2K分辨率。 3)在显示器分辨率列表中添加上面得到的分辨率设置: [crayon-69c4086f1cf38925413468/] 4)添加该模式,其中Virtual1是第一步中得到的显示器名称,由于我是跑在虚拟机,所以为Virtual1: [crayon-69c4086f1cf3a023504810/] 最后就可以在分辨率设置中找到该分辨率了。

2017年3月4日 0comments 4177hotness 11likes Jeff Read all
Beauty of Programming

Intel Media SDK 内存优化(转)

简介 Media SDK 是一个软件开发库,包含解码、视频处理和编码三大模块。利用 Intel 平台的硬件加速能力, Media SDK 为低端用户提供了优秀的高清视频质量,极大的降低了播放高清视频的硬件门槛。此外,强大的视频 APIs 也减轻了程序开发者的工作负担,使他们能够集中精力去处理程序的逻辑模块,而不必关心于 Media SDK 内部的复杂编解码逻辑及其如何提高效率。 本篇文章将着重讲述如何利用 Media SDK 提高程序的效率,面对的读者主要是视音频程序开发人员。 本文以下内容为: - 初始化设置之优化 - 内存选择之优化 - 多线程之优化 - 异步方式之优化 初始化设置之优化 在讨论优化之前,首先要了解一下 Media SDK 是如何初始化编解码器的。 1. 创建和初始化一个编解码 Session。Media SDK 提供了 mfxStatus MFXInit(mfxIMPL impl,mfxVersion *ver, mfxSession *session)函数来完成这个创建和初始化工作。 2. 使 用 已 创 建 的 Session 来 创 建 它 的 解 码 器 。 Media SDK 提 供 了 mfxStatus MFXVideoDECODE_Init(mfxSession session, mfxVideoParam *par)来完成解码器的创建和初始化工作。 3. 使 用 已 创 建 的 Session 来 创 建 它 的 编 码 器 。 Media SDK 提 供 了 mfxStatus MFXVideoENCODE_Init(mfxSession session, mfxVideoParam *par)来完成编码器的创建和初始化工作。 在创建和初始化编解码 Session 时,我们需要制定编解码的实现方式:硬件方式还是软件方式。最简单的方法是强制使用硬件方式。这会带来一个问题,在非 Intel 显卡支持的平台,应用程序将无法正常工作。当然,如果强制使用软件方式,虽然应用程序能够工作于其他平台,但是在 Intel 显卡平台,硬件加速特性将荡然无存!虽然应用程序可以外加代码检测平台硬件来决定如何选择,但是程序的复杂度和效率将受到影响。Media SDK 内部提供了自动选择功能,它会根据当前运行系统来选择何种方式。这样就能够兼顾不同平台及其性能。 在 MFXInit 函数中,枚举类型 mfxIMPL 定义 AUTO 功能: [crayon-69c4086f1d8dd168119344/] 相应的简单实用方式如下: [crayon-69c4086f1d8e2656319311/] 通过 MFX_IMPL_AUTO 的设置,问题迎刃而解。 那么如何获知当前的编解码实用方法呢?Media SDK 已经考虑到了这种需求,它提供了mfxStatus MFXQueryIMPL(mfxSession session, mfxIMPL *impl)来查询当前采用的方法。 此外,在优化编码器初始化时,程序必须注意 mfxInfoMFX 结构中 TargetUsage 变量的选择,它的定义如下: [crayon-69c4086f1d8e3359012178/] TargetUsage 值的选择决定了编码的性能和图像质量,它的值从 0~7,值越高效率越好,但图像质量会有所下降。最佳值应该和用户选择需求挂钩,原则上是略比最小用户需求高 1 级。 本节小结: 1. 初始化 Session 时,要使用 MFX_IMPL_AUTO。它有利于跨越硬件平台,并提高编解码效率。 2. TargetUsage 的选择应该和用户需求相结合。为了提高性能,选择略高于用户最小需求的值为佳。 内存选择之优化 Media SDK 使用内存缓冲来输入/输出视频数据,内存缓冲的不同种类将会直接影响编解码的效率。内存缓冲可以是一块在系统内存中的连续块(通过 malloc 或者 new 来分配),也可以是显卡内存的连续块(通过 Microsoft Direct3D9 Surface 函数来分配)。那么内存缓冲的 种类由谁来决定呢?本节就是以此为基础,讨论在不同情况下程序如何选择内存缓冲种类的问题。 在讨论内存缓冲对编解码影响之前,先讨论下面三种情况下的内存数据传送问题。 - 系统内存间数据如何传送? 对于程序员而言,这个是最为简单的日常编程事项。一般的使用方式是 memcpy,在一些数据较大情况下(超过 L3 的 cache 尺寸时候,用 movntqa 等指令)。不管何种方式,都是CPU-BASED 的代码,在 SIMD 下效率很高。 - 显存间数据是如何传送的? 它类似于系统内存之间的数据传送,并且显存的带宽和速率都很高,传送速度更快。 - 显存和系统内存间数据是如何传送的? 通过 DMA 方式传送内存数据,速度依赖于 DMA 的带宽和速率(普通 DMA 的传送速率在33.3MB/s,而 Ultra DMA 最高也不过 100MB/s)。相比与上述两种情况,它的传送速度明显慢。 从上面的三种情况可以看出,程序一定要尽量避免出现系统内存和显存之间的数据传送,那么 Media SDK 在什么配置下会出现此类尴尬状态呢? 初始化设置之优化小节中,程序通过 MFX_IMPL_AUTO 参数根据当前平台来自动选择硬件或软件编解码,并能通过 mfxStatus MFXQueryIMPL(mfxSession session, mfxIMPL *impl)函数来获取当前平台的编解码方式,在此将获取的编码方式分别讨论。 a)使用硬件编解码方式 硬件编解码方式主要是通过显卡的硬件加速达到高效编解码的作用,也就是说它的核心是显卡。如果我们使用系统内存为其提供缓存,会出现什么情况呢?显然,在数据输出/输出时,程序必将会有显存和系统内存之间的数据传送作用,效能将受到严重影响。在此情况下,程序的最好选择就是显存,否则必将受到性能惩罚! b)使用软件编解码方式 很显然,软件编解码的核心是 CPU。如果我们使用显存作为其缓冲,那么必将导致显存和系统内存之间的数据交互,也就会导致速度低下的程序出现,故此,系统内存是它的不二选择! 本节小结: Media SDK 中内存类型的选择分两步走: 1. 使用 MFXQueryIMPL 函数来查询当前的编解码方式。 2. 根据编解码方式(MFX_IMPL_SOFTWARE 为软件;MFX_IMPL_HARDWARE 为硬件)来决定内存选用类型。为了便于日后方便查询,笔者建立了一个小表格,如表 1 所示,以供参考。 此外,笔者对 Media SDK 的两种不同内存类型在解码器下做了一个简单的比较。在软件解码方式下,显存选取要比内存选取慢了近 1 倍,这个是相当可观的数字!切忌,正确选取内存是高效程序的基本点! 多线程之优化 初始化设置之优化小节和内存选择之优化小节中,已经对 Media SDK 的两个重要配置部分进行了分析和总结。本节,我们将着重讨论如何使用多线程技术提高视频 Converter 的效能(一种视频的常用应用)。 在运用 Media SDK 进行格式转换时,一般要涉及三大模块,他们是 Decoder,VPP 和 Encoder,数据输入输出如图 1 所示。 从图 1 可以看出,每经过一个模块,都要对数据进行同步操作。在此期间,其他两个模块是处于空闲状态,是一个典型的串行处理过程。对于英特尔的多核技术,它的多核利用率是最低的,相应的效率也较差。 那么如何对现有流程进行多线程化呢? 本节提供了一种最简单的方法,即对每个模块线程化。请参考图 2 所示。 图 2 将 Decoder,VPP 和 Encoder 三个模块分别线程化,在彼此之间以队列(queue)为数据交换。 简单的工作模式如下: - 若队列为空,后级模块等待数据。 -…

2016年10月7日 0comments 3050hotness 5likes Jeff Read all
Moments of Life

坑爹的主机商

买的主机停了将近10天,以前一些文章排名都没了。垃圾主机商,被攻击了,要快10天才能搞好,又不给取出数据,恒创主机,垃圾。

2016年9月30日 0comments 1332hotness 0likes Jeff Read all
音视频

一路走好,雷神

今天下班时打开QQ群,看到大家在讨论一个无法相信的消息:雷神离开了。看了新闻,实在不敢相信,天妒英才啊。当初踏入音视频这一行,ffmpeg学习,音视频基础,都是学习他的博客的(雷神博客:http://blog.csdn.net/leixiaohua1020)。后面也加了他的QQ群,在这个平台上学到了很多,很感谢他提供的这么一个平台,以及他无私奉献的精神。 感觉自己也要劳逸结合了,少加班,多锻炼,身体最重要。钱是赚不完的,但是身体确实可以透支完的。 一路走好,雷神!

2016年8月3日 0comments 1924hotness 1likes Jeff Read all
音视频

mp4文件elst研究

elst全称Edit List Box,mp4文件中不一定都含有这个box。该box作用是使某个track的时间戳产生偏移。 结构 在ISO_IEC_14496-12中,elst结构定义如下: segment_duration:表示该edit段的时长,以Movie Header Box(mvhd)中的timescale为单位。 media_time:表示该edit段的起始时间,以track中Media Header Box(mdhd)中的timescale为单位。如果值为-1,表示是空edit,一个track中最后一个edit不能为空。 media_rate:edit段的速率为0的话,edit段相当于一个"dwell",即画面停止。画面会在media_time点上停止segment_duration时间。否则这个值始终为1。 例子 现在我们手里有个mp4文件,我们要让封装的视频延迟10秒才开始显示,封装的音频不变,这个可以通过修改视频的时间戳实现,将视频的所有时间戳都加上10秒,但是一个个改太麻烦了,此时elst就派上用场了,我们要通过它让视频时间戳偏移10秒。 下面我们先动手操作番,了解elst如何起作用。 1)找一个没有elst box的mp4文件:test.mp4,假设我放在D:\\bin目录下。至于mp4有没有包含elst可以用文章末尾链接提供的mp4分析工具Mp4Reader分析下。用mediainfo查看该视频的信息: 该mp4音视频时长都为3分32秒。 2)得到带elst的mp4。到https://gpac.wp.mines-telecom.fr/mp4box/ 下载windows下的mp4box,按提示一步步安装。 打开windows cmd命令行,cd到test.mp4目录,然后敲入Mp4Box的命令: [crayon-69c4086f1e28a941542014/] 得到: 由此可知test.mp4中,视频的track id 为1,音频track id为2。 3)接着我们敲如下命令: [crayon-69c4086f1e290221322512/] 由于我们只对视频操作,视频track id是1,所以是#1:delay=10000。得到: 此时在bin目录下会生成一个delay_10s.mp4,该mp4中视频track延迟了10秒,音频track不变。mediainfo查看delay_10s.mp4信息: 可以看到视频的时长多了10秒 4)打开mp4reader查看视频track的elst信息: 也就是: [crayon-69c4086f1e291106728549/] 可以看到有两个elst entry,第一个为空,Segment-duration为6000,由于timescale为600(该timescale在mvhd中获 得),6000除以timescale刚好为10秒。由此可知我们要延迟播放某个track,可以在elst中插入一个空的entry,Segment-duration设置为需要延迟播放的时间,Media-Time设置为-1,然后在插入一个entry,Segment-duration设置为正常播放时间,Media-Time也就是起始时间设置为0。 5)播放器验证。我们使用vlc播放器打开delay_10s.mp4: 前10秒视频没有播放,而声音正常播放,到第10秒时视频才开始播放,等声音播放结束后,视频还会播放10秒,可以看出视频确实是推迟了10秒播放,此时音视频已经不同步了。 不是所有的播放器都支持elst的,我测试了下,vlc与potplayer支持,windows自带播放器就不支持。 ffmpeg相关代码分析 下面结合ffmpeg中相关代码以及上面的视频延迟10秒的例子分析,看ffmpeg中对elst数据如何处理。ffmpeg中elst entry数据存放在MOVElst 结构体中: [crayon-69c4086f1e292962158058/] duration对应mp4标准中的segment_duration time对应mp4标准中的media_time 在ffmpeg源码libavformat\mov.c中的mov_build_index函数中有如下代码: [crayon-69c4086f1e294029704487/] 第8行代码中可以知道,如果e->time == -1,也就是第一个elst为空,此时得到empty_duration,按前面的例 子该值为10*timescale,下一个for循环得到start_time =e->time,值为0。 在第26行代码中,可知sc->time_offset =0 -10*timescale = -10timescale,然后所有dts都要减去该sc->time_offse,最后结果是都加上10timescale,与原来时间戳比相当于延迟了10s。所以当mp4存在elst时,dts要按如下计算: 1.参考上述ffmpeg代码得到time_offset 2.解码时间戳dts = sample_delta * n – time_offset,其中sample_delta在stts中获得,如果存在B帧,还要从ctts中获得sample_offset,此时: 显示时间戳pts= dts+ sample_offset 否则pts = dts。 接下来我们使用ffmpeg验证下,打印出所有viedeo packet的dts与pts: 可以看到所有时间戳都偏移了230000,也就是10timescale,在video track的mdhd中可知timescale为23000,刚好是10timescale = 23000*10: 由此可知elst的作用就是使某个track时间戳偏移,达到延迟播放的效果。在我们解析mp4文件时,如果存在elst,一定要解析,然后配合stts与ctts,这样才可以得到正确的时间戳。 相关下载 Mp4Reader:https://pan.baidu.com/s/1cBC_yRR-BUfMGpUnC2LN8g

2016年6月16日 1comments 5312hotness 11likes Jeff Read all
1…89101112…25
Copyright Statement

Unauthorized reproduction or plagiarism in any form is strictly prohibited. For reprint requests, please contact via email.

Recent Comments
Pereplanirovka kvartir_cvsr Published at 7 hours ago(03 03202633105 25 25pm26) перепланировка услуги [url=https://pereplanirovka-...
Mirzoemele Published at 3 months ago(01 01202613104 06 06pm26) Double blind randomised controlled trial of two to...
PedarPhago Published at 8 months ago(08 08202583109 12 12pm25) Association between selective serotonin reuptake i...
EsielTooft Published at 8 months ago(07 07202573112 29 29am25) International scientific apply guidelines for the ...
dongxuh Published at 8 months ago(07 07202573103 27 27pm25) 真心不错的博客,有机会能一起分享

COPYRIGHT © 2026 jianchihu.net. ALL RIGHTS RESERVED.

Theme Kratos Made By Seaton Jiang