From 077b52250d704286f9db1a5b57ba980262434cf9 Mon Sep 17 00:00:00 2001 From: Sebastian Schmidt Date: Mon, 6 Nov 2023 13:39:48 -0800 Subject: [PATCH 1/3] Pass Model Asset Buffer as byte array + length PiperOrigin-RevId: 579944283 --- mediapipe/tasks/c/core/base_options.h | 5 ++++- mediapipe/tasks/c/core/base_options_converter.cc | 4 +++- mediapipe/tasks/c/core/base_options_converter_test.cc | 4 ++++ .../tasks/c/text/language_detector/language_detector_test.cc | 2 ++ .../tasks/c/text/text_classifier/text_classifier_test.cc | 2 ++ mediapipe/tasks/c/text/text_embedder/text_embedder_test.cc | 2 ++ mediapipe/tasks/c/vision/image_classifier/BUILD | 4 ---- .../tasks/c/vision/image_classifier/image_classifier_test.cc | 5 +++++ 8 files changed, 22 insertions(+), 6 deletions(-) diff --git a/mediapipe/tasks/c/core/base_options.h b/mediapipe/tasks/c/core/base_options.h index 78d89ce8c..bbfd3ef7e 100644 --- a/mediapipe/tasks/c/core/base_options.h +++ b/mediapipe/tasks/c/core/base_options.h @@ -22,9 +22,12 @@ extern "C" { // Base options for MediaPipe C Tasks. struct BaseOptions { - // The model asset file contents as a string. + // The model asset file contents as bytes. const char* model_asset_buffer; + // The size of the model assets buffer (or `0` if not set). + const unsigned int model_asset_buffer_count; + // The path to the model asset to open and mmap in memory. const char* model_asset_path; }; diff --git a/mediapipe/tasks/c/core/base_options_converter.cc b/mediapipe/tasks/c/core/base_options_converter.cc index 3f126168b..07a9e81d0 100644 --- a/mediapipe/tasks/c/core/base_options_converter.cc +++ b/mediapipe/tasks/c/core/base_options_converter.cc @@ -27,7 +27,9 @@ void CppConvertToBaseOptions(const BaseOptions& in, mediapipe::tasks::core::BaseOptions* out) { out->model_asset_buffer = in.model_asset_buffer - ? std::make_unique(in.model_asset_buffer) + ? std::make_unique( + in.model_asset_buffer, + in.model_asset_buffer + in.model_asset_buffer_count) : nullptr; out->model_asset_path = in.model_asset_path ? std::string(in.model_asset_path) : ""; diff --git a/mediapipe/tasks/c/core/base_options_converter_test.cc b/mediapipe/tasks/c/core/base_options_converter_test.cc index 27c7fb3ec..37ab90f94 100644 --- a/mediapipe/tasks/c/core/base_options_converter_test.cc +++ b/mediapipe/tasks/c/core/base_options_converter_test.cc @@ -15,6 +15,7 @@ limitations under the License. #include "mediapipe/tasks/c/core/base_options_converter.h" +#include #include #include "mediapipe/framework/port/gtest.h" @@ -28,6 +29,8 @@ constexpr char kModelAssetPath[] = "abc.tflite"; TEST(BaseOptionsConverterTest, ConvertsBaseOptionsAssetBuffer) { BaseOptions c_base_options = {/* model_asset_buffer= */ kAssetBuffer, + /* model_asset_buffer_count= */ + static_cast(strlen(kAssetBuffer)), /* model_asset_path= */ nullptr}; mediapipe::tasks::core::BaseOptions cpp_base_options = {}; @@ -39,6 +42,7 @@ TEST(BaseOptionsConverterTest, ConvertsBaseOptionsAssetBuffer) { TEST(BaseOptionsConverterTest, ConvertsBaseOptionsAssetPath) { BaseOptions c_base_options = {/* model_asset_buffer= */ nullptr, + /* model_asset_buffer_count= */ 0, /* model_asset_path= */ kModelAssetPath}; mediapipe::tasks::core::BaseOptions cpp_base_options = {}; diff --git a/mediapipe/tasks/c/text/language_detector/language_detector_test.cc b/mediapipe/tasks/c/text/language_detector/language_detector_test.cc index b8653e616..1c55b2ab5 100644 --- a/mediapipe/tasks/c/text/language_detector/language_detector_test.cc +++ b/mediapipe/tasks/c/text/language_detector/language_detector_test.cc @@ -44,6 +44,7 @@ TEST(LanguageDetectorTest, SmokeTest) { std::string model_path = GetFullPath(kTestLanguageDetectorModelPath); LanguageDetectorOptions options = { /* base_options= */ {/* model_asset_buffer= */ nullptr, + /* model_asset_buffer_count= */ 0, /* model_asset_path= */ model_path.c_str()}, /* classifier_options= */ {/* display_names_locale= */ nullptr, @@ -71,6 +72,7 @@ TEST(LanguageDetectorTest, ErrorHandling) { // It is an error to set neither the asset buffer nor the path. LanguageDetectorOptions options = { /* base_options= */ {/* model_asset_buffer= */ nullptr, + /* model_asset_buffer_count= */ 0, /* model_asset_path= */ nullptr}, /* classifier_options= */ {}, }; diff --git a/mediapipe/tasks/c/text/text_classifier/text_classifier_test.cc b/mediapipe/tasks/c/text/text_classifier/text_classifier_test.cc index 51232d63a..d261be1c8 100644 --- a/mediapipe/tasks/c/text/text_classifier/text_classifier_test.cc +++ b/mediapipe/tasks/c/text/text_classifier/text_classifier_test.cc @@ -43,6 +43,7 @@ TEST(TextClassifierTest, SmokeTest) { std::string model_path = GetFullPath(kTestBertModelPath); TextClassifierOptions options = { /* base_options= */ {/* model_asset_buffer= */ nullptr, + /* model_asset_buffer_count= */ 0, /* model_asset_path= */ model_path.c_str()}, /* classifier_options= */ {/* display_names_locale= */ nullptr, @@ -74,6 +75,7 @@ TEST(TextClassifierTest, ErrorHandling) { // It is an error to set neither the asset buffer nor the path. TextClassifierOptions options = { /* base_options= */ {/* model_asset_buffer= */ nullptr, + /* model_asset_buffer_count= */ 0, /* model_asset_path= */ nullptr}, /* classifier_options= */ {}, }; diff --git a/mediapipe/tasks/c/text/text_embedder/text_embedder_test.cc b/mediapipe/tasks/c/text/text_embedder/text_embedder_test.cc index c823e01b4..40c449b8a 100644 --- a/mediapipe/tasks/c/text/text_embedder/text_embedder_test.cc +++ b/mediapipe/tasks/c/text/text_embedder/text_embedder_test.cc @@ -42,6 +42,7 @@ TEST(TextEmbedderTest, SmokeTest) { std::string model_path = GetFullPath(kTestBertModelPath); TextEmbedderOptions options = { /* base_options= */ {/* model_asset_buffer= */ nullptr, + /* model_asset_buffer_count= */ 0, /* model_asset_path= */ model_path.c_str()}, /* embedder_options= */ {/* l2_normalize= */ false, /* quantize= */ true}, @@ -63,6 +64,7 @@ TEST(TextEmbedderTest, ErrorHandling) { // It is an error to set neither the asset buffer nor the path. TextEmbedderOptions options = { /* base_options= */ {/* model_asset_buffer= */ nullptr, + /* model_asset_buffer_count= */ 0, /* model_asset_path= */ nullptr}, /* embedder_options= */ {}, }; diff --git a/mediapipe/tasks/c/vision/image_classifier/BUILD b/mediapipe/tasks/c/vision/image_classifier/BUILD index e8ac090e9..a2c7ca290 100644 --- a/mediapipe/tasks/c/vision/image_classifier/BUILD +++ b/mediapipe/tasks/c/vision/image_classifier/BUILD @@ -55,11 +55,7 @@ cc_test( ":image_classifier_lib", "//mediapipe/framework/deps:file_path", "//mediapipe/framework/formats:image", - "//mediapipe/framework/formats:image_frame", - "//mediapipe/framework/formats:image_frame_opencv", "//mediapipe/framework/port:gtest", - "//mediapipe/framework/port:opencv_core", - "//mediapipe/framework/port:opencv_imgproc", "//mediapipe/tasks/c/components/containers:category", "//mediapipe/tasks/cc/vision/utils:image_utils", "@com_google_absl//absl/flags:flag", diff --git a/mediapipe/tasks/c/vision/image_classifier/image_classifier_test.cc b/mediapipe/tasks/c/vision/image_classifier/image_classifier_test.cc index 790f5ce36..a66e42832 100644 --- a/mediapipe/tasks/c/vision/image_classifier/image_classifier_test.cc +++ b/mediapipe/tasks/c/vision/image_classifier/image_classifier_test.cc @@ -50,6 +50,7 @@ TEST(ImageClassifierTest, ImageModeTest) { const std::string model_path = GetFullPath(kModelName); ImageClassifierOptions options = { /* base_options= */ {/* model_asset_buffer= */ nullptr, + /* model_asset_buffer_count= */ 0, /* model_asset_path= */ model_path.c_str()}, /* running_mode= */ RunningMode::IMAGE, /* classifier_options= */ @@ -92,6 +93,7 @@ TEST(ImageClassifierTest, VideoModeTest) { const std::string model_path = GetFullPath(kModelName); ImageClassifierOptions options = { /* base_options= */ {/* model_asset_buffer= */ nullptr, + /* model_asset_buffer_count= */ 0, /* model_asset_path= */ model_path.c_str()}, /* running_mode= */ RunningMode::VIDEO, /* classifier_options= */ @@ -164,6 +166,7 @@ TEST(ImageClassifierTest, LiveStreamModeTest) { ImageClassifierOptions options = { /* base_options= */ {/* model_asset_buffer= */ nullptr, + /* model_asset_buffer_count= */ 0, /* model_asset_path= */ model_path.c_str()}, /* running_mode= */ RunningMode::LIVE_STREAM, /* classifier_options= */ @@ -203,6 +206,7 @@ TEST(ImageClassifierTest, InvalidArgumentHandling) { // It is an error to set neither the asset buffer nor the path. ImageClassifierOptions options = { /* base_options= */ {/* model_asset_buffer= */ nullptr, + /* model_asset_buffer_count= */ 0, /* model_asset_path= */ nullptr}, /* classifier_options= */ {}, }; @@ -220,6 +224,7 @@ TEST(ImageClassifierTest, FailedClassificationHandling) { const std::string model_path = GetFullPath(kModelName); ImageClassifierOptions options = { /* base_options= */ {/* model_asset_buffer= */ nullptr, + /* model_asset_buffer_count= */ 0, /* model_asset_path= */ model_path.c_str()}, /* running_mode= */ RunningMode::IMAGE, /* classifier_options= */ From a8d88bf7cf398a382ddfa049b11fd79655abe37b Mon Sep 17 00:00:00 2001 From: MediaPipe Team Date: Mon, 6 Nov 2023 14:39:10 -0800 Subject: [PATCH 2/3] Creates GpuBuffers around pre-allocated AHardware_Buffer objects. PiperOrigin-RevId: 579961642 --- mediapipe/gpu/BUILD | 5 ----- mediapipe/gpu/gpu_buffer_format.cc | 2 +- 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/mediapipe/gpu/BUILD b/mediapipe/gpu/BUILD index f39b8d3f7..b75c824b3 100644 --- a/mediapipe/gpu/BUILD +++ b/mediapipe/gpu/BUILD @@ -516,7 +516,6 @@ cc_library( ":gpu_buffer_storage", ":image_frame_view", "//mediapipe/framework/formats:image_frame", - "//mediapipe/framework/port:ret_check", "@com_google_absl//absl/strings:str_format", ], ) @@ -1224,13 +1223,9 @@ mediapipe_cc_test( ], requires_full_emulation = True, deps = [ - ":gl_texture_buffer", - ":gl_texture_util", ":gpu_buffer_format", ":gpu_buffer_storage_ahwb", - ":gpu_test_base", "//mediapipe/framework/port:gtest_main", - "//mediapipe/framework/tool:test_util", ], ) diff --git a/mediapipe/gpu/gpu_buffer_format.cc b/mediapipe/gpu/gpu_buffer_format.cc index 510a9cd48..b099f4a25 100644 --- a/mediapipe/gpu/gpu_buffer_format.cc +++ b/mediapipe/gpu/gpu_buffer_format.cc @@ -238,7 +238,7 @@ ImageFormat::Format ImageFormatForGpuBufferFormat(GpuBufferFormat format) { case GpuBufferFormat::kRGBAFloat128: return ImageFormat::VEC32F4; case GpuBufferFormat::kRGBA32: - return ImageFormat::SRGBA; + // TODO: this likely maps to ImageFormat::SRGBA case GpuBufferFormat::kGrayHalf16: case GpuBufferFormat::kOneComponent8Alpha: case GpuBufferFormat::kOneComponent8Red: From 2abaabce0e851521bf05540318062f4fee79b50b Mon Sep 17 00:00:00 2001 From: Sebastian Schmidt Date: Mon, 6 Nov 2023 14:53:42 -0800 Subject: [PATCH 3/3] Drop default arguments in C API PiperOrigin-RevId: 579965820 --- .../language_detector/language_detector.h | 13 +++++----- .../language_detector_test.cc | 7 ++--- .../c/text/text_classifier/text_classifier.h | 13 +++++----- .../text_classifier/text_classifier_test.cc | 7 ++--- .../c/text/text_embedder/text_embedder.h | 7 +++-- .../text/text_embedder/text_embedder_test.cc | 6 ++--- .../image_classifier/image_classifier.h | 17 ++++++------ .../image_classifier/image_classifier_test.cc | 26 +++++++++++-------- 8 files changed, 49 insertions(+), 47 deletions(-) diff --git a/mediapipe/tasks/c/text/language_detector/language_detector.h b/mediapipe/tasks/c/text/language_detector/language_detector.h index f1c85069f..a7f2159b6 100644 --- a/mediapipe/tasks/c/text/language_detector/language_detector.h +++ b/mediapipe/tasks/c/text/language_detector/language_detector.h @@ -60,18 +60,18 @@ struct LanguageDetectorOptions { // Creates a LanguageDetector from the provided `options`. // Returns a pointer to the language detector on success. // If an error occurs, returns `nullptr` and sets the error parameter to an -// an error message (if `error_msg` is not nullptr). You must free the memory +// an error message (if `error_msg` is not `nullptr`). You must free the memory // allocated for the error message. MP_EXPORT void* language_detector_create( - struct LanguageDetectorOptions* options, char** error_msg = nullptr); + struct LanguageDetectorOptions* options, char** error_msg); // Performs language detection on the input `text`. Returns `0` on success. // If an error occurs, returns an error code and sets the error parameter to an -// an error message (if `error_msg` is not nullptr). You must free the memory +// an error message (if `error_msg` is not `nullptr`). You must free the memory // allocated for the error message. MP_EXPORT int language_detector_detect(void* detector, const char* utf8_str, LanguageDetectorResult* result, - char** error_msg = nullptr); + char** error_msg); // Frees the memory allocated inside a LanguageDetectorResult result. Does not // free the result pointer itself. @@ -79,10 +79,9 @@ MP_EXPORT void language_detector_close_result(LanguageDetectorResult* result); // Shuts down the LanguageDetector when all the work is done. Frees all memory. // If an error occurs, returns an error code and sets the error parameter to an -// an error message (if `error_msg` is not nullptr). You must free the memory +// an error message (if `error_msg` is not `nullptr`). You must free the memory // allocated for the error message. -MP_EXPORT int language_detector_close(void* detector, - char** error_msg = nullptr); +MP_EXPORT int language_detector_close(void* detector, char** error_msg); #ifdef __cplusplus } // extern C diff --git a/mediapipe/tasks/c/text/language_detector/language_detector_test.cc b/mediapipe/tasks/c/text/language_detector/language_detector_test.cc index 1c55b2ab5..47770986f 100644 --- a/mediapipe/tasks/c/text/language_detector/language_detector_test.cc +++ b/mediapipe/tasks/c/text/language_detector/language_detector_test.cc @@ -56,16 +56,17 @@ TEST(LanguageDetectorTest, SmokeTest) { /* category_denylist_count= */ 0}, }; - void* detector = language_detector_create(&options); + void* detector = language_detector_create(&options, /* error_msg */ nullptr); EXPECT_NE(detector, nullptr); LanguageDetectorResult result; - language_detector_detect(detector, kTestString, &result); + language_detector_detect(detector, kTestString, &result, + /* error_msg */ nullptr); EXPECT_EQ(std::string(result.predictions[0].language_code), "fr"); EXPECT_NEAR(result.predictions[0].probability, 0.999781, kPrecision); language_detector_close_result(&result); - language_detector_close(detector); + language_detector_close(detector, /* error_msg */ nullptr); } TEST(LanguageDetectorTest, ErrorHandling) { diff --git a/mediapipe/tasks/c/text/text_classifier/text_classifier.h b/mediapipe/tasks/c/text/text_classifier/text_classifier.h index 057b00f99..55b4bc710 100644 --- a/mediapipe/tasks/c/text/text_classifier/text_classifier.h +++ b/mediapipe/tasks/c/text/text_classifier/text_classifier.h @@ -44,18 +44,18 @@ struct TextClassifierOptions { // Creates a TextClassifier from the provided `options`. // Returns a pointer to the text classifier on success. // If an error occurs, returns `nullptr` and sets the error parameter to an -// an error message (if `error_msg` is not nullptr). You must free the memory +// an error message (if `error_msg` is not `nullptr`). You must free the memory // allocated for the error message. MP_EXPORT void* text_classifier_create(struct TextClassifierOptions* options, - char** error_msg = nullptr); + char** error_msg); // Performs classification on the input `text`. Returns `0` on success. // If an error occurs, returns an error code and sets the error parameter to an -// an error message (if `error_msg` is not nullptr). You must free the memory +// an error message (if `error_msg` is not `nullptr`). You must free the memory // allocated for the error message. MP_EXPORT int text_classifier_classify(void* classifier, const char* utf8_str, TextClassifierResult* result, - char** error_msg = nullptr); + char** error_msg); // Frees the memory allocated inside a TextClassifierResult result. Does not // free the result pointer itself. @@ -63,10 +63,9 @@ MP_EXPORT void text_classifier_close_result(TextClassifierResult* result); // Shuts down the TextClassifier when all the work is done. Frees all memory. // If an error occurs, returns an error code and sets the error parameter to an -// an error message (if `error_msg` is not nullptr). You must free the memory +// an error message (if `error_msg` is not `nullptr`). You must free the memory // allocated for the error message. -MP_EXPORT int text_classifier_close(void* classifier, - char** error_msg = nullptr); +MP_EXPORT int text_classifier_close(void* classifier, char** error_msg); #ifdef __cplusplus } // extern C diff --git a/mediapipe/tasks/c/text/text_classifier/text_classifier_test.cc b/mediapipe/tasks/c/text/text_classifier/text_classifier_test.cc index d261be1c8..1dd3f6910 100644 --- a/mediapipe/tasks/c/text/text_classifier/text_classifier_test.cc +++ b/mediapipe/tasks/c/text/text_classifier/text_classifier_test.cc @@ -55,11 +55,12 @@ TEST(TextClassifierTest, SmokeTest) { /* category_denylist_count= */ 0}, }; - void* classifier = text_classifier_create(&options); + void* classifier = text_classifier_create(&options, /* error_msg */ nullptr); EXPECT_NE(classifier, nullptr); TextClassifierResult result; - text_classifier_classify(classifier, kTestString, &result); + text_classifier_classify(classifier, kTestString, &result, + /* error_msg */ nullptr); EXPECT_EQ(result.classifications_count, 1); EXPECT_EQ(result.classifications[0].categories_count, 2); EXPECT_EQ(std::string{result.classifications[0].categories[0].category_name}, @@ -68,7 +69,7 @@ TEST(TextClassifierTest, SmokeTest) { kPrecision); text_classifier_close_result(&result); - text_classifier_close(classifier); + text_classifier_close(classifier, /* error_msg */ nullptr); } TEST(TextClassifierTest, ErrorHandling) { diff --git a/mediapipe/tasks/c/text/text_embedder/text_embedder.h b/mediapipe/tasks/c/text/text_embedder/text_embedder.h index c9ccf816b..c0aab5c76 100644 --- a/mediapipe/tasks/c/text/text_embedder/text_embedder.h +++ b/mediapipe/tasks/c/text/text_embedder/text_embedder.h @@ -47,15 +47,14 @@ struct TextEmbedderOptions { // an error message (if `error_msg` is not `nullptr`). You must free the memory // allocated for the error message. MP_EXPORT void* text_embedder_create(struct TextEmbedderOptions* options, - char** error_msg = nullptr); + char** error_msg); // Performs embedding extraction on the input `text`. Returns `0` on success. // If an error occurs, returns an error code and sets the error parameter to an // an error message (if `error_msg` is not `nullptr`). You must free the memory // allocated for the error message. MP_EXPORT int text_embedder_embed(void* embedder, const char* utf8_str, - TextEmbedderResult* result, - char** error_msg = nullptr); + TextEmbedderResult* result, char** error_msg); // Frees the memory allocated inside a TextEmbedderResult result. Does not // free the result pointer itself. @@ -65,7 +64,7 @@ MP_EXPORT void text_embedder_close_result(TextEmbedderResult* result); // If an error occurs, returns an error code and sets the error parameter to an // an error message (if `error_msg` is not `nullptr`). You must free the memory // allocated for the error message. -MP_EXPORT int text_embedder_close(void* embedder, char** error_msg = nullptr); +MP_EXPORT int text_embedder_close(void* embedder, char** error_msg); #ifdef __cplusplus } // extern C diff --git a/mediapipe/tasks/c/text/text_embedder/text_embedder_test.cc b/mediapipe/tasks/c/text/text_embedder/text_embedder_test.cc index 40c449b8a..1c38a1703 100644 --- a/mediapipe/tasks/c/text/text_embedder/text_embedder_test.cc +++ b/mediapipe/tasks/c/text/text_embedder/text_embedder_test.cc @@ -48,16 +48,16 @@ TEST(TextEmbedderTest, SmokeTest) { {/* l2_normalize= */ false, /* quantize= */ true}, }; - void* embedder = text_embedder_create(&options); + void* embedder = text_embedder_create(&options, /* error_msg */ nullptr); EXPECT_NE(embedder, nullptr); TextEmbedderResult result; - text_embedder_embed(embedder, kTestString, &result); + text_embedder_embed(embedder, kTestString, &result, /* error_msg */ nullptr); EXPECT_EQ(result.embeddings_count, 1); EXPECT_EQ(result.embeddings[0].values_count, 512); text_embedder_close_result(&result); - text_embedder_close(embedder); + text_embedder_close(embedder, /* error_msg */ nullptr); } TEST(TextEmbedderTest, ErrorHandling) { diff --git a/mediapipe/tasks/c/vision/image_classifier/image_classifier.h b/mediapipe/tasks/c/vision/image_classifier/image_classifier.h index 549c3f300..51316bcbe 100644 --- a/mediapipe/tasks/c/vision/image_classifier/image_classifier.h +++ b/mediapipe/tasks/c/vision/image_classifier/image_classifier.h @@ -108,30 +108,30 @@ struct ImageClassifierOptions { // Creates an ImageClassifier from provided `options`. // Returns a pointer to the image classifier on success. // If an error occurs, returns `nullptr` and sets the error parameter to an -// an error message (if `error_msg` is not nullptr). You must free the memory +// an error message (if `error_msg` is not `nullptr`). You must free the memory // allocated for the error message. MP_EXPORT void* image_classifier_create(struct ImageClassifierOptions* options, - char** error_msg = nullptr); + char** error_msg); // Performs image classification on the input `image`. Returns `0` on success. // If an error occurs, returns an error code and sets the error parameter to an -// an error message (if `error_msg` is not nullptr). You must free the memory +// an error message (if `error_msg` is not `nullptr`). You must free the memory // allocated for the error message. MP_EXPORT int image_classifier_classify_image(void* classifier, const MpImage* image, ImageClassifierResult* result, - char** error_msg = nullptr); + char** error_msg); MP_EXPORT int image_classifier_classify_for_video(void* classifier, const MpImage* image, int64_t timestamp_ms, ImageClassifierResult* result, - char** error_msg = nullptr); + char** error_msg); MP_EXPORT int image_classifier_classify_async(void* classifier, const MpImage* image, int64_t timestamp_ms, - char** error_msg = nullptr); + char** error_msg); // Frees the memory allocated inside a ImageClassifierResult result. // Does not free the result pointer itself. @@ -139,10 +139,9 @@ MP_EXPORT void image_classifier_close_result(ImageClassifierResult* result); // Frees image classifier. // If an error occurs, returns an error code and sets the error parameter to an -// an error message (if `error_msg` is not nullptr). You must free the memory +// an error message (if `error_msg` is not `nullptr`). You must free the memory // allocated for the error message. -MP_EXPORT int image_classifier_close(void* classifier, - char** error_msg = nullptr); +MP_EXPORT int image_classifier_close(void* classifier, char** error_msg); #ifdef __cplusplus } // extern C diff --git a/mediapipe/tasks/c/vision/image_classifier/image_classifier_test.cc b/mediapipe/tasks/c/vision/image_classifier/image_classifier_test.cc index a66e42832..22a716dfd 100644 --- a/mediapipe/tasks/c/vision/image_classifier/image_classifier_test.cc +++ b/mediapipe/tasks/c/vision/image_classifier/image_classifier_test.cc @@ -63,7 +63,7 @@ TEST(ImageClassifierTest, ImageModeTest) { /* category_denylist_count= */ 0}, }; - void* classifier = image_classifier_create(&options); + void* classifier = image_classifier_create(&options, /* error_msg */ nullptr); EXPECT_NE(classifier, nullptr); const auto& image_frame = image->GetImageFrameSharedPtr(); @@ -75,7 +75,8 @@ TEST(ImageClassifierTest, ImageModeTest) { .height = image_frame->Height()}}; ImageClassifierResult result; - image_classifier_classify_image(classifier, &mp_image, &result); + image_classifier_classify_image(classifier, &mp_image, &result, + /* error_msg */ nullptr); EXPECT_EQ(result.classifications_count, 1); EXPECT_EQ(result.classifications[0].categories_count, 1001); EXPECT_EQ(std::string{result.classifications[0].categories[0].category_name}, @@ -83,7 +84,7 @@ TEST(ImageClassifierTest, ImageModeTest) { EXPECT_NEAR(result.classifications[0].categories[0].score, 0.7939f, kPrecision); image_classifier_close_result(&result); - image_classifier_close(classifier); + image_classifier_close(classifier, /* error_msg */ nullptr); } TEST(ImageClassifierTest, VideoModeTest) { @@ -107,7 +108,7 @@ TEST(ImageClassifierTest, VideoModeTest) { /* result_callback= */ nullptr, }; - void* classifier = image_classifier_create(&options); + void* classifier = image_classifier_create(&options, /* error_msg */ nullptr); EXPECT_NE(classifier, nullptr); const auto& image_frame = image->GetImageFrameSharedPtr(); @@ -120,7 +121,8 @@ TEST(ImageClassifierTest, VideoModeTest) { for (int i = 0; i < kIterations; ++i) { ImageClassifierResult result; - image_classifier_classify_for_video(classifier, &mp_image, i, &result); + image_classifier_classify_for_video(classifier, &mp_image, i, &result, + /* error_msg */ nullptr); EXPECT_EQ(result.classifications_count, 1); EXPECT_EQ(result.classifications[0].categories_count, 3); EXPECT_EQ( @@ -130,7 +132,7 @@ TEST(ImageClassifierTest, VideoModeTest) { kPrecision); image_classifier_close_result(&result); } - image_classifier_close(classifier); + image_classifier_close(classifier, /* error_msg */ nullptr); } // A structure to support LiveStreamModeTest below. This structure holds a @@ -180,7 +182,7 @@ TEST(ImageClassifierTest, LiveStreamModeTest) { /* result_callback= */ LiveStreamModeCallback::Fn, }; - void* classifier = image_classifier_create(&options); + void* classifier = image_classifier_create(&options, /* error_msg */ nullptr); EXPECT_NE(classifier, nullptr); const auto& image_frame = image->GetImageFrameSharedPtr(); @@ -192,9 +194,11 @@ TEST(ImageClassifierTest, LiveStreamModeTest) { .height = image_frame->Height()}}; for (int i = 0; i < kIterations; ++i) { - EXPECT_GE(image_classifier_classify_async(classifier, &mp_image, i), 0); + EXPECT_GE(image_classifier_classify_async(classifier, &mp_image, i, + /* error_msg */ nullptr), + 0); } - image_classifier_close(classifier); + image_classifier_close(classifier, /* error_msg */ nullptr); // Due to the flow limiter, the total of outputs might be smaller than the // number of iterations. @@ -237,7 +241,7 @@ TEST(ImageClassifierTest, FailedClassificationHandling) { /* category_denylist_count= */ 0}, }; - void* classifier = image_classifier_create(&options); + void* classifier = image_classifier_create(&options, /* error_msg */ nullptr); EXPECT_NE(classifier, nullptr); const MpImage mp_image = {.type = MpImage::GPU_BUFFER, .gpu_buffer = {}}; @@ -246,7 +250,7 @@ TEST(ImageClassifierTest, FailedClassificationHandling) { image_classifier_classify_image(classifier, &mp_image, &result, &error_msg); EXPECT_THAT(error_msg, HasSubstr("GPU Buffer not supported yet")); free(error_msg); - image_classifier_close(classifier); + image_classifier_close(classifier, /* error_msg */ nullptr); } } // namespace