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.
-
1It might be worth implementing [forward error correction](https://en.wikipedia.org/wiki/Forward_error_correction). It requires that you send a little extra data than you normally would, but you can recover from errors (so long as there isn't too much data loss). – Cornstalks Jun 26 '15 at 05:52
-
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) – samgak Jun 26 '15 at 05:59
-
JPEG is not that simple, it is a compressed format. Not knowing how many bytes are lost, the decoder can't find the correct position for the next restart marker, so in essence the file appears corrupted. – SteveFerg Jun 26 '15 at 06:00
-
1@SteveFerg the decoder just scans for the next 0xFF followed by 0xDn. The 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). Recovering from transmission/corruption errors is the whole reason restart markers are part of the format. – samgak Jun 26 '15 at 06:06
-
FEC looks really cool but I can't afford to send duplicate bits, it already takes an ungodly amount of time to send a whole image. I'll look in to restart markers. – Grimmer Jun 26 '15 at 06:17
1 Answers
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).
-
I think I understand. I check the intervals between the restart markers to make sure if there is corruption to get rid of that block and to rejoin the image. But what is the significance of cycling the n if all I need is the marker? Anyways this has been helpful. – Grimmer Jun 30 '15 at 00:22
-
1The significance of cycling the n is that it helps identify how much corruption has occurred. Suppose that the corruption ended up corrupting one of the restart markers. When you read the next one, the count will be one ahead of what you were expecting, so you know the previous one was corrupted. Because the restart markers are at regular intervals (in terms of MCU blocks) you know where to restart decoding from – samgak Jun 30 '15 at 00:57