You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
303 lines
14 KiB
303 lines
14 KiB
//
|
|
// SCLogger+Camera.m
|
|
// Snapchat
|
|
//
|
|
// Created by Derek Peirce on 5/8/17.
|
|
// Copyright © 2017 Snapchat, Inc. All rights reserved.
|
|
//
|
|
|
|
#import "SCLogger+Camera.h"
|
|
|
|
#import "SCCameraTweaks.h"
|
|
|
|
#import <SCFoundation/SCTrace.h>
|
|
#import <SCFoundation/SCTraceODPCompatible.h>
|
|
#import <SCLogger/SCCameraMetrics+CameraCreationDelay.h>
|
|
#import <SCLogger/SCCameraMetrics.h>
|
|
#import <SCLogger/SCLogger+Performance.h>
|
|
|
|
#import <objc/runtime.h>
|
|
|
|
@implementation SCLogger (Camera)
|
|
|
|
@dynamic cameraCreationDelayLoggingStatus;
|
|
|
|
- (NSNumber *)cameraCreationDelayLoggingStatus
|
|
{
|
|
return objc_getAssociatedObject(self, @selector(cameraCreationDelayLoggingStatus));
|
|
}
|
|
|
|
- (void)setCameraCreationDelayLoggingStatus:(NSNumber *)status
|
|
{
|
|
objc_setAssociatedObject(self, @selector(cameraCreationDelayLoggingStatus), status,
|
|
OBJC_ASSOCIATION_RETAIN_NONATOMIC);
|
|
}
|
|
|
|
- (BOOL)shouldLogCameraCreationDelay
|
|
{
|
|
return [[self cameraCreationDelayLoggingStatus] intValue] != CAMERA_CREATION_DELAY_LOGGING_END;
|
|
}
|
|
|
|
- (void)logCameraCreationDelayEnd
|
|
{
|
|
if ([[self cameraCreationDelayLoggingStatus] intValue] == CAMERA_CREATION_DELAY_LOGGINT_LAST_STEP) {
|
|
SCTraceSignPostEndForMetrics(kSCSignPostCameraCreationDelay, 0, 0, 0, 0);
|
|
[self setCameraCreationDelayLoggingStatus:@(CAMERA_CREATION_DELAY_LOGGING_END)];
|
|
} else {
|
|
[self setCameraCreationDelayLoggingStatus:@(CAMERA_CREATION_DELAY_LOGGINT_LAST_STEP)];
|
|
}
|
|
}
|
|
|
|
- (void)logCameraCreationStartWithMethod:(SCCameraRecordingMethod)method
|
|
lensesEnabled:(BOOL)lensesEnabled
|
|
activeLensId:(NSString *)activeLensId
|
|
captureSessionId:(NSString *)captureSessionId
|
|
{
|
|
NSMutableDictionary *parameters = [@{
|
|
@"lens_ui_enabled" : @(lensesEnabled),
|
|
@"analytics_version" : kSCCameraDelayEventVersion,
|
|
@"method" : @(method),
|
|
} mutableCopy];
|
|
if (lensesEnabled && activeLensId) {
|
|
[parameters setObject:activeLensId forKey:@"lens_id"];
|
|
}
|
|
if (captureSessionId) {
|
|
[parameters setObject:captureSessionId forKey:@"capture_session_id"];
|
|
}
|
|
[self setCameraCreationDelayLoggingStatus:@(CAMERA_CREATION_DELAY_LOGGING_START)];
|
|
[self logCameraCreationDelaySubMetricsStartWithSignCode:kSCSignPostCameraCreationDelay];
|
|
[self logCameraCreationDelaySubMetricsStartWithSignCode:kSCSignPostCameraRecordingGestureFinished];
|
|
[self logCameraCreationDelaySubMetricsStartWithSignCode:kSCSignPostCameraPreCaptureOperationRequested];
|
|
[[SCLogger sharedInstance] logTimedEventStart:kSCCameraCaptureDelayEvent
|
|
uniqueId:@""
|
|
isUniqueEvent:NO
|
|
parameters:parameters
|
|
shouldLogStartTime:YES];
|
|
}
|
|
|
|
- (void)logCameraExposureAdjustmentDelayStart
|
|
{
|
|
[[SCLogger sharedInstance] logTimedEventStart:kSCCameraExposureAdjustmentDelay
|
|
uniqueId:@""
|
|
isUniqueEvent:NO
|
|
parameters:nil
|
|
shouldLogStartTime:YES];
|
|
}
|
|
|
|
- (void)logCameraExposureAdjustmentDelayEndWithStrategy:(NSString *)strategy
|
|
{
|
|
[[SCLogger sharedInstance] logTimedEventEnd:kSCCameraExposureAdjustmentDelay
|
|
uniqueId:@""
|
|
parameters:@{
|
|
@"strategy" : strategy
|
|
}];
|
|
}
|
|
|
|
- (void)logCameraCaptureRecordingGestureFinishedAtTime:(CFTimeInterval)endRecordingTime
|
|
{
|
|
[self logCameraCreationDelaySubMetricsEndWithSignCode:kSCSignPostCameraRecordingGestureFinished];
|
|
[[SCLogger sharedInstance]
|
|
updateLogTimedEvent:kSCCameraCaptureDelayEvent
|
|
uniqueId:@""
|
|
update:^(NSMutableDictionary *startParameters) {
|
|
NSMutableDictionary *eventParameters =
|
|
startParameters[SCPerformanceMetricsKey.kSCLoggerStartEventParametersKey];
|
|
NSNumber *recordStartTime =
|
|
(NSNumber *)eventParameters[kSCCameraSubmetricsPreCaptureOperationFinished];
|
|
CFTimeInterval endRecordingTimeOffset =
|
|
endRecordingTime -
|
|
[startParameters[SCPerformanceMetricsKey.kSCLoggerStartEventTimeKey] doubleValue];
|
|
if (recordStartTime) {
|
|
CFTimeInterval timeDisplacement =
|
|
([recordStartTime doubleValue] / 1000.0) - endRecordingTimeOffset;
|
|
[eventParameters setObject:@(timeDisplacement)
|
|
forKey:SCPerformanceMetricsKey.kSCLoggerStartEventTimeAdjustmentKey];
|
|
}
|
|
[self addSplitPoint:kSCCameraSubmetricsRecordingGestureFinished
|
|
atTime:endRecordingTime
|
|
toEvent:startParameters];
|
|
}];
|
|
}
|
|
|
|
- (void)logStillImageCaptureApi:(NSString *)api
|
|
{
|
|
[self logCameraCreationDelaySubMetricsEndWithSignCode:kSCSignPostCameraPreCaptureOperationRequested];
|
|
[self logCameraCreationDelaySubMetricsStartWithSignCode:kSCSignPostCameraPreCaptureOperationFinished];
|
|
[self logCameraCreationDelaySubMetricsStartWithSignCode:kSCSignPostCameraCaptureContentReady];
|
|
CFTimeInterval requestTime = CACurrentMediaTime();
|
|
[self updateLogTimedEvent:kSCCameraCaptureDelayEvent
|
|
uniqueId:@""
|
|
update:^(NSMutableDictionary *startParameters) {
|
|
NSMutableDictionary *eventParameters =
|
|
startParameters[SCPerformanceMetricsKey.kSCLoggerStartEventParametersKey];
|
|
[eventParameters setObject:api forKey:@"api_type"];
|
|
[eventParameters setObject:@(1) forKey:@"camera_api_level"];
|
|
[self addSplitPoint:@"PRE_CAPTURE_OPERATION_REQUESTED"
|
|
atTime:requestTime
|
|
toEvent:startParameters];
|
|
}];
|
|
}
|
|
|
|
- (void)logPreCaptureOperationRequestedAt:(CFTimeInterval)requestTime
|
|
{
|
|
[self logCameraCreationDelaySubMetricsEndWithSignCode:kSCSignPostCameraPreCaptureOperationRequested];
|
|
[self logCameraCreationDelaySubMetricsStartWithSignCode:kSCSignPostCameraPreCaptureOperationFinished];
|
|
[self logCameraCreationDelaySubMetricsStartWithSignCode:kSCSignPostCameraCaptureContentReady];
|
|
[self updateLogTimedEvent:kSCCameraCaptureDelayEvent
|
|
uniqueId:@""
|
|
splitPoint:kSCCameraSubmetricsPreCaptureOperationRequested
|
|
time:requestTime];
|
|
}
|
|
|
|
- (void)logPreCaptureOperationFinishedAt:(CFTimeInterval)time
|
|
{
|
|
[self logCameraCreationDelaySubMetricsEndWithSignCode:kSCSignPostCameraPreCaptureOperationFinished];
|
|
[self logCameraCreationDelaySubMetricsStartWithSignCode:kSCSignPostCameraPreviewPlayerReady];
|
|
[self updateLogTimedEvent:kSCCameraCaptureDelayEvent
|
|
uniqueId:@""
|
|
splitPoint:kSCCameraSubmetricsPreCaptureOperationFinished
|
|
time:time];
|
|
}
|
|
|
|
- (void)logCameraCaptureFinishedWithDuration:(CFTimeInterval)duration
|
|
{
|
|
[[SCLogger sharedInstance]
|
|
updateLogTimedEvent:kSCCameraCaptureDelayEvent
|
|
uniqueId:@""
|
|
update:^(NSMutableDictionary *startParameters) {
|
|
NSMutableDictionary *eventParameters =
|
|
startParameters[SCPerformanceMetricsKey.kSCLoggerStartEventParametersKey];
|
|
[eventParameters setObject:@(SCTimeInMillisecond(duration)) forKey:@"content_duration"];
|
|
}];
|
|
}
|
|
|
|
- (void)logCameraCaptureContentReady
|
|
{
|
|
[self logCameraCreationDelaySubMetricsEndWithSignCode:kSCSignPostCameraCaptureContentReady];
|
|
[[SCLogger sharedInstance] updateLogTimedEvent:kSCCameraCaptureDelayEvent
|
|
uniqueId:@""
|
|
splitPoint:kSCCameraSubmetricsCameraCaptureContentReady];
|
|
}
|
|
|
|
- (void)logPreviewFinishedPreparation
|
|
{
|
|
[self logCameraCreationDelaySubMetricsEndWithSignCode:kSCSignPostCameraPreviewFinishPreparation];
|
|
[self logCameraCreationDelaySubMetricsStartWithSignCode:kSCSignPostCameraPreviewAnimationFinish];
|
|
[self updateLogTimedEvent:kSCCameraCaptureDelayEvent
|
|
uniqueId:@""
|
|
splitPoint:kSCCameraSubmetricsPreviewFinishPreparation];
|
|
}
|
|
|
|
- (void)logPreviewDisplayedForImage:(BOOL)isImage
|
|
{
|
|
[self logCameraCreationDelaySubMetricsEndWithSignCode:kSCSignPostCameraPreviewLayoutReady];
|
|
[self updateLogTimedEvent:kSCCameraCaptureDelayEvent uniqueId:@"" splitPoint:kSCCameraSubmetricsPreviewLayoutReady];
|
|
}
|
|
|
|
- (void)logPreviewAnimationComplete:(BOOL)isImage
|
|
{
|
|
[self updateLogTimedEvent:kSCCameraCaptureDelayEvent
|
|
uniqueId:@""
|
|
splitPoint:kSCCameraSubmetricsPreviewAnimationFinish];
|
|
[self logCameraCreationDelaySubMetricsEndWithSignCode:kSCSignPostCameraPreviewAnimationFinish];
|
|
[self logCameraCreationDelayEnd];
|
|
[self conditionallyLogTimedEventEnd:kSCCameraCaptureDelayEvent
|
|
uniqueId:@""
|
|
parameters:@{
|
|
@"type" : isImage ? @"image" : @"video",
|
|
}
|
|
shouldLog:^BOOL(NSDictionary *startParameters) {
|
|
// For video, PREVIEW_PLAYER_READY and PREVIEW_ANIMATION_FINISH can happen in either
|
|
// order. So here we check for existence of this key, and end timer if the other
|
|
// event have happened.
|
|
NSMutableDictionary *eventParameters =
|
|
startParameters[SCPerformanceMetricsKey.kSCLoggerStartEventParametersKey];
|
|
return eventParameters[kSCCameraSubmetricsPreviewPlayerReady] != nil;
|
|
}];
|
|
}
|
|
|
|
- (void)logPreviewFirstFramePlayed:(BOOL)isImage
|
|
{
|
|
[self updateLogTimedEvent:kSCCameraCaptureDelayEvent uniqueId:@"" splitPoint:kSCCameraSubmetricsPreviewPlayerReady];
|
|
[self logCameraCreationDelaySubMetricsEndWithSignCode:kSCSignPostCameraPreviewPlayerReady];
|
|
[self logCameraCreationDelayEnd];
|
|
[self conditionallyLogTimedEventEnd:kSCCameraCaptureDelayEvent
|
|
uniqueId:@""
|
|
parameters:@{
|
|
@"type" : isImage ? @"image" : @"video",
|
|
}
|
|
shouldLog:^BOOL(NSDictionary *startParameters) {
|
|
NSMutableDictionary *eventParameters =
|
|
startParameters[SCPerformanceMetricsKey.kSCLoggerStartEventParametersKey];
|
|
// See the comment above for PREVIEW_PLAYER_READY and PREVIEW_ANIMATION_FINISH.
|
|
return eventParameters[kSCCameraSubmetricsPreviewAnimationFinish] != nil;
|
|
}];
|
|
}
|
|
|
|
- (void)cancelCameraCreationEvent
|
|
{
|
|
[self cancelLogTimedEvent:kSCCameraCaptureDelayEvent uniqueId:@""];
|
|
}
|
|
|
|
- (void)logRecordingMayBeTooShortWithMethod:(SCCameraRecordingMethod)method
|
|
{
|
|
[[SCLogger sharedInstance] cancelLogTimedEvent:kSCCameraMetricsRecordingTooShort uniqueId:@""];
|
|
[[SCLogger sharedInstance] logTimedEventStart:kSCCameraMetricsRecordingTooShort
|
|
uniqueId:@""
|
|
isUniqueEvent:NO
|
|
parameters:@{
|
|
@"method" : @(method),
|
|
@"analytics_version" : kSCCameraRecordingTooShortVersion,
|
|
}
|
|
shouldLogStartTime:YES];
|
|
}
|
|
|
|
- (void)logRecordingWasTooShortWithFirstFrame:(CMTime)firstFrame
|
|
frontFacingCamera:(BOOL)isFrontFacing
|
|
cameraFlips:(NSInteger)cameraFlips
|
|
{
|
|
[self logTimedEventEnd:kSCCameraMetricsRecordingTooShort
|
|
uniqueId:@""
|
|
update:^(NSDictionary *startParameters, CFTimeInterval eventEndTime, CFTimeInterval adjustedTime) {
|
|
NSMutableDictionary *eventParameters =
|
|
startParameters[SCPerformanceMetricsKey.kSCLoggerStartEventParametersKey];
|
|
if (CMTIME_IS_VALID(firstFrame)) {
|
|
CFTimeInterval startTime =
|
|
[startParameters[SCPerformanceMetricsKey.kSCLoggerStartEventTimeKey] doubleValue];
|
|
CFTimeInterval firstFrameRelative = CMTimeGetSeconds(firstFrame) - startTime;
|
|
[eventParameters setObject:@(firstFrameRelative) forKey:@"first_frame_s"];
|
|
}
|
|
[eventParameters setObject:@(isFrontFacing) forKey:@"is_front_facing"];
|
|
if (cameraFlips) {
|
|
[eventParameters setObject:@(cameraFlips > 0) forKey:@"has_camera_been_flipped"];
|
|
}
|
|
}];
|
|
}
|
|
|
|
- (void)logManagedCapturerSettingFailure:(NSString *)settingTask error:(NSError *)error
|
|
{
|
|
NSMutableDictionary *parameters = [[NSMutableDictionary alloc] init];
|
|
parameters[@"setting_task"] = settingTask;
|
|
if (error) {
|
|
parameters[@"setting error"] = error;
|
|
}
|
|
[[SCLogger sharedInstance] logTimedEventEnd:kSCCameraManagedCaptureSettingFailure
|
|
uniqueId:@""
|
|
parameters:parameters];
|
|
}
|
|
|
|
- (void)logCameraCreationDelaySubMetricsStartWithSignCode:(kSCSignPostCodeEnum)signPostCode
|
|
{
|
|
if ([self shouldLogCameraCreationDelay]) {
|
|
SCTraceSignPostStartForMetrics(signPostCode, 0, 0, 0, 0);
|
|
}
|
|
}
|
|
|
|
- (void)logCameraCreationDelaySubMetricsEndWithSignCode:(kSCSignPostCodeEnum)signPostCode
|
|
{
|
|
if ([self shouldLogCameraCreationDelay]) {
|
|
SCTraceSignPostEndForMetrics(signPostCode, 0, 0, 0, 0);
|
|
}
|
|
}
|
|
|
|
@end
|