views:

253

answers:

4

I'm developing a screencasting utility in C++.

It basically captures desktop frames and creates an AVI file. The algorithm is as follows:

  1. Create a thread: this->m_hThread=CreateThread(NULL,0,thScreenCapture,this,0,NULL);
  2. Capture desktop in thScreenCapture n times per second (like 5 fps).

    obj->Capture();

  3. In Capture(), append the bitmap data to the avi file.

    this->appendBitmapToAvi(this->avifile, bmp);

This utility also records sound. So, in method thScreenCapture, sound data is also being appended to the avi file.

The problem is that a lag occurs between frames and sound when more than 6 frames (this can change depending on hardware configuration) are captured per second.

I'm seeking for a solution to optimize the algorithm. A solution may be buffering frames in memory, not appending all of them to the avi file on-the-fly. But this makes the code more complex because I have to deal with the sound data that's being captured in a different thread.

What do you suggest to increase the fps value that this utility supports without losing synchronization?

+1  A: 

You could take a look at the source for other screencasting software, such as CamStudio, to see how they are doing it.

If your program is disk bound (and I suspect it is), then things might improve by using compression (this is how the big name programs, such as Camtasia Studio, operate)

Billy ONeal
Yes, it's disk bound that's why I compress frames with the excellent Xvid codec which I did not mentioned in my question.
Zafer
@Zafer: Then you're going to have to memory buffer things, or you're going to have to develop your own codec. That's what the Camtasia people did -- write their own codec, I mean. DivX and XviD are good for general movie video, but there are more optimizations that can be done for screencasts.
Billy ONeal
Do you know resources about codec development?
Zafer
@Zafer: No idea where to even begin :(
Billy ONeal
Check out http://www.theora.org/ -- It's open source, should get you going.
M. Tibbits
@M. Tibbits: Theora is not a codec optimized for screencasting; it will do little better (and in fact, will probably do worse) than DivX and XviD.
Billy ONeal
Check out how VNC compresses, might be useful.
Amigable Clark Kant
I'd rather check how FRAPS does. VNC is likely to use JPEG/PNG compression and only transfer updated regions (rects).
jweyrich
CamStudio uses VFW - the codebase is terribly outdated. I'm not saying don't learn from it, but be aware that VFW has been superseded by DirectShow, which is being replaced by Media Foundation. Note that Media Foundation is Vista and later only, so while majority market share use the XP OS, DirectShow is the API of choice for developing these apps on the Windows platform.
freefallr
A: 

What OS are you targeting? If tyou are working on Windows XP I would take a look at some of the DirectShow code at http://tmhare.mvps.org/downloads.htm, specifically Filter Graph Library.

Dolphin
@Dolphin: Thanks for the link. I'm targeting Win XP, Vista, and 7.
Zafer
+1  A: 

Use a circular double or triple buffer to store the bitmap and sound each frame and use a separate thread to add the bitmap and sound to the avi. So data-collection is in one thread, data is in a circular (thread-safe) buffer and the data-storage is in another thread.

Vite Falcon
A/V frames must be synch'd! Buffering won't solve this problem!
freefallr
That's right. I'm using seperate threads to collect video and audio data but add them to avi file in a synchronized fashion for interleaving.
Zafer
@freefallr So Zafer is doing it in an interleaved manner, which means having data collection in the main-thread and storage in another thread would make more sense. Correct me if I'm wrong.
Vite Falcon
The way I do streaming is to have two thread-safe queues (audio and video frame queues). A network thread retrieves frames and adds them to the appropriate queues. A source filter then consumes the queues. This is all standard theory. The problem the OP is querying - that is synch'ing the A/V in an AVI file won't be solved by circular or triple buffers.
freefallr
+1  A: 

Are you writing the AVI file yourself? A noble effort, but there are APIs to help with this task.

If you're working on the windows platform, I'd suggest considering using the DirectShow or Media Foundation APIs to mux the audio and video to disk. DirectShow is the API for A/V capture, streaming and muxing on the windows platform.

This article on CodeProject talks about audio & video sync issues and the mechanism that DirectShow uses to overcome this difficulty.

Essentially, a reference clock is employed and the frames are timestamped.

There's a very active DirectShow community that is an extremely useful resource for new folks. TMH's website is well worth checking out - he's an MS MVP and is an active member of the community.

I hope this helps!

freefallr
Thanks for the advise. I'm using an opensource avi library which works very well. I've solved so many problems like adding mp3 audio data (which needed extra header information and took days to find out). Now what I need is to accelerate the my capturing engine.
Zafer