33d683c671
GitOrigin-RevId: 373e3ac1e5839befd95bf7d73ceff3c5f1171969
251 lines
9.0 KiB
Plaintext
251 lines
9.0 KiB
Plaintext
// Copyright 2019 The MediaPipe Authors.
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
#import <UIKit/UIKit.h>
|
|
#import <XCTest/XCTest.h>
|
|
|
|
#import "mediapipe/framework/tool/source.pb.h"
|
|
#import "mediapipe/gpu/gpu_shared_data_internal.h"
|
|
#import "mediapipe/objc/MPPGraph.h"
|
|
#import "mediapipe/objc/MPPGraphTestBase.h"
|
|
#import "mediapipe/objc/util.h"
|
|
|
|
#include "absl/memory/memory.h"
|
|
#import "mediapipe/framework/calculator_framework.h"
|
|
#import "mediapipe/gpu/gl_calculator_helper.h"
|
|
|
|
@interface GLIOSTests : MPPGraphTestBase{
|
|
UIImage* _sourceImage;
|
|
MPPGraph* _graph;
|
|
}
|
|
@end
|
|
|
|
@implementation GLIOSTests
|
|
|
|
- (void)setUp {
|
|
[super setUp];
|
|
|
|
_sourceImage = [self testImageNamed:@"googlelogo_color_272x92dp" extension:@"png"];
|
|
}
|
|
|
|
- (void)tearDown {
|
|
[super tearDown];
|
|
}
|
|
|
|
- (CVPixelBufferRef)redPixelBuffer:(CVPixelBufferRef)input {
|
|
return [self transformPixelBuffer:input
|
|
outputPixelFormat:kCVPixelFormatType_32BGRA
|
|
transformation:^(CVPixelBufferRef input,
|
|
CVPixelBufferRef output) {
|
|
vImage_Buffer vInput = vImageForCVPixelBuffer(input);
|
|
vImage_Buffer vRed = vImageForCVPixelBuffer(output);
|
|
|
|
static const int16_t matrix[16] = {
|
|
0, 0, 0, 0,
|
|
0, 0, 0, 0,
|
|
0, 0, 256, 0,
|
|
0, 0, 0, 256,
|
|
};
|
|
vImage_Error vError = vImageMatrixMultiply_ARGB8888(
|
|
&vInput, &vRed, matrix, 256, NULL, NULL, 0);
|
|
XCTAssertEqual(vError, kvImageNoError);
|
|
}];
|
|
}
|
|
|
|
- (CVPixelBufferRef)luminancePixelBuffer:(CVPixelBufferRef)input {
|
|
return [self transformPixelBuffer:input
|
|
outputPixelFormat:kCVPixelFormatType_32BGRA
|
|
transformation:^(CVPixelBufferRef input,
|
|
CVPixelBufferRef output) {
|
|
vImage_Buffer vInput = vImageForCVPixelBuffer(input);
|
|
vImage_Buffer vLuminance = vImageForCVPixelBuffer(output);
|
|
|
|
// sRGB weights: R 0.2125, G 0.7154, B 0.0721
|
|
static const int16_t matrix[16] = {
|
|
721, 721, 721, 0,
|
|
7154, 7154, 7154, 0,
|
|
2125, 2125, 2125, 0,
|
|
0, 0, 0, 10000,
|
|
};
|
|
vImage_Error vError = vImageMatrixMultiply_ARGB8888(
|
|
&vInput, &vLuminance, matrix, 10000, NULL, NULL, 0);
|
|
XCTAssertEqual(vError, kvImageNoError);
|
|
}];
|
|
}
|
|
|
|
- (CVPixelBufferRef)grayPixelBuffer:(CVPixelBufferRef)input {
|
|
return [self transformPixelBuffer:input
|
|
outputPixelFormat:kCVPixelFormatType_OneComponent8
|
|
transformation:^(CVPixelBufferRef input,
|
|
CVPixelBufferRef output) {
|
|
vImage_Buffer vInput = vImageForCVPixelBuffer(input);
|
|
vImage_Buffer vGray = vImageForCVPixelBuffer(output);
|
|
vImage_Error vError = vImageBGRAToGray(&vInput, &vGray);
|
|
XCTAssertEqual(vError, kvImageNoError);
|
|
}];
|
|
}
|
|
|
|
- (void)testGlConverters {
|
|
CFHolder<CVPixelBufferRef> originalPixelBuffer;
|
|
absl::Status status =
|
|
CreateCVPixelBufferFromCGImage([_sourceImage CGImage], &originalPixelBuffer);
|
|
XCTAssert(status.ok());
|
|
|
|
mediapipe::CalculatorGraphConfig config;
|
|
config.add_input_stream("input_frames");
|
|
auto node = config.add_node();
|
|
node->set_calculator("GpuBufferToImageFrameCalculator");
|
|
node->add_input_stream("input_frames");
|
|
node->add_output_stream("image_frames");
|
|
auto node2 = config.add_node();
|
|
node2->set_calculator("ImageFrameToGpuBufferCalculator");
|
|
node2->add_input_stream("image_frames");
|
|
node2->add_output_stream("output_frames");
|
|
|
|
_graph = [[MPPGraph alloc] initWithGraphConfig:config];
|
|
[_graph addFrameOutputStream:"output_frames"
|
|
outputPacketType:MPPPacketTypePixelBuffer];
|
|
[self testGraph:_graph input:*originalPixelBuffer expectedOutput:*originalPixelBuffer];
|
|
}
|
|
|
|
- (void)testGlConvertersNoOpInserted {
|
|
CFHolder<CVPixelBufferRef> originalPixelBuffer;
|
|
absl::Status status =
|
|
CreateCVPixelBufferFromCGImage([_sourceImage CGImage], &originalPixelBuffer);
|
|
XCTAssert(status.ok());
|
|
|
|
mediapipe::CalculatorGraphConfig config;
|
|
config.add_input_stream("input_frames");
|
|
auto node = config.add_node();
|
|
node->set_calculator("GpuBufferToImageFrameCalculator");
|
|
node->add_input_stream("input_frames");
|
|
node->add_output_stream("image_frames");
|
|
// This node should be a no-op, since its inputs are already ImageFrames.
|
|
auto no_op_node = config.add_node();
|
|
no_op_node->set_calculator("GpuBufferToImageFrameCalculator");
|
|
no_op_node->add_input_stream("image_frames");
|
|
no_op_node->add_output_stream("still_image_frames");
|
|
auto node2 = config.add_node();
|
|
node2->set_calculator("ImageFrameToGpuBufferCalculator");
|
|
node2->add_input_stream("still_image_frames");
|
|
node2->add_output_stream("output_frames");
|
|
|
|
_graph = [[MPPGraph alloc] initWithGraphConfig:config];
|
|
[_graph addFrameOutputStream:"output_frames"
|
|
outputPacketType:MPPPacketTypePixelBuffer];
|
|
[self testGraph:_graph input:*originalPixelBuffer expectedOutput:*originalPixelBuffer];
|
|
}
|
|
|
|
- (void)testGlConvertersWithOptionalSidePackets {
|
|
CFHolder<CVPixelBufferRef> originalPixelBuffer;
|
|
absl::Status status =
|
|
CreateCVPixelBufferFromCGImage([_sourceImage CGImage], &originalPixelBuffer);
|
|
XCTAssert(status.ok());
|
|
|
|
mediapipe::CalculatorGraphConfig config;
|
|
config.add_input_stream("input_frames");
|
|
auto node = config.add_node();
|
|
node->set_calculator("GpuBufferToImageFrameCalculator");
|
|
node->add_input_stream("input_frames");
|
|
node->add_output_stream("image_frames");
|
|
auto node2 = config.add_node();
|
|
node2->set_calculator("ImageFrameToGpuBufferCalculator");
|
|
node2->add_input_stream("image_frames");
|
|
node2->add_output_stream("output_frames");
|
|
|
|
_graph = [[MPPGraph alloc] initWithGraphConfig:config];
|
|
[_graph addFrameOutputStream:"output_frames"
|
|
outputPacketType:MPPPacketTypePixelBuffer];
|
|
[self testGraph:_graph input:*originalPixelBuffer expectedOutput:*originalPixelBuffer];
|
|
}
|
|
|
|
- (void)testDestinationSizes {
|
|
mediapipe::GpuSharedData gpuData;
|
|
mediapipe::GlCalculatorHelper helper;
|
|
helper.InitializeForTest(&gpuData);
|
|
|
|
helper.RunInGlContext([&helper] {
|
|
std::vector<std::pair<int, int>> sizes{
|
|
{200, 300}, {200, 299}, {196, 300}, {194, 300}, {193, 300},
|
|
};
|
|
for (const auto& width_height : sizes) {
|
|
mediapipe::GlTexture texture =
|
|
helper.CreateDestinationTexture(width_height.first, width_height.second);
|
|
XCTAssertNotEqual(texture.name(), 0);
|
|
}
|
|
});
|
|
}
|
|
|
|
- (void)testSimpleConversionFromFormat:(OSType)cvPixelFormat {
|
|
CFHolder<CVPixelBufferRef> originalPixelBuffer;
|
|
absl::Status status =
|
|
CreateCVPixelBufferFromCGImage([_sourceImage CGImage], &originalPixelBuffer);
|
|
XCTAssert(status.ok());
|
|
CVPixelBufferRef convertedPixelBuffer =
|
|
[self convertPixelBuffer:*originalPixelBuffer
|
|
toPixelFormat:cvPixelFormat];
|
|
CVPixelBufferRef bgraPixelBuffer =
|
|
[self convertPixelBuffer:convertedPixelBuffer
|
|
toPixelFormat:kCVPixelFormatType_32BGRA];
|
|
|
|
mediapipe::CalculatorGraphConfig config;
|
|
config.add_input_stream("input_frames");
|
|
auto node = config.add_node();
|
|
node->set_calculator("GlScalerCalculator");
|
|
node->add_input_stream("input_frames");
|
|
node->add_output_stream("output_frames");
|
|
|
|
_graph = [[MPPGraph alloc] initWithGraphConfig:config];
|
|
[_graph addFrameOutputStream:"output_frames"
|
|
outputPacketType:MPPPacketTypePixelBuffer];
|
|
[self testGraph:_graph input:convertedPixelBuffer expectedOutput:bgraPixelBuffer];
|
|
CFRelease(convertedPixelBuffer);
|
|
CFRelease(bgraPixelBuffer);
|
|
}
|
|
|
|
- (void)testOneComponent8 {
|
|
[self testSimpleConversionFromFormat:kCVPixelFormatType_OneComponent8];
|
|
}
|
|
|
|
- (void)testMetalRgbWeight {
|
|
#if TARGET_IPHONE_SIMULATOR
|
|
NSLog(@"Metal tests skipped on Simulator.");
|
|
#else
|
|
CFHolder<CVPixelBufferRef> originalPixelBuffer;
|
|
absl::Status status =
|
|
CreateCVPixelBufferFromCGImage([_sourceImage CGImage], &originalPixelBuffer);
|
|
XCTAssert(status.ok());
|
|
CVPixelBufferRef redPixelBuffer = [self redPixelBuffer:*originalPixelBuffer];
|
|
|
|
mediapipe::CalculatorGraphConfig config;
|
|
config.add_input_stream("input_frames");
|
|
auto node = config.add_node();
|
|
node->set_calculator("MetalRgbWeightCalculator");
|
|
node->add_input_stream("input_frames");
|
|
node->add_output_stream("output_frames");
|
|
node->add_input_side_packet("WEIGHTS:rgb_weights");
|
|
|
|
_graph = [[MPPGraph alloc] initWithGraphConfig:config];
|
|
[_graph addFrameOutputStream:"output_frames"
|
|
outputPacketType:MPPPacketTypePixelBuffer];
|
|
[_graph setSidePacket:(mediapipe::MakePacket<float[3]>(1.0, 0.0, 0.0))
|
|
named:"rgb_weights"];
|
|
|
|
[self testGraph:_graph input:*originalPixelBuffer expectedOutput:redPixelBuffer];
|
|
CFRelease(redPixelBuffer);
|
|
#endif // TARGET_IPHONE_SIMULATOR
|
|
}
|
|
|
|
@end
|