-
Notifications
You must be signed in to change notification settings - Fork 660
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Bad jpeg format returned from esp_camera_fb_get() #162
Comments
It turns out that these jpegs are not bad, but have junk appended at the end after the FFD9 end-of-image code. Whenever the FFD9 is the last, or last but 1 byte of a 16 byte block, then there will be a bunch of data after the FFD9. It must be some unused memory allocation (giving those round numbers 10400 ,14400, ...) that is sent along with the image rather than specifying exactly where the image ends. If the FFD9 ends the group of 16, then there will be 96, 144, 160 more bytes ... a multiple of 16. I cannot seem to find a length of the start-of-scan to end-of-image, so I guess the jpeg reader just takes all data available after the start-of-scan, and processes it, and when the data runs out before the end-of-image arrives, then you get the strange pictures. But that would mean you would have to scan the jpeg from the back looking for the end-of-image code to confirm that it is there, and the image isn't corrupted or truncated. Or maybe just scan back 512 bytes or so. It will be at the very end 95% ish of the time, and you could spend the cpu time to scan back 500 or 1000 bytes rather than discard the image and get a fresh one. |
you are all correct :) the code does go backwards to find the end of the image. It actually scans for FFD9 and zero after it. |
Interesting ... I wonder why it checks for the two 00 bytes after the FF D9. In my examples where there is more data after the FFD9, they do not have two 00 bytes -- which must break that test to find the end of image, and it just gives the length of entire buffer. I'll have to look backwards at the code that generates that. I re-did my example to look for these truncated frames, and searched backwards for the FFD9 by 1025 bytes to see if I could find the end-of-image. Using vga and quality 10 pointing at a bland ceiling, the camera gives about 5% frames with extra bytes after the FFD9, but no truncated frames - missing the FFD9. I'll have to take it outside to the bright sun, where I can usually find these problems. But there is quite a bit of extra data tagging along if you save/transmit the entire jpeg including the bytes after the FFD9. This is what I got with my bland ceiling for vga quality 10 (running at 10 frames per second) 19:13:04.252 -> Len = 11200, Extra Bytes = 384 I think those extra-byte calculations are correct, but they do not match my rule of 16. |
I think the check for those latter two zero bytes can be dropped. I think the FFD9 will not appear in the data. This misses the end of image if it comes at the 15th or 16th byte on a 16 byte block. When it is at the 15th, there is one zero, and at the 16th, there is no zero. Still haven't located my nemesis - the truncated image.
|
This is the code I ended up using. It searches for the FFD9 for 1025 bytes from the end of frame -- if there is no FFD9 it discards the frame, and if there is an FFD9, it justs uses the frame along with the extra bytes. You could trim the extra bytes, but that is a nuisance in my frame queuing system.
|
Hi, I have a program that makes a mjeg avi on an ESP32-CAM board, and I have been trying to resolve the issue of too much data for the jpeg, which happens if you have a high quality setting like 6 or 8 and then you expose it to bright sun, and you only get 3/4 of the image. My solution was to configure the camera quality with a high number (like 6) then switch to a lower quality (like 10 or 12) when I am recording. I think the initial config allocates buffers, then the lower quality photo does not exceed those buffers. This works okay, but whenever a single jpeg exceeded its allowable size, it ruined an entire .avi with 36,000 pictures or more as the avi player on the computer cannot understand the format, and will try to rebuild the index, ...
So I wrote this bit of code to select only good jpegs:
The code checks that the final two bytes of the jpeg are 0xFF, 0xD9 which is the end-of-image code, then prints out the frame length and the final two bytes.
What I discovered is that about 5% of images do not have the end-of-image code at the end of image. This recording is a vga or svga video of my ceiling in a medium dark room at quality 10 or 12, so it not full of light and bright colors, just ceiling tiles. In some cases there is a D9 one byte off, other cases there are random data. But the size of the frames are usually the same.
I am surprised that this many jpegs are wrong, as I have only seem rare problems with bright sunlight when using too high a quality (high quality = low number). The jpeg and avi viewer software usually handles these problems without complaining, ... until a real problem occurs and 1/4 of the frame is gone, etc.
So my questions is: Anybody know that jpeg creation code, and if there are problems with it?
In these 3 examples, the camera is initially configured for the following, then framesize and quality adjusted to record a particular video.
svga, quality 8
svga, quality 12
vga, quality 10
The text was updated successfully, but these errors were encountered: