Repository navigation
cam_hal: PSRAM JPEG: fall back to full-frame EOI search when the tail probe misses - #871
Open
JohannYellow wants to merge 1 commit into
Open
JohannYellow wants to merge 1 commit into
JohannYellow wants to merge 1 commit into
Conversation
esp_camera_fb_get() discarded every frame with "NO-EOI - JPEG end marker missing" and timed out. The JPEGs were valid all along - the driver was looking in the wrong place. In PSRAM mode cam_take() only scans the last (dma_node_buffer_size + 1) = 1025 bytes of the frame for the EOI marker. The OV3660 pads each frame with zeros well past the end marker - measured 2218-2903 bytes on an ESP32-S3 at SVGA/JPEG - so the marker consistently fell outside that window and every frame was discarded. The OV2640 does not pad, which is why it was unaffected. Instrumenting the NO-EOI path showed the marker present every time: len=19456 fb_size=96000 full_eoi_off=17201 tail=00 00 00 00 00 00 00 00 len=18432 fb_size=96000 full_eoi_off=16214 tail=00 00 00 00 00 00 00 00 (~17 kB JPEGs in a 96000-byte buffer, so truncation was never involved.) When the narrow tail probe misses, re-scan the whole frame with the same backward search the non-PSRAM path already uses. The fast path is unchanged for sensors that do not pad. Safe against the stale-frame case the probe window guards against: len = cnt * dma_half_buffer_size, so all of [0, len) was written by this frame's DMA - stale bytes only live beyond len. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
3 tasks done
Contributor
|
Test with OV5640 / ESP32S3, confirm it works after applying this fix. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #853. Likely also the unresolved reports in #775.
What this does
In PSRAM DMA mode (
CONFIG_CAMERA_PSRAM_DMA=y) withPIXFORMAT_JPEG,cam_take()only searches the tail of the frame for the JPEG EOI marker: a window ofdma_node_buffer_size + 1bytes (1025 by default), introduced in #777 / #785 to avoid slow PSRAM reads and stale markers from a larger previous frame.Some sensors pad the frame with zeros past the EOI. The OV3660 appends ~2.2–2.9 kB, so
FF D9consistently lands outside the window,offset_estays-1, and every frame is dropped:This PR keeps the fast tail probe unchanged and, only when it misses, re-scans the whole frame with the same backward search the non-PSRAM path already uses:
The change is strictly additive: sensors that end the frame at the EOI (e.g. OV2640) never reach the fallback, and the fallback only runs on frames that would otherwise have been discarded.
Why it is safe against stale markers
The tail probe exists partly to avoid picking up an EOI left behind by a larger previous frame. That cannot happen here: in this path
len = cnt * dma_half_buffer_size, so all of[0, len)was written by this frame's DMA. Stale bytes only live beyondlen. A backward search over[0, len)therefore returns the last marker before the padding, which is this frame's real EOI.Measured
ESP32-S3, 8 MB octal PSRAM, OV3660, SVGA/JPEG q12,
fb_count=2, ESP-IDF 5.4.2. Instrumenting the NO-EOI path with a full-buffer search found the marker on every dropped frame:There is no truncation: the JPEGs are ~17 kB in a 96 kB buffer, the tail is all zeros, and no
DMA overflow/NO-SOIwarning is ever logged. The failure reproduced the same way on v2.1.4 and v2.1.7, and at both 10 and 20 MHz XCLK. Swapping in an OV2640 with everything else unchanged works.This also explains the light dependency reported in #775:
eoi_probe_window()returns the fullframe_lenwhen the frame is ≤ 1025 bytes, so a near-black frame small enough to fit gets a full scan and succeeds, while larger frames get the narrow window.Tested
master(after s3: drop frames the PSRAM DMA path did not write completely #868, which only touches the non-JPEG PSRAM path); applies cleanly.Limits
eoi_first=-1 eoi_last=-1across the whole buffer, which is that other failure mode.Unrelated observation (not changed here)
eoi_probe_window()names its first parameterhalf, and #785's title talks about the last half-buffer, but the call site passescam_obj->dma_node_buffer_size. Whendma_half_buffer_size > dma_node_buffer_sizethe window is smaller than intended. Both are 1024 in my configuration, so it is not the cause here.🤖 Generated with Claude Code