Table of Contents
SSDV (Slow Scan Digital Video) is a packetised digital form of SSTV (Slow Scan TeleVision). It can be used to transmit small images along with the regular telemetry transmitted by a payload during flight. Any digital mode that can carry text or data can be used, although the current implementation is limited to 8-bit RTTY (Radio TeleTYpe).
|0||Sync Byte||1||0x55 - May be preceded by one or more sync bytes|
|1||Packet Type||1||0x66 - Normal mode (224 byte packet + 32 byte FEC)|
|0x67 - No-FEC mode (256 byte packet)|
|2||Callsign||4||Base-40 encoded callsign. Up to 6 digits|
|6||Image ID||1||Normally beginning at 0 and incremented by 1 for each new image|
|7||Packet ID||2||The packet number, beginning at 0 for each new image (big endian)|
|9||Width||1||Width of the image in MCU blocks (pixels / 16) 0 = Invalid|
|10||Height||1||Height of the image in MCU blocks (pixels / 16) 0 = Invalid|
|11||Flags||1||00qqqexx: 00 = Reserved, qqq = JPEG quality level (0-7 XOR 4), e = EOI flag (1 = Last Packet), xx = Subsampling Mode (0 = 2×2, 1 = 1×2, 2 = 2×1, 3 = 1×1)|
|12||MCU offset||1||Offset in bytes to the beginning of the first MCU block in the payload, or 0xFF if none present|
|13||MCU index||2||The number of the MCU pointed to by the offset above (big endian), or 0xFFFF if none present|
|15||Payload||205 / 237||Payload data|
|220 / 252||Checksum||4||32-bit CRC|
|224||FEC||32||Reed-Solomon forward error correction data. Normal mode only (0x66)|
Sizes and offsets are in bytes, with each packet being 256 bytes in total.
The image should contain just the scan data from a JPEG image (an “Abbreviated image” in JPEG terminology), with none of the markers or headers that normally make up a JPEG image. Because there are no headers, the image must conform to the following rules:
- Y′CbCr colour format
- Width and height must be a multiple of 16 (up to a resolution of 4080 x 4080)
- The quantisation and huffman tables are fixed
- Baseline DCT only
- Total scan data must not exceed 13434880 bytes (~12.8 MB) in length (205 payload bytes per packet, 65536 packets max)
- The first MCU of each packet is byte aligned
- The first DC values for each component in the first MCU of a packet are relative to 0
- The scan data does not need byte stuffing (0xFF bytes do not need to be followed by 0x00)
- The total number of MCU blocks must not exceed 65535
Each packet ends with 32 bytes of Reed-Solomon codes, calculated from the 223 bytes beginning with the packet type (offset 1) to the end of the payload data. These codes allow the receiver to correct up to 16 byte errors in a received packet (including the Reed-Solomon codes themselves).
Whilst the Reed-Solomon decoder is able to handle incorrectly received bytes it is useless when it comes to missing bytes. When a byte is dropped for any reason all subsequent bytes will be in the wrong position and the decoder will see most as errors. To better handle this the receiver should be able to detect and insert an appropriate number of padding bytes, allowing the decoder to see them as errors and correct.
C code to generate the Reed-Solomon codes is available here: rs8encode
When a packet is lost there are a number of scenarios that may need to be handled:
- An MCU block from the previous packet was incomplete. If the break occurs during the AC coefficients of a component, emit the EOB symbol to end them early. For each remaining component in the MCU emit an EOB symbol for both the DC and AC coefficients. This should end the incomplete MCU cleanly.
- Subtract the MCU index value from the index of the last decoded MCU block to calculate how many blocks have been lost. For each lost block emit an empty MCU block.
- The current packet will likely begin with the end of one of the missing MCU blocks. This data cannot be used and needs to be discarded. The MCU offset field in the header indicates the number of bytes to skip before resuming decoding.
Once these conditions have been dealt with, normal decoding can resume.
Modulation / Mode
The current implementation uses 8-bit RTTY at various baud rates. A more appropriate method should be used in future.
One idea is to pack the SSDV packets (sans-FEC) into an AX.25 frame for transmission over standard amateur radio packet networks. It may even be possible to do this in such a way that the format is compatible with the APRS network.
dl-fldigi contains a decoder built in, that listens to the RTTY stream for packets and decodes when received. It also can upload the packet to a central server where the data from multiple distributed listeners can be combined - often filling in gaps.
NOTE: Versions prior to DL3.1 contained an older version of the SSDV decoder which can not handle the finalised format described above.
I have written a small command line application that can encode and decode the packet data. It is used by the server to produce the images from the data uploaded by multiple dl-fldigi users.
hadie flight software
An example of how I used the code on the hadie flights can be seen in the flight software, available on github:
The camera used on these flights was a C328-based UART camera.
- Dynamic or adaptive huffman and quantisation tables.
- Try 1200 baud on a future flight. (Tim did this, and it mostly worked. Requires very careful tuning)
- BPSK modulation via fldigi.
- Add an interface to dl-fldigi for sending images.
- 2015-10-19: An EOI flag was added to the header, using one of the previously reserved bits. This bit should be set to 0 except on the final packet for the current image.
- Some final changes made to the format 2012-03-04. Images produced with this version of the encoder will be compatible with all future decoders.
- TU Delft launch in Holland transmitted images at 600 and 1200 baud. Two receiving stations where decoding data, and at 600 baud almost all data was received. Some of the 1200 baud images where also received, but with more gaps in the data.
- hadie:3 tested the latest version at 300 baud and was a full success. Every image was decoded completely, with only a few missing packets near the ground when I was changing antenna. Although each station missed a couple of packets the combined uploaded images where complete.
- The new version was used on the hadie:2 HAB flight 2011-01-09 with the updated error recovery and correction code. An antenna problem meant the signal was very weak and contact was lost with the balloon shortly after launch, but despite this three full images where returned from the air. Missing packets had no impact on the rest of the image, which continued decoding as data came in.
- An early version was used on the Cirrus/Hadie HAB flight 2010-04-16. This version transmitted the entire JPEG file returned by a C328 serial camera but flaws in the reception code left the error correction ineffective and a number of packets where lost. Lacking the ability to correct the JPEG stream, the lost packets prevented the image from decoding after that point.