diff options
author | Joel Fischer <joeljfischer@gmail.com> | 2018-06-19 13:41:35 -0400 |
---|---|---|
committer | Joel Fischer <joeljfischer@gmail.com> | 2018-06-19 13:41:35 -0400 |
commit | b108fcac30765aacfcc8fbeb450be104432a6420 (patch) | |
tree | bd0feecec120959f165a2230cfe693f5bf53509e | |
parent | 3ba2b1bf041ebc17e86f4a6c152a2a67626b4232 (diff) | |
download | sdl_ios-b108fcac30765aacfcc8fbeb450be104432a6420.tar.gz |
Separate video / audio streaming lifecycle manager code
-rw-r--r-- | SmartDeviceLink-iOS.podspec | 1 | ||||
-rw-r--r-- | SmartDeviceLink-iOS.xcodeproj/project.pbxproj | 26 | ||||
-rw-r--r-- | SmartDeviceLink.podspec | 1 | ||||
-rwxr-xr-x | SmartDeviceLink/SDLCarWindow.h | 4 | ||||
-rwxr-xr-x | SmartDeviceLink/SDLCarWindow.m | 6 | ||||
-rw-r--r-- | SmartDeviceLink/SDLStreamingAudioLifecycleManager.h | 94 | ||||
-rw-r--r-- | SmartDeviceLink/SDLStreamingAudioLifecycleManager.m | 345 | ||||
-rw-r--r-- | SmartDeviceLink/SDLStreamingMediaManager.m | 56 | ||||
-rw-r--r-- | SmartDeviceLink/SDLStreamingMediaManagerConstants.h | 17 | ||||
-rw-r--r-- | SmartDeviceLink/SDLStreamingMediaManagerConstants.m | 14 | ||||
-rw-r--r-- | SmartDeviceLink/SDLStreamingVideoLifecycleManager.h (renamed from SmartDeviceLink/SDLStreamingMediaLifecycleManager.h) | 69 | ||||
-rw-r--r-- | SmartDeviceLink/SDLStreamingVideoLifecycleManager.m (renamed from SmartDeviceLink/SDLStreamingMediaLifecycleManager.m) | 225 | ||||
-rw-r--r-- | SmartDeviceLink/SmartDeviceLink.h | 1 |
13 files changed, 570 insertions, 289 deletions
diff --git a/SmartDeviceLink-iOS.podspec b/SmartDeviceLink-iOS.podspec index bb6c44e3e..4bc15a3de 100644 --- a/SmartDeviceLink-iOS.podspec +++ b/SmartDeviceLink-iOS.podspec @@ -327,6 +327,7 @@ ss.public_header_files = [ 'SmartDeviceLink/SDLVideoStreamingCodec.h', 'SmartDeviceLink/SDLVideoStreamingFormat.h', 'SmartDeviceLink/SDLVideoStreamingProtocol.h', +'SmartDeviceLink/SDLVideoStreamingState.h', 'SmartDeviceLink/SDLVoiceCommand.h', 'SmartDeviceLink/SDLVrCapabilities.h', 'SmartDeviceLink/SDLVrHelpItem.h', diff --git a/SmartDeviceLink-iOS.xcodeproj/project.pbxproj b/SmartDeviceLink-iOS.xcodeproj/project.pbxproj index 391f4e1f2..8464876ab 100644 --- a/SmartDeviceLink-iOS.xcodeproj/project.pbxproj +++ b/SmartDeviceLink-iOS.xcodeproj/project.pbxproj @@ -333,8 +333,12 @@ 5D0A9F971F1559EC00CC80DD /* SDLSystemCapabilitySpec.m in Sources */ = {isa = PBXBuildFile; fileRef = 5D0A9F961F1559EC00CC80DD /* SDLSystemCapabilitySpec.m */; }; 5D0A9F9A1F15636800CC80DD /* SDLGetSystemCapabilitiesSpec.m in Sources */ = {isa = PBXBuildFile; fileRef = 5D0A9F991F15636800CC80DD /* SDLGetSystemCapabilitiesSpec.m */; }; 5D0A9F9C1F1565EB00CC80DD /* SDLGetSystemCapabilityResponseSpec.m in Sources */ = {isa = PBXBuildFile; fileRef = 5D0A9F9B1F1565EB00CC80DD /* SDLGetSystemCapabilityResponseSpec.m */; }; - 5D0C29FC20D93D8C008B56CD /* SDLVideoStreamingState.h in Headers */ = {isa = PBXBuildFile; fileRef = 5D0C29FA20D93D8C008B56CD /* SDLVideoStreamingState.h */; }; + 5D0C29FC20D93D8C008B56CD /* SDLVideoStreamingState.h in Headers */ = {isa = PBXBuildFile; fileRef = 5D0C29FA20D93D8C008B56CD /* SDLVideoStreamingState.h */; settings = {ATTRIBUTES = (Public, ); }; }; 5D0C29FD20D93D8C008B56CD /* SDLVideoStreamingState.m in Sources */ = {isa = PBXBuildFile; fileRef = 5D0C29FB20D93D8C008B56CD /* SDLVideoStreamingState.m */; }; + 5D0C2A0020D9479B008B56CD /* SDLStreamingVideoLifecycleManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 5D0C29FE20D9479B008B56CD /* SDLStreamingVideoLifecycleManager.h */; }; + 5D0C2A0120D9479B008B56CD /* SDLStreamingVideoLifecycleManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 5D0C29FF20D9479B008B56CD /* SDLStreamingVideoLifecycleManager.m */; }; + 5D0C2A0420D947AB008B56CD /* SDLStreamingAudioLifecycleManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 5D0C2A0220D947AB008B56CD /* SDLStreamingAudioLifecycleManager.h */; }; + 5D0C2A0520D947AB008B56CD /* SDLStreamingAudioLifecycleManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 5D0C2A0320D947AB008B56CD /* SDLStreamingAudioLifecycleManager.m */; }; 5D1654561D3E754F00554D93 /* SDLLifecycleManagerSpec.m in Sources */ = {isa = PBXBuildFile; fileRef = 5D1654551D3E754F00554D93 /* SDLLifecycleManagerSpec.m */; }; 5D16545A1D3E7A1600554D93 /* SDLLifecycleManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 5D1654581D3E7A1600554D93 /* SDLLifecycleManager.h */; }; 5D16545B1D3E7A1600554D93 /* SDLLifecycleManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 5D1654591D3E7A1600554D93 /* SDLLifecycleManager.m */; }; @@ -1145,8 +1149,6 @@ DA4F47961E771AA100FC809E /* SDLEnum.m in Sources */ = {isa = PBXBuildFile; fileRef = DA4F47951E771AA100FC809E /* SDLEnum.m */; }; DA6223BD1E7B088200878689 /* CVPixelBufferRef+SDLUtil.h in Headers */ = {isa = PBXBuildFile; fileRef = DA6223BB1E7B088200878689 /* CVPixelBufferRef+SDLUtil.h */; }; DA6223BE1E7B088200878689 /* CVPixelBufferRef+SDLUtil.m in Sources */ = {isa = PBXBuildFile; fileRef = DA6223BC1E7B088200878689 /* CVPixelBufferRef+SDLUtil.m */; }; - DA8966EB1E56939F00413EAB /* SDLStreamingMediaLifecycleManager.h in Headers */ = {isa = PBXBuildFile; fileRef = DA8966E91E56939F00413EAB /* SDLStreamingMediaLifecycleManager.h */; }; - DA8966EC1E56939F00413EAB /* SDLStreamingMediaLifecycleManager.m in Sources */ = {isa = PBXBuildFile; fileRef = DA8966EA1E56939F00413EAB /* SDLStreamingMediaLifecycleManager.m */; }; DA8966EF1E5693E300413EAB /* SDLStreamingMediaLifecycleManagerSpec.m in Sources */ = {isa = PBXBuildFile; fileRef = DA8966EE1E5693E300413EAB /* SDLStreamingMediaLifecycleManagerSpec.m */; }; DA8966F21E56973700413EAB /* SDLStreamingMediaManagerConstants.h in Headers */ = {isa = PBXBuildFile; fileRef = DA8966F11E56973700413EAB /* SDLStreamingMediaManagerConstants.h */; settings = {ATTRIBUTES = (Public, ); }; }; DA96C0661D4D4F730022F520 /* SDLAppInfoSpec.m in Sources */ = {isa = PBXBuildFile; fileRef = DA96C0651D4D4F730022F520 /* SDLAppInfoSpec.m */; }; @@ -1641,6 +1643,10 @@ 5D0A9F9B1F1565EB00CC80DD /* SDLGetSystemCapabilityResponseSpec.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SDLGetSystemCapabilityResponseSpec.m; sourceTree = "<group>"; }; 5D0C29FA20D93D8C008B56CD /* SDLVideoStreamingState.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SDLVideoStreamingState.h; sourceTree = "<group>"; }; 5D0C29FB20D93D8C008B56CD /* SDLVideoStreamingState.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SDLVideoStreamingState.m; sourceTree = "<group>"; }; + 5D0C29FE20D9479B008B56CD /* SDLStreamingVideoLifecycleManager.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SDLStreamingVideoLifecycleManager.h; sourceTree = "<group>"; }; + 5D0C29FF20D9479B008B56CD /* SDLStreamingVideoLifecycleManager.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SDLStreamingVideoLifecycleManager.m; sourceTree = "<group>"; }; + 5D0C2A0220D947AB008B56CD /* SDLStreamingAudioLifecycleManager.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SDLStreamingAudioLifecycleManager.h; sourceTree = "<group>"; }; + 5D0C2A0320D947AB008B56CD /* SDLStreamingAudioLifecycleManager.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SDLStreamingAudioLifecycleManager.m; sourceTree = "<group>"; }; 5D1654551D3E754F00554D93 /* SDLLifecycleManagerSpec.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = SDLLifecycleManagerSpec.m; path = DevAPISpecs/SDLLifecycleManagerSpec.m; sourceTree = "<group>"; }; 5D1654581D3E7A1600554D93 /* SDLLifecycleManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDLLifecycleManager.h; sourceTree = "<group>"; }; 5D1654591D3E7A1600554D93 /* SDLLifecycleManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SDLLifecycleManager.m; sourceTree = "<group>"; }; @@ -2491,8 +2497,6 @@ DA6223BB1E7B088200878689 /* CVPixelBufferRef+SDLUtil.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "CVPixelBufferRef+SDLUtil.h"; sourceTree = "<group>"; }; DA6223BC1E7B088200878689 /* CVPixelBufferRef+SDLUtil.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "CVPixelBufferRef+SDLUtil.m"; sourceTree = "<group>"; }; DA661E2B1E553E7E001C1345 /* SDLStreamingMediaManagerSpec.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SDLStreamingMediaManagerSpec.m; sourceTree = "<group>"; }; - DA8966E91E56939F00413EAB /* SDLStreamingMediaLifecycleManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDLStreamingMediaLifecycleManager.h; sourceTree = "<group>"; }; - DA8966EA1E56939F00413EAB /* SDLStreamingMediaLifecycleManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SDLStreamingMediaLifecycleManager.m; sourceTree = "<group>"; }; DA8966EE1E5693E300413EAB /* SDLStreamingMediaLifecycleManagerSpec.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SDLStreamingMediaLifecycleManagerSpec.m; sourceTree = "<group>"; }; DA8966F11E56973700413EAB /* SDLStreamingMediaManagerConstants.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDLStreamingMediaManagerConstants.h; sourceTree = "<group>"; }; DA8966F31E56977C00413EAB /* SDLStreamingMediaManagerConstants.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SDLStreamingMediaManagerConstants.m; sourceTree = "<group>"; }; @@ -5023,8 +5027,10 @@ DA8966E81E56938C00413EAB /* Lifecycle */ = { isa = PBXGroup; children = ( - DA8966E91E56939F00413EAB /* SDLStreamingMediaLifecycleManager.h */, - DA8966EA1E56939F00413EAB /* SDLStreamingMediaLifecycleManager.m */, + 5D0C2A0220D947AB008B56CD /* SDLStreamingAudioLifecycleManager.h */, + 5D0C2A0320D947AB008B56CD /* SDLStreamingAudioLifecycleManager.m */, + 5D0C29FE20D9479B008B56CD /* SDLStreamingVideoLifecycleManager.h */, + 5D0C29FF20D9479B008B56CD /* SDLStreamingVideoLifecycleManager.m */, ); name = Lifecycle; sourceTree = "<group>"; @@ -5283,6 +5289,7 @@ 5D61FDE91A84238C00846EE7 /* SDLUnsubscribeButtonResponse.h in Headers */, 5D61FCD51A84238C00846EE7 /* SDLImageType.h in Headers */, 5D61FC2F1A84238C00846EE7 /* SDLAddCommandResponse.h in Headers */, + 5D0C2A0020D9479B008B56CD /* SDLStreamingVideoLifecycleManager.h in Headers */, 5D61FD631A84238C00846EE7 /* SDLResetGlobalProperties.h in Headers */, 5D61FDD71A84238C00846EE7 /* SDLTouchType.h in Headers */, 5D61FDD31A84238C00846EE7 /* SDLTouchEvent.h in Headers */, @@ -5372,6 +5379,7 @@ 5D61FDB91A84238C00846EE7 /* SDLSyncPDataResponse.h in Headers */, DAC572631D10C5020004288B /* SDLPinchGesture.h in Headers */, 5D61FC311A84238C00846EE7 /* SDLAddSubMenu.h in Headers */, + 5D0C2A0420D947AB008B56CD /* SDLStreamingAudioLifecycleManager.h in Headers */, 5D61FD171A84238C00846EE7 /* SDLOnPermissionsChange.h in Headers */, 5D4631081F21261A0092EFDC /* SDLControlFramePayloadRPCStartServiceAck.h in Headers */, 5D61FDD51A84238C00846EE7 /* SDLTouchEventCapabilities.h in Headers */, @@ -5450,7 +5458,6 @@ 5D61FD5B1A84238C00846EE7 /* SDLReadDIDResponse.h in Headers */, 5D61FDEF1A84238C00846EE7 /* SDLUpdateMode.h in Headers */, EED5CA001F4D18DC00F04000 /* SDLRAWH264Packetizer.h in Headers */, - DA8966EB1E56939F00413EAB /* SDLStreamingMediaLifecycleManager.h in Headers */, 5D293AFE1FE078A9000CBD7E /* SDLCarWindowViewController.h in Headers */, 5D61FDDB1A84238C00846EE7 /* SDLTriggerSource.h in Headers */, 5D61FD8F1A84238C00846EE7 /* SDLShow.h in Headers */, @@ -5776,6 +5783,7 @@ 1E4920B31F6A6463008F2CC3 /* SDLOnInteriorVehicleData.m in Sources */, 1E4920B21F6A6455008F2CC3 /* SDLGetInteriorVehicleDataResponse.m in Sources */, 1E4920B11F6A6443008F2CC3 /* SDLRadioState.m in Sources */, + 5D0C2A0120D9479B008B56CD /* SDLStreamingVideoLifecycleManager.m in Sources */, 5DA8A0EA1E955FE00039C50D /* SDLLogModel.m in Sources */, 5DA8A0E91E955F710039C50D /* SDLStreamingMediaManagerConstants.m in Sources */, 332A914F1CED9CC60043824C /* SDLAppInfo.m in Sources */, @@ -5803,6 +5811,7 @@ 5D61FD1A1A84238C00846EE7 /* SDLOnSyncPData.m in Sources */, 8B7B319F1F2F7CF700BDC38D /* SDLVideoStreamingProtocol.m in Sources */, 5D61FC461A84238C00846EE7 /* SDLAudioPassThruCapabilities.m in Sources */, + 5D0C2A0520D947AB008B56CD /* SDLStreamingAudioLifecycleManager.m in Sources */, 5D61FD301A84238C00846EE7 /* SDLPermissionStatus.m in Sources */, 5D61FDEE1A84238C00846EE7 /* SDLUnsubscribeVehicleDataResponse.m in Sources */, 8B7B319B1F2F7B5700BDC38D /* SDLVideoStreamingCodec.m in Sources */, @@ -6122,7 +6131,6 @@ 5D61FDC21A84238C00846EE7 /* SDLSystemRequestResponse.m in Sources */, 5D9FDA911F2A7D3400A495C8 /* bson_object.c in Sources */, 5D61FD001A84238C00846EE7 /* SDLOnAppInterfaceUnregistered.m in Sources */, - DA8966EC1E56939F00413EAB /* SDLStreamingMediaLifecycleManager.m in Sources */, DAC5726A1D10D5FC0004288B /* dispatch_timer.m in Sources */, 5D61FC6C1A84238C00846EE7 /* SDLCreateInteractionChoiceSet.m in Sources */, 5DCD7AF71FCCA8E400A0FC7F /* SDLScreenshotViewController.m in Sources */, diff --git a/SmartDeviceLink.podspec b/SmartDeviceLink.podspec index edda2f508..efbc2ae5f 100644 --- a/SmartDeviceLink.podspec +++ b/SmartDeviceLink.podspec @@ -327,6 +327,7 @@ ss.public_header_files = [ 'SmartDeviceLink/SDLVideoStreamingCodec.h', 'SmartDeviceLink/SDLVideoStreamingFormat.h', 'SmartDeviceLink/SDLVideoStreamingProtocol.h', +'SmartDeviceLink/SDLVideoStreamingState.h', 'SmartDeviceLink/SDLVoiceCommand.h', 'SmartDeviceLink/SDLVrCapabilities.h', 'SmartDeviceLink/SDLVrHelpItem.h', diff --git a/SmartDeviceLink/SDLCarWindow.h b/SmartDeviceLink/SDLCarWindow.h index 076f24b23..aaed77b35 100755 --- a/SmartDeviceLink/SDLCarWindow.h +++ b/SmartDeviceLink/SDLCarWindow.h @@ -8,7 +8,7 @@ #import <UIKit/UIKit.h> @class SDLStreamingMediaConfiguration; -@class SDLStreamingMediaLifecycleManager; +@class SDLStreamingVideoLifecycleManager; NS_ASSUME_NONNULL_BEGIN @@ -24,7 +24,7 @@ NS_ASSUME_NONNULL_BEGIN @param configuration The streaming media configuration @return An instance of this class */ -- (instancetype)initWithStreamManager:(SDLStreamingMediaLifecycleManager *)streamManager configuration:(SDLStreamingMediaConfiguration *)configuration; +- (instancetype)initWithStreamManager:(SDLStreamingVideoLifecycleManager *)streamManager configuration:(SDLStreamingMediaConfiguration *)configuration; /** * View Controller that will be streamed. diff --git a/SmartDeviceLink/SDLCarWindow.m b/SmartDeviceLink/SDLCarWindow.m index 448478fce..2d6c6f4b2 100755 --- a/SmartDeviceLink/SDLCarWindow.m +++ b/SmartDeviceLink/SDLCarWindow.m @@ -19,14 +19,14 @@ #import "SDLError.h" #import "SDLStateMachine.h" #import "SDLStreamingMediaConfiguration.h" -#import "SDLStreamingMediaLifecycleManager.h" +#import "SDLStreamingVideoLifecycleManager.h" #import "SDLStreamingMediaManagerConstants.h" NS_ASSUME_NONNULL_BEGIN @interface SDLCarWindow () -@property (weak, nonatomic, nullable) SDLStreamingMediaLifecycleManager *streamManager; +@property (weak, nonatomic, nullable) SDLStreamingVideoLifecycleManager *streamManager; @property (assign, nonatomic) SDLCarWindowRenderingType renderingType; @property (assign, nonatomic) BOOL drawsAfterScreenUpdates; @@ -41,7 +41,7 @@ NS_ASSUME_NONNULL_BEGIN @implementation SDLCarWindow -- (instancetype)initWithStreamManager:(SDLStreamingMediaLifecycleManager *)streamManager configuration:(nonnull SDLStreamingMediaConfiguration *)configuration { +- (instancetype)initWithStreamManager:(SDLStreamingVideoLifecycleManager *)streamManager configuration:(nonnull SDLStreamingMediaConfiguration *)configuration { self = [super init]; if (!self) { return nil; } diff --git a/SmartDeviceLink/SDLStreamingAudioLifecycleManager.h b/SmartDeviceLink/SDLStreamingAudioLifecycleManager.h new file mode 100644 index 000000000..defc18e17 --- /dev/null +++ b/SmartDeviceLink/SDLStreamingAudioLifecycleManager.h @@ -0,0 +1,94 @@ +// +// SDLStreamingAudioLifecycleManager.h +// SmartDeviceLink +// +// Created by Joel Fischer on 6/19/18. +// Copyright © 2018 smartdevicelink. All rights reserved. +// + +#import <Foundation/Foundation.h> + +#import "SDLHMILevel.h" +#import "SDLProtocolListener.h" +#import "SDLStreamingAudioManagerType.h" +#import "SDLStreamingMediaManagerConstants.h" + +@class SDLAudioStreamManager; +@class SDLProtocol; +@class SDLStateMachine; +@class SDLStreamingMediaConfiguration; + +@protocol SDLConnectionManagerType; + + +NS_ASSUME_NONNULL_BEGIN + +@interface SDLStreamingAudioLifecycleManager : NSObject <SDLProtocolListener, SDLStreamingAudioManagerType> + +@property (nonatomic, strong, readonly) SDLAudioStreamManager *audioManager; + +@property (strong, nonatomic, readonly) SDLStateMachine *audioStreamStateMachine; +@property (strong, nonatomic, readonly) SDLAudioStreamState *currentAudioStreamState; + +@property (strong, nonatomic, readonly) SDLStateMachine *appStateMachine; +@property (strong, nonatomic, readonly) SDLAppState *currentAppState; + +@property (copy, nonatomic, nullable) SDLHMILevel hmiLevel; + +/** + * Whether or not the audio session is connected. + */ +@property (assign, nonatomic, readonly, getter=isAudioConnected) BOOL audioConnected; + +/** + * Whether or not the audio session is encrypted. This may be different than the requestedEncryptionType. + */ +@property (assign, nonatomic, readonly, getter=isAudioEncrypted) BOOL audioEncrypted; + +/** + * Whether or not video streaming is supported + * + * @see SDLRegisterAppInterface SDLDisplayCapabilities + */ +@property (assign, nonatomic, readonly, getter=isStreamingSupported) BOOL streamingSupported; + +/** + * The requested encryption type when a session attempts to connect. This setting applies to both video and audio sessions. + * + * DEFAULT: SDLStreamingEncryptionFlagAuthenticateAndEncrypt + */ +@property (assign, nonatomic) SDLStreamingEncryptionFlag requestedEncryptionType; + +- (instancetype)init NS_UNAVAILABLE; + +/** + Create a new streaming media manager for navigation and VPM apps with a specified configuration + + @param connectionManager The pass-through for RPCs + @param configuration The configuration of this streaming media session + @return A new streaming manager + */ +- (instancetype)initWithConnectionManager:(id<SDLConnectionManagerType>)connectionManager configuration:(SDLStreamingMediaConfiguration *)configuration NS_DESIGNATED_INITIALIZER; + +/** + * Start the manager with a completion block that will be called when startup completes. This is used internally. To use an SDLStreamingMediaManager, you should use the manager found on `SDLManager`. + */ +- (void)startWithProtocol:(SDLProtocol *)protocol; + +/** + * Stop the manager. This method is used internally. + */ +- (void)stop; + +/** + * This method receives PCM audio data and will attempt to send that data across to the head unit for immediate playback + * + * @param audioData The data in PCM audio format, to be played + * + * @return Whether or not the data was successfully sent. + */ +- (BOOL)sendAudioData:(NSData *)audioData; + +@end + +NS_ASSUME_NONNULL_END diff --git a/SmartDeviceLink/SDLStreamingAudioLifecycleManager.m b/SmartDeviceLink/SDLStreamingAudioLifecycleManager.m new file mode 100644 index 000000000..4cc07967a --- /dev/null +++ b/SmartDeviceLink/SDLStreamingAudioLifecycleManager.m @@ -0,0 +1,345 @@ +// +// SDLStreamingAudioLifecycleManager.m +// SmartDeviceLink +// +// Created by Joel Fischer on 6/19/18. +// Copyright © 2018 smartdevicelink. All rights reserved. +// + +#import "SDLStreamingAudioLifecycleManager.h" + +#import "SDLAudioStreamManager.h" +#import "SDLConnectionManagerType.h" +#import "SDLControlFramePayloadAudioStartServiceAck.h" +#import "SDLControlFramePayloadConstants.h" +#import "SDLControlFramePayloadNak.h" +#import "SDLDisplayCapabilities.h" +#import "SDLGlobals.h" +#import "SDLHMICapabilities.h" +#import "SDLLogMacros.h" +#import "SDLOnHMIStatus.h" +#import "SDLProtocol.h" +#import "SDLProtocolMessage.h" +#import "SDLRegisterAppInterfaceResponse.h" +#import "SDLRPCNotificationNotification.h" +#import "SDLRPCResponseNotification.h" +#import "SDLStateMachine.h" +#import "SDLStreamingMediaConfiguration.h" +#import "SDLVehicleType.h" + + +NS_ASSUME_NONNULL_BEGIN + +@interface SDLStreamingAudioLifecycleManager() + +@property (strong, nonatomic, readwrite) SDLStateMachine *appStateMachine; +@property (strong, nonatomic, readwrite) SDLStateMachine *audioStreamStateMachine; +@property (assign, nonatomic, readonly, getter=isHmiStateAudioStreamCapable) BOOL hmiStateAudioStreamCapable; + +@property (weak, nonatomic) id<SDLConnectionManagerType> connectionManager; +@property (weak, nonatomic) SDLProtocol *protocol; + +@property (copy, nonatomic) NSArray<NSString *> *secureMakes; +@property (copy, nonatomic) NSString *connectedVehicleMake; + +@end + +@implementation SDLStreamingAudioLifecycleManager + +- (instancetype)initWithConnectionManager:(id<SDLConnectionManagerType>)connectionManager configuration:(SDLStreamingMediaConfiguration *)configuration { + self = [super init]; + if (!self) { + return nil; + } + + SDLLogV(@"Creating AudioStreamingLifecycleManager"); + + _connectionManager = connectionManager; + + _audioManager = [[SDLAudioStreamManager alloc] initWithManager:self]; + + _requestedEncryptionType = configuration.maximumDesiredEncryption; + + NSMutableArray<NSString *> *tempMakeArray = [NSMutableArray array]; + for (Class securityManagerClass in configuration.securityManagers) { + [tempMakeArray addObjectsFromArray:[securityManagerClass availableMakes].allObjects]; + } + _secureMakes = [tempMakeArray copy]; + + SDLAppState *initialState = SDLAppStateInactive; + switch ([[UIApplication sharedApplication] applicationState]) { + case UIApplicationStateActive: { + initialState = SDLAppStateActive; + } break; + case UIApplicationStateInactive: // fallthrough + case UIApplicationStateBackground: { + initialState = SDLAppStateInactive; + } break; + default: break; + } + + _appStateMachine = [[SDLStateMachine alloc] initWithTarget:self initialState:initialState states:[self.class sdl_appStateTransitionDictionary]]; + _audioStreamStateMachine = [[SDLStateMachine alloc] initWithTarget:self initialState:SDLAudioStreamStateStopped states:[self.class sdl_audioStreamingStateTransitionDictionary]]; + + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(sdl_didReceiveRegisterAppInterfaceResponse:) name:SDLDidReceiveRegisterAppInterfaceResponse object:nil]; + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(sdl_hmiLevelDidChange:) name:SDLDidChangeHMIStatusNotification object:nil]; + + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(sdl_appStateDidUpdate:) name:UIApplicationDidBecomeActiveNotification object:nil]; + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(sdl_appStateDidUpdate:) name:UIApplicationWillResignActiveNotification object:nil]; + + return self; +} + +- (void)startWithProtocol:(SDLProtocol *)protocol { + _protocol = protocol; + + if (![self.protocol.protocolDelegateTable containsObject:self]) { + [self.protocol.protocolDelegateTable addObject:self]; + } +} + +- (void)stop { + SDLLogD(@"Stopping manager"); + [self sdl_stopAudioSession]; + + self.hmiLevel = SDLHMILevelNone; + + [self.audioStreamStateMachine transitionToState:SDLAudioStreamStateStopped]; +} + +- (BOOL)sendAudioData:(NSData*)audioData { + if (!self.isAudioConnected) { + return NO; + } + + SDLLogV(@"Sending raw audio data"); + if (self.isAudioEncrypted) { + [self.protocol sendEncryptedRawData:audioData onService:SDLServiceTypeAudio]; + } else { + [self.protocol sendRawData:audioData withServiceType:SDLServiceTypeAudio]; + } + return YES; +} + +#pragma mark Getters + +- (BOOL)isAudioConnected { + return [self.audioStreamStateMachine isCurrentState:SDLAudioStreamStateReady]; +} + +- (SDLAppState *)currentAppState { + return self.appStateMachine.currentState; +} + +- (SDLAudioStreamState *)currentAudioStreamState { + return self.audioStreamStateMachine.currentState; +} + +#pragma mark - State Machines +#pragma mark App State ++ (NSDictionary<SDLState *, SDLAllowableStateTransitions *> *)sdl_appStateTransitionDictionary { + return @{ + // Will go from Inactive to Active if coming from a Phone Call. + // Will go from Inactive to IsRegainingActive if coming from Background. + SDLAppStateInactive : @[SDLAppStateActive], + SDLAppStateActive : @[SDLAppStateInactive] + }; +} + +- (void)sdl_appStateDidUpdate:(NSNotification*)notification { + if (notification.name == UIApplicationWillResignActiveNotification) { + [self.appStateMachine transitionToState:SDLAppStateInactive]; + } else if (notification.name == UIApplicationDidBecomeActiveNotification) { + [self.appStateMachine transitionToState:SDLAppStateActive]; + } +} + +- (void)didEnterStateAppInactive { + SDLLogD(@"App became inactive"); + [self sdl_stopAudioSession]; +} + +// Per Apple's guidelines: https://developer.apple.com/library/content/documentation/iPhone/Conceptual/iPhoneOSProgrammingGuide/StrategiesforHandlingAppStateTransitions/StrategiesforHandlingAppStateTransitions.html +// We should be waiting to start any OpenGL drawing until UIApplicationDidBecomeActive is called. +- (void)didEnterStateAppActive { + SDLLogD(@"App became active"); + [self sdl_startAudioSession]; +} + +#pragma mark Audio ++ (NSDictionary<SDLState *, SDLAllowableStateTransitions *> *)sdl_audioStreamingStateTransitionDictionary { + return @{ + SDLAudioStreamStateStopped : @[SDLAudioStreamStateStarting], + SDLAudioStreamStateStarting : @[SDLAudioStreamStateStopped, SDLAudioStreamStateReady], + SDLAudioStreamStateReady : @[SDLAudioStreamStateShuttingDown, SDLAudioStreamStateStopped], + SDLAudioStreamStateShuttingDown : @[SDLAudioStreamStateStopped] + }; +} + +- (void)didEnterStateAudioStreamStopped { + SDLLogD(@"Audio stream stopped"); + _audioEncrypted = NO; + + [[NSNotificationCenter defaultCenter] postNotificationName:SDLAudioStreamDidStopNotification object:nil]; +} + +- (void)didEnterStateAudioStreamStarting { + SDLLogD(@"Audio stream starting"); + if ((self.requestedEncryptionType != SDLStreamingEncryptionFlagNone) && ([self.secureMakes containsObject:self.connectedVehicleMake])) { + [self.protocol startSecureServiceWithType:SDLServiceTypeAudio payload:nil completionHandler:^(BOOL success, NSError * _Nonnull error) { + if (error) { + SDLLogE(@"TLS setup error: %@", error); + [self.audioStreamStateMachine transitionToState:SDLAudioStreamStateStopped]; + } + }]; + } else { + [self.protocol startServiceWithType:SDLServiceTypeAudio payload:nil]; + } +} + +- (void)didEnterStateAudioStreamReady { + SDLLogD(@"Audio stream ready"); + [[NSNotificationCenter defaultCenter] postNotificationName:SDLAudioStreamDidStartNotification object:nil]; +} + +- (void)didEnterStateAudioStreamShuttingDown { + SDLLogD(@"Audio stream shutting down"); + [self.protocol endServiceWithType:SDLServiceTypeAudio]; +} + +#pragma mark - SDLProtocolListener +#pragma mark Video / Audio Start Service ACK + +- (void)handleProtocolStartServiceACKMessage:(SDLProtocolMessage *)startServiceACK { + switch (startServiceACK.header.serviceType) { + case SDLServiceTypeAudio: { + [self sdl_handleAudioStartServiceAck:startServiceACK]; + } break; + default: break; + } +} + +- (void)sdl_handleAudioStartServiceAck:(SDLProtocolMessage *)audioStartServiceAck { + SDLLogD(@"Audio service started"); + _audioEncrypted = audioStartServiceAck.header.encrypted; + + SDLControlFramePayloadAudioStartServiceAck *audioAckPayload = [[SDLControlFramePayloadAudioStartServiceAck alloc] initWithData:audioStartServiceAck.payload]; + SDLLogV(@"ACK: %@", audioAckPayload); + + if (audioAckPayload.mtu != SDLControlFrameInt64NotFound) { + [[SDLGlobals sharedGlobals] setDynamicMTUSize:(NSUInteger)audioAckPayload.mtu forServiceType:SDLServiceTypeAudio]; + } + + [self.audioStreamStateMachine transitionToState:SDLAudioStreamStateReady]; +} + +#pragma mark Video / Audio Start Service NAK + +- (void)handleProtocolStartServiceNAKMessage:(SDLProtocolMessage *)startServiceNAK { + switch (startServiceNAK.header.serviceType) { + case SDLServiceTypeAudio: { + [self sdl_handleAudioStartServiceNak:startServiceNAK]; + } break; + default: break; + } +} + +- (void)sdl_handleAudioStartServiceNak:(SDLProtocolMessage *)audioStartServiceNak { + SDLLogW(@"Audio service failed to start due to NAK"); + [self sdl_transitionToStoppedState:SDLServiceTypeAudio]; +} + +#pragma mark Video / Audio End Service + +- (void)handleProtocolEndServiceACKMessage:(SDLProtocolMessage *)endServiceACK { + SDLLogD(@"%@ service ended", (endServiceACK.header.serviceType == SDLServiceTypeVideo ? @"Video" : @"Audio")); + [self sdl_transitionToStoppedState:endServiceACK.header.serviceType]; +} + +- (void)handleProtocolEndServiceNAKMessage:(SDLProtocolMessage *)endServiceNAK { + SDLLogW(@"%@ service ended with end service NAK", (endServiceNAK.header.serviceType == SDLServiceTypeVideo ? @"Video" : @"Audio")); + [self sdl_transitionToStoppedState:endServiceNAK.header.serviceType]; +} + +#pragma mark - SDL RPC Notification callbacks + +- (void)sdl_didReceiveRegisterAppInterfaceResponse:(SDLRPCResponseNotification *)notification { + NSAssert([notification.response isKindOfClass:[SDLRegisterAppInterfaceResponse class]], @"A notification was sent with an unanticipated object"); + if (![notification.response isKindOfClass:[SDLRegisterAppInterfaceResponse class]]) { + return; + } + + SDLLogD(@"Received Register App Interface"); + SDLRegisterAppInterfaceResponse* registerResponse = (SDLRegisterAppInterfaceResponse*)notification.response; + + SDLLogV(@"Determining whether streaming is supported"); + _streamingSupported = registerResponse.hmiCapabilities.videoStreaming ? registerResponse.hmiCapabilities.videoStreaming.boolValue : registerResponse.displayCapabilities.graphicSupported.boolValue; + + if (!self.isStreamingSupported) { + SDLLogE(@"Graphics are not supported on this head unit. We are are assuming screen size is also unavailable and exiting."); + return; + } + + self.connectedVehicleMake = registerResponse.vehicleType.make; +} + +- (void)sdl_hmiLevelDidChange:(SDLRPCNotificationNotification *)notification { + NSAssert([notification.notification isKindOfClass:[SDLOnHMIStatus class]], @"A notification was sent with an unanticipated object"); + if (![notification.notification isKindOfClass:[SDLOnHMIStatus class]]) { + return; + } + + SDLOnHMIStatus *hmiStatus = (SDLOnHMIStatus*)notification.notification; + SDLLogD(@"HMI level changed from level %@ to level %@", self.hmiLevel, hmiStatus.hmiLevel); + self.hmiLevel = hmiStatus.hmiLevel; + + if (self.isHmiStateAudioStreamCapable) { + [self sdl_startAudioSession]; + } else { + [self sdl_stopAudioSession]; + } +} + +#pragma mark - Streaming session helpers + +- (void)sdl_startAudioSession { + SDLLogV(@"Attempting to start audio session"); + if (!self.isStreamingSupported) { + return; + } + + if ([self.audioStreamStateMachine isCurrentState:SDLAudioStreamStateStopped] + && self.isHmiStateAudioStreamCapable) { + [self.audioStreamStateMachine transitionToState:SDLAudioStreamStateStarting]; + } +} + +- (void)sdl_stopAudioSession { + SDLLogV(@"Attempting to stop audio session"); + if (!self.isStreamingSupported) { + return; + } + + if (self.isAudioConnected) { + [self.audioStreamStateMachine transitionToState:SDLAudioStreamStateShuttingDown]; + } +} + +- (void)sdl_transitionToStoppedState:(SDLServiceType)serviceType { + switch (serviceType) { + case SDLServiceTypeAudio: + [self.audioStreamStateMachine transitionToState:SDLAudioStreamStateStopped]; + break; + default: break; + } +} + +#pragma mark Setters / Getters + +- (BOOL)isHmiStateAudioStreamCapable { + return [self.hmiLevel isEqualToEnum:SDLHMILevelLimited] || [self.hmiLevel isEqualToEnum:SDLHMILevelFull]; +} + +@end + +NS_ASSUME_NONNULL_END diff --git a/SmartDeviceLink/SDLStreamingMediaManager.m b/SmartDeviceLink/SDLStreamingMediaManager.m index ade1165e7..0d57cd6bd 100644 --- a/SmartDeviceLink/SDLStreamingMediaManager.m +++ b/SmartDeviceLink/SDLStreamingMediaManager.m @@ -12,7 +12,8 @@ #import "SDLConnectionManagerType.h" #import "SDLStreamingMediaConfiguration.h" #import "SDLStreamingMediaManagerDataSource.h" -#import "SDLStreamingMediaLifecycleManager.h" +#import "SDLStreamingAudioLifecycleManager.h" +#import "SDLStreamingVideoLifecycleManager.h" #import "SDLTouchManager.h" @@ -20,7 +21,8 @@ NS_ASSUME_NONNULL_BEGIN @interface SDLStreamingMediaManager () -@property (strong, nonatomic) SDLStreamingMediaLifecycleManager *lifecycleManager; +@property (strong, nonatomic) SDLStreamingAudioLifecycleManager *audioLifecycleManager; +@property (strong, nonatomic) SDLStreamingVideoLifecycleManager *videoLifecycleManager; @end @@ -36,101 +38,105 @@ NS_ASSUME_NONNULL_BEGIN return nil; } - _lifecycleManager = [[SDLStreamingMediaLifecycleManager alloc] initWithConnectionManager:connectionManager configuration:configuration]; + _audioLifecycleManager = [[SDLStreamingAudioLifecycleManager alloc] initWithConnectionManager:connectionManager configuration:configuration]; + _videoLifecycleManager = [[SDLStreamingVideoLifecycleManager alloc] initWithConnectionManager:connectionManager configuration:configuration]; return self; } - (void)startWithProtocol:(SDLProtocol *)protocol { - [self.lifecycleManager startWithProtocol:protocol]; + [self.audioLifecycleManager startWithProtocol:protocol]; + [self.videoLifecycleManager startWithProtocol:protocol]; } - (void)stop { - [self.lifecycleManager stop]; + [self.audioLifecycleManager stop]; + [self.videoLifecycleManager stop]; } - (BOOL)sendVideoData:(CVImageBufferRef)imageBuffer { - return [self.lifecycleManager sendVideoData:imageBuffer]; + return [self.videoLifecycleManager sendVideoData:imageBuffer]; } - (BOOL)sendVideoData:(CVImageBufferRef)imageBuffer presentationTimestamp:(CMTime)presentationTimestamp { - return [self.lifecycleManager sendVideoData:imageBuffer presentationTimestamp:presentationTimestamp]; + return [self.videoLifecycleManager sendVideoData:imageBuffer presentationTimestamp:presentationTimestamp]; } - (BOOL)sendAudioData:(NSData*)audioData { - return [self.lifecycleManager sendAudioData:audioData]; + return [self.audioLifecycleManager sendAudioData:audioData]; } #pragma mark - Getters - (SDLTouchManager *)touchManager { - return self.lifecycleManager.touchManager; + return self.videoLifecycleManager.touchManager; } - (SDLAudioStreamManager *)audioManager { - return self.lifecycleManager.audioManager; + return self.audioLifecycleManager.audioManager; } - (UIViewController *)rootViewController { - return self.lifecycleManager.rootViewController; + return self.videoLifecycleManager.rootViewController; } - (nullable id<SDLFocusableItemLocatorType>)focusableItemManager { - return self.lifecycleManager.focusableItemManager; + return self.videoLifecycleManager.focusableItemManager; } - (BOOL)isStreamingSupported { - return self.lifecycleManager.isStreamingSupported; + return self.videoLifecycleManager.isStreamingSupported; } - (BOOL)isAudioConnected { - return self.lifecycleManager.isAudioConnected; + return self.audioLifecycleManager.isAudioConnected; } - (BOOL)isVideoConnected { - return self.lifecycleManager.isVideoConnected; + return self.videoLifecycleManager.isVideoConnected; } - (BOOL)isAudioEncrypted { - return self.lifecycleManager.isAudioEncrypted; + return self.audioLifecycleManager.isAudioEncrypted; } - (BOOL)isVideoEncrypted { - return self.lifecycleManager.isVideoEncrypted; + return self.videoLifecycleManager.isVideoEncrypted; } - (BOOL)isVideoStreamingPaused { - return self.lifecycleManager.isVideoStreamingPaused; + return self.videoLifecycleManager.isVideoStreamingPaused; } - (CGSize)screenSize { - return self.lifecycleManager.screenSize; + return self.videoLifecycleManager.screenSize; } - (nullable SDLVideoStreamingFormat *)videoFormat { - return self.lifecycleManager.videoFormat; + return self.videoLifecycleManager.videoFormat; } - (NSArray<SDLVideoStreamingFormat *> *)supportedFormats { - return self.lifecycleManager.supportedFormats; + return self.videoLifecycleManager.supportedFormats; } - (CVPixelBufferPoolRef __nullable)pixelBufferPool { - return self.lifecycleManager.pixelBufferPool; + return self.videoLifecycleManager.pixelBufferPool; } - (SDLStreamingEncryptionFlag)requestedEncryptionType { - return self.lifecycleManager.requestedEncryptionType; + return self.videoLifecycleManager.requestedEncryptionType; } #pragma mark - Setters - (void)setRootViewController:(UIViewController *)rootViewController { - self.lifecycleManager.rootViewController = rootViewController; + self.videoLifecycleManager.rootViewController = rootViewController; } - (void)setRequestedEncryptionType:(SDLStreamingEncryptionFlag)requestedEncryptionType { - self.lifecycleManager.requestedEncryptionType = requestedEncryptionType; + self.videoLifecycleManager.requestedEncryptionType = requestedEncryptionType; + self.audioLifecycleManager.requestedEncryptionType = requestedEncryptionType; } @end diff --git a/SmartDeviceLink/SDLStreamingMediaManagerConstants.h b/SmartDeviceLink/SDLStreamingMediaManagerConstants.h index acb455ccd..c3e7b52f3 100644 --- a/SmartDeviceLink/SDLStreamingMediaManagerConstants.h +++ b/SmartDeviceLink/SDLStreamingMediaManagerConstants.h @@ -37,4 +37,21 @@ extern NSString *const SDLLockScreenManagerDidPresentLockScreenViewController; extern NSString *const SDLLockScreenManagerWillDismissLockScreenViewController; extern NSString *const SDLLockScreenManagerDidDismissLockScreenViewController; +typedef NSString SDLVideoStreamState; +extern SDLVideoStreamState *const SDLVideoStreamStateStopped; +extern SDLVideoStreamState *const SDLVideoStreamStateStarting; +extern SDLVideoStreamState *const SDLVideoStreamStateReady; +extern SDLVideoStreamState *const SDLVideoStreamStateSuspended; +extern SDLVideoStreamState *const SDLVideoStreamStateShuttingDown; + +typedef NSString SDLAudioStreamState; +extern SDLAudioStreamState *const SDLAudioStreamStateStopped; +extern SDLAudioStreamState *const SDLAudioStreamStateStarting; +extern SDLAudioStreamState *const SDLAudioStreamStateReady; +extern SDLAudioStreamState *const SDLAudioStreamStateShuttingDown; + +typedef NSString SDLAppState; +extern SDLAppState *const SDLAppStateInactive; +extern SDLAppState *const SDLAppStateActive; + NS_ASSUME_NONNULL_END diff --git a/SmartDeviceLink/SDLStreamingMediaManagerConstants.m b/SmartDeviceLink/SDLStreamingMediaManagerConstants.m index f80107e25..0a6e2a5ee 100644 --- a/SmartDeviceLink/SDLStreamingMediaManagerConstants.m +++ b/SmartDeviceLink/SDLStreamingMediaManagerConstants.m @@ -22,3 +22,17 @@ NSString *const SDLLockScreenManagerWillPresentLockScreenViewController = @"com. NSString *const SDLLockScreenManagerDidPresentLockScreenViewController = @"com.sdl.lockscreen.didPresent"; NSString *const SDLLockScreenManagerWillDismissLockScreenViewController = @"com.sdl.lockscreen.willDismiss"; NSString *const SDLLockScreenManagerDidDismissLockScreenViewController = @"com.sdl.lockscreen.didDismiss"; + +SDLVideoStreamState *const SDLVideoStreamStateStopped = @"VideoStreamStopped"; +SDLVideoStreamState *const SDLVideoStreamStateStarting = @"VideoStreamStarting"; +SDLVideoStreamState *const SDLVideoStreamStateReady = @"VideoStreamReady"; +SDLVideoStreamState *const SDLVideoStreamStateSuspended = @"VideoStreamSuspended"; +SDLVideoStreamState *const SDLVideoStreamStateShuttingDown = @"VideoStreamShuttingDown"; + +SDLAudioStreamState *const SDLAudioStreamStateStopped = @"AudioStreamStopped"; +SDLAudioStreamState *const SDLAudioStreamStateStarting = @"AudioStreamStarting"; +SDLAudioStreamState *const SDLAudioStreamStateReady = @"AudioStreamReady"; +SDLAudioStreamState *const SDLAudioStreamStateShuttingDown = @"AudioStreamShuttingDown"; + +SDLAppState *const SDLAppStateInactive = @"AppInactive"; +SDLAppState *const SDLAppStateActive = @"AppActive"; diff --git a/SmartDeviceLink/SDLStreamingMediaLifecycleManager.h b/SmartDeviceLink/SDLStreamingVideoLifecycleManager.h index 3fc753585..d0ce607e1 100644 --- a/SmartDeviceLink/SDLStreamingMediaLifecycleManager.h +++ b/SmartDeviceLink/SDLStreamingVideoLifecycleManager.h @@ -1,74 +1,47 @@ // -// SDLStreamingMediaLifecycleManager.h -// SmartDeviceLink-iOS +// SDLStreamingVideoLifecycleManager.h +// SmartDeviceLink // -// Created by Muller, Alexander (A.) on 2/16/17. -// Copyright © 2017 smartdevicelink. All rights reserved. +// Created by Joel Fischer on 6/19/18. +// Copyright © 2018 smartdevicelink. All rights reserved. // -#import <Foundation/Foundation.h> +#import <UIKit/UIKit.h> #import <VideoToolbox/VideoToolbox.h> -#import "SDLConnectionManagerType.h" #import "SDLHMILevel.h" #import "SDLProtocolListener.h" -#import "SDLStreamingAudioManagerType.h" #import "SDLStreamingMediaManagerConstants.h" +#import "SDLVideoStreamingFormat.h" -@class SDLAudioStreamManager; @class SDLCarWindow; @class SDLImageResolution; @class SDLProtocol; @class SDLStateMachine; @class SDLStreamingMediaConfiguration; @class SDLTouchManager; -@class SDLVideoStreamingFormat; +@protocol SDLConnectionManagerType; @protocol SDLFocusableItemLocatorType; @protocol SDLStreamingMediaManagerDataSource; -NS_ASSUME_NONNULL_BEGIN - -typedef NSString SDLAppState; -extern SDLAppState *const SDLAppStateInactive; -extern SDLAppState *const SDLAppStateActive; - -typedef NSString SDLVideoStreamState; -extern SDLVideoStreamState *const SDLVideoStreamStateStopped; -extern SDLVideoStreamState *const SDLVideoStreamStateStarting; -extern SDLVideoStreamState *const SDLVideoStreamStateReady; -extern SDLVideoStreamState *const SDLVideoStreamStateSuspended; -extern SDLVideoStreamState *const SDLVideoStreamStateShuttingDown; -typedef NSString SDLAudioStreamState; -extern SDLAudioStreamState *const SDLAudioStreamStateStopped; -extern SDLAudioStreamState *const SDLAudioStreamStateStarting; -extern SDLAudioStreamState *const SDLAudioStreamStateReady; -extern SDLAudioStreamState *const SDLAudioStreamStateShuttingDown; +NS_ASSUME_NONNULL_BEGIN -#pragma mark - Interface - -@interface SDLStreamingMediaLifecycleManager : NSObject <SDLProtocolListener, SDLStreamingAudioManagerType> +@interface SDLStreamingVideoLifecycleManager : NSObject <SDLProtocolListener> -@property (strong, nonatomic, readonly) SDLStateMachine *appStateMachine; @property (strong, nonatomic, readonly) SDLStateMachine *videoStreamStateMachine; -@property (strong, nonatomic, readonly) SDLStateMachine *audioStreamStateMachine; - -@property (strong, nonatomic, readonly) SDLAppState *currentAppState; -@property (strong, nonatomic, readonly) SDLAudioStreamState *currentAudioStreamState; @property (strong, nonatomic, readonly) SDLVideoStreamState *currentVideoStreamState; +@property (strong, nonatomic, readonly) SDLStateMachine *appStateMachine; +@property (strong, nonatomic, readonly) SDLAppState *currentAppState; @property (copy, nonatomic, nullable) SDLHMILevel hmiLevel; -@property (assign, nonatomic, readonly, getter=shouldRestartVideoStream) BOOL restartVideoStream __deprecated_msg("This is now unused as the stream doesn't restart anymore. The video stream suspends and resumes if the app changed the state during active video stream"); - /** * Touch Manager responsible for providing touch event notifications. */ @property (nonatomic, strong, readonly) SDLTouchManager *touchManager; - -@property (nonatomic, strong, readonly) SDLAudioStreamManager *audioManager; @property (nonatomic, strong) UIViewController *rootViewController; @property (strong, nonatomic, readonly, nullable) SDLCarWindow *carWindow; @@ -100,16 +73,6 @@ extern SDLAudioStreamState *const SDLAudioStreamStateShuttingDown; @property (assign, nonatomic, readonly, getter=isVideoEncrypted) BOOL videoEncrypted; /** - * Whether or not the audio session is connected. - */ -@property (assign, nonatomic, readonly, getter=isAudioConnected) BOOL audioConnected; - -/** - * Whether or not the audio session is encrypted. This may be different than the requestedEncryptionType. - */ -@property (assign, nonatomic, readonly, getter=isAudioEncrypted) BOOL audioEncrypted; - -/** * Whether or not the video stream is paused due to either the application being backgrounded, the HMI state being either NONE or BACKGROUND, or the video stream not being ready. */ @property (assign, nonatomic, readonly, getter=isVideoStreamingPaused) BOOL videoStreamingPaused; @@ -204,16 +167,6 @@ extern SDLAudioStreamState *const SDLAudioStreamStateShuttingDown; */ - (BOOL)sendVideoData:(CVImageBufferRef)imageBuffer presentationTimestamp:(CMTime)presentationTimestamp; -/** - * This method receives PCM audio data and will attempt to send that data across to the head unit for immediate playback - * - * @param audioData The data in PCM audio format, to be played - * - * @return Whether or not the data was successfully sent. - */ -- (BOOL)sendAudioData:(NSData *)audioData; - - @end NS_ASSUME_NONNULL_END diff --git a/SmartDeviceLink/SDLStreamingMediaLifecycleManager.m b/SmartDeviceLink/SDLStreamingVideoLifecycleManager.m index f8e4ebe4f..ac7903407 100644 --- a/SmartDeviceLink/SDLStreamingMediaLifecycleManager.m +++ b/SmartDeviceLink/SDLStreamingVideoLifecycleManager.m @@ -1,31 +1,31 @@ // -// SDLStreamingMediaLifecycleManager.m -// SmartDeviceLink-iOS +// SDLStreamingVideoLifecycleManager.m +// SmartDeviceLink // -// Created by Muller, Alexander (A.) on 2/16/17. -// Copyright © 2017 smartdevicelink. All rights reserved. +// Created by Joel Fischer on 6/19/18. +// Copyright © 2018 smartdevicelink. All rights reserved. // -#import "SDLStreamingMediaLifecycleManager.h" +#import "SDLStreamingVideoLifecycleManager.h" -#import "SDLAudioStreamManager.h" +#import "CVPixelBufferRef+SDLUtil.h" #import "SDLCarWindow.h" -#import "SDLControlFramePayloadAudioStartServiceAck.h" +#import "SDLConnectionManagerType.h" #import "SDLControlFramePayloadConstants.h" #import "SDLControlFramePayloadNak.h" #import "SDLControlFramePayloadVideoStartService.h" #import "SDLControlFramePayloadVideoStartServiceAck.h" #import "SDLDisplayCapabilities.h" +#import "SDLFocusableItemLocator.h" #import "SDLGenericResponse.h" #import "SDLGetSystemCapability.h" #import "SDLGetSystemCapabilityResponse.h" #import "SDLGlobals.h" -#import "SDLFocusableItemLocator.h" #import "SDLH264VideoEncoder.h" #import "SDLHMICapabilities.h" +#import "SDLHMILevel.h" #import "SDLImageResolution.h" #import "SDLLogMacros.h" -#import "SDLNotificationConstants.h" #import "SDLOnHMIStatus.h" #import "SDLProtocol.h" #import "SDLProtocolMessage.h" @@ -39,44 +39,26 @@ #import "SDLSystemCapability.h" #import "SDLTouchManager.h" #import "SDLVehicleType.h" +#import "SDLVideoEncoderDelegate.h" #import "SDLVideoStreamingCapability.h" -#import "SDLVideoStreamingCodec.h" -#import "SDLVideoStreamingFormat.h" -#import "SDLVideoStreamingProtocol.h" - -#import "CVPixelBufferRef+SDLUtil.h" +static NSUInteger const FramesToSendOnBackground = 30; NS_ASSUME_NONNULL_BEGIN -SDLAppState *const SDLAppStateInactive = @"AppInactive"; -SDLAppState *const SDLAppStateActive = @"AppActive"; - -SDLVideoStreamState *const SDLVideoStreamStateStopped = @"VideoStreamStopped"; -SDLVideoStreamState *const SDLVideoStreamStateStarting = @"VideoStreamStarting"; -SDLVideoStreamState *const SDLVideoStreamStateReady = @"VideoStreamReady"; -SDLVideoStreamState *const SDLVideoStreamStateSuspended = @"VideoStreamSuspended"; -SDLVideoStreamState *const SDLVideoStreamStateShuttingDown = @"VideoStreamShuttingDown"; - -SDLAudioStreamState *const SDLAudioStreamStateStopped = @"AudioStreamStopped"; -SDLAudioStreamState *const SDLAudioStreamStateStarting = @"AudioStreamStarting"; -SDLAudioStreamState *const SDLAudioStreamStateReady = @"AudioStreamReady"; -SDLAudioStreamState *const SDLAudioStreamStateShuttingDown = @"AudioStreamShuttingDown"; - -static NSUInteger const FramesToSendOnBackground = 30; - typedef void(^SDLVideoCapabilityResponseHandler)(SDLVideoStreamingCapability *_Nullable capability); - -@interface SDLStreamingMediaLifecycleManager () <SDLVideoEncoderDelegate> +@interface SDLStreamingVideoLifecycleManager() <SDLVideoEncoderDelegate> @property (weak, nonatomic) id<SDLConnectionManagerType> connectionManager; @property (weak, nonatomic) SDLProtocol *protocol; @property (assign, nonatomic, readonly, getter=isAppStateVideoStreamCapable) BOOL appStateVideoStreamCapable; -@property (assign, nonatomic, readonly, getter=isHmiStateAudioStreamCapable) BOOL hmiStateAudioStreamCapable; @property (assign, nonatomic, readonly, getter=isHmiStateVideoStreamCapable) BOOL hmiStateVideoStreamCapable; +@property (strong, nonatomic, readwrite) SDLStateMachine *videoStreamStateMachine; +@property (strong, nonatomic, readwrite) SDLStateMachine *appStateMachine; + @property (strong, nonatomic, readwrite, nullable) SDLVideoStreamingFormat *videoFormat; @property (strong, nonatomic, nullable) SDLH264VideoEncoder *videoEncoder; @@ -84,10 +66,6 @@ typedef void(^SDLVideoCapabilityResponseHandler)(SDLVideoStreamingCapability *_N @property (copy, nonatomic) NSArray<NSString *> *secureMakes; @property (copy, nonatomic) NSString *connectedVehicleMake; -@property (strong, nonatomic, readwrite) SDLStateMachine *appStateMachine; -@property (strong, nonatomic, readwrite) SDLStateMachine *videoStreamStateMachine; -@property (strong, nonatomic, readwrite) SDLStateMachine *audioStreamStateMachine; - @property (assign, nonatomic) CV_NULLABLE CVPixelBufferRef backgroundingPixelBuffer; @property (strong, nonatomic, nullable) CADisplayLink *displayLink; @@ -97,11 +75,7 @@ typedef void(^SDLVideoCapabilityResponseHandler)(SDLVideoStreamingCapability *_N @end - -@implementation SDLStreamingMediaLifecycleManager - -#pragma mark - Public -#pragma mark Lifecycle +@implementation SDLStreamingVideoLifecycleManager - (instancetype)initWithConnectionManager:(id<SDLConnectionManagerType>)connectionManager configuration:(SDLStreamingMediaConfiguration *)configuration { self = [super init]; @@ -127,7 +101,6 @@ typedef void(^SDLVideoCapabilityResponseHandler)(SDLVideoStreamingCapability *_N } _touchManager = [[SDLTouchManager alloc] initWithHitTester:(id)_focusableItemManager]; - _audioManager = [[SDLAudioStreamManager alloc] initWithManager:self]; _requestedEncryptionType = configuration.maximumDesiredEncryption; _dataSource = configuration.dataSource; @@ -157,7 +130,6 @@ typedef void(^SDLVideoCapabilityResponseHandler)(SDLVideoStreamingCapability *_N _appStateMachine = [[SDLStateMachine alloc] initWithTarget:self initialState:initialState states:[self.class sdl_appStateTransitionDictionary]]; _videoStreamStateMachine = [[SDLStateMachine alloc] initWithTarget:self initialState:SDLVideoStreamStateStopped states:[self.class sdl_videoStreamStateTransitionDictionary]]; - _audioStreamStateMachine = [[SDLStateMachine alloc] initWithTarget:self initialState:SDLAudioStreamStateStopped states:[self.class sdl_audioStreamingStateTransitionDictionary]]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(sdl_didReceiveRegisterAppInterfaceResponse:) name:SDLDidReceiveRegisterAppInterfaceResponse object:nil]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(sdl_hmiLevelDidChange:) name:SDLDidChangeHMIStatusNotification object:nil]; @@ -180,12 +152,10 @@ typedef void(^SDLVideoCapabilityResponseHandler)(SDLVideoStreamingCapability *_N - (void)stop { SDLLogD(@"Stopping manager"); - [self sdl_stopAudioSession]; [self sdl_stopVideoSession]; self.hmiLevel = SDLHMILevelNone; - [self.audioStreamStateMachine transitionToState:SDLAudioStreamStateStopped]; [self.videoStreamStateMachine transitionToState:SDLVideoStreamStateStopped]; } @@ -221,24 +191,7 @@ typedef void(^SDLVideoCapabilityResponseHandler)(SDLVideoStreamingCapability *_N return [self.videoEncoder encodeFrame:imageBuffer presentationTimestamp:presentationTimestamp]; } -- (BOOL)sendAudioData:(NSData*)audioData { - if (!self.isAudioConnected) { - return NO; - } - - SDLLogV(@"Sending raw audio data"); - if (self.isAudioEncrypted) { - [self.protocol sendEncryptedRawData:audioData onService:SDLServiceTypeAudio]; - } else { - [self.protocol sendRawData:audioData withServiceType:SDLServiceTypeAudio]; - } - return YES; -} - #pragma mark Getters -- (BOOL)isAudioConnected { - return [self.audioStreamStateMachine isCurrentState:SDLAudioStreamStateReady]; -} - (BOOL)isVideoConnected { return [self.videoStreamStateMachine isCurrentState:SDLVideoStreamStateReady]; @@ -256,10 +209,6 @@ typedef void(^SDLVideoCapabilityResponseHandler)(SDLVideoStreamingCapability *_N return self.appStateMachine.currentState; } -- (SDLAudioStreamState *)currentAudioStreamState { - return self.audioStreamStateMachine.currentState; -} - - (SDLVideoStreamState *)currentVideoStreamState { return self.videoStreamStateMachine.currentState; } @@ -295,8 +244,6 @@ typedef void(^SDLVideoCapabilityResponseHandler)(SDLVideoStreamingCapability *_N } else { [self sdl_stopVideoSession]; } - - [self sdl_stopAudioSession]; } // Per Apple's guidelines: https://developer.apple.com/library/content/documentation/iPhone/Conceptual/iPhoneOSProgrammingGuide/StrategiesforHandlingAppStateTransitions/StrategiesforHandlingAppStateTransitions.html @@ -310,8 +257,6 @@ typedef void(^SDLVideoCapabilityResponseHandler)(SDLVideoStreamingCapability *_N } else { [self sdl_startVideoSession]; } - - [self sdl_startAudioSession]; } #pragma mark Video Streaming @@ -395,7 +340,7 @@ typedef void(^SDLVideoCapabilityResponseHandler)(SDLVideoStreamingCapability *_N [self.videoEncoder stop]; self.videoEncoder = nil; } - + if (self.videoEncoder == nil) { NSError* error = nil; NSAssert(self.videoFormat != nil, @"No video format is known, but it must be if we got a protocol start service response"); @@ -444,7 +389,7 @@ typedef void(^SDLVideoCapabilityResponseHandler)(SDLVideoStreamingCapability *_N - (void)didEnterStateVideoStreamSuspended { SDLLogD(@"Video stream suspended"); - + [[NSNotificationCenter defaultCenter] postNotificationName:SDLVideoStreamSuspendedNotification object:nil]; } @@ -453,55 +398,11 @@ typedef void(^SDLVideoCapabilityResponseHandler)(SDLVideoStreamingCapability *_N [self.protocol endServiceWithType:SDLServiceTypeVideo]; } -#pragma mark Audio -+ (NSDictionary<SDLState *, SDLAllowableStateTransitions *> *)sdl_audioStreamingStateTransitionDictionary { - return @{ - SDLAudioStreamStateStopped : @[SDLAudioStreamStateStarting], - SDLAudioStreamStateStarting : @[SDLAudioStreamStateStopped, SDLAudioStreamStateReady], - SDLAudioStreamStateReady : @[SDLAudioStreamStateShuttingDown, SDLAudioStreamStateStopped], - SDLAudioStreamStateShuttingDown : @[SDLAudioStreamStateStopped] - }; -} - -- (void)didEnterStateAudioStreamStopped { - SDLLogD(@"Audio stream stopped"); - _audioEncrypted = NO; - - [[NSNotificationCenter defaultCenter] postNotificationName:SDLAudioStreamDidStopNotification object:nil]; -} - -- (void)didEnterStateAudioStreamStarting { - SDLLogD(@"Audio stream starting"); - if ((self.requestedEncryptionType != SDLStreamingEncryptionFlagNone) && ([self.secureMakes containsObject:self.connectedVehicleMake])) { - [self.protocol startSecureServiceWithType:SDLServiceTypeAudio payload:nil completionHandler:^(BOOL success, NSError * _Nonnull error) { - if (error) { - SDLLogE(@"TLS setup error: %@", error); - [self.audioStreamStateMachine transitionToState:SDLAudioStreamStateStopped]; - } - }]; - } else { - [self.protocol startServiceWithType:SDLServiceTypeAudio payload:nil]; - } -} - -- (void)didEnterStateAudioStreamReady { - SDLLogD(@"Audio stream ready"); - [[NSNotificationCenter defaultCenter] postNotificationName:SDLAudioStreamDidStartNotification object:nil]; -} - -- (void)didEnterStateAudioStreamShuttingDown { - SDLLogD(@"Audio stream shutting down"); - [self.protocol endServiceWithType:SDLServiceTypeAudio]; -} - #pragma mark - SDLProtocolListener #pragma mark Video / Audio Start Service ACK - (void)handleProtocolStartServiceACKMessage:(SDLProtocolMessage *)startServiceACK { switch (startServiceACK.header.serviceType) { - case SDLServiceTypeAudio: { - [self sdl_handleAudioStartServiceAck:startServiceACK]; - } break; case SDLServiceTypeVideo: { [self sdl_handleVideoStartServiceAck:startServiceACK]; } break; @@ -509,20 +410,6 @@ typedef void(^SDLVideoCapabilityResponseHandler)(SDLVideoStreamingCapability *_N } } -- (void)sdl_handleAudioStartServiceAck:(SDLProtocolMessage *)audioStartServiceAck { - SDLLogD(@"Audio service started"); - _audioEncrypted = audioStartServiceAck.header.encrypted; - - SDLControlFramePayloadAudioStartServiceAck *audioAckPayload = [[SDLControlFramePayloadAudioStartServiceAck alloc] initWithData:audioStartServiceAck.payload]; - SDLLogV(@"ACK: %@", audioAckPayload); - - if (audioAckPayload.mtu != SDLControlFrameInt64NotFound) { - [[SDLGlobals sharedGlobals] setDynamicMTUSize:(NSUInteger)audioAckPayload.mtu forServiceType:SDLServiceTypeAudio]; - } - - [self.audioStreamStateMachine transitionToState:SDLAudioStreamStateReady]; -} - - (void)sdl_handleVideoStartServiceAck:(SDLProtocolMessage *)videoStartServiceAck { SDLLogD(@"Video service started"); _videoEncrypted = videoStartServiceAck.header.encrypted; @@ -559,9 +446,6 @@ typedef void(^SDLVideoCapabilityResponseHandler)(SDLVideoStreamingCapability *_N - (void)handleProtocolStartServiceNAKMessage:(SDLProtocolMessage *)startServiceNAK { switch (startServiceNAK.header.serviceType) { - case SDLServiceTypeAudio: { - [self sdl_handleAudioStartServiceNak:startServiceNAK]; - } break; case SDLServiceTypeVideo: { [self sdl_handleVideoStartServiceNak:startServiceNAK]; } @@ -594,11 +478,6 @@ typedef void(^SDLVideoCapabilityResponseHandler)(SDLVideoStreamingCapability *_N [self sdl_sendVideoStartService]; } -- (void)sdl_handleAudioStartServiceNak:(SDLProtocolMessage *)audioStartServiceNak { - SDLLogW(@"Audio service failed to start due to NAK"); - [self sdl_transitionToStoppedState:SDLServiceTypeAudio]; -} - #pragma mark Video / Audio End Service - (void)handleProtocolEndServiceACKMessage:(SDLProtocolMessage *)endServiceACK { @@ -611,22 +490,6 @@ typedef void(^SDLVideoCapabilityResponseHandler)(SDLVideoStreamingCapability *_N [self sdl_transitionToStoppedState:endServiceNAK.header.serviceType]; } -#pragma mark - SDLVideoEncoderDelegate - -- (void)videoEncoder:(SDLH264VideoEncoder *)encoder hasEncodedFrame:(NSData *)encodedVideo { - SDLLogV(@"Video encoder encoded frame, sending data"); - // Do we care about app state here? I don't think so… - BOOL capableVideoStreamState = [self.videoStreamStateMachine isCurrentState:SDLVideoStreamStateReady]; - - if (self.isHmiStateVideoStreamCapable && capableVideoStreamState) { - if (self.isVideoEncrypted) { - [self.protocol sendEncryptedRawData:encodedVideo onService:SDLServiceTypeVideo]; - } else { - [self.protocol sendRawData:encodedVideo withServiceType:SDLServiceTypeVideo]; - } - } -} - #pragma mark - SDL RPC Notification callbacks - (void)sdl_didReceiveRegisterAppInterfaceResponse:(SDLRPCResponseNotification *)notification { @@ -674,15 +537,24 @@ typedef void(^SDLVideoCapabilityResponseHandler)(SDLVideoStreamingCapability *_N } else { [self sdl_stopVideoSession]; } +} - if (self.isHmiStateAudioStreamCapable) { - [self sdl_startAudioSession]; - } else { - [self sdl_stopAudioSession]; +#pragma mark - SDLVideoEncoderDelegate + +- (void)videoEncoder:(SDLH264VideoEncoder *)encoder hasEncodedFrame:(NSData *)encodedVideo { + SDLLogV(@"Video encoder encoded frame, sending data"); + // Do we care about app state here? I don't think so… + BOOL capableVideoStreamState = [self.videoStreamStateMachine isCurrentState:SDLVideoStreamStateReady]; + + if (self.isHmiStateVideoStreamCapable && capableVideoStreamState) { + if (self.isVideoEncrypted) { + [self.protocol sendEncryptedRawData:encodedVideo onService:SDLServiceTypeVideo]; + } else { + [self.protocol sendRawData:encodedVideo withServiceType:SDLServiceTypeVideo]; + } } } - #pragma mark - Streaming session helpers - (void)sdl_startVideoSession { @@ -708,18 +580,6 @@ typedef void(^SDLVideoCapabilityResponseHandler)(SDLVideoStreamingCapability *_N } } -- (void)sdl_startAudioSession { - SDLLogV(@"Attempting to start audio session"); - if (!self.isStreamingSupported) { - return; - } - - if ([self.audioStreamStateMachine isCurrentState:SDLAudioStreamStateStopped] - && self.isHmiStateAudioStreamCapable) { - [self.audioStreamStateMachine transitionToState:SDLAudioStreamStateStarting]; - } -} - - (void)sdl_stopVideoSession { SDLLogV(@"Attempting to stop video session"); if (!self.isStreamingSupported) { @@ -731,22 +591,8 @@ typedef void(^SDLVideoCapabilityResponseHandler)(SDLVideoStreamingCapability *_N } } -- (void)sdl_stopAudioSession { - SDLLogV(@"Attempting to stop audio session"); - if (!self.isStreamingSupported) { - return; - } - - if (self.isAudioConnected) { - [self.audioStreamStateMachine transitionToState:SDLAudioStreamStateShuttingDown]; - } -} - - (void)sdl_transitionToStoppedState:(SDLServiceType)serviceType { switch (serviceType) { - case SDLServiceTypeAudio: - [self.audioStreamStateMachine transitionToState:SDLAudioStreamStateStopped]; - break; case SDLServiceTypeVideo: [self.videoStreamStateMachine transitionToState:SDLVideoStreamStateStopped]; break; @@ -849,7 +695,6 @@ typedef void(^SDLVideoCapabilityResponseHandler)(SDLVideoStreamingCapability *_N } } - #pragma mark Setters / Getters - (void)setRootViewController:(UIViewController *)rootViewController { @@ -866,10 +711,6 @@ typedef void(^SDLVideoCapabilityResponseHandler)(SDLVideoStreamingCapability *_N return [self.appStateMachine isCurrentState:SDLAppStateActive]; } -- (BOOL)isHmiStateAudioStreamCapable { - return [self.hmiLevel isEqualToEnum:SDLHMILevelLimited] || [self.hmiLevel isEqualToEnum:SDLHMILevelFull]; -} - - (BOOL)isHmiStateVideoStreamCapable { return [self.hmiLevel isEqualToEnum:SDLHMILevelLimited] || [self.hmiLevel isEqualToEnum:SDLHMILevelFull]; } @@ -877,7 +718,7 @@ typedef void(^SDLVideoCapabilityResponseHandler)(SDLVideoStreamingCapability *_N - (NSArray<SDLVideoStreamingFormat *> *)supportedFormats { SDLVideoStreamingFormat *h264raw = [[SDLVideoStreamingFormat alloc] initWithCodec:SDLVideoStreamingCodecH264 protocol:SDLVideoStreamingProtocolRAW]; SDLVideoStreamingFormat *h264rtp = [[SDLVideoStreamingFormat alloc] initWithCodec:SDLVideoStreamingCodecH264 protocol:SDLVideoStreamingProtocolRTP]; - + return @[h264raw, h264rtp]; } diff --git a/SmartDeviceLink/SmartDeviceLink.h b/SmartDeviceLink/SmartDeviceLink.h index 6a9fc4da7..8f19b93fa 100644 --- a/SmartDeviceLink/SmartDeviceLink.h +++ b/SmartDeviceLink/SmartDeviceLink.h @@ -283,6 +283,7 @@ FOUNDATION_EXPORT const unsigned char SmartDeviceLinkVersionString[]; #import "SDLVentilationMode.h" #import "SDLVideoStreamingCodec.h" #import "SDLVideoStreamingProtocol.h" +#import "SDLVideoStreamingState.h" #import "SDLVrCapabilities.h" #import "SDLWarningLightStatus.h" #import "SDLWayPointType.h" |