Having made my first AMV (anime music video), I am now even more keen on this subject.
So, the project target is: from 1...25 videofiles fetch scenes, arrange them in a timetable, 1..6 minutes long, add a .wav as background music and compress to .avi . Effects (like fade-in) should be done in this software (and not via DirectShow filters).

So, I need direct access to the decoded video buffer.

First I looked at DX9's SDK samples, but I didn't find example of direct buffer access (maybe I didn't revise well enough).
Then, I dug up my oldest MSDN copy - examples for Win95 and 98 (when DirectShow was known as DirectAnimation), and got interested in the AVIxxx API. Though, they fail in opening half of the videofiles I have. So, I'm stuck with DShow, I guess.

Any pointers on how to fetch decoded videoframes at arbitrary position? Using DirectShow, preferably. Or rendering to a DirectDraw back-surface.

There are several free video-editing tools available, but I think their creators never really tried using their software. On my PC (AthlonXP 2000+, 512MB DDR@400), previewing movies cannot be called "realtime". So, for a 2 minutes' video I have to compile it to see what the result might be. Compilation of 22 minutes.

Since I want this software to be _fast_ to use, I've decided to make a cache-system, each useful frame gets decoded into a 160x120x2 malloced buffer. Taking 66MB RAM per minute at 30fps is perfect.

Managing media cache, sequencing, adding effects, saving to .avi - all are clear. Only fetching of the input video frames is problematic.

Ah, this project, if started, will be opensource in MASM, using my libraries/macros: Ilix (DirectDraw wrapper), ATC (C++ wrapper/ OOP for asm) .
Posted on 2005-06-12 15:54:50 by Ultrano
I dug deeper into the AVIFileXXX , and found a good enough solution :)
The only .avi files these API fail to render are .asf files, as Microsoft have decided. Supporting .wmv and .mpg files will be dropped.

I did some benchmarks to compare rendering the time of AVIFileXX with that of DirectShow. They're 100% equal :) . But for my purpose (getting the decoded data), AVIFile is maybe 10% to 50% faster .
I also decided to set the cache-buffer from 160x120x2 (565) to 160x120x3 (24-bit RGB), taking 99MB per minute.

A funny thing I found about the AVIFile functions - the samples are coded to be slow lol. On every frame decoding, they reallocate the output .dib several times, and get the "current frame to render" more than a dozen times :) .

Ah, a tricky part about the decoding is that in the BITMAPINFOHEADER you have to specify the same dimensions as specified in the AVIFileInfo. And .dibs are upside-down...
Posted on 2005-06-12 18:40:41 by Ultrano
You might want to test the AVIFileXXX performance on 9x as well - it sounds a bit like one of those pretty old APIs that could have crappy half-16bit implementation on 9x. One never knows :)

.wmv support isn't a big loss IMHO, but .mpg is a bit sad... I guess it might be possible to move to DShow later (if you figure out how to access the buffer) without too much pain, if your classes are abstract enough.

the samples are coded to be slow lol

Sounds typical of the old Microsoft samples... they vary extremely in quality, from pretty good code to the atrocities included in the MDAC SDK (ODBC samples are eeky).
Posted on 2005-06-12 18:49:45 by f0dder
From what I've been trying out so far, the AVIxxxxx VFW functions are slow (even with fast codecs, though I have not compared them with another set of functions as you have). They are limited in user interfacing, which I find is the biggest problem, but they work. That to say that I won't be using them for any real-time work. They're also very picky when it comes to order in function calls and from where they're called (I was unable to get AVIStreamWrite and AVIStreamRelease to not hang in a DLLEntryPoint function).

I found this tutorial on the AVIxxxxx implementation:
Maybe it would be of some help.

Posted on 2005-06-13 10:44:27 by Big Red
Is that on Win98 ? Or probably you have awful codecs. Or you have seen bad examples (it's full of them). On both PCs here they manage to render as fast as DirectShow. Accessing arbitrary-positioned frames from a movie with AVIFile is even faster than what I've seen with DShow - mostly because with AVIFile the programmer has full control of when and what to decode/show.
Losing .mpg support is not a big deal for AMV makers, I did a bit limited research on that :).

At first I thought DirectShow would be the way, but it turned out I have to write a lot of code, and achieve bad results and get no control of the video data. The DShow filters seemed nice, but in the end only "Fade" is useful. But the word "limitation" is what DShow shouts all the time, while AVIFile gives full control :) . Only managing DIBs is nasty there, but I'll handle it easily :) .
Posted on 2005-06-13 11:20:43 by Ultrano
I've been programming on WinME, but I've tried the code on WinXP HE as well. I've tried the Intel, Windows Media, DivX and XviD codecs so far.

I didn't mean that the AVIxxxx functions are bad at all; I will use them for my own project (in a separate module). But they're still too slow to use in real-time for something like game video capture (for example, simply dumping the single frames to an uncompressed DIB stream automatically shaves off 25+ fps, excluding the massive original blitting loss of 50+ fps; using any kind of compression bumps the final framerate to below 10 fps, all this in a level that originally ran at 100+ fps). I've also run into problems when trying to write multiple frames to compressed streams in a single call.

They may still be faster than other methods, though; as I said, I can't comment on that.

I'm also not taking into account my lack of experience in such programming here. If you can make them work well, and/or if encoding speed really doesn't matter, then by all means ignore this.
Posted on 2005-06-13 14:05:36 by Big Red
If you're looking for a good open source example, you should check out VirtualDub.  It's written in C with, what it soulds like, a lot of inline assembly.

Posted on 2005-06-13 14:50:02 by Sparafusile
I've seen VDub's code briefly - and none of it is useful to my project (codenamed VAMV).
VDub is specialized in editing/exporting a single videofile, while VAMV's purpose is to easily import many .avi-s, arrange fragments of them and apply effects+transitions.

So far, I have completed the OOP class for loading of arbitrary frames:

set avi1 as IVideo
mov avi1,new(IVideo)
pcall avi1.LoadFile,T("test.avi")
pcall avi1.RenderFrame,ptr1,160,120,2338 ; outBuffer,outWidth,outHeight,FrameNumber
delete avi1

Did many benchmarks on both PCs here (PC1: a high-end one, PC2: a low-end one).
It doesn't matter at all if I render frames sequentially or not - the time taken is the same +/- 3%.
PC1: 74fps => 13ms to render a frame
PC2: 17fps => 58ms
On PC2, films are awful to watch anyway - 17fps is a better result than I expected :D

I just wonder how to make the cache system. Right now I got the idea of doing it in a background thread.
Posted on 2005-06-13 19:41:53 by Ultrano