UEFI 里的 IGD Minimum Memory 和 IGD Aperture Size

今天进 UEFI 看到集显的两个设置选项:IGD Minimum Memory 和 IGD Aperture Size,想着 UMU 的 NUC 有 32G 内存,要不要改大点?然后搜一下他们的作用,结果发现最好不要改……

知识

  1. 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.

  2. 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.

参考

https://communities.intel.com/thread/106880

https://communities.intel.com/thread/106428

Windows 的 ChannelMask 转 ffmpeg 的 ChannelLayout

需求

Windows 平台,录音。

任务

用 Windows 的 IAudioCaptureClient 对象采集音频,然后用 ffmpeg 编码。

困难

一些类型定义不一样,比如 SampleFormat。

解决方案

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
inline AVSampleFormat GetSampleFormat(const WAVEFORMATEX *wave_format)
{
switch (wave_format->wFormatTag) {
case WAVE_FORMAT_PCM:
if (16 == wave_format->wBitsPerSample) {
return AV_SAMPLE_FMT_S16;
}
if (32 == wave_format->wBitsPerSample) {
return AV_SAMPLE_FMT_S32;
}
break;
case WAVE_FORMAT_IEEE_FLOAT:
return AV_SAMPLE_FMT_FLT;
case WAVE_FORMAT_ALAW:
case WAVE_FORMAT_MULAW:
return AV_SAMPLE_FMT_U8;
case WAVE_FORMAT_EXTENSIBLE:
{
const WAVEFORMATEXTENSIBLE *wfe = reinterpret_cast<const WAVEFORMATEXTENSIBLE *>(wave_format);
if (KSDATAFORMAT_SUBTYPE_IEEE_FLOAT == wfe->SubFormat) {
return AV_SAMPLE_FMT_FLT;
}
if (KSDATAFORMAT_SUBTYPE_PCM == wfe->SubFormat) {
if (16 == wave_format->wBitsPerSample) {
return AV_SAMPLE_FMT_S16;
}
if (32 == wave_format->wBitsPerSample) {
return AV_SAMPLE_FMT_S32;
}
}
break;
}
default:
break;
}
return AV_SAMPLE_FMT_NONE;
}

相关书籍

京东联盟购买链接:

FFmpeg从入门到精通 出版时间:2018-04-01 用纸:胶版纸

Opus 编解码遇到的怪事

前情

最近参考 ffmpeg 的 transcoding_aac 示例代码,写了一个 transcoding_opus,并拿 MP3 测试转码,结果发现转完的 opus 文件的 SampleFormat 和指定的并不一样。UMU 的代码是把源文件解码出来的 sample 先 resample 成 AV_SAMPLE_FMT_S16 格式,然后再交给 opus encoder 去编码的,但是编完用 ffprobe 查看,发现 SampleFormat 变成 AV_SAMPLE_FMT_FLTP。

那么第一个问题来了,为什么会这样?

分析

开始研究,首先 UMU 把 opus encoder 支持的 sample_fmt 打印出来,发现只有两种:AV_SAMPLE_FMT_S16、AV_SAMPLE_FMT_FLT,压根就没有 AV_SAMPLE_FMT_FLTP,强行指定 AV_SAMPLE_FMT_FLTP 之后,直接报错,不支持这种 sample_fmt。

推测,真的被编码为 AV_SAMPLE_FMT_S16 了,是 ffprobe 的问题,于是自己写了个简化版的 ffprobe,流程几乎是一样的,出来的结果——果然一模一样……打印出 AV_SAMPLE_FMT_FLTP。

接着怀疑 ffprobe 用的 decoder,于是去看了 avcodec_find_decoder 返回的 AVCodec,打印一下 name 和 long_name,和 transcoding_opus 的 avcodec_find_encoder 返回的一比,果然不一样……

选用的编码器是这样的:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
AVCodec ff_libopus_encoder = {
.name = "libopus",
.long_name = NULL_IF_CONFIG_SMALL("libopus Opus"),
.type = AVMEDIA_TYPE_AUDIO,
.id = AV_CODEC_ID_OPUS,
.priv_data_size = sizeof(LibopusEncContext),
.init = libopus_encode_init,
.encode2 = libopus_encode,
.close = libopus_encode_close,
.capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_SMALL_LAST_FRAME,
.sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_S16,
AV_SAMPLE_FMT_FLT,
AV_SAMPLE_FMT_NONE },
.supported_samplerates = libopus_sample_rates,
.priv_class = &libopus_class,
.defaults = libopus_defaults,
};

而选用的解码器是这样的:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
AVCodec ff_opus_encoder = {
.name = "opus",
.long_name = NULL_IF_CONFIG_SMALL("Opus"),
.type = AVMEDIA_TYPE_AUDIO,
.id = AV_CODEC_ID_OPUS,
.defaults = opusenc_defaults,
.priv_class = &opusenc_class,
.priv_data_size = sizeof(OpusEncContext),
.init = opus_encode_init,
.encode2 = opus_encode_frame,
.close = opus_encode_end,
.caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP,
.capabilities = AV_CODEC_CAP_EXPERIMENTAL | AV_CODEC_CAP_SMALL_LAST_FRAME | AV_CODEC_CAP_DELAY,
.supported_samplerates = (const int []){ 48000, 0 },
.channel_layouts = (const uint64_t []){ AV_CH_LAYOUT_MONO,
AV_CH_LAYOUT_STEREO, 0 },
.sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_FLTP,
AV_SAMPLE_FMT_NONE },
};

问题清楚了,看来用 ID 查找编解码器并不靠谱,因为这个 ID 是 Type ID,不是 Item ID,还是改为用 name 来找:

1
2
//AVCodec *output_codec = avcodec_find_encoder(AV_CODEC_ID_OPUS);
AVCodec *output_codec = avcodec_find_encoder_by_name("opus");

那么,第二个问题顺势而来——哪个比较牛?

结论

用 AV_SAMPLE_FMT_FLTP 后 frame_size 是 120,用其它是 960,frame_size 小有小的好处,比如在做实时编码直播时,理论延迟会更小。

经过测试,用 AV_SAMPLE_FMT_FLTP 的 opus 比 libopus 压缩率普遍略高一些,但它只支持 48000Hz 一种 sample_rate,libopus 支持的更多:48000, 24000, 16000, 12000, 8000。

相关书籍

京东联盟购买链接:

FFmpeg从入门到精通 出版时间:2018-04-01 用纸:胶版纸

诗盗·科技傲娇爹

《#诗盗#·科技傲娇爹》:股市两桶我四桶,阿里一桶爹三桶。前年科技蹭得累,今年集体来做空。

注解

股市两桶我四桶:股市两桶油,最近都是绿的,我门口放着四桶油……
一桶:一捅
三桶:伤痛
蹭得累:多傲娇

2017-03-21 09:42

《#诗盗#·熵增熵稣屎里掏花》:天增岁月房增值,物价如熵人作死。当年科技不买楼,如今只能搬三期。

2017-03-31 10:30

《#诗盗#·科技变化太快》:当初不买楼,如今望天愁。当初不卖出,如今爹成猪。

诗盗·213

《#诗盗#·213》:上街街上行人稀,下车车下雨水积。两脚牵拖做好湿,一觉穿越三生世!

注解

213 是车牌号,雨天开高速,开了 5 个多小时……
在“上街”停车休息,下车踩了水雷,做梦穿越。
牵拖:拖鞋。

完全免费的 Windows Server 系统,不需要序列号、不需要激活、更不需要破解

2009-04-17 22:06 在百度空间上发表过一次,后来百度空间倒闭了……最近给自己家里搭建家庭文件共享服务器用到,所以在这边再发一次。

2009 年时,由于项目需要,用过 Hyper-V Server 2008。到了 2012-09-25 升级为 Hyper-V Server 2012。这次(2017-03-22)用的是 Hyper-V Server 2016。这么多年一直还是完全免费的。

Hyper-V Server 是基于 Windows Server Server Core x64 的虚拟机服务器系统,要正常提供虚拟机服务, CPU 必须满足三个条件:x64、DEP (Data Execution Prevention)、HV (Hardware Virtualization),但 UMU 不需要它的专业本领——虚拟机服务,所以只需要有 x64 CPU 就可以了。目前只使用他的副业,作为网上邻居(SMB)服务器和静态文件 HTTP Server,就家用而言,绝对够用,前者是系统自带的共享功能,用 net share 命令开启,后者安装 node.js + http-server 模块。

但它不是完整的 Windows Server,比如您想跑 IIS,那就不能使用它了。它最适合的情况是您开发了一些系统服务(NT Service)类的应用,比如游戏服务端、聊天软件服务端,想发布到 Windows Server 上。

2023-12-04 补充

  1. Hyper-V Server 2019 是最后一个免费的 Hyper-V Server。

  2. 主流支持到 2024-01-09,扩展支持到 2029-01-09。

参考:https://learn.microsoft.com/en-us/lifecycle/products/hyperv-server-2019

跟 UMU 一起玩 OpenWRT(入门篇13):改进 autossh 支持多实例

需求

在之前的文章《跟 UMU 一起玩 OpenWRT(入门篇10):穿透内网》,介绍了 autossh 的使用,现在多个需求:想在内网打通多条隧道,即让 autossh 能运行多个 ssh 实例。

解决

  • 首先在 /etc/config/autossh 里增加一个 section,看起来如下:
1
2
3
4
5
6
7
8
9
10
11
config autossh
option gatetime '0'
option monitorport '0'
option poll '600'
option ssh '-i /etc/dropbear/id_rsa -N -T -R 2222:localhost:22 root@Server1'

config autossh
option gatetime '0'
option monitorport '0'
option poll '600'
option ssh '-i /etc/dropbear/id_rsa -N -T -R 2222:localhost:22 root@Server2'
  • 然后改进一下 /etc/init.d/autossh,让它支持多实例,给 start_instance() 函数增加两行:
1
2
export SERVICE_MATCH_NAME=1
export SERVICE_NAME="$section"
  • 最终 start_instance() 函数看起来是这样:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
start_instance() {
local section="$1"

config_get ssh "$section" 'ssh'
config_get gatetime "$section" 'gatetime'
config_get monitorport "$section" 'monitorport'
config_get poll "$section" 'poll'

export AUTOSSH_GATETIME="${gatetime:-30}"
export AUTOSSH_POLL="${poll:-600}"
export SERVICE_MATCH_NAME=1
export SERVICE_NAME="$section"
#export SERVICE_DEBUG=1
service_start /usr/sbin/autossh -M ${monitorport:-20000} -f ${ssh}
}

注意事项

这样改是有副作用的,您反复启动多次就知道了……启动的命令是:

1
/etc/init.d/autossh start

跟 UMU 一起玩 OpenWRT(入门篇12):SSH 端口转发(代理上 QQ)

需求

在之前的文章《跟 UMU 一起玩 OpenWRT(入门篇10):穿透内网》,介绍了从家里连到公司内网,现在需求反过来了,想在公司代理到家里,让公司的 QQ 使用家里的网络出口。

解决

还是那些熟悉的工具!首先,家里的路由器要刷好 OpenWRT,绑定一个动态域名,记为 HomeRouter。

2020/04/05 23:59 添加:

绑定动态域名的方法可以参考:https://github.com/UMU618/openwrt-ipv6-addresses

在 Windows 下用 putty 连到 HomeRouter,基本就大功告成!开 tunnels 方法如图:

PuTTY tunnels

或者用:

1
PLINK.EXE -N -D 1080 root@HomeRouter

最后是 QQ 的设置:

QQ Proxy

诗盗·非正常人类

《#诗盗#·非正常人类》:一觉好梦游仙,管它屋冷床寒!参编善恶演幻,听尽庸人说谗。

注解

写于软件非正常人类研究中心。改编自霹雳角色“人觉·非常君”和“禅剑一如寄昙说”的诗号。

一觉游仙好梦,任它竹冷松寒。
轩辕事,古今谈,风流河山。
沉醉负白首,舒怀成大观。
醒,亦在人间;梦,亦在人间。

看红尘冉冉,须臾无间,参遍昙华演换。
问法珠玄玄,方寸有变,听尽默剑说禅。