Download Delphi FFmpeg VCL Components

Source of the Simple Video Converter Demo

unit SimpleConverterFrm;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, ComCtrls, FFmpegVCL, FFmpegLogger;

type
  TfrmSimpleConverter = class(TForm)
    lblStatus: TLabel;
    btnOpen: TButton;
    btnStart: TButton;
    btnStop: TButton;
    btnPause: TButton;
    btnResume: TButton;
    btnWebSite: TButton;
    cboLogLevel: TComboBox;
    mmoLog: TMemo;
    ProgressBar1: TProgressBar;
    FFVCL: TFFmpegVCL;
    FFLogger: TFFLogger;
    OpenDialog1: TOpenDialog;
    procedure FormCreate(Sender: TObject);
    procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean);
    procedure btnOpenClick(Sender: TObject);
    procedure btnStartClick(Sender: TObject);
    procedure btnStopClick(Sender: TObject);
    procedure btnPauseClick(Sender: TObject);
    procedure btnResumeClick(Sender: TObject);
    procedure btnWebSiteClick(Sender: TObject);
    procedure cboLogLevelChange(Sender: TObject);
    procedure FFVCLProgress(Sender: TObject; AProgressInfo: PProgressInfo);
    procedure FFVCLTerminate(Sender: TObject; const ATerminateInfo: TTerminateInfo);
    procedure FFLoggerLog(Sender: TObject; AThreadID: Cardinal;
      ALogLevel: TLogLevel; const ALogMsg: string);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  frmSimpleConverter: TfrmSimpleConverter;

implementation

{$R *.dfm}

uses
{$IF NOT (DEFINED(VER140) OR DEFINED(VER185) OR DEFINED(VER200) OR DEFINED(VER210))}
  XPMan,
{$IFEND}
  ShellAPI,
  MyUtils;

const
  CLibAVPath = 'LibAV';

  SAppTitle = 'Demo of FFVCL %s';
  SCaption = 'Demo of FFVCL %s (SimpleConverter) - Delphi FFmpeg VCL Components';
  SWebSiteC = 'http://www.CCAVC.com';
  SWebSiteE = 'http://www.DelphiFFmpeg.com';

  // License sample (this is a fake license key)
  // The full source version doesn't need license key.
//BOMB: you should replace the seed and the key with your own ones.
  LICENSE_SEED = $D24E9E33;
  LICENSE_KEY =
    '39EA968465F26B6CDCA1E51EC8FAC6392100A838813BD0E0F5575E31AC38AEE4' +
    '34E3AF85FDC4B84FBC8BC88078E83D482D8CD226F013CF85BA90F88765D91977' +
    'A8C2E0E345B052AFC342FF244A8D7A95306623716DDBB1B512A1F44F32D6731C' +
    '49308768679B36FC8F6AEF3207ED6CC8EA5EF8F4D2F2AA0F2DC5F13654B78322';

  CDialogOptions = [ofHideReadOnly, ofFileMustExist, ofEnableSizing];
  CPictureFiles = '*.BMP;*.GIF;*.JPEG;*.JPG;*.PNG;';
  CAudioFiles = '*.MP3;*.AAC;*.WAV;*.WMA;*.CDA;*.FLAC;*.M4A;*.MID;*.MKA;' +
      '*.MP2;*.MPA;*.MPC;*.APE;*.OFR;*.OGG;*.RA;*.WV;*.TTA;*.AC3;*.DTS;';
  CVideoFiles = '*.AVI;*.AVM;*.ASF;*.WMV;*.AVS;*.FLV;*.MKV;*.MOV;*.3GP;' +
      '*.MP4;*.MPG;*.MPEG;*.DAT;*.OGM;*.VOB;*.RM;*.RMVB;*.TS;*.TP;*.IFO;*.NSV;';
  CDialogFilter =
      'Video/Audio/Picture Files|' + CVideoFiles + CAudioFiles + CPictureFiles +
      '|Video Files|' + CVideoFiles +
      '|Audio Files|' + CAudioFiles +
      '|Picture Files|' + CPictureFiles +
      '|All Files|*.*';

var
  SWebSite: string = SWebSiteE;

function GenerateOutputFileName(const AFileName, AFileExt: string): string;
var
  LBaseName: string;
  I: Integer;
begin
  // generate output filename automatically
  LBaseName := ChangeFileExt(AFileName, '');
  Result := LBaseName + '_(new)' + AFileExt;
  if FileExists(Result) then
  begin
    I := 1;
    while FileExists(LBaseName + '_(new_' + IntToStr(I) + ')' + AFileExt) do
      Inc(I);
    Result := LBaseName + '_(new_' + IntToStr(I) + ')' + AFileExt;
  end;
end;

procedure TfrmSimpleConverter.FormCreate(Sender: TObject);
begin
  Application.Title := Format(SAppTitle, [FFVCL.Version]);
  Self.Caption := Format(SCaption, [FFVCL.Version]);

  if SysUtils.SysLocale.PriLangID = LANG_CHINESE then
    SWebSite := SWebSiteC
  else
    SWebSite := SWebSiteE;

  mmoLog.Text := SWebSite + #13#10#13#10;
  btnWebsite.Hint := SWebSite;
  btnWebsite.ShowHint := True;

  // open dialog setting
  OpenDialog1.Options := CDialogOptions;
  OpenDialog1.Filter := CDialogFilter;

  // Set License Key
  // The full source version doesn't need license key.
  FFVCL.SetLicenseKey(LICENSE_KEY, LICENSE_SEED);
end;

procedure TfrmSimpleConverter.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
begin
  with FFVCL do
  begin
    // Clear the event handlers
    OnCustomHook := nil;
    OnProgress := nil;
    OnTerminate := nil;

    // Break converting
    Stop;
  end;
  FFLogger.OnLog := nil;
end;

procedure TfrmSimpleConverter.btnOpenClick(Sender: TObject);
var
  LIndex: Integer;
  IO: TInputOptions;
  OO: TOutputOptions;
  LInFileName: string;
  LOutFileName: string;
begin
  // Load dynamic link libraries
  if not FFVCL.AVLibLoaded then
  begin
    // TPathFileName = type WideString;
    // FFVCL.LoadAVLib(const APath: TPathFileName): Boolean;
    // APath: Full path indicates location of FFmpeg DLLs.
    //        It can be empty, let Windows search DLLs in current dir or environment <PATH>
    //if not FFVCL.LoadAVLib(ExtractFilePath(Application.ExeName) + CLibAVPath) then
    // the routine ExePath() is implemented in unit MyUtils which returns WideString type
    // of ExtractFilePath(Application.ExeName)
    if not FFVCL.LoadAVLib(ExePath + CLibAVPath) then
    begin
      mmoLog.Lines.Add(FFVCL.LastErrMsg);
      Exit;
    end;
  end;

  if not OpenDialog1.Execute then
    // cancel open file
    Exit;

  // ensure reset FFVCL
  FFVCL.ClearTasks;
  ProgressBar1.Position := 0;

  // open input file selected
  LInFileName := OpenDialog1.FileName;

  // you should determine the out filename
  LOutFileName := GenerateOutputFileName(LInFileName, '_ipod.mp4');

  // set input options
  InitInputOptions(@IO);

  // try to open input file
  LIndex := FFVCL.AddTask(LInFileName, @IO);
  if LIndex < 0 then
  begin // open failed
    mmoLog.Lines.Add('');
    mmoLog.Lines.Add('***File open error: ' + FFVCL.LastErrMsg);
    mmoLog.Lines.Add('');
    Exit;
  end;

  // here you can get input file info by property AVProbes
  // property AVProbes[TaskIndex, FileIndex: Integer]: TAVProbe read GetAVProbes;
  mmoLog.Lines.Add('');
  mmoLog.Lines.Add(FFVCL.AVProbes[LIndex, 0].FileInfoText);

  // set output options
  InitOutputOptions(@OO);

  // ipod mp4 output options
  // -acodec libfaac -vcodec mpeg4 width<=320 height<=240
  OO.VideoCodec := 'mpeg4';     {Do not Localize}
  OO.AudioCodec := 'libfaac';   {Do not Localize}
  OO.FrameSize := '320x240';

  // try to set output file with output options
  if not FFVCL.SetOutputFile(LIndex, LOutFileName, @OO) then
  begin // cannot do output file, remove input file
    FFVCL.RemoveTask(LIndex);
    mmoLog.Lines.Add('');
    mmoLog.Lines.Add('***Cannot do convert, error: ' + FFVCL.LastErrMsg);
    mmoLog.Lines.Add('');
    Exit;
  end;

  // can do output file with output options
  mmoLog.Lines.Add('');
  mmoLog.Lines.Add('***Can do convert.');
  mmoLog.Lines.Add('');

  btnStart.Enabled := True;
  btnStart.SetFocus;
end;

procedure TfrmSimpleConverter.btnStartClick(Sender: TObject);
begin
  // set status of buttons
  btnOpen.Enabled := False;
  btnStart.Enabled := False;
  btnStop.Enabled := True;
  btnPause.Enabled := True;
  btnResume.Enabled := False;
  btnStop.SetFocus;

  // procedure Start(AThreadCount: Integer);
  // AThreadCount: >  0, means do converting task in thread mode
  //               >  1, means do converting task with multiple files in the same time
  //               <= 0, means do converting task in main thread
  FFVCL.Start(1);
end;

procedure TfrmSimpleConverter.btnStopClick(Sender: TObject);
begin
  btnStop.Enabled := False;
  FFVCL.Stop; // only works in thread mode
end;

procedure TfrmSimpleConverter.btnPauseClick(Sender: TObject);
begin
  btnPause.Enabled := False;
  btnResume.Enabled := True;
  FFVCL.Pause; // only works in thread mode
end;

procedure TfrmSimpleConverter.btnResumeClick(Sender: TObject);
begin
  btnPause.Enabled := True;
  btnResume.Enabled := False;
  FFVCL.Resume; // only works in thread mode
end;

procedure TfrmSimpleConverter.btnWebSiteClick(Sender: TObject);
begin
  ShellExecute(Application.Handle, 'Open',   {Do not Localize}
    PChar(LowerCase(SWebSite)), '',
    PChar(ExtractFilePath(Application.ExeName)), 1);
end;

procedure TfrmSimpleConverter.cboLogLevelChange(Sender: TObject);
begin
  FFLogger.LogLevel := TLogLevel(cboLogLevel.ItemIndex);
end;

procedure TfrmSimpleConverter.FFVCLProgress(Sender: TObject;
  AProgressInfo: PProgressInfo);
begin
  // OnProgress event handler
{
  PProgressInfo = ^TProgressInfo;
  TProgressInfo = record
    TaskIndex: Integer;     // index of converting tasks
    FileIndex: Integer;     // index of input files in the current task
    FrameNumber: Integer;   // current frame number
    FPS: Integer;           // video converting speed, frames per second, not valid when only audio output
    Quality: Single;        // quality
    BitRate: Single;        // bitrate
    CurrentSize: Int64;     // current output file size in bytes
    CurrentDuration: Int64; // current duration time in microsecond
    TotalDuration: Int64;   // total output duration time in microsecond
  end;
}
  with AProgressInfo^ do
  begin
    lblStatus.Caption := Format('Frame number: %d; FPS: %d; Size: %d; Time: %d',
        [FrameNumber, FPS, CurrentSize, CurrentDuration]);
    if TotalDuration > 0 then
      ProgressBar1.Position := CurrentDuration * 100 div TotalDuration;
  end;
end;

procedure TfrmSimpleConverter.FFVCLTerminate(Sender: TObject;
  const ATerminateInfo: TTerminateInfo);
begin
  // OnTerminate event handler
{
  TTerminateInfo = record
    TaskIndex: Integer;     // index of converting tasks, (-1) means all tasks are terminated
    Finished: Boolean;      // True means converted success, False means converting breaked
    Exception: Boolean;     // True means Exception occured, False please ignore
    ExceptionMsg: string;   // Exception message
  end;
}
  if ATerminateInfo.TaskIndex < 0 then
  begin
    // set status of buttons
    btnOpen.Enabled := True;
    btnStart.Enabled := False;
    btnStop.Enabled := False;
    btnPause.Enabled := False;
    btnResume.Enabled := False;
  end
  else if ATerminateInfo.Finished then
  begin // TaskIndex task converted success
    ProgressBar1.Position := 100;
  end;
  if ATerminateInfo.Exception then // Exception occured, show exception message
    Application.MessageBox(PChar(ATerminateInfo.ExceptionMsg), PChar(Application.Title), MB_OK + MB_ICONWARNING);
end;

procedure TfrmSimpleConverter.FFLoggerLog(Sender: TObject; AThreadID: Cardinal;
  ALogLevel: TLogLevel; const ALogMsg: string);
begin
  // OnLog event handler
  // TLogLevel = (llQuiet, llPanic, llFatal, llError, llWarning, llInfo, llVerbose, llDebug);
  mmoLog.Lines.Add('#' + IntToStr(AThreadID) + '.' + IntToStr(Ord(ALogLevel)) + ': ' + ALogMsg);
end;

end.