FactoryXCode / MfPack

Delphi translations for Microsoft Media Foundation and related API's
Mozilla Public License 2.0
80 stars 22 forks source link

setPosition (setCurrentTime) frequently freezes the video but not the audio #52

Closed BazzaCuda closed 1 year ago

BazzaCuda commented 1 year ago

Hi,

I'm using \Samples\MfMediaEnginePlayer II as the foundation for building a media player. If I click on the progress bar (in the sample app) at different places going forward, the video picture often freezes, while the audio continues at the correct point. The form caption displays the correct position.

Clicking at previous points before the current position in the video seems to work every time. It's just seeking forwards that has a problem.

I've tried this on several different videos. Sometimes clicking forward works, sometimes it doesn't. Some videos behave better than others.

My other media player, based on the Windows Media Player ActiveX control doesn't have this problem, using the exact same video files as test files.

BazzaCuda commented 1 year ago

Just to add some further info, when the video gets stuck, clicking slightly earlier on the progress bar fixes the problem and both the video and audio continue correctly.

FactoryXCode commented 1 year ago

Hi, Thank you for reporting this issue.

Since the latest Windows updates Microsoft repaired some bugs (like freezing) on the IMFMediaEngine.

I tested your issues on Win 11 latest update, so I suggest the following:

Change the procedure TFeMediaEnginePlayer.prbProgressMouseUp:

procedure TFeMediaEnginePlayer.prbProgressMouseUp(Sender: TObject; Button: TMouseButton;
                                                  Shift: TShiftState; X, Y: Integer);
var
  hr: HResult;
  fPos: Double;

begin
  //FrameStep
 // gi_MediaEngine.FrameStep(True);

  if (X <= 0) then
    fPos:= 0.0
  else
    fPos:= ((X / prbProgress.Width) * gi_MediaEngine.pu_Duration);

  hr := gi_MediaEngine.SetPosition(fPos); // set new StartPosition

  if FAILED(hr) then
    begin
      ShowMessage(Format('SetPosition failed with error code: %d. We start all over again.', [hr]));
      gi_MediaEngine.SetPosition(0);
    end;
    //gi_MediaEngine.FrameStep(False);
    // Force play
    gi_MediaEngine.Play();
end;

Other methods to change are:

procedure TcMediaEngine.SetVolume(dVol: Double);
begin
  // Result := gi_MediaEngine.SetVolume(dVol); >> Don't use this directly,
  // but let it be done in the eventhandler, to prevent application is going into zombie state.
  pt_RequestMsg := rMsgSetVolume;
  pr_Volume := dVol;
  //while (pt_RequestMsg <> rMsgNone) do
  //  HandleMessages(GetCurrentThread());
end;

procedure TcMediaEngine.SetBalance(dBal: Double);
begin
  // Result := gi_MediaEngine.SetBalance(dBal); >> Don't use this directly,
  // but let it be done in the eventhandler, to prevent application is going into zombie state.
  pt_RequestMsg := rMsgSetBalance;
  pr_Balance := dBal;
  //while (pt_RequestMsg <> rMsgNone) do
  //  HandleMessages(GetCurrentThread());
end;

because the issues described in those methods have been fixed.

The next MfPack version (3.1.5) will be released soon, including those fixes.

Regards, Tony.

BazzaCuda commented 1 year ago

Hi Tony, thanks for your reply.

The problem I have is that hr := gi_MediaEngine.SetPosition(fPos) doesn't fail. The audio and pr_MediaEngine.GetCurrentTime both continue correctly from the new position. It's only the video picture that's effected.

Is there any way for my code to detect that the video picture has frozen when MMF thinks it's still playing? Starting over seems a bit extreme when [seemingly] all I need to do is to reissue the gi_MediaEngine.SetPosition(fPos) command for a few seconds before the CurrentTime. So far, this always rectifies the issue and both audio and video continue correctly from that slightly earlier position.

Thanks, Baz

FactoryXCode commented 1 year ago

Hi, The only way to see what can be a possible issue, is to check the event handlers of the MediaEngineClass. As you can see, for the most handlers you should implement the code when necessary. Regards, Tony.

BazzaCuda commented 1 year ago

Ok, thanks Tony. If I come up with a solution I'll post it here.

FactoryXCode commented 1 year ago

I uploaded the new version that seams to be doing better.

BazzaCuda commented 1 year ago

Thanks, I'll give it a try.