HarmonyOS 鸿蒙Next求助:OpenHarmony 5.0.3.135 上硬件解码 YUV 数据花屏,参考官方 AVCodec 示例时遇到 API 版本不匹配问题
HarmonyOS 鸿蒙Next求助:OpenHarmony 5.0.3.135 上硬件解码 YUV 数据花屏,参考官方 AVCodec 示例时遇到 API 版本不匹配问题 各位大佬好,我在使用 DevEco Studio 开发鸿蒙电视应用时,遇到了一个关于硬件解码的问题,折腾了几天没有解决,特来求助。
环境:
- 系统版本:OpenHarmony 5.0.3.135(电视)
- 开发工具:DevEco Studio
- 功能:使用硬件解码器解码视频,提取 YUV 数据进行后续处理
问题现象: 在应用中调用硬件解码器(AVCodec)解码视频后,从输出回调中获取的 YUV 数据是花屏/乱码的。但如果切换到软件解码,数据完全正常。为了排除我代码逻辑的问题,我准备参考官方 Sample,用系统自带视频播放器播放正常,但是不知道系统用的是硬解还是软解。
参考官方的尝试:
我找到了 OpenHarmony 官方应用示例仓库中的 AVCodec 示例:
https://gitcode.com/openharmony/applications_app_samples/blob/master/code/BasicFeature/Media/AVCodec
该示例的 README 明确写着**“基于 API12 构建”**。
遇到的矛盾点:
-
SDK 版本号异常: 在该项目的
build_profile.json5中,我看到了如下配置: module_profile.json5"products": [ { "name": "default", "signingConfig": "default", "compileSdkVersion": 26, "compatibleSdkVersion": 26, "targetSdkVersion": 26, "runtimeOS": "OpenHarmony", } ]这里的
compileSdkVersion等版本号填的是 26。但是在 DevEco Studio 中,OpenHarmony 的 SDK 最高只到 23。这个 “26” 不知道是怎么来的,是笔误还是特殊版本? -
改成 API 12 后编译报错: 我尝试将版本号改为 DevEco Studio 中可选的 API 12(版本号 23)后,项目出现大量编译错误,提示各种 API 不存在或头文件找不到。这说明示例代码很可能依赖了更高版本的 SDK 接口,与当前 OpenHarmony 5.0.3.135 所提供的 API 12 不完全兼容。这是什么情况?
我的核心疑问:
- 如果要在这个系统版本上稳定使用硬件解码并正常提取 YUV 数据,应该参考哪个版本的 Sample 或文档?目前的 Sample 不能编译。
- 哪位大佬在类似的 OpenHarmony 版本上成功实现过硬件解码->获取 YUV 数据->处理或保存的流程?能否分享一下关键的配置步骤或代码片段?我的核心目标就是让硬件解码出来的 YUV 数据不花屏。
我已经确认过:
- 解码器的
surface模式我没有用(因为需要提取数据,所以用的是buffer模式)。 - 输入码流格式是正确的(annexB,包含 sps/pps)。
- 软解输出正常,说明输入数据没问题。
恳请各位有经验的大佬指点迷津,非常感谢!
(附:如果有朋友成功在 OpenHarmony 5.0.3.x 上运行过上述 AVCodec Sample,也请告知一下您的开发环境配置,谢谢!)
更多关于HarmonyOS 鸿蒙Next求助:OpenHarmony 5.0.3.135 上硬件解码 YUV 数据花屏,参考官方 AVCodec 示例时遇到 API 版本不匹配问题的实战教程也可以访问 https://www.itying.com/category-93-b0.html
历史版本的Samples可以去Tag里找找。
https://gitcode.com/openharmony/applications_app_samples/tags
花屏可以看看:视频播放花屏

更多关于HarmonyOS 鸿蒙Next求助:OpenHarmony 5.0.3.135 上硬件解码 YUV 数据花屏,参考官方 AVCodec 示例时遇到 API 版本不匹配问题的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html
您好,我尝试在框架层dump下硬解码数据 mkdir /data/misc/hcodecdump;chmod 777 /data/misc/hcodecdump/;param set hcodec.dump 1
发现解码后的yuv数据已经花屏
试试其他工具(比如ffmpeg)解出来,看看正常不。然后设置硬解的参数。
软解是正常的,现在我改用surface直接渲染正常了,不再取出数据使用opengl渲染
- 验证:
hilog | grep "CreateCodecBy"应含 hardware;输入码流需 Annex-B 格式(起始码 0x00000001)。 - 若遇 NV12_TILE 且 Pixelmap 无效,可用
libyuv::NV12TileToNV12转换(仅调试)。按上述步骤修改后硬解输出 YUV 正常。
您好,感谢您的回复!我怀疑现在硬件解码的输出就是NV12_TILE格式,我是用的一块openharmony电视板卡,芯片型号是hi3781v735,我查了一下NV12_TILE也有多种格式,我该怎么知道输出的是哪一种呢?而且我看了一下libyuv库,里面并没有NV12Tile相关的转换函数。期待您的回复!谢谢!
您好,我通过重新排列解码后的yuv数据后可以正常显示,但是这个排列方式是从多种方式中测试出来的,我看好像也没有api可以获取这种排列方式,format就一个字段显示为NV12格式
我这边建议先把“示例工程版本不匹配”和“硬解输出花屏”分开看。示例里的 compileSdkVersion 26 更像是当前样例仓库跟你本机 OpenHarmony SDK 不在同一分支,不能直接把 26 改成 23 编译;在 5.0.3.135 上应以设备 SDK 对应的 AVCodec C API 文档和本机头文件为准,把核心 Buffer 模式流程移过去。
花屏优先查 YUV 跨距。视频解码文档里 Buffer 模式输出的是解码后的 AVBuffer,硬件解码输出通常会按对齐宽高存放,不一定是紧凑的 width * height * 3 / 2。软解正常、硬解花屏时,常见原因就是按真实宽高直接 dump,没有处理 wStride、hStride 和像素格式。
在第一帧输出或 OnStreamChanged 后先取输出描述:
OH_AVFormat* fmt = OH_VideoDecoder_GetOutputDescription(codec);
int32_t w = 0, h = 0, wStride = 0, hStride = 0, pix = 0;
OH_AVFormat_GetIntValue(fmt, OH_MD_KEY_VIDEO_PIC_WIDTH, &w);
OH_AVFormat_GetIntValue(fmt, OH_MD_KEY_VIDEO_PIC_HEIGHT, &h);
OH_AVFormat_GetIntValue(fmt, OH_MD_KEY_VIDEO_STRIDE, &wStride);
OH_AVFormat_GetIntValue(fmt, OH_MD_KEY_VIDEO_SLICE_HEIGHT, &hStride);
OH_AVFormat_GetIntValue(fmt, OH_MD_KEY_PIXEL_FORMAT, &pix);
OH_AVFormat_Destroy(fmt);
然后按行拷贝:Y 平面拷贝 h 行,每行从源 wStride 中取 w 字节;NV12/NV21 的 UV 平面拷贝 h / 2 行,同样每行取 w 字节。处理完成后及时 OH_VideoDecoder_FreeOutputBuffer()。另外 Flush、Reset、Stop 后重新 Start 要重新送 SPS/PPS,AnnexB 多 slice 也要保证同一帧一次送入。
参考来源:视频解码开发指导:https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/video-decoding
参考来源:Buffer 模式转码最佳实践:https://developer.huawei.com/consumer/cn/doc/best-practices/bpta-buffer-mode-transcoding
您好,上述这些format参数我都对比过了,都是正常的,我怀疑硬解后是NV12Tile格式
format info: width=1920 height=1080 stride=1920 slice_height=1080 crop_top=0 crop_bottom=1079 crop_left=0 crop_right=1919 display_width=1920 display_height=1080 color_format=2 size=311040
期待HarmonyOS能在未来带来更多创新的技术和理念。
请提供需要转换的HTML内容。
您好,我通过重新排列解码后的yuv数据后可以正常显示,但是这个排列方式是从多种方式中测试出来的,我看好像也没有api可以获取这种排列方式,format就一个字段显示为NV12格式
解码后的yuv数据已经花屏说明是驱动问题。排查一下解码前送下来的数据把
赞,
OpenHarmony 5.0.3.135 对应的 API level 可能与官方示例版本不一致,导致 AVCodec 接口参数(如像素格式、对齐要求)不匹配,进而引起硬件解码花屏。请确认开发环境 SDK 版本与设备固件版本一致,并检查解码输出 YUV 的 stride 和 color space 是否正确设置。
OpenHarmony 5.0.3.135 对应 API 12,compileSdkVersion 应为 12,你看到的 26 是 HarmonyOS NEXT 的 SDK 版本号,二者不兼容。从 applications_app_samples 仓库切换到 OpenHarmony-5.0-Release 分支,就能取到正确的 AVCodec 示例,编译不会报错。
花屏的直接原因:硬件解码输出 buffer 的 YUV(通常 NV12)存在内存对齐,stride(行跨距)通常大于图像宽,且 slice_height 可能也大于高。你如果按宽×高连续拷贝,UV 平面会错位,必定花屏。软解内部做了对齐转换,所以正常。
解决方法:解码器回调拿到 OH_AVBuffer 或 OH_AVMemory 后,先通过 OH_AVFormat 获取实际 stride(OH_MD_KEY_VIDEO_STRIDE / "STRIDE")、slice_height、pixel_format,然后逐行 memcpy。下面以 NV12 buffer 模式为例,给出核心拷贝逻辑(无需 surface):
// 回调中获取 OH_AVBuffer *buffer
OH_AVFormat *format = OH_AVBuffer_GetFormat(buffer);
int32_t width, height, stride, sliceHeight, pixelFmt;
OH_AVFormat_GetIntValue(format, OH_MD_KEY_WIDTH, &width);
OH_AVFormat_GetIntValue(format, OH_MD_KEY_HEIGHT, &height);
OH_AVFormat_GetIntValue(format, OH_MD_KEY_VIDEO_STRIDE, &stride);
OH_AVFormat_GetIntValue(format, OH_MD_KEY_VIDEO_SLICE_HEIGHT, &sliceHeight);
OH_AVFormat_GetIntValue(format, OH_MD_KEY_PIXEL_FORMAT, &pixelFmt); // 预期 NV12:2
uint8_t *srcData = OH_AVBuffer_GetAddr(buffer);
size_t ySize = stride * sliceHeight; // Y 平面大小
uint8_t *uvSrc = srcData + ySize; // UV 交叉平面
int uvStride = stride; // UV 通常与 Y 一致
// 拷贝到你的连续 YUV planar buffer (yBuf, uvBuf 预分配 width*height 大小)
for (int i = 0; i < height; i++) {
memcpy(yBuf + i * width, srcData + i * stride, width);
}
for (int i = 0; i < height / 2; i++) { // NV12 UV 高度为 1/2
memcpy(uvBuf + i * width, uvSrc + i * uvStride, width); // UV 交叉: u、v 交替
}
// 用完释放 buffer
OH_VideoDecoder_FreeOutputBuffer(decoder, bufferIndex);
关键点:配置解码器时设置 OH_MD_KEY_PIXEL_FORMAT = PIXEL_FORMAT_NV12(2),不绑定 surface。校验 stride 是否与硬件对齐相关(常为 64 或 16 的倍数),按 stride 逐行搬数据,丢弃 padding 部分,即可得到正常的 YUV 数据。


