Hallo, ich habe mal wieder ein kompliziertes Anliegen, und vor allem: keine Ahnung von der Materie.
Ich verwende Delphi 10.4.2 mit der aktuellen Version von dglOpenGL und glBitmap.
Aufgabe: Zeichne den Frame eines Videos als Textur.
Über die Demo-Version von FFMPEG http://www.delphiffmpeg.com kann ich z.B. mit der TFFDecoder-Komponente mir die einzelnen Frames meiner .mp4-Datei holen:
Code:
var
bmp: Graphics.TBitmap;
bmp32: TBitmap32;
begin
FFDecoder.Decode;
bmp := graphics.TBitmap.create;
FFDecoder.CopyToBitmap(bmp);
bmp32 := TBitmap32.Create;
bmp32.Assign(bmp);
FTextur.LoadFromBitmap32(bmp32);
FreeAndNil(bmp);
FreeAndNil(bmp32);
In diesem Beispiel hole ich mir den Frame über CopyToBitmap. In "bmp" ist dann schon alles gespeichert, was ich brauche. Jetzt noch einmal in TBitmap32 umwandeln (wenn ich die Textur mit TBitmap erstellen will, ist nix zu sehen??), das wird dann intern nochmal auf PowerOf2 vergrößert und dann hochgeladen, danach gerendet. Geht auch alles soweit.
Problem: Mit meiner Tech-Demo (Rendern alle 30ms über Timer) habe ich auf meinem High-End-System eine stete Prozessorlast von 25%, auf den PCs der potentiellen Kunden > 60%. Laut Support liegt das daran, das die Umwandlung in TBitmap sehr rechenaufwändig ist. Die reine "Player"-Demo vom Hersteller braucht ~ 2% Auslastung, was vollkommen okay wäre.
Zitat:
And CurrentFrame() will cost much more CPU for calculation. FFPlayer reads packets and decodes to YUV frames and then renders YUV frames via SDL. CurrentFrame() is just a convenience for Delphi to use TBitmap. YUV2RGB takes a lot of calculation. To CurrentFrame() is slow. And assigning a Bitmap to a Image also costs much more time then rendering YUV directly. (Hier ist zwar der FFPlayer genannt, nicht der o.g. FFDecoder, aber das Problem ist das gleiche.)
Da FFMpeg ja eh schon alles mit SDL darstellt, kann ich nicht irgendwie auf diese Textur oder "diesen Arbeitsspeicherbereich" zugreifen und das selbe Bild, was der Player rendert nochmal bei mir rendern lassen? Kann ich irgendwie die Textur-ID rausbekommen oder sowas? Verwendet mein Programm SDL? Keine Ahnung! Ich denke nicht. Ich kenne SDL nicht, habe nur schon mal davon gehört...
Der FFDecoder bietet "FFDecoder.GetBitmapPtr", was ein PBitmap zurück gibt. Kann man damit etwas anfangen? Ich bekomme zum Thema PBitmap + Delphi partout auch über Google nichts sinnvolles raus, und habe keine Ahnung, wie ich mit glBitmap oder notfalls nativ dglOpenGL daraus eine Textur erzeugen kann. Wahrscheinlich ist das nur ein Handle auf ein TBitmap, und es würde keinen Geschwindigkeitsvorteil bringen, selbst wenn ich darauf zugreifen könnte? Oder doch? Edit: Habe mittlerweile herausgefunden, dass ich über
Auf den Frame als Bitmap zugreifen kann. Dürfte aber letztendlich nichts anderes sein, als CurrentFrame(), was ja auch bei TBitmap zurück gibt. Von der Geschwindigkeit/Auslastung bringt es leider keine Besserung.
Der Support meint weiter:
Zitat:
Or use FFDecoder.FrameInfo.Picture to access the original decoded frames.
Upload data[1] and [2] in the same way but apply chroma subsamplings to width/height (e.g. uvwidth = (width + 1) >> 1). This code also assumes that you've created 3 textures in an array called texture[]. In your drawing loop, you can then refer to these texture ids to link them to uniform textures in your shaders, which you eventually use to draw. Shader examples that do YUV-to-RGB conversion can be found virtually anywhere.
Ich soll also drei Texturen erzeugen (wie auch immer sich dann die parameter unterscheiden sollen...) und dann in jedem Rendervorgang alle drei Texturen zeichnen... In welchem Blend/Wie-auch-Immer-Modus. Kann hier jemand mit einem Codebeispiel aushelfen?
Jetzt noch einmal in TBitmap32 umwandeln (wenn ich die Textur mit TBitmap erstellen will, ist nix zu sehen??), das wird dann intern nochmal auf PowerOf2 vergrößert und dann hochgeladen, danach gerendet. Geht auch alles soweit.
Warum Du das von TBitmap in TBitmap32 umwandelst verstehe ich nicht so ganz. Das wird aber auch kein Problem sein.
Könnte es aber auch sein, dass Deine PowerOf2 Vergrößerung sehr viel Prozessorlast kostet?
> Warum Du das von TBitmap in TBitmap32 umwandelst verstehe ich nicht so ganz. Das war nur ein kurzer Workaround, weil mein LoadFromBitmap() (ohne 32) kurzzeitig nicht funktioniert hatte, ist aber ein internes Problem und hat in der Tat nichts hiermit zu tun. Einfach ignorieren.
PowerOf2 erstellt einfach nur ein neues TBitmap(32) und in der Größe PowerOf2(Width bzw. Height) und zeichnet das Bild drauf, das kostet aber auch keine Zeit.
Was aktuell am meisten interessiert: Mit der oben im Edit verlinkten Seite: https://stackoverflow.com/questions/302 ... ing-opengl könnte ich ggf. direkt auf den Frame zugreifen. Aber ich schaffe es nicht, das in eine sinnvolle Renderanweisung umzuwandeln...
Hier ist noch ein Beispiel wie man den Frame in eine Textur bekommt, aber die verwenden SDL. Und ich wüsste wieder nicht, was ich alles mit SDL machen müsste (initialisieren, cleanup etc.), nur um diesen einen Frame so auszuwerten, dass ich ihn in OpenGL rendern kann...
Code:
function TForm1.queue_picture(var is_: PVideoState; pFrame: PAVFrame; pts:double):integer;
Genaues kann ich Dir da nicht sagen. Ich weiß auch nicht, was Du da gerade alles benutzt. Aber.. glBitmap von Bergmann hat da ein : LoadFromFunc(..) in der Klasse TglBitmapData damit könnte Deine Sache vllt gelöst werden.
Mitglieder in diesem Forum: 0 Mitglieder und 33 Gäste
Du darfst keine neuen Themen in diesem Forum erstellen. Du darfst keine Antworten zu Themen in diesem Forum erstellen. Du darfst deine Beiträge in diesem Forum nicht ändern. Du darfst deine Beiträge in diesem Forum nicht löschen. Du darfst keine Dateianhänge in diesem Forum erstellen.