Swift

Inicializando a captura

Neste exemplo, o aplicativo utiliza um capturador de vídeo personalizado para exibir pixels aleatórios (ruído branco). Isso é feito simplesmente para ilustrar os princípios básicos da configuração de um capturador de vídeo personalizado.

Em geral VonageVideoManager, depois de ligar para session.publish(publisher, error: &error) para iniciar a transmissão de um fluxo de áudio e vídeo, o videoCapture propriedade do OTPublisher o objeto é definido como uma instância de BasicVideoCapturer:

publisher.videoCapture = BasicVideoCapturer()

BasicVideoCapturer é uma classe personalizada que implementa a OTVideoCapture protocolo (definido no SDK da Vonage para iOS). Esse protocolo permite definir um capturador de vídeo personalizado para ser usado por um editor do OpenTok.

O initCapture O método inicializa as configurações de captura a serem utilizadas pelo capturador de vídeo personalizado. Na implementação personalizada deste exemplo de OTVideoCapture (OTKBasicVideoCapturer), o initCapture O método define as propriedades do videoFormat propriedade:

func initCapture() {
    let format = OTVideoFormat()
    format.pixelFormat = .ARGB
    format.bytesPerRow = [NSNumber(value: imageWidth * 4)]
    format.imageHeight = imageHeight
    format.imageWidth = imageWidth
    
    self.videoFormat = format
}

O OTVideoFormat A classe é definida pelo SDK da Vonage para iOS. Neste código de exemplo, o formato do capturador de vídeo está configurado para usar ARGB como formato de pixel, com um número específico de bytes por linha, altura e largura.

O videoCaptureConsumer A propriedade define um OTVideoCaptureConsumer objeto que o consumidor de vídeo utiliza para transmitir quadros de vídeo para o fluxo do editor. Em BasicVideoCapturer, essa propriedade é sintetizada a partir do protocolo:

var videoCaptureConsumer: OTVideoCaptureConsumer?

Iniciando a captura

O start O método é chamado quando um emissor começa a capturar vídeo para enviá-lo como um stream para a sessão da Vonage. Isso ocorrerá após o Session.publish(_:error:) método é chamado. No BasicVideoCapturer, esse método aciona produceFrame em uma fila de segundo plano:

//
//  returns:
//  - a negative value for error
//  - 0 value when all is OK
//
func start() -> Int32 {
    self.captureStarted = true
    
    // Start the frame loop on a background queue
    DispatchQueue.global(qos: .background).asyncAfter(deadline: timerInterval) { [weak self] in
        self?.produceFrame()
    }
    
    return 0
}

Personalização da moldura

O produceFrame O método gera um OTVideoFrame objeto que representa um quadro de vídeo. Nesse caso, o quadro contém pixels aleatórios que preenchem a altura e a largura definidas:

private func produceFrame() {
    guard let format = self.videoFormat else { return }
    
    let frame = OTVideoFrame(format: format)
    
    // Allocate buffer for image data
    let bufferSize = Int(imageWidth * imageHeight * 4)
    let buffer = UnsafeMutablePointer<UInt8>.allocate(capacity: bufferSize)
    
    // Generate random pixels
    for i in stride(from: 0, to: bufferSize, by: 4) {
        buffer[i]     = UInt8.random(in: 0...255) // A
        buffer[i + 1] = UInt8.random(in: 0...255) // R
        buffer[i + 2] = UInt8.random(in: 0...255) // G
        buffer[i + 3] = UInt8.random(in: 0...255) // B
    }
    
    // Pass pointer to Vonage
    var planePointer: UnsafeMutablePointer<UInt8> = buffer
    withUnsafeMutablePointer(to: &planePointer) { pointerToPlanePointer in
        frame.setPlanesWithPointers(UnsafeMutableRawPointer(pointerToPlanePointer).assumingMemoryBound(to: UnsafeMutablePointer<UInt8>.self), numPlanes: 1)
    }
    
    // Send frame to consumer
    self.videoCaptureConsumer?.consumeFrame(frame)
    
    buffer.deallocate()
    
    if self.captureStarted {
        DispatchQueue.global(qos: .background).asyncAfter(deadline: timerInterval) { [weak self] in
            self?.produceFrame()
        }
    }
}

O método passa o quadro para o consumeFrame método do OTVideoCaptureConsumer. Isso faz com que o editor envie o quadro de dados para o fluxo de vídeo na sessão.