fn nv12_rgb()

in src/convert_image/avx2.rs [1460:1569]


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;
    }

    // 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 {
            if DEPTH == 4 {
                nv12_to_bgra_avx2::<COLORIMETRY, REVERSED>(
                    vector_part,
                    h,
                    src_strides,
                    src_buffers,
                    dst_stride,
                    dst_buffer,
                );
            } else {
                nv12_to_rgb_avx2::<COLORIMETRY>(
                    vector_part,
                    h,
                    src_strides,
                    src_buffers,
                    dst_stride,
                    dst_buffer,
                );
            }
        }
    }

    if scalar_part > 0 {
        let x = vector_part;
        let dx = x * DEPTH;

        if DEPTH == 4 {
            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..],
            );
        } else {
            x86::nv12_to_rgb::<COLORIMETRY>(
                scalar_part,
                h,
                src_strides,
                (&src_buffers.0[x..], &src_buffers.1[x..]),
                dst_stride,
                &mut dst_buffer[dx..],
            );
        }
    }

    true
}