Movie Control Alternatives

Blitz3D Forums/Blitz3D Programming/Movie Control Alternatives

jfk EO-11110(Posted 2005) [#1]
I am still searching for a method to control Movies. The Solutions offered by several people here (like BlitzMovie) didn't satisfy my needs so far. Blitz's built in Movie capabilities also don't offer the functions I need. Currently I am using a Userlib for MCISendString.

My project needs the following functions: Seek Frame and UpdateFrame, as well as a funtion that returns the length of the movie in frames. I still can combine it with Blitz's Movie Commands, eg. to read the movie width and height using the Blitz Commands.

As I said, currently I use MCSendString. In theory it supports SeekFame and UpdateFrame. The problem is, using the commands works sometimes and sometimes not. I think everyody can imagine that I better don't release a tool that uses a function that works "sometimes".

The tool makes great progress and I really have big plans for it since I got ideas for a market niche that is still not saturated. It's only this MCI SendString Problem that stops me.

Now I need to know - are there any Alternatives? How reliable are the Seek and Update Fame Commands in DirectShow's Movie Functions. Do they exist at all? And would it be possible to use them trough Userlibs?

Are there any other sources that allow to utilize windows installed Video Codecs?


jfk EO-11110(Posted 2005) [#2]
Uh, maybe somebody has an idea on how to use AVISYNTH as a frameserver for Blitz? ( http://www.avisynth.org/ )

EDIT
It seems it's possible to use the TCP server option to send frames to blitz in an easy way, tho I still don't understand how to order a certain frame - so I became member of the doom9.org forum, that is the default forum for avisynth. A lot of knowhow there, but this was extremly annoying:


vBulletin Message
You are not allowed to post or reply until you have been registered for at least 5 days.



so after Downloading Avisynth, I first have to wait 5 days until I can ask a question... è_é


John Blackledge(Posted 2005) [#3]
Jfk, just a quick thought:
Are you using the 'wait' string in your MCIsendstring calls?
I remember that many of mine appeared to malfunction until I added ' wait' at the end of every string sent.
Basically you are telling MCI not to execute any other MCI calls until this one is finished (with no noticeable loss).
Yes, it really was that simple and effective.


jfk EO-11110(Posted 2005) [#4]
Thanks - I already tried that, although I am not sure if I did this right. I think you are referring to this:
lpszFlags



wsprintf(
lpszCommand,
"seek %s %s %s",
lpszDeviceID,
lpszSeekFlags,
lpszFlags
);

...

lpszFlags:
Can be "wait", "notify", or both. For digital-video and VCR devices, "test" can also be specified. For more information about these flags, see The Wait, Notify, and Test Flags.




I still don't know what the bit values of these constants should be:
MCI_WAIT
MCI_NOTIFY
MCI_TEST

If it's 1 for wait, then I think I already tried it without success. But I'll surely doublecheck this.

EDIT:
Ah, good old pascal programmers:
const MCI_WAIT = 2
const MCI_NOTIFY = 1
...testing...

Ah, i've just realized that I am doing something completely wrong. I've tried to use the last parameter of mciSendString for this flag, but the parameter should be used for a callbackHWND!
But how should I add the flag to the command string? Should I simply Space-delimit-append it at the end of the string? Or comma delimited? And what do I have to use, it's value, "2" or "wait"? I have no idea.

EDIT2:
uh, infact you already said it, it should be " wait", so i take it it's comma delimited. ...
It seems it still don't works. I tried various combinations, like seek with wait, update with wait and both, but it's still some kind of random game.

I think I really got to try Avisynth since it's a highly advanced Frameserver, especially compared to MCISendstring.


John Blackledge(Posted 2005) [#5]
No, you were nearly there.

It's actually 'wait' (no quotes) with one space in front, and no delimiting commas.

Which is shown by your line: "seek %s %s %s"
-where the separater space is correctly placed just before the last %s.

Nothing else is needed.
The word 'wait' is substituted for the last %s.
Certainly no numerical value is needed.

That was, and still is, the beauty of the MCIsendstring calls, you can think in English!
And as I said, adding ' wait' to the end of all my calls made the difference.
My conclusion was that the MCI subsystem really is multitasking, but the ' wait' parameter forces it to do the given tasks one at a time.

For example, when you say 'stop', you mean 'stop'.

You don't mean 'send a stop command to the MCI queue, but run anything else that may need processing while the media stop command is waiting to be executed'

But MCI is quite capable that sort of logic!
(Don't you just love Microsoft.)


John Blackledge(Posted 2005) [#6]
So, other than all that.... how's it coming jfk?
Are you getting any closer to using MCIsendstring to draw a movie to the Blitz window?

With the 'seek' and other fine tuning controls it really was a useful library. I'm still running a 'Media Player' I coded in GFA Basic about 10 years ago, and it still works like a dream.

Err, just in case you don't know, the MCI system could also 'crop' the source (magnify an area) and all sorts of useful things in realtime.


jfk EO-11110(Posted 2005) [#7]
Thanks. Well it seems this doesn't work for me for some reason. I used 'wait' at the end of the command string, and it clearly had an impact on the behaviour, so I guess after all I did it right, but it still didn't function correctly.
I have a timeline that can be clicked by the mouse. MCI should then "jump" to that frame. This works sometimes, and sometimes not. So I had to add a "manual Update" button that would repeat the seek command. Now the user sometimes has to click this 5 or so times until it finally works. Using "wait" produced some stuttering program flow, so it looked like MC gained a higher priority in the background, but it still didn't work for some reason.

I have tried to capture frames in windowed mode in blitz without success, I have really tried for a long time with all kinds of tricks. In the end I was only capable of grabing frames in blitz' fullscreen mode, from the frontbuffer. Unfortunately the BlitzAvi.dll that saves me the result, required windowed mode at least for a second to start some processes. So I had to minimize and then re-maximize the Blitz fullscreen window, using some horrible tricks, to make them work together. So, yes, I really NEED something that can grab frames in windowed mode.

I know, MCI is cool, it has a lot of nice features. Only the seek problem and the non-windowed Mode in Blitz problem makes it very, very hard to use for me.

I am really thinking about to use Avisynth since it's a real Frameserver, as in "Frameserver", and it's developed by a wide open source community, already offers a zillion of up to date filters and scripts. Now I only got to make it work in blitz.

It's really good that I have organised DrGreen, my video compositing app in a way that allows me to replace the whole MCI Code by something else cause everything goes trough a function named "GrabFrame(n)".

Thank you for your help nevertheless. If I can make use of avisynth in blitz, I'll let you know.


jfk EO-11110(Posted 2005) [#8]
Ok, I made some tests with Avisynth 2.55. I create a .AVS scriptfile using Blitz on the fly, containing the following lines:

DirectShowSource("avifilename.avi")
Trim(seekframe,seekframe)

where seekframe is the frame I want to be displayed (Trim is usually used with startfame and endframe). I then can use Blitz's Openmovie command with the .AVS file. Avisynth now delivers an Avi Clip containig a trimed version of the source Avi, in this case only one Frame long. In Blitz I have to DrawMovie it once then I can close the handle.

The entire Framegrabbing process consistently takes about 2 seconds, no matter if I seek for a frame at the end or the beginning of the clip.

It sounds like a long time, but maybe it's better than what MCI does, sometimes 100 Milliscs, sometimes never. I still try to find a faster way. Probably it's Blitz that loses significant time in Opening the movie. And, of course, there is the video memory problem you described in the bug reports that may make troubles when used this way.

There is still an option to use AviSynth as a TCP Server for frames, maybe that's better.

EDIT - uh, it seems TCPServer() is no option since it requires some App to open the .AVS scipt in the first place to start the TCP Server at all. And I also don't have an Idea how the protocol works. It is a very handy command when you want to send video over a LANs tcp. On the client side you'd use TCPClient() as an Avi-Source in a Script, so you can stream movies easily. But for Blitz it's no solution.

I have measured when I grab frames from 2 Movies simultanously, eg. from one indeo encoded 50 Megs and one uncompressed 800 Megs Avi, the frame-access time still remains the same, 2 seconds for each frame. 500 Millisecs are used by Blitz for each Openmovie command. Currently I have no idea how to make it faster. Unfortunately you cannot send commands to Avisynth like to MCI (AFAIK). You have to open an AVS Script and the opening app thinks it's an ordinary movie file.


John Blackledge(Posted 2005) [#9]
It's more likely that the load time of an AVI depends on DirectX rather than Blitz.
My impression is that Mark (or whoever) is merely wrapping the DirectX calls with his own 'OpenMovie' etc calls, which is fine. It's how I'd do it.

But the route you are taking seems to be a long way away from the type of control that you and I are really looking for - using a frame server...?

I feel that it's worth mentioning that the likely reason for the stutter is much more simple than you think; that what you should be doing to achieve a 'seek' is to a) stop the movie first, b) seek, then c)play again.
This is what I meant by MCI multitasking.... 'seek' will not cause the movie to stop playing, then seek. It _will_ seek, but also carry on with any other running tasks.
Do you see what I mean?

I just wish I had more time to actually bring my original MCI code into Blitz. (I am my own boss - dare I justify the time?)

Which brings me to the question: surely once you have the window handle (via BlitzSys?) then what more do you need?
It should not matter to MCI whether the Blitz window is windowed or full-screen... it just needs a window handle. Why do you feel you need to go windowed then back to full-screen to get it to react?

By the way how are you calling MCI? Are you using a decls lib?


jfk EO-11110(Posted 2005) [#10]
Well, the Avisynth frame server method was up and running in 2 minutes. Compared to the troubles I had and have with MCI that's a pleasure.

But with MCI I tried to solve all kinds of problems for several months now, all in all surely over 100 hours of MCI hacking and troubleshooting. Believe me, MCI is capable of playing its movie on the blitz window, but (and this is the point) you will not be able to grab the frame from front or backbuffer since MCI will use an Overlay when blitz runs in windowed mode. It will not use that overlay in fullscreen. Of course, you can try it too, but let me tell you that I have wasted 30 or so hours just with this very problem. I tried a lot of work-arounds, without success (bitblit etc.). I couldn't believe it too that MCI makes a big diffrence if it's windowed or fullscreen, unfortunately it's a fact, but feel free to try your luck as well.

Of course I know about the multitasking behaviour of MCI. The movie is not playing when I try to seek a frame. I wrote a movieplayer too, with fancy buttons. Play, Stop, ffwd, reverse, doubl speed, half speed, resize, whatever. But direct-accessing a single specific frame seems to be something that isn't so easy for the MCI system. It works most times when you seek frame by frame, from zero to the end, but when you jump to any frame, it oftenly fails.

BTW I don't FEEL like I need to go windowed and then back - I simply HAVE to do that, it's a hard fact as well. But it has nothing to do with MCI. I am using BlitzAvi.dll to save the result of the image-processing as an Avi, and this DLL requires to be in windowed mode right after codec selection, if it's not, it will freeze. You know, it's not the way that I tried something halfhearted for 10 Minutes and then gave up. I have worked out an insane workaround for this problem (especially since MCI needs to be in fullscreen in the same time) and it took me many many hours.

Of course I use MCIs window command to make Blitz the parent of the canvas, and it also works in fullscreen mode. There is no need for BlitzSys, if you want to know blitz' HWND, simply use SystemProperty$("AppHWND"), so you even don't need to know the App Class Name.

Yes, I use a Decls lib for MciSendstring, the one in the code archives.

After a long time with MCISendString, I probably have to drop it. Well maybe I'm gonna use it to read out a movies properties, but that's it.

I really need an alternative. Avisynth is such an alternative, but maybe there's more. Also, in a few days they let me ask questions in their forum (5 days delay after registration, as mentioned), and then maybe somebody can tell me if there's a faster way. It supports plugins, and maybe a plugin could process runtime parameters like "seek frame".


John Blackledge(Posted 2005) [#11]
Sorry jfk, I didn't mean to suggest that you'd done half a job.
I already know your reputation, and you leave me standing.

If it makes you feel any better I just purchased your CSP Interior Pack 1 while I was waitng for your reply.
Nice stuff!

As I last thought, would you say that it would be no use me following MCI through, since what I most need to do is to render each frame to a texture on a mesh, to get a TV/billboard effect?

By the way I get the impression that you guys are either Swiss or German. How come you speak and write such excellent English - better than we English!


jfk EO-11110(Posted 2005) [#12]
No problem. Thank you for purchasing the interior package.

And thanks for the comment about my english as well. I don't think it's very good. I can hardly express myself in english. Yes, I live in switzerland.

MCI may be ok when you grab frames one by one sequentially and when it's not that vital if you miss a frame sometimes.
But you could also use Blitzs' OpenMovie command, it's probably faster and it's realtime oriented. And it can be used in windowed mode too.


John Blackledge(Posted 2005) [#13]
If only I could use OpenMovie()!

Please see the Blitz3D bugs forum:
http://www.blitzbasic.co.nz/Community/posts.php?topic=46958

As much as I would like to have a 'seek' command, it far more important to me to have OpenMovie/CloseMovie working without a memory leak.


jfk EO-11110(Posted 2005) [#14]
Yes, I know that bug report, and it's probably gonna stop me from using it too, especially for continous single frame access as described.

But there is still a chance that blitz (or diretctX) will do a carbage collection only when it runs out of videoram. We should do some tests and see what happens when OpenMovie used to eat all memory and then the app tries to reserve VRam for a texture...


jfk EO-11110(Posted 2005) [#15]
I've just tested it, it's definitively some kind of bug. Although I can create 20 times a 1024*1024 Texture after I did continously open and close a movie, which used to lower my AvailVidMem to 1.2 Megs, the framerate drops to something like 1 fps when I put the 20 textures onto some spheres and turn them in fromt of a camera (as if the texture Vram was swapped from system ram or something). when I skip the Movie Commands and execute the 20-textures and spheres test only, it runs at max/normal speed.

well, this is good news since I see a small chance that mark will also add exact frame access and an option for not playing realtime oriented movies (well, play them frame by frame, no matter what), if he once has to revisit this chapter due to the fact that we have a real bug here.