unit OptionFrm;
interface
uses
  Windows, Messages, SysUtils,  Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, ExtCtrls, ComCtrls, FFmpegVCL, AVProbe, libavcodec,
  libavformat;
type
  TfrmOption = class(TForm)
    grpNorm: TRadioGroup;
    grpAudioChannels: TRadioGroup;
    edtStartTime: TEdit;
    edtEndTime: TEdit;
    edtAudioVolume: TEdit;
    grpFormats: TRadioGroup;
    grpAudioSampleRate: TRadioGroup;
    grpAspectRatio: TRadioGroup;
    grpAudioVolume: TGroupBox;
    chkAudioVolume: TCheckBox;
    grpCutClip: TGroupBox;
    chkCutClip: TCheckBox;
    btnOk: TButton;
    btnCancel: TButton;
    chkOverwrite: TCheckBox;
    cboFrameSize: TComboBox;
    grpFrameSize: TGroupBox;
    grpVideoCodec: TRadioGroup;
    grpAudioCodec: TRadioGroup;
    chkCopyTimestamp: TCheckBox;
    grpBitRate: TGroupBox;
    edtVideoBitRate: TEdit;
    edtAudioBitRate: TEdit;
    grpFrameRate: TRadioGroup;
    grpVideoHook: TGroupBox;
    chkVideoBitRate: TCheckBox;
    chkAudioBitRate: TCheckBox;
    rdoExternalHook: TRadioButton;
    pnlHook: TPanel;
    chkWaterMark: TCheckBox;
    chkImlib2Img: TCheckBox;
    chkImgDancing: TCheckBox;
    chkImlib2Txt: TCheckBox;
    chkTxtScrolling: TCheckBox;
    chkWaterMarkMode: TCheckBox;
    edtPTSs: TEdit;
    btnPTSs: TButton;
    rdoCustomHook: TRadioButton;
    rdoStandardHook: TRadioButton;
    rdoBeforeHook: TRadioButton;
    rdoPTSs: TRadioButton;
    grpAVFileInfo: TGroupBox;
    mmoAVFileInfo: TMemo;
    edtImlib2Txt: TEdit;
    chkDelphiHookImg: TCheckBox;
    chkDelphiHookTxt: TCheckBox;
    edtDelphiHookTxt: TEdit;
    imgPreview: TImage;
    trcPreview: TTrackBar;
    btnStartTime: TButton;
    btnEndTime: TButton;
    lblPTS: TLabel;
    grpVideoFilter: TGroupBox;
    chkVertFlip: TCheckBox;
    chkHoriFlip: TCheckBox;
    edtOutPath: TEdit;
    lblOutPath: TLabel;
    btnOutPath: TButton;
    chkNegate: TCheckBox;
    chkRotate: TCheckBox;
    edtRotate: TEdit;
    chkScale: TCheckBox;
    edtScale: TEdit;
    chkSetPTS: TCheckBox;
    edtSetPTS: TEdit;
    grpPadCrop: TGroupBox;
    lblTop: TLabel;
    lblBottom: TLabel;
    lblLeft: TLabel;
    lblRight: TLabel;
    chkCrop: TCheckBox;
    edtCropTop: TEdit;
    edtCropBottom: TEdit;
    edtCropLeft: TEdit;
    edtCropRight: TEdit;
    chkPad: TCheckBox;
    edtPadTop: TEdit;
    edtPadBottom: TEdit;
    edtPadLeft: TEdit;
    edtPadRight: TEdit;
    procedure chkAudioVolumeClick(Sender: TObject);
    procedure FormShow(Sender: TObject);
    procedure chkVideoBitRateClick(Sender: TObject);
    procedure chkAudioBitRateClick(Sender: TObject);
    procedure btnPTSsClick(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure trcPreviewChange(Sender: TObject);
    procedure btnStartTimeClick(Sender: TObject);
    procedure btnEndTimeClick(Sender: TObject);
    procedure DoUpdateHook(Sender: TObject);
    procedure imgPreviewClick(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure FormHide(Sender: TObject);
    procedure btnOutPathClick(Sender: TObject);
    procedure chkRotateClick(Sender: TObject);
    procedure chkScaleClick(Sender: TObject);
    procedure chkSetPTSClick(Sender: TObject);
    procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean);
    procedure chkCropClick(Sender: TObject);
    procedure chkPadClick(Sender: TObject);
  private
    FAVProbe: TAVProbe;
    FTraceBarUpdating: Boolean;
    FBitmap: TBitmap;
    FPosFactor: Int64;
    FVideoStreamIndex: Integer;
    FAudioStreamIndex: Integer;
    procedure DoActualFormClick(Sender: TObject);
    procedure UpdateHook;
    procedure DrawFramePicture;
    function GetClipStartTime: Integer;
    function GetClipTimeLength: Integer;
    function GetInputOptions: TInputOptions;
    function GetOutputOptions: TOutputOptions;
    procedure SetAVProbe(const Value: TAVProbe);
  public
    property AVProbe: TAVProbe read FAVProbe write SetAVProbe;
    property InputOptions: TInputOptions read GetInputOptions;
    property OutputOptions: TOutputOptions read GetOutputOptions;
  end;
implementation
uses
  ShlObj,
  ActiveX;
const
  SHookText = 'FFVCL';
  CHookPath = 'vhook\';
  CImlib2DLL = 'imlib2.dll';
  CImlib2Img = 'imlib2.jpg';
  CImlib2DepDLL = 'libImlib2-1.dll';
  CFreeTypeDLL = 'libfreetype-6.dll';
  CWaterMarkDLL = 'watermark.dll';
  CWaterMarkImg = 'watermark.gif';
  CDelphiHookDLL= 'DelphiHook.dll';
  CDelphiHookImg = 'DelphiHook.bmp';
  SSameAsInput = '<same as input>';
  SViewActual = 'Click to view current picture in actual size';
  SHelpPTSCaption = 'Video Hook PTS Periods';
  SHelpPTSText =
    'Enable Video Hook only in special periods, empty means whole duration enabled.'#13#10 +
    'format: [<pts1>-<pts2>[,pts3-pts4[,...]]]'#13#10 +
    'example: to process video hook only in pts periods 0-5,10-15 (seconds)'#13#10 +
    '         PTS Periosd(millisecond!!!) -> "0-5000,10000-15000"';
function FormatSeconds(const AMicroSeconds: Int64): string;
begin
  Result := Format('%d.%.3d', [AMicroSeconds div 1000000, AMicroSeconds div 1000 mod 1000]);
end;
function FitRect(ASrcRect, ADestRect: TRect): TRect;
var
  LWFactor: Double;
  LHFactor: Double;
  LSpace: Integer;
begin
  LWFactor := (ASrcRect.Right - ASrcRect.Left) / (ADestRect.Right - ADestRect.Left);
  LHFactor := (ASrcRect.Bottom - ASrcRect.Top) / (ADestRect.Bottom - ADestRect.Top);
  if LWFactor < LHFactor then
  begin
    Result.Top := ADestRect.Top;
    Result.Bottom := ADestRect.Bottom;
    LSpace := Round(((ADestRect.Right - ADestRect.Left) - (ASrcRect.Right - ASrcRect.Left) / LHFactor) / 2);
    Result.Left := ADestRect.Left + LSpace;
    Result.Right := ADestRect.Right - LSpace;
  end
  else
  begin
    Result.Left := ADestRect.Left;
    Result.Right := ADestRect.Right;
    LSpace := Round(((ADestRect.Bottom - ADestRect.Top) - (ASrcRect.Bottom - ASrcRect.Top) / LWFactor) / 2);
    Result.Top := ADestRect.Top + LSpace;
    Result.Bottom := ADestRect.Bottom - LSpace;
  end;
end;
procedure FitDraw(ACanvas: TCanvas; ABitmap: TBitmap);
var
  R: TRect;
begin
  if ABitmap.Width * ABitmap.Height = 0 then Exit;
  R := ACanvas.ClipRect;
  
  InflateRect(R, -1, -1);
  R := FitRect(ABitmap.Canvas.ClipRect, R);
  ACanvas.StretchDraw(R, ABitmap);
  AImage.Canvas.Brush.Color := clGreen;
  InflateRect(R, 1, 1);
  AImage.Canvas.FrameRect(R);
end;
function SelectDirCBEx(Wnd: HWND; uMsg: UINT; lParam, lpData: LPARAM): Integer stdcall;
var
  LRect: TRect;
  cx, cy, w, h, x, y: Integer;
begin
  if (uMsg = BFFM_INITIALIZED) then
  begin
    if (lpData <> 0) then
      SendMessage(Wnd, BFFM_SETSELECTION, Integer(True), lpData);
    cx := GetSystemMetrics(SM_CXSCREEN);
    cy := GetSystemMetrics(SM_CYSCREEN);
    GetWindowRect(Wnd, LRect);
    w := LRect.Right - LRect.Left;
    h := LRect.Bottom - LRect.Top;
    x := (cx - w) div 2;
    y := (cy - h) div 2;
    SetWindowPos(Wnd, 0, x, y, 0, 0, SWP_NOSIZE or SWP_NOZORDER);
  end;
  Result := 0;
end;
function SelectDirectoryEx(const Caption: string; const Root: WideString; var Directory: string): Boolean;
const
  BIF_NEWDIALOGSTYLE = $0040;
  BIF_USENEWUI = BIF_NEWDIALOGSTYLE or BIF_EDITBOX;
var
  WindowList: Pointer;
  BrowseInfo: TBrowseInfo;
  Buffer: PChar;
  OldErrorMode: Cardinal;
  RootItemIDList, ItemIDList: PItemIDList;
  ShellMalloc: IMalloc;
  IDesktopFolder: IShellFolder;
  Eaten, Flags: LongWord;
begin
  Result := False;
  if not DirectoryExists(Directory) then
    Directory := '';
  Directory := ExpandFileName(Directory);
  FillChar(BrowseInfo, SizeOf(BrowseInfo), 0);
  if (ShGetMalloc(ShellMalloc) = S_OK) and (ShellMalloc <> nil) then
  begin
    Buffer := ShellMalloc.Alloc(MAX_PATH);
    try
      RootItemIDList := nil;
      if Root <> '' then
      begin
        SHGetDesktopFolder(IDesktopFolder);
        IDesktopFolder.ParseDisplayName(Application.Handle, nil,
          POleStr(Root), Eaten, RootItemIDList, Flags);
      end;
      with BrowseInfo do
      begin
        hwndOwner := Application.Handle;
        pidlRoot := RootItemIDList;
        pszDisplayName := Buffer;
        lpszTitle := PChar(Caption);
        ulFlags := BIF_RETURNONLYFSDIRS or BIF_DONTGOBELOWDOMAIN or BIF_USENEWUI;
        lpfn := SelectDirCBEx;
        if Directory <> '' then
          lParam := Integer(PChar(Directory));
      end;
      WindowList := DisableTaskWindows(0);
      OldErrorMode := SetErrorMode(SEM_FAILCRITICALERRORS);
      try
        ItemIDList := ShBrowseForFolder(BrowseInfo);
      finally
        SetErrorMode(OldErrorMode);
        EnableTaskWindows(WindowList);
      end;
      Result := ItemIDList <> nil;
      if Result then
      begin
        ShGetPathFromIDList(ItemIDList, Buffer);
        ShellMalloc.Free(ItemIDList);
        if Buffer <> '' then
          Directory := IncludeTrailingPathDelimiter(Buffer)
        else
          Result := False;
      end;
    finally
      ShellMalloc.Free(Buffer);
    end;
  end;
end;
procedure TfrmOption.FormCreate(Sender: TObject);
begin
  imgPreview.Hint := SViewActual;
  imgPreview.ShowHint := True;
  edtImlib2Txt.Text := SHookText;
  edtDelphiHookTxt.Text := SHookText;
  edtOutPath.Text := SSameAsInput;
  FBitmap := TBitmap.Create;
end;
procedure TfrmOption.FormDestroy(Sender: TObject);
begin
  FBitmap.Free;
end;
procedure TfrmOption.FormShow(Sender: TObject);
begin
  UpdateHook;
  if grpFormats.CanFocus and (grpFormats.ItemIndex >= 0) then
    grpFormats.SetFocus;
    grpFormats.Buttons[grpFormats.ItemIndex].SetFocus;
end;
procedure TfrmOption.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
var
  LDriveType: UINT;
begin
  if Self.ModalResult = mrOk then
  begin
    if edtOutPath.Text = SSameAsInput then
      LDriveType := GetDriveType(PChar(ExtractFileDrive(FAVProbe.FileName)))
    else
      LDriveType := GetDriveType(PChar(ExtractFileDrive(edtOutPath.Text)));
    if LDriveType = DRIVE_CDROM then
    begin
      Application.MessageBox('Input folder is located in CD-ROM, please select output folder.',
        PChar(Application.Title), MB_ICONINFORMATION);
      btnOutPath.SetFocus;
      CanClose := False;
    end;
  end;
end;
procedure TfrmOption.FormHide(Sender: TObject);
begin
  FTraceBarUpdating := True;
  try
    trcPreview.Max := 0;
  finally
    FTraceBarUpdating := False;
  end;
end;
procedure TfrmOption.DrawFramePicture;
begin
  
  
  
  
  
  
  
  
  
  
  
  
  
  if not FTraceBarUpdating and (FAVProbe.VideoStreamCount > 0) then
  begin
    
    if trcPreview.Position = trcPreview.Max then
      FAVProbe.SeekFrame(FAVProbe.FileStreamInfo.Duration, FVideoStreamIndex)
    else
      FAVProbe.SeekFrame(trcPreview.Position * FPosFactor, FVideoStreamIndex);
    
    FitDraw(imgPreview.Canvas, FAVProbe.ReadFramePicture(FVideoStreamIndex));
    FBitmap.Assign(FAVProbe.FramePicture);
  end;
  if not FTraceBarUpdating then
    
    lblPTS.Caption := 'PTS: ' + FormatSeconds(trcPreview.Position * FPosFactor);
end;
procedure TfrmOption.SetAVProbe(const Value: TAVProbe);
  procedure SetupTraceBar;
  var
    LPosMax: Int64;
    LLineSize: Integer;
  begin
    
    trcPreview.SliderVisible := (FAVProbe.FormatName <> 'image2'); ;
    FTraceBarUpdating := True;
    try
      trcPreview.SelStart := 0;
      trcPreview.SelEnd := 0;
      chkCutClip.Enabled := False;
      chkCutClip.Checked := False;
      edtStartTime.Text := 'N/A';
      edtEndTime.Text := 'N/A';
      if trcPreview.SliderVisible then
      begin
        FPosFactor := 1;
        repeat
          FPosFactor := FPosFactor * 10;
          LPosMax := FAVProbe.FileStreamInfo.Duration div FPosFactor;
        until LPosMax < $8000;
        trcPreview.Frequency := LPosMax div ((trcPreview.Width - 12) div 10);
        trcPreview.Min := 0;
        trcPreview.Max := LPosMax;
        if LPosMax > 10000 then
          LLineSize := 1000
        else if LPosMax > 1000 then
          LLineSize := 100
        else if LPosMax > 100 then
          LLineSize := 10
        else
          LLineSize := 1;
        trcPreview.LineSize := LLineSize;
        trcPreview.PageSize := LLineSize * 5;
        trcPreview.Position := 0;
        trcPreview.TickStyle := tsAuto;
      end
      else
      begin
        trcPreview.Min := 0;
        trcPreview.Max := 0;
      end;
    finally
      FTraceBarUpdating := False;
    end;
  end;
begin
  
  FBitmap.Width := 0;
  FBitmap.Height := 0;
  
  imgPreview.Canvas.Brush.Color := clSkyBlue;
  imgPreview.Canvas.FillRect(imgPreview.Canvas.ClipRect);
  FAVProbe := Value;
  
  FVideoStreamIndex := FAVProbe.FirstVideoStreamIndex;
  FAudioStreamIndex := FAVProbe.FirstAudioStreamIndex;
  
  SetupTraceBar;
  
  DrawFramePicture;
  
  mmoAVFileInfo.Text := FAVProbe.FileInfoText;
  
  
end;
procedure TfrmOption.UpdateHook;
var
  LVideoHookPath: string;
begin
  
  LVideoHookPath := ExtractFilePath(Application.ExeName) + CHookPath;
  
  chkImlib2Img.Enabled := rdoExternalHook.Checked and
    FileExists(LVideoHookPath + CImlib2DLL) and
    FileExists(LVideoHookPath + CImlib2DepDLL) and
    FileExists(LVideoHookPath + CFreeTypeDLL);
  chkImlib2Txt.Enabled := chkImlib2Img.Enabled;
  
  chkWaterMark.Enabled := rdoExternalHook.Checked and FileExists(LVideoHookPath + CWaterMarkDLL);
  
  chkDelphiHookImg.Enabled := rdoExternalHook.Checked and FileExists(LVideoHookPath + CDelphiHookDLL);
  chkDelphiHookTxt.Enabled := chkDelphiHookImg.Enabled;
  chkImgDancing.Enabled := chkImlib2Img.Enabled and chkImlib2Img.Checked;
  edtImlib2Txt.Enabled := chkImlib2Txt.Enabled and chkImlib2Txt.Checked;
  chkTxtScrolling.Enabled := chkImlib2Txt.Enabled and chkImlib2Txt.Checked;
  chkWaterMarkMode.Enabled := chkWatermark.Enabled and chkWatermark.Checked;
  edtDelphiHookTxt.Enabled := chkDelphiHookTxt.Enabled and chkDelphiHookTxt.Checked;
  rdoStandardHook.Enabled := (chkImlib2Img.Enabled and chkImlib2Img.Checked) or
                             (chkImlib2Txt.Enabled and chkImlib2Txt.Checked) or
                             (chkWaterMark.Enabled and chkWaterMark.Checked) or
                             (chkDelphiHookImg.Enabled and chkDelphiHookImg.Checked) or
                             (chkDelphiHookTxt.Enabled and chkDelphiHookTxt.Checked);
  rdoBeforeHook.Enabled := rdoStandardHook.Enabled;
  rdoPTSs.Enabled := rdoStandardHook.Enabled;
  edtPTSs.Enabled := rdoPTSs.Enabled and rdoPTSs.Checked;
end;
procedure TfrmOption.chkAudioVolumeClick(Sender: TObject);
begin
  edtAudioVolume.Enabled := chkAudioVolume.Checked;
end;
procedure TfrmOption.chkCropClick(Sender: TObject);
begin
  edtCropLeft.Enabled := chkCrop.Checked;
  edtCropRight.Enabled := chkCrop.Checked;
  edtCropTop.Enabled := chkCrop.Checked;
  edtCropBottom.Enabled := chkCrop.Checked;
end;
procedure TfrmOption.chkPadClick(Sender: TObject);
begin
  edtPadLeft.Enabled := chkPad.Checked;
  edtPadRight.Enabled := chkPad.Checked;
  edtPadTop.Enabled := chkPad.Checked;
  edtPadBottom.Enabled := chkPad.Checked;
end;
procedure TfrmOption.chkRotateClick(Sender: TObject);
begin
  edtRotate.Enabled := chkRotate.Checked;
end;
procedure TfrmOption.chkScaleClick(Sender: TObject);
begin
  edtScale.Enabled := chkScale.Checked;
end;
procedure TfrmOption.chkSetPTSClick(Sender: TObject);
begin
  edtSetPTS.Enabled := chkSetPTS.Checked;
end;
procedure TfrmOption.chkAudioBitRateClick(Sender: TObject);
begin
  edtAudioBitRate.Enabled := chkAudioBitRate.Checked;
end;
procedure TfrmOption.chkVideoBitRateClick(Sender: TObject);
begin
  edtVideoBitRate.Enabled := chkVideoBitRate.Checked;
end;
procedure TfrmOption.DoUpdateHook(Sender: TObject);
begin
  UpdateHook;
end;
procedure TfrmOption.btnOutPathClick(Sender: TObject);
var
  LPath: string;
begin
  if edtOutPath.Text = SSameAsInput then
    LPath := ExtractFilePath(FAVProbe.FileName)
  else
    LPath := edtOutPath.Text;
  if SelectDirectoryEx('Select Output Folder', '', LPath) then
    if GetDriveType(PChar(ExtractFileDrive(LPath))) = DRIVE_CDROM then
      Application.MessageBox('Output folder cannot be located in CD-ROM.',
        PChar(Application.Title), MB_ICONINFORMATION)
    else
      edtOutPath.Text := LPath;
end;
procedure TfrmOption.btnPTSsClick(Sender: TObject);
begin
  Application.MessageBox(SHelpPTSText, SHelpPTSCaption, MB_ICONINFORMATION);
end;
procedure TfrmOption.DoActualFormClick(Sender: TObject);
begin
  if Assigned(Sender) and (Sender is TControl) and ((Sender as TControl).Parent is TForm) then
    ((Sender as TControl).Parent as TForm).Close;
end;
procedure TfrmOption.imgPreviewClick(Sender: TObject);
var
  F: TForm;
  I: TImage;
  B: TButton;
begin
  if FBitmap.Width * FBitmap.Height = 0 then Exit;
  
  F := TForm.Create(Self);
  try
    F.BorderIcons := [biSystemMenu];
    B := TButton.Create(F);
    B.Parent := F;
    B.Default := True;
    B.Cancel := True;
    B.ModalResult := mrCancel;
    B.Top := 0;
    B.Left := 0;
    B.Width := 0;
    B.Height := 0;
    B.Visible := True;
    I := TImage.Create(F);
    I.Parent := F;
    I.OnClick := Self.DoActualFormClick;
    I.Visible := True;
    I.Left := 0;
    I.Top := 0;
    I.Width := FBitmap.Width;
    I.Height := FBitmap.Height;
    I.Picture.Assign(FBitmap);
    F.Position := poScreenCenter;
    F.BorderStyle := bsSingle;
    F.Caption := Format('%dx%d PTS: %s', [FBitmap.Width, FBitmap.Height,
      FormatSeconds(trcPreview.Position * FPosFactor)]);;
    F.ClientWidth := I.Width;
    F.ClientHeight := I.Height;
    F.ShowModal;
  finally
    F.Free;
  end;
end;
procedure TfrmOption.trcPreviewChange(Sender: TObject);
begin
  DrawFramePicture;
end;
procedure TfrmOption.btnStartTimeClick(Sender: TObject);
begin
  trcPreview.SelStart := trcPreview.Position;
  edtStartTime.Text := FormatSeconds(trcPreview.Position * FPosFactor);
  chkCutClip.Enabled := (trcPreview.SelEnd > 0) and (trcPreview.SelEnd > trcPreview.SelStart);
end;
procedure TfrmOption.btnEndTimeClick(Sender: TObject);
begin
  trcPreview.SelEnd := trcPreview.Position;
  edtEndTime.Text := FormatSeconds(trcPreview.Position * FPosFactor);
  chkCutClip.Enabled := (trcPreview.SelEnd > 0) and (trcPreview.SelEnd > trcPreview.SelStart);
end;
procedure CheckClipTime(const ATotalDuration: Integer; var AStartTime, AEndTime: Integer);
begin
  if (AStartTime < 0) or (AStartTime >= ATotalDuration) then
    AStartTime := 0; 
  if (AEndTime <= AStartTime) or (AEndTime > ATotalDuration) then
    AEndTime := ATotalDuration; 
end;
function TfrmOption.GetClipStartTime: Integer;
var
  LStartTime: Integer;
  LEndTime: Integer;
begin
  LStartTime := trcPreview.SelStart * FPosFactor div 1000; 
  LEndTime := trcPreview.SelEnd * FPosFactor div 1000;     
  CheckClipTime(FAVProbe.FileStreamInfo.Duration div 1000, LStartTime, LEndTime);
  Result := LStartTime; 
end;
function TfrmOption.GetClipTimeLength: Integer;
var
  LStartTime: Integer;
  LEndTime: Integer;
begin
  LStartTime := trcPreview.SelStart * FPosFactor div 1000; 
  LEndTime := trcPreview.SelEnd * FPosFactor div 1000;     
  CheckClipTime(FAVProbe.FileStreamInfo.Duration div 1000, LStartTime, LEndTime);
  Result := LEndTime - LStartTime; 
end;
function TfrmOption.GetInputOptions: TInputOptions;
var
  IO: TInputOptions;
begin
  
  InitInputOptions(@IO); 
  IO.FileName := FAVProbe.FileName;
  IO.FileFormat := FAVProbe.ForceFormat; 
  
  if chkCutClip.Enabled and chkCutClip.Checked and
    (trcPreview.SelEnd > 0) and (trcPreview.SelEnd > trcPreview.SelStart) then
    IO.TimeStart := GetClipStartTime; 
  
  
  
  
  
  if Pos(LowerCase(grpFormats.Items.Strings[grpFormats.ItemIndex]),
    'aac ac3 mp2 mp3 wav wma') > 0 then
    IO.ExtOptions := 'vn=1'; 
  Result := IO;
end;
function TfrmOption.GetOutputOptions: TOutputOptions;
var
  OO: TOutputOptions;
  LFileExt: string;
  LTemp: string;
  LBaseName: string;
  LVideoCodec: string;
  LAudioCodec: string;
  I: Integer;
  LHookDLL: string;
  LHookImg: string;
  LDelimiter: string;
  X, Y: string;
  LBitmap: TBitmap;
begin
  
  InitOutputOptions(@OO); 
  
  LFileExt := '.' + LowerCase(grpFormats.Items.Strings[grpFormats.ItemIndex]);
  
  if grpAudioChannels.ItemIndex > 0 then
    OO.AudioChannels := grpAudioChannels.ItemIndex;
  
  if grpAudioSampleRate.ItemIndex > 0 then
    OO.AudioSampleRate :=
      StrToIntDef(grpAudioSampleRate.Items.Strings[grpAudioSampleRate.ItemIndex], 22050);
  
  if chkAudioVolume.Checked then
    OO.AudioVolume := StrToIntDef(edtAudioVolume.Text, -1);
  
  if cboFrameSize.ItemIndex > 0 then
  begin
    LTemp := cboFrameSize.Items.Strings[cboFrameSize.ItemIndex];
    if Pos(' ', LTemp) > 1 then
      LTemp := Copy(LTemp, 1, Pos(' ', LTemp) - 1);
    OO.FrameSize := LTemp;
  end;
  
  if grpFrameRate.ItemIndex > 0 then
    OO.FrameRate := grpFrameRate.Items.Strings[grpFrameRate.ItemIndex];
  
  if grpAspectRatio.ItemIndex > 0 then
    OO.FrameAspectRatio := grpAspectRatio.Items.Strings[grpAspectRatio.ItemIndex];
  
  if chkVideoBitRate.Checked then
    OO.VideoBitrate := 1000 * StrToIntDef(edtVideoBitRate.Text, 200)
  else
  begin
    
    
    
    
    
  end;
  
  if chkAudioBitRate.Checked then
    OO.AudioBitrate := 1000 * StrToIntDef(edtAudioBitRate.Text, 64)
  else
  begin
    
    
    
    
    
  end;
  
  if grpVideoCodec.ItemIndex > 0 then
  begin
    LVideoCodec := LowerCase(grpVideoCodec.Items.Strings[grpVideoCodec.ItemIndex]);
    if LVideoCodec = 'divx' then
    begin
      OO.VideoCodec := 'mpeg4';      
      OO.VideoTag := 'DIVX';         
    end
    else if LVideoCodec = 'xvid' then
      OO.VideoCodec := 'libxvid'      
    else if LVideoCodec = 'x264' then
      OO.VideoCodec := 'libx264';     
    
  end;
  
  if grpAudioCodec.ItemIndex > 0 then
  begin
    LAudioCodec := LowerCase(grpAudioCodec.Items.Strings[grpAudioCodec.ItemIndex]);
    if LAudioCodec = 'aac' then
      OO.AudioCodec := 'libfaac'      
    else if LAudioCodec = 'ac3' then
      OO.AudioCodec := 'ac3'          
    else if LAudioCodec = 'flac' then
      OO.AudioCodec := 'flac'         
    else if LAudioCodec = 'mp3' then
      OO.AudioCodec := 'libmp3lame';  
    
  end;
  
  if chkCutClip.Enabled and chkCutClip.Checked and
    (trcPreview.SelEnd > 0) and (trcPreview.SelEnd > trcPreview.SelStart) then
    OO.TimeLength := GetClipTimeLength; 
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  if rdoExternalHook.Checked and chkImlib2Img.Checked and chkImlib2Img.Enabled then
  begin 
    LHookDLL := ExtractFilePath(Application.ExeName) + CHookPath + CImlib2DLL;
    LHookImg := ExtractFilePath(Application.ExeName) + CHookPath + CImlib2Img;
    if (Pos(' ', LHookDLL) > 0) or (Pos(' ', LHookImg) > 0) then
      LDelimiter := '|' 
    else
      LDelimiter := ' ';
    if chkImgDancing.Checked then
    begin
      X := '(W-w)*(0.5+0.5*sin(N/47*PI))';
      Y := '(H-h)*(0.5+0.5*cos(N/97*PI))';
    end
    else
    begin
      X := 'W-w';
      Y := 'H-h';
    end;
    OO.ExtOptions := OO.ExtOptions +
      Format('vhook=%s%s%s%s%s%s%s%s%s%s%s%s%s'#13#10, [
        LHookDLL, LDelimiter,
        '-i', LDelimiter, LHookImg, LDelimiter,
        '-x', LDelimiter, X, LDelimiter,
        '-y', LDelimiter, Y]);
  end;
  if rdoExternalHook.Checked and chkImlib2Txt.Checked and chkImlib2Txt.Enabled then
  begin 
    LHookDLL := ExtractFilePath(Application.ExeName) + CHookPath + CImlib2DLL;
    if Pos(' ', LHookDLL) > 0 then
      LDelimiter := '|' 
    else
      LDelimiter := ' ';
    if chkTxtScrolling.Checked then
    begin
      X := '10';
      Y := '(H-25)*(0.5+0.50*cos(N/97*PI))';
    end
    else
    begin
      X := '10';
      Y := '10';
    end;
    edtImlib2Txt.Text := Trim(edtImlib2Txt.Text);
    if edtImlib2Txt.Text = '' then
      edtImlib2Txt.Text := SHookText;
    OO.ExtOptions := OO.ExtOptions +
      Format('vhook=%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s'#13#10, [
        LHookDLL, LDelimiter,
        '-R', LDelimiter, '255', LDelimiter,
        '-G', LDelimiter, '255', LDelimiter,
        '-B', LDelimiter, '255', LDelimiter,
        '-F', LDelimiter, 'Tahoma.ttf/16', LDelimiter,  
        '-t', LDelimiter, edtImlib2Txt.Text, LDelimiter,
        '-x', LDelimiter, X, LDelimiter,
        '-y', LDelimiter, Y]);
  end;
  
  if rdoExternalHook.Checked and chkWaterMark.Checked and chkWaterMark.Enabled then
  begin
    LHookDLL := ExtractFilePath(Application.ExeName) + CHookPath + CWaterMarkDLL;
    LHookImg := ExtractFilePath(Application.ExeName) + CHookPath + CWaterMarkImg;
    if (Pos(' ', LHookDLL) > 0) or (Pos(' ', LHookImg) > 0) then
      LDelimiter := '|' 
    else
      LDelimiter := ' ';
    OO.ExtOptions := OO.ExtOptions +
      Format('vhook=%s%s%s%s%s%s%s%s%d'#13#10, [
        LHookDLL, LDelimiter,
        '-f', LDelimiter, LHookImg, LDelimiter,
        '-m', LDelimiter, Ord(chkWaterMarkMode.Checked)]);
  end;
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  if rdoExternalHook.Checked and chkDelphiHookImg.Checked and chkDelphiHookImg.Enabled then
  begin 
    LHookDLL := ExtractFilePath(Application.ExeName) + CHookPath + CDelphiHookDLL;
    LHookImg := ExtractFilePath(Application.ExeName) + CHookPath + CDelphiHookImg;
    LBitmap := TBitmap.Create;
    try
      if FileExists(LHookImg) then
        LBitmap.LoadFromFile(LHookImg)
      else
      begin
        LBitmap.Width := 64;
        LBitmap.Height := 64;
      end;
      if (Pos(' ', LHookDLL) > 0) or (Pos(' ', LHookImg) > 0) then
        LDelimiter := '|' 
      else
        LDelimiter := ' ';
      OO.ExtOptions := OO.ExtOptions +
        Format('vhook=%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s'#13#10, [
          LHookDLL, LDelimiter,
          '-i', LDelimiter, LHookImg, LDelimiter,
          '-mc', LDelimiter, 'FFFFFF', LDelimiter,
          '-ix', LDelimiter,
          IntToStr(FAVProbe.VideoStreamInfos[FVideoStreamIndex].Width - LBitmap.Width - 10), LDelimiter,
          '-iy', LDelimiter,
          IntToStr(FAVProbe.VideoStreamInfos[FVideoStreamIndex].Height - LBitmap.Height - 10)]);
    finally
      LBitmap.Free;
    end;
  end;
  if rdoExternalHook.Checked and chkDelphiHookTxt.Checked and chkDelphiHookTxt.Enabled then
  begin 
    LHookDLL := ExtractFilePath(Application.ExeName) + CHookPath + CDelphiHookDLL;
    if Pos(' ', LHookDLL) > 0 then
      LDelimiter := '|' 
    else
      LDelimiter := ' ';
    edtDelphiHookTxt.Text := Trim(edtDelphiHookTxt.Text);
    if edtDelphiHookTxt.Text = '' then
      edtDelphiHookTxt.Text := SHookText;
    OO.ExtOptions := OO.ExtOptions +
      Format('vhook=%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s'#13#10, [
        LHookDLL, LDelimiter,
        '-t', LDelimiter, edtDelphiHookTxt.Text, LDelimiter,
        '-tx', LDelimiter, '10', LDelimiter,
        '-ty', LDelimiter, '10', LDelimiter,
        '-fc', LDelimiter, 'FFFFFF', LDelimiter,
        '-fn', LDelimiter, 'Tahoma', LDelimiter,
        '-fs', LDelimiter, '16', LDelimiter,
        '-fst', LDelimiter, 'BU']);
  end;
  
  
  OO.BeforeHook := rdoExternalHook.Checked and
    rdoBeforeHook.Checked and rdoBeforeHook.Enabled and
    (chkImlib2Img.Checked or chkImlib2Txt.Checked or chkWaterMark.Checked or
     chkDelphiHookImg.Checked or chkDelphiHookTxt.Checked);
  
  
  if rdoExternalHook.Checked and rdoPTSs.Checked and rdoPTSs.Enabled and
    (chkImlib2Img.Checked or chkImlib2Txt.Checked or chkWaterMark.Checked or
     chkDelphiHookImg.Checked or chkDelphiHookTxt.Checked) then
  begin
    
    
    
    
    
    OO.VideoHookPTSs := edtPTSs.Text;
  end;
  
  
  OO.CustomHook := rdoCustomHook.Checked;
  
  OO.CopyTimestamp := chkCopyTimestamp.Checked;
  
  
  
  
  
  
  if chkVertFlip.Checked then
    if OO.VideoFilters <> '' then
      OO.VideoFilters := OO.VideoFilters + ',vflip' 
    else
      OO.VideoFilters := 'vflip'; 
  
  if chkHoriFlip.Checked then
    if OO.VideoFilters <> '' then
      OO.VideoFilters := OO.VideoFilters + ',hflip' 
    else
      OO.VideoFilters := 'hflip'; 
  
  if chkNegate.Checked then
    if OO.VideoFilters <> '' then
      OO.VideoFilters := OO.VideoFilters + ',negate' 
    else
      OO.VideoFilters := 'negate'; 
  
  if chkScale.Checked then
  begin
    LTemp := Trim(edtScale.Text);
    if LTemp <> '' then
    begin
      if OO.VideoFilters <> '' then
        OO.VideoFilters := OO.VideoFilters + ',scale=' + LTemp 
      else
        OO.VideoFilters := 'scale=' + LTemp; 
    end;
  end;
  
  if chkRotate.Checked then
  begin
    LTemp := IntToStr(StrToIntDef(Trim(edtRotate.Text), 45));
    if OO.VideoFilters <> '' then
      OO.VideoFilters := OO.VideoFilters + ',rotate=' + LTemp 
    else
      OO.VideoFilters := 'rotate=' + LTemp; 
  end;
  
  if chkSetPTS.Checked then
  begin
    LTemp := Trim(edtSetPTS.Text);
    if LTemp <> '' then
    begin
      if OO.VideoFilters <> '' then
        OO.VideoFilters := OO.VideoFilters + ',setpts=' + LTemp 
      else
        OO.VideoFilters := 'setpts=' + LTemp; 
    end;
  end;
  
  if (LFileExt = '.flv') or (LFileExt = '.swf') then
  begin
    
    if (OO.AudioSampleRate <> 11025) and (OO.AudioSampleRate <> 22050)
      and (OO.AudioSampleRate <> 44100) then
      OO.AudioSampleRate := 22050;
  end
  else if LFileExt = '.ogg' then
  begin
    OO.VideoCodec := 'libtheora'; 
    OO.AudioCodec := 'flac';      
  end
  else if LFileExt = '.psp' then
  begin
    OO.FileFormat := 'psp';       
    OO.VideoCodec := 'mpeg4';     
    OO.AudioCodec := 'libfaac';   
    OO.AudioSampleRate := 24000;
    OO.FrameRate := '15000/1001';
    LFileExt := '_psp.mp4';
  end
  else if LFileExt = '.ipod' then
  begin
    OO.VideoCodec := 'mpeg4';     
    OO.AudioCodec := 'libfaac';   
    OO.FrameSize := '320x240';
    LFileExt := '_ipod.mp4';
  end
  else if LFileExt = '.rm10' then
  begin
    OO.VideoCodec := 'rv10';      
    LFileExt := '_rv10.rm';
  end
  else if LFileExt = '.rm20' then
  begin
    OO.VideoCodec := 'rv20';      
    LFileExt := '_rv20.rm';
  end
  else if LFileExt = '.mp4' then
  begin
  end
  else if LFileExt = '.wmv' then
  begin
    OO.VideoCodec := 'wmv2';      
    OO.AudioCodec := 'wmav2';     
    
  end
  else if LFileExt = '.mkv' then
  begin
    OO.VideoCodec := 'libx264';   
    
  end
  else if LFileExt = '.wma' then
  begin
    OO.DisableVideo := True;
    OO.AudioCodec := 'wmav2';     
    
  end
  else if LFileExt = '.3gp' then
  begin
    
    OO.AudioChannels := 1;
    
    OO.AudioSampleRate := 8000;
    
    
,
                           ,
                           ,
                           ,
                           ,
                           ,
                           ,
                           ,
                         };
*)
    OO.AudioBitrate := 7400;
    
    
    OO.FrameSize := '128x96';
  end
  else if Pos(LFileExt, '.vcd.svcd.dvd') > 0 then
  begin
    if LFileExt = '.vcd' then
      OO.TargetType := ttVCD
    else if LFileExt = '.svcd' then
      OO.TargetType := ttSVCD
    else 
      OO.TargetType := ttDVD;
    if grpNorm.ItemIndex = 0 then
      OO.NormType := ntAuto
    else if grpNorm.ItemIndex = 1 then
      OO.NormType := ntPAL
    else
      OO.NormType := ntNTSC;
    OO.NormDefault := ntPAL; 
  end;
  OO.Info.TimeStamp := 0; 
  if chkCrop.Checked then
  begin
    
    OO.CropTop := StrToIntDef(edtCropTop.Text, 0) div 2 * 2;
    OO.CropBottom := StrToIntDef(edtCropBottom.Text, 0) div 2 * 2;
    OO.CropLeft := StrToIntDef(edtCropLeft.Text, 0) div 2 * 2;
    OO.CropRight := StrToIntDef(edtCropRight.Text, 0) div 2 * 2;
  end;
  if chkPad.Checked then
  begin
    
    OO.PadTop := StrToIntDef(edtPadTop.Text, 0) div 2 * 2;
    OO.PadBottom := StrToIntDef(edtPadBottom.Text, 0) div 2 * 2;
    OO.PadLeft := StrToIntDef(edtPadLeft.Text, 0) div 2 * 2;
    OO.PadRight := StrToIntDef(edtPadRight.Text, 0) div 2 * 2;
    OO.PadColor := clBlack;
  end;
  
  
  if Pos(LFileExt, '.vcd.svcd.dvd') > 0 then
  begin
    LFileExt := '_' + Copy(LFileExt, 2, MaxInt);
    if OO.NormType = ntPAL then
      LFileExt := LFileExt + '_pal.mpg'
    else if OO.NormType = ntNTSC then
      LFileExt := LFileExt + '_ntsc.mpg'
    else
      LFileExt := LFileExt + '_auto.mpg';
  end;
  
  OO.FileExt := LFileExt;
  if edtOutPath.Text = SSameAsInput then
    LBaseName := ChangeFileExt(FAVProbe.FileName, '')
  else
    LBaseName := edtOutPath.Text + ChangeFileExt(ExtractFileName(FAVProbe.FileName), '');
  OO.FileName := LBaseName + '_(new)' + OO.FileExt;
  if FileExists(OO.FileName) and not chkOverwrite.Checked then
  begin
    I := 1;
    while FileExists(LBaseName + '_(new_' + IntToStr(I) + ')' + OO.FileExt) do
      Inc(I);
    OO.FileName := LBaseName + '_(new_' + IntToStr(I) + ')' + OO.FileExt;
  end;
  
  
  OO.DisableSubtitle := True;
  Result := OO;
end;
end.