Avatar billede mrcorex Nybegynder
30. september 2005 - 19:26 Der er 9 kommentarer og
2 løsninger

Info fra media-filer

Jeg har brug for at kunne hente info fra avi, mpg, wmv, mp3, wav, gif, jpg, png + flere. Info om størrelse og den slags.

Nogen der kender noget kode til det ?

/CoRex
Avatar billede vallemanden Nybegynder
30. september 2005 - 19:40 #1
Denne henter ALT hvad der er at hente fra MP3

type
  TID3Tag = record
    ID: string[3];
    Titel: string[30];
    Artist: string[30];
    Album: string[30];
    Year: string[4];
    Comment: string[30];
    Genre: Byte;
  end;

const
Genres : array[0..146] of string =
    ('Blues','Classic Rock','Country','Dance','Disco','Funk','Grunge',
    'Hip- Hop','Jazz','Metal','New Age','Oldies','Other','Pop','R&B',
    'Rap','Reggae','Rock','Techno','Industrial','Alternative','Ska',
    'Death Metal','Pranks','Soundtrack','Euro-Techno','Ambient',
    'Trip-Hop','Vocal','Jazz+Funk','Fusion','Trance','Classical',
    'Instrumental','Acid','House','Game','Sound Clip','Gospel','Noise',
    'Alternative Rock','Bass','Punk','Space','Meditative','Instrumental Pop',
    'Instrumental Rock','Ethnic','Gothic','Darkwave','Techno-Industrial','Electronic',
    'Pop-Folk','Eurodance','Dream','Southern Rock','Comedy','Cult','Gangsta',
    'Top 40','Christian Rap','Pop/Funk','Jungle','Native US','Cabaret','New Wave',
    'Psychadelic','Rave','Showtunes','Trailer','Lo-Fi','Tribal','Acid Punk',
    'Acid Jazz','Polka','Retro','Musical','Rock & Roll','Hard Rock','Folk',
    'Folk-Rock','National Folk','Swing','Fast Fusion','Bebob','Latin','Revival',
    'Celtic','Bluegrass','Avantgarde','Gothic Rock','Progressive Rock',
    'Psychedelic Rock','Symphonic Rock','Slow Rock','Big Band','Chorus',
    'Easy Listening','Acoustic','Humour','Speech','Chanson','Opera',
    'Chamber Music','Sonata','Symphony','Booty Bass','Primus','Porn Groove',
    'Satire','Slow Jam','Club','Tango','Samba','Folklore','Ballad',
    'Power Ballad','Rhytmic Soul','Freestyle','Duet','Punk Rock','Drum Solo',
    'Acapella','Euro-House','Dance Hall','Goa','Drum & Bass','Club-House',
    'Hardcore','Terror','Indie','BritPop','Negerpunk','Polsk Punk','Beat',
    'Christian Gangsta','Heavy Metal','Black Metal','Crossover','Contemporary C',
    'Christian Rock','Merengue','Salsa','Thrash Metal','Anime','JPop','SynthPop');


var
  Form1: TForm1;

implementation

{$R *.dfm}

function readID3Tag(FileName: string): TID3Tag;
var
  FS: TFileStream;
  Buffer: array [1..128] of Char;
begin
  FS := TFileStream.Create(FileName, fmOpenRead or fmShareDenyWrite);
  try
    FS.Seek(-128, soFromEnd);
    FS.Read(Buffer, 128);
    with Result do
    begin
      ID := Copy(Buffer, 1, 3);
      Titel := Copy(Buffer, 4, 30);
      Artist := Copy(Buffer, 34, 30);
      Album := Copy(Buffer, 64, 30);
      Year := Copy(Buffer, 94, 4);
      Comment := Copy(Buffer, 98, 30);
      Genre := Ord(Buffer[128]);
    end;
  finally
    FS.Free;
  end;
end;

procedure TfrmMain.Button1Click(Sender: TObject);
begin
  if OpenDialog1.Execute then
  begin
    with readID3Tag(OpenDialog1.FileName) do
    begin
      LlbID.Caption := 'ID: ' + ID;
      LlbTitel.Caption := 'Titel: ' + Titel;
      LlbArtist.Caption := 'Artist: ' + Artist;
      LlbAlbum.Caption := 'Album: ' + Album;
      LlbYear.Caption := 'Year: ' + Year;
      LlbComment.Caption := 'Comment: ' + Comment;
      if (Genre >= 0) and (Genre <=146) then
      LlbGenre.Caption := 'Genre: ' + Genres[Genre]
      else
      LlbGenre.Caption := 'N/A';
    end;
  end;
end;
Avatar billede mrcorex Nybegynder
30. september 2005 - 19:42 #2
Jeg venter lige med at give point, da det er meget mere info jeg skal bruge. Men du skal nok få. Det bliver bare fordelt.
Avatar billede stone Forsker
30. september 2005 - 20:25 #3
Avatar billede mrcorex Nybegynder
06. oktober 2005 - 07:05 #4
Ingen der kan give lidt mere info på video-filer ?
Avatar billede vallemanden Nybegynder
06. oktober 2005 - 08:21 #5
når du skriver størelse......er det så længen eller den fysiske størelse?
Avatar billede mrcorex Nybegynder
06. oktober 2005 - 09:59 #6
Med størrelse mener jeg opløsningen på billede, f.eks. for en avi-fil 720x576 og den slags. Det må jo stå i en eller anden form for header i diverse filer hvad den er lavet af o.s.v.
Avatar billede vallemanden Nybegynder
06. oktober 2005 - 10:21 #7
det kunne du jo bare have sagt ....Hi hi

unit ImgSize;

interface

uses Classes;


procedure GetJPGSize(const sFile: string; var wWidth, wHeight: Word);
procedure GetPNGSize(const sFile: string; var wWidth, wHeight: Word);
procedure GetGIFSize(const sGIFFile: string; var wWidth, wHeight: Word);


implementation

uses SysUtils;

function ReadMWord(f: TFileStream): Word;
type
  TMotorolaWord = record
    case Byte of
      0: (Value: Word);
      1: (Byte1, Byte2: Byte);
  end;
var
  MW: TMotorolaWord;
begin
  { It would probably be better to just read these two bytes in normally }
  { and then do a small ASM routine to swap them.  But we aren't talking }
  { about reading entire files, so I doubt the performance gain would be }
  { worth the trouble. }
  f.read(MW.Byte2, SizeOf(Byte));
  f.read(MW.Byte1, SizeOf(Byte));
  Result := MW.Value;
end;

procedure GetJPGSize(const sFile: string; var wWidth, wHeight: Word);
const
  ValidSig: array[0..1] of Byte = ($FF, $D8);
  Parameterless = [$01, $D0, $D1, $D2, $D3, $D4, $D5, $D6, $D7];
var
  Sig: array[0..1] of byte;
  f: TFileStream;
  x: integer;
  Seg: byte;
  Dummy: array[0..15] of byte;
  Len: word;
  ReadLen: LongInt;
begin
  FillChar(Sig, SizeOf(Sig), #0);
  f := TFileStream.Create(sFile, fmOpenRead);
  try
    ReadLen := f.read(Sig[0], SizeOf(Sig));

    for x := Low(Sig) to High(Sig) do
      if Sig[x] <> ValidSig[x] then ReadLen := 0;

    if ReadLen > 0 then
    begin
      ReadLen := f.read(Seg, 1);
      while (Seg = $FF) and (ReadLen > 0) do
      begin
        ReadLen := f.read(Seg, 1);
        if Seg <> $FF then
        begin
          if (Seg = $C0) or (Seg = $C1) then
          begin
            ReadLen := f.read(Dummy[0], 3); { don't need these bytes }
            wHeight := ReadMWord(f);
            wWidth  := ReadMWord(f);
          end
          else
          begin
            if not (Seg in Parameterless) then
            begin
              Len := ReadMWord(f);
              f.Seek(Len - 2, 1);
              f.read(Seg, 1);
            end
            else
              Seg := $FF; { Fake it to keep looping. }
          end;
        end;
      end;
    end;
  finally
    f.Free;
  end;
end;

procedure GetPNGSize(const sFile: string; var wWidth, wHeight: Word);
type
  TPNGSig = array[0..7] of Byte;
const
  ValidSig: TPNGSig = (137,80,78,71,13,10,26,10);
var
  Sig: TPNGSig;
  f: tFileStream;
  x: integer;
begin
  FillChar(Sig, SizeOf(Sig), #0);
  f := TFileStream.Create(sFile, fmOpenRead);
  try
    f.read(Sig[0], SizeOf(Sig));
    for x := Low(Sig) to High(Sig) do
      if Sig[x] <> ValidSig[x] then Exit;
    f.Seek(18, 0);
    wWidth := ReadMWord(f);
    f.Seek(22, 0);
    wHeight := ReadMWord(f);
  finally
    f.Free;
  end;
end;


procedure GetGIFSize(const sGIFFile: string; var wWidth, wHeight: Word);
type
  TGIFHeader = record
    Sig: array[0..5] of char;
    ScreenWidth, ScreenHeight: Word;
    Flags, Background, Aspect: Byte;
  end;

  TGIFImageBlock = record
    Left, Top, Width, Height: Word;
    Flags: Byte;
  end;
var
  f: file;
  Header: TGifHeader;
  ImageBlock: TGifImageBlock;
  nResult: integer;
  x: integer;
  c: char;
  DimensionsFound: boolean;
begin
  wWidth  := 0;
  wHeight := 0;

  if sGifFile = '' then
    Exit;

  {$I-}
  FileMode := 0;  { read-only }
  AssignFile(f, sGifFile);
  reset(f, 1);
  if IOResult <> 0 then
    { Could not open file }
    Exit;

  { Read header and ensure valid file. }
  BlockRead(f, Header, SizeOf(TGifHeader), nResult);
  if (nResult <> SizeOf(TGifHeader)) or (IOResult <> 0) or
    (StrLComp('GIF', Header.Sig, 3) <> 0) then
  begin
    { Image file invalid }
    Close(f);
    Exit;
  end;

  { Skip color map, if there is one }
  if (Header.Flags and $80) > 0 then
  begin
    x := 3 * (1 shl ((Header.Flags and 7) + 1));
    Seek(f, x);
    if IOResult <> 0 then
    begin
      { Color map thrashed }
      Close(f);
      Exit;
    end;
  end;

  DimensionsFound := False;
  FillChar(ImageBlock, SizeOf(TGIFImageBlock), #0);
  { Step through blocks. }
  BlockRead(f, c, 1, nResult);
  while (not EOF(f)) and (not DimensionsFound) do
  begin
    case c of
      ',': { Found image }
        begin
          BlockRead(f, ImageBlock, SizeOf(TGIFImageBlock), nResult);
          if nResult <> SizeOf(TGIFImageBlock) then
          begin
            { Invalid image block encountered }
            Close(f);
            Exit;
          end;
          wWidth := ImageBlock.Width;
          wHeight := ImageBlock.Height;
          DimensionsFound := True;
        end;
      'ÿ': { Skip }
        begin
          { NOP }
        end;
      { nothing else.  just ignore }
    end;
    BlockRead(f, c, 1, nResult);
  end;
  Close(f);
  {$I+}
end;

end.
Avatar billede mrcorex Nybegynder
06. oktober 2005 - 10:41 #8
Ahhh, this is nice. Har du også noget til video-filer. :)
Avatar billede vallemanden Nybegynder
06. oktober 2005 - 10:46 #9
AVI unit

Unit AVIinfo;

Interface

Uses Classes, Consts, SysUtils, Windows, Math;

Type
  FOURCC = DWORD;

  PropertyStrings = (prAviInfo = 2, prFileName, prFileSize, prStreams,
    prVideoStream,
    prCompression, prVidBitrate, prResolution, prColorDepth,
    prRunningTime, prFrameRate, prMsPerFrame, prFrames,
    prKeyFrames, prAudioStream, prWaveType, prAudBitrate,
    prSamplerate, prBitDepth, prChannels, prAudioDelay);

  TagInfo = Record
    Name: String; // Name of the tag
    Position, Size: Int64; // Position to Size of this ta int64
  End;

  TMainAVIHeader = Packed Record
    dwMicroSecPerFrame: DWORD; // frame display rate (or 0L)
    dwMaxBytesPerSec: DWORD; // max. transfer rate
    dwPaddingGranularity: DWORD; // pad to multiples of this
                                            // size; normally 2K.
    dwFlags: DWORD; // the ever-present flags
    dwTotalFrames: DWORD; // # frames in file
    dwInitialFrames: DWORD;
    dwStreams: DWORD;
    dwSuggestedBufferSize: DWORD;

    dwWidth: DWORD;
    dwHeight: DWORD;

    dwReserved: Array[0..3] Of DWORD;
  End;

  TAVIStreamHeader = Packed Record
    fccType: FOURCC;
    fccHandler: FOURCC;
    dwFlags: DWORD; // Contains AVITF_* flags
    wPriority: WORD;
    wLanguage: WORD;
    dwInitialFrames: DWORD;
    dwScale: DWORD;
    dwRate: DWORD; // dwRate / dwScale == samples/second
    dwStart: DWORD;
    dwLength: DWORD; // In units above...
    dwSuggestedBufferSize: DWORD;
    dwQuality: DWORD;
    dwSampleSize: DWORD;
    rcFrame: TRECT;
  End;

  WAVEFORMATEX = Packed Record
    wFormatTag: Word; { format type }
    nChannels: Word; { number of channels (i.e. mono, stereo, etc.) }
    nSamplesPerSec: DWORD; { sample rate }
    nAvgBytesPerSec: DWORD; { for buffer estimation }
    nBlockAlign: Word; { block size of data }
    wBitsPerSample: Word;
    cbSize: Word;
  End;

  TAuthorInfo = Record
    Artist, Comment, Copyright, Name, Product, Source, Subject, DisplayName,
      Genre, Language, Software:
    String;
  End;

  TBackup = Record
    AviH: TMainAVIHeader;
    VidSH: TAVIStreamHeader;
    AudSH: TAVIStreamHeader;
  End;

  EAviInfoError = Class(Exception);

  TAviStreamInfo = Class(TObject)
  Private
    fAviHeader: TMainAviHeader;
    fVideoStreamHeader: TAviStreamHeader;
    fVideoStreamFormat: BitmapInfoHeader;
    fAudioStreamHeader: TAviStreamHeader;
    fAudioStreamFormat: WaveformatEx;

    fHasVideo: Boolean;
    fHasAudio: Boolean;
    fFrameRate: Double;
    fRunningTime: Double;

    fAuthorInfo: TAuthorInfo;

    fKeyFrames: DWord;
    fVideoBitrate: Double;
    fAudioBitrate: Double;
    fSize: Int64;
    fAudioDelay: Double;

    fChanged: Boolean;

    PropertyStringList: TStringList;
  Protected
    TagList: Record
      Count, Idx1Pos, MoviPos, InfoPos, VidsPos, AudsPos, AvihPos: Byte;
      Tags: Array[0..40] Of TagInfo;
    End;
    Backup: TBackup;

    AviStream: TStream;

    Procedure CreateTagList(AStream: TStream);
    Procedure ParseTagList(AStream: TStream);
    Procedure CalcKeyFrames(AStream: TStream);
    Procedure FillPropertyString;
    Procedure FillPropertyStringNoDescription;
    Function TimeToShortString(myTime: Double): String;

    Procedure SetAuthorInfo(Value: TAuthorInfo); Virtual;
    Procedure SetFrameRate(Value: Double); Virtual;
    Procedure SetAudioDelay(Value: Double); Virtual;

    // CheckAVI should make sure before altering the AVI that it's the same
    // file/stream that was used with LoadAVI
    // Implement it if you need to use TAviStreamInfo,
    // currently it always returns false.
    Function CheckAVI(AStream: TStream): Boolean;
  Public
    Constructor Create;
    Destructor Destroy; Override;

  // procedure LoadAVI(AStream: TStream);
    Procedure LoadAVI(AStream: TStream; Description: Boolean);
    Procedure UndoChanges;
    Procedure SaveToFile(aFilename: TFileName);
    Procedure SaveToStream(AStream: TStream);
    Function PropertyString(pr: PropertyStrings): String;

    Property AviHeader: TMainAviHeader Read fAviHeader;
    Property VideoStreamHeader: TAviStreamHeader Read fVideoStreamHeader;
    Property VideoStreamFormat: BitmapInfoHeader Read fVideoStreamFormat;

    Property AudioStreamHeader: TAviStreamHeader Read fAudioStreamHeader;
    Property AudioStreamFormat: WaveFormatEx Read fAudioStreamFormat;

    Property HasVideo: Boolean Read fHasVideo;
    Property HasAudio: Boolean Read fHasAudio;
    Property FrameRate: Double Read fFrameRate Write SetFrameRate;
    Property RunningTime: Double Read fRunningTime;

    Property KeyFrames: DWord Read fKeyFrames;
    Property VideoBitrate: Double Read fVideoBitrate;
    Property AudioBitrate: Double Read fAudioBitrate;
    Property AudioDelay: Double Read fAudioDelay Write SetAudioDelay;

    Property AuthorInfo: TAuthorInfo Read fAuthorInfo Write SetAuthorInfo;
    Property Size: Int64 Read fSize;

    Property Changed: Boolean Read fChanged;
  Published

  End;

  TAviFileInfo = Class(TAviStreamInfo)
  Private
  Protected
    fAviFile: TFileName;

    Function CheckAVI(Const Filename: String): Boolean;
    Procedure SetAuthorInfo(Value: TAuthorInfo); Override;
    Procedure SetFrameRate(Value: Double); Override;
    Procedure SetAudioDelay(Value: Double); Override;
  Public
    Procedure UndoChanges;
    Property AviFile: TFileName Read fAviFile;
    Procedure LoadAVI(Const FileName: TFilename; Description: Boolean);
    //    procedure LoadAVI(const FileName: TFileName);
  End;

Function fcc2String(fcc: FourCC): String;
Function Wavetype2String(WaveType: Word): String;
Function CodecIdent2String(fcc: FourCC): String;

Implementation

// **********************************
// **  USEFUL MAKROS
// **********************************

Function fcc2String(fcc: FourCC): String;
Var
  Buffer: Array[0..3] Of Char;
Begin
  Move(fcc, Buffer, SizeOf(Buffer));
  Result := Buffer;
End;

Function GetStringFromResource(Name: String): String;
Begin
  With TResourceStream.Create(HInstance, Name, RT_RCDATA) Do
    Try
      SetLength(Result, Size);
      Read(Result[1], Size);
    Finally
      Free;
    End;
End;

Function Wavetype2String(WaveType: Word): String;
Var
  StrLst: TStringList;
  I, P: Integer;
  S: String;
Begin
  StrLst := TStringList.Create;
  Try
    StrLst.Text := GetStringFromResource('AudioCodecs');
    For i := 0 To StrLst.Count - 1 Do
      Begin
        S := StrLst[i];
//      TStrings.NameValueSeperator property isn't there on D6 or lower,
//      So i just use '=' here (as this is the default).
//      P := AnsiPos(StrLst.NameValueSeparator, S);
        P := AnsiPos('=', S);
        If P > 0 Then
          Begin
            If WaveType = StrToInt(Copy(S, 1, P - 1)) Then
              Begin
//          Again, ValueFromIndex doesn't seem to be there on D6 or lower.
//          Result:=StrLst.ValueFromIndex[i];
                Result := StrLst.Values[StrLst.Names[i]];
                Exit;
              End;
          End;
      End;
  Finally
    StrLst.Free;
  End;
End;

Function CodecIdent2String(fcc: FourCC): String;
Var
  Codec: String;
  S: TStringList;
Begin
  Result := '';
  Codec := Fcc2String(Fcc);
  S := TStringList.Create;
  Try
    S.Text := GetStringFromResource('VideoCodecs');
    Result := S.Values[Codec];
  Finally
    S.Free;
  End;
  If Result = '' Then
    Result := 'Unknown';
End;

{ TAviFileInfo }

Function TAviFileInfo.CheckAVI(Const Filename: String): Boolean;
Begin
  Result := (Filename = fAviFile);
End;

Procedure TAviFileInfo.LoadAVI(Const FileName: TFilename; Description:
  Boolean);
Var
  tempStream: TFileStream;
Begin
  fAviFile := FileName;
  tempStream := TFileStream.Create(Filename, fmOpenRead Or fmShareDenyWrite);
  Try
    Inherited LoadAVI(tempStream, Description);
  Finally
    tempstream.Free;
  End;
  PropertyStringList[ord(prFileName)] :=
    StringReplace(PropertyStringList[ord(prFileName)],
    'None [Loaded from Stream]',
    ExtractFileName(FileName), []);
End;

Procedure TAviFileInfo.SetAudioDelay(Value: Double);
Var
  tempStream: TFileStream;
Begin
  tempStream := TFileStream.Create(fAviFile, fmOpenReadWrite Or
    fmShareDenyWrite);
  Try
    AviStream := tempStream;
    Inherited SetAudioDelay(Value);
  Finally
    tempstream.Free;
  End;
End;

Procedure TAviFileInfo.SetAuthorInfo(Value: TAuthorInfo);
Var
  tempStream: TFileStream;
Begin
  tempStream := TFileStream.Create(fAviFile, fmOpenReadWrite Or
    fmShareDenyWrite);
  Try
    AviStream := tempStream;
    Inherited SetAuthorInfo(Value);
  Finally
    tempstream.Free;
  End;
End;

Procedure TAviFileInfo.SetFrameRate(Value: Double);
Var
  tempStream: TFileStream;
Begin
  tempStream := TFileStream.Create(fAviFile, fmOpenReadWrite Or
    fmShareDenyWrite);
  Try
    AviStream := tempStream;
    Inherited SetFrameRate(Value);
  Finally
    tempstream.Free;
  End;
End;

Procedure TAviFileInfo.UndoChanges;
Var
  tempStream: TFileStream;
Begin
  tempStream := TFileStream.Create(fAviFile, fmOpenReadWrite Or
    fmShareExclusive);
  Try
    AviStream := tempStream;
    Inherited UndoChanges;
  Finally
    tempstream.Free;
  End;
End;

{ TAviStreamInfo }

Procedure TAviStreamInfo.UndoChanges;
Begin
//  AStream.Seek(0,soBeginning);
//  AStream.Write(BackupHdr,sizeof(BackupHdr));
  AviStream.Seek(TagList.Tags[TagList.AudsPos].Position + 4, soBeginning);
  AviStream.WriteBuffer(BackUp.AudSH, SizeOf(BackUp.AudSH));

  AviStream.Seek(TagList.Tags[TagList.VidsPos].Position + 4, soBeginning);
  AviStream.WriteBuffer(BackUp.VidSH, SizeOf(BackUp.VidSH));

  AviStream.Seek(TagList.Tags[TagList.AvihPos].Position + 16, soBeginning);
  AviStream.WriteBuffer(BackUp.AviH, SizeOf(BackUp.AviH));

End;

Procedure TAviStreamInfo.LoadAVI(AStream: TStream; Description: Boolean);
Begin
  fSize := AStream.Size;
  fChanged := false;
  AviStream := AStream;

  CreateTagList(AStream); // Fill the array TagList
                                  // It contains the positions of the
                                  // tags in the file.
  ParseTagList(AStream); // Interpret the TagList and fill
                                  // the public properties with the info
  CalcKeyFrames(AStream);
  If Description Then
    FillPropertyString
  Else
    FillPropertyStringNoDescription;
End;

Procedure TAviStreamInfo.CreateTagList(AStream: TStream);
Var
  Code: String;
  ChunkSize: DWord;
  StreamSize, ChunkPos: Int64;
  Buffer: Array[0..3] Of Char;
Begin
  StreamSize := Astream.Size; // Astream.Size is a
                                            // property -> Slower
  AStream.Seek(0, soBeginning);
  TagList.Count := 0;
  While Astream.Position < StreamSize - 4 Do
    Begin
      AStream.Read(Buffer, Sizeof(Buffer));
      ChunkPos := Astream.Position;
      Code := AnsiUpperCase(Buffer); {-GENRE,,}
      If (Code = 'INFO') Or (Code = 'AVIH') Or (Code = 'IART') Or (Code =
        'ICMT') Or
        (Code = 'ICOP') Or (Code = 'INAM') Or (Code = 'IPRD') Or (Code = 'ISBJ')
        Or
        (Code = 'ISRC') Or (Code = 'STRF') Or (Code = 'DISP') Or (Code = 'STRH')
        Or
        (Code = 'STRD') Or (Code = 'MOVI') Or (Code = 'IDX1') Or (Code = 'JUNK')
        Or
        (Code = 'PRMI') Or (Code = 'LIST') Or (Code = 'IGNR') Or (Code = 'ILNG')
        Or (Code = 'ISFT') Then
        Begin

          AStream.Read(ChunkSize, Sizeof(ChunkSize));
          If Code = 'MOVI' Then
            Begin
              AStream.Seek(-12, soCurrent);
              AStream.Read(ChunkSize, Sizeof(ChunkSize));
              AStream.Seek(ChunkSize, soCurrent);
            End;
          If Code = 'INFO' Then
            Begin
              AStream.Seek(-12, soCurrent);
              AStream.Read(ChunkSize, Sizeof(ChunkSize));
              AStream.Seek(4, soCurrent);
            End;
          If (Code = 'JUNK') Or (Code = 'DISP') Or (Code = 'IDX1') Then
            AStream.Seek(ChunkSize, soCurrent);
          TagList.Tags[TagList.Count].Name := Code;
          TagList.Tags[TagList.Count].Position := ChunkPos;
          TagList.Tags[TagList.Count].Size := ChunkSize;
          Inc(TagList.Count);
        End
      Else
        Begin
          AStream.Seek(-3, soCurrent);
        End;
    End;
End;

Procedure TAviStreamInfo.ParseTagList(AStream: TStream);

  Function ReadAuthorInfo(AStream: TStream; i: Byte): AnsiString;
  Var
    BigBuffer: Array[0..2147] Of Char; //2147
    InfoSize: LongInt;
    s, sc: String;
    ii: Integer;
  Begin
    AStream.Seek(TagList.Tags[i].Position, soBeginning);
    InfoSize := AStream.Read(BigBuffer, Min(TagList.Tags[i].Size + 3,
      Sizeof(BigBuffer)));

    s := '';
    For ii := 1 To InfoSize - 1 Do
      Begin
        sc := BigBuffer[ii];
        If sc <> #0 Then
          s := s + sc;
      End;
    Result := s; //Copy(s, 0, InfoSize);
  End;
Var
  i: byte;
  Code: String;
  StreamHeader: TAviStreamHeader;
Begin
  For i := 0 To TagList.Count Do
    Begin
      If TagList.Tags[i].Name = 'AVIH' Then
        Begin
          AStream.Seek(TagList.Tags[i].Position + 4, soBeginning);
          AStream.Read(fAviHeader, Sizeof(fAviHeader));
        End;
      If TagList.tags[i].Name = 'STRH' Then
        Begin
          AStream.Seek(TagList.Tags[i].Position + 4, soBeginning);
          AStream.Read(StreamHeader, SizeOf(StreamHeader));
          Code := AnsiUpperCase(fcc2String(StreamHeader.fccType));
          If code = 'VIDS' Then
            Begin
              fHasVideo := true;
              TagList.VidsPos := i;
              fVideoStreamHeader := StreamHeader;
              fFrameRate := StreamHeader.dwRate / StreamHeader.dwScale;
              fRunningTime := AviHeader.dwTotalFrames / FrameRate;
              AStream.Read(fVideoStreamFormat, Sizeof(fVideoStreamFormat));
            End;
          If code = 'AUDS' Then
            Begin
              fHasAudio := true;
              TagList.AudsPos := i;
              fAudioStreamHeader := StreamHeader;
              AStream.Read(fAudioStreamFormat, Sizeof(fAudioStreamFormat));
            End;
        End; // Ende STRH
      If TagList.tags[i].Name = 'IART' Then //director
        fAuthorInfo.Artist := ReadAuthorInfo(AStream, i);
      If TagList.tags[i].Name = 'ICMT' Then
        fAuthorInfo.Comment := ReadAuthorInfo(AStream, i);
      If TagList.tags[i].Name = 'ICOP' Then //CPYRIGHT
        fAuthorInfo.Copyright := ReadAuthorInfo(AStream, i);
      If TagList.tags[i].Name = 'INAM' Then //title
        fAuthorInfo.Name := ReadAuthorInfo(AStream, i);
      If TagList.tags[i].Name = 'IPRD' Then //product
        fAuthorInfo.Product := ReadAuthorInfo(AStream, i);
      If TagList.tags[i].Name = 'ISRC' Then
        fAuthorInfo.Source := ReadAuthorInfo(AStream, i);
      If TagList.tags[i].Name = 'ISBJ' Then //SUBJECT
        fAuthorInfo.Subject := ReadAuthorInfo(AStream, i);
      If TagList.tags[i].Name = 'DISP' Then
        fAuthorInfo.DisplayName := ReadAuthorInfo(AStream, i);
      {________}
      If TagList.tags[i].Name = 'IGNR' Then //genre
        fAuthorInfo.Genre := ReadAuthorInfo(AStream, i);
      If TagList.tags[i].Name = 'ILNG' Then //lang
        fAuthorInfo.Language := ReadAuthorInfo(AStream, i);
      If TagList.tags[i].Name = 'ISFT' Then //software
        fAuthorInfo.Software := ReadAuthorInfo(AStream, i);
      {________}
      If TagList.Tags[i].Name = 'IDX1' Then
        TagList.Idx1Pos := i;
      If TagList.Tags[i].Name = 'INFO' Then
        TagList.InfoPos := i;
      If TagList.Tags[i].Name = 'MOVI' Then
        TagList.MoviPos := i;
    End;
  fAudioDelay := (AudioStreamHeader.dwStart * AudioStreamHeader.dwScale /
    AudioStreamHeader.dwRate) - (VideoStreamHeader.dwStart / FrameRate);

  // Backup Everything
  BackUp.AviH := AviHeader;
  Backup.VidSH := VideoStreamHeader;
  Backup.AudSH := AudioStreamHeader;
End;

Constructor TAviStreamInfo.Create;
Begin
  fHasVideo := false;
  fHasAudio := false;
  fChanged := false;
  PropertyStringList := TStringList.Create;
End;

Procedure TAviStreamInfo.CalcKeyFrames(AStream: TStream);
Var
  Idx1End, BytesRead: Int64;
  Keyfr: LongInt;
  Buffer: Array[1..2048] Of byte;
  i: word;
  VidStreamSize, AudStreamSize: Dword;
Begin
  KeyFr := 0;
  VidStreamSize := 0;
  AudStreamSize := 0;

  AStream.Seek(TagList.Tags[TagList.Idx1Pos].Position + 4, soBeginning);
  Idx1End := TagList.Tags[TagList.Idx1Pos].Size +
    TagList.Tags[TagList.Idx1Pos].Position + 4;
  While AStream.Position < Idx1End Do
    Begin
      // Sorry for this terrible type of code, but
      // reading big chunks is considerably faster
      // than getting small chunks.
      BytesRead := AStream.Read(Buffer, Sizeof(Buffer)) Div 16 - 1;
      For i := 0 To BytesRead Do
        Begin
      // 00 is normally the video stream
          If (Buffer[1 + 16 * i] = Ord('0')) And (Buffer[2 + 16 * i] = Ord('0'))
            Then
            Begin
        // keyframe flag set?
              If ((Buffer[5 + 16 * i] And $10) <> 0) Then
                Begin
                  Inc(Keyfr);
                End;
              VidStreamSize := VidStreamSize + Buffer[13 + i * 16] + Buffer[14
                + i * 16] * $100 + Buffer[15 + i * 16] * $10000 + Buffer[16 + i
                *
                16] * $1000000;
            End;
      // 01 is the audio stream
          If (Buffer[1 + 16 * i] = Ord('0')) And (Buffer[2 + 16 * i] = Ord('1'))
            Then
            AudStreamSize := AudStreamSize + Buffer[13 + i * 16] + Buffer[14 + i
              * 16] * $100 + Buffer[15 + i * 16] * $10000 + Buffer[16 + i * 16]
              *
              $1000000;
        End;
    End;

  fKeyframes := KeyFr;
  fVideoBitrate := VidStreamSize * FrameRate / (125 * AviHeader.dwTotalFrames);
  fAudioBitrate := AudStreamSize * FrameRate / (125 * AviHeader.dwTotalFrames);
End;

Function TAviStreamInfo.CheckAVI(AStream: TStream): Boolean;
Begin
  // Donno what to do here, perhaps compare the first 8 Kb with BackupHdr.
  // Just a dummy function for CheckAVI in TAviFileInfo.
  // If you want to use TAviStreamInfo implement this function!
  Result := false;
End;

Procedure TAviStreamInfo.SetAuthorInfo(Value: TAuthorInfo);
Begin
  // yet to implement
End;

Procedure TAviStreamInfo.SetFrameRate(Value: Double);
Begin
  // Check here if AviStream is still valid
  If Value <= 0 Then
    Raise
      EAviInfoError.Create('Framerate can''t set the framerate to a negative value. (' + FloatToStr(Value) + ')');

  fChanged := true;
  fVideoStreamHeader.dwScale := 10000;
  fVideoStreamHeader.dwRate := Round(Value * fVideoStreamHeader.dwScale);
  fAviHeader.dwMicroSecPerFrame :=
    Round(fVideoStreamHeader.dwScale / fVideoStreamHeader.dwRate * 1000000);
  AviStream.Seek(TagList.Tags[TagList.VidsPos].Position + 4, soBeginning);
  AviStream.WriteBuffer(fVideoStreamHeader, SizeOf(fVideoStreamHeader));

  AviStream.Seek(TagList.Tags[TagList.AvihPos].Position + 16, soBeginning);
  AviStream.WriteBuffer(fAviHeader, SizeOf(fAviHeader));
  fFrameRate := Value;
End;

Procedure TAviStreamInfo.SetAudioDelay(Value: Double);
Begin
  fChanged := true;

  If Value >= 0 Then
    Begin
    // The following is something as an "Audio Framerate":
    // AudioStreamHeader.dwRate/AudioStreamHeader.dwScale
      fAudioStreamHeader.dwStart := Round(Value * AudioStreamHeader.dwRate /
        AudioStreamHeader.dwScale);
      fVideoStreamHeader.dwStart := 0;
    End;
  If Value < 0 Then
    Begin
      fAudioStreamHeader.dwStart := 0;
      fVideoStreamHeader.dwStart := -Round(Value * FrameRate);
    End;
  AviStream.Seek(TagList.Tags[TagList.AudsPos].Position + 4, soBeginning);
  AviStream.WriteBuffer(fAudioStreamHeader, SizeOf(fAudioStreamHeader));
  AviStream.Seek(TagList.Tags[TagList.VidsPos].Position + 4, soBeginning);
  AviStream.WriteBuffer(fVideoStreamHeader, SizeOf(fVideoStreamHeader));
  fAudioDelay := Value;
End;
{____________________________________________}

Procedure TAviStreamInfo.FillPropertyStringNoDescription;
Begin
  PropertyStringList.Clear;
  PropertyStringList.Add('Yet Another Avi Info (YAAI) Output File');
  PropertyStringList.Add('visit http://yaai.sourceforge.net/ for more information');
  PropertyStringList.Add('AVI Information');
  PropertyStringList.Add(' None [Loaded from Stream]');
  PropertyStringList.Add(IntToStr(Size) + ' Bytes (' +
    Floattostrf(Size / 1048576, ffFixed, 15, 2) + ' MB)');
  PropertyStringList.Add(IntToStr(AviHeader.dwStreams));

  If HasVideo Then
    Begin
      PropertyStringList.Add('Video Stream');
      PropertyStringList.Add(fcc2String(VideoStreamHeader.fccHandler) + ' - ' +
        CodecIdent2String(VideostreamHeader.fccHandler));
      PropertyStringList.Add(FloatToStrF(VideoBitrate, ffFixed, 15, 2) +
        ' kbit/s');
      PropertyStringList.Add(IntToStr(AviHeader.dwWidth) +
        'x' + IntToStr(AviHeader.dwHeight));
      PropertyStringList.Add(IntToStr(VideoStreamFormat.biBitCount) + ' bits');
      PropertyStringList.Add(FloatToStrF(RunningTime,
        ffFixed, 15, 2) + ' s (' + TimeToShortString(RunningTime) + ')');
        // 86400 = Seconds / Day
      PropertyStringList.Add(FloatToStrF(FrameRate,
        ffFixed, 15, 4) + ' fps');
      PropertyStringList.Add(
        IntToStr(AviHeader.dwMicroSecPerFrame) + ' ms');
      PropertyStringList.Add(
        IntToStr(AviHeader.dwTotalFrames));
      PropertyStringList.Add(IntToStr(KeyFrames) +
        ' (Every ' + IntToStr(AviHeader.dwTotalFrames Div Keyframes) + ')');
    End
  Else
    Begin
      PropertyStringList.Add('No Video Stream Found!');
      PropertyStringList.Add('-');
      PropertyStringList.Add('-');
      PropertyStringList.Add('-');
      PropertyStringList.Add('-');
      PropertyStringList.Add('-');
      PropertyStringList.Add('-');
      PropertyStringList.Add('-');
      PropertyStringList.Add('-');
      PropertyStringList.Add('-');
    End;

  If HasAudio Then
    Begin
      PropertyStringList.Add('Audio Stream');
      PropertyStringList.Add(
        IntToStr(AudioStreamFormat.wFormatTag) + ' - ' +
        WaveType2String(AudioStreamFormat.wFormatTag));
      PropertyStringList.Add(FloatToStrF(AudioBitrate,
        ffFixed, 15, 2) + ' kbit/s');
      PropertyStringList.Add(IntToStr(AudioStreamFormat.nSamplesPerSec) +
        ' Hz');
      PropertyStringList.Add(IntToStr(AudioStreamFormat.wBitsPerSample) +
        ' Bits');
      PropertyStringList.Add(IntToStr(AudioStreamFormat.nChannels));
      PropertyStringList.Add(FloatToStrF(AudioDelay,
        ffFixed, 15, 2) + ' s');
    End
  Else
    Begin
      PropertyStringList.Add('No Audio Stream Found!');
      PropertyStringList.Add('-');
      PropertyStringList.Add('-');
      PropertyStringList.Add('-');
      PropertyStringList.Add('-');
      PropertyStringList.Add('-');
      PropertyStringList.Add('-');
    End;

  PropertyStringList.Add('Author Details');
  PropertyStringList.Add(AuthorInfo.Artist);
  PropertyStringList.Add(AuthorInfo.Comment);
  PropertyStringList.Add(AuthorInfo.Copyright);
  PropertyStringList.Add(AuthorInfo.Name);
  PropertyStringList.Add(AuthorInfo.Product);
  PropertyStringList.Add(AuthorInfo.Source);
  PropertyStringList.Add(AuthorInfo.Subject);
  PropertyStringList.Add(AuthorInfo.DisplayName);
  PropertyStringList.Add(AuthorInfo.Genre);
  PropertyStringList.Add(AuthorInfo.Language);
  PropertyStringList.Add(AuthorInfo.Software);
End;

Procedure TAviStreamInfo.FillPropertyString;
Begin
  PropertyStringList.Clear;
  PropertyStringList.Add('Yet Another Avi Info (YAAI) Output File');
  PropertyStringList.Add('visit http://yaai.sourceforge.net/ for more information');

  PropertyStringList.Add('AVI Information');
  PropertyStringList.Add('    Filename: None [Loaded from Stream]');
  PropertyStringList.Add('    Filesize: ' + IntToStr(Size) + ' Bytes (' +
    Floattostrf(Size / 1048576, ffFixed, 15, 2) + ' MB)');
  PropertyStringList.Add('    Streams (i.e. Video, Audio): ' +
    IntToStr(AviHeader.dwStreams));

  If HasVideo Then
    Begin
      PropertyStringList.Add('Video Stream');
      PropertyStringList.Add('    Compression: ' +
        fcc2String(VideoStreamHeader.fccHandler) + ' - ' +
        CodecIdent2String(VideostreamHeader.fccHandler));
      PropertyStringList.Add('    Avg. Bitrate: ' + FloatToStrF(VideoBitrate,
        ffFixed, 15, 2) + ' kbit/s');
      PropertyStringList.Add('    Resolution: ' + IntToStr(AviHeader.dwWidth) +
        'x' + IntToStr(AviHeader.dwHeight));
      PropertyStringList.Add('    Color Depth: ' +
        IntToStr(VideoStreamFormat.biBitCount) + ' bits');
      PropertyStringList.Add('    Running Time: ' + FloatToStrF(RunningTime,
        ffFixed, 15, 2) + ' s (' + TimeToShortString(RunningTime) + ')');
      PropertyStringList.Add('    Framerate: ' + FloatToStrF(FrameRate,
        ffFixed, 15, 4) + ' fps');
      PropertyStringList.Add('    Microseconds Per Frame: ' +
        IntToStr(AviHeader.dwMicroSecPerFrame) + ' ms');
      PropertyStringList.Add('    Frames: ' +
        IntToStr(AviHeader.dwTotalFrames));
      PropertyStringList.Add('    Keyframes: ' + IntToStr(KeyFrames) +
        ' (Every ' + IntToStr(AviHeader.dwTotalFrames Div Keyframes) + ')');
    End
  Else
    Begin
      PropertyStringList.Add('No Video Stream Found!');
      PropertyStringList.Add('    Compression: -');
      PropertyStringList.Add('    Avg. Bitrate: -');
      PropertyStringList.Add('    Resolution: -');
      PropertyStringList.Add('    Color Depth: -');
      PropertyStringList.Add('    Running Time: -');
      PropertyStringList.Add('    Framerate: -');
      PropertyStringList.Add('    Microseconds Per Frame: -');
      PropertyStringList.Add('    Frames: -');
      PropertyStringList.Add('    Keyframes: -');
    End;

  If HasAudio Then
    Begin
      PropertyStringList.Add('Audio Stream');
      PropertyStringList.Add('    Wave Type: ' +
        IntToStr(AudioStreamFormat.wFormatTag) + ' - ' +
        WaveType2String(AudioStreamFormat.wFormatTag));
      PropertyStringList.Add('    Avg. Bitrate: ' + FloatToStrF(AudioBitrate,
        ffFixed, 15, 2) + ' kbit/s');
      PropertyStringList.Add('    Sample Rate: ' +
        IntToStr(AudioStreamFormat.nSamplesPerSec) + ' Hz');
      PropertyStringList.Add('    Bit Depth: ' +
        IntToStr(AudioStreamFormat.wBitsPerSample) + ' Bits');
      PropertyStringList.Add('    Channels: ' +
        IntToStr(AudioStreamFormat.nChannels));
      PropertyStringList.Add('    Audio Delay: ' + FloatToStrF(AudioDelay,
        ffFixed, 15, 2) + ' s');
    End
  Else
    Begin
      PropertyStringList.Add('No Audio Stream Found!');
      PropertyStringList.Add('    Wave Type: -');
      PropertyStringList.Add('    Avg. Bitrate: -');
      PropertyStringList.Add('    Sample Rate: -');
      PropertyStringList.Add('    Bit Depth: -');
      PropertyStringList.Add('    Channels: -');
      PropertyStringList.Add('    Audio Delay: -');
    End;

  PropertyStringList.Add('Author Details');
  PropertyStringList.Add('    Artist: ' + AuthorInfo.Artist);
  PropertyStringList.Add('    Comment: ' + AuthorInfo.Comment);
  PropertyStringList.Add('    Copyright: ' + AuthorInfo.Copyright);
  PropertyStringList.Add('    Name: ' + AuthorInfo.Name);
  PropertyStringList.Add('    Product: ' + AuthorInfo.Product);
  PropertyStringList.Add('    Source: ' + AuthorInfo.Source);
  PropertyStringList.Add('    Subject: ' + AuthorInfo.Subject);
  PropertyStringList.Add('    Display Name: ' + AuthorInfo.DisplayName);
  PropertyStringList.Add('    Genre: ' + AuthorInfo.Genre);
  PropertyStringList.Add('    Language: ' + AuthorInfo.Language);
  PropertyStringList.Add('    Software: ' + AuthorInfo.Software);
End;

Destructor TAviStreamInfo.Destroy;
Begin
  If PropertyStringList <> Nil Then
    PropertyStringList.Free;
  Inherited Destroy;
End;

Function TAviStreamInfo.PropertyString(pr: PropertyStrings): String;
Begin
  Result := trim(PropertyStringList[ord(pr)]);
End;

Procedure TAviStreamInfo.SaveToFile(aFilename: TFileName);
Begin
  PropertyStringList.SaveToFile(aFilename);
End;

Procedure TAviStreamInfo.SaveToStream(AStream: TStream);
Begin
  PropertyStringList.SaveToStream(aStream);
End;

Function TAviStreamInfo.TimeToShortString(myTime: Double): String;
Var
  i: Dword;
Begin
  i := Trunc(myTime);
  Result := IntToStr(i Mod 60) + 's';
  If i >= 60 Then
    Begin
      i := i Div 60;
      Result := IntToStr(i Mod 60) + 'm ' + Result;
      If i >= 60 Then
        Begin
          i := i Div 60;
          Result := IntToStr(i Mod 60) + 'h ' + Result;
        End;
    End;
End;

End.
Avatar billede mrcorex Nybegynder
06. oktober 2005 - 11:09 #10
ok, nu har jeg vist nok en del at lege med. Jeg siger tak og fordeler point. Mange tak alle sammen. Det er guld der her. :)
Avatar billede mrcorex Nybegynder
06. oktober 2005 - 11:12 #11
.
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Kurser inden for grundlæggende programmering

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester