AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Multimedia Delphi Video aus (Teil-)Stream abspielen
Thema durchsuchen
Ansicht
Themen-Optionen

Video aus (Teil-)Stream abspielen

Offene Frage von "dominikkv"
Ein Thema von dominikkv · begonnen am 26. Feb 2010 · letzter Beitrag vom 4. Mär 2010
Antwort Antwort
dominikkv

Registriert seit: 30. Sep 2006
Ort: Gundelfingen
1.109 Beiträge
 
Delphi 2007 Professional
 
#1

Video aus (Teil-)Stream abspielen

  Alt 26. Feb 2010, 15:23
Hallo,

ich suche eine Möglichkeit, ein Video aus einem Stream heraus abzuspielen. Ich habe eine Datei, in der mehrere Videos hintereinander angehängt sind, die unterschiedliche Formate und Codexe haben, aus der ich nun zB Video Nr 3 abspielen will.

Erste Frage: gibt es Komponenten, die ein Abspielen aus einem Stream heraus ermöglichen? Ein Vor-/Zurückspulen bzw an eine bestimmte Position springen sollten möglich sein.

Zweite Frage: mit welchem Stream mache ich das am besten? Weil ein TFileStream geht ja über die komplette Datei, ich will aber nur einen Teil davon als eigenständigen Stream betrachten, und ein TMemoryStream kopiert ja den Inhalt in den Speicher, was ich bei Videos und den damit verbundenen Dantenmengen vermeiden will.

Vielen Dank für eure Antworten
Dominik
Dominik
Wer anderen eine Grube gräbt, hat ein Gruben-Grab-Gerät!
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
43.116 Beiträge
 
Delphi 12 Athens
 
#2

Re: Video aus (Teil-)Stream abspielen

  Alt 26. Feb 2010, 16:06
Mal was Billiges:
Delphi-Quellcode:
Type TStreamPart = Class(TStream)
  Private
    _Stream: TStream;
    _Offset, _Len: Int64;
  Protected
    Function GetSize: Int64; Override;
    Procedure SetSize(NewSize: LongInt); Overload; Override;
    Procedure SetSize(Const NewSize: Int64); Overload; Override;
  Public
    Constructor Create(Stream: TStream; Const Start, Length: Int64);
    Function Read(Var Buffer; Count: LongInt): LongInt; Override;
    Function Write(Const Buffer; Count: LongInt): LongInt; Override;
    Function Seek(Offset: LongInt; Origin: Word): LongInt; Overload; Override;
    Function Seek(Const Offset: Int64; Origin: TSeekOrigin): Int64; Overload; Override;
  End;

Function TStreamPart.GetSize: Int64;
  Begin
    Result := Min(Max(_Stream.Size - _Offset, 0), _Len);
  End;

Procedure TStreamPart.SetSize(NewSize: LongInt);
  Begin
    SetSize(Int64(NewSize));
  End;

Procedure TStreamPart.SetSize(Const NewSize: Int64);
  Begin
    Raise Exception.Create('read only');
  End;

Constructor TStreamPart.Create(Stream: TStream; Const Start, Length: Int64);
  Begin
    _Stream := Stream;
    _Offset := Start;
    _Len := Length;
  End;

Function TStreamPart.Read(Var Buffer; Count: LongInt): LongInt;
  Begin
    Result := _Stream.Read(Buffer, Min(Int64(Count), Size - Position));
  End;

Function TStreamPart.Write(Const Buffer; Count: LongInt): LongInt;
  Begin
    Result := _Stream.Write(Buffer, Min(Int64(Count), Size - Position));
  End;

Function TStreamPart.Seek(Offset: LongInt; Origin: Word): LongInt;
  Begin
    Result := _Stream.Seek(LongInt(Min(Max(Int64(Offset), 0) + _Offset, MaxInt)), Origin);
  End;

Function TStreamPart.Seek(Const Offset: Int64; Origin: TSeekOrigin): Int64;
  Begin
    Result := _Stream.Seek(Max(Offset, 0) + _Offset, Origin);
  End;
Delphi-Quellcode:
Var X: TStream;

X := TStreamPart.Create(MyFileStream, 1000, 10);
Und schon hat man einen neuen Stream, welcher einen Teil eines anderen Streams liefert.
In diesem Fall z.B. die Bytes 1000 bis 1009 von einem FileStream.
(falls ich mich jetzt nicht verdacht hab)
Garbage Collector ... Delphianer erzeugen keinen Müll, also brauchen sie auch keinen Müllsucher.
my Delphi wish list : BugReports/FeatureRequests
  Mit Zitat antworten Zitat
dominikkv

Registriert seit: 30. Sep 2006
Ort: Gundelfingen
1.109 Beiträge
 
Delphi 2007 Professional
 
#3

Re: Video aus (Teil-)Stream abspielen

  Alt 26. Feb 2010, 17:40
Hallo himitsu,

vielen Dank für deine Hilfe. Ich habe mir den Code von dir mal genauer angeschaut und glaube, bei dir hat sich ein Fehler eingeschlichen. Für .Read und .Write benutzt du .Size und .Position der Basisklasse, außerdem wird bei .Seek der Offset falsch berechnet.
Delphi-Quellcode:
Function TStreamPart.Read(Var Buffer; Count: LongInt): LongInt;
  Begin
    Result := _Stream.Read(Buffer, Min(Int64(Count), _Len - (_Stream.Position - _Offset)));
  End;

Function TStreamPart.Write(Const Buffer; Count: LongInt): LongInt;
  Begin
    Result := _Stream.Write(Buffer, Min(Int64(Count), _Len - (_Stream.Position - _Offset)));
  End;

Function TStreamPart.Seek(Offset: LongInt; Origin: Word): LongInt;
  Begin
    case TSeekOrigin(Origin) of
      soBeginning: Result := _Stream.Seek(LongInt(Min(Max(Int64(Offset), 0) + _Offset, MaxInt)), Origin);
      soCurrent: Result := _Stream.Seek(LongInt(Min(Max(Int64(Offset), 0) , MaxInt)), Origin);
      soEnd: Result := _Stream.Seek(LongInt(Min(Max(Int64(Offset), 0) + _Stream.Size - (_Offset + _Len), MaxInt)), Origin);
    end;
  End;

Function TStreamPart.Seek(Const Offset: Int64; Origin: TSeekOrigin): Int64;
  Begin
    case Origin of
      soBeginning: Result := _Stream.Seek(LongInt(Min(Max(Offset, 0) + _Offset, MaxInt)), Origin);
      soCurrent: Result := _Stream.Seek(LongInt(Min(Max(Offset, 0) , MaxInt)), Origin);
      soEnd: Result := _Stream.Seek(LongInt(Min(Max(Offset, 0) + _Stream.Size - (_Offset + _Len), MaxInt)), Origin);
    end;
  End;
So müsste das stimmen, oder?

Und hat jemand eine Idee, wie ich diesen Stream nun wiedergeben kann?
Dominik
Wer anderen eine Grube gräbt, hat ein Gruben-Grab-Gerät!
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
43.116 Beiträge
 
Delphi 12 Athens
 
#4

Re: Video aus (Teil-)Stream abspielen

  Alt 26. Feb 2010, 20:38
Mit dem Seek hast du Recht, obwohl ich jetzt auf die Schnelle nicht sagen kann, ob es so nun stimmt,
aber ich hat so das Gefühlt, daß dem leider nicht so ist.

Beim Read und Write war es schon richtig, daß die Grenzen des abgeleiteten Streams genutzt wurden.


Dieses Wochenende hab ich kaum Zeit, so werd' ich wohl erst nächste Woche nochmal genauer nachsehn können.

Zitat von dominikkv:
Und hat jemand eine Idee, wie ich diesen Stream nun wiedergeben kann?
theoretisch mit einer Mediaplayer-Komponente, welche über einen Stream abspielen kann.
Garbage Collector ... Delphianer erzeugen keinen Müll, also brauchen sie auch keinen Müllsucher.
my Delphi wish list : BugReports/FeatureRequests
  Mit Zitat antworten Zitat
Benutzerbild von Luckie
Luckie

Registriert seit: 29. Mai 2002
37.621 Beiträge
 
Delphi 2006 Professional
 
#5

Re: Video aus (Teil-)Stream abspielen

  Alt 26. Feb 2010, 20:58
Aber ob das bei einem Video Stream klappt, halte ich für fraglich, da die Headerdaten fehlen. Er müsste dann noch die passenden Headerdaten für den Teilstream generieren, um ihn abspielen zu können.
Michael
Ein Teil meines Codes würde euch verunsichern.
  Mit Zitat antworten Zitat
dominikkv

Registriert seit: 30. Sep 2006
Ort: Gundelfingen
1.109 Beiträge
 
Delphi 2007 Professional
 
#6

Re: Video aus (Teil-)Stream abspielen

  Alt 26. Feb 2010, 21:46
Danke, himitsu, ich werde das mal testen. Aber .Position und .Size von der Basisklasse wird doch überhaupt nicht initialisiert, oder verstehe ich das falsch? Wir leiten ja nur von TStream ab, damit sich die Klasse "Stream" nennen darf.
Zitat von Luckie:
Aber ob das bei einem Video Stream klappt, halte ich für fraglich, da die Headerdaten fehlen. Er müsste dann noch die passenden Headerdaten für den Teilstream generieren, um ihn abspielen zu können.
Hmm die Headerinformationen müssten ja da sein, weil die große Datei aus mehreren Einzelvideos besteht, die, wenn man sie wieder einzeln als Datei speichern würde, normal abspielbar sind. Oder bekommt der Mediaplayer (MPlayer.TMediaPlayer?) die Headerinformationen nicht aus dem Stream?
Dominik
Wer anderen eine Grube gräbt, hat ein Gruben-Grab-Gerät!
  Mit Zitat antworten Zitat
Benutzerbild von Luckie
Luckie

Registriert seit: 29. Mai 2002
37.621 Beiträge
 
Delphi 2006 Professional
 
#7

Re: Video aus (Teil-)Stream abspielen

  Alt 26. Feb 2010, 21:52
Ach so, das ist natürlich was anderes. Das sind schon aneinander gehangene einzelne Videos?
Michael
Ein Teil meines Codes würde euch verunsichern.
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
43.116 Beiträge
 
Delphi 12 Athens
 
#8

Re: Video aus (Teil-)Stream abspielen

  Alt 27. Feb 2010, 06:22
Size kommt über GetSize, welches auf dem QuellStream die Größe ausließt und begrenzt.

Position wird über Seek berechnet ... dort führt der TStream einen Seek(0) auf die aktuelle Position aus und Seek liefert ja dann als Ergebnis die Position, auf welche verschoben wurde, also die aktuelle Position, da ja nicht wirklich verschoben wurde.
Garbage Collector ... Delphianer erzeugen keinen Müll, also brauchen sie auch keinen Müllsucher.
my Delphi wish list : BugReports/FeatureRequests
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
43.116 Beiträge
 
Delphi 12 Athens
 
#9

Re: Video aus (Teil-)Stream abspielen

  Alt 1. Mär 2010, 09:03
Soo, ich glaub jetzt dürfte es soweit stimmen.

'ne Positionsprüfung bei Read- und Write-Zugriffen gibt's nun,
denn der Zugriff über den "Hauptstream" existiert ja weiterhin, so daß von dort aus auch was geändert werden könnte, welches so jetzt abgefangen wird.

In .Create wird der Hauptstream absichtlich nicht geprüft, denn Assigned(Stream) würde nur den einen Fall eines NIL-Pointers abgefangen, aber eine ungültige Objektvariable kann einfach nicht mit Sicherheit erkannt werden.

Die Streamgröße kann nun auch geändert werden, aber nur wenn der TeilStream am Ende des Hauptstreams liegt und somit nichts Nachfolgendes gelöscht werden könnte.

Und das Wichtigste: Das fehlerhafte Seek/Position wurde überarbeitet.

Delphi-Quellcode:
Unit StreamPart;

Interface
  Uses SysUtils, Classes, Math;

  Type TStreamPart = Class(TStream)
    Private
      _Stream: TStream;
      _Offset, _MaxLen: Int64;
    Protected
      Function GetSize: Int64; Override;
      Procedure SetSize(NewSize: LongInt); Overload; Override;
      Procedure SetSize(Const NewSize: Int64); Overload; Override;
    Public
      Constructor Create(Stream: TStream; Const Offset, MaxLength: Int64);
      Function Read(Var Buffer; Count: LongInt): LongInt; Override;
      Function Write(Const Buffer; Count: LongInt): LongInt; Override;
      Function Seek(Offset: LongInt; Origin: Word): LongInt; Overload; Override;
      Function Seek(Const Offset: Int64; Origin: TSeekOrigin): Int64; Overload; Override;
    End;

Implementation

  Function TStreamPart.GetSize: Int64;
    Begin
      Result := Min(Max(_Stream.Size - _Offset, 0), _MaxLen);
    End;

  Procedure TStreamPart.SetSize(NewSize: LongInt);
    Begin
      SetSize(Int64(NewSize));
    End;

  Procedure TStreamPart.SetSize(Const NewSize: Int64);
    Begin
      If _Stream.Size <= _Offset + _MaxLen Then
        _Stream.Size := _Offset + NewSize
      Else Raise Exception.Create('The StreamPart must lie at the '
          + 'end of the main stream to change its size to be allowed.');
    End;

  Constructor TStreamPart.Create(Stream: TStream; Const Offset, MaxLength: Int64);
    Begin
      _Stream := Stream;
      _Offset := Offset;
      _MaxLen := MaxLength;
    End;

  Function TStreamPart.Read(Var Buffer; Count: LongInt): LongInt;
    Var Pos: Int64;

    Begin
      Pos := _Stream.Position;
      If (Pos < _Offset) or (Pos >= _Offset + _MaxLen) Then
        Raise Exception.Create('The .Position is out of range.');
      Result := _Stream.Read(Buffer, Min(Int64(Count), _Stream.Size - Pos));
    End;

  Function TStreamPart.Write(Const Buffer; Count: LongInt): LongInt;
    Var Pos: Int64;

    Begin
      Pos := _Stream.Position;
      If (Pos < _Offset) or (Pos >= _Offset + _MaxLen) Then
        Raise Exception.Create('The .Position is out of range.');
      Result := _Stream.Write(Buffer, Min(Int64(Count), _Stream.Size - Pos));
    End;

  Function TStreamPart.Seek(Offset: LongInt; Origin: Word): LongInt;
    Begin
      Result := Seek(Int64(Offset), TSeekOrigin(Origin));
    End;

  Function TStreamPart.Seek(Const Offset: Int64; Origin: TSeekOrigin): Int64;
    Begin
      Case Origin of
        soEnd: Offset := _Offset + _MaxLen + Offset;
        soCurrent: Offset := _Stream.Position + Offset;
        Else Offset := _Offset + Offset;
      End;
      Result := _Stream.Seek(Min(Max(Offset, _Offset), _Offset + _MaxLen), soBeginning);
    End;

End.
Garbage Collector ... Delphianer erzeugen keinen Müll, also brauchen sie auch keinen Müllsucher.
my Delphi wish list : BugReports/FeatureRequests
  Mit Zitat antworten Zitat
dominikkv

Registriert seit: 30. Sep 2006
Ort: Gundelfingen
1.109 Beiträge
 
Delphi 2007 Professional
 
#10

Re: Video aus (Teil-)Stream abspielen

  Alt 4. Mär 2010, 19:22
Wow, danke, himitsu! Funktioniert wie ne Eins
Zitat von Luckie:
Ach so, das ist natürlich was anderes. Das sind schon aneinander gehangene einzelne Videos?
Genau, nichts daran verändert.

Jetzt brauche ich nur noch eine Möglichkeit diesen Stream wiederzugeben. Als Erweiterung zur Bass.dll gibts die BassVideo.dll (klick), damit sollte das theoretisch gehen, es will aber nicht so recht
Die Demos, die dabei sind, spielen die Videos einfach nicht ab... Anzeigebereich bleibt einfach schwarz. Kann das jemand mit einer Delphi-Version unter 2009 bestätigen?

Ich habe mir schon überlegt, selbst über DirectX (DirectShow) die Videos wiederzugeben... wenn ich das hinbekomme

Kennt jemand sonst ne Komponente die Videos aus Streams wiedergeben kann?
Dominik
Wer anderen eine Grube gräbt, hat ein Gruben-Grab-Gerät!
  Mit Zitat antworten Zitat
Antwort Antwort


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 05:02 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz