0

I have built a mediaplayer application based on the PlayWin demo that comes with DSPack. I have built this in Delphi 10.4 Sydney. The primary file type I am focussing on is *.mp4. All this is working fine.

I would like to provide the capability to move to the middle of the currently plying video and continue playing to the end of the video.

I have searched extensively on StackOverflow and attempted any solutions that appear correct. Nothing has worked.

My current attempt is:

procedure TMediaPlayer.btnMoveToMidVideoClick(Sender: TObject);
Var
  sgBefore: String;
  sgAfter: String;
  MediaSeeking: IMediaSeeking;
  Start: Int64;
  Stop: Int64;
begin
  FilterGraph.Active := true;
  VideoWindow.FilterGraph:= FilterGraph;
  FilterGraph.RenderFile('S:\iTube Studio Downloaded\6.5 HP Greyhound Engine\6_5HP_Best Way To Clean a Honda Style Carburetor - Vide0.mp4');
  FilterGraph.QueryInterface(IMediaSeeking, MediaSeeking);

  Start := 1200519 div 2;
  Stop := 1200519;

  MediaSeeking.SetPositions(Start, AM_SEEKING_AbsolutePositioning, Stop, AM_SEEKING_AbsolutePositioning);

  FilterGraph.Play;
end;

I HAVE NO IDEA WHERE TO GET THE START AND STOP VALUES FROM.

Can anyone figure out how to move to the middle of a currently playing video?

Dick Maley

Thank you in advance.

  • I don't have any experience working with DSPack so I can't give you direct answer. What I can tel you is that most of the times codecs aren't capable of changing movie position to any arbitrary frame but only to specific key frames. What are key frames? Key frame is a frame that is stored inside a video without compression. Non key frames are the ones that are compressed. Most commonly they are stored just as differentiation from the previous frame, so they don't take so much data. And in order to render such frame correctly you need information of previous frame. ... – SilverWarior Mar 13 '21 at 13:27
  • .. This is why most codecs and even video players live VLC only support seeking to nearest key frame. Some more advanced players like BS Player do seem to allow seeking to any arbitrary frame but they do this by first seeking to first key frame that is before desired frame and then silently playing the video to desired frame (quickly playing without rendering). – SilverWarior Mar 13 '21 at 13:32
  • Also I have noticed that you are using `AM_SEEKING_AbsolutePositioning` which I guess require you to pas specific frame numbers for start and end positions. Since you want to play your video from middle you might be better of to use Relative Positioning which guess would provide you to pass video position as percentage and not as specific frame. This way your code won't have to know how many frames are there in a video. – SilverWarior Mar 13 '21 at 13:37

1 Answers1

0

I thank you all for your ideas.

It can be done, Here is the code that achieved it.

Procedure TMediaPlayer.actVideoHalfWayExecute(Sender: TObject);
Var
  inThumbX: Integer;
  inThumbY: Integer;
  R: TRect;
Begin
  FillChar(R, 0, Sizeof(R));
  tbDSTrackBar.Perform(TBM_GETTHUMBRECT, 0, lparam(@r));
  inThumbX := (r.Left + r.Right) Div 2;
  inThumbY := (r.Top + r.Bottom) Div 2;
  tbDSTrackBar.MouseDown(mbLeft, [], inThumbX, inThumbY);
  tbDSTrackBar.Position := tbDSTrackBar.max Div 2;
  Application.processmessages();
  inThumbX := tbDSTrackBar.Width Div 2;
  tbDSTrackBar.MouseUp(mbLeft, [], inThumbX, inThumbY);
  Application.processmessages();
End;

However, I cheated. I modified TDSTrackBar in DSPack.pas from

  protected
    {@exclude}
    procedure Notification(AComponent: TComponent; Operation: TOperation); override;
    {@exclude}
    procedure MouseUp(Button: TMouseButton; Shift: TShiftState;
      X, Y: Integer); override;
    {@exclude}
    procedure MouseDown(Button: TMouseButton; Shift: TShiftState;
      X, Y: Integer); override;
    {@exclude}
    procedure Timer; dynamic;

To

  public
    {@exclude}
    procedure Notification(AComponent: TComponent; Operation: TOperation); override;
    {@exclude}
    procedure MouseUp(Button: TMouseButton; Shift: TShiftState;
      X, Y: Integer); override;
    {@exclude}
    procedure MouseDown(Button: TMouseButton; Shift: TShiftState;
      X, Y: Integer); override;
    {@exclude}
    procedure Timer; dynamic;

My objective was to move to the halfway point in the video and trackbar, however this code can be used to move any anywhere in the video and trackbar.

Thank you

Dick Maley