1

おはよう!

私は現在 XE3 を試していFM2ます. 私はビデオ スケールに関する問題に直面しています。むしろ、ビデオ スケールに対するサポートが完全に欠如しているように見えます。

TMediaPlayeraと aTMediaPlayerControlをフォームに追加して接続しました。次に、単純な再生/停止機能を備えたボタンと、ビデオ ファイルをロードするためのボタンを追加しました。ただし、再生されるすべてのビデオは、実際の解像度で再生されます (align が に設定されているにもかかわらずalClient)。ドキュメントとソースの両方をできる限り調べましたが、実際のビデオ領域をスケーリングまたはサイズ変更する方法が見つからないようです。これに対する唯一の例外は、実際のウィンドウのサイズをビデオ領域よりも小さく変更した場合です。その時点で、アスペクト比を維持しながら縮小されます。

追加のメモとして、ビデオ領域は、「背面に移動」されているかどうかに関係なく、すべての標準コントロールの上に表示されます。

少なくとも、新しいFM²/Firemonkey2 XE3 メディア コンポーネントを使用したビデオ領域のサイズ変更またはスケーリングに関するご意見をいただければ幸いです。それは現在可能ですか、それとも実装を改善するためのパッチを待つつもりですか?

4

3 に答える 3

6

現在、FM2の組み込み実装は、拡張ビューをサポートしていません。

これを解決することは、実際にはこのバグを回避することです...申し訳ありませんが、長い投稿になります:)

ビデオサイズを含むコントロール(通常はTMediaPlayerControl)に合わせて調整する魔法は、TMedia.UpdateMediaFromControlメソッドで、より正確にはプラットフォーム固有TMediaの子孫UpdateMediaFromControlTWindowsMedia.UpdateMediaFromControl勝利時)で行われます。

このメソッドはTRectF.Fit、コントロールのクライアント領域に合わせてビデオサイズを調整するために使用します。このメソッドは、スケールダウンのみをサポートし、スケールアップはサポートしません。だからあなたはこれを変更したいかもしれません...

私の解決策は完璧ではないかもしれませんが、それは私にとってはうまくいきます...

  1. FM2からプラットフォーム固有の実装をコピーして貼り付けることにより、独自のTMedia子孫( )を作成します。TMyMedia(例FMX.Media.Win.TWindowsMedia)。残念ながら、Embarcaderoの開発者は必要なすべてのフィールドをプライベートにしたため、子孫クラスの作成は機能せず、子孫クラスはそれらにアクセスできなくなります。必ずすべてのメソッドをコピーして貼り付け、そのままにしておきます。
  2. 更新のみUpdateMediaFromControl

    procedure TMyMedia.UpdateMediaFromControl;
    var
      P: TPointF;
      R: TRect;
      Bounds: TRectF;
      Form: TCommonCustomForm;
    
      // this is just an updated version of TRecF.Fit to support scaling up      
      function MyRectFit(var R: TRectF; const BoundsRect: TRectF): Single;
      var
        ratio: Single;
      begin
        Result := 1;
        if BoundsRect.Width * BoundsRect.Height = 0 then
          Exit;
    
        if (R.Width / BoundsRect.Width) > (R.Height / BoundsRect.Height) then
          ratio := R.Width / BoundsRect.Width
        else
          ratio := R.Height / BoundsRect.Height;
    
        // UPDATED
        R := RectF(0, 0, R.Width / ratio, R.Height / ratio);
    
        Result := ratio;
        RectCenter(R, BoundsRect);
      end;
    
    begin
      if FWnd <> 0 then
      begin
        if (Control <> nil) and not(csDesigning in Control.ComponentState) and
          (Control.ParentedVisible) and (Control.Root <> nil) and 
          (Control.Root.GetObject is TCommonCustomForm) then
        begin
          Form := TCommonCustomForm(Control.Root.GetObject);
          P := GetVideoSize;
          Bounds := TRectF.Create(0, 0, P.X, P.Y);
    
          // UPDATED:
          // Bounds.Fit(RectF(0, 0, Control.AbsoluteWidth, Control.AbsoluteHeight));
          MyRectFit(Bounds, RectF(0, 0, Control.AbsoluteWidth, Control.AbsoluteHeight));
    
          Bounds.Offset(Control.AbsoluteRect.Left, Control.AbsoluteRect.Top);
          SetParent(FWnd, FmxHandleToHWND(Form.Handle));
          SetWindowPos(FWnd, 0, Bounds.Round.Left, Bounds.Round.Top, Bounds.Round.Width,
                       Bounds.Round.Height, 0);
          R.Create(0, 0, Bounds.Round.Width, Bounds.Round.Height);
          if FVMRWindowlessControl <> nil then
            FVMRWindowlessControl.SetVideoPosition(nil, @R);
          ShowWindow(FWnd, SW_SHOW)
        end
        else
          ShowWindow(FWnd, SW_HIDE)
      end;
    end;
    
  3. トリックは完了です。FM2にそれを使用させましょう。FM2は、TMediaCodecManagerクラスを使用してメディアタイプ(winTCustomMediaCodecのファイル拡張子)と-descendantをペアにして再生します。Windowsの実装ではTWindowsMediaCodec、サポートされているすべてのメディアファイル形式を使用します。TCustomMediaCodecメソッドは1つだけです。これは、メディアファイルを再生するための-descendantクラスをCreateFromFile作成することになっています。TMediaあなたはあなた自身TCustomMediaCodecを利用するためにあなた自身の子孫を作成しなければならないでしょうTMyMedia...

    type
      TMyMediaCodec = class(TCustomMediaCodec)
      public
        function CreateFromFile(const AFileName: string): TMedia; override;
      end;
    
    function TMyMediaCodec.CreateFromFile(const AFileName: string): TMedia;
    begin
      // LeftStr is for the extension trick - see later
      Result := TMyMedia.Create(LeftStr(AFileName, Length(AFileName) - 4));
    end;
    
  4. 「コーデック」TMediaCodecManagerを使用するように指示しましょう...サポートされているすべてのメディアファイル拡張子をセクションのリストに追加します。これらを削除または変更する方法はないため、これを回避する必要があります。独自の拡張機能を登録します。私たちと。FMX.Media.Wininitialization.###TMyMediaCodec

    TMediaCodecManager.RegisterMediaCodecClass('.###', 'My Media Codec', TMediaType.Video, TMyMediaCodec);
    
  5. これを使用するには、.###割り当てるときにすべてのメディアファイル名に拡張子を追加する必要があります。TMediaPlayer.FileNameもちろん、ファイルを再生する前にこの拡張子を削除する必要があります(TMyMediaCodec.CreateFromFile上記を参照)。

    MediaPlayer1.FileName := OpenDialog1.FileName + '.###';
    
  6. TMediaCodecManager.GetFilterStringサポートされているメディアファイルタイプのリストを呼び出す場合は、リストを.###使用する前に、拡張子を手動で削除する必要があります。でTOpenDialog.Filter

このソリューションは最もエレガントではないかもしれませんが、EmbarcaderoがFM2を更新するまでは機能します。

于 2013-01-14T21:11:22.297 に答える
4

ソースにアクセスできない場合は、クラス ヘルパーを記述できます。

unit mediaPlayerStretchFix;

interface
uses windows,FMX.Platform.Win,FMX.Media.Win,FMX.Forms, system.types, fmx.controls,
     system.Classes,directshow9;

type

  TMediaPlayerTurbo = class helper for TWindowsMedia
  private
    function getFWnd: HWND;
    function getFControl: TControl;
    function getVMRWC: IVMRWindowlessControl9;
    property leFWnd:HWND read getFWnd;
    property leControl:TControl read getFControl;
    property leFVMRWindowlessControl:IVMRWindowlessControl9 read getVMRWC;
  public
    procedure Stretch;
  end;

implementation

procedure TMediaPlayerTurbo.Stretch;
var
  P: TPointF;
  R: TRect;
  Bounds: TRectF;
  Form: TCommonCustomForm;

  // this is just an updated version of TRecF.Fit to support scaling up
  function MyRectFit(var R: TRectF; const BoundsRect: TRectF): Single;
  var
    ratio: Single;
  begin
    Result := 1;
    if BoundsRect.Width * BoundsRect.Height = 0 then
      Exit;
    if (R.Width / BoundsRect.Width) > (R.Height / BoundsRect.Height) then
      ratio := R.Width / BoundsRect.Width
    else
      ratio := R.Height / BoundsRect.Height;

    // UPDATED
    R := RectF(0, 0, R.Width / ratio, R.Height / ratio);

    Result := ratio;
    RectCenter(R, BoundsRect);
  end;

begin
  if leFWnd <> 0 then
  begin
    if (leControl <> nil) and not(csDesigning in Control.ComponentState) and
      (Control.ParentedVisible) and (Control.Root <> nil) and
      (Control.Root.GetObject is TCommonCustomForm) then
    begin
      Form := TCommonCustomForm(Control.Root.GetObject);
      P := self.GetVideoSize;
      Bounds := TRectF.Create(0, 0, P.X, P.Y);

      // UPDATED:
      // Bounds.Fit(RectF(0, 0, Control.AbsoluteWidth, Control.AbsoluteHeight));
      MyRectFit(Bounds, RectF(0, 0, Control.AbsoluteWidth, Control.AbsoluteHeight));

      Bounds.Offset(Control.AbsoluteRect.Left, Control.AbsoluteRect.Top);
      SetParent(leFWnd, FmxHandleToHWND(Form.Handle));
      SetWindowPos(leFWnd, 0, Bounds.Round.Left, Bounds.Round.Top, Bounds.Round.Width,
                   Bounds.Round.Height, 0);
      R.Create(0, 0, Bounds.Round.Width, Bounds.Round.Height);
      if leFVMRWindowlessControl <> nil then
        leFVMRWindowlessControl.SetVideoPosition(nil, @R);
      ShowWindow(leFWnd, SW_SHOW)
    end
    else
      ShowWindow(leFWnd, SW_HIDE)
  end;
end;

function TMediaPlayerTurbo.getFControl: TControl;
begin
  result:=TControl(fCOntrol);
end;

function TMediaPlayerTurbo.getFWnd: HWND;
begin
  result:=self.fWnd;
end;


function TMediaPlayerTurbo.getVMRWC: IVMRWindowlessControl9;
begin
  result:=self.FVMRWindowlessControl;
end;

end.

テスト:

var
  mp:TWindowsMedia
begin
  mp:=TWindowsMedia.create(filename);
  mp.Control:=videoframe;
  mp.Play;
  mp.Stretch;
end;
于 2013-11-19T10:04:08.730 に答える