New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Access out of boundary #3161

Open
rzwm opened this Issue Jul 28, 2018 · 0 comments

Comments

Projects
None yet
1 participant
@rzwm

rzwm commented Jul 28, 2018

I am writing a function to convert a yuv(I420) image to a BGR image. But there always has an "access out of boundary" error.
The error information is like this:
Error: Input buffer yuv is accessed at -8, which is before the min (0) in dimension 0
and the code is like this:

Func every_V_offset{"every_V_offset"}; // every V's offset
every_V_offset(x, y) = V_offset + (y / 2) * (yuv.width() / 2) + x / 2;

V_x(x, y) = every_V_offset(x, y) - yuv.width() * (every_V_offset(x, y) / yuv.width());

In theory, x - (x / w) * w should never be negative, but it occurs!
I find the reason for all day, but still confused.
I don't know whether it is my fault, or it is Halide's bug.
Below is the full code:

class I420_to_BGR : public Generator<I420_to_BGR>
{
public:
	Input<Buffer<uint8_t>> yuv{ "yuv", 2 };
	Output<Buffer<uint8_t>> bgr{ "bgr", 3 };

	Var x{ "x" }, y{ "y" }, c{ "c" };

	void generate()
	{
		// I420 format:
		// Y Y Y Y
		// Y Y Y Y
		// Y Y Y Y
		// Y Y Y Y
		// Y Y Y Y
		// Y Y Y Y
		// U U U U
		// U U V V
		// V V V V
		Expr Y_height = yuv.height() * 2 / 3; // Y channel's height
		Expr U_offset = Y_height * yuv.width(); // U channel's offset
		Expr V_offset = Y_height * yuv.width() * 5 / 4; // V channel's offset

		Func U_y{"U_y"}; // every U's y coordinate
		Func U_x{"U_x"}; // every U's x coordinate
		Func V_y{"V_y"}; // every V's y coordinate
		Func V_x{"V_x"}; // every V's x coordinate

		U_y(x, y) = (U_offset + (y / 2) * (yuv.width() / 2) + x / 2) / yuv.width(); // every U's offset / width -> y
		U_x(x, y) = (U_offset + (y / 2) * (yuv.width() / 2) + x / 2) % yuv.width(); // every U's offset % width -> x

		V_y(x, y) = (V_offset + (y / 2) * (yuv.width() / 2) + x / 2) / yuv.width(); // every V's offset / width ->y
		//v_x(x, y) = (v_offset + (y / 2) * (yuv.width() / 2) + x / 2) % yuv.width(); // every V's offset % width -> x(if using this, there is no error)

		////////////////////////////////////////////////////////////////////////
		////////////////////////////////////////////////////////////////////////
		////////////////////////////Error region////////////////////////////////

		Func every_V_offset{"every_V_offset"}; // every V's offset
		every_V_offset(x, y) = V_offset + (y / 2) * (yuv.width() / 2) + x / 2;

		//V_x(x, y) = every_V_offset(x, y) % yuv.width(); // if using this, there is no error!!!!!!!!!!!!!!!!!!!!!!!
		V_x(x, y) = every_V_offset(x, y) - yuv.width() * (every_V_offset(x, y) / yuv.width()); // if using this, access out of boundary!!!!!!!!!!!!!!!!!!!!!!!

		////////////////////////////////////////////////////////////////////////
		////////////////////////////////////////////////////////////////////////

		Func get_u{"get_u"}; // get every U's value
		Func get_v{"get_v"}; // get every V's value

		get_u(x, y) = yuv(U_x(x, y), U_y(x, y));
		get_v(x, y) = yuv(V_x(x, y), V_y(x, y));

		Func temp_b{"temp_b"};
		Func temp_g{"temp_g"};
		Func temp_r{"temp_r"};
		temp_b(x, y) = 1.8556f * (cast<int16_t>(get_u(x, y)) - 128);
 		temp_g(x, y) = -0.1873f * (cast<int16_t>(get_u(x, y)) - 128) - 0.4681f * (cast<int16_t>(get_v(x, y)) - 128);
 		temp_r(x, y) = 1.5748f * (cast<int16_t>(get_v(x, y)) - 128);
 
		Func temp_bgr{"temp_bgr"};
 		temp_bgr(x, y, c) = 0.0f;
 		temp_bgr(x, y, 0) = temp_b(x, y);
 		temp_bgr(x, y, 1) = temp_g(x, y);
 		temp_bgr(x, y, 2) = temp_r(x, y);
 
 		bgr(x, y, c) = cast<uint8_t>(clamp(yuv(x, y) + temp_bgr(x, y, c), 0, 255));

		bgr.dim(0).set_stride(3).dim(2).set_stride(1).set_bounds(0, 3);
		bgr.reorder(c, x, y).bound(c, 0, 3).unroll(c);
	}
};

HALIDE_REGISTER_GENERATOR(I420_to_BGR, halide_I420_to_BGR);

Using this to test:

int main()
{
	const int width = 8;
	const int height = 8;

	Runtime::Buffer<uint8_t> yuv(width, height * 3 / 2);
	Runtime::Buffer<uint8_t> bgr = Runtime::Buffer<uint8_t>::make_interleaved(width, height, 3);
	halide_I420_to_BGR(yuv, bgr);

	return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment