Integrating Theora support in TSE
by Jon Wilsdon · in Torque Game Engine Advanced · 10/24/2005 (12:28 pm) · 5 replies
I have ported over the Theora support from TGE 1.4 to the latest cvs version of TSE, but am having one small problem that I can't seem to figure out. I can get video to play, and the sound to synch up, but the video ends up getting cyanish bands that take over part of a lot of the frames (it might be every other one, but it is swapping frames fast enough that I can't tell, it is always present and really annoying) and all of some of the other ones. It happens on all of the videos I play, both the ones that come with 1.4 and ones that we have made that also work just fine in 1.4.
Here are two screenshots of the problem on the soundCheck.ogg file:


In porting the code over I obviously had to change up the dgl calls to use the new gfx ones, and it seems likely to me that the problem is somewhere in how I am using the texture.
The only real change was in that I changed the original createVideoBuffers in theoraPlayer.cc from:
to:
Any ideas?
Also, once I get this taken care of, if there is any interest I could write up a resource on how to get Theora support in TSE from 1.4 (I have written one about getting Theora support in 1.3), but I am not sure when TSE will be merged with 1.4 again or if anyone is interested in a resource like that.
Here are two screenshots of the problem on the soundCheck.ogg file:


In porting the code over I obviously had to change up the dgl calls to use the new gfx ones, and it seems likely to me that the problem is somewhere in how I am using the texture.
The only real change was in that I changed the original createVideoBuffers in theoraPlayer.cc from:
bool TheoraTexture::createVideoBuffers()
{
// Set up our texture.
const GBitmap *bmp = new GBitmap(
getMax(mTheoraInfo.frame_width, mTheoraInfo.width),
getMax(mTheoraInfo.frame_height, mTheoraInfo.height),
false, GBitmap::RGB);
mTextureHandle = new TextureHandle(NULL, bmp, true);
// generate yuv conversion lookup tables
generateLookupTables();
return true;
}to:
bool TheoraTexture::createVideoBuffers()
{
// Set up our texture.
GBitmap *bmp = new GBitmap(
getMax(mTheoraInfo.frame_width, mTheoraInfo.width),
getMax(mTheoraInfo.frame_height, mTheoraInfo.height),
false, GFXFormatR8G8B8 );
mTextureHandle = new GFXTexHandle(bmp, &GFXDefaultPersistentProfile, true);
// generate yuv conversion lookup tables
generateLookupTables();
return true;
}Any ideas?
Also, once I get this taken care of, if there is any interest I could write up a resource on how to get Theora support in TSE from 1.4 (I have written one about getting Theora support in 1.3), but I am not sure when TSE will be merged with 1.4 again or if anyone is interested in a resource like that.
#2
02/25/2006 (2:53 pm)
I'm no help, but I hope this gets working; I'd love to use Theora in TSE. :)
#3
Things we ended up doing:
Copy over the theora stuff from 1.4.
Create a GFXTheoraProfile that consists of GFXTextureProfile::KeepBitmap | GFXTextureProfile::Dynamic | GFXTextureProfile::NoMipmap (the NoMipmap probably isn't necessary, but we don't really want our videos mipmapped... if you were using it as a texture on an object in the world I guess you might though). Also, changing to a profile with Dynamic makes playing multiple videos smoother.
Change GFXD3DTextureManager::_refreshTexture() function to allow both KeepBitmap and Dynamic. An assert is stopping us there so we made an if statement specific for those times you want a Dynamic texture that you can call getBitmap() on.
We also had to change the definition of _loadTexture to take a boolean value as a third parameter (defaulting to true so we didn't have to change any of the calls to it, but our one in the aformentioned if statement). The if statement essentially tells _loadTexture whether or not to do the pDL->convertToBGRx() call or not. (This was the main cause of the banding).
Once we no longer have that call to convertToBGRx, then we really are writing the pixels in the wrong order since DirectX apparently stores the underlying textures in BGR, so we changed the TheoraTexture::drawFrame() to write directly to the texture as BGR instead of RGB.
And voila, theora videos in TSE. This post should help me to not forget anything major when I write the resource and if you can't wait that long you could probably get it working with what I've written above.
02/28/2006 (3:12 pm)
Ok. After spending about half a day today and enlisting the help of another programmer to bounce ideas off of (thanks Ben McMahan!) we finally managed to track down the problem and come up with a fix for it. I don't have time to write it up into a resource today, but I will later (hopefully before next week) once I am sure our solution is a decent enough one. Basically the main cause was _loadTexture converting to BGR an extra time in some cases and not in others which caused the weird banding.Things we ended up doing:
Copy over the theora stuff from 1.4.
Create a GFXTheoraProfile that consists of GFXTextureProfile::KeepBitmap | GFXTextureProfile::Dynamic | GFXTextureProfile::NoMipmap (the NoMipmap probably isn't necessary, but we don't really want our videos mipmapped... if you were using it as a texture on an object in the world I guess you might though). Also, changing to a profile with Dynamic makes playing multiple videos smoother.
Change GFXD3DTextureManager::_refreshTexture() function to allow both KeepBitmap and Dynamic. An assert is stopping us there so we made an if statement specific for those times you want a Dynamic texture that you can call getBitmap() on.
We also had to change the definition of _loadTexture to take a boolean value as a third parameter (defaulting to true so we didn't have to change any of the calls to it, but our one in the aformentioned if statement). The if statement essentially tells _loadTexture whether or not to do the pDL->convertToBGRx() call or not. (This was the main cause of the banding).
Once we no longer have that call to convertToBGRx, then we really are writing the pixels in the wrong order since DirectX apparently stores the underlying textures in BGR, so we changed the TheoraTexture::drawFrame() to write directly to the texture as BGR instead of RGB.
And voila, theora videos in TSE. This post should help me to not forget anything major when I write the resource and if you can't wait that long you could probably get it working with what I've written above.
#4
www.garagegames.com/index.php?sec=mg&mod=resource&page=view&qid=9958
Try it out, let me know if it works.
03/03/2006 (3:13 pm)
Ok. I just spent a decent amount of time (it just kept growing!) creating a resource to get Theora into TSE.www.garagegames.com/index.php?sec=mg&mod=resource&page=view&qid=9958
Try it out, let me know if it works.
#5
03/17/2009 (8:30 pm)
Trying just now to port it to TGEA 1.8.1. Will tell you as soon as it is working.
Jon Wilsdon
Default Studio Name
I have tried changing the texture profile to a custom one since I don't think the DefaultPersistentProfile is the correct one (the GFXTextureProfile::Static is supposed to mean that the texture will never be modified, at least according to the comment in gfxTextureProfile.h). So I started by creating a custom profile with just KeepBitmap (KeepBitmap has to be one of the flags so that I can call mTextureHandle->getBitmap() in drawFrame), and I still got the bands, and then I added NoPadding, NoMipMap and PreserveSize and they didn't affect it at all. I also tried adding SystemMemory (thinking that it could possibly be something to do with uploading the texture to the card) which just ended up giving me a bitmap of another texture that never changed.
Another thing I wanted to make sure was that I was linking against the proper theora libraries, so I copied over the ones from 1.4 that worked and that didn't change anything. I also built the libraries (from libtheora-1.0alpha5) and no difference.
I also thought that it might something to do with something set up incorrectly with the state of DirectX, so I tried adding GFX->setBaseRenderState() and (separately) also some calls like GFX->disableShaders but those just ended up in either asserts saying that DirectX didn't get returned to a good state or a crash.
I have probably tried a few other things that I can't remember at the moment. In addition to the code above, I also have the following in theoraPlayer.cc:
void TheoraTexture::drawFrame() { yuv_buffer yuv; // decode a frame! (into yuv) theora_decode_YUVout(&mTheoraState, &yuv); // get destination buffer (and 1 row offset) GBitmap *bmp = mTextureHandle->getBitmap(); U8* dst0 = bmp->getAddress(0, 0); U8 *dst1 = bmp->getAddress(0, 1); .... }And in guiTheoraCtrl.cc:
void GuiTheoraCtrl::onRender(Point2I offset, const RectI &updateRect) { const RectI rect(offset, mBounds.extent); if(mTheoraTexture.isReady() && mTheoraTexture.isPlaying()) { mTheoraTexture.refresh(); GFX->clearBitmapModulation(); GFX->drawBitmapStretch(mTheoraTexture, rect); } else { if(mTheoraTexture.isReady()) mDone = true; GFX->drawRectFill(rect, mBackgroundColor); // black rect } renderChildControls(offset, updateRect); }So if someone else wanted to test this out, that should be all of the changes you have to make.
Does anyone have any ideas on what to try, or what it might be? Anyone have a fix? ;)