@@ -335,11 +335,14 @@ void CameraFeedAndroid::onImage(void *context, AImageReader *p_reader) {
335335 data_y.resize (y_size);
336336 memcpy (data_y.ptrw (), data, y_size);
337337 } else {
338- // ColorOS stride alignment present - use in-place processing
339- data_y.resize (len);
340- memcpy (data_y.ptrw (), data, len);
341- compact_stride_inplace (data_y.ptrw (), width, height, y_row_stride);
338+ // Stride alignment present - use scratch buffer to avoid realloc
339+ if (feed->scratch_y .size () < len) {
340+ feed->scratch_y .resize (len);
341+ }
342+ memcpy (feed->scratch_y .ptrw (), data, len);
343+ CameraFeedAndroid::compact_stride_inplace (feed->scratch_y .ptrw (), width, height, y_row_stride);
342344 data_y.resize (y_size);
345+ memcpy (data_y.ptrw (), feed->scratch_y .ptr (), y_size);
343346 }
344347
345348 // Handle UV plane
@@ -374,13 +377,16 @@ void CameraFeedAndroid::onImage(void *context, AImageReader *p_reader) {
374377 data_uv.resize (uv_size);
375378 memcpy (data_uv.ptrw (), data, uv_size);
376379 } else if (pixel_stride == 2 ) {
377- // Semiplanar format with ColorOS stride alignment
378- data_uv.resize (len);
379- memcpy (data_uv.ptrw (), data, len);
380+ // Semiplanar format with stride alignment - use scratch buffer
381+ if (feed->scratch_uv .size () < len) {
382+ feed->scratch_uv .resize (len);
383+ }
384+ memcpy (feed->scratch_uv .ptrw (), data, len);
380385 if (row_stride != uv_width * 2 ) {
381- compact_stride_inplace (data_uv .ptrw (), uv_width * 2 , uv_height, row_stride);
386+ CameraFeedAndroid:: compact_stride_inplace (feed-> scratch_uv .ptrw (), uv_width * 2 , uv_height, row_stride);
382387 }
383388 data_uv.resize (uv_size);
389+ memcpy (data_uv.ptrw (), feed->scratch_uv .ptr (), uv_size);
384390 } else {
385391 // Planar format - interleave U and V safely (no overlap)
386392 if (data_v && len_v > 0 ) {
0 commit comments