H264 HTTP Test Stream Generator

As I haven't got an H264-capable camera to use as a test source (yet) I'm using the following GStreamer pipeline, adapted from videotestsrc documentation to generate an endless, mildly hypnotic low bitrate zone plate pattern wrapped in an MPEG transport stream. A clock is also shown so that when the stream is transcoded and/or segmented, it's easy to see how bad the lag is. Audio is not included but for example audiotestsrc could be plugged in the pipeline if necessary (although I won't be using audio in my app). VLC is used in the end of the command line to serve the stream over HTTP.
gst-launch-0.10 -v mpegtsmux name="mux" ! fdsink fd=1 »
videotestsrc pattern=zone-plate kx2=20 ky2=20 kt=1 ! »
video/x-raw-yuv,width=320,height=240 ! »
clockoverlay valign=bottom halign=left font-desc="Sans 23" ! »
ffmpegcolorspace ! videorate ! video/x-raw-yuv,framerate=15/1 ! »
x264enc bitrate=100000 cabac=false pass=qual quantizer=27 »
subme=4 threads=0 bframes=0 dct8x8=false ! mux. | »
vlc -I "dummy" file/ts:///dev/stdin »
:sout='#std{access=http{mime=video/mp4},mux=ts,dst=192.168.1.35:8000}'

Update: Here's how to save the encoded video to an MPEG-4 file:

gst-launch-0.10 -v videotestsrc num-buffers=900000 pattern=zone-plate kx2=20 ky2=20 kt=1 ! video/x-raw-yuv,width=1920,height=1080,framerate=25/1 ! x264enc bitrate=16000 cabac=false pass=qual quantizer=27 subme=4 threads=0 bframes=0 dct8x8=false ! queue ! muxer. ffmux_mp4 name=muxer ! filesink location=zone-plate-900000-frames-1920x1080-25fps.m4v

Tagged with:

Categorised as:


HTTP Live Streaming with VLC

Well, it took "a while" but I finally got HTTP Live Streaming working with VLC. Downloading and compiling the latest from Videolan's Git repo was required ("1.2.0-git Twoflower" here). I might add that even though on the box that I did this I've compiled a lot of different programs (an Ubuntu installation that has gone through multiple dist-upgrades so it's a few years old and has a lot of packages (2344 atm) installed), quite a few external -dev packages relating to audio and video had to be apt-get'ed to make things work. Below is the command to make VLC read a DVD and generate a segmented stream of H264 video and AAC audio to directory /var/www/html-video-stream/x/ on our local web server. In an IRL situation we would perhaps run the transcoder and segmenter instances on separate machines, or if we already had a suitable H264 stream source (like a camera) we could skip the transcoding step altogether.
vlc -v -I "dummy" dvdsimple:///dev/scd0 »
:sout="#transcode{vcodec=h264,vb=100, »
venc=x264{aud,profile=baseline,level=30,keyint=30,ref=1}, »
aenc=ffmpeg{aac-profile=low},acodec=mp4a,ab=32,channels=1,samplerate=8000} »
:std{access=livehttp{seglen=10,delsegs=true,numsegs=5, »
index=/var/www/html-video-stream/x/stream.m3u8, »
index-url=http://192.168.1.33/html-video-stream/x/stream-########.ts}, »
mux=ts{use-key-frames}, »
dst=/var/www/html-video-stream/x/stream-########.ts}"
  QuickTime X (fanboys have had this since Snow Leopard) supports HTTP Live Streaming, so in order to show the above stream on a web page in Safari using the <video> tag, we can do the following:
<video autoplay loop controls>
  <source src="http://192.168.1.33/html-video-stream/x/stream.m3u8" »
   type='video/mp4; codecs="avc1.42E01E, mp4a.40.2"'/>
  <!-- additional sources here -->
</video>
  Although I'm not sure if this will work in a situation where we attempt to feed H264 to clients that don't support HTTP Live Streaming, that is, we have an additional <source> element that points to a "regular" H264 HTTP stream. However, adding Ogg/Theora and WebM/VP8 support should not cause problems – I just haven't been able to make VLC output those (properly) yet. HTML5 video tag streaming support in different browsers is also one big question mark.

Tagged with:

Categorised as:


Blogging activities migrated to Async.fi

Installing Wordpress and getting the basic settings straight was, all and all, a relatively painless experience. One downside of choosing this particular blogging platform is that I now have to run a MySQL server just for this purpose (I have no intention to use MySQL for anything else as I have actively tried to steer away from RDBMSs, even before this whole "NoSQL" thing became fashionable). I would've preferred to be able to run Wordpress on top of an SQLite backend, just because that would've kept things one step simpler, but I just could not get the "PDO (SQLite) For WordPress" adapter to work with a reasonable amount of work, so I gave up and went ahead with a MySQL server install. So it's a tradeoff (what isn't?) but with all these plugins and stuff and whatnot that this system supports I think it's a pretty good deal. I went through the old posts at sivuraide.blogspot.com and imported what I thought I might find useful at least to some extent. Unsurprisingly not too many of the old posts fall to this category. Then again, the old blog is titled Code Notebook. The old posts did not "just work" in all places, a quick eyeballing revealed some glitches that need to be ironed out. I installed the following plugins in addition to what was bundled:

Tagged with:

Categorised as:


(Desktop) Safari & (W3C) Geolocation API

I don't know why this thing fails in desktop Safari. I'm using Modernizr (which is bundled with the highly recommended HTML5 Boilerplate) which reports that the Geolocation API is supported but I'm unable to even get any dialog asking the user for permission to geolocate (which is, if I read the draft correctly, REQUIRED to be implemented). Also, it seems that others (quite a few people actually) have had this same problem but I have been unable to find a solution yet. Below is a snippet from the code; in desktop Safari the PositionErrorCallback (the latter cb function) gets called after timeout but no luck with PositionCallback, no matter how long the timeout value is. Other tested browsers work as expected. Referenced in other places:

(Note to self: check if Google Gears, which is still installed, is causing this?)

[javascript] var position = null; $(document).ready(function() { if(!Modernizr.geolocation) { return; } navigator.geolocation.watchPosition( function(pos) { position = {}; position.lat = pos.coords.latitude; position.lng = pos.coords.longitude; position.allowed = true; init(); }, function(error) { position = {}; position.allowed = false; }, { enableHighAccuracy: false, timeout: 10000, maximumAge: 86400000 } ); checkposition(); }); function checkposition() { log("checkposition()"); if(!position) { setTimeout(function() { checkposition(); }, 1000); return; } else { if(position.allowed) { log("checkposition(): got position: " + position.lat + "," + position.lng); fetchephemeris(); } else { log("checkposition(): could not get a position, giving up"); $("#geolocate").hide(); } } } [/javascript]

Tagged with:

Categorised as:


QUERY_STRING parsing in plain C

As far as I can tell (which, I'll be the first one to admit, doesn't count for that much) this code is so simple that there are no holes that could be exploited.

  char * query = getenv("QUERY_STRING");
  char * pair;
  char * key;
  double value;

  if(query &amp;&amp; strlen(query) > 0) {
    pair = strtok(query, "&amp;");
    while(pair) {
      key = (char *)malloc(strlen(pair)+1);
      sscanf(pair, "%[^=]=%lf", key, &amp;value;);
      if(!strcmp(key, "lat")) {
        lat = value;
      } else if(!strcmp(key, "lng")) {
        lng = value;
      }
      free(key);
      pair = strtok((char *)0, "&amp;");
    }
  }

Tagged with:

Categorised as: