If you are using the main C++ distribution of wxWidgets, Feel free to ask any question related to wxWidgets development here. This means questions regarding to C++ and wxWidgets, not compile problems.
We're trying to display a real-time network video stream in a wxFrame window on MSW. Video frames are decoded, loaded into a wxImage object, and then displayed in the frame. This requires converting the wxImage to a wxBitmap for display. But, the wxBitmap constructor is extraodinarily slow on Win32.
I profiled the app and discovered that the wxBitmap constructor calls the Window's GDI function CreateDIBitmap(). This function is responsible for up to 50% of the runtime of the entire application. Ouch.
Is there a way to display wxImage objects in a wxFrame without creating a new wxBitmap every single time OnPaint() is called?
Here's the OnPaint(), it's pretty basic. The wxBitmap constructor can take up to a couple seconds to complete.
I coded a video processor using DirectShow a while back. To display each frame I sent the image to the DC through the SetDIBitsToDevice function. This was also not very efficient, but it was fast enough for 24fps video.
I suspect the problem could be solved, for the most part, by implementing the GDI function SetBitmapBits in the wxBitmap class for MSW. This way, the wxBitmap could be stored as a private global in a class, allocated once, and reused. As opposed to creating a new wxBitmap for every frame.
Well, I've worked on the problem for about a week now with no luck. I've tried just about everything I can think of, and about all I can figure out is that there is something in the conversion from the DIB to the Window's DDB that is just plain slow. I've tried building compatible DC's, reusing bitmap's, calling BitBlt directly, drawing directly to the DC, but there's still something going on inside GDI that I just can't grasp.
So, I'm giving up. I'm going to code a DirectShow source filter to do this job, and that'll be the end of it. But, if someone has a solution that they can share, I'm still interested. I sincerely appreciate your help.
Direwolf wrote:
So, I'm giving up. I'm going to code a DirectShow source filter to do this job, and that'll be the end of it. But, if someone has a solution that they can share, I'm still interested. I sincerely appreciate your help.
You might give a try at SDL, IIRC the Windows version interfaces directly to DirectDraw and should be fast (and you don't need to write non-portable unreadable windows-api code).
quote: "wxWidgets is not a good game programming library, but it is an excellent cross-platform widget toolkit. SDL is an excellent cross-platform game programming library." Game programming library means real-time graphics, and that's what you want.
ssigala wrote:You might give a try at SDL, IIRC the Windows version interfaces directly to DirectDraw and should be fast (and you don't need to write non-portable unreadable windows-api code).
This is fantastic! I'll definitely give this a try and let you know how it turns out.
After more testing, it turns out that my profiler was lying to me. The display system wasn't slow... it is the HTTP stream that is slow. We're streaming an MJPG stream from an IP camera. The only way to capture each frame is to read the stream character by character, locate the packet boundary, strip the headers, and send the rest of the stream to the JPEG decoder. We were reading one character at a time from the stream via calls to wxInputStream::Read(). Why the profiler didn't pick this up, I don't know, but this is clearly where our speed problem lies.
I modified the program to read in chunks of bytes from the stream, and then write back the unused portion after the header has been stripped. This increased the speed of the video stream by about a factor of 5. There is still much room for improvment. But, at least, I've finally gotten to the root of the problem.
Thanks for the help guys. The tip to use SDL was extreamly helpful, and I've already put it to use in my app.