Friday, December 21, 2007
For the last couple weeks I've been struggling with getting camera capture inside a desktop application (yes - I lower myself to do desktop development occasionally).  The problem I'm finding is that API documentation and especially sample availability for things like DShow and Windows Image Acquisition (WIA) are pretty poor and there seem to be no reasonable, comprehensize samples on how to use any of it.  Occasionally you find something on sites like CodeProject, but IMO those projects tend to suck.  The authors typically "solve" a specific problem by writing code tightly coupled to the problem they're solving, so the code is very rarely reusable or extensible, and the quality usually is lacking as well.

Well today I finished up a general library and test harness for WIA.  It's too soon to tell if we'll actually use it in the application I'm working on, since it's missing a lot of capabilities that DShow will likely be better for, but to save a little headache in the developer community, I'm making it shared source (under our typical MIT x11 license).  It provides a simple object model for seeing what cameras you have, displaying live video from them and grabbing frames.  The test harness generates a TabControl with a page for each camera you have plugged in.  If you add or remove a camera while the app is running, tabs are added or removed.

Most importantly I designed the clas library for general use.  It can be dropped into any project and consumed for camera control without a bunch of rewrite, and while I'm not going to say it's bug free, I at least tested it though several scenarios and let it run for a fairly long time without it puking (which is more than I can say about pretty much anything else I found).

Below is the object model and a screen shot of the test app.





Download the source code here (Updated 1/3/08).
12/21/2007 4:14:58 PM (Eastern Standard Time, UTC-05:00)  #    Comments [0]  | 
 Friday, December 14, 2007
We here at OpenNETCF are huge proponents of teaching technology in an academic environment.  It still surprises me that both Mobile and Embedded computing are entwined in our everyday lives and their presence is growing rapidly, yet very, very few schools offer any sort of courses covering them. 

That's why it's always interesting to see that when mobile development is being taught, students sometimes turn to our libraries for the exact same reasons that non-academic customers do - so they can get more done in less time (I've always considered people that won't use third party tools foolish, as they spend a lot of time and opportunity cost developing something that's already been done).

If you're looking for a school that actually teaches material that is relevent in our industry, Georgia Tech seems to have a pretty strong mobile and embedded curriculum.  I just saw that a team put together a war-walking application this semester using the SDF.  We've shipped them some more software and we're keen to see how they use it in the coming semesters.

12/14/2007 9:43:56 AM (Eastern Standard Time, UTC-05:00)  #    Comments [0]  | 
 Thursday, December 13, 2007
Today we rolled out an update to Padarn: version 1.0.5010.

"So what's new," you ask? 

  1. We added support for the Page.Request.Browser property.  On the surface it seemed quite simple, but the implementation was actually quite a challenge.
  2. We fixed a bug that Page.Request.Headers always came back null
  3. We updated the SampleSite demo including:
    1. Updates and additions to the OpenNETCF.Web.Html namespace
    2. A new Camera Demo page that controls a camera in our "server closet"
    3. A page showing hosting the WMP control service media off of Padarn
    4. A page that shows client browser capability detection
The docs and live page are updated - you can reach them both from here:  www.opennetcf.com/padarn.ocf


We are also now offering Padarn free of charge for academic use.  Contact us for details.

12/13/2007 7:26:16 PM (Eastern Standard Time, UTC-05:00)  #    Comments [0]  | 
 Thursday, December 06, 2007

So I picked up a cheap PTZ (pan/tilt/zoom) camera off eBay a couple weeks ago for doing some R&D on a project I'm working on.  My hope was I'd be able to hook it up and talk to it from a device and get streaming video into an app.  Well it turns out that it's not so simple.  All cameras appear to have some form of proprietary interface that obviously varies from OEM to OEM.

I hooked up WireShark in hopes that I could reverse engineer the network commands fromthe packets, but it looks like it would take me weeks to get it figured out, and I don't have that kind of time (or desire) so I shot off an email to the OEM.  While I wait for them to reply (if they ever do) I went about reverse-engineering a kludge.

The device has a built in web server that allows you to control the camera, view video, etc.  So I opened up a page and looked at the source.  It contained a frameset, so I started navigating through frame pages and deconstructing the html to see what commands did what.  Unfortunately the video streaming piece appears to be in a compiled Java applet so getting at that turned out to be a dead-end, however it wasn't a total loss.  I did figure out how to send it commands to pan, tilt and capture single frames (well I figured out a lot more, but I limited my implementation to those functions for now).

So armed with what I knew, I slapped together the following class, basically simulating myself as a browser:

using System;
using System.Net;
using System.Net.Sockets;
using System.Drawing;
using System.IO;
using System.Threading;
using OpenNETCF.Peripherals.Camera;

namespace OpenNETCF.Peripherals
{
  public class MegaTecCamera : ICamera
  {
    private const int CMD_UP = 1;
    private const int CMD_DOWN = 2;
    private const int CMD_LEFT = 3;
    private const int CMD_RIGHT = 4;

    private string m_ip;
    private string m_username;
    private string m_password;

    public MegaTecCamera(IPAddress address, string username, string password)
    {
        m_ip = address.ToString();
        m_username = username;
        m_password = password;
    }

    public Image GetImage()
    {
        Image img = null;

        string command = string.Format(http://{0}/pda.cgi?user={1}&password={2}&page=image&cam=1
            m_ip, m_username, m_password);

        byte[] buffer = new byte[10000];
        HttpWebRequest request = (HttpWebRequest)WebRequest.Create(command);
        HttpWebResponse response = (HttpWebResponse)request.GetResponse();
        using (Stream stream = response.GetResponseStream())
        {
            try
            {
                img = new Bitmap(stream);
            }
            catch (Exception ex)
            {
                System.Diagnostics.Debug.WriteLine("Capture failed: " + ex.Message);
            }

            response.Close();
        }
        return img;
    }

    public void Pan(PanDirection direction)
    {
        if (direction == PanDirection.Left)
            SendHttpCommand(GetDirectionCommand(CMD_LEFT));
        else
            SendHttpCommand(GetDirectionCommand(CMD_RIGHT));
    }

    public void Tilt(TiltDirection direction)
    {
        if (direction == TiltDirection.Up)
            SendHttpCommand(GetDirectionCommand(CMD_UP));
        else
            SendHttpCommand(GetDirectionCommand(CMD_DOWN));
    }

    private string GetDirectionCommand(int direction)
    {
        return string.Format(http://{0}/pda.cgi?user={1}&password={2}&page=execute&cam=1&command={3},
            m_ip, m_username, m_password, direction);
    }

    private void SendHttpCommand(string command)
    {
        ThreadPool.QueueUserWorkItem(new WaitCallback(delegate(object o)
        {
            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(command);
            try
            {
                request.GetResponse().Close();
            }
            catch { }
        }));
    }
  }
}

The next obvious question is "What the hell do I do with this class that is of any use?"

Well that's the fun part!  I integrated it into a sample page on our demo Padarn server, so we now have images captured from an IP camera streamed back to a 200MHz Windows CE device that in turn serves up those images (and control of the camera) using an ASP.NET server.

The next step I'll add is the ability to turn on and off the light in the room via a web page.

 

12/6/2007 6:15:00 PM (Eastern Standard Time, UTC-05:00)  #    Comments [1]  | 
 Thursday, November 29, 2007
We just published a new article on using WCF from device applications on the Community siteRead it here.

11/29/2007 2:40:14 PM (Eastern Standard Time, UTC-05:00)  #    Comments [0]  | 
In case you missed it, I published a new article on our community site last week on how to get a DateTime.Now equivalent with the milliseconds field filled in.  Read it here.

11/29/2007 11:20:53 AM (Eastern Standard Time, UTC-05:00)  #    Comments [0]  | 
 Tuesday, November 13, 2007
11/13/2007 12:11:46 PM (Eastern Standard Time, UTC-05:00)  #    Comments [0]  | 
We've proactively pulled (meaning no one threatened us or asked us to do it) our QRCodeCF Library from public availability due to internal concerns about GPL.  Personally I dislike GPL due to its viral nature - it makes using any GPL code in any software that you intend to use for commercial or proprietary systems extremely risky, and we simply don't want to perpetuate that.  We write software to solve problems, and not surprisingly I feel those who write software should be able to get paid for doing so and not worry that their entire business might have to be given away because of some insane licensing issue.

11/13/2007 12:10:29 PM (Eastern Standard Time, UTC-05:00)  #    Comments [0]  |