Skip to content

Skip motion comparison when camera frame size changes - #475

Open
munzzyy wants to merge 1 commit into
guardianproject:masterfrom
munzzyy:fix-cameraviewholder-stale-frame-oob
Open

Skip motion comparison when camera frame size changes#475
munzzyy wants to merge 1 commit into
guardianproject:masterfrom
munzzyy:fix-cameraviewholder-stale-frame-oob

Conversation

@munzzyy

@munzzyy munzzyy commented Sep 3, 2026

Copy link
Copy Markdown

Fixes #468.

Traced the crash back past ImageCodec.N21toLuma() and MotionDetector.detect() to where the frames actually come from: CameraViewHolder.processNewFrame().

private void processNewFrame (byte[] data, Size size)
{
    if (data != null && size != null) {
        int width = size.getWidth();
        int height = size.getHeight();

        motionDetector.detect(
                lastPic,
                data,
                width,
                height);

        lastPic = data;
    }
}

lastPic is the previous frame's raw buffer, but it gets passed to detect() along with the current frame's width/height. Most of the time that's fine because the camera preview size doesn't change between frames. But if it does change (camera restart, resolution switch, etc.), lastPic is still sized for the old resolution while width/height describe the new one. N21toLuma() then indexes the old, smaller buffer using the new, larger width*height, and you get the exact crash from the issue.

Fix tracks the size lastPic was captured at and only hands it to detect() when it matches the current frame's size. When it doesn't match, this frame is treated the same as the very first frame (no previous frame to compare against yet), since there's nothing valid to diff against anyway.

I didn't just clamp the loop in N21toLuma() to the buffer length, since that would still compare frames of different resolutions pixel-by-pixel against garbage data and produce a bogus "motion detected" event. Skipping the comparison for that one frame is the correct behavior.

This repo has no Android instrumentation set up in my checkout, so I couldn't run it through the app itself. I copied the exact code path (N21toLuma, the same/different-size branching) into a plain Java file outside the project and ran it standalone: confirmed the fix prevents the crash on a resolution change and leaves the normal same-size case untouched.

processNewFrame() hands the previous frame's buffer (lastPic) to
MotionDetector.detect() along with the CURRENT frame's width/height.
If the camera's preview size changes between two frames, lastPic is
still sized for the old resolution, so ImageCodec.N21toLuma() ends up
indexing it with the new (larger) width*height and throws
ArrayIndexOutOfBoundsException.

Track the size lastPic was captured at and only pass it along for
comparison when it matches the current frame's size. Otherwise this
frame is treated the same way as the very first frame (no previous
frame to compare against), which is correct since there's nothing
usable to diff against anyway.

Fixes guardianproject#468
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Critical ArrayIndexOutOfBoundsException in Image Processing

1 participant