2017-08-06 8 views
0

Gegeben zwei codierte Streams, ich möchte sie Seite an Seite beitreten. Wie ich annehme, habe ich zwei separate H.264-kodierte 1024x768 Videos mit der gleichen Bildrate. Ich möchte diese beiden so kombinieren, dass Video 1 und Video 2 nebeneinander liegen, um einen Stream mit der doppelten Breite (1024 * 2) × 768 oder 2048 × 768 zu bilden. Mein erster Versuch war, den Stream zu decodieren und die einzelnen Frames zu kombinieren, um dann den einzelnen Stream erneut zu codieren. Decoding und Reencoding sind in Ordnung und das funktioniert aber sehr langsam (wie ffmpeg). Das Problem scheint mit der Rechenzeit zu sein, Frames von YUV nach RGB zu konvertieren oder sie in ihrer YUV-Form zu kombinieren. Der Android-Decoder produziert YUV und die Mathematik, die verwendet wird, um Rahmen nebeneinander zu kombinieren, ist für dieses Formular intensiv. Also meine Frage ist;Anzeigen von Video-Frames nebeneinander nach dem Entschlüsseln (Android)

1) Gibt es eine schnellere oder effizientere Möglichkeit, Frames zu kombinieren, wenn sie in YUV-Form vorliegen?

2a) Wenn nicht, ist es viel schneller, sie zu kombinieren, wenn sie stattdessen in RGB-Form vorliegen?

2b) Wenn ja, wie würde ich einen H.264-Stream in RGB-Frames in Android decodieren?

P.S. Versuchtes ffmpeg und openCV erfordern beide die YUV zu RGB Umwandlung, die es extrem langsam macht (~ 5fps)

Danke!

+0

Verwenden Sie die API oder die Befehlszeile? – WLGfx

+0

API, aber verwendete Befehlszeile beim Testen mit ffmpeg –

+0

Der schnellste Weg wäre, die YUV-Puffer groß genug für beide Frames zu erstellen und die Daten selbst zu kopieren, bevor sie an den Encoder übergeben werden, ohne dass RGB in RGB konvertiert werden muss. – WLGfx

Antwort

1

Der decodierte Frame AVFrame hat uint_t *data[] und int linesize[] in der Struktur. Ein YUV-Rahmen hat drei Datenzeiger und drei Zeilengrößen. Ziemlich häufig sind die Liniengrößen größer als die Breite, also passen Sie darauf auf.

Hier ist einige Pseudo-Code, der helfen kann. Hoffentlich ohne zu viele Tippfehler.

// No proper checks in here, it's just for reference 
// You could just as easily pass the data pointers for the outframe as uint8_t *data[] 

void mergeFrames(AVFrame *frame1, AVFrame *frame2, AVFrame *outframe) 
{ 
    // do Y frame 
    uint32_t *out = outframe->data[0]; // 1 and 2 are for the U and V frames 

    uint8_t *in1 = frame1->data[0]; 
    uint8_t *in2 = frame2->data[0]; 

    int height = outframe->height; 
    int inwidth = frame1->width; 
    int stride = frame1->linesize[0]; 
    int pos = 0; 

    while (pos++ < height) { 
     // left side 

     uint32_t *in = (uint32_t*)(in1 + pos * stride); // <- stride, not width 

     int c = frame1->width >> 2; // assume 4 bytes 
     while (c--) *out++ = *in++; 

     // right side 

     in = (uint32_t*)(in2 + pos * stride); 

     c = width >> 2; 
     while (c--) *out++ = *in++; 
    } 

    // And the same for the U and V frames 
} 

Der Compiler sollte einen guten Job der Optimierung tun.

Beachten Sie auch, dass wenn Sie mit den U- und V-Rahmen arbeiten, sie die halbe Breite und die halbe Höhe des Y-Rahmens haben.

+0

Wird dies versuchen und melden Sie sich zurück! –

+0

Also diese Art von Arbeiten ... Das Ergebnis ist die Rahmen nebeneinander, aber es ist vollständig mit grün getönt statt –

+0

Wenn es grün ist, wird einer der U-oder V-Frames nicht korrekt kopiert. – WLGfx

0

Welche komplexe Mathematik wird benötigt, um diese Bilder zu kombinieren?

Alles, was Sie tun müssen, ist jede Zeile von frameOfVideo1 auf Indizes 0 bis 1023 und jede Zeile von frameOfVideo2 auf Indizes 1024 bis 2047. (von der Linie des kombinierten Bildes) kopieren

(dies ist die Indizes für die y-Ebene Die u-, v-Ebenen oder die uv-Ebene (z. B. nv12) Die Zahlen sind unterschiedlich, aber das Konzept ist identisch)

+0

Mein Verständnis ist, was Sie beschrieben, ist relevant für RGB und deshalb ist es einfach, aber für YUV ist es komplexer und erfordert mehr Mathematik als nur eine einfache Massenkopie –

Verwandte Themen