2017-01-14 2 views
3

Mit einfachen Worten, alles, was ich tun muss, ist ein Live-Stream von Video-Frames in Android anzuzeigen (jedes Bild ist YUV420-Format). Ich habe eine Callback-Funktion, wo ich einzelne Frames als Byte-Array empfange. Etwas, das wie folgt aussieht:Optionen zum effizienten Zeichnen eines Stroms von Byte-Arrays zur Anzeige in Android

public void onFrameReceived(byte[] frame, int height, int width, int format) { 
    // display this frame to surfaceview/textureview. 
} 

A möglich, aber langsam Option ist die Byte-Array in eine Bitmap zu konvertieren und auf die Leinwand auf Surface zu ziehen. In der Zukunft möchte ich in der Lage sein, die Helligkeit, den Kontrast usw. dieses Bildes zu ändern und hoffe daher, dass ich OpenGL-ES für dasselbe verwenden kann. Was sind meine anderen Möglichkeiten, dies effizient zu tun?

Erinnern Sie sich, anders als bei Implementierungen von Camera oder MediaPlayer Klasse, kann ich nicht meine Ausgabe zu einem Surface/TextureView direkt mit camera.setPreviewTexture(surfaceTexture); wie ich einzelne Frames empfange mit GStreamer in C.

+0

Ich ging direkt auf der Strecke mit OpenGLES die YUV-Frames direkt von Rendering. Ich kann den Fragment-Shader und jede andere Quelle aus meinem Code veröffentlichen, wenn es hilft. – WLGfx

+0

Wie Sie diese YUV-Frames gerendert haben, ist genau das, was ich wissen muss! Haben Sie diese Frames in Form eines Bytearrays empfangen, so wie ich bin? (Quellcode wäre hilfreich, danke!) –

Antwort

1

ich ffmpeg bin mit für mein Projekt, aber das Prinzip für das Rendern des YUV-Rahmens sollte für dich das gleiche sein.

Wenn ein Rahmen zum Beispiel 756 x 576 ist, wird der Y-Rahmen diese Größe haben. Der U- und V-Frame sind die Hälfte der Breite und Höhe des Y-Frames, daher müssen Sie sicherstellen, dass Sie die Größenunterschiede berücksichtigen.

Ich weiß nicht über die Kamera-API, aber die Frames, die ich von einer DVB-Quelle bekomme, haben eine Breite und auch jede Zeile hat einen Schritt. Extras Pixel am Ende jeder Zeile im Rahmen. Nur für den Fall, dass Ihr gleich ist, berücksichtigen Sie dies bei der Berechnung Ihrer Texturkoordinaten.

die Textur Einstellen Koordinaten für die Breite und Schritt (linesize) zu berücksichtigen:

float u = 1.0f/buffer->y_linesize * buffer->wid; // adjust texture coord for edge 

Der Vertex-Shader ich verwendet habe, nimmt Bildschirm von 0,0 bis 1,0-Koordinaten, aber Sie können diese anpassen ändern. Es berücksichtigt auch die Texturkoordinaten und eine Farbeingabe. Ich habe die Farbeingabe verwendet, so dass I Fading hinzuzufügen, usw.

Vertex-Shader:

#ifdef GL_ES 
precision mediump float; 
const float c1 = 1.0; 
const float c2 = 2.0; 
#else 
const float c1 = 1.0f; 
const float c2 = 2.0f; 
#endif 

attribute vec4 a_vertex; 
attribute vec2 a_texcoord; 
attribute vec4 a_colorin; 
varying vec2 v_texcoord; 
varying vec4 v_colorout; 



void main(void) 
{ 
    v_texcoord = a_texcoord; 
    v_colorout = a_colorin; 

    float x = a_vertex.x * c2 - c1; 
    float y = -(a_vertex.y * c2 - c1); 

    gl_Position = vec4(x, y, a_vertex.z, c1); 
} 

Die Fragment-Shader, die drei gleichförmige Texturen nimmt, eine für jeden Y, U und V und wandelt framges zu RGB. Dies vervielfacht auch durch die Farbe aus dem Vertex-Shader übergeben:

#ifdef GL_ES 
precision mediump float; 
#endif 

uniform sampler2D u_texturey; 
uniform sampler2D u_textureu; 
uniform sampler2D u_texturev; 
varying vec2 v_texcoord; 
varying vec4 v_colorout; 

void main(void) 
{ 
    float y = texture2D(u_texturey, v_texcoord).r; 
    float u = texture2D(u_textureu, v_texcoord).r - 0.5; 
    float v = texture2D(u_texturev, v_texcoord).r - 0.5; 
    vec4 rgb = vec4(y + 1.403 * v, 
        y - 0.344 * u - 0.714 * v, 
        y + 1.770 * u, 
        1.0); 
    gl_FragColor = rgb * v_colorout; 
} 

Die verwendeten Eckpunkte sind in:

float x, y, z; // coords 
float s, t;  // texture coords 
uint8_t r, g, b, a; // colour and alpha 

hoffe, das hilft!

EDIT:

Für NV12 Format, das Sie noch ein Fragment-Shader verwenden können, obwohl ich es selbst nicht ausprobiert habe. Es nimmt das verschachtelte UV als Luminanz-Alpha-Kanal oder ähnliches auf.

Sehen Sie hier, wie eine Person diese beantwortet hat: https://stackoverflow.com/a/22456885/2979092

+0

Meine ursprüngliche Frage war tatsächlich, wie diese Byte-Frames auf einer Oberfläche angezeigt werden würden (der tatsächliche Mechanismus, wie der Frame gezeichnet werden würde). Daher kann ich das nicht als Antwort akzeptieren. Dies ist jedoch hilfreich! Danke vielmals. Das wahre Format, in dem meine Bilder sind, ist NV12. (Die UV-Komponenten sind verschachtelt). Weißt du, wie ich U- und V-Komponenten einzeln extrahiere? –

+0

Ich habe eine Bearbeitung mit einem Verweis auf die NV12-Shader-Antwort hinzugefügt. – WLGfx

+0

Ja, ich habe das benutzt. Nochmals vielen Dank! Ich werde meine Lösung veröffentlichen, wie ich einzelne Byte-Frames effizient zur Strukturansicht anzeigen kann. Ich werde jedoch Ihre Antwort auffrischen, da sie sehr hilfreich war, sobald ich genug Reputation dazu habe! –

Verwandte Themen