Game Development Community

T3D 1.1 Final - GuiTheoraCtrl causes access violations - RESOLVED (THREED-2594)

by Michael Reino · in Torque 3D Professional · 09/08/2011 (2:27 am) · 3 replies

Build: 1.1 Final
Platform: Windows XP 32
Target: Any use of GuiTheoraCtrl

Issue: The GuiTheoraCtrl has a bug that causes it to overwrite memory if the video resolution is larger than the texture mode allows.

Steps To Repeat: We discovered this bug by loading a 1280x720 ogv video with texture quality set to "Low". You should be able to duplicate the error by loading a video larger than 512x512 with texture quality set to "Lowest". The problem occurs in TheoraTexture::FrameReadItem::execute() because the dMemcpy() statements overwrite the texture buffer.
A simple work-around can be implemented to prevent the crash by changing the following lines in TheoraTexture::FrameReadItem::execute() from:

GFXLockedRect* rect = mFrame->mLockedRect;
   if( rect )
   {
      if( framePitch == rect->pitch )
         dMemcpy( rect->bits, frame->data, rect->pitch * height );
      else
      {
         // Scanline length does not match.  Copy line by line.
         
         U8* dst = rect->bits;
         U8* src = ( U8* ) frame->data;
         for( U32 i = 0; i < height; ++ i )
         {
            dMemcpy( dst, src, framePitch );
            dst += rect->pitch;
            src += framePitch;
         }
      }
   }

To:
GFXLockedRect* rect = mFrame->mLockedRect;
   if( rect )
   {
      const U32 usePitch = getMin(framePitch, mFrame->mTexture->getWidth() * 4);
      const U32 useHeight = getMin(height, mFrame->mTexture->getHeight());
      if( (framePitch == rect->pitch) && (height == useHeight) )
         dMemcpy( rect->bits, frame->data, rect->pitch * height );
      else
      {
         // Scanline length does not match.  Copy line by line.
         
         U8* dst = rect->bits;
         U8* src = ( U8* ) frame->data;
         // Center the ogv if it is too big for the texture mode
         if ( height > useHeight )
            src += framePitch * ((height - useHeight) / 2);
         if ( framePitch > usePitch )
            src += (framePitch - usePitch) / 2;
         for( U32 i = 0; i < useHeight; ++ i )
         {
            //dMemcpy( dst, src, framePitch );
            dMemcpy( dst, src, usePitch );
            dst += rect->pitch;
            src += framePitch;
         }
      }
   }

This work-around just copies as much data as will fit in the texture from the middle of the video frame. It would be nice (although probably impractical) to see a loading solution that scales down the video frame to fit the allotted texture space.

#1
09/08/2011 (9:32 am)
I've gone ahead and logged this bug under THREED-2594. Thanks Michael.
#2
09/23/2011 (1:15 pm)
Michael, is there any way you can e-mail me the video that you were trying to use? I'm attempting to replicate the issue, but having trouble. I'm using a video that's 960X544 with the Texture Quality set to "lowest", and while the video occasionally flickers and only shows the top left corner of the video, I cannot get the engine to crash. I can better debug and tend to the issue if you can send me the video that's causing you problems. Send it to the e-mail in my GarageGames profile and I'll get to it immediately!
#3
10/11/2011 (2:49 pm)
Fixed in 1.2.