summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMuller, Alexander (A.) <amulle19@ford.com>2016-05-25 18:28:03 -0700
committerMuller, Alexander (A.) <amulle19@ford.com>2016-05-25 18:28:03 -0700
commitaac227ab58b24c4296e24dea5ddf782985a021e6 (patch)
tree35f4bc55048545b62a4900989932dfc4803167fb
parentc444bce2c2c39d504567b18c713d244f4a2b8dc5 (diff)
downloadsdl_ios-aac227ab58b24c4296e24dea5ddf782985a021e6.tar.gz
Added support for allowing developers to set custom video encoder settings.
-rw-r--r--SmartDeviceLink-iOS/SmartDeviceLink/SDLStreamingMediaManager.h12
-rw-r--r--SmartDeviceLink-iOS/SmartDeviceLink/SDLStreamingMediaManager.m117
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;