2014-04-15 6 views
6

[WITH PARTIAL ANTWORT AKTUALISIERT]
Hier ist mein Code:Get Frame von Video mit libvlc smem und konvertieren Sie es zu opencv Mat. (C++)

void cbVideoPrerender(void *p_video_data, uint8_t **pp_pixel_buffer, int size) { 
    // Locking 
    imageMutex.lock(); 
    videoBuffer = (uint8_t *)malloc(size); 
    *pp_pixel_buffer = videoBuffer; 
} 
void cbVideoPostrender(void *p_video_data, uint8_t *p_pixel_buffer 
     , int width, int height, int pixel_pitch, int size, int64_t pts) { 
    // Unlocking 
    imageMutex.unlock(); 
    Mat img = Mat(Size(width,height), CV_8UC3, p_pixel_buffer); 
    //cvtColor(img,img,CV_RGB2BGR); 
} 
int main(int argc, char ** argv) 
{ 
    libvlc_instance_t * inst; 
    char smem_options[1000]; 
    sprintf(smem_options 
     , "#transcode{vcodec=RV24}:smem{" 
     "video-prerender-callback=%lld," 
     "video-postrender-callback=%lld," 
     "video-data=%lld," 
     "no-time-sync}," 
     , (long long int)(intptr_t)(void*)&cbVideoPrerender 
     , (long long int)(intptr_t)(void*)&cbVideoPostrender //This would normally be useful data, 100 is just test data 
     , (long long int)200 //Test data 
    ); 
    const char * const vlc_args[] = { 
       "-I", "dummy", // Don't use any interface 
       "--ignore-config", // Don't use VLC's config 
       "--extraintf=logger", // Log anything 
       "--verbose=1", // Be verbose 
       "--sout", smem_options // Stream to memory 
       }; 

    // We launch VLC 
    inst = libvlc_new(sizeof(vlc_args)/sizeof(vlc_args[0]), vlc_args); 
... 
return 0; 
} 

FRAGE AKTUALISIERT
Ich habe meine zwei Callback-Funktionen korrekt ausgeführt zu sein scheinen.
_Welche Daten werden von RV32 genau ausgegeben? Ist es die CV_8U3C passen (unsigned 8bits int 3-Kanal hier erforderlich _DO Ich brauche einen Schritt auf meine Matte Klasse hinzuzufügen (Schritt? - Anzahl der Bytes jeder Matrixzeile belegt)
Aktualisiertvor 2
Ich änderte RV32 zu RV24 Das macht mehr Sinn.Ich füge cvtColor hinzu, weil die MAT-Matrix BGR-Pixel und nicht RGB zu brauchen scheint, aber das Bild nicht korrekt angezeigt wird
_Ist da ein Vcodec, der mir ein YUV-Format als Ausgabe geben würde, damit ich das Pixel testen kann Daten vor dem Versuch, eine opencv ausgeben :: Mat img?
[EDIT OUTPUT IMG] (Durch Ändern vlc Typ zu CV_8UC4 vier Kanal (weiß nicht warum) können wir fast den Rahmen sehen, aber in wirklich schlechter Qualität Warum ist das so? img updated 2
[SOLUTION]
fand ich heraus, dass die Bilder am Anfang meines Videos von schlechter Qualität waren, deshalb ist meine Mat imshow() hat mir gezeigt, so hässlich, was der Code oben sollte nun funktionieren (Apperently nicht nötig cvtColor)

+0

afaik, die Pixel sind in p_pixel_buffer, nicht in p_video_data. auch, sollte nicht die Entsperrung() gehen * nach * Setzen der Mat-Pixel? – berak

+0

Ich hatte auch diesen Gedanken, aber wie gebe ich mein Pixel-Array an den Mat-Konstruktor? – grll

+0

auf die gleiche Weise, Sie tun es jetzt. Ändere einfach die Variablen – berak

Antwort

5

Zunächst eine kurze Warnung: Beginnend mit VLC2.2 (aktuelle git-Version, wird in Kürze veröffentlicht), ist der Größenparameter eine size_t. Es gibt keine API für smem (noch? Hoffentlich ändert sich das), die saugt, also würde dies Ihre Anwendung stumm brechen.

Dann ein kurzer Kommentar über den Parameter "Daten": Es sollte halten, was Sie für Ihre Verarbeitung benötigen. Da es sich um einen Zeiger auf eine Struktur handelt, eine Instanz einer Klasse, benennen Sie sie. Ich bezweifle stark, dass das Überschreiten einer langen Länge auf einer 32-Bit-Maschine funktionieren würde, da Sie 64 Bits in etwas erzwingen würden, das nur 32 enthalten kann. Sie sollten eine Struktur deklarieren und speichern, was Sie brauchen. Hier ein gutes Beispiel:

Über die Mutex-Nutzung sieht es gut für mich aus. Tatsächlich scheint es, dass Sie hier kein Concurrency-Problem haben, da Sie für jeden Frame synchron einen neuen Puffer zuweisen. Wenn Sie jedes Mal einen vorab zugewiesenen Puffer verwenden, müssen Sie beim Beenden der postrender-Funktion eine Sperrung in Betracht ziehen.

In der Tat bin ich nicht einmal sicher, was ist genau der Zeiger void p_video_data.

Das hängt von Ihrem Bildformat ab. Für H264 hängt dies vom Pixelformat ab, das vom Decoder ausgegeben wird. Da Sie nach der H264-Ausgabe fragen, ist es sehr wahrscheinlich, dass Sie ein planares Pixelformat erhalten, obwohl der genaue Typ von Ihrem H264-Profil abhängt.

Wenn Sie Rohdaten als Ergebnis erwarten (was so aussieht, als ob CV_8UC3 nach einem kurzen Blick auf Google auf ein 3-Kanal-Rohbild verweist), würde ich Ihnen empfehlen, zu RV32 zu wechseln : #transcode{vcodec=RV32}

Was müssen Sie mit dem Transcodierungsmodul zu übergeben ist Ihr Ausgang fourcc, wird VLC mit dem Eingang für Sie beschäftigen :)

aktualisieren

ich habe keine Ahnung, ob die Matte Klasse nimmt den Besitzer Ihres Zeigers, aber Sie könnten wa Das muss ich auch überprüfen.

Update 2

Um Ihre weitere Frage zu beantworten, was RV32 ist:

/* 24 bits RGB */ 
#define VLC_CODEC_RGB24   VLC_FOURCC('R','V','2','4') 
/* 24 bits RGB padded to 32 bits */ 
#define VLC_CODEC_RGB32   VLC_FOURCC('R','V','3','2') 
/* 32 bits RGBA */ 
#define VLC_CODEC_RGBA   VLC_FOURCC('R','G','B','A') 

Wenn Sie 3 Bytes erwarten nur, dann haben Sie wahrscheinlich einen Versuch RV24 sollte! Ich hätte das wahrscheinlich von Anfang an vorgeschlagen, da die 8CU3 definitiv nur 3 Bytes vorschlägt ...