OpenHarmony 3.2 Release版本实战开发——Codec HDI适配过程

news2024/10/5 17:22:18

简介

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);
    }
    

码牛课堂也为了积极培养鸿蒙生态人才,让大家都能学习到鸿蒙开发最新的技术,针对一些在职人员、0基础小白、应届生/计算机专业、鸿蒙爱好者等人群,整理了一套纯血版鸿蒙(HarmonyOS Next)全栈开发技术的学习路线。大家可以进行参考学习:https://qr21.cn/FV7h05

①全方位,更合理的学习路径
路线图包括ArkTS基础语法、鸿蒙应用APP开发、鸿蒙能力集APP开发、次开发多端部署开发、物联网开发等九大模块,六大实战项目贯穿始终,由浅入深,层层递进,深入理解鸿蒙开发原理!

②多层次,更多的鸿蒙原生应用
路线图将包含完全基于鸿蒙内核开发的应用,比如一次开发多端部署、自由流转、元服务、端云一体化等,多方位的学习内容让学生能够高效掌握鸿蒙开发,少走弯路,真正理解并应用鸿蒙的核心技术和理念。

③实战化,更贴合企业需求的技术点
学习路线图中的每一个技术点都能够紧贴企业需求,经过多次真实实践,每一个知识点、每一个项目,都是码牛课堂鸿蒙研发团队精心打磨和深度解析的成果,注重对学生的细致教学,每一步都确保学生能够真正理解和掌握。

为了能让大家更好的学习鸿蒙(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://qr21.cn/FV7h05

大厂鸿蒙面试题::https://qr18.cn/F781PH

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

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

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

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

相关文章

OpenMVS学习笔记(一):WSL编译安装测试

1.CUDA和CUDNN安装 [1] WSL版本cuda安装: >> wget https://developer.download.nvidia.com/compute/cuda/repos/wsl-ubuntu/x86_64/cuda-wsl-ubuntu.pin >> sudo mv cuda-wsl-ubuntu.pin /etc/apt/preferences.d/cuda-repository-pin-600 >> wg…

Burp Suite (bp)启动激活报错问题

一、自查 1、从哪里下载程序 【大部分同学的问题,都是重新下载解决的,简单快速直接】 一律使用“常用软件”中提供的Burp Suite软件包,方便排查问题 自带JDK的版本 Burp 2024.3,自带JDK21,双击bat即可启动&#xff…

YOLOv8网络结构介绍

将按照YOLOv8目标检测任务、实例分割任务、关键点检测任务以及旋转目标检测任务的顺序来介绍,主要内容也是在目标检测任务中介绍,其他任务也只是Head层不相同。 1.YOLOv8_det网络结构 首先,YOLOv8网络分成了三部分,分别是主干网络…

Java | Spring框架| 集合与复杂类型的注入:处理多值依赖

集合与复杂类型的注入:处理多值依赖 在Spring框架中,除了可以注入简单的依赖类型,如字符串、整数等,还可以注入集合类型和复杂类型的数据。集合类型包括List、Set、Map和数组,而复杂类型可以是自定义的对象、配置类等…

【JavaEE网络】用Form与Ajax构建HTTP请求

目录 通过 form 表单构造 HTTP 请求form 发送 GET 请求form 发送 POST 请求 通过 ajax 构造 HTTP 请求发送 GET 请求发送 POST 请求发送 application/json 数据封装 ajax 方法 通过 form 表单构造 HTTP 请求 form (表单) 是 HTML 中的一个常用标签. 可以用于给服务器发送 GET …

janus源码分析

基础说明 janus官网 https://janus.conf.meetecho.com/index.html janus源码地址 https://github.com/meetecho/janus-gateway 编译及部署参考 https://pro-hnb.blog.csdn.net/article/details/137730389?spm1001.2014.3001.5502 https://pro-hnb.blog.csdn.net/article/deta…

QT设计模式:策略模式

基本概念 策略模式(Strategy Pattern)是一种行为型设计模式,它定义了一系列方法,并使它们可以相互替换。策略模式使得算法可以独立于客户端而变化,使得客户端可以根据需要选择相应的算法。 策略模式通常由以下角色组…

AutoDL服务器远程桌面

文章目录 1.安装VNC和必要的一些图形显式库:2.SSH隧道2.1.本地安装openssh服务器2.2.服务开启2.3.显示当前安装的 SSH 版本信息2.3.设置一个 SSH 隧道 注意3.VNC Viewer客户端登录4.测试5.参考 VNC(Virtual Network Computing )是一种图形化的桌面共享协…

mac电脑如何安装java

1、检查当前系统的 Java 版本 打开终端,输入以下命令查看当前 Java 版本 /usr/bin/java -version 2、前往 Java 官网下载 Java JDK 打开 Java 官网 (https://www.java.com/zh-CN/download/) 并下载最新版本的 Java JDK。 3、安装 Java JDK 双击下载的 .dmg 文件启动安装程序…

力扣爆刷第135天之数组五连刷(双指针快慢指针滑动窗口)

力扣爆刷第135天之数组五连刷(双指针快慢指针滑动窗口) 文章目录 力扣爆刷第135天之数组五连刷(双指针快慢指针滑动窗口)一、704. 二分查找二、27. 移除元素三、977. 有序数组的平方四、209. 长度最小的子数组五、59. 螺旋矩阵 II…

【C++初阶】第十站:vector 中通用函数的模拟实现

目录 vector中的三个重要迭代器 默认成员函数 构造函数(无参构造) 构造函数(函数模板) 构造函数(带有默认参数) size_t int 拷贝构造函数 赋值重载 析构函数 迭代器相关函数 begin和end 容量和大小相关函数 size capacity resize 修改容器内容相关函数 reser…

自动驾驶学习2-毫米波雷达

1、简介 1.1 频段 毫米波波长短、频段宽,比较容易实现窄波束,雷达分辨率高,不易受干扰。波长介于1~10mm的电磁波,频率大致范围是30GHz~300GHz 毫米波雷达是测量被测物体相对距离、相对速度、方位的高精度传感器。 车载毫米波雷达主要有24GHz、60GHz、77GHz、79GHz四个频段。 …

使用Postman进行接口测试---解析postman页面

一、Postman 是一款流行的 API 测试工具,它提供了丰富的功能来帮助开发者测试和调试 API。以下是 Postman 页面上的主要功能及其含义和作用: 1. 请求详情(Request Details) : - 方法(Method&#xff0…

Disk Doctor for Mac 免激活版:数据安全守卫者

数据丢失是每个人都可能遇到的问题,但Disk Doctor for Mac能让这个问题迎刃而解。这款强大的数据恢复软件,能迅速找回因各种原因丢失的数据。 Disk Doctor采用先进的扫描技术,能深入剖析磁盘,找到并恢复被删除或损坏的文件。同时&…

JavaScript 进阶征途:解锁Function奥秘,深掘Object方法精髓

个人主页:学习前端的小z 个人专栏:JavaScript 精粹 本专栏旨在分享记录每日学习的前端知识和学习笔记的归纳总结,欢迎大家在评论区交流讨论! 文章目录 🈵Function方法 与 函数式编程💝1 call &#x1f49d…

竞赛课第十周(巴什游戏,尼姆博弈)

目录 目的: 实验内容: 第一题 思路: 【参考代码】 【运行结果】 第二题 输入: 输出: 【参考代码】 【运行结果】 目的: 熟悉并掌握公平组合游戏 (1)巴什游戏、尼姆游戏 (2)图游戏…

rs485自动收发电路

R/RO:receive/receive out,接收,连接单片机的 rx D/DI:drive/drive in,驱动,连接单片机的 tx 自动控制电路的目的就是在 tx 空闲(空闲为高并)时拉低 RE 和 DE,工作&…

B/S模式的web通信

这里写目录标题 目标实现的目标 服务器代码(采用epoll实现服务器)整体框架main函数init_listen_fd函数(负责对lfd初始化的那一系列操作)epoll_run函数 一级目录二级目录二级目录二级目录 目标 实现的目标 我们要实现,…

Hive-URL解析函数

Hive-URL解析函数 1.实际工作需求 2.URL的基本组成 3.Hive中的Url解析函数 parse_url函数 parse_url_tuple函数

Nacos Docker 快速部署----解决nacos鉴权漏洞问题

Nacos Docker 快速部署 1. 说明 1.1 官方文档 官方地址 https://nacos.io/zh-cn/docs/v2/quickstart/quick-start.html docker启动文件的gitlhub地址 https://github.com/nacos-group/nacos-docker.git 问题: 缺少部分必要配置与说明 1.2 部署最新版本Nacos&…