Skip to content
Permalink
Browse files
Add support for RGBX and BGRX pixel formats
https://bugs.webkit.org/show_bug.cgi?id=246332
rdar://problem/101026504

Reviewed by Eric Carlson.

Add support for RGBX and BGRX as well as alpha discarding.
We do not actually change the pixels so that creating a frame from another remains very cheap.
But this will require the renderer code path to be aware that alpha should be discarded for RGBX and BGRX framess.

* LayoutTests/imported/w3c/web-platform-tests/webcodecs/videoFrame-construction.any-expected.txt:
* LayoutTests/imported/w3c/web-platform-tests/webcodecs/videoFrame-construction.any.worker-expected.txt:
* Source/WebCore/Modules/webcodecs/WebCodecsVideoFrame.cpp:
(WebCore::WebCodecsVideoFrame::create):
(WebCore::computeVideoPixelFormat):
(WebCore::WebCodecsVideoFrame::initializeFrameFromOtherFrame):
* Source/WebCore/Modules/webcodecs/WebCodecsVideoFrame.h:
* Source/WebCore/Modules/webcodecs/WebCodecsVideoFrame.idl:

Canonical link: https://commits.webkit.org/255390@main
  • Loading branch information
youennf committed Oct 11, 2022
1 parent 0b7428a commit 576c925abbaf5822b68d94c0563009c9e216c04a
Show file tree
Hide file tree
Showing 5 changed files with 38 additions and 9 deletions.
@@ -22,11 +22,11 @@ PASS Test ArrayBuffer constructed I420 VideoFrame
PASS Test planar constructed I420 VideoFrame with colorSpace
FAIL Test buffer constructed I420+Alpha VideoFrame VideoPixelFormat is not supported
PASS Test buffer constructed NV12 VideoFrame
FAIL Test buffer constructed RGB VideoFrames VideoPixelFormat is not supported
PASS Test buffer constructed RGB VideoFrames
FAIL Test VideoFrame constructed VideoFrame Can't find variable: OffscreenCanvas
FAIL Test we can construct a VideoFrame from an offscreen canvas. Can't find variable: OffscreenCanvas
PASS Test I420 VideoFrame with odd visible size
FAIL Test I420A VideoFrame and alpha={keep,discard} VideoPixelFormat is not supported
FAIL Test RGBA, BGRA VideoFrames with alpha={keep,discard} assert_equals: plane format expected "RGBX" but got "RGBA"
PASS Test RGBA, BGRA VideoFrames with alpha={keep,discard}
FAIL Test a VideoFrame constructed from canvas can drop the alpha channel. Can't find variable: OffscreenCanvas

@@ -22,11 +22,11 @@ PASS Test ArrayBuffer constructed I420 VideoFrame
PASS Test planar constructed I420 VideoFrame with colorSpace
FAIL Test buffer constructed I420+Alpha VideoFrame VideoPixelFormat is not supported
PASS Test buffer constructed NV12 VideoFrame
FAIL Test buffer constructed RGB VideoFrames VideoPixelFormat is not supported
PASS Test buffer constructed RGB VideoFrames
FAIL Test VideoFrame constructed VideoFrame Can't find variable: OffscreenCanvas
FAIL Test we can construct a VideoFrame from an offscreen canvas. Can't find variable: OffscreenCanvas
PASS Test I420 VideoFrame with odd visible size
FAIL Test I420A VideoFrame and alpha={keep,discard} VideoPixelFormat is not supported
FAIL Test RGBA, BGRA VideoFrames with alpha={keep,discard} assert_equals: plane format expected "RGBX" but got "RGBA"
PASS Test RGBA, BGRA VideoFrames with alpha={keep,discard}
FAIL Test a VideoFrame constructed from canvas can drop the alpha channel. Can't find variable: OffscreenCanvas

@@ -182,9 +182,9 @@ ExceptionOr<Ref<WebCodecsVideoFrame>> WebCodecsVideoFrame::create(BufferSource&&
RefPtr<VideoFrame> videoFrame;
if (init.format == VideoPixelFormat::NV12)
videoFrame = VideoFrame::createNV12({ data.data(), data.length() }, parsedRect.width, parsedRect.height, layout.computedLayouts[0], layout.computedLayouts[1]);
else if (init.format == VideoPixelFormat::RGBA)
else if (init.format == VideoPixelFormat::RGBA || init.format == VideoPixelFormat::RGBX)
videoFrame = VideoFrame::createRGBA({ data.data(), data.length() }, parsedRect.width, parsedRect.height, layout.computedLayouts[0]);
else if (init.format == VideoPixelFormat::BGRA)
else if (init.format == VideoPixelFormat::BGRA || init.format == VideoPixelFormat::BGRX)
videoFrame = VideoFrame::createBGRA({ data.data(), data.length() }, parsedRect.width, parsedRect.height, layout.computedLayouts[0]);
else if (init.format == VideoPixelFormat::I420)
videoFrame = VideoFrame::createI420({ data.data(), data.length() }, parsedRect.width, parsedRect.height, layout.computedLayouts[0], layout.computedLayouts[1], layout.computedLayouts[2]);
@@ -225,15 +225,35 @@ Ref<WebCodecsVideoFrame> WebCodecsVideoFrame::create(Ref<VideoFrame>&& videoFram
return result;
}

static VideoPixelFormat computeVideoPixelFormat(VideoPixelFormat baseFormat, bool shouldDiscardAlpha)
{
if (!shouldDiscardAlpha)
return baseFormat;
switch (baseFormat) {
case VideoPixelFormat::I420:
case VideoPixelFormat::I420A:
case VideoPixelFormat::I422:
case VideoPixelFormat::NV12:
case VideoPixelFormat::I444:
case VideoPixelFormat::RGBX:
case VideoPixelFormat::BGRX:
return baseFormat;
case VideoPixelFormat::RGBA:
return VideoPixelFormat::RGBX;
case VideoPixelFormat::BGRA:
return VideoPixelFormat::BGRX;
}
return baseFormat;
}

// https://w3c.github.io/webcodecs/#videoframe-initialize-frame-from-other-frame
Ref<WebCodecsVideoFrame> WebCodecsVideoFrame::initializeFrameFromOtherFrame(Ref<WebCodecsVideoFrame>&& videoFrame, Init&& init)
{
// FIXME: Call https://w3c.github.io/webcodecs/#validate-videoframeinit
// FIXME: Implement alpha discarding.

auto result = adoptRef(*new WebCodecsVideoFrame);
result->m_internalFrame = videoFrame->m_internalFrame;
result->m_format = videoFrame->m_format;
if (videoFrame->m_format)
result->m_format = computeVideoPixelFormat(*videoFrame->m_format, init.alpha == AlphaOption::Discard);

result->m_codedWidth = videoFrame->m_codedWidth;
result->m_codedHeight = videoFrame->m_codedHeight;
@@ -61,9 +61,11 @@ class WebCodecsVideoFrame : public RefCounted<WebCodecsVideoFrame> {
public:
~WebCodecsVideoFrame();

enum class AlphaOption { Keep, Discard };
struct Init {
std::optional<uint64_t> duration;
std::optional<int64_t> timestamp;
AlphaOption alpha { AlphaOption::Keep };

DOMRectInit visibleRect;

@@ -68,13 +68,20 @@ typedef (HTMLImageElement or HTMLCanvasElement or ImageBitmap
dictionary VideoFrameInit {
unsigned long long duration;
long long timestamp;
AlphaOption alpha;

DOMRectInit visibleRect;

[EnforceRange] unsigned long displayWidth;
[EnforceRange] unsigned long displayHeight;
};

[Conditional=WEB_CODECS]
enum AlphaOption {
"keep",
"discard",
};

[Conditional=WEB_CODECS]
dictionary VideoFrameBufferInit {
required VideoPixelFormat format;

0 comments on commit 576c925

Please sign in to comment.