diff --git a/mediapipe/tasks/ios/common/sources/MPPCommon.h b/mediapipe/tasks/ios/common/sources/MPPCommon.h index 09a61e20d..f8047fc35 100644 --- a/mediapipe/tasks/ios/common/sources/MPPCommon.h +++ b/mediapipe/tasks/ios/common/sources/MPPCommon.h @@ -25,153 +25,44 @@ typedef NS_ENUM(NSUInteger, MPPTasksErrorCode) { // Generic error codes. - // Unspecified error. - MPPTasksErrorCodeError = 1, - // Invalid argument specified. - MPPTasksErrorCodeInvalidArgumentError = 2, - // Invalid FlatBuffer file or buffer specified. - MPPTasksErrorCodeInvalidFlatBufferError = 3, - // Model contains a builtin op that isn't supported by the OpResolver or - // delegates. - MPPTasksErrorCodeUnsupportedBuiltinOp = 4, - // Model contains a custom op that isn't supported by the OpResolver or - // delegates. - MPPTasksErrorCodeUnsupportedCustomOp = 5, + /** Indicates the operation was cancelled, typically by the caller. */ + MPPTasksErrorCodeCancelledError = 1, + /** Indicates an unknown error occurred. */ + MPPTasksErrorCodeUnknownError = 2, + /** Indicates the caller specified an invalid argument, such as a malformed filename. */ + MPPTasksErrorCodeInvalidArgumentError = 3, + /** Indicates a deadline expired before the operation could complete. */ + MPPTasksErrorCodeDeadlineExceededError = 4, + /** Indicates some requested entity (such as a file or directory) was not found. */ + MPPTasksErrorCodeNotFoundError = 5, + /** Indicates that the entity a caller attempted to create (such as a file or directory) is already present. */ + MPPTasksErrorCodeAlreadyExistsError = 6, + /** Indicates that the caller does not have permission to execute the specified operation. */ + MPPTasksErrorCodePermissionDeniedError = 7, - // File I/O error codes. + MPPTasksErrorCodeResourceExhaustedError = 8, - // No such file. - MPPTasksErrorCodeFileNotFoundError = 100, - // Permission issue. - MPPTasksErrorCodeFilePermissionDeniedError, - // I/O error when reading file. - MPPTasksErrorCodeFileReadError, - // I/O error when mmap-ing file. - MPPTasksErrorCodeFileMmapError, - // ZIP I/O error when unpacking the zip file. - MPPTasksErrorCodeFileZipError, + MPPTasksErrorCodeFailedPreconditionError = 9, - // TensorFlow Lite metadata error codes. + MPPTasksErrorCodeAbortedError = 10, - // Unexpected schema version (aka file_identifier) in the Metadata FlatBuffer. - MPPTasksErrorCodeMetadataInvalidSchemaVersionError = 200, - // No such associated file within metadata, or file has not been packed. - MPPTasksErrorCodeMetadataAssociatedFileNotFoundError, - // ZIP I/O error when unpacking an associated file. - MPPTasksErrorCodeMetadataAssociatedFileZipError, - // Inconsistency error between the metadata and actual TF Lite model. - // E.g.: number of labels and output tensor values differ. - MPPTasksErrorCodeMetadataInconsistencyError, - // Invalid process units specified. - // E.g.: multiple ProcessUnits with the same type for a given tensor. - MPPTasksErrorCodeMetadataInvalidProcessUnitsError, - // Inconsistency error with the number of labels. - // E.g.: label files for different locales have a different number of labels. - MPPTasksErrorCodeMetadataNumLabelsMismatchError, - // Score calibration parameters parsing error. - // E.g.: too many parameters provided in the corresponding associated file. - MPPTasksErrorCodeMetadataMalformedScoreCalibrationError, - // Unexpected number of subgraphs for the current task. - // E.g.: image classification expects a single subgraph. - MPPTasksErrorCodeMetadataInvalidNumSubgraphsError, - // A given tensor requires NormalizationOptions but none were found. - // E.g.: float input tensor requires normalization to preprocess input images. - MPPTasksErrorCodeMetadataMissingNormalizationOptionsError, - // Invalid ContentProperties specified. - // E.g. expected ImageProperties, got BoundingBoxProperties. - MPPTasksErrorCodeMetadataInvalidContentPropertiesError, - // Metadata is mandatory but was not found. - // E.g. current task requires TFLite Model Metadata but none was found. - MPPTasksErrorCodeMetadataNotFoundError, - // Associated TENSOR_AXIS_LABELS or TENSOR_VALUE_LABELS file is mandatory but - // none was found or it was empty. - // E.g. current task requires labels but none were found. - MPPTasksErrorCodeMetadataMissingLabelsError, - // The ProcessingUnit for tokenizer is not correctly configured. - // E.g BertTokenizer doesn't have a valid vocab file associated. - MPPTasksErrorCodeMetadataInvalidTokenizerError, + MPPTasksErrorCodeOutOfRangeError = 11, - // Input tensor(s) error codes. + MPPTasksErrorCodeUnimplementedError = 12, - // Unexpected number of input tensors for the current task. - // E.g. current task expects a single input tensor. - MPPTasksErrorCodeInvalidNumInputTensorsError = 300, - // Unexpected input tensor dimensions for the current task. - // E.g.: only 4D input tensors supported. - MPPTasksErrorCodeInvalidInputTensorDimensionsError, - // Unexpected input tensor type for the current task. - // E.g.: current task expects a uint8 pixel image as input. - MPPTasksErrorCodeInvalidInputTensorTypeError, - // Unexpected input tensor bytes size. - // E.g.: size in bytes does not correspond to the expected number of pixels. - MPPTasksErrorCodeInvalidInputTensorSizeError, - // No correct input tensor found for the model. - // E.g.: input tensor name is not part of the text model's input tensors. - MPPTasksErrorCodeInputTensorNotFoundError, + MPPTasksErrorCodeInternalError = 13, - // Output tensor(s) error codes. + MPPTasksErrorCodeUnavailableError = 14, - // Unexpected output tensor dimensions for the current task. - // E.g.: only a batch size of 1 is supported. - MPPTasksErrorCodeInvalidOutputTensorDimensionsError = 400, - // Unexpected input tensor type for the current task. - // E.g.: multi-head model with different output tensor types. - MPPTasksErrorCodeInvalidOutputTensorTypeError, - // No correct output tensor found for the model. - // E.g.: output tensor name is not part of the text model's output tensors. - MPPTasksErrorCodeOutputTensorNotFoundError, - // Unexpected number of output tensors for the current task. - // E.g.: current task expects a single output tensor. - MPPTasksErrorCodeInvalidNumOutputTensorsError, + MPPTasksErrorCodeDataLossError = 15, - // Image processing error codes. - - // Unspecified image processing failures. - MPPTasksErrorCodeImageProcessingError = 500, - // Unexpected input or output buffer metadata. - // E.g.: rotate RGBA buffer to Grayscale buffer by 90 degrees. - MPPTasksErrorCodeImageProcessingInvalidArgumentError, - // Image processing operation failures. - // E.g. libyuv rotation failed for an unknown reason. - MPPTasksErrorCodeImageProcessingBackendError, - - // Task runner error codes. - MPPTasksErrorCodeRunnerError = 600, - // Task runner is not initialized. - MPPTasksErrorCodeRunnerInitializationError, - // Task runner is not started successfully. - MPPTasksErrorCodeRunnerFailsToStartError, - // Task runner is not started. - MPPTasksErrorCodeRunnerNotStartedError, - // Task runner API is called in the wrong processing mode. - MPPTasksErrorCodeRunnerApiCalledInWrongModeError, - // Task runner receives/produces invalid MediaPipe packet timestamp. - MPPTasksErrorCodeRunnerInvalidTimestampError, - // Task runner receives unexpected MediaPipe graph input packet. - // E.g. The packet type doesn't match the graph input stream's data type. - MPPTasksErrorCodeRunnerUnexpectedInputError, - // Task runner produces unexpected MediaPipe graph output packet. - // E.g. The number of output packets is not equal to the number of graph - // output streams. - MPPTasksErrorCodeRunnerUnexpectedOutputError, - // Task runner is not closed successfully. - MPPTasksErrorCodeRunnerFailsToCloseError, - // Task runner's model resources cache service is unavailable or the - // targeting model resources bundle is not found. - MPPTasksErrorCodeRunnerModelResourcesCacheServiceError, - - // Task graph error codes. - MPPTasksErrorCodeGraphError = 700, - // Task graph is not implemented. - MPPTasksErrorCodeTaskGraphNotImplementedError, - // Task graph config is invalid. - MPPTasksErrorCodeInvalidTaskGraphConfigError, + MPPTasksErrorCodeUnauthenticatedError = 16, // The first error code in MPPTasksErrorCode (for internal use only). - MPPTasksErrorCodeFirst = MPPTasksErrorCodeError, + MPPTasksErrorCodeFirst = MPPTasksErrorCodeCancelledError, // The last error code in MPPTasksErrorCode (for internal use only). - MPPTasksErrorCodeLast = MPPTasksErrorCodeInvalidTaskGraphConfigError, + MPPTasksErrorCodeLast = MPPTasksErrorCodeUnauthenticatedError, } NS_SWIFT_NAME(TasksErrorCode); diff --git a/mediapipe/tasks/ios/common/utils/sources/MPPCommonUtils.mm b/mediapipe/tasks/ios/common/utils/sources/MPPCommonUtils.mm index 1a37f8465..9932dd13c 100644 --- a/mediapipe/tasks/ios/common/utils/sources/MPPCommonUtils.mm +++ b/mediapipe/tasks/ios/common/utils/sources/MPPCommonUtils.mm @@ -25,6 +25,10 @@ /** Error domain of MediaPipe task library errors. */ NSString *const MPPTasksErrorDomain = @"com.google.mediapipe.tasks"; +namespace { + using absl::StatusCode; +} + @implementation MPPCommonUtils + (void)createCustomError:(NSError **)error @@ -67,52 +71,6 @@ NSString *const MPPTasksErrorDomain = @"com.google.mediapipe.tasks"; if (status.ok()) { return YES; } - // Payload of absl::Status created by the MediaPipe task library stores an appropriate value of - // the enum MediaPipeTasksStatus. The integer value corresponding to the MediaPipeTasksStatus enum - // stored in the payload is extracted here to later map to the appropriate error code to be - // returned. In cases where the enum is not stored in (payload is NULL or the payload string - // cannot be converted to an integer), we set the error code value to be 1 - // (MPPTasksErrorCodeError of MPPTasksErrorCode used in the iOS library to signify - // any errors not falling into other categories.) Since payload is of type absl::Cord that can be - // type cast into an absl::optional, we use the std::stoi function to convert it into - // an integer code if possible. - NSUInteger genericErrorCode = MPPTasksErrorCodeError; - NSUInteger errorCode; - try { - // Try converting payload to integer if payload is not empty. Otherwise convert a string - // signifying generic error code MPPTasksErrorCodeError to integer. - errorCode = - (NSUInteger)std::stoi(static_cast>( - status.GetPayload(mediapipe::tasks::kMediaPipeTasksPayload)) - .value_or(std::to_string(genericErrorCode))); - } catch (std::invalid_argument &e) { - // If non empty payload string cannot be converted to an integer. Set error code to 1(kError). - errorCode = MPPTasksErrorCodeError; - } - - // If errorCode is outside the range of enum values possible or is - // MPPTasksErrorCodeError, we try to map the absl::Status::code() to assign - // appropriate MPPTasksErrorCode in default cases. Note: - // The mapping to absl::Status::code() is done to generate a more specific error code than - // MPPTasksErrorCodeError in cases when the payload can't be mapped to - // MPPTasksErrorCode. This can happen when absl::Status returned by TFLite library are in turn - // returned without modification by MediaPipe cc library methods. - if (errorCode > MPPTasksErrorCodeLast || errorCode <= MPPTasksErrorCodeFirst) { - switch (status.code()) { - case absl::StatusCode::kInternal: - errorCode = MPPTasksErrorCodeError; - break; - case absl::StatusCode::kInvalidArgument: - errorCode = MPPTasksErrorCodeInvalidArgumentError; - break; - case absl::StatusCode::kNotFound: - errorCode = MPPTasksErrorCodeError; - break; - default: - errorCode = MPPTasksErrorCodeError; - break; - } - } // Creates the NSEror with the appropriate error // MPPTasksErrorCode and message. MPPTasksErrorCode has a one to one @@ -129,6 +87,81 @@ NSString *const MPPTasksErrorDomain = @"com.google.mediapipe.tasks"; NSString *description = [NSString stringWithCString:status.ToString(absl::StatusToStringMode::kWithNoExtraData).c_str() encoding:NSUTF8StringEncoding]; + + // Payload of absl::Status created by the MediaPipe task library stores an appropriate value of + // the enum MediaPipeTasksStatus. The integer value corresponding to the MediaPipeTasksStatus enum + // stored in the payload is extracted here to later map to the appropriate error code to be + // returned. In cases where the enum is not stored in (payload is NULL or the payload string + // cannot be converted to an integer), we set the error code value to be 1 + // (MPPTasksErrorCodeError of MPPTasksErrorCode used in the iOS library to signify + // any errors not falling into other categories.) Since payload is of type absl::Cord that can be + // type cast into an absl::optional, we use the std::stoi function to convert it into + // an integer code if possible. + MPPTasksErrorCode genericErrorCode = MPPTasksErrorCodeUnknownError; + + MPPTasksErrorCode errorCode = genericErrorCode; + + // If errorCode is outside the range of enum values possible or is + // MPPTasksErrorCodeError, we try to map the absl::Status::code() to assign + // appropriate MPPTasksErrorCode in default cases. Note: + // The mapping to absl::Status::code() is done to generate a more specific error code than + // MPPTasksErrorCodeError in cases when the payload can't be mapped to + // MPPTasksErrorCode. This can happen when absl::Status returned by TFLite library are in turn + // returned without modification by MediaPipe cc library methods. + switch (status.code()) { + case StatusCode::kCancelled: + errorCode = MPPTasksErrorCodeCancelledError; + break; + case StatusCode::kUnknown: + errorCode = MPPTasksErrorCodeUnknownError; + break; + case StatusCode::kInvalidArgument: + errorCode = MPPTasksErrorCodeInvalidArgumentError; + break; + case StatusCode::kDeadlineExceeded: + errorCode = MPPTasksErrorCodeDeadlineExceededError; + break; + case StatusCode::kNotFound: + errorCode = MPPTasksErrorCodeNotFoundError; + break; + case StatusCode::kAlreadyExists: + errorCode = MPPTasksErrorCodeAlreadyExistsError; + break; + case StatusCode::kPermissionDenied: + errorCode = MPPTasksErrorCodePermissionDeniedError; + break; + case StatusCode::kResourceExhausted: + errorCode = MPPTasksErrorCodeResourceExhaustedError; + break; + case StatusCode::kFailedPrecondition: + errorCode = MPPTasksErrorCodeFailedPreconditionError; + break; + case StatusCode::kAborted: + errorCode = MPPTasksErrorCodeAbortedError; + break; + case StatusCode::kOutOfRange: + errorCode = MPPTasksErrorCodeOutOfRangeError; + break; + case StatusCode::kUnimplemented: + errorCode = MPPTasksErrorCodeUnimplementedError; + break; + case StatusCode::kInternal: + errorCode = MPPTasksErrorCodeInternalError; + break; + case StatusCode::kUnavailable: + errorCode = MPPTasksErrorCodeUnavailableError; + break; + case StatusCode::kDataLoss: + errorCode = MPPTasksErrorCodeDataLossError; + break; + case StatusCode::kUnauthenticated: + errorCode = MPPTasksErrorCodeUnauthenticatedError; + break; + default: + errorCode = genericErrorCode; + break; + } + [MPPCommonUtils createCustomError:error withCode:errorCode description:description]; return NO; }