OpenHarmony 3.2 Release版本Codec HDI适配过程

2024-04-12 08:04

本文主要是介绍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.鸿蒙南向开发方向

这篇关于OpenHarmony 3.2 Release版本Codec HDI适配过程的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/896566

相关文章

Python一次性将指定版本所有包上传PyPI镜像解决方案

《Python一次性将指定版本所有包上传PyPI镜像解决方案》本文主要介绍了一个安全、完整、可离线部署的解决方案,用于一次性准备指定Python版本的所有包,然后导出到内网环境,感兴趣的小伙伴可以跟随... 目录为什么需要这个方案完整解决方案1. 项目目录结构2. 创建智能下载脚本3. 创建包清单生成脚本4

oracle 11g导入\导出(expdp impdp)之导入过程

《oracle11g导入导出(expdpimpdp)之导入过程》导出需使用SEC.DMP格式,无分号;建立expdir目录(E:/exp)并确保存在;导入在cmd下执行,需sys用户权限;若需修... 目录准备文件导入(impdp)1、建立directory2、导入语句 3、更改密码总结上一个环节,我们讲了

ShardingProxy读写分离之原理、配置与实践过程

《ShardingProxy读写分离之原理、配置与实践过程》ShardingProxy是ApacheShardingSphere的数据库中间件,通过三层架构实现读写分离,解决高并发场景下数据库性能瓶... 目录一、ShardingProxy技术定位与读写分离核心价值1.1 技术定位1.2 读写分离核心价值二

MyBatis-plus处理存储json数据过程

《MyBatis-plus处理存储json数据过程》文章介绍MyBatis-Plus3.4.21处理对象与集合的差异:对象可用内置Handler配合autoResultMap,集合需自定义处理器继承F... 目录1、如果是对象2、如果需要转换的是List集合总结对象和集合分两种情况处理,目前我用的MP的版本

Ubuntu如何升级Python版本

《Ubuntu如何升级Python版本》Ubuntu22.04Docker中,安装Python3.11后,使用update-alternatives设置为默认版本,最后用python3-V验证... 目China编程录问题描述前提环境解决方法总结问题描述Ubuntu22.04系统自带python3.10,想升级

Java Kafka消费者实现过程

《JavaKafka消费者实现过程》Kafka消费者通过KafkaConsumer类实现,核心机制包括偏移量管理、消费者组协调、批量拉取消息及多线程处理,手动提交offset确保数据可靠性,自动提交... 目录基础KafkaConsumer类分析关键代码与核心算法2.1 订阅与分区分配2.2 拉取消息2.3

AOP编程的基本概念与idea编辑器的配合体验过程

《AOP编程的基本概念与idea编辑器的配合体验过程》文章简要介绍了AOP基础概念,包括Before/Around通知、PointCut切入点、Advice通知体、JoinPoint连接点等,说明它们... 目录BeforeAroundAdvise — 通知PointCut — 切入点Acpect — 切面

C++ STL-string类底层实现过程

《C++STL-string类底层实现过程》本文实现了一个简易的string类,涵盖动态数组存储、深拷贝机制、迭代器支持、容量调整、字符串修改、运算符重载等功能,模拟标准string核心特性,重点强... 目录实现框架一、默认成员函数1.默认构造函数2.构造函数3.拷贝构造函数(重点)4.赋值运算符重载函数

MySQ中出现幻读问题的解决过程

《MySQ中出现幻读问题的解决过程》文章解析MySQLInnoDB通过MVCC与间隙锁机制在可重复读隔离级别下解决幻读,确保事务一致性,同时指出性能影响及乐观锁等替代方案,帮助开发者优化数据库应用... 目录一、幻读的准确定义与核心特征幻读 vs 不可重复读二、mysql隔离级别深度解析各隔离级别的实现差异

Nginx添加内置模块过程

《Nginx添加内置模块过程》文章指导如何检查并添加Nginx的with-http_gzip_static模块:确认该模块未默认安装后,需下载同版本源码重新编译,备份替换原有二进制文件,最后重启服务验... 目录1、查看Nginx已编辑的模块2、Nginx官网查看内置模块3、停止Nginx服务4、Nginx