processNv21 method

FaceMeshResult processNv21(
  1. FaceMeshNv21Image image, {
  2. NormalizedRect? roi,
  3. FaceMeshBox? box,
  4. double boxScale = _boxScale,
  5. bool boxMakeSquare = true,
  6. int rotationDegrees = 0,
  7. bool mirrorHorizontal = false,
})

Processes NV21 camera frames captured directly from a camera preview.

Parameters mirror the process method although the inputs are provided as separate Y and VU planes in NV21 layout. Set mirrorHorizontal to true if your camera preview is mirrored to avoid flipped outputs.

Implementation

FaceMeshResult processNv21(
  FaceMeshNv21Image image, {
  NormalizedRect? roi,
  FaceMeshBox? box,
  double boxScale = _boxScale,
  bool boxMakeSquare = true,
  int rotationDegrees = 0,
  bool mirrorHorizontal = false,
}) {
  _ensureNotClosed();
  if (roi != null && box != null) {
    throw ArgumentError('Provide either roi or box, not both.');
  }
  _validateRotationDegrees(rotationDegrees);
  final int logicalWidth = (rotationDegrees == 90 || rotationDegrees == 270)
      ? image.height
      : image.width;
  final int logicalHeight = (rotationDegrees == 90 || rotationDegrees == 270)
      ? image.width
      : image.height;
  final NormalizedRect? effectiveRoi =
      roi ??
      (box != null
          ? _normalizedRectFromBox(
              box,
              imageWidth: logicalWidth,
              imageHeight: logicalHeight,
              scale: boxScale,
              makeSquare: boxMakeSquare,
            )
          : null);
  final _NativeNv21Image nativeImage = _toNativeNv21Image(image);
  final ffi.Pointer<MpNormalizedRect> roiPtr = effectiveRoi != null
      ? _toNativeRect(effectiveRoi)
      : ffi.nullptr;
  FaceMeshResult? processed;
  try {
    final ffi.Pointer<MpFaceMeshResult> resultPtr = faceBindings
        .mp_face_mesh_process_nv21(
          _context,
          nativeImage.image,
          roiPtr == ffi.nullptr ? ffi.nullptr : roiPtr,
          rotationDegrees,
          mirrorHorizontal ? 1 : 0,
        );
    if (resultPtr == ffi.nullptr) {
      throw MediapipeFaceMeshException(
        _readCString(faceBindings.mp_face_mesh_last_error(_context)) ??
            'Native face mesh error.',
      );
    }
    processed = _copyResult(resultPtr.ref);
    faceBindings.mp_face_mesh_release_result(resultPtr);
  } finally {
    pkg_ffi.calloc.free(nativeImage.yPlane);
    pkg_ffi.calloc.free(nativeImage.vuPlane);
    pkg_ffi.calloc.free(nativeImage.image);
    if (roiPtr != ffi.nullptr) {
      pkg_ffi.calloc.free(roiPtr);
    }
  }
  return processed;
}