什么是HDR视频

HDR视频是高动态规模视频(High Dynamic Range的缩写),SDR视频是规范动态规模视频(Standard Dynamic Range的缩写),动态规模指的是亮度最大值和最小值的比值。

如下图所示SDR和HDR比照发现动态规模越高,色彩更艳丽,亮度暗部细节越多。

HDR转SDR实践之旅(一)流程总结

先从遇到的问题开端讲起,之所以要处理HDR视频是因为线上反馈HDR视频又暗又灰,HDR视频正确播映需求特殊处理才行。

HDR转SDR实践之旅(一)流程总结

本系列文章主要讲Android中怎样正确处理HDR视频,从开发遇到的问题作为切入点浅显易懂解说HDR理论,你会从中学到以下10点。

  1. 怎样用MediaCodec完成HDR解码烘托
  2. HDR视频转化SDR流程
  3. OpenGL纹路怎样支撑10位YUV数据
  4. SurfaceTexture怎样支撑10位BT2020YUV
  5. 10位YUV420(i420、YV12、NV12、NV21)怎样用Shader转化成RGB
  6. YUV转RGB矩阵、BT2020转BT709色域矩阵是怎样计算出来的
  7. 传递函数(Gamma纠正、光电转化、电光转化)的正确认知和参数详解
  8. 各种ToneMapping色彩映射技能汇总
  9. 怎样使用HDR视频和屏幕亮度信息动态调整作用
  10. 全网最全HDR开发资源汇总(测验视频、LUT、经历共享、规范文档)

假如你觉得有所收获,来给HDR转SDR开源代码点个赞吧,你的鼓舞是我前进最大的动力。

HDR带来的问题

HDR作用虽好也给拍照、存储、显现阶段带来了各种问题

拍照问题

摄像头的图画传感器能捕捉的动态规模有限,怎样收集更多亮度信息呢?用不同的曝光得到多张图融合成一张,其间低曝光拿到亮处信息,高曝光拿到暗处信息,下图依据多张曝光度不相同的照片(a)融合生成亮处暗处都清晰的照片(c)。

HDR转SDR实践之旅(一)流程总结

存储问题

下图HDR图画用8位数据存储会呈现色晕、暗部和亮部看不清等情况,怎样用更小的数据存储更多更亮的色彩?用更多位数、更大色域、压缩率更高的格局存储数据(10位_BT2020色域_PQ_H265视频)。

HDR转SDR实践之旅(一)流程总结

显现问题

怎样让屏幕支撑更高亮度、更多色彩?替换屏幕资料(量子点、OLED)是种做法,下图OLED屏幕比起LCD屏幕亮的更亮、黑的更黑,也有厂商为了减小成本用抖色计划支撑更高位数的色彩(假HDR)。

HDR转SDR实践之旅(一)流程总结

怎样让屏幕中的色彩更真实?依据屏幕和图画的亮度信息重新调整作用,下图把左边的色彩经过色彩映射到右边三种屏幕上。

HDR转SDR实践之旅(一)流程总结

本篇文章讲的便是HDR显现问题,HDR视频怎样在SDR屏幕正确播映的开发流程。

SDR视频播映流程

HDR视频和SDR视频相比色域更大、亮度更高、细节更多,理论上播映起来也就不行艳丽而已,怎样播映起来又暗又灰呢?变暗还好理解,HDR视频比SDR视频亮,把HDR视频当SDR视频处理当然会变暗了,那怎样还变灰了呢?宽色域用窄色域的屏幕会变灰,如下图所示左右两个色彩都是(0.5,0.0,0.0),可是不同屏幕下不相同。

HDR转SDR实践之旅(一)流程总结

那怎样正确播映HDR视频,也不要求视频作用很好至少也不要变灰呀,让我们先来整理一下原先的SDR视频播映流程。

HDR转SDR实践之旅(一)流程总结

如上图SDR视频播映流程分3步

第1步: Mp4解封装的数据送入MediaCodec

第2步: MediaCodec解码到SurfaceTexture

第3步: SurfaceTexture绑定的纹路经过处理后烘托到SurfaceView或TextureView上屏

刚开端以为问题出在第2步,SurfaceTexture不支撑10位只取HDR视频的低8位数据忽略高2位,测验发现SurfaceTexture支撑10位,绑定的RGB纹路和视频原始YUV换算后基本上相同,其实问题出在第三步,纹路用OpenGL烘托时屏幕不知道要敞开HDR,这需求对屏幕Surface敞开HDR标识。针对这个问题有两个思路,一个是让屏幕敞开HDR来习惯视频,另外一个是让视频变成SDR来习惯屏幕,依据这两个思路有4个处理计划。

HDR转SDR实践之旅(一)流程总结

计划 优点 缺陷
直接解码并烘托到SurfaceView(不需OpenGL的HDR标识) 真HDR 1.不支撑修改
2.不支撑TextureView
3.屏幕需支撑HDR
解码到SurfaceTexture再烘托SurfaceView(HDR标识) 1.真HDR
2.支撑纯HDR修改
1.不支撑HDR和SDR混合修改
2.不支撑TextureView
3.屏幕需支撑HDR
4.不支撑HLG视频
5.存在兼容性问题(小米手机上发现10位HDR标识导致HDR作用延时,用16位HDR标识正常)
解码到SurfaceTexture后转成8位BT709再烘托 1.支撑修改
2.支撑TextureView和SurfaceView
3.屏幕不需支撑HDR
4.支撑HLG、PQ视频
1. HDR转SDR作用相对而言差一点
2. 部分手机或许存在SurfaceTexture不支撑10位BT2020,暂时未发现
解码到Buffer后把10位YUV数据转成8位BT709RGB纹路再烘托 1.支撑修改
2.支撑TextureView和SurfaceView
3.屏幕不需支撑HDR
4.支撑HLG、PQ视频
1. HDR转SDR作用相对而言差一点
2. 部分手机对HDR视频不支撑Buffer解码(如华为的麒麟芯片手机)

定论: 只播映不需求修改用计划1,纯HDR修改用计划2,HDR和SDR混合修改的话归纳计划3、4处理兼容性问题。

注意点:

  1. 计划1、2只能烘托到SurfaceView的Surface上,TextureView的SurfaceTexture结构出来的Surface没有HDR作用,这也是为什么分明ExoPlayer完成了HDR却在Flutter和TextureView上失效的原因。
  2. 计划3、4把HDR视频转成了SDR是为了能和原先的SDR资料一起修改,不把SDR资料转成HDR是因为SDR转HDRHDR转SDR的难度更大很简略呈现色差(采用反色彩映射时损失的亮度和色度无法康复导致呈现色彩失真和条带现象)。计划3比计划4代码写起来简略一点。
  3. OpenGL对Surface标识HDR只需求对WindowSurface的Config设为RGB10位(不需求GLContext的Config也设置10位)和装备EGL_GL_COLORSPACE_BT2020_PQ_EXT属性,可是该标识只对PQ视频有效,作用在HLG视频会导致视频过爆,暂时未发现OpenGL支撑HLG。
  4. SurfaceTexture可以相关samplerExternalOESsamplerExternal2DY2YEXT纹路采样器处理得到归一化线性RGB。

HDR视频转SDR流程

HDR视频播映只需求用SurfaceView就行,修改需求HDR转SDR,下图阐明HDR视频相对于SDR视频是宽色域、高亮度、高位深的,只需改变这三要素就能把HDR视频转成SDR视频。

HDR转SDR实践之旅(一)流程总结

如下图所示HDR转化流程便是用色域转化矩阵把宽色域变成窄色域,用色彩映射确保亮度变化时色彩不失真,归一化后量化改变位深,而所有的前提要在线性空间操作才行(拍照视频时会把天然场景的线性场景光变成非线性的电信号,修改视频时当然要转化回来啦)。所谓线性空间指的是色彩接连均匀(色彩之间可以插值),其间线性变非线性叫光电转化,非线性转线性叫电光转化,很好记,光是天然生成的,天然界的东西都是线性的,光变电便是线性变非线性,这两种转化都被叫做传递函数。

HDR转SDR实践之旅(一)流程总结

名词解释:

归一化: 将数值压缩到[0,1] 规模

电光转化: 视频用非线性电信号存储,处理的时分需求转成线性光数据,实际操作是代入特定的数学公式

色彩映射: 目的是为了高亮度转成低亮度确保色彩不失真,实际操作是一段曲线映射

色域转化: 宽色域视频直接用窄色域进行显现会变灰,需求用宽色域转化成窄色域,实际操作是矩阵转化

光电转化: 屏幕只能显现非线性电信号,线性光数据需求转成非线性电信号,用线性光数据显现会导致变亮,实际操作是代入特定的数学公式,和电光转化的公式反了反

量化: 将数值还原到[0,2^n-1] 规模内,n=8便是变成0-255,n=10便是变成0-1023

以下便是在Android中HDR视频转SDR的具体步骤:

HDR转SDR实践之旅(一)流程总结

HDR视频转SDR视频在实际操作中其实便是把10位BT2020YUV转成8位BT709RGB,前者动态规模高,后者动态规模低。

第一步: 解码处理得到归一化线形RGB有3种方法,其间方法1代码写起来最简略。

  1. MediaCodec解码到SurfaceTexture,SurfaceTexture与samplerExternalOES纹路采样器绑定得到归一化非线性的RGB数据,samplerExternalOES测验发现支撑10位BT2020RGB(兼容性不知道)
  2. MediaCodec解码到SurfaceTexture,SurfaceTexture与samplerExternal2DY2YEXT纹路采样器绑定得到归一化非线性的YUV数据,再用BT2020YUV转RGB矩阵转化成归一化非线性的RGB数据,需GL_EXT_YUV_target扩展支撑
  3. MediaCodec解码得到YUV420 ByteBuffer转化成OpenGL16位非线性YUV纹路,位移得到10位YUV再经过Shader处理转成归一化非线性的RGB数据

第二步: 电光转化把归一化非线性的RGB数据转化成线性

第三步: 依据视频元数据里边的亮度信息和屏幕亮度数据用色彩映射调整RGB色彩

第四步: 色域转化矩阵把BT2020转化BT709,BT2020是宽色域BT709是窄色域

第五步: 光电转化把线性数据还原成非线性,量化得到8位BT709RGB

问题考虑

下面3个问题留给大家考虑

  1. 色彩处理要在线性空间,YUV转RGB为什么要在电光转化之前(非线性)处理?
  2. 为什么SurfaceView支撑HDR,TextureView不支撑HDR?
  3. OpenGL创建的WindowSurface只支撑PQ不支撑HLG,有什么好的处理计划吗?

系列文章

  • HDR转SDR实践之旅(一)流程总结
  • HDR转SDR实践之旅(二)解码10位YUV纹路
  • HDR转SDR实践之旅(三)YUV420转YUV公式
  • HDR转SDR实践之旅(四)YUV转RGB矩阵推导
  • HDR转SDR实践之旅(五)色域转化BT2020转BT709
  • HDR转SDR实践之旅(六)传递函数与色差纠正
  • HDR转SDR实践之旅(七)Gamma、HLG、PQ公式详解
  • HDR转SDR实践之旅(八)色彩映射
  • HDR转SDR实践之旅(九)HDR开发资源汇总
  • HDR转SDR实践之旅(十)SDR转HDR逆色彩映射探索