2009. augusztus 21., péntek

How to open and read the first frame in an AVI file


Problem/Question/Abstract:

How to open and read the first frame in an AVI file

Answer:

{File: AVIObjects.pas
Author: Liran Shahar
Purpose: AVI file objects routines to open,read and retrive poster frames (first frame in AVI file)
Copyright(C) 2001, Com-N-Sense Ltd, all rights reserved

Note: this unit is released as freeware. In other words, you are free  to use this unit in your own applications, however I retain all copyright to the code. LS}

unit AVIObjects;

interface

uses
  Windows, Graphics, Sysutils, Classes, VFW, Ole2;

type
  TAviFileStream = class(TPersistent)
  private
    aviFile: IAviFile;
    aviStream: IAviStream;
    aviFrame: IGetFrame;
    aviInfo: TAviStreamInfo;
  protected
    function GetFrameCount: cardinal; virtual;
    function GetDuration: double; virtual;
    function GetWidth: integer; virtual;
    function GetHeight: integer; virtual;
    function GetWantedBitmapFormat: PBitmapInfoHeader; virtual;
  public
    constructor Create; virtual;
    destructor Destroy; override;
    function Active: boolean; virtual;
    procedure Open(const Filename: AnsiString); virtual;
    procedure Close; virtual;
    procedure GetFrame(FrameNumber: cardinal; var DIB: PBitmapInfoHeader); virtual;
    property FrameCount: cardinal read GetFrameCount;
    property Duration: double read GetDuration;
    property ImageWidth: integer read GetWidth;
    property ImageHeight: integer read GetHeight;
  end;

implementation

constructor TAviFileStream.Create;
begin
  inherited Create;
  aviFile := nil;
  aviStream := nil;
  aviFrame := nil;
end;

destructor TAviFileStream.Destroy;
begin
  Close;
  inherited Destroy;
end;

function TAviFileStream.Active: boolean;
begin
  Result := (aviStream <> nil) and (aviFrame <> nil);
end;

function TAviFileStream.GetFrameCount: cardinal;
begin
  Result := aviInfo.dwLength;
end;

function TAviFileStream.GetDuration: double;
begin
  if (aviInfo.dwRate <> 0) and (aviInfo.dwScale <> 0) then
    Result := aviInfo.dwLength / (aviInfo.dwRate / aviInfo.dwScale)
  else
    Result := 0.0;
end;

function TAviFileStream.GetWidth: integer;
begin
  Result := aviInfo.rcFrame.Right - aviInfo.rcFrame.Left;
end;

function TAviFileStream.GetHeight: integer;
begin
  Result := aviInfo.rcFrame.Bottom - aviInfo.rcFrame.Top;
end;

function TAviFileStream.GetWantedBitmapFormat: PBitmapInfoHeader;
begin
  Result := nil;
end;

procedure TAviFileStream.Open(const Filename: AnsiString);
var
  iResult: integer;
  BmpInfoHeader: PBitmapInfoHeader;
begin
  Close;
  fillchar(aviInfo, sizeof(aviInfo), 0);
  iResult := AviFileOpen(aviFile, pchar(FileName), OF_READ + OF_SHARE_DENY_WRITE, nil);
  if iResult <> AVIERR_OK then
    raise Exception.Create('Cannot open AVI file ' + Filename);
  iResult := AVIFileGetStream(aviFile, aviStream, streamTypeVideo, 0);
  if iResult <> AVIERR_OK then
    raise Exception.Create('Cannot open stream for that file');
  iResult := AVIStreamInfo(aviStream, aviInfo, sizeof(aviInfo));
  if iResult <> AVIERR_OK then
    raise Exception.Create('Cannot read stream info');
  BmpInfoHeader := GetWantedBitmapFormat;
  aviFrame := AVIStreamGetFrameOpen(aviStream, BmpInfoHeader);
  if not assigned(aviFrame) then
    raise Exception.Create('Cannot find suitable decompressor');
  if assigned(BmpInfoHeader) then
    dispose(BmpInfoHeader);
end;

procedure TAviFileStream.Close;
var
  iResult: integer;
begin
  aviFrame := nil;
  aviStream := nil;
  aviFile := nil;
end;

procedure TAviFileStream.GetFrame(FrameNumber: cardinal; var DIB: PBitmapInfoHeader);
begin
  DIB := aviStreamGetFrame(aviFrame, FrameNumber)
end;

initialization
  CoInitialize(nil);
  AVIFileInit;

finalization
  AVIFileExit;
  CoUninitialize;

end.

Nincsenek megjegyzések:

Megjegyzés küldése