help:BlitToMemory() cause an ACCESS VIOLATION error!

LuRenJia

13-03-2007 07:06:19

sorry for my bad English.

I try to capture screen contents and write data into an avi file.

the code:

byte[] bytes = new byte[512 * 512 * 4];
PixelBox pb = new PixelBox(512, 512, 1,
PixelFormat.PF_BYTE_RGBA,
Marshal.GetIUnknownForObject(bytes));

TexturePtr texturePtr = TextureManager.Singleton.CreateManual("record",
ResourceGroupManager.DEFAULT_RESOURCE_GROUP_NAME,
TextureType.TEX_TYPE_2D,
512, 512, 0, PixelFormat.PF_BYTE_RGBA,
(int)TextureUsage.TU_RENDERTARGET);
RenderTexture rtt = texturePtr.GetBuffer().GetRenderTarget();
Viewport v = rtt.AddViewport(c);
v.OverlaysEnabled = false;
root.RenderOneFrame();
HardwarePixelBuffer buffer = texturePtr.GetBuffer().Target;
buffer.BlitToMemory(pb); // cause an access violation error
MemoryStream ms = new MemoryStream();
ms.Write(bytes, 0, bytes.Length);
bmp = (Bitmap)Bitmap.FromStream(ms);

AviManager am = new AviManager("filename.avi", false);
VideoStream vs = am.AddVideoStream(false, 25, bmp);
bmp.Dispose();
ms.Close();
ms.Dispose();
am.Close();


what's wrong with me? :?:

LuRenJia

23-03-2007 10:30:44

some one can help me? :cry:

Bekas

23-03-2007 13:18:27

Marshal.GetIUnknownForObject is for COM objects. Change the code like this:
unsafe
{
byte[] bytes = new byte[512 * 512 * 4];
fixed (byte* ptr = &bytes[0])
{
PixelBox pb = new PixelBox(512, 512, 1,
PixelFormat.PF_BYTE_RGBA,
(IntPtr)ptr);

TexturePtr texturePtr = TextureManager.Singleton.CreateManual("record",
ResourceGroupManager.DEFAULT_RESOURCE_GROUP_NAME,
TextureType.TEX_TYPE_2D,
512, 512, 0, PixelFormat.PF_BYTE_RGBA,
(int)TextureUsage.TU_RENDERTARGET);
RenderTexture rtt = texturePtr.GetBuffer().GetRenderTarget();
Viewport v = rtt.AddViewport(c);
v.OverlaysEnabled = false;
root.RenderOneFrame();
// Prefer to use a SharedPtr object directly if possible, instead of its 'Target'
HardwarePixelBufferSharedPtr buffer = texturePtr.GetBuffer();
buffer.BlitToMemory(pb);
}
}


Let me know if it works or not.

LuRenJia

26-03-2007 08:55:58

yes, blitToMemory now works fine. thank you very much!

but I ran into a new problem "code to memory not implemented" when I using "Codec.code(Mogre.MemoryDataStreamPtr input, Mogre.Codec.CodecDataPtr pData)".

I searched and got an explaination:
Yes, encoding to memory was never implemented, only encoding to file. You are welcome to implement it although please note we've switched to FreeImage in Eihort.

LuRenJia

26-03-2007 14:06:04

I solved the problem, and post the code, maybe it's useful.
(download AviFile component from ]http://www.codeproject.com/cs/media/aviFileWrapper.asp)

public class RecordDesc
{
public int Rate;
public List<Vector3> PositionList;
public List<Quaternion> OrientationList;
public string AviFile;

public RecordDesc ()
{
PositionList = new List<Vector3> ();
OrientationList = new List<Quaternion> ();
}

public void Clear ()
{
PositionList.Clear ();
OrientationList.Clear ();
}
}

public void GenerateAVI (Size scrSize, RenderWindow window, SceneManager sceneMgr, RecordDesc recDesc)
{
Cursor = Cursors.WaitCursor;

Camera c = null;
TexturePtr texturePtr = null;
RenderTexture rtt;
AviManager am = null;
VideoStream vs;
Bitmap bmp = null;
Rectangle rect = new Rectangle ( 0, 0, scrSize.Width, scrSize.Height );
window.IsActive = false;

try
{
c = sceneMgr.CreateCamera ( "aviCam";
c.AspectRatio = (float)scrSize.Width / scrSize.Height;
c.Position = recDesc.PositionList[0];
c.Orientation = recDesc.OrientationList[0];
bmp = new Bitmap ( scrSize.Width, scrSize.Height, System.Drawing.Imaging.PixelFormat.Format32bppArgb );
unsafe
{
byte[] bytes = new byte[scrSize.Width * scrSize.Height * 4];
fixed ( byte* ptr = &bytes[0] )
{
PixelBox pb = new PixelBox ( (uint)scrSize.Width, (uint)scrSize.Height, 1,
PixelFormat.PF_A8R8G8B8,
(IntPtr)ptr );

texturePtr = TextureManager.Singleton.CreateManual ( "record",
ResourceGroupManager.DEFAULT_RESOURCE_GROUP_NAME,
TextureType.TEX_TYPE_2D,
(uint)scrSize.Width, (uint)scrSize.Height, 0, PixelFormat.PF_A8R8G8B8,
(int)TextureUsage.TU_RENDERTARGET );
rtt = texturePtr.GetBuffer ().GetRenderTarget ();
Viewport v = rtt.AddViewport ( c );
v.OverlaysEnabled = false;
core.root.RenderOneFrame ();
HardwarePixelBufferSharedPtr buffer = texturePtr.GetBuffer ();
buffer.BlitToMemory ( pb );
System.Drawing.Imaging.BitmapData bmpData
= bmp.LockBits ( rect, System.Drawing.Imaging.ImageLockMode.WriteOnly, bmp.PixelFormat );
Marshal.Copy ( bytes, 0, bmpData.Scan0, (int)buffer.SizeInBytes );
bmp.UnlockBits ( bmpData );
am = new AviManager ( recDesc.AviFile, false );
vs = am.AddVideoStream ( false, recDesc.Rate, bmp );
for ( int i = 1; i < recDesc.PositionList.Count; i++ )
{
c.Position = recDesc.PositionList[i];
c.Orientation = recDesc.OrientationList[i];
core.root.RenderOneFrame ();
texturePtr.GetBuffer ().BlitToMemory ( pb );
bmpData = bmp.LockBits ( rect, System.Drawing.Imaging.ImageLockMode.WriteOnly, bmp.PixelFormat );
Marshal.Copy ( bytes, 0, bmpData.Scan0, (int)buffer.SizeInBytes );
bmp.UnlockBits ( bmpData );
vs.AddFrame ( bmp );
//progbar.Value = (int)Math.Round ( (float)i / recDesc.PositionList.Count * 100 );
//Application.DoEvents ();
}
}
}
}
catch ( Exception ex )
{
MessageBox.Show ( ex.Message, "error" );
}
finally
{
if ( texturePtr != null )
TextureManager.Singleton.Remove ( texturePtr.Name );
if ( c != null )
core.SceneMgr.DestroyCamera ( c );
if ( am != null )
am.Close ();
if ( bmp != null )
bmp.Dispose ();
}
window.IsActive = true;
}

Bekas

26-03-2007 23:21:42

Thanks for the code.

but I ran into a new problem "code to memory not implemented" when I using "Codec.code(Mogre.MemoryDataStreamPtr input, Mogre.Codec.CodecDataPtr pData)".

I searched and got an explaination:
Yes, encoding to memory was never implemented, only encoding to file. You are welcome to implement it although please note we've switched to FreeImage in Eihort.

I think Eihort implements it now.