diff options
author | Muller, Alexander (A.) <amulle19@ford.com> | 2016-05-25 18:28:03 -0700 |
---|---|---|
committer | Muller, Alexander (A.) <amulle19@ford.com> | 2016-05-25 18:28:03 -0700 |
commit | aac227ab58b24c4296e24dea5ddf782985a021e6 (patch) | |
tree | 35f4bc55048545b62a4900989932dfc4803167fb | |
parent | c444bce2c2c39d504567b18c713d244f4a2b8dc5 (diff) | |
download | sdl_ios-aac227ab58b24c4296e24dea5ddf782985a021e6.tar.gz |
Added support for allowing developers to set custom video encoder settings.
-rw-r--r-- | SmartDeviceLink-iOS/SmartDeviceLink/SDLStreamingMediaManager.h | 12 | ||||
-rw-r--r-- | SmartDeviceLink-iOS/SmartDeviceLink/SDLStreamingMediaManager.m | 117 |
2 files changed, 67 insertions, 62 deletions
diff --git a/SmartDeviceLink-iOS/SmartDeviceLink/SDLStreamingMediaManager.h b/SmartDeviceLink-iOS/SmartDeviceLink/SDLStreamingMediaManager.h index 05a855e13..2e3a6dbb1 100644 --- a/SmartDeviceLink-iOS/SmartDeviceLink/SDLStreamingMediaManager.h +++ b/SmartDeviceLink-iOS/SmartDeviceLink/SDLStreamingMediaManager.h @@ -82,9 +82,21 @@ typedef void (^SDLStreamingStartBlock)(BOOL success, NSError *__nullable error); */ - (BOOL)sendAudioData:(NSData *)pcmAudioData; +/** + * The settings used in a VTCompressionSessionRef encoder. These will be verified when the video stream is started. Acceptable properties for this are located in VTCompressionProperties. If set to nil, the defaultVideoEncoderSettings will be used. + * + * @warning Video streaming must not be connected to update the encoder properties. If it is running, issue a stopVideoSession before updating. + */ +@property (strong, nonatomic, nullable) NSDictionary* videoEncoderSettings; + @property (assign, nonatomic, readonly) BOOL videoSessionConnected; @property (assign, nonatomic, readonly) BOOL audioSessionConnected; +/** + * Provides default video encoder settings used. + */ +@property (strong, nonatomic, readonly) NSDictionary* defaultVideoEncoderSettings; + @end diff --git a/SmartDeviceLink-iOS/SmartDeviceLink/SDLStreamingMediaManager.m b/SmartDeviceLink-iOS/SmartDeviceLink/SDLStreamingMediaManager.m index 9b7f5a8ac..74a9f634d 100644 --- a/SmartDeviceLink-iOS/SmartDeviceLink/SDLStreamingMediaManager.m +++ b/SmartDeviceLink-iOS/SmartDeviceLink/SDLStreamingMediaManager.m @@ -127,6 +127,30 @@ NS_ASSUME_NONNULL_BEGIN return YES; } +#pragma mark - Update video encoder + +- (void)setVideoEncoderSettings:( NSDictionary * _Nullable)videoEncoderSettings { + if (self.videoSessionConnected) { + @throw [NSException exceptionWithName:SDLErrorDomainStreamingMediaVideo reason:@"Cannot update video encoder settings while video session is connected." userInfo:nil]; + return; + } + + _videoEncoderSettings = videoEncoderSettings; +} + +- (NSDictionary*)defaultVideoEncoderSettings { + static NSDictionary* defaultVideoEncoderSettings = nil; + if (defaultVideoEncoderSettings == nil) { + defaultVideoEncoderSettings = @{ + (__bridge NSString*)kVTCompressionPropertyKey_AverageBitRate : @(5000 * 1024), + (__bridge NSString*)kVTCompressionPropertyKey_ProfileLevel : (__bridge NSString*)kVTProfileLevel_H264_Baseline_AutoLevel, + (__bridge NSString*)kVTCompressionPropertyKey_RealTime : @(YES), + (__bridge NSString*)kVTCompressionPropertyKey_MaxKeyFrameInterval : @(50) + }; + } + return defaultVideoEncoderSettings; +} + #pragma mark - SDLProtocolListener Methods @@ -229,83 +253,52 @@ void sdl_videoEncoderOutputCallback(void *outputCallbackRefCon, void *sourceFram if (status != noErr) { // TODO: Log the error - if (*error != nil) { + if (*error == nil) { *error = [NSError errorWithDomain:SDLErrorDomainStreamingMediaVideo code:SDLStreamingVideoErrorConfigurationCompressionSessionCreationFailure userInfo:@{ @"OSStatus" : @(status) }]; } return NO; } - - // Set the bitrate of our video compression - int bitRate = 5000; - CFNumberRef bitRateNumRef = CFNumberCreate(NULL, kCFNumberSInt32Type, &bitRate); - if (bitRateNumRef == NULL) { - // TODO: Log & end session - if (*error != nil) { - *error = [NSError errorWithDomain:SDLErrorDomainStreamingMediaVideo code:SDLStreamingVideoErrorConfigurationAllocationFailure userInfo:nil]; - } - - return NO; + + if (self.videoEncoderSettings == nil) { + self.videoEncoderSettings = self.defaultVideoEncoderSettings; } - status = VTSessionSetProperty(self.compressionSession, kVTCompressionPropertyKey_AverageBitRate, bitRateNumRef); - - // Release our bitrate number - CFRelease(bitRateNumRef); - bitRateNumRef = NULL; - + // Validate that the video encoder properties are valid. + CFDictionaryRef supportedProperties; + status = VTSessionCopySupportedPropertyDictionary(self.compressionSession, &supportedProperties); if (status != noErr) { - // TODO: Log & End session - if (*error != nil) { + if (*error == nil) { *error = [NSError errorWithDomain:SDLErrorDomainStreamingMediaVideo code:SDLStreamingVideoErrorConfigurationCompressionSessionSetPropertyFailure userInfo:@{ @"OSStatus" : @(status) }]; } - + return NO; } - - // Set the profile level of the video stream - status = VTSessionSetProperty(self.compressionSession, kVTCompressionPropertyKey_ProfileLevel, kVTProfileLevel_H264_Baseline_AutoLevel); - if (status != noErr) { - if (*error != nil) { - *error = [NSError errorWithDomain:SDLErrorDomainStreamingMediaVideo code:SDLStreamingVideoErrorConfigurationCompressionSessionSetPropertyFailure userInfo:@{ @"OSStatus" : @(status) }]; - } - - return NO; - } - - // Set the session to compress in real time - status = VTSessionSetProperty(self.compressionSession, kVTCompressionPropertyKey_RealTime, kCFBooleanTrue); - if (status != noErr) { - if (*error != nil) { - *error = [NSError errorWithDomain:SDLErrorDomainStreamingMediaVideo code:SDLStreamingVideoErrorConfigurationCompressionSessionSetPropertyFailure userInfo:@{ @"OSStatus" : @(status) }]; - } - - return NO; - } - - // Set the key-frame interval - // TODO: This may be unnecessary, can the encoder do a better job than us? - int interval = 50; - CFNumberRef intervalNumRef = CFNumberCreate(NULL, kCFNumberSInt32Type, &interval); - if (intervalNumRef == NULL) { - if (*error != nil) { - *error = [NSError errorWithDomain:SDLErrorDomainStreamingMediaVideo code:SDLStreamingVideoErrorConfigurationAllocationFailure userInfo:nil]; + + for (NSString* key in self.videoEncoderSettings.allKeys) { + if (CFDictionaryContainsKey(supportedProperties, (__bridge CFStringRef)key) == false) { + if (*error == nil) { + NSString* description = [NSString stringWithFormat:@"\"%@\" is not a supported key.", key]; + *error = [NSError errorWithDomain:SDLErrorDomainStreamingMediaVideo code:SDLStreamingVideoErrorConfigurationCompressionSessionSetPropertyFailure userInfo:@{NSLocalizedDescriptionKey : description}]; + } + CFRelease(supportedProperties); + return NO; } - - return NO; } - - status = VTSessionSetProperty(self.compressionSession, kVTCompressionPropertyKey_MaxKeyFrameInterval, intervalNumRef); - - CFRelease(intervalNumRef); - intervalNumRef = NULL; - - if (status != noErr) { - if (*error != nil) { - *error = [NSError errorWithDomain:SDLErrorDomainStreamingMediaVideo code:SDLStreamingVideoErrorConfigurationCompressionSessionSetPropertyFailure userInfo:@{ @"OSStatus" : @(status) }]; + CFRelease(supportedProperties); + + // Populate the video encoder settings from provided dictionary. + for (NSString* key in self.videoEncoderSettings.allKeys) { + id value = self.videoEncoderSettings[key]; + + status = VTSessionSetProperty(self.compressionSession, (__bridge CFStringRef)key, (__bridge CFTypeRef)value); + if (status != noErr) { + if (*error == nil) { + *error = [NSError errorWithDomain:SDLErrorDomainStreamingMediaVideo code:SDLStreamingVideoErrorConfigurationCompressionSessionSetPropertyFailure userInfo:@{ @"OSStatus" : @(status) }]; + } + + return NO; } - - return NO; } return YES; |