I'm new to Neon. I want to write a code to convert YUV420 to RGB with Neon. The pixels are 8 bit depth, I need to convert them to int32_t or float (but still clamped to a 0-255 range). However, I haven't found any Neon instruction to do that. By the way, it seems that there is no instruction to do multiplication between different types like int16 and float. Do I have to do data type converting with C code to fit Neon's requirement?
Below is the algorithm to convert YUV to RGB, the params range is [0, 255], I do the converting outside with C code:
inline std::uint8_t clamp(std::int32_t n) {
n &= -(n >= 0);
return n | ((255 - n) >> 31);
}
inline void yuv2rgb_i32(std::int32_t y, std::int32_t u, std::int32_t v, std::int32_t &r, std::int32_t &g, std::int32_t &b) {
y -= 16;
u -= 128;
v -= 128;
r = clamp((std::int32_t)(1.164 * y + 1.596 * v));
g = clamp((std::int32_t)(1.164 * y - 0.392 * u - 0.813 * v));
b = clamp((std::int32_t)(1.164 * y + 2.017 * u));
}
Here is an example how to convert planar YUV (BT.601 full swing, as used in JPEG for example):
This is a stand-alone file that can be assembled by the GNU Assembler for aarch64. Once assembled into an object file, you can simply link it to the rest of your code. From within C you can simply reference the code by:
The code is maybe not the most optimal way to do it, but it is also not slow either. It expects the image dimensions to be even, so make sure to pad if that is not the case.