Apple HEVC Stereo Video

1. 前言

为左眼和右眼携带立体视频视图的能力产生了更丰富的用户体验。 立体视频(有时称为“3D 视频”)向用户的左眼呈现一个图像,向用户的右眼呈现另一幅图像(通常是相关的)以产生立体效果,定义为:大脑接收双眼视觉刺激而产生的深度知觉; 双眼视觉。

如下图,左眼一幅图,右眼一幅图,同时播放在加上apple眼镜的渲染,就形成3D效果。

Apple的立体视频也是以上的模式,这里介绍Apple定义的HEVC在mp4中的3D视觉如何构造格式box和其特点。

主视觉可以是左眼,也可以是右眼。下面为了方便叙述,左眼为主视觉,右眼为子视觉。

1.1 Apple HEVC Nalu

HEVC NALU头:

+---------------+---------------+
|0|1|2|3|4|5|6|7|0|1|2|3|4|5|6|7|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|F|     Type   | LayerId  | TID |
+---------------+---------------+

F: forbid,如果使能,该nalu就无效,一般f都为0;

type: nalu类型

layerId: 空间层,常规都是0,但是在apple hevc stereo中,主视觉layerId=0, 子视觉layerId=1

tid: 时间层

两个连续nalu的例子:

video data dts:50, pts:133, len: 2280, hevc header:{"forbid":0,"nalu_type":1,"layer_id":0,"tid":1}
video data dts:50, pts:133, len: 1981, hevc header:{"forbid":0,"nalu_type":1,"layer_id":1,"tid":1}

如上:
主视觉,dts=50,layer_id=0
子视觉,dts=50,layer_id=1
两个nalu的dts和pts一样,通过layer_id的不一样,来标识主视觉和子视觉。

注意: 通过layer_id的不同来标识主视觉和子视觉,这样能实现播放器的前后兼容。

新播放器(支持apple hevc stereo, vision pro),能通过layerId=0和1,来识别主视觉和子视觉;

旧播放器(不支持apple hevc stereo),只能识别layerId=0,只能识别主视觉,也就是当作普通的视频来播放,从而实现前后兼容。

2. mp4中的hevc stereo

2.1 stsd box中的hvc1

stsd box主要用于存放音频/视频的sequenc header信息,如果是H264编码,其中就是存放的avc1格式的sps+pps;如果是H265编码,这里就是存放的是hvc1,其包含vps+sps+pps;

如上stsd box中,包含hvc1 box,hvc1 box自身的关键信息有:

//字段顺序如下,字段大小也如下
typedef struct
{uint32_t reserved1_ = 0;uint16_t reserved2_ = 0;uint16_t data_reference_index_ = 0;uint16_t codec_stream_version_ = 0;//Reserveduint16_t codec_stream_reversion_ = 0;//Reserveduint32_t reserved3_[3];uint16_t width_ = 0;uint16_t height_ = 0;uint32_t horizontal_resolution_ = 0;uint32_t vertical_resolution_ = 0;uint32_t data_size_ = 0;//Reserveduint16_t frame_count_ = 0;//frame cout == 1char compressorname_[32];//0 for defaultuint16_t alpha_ = 0x18;uint16_t reserved4_ = 0xffff;
} HVC1_INFO;

hvc1 box中包含的子box比较多,其中比较中要的有:

  • hvcC box:主视觉的vps+sps+pps,比如:左眼视觉
  • lhvC box(新增): 子视觉的sps+pps,比如:右眼视觉
  • vexu box(新增): apple hevc stereo独有的box,后面单独介绍

重要信息:lhvC box和vexu box都是apple新增的box,主要用于hevc stereo(3D视觉),这里支持对旧版本播放器的兼容,因为旧版本播放器(不支持3d)并不认识lhvC和vexu这两个box,所以仅仅只解析hvcC box,也就是主视觉的vps+sps+pps,这样旧的播放器一样能播放该视频文件(当作2d的视频来播放,也就是只播放左眼视觉的图片)

总结: 这种格式是能对2d和3d都兼容播放

  • 新播放器(支持apple hevc stereo, vision pro):同时解析hvcC(左眼)和lhvC(右眼),最后播放的是3D效果;
  • 旧播放器(不支持apple hevc stereo):仅仅解析hvcC,把视频当作是2d普通视频来播放,一样能看。

2.1.1 hvcC box

该box包含的关键信息:

//具体的vps或sps或pps数据信息
typedef struct HEVC_NALU_DATA_S {std::vector<uint8_t>  nalu_data;
} HEVC_NALU_DATA;typedef struct HEVC_NALUnit_S {uint8_t  array_completeness;
// nal type一般为: vps(32), sps(33), pps(34)uint8_t  nal_unit_type; 
//vps或sps或pps的个数uint16_t num_nalus; std::vector<HEVC_NALU_DATA> nal_data_vec;
} HEVC_NALUnit;typedef struct HEVC_DEC_CONF_RECORD_S {uint8_t  configuration_version;uint8_t  general_profile_space;uint8_t  general_tier_flag;uint8_t  general_profile_idc;uint32_t general_profile_compatibility_flags;uint64_t general_constraint_indicator_flags;uint8_t  general_level_idc;uint16_t min_spatial_segmentation_idc;uint8_t  parallelism_type;uint8_t  chroma_format;uint8_t  bitdepth_lumaminus8;uint8_t  bitdepth_chromaminus8;uint16_t avg_framerate;uint8_t  constant_frameRate;uint8_t  num_temporallayers;uint8_t  temporalid_nested;//mdat box中前面多少字节为长度,一般是4字节(lengthsize_minusone+1)uint8_t  lengthsize_minusone;std::vector<HEVC_NALUnit> nalu_vec;
} HEVC_DEC_CONF_RECORD;

为了支持左右立体眼睛视图,SPS和PPS,它们几乎相同,仅在立体眼睛分配和绑定到 nuh_layer_id 值方面有所不同。

两个SPS(主视觉与子视觉):

  • 两个sps的 sps_video_parameter_set_id 均应等于 0。
  • 两个sps应指示两个立体眼睛视图的相同特征,例如width, height, bitDepth, chromaFormat 和 conformanceWindow。 这可以在第二层中通过使用 update_rep_format=1 或通过为相应的 seq_parameter_set_rbsp 字段显式设置相同的值来完成
  • 基础层SPS 可以具有指示video_full_range_flag = 0 或video_full_range_flag = 1 的vui_parameters。两个层应具有相同的标志
  • 两个序列参数集应指示相同的亮度和色度位深度,但可以是 8 位或 10 位

两个PPS(主视觉与子视觉):

  • 一个用于主视觉,nuh_layer_id 等于0,pps_seq_parameter_set_id 等于0,pps_pic_parameter_set_id 等于0。这对应于主眼视觉。
  • 一个用于子视觉,其中 nuh_layer_id 等于副眼 nuh_layer_id,一般为1,并且 pps_seq_parameter_set_id 等于副眼层 SPS ID,并且 pps_pic_parameter_set_id 等于非零数字,此处称为副眼层 PPS ID。
  • 所有参考帧必须与引用它们的图片具有相同的 CTB 大小

VPS(仅仅在hvcC中有,lvcC中没有):

主要用传输视频分级信息,有利于兼容可分级视频以及3D视频,如视频包含最大的层级,也可包含profile,level等信息。一个给定的视频序列,无论它的SPS是否相同,都参考相同的VPS.

一个视频参数集 (VPS),nuh_layer_id 等于 0,vps_video_parameter_set_id 等于 0,并且包含 vps_extension.

  • vps_max_layers_minus1 应至少为 1,表示两层,一层用于左眼,一层用于右眼。 仅支持纹理层。
  • 基础层应出现在 MV-HEVC 比特流中,VPS 中的 vps_base_layer_internal_flag 和 vps_base_layer_available_flag 应具有值 1。
  • vps_extension具有左眼和右眼的viewID,指示出layer_id_in_nuh[]、scalability_mask_flag[]、dimension_id [][]、view_id_val[]和direct_dependency_flag[][]语法元素的值,以将纹理层与左眼和右眼相关联,并映射到在 三维_reference_displays_info SEI 消息。 有关如何根据 nuh_layer_ids 建立 left_view_id[0] 和 right_view_id[0] 的描述,具体在后面的附录中给出。

2.1.2 lhvC box

lhvC中

SPS: 

  • nuh_layer_id 应等于副眼 nuh_layer_id(一般为1),并且 sps_seq_parameter_set_id 等于非零数字,此处称为副眼 SPS ID(一般为1)
  • 推荐SPSID为1标识右眼
  • 接受副眼层 SPS ID 的非零值,并识别副眼 PPS 的 pps_seq_parameter_set_id 字段中的值

PPS:

  • nuh_layer_id 应等于子视觉 nuh_layer_id(一般为1),并且pps_seq_parameter_set_id 等于子视觉SPS ID,并且 pps_pic_parameter_set_id 等于非零数字,此处称为子视觉PPS ID;
  • 推荐子视觉PPS ID为1;
  • 接受副眼 PPS ID 的非零值,并在视频切片 slice_pic_parameter_set_id 字段中识别视频帧的副眼部分中的值

2.1.3 小结

如上,

主视觉,nah_layer_id = 0; 子视觉nah_layer_id = 1;

hvcC box中含vps, sps, pps, 和3d sei。

其中VPS中vps_video_para_set_id = 0; SPS中sps_seq_para_set_id = 0; PPS中pps_pic_param_set_id = 0;

lhvC(子视觉), SPS中sps_seq_para_set_id = 1; PPS中pps_pic_param_set_id = 1;

在mdat box中的具体数据,

主视觉帧: dts:50, pts:133, len: 2280, hevc header:{"forbid":0,"nalu_type":1,"layer_id":0,"tid":1}
子视觉帧: dts:50, pts:133, len: 1981, hevc header:{"forbid":0,"nalu_type":1,"layer_id":1,"tid":1}

也就是通过nalu header中的layer_id的不同来标识该帧是主视觉,还是子视觉;

2.2 Video Extended Usage (‘vexu’) box

vexu box仅仅在stereo的3d播放时有用,其余的时候可以忽略。

vexu box内部包含的子box:

2.2.1 must box

aligned(8) class RequiredBoxTypesBox extends FullBox(‘must’, 0, 0 ) {unsigned int(32) required_box_types[];
}

这个box不是必须的;

2.2.2 stri box

必须有。

aligned(8) class StereoViewInformationBox extends FullBox(‘stri’, 0, 0) {unsigned int(4) reserved;       // reserved, set to 0unsigned int(1) eye_views_reversed;unsigned int(1) has_additional_views;unsigned int(1) has_right_eye_view;//video contains a right-eye viewunsigned int(1) has_left_eye_view;//video contains a left-eye view
}

has_left_eye_view:表示立体左眼出现在视频帧中 has_right_eye_view:表示立体右眼出现在视频帧中
has_additional_views:表示除了立体左眼和立体右眼之外,可能还存在一个或多个其他视图(例如,“中心线”视图)
eye_views_reversed:表示立体左眼和立体右眼的顺序与默认的左眼第一右眼第二顺序相反

2.2.3 hero box

这个box不是必须

aligned(8) class HeroStereoEyeDescriptionBox extends FullBox(‘hero’, 0, 0)
{unsigned int(8) hero_eye_indicator; // 0 = none, 1 = left, 2 = right, >=
3 reserved
}

hero_eye_indicator:用于 HeroStereoEyeDescriptionBox,用于指示指定了哪个英雄眼(如果有)。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/847761.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

JDBC学习笔记(二)进阶篇

一、JDBC 扩展 1.1 实体类和ROM 实体类代码&#xff1a; package com.atguigu.advanced.pojo;//类名就是数据库表的 t_ 后面的单词全写 public class Employee {private Integer empId;//emp_idprivate String empName;//emp_nameprivate Double empSalary;//emp_salarypriva…

太极图形课——渲染——光线追踪实战第一部分呢

根据概念部分我们逐步通过太极实现光线追踪 总共可以分为5步 第一步&#xff1a;如何发射出一道光&#xff1f; 首先明确何为一道光&#xff0c;光从我们眼睛&#xff08;摄像机&#xff09;射出&#xff0c;那么在三维虚拟世界里&#xff0c;我们可以认为这道光就是一条射线…

【Docker学习】docker login/logout

docker login和docker logout是两个相反的操作&#xff0c;分别是登入/登出注册表&#xff08;镜像仓库&#xff09;。我们一般说的公共镜像仓库&#xff08;docker hub&#xff09;是不需要登入的&#xff0c;但私有的镜像仓库通常是需要登入&#xff08;安全考虑&#xff09;…

【TB作品】msp430g2553单片机,读取GY-30,光强传感器,显示到oled

硬件 七针 OLED * P2.0 CS* P2.1 DC* P2.2 RES* P2.3 D1 SDA* P2.4 D0* VCC 3.3V* GND GNDGY-30 //gy-30 //SCL--P1.4 //SDA--P1.5 //VCC--3.3V //GND--GND //ADDR--GND部分程序 #include <msp430.h> #include "gy30.h" #include "oled.h"f…

凸包算法Revit实例

ConvertHullAlgorithm &#xff08;凸包算法&#xff09; 引用 《计算几何》-导言&#xff1a;凸包的例子 前言 算法的基本逻辑与理念来自于《计算几何》这本书&#xff0c;后面其他几章的演示也都会在Revit中实现调试&#xff0c;希望能够每个算法都找一个合适的实现方向在R…

Pytorch实用教程:pytorch中 argmax(dim)用法详解

argmax(dim) 是 PyTorch 中的一个函数,用于找出指定维度上最大值的索引。argmax 函数是在多维张量上进行操作的,通过 dim 参数可以指定在哪一个维度上查找最大值。 参数解释 dim: 指定要在哪个维度上执行寻找最大值的操作。维度的索引从 0 开始,对应于张量的各个轴。返回值…

实现从微信聊天记录中获取信息,整理:具体的项目名称,要整理的日期范围,关键数据点(如任务完成度,主要负责人,重要的待解决问题)

使用开源模型从微信聊天记录中获取并整理信息&#xff0c;可以通过以下步骤实现&#xff1a; 数据收集&#xff1a; 确保合法合规地获取聊天记录。这可能需要用户的明确授权。将微信聊天记录导出为可处理的格式&#xff0c;例如文本文件或JSON。 数据预处理&#xff1a; 清洗数…

美国遛宠黑科技掀起热潮,沃尔玛跨境新品解析

美国遛宠黑科技掀起热潮&#xff0c;这一趋势不仅反映了宠物主人们对于宠物关怀的日益加深&#xff0c;也展示了科技在日常生活中的广泛应用。在这一热潮中&#xff0c;创新遛宠产品为宠物主人带来便利与体验。沃尔玛作为全球零售巨头&#xff0c;紧跟趋势&#xff0c;推出跨境…

用C#(WinForm)开发触摸屏,体验感满满

用C#&#xff08;WinForm&#xff09;开发触摸屏&#xff0c;体验感满满

加油卡APP系统开发,打造便利的汽车加油模式

随着人们生活水平的提高&#xff0c;汽车已经成为了家中必备的交通工具&#xff0c;因此&#xff0c;汽车加油也成为了大众经常要做的事。在互联网的发展下&#xff0c;汽车加油卡APP出现在了居民的生活中。加油卡系统与各个加油站合作&#xff0c;提供各种优惠折扣&#xff0c…

【Unity美术】spine软件的使用—2D动画的制作

&#x1f468;‍&#x1f4bb;个人主页&#xff1a;元宇宙-秩沅 &#x1f468;‍&#x1f4bb; hallo 欢迎 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! &#x1f468;‍&#x1f4bb; 本文由 秩沅 原创 &#x1f468;‍&#x1f4bb; 收录于专栏&#xff1a;就业…

Android Bundle的作用

Android Bundle的作用 Bundle作用 Bundle作用 Bundle主要用于传递数据&#xff1b;它保存的数据&#xff0c;是以key-value(键值对)的形式存在的传递的数据可以是boolean、byte、int、long、float、double、string等基本类型或它们对应的数组&#xff0c;也可以是对象或对象数…

透视亚马逊云科技中国峰会:生成式AI全面提速,加速行业应用落地

导读&#xff1a;亚马逊云科技在中国&#xff0c;生成式AI与行业化战略齐头并进。 “亚马逊云科技致力于成为企业构建和应用生成式AI的首选。” 近日2024亚马逊云科技中国峰会上&#xff0c;亚马逊全球副总裁、亚马逊云科技大中华区总裁储瑞松分享了亚马逊云科技中国业务最新进…

C#面:请解释ASP.NET中的web页面与其隐藏类之间的关系

在 ASP.NET 中&#xff0c;每个web页面都对应着一个隐藏类&#xff0c;这个隐藏类是由 ASP.NET 框架自动生成的。这个隐藏类继承自Page类&#xff0c;它是 ASP.NET 页面的基类。隐藏类的命名规则是以页面的名称为基础&#xff0c;加上一个下划线和一串随机生成的字符。 隐藏类…

通过ffmpeg 将wav格式转为mp3格式.

通过ffmpeg实现将wav转为mp3格式.需要下载一个ffmpeg放到执行文件所在目录. 我ffmpeg的下载地址为:ffmpeg.exe下载-ffmpeg.exe32&#xff06;64位下载免费版-旋风软件园 use ShellAPI; {$R *.dfm}procedure ConvertWavToMp3(const InputFile, OutputFile: string); varExecu…

Linux下文件权限管理

任务要求 1. 在跳板机上为开发部门专门创建一个目录&#xff0c;只允许开发部门所有员工使用该目录 2. 其他人员不能进入和查看该目录里的内容 任务分解 1. 在跳板机给开发部门创建目录 2. 对该目录做好权限的管控工作 只允许开发部门的所有人使用&#xff0c;创建、删除…

无人机航迹规划:人工原生动物优化器(Artificial Protozoa Optimizer ,APO)求解无人机路径规划,提供MATLAB代码

一、无人机模型介绍 单个无人机三维路径规划问题及其建模_无人机路径规划场景建模-CSDN博客 参考文献&#xff1a; [1]胡观凯,钟建华,李永正,黎万洪.基于IPSO-GA算法的无人机三维路径规划[J].现代电子技术,2023,46(07):115-120 二、人工原生动物优化算法APO求解无人机路径规…

linux 系统被异地登录,cpu占用拉满100%

一般是kswapd0导致的cpu占用异常 按顺序执行以下操作 在控制台执行top命令&#xff0c;查看占用最高的是否kswapd0。基本100%占用。记下该进程ID 5081 执行查找命令 find / -name kswapd0 显示查找结果&#xff1a; /proc/3316/.X2c4-unix/.rsync/a/kswapd0 /root/.configrc…

【Flutter】 TextField限制长度时, 第三方手写输入法、ios原始拼音输入法输入被吞问题

问题描述 TextField限制长度时&#xff0c; 当你的输入字符长度已经到了最大值-1时&#xff0c;使用第三方手写输入法或者ios原生拼音输入法输入liang&#xff08;什么拼音都行&#xff0c;这里只是举例&#xff09;&#xff0c;输到i那么li都会消失。 原因分析 这是因为第三…

缓存方法返回值

1. 业务需求 前端用户查询数据时,数据查询缓慢耗费时间; 基于缓存中间件实现缓存方法返回值:实现流程用户第一次查询时在数据库查询,并将查询的返回值存储在缓存中间件中,在缓存有效期内前端用户再次查询时,从缓存中间件缓存获取 2. 基于Redis实现 参考1 2.1 简单实现 引入…