Bug 230338 - Add utility to create CVPixelBuffers from IOSurfaces
Summary: Add utility to create CVPixelBuffers from IOSurfaces
Status: RESOLVED FIXED
Alias: None
Product: WebKit
Classification: Unclassified
Component: Media (show other bugs)
Version: WebKit Nightly Build
Hardware: Unspecified Unspecified
: P2 Normal
Assignee: Kimmo Kinnunen
URL:
Keywords: InRadar
Depends on:
Blocks: 230613
  Show dependency treegraph
 
Reported: 2021-09-16 03:49 PDT by Kimmo Kinnunen
Modified: 2021-09-24 06:34 PDT (History)
14 users (show)

See Also:


Attachments
Patch (41.31 KB, patch)
2021-09-16 04:46 PDT, Kimmo Kinnunen
ews-feeder: commit-queue-
Details | Formatted Diff | Diff
Patch (41.85 KB, patch)
2021-09-16 05:27 PDT, Kimmo Kinnunen
ews-feeder: commit-queue-
Details | Formatted Diff | Diff
Patch (41.85 KB, patch)
2021-09-16 05:29 PDT, Kimmo Kinnunen
no flags Details | Formatted Diff | Diff
Patch (41.85 KB, patch)
2021-09-16 11:50 PDT, Kimmo Kinnunen
no flags Details | Formatted Diff | Diff
Patch (41.68 KB, patch)
2021-09-16 12:14 PDT, Kimmo Kinnunen
no flags Details | Formatted Diff | Diff
Patch (41.89 KB, patch)
2021-09-16 23:38 PDT, Kimmo Kinnunen
no flags Details | Formatted Diff | Diff
Patch (41.90 KB, patch)
2021-09-17 12:29 PDT, Kimmo Kinnunen
ews-feeder: commit-queue-
Details | Formatted Diff | Diff
Patch (42.08 KB, patch)
2021-09-17 13:14 PDT, Kimmo Kinnunen
no flags Details | Formatted Diff | Diff
Patch (41.63 KB, patch)
2021-09-24 00:48 PDT, Kimmo Kinnunen
ews-feeder: commit-queue-
Details | Formatted Diff | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Kimmo Kinnunen 2021-09-16 03:49:09 PDT
Add utility to create CVPixelBuffers from IOSurfaces
Comment 1 Kimmo Kinnunen 2021-09-16 04:46:48 PDT
Created attachment 438338 [details]
Patch
Comment 2 Kimmo Kinnunen 2021-09-16 05:27:12 PDT
Created attachment 438339 [details]
Patch
Comment 3 Kimmo Kinnunen 2021-09-16 05:29:12 PDT
Created attachment 438340 [details]
Patch
Comment 4 Kimmo Kinnunen 2021-09-16 11:50:53 PDT
Created attachment 438378 [details]
Patch
Comment 5 Eric Carlson 2021-09-16 12:03:02 PDT
Comment on attachment 438378 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=438378&action=review

> Source/WebCore/platform/graphics/cv/CVUtilities.mm:84
> +#if PLATFORM(MAC)
> +    auto format = IOSurfaceGetPixelFormat(surface);
> +    if (format == kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange || format == kCVPixelFormatType_420YpCbCr8BiPlanarFullRange) {
> +        constexpr size_t macroblockSize = 16;
> +        auto width = IOSurfaceGetWidth(surface);
> +        auto height = IOSurfaceGetHeight(surface);
> +        auto extendedRight = roundUpToMultipleOf(macroblockSize, width) - width;
> +        auto extendedBottom = roundUpToMultipleOf(macroblockSize, height) - height;
> +        if ((IOSurfaceGetBytesPerRowOfPlane(surface, 0) >= width + extendedRight)
> +            && (IOSurfaceGetBytesPerRowOfPlane(surface, 1) >= width + extendedRight)
> +            && (IOSurfaceGetAllocSize(surface) >= (height + extendedBottom) * IOSurfaceGetBytesPerRowOfPlane(surface, 0) * 3 / 2)) {
> +            return (__bridge CFDictionaryRef) @{
> +#if PLATFORM(MAC)
> +                (__bridge NSString *)kCVPixelBufferOpenGLCompatibilityKey : @YES,
> +#endif

Why have nested `#if PLATFORM(MAC)` ?

> Source/WebCore/platform/graphics/cv/CVUtilities.mm:102
> +    if (!surface)

Might be worth ASSERT-ing this
Comment 6 Kimmo Kinnunen 2021-09-16 12:14:37 PDT
Created attachment 438382 [details]
Patch
Comment 7 Darin Adler 2021-09-16 12:52:25 PDT
Comment on attachment 438382 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=438382&action=review

> Source/WebCore/platform/graphics/cv/CVUtilities.mm:72
> +    if (format == kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange || format == kCVPixelFormatType_420YpCbCr8BiPlanarFullRange) {

I think this needs a brief "why" comment.

> Source/WebCore/platform/graphics/cv/CVUtilities.mm:100
> +    ASSERT(surface);

Why assert this? We’re not asserting pixelBufferPool above, for example.

Separately, but related: Maybe we could do a null check, return an unexpected value in that case, and remove the null check in ImageTransferSessionVT::createCMSampleBuffer?

> Source/WebCore/platform/mediastream/mac/RealtimeIncomingVideoSourceCocoa.mm:102
> +        if (auto pool = createIOSurfaceCVPixelBufferPool({ static_cast<int>(width), static_cast<int>(height) }, poolBufferType)) {

Not new, but what guarantees the width and height fit into int?

> Source/WebKit/WebProcess/GPU/webrtc/LibWebRTCCodecs.cpp:500
> +        m_pixelBufferPool = WebCore::createIOSurfaceCVPixelBufferPool({ static_cast<int>(width), static_cast<int>(height) }, type).value_or(nullptr);

Not new, but what guarantees the width and height fit into int?
Comment 8 Darin Adler 2021-09-16 12:52:55 PDT
Comment on attachment 438382 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=438382&action=review

>> Source/WebCore/platform/graphics/cv/CVUtilities.mm:100
>> +    ASSERT(surface);
> 
> Why assert this? We’re not asserting pixelBufferPool above, for example.
> 
> Separately, but related: Maybe we could do a null check, return an unexpected value in that case, and remove the null check in ImageTransferSessionVT::createCMSampleBuffer?

I see now that my comment is the opposite of Eric’s!
Comment 9 Eric Carlson 2021-09-16 12:59:01 PDT
Comment on attachment 438382 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=438382&action=review

>>> Source/WebCore/platform/graphics/cv/CVUtilities.mm:100
>>> +    ASSERT(surface);
>> 
>> Why assert this? We’re not asserting pixelBufferPool above, for example.
>> 
>> Separately, but related: Maybe we could do a null check, return an unexpected value in that case, and remove the null check in ImageTransferSessionVT::createCMSampleBuffer?
> 
> I see now that my comment is the opposite of Eric’s!

I suggested the change because CVPixelBufferCreateWithIOSurface already returns an error when passed a NULL surface, but I think it would be useful to catch this in debug builds.
Comment 10 Kimmo Kinnunen 2021-09-16 23:38:03 PDT
Created attachment 438448 [details]
Patch
Comment 11 Kimmo Kinnunen 2021-09-17 12:29:33 PDT
Created attachment 438500 [details]
Patch
Comment 12 Kimmo Kinnunen 2021-09-17 13:14:08 PDT
Created attachment 438506 [details]
Patch
Comment 13 Kimmo Kinnunen 2021-09-17 13:16:17 PDT
> > Source/WebCore/platform/graphics/cv/CVUtilities.mm:72
> > +    if (format == kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange || format == kCVPixelFormatType_420YpCbCr8BiPlanarFullRange) {
> 
> I think this needs a brief "why" comment.

Eric, do you have a wording for why?
I know roughly what it does, but not exactly why.

git log --oneline -S "roundUpToMacroblockMultiple" -- Source/WebCore/platform 

53093dc43c75 [MediaStream] Consolidate all image conversion and resizing into one class https://bugs.webkit.org/show_bug.cgi?id=190519 <rdar://problem/45224307>
600ac42b961f [MediaStream] Restructure getDisplayMedia classes https://bugs.webkit.org/show_bug.cgi?id=187905
342759df7ad6 [MediaStream] Add Mac screen capture source https://bugs.webkit.org/show_bug.cgi?id=181333 <rdar://problem/36323219>

I tried to formulate something, unsure if it's any better or exactly correct.


> Not new, but what guarantees the width and height fit into int?
Reverted these to the original.

>>>> +    ASSERT(surface);
>>> Why assert this? We’re not asserting pixelBufferPool above, for example.

Reverted the assert.
Comment 14 youenn fablet 2021-09-22 06:41:46 PDT
Comment on attachment 438506 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=438506&action=review

> Source/WebCore/platform/graphics/cv/CVUtilities.mm:55
> +        return makeUnexpected(status);

We do not seem to log errors at call sites of createIOSurfaceCVPixelBufferPool.
Maybe we should, or should do here.

> Source/WebCore/platform/graphics/cv/CVUtilities.mm:64
> +        return makeUnexpected(status);

It is a bit odd to have a case where kCVReturnSuccess and pixelBuffer is null.
But it seems good to make it the error path.

> Source/WebCore/platform/graphics/cv/ImageTransferSessionVT.mm:79
> +    auto bufferPool = createIOSurfaceCVPixelBufferPool(size.width(), size.height(), m_pixelFormat, 6).value_or(nullptr);

Preexisting issue but this value 6 is a bit mysterious.

> Source/WebKit/GPUProcess/webrtc/LibWebRTCCodecsProxy.mm:214
> +    auto pixelBuffer = WebCore::createCVPixelBuffer(sample.surface()).value_or(nullptr);

If pixelBuffer is null, we probably want to exit early, maybe log an error.

> Source/WebKit/WebProcess/GPU/webrtc/LibWebRTCCodecs.cpp:500
> +        m_pixelBufferPool = WebCore::createIOSurfaceCVPixelBufferPool(width, height, type).value_or(nullptr);

We could not set m_pixelBufferPoolWidth/m_pixelBufferPoolHeight if m_pixelBufferPool creation failed.
Comment 15 Radar WebKit Bug Importer 2021-09-23 03:50:18 PDT
<rdar://problem/83440494>
Comment 16 Kimmo Kinnunen 2021-09-24 00:48:55 PDT
Created attachment 439133 [details]
Patch
Comment 17 EWS 2021-09-24 05:41:11 PDT
Committed r283036 (242096@main): <https://commits.webkit.org/242096@main>

All reviewed patches have been landed. Closing bug and clearing flags on attachment 439133 [details].