Jump to content
Tuts 4 You

How to play video from URL? (MASM)


Recommended Posts

Hi guys,

I would like to create a video player in my main dialog window (somewhere placed on it) and playing any direct video URL into that player so simple as possible. Something like an internet HTML 5 player or something. The question is how to do that? On MSDN you can find some mfplay documentation using MFPCreateMediaPlayer function. So I got the mfplay.dll (32bit) using Loadlibrary / GetProcAddress function to load dll & function MFPCreateMediaPlayer and was trying to execute this function with basic parameters and any on HDD video path or direct video URL from internet like this one. In both cases I get an error code back 0x80070002 (FILE_NOT_FOUND) (The system cannot find the file specified). Below a image from Olly...

Error_2024-04-02_224159.png.e2fcec8baacdf78e50f975c35834e06d.png

...but I don't know why. Do you know? Just using URL or Video path from HDD like "c:\testvideo.mp4" Maybe you have any tiny working sample code or maybe you know anything else I could use to get a player window in my dialog what can play direct video URLs etc. Just a simple one without any specials.

greetz

  • Like 2
Link to comment
jackyjask

Hey @LCF-AT

lets have some more fun! :)

so according to WinAPI it is deprecated, but well, who cares, right?

next, the 1st param gonna be not ASCII but wide string - LPCWSTR

are you passing in this string type?

it is not visible o your OllyDbg screen the input argument

YOur error FILE_NOT_FOUND might be the reason for that

...

lets start having the fun!

 

 

  • Like 1
Link to comment
Kurapica

Next challenge : Let's write a fully unbiased spectral 3d rendering engine with ASM 🤪

  • Haha 1
Link to comment

Hey guys,

as I said, I'm just looking for any function I could use to play any video file in a player device in a simple way. No idea what function there are already I could use for that thing. So if you have anything else in mind what would  be better / easier etc then tell me. The first parameter is a ASCII string to the video file on my HDD or ASCII URL of the direct video but in both cases I get that error back.

		.elseif ax == IDC_TEST
			invoke LoadLibrary,chr$("mfplay.dll")
			mov edi, eax
			invoke GetProcAddress,edi,chr$("MFPCreateMediaPlayer")
			mov esi, eax
			push offset g_pPlayer
			push hWin	<-- handle of my dialog window / app GUI
			push 0
			push NULL
			push TRUE
			push offset VIDEO_URL_2	<-- "C:\video.mp4"
			call esi

No idea what is wrong here.

greetz

Link to comment
5 hours ago, jackyjask said:

the 1st param gonna be not ASCII but wide string - LPCWSTR

^^^

  • Haha 1
Link to comment

Uhmmm! Why don't they just say it to use UNICODE strings instead of ANSI! Ok I tried it again using MultiByteToWideChar function to convert my ANSI string to Unicode and it seems to work and my video from HDD is playing in my app window. :) Coolio! The URL seems also to work to play that video directly on a static control. All good so far on a first view & test and just need to create some stop / pause / seek controls. Will see.

Can anyone tell me where the other functions are like CreateMediaItemFromURL? When I try to call it via LLA & GPA it fails = 0 and I even can not find any other functions inside of that dll only these...

6CE99E90   .text      Export     DllRegisterServer
6CE99EF0   .text      Export     DllUnregisterServer
6CE99F00   .text      Export     DllCanUnloadNow
6CE99F20   .text      Export     DllGetClassObject
6CE99F30   .text      Export     MFPCreateMediaPlayer
6CE9A0E0   .text      Export     MFPCreateMediaPlayerEx
6CEE6110   .text      Export     <ModuleEntryPoint>

...so I would like to create that callback routine to handle stop / play / unload etc stuff but as always the descriptions are not my thing to follow them anyhow good. Can anyone build / compile a small exe file using that function to play any example video + using callback / pause stop event things etc? So I think that would be better to follow the code in Olly itself to get some info's I can do anything with. :)

My test code at the moment is this...

		invoke LoadLibrary,chr$("mfplay.dll")
		mov MFPLAY_BASE, eax
		invoke GetProcAddress,MFPLAY_BASE,chr$("MFPCreateMediaPlayer")
		mov _MFPCreateMediaPlayer, eax


		.elseif ax == IDC_TEST
			invoke lstrlen,addr VIDEO_URL_2
			invoke MultiByteToWideChar,CP_ACP,0,addr VIDEO_URL_2,-1,addr ouptbuf,eax
			invoke GetDlgItem,hWin,IDC_PLAYERSTATIC
			mov ebx, eax
			.if g_pPlayer
				invoke _MFPCreateMediaPlayer,offset ouptbuf,TRUE,NULL,0,ebx,offset g_pPlayer
			.else
				; CreateMediaItemFromURL HOW?
			.endif

...but I can do this only one time to create the player object g_pPlayer and next time I must use that CreateMediaItemFromURL function (not there etc). Maybe you have some better advice for me to understand that mfplay description. By the way, here I found also a code of it..

https://github.com/MicrosoftDocs/win32/blob/docs/desktop-src/medfound/mfplay-tutorial--video-playback.md

...and using a SafeRelease function / using...

template <class T> void SafeRelease(T **ppT)
{
    if (*ppT)
    {
        (*ppT)->Release();
        *ppT = NULL;
    }
}

....with a Release function? I don't have a Release() function so what is it / what to call?

greetz

  • Like 1
Link to comment

Read the MSDN and pay attention, it's all there. :)

Last parameter of MFPCreateMediaPlayer receives a pointer to player's COM interface, which you can then use to call CreateMediaItemFromURL and other funcions.

It's possible to use COM interfaces in MASM but in general it's a pain in the butt. Good place to get started: https://www.japheth.de/COMnASM.html

 

Before you complain - it is what it is, we don't know why it's like that, and we didn't create it. Please don't write long rambles about you not liking the answer. ;)

  • Like 1
  • Haha 2
  • Sad 1
Link to comment
fearless

I created a Uasm64 project in radasm and used uasm (https://www.terraspace.co.uk/uasm.html) to assemble it.

The release method (MFPlayer_Release) caused a crash for some reason, so i just commented it out, maybe someone else who knows COM and x64 will be able to spot the problem there. Also Uasm complained about 'Pause' in the method name - which matches to an x86-64 instruction called pause. So i added the option nokeyword at the top of the include file to handle that.

Some crashing occured during testing, might have been due to passing an unused parameter (hWin), so took that out of the procs, and possibly using rbx as a register. I decide to just use rcx as it was going to be used for the THIS pointer anyhow before calling with the call rax. Thought it might have something to do with shadow space allocation so tried some stuff with that as well, but it crashed with that addition so that was removed. Anyhow seems to be working now.

MFPlayTest x64.zip

Edited by fearless
  • Like 1
  • Thanks 2
Link to comment
Sean Park - Lovejoy
5 minutes ago, fearless said:

I created a Uasm64 project in radasm and used uasm (https://www.terraspace.co.uk/uasm.html) to assemble it.

The release method (MFPlayer_Release) caused a crash for some reason, so i just commented it out, maybe someone else who knows COM and x64 will be able to spot the problem there. Also Uasm complained about 'Pause' in the method name - which matches to an x86-64 instruction called pause. So i added the option nokeyword at the top of the include file to handle that.

Some crashing occured during testing, might have been due to passing an unused parameter (hWin), so took that out of the procs, and possibly using rbx as a register. I decide to just use rcx as it was going to be used for the THIS pointer anyhow before calling with the call rax. Thought it might have something to do with shadow space allocation so tried some stuff with that as well, but it crashed with that addition so that was removed. Anyhow seems to be working now.

MFPlayTest x64.zip 1.04 MB · 1 download

It plays the file incompletely but thanks for your effort.

Regards.

sean.

Link to comment

Hey guys,

thank for that work you made @fearless. :) I have test it and it works so far but that COM thing I did not understand yet. I have just a little tiny & small addon questions if you don't mind.

1.) How to clear the static control window to remove that video from? When I press STOP then I can still see the last video image. I would like to clean it if possible.

2.) How to load a next video? Somehow I must use that IMFPMediaPlayer.CreateMediaItemFromURL right? Can you tell me how to handle that?

greetz

Link to comment
fearless
51 minutes ago, Sean Park - Lovejoy said:

It plays the file incompletely but thanks for your effort.

Regards.

sean.

Its only a 5 seconds sample video used for testing, so should play to the end and/or allow the pause/step/stop/play to work

  • Like 1
Link to comment
Sean Park - Lovejoy
19 minutes ago, fearless said:

Its only a 5 seconds sample video used for testing, so should play to the end and/or allow the pause/step/stop/play to work

 

Regards.

sean.

 

  • Like 1
Link to comment
1 hour ago, Sean Park - Lovejoy said:

It plays the file incompletely

Works fine here.

  • Like 1
Link to comment
fearless
17 minutes ago, LCF-AT said:

Hey guys,

thank for that work you made @fearless. :) I have test it and it works so far but that COM thing I did not understand yet. I have just a little tiny & small addon questions if you don't mind.

1.) How to clear the static control window to remove that video from? When I press STOP then I can still see the last video image. I would like to clean it if possible.

2.) How to load a next video? Somehow I must use that IMFPMediaPlayer.CreateMediaItemFromURL right? Can you tell me how to handle that?

greetz

Not sure, there is a method to clear an item, but that releases the currently queued media file, so you would then need to call CreateMediaItemFromURL, pszURL, FALSE, 0, NULL and then in the IMFPMPC_OnMediaPlayerEvent check for MFP_EVENT_TYPE_MEDIAITEM_CREATED and then call SetMediaItem, check for MFP_EVENT_TYPE_MEDIAITEM_SET in IMFPMPC_OnMediaPlayerEvent, then a call to play. Might have to subclass the static control and handle the paint as described here: https://learn.microsoft.com/en-us/windows/win32/medfound/mfplay-tutorial--video-playback

Not sure if i will get a chance to look at that, currently have other projects ongoing at the moment.

Im using windows 10 here, so maybe there is some difference with the OS. Also make sure the file was cleared from the internet before unzipping - right click the zip, properties, uncheck the box. Try to unzip to a neutral folder, like c:\test or something, just to rule out any permission issues with protected folders. Does the same thing occur with the x86 version or just the x64 one?

If its ok with the x86 one and not with the x64 then could be a programming error somewhere. COM isn't my field so I may have missed something or done something that just doesnt quite work.

  • Like 1
  • Thanks 1
Link to comment

Hi again,

how to call this NOT function CreateMediaItemFromURL? I tried something like this...

		.elseif ax == IDC_TEST
			invoke lstrlen,addr VIDEO_URL_2
			invoke MultiByteToWideChar,CP_ACP,0,addr VIDEO_URL_2,-1,addr ouptbuf,eax
			invoke MFPlayer_URL,hWin,pMediaPlayer

MFPlayer_URL PROC USES EBX hWin:DWORD, pMP:DWORD
    
    .IF pMP == 0
        ret
    .ENDIF    
    mov eax, pMP
    mov ebx, [eax]
    .IF ebx == 0
        ret
    .ENDIF
    mov eax, [ebx].IMFPMediaPlayer.CreateMediaItemFromURL
    .IF eax == 0
        ret
    .ENDIF

    push eax
    pop edi
    
    
    push 0
    push 0
    push FALSE
    push offset ouptbuf <--- New file path UNICODE
    call edi	<--- IMFPMediaPlayer.CreateMediaItemFromURL

    ret
MFPlayer_URL ENDP

...but it crash inside of that COM function. Just wanna know how to handle it right after the first use / call of MFPCreateMediaPlayer what does create that object and on next videos I wanna load / play etc I have to use that CreateMediaItemFromURL function what  is not a real function so I can not use it lile invoke CreateMediaItemFromURL etc. How to put that new video file path into that object to play the other video?

greetz

Link to comment
fearless

Some small success with the x86 version in getting it to play 2 different mp4 test files, using the CreateMediaItemFromURL - so will post an update probably tomorrow at some point. Still working on the clearing of the UI - tried subclassing a static control and handling WM_PAINT, which shows the initial blank drawing, but still shows the video regardless after it has started to play and is stopped or a different media file is queued for play. Probably will try with a brand new window class instead of subclassing a static to see if that works with the WM_PAINT. Havent looked at the x64 version since.

  • Like 1
Link to comment
jackyjask

Interesting...

tried to compile the x64 project using masm64, got tons of errors, eg

..........
MFPlayTest.asm(394) : error A2008:syntax error : .ENDIF
MFPlayTest.asm(406) : error A2008:syntax error : Invoke
MFPlayTest.asm(415) : error A2008:syntax error : WinMainCRTStartup
MFPlayTest.asm(416) : fatal error A1012:error count exceeds 100; stopping assembly

 

Link to comment
fearless

Unfortunately ML64 doesn't support .IF/.ELSE/.ENDIF or Invoke and a few other things - theses features where removed by Microsoft for ML64/Masm 64 - that's why I use Uasm as it has the support of the Masm x86 features but also in x64. I also use the WinInc project for the includes using them with Uasm instead of the regular masm32/64 sdk includes.

Attached is v1.0.0.1 of the test/demo/example showing that it can play 2 different mp4 samples using the CreateMediaFromURL etc.

I have had no success with changing the UI on the video player. I think the player window is subclassed by the MFPlay and it handles the drawing. In some examples it suggests you can draw in the window if its not playing, but I couldnt get that to work, maybe if its a top level form and not a child window it might work. Best I could do is do a step when stopped. Another option would be to hide the player window when finished/stopped and show it when playing, and have some other default window underneath.

Maybe someone else can play around with it and can figure out.

 

MFPlayTest-1001.zip

  • Like 1
  • Thanks 2
Link to comment

Hi again,

thanks for the new source @fearless. :) Works good so far to switch the videos etc. So I just have another tiny question about that pre loading of a video into the COM object. In the example app you did add 2 query buttons to prepare video 1 or video 2 to make them ready to play. Just wanna know whether it's possible to show the first video image of the video itself when I switch the video without to start the playing it? Do you know what I mean right? When I press query button 1 it should show the first video frame of video 1 and same in case of any other video. Just wanna know whether this could be possible here too. So I thought it would be doable when using the STEP function once like this...

		.elseif ax == IDC_TEST
			Invoke MFPlayer_Stop, pMediaPlayer
			Invoke MFPlayer_Clear, pMediaPlayer
			Invoke MFPlayer_Url, pMediaPlayer, Addr szWideTestURL2
			mov bVideoStopped, TRUE
			Invoke MFPlayer_Step, pMediaPlayer	<---

...but seems not to work to make any step / displaying the video frame etc. But when I load the next video (is not showing in static control) and press then the STEP button then it works to show the first video frame. Why? Just would like to load the video and do a first STEP call to get that video displaying in my static control. Not sure why its not working with the code above. Maybe you got an idea about that. Thanks.

greetz

  • Like 1
Link to comment
fearless

Yeh I tried that as well, but no luck. I don't know. Perhaps someone else will know? Maybe there is some other third party library for displaying videos on github or somewhere as an alternative.

  • Like 1
Link to comment

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...