OpenHarmony 3.2 Release版本Codec HDI适配过程

简介

OpenHarmony Codec HDI(Hardware Device Interface)驱动框架基于 OpenMax 实现了视屏硬件编解码驱动,提供 Codec 基础能力接口供上层媒体服务调用,包括获取组件编解码能力、创建组件、参数设置、数据的轮转和控制、以及销毁组件等功能,实现对视频数据的编解码处理。

视频编解码驱动架构

Codec HDI 2.0 接口依赖 OpenMax IL 的标准接口。OMX Wrapper 将 OMX 接口的实现封装成 libOMX_Core.z.so 供 HDI 层调用。如果 codec 驱动为实现 OpenMax 标准接口,则需根据驱动适配实现 OMX Interface 接口。

Codec HDI 2.0 接口列表:

头文件接口名称功能描述
codec_component _manager.hint32_t (*GetComponentNum)();获取 Codec 编解码组件数量
int32_t (*GetComponentCapabilityList)(CodecCompCapability *capList, int32_t count);获取编解码能力集表
int32_t (*CreateComponent)(struct CodecComponentType **component, uint32_t *componentId, char *compName, int64_t appData, struct CodecCallbackType *callbacks);创建 Codec 组件实例
int32_t (*DestroyComponent)(uint32_t componentId);销毁组件实例
codec_component _if.hint32_t (*GetComponentVersion)(struct CodecComponentType *self, struct CompVerInfo *verInfo);获取 Codec 组件版本号
int32_t (*SendCommand)(struct CodecComponentType *self, enum OMX_COMMANDTYPE cmd, uint32_t param, int8_t *cmdData, uint32_t cmdDataLen);发送命令给组件
int32_t (*GetParameter)(struct CodecComponentType *self, uint32_t paramIndex, int8_t *paramStruct, uint32_t paramStructLen);获取组件参数设置
int32_t (*SetParameter)(struct CodecComponentType *self, uint32_t index, int8_t *paramStruct, uint32_t paramStructLen);设置组件需要的参数
int32_t (*GetConfig)(struct CodecComponentType *self, uint32_t index, int8_t *cfgStruct, uint32_t cfgStructLen);获取组件的配置结构
int32_t (*SetConfig)(struct CodecComponentType *self, uint32_t index, int8_t *cfgStruct, uint32_t cfgStructLen);设置组件的配置
int32_t (*GetExtensionIndex)(struct CodecComponentType *self, const char *paramName, uint32_t *indexType);根据字符串获取组件的扩展索引
int32_t (*GetState)(struct CodecComponentType *self, enum OMX_STATETYPE *state);获取组件的状态
int32_t (*ComponentTunnelRequest)(struct CodecComponentType *self, uint32_t port, int32_t tunneledComp, uint32_t tunneledPort, struct OMX_TUNNELSETUPTYPE *tunnelSetup);设置组件 Tunneled 方式通信
int32_t (*UseBuffer)(struct CodecComponentType *self, uint32_t portIndex, struct OmxCodecBuffer *buffer);指定组件端口的 buffer
int32_t (*AllocateBuffer)(struct CodecComponentType *self, uint32_t portIndex, struct OmxCodecBuffer *buffer);向组件申请端口 buffer
int32_t (*FreeBuffer)(struct CodecComponentType *self, uint32_t portIndex, const struct OmxCodecBuffer *buffer);释放 buffer
int32_t (*EmptyThisBuffer)(struct CodecComponentType *self, const struct OmxCodecBuffer *buffer);编解码输入待处理 buffer
int32_t (*FillThisBuffer)(struct CodecComponentType *self, const struct OmxCodecBuffer *buffer);编解码输出填充 buffer
int32_t (*SetCallbacks)(struct CodecComponentType *self, struct CodecCallbackType *callback, int64_t appData);设置 Codec 组件的回调函数
int32_t (*ComponentDeInit)(struct CodecComponentType *self);组件去初始化
int32_t (*UseEglImage)(struct CodecComponentType *self, struct OmxCodecBuffer *buffer, uint32_t portIndex, int8_t *eglImage, uint32_t eglImageLen);使用已在 ELG 中申请的空间
int32_t (*ComponentRoleEnum)(struct CodecComponentType *self, uint8_t *role, uint32_t roleLen, uint32_t index);获取组件角色
codec_callback_if.hint32_t (*EventHandler)(struct CodecCallbackType *self, enum OMX_EVENTTYPE event, struct EventInfo *info);事件上报
int32_t (*EmptyBufferDone)(struct CodecCallbackType *self, int64_t appData, const struct OmxCodecBuffer *buffer);上报输入 buffer 编码或者解码处理完毕
int32_t (*FillBufferDone)(struct CodecCallbackType *self, int64_t appData, const struct OmxCodecBuffer *buffer);上报输出 buffer 填充完毕

Codec HDI 相关目录接口

├── //drivers/peripheral/codec
│   ├── hal
│   │   ├── BUILD.gn
│   │   ├── idl_service
│   │   ├── include
│   │   ├── passthrough             # v2.0到v1.0的转换,v1.0接口已弃用,无需实现
│   │   ├── src
│   │   ├── v1.0                    # codec hdi v1.0接口的实现,已弃用,MediaService已不对接相关接口。
│   │   └── v2.0                    # codec hdi v2.0接口的实现,依赖OpenMax接口,需封装实现libOMX_Core.z.so
│   ├── hdi_service                 # codec_host相关实现
│   │   ├── BUILD.gn
│   │   ├── codec_proxy
│   │   ├── codec_service_stub
│   │   └── common
│   ├── interfaces
│   │   └── include
│   └── test

OMX_Core 相关接口

codec hdi V2.0 的实现依赖 libOMX_Core.z.so,需根据 OpenMax 标准接口封装实现。

参考 drivers/peripheral/codec/hal/v2.0/hdi_impl/include/codec_omx_core.h 的定义调用过程。

typedef OMX_ERRORTYPE (*InitFunc)();
typedef OMX_ERRORTYPE (*DeinitFunc)();
typedef OMX_ERRORTYPE (*ComponentNameEnumFunc)(OMX_STRING, OMX_U32, OMX_U32);
typedef OMX_ERRORTYPE (*GetHandleFunc)(OMX_HANDLETYPE *, OMX_STRING, OMX_PTR, OMX_CALLBACKTYPE *);
typedef OMX_ERRORTYPE (*FreeHandleFunc)(OMX_HANDLETYPE);
typedef OMX_ERRORTYPE (*GetRolesOfComponentFunc)(OMX_STRING, OMX_U32 *, OMX_U8 **);

HCS 配置

配置 codec_host 服务

./hdf_config/uhdf/device_info.hcs

codec :: host {
    hostName = "codec_host";
    priority = 50;
    gid = ["codec_host", "uhdf_driver", "vendor_mpp_driver"];
    codec_omx_device :: device {
        device0 :: deviceNode {
            policy = 2;
            priority = 100;
            moduleName = "libcodec_hdi_omx_server.z.so";
            serviceName = "codec_hdi_omx_service";
            deviceMatchAttr = "media_codec_capabilities";
        }
    }
}

配置 codec_capabilities

根据 codec::host 中配置的 deviceMatchAttr,配置 hdf.hcs

./hdf_config/uhdf/hdf.hcs

#include "media_codec_capabilitie.hcs"

参考 media_codec_capabilitie.hcs

root {
    module = "master";
    codec_config {
        match_attr = "media_codec_capabilities";
        use_openmax = true;
        // capsMask: 0x01, Adaptive playback; 0x02, Secure playback; 0x04, Tunnel playback.
        // allocateMask: 0x01, Input buffer allocated within the Codec module;
        // allocateMask: 0x02, Input buffer allocated by an external user;
        // allocateMask: 0x04, Output buffer allocated within the Codec module;
        // allocateMask: 0x08, Output buffer allocated by an external user.
​
        VideoHwEncoders {
            /* node name explanation -- HDF_video_hw_enc_avc_rk:
            **
            **    HDF____________video__________________hw____________________enc____________avc_______rk
            **     |               |                    |                      |              |        |
            ** HDF or OMX    video or audio    hardware or software    encoder or decoder    mime    vendor
            */
            HDF_video_hw_enc_avc_rk {
                role = 1;
                type = 1;
                name = "OMX.rk.video_encoder.avc";
                supportProfiles = [1, 32768, 2, 32768, 8, 32768];
                maxInst = 4;
                isSoftwareCodec = false;
                processModeMask = [];
                capsMask = [0x01];
                minBitRate = 1;
                maxBitRate = 40000000;
                minWidth = 176;
                minHeight = 144;
                maxWidth = 1920;
                maxHeight = 1088;
                widthAlignment = 16;
                heightAlignment = 8;
                minBlockCount = 99;
                maxBlockCount = 8160;
                minBlocksPerSecond = 99;
                maxBlocksPerSecond = 489600;
                blockSizeWidth = 16;
                blockSizeHeight = 16;
                supportPixelFmts = [28, 24, 20, 12];
                measuredFrameRate = [320, 240, 165, 165, 720, 480, 149, 149, 1280, 720, 73, 73, 1920, 1080, 18, 18];
                bitRateMode = [1, 2];
                minFrameRate = 1;
                maxFrameRate = 60;
            }
            ......
            ......
            ......
      }
}

RK3568 的参考适配过程

OMX Wrapper 的封装

根据 gn 文件://drivers/peripheral/codec/BUILD.gn

OMX_IL_PATH = rebase_path(
          "//device/soc/${device_company}/${product_name}/hardware/omx_il")
  cmd = "if [ -f ${OMX_IL_PATH}/BUILD.gn ]; then echo true; else echo false; fi"
  HAVE_OMX_IL_PATH =
      exec_script("//build/lite/run_shell_cmd.py", [ cmd ], "value")
​
  if (HAVE_OMX_IL_PATH) {
    deps += [ "${OMX_IL_PATH}:lib_omx" ]
  }

需创建 lib_omx 工程,并封装实现 libOMX_Core.z.so,供 codec hdi 接口调用。

如果 codec 驱动已实现 OpenMax 标准接口,则可直接封装 libOMX_Core 库,否则需要根据私有驱动实现 OpenMax 接口。

参考 RK3568 的适配过程,因 codec 驱动使用 rockchip 的 mpp 平台实现,需根据私有驱动实现 OpenMax 的接口。

参考 gn 文件://device/soc/rockchip/rk3568/hardware/omx_il/BUILD.gn

group("lib_omx") {
  if (product_name == "rk3568") {
    deps = [
      "//device/soc/rockchip/rk3568/hardware/omx_il/component/video/dec:libomxvpu_dec",
      "//device/soc/rockchip/rk3568/hardware/omx_il/component/video/enc:libomxvpu_enc",
      "//device/soc/rockchip/rk3568/hardware/omx_il/core:libOMX_Core",
      "//device/soc/rockchip/rk3568/hardware/omx_il/libOMXPlugin:libOMX_Pluginhw",
    ]
  }
}

hcs 配置

  • 配置 codec_host 服务
    //vendor/hihope/rk3568/hdf_config/uhdf/device_info.hcs

    codec :: host {
        hostName = "codec_host";
        priority = 50;
        gid = ["codec_host", "uhdf_driver", "vendor_mpp_driver"];
        codec_omx_device :: device {
            device0 :: deviceNode {
                policy = 2;
                priority = 100;
                moduleName = "libcodec_hdi_omx_server.z.so";
                serviceName = "codec_hdi_omx_service";
                deviceMatchAttr = "codec_component_capabilities";
            }
        }
    }
    
    
  • 配置 codec hcs
    需根据硬件信息配置编解码组件的配置参数
    //vendor/hihope/rk3568/hdf_config/uhdf/hdf.hcs

    #include "media_codec/codec_component_capabilities.hcs"
    
    

    //vendor/hihope/rk3568/hdf_config/uhdf/media_codec/codec_component_capabilities.hcs

    root {
        module = "master";
        codec_config {
            match_attr = "codec_component_capabilities";
            use_openmax = true;
            // capsMask: 0x01, Adaptive playback; 0x02, Secure playback; 0x04, Tunnel playback.
            // allocateMask: 0x01, Input buffer allocated within the Codec module;
            // allocateMask: 0x02, Input buffer allocated by an external user;
            // allocateMask: 0x04, Output buffer allocated within the Codec module;
            // allocateMask: 0x08, Output buffer allocated by an external user.
    
            VideoHwEncoders {
                /* node name explanation -- HDF_video_hw_enc_avc_rk:
                **
                **    HDF____________video__________________hw____________________enc____________avc_______rk
                **     |               |                    |                      |              |        |
                ** HDF or OMX    video or audio    hardware or software    encoder or decoder    mime    vendor
                */
                HDF_video_hw_enc_avc_rk {
                    role = 1;
                    type = 1;
                    name = "OMX.rk.video_encoder.avc";
                    supportProfiles = [1, 32768, 2, 32768, 8, 32768];
                    maxInst = 4;
                    isSoftwareCodec = false;
                    processModeMask = [];
                    capsMask = [0x01];
                    minBitRate = 1;
                    maxBitRate = 40000000;
                    minWidth = 176;
                    minHeight = 144;
                    maxWidth = 1920;
                    maxHeight = 1088;
                    widthAlignment = 16;
                    heightAlignment = 8;
                    minBlockCount = 0xFFFFFFFF;
                    maxBlockCount = 0xFFFFFFFF;
                    minBlocksPerSecond = 0xFFFFFFFF;
                    maxBlocksPerSecond = 0xFFFFFFFF;
                    blockSizeWidth = 0xFFFFFFFF;
                    blockSizeHeight = 0xFFFFFFFF;
                    supportPixelFmts = [28, 24, 20, 12];
                    measuredFrameRate = [320, 240, 165, 165, 720, 480, 149, 149, 1280, 720, 73, 73, 1920, 1080, 18, 18];
                    bitRateMode = [1, 2];
                    minFrameRate = 0;
                    maxFrameRate = 0;
                }
            }
            VideoHwDecoders {
                HDF_video_hw_dec_avc_rk {
                    role = 1;
                    type = 0;
                    name = "OMX.rk.video_decoder.avc";
                    supportProfiles = [1, 32768, 2, 32768, 8, 32768];
                    maxInst = 6;
                    isSoftwareCodec = false;
                    processModeMask = [];
                    capsMask = [0x01];
                    minBitRate = 1;
                    maxBitRate = 10000000;
                    minWidth = 176;
                    minHeight = 144;
                    maxWidth = 4096;
                    maxHeight = 2160;
                    widthAlignment = 8;
                    heightAlignment = 8;
                    minBlockCount = 0xFFFFFFFF;
                    maxBlockCount = 0xFFFFFFFF;
                    minBlocksPerSecond = 1;
                    maxBlocksPerSecond = 244800;
                    blockSizeWidth = 16;
                    blockSizeHeight = 16;
                    supportPixelFmts = [24];
                    measuredFrameRate = [320, 240, 617, 617, 720, 480, 559, 559, 1280, 720, 276, 276, 1920, 1080, 164, 164, 3840, 2160, 30, 30];
                    bitRateMode = [];
                    minFrameRate = 0;
                    maxFrameRate = 0;
                }
                HDF_video_hw_dec_mpeg2_rk {
                    role = 0xFFFFFFFF;
                    type = 0;
                    name = "OMX.rk.video_decoder.m2v";
                    supportProfiles = [0, 3, 1, 3];
                    maxInst = 6;
                    isSoftwareCodec = false;
                    processModeMask = [];
                    capsMask = [0x01];
                    minBitRate = 1;
                    maxBitRate = 10000000;
                    minWidth = 176;
                    minHeight = 144;
                    maxWidth = 1920;
                    maxHeight = 1088;
                    widthAlignment = 8;
                    heightAlignment = 8;
                    minBlockCount = 0xFFFFFFFF;
                    maxBlockCount = 0xFFFFFFFF;
                    minBlocksPerSecond = 1;
                    maxBlocksPerSecond = 244800;
                    blockSizeWidth = 16;
                    blockSizeHeight = 8;
                    supportPixelFmts = [24];
                    measuredFrameRate = [];
                    bitRateMode = [];
                    minFrameRate = 0;
                    maxFrameRate = 0;
                }
                HDF_video_hw_dec_v8p_rk {
                    role = 0xFFFFFFFF;
                    type = 0;
                    name = "OMX.rk.video_decoder.vp8";
                    supportProfiles = [];
                    maxInst = 6;
                    isSoftwareCodec = false;
                    processModeMask = [];
                    capsMask = [0x01];
                    minBitRate = 1;
                    maxBitRate = 10000000;
                    minWidth = 176;
                    minHeight = 144;
                    maxWidth = 1920;
                    maxHeight = 1088;
                    widthAlignment = 8;
                    heightAlignment = 8;
                    minBlockCount = 0xFFFFFFFF;
                    maxBlockCount = 0xFFFFFFFF;
                    minBlocksPerSecond = 1;
                    maxBlocksPerSecond = 244800;
                    blockSizeWidth = 16;
                    blockSizeHeight = 16;
                    supportPixelFmts = [24];
                    measuredFrameRate = [320, 180, 500, 500, 640, 360, 387, 387, 1280, 720, 112, 112, 1920, 1080, 77, 77];
                    bitRateMode = [];
                    minFrameRate = 0;
                    maxFrameRate = 0;
                }
                HDF_video_hw_dec_h263_rk {
                    role = 0xFFFFFFFF;
                    type = 0;
                    name = "OMX.rk.video_decoder.h263";
                    supportProfiles = [1, 1, 1, 2, 1, 4, 1, 16, 8, 1, 8, 2, 8, 4, 8, 16];
                    maxInst = 6;
                    isSoftwareCodec = false;
                    processModeMask = [];
                    capsMask = [0x01];
                    minBitRate = 1;
                    maxBitRate = 10000000;
                    minWidth = 176;
                    minHeight = 144;
                    maxWidth = 1920;
                    maxHeight = 1088;
                    widthAlignment = 8;
                    heightAlignment = 8;
                    minBlockCount = 0xFFFFFFFF;
                    maxBlockCount = 0xFFFFFFFF;
                    minBlocksPerSecond = 1;
                    maxBlocksPerSecond = 244800;
                    blockSizeWidth = 16;
                    blockSizeHeight = 16;
                    supportPixelFmts = [24];
                    measuredFrameRate = [176, 144, 600, 600, 352, 288, 600, 600];
                    bitRateMode = [];
                    minFrameRate = 0;
                    maxFrameRate = 0;
                }
                HDF_video_hw_dec_m4v_rk {
                    role = 3;
                    type = 0;
                    name = "OMX.rk.video_decoder.m4v";
                    supportProfiles = [1, 1, 1, 2, 1, 4, 1, 8, 1, 16];
                    maxInst = 6;
                    isSoftwareCodec = false;
                    processModeMask = [];
                    capsMask = [0x01];
                    minBitRate = 1;
                    maxBitRate = 10000000;
                    minWidth = 176;
                    minHeight = 144;
                    maxWidth = 1920;
                    maxHeight = 1088;
                    widthAlignment = 8;
                    heightAlignment = 8;
                    minBlockCount = 0xFFFFFFFF;
                    maxBlockCount = 0xFFFFFFFF;
                    minBlocksPerSecond = 1;
                    maxBlocksPerSecond = 244800;
                    blockSizeWidth = 16;
                    blockSizeHeight = 16;
                    supportPixelFmts = [24];
                    measuredFrameRate = [176, 144, 600, 600];
                    bitRateMode = [];
                    minFrameRate = 0;
                    maxFrameRate = 0;
                }
                HDF_video_hw_dec_flv_rk {
                    role = 0xFFFFFFFF;
                    type = 0;
                    name = "OMX.rk.video_decoder.flv1";
                    supportProfiles = [];
                    maxInst = 6;
                    isSoftwareCodec = false;
                    processModeMask = [];
                    capsMask = [0x01];
                    minBitRate = 1;
                    maxBitRate = 10000000;
                    minWidth = 176;
                    minHeight = 144;
                    maxWidth = 1920;
                    maxHeight = 1088;
                    widthAlignment = 8;
                    heightAlignment = 8;
                    minBlockCount = 0xFFFFFFFF;
                    maxBlockCount = 0xFFFFFFFF;
                    minBlocksPerSecond = 1;
                    maxBlocksPerSecond = 244800;
                    blockSizeWidth = 16;
                    blockSizeHeight = 16;
                    supportPixelFmts = [24];
                    measuredFrameRate = [];
                    bitRateMode = [];
                    minFrameRate = 0;
                    maxFrameRate = 0;
                }
                HDF_video_hw_dec_mjpeg_rk {
                    role = 0;
                    type = 0;
                    name = "OMX.rk.video_decoder.mjpeg";
                    supportProfiles = [];
                    maxInst = 6;
                    isSoftwareCodec = false;
                    processModeMask = [];
                    capsMask = [0x01];
                    minBitRate = 1;
                    maxBitRate = 10000000;
                    minWidth = 176;
                    minHeight = 144;
                    maxWidth = 1920;
                    maxHeight = 1088;
                    widthAlignment = 8;
                    heightAlignment = 8;
                    minBlockCount = 0xFFFFFFFF;
                    maxBlockCount = 0xFFFFFFFF;
                    minBlocksPerSecond = 1;
                    maxBlocksPerSecond = 244800;
                    blockSizeWidth = 16;
                    blockSizeHeight = 16;
                    supportPixelFmts = [24];
                    measuredFrameRate = [];
                    bitRateMode = [];
                    minFrameRate = 0;
                    maxFrameRate = 0;
                }
                HDF_video_hw_dec_hevc_rk {
                    role = 2;
                    type = 0;
                    name = "OMX.rk.video_decoder.hevc";
                    supportProfiles = [1, 1, 1, 4, 1, 16, 1, 64, 1, 256, 1, 1024, 1, 4096, 1, 16384, 1, 65536, 2, 65536];
                    maxInst = 6;
                    isSoftwareCodec = false;
                    processModeMask = [];
                    capsMask = [0x01];
                    minBitRate = 1;
                    maxBitRate = 160000000;
                    minWidth = 176;
                    minHeight = 144;
                    maxWidth = 1920;
                    maxHeight = 1088;
                    widthAlignment = 2;
                    heightAlignment = 2;
                    minBlockCount = 0xFFFFFFFF;
                    maxBlockCount = 0xFFFFFFFF;
                    minBlocksPerSecond = 1;
                    maxBlocksPerSecond = 244800;
                    blockSizeWidth = 16;
                    blockSizeHeight = 16;
                    supportPixelFmts = [24];
                    measuredFrameRate = [352, 288, 700, 700, 720, 480, 700, 700, 640, 360, 980, 980, 1280, 720, 600, 600, 1920, 1080, 130, 130, 3840, 2160, 130, 130];
                    bitRateMode = [];
                    minFrameRate = 0;
                    maxFrameRate = 0;
                }
            }
            VideoSwEncoders {
            }
            VideoSwDecoders {
            }
            AudioHwEncoders {
            }
            AudioHwDecoders {
            }
            AudioSwEncoders {
            }
            AudioSwDecoders {
            }
        }
    }
    
    

适配验证

  • 当系统启动后,拉起 codec_host 进程,日志中有加载 hcs 配置的 component 相关组件的 log,则初步判定适配过程正常。

  • 当前系统通过 gstreamer 插件实现视频编解码功能。当未实现硬件编解码时,默认使用 FFmpeg 软件编解码。
    codec hdi 插件加载过程如下:
    ///foundation/multimedia/player_framework/services/engine/gstreamer/plugins/codec/hdi_plugins/hdi_init.cpp

    void HdiInit::AddHdiCap(CodecCompCapability &hdiCap)
    {
        MEDIA_LOGI("Add codec name %{public}s", hdiCap.compName);
        CapabilityData codecCap;
        codecCap.codecName = hdiCap.compName;
        codecCap.codecType = GetCodecType(hdiCap.type);
        codecCap.mimeType = GetCodecMime(hdiCap.role);
        codecCap.isVendor = !hdiCap.isSoftwareCodec;
        codecCap.alignment = {hdiCap.port.video.whAlignment.widthAlignment, hdiCap.port.video.whAlignment.heightAlignment};
        codecCap.bitrateMode = GetBitrateMode(hdiCap.port.video);
        codecCap.width = {hdiCap.port.video.minSize.width, hdiCap.port.video.maxSize.width};
        codecCap.height = {hdiCap.port.video.minSize.height, hdiCap.port.video.maxSize.height};
        codecCap.bitrate = {hdiCap.bitRate.min, hdiCap.bitRate.max};
        codecCap.frameRate = {hdiCap.port.video.frameRate.min, hdiCap.port.video.frameRate.max};
        codecCap.format = GetCodecFormats(hdiCap.port.video);
        codecCap.blockPerFrame = {hdiCap.port.video.blockCount.min, hdiCap.port.video.blockCount.max};
        codecCap.blockPerSecond = {hdiCap.port.video.blocksPerSecond.min, hdiCap.port.video.blocksPerSecond.max};
        codecCap.blockSize = {hdiCap.port.video.blockSize.width, hdiCap.port.video.blockSize.height};
        codecCap.measuredFrameRate = GetMeasuredFrameRate(hdiCap.port.video);
        codecCap.profileLevelsMap = GetCodecProfileLevels(hdiCap);
        capabilitys_.push_back(codecCap);
    }
    

为了能让大家更好的学习鸿蒙(HarmonyOS NEXT)开发技术,这边特意整理了《鸿蒙开发学习手册》(共计890页),希望对大家有所帮助:https://qr21.cn/FV7h05

《鸿蒙开发学习手册》:

如何快速入门:https://qr21.cn/FV7h05

  1. 基本概念
  2. 构建第一个ArkTS应用
  3. ……

开发基础知识:https://qr21.cn/FV7h05

  1. 应用基础知识
  2. 配置文件
  3. 应用数据管理
  4. 应用安全管理
  5. 应用隐私保护
  6. 三方应用调用管控机制
  7. 资源分类与访问
  8. 学习ArkTS语言
  9. ……

基于ArkTS 开发:https://qr21.cn/FV7h05

  1. Ability开发
  2. UI开发
  3. 公共事件与通知
  4. 窗口管理
  5. 媒体
  6. 安全
  7. 网络与链接
  8. 电话服务
  9. 数据管理
  10. 后台任务(Background Task)管理
  11. 设备管理
  12. 设备使用信息统计
  13. DFX
  14. 国际化开发
  15. 折叠屏系列
  16. ……

鸿蒙开发面试真题(含参考答案):https://qr18.cn/F781PH

鸿蒙开发面试大盘集篇(共计319页):https://qr18.cn/F781PH

1.项目开发必备面试题
2.性能优化方向
3.架构方向
4.鸿蒙开发系统底层方向
5.鸿蒙音视频开发方向
6.鸿蒙车载开发方向
7.鸿蒙南向开发方向

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

uniapp h5项目实现多选按钮/多选标签/多选框

需求&#xff1a;实现简单多选功能&#xff0c;遍历数据&#xff0c;添加样式 1.效果图 2.以下代码粘贴到代码中&#xff0c;可直接运行&#xff0c;html代码 <view class"page index"><view class"list-box"><view v-for"(item,in…

智能网络新纪元:机器学习赋能未来计算机网络高速发展

&#x1f9d1; 作者简介&#xff1a;阿里巴巴嵌入式技术专家&#xff0c;深耕嵌入式人工智能领域&#xff0c;具备多年的嵌入式硬件产品研发管理经验。 &#x1f4d2; 博客介绍&#xff1a;分享嵌入式开发领域的相关知识、经验、思考和感悟,欢迎关注。提供嵌入式方向的学习指导…

赋能技术 助锂制造|青软青之助力锂电检测行业数字化升级

在全球范围内&#xff0c;新能源转型已成为时代的必然选择。随着“双碳”目标的深入推进&#xff0c;这一趋势愈发明显。而作为新能源领域的一颗璀璨明珠&#xff0c;锂电池的研发、产业链建设和技术创新&#xff0c;无疑是这场能源革命的核心所在。其产业链的日趋完善、技术的…

企业培训系统私有化解决方案:PlayEdu

PlayEdu&#xff1a;打造私有化的企业智慧教育平台&#xff0c;赋能全员高效成长&#xff01;- 精选真开源&#xff0c;释放新价值。 概览 随着企业不断发展及市场竞争加剧&#xff0c;内部培训的重要性日益凸显。然而&#xff0c;在实施过程中&#xff0c;如何确保培训内容与…

2024个人动态线条导航HTML源码

源码介绍 2024个人导航HTML源码&#xff0c;源码由HTMLCSSJS组成&#xff0c;记事本打开源码文件可以进行内容文字之类的修改&#xff0c;双击html文件可以本地运行效果&#xff0c;也可以上传到服务器里面&#xff0c;重定向这个界面 源码下载 2024个人导航HTML源码

进军俄罗斯市场,一站式Yandex广告开户与代运营服务

俄罗斯作为欧洲最大的经济体之一&#xff0c;拥有庞大的消费者群体和独特的市场环境&#xff0c;成为了众多国际商家关注的焦点。要有效地触达这片潜力无限的市场&#xff0c;精准且高效的网络营销策略至关重要。利用Yandex——俄罗斯最大的搜索引擎与数字广告平台&#xff0c;…

计算机网络-浏览器解析到URL对应的IP地址的时间

声明&#xff1a;原文转载链接出自&#xff1a; 哈工大Mooc——计算机网络&#xff1a;作业3 假设你在浏览某网页时点击了一个超链接&#xff0c;URL为“https://www.kicker.com.cn/index.html”&#xff0c;且该URL对应的IP地址在你的计算机上没有缓存&#xff1b;文件index…

路由器如何端口映射到外网?

随着互联网的发展和普及&#xff0c;远程访问已经成为了现代社会的一个重要需求。在复杂的网络环境下&#xff0c;特别是涉及异地组网的情况下&#xff0c;实现远程访问变得更加困难。本文将介绍一种名为【天联】的组网产品&#xff0c;它可以解决复杂网络环境下的远程连接问题…

最优算法100例之41-用两个栈实现队列

专栏主页:计算机专业基础知识总结(适用于期末复习考研刷题求职面试)系列文章https://blog.csdn.net/seeker1994/category_12585732.html 题目描述 用两个栈实现队列 题解报告 stack<int> stack1; stack<int> stack2; void push(int node) {stack1.push(node);…

极狐GitLab对接OAuth2实现SSO

本文作者&#xff1a;极狐(GitLab) 高级解决方案架构师 武让 GitLab 是一个全球知名的一体化 DevOps 平台&#xff0c;很多人都通过私有化部署 GitLab 来进行源代码托管。极狐GitLab 是 GitLab 在中国的发行版&#xff0c;专门为中国程序员服务。可以一键式部署极狐GitLab。 企…

windows停掉jenkins服务

在Windows系统中&#xff0c;如果你需要停止Jenkins服务&#xff0c; 使用服务管理器&#xff08;Service Manager&#xff09;: 打开“运行”对话框&#xff08;Win R&#xff09;&#xff0c;输入services.msc&#xff0c;然后回车。 在服务列表中找到“Jenkins”服务&am…

网工基础协议——IP地址

IP地址的概念&#xff1a; IP 地址是我们进行TCP/IP通讯的基础&#xff0c;每个连接到网络上的计算机都必须有一个!P地址。我们目前使用的IP地址是32位的&#xff0c;通常以点分十进制表示。例如:192.168.0.181。IP地址的格式为: IP地址 网络地址 主机地址 或者 |P地址主机地…

【Docker】docker快速安装部署fastdfs的镜像详细记录

部署nacos的docker镜像 第一步&#xff1a; 获取fastdfs镜像1、查看镜像列表2、创建本地映射文件夹 第二步&#xff1a;运行镜像1.使用docker镜像构建tracker服务2.使用docker镜像构建Storage服务3.Storage服务中默认安装了Nginx服务4.如果需要修改storage则配置则进到以下目录…

新手入门:大语言模型训练指南

在这个信息爆炸的时代&#xff0c;人工智能技术正以前所未有的速度渗透到我们生活的方方面面。从智能手机上的语音助手到自动驾驶汽车&#xff0c;AI的应用无处不在。而在这些令人惊叹的技术背后&#xff0c;大语言模型&#xff08;LLM&#xff09;扮演着至关重要的角色。它们不…

从 SQLite 3.4.2 迁移到 3.5.0(二十)

返回&#xff1a;SQLite—系列文章目录 上一篇:SQLite---调试提示&#xff08;十九&#xff09; 下一篇&#xff1a;SQLite—系列文章目录 ​ SQLite 版本 3.5.0 &#xff08;2007-09-04&#xff09; 引入了一个新的操作系统接口层&#xff0c; 与所有先前版本的 SQLi…

游戏测试审表流程

备注:本文为博主原创文章,未经博主允许禁止转载。如有问题,欢迎指正。 个人笔记(整理不易,有帮助,收藏+点赞+评论,爱你们!!!你的支持是我写作的动力) 笔记目录:笔记本~笔记目录_airtest和selenium那个好用-CSDN博客 个人随笔:工作总结随笔_8、以前工作中都接触过哪…

【MATLAB 预测算法教程】_1粒子群算法优化BP神经网络预测 - 教程和对应MATLAB代码

本文以MATLAB自带的脂肪数据集为例,将数据保存在EXCEL工作簿内,方便替换数据使用,以下介绍粒子群算法优化BP神经网络预测的MATLAB代码编写,主要流程包括1. 读取数据 2.划分训练集和测试集 3.归一化 4.确定BP神经网络的隐含层最优节点数量 5. 使用粒子群算法优化BP的神经网络…

为什么你选择成为一名程序员?

逐码探梦&#xff1a;我选择程序员之路 在数字化的纹理中编织梦想&#xff0c;于逻辑的海洋里追寻真理&#xff0c;程序员&#xff0c;这个职业对我而言不仅仅是一份工作&#xff0c;更是一扇通向无限可能性的大门。选择成为一名程序员&#xff0c;是一个交织着兴趣和职业规划…

数字IC/FPGA——复位篇

本文主要介绍以下几点&#xff1a; 复位的作用及什么时候需要复位复位的分类全局复位、局部复位的目的如何选择全局复位和局部复位同步复位、异步复位及异步复位同步释放的原理、优缺点 注&#xff1a;参考文章在文末给出 目录 一、复位信号的作用和分类1.复位信号的作用2.复…

浅尝一下ECS(Entity Component System)(学习笔记)

参考文章&#xff1a;浅谈Unity ECS&#xff08;一&#xff09;Uniy ECS基础概念介绍&#xff1a;面向未来的ECS - 知乎 (zhihu.com) 视频链接&#xff1a;【青幻译制】GDC讲座系列之三 守望先锋的游戏架构和网络代码_哔哩哔哩_bilibili 云风的 BLOG: 浅谈《守望先锋》中的 E…