diff options
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.mm | 607 |
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)); |