void WebPFrame_nativeRenderFrame()

in static-webp/src/main/jni/static-webp/webp.cpp [585:662]


void WebPFrame_nativeRenderFrame(
    JNIEnv* pEnv,
    jobject thiz,
    jint width,
    jint height,
    jobject bitmap) {
  auto spNativeContext = getWebPFrameNativeContext(pEnv, thiz);
  if (!spNativeContext) {
    throwIllegalStateException(pEnv, "Already disposed");
    return;
  }

  AndroidBitmapInfo bitmapInfo;
  if (AndroidBitmap_getInfo(pEnv, bitmap, &bitmapInfo) != ANDROID_BITMAP_RESULT_SUCCESS) {
    throwIllegalStateException(pEnv, "Bad bitmap");
    return;
  }

  if (width < 0 || height < 0) {
    throwIllegalArgumentException(pEnv, "Width or height is negative !");
    return;
  }
  
  if (bitmapInfo.width < (unsigned) width || bitmapInfo.height < (unsigned) height) {
    throwIllegalStateException(pEnv, "Width or height is too small");
    return;
  }

  if (bitmapInfo.format != ANDROID_BITMAP_FORMAT_RGBA_8888) {
    spNativeContext.reset();
    throwIllegalStateException(pEnv, "Wrong color format");
    return;
  }

  WebPDecoderConfig config;
  int ret = WebPInitDecoderConfig(&config);
  if (!ret) {
    throwIllegalStateException(pEnv, "WebPInitDecoderConfig failed");
    return;
  }

  const uint8_t* pPayload = spNativeContext->pPayload;
  size_t payloadSize = spNativeContext->payloadSize;

  ret = (WebPGetFeatures(pPayload , payloadSize, &config.input) == VP8_STATUS_OK);
  if (!ret) {
    spNativeContext.reset();
    throwIllegalStateException(pEnv, "WebPGetFeatures failed");
    return;
  }

  uint8_t* pixels;
  if (AndroidBitmap_lockPixels(pEnv, bitmap, (void**) &pixels) != ANDROID_BITMAP_RESULT_SUCCESS) {
    spNativeContext.reset();
    throwIllegalStateException(pEnv, "Bad bitmap");
    return;
  }

  config.options.no_fancy_upsampling = 1;
  if (width != spNativeContext->width || height != spNativeContext->height) {
    config.options.use_scaling = true;
    config.options.scaled_width = width;
    config.options.scaled_height = height;
  }

  config.output.colorspace = MODE_rgbA;
  config.output.is_external_memory = 1;
  config.output.u.RGBA.rgba = pixels;
  config.output.u.RGBA.stride = bitmapInfo.stride;
  config.output.u.RGBA.size   = bitmapInfo.stride * bitmapInfo.height;

  ret = WebPDecode(pPayload, payloadSize, &config);
  AndroidBitmap_unlockPixels(pEnv, bitmap);
  if (ret != VP8_STATUS_OK) {
    spNativeContext.reset();
    throwIllegalStateException(pEnv, "Failed to decode frame. VP8StatusCode: %d", ret);
  }
}