一个工程同时使用了 ffmpeg 和 live555,结果一不注意就混乱了……原因如下:
1 | // ffmpeg 的 error.h 里 include 了 errno.h,有以下定义: |
很明显,live555 这么做,违背了面向对象的基本特征——封装,这种平台相关的抽象应该封装在源文件里面,而不是放在头文件。挪个位置即可。
一个工程同时使用了 ffmpeg 和 live555,结果一不注意就混乱了……原因如下:
1 | // ffmpeg 的 error.h 里 include 了 errno.h,有以下定义: |
很明显,live555 这么做,违背了面向对象的基本特征——封装,这种平台相关的抽象应该封装在源文件里面,而不是放在头文件。挪个位置即可。
刚刷完 OpenWRT trunk 版本,默认不支持 PPTP passthrough,表现为此路由器内网的 PC 拨号时,认证很快成功,但迟迟不能完成,最终报错误码 619。
这是因为默认不支持 GRE 协议的 NAT。
官方就有解决方案,简单地说是运行一下两条:
1 | opkg update |
立刻生效。
《#诗盗#·天鸡 Book 测漏》:白首相知友难交,一心逍遥,两袖飘飘;十里春风稣不嫖,九零太老,零零太早!
改编自霹雳角色“天迹”的诗号。
仙衣眠云碧岚袍,一襟潇洒,两袖飘飘;
玉墨舒心春酝瓢,行也逍遥,坐也逍遥。
《#诗盗#·有朋自远方来》:写诗浑似画虎卵,不用古精与酒坛。今日相逢无限饮,老婆太多七次难。
画虎卵:闽南语,吹牛侃大山。
古精:古经的通假字,古典经书。
《#诗盗#·绿艹囧》:绿草横四空,网兔分六笼。骑虎三流灵,科技万花捅。
最近 KJ 四个绿色的 +,大花园的乖乖兔们终于迎来六个办公室~
用了三流灵就是骑虎难下,虽然人人喊打,然并卵。
在云游戏和云桌面项目中,总结了几类声音采集技术,把录音做到极致。
最典型的就是麦克风,内置麦克风、外置麦克风,其实还有一种通过 LineIn 插入的其它播放器设备,比如 CD、DVD 等。
采集这种音频的方法可以只用 ffmpeg 搞定:av_find_input_format(“dshow”)…,也可以用 CoreAudio 搞定:
1 | enumerator->EnumAudioEndpoints(eCapture, DEVICE_STATE_ACTIVE, ... |
采集方式是用 CoreAudio:
1 | enumerator->(eRender, DEVICE_STATE_ACTIVE, ... |
这种方式会混音,比如说您开个 foobar 播歌,再开个 QQ 影音看电影,则会录到这两个应用程序的混音,嗯,如果 QQ 再嘀嘀嘀,也是会混进去的……
有个叫 Virtual Audio Cable 的虚拟声卡,能虚拟多张声卡,并且可以把声音转发到对应的虚拟 LineIn 设备,供应用程序采集。
比前一种更先进一些,多个播放器同时播歌,我们可以只录其中一个。
采集方法是:Hook CoreAudio。
另一个思路是:Hook 到这个应用,给它单独指定一个输出设备,其它应用不能用,否则还是混音了,然后用前面的回放录音技术录制这个独占的输出设备。您可能要说,哪有那么多输出设备?这个问题可以用前面提到的虚拟声卡解决,分分秒虚拟出 64 个是没问题的。而且用 VAC 的好处是,可以在这 64 个对应的 LineIn 通道直接录制,不需要用 CoreAudio,兼容性会更好。
一般情况下操作 AVAudioFifo/AVFrame 都是用全套 ffmpeg API,内部自己管理内存,不需要了解它们内部怎么组织内存。比如:
1 | inline int InitFrame(AVFrame *&frame, int frame_size = kTargetSamplesPerFrame) |
这里读了一个 AVFrame 出来,并不需要知道具体的内存布局,但如果要写入 FileMapping 对象里,就得知道了! 参考以下函数:
1 | int av_audio_fifo_read(AVAudioFifo *af, void **data, int nb_samples) |
和 AVFrame 定义:
1 | typedef struct AVFrame { |
以 AV_SAMPLE_FMT_S16 为例,发现 InitFrame() 里的 av_frame_get_buffer() 之后只有 linesize[0] 是非 0,即 data[0] 的分配长度,其它 7 个都是 0,即 data[1] -> data[7] 都没有分配,于是猜测就是读 data[0],长度 linesize[0],尝试把它写到 FileMapping 里,果然是对的。如果 SampleFormat 是带 P 的,就不是只有 data[0] 了,有几个 channel 就有几个 data,要相应改变。
京东联盟购买链接:
FFmpeg从入门到精通 出版时间:2018-04-01 用纸:胶版纸
最近写录音程序,发现 MBP 的扬声器是 4 频道的,然后在抓音频保存时,Opus 编码器居然不支持 4 个频道,avcodec_open2() 会返回错误码 -22,Invalid argument。解决方法就是 resample 成 AV_CH_LAYOUT_STEREO。搞定后就顺便细研了这个 ChannelLayout,UMU 的代码里需要把微软 CoreAudio 的一些参数转成 ffmpeg 的,比如之前写的《Windows 的 WAVEFORMATEX 转 ffmpeg 的 AVSampleFormat 类型》,这次写 ChannelLayout 的转换。
ffmpeg 的 channel layouts 定义:
1 | /** |
ffmpeg 的频道位置信息:
1 |
微软的频道位置信息:
1 | // Speaker Positions for dwChannelMask in WAVEFORMATEXTENSIBLE: |
经过对比可以发现两者是一致的,只是微软的 dwChannelMask 是 DWORD,ffmpeg 用的是 int64_t。所以我们可以写个函数来转换他们:
1 | // 微软的 ChannelMask 值转为 ffmpeg 的 channel_layout |
京东联盟购买链接:
FFmpeg从入门到精通 出版时间:2018-04-01 用纸:胶版纸
今天进 UEFI 看到集显的两个设置选项:IGD Minimum Memory 和 IGD Aperture Size,想着 UMU 的 NUC 有 32G 内存,要不要改大点?然后搜一下他们的作用,结果发现最好不要改……
Adjusting the minimum memory can impact graphics performance in legacy operating systems (Windows 7/8/8/1).
The default value (64 MB) is recommended for Windows 10. Windows 10 will allocate graphics memory dynamically when it loads, so setting the IGD minimal memory to higher value may not improve performance.
Keep the default BIOS setting for IGD Aperture Size and IGD Min Memory. This values are used only during POST and to boot of the Windows.
Window 10 assigns automatically the maximum available graphics memory and it depends off how much RAM you have. Usually it assigns about half of available RAM.
Windows 平台,录音。
用 Windows 的 IAudioCaptureClient 对象采集音频,然后用 ffmpeg 编码。
一些类型定义不一样,比如 SampleFormat。
1 | inline AVSampleFormat GetSampleFormat(const WAVEFORMATEX *wave_format) |
京东联盟购买链接:
FFmpeg从入门到精通 出版时间:2018-04-01 用纸:胶版纸