Benutzerdefiniertes Video-Rendering

Übersicht

Die Vonage Video API ermöglicht es, den Video-Renderer für die Verwendung in Android- und iOS-Applikationen zu modifizieren.

In dieser Anleitung wird das Thema behandelt:

  • Nehmen Sie Änderungen am Videorenderer in Ihrer Vonage Video Android-Anwendung vor
  • Nehmen Sie Änderungen am Videorenderer in Ihrer Vonage Video iOS-Anwendung vor

Android

Bevor Sie beginnen

Diese Anleitung zeigt den Code, der erforderlich ist, um kleinere Änderungen am Video-Renderer vorzunehmen, der von einem Subscriber Objekt.

Mit den gleichen Techniken können Sie auch den Videorenderer ändern, der von einer Publisher Objekts (obwohl dieses Beispiel nur einen benutzerdefinierten Renderer für einen Abonnenten veranschaulicht).

Der Code für diesen Abschnitt ist im Basic-Video-Renderer-Java-Projekt des opentok-android-sdk-Beispiele Repo. Wenn Sie dies noch nicht getan haben, müssen Sie das Projektarchiv in ein lokales Verzeichnis klonen. Führen Sie in der Befehlszeile Folgendes aus:

git clone git@github.com:opentok/opentok-android-sdk-samples.git

Öffnen Sie die Basic-Video-Renderer-Java Projekt in Android Studio, um die Entwicklung zu verfolgen.

Wichtig: Bitte beachten Sie, dass Ihr App ID ist Ihr API key.

Erforschung des Codes

In diesem Beispiel verwendet die Anwendung einen benutzerdefinierten Videorenderer, um eine invertierte Farbversion des Videos anzuzeigen.

InvertedColorsVideoRenderer ist eine benutzerdefinierte Klasse, die die BaseVideoRenderer Klasse (definiert im Android SDK). Die BaseVideoRenderer Klasse können Sie einen benutzerdefinierten Video-Renderer definieren, der von einem Vonage Video-Publisher oder -Abonnenten verwendet wird:

subscriber = new Subscriber.Builder(this, stream)
    .renderer(new InvertedColorsVideoRenderer(this))
    .build();


publisher = new Publisher.Builder(MainActivity.this)
    .renderer(new InvertedColorsVideoRenderer(MainActivity.this))
    .build();

Die InvertedColorsVideoRenderer() Konstruktor setzt eine renderer Eigenschaft zu einer GLSurfaceView Objekt. Die App verwendet dieses Objekt, um das Video mit OpenGL ES 2.0 anzuzeigen. Der Renderer für dieses GLSurfaceView Objekt wird auf ein MyRenderer Objekt. MyRenderer ist eine benutzerdefinierte Klasse, die die GLSurfaceView.Rendererund wird zum Rendern des Videos auf dem Computer verwendet. GLSurfaceView Objekt:

public InvertedColorsVideoRenderer(Context context) {
    view = new GLSurfaceView(context);
    view.setEGLContextClientVersion(2);

    renderer = new MyRenderer();
    view.setRenderer(renderer);

    view.setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY);
}

Die onFrame() Methode des Video-Renderers wird von der BaseVideoRenderer Klasse. Die Website BaseVideoRenderer.onFrame() Methode wird aufgerufen, wenn der Herausgeber (oder Abonnent) ein Videobild an den Videorenderer überträgt.

Die InvertedColorsVideoRenderer Implementierung dieser Methode nimmt sie den Bildpuffer des Bildes (YUV Darstellung des Rahmens), übergibt sie an die displayFrame Methode der MyRenderer Objekt und ruft das Objekt requestRender() Methode der GLSurfaceView Objekt:

@Override
public void onFrame(Frame frame) {
    renderer.displayFrame(frame);
    view.requestRender();
}

Um die Videobilder zu rendern, verwendet die Renderer-Klasse OpenGL-Shader. In diesem Beispiel erzeugt der Shader den invertierten Farbeffekt, genauer gesagt wird dies durch diese Zeile erreicht, die sich innerhalb der fragmentShaderCode String:

"y=1.0-1.1643*(y-0.0625);\n"

iOS

Bevor Sie beginnen

Diese Anleitung zeigt den Code, der erforderlich ist, um kleinere Änderungen am Video-Renderer vorzunehmen, der von einem OTPublisher Objekt.

Mit den gleichen Techniken können Sie auch den Videorenderer ändern, der von einer OTSubscriber Objekts (obwohl dieses Beispiel nur einen benutzerdefinierten Renderer für einen Verlag veranschaulicht).

Der Code für diesen Abschnitt befindet sich in der Grundlegender Video-Renderer Projekt des opentok-ios-sdk-Beispiele Repository. Wenn Sie das noch nicht getan haben, müssen Sie das Repository in ein lokales Verzeichnis klonen - Dies kann über die Befehlszeile erfolgen:

git clone https://github.com/opentok/opentok-ios-sdk-samples.git

Wechseln Sie in das Verzeichnis des Basic Video Renderer-Projekts:

cd opentok-ios-sdk-samples/Basic-Video-Renderer

Installieren Sie dann die Vonage Video-Abhängigkeit:

pod install

Öffnen Sie das Projekt in Xcode, um es zu verfolgen.

Wichtig: Bitte beachten Sie, dass Ihre App-ID Ihr API-Schlüssel ist.

Erforschung des Codes

In diesem Beispiel verwendet die Anwendung einen benutzerdefinierten Video-Renderer, um eine Schwarz-Weiß-Version des Videos des OTPublisher-Objekts anzuzeigen.

Im Haupt-ViewController wird nach der Initialisierung des OTPublisher-Objekts die videoRender Eigenschaft des OTPublisher-Objekts auf eine Instanz von OTKBasicVideoRender gesetzt wird:

_publisher = [[OTPublisher alloc] initWithDelegate:self settings:settings];
_renderer = [[OTKBasicVideoRender alloc] init];
_publisher.videoRender = _renderer;

OTKBasicVideoRender ist eine benutzerdefinierte Klasse, die das OTVideoRender-Protokoll implementiert (definiert im iOS SDK). Mit diesem Protokoll können Sie einen benutzerdefinierten Video-Renderer definieren, der von einem Vonage Video-Publisher oder -Teilnehmer verwendet wird.

Die [OTKBasicVideoRender init:] Methode setzt eine _renderView Eigenschaft auf ein UIView-Objekt. Dies ist das UIView-Objekt, das die (vom Herausgeber oder Abonnenten) zu rendernde Ansicht enthält. In diesem Beispiel wird das UIView-Objekt durch die benutzerdefinierte Klasse OTKCustomRenderView definiert, die UIView erweitert:

- (id)init
{
    self = [super init];
    if (self) {
        _renderView = [[OTKCustomRenderView alloc] initWithFrame:CGRectZero];
    }
    return self;
}

Die Klasse OTKCustomRenderView enthält Methoden (die später besprochen werden), die ein Videobild in eine Schwarz-Weiß-Darstellung umwandeln.

Die [OTVideoRender renderVideoFrame:] Methode wird aufgerufen, wenn der Herausgeber (oder Abonnent) ein Videobild an den Videorenderer überträgt. Das Bild ist ein OTVideoFrame-Objekt (definiert durch das iOS SDK). In der OTKCustomRenderView-Implementierung dieser Methode wird der Frame genommen und an die [renderVideoFrame] Methode des OTKCustomRenderView-Objekts:

- (void)renderVideoFrame:(OTVideoFrame*) frame
{
    [(OTKCustomRenderView*)self.renderView renderVideoFrame:frame];
}

Die [OTKCustomRenderView renderVideoFrame] Methode durchläuft die Pixel in der Ebene, stellt jedes Pixel auf einen Schwarz-Weiß-Wert ein und fügt den Wert in einen Puffer ein. Anschließend schreibt sie den Puffer in eine CGImageRef, die das Bild der Ansicht darstellt, und ruft [self setNeedsDisplay] um die Bildansicht zu rendern:

- (void)renderVideoFrame:(OTVideoFrame *)frame
{
    __block OTVideoFrame *frameToRender = frame;
    dispatch_sync(self.renderQueue, ^{
        if (_img != NULL) {
            CGImageRelease(_img);
            _img = NULL;
        }

        size_t bufferSize = frameToRender.format.imageHeight
            * frameToRender.format.imageWidth * 3;
        uint8_t *buffer = malloc(bufferSize);

        uint8_t *yplane = [frameToRender.planes pointerAtIndex:0];

        for (int i = 0; i < frameToRender.format.imageHeight; i++) {
            for (int j = 0; j < frameToRender.format.imageWidth; j++) {
                int starting = (i * frameToRender.format.imageWidth * 3) + (j * 3);
                uint8_t yvalue = yplane[(i * frameToRender.format.imageWidth) + j];
                // If in a RGB image we copy the same Y value for R, G and B
                // we will obtain a Black & White image
                buffer[starting] = yvalue;
                buffer[starting+1] = yvalue;
                buffer[starting+2] = yvalue;
            }
        }

        CGDataProviderRef imgProvider = CGDataProviderCreateWithData(NULL,
                                                                        buffer,
                                                                        bufferSize,
                                                                        release_frame);

        _img = CGImageCreate(frameToRender.format.imageWidth,
                                frameToRender.format.imageHeight,
                                8,
                                24,
                                3 * frameToRender.format.imageWidth,
                                CGColorSpaceCreateDeviceRGB(),
                                kCGBitmapByteOrder32Big | kCGImageAlphaNone,
                                imgProvider,
                                NULL,
                                false,
                                kCGRenderingIntentDefault);


        CGDataProviderRelease(imgProvider);
        dispatch_async(dispatch_get_main_queue(), ^{
            [self setNeedsDisplay];
        });
    });
}

Siehe auch