Jump to content
Tuts 4 You

VLC playing lags using Named Pipe


LCF-AT

Recommended Posts

Hi guys,

so I got following problem.So you know the VLC player which you can also use to enter direct URL addresses of video files to play them.If I use this function then all is working well and the video will played normaly and liquid as it should.Now I wrote a WinSock code to download the bytes and write them into a name pipe handle created for VLC process and started the player via ShellExecuteEx.The VLC player starts and does play the video reading the bytes from pipe.All is working fine so far but the video dosent play liquid and it lags / jerky etc so its not good and also not playing same if I enter the URL in VLC.So I dont find the problem reason in this case.In short my way looks so..

socket
connect
send
VLC_PIPE          ; create pipe & start VLC via ShellExecuteEx
////////////////////////
LOOP:
recv
WriteFile         ; datas to pipe handle
FlushFileBuffers

...as I said all is working except the problem that the video playing lags etc.The buffer for recv API is also large enough (1024*1024*10) I created with HeapAlloc API.Has anyone a idea what the problem could be?Maybe I need to use another WinSock APIs etc?Also if I pause the video for some seconds and let play it again then it still lags and many frames get lost.I also tried to use some commandline paramters for VLC in the SHELLEXECUTEINFO struct like --file-caching xy which also get set but it has no effect.Maybe you know whats going on and how to fix that problem.

Thanks

Link to comment

Personally, I have always had bad experiences with named pipes with lag as well as random crashing after the pipe just dies for no reason. I would recommend trying to implement your own pipe/protocol using memory mapped files instead. They are a lot more stable and much faster than named pipes in my testing in the past.

  • Like 2
Link to comment

Thanks for your answer so far but normaly I always use named pipes also with librtmp and never got any problems so far.So somehow it should work but how is the question.

Do you have any example or description how to do it with your method?

greetz

Link to comment

When I was developing some packet bots for MMORPGs I started testing with named pipes and in high-flow traffic named pipes always broke and gave me problems. They were extremely slow as well and were not suitable for ensuring the traffic was handled immediately / when it came in etc. I switched to memory mapped files to get what I needed working in a much better manner stress testing with 10,000 test packets of data in milliseconds. 

I don't have an example I can share, the source code for that stuff is copywritten and commercial, but I can help you create something similar.

In terms of the API needed, you will need:

  • CreateFileMapping
  • MapViewOfFile
  • UnmapViewOfFile
  • CloseHandle

With CreateFileMapping you will create a mapping with a total buffer size of what you want to allow to be placed into the buffer. Also with that, add some space at the start of the buffer for some custom data to handle when the buffer is clean/ready for more data.

So for example, you could have something like:

#define MMF_MAX_BUFFER_SIZE 0xA00004

The starting part of the buffer can hold something like:

struct Buffer
{
    unsigned int Timestamp;
    unsigned char Buffer[0xA00000];
};

The timestamp here could be used to hold when your buffer was last written to, useful to ensure that data is not being overwritten and is being handled by your app immediately. That said, you should send the data to VLC in whatever manner you are using, and clear the buffer to ready it for the next write immediately. You want to be sure that the MMF is always free and clear to keep accepting data. Another method you can do to ensure that is having a thread reading the MMF constantly for new data to be written (monitoring the Timestamp for a new value that is not 0 and does not match the previous timestamp it read) then copying the Buffer out into a local storage buffer to be handled within VLC etc.

  • Like 1
Link to comment

Hi again,

hhmm.So I tried already to copy all received bytes from revc to my own buffer location which has a size of 200000h bytes.Now I wait so long till my buffer has filled +100000h bytes and then I create the pipe and write the 100000h bytes to pipe handle and right after this I use the old buffer location again which gets filled / wriiten / erased etc.Problem now is that the video dosent play anymore.Just see the first few frames of the video then no more frames are comming but the time of VLC video is running forward normaly!?That really sucks.I also asked kao about that problem and kao said to use MSG_WAITALL flag for recv API and its working for kao but in my case I can't use this flag so it seems not to work on XP 32bit and just get WSAEOPNOTSUPP error on recv API.Uhmmm!Such a BS!

greetz

Link to comment
  • 1 month later...

Hi guys,

today I have a new question about pipes and set the question into this topic to prevent another topic.So its a tiny question and need some help so I dont get alone again.

Question: How to build unnamed / anonymous pipes instead named pipes?Following problem.I would like to execute a extern player app like VLC or MPC-HC but this time only with not named pipes.VLC player does support named pipes I can also use but MPC-HC dosent support named pipes only stdin pipe and here I have to use a other way I dont get it work.Below a short example for named pipe.

CreateNamedPipe = PIPEHANDLE
ShellExecuteEx   SHELL.cbSize, sizeof SHELLEXECUTEINFO
                 SHELL.fMask, SEE_MASK_NOCLOSEPROCESS
                 SHELL.lpFile,       offset VLC_PLAYPATH (c:\vlc.exe)
                 SHELL.lpParameters, offset PPARAM (stream://\\\.\pipe\streamer)
                 SHELL.nShow, SW_SHOW
ConnectNamedPipe (PIPEHANDLE)
WriteFile        (PIPEHANDLE) (writes bytes from my buffer into pipe)
FlushFileBuffers (PIPEHANDLE)
CloseHandle      (PIPEHANDLE)
TerminateProcess (SHELL.hProcess)

Now I need almost same just for unnamed pipe to get it also working with players like MPC-HC who dont support named pipes but here I do stuck and dont get it work.So maybe anyone of you does know it how the code has to look (API way) for unnamed pipe.If I see it right then I cant also use ShellExecuteEx API and need to use CreateProcess etc.Also tried this anyhow but dont get it work so I still do something wrong. :(

Thank you

Link to comment
  • 7 months later...
  • 2 weeks later...

Hi again,

so after a lot of testing I see that this pipe method using named pipe (as I did post above) dosent work good and  seems to be a bad idea using it with video streams (lags / hangs / jumps etc).Now I switched back using anonymous pipe method which works a lot better.

But now I have a other little problem with that and wanna find a solution.So before I used NamePipe and started VLC player (see above) and if I did press the stop button in VLC player then it also did close the player.So this was the advantage of Name pipe method.Now if I use anonymous pipe method it keeps connected if I press stop button in VLC player and I need to exit the player manually.My question is whether there is also a way to check if the pipe is still active in VLC etc?

greetz

EDIT: So the problem is also if I press stop in VLC or exit VLC that I will not come  back from write API.Its hangs inside.So how can I check this pipe before writing bytes to prevent a no return from write API?

Edited by LCF-AT
Just edit...
Link to comment

Hello

 

I´m not experience about Name pipe but if i use google tell me you can check it with ReadFile.

 

while True:
      ret_code = ReadFile()
      if ret_code == 0 and GetLastError() == ERROR_BROKEN_PIPE:
         # client disconnected

 

Check it out and post a solution.

But i think you ask on a wrong Board on a programming Board (Cpp/Masm32) have you faster a solution. B)

Regards,

Edited by ragdog
Link to comment

Hi raggy,

so the named  pipe does work without to check the read pipe handle but disadvantage is that I get this playing lag / fame dropping issues = sucks.If I use anonymous pipe then I dont get any lag playing issues anymore = good but I cant check whether the pipe is still active in  the player anyhow.Only thing what I can do is to close the read pipe handle after creating the pipe and if I exit VLC manually then it will also come  back from write API where I then can  clean  the rest etc.

So the problem is to find out whats the right and best method.

NamedPipe: +Dosent hang in write API (Has overlapped feature) // - Playing lags

AnonymousPipe: -Does hang in write API till I exit VLC player (need to close read pipe handle before) // + Playing fine // - Cant read the readpipe handle

Normaly I would still NamedPipe if it would not lag.The question is why it does lag.Maybe it has something to do that I use for NamedPipe ShellExecuteEx and or AnonPipe CreateProcess API.Also found any info on internet not to use NamedPipe for Client and  should use CreateFile / read / write API.

AnonymousPipe
------------------------
invoke CreatePipe,addr HREAD,addr HWRITE,addr SECURITY,0
invoke SetHandleInformation,HWRITE,HANDLE_FLAG_INHERIT,0

mov eax, HREAD
mov startupinfo1.hStdInput,eax
mov eax,HWRITE
mov startupinfo1.hStdOutput,eax
invoke CreateProcess,NULL,addr VLC_PLAYPATHBUFFER ,NULL,NULL,TRUE,NULL,NULL,NULL,addr startupinfo1,addr pinfo

invoke CloseHandle,HREAD

Here I read bytes from internet constantly = InternetBytes / InternetSize


The bytes I do send to WriteFile API into HWRITE handle

invoke WriteFile,HWRITE,InternetBytes,InternetSize,addr numberBytesWrittennew,offset overlapped
---------------------------------------------------------------
Now if I press Stop button in VLC then it does hang in WriteFile API 
so long till I close VLC player and then it comes back.Thats the problem here.


NAMEDPIPE
-------------------------
invoke CreateNamedPipe,offset PNAME,PIPE_ACCESS_DUPLEX,PIPE_TYPE_BYTE or PIPE_READMODE_BYTE or PIPE_WAIT,1,1024*64,1024*64,NMPWAIT_USE_DEFAULT_WAIT,0 
mov	esi, eax
invoke ShellExecuteEx,addr SHELL // VLC
invoke ConnectNamedPipe,esi,0

Here I read bytes from internet constantly = InternetBytes / InternetSize

invoke WriteFile,esi, InternetBytes,InternetSize,addr numberBytesWrittennew,offset overlapped
-----------------------------------------------------------------
Here its working and it does not hang in WriteFile API if I press Stop button in VLC 
and it comes back with eax 0 and  I can terminate VLC and cleanup the rest.Only problem 
for this method is the lag / frame dropping issues.

Maybe you or anyone else has some another ideas.

greetz

Link to comment

Hello

I think it works a named pipe is similar to get the pipe from console output from created process.

 

	mov	SA.nLength, sizeof SECURITY_ATTRIBUTES
	mov 	SA.lpSecurityDescriptor, NULL
	mov 	SA.bInheritHandle, TRUE
	invoke  CreatePipe, addr hRead, addr hWrite, addr SA, NULL
	invoke  RtlZeroMemory, addr StIn, sizeof STARTUPINFO
	mov 	StIn.cb, sizeof STARTUPINFO
	invoke  GetStartupInfo, addr StIn
	mov 	eax, hWrite
	mov 	StIn.hStdOutput, eax
	mov 	StIn.hStdError, eax
	mov 	StIn.dwFlags, STARTF_USESHOWWINDOW or STARTF_USESTDHANDLES
	mov 	StIn.wShowWindow, SW_HIDE
	invoke  RtlZeroMemory, addr PI, sizeof PROCESS_INFORMATION
	
	invoke CreateProcess, NULL, addr Buffer, NULL, NULL, TRUE, NULL, NULL, NULL, addr StIn, addr PI
	.if (eax)
		invoke CloseHandle, hWrite
		.while TRUE
			invoke RtlZeroMemory, addr Buffer, sizeof Buffer
			invoke ReadFile, hRead, addr Buffer,sizeof Buffer, addr nOfBytes, NULL
			.if (eax)
		            .if nOfBytes != 0;Error = bytes read.

It read from Created pipe from hRead.

You can correct me if i wrong but i think is similar.

Cherrs,

Edited by ragdog
  • Like 1
Link to comment

Hi raggy,

no it dosent work.VLC player send error messages if it starts.Also I need to use SetHandleInformation too without it dosent work.Anyway if I keep read & pipe handles then it will also hang inside and dosent come back in readfile API for read pipe handle from the beginning.Just if I close the read pipe hanlde then writefile API will come  back but just if I exit VLC player.

So I only have the write pipe handle where I can  send my bytes into but I need to find any check method before writefile API but how. :( I just can exit VLC manually but this I dont prefer and want it auto closed if the video stream isnt active anymore.As I said,with NamedPipe method it does work as I want but this has the stupid lag problem.

Here I found some new infos....

http://stackoverflow.com/questions/60645/overlapped-i-o-on-anonymous-pipe

....not sure whether this could work or not.

greetz

Link to comment

Hi again,

so I still try to find a way how to catch the info if when I do press STOP button in VLC player (if I use anonymous pipe).So as I told above if I press stop then it hangs in writefile API till I exit VLC and then it comes back.

My question now: Is there maybe any other way to find out if the user did press stop in VLC player?So for example,if I play something in VLC on Win7 and go with the mouse on the VLC player icon in the bottom taskbar then it pop ups a small window what does show me also the VLC player (you know what I mean) and inside this little window it does also show a play / pause / stop etc buttons I can use.So how does Windows that and find this functions + hooking them etc?

So maybe anyone of you have any another ideas how to find out if the stop button was pressed in VLC player.

greetz

Link to comment

Hi raggy,

just use a older PM topic from us and earlier so there you can PM me.Or does it now work for you to PM me there?

greetz

Link to comment

Hi again,

got another problem with the pipes.Problem is that the bytes I do read from internet (video) are fast finished and then I do close the pipe also if the video what is shown in VLC is not finished yet.Lets say the video has a lenght of 10 seconds and after 2 seconds the bytes reading is finished and then the pipe gets closed etc.So how can I set a paramter to wait into pipe (keep running)?Anyway whether I use Named or Anonymous pipes.

.repeat
invoke recv, s, buffer, len, 0
mov BYTES, eax
..............
invoke WriteFile, PIPEHANDLE_WRITE, buffer, BYTES, offset numberBytesWritten ,offset overlapped
..............
.until  BYTES == 0

Close / Cleanup code

So after all bytes was written into the pipe I need to do anything like any wait operation etc so that the video keeps playing in VLC player so long till all bytes was played.You know what I mean right?I also tried to set a sleep API after until command with some seconds just to see whether its playing longer etc but also in this case isnt working.Also tried other wait APIs as WaitForSingleObject or WaitNamedPipe but dosent work.So has anyone of you any idea how to handle that problem?

Thank you

Link to comment

Hi again,

thanks for your answer but I tried this already without success.The WaitNamedPipe function dosent return anymore if I use flag NMPWAIT_WAIT_FOREVER also if the playing bytes are finished or if I close the player.If I use default timeout flag then it comes back right after video did start.Also the video does only start if I disconnect the pipe after all bytes was received from recv API and written into pipe.If I use DisconnectNamedPipe (Entire video gets played till end) and I use right after that function the PeekNamedPipe API to get infos about this pipe then I get the error ERROR_BAD_PIPE also if I close the player so the error keeps same and dosent change.If I close the handle to pipe = video runs complete but after this I cant check anymore anything whether the pipe is still playing or not to let terminate the player prrocess. you know what I mean?

.repeat
invoke recv, s, buffer, len, 0
mov BYTES, eax
..............
invoke WriteFile, PIPEHANDLE_WRITE, buffer, BYTES, offset numberBytesWritten ,offset overlapped
..............
.until  BYTES == 0


invoke CloseHandle,PIPEHANDLE_WRITE

// Now Here I need any checks / waits before calling terminate
// A check whether video still runs or not or if finished
// Wait so long here and then go on to terminate / cleanup

invoke TerminateProcess, pinfo.hProcess, NULL // Terminate player

Close / Cleanup code

greetz

Link to comment

Hi again,

ok I have testet go on and did created now a another thread to check the player window titel and if this does match then I do terminate the player.So its working so far on first tests but again there is a little problem with the FindWindow / Ex APIs.So the API only does work for top-level windows (only if player is on top / selected).Now I tried to find another method and wrote this new thread code...

VLC_RUNCHECK proc A:DWORD,B:DWORD,BB:DWORD,CC:DWORD

local PID:DWORD    
local ExitCode:DWORD
local class [512]:BYTE
    
    mov edi,CC
    ASSUME edi:PTR VLC_EXIT

    A1:
    invoke Sleep,1000
    invoke GetExitCodeProcess,[edi].hProcess,addr ExitCode
    .if ExitCode == STILL_ACTIVE
    .else
    invoke CloseHandle,[edi].hThread
    invoke TerminateProcess,[edi].hProcess,NULL
    invoke VirtualFree,[edi].section,0,MEM_RELEASE
    ret
    .endif
    
    
    invoke GetTopWindow,NULL
    .while eax != 0h
       mov esi,eax
       invoke GetWindowThreadProcessId,esi,addr PID
       mov eax, PID
       .if eax == [edi].dwProcessId
           invoke GetWindowText,esi,Addr class,sizeof class
           .if eax != 0h
               invoke lstrcmpi,addr class,chr$("VLC media player")
               .if eax == 0h
                   nop
                   invoke CloseHandle,[edi].hThread
                   invoke TerminateProcess,[edi].hProcess,NULL
                   invoke VirtualFree,[edi].section,0,MEM_RELEASE
                   ret
               .endif
          .endif
       .endif
       invoke GetWindow,esi,GW_HWNDNEXT
    .endw
    jmp A1

VLC_RUNCHECK endp

...seems to work so far. :) Should be ok or what do you think?Now the player does close if video is finished or if I press stop button in VLC.

greetz

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