Added a method in iOS image classifier to process result for the callback

This commit is contained in:
Prianka Liz Kariat 2023-05-29 22:37:59 +05:30
parent 759e9fd56e
commit 250b11f5d1

View File

@ -55,6 +55,7 @@ static const int kMicroSecondsPerMilliSecond = 1000;
@interface MPPImageClassifier () { @interface MPPImageClassifier () {
/** iOS Vision Task Runner */ /** iOS Vision Task Runner */
MPPVisionTaskRunner *_visionTaskRunner; MPPVisionTaskRunner *_visionTaskRunner;
dispatch_queue_t _callbackQueue;
} }
@property(nonatomic, weak) id<MPPImageClassifierLiveStreamDelegate> @property(nonatomic, weak) id<MPPImageClassifierLiveStreamDelegate>
imageClassifierLiveStreamDelegate; imageClassifierLiveStreamDelegate;
@ -62,6 +63,44 @@ static const int kMicroSecondsPerMilliSecond = 1000;
@implementation MPPImageClassifier @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, ^{
[self.imageClassifierLiveStreamDelegate imageClassifier:self
didFinishClassificationWithResult:nil
timestampInMilliseconds:Timestamp::Unset().Value()
error:callbackError];
});
return;
}
PacketMap &outputPacketMap = liveStreamResult.value();
if (outputPacketMap[kImageOutStreamName.cppString].IsEmpty()) {
return;
}
MPPImageClassifierResult *result = [MPPImageClassifierResult
imageClassifierResultWithClassificationsPacket:outputPacketMap[kClassificationsStreamName
.cppString]];
NSInteger timeStampInMilliseconds =
outputPacketMap[kImageOutStreamName.cppString].Timestamp().Value() /
kMicroSecondsPerMilliSecond;
dispatch_async(_callbackQueue, ^{
[self.imageClassifierLiveStreamDelegate imageClassifier:self
didFinishClassificationWithResult:result
timestampInMilliseconds:timeStampInMilliseconds
error:callbackError];
});
}
- (instancetype)initWithOptions:(MPPImageClassifierOptions *)options error:(NSError **)error { - (instancetype)initWithOptions:(MPPImageClassifierOptions *)options error:(NSError **)error {
self = [super init]; self = [super init];
if (self) { if (self) {
@ -88,56 +127,19 @@ static const int kMicroSecondsPerMilliSecond = 1000;
if (options.imageClassifierLiveStreamDelegate) { if (options.imageClassifierLiveStreamDelegate) {
_imageClassifierLiveStreamDelegate = options.imageClassifierLiveStreamDelegate; _imageClassifierLiveStreamDelegate = options.imageClassifierLiveStreamDelegate;
// Capturing `self` as weak in order to avoid `self` being kept in memory
// and cause a retain cycle, after self is set to `nil`.
MPPImageClassifier *__weak weakSelf = self;
// Create a private serial dispatch queue in which the deleagte method will be called // Create a private serial dispatch queue in which the deleagte method will be called
// asynchronously. This is to ensure that if the client performs a long running operation in // asynchronously. This is to ensure that if the client performs a long running operation in
// the delegate method, the queue on which the C++ callbacks is invoked is not blocked and is // the delegate method, the queue on which the C++ callbacks is invoked is not blocked and is
// freed up to continue with its operations. // freed up to continue with its operations.
const char *queueName = [MPPVisionTaskRunner uniqueDispatchQueueNameWithSuffix:kTaskName]; _callbackQueue = dispatch_queue_create(
dispatch_queue_t callbackQueue = dispatch_queue_create(queueName, NULL); [MPPVisionTaskRunner uniqueDispatchQueueNameWithSuffix:kTaskName], NULL);
packetsCallback = [=](absl::StatusOr<PacketMap> status_or_packets) {
if (!weakSelf) {
return;
}
if (![weakSelf.imageClassifierLiveStreamDelegate
respondsToSelector:@selector
(imageClassifier:
didFinishClassificationWithResult:timestampInMilliseconds:error:)]) {
return;
}
NSError *callbackError = nil; // Capturing `self` as weak in order to avoid `self` being kept in memory
if (![MPPCommonUtils checkCppError:status_or_packets.status() toError:&callbackError]) { // and cause a retain cycle, after self is set to `nil`.
dispatch_async(callbackQueue, ^{ MPPImageClassifier *__weak weakSelf = self;
[weakSelf.imageClassifierLiveStreamDelegate imageClassifier:weakSelf packetsCallback = [=](absl::StatusOr<PacketMap> liveStreamResult) {
didFinishClassificationWithResult:nil [weakSelf processLiveStreamResult:liveStreamResult];
timestampInMilliseconds:Timestamp::Unset().Value()
error:callbackError];
});
return;
}
PacketMap &outputPacketMap = status_or_packets.value();
if (outputPacketMap[kImageOutStreamName.cppString].IsEmpty()) {
return;
}
MPPImageClassifierResult *result =
[MPPImageClassifierResult imageClassifierResultWithClassificationsPacket:
outputPacketMap[kClassificationsStreamName.cppString]];
NSInteger timeStampInMilliseconds =
outputPacketMap[kImageOutStreamName.cppString].Timestamp().Value() /
kMicroSecondsPerMilliSecond;
dispatch_async(callbackQueue, ^{
[weakSelf.imageClassifierLiveStreamDelegate imageClassifier:weakSelf
didFinishClassificationWithResult:result
timestampInMilliseconds:timeStampInMilliseconds
error:callbackError];
});
}; };
} }