in src/convert_image/sse2.rs [915:1016]
fn nv12_rgb<const COLORIMETRY: usize, const DEPTH: usize, const REVERSED: bool>(
width: u32,
height: u32,
last_src_plane: usize,
src_strides: &[usize],
src_buffers: &[&[u8]],
_last_dst_plane: usize,
dst_strides: &[usize],
dst_buffers: &mut [&mut [u8]],
) -> bool {
// Degenerate case, trivially accept
if width == 0 || height == 0 {
return true;
}
// Check there are sufficient strides and buffers
if last_src_plane >= src_strides.len()
|| last_src_plane >= src_buffers.len()
|| dst_strides.is_empty()
|| dst_buffers.is_empty()
{
return false;
}
// Check subsampling limits
let w = width as usize;
let h = height as usize;
let ch = h / 2;
let rgb_stride = DEPTH * w;
// Compute actual strides
let src_strides = (
compute_stride(src_strides[0], w),
compute_stride(src_strides[last_src_plane], w),
);
let dst_stride = compute_stride(dst_strides[0], rgb_stride);
// Ensure there is sufficient data in the buffers according
// to the image dimensions and computed strides
let mut src_buffers = (src_buffers[0], src_buffers[last_src_plane]);
if last_src_plane == 0 {
if src_buffers.0.len() < src_strides.0 * h {
return false;
}
src_buffers = src_buffers.0.split_at(src_strides.0 * h);
}
let dst_buffer = &mut *dst_buffers[0];
if out_of_bounds(src_buffers.0.len(), src_strides.0, h - 1, w)
|| out_of_bounds(src_buffers.1.len(), src_strides.1, ch - 1, w)
|| out_of_bounds(dst_buffer.len(), dst_stride, h - 1, rgb_stride)
{
return false;
}
if DEPTH == 3 {
// Needed _mm_shuffle_epi8 is from SSSE3, fallback to scalar path
x86::nv12_to_rgb::<COLORIMETRY>(
w,
h,
src_strides,
(src_buffers.0, src_buffers.1),
dst_stride,
dst_buffer,
);
return true;
}
// Process vector part and scalar one
let vector_part = lower_multiple_of_pot(w, YUV_TO_RGB_WAVES);
let scalar_part = w - vector_part;
if vector_part > 0 {
unsafe {
nv12_to_bgra_sse2::<COLORIMETRY, REVERSED>(
vector_part,
h,
src_strides,
src_buffers,
dst_stride,
dst_buffer,
);
}
}
if scalar_part > 0 {
let x = vector_part;
let dx = x * DEPTH;
x86::nv12_to_bgra::<COLORIMETRY, REVERSED>(
scalar_part,
h,
src_strides,
(&src_buffers.0[x..], &src_buffers.1[x..]),
dst_stride,
&mut dst_buffer[dx..],
);
}
true
}