首页 > 其他分享 >鸿蒙开发进阶(HarmonyOS)时域可分层视频编码

鸿蒙开发进阶(HarmonyOS)时域可分层视频编码

时间:2024-11-06 14:47:46浏览次数:5  
标签:LTR 编码 进阶 OH 参考 HarmonyOS 分层 时域

 鸿蒙NEXT开发实战往期必看文章:

一分钟了解”纯血版!鸿蒙HarmonyOS Next应用开发!

“非常详细的” 鸿蒙HarmonyOS Next应用开发学习路线!(从零基础入门到精通)

HarmonyOS NEXT应用开发案例实践总结合(持续更新......)

HarmonyOS NEXT应用开发性能优化实践总结(持续更新......)


基础概念

时域可分层视频编码介绍

可分层视频编码,又叫可分级视频编码、可伸缩视频编码,是视频编码的扩展标准,目前常用的包含SVC(H.264编码标准采用的可伸缩扩展)和SHVC(H.265编码标准采用的可扩展标准)。

其特点是能一次编码出时域分层、空域分层、质量域分层的码流结构,满足因网络、终端能力和用户需求不同带来的的差异化需求。

时域可分层视频编码, 是指能编码出时域分层码流的视频编码,下图是通过参考关系构建的4层时域分层码流结构。

从高到低逐层丢弃部分层级的码流(丢弃顺序L3->L2->L1),能实现不同程度的帧率伸缩,以满足传输和解码能力的变化需求。

如下图所示,是上述4层时域分层码流结构丢弃L3后组成的新的码流结构,能在解码正常的情况下实现帧率减半的效果。其他层的丢弃同理。

时域分层码流结构介绍

基础码流是由一个或多个独立图像组(Group Of Pictures,简称GOP)组合而成的。GOP是在编码中一组从I帧开始到I帧结束的连续的可独立解码的图像组。

时域分层码流可以在GOP内继续细分为独立的一个或多个时域图像组(Temporal Group Of Pictures, 简称TGOP),每一个TGOP由一个基本层和后续的一个或多个增强层组合而成,如上述4层时域分层码流结构中的帧0到帧7是一个TGOP。

  • 基本层(Base Layer, 简称BL): 是GOP中的最底层(L0)。在时域分层中,该层用最低帧率进行编码。

  • 增强层(Enhance Layer简称EL): 是BL之上的层级,由低到高可以分为多层(L1,L2,L3)。在时域分层中,最低层的EL依据BL获得的编码信息,进一步编码帧率更高的层级,更高层的EL会依据BL或低层EL,来编码比低层更高帧率的视频。

如何实现时域分层码流结构

时域分层码流结构的实现是依靠参考关系逐帧指定实现的,参考帧按在解码图像缓存区(Decoded Picture Buffer,简称DPB)驻留的时长分为短期参考帧和长期参考帧。

  • 短期参考帧(Short-Term Reference,简称STR): 是不能长期驻留在DPB中的参考帧,更新方式是先进先出,如果DPB满,旧的短期参考帧会被移出DPB。

  • 长期参考帧(Long-Term Reference,简称LTR): 是能长期驻留在DPB中的参考帧,通过标记替换的方式更新,不主动标记替换就不会更新。

虽然STR个数大于1时,也能实现一定的跨帧参考结构,但受限于存在时效过短,时域分层结构支持的跨度有限。LTR则不存在上述问题,也能覆盖短期参考帧跨帧场景。优选使用LTR实现时域分层码流结构。

适用场景

基于上述描述的时域分层编码特点,推荐以下场景使用:

  • 场景1:播放侧无缓存或低缓存的实时编码传输场景,例如视频会议、视频直播、协同办公等。

  • 场景2:有视频预览播放或倍速播放需求的视频编码录制场景。

若开发场景不涉及动态调整时域参考结构,且分层结构简单,则推荐使用全局时域可分层特性,否则使能长期参考帧特性

约束和限制

  • 不可以混用全局时域可分层特性和长期参考帧特性。

    由于底层实现归一,全局时域可分层特性和长期参考帧特性不能同时开启。

  • 叠加强制IDR配置时,请使用随帧通路配置。

    参考帧仅在GOP内有效,刷新I帧后,DPB随之清空,参考帧也会被清空,因此参考关系的指定受I帧刷新位置影响很大。

    使能时域分层能力后,若需要通过OH_MD_KEY_REQUEST_I_FRAME临时请求I帧,应使用生效时机确定的随帧通路配置方式准确告知框架I帧刷新位置以避免参考关系错乱,参考随帧通路配置相关指导,避免使用生效时机不确定的OH_VideoEncoder_SetParameter方式。

  • 支持OH_AVBuffer回调通路,不支持OH_AVMemory回调通路。

    新特性依赖随帧特性,应避免使用OH_AVMemory回调OH_AVCodecAsyncCallback,应使用OH_AVBuffer回调OH_AVCodecCallback

  • 支持时域P分层,不支持时域B分层。

    时域可分层编码按分层帧类型分为基于P帧的时域分层和基于B帧的时域编码,当前支持分层P编码,不支持分层B编码。

  • 均匀分层模式当前只支持TGOP为2或4。

全局时域可分层特性(Feature_Temporal_Scalability)

接口介绍

全局时域可层特性,适用于编码稳定和简单的时域分层结构,初始配置,全局生效,不支持动态修改。开发配置参数如下:

配置参数语义
OH_MD_KEY_VIDEO_ENCODER_ENABLE_TEMPORAL_SCALABILITY全局时域分层编码使能参数
OH_MD_KEY_VIDEO_ENCODER_TEMPORAL_GOP_SIZE全局时域分层编码TGOP大小参数
OH_MD_KEY_VIDEO_ENCODER_TEMPORAL_GOP_REFERENCE_MODE全局时域分层编码TGOP参考模式
  • 全局时域分层编码使能参数: 在配置阶段配置,仅特性支持才会真正使能成功。

  • 全局时域分层编码TGOP大小参数: 可选配置,影响时域关键帧之间的间隔,用户需要基于自身业务场景下抽帧需求自定义关键帧密度,可在[2, GopSize)范围内配置,若不配置则使用默认值

  • 全局时域分层编码TGOP参考模式参数: 可选配置,影响非关键帧参考模式。包括相邻参考ADJACENT_REFERENCE、跨帧参考JUMP_REFERENCE 和均匀分层UNIFORMLY_SCALED_REFERENCE。相邻参考相对跨帧参考拥有更好的压缩性能,跨帧参考相对相邻参考拥有更好的丢帧自由度,均匀分层模式丢帧后的码流分布更均匀,如不配置则使用默认值。

    说明:均匀分层模式当前只支持TGOP为2或4。

使用举例1:TGOP=4,相邻参考模式

使用举例2:TGOP=4,跨帧参考模式

使用举例3:TGOP=4,均匀分层模式

开发指导

基础编码流程请参考视频编码开发指导,下面仅针与基础视频编码过程中存在的区别做具体说明。

  1. 在初始阶段创建编码实例时,校验当前视频编码器是否支持全局时域可分层特性。

    // 1.1 获取对应视频编码器能力句柄,此处以H.264为例
    OH_AVCapability *cap = OH_AVCodec_GetCapability(OH_AVCODEC_MIMETYPE_VIDEO_AVC, true);
    // 1.2 通过特性能力查询接口校验是否支持全局时域可分层特性
    bool isSupported = OH_AVCapability_isFeatureSupported(cap, VIDEO_ENCODER_TEMPORAL_SCALABILITY);
    c++

    若支持,则可以使能全局时域可分层特性。

  2. 在配置阶段,配置全局时域分层编码特性参数。

    constexpr int32_t TGOP_SIZE = 3; 
    // 2.1 创建配置用临时AVFormat
    OH_AVFormat *format = OH_AVFormat_Create();
    // 2.2 填充使能参数键值对
    OH_AVFormat_SetIntValue(format, OH_MD_KEY_VIDEO_ENCODER_ENABLE_TEMPORAL_SCALABILITY, 1);
    // 2.3 (可选)填充TGOP大小和TGOP内参考模式键值对
    OH_AVFormat_SetIntValue(format, OH_MD_KEY_VIDEO_ENCODER_TEMPORAL_GOP_SIZE, TGOP_SIZE);
    OH_AVFormat_SetIntValue(format, OH_MD_KEY_VIDEO_ENCODER_TEMPORAL_GOP_REFERENCE_MODE, ADJACENT_REFERENCE);
    // 2.4 参数配置
    int32_t ret = OH_VideoEncoder_Configure(videoEnc, format);
    if (ret != AV_ERR_OK) {
        // 异常处理
    }
    // 2.5 配置完成后销毁临时AVFormat
    OH_AVFormat_Destroy(format);
    c++
  3. (可选)在运行阶段输出轮转中,获取码流对应时域层级信息。

    开发者可基于已配置的TGOP参数,按编码出帧数目周期性获取。

    通过配置周期获取示例代码如下:

    uint32_t outPoc = 0;
    // 通过输出回调中有效帧数,获取TGOP内相对位置,对照配置确认层级
    static void OnNewOutputBuffer(OH_AVCodec *codec, uint32_t index, OH_AVBuffer *buffer, void *userData)
    {
        // 注:若涉及复杂处理流程,建议相关
        struct OH_AVCodecBufferAttr attr;
        (void)buffer->GetBufferAttr(attr);
        // 刷新I帧后poc归零
        if (attr.flags & AVCODEC_BUFFER_FLAG_KEY_FRAME) {
            outPoc = 0;
        }
        // 没有帧码流只有XPS的输出需要跳过
        if (attr.flags != AVCODEC_BUFFER_FLAG_CODEC_DATA) {
            int32_t tGopInner = outPoc % TGOP_SIZE;
            if (tGopInner == 0) {
                // 时域关键帧,后续传输、解码流程不可丢弃
            } else {
                // 时域非关键帧,后续传输、解码流程可以丢弃
            }
            outPoc++;
        }
    }
    c++
  4. (可选)在运行阶段输出轮转中,使用步骤3获取的时域层级信息,自适应传输或自适应解码。

    基于获取的时域可分层码流和对应的层级信息,开发者可选择需要的层级进行传输,或携带至对端自适应选帧解码。

长期参考帧特性(Feature_Long-Term_Reference)

接口介绍

长期参考帧特性提供帧级灵活的参考关系配置。适用于灵活和复杂的时域分层结构。

配置参数语义
OH_MD_KEY_VIDEO_ENCODER_LTR_FRAME_COUNT长期参考帧个数参数
OH_MD_KEY_VIDEO_ENCODER_PER_FRAME_MARK_LTR当前帧标记为LTR帧
OH_MD_KEY_VIDEO_ENCODER_PER_FRAME_USE_LTR当前帧参考的LTR帧号
  • 长期参考帧个数参数: 在配置阶段配置,应小于等于查询到的最大支持数目,查询方式详见开发指导。
  • 当前帧标记为LTR帧: BL层标记为LTR,被跳跃参考的EL层也标记为LTR。
  • 当前帧参考的LTR帧号: 如当前帧需要跳跃参考前面已被标记为LTR的帧号。

使用举例,实现时域可分层视频编码介绍中的4层时域分层结构的配置如下:

  1. 在配置阶段,将OH_MD_KEY_VIDEO_ENCODER_LTR_FRAME_COUNT 配置为5。

  2. 在运行阶段输入轮转中,按如下表所示随帧配置LTR相关参数,下表中\表示不做配置。

    配置\POC012345678910111213141516
    MARK_LTR10001000100010001
    USE_LTR\\0\0\4\0\8\8\1208

开发指导

基础编码流程请参考视频编码开发指导,下面仅针与基础视频编码过程中存在的区别做具体说明。

  1. 在初始阶段创建编码实例时,校验当前视频编码器是否支持LTR特性。

    constexpr int32_t NEEDED_LTR_COUNT = 5;
    bool isSupported = false;
    int32_t supportedLTRCount = 0;
    // 1.1 获取对应编码器能力句柄,此处以H.264为例
    OH_AVCapability *cap = OH_AVCodec_GetCapability(OH_AVCODEC_MIMETYPE_VIDEO_AVC, true);
    // 1.2 通过特性能力查询接口校验是否支持LTR特性
    isSupported = OH_AVCapability_isFeatureSupported(cap, VIDEO_ENCODER_LONG_TERM_REFERENCE);
    // 1.3 确定支持的LTR数目
    if (isSupported) {
        OH_AVFormat *properties = OH_AVCapability_GetFeatureProperties(cap, VIDEO_ENCODER_LONG_TERM_REFERENCE);
        OH_AVFormat_GetIntValue(properties, OH_FEATURE_PROPERTY_KEY_VIDEO_ENCODER_MAX_LTR_FRAME_COUNT, &supportedLTRCount);
        OH_AVFormat_Destroy(properties);
        // 1.4 判断LTR是否满足结构需求
        isSupported = supportedLTRCount >= NEEDED_LTR_COUNT;
    }
    c++

    若支持,且支持的LTR数目满足自身码流结构需求,则可以使能LTR特性。

  2. 在配置之前注册回调时,注册随帧通路回调。

    Buffer输入模式示例:

    // 2.1 编码输入回调OH_AVCodecOnNeedInputBuffer实现
    static void OnNeedInputBuffer(OH_AVCodec *codec, uint32_t index, OH_AVBuffer *buffer, void *userData)
    {
        // 输入帧buffer对应的index,送入InIndexQueue队列
        // 输入帧的数据buffer送入InBufferQueue队列
        // 数据处理,请参考:
        // - 写入编码码流
        // - 通知编码器码流结束
        // - 随帧参数写入
        OH_AVFormat *format = OH_AVBuffer_GetParameter(buffer);
        OH_AVFormat_SetIntValue(format, OH_MD_KEY_VIDEO_ENCODER_PER_FRAME_MARK_LTR, 1);
        OH_AVFormat_SetIntValue(format, OH_MD_KEY_VIDEO_ENCODER_PER_FRAME_USE_LTR, 4);
        OH_AVBuffer_SetParameter(buffer, format);
        // 通知编码器buffer输入完成
        OH_VideoEncoder_PushInputBuffer(codec, index);
    }
    
    // 2.2 编码输出回调OH_AVCodecOnNewOutputBuffer实现
    static void OnNewOutputBuffer(OH_AVCodec *codec, uint32_t index, OH_AVBuffer *buffer, void *userData)
    {
        // 完成帧buffer对应的index,送入outIndexQueue队列
        // 完成帧的数据buffer送入outBufferQueue队列
        // 数据处理,请参考:
        // - 释放编码帧
        // - 记录POC和LTR生效情况
    }
    
    // 2.3 注册数据回调
    OH_AVCodecCallback cb;
    cb.onNeedInputBuffer = OnNeedInputBuffer;
    cb.onNewOutputBuffer = OnNewOutputBuffer;
    OH_VideoEncoder_RegisterCallback(codec, cb, nullptr);
    c++

    Surface输入模式示例:

    // 2.1 编码输入参数回调OH_VideoEncoder_OnNeedInputParameter实现
    static void OnNeedInputParameter(OH_AVCodec *codec, uint32_t index, OH_AVFormat *parameter, void *userData)
    {
        // 输入帧buffer对应的index,送入InIndexQueue队列
        // 输入帧的数据avformat送入InFormatQueue队列
        // 数据处理,请参考:
        // - 写入编码码流
        // - 通知编码器码流结束
        // - 随帧参数写入
        OH_AVFormat_SetIntValue(parameter, OH_MD_KEY_VIDEO_ENCODER_PER_FRAME_MARK_LTR, 1);
        OH_AVFormat_SetIntValue(parameter, OH_MD_KEY_VIDEO_ENCODER_PER_FRAME_USE_LTR, 4);
        // 通知编码器随帧参数配置输入完成
        OH_VideoEncoder_PushInputParameter(codec, index);
    }
    
    // 2.2 编码输出回调OH_AVCodecOnNewOutputBuffer实现
    static void OnNewOutputBuffer(OH_AVCodec *codec, uint32_t index, OH_AVBuffer *buffer, void *userData)
    {
        // 完成帧buffer对应的index,送入outIndexQueue队列
        // 完成帧的数据buffer送入outBufferQueue队列
        // 数据处理,请参考:
        // - 释放编码帧
        // - 记录POC和LTR生效情况
    }
    
    // 2.3 注册数据回调
    OH_AVCodecCallback cb;
    cb.onNewOutputBuffer = OnNewOutputBuffer;
    OH_VideoEncoder_RegisterCallback(codec, cb, nullptr);
    // 2.4 注册随帧参数回调
    OH_VideoEncoder_OnNeedInputParameter inParaCb = OnNeedInputParameter;
    OH_VideoEncoder_RegisterParameterCallback(codec, inParaCb, nullptr);
    c++
  3. 在配置阶段,配置同时存在LTR最大数目。

    constexpr int32_t TGOP_SIZE = 3;
    // 3.1 创建配置用临时AVFormat
    OH_AVFormat *format = OH_AVFormat_Create();
    // 3.2 填充使能LTR个数键值对
    OH_AVFormat_SetIntValue(format, OH_MD_KEY_VIDEO_ENCODER_LTR_FRAME_COUNT, NEEDED_LTR_COUNT);
    // 3.3 参数配置
    int32_t ret = OH_VideoEncoder_Configure(videoEnc, format);
    if (ret != AV_ERR_OK) {
        // 异常处理
    }
    // 3.4 配置完成后销毁临时AVFormat
    OH_AVFormat_Destroy(format);
    c++
  4. (可选)在运行阶段输出轮转中,获取码流对应时域层级信息。

    同全局时域分层特性。

    因在输入轮转有配置LTR参数,也可在输入轮转中中记录,输出轮转中找到对应的输入参数。

  5. (可选)在运行阶段输出轮转中,使用步骤4获取的时域层级信息,自适应传输或自适应解码。

    同全局时域分层特性。

标签:LTR,编码,进阶,OH,参考,HarmonyOS,分层,时域
From: https://blog.csdn.net/wea22984984/article/details/143570637

相关文章

  • 鸿蒙开发进阶(OpenHarmony)扩展组件-系统调用
    鸿蒙NEXT开发实战往期必看文章:一分钟了解”纯血版!鸿蒙HarmonyOSNext应用开发!“非常详细的”鸿蒙HarmonyOSNext应用开发学习路线!(从零基础入门到精通)HarmonyOSNEXT应用开发案例实践总结合(持续更新......)HarmonyOSNEXT应用开发性能优化实践总结(持续更新......)基本概念......
  • 华为大气啊!HarmonyOS NEXT公测发福利~这个可以有
    HarmonyOSNEXT火热公测中,首批100万名公测用户速来领取多重权益!华为视频、华为阅读、音乐、主题、云空间、天际通等应用会员一应俱全;还有爱奇艺、哔哩哔哩、芒果TV、WPS、喜马拉雅、优酷六大应用的会员季卡6选2,这一波不得不说华为大气!......
  • Python:用 turtle 库打造趣味动画 —— 基础示例与进阶拓展
    以下是一个使用Python的matplotlib库实现的简单动画程序示例,展示了一个正弦波动态变化的效果,标题为《Python与Matplotlib:动态正弦波动画展示》。收起python复制importnumpyasnpimportmatplotlib.pyplotaspltimportmatplotlib.animationasanimation#创......
  • 鸿蒙HarmonyOS(ArkUI基础-3)
    文章目录ArkUI(方舟UI框架)1.简介2.基本概念3.概述4.布局1.概述......
  • Android高级进阶之路【二】十分钟彻底弄明白 View 事件分发机制
    前言Android事件分发机制是Android开发者必须了解的基础网上有大量关于Android事件分发机制的文章,但存在一些问题:内容不全、思路不清晰、无源码分析、简单问题复杂化等等今天,我将全面总结Android的事件分发机制,我能保证这是市面上的最全面、最清晰、最易懂的本文秉着“结论......
  • IT监控(进阶篇):运维监控系统手把手部署教学
    前言:注:系统需必须是centos7.4-7.9或redhat7.4-7.9且无其他业务的,不存在nginx、php、mysql、perseusZ_server、ansibles、postgresql等软件,否则一些脚本探测到已安装则会跳过配置文件的修改导致后续安装的系统功能异常。top#查看系统配置最低要求CPU8核心以上,内存8G以上。df-hl......
  • 鸿蒙开发进阶(HarmonyOS )加速Web页面的访问
     鸿蒙NEXT开发实战往期必看文章:一分钟了解”纯血版!鸿蒙HarmonyOSNext应用开发!“非常详细的”鸿蒙HarmonyOSNext应用开发学习路线!(从零基础入门到精通)HarmonyOSNEXT应用开发案例实践总结合(持续更新......)HarmonyOSNEXT应用开发性能优化实践总结(持续更新......)当Web页......
  • 鸿蒙HarmonyOS(ArkTS基础-1)
    文章目录HarmonyOS鸿蒙开发ArkTS语言1.初识ArkTS语言a.ArKTS是什么b.ArkTS的编程规范c.从Ts到ArkTS的注意点2.ArkTS的基本语法a.声明b.类型c.运算符d.语句HarmonyOS鸿蒙开发(本文档是在鸿蒙开发者文档的基础上,选取了最常用的一些关键语法,以及一些注释,可......
  • 【JavaScript进阶部分——DOM操作 (节点获取,节点属性修改,节点创建与插入,CSS样式的修改)
    ‌DOM操作‌是指对文档对象模型(DocumentObjectModel,简称DOM)进行增删改查等操作的过程。DOM是一种表示和操作HTML、XML等文档的标准编程接口,它将文档解析为一个由节点和对象(包含属性和方法)组成的集合,开发者可以通过DOM提供的接口来访问和操作文档的各个部分,包括元素、属性、文......
  • Java面试题中高级进阶(JVM篇)
    前言本来想着给自己放松一下,刷刷博客,突然被几道面试题难倒!什么是StopTheWorld?什么是OopMap?说一下JVM的主要组成部分及其作用?什么是指针碰撞?什么是空闲列表?什么是TLAB?似乎有点模糊了,那就大概看一下面试题吧。好记性不如烂键盘***12万字的java面试题整理***什么是StopT......