Skip to content

Commit

Permalink
fix(👾): use PixelBuffer instead of SampleBuffer on iOS (#2374)
Browse files Browse the repository at this point in the history
  • Loading branch information
wcandillon authored Apr 17, 2024
1 parent 2f6ff85 commit 8e41da3
Show file tree
Hide file tree
Showing 5 changed files with 10 additions and 42 deletions.
4 changes: 2 additions & 2 deletions package/cpp/rnskia/RNSkPlatformContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -134,8 +134,8 @@ class RNSkPlatformContext {
virtual sk_sp<SkSurface> makeOffscreenSurface(int width, int height) = 0;

/**
* Creates an image from a native buffer.
* - On iOS, this is a `CMSampleBuffer`
* Creates an image from a native buffer. (for testing purposes only)

This comment has been minimized.

Copy link
@mrousavy

mrousavy Apr 17, 2024

Contributor

why for testing purposes only? 😅

This comment has been minimized.

Copy link
@wcandillon

wcandillon Apr 17, 2024

Author Contributor

haha that was a mistake thanks for catching it

* - On iOS, this is a `CVPixelBufferRef*`

This comment has been minimized.

Copy link
@mrousavy

mrousavy Apr 17, 2024

Contributor

It's a CVPixelBufferRef or a CVPixelBuffer*, not a CVPixelBufferRef*

This comment has been minimized.

Copy link
@wcandillon

wcandillon Apr 17, 2024

Author Contributor

yep :) thanks 🙏

* - On Android, this is a `AHardwareBuffer*`
* @param buffer The native platform buffer.
* @return sk_sp<SkImage>
Expand Down
34 changes: 4 additions & 30 deletions package/ios/RNSkia-iOS/RNSkiOSPlatformContext.mm
Original file line number Diff line number Diff line change
Expand Up @@ -143,34 +143,8 @@
std::to_string(result));
}

// 6. Create CMSampleBuffer base information
CMFormatDescriptionRef formatDescription = nullptr;
CMVideoFormatDescriptionCreateForImageBuffer(kCFAllocatorDefault, pixelBuffer,
&formatDescription);
CMSampleTimingInfo timingInfo = {0};
timingInfo.duration = kCMTimeInvalid;
timingInfo.presentationTimeStamp = kCMTimeZero;
timingInfo.decodeTimeStamp = kCMTimeInvalid;

// 7. Wrap the CVPixelBuffer in a CMSampleBuffer
CMSampleBufferRef sampleBuffer = nullptr;
OSStatus status = CMSampleBufferCreateReadyWithImageBuffer(
kCFAllocatorDefault, pixelBuffer, formatDescription, &timingInfo,
&sampleBuffer);
if (status != noErr) {
if (formatDescription) {
CFRelease(formatDescription);
}
if (pixelBuffer) {
CFRelease(pixelBuffer);
}
throw std::runtime_error(
"Failed to wrap CVPixelBuffer in CMSampleBuffer! Return value: " +
std::to_string(status));
}

// 8. Return CMsampleBuffer casted to uint64_t
return reinterpret_cast<uint64_t>(sampleBuffer);
// 8. Return CVPixelBuffer casted to uint64_t
return reinterpret_cast<uint64_t>(pixelBuffer);
}

void RNSkiOSPlatformContext::raiseError(const std::exception &err) {
Expand All @@ -183,8 +157,8 @@
}

sk_sp<SkImage> RNSkiOSPlatformContext::makeImageFromNativeBuffer(void *buffer) {
CMSampleBufferRef sampleBuffer = (CMSampleBufferRef)buffer;
return SkiaMetalSurfaceFactory::makeTextureFromCMSampleBuffer(sampleBuffer);
CVPixelBufferRef sampleBuffer = (CVPixelBufferRef)buffer;
return SkiaMetalSurfaceFactory::makeTextureFromCVPixelBuffer(sampleBuffer);
}

sk_sp<SkFontMgr> RNSkiOSPlatformContext::createFontMgr() {
Expand Down
2 changes: 1 addition & 1 deletion package/ios/RNSkia-iOS/SkiaMetalSurfaceFactory.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ class SkiaMetalSurfaceFactory {
static sk_sp<SkSurface> makeOffscreenSurface(int width, int height);

static sk_sp<SkImage>
makeTextureFromCMSampleBuffer(CMSampleBufferRef sampleBuffer);
makeTextureFromCVPixelBuffer(CVPixelBufferRef pixelBuffer);

private:
static id<MTLDevice> device;
Expand Down
10 changes: 2 additions & 8 deletions package/ios/RNSkia-iOS/SkiaMetalSurfaceFactory.mm
Original file line number Diff line number Diff line change
Expand Up @@ -107,20 +107,14 @@
return surface;
}

sk_sp<SkImage> SkiaMetalSurfaceFactory::makeTextureFromCMSampleBuffer(
CMSampleBufferRef sampleBuffer) {
sk_sp<SkImage> SkiaMetalSurfaceFactory::makeTextureFromCVPixelBuffer(
CVPixelBufferRef pixelBuffer) {
if (!SkiaMetalSurfaceFactory::createSkiaDirectContextIfNecessary(
&ThreadContextHolder::ThreadSkiaMetalContext)) [[unlikely]] {
throw std::runtime_error("Failed to create Skia Context for this Thread!");
}
const SkiaMetalContext &context = ThreadContextHolder::ThreadSkiaMetalContext;

if (!CMSampleBufferIsValid(sampleBuffer)) [[unlikely]] {
throw std::runtime_error("The given CMSampleBuffer is not valid!");
}

CVPixelBufferRef pixelBuffer = CMSampleBufferGetImageBuffer(sampleBuffer);

SkiaCVPixelBufferUtils::CVPixelBufferBaseFormat format =
SkiaCVPixelBufferUtils::getCVPixelBufferBaseFormat(pixelBuffer);
switch (format) {
Expand Down
2 changes: 1 addition & 1 deletion package/src/skia/types/Image/ImageFactory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ export interface ImageFactory {
* to render a Skia Camera preview.
*
* - On Android; This is an `AHardwareBuffer*`
* - On iOS, this is a `CMSampleBufferRef`
* - On iOS, this is a `CVPixelBufferRef`
* @param nativeBuffer A strong `uintptr_t` pointer to the native platform buffer
* @throws Throws an error if the Image could not be created, for example when the given
* platform buffer is invalid.
Expand Down

0 comments on commit 8e41da3

Please sign in to comment.