You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Hololens 2 WebRTC开启VideoStabilizationEnabled后ConvertToI420异常

HoloLens 2 WebRTC开启视频防抖后libyuv帧转换异常排查方案

问题根因

开启MRC视频防抖效果后,系统会自动对采集画面做边缘裁剪、对齐、缓冲处理,输出帧的实际分辨率、数据长度、像素格式不会和防抖关闭时的初始采集参数完全一致;原有代码直接复用初始化时缓存的固定分辨率、帧长度、格式参数传入libyuv::ConvertToI420,参数和实际帧数据不匹配,就会触发转换失败。
你遇到的帧长度异常可以直接验证:错误值497664恰好是768×432分辨率下NV12(YUV420)格式的标准帧长度(计算逻辑:768×432×3/2=497664),就是防抖自动裁剪边缘后输出了更低分辨率的帧,代码还按原896×504分辨率做参数校验和转换,必然出错。

排查解决步骤

  • 每帧实时读取输出帧的真实属性,禁止复用初始化缓存的固定参数
    防抖开启后帧属性可能动态变化,不要在采集初始化时读一次width/height/fourcc就全局复用,拿到每帧sample时直接从帧对象中读取实时参数:
    • 从帧对应的SoftwareBitmap对象读取真实PixelWidth、PixelHeight,不要用预设的896、504
    • 直接从帧的PixelBuffer.Length属性读取真实帧长度,不要自己按预设分辨率计算videoFrameLength
    • 校验当前帧的实际像素格式,确认映射到libyuv对应的FourCC枚举值,不要固定用初始化时记录的格式
  • 调整MRC防抖配置,关闭自动缩放裁剪
    你当前设置的15帧缓冲长度过大,HoloLens 2的MRC防抖会根据缓冲长度动态调整裁剪幅度,缓冲越大裁剪范围越大、输出分辨率缩水越明显,按如下方式修改配置:
    // 缓冲长度调整为3-5帧,平衡防抖效果和裁剪幅度
    mrcVideoEffectDefinition.VideoStabilizationBufferLength(3);
    // 强制防抖输出和采集预设一致的NV12格式、896×504分辨率,禁止自动降分辨率
    auto outputProps = Windows::Media::MediaProperties::VideoEncodingProperties::CreateUncompressed(
        Windows::Media::MediaProperties::MediaEncodingSubtypes::Nv12, 896, 504
    );
    mrcVideoEffectDefinition.OutputResolution(outputProps);
    
  • 修正ConvertToI420传参逻辑
    将原有传入固定缓存参数的逻辑替换为实时读取的帧参数,参考修改如下:
    // 从当前帧实时获取参数
    auto currentBitmap = mediaFrame.VideoMediaFrame().SoftwareBitmap();
    uint32_t actualWidth = currentBitmap.PixelWidth();
    uint32_t actualHeight = currentBitmap.PixelHeight();
    uint32_t actualFrameLen = currentBitmap.PixelBuffer().Length();
    // 自行实现像素格式到libyuv FourCC的映射,NV12对应libyuv::FOURCC_NV12
    uint32_t actualFourcc = ConvertBitmapFormatToFourCC(currentBitmap.BitmapPixelFormat());
    
    const int conversionResult = libyuv::ConvertToI420(
      videoFrame, actualFrameLen, buffer.get()->MutableDataY(),
      buffer.get()->StrideY(), buffer.get()->MutableDataU(),
      buffer.get()->StrideU(), buffer.get()->MutableDataV(),
      buffer.get()->StrideV(), 0, 0,  // 无裁剪
      actualWidth, actualHeight, target_width, target_height, rotation_mode,
      actualFourcc);
    
  • 校验帧步长(stride)匹配
    部分场景下防抖输出的帧会带内存对齐用的padding字节,行步长和width*像素字节数不一致,不要自行计算stride,直接从SoftwareBitmap的LockBuffer接口获取逐行真实步长传入libyuv,避免步长不匹配导致的花屏、崩溃问题。

内容的提问来源于stack exchange,提问作者davidlll

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.27 21:09:17