2008. április 2., szerda

Reading information from an AVI file


Problem/Question/Abstract:

How to read information from an AVI file

Answer:

First, put a memo, button and a open dialog on an empty form. Then use the
following code to show the information of a avi file.

procedure TForm1.ReadAviInfo(FileName: string);
var
  iFileHandle: Integer; // File handle

  // Needed for positioning in the avi file
  Aviheadersize: integer;
  Vheadersize: integer;
  Aviheaderstart: integer;
  Vheaderstart: integer;
  Aheaderstart: integer;
  Astrhsize: integer;

  // Temporary values
  TempTest: string[5];
  TempSize: Integer;
  TempVcodec: string[5];
  TempAcodec: integer;
  TempMicrosec: integer;
  TempLengthInFrames: integer;
  TempAchannels: integer;
  TempAsamplerate: integer;
  TempAbitrate: integer;

  // Final values
  Size: double;
  Length: string;
  Vcodec: string;
  Vbitrate: double;
  VWidth: integer;
  VHeight: integer;
  Fps: double;

  LengthInSec: double;
  Acodec: string;
  Abitrate: string;
begin
  // Open the file
  iFileHandle := FileOpen(FileName, fmOpenRead);

  // Test to see if file is AVI
  FileSeek(iFileHandle, 7, 0);
  FileRead(iFileHandle, TempTest, 5);
  if copy(TempTest, 0, 4) <> 'AVI ' then
  begin
    MessageDlg('Could not open ' + FileName + ' because it is not a valid video file', mtError, [mbOk], 0);
    Exit;
  end;

  // File size
  FileSeek(iFileHandle, 4, 0);
  FileRead(iFileHandle, TempSize, 4);

  // Avi header size (needed to locate the audio part)
  FileSeek(iFileHandle, 28, 0);
  FileRead(iFileHandle, Aviheadersize, 4);

  // Avi header start (needed to locate the video part)
  Aviheaderstart := 32;

  // Microseconds (1000000 / TempMicrosec = fps)
  FileSeek(iFileHandle, Aviheaderstart, 0);
  FileRead(iFileHandle, TempMicrosec, 4);

  // Length of movie in frames
  FileSeek(iFileHandle, Aviheaderstart + 16, 0);
  FileRead(iFileHandle, TempLengthInFrames, 4);

  // Width
  FileSeek(iFileHandle, Aviheaderstart + 32, 0);
  FileRead(iFileHandle, VWidth, 4);

  // Height
  FileSeek(iFileHandle, Aviheaderstart + 36, 0);
  FileRead(iFileHandle, VHeight, 4);

  FileSeek(iFileHandle, Aviheaderstart + Aviheadersize + 4, 0);
  FileRead(iFileHandle, Vheadersize, 4);

  Vheaderstart := Aviheaderstart + Aviheadersize + 20;

  // Video codec
  FileSeek(iFileHandle, Vheaderstart + 3, 0);
  FileRead(iFileHandle, TempVCodec, 5);

  Aheaderstart := Vheaderstart + Vheadersize + 8;

  FileSeek(iFileHandle, Aheaderstart - 4, 0);
  FileRead(iFileHandle, Astrhsize, 5);

  // Audio codec
  FileSeek(iFileHandle, Aheaderstart + Astrhsize + 8, 0);
  FileRead(iFileHandle, TempACodec, 2);

  // Audio channels (1 = mono, 2 = stereo)
  FileSeek(iFileHandle, Aheaderstart + Astrhsize + 10, 0);
  FileRead(iFileHandle, TempAchannels, 2);

  // Audio samplerate
  FileSeek(iFileHandle, Aheaderstart + Astrhsize + 12, 0);
  FileRead(iFileHandle, TempAsamplerate, 4);

  // Audio bitrate
  FileSeek(iFileHandle, Aheaderstart + Astrhsize + 16, 0);
  FileRead(iFileHandle, TempAbitrate, 4);

  // Close the file
  FileClose(iFileHandle);

  // Analyse the video codec (more can be added)
  Vcodec := copy(TempVcodec, 0, 4);
  if Vcodec = 'div2' then
    Vcodec := 'MS MPEG4 v2'
  else if Vcodec = 'DIV2' then
    Vcodec := 'MS MPEG4 v2'
  else if Vcodec = 'div3' then
    Vcodec := 'DivX;-) MPEG4 v3'
  else if Vcodec = 'DIV3' then
    Vcodec := 'DivX;-) MPEG4 v3'
  else if Vcodec = 'div4' then
    Vcodec := 'DivX;-) MPEG4 v4'
  else if Vcodec = 'DIV4' then
    Vcodec := 'DivX;-) MPEG4 v4'
  else if Vcodec = 'div5' then
    Vcodec := 'DivX;-) MPEG4 v5'
  else if Vcodec = 'DIV5' then
    Vcodec := 'DivX;-) MPEG4 v5'
  else if Vcodec = 'divx' then
    Vcodec := 'DivX 4'
  else if Vcodec = 'mp43' then
    Vcodec := 'Microcrap MPEG4 v3';

  // Analyse the audio codec (more can be added)
  case TempAcodec of
    0: Acodec := 'PCM';
    1: Acodec := 'PCM';
    85: Acodec := 'MPEG Layer 3';
    353: Acodec := 'DivX;-) Audio';
    8192: Acodec := 'AC3-Digital';
  else
    Acodec := 'Unknown (' + IntToStr(TempAcodec) + ')';
  end;

  case (Trunc(TempAbitrate / 1024 * 8)) of
    246..260: Abitrate := '128 Kbit/s';
    216..228: Abitrate := '128 Kbit/s';
    187..196: Abitrate := '128 Kbit/s';
    156..164: Abitrate := '128 Kbit/s';
    124..132: Abitrate := '128 Kbit/s';
    108..116: Abitrate := '128 Kbit/s';
    92..100: Abitrate := '128 Kbit/s';
    60..68: Abitrate := '128 Kbit/s';
  else
    Abitrate := FormatFloat('# Kbit/s', TempAbitrate / 1024 * 8);
  end;

  // Some final calculations
  Size := TempSize / 1024 / 1024;
  Fps := 1000000 / TempMicrosec; // FPS
  LengthInSec := TempLengthInFrames / fps; // Length in seconds
  Length := FormatFloat('# min', Int(LengthInSec / 60)) + FormatFloat(' # sec',
    Round(LengthInSec - (Int(LengthInSec / 60) * 60)));
  Vbitrate := (TempSize / LengthInSec - TempABitrate) / 1024 * 8;

  // Output information to memo field
  Memo1.Lines.Add('AVI INFORMATION');
  Memo1.lines.Add('Size: ' + FormatFloat('#.## MB', Size));
  Memo1.Lines.Add('Length: ' + Length);
  Memo1.Lines.Add('');
  Memo1.Lines.Add('VIDEO INFORMATION');
  Memo1.Lines.Add('Codec: ' + Vcodec);
  Memo1.Lines.Add('Bitrate: ' + FormatFloat('# Kbit/s', Vbitrate));
  Memo1.lines.Add('Width: ' + IntToStr(VWidth) + ' px');
  Memo1.lines.Add('Height: ' + IntToStr(VHeight) + ' px');
  Memo1.Lines.Add('FPS: ' + FormatFloat('#.##', fps));
  Memo1.Lines.Add('');
  Memo1.Lines.Add('AUDIO INFORMATION');
  Memo1.Lines.Add('Codec: ' + Acodec);
  Memo1.Lines.Add('Bitrate: ' + Abitrate);
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  OpenDialog1.Filter := 'AVI files (*.avi)|*.avi';
  if OpenDialog1.Execute then
  begin
    Memo1.Clear;
    ReadAviInfo(OpenDialog1.FileName);
  end;
end;

Nincsenek megjegyzések:

Megjegyzés küldése