Coverage Report

Created: 2026-01-16 07:04

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libavif/ext/libyuv/source/convert_from_argb.cc
Line
Count
Source
1
/*
2
 *  Copyright 2012 The LibYuv Project Authors. All rights reserved.
3
 *
4
 *  Use of this source code is governed by a BSD-style license
5
 *  that can be found in the LICENSE file in the root of the source
6
 *  tree. An additional intellectual property rights grant can be found
7
 *  in the file PATENTS. All contributing project authors may
8
 *  be found in the AUTHORS file in the root of the source tree.
9
 */
10
11
#include "libyuv/convert_from_argb.h"
12
13
#include "libyuv/basic_types.h"
14
#include "libyuv/cpu_id.h"
15
#include "libyuv/planar_functions.h"
16
#include "libyuv/row.h"
17
18
#ifdef __cplusplus
19
namespace libyuv {
20
extern "C" {
21
#endif
22
23
// ARGB little endian (bgra in memory) to I444
24
LIBYUV_API
25
int ARGBToI444(const uint8_t* src_argb,
26
               int src_stride_argb,
27
               uint8_t* dst_y,
28
               int dst_stride_y,
29
               uint8_t* dst_u,
30
               int dst_stride_u,
31
               uint8_t* dst_v,
32
               int dst_stride_v,
33
               int width,
34
0
               int height) {
35
0
  int y;
36
0
  void (*ARGBToYRow)(const uint8_t* src_argb, uint8_t* dst_y, int width) =
37
0
      ARGBToYRow_C;
38
0
  void (*ARGBToUV444Row)(const uint8_t* src_argb, uint8_t* dst_u,
39
0
                         uint8_t* dst_v, int width) = ARGBToUV444Row_C;
40
0
  if (!src_argb || !dst_y || !dst_u || !dst_v || width <= 0 || height == 0) {
41
0
    return -1;
42
0
  }
43
0
  if (height < 0) {
44
0
    height = -height;
45
0
    src_argb = src_argb + (height - 1) * src_stride_argb;
46
0
    src_stride_argb = -src_stride_argb;
47
0
  }
48
  // Coalesce rows.
49
0
  if (src_stride_argb == width * 4 && dst_stride_y == width &&
50
0
      dst_stride_u == width && dst_stride_v == width) {
51
0
    width *= height;
52
0
    height = 1;
53
0
    src_stride_argb = dst_stride_y = dst_stride_u = dst_stride_v = 0;
54
0
  }
55
0
#if defined(HAS_ARGBTOUV444ROW_SSSE3)
56
0
  if (TestCpuFlag(kCpuHasSSSE3)) {
57
0
    ARGBToUV444Row = ARGBToUV444Row_Any_SSSE3;
58
0
    if (IS_ALIGNED(width, 16)) {
59
0
      ARGBToUV444Row = ARGBToUV444Row_SSSE3;
60
0
    }
61
0
  }
62
0
#endif
63
0
#if defined(HAS_ARGBTOUV444ROW_AVX2)
64
0
  if (TestCpuFlag(kCpuHasAVX2)) {
65
0
    ARGBToUV444Row = ARGBToUV444Row_Any_AVX2;
66
0
    if (IS_ALIGNED(width, 32)) {
67
0
      ARGBToUV444Row = ARGBToUV444Row_AVX2;
68
0
    }
69
0
  }
70
0
#endif
71
#if defined(HAS_ARGBTOUV444ROW_NEON)
72
  if (TestCpuFlag(kCpuHasNEON)) {
73
    ARGBToUV444Row = ARGBToUV444Row_Any_NEON;
74
    if (IS_ALIGNED(width, 8)) {
75
      ARGBToUV444Row = ARGBToUV444Row_NEON;
76
    }
77
  }
78
#endif
79
#if defined(HAS_ARGBTOUV444ROW_NEON_I8MM)
80
  if (TestCpuFlag(kCpuHasNeonI8MM)) {
81
    ARGBToUV444Row = ARGBToUV444Row_Any_NEON_I8MM;
82
    if (IS_ALIGNED(width, 8)) {
83
      ARGBToUV444Row = ARGBToUV444Row_NEON_I8MM;
84
    }
85
  }
86
#endif
87
#if defined(HAS_ARGBTOUV444ROW_LSX)
88
  if (TestCpuFlag(kCpuHasLSX)) {
89
    ARGBToUV444Row = ARGBToUV444Row_Any_LSX;
90
    if (IS_ALIGNED(width, 16)) {
91
      ARGBToUV444Row = ARGBToUV444Row_LSX;
92
    }
93
  }
94
#endif
95
#if defined(HAS_ARGBTOUV444ROW_LASX)
96
  if (TestCpuFlag(kCpuHasLASX)) {
97
    ARGBToUV444Row = ARGBToUV444Row_Any_LASX;
98
    if (IS_ALIGNED(width, 32)) {
99
      ARGBToUV444Row = ARGBToUV444Row_LASX;
100
    }
101
  }
102
#endif
103
0
#if defined(HAS_ARGBTOYROW_SSSE3)
104
0
  if (TestCpuFlag(kCpuHasSSSE3)) {
105
0
    ARGBToYRow = ARGBToYRow_Any_SSSE3;
106
0
    if (IS_ALIGNED(width, 16)) {
107
0
      ARGBToYRow = ARGBToYRow_SSSE3;
108
0
    }
109
0
  }
110
0
#endif
111
0
#if defined(HAS_ARGBTOYROW_AVX2)
112
0
  if (TestCpuFlag(kCpuHasAVX2)) {
113
0
    ARGBToYRow = ARGBToYRow_Any_AVX2;
114
0
    if (IS_ALIGNED(width, 32)) {
115
0
      ARGBToYRow = ARGBToYRow_AVX2;
116
0
    }
117
0
  }
118
0
#endif
119
#if defined(HAS_ARGBTOYROW_NEON)
120
  if (TestCpuFlag(kCpuHasNEON)) {
121
    ARGBToYRow = ARGBToYRow_Any_NEON;
122
    if (IS_ALIGNED(width, 16)) {
123
      ARGBToYRow = ARGBToYRow_NEON;
124
    }
125
  }
126
#endif
127
#if defined(HAS_ARGBTOYROW_NEON_DOTPROD)
128
  if (TestCpuFlag(kCpuHasNeonDotProd)) {
129
    ARGBToYRow = ARGBToYRow_Any_NEON_DotProd;
130
    if (IS_ALIGNED(width, 16)) {
131
      ARGBToYRow = ARGBToYRow_NEON_DotProd;
132
    }
133
  }
134
#endif
135
#if defined(HAS_ARGBTOYROW_LSX)
136
  if (TestCpuFlag(kCpuHasLSX)) {
137
    ARGBToYRow = ARGBToYRow_Any_LSX;
138
    if (IS_ALIGNED(width, 16)) {
139
      ARGBToYRow = ARGBToYRow_LSX;
140
    }
141
  }
142
#endif
143
#if defined(HAS_ARGBTOYROW_LASX)
144
  if (TestCpuFlag(kCpuHasLASX)) {
145
    ARGBToYRow = ARGBToYRow_Any_LASX;
146
    if (IS_ALIGNED(width, 32)) {
147
      ARGBToYRow = ARGBToYRow_LASX;
148
    }
149
  }
150
#endif
151
#if defined(HAS_ARGBTOYROW_RVV)
152
  if (TestCpuFlag(kCpuHasRVV)) {
153
    ARGBToYRow = ARGBToYRow_RVV;
154
  }
155
#endif
156
157
0
  for (y = 0; y < height; ++y) {
158
0
    ARGBToUV444Row(src_argb, dst_u, dst_v, width);
159
0
    ARGBToYRow(src_argb, dst_y, width);
160
0
    src_argb += src_stride_argb;
161
0
    dst_y += dst_stride_y;
162
0
    dst_u += dst_stride_u;
163
0
    dst_v += dst_stride_v;
164
0
  }
165
0
  return 0;
166
0
}
167
168
// ARGB little endian (bgra in memory) to I422
169
LIBYUV_API
170
int ARGBToI422(const uint8_t* src_argb,
171
               int src_stride_argb,
172
               uint8_t* dst_y,
173
               int dst_stride_y,
174
               uint8_t* dst_u,
175
               int dst_stride_u,
176
               uint8_t* dst_v,
177
               int dst_stride_v,
178
               int width,
179
0
               int height) {
180
0
  int y;
181
0
  void (*ARGBToUVRow)(const uint8_t* src_argb0, int src_stride_argb,
182
0
                      uint8_t* dst_u, uint8_t* dst_v, int width) =
183
0
      ARGBToUVRow_C;
184
0
  void (*ARGBToYRow)(const uint8_t* src_argb, uint8_t* dst_y, int width) =
185
0
      ARGBToYRow_C;
186
0
  if (!src_argb || !dst_y || !dst_u || !dst_v || width <= 0 || height == 0) {
187
0
    return -1;
188
0
  }
189
  // Negative height means invert the image.
190
0
  if (height < 0) {
191
0
    height = -height;
192
0
    src_argb = src_argb + (height - 1) * src_stride_argb;
193
0
    src_stride_argb = -src_stride_argb;
194
0
  }
195
  // Coalesce rows.
196
0
  if (src_stride_argb == width * 4 && dst_stride_y == width &&
197
0
      dst_stride_u * 2 == width && dst_stride_v * 2 == width) {
198
0
    width *= height;
199
0
    height = 1;
200
0
    src_stride_argb = dst_stride_y = dst_stride_u = dst_stride_v = 0;
201
0
  }
202
0
#if defined(HAS_ARGBTOYROW_SSSE3)
203
0
  if (TestCpuFlag(kCpuHasSSSE3)) {
204
0
    ARGBToYRow = ARGBToYRow_Any_SSSE3;
205
0
    if (IS_ALIGNED(width, 16)) {
206
0
      ARGBToYRow = ARGBToYRow_SSSE3;
207
0
    }
208
0
  }
209
0
#endif
210
0
#if defined(HAS_ARGBTOUVROW_SSSE3)
211
0
  if (TestCpuFlag(kCpuHasSSSE3)) {
212
0
    ARGBToUVRow = ARGBToUVRow_Any_SSSE3;
213
0
    if (IS_ALIGNED(width, 16)) {
214
0
      ARGBToUVRow = ARGBToUVRow_SSSE3;
215
0
    }
216
0
  }
217
0
#endif
218
0
#if defined(HAS_ARGBTOYROW_AVX2)
219
0
  if (TestCpuFlag(kCpuHasAVX2)) {
220
0
    ARGBToYRow = ARGBToYRow_Any_AVX2;
221
0
    if (IS_ALIGNED(width, 32)) {
222
0
      ARGBToYRow = ARGBToYRow_AVX2;
223
0
    }
224
0
  }
225
0
#endif
226
0
#if defined(HAS_ARGBTOUVROW_AVX2)
227
0
  if (TestCpuFlag(kCpuHasAVX2)) {
228
0
    ARGBToUVRow = ARGBToUVRow_Any_AVX2;
229
0
    if (IS_ALIGNED(width, 32)) {
230
0
      ARGBToUVRow = ARGBToUVRow_AVX2;
231
0
    }
232
0
  }
233
0
#endif
234
#if defined(HAS_ARGBTOYROW_NEON)
235
  if (TestCpuFlag(kCpuHasNEON)) {
236
    ARGBToYRow = ARGBToYRow_Any_NEON;
237
    if (IS_ALIGNED(width, 16)) {
238
      ARGBToYRow = ARGBToYRow_NEON;
239
    }
240
  }
241
#endif
242
#if defined(HAS_ARGBTOYROW_NEON_DOTPROD)
243
  if (TestCpuFlag(kCpuHasNeonDotProd)) {
244
    ARGBToYRow = ARGBToYRow_Any_NEON_DotProd;
245
    if (IS_ALIGNED(width, 16)) {
246
      ARGBToYRow = ARGBToYRow_NEON_DotProd;
247
    }
248
  }
249
#endif
250
#if defined(HAS_ARGBTOUVROW_NEON)
251
  if (TestCpuFlag(kCpuHasNEON)) {
252
    ARGBToUVRow = ARGBToUVRow_Any_NEON;
253
    if (IS_ALIGNED(width, 16)) {
254
      ARGBToUVRow = ARGBToUVRow_NEON;
255
    }
256
  }
257
#endif
258
#if defined(HAS_ARGBTOUVROW_NEON_I8MM)
259
  if (TestCpuFlag(kCpuHasNeonI8MM)) {
260
    ARGBToUVRow = ARGBToUVRow_Any_NEON_I8MM;
261
    if (IS_ALIGNED(width, 16)) {
262
      ARGBToUVRow = ARGBToUVRow_NEON_I8MM;
263
    }
264
  }
265
#endif
266
#if defined(HAS_ARGBTOUVROW_SVE2)
267
  if (TestCpuFlag(kCpuHasSVE2)) {
268
    ARGBToUVRow = ARGBToUVRow_Any_SVE2;
269
    if (IS_ALIGNED(width, 2)) {
270
      ARGBToUVRow = ARGBToUVRow_SVE2;
271
    }
272
  }
273
#endif
274
#if defined(HAS_ARGBTOUVROW_SME)
275
  if (TestCpuFlag(kCpuHasSME)) {
276
    ARGBToUVRow = ARGBToUVRow_Any_SME;
277
    if (IS_ALIGNED(width, 2)) {
278
      ARGBToUVRow = ARGBToUVRow_SME;
279
    }
280
  }
281
#endif
282
#if defined(HAS_ARGBTOYROW_LSX)
283
  if (TestCpuFlag(kCpuHasLSX)) {
284
    ARGBToYRow = ARGBToYRow_Any_LSX;
285
    if (IS_ALIGNED(width, 16)) {
286
      ARGBToYRow = ARGBToYRow_LSX;
287
    }
288
  }
289
#endif
290
#if defined(HAS_ARGBTOYROW_LSX) && defined(HAS_ARGBTOUVROW_LSX)
291
  if (TestCpuFlag(kCpuHasLSX)) {
292
    ARGBToYRow = ARGBToYRow_Any_LSX;
293
    ARGBToUVRow = ARGBToUVRow_Any_LSX;
294
    if (IS_ALIGNED(width, 16)) {
295
      ARGBToYRow = ARGBToYRow_LSX;
296
      ARGBToUVRow = ARGBToUVRow_LSX;
297
    }
298
  }
299
#endif
300
#if defined(HAS_ARGBTOYROW_LASX) && defined(HAS_ARGBTOUVROW_LASX)
301
  if (TestCpuFlag(kCpuHasLASX)) {
302
    ARGBToYRow = ARGBToYRow_Any_LASX;
303
    ARGBToUVRow = ARGBToUVRow_Any_LASX;
304
    if (IS_ALIGNED(width, 32)) {
305
      ARGBToYRow = ARGBToYRow_LASX;
306
      ARGBToUVRow = ARGBToUVRow_LASX;
307
    }
308
  }
309
#endif
310
#if defined(HAS_ARGBTOYROW_RVV)
311
  if (TestCpuFlag(kCpuHasRVV)) {
312
    ARGBToYRow = ARGBToYRow_RVV;
313
  }
314
#endif
315
316
0
  for (y = 0; y < height; ++y) {
317
0
    ARGBToUVRow(src_argb, 0, dst_u, dst_v, width);
318
0
    ARGBToYRow(src_argb, dst_y, width);
319
0
    src_argb += src_stride_argb;
320
0
    dst_y += dst_stride_y;
321
0
    dst_u += dst_stride_u;
322
0
    dst_v += dst_stride_v;
323
0
  }
324
0
  return 0;
325
0
}
326
327
LIBYUV_API
328
int ARGBToNV12(const uint8_t* src_argb,
329
               int src_stride_argb,
330
               uint8_t* dst_y,
331
               int dst_stride_y,
332
               uint8_t* dst_uv,
333
               int dst_stride_uv,
334
               int width,
335
0
               int height) {
336
0
  int y;
337
0
  int halfwidth = (width + 1) >> 1;
338
0
  void (*ARGBToUVRow)(const uint8_t* src_argb0, int src_stride_argb,
339
0
                      uint8_t* dst_u, uint8_t* dst_v, int width) =
340
0
      ARGBToUVRow_C;
341
0
  void (*ARGBToYRow)(const uint8_t* src_argb, uint8_t* dst_y, int width) =
342
0
      ARGBToYRow_C;
343
0
  void (*MergeUVRow_)(const uint8_t* src_u, const uint8_t* src_v,
344
0
                      uint8_t* dst_uv, int width) = MergeUVRow_C;
345
0
  if (!src_argb || !dst_y || !dst_uv || width <= 0 || height == 0) {
346
0
    return -1;
347
0
  }
348
  // Negative height means invert the image.
349
0
  if (height < 0) {
350
0
    height = -height;
351
0
    src_argb = src_argb + (height - 1) * src_stride_argb;
352
0
    src_stride_argb = -src_stride_argb;
353
0
  }
354
#if defined(HAS_ARGBTOYROW_NEON)
355
  if (TestCpuFlag(kCpuHasNEON)) {
356
    ARGBToYRow = ARGBToYRow_Any_NEON;
357
    if (IS_ALIGNED(width, 16)) {
358
      ARGBToYRow = ARGBToYRow_NEON;
359
    }
360
  }
361
#endif
362
#if defined(HAS_ARGBTOYROW_NEON_DOTPROD)
363
  if (TestCpuFlag(kCpuHasNeonDotProd)) {
364
    ARGBToYRow = ARGBToYRow_Any_NEON_DotProd;
365
    if (IS_ALIGNED(width, 16)) {
366
      ARGBToYRow = ARGBToYRow_NEON_DotProd;
367
    }
368
  }
369
#endif
370
#if defined(HAS_ARGBTOUVROW_NEON)
371
  if (TestCpuFlag(kCpuHasNEON)) {
372
    ARGBToUVRow = ARGBToUVRow_Any_NEON;
373
    if (IS_ALIGNED(width, 16)) {
374
      ARGBToUVRow = ARGBToUVRow_NEON;
375
    }
376
  }
377
#endif
378
#if defined(HAS_ARGBTOUVROW_NEON_I8MM)
379
  if (TestCpuFlag(kCpuHasNeonI8MM)) {
380
    ARGBToUVRow = ARGBToUVRow_Any_NEON_I8MM;
381
    if (IS_ALIGNED(width, 16)) {
382
      ARGBToUVRow = ARGBToUVRow_NEON_I8MM;
383
    }
384
  }
385
#endif
386
#if defined(HAS_ARGBTOUVROW_SVE2)
387
  if (TestCpuFlag(kCpuHasSVE2)) {
388
    ARGBToUVRow = ARGBToUVRow_Any_SVE2;
389
    if (IS_ALIGNED(width, 2)) {
390
      ARGBToUVRow = ARGBToUVRow_SVE2;
391
    }
392
  }
393
#endif
394
#if defined(HAS_ARGBTOUVROW_SME)
395
  if (TestCpuFlag(kCpuHasSME)) {
396
    ARGBToUVRow = ARGBToUVRow_Any_SME;
397
    if (IS_ALIGNED(width, 2)) {
398
      ARGBToUVRow = ARGBToUVRow_SME;
399
    }
400
  }
401
#endif
402
0
#if defined(HAS_ARGBTOYROW_SSSE3)
403
0
  if (TestCpuFlag(kCpuHasSSSE3)) {
404
0
    ARGBToYRow = ARGBToYRow_Any_SSSE3;
405
0
    if (IS_ALIGNED(width, 16)) {
406
0
      ARGBToYRow = ARGBToYRow_SSSE3;
407
0
    }
408
0
  }
409
0
#endif
410
0
#if defined(HAS_ARGBTOUVROW_SSSE3)
411
0
  if (TestCpuFlag(kCpuHasSSSE3)) {
412
0
    ARGBToUVRow = ARGBToUVRow_Any_SSSE3;
413
0
    if (IS_ALIGNED(width, 16)) {
414
0
      ARGBToUVRow = ARGBToUVRow_SSSE3;
415
0
    }
416
0
  }
417
0
#endif
418
0
#if defined(HAS_ARGBTOYROW_AVX2)
419
0
  if (TestCpuFlag(kCpuHasAVX2)) {
420
0
    ARGBToYRow = ARGBToYRow_Any_AVX2;
421
0
    if (IS_ALIGNED(width, 32)) {
422
0
      ARGBToYRow = ARGBToYRow_AVX2;
423
0
    }
424
0
  }
425
0
#endif
426
0
#if defined(HAS_ARGBTOUVROW_AVX2)
427
0
  if (TestCpuFlag(kCpuHasAVX2)) {
428
0
    ARGBToUVRow = ARGBToUVRow_Any_AVX2;
429
0
    if (IS_ALIGNED(width, 32)) {
430
0
      ARGBToUVRow = ARGBToUVRow_AVX2;
431
0
    }
432
0
  }
433
0
#endif
434
#if defined(HAS_ARGBTOYROW_LSX)
435
  if (TestCpuFlag(kCpuHasLSX)) {
436
    ARGBToYRow = ARGBToYRow_Any_LSX;
437
    if (IS_ALIGNED(width, 16)) {
438
      ARGBToYRow = ARGBToYRow_LSX;
439
    }
440
  }
441
#endif
442
#if defined(HAS_ARGBTOYROW_LASX) && defined(HAS_ARGBTOUVROW_LASX)
443
  if (TestCpuFlag(kCpuHasLASX)) {
444
    ARGBToYRow = ARGBToYRow_Any_LASX;
445
    ARGBToUVRow = ARGBToUVRow_Any_LASX;
446
    if (IS_ALIGNED(width, 32)) {
447
      ARGBToYRow = ARGBToYRow_LASX;
448
      ARGBToUVRow = ARGBToUVRow_LASX;
449
    }
450
  }
451
#endif
452
#if defined(HAS_ARGBTOYROW_RVV)
453
  if (TestCpuFlag(kCpuHasRVV)) {
454
    ARGBToYRow = ARGBToYRow_RVV;
455
  }
456
#endif
457
0
#if defined(HAS_MERGEUVROW_SSE2)
458
0
  if (TestCpuFlag(kCpuHasSSE2)) {
459
0
    MergeUVRow_ = MergeUVRow_Any_SSE2;
460
0
    if (IS_ALIGNED(halfwidth, 16)) {
461
0
      MergeUVRow_ = MergeUVRow_SSE2;
462
0
    }
463
0
  }
464
0
#endif
465
0
#if defined(HAS_MERGEUVROW_AVX2)
466
0
  if (TestCpuFlag(kCpuHasAVX2)) {
467
0
    MergeUVRow_ = MergeUVRow_Any_AVX2;
468
0
    if (IS_ALIGNED(halfwidth, 16)) {
469
0
      MergeUVRow_ = MergeUVRow_AVX2;
470
0
    }
471
0
  }
472
0
#endif
473
0
#if defined(HAS_MERGEUVROW_AVX512BW)
474
0
  if (TestCpuFlag(kCpuHasAVX512BW)) {
475
0
    MergeUVRow_ = MergeUVRow_Any_AVX512BW;
476
0
    if (IS_ALIGNED(halfwidth, 32)) {
477
0
      MergeUVRow_ = MergeUVRow_AVX512BW;
478
0
    }
479
0
  }
480
0
#endif
481
#if defined(HAS_MERGEUVROW_NEON)
482
  if (TestCpuFlag(kCpuHasNEON)) {
483
    MergeUVRow_ = MergeUVRow_Any_NEON;
484
    if (IS_ALIGNED(halfwidth, 16)) {
485
      MergeUVRow_ = MergeUVRow_NEON;
486
    }
487
  }
488
#endif
489
#if defined(HAS_MERGEUVROW_SME)
490
  if (TestCpuFlag(kCpuHasSME)) {
491
    MergeUVRow_ = MergeUVRow_SME;
492
  }
493
#endif
494
#if defined(HAS_MERGEUVROW_LSX)
495
  if (TestCpuFlag(kCpuHasLSX)) {
496
    MergeUVRow_ = MergeUVRow_Any_LSX;
497
    if (IS_ALIGNED(halfwidth, 16)) {
498
      MergeUVRow_ = MergeUVRow_LSX;
499
    }
500
  }
501
#endif
502
#if defined(HAS_MERGEUVROW_RVV)
503
  if (TestCpuFlag(kCpuHasRVV)) {
504
    MergeUVRow_ = MergeUVRow_RVV;
505
  }
506
#endif
507
0
  {
508
    // Allocate a rows of uv.
509
0
    align_buffer_64(row_u, ((halfwidth + 31) & ~31) * 2);
510
0
    uint8_t* row_v = row_u + ((halfwidth + 31) & ~31);
511
0
    if (!row_u)
512
0
      return 1;
513
514
0
    for (y = 0; y < height - 1; y += 2) {
515
0
      ARGBToUVRow(src_argb, src_stride_argb, row_u, row_v, width);
516
0
      MergeUVRow_(row_u, row_v, dst_uv, halfwidth);
517
0
      ARGBToYRow(src_argb, dst_y, width);
518
0
      ARGBToYRow(src_argb + src_stride_argb, dst_y + dst_stride_y, width);
519
0
      src_argb += src_stride_argb * 2;
520
0
      dst_y += dst_stride_y * 2;
521
0
      dst_uv += dst_stride_uv;
522
0
    }
523
0
    if (height & 1) {
524
0
      ARGBToUVRow(src_argb, 0, row_u, row_v, width);
525
0
      MergeUVRow_(row_u, row_v, dst_uv, halfwidth);
526
0
      ARGBToYRow(src_argb, dst_y, width);
527
0
    }
528
0
    free_aligned_buffer_64(row_u);
529
0
  }
530
0
  return 0;
531
0
}
532
533
// Same as NV12 but U and V swapped.
534
LIBYUV_API
535
int ARGBToNV21(const uint8_t* src_argb,
536
               int src_stride_argb,
537
               uint8_t* dst_y,
538
               int dst_stride_y,
539
               uint8_t* dst_vu,
540
               int dst_stride_vu,
541
               int width,
542
0
               int height) {
543
0
  int y;
544
0
  int halfwidth = (width + 1) >> 1;
545
0
  void (*ARGBToUVRow)(const uint8_t* src_argb0, int src_stride_argb,
546
0
                      uint8_t* dst_u, uint8_t* dst_v, int width) =
547
0
      ARGBToUVRow_C;
548
0
  void (*ARGBToYRow)(const uint8_t* src_argb, uint8_t* dst_y, int width) =
549
0
      ARGBToYRow_C;
550
0
  void (*MergeUVRow_)(const uint8_t* src_u, const uint8_t* src_v,
551
0
                      uint8_t* dst_vu, int width) = MergeUVRow_C;
552
0
  if (!src_argb || !dst_y || !dst_vu || width <= 0 || height == 0) {
553
0
    return -1;
554
0
  }
555
  // Negative height means invert the image.
556
0
  if (height < 0) {
557
0
    height = -height;
558
0
    src_argb = src_argb + (height - 1) * src_stride_argb;
559
0
    src_stride_argb = -src_stride_argb;
560
0
  }
561
0
#if defined(HAS_ARGBTOYROW_SSSE3)
562
0
  if (TestCpuFlag(kCpuHasSSSE3)) {
563
0
    ARGBToYRow = ARGBToYRow_Any_SSSE3;
564
0
    if (IS_ALIGNED(width, 16)) {
565
0
      ARGBToYRow = ARGBToYRow_SSSE3;
566
0
    }
567
0
  }
568
0
#endif
569
0
#if defined(HAS_ARGBTOUVROW_SSSE3)
570
0
  if (TestCpuFlag(kCpuHasSSSE3)) {
571
0
    ARGBToUVRow = ARGBToUVRow_Any_SSSE3;
572
0
    if (IS_ALIGNED(width, 16)) {
573
0
      ARGBToUVRow = ARGBToUVRow_SSSE3;
574
0
    }
575
0
  }
576
0
#endif
577
0
#if defined(HAS_ARGBTOYROW_AVX2)
578
0
  if (TestCpuFlag(kCpuHasAVX2)) {
579
0
    ARGBToYRow = ARGBToYRow_Any_AVX2;
580
0
    if (IS_ALIGNED(width, 32)) {
581
0
      ARGBToYRow = ARGBToYRow_AVX2;
582
0
    }
583
0
  }
584
0
#endif
585
0
#if defined(HAS_ARGBTOUVROW_AVX2)
586
0
  if (TestCpuFlag(kCpuHasAVX2)) {
587
0
    ARGBToUVRow = ARGBToUVRow_Any_AVX2;
588
0
    if (IS_ALIGNED(width, 32)) {
589
0
      ARGBToUVRow = ARGBToUVRow_AVX2;
590
0
    }
591
0
  }
592
0
#endif
593
#if defined(HAS_ARGBTOYROW_NEON)
594
  if (TestCpuFlag(kCpuHasNEON)) {
595
    ARGBToYRow = ARGBToYRow_Any_NEON;
596
    if (IS_ALIGNED(width, 16)) {
597
      ARGBToYRow = ARGBToYRow_NEON;
598
    }
599
  }
600
#endif
601
#if defined(HAS_ARGBTOYROW_NEON_DOTPROD)
602
  if (TestCpuFlag(kCpuHasNeonDotProd)) {
603
    ARGBToYRow = ARGBToYRow_Any_NEON_DotProd;
604
    if (IS_ALIGNED(width, 16)) {
605
      ARGBToYRow = ARGBToYRow_NEON_DotProd;
606
    }
607
  }
608
#endif
609
#if defined(HAS_ARGBTOUVROW_NEON)
610
  if (TestCpuFlag(kCpuHasNEON)) {
611
    ARGBToUVRow = ARGBToUVRow_Any_NEON;
612
    if (IS_ALIGNED(width, 16)) {
613
      ARGBToUVRow = ARGBToUVRow_NEON;
614
    }
615
  }
616
#endif
617
#if defined(HAS_ARGBTOUVROW_NEON_I8MM)
618
  if (TestCpuFlag(kCpuHasNeonI8MM)) {
619
    ARGBToUVRow = ARGBToUVRow_Any_NEON_I8MM;
620
    if (IS_ALIGNED(width, 16)) {
621
      ARGBToUVRow = ARGBToUVRow_NEON_I8MM;
622
    }
623
  }
624
#endif
625
#if defined(HAS_ARGBTOUVROW_SVE2)
626
  if (TestCpuFlag(kCpuHasSVE2)) {
627
    ARGBToUVRow = ARGBToUVRow_Any_SVE2;
628
    if (IS_ALIGNED(width, 2)) {
629
      ARGBToUVRow = ARGBToUVRow_SVE2;
630
    }
631
  }
632
#endif
633
#if defined(HAS_ARGBTOUVROW_SME)
634
  if (TestCpuFlag(kCpuHasSME)) {
635
    ARGBToUVRow = ARGBToUVRow_Any_SME;
636
    if (IS_ALIGNED(width, 2)) {
637
      ARGBToUVRow = ARGBToUVRow_SME;
638
    }
639
  }
640
#endif
641
#if defined(HAS_ARGBTOYROW_LSX)
642
  if (TestCpuFlag(kCpuHasLSX)) {
643
    ARGBToYRow = ARGBToYRow_Any_LSX;
644
    if (IS_ALIGNED(width, 16)) {
645
      ARGBToYRow = ARGBToYRow_LSX;
646
    }
647
  }
648
#endif
649
#if defined(HAS_ARGBTOYROW_LSX) && defined(HAS_ARGBTOUVROW_LSX)
650
  if (TestCpuFlag(kCpuHasLSX)) {
651
    ARGBToYRow = ARGBToYRow_Any_LSX;
652
    ARGBToUVRow = ARGBToUVRow_Any_LSX;
653
    if (IS_ALIGNED(width, 16)) {
654
      ARGBToYRow = ARGBToYRow_LSX;
655
      ARGBToUVRow = ARGBToUVRow_LSX;
656
    }
657
  }
658
#endif
659
#if defined(HAS_ARGBTOYROW_LASX) && defined(HAS_ARGBTOUVROW_LASX)
660
  if (TestCpuFlag(kCpuHasLASX)) {
661
    ARGBToYRow = ARGBToYRow_Any_LASX;
662
    ARGBToUVRow = ARGBToUVRow_Any_LASX;
663
    if (IS_ALIGNED(width, 32)) {
664
      ARGBToYRow = ARGBToYRow_LASX;
665
      ARGBToUVRow = ARGBToUVRow_LASX;
666
    }
667
  }
668
#endif
669
#if defined(HAS_ARGBTOYROW_RVV)
670
  if (TestCpuFlag(kCpuHasRVV)) {
671
    ARGBToYRow = ARGBToYRow_RVV;
672
  }
673
#endif
674
0
#if defined(HAS_MERGEUVROW_SSE2)
675
0
  if (TestCpuFlag(kCpuHasSSE2)) {
676
0
    MergeUVRow_ = MergeUVRow_Any_SSE2;
677
0
    if (IS_ALIGNED(halfwidth, 16)) {
678
0
      MergeUVRow_ = MergeUVRow_SSE2;
679
0
    }
680
0
  }
681
0
#endif
682
0
#if defined(HAS_MERGEUVROW_AVX2)
683
0
  if (TestCpuFlag(kCpuHasAVX2)) {
684
0
    MergeUVRow_ = MergeUVRow_Any_AVX2;
685
0
    if (IS_ALIGNED(halfwidth, 16)) {
686
0
      MergeUVRow_ = MergeUVRow_AVX2;
687
0
    }
688
0
  }
689
0
#endif
690
0
#if defined(HAS_MERGEUVROW_AVX512BW)
691
0
  if (TestCpuFlag(kCpuHasAVX512BW)) {
692
0
    MergeUVRow_ = MergeUVRow_Any_AVX512BW;
693
0
    if (IS_ALIGNED(halfwidth, 64)) {
694
0
      MergeUVRow_ = MergeUVRow_AVX512BW;
695
0
    }
696
0
  }
697
0
#endif
698
#if defined(HAS_MERGEUVROW_NEON)
699
  if (TestCpuFlag(kCpuHasNEON)) {
700
    MergeUVRow_ = MergeUVRow_Any_NEON;
701
    if (IS_ALIGNED(halfwidth, 16)) {
702
      MergeUVRow_ = MergeUVRow_NEON;
703
    }
704
  }
705
#endif
706
#if defined(HAS_MERGEUVROW_SME)
707
  if (TestCpuFlag(kCpuHasSME)) {
708
    MergeUVRow_ = MergeUVRow_SME;
709
  }
710
#endif
711
#if defined(HAS_MERGEUVROW_LSX)
712
  if (TestCpuFlag(kCpuHasLSX)) {
713
    MergeUVRow_ = MergeUVRow_Any_LSX;
714
    if (IS_ALIGNED(halfwidth, 16)) {
715
      MergeUVRow_ = MergeUVRow_LSX;
716
    }
717
  }
718
#endif
719
#if defined(HAS_MERGEUVROW_RVV)
720
  if (TestCpuFlag(kCpuHasRVV)) {
721
    MergeUVRow_ = MergeUVRow_RVV;
722
  }
723
#endif
724
0
  {
725
    // Allocate a rows of uv.
726
0
    align_buffer_64(row_u, ((halfwidth + 31) & ~31) * 2);
727
0
    uint8_t* row_v = row_u + ((halfwidth + 31) & ~31);
728
0
    if (!row_u)
729
0
      return 1;
730
731
0
    for (y = 0; y < height - 1; y += 2) {
732
0
      ARGBToUVRow(src_argb, src_stride_argb, row_u, row_v, width);
733
0
      MergeUVRow_(row_v, row_u, dst_vu, halfwidth);
734
0
      ARGBToYRow(src_argb, dst_y, width);
735
0
      ARGBToYRow(src_argb + src_stride_argb, dst_y + dst_stride_y, width);
736
0
      src_argb += src_stride_argb * 2;
737
0
      dst_y += dst_stride_y * 2;
738
0
      dst_vu += dst_stride_vu;
739
0
    }
740
0
    if (height & 1) {
741
0
      ARGBToUVRow(src_argb, 0, row_u, row_v, width);
742
0
      MergeUVRow_(row_v, row_u, dst_vu, halfwidth);
743
0
      ARGBToYRow(src_argb, dst_y, width);
744
0
    }
745
0
    free_aligned_buffer_64(row_u);
746
0
  }
747
0
  return 0;
748
0
}
749
750
LIBYUV_API
751
int ABGRToNV12(const uint8_t* src_abgr,
752
               int src_stride_abgr,
753
               uint8_t* dst_y,
754
               int dst_stride_y,
755
               uint8_t* dst_uv,
756
               int dst_stride_uv,
757
               int width,
758
0
               int height) {
759
0
  int y;
760
0
  int halfwidth = (width + 1) >> 1;
761
0
  void (*ABGRToUVRow)(const uint8_t* src_abgr0, int src_stride_abgr,
762
0
                      uint8_t* dst_u, uint8_t* dst_v, int width) =
763
0
      ABGRToUVRow_C;
764
0
  void (*ABGRToYRow)(const uint8_t* src_abgr, uint8_t* dst_y, int width) =
765
0
      ABGRToYRow_C;
766
0
  void (*MergeUVRow_)(const uint8_t* src_u, const uint8_t* src_v,
767
0
                      uint8_t* dst_uv, int width) = MergeUVRow_C;
768
0
  if (!src_abgr || !dst_y || !dst_uv || width <= 0 || height == 0) {
769
0
    return -1;
770
0
  }
771
  // Negative height means invert the image.
772
0
  if (height < 0) {
773
0
    height = -height;
774
0
    src_abgr = src_abgr + (height - 1) * src_stride_abgr;
775
0
    src_stride_abgr = -src_stride_abgr;
776
0
  }
777
0
#if defined(HAS_ABGRTOYROW_SSSE3)
778
0
  if (TestCpuFlag(kCpuHasSSSE3)) {
779
0
    ABGRToYRow = ABGRToYRow_Any_SSSE3;
780
0
    if (IS_ALIGNED(width, 16)) {
781
0
      ABGRToYRow = ABGRToYRow_SSSE3;
782
0
    }
783
0
  }
784
0
#endif
785
0
#if defined(HAS_ABGRTOUVROW_SSSE3)
786
0
  if (TestCpuFlag(kCpuHasSSSE3)) {
787
0
    ABGRToUVRow = ABGRToUVRow_Any_SSSE3;
788
0
    if (IS_ALIGNED(width, 16)) {
789
0
      ABGRToUVRow = ABGRToUVRow_SSSE3;
790
0
    }
791
0
  }
792
0
#endif
793
0
#if defined(HAS_ABGRTOYROW_AVX2)
794
0
  if (TestCpuFlag(kCpuHasAVX2)) {
795
0
    ABGRToYRow = ABGRToYRow_Any_AVX2;
796
0
    if (IS_ALIGNED(width, 32)) {
797
0
      ABGRToYRow = ABGRToYRow_AVX2;
798
0
    }
799
0
  }
800
0
#endif
801
0
#if defined(HAS_ABGRTOUVROW_AVX2)
802
0
  if (TestCpuFlag(kCpuHasAVX2)) {
803
0
    ABGRToUVRow = ABGRToUVRow_Any_AVX2;
804
0
    if (IS_ALIGNED(width, 32)) {
805
0
      ABGRToUVRow = ABGRToUVRow_AVX2;
806
0
    }
807
0
  }
808
0
#endif
809
#if defined(HAS_ABGRTOYROW_NEON)
810
  if (TestCpuFlag(kCpuHasNEON)) {
811
    ABGRToYRow = ABGRToYRow_Any_NEON;
812
    if (IS_ALIGNED(width, 16)) {
813
      ABGRToYRow = ABGRToYRow_NEON;
814
    }
815
  }
816
#endif
817
#if defined(HAS_ABGRTOYROW_NEON_DOTPROD)
818
  if (TestCpuFlag(kCpuHasNeonDotProd)) {
819
    ABGRToYRow = ABGRToYRow_Any_NEON_DotProd;
820
    if (IS_ALIGNED(width, 16)) {
821
      ABGRToYRow = ABGRToYRow_NEON_DotProd;
822
    }
823
  }
824
#endif
825
#if defined(HAS_ABGRTOUVROW_NEON)
826
  if (TestCpuFlag(kCpuHasNEON)) {
827
    ABGRToUVRow = ABGRToUVRow_Any_NEON;
828
    if (IS_ALIGNED(width, 16)) {
829
      ABGRToUVRow = ABGRToUVRow_NEON;
830
    }
831
  }
832
#endif
833
#if defined(HAS_ABGRTOUVROW_NEON_I8MM)
834
  if (TestCpuFlag(kCpuHasNeonI8MM)) {
835
    ABGRToUVRow = ABGRToUVRow_Any_NEON_I8MM;
836
    if (IS_ALIGNED(width, 16)) {
837
      ABGRToUVRow = ABGRToUVRow_NEON_I8MM;
838
    }
839
  }
840
#endif
841
#if defined(HAS_ABGRTOUVROW_SVE2)
842
  if (TestCpuFlag(kCpuHasSVE2)) {
843
    ABGRToUVRow = ABGRToUVRow_Any_SVE2;
844
    if (IS_ALIGNED(width, 2)) {
845
      ABGRToUVRow = ABGRToUVRow_SVE2;
846
    }
847
  }
848
#endif
849
#if defined(HAS_ABGRTOUVROW_SME)
850
  if (TestCpuFlag(kCpuHasSME)) {
851
    ABGRToUVRow = ABGRToUVRow_Any_SME;
852
    if (IS_ALIGNED(width, 2)) {
853
      ABGRToUVRow = ABGRToUVRow_SME;
854
    }
855
  }
856
#endif
857
#if defined(HAS_ABGRTOYROW_LSX)
858
  if (TestCpuFlag(kCpuHasLSX)) {
859
    ABGRToYRow = ABGRToYRow_Any_LSX;
860
    if (IS_ALIGNED(width, 16)) {
861
      ABGRToYRow = ABGRToYRow_LSX;
862
    }
863
  }
864
#endif
865
#if defined(HAS_ABGRTOYROW_LASX)
866
  if (TestCpuFlag(kCpuHasLASX)) {
867
    ABGRToYRow = ABGRToYRow_Any_LASX;
868
    if (IS_ALIGNED(width, 32)) {
869
      ABGRToYRow = ABGRToYRow_LASX;
870
    }
871
  }
872
#endif
873
#if defined(HAS_ABGRTOYROW_RVV)
874
  if (TestCpuFlag(kCpuHasRVV)) {
875
    ABGRToYRow = ABGRToYRow_RVV;
876
  }
877
#endif
878
0
#if defined(HAS_MERGEUVROW_SSE2)
879
0
  if (TestCpuFlag(kCpuHasSSE2)) {
880
0
    MergeUVRow_ = MergeUVRow_Any_SSE2;
881
0
    if (IS_ALIGNED(halfwidth, 16)) {
882
0
      MergeUVRow_ = MergeUVRow_SSE2;
883
0
    }
884
0
  }
885
0
#endif
886
0
#if defined(HAS_MERGEUVROW_AVX2)
887
0
  if (TestCpuFlag(kCpuHasAVX2)) {
888
0
    MergeUVRow_ = MergeUVRow_Any_AVX2;
889
0
    if (IS_ALIGNED(halfwidth, 16)) {
890
0
      MergeUVRow_ = MergeUVRow_AVX2;
891
0
    }
892
0
  }
893
0
#endif
894
0
#if defined(HAS_MERGEUVROW_AVX512BW)
895
0
  if (TestCpuFlag(kCpuHasAVX512BW)) {
896
0
    MergeUVRow_ = MergeUVRow_Any_AVX512BW;
897
0
    if (IS_ALIGNED(halfwidth, 64)) {
898
0
      MergeUVRow_ = MergeUVRow_AVX512BW;
899
0
    }
900
0
  }
901
0
#endif
902
#if defined(HAS_MERGEUVROW_NEON)
903
  if (TestCpuFlag(kCpuHasNEON)) {
904
    MergeUVRow_ = MergeUVRow_Any_NEON;
905
    if (IS_ALIGNED(halfwidth, 16)) {
906
      MergeUVRow_ = MergeUVRow_NEON;
907
    }
908
  }
909
#endif
910
#if defined(HAS_MERGEUVROW_SME)
911
  if (TestCpuFlag(kCpuHasSME)) {
912
    MergeUVRow_ = MergeUVRow_SME;
913
  }
914
#endif
915
#if defined(HAS_MERGEUVROW_LSX)
916
  if (TestCpuFlag(kCpuHasLSX)) {
917
    MergeUVRow_ = MergeUVRow_Any_LSX;
918
    if (IS_ALIGNED(halfwidth, 16)) {
919
      MergeUVRow_ = MergeUVRow_LSX;
920
    }
921
  }
922
#endif
923
#if defined(HAS_MERGEUVROW_RVV)
924
  if (TestCpuFlag(kCpuHasRVV)) {
925
    MergeUVRow_ = MergeUVRow_RVV;
926
  }
927
#endif
928
0
  {
929
    // Allocate a rows of uv.
930
0
    align_buffer_64(row_u, ((halfwidth + 31) & ~31) * 2);
931
0
    uint8_t* row_v = row_u + ((halfwidth + 31) & ~31);
932
0
    if (!row_u)
933
0
      return 1;
934
935
0
    for (y = 0; y < height - 1; y += 2) {
936
0
      ABGRToUVRow(src_abgr, src_stride_abgr, row_u, row_v, width);
937
0
      MergeUVRow_(row_u, row_v, dst_uv, halfwidth);
938
0
      ABGRToYRow(src_abgr, dst_y, width);
939
0
      ABGRToYRow(src_abgr + src_stride_abgr, dst_y + dst_stride_y, width);
940
0
      src_abgr += src_stride_abgr * 2;
941
0
      dst_y += dst_stride_y * 2;
942
0
      dst_uv += dst_stride_uv;
943
0
    }
944
0
    if (height & 1) {
945
0
      ABGRToUVRow(src_abgr, 0, row_u, row_v, width);
946
0
      MergeUVRow_(row_u, row_v, dst_uv, halfwidth);
947
0
      ABGRToYRow(src_abgr, dst_y, width);
948
0
    }
949
0
    free_aligned_buffer_64(row_u);
950
0
  }
951
0
  return 0;
952
0
}
953
954
// Same as NV12 but U and V swapped.
955
LIBYUV_API
956
int ABGRToNV21(const uint8_t* src_abgr,
957
               int src_stride_abgr,
958
               uint8_t* dst_y,
959
               int dst_stride_y,
960
               uint8_t* dst_vu,
961
               int dst_stride_vu,
962
               int width,
963
0
               int height) {
964
0
  int y;
965
0
  int halfwidth = (width + 1) >> 1;
966
0
  void (*ABGRToUVRow)(const uint8_t* src_abgr0, int src_stride_abgr,
967
0
                      uint8_t* dst_u, uint8_t* dst_v, int width) =
968
0
      ABGRToUVRow_C;
969
0
  void (*ABGRToYRow)(const uint8_t* src_abgr, uint8_t* dst_y, int width) =
970
0
      ABGRToYRow_C;
971
0
  void (*MergeUVRow_)(const uint8_t* src_u, const uint8_t* src_v,
972
0
                      uint8_t* dst_vu, int width) = MergeUVRow_C;
973
0
  if (!src_abgr || !dst_y || !dst_vu || width <= 0 || height == 0) {
974
0
    return -1;
975
0
  }
976
  // Negative height means invert the image.
977
0
  if (height < 0) {
978
0
    height = -height;
979
0
    src_abgr = src_abgr + (height - 1) * src_stride_abgr;
980
0
    src_stride_abgr = -src_stride_abgr;
981
0
  }
982
0
#if defined(HAS_ABGRTOYROW_SSSE3)
983
0
  if (TestCpuFlag(kCpuHasSSSE3)) {
984
0
    ABGRToYRow = ABGRToYRow_Any_SSSE3;
985
0
    if (IS_ALIGNED(width, 16)) {
986
0
      ABGRToYRow = ABGRToYRow_SSSE3;
987
0
    }
988
0
  }
989
0
#endif
990
0
#if defined(HAS_ABGRTOUVROW_SSSE3)
991
0
  if (TestCpuFlag(kCpuHasSSSE3)) {
992
0
    ABGRToUVRow = ABGRToUVRow_Any_SSSE3;
993
0
    if (IS_ALIGNED(width, 16)) {
994
0
      ABGRToUVRow = ABGRToUVRow_SSSE3;
995
0
    }
996
0
  }
997
0
#endif
998
0
#if defined(HAS_ABGRTOYROW_AVX2)
999
0
  if (TestCpuFlag(kCpuHasAVX2)) {
1000
0
    ABGRToYRow = ABGRToYRow_Any_AVX2;
1001
0
    if (IS_ALIGNED(width, 32)) {
1002
0
      ABGRToYRow = ABGRToYRow_AVX2;
1003
0
    }
1004
0
  }
1005
0
#endif
1006
0
#if defined(HAS_ABGRTOUVROW_AVX2)
1007
0
  if (TestCpuFlag(kCpuHasAVX2)) {
1008
0
    ABGRToUVRow = ABGRToUVRow_Any_AVX2;
1009
0
    if (IS_ALIGNED(width, 32)) {
1010
0
      ABGRToUVRow = ABGRToUVRow_AVX2;
1011
0
    }
1012
0
  }
1013
0
#endif
1014
#if defined(HAS_ABGRTOYROW_NEON)
1015
  if (TestCpuFlag(kCpuHasNEON)) {
1016
    ABGRToYRow = ABGRToYRow_Any_NEON;
1017
    if (IS_ALIGNED(width, 16)) {
1018
      ABGRToYRow = ABGRToYRow_NEON;
1019
    }
1020
  }
1021
#endif
1022
#if defined(HAS_ABGRTOYROW_NEON_DOTPROD)
1023
  if (TestCpuFlag(kCpuHasNeonDotProd)) {
1024
    ABGRToYRow = ABGRToYRow_Any_NEON_DotProd;
1025
    if (IS_ALIGNED(width, 16)) {
1026
      ABGRToYRow = ABGRToYRow_NEON_DotProd;
1027
    }
1028
  }
1029
#endif
1030
#if defined(HAS_ABGRTOUVROW_NEON)
1031
  if (TestCpuFlag(kCpuHasNEON)) {
1032
    ABGRToUVRow = ABGRToUVRow_Any_NEON;
1033
    if (IS_ALIGNED(width, 16)) {
1034
      ABGRToUVRow = ABGRToUVRow_NEON;
1035
    }
1036
  }
1037
#endif
1038
#if defined(HAS_ABGRTOUVROW_NEON_I8MM)
1039
  if (TestCpuFlag(kCpuHasNeonI8MM)) {
1040
    ABGRToUVRow = ABGRToUVRow_Any_NEON_I8MM;
1041
    if (IS_ALIGNED(width, 16)) {
1042
      ABGRToUVRow = ABGRToUVRow_NEON_I8MM;
1043
    }
1044
  }
1045
#endif
1046
#if defined(HAS_ABGRTOUVROW_SVE2)
1047
  if (TestCpuFlag(kCpuHasSVE2)) {
1048
    ABGRToUVRow = ABGRToUVRow_Any_SVE2;
1049
    if (IS_ALIGNED(width, 2)) {
1050
      ABGRToUVRow = ABGRToUVRow_SVE2;
1051
    }
1052
  }
1053
#endif
1054
#if defined(HAS_ABGRTOUVROW_SME)
1055
  if (TestCpuFlag(kCpuHasSME)) {
1056
    ABGRToUVRow = ABGRToUVRow_Any_SME;
1057
    if (IS_ALIGNED(width, 2)) {
1058
      ABGRToUVRow = ABGRToUVRow_SME;
1059
    }
1060
  }
1061
#endif
1062
#if defined(HAS_ABGRTOYROW_LSX)
1063
  if (TestCpuFlag(kCpuHasLSX)) {
1064
    ABGRToYRow = ABGRToYRow_Any_LSX;
1065
    if (IS_ALIGNED(width, 16)) {
1066
      ABGRToYRow = ABGRToYRow_LSX;
1067
    }
1068
  }
1069
#endif
1070
#if defined(HAS_ABGRTOYROW_LASX)
1071
  if (TestCpuFlag(kCpuHasLASX)) {
1072
    ABGRToYRow = ABGRToYRow_Any_LASX;
1073
    if (IS_ALIGNED(width, 32)) {
1074
      ABGRToYRow = ABGRToYRow_LASX;
1075
    }
1076
  }
1077
#endif
1078
#if defined(HAS_ABGRTOYROW_RVV)
1079
  if (TestCpuFlag(kCpuHasRVV)) {
1080
    ABGRToYRow = ABGRToYRow_RVV;
1081
  }
1082
#endif
1083
0
#if defined(HAS_MERGEUVROW_SSE2)
1084
0
  if (TestCpuFlag(kCpuHasSSE2)) {
1085
0
    MergeUVRow_ = MergeUVRow_Any_SSE2;
1086
0
    if (IS_ALIGNED(halfwidth, 16)) {
1087
0
      MergeUVRow_ = MergeUVRow_SSE2;
1088
0
    }
1089
0
  }
1090
0
#endif
1091
0
#if defined(HAS_MERGEUVROW_AVX2)
1092
0
  if (TestCpuFlag(kCpuHasAVX2)) {
1093
0
    MergeUVRow_ = MergeUVRow_Any_AVX2;
1094
0
    if (IS_ALIGNED(halfwidth, 16)) {
1095
0
      MergeUVRow_ = MergeUVRow_AVX2;
1096
0
    }
1097
0
  }
1098
0
#endif
1099
0
#if defined(HAS_MERGEUVROW_AVX512BW)
1100
0
  if (TestCpuFlag(kCpuHasAVX512BW)) {
1101
0
    MergeUVRow_ = MergeUVRow_Any_AVX512BW;
1102
0
    if (IS_ALIGNED(halfwidth, 64)) {
1103
0
      MergeUVRow_ = MergeUVRow_AVX512BW;
1104
0
    }
1105
0
  }
1106
0
#endif
1107
#if defined(HAS_MERGEUVROW_NEON)
1108
  if (TestCpuFlag(kCpuHasNEON)) {
1109
    MergeUVRow_ = MergeUVRow_Any_NEON;
1110
    if (IS_ALIGNED(halfwidth, 16)) {
1111
      MergeUVRow_ = MergeUVRow_NEON;
1112
    }
1113
  }
1114
#endif
1115
#if defined(HAS_MERGEUVROW_SME)
1116
  if (TestCpuFlag(kCpuHasSME)) {
1117
    MergeUVRow_ = MergeUVRow_SME;
1118
  }
1119
#endif
1120
#if defined(HAS_MERGEUVROW_LSX)
1121
  if (TestCpuFlag(kCpuHasLSX)) {
1122
    MergeUVRow_ = MergeUVRow_Any_LSX;
1123
    if (IS_ALIGNED(halfwidth, 16)) {
1124
      MergeUVRow_ = MergeUVRow_LSX;
1125
    }
1126
  }
1127
#endif
1128
#if defined(HAS_MERGEUVROW_RVV)
1129
  if (TestCpuFlag(kCpuHasRVV)) {
1130
    MergeUVRow_ = MergeUVRow_RVV;
1131
  }
1132
#endif
1133
0
  {
1134
    // Allocate a rows of uv.
1135
0
    align_buffer_64(row_u, ((halfwidth + 31) & ~31) * 2);
1136
0
    uint8_t* row_v = row_u + ((halfwidth + 31) & ~31);
1137
0
    if (!row_u)
1138
0
      return 1;
1139
1140
0
    for (y = 0; y < height - 1; y += 2) {
1141
0
      ABGRToUVRow(src_abgr, src_stride_abgr, row_u, row_v, width);
1142
0
      MergeUVRow_(row_v, row_u, dst_vu, halfwidth);
1143
0
      ABGRToYRow(src_abgr, dst_y, width);
1144
0
      ABGRToYRow(src_abgr + src_stride_abgr, dst_y + dst_stride_y, width);
1145
0
      src_abgr += src_stride_abgr * 2;
1146
0
      dst_y += dst_stride_y * 2;
1147
0
      dst_vu += dst_stride_vu;
1148
0
    }
1149
0
    if (height & 1) {
1150
0
      ABGRToUVRow(src_abgr, 0, row_u, row_v, width);
1151
0
      MergeUVRow_(row_v, row_u, dst_vu, halfwidth);
1152
0
      ABGRToYRow(src_abgr, dst_y, width);
1153
0
    }
1154
0
    free_aligned_buffer_64(row_u);
1155
0
  }
1156
0
  return 0;
1157
0
}
1158
1159
// Convert ARGB to YUY2.
1160
LIBYUV_API
1161
int ARGBToYUY2(const uint8_t* src_argb,
1162
               int src_stride_argb,
1163
               uint8_t* dst_yuy2,
1164
               int dst_stride_yuy2,
1165
               int width,
1166
0
               int height) {
1167
0
  int y;
1168
0
  void (*ARGBToUVRow)(const uint8_t* src_argb, int src_stride_argb,
1169
0
                      uint8_t* dst_u, uint8_t* dst_v, int width) =
1170
0
      ARGBToUVRow_C;
1171
0
  void (*ARGBToYRow)(const uint8_t* src_argb, uint8_t* dst_y, int width) =
1172
0
      ARGBToYRow_C;
1173
0
  void (*I422ToYUY2Row)(const uint8_t* src_y, const uint8_t* src_u,
1174
0
                        const uint8_t* src_v, uint8_t* dst_yuy2, int width) =
1175
0
      I422ToYUY2Row_C;
1176
1177
0
  if (!src_argb || !dst_yuy2 || width <= 0 || height == 0) {
1178
0
    return -1;
1179
0
  }
1180
  // Negative height means invert the image.
1181
0
  if (height < 0) {
1182
0
    height = -height;
1183
0
    dst_yuy2 = dst_yuy2 + (height - 1) * dst_stride_yuy2;
1184
0
    dst_stride_yuy2 = -dst_stride_yuy2;
1185
0
  }
1186
  // Coalesce rows.
1187
0
  if (src_stride_argb == width * 4 && dst_stride_yuy2 == width * 2) {
1188
0
    width *= height;
1189
0
    height = 1;
1190
0
    src_stride_argb = dst_stride_yuy2 = 0;
1191
0
  }
1192
0
#if defined(HAS_ARGBTOYROW_SSSE3)
1193
0
  if (TestCpuFlag(kCpuHasSSSE3)) {
1194
0
    ARGBToYRow = ARGBToYRow_Any_SSSE3;
1195
0
    if (IS_ALIGNED(width, 16)) {
1196
0
      ARGBToYRow = ARGBToYRow_SSSE3;
1197
0
    }
1198
0
  }
1199
0
#endif
1200
0
#if defined(HAS_ARGBTOUVROW_SSSE3)
1201
0
  if (TestCpuFlag(kCpuHasSSSE3)) {
1202
0
    ARGBToUVRow = ARGBToUVRow_Any_SSSE3;
1203
0
    if (IS_ALIGNED(width, 16)) {
1204
0
      ARGBToUVRow = ARGBToUVRow_SSSE3;
1205
0
    }
1206
0
  }
1207
0
#endif
1208
0
#if defined(HAS_ARGBTOYROW_AVX2)
1209
0
  if (TestCpuFlag(kCpuHasAVX2)) {
1210
0
    ARGBToYRow = ARGBToYRow_Any_AVX2;
1211
0
    if (IS_ALIGNED(width, 32)) {
1212
0
      ARGBToYRow = ARGBToYRow_AVX2;
1213
0
    }
1214
0
  }
1215
0
#endif
1216
0
#if defined(HAS_ARGBTOUVROW_AVX2)
1217
0
  if (TestCpuFlag(kCpuHasAVX2)) {
1218
0
    ARGBToUVRow = ARGBToUVRow_Any_AVX2;
1219
0
    if (IS_ALIGNED(width, 32)) {
1220
0
      ARGBToUVRow = ARGBToUVRow_AVX2;
1221
0
    }
1222
0
  }
1223
0
#endif
1224
#if defined(HAS_ARGBTOYROW_NEON)
1225
  if (TestCpuFlag(kCpuHasNEON)) {
1226
    ARGBToYRow = ARGBToYRow_Any_NEON;
1227
    if (IS_ALIGNED(width, 16)) {
1228
      ARGBToYRow = ARGBToYRow_NEON;
1229
    }
1230
  }
1231
#endif
1232
#if defined(HAS_ARGBTOYROW_NEON_DOTPROD)
1233
  if (TestCpuFlag(kCpuHasNeonDotProd)) {
1234
    ARGBToYRow = ARGBToYRow_Any_NEON_DotProd;
1235
    if (IS_ALIGNED(width, 16)) {
1236
      ARGBToYRow = ARGBToYRow_NEON_DotProd;
1237
    }
1238
  }
1239
#endif
1240
#if defined(HAS_ARGBTOUVROW_NEON)
1241
  if (TestCpuFlag(kCpuHasNEON)) {
1242
    ARGBToUVRow = ARGBToUVRow_Any_NEON;
1243
    if (IS_ALIGNED(width, 16)) {
1244
      ARGBToUVRow = ARGBToUVRow_NEON;
1245
    }
1246
  }
1247
#endif
1248
#if defined(HAS_ARGBTOUVROW_NEON_I8MM)
1249
  if (TestCpuFlag(kCpuHasNeonI8MM)) {
1250
    ARGBToUVRow = ARGBToUVRow_Any_NEON_I8MM;
1251
    if (IS_ALIGNED(width, 16)) {
1252
      ARGBToUVRow = ARGBToUVRow_NEON_I8MM;
1253
    }
1254
  }
1255
#endif
1256
#if defined(HAS_ARGBTOUVROW_SVE2)
1257
  if (TestCpuFlag(kCpuHasSVE2)) {
1258
    ARGBToUVRow = ARGBToUVRow_Any_SVE2;
1259
    if (IS_ALIGNED(width, 2)) {
1260
      ARGBToUVRow = ARGBToUVRow_SVE2;
1261
    }
1262
  }
1263
#endif
1264
#if defined(HAS_ARGBTOUVROW_SME)
1265
  if (TestCpuFlag(kCpuHasSME)) {
1266
    ARGBToUVRow = ARGBToUVRow_Any_SME;
1267
    if (IS_ALIGNED(width, 2)) {
1268
      ARGBToUVRow = ARGBToUVRow_SME;
1269
    }
1270
  }
1271
#endif
1272
#if defined(HAS_ARGBTOYROW_LSX)
1273
  if (TestCpuFlag(kCpuHasLSX)) {
1274
    ARGBToYRow = ARGBToYRow_Any_LSX;
1275
    if (IS_ALIGNED(width, 16)) {
1276
      ARGBToYRow = ARGBToYRow_LSX;
1277
    }
1278
  }
1279
#endif
1280
#if defined(HAS_ARGBTOYROW_LSX) && defined(HAS_ARGBTOUVROW_LSX)
1281
  if (TestCpuFlag(kCpuHasLSX)) {
1282
    ARGBToYRow = ARGBToYRow_Any_LSX;
1283
    ARGBToUVRow = ARGBToUVRow_Any_LSX;
1284
    if (IS_ALIGNED(width, 16)) {
1285
      ARGBToYRow = ARGBToYRow_LSX;
1286
      ARGBToUVRow = ARGBToUVRow_LSX;
1287
    }
1288
  }
1289
#endif
1290
#if defined(HAS_ARGBTOYROW_LASX) && defined(HAS_ARGBTOUVROW_LASX)
1291
  if (TestCpuFlag(kCpuHasLASX)) {
1292
    ARGBToYRow = ARGBToYRow_Any_LASX;
1293
    ARGBToUVRow = ARGBToUVRow_Any_LASX;
1294
    if (IS_ALIGNED(width, 32)) {
1295
      ARGBToYRow = ARGBToYRow_LASX;
1296
      ARGBToUVRow = ARGBToUVRow_LASX;
1297
    }
1298
  }
1299
#endif
1300
#if defined(HAS_ARGBTOYROW_RVV)
1301
  if (TestCpuFlag(kCpuHasRVV)) {
1302
    ARGBToYRow = ARGBToYRow_RVV;
1303
  }
1304
#endif
1305
0
#if defined(HAS_I422TOYUY2ROW_SSE2)
1306
0
  if (TestCpuFlag(kCpuHasSSE2)) {
1307
0
    I422ToYUY2Row = I422ToYUY2Row_Any_SSE2;
1308
0
    if (IS_ALIGNED(width, 16)) {
1309
0
      I422ToYUY2Row = I422ToYUY2Row_SSE2;
1310
0
    }
1311
0
  }
1312
0
#endif
1313
0
#if defined(HAS_I422TOYUY2ROW_AVX2)
1314
0
  if (TestCpuFlag(kCpuHasAVX2)) {
1315
0
    I422ToYUY2Row = I422ToYUY2Row_Any_AVX2;
1316
0
    if (IS_ALIGNED(width, 32)) {
1317
0
      I422ToYUY2Row = I422ToYUY2Row_AVX2;
1318
0
    }
1319
0
  }
1320
0
#endif
1321
#if defined(HAS_I422TOYUY2ROW_NEON)
1322
  if (TestCpuFlag(kCpuHasNEON)) {
1323
    I422ToYUY2Row = I422ToYUY2Row_Any_NEON;
1324
    if (IS_ALIGNED(width, 16)) {
1325
      I422ToYUY2Row = I422ToYUY2Row_NEON;
1326
    }
1327
  }
1328
#endif
1329
#if defined(HAS_I422TOYUY2ROW_LSX)
1330
  if (TestCpuFlag(kCpuHasLSX)) {
1331
    I422ToYUY2Row = I422ToYUY2Row_Any_LSX;
1332
    if (IS_ALIGNED(width, 16)) {
1333
      I422ToYUY2Row = I422ToYUY2Row_LSX;
1334
    }
1335
  }
1336
#endif
1337
#if defined(HAS_I422TOYUY2ROW_LASX)
1338
  if (TestCpuFlag(kCpuHasLASX)) {
1339
    I422ToYUY2Row = I422ToYUY2Row_Any_LASX;
1340
    if (IS_ALIGNED(width, 32)) {
1341
      I422ToYUY2Row = I422ToYUY2Row_LASX;
1342
    }
1343
  }
1344
#endif
1345
1346
0
  {
1347
    // Allocate a rows of yuv.
1348
0
    align_buffer_64(row_y, ((width + 63) & ~63) * 2);
1349
0
    uint8_t* row_u = row_y + ((width + 63) & ~63);
1350
0
    uint8_t* row_v = row_u + ((width + 63) & ~63) / 2;
1351
0
    if (!row_y)
1352
0
      return 1;
1353
1354
0
    for (y = 0; y < height; ++y) {
1355
0
      ARGBToUVRow(src_argb, 0, row_u, row_v, width);
1356
0
      ARGBToYRow(src_argb, row_y, width);
1357
0
      I422ToYUY2Row(row_y, row_u, row_v, dst_yuy2, width);
1358
0
      src_argb += src_stride_argb;
1359
0
      dst_yuy2 += dst_stride_yuy2;
1360
0
    }
1361
1362
0
    free_aligned_buffer_64(row_y);
1363
0
  }
1364
0
  return 0;
1365
0
}
1366
1367
// Convert ARGB to UYVY.
1368
LIBYUV_API
1369
int ARGBToUYVY(const uint8_t* src_argb,
1370
               int src_stride_argb,
1371
               uint8_t* dst_uyvy,
1372
               int dst_stride_uyvy,
1373
               int width,
1374
0
               int height) {
1375
0
  int y;
1376
0
  void (*ARGBToUVRow)(const uint8_t* src_argb, int src_stride_argb,
1377
0
                      uint8_t* dst_u, uint8_t* dst_v, int width) =
1378
0
      ARGBToUVRow_C;
1379
0
  void (*ARGBToYRow)(const uint8_t* src_argb, uint8_t* dst_y, int width) =
1380
0
      ARGBToYRow_C;
1381
0
  void (*I422ToUYVYRow)(const uint8_t* src_y, const uint8_t* src_u,
1382
0
                        const uint8_t* src_v, uint8_t* dst_uyvy, int width) =
1383
0
      I422ToUYVYRow_C;
1384
1385
0
  if (!src_argb || !dst_uyvy || width <= 0 || height == 0) {
1386
0
    return -1;
1387
0
  }
1388
  // Negative height means invert the image.
1389
0
  if (height < 0) {
1390
0
    height = -height;
1391
0
    dst_uyvy = dst_uyvy + (height - 1) * dst_stride_uyvy;
1392
0
    dst_stride_uyvy = -dst_stride_uyvy;
1393
0
  }
1394
  // Coalesce rows.
1395
0
  if (src_stride_argb == width * 4 && dst_stride_uyvy == width * 2) {
1396
0
    width *= height;
1397
0
    height = 1;
1398
0
    src_stride_argb = dst_stride_uyvy = 0;
1399
0
  }
1400
0
#if defined(HAS_ARGBTOYROW_SSSE3)
1401
0
  if (TestCpuFlag(kCpuHasSSSE3)) {
1402
0
    ARGBToYRow = ARGBToYRow_Any_SSSE3;
1403
0
    if (IS_ALIGNED(width, 16)) {
1404
0
      ARGBToYRow = ARGBToYRow_SSSE3;
1405
0
    }
1406
0
  }
1407
0
#endif
1408
0
#if defined(HAS_ARGBTOUVROW_SSSE3)
1409
0
  if (TestCpuFlag(kCpuHasSSSE3)) {
1410
0
    ARGBToUVRow = ARGBToUVRow_Any_SSSE3;
1411
0
    if (IS_ALIGNED(width, 16)) {
1412
0
      ARGBToUVRow = ARGBToUVRow_SSSE3;
1413
0
    }
1414
0
  }
1415
0
#endif
1416
0
#if defined(HAS_ARGBTOYROW_AVX2)
1417
0
  if (TestCpuFlag(kCpuHasAVX2)) {
1418
0
    ARGBToYRow = ARGBToYRow_Any_AVX2;
1419
0
    if (IS_ALIGNED(width, 32)) {
1420
0
      ARGBToYRow = ARGBToYRow_AVX2;
1421
0
    }
1422
0
  }
1423
0
#endif
1424
0
#if defined(HAS_ARGBTOUVROW_AVX2)
1425
0
  if (TestCpuFlag(kCpuHasAVX2)) {
1426
0
    ARGBToUVRow = ARGBToUVRow_Any_AVX2;
1427
0
    if (IS_ALIGNED(width, 32)) {
1428
0
      ARGBToUVRow = ARGBToUVRow_AVX2;
1429
0
    }
1430
0
  }
1431
0
#endif
1432
#if defined(HAS_ARGBTOYROW_NEON)
1433
  if (TestCpuFlag(kCpuHasNEON)) {
1434
    ARGBToYRow = ARGBToYRow_Any_NEON;
1435
    if (IS_ALIGNED(width, 16)) {
1436
      ARGBToYRow = ARGBToYRow_NEON;
1437
    }
1438
  }
1439
#endif
1440
#if defined(HAS_ARGBTOYROW_NEON_DOTPROD)
1441
  if (TestCpuFlag(kCpuHasNeonDotProd)) {
1442
    ARGBToYRow = ARGBToYRow_Any_NEON_DotProd;
1443
    if (IS_ALIGNED(width, 16)) {
1444
      ARGBToYRow = ARGBToYRow_NEON_DotProd;
1445
    }
1446
  }
1447
#endif
1448
#if defined(HAS_ARGBTOUVROW_NEON)
1449
  if (TestCpuFlag(kCpuHasNEON)) {
1450
    ARGBToUVRow = ARGBToUVRow_Any_NEON;
1451
    if (IS_ALIGNED(width, 16)) {
1452
      ARGBToUVRow = ARGBToUVRow_NEON;
1453
    }
1454
  }
1455
#endif
1456
#if defined(HAS_ARGBTOUVROW_NEON_I8MM)
1457
  if (TestCpuFlag(kCpuHasNeonI8MM)) {
1458
    ARGBToUVRow = ARGBToUVRow_Any_NEON_I8MM;
1459
    if (IS_ALIGNED(width, 16)) {
1460
      ARGBToUVRow = ARGBToUVRow_NEON_I8MM;
1461
    }
1462
  }
1463
#endif
1464
#if defined(HAS_ARGBTOUVROW_SVE2)
1465
  if (TestCpuFlag(kCpuHasSVE2)) {
1466
    ARGBToUVRow = ARGBToUVRow_Any_SVE2;
1467
    if (IS_ALIGNED(width, 2)) {
1468
      ARGBToUVRow = ARGBToUVRow_SVE2;
1469
    }
1470
  }
1471
#endif
1472
#if defined(HAS_ARGBTOUVROW_SME)
1473
  if (TestCpuFlag(kCpuHasSME)) {
1474
    ARGBToUVRow = ARGBToUVRow_Any_SME;
1475
    if (IS_ALIGNED(width, 2)) {
1476
      ARGBToUVRow = ARGBToUVRow_SME;
1477
    }
1478
  }
1479
#endif
1480
#if defined(HAS_ARGBTOYROW_LSX)
1481
  if (TestCpuFlag(kCpuHasLSX)) {
1482
    ARGBToYRow = ARGBToYRow_Any_LSX;
1483
    if (IS_ALIGNED(width, 16)) {
1484
      ARGBToYRow = ARGBToYRow_LSX;
1485
    }
1486
  }
1487
#endif
1488
#if defined(HAS_ARGBTOYROW_LSX) && defined(HAS_ARGBTOUVROW_LSX)
1489
  if (TestCpuFlag(kCpuHasLSX)) {
1490
    ARGBToYRow = ARGBToYRow_Any_LSX;
1491
    ARGBToUVRow = ARGBToUVRow_Any_LSX;
1492
    if (IS_ALIGNED(width, 16)) {
1493
      ARGBToYRow = ARGBToYRow_LSX;
1494
      ARGBToUVRow = ARGBToUVRow_LSX;
1495
    }
1496
  }
1497
#endif
1498
#if defined(HAS_ARGBTOYROW_LASX) && defined(HAS_ARGBTOUVROW_LASX)
1499
  if (TestCpuFlag(kCpuHasLASX)) {
1500
    ARGBToYRow = ARGBToYRow_Any_LASX;
1501
    ARGBToUVRow = ARGBToUVRow_Any_LASX;
1502
    if (IS_ALIGNED(width, 32)) {
1503
      ARGBToYRow = ARGBToYRow_LASX;
1504
      ARGBToUVRow = ARGBToUVRow_LASX;
1505
    }
1506
  }
1507
#endif
1508
#if defined(HAS_ARGBTOYROW_RVV)
1509
  if (TestCpuFlag(kCpuHasRVV)) {
1510
    ARGBToYRow = ARGBToYRow_RVV;
1511
  }
1512
#endif
1513
0
#if defined(HAS_I422TOUYVYROW_SSE2)
1514
0
  if (TestCpuFlag(kCpuHasSSE2)) {
1515
0
    I422ToUYVYRow = I422ToUYVYRow_Any_SSE2;
1516
0
    if (IS_ALIGNED(width, 16)) {
1517
0
      I422ToUYVYRow = I422ToUYVYRow_SSE2;
1518
0
    }
1519
0
  }
1520
0
#endif
1521
0
#if defined(HAS_I422TOUYVYROW_AVX2)
1522
0
  if (TestCpuFlag(kCpuHasAVX2)) {
1523
0
    I422ToUYVYRow = I422ToUYVYRow_Any_AVX2;
1524
0
    if (IS_ALIGNED(width, 32)) {
1525
0
      I422ToUYVYRow = I422ToUYVYRow_AVX2;
1526
0
    }
1527
0
  }
1528
0
#endif
1529
#if defined(HAS_I422TOUYVYROW_NEON)
1530
  if (TestCpuFlag(kCpuHasNEON)) {
1531
    I422ToUYVYRow = I422ToUYVYRow_Any_NEON;
1532
    if (IS_ALIGNED(width, 16)) {
1533
      I422ToUYVYRow = I422ToUYVYRow_NEON;
1534
    }
1535
  }
1536
#endif
1537
#if defined(HAS_I422TOUYVYROW_LSX)
1538
  if (TestCpuFlag(kCpuHasLSX)) {
1539
    I422ToUYVYRow = I422ToUYVYRow_Any_LSX;
1540
    if (IS_ALIGNED(width, 16)) {
1541
      I422ToUYVYRow = I422ToUYVYRow_LSX;
1542
    }
1543
  }
1544
#endif
1545
#if defined(HAS_I422TOUYVYROW_LASX)
1546
  if (TestCpuFlag(kCpuHasLASX)) {
1547
    I422ToUYVYRow = I422ToUYVYRow_Any_LASX;
1548
    if (IS_ALIGNED(width, 32)) {
1549
      I422ToUYVYRow = I422ToUYVYRow_LASX;
1550
    }
1551
  }
1552
#endif
1553
1554
0
  {
1555
    // Allocate a rows of yuv.
1556
0
    align_buffer_64(row_y, ((width + 63) & ~63) * 2);
1557
0
    uint8_t* row_u = row_y + ((width + 63) & ~63);
1558
0
    uint8_t* row_v = row_u + ((width + 63) & ~63) / 2;
1559
0
    if (!row_y)
1560
0
      return 1;
1561
1562
0
    for (y = 0; y < height; ++y) {
1563
0
      ARGBToUVRow(src_argb, 0, row_u, row_v, width);
1564
0
      ARGBToYRow(src_argb, row_y, width);
1565
0
      I422ToUYVYRow(row_y, row_u, row_v, dst_uyvy, width);
1566
0
      src_argb += src_stride_argb;
1567
0
      dst_uyvy += dst_stride_uyvy;
1568
0
    }
1569
1570
0
    free_aligned_buffer_64(row_y);
1571
0
  }
1572
0
  return 0;
1573
0
}
1574
1575
// Convert ARGB to I400.
1576
LIBYUV_API
1577
int ARGBToI400(const uint8_t* src_argb,
1578
               int src_stride_argb,
1579
               uint8_t* dst_y,
1580
               int dst_stride_y,
1581
               int width,
1582
0
               int height) {
1583
0
  int y;
1584
0
  void (*ARGBToYRow)(const uint8_t* src_argb, uint8_t* dst_y, int width) =
1585
0
      ARGBToYRow_C;
1586
0
  if (!src_argb || !dst_y || width <= 0 || height == 0) {
1587
0
    return -1;
1588
0
  }
1589
0
  if (height < 0) {
1590
0
    height = -height;
1591
0
    src_argb = src_argb + (height - 1) * src_stride_argb;
1592
0
    src_stride_argb = -src_stride_argb;
1593
0
  }
1594
  // Coalesce rows.
1595
0
  if (src_stride_argb == width * 4 && dst_stride_y == width) {
1596
0
    width *= height;
1597
0
    height = 1;
1598
0
    src_stride_argb = dst_stride_y = 0;
1599
0
  }
1600
0
#if defined(HAS_ARGBTOYROW_SSSE3)
1601
0
  if (TestCpuFlag(kCpuHasSSSE3)) {
1602
0
    ARGBToYRow = ARGBToYRow_Any_SSSE3;
1603
0
    if (IS_ALIGNED(width, 16)) {
1604
0
      ARGBToYRow = ARGBToYRow_SSSE3;
1605
0
    }
1606
0
  }
1607
0
#endif
1608
0
#if defined(HAS_ARGBTOYROW_AVX2)
1609
0
  if (TestCpuFlag(kCpuHasAVX2)) {
1610
0
    ARGBToYRow = ARGBToYRow_Any_AVX2;
1611
0
    if (IS_ALIGNED(width, 32)) {
1612
0
      ARGBToYRow = ARGBToYRow_AVX2;
1613
0
    }
1614
0
  }
1615
0
#endif
1616
#if defined(HAS_ARGBTOYROW_NEON)
1617
  if (TestCpuFlag(kCpuHasNEON)) {
1618
    ARGBToYRow = ARGBToYRow_Any_NEON;
1619
    if (IS_ALIGNED(width, 16)) {
1620
      ARGBToYRow = ARGBToYRow_NEON;
1621
    }
1622
  }
1623
#endif
1624
#if defined(HAS_ARGBTOYROW_NEON_DOTPROD)
1625
  if (TestCpuFlag(kCpuHasNeonDotProd)) {
1626
    ARGBToYRow = ARGBToYRow_Any_NEON_DotProd;
1627
    if (IS_ALIGNED(width, 16)) {
1628
      ARGBToYRow = ARGBToYRow_NEON_DotProd;
1629
    }
1630
  }
1631
#endif
1632
#if defined(HAS_ARGBTOYROW_LSX)
1633
  if (TestCpuFlag(kCpuHasLSX)) {
1634
    ARGBToYRow = ARGBToYRow_Any_LSX;
1635
    if (IS_ALIGNED(width, 16)) {
1636
      ARGBToYRow = ARGBToYRow_LSX;
1637
    }
1638
  }
1639
#endif
1640
#if defined(HAS_ARGBTOYROW_LASX)
1641
  if (TestCpuFlag(kCpuHasLASX)) {
1642
    ARGBToYRow = ARGBToYRow_Any_LASX;
1643
    if (IS_ALIGNED(width, 32)) {
1644
      ARGBToYRow = ARGBToYRow_LASX;
1645
    }
1646
  }
1647
#endif
1648
#if defined(HAS_ARGBTOYROW_RVV)
1649
  if (TestCpuFlag(kCpuHasRVV)) {
1650
    ARGBToYRow = ARGBToYRow_RVV;
1651
  }
1652
#endif
1653
1654
0
  for (y = 0; y < height; ++y) {
1655
0
    ARGBToYRow(src_argb, dst_y, width);
1656
0
    src_argb += src_stride_argb;
1657
0
    dst_y += dst_stride_y;
1658
0
  }
1659
0
  return 0;
1660
0
}
1661
1662
#ifndef __riscv
1663
// Shuffle table for converting ARGB to RGBA.
1664
static const uvec8 kShuffleMaskARGBToRGBA = {
1665
    3u, 0u, 1u, 2u, 7u, 4u, 5u, 6u, 11u, 8u, 9u, 10u, 15u, 12u, 13u, 14u};
1666
1667
// Convert ARGB to RGBA.
1668
LIBYUV_API
1669
int ARGBToRGBA(const uint8_t* src_argb,
1670
               int src_stride_argb,
1671
               uint8_t* dst_rgba,
1672
               int dst_stride_rgba,
1673
               int width,
1674
0
               int height) {
1675
0
  return ARGBShuffle(src_argb, src_stride_argb, dst_rgba, dst_stride_rgba,
1676
0
                     (const uint8_t*)(&kShuffleMaskARGBToRGBA), width, height);
1677
0
}
1678
#else
1679
// Convert ARGB to RGBA.
1680
LIBYUV_API
1681
int ARGBToRGBA(const uint8_t* src_argb,
1682
               int src_stride_argb,
1683
               uint8_t* dst_rgba,
1684
               int dst_stride_rgba,
1685
               int width,
1686
               int height) {
1687
  int y;
1688
  void (*ARGBToRGBARow)(const uint8_t* src_argb, uint8_t* dst_rgba, int width) =
1689
      ARGBToRGBARow_C;
1690
  if (!src_argb || !dst_rgba || width <= 0 || height == 0) {
1691
    return -1;
1692
  }
1693
  if (height < 0) {
1694
    height = -height;
1695
    src_argb = src_argb + (height - 1) * src_stride_argb;
1696
    src_stride_argb = -src_stride_argb;
1697
  }
1698
  // Coalesce rows.
1699
  if (src_stride_argb == width * 4 && dst_stride_rgba == width * 4) {
1700
    width *= height;
1701
    height = 1;
1702
    src_stride_argb = dst_stride_rgba = 0;
1703
  }
1704
1705
#if defined(HAS_ARGBTORGBAROW_RVV)
1706
  if (TestCpuFlag(kCpuHasRVV)) {
1707
    ARGBToRGBARow = ARGBToRGBARow_RVV;
1708
  }
1709
#endif
1710
1711
  for (y = 0; y < height; ++y) {
1712
    ARGBToRGBARow(src_argb, dst_rgba, width);
1713
    src_argb += src_stride_argb;
1714
    dst_rgba += dst_stride_rgba;
1715
  }
1716
  return 0;
1717
}
1718
#endif
1719
1720
// Convert ARGB To RGB24.
1721
LIBYUV_API
1722
int ARGBToRGB24(const uint8_t* src_argb,
1723
                int src_stride_argb,
1724
                uint8_t* dst_rgb24,
1725
                int dst_stride_rgb24,
1726
                int width,
1727
0
                int height) {
1728
0
  int y;
1729
0
  void (*ARGBToRGB24Row)(const uint8_t* src_argb, uint8_t* dst_rgb, int width) =
1730
0
      ARGBToRGB24Row_C;
1731
0
  if (!src_argb || !dst_rgb24 || width <= 0 || height == 0) {
1732
0
    return -1;
1733
0
  }
1734
0
  if (height < 0) {
1735
0
    height = -height;
1736
0
    src_argb = src_argb + (height - 1) * src_stride_argb;
1737
0
    src_stride_argb = -src_stride_argb;
1738
0
  }
1739
  // Coalesce rows.
1740
0
  if (src_stride_argb == width * 4 && dst_stride_rgb24 == width * 3) {
1741
0
    width *= height;
1742
0
    height = 1;
1743
0
    src_stride_argb = dst_stride_rgb24 = 0;
1744
0
  }
1745
0
#if defined(HAS_ARGBTORGB24ROW_SSSE3)
1746
0
  if (TestCpuFlag(kCpuHasSSSE3)) {
1747
0
    ARGBToRGB24Row = ARGBToRGB24Row_Any_SSSE3;
1748
0
    if (IS_ALIGNED(width, 16)) {
1749
0
      ARGBToRGB24Row = ARGBToRGB24Row_SSSE3;
1750
0
    }
1751
0
  }
1752
0
#endif
1753
0
#if defined(HAS_ARGBTORGB24ROW_AVX2)
1754
0
  if (TestCpuFlag(kCpuHasAVX2)) {
1755
0
    ARGBToRGB24Row = ARGBToRGB24Row_Any_AVX2;
1756
0
    if (IS_ALIGNED(width, 32)) {
1757
0
      ARGBToRGB24Row = ARGBToRGB24Row_AVX2;
1758
0
    }
1759
0
  }
1760
0
#endif
1761
0
#if defined(HAS_ARGBTORGB24ROW_AVX512VBMI)
1762
0
  if (TestCpuFlag(kCpuHasAVX512VBMI)) {
1763
0
    ARGBToRGB24Row = ARGBToRGB24Row_Any_AVX512VBMI;
1764
0
    if (IS_ALIGNED(width, 32)) {
1765
0
      ARGBToRGB24Row = ARGBToRGB24Row_AVX512VBMI;
1766
0
    }
1767
0
  }
1768
0
#endif
1769
#if defined(HAS_ARGBTORGB24ROW_NEON)
1770
  if (TestCpuFlag(kCpuHasNEON)) {
1771
    ARGBToRGB24Row = ARGBToRGB24Row_Any_NEON;
1772
    if (IS_ALIGNED(width, 16)) {
1773
      ARGBToRGB24Row = ARGBToRGB24Row_NEON;
1774
    }
1775
  }
1776
#endif
1777
#if defined(HAS_ARGBTORGB24ROW_SVE2)
1778
  if (TestCpuFlag(kCpuHasSVE2)) {
1779
    ARGBToRGB24Row = ARGBToRGB24Row_SVE2;
1780
  }
1781
#endif
1782
#if defined(HAS_ARGBTORGB24ROW_LSX)
1783
  if (TestCpuFlag(kCpuHasLSX)) {
1784
    ARGBToRGB24Row = ARGBToRGB24Row_Any_LSX;
1785
    if (IS_ALIGNED(width, 16)) {
1786
      ARGBToRGB24Row = ARGBToRGB24Row_LSX;
1787
    }
1788
  }
1789
#endif
1790
#if defined(HAS_ARGBTORGB24ROW_LASX)
1791
  if (TestCpuFlag(kCpuHasLASX)) {
1792
    ARGBToRGB24Row = ARGBToRGB24Row_Any_LASX;
1793
    if (IS_ALIGNED(width, 32)) {
1794
      ARGBToRGB24Row = ARGBToRGB24Row_LASX;
1795
    }
1796
  }
1797
#endif
1798
#if defined(HAS_ARGBTORGB24ROW_RVV)
1799
  if (TestCpuFlag(kCpuHasRVV)) {
1800
    ARGBToRGB24Row = ARGBToRGB24Row_RVV;
1801
  }
1802
#endif
1803
1804
0
  for (y = 0; y < height; ++y) {
1805
0
    ARGBToRGB24Row(src_argb, dst_rgb24, width);
1806
0
    src_argb += src_stride_argb;
1807
0
    dst_rgb24 += dst_stride_rgb24;
1808
0
  }
1809
0
  return 0;
1810
0
}
1811
1812
// Convert ARGB To RAW.
1813
LIBYUV_API
1814
int ARGBToRAW(const uint8_t* src_argb,
1815
              int src_stride_argb,
1816
              uint8_t* dst_raw,
1817
              int dst_stride_raw,
1818
              int width,
1819
0
              int height) {
1820
0
  int y;
1821
0
  void (*ARGBToRAWRow)(const uint8_t* src_argb, uint8_t* dst_rgb, int width) =
1822
0
      ARGBToRAWRow_C;
1823
0
  if (!src_argb || !dst_raw || width <= 0 || height == 0) {
1824
0
    return -1;
1825
0
  }
1826
0
  if (height < 0) {
1827
0
    height = -height;
1828
0
    src_argb = src_argb + (height - 1) * src_stride_argb;
1829
0
    src_stride_argb = -src_stride_argb;
1830
0
  }
1831
  // Coalesce rows.
1832
0
  if (src_stride_argb == width * 4 && dst_stride_raw == width * 3) {
1833
0
    width *= height;
1834
0
    height = 1;
1835
0
    src_stride_argb = dst_stride_raw = 0;
1836
0
  }
1837
0
#if defined(HAS_ARGBTORAWROW_SSSE3)
1838
0
  if (TestCpuFlag(kCpuHasSSSE3)) {
1839
0
    ARGBToRAWRow = ARGBToRAWRow_Any_SSSE3;
1840
0
    if (IS_ALIGNED(width, 16)) {
1841
0
      ARGBToRAWRow = ARGBToRAWRow_SSSE3;
1842
0
    }
1843
0
  }
1844
0
#endif
1845
0
#if defined(HAS_ARGBTORAWROW_AVX2)
1846
0
  if (TestCpuFlag(kCpuHasAVX2)) {
1847
0
    ARGBToRAWRow = ARGBToRAWRow_Any_AVX2;
1848
0
    if (IS_ALIGNED(width, 32)) {
1849
0
      ARGBToRAWRow = ARGBToRAWRow_AVX2;
1850
0
    }
1851
0
  }
1852
0
#endif
1853
#if defined(HAS_ARGBTORAWROW_NEON)
1854
  if (TestCpuFlag(kCpuHasNEON)) {
1855
    ARGBToRAWRow = ARGBToRAWRow_Any_NEON;
1856
    if (IS_ALIGNED(width, 8)) {
1857
      ARGBToRAWRow = ARGBToRAWRow_NEON;
1858
    }
1859
  }
1860
#endif
1861
#if defined(HAS_ARGBTORAWROW_SVE2)
1862
  if (TestCpuFlag(kCpuHasSVE2)) {
1863
    ARGBToRAWRow = ARGBToRAWRow_SVE2;
1864
  }
1865
#endif
1866
#if defined(HAS_ARGBTORAWROW_LSX)
1867
  if (TestCpuFlag(kCpuHasLSX)) {
1868
    ARGBToRAWRow = ARGBToRAWRow_Any_LSX;
1869
    if (IS_ALIGNED(width, 16)) {
1870
      ARGBToRAWRow = ARGBToRAWRow_LSX;
1871
    }
1872
  }
1873
#endif
1874
#if defined(HAS_ARGBTORAWROW_LASX)
1875
  if (TestCpuFlag(kCpuHasLASX)) {
1876
    ARGBToRAWRow = ARGBToRAWRow_Any_LASX;
1877
    if (IS_ALIGNED(width, 32)) {
1878
      ARGBToRAWRow = ARGBToRAWRow_LASX;
1879
    }
1880
  }
1881
#endif
1882
#if defined(HAS_ARGBTORAWROW_RVV)
1883
  if (TestCpuFlag(kCpuHasRVV)) {
1884
    ARGBToRAWRow = ARGBToRAWRow_RVV;
1885
  }
1886
#endif
1887
1888
0
  for (y = 0; y < height; ++y) {
1889
0
    ARGBToRAWRow(src_argb, dst_raw, width);
1890
0
    src_argb += src_stride_argb;
1891
0
    dst_raw += dst_stride_raw;
1892
0
  }
1893
0
  return 0;
1894
0
}
1895
1896
// Ordered 8x8 dither for 888 to 565.  Values from 0 to 7.
1897
static const uint8_t kDither565_4x4[16] = {
1898
    0, 4, 1, 5, 6, 2, 7, 3, 1, 5, 0, 4, 7, 3, 6, 2,
1899
};
1900
1901
// Convert ARGB To RGB565 with 4x4 dither matrix (16 bytes).
1902
LIBYUV_API
1903
int ARGBToRGB565Dither(const uint8_t* src_argb,
1904
                       int src_stride_argb,
1905
                       uint8_t* dst_rgb565,
1906
                       int dst_stride_rgb565,
1907
                       const uint8_t* dither4x4,
1908
                       int width,
1909
0
                       int height) {
1910
0
  int y;
1911
0
  void (*ARGBToRGB565DitherRow)(const uint8_t* src_argb, uint8_t* dst_rgb,
1912
0
                                uint32_t dither4, int width) =
1913
0
      ARGBToRGB565DitherRow_C;
1914
0
  if (!src_argb || !dst_rgb565 || width <= 0 || height == 0) {
1915
0
    return -1;
1916
0
  }
1917
0
  if (height < 0) {
1918
0
    height = -height;
1919
0
    src_argb = src_argb + (height - 1) * src_stride_argb;
1920
0
    src_stride_argb = -src_stride_argb;
1921
0
  }
1922
0
  if (!dither4x4) {
1923
0
    dither4x4 = kDither565_4x4;
1924
0
  }
1925
0
#if defined(HAS_ARGBTORGB565DITHERROW_SSE2)
1926
0
  if (TestCpuFlag(kCpuHasSSE2)) {
1927
0
    ARGBToRGB565DitherRow = ARGBToRGB565DitherRow_Any_SSE2;
1928
0
    if (IS_ALIGNED(width, 4)) {
1929
0
      ARGBToRGB565DitherRow = ARGBToRGB565DitherRow_SSE2;
1930
0
    }
1931
0
  }
1932
0
#endif
1933
0
#if defined(HAS_ARGBTORGB565DITHERROW_AVX2)
1934
0
  if (TestCpuFlag(kCpuHasAVX2)) {
1935
0
    ARGBToRGB565DitherRow = ARGBToRGB565DitherRow_Any_AVX2;
1936
0
    if (IS_ALIGNED(width, 8)) {
1937
0
      ARGBToRGB565DitherRow = ARGBToRGB565DitherRow_AVX2;
1938
0
    }
1939
0
  }
1940
0
#endif
1941
#if defined(HAS_ARGBTORGB565DITHERROW_NEON)
1942
  if (TestCpuFlag(kCpuHasNEON)) {
1943
    ARGBToRGB565DitherRow = ARGBToRGB565DitherRow_Any_NEON;
1944
    if (IS_ALIGNED(width, 8)) {
1945
      ARGBToRGB565DitherRow = ARGBToRGB565DitherRow_NEON;
1946
    }
1947
  }
1948
#endif
1949
#if defined(HAS_ARGBTORGB565DITHERROW_SVE2)
1950
  if (TestCpuFlag(kCpuHasSVE2)) {
1951
    ARGBToRGB565DitherRow = ARGBToRGB565DitherRow_SVE2;
1952
  }
1953
#endif
1954
#if defined(HAS_ARGBTORGB565DITHERROW_LSX)
1955
  if (TestCpuFlag(kCpuHasLSX)) {
1956
    ARGBToRGB565DitherRow = ARGBToRGB565DitherRow_Any_LSX;
1957
    if (IS_ALIGNED(width, 8)) {
1958
      ARGBToRGB565DitherRow = ARGBToRGB565DitherRow_LSX;
1959
    }
1960
  }
1961
#endif
1962
#if defined(HAS_ARGBTORGB565DITHERROW_LASX)
1963
  if (TestCpuFlag(kCpuHasLASX)) {
1964
    ARGBToRGB565DitherRow = ARGBToRGB565DitherRow_Any_LASX;
1965
    if (IS_ALIGNED(width, 16)) {
1966
      ARGBToRGB565DitherRow = ARGBToRGB565DitherRow_LASX;
1967
    }
1968
  }
1969
#endif
1970
1971
0
  for (y = 0; y < height; ++y) {
1972
0
    ARGBToRGB565DitherRow(src_argb, dst_rgb565,
1973
0
                          *(const uint32_t*)(dither4x4 + ((y & 3) << 2)),
1974
0
                          width);
1975
0
    src_argb += src_stride_argb;
1976
0
    dst_rgb565 += dst_stride_rgb565;
1977
0
  }
1978
0
  return 0;
1979
0
}
1980
1981
// Convert ARGB To RGB565.
1982
// TODO(fbarchard): Consider using dither function low level with zeros.
1983
LIBYUV_API
1984
int ARGBToRGB565(const uint8_t* src_argb,
1985
                 int src_stride_argb,
1986
                 uint8_t* dst_rgb565,
1987
                 int dst_stride_rgb565,
1988
                 int width,
1989
0
                 int height) {
1990
0
  int y;
1991
0
  void (*ARGBToRGB565Row)(const uint8_t* src_argb, uint8_t* dst_rgb,
1992
0
                          int width) = ARGBToRGB565Row_C;
1993
0
  if (!src_argb || !dst_rgb565 || width <= 0 || height == 0) {
1994
0
    return -1;
1995
0
  }
1996
0
  if (height < 0) {
1997
0
    height = -height;
1998
0
    src_argb = src_argb + (height - 1) * src_stride_argb;
1999
0
    src_stride_argb = -src_stride_argb;
2000
0
  }
2001
  // Coalesce rows.
2002
0
  if (src_stride_argb == width * 4 && dst_stride_rgb565 == width * 2) {
2003
0
    width *= height;
2004
0
    height = 1;
2005
0
    src_stride_argb = dst_stride_rgb565 = 0;
2006
0
  }
2007
0
#if defined(HAS_ARGBTORGB565ROW_SSE2)
2008
0
  if (TestCpuFlag(kCpuHasSSE2)) {
2009
0
    ARGBToRGB565Row = ARGBToRGB565Row_Any_SSE2;
2010
0
    if (IS_ALIGNED(width, 4)) {
2011
0
      ARGBToRGB565Row = ARGBToRGB565Row_SSE2;
2012
0
    }
2013
0
  }
2014
0
#endif
2015
#if defined(HAS_ARGBTORGB565ROW_AVX2)
2016
  if (TestCpuFlag(kCpuHasAVX2)) {
2017
    ARGBToRGB565Row = ARGBToRGB565Row_Any_AVX2;
2018
    if (IS_ALIGNED(width, 8)) {
2019
      ARGBToRGB565Row = ARGBToRGB565Row_AVX2;
2020
    }
2021
  }
2022
#endif
2023
#if defined(HAS_ARGBTORGB565ROW_NEON)
2024
  if (TestCpuFlag(kCpuHasNEON)) {
2025
    ARGBToRGB565Row = ARGBToRGB565Row_Any_NEON;
2026
    if (IS_ALIGNED(width, 8)) {
2027
      ARGBToRGB565Row = ARGBToRGB565Row_NEON;
2028
    }
2029
  }
2030
#endif
2031
#if defined(HAS_ARGBTORGB565ROW_SVE2)
2032
  if (TestCpuFlag(kCpuHasSVE2)) {
2033
    ARGBToRGB565Row = ARGBToRGB565Row_SVE2;
2034
  }
2035
#endif
2036
#if defined(HAS_ARGBTORGB565ROW_LSX)
2037
  if (TestCpuFlag(kCpuHasLSX)) {
2038
    ARGBToRGB565Row = ARGBToRGB565Row_Any_LSX;
2039
    if (IS_ALIGNED(width, 8)) {
2040
      ARGBToRGB565Row = ARGBToRGB565Row_LSX;
2041
    }
2042
  }
2043
#endif
2044
2045
#if defined(HAS_ARGBTORGB565ROW_LASX)
2046
  if (TestCpuFlag(kCpuHasLASX)) {
2047
    ARGBToRGB565Row = ARGBToRGB565Row_Any_LASX;
2048
    if (IS_ALIGNED(width, 16)) {
2049
      ARGBToRGB565Row = ARGBToRGB565Row_LASX;
2050
    }
2051
  }
2052
#endif
2053
2054
0
  for (y = 0; y < height; ++y) {
2055
0
    ARGBToRGB565Row(src_argb, dst_rgb565, width);
2056
0
    src_argb += src_stride_argb;
2057
0
    dst_rgb565 += dst_stride_rgb565;
2058
0
  }
2059
0
  return 0;
2060
0
}
2061
2062
// Convert ARGB To ARGB1555.
2063
LIBYUV_API
2064
int ARGBToARGB1555(const uint8_t* src_argb,
2065
                   int src_stride_argb,
2066
                   uint8_t* dst_argb1555,
2067
                   int dst_stride_argb1555,
2068
                   int width,
2069
0
                   int height) {
2070
0
  int y;
2071
0
  void (*ARGBToARGB1555Row)(const uint8_t* src_argb, uint8_t* dst_rgb,
2072
0
                            int width) = ARGBToARGB1555Row_C;
2073
0
  if (!src_argb || !dst_argb1555 || width <= 0 || height == 0) {
2074
0
    return -1;
2075
0
  }
2076
0
  if (height < 0) {
2077
0
    height = -height;
2078
0
    src_argb = src_argb + (height - 1) * src_stride_argb;
2079
0
    src_stride_argb = -src_stride_argb;
2080
0
  }
2081
  // Coalesce rows.
2082
0
  if (src_stride_argb == width * 4 && dst_stride_argb1555 == width * 2) {
2083
0
    width *= height;
2084
0
    height = 1;
2085
0
    src_stride_argb = dst_stride_argb1555 = 0;
2086
0
  }
2087
0
#if defined(HAS_ARGBTOARGB1555ROW_SSE2)
2088
0
  if (TestCpuFlag(kCpuHasSSE2)) {
2089
0
    ARGBToARGB1555Row = ARGBToARGB1555Row_Any_SSE2;
2090
0
    if (IS_ALIGNED(width, 4)) {
2091
0
      ARGBToARGB1555Row = ARGBToARGB1555Row_SSE2;
2092
0
    }
2093
0
  }
2094
0
#endif
2095
#if defined(HAS_ARGBTOARGB1555ROW_AVX2)
2096
  if (TestCpuFlag(kCpuHasAVX2)) {
2097
    ARGBToARGB1555Row = ARGBToARGB1555Row_Any_AVX2;
2098
    if (IS_ALIGNED(width, 8)) {
2099
      ARGBToARGB1555Row = ARGBToARGB1555Row_AVX2;
2100
    }
2101
  }
2102
#endif
2103
#if defined(HAS_ARGBTOARGB1555ROW_NEON)
2104
  if (TestCpuFlag(kCpuHasNEON)) {
2105
    ARGBToARGB1555Row = ARGBToARGB1555Row_Any_NEON;
2106
    if (IS_ALIGNED(width, 8)) {
2107
      ARGBToARGB1555Row = ARGBToARGB1555Row_NEON;
2108
    }
2109
  }
2110
#endif
2111
#if defined(HAS_ARGBTOARGB1555ROW_LSX)
2112
  if (TestCpuFlag(kCpuHasLSX)) {
2113
    ARGBToARGB1555Row = ARGBToARGB1555Row_Any_LSX;
2114
    if (IS_ALIGNED(width, 8)) {
2115
      ARGBToARGB1555Row = ARGBToARGB1555Row_LSX;
2116
    }
2117
  }
2118
#endif
2119
#if defined(HAS_ARGBTOARGB1555ROW_LASX)
2120
  if (TestCpuFlag(kCpuHasLASX)) {
2121
    ARGBToARGB1555Row = ARGBToARGB1555Row_Any_LASX;
2122
    if (IS_ALIGNED(width, 16)) {
2123
      ARGBToARGB1555Row = ARGBToARGB1555Row_LASX;
2124
    }
2125
  }
2126
#endif
2127
2128
0
  for (y = 0; y < height; ++y) {
2129
0
    ARGBToARGB1555Row(src_argb, dst_argb1555, width);
2130
0
    src_argb += src_stride_argb;
2131
0
    dst_argb1555 += dst_stride_argb1555;
2132
0
  }
2133
0
  return 0;
2134
0
}
2135
2136
// Convert ARGB To ARGB4444.
2137
LIBYUV_API
2138
int ARGBToARGB4444(const uint8_t* src_argb,
2139
                   int src_stride_argb,
2140
                   uint8_t* dst_argb4444,
2141
                   int dst_stride_argb4444,
2142
                   int width,
2143
0
                   int height) {
2144
0
  int y;
2145
0
  void (*ARGBToARGB4444Row)(const uint8_t* src_argb, uint8_t* dst_rgb,
2146
0
                            int width) = ARGBToARGB4444Row_C;
2147
0
  if (!src_argb || !dst_argb4444 || width <= 0 || height == 0) {
2148
0
    return -1;
2149
0
  }
2150
0
  if (height < 0) {
2151
0
    height = -height;
2152
0
    src_argb = src_argb + (height - 1) * src_stride_argb;
2153
0
    src_stride_argb = -src_stride_argb;
2154
0
  }
2155
  // Coalesce rows.
2156
0
  if (src_stride_argb == width * 4 && dst_stride_argb4444 == width * 2) {
2157
0
    width *= height;
2158
0
    height = 1;
2159
0
    src_stride_argb = dst_stride_argb4444 = 0;
2160
0
  }
2161
0
#if defined(HAS_ARGBTOARGB4444ROW_SSE2)
2162
0
  if (TestCpuFlag(kCpuHasSSE2)) {
2163
0
    ARGBToARGB4444Row = ARGBToARGB4444Row_Any_SSE2;
2164
0
    if (IS_ALIGNED(width, 4)) {
2165
0
      ARGBToARGB4444Row = ARGBToARGB4444Row_SSE2;
2166
0
    }
2167
0
  }
2168
0
#endif
2169
#if defined(HAS_ARGBTOARGB4444ROW_AVX2)
2170
  if (TestCpuFlag(kCpuHasAVX2)) {
2171
    ARGBToARGB4444Row = ARGBToARGB4444Row_Any_AVX2;
2172
    if (IS_ALIGNED(width, 8)) {
2173
      ARGBToARGB4444Row = ARGBToARGB4444Row_AVX2;
2174
    }
2175
  }
2176
#endif
2177
#if defined(HAS_ARGBTOARGB4444ROW_NEON)
2178
  if (TestCpuFlag(kCpuHasNEON)) {
2179
    ARGBToARGB4444Row = ARGBToARGB4444Row_Any_NEON;
2180
    if (IS_ALIGNED(width, 8)) {
2181
      ARGBToARGB4444Row = ARGBToARGB4444Row_NEON;
2182
    }
2183
  }
2184
#endif
2185
#if defined(HAS_ARGBTOARGB4444ROW_LSX)
2186
  if (TestCpuFlag(kCpuHasLSX)) {
2187
    ARGBToARGB4444Row = ARGBToARGB4444Row_Any_LSX;
2188
    if (IS_ALIGNED(width, 8)) {
2189
      ARGBToARGB4444Row = ARGBToARGB4444Row_LSX;
2190
    }
2191
  }
2192
#endif
2193
#if defined(HAS_ARGBTOARGB4444ROW_LASX)
2194
  if (TestCpuFlag(kCpuHasLASX)) {
2195
    ARGBToARGB4444Row = ARGBToARGB4444Row_Any_LASX;
2196
    if (IS_ALIGNED(width, 16)) {
2197
      ARGBToARGB4444Row = ARGBToARGB4444Row_LASX;
2198
    }
2199
  }
2200
#endif
2201
2202
0
  for (y = 0; y < height; ++y) {
2203
0
    ARGBToARGB4444Row(src_argb, dst_argb4444, width);
2204
0
    src_argb += src_stride_argb;
2205
0
    dst_argb4444 += dst_stride_argb4444;
2206
0
  }
2207
0
  return 0;
2208
0
}
2209
2210
// Convert ABGR To AR30.
2211
LIBYUV_API
2212
int ABGRToAR30(const uint8_t* src_abgr,
2213
               int src_stride_abgr,
2214
               uint8_t* dst_ar30,
2215
               int dst_stride_ar30,
2216
               int width,
2217
0
               int height) {
2218
0
  int y;
2219
0
  void (*ABGRToAR30Row)(const uint8_t* src_abgr, uint8_t* dst_rgb, int width) =
2220
0
      ABGRToAR30Row_C;
2221
0
  if (!src_abgr || !dst_ar30 || width <= 0 || height == 0) {
2222
0
    return -1;
2223
0
  }
2224
0
  if (height < 0) {
2225
0
    height = -height;
2226
0
    src_abgr = src_abgr + (height - 1) * src_stride_abgr;
2227
0
    src_stride_abgr = -src_stride_abgr;
2228
0
  }
2229
  // Coalesce rows.
2230
0
  if (src_stride_abgr == width * 4 && dst_stride_ar30 == width * 4) {
2231
0
    width *= height;
2232
0
    height = 1;
2233
0
    src_stride_abgr = dst_stride_ar30 = 0;
2234
0
  }
2235
#if defined(HAS_ABGRTOAR30ROW_NEON)
2236
  if (TestCpuFlag(kCpuHasNEON)) {
2237
    ABGRToAR30Row = ABGRToAR30Row_Any_NEON;
2238
    if (IS_ALIGNED(width, 8)) {
2239
      ABGRToAR30Row = ABGRToAR30Row_NEON;
2240
    }
2241
  }
2242
#endif
2243
0
#if defined(HAS_ABGRTOAR30ROW_SSSE3)
2244
0
  if (TestCpuFlag(kCpuHasSSSE3)) {
2245
0
    ABGRToAR30Row = ABGRToAR30Row_Any_SSSE3;
2246
0
    if (IS_ALIGNED(width, 4)) {
2247
0
      ABGRToAR30Row = ABGRToAR30Row_SSSE3;
2248
0
    }
2249
0
  }
2250
0
#endif
2251
0
#if defined(HAS_ABGRTOAR30ROW_AVX2)
2252
0
  if (TestCpuFlag(kCpuHasAVX2)) {
2253
0
    ABGRToAR30Row = ABGRToAR30Row_Any_AVX2;
2254
0
    if (IS_ALIGNED(width, 8)) {
2255
0
      ABGRToAR30Row = ABGRToAR30Row_AVX2;
2256
0
    }
2257
0
  }
2258
0
#endif
2259
0
  for (y = 0; y < height; ++y) {
2260
0
    ABGRToAR30Row(src_abgr, dst_ar30, width);
2261
0
    src_abgr += src_stride_abgr;
2262
0
    dst_ar30 += dst_stride_ar30;
2263
0
  }
2264
0
  return 0;
2265
0
}
2266
2267
// Convert ARGB To AR30.
2268
LIBYUV_API
2269
int ARGBToAR30(const uint8_t* src_argb,
2270
               int src_stride_argb,
2271
               uint8_t* dst_ar30,
2272
               int dst_stride_ar30,
2273
               int width,
2274
0
               int height) {
2275
0
  int y;
2276
0
  void (*ARGBToAR30Row)(const uint8_t* src_argb, uint8_t* dst_rgb, int width) =
2277
0
      ARGBToAR30Row_C;
2278
0
  if (!src_argb || !dst_ar30 || width <= 0 || height == 0) {
2279
0
    return -1;
2280
0
  }
2281
0
  if (height < 0) {
2282
0
    height = -height;
2283
0
    src_argb = src_argb + (height - 1) * src_stride_argb;
2284
0
    src_stride_argb = -src_stride_argb;
2285
0
  }
2286
  // Coalesce rows.
2287
0
  if (src_stride_argb == width * 4 && dst_stride_ar30 == width * 4) {
2288
0
    width *= height;
2289
0
    height = 1;
2290
0
    src_stride_argb = dst_stride_ar30 = 0;
2291
0
  }
2292
#if defined(HAS_ARGBTOAR30ROW_NEON)
2293
  if (TestCpuFlag(kCpuHasNEON)) {
2294
    ARGBToAR30Row = ARGBToAR30Row_Any_NEON;
2295
    if (IS_ALIGNED(width, 8)) {
2296
      ARGBToAR30Row = ARGBToAR30Row_NEON;
2297
    }
2298
  }
2299
#endif
2300
0
#if defined(HAS_ARGBTOAR30ROW_SSSE3)
2301
0
  if (TestCpuFlag(kCpuHasSSSE3)) {
2302
0
    ARGBToAR30Row = ARGBToAR30Row_Any_SSSE3;
2303
0
    if (IS_ALIGNED(width, 4)) {
2304
0
      ARGBToAR30Row = ARGBToAR30Row_SSSE3;
2305
0
    }
2306
0
  }
2307
0
#endif
2308
0
#if defined(HAS_ARGBTOAR30ROW_AVX2)
2309
0
  if (TestCpuFlag(kCpuHasAVX2)) {
2310
0
    ARGBToAR30Row = ARGBToAR30Row_Any_AVX2;
2311
0
    if (IS_ALIGNED(width, 8)) {
2312
0
      ARGBToAR30Row = ARGBToAR30Row_AVX2;
2313
0
    }
2314
0
  }
2315
0
#endif
2316
0
  for (y = 0; y < height; ++y) {
2317
0
    ARGBToAR30Row(src_argb, dst_ar30, width);
2318
0
    src_argb += src_stride_argb;
2319
0
    dst_ar30 += dst_stride_ar30;
2320
0
  }
2321
0
  return 0;
2322
0
}
2323
2324
// ARGB little endian (bgra in memory) to J444
2325
LIBYUV_API
2326
int ARGBToJ444(const uint8_t* src_argb,
2327
               int src_stride_argb,
2328
               uint8_t* dst_y,
2329
               int dst_stride_y,
2330
               uint8_t* dst_u,
2331
               int dst_stride_u,
2332
               uint8_t* dst_v,
2333
               int dst_stride_v,
2334
               int width,
2335
0
               int height) {
2336
0
  int y;
2337
0
  void (*ARGBToYJRow)(const uint8_t* src_argb, uint8_t* dst_y, int width) =
2338
0
      ARGBToYJRow_C;
2339
0
  void (*ARGBToUVJ444Row)(const uint8_t* src_argb, uint8_t* dst_u,
2340
0
                          uint8_t* dst_v, int width) = ARGBToUVJ444Row_C;
2341
0
  if (!src_argb || !dst_y || !dst_u || !dst_v || width <= 0 || height == 0) {
2342
0
    return -1;
2343
0
  }
2344
0
  if (height < 0) {
2345
0
    height = -height;
2346
0
    src_argb = src_argb + (height - 1) * src_stride_argb;
2347
0
    src_stride_argb = -src_stride_argb;
2348
0
  }
2349
  // Coalesce rows.
2350
0
  if (src_stride_argb == width * 4 && dst_stride_y == width &&
2351
0
      dst_stride_u == width && dst_stride_v == width) {
2352
0
    width *= height;
2353
0
    height = 1;
2354
0
    src_stride_argb = dst_stride_y = dst_stride_u = dst_stride_v = 0;
2355
0
  }
2356
0
#if defined(HAS_ARGBTOUVJ444ROW_SSSE3)
2357
0
  if (TestCpuFlag(kCpuHasSSSE3)) {
2358
0
    ARGBToUVJ444Row = ARGBToUVJ444Row_Any_SSSE3;
2359
0
    if (IS_ALIGNED(width, 16)) {
2360
0
      ARGBToUVJ444Row = ARGBToUVJ444Row_SSSE3;
2361
0
    }
2362
0
  }
2363
0
#endif
2364
0
#if defined(HAS_ARGBTOUVJ444ROW_AVX2)
2365
0
  if (TestCpuFlag(kCpuHasAVX2)) {
2366
0
    ARGBToUVJ444Row = ARGBToUVJ444Row_Any_AVX2;
2367
0
    if (IS_ALIGNED(width, 32)) {
2368
0
      ARGBToUVJ444Row = ARGBToUVJ444Row_AVX2;
2369
0
    }
2370
0
  }
2371
0
#endif
2372
#if defined(HAS_ARGBTOUVJ444ROW_NEON)
2373
  if (TestCpuFlag(kCpuHasNEON)) {
2374
    ARGBToUVJ444Row = ARGBToUVJ444Row_Any_NEON;
2375
    if (IS_ALIGNED(width, 8)) {
2376
      ARGBToUVJ444Row = ARGBToUVJ444Row_NEON;
2377
    }
2378
  }
2379
#endif
2380
#if defined(HAS_ARGBTOUVJ444ROW_NEON_I8MM)
2381
  if (TestCpuFlag(kCpuHasNeonI8MM)) {
2382
    ARGBToUVJ444Row = ARGBToUVJ444Row_Any_NEON_I8MM;
2383
    if (IS_ALIGNED(width, 8)) {
2384
      ARGBToUVJ444Row = ARGBToUVJ444Row_NEON_I8MM;
2385
    }
2386
  }
2387
#endif
2388
#if defined(HAS_ARGBTOUVJ444ROW_LSX)
2389
  if (TestCpuFlag(kCpuHasLSX)) {
2390
    ARGBToUVJ444Row = ARGBToUVJ444Row_Any_LSX;
2391
    if (IS_ALIGNED(width, 16)) {
2392
      ARGBToUVJ444Row = ARGBToUVJ444Row_LSX;
2393
    }
2394
  }
2395
#endif
2396
#if defined(HAS_ARGBTOUVJ444ROW_LASX)
2397
  if (TestCpuFlag(kCpuHasLASX)) {
2398
    ARGBToUVJ444Row = ARGBToUVJ444Row_Any_LASX;
2399
    if (IS_ALIGNED(width, 32)) {
2400
      ARGBToUVJ444Row = ARGBToUVJ444Row_LASX;
2401
    }
2402
  }
2403
#endif
2404
0
#if defined(HAS_ARGBTOYJROW_SSSE3)
2405
0
  if (TestCpuFlag(kCpuHasSSSE3)) {
2406
0
    ARGBToYJRow = ARGBToYJRow_Any_SSSE3;
2407
0
    if (IS_ALIGNED(width, 16)) {
2408
0
      ARGBToYJRow = ARGBToYJRow_SSSE3;
2409
0
    }
2410
0
  }
2411
0
#endif
2412
0
#if defined(HAS_ARGBTOYJROW_AVX2)
2413
0
  if (TestCpuFlag(kCpuHasAVX2)) {
2414
0
    ARGBToYJRow = ARGBToYJRow_Any_AVX2;
2415
0
    if (IS_ALIGNED(width, 32)) {
2416
0
      ARGBToYJRow = ARGBToYJRow_AVX2;
2417
0
    }
2418
0
  }
2419
0
#endif
2420
#if defined(HAS_ARGBTOYJROW_NEON)
2421
  if (TestCpuFlag(kCpuHasNEON)) {
2422
    ARGBToYJRow = ARGBToYJRow_Any_NEON;
2423
    if (IS_ALIGNED(width, 16)) {
2424
      ARGBToYJRow = ARGBToYJRow_NEON;
2425
    }
2426
  }
2427
#endif
2428
#if defined(HAS_ARGBTOYJROW_NEON_DOTPROD)
2429
  if (TestCpuFlag(kCpuHasNeonDotProd)) {
2430
    ARGBToYJRow = ARGBToYJRow_Any_NEON_DotProd;
2431
    if (IS_ALIGNED(width, 16)) {
2432
      ARGBToYJRow = ARGBToYJRow_NEON_DotProd;
2433
    }
2434
  }
2435
#endif
2436
#if defined(HAS_ARGBTOYJROW_LSX)
2437
  if (TestCpuFlag(kCpuHasLSX)) {
2438
    ARGBToYJRow = ARGBToYJRow_Any_LSX;
2439
    if (IS_ALIGNED(width, 16)) {
2440
      ARGBToYJRow = ARGBToYJRow_LSX;
2441
    }
2442
  }
2443
#endif
2444
#if defined(HAS_ARGBTOYJROW_LASX)
2445
  if (TestCpuFlag(kCpuHasLASX)) {
2446
    ARGBToYJRow = ARGBToYJRow_Any_LASX;
2447
    if (IS_ALIGNED(width, 32)) {
2448
      ARGBToYJRow = ARGBToYJRow_LASX;
2449
    }
2450
  }
2451
#endif
2452
#if defined(HAS_ARGBTOYJROW_RVV)
2453
  if (TestCpuFlag(kCpuHasRVV)) {
2454
    ARGBToYJRow = ARGBToYJRow_RVV;
2455
  }
2456
#endif
2457
2458
0
  for (y = 0; y < height; ++y) {
2459
0
    ARGBToUVJ444Row(src_argb, dst_u, dst_v, width);
2460
0
    ARGBToYJRow(src_argb, dst_y, width);
2461
0
    src_argb += src_stride_argb;
2462
0
    dst_y += dst_stride_y;
2463
0
    dst_u += dst_stride_u;
2464
0
    dst_v += dst_stride_v;
2465
0
  }
2466
0
  return 0;
2467
0
}
2468
2469
// Convert ARGB to J420. (JPeg full range I420).
2470
LIBYUV_API
2471
int ARGBToJ420(const uint8_t* src_argb,
2472
               int src_stride_argb,
2473
               uint8_t* dst_yj,
2474
               int dst_stride_yj,
2475
               uint8_t* dst_uj,
2476
               int dst_stride_uj,
2477
               uint8_t* dst_vj,
2478
               int dst_stride_vj,
2479
               int width,
2480
0
               int height) {
2481
0
  int y;
2482
0
  void (*ARGBToUVJRow)(const uint8_t* src_argb0, int src_stride_argb,
2483
0
                       uint8_t* dst_uj, uint8_t* dst_vj, int width) =
2484
0
      ARGBToUVJRow_C;
2485
0
  void (*ARGBToYJRow)(const uint8_t* src_argb, uint8_t* dst_yj, int width) =
2486
0
      ARGBToYJRow_C;
2487
0
  if (!src_argb || !dst_yj || !dst_uj || !dst_vj || width <= 0 || height == 0) {
2488
0
    return -1;
2489
0
  }
2490
  // Negative height means invert the image.
2491
0
  if (height < 0) {
2492
0
    height = -height;
2493
0
    src_argb = src_argb + (height - 1) * src_stride_argb;
2494
0
    src_stride_argb = -src_stride_argb;
2495
0
  }
2496
#if defined(HAS_ARGBTOYJROW_NEON)
2497
  if (TestCpuFlag(kCpuHasNEON)) {
2498
    ARGBToYJRow = ARGBToYJRow_Any_NEON;
2499
    if (IS_ALIGNED(width, 16)) {
2500
      ARGBToYJRow = ARGBToYJRow_NEON;
2501
    }
2502
  }
2503
#endif
2504
#if defined(HAS_ARGBTOYJROW_NEON_DOTPROD)
2505
  if (TestCpuFlag(kCpuHasNeonDotProd)) {
2506
    ARGBToYJRow = ARGBToYJRow_Any_NEON_DotProd;
2507
    if (IS_ALIGNED(width, 16)) {
2508
      ARGBToYJRow = ARGBToYJRow_NEON_DotProd;
2509
    }
2510
  }
2511
#endif
2512
#if defined(HAS_ARGBTOUVJROW_NEON)
2513
  if (TestCpuFlag(kCpuHasNEON)) {
2514
    ARGBToUVJRow = ARGBToUVJRow_Any_NEON;
2515
    if (IS_ALIGNED(width, 16)) {
2516
      ARGBToUVJRow = ARGBToUVJRow_NEON;
2517
    }
2518
  }
2519
#endif
2520
#if defined(HAS_ARGBTOUVJROW_NEON_I8MM)
2521
  if (TestCpuFlag(kCpuHasNeonI8MM)) {
2522
    ARGBToUVJRow = ARGBToUVJRow_Any_NEON_I8MM;
2523
    if (IS_ALIGNED(width, 16)) {
2524
      ARGBToUVJRow = ARGBToUVJRow_NEON_I8MM;
2525
    }
2526
  }
2527
#endif
2528
#if defined(HAS_ARGBTOUVJROW_SVE2)
2529
  if (TestCpuFlag(kCpuHasSVE2)) {
2530
    ARGBToUVJRow = ARGBToUVJRow_Any_SVE2;
2531
    if (IS_ALIGNED(width, 2)) {
2532
      ARGBToUVJRow = ARGBToUVJRow_SVE2;
2533
    }
2534
  }
2535
#endif
2536
#if defined(HAS_ARGBTOUVJROW_SME)
2537
  if (TestCpuFlag(kCpuHasSME)) {
2538
    ARGBToUVJRow = ARGBToUVJRow_Any_SME;
2539
    if (IS_ALIGNED(width, 2)) {
2540
      ARGBToUVJRow = ARGBToUVJRow_SME;
2541
    }
2542
  }
2543
#endif
2544
0
#if defined(HAS_ARGBTOYJROW_SSSE3)
2545
0
  if (TestCpuFlag(kCpuHasSSSE3)) {
2546
0
    ARGBToYJRow = ARGBToYJRow_Any_SSSE3;
2547
0
    if (IS_ALIGNED(width, 16)) {
2548
0
      ARGBToYJRow = ARGBToYJRow_SSSE3;
2549
0
    }
2550
0
  }
2551
0
#endif
2552
0
#if defined(HAS_ARGBTOUVJROW_SSSE3)
2553
0
  if (TestCpuFlag(kCpuHasSSSE3)) {
2554
0
    ARGBToUVJRow = ARGBToUVJRow_Any_SSSE3;
2555
0
    if (IS_ALIGNED(width, 16)) {
2556
0
      ARGBToUVJRow = ARGBToUVJRow_SSSE3;
2557
0
    }
2558
0
  }
2559
0
#endif
2560
0
#if defined(HAS_ARGBTOYJROW_AVX2)
2561
0
  if (TestCpuFlag(kCpuHasAVX2)) {
2562
0
    ARGBToYJRow = ARGBToYJRow_Any_AVX2;
2563
0
    if (IS_ALIGNED(width, 32)) {
2564
0
      ARGBToYJRow = ARGBToYJRow_AVX2;
2565
0
    }
2566
0
  }
2567
0
#endif
2568
0
#if defined(HAS_ARGBTOUVJROW_AVX2)
2569
0
  if (TestCpuFlag(kCpuHasAVX2)) {
2570
0
    ARGBToUVJRow = ARGBToUVJRow_Any_AVX2;
2571
0
    if (IS_ALIGNED(width, 32)) {
2572
0
      ARGBToUVJRow = ARGBToUVJRow_AVX2;
2573
0
    }
2574
0
  }
2575
0
#endif
2576
#if defined(HAS_ARGBTOYJROW_LSX) && defined(HAS_ARGBTOUVJROW_LSX)
2577
  if (TestCpuFlag(kCpuHasLSX)) {
2578
    ARGBToYJRow = ARGBToYJRow_Any_LSX;
2579
    ARGBToUVJRow = ARGBToUVJRow_Any_LSX;
2580
    if (IS_ALIGNED(width, 16)) {
2581
      ARGBToYJRow = ARGBToYJRow_LSX;
2582
      ARGBToUVJRow = ARGBToUVJRow_LSX;
2583
    }
2584
  }
2585
#endif
2586
#if defined(HAS_ARGBTOYJROW_LASX) && defined(HAS_ARGBTOUVJROW_LASX)
2587
  if (TestCpuFlag(kCpuHasLASX)) {
2588
    ARGBToYJRow = ARGBToYJRow_Any_LASX;
2589
    ARGBToUVJRow = ARGBToUVJRow_Any_LASX;
2590
    if (IS_ALIGNED(width, 32)) {
2591
      ARGBToYJRow = ARGBToYJRow_LASX;
2592
      ARGBToUVJRow = ARGBToUVJRow_LASX;
2593
    }
2594
  }
2595
#endif
2596
#if defined(HAS_ARGBTOYJROW_RVV)
2597
  if (TestCpuFlag(kCpuHasRVV)) {
2598
    ARGBToYJRow = ARGBToYJRow_RVV;
2599
  }
2600
#endif
2601
2602
0
  for (y = 0; y < height - 1; y += 2) {
2603
0
    ARGBToUVJRow(src_argb, src_stride_argb, dst_uj, dst_vj, width);
2604
0
    ARGBToYJRow(src_argb, dst_yj, width);
2605
0
    ARGBToYJRow(src_argb + src_stride_argb, dst_yj + dst_stride_yj, width);
2606
0
    src_argb += src_stride_argb * 2;
2607
0
    dst_yj += dst_stride_yj * 2;
2608
0
    dst_uj += dst_stride_uj;
2609
0
    dst_vj += dst_stride_vj;
2610
0
  }
2611
0
  if (height & 1) {
2612
0
    ARGBToUVJRow(src_argb, 0, dst_uj, dst_vj, width);
2613
0
    ARGBToYJRow(src_argb, dst_yj, width);
2614
0
  }
2615
0
  return 0;
2616
0
}
2617
2618
// Convert ARGB to J422. (JPeg full range I422).
2619
LIBYUV_API
2620
int ARGBToJ422(const uint8_t* src_argb,
2621
               int src_stride_argb,
2622
               uint8_t* dst_yj,
2623
               int dst_stride_yj,
2624
               uint8_t* dst_uj,
2625
               int dst_stride_uj,
2626
               uint8_t* dst_vj,
2627
               int dst_stride_vj,
2628
               int width,
2629
64.4k
               int height) {
2630
64.4k
  int y;
2631
64.4k
  void (*ARGBToUVJRow)(const uint8_t* src_argb0, int src_stride_argb,
2632
64.4k
                       uint8_t* dst_uj, uint8_t* dst_vj, int width) =
2633
64.4k
      ARGBToUVJRow_C;
2634
64.4k
  void (*ARGBToYJRow)(const uint8_t* src_argb, uint8_t* dst_yj, int width) =
2635
64.4k
      ARGBToYJRow_C;
2636
64.4k
  if (!src_argb || !dst_yj || !dst_uj || !dst_vj || width <= 0 || height == 0) {
2637
0
    return -1;
2638
0
  }
2639
  // Negative height means invert the image.
2640
64.4k
  if (height < 0) {
2641
0
    height = -height;
2642
0
    src_argb = src_argb + (height - 1) * src_stride_argb;
2643
0
    src_stride_argb = -src_stride_argb;
2644
0
  }
2645
  // Coalesce rows.
2646
64.4k
  if (src_stride_argb == width * 4 && dst_stride_yj == width &&
2647
64.4k
      dst_stride_uj * 2 == width && dst_stride_vj * 2 == width) {
2648
37.4k
    width *= height;
2649
37.4k
    height = 1;
2650
37.4k
    src_stride_argb = dst_stride_yj = dst_stride_uj = dst_stride_vj = 0;
2651
37.4k
  }
2652
64.4k
#if defined(HAS_ARGBTOYJROW_SSSE3)
2653
64.4k
  if (TestCpuFlag(kCpuHasSSSE3)) {
2654
64.4k
    ARGBToYJRow = ARGBToYJRow_Any_SSSE3;
2655
64.4k
    if (IS_ALIGNED(width, 16)) {
2656
9.35k
      ARGBToYJRow = ARGBToYJRow_SSSE3;
2657
9.35k
    }
2658
64.4k
  }
2659
64.4k
#endif
2660
64.4k
#if defined(HAS_ARGBTOUVJROW_SSSE3)
2661
64.4k
  if (TestCpuFlag(kCpuHasSSSE3)) {
2662
64.4k
    ARGBToUVJRow = ARGBToUVJRow_Any_SSSE3;
2663
64.4k
    if (IS_ALIGNED(width, 16)) {
2664
9.35k
      ARGBToUVJRow = ARGBToUVJRow_SSSE3;
2665
9.35k
    }
2666
64.4k
  }
2667
64.4k
#endif
2668
64.4k
#if defined(HAS_ARGBTOYJROW_AVX2)
2669
64.4k
  if (TestCpuFlag(kCpuHasAVX2)) {
2670
64.4k
    ARGBToYJRow = ARGBToYJRow_Any_AVX2;
2671
64.4k
    if (IS_ALIGNED(width, 32)) {
2672
4.01k
      ARGBToYJRow = ARGBToYJRow_AVX2;
2673
4.01k
    }
2674
64.4k
  }
2675
64.4k
#endif
2676
64.4k
#if defined(HAS_ARGBTOUVJROW_AVX2)
2677
64.4k
  if (TestCpuFlag(kCpuHasAVX2)) {
2678
64.4k
    ARGBToUVJRow = ARGBToUVJRow_Any_AVX2;
2679
64.4k
    if (IS_ALIGNED(width, 32)) {
2680
4.01k
      ARGBToUVJRow = ARGBToUVJRow_AVX2;
2681
4.01k
    }
2682
64.4k
  }
2683
64.4k
#endif
2684
#if defined(HAS_ARGBTOYJROW_NEON)
2685
  if (TestCpuFlag(kCpuHasNEON)) {
2686
    ARGBToYJRow = ARGBToYJRow_Any_NEON;
2687
    if (IS_ALIGNED(width, 16)) {
2688
      ARGBToYJRow = ARGBToYJRow_NEON;
2689
    }
2690
  }
2691
#endif
2692
#if defined(HAS_ARGBTOYJROW_NEON_DOTPROD)
2693
  if (TestCpuFlag(kCpuHasNeonDotProd)) {
2694
    ARGBToYJRow = ARGBToYJRow_Any_NEON_DotProd;
2695
    if (IS_ALIGNED(width, 16)) {
2696
      ARGBToYJRow = ARGBToYJRow_NEON_DotProd;
2697
    }
2698
  }
2699
#endif
2700
#if defined(HAS_ARGBTOUVJROW_NEON)
2701
  if (TestCpuFlag(kCpuHasNEON)) {
2702
    ARGBToUVJRow = ARGBToUVJRow_Any_NEON;
2703
    if (IS_ALIGNED(width, 16)) {
2704
      ARGBToUVJRow = ARGBToUVJRow_NEON;
2705
    }
2706
  }
2707
#endif
2708
#if defined(HAS_ARGBTOUVJROW_NEON_I8MM)
2709
  if (TestCpuFlag(kCpuHasNeonI8MM)) {
2710
    ARGBToUVJRow = ARGBToUVJRow_Any_NEON_I8MM;
2711
    if (IS_ALIGNED(width, 16)) {
2712
      ARGBToUVJRow = ARGBToUVJRow_NEON_I8MM;
2713
    }
2714
  }
2715
#endif
2716
#if defined(HAS_ARGBTOUVJROW_SVE2)
2717
  if (TestCpuFlag(kCpuHasSVE2)) {
2718
    ARGBToUVJRow = ARGBToUVJRow_Any_SVE2;
2719
    if (IS_ALIGNED(width, 2)) {
2720
      ARGBToUVJRow = ARGBToUVJRow_SVE2;
2721
    }
2722
  }
2723
#endif
2724
#if defined(HAS_ARGBTOUVJROW_SME)
2725
  if (TestCpuFlag(kCpuHasSME)) {
2726
    ARGBToUVJRow = ARGBToUVJRow_Any_SME;
2727
    if (IS_ALIGNED(width, 2)) {
2728
      ARGBToUVJRow = ARGBToUVJRow_SME;
2729
    }
2730
  }
2731
#endif
2732
#if defined(HAS_ARGBTOYJROW_LSX) && defined(HAS_ARGBTOUVJROW_LSX)
2733
  if (TestCpuFlag(kCpuHasLSX)) {
2734
    ARGBToYJRow = ARGBToYJRow_Any_LSX;
2735
    ARGBToUVJRow = ARGBToUVJRow_Any_LSX;
2736
    if (IS_ALIGNED(width, 16)) {
2737
      ARGBToYJRow = ARGBToYJRow_LSX;
2738
      ARGBToUVJRow = ARGBToUVJRow_LSX;
2739
    }
2740
  }
2741
#endif
2742
#if defined(HAS_ARGBTOYJROW_LASX) && defined(HAS_ARGBTOUVJROW_LASX)
2743
  if (TestCpuFlag(kCpuHasLASX)) {
2744
    ARGBToYJRow = ARGBToYJRow_Any_LASX;
2745
    ARGBToUVJRow = ARGBToUVJRow_Any_LASX;
2746
    if (IS_ALIGNED(width, 32)) {
2747
      ARGBToYJRow = ARGBToYJRow_LASX;
2748
      ARGBToUVJRow = ARGBToUVJRow_LASX;
2749
    }
2750
  }
2751
#endif
2752
#if defined(HAS_ARGBTOYJROW_RVV)
2753
  if (TestCpuFlag(kCpuHasRVV)) {
2754
    ARGBToYJRow = ARGBToYJRow_RVV;
2755
  }
2756
#endif
2757
2758
249k
  for (y = 0; y < height; ++y) {
2759
184k
    ARGBToUVJRow(src_argb, 0, dst_uj, dst_vj, width);
2760
184k
    ARGBToYJRow(src_argb, dst_yj, width);
2761
184k
    src_argb += src_stride_argb;
2762
184k
    dst_yj += dst_stride_yj;
2763
184k
    dst_uj += dst_stride_uj;
2764
184k
    dst_vj += dst_stride_vj;
2765
184k
  }
2766
64.4k
  return 0;
2767
64.4k
}
2768
2769
// Convert ARGB to J400.
2770
LIBYUV_API
2771
int ARGBToJ400(const uint8_t* src_argb,
2772
               int src_stride_argb,
2773
               uint8_t* dst_yj,
2774
               int dst_stride_yj,
2775
               int width,
2776
0
               int height) {
2777
0
  int y;
2778
0
  void (*ARGBToYJRow)(const uint8_t* src_argb, uint8_t* dst_yj, int width) =
2779
0
      ARGBToYJRow_C;
2780
0
  if (!src_argb || !dst_yj || width <= 0 || height == 0) {
2781
0
    return -1;
2782
0
  }
2783
0
  if (height < 0) {
2784
0
    height = -height;
2785
0
    src_argb = src_argb + (height - 1) * src_stride_argb;
2786
0
    src_stride_argb = -src_stride_argb;
2787
0
  }
2788
  // Coalesce rows.
2789
0
  if (src_stride_argb == width * 4 && dst_stride_yj == width) {
2790
0
    width *= height;
2791
0
    height = 1;
2792
0
    src_stride_argb = dst_stride_yj = 0;
2793
0
  }
2794
0
#if defined(HAS_ARGBTOYJROW_SSSE3)
2795
0
  if (TestCpuFlag(kCpuHasSSSE3)) {
2796
0
    ARGBToYJRow = ARGBToYJRow_Any_SSSE3;
2797
0
    if (IS_ALIGNED(width, 16)) {
2798
0
      ARGBToYJRow = ARGBToYJRow_SSSE3;
2799
0
    }
2800
0
  }
2801
0
#endif
2802
0
#if defined(HAS_ARGBTOYJROW_AVX2)
2803
0
  if (TestCpuFlag(kCpuHasAVX2)) {
2804
0
    ARGBToYJRow = ARGBToYJRow_Any_AVX2;
2805
0
    if (IS_ALIGNED(width, 32)) {
2806
0
      ARGBToYJRow = ARGBToYJRow_AVX2;
2807
0
    }
2808
0
  }
2809
0
#endif
2810
#if defined(HAS_ARGBTOYJROW_NEON)
2811
  if (TestCpuFlag(kCpuHasNEON)) {
2812
    ARGBToYJRow = ARGBToYJRow_Any_NEON;
2813
    if (IS_ALIGNED(width, 16)) {
2814
      ARGBToYJRow = ARGBToYJRow_NEON;
2815
    }
2816
  }
2817
#endif
2818
#if defined(HAS_ARGBTOYJROW_NEON_DOTPROD)
2819
  if (TestCpuFlag(kCpuHasNeonDotProd)) {
2820
    ARGBToYJRow = ARGBToYJRow_Any_NEON_DotProd;
2821
    if (IS_ALIGNED(width, 16)) {
2822
      ARGBToYJRow = ARGBToYJRow_NEON_DotProd;
2823
    }
2824
  }
2825
#endif
2826
#if defined(HAS_ARGBTOYJROW_RVV)
2827
  if (TestCpuFlag(kCpuHasRVV)) {
2828
    ARGBToYJRow = ARGBToYJRow_RVV;
2829
  }
2830
#endif
2831
2832
0
  for (y = 0; y < height; ++y) {
2833
0
    ARGBToYJRow(src_argb, dst_yj, width);
2834
0
    src_argb += src_stride_argb;
2835
0
    dst_yj += dst_stride_yj;
2836
0
  }
2837
0
  return 0;
2838
0
}
2839
2840
// Convert RGBA to J400.
2841
LIBYUV_API
2842
int RGBAToJ400(const uint8_t* src_rgba,
2843
               int src_stride_rgba,
2844
               uint8_t* dst_yj,
2845
               int dst_stride_yj,
2846
               int width,
2847
0
               int height) {
2848
0
  int y;
2849
0
  void (*RGBAToYJRow)(const uint8_t* src_rgba, uint8_t* dst_yj, int width) =
2850
0
      RGBAToYJRow_C;
2851
0
  if (!src_rgba || !dst_yj || width <= 0 || height == 0) {
2852
0
    return -1;
2853
0
  }
2854
0
  if (height < 0) {
2855
0
    height = -height;
2856
0
    src_rgba = src_rgba + (height - 1) * src_stride_rgba;
2857
0
    src_stride_rgba = -src_stride_rgba;
2858
0
  }
2859
  // Coalesce rows.
2860
0
  if (src_stride_rgba == width * 4 && dst_stride_yj == width) {
2861
0
    width *= height;
2862
0
    height = 1;
2863
0
    src_stride_rgba = dst_stride_yj = 0;
2864
0
  }
2865
0
#if defined(HAS_RGBATOYJROW_SSSE3)
2866
0
  if (TestCpuFlag(kCpuHasSSSE3)) {
2867
0
    RGBAToYJRow = RGBAToYJRow_Any_SSSE3;
2868
0
    if (IS_ALIGNED(width, 16)) {
2869
0
      RGBAToYJRow = RGBAToYJRow_SSSE3;
2870
0
    }
2871
0
  }
2872
0
#endif
2873
0
#if defined(HAS_RGBATOYJROW_AVX2)
2874
0
  if (TestCpuFlag(kCpuHasAVX2)) {
2875
0
    RGBAToYJRow = RGBAToYJRow_Any_AVX2;
2876
0
    if (IS_ALIGNED(width, 32)) {
2877
0
      RGBAToYJRow = RGBAToYJRow_AVX2;
2878
0
    }
2879
0
  }
2880
0
#endif
2881
#if defined(HAS_RGBATOYJROW_NEON)
2882
  if (TestCpuFlag(kCpuHasNEON)) {
2883
    RGBAToYJRow = RGBAToYJRow_Any_NEON;
2884
    if (IS_ALIGNED(width, 16)) {
2885
      RGBAToYJRow = RGBAToYJRow_NEON;
2886
    }
2887
  }
2888
#endif
2889
#if defined(HAS_RGBATOYJROW_NEON_DOTPROD)
2890
  if (TestCpuFlag(kCpuHasNeonDotProd)) {
2891
    RGBAToYJRow = RGBAToYJRow_Any_NEON_DotProd;
2892
    if (IS_ALIGNED(width, 16)) {
2893
      RGBAToYJRow = RGBAToYJRow_NEON_DotProd;
2894
    }
2895
  }
2896
#endif
2897
#if defined(HAS_RGBATOYJROW_LSX)
2898
  if (TestCpuFlag(kCpuHasLSX)) {
2899
    RGBAToYJRow = RGBAToYJRow_Any_LSX;
2900
    if (IS_ALIGNED(width, 16)) {
2901
      RGBAToYJRow = RGBAToYJRow_LSX;
2902
    }
2903
  }
2904
#endif
2905
#if defined(HAS_RGBATOYJROW_LASX)
2906
  if (TestCpuFlag(kCpuHasLASX)) {
2907
    RGBAToYJRow = RGBAToYJRow_Any_LASX;
2908
    if (IS_ALIGNED(width, 32)) {
2909
      RGBAToYJRow = RGBAToYJRow_LASX;
2910
    }
2911
  }
2912
#endif
2913
#if defined(HAS_RGBATOYJROW_RVV)
2914
  if (TestCpuFlag(kCpuHasRVV)) {
2915
    RGBAToYJRow = RGBAToYJRow_RVV;
2916
  }
2917
#endif
2918
2919
0
  for (y = 0; y < height; ++y) {
2920
0
    RGBAToYJRow(src_rgba, dst_yj, width);
2921
0
    src_rgba += src_stride_rgba;
2922
0
    dst_yj += dst_stride_yj;
2923
0
  }
2924
0
  return 0;
2925
0
}
2926
2927
// Convert ABGR to J420. (JPeg full range I420).
2928
LIBYUV_API
2929
int ABGRToJ420(const uint8_t* src_abgr,
2930
               int src_stride_abgr,
2931
               uint8_t* dst_yj,
2932
               int dst_stride_yj,
2933
               uint8_t* dst_uj,
2934
               int dst_stride_uj,
2935
               uint8_t* dst_vj,
2936
               int dst_stride_vj,
2937
               int width,
2938
6
               int height) {
2939
6
  int y;
2940
6
  void (*ABGRToUVJRow)(const uint8_t* src_abgr0, int src_stride_abgr,
2941
6
                       uint8_t* dst_uj, uint8_t* dst_vj, int width) =
2942
6
      ABGRToUVJRow_C;
2943
6
  void (*ABGRToYJRow)(const uint8_t* src_abgr, uint8_t* dst_yj, int width) =
2944
6
      ABGRToYJRow_C;
2945
6
  if (!src_abgr || !dst_yj || !dst_uj || !dst_vj || width <= 0 || height == 0) {
2946
0
    return -1;
2947
0
  }
2948
  // Negative height means invert the image.
2949
6
  if (height < 0) {
2950
0
    height = -height;
2951
0
    src_abgr = src_abgr + (height - 1) * src_stride_abgr;
2952
0
    src_stride_abgr = -src_stride_abgr;
2953
0
  }
2954
6
#if defined(HAS_ABGRTOYJROW_SSSE3)
2955
6
  if (TestCpuFlag(kCpuHasSSSE3)) {
2956
6
    ABGRToYJRow = ABGRToYJRow_Any_SSSE3;
2957
6
    if (IS_ALIGNED(width, 16)) {
2958
3
      ABGRToYJRow = ABGRToYJRow_SSSE3;
2959
3
    }
2960
6
  }
2961
6
#endif
2962
6
#if defined(HAS_ABGRTOUVJROW_SSSE3)
2963
6
  if (TestCpuFlag(kCpuHasSSSE3)) {
2964
6
    ABGRToUVJRow = ABGRToUVJRow_Any_SSSE3;
2965
6
    if (IS_ALIGNED(width, 16)) {
2966
3
      ABGRToUVJRow = ABGRToUVJRow_SSSE3;
2967
3
    }
2968
6
  }
2969
6
#endif
2970
6
#if defined(HAS_ABGRTOYJROW_AVX2)
2971
6
  if (TestCpuFlag(kCpuHasAVX2)) {
2972
6
    ABGRToYJRow = ABGRToYJRow_Any_AVX2;
2973
6
    if (IS_ALIGNED(width, 32)) {
2974
3
      ABGRToYJRow = ABGRToYJRow_AVX2;
2975
3
    }
2976
6
  }
2977
6
#endif
2978
6
#if defined(HAS_ABGRTOUVJROW_AVX2)
2979
6
  if (TestCpuFlag(kCpuHasAVX2)) {
2980
6
    ABGRToUVJRow = ABGRToUVJRow_Any_AVX2;
2981
6
    if (IS_ALIGNED(width, 32)) {
2982
3
      ABGRToUVJRow = ABGRToUVJRow_AVX2;
2983
3
    }
2984
6
  }
2985
6
#endif
2986
#if defined(HAS_ABGRTOYJROW_NEON)
2987
  if (TestCpuFlag(kCpuHasNEON)) {
2988
    ABGRToYJRow = ABGRToYJRow_Any_NEON;
2989
    if (IS_ALIGNED(width, 16)) {
2990
      ABGRToYJRow = ABGRToYJRow_NEON;
2991
    }
2992
  }
2993
#endif
2994
#if defined(HAS_ABGRTOYJROW_NEON_DOTPROD)
2995
  if (TestCpuFlag(kCpuHasNeonDotProd)) {
2996
    ABGRToYJRow = ABGRToYJRow_Any_NEON_DotProd;
2997
    if (IS_ALIGNED(width, 16)) {
2998
      ABGRToYJRow = ABGRToYJRow_NEON_DotProd;
2999
    }
3000
  }
3001
#endif
3002
#if defined(HAS_ABGRTOUVJROW_NEON)
3003
  if (TestCpuFlag(kCpuHasNEON)) {
3004
    ABGRToUVJRow = ABGRToUVJRow_Any_NEON;
3005
    if (IS_ALIGNED(width, 16)) {
3006
      ABGRToUVJRow = ABGRToUVJRow_NEON;
3007
    }
3008
  }
3009
#endif
3010
#if defined(HAS_ABGRTOUVJROW_NEON_I8MM)
3011
  if (TestCpuFlag(kCpuHasNeonI8MM)) {
3012
    ABGRToUVJRow = ABGRToUVJRow_Any_NEON_I8MM;
3013
    if (IS_ALIGNED(width, 16)) {
3014
      ABGRToUVJRow = ABGRToUVJRow_NEON_I8MM;
3015
    }
3016
  }
3017
#endif
3018
#if defined(HAS_ABGRTOUVJROW_SVE2)
3019
  if (TestCpuFlag(kCpuHasSVE2)) {
3020
    ABGRToUVJRow = ABGRToUVJRow_Any_SVE2;
3021
    if (IS_ALIGNED(width, 2)) {
3022
      ABGRToUVJRow = ABGRToUVJRow_SVE2;
3023
    }
3024
  }
3025
#endif
3026
#if defined(HAS_ABGRTOUVJROW_SME)
3027
  if (TestCpuFlag(kCpuHasSME)) {
3028
    ABGRToUVJRow = ABGRToUVJRow_Any_SME;
3029
    if (IS_ALIGNED(width, 2)) {
3030
      ABGRToUVJRow = ABGRToUVJRow_SME;
3031
    }
3032
  }
3033
#endif
3034
#if defined(HAS_ABGRTOYJROW_LSX)
3035
  if (TestCpuFlag(kCpuHasLSX)) {
3036
    ABGRToYJRow = ABGRToYJRow_Any_LSX;
3037
    if (IS_ALIGNED(width, 16)) {
3038
      ABGRToYJRow = ABGRToYJRow_LSX;
3039
    }
3040
  }
3041
#endif
3042
#if defined(HAS_ABGRTOYJROW_LASX)
3043
  if (TestCpuFlag(kCpuHasLASX)) {
3044
    ABGRToYJRow = ABGRToYJRow_Any_LASX;
3045
    if (IS_ALIGNED(width, 32)) {
3046
      ABGRToYJRow = ABGRToYJRow_LASX;
3047
    }
3048
  }
3049
#endif
3050
#if defined(HAS_ABGRTOYJROW_RVV)
3051
  if (TestCpuFlag(kCpuHasRVV)) {
3052
    ABGRToYJRow = ABGRToYJRow_RVV;
3053
  }
3054
#endif
3055
3056
462
  for (y = 0; y < height - 1; y += 2) {
3057
456
    ABGRToUVJRow(src_abgr, src_stride_abgr, dst_uj, dst_vj, width);
3058
456
    ABGRToYJRow(src_abgr, dst_yj, width);
3059
456
    ABGRToYJRow(src_abgr + src_stride_abgr, dst_yj + dst_stride_yj, width);
3060
456
    src_abgr += src_stride_abgr * 2;
3061
456
    dst_yj += dst_stride_yj * 2;
3062
456
    dst_uj += dst_stride_uj;
3063
456
    dst_vj += dst_stride_vj;
3064
456
  }
3065
6
  if (height & 1) {
3066
2
    ABGRToUVJRow(src_abgr, 0, dst_uj, dst_vj, width);
3067
2
    ABGRToYJRow(src_abgr, dst_yj, width);
3068
2
  }
3069
6
  return 0;
3070
6
}
3071
3072
// Convert ABGR to J422. (JPeg full range I422).
3073
LIBYUV_API
3074
int ABGRToJ422(const uint8_t* src_abgr,
3075
               int src_stride_abgr,
3076
               uint8_t* dst_yj,
3077
               int dst_stride_yj,
3078
               uint8_t* dst_uj,
3079
               int dst_stride_uj,
3080
               uint8_t* dst_vj,
3081
               int dst_stride_vj,
3082
               int width,
3083
5
               int height) {
3084
5
  int y;
3085
5
  void (*ABGRToUVJRow)(const uint8_t* src_abgr0, int src_stride_abgr,
3086
5
                       uint8_t* dst_uj, uint8_t* dst_vj, int width) =
3087
5
      ABGRToUVJRow_C;
3088
5
  void (*ABGRToYJRow)(const uint8_t* src_abgr, uint8_t* dst_yj, int width) =
3089
5
      ABGRToYJRow_C;
3090
5
  if (!src_abgr || !dst_yj || !dst_uj || !dst_vj || width <= 0 || height == 0) {
3091
0
    return -1;
3092
0
  }
3093
  // Negative height means invert the image.
3094
5
  if (height < 0) {
3095
0
    height = -height;
3096
0
    src_abgr = src_abgr + (height - 1) * src_stride_abgr;
3097
0
    src_stride_abgr = -src_stride_abgr;
3098
0
  }
3099
  // Coalesce rows.
3100
5
  if (src_stride_abgr == width * 4 && dst_stride_yj == width &&
3101
5
      dst_stride_uj * 2 == width && dst_stride_vj * 2 == width) {
3102
3
    width *= height;
3103
3
    height = 1;
3104
3
    src_stride_abgr = dst_stride_yj = dst_stride_uj = dst_stride_vj = 0;
3105
3
  }
3106
5
#if defined(HAS_ABGRTOYJROW_SSSE3)
3107
5
  if (TestCpuFlag(kCpuHasSSSE3)) {
3108
5
    ABGRToYJRow = ABGRToYJRow_Any_SSSE3;
3109
5
    if (IS_ALIGNED(width, 16)) {
3110
3
      ABGRToYJRow = ABGRToYJRow_SSSE3;
3111
3
    }
3112
5
  }
3113
5
#endif
3114
5
#if defined(HAS_ABGRTOUVJROW_SSSE3)
3115
5
  if (TestCpuFlag(kCpuHasSSSE3)) {
3116
5
    ABGRToUVJRow = ABGRToUVJRow_Any_SSSE3;
3117
5
    if (IS_ALIGNED(width, 16)) {
3118
3
      ABGRToUVJRow = ABGRToUVJRow_SSSE3;
3119
3
    }
3120
5
  }
3121
5
#endif
3122
5
#if defined(HAS_ABGRTOYJROW_AVX2)
3123
5
  if (TestCpuFlag(kCpuHasAVX2)) {
3124
5
    ABGRToYJRow = ABGRToYJRow_Any_AVX2;
3125
5
    if (IS_ALIGNED(width, 32)) {
3126
1
      ABGRToYJRow = ABGRToYJRow_AVX2;
3127
1
    }
3128
5
  }
3129
5
#endif
3130
5
#if defined(HAS_ABGRTOUVJROW_AVX2)
3131
5
  if (TestCpuFlag(kCpuHasAVX2)) {
3132
5
    ABGRToUVJRow = ABGRToUVJRow_Any_AVX2;
3133
5
    if (IS_ALIGNED(width, 32)) {
3134
1
      ABGRToUVJRow = ABGRToUVJRow_AVX2;
3135
1
    }
3136
5
  }
3137
5
#endif
3138
#if defined(HAS_ABGRTOYJROW_NEON)
3139
  if (TestCpuFlag(kCpuHasNEON)) {
3140
    ABGRToYJRow = ABGRToYJRow_Any_NEON;
3141
    if (IS_ALIGNED(width, 16)) {
3142
      ABGRToYJRow = ABGRToYJRow_NEON;
3143
    }
3144
  }
3145
#endif
3146
#if defined(HAS_ABGRTOYJROW_NEON_DOTPROD)
3147
  if (TestCpuFlag(kCpuHasNeonDotProd)) {
3148
    ABGRToYJRow = ABGRToYJRow_Any_NEON_DotProd;
3149
    if (IS_ALIGNED(width, 16)) {
3150
      ABGRToYJRow = ABGRToYJRow_NEON_DotProd;
3151
    }
3152
  }
3153
#endif
3154
#if defined(HAS_ABGRTOUVJROW_NEON)
3155
  if (TestCpuFlag(kCpuHasNEON)) {
3156
    ABGRToUVJRow = ABGRToUVJRow_Any_NEON;
3157
    if (IS_ALIGNED(width, 16)) {
3158
      ABGRToUVJRow = ABGRToUVJRow_NEON;
3159
    }
3160
  }
3161
#endif
3162
#if defined(HAS_ABGRTOUVJROW_NEON_I8MM)
3163
  if (TestCpuFlag(kCpuHasNeonI8MM)) {
3164
    ABGRToUVJRow = ABGRToUVJRow_Any_NEON_I8MM;
3165
    if (IS_ALIGNED(width, 16)) {
3166
      ABGRToUVJRow = ABGRToUVJRow_NEON_I8MM;
3167
    }
3168
  }
3169
#endif
3170
#if defined(HAS_ABGRTOUVJROW_SVE2)
3171
  if (TestCpuFlag(kCpuHasSVE2)) {
3172
    ABGRToUVJRow = ABGRToUVJRow_Any_SVE2;
3173
    if (IS_ALIGNED(width, 2)) {
3174
      ABGRToUVJRow = ABGRToUVJRow_SVE2;
3175
    }
3176
  }
3177
#endif
3178
#if defined(HAS_ABGRTOUVJROW_SME)
3179
  if (TestCpuFlag(kCpuHasSME)) {
3180
    ABGRToUVJRow = ABGRToUVJRow_Any_SME;
3181
    if (IS_ALIGNED(width, 2)) {
3182
      ABGRToUVJRow = ABGRToUVJRow_SME;
3183
    }
3184
  }
3185
#endif
3186
#if defined(HAS_ABGRTOYJROW_LSX)
3187
  if (TestCpuFlag(kCpuHasLSX)) {
3188
    ABGRToYJRow = ABGRToYJRow_Any_LSX;
3189
    if (IS_ALIGNED(width, 16)) {
3190
      ABGRToYJRow = ABGRToYJRow_LSX;
3191
    }
3192
  }
3193
#endif
3194
#if defined(HAS_ABGRTOYJROW_LASX)
3195
  if (TestCpuFlag(kCpuHasLASX)) {
3196
    ABGRToYJRow = ABGRToYJRow_Any_LASX;
3197
    if (IS_ALIGNED(width, 32)) {
3198
      ABGRToYJRow = ABGRToYJRow_LASX;
3199
    }
3200
  }
3201
#endif
3202
#if defined(HAS_ABGRTOYJROW_RVV)
3203
  if (TestCpuFlag(kCpuHasRVV)) {
3204
    ABGRToYJRow = ABGRToYJRow_RVV;
3205
  }
3206
#endif
3207
3208
30
  for (y = 0; y < height; ++y) {
3209
25
    ABGRToUVJRow(src_abgr, 0, dst_uj, dst_vj, width);
3210
25
    ABGRToYJRow(src_abgr, dst_yj, width);
3211
25
    src_abgr += src_stride_abgr;
3212
25
    dst_yj += dst_stride_yj;
3213
25
    dst_uj += dst_stride_uj;
3214
25
    dst_vj += dst_stride_vj;
3215
25
  }
3216
5
  return 0;
3217
5
}
3218
3219
// Convert ABGR to J400.
3220
LIBYUV_API
3221
int ABGRToJ400(const uint8_t* src_abgr,
3222
               int src_stride_abgr,
3223
               uint8_t* dst_yj,
3224
               int dst_stride_yj,
3225
               int width,
3226
3
               int height) {
3227
3
  int y;
3228
3
  void (*ABGRToYJRow)(const uint8_t* src_abgr, uint8_t* dst_yj, int width) =
3229
3
      ABGRToYJRow_C;
3230
3
  if (!src_abgr || !dst_yj || width <= 0 || height == 0) {
3231
0
    return -1;
3232
0
  }
3233
3
  if (height < 0) {
3234
0
    height = -height;
3235
0
    src_abgr = src_abgr + (height - 1) * src_stride_abgr;
3236
0
    src_stride_abgr = -src_stride_abgr;
3237
0
  }
3238
  // Coalesce rows.
3239
3
  if (src_stride_abgr == width * 4 && dst_stride_yj == width) {
3240
3
    width *= height;
3241
3
    height = 1;
3242
3
    src_stride_abgr = dst_stride_yj = 0;
3243
3
  }
3244
3
#if defined(HAS_ABGRTOYJROW_SSSE3)
3245
3
  if (TestCpuFlag(kCpuHasSSSE3)) {
3246
3
    ABGRToYJRow = ABGRToYJRow_Any_SSSE3;
3247
3
    if (IS_ALIGNED(width, 16)) {
3248
2
      ABGRToYJRow = ABGRToYJRow_SSSE3;
3249
2
    }
3250
3
  }
3251
3
#endif
3252
3
#if defined(HAS_ABGRTOYJROW_AVX2)
3253
3
  if (TestCpuFlag(kCpuHasAVX2)) {
3254
3
    ABGRToYJRow = ABGRToYJRow_Any_AVX2;
3255
3
    if (IS_ALIGNED(width, 32)) {
3256
1
      ABGRToYJRow = ABGRToYJRow_AVX2;
3257
1
    }
3258
3
  }
3259
3
#endif
3260
#if defined(HAS_ABGRTOYJROW_NEON)
3261
  if (TestCpuFlag(kCpuHasNEON)) {
3262
    ABGRToYJRow = ABGRToYJRow_Any_NEON;
3263
    if (IS_ALIGNED(width, 16)) {
3264
      ABGRToYJRow = ABGRToYJRow_NEON;
3265
    }
3266
  }
3267
#endif
3268
#if defined(HAS_ABGRTOYJROW_NEON_DOTPROD)
3269
  if (TestCpuFlag(kCpuHasNeonDotProd)) {
3270
    ABGRToYJRow = ABGRToYJRow_Any_NEON_DotProd;
3271
    if (IS_ALIGNED(width, 16)) {
3272
      ABGRToYJRow = ABGRToYJRow_NEON_DotProd;
3273
    }
3274
  }
3275
#endif
3276
#if defined(HAS_ABGRTOYJROW_LSX)
3277
  if (TestCpuFlag(kCpuHasLSX)) {
3278
    ABGRToYJRow = ABGRToYJRow_Any_LSX;
3279
    if (IS_ALIGNED(width, 16)) {
3280
      ABGRToYJRow = ABGRToYJRow_LSX;
3281
    }
3282
  }
3283
#endif
3284
#if defined(HAS_ABGRTOYJROW_LASX)
3285
  if (TestCpuFlag(kCpuHasLASX)) {
3286
    ABGRToYJRow = ABGRToYJRow_Any_LASX;
3287
    if (IS_ALIGNED(width, 32)) {
3288
      ABGRToYJRow = ABGRToYJRow_LASX;
3289
    }
3290
  }
3291
#endif
3292
#if defined(HAS_ABGRTOYJROW_RVV)
3293
  if (TestCpuFlag(kCpuHasRVV)) {
3294
    ABGRToYJRow = ABGRToYJRow_RVV;
3295
  }
3296
#endif
3297
3298
6
  for (y = 0; y < height; ++y) {
3299
3
    ABGRToYJRow(src_abgr, dst_yj, width);
3300
3
    src_abgr += src_stride_abgr;
3301
3
    dst_yj += dst_stride_yj;
3302
3
  }
3303
3
  return 0;
3304
3
}
3305
3306
// Convert ARGB to AR64.
3307
LIBYUV_API
3308
int ARGBToAR64(const uint8_t* src_argb,
3309
               int src_stride_argb,
3310
               uint16_t* dst_ar64,
3311
               int dst_stride_ar64,
3312
               int width,
3313
0
               int height) {
3314
0
  int y;
3315
0
  void (*ARGBToAR64Row)(const uint8_t* src_argb, uint16_t* dst_ar64,
3316
0
                        int width) = ARGBToAR64Row_C;
3317
0
  if (!src_argb || !dst_ar64 || width <= 0 || height == 0) {
3318
0
    return -1;
3319
0
  }
3320
  // Negative height means invert the image.
3321
0
  if (height < 0) {
3322
0
    height = -height;
3323
0
    src_argb = src_argb + (height - 1) * src_stride_argb;
3324
0
    src_stride_argb = -src_stride_argb;
3325
0
  }
3326
  // Coalesce rows.
3327
0
  if (src_stride_argb == width * 4 && dst_stride_ar64 == width * 4) {
3328
0
    width *= height;
3329
0
    height = 1;
3330
0
    src_stride_argb = dst_stride_ar64 = 0;
3331
0
  }
3332
0
#if defined(HAS_ARGBTOAR64ROW_SSSE3)
3333
0
  if (TestCpuFlag(kCpuHasSSSE3)) {
3334
0
    ARGBToAR64Row = ARGBToAR64Row_Any_SSSE3;
3335
0
    if (IS_ALIGNED(width, 4)) {
3336
0
      ARGBToAR64Row = ARGBToAR64Row_SSSE3;
3337
0
    }
3338
0
  }
3339
0
#endif
3340
0
#if defined(HAS_ARGBTOAR64ROW_AVX2)
3341
0
  if (TestCpuFlag(kCpuHasAVX2)) {
3342
0
    ARGBToAR64Row = ARGBToAR64Row_Any_AVX2;
3343
0
    if (IS_ALIGNED(width, 8)) {
3344
0
      ARGBToAR64Row = ARGBToAR64Row_AVX2;
3345
0
    }
3346
0
  }
3347
0
#endif
3348
#if defined(HAS_ARGBTOAR64ROW_NEON)
3349
  if (TestCpuFlag(kCpuHasNEON)) {
3350
    ARGBToAR64Row = ARGBToAR64Row_Any_NEON;
3351
    if (IS_ALIGNED(width, 8)) {
3352
      ARGBToAR64Row = ARGBToAR64Row_NEON;
3353
    }
3354
  }
3355
#endif
3356
#if defined(HAS_ARGBTOAR64ROW_RVV)
3357
  if (TestCpuFlag(kCpuHasRVV)) {
3358
    ARGBToAR64Row = ARGBToAR64Row_RVV;
3359
  }
3360
#endif
3361
3362
0
  for (y = 0; y < height; ++y) {
3363
0
    ARGBToAR64Row(src_argb, dst_ar64, width);
3364
0
    src_argb += src_stride_argb;
3365
0
    dst_ar64 += dst_stride_ar64;
3366
0
  }
3367
0
  return 0;
3368
0
}
3369
3370
// Convert ARGB to AB64.
3371
LIBYUV_API
3372
int ARGBToAB64(const uint8_t* src_argb,
3373
               int src_stride_argb,
3374
               uint16_t* dst_ab64,
3375
               int dst_stride_ab64,
3376
               int width,
3377
0
               int height) {
3378
0
  int y;
3379
0
  void (*ARGBToAB64Row)(const uint8_t* src_argb, uint16_t* dst_ar64,
3380
0
                        int width) = ARGBToAB64Row_C;
3381
0
  if (!src_argb || !dst_ab64 || width <= 0 || height == 0) {
3382
0
    return -1;
3383
0
  }
3384
  // Negative height means invert the image.
3385
0
  if (height < 0) {
3386
0
    height = -height;
3387
0
    src_argb = src_argb + (height - 1) * src_stride_argb;
3388
0
    src_stride_argb = -src_stride_argb;
3389
0
  }
3390
  // Coalesce rows.
3391
0
  if (src_stride_argb == width * 4 && dst_stride_ab64 == width * 4) {
3392
0
    width *= height;
3393
0
    height = 1;
3394
0
    src_stride_argb = dst_stride_ab64 = 0;
3395
0
  }
3396
0
#if defined(HAS_ARGBTOAB64ROW_SSSE3)
3397
0
  if (TestCpuFlag(kCpuHasSSSE3)) {
3398
0
    ARGBToAB64Row = ARGBToAB64Row_Any_SSSE3;
3399
0
    if (IS_ALIGNED(width, 4)) {
3400
0
      ARGBToAB64Row = ARGBToAB64Row_SSSE3;
3401
0
    }
3402
0
  }
3403
0
#endif
3404
0
#if defined(HAS_ARGBTOAB64ROW_AVX2)
3405
0
  if (TestCpuFlag(kCpuHasAVX2)) {
3406
0
    ARGBToAB64Row = ARGBToAB64Row_Any_AVX2;
3407
0
    if (IS_ALIGNED(width, 8)) {
3408
0
      ARGBToAB64Row = ARGBToAB64Row_AVX2;
3409
0
    }
3410
0
  }
3411
0
#endif
3412
#if defined(HAS_ARGBTOAB64ROW_NEON)
3413
  if (TestCpuFlag(kCpuHasNEON)) {
3414
    ARGBToAB64Row = ARGBToAB64Row_Any_NEON;
3415
    if (IS_ALIGNED(width, 8)) {
3416
      ARGBToAB64Row = ARGBToAB64Row_NEON;
3417
    }
3418
  }
3419
#endif
3420
#if defined(HAS_ARGBTOAB64ROW_RVV)
3421
  if (TestCpuFlag(kCpuHasRVV)) {
3422
    ARGBToAB64Row = ARGBToAB64Row_RVV;
3423
  }
3424
#endif
3425
3426
0
  for (y = 0; y < height; ++y) {
3427
0
    ARGBToAB64Row(src_argb, dst_ab64, width);
3428
0
    src_argb += src_stride_argb;
3429
0
    dst_ab64 += dst_stride_ab64;
3430
0
  }
3431
0
  return 0;
3432
0
}
3433
3434
// Enabled if 1 pass is available
3435
#if defined(HAS_RAWTOYJROW_NEON) || defined(HAS_RAWTOYJROW_RVV)
3436
#define HAS_RAWTOYJROW
3437
#endif
3438
3439
// RAW to JNV21 full range NV21
3440
LIBYUV_API
3441
int RAWToJNV21(const uint8_t* src_raw,
3442
               int src_stride_raw,
3443
               uint8_t* dst_y,
3444
               int dst_stride_y,
3445
               uint8_t* dst_vu,
3446
               int dst_stride_vu,
3447
               int width,
3448
0
               int height) {
3449
0
  int y;
3450
0
  int halfwidth = (width + 1) >> 1;
3451
#if defined(HAS_RAWTOYJROW)
3452
  void (*RAWToUVJRow)(const uint8_t* src_raw, int src_stride_raw,
3453
                      uint8_t* dst_uj, uint8_t* dst_vj, int width) =
3454
      RAWToUVJRow_C;
3455
  void (*RAWToYJRow)(const uint8_t* src_raw, uint8_t* dst_y, int width) =
3456
      RAWToYJRow_C;
3457
#else
3458
0
  void (*RAWToARGBRow)(const uint8_t* src_rgb, uint8_t* dst_argb, int width) =
3459
0
      RAWToARGBRow_C;
3460
0
  void (*ARGBToUVJRow)(const uint8_t* src_argb0, int src_stride_argb,
3461
0
                       uint8_t* dst_uj, uint8_t* dst_vj, int width) =
3462
0
      ARGBToUVJRow_C;
3463
0
  void (*ARGBToYJRow)(const uint8_t* src_argb, uint8_t* dst_y, int width) =
3464
0
      ARGBToYJRow_C;
3465
0
#endif
3466
0
  void (*MergeUVRow_)(const uint8_t* src_uj, const uint8_t* src_vj,
3467
0
                      uint8_t* dst_vu, int width) = MergeUVRow_C;
3468
0
  if (!src_raw || !dst_y || !dst_vu || width <= 0 || height == 0) {
3469
0
    return -1;
3470
0
  }
3471
  // Negative height means invert the image.
3472
0
  if (height < 0) {
3473
0
    height = -height;
3474
0
    src_raw = src_raw + (height - 1) * src_stride_raw;
3475
0
    src_stride_raw = -src_stride_raw;
3476
0
  }
3477
3478
#if defined(HAS_RAWTOYJROW)
3479
3480
// Neon version does direct RAW to YUV.
3481
#if defined(HAS_RAWTOYJROW_NEON) && defined(HAS_RAWTOUVJROW_NEON)
3482
  if (TestCpuFlag(kCpuHasNEON)) {
3483
    RAWToUVJRow = RAWToUVJRow_Any_NEON;
3484
    RAWToYJRow = RAWToYJRow_Any_NEON;
3485
    if (IS_ALIGNED(width, 16)) {
3486
      RAWToYJRow = RAWToYJRow_NEON;
3487
      RAWToUVJRow = RAWToUVJRow_NEON;
3488
    }
3489
  }
3490
#endif
3491
#if defined(HAS_RAWTOYJROW_LSX)
3492
  if (TestCpuFlag(kCpuHasLSX)) {
3493
    RAWToYJRow = RAWToYJRow_Any_LSX;
3494
    if (IS_ALIGNED(width, 16)) {
3495
      RAWToYJRow = RAWToYJRow_LSX;
3496
    }
3497
  }
3498
#endif
3499
#if defined(HAS_RAWTOYJROW_LASX)
3500
  if (TestCpuFlag(kCpuHasLASX)) {
3501
    RAWToYJRow = RAWToYJRow_Any_LASX;
3502
    if (IS_ALIGNED(width, 32)) {
3503
      RAWToYJRow = RAWToYJRow_LASX;
3504
    }
3505
  }
3506
#endif
3507
#if defined(HAS_RAWTOYJROW_RVV)
3508
  if (TestCpuFlag(kCpuHasRVV)) {
3509
    RAWToYJRow = RAWToYJRow_RVV;
3510
  }
3511
#endif
3512
3513
// Other platforms do intermediate conversion from RAW to ARGB.
3514
#else  // HAS_RAWTOYJROW
3515
3516
0
#if defined(HAS_RAWTOARGBROW_SSSE3)
3517
0
  if (TestCpuFlag(kCpuHasSSSE3)) {
3518
0
    RAWToARGBRow = RAWToARGBRow_Any_SSSE3;
3519
0
    if (IS_ALIGNED(width, 16)) {
3520
0
      RAWToARGBRow = RAWToARGBRow_SSSE3;
3521
0
    }
3522
0
  }
3523
0
#endif
3524
0
#if defined(HAS_RAWTOARGBROW_AVX2)
3525
0
  if (TestCpuFlag(kCpuHasAVX2)) {
3526
0
    RAWToARGBRow = RAWToARGBRow_Any_AVX2;
3527
0
    if (IS_ALIGNED(width, 32)) {
3528
0
      RAWToARGBRow = RAWToARGBRow_AVX2;
3529
0
    }
3530
0
  }
3531
0
#endif
3532
0
#if defined(HAS_ARGBTOYJROW_SSSE3)
3533
0
  if (TestCpuFlag(kCpuHasSSSE3)) {
3534
0
    ARGBToYJRow = ARGBToYJRow_Any_SSSE3;
3535
0
    if (IS_ALIGNED(width, 16)) {
3536
0
      ARGBToYJRow = ARGBToYJRow_SSSE3;
3537
0
    }
3538
0
  }
3539
0
#endif
3540
0
#if defined(HAS_ARGBTOYJROW_AVX2)
3541
0
  if (TestCpuFlag(kCpuHasAVX2)) {
3542
0
    ARGBToYJRow = ARGBToYJRow_Any_AVX2;
3543
0
    if (IS_ALIGNED(width, 32)) {
3544
0
      ARGBToYJRow = ARGBToYJRow_AVX2;
3545
0
    }
3546
0
  }
3547
0
#endif
3548
0
#if defined(HAS_ARGBTOUVJROW_SSSE3)
3549
0
  if (TestCpuFlag(kCpuHasSSSE3)) {
3550
0
    ARGBToUVJRow = ARGBToUVJRow_Any_SSSE3;
3551
0
    if (IS_ALIGNED(width, 16)) {
3552
0
      ARGBToUVJRow = ARGBToUVJRow_SSSE3;
3553
0
    }
3554
0
  }
3555
0
#endif
3556
0
#if defined(HAS_ARGBTOUVJROW_AVX2)
3557
0
  if (TestCpuFlag(kCpuHasAVX2)) {
3558
0
    ARGBToUVJRow = ARGBToUVJRow_Any_AVX2;
3559
0
    if (IS_ALIGNED(width, 32)) {
3560
0
      ARGBToUVJRow = ARGBToUVJRow_AVX2;
3561
0
    }
3562
0
  }
3563
0
#endif
3564
0
#endif  // HAS_RAWTOYJROW
3565
0
#if defined(HAS_MERGEUVROW_SSE2)
3566
0
  if (TestCpuFlag(kCpuHasSSE2)) {
3567
0
    MergeUVRow_ = MergeUVRow_Any_SSE2;
3568
0
    if (IS_ALIGNED(halfwidth, 16)) {
3569
0
      MergeUVRow_ = MergeUVRow_SSE2;
3570
0
    }
3571
0
  }
3572
0
#endif
3573
0
#if defined(HAS_MERGEUVROW_AVX2)
3574
0
  if (TestCpuFlag(kCpuHasAVX2)) {
3575
0
    MergeUVRow_ = MergeUVRow_Any_AVX2;
3576
0
    if (IS_ALIGNED(halfwidth, 16)) {
3577
0
      MergeUVRow_ = MergeUVRow_AVX2;
3578
0
    }
3579
0
  }
3580
0
#endif
3581
0
#if defined(HAS_MERGEUVROW_AVX512BW)
3582
0
  if (TestCpuFlag(kCpuHasAVX512BW)) {
3583
0
    MergeUVRow_ = MergeUVRow_Any_AVX512BW;
3584
0
    if (IS_ALIGNED(halfwidth, 64)) {
3585
0
      MergeUVRow_ = MergeUVRow_AVX512BW;
3586
0
    }
3587
0
  }
3588
0
#endif
3589
#if defined(HAS_MERGEUVROW_NEON)
3590
  if (TestCpuFlag(kCpuHasNEON)) {
3591
    MergeUVRow_ = MergeUVRow_Any_NEON;
3592
    if (IS_ALIGNED(halfwidth, 16)) {
3593
      MergeUVRow_ = MergeUVRow_NEON;
3594
    }
3595
  }
3596
#endif
3597
#if defined(HAS_MERGEUVROW_SME)
3598
  if (TestCpuFlag(kCpuHasSME)) {
3599
    MergeUVRow_ = MergeUVRow_SME;
3600
  }
3601
#endif
3602
#if defined(HAS_MERGEUVROW_LSX)
3603
  if (TestCpuFlag(kCpuHasLSX)) {
3604
    MergeUVRow_ = MergeUVRow_Any_LSX;
3605
    if (IS_ALIGNED(halfwidth, 16)) {
3606
      MergeUVRow_ = MergeUVRow_LSX;
3607
    }
3608
  }
3609
#endif
3610
#if defined(HAS_MERGEUVROW_RVV)
3611
  if (TestCpuFlag(kCpuHasRVV)) {
3612
    MergeUVRow_ = MergeUVRow_RVV;
3613
  }
3614
#endif
3615
0
  {
3616
#if defined(HAS_RAWTOYJROW)
3617
    // Allocate a row of uv.
3618
    const int row_uv_size = ((halfwidth + 31) & ~31);
3619
    align_buffer_64(row_uj, row_uv_size * 2);
3620
    uint8_t* row_vj = row_uj + row_uv_size;
3621
#else
3622
    // Allocate row of uv and 2 rows of ARGB.
3623
0
    const int row_size = ((width * 4 + 31) & ~31);
3624
0
    const int row_uv_size = ((halfwidth + 31) & ~31);
3625
0
    align_buffer_64(row_uj, row_uv_size * 2 + row_size * 2);
3626
0
    uint8_t* row_vj = row_uj + row_uv_size;
3627
0
    uint8_t* row = row_vj + row_uv_size;
3628
0
#endif
3629
0
    if (!row_uj)
3630
0
      return 1;
3631
3632
0
    for (y = 0; y < height - 1; y += 2) {
3633
#if defined(HAS_RAWTOYJROW)
3634
      RAWToUVJRow(src_raw, src_stride_raw, row_uj, row_vj, width);
3635
      MergeUVRow_(row_vj, row_uj, dst_vu, halfwidth);
3636
      RAWToYJRow(src_raw, dst_y, width);
3637
      RAWToYJRow(src_raw + src_stride_raw, dst_y + dst_stride_y, width);
3638
#else
3639
0
      RAWToARGBRow(src_raw, row, width);
3640
0
      RAWToARGBRow(src_raw + src_stride_raw, row + row_size, width);
3641
0
      ARGBToUVJRow(row, row_size, row_uj, row_vj, width);
3642
0
      MergeUVRow_(row_vj, row_uj, dst_vu, halfwidth);
3643
0
      ARGBToYJRow(row, dst_y, width);
3644
0
      ARGBToYJRow(row + row_size, dst_y + dst_stride_y, width);
3645
0
#endif
3646
0
      src_raw += src_stride_raw * 2;
3647
0
      dst_y += dst_stride_y * 2;
3648
0
      dst_vu += dst_stride_vu;
3649
0
    }
3650
0
    if (height & 1) {
3651
#if defined(HAS_RAWTOYJROW)
3652
      RAWToUVJRow(src_raw, 0, row_uj, row_vj, width);
3653
      MergeUVRow_(row_vj, row_uj, dst_vu, halfwidth);
3654
      RAWToYJRow(src_raw, dst_y, width);
3655
#else
3656
0
      RAWToARGBRow(src_raw, row, width);
3657
0
      ARGBToUVJRow(row, 0, row_uj, row_vj, width);
3658
0
      MergeUVRow_(row_vj, row_uj, dst_vu, halfwidth);
3659
0
      ARGBToYJRow(row, dst_y, width);
3660
0
#endif
3661
0
    }
3662
0
    free_aligned_buffer_64(row_uj);
3663
0
  }
3664
0
  return 0;
3665
0
}
3666
#undef HAS_RAWTOYJROW
3667
3668
#ifdef __cplusplus
3669
}  // extern "C"
3670
}  // namespace libyuv
3671
#endif