2017-01-31 12 views
2

Большое спасибо за это, я знаю, что этот вопрос может быть непростым. Если вам нужно какое-либо разъяснение или я хочу лучше объяснить метод, я с радостью поможем вам.Аудио, записанное с AVCaptureSession, генерирует ошибку «Плохой адрес» при потоковой передаче на другое устройство

Я создаю AVCaptureSession и создаю OutputStream, используя этот метод. OutputStream создается методом MultipeerConnectivity. Более конкретно, метод: startStream (withName: _, fromPeer: _). Если вы не знакомы с этим методом, он возвращает outputStream и отправляет inputStream в peer.

func setupAVRecorder() { 
do { 
    try recordingSession.setCategory(AVAudioSessionCategoryPlayAndRecord) 
    try recordingSession.setMode(AVAudioSessionModeVoiceChat) 
    try recordingSession.setPreferredSampleRate(44000.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) 
       } 
       catch let error { 
        print("\(#file) > \(#function) > ERROR: \(error.localizedDescription)") 
       } 
      } 
     } 
    } 
} 
catch let error { 
    print("\(#file) > \(#function) > ERROR: \(error.localizedDescription)") 
} 

//------------------------------------------------------------------ 
// Set output stream 

if (!outputStreamIsSet) { 
    do { 
     outputStream = try self.appDelegate.connectionManager.sessions[sessionIndex!].startStream(withName: "audioStream", toPeer: peerID!) 
     outputStreamIsSet = true 
    } 
    catch let error as NSError { 
     print("\(#file) > \(#function) > Failed to create outputStream: \(error.localizedDescription)") 

     endCallButtonIsClicked(endCallButton) // this just ends the stream 
    } 
} 
} 

Как только пользователи фактически соединяются друг с другом, вызывается метод делегата. В методе делегата мы получаем InputStream, мы открываем выходные и входные потоки, и, наконец, мы начинаем запись, используя метод startRunning():

func startedStreamWithPeer(_ peerID: MCPeerID, inputStream: InputStream) { 
    if (peerID == self.peerID) { 

     self.inputStream = inputStream 
     self.inputStreamIsSet = true 
     self.inputStream?.delegate = self 
     self.inputStream?.open() 
     self.outputStream?.open() 

     self.captureSession.startRunning() 
    } 
    else { 
     print("\(#file) > \(#function) > Should not print.") 
    } 
} 

Вот проблема. Функция captureSession записывает данные в буфер и вызывает метод captureOutput (я считаю, что это метод делегата). Внутри этого метода я пытаюсь преобразовать CMSampleBuffer в UnsafePointer, чтобы я мог записать его в 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 output = outputStream?.write((buffer.mData?.load(as: UnsafePointer<UInt8>.self))!, maxLength: Int(buffer.mDataByteSize)) 

     if (output == -1) { 
      let error = outputStream?.streamError 
      print("\(#file) > \(#function) > Error: \(error!.localizedDescription)") 
     } 
    } 
} 

В последнем заявлении печати я получаю сообщение об ошибке, о котором я говорил ранее: «Операция не может быть выполнена. Плохой адрес».

Есть ли у кого-нибудь опыт в записи звука, а затем преобразование этого аудио в объект UnsafePointer?

Спасибо!

ответ

2
buffer.mData?.load(as: UnsafePointer<UInt8>.self) 

считывает байты, которые buffer.mData указывает на UnsafePointer<UInt8> переменной а, другими словами, указатель разыменовываются, и результат передается в качестве буфера адреса к методу write(). Однако buffer.mData указывает на звуковые данные, а не на (действительный) указатель , и именно поэтому write() не работает с «Плохим адресом».

То, что вы действительно хотите, чтобы «бросить» или «переосмысливать» buffer.mData как UnsafePointer<UInt8>, и что делается с

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

(я оставляю вам заменить вынужденное разворачивает с дополнительными креплениями или необязательная цепочка.)

+0

Спасибо, @Martin, что исправил проблему. Единственная проблема теперь в том, что метод делегата InputStream «func stream (Stream, eventCode)» не вызывается ... Я полагаю, что это еще одна проблема. – Logan

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

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