Saturday, April 13, 2013

Handling Motion JPEG video streams with pharo smalltalk

Playing around with Zinc’s streaming entities I looked for a source of streaming data. A never ending streaming source are video streams. So I implemented a very simple Motion JPEG reader using Pharo Smalltalk. It does not use any plugins. Just plain smalltalk and a stock pharo image.

Use your pharos monticello browser to add the following repository and open it.

MCHttpRepository
   location: 'http://www.min.at/prinz/repo/mjpeg'
   user: ''
   password: ''

Update:
Some people have reported hat they cannot load the package into their image. Opening a monticello browser, adding a new http repository with +Repository and pasting the code snippet above and then opening the repository works as expected. Alternatively you can download the package using this link and open it from a local directory repository.

Update 2:
As noted by Sven Van Caekenberghe the mime type for .mcz monticello archives is now set to application/x-monticello in the webserver response. So now there should not be any format errors. Thanks for this hint.

Update 3:
Cédrick Béler modified the source to work under Pharo 7. Thanks for that. The new version can be found in the repo.

It consists of just one class Mjpeg.

| cam |
" Create a new MJPEG stream from a given url "
cam := Mjpeg 
   fromUrl: 'http://218.219.210.174:86/mjpg/video.mjpg?camera=1'.
" Start reading the stream and displaying it in a window "
cam start. 
" Start capturing the stream frame by frame to disk "
cam startCapture: 'c:/temp/test'.
" Returns true if the stream is started (reading or "
" capturing), false otherwise "
cam isRunning.
" Stop reading the stream and close the camera window "
cam stop.
" Stop capturing "
cam stopCapture.

There are two example class methods availabe.

" Sample of a webcam stream from Tokyo "
Mjpeg exampleTokyo.
" Webcam from Vienna "
Mjpeg exampleVienna.

Performance of this simple implementation is quite good. The Tokyo example used the stream available at http://218.219.210.174:86/mjpg/video.mjpg?camera=1. Playing this stream with Pharo has no impact on CPU usage whereas playing the same stream with Chrome has a noticeable effect on CPU usage.

  1. Thomas Worthington

    Monday, April 15, 2013 at 20:55:43

    I’m just getting “Expected a binary response instead of text/plain” when trying to open the repo.

  2. Colin

    Saturday, April 20, 2013 at 23:43:06

    I’m getting same error when trying to load/open repo : Error bad signature

  3. Tom

    Sunday, April 21, 2013 at 11:13:06

    Error Bad Signature

  4. Sven Van Caekenberghe

    Monday, April 22, 2013 at 11:09:09

    Hi Richard,

    This is really a cool hack. Thanks for sharing it. It has the hallmark of a great hack because it looks simple when you read the code, well done.

    Sven

    PS: the problem with your repository is that you (your server) is serving the .mcz files as text/plain, in Pharo try

    ZnEasy head: ‘http://www.min.at/prinz/repo/mjpeg/Mjpeg-RichardPrinz.3.mcz’

    and inspect the contentType.

    Pharo/Zinc is strict about this, here are some mailing list discussion explaining the issue

    http://forum.world.st/Monticello-and-webdav-tt4633710.html#a4633845
    http://forum.world.st/making-Apache-serve-mcz-files-in-the-proper-mode-tt4639360.html#a4639457

  5. Karl

    Friday, April 26, 2013 at 06:41:47

    Cool implementation.
    One question
    You say you don’t use any primitives, but you use JPEGReadWriter to decompress the image.
    Did you mean that you don’t use any primitives to do the streaming ?

    Karl