Video aus Consolenoutput abspielen (pipe)

Für Probleme bezüglich Grafik, Audio, GL, ACS, ...
Antworten
Adromir
Beiträge: 37
Registriert: Sa 28. Apr 2018, 04:09

Video aus Consolenoutput abspielen (pipe)

Beitrag von Adromir »

Ich bastele gerade an einer GUI für die ADB Schnittstelle. Dazu spielt sich natürlich viel über die Kommandozeile ab und habe ich prinzipiel schon gelöst/realisert, bei einem Feature was ich gerne umsetzen würde, weiss ich aber nicht so richtig, ob das irgendwie realisierbar ist. Und zwar würde ich gerne den Bildschirm des Gerätes auf den PC spiegeln.

Ich weiß, daß es prinzipiel über die Befehlszeile möglich ist, z.B. so:

Code: Alles auswählen

adb shell screenrecord --output-format=h264 - | <player>


prinzipiell unterstützt werden mplayer, ffplay und VLC. Da ich mit dem Videostream aber auch noch was vorhabe um eine rudimentäre Fernsteuerung des Gerätes zu realiseren, müsste ich den Stream also Direkt n meinem Programm abspielen .. Ist das denn irgendwie möglich? Ich bräuchte da ein paar Anregungen, am besten wäre natürlich wenn man die Datei aus STDOUT direkt abspielen könnte. Ansonsten wäre meine Idee diesen Stream in eine Datei umzuleiten und dann diese Abzuspielen. Wie könnte das grob funktionieren?

Warf
Beiträge: 1907
Registriert: Di 23. Sep 2014, 17:46
OS, Lazarus, FPC: Win10 | Linux
CPU-Target: x86_64

Re: Video aus Consolenoutput abspielen (pipe)

Beitrag von Warf »

Musst du das wirklich in deinem Programm abspielen, oder reicht es nicht wenn dein Programm eine mediaplayer Instanz ausführt welche das video abspielt? Dann würde ich einfach mit TProcess einen VLC prozess ausführen und den output von adb einfach an den VLC prozess übergeben.

Ansonsten schau mal hier: Link

Wenn du den Output einfach in eine FiFo pipest:

Code: Alles auswählen

$ mkfifo buffer.fifo
$ adb shell screenrecord --output-format=h264 - 1> buffer.fifo 2> /dev/null

müsstest du einfach mit der VLC mediaplayer komponente oder ähnlichen die datei buffer.fifo abspielen können.

Denk aber dran unter Linux haben Pipes (und damit auch Fifos) standardmäßig eine maximalgröße von 64k. Normalerweise kann man diese mit fnctl auf bis zu 1m erhöhen, mit sudo access sogar auf 32m, mehr geht aber nicht. Daher würde ich nicht so lang zwischen dem erstellen der Fifo und dem starten von VLC warten, damit VLC so früh wie möglich beginnt die daten aus dem FIFO zu lesen. (Unter Windows keine Ahnung)

Adromir
Beiträge: 37
Registriert: Sa 28. Apr 2018, 04:09

Re: Video aus Consolenoutput abspielen (pipe)

Beitrag von Adromir »

Also wenn ich ein reines Screen mirroring mache, dann reicht auch eine VLC/sonstige Instanz. Da ich das aber gerne für eine "fernsteuerung" benutzen würde, müsste ich das in einem Fenster ausführen, in dem ich irgendwie auslesen kann, wohin (im video fenster) der User mit der mouse hingeklickt hat. Zudem würde ich das gerne mit so wenig Abhängigkeiten realisieren, die der Nutzer installieren mus

Warf
Beiträge: 1907
Registriert: Di 23. Sep 2014, 17:46
OS, Lazarus, FPC: Win10 | Linux
CPU-Target: x86_64

Re: Video aus Consolenoutput abspielen (pipe)

Beitrag von Warf »

Für welche Plattform soll es denn sein? Denn wenn es auf Linux laufen soll musst du wohl FFmpeg oder VLC verwenden. Für windows gibt es glaube ich mehr Optionen, da kenn ich mich aber nicht so gut mit aus.

Ich würde empfehlen mal die VLC Mediaplayer Komponente anzuschauen und das ganze über fifos in vlc zu laden.

Unter Linux/unix wäre es z.B.

Code: Alles auswählen

uses BaseUnix, Unix, process, asyncprocess;
procedure TForm1.StartStream;
begin
  FAdbProc.Executable:='adb';
  // eventuell noch FAdbProc.Paramets füllen
  FAdbProc.OnReadData:=@ReadData;
  FAdbProc.OnTerminate:=@AdbTerminate;
  FAdbProc.Options += [poUsePipes];
  // pipe erstellen und öffnen
  FpMkfifo('buffer.fifo', &600);
  FBufferFile := TFileStream.Create('buffer.fifi', fmOpenWrite);
{$IFDEF LINUX}
  // pipe vergrößern
  FpFcntl(FBufferFile.Handle, F_SETPIPE_SZ, 1048576);
{$ENDIF}
  FAdbProc.Execute;
  Player.Play('buffer.fifo')
end;
 
procedure TForm1.FormCreate(Sender: TObject);
begin
  FAdbProc := TAsyncProcess.Create(self);
end;
 
procedure TForm1.StopStream;
begin
  FAdbProc.Terminate;
end;
 
procedure TForm1.ReadData(Sender: TObject);
var buff: array[0..511] of Byte;
  len: Integer;
begin         
    // daten in pipe schreiben
  while FAdbProc.Output.NumBytesAvailable > 0 do
  begin
    len := FAdbProc.Output.Read(buff[0], SizeOf(buff));
    FBufferFile.WriteBuffer(buff[0], len);
  end;
end;
 
procedure TForm1.AdbTerminate(Sender: TObject);
begin
  // pipe schließen -> EOF in pipe
  FBufferFile.Free;
end;
 
procedure TForm1.Form1Destroy(Sender: TObject);
begin
  // fifo freigeben
  fpunlink('buff.fifo');
end;


Sollte so ähnlich auch für Windows gehen, da musst du dir einfach mal die MSDN Dokumentation für FiFos/named pipes durchlesen

Adromir
Beiträge: 37
Registriert: Sa 28. Apr 2018, 04:09

Re: Video aus Consolenoutput abspielen (pipe)

Beitrag von Adromir »

Herzlichen Dank. Primäres system wäre windows, ich möchte es aber crossfähig erstellen. Aller herzlichen dank, das hilft mir sehr weiter, da hast du sogar direct ne Frage beantwortet die mir zwischenzeitlich kam *daumen hoch*

Adromir
Beiträge: 37
Registriert: Sa 28. Apr 2018, 04:09

Re: Video aus Consolenoutput abspielen (pipe)

Beitrag von Adromir »

Ich hab mir gerade oberflächlich PasLibVlc angeschaut. Wenn ich das changelog richtig interpretiere unterstützt das ab der neuesten Version das abspielen eines TStreams.. Vielleicht ist das ne blöde frage, aber könnte das dann gehen? Den Output in einen TStream schreiben und den dann abspielen?

Warf
Beiträge: 1907
Registriert: Di 23. Sep 2014, 17:46
OS, Lazarus, FPC: Win10 | Linux
CPU-Target: x86_64

Re: Video aus Consolenoutput abspielen (pipe)

Beitrag von Warf »

Adromir hat geschrieben:Ich hab mir gerade oberflächlich PasLibVlc angeschaut. Wenn ich das changelog richtig interpretiere unterstützt das ab der neuesten Version das abspielen eines TStreams.. Vielleicht ist das ne blöde frage, aber könnte das dann gehen? Den Output in einen TStream schreiben und den dann abspielen?


Das macht das ganze sogar noch ne ecke einfacher, denn bei UsePipes ist Output (und input) ein TStream:

Code: Alles auswählen

  FAdbProc := TProcess.Create;
  FAdbProc.Executeable := 'adb';
  FadbProc.Patameters.Delimiter := ' ';
  FAdbProc.Parameters.DelimittedText := 'shell screenrecord --output-format=h264 -';
  FadbProc.Options += [poUsePipes];
  FadbProc.Execute;
  Player.PlayFromStream(FAdbProc.Output);

Adromir
Beiträge: 37
Registriert: Sa 28. Apr 2018, 04:09

Re: Video aus Consolenoutput abspielen (pipe)

Beitrag von Adromir »

Das Wäre natürlich Super. Jedenfalls lese ich das aus dieser Zeile im Changelog heraus:

Add support for media callbacks

new procedure:

procedure Play(stm : TStream, ...); overload;


Aber muss mir da noch den Code genauer anschauen.

Antworten