Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Algorithmen, Datenstrukturen und Klassendesign (https://www.delphipraxis.net/78-algorithmen-datenstrukturen-und-klassendesign/)
-   -   Bitmaps als AVI-Vido / MPEG-Video speichern (https://www.delphipraxis.net/198115-bitmaps-als-avi-vido-mpeg-video-speichern.html)

Harry Stahl 4. Okt 2018 17:32

Bitmaps als AVI-Vido / MPEG-Video speichern
 
In einem anderen Thread wurde kürzlich einmal die Frage gestellt, wie man einen (bewegten) Bildschirminhalt auf einem anderen PC einfängt und auf den eigenen PC überträgt (um ihn dann u.U. auch als Video zu speichern).

Dieses "als Video speichern" würde mich auch näher interessieren.

KodeZwerg hatte da mal die Anmerkung gemacht:

"Avi Container mit JPEGs füttern, ob nun 5FPS oder was auch immer, das ist jedenfalls relativ einfach umzusetzen und verbraucht nicht viel resourcen/bandweite."
Die von Ihm genannte Komponente "Avi-Writer" konnte ich hier aber leider nicht installieren.

Hat jemand dazu evtl. eine Information oder einen Link oder ein kurzes Beispiel, wie man Bitmaps, die in der Anzahl so zwischen 5 und 20 pro Sekunde zur Verfügung gestellt werden könnten, in eine AVI-Datei (oder als MPEG) Datei speichern kann?

Oder ist es doch nicht so relativ einfach?

Delphi.Narium 4. Okt 2018 18:00

AW: Bitmaps als AVI-Vido / MPEG-Video speichern
 
Die Komponente TAviWriter nutzt die avifil32.dll. Dies enthält aber nicht immer die Prozedur AVIFileInitW, sondern (bei älteren Windosen) "nur" AVIFileInit.

Eventuell reicht es aus, den Quelltext der Komponente entsprechend anzupassen.

Aus
Delphi-Quellcode:
procedure AVIFileInit; stdcall; external 'avifil32.dll' name 'AVIFileInitW';
müsste dann
Delphi-Quellcode:
procedure AVIFileInit; stdcall; external 'avifil32.dll' name 'AVIFileInit';
werden.

Da AVIFileInit ohne irgendwelche Parameter aufgerufen wird, könnte es eventuell klappen. Kommt halt auf 'nen Versuch an.

Doku dazu: https://docs.microsoft.com/en-us/win...fw-avifileinit
https://docs.microsoft.com/de-de/win...file-functions

Quelltext bmp2avi: http://read.pudn.com/downloads110/so...2avi.pas__.htm

Ydobon 4. Okt 2018 20:27

AW: Bitmaps als AVI-Vido / MPEG-Video speichern
 
16 Jahre alt und Delphi 6. Funktioniert überraschenderweise aber anscheinend sogar noch. Verwendet die vfw.pas der JVCL. Und wohl nur als Ideengeber geeignet. Für andere Container wird es dann komplizierter.

Delphi-Quellcode:
var dir: String;
    ts: TSearchRec;
    datlist: TStringList;
    tfs: TFileStream;
    pfile: IAVIFile;
    pavi: IAVIStream;
    psi: TAVISTREAMINFO;
    Bfi: BITMAPFILEHEADER;
    bmi: PBITMAPINFO;
    bits: PByteArray;
    i, bmisize: Integer;
begin
  if Not SelectDirectory('Bitmapverzeichnis wählen', 'c:', dir) then Exit;
  if FindFirst(dir+'\*.bmp', faAnyFile, ts)<>0 then Exit;
  if Not SaveDialog1.Execute then Exit;
  datlist:=TStringList.Create;
  try
    datlist.Add(ts.Name);
    while FindNext(ts)=0 do datlist.Add(ts.Name);
    datlist.Sort;
  finally
    FindClose(ts);
  end;
  Label1.Caption:=IntToStr(datlist.Count);
  tfs:=TFileStream.Create(dir+'\'+datlist[0], fmOpenRead);
  tfs.Read(bfi, SizeOf(BITMAPFILEHEADER));
  bmisize:=bfi.bfOffBits-SizeOf(BITMAPFILEHEADER);
  GetMem(bmi, bmisize);
  tfs.Read(bmi^, bmisize);
  GetMem(bits, bmi.bmiHeader.biSizeImage);
  tfs.Read(bits^, bmi^.bmiHeader.biSizeImage);
  AVIFileInit;
  AVIFileOpen(pfile, PChar(SaveDialog1.FileName), OF_CREATE OR OF_WRITE, NIL);
  ZeroMemory(@psi, SizeOf(TAVIStreamInfo));
  with psi do
  begin
    fccType:=streamtypeVIDEO;
    fccHandler:=mmioFourcc(#0, 'D', 'I', 'B');
    dwScale:=1;
    dwRate:=25;
    dwLength:=datlist.Count;
    dwSuggestedBufferSize:=bmi.bmiHeader.biSizeImage;
    rcFrame:=Rect(0, 0, bmi.bmiHeader.biWidth, bmi.bmiHeader.biHeight);
    szName:='Noname';
    dwQuality:=$FFFFFFFF;
    dwSampleSize:=bmi.bmiHeader.biSizeImage;
  end;
  AVIFileCreateStream(pfile, pavi, psi);
  AVIStreamSetFormat(pavi, 0, bmi, bmisize);
  For i:=0 to datlist.Count-1 do
  begin
    AVIStreamWrite(pavi, i, 1, bits, bmi.bmiHeader.biSizeImage, AVIIF_KEYFRAME, NIL, NIL);
    tfs.Free;
    tfs:=TFileStream.Create(dir+'\'+datlist[i], fmOpenRead);
    Image1.Picture.Bitmap.LoadFromStream(tfs);
    tfs.Seek(bfi.bfOffBits, soFromBeginning);
    tfs.Read(bits^, bmi.bmiHeader.biSizeImage);
    Label2.Caption:=IntToStr(i+1);
    Application.ProcessMessages;
  end;
  tfs.Free;
  FreeMem(bits);
  datlist.Free;

KodeZwerg 4. Okt 2018 20:31

AW: Bitmaps als AVI-Vido / MPEG-Video speichern
 
Ich habe ein lauffähiges Demo hier in DP gefunden, also BMP2AVI, geschrieben von turboPASCAL.

Für mein Delphi 2010 musste ich folgende Änderung vornehmen damit es erstmal überhaupt funktioniert, es hat noch Probleme und Speicherleks, aber die Grundsubstanz funktioniert.
Datei: CreateAVI.pas
Zeile: 198
ist nun:
Delphi-Quellcode:
    if AVIFileOpenW(pfile, PWideChar(WideString(WorkFile)), OF_WRITE or OF_CREATE, nil) <> AVIERR_OK then


edit
Ps: vorher war die Zeile
Delphi-Quellcode:
    if AVIFileOpen(pfile, PChar(WorkFile), OF_WRITE or OF_CREATE, nil) <> AVIERR_OK then
aber der Compiler hat immer die Ansi Version genommen und beim String abgekackt. Da ist wieder so was was ich nicht verstehe obwohl ja PChar und keine A/W angegeben war nimmt der intern bei mir die A variante...... (Workfile : String; falls ihr das fragen/sagen wollt)

Harry Stahl 4. Okt 2018 21:46

AW: Bitmaps als AVI-Vido / MPEG-Video speichern
 
Hey KodeZwerg, herzlichen Dank für Deinen Einsatz.:thumb:

Funktioniert hier auch unter Delphi 10.2.3.

KodeZwerg 4. Okt 2018 21:59

AW: Bitmaps als AVI-Vido / MPEG-Video speichern
 
Ja gern geschehn, aber halt Windows vorbehalten (Video for Windows).
Bei der AviWriter komponente habe ich mal reingeschaut (zuletzt kam es mit Delphi 7 zum Einsatz), ja die Init abändern wie oben vorgeschlagen.
Ich habe es auf die schnelle nicht zum laufen bekommen, aber wenn die VfW Variante Dir erstmal genug Reiz bietet, belasse ich es dabei.


Ps: Musstest Du es wie ich auch abändern oder lief es out-of-box?

Harry Stahl 4. Okt 2018 22:46

AW: Bitmaps als AVI-Vido / MPEG-Video speichern
 
Ja, musste es abändern...

EWeiss 4. Okt 2018 22:59

AW: Bitmaps als AVI-Vido / MPEG-Video speichern
 
Zitat:

Zitat von Harry Stahl (Beitrag 1414923)
Ja, musste es abändern...

Das ist was ich vermisse das ihr euch bei anderen bedient aber die Änderungen (Fehlerbehebung) hier nicht hochladen tut damit andere auch davon profitieren können ;)
Die müssen jetzt raten, was geändert wurde.
Ich brauche es nicht aber vielleicht andere!

gruss

Harry Stahl 4. Okt 2018 23:03

AW: Bitmaps als AVI-Vido / MPEG-Video speichern
 
@Eiweiss: KodeZwerg hat es doch in Beitrag 4 beschrieben, was er (und dann auch ich) geändert hat...

EWeiss 4. Okt 2018 23:04

AW: Bitmaps als AVI-Vido / MPEG-Video speichern
 
Zitat:

Zitat von Harry Stahl (Beitrag 1414926)
@Eiweiss: KodeZwerg hat es doch in Beitrag 4 beschrieben, was er (und dann auch ich) geändert hat...

Nur bei ihm hat es ja nicht funktioniert ;)
Zitat:

es hat noch Probleme und Speicherleks, aber die Grundsubstanz funktioniert.
gruss

KodeZwerg 4. Okt 2018 23:06

AW: Bitmaps als AVI-Vido / MPEG-Video speichern
 
Liste der Anhänge anzeigen (Anzahl: 1)
Ich schrieb doch a) welche Datei und b) welche Zeile

Im Anhang für Leute die mich nicht Verstanden haben das komplette Projekt so wie es bei mir gerade läuft.

Eventuell EurekaLog auskommentieren, das hab ich nachträglich aktiviert.

Danke Harry, hast Du ne Antwort WARUM man es ändern muss? Weil in nem anderen Thread mir wiederholt auf ohne A/W und PChar als das einzig Wahre. Worin liegt da nun der Fehler?

EWeiss 4. Okt 2018 23:10

AW: Bitmaps als AVI-Vido / MPEG-Video speichern
 
Zitat:

Ich schrieb doch a) welche Datei und b) welche Zeile
Nun ja Papier (oder hier Beiträge sind geduldig)..

Dein Beitrag!
Zitat:

es hat noch Probleme und Speicherleks, aber die Grundsubstanz funktioniert.
Nun in dem fall sind die Fehler nicht behoben.

gruss

KodeZwerg 4. Okt 2018 23:17

AW: Bitmaps als AVI-Vido / MPEG-Video speichern
 
Das ist korrekt. (das da noch Probleme enthalten sind)

Alles nicht super stabil plus EurekaLogs "hat Speicherleks" Anzeige der ich jetzt noch nicht weiter nachgegangen bin.

Ich konnte jedenfalls erfolgreich aus den Samples ein Avi erstellen.


Ps:
Ich bin der Meinung, das die Fehler nur in dem Demo-Programm, was die Demo sich selbst betrifft angehen.
Also was die VfW Anbindung betrifft, die scheint gut zu sein aber sobald man in Gui darauf lesend zugreift, da treten Fehler auf, in Demo-Gui, nicht VfW.

Harry Stahl 4. Okt 2018 23:45

AW: Bitmaps als AVI-Vido / MPEG-Video speichern
 
Zitat:

Zitat von KodeZwerg (Beitrag 1414928)
Ich schrieb doch a) welche Datei und b) welche Zeile

Im Anhang für Leute die mich nicht Verstanden haben das komplette Projekt so wie es bei mir gerade läuft.

Eventuell EurekaLog auskommentieren, das hab ich nachträglich aktiviert.

Danke Harry, hast Du ne Antwort WARUM man es ändern muss? Weil in nem anderen Thread mir wiederholt auf ohne A/W und PChar als das einzig Wahre. Worin liegt da nun der Fehler?

Ja, in dem Fall ist es klar:

In der VFW.pas unit gibt es ganz am Anfang ein

Delphi-Quellcode:
{$UNDEF UNICODE}
und weiter unten ein

Delphi-Quellcode:
{$IFDEF UNICODE}
function   AVIFileOpen(var ppfile: IAVIFile; szFile: LPCWSTR; uMode: UINT; lpHandler: PCLSID): HResult; stdcall;
{$ELSE}
function   AVIFileOpen(var ppfile: IAVIFile; szFile: LPCSTR; uMode: UINT; lpHandler: PCLSID): HResult; stdcall;
{$ENDIF}
daher wird in Deinem Unicode-Delphi mit "AVIFileOpen" die untere Funktion aufgerufen, wo dann in dem Ursprungscode ein Widestring an eine Funktion übergeben wird, die einen Pointer of Ansistring erwartet.

Unter einem Delphi 2007 müsste der Code daher direkt compilieren.

Man hätte alternativ auch

Delphi-Quellcode:
if AVIFileOpen(pfile, PAnsichar(AnsiString(WorkFile)), OF_WRITE or OF_CREATE, nil) <> AVIERR_OK then
machen können, das kompiliert und hätte mit normalen Dateinamen auch funktioniert, aber eben nicht mit Unicode-Dateinamen.

Insofern ist Deine Lösung korrekt hier.

Evtl. könnte aber noch besser sein, das Undef Unicode zu entfernen (dann stimmt der Original-Code wieder hier, nur unter TAVICreator muss man

Delphi-Quellcode:
asi: TAVIStreamInfoA; in asi: TAVIStreamInfoW; ändern.
Vielleicht funktionierts dann insgesamt besser, aber das war jetzt nur ein kurzer Blick drauf, muss ich mir noch genauer ansehen...

KodeZwerg 4. Okt 2018 23:53

AW: Bitmaps als AVI-Vido / MPEG-Video speichern
 
Ja das brachte mich total durcheinander, ich sah ja auch die {$IFDEFs} und wunderte mich, warum zum Henker nimmt der da Ansi anstelle wie vom Compiler vorgegeben Wide.
Nach einem {$UNDEF} zu schauen, darauf muss man erstmal kommen, super Lösung, UNDEF raus und zurück zum original source.
bzw erstmal in VfW.pas gucken was davon noch betroffen ist :)

Ydobon 5. Okt 2018 00:53

AW: Bitmaps als AVI-Vido / MPEG-Video speichern
 
Warum nehmt ihr nicht einfach eine Version der vfw.pas, die mit Unicode Delphi klar kommt? Dann stört im TAVICreator nur noch die Festlegung von asi als AnsiVersion. Die einzige Änderung ist dann von TAVIStreamInfoA das "A" zu entfernen.

KodeZwerg 5. Okt 2018 12:01

AW: Bitmaps als AVI-Vido / MPEG-Video speichern
 
Danke für den Hinweis Ydobon!

Rollo62 5. Okt 2018 13:03

AW: Bitmaps als AVI-Vido / MPEG-Video speichern
 
Vielleicht hilft das hier auch noch um zu sehen wie es angewendet wird.
Ist zwar kein Delphi, aber naja ...


Alle Zeitangaben in WEZ +1. Es ist jetzt 22:02 Uhr.

Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz