Merge f9f864883d
into 45b0271ded
This commit is contained in:
commit
32a7e62c6c
|
@ -87,6 +87,7 @@ objc_library(
|
|||
"//mediapipe/framework:calculator_cc_proto",
|
||||
"//mediapipe/tasks/cc/core:mediapipe_builtin_op_resolver",
|
||||
"//mediapipe/tasks/cc/core:task_runner",
|
||||
"//mediapipe/tasks/ios/common:MPPCommon",
|
||||
"//mediapipe/tasks/ios/common/utils:MPPCommonUtils",
|
||||
],
|
||||
)
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
// limitations under the License.
|
||||
|
||||
#import "mediapipe/tasks/ios/core/sources/MPPTaskRunner.h"
|
||||
#import "mediapipe/tasks/ios/common/sources/MPPCommon.h"
|
||||
#import "mediapipe/tasks/ios/common/utils/sources/MPPCommonUtils.h"
|
||||
|
||||
#include "mediapipe/tasks/cc/core/mediapipe_builtin_op_resolver.h"
|
||||
|
@ -28,6 +29,7 @@ using TaskRunnerCpp = ::mediapipe::tasks::core::TaskRunner;
|
|||
@interface MPPTaskRunner () {
|
||||
// Cpp Task Runner
|
||||
std::unique_ptr<TaskRunnerCpp> _cppTaskRunner;
|
||||
BOOL _initializedWithPacketsCallback;
|
||||
}
|
||||
@end
|
||||
|
||||
|
@ -46,6 +48,7 @@ using TaskRunnerCpp = ::mediapipe::tasks::core::TaskRunner;
|
|||
return nil;
|
||||
}
|
||||
_cppTaskRunner = std::move(taskRunnerResult.value());
|
||||
_initializedWithPacketsCallback = packetsCallback ? YES : NO;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
@ -59,7 +62,20 @@ using TaskRunnerCpp = ::mediapipe::tasks::core::TaskRunner;
|
|||
}
|
||||
|
||||
- (BOOL)sendPacketMap:(const PacketMap &)packetMap error:(NSError **)error {
|
||||
if (!_initializedWithPacketsCallback) {
|
||||
[MPPCommonUtils
|
||||
createCustomError:error
|
||||
withCode:MPPTasksErrorCodeFailedPreconditionError
|
||||
description:[NSString
|
||||
stringWithFormat:@"This method can only be called if the task is "
|
||||
@"running in a stream mode and an object of a class "
|
||||
@"is provided as the delegate in the task options "
|
||||
@"to receive the results asynchronously."]];
|
||||
return NO;
|
||||
}
|
||||
|
||||
absl::Status sendStatus = _cppTaskRunner->Send(packetMap);
|
||||
|
||||
return [MPPCommonUtils checkCppError:sendStatus toError:error];
|
||||
}
|
||||
|
||||
|
|
|
@ -439,7 +439,7 @@ static NSString *const kLiveStreamTestsDictExpectationKey = @"expectation";
|
|||
|
||||
#pragma mark Running Mode Tests
|
||||
|
||||
- (void)testCreateImageClassifierFailsWithDelegateInNonLiveStreamMode {
|
||||
- (void)testCreateImageClassifierSucceedsWithDelegateInNonLiveStreamMode {
|
||||
MPPRunningMode runningModesToTest[] = {MPPRunningModeImage, MPPRunningModeVideo};
|
||||
for (int i = 0; i < sizeof(runningModesToTest) / sizeof(runningModesToTest[0]); i++) {
|
||||
MPPImageClassifierOptions *options = [self imageClassifierOptionsWithModelName:kFloatModelName];
|
||||
|
@ -447,36 +447,20 @@ static NSString *const kLiveStreamTestsDictExpectationKey = @"expectation";
|
|||
options.runningMode = runningModesToTest[i];
|
||||
options.imageClassifierLiveStreamDelegate = self;
|
||||
|
||||
[self
|
||||
assertCreateImageClassifierWithOptions:options
|
||||
failsWithExpectedError:
|
||||
[NSError
|
||||
errorWithDomain:kExpectedErrorDomain
|
||||
code:MPPTasksErrorCodeInvalidArgumentError
|
||||
userInfo:@{
|
||||
NSLocalizedDescriptionKey :
|
||||
@"The vision task is in image or video mode. The "
|
||||
@"delegate must not be set in the task's options."
|
||||
}]];
|
||||
MPPImageClassifier *imageClassifier = [[MPPImageClassifier alloc] initWithOptions:options
|
||||
error:nil];
|
||||
XCTAssertNotNil(imageClassifier);
|
||||
}
|
||||
}
|
||||
|
||||
- (void)testCreateImageClassifierFailsWithMissingDelegateInLiveStreamMode {
|
||||
- (void)testCreateImageClassifieSucceedsWithMissingDelegateInLiveStreamMode {
|
||||
MPPImageClassifierOptions *options = [self imageClassifierOptionsWithModelName:kFloatModelName];
|
||||
|
||||
options.runningMode = MPPRunningModeLiveStream;
|
||||
|
||||
[self assertCreateImageClassifierWithOptions:options
|
||||
failsWithExpectedError:
|
||||
[NSError errorWithDomain:kExpectedErrorDomain
|
||||
code:MPPTasksErrorCodeInvalidArgumentError
|
||||
userInfo:@{
|
||||
NSLocalizedDescriptionKey :
|
||||
@"The vision task is in live stream mode. An "
|
||||
@"object must be set as the delegate of the task "
|
||||
@"in its options to ensure asynchronous delivery "
|
||||
@"of results."
|
||||
}]];
|
||||
MPPImageClassifier *imageClassifier = [[MPPImageClassifier alloc] initWithOptions:options
|
||||
error:nil];
|
||||
XCTAssertNotNil(imageClassifier);
|
||||
}
|
||||
|
||||
- (void)testClassifyFailsWithCallingWrongApiInImageMode {
|
||||
|
@ -614,6 +598,30 @@ static NSString *const kLiveStreamTestsDictExpectationKey = @"expectation";
|
|||
}
|
||||
}
|
||||
|
||||
- (void)testClassifyFailsWithMissingDelegateInLiveStreamMode {
|
||||
MPPImageClassifierOptions *options = [self imageClassifierOptionsWithModelName:kFloatModelName];
|
||||
options.runningMode = MPPRunningModeLiveStream;
|
||||
|
||||
MPPImageClassifier *imageClassifier = [self imageClassifierWithOptionsSucceeds:options];
|
||||
|
||||
NSError *expectedError =
|
||||
[NSError errorWithDomain:kExpectedErrorDomain
|
||||
code:MPPTasksErrorCodeFailedPreconditionError
|
||||
userInfo:@{
|
||||
NSLocalizedDescriptionKey :
|
||||
@"This method can only be called if the task is running in a stream "
|
||||
@"mode and an object of a class is provided as the delegate in the "
|
||||
@"task options to receive the results asynchronously."
|
||||
}];
|
||||
|
||||
MPPImage *image = [self imageWithFileInfo:kBurgerImage];
|
||||
|
||||
NSError *error = nil;
|
||||
XCTAssertFalse([imageClassifier classifyAsyncImage:image timestampInMilliseconds:1 error:&error]);
|
||||
|
||||
AssertEqualErrors(error, expectedError);
|
||||
}
|
||||
|
||||
- (void)testClassifyWithOutOfOrderTimestampsAndLiveStreamModeFails {
|
||||
MPPImageClassifierOptions *options = [self imageClassifierOptionsWithModelName:kFloatModelName];
|
||||
|
||||
|
|
|
@ -51,39 +51,14 @@ static NSString *const kTaskPrefix = @"com.mediapipe.tasks.vision";
|
|||
runningMode:(MPPRunningMode)runningMode
|
||||
packetsCallback:(PacketsCallback)packetsCallback
|
||||
error:(NSError **)error {
|
||||
switch (runningMode) {
|
||||
case MPPRunningModeImage:
|
||||
case MPPRunningModeVideo: {
|
||||
if (packetsCallback) {
|
||||
[MPPCommonUtils createCustomError:error
|
||||
withCode:MPPTasksErrorCodeInvalidArgumentError
|
||||
description:@"The vision task is in image or video mode. The "
|
||||
@"delegate must not be set in the task's options."];
|
||||
return nil;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MPPRunningModeLiveStream: {
|
||||
if (!packetsCallback) {
|
||||
[MPPCommonUtils
|
||||
createCustomError:error
|
||||
withCode:MPPTasksErrorCodeInvalidArgumentError
|
||||
description:
|
||||
@"The vision task is in live stream mode. An object must be set as the "
|
||||
@"delegate of the task in its options to ensure asynchronous delivery of "
|
||||
@"results."];
|
||||
return nil;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
|
||||
if (_runningMode > MPPRunningModeLiveStream) {
|
||||
[MPPCommonUtils createCustomError:error
|
||||
withCode:MPPTasksErrorCodeInvalidArgumentError
|
||||
description:@"Unrecognized running mode"];
|
||||
return nil;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
_runningMode = runningMode;
|
||||
self = [super initWithCalculatorGraphConfig:graphConfig
|
||||
packetsCallback:packetsCallback
|
||||
|
|
|
@ -64,12 +64,7 @@ static const int kMicroSecondsPerMilliSecond = 1000;
|
|||
@implementation MPPImageClassifier
|
||||
|
||||
- (void)processLiveStreamResult:(absl::StatusOr<PacketMap>)liveStreamResult {
|
||||
if (![self.imageClassifierLiveStreamDelegate
|
||||
respondsToSelector:@selector
|
||||
(imageClassifier:didFinishClassificationWithResult:timestampInMilliseconds:error:)]) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
NSError *callbackError = nil;
|
||||
if (![MPPCommonUtils checkCppError:liveStreamResult.status() toError:&callbackError]) {
|
||||
dispatch_async(_callbackQueue, ^{
|
||||
|
|
|
@ -33,7 +33,7 @@ NS_ASSUME_NONNULL_BEGIN
|
|||
NS_SWIFT_NAME(ImageClassifierLiveStreamDelegate)
|
||||
@protocol MPPImageClassifierLiveStreamDelegate <NSObject>
|
||||
|
||||
@optional
|
||||
@required
|
||||
/**
|
||||
* This method notifies a delegate that the results of asynchronous classification of
|
||||
* an image submitted to the `ImageClassifier` is available.
|
||||
|
|
Loading…
Reference in New Issue
Block a user