2017-02-03 12 views
0

Мое приложение - это в основном телефонный звонок по MultipeerConnectivity.iOS - Потоковое и приемное аудио с устройства на другое заканчивается одной только отправкой, а другая только принимает

Вот как я настраиваю сеанс аудио: Обратите внимание, что записьSession имеет тип AVAudioSession и captureSession имеет тип AVCaptureSession.

func setupAVRecorder() { 
    print("\(#file) > \(#function) > Entry") 

    do { 
     try recordingSession.setCategory(AVAudioSessionCategoryPlayAndRecord) 
     try recordingSession.setMode(AVAudioSessionModeVoiceChat) 
     try recordingSession.setPreferredSampleRate(44100.00) 
     try recordingSession.setPreferredIOBufferDuration(0.2) 
     try recordingSession.setActive(true) 

     recordingSession.requestRecordPermission() { [unowned self] (allowed: Bool) -> Void in 
      DispatchQueue.main.async { 
       if allowed { 
        do { 
         self.captureDevice = AVCaptureDevice.defaultDevice(withMediaType: AVMediaTypeAudio) 
         try self.captureDeviceInput = AVCaptureDeviceInput.init(device: self.captureDevice) 

         self.outputDevice = AVCaptureAudioDataOutput() 
         self.outputDevice?.setSampleBufferDelegate(self, queue: DispatchQueue.main) 

         self.captureSession = AVCaptureSession() 
         self.captureSession.addInput(self.captureDeviceInput) 
         self.captureSession.addOutput(self.outputDevice) 
         self.captureSession.startRunning() 

        } 
        catch let error { 
         print("\(#file) > \(#function) > ERROR: \(error.localizedDescription)") 
        } 
       } 
      } 
     } 
    } 
    catch let error { 
     print("\(#file) > \(#function) > ERROR: \(error.localizedDescription)") 
    } 
} 

Тогда я получил функцию captureOutput от AVCaptureAudioDataOutputSampleBufferDelegate. В этом методе я записываю данные в outputStream.

func captureOutput(_ captureOutput: AVCaptureOutput!, didOutputSampleBuffer sampleBuffer: CMSampleBuffer!, from connection: AVCaptureConnection!) { 

    var blockBuffer: CMBlockBuffer? 
    var audioBufferList: AudioBufferList = AudioBufferList.init() 

    CMSampleBufferGetAudioBufferListWithRetainedBlockBuffer(sampleBuffer, nil, &audioBufferList, MemoryLayout<AudioBufferList>.size, nil, nil, kCMSampleBufferFlag_AudioBufferList_Assure16ByteAlignment, &blockBuffer) 
    let buffers = UnsafeMutableAudioBufferListPointer(&audioBufferList) 

    for buffer in buffers { 
     let u8ptr = buffer.mData!.assumingMemoryBound(to: UInt8.self) 
     let output = outputStream!.write(u8ptr, maxLength: Int(buffer.mDataByteSize)) 
    } 
} 

я получаю данные в потоке Func (_ aStream: поток, ручка eventCode: Stream.Event), которая из InputStreamDelegate. В этом методе, когда доступны байты, я вызываю свой метод readFromStream().

func readFromStream() { 
    while (inputStream!.hasBytesAvailable) { 
     var buffer = [UInt8](repeating: 0, count: 4096) 
     let length = inputStream!.read(&buffer, maxLength: buffer.count) 

     if (length > 0) { 

      let audioBuffer = bytesToAudioBuffer(buffer) 
      let mainMixer = audioEngine!.mainMixerNode 

      audioEngine!.connect(audioPlayer!, to: mainMixer, format: audioBuffer.format) 
      audioPlayer!.scheduleBuffer(audioBuffer, completionHandler: nil) 

      do { 
       try audioEngine!.start() 
      } 
      catch let error as NSError { 
       print("\(#file) > \(#function) > error: \(error.localizedDescription)") 
      } 

      audioPlayer!.play() 
     } 
    } 
} 

Этот метод, кажется, прекрасно работать, за исключением того, что звук фактически не играл, за исключением, есть только тишина, но это другой вопрос. Моя проблема прямо сейчас заключается в том, что когда я помещаю заявления печати внутри этих методов, одно из устройств постоянно отправляет данные, не получая их, а другое устройство постоянно получает данные, не отправляя их. Я предполагаю, что это связано с тем, что я использую один поток, чтобы следить за отправкой и получением данных, поэтому одно из устройств inputBuffers никогда не очищается.

Мое предположение заключается в том, что исправление заключается в том, чтобы сделать одну нить заботой о записи и отправке, а другую - заботиться о приеме и игре?

Я только хорошо знаком с потоками, но не знаком с тем, как потоки работают в Swift, так что если это так, кто-нибудь может мне помочь в этом?

Большое вам спасибо за ваше время!

ответ

1

Вам необходимо использовать DispatchQueues. Вот пример того, как сделать один:

пусть streamReceiverQueue = DispatchQueue (метка: «someNameForQueue», QOS: DispatchQoS.userInteractive)

Ярлык не важно, это просто должно быть уникальным, если используется несколько DispatchQueues , Qos - это в основном тот приоритет, который является очередью, если вы настроили его на userInteractive, это самое важное и быстро выполнит все действия.

Вы можете найти более подробную информацию о QoS here

Тогда, если вы хотите очередь выполнить вещи синхронно, чем выполнить его, используя

streamReceiverQueue.sync { 
    // Here is what will execute on the streamReceiverQueue 
} 

И если вы хотите вещи, чтобы выполнить асинхронно, чем выполнить его, используя:

streamReceiverQueue.async { 
    // Your code here 
} 

 Смежные вопросы

  • Нет связанных вопросов^_^