summaryrefslogtreecommitdiff
path: root/chromium/media/capture/video/mac/sample_buffer_transformer_mac_unittest.mm
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/media/capture/video/mac/sample_buffer_transformer_mac_unittest.mm')
-rw-r--r--chromium/media/capture/video/mac/sample_buffer_transformer_mac_unittest.mm607
1 files changed, 511 insertions, 96 deletions
diff --git a/chromium/media/capture/video/mac/sample_buffer_transformer_mac_unittest.mm b/chromium/media/capture/video/mac/sample_buffer_transformer_mac_unittest.mm
index dde2a940139..3c83dd24d4c 100644
--- a/chromium/media/capture/video/mac/sample_buffer_transformer_mac_unittest.mm
+++ b/chromium/media/capture/video/mac/sample_buffer_transformer_mac_unittest.mm
@@ -7,7 +7,8 @@
#include <tuple>
#include "base/logging.h"
-#include "base/test/scoped_feature_list.h"
+#include "base/mac/scoped_cftyperef.h"
+#include "build/build_config.h"
#include "media/capture/video/mac/test/pixel_buffer_test_utils_mac.h"
#include "media/capture/video/mac/video_capture_device_avfoundation_utils_mac.h"
#include "testing/gmock/include/gmock/gmock.h"
@@ -147,6 +148,116 @@ base::ScopedCFTypeRef<CVPixelBufferRef> CreatePixelBuffer(OSType pixel_format,
return pixel_buffer;
}
+enum class PixelBufferType {
+ kIoSurfaceBacked,
+ kIoSurfaceMissing,
+};
+
+void NonPlanarCvPixelBufferReleaseCallback(void* releaseRef, const void* data) {
+ free(const_cast<void*>(data));
+}
+
+void PlanarCvPixelBufferReleaseCallback(void* releaseRef,
+ const void* data,
+ size_t size,
+ size_t num_planes,
+ const void* planes[]) {
+ free(const_cast<void*>(data));
+ for (size_t plane = 0; plane < num_planes; ++plane)
+ free(const_cast<void*>(planes[plane]));
+}
+
+std::pair<uint8_t*, size_t> GetDataAndStride(CVPixelBufferRef pixel_buffer,
+ size_t plane) {
+ if (CVPixelBufferIsPlanar(pixel_buffer)) {
+ return {static_cast<uint8_t*>(
+ CVPixelBufferGetBaseAddressOfPlane(pixel_buffer, plane)),
+ CVPixelBufferGetBytesPerRowOfPlane(pixel_buffer, plane)};
+ } else {
+ DCHECK_EQ(plane, 0u) << "Non-planar pixel buffers only have 1 plane.";
+ return {static_cast<uint8_t*>(CVPixelBufferGetBaseAddress(pixel_buffer)),
+ CVPixelBufferGetBytesPerRow(pixel_buffer)};
+ }
+}
+
+base::ScopedCFTypeRef<CVPixelBufferRef> AddPadding(
+ CVPixelBufferRef pixel_buffer,
+ OSType pixel_format,
+ int width,
+ int height,
+ int padding) {
+ size_t num_planes = CVPixelBufferGetPlaneCount(pixel_buffer);
+ size_t padded_size = 0;
+ std::vector<size_t> plane_widths;
+ std::vector<size_t> plane_heights;
+ std::vector<size_t> plane_strides;
+ if (CVPixelBufferIsPlanar(pixel_buffer)) {
+ for (size_t plane = 0; plane < num_planes; ++plane) {
+ size_t plane_stride =
+ CVPixelBufferGetBytesPerRowOfPlane(pixel_buffer, plane);
+ size_t padded_stride = plane_stride + padding;
+ size_t h = CVPixelBufferGetHeightOfPlane(pixel_buffer, plane);
+ size_t w = CVPixelBufferGetWidthOfPlane(pixel_buffer, plane);
+ plane_heights.push_back(h);
+ plane_widths.push_back(w);
+ plane_strides.push_back(padded_stride);
+ padded_size += h * padded_stride;
+ }
+ } else {
+ // CVPixelBufferGetPlaneCount returns 0 for non-planar buffers.
+ num_planes = 1;
+ size_t plane_stride = CVPixelBufferGetBytesPerRow(pixel_buffer);
+ size_t padded_stride = plane_stride + padding;
+ size_t h = CVPixelBufferGetHeight(pixel_buffer);
+ padded_size += h * padded_stride;
+ plane_heights.push_back(h);
+ plane_strides.push_back(padded_stride);
+ }
+ std::vector<void*> plane_address;
+ CHECK_EQ(
+ CVPixelBufferLockBaseAddress(pixel_buffer, kCVPixelBufferLock_ReadOnly),
+ kCVReturnSuccess);
+ // Allocate and copy each plane.
+ for (size_t plane = 0; plane < num_planes; ++plane) {
+ plane_address.push_back(
+ calloc(1, plane_strides[plane] * plane_heights[plane]));
+ uint8_t* dst_ptr = static_cast<uint8_t*>(plane_address[plane]);
+ uint8_t* src_ptr;
+ size_t plane_stride;
+ std::tie(src_ptr, plane_stride) = GetDataAndStride(pixel_buffer, plane);
+ CHECK(dst_ptr);
+ CHECK(src_ptr);
+ for (size_t r = 0; r < plane_heights[plane]; ++r) {
+ memcpy(dst_ptr, src_ptr, plane_stride);
+ src_ptr += plane_stride;
+ dst_ptr += plane_strides[plane];
+ }
+ }
+ CHECK_EQ(
+ CVPixelBufferUnlockBaseAddress(pixel_buffer, kCVPixelBufferLock_ReadOnly),
+ kCVReturnSuccess);
+
+ base::ScopedCFTypeRef<CVPixelBufferRef> padded_pixel_buffer;
+ CVReturn create_buffer_result;
+ if (CVPixelBufferIsPlanar(pixel_buffer)) {
+ // Without some memory block the callback won't be called and we leak the
+ // planar data.
+ void* descriptor = calloc(1, sizeof(CVPlanarPixelBufferInfo_YCbCrPlanar));
+ create_buffer_result = CVPixelBufferCreateWithPlanarBytes(
+ nullptr, width, height, pixel_format, descriptor, 0, num_planes,
+ plane_address.data(), plane_widths.data(), plane_heights.data(),
+ plane_strides.data(), &PlanarCvPixelBufferReleaseCallback,
+ plane_strides.data(), nullptr, padded_pixel_buffer.InitializeInto());
+ } else {
+ create_buffer_result = CVPixelBufferCreateWithBytes(
+ nullptr, width, height, pixel_format, plane_address[0],
+ plane_strides[0], &NonPlanarCvPixelBufferReleaseCallback, nullptr,
+ nullptr, padded_pixel_buffer.InitializeInto());
+ }
+ DCHECK_EQ(create_buffer_result, kCVReturnSuccess);
+ return padded_pixel_buffer;
+}
+
base::ScopedCFTypeRef<CMSampleBufferRef> CreateSampleBuffer(
OSType pixel_format,
int width,
@@ -154,19 +265,40 @@ base::ScopedCFTypeRef<CMSampleBufferRef> CreateSampleBuffer(
uint8_t r,
uint8_t g,
uint8_t b,
- bool iosurface_backed = true) {
- base::ScopedCFTypeRef<CVPixelBufferRef> pixel_buffer;
- if (iosurface_backed) {
- pixel_buffer = CreatePixelBuffer(pixel_format, width, height, r, g, b);
- } else {
- CVPixelBufferCreate(nullptr, width, height, pixel_format, nullptr,
- pixel_buffer.InitializeInto());
+ PixelBufferType pixel_buffer_type,
+ size_t padding = 0) {
+ base::ScopedCFTypeRef<CVPixelBufferRef> pixel_buffer =
+ CreatePixelBuffer(pixel_format, width, height, r, g, b);
+ if (padding != 0) {
+ CHECK_EQ(pixel_buffer_type, PixelBufferType::kIoSurfaceMissing)
+ << "Padding does not work with IOSurfaces.";
+ }
+ if (pixel_buffer_type == PixelBufferType::kIoSurfaceMissing) {
+ // Our pixel buffer currently has an IOSurface. To get rid of it, we perform
+ // a pixel buffer transfer to a destination pixel buffer that is not backed
+ // by an IOSurface. The resulting pixel buffer will have the desired color.
+ base::ScopedCFTypeRef<CVPixelBufferRef> iosurfaceless_pixel_buffer;
+ CVReturn create_buffer_result =
+ CVPixelBufferCreate(nullptr, width, height, pixel_format, nullptr,
+ iosurfaceless_pixel_buffer.InitializeInto());
+ DCHECK_EQ(create_buffer_result, kCVReturnSuccess);
+ PixelBufferTransferer transferer;
+ bool success =
+ transferer.TransferImage(pixel_buffer, iosurfaceless_pixel_buffer);
+ DCHECK(success);
+ DCHECK(!CVPixelBufferGetIOSurface(iosurfaceless_pixel_buffer));
+ pixel_buffer = iosurfaceless_pixel_buffer;
+
+ if (padding > 0) {
+ pixel_buffer =
+ AddPadding(pixel_buffer, pixel_format, width, height, padding);
+ }
}
// Wrap the pixel buffer in a sample buffer.
- CMFormatDescriptionRef format_description;
+ base::ScopedCFTypeRef<CMFormatDescriptionRef> format_description;
OSStatus status = CMVideoFormatDescriptionCreateForImageBuffer(
- nil, pixel_buffer, &format_description);
+ nil, pixel_buffer, format_description.InitializeInto());
DCHECK(status == noErr);
// Dummy information to make CMSampleBufferCreateForImageBuffer() happy.
@@ -189,16 +321,24 @@ base::ScopedCFTypeRef<CMSampleBufferRef> CreateMjpegSampleBuffer(
size_t mjpeg_data_size,
size_t width,
size_t height) {
- CMBlockBufferRef data_buffer;
+ CMBlockBufferCustomBlockSource source = {0};
+ source.FreeBlock = [](void* refcon, void* doomedMemoryBlock,
+ size_t sizeInBytes) {
+ // Do nothing. The data to be released is not dynamically allocated in this
+ // test code.
+ };
+
+ base::ScopedCFTypeRef<CMBlockBufferRef> data_buffer;
OSStatus status = CMBlockBufferCreateWithMemoryBlock(
nil, const_cast<void*>(static_cast<const void*>(mjpeg_data)),
- mjpeg_data_size, nil, nil, 0, mjpeg_data_size, 0, &data_buffer);
+ mjpeg_data_size, nil, &source, 0, mjpeg_data_size, 0,
+ data_buffer.InitializeInto());
DCHECK(status == noErr);
- CMFormatDescriptionRef format_description;
- status =
- CMVideoFormatDescriptionCreate(nil, kCMVideoCodecType_JPEG_OpenDML, width,
- height, nil, &format_description);
+ base::ScopedCFTypeRef<CMFormatDescriptionRef> format_description;
+ status = CMVideoFormatDescriptionCreate(nil, kCMVideoCodecType_JPEG_OpenDML,
+ width, height, nil,
+ format_description.InitializeInto());
DCHECK(status == noErr);
// Dummy information to make CMSampleBufferCreateReady() happy.
@@ -247,38 +387,130 @@ TEST_P(SampleBufferTransformerPixelTransferTest, CanConvertFullScale) {
base::ScopedCFTypeRef<CMSampleBufferRef> input_sample_buffer =
CreateSampleBuffer(input_pixel_format, kFullResolutionWidth,
- kFullResolutionHeight, kColorR, kColorG, kColorB);
+ kFullResolutionHeight, kColorR, kColorG, kColorB,
+ PixelBufferType::kIoSurfaceBacked);
std::unique_ptr<SampleBufferTransformer> transformer =
SampleBufferTransformer::Create();
transformer->Reconfigure(
SampleBufferTransformer::Transformer::kPixelBufferTransfer,
- output_pixel_format, kFullResolutionWidth, kFullResolutionHeight, 1);
+ output_pixel_format,
+ gfx::Size(kFullResolutionWidth, kFullResolutionHeight), 1);
base::ScopedCFTypeRef<CVPixelBufferRef> output_pixel_buffer =
transformer->Transform(input_sample_buffer);
+ EXPECT_TRUE(CVPixelBufferGetIOSurface(output_pixel_buffer));
EXPECT_EQ(kFullResolutionWidth, CVPixelBufferGetWidth(output_pixel_buffer));
EXPECT_EQ(kFullResolutionHeight, CVPixelBufferGetHeight(output_pixel_buffer));
EXPECT_TRUE(
PixelBufferIsSingleColor(output_pixel_buffer, kColorR, kColorG, kColorB));
}
-TEST_P(SampleBufferTransformerPixelTransferTest, CanConvertAndScaleDown) {
+#if defined(ARCH_CPU_ARM64)
+// Bulk-disabled for arm64 bot stabilization: https://crbug.com/1154345
+#define MAYBE_CanConvertAndScaleDown DISABLED_CanConvertAndScaleDown
+#else
+#define MAYBE_CanConvertAndScaleDown CanConvertAndScaleDown
+#endif
+
+TEST_P(SampleBufferTransformerPixelTransferTest, MAYBE_CanConvertAndScaleDown) {
OSType input_pixel_format;
OSType output_pixel_format;
std::tie(input_pixel_format, output_pixel_format) = GetParam();
base::ScopedCFTypeRef<CMSampleBufferRef> input_sample_buffer =
CreateSampleBuffer(input_pixel_format, kFullResolutionWidth,
- kFullResolutionHeight, kColorR, kColorG, kColorB);
+ kFullResolutionHeight, kColorR, kColorG, kColorB,
+ PixelBufferType::kIoSurfaceBacked);
std::unique_ptr<SampleBufferTransformer> transformer =
SampleBufferTransformer::Create();
transformer->Reconfigure(
SampleBufferTransformer::Transformer::kPixelBufferTransfer,
- output_pixel_format, kScaledDownResolutionWidth,
- kScaledDownResolutionHeight, 1);
+ output_pixel_format,
+ gfx::Size(kScaledDownResolutionWidth, kScaledDownResolutionHeight), 1);
base::ScopedCFTypeRef<CVPixelBufferRef> output_pixel_buffer =
transformer->Transform(input_sample_buffer);
+ EXPECT_TRUE(CVPixelBufferGetIOSurface(output_pixel_buffer));
+ EXPECT_EQ(kScaledDownResolutionWidth,
+ CVPixelBufferGetWidth(output_pixel_buffer));
+ EXPECT_EQ(kScaledDownResolutionHeight,
+ CVPixelBufferGetHeight(output_pixel_buffer));
+ EXPECT_TRUE(
+ PixelBufferIsSingleColor(output_pixel_buffer, kColorR, kColorG, kColorB));
+}
+
+TEST_P(SampleBufferTransformerPixelTransferTest,
+ CanConvertAndScaleDownWhenIoSurfaceIsMissing) {
+ OSType input_pixel_format;
+ OSType output_pixel_format;
+ std::tie(input_pixel_format, output_pixel_format) = GetParam();
+
+ base::ScopedCFTypeRef<CMSampleBufferRef> input_sample_buffer =
+ CreateSampleBuffer(input_pixel_format, kFullResolutionWidth,
+ kFullResolutionHeight, kColorR, kColorG, kColorB,
+ PixelBufferType::kIoSurfaceMissing);
+ std::unique_ptr<SampleBufferTransformer> transformer =
+ SampleBufferTransformer::Create();
+ transformer->Reconfigure(
+ SampleBufferTransformer::Transformer::kPixelBufferTransfer,
+ output_pixel_format,
+ gfx::Size(kScaledDownResolutionWidth, kScaledDownResolutionHeight), 1);
+ base::ScopedCFTypeRef<CVPixelBufferRef> output_pixel_buffer =
+ transformer->Transform(input_sample_buffer);
+
+ EXPECT_TRUE(CVPixelBufferGetIOSurface(output_pixel_buffer));
+ EXPECT_EQ(kScaledDownResolutionWidth,
+ CVPixelBufferGetWidth(output_pixel_buffer));
+ EXPECT_EQ(kScaledDownResolutionHeight,
+ CVPixelBufferGetHeight(output_pixel_buffer));
+ EXPECT_TRUE(
+ PixelBufferIsSingleColor(output_pixel_buffer, kColorR, kColorG, kColorB));
+}
+
+TEST_P(SampleBufferTransformerPixelTransferTest,
+ CanConvertWithPaddingFullScale) {
+ OSType input_pixel_format;
+ OSType output_pixel_format;
+ std::tie(input_pixel_format, output_pixel_format) = GetParam();
+ base::ScopedCFTypeRef<CMSampleBufferRef> input_sample_buffer =
+ CreateSampleBuffer(input_pixel_format, kFullResolutionWidth,
+ kFullResolutionHeight, kColorR, kColorG, kColorB,
+ PixelBufferType::kIoSurfaceMissing, /*padding*/ 100);
+ std::unique_ptr<SampleBufferTransformer> transformer =
+ SampleBufferTransformer::Create();
+ transformer->Reconfigure(
+ SampleBufferTransformer::Transformer::kPixelBufferTransfer,
+ output_pixel_format,
+ gfx::Size(kFullResolutionWidth, kFullResolutionHeight), 1);
+ base::ScopedCFTypeRef<CVPixelBufferRef> output_pixel_buffer =
+ transformer->Transform(input_sample_buffer);
+
+ EXPECT_TRUE(CVPixelBufferGetIOSurface(output_pixel_buffer));
+ EXPECT_EQ(kFullResolutionWidth, CVPixelBufferGetWidth(output_pixel_buffer));
+ EXPECT_EQ(kFullResolutionHeight, CVPixelBufferGetHeight(output_pixel_buffer));
+ EXPECT_TRUE(
+ PixelBufferIsSingleColor(output_pixel_buffer, kColorR, kColorG, kColorB));
+}
+
+TEST_P(SampleBufferTransformerPixelTransferTest,
+ CanConvertAndScaleWithPadding) {
+ OSType input_pixel_format;
+ OSType output_pixel_format;
+ std::tie(input_pixel_format, output_pixel_format) = GetParam();
+ base::ScopedCFTypeRef<CMSampleBufferRef> input_sample_buffer =
+ CreateSampleBuffer(input_pixel_format, kFullResolutionWidth,
+ kFullResolutionHeight, kColorR, kColorG, kColorB,
+ PixelBufferType::kIoSurfaceMissing, /*padding*/ 100);
+ std::unique_ptr<SampleBufferTransformer> transformer =
+ SampleBufferTransformer::Create();
+ transformer->Reconfigure(
+ SampleBufferTransformer::Transformer::kPixelBufferTransfer,
+ output_pixel_format,
+ gfx::Size(kScaledDownResolutionWidth, kScaledDownResolutionHeight), 1);
+ base::ScopedCFTypeRef<CVPixelBufferRef> output_pixel_buffer =
+ transformer->Transform(input_sample_buffer);
+
+ EXPECT_TRUE(CVPixelBufferGetIOSurface(output_pixel_buffer));
EXPECT_EQ(kScaledDownResolutionWidth,
CVPixelBufferGetWidth(output_pixel_buffer));
EXPECT_EQ(kScaledDownResolutionHeight,
@@ -304,37 +536,116 @@ TEST_P(SampleBufferTransformerLibyuvTest, CanConvertFullScale) {
base::ScopedCFTypeRef<CMSampleBufferRef> input_sample_buffer =
CreateSampleBuffer(input_pixel_format, kFullResolutionWidth,
- kFullResolutionHeight, kColorR, kColorG, kColorB);
+ kFullResolutionHeight, kColorR, kColorG, kColorB,
+ PixelBufferType::kIoSurfaceBacked);
std::unique_ptr<SampleBufferTransformer> transformer =
SampleBufferTransformer::Create();
- transformer->Reconfigure(SampleBufferTransformer::Transformer::kLibyuv,
- output_pixel_format, kFullResolutionWidth,
- kFullResolutionHeight, 1);
+ transformer->Reconfigure(
+ SampleBufferTransformer::Transformer::kLibyuv, output_pixel_format,
+ gfx::Size(kFullResolutionWidth, kFullResolutionHeight), 1);
base::ScopedCFTypeRef<CVPixelBufferRef> output_pixel_buffer =
transformer->Transform(input_sample_buffer);
+ EXPECT_TRUE(CVPixelBufferGetIOSurface(output_pixel_buffer));
EXPECT_EQ(kFullResolutionWidth, CVPixelBufferGetWidth(output_pixel_buffer));
EXPECT_EQ(kFullResolutionHeight, CVPixelBufferGetHeight(output_pixel_buffer));
EXPECT_TRUE(
PixelBufferIsSingleColor(output_pixel_buffer, kColorR, kColorG, kColorB));
}
-TEST_P(SampleBufferTransformerLibyuvTest, CanConvertAndScaleDown) {
+TEST_P(SampleBufferTransformerLibyuvTest, MAYBE_CanConvertAndScaleDown) {
OSType input_pixel_format;
OSType output_pixel_format;
std::tie(input_pixel_format, output_pixel_format) = GetParam();
base::ScopedCFTypeRef<CMSampleBufferRef> input_sample_buffer =
CreateSampleBuffer(input_pixel_format, kFullResolutionWidth,
- kFullResolutionHeight, kColorR, kColorG, kColorB);
+ kFullResolutionHeight, kColorR, kColorG, kColorB,
+ PixelBufferType::kIoSurfaceBacked);
std::unique_ptr<SampleBufferTransformer> transformer =
SampleBufferTransformer::Create();
- transformer->Reconfigure(SampleBufferTransformer::Transformer::kLibyuv,
- output_pixel_format, kScaledDownResolutionWidth,
- kScaledDownResolutionHeight, 1);
+ transformer->Reconfigure(
+ SampleBufferTransformer::Transformer::kLibyuv, output_pixel_format,
+ gfx::Size(kScaledDownResolutionWidth, kScaledDownResolutionHeight), 1);
base::ScopedCFTypeRef<CVPixelBufferRef> output_pixel_buffer =
transformer->Transform(input_sample_buffer);
+ EXPECT_TRUE(CVPixelBufferGetIOSurface(output_pixel_buffer));
+ EXPECT_EQ(kScaledDownResolutionWidth,
+ CVPixelBufferGetWidth(output_pixel_buffer));
+ EXPECT_EQ(kScaledDownResolutionHeight,
+ CVPixelBufferGetHeight(output_pixel_buffer));
+ EXPECT_TRUE(
+ PixelBufferIsSingleColor(output_pixel_buffer, kColorR, kColorG, kColorB));
+}
+
+TEST_P(SampleBufferTransformerLibyuvTest, CanConvertWithPaddingFullScale) {
+ OSType input_pixel_format;
+ OSType output_pixel_format;
+ std::tie(input_pixel_format, output_pixel_format) = GetParam();
+ base::ScopedCFTypeRef<CMSampleBufferRef> input_sample_buffer =
+ CreateSampleBuffer(input_pixel_format, kFullResolutionWidth,
+ kFullResolutionHeight, kColorR, kColorG, kColorB,
+ PixelBufferType::kIoSurfaceMissing, /*padding*/ 100);
+ std::unique_ptr<SampleBufferTransformer> transformer =
+ SampleBufferTransformer::Create();
+ transformer->Reconfigure(
+ SampleBufferTransformer::Transformer::kLibyuv, output_pixel_format,
+ gfx::Size(kFullResolutionWidth, kFullResolutionHeight), 1);
+ base::ScopedCFTypeRef<CVPixelBufferRef> output_pixel_buffer =
+ transformer->Transform(input_sample_buffer);
+
+ EXPECT_TRUE(CVPixelBufferGetIOSurface(output_pixel_buffer));
+ EXPECT_EQ(kFullResolutionWidth, CVPixelBufferGetWidth(output_pixel_buffer));
+ EXPECT_EQ(kFullResolutionHeight, CVPixelBufferGetHeight(output_pixel_buffer));
+ EXPECT_TRUE(
+ PixelBufferIsSingleColor(output_pixel_buffer, kColorR, kColorG, kColorB));
+}
+
+TEST_P(SampleBufferTransformerLibyuvTest, CanConvertAndScaleWithPadding) {
+ OSType input_pixel_format;
+ OSType output_pixel_format;
+ std::tie(input_pixel_format, output_pixel_format) = GetParam();
+ base::ScopedCFTypeRef<CMSampleBufferRef> input_sample_buffer =
+ CreateSampleBuffer(input_pixel_format, kFullResolutionWidth,
+ kFullResolutionHeight, kColorR, kColorG, kColorB,
+ PixelBufferType::kIoSurfaceMissing, /*padding*/ 100);
+ std::unique_ptr<SampleBufferTransformer> transformer =
+ SampleBufferTransformer::Create();
+ transformer->Reconfigure(
+ SampleBufferTransformer::Transformer::kLibyuv, output_pixel_format,
+ gfx::Size(kScaledDownResolutionWidth, kScaledDownResolutionHeight), 1);
+ base::ScopedCFTypeRef<CVPixelBufferRef> output_pixel_buffer =
+ transformer->Transform(input_sample_buffer);
+
+ EXPECT_TRUE(CVPixelBufferGetIOSurface(output_pixel_buffer));
+ EXPECT_EQ(kScaledDownResolutionWidth,
+ CVPixelBufferGetWidth(output_pixel_buffer));
+ EXPECT_EQ(kScaledDownResolutionHeight,
+ CVPixelBufferGetHeight(output_pixel_buffer));
+ EXPECT_TRUE(
+ PixelBufferIsSingleColor(output_pixel_buffer, kColorR, kColorG, kColorB));
+}
+
+TEST_P(SampleBufferTransformerLibyuvTest,
+ CanConvertAndScaleDownWhenIoSurfaceIsMissing) {
+ OSType input_pixel_format;
+ OSType output_pixel_format;
+ std::tie(input_pixel_format, output_pixel_format) = GetParam();
+
+ base::ScopedCFTypeRef<CMSampleBufferRef> input_sample_buffer =
+ CreateSampleBuffer(input_pixel_format, kFullResolutionWidth,
+ kFullResolutionHeight, kColorR, kColorG, kColorB,
+ PixelBufferType::kIoSurfaceMissing);
+ std::unique_ptr<SampleBufferTransformer> transformer =
+ SampleBufferTransformer::Create();
+ transformer->Reconfigure(
+ SampleBufferTransformer::Transformer::kLibyuv, output_pixel_format,
+ gfx::Size(kScaledDownResolutionWidth, kScaledDownResolutionHeight), 1);
+ base::ScopedCFTypeRef<CVPixelBufferRef> output_pixel_buffer =
+ transformer->Transform(input_sample_buffer);
+
+ EXPECT_TRUE(CVPixelBufferGetIOSurface(output_pixel_buffer));
EXPECT_EQ(kScaledDownResolutionWidth,
CVPixelBufferGetWidth(output_pixel_buffer));
EXPECT_EQ(kScaledDownResolutionHeight,
@@ -361,8 +672,8 @@ TEST_P(SampleBufferTransformerMjpegTest, CanConvertFullScale) {
std::unique_ptr<SampleBufferTransformer> transformer =
SampleBufferTransformer::Create();
transformer->Reconfigure(SampleBufferTransformer::Transformer::kLibyuv,
- output_pixel_format, kExampleJpegWidth,
- kExampleJpegHeight, 1);
+ output_pixel_format,
+ gfx::Size(kExampleJpegWidth, kExampleJpegHeight), 1);
base::ScopedCFTypeRef<CVPixelBufferRef> output_pixel_buffer =
transformer->Transform(input_sample_buffer);
@@ -372,16 +683,16 @@ TEST_P(SampleBufferTransformerMjpegTest, CanConvertFullScale) {
PixelBufferIsSingleColor(output_pixel_buffer, kColorR, kColorG, kColorB));
}
-TEST_P(SampleBufferTransformerMjpegTest, CanConvertAndScaleDown) {
+TEST_P(SampleBufferTransformerMjpegTest, MAYBE_CanConvertAndScaleDown) {
OSType output_pixel_format = GetParam();
base::ScopedCFTypeRef<CMSampleBufferRef> input_sample_buffer =
CreateExampleMjpegSampleBuffer();
std::unique_ptr<SampleBufferTransformer> transformer =
SampleBufferTransformer::Create();
- transformer->Reconfigure(SampleBufferTransformer::Transformer::kLibyuv,
- output_pixel_format, kExampleJpegScaledDownWidth,
- kExampleJpegScaledDownHeight, 1);
+ transformer->Reconfigure(
+ SampleBufferTransformer::Transformer::kLibyuv, output_pixel_format,
+ gfx::Size(kExampleJpegScaledDownWidth, kExampleJpegScaledDownHeight), 1);
base::ScopedCFTypeRef<CVPixelBufferRef> output_pixel_buffer =
transformer->Transform(input_sample_buffer);
@@ -402,8 +713,8 @@ TEST_P(SampleBufferTransformerMjpegTest,
std::unique_ptr<SampleBufferTransformer> transformer =
SampleBufferTransformer::Create();
transformer->Reconfigure(SampleBufferTransformer::Transformer::kLibyuv,
- output_pixel_format, kExampleJpegWidth,
- kExampleJpegHeight, 1);
+ output_pixel_format,
+ gfx::Size(kExampleJpegWidth, kExampleJpegHeight), 1);
base::ScopedCFTypeRef<CVPixelBufferRef> output_pixel_buffer =
transformer->Transform(input_sample_buffer);
EXPECT_FALSE(output_pixel_buffer);
@@ -414,28 +725,23 @@ INSTANTIATE_TEST_SUITE_P(SampleBufferTransformerTest,
SupportedOutputFormats(),
TestParametersOSTypeToString);
-TEST(SampleBufferTransformerAutoReconfigureTest,
- AutoReconfigureIsEnabledByDefault) {
- EXPECT_TRUE(SampleBufferTransformer::CreateIfAutoReconfigureEnabled());
-}
-
-TEST(SampleBufferTransformerAutoReconfigureTest,
- SourceAndDestinationResolutionMatches) {
- base::test::ScopedFeatureList scoped_feature_list;
- scoped_feature_list.InitAndEnableFeature(kInCaptureConvertToNv12);
+TEST(SampleBufferTransformerBestTransformerForNv12OutputTest,
+ SourceAndDestinationResolutionMatches_InputSampleBuffer) {
std::unique_ptr<SampleBufferTransformer> transformer =
- SampleBufferTransformer::CreateIfAutoReconfigureEnabled();
- ASSERT_TRUE(transformer);
+ SampleBufferTransformer::Create();
base::ScopedCFTypeRef<CMSampleBufferRef> sample0 = CreateSampleBuffer(
kPixelFormatNv12, kFullResolutionWidth, kFullResolutionHeight, kColorR,
- kColorG, kColorB, /*iosurface_backed=*/false);
+ kColorG, kColorB, PixelBufferType::kIoSurfaceMissing);
+ transformer->Reconfigure(
+ SampleBufferTransformer::GetBestTransformerForNv12Output(sample0),
+ kPixelFormatNv12, media::GetSampleBufferSize(sample0));
base::ScopedCFTypeRef<CVPixelBufferRef> output_buffer =
- transformer->AutoReconfigureAndTransform(sample0);
+ transformer->Transform(sample0);
- EXPECT_EQ(kFullResolutionWidth, transformer->destination_width());
- EXPECT_EQ(kFullResolutionHeight, transformer->destination_height());
+ EXPECT_EQ(gfx::Size(kFullResolutionWidth, kFullResolutionHeight),
+ transformer->destination_size());
EXPECT_EQ(kFullResolutionWidth, CVPixelBufferGetWidth(output_buffer));
EXPECT_EQ(kFullResolutionHeight, CVPixelBufferGetHeight(output_buffer));
EXPECT_TRUE(CVPixelBufferGetIOSurface(output_buffer));
@@ -445,12 +751,15 @@ TEST(SampleBufferTransformerAutoReconfigureTest,
base::ScopedCFTypeRef<CMSampleBufferRef> sample1 = CreateSampleBuffer(
kPixelFormatNv12, kScaledDownResolutionWidth, kScaledDownResolutionHeight,
- kColorR, kColorG, kColorB);
+ kColorR, kColorG, kColorB, PixelBufferType::kIoSurfaceBacked);
- output_buffer = transformer->AutoReconfigureAndTransform(sample1);
+ transformer->Reconfigure(
+ SampleBufferTransformer::GetBestTransformerForNv12Output(sample1),
+ kPixelFormatNv12, media::GetSampleBufferSize(sample1));
+ output_buffer = transformer->Transform(sample1);
- EXPECT_EQ(kScaledDownResolutionWidth, transformer->destination_width());
- EXPECT_EQ(kScaledDownResolutionHeight, transformer->destination_height());
+ EXPECT_EQ(gfx::Size(kScaledDownResolutionWidth, kScaledDownResolutionHeight),
+ transformer->destination_size());
EXPECT_EQ(kScaledDownResolutionWidth, CVPixelBufferGetWidth(output_buffer));
EXPECT_EQ(kScaledDownResolutionHeight, CVPixelBufferGetHeight(output_buffer));
EXPECT_TRUE(CVPixelBufferGetIOSurface(output_buffer));
@@ -458,88 +767,194 @@ TEST(SampleBufferTransformerAutoReconfigureTest,
EXPECT_EQ(output_buffer.get(), CMSampleBufferGetImageBuffer(sample1.get()));
}
-TEST(SampleBufferTransformerAutoReconfigureTest,
+// Same test as above, verifying that Transform() methods work on pixel buffers
+// directly (so that there's no need to have a sample buffer).
+TEST(SampleBufferTransformerBestTransformerForNv12OutputTest,
+ SourceAndDestinationResolutionMatches_InputPixelBuffer) {
+ std::unique_ptr<SampleBufferTransformer> transformer =
+ SampleBufferTransformer::Create();
+
+ base::ScopedCFTypeRef<CMSampleBufferRef> sample0 = CreateSampleBuffer(
+ kPixelFormatNv12, kFullResolutionWidth, kFullResolutionHeight, kColorR,
+ kColorG, kColorB, PixelBufferType::kIoSurfaceMissing);
+ CVPixelBufferRef pixel0 = CMSampleBufferGetImageBuffer(sample0);
+ ASSERT_TRUE(pixel0);
+
+ transformer->Reconfigure(
+ SampleBufferTransformer::kBestTransformerForPixelBufferToNv12Output,
+ kPixelFormatNv12, media::GetPixelBufferSize(pixel0));
+ base::ScopedCFTypeRef<CVPixelBufferRef> output_buffer =
+ transformer->Transform(pixel0);
+
+ EXPECT_EQ(gfx::Size(kFullResolutionWidth, kFullResolutionHeight),
+ transformer->destination_size());
+ EXPECT_EQ(kFullResolutionWidth, CVPixelBufferGetWidth(output_buffer));
+ EXPECT_EQ(kFullResolutionHeight, CVPixelBufferGetHeight(output_buffer));
+ EXPECT_TRUE(CVPixelBufferGetIOSurface(output_buffer));
+ // Because pixel0 has no underlying IOSurface, it should not be returned from
+ // the transformer.
+ EXPECT_NE(output_buffer.get(), pixel0);
+
+ base::ScopedCFTypeRef<CMSampleBufferRef> sample1 = CreateSampleBuffer(
+ kPixelFormatNv12, kScaledDownResolutionWidth, kScaledDownResolutionHeight,
+ kColorR, kColorG, kColorB, PixelBufferType::kIoSurfaceBacked);
+ CVPixelBufferRef pixel1 = CMSampleBufferGetImageBuffer(sample1);
+ ASSERT_TRUE(pixel1);
+
+ transformer->Reconfigure(
+ SampleBufferTransformer::kBestTransformerForPixelBufferToNv12Output,
+ kPixelFormatNv12, media::GetPixelBufferSize(pixel1));
+ output_buffer = transformer->Transform(pixel1);
+
+ EXPECT_EQ(gfx::Size(kScaledDownResolutionWidth, kScaledDownResolutionHeight),
+ transformer->destination_size());
+ EXPECT_EQ(kScaledDownResolutionWidth, CVPixelBufferGetWidth(output_buffer));
+ EXPECT_EQ(kScaledDownResolutionHeight, CVPixelBufferGetHeight(output_buffer));
+ EXPECT_TRUE(CVPixelBufferGetIOSurface(output_buffer));
+ // Because pixel1 does have an IOSurface, it can be returned directly.
+ EXPECT_EQ(output_buffer.get(), pixel1);
+}
+
+TEST(SampleBufferTransformerBestTransformerForNv12OutputTest,
+ CanConvertAndScaleDown_InputPixelBuffer) {
+ std::unique_ptr<SampleBufferTransformer> transformer =
+ SampleBufferTransformer::Create();
+
+ base::ScopedCFTypeRef<CMSampleBufferRef> sample_buffer = CreateSampleBuffer(
+ kPixelFormatNv12, kFullResolutionWidth, kFullResolutionHeight, kColorR,
+ kColorG, kColorB, PixelBufferType::kIoSurfaceBacked);
+ CVPixelBufferRef pixel_buffer = CMSampleBufferGetImageBuffer(sample_buffer);
+ ASSERT_TRUE(pixel_buffer);
+
+ transformer->Reconfigure(
+ SampleBufferTransformer::kBestTransformerForPixelBufferToNv12Output,
+ kPixelFormatNv12,
+ gfx::Size(kScaledDownResolutionWidth, kScaledDownResolutionHeight));
+ base::ScopedCFTypeRef<CVPixelBufferRef> output_buffer =
+ transformer->Transform(pixel_buffer);
+
+ EXPECT_TRUE(CVPixelBufferGetIOSurface(output_buffer));
+ EXPECT_EQ(kScaledDownResolutionWidth, CVPixelBufferGetWidth(output_buffer));
+ EXPECT_EQ(kScaledDownResolutionHeight, CVPixelBufferGetHeight(output_buffer));
+ EXPECT_TRUE(
+ PixelBufferIsSingleColor(output_buffer, kColorR, kColorG, kColorB));
+}
+
+TEST(SampleBufferTransformerBestTransformerForNv12OutputTest,
DestinationPixelFormatIsAlwaysNv12) {
- base::test::ScopedFeatureList scoped_feature_list;
- scoped_feature_list.InitAndEnableFeature(kInCaptureConvertToNv12);
std::unique_ptr<SampleBufferTransformer> transformer =
- SampleBufferTransformer::CreateIfAutoReconfigureEnabled();
- ASSERT_TRUE(transformer);
+ SampleBufferTransformer::Create();
+ base::ScopedCFTypeRef<CMSampleBufferRef> sample = CreateSampleBuffer(
+ kPixelFormatNv12, kScaledDownResolutionWidth, kScaledDownResolutionHeight,
+ kColorR, kColorG, kColorB, PixelBufferType::kIoSurfaceBacked);
+ transformer->Reconfigure(
+ SampleBufferTransformer::GetBestTransformerForNv12Output(sample),
+ kPixelFormatNv12, media::GetSampleBufferSize(sample));
base::ScopedCFTypeRef<CVPixelBufferRef> output_buffer =
- transformer->AutoReconfigureAndTransform(CreateSampleBuffer(
- kPixelFormatNv12, kScaledDownResolutionWidth,
- kScaledDownResolutionHeight, kColorR, kColorG, kColorB));
+ transformer->Transform(sample);
EXPECT_EQ(kPixelFormatNv12, transformer->destination_pixel_format());
EXPECT_EQ(kPixelFormatNv12,
IOSurfaceGetPixelFormat(CVPixelBufferGetIOSurface(output_buffer)));
- output_buffer = transformer->AutoReconfigureAndTransform(CreateSampleBuffer(
- kPixelFormatUyvy, kScaledDownResolutionWidth, kScaledDownResolutionHeight,
- kColorR, kColorG, kColorB));
+ sample = CreateSampleBuffer(kPixelFormatUyvy, kScaledDownResolutionWidth,
+ kScaledDownResolutionHeight, kColorR, kColorG,
+ kColorB, PixelBufferType::kIoSurfaceBacked);
+ transformer->Reconfigure(
+ SampleBufferTransformer::GetBestTransformerForNv12Output(sample),
+ kPixelFormatNv12, media::GetSampleBufferSize(sample));
+ output_buffer = transformer->Transform(sample);
EXPECT_EQ(kPixelFormatNv12, transformer->destination_pixel_format());
EXPECT_EQ(kPixelFormatNv12,
IOSurfaceGetPixelFormat(CVPixelBufferGetIOSurface(output_buffer)));
- output_buffer = transformer->AutoReconfigureAndTransform(CreateSampleBuffer(
- kPixelFormatYuy2, kScaledDownResolutionWidth, kScaledDownResolutionHeight,
- kColorR, kColorG, kColorB));
+ sample = CreateSampleBuffer(kPixelFormatYuy2, kScaledDownResolutionWidth,
+ kScaledDownResolutionHeight, kColorR, kColorG,
+ kColorB, PixelBufferType::kIoSurfaceBacked);
+ transformer->Reconfigure(
+ SampleBufferTransformer::GetBestTransformerForNv12Output(sample),
+ kPixelFormatNv12, media::GetSampleBufferSize(sample));
+ output_buffer = transformer->Transform(sample);
EXPECT_EQ(kPixelFormatNv12, transformer->destination_pixel_format());
EXPECT_EQ(kPixelFormatNv12,
IOSurfaceGetPixelFormat(CVPixelBufferGetIOSurface(output_buffer)));
- output_buffer = transformer->AutoReconfigureAndTransform(CreateSampleBuffer(
- kPixelFormatI420, kScaledDownResolutionWidth, kScaledDownResolutionHeight,
- kColorR, kColorG, kColorB));
+ sample = CreateSampleBuffer(kPixelFormatI420, kScaledDownResolutionWidth,
+ kScaledDownResolutionHeight, kColorR, kColorG,
+ kColorB, PixelBufferType::kIoSurfaceBacked);
+ transformer->Reconfigure(
+ SampleBufferTransformer::GetBestTransformerForNv12Output(sample),
+ kPixelFormatNv12, media::GetSampleBufferSize(sample));
+ output_buffer = transformer->Transform(sample);
EXPECT_EQ(kPixelFormatNv12, transformer->destination_pixel_format());
EXPECT_EQ(kPixelFormatNv12,
IOSurfaceGetPixelFormat(CVPixelBufferGetIOSurface(output_buffer)));
- output_buffer = transformer->AutoReconfigureAndTransform(
- CreateExampleMjpegSampleBuffer());
+ sample = CreateExampleMjpegSampleBuffer();
+ transformer->Reconfigure(
+ SampleBufferTransformer::GetBestTransformerForNv12Output(sample),
+ kPixelFormatNv12, media::GetSampleBufferSize(sample));
+ output_buffer = transformer->Transform(sample);
EXPECT_EQ(kPixelFormatNv12, transformer->destination_pixel_format());
EXPECT_EQ(kPixelFormatNv12,
IOSurfaceGetPixelFormat(CVPixelBufferGetIOSurface(output_buffer)));
}
-TEST(SampleBufferTransformerAutoReconfigureTest, UsesBestTransformerPaths) {
- base::test::ScopedFeatureList scoped_feature_list;
- scoped_feature_list.InitAndEnableFeature(kInCaptureConvertToNv12);
+TEST(SampleBufferTransformerBestTransformerForNv12OutputTest,
+ UsesBestTransformerPaths) {
std::unique_ptr<SampleBufferTransformer> transformer =
- SampleBufferTransformer::CreateIfAutoReconfigureEnabled();
- ASSERT_TRUE(transformer);
+ SampleBufferTransformer::Create();
+ base::ScopedCFTypeRef<CMSampleBufferRef> sample = CreateSampleBuffer(
+ kPixelFormatNv12, kScaledDownResolutionWidth, kScaledDownResolutionHeight,
+ kColorR, kColorG, kColorB, PixelBufferType::kIoSurfaceBacked);
+ transformer->Reconfigure(
+ SampleBufferTransformer::GetBestTransformerForNv12Output(sample),
+ kPixelFormatNv12, media::GetSampleBufferSize(sample));
base::ScopedCFTypeRef<CVPixelBufferRef> output_buffer =
- transformer->AutoReconfigureAndTransform(CreateSampleBuffer(
- kPixelFormatNv12, kScaledDownResolutionWidth,
- kScaledDownResolutionHeight, kColorR, kColorG, kColorB));
+ transformer->Transform(sample);
EXPECT_EQ(SampleBufferTransformer::Transformer::kPixelBufferTransfer,
transformer->transformer());
EXPECT_TRUE(CVPixelBufferGetIOSurface(output_buffer));
- output_buffer = transformer->AutoReconfigureAndTransform(CreateSampleBuffer(
- kPixelFormatUyvy, kScaledDownResolutionWidth, kScaledDownResolutionHeight,
- kColorR, kColorG, kColorB));
+ sample = CreateSampleBuffer(kPixelFormatUyvy, kScaledDownResolutionWidth,
+ kScaledDownResolutionHeight, kColorR, kColorG,
+ kColorB, PixelBufferType::kIoSurfaceBacked);
+ transformer->Reconfigure(
+ SampleBufferTransformer::GetBestTransformerForNv12Output(sample),
+ kPixelFormatNv12, media::GetSampleBufferSize(sample));
+ output_buffer = transformer->Transform(sample);
EXPECT_EQ(SampleBufferTransformer::Transformer::kPixelBufferTransfer,
transformer->transformer());
EXPECT_TRUE(CVPixelBufferGetIOSurface(output_buffer));
- output_buffer = transformer->AutoReconfigureAndTransform(CreateSampleBuffer(
- kPixelFormatYuy2, kScaledDownResolutionWidth, kScaledDownResolutionHeight,
- kColorR, kColorG, kColorB));
+ sample = CreateSampleBuffer(kPixelFormatYuy2, kScaledDownResolutionWidth,
+ kScaledDownResolutionHeight, kColorR, kColorG,
+ kColorB, PixelBufferType::kIoSurfaceBacked);
+ transformer->Reconfigure(
+ SampleBufferTransformer::GetBestTransformerForNv12Output(sample),
+ kPixelFormatNv12, media::GetSampleBufferSize(sample));
+ output_buffer = transformer->Transform(sample);
EXPECT_EQ(SampleBufferTransformer::Transformer::kPixelBufferTransfer,
transformer->transformer());
EXPECT_TRUE(CVPixelBufferGetIOSurface(output_buffer));
- output_buffer = transformer->AutoReconfigureAndTransform(CreateSampleBuffer(
- kPixelFormatI420, kScaledDownResolutionWidth, kScaledDownResolutionHeight,
- kColorR, kColorG, kColorB));
+ sample = CreateSampleBuffer(kPixelFormatI420, kScaledDownResolutionWidth,
+ kScaledDownResolutionHeight, kColorR, kColorG,
+ kColorB, PixelBufferType::kIoSurfaceBacked);
+ transformer->Reconfigure(
+ SampleBufferTransformer::GetBestTransformerForNv12Output(sample),
+ kPixelFormatNv12, media::GetSampleBufferSize(sample));
+ output_buffer = transformer->Transform(sample);
EXPECT_EQ(SampleBufferTransformer::Transformer::kPixelBufferTransfer,
transformer->transformer());
EXPECT_TRUE(CVPixelBufferGetIOSurface(output_buffer));
- output_buffer = transformer->AutoReconfigureAndTransform(
- CreateExampleMjpegSampleBuffer());
+ sample = CreateExampleMjpegSampleBuffer();
+ transformer->Reconfigure(
+ SampleBufferTransformer::GetBestTransformerForNv12Output(sample),
+ kPixelFormatNv12, media::GetSampleBufferSize(sample));
+ output_buffer = transformer->Transform(sample);
EXPECT_EQ(SampleBufferTransformer::Transformer::kLibyuv,
transformer->transformer());
EXPECT_TRUE(CVPixelBufferGetIOSurface(output_buffer));