Swift

Initialisierung der Erfassung

In diesem Beispiel verwendet die Anwendung einen benutzerdefinierten Video-Capturer, um zufällige Pixel (weißes Rauschen) zu veröffentlichen. Dies dient lediglich zur Veranschaulichung der grundlegenden Prinzipien der Einrichtung eines benutzerdefinierten Video-Capturers.

In der Hauptsache VonageVideoManagernach dem Aufruf session.publish(publisher, error: &error) um die Veröffentlichung eines Audio-Video-Streams zu veranlassen, die videoCapture Eigenschaft der OTPublisher Objekt wird auf eine Instanz von BasicVideoCapturer:

publisher.videoCapture = BasicVideoCapturer()

BasicVideoCapturer ist eine benutzerdefinierte Klasse, die die OTVideoCapture Protokoll (definiert im Vonage iOS SDK). Mit diesem Protokoll können Sie einen benutzerdefinierten Video-Capturer definieren, der von einem OpenTok-Publisher verwendet wird.

Die initCapture Methode initialisiert die Aufnahmeeinstellungen, die vom benutzerdefinierten Video-Capturer verwendet werden sollen. In der benutzerdefinierten Implementierung dieses Beispiels von OTVideoCapture (OTKBasicVideoCapturer), die initCapture Methode setzt Eigenschaften der videoFormat Eigentum:

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

Die OTVideoFormat Klasse ist durch das Vonage iOS SDK definiert. In diesem Beispielcode ist das Format des Video-Capturers so eingestellt, dass ARGB als Pixelformat verwendet wird, mit einer bestimmten Anzahl von Bytes pro Zeile, Höhe und Breite.

Die videoCaptureConsumer Eigenschaft setzt eine OTVideoCaptureConsumer Objekt, das der Videokonsument zur Übertragung von Videobildern an den Stream des Herausgebers verwendet. Unter BasicVideoCapturerwird diese Eigenschaft aus dem Protokoll synthetisiert:

var videoCaptureConsumer: OTVideoCaptureConsumer?

Start der Erfassung

Die start Methode wird aufgerufen, wenn ein Publisher mit der Aufnahme von Videos beginnt, um diese als Stream an die Vonage-Sitzung zu senden. Dies geschieht, nachdem die Session.publish(_:error:) Methode aufgerufen wird. In der BasicVideoCapturerlöst diese Methode Folgendes aus produceFrame in einer Warteschlange im Hintergrund:

//
//  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
}

Rahmenanpassung

Die produceFrame Methode erzeugt eine OTVideoFrame Objekt, das ein Einzelbild eines Videos darstellt. In diesem Fall enthält der Rahmen zufällige Pixel, die die festgelegte Höhe und Breite ausfüllen:

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()
        }
    }
}

Die Methode übergibt den Rahmen an die consumeFrame Methode der OTVideoCaptureConsumer. Dies veranlasst den Herausgeber, das Datenbild an den Videostream in der Sitzung zu senden.