• entries
455
639
• views
424152

# A Mildly Productive Phantom : Video Enc Part 3

70 views

Now, you may or may not remember but back in June of this year I was firstly swearing about the GPL and XVid and then muttering about using Theora to encode video with some shiny SSE goodness etc etc

Months passed, my computer exploded and it looked like everything was dead... until the other night I decided it was time to do something and this got my attention once again.

Now, when my computer died due to a few mistakes I lost all the conversion code I wrote; this is a good thing.
As good as my SSE was it was being spanked by a lookup table version, heh.. although that was lost as well [sad]

So, I started from the top tuesday night and spec'd out some ideas about how I wanted it to work and wrote a basic interface;

A library to allow drop in encoding of RGB data (framebuffer) to acompressed ogg stream via TheoraUseage process:- Initalise with a filename/stream to save to-- version 1.0 just has a filename for nowEncoding:- start encoder-- encoder pre-allocates a series of buffers-- spawns a worker thread to do the encoding workper frame:- request a buffer from encoder lib-- this can block if the encoder is too far behind- use supplied buffer to pass RGB/RGBA data to encoderEncoder:- Performs colour space conversion from RGB=>YUV via lookup table-- this frees RGB buffer to be reused as it's copied into an internal buffer-- UV data needs to be 1/4 that of Y data; need to resample--- ? simple drop or do a proper filter on the image ?- YUV is passed to lib Theora for encoding- when completed write frame data outEnd :- system must request end of encoding-- lib writes special frame data out and shuts down as requiredNotes: * no sound support as yet...* might want to cue a frame in advance before we being encoding, last frameis flushed on shutdown requestbasic API ideas;void initialiseEncoder(std::string &filename);	// setup stream + internalsvoid beginEncoding(int width, int height);		// preallocate bufferschar * requestRGBBuffer();						// pass a pointer to a RGB buffer out (handle type maybe?)void processRGBBuffer(char * buffer);			// process the buffer back againvoid endEncodering();							// flush all buffers and close streamvoid shutdownEncoder();							// or maybe this name?class maybe?Initialise becomes the constructor, the rest member functions...

That was where I started tuesday night... I then distracted myself for 24h to give my brain a chance to process the ideas.

Tonight, about 2:30am I picked it up again, the net result is the following interface (and code behind it, you'll have to trust me on that, heh)
namespace FrameEncoder{	class TheoraEncoder	{	public:		TheoraEncoder(std::string const& filename, int width, int height);		~TheoraEncoder();		void beginEncoding();		unsigned char * requestBuffer();		void processBuffer(unsigned char * buffer);		void endEncoding();		void Process();	// TEMP!!!! this will be a threaded section!	protected:	private:		void Process(bool lastframe);		void WriteData();		std::queue<unsigned char *> rgbfreebuffers;		std::queue<unsigned char *> rgbusedbuffers;		unsigned char * ybuffer;		unsigned char * vbuffer;		unsigned char * ubuffer;		int height, width, video_height, video_width, frame_x_offset, frame_y_offset;		ogg_page videopage;				ogg_stream_state to; /* take physical pages, weld into a logical							 stream of packets */		ogg_page         og; /* one Ogg bitstream page.  Vorbis packets are inside */		ogg_packet       op; /* one raw packet of data for decode */		theora_state     td;		theora_info      ti;		theora_comment   tc;		FILE * outfile;	};}

Not overly comment and no support for encoding in a second thread yet (thus teh big 'TEMP!' comment [grin]

The code might need some refining, however the process is pretty simple;

• Construct a TheoraEncoder object, giving it the filename and sizes

This will do all the Theora/Ogg setup and open the output file.

• Request a start to encoding

Memory is reserved for a number of buffers (right now 2xRGB and 1xYUV, the RGB might be made variable)

• Per-frame you want to encode;

• Request a pointer to a buffer (in MT mode this will block until a buffer is free)

• Fill the buffer with RGB data

• Send it back for processing

• when you are done, tell it to enencoding and the final frames are flushed and memory buffers released

• On destruction the file is closed

The file stuff and maybe some of the init and final frame flushing might require some more thought (mostly todo with when these things should happen), however the basic theory is sound.

I'd be testing it about now, indeed it's mostly intergrated into an FBO example I've got which uses GLUT, however due to a mild library incompatiblity I can't be bothered to solve right now it's not linking [sad]

I'm a bit tired now so I plan on fixing it tomorrow... of course I also plan to go down the pub, so I'll have to do it before I pickle my brain, heh

There are no comments to display.

## Create an account

Register a new account

×

## Important Information

Participate in the game development conversation and more when you create an account on GameDev.net!

Sign me up!