New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Custom video encoder settings and dynamic screen sizes #406
Changes from 2 commits
aac227a
abfb28d
801f54f
f3eb424
4694398
74ae86f
2e929ed
1c82de4
6bb971b
1ac0a6b
5f7b6c3
0f7226c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -127,6 +127,28 @@ - (BOOL)sendAudioData:(NSData *)pcmAudioData { | |
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_ProfileLevel : (__bridge NSString*)kVTProfileLevel_H264_Baseline_AutoLevel, | ||
(__bridge NSString*)kVTCompressionPropertyKey_RealTime : @(YES) | ||
}; | ||
} | ||
return defaultVideoEncoderSettings; | ||
} | ||
|
||
|
||
#pragma mark - SDLProtocolListener Methods | ||
|
||
|
@@ -229,83 +251,52 @@ - (BOOL)sdl_configureVideoEncoderWithError:(NSError *__autoreleasing *)error { | |
|
||
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) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If this is how it's being done, then the video encoder settings dict should be null_resettable, not nullable, and the api should be redesigned so that it's initialized on There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We need to decide how this init will work with #400 also making a change / addition to init. |
||
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; | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@(YES)
can be written as@YES