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