Coverage Report

Created: 2025-11-24 06:52

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