皮皮网

【自助表单源码】【一起牛牛源码】【呆萌直播源码系统】cameraview源码解析

2024-11-27 15:32:02 来源:跑胡子 java 源码

1.Apple Vision Pros使用的源码MV-HEVC编码格式
2.UE4:Niagara扩展CameraQuery支持CPU获取ViewSize
3.surfaceview和view的区别

cameraview源码解析

Apple Vision Pros使用的MV-HEVC编码格式

       MV-HEVC,全称Multiview High Efficiency Video Coding,解析是源码HEVC(High Efficiency Video Coding)编码标准的扩展部分,记为HEVC version 2。解析这一视频编码标准自年7月发布以来,源码相关标准于年月发布。解析自助表单源码然而,源码尽管这一标准已发布近十年,解析但在具体业务中的源码应用却并不多。

       年6月,解析在WWDC开发者大会上,源码苹果公司宣布,解析通过iOS .2 Beta版本,源码iPhone Pro能够拍摄出Apple Vision Pro的解析空间视频,而Apple Vision Pro所采用的源码一起牛牛源码视频编码格式,正是MV-HEVC。

       为何苹果选择使用MV-HEVC格式来实现3D视频编码?在开发者大会上,苹果介绍了3D视频的视频,链接地址如下:developer.apple.com/vid...

       苹果表示,MV-HEVC实际上是HEVC,而目前对HEVC视频编码格式支持最好的或许就是苹果。无论是基于HEVC的HEIF静态格式、HEVC的动图live photo,还是苹果的HEVC视频hvc1,苹果都提供了良好的支持。

       苹果在开发者大会上所提到的“空间视频”,其原理与我们在**院看的3D**类似,都是利用人眼的左右眼视差来制造和表现“立体”效果。

       从视频编解码的呆萌直播源码系统角度来看,使用MV-HEVC方案的好处是,它可以在不改变slice层以下的HEVC原有语法和解码过程下,通过layer间预测技术实现对3D和多视角视频的支持。这也意味着MV-HEVC可后向兼容和使用现有的HEVC编码器和解码器,不需要有较大的修改,仅修改high level语法即可。

       如果对MV-HEVC格式做了Block Level语法的修改,此时对应的便是JCT-3V制定的3D-HEVC格式,它的压缩性能要比MV-HEVC更高,会有额外的压缩性能的工具。

       目前MV-HEVC和3D-HEVC的参考软件都是同一套代码,叫做HTM。hevc.hhi.fraunhofer.de/...

       HTM的代码是使用SVN进行版本管理的,如果想下载源码,动态效果网站源码在macOS上可以在终端直接使用下面的命令检出代码:

       在HTM源码的TypeDef.h头文件中,可以看到有一个HEVC_EXT宏,如果这个宏的值是1,此时编译的就是MV-HEVC,而如果是2,此时就是3D-HEVC。

       在MV-HEVC标准中语法元素LayerId,表示该NALU所归属的view。在空间视频中,通常用LayerId 0表示该帧属于左视点(通常也是主视点),LayerId 1则表示属于右视点(辅视点)。

       属于主视点的图像编码参考帧规则保持和沿用标准HEVC,它得到的码流就是标准HEVC码流,而辅视点每一帧图像编码多了视点间的源码安装ssh卸载脚本参考帧,如果显示设备还不支持解码和播放MV-HEVC格式,那就可以只解码和显示主视点的标准HEVC码流,就像把3D**用2D来看一样。

       实际上3D-HEVC,MV-HEVC以及Scalable HEVC有一样的层间预测技术,都可以抽取出base view码流,且能用支持Main profile的HEVC解码器来解码。而3D-HEVC里还可以抽取出MV-HEVC的码流,因为MV-HEVC加上Depth信息就是3D-HEVC,而HEVC加上delta信息就是MV-HEVC。

       最后,再来看一下MV-HEVC名字里的view具体是什么?view表示All layers belonging to the same camera perspective,包括像苹果的MV-HEVC格式,通常是有2个view,分别是left view和right view,对应人眼的左眼和右眼。

       当然也可以有多个view,下图是4个layer和2个view的编码结构和参考依赖图。

       以上是对MV-HEVC的简单介绍,由于目前能够支持对其进行正常解析和解码的硬件和软件几乎没有,所以暂时不能对实际拍摄的空间视频做更多分析和介绍。更多MV-HEVC对高层语法的修改内容请参考文章后面的参考资料4。

       虽然今天来看MV-HEVC不是什么新技术,但苹果能在自家手机和消费终端Apple Version Pro上首次推广和使用这个技术,让这个技术更接近用户,此举是值得点赞的。而对我们这些视频编解码算法工程师来说,一项编码技术能有更多的业务应用,也是好事。

       参考资料

       1. ieeexplore.ieee.org/sta...

       2. developer.apple.com/av-...

       3.Standardized Extensions of High Efficiency Video Coding (HEVC)

       4.Overview of the Multiview and 3D Extensions of High Efficiency Video Coding

       5. pastebin.com/qZ1xSmuc#...

UE4:Niagara扩展CameraQuery支持CPU获取ViewSize

       在使用UE4中的Niagara系统进行粒子系统开发时,遇到过一个需求:需要在CPU粒子系统中获取ViewSize参数,而该参数在CameraQuery组件中仅提供了一个支持GPU的方法。为了解决这个问题,我们探究了如何在Niagara系统中实现CPU获取ViewSize的方法。

       首先,创建一个NiagaraScript并添加CameraQuery节点,目的是获取ViewSize参数。在MapGet节点中拉出一个Get方法,可以看到该方法支持CPU还是GPU。然而,由于添加了一个不支持的方法,编译时会报错。因此,我们需要实现一个在CPU粒子系统中获取ViewSize的解决方案。

       通过查看CameraQuery的源码,发现GetViewPropertiesGPU函数在注释中被标记为CPU模拟实现,实际并未获取任何数据。进一步研究其他CPU函数的实现,我们了解到数据实际上是从Context的FCameraDataInterface_InstanceData中获取的。通过VectorVM::FExternalFuncRegisterHandler的方式,将获取到的值传递到输出pin,完成了数据从实例数据到输出的传递。

       接着,关注到UNiagaraDataInterfaceCamera::GetCameraProperties函数中的完整流程,它更详细地展示了如何添加输出、获取值和赋值的操作。通过分析FCameraDataInterface_InstanceData的初始化和PerInstanceTick函数,我们了解到摄像机参数是通过从World和PlayerController获取的,而这些操作在Tick函数中进行。确认了摄像机参数的获取过程合理,并支持编辑器模式下的正常获取。

       在GetFunctions函数中,添加输出和方法的定义时,需要注意函数名、支持CPU/GPU的标志以及是否为成员函数等细节。在GetFunctionHLSL中,只关注CPU方法的实现,通过函数的DefinitionName获取HLSL代码。

       为了在CameraQuery中增加获取ViewSize的方法,我们需要在FCameraDataInterface_InstanceData结构体中增加相应的参数,并在PerInstanceTick函数中进行赋值。同时,修改GetFunctions和GetFunctionHLSL以支持CPU粒子系统。最后,通过绑定GetVMExternalFunction完成方法的实现。

       实现后,可以通过任意的Material进行调试,并在编辑器中查看结果,验证方法的正确性。这样,我们不仅解决了获取ViewSize的需求,还为Niagara系统的CPU粒子系统增加了更多灵活性。

surfaceview和view的区别

       ã€€ã€€SurfaceView是从View基类中派生出来的显示类,直接子类有GLSurfaceView和VideoView,可以看出GL和视频播放以及Camera摄像头一般均使用SurfaceView,到底有哪些优势呢? SurfaceView可以控制表面的格式,比如大小,显示在屏幕中的位置,最关键是的提供了SurfaceHolder类,使用getHolder方法获取,相关的有Canvas lockCanvas()

       ã€€ã€€Canvas lockCanvas(Rect dirty) 、void removeCallback(SurfaceHolder.Callback callback)、void unlockCanvasAndPost(Canvas canvas) 控制图形以及绘制,而在SurfaceHolder.Callback 接口回调中可以通过重写下面方法实现。

       ã€€ã€€ä½¿ç”¨çš„SurfaceView的时候,一般情况下要对其进行创建,销毁,改变时的情况进行监视,这就要用到 SurfaceHolder.Callback.

       ã€€ã€€class XxxView extends SurfaceView implements SurfaceHolder.Callback {

       ã€€ã€€public void surfaceChanged(SurfaceHolder holder,int format,int width,int height){ }

       ã€€ã€€//看其名知其义,在surface的大小发生改变时激发

       ã€€ã€€public void surfaceCreated(SurfaceHolder holder){ }

       ã€€ã€€//同上,在创建时激发,一般在这里调用画图的线程。

       ã€€ã€€public void surfaceDestroyed(SurfaceHolder holder) { }

       ã€€ã€€//同上,销毁时激发,一般在这里将画图的线程停止、释放。

       ã€€ã€€}

       ã€€ã€€å¯¹äºŽSurface相关的,Android底层还提供了GPU加速功能,所以一般实时性很强的应用中主要使用SurfaceView而不是直接从View构建,同时后来做android 3d OpenGL中的GLSurfaceView也是从该类实现。

       ã€€ã€€SurfaceView和View最本质的区别在于,surfaceView是在一个新起的单独线程中可以重新绘制画面而View必须在UI的主线程中更新画面。

       ã€€ã€€é‚£ä¹ˆåœ¨UI的主线程中更新画面 可能会引发问题,比如你更新画面的时间过长,那么你的主UI线程会被你正在画的函数阻塞。那么将无法响应按键,触屏等消息。

       ã€€ã€€å½“使用surfaceView 由于是在新的线程中更新画面所以不会阻塞你的UI主线程。但这也带来了另外一个问题,就是事件同步。比如你触屏了一下,你需要surfaceView中thread处理,一般就需要有一个event queue的设计来保存touch event,这会稍稍复杂一点,因为涉及到线程同步。

       ã€€ã€€æ‰€ä»¥åŸºäºŽä»¥ä¸Šï¼Œæ ¹æ®æ¸¸æˆç‰¹ç‚¹ï¼Œä¸€èˆ¬åˆ†æˆä¸¤ç±»ã€‚

       ã€€ã€€1 被动更新画面的。比如棋类,这种用view就好了。因为画面的更新是依赖于 onTouch 来更新,可以直接使用 invalidate。 因为这种情况下,这一次Touch和下一次的Touch需要的时间比较长些,不会产生影响。

       ã€€ã€€2 主动更新。比如一个人在一直跑动。这就需要一个单独的thread不停的重绘人的状态,避免阻塞main UI thread。所以显然view不合适,需要surfaceView来控制。

       ã€€ã€€

       ã€€ã€€3.Android中的SurfaceView类就是双缓冲机制。因此,开发游戏时尽量使用SurfaceView而不要使用View,这样的话效率较高,而且SurfaceView的功能也更加完善。

       ã€€ã€€

       ã€€ã€€è€ƒè™‘以上几点,所以我一直都选用 SurfaceView 来进行游戏开发。

       ã€€ã€€é‚£ä¹ˆåœ¨ä»¥åŽæºç å®žä¾‹ä¸­ï¼Œæˆ‘都会以继承sarfaceView框架来进行演示。下一章将详细剖析sarfaceview ,以及附上本人写的游戏开发架构