HarmonyOS 相机帧yuv格式的buffer大小和size乘积大小不一致,导致memcpy时出现数据源错误?

如题:HarmonyOS 相机帧yuv格式的buffer大小和size乘积大小不一致,导致memcpy时出现数据源错误?

阅读 458
1 个回答

建议自己实现memcpy方法,参考以下代码:

void MemcpyHelper::CopyData(CopyInfo &src, CopyInfo &dst)
{
  uint8_t *srcBuffet = src.data;
  uint8_t *dstBuffer = dst.data;
  CHECK_AND_RETURN_LOG(srcBuffet != nullptr && dstBuffer != nullptr,
    "Input addr is null! srcAddr=%{public}p, dstAddr=%{public}p", srcBuffet, dstBuffer);
  if (srcBuffet == dstBuffer) {
    EFFECT_LOGD("Buffer is same, not need copy.");
    return;
  }
  BufferInfo &srcInfo = src.bufferInfo;
  BufferInfo &dstInfo = dst.bufferInfo;
  EFFECT_LOGD("CopyData: srcAddr=%{public}p, srcH=%{public}d, srcFormat=%{public}d, srcStride=%{public}d, "
  "srcLen=%{public}d, dstAddr=%{public}p, dstH=%{public}d, dstFormat=%{public}d, dstStride=%{public}d, "
  "dstLen=%{public}d", src.data, srcInfo.height_, srcInfo.formatType_, srcInfo.rowStride_, srcInfo.len_,
  dst.data, dstInfo.height_, dstInfo.formatType_, dstInfo.rowStride_, dstInfo.len_);
  uint32_t srcRowStride = srcInfo.rowStride_;
  uint32_t dstRowStride = dstInfo.rowStride_;
  uint32_t srcBufferLen = srcInfo.len_;
  uint32_t dstBufferLen = dstInfo.len_;
  // direct copy the date while the size is same.
  if (srcRowStride == dstRowStride && srcBufferLen == dstBufferLen) {
    errno_t ret = memcpy_s(dstBuffer, dstBufferLen, srcBuffet, srcBufferLen);
    if (ret != 0) {
      EFFECT_LOGE("CopyData memcpy_s failed. ret=%{public}d, dstBuf=%{public}p, dstBufLen=%{public}d,"
      " srcBuf=%{public}p, srcBufLen=%{public}d", ret, dstBuffer, dstBufferLen, srcBuffet, srcBufferLen);
    }
    return;
  }
  // copy by row
  uint32_t srcRowCount = FormatHelper::CalculateDataRowCount(srcInfo.height_, srcInfo.formatType_);
  uint32_t dstRowCount = FormatHelper::CalculateDataRowCount(dstInfo.height_, dstInfo.formatType_);
  uint32_t rowCount = srcRowCount > dstRowCount ? dstRowCount : srcRowCount;
  uint32_t count = srcRowStride > dstRowStride ? dstRowStride : srcRowStride;
  if (rowCount * dstRowStride > dstBufferLen || rowCount * srcRowStride > srcBufferLen) {
    EFFECT_LOGE("Out of buffer available range! Copy fail! srcH=%{public}d, srcFormat=%{public}d, "
    "srcStride=%{public}d, srcLen=%{public}d, dstH=%{public}d, dstFormat=%{public}d, dstStride=%{public}d, "
    "dstLen=%{public}d", srcInfo.height_, srcInfo.formatType_, srcInfo.rowStride_, srcInfo.len_,
    dstInfo.height_, dstInfo.formatType_, dstInfo.rowStride_, dstInfo.len_);
    return;
  }
  for (uint32_t i = 0; i < rowCount; i++) {
  errno_t ret = memcpy_s(dstBuffer + i * dstRowStride, dstRowStride, srcBuffet + i * srcRowStride, count);
  if (ret != 0) {
    EFFECT_LOGE("CopyData: copy by row memcpy_s failed. ret=%{public}d, row=%{public}d, srcH=%{public}d, "
    "srcFormat=%{public}d, srcStride=%{public}d, srcLen=%{public}d, dstH=%{public}d, dstFormat=%{public}d, "
    "dstStride=%{public}d, dstLen=%{public}d", ret, i,
    srcInfo.height_, srcInfo.formatType_, srcInfo.rowStride_, srcInfo.len_,
    dstInfo.height_, dstInfo.formatType_, dstInfo.rowStride_, dstInfo.len_);
    continue;
  }
}
}

uint32_t FormatHelper::CalculateDataRowCount(uint32_t height, IEffectFormat format)
{
  switch (format) {
    case IEffectFormat::RGBA8888:
    case IEffectFormat::RGBA_1010102:
  return height;
    case IEffectFormat::YUVNV12:
    case IEffectFormat::YUVNV21:
    case IEffectFormat::YCBCR_P010:
    case IEffectFormat::YCRCB_P010:
  return static_cast<uint32_t>(height * YUV_BYTES_PER_PIXEL);
    default:
      return height;
  }
}
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进