Reading Motion-JPEG camera streams
I’ve recently come across a Hawking HNC230G network camera, which shares internals with the Edimax IC-1500Wg. These cameras pump out a Motion-JPEG stream which is unlike many other “Motion-JPEG” IP cameras.
Many of these devices will create video with a constantly updating jpeg file, served via HTTP. This is generally a better solution than what exists in my camera. Reading these streams is simple in many languages. The HNC230G took a little more probing and experimentation before I could read data without artifacts.
Camera Services
HTTP Administration website – Port 80
Motion-JPEG stream – Port 4321
There does not appear to be any images on the HTTP administration website. All video data passes through the service on 4321. Video data is not encrypted or secured in any way – there is no authentication.
Finished Protocol
After a socket is connected to the service on 4321, it should send the single command which is supported: 0110\n. Sending 0110 followed by a linebreak will signal the device to send a JFIF frame.
The camera will send 4 bytes of data before the JFIF header, these bytes can be interpreted as follows:
- Byte 1: High 8 bits of the frame size
- Byte 2: Low 8 bits of the frame size
- Byte 3: Active users on the camera
- Byte 4: Unknown reserved byte
The size of the frame is calculated only after the 4-byte header. The process can be repeated once the frame has been received by the client. The image data received will contain a JFIF (JPEG File Interchange Format) frame.
I’ve been able to achieve approximately 10fps at 640×480 with this method.
Limitations
The key limitations with this method relate to the firmware design for this camera.
- Image size can only be set through the HTTP web service.
- LED state can only be queried or set through the HTTP web service.
- The device will sometimes disconnect the client or return invalid data. This is solved by reconnecting the client.
- As the number of users increase, the possible frames-per-second decreases. Frame rates are 25-50% less when adding a second user.
Sample C# Code
public byte[] GetFrame() { if (!conn.Connected) { Connect(); if (!conn.Connected) { throw new Exception("Cannot fetch frame from camera. Not Connected."); } } StreamWriter sw = new StreamWriter(conn.GetStream()); // request a frame sw.WriteLine("0110"); sw.Flush(); // get the high 8bits of the size int size = conn.GetStream().ReadByte() << 8; // get the low 8bits of the size size += conn.GetStream().ReadByte(); // active users int j1 = conn.GetStream().ReadByte(); ActiveUsers = j1; // unknown byte int j2 = conn.GetStream().ReadByte(); if (size == 0) { return null; } return new BinaryReader(conn.GetStream()).ReadBytes(size); }
Comments
One Comment on Reading Motion-JPEG camera streams
-
Keapon Laffin on
Sat, 30th Oct 2010 4:16 PM
Wow! Thank you mucho. I’ve been teaching myself C# forever trying to reverse engineer this camera’s stupid viewer software.
Tho now I’m mad because I see I was 90% finished figuring it out. ;)
Thanks again.
