Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Multimedia (https://www.delphipraxis.net/16-multimedia/)
-   -   Mediaplayer Firemonkey (https://www.delphipraxis.net/186753-mediaplayer-firemonkey.html)

holgerderchsler 26. Sep 2015 08:11

Mediaplayer Firemonkey
 
Hallo und einen schönen Tag.

Ich habe in meiner plattformübergreifenden Anwendung einen Mediaplayer integriert. Nun wollte ich das Bild auf dem ganzen Bildschirm darstellen, finde aber keine Möglichkeit dies zu tun. Der Mediaplayer und auch das notwendige MediaplayerControl bieten weder eine Skalierung noch Zoomfunktionen an. Hat da eventuell jemand eine Idee?

Liebe Grüsse

Holger

Perlsau 26. Sep 2015 10:29

AW: Mediaplayer Firemonkey
 
Du kannst aber doch die Properties Width und Height der Komponente an deinen Bildschirm anpassen, oder etwa nicht?

holgerderchsler 26. Sep 2015 14:38

AW: Mediaplayer Firemonkey
 
Ja, die Eigenschaften kann ich schon ändern, aber das Bild bleibt immer gleich gross oder besser klein.

Harry Stahl 26. Sep 2015 19:00

AW: Mediaplayer Firemonkey
 
Ich kenne da leider auch keine Standardmöglichkeit. Es wird maximal die Größe des Videos ausgegeben. Das Bild des Videos wird direkt auf den Screen gerendert, daher helfen alle Umgehungsversuche nicht (z.B. die Mediaplayer-Komponente in ein Scaled-Layout zu legen und dieses zu skalieren).

Für Windows wird die Videoplayer-Funktion in FMX.Media.Win implementiert, die Ausgabegröße des Fensters dort in der procedure "UpdateMediaFromControl" festgelegt. Hier könntest Du evtl. eigene Anpassungen machen (z.B. statt "Bounds.Fit", die Größe des Monitors als Grundlage eines Ausgabe-Rects verwenden).

Du müsstest da natürlich alles selber berechnen, damit die Ausgabe des Bildes die richtige Vergrößerung hat und mit den entsprechenden Offests richtig in das Ausgabefenster reingeht, aber das sollte machbar sein.

Du könntest hier entweder eine eigene Ableitung der Komponente machen, oder eine Kopie der FMX.Media.Win.pas in Dein Projektverzeichnis legen und dort die entsprechenden Änderungen in der Datei vornehmen.

holgerderchsler 27. Sep 2015 15:18

AW: Mediaplayer Firemonkey
 
Erst mal Danke und schön, dass ich nichts einfaches übersehen habe. Das klingt einleuchtend. Ich könnte mir allerdings vorstellen, dass ich nicht der erste bin, der dieses Problem. Eine Komponente direkt gibt es wohl nicht?

Gruss Holger

hathor 27. Sep 2015 21:50

AW: Mediaplayer Firemonkey
 
Da gibt es was:

Delphi-Quellcode:
uses ... FMX.Media.Win,..., mediaPlayerStretchFix;

procedure TfrmMain.Button2Click(Sender: TObject);
var mp: TWindowsMedia;
   filename : String;
begin
filename:= 'F:\_ForExportOnly\SDXC64\TEST6.mp4'; // DEIN Videofile !
  mp:= TWindowsMedia.create(filename);
  mp.Control:= MediaPlayerControl1;
  mp.Play;
  mp.Stretch; // <--------------
end;
---------------------
Delphi-Quellcode:
unit mediaPlayerStretchFix; //20150927

interface

uses Winapi.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.

Harry Stahl 27. Sep 2015 23:01

AW: Mediaplayer Firemonkey
 
Ja klar, Classhelper geht natürlich auch (oft).

Hier nur 3 kurze Anmerkungen:

1. Man muss nicht unbedingt ein eigenes Media-Objekt erzeugen. Man kann die ergänzte Funktion auch bei den üblicherweise verwendeten Komponenten mit

Delphi-Quellcode:
TWindowsMedia (Mediaplayer1.Media).stretch;
aufrufen.

2. Das ist natürlich nur eine Lösung für Windows, wollte man eine Plattform-übergreifende Lösung, müsste man auch Classhelper für FMX.Media.Mac.pas, FMX.Media.iOS.pas und FMX.Media.Android.pas erstellen.

3. Gut wäre auch, man macht einen Feature-Request und regt beim Quality-Portal an, eine entsprechende Erweiterung in die bestehende Komponente einzubauen.

mkinzler 28. Sep 2015 08:50

AW: Mediaplayer Firemonkey
 
http://www.fmxexpress.com/record-pla...droid-and-ios/

hathor 28. Sep 2015 10:01

AW: Mediaplayer Firemonkey
 
Zitat:

Zitat von Harry Stahl (Beitrag 1317085)
Man kann die ergänzte Funktion auch bei den üblicherweise verwendeten Komponenten mit

Delphi-Quellcode:
TWindowsMedia (Mediaplayer1.Media).stretch;
aufrufen.

Ja, das funktioniert sehr gut:
Delphi-Quellcode:
procedure TfrmMain.FormResize(Sender: TObject);
begin
if (MediaPlayer1.State = TMediaState.Playing) then
TWindowsMedia (Mediaplayer1.Media).stretch;
end;

holgerderchsler 28. Sep 2015 14:33

AW: Mediaplayer Firemonkey
 
Super, viele Ideen. werde heute Abend am PC die tollen Ideen probieren umzusetzen, sage euch dann, wie es gelaufen ist.

Liebe Grüsse und vielen Dank.

Holger

Sir Rufo 28. Sep 2015 15:29

AW: Mediaplayer Firemonkey
 
Nur der Vollständigkeit halber, wie man das plattformübergreifend aufbauen sollte:
  • Ziel:
    Delphi-Quellcode:
    unit dp_186753.Forms.MainForm;

    interface

    uses
      System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants,
      FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs, FMX.Media,
      FMX.Controls.Presentation, FMX.StdCtrls;

    type
      TMainForm = class( TForm )
        MediaPlayer1: TMediaPlayer;
        MediaPlayerControl1: TMediaPlayerControl;
        Button1: TButton;
        procedure Button1Click( Sender: TObject );
      private
        { Private-Deklarationen }
      public
        { Public-Deklarationen }
      end;

    var
      MainForm: TMainForm;

    implementation

    {$R *.fmx}

    uses
      FMX.Media.Helpers; // 1 unit einbinden

    procedure TMainForm.Button1Click( Sender: TObject );
    begin
      MediaPlayerControl1.Stretch; // stretch aufrufen
    end;

    end.
  • Umsetzung
    Delphi-Quellcode:
    unit FMX.Media.Helpers;

    // Hier wird das Routing für die unterschiedlichen Plattformen erledigt

    interface

    uses
      FMX.Media;

    type
      TMediaPlayerControlHelper = class helper for TMediaPlayerControl
      public
        procedure Stretch;
      end;

      TMediaPlayerHelper = class helper for TMediaPlayer
      public
        procedure Stretch;
      end;

      TMediaHelper = class helper for TMedia
      public
        procedure Stretch;
      end;

    implementation

    uses
      FMX.Consts
    {$IFDEF MSWINDOWS}
        , FMX.Media.Win, FMX.Media.Win.Helpers
    {$ENDIF}
    {$IFDEF MACOS}
        , FMX.Media.AVFoundation
    {$IFDEF IOS}
        , FMX.Media.iOS // , FMX.Media.iOS.Helpers { TODO }
    {$ELSE}
        , FMX.Media.Mac // , FMX.Media.Mac.Helpers { TODO }
    {$ENDIF}
    {$ENDIF}
    {$IFDEF ANDROID}
        , FMX.Media.Android // , FMX.Media.Android.Helpers { TODO }
    {$ENDIF ANDROID}
        ;

    { TMediaHelper }

    procedure TMediaHelper.Stretch;
    begin
    {$IFDEF MSWINDOWS}
      // Windows
      if Self is TWindowsMedia
      then
        TWindowsMedia( Self ).Stretch;
    {$ENDIF}
    {$IFDEF MACOS}
    {$IFDEF IOS}
      // iOS
    {$ELSE}
      // OSX
    {$ENDIF}
    {$ENDIF}
    {$IFDEF ANDROID}
      // Android
    {$ENDIF ANDROID}
    end;

    { TMediaPlayerHelper }

    procedure TMediaPlayerHelper.Stretch;
    begin
      if Assigned( Media ) and ( State = TMediaState.Playing )
      then
        Media.Stretch;
    end;

    { TMediaPlayerControlHelper }

    procedure TMediaPlayerControlHelper.Stretch;
    begin
      if Assigned( MediaPlayer )
      then
        MediaPlayer.Stretch;
    end;

    end.
    Delphi-Quellcode:
    unit FMX.Media.Win.Helpers;

    interface

    uses
      FMX.Media,
      FMX.Media.Win;

    type
      TWindowsMediaHelper = class helper for TWindowsMedia
        procedure Stretch;
      end;

    implementation

    uses
      FMX.Controls,
      FMX.Forms,
      FMX.Platform.Win,
      FMX.Types,
      System.Classes,
      System.Types,
      Winapi.DirectShow9,
      Winapi.Windows;

    { TWindowsMediaHelper }

    procedure TWindowsMediaHelper.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;

    var
      leFWnd                : HWND;
      leControl             : TControl;
      leFVMRWindowlessControl: IVMRWindowlessControl9;
    begin
      leFWnd                 := Self.FWnd;
      leControl              := TControl( FControl );
      leFVMRWindowlessControl := Self.FVMRWindowlessControl;

      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;

    end.

holgerderchsler 29. Sep 2015 14:14

AW: Mediaplayer Firemonkey
 
So habe mal den Quellcode, wie es hathor geschrieben hat umgesetzt. Die unit mediaPlayerStretchFix; //20150927 eingebunden und tatsächlich, eine neue Funktion stretch steht bereit. Ich habe den MediaControl auf Client gestellt, aber leider wird das Bild nicht grösser.

Wo habe ich was falsch gemacht oder übersehen?

Liebe Grüsse

Holger

hathor 29. Sep 2015 14:44

AW: Mediaplayer Firemonkey
 
Liste der Anhänge anzeigen (Anzahl: 1)
Ohne Sourcecode kann man nicht einmal raten...

Delphi-Quellcode:
procedure TForm1.FormResize(Sender: TObject);
begin
if (MediaPlayer1.State = TMediaState.Playing) then
TWindowsMedia (Mediaplayer1.Media).stretch;
end;
Nichts vergessen?

holgerderchsler 29. Sep 2015 15:57

AW: Mediaplayer Firemonkey
 
Alles klar.

Delphi Quellcode

Delphi-Quellcode:
unit unitmedia;
interface

uses
  System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants,
  FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs, FMX.Media.Win,
  FMX.Controls.Presentation, FMX.StdCtrls,mediaPLayerStretchFix,
  FMX.Media, FMX.Objects;

type
  Tplayer = class(TForm)
    OpenDialog1: TOpenDialog;
    Button1: TButton;
    MediaPlayer1: TMediaPlayer;
    MediaPlayerControl1: TMediaPlayerControl;
    Button2: TButton;
    Button3: TButton;
    Button4: TButton;
    Image1: TImage;
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
    procedure Button3Click(Sender: TObject);
    procedure OpenDialog1Close(Sender: TObject);
    procedure Button4Click(Sender: TObject);
  private
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
  end;

var
  player: Tplayer;

implementation

{$R *.fmx}

procedure Tplayer.Button1Click(Sender: TObject);
var pfad: String;
begin
     pfad := 'D:\PROGRAMME\SEHTEST mit externen Bildern V3\Win32\Debug\Filme\';
     OpenDialog1.InitialDir := pfad;
     OpenDialog1.Execute;
end;

procedure Tplayer.Button2Click(Sender: TObject);
begin
  MediaPlayer1.Play;
end;

procedure Tplayer.Button3Click(Sender: TObject);
begin
  MediaPlayer1.Stop;
end;

procedure Tplayer.Button4Click(Sender: TObject);
begin
     if (MediaPlayer1.State = TMediaState.Playing) then
     begin
      TWindowsMedia(MediaPlayer1).stretch;
     end;

end;

procedure Tplayer.OpenDialog1Close(Sender: TObject);
begin
    MediaPlayer1.FileName := OpenDialog1.FileName;
end;

end.

die unit mediaPLayerStretchFix habe ich genau so eingegeben, wie von Dir geschrieben.





Wäre denn ein OleContainer für einen externen Player auch möglich, so wie der vcl player ?


Liebe Grüsse Holger

hathor 29. Sep 2015 16:48

AW: Mediaplayer Firemonkey
 
Du solltest den Code in Resize aufrufen:
Delphi-Quellcode:
procedure TForm1.FormResize(Sender: TObject);
begin
if (MediaPlayer1.State = TMediaState.Playing) then
TWindowsMedia (Mediaplayer1.Media).stretch;
end;
Sei NICHT so stur - mit dem Button macht das keinen Sinn!

Wenn Du es UNBEDINGT mit dem Button machen willst:
Lösche den OnResize-Eintrag und mache es so:
Delphi-Quellcode:
procedure TForm1.Button1Click(Sender: TObject);
begin
FormResize(Self);
end;

procedure TForm1.FormResize(Sender: TObject);
begin
if (MediaPlayer1.State = TMediaState.Playing) then
TWindowsMedia (Mediaplayer1.Media).stretch;
end;

holgerderchsler 29. Sep 2015 18:33

AW: Mediaplayer Firemonkey
 
Keine Ahnung, wie Du darauf kommst, ich sei stur, aber egal...
Ich habe das jetzt in Resize eingegeben, der Button war ja zunächst als Versuchsobjekt gedacht, später sollte das automatisch laufen auch egal..
Leider bleibt das Bild in der Ausgangsgrösse..

Liebe Grüsse Holger

hathor 29. Sep 2015 20:25

AW: Mediaplayer Firemonkey
 
Delphi-Quellcode:
procedure TForm1.Button1Click(Sender: TObject);
begin
if OpenDialog1.Execute then
   MediaPlayer1.FileName:= OpenDialog1.Filename;
   MediaPlayer1.Play;
   FormResize(Self);
end;

mkinzler 30. Sep 2015 04:48

AW: Mediaplayer Firemonkey
 
Besser

Delphi-Quellcode:
procedure TForm1.Button1Click(Sender: TObject);
begin
if OpenDialog1.Execute then
  begin
    MediaPlayer1.FileName:= OpenDialog1.Filename;
    MediaPlayer1.Play;
    FormResize(Self);
  end;
end;
Sonst wird ein Teil des Codes auch ausgehührt wenn der Dialog abgebrochen wird.

hathor 30. Sep 2015 06:38

AW: Mediaplayer Firemonkey
 
Typisch "Flüchtigkeitsfehler". Alles klar, danke!

mkinzler 30. Sep 2015 07:27

AW: Mediaplayer Firemonkey
 
Zitat:

Zitat von hathor (Beitrag 1317284)
Typisch "Flüchtigkeitsfehler". Alles klar, danke!

Das habe ich mir gedacht.

hathor 30. Sep 2015 08:04

AW: Mediaplayer Firemonkey
 
Natürlich ist es immer ratsam, am Ort möglicher Fehlerentstehungen Sicherungen einzubauen.
Aber in diesem OpenDialog-Fall wäre nichts passiert:
- wird bereits ein File abgespielt, wird es fortgesetzt, wenn KEIN anderes File ausgewählt wird
- wird KEIN File abgespielt und KEIN File ausgewählt, geschieht nichts.

Es greifen vor- und/oder nachgelagerte "Sicherungen".
Aber wenn man's ordentlich macht, wird kein überflüssiger Code ausgeführt...


Alle Zeitangaben in WEZ +1. Es ist jetzt 04:40 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz