2014 snapchat source code
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.

115 lines
3.5 KiB

  1. //
  2. // SCManagedAudioStreamer.m
  3. // Snapchat
  4. //
  5. // Created by Ricardo Sánchez-Sáez on 7/28/16.
  6. // Copyright © 2016 Snapchat, Inc. All rights reserved.
  7. //
  8. #import "SCManagedAudioStreamer.h"
  9. #import "SCAudioCaptureSession.h"
  10. #import <SCAudio/SCAudioSession.h>
  11. #import <SCCameraFoundation/SCManagedAudioDataSourceListenerAnnouncer.h>
  12. #import <SCFoundation/SCQueuePerformer.h>
  13. #import <SCFoundation/SCTrace.h>
  14. #import <SCAudioScope/SCAudioScope.h>
  15. #import <SCAudioScope/SCAudioSessionExperimentAdapter.h>
  16. static char *const kSCManagedAudioStreamerQueueLabel = "com.snapchat.audioStreamerQueue";
  17. @interface SCManagedAudioStreamer () <SCAudioCaptureSessionDelegate>
  18. @end
  19. @implementation SCManagedAudioStreamer {
  20. SCAudioCaptureSession *_captureSession;
  21. SCAudioConfigurationToken *_audioConfiguration;
  22. SCManagedAudioDataSourceListenerAnnouncer *_announcer;
  23. SCScopedAccess<SCMutableAudioSession *> *_scopedMutableAudioSession;
  24. }
  25. @synthesize performer = _performer;
  26. + (instancetype)sharedInstance
  27. {
  28. static dispatch_once_t onceToken;
  29. static SCManagedAudioStreamer *managedAudioStreamer;
  30. dispatch_once(&onceToken, ^{
  31. managedAudioStreamer = [[SCManagedAudioStreamer alloc] initSharedInstance];
  32. });
  33. return managedAudioStreamer;
  34. }
  35. - (instancetype)initSharedInstance
  36. {
  37. SCTraceStart();
  38. self = [super init];
  39. if (self) {
  40. _performer = [[SCQueuePerformer alloc] initWithLabel:kSCManagedAudioStreamerQueueLabel
  41. qualityOfService:QOS_CLASS_USER_INTERACTIVE
  42. queueType:DISPATCH_QUEUE_SERIAL
  43. context:SCQueuePerformerContextCamera];
  44. _announcer = [[SCManagedAudioDataSourceListenerAnnouncer alloc] init];
  45. _captureSession = [[SCAudioCaptureSession alloc] init];
  46. _captureSession.delegate = self;
  47. }
  48. return self;
  49. }
  50. - (BOOL)isStreaming
  51. {
  52. return _audioConfiguration != nil;
  53. }
  54. - (void)startStreamingWithAudioConfiguration:(SCAudioConfiguration *)configuration
  55. {
  56. SCTraceStart();
  57. [_performer perform:^{
  58. if (!self.isStreaming) {
  59. // Begin audio recording asynchronously. First we need to have the proper audio session category.
  60. _audioConfiguration = [SCAudioSessionExperimentAdapter
  61. configureWith:configuration
  62. performer:_performer
  63. completion:^(NSError *error) {
  64. [_captureSession
  65. beginAudioRecordingAsynchronouslyWithSampleRate:kSCAudioCaptureSessionDefaultSampleRate
  66. completionHandler:NULL];
  67. }];
  68. }
  69. }];
  70. }
  71. - (void)stopStreaming
  72. {
  73. [_performer perform:^{
  74. if (self.isStreaming) {
  75. [_captureSession disposeAudioRecordingSynchronouslyWithCompletionHandler:NULL];
  76. [SCAudioSessionExperimentAdapter relinquishConfiguration:_audioConfiguration performer:nil completion:nil];
  77. _audioConfiguration = nil;
  78. }
  79. }];
  80. }
  81. - (void)addListener:(id<SCManagedAudioDataSourceListener>)listener
  82. {
  83. SCTraceStart();
  84. [_announcer addListener:listener];
  85. }
  86. - (void)removeListener:(id<SCManagedAudioDataSourceListener>)listener
  87. {
  88. SCTraceStart();
  89. [_announcer removeListener:listener];
  90. }
  91. - (void)audioCaptureSession:(SCAudioCaptureSession *)audioCaptureSession
  92. didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer
  93. {
  94. [_announcer managedAudioDataSource:self didOutputSampleBuffer:sampleBuffer];
  95. }
  96. @end