Skip to content

Commit 7c9ce2b

Browse files
committed
fix convert odd height cvpixelbuffer to bgra crash
1 parent e4424cc commit 7c9ce2b

File tree

1 file changed

+219
-0
lines changed

1 file changed

+219
-0
lines changed
Lines changed: 219 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,219 @@
1+
From c253f0b58f86597d7e020076454fbf8c63847f8d Mon Sep 17 00:00:00 2001
2+
From: qianlongxu <[email protected]>
3+
Date: Fri, 5 Dec 2025 16:07:06 +0800
4+
Subject: [PATCH] fix convert odd height cvpixelbuffer to bgra crash
5+
6+
---
7+
include/libyuv/convert_argb.h | 44 +++++++++++
8+
source/convert_argb.cc | 140 ++++++++++++++++++++++++++++++++++
9+
2 files changed, 184 insertions(+)
10+
11+
diff --git a/include/libyuv/convert_argb.h b/include/libyuv/convert_argb.h
12+
index 5b50567..2bcfda8 100644
13+
--- a/include/libyuv/convert_argb.h
14+
+++ b/include/libyuv/convert_argb.h
15+
@@ -1856,6 +1856,50 @@ int NV12ToARGBMatrix(const uint8_t* src_y,
16+
int width,
17+
int height);
18+
19+
+ /*
20+
+Convert NV12 to ARGB with matrix safely
21+
+itu_matrix 1: BT.709
22+
+ 2: BT.601
23+
+ 3: BT.2020
24+
+full_range 0: limited range
25+
+ 1: full range
26+
+*/
27+
+
28+
+LIBYUV_API
29+
+int NV12ToARGBMatrixRangeSafely(const uint8_t* src_y,
30+
+ int src_stride_y,
31+
+ const uint8_t* src_uv,
32+
+ int src_stride_uv,
33+
+ uint8_t* dst_argb,
34+
+ int dst_stride_argb,
35+
+ int width,
36+
+ int height,
37+
+ int uv_height,
38+
+ int itu_matrix,
39+
+ int full_range);
40+
+
41+
+
42+
+ /*
43+
+convert nv12 to argb with matrix,uv height safely
44+
+because cvpixelbuffer uv height is y_height/2
45+
+libyuv need uv height is y_height/2 + 1
46+
+for example:
47+
+y height is 615
48+
+uv height is 307
49+
+libyuv need uv height is 308
50+
+*/
51+
+LIBYUV_API
52+
+int NV12ToARGBMatrixSafely(const uint8_t* src_y,
53+
+ int src_stride_y,
54+
+ const uint8_t* src_uv,
55+
+ int src_stride_uv,
56+
+ uint8_t* dst_argb,
57+
+ int dst_stride_argb,
58+
+ const struct YuvConstants* yuvconstants,
59+
+ int width,
60+
+ int height,
61+
+ int uv_height);
62+
+
63+
// Convert NV21 to ARGB with matrix.
64+
LIBYUV_API
65+
int NV21ToARGBMatrix(const uint8_t* src_y,
66+
diff --git a/source/convert_argb.cc b/source/convert_argb.cc
67+
index 3655e30..eaff1e9 100644
68+
--- a/source/convert_argb.cc
69+
+++ b/source/convert_argb.cc
70+
@@ -4060,6 +4060,146 @@ int NV12ToARGBMatrix(const uint8_t* src_y,
71+
return 0;
72+
}
73+
74+
+/*
75+
+convert nv12 to argb with matrix,uv height safe
76+
+because cvpixelbuffer uv height is y_height/2
77+
+libyuv need uv height is y_height/2 + 1
78+
+for example:
79+
+y height is 615
80+
+uv height is 307
81+
+libyuv need uv height is 308
82+
+*/
83+
+LIBYUV_API
84+
+int NV12ToARGBMatrixSafely(const uint8_t* src_y,
85+
+ int src_stride_y,
86+
+ const uint8_t* src_uv,
87+
+ int src_stride_uv,
88+
+ uint8_t* dst_argb,
89+
+ int dst_stride_argb,
90+
+ const struct YuvConstants* yuvconstants,
91+
+ int width,
92+
+ int height,
93+
+ int uv_height) {
94+
+ int y;
95+
+ void (*NV12ToARGBRow)(
96+
+ const uint8_t* y_buf, const uint8_t* uv_buf, uint8_t* rgb_buf,
97+
+ const struct YuvConstants* yuvconstants, int width) = NV12ToARGBRow_C;
98+
+ assert(yuvconstants);
99+
+ if (!src_y || !src_uv || !dst_argb || width <= 0 || height == 0) {
100+
+ return -1;
101+
+ }
102+
+ // Negative height means invert the image.
103+
+ if (height < 0) {
104+
+ height = -height;
105+
+ dst_argb = dst_argb + (height - 1) * dst_stride_argb;
106+
+ dst_stride_argb = -dst_stride_argb;
107+
+ }
108+
+#if defined(HAS_NV12TOARGBROW_SSSE3)
109+
+ if (TestCpuFlag(kCpuHasSSSE3)) {
110+
+ NV12ToARGBRow = NV12ToARGBRow_Any_SSSE3;
111+
+ if (IS_ALIGNED(width, 8)) {
112+
+ NV12ToARGBRow = NV12ToARGBRow_SSSE3;
113+
+ }
114+
+ }
115+
+#endif
116+
+#if defined(HAS_NV12TOARGBROW_AVX2)
117+
+ if (TestCpuFlag(kCpuHasAVX2)) {
118+
+ NV12ToARGBRow = NV12ToARGBRow_Any_AVX2;
119+
+ if (IS_ALIGNED(width, 16)) {
120+
+ NV12ToARGBRow = NV12ToARGBRow_AVX2;
121+
+ }
122+
+ }
123+
+#endif
124+
+#if defined(HAS_NV12TOARGBROW_NEON)
125+
+ if (TestCpuFlag(kCpuHasNEON)) {
126+
+ NV12ToARGBRow = NV12ToARGBRow_Any_NEON;
127+
+ if (IS_ALIGNED(width, 8)) {
128+
+ NV12ToARGBRow = NV12ToARGBRow_NEON;
129+
+ }
130+
+ }
131+
+#endif
132+
+#if defined(HAS_NV12TOARGBROW_MSA)
133+
+ if (TestCpuFlag(kCpuHasMSA)) {
134+
+ NV12ToARGBRow = NV12ToARGBRow_Any_MSA;
135+
+ if (IS_ALIGNED(width, 8)) {
136+
+ NV12ToARGBRow = NV12ToARGBRow_MSA;
137+
+ }
138+
+ }
139+
+#endif
140+
+#if defined(HAS_NV12TOARGBROW_LSX)
141+
+ if (TestCpuFlag(kCpuHasLSX)) {
142+
+ NV12ToARGBRow = NV12ToARGBRow_Any_LSX;
143+
+ if (IS_ALIGNED(width, 8)) {
144+
+ NV12ToARGBRow = NV12ToARGBRow_LSX;
145+
+ }
146+
+ }
147+
+#endif
148+
+#if defined(HAS_NV12TOARGBROW_LASX)
149+
+ if (TestCpuFlag(kCpuHasLASX)) {
150+
+ NV12ToARGBRow = NV12ToARGBRow_Any_LASX;
151+
+ if (IS_ALIGNED(width, 16)) {
152+
+ NV12ToARGBRow = NV12ToARGBRow_LASX;
153+
+ }
154+
+ }
155+
+#endif
156+
+#if defined(HAS_NV12TOARGBROW_RVV)
157+
+ if (TestCpuFlag(kCpuHasRVV)) {
158+
+ NV12ToARGBRow = NV12ToARGBRow_RVV;
159+
+ }
160+
+#endif
161+
+
162+
+ //because src_uv will add src_stride_uv,so after added src_uv should not exceed uv_height
163+
+ uv_height--;
164+
+
165+
+ for (y = 0; y < height; ++y) {
166+
+ NV12ToARGBRow(src_y, src_uv, dst_argb, yuvconstants, width);
167+
+ dst_argb += dst_stride_argb;
168+
+ src_y += src_stride_y;
169+
+ //cvpixelbuffer may have different uv height: height >> 1 - 1
170+
+ if (y & 1 && (y >> 1) < uv_height) {
171+
+ src_uv += src_stride_uv;
172+
+ }
173+
+ }
174+
+ return 0;
175+
+}
176+
+
177+
+/*
178+
+Convert NV12 to ARGB with matrix.
179+
+itu_matrix 1: BT.709
180+
+ 2: BT.601
181+
+ 3: BT.2020
182+
+full_range 0: limited range
183+
+ 1: full range
184+
+*/
185+
+
186+
+LIBYUV_API
187+
+int NV12ToARGBMatrixRangeSafely(const uint8_t* src_y,
188+
+ int src_stride_y,
189+
+ const uint8_t* src_uv,
190+
+ int src_stride_uv,
191+
+ uint8_t* dst_argb,
192+
+ int dst_stride_argb,
193+
+ int width,
194+
+ int height,
195+
+ int uv_height,
196+
+ int itu_matrix,
197+
+ int full_range)
198+
+ {
199+
+const struct YuvConstants* yuvconstants;
200+
+
201+
+ if (itu_matrix == 2) {
202+
+ yuvconstants = full_range ? &kYuvJPEGConstants : &kYuvI601Constants;
203+
+ } else if (itu_matrix == 3) {
204+
+ yuvconstants = full_range ? &kYuvV2020Constants : &kYuv2020Constants;
205+
+ } else {
206+
+ yuvconstants = full_range ? &kYuvF709Constants : &kYuvH709Constants;
207+
+ }
208+
+ return NV12ToARGBMatrixSafely(src_y, src_stride_y, src_uv, src_stride_uv,
209+
+ dst_argb, dst_stride_argb,
210+
+ yuvconstants,
211+
+ width, height,uv_height);
212+
+}
213+
+
214+
// Convert NV21 to ARGB with matrix.
215+
LIBYUV_API
216+
int NV21ToARGBMatrix(const uint8_t* src_y,
217+
--
218+
2.50.1 (Apple Git-155)
219+

0 commit comments

Comments
 (0)