Source code
Revision control
Copy as Markdown
Other Tools
From: Michael Froman <mfroman@mozilla.com>
Date: Thu, 20 Aug 2026 15:17:00 +0000
VideoCaptureImpl::IncomingFrame. r=bwc
Mercurial Revision: https://hg.mozilla.org/mozilla-central/rev/f0c6e846e0d33294378079b83208d1a91c5bf293
---
api/video/i420_buffer.cc | 27 ++++++++++++++++++---
api/video/i420_buffer.h | 15 +++++++++++-
modules/video_capture/video_capture_impl.cc | 11 ++++++++-
3 files changed, 47 insertions(+), 6 deletions(-)
diff --git a/api/video/i420_buffer.cc b/api/video/i420_buffer.cc
index e9320ced2a..4eec83cd3a 100644
--- a/api/video/i420_buffer.cc
+++ b/api/video/i420_buffer.cc
@@ -54,15 +54,18 @@ I420Buffer::I420Buffer(int width,
int height,
int stride_y,
int stride_u,
- int stride_v)
+ int stride_v,
+ uint8_t* data)
: width_(width),
height_(height),
stride_y_(stride_y),
stride_u_(stride_u),
stride_v_(stride_v),
- data_(static_cast<uint8_t*>(AlignedMalloc(
- I420DataSize(width, height, stride_y, stride_u, stride_v),
- kBufferAlignment))) {
+ data_(data ? data
+ : static_cast<uint8_t*>(AlignedMalloc(
+ I420DataSize(width, height, stride_y, stride_u,
+ stride_v),
+ kBufferAlignment))) {
RTC_DCHECK_GE(stride_u, (width + 1) / 2);
RTC_DCHECK_GE(stride_v, (width + 1) / 2);
}
@@ -84,6 +87,22 @@ scoped_refptr<I420Buffer> I420Buffer::Create(int width,
stride_v);
}
+// static
+scoped_refptr<I420Buffer> I420Buffer::CreateOrNull(int width,
+ int height,
+ int stride_y,
+ int stride_u,
+ int stride_v) {
+ uint8_t* data = AlignedMallocOrNull<uint8_t>(
+ I420DataSize(width, height, stride_y, stride_u, stride_v),
+ kBufferAlignment);
+ if (!data) {
+ return nullptr;
+ }
+ return make_ref_counted<I420Buffer>(width, height, stride_y, stride_u,
+ stride_v, data);
+}
+
// static
scoped_refptr<I420Buffer> I420Buffer::Copy(const I420BufferInterface& source) {
return Copy(source.width(), source.height(), source.DataY(), source.StrideY(),
diff --git a/api/video/i420_buffer.h b/api/video/i420_buffer.h
index a7a0fb014d..e4935b430c 100644
--- a/api/video/i420_buffer.h
+++ b/api/video/i420_buffer.h
@@ -32,6 +32,11 @@ class RTC_EXPORT I420Buffer : public I420BufferInterface {
int stride_y,
int stride_u,
int stride_v);
+ static scoped_refptr<I420Buffer> CreateOrNull(int width,
+ int height,
+ int stride_y,
+ int stride_u,
+ int stride_v);
// Create a new buffer and copy the pixel data.
static scoped_refptr<I420Buffer> Copy(const I420BufferInterface& buffer);
@@ -100,7 +105,15 @@ class RTC_EXPORT I420Buffer : public I420BufferInterface {
protected:
I420Buffer(int width, int height);
- I420Buffer(int width, int height, int stride_y, int stride_u, int stride_v);
+ // If `data` is non-null, it must have been allocated with AlignedMalloc and
+ // be large enough to hold the planes described by the strides; the buffer
+ // takes ownership of it. Otherwise the data is allocated by the constructor.
+ I420Buffer(int width,
+ int height,
+ int stride_y,
+ int stride_u,
+ int stride_v,
+ uint8_t* data = nullptr);
~I420Buffer() override;
diff --git a/modules/video_capture/video_capture_impl.cc b/modules/video_capture/video_capture_impl.cc
index ed83ab6e57..7bf88028ef 100644
--- a/modules/video_capture/video_capture_impl.cc
+++ b/modules/video_capture/video_capture_impl.cc
@@ -200,8 +200,17 @@ int32_t VideoCaptureImpl::IncomingFrame(uint8_t* videoFrame,
// Setting absolute height (in case it was negative).
// In Windows, the image starts bottom left, instead of top left.
// Setting a negative source height, inverts the image (within LibYuv).
- scoped_refptr<I420Buffer> buffer = I420Buffer::Create(
+ scoped_refptr<I420Buffer> buffer = I420Buffer::CreateOrNull(
target_width, target_height, stride_y, stride_uv, stride_uv);
+ if (!buffer) {
+ RTC_LOG(LS_ERROR) << "Unable to allocate I420Buffer"
+ << " (w: " << target_width
+ << ", h: " << target_height
+ << ", stride_y: " << stride_y
+ << ", stride_u: " << stride_uv
+ << ", stride_v: " << stride_uv << ")";
+ return -1;
+ }
libyuv::RotationMode rotation_mode = libyuv::kRotate0;
if (apply_rotation_) {