changeset 4:a1202aac1124

Started implementing separate encoder class
author fraserofthenight
date Wed, 08 Jul 2009 19:16:39 -0700
parents e6cf9f26d0e7
children 59aa8015d539
files .settings/descent.core.prefs bin/frankenbuild.map ref/buffer.d src/build/frankenbuild.d src/impl/hoofbaby/codec/encoder.d src/impl/hoofbaby/codec/libav/avbuffer.d src/impl/hoofbaby/codec/libav/avutil.d src/impl/hoofbaby/codec/libav/swscale.d src/impl/hoofbaby/util/buffer.d
diffstat 9 files changed, 477 insertions(+), 298 deletions(-) [+]
line wrap: on
line diff
--- a/.settings/descent.core.prefs	Wed Jul 08 07:29:48 2009 -0700
+++ b/.settings/descent.core.prefs	Wed Jul 08 19:16:39 2009 -0700
@@ -1,4 +1,4 @@
-#Sun Jun 21 09:02:00 PDT 2009
+#Wed Jul 08 18:44:23 PDT 2009
 descent.core.compiler.allowDeprecated=enabled
 descent.core.compiler.debugIdentifiers=AVBuffer
 descent.core.compiler.debugLevel=1
@@ -6,8 +6,8 @@
 descent.core.compiler.enableWarnings=enabled
 descent.core.compiler.source=1
 descent.core.compiler.taskCaseSensitive=enabled
-descent.core.compiler.taskPriorities=NORMAL,LOW,HIGH,HIGH,LOW,HIGH,LOW,LOW,LOW,HIGH
-descent.core.compiler.taskTags=TODO,PERHAPS,BUG,WTF,NEXTVERSION,WORKAREA,OPTIMIZE,CBUG,PORT,IMPORTANT
+descent.core.compiler.taskPriorities=NORMAL,LOW,HIGH,HIGH,LOW,HIGH,LOW,LOW,LOW,HIGH,NORMAL
+descent.core.compiler.taskTags=TODO,PERHAPS,BUG,WTF,NEXTVERSION,WORKAREA,OPTIMIZE,CBUG,PORT,IMPORTANT,TEMP
 descent.core.compiler.versionIdentifiers=DigitalMars, Windows, Win32, X86, LittleEndian, D_InlineAsm, D_InlineAsm_X86, all, Tango, Descent
 descent.core.compiler.versionLevel=0
 descent.core.formatter.alignment_for_array_literals=0
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/bin/frankenbuild.map	Wed Jul 08 19:16:39 2009 -0700
@@ -0,0 +1,41 @@
+
+ Start         Length     Name                   Class
+ 0002:00000000 000213BBH  _TEXT                  CODE 32-bit
+ 0002:000213BC 000001FEH  ICODE                  ICODE 32-bit
+ 0003:00000000 00000004H  .CRT$XIA               DATA 32-bit
+ 0003:00000010 00000004H  .CRT$XIZ               DATA 32-bit
+ 0003:00000020 00000004H  .CRT$XCA               DATA 32-bit
+ 0003:00000030 00000004H  .CRT$XCZ               DATA 32-bit
+ 0003:00000040 00000004H  .CRT$XPA               DATA 32-bit
+ 0003:00000050 00000004H  .CRT$XPZ               DATA 32-bit
+ 0003:00000060 00000004H  .CRT$XTA               DATA 32-bit
+ 0003:00000070 00000004H  .CRT$XTZ               DATA 32-bit
+ 0003:00000074 00000000H  IMP__DATA              IMP__DATA 32-bit
+ 0003:00000080 0000E91CH  _DATA                  DATA 32-bit
+ 0003:0000E99C 00000000H  FMB                    DATA 32-bit
+ 0003:0000E99C 00000110H  FM                     DATA 32-bit
+ 0003:0000EAAC 00000000H  FME                    DATA 32-bit
+ 0003:0000EAAC 00000000H  XIB                    DATA 32-bit
+ 0003:0000EAAC 00000018H  XI                     DATA 32-bit
+ 0003:0000EAC4 00000000H  XIE                    DATA 32-bit
+ 0003:0000EAC4 00000000H  XCB                    DATA 32-bit
+ 0003:0000EAC4 00000010H  XC                     DATA 32-bit
+ 0003:0000EAD4 00000000H  XCE                    DATA 32-bit
+ 0003:0000EAD4 00000000H  XIFCB                  DATA 32-bit
+ 0003:0000EAD4 00000004H  XIFU                   DATA 32-bit
+ 0003:0000EAD8 00000000H  XIFL                   DATA 32-bit
+ 0003:0000EAD8 00000004H  XIFM                   DATA 32-bit
+ 0003:0000EADC 00000000H  XIFCE                  DATA 32-bit
+ 0003:0000EAE0 00000000H  CONST                  CONST 32-bit
+ 0003:0000EAE0 00000000H  EEND                   ENDBSS 32-bit
+ 0003:0000EAE0 000019FCH  _BSS                   BSS 32-bit
+ 0003:000104DC 00000000H  XOB                    BSS 32-bit
+ 0003:000104DC 00000004H  XO                     BSS 32-bit
+ 0003:000104E0 00000000H  XOE                    BSS 32-bit
+ 0003:000104E0 00000000H  XOFB                   BSS 32-bit
+ 0003:000104E0 00000108H  XOF                    BSS 32-bit
+ 0003:000105E8 00000000H  XOFE                   BSS 32-bit
+ 0003:000105F0 00000419H  c_common               BSS 32-bit
+ 0003:00010A10 00000000H  STACK                  STACK 32-bit
+
+Program entry point at 0001A090 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ref/buffer.d	Wed Jul 08 19:16:39 2009 -0700
@@ -0,0 +1,244 @@
+/**
+ * Hoofbaby -- http://www.dsource.org/projects/hoofbaby
+ * Copyright (C) 2009 Robert Fraser
+ * 
+ * This program is free software; you can redistribute it andor
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+module hoofbaby.util.buffer;
+
+import tango.time.StopWatch;
+import tango.core.sync.Condition;
+import tango.core.sync.Mutex;
+
+version(Windows)
+{
+	import tango.stdc.stringz;
+	import tango.text.convert.Format;
+	import tango.sys.win32.UserGdi;
+	
+	import hoofbaby.util.exception;
+
+	private extern(Windows)
+	{
+		HANDLE CreateFileMappingA(HANDLE, LPSECURITY_ATTRIBUTES, DWORD, DWORD, DWORD, LPCTSTR);
+		LPVOID MapViewOfFile(HANDLE, DWORD, DWORD, DWORD, DWORD);
+		LPVOID MapViewOfFileEx(HANDLE hFileMappingObject, DWORD dwDesiredAccess, DWORD dwFileOffsetHigh, DWORD dwFileOffsetLow, DWORD dwNumberOfBytesToMap, LPVOID lpBaseAddress);
+		BOOL UnmapViewOfFile(LPCVOID);
+	}
+	
+	private uint bufNum = 0;
+	
+	/**
+	 * Allocates a buffer of the given size. ALl accesses up to buf + (size * 2)
+	 * are valid; those over buf + size will reach around
+	 * 
+	 * Params:
+	 *     size = The size of the buffer (must be multiple of page size; use large powers of two)
+	 * Returns: A pointer to the beginning of that memory
+	 */
+	private void* _allocBuffer(uint size)
+	{
+		// Ensure page file is the right size
+		SYSTEM_INFO info;
+		GetSystemInfo(&info);
+		uint pageSize = info.dwAllocationGranularity;
+		if(size % pageSize) // PERHAPS next multiple of instead of error?
+			throw new IllegalOperationException(Format("Memory map pagefile mismatch -- "
+					"requested {0}, but page size is {1}", size, pageSize));
+		
+		// Try to allocate the buffer
+		HANDLE mmap = CreateFileMappingA(INVALID_HANDLE_VALUE, null, PAGE_READWRITE, 0, size, null);
+		if(!mmap) throw new UnrecoverableException("Could not create memory mapping for buffer");
+		void* buf = MapViewOfFile(mmap, FILE_MAP_ALL_ACCESS, 0, 0, size);
+		if(!buf) throw new UnrecoverableException("Could not map view of buffer");
+		void* buf2 = MapViewOfFileEx(mmap, FILE_MAP_ALL_ACCESS, 0, 0, size, buf + size);
+		if(!buf2) throw new UnrecoverableException("Could not map second view of buffer");
+		if(buf2 != buf + size) throw new UnrecoverableException("Memory mapped buffers are not contiguous");
+		return buf;
+	}
+	
+	private void _freeBuffer(void* buffer, uint size)
+	{
+		UnmapViewOfFile(buffer);
+		UnmapViewOfFile(buffer + size);
+	}
+}
+else
+{
+	static assert(false, "Unsupported operating system");
+}
+
+// IMPORTANT synchronization!!!!
+public struct RingBuffer
+{
+	private const double WAIT_TIME = 0.01; // 10 ms
+	private static Condition NULL_CONDITION;
+	
+	private uint size;
+	private void* addr;
+	
+	private uint readOfs;
+	private uint writeOfs;
+	
+	/**
+	 * The callback function to be called upon an overflow or underflow.
+	 * 
+	 * Params:
+	 *     buffer = The RIngBuffer instance with the issue
+	 *     sizeRequested = the size the operation requested
+	 *     sizeAvailable = how much is actually there
+	 * Returns: true if the function should return null, false if the buffer should still
+	 *          return the requested pointer (i.e. if the function waited until something
+	 *          was available)
+	 */
+	public alias bool delegate(RingBuffer* buffer, uint sizeRequested, uint sizeAvialbale) BufferCallback;
+	public BufferCallback onUnderflow;
+	public BufferCallback onOverflow;
+	
+	debug(AVBuffer)
+	{
+		private uint readRequested = 0;
+		private uint writeRequested = 0;
+	}
+	
+	public static RingBuffer opCall(uint size)
+	{
+		// Not really a singleton; who cares if more than one is constructed?
+		if(!NULL_CONDITION)
+			NULL_CONDITION = new Condition(new Mutex());
+		
+		RingBuffer r;
+		assert(size > 0);
+		r.size = size;
+		r.addr = _allocBuffer(size);
+		return r;
+	}
+	
+	public void free()
+	{
+		_freeBuffer(addr, size);
+		addr = null;
+	}
+	
+	public void* beginRead(uint requested)
+	{
+		debug(AVBuffer)
+		{
+			assert(readRequested == 0);
+			readRequested = requested;
+		}
+		
+		if(requested > available)
+		{
+			if(!onUnderflow || onUnderflow(this, requested, available))
+			{
+				debug(AVBuffer) readRequested = 0;
+				return null;
+			}
+		}
+		
+		return addr + readOfs;
+	}
+	
+	public void endRead(uint bytes)
+	{
+		debug(AVBuffer)
+		{
+			assert(bytes == readRequested);
+			readRequested = 0;
+		}
+		
+		readOfs += bytes;
+		if(readOfs > size)
+		{
+			readOfs -= bytes;
+			writeOfs -= bytes;
+		}
+	}
+	
+	public void* beginWrite(uint requested)
+	{
+		debug(AVBuffer)
+		{
+			assert(writeRequested == 0);
+			writeRequested = requested;
+		}
+		
+		if(requested > freeSpace)
+		{
+			if(!onOverflow || onOverflow(this, requested, available))
+			{
+				return null;
+			}
+		}
+		
+		return addr + writeOfs;
+	}
+
+	public void endWrite(uint bytes)
+	{
+		debug(AVBuffer)
+		{
+			assert(bytes == writeRequested);
+			writeRequested = 0;
+		}
+		
+		writeOfs += bytes;
+	}
+	
+	public uint available()
+	{
+		return writeOfs - readOfs;
+	}
+	
+	public uint freeSpace()
+	{
+		return size - available();
+	}
+	
+	public uint totalSize()
+	{
+		return size;
+	}
+	
+	public void clear()
+	{
+		readOfs = 0;
+		writeOfs = 0;
+	}
+	
+	public void isEmpty()
+	{
+		return readOfs == writeOfs;
+	}
+	
+	private bool _waitFor(char[] exp)(uint bytes, uint timeoutMs, Condition cond = null)
+	{
+		if(!cond)
+			cond = NULL_CONDITION;
+		
+		ulong microsecs = timeoutMs * 1000;
+		StopWatch sw;
+		sw.start();
+		do
+		{
+			if(mixin(exp) >= bytes)
+				return true;
+			if(cond.wait(WAIT_TIME))
+				return false;
+		} while(sw.microsec() < microsecs);
+		return false;
+	}
+	
+	public alias _waitFor!("available") waitAvailable;
+	public alias _waitFor!("freeSpace") waitFreeSpace;
+}
\ No newline at end of file
--- a/src/build/frankenbuild.d	Wed Jul 08 07:29:48 2009 -0700
+++ b/src/build/frankenbuild.d	Wed Jul 08 19:16:39 2009 -0700
@@ -64,7 +64,6 @@
     if(cats.contains("transcode"))
     {
     	targetFound = true;
-	    cats ~= "platif-debug";
 	    char[] cargs = cbase.dup;
 	    cargs ~= " -g";
 	    cargs ~= " -debug -debug=AVBuffer";
@@ -72,7 +71,6 @@
 	    cargs ~= " -I../src/test";
 	    cargs ~= " -oqobjs/debug";
 	    cargs ~= " ../src/test/hoofbaby/test/adhoc/transcode.d";
-	    commands ~= { return cpp("../src/platif/platif.h", "../src/impl/hoofbaby/platinum/platif.d"); };
 	    commands ~= { return rebuild(cargs); };
     }
 	
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/impl/hoofbaby/codec/encoder.d	Wed Jul 08 19:16:39 2009 -0700
@@ -0,0 +1,187 @@
+/**
+ * Hoofbaby -- http://www.dsource.org/projects/hoofbaby
+ * Copyright (C) 2009 Robert Fraser
+ * 
+ * This program is free software; you can redistribute it andor
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+module hoofbaby.codec.encoder;
+
+import hoofbaby.codec.libav.avutil;
+import hoofbaby.codec.libav.avcodec;
+import hoofbaby.codec.libav.avformat;
+
+public final class Encoder
+{
+	// TODO convert asserts to exceptions
+	
+	private const int OUTBUF_SIZE = 100000;
+	
+	private AVOutputFormat* format;
+	private AVFormatContext* formatContext;
+	
+	private AVCodec* audioCodec;
+	private AVCodecContext* audioContext;
+	private AVStream* audioStream;
+	private char* audioOutbuf;
+	
+	private AVCodec* videoCodec;
+	private AVCodecContext* videoContext;
+	private AVStream* videoStream;
+	private char* videoOutbuf;
+	
+	public this()
+	{
+		int ret; // Stores return value of functions called within
+		
+		//--------------------------------------------------------------------------
+		// Container format
+		
+		format = guess_format("asf", null, null);
+		assert(format !is null, "Could not find format");
+		
+		formatContext = av_alloc_format_context();
+		assert(formatContext !is null, "Could not allocate format context");
+		res.add(formatContext, &av_free);
+		formatContext.oformat = fmt;
+		//ctx.preload = cast(int) (0.5 * AV_TIME_BASE);
+		formatContext.max_delay = cast(int) (0.7 * AV_TIME_BASE);
+		formatContext.loop_output = AVFMT_NOOUTPUTLOOP;
+		formatContext.flags |= AVFMT_FLAG_NONBLOCK;
+		
+		AVFormatParameters params;
+		params.prealloced_context = 1;
+		params.video_codec_id = CODEC_ID_WMV2;
+		params.audio_codec_id = CODEC_ID_WMAV2;
+		params.width = 352; // TEMP
+		params.height = 288; // TEMP
+		params.time_base.num = 1; // TEMP
+		params.time_base.den = 25; // TEMP
+		params.pix_fmt = PIX_FMT_YUV420P;
+		params.channels = 2; // NEXTVERSION support >2 channels for devices that can handle it
+		params.sample_rate = 44100; // TEMP
+		ret = av_set_parameters(formatContext, null);
+		assert(ret >= 0, "Could not set parameters");
+		
+		//--------------------------------------------------------------------------
+		// Video stream
+		
+		videoStream = av_new_stream(formatContext, 0);
+		assert(videoStream !is null, "Could not allocate video stream");
+		formatContext.streams[0] = vstream;
+		
+		videoCodec = avcodec_find_encoder(CODEC_ID_WMV2);
+		assert(videoCodec !is null, "Could not find video codec");
+		
+		videoContext = videoStream.codec;
+		videoContext.codec_id = CODEC_ID_WMV2;
+		videoContext.codec_type = CODEC_TYPE_VIDEO;
+		videoContext.bit_rate = 400000; //TEMP
+		videoContext.width = 352; // TEMP
+		videoContext.height = 288; // TEMP
+		videoContext.gop_size = 12; // TEMP
+		videoContext.qmin = 3; // TEMP
+		videoContext.time_base.den = 25; // TEMP
+		videoContext.time_base.num = 1; // TEMP
+		videoContext.pix_fmt = PIX_FMT_YUV420P;
+		videoContext.flags |= CODEC_FLAG_GLOBAL_HEADER;
+		ret = avcodec_open(videoContext, videoCodec);
+		assert(ret >= 0, "Could not open video codec");
+		
+		videoOutbuf = cast(char*) av_malloc(OUTBUF_SIZE);
+		assert(videoOutbuf !is null, "Could not allocate video output buffer");
+		
+		//--------------------------------------------------------------------------
+		// Audio stream
+		
+		audioStream = av_new_stream(formatContext, 0);
+		assert(audioStream !is null, "Could not allocate audio stream");
+		formatContext.streams[1] = audioStream;
+		
+		audioCodec = avcodec_find_encoder(CODEC_ID_WMAV2);
+		assert(audioCodec !is null, "Could not find audio codec");
+		
+		audioContext = audioStream.codec;
+		audioContext.codec_id = CODEC_ID_WMAV2;
+		audioContext.codec_type = CODEC_TYPE_AUDIO;
+		audioContext.bit_rate = 64000;
+		audioContext.sample_rate = 44100;
+		audioContext.channels = 2;
+		audioContext.flags |= CODEC_FLAG_GLOBAL_HEADER;
+		ret = avcodec_open(audioContext, audioCodec);
+		assert(res >= 0, "Could not open audio codec");
+		
+		audioOutbuf = cast(char*) av_malloc(OUTBUF_SIZE);
+		assert(audioOutbuf !is null, "Could not allocate audio output buffer");
+		
+		scope(failure)
+		{
+			freeResources();
+		}
+	}
+	
+	public ~this()
+	{
+		freeResources();
+	}
+	
+	public void writeHeader()
+	{
+		int ret = av_write_header(formatContext);
+		assert(ret >= 0, "Could not write header for output file (incorrect codec paramters?)");
+	}
+	
+	public void writeTrailer()
+	{
+		int ret = av_write_trailer(ctx);
+		assert(ret >= 0, "Could not write trailer for output file");
+	}
+	
+	public void writeVideoFrame(AVFrame* frame)
+	{
+		int outSize = avcodec_encode_video(videoCodec, videoOutbuf, OUTBUF_SIZE, frame);
+		
+		// if zero size, it means the image was buffered, so don't write the packet
+		if(outSize > 0)
+		{
+			AVPacket pkt;
+			av_init_packet(&pkt);
+			pkt.pts = av_rescale_q(videoCodec.coded_frame.pts, videoCodec.time_base, videoStream.time_base);
+			if(videoCodec.coded_frame.key_frame)
+				pkt.flags |= PKT_FLAG_KEY;
+			pkt.stream_index = videoStream.index;
+			pkt.data = videoOutbuf;
+			pkt.size = outSize;
+			int ret = av_write_frame(ctx, &pkt);
+			assert(!ret, "Error writing video frame");
+		}
+	}
+	
+	public void writeAudioFrame(short* samples)
+	{
+		AVPacket pkt;
+		av_init_packet(&pkt);
+		pkt.size = avcodec_encode_audio(audioCodec, audioOutbuf, OUTBUF_SIZE, samples);
+		//pkt.pts = av_rescale_q(acodec.coded_frame.pts, acodec.time_base, acodec.time_base);
+		pkt.flags |= PKT_FLAG_KEY;
+		pkt.stream_index = audioStream.index;
+		pkt.data = audioOutbuf;
+		int ret = av_write_frame(ctx, &pkt) != 0;
+		assert(ret == 0, "Error writing audio frame");
+	}
+	
+	private void freeResources()
+	{
+		if(formatContext) av_free(formatContext);
+		if(audioOutbuf)   av_free(audioOutbuf);
+		if(videoOutbuf)   av_free(videoOutbuf);
+	}
+}
--- a/src/impl/hoofbaby/codec/libav/avbuffer.d	Wed Jul 08 07:29:48 2009 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,41 +0,0 @@
-/**
- * Hoofbaby -- http://www.dsource.org/projects/hoofbaby
- * Copyright (C) 2009 Robert Fraser
- * 
- * This program is free software; you can redistribute it andor
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- * 
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
-
-module hoofbaby.codec.libav.avbuffer;
-
-import hoofbaby.codec.libav.avformat;
-import hoofbaby.util.buffer;
-import tango.stdc.stdlib;
-import tango.stdc.string;
-import tango.stdc.stdio;
-
-ByteIOContext* getBioContext(RingBuffer* buf, int maxPacketSize)
-{
-	ByteIOContext* bio = av_alloc_put_byte(cast(char*) malloc(1 << 16), 1 << 16, 1, buf, null, &hoofbaby_avbuffer_write, null);
-	if(bio)
-		bio.is_streamed = true;
-	return bio;
-}
-
-extern(C) int hoofbaby_avbuffer_write(void* _buf, char* data, int size)
-{
-	RingBuffer* buf = cast(RingBuffer*) _buf;
-	assert(buf);
-	void* p = buf.beginWrite(size);
-	assert(p);
-	memcpy(p, data, size);
-	buf.endWrite(size);
-	return 0;
-}
--- a/src/impl/hoofbaby/codec/libav/avutil.d	Wed Jul 08 07:29:48 2009 -0700
+++ b/src/impl/hoofbaby/codec/libav/avutil.d	Wed Jul 08 19:16:39 2009 -0700
@@ -83,10 +83,6 @@
 	PIX_FMT_NB = 60,
 }
 
-alias char* function(void*) _BCD_func__901;
-alias void function(void*, int, char*, char*) _BCD_func__880;
-alias int function() _BCD_func__823;
-
 alias int AVRounding;
 enum : AVRounding
 {
@@ -100,7 +96,7 @@
 struct AVClass
 {
 	char* class_name;
-	_BCD_func__901 item_name;
+	char* function(void*) item_name;
 	void* option;
 }
 
@@ -119,7 +115,7 @@
 extern(C)
 {
 	void av_log_default_callback(void*, int, char*, char*);
-	void av_log_set_callback(_BCD_func__880);
+	void av_log_set_callback(void function(void*, int, char*, char*));
 	void av_log_set_level(int);
 	int av_log_get_level();
 	void av_vlog(void*, int, char*, char*);
--- a/src/impl/hoofbaby/codec/libav/swscale.d	Wed Jul 08 07:29:48 2009 -0700
+++ b/src/impl/hoofbaby/codec/libav/swscale.d	Wed Jul 08 19:16:39 2009 -0700
@@ -45,8 +45,6 @@
 const double SWS_MAX_REDUCE_CUTOFF = 0.002;
 typedef void SwsContext;
 
-alias int function() _BCD_func__867;
-
 struct SwsFilter
 {
 	SwsVector* lumH;
--- a/src/impl/hoofbaby/util/buffer.d	Wed Jul 08 07:29:48 2009 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,244 +0,0 @@
-/**
- * Hoofbaby -- http://www.dsource.org/projects/hoofbaby
- * Copyright (C) 2009 Robert Fraser
- * 
- * This program is free software; you can redistribute it andor
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- * 
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
-
-module hoofbaby.util.buffer;
-
-import tango.time.StopWatch;
-import tango.core.sync.Condition;
-import tango.core.sync.Mutex;
-
-version(Windows)
-{
-	import tango.stdc.stringz;
-	import tango.text.convert.Format;
-	import tango.sys.win32.UserGdi;
-	
-	import hoofbaby.util.exception;
-
-	private extern(Windows)
-	{
-		HANDLE CreateFileMappingA(HANDLE, LPSECURITY_ATTRIBUTES, DWORD, DWORD, DWORD, LPCTSTR);
-		LPVOID MapViewOfFile(HANDLE, DWORD, DWORD, DWORD, DWORD);
-		LPVOID MapViewOfFileEx(HANDLE hFileMappingObject, DWORD dwDesiredAccess, DWORD dwFileOffsetHigh, DWORD dwFileOffsetLow, DWORD dwNumberOfBytesToMap, LPVOID lpBaseAddress);
-		BOOL UnmapViewOfFile(LPCVOID);
-	}
-	
-	private uint bufNum = 0;
-	
-	/**
-	 * Allocates a buffer of the given size. ALl accesses up to buf + (size * 2)
-	 * are valid; those over buf + size will reach around
-	 * 
-	 * Params:
-	 *     size = The size of the buffer (must be multiple of page size; use large powers of two)
-	 * Returns: A pointer to the beginning of that memory
-	 */
-	private void* _allocBuffer(uint size)
-	{
-		// Ensure page file is the right size
-		SYSTEM_INFO info;
-		GetSystemInfo(&info);
-		uint pageSize = info.dwAllocationGranularity;
-		if(size % pageSize) // PERHAPS next multiple of instead of error?
-			throw new IllegalOperationException(Format("Memory map pagefile mismatch -- "
-					"requested {0}, but page size is {1}", size, pageSize));
-		
-		// Try to allocate the buffer
-		HANDLE mmap = CreateFileMappingA(INVALID_HANDLE_VALUE, null, PAGE_READWRITE, 0, size, null);
-		if(!mmap) throw new UnrecoverableException("Could not create memory mapping for buffer");
-		void* buf = MapViewOfFile(mmap, FILE_MAP_ALL_ACCESS, 0, 0, size);
-		if(!buf) throw new UnrecoverableException("Could not map view of buffer");
-		void* buf2 = MapViewOfFileEx(mmap, FILE_MAP_ALL_ACCESS, 0, 0, size, buf + size);
-		if(!buf2) throw new UnrecoverableException("Could not map second view of buffer");
-		if(buf2 != buf + size) throw new UnrecoverableException("Memory mapped buffers are not contiguous");
-		return buf;
-	}
-	
-	private void _freeBuffer(void* buffer, uint size)
-	{
-		UnmapViewOfFile(buffer);
-		UnmapViewOfFile(buffer + size);
-	}
-}
-else
-{
-	static assert(false, "Unsupported operating system");
-}
-
-// IMPORTANT synchronization!!!!
-public struct RingBuffer
-{
-	private const double WAIT_TIME = 0.01; // 10 ms
-	private static Condition NULL_CONDITION;
-	
-	private uint size;
-	private void* addr;
-	
-	private uint readOfs;
-	private uint writeOfs;
-	
-	/**
-	 * The callback function to be called upon an overflow or underflow.
-	 * 
-	 * Params:
-	 *     buffer = The RIngBuffer instance with the issue
-	 *     sizeRequested = the size the operation requested
-	 *     sizeAvailable = how much is actually there
-	 * Returns: true if the function should return null, false if the buffer should still
-	 *          return the requested pointer (i.e. if the function waited until something
-	 *          was available)
-	 */
-	public alias bool delegate(RingBuffer* buffer, uint sizeRequested, uint sizeAvialbale) BufferCallback;
-	public BufferCallback onUnderflow;
-	public BufferCallback onOverflow;
-	
-	debug(AVBuffer)
-	{
-		private uint readRequested = 0;
-		private uint writeRequested = 0;
-	}
-	
-	public static RingBuffer opCall(uint size)
-	{
-		// Not really a singleton; who cares if more than one is constructed?
-		if(!NULL_CONDITION)
-			NULL_CONDITION = new Condition(new Mutex());
-		
-		RingBuffer r;
-		assert(size > 0);
-		r.size = size;
-		r.addr = _allocBuffer(size);
-		return r;
-	}
-	
-	public void free()
-	{
-		_freeBuffer(addr, size);
-		addr = null;
-	}
-	
-	public void* beginRead(uint requested)
-	{
-		debug(AVBuffer)
-		{
-			assert(readRequested == 0);
-			readRequested = requested;
-		}
-		
-		if(requested > available)
-		{
-			if(!onUnderflow || onUnderflow(this, requested, available))
-			{
-				debug(AVBuffer) readRequested = 0;
-				return null;
-			}
-		}
-		
-		return addr + readOfs;
-	}
-	
-	public void endRead(uint bytes)
-	{
-		debug(AVBuffer)
-		{
-			assert(bytes == readRequested);
-			readRequested = 0;
-		}
-		
-		readOfs += bytes;
-		if(readOfs > size)
-		{
-			readOfs -= bytes;
-			writeOfs -= bytes;
-		}
-	}
-	
-	public void* beginWrite(uint requested)
-	{
-		debug(AVBuffer)
-		{
-			assert(writeRequested == 0);
-			writeRequested = requested;
-		}
-		
-		if(requested > freeSpace)
-		{
-			if(!onOverflow || onOverflow(this, requested, available))
-			{
-				return null;
-			}
-		}
-		
-		return addr + writeOfs;
-	}
-
-	public void endWrite(uint bytes)
-	{
-		debug(AVBuffer)
-		{
-			assert(bytes == writeRequested);
-			writeRequested = 0;
-		}
-		
-		writeOfs += bytes;
-	}
-	
-	public uint available()
-	{
-		return writeOfs - readOfs;
-	}
-	
-	public uint freeSpace()
-	{
-		return size - available();
-	}
-	
-	public uint totalSize()
-	{
-		return size;
-	}
-	
-	public void clear()
-	{
-		readOfs = 0;
-		writeOfs = 0;
-	}
-	
-	public void isEmpty()
-	{
-		return readOfs == writeOfs;
-	}
-	
-	private bool _waitFor(char[] exp)(uint bytes, uint timeoutMs, Condition cond = null)
-	{
-		if(!cond)
-			cond = NULL_CONDITION;
-		
-		ulong microsecs = timeoutMs * 1000;
-		StopWatch sw;
-		sw.start();
-		do
-		{
-			if(mixin(exp) >= bytes)
-				return true;
-			if(cond.wait(WAIT_TIME))
-				return false;
-		} while(sw.microsec() < microsecs);
-		return false;
-	}
-	
-	public alias _waitFor!("available") waitAvailable;
-	public alias _waitFor!("freeSpace") waitFreeSpace;
-}
\ No newline at end of file