Recent

Author Topic: Multithreading vrs. async  (Read 6916 times)

user5

  • Sr. Member
  • ****
  • Posts: 357
Multithreading vrs. async
« on: July 06, 2015, 04:05:55 am »
I'm trying to learn how to do some simple multithreading because I need to play several videos simultaneously. I already know that I can play them together using mplayer but I also need them to start at the same moment. The code below is what I have so far but when I press button1 the beeping sound works but mplayer doesn't. Can anyone enlighten me or is there an async way to do this without multithreading?

I previously posted a query in the Multimedia section of this forum about mplayer and MPlayerControl and I figured out how to use MPlayerControl but my main concern now is about multithreading. If you know what I'm doing wrong then please show me the correct code. I would be so grateful.

Code: [Select]

type

  { TForm1 }

  TForm1 = class(TForm)
    Button1: TButton;
    MPlayerControl1: TMPlayerControl;
    procedure Button1Click(Sender: TObject);
  private
    { private declarations }
  public
    { public declarations }
  end;

  TMyWorkerThread1 = class(TThread)
  public
   procedure Execute; override;
  end;

var
  Form1: TForm1;

implementation

{$R *.lfm}

{ TForm1 }


procedure TMyWorkerThread1.Execute;
begin
 sound(350);
 MPlayerControl1.play;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
 MPlayerControl1.FileName := 'c:\temp15\bin\film1.mpg';
 MPlayerControl1.MPlayerPath:='c:\temp38\mplayer.exe';
 TMyWorkerThread1.Create(false);
end;


end.

user5

  • Sr. Member
  • ****
  • Posts: 357
Re: Multithreading vrs. async
« Reply #1 on: July 06, 2015, 05:02:59 pm »
The problem with the example code I posted in my previous message is that the thread doesn't seem to have access to the form.

Multithreading aside, basically what I need to do is to start and run two or more MPlaayerControls (MPlayerControl1-MPlayerControl2) at the same time. I tried nestling two virtual button clicks together inside a third buttonclick but that only ran the first buttonclick.

taazz or somebody else, could you help me with this as you've helped me before? This is really important to me but multithreading is so difficult. I've been scouring the Web for info.

taazz

  • Hero Member
  • *****
  • Posts: 5368
Re: Multithreading vrs. async
« Reply #2 on: July 07, 2015, 03:48:39 am »
I'm sorry I do not have any experience with video playback or mplayer library/application. I do know that lcl is not thread safe and you can not use threads to update any lcl control so you only have the async path to travel but I can't help.
Good judgement is the result of experience … Experience is the result of bad judgement.

OS : Windows 7 64 bit
Laz: Lazarus 1.4.4 FPC 2.6.4 i386-win32-win32/win64

BitBangerUSA

  • Full Member
  • ***
  • Posts: 183
Re: Multithreading vrs. async
« Reply #3 on: July 07, 2015, 05:11:11 am »
just a thought - why not allow multiple instances of your program to run instead of multiple threads in one instance?
i also have no experience with MPlayer... but i see that VLC can handled multiple instances - each running a given video...
Lazarus Ver 2.2.6 FPC Ver 3.2.2
Windows 10 Pro 64-bit

kapibara

  • Hero Member
  • *****
  • Posts: 610
Re: Multithreading vrs. async
« Reply #4 on: July 07, 2015, 06:35:43 am »
I tried MPLayer briefly after reading your post and accidentally spawned close to 200 forms, each playing the same video. Shutting the computer down was the tricky part!  8)

Having two MPLayers on a single form didn't seem to work, only one player worked then. But using several forms, or maybe multiple TFrames per form with each a MPlayer could be worth trying.
Lazarus trunk / fpc 3.2.2 / Kubuntu 22.04 - 64 bit

user5

  • Sr. Member
  • ****
  • Posts: 357
Re: Multithreading vrs. async
« Reply #5 on: July 07, 2015, 07:13:34 am »
In case anyone is interested, below is the solution for loading multiple movies using MPlayer and then having them start and run all at the same time. This message posting will at least put this information into the Lazarus forum database so that in the future anyone searching the Web for a solution to the same problem will be directed to this great forum for the answer.

First of all, I did learn how to do multithreading but I also found out that it's not a good idea or even impossible to access and use the components of a form (the first thread) from inside another secondary thread, as taazz said. Thanks so much taazz, BitBangerUSA, kapibara and jc99 (re: previous multimedia posting) for responding. You guys are the greatest.

The unit below, or a variation of it, will load multiple movies into a form and then play them at the same time.

All praise to Lazarus.

Code: [Select]
unit Unit1;

{$mode objfpc}{$H+}

interface

uses
  Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls,
  MPlayerCtrl;

type

  { TForm1 }

  TForm1 = class(TForm)
    Button1: TButton;
    Button2: TButton;
    Button3: TButton;
    Button4: TButton;
    MPlayerControl1: TMPlayerControl;
    MPlayerControl2: TMPlayerControl;
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
    procedure Button3Click(Sender: TObject);
    procedure Button4Click(Sender: TObject);
  private
    { private declarations }
  public
    { public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.lfm}

{ TForm1 }

//Procedure below loads one movie and freezes it on the first frame.
procedure TForm1.Button1Click(Sender: TObject);
begin
 MPlayerControl1.FileName := 'c:\temp15\bin\film1.mpg';
 MPlayerControl1.MPlayerPath:='c:\temp38\mplayer.exe';
 MPlayerControl1.play;
 MPlayerControl1.SendMPlayerCommand('Pause');
end;

//Procedure below loads the next movie and freezes it on the first frame.
procedure TForm1.Button2Click(Sender: TObject);
begin
 MPlayerControl2.FileName := 'c:\temp15\bin\news4.mpg';
 MPlayerControl2.MPlayerPath:='c:\temp38\mplayer.exe';
 MPlayerControl2.play;
 MPlayerControl2.SendMPlayerCommand('Pause');
end;

//Procedure below plays both movies practically at the same time. The
//"Pause" command is a toggle which pauses the movies on its first
//usage and then runs them on the next usage.
procedure TForm1.Button3Click(Sender: TObject);
begin
 MPlayerControl1.SendMPlayerCommand('Pause');
 MPlayerControl2.SendMPlayerCommand('Pause');
end;

//This procedure stops both movies.
procedure TForm1.Button4Click(Sender: TObject);
begin
 MPlayerControl1.stop;
 MPlayerControl2.stop;
end;

end.

balazsszekely

  • Guest
Re: Multithreading vrs. async
« Reply #6 on: July 07, 2015, 07:32:40 am »
Quote
@user5
First of all, I did learn how to do multithreading but I also found out that it's not a good idea or even impossible to access and use the components of a form
It is possible, but you have to use the Synchronize method(See attachment). 

jc99

  • Hero Member
  • *****
  • Posts: 553
    • My private Site
Re: Multithreading vrs. async
« Reply #7 on: July 07, 2015, 07:49:35 am »
Hi user5, generaly using the pause function is a good idea to get a syncronous start.
but instead of using 
Code: [Select]
MPlayerControl1.SendMPlayerCommand('Pause');
have you tried
Code: [Select]
MPlayerControl1.Paused:= true; // false

If it works, then the unit would look like:
Code: [Select]
unit Unit1;

{$mode objfpc}{$H+}

interface

uses
  Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls,
  MPlayerCtrl;

type

  { TForm1 }

  TForm1 = class(TForm)
    Button1: TButton;
    Button2: TButton;
    Button3: TButton;
    Button4: TButton;
    MPlayerControl1: TMPlayerControl;
    MPlayerControl2: TMPlayerControl;
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
    procedure Button3Click(Sender: TObject);
    procedure Button4Click(Sender: TObject);
  private
    { private declarations }
  public
    { public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.lfm}

{ TForm1 }

//Procedure below loads one movie and freezes it on the first frame.
procedure TForm1.Button1Click(Sender: TObject);
begin
 MPlayerControl1.FileName := 'c:\temp15\bin\film1.mpg';
 MPlayerControl1.MPlayerPath:='c:\temp38\mplayer.exe';
 MPlayerControl1.play;
 MPlayerControl1.Paused:= true; // <-----------------------------
end;

//Procedure below loads the next movie and freezes it on the first frame.
procedure TForm1.Button2Click(Sender: TObject);
begin
 MPlayerControl2.FileName := 'c:\temp15\bin\news4.mpg';
 MPlayerControl2.MPlayerPath:='c:\temp38\mplayer.exe';
 MPlayerControl2.play;
 MPlayerControl2.Paused:= true; // <-----------------------------
end;

//Procedure below plays both movies practically at the same time.
procedure TForm1.Button3Click(Sender: TObject);
begin
 MPlayerControl1.Paused:= false; // <-----------------------------
 MPlayerControl2.Paused:= false; // <-----------------------------
end;

//This procedure stops both movies.
procedure TForm1.Button4Click(Sender: TObject);
begin
 MPlayerControl1.stop;
 MPlayerControl2.stop;
end;

end.
If this works, It's much clearer what happens.
and it's theoreticly possible, if a pause command missed, that with hit of button3 you stop the one and let the other play.
If you also what Button3 to pause the movie again, you have to use a toggle-Variable like:
Code: [Select]
//Procedure below plays(& pauses) both movies practically at the same time.
procedure TForm1.Button3Click(Sender: TObject);
var lToggle: boolean; // local toggle variable
begin
 lToggle := not MPlayerControl1.Paused; // Use MPC1 as master
 MPlayerControl1.Paused:= lToggle; // Set the new pause-state
 MPlayerControl2.Paused:= lToggle; //   to the same value.
end;
Have fun  :)

@GetMem:
Everything that is not necessary is unnecessary and mostly comes back to you.
Saying, if it can be done easily without MT, don't use it.
OS: Win XP x64, Win 7, Win 7 x64, Win 10, Win 10 x64, Suse Linux 13.2
Laz: 1.4 - 1.8.4, 2.0
https://github.com/joecare99/public
'~|    /''
,_|oe \_,are
If you want to do something for the environment: Twitter: #reduceCO2 or
https://www.betterplace.me/klimawandel-stoppen-co-ueber-preis-reduzieren

user5

  • Sr. Member
  • ****
  • Posts: 357
Re: Multithreading vrs. async
« Reply #8 on: July 07, 2015, 08:08:39 am »
I stand corrected, GetMem. Now that you mention it, during my investigations I do recall reading about the Synchronize method and that it could be used to access the form components but I haven't yet learned how to use it properly.

I'll download and take a look at your message attachment. Multithreading is one of the most difficult things that I've ever encountered.

Thanks to you also, for your current and past help. It's very appreciated.

By the way, I reckon that "Play" could be used instead of "Pause" in the Button3Click procedure shown in my previous message.

I can't tell ya how happy I am to have something that plays multiple videos.

jc99, I just got and read your message a moment before I posted this message. Thanks and I will keep what you said about the "Pause" command in mind.

user5

  • Sr. Member
  • ****
  • Posts: 357
Re: Multithreading vrs. async
« Reply #9 on: July 07, 2015, 08:56:40 am »
One last note: BitBangerUSA, I've seen VLC mentioned many times on the Web but I've never used it. I don't know if there is a  component .lpk package for it that allows it to be plugged into Lazarus as easily and transparently as MPlayer but I do know that it's about 3 Mb larger than MPlayer.

jc99

  • Hero Member
  • *****
  • Posts: 553
    • My private Site
Re: Multithreading vrs. async
« Reply #10 on: July 07, 2015, 06:41:36 pm »
One last note: BitBangerUSA, I've seen VLC mentioned many times on the Web but I've never used it. I don't know if there is a  component .lpk package for it that allows it to be plugged into Lazarus as easily and transparently as MPlayer but I do know that it's about 3 Mb larger than MPlayer.
... But's it's more common, most of the systems I came across have it already installed.
MPlayer may be a good, small alternative. But it's still an alternative.
Maybe you could first try to find vlc then Mplayer, and then offer the user to download one of them.
OS: Win XP x64, Win 7, Win 7 x64, Win 10, Win 10 x64, Suse Linux 13.2
Laz: 1.4 - 1.8.4, 2.0
https://github.com/joecare99/public
'~|    /''
,_|oe \_,are
If you want to do something for the environment: Twitter: #reduceCO2 or
https://www.betterplace.me/klimawandel-stoppen-co-ueber-preis-reduzieren

taazz

  • Hero Member
  • *****
  • Posts: 5368
Re: Multithreading vrs. async
« Reply #11 on: July 08, 2015, 03:51:45 am »
MPlayer may be a good, small alternative. But it's still an alternative.
Erm, vlc also is an alternative. I do not understand the logic.

To make things clear mplayer rely on the installed codecs on windows to play videos while vlc come with everything in the box and although it can use the windows installed codecs it usually do not have to. It is bigger yes but it packs more functionality that said it would probably be harder to share with your application since the libvlc.dll will use and need extra dlls which must be on the system path etc etc. It would probably be easier to use mplayer and prompt the user to install the missing codec.
« Last Edit: July 08, 2015, 04:31:53 am by taazz »
Good judgement is the result of experience … Experience is the result of bad judgement.

OS : Windows 7 64 bit
Laz: Lazarus 1.4.4 FPC 2.6.4 i386-win32-win32/win64

jc99

  • Hero Member
  • *****
  • Posts: 553
    • My private Site
Re: Multithreading vrs. async
« Reply #12 on: July 08, 2015, 11:32:53 am »
[qwuote author=jc99 link=topic=28980.msg182368#msg182368 date=1436287296]
Erm, vlc also is an alternative. I do not understand the logic.

To make things clear mplayer rely on the installed codecs on windows to play videos while vlc come with everything in the box and although it can use the windows installed codecs it usually do not have to. It is bigger yes but it packs more functionality that said it would probably be harder to share with your application since the libvlc.dll will use and need extra dlls which must be on the system path etc etc. It would probably be easier to use mplayer and prompt the user to install the missing codec.
I totally agree to the second Part.
The point I try to make You should Use what You find on the System.
BTW. You are right VLC started as an Alternative, but to me it's now pretty much Standard Player on many Systems, Not depending on external Codecs might be the reason for this. (at least it's the reason why I Use it.)

Ps: sorry for the funny capitals in the Post, I wrote this on mobile/cell-phpne in car sitting next to driver
OS: Win XP x64, Win 7, Win 7 x64, Win 10, Win 10 x64, Suse Linux 13.2
Laz: 1.4 - 1.8.4, 2.0
https://github.com/joecare99/public
'~|    /''
,_|oe \_,are
If you want to do something for the environment: Twitter: #reduceCO2 or
https://www.betterplace.me/klimawandel-stoppen-co-ueber-preis-reduzieren

taazz

  • Hero Member
  • *****
  • Posts: 5368
Re: Multithreading vrs. async
« Reply #13 on: July 08, 2015, 01:54:08 pm »
BTW. You are right VLC started as an Alternative, but to me it's now pretty much Standard Player on many Systems, Not depending on external Codecs might be the reason for this. (at least it's the reason why I Use it.)
You are giving to much meaning to the word alternative. In windows vlc, mplayer, and every other video player is alternative to the default windows media player then again if you are looking to migrate away from mplayer or vlc then windows media player becomes the alternative. There is no such think as main application and alternative applications per see only "in regard to ....." where to can be default, pre installed, my current choice, etc.
Good judgement is the result of experience … Experience is the result of bad judgement.

OS : Windows 7 64 bit
Laz: Lazarus 1.4.4 FPC 2.6.4 i386-win32-win32/win64

user5

  • Sr. Member
  • ****
  • Posts: 357
Re: Multithreading vrs. async
« Reply #14 on: July 08, 2015, 02:08:03 pm »
The latest posts on this thread are interesting and I also have some new information and a correction.

I have said that the example code that I posted would load a movie file and then freeze the movie on the first frame. After some further experimentation I discovered that this is NOT true. The code I posted freezes the movie frame on the SECOND frame, not the first.

There are probably some solutions to this and I'm looking at various alternatives, including additional MPlayer commands and parameters. In my case and for my particular purposes I could add an extra frame to the movie or display an image of the first frame over the MPlayerControl before the movie begins playing.

Some of you have mentioned VLC and I'm thinking about that. I did some more searching and it appears that there IS a component package for VLC called lazvlc.lpk so I'll probably check it out to see if it works out better than MPlayer. Thanks again.

 

TinyPortal © 2005-2018