Search code examples
cjpegmicrocontrollerdata-lossradio-transmission

Compensating for missing jpeg bytes


I am making a program for a micro-controller connected to a radio that has to send bytes of a JPEG image to a computer. I want to know if there is a way to compensate for a situation where some bytes of the JPEG are lost. As it is now, if even 1 byte is lost it corrupts the whole image. I could program it so the micro-controller re-sends the bytes that were lost but I want to avoid wasting communication time for one or two bytes and I don't want to process too much on the micro-controller. So, it would be ideal if I could just fill in the blanks with placeholders because that way the picture would only be a few pixels off which is fine.


Solution

  • You could use JPEG restart markers but that would mean losing a row of MCU blocks or so when you get corruption, not just a few pixels (depending on how far apart you space them).

    You need to add a Define Restart Interval marker at the start of the file (before Start Of Scan) to specify the restart interval in macroblocks.

    DRI 0xFF, 0xDD 4 bytes Define Restart Interval Specifies the interval between RSTn markers, in macroblocks. This marker is followed by two bytes indicating the fixed size so it can be treated like any other variable size segment.

    Then in your stream, at an interval of however many macroblocks you specifed, you insert a 2-byte restart marker, using a counter that cycles between 0 and 7:

    RSTn 0xFF, 0xDn (n=0..7) none Restart Inserted every r macroblocks, where r is the restart interval set by a DRI marker. Not used if there was no DRI marker. The low 3 bits of the marker code cycle in value from 0 to 7.

    At a restart marker, block-to-block predictor variables are reset, and the bitstream is synchronized to a byte boundary. Restart markers provide means for recovery after bitstream error, such as transmission over an unreliable network or file corruption. Since the runs of macroblocks between restart markers may be independently decoded, these runs may be decoded in parallel.

    So, every time your decoder encounters an 0xFF byte followed by 0xDn (0-7) you can resync to a byte boundary. The 0xFF 0xDn sequence isn't allowed to appear in the normal compression stream (any 0xFF has to be followed by a zero padding byte, to avoid confusion).