Einzelnen Beitrag anzeigen

Benutzerbild von himitsu
himitsu

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

Re: Video aus (Teil-)Stream abspielen

  Alt 1. Mär 2010, 10: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.
Neuste Erkenntnis:
Seit Pos einen dritten Parameter hat,
wird PoSex im Delphi viel seltener praktiziert.
  Mit Zitat antworten Zitat