Wednesday, August 6, 2008

Saya-VE without SDL, experiment 1

Finally, my efforts are beginning to show results. I realized that I had committed several mistakes (read-as: bugs) while implementing wxVideoPanel. While fixing them, I also improved the code a little.

Additional bitmap
The most important bug was trying to save time by not creating another buffer. This caused a crash when resizing the panel under certain conditions. By using another buffer for wxVideoPanel, and updating it from wxVideoOutputDevice::Renderdata(), I could finally be sure that the wxVideoOutputDevice's bitmap was not accessed at the wrong time. As a bonus, this meant that while the video is paused, I still keep a copy of the buffer (oops... now that I think of it, when resizing, the bitmap info is actually lost. I'll fix that soon).

I finished implementing the syBitmapCopier class. Most functions are inline, so no stack space will be used when invoking them (well, some variables were required, but those are unavoidable).

I also did some clean up. I moved all the thread functions to syBitmap. I replaced the VideoOutputDevice* pointer from syVODBitmap and replaced it with an syAborter* pointer. syAborter is an abstract class that has only one method: bool MustAbort(), which indicates if an expensive operation must be aborted immediately. Then, I made VideoOutputDevice and AudioOutputDevice subclasses of syAborter.

What this means: syBitmap has all the required functions to be thread safe, and integration with ANY VideoOutputDevice class will be a piece of cake.

Classes cleanup
Now that all the syVODBitmap functions were moved to syBitmap, syVODBitmap was no longer necessary, so I deleted it.

And now, ladies and gentlemen... the demo!

The last bug I had made was calling an expensive wxWidgets function inside a for(x)... for(y) loop. No wonder the display was so slow. But now the wxVideoPanel demo is fully functional. And here it is!

The Demo() function (actually, method) of wxVideoPanel, regularly creates a nice colored image or arbitrary dimensions (the ripples change every 5ms approximately) which is later scaled to fit in the panel's dimensions. This way, no matter if your video is 4:3 or 16:9, it won't be distorted.

After being created, the image is sent to wxVideoOutputDevice via the LoadVideoData() method. This method copies the data to its own bitmap, and then, in its RenderData() method, it calls wxVideoPanel::LoadData().

wxVideoPanel::LoadData() locks its own bitmap and pastes the data. wxVideoPanel's bitmap is locked because there are two other functions that access it (each one locks the bitmap as well) : OnResize, and OnPaint.

wxVideoPanel::OnIdle() checks if new data has been loaded, and calls OnPaint() if necessary. OnPaint() uses a wxBufferedDC to repaint the screen.

This way, we have our nicely colored image which changes in realtime without flickering at all. Ta-da!

No comments: