Skip to content

Commit

Permalink
[ios] Use VTPixelRotationSessionCreate to rotate CVPixelBuffers
Browse files Browse the repository at this point in the history
CL https://crrev.com/c/4659640 introduced pixel rotation support for
the SW path of Video Capture.

The CL introduces hardware support for pixel rotation by using
VTPixelRotationSessionCreate to rotate CVPixelBuffers backed by
IOsurfaces.

TEST: ios-deploy --justlaunch --bundle \
      out/Debug-iphoneos/content_shell.app --args=" \
      --auto-accept-camera-and-microphone-capture \
      --video-capture-use-gpu-memory-buffer \
      https://webrtc.github.io/samples/src/content/getusermedia/gum/"

Bug: 1430702
Change-Id: I9f326c606795c55ed9f0465dfe6efe49f7ec4472
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4759044
Reviewed-by: Henrik Boström <hbos@chromium.org>
Commit-Queue: Abhijeet Kandalkar <abhijeet@igalia.com>
Cr-Commit-Position: refs/heads/main@{#1184734}
  • Loading branch information
abhijeetk authored and Chromium LUCI CQ committed Aug 17, 2023
1 parent 6c128d3 commit f777cb3
Show file tree
Hide file tree
Showing 7 changed files with 268 additions and 36 deletions.
7 changes: 7 additions & 0 deletions media/capture/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,13 @@ component("capture_lib") {
deps += [ "//third_party/decklink" ]
}

if (is_ios) {
sources += [
"video/ios/pixel_buffer_rotator.cc",
"video/ios/pixel_buffer_rotator.h",
]
}

if (is_win) {
sources += [
"video/win/capability_list_win.cc",
Expand Down
50 changes: 50 additions & 0 deletions media/capture/video/apple/sample_buffer_transformer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -479,6 +479,7 @@ void SampleBufferTransformer::Reconfigure(
Transformer transformer,
OSType destination_pixel_format,
const gfx::Size& destination_size,
int rotation_angle,
absl::optional<size_t> buffer_pool_size) {
DCHECK(transformer != Transformer::kLibyuv ||
destination_pixel_format == kPixelFormatI420 ||
Expand All @@ -498,7 +499,30 @@ void SampleBufferTransformer::Reconfigure(
destination_size_.height(), buffer_pool_size);
if (transformer == Transformer::kPixelBufferTransfer) {
pixel_buffer_transferer_ = std::make_unique<PixelBufferTransferer>();
rotation_angle_ = rotation_angle;
#if BUILDFLAG(IS_IOS)
int width, height;
switch (rotation_angle_) {
case 0:
case 180:
width = destination_size_.width();
height = destination_size_.height();
break;
case 90:
case 270:
width = destination_size_.height();
height = destination_size_.width();
break;
}

rotated_destination_pixel_buffer_pool_ = PixelBufferPool::Create(
destination_pixel_format_, width, height, buffer_pool_size);
pixel_buffer_rotator_ = std::make_unique<PixelBufferRotator>();
#endif
} else {
#if BUILDFLAG(IS_IOS)
pixel_buffer_rotator_.reset();
#endif
pixel_buffer_transferer_.reset();
}
intermediate_i420_buffer_.resize(0);
Expand Down Expand Up @@ -560,6 +584,32 @@ base::ScopedCFTypeRef<CVPixelBufferRef> SampleBufferTransformer::Transform(
return destination_pixel_buffer;
}

#if BUILDFLAG(IS_IOS)
base::ScopedCFTypeRef<CVPixelBufferRef> SampleBufferTransformer::Rotate(
CVPixelBufferRef source_pixel_buffer) {
DCHECK(source_pixel_buffer);
DCHECK(pixel_buffer_rotator_);

// Create destination buffer from pool.
base::ScopedCFTypeRef<CVPixelBufferRef> rotated_pixel_buffer =
rotated_destination_pixel_buffer_pool_->CreateBuffer();
if (!rotated_pixel_buffer) {
// Most likely the buffer count was exceeded, but other errors are possible.
LOG(ERROR) << "Failed to create a destination buffer";
return base::ScopedCFTypeRef<CVPixelBufferRef>();
}

// The rotated_pixel_buffer might not be the same size as source_pixel_buffer
// since source_pixel_buffer gets rotated by rotation_angle_.
if (pixel_buffer_rotator_->Rotate(source_pixel_buffer, rotated_pixel_buffer,
rotation_angle_)) {
return base::ScopedCFTypeRef<CVPixelBufferRef>(rotated_pixel_buffer);
} else {
return base::ScopedCFTypeRef<CVPixelBufferRef>();
}
}
#endif

void SampleBufferTransformer::TransformPixelBuffer(
CVPixelBufferRef source_pixel_buffer,
CVPixelBufferRef destination_pixel_buffer) {
Expand Down
17 changes: 17 additions & 0 deletions media/capture/video/apple/sample_buffer_transformer.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@
#include "media/capture/video/apple/pixel_buffer_transferer.h"
#include "ui/gfx/geometry/size.h"

#if BUILDFLAG(IS_IOS)
#include "media/capture/video/ios/pixel_buffer_rotator.h"
#endif

namespace media {

// Capable of converting from any supported capture format (NV12, YUY2, UYVY and
Expand Down Expand Up @@ -55,6 +59,7 @@ class CAPTURE_EXPORT SampleBufferTransformer {
void Reconfigure(Transformer transformer,
OSType destination_pixel_format,
const gfx::Size& destination_size,
int rotation_angle,
absl::optional<size_t> buffer_pool_size = absl::nullopt);

// Converts the input buffer to an IOSurface-backed pixel buffer according to
Expand All @@ -65,6 +70,12 @@ class CAPTURE_EXPORT SampleBufferTransformer {
base::ScopedCFTypeRef<CVPixelBufferRef> Transform(
CMSampleBufferRef sample_buffer);

#if BUILDFLAG(IS_IOS)
// Rotates a source pixel buffer and returns rotated pixel buffer as a output.
base::ScopedCFTypeRef<CVPixelBufferRef> Rotate(
CVPixelBufferRef source_pixel_buffer);
#endif

private:
friend std::unique_ptr<SampleBufferTransformer>
std::make_unique<SampleBufferTransformer>();
Expand Down Expand Up @@ -114,6 +125,12 @@ class CAPTURE_EXPORT SampleBufferTransformer {
// For kLibyuv in cases where an intermediate buffer is needed.
std::vector<uint8_t> intermediate_i420_buffer_;
std::vector<uint8_t> intermediate_nv12_buffer_;

int rotation_angle_;
#if BUILDFLAG(IS_IOS)
std::unique_ptr<PixelBufferPool> rotated_destination_pixel_buffer_pool_;
std::unique_ptr<PixelBufferRotator> pixel_buffer_rotator_;
#endif
};

} // namespace media
Expand Down

0 comments on commit f777cb3

Please sign in to comment.