openharmony之AV_CodeC音视频编解码模块详解(一)
AV_CODEC是OpenHarmony多媒体系统的核心组件,专门负责音视频编解码处理。音视频编解码音视频解封装音视频封装。
·
🎯 模块概述
AV_CODEC 是OpenHarmony多媒体系统的核心组件,专门负责音视频编解码处理。
av_codec部件提供了以下常用功能:
- 音视频编解码
- 音视频解封装
- 音视频封装
API18之前支持情况
API18之后
关于该模块的函数调用链可查看我的前期文章进行详细学习
🏗️ 系统架构
整体架构图
┌─────────────────────────────────────────────────────────┐
│ 应用层 (Application) │
├─────────────────────────────────────────────────────────┤
│ 框架接口层 (Framework API) │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ native_avcodec_base.h - 基础定义和通用接口 │ │
│ │ native_avcodec_videocodec.h - 视频编解码接口 │ │
│ │ native_avcodec_audiocodec.h - 音频编解码接口 │ │
│ │ native_avcodec_demuxer.h - 解复用接口 │ │
│ └─────────────────────────────────────────────────────┘ │
├─────────────────────────────────────────────────────────┤
│ 服务层 (Codec Service) │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ AVCodecService │ │
│ │ ├─ 视频编解码器管理 (H.264/H.265/VP8/VP9) │ │
│ │ ├─ 音频编解码器管理 (AAC/MP3/FLAC/WAV) │ │
│ │ ├─ 格式转换和转码 │ │
│ │ └─ 硬件加速调度 │ │
│ └─────────────────────────────────────────────────────┘ │
├─────────────────────────────────────────────────────────┤
│ 引擎层 (Codec Engine) │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ 硬件编解码器 (HW Codec) │ │
│ │ ├─ 支持4K@60fps硬件解码 │ │
│ │ ├─ 低功耗硬件编码 │ │
│ │ └─ 多路并发处理 │ │
│ │ │ │
│ │ 软件编解码器 (SW Codec) │ │
│ │ ├─ 通用软件编解码 │ │
│ │ └─ 格式兼容性保证 │ │
│ └─────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────┘
实现细节(ArkTs):
视频解码部分
- 用户点击播放按钮后,触发点击事件,调起PhotoViewPicker()接口,该函数会调起图库的选择文件模块,拿到用户选取视频的路径;
- 用户选择文件成功后,playNative()接口调用PlayerNative::Play()函数,进行初始化并调用解码模块开始解码;
- 解码器Start后,输入回调会调起,将待解码的数据填入OH_AVBuffer中,调用PushInputBuffer接口,送给解码器解码,每次Start后,至少要Push一次XPS帧;
- 解码器每解出来一帧,输出回调就会调起一次,用户需要及时调用送显或释放接口,归还buffer给解码器,由于解码器的buffer数量有上限,需要及时归还,否则达到上限后解码器就会停止工作,直到有buffer被归还;
- 播放结束时,Callback()中napi_call_function()接口调起,执行对应的回调事件。
音画同步部分
- 收到视频帧的时候,通过调用OH_AudioRenderer_GetTimestamp()接口获取音频渲染位置等信息。
- 音频未启动前,为避免出现卡顿等问题,暂不同步,视频帧直接送显。
- 音频启动后,根据视频帧pts和音频渲染位置计算延迟,根据延迟选择音画同步策略:
- 视频帧晚于音频帧40ms以上,直接丢弃此视频帧;
- 视频帧晚于音频帧40ms以下,直接送显;
- 视频帧早于音频帧时,进行渐进同步,等待一段时间送显。
🔧 核心功能特性
1. 视频编解码能力
支持的视频格式
-
解码器支持:
- H.264/AVC (Baseline, Main, High Profile)
- H.265/HEVC (Main, Main10 Profile)
- VP8 (WebM容器)
- VP9 (WebM容器)
- MPEG-4 Part 2
-
编码器支持:
- H.264/AVC (Baseline, Main, High Profile)
- H.265/HEVC (Main Profile)
-
分辨率支持:
- 最小: QCIF (176×144)
- 最大: 4K@60fps (3840×2160)
- 支持8K@30fps (部分硬件)
色彩空间支持
- NV12 (YUV420SP)
- NV21 (YUV420SP)
- YUV420P (I420)
- RGB565, RGB888, RGBA8888
- HDR10 (部分硬件支持)
2. 音频编解码能力
支持的音频格式
-
解码器支持:
- AAC-LC, HE-AAC, HE-AACv2
- MP3 (MPEG-1/2 Layer III)
- FLAC (无损音频)
- WAV (PCM)
- AMR-NB, AMR-WB
- Vorbis
-
编码器支持:
- AAC-LC (Low Complexity)
- WAV (PCM 16bit/24bit)
音频参数支持
- 采样率: 8kHz - 192kHz
- 位深度: 16bit, 24bit, 32bit
- 声道数: 单声道, 立体声, 5.1环绕声
📁 模块文件结构
核心接口文件
foundation/multimedia/av_codec/
├── interfaces/kits/c/ # C语言接口
│ ├── native_avcodec_base.h # 基础定义和通用接口
│ ├── native_avcodec_videocodec.h # 视频编解码器接口
│ ├── native_avcodec_audiocodec.h # 音频编解码器接口
│ ├── native_avcodec_demuxer.h # 解复用器接口
│ └── native_avcodec_muxer.h # 复用器接口
├── interfaces/inner_api/native/ # 内部接口
│ ├── avcodec_errors.h # 错误码定义
│ └── codec_capability.h # 编解码器能力查询
示例代码目录(ArkTs应用层)
applications/standard/app_samples/code/BasicFeature/Media/
├── AudioToVideoSync/ # 音视频同步示例
│ ├── entry/src/main/cpp/
│ │ ├── capabilities/Demuxer.cpp # 解复用实现
│ │ ├── capabilities/VideoDecoder.cpp # 视频解码
│ │ ├── capabilities/AudioDecoder.h # 音频解码
│ │ └── capabilities/VideoEncoder.cpp # 视频编码
├── VideoPlayer/ # 视频播放器
└── AudioRecorder/ # 音频录制器
💻 开发使用指南
1. 视频解码完整流程
步骤1: 创建解码器
#include "multimedia/player_framework/native_avcodec_videocodec.h"
// 根据MIME类型创建视频解码器
OH_AVCodec *videoDecoder = OH_VideoDecoder_CreateByMime("video/avc");
if (!videoDecoder) {
printf("Failed to create video decoder\n");
return -1;
}
步骤2: 配置解码参数
// 创建格式配置
OH_AVFormat *format = OH_AVFormat_Create();
if (!format) {
printf("Failed to create format\n");
return -1;
}
// 设置视频参数
OH_AVFormat_SetIntValue(format, OH_MD_KEY_WIDTH, 1920);
OH_AVFormat_SetIntValue(format, OH_MD_KEY_HEIGHT, 1080);
OH_AVFormat_SetIntValue(format, OH_MD_KEY_PIXEL_FORMAT, AV_PIXEL_FORMAT_NV12);
OH_AVFormat_SetDoubleValue(format, OH_MD_KEY_FRAME_RATE, 30.0);
// 配置解码器
int32_t ret = OH_VideoDecoder_Configure(videoDecoder, format);
if (ret != AV_ERR_OK) {
printf("Configure failed: %d\n", ret);
return -1;
}
步骤3: 设置回调函数
// 定义回调结构体
OH_AVCodecCallback callback = {
.onError = [](OH_AVCodec *codec, int32_t errorCode, void *userData) {
printf("Decoder error: %d\n", errorCode);
},
.onStreamChanged = [](OH_AVCodec *codec, OH_AVFormat *format, void *userData) {
printf("Stream format changed\n");
},
.onNeedInputBuffer = [](OH_AVCodec *codec, uint32_t index, OH_AVBuffer *buffer, void *userData) {
// 输入压缩数据
printf("Need input buffer: %u\n", index);
},
.onNewOutputBuffer = [](OH_AVCodec *codec, uint32_t index, OH_AVBuffer *buffer, void *userData) {
// 获取解码后的视频帧
printf("New output buffer: %u\n", index);
}
};
OH_VideoDecoder_SetCallback(videoDecoder, callback, nullptr);
步骤4: 启动解码器
// 启动解码
int32_t ret = OH_VideoDecoder_Start(videoDecoder);
if (ret != AV_ERR_OK) {
printf("Start failed: %d\n", ret);
return -1;
}
2. 音频编码完整流程
步骤1: 创建编码器
#include "multimedia/player_framework/native_avcodec_audiocodec.h"
// 创建AAC音频编码器
OH_AVCodec *audioEncoder = OH_AudioEncoder_CreateByMime("audio/mp4a-latm");
步骤2: 配置音频参数
OH_AVFormat *format = OH_AVFormat_Create();
OH_AVFormat_SetIntValue(format, OH_MD_KEY_AUD_SAMPLE_RATE, 44100);
OH_AVFormat_SetIntValue(format, OH_MD_KEY_AUD_CHANNEL_COUNT, 2);
OH_AVFormat_SetIntValue(format, OH_MD_KEY_AUDIO_SAMPLE_FORMAT, AV_SAMPLE_FORMAT_S16);
OH_AVFormat_SetIntValue(format, OH_MD_KEY_BITRATE, 128000); // 128kbps
OH_AudioEncoder_Configure(audioEncoder, format);
3. 解复用器使用示例
从MP4文件中提取音视频流
#include "multimedia/player_framework/native_avcodec_demuxer.h"
// 创建解复用器
OH_AVDemuxer *demuxer = OH_AVDemuxer_Create();
OH_AVDemuxer_SetDataSource(demuxer, "input.mp4");
// 获取轨道信息
int32_t trackCount = OH_AVDemuxer_GetTrackCount(demuxer);
for (int32_t i = 0; i < trackCount; i++) {
OH_AVFormat *trackFormat = OH_AVDemuxer_GetTrackFormat(demuxer, i);
int32_t trackType;
OH_AVFormat_GetIntValue(trackFormat, OH_MD_KEY_TRACK_TYPE, &trackType);
if (trackType == MEDIA_TYPE_VID) {
// 视频轨道
OH_AVDemuxer_SelectTrackByID(demuxer, i);
} else if (trackType == MEDIA_TYPE_AUD) {
// 音频轨道
OH_AVDemuxer_SelectTrackByID(demuxer, i);
}
}
编译构建
编译32位ARM系统av_codec部件
./build.sh --product-name {product_name} --ccache --build-target av_codec
编译64位ARM系统av_codec部件
./build.sh --product-name {product_name} --ccache --target-cpu arm64 --build-target av_codec
{product_name}为当前支持的平台,比如rk3568。
🎬 实际应用场景
1. 视频播放器
- 功能: 播放本地/网络视频文件
- 支持格式: MP4, MKV, AVI, MOV, FLV
- 特性: 硬件加速解码,音视频同步,倍速播放
2. 视频通话应用
- 功能: 实时视频通话
- 编解码: H.264实时编码,低延迟传输
- 特性: 自适应码率,网络容错,回声消除
3. 屏幕录制工具
- 功能: 录制设备屏幕操作
- 流程: 屏幕捕获 → 视频编码 → 音频混合 → 文件保存
- 输出: MP4文件,支持1080P@60fps
4. 视频编辑应用
- 功能: 视频剪辑、转码、特效处理
- 特性: 多轨道编辑,实时预览,批量转码
- 输出: 支持多种分辨率和码率配置
📊 性能指标
硬件加速性能
- 4K解码: 60fps稳定播放,CPU占用<30%
- 1080P编码: 30fps实时编码,功耗<500mW
- 多路并发: 支持4路1080P同时解码
软件编解码性能
- 兼容性: 100%格式支持
- 效率: 相比硬件编码,CPU占用增加50-80%
- 适用场景: 非标准格式或特殊需求
🔍 调试和优化
1. 性能分析工具
# 查看编解码器能力
hdc shell "hidumper -s 10 -a -c"
# 监控编解码性能
hdc shell "top -p codec_service_pid"
2. 日志调试
// 设置日志级别
OH_AVCodec_SetLogLevel(AV_LOG_LEVEL_DEBUG);
// 获取编解码器信息
OH_AVFormat *codecInfo = OH_VideoDecoder_GetCodecDescription(decoder);
3. 内存优化
- 零拷贝设计: 减少数据拷贝,降低内存占用
- 内存池管理: 预分配内存,避免频繁分配释放
- 大页支持: 提升TLB命中率,改善性能
🚀 开发最佳实践
1. 选择合适的编解码器
- 优先使用硬件: 性能更好,功耗更低
- 格式标准化: 使用标准格式确保兼容性
- 参数优化: 根据设备能力调整分辨率/码率
2. 错误处理策略
- 预判检查: 提前检查设备能力
- 优雅降级: 硬件失败时切换到软件编解码
- 资源清理: 确保异常情况下正确释放资源
3. 性能优化建议
- 异步处理: 使用异步回调避免阻塞主线程
- 批量处理: 减少系统调用次数
- 缓存策略: 合理使用输入输出缓冲区
更多推荐

所有评论(0)