PotPlayer无MadVR设置方案

又来折腾这玩意了。其实之前的方案完全正常啦,但是最近组了个新电脑没买显卡,本来以为反正自己也不玩游戏够用了,没想到居然用MadVR随便播个东西就GPU占用100%:

直接卡到12fps!把所有的缩放算法全部改成最低端的Cubic也只能勉强到50多fps(显示器是75的),看来是没得救了。那让我们找个替代品吧。

面临的问题

如果有读过前文和前前文就应该知道,之所以用MadVR并不是我对画质有什么极致的追求,而是在很多基础的东西譬如10bit抖8、格式转换等上PotPlayer是非常的差,MadVR恰好可以简单地修正这些问题罢了。

具体系统性的细节就不再赘述,如果需要可以复习前面两篇文章。这里直接说我们要解决哪些问题。

其实对于最常见的,4:2:0、limited range、8bit的视频,PotPlayer开箱的默认配置也不是完全不能用。但是有以下三个特例需要处理:

  1. 10bit视频——显示器是8bit的,所以10需要抖到8,无抖动大量banding。10bit视频现在已经非常常见了,动画民间压制组几乎全都是用HEVC 10bit出片。所以这个dithering是必须要有的,否则白瞎了。
  2. full range视频——商业发行的影音产品不算太常见,但是直播等非常常见。
  3. 非4:2:0视频(例如4:2:2、4:4:4视频)——更少见,除了某些民间压制组会用,其他基本见不到。

例如,Pot默认的用EVR (Custom Preset) (下面简称EVR)这个渲染器的最大问题就是不能正常显示full range视频。无论用软解硬解还是外置LAV都不行:

所以我们直接pass。

另外,一个thumb rule是所有转换都应该只做必要的转换,比如如果本来是422,那就不要劣化成420再转RGB;本来是8bit也别转10bit,反之亦然。

PotPlayer近年来的改进以及10bit输出

在最早那篇文章提过,PotPlayer当年最大的问题是他内部默认使用YUY2这个4:2:2的格式来处理,所以常见的8bit 4:2:0格式会被Pot拉伸一次,而且默认还是极差的NN算法。现在,Pot修复了这个问题,基本正常情况都会用NV12、YV12之类的格式通到渲染器。单这一点就把其播放一般普通视频的画质提升了一个量级,完全达到了能用的水平。所以如果没有特殊需求(下述),这两个之前提过的选项可以用Auto不用动了:

不过为了以防万一,还是把下面的高质量也给勾上吧。

另外,在输出方面增加了10bit的输出的选项:

开启10bit输出后会尽量在解码器端输出为10bit,然后到renderer会转成A2RBGB10之类的10bit RGB格式。但是因为我显示器只有8bit,最后还是会banding成8bit(且和P010这类10bit YCbCr格式直接转RGBA的banding还不太一样)。这里自然不开启。而且这个10bit输出还有一些bug:

  • 用EVR,会发生奇怪的颜色反转。蓝色变成黄色
  • 用D3D9 native 解码再输出到D3D9 renderer,会出现一个奇怪的绿条在下面:

最糟糕的问题其实是8bit的视频会被拉成10bit(然后最后在display层面再降回去)——据我观察D3D11 renderer即使这样折腾一次也问题不大,但是D3D9 renderer整个画面会变得超级糊,一定要避免。

处理10bit视频

这里先明确几个前提:我们只追求抖动的有无,质量不关键。另外我是8bit屏幕,所以一定要10转8;如果是用的原生10bit,则自行保证最后renderer是10bit输出即可。

这个转换,可以在编码器阶段进行,也可以在renderer阶段进行。之前用MadVR的时候就是在renderer阶段进行,所以一定要把解码后的视频保持10bit的格式(一般为P010)输送到renderer。

不过现在不用MadVR了,我们应该在哪里进行效果好呢?经过一些基本的测试,结论如下:

首先,如果在硬解native里进行10转8,是没有dithering的,效果很差。

如果用LAV调用硬解,我测试中是发现用DXVA2 native或者 D3D11都会banding,DXVA2 copy-back和软解则无问题:

测试时强制了LAV用RGB输出,这样保证不会在接下来的任何步骤再修改。LAV自己的10转8是有dithering的。我的理解是,用了DXVA2和D3D11 native的话,LAV就完全放手了让他们来输出为NV12之类的的格式,自己仅负责转换为RGB的样子。

240105更新:上面的DXVA的测试结果仅限于 Intel CPU 带的 iGPU;我使用N卡测试时,即使使用native也是自带dithering的!

如果用Pot内置解码测试,默认是用D3D9,只有用D3D11的renderer的时候才会用D3D11的解码,不过可以手动修改。也可以用D3D9 copy-back和D3D11 copy-back。搭配MadVR的时候,这里无论选哪个都是可以直出P010的,也是我之前一直用的。顺便一提,我在这台电脑上用D3D9 native + madVR播放full range视频,会出一个很奇妙的问题:

可以看到色域虽然没有错误伸张、压缩,但是16/235外的被clip掉了。然而我用我的笔记本无法复现。不过无伤大雅,改成copy-back或者D3D11即可。

回到正题。既然我们不能用MadVR,我们可以用默认的EVR、D3D9 renderer或者D3D11的renderer。使用硬解的时候,基本都会直出10bit的P010给renderer。但是凡是在上述三个renderer里发生P010转RGBA(即10转8),也都会banding。开启10bit输出虽然可以正常转成RGB10,但是最后在display层也会转到8bit所以也是同理。一言以蔽之,不要在非MadVR之外的renderer这一层来进行10转8,因为没有dithering。

所以,如果要用LAV内置解码器,就一定要用软解或者硬解copy-back(copy-back的硬解基本在实践上和软解区别不大,应该也是用了ffmpeg来处理)来输出NV12,然后renderer直接转RGB就完事儿了。Pot默认设置不开硬解其实就是这样的。注意一点就是如果你开启了direct conversion (change default output color space) 这个选项的话,可能又变回P010输出坏事儿。

另外一个小细节:不能选D3D11 native解码+D3D9渲染。会强制给你改成D3D9。反之则可以。

总结一下:

  • 硬解直接10转8输出:banding
  • 无论软解硬解如果输出10bit,渲染器里10转8:banding
  • 所以要用:软件解码器或者硬解copy-back来完成10转8的过程。

软解的选择可以用Pot内置(即FFmpeg)、LAV(可以手选dithering的方式)。记住,Pot默认强制HEVC用硬解,即使不勾“Use DXVA”也是。可以通过修改这里为FFmpeg.dll来强行取消:

FFmpeg根据我的观察应该是用的ordered dithering。

这里来比较一下。先来一张banding的(所有的截图都是1080p片源1440p播放,然后截图后调整曲线来增加对比度,最后再NN放大到3x):

再比较一下dithering:

可以很明显看到两种dithering的区别。观感上来说其实都差不多,不过还是用random吧。中间的则是对比用的MadVR——MadVR dithering最好的地方在于他工作在全分辨率(也就是1440p),所以pattern极其小,可以说100%时肉眼完全看不出任何颗粒感。别的都是先生成dithering、然后再被放大,那自然效果远不如。不过,看片的时候还是OK的。

至于渲染器的选择在这里不影响,我们都是8bit输出了反正。

视频resize的表现

确定了10bit没问题,我们再回来看看经典8bit视频resize的效果。这里有点出乎我的意料:无论是用D3D默认的DXVA Video Processor,还是D3D11带的D3D11 Video Processor(Pot里选成Auto就好),效果都出奇的好,可以和说我MadVR拉满不相上下!

我的理论是,他这个不知道用了什么Intel的劳什子视频后处理科技,估计是在全屏分辨率级别搞了点锐化之类的?无论如何,至少看高锐度的东西效果很好,清晰,也没有太明显的ringing,远强于Cubic之类的了。我们尽量选用能调用Video Processor来resize的方案。顺便一提,EVR默认也是调用DXVA Video Processor来当resizer。

Full range、422/444视频

Full range视频不出意外地都没有问题,甚至EVR (Vista/.NET3)那个都没问题——只要别用EVR custom preset那个。

422/444视频则比较tricky。理想情况,当然是422就全程用YUY2,444就全程AYUV,不要出现被转化为420格式再喂给渲染器的现象,自降分辨率是大忌。

但是现实很骨感,这里面有好几个局限性:

  • Renderer只能接受部分格式输入
  • 某些格式用LAV+开启Pot转换滤镜时,Pot不收(虽然用内置的可以)
  • Pot的自动格式选择非常的弱

让我们先来个一览表:

这里面绿色是我们想要的,黄色的是非最佳的,红色的是无法接受的。这里面第三列就是前面提过那个开关:所谓的“direct conversion (auto change color space)”是开还是关。

简单概括下:如上面说的第三点,Pot如果把输出设为Auto,其实基本就是只会用NV12/YV12这种8bit/420的格式。唯一的例外是用硬解native的时候,会直通P010(10bit 420)到renderer(但是我们已经说过我们不想这样,因为非MadVR的renderer没有dithering)。所以,这样下来面对422/444的视频,都会被Pot给降低到420,bad。

这个问题可以通过这个开关来改善——开了之后,对于EVR,解码器会自动改用422和444的输出,对于D3D9,至少能修复422(但是444会crash)。D3D11则比较怪,即使开了开关,还是只能被喂420(或者RGB);我稍微查了下应该是支持至少422才对,可能是Pot的implementation有问题吧。

但是这个开关也有个副作用,就是用内置解码器的时候,会把10bit本来我们想要的8bit输出(抖动后)也给变成了10bit直通。

如果是用LAV,就很容易解决这个问题,LAV里把10bit的格式全部去掉,自然就只可能输出抖动后的8bit。

(这里有个疑似BUG:Pot的转换滤镜开启时,它并不收来自LAV的P010,如果你强制在LAV那边只勾选P010,Pot会直接强制自行关闭转换滤镜……嘛,纯粹是好奇罢了,毕竟我们的目的恰恰是LAV不要用10bit输出。)

另外,使用“LAV+EVR (Custom Present)+开启auto coloir space开关”这个组合时,除了会有前面多次提过的full range色域错误的问题(未伸张,即0变成16),另外播放444视频时,会出现色域过度伸张的错误(即16变成0)。

但是如果把渲染器换成EVR (Vista/.net3),看表格里似乎完美?

很可惜,EVR (Vista/.NET3)有个更阴间的BUG……字母某些特效会变成这鸟样(请无视我没安装字体。下面是对比用的EVR (CP)):

结语

既然没有一个完美方案,我们只能两害取其轻了。我最后采用的是内置软件解码器+D3D11渲染器+不开auto色域转换开关的方案(换成D3D9渲染器也行)。这样只有422、444不能完美播放(但是也不至于不能播放),而我除了我自己造的测试视频其实根本没下过这种视频w。我还检查了下BT601的视频,也是没问题的。

哦,其实还有个方案就是上面提过的LAV+强制RGB输出的方案。可以一揽子规避所有转换的坑。但是,这样就没法享受到高质量的DXVA/D3D11 Video Processor做resizer,所以还是算了。

20230520补记

最近碰到一个视频是 SMPTE 240M 的matrix,发现用D3D9的 renderer 有问题,D3D11的OK(和MPV的效果一致),所以虽然都行还是推荐用D3D11。

另外,我发现我上面明明还有一个全绿的组合:使用LAV+D3D9渲染器+开启auto coloir space开关,但是我为啥没使用?我自己也忘了,大概还是为了尽量不用外部滤镜来让截图不偏差吧。

个人用视频播放器最新设置方案

本文是前文,外挂LAV+开启PotPlayer转换滤镜时的最佳设置方案的追记或者说更新。

本文大纲:

  1. 重新总结下视频播放中Pot无法胜任的部分和原因;
  2. 我现在如何设置PotPlayer来workaround这些问题;
  3. 我的备胎播放器;
  4. 为什么如此忍辱负重也无法抛弃PotPlayer。

视频播放的几个转换

视频播放,宏观上通常需要经历这么几个的转换步骤到输出(不按顺序,也不一定都有):

  1. 解码
  2. 色度抽样还原 (420或者422->444)
  3. 缩放
  4. YUV->RGB
  5. 降位深(10bit -> 8bit)
  6. 反交错

解码没什么好说的,其他大部分逐条说一下。

色度抽样还原

色度抽样还原 (420->444) 就是把被缩放到(面积)1/4大小(420)或者一半大小(422)的U、V channel放大到原始尺寸,和缩放本质没有区别。无非就是点对点播放时,Y通道不需要缩放而色度通道依然需要而已。

这个工作LAV、Pot和渲染器都能做,做的最好的是MadVR这个大家都知道了,LAV可以接受,Pot如果如上文所说,如果使用了转换滤镜(下边凡是提到Pot,都是指如果使用了Pot的转换滤镜)会默认强制将420的转换一次422且使用最差的硬差值算法,勾选“高质量转换”可以改善但仍然一般——推荐不在Pot进行。

缩放

都能做,MadVR最佳。

YUV->RGB

都能做。这个的质量问题我不是很敏感,但是Pot有诸多BUG。不推荐在Pot进行YUV和RGB的转换(一般也不会)。

降位深(10bit->8bit)

都能做,但是如果被Pot降位深会完全无任何dithering,效果完全不能忍,巨大banding,故实际上必须要在LAV或者MadVR进行。

反交错

都能做,但是LAV和MadVR的算法好一些。Pot有一堆选项,但是却没有感觉特别好用的。我个人对于反交错的要求其实不多,就一条:真·交错内容一定要还原成原始拍摄帧率(60 / 59.94 fps),否则流畅度不能忍。这点MadVR和LAV的3种算法都能做到,如果用Pot,要选2x frame的,我现在选用的是“motion adpative (2x frame)”这个。

另外对于IVTC的内容,即时反交错的效果都差强人意,但是Pot的更差些。

具体设置方案

那么有了上面那些预备知识,我们可以来对比下几种设置方案。当然,我们只考虑高画质的方案。

LAV->Pot(禁用转换滤镜)->MadVR

分工:

  • LAV:解码
  • Pot:什么也不做
  • MadVR:色度抽样还原、缩放、YUV->RGB、降位深、反交错

设置方法:

  • Pot里转换滤镜disabled
  • LAV全默认设置

另外,可以通过修改LAV的输出或者反交错选项来把部分工作移动到LAV中(比如如果你比较喜欢LAV的反交错滤镜),但是整体区别不大。

优点:最高画质设置,完全不会被Pot劣化。

缺点:导致Pot非常容易崩溃——尤其是播放TS文件的时候(原因不明),这也是为什么会纠结这一切的原因。

LAV->Pot(开启转换滤镜)-> MadVR

分工:

  • LAV:解码、降位深、反交错
  • Pot:什么也不做
  • MadVR:色度抽样还原、缩放、YUV->RGB

也就是前文提到过的方案。首先,我们知道一旦开启了转换滤镜,由于Pot内部处理精度只有8bit且没有dithering,所以降位深必须在Lav做好。事实上,由于Pot的转换滤镜根本不接受10bit的输入,Lav那边会自动diether成NV12再输入Pot,所以无需专门设置。

至于反交错,Pot有个弱智问题就是一旦进入了他的转换滤镜,无论你的反交错是enabled还是disabled,后面都会强制输出deinterlacing=off的flag,导致无法在MadVR中进行。所以必须在Lav或者Pot自身里完成反交错才行。这两个选的话,当然是Lav的好些。

设置方法:

Lav:选一个反交错滤镜开启,其他默认。

Pot里:

  • 开启转换滤镜
  • Video->colorspaces中,选择NV12或者其他4:2:0的色彩空间
    • 目的:防止Pot自做多情的420 to 422转换
  • “Direct conversion”选择“Enable: change default output color space”
    • 目的:直通YUV422/444/RGB内容到MadVR
  • 反交错:disabled

优点:由于大部分MadVR的优势部分依然是在MadVR进行,所以基本可以维持最高画质。非YUV420的内容会直传MadVR所以不会被Pot劣化。

缺点:依·然·会·崩·溃。

Pot(解码+转换滤镜)->MadVR

分工:

  • Pot:解码、反交错
  • MadVR:降位深、色度抽样还原、缩放、YUV->RGB

在上面那个方法依然会导致Pot不时崩溃的情况下,我开始思考:能否完全绕过Lav,直接用Pot内置解码?对于我来说,解码器的质量并不是关键的,因为解码本身是个deterministic的过程(而且Pot其实就是用的ffmpeg,质量不会有大问题)。但是通过使用Pot自带的内部工作流程,应该会明显改善崩溃问题。

我的第一直觉是这个流程对10bit会不行——从上文可知,Pot的转换滤镜甚至不接受(LAV的)P010的输入,怕不是直接就给我砍成8bit了?结果不试不知道:在开启“Direct conversion”的前提下,Pot用内置解码器居然反而可以直通P010到MadVR!

blog01

那么赶紧来试一下其他几种色彩空间:

YUV422:YUY2直通MadVR; YUV444:AYUV直通MadVR。

很完美!当然,对于YUV420的视频,Pot那个自作多情的伸张成422的问题依然存在,所以手动设置色彩空间为NV12依然是必要的。

设置方法:

Pot里:

  • 开启转换滤镜
  • Video->colorspaces中,选择NV12或者其他4:2:0的色彩空间
    • 目的:防止Pot自做多情的420 to 422转换
  • “Direct conversion”选择“Enable: change default output color space”
    • 目的:直通YUV422/444/RGB内容到MadVR
  • 反交错:enabled,选一个喜欢的。个人用motion adpative (2x frame)

优点:终于不会崩溃了!另外,除了反交错由于Pot的限制必须在Pot进行无法达到最高质量以外,其他的转换都正常在MadVR进行,接近完美。

缺点:反交错效果略微差点。

另外,稍显遗憾的是,无论是上面哪种方案,之前提到的截图问题都存在。我以为改用内部解码器就能解决这个问题呢,看来似乎只要用MadVR就会这样?

音频解码

音频解码可以继续用LAV,或者也换回Pot自带,我感觉区别不大。因为这个并没有太多可以搞糟的部分嘛。

唯一一个需要注意的是5.1->2.0转换。LAV默认的设置是这样的:

QQ图片20190713212105

也就是说,Center和Surround都会降低到71%、LFE直接完全关闭之后再mix到Front——据LAV的作者在Doom9说,这是标准里写的。那么我们把Pot也改成一致的呗:

QQ截图20190713212326

这里我改了几个地方:

  1. mixer level改成了和LAV默认一致。
  2. 关闭了Expand stereo to center 和expend stereo to surround。这两个选项其实是把2.0映射到5.1才有必要的,但是Pot的实现很怪,是先把2.0用这个映射到5.1,再用下面的mix level mix回2.0。如果下面全是100的情况下自然是完全一样,但是我们都改成非100了,还保持这两个勾中会导致音量变低,所以去掉。

这么改完听5.1音轨,发现LAV的声音还是会小一点(mix倒是听上去完全一样了),研究了下发现是LAV里那个”prevent clipping”选项导致的(自动降低了音量防止削波也就是爆音),我音量因为一般都不拉满所以其实无所谓,可以自行调整。

嘛,这个改不改其实区别不大了,因为一般有5.1音轨的视频大多会有官方混音好的2.0,2.0的设备就应该听那个才对。

备胎播放器:mpv->SMPlayer

在Pot频繁崩溃我却不知所措(笑)的期间,我使用mpv当做备胎播放器,尤其是用来播放ts文件。

mpv是个非常优秀的跨平台开源一体化播放器,渲染质量很高功能也很全。尤其是不依赖太多外部程序(比如LAV、MadVR)这点非常好。而且mpv那种seek时丝般顺滑、毫无delay的感觉和极速的启动速度实在太美。可以一键开启手动反交错(默认是D)这点我也很喜欢。

但是作为一个命令行为主的工具,其用户体验并不是特别好。本人并不排斥CLI工具或者手动修改config文件,但是如果需要经常或者大量调整这些东西,还是非常难受的(尤其是大多时候还得去翻doc,而不是有intuitive的选项可以直接找到想要的设置)。另外,自带的那个简陋的UI也有诸多不便。

于是我去找了下mpv的套壳播放器。很快,我就找到这款叫SMPlayer的软件。虽然UI比MPC-HC还要丑几个档次,但是至少完美保留了mpv的优点,定制快捷键很方便(我基本全改成和Pot一样了w),有基础的选择音轨、章节功能,作为主要拿来看ts的备胎,我也不能要求太高了。

为什么Pot不可替代

个人对Pot的依赖,有部分是来自于迁移成本太高(我建立了大量播放列表),但是主要还是UX体验太好。

就拿一点来说,事实上也是我每次用其他播放器都感觉极其不便的一点:章节选择。Pot可以:

  • 在进度条显示章节marker
  • 且悬浮会有章节名称的Tooltip;
  • 一键(H)开启章节列表选单,然后在列表中自由选择想要的章节;
  • 可以用快捷键(默认是Shift+PageDn)来快速跳转下一章节。

上面的这些功能,不少播放器都有某种程度的支持(比如mpv的进度条有章节marker,大部分播放器的menu里都有章节选择),但是能完美做到上面所有的?并没有。

尤其是一键开启这里——我之前多次提过,快捷键是否“快捷”和是否有快捷键一样重要。比如你想在SMPlayer里选章节?倒是可以,先点browse,再点chapter,然后选,这至少需要3-5秒,中间还要不断移动鼠标光标到很小的目标上。这个方便程度和直接按H是天上地下的。同理,在Pot里按A选音轨、L选字幕、都是极其经常需要用到的,单键快捷键比起组合键或者菜单的优势非常明显。

而且万一视频没有章节,想自己添加?小case:按下P即可添加bookmark。而且这个bookmark在以后使用上,和章节完全没有区别:你依然可以按H查看、按Shift+PgDn来跳转、在进度条上看到marker。另外,通过设置选项之后,bookmark完全可以做成外挂的,这样即使视频文件移动了也能保持所有的bookmark。(参见前文的相关内容)。

注意,bookmark这个功能不是Pot独有的,我能想到不少播放器都有这种功能。但是能做到如此方便、让人去愿意去用,才是其独到之处。

同理,我们来比较下“跳转功能”。在Pot里,按下G会出现跳转框:

QQ图片20190713205207

同样地,在SMPlayer可以用ctrl+J出现跳转窗口:

QQ图片20190713205308

看出两者的区别了吗?姑且不论Pot多了个按帧跳转的功能,但就按时间跳转,Pot就多了:

  1. 精确到毫秒
  2. 直接默认选中全部时间,所以配合ctrl+V等于多了个快速的选中当前时间的功能。

当然公平起见,我们也举个比较接近的例子,MPC-BE的(ctrl+G):

004

基本和Pot很接近了,但是还缺少一个自动hightlight时间的功能,所以不能直接ctrl+V选择当前时间,得先ctrl+A一下。

再来说说缩放:调整视频canvas大小是个很常见的操作,在Pot里你可以:

  • 按123选视频原始大小的50%、100%、150%大小;
  • 按atrl+1/2/3/4按当前桌面百分比大小来缩放;
  • 全屏时依然可以按上述快捷键,来直接窗口化并缩放到对应大小,而不用先退出全屏;
  • 拖拽改变大小时,窗口frame保持比例,不会出现黑边;
  • 在同一个窗口打开新视频时保持窗口大小(可设置)。

等等等等。上面后四条都是非常好用的功能。

播放列表方面我别的播放器的用的不多所以也没有对比不太好吹,至少可以做到只选取视频的部分加入播放列表:

QQ图片20190713211402

Pot不是一个完美的播放器,但是就是这种UX上的attention to detail,让人爱不释手。

结语的一些碎碎念

我发现x264好像根本不支持RGB空间。我刚测试才发现,之前自己用ffmpeg做的“RGB24测试视频”实际是YUV444的…

PotPlayer的崩溃问题我感觉和他的I/O buffer有关。因为我发现在我的5400rpm硬盘上开启bitrate特别大的文件(比如ts)时或者拖拽进度条时最容易崩溃。

最近遇到的几个视频相关的问题(二)

本来想直接在前文里追记,但是正好有点别的东西一并写了。

Progressive的DVD

上文中说到“发现近年的DVD大多都是progressive的了”,其实相当不准确。感谢boday的指点,其实准确地说:近年的DVD依然大多是交错的,但是确实存在一种,(例如TrySail的好几张碟都这样)实质是Progressive的DVD,元数据长这样:

Width : 720 pixels
Height : 480 pixels
Display aspect ratio : 16:9
Frame rate : 23.976 (24000/1001) FPS
Color space : YUV
Chroma subsampling : 4:2:0
Bit depth : 8 bits
Scan type : Progressive
Scan order : 2:3 Pulldown

这种应该叫做“软Telecine”,可以看到帧率是23.976p而不是30,其原理就是完全按照Progressive来存储,但是加了个2:3 Pulldown的metatag,所以DVD player播放的时候会即时进行telecine来pull到30i。当然,对于电脑播放的情况,解码器会直接按照24p播放,也不需要进行IVTC。

看不出交错的隔行视频

前文提到有些HDTV明明是隔行却看不出任何交错现象。这个问题后来想想简直太弱智了:因为人家就是用逐行拍摄、然后把每一帧拆成两场罢了,由于根本就是同时曝光的两场,所以weave回去自然不会有交错条纹……

MKV的音频Delay“问题”

后来问了作者了,作者到也很直接:“我没什么好说的,有很多原因可能导致这个,比如sequence不是从视频关键帧开始等等”。总之我理解就是他是说这个delay区别并不是什么bug,而是有技术原因在背后罢了。

上面算是补记,下面是一点点新东西。

PotPlayer使用外挂滤镜的截图问题

Pot使用外挂解码器(Lav)之后,截图功能就变得稳定性极差。估计多出自Pot截图的时间点和渲染的步骤不同步/不一致造成。最基本的错帧问题大家都知道了,就不提了,提几个别的。

其中最滑稽的问题是,如果开启了Pot的转换滤镜,会出现播放中截图暂停后截图结果不一样的现象。其不一样之处主要是缩放质量,缩小播放尺寸+用实画面截图(ctrl+alt+C)就可以发觉。

001
Lav+Pot转换滤镜实画面截图对比:先暂停 vs 播放时直接截图

顺便一提,如果不开启Pot的转换滤镜,倒是没有暂停和不暂停的区别了,但是截图出来的依然和你实际MadVR渲染出的高质量缩放是不一样的,在缩放倍数较大的时候很明显。当然,这个倒也是意料之中了。

002
实画面截图 vs 手动prtScn(200% NN放大)

说回开启了Pot转换滤镜会出现播放中截图和暂停后截图的结果不一样的现象,其实有另外一个更奇葩的:播放时截图Pot的yuv->rgb的转换矩阵和暂停截图不一致。这个现象经常在没有很鲜艳的颜色时不是很明显,所以容易被坑。

具体说来,在“暂停后截图”时,Pot会和正常编码器/渲染器一样(?),自行根据视频metatag或者尺寸选择正确的转换。然而,在“播放中截图”时,Pot会套用这个设置:

003

这里的坑爹之处在于,和前文提到过的让Pot处理YUV->RGB的BUG一样,这里设成Auto也会永远用BT.601,即使视频是HD、且有显式Tag的。由于HD视频更为常见,所以我手动改成了BT.709,但是自然这样会导致SD视频又有问题。所以,如果真的要用Pot截图,还是老老实实暂停了再截吧。

MadVR缩放算法

另外没事儿干对比了下MadVR的缩放算法。简单来说就是chroma upscaling用NGU比Lanczos在某些大色块高锐度(比如我一直用的测试视频)还是勉强有肉眼可见的区别,虽然实际放片还是区别很小。我暂时改用NGU+low quality了,能把GPU的load压在20%左右,还算能接受。由于上述各种笔油鸡,下面截图用的PrtScn。

004

Downscaling/upscaling那边,我比较了几个没看出大区别,NGU太耗资源不考虑,我相对喜欢锐度高一点的,所以继续用Lanczos+anti-ring filter。

(顺便吐槽自己干的一个蠢事:用50%大小播片,然后好奇为啥NGU完全不耗资源……)

外挂LAV+开启PotPlayer转换滤镜时的最佳设置方案

注:本文的更新版在这里


 

自从前一段发现PotPlayer播放10bit视频惨到不行的banding问题之后(目测是直接把10bit砍到8bit,没有使用正确的抖动,甚至连设置的地方都没有!),就换用了LAVfilters来作为主力滤镜。既然都换了LAV,顺便也把EVR换成了MVR——因为我发现我之前一直无法忍受MVR的一点,全屏和窗口化切换会卡一下的问题现在没有了(即使是非exclusive模式)——不过这是后话。

但是,PotPlayer调用外部滤镜的兼容性实在是惨不忍睹,其实这也是我之前为啥一直坚持使用内置滤镜的原因。短短用了这半个月,遇到过的问题就包括但不限于某些视频直接无法播放freeze、拖动进度条卡顿、PotPlayer.dll报错崩掉等等。无奈之下,我尝试了下升级到最新dev版,结果发现更可怕了,比如之前我发现banding的那个[LoliHouse] A.I.C.O.用LAV直接无法播放(稳定版没问题,已经报错到论坛了)。

PotPlayer的转换滤镜

我后来发现,在依然使用LAV的前提下,如果开启PotPlayer的所谓“转换”(transform)滤镜,则可以大幅度缓解不兼容的各种问题。上述的那个视频可以正常播放了没问题,崩溃的次数也大幅减少。另外,这个滤镜是PotPlayer用来实现PotPlayer内置的一些功能的,所以只有开启之后一些功能(比如视频调色,虽然我从来不用就是了)才能正常工作,而且不开启的情况下还会有截图错帧的问题。

当然,这个功能之所以之前我选择不开启,是因为它是有不少副作用的。其最大的问题就是在不同Pixel format之间转换会有很大的精度和算法问题。Pixel format就是形如NV12、YUY2、RGB24等等各类色彩的数据存储格式——包括但不限于colorspace、位深、通道数、通道混合方式等。对于YUV色彩空间的几种常见的格式VLC的wiki有篇详尽的文章可以参考,这里不再赘述。

要谈论transform的对pixel format转换的影响,得先说说如果不用它,直接LAV输出到渲染器是怎样的一个流程。例如最常见的YUV 4:2:0(YUV色彩空间,纵向横向均有2:1的色度抽样)的8 bit视频(注意:俗称的8 bit、10 bit指的是单通道。实际上,对于YUV 4:2:0,每个pixel平摊下来有一个Y通道像素+1/4个U通道像素和1/4个V通道像素,所以一共有8+2+2=12bit)在LAV勾选默认所有输出方式(除了AYUV)的情况下,会用NV12输出给渲染器。这里罗列一下常见的几种格式都会是怎样:

原始格式 LAV输出格式
YUV 4:2:0 8 bit NV12
YUV 4:4:4 8 bit YV24
YUV 4:2:0 10 bit P010

可以看到,LAV自动选用的位深和色度抽样都是和原来一样的,不会进行多余的操作。

顺便一提,如果细心看,会发现LAV会输出2048×1080,而不是1920,这是因为使用了叫做Image stride的技巧,把图像尺寸填充到2的整数幂来加快GPU运算。LAV作者的原帖见此

本文中使用的测试视频由作者使用静态图片使用ffmpeg生成。其中的一些细节请参见此文

YUV 4:2:0 8 bit视频

现在来看看如果开启PotPlayer的转换滤镜,会发生什么。还是先看看最常见的YUV 4:2:0 8 bit格式:

QQ图片20180325012835

从OCD信息可以看出,LAV依然输出的是NV12(这里写“Input”,因为是相对Pot的转换滤镜而言),不过经过了转换滤镜之后就变成了YUY2这个4:2:2(水平有色度抽样,纵向没有)的格式——也就是说Pot自作多情地把U、V通道给upscale了一倍。很显然,我们是希望所有的upscaling工作全部在MadVR进行,因为其拥有最优秀的算法;Pot的算法?已经不能用“一般”来形容了——事实上可以看出,他根本就是用的nearest neighbor(截图均为200%缩放,下同):

yuy2
Pot转换滤镜,默认(YUY2)输出

disabled
转换滤镜禁用,LAV直出MVR

这个结果显然是无法接受的,那么怎么能拯救一下呢?PotPlayer相关的选项有这些:

QQ图片20180325013808

这里我们主要可以调整的是三个:一个是输出格式(Output color space),一个是所谓的“直接转换”(Direct conversion),一个是下面那个高质量(High quality YUY2/RGB24/32 conversion)选项。

首先想到的自然是勾选那个high quality选项了。勾选之后,PotPlayer会用比NN高级那么一点的算法,结果如下:

yuy2hq
Pot转换滤镜,默认(YUY2)输出+HQ

比上面那个锯齿到爆的自然是好多了,但是理想情况下我们还是希望能让MVR来处理,所以我们还可以选成强制NV12输出(注意,非YUY2输出的话那个HQ选项勾选与否没有任何区别):

nv12
Pot转换滤镜,NV12输出

这里可能几乎看不出区别,不过如果放再大点可以看出这个会比上面那个稍微锐化那么一点。另外很奇怪的是,即使是选成NV12输出,结果也和直接禁用转换滤镜(LAV用NV12直传MVR)不是逐像素相等,我初步怀疑是截图的帧数不同(虽然这是我拿静止图片做的视频,但是毕竟是有损压缩每一帧还是略有区别的)导致的,也有可能Pot的转换滤镜还干了其他什么,但是无论如何,这个区别是肉眼完全没有可能区分的了。

哦其实还有个直接转换的选项——有啥用呢?具体原理不明,不知道所谓的“直接”是指什么,但是选了之后YUY2(默认)会变成“Direct YUY2”,NV12会变成“Direct NV12”,其中前者结果和默认+HQ一样,后者和NV12一样,所以感觉意义不大。

你当然也可以选成那些4:4:4的格式来输出(而且不用勾选HQ选项,自动会使用比NN强的算法),来获得能接受的结果,但是这样完全是把MadVRupscaling的工作给做了,自然不是我们想要的。

值得一提的是RGB输出的选项……首先RGB24+HQ选项=直接崩溃,是很彻底那种,连用Pot内置滤镜解码都崩(啥时候抽空汇报一下)。RGB32+HQ倒是不会崩溃,但是这下不但U/V的upscaling、连YUV->RGB都在Pot做了,不是很让人放心。不过也算有个优点:PotPlayer至少可以手动改Color matrix,放到MadVR或者LAV里做的话全靠自动判断了,如果有什么文件的元数据不对,没办法纠正。

题外话,RGB32比起24是多了8位的Alpha通道这点没错,但是绝大部分情况,alpha通道是根本不会使用的。那为啥会用32?其实是因为可以在x86(32位机)下做到下完全对齐,这会显著影响到内存和运算单元的速度。参见[1][2]

另外,在测试过程中我发现PotPlayer一个BUG:LAV输入NV12+转换滤镜+RGB输出(RGB24/32+MVR或RGB32+EVR)+Auto color matrix的情况下,永远使用Rec. 601。不但不会自动识别HD视频,连有显式Ret. 709的tag都不行。所以Pot转换滤镜RGB输出这条心还是死了吧。

YUV 4:2:0 10 bit视频

一般的8 bit视频还是比较容易找到一个靠谱的方案,我们再来看看10 bit。和8 bit相比,主要的问题在于,Pot这个transform滤镜能接受的输入很少[主要包括:NV12/YV12、YUY2/UYVY、RGB32,基本和EVR能接受的输入差不多。不支持任何10 bit及其以上或者4:4:4的YUV的格式]。前面提到LAV一般是直出P010给MadVR,而transform滤镜恰恰不接受这个输入。所以,默认情况下,LAV会选择抖动降低8bit然后NV12输出给转换滤镜。

这之后的流程自然和上面就一样了,Pot这边也选择NV12输出的话,无非就是把10->8转换的步骤从MAR变到了LAV,两者的dither质量都OK(虽然MVR的选项更多)。

YUV 4:4:4视频

其实这个没什么测试的意义,因为你99%根本不会见到这类视频,纯粹是为了蛋疼。而且这个的毛病可就太多了:首先,PotPlayer也不接受YV24输入,所以LAV会直接转换好RGB32送过来。接下来怎么办?显然不能再用NV12或者默认的YUY2了,我们本来明明没有任何色度抽样的,不能自降质量。最简单的就是这边也设成RGB32输出——由于无色度抽样完全不牵扯到resizing,所以这样的结果和LAV YV24直出MVR完全没有区别,锐度满分。不过兼容性还是有点,经常视频如果不重头开始播放就会出现这种屌炸天的现象:

QQ图片20180325034639.png

如果你手贱一定要用NV12输出,也就是让转换滤镜从RGB32转换成NV12,那么除了显而易见的视频会变模糊以外(你自己引入了色度抽样),PotPlayer还会莫名地引入color range压缩的问题(最后出来的视频是16-235的)。而且我LAV那边无论是设成输出full还是limited的RGB都不行,PotPlayer一定会搞糟。结合MVR的OSD,我们来猜测下发生了什么:

如果LAV输出full的RGB:

Pot将full的RGB转换成limited的YUV,但是不修改stream的信息,所以MVR会认为还是full,不伸张,导致最后输出limited RGB;

如果LAV输出limited的RGB:

Pot根本不知道还有Limited的RGB一说,当成full来用又再压缩一次变成double limited的YUV;stream信息依然不修改(limited),所以MVR那边会伸张一次,但是结果依然是limited的。

你倒是可以在Pot这边手动修改YCbCr的color range为full来修复,但是这样你如果用Pot做YUV→RGB转换又要遭重… 嗯,前面提到过的Pot只用Rec. 601的color matrix问题在反向的RGB→YUV也存在。总之,就是Pot对上流的metadata的识别能力非常弱智,或者说根本不读取的。

不过,就在我无计可施的时候,我发现之前提到过的Direct conversion选项能用上!如果选成“Enable: change default output color space”,即使上的么color space选的是NV12(或者Auto),那么当输入时RGB32的时候也会自动触发“Direct RGB32”,完美规避了各种色彩空间转换的BUG!试了下4:4:2的视频,结果也是一样喜人。

结论

一言以蔽之,要避免让Pot的transform滤镜干任何事(……),我们用他的唯一目的就是防止PotPlayer崩溃。由于它夹在LAV和MVR中间,所以最简单的办法就是把10bit->8bit交给LAV,把色彩空间转换和resizing交给MVR。因此,对于99%的4:2:0视频,把PotPlayer的输出选成NV12即可——反正转换滤镜不支持10 bit输入,LAV那边也会先dither到NV12的。之所以要手动设一下而不用默认的Auto,是因为Pot默认会自作主张upscale到YUY2。对于高于4:2:0的视频,通过把Direct conversion设为Enable: change default output color space,会自动复制输入的格式(YUY2或者RGB32),依然完美规避转换问题。

Lav那边不需要做任何调整,默认输出全勾的状态就OK。

补记

呃我都忘了补记一下了,我后来发现如果开启了Direct conversion,部分视频(还不少…)会直接崩掉Pot。所以这个选项暂时改回去了,反正非4:2:0的视频实践中基本没有。