Coverage Report

Created: 2025-10-10 07:09

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libavif/ext/libyuv/source/convert_argb.cc
Line
Count
Source
1
/*
2
 *  Copyright 2011 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_argb.h"
12
13
#include <assert.h>
14
15
#include "libyuv/convert_from_argb.h"
16
#include "libyuv/cpu_id.h"
17
#include "libyuv/planar_functions.h"  // For CopyPlane and ARGBShuffle.
18
#include "libyuv/rotate_argb.h"
19
#include "libyuv/row.h"
20
#include "libyuv/scale_row.h"  // For ScaleRowUp2_Linear and ScaleRowUp2_Bilinear
21
#include "libyuv/video_common.h"
22
23
#ifdef __cplusplus
24
namespace libyuv {
25
extern "C" {
26
#endif
27
28
// Copy ARGB with optional flipping
29
LIBYUV_API
30
int ARGBCopy(const uint8_t* src_argb,
31
             int src_stride_argb,
32
             uint8_t* dst_argb,
33
             int dst_stride_argb,
34
             int width,
35
0
             int height) {
36
0
  if (!src_argb || !dst_argb || width <= 0 || height == 0) {
37
0
    return -1;
38
0
  }
39
  // Negative height means invert the image.
40
0
  if (height < 0) {
41
0
    height = -height;
42
0
    src_argb = src_argb + (height - 1) * src_stride_argb;
43
0
    src_stride_argb = -src_stride_argb;
44
0
  }
45
46
0
  CopyPlane(src_argb, src_stride_argb, dst_argb, dst_stride_argb, width * 4,
47
0
            height);
48
0
  return 0;
49
0
}
50
51
// Convert I420 to ARGB with matrix.
52
LIBYUV_API
53
int I420ToARGBMatrix(const uint8_t* src_y,
54
                     int src_stride_y,
55
                     const uint8_t* src_u,
56
                     int src_stride_u,
57
                     const uint8_t* src_v,
58
                     int src_stride_v,
59
                     uint8_t* dst_argb,
60
                     int dst_stride_argb,
61
                     const struct YuvConstants* yuvconstants,
62
                     int width,
63
152
                     int height) {
64
152
  int y;
65
152
  void (*I422ToARGBRow)(const uint8_t* y_buf, const uint8_t* u_buf,
66
152
                        const uint8_t* v_buf, uint8_t* rgb_buf,
67
152
                        const struct YuvConstants* yuvconstants, int width) =
68
152
      I422ToARGBRow_C;
69
152
  assert(yuvconstants);
70
152
  if (!src_y || !src_u || !src_v || !dst_argb || width <= 0 || height == 0) {
71
0
    return -1;
72
0
  }
73
  // Negative height means invert the image.
74
152
  if (height < 0) {
75
0
    height = -height;
76
0
    dst_argb = dst_argb + (height - 1) * dst_stride_argb;
77
0
    dst_stride_argb = -dst_stride_argb;
78
0
  }
79
152
#if defined(HAS_I422TOARGBROW_SSSE3)
80
152
  if (TestCpuFlag(kCpuHasSSSE3)) {
81
152
    I422ToARGBRow = I422ToARGBRow_Any_SSSE3;
82
152
    if (IS_ALIGNED(width, 8)) {
83
35
      I422ToARGBRow = I422ToARGBRow_SSSE3;
84
35
    }
85
152
  }
86
152
#endif
87
152
#if defined(HAS_I422TOARGBROW_AVX2)
88
152
  if (TestCpuFlag(kCpuHasAVX2)) {
89
152
    I422ToARGBRow = I422ToARGBRow_Any_AVX2;
90
152
    if (IS_ALIGNED(width, 16)) {
91
17
      I422ToARGBRow = I422ToARGBRow_AVX2;
92
17
    }
93
152
  }
94
152
#endif
95
152
#if defined(HAS_I422TOARGBROW_AVX512BW)
96
152
  if (TestCpuFlag(kCpuHasAVX512BW | kCpuHasAVX512VL) ==
97
152
      (kCpuHasAVX512BW | kCpuHasAVX512VL)) {
98
0
    I422ToARGBRow = I422ToARGBRow_Any_AVX512BW;
99
0
    if (IS_ALIGNED(width, 32)) {
100
0
      I422ToARGBRow = I422ToARGBRow_AVX512BW;
101
0
    }
102
0
  }
103
152
#endif
104
#if defined(HAS_I422TOARGBROW_NEON)
105
  if (TestCpuFlag(kCpuHasNEON)) {
106
    I422ToARGBRow = I422ToARGBRow_Any_NEON;
107
    if (IS_ALIGNED(width, 8)) {
108
      I422ToARGBRow = I422ToARGBRow_NEON;
109
    }
110
  }
111
#endif
112
#if defined(HAS_I422TOARGBROW_SVE2)
113
  if (TestCpuFlag(kCpuHasSVE2)) {
114
    I422ToARGBRow = I422ToARGBRow_SVE2;
115
  }
116
#endif
117
#if defined(HAS_I422TOARGBROW_SME)
118
  if (TestCpuFlag(kCpuHasSME)) {
119
    I422ToARGBRow = I422ToARGBRow_SME;
120
  }
121
#endif
122
#if defined(HAS_I422TOARGBROW_MSA)
123
  if (TestCpuFlag(kCpuHasMSA)) {
124
    I422ToARGBRow = I422ToARGBRow_Any_MSA;
125
    if (IS_ALIGNED(width, 8)) {
126
      I422ToARGBRow = I422ToARGBRow_MSA;
127
    }
128
  }
129
#endif
130
#if defined(HAS_I422TOARGBROW_LSX)
131
  if (TestCpuFlag(kCpuHasLSX)) {
132
    I422ToARGBRow = I422ToARGBRow_Any_LSX;
133
    if (IS_ALIGNED(width, 16)) {
134
      I422ToARGBRow = I422ToARGBRow_LSX;
135
    }
136
  }
137
#endif
138
#if defined(HAS_I422TOARGBROW_LASX)
139
  if (TestCpuFlag(kCpuHasLASX)) {
140
    I422ToARGBRow = I422ToARGBRow_Any_LASX;
141
    if (IS_ALIGNED(width, 32)) {
142
      I422ToARGBRow = I422ToARGBRow_LASX;
143
    }
144
  }
145
#endif
146
#if defined(HAS_I422TOARGBROW_RVV)
147
  if (TestCpuFlag(kCpuHasRVV)) {
148
    I422ToARGBRow = I422ToARGBRow_RVV;
149
  }
150
#endif
151
152
2.52k
  for (y = 0; y < height; ++y) {
153
2.37k
    I422ToARGBRow(src_y, src_u, src_v, dst_argb, yuvconstants, width);
154
2.37k
    dst_argb += dst_stride_argb;
155
2.37k
    src_y += src_stride_y;
156
2.37k
    if (y & 1) {
157
1.16k
      src_u += src_stride_u;
158
1.16k
      src_v += src_stride_v;
159
1.16k
    }
160
2.37k
  }
161
152
  return 0;
162
152
}
163
164
// Convert I420 to ARGB.
165
LIBYUV_API
166
int I420ToARGB(const uint8_t* src_y,
167
               int src_stride_y,
168
               const uint8_t* src_u,
169
               int src_stride_u,
170
               const uint8_t* src_v,
171
               int src_stride_v,
172
               uint8_t* dst_argb,
173
               int dst_stride_argb,
174
               int width,
175
0
               int height) {
176
0
  return I420ToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
177
0
                          src_stride_v, dst_argb, dst_stride_argb,
178
0
                          &kYuvI601Constants, width, height);
179
0
}
180
181
// Convert I420 to ABGR.
182
LIBYUV_API
183
int I420ToABGR(const uint8_t* src_y,
184
               int src_stride_y,
185
               const uint8_t* src_u,
186
               int src_stride_u,
187
               const uint8_t* src_v,
188
               int src_stride_v,
189
               uint8_t* dst_abgr,
190
               int dst_stride_abgr,
191
               int width,
192
0
               int height) {
193
0
  return I420ToARGBMatrix(src_y, src_stride_y, src_v,
194
0
                          src_stride_v,  // Swap U and V
195
0
                          src_u, src_stride_u, dst_abgr, dst_stride_abgr,
196
0
                          &kYvuI601Constants,  // Use Yvu matrix
197
0
                          width, height);
198
0
}
199
200
// Convert J420 to ARGB.
201
LIBYUV_API
202
int J420ToARGB(const uint8_t* src_y,
203
               int src_stride_y,
204
               const uint8_t* src_u,
205
               int src_stride_u,
206
               const uint8_t* src_v,
207
               int src_stride_v,
208
               uint8_t* dst_argb,
209
               int dst_stride_argb,
210
               int width,
211
0
               int height) {
212
0
  return I420ToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
213
0
                          src_stride_v, dst_argb, dst_stride_argb,
214
0
                          &kYuvJPEGConstants, width, height);
215
0
}
216
217
// Convert J420 to ABGR.
218
LIBYUV_API
219
int J420ToABGR(const uint8_t* src_y,
220
               int src_stride_y,
221
               const uint8_t* src_u,
222
               int src_stride_u,
223
               const uint8_t* src_v,
224
               int src_stride_v,
225
               uint8_t* dst_abgr,
226
               int dst_stride_abgr,
227
               int width,
228
0
               int height) {
229
0
  return I420ToARGBMatrix(src_y, src_stride_y, src_v,
230
0
                          src_stride_v,  // Swap U and V
231
0
                          src_u, src_stride_u, dst_abgr, dst_stride_abgr,
232
0
                          &kYvuJPEGConstants,  // Use Yvu matrix
233
0
                          width, height);
234
0
}
235
236
// Convert H420 to ARGB.
237
LIBYUV_API
238
int H420ToARGB(const uint8_t* src_y,
239
               int src_stride_y,
240
               const uint8_t* src_u,
241
               int src_stride_u,
242
               const uint8_t* src_v,
243
               int src_stride_v,
244
               uint8_t* dst_argb,
245
               int dst_stride_argb,
246
               int width,
247
0
               int height) {
248
0
  return I420ToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
249
0
                          src_stride_v, dst_argb, dst_stride_argb,
250
0
                          &kYuvH709Constants, width, height);
251
0
}
252
253
// Convert H420 to ABGR.
254
LIBYUV_API
255
int H420ToABGR(const uint8_t* src_y,
256
               int src_stride_y,
257
               const uint8_t* src_u,
258
               int src_stride_u,
259
               const uint8_t* src_v,
260
               int src_stride_v,
261
               uint8_t* dst_abgr,
262
               int dst_stride_abgr,
263
               int width,
264
0
               int height) {
265
0
  return I420ToARGBMatrix(src_y, src_stride_y, src_v,
266
0
                          src_stride_v,  // Swap U and V
267
0
                          src_u, src_stride_u, dst_abgr, dst_stride_abgr,
268
0
                          &kYvuH709Constants,  // Use Yvu matrix
269
0
                          width, height);
270
0
}
271
272
// Convert U420 to ARGB.
273
LIBYUV_API
274
int U420ToARGB(const uint8_t* src_y,
275
               int src_stride_y,
276
               const uint8_t* src_u,
277
               int src_stride_u,
278
               const uint8_t* src_v,
279
               int src_stride_v,
280
               uint8_t* dst_argb,
281
               int dst_stride_argb,
282
               int width,
283
0
               int height) {
284
0
  return I420ToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
285
0
                          src_stride_v, dst_argb, dst_stride_argb,
286
0
                          &kYuv2020Constants, width, height);
287
0
}
288
289
// Convert U420 to ABGR.
290
LIBYUV_API
291
int U420ToABGR(const uint8_t* src_y,
292
               int src_stride_y,
293
               const uint8_t* src_u,
294
               int src_stride_u,
295
               const uint8_t* src_v,
296
               int src_stride_v,
297
               uint8_t* dst_abgr,
298
               int dst_stride_abgr,
299
               int width,
300
0
               int height) {
301
0
  return I420ToARGBMatrix(src_y, src_stride_y, src_v,
302
0
                          src_stride_v,  // Swap U and V
303
0
                          src_u, src_stride_u, dst_abgr, dst_stride_abgr,
304
0
                          &kYvu2020Constants,  // Use Yvu matrix
305
0
                          width, height);
306
0
}
307
308
// Convert I422 to ARGB with matrix.
309
LIBYUV_API
310
int I422ToARGBMatrix(const uint8_t* src_y,
311
                     int src_stride_y,
312
                     const uint8_t* src_u,
313
                     int src_stride_u,
314
                     const uint8_t* src_v,
315
                     int src_stride_v,
316
                     uint8_t* dst_argb,
317
                     int dst_stride_argb,
318
                     const struct YuvConstants* yuvconstants,
319
                     int width,
320
108
                     int height) {
321
108
  int y;
322
108
  void (*I422ToARGBRow)(const uint8_t* y_buf, const uint8_t* u_buf,
323
108
                        const uint8_t* v_buf, uint8_t* rgb_buf,
324
108
                        const struct YuvConstants* yuvconstants, int width) =
325
108
      I422ToARGBRow_C;
326
108
  assert(yuvconstants);
327
108
  if (!src_y || !src_u || !src_v || !dst_argb || width <= 0 || height == 0) {
328
0
    return -1;
329
0
  }
330
  // Negative height means invert the image.
331
108
  if (height < 0) {
332
0
    height = -height;
333
0
    dst_argb = dst_argb + (height - 1) * dst_stride_argb;
334
0
    dst_stride_argb = -dst_stride_argb;
335
0
  }
336
  // Coalesce rows.
337
108
  if (src_stride_y == width && src_stride_u * 2 == width &&
338
57
      src_stride_v * 2 == width && dst_stride_argb == width * 4) {
339
57
    width *= height;
340
57
    height = 1;
341
57
    src_stride_y = src_stride_u = src_stride_v = dst_stride_argb = 0;
342
57
  }
343
108
#if defined(HAS_I422TOARGBROW_SSSE3)
344
108
  if (TestCpuFlag(kCpuHasSSSE3)) {
345
108
    I422ToARGBRow = I422ToARGBRow_Any_SSSE3;
346
108
    if (IS_ALIGNED(width, 8)) {
347
37
      I422ToARGBRow = I422ToARGBRow_SSSE3;
348
37
    }
349
108
  }
350
108
#endif
351
108
#if defined(HAS_I422TOARGBROW_AVX2)
352
108
  if (TestCpuFlag(kCpuHasAVX2)) {
353
108
    I422ToARGBRow = I422ToARGBRow_Any_AVX2;
354
108
    if (IS_ALIGNED(width, 16)) {
355
17
      I422ToARGBRow = I422ToARGBRow_AVX2;
356
17
    }
357
108
  }
358
108
#endif
359
108
#if defined(HAS_I422TOARGBROW_AVX512BW)
360
108
  if (TestCpuFlag(kCpuHasAVX512BW | kCpuHasAVX512VL) ==
361
108
      (kCpuHasAVX512BW | kCpuHasAVX512VL)) {
362
0
    I422ToARGBRow = I422ToARGBRow_Any_AVX512BW;
363
0
    if (IS_ALIGNED(width, 32)) {
364
0
      I422ToARGBRow = I422ToARGBRow_AVX512BW;
365
0
    }
366
0
  }
367
108
#endif
368
#if defined(HAS_I422TOARGBROW_NEON)
369
  if (TestCpuFlag(kCpuHasNEON)) {
370
    I422ToARGBRow = I422ToARGBRow_Any_NEON;
371
    if (IS_ALIGNED(width, 8)) {
372
      I422ToARGBRow = I422ToARGBRow_NEON;
373
    }
374
  }
375
#endif
376
#if defined(HAS_I422TOARGBROW_SVE2)
377
  if (TestCpuFlag(kCpuHasSVE2)) {
378
    I422ToARGBRow = I422ToARGBRow_SVE2;
379
  }
380
#endif
381
#if defined(HAS_I422TOARGBROW_SME)
382
  if (TestCpuFlag(kCpuHasSME)) {
383
    I422ToARGBRow = I422ToARGBRow_SME;
384
  }
385
#endif
386
#if defined(HAS_I422TOARGBROW_MSA)
387
  if (TestCpuFlag(kCpuHasMSA)) {
388
    I422ToARGBRow = I422ToARGBRow_Any_MSA;
389
    if (IS_ALIGNED(width, 8)) {
390
      I422ToARGBRow = I422ToARGBRow_MSA;
391
    }
392
  }
393
#endif
394
#if defined(HAS_I422TOARGBROW_LSX)
395
  if (TestCpuFlag(kCpuHasLSX)) {
396
    I422ToARGBRow = I422ToARGBRow_Any_LSX;
397
    if (IS_ALIGNED(width, 16)) {
398
      I422ToARGBRow = I422ToARGBRow_LSX;
399
    }
400
  }
401
#endif
402
#if defined(HAS_I422TOARGBROW_LASX)
403
  if (TestCpuFlag(kCpuHasLASX)) {
404
    I422ToARGBRow = I422ToARGBRow_Any_LASX;
405
    if (IS_ALIGNED(width, 32)) {
406
      I422ToARGBRow = I422ToARGBRow_LASX;
407
    }
408
  }
409
#endif
410
#if defined(HAS_I422TOARGBROW_RVV)
411
  if (TestCpuFlag(kCpuHasRVV)) {
412
    I422ToARGBRow = I422ToARGBRow_RVV;
413
  }
414
#endif
415
416
1.68k
  for (y = 0; y < height; ++y) {
417
1.58k
    I422ToARGBRow(src_y, src_u, src_v, dst_argb, yuvconstants, width);
418
1.58k
    dst_argb += dst_stride_argb;
419
1.58k
    src_y += src_stride_y;
420
1.58k
    src_u += src_stride_u;
421
1.58k
    src_v += src_stride_v;
422
1.58k
  }
423
108
  return 0;
424
108
}
425
426
// Convert I422 to ARGB.
427
LIBYUV_API
428
int I422ToARGB(const uint8_t* src_y,
429
               int src_stride_y,
430
               const uint8_t* src_u,
431
               int src_stride_u,
432
               const uint8_t* src_v,
433
               int src_stride_v,
434
               uint8_t* dst_argb,
435
               int dst_stride_argb,
436
               int width,
437
0
               int height) {
438
0
  return I422ToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
439
0
                          src_stride_v, dst_argb, dst_stride_argb,
440
0
                          &kYuvI601Constants, width, height);
441
0
}
442
443
// Convert I422 to ABGR.
444
LIBYUV_API
445
int I422ToABGR(const uint8_t* src_y,
446
               int src_stride_y,
447
               const uint8_t* src_u,
448
               int src_stride_u,
449
               const uint8_t* src_v,
450
               int src_stride_v,
451
               uint8_t* dst_abgr,
452
               int dst_stride_abgr,
453
               int width,
454
0
               int height) {
455
0
  return I422ToARGBMatrix(src_y, src_stride_y, src_v,
456
0
                          src_stride_v,  // Swap U and V
457
0
                          src_u, src_stride_u, dst_abgr, dst_stride_abgr,
458
0
                          &kYvuI601Constants,  // Use Yvu matrix
459
0
                          width, height);
460
0
}
461
462
// Convert J422 to ARGB.
463
LIBYUV_API
464
int J422ToARGB(const uint8_t* src_y,
465
               int src_stride_y,
466
               const uint8_t* src_u,
467
               int src_stride_u,
468
               const uint8_t* src_v,
469
               int src_stride_v,
470
               uint8_t* dst_argb,
471
               int dst_stride_argb,
472
               int width,
473
0
               int height) {
474
0
  return I422ToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
475
0
                          src_stride_v, dst_argb, dst_stride_argb,
476
0
                          &kYuvJPEGConstants, width, height);
477
0
}
478
479
// Convert J422 to ABGR.
480
LIBYUV_API
481
int J422ToABGR(const uint8_t* src_y,
482
               int src_stride_y,
483
               const uint8_t* src_u,
484
               int src_stride_u,
485
               const uint8_t* src_v,
486
               int src_stride_v,
487
               uint8_t* dst_abgr,
488
               int dst_stride_abgr,
489
               int width,
490
0
               int height) {
491
0
  return I422ToARGBMatrix(src_y, src_stride_y, src_v,
492
0
                          src_stride_v,  // Swap U and V
493
0
                          src_u, src_stride_u, dst_abgr, dst_stride_abgr,
494
0
                          &kYvuJPEGConstants,  // Use Yvu matrix
495
0
                          width, height);
496
0
}
497
498
// Convert H422 to ARGB.
499
LIBYUV_API
500
int H422ToARGB(const uint8_t* src_y,
501
               int src_stride_y,
502
               const uint8_t* src_u,
503
               int src_stride_u,
504
               const uint8_t* src_v,
505
               int src_stride_v,
506
               uint8_t* dst_argb,
507
               int dst_stride_argb,
508
               int width,
509
0
               int height) {
510
0
  return I422ToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
511
0
                          src_stride_v, dst_argb, dst_stride_argb,
512
0
                          &kYuvH709Constants, width, height);
513
0
}
514
515
// Convert H422 to ABGR.
516
LIBYUV_API
517
int H422ToABGR(const uint8_t* src_y,
518
               int src_stride_y,
519
               const uint8_t* src_u,
520
               int src_stride_u,
521
               const uint8_t* src_v,
522
               int src_stride_v,
523
               uint8_t* dst_abgr,
524
               int dst_stride_abgr,
525
               int width,
526
0
               int height) {
527
0
  return I422ToARGBMatrix(src_y, src_stride_y, src_v,
528
0
                          src_stride_v,  // Swap U and V
529
0
                          src_u, src_stride_u, dst_abgr, dst_stride_abgr,
530
0
                          &kYvuH709Constants,  // Use Yvu matrix
531
0
                          width, height);
532
0
}
533
534
// Convert U422 to ARGB.
535
LIBYUV_API
536
int U422ToARGB(const uint8_t* src_y,
537
               int src_stride_y,
538
               const uint8_t* src_u,
539
               int src_stride_u,
540
               const uint8_t* src_v,
541
               int src_stride_v,
542
               uint8_t* dst_argb,
543
               int dst_stride_argb,
544
               int width,
545
0
               int height) {
546
0
  return I422ToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
547
0
                          src_stride_v, dst_argb, dst_stride_argb,
548
0
                          &kYuv2020Constants, width, height);
549
0
}
550
551
// Convert U422 to ABGR.
552
LIBYUV_API
553
int U422ToABGR(const uint8_t* src_y,
554
               int src_stride_y,
555
               const uint8_t* src_u,
556
               int src_stride_u,
557
               const uint8_t* src_v,
558
               int src_stride_v,
559
               uint8_t* dst_abgr,
560
               int dst_stride_abgr,
561
               int width,
562
0
               int height) {
563
0
  return I422ToARGBMatrix(src_y, src_stride_y, src_v,
564
0
                          src_stride_v,  // Swap U and V
565
0
                          src_u, src_stride_u, dst_abgr, dst_stride_abgr,
566
0
                          &kYvu2020Constants,  // Use Yvu matrix
567
0
                          width, height);
568
0
}
569
570
// Convert I444 to ARGB with matrix.
571
LIBYUV_API
572
int I444ToARGBMatrix(const uint8_t* src_y,
573
                     int src_stride_y,
574
                     const uint8_t* src_u,
575
                     int src_stride_u,
576
                     const uint8_t* src_v,
577
                     int src_stride_v,
578
                     uint8_t* dst_argb,
579
                     int dst_stride_argb,
580
                     const struct YuvConstants* yuvconstants,
581
                     int width,
582
76
                     int height) {
583
76
  int y;
584
76
  void (*I444ToARGBRow)(const uint8_t* y_buf, const uint8_t* u_buf,
585
76
                        const uint8_t* v_buf, uint8_t* rgb_buf,
586
76
                        const struct YuvConstants* yuvconstants, int width) =
587
76
      I444ToARGBRow_C;
588
76
  assert(yuvconstants);
589
76
  if (!src_y || !src_u || !src_v || !dst_argb || width <= 0 || height == 0) {
590
0
    return -1;
591
0
  }
592
  // Negative height means invert the image.
593
76
  if (height < 0) {
594
0
    height = -height;
595
0
    dst_argb = dst_argb + (height - 1) * dst_stride_argb;
596
0
    dst_stride_argb = -dst_stride_argb;
597
0
  }
598
  // Coalesce rows.
599
76
  if (src_stride_y == width && src_stride_u == width && src_stride_v == width &&
600
76
      dst_stride_argb == width * 4) {
601
76
    width *= height;
602
76
    height = 1;
603
76
    src_stride_y = src_stride_u = src_stride_v = dst_stride_argb = 0;
604
76
  }
605
76
#if defined(HAS_I444TOARGBROW_SSSE3)
606
76
  if (TestCpuFlag(kCpuHasSSSE3)) {
607
76
    I444ToARGBRow = I444ToARGBRow_Any_SSSE3;
608
76
    if (IS_ALIGNED(width, 8)) {
609
37
      I444ToARGBRow = I444ToARGBRow_SSSE3;
610
37
    }
611
76
  }
612
76
#endif
613
76
#if defined(HAS_I444TOARGBROW_AVX2)
614
76
  if (TestCpuFlag(kCpuHasAVX2)) {
615
76
    I444ToARGBRow = I444ToARGBRow_Any_AVX2;
616
76
    if (IS_ALIGNED(width, 16)) {
617
17
      I444ToARGBRow = I444ToARGBRow_AVX2;
618
17
    }
619
76
  }
620
76
#endif
621
#if defined(HAS_I444TOARGBROW_NEON)
622
  if (TestCpuFlag(kCpuHasNEON)) {
623
    I444ToARGBRow = I444ToARGBRow_Any_NEON;
624
    if (IS_ALIGNED(width, 8)) {
625
      I444ToARGBRow = I444ToARGBRow_NEON;
626
    }
627
  }
628
#endif
629
#if defined(HAS_I444TOARGBROW_SVE2)
630
  if (TestCpuFlag(kCpuHasSVE2)) {
631
    I444ToARGBRow = I444ToARGBRow_SVE2;
632
  }
633
#endif
634
#if defined(HAS_I444TOARGBROW_SME)
635
  if (TestCpuFlag(kCpuHasSME)) {
636
    I444ToARGBRow = I444ToARGBRow_SME;
637
  }
638
#endif
639
#if defined(HAS_I444TOARGBROW_MSA)
640
  if (TestCpuFlag(kCpuHasMSA)) {
641
    I444ToARGBRow = I444ToARGBRow_Any_MSA;
642
    if (IS_ALIGNED(width, 8)) {
643
      I444ToARGBRow = I444ToARGBRow_MSA;
644
    }
645
  }
646
#endif
647
#if defined(HAS_I444TOARGBROW_LSX)
648
  if (TestCpuFlag(kCpuHasLSX)) {
649
    I444ToARGBRow = I444ToARGBRow_Any_LSX;
650
    if (IS_ALIGNED(width, 16)) {
651
      I444ToARGBRow = I444ToARGBRow_LSX;
652
    }
653
  }
654
#endif
655
#if defined(HAS_I444TOARGBROW_RVV)
656
  if (TestCpuFlag(kCpuHasRVV)) {
657
    I444ToARGBRow = I444ToARGBRow_RVV;
658
  }
659
#endif
660
661
152
  for (y = 0; y < height; ++y) {
662
76
    I444ToARGBRow(src_y, src_u, src_v, dst_argb, yuvconstants, width);
663
76
    dst_argb += dst_stride_argb;
664
76
    src_y += src_stride_y;
665
76
    src_u += src_stride_u;
666
76
    src_v += src_stride_v;
667
76
  }
668
76
  return 0;
669
76
}
670
671
// Convert I444 to ARGB.
672
LIBYUV_API
673
int I444ToARGB(const uint8_t* src_y,
674
               int src_stride_y,
675
               const uint8_t* src_u,
676
               int src_stride_u,
677
               const uint8_t* src_v,
678
               int src_stride_v,
679
               uint8_t* dst_argb,
680
               int dst_stride_argb,
681
               int width,
682
0
               int height) {
683
0
  return I444ToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
684
0
                          src_stride_v, dst_argb, dst_stride_argb,
685
0
                          &kYuvI601Constants, width, height);
686
0
}
687
688
// Convert I444 to ABGR.
689
LIBYUV_API
690
int I444ToABGR(const uint8_t* src_y,
691
               int src_stride_y,
692
               const uint8_t* src_u,
693
               int src_stride_u,
694
               const uint8_t* src_v,
695
               int src_stride_v,
696
               uint8_t* dst_abgr,
697
               int dst_stride_abgr,
698
               int width,
699
0
               int height) {
700
0
  return I444ToARGBMatrix(src_y, src_stride_y, src_v,
701
0
                          src_stride_v,  // Swap U and V
702
0
                          src_u, src_stride_u, dst_abgr, dst_stride_abgr,
703
0
                          &kYvuI601Constants,  // Use Yvu matrix
704
0
                          width, height);
705
0
}
706
707
// Convert J444 to ARGB.
708
LIBYUV_API
709
int J444ToARGB(const uint8_t* src_y,
710
               int src_stride_y,
711
               const uint8_t* src_u,
712
               int src_stride_u,
713
               const uint8_t* src_v,
714
               int src_stride_v,
715
               uint8_t* dst_argb,
716
               int dst_stride_argb,
717
               int width,
718
0
               int height) {
719
0
  return I444ToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
720
0
                          src_stride_v, dst_argb, dst_stride_argb,
721
0
                          &kYuvJPEGConstants, width, height);
722
0
}
723
724
// Convert J444 to ABGR.
725
LIBYUV_API
726
int J444ToABGR(const uint8_t* src_y,
727
               int src_stride_y,
728
               const uint8_t* src_u,
729
               int src_stride_u,
730
               const uint8_t* src_v,
731
               int src_stride_v,
732
               uint8_t* dst_abgr,
733
               int dst_stride_abgr,
734
               int width,
735
0
               int height) {
736
0
  return I444ToARGBMatrix(src_y, src_stride_y, src_v,
737
0
                          src_stride_v,  // Swap U and V
738
0
                          src_u, src_stride_u, dst_abgr, dst_stride_abgr,
739
0
                          &kYvuJPEGConstants,  // Use Yvu matrix
740
0
                          width, height);
741
0
}
742
743
// Convert H444 to ARGB.
744
LIBYUV_API
745
int H444ToARGB(const uint8_t* src_y,
746
               int src_stride_y,
747
               const uint8_t* src_u,
748
               int src_stride_u,
749
               const uint8_t* src_v,
750
               int src_stride_v,
751
               uint8_t* dst_argb,
752
               int dst_stride_argb,
753
               int width,
754
0
               int height) {
755
0
  return I444ToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
756
0
                          src_stride_v, dst_argb, dst_stride_argb,
757
0
                          &kYuvH709Constants, width, height);
758
0
}
759
760
// Convert H444 to ABGR.
761
LIBYUV_API
762
int H444ToABGR(const uint8_t* src_y,
763
               int src_stride_y,
764
               const uint8_t* src_u,
765
               int src_stride_u,
766
               const uint8_t* src_v,
767
               int src_stride_v,
768
               uint8_t* dst_abgr,
769
               int dst_stride_abgr,
770
               int width,
771
0
               int height) {
772
0
  return I444ToARGBMatrix(src_y, src_stride_y, src_v,
773
0
                          src_stride_v,  // Swap U and V
774
0
                          src_u, src_stride_u, dst_abgr, dst_stride_abgr,
775
0
                          &kYvuH709Constants,  // Use Yvu matrix
776
0
                          width, height);
777
0
}
778
779
// Convert U444 to ARGB.
780
LIBYUV_API
781
int U444ToARGB(const uint8_t* src_y,
782
               int src_stride_y,
783
               const uint8_t* src_u,
784
               int src_stride_u,
785
               const uint8_t* src_v,
786
               int src_stride_v,
787
               uint8_t* dst_argb,
788
               int dst_stride_argb,
789
               int width,
790
0
               int height) {
791
0
  return I444ToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
792
0
                          src_stride_v, dst_argb, dst_stride_argb,
793
0
                          &kYuv2020Constants, width, height);
794
0
}
795
796
// Convert U444 to ABGR.
797
LIBYUV_API
798
int U444ToABGR(const uint8_t* src_y,
799
               int src_stride_y,
800
               const uint8_t* src_u,
801
               int src_stride_u,
802
               const uint8_t* src_v,
803
               int src_stride_v,
804
               uint8_t* dst_abgr,
805
               int dst_stride_abgr,
806
               int width,
807
0
               int height) {
808
0
  return I444ToARGBMatrix(src_y, src_stride_y, src_v,
809
0
                          src_stride_v,  // Swap U and V
810
0
                          src_u, src_stride_u, dst_abgr, dst_stride_abgr,
811
0
                          &kYvu2020Constants,  // Use Yvu matrix
812
0
                          width, height);
813
0
}
814
815
// Convert I444 to RGB24 with matrix.
816
LIBYUV_API
817
int I444ToRGB24Matrix(const uint8_t* src_y,
818
                      int src_stride_y,
819
                      const uint8_t* src_u,
820
                      int src_stride_u,
821
                      const uint8_t* src_v,
822
                      int src_stride_v,
823
                      uint8_t* dst_rgb24,
824
                      int dst_stride_rgb24,
825
                      const struct YuvConstants* yuvconstants,
826
                      int width,
827
123
                      int height) {
828
123
  int y;
829
123
  void (*I444ToRGB24Row)(const uint8_t* y_buf, const uint8_t* u_buf,
830
123
                         const uint8_t* v_buf, uint8_t* rgb_buf,
831
123
                         const struct YuvConstants* yuvconstants, int width) =
832
123
      I444ToRGB24Row_C;
833
123
  assert(yuvconstants);
834
123
  if (!src_y || !src_u || !src_v || !dst_rgb24 || width <= 0 || height == 0) {
835
0
    return -1;
836
0
  }
837
  // Negative height means invert the image.
838
123
  if (height < 0) {
839
0
    height = -height;
840
0
    dst_rgb24 = dst_rgb24 + (height - 1) * dst_stride_rgb24;
841
0
    dst_stride_rgb24 = -dst_stride_rgb24;
842
0
  }
843
  // Coalesce rows.
844
123
  if (src_stride_y == width && src_stride_u == width && src_stride_v == width &&
845
123
      dst_stride_rgb24 == width * 3) {
846
123
    width *= height;
847
123
    height = 1;
848
123
    src_stride_y = src_stride_u = src_stride_v = dst_stride_rgb24 = 0;
849
123
  }
850
123
#if defined(HAS_I444TORGB24ROW_SSSE3)
851
123
  if (TestCpuFlag(kCpuHasSSSE3)) {
852
123
    I444ToRGB24Row = I444ToRGB24Row_Any_SSSE3;
853
123
    if (IS_ALIGNED(width, 16)) {
854
60
      I444ToRGB24Row = I444ToRGB24Row_SSSE3;
855
60
    }
856
123
  }
857
123
#endif
858
123
#if defined(HAS_I444TORGB24ROW_AVX2)
859
123
  if (TestCpuFlag(kCpuHasAVX2)) {
860
123
    I444ToRGB24Row = I444ToRGB24Row_Any_AVX2;
861
123
    if (IS_ALIGNED(width, 32)) {
862
33
      I444ToRGB24Row = I444ToRGB24Row_AVX2;
863
33
    }
864
123
  }
865
123
#endif
866
#if defined(HAS_I444TORGB24ROW_NEON)
867
  if (TestCpuFlag(kCpuHasNEON)) {
868
    I444ToRGB24Row = I444ToRGB24Row_Any_NEON;
869
    if (IS_ALIGNED(width, 8)) {
870
      I444ToRGB24Row = I444ToRGB24Row_NEON;
871
    }
872
  }
873
#endif
874
#if defined(HAS_I444TORGB24ROW_MSA)
875
  if (TestCpuFlag(kCpuHasMSA)) {
876
    I444ToRGB24Row = I444ToRGB24Row_Any_MSA;
877
    if (IS_ALIGNED(width, 8)) {
878
      I444ToRGB24Row = I444ToRGB24Row_MSA;
879
    }
880
  }
881
#endif
882
#if defined(HAS_I444TORGB24ROW_LSX)
883
  if (TestCpuFlag(kCpuHasLSX)) {
884
    I444ToRGB24Row = I444ToRGB24Row_Any_LSX;
885
    if (IS_ALIGNED(width, 16)) {
886
      I444ToRGB24Row = I444ToRGB24Row_LSX;
887
    }
888
  }
889
#endif
890
#if defined(HAS_I444TORGB24ROW_RVV)
891
  if (TestCpuFlag(kCpuHasRVV)) {
892
    I444ToRGB24Row = I444ToRGB24Row_RVV;
893
  }
894
#endif
895
896
246
  for (y = 0; y < height; ++y) {
897
123
    I444ToRGB24Row(src_y, src_u, src_v, dst_rgb24, yuvconstants, width);
898
123
    dst_rgb24 += dst_stride_rgb24;
899
123
    src_y += src_stride_y;
900
123
    src_u += src_stride_u;
901
123
    src_v += src_stride_v;
902
123
  }
903
123
  return 0;
904
123
}
905
906
// Convert I444 to RGB24.
907
LIBYUV_API
908
int I444ToRGB24(const uint8_t* src_y,
909
                int src_stride_y,
910
                const uint8_t* src_u,
911
                int src_stride_u,
912
                const uint8_t* src_v,
913
                int src_stride_v,
914
                uint8_t* dst_rgb24,
915
                int dst_stride_rgb24,
916
                int width,
917
0
                int height) {
918
0
  return I444ToRGB24Matrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
919
0
                           src_stride_v, dst_rgb24, dst_stride_rgb24,
920
0
                           &kYuvI601Constants, width, height);
921
0
}
922
923
// Convert I444 to RAW.
924
LIBYUV_API
925
int I444ToRAW(const uint8_t* src_y,
926
              int src_stride_y,
927
              const uint8_t* src_u,
928
              int src_stride_u,
929
              const uint8_t* src_v,
930
              int src_stride_v,
931
              uint8_t* dst_raw,
932
              int dst_stride_raw,
933
              int width,
934
0
              int height) {
935
0
  return I444ToRGB24Matrix(src_y, src_stride_y, src_v,
936
0
                           src_stride_v,  // Swap U and V
937
0
                           src_u, src_stride_u, dst_raw, dst_stride_raw,
938
0
                           &kYvuI601Constants,  // Use Yvu matrix
939
0
                           width, height);
940
0
}
941
942
// Convert 10 bit YUV to ARGB with matrix.
943
// TODO(fbarchard): Consider passing scale multiplier to I210ToARGB to
944
// multiply 10 bit yuv into high bits to allow any number of bits.
945
LIBYUV_API
946
int I010ToAR30Matrix(const uint16_t* src_y,
947
                     int src_stride_y,
948
                     const uint16_t* src_u,
949
                     int src_stride_u,
950
                     const uint16_t* src_v,
951
                     int src_stride_v,
952
                     uint8_t* dst_ar30,
953
                     int dst_stride_ar30,
954
                     const struct YuvConstants* yuvconstants,
955
                     int width,
956
0
                     int height) {
957
0
  int y;
958
0
  void (*I210ToAR30Row)(const uint16_t* y_buf, const uint16_t* u_buf,
959
0
                        const uint16_t* v_buf, uint8_t* rgb_buf,
960
0
                        const struct YuvConstants* yuvconstants, int width) =
961
0
      I210ToAR30Row_C;
962
0
  assert(yuvconstants);
963
0
  if (!src_y || !src_u || !src_v || !dst_ar30 || width <= 0 || height == 0) {
964
0
    return -1;
965
0
  }
966
  // Negative height means invert the image.
967
0
  if (height < 0) {
968
0
    height = -height;
969
0
    dst_ar30 = dst_ar30 + (height - 1) * dst_stride_ar30;
970
0
    dst_stride_ar30 = -dst_stride_ar30;
971
0
  }
972
#if defined(HAS_I210TOAR30ROW_NEON)
973
  if (TestCpuFlag(kCpuHasNEON)) {
974
    I210ToAR30Row = I210ToAR30Row_Any_NEON;
975
    if (IS_ALIGNED(width, 8)) {
976
      I210ToAR30Row = I210ToAR30Row_NEON;
977
    }
978
  }
979
#endif
980
#if defined(HAS_I210TOAR30ROW_SVE2)
981
  if (TestCpuFlag(kCpuHasSVE2)) {
982
    I210ToAR30Row = I210ToAR30Row_SVE2;
983
  }
984
#endif
985
#if defined(HAS_I210TOAR30ROW_SME)
986
  if (TestCpuFlag(kCpuHasSME)) {
987
    I210ToAR30Row = I210ToAR30Row_SME;
988
  }
989
#endif
990
0
#if defined(HAS_I210TOAR30ROW_SSSE3)
991
0
  if (TestCpuFlag(kCpuHasSSSE3)) {
992
0
    I210ToAR30Row = I210ToAR30Row_Any_SSSE3;
993
0
    if (IS_ALIGNED(width, 8)) {
994
0
      I210ToAR30Row = I210ToAR30Row_SSSE3;
995
0
    }
996
0
  }
997
0
#endif
998
0
#if defined(HAS_I210TOAR30ROW_AVX2)
999
0
  if (TestCpuFlag(kCpuHasAVX2)) {
1000
0
    I210ToAR30Row = I210ToAR30Row_Any_AVX2;
1001
0
    if (IS_ALIGNED(width, 16)) {
1002
0
      I210ToAR30Row = I210ToAR30Row_AVX2;
1003
0
    }
1004
0
  }
1005
0
#endif
1006
0
  for (y = 0; y < height; ++y) {
1007
0
    I210ToAR30Row(src_y, src_u, src_v, dst_ar30, yuvconstants, width);
1008
0
    dst_ar30 += dst_stride_ar30;
1009
0
    src_y += src_stride_y;
1010
0
    if (y & 1) {
1011
0
      src_u += src_stride_u;
1012
0
      src_v += src_stride_v;
1013
0
    }
1014
0
  }
1015
0
  return 0;
1016
0
}
1017
1018
// Convert I010 to AR30.
1019
LIBYUV_API
1020
int I010ToAR30(const uint16_t* src_y,
1021
               int src_stride_y,
1022
               const uint16_t* src_u,
1023
               int src_stride_u,
1024
               const uint16_t* src_v,
1025
               int src_stride_v,
1026
               uint8_t* dst_ar30,
1027
               int dst_stride_ar30,
1028
               int width,
1029
0
               int height) {
1030
0
  return I010ToAR30Matrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
1031
0
                          src_stride_v, dst_ar30, dst_stride_ar30,
1032
0
                          &kYuvI601Constants, width, height);
1033
0
}
1034
1035
// Convert H010 to AR30.
1036
LIBYUV_API
1037
int H010ToAR30(const uint16_t* src_y,
1038
               int src_stride_y,
1039
               const uint16_t* src_u,
1040
               int src_stride_u,
1041
               const uint16_t* src_v,
1042
               int src_stride_v,
1043
               uint8_t* dst_ar30,
1044
               int dst_stride_ar30,
1045
               int width,
1046
0
               int height) {
1047
0
  return I010ToAR30Matrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
1048
0
                          src_stride_v, dst_ar30, dst_stride_ar30,
1049
0
                          &kYuvH709Constants, width, height);
1050
0
}
1051
1052
// Convert U010 to AR30.
1053
LIBYUV_API
1054
int U010ToAR30(const uint16_t* src_y,
1055
               int src_stride_y,
1056
               const uint16_t* src_u,
1057
               int src_stride_u,
1058
               const uint16_t* src_v,
1059
               int src_stride_v,
1060
               uint8_t* dst_ar30,
1061
               int dst_stride_ar30,
1062
               int width,
1063
0
               int height) {
1064
0
  return I010ToAR30Matrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
1065
0
                          src_stride_v, dst_ar30, dst_stride_ar30,
1066
0
                          &kYuv2020Constants, width, height);
1067
0
}
1068
1069
// Convert I010 to AB30.
1070
LIBYUV_API
1071
int I010ToAB30(const uint16_t* src_y,
1072
               int src_stride_y,
1073
               const uint16_t* src_u,
1074
               int src_stride_u,
1075
               const uint16_t* src_v,
1076
               int src_stride_v,
1077
               uint8_t* dst_ab30,
1078
               int dst_stride_ab30,
1079
               int width,
1080
0
               int height) {
1081
0
  return I010ToAR30Matrix(src_y, src_stride_y, src_v, src_stride_v, src_u,
1082
0
                          src_stride_u, dst_ab30, dst_stride_ab30,
1083
0
                          &kYvuI601Constants, width, height);
1084
0
}
1085
1086
// Convert H010 to AB30.
1087
LIBYUV_API
1088
int H010ToAB30(const uint16_t* src_y,
1089
               int src_stride_y,
1090
               const uint16_t* src_u,
1091
               int src_stride_u,
1092
               const uint16_t* src_v,
1093
               int src_stride_v,
1094
               uint8_t* dst_ab30,
1095
               int dst_stride_ab30,
1096
               int width,
1097
0
               int height) {
1098
0
  return I010ToAR30Matrix(src_y, src_stride_y, src_v, src_stride_v, src_u,
1099
0
                          src_stride_u, dst_ab30, dst_stride_ab30,
1100
0
                          &kYvuH709Constants, width, height);
1101
0
}
1102
1103
// Convert U010 to AB30.
1104
LIBYUV_API
1105
int U010ToAB30(const uint16_t* src_y,
1106
               int src_stride_y,
1107
               const uint16_t* src_u,
1108
               int src_stride_u,
1109
               const uint16_t* src_v,
1110
               int src_stride_v,
1111
               uint8_t* dst_ab30,
1112
               int dst_stride_ab30,
1113
               int width,
1114
0
               int height) {
1115
0
  return I010ToAR30Matrix(src_y, src_stride_y, src_v, src_stride_v, src_u,
1116
0
                          src_stride_u, dst_ab30, dst_stride_ab30,
1117
0
                          &kYuv2020Constants, width, height);
1118
0
}
1119
1120
// Convert 12 bit YUV to ARGB with matrix.
1121
// TODO(fbarchard): Consider passing scale multiplier to I212ToARGB to
1122
// multiply 12 bit yuv into high bits to allow any number of bits.
1123
LIBYUV_API
1124
int I012ToAR30Matrix(const uint16_t* src_y,
1125
                     int src_stride_y,
1126
                     const uint16_t* src_u,
1127
                     int src_stride_u,
1128
                     const uint16_t* src_v,
1129
                     int src_stride_v,
1130
                     uint8_t* dst_ar30,
1131
                     int dst_stride_ar30,
1132
                     const struct YuvConstants* yuvconstants,
1133
                     int width,
1134
0
                     int height) {
1135
0
  int y;
1136
0
  void (*I212ToAR30Row)(const uint16_t* y_buf, const uint16_t* u_buf,
1137
0
                        const uint16_t* v_buf, uint8_t* rgb_buf,
1138
0
                        const struct YuvConstants* yuvconstants, int width) =
1139
0
      I212ToAR30Row_C;
1140
0
  assert(yuvconstants);
1141
0
  if (!src_y || !src_u || !src_v || !dst_ar30 || width <= 0 || height == 0) {
1142
0
    return -1;
1143
0
  }
1144
  // Negative height means invert the image.
1145
0
  if (height < 0) {
1146
0
    height = -height;
1147
0
    dst_ar30 = dst_ar30 + (height - 1) * dst_stride_ar30;
1148
0
    dst_stride_ar30 = -dst_stride_ar30;
1149
0
  }
1150
0
#if defined(HAS_I212TOAR30ROW_SSSE3)
1151
0
  if (TestCpuFlag(kCpuHasSSSE3)) {
1152
0
    I212ToAR30Row = I212ToAR30Row_Any_SSSE3;
1153
0
    if (IS_ALIGNED(width, 8)) {
1154
0
      I212ToAR30Row = I212ToAR30Row_SSSE3;
1155
0
    }
1156
0
  }
1157
0
#endif
1158
0
#if defined(HAS_I212TOAR30ROW_AVX2)
1159
0
  if (TestCpuFlag(kCpuHasAVX2)) {
1160
0
    I212ToAR30Row = I212ToAR30Row_Any_AVX2;
1161
0
    if (IS_ALIGNED(width, 16)) {
1162
0
      I212ToAR30Row = I212ToAR30Row_AVX2;
1163
0
    }
1164
0
  }
1165
0
#endif
1166
#if defined(HAS_I212TOAR30ROW_NEON)
1167
  if (TestCpuFlag(kCpuHasNEON)) {
1168
    I212ToAR30Row = I212ToAR30Row_Any_NEON;
1169
    if (IS_ALIGNED(width, 8)) {
1170
      I212ToAR30Row = I212ToAR30Row_NEON;
1171
    }
1172
  }
1173
#endif
1174
#if defined(HAS_I212TOAR30ROW_SVE2)
1175
  if (TestCpuFlag(kCpuHasSVE2)) {
1176
    I212ToAR30Row = I212ToAR30Row_SVE2;
1177
  }
1178
#endif
1179
#if defined(HAS_I212TOAR30ROW_SME)
1180
  if (TestCpuFlag(kCpuHasSME)) {
1181
    I212ToAR30Row = I212ToAR30Row_SME;
1182
  }
1183
#endif
1184
0
  for (y = 0; y < height; ++y) {
1185
0
    I212ToAR30Row(src_y, src_u, src_v, dst_ar30, yuvconstants, width);
1186
0
    dst_ar30 += dst_stride_ar30;
1187
0
    src_y += src_stride_y;
1188
0
    if (y & 1) {
1189
0
      src_u += src_stride_u;
1190
0
      src_v += src_stride_v;
1191
0
    }
1192
0
  }
1193
0
  return 0;
1194
0
}
1195
1196
// Convert 10 bit YUV to ARGB with matrix.
1197
// TODO(fbarchard): Consider passing scale multiplier to I210ToARGB to
1198
// multiply 10 bit yuv into high bits to allow any number of bits.
1199
LIBYUV_API
1200
int I210ToAR30Matrix(const uint16_t* src_y,
1201
                     int src_stride_y,
1202
                     const uint16_t* src_u,
1203
                     int src_stride_u,
1204
                     const uint16_t* src_v,
1205
                     int src_stride_v,
1206
                     uint8_t* dst_ar30,
1207
                     int dst_stride_ar30,
1208
                     const struct YuvConstants* yuvconstants,
1209
                     int width,
1210
0
                     int height) {
1211
0
  int y;
1212
0
  void (*I210ToAR30Row)(const uint16_t* y_buf, const uint16_t* u_buf,
1213
0
                        const uint16_t* v_buf, uint8_t* rgb_buf,
1214
0
                        const struct YuvConstants* yuvconstants, int width) =
1215
0
      I210ToAR30Row_C;
1216
0
  assert(yuvconstants);
1217
0
  if (!src_y || !src_u || !src_v || !dst_ar30 || width <= 0 || height == 0) {
1218
0
    return -1;
1219
0
  }
1220
  // Negative height means invert the image.
1221
0
  if (height < 0) {
1222
0
    height = -height;
1223
0
    dst_ar30 = dst_ar30 + (height - 1) * dst_stride_ar30;
1224
0
    dst_stride_ar30 = -dst_stride_ar30;
1225
0
  }
1226
#if defined(HAS_I210TOAR30ROW_NEON)
1227
  if (TestCpuFlag(kCpuHasNEON)) {
1228
    I210ToAR30Row = I210ToAR30Row_Any_NEON;
1229
    if (IS_ALIGNED(width, 8)) {
1230
      I210ToAR30Row = I210ToAR30Row_NEON;
1231
    }
1232
  }
1233
#endif
1234
#if defined(HAS_I210TOAR30ROW_SVE2)
1235
  if (TestCpuFlag(kCpuHasSVE2)) {
1236
    I210ToAR30Row = I210ToAR30Row_SVE2;
1237
  }
1238
#endif
1239
#if defined(HAS_I210TOAR30ROW_SME)
1240
  if (TestCpuFlag(kCpuHasSME)) {
1241
    I210ToAR30Row = I210ToAR30Row_SME;
1242
  }
1243
#endif
1244
0
#if defined(HAS_I210TOAR30ROW_SSSE3)
1245
0
  if (TestCpuFlag(kCpuHasSSSE3)) {
1246
0
    I210ToAR30Row = I210ToAR30Row_Any_SSSE3;
1247
0
    if (IS_ALIGNED(width, 8)) {
1248
0
      I210ToAR30Row = I210ToAR30Row_SSSE3;
1249
0
    }
1250
0
  }
1251
0
#endif
1252
0
#if defined(HAS_I210TOAR30ROW_AVX2)
1253
0
  if (TestCpuFlag(kCpuHasAVX2)) {
1254
0
    I210ToAR30Row = I210ToAR30Row_Any_AVX2;
1255
0
    if (IS_ALIGNED(width, 16)) {
1256
0
      I210ToAR30Row = I210ToAR30Row_AVX2;
1257
0
    }
1258
0
  }
1259
0
#endif
1260
0
  for (y = 0; y < height; ++y) {
1261
0
    I210ToAR30Row(src_y, src_u, src_v, dst_ar30, yuvconstants, width);
1262
0
    dst_ar30 += dst_stride_ar30;
1263
0
    src_y += src_stride_y;
1264
0
    src_u += src_stride_u;
1265
0
    src_v += src_stride_v;
1266
0
  }
1267
0
  return 0;
1268
0
}
1269
1270
// Convert I210 to AR30.
1271
LIBYUV_API
1272
int I210ToAR30(const uint16_t* src_y,
1273
               int src_stride_y,
1274
               const uint16_t* src_u,
1275
               int src_stride_u,
1276
               const uint16_t* src_v,
1277
               int src_stride_v,
1278
               uint8_t* dst_ar30,
1279
               int dst_stride_ar30,
1280
               int width,
1281
0
               int height) {
1282
0
  return I210ToAR30Matrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
1283
0
                          src_stride_v, dst_ar30, dst_stride_ar30,
1284
0
                          &kYuvI601Constants, width, height);
1285
0
}
1286
1287
// Convert H210 to AR30.
1288
LIBYUV_API
1289
int H210ToAR30(const uint16_t* src_y,
1290
               int src_stride_y,
1291
               const uint16_t* src_u,
1292
               int src_stride_u,
1293
               const uint16_t* src_v,
1294
               int src_stride_v,
1295
               uint8_t* dst_ar30,
1296
               int dst_stride_ar30,
1297
               int width,
1298
0
               int height) {
1299
0
  return I210ToAR30Matrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
1300
0
                          src_stride_v, dst_ar30, dst_stride_ar30,
1301
0
                          &kYuvH709Constants, width, height);
1302
0
}
1303
1304
// Convert U210 to AR30.
1305
LIBYUV_API
1306
int U210ToAR30(const uint16_t* src_y,
1307
               int src_stride_y,
1308
               const uint16_t* src_u,
1309
               int src_stride_u,
1310
               const uint16_t* src_v,
1311
               int src_stride_v,
1312
               uint8_t* dst_ar30,
1313
               int dst_stride_ar30,
1314
               int width,
1315
0
               int height) {
1316
0
  return I210ToAR30Matrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
1317
0
                          src_stride_v, dst_ar30, dst_stride_ar30,
1318
0
                          &kYuv2020Constants, width, height);
1319
0
}
1320
1321
// Convert I210 to AB30.
1322
LIBYUV_API
1323
int I210ToAB30(const uint16_t* src_y,
1324
               int src_stride_y,
1325
               const uint16_t* src_u,
1326
               int src_stride_u,
1327
               const uint16_t* src_v,
1328
               int src_stride_v,
1329
               uint8_t* dst_ab30,
1330
               int dst_stride_ab30,
1331
               int width,
1332
0
               int height) {
1333
0
  return I210ToAR30Matrix(src_y, src_stride_y, src_v, src_stride_v, src_u,
1334
0
                          src_stride_u, dst_ab30, dst_stride_ab30,
1335
0
                          &kYvuI601Constants, width, height);
1336
0
}
1337
1338
// Convert H210 to AB30.
1339
LIBYUV_API
1340
int H210ToAB30(const uint16_t* src_y,
1341
               int src_stride_y,
1342
               const uint16_t* src_u,
1343
               int src_stride_u,
1344
               const uint16_t* src_v,
1345
               int src_stride_v,
1346
               uint8_t* dst_ab30,
1347
               int dst_stride_ab30,
1348
               int width,
1349
0
               int height) {
1350
0
  return I210ToAR30Matrix(src_y, src_stride_y, src_v, src_stride_v, src_u,
1351
0
                          src_stride_u, dst_ab30, dst_stride_ab30,
1352
0
                          &kYvuH709Constants, width, height);
1353
0
}
1354
1355
// Convert U210 to AB30.
1356
LIBYUV_API
1357
int U210ToAB30(const uint16_t* src_y,
1358
               int src_stride_y,
1359
               const uint16_t* src_u,
1360
               int src_stride_u,
1361
               const uint16_t* src_v,
1362
               int src_stride_v,
1363
               uint8_t* dst_ab30,
1364
               int dst_stride_ab30,
1365
               int width,
1366
0
               int height) {
1367
0
  return I210ToAR30Matrix(src_y, src_stride_y, src_v, src_stride_v, src_u,
1368
0
                          src_stride_u, dst_ab30, dst_stride_ab30,
1369
0
                          &kYuv2020Constants, width, height);
1370
0
}
1371
1372
LIBYUV_API
1373
int I410ToAR30Matrix(const uint16_t* src_y,
1374
                     int src_stride_y,
1375
                     const uint16_t* src_u,
1376
                     int src_stride_u,
1377
                     const uint16_t* src_v,
1378
                     int src_stride_v,
1379
                     uint8_t* dst_ar30,
1380
                     int dst_stride_ar30,
1381
                     const struct YuvConstants* yuvconstants,
1382
                     int width,
1383
0
                     int height) {
1384
0
  int y;
1385
0
  void (*I410ToAR30Row)(const uint16_t* y_buf, const uint16_t* u_buf,
1386
0
                        const uint16_t* v_buf, uint8_t* rgb_buf,
1387
0
                        const struct YuvConstants* yuvconstants, int width) =
1388
0
      I410ToAR30Row_C;
1389
0
  assert(yuvconstants);
1390
0
  if (!src_y || !src_u || !src_v || !dst_ar30 || width <= 0 || height == 0) {
1391
0
    return -1;
1392
0
  }
1393
  // Negative height means invert the image.
1394
0
  if (height < 0) {
1395
0
    height = -height;
1396
0
    dst_ar30 = dst_ar30 + (height - 1) * dst_stride_ar30;
1397
0
    dst_stride_ar30 = -dst_stride_ar30;
1398
0
  }
1399
#if defined(HAS_I410TOAR30ROW_NEON)
1400
  if (TestCpuFlag(kCpuHasNEON)) {
1401
    I410ToAR30Row = I410ToAR30Row_Any_NEON;
1402
    if (IS_ALIGNED(width, 8)) {
1403
      I410ToAR30Row = I410ToAR30Row_NEON;
1404
    }
1405
  }
1406
#endif
1407
#if defined(HAS_I410TOAR30ROW_SVE2)
1408
  if (TestCpuFlag(kCpuHasSVE2)) {
1409
    I410ToAR30Row = I410ToAR30Row_SVE2;
1410
  }
1411
#endif
1412
#if defined(HAS_I410TOAR30ROW_SME)
1413
  if (TestCpuFlag(kCpuHasSME)) {
1414
    I410ToAR30Row = I410ToAR30Row_SME;
1415
  }
1416
#endif
1417
0
#if defined(HAS_I410TOAR30ROW_SSSE3)
1418
0
  if (TestCpuFlag(kCpuHasSSSE3)) {
1419
0
    I410ToAR30Row = I410ToAR30Row_Any_SSSE3;
1420
0
    if (IS_ALIGNED(width, 8)) {
1421
0
      I410ToAR30Row = I410ToAR30Row_SSSE3;
1422
0
    }
1423
0
  }
1424
0
#endif
1425
0
#if defined(HAS_I410TOAR30ROW_AVX2)
1426
0
  if (TestCpuFlag(kCpuHasAVX2)) {
1427
0
    I410ToAR30Row = I410ToAR30Row_Any_AVX2;
1428
0
    if (IS_ALIGNED(width, 16)) {
1429
0
      I410ToAR30Row = I410ToAR30Row_AVX2;
1430
0
    }
1431
0
  }
1432
0
#endif
1433
0
  for (y = 0; y < height; ++y) {
1434
0
    I410ToAR30Row(src_y, src_u, src_v, dst_ar30, yuvconstants, width);
1435
0
    dst_ar30 += dst_stride_ar30;
1436
0
    src_y += src_stride_y;
1437
0
    src_u += src_stride_u;
1438
0
    src_v += src_stride_v;
1439
0
  }
1440
0
  return 0;
1441
0
}
1442
1443
// Convert 10 bit YUV to ARGB with matrix.
1444
LIBYUV_API
1445
int I010ToARGBMatrix(const uint16_t* src_y,
1446
                     int src_stride_y,
1447
                     const uint16_t* src_u,
1448
                     int src_stride_u,
1449
                     const uint16_t* src_v,
1450
                     int src_stride_v,
1451
                     uint8_t* dst_argb,
1452
                     int dst_stride_argb,
1453
                     const struct YuvConstants* yuvconstants,
1454
                     int width,
1455
128
                     int height) {
1456
128
  int y;
1457
128
  void (*I210ToARGBRow)(const uint16_t* y_buf, const uint16_t* u_buf,
1458
128
                        const uint16_t* v_buf, uint8_t* rgb_buf,
1459
128
                        const struct YuvConstants* yuvconstants, int width) =
1460
128
      I210ToARGBRow_C;
1461
128
  assert(yuvconstants);
1462
128
  if (!src_y || !src_u || !src_v || !dst_argb || width <= 0 || height == 0) {
1463
0
    return -1;
1464
0
  }
1465
  // Negative height means invert the image.
1466
128
  if (height < 0) {
1467
0
    height = -height;
1468
0
    dst_argb = dst_argb + (height - 1) * dst_stride_argb;
1469
0
    dst_stride_argb = -dst_stride_argb;
1470
0
  }
1471
128
#if defined(HAS_I210TOARGBROW_SSSE3)
1472
128
  if (TestCpuFlag(kCpuHasSSSE3)) {
1473
128
    I210ToARGBRow = I210ToARGBRow_Any_SSSE3;
1474
128
    if (IS_ALIGNED(width, 8)) {
1475
34
      I210ToARGBRow = I210ToARGBRow_SSSE3;
1476
34
    }
1477
128
  }
1478
128
#endif
1479
#if defined(HAS_I210TOARGBROW_NEON)
1480
  if (TestCpuFlag(kCpuHasNEON)) {
1481
    I210ToARGBRow = I210ToARGBRow_Any_NEON;
1482
    if (IS_ALIGNED(width, 8)) {
1483
      I210ToARGBRow = I210ToARGBRow_NEON;
1484
    }
1485
  }
1486
#endif
1487
#if defined(HAS_I210TOARGBROW_SVE2)
1488
  if (TestCpuFlag(kCpuHasSVE2)) {
1489
    I210ToARGBRow = I210ToARGBRow_SVE2;
1490
  }
1491
#endif
1492
#if defined(HAS_I210TOARGBROW_SME)
1493
  if (TestCpuFlag(kCpuHasSME)) {
1494
    I210ToARGBRow = I210ToARGBRow_SME;
1495
  }
1496
#endif
1497
128
#if defined(HAS_I210TOARGBROW_AVX2)
1498
128
  if (TestCpuFlag(kCpuHasAVX2)) {
1499
128
    I210ToARGBRow = I210ToARGBRow_Any_AVX2;
1500
128
    if (IS_ALIGNED(width, 16)) {
1501
17
      I210ToARGBRow = I210ToARGBRow_AVX2;
1502
17
    }
1503
128
  }
1504
128
#endif
1505
2.69k
  for (y = 0; y < height; ++y) {
1506
2.57k
    I210ToARGBRow(src_y, src_u, src_v, dst_argb, yuvconstants, width);
1507
2.57k
    dst_argb += dst_stride_argb;
1508
2.57k
    src_y += src_stride_y;
1509
2.57k
    if (y & 1) {
1510
1.27k
      src_u += src_stride_u;
1511
1.27k
      src_v += src_stride_v;
1512
1.27k
    }
1513
2.57k
  }
1514
128
  return 0;
1515
128
}
1516
1517
// Convert I010 to ARGB.
1518
LIBYUV_API
1519
int I010ToARGB(const uint16_t* src_y,
1520
               int src_stride_y,
1521
               const uint16_t* src_u,
1522
               int src_stride_u,
1523
               const uint16_t* src_v,
1524
               int src_stride_v,
1525
               uint8_t* dst_argb,
1526
               int dst_stride_argb,
1527
               int width,
1528
0
               int height) {
1529
0
  return I010ToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
1530
0
                          src_stride_v, dst_argb, dst_stride_argb,
1531
0
                          &kYuvI601Constants, width, height);
1532
0
}
1533
1534
// Convert I010 to ABGR.
1535
LIBYUV_API
1536
int I010ToABGR(const uint16_t* src_y,
1537
               int src_stride_y,
1538
               const uint16_t* src_u,
1539
               int src_stride_u,
1540
               const uint16_t* src_v,
1541
               int src_stride_v,
1542
               uint8_t* dst_abgr,
1543
               int dst_stride_abgr,
1544
               int width,
1545
0
               int height) {
1546
0
  return I010ToARGBMatrix(src_y, src_stride_y, src_v,
1547
0
                          src_stride_v,  // Swap U and V
1548
0
                          src_u, src_stride_u, dst_abgr, dst_stride_abgr,
1549
0
                          &kYvuI601Constants,  // Use Yvu matrix
1550
0
                          width, height);
1551
0
}
1552
1553
// Convert H010 to ARGB.
1554
LIBYUV_API
1555
int H010ToARGB(const uint16_t* src_y,
1556
               int src_stride_y,
1557
               const uint16_t* src_u,
1558
               int src_stride_u,
1559
               const uint16_t* src_v,
1560
               int src_stride_v,
1561
               uint8_t* dst_argb,
1562
               int dst_stride_argb,
1563
               int width,
1564
0
               int height) {
1565
0
  return I010ToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
1566
0
                          src_stride_v, dst_argb, dst_stride_argb,
1567
0
                          &kYuvH709Constants, width, height);
1568
0
}
1569
1570
// Convert H010 to ABGR.
1571
LIBYUV_API
1572
int H010ToABGR(const uint16_t* src_y,
1573
               int src_stride_y,
1574
               const uint16_t* src_u,
1575
               int src_stride_u,
1576
               const uint16_t* src_v,
1577
               int src_stride_v,
1578
               uint8_t* dst_abgr,
1579
               int dst_stride_abgr,
1580
               int width,
1581
0
               int height) {
1582
0
  return I010ToARGBMatrix(src_y, src_stride_y, src_v,
1583
0
                          src_stride_v,  // Swap U and V
1584
0
                          src_u, src_stride_u, dst_abgr, dst_stride_abgr,
1585
0
                          &kYvuH709Constants,  // Use Yvu matrix
1586
0
                          width, height);
1587
0
}
1588
1589
// Convert U010 to ARGB.
1590
LIBYUV_API
1591
int U010ToARGB(const uint16_t* src_y,
1592
               int src_stride_y,
1593
               const uint16_t* src_u,
1594
               int src_stride_u,
1595
               const uint16_t* src_v,
1596
               int src_stride_v,
1597
               uint8_t* dst_argb,
1598
               int dst_stride_argb,
1599
               int width,
1600
0
               int height) {
1601
0
  return I010ToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
1602
0
                          src_stride_v, dst_argb, dst_stride_argb,
1603
0
                          &kYuv2020Constants, width, height);
1604
0
}
1605
1606
// Convert U010 to ABGR.
1607
LIBYUV_API
1608
int U010ToABGR(const uint16_t* src_y,
1609
               int src_stride_y,
1610
               const uint16_t* src_u,
1611
               int src_stride_u,
1612
               const uint16_t* src_v,
1613
               int src_stride_v,
1614
               uint8_t* dst_abgr,
1615
               int dst_stride_abgr,
1616
               int width,
1617
0
               int height) {
1618
0
  return I010ToARGBMatrix(src_y, src_stride_y, src_v,
1619
0
                          src_stride_v,  // Swap U and V
1620
0
                          src_u, src_stride_u, dst_abgr, dst_stride_abgr,
1621
0
                          &kYvu2020Constants,  // Use Yvu matrix
1622
0
                          width, height);
1623
0
}
1624
1625
// Convert 12 bit YUV to ARGB with matrix.
1626
LIBYUV_API
1627
int I012ToARGBMatrix(const uint16_t* src_y,
1628
                     int src_stride_y,
1629
                     const uint16_t* src_u,
1630
                     int src_stride_u,
1631
                     const uint16_t* src_v,
1632
                     int src_stride_v,
1633
                     uint8_t* dst_argb,
1634
                     int dst_stride_argb,
1635
                     const struct YuvConstants* yuvconstants,
1636
                     int width,
1637
108
                     int height) {
1638
108
  int y;
1639
108
  void (*I212ToARGBRow)(const uint16_t* y_buf, const uint16_t* u_buf,
1640
108
                        const uint16_t* v_buf, uint8_t* rgb_buf,
1641
108
                        const struct YuvConstants* yuvconstants, int width) =
1642
108
      I212ToARGBRow_C;
1643
108
  assert(yuvconstants);
1644
108
  if (!src_y || !src_u || !src_v || !dst_argb || width <= 0 || height == 0) {
1645
0
    return -1;
1646
0
  }
1647
  // Negative height means invert the image.
1648
108
  if (height < 0) {
1649
0
    height = -height;
1650
0
    dst_argb = dst_argb + (height - 1) * dst_stride_argb;
1651
0
    dst_stride_argb = -dst_stride_argb;
1652
0
  }
1653
108
#if defined(HAS_I212TOARGBROW_SSSE3)
1654
108
  if (TestCpuFlag(kCpuHasSSSE3)) {
1655
108
    I212ToARGBRow = I212ToARGBRow_Any_SSSE3;
1656
108
    if (IS_ALIGNED(width, 8)) {
1657
36
      I212ToARGBRow = I212ToARGBRow_SSSE3;
1658
36
    }
1659
108
  }
1660
108
#endif
1661
108
#if defined(HAS_I212TOARGBROW_AVX2)
1662
108
  if (TestCpuFlag(kCpuHasAVX2)) {
1663
108
    I212ToARGBRow = I212ToARGBRow_Any_AVX2;
1664
108
    if (IS_ALIGNED(width, 16)) {
1665
19
      I212ToARGBRow = I212ToARGBRow_AVX2;
1666
19
    }
1667
108
  }
1668
108
#endif
1669
#if defined(HAS_I212TOARGBROW_NEON)
1670
  if (TestCpuFlag(kCpuHasNEON)) {
1671
    I212ToARGBRow = I212ToARGBRow_Any_NEON;
1672
    if (IS_ALIGNED(width, 8)) {
1673
      I212ToARGBRow = I212ToARGBRow_NEON;
1674
    }
1675
  }
1676
#endif
1677
#if defined(HAS_I212TOARGBROW_SVE2)
1678
  if (TestCpuFlag(kCpuHasSVE2)) {
1679
    I212ToARGBRow = I212ToARGBRow_SVE2;
1680
  }
1681
#endif
1682
#if defined(HAS_I212TOARGBROW_SME)
1683
  if (TestCpuFlag(kCpuHasSME)) {
1684
    I212ToARGBRow = I212ToARGBRow_SME;
1685
  }
1686
#endif
1687
3.83k
  for (y = 0; y < height; ++y) {
1688
3.72k
    I212ToARGBRow(src_y, src_u, src_v, dst_argb, yuvconstants, width);
1689
3.72k
    dst_argb += dst_stride_argb;
1690
3.72k
    src_y += src_stride_y;
1691
3.72k
    if (y & 1) {
1692
1.84k
      src_u += src_stride_u;
1693
1.84k
      src_v += src_stride_v;
1694
1.84k
    }
1695
3.72k
  }
1696
108
  return 0;
1697
108
}
1698
1699
// Convert 10 bit 422 YUV to ARGB with matrix.
1700
LIBYUV_API
1701
int I210ToARGBMatrix(const uint16_t* src_y,
1702
                     int src_stride_y,
1703
                     const uint16_t* src_u,
1704
                     int src_stride_u,
1705
                     const uint16_t* src_v,
1706
                     int src_stride_v,
1707
                     uint8_t* dst_argb,
1708
                     int dst_stride_argb,
1709
                     const struct YuvConstants* yuvconstants,
1710
                     int width,
1711
65
                     int height) {
1712
65
  int y;
1713
65
  void (*I210ToARGBRow)(const uint16_t* y_buf, const uint16_t* u_buf,
1714
65
                        const uint16_t* v_buf, uint8_t* rgb_buf,
1715
65
                        const struct YuvConstants* yuvconstants, int width) =
1716
65
      I210ToARGBRow_C;
1717
65
  assert(yuvconstants);
1718
65
  if (!src_y || !src_u || !src_v || !dst_argb || width <= 0 || height == 0) {
1719
0
    return -1;
1720
0
  }
1721
  // Negative height means invert the image.
1722
65
  if (height < 0) {
1723
0
    height = -height;
1724
0
    dst_argb = dst_argb + (height - 1) * dst_stride_argb;
1725
0
    dst_stride_argb = -dst_stride_argb;
1726
0
  }
1727
65
#if defined(HAS_I210TOARGBROW_SSSE3)
1728
65
  if (TestCpuFlag(kCpuHasSSSE3)) {
1729
65
    I210ToARGBRow = I210ToARGBRow_Any_SSSE3;
1730
65
    if (IS_ALIGNED(width, 8)) {
1731
34
      I210ToARGBRow = I210ToARGBRow_SSSE3;
1732
34
    }
1733
65
  }
1734
65
#endif
1735
#if defined(HAS_I210TOARGBROW_NEON)
1736
  if (TestCpuFlag(kCpuHasNEON)) {
1737
    I210ToARGBRow = I210ToARGBRow_Any_NEON;
1738
    if (IS_ALIGNED(width, 8)) {
1739
      I210ToARGBRow = I210ToARGBRow_NEON;
1740
    }
1741
  }
1742
#endif
1743
#if defined(HAS_I210TOARGBROW_SVE2)
1744
  if (TestCpuFlag(kCpuHasSVE2)) {
1745
    I210ToARGBRow = I210ToARGBRow_SVE2;
1746
  }
1747
#endif
1748
#if defined(HAS_I210TOARGBROW_SME)
1749
  if (TestCpuFlag(kCpuHasSME)) {
1750
    I210ToARGBRow = I210ToARGBRow_SME;
1751
  }
1752
#endif
1753
65
#if defined(HAS_I210TOARGBROW_AVX2)
1754
65
  if (TestCpuFlag(kCpuHasAVX2)) {
1755
65
    I210ToARGBRow = I210ToARGBRow_Any_AVX2;
1756
65
    if (IS_ALIGNED(width, 16)) {
1757
17
      I210ToARGBRow = I210ToARGBRow_AVX2;
1758
17
    }
1759
65
  }
1760
65
#endif
1761
540
  for (y = 0; y < height; ++y) {
1762
475
    I210ToARGBRow(src_y, src_u, src_v, dst_argb, yuvconstants, width);
1763
475
    dst_argb += dst_stride_argb;
1764
475
    src_y += src_stride_y;
1765
475
    src_u += src_stride_u;
1766
475
    src_v += src_stride_v;
1767
475
  }
1768
65
  return 0;
1769
65
}
1770
1771
// Convert I210 to ARGB.
1772
LIBYUV_API
1773
int I210ToARGB(const uint16_t* src_y,
1774
               int src_stride_y,
1775
               const uint16_t* src_u,
1776
               int src_stride_u,
1777
               const uint16_t* src_v,
1778
               int src_stride_v,
1779
               uint8_t* dst_argb,
1780
               int dst_stride_argb,
1781
               int width,
1782
0
               int height) {
1783
0
  return I210ToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
1784
0
                          src_stride_v, dst_argb, dst_stride_argb,
1785
0
                          &kYuvI601Constants, width, height);
1786
0
}
1787
1788
// Convert I210 to ABGR.
1789
LIBYUV_API
1790
int I210ToABGR(const uint16_t* src_y,
1791
               int src_stride_y,
1792
               const uint16_t* src_u,
1793
               int src_stride_u,
1794
               const uint16_t* src_v,
1795
               int src_stride_v,
1796
               uint8_t* dst_abgr,
1797
               int dst_stride_abgr,
1798
               int width,
1799
0
               int height) {
1800
0
  return I210ToARGBMatrix(src_y, src_stride_y, src_v,
1801
0
                          src_stride_v,  // Swap U and V
1802
0
                          src_u, src_stride_u, dst_abgr, dst_stride_abgr,
1803
0
                          &kYvuI601Constants,  // Use Yvu matrix
1804
0
                          width, height);
1805
0
}
1806
1807
// Convert H210 to ARGB.
1808
LIBYUV_API
1809
int H210ToARGB(const uint16_t* src_y,
1810
               int src_stride_y,
1811
               const uint16_t* src_u,
1812
               int src_stride_u,
1813
               const uint16_t* src_v,
1814
               int src_stride_v,
1815
               uint8_t* dst_argb,
1816
               int dst_stride_argb,
1817
               int width,
1818
0
               int height) {
1819
0
  return I210ToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
1820
0
                          src_stride_v, dst_argb, dst_stride_argb,
1821
0
                          &kYuvH709Constants, width, height);
1822
0
}
1823
1824
// Convert H210 to ABGR.
1825
LIBYUV_API
1826
int H210ToABGR(const uint16_t* src_y,
1827
               int src_stride_y,
1828
               const uint16_t* src_u,
1829
               int src_stride_u,
1830
               const uint16_t* src_v,
1831
               int src_stride_v,
1832
               uint8_t* dst_abgr,
1833
               int dst_stride_abgr,
1834
               int width,
1835
0
               int height) {
1836
0
  return I210ToARGBMatrix(src_y, src_stride_y, src_v,
1837
0
                          src_stride_v,  // Swap U and V
1838
0
                          src_u, src_stride_u, dst_abgr, dst_stride_abgr,
1839
0
                          &kYvuH709Constants,  // Use Yvu matrix
1840
0
                          width, height);
1841
0
}
1842
1843
// Convert U210 to ARGB.
1844
LIBYUV_API
1845
int U210ToARGB(const uint16_t* src_y,
1846
               int src_stride_y,
1847
               const uint16_t* src_u,
1848
               int src_stride_u,
1849
               const uint16_t* src_v,
1850
               int src_stride_v,
1851
               uint8_t* dst_argb,
1852
               int dst_stride_argb,
1853
               int width,
1854
0
               int height) {
1855
0
  return I210ToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
1856
0
                          src_stride_v, dst_argb, dst_stride_argb,
1857
0
                          &kYuv2020Constants, width, height);
1858
0
}
1859
1860
// Convert U210 to ABGR.
1861
LIBYUV_API
1862
int U210ToABGR(const uint16_t* src_y,
1863
               int src_stride_y,
1864
               const uint16_t* src_u,
1865
               int src_stride_u,
1866
               const uint16_t* src_v,
1867
               int src_stride_v,
1868
               uint8_t* dst_abgr,
1869
               int dst_stride_abgr,
1870
               int width,
1871
0
               int height) {
1872
0
  return I210ToARGBMatrix(src_y, src_stride_y, src_v,
1873
0
                          src_stride_v,  // Swap U and V
1874
0
                          src_u, src_stride_u, dst_abgr, dst_stride_abgr,
1875
0
                          &kYvu2020Constants,  // Use Yvu matrix
1876
0
                          width, height);
1877
0
}
1878
1879
LIBYUV_API
1880
int I410ToARGBMatrix(const uint16_t* src_y,
1881
                     int src_stride_y,
1882
                     const uint16_t* src_u,
1883
                     int src_stride_u,
1884
                     const uint16_t* src_v,
1885
                     int src_stride_v,
1886
                     uint8_t* dst_argb,
1887
                     int dst_stride_argb,
1888
                     const struct YuvConstants* yuvconstants,
1889
                     int width,
1890
75
                     int height) {
1891
75
  int y;
1892
75
  void (*I410ToARGBRow)(const uint16_t* y_buf, const uint16_t* u_buf,
1893
75
                        const uint16_t* v_buf, uint8_t* rgb_buf,
1894
75
                        const struct YuvConstants* yuvconstants, int width) =
1895
75
      I410ToARGBRow_C;
1896
75
  assert(yuvconstants);
1897
75
  if (!src_y || !src_u || !src_v || !dst_argb || width <= 0 || height == 0) {
1898
0
    return -1;
1899
0
  }
1900
  // Negative height means invert the image.
1901
75
  if (height < 0) {
1902
0
    height = -height;
1903
0
    dst_argb = dst_argb + (height - 1) * dst_stride_argb;
1904
0
    dst_stride_argb = -dst_stride_argb;
1905
0
  }
1906
75
#if defined(HAS_I410TOARGBROW_SSSE3)
1907
75
  if (TestCpuFlag(kCpuHasSSSE3)) {
1908
75
    I410ToARGBRow = I410ToARGBRow_Any_SSSE3;
1909
75
    if (IS_ALIGNED(width, 8)) {
1910
36
      I410ToARGBRow = I410ToARGBRow_SSSE3;
1911
36
    }
1912
75
  }
1913
75
#endif
1914
#if defined(HAS_I410TOARGBROW_NEON)
1915
  if (TestCpuFlag(kCpuHasNEON)) {
1916
    I410ToARGBRow = I410ToARGBRow_Any_NEON;
1917
    if (IS_ALIGNED(width, 8)) {
1918
      I410ToARGBRow = I410ToARGBRow_NEON;
1919
    }
1920
  }
1921
#endif
1922
#if defined(HAS_I410TOARGBROW_SVE2)
1923
  if (TestCpuFlag(kCpuHasSVE2)) {
1924
    I410ToARGBRow = I410ToARGBRow_SVE2;
1925
  }
1926
#endif
1927
#if defined(HAS_I410TOARGBROW_SME)
1928
  if (TestCpuFlag(kCpuHasSME)) {
1929
    I410ToARGBRow = I410ToARGBRow_SME;
1930
  }
1931
#endif
1932
75
#if defined(HAS_I410TOARGBROW_AVX2)
1933
75
  if (TestCpuFlag(kCpuHasAVX2)) {
1934
75
    I410ToARGBRow = I410ToARGBRow_Any_AVX2;
1935
75
    if (IS_ALIGNED(width, 16)) {
1936
19
      I410ToARGBRow = I410ToARGBRow_AVX2;
1937
19
    }
1938
75
  }
1939
75
#endif
1940
634
  for (y = 0; y < height; ++y) {
1941
559
    I410ToARGBRow(src_y, src_u, src_v, dst_argb, yuvconstants, width);
1942
559
    dst_argb += dst_stride_argb;
1943
559
    src_y += src_stride_y;
1944
559
    src_u += src_stride_u;
1945
559
    src_v += src_stride_v;
1946
559
  }
1947
75
  return 0;
1948
75
}
1949
1950
LIBYUV_API
1951
int P010ToARGBMatrix(const uint16_t* src_y,
1952
                     int src_stride_y,
1953
                     const uint16_t* src_uv,
1954
                     int src_stride_uv,
1955
                     uint8_t* dst_argb,
1956
                     int dst_stride_argb,
1957
                     const struct YuvConstants* yuvconstants,
1958
                     int width,
1959
0
                     int height) {
1960
0
  int y;
1961
0
  void (*P210ToARGBRow)(
1962
0
      const uint16_t* y_buf, const uint16_t* uv_buf, uint8_t* rgb_buf,
1963
0
      const struct YuvConstants* yuvconstants, int width) = P210ToARGBRow_C;
1964
0
  assert(yuvconstants);
1965
0
  if (!src_y || !src_uv || !dst_argb || width <= 0 || height == 0) {
1966
0
    return -1;
1967
0
  }
1968
  // Negative height means invert the image.
1969
0
  if (height < 0) {
1970
0
    height = -height;
1971
0
    dst_argb = dst_argb + (height - 1) * dst_stride_argb;
1972
0
    dst_stride_argb = -dst_stride_argb;
1973
0
  }
1974
0
#if defined(HAS_P210TOARGBROW_SSSE3)
1975
0
  if (TestCpuFlag(kCpuHasSSSE3)) {
1976
0
    P210ToARGBRow = P210ToARGBRow_Any_SSSE3;
1977
0
    if (IS_ALIGNED(width, 8)) {
1978
0
      P210ToARGBRow = P210ToARGBRow_SSSE3;
1979
0
    }
1980
0
  }
1981
0
#endif
1982
0
#if defined(HAS_P210TOARGBROW_AVX2)
1983
0
  if (TestCpuFlag(kCpuHasAVX2)) {
1984
0
    P210ToARGBRow = P210ToARGBRow_Any_AVX2;
1985
0
    if (IS_ALIGNED(width, 16)) {
1986
0
      P210ToARGBRow = P210ToARGBRow_AVX2;
1987
0
    }
1988
0
  }
1989
0
#endif
1990
#if defined(HAS_P210TOARGBROW_NEON)
1991
  if (TestCpuFlag(kCpuHasNEON)) {
1992
    P210ToARGBRow = P210ToARGBRow_Any_NEON;
1993
    if (IS_ALIGNED(width, 8)) {
1994
      P210ToARGBRow = P210ToARGBRow_NEON;
1995
    }
1996
  }
1997
#endif
1998
#if defined(HAS_P210TOARGBROW_SVE2)
1999
  if (TestCpuFlag(kCpuHasSVE2)) {
2000
    P210ToARGBRow = P210ToARGBRow_SVE2;
2001
  }
2002
#endif
2003
#if defined(HAS_P210TOARGBROW_SME)
2004
  if (TestCpuFlag(kCpuHasSME)) {
2005
    P210ToARGBRow = P210ToARGBRow_SME;
2006
  }
2007
#endif
2008
0
  for (y = 0; y < height; ++y) {
2009
0
    P210ToARGBRow(src_y, src_uv, dst_argb, yuvconstants, width);
2010
0
    dst_argb += dst_stride_argb;
2011
0
    src_y += src_stride_y;
2012
0
    if (y & 1) {
2013
0
      src_uv += src_stride_uv;
2014
0
    }
2015
0
  }
2016
0
  return 0;
2017
0
}
2018
2019
LIBYUV_API
2020
int P210ToARGBMatrix(const uint16_t* src_y,
2021
                     int src_stride_y,
2022
                     const uint16_t* src_uv,
2023
                     int src_stride_uv,
2024
                     uint8_t* dst_argb,
2025
                     int dst_stride_argb,
2026
                     const struct YuvConstants* yuvconstants,
2027
                     int width,
2028
0
                     int height) {
2029
0
  int y;
2030
0
  void (*P210ToARGBRow)(
2031
0
      const uint16_t* y_buf, const uint16_t* uv_buf, uint8_t* rgb_buf,
2032
0
      const struct YuvConstants* yuvconstants, int width) = P210ToARGBRow_C;
2033
0
  assert(yuvconstants);
2034
0
  if (!src_y || !src_uv || !dst_argb || width <= 0 || height == 0) {
2035
0
    return -1;
2036
0
  }
2037
  // Negative height means invert the image.
2038
0
  if (height < 0) {
2039
0
    height = -height;
2040
0
    dst_argb = dst_argb + (height - 1) * dst_stride_argb;
2041
0
    dst_stride_argb = -dst_stride_argb;
2042
0
  }
2043
0
#if defined(HAS_P210TOARGBROW_SSSE3)
2044
0
  if (TestCpuFlag(kCpuHasSSSE3)) {
2045
0
    P210ToARGBRow = P210ToARGBRow_Any_SSSE3;
2046
0
    if (IS_ALIGNED(width, 8)) {
2047
0
      P210ToARGBRow = P210ToARGBRow_SSSE3;
2048
0
    }
2049
0
  }
2050
0
#endif
2051
0
#if defined(HAS_P210TOARGBROW_AVX2)
2052
0
  if (TestCpuFlag(kCpuHasAVX2)) {
2053
0
    P210ToARGBRow = P210ToARGBRow_Any_AVX2;
2054
0
    if (IS_ALIGNED(width, 16)) {
2055
0
      P210ToARGBRow = P210ToARGBRow_AVX2;
2056
0
    }
2057
0
  }
2058
0
#endif
2059
#if defined(HAS_P210TOARGBROW_NEON)
2060
  if (TestCpuFlag(kCpuHasNEON)) {
2061
    P210ToARGBRow = P210ToARGBRow_Any_NEON;
2062
    if (IS_ALIGNED(width, 8)) {
2063
      P210ToARGBRow = P210ToARGBRow_NEON;
2064
    }
2065
  }
2066
#endif
2067
#if defined(HAS_P210TOARGBROW_SVE2)
2068
  if (TestCpuFlag(kCpuHasSVE2)) {
2069
    P210ToARGBRow = P210ToARGBRow_SVE2;
2070
  }
2071
#endif
2072
#if defined(HAS_P210TOARGBROW_SME)
2073
  if (TestCpuFlag(kCpuHasSME)) {
2074
    P210ToARGBRow = P210ToARGBRow_SME;
2075
  }
2076
#endif
2077
0
  for (y = 0; y < height; ++y) {
2078
0
    P210ToARGBRow(src_y, src_uv, dst_argb, yuvconstants, width);
2079
0
    dst_argb += dst_stride_argb;
2080
0
    src_y += src_stride_y;
2081
0
    src_uv += src_stride_uv;
2082
0
  }
2083
0
  return 0;
2084
0
}
2085
2086
LIBYUV_API
2087
int P010ToAR30Matrix(const uint16_t* src_y,
2088
                     int src_stride_y,
2089
                     const uint16_t* src_uv,
2090
                     int src_stride_uv,
2091
                     uint8_t* dst_ar30,
2092
                     int dst_stride_ar30,
2093
                     const struct YuvConstants* yuvconstants,
2094
                     int width,
2095
0
                     int height) {
2096
0
  int y;
2097
0
  void (*P210ToAR30Row)(
2098
0
      const uint16_t* y_buf, const uint16_t* uv_buf, uint8_t* rgb_buf,
2099
0
      const struct YuvConstants* yuvconstants, int width) = P210ToAR30Row_C;
2100
0
  assert(yuvconstants);
2101
0
  if (!src_y || !src_uv || !dst_ar30 || width <= 0 || height == 0) {
2102
0
    return -1;
2103
0
  }
2104
  // Negative height means invert the image.
2105
0
  if (height < 0) {
2106
0
    height = -height;
2107
0
    dst_ar30 = dst_ar30 + (height - 1) * dst_stride_ar30;
2108
0
    dst_stride_ar30 = -dst_stride_ar30;
2109
0
  }
2110
0
#if defined(HAS_P210TOAR30ROW_SSSE3)
2111
0
  if (TestCpuFlag(kCpuHasSSSE3)) {
2112
0
    P210ToAR30Row = P210ToAR30Row_Any_SSSE3;
2113
0
    if (IS_ALIGNED(width, 8)) {
2114
0
      P210ToAR30Row = P210ToAR30Row_SSSE3;
2115
0
    }
2116
0
  }
2117
0
#endif
2118
0
#if defined(HAS_P210TOAR30ROW_AVX2)
2119
0
  if (TestCpuFlag(kCpuHasAVX2)) {
2120
0
    P210ToAR30Row = P210ToAR30Row_Any_AVX2;
2121
0
    if (IS_ALIGNED(width, 16)) {
2122
0
      P210ToAR30Row = P210ToAR30Row_AVX2;
2123
0
    }
2124
0
  }
2125
0
#endif
2126
#if defined(HAS_P210TOAR30ROW_NEON)
2127
  if (TestCpuFlag(kCpuHasNEON)) {
2128
    P210ToAR30Row = P210ToAR30Row_Any_NEON;
2129
    if (IS_ALIGNED(width, 8)) {
2130
      P210ToAR30Row = P210ToAR30Row_NEON;
2131
    }
2132
  }
2133
#endif
2134
#if defined(HAS_P210TOAR30ROW_SVE2)
2135
  if (TestCpuFlag(kCpuHasSVE2)) {
2136
    P210ToAR30Row = P210ToAR30Row_SVE2;
2137
  }
2138
#endif
2139
#if defined(HAS_P210TOAR30ROW_SME)
2140
  if (TestCpuFlag(kCpuHasSME)) {
2141
    P210ToAR30Row = P210ToAR30Row_SME;
2142
  }
2143
#endif
2144
0
  for (y = 0; y < height; ++y) {
2145
0
    P210ToAR30Row(src_y, src_uv, dst_ar30, yuvconstants, width);
2146
0
    dst_ar30 += dst_stride_ar30;
2147
0
    src_y += src_stride_y;
2148
0
    if (y & 1) {
2149
0
      src_uv += src_stride_uv;
2150
0
    }
2151
0
  }
2152
0
  return 0;
2153
0
}
2154
2155
LIBYUV_API
2156
int P210ToAR30Matrix(const uint16_t* src_y,
2157
                     int src_stride_y,
2158
                     const uint16_t* src_uv,
2159
                     int src_stride_uv,
2160
                     uint8_t* dst_ar30,
2161
                     int dst_stride_ar30,
2162
                     const struct YuvConstants* yuvconstants,
2163
                     int width,
2164
0
                     int height) {
2165
0
  int y;
2166
0
  void (*P210ToAR30Row)(
2167
0
      const uint16_t* y_buf, const uint16_t* uv_buf, uint8_t* rgb_buf,
2168
0
      const struct YuvConstants* yuvconstants, int width) = P210ToAR30Row_C;
2169
0
  assert(yuvconstants);
2170
0
  if (!src_y || !src_uv || !dst_ar30 || width <= 0 || height == 0) {
2171
0
    return -1;
2172
0
  }
2173
  // Negative height means invert the image.
2174
0
  if (height < 0) {
2175
0
    height = -height;
2176
0
    dst_ar30 = dst_ar30 + (height - 1) * dst_stride_ar30;
2177
0
    dst_stride_ar30 = -dst_stride_ar30;
2178
0
  }
2179
0
#if defined(HAS_P210TOAR30ROW_SSSE3)
2180
0
  if (TestCpuFlag(kCpuHasSSSE3)) {
2181
0
    P210ToAR30Row = P210ToAR30Row_Any_SSSE3;
2182
0
    if (IS_ALIGNED(width, 8)) {
2183
0
      P210ToAR30Row = P210ToAR30Row_SSSE3;
2184
0
    }
2185
0
  }
2186
0
#endif
2187
0
#if defined(HAS_P210TOAR30ROW_AVX2)
2188
0
  if (TestCpuFlag(kCpuHasAVX2)) {
2189
0
    P210ToAR30Row = P210ToAR30Row_Any_AVX2;
2190
0
    if (IS_ALIGNED(width, 16)) {
2191
0
      P210ToAR30Row = P210ToAR30Row_AVX2;
2192
0
    }
2193
0
  }
2194
0
#endif
2195
#if defined(HAS_P210TOAR30ROW_NEON)
2196
  if (TestCpuFlag(kCpuHasNEON)) {
2197
    P210ToAR30Row = P210ToAR30Row_Any_NEON;
2198
    if (IS_ALIGNED(width, 8)) {
2199
      P210ToAR30Row = P210ToAR30Row_NEON;
2200
    }
2201
  }
2202
#endif
2203
#if defined(HAS_P210TOAR30ROW_SVE2)
2204
  if (TestCpuFlag(kCpuHasSVE2)) {
2205
    P210ToAR30Row = P210ToAR30Row_SVE2;
2206
  }
2207
#endif
2208
#if defined(HAS_P210TOAR30ROW_SME)
2209
  if (TestCpuFlag(kCpuHasSME)) {
2210
    P210ToAR30Row = P210ToAR30Row_SME;
2211
  }
2212
#endif
2213
0
  for (y = 0; y < height; ++y) {
2214
0
    P210ToAR30Row(src_y, src_uv, dst_ar30, yuvconstants, width);
2215
0
    dst_ar30 += dst_stride_ar30;
2216
0
    src_y += src_stride_y;
2217
0
    src_uv += src_stride_uv;
2218
0
  }
2219
0
  return 0;
2220
0
}
2221
2222
// Convert I420 with Alpha to preattenuated ARGB with matrix.
2223
LIBYUV_API
2224
int I420AlphaToARGBMatrix(const uint8_t* src_y,
2225
                          int src_stride_y,
2226
                          const uint8_t* src_u,
2227
                          int src_stride_u,
2228
                          const uint8_t* src_v,
2229
                          int src_stride_v,
2230
                          const uint8_t* src_a,
2231
                          int src_stride_a,
2232
                          uint8_t* dst_argb,
2233
                          int dst_stride_argb,
2234
                          const struct YuvConstants* yuvconstants,
2235
                          int width,
2236
                          int height,
2237
131
                          int attenuate) {
2238
131
  int y;
2239
131
  void (*I422AlphaToARGBRow)(const uint8_t* y_buf, const uint8_t* u_buf,
2240
131
                             const uint8_t* v_buf, const uint8_t* a_buf,
2241
131
                             uint8_t* dst_argb,
2242
131
                             const struct YuvConstants* yuvconstants,
2243
131
                             int width) = I422AlphaToARGBRow_C;
2244
131
  void (*ARGBAttenuateRow)(const uint8_t* src_argb, uint8_t* dst_argb,
2245
131
                           int width) = ARGBAttenuateRow_C;
2246
131
  assert(yuvconstants);
2247
131
  if (!src_y || !src_u || !src_v || !src_a || !dst_argb || width <= 0 ||
2248
131
      height == 0) {
2249
0
    return -1;
2250
0
  }
2251
  // Negative height means invert the image.
2252
131
  if (height < 0) {
2253
0
    height = -height;
2254
0
    dst_argb = dst_argb + (height - 1) * dst_stride_argb;
2255
0
    dst_stride_argb = -dst_stride_argb;
2256
0
  }
2257
131
#if defined(HAS_I422ALPHATOARGBROW_SSSE3)
2258
131
  if (TestCpuFlag(kCpuHasSSSE3)) {
2259
131
    I422AlphaToARGBRow = I422AlphaToARGBRow_Any_SSSE3;
2260
131
    if (IS_ALIGNED(width, 8)) {
2261
34
      I422AlphaToARGBRow = I422AlphaToARGBRow_SSSE3;
2262
34
    }
2263
131
  }
2264
131
#endif
2265
131
#if defined(HAS_I422ALPHATOARGBROW_AVX2)
2266
131
  if (TestCpuFlag(kCpuHasAVX2)) {
2267
131
    I422AlphaToARGBRow = I422AlphaToARGBRow_Any_AVX2;
2268
131
    if (IS_ALIGNED(width, 16)) {
2269
17
      I422AlphaToARGBRow = I422AlphaToARGBRow_AVX2;
2270
17
    }
2271
131
  }
2272
131
#endif
2273
#if defined(HAS_I422ALPHATOARGBROW_NEON)
2274
  if (TestCpuFlag(kCpuHasNEON)) {
2275
    I422AlphaToARGBRow = I422AlphaToARGBRow_Any_NEON;
2276
    if (IS_ALIGNED(width, 8)) {
2277
      I422AlphaToARGBRow = I422AlphaToARGBRow_NEON;
2278
    }
2279
  }
2280
#endif
2281
#if defined(HAS_I422ALPHATOARGBROW_SVE2)
2282
  if (TestCpuFlag(kCpuHasSVE2)) {
2283
    I422AlphaToARGBRow = I422AlphaToARGBRow_SVE2;
2284
  }
2285
#endif
2286
#if defined(HAS_I422ALPHATOARGBROW_SME)
2287
  if (TestCpuFlag(kCpuHasSME)) {
2288
    I422AlphaToARGBRow = I422AlphaToARGBRow_SME;
2289
  }
2290
#endif
2291
#if defined(HAS_I422ALPHATOARGBROW_MSA)
2292
  if (TestCpuFlag(kCpuHasMSA)) {
2293
    I422AlphaToARGBRow = I422AlphaToARGBRow_Any_MSA;
2294
    if (IS_ALIGNED(width, 8)) {
2295
      I422AlphaToARGBRow = I422AlphaToARGBRow_MSA;
2296
    }
2297
  }
2298
#endif
2299
#if defined(HAS_I422ALPHATOARGBROW_LSX)
2300
  if (TestCpuFlag(kCpuHasLSX)) {
2301
    I422AlphaToARGBRow = I422AlphaToARGBRow_Any_LSX;
2302
    if (IS_ALIGNED(width, 16)) {
2303
      I422AlphaToARGBRow = I422AlphaToARGBRow_LSX;
2304
    }
2305
  }
2306
#endif
2307
#if defined(HAS_I422ALPHATOARGBROW_LASX)
2308
  if (TestCpuFlag(kCpuHasLASX)) {
2309
    I422AlphaToARGBRow = I422AlphaToARGBRow_Any_LASX;
2310
    if (IS_ALIGNED(width, 16)) {
2311
      I422AlphaToARGBRow = I422AlphaToARGBRow_LASX;
2312
    }
2313
  }
2314
#endif
2315
#if defined(HAS_I422ALPHATOARGBROW_RVV)
2316
  if (TestCpuFlag(kCpuHasRVV)) {
2317
    I422AlphaToARGBRow = I422AlphaToARGBRow_RVV;
2318
  }
2319
#endif
2320
131
#if defined(HAS_ARGBATTENUATEROW_SSSE3)
2321
131
  if (TestCpuFlag(kCpuHasSSSE3)) {
2322
131
    ARGBAttenuateRow = ARGBAttenuateRow_Any_SSSE3;
2323
131
    if (IS_ALIGNED(width, 4)) {
2324
51
      ARGBAttenuateRow = ARGBAttenuateRow_SSSE3;
2325
51
    }
2326
131
  }
2327
131
#endif
2328
131
#if defined(HAS_ARGBATTENUATEROW_AVX2)
2329
131
  if (TestCpuFlag(kCpuHasAVX2)) {
2330
131
    ARGBAttenuateRow = ARGBAttenuateRow_Any_AVX2;
2331
131
    if (IS_ALIGNED(width, 8)) {
2332
34
      ARGBAttenuateRow = ARGBAttenuateRow_AVX2;
2333
34
    }
2334
131
  }
2335
131
#endif
2336
#if defined(HAS_ARGBATTENUATEROW_NEON)
2337
  if (TestCpuFlag(kCpuHasNEON)) {
2338
    ARGBAttenuateRow = ARGBAttenuateRow_Any_NEON;
2339
    if (IS_ALIGNED(width, 8)) {
2340
      ARGBAttenuateRow = ARGBAttenuateRow_NEON;
2341
    }
2342
  }
2343
#endif
2344
#if defined(HAS_ARGBATTENUATEROW_MSA)
2345
  if (TestCpuFlag(kCpuHasMSA)) {
2346
    ARGBAttenuateRow = ARGBAttenuateRow_Any_MSA;
2347
    if (IS_ALIGNED(width, 8)) {
2348
      ARGBAttenuateRow = ARGBAttenuateRow_MSA;
2349
    }
2350
  }
2351
#endif
2352
#if defined(HAS_ARGBATTENUATEROW_RVV)
2353
  if (TestCpuFlag(kCpuHasRVV)) {
2354
    ARGBAttenuateRow = ARGBAttenuateRow_RVV;
2355
  }
2356
#endif
2357
#if defined(HAS_ARGBATTENUATEROW_LSX)
2358
  if (TestCpuFlag(kCpuHasLSX)) {
2359
    ARGBAttenuateRow = ARGBAttenuateRow_Any_LSX;
2360
    if (IS_ALIGNED(width, 8)) {
2361
      ARGBAttenuateRow = ARGBAttenuateRow_LSX;
2362
    }
2363
  }
2364
#endif
2365
#if defined(HAS_ARGBATTENUATEROW_LASX)
2366
  if (TestCpuFlag(kCpuHasLASX)) {
2367
    ARGBAttenuateRow = ARGBAttenuateRow_Any_LASX;
2368
    if (IS_ALIGNED(width, 16)) {
2369
      ARGBAttenuateRow = ARGBAttenuateRow_LASX;
2370
    }
2371
  }
2372
#endif
2373
2374
2.80k
  for (y = 0; y < height; ++y) {
2375
2.67k
    I422AlphaToARGBRow(src_y, src_u, src_v, src_a, dst_argb, yuvconstants,
2376
2.67k
                       width);
2377
2.67k
    if (attenuate) {
2378
0
      ARGBAttenuateRow(dst_argb, dst_argb, width);
2379
0
    }
2380
2.67k
    dst_argb += dst_stride_argb;
2381
2.67k
    src_a += src_stride_a;
2382
2.67k
    src_y += src_stride_y;
2383
2.67k
    if (y & 1) {
2384
1.32k
      src_u += src_stride_u;
2385
1.32k
      src_v += src_stride_v;
2386
1.32k
    }
2387
2.67k
  }
2388
131
  return 0;
2389
131
}
2390
2391
// Convert I422 with Alpha to preattenuated ARGB with matrix.
2392
LIBYUV_API
2393
int I422AlphaToARGBMatrix(const uint8_t* src_y,
2394
                          int src_stride_y,
2395
                          const uint8_t* src_u,
2396
                          int src_stride_u,
2397
                          const uint8_t* src_v,
2398
                          int src_stride_v,
2399
                          const uint8_t* src_a,
2400
                          int src_stride_a,
2401
                          uint8_t* dst_argb,
2402
                          int dst_stride_argb,
2403
                          const struct YuvConstants* yuvconstants,
2404
                          int width,
2405
                          int height,
2406
93
                          int attenuate) {
2407
93
  int y;
2408
93
  void (*I422AlphaToARGBRow)(const uint8_t* y_buf, const uint8_t* u_buf,
2409
93
                             const uint8_t* v_buf, const uint8_t* a_buf,
2410
93
                             uint8_t* dst_argb,
2411
93
                             const struct YuvConstants* yuvconstants,
2412
93
                             int width) = I422AlphaToARGBRow_C;
2413
93
  void (*ARGBAttenuateRow)(const uint8_t* src_argb, uint8_t* dst_argb,
2414
93
                           int width) = ARGBAttenuateRow_C;
2415
93
  assert(yuvconstants);
2416
93
  if (!src_y || !src_u || !src_v || !src_a || !dst_argb || width <= 0 ||
2417
93
      height == 0) {
2418
0
    return -1;
2419
0
  }
2420
  // Negative height means invert the image.
2421
93
  if (height < 0) {
2422
0
    height = -height;
2423
0
    dst_argb = dst_argb + (height - 1) * dst_stride_argb;
2424
0
    dst_stride_argb = -dst_stride_argb;
2425
0
  }
2426
93
#if defined(HAS_I422ALPHATOARGBROW_SSSE3)
2427
93
  if (TestCpuFlag(kCpuHasSSSE3)) {
2428
93
    I422AlphaToARGBRow = I422AlphaToARGBRow_Any_SSSE3;
2429
93
    if (IS_ALIGNED(width, 8)) {
2430
34
      I422AlphaToARGBRow = I422AlphaToARGBRow_SSSE3;
2431
34
    }
2432
93
  }
2433
93
#endif
2434
93
#if defined(HAS_I422ALPHATOARGBROW_AVX2)
2435
93
  if (TestCpuFlag(kCpuHasAVX2)) {
2436
93
    I422AlphaToARGBRow = I422AlphaToARGBRow_Any_AVX2;
2437
93
    if (IS_ALIGNED(width, 16)) {
2438
17
      I422AlphaToARGBRow = I422AlphaToARGBRow_AVX2;
2439
17
    }
2440
93
  }
2441
93
#endif
2442
#if defined(HAS_I422ALPHATOARGBROW_NEON)
2443
  if (TestCpuFlag(kCpuHasNEON)) {
2444
    I422AlphaToARGBRow = I422AlphaToARGBRow_Any_NEON;
2445
    if (IS_ALIGNED(width, 8)) {
2446
      I422AlphaToARGBRow = I422AlphaToARGBRow_NEON;
2447
    }
2448
  }
2449
#endif
2450
#if defined(HAS_I422ALPHATOARGBROW_SVE2)
2451
  if (TestCpuFlag(kCpuHasSVE2)) {
2452
    I422AlphaToARGBRow = I422AlphaToARGBRow_SVE2;
2453
  }
2454
#endif
2455
#if defined(HAS_I422ALPHATOARGBROW_SME)
2456
  if (TestCpuFlag(kCpuHasSME)) {
2457
    I422AlphaToARGBRow = I422AlphaToARGBRow_SME;
2458
  }
2459
#endif
2460
#if defined(HAS_I422ALPHATOARGBROW_MSA)
2461
  if (TestCpuFlag(kCpuHasMSA)) {
2462
    I422AlphaToARGBRow = I422AlphaToARGBRow_Any_MSA;
2463
    if (IS_ALIGNED(width, 8)) {
2464
      I422AlphaToARGBRow = I422AlphaToARGBRow_MSA;
2465
    }
2466
  }
2467
#endif
2468
#if defined(HAS_I422ALPHATOARGBROW_LSX)
2469
  if (TestCpuFlag(kCpuHasLSX)) {
2470
    I422AlphaToARGBRow = I422AlphaToARGBRow_Any_LSX;
2471
    if (IS_ALIGNED(width, 16)) {
2472
      I422AlphaToARGBRow = I422AlphaToARGBRow_LSX;
2473
    }
2474
  }
2475
#endif
2476
#if defined(HAS_I422ALPHATOARGBROW_LASX)
2477
  if (TestCpuFlag(kCpuHasLASX)) {
2478
    I422AlphaToARGBRow = I422AlphaToARGBRow_Any_LASX;
2479
    if (IS_ALIGNED(width, 16)) {
2480
      I422AlphaToARGBRow = I422AlphaToARGBRow_LASX;
2481
    }
2482
  }
2483
#endif
2484
#if defined(HAS_I422ALPHATOARGBROW_RVV)
2485
  if (TestCpuFlag(kCpuHasRVV)) {
2486
    I422AlphaToARGBRow = I422AlphaToARGBRow_RVV;
2487
  }
2488
#endif
2489
93
#if defined(HAS_ARGBATTENUATEROW_SSSE3)
2490
93
  if (TestCpuFlag(kCpuHasSSSE3)) {
2491
93
    ARGBAttenuateRow = ARGBAttenuateRow_Any_SSSE3;
2492
93
    if (IS_ALIGNED(width, 4)) {
2493
52
      ARGBAttenuateRow = ARGBAttenuateRow_SSSE3;
2494
52
    }
2495
93
  }
2496
93
#endif
2497
93
#if defined(HAS_ARGBATTENUATEROW_AVX2)
2498
93
  if (TestCpuFlag(kCpuHasAVX2)) {
2499
93
    ARGBAttenuateRow = ARGBAttenuateRow_Any_AVX2;
2500
93
    if (IS_ALIGNED(width, 8)) {
2501
34
      ARGBAttenuateRow = ARGBAttenuateRow_AVX2;
2502
34
    }
2503
93
  }
2504
93
#endif
2505
#if defined(HAS_ARGBATTENUATEROW_NEON)
2506
  if (TestCpuFlag(kCpuHasNEON)) {
2507
    ARGBAttenuateRow = ARGBAttenuateRow_Any_NEON;
2508
    if (IS_ALIGNED(width, 8)) {
2509
      ARGBAttenuateRow = ARGBAttenuateRow_NEON;
2510
    }
2511
  }
2512
#endif
2513
#if defined(HAS_ARGBATTENUATEROW_MSA)
2514
  if (TestCpuFlag(kCpuHasMSA)) {
2515
    ARGBAttenuateRow = ARGBAttenuateRow_Any_MSA;
2516
    if (IS_ALIGNED(width, 8)) {
2517
      ARGBAttenuateRow = ARGBAttenuateRow_MSA;
2518
    }
2519
  }
2520
#endif
2521
#if defined(HAS_ARGBATTENUATEROW_RVV)
2522
  if (TestCpuFlag(kCpuHasRVV)) {
2523
    ARGBAttenuateRow = ARGBAttenuateRow_RVV;
2524
  }
2525
#endif
2526
#if defined(HAS_ARGBATTENUATEROW_LSX)
2527
  if (TestCpuFlag(kCpuHasLSX)) {
2528
    ARGBAttenuateRow = ARGBAttenuateRow_Any_LSX;
2529
    if (IS_ALIGNED(width, 8)) {
2530
      ARGBAttenuateRow = ARGBAttenuateRow_LSX;
2531
    }
2532
  }
2533
#endif
2534
#if defined(HAS_ARGBATTENUATEROW_LASX)
2535
  if (TestCpuFlag(kCpuHasLASX)) {
2536
    ARGBAttenuateRow = ARGBAttenuateRow_Any_LASX;
2537
    if (IS_ALIGNED(width, 16)) {
2538
      ARGBAttenuateRow = ARGBAttenuateRow_LASX;
2539
    }
2540
  }
2541
#endif
2542
2543
1.51k
  for (y = 0; y < height; ++y) {
2544
1.42k
    I422AlphaToARGBRow(src_y, src_u, src_v, src_a, dst_argb, yuvconstants,
2545
1.42k
                       width);
2546
1.42k
    if (attenuate) {
2547
0
      ARGBAttenuateRow(dst_argb, dst_argb, width);
2548
0
    }
2549
1.42k
    dst_argb += dst_stride_argb;
2550
1.42k
    src_a += src_stride_a;
2551
1.42k
    src_y += src_stride_y;
2552
1.42k
    src_u += src_stride_u;
2553
1.42k
    src_v += src_stride_v;
2554
1.42k
  }
2555
93
  return 0;
2556
93
}
2557
2558
// Convert I444 with Alpha to preattenuated ARGB with matrix.
2559
LIBYUV_API
2560
int I444AlphaToARGBMatrix(const uint8_t* src_y,
2561
                          int src_stride_y,
2562
                          const uint8_t* src_u,
2563
                          int src_stride_u,
2564
                          const uint8_t* src_v,
2565
                          int src_stride_v,
2566
                          const uint8_t* src_a,
2567
                          int src_stride_a,
2568
                          uint8_t* dst_argb,
2569
                          int dst_stride_argb,
2570
                          const struct YuvConstants* yuvconstants,
2571
                          int width,
2572
                          int height,
2573
123
                          int attenuate) {
2574
123
  int y;
2575
123
  void (*I444AlphaToARGBRow)(const uint8_t* y_buf, const uint8_t* u_buf,
2576
123
                             const uint8_t* v_buf, const uint8_t* a_buf,
2577
123
                             uint8_t* dst_argb,
2578
123
                             const struct YuvConstants* yuvconstants,
2579
123
                             int width) = I444AlphaToARGBRow_C;
2580
123
  void (*ARGBAttenuateRow)(const uint8_t* src_argb, uint8_t* dst_argb,
2581
123
                           int width) = ARGBAttenuateRow_C;
2582
123
  assert(yuvconstants);
2583
123
  if (!src_y || !src_u || !src_v || !src_a || !dst_argb || width <= 0 ||
2584
123
      height == 0) {
2585
0
    return -1;
2586
0
  }
2587
  // Negative height means invert the image.
2588
123
  if (height < 0) {
2589
0
    height = -height;
2590
0
    dst_argb = dst_argb + (height - 1) * dst_stride_argb;
2591
0
    dst_stride_argb = -dst_stride_argb;
2592
0
  }
2593
123
#if defined(HAS_I444ALPHATOARGBROW_SSSE3)
2594
123
  if (TestCpuFlag(kCpuHasSSSE3)) {
2595
123
    I444AlphaToARGBRow = I444AlphaToARGBRow_Any_SSSE3;
2596
123
    if (IS_ALIGNED(width, 8)) {
2597
36
      I444AlphaToARGBRow = I444AlphaToARGBRow_SSSE3;
2598
36
    }
2599
123
  }
2600
123
#endif
2601
123
#if defined(HAS_I444ALPHATOARGBROW_AVX2)
2602
123
  if (TestCpuFlag(kCpuHasAVX2)) {
2603
123
    I444AlphaToARGBRow = I444AlphaToARGBRow_Any_AVX2;
2604
123
    if (IS_ALIGNED(width, 16)) {
2605
19
      I444AlphaToARGBRow = I444AlphaToARGBRow_AVX2;
2606
19
    }
2607
123
  }
2608
123
#endif
2609
#if defined(HAS_I444ALPHATOARGBROW_NEON)
2610
  if (TestCpuFlag(kCpuHasNEON)) {
2611
    I444AlphaToARGBRow = I444AlphaToARGBRow_Any_NEON;
2612
    if (IS_ALIGNED(width, 8)) {
2613
      I444AlphaToARGBRow = I444AlphaToARGBRow_NEON;
2614
    }
2615
  }
2616
#endif
2617
#if defined(HAS_I444ALPHATOARGBROW_SVE2)
2618
  if (TestCpuFlag(kCpuHasSVE2)) {
2619
    I444AlphaToARGBRow = I444AlphaToARGBRow_SVE2;
2620
  }
2621
#endif
2622
#if defined(HAS_I444ALPHATOARGBROW_SME)
2623
  if (TestCpuFlag(kCpuHasSME)) {
2624
    I444AlphaToARGBRow = I444AlphaToARGBRow_SME;
2625
  }
2626
#endif
2627
#if defined(HAS_I444ALPHATOARGBROW_MSA)
2628
  if (TestCpuFlag(kCpuHasMSA)) {
2629
    I444AlphaToARGBRow = I444AlphaToARGBRow_Any_MSA;
2630
    if (IS_ALIGNED(width, 8)) {
2631
      I444AlphaToARGBRow = I444AlphaToARGBRow_MSA;
2632
    }
2633
  }
2634
#endif
2635
#if defined(HAS_I444ALPHATOARGBROW_RVV)
2636
  if (TestCpuFlag(kCpuHasRVV)) {
2637
    I444AlphaToARGBRow = I444AlphaToARGBRow_RVV;
2638
  }
2639
#endif
2640
123
#if defined(HAS_ARGBATTENUATEROW_SSSE3)
2641
123
  if (TestCpuFlag(kCpuHasSSSE3)) {
2642
123
    ARGBAttenuateRow = ARGBAttenuateRow_Any_SSSE3;
2643
123
    if (IS_ALIGNED(width, 4)) {
2644
61
      ARGBAttenuateRow = ARGBAttenuateRow_SSSE3;
2645
61
    }
2646
123
  }
2647
123
#endif
2648
123
#if defined(HAS_ARGBATTENUATEROW_AVX2)
2649
123
  if (TestCpuFlag(kCpuHasAVX2)) {
2650
123
    ARGBAttenuateRow = ARGBAttenuateRow_Any_AVX2;
2651
123
    if (IS_ALIGNED(width, 8)) {
2652
36
      ARGBAttenuateRow = ARGBAttenuateRow_AVX2;
2653
36
    }
2654
123
  }
2655
123
#endif
2656
#if defined(HAS_ARGBATTENUATEROW_NEON)
2657
  if (TestCpuFlag(kCpuHasNEON)) {
2658
    ARGBAttenuateRow = ARGBAttenuateRow_Any_NEON;
2659
    if (IS_ALIGNED(width, 8)) {
2660
      ARGBAttenuateRow = ARGBAttenuateRow_NEON;
2661
    }
2662
  }
2663
#endif
2664
#if defined(HAS_ARGBATTENUATEROW_MSA)
2665
  if (TestCpuFlag(kCpuHasMSA)) {
2666
    ARGBAttenuateRow = ARGBAttenuateRow_Any_MSA;
2667
    if (IS_ALIGNED(width, 8)) {
2668
      ARGBAttenuateRow = ARGBAttenuateRow_MSA;
2669
    }
2670
  }
2671
#endif
2672
#if defined(HAS_ARGBATTENUATEROW_RVV)
2673
  if (TestCpuFlag(kCpuHasRVV)) {
2674
    ARGBAttenuateRow = ARGBAttenuateRow_RVV;
2675
  }
2676
#endif
2677
#if defined(HAS_ARGBATTENUATEROW_LSX)
2678
  if (TestCpuFlag(kCpuHasLSX)) {
2679
    ARGBAttenuateRow = ARGBAttenuateRow_Any_LSX;
2680
    if (IS_ALIGNED(width, 8)) {
2681
      ARGBAttenuateRow = ARGBAttenuateRow_LSX;
2682
    }
2683
  }
2684
#endif
2685
#if defined(HAS_ARGBATTENUATEROW_LASX)
2686
  if (TestCpuFlag(kCpuHasLASX)) {
2687
    ARGBAttenuateRow = ARGBAttenuateRow_Any_LASX;
2688
    if (IS_ALIGNED(width, 16)) {
2689
      ARGBAttenuateRow = ARGBAttenuateRow_LASX;
2690
    }
2691
  }
2692
#endif
2693
2694
2.02k
  for (y = 0; y < height; ++y) {
2695
1.90k
    I444AlphaToARGBRow(src_y, src_u, src_v, src_a, dst_argb, yuvconstants,
2696
1.90k
                       width);
2697
1.90k
    if (attenuate) {
2698
0
      ARGBAttenuateRow(dst_argb, dst_argb, width);
2699
0
    }
2700
1.90k
    dst_argb += dst_stride_argb;
2701
1.90k
    src_a += src_stride_a;
2702
1.90k
    src_y += src_stride_y;
2703
1.90k
    src_u += src_stride_u;
2704
1.90k
    src_v += src_stride_v;
2705
1.90k
  }
2706
123
  return 0;
2707
123
}
2708
2709
// Convert I420 with Alpha to ARGB.
2710
LIBYUV_API
2711
int I420AlphaToARGB(const uint8_t* src_y,
2712
                    int src_stride_y,
2713
                    const uint8_t* src_u,
2714
                    int src_stride_u,
2715
                    const uint8_t* src_v,
2716
                    int src_stride_v,
2717
                    const uint8_t* src_a,
2718
                    int src_stride_a,
2719
                    uint8_t* dst_argb,
2720
                    int dst_stride_argb,
2721
                    int width,
2722
                    int height,
2723
0
                    int attenuate) {
2724
0
  return I420AlphaToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
2725
0
                               src_stride_v, src_a, src_stride_a, dst_argb,
2726
0
                               dst_stride_argb, &kYuvI601Constants, width,
2727
0
                               height, attenuate);
2728
0
}
2729
2730
// Convert I420 with Alpha to ABGR.
2731
LIBYUV_API
2732
int I420AlphaToABGR(const uint8_t* src_y,
2733
                    int src_stride_y,
2734
                    const uint8_t* src_u,
2735
                    int src_stride_u,
2736
                    const uint8_t* src_v,
2737
                    int src_stride_v,
2738
                    const uint8_t* src_a,
2739
                    int src_stride_a,
2740
                    uint8_t* dst_abgr,
2741
                    int dst_stride_abgr,
2742
                    int width,
2743
                    int height,
2744
0
                    int attenuate) {
2745
0
  return I420AlphaToARGBMatrix(
2746
0
      src_y, src_stride_y, src_v, src_stride_v,  // Swap U and V
2747
0
      src_u, src_stride_u, src_a, src_stride_a, dst_abgr, dst_stride_abgr,
2748
0
      &kYvuI601Constants,  // Use Yvu matrix
2749
0
      width, height, attenuate);
2750
0
}
2751
2752
// Convert I422 with Alpha to ARGB.
2753
LIBYUV_API
2754
int I422AlphaToARGB(const uint8_t* src_y,
2755
                    int src_stride_y,
2756
                    const uint8_t* src_u,
2757
                    int src_stride_u,
2758
                    const uint8_t* src_v,
2759
                    int src_stride_v,
2760
                    const uint8_t* src_a,
2761
                    int src_stride_a,
2762
                    uint8_t* dst_argb,
2763
                    int dst_stride_argb,
2764
                    int width,
2765
                    int height,
2766
0
                    int attenuate) {
2767
0
  return I422AlphaToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
2768
0
                               src_stride_v, src_a, src_stride_a, dst_argb,
2769
0
                               dst_stride_argb, &kYuvI601Constants, width,
2770
0
                               height, attenuate);
2771
0
}
2772
2773
// Convert I422 with Alpha to ABGR.
2774
LIBYUV_API
2775
int I422AlphaToABGR(const uint8_t* src_y,
2776
                    int src_stride_y,
2777
                    const uint8_t* src_u,
2778
                    int src_stride_u,
2779
                    const uint8_t* src_v,
2780
                    int src_stride_v,
2781
                    const uint8_t* src_a,
2782
                    int src_stride_a,
2783
                    uint8_t* dst_abgr,
2784
                    int dst_stride_abgr,
2785
                    int width,
2786
                    int height,
2787
0
                    int attenuate) {
2788
0
  return I422AlphaToARGBMatrix(
2789
0
      src_y, src_stride_y, src_v, src_stride_v,  // Swap U and V
2790
0
      src_u, src_stride_u, src_a, src_stride_a, dst_abgr, dst_stride_abgr,
2791
0
      &kYvuI601Constants,  // Use Yvu matrix
2792
0
      width, height, attenuate);
2793
0
}
2794
2795
// Convert I444 with Alpha to ARGB.
2796
LIBYUV_API
2797
int I444AlphaToARGB(const uint8_t* src_y,
2798
                    int src_stride_y,
2799
                    const uint8_t* src_u,
2800
                    int src_stride_u,
2801
                    const uint8_t* src_v,
2802
                    int src_stride_v,
2803
                    const uint8_t* src_a,
2804
                    int src_stride_a,
2805
                    uint8_t* dst_argb,
2806
                    int dst_stride_argb,
2807
                    int width,
2808
                    int height,
2809
0
                    int attenuate) {
2810
0
  return I444AlphaToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
2811
0
                               src_stride_v, src_a, src_stride_a, dst_argb,
2812
0
                               dst_stride_argb, &kYuvI601Constants, width,
2813
0
                               height, attenuate);
2814
0
}
2815
2816
// Convert I444 with Alpha to ABGR.
2817
LIBYUV_API
2818
int I444AlphaToABGR(const uint8_t* src_y,
2819
                    int src_stride_y,
2820
                    const uint8_t* src_u,
2821
                    int src_stride_u,
2822
                    const uint8_t* src_v,
2823
                    int src_stride_v,
2824
                    const uint8_t* src_a,
2825
                    int src_stride_a,
2826
                    uint8_t* dst_abgr,
2827
                    int dst_stride_abgr,
2828
                    int width,
2829
                    int height,
2830
0
                    int attenuate) {
2831
0
  return I444AlphaToARGBMatrix(
2832
0
      src_y, src_stride_y, src_v, src_stride_v,  // Swap U and V
2833
0
      src_u, src_stride_u, src_a, src_stride_a, dst_abgr, dst_stride_abgr,
2834
0
      &kYvuI601Constants,  // Use Yvu matrix
2835
0
      width, height, attenuate);
2836
0
}
2837
2838
// Convert I010 with Alpha to preattenuated ARGB with matrix.
2839
LIBYUV_API
2840
int I010AlphaToARGBMatrix(const uint16_t* src_y,
2841
                          int src_stride_y,
2842
                          const uint16_t* src_u,
2843
                          int src_stride_u,
2844
                          const uint16_t* src_v,
2845
                          int src_stride_v,
2846
                          const uint16_t* src_a,
2847
                          int src_stride_a,
2848
                          uint8_t* dst_argb,
2849
                          int dst_stride_argb,
2850
                          const struct YuvConstants* yuvconstants,
2851
                          int width,
2852
                          int height,
2853
125
                          int attenuate) {
2854
125
  int y;
2855
125
  void (*I210AlphaToARGBRow)(const uint16_t* y_buf, const uint16_t* u_buf,
2856
125
                             const uint16_t* v_buf, const uint16_t* a_buf,
2857
125
                             uint8_t* dst_argb,
2858
125
                             const struct YuvConstants* yuvconstants,
2859
125
                             int width) = I210AlphaToARGBRow_C;
2860
125
  void (*ARGBAttenuateRow)(const uint8_t* src_argb, uint8_t* dst_argb,
2861
125
                           int width) = ARGBAttenuateRow_C;
2862
125
  assert(yuvconstants);
2863
125
  if (!src_y || !src_u || !src_v || !src_a || !dst_argb || width <= 0 ||
2864
125
      height == 0) {
2865
0
    return -1;
2866
0
  }
2867
  // Negative height means invert the image.
2868
125
  if (height < 0) {
2869
0
    height = -height;
2870
0
    dst_argb = dst_argb + (height - 1) * dst_stride_argb;
2871
0
    dst_stride_argb = -dst_stride_argb;
2872
0
  }
2873
#if defined(HAS_I210ALPHATOARGBROW_NEON)
2874
  if (TestCpuFlag(kCpuHasNEON)) {
2875
    I210AlphaToARGBRow = I210AlphaToARGBRow_Any_NEON;
2876
    if (IS_ALIGNED(width, 8)) {
2877
      I210AlphaToARGBRow = I210AlphaToARGBRow_NEON;
2878
    }
2879
  }
2880
#endif
2881
#if defined(HAS_I210ALPHATOARGBROW_SVE2)
2882
  if (TestCpuFlag(kCpuHasSVE2)) {
2883
    I210AlphaToARGBRow = I210AlphaToARGBRow_SVE2;
2884
  }
2885
#endif
2886
#if defined(HAS_I210ALPHATOARGBROW_SME)
2887
  if (TestCpuFlag(kCpuHasSME)) {
2888
    I210AlphaToARGBRow = I210AlphaToARGBRow_SME;
2889
  }
2890
#endif
2891
125
#if defined(HAS_I210ALPHATOARGBROW_SSSE3)
2892
125
  if (TestCpuFlag(kCpuHasSSSE3)) {
2893
125
    I210AlphaToARGBRow = I210AlphaToARGBRow_Any_SSSE3;
2894
125
    if (IS_ALIGNED(width, 8)) {
2895
34
      I210AlphaToARGBRow = I210AlphaToARGBRow_SSSE3;
2896
34
    }
2897
125
  }
2898
125
#endif
2899
125
#if defined(HAS_I210ALPHATOARGBROW_AVX2)
2900
125
  if (TestCpuFlag(kCpuHasAVX2)) {
2901
125
    I210AlphaToARGBRow = I210AlphaToARGBRow_Any_AVX2;
2902
125
    if (IS_ALIGNED(width, 16)) {
2903
17
      I210AlphaToARGBRow = I210AlphaToARGBRow_AVX2;
2904
17
    }
2905
125
  }
2906
125
#endif
2907
125
#if defined(HAS_ARGBATTENUATEROW_SSSE3)
2908
125
  if (TestCpuFlag(kCpuHasSSSE3)) {
2909
125
    ARGBAttenuateRow = ARGBAttenuateRow_Any_SSSE3;
2910
125
    if (IS_ALIGNED(width, 4)) {
2911
52
      ARGBAttenuateRow = ARGBAttenuateRow_SSSE3;
2912
52
    }
2913
125
  }
2914
125
#endif
2915
125
#if defined(HAS_ARGBATTENUATEROW_AVX2)
2916
125
  if (TestCpuFlag(kCpuHasAVX2)) {
2917
125
    ARGBAttenuateRow = ARGBAttenuateRow_Any_AVX2;
2918
125
    if (IS_ALIGNED(width, 8)) {
2919
34
      ARGBAttenuateRow = ARGBAttenuateRow_AVX2;
2920
34
    }
2921
125
  }
2922
125
#endif
2923
#if defined(HAS_ARGBATTENUATEROW_NEON)
2924
  if (TestCpuFlag(kCpuHasNEON)) {
2925
    ARGBAttenuateRow = ARGBAttenuateRow_Any_NEON;
2926
    if (IS_ALIGNED(width, 8)) {
2927
      ARGBAttenuateRow = ARGBAttenuateRow_NEON;
2928
    }
2929
  }
2930
#endif
2931
#if defined(HAS_ARGBATTENUATEROW_MSA)
2932
  if (TestCpuFlag(kCpuHasMSA)) {
2933
    ARGBAttenuateRow = ARGBAttenuateRow_Any_MSA;
2934
    if (IS_ALIGNED(width, 8)) {
2935
      ARGBAttenuateRow = ARGBAttenuateRow_MSA;
2936
    }
2937
  }
2938
#endif
2939
#if defined(HAS_ARGBATTENUATEROW_RVV)
2940
  if (TestCpuFlag(kCpuHasRVV)) {
2941
    ARGBAttenuateRow = ARGBAttenuateRow_RVV;
2942
  }
2943
#endif
2944
#if defined(HAS_ARGBATTENUATEROW_LSX)
2945
  if (TestCpuFlag(kCpuHasLSX)) {
2946
    ARGBAttenuateRow = ARGBAttenuateRow_Any_LSX;
2947
    if (IS_ALIGNED(width, 8)) {
2948
      ARGBAttenuateRow = ARGBAttenuateRow_LSX;
2949
    }
2950
  }
2951
#endif
2952
#if defined(HAS_ARGBATTENUATEROW_LASX)
2953
  if (TestCpuFlag(kCpuHasLASX)) {
2954
    ARGBAttenuateRow = ARGBAttenuateRow_Any_LASX;
2955
    if (IS_ALIGNED(width, 16)) {
2956
      ARGBAttenuateRow = ARGBAttenuateRow_LASX;
2957
    }
2958
  }
2959
#endif
2960
2961
2.82k
  for (y = 0; y < height; ++y) {
2962
2.70k
    I210AlphaToARGBRow(src_y, src_u, src_v, src_a, dst_argb, yuvconstants,
2963
2.70k
                       width);
2964
2.70k
    if (attenuate) {
2965
0
      ARGBAttenuateRow(dst_argb, dst_argb, width);
2966
0
    }
2967
2.70k
    dst_argb += dst_stride_argb;
2968
2.70k
    src_a += src_stride_a;
2969
2.70k
    src_y += src_stride_y;
2970
2.70k
    if (y & 1) {
2971
1.34k
      src_u += src_stride_u;
2972
1.34k
      src_v += src_stride_v;
2973
1.34k
    }
2974
2.70k
  }
2975
125
  return 0;
2976
125
}
2977
2978
// Convert I210 with Alpha to preattenuated ARGB with matrix.
2979
LIBYUV_API
2980
int I210AlphaToARGBMatrix(const uint16_t* src_y,
2981
                          int src_stride_y,
2982
                          const uint16_t* src_u,
2983
                          int src_stride_u,
2984
                          const uint16_t* src_v,
2985
                          int src_stride_v,
2986
                          const uint16_t* src_a,
2987
                          int src_stride_a,
2988
                          uint8_t* dst_argb,
2989
                          int dst_stride_argb,
2990
                          const struct YuvConstants* yuvconstants,
2991
                          int width,
2992
                          int height,
2993
84
                          int attenuate) {
2994
84
  int y;
2995
84
  void (*I210AlphaToARGBRow)(const uint16_t* y_buf, const uint16_t* u_buf,
2996
84
                             const uint16_t* v_buf, const uint16_t* a_buf,
2997
84
                             uint8_t* dst_argb,
2998
84
                             const struct YuvConstants* yuvconstants,
2999
84
                             int width) = I210AlphaToARGBRow_C;
3000
84
  void (*ARGBAttenuateRow)(const uint8_t* src_argb, uint8_t* dst_argb,
3001
84
                           int width) = ARGBAttenuateRow_C;
3002
84
  assert(yuvconstants);
3003
84
  if (!src_y || !src_u || !src_v || !src_a || !dst_argb || width <= 0 ||
3004
84
      height == 0) {
3005
0
    return -1;
3006
0
  }
3007
  // Negative height means invert the image.
3008
84
  if (height < 0) {
3009
0
    height = -height;
3010
0
    dst_argb = dst_argb + (height - 1) * dst_stride_argb;
3011
0
    dst_stride_argb = -dst_stride_argb;
3012
0
  }
3013
#if defined(HAS_I210ALPHATOARGBROW_NEON)
3014
  if (TestCpuFlag(kCpuHasNEON)) {
3015
    I210AlphaToARGBRow = I210AlphaToARGBRow_Any_NEON;
3016
    if (IS_ALIGNED(width, 8)) {
3017
      I210AlphaToARGBRow = I210AlphaToARGBRow_NEON;
3018
    }
3019
  }
3020
#endif
3021
#if defined(HAS_I210ALPHATOARGBROW_SVE2)
3022
  if (TestCpuFlag(kCpuHasSVE2)) {
3023
    I210AlphaToARGBRow = I210AlphaToARGBRow_SVE2;
3024
  }
3025
#endif
3026
#if defined(HAS_I210ALPHATOARGBROW_SME)
3027
  if (TestCpuFlag(kCpuHasSME)) {
3028
    I210AlphaToARGBRow = I210AlphaToARGBRow_SME;
3029
  }
3030
#endif
3031
84
#if defined(HAS_I210ALPHATOARGBROW_SSSE3)
3032
84
  if (TestCpuFlag(kCpuHasSSSE3)) {
3033
84
    I210AlphaToARGBRow = I210AlphaToARGBRow_Any_SSSE3;
3034
84
    if (IS_ALIGNED(width, 8)) {
3035
34
      I210AlphaToARGBRow = I210AlphaToARGBRow_SSSE3;
3036
34
    }
3037
84
  }
3038
84
#endif
3039
84
#if defined(HAS_I210ALPHATOARGBROW_AVX2)
3040
84
  if (TestCpuFlag(kCpuHasAVX2)) {
3041
84
    I210AlphaToARGBRow = I210AlphaToARGBRow_Any_AVX2;
3042
84
    if (IS_ALIGNED(width, 16)) {
3043
17
      I210AlphaToARGBRow = I210AlphaToARGBRow_AVX2;
3044
17
    }
3045
84
  }
3046
84
#endif
3047
84
#if defined(HAS_ARGBATTENUATEROW_SSSE3)
3048
84
  if (TestCpuFlag(kCpuHasSSSE3)) {
3049
84
    ARGBAttenuateRow = ARGBAttenuateRow_Any_SSSE3;
3050
84
    if (IS_ALIGNED(width, 4)) {
3051
51
      ARGBAttenuateRow = ARGBAttenuateRow_SSSE3;
3052
51
    }
3053
84
  }
3054
84
#endif
3055
84
#if defined(HAS_ARGBATTENUATEROW_AVX2)
3056
84
  if (TestCpuFlag(kCpuHasAVX2)) {
3057
84
    ARGBAttenuateRow = ARGBAttenuateRow_Any_AVX2;
3058
84
    if (IS_ALIGNED(width, 8)) {
3059
34
      ARGBAttenuateRow = ARGBAttenuateRow_AVX2;
3060
34
    }
3061
84
  }
3062
84
#endif
3063
#if defined(HAS_ARGBATTENUATEROW_NEON)
3064
  if (TestCpuFlag(kCpuHasNEON)) {
3065
    ARGBAttenuateRow = ARGBAttenuateRow_Any_NEON;
3066
    if (IS_ALIGNED(width, 8)) {
3067
      ARGBAttenuateRow = ARGBAttenuateRow_NEON;
3068
    }
3069
  }
3070
#endif
3071
#if defined(HAS_ARGBATTENUATEROW_MSA)
3072
  if (TestCpuFlag(kCpuHasMSA)) {
3073
    ARGBAttenuateRow = ARGBAttenuateRow_Any_MSA;
3074
    if (IS_ALIGNED(width, 8)) {
3075
      ARGBAttenuateRow = ARGBAttenuateRow_MSA;
3076
    }
3077
  }
3078
#endif
3079
#if defined(HAS_ARGBATTENUATEROW_RVV)
3080
  if (TestCpuFlag(kCpuHasRVV)) {
3081
    ARGBAttenuateRow = ARGBAttenuateRow_RVV;
3082
  }
3083
#endif
3084
#if defined(HAS_ARGBATTENUATEROW_LSX)
3085
  if (TestCpuFlag(kCpuHasLSX)) {
3086
    ARGBAttenuateRow = ARGBAttenuateRow_Any_LSX;
3087
    if (IS_ALIGNED(width, 8)) {
3088
      ARGBAttenuateRow = ARGBAttenuateRow_LSX;
3089
    }
3090
  }
3091
#endif
3092
#if defined(HAS_ARGBATTENUATEROW_LASX)
3093
  if (TestCpuFlag(kCpuHasLASX)) {
3094
    ARGBAttenuateRow = ARGBAttenuateRow_Any_LASX;
3095
    if (IS_ALIGNED(width, 16)) {
3096
      ARGBAttenuateRow = ARGBAttenuateRow_LASX;
3097
    }
3098
  }
3099
#endif
3100
3101
1.49k
  for (y = 0; y < height; ++y) {
3102
1.41k
    I210AlphaToARGBRow(src_y, src_u, src_v, src_a, dst_argb, yuvconstants,
3103
1.41k
                       width);
3104
1.41k
    if (attenuate) {
3105
0
      ARGBAttenuateRow(dst_argb, dst_argb, width);
3106
0
    }
3107
1.41k
    dst_argb += dst_stride_argb;
3108
1.41k
    src_a += src_stride_a;
3109
1.41k
    src_y += src_stride_y;
3110
1.41k
    src_u += src_stride_u;
3111
1.41k
    src_v += src_stride_v;
3112
1.41k
  }
3113
84
  return 0;
3114
84
}
3115
3116
// Convert I410 with Alpha to preattenuated ARGB with matrix.
3117
LIBYUV_API
3118
int I410AlphaToARGBMatrix(const uint16_t* src_y,
3119
                          int src_stride_y,
3120
                          const uint16_t* src_u,
3121
                          int src_stride_u,
3122
                          const uint16_t* src_v,
3123
                          int src_stride_v,
3124
                          const uint16_t* src_a,
3125
                          int src_stride_a,
3126
                          uint8_t* dst_argb,
3127
                          int dst_stride_argb,
3128
                          const struct YuvConstants* yuvconstants,
3129
                          int width,
3130
                          int height,
3131
87
                          int attenuate) {
3132
87
  int y;
3133
87
  void (*I410AlphaToARGBRow)(const uint16_t* y_buf, const uint16_t* u_buf,
3134
87
                             const uint16_t* v_buf, const uint16_t* a_buf,
3135
87
                             uint8_t* dst_argb,
3136
87
                             const struct YuvConstants* yuvconstants,
3137
87
                             int width) = I410AlphaToARGBRow_C;
3138
87
  void (*ARGBAttenuateRow)(const uint8_t* src_argb, uint8_t* dst_argb,
3139
87
                           int width) = ARGBAttenuateRow_C;
3140
87
  assert(yuvconstants);
3141
87
  if (!src_y || !src_u || !src_v || !src_a || !dst_argb || width <= 0 ||
3142
87
      height == 0) {
3143
0
    return -1;
3144
0
  }
3145
  // Negative height means invert the image.
3146
87
  if (height < 0) {
3147
0
    height = -height;
3148
0
    dst_argb = dst_argb + (height - 1) * dst_stride_argb;
3149
0
    dst_stride_argb = -dst_stride_argb;
3150
0
  }
3151
#if defined(HAS_I410ALPHATOARGBROW_NEON)
3152
  if (TestCpuFlag(kCpuHasNEON)) {
3153
    I410AlphaToARGBRow = I410AlphaToARGBRow_Any_NEON;
3154
    if (IS_ALIGNED(width, 8)) {
3155
      I410AlphaToARGBRow = I410AlphaToARGBRow_NEON;
3156
    }
3157
  }
3158
#endif
3159
#if defined(HAS_I410ALPHATOARGBROW_SVE2)
3160
  if (TestCpuFlag(kCpuHasSVE2)) {
3161
    I410AlphaToARGBRow = I410AlphaToARGBRow_SVE2;
3162
  }
3163
#endif
3164
#if defined(HAS_I410ALPHATOARGBROW_SME)
3165
  if (TestCpuFlag(kCpuHasSME)) {
3166
    I410AlphaToARGBRow = I410AlphaToARGBRow_SME;
3167
  }
3168
#endif
3169
87
#if defined(HAS_I410ALPHATOARGBROW_SSSE3)
3170
87
  if (TestCpuFlag(kCpuHasSSSE3)) {
3171
87
    I410AlphaToARGBRow = I410AlphaToARGBRow_Any_SSSE3;
3172
87
    if (IS_ALIGNED(width, 8)) {
3173
34
      I410AlphaToARGBRow = I410AlphaToARGBRow_SSSE3;
3174
34
    }
3175
87
  }
3176
87
#endif
3177
87
#if defined(HAS_I410ALPHATOARGBROW_AVX2)
3178
87
  if (TestCpuFlag(kCpuHasAVX2)) {
3179
87
    I410AlphaToARGBRow = I410AlphaToARGBRow_Any_AVX2;
3180
87
    if (IS_ALIGNED(width, 16)) {
3181
17
      I410AlphaToARGBRow = I410AlphaToARGBRow_AVX2;
3182
17
    }
3183
87
  }
3184
87
#endif
3185
87
#if defined(HAS_ARGBATTENUATEROW_SSSE3)
3186
87
  if (TestCpuFlag(kCpuHasSSSE3)) {
3187
87
    ARGBAttenuateRow = ARGBAttenuateRow_Any_SSSE3;
3188
87
    if (IS_ALIGNED(width, 4)) {
3189
51
      ARGBAttenuateRow = ARGBAttenuateRow_SSSE3;
3190
51
    }
3191
87
  }
3192
87
#endif
3193
87
#if defined(HAS_ARGBATTENUATEROW_AVX2)
3194
87
  if (TestCpuFlag(kCpuHasAVX2)) {
3195
87
    ARGBAttenuateRow = ARGBAttenuateRow_Any_AVX2;
3196
87
    if (IS_ALIGNED(width, 8)) {
3197
34
      ARGBAttenuateRow = ARGBAttenuateRow_AVX2;
3198
34
    }
3199
87
  }
3200
87
#endif
3201
#if defined(HAS_ARGBATTENUATEROW_NEON)
3202
  if (TestCpuFlag(kCpuHasNEON)) {
3203
    ARGBAttenuateRow = ARGBAttenuateRow_Any_NEON;
3204
    if (IS_ALIGNED(width, 8)) {
3205
      ARGBAttenuateRow = ARGBAttenuateRow_NEON;
3206
    }
3207
  }
3208
#endif
3209
#if defined(HAS_ARGBATTENUATEROW_MSA)
3210
  if (TestCpuFlag(kCpuHasMSA)) {
3211
    ARGBAttenuateRow = ARGBAttenuateRow_Any_MSA;
3212
    if (IS_ALIGNED(width, 8)) {
3213
      ARGBAttenuateRow = ARGBAttenuateRow_MSA;
3214
    }
3215
  }
3216
#endif
3217
#if defined(HAS_ARGBATTENUATEROW_RVV)
3218
  if (TestCpuFlag(kCpuHasRVV)) {
3219
    ARGBAttenuateRow = ARGBAttenuateRow_RVV;
3220
  }
3221
#endif
3222
#if defined(HAS_ARGBATTENUATEROW_LSX)
3223
  if (TestCpuFlag(kCpuHasLSX)) {
3224
    ARGBAttenuateRow = ARGBAttenuateRow_Any_LSX;
3225
    if (IS_ALIGNED(width, 8)) {
3226
      ARGBAttenuateRow = ARGBAttenuateRow_LSX;
3227
    }
3228
  }
3229
#endif
3230
#if defined(HAS_ARGBATTENUATEROW_LASX)
3231
  if (TestCpuFlag(kCpuHasLASX)) {
3232
    ARGBAttenuateRow = ARGBAttenuateRow_Any_LASX;
3233
    if (IS_ALIGNED(width, 16)) {
3234
      ARGBAttenuateRow = ARGBAttenuateRow_LASX;
3235
    }
3236
  }
3237
#endif
3238
3239
1.74k
  for (y = 0; y < height; ++y) {
3240
1.66k
    I410AlphaToARGBRow(src_y, src_u, src_v, src_a, dst_argb, yuvconstants,
3241
1.66k
                       width);
3242
1.66k
    if (attenuate) {
3243
0
      ARGBAttenuateRow(dst_argb, dst_argb, width);
3244
0
    }
3245
1.66k
    dst_argb += dst_stride_argb;
3246
1.66k
    src_a += src_stride_a;
3247
1.66k
    src_y += src_stride_y;
3248
1.66k
    src_u += src_stride_u;
3249
1.66k
    src_v += src_stride_v;
3250
1.66k
  }
3251
87
  return 0;
3252
87
}
3253
3254
// Convert I400 to ARGB with matrix.
3255
LIBYUV_API
3256
int I400ToARGBMatrix(const uint8_t* src_y,
3257
                     int src_stride_y,
3258
                     uint8_t* dst_argb,
3259
                     int dst_stride_argb,
3260
                     const struct YuvConstants* yuvconstants,
3261
                     int width,
3262
347
                     int height) {
3263
347
  int y;
3264
347
  void (*I400ToARGBRow)(const uint8_t* y_buf, uint8_t* rgb_buf,
3265
347
                        const struct YuvConstants* yuvconstants, int width) =
3266
347
      I400ToARGBRow_C;
3267
347
  assert(yuvconstants);
3268
347
  if (!src_y || !dst_argb || width <= 0 || height == 0) {
3269
0
    return -1;
3270
0
  }
3271
  // Negative height means invert the image.
3272
347
  if (height < 0) {
3273
0
    height = -height;
3274
0
    dst_argb = dst_argb + (height - 1) * dst_stride_argb;
3275
0
    dst_stride_argb = -dst_stride_argb;
3276
0
  }
3277
  // Coalesce rows.
3278
347
  if (src_stride_y == width && dst_stride_argb == width * 4) {
3279
347
    width *= height;
3280
347
    height = 1;
3281
347
    src_stride_y = dst_stride_argb = 0;
3282
347
  }
3283
347
#if defined(HAS_I400TOARGBROW_SSE2)
3284
347
  if (TestCpuFlag(kCpuHasSSE2)) {
3285
347
    I400ToARGBRow = I400ToARGBRow_Any_SSE2;
3286
347
    if (IS_ALIGNED(width, 8)) {
3287
76
      I400ToARGBRow = I400ToARGBRow_SSE2;
3288
76
    }
3289
347
  }
3290
347
#endif
3291
347
#if defined(HAS_I400TOARGBROW_AVX2)
3292
347
  if (TestCpuFlag(kCpuHasAVX2)) {
3293
347
    I400ToARGBRow = I400ToARGBRow_Any_AVX2;
3294
347
    if (IS_ALIGNED(width, 16)) {
3295
33
      I400ToARGBRow = I400ToARGBRow_AVX2;
3296
33
    }
3297
347
  }
3298
347
#endif
3299
#if defined(HAS_I400TOARGBROW_NEON)
3300
  if (TestCpuFlag(kCpuHasNEON)) {
3301
    I400ToARGBRow = I400ToARGBRow_Any_NEON;
3302
    if (IS_ALIGNED(width, 8)) {
3303
      I400ToARGBRow = I400ToARGBRow_NEON;
3304
    }
3305
  }
3306
#endif
3307
#if defined(HAS_I400TOARGBROW_SVE2)
3308
  if (TestCpuFlag(kCpuHasSVE2)) {
3309
    I400ToARGBRow = I400ToARGBRow_SVE2;
3310
  }
3311
#endif
3312
#if defined(HAS_I400TOARGBROW_SME)
3313
  if (TestCpuFlag(kCpuHasSME)) {
3314
    I400ToARGBRow = I400ToARGBRow_SME;
3315
  }
3316
#endif
3317
#if defined(HAS_I400TOARGBROW_MSA)
3318
  if (TestCpuFlag(kCpuHasMSA)) {
3319
    I400ToARGBRow = I400ToARGBRow_Any_MSA;
3320
    if (IS_ALIGNED(width, 16)) {
3321
      I400ToARGBRow = I400ToARGBRow_MSA;
3322
    }
3323
  }
3324
#endif
3325
#if defined(HAS_I400TOARGBROW_LSX)
3326
  if (TestCpuFlag(kCpuHasLSX)) {
3327
    I400ToARGBRow = I400ToARGBRow_Any_LSX;
3328
    if (IS_ALIGNED(width, 16)) {
3329
      I400ToARGBRow = I400ToARGBRow_LSX;
3330
    }
3331
  }
3332
#endif
3333
#if defined(HAS_I400TOARGBROW_RVV)
3334
  if (TestCpuFlag(kCpuHasRVV)) {
3335
    I400ToARGBRow = I400ToARGBRow_RVV;
3336
  }
3337
#endif
3338
3339
694
  for (y = 0; y < height; ++y) {
3340
347
    I400ToARGBRow(src_y, dst_argb, yuvconstants, width);
3341
347
    dst_argb += dst_stride_argb;
3342
347
    src_y += src_stride_y;
3343
347
  }
3344
347
  return 0;
3345
347
}
3346
3347
// Convert I400 to ARGB.
3348
LIBYUV_API
3349
int I400ToARGB(const uint8_t* src_y,
3350
               int src_stride_y,
3351
               uint8_t* dst_argb,
3352
               int dst_stride_argb,
3353
               int width,
3354
0
               int height) {
3355
0
  return I400ToARGBMatrix(src_y, src_stride_y, dst_argb, dst_stride_argb,
3356
0
                          &kYuvI601Constants, width, height);
3357
0
}
3358
3359
// Convert J400 to ARGB.
3360
LIBYUV_API
3361
int J400ToARGB(const uint8_t* src_y,
3362
               int src_stride_y,
3363
               uint8_t* dst_argb,
3364
               int dst_stride_argb,
3365
               int width,
3366
0
               int height) {
3367
0
  int y;
3368
0
  void (*J400ToARGBRow)(const uint8_t* src_y, uint8_t* dst_argb, int width) =
3369
0
      J400ToARGBRow_C;
3370
0
  if (!src_y || !dst_argb || width <= 0 || height == 0) {
3371
0
    return -1;
3372
0
  }
3373
  // Negative height means invert the image.
3374
0
  if (height < 0) {
3375
0
    height = -height;
3376
0
    src_y = src_y + (height - 1) * src_stride_y;
3377
0
    src_stride_y = -src_stride_y;
3378
0
  }
3379
  // Coalesce rows.
3380
0
  if (src_stride_y == width && dst_stride_argb == width * 4) {
3381
0
    width *= height;
3382
0
    height = 1;
3383
0
    src_stride_y = dst_stride_argb = 0;
3384
0
  }
3385
0
#if defined(HAS_J400TOARGBROW_SSE2)
3386
0
  if (TestCpuFlag(kCpuHasSSE2)) {
3387
0
    J400ToARGBRow = J400ToARGBRow_Any_SSE2;
3388
0
    if (IS_ALIGNED(width, 8)) {
3389
0
      J400ToARGBRow = J400ToARGBRow_SSE2;
3390
0
    }
3391
0
  }
3392
0
#endif
3393
#if defined(HAS_J400TOARGBROW_AVX2)
3394
  if (TestCpuFlag(kCpuHasAVX2)) {
3395
    J400ToARGBRow = J400ToARGBRow_Any_AVX2;
3396
    if (IS_ALIGNED(width, 16)) {
3397
      J400ToARGBRow = J400ToARGBRow_AVX2;
3398
    }
3399
  }
3400
#endif
3401
#if defined(HAS_J400TOARGBROW_NEON)
3402
  if (TestCpuFlag(kCpuHasNEON)) {
3403
    J400ToARGBRow = J400ToARGBRow_Any_NEON;
3404
    if (IS_ALIGNED(width, 8)) {
3405
      J400ToARGBRow = J400ToARGBRow_NEON;
3406
    }
3407
  }
3408
#endif
3409
#if defined(HAS_J400TOARGBROW_MSA)
3410
  if (TestCpuFlag(kCpuHasMSA)) {
3411
    J400ToARGBRow = J400ToARGBRow_Any_MSA;
3412
    if (IS_ALIGNED(width, 16)) {
3413
      J400ToARGBRow = J400ToARGBRow_MSA;
3414
    }
3415
  }
3416
#endif
3417
#if defined(HAS_J400TOARGBROW_LSX)
3418
  if (TestCpuFlag(kCpuHasLSX)) {
3419
    J400ToARGBRow = J400ToARGBRow_Any_LSX;
3420
    if (IS_ALIGNED(width, 16)) {
3421
      J400ToARGBRow = J400ToARGBRow_LSX;
3422
    }
3423
  }
3424
#endif
3425
#if defined(HAS_J400TOARGBROW_RVV)
3426
  if (TestCpuFlag(kCpuHasRVV)) {
3427
    J400ToARGBRow = J400ToARGBRow_RVV;
3428
  }
3429
#endif
3430
3431
0
  for (y = 0; y < height; ++y) {
3432
0
    J400ToARGBRow(src_y, dst_argb, width);
3433
0
    src_y += src_stride_y;
3434
0
    dst_argb += dst_stride_argb;
3435
0
  }
3436
0
  return 0;
3437
0
}
3438
3439
#ifndef __riscv
3440
// Shuffle table for converting BGRA to ARGB.
3441
static const uvec8 kShuffleMaskBGRAToARGB = {
3442
    3u, 2u, 1u, 0u, 7u, 6u, 5u, 4u, 11u, 10u, 9u, 8u, 15u, 14u, 13u, 12u};
3443
3444
// Shuffle table for converting ABGR to ARGB.
3445
static const uvec8 kShuffleMaskABGRToARGB = {
3446
    2u, 1u, 0u, 3u, 6u, 5u, 4u, 7u, 10u, 9u, 8u, 11u, 14u, 13u, 12u, 15u};
3447
3448
// Shuffle table for converting RGBA to ARGB.
3449
static const uvec8 kShuffleMaskRGBAToARGB = {
3450
    1u, 2u, 3u, 0u, 5u, 6u, 7u, 4u, 9u, 10u, 11u, 8u, 13u, 14u, 15u, 12u};
3451
3452
// Shuffle table for converting AR64 to AB64.
3453
static const uvec8 kShuffleMaskAR64ToAB64 = {
3454
    4u, 5u, 2u, 3u, 0u, 1u, 6u, 7u, 12u, 13u, 10u, 11u, 8u, 9u, 14u, 15u};
3455
3456
// Convert BGRA to ARGB.
3457
LIBYUV_API
3458
int BGRAToARGB(const uint8_t* src_bgra,
3459
               int src_stride_bgra,
3460
               uint8_t* dst_argb,
3461
               int dst_stride_argb,
3462
               int width,
3463
0
               int height) {
3464
0
  return ARGBShuffle(src_bgra, src_stride_bgra, dst_argb, dst_stride_argb,
3465
0
                     (const uint8_t*)&kShuffleMaskBGRAToARGB, width, height);
3466
0
}
3467
3468
// Convert ARGB to BGRA (same as BGRAToARGB).
3469
LIBYUV_API
3470
int ARGBToBGRA(const uint8_t* src_bgra,
3471
               int src_stride_bgra,
3472
               uint8_t* dst_argb,
3473
               int dst_stride_argb,
3474
               int width,
3475
0
               int height) {
3476
0
  return ARGBShuffle(src_bgra, src_stride_bgra, dst_argb, dst_stride_argb,
3477
0
                     (const uint8_t*)&kShuffleMaskBGRAToARGB, width, height);
3478
0
}
3479
3480
// Convert ABGR to ARGB.
3481
LIBYUV_API
3482
int ABGRToARGB(const uint8_t* src_abgr,
3483
               int src_stride_abgr,
3484
               uint8_t* dst_argb,
3485
               int dst_stride_argb,
3486
               int width,
3487
0
               int height) {
3488
0
  return ARGBShuffle(src_abgr, src_stride_abgr, dst_argb, dst_stride_argb,
3489
0
                     (const uint8_t*)&kShuffleMaskABGRToARGB, width, height);
3490
0
}
3491
3492
// Convert ARGB to ABGR to (same as ABGRToARGB).
3493
LIBYUV_API
3494
int ARGBToABGR(const uint8_t* src_abgr,
3495
               int src_stride_abgr,
3496
               uint8_t* dst_argb,
3497
               int dst_stride_argb,
3498
               int width,
3499
0
               int height) {
3500
0
  return ARGBShuffle(src_abgr, src_stride_abgr, dst_argb, dst_stride_argb,
3501
0
                     (const uint8_t*)&kShuffleMaskABGRToARGB, width, height);
3502
0
}
3503
3504
// Convert RGBA to ARGB.
3505
LIBYUV_API
3506
int RGBAToARGB(const uint8_t* src_rgba,
3507
               int src_stride_rgba,
3508
               uint8_t* dst_argb,
3509
               int dst_stride_argb,
3510
               int width,
3511
0
               int height) {
3512
0
  return ARGBShuffle(src_rgba, src_stride_rgba, dst_argb, dst_stride_argb,
3513
0
                     (const uint8_t*)&kShuffleMaskRGBAToARGB, width, height);
3514
0
}
3515
3516
// Convert AR64 To AB64.
3517
LIBYUV_API
3518
int AR64ToAB64(const uint16_t* src_ar64,
3519
               int src_stride_ar64,
3520
               uint16_t* dst_ab64,
3521
               int dst_stride_ab64,
3522
               int width,
3523
0
               int height) {
3524
0
  return AR64Shuffle(src_ar64, src_stride_ar64, dst_ab64, dst_stride_ab64,
3525
0
                     (const uint8_t*)&kShuffleMaskAR64ToAB64, width, height);
3526
0
}
3527
#else
3528
// Convert BGRA to ARGB (same as ARGBToBGRA).
3529
LIBYUV_API
3530
int BGRAToARGB(const uint8_t* src_bgra,
3531
               int src_stride_bgra,
3532
               uint8_t* dst_argb,
3533
               int dst_stride_argb,
3534
               int width,
3535
               int height) {
3536
  return ARGBToBGRA(src_bgra, src_stride_bgra, dst_argb, dst_stride_argb, width,
3537
                    height);
3538
}
3539
3540
// Convert ARGB to BGRA.
3541
LIBYUV_API
3542
int ARGBToBGRA(const uint8_t* src_argb,
3543
               int src_stride_argb,
3544
               uint8_t* dst_bgra,
3545
               int dst_stride_bgra,
3546
               int width,
3547
               int height) {
3548
  int y;
3549
  void (*ARGBToBGRARow)(const uint8_t* src_argb, uint8_t* dst_bgra, int width) =
3550
      ARGBToBGRARow_C;
3551
  if (!src_argb || !dst_bgra || width <= 0 || height == 0) {
3552
    return -1;
3553
  }
3554
  // Negative height means invert the image.
3555
  if (height < 0) {
3556
    height = -height;
3557
    src_argb = src_argb + (height - 1) * src_stride_argb;
3558
    src_stride_argb = -src_stride_argb;
3559
  }
3560
  // Coalesce rows.
3561
  if (src_stride_argb == width * 4 && dst_stride_bgra == width * 4) {
3562
    width *= height;
3563
    height = 1;
3564
    src_stride_argb = dst_stride_bgra = 0;
3565
  }
3566
3567
#if defined(HAS_ARGBTOBGRAROW_RVV)
3568
  if (TestCpuFlag(kCpuHasRVV)) {
3569
    ARGBToBGRARow = ARGBToBGRARow_RVV;
3570
  }
3571
#endif
3572
3573
  for (y = 0; y < height; ++y) {
3574
    ARGBToBGRARow(src_argb, dst_bgra, width);
3575
    src_argb += src_stride_argb;
3576
    dst_bgra += dst_stride_bgra;
3577
  }
3578
  return 0;
3579
}
3580
3581
// Convert ARGB to ABGR.
3582
LIBYUV_API
3583
int ARGBToABGR(const uint8_t* src_argb,
3584
               int src_stride_argb,
3585
               uint8_t* dst_abgr,
3586
               int dst_stride_abgr,
3587
               int width,
3588
               int height) {
3589
  int y;
3590
  void (*ARGBToABGRRow)(const uint8_t* src_argb, uint8_t* dst_abgr, int width) =
3591
      ARGBToABGRRow_C;
3592
  if (!src_argb || !dst_abgr || width <= 0 || height == 0) {
3593
    return -1;
3594
  }
3595
  // Negative height means invert the image.
3596
  if (height < 0) {
3597
    height = -height;
3598
    src_argb = src_argb + (height - 1) * src_stride_argb;
3599
    src_stride_argb = -src_stride_argb;
3600
  }
3601
  // Coalesce rows.
3602
  if (src_stride_argb == width * 4 && dst_stride_abgr == width * 4) {
3603
    width *= height;
3604
    height = 1;
3605
    src_stride_argb = dst_stride_abgr = 0;
3606
  }
3607
3608
#if defined(HAS_ARGBTOABGRROW_RVV)
3609
  if (TestCpuFlag(kCpuHasRVV)) {
3610
    ARGBToABGRRow = ARGBToABGRRow_RVV;
3611
  }
3612
#endif
3613
3614
  for (y = 0; y < height; ++y) {
3615
    ARGBToABGRRow(src_argb, dst_abgr, width);
3616
    src_argb += src_stride_argb;
3617
    dst_abgr += dst_stride_abgr;
3618
  }
3619
  return 0;
3620
}
3621
3622
// Convert ABGR to ARGB (same as ARGBToABGR).
3623
LIBYUV_API
3624
int ABGRToARGB(const uint8_t* src_abgr,
3625
               int src_stride_abgr,
3626
               uint8_t* dst_argb,
3627
               int dst_stride_argb,
3628
               int width,
3629
               int height) {
3630
  return ARGBToABGR(src_abgr, src_stride_abgr, dst_argb, dst_stride_argb, width,
3631
                    height);
3632
}
3633
3634
// Convert RGBA to ARGB.
3635
LIBYUV_API
3636
int RGBAToARGB(const uint8_t* src_rgba,
3637
               int src_stride_rgba,
3638
               uint8_t* dst_argb,
3639
               int dst_stride_argb,
3640
               int width,
3641
               int height) {
3642
  int y;
3643
  void (*RGBAToARGBRow)(const uint8_t* src_rgba, uint8_t* dst_argb, int width) =
3644
      RGBAToARGBRow_C;
3645
  if (!src_rgba || !dst_argb || width <= 0 || height == 0) {
3646
    return -1;
3647
  }
3648
  // Negative height means invert the image.
3649
  if (height < 0) {
3650
    height = -height;
3651
    src_rgba = src_rgba + (height - 1) * src_stride_rgba;
3652
    src_stride_rgba = -src_stride_rgba;
3653
  }
3654
  // Coalesce rows.
3655
  if (src_stride_rgba == width * 4 && dst_stride_argb == width * 4) {
3656
    width *= height;
3657
    height = 1;
3658
    src_stride_rgba = dst_stride_argb = 0;
3659
  }
3660
3661
#if defined(HAS_RGBATOARGBROW_RVV)
3662
  if (TestCpuFlag(kCpuHasRVV)) {
3663
    RGBAToARGBRow = RGBAToARGBRow_RVV;
3664
  }
3665
#endif
3666
3667
  for (y = 0; y < height; ++y) {
3668
    RGBAToARGBRow(src_rgba, dst_argb, width);
3669
    src_rgba += src_stride_rgba;
3670
    dst_argb += dst_stride_argb;
3671
  }
3672
  return 0;
3673
}
3674
3675
// Convert AR64 To AB64.
3676
LIBYUV_API
3677
int AR64ToAB64(const uint16_t* src_ar64,
3678
               int src_stride_ar64,
3679
               uint16_t* dst_ab64,
3680
               int dst_stride_ab64,
3681
               int width,
3682
               int height) {
3683
  int y;
3684
  void (*AR64ToAB64Row)(const uint16_t* src_ar64, uint16_t* dst_ab64,
3685
                        int width) = AR64ToAB64Row_C;
3686
  if (!src_ar64 || !dst_ab64 || width <= 0 || height == 0) {
3687
    return -1;
3688
  }
3689
  // Negative height means invert the image.
3690
  if (height < 0) {
3691
    height = -height;
3692
    src_ar64 = src_ar64 + (height - 1) * src_stride_ar64;
3693
    src_stride_ar64 = -src_stride_ar64;
3694
  }
3695
  // Coalesce rows.
3696
  if (src_stride_ar64 == width * 4 && dst_stride_ab64 == width * 4) {
3697
    width *= height;
3698
    height = 1;
3699
    src_stride_ar64 = dst_stride_ab64 = 0;
3700
  }
3701
3702
#if defined(HAS_AR64TOAB64ROW_RVV)
3703
  if (TestCpuFlag(kCpuHasRVV)) {
3704
    AR64ToAB64Row = AR64ToAB64Row_RVV;
3705
  }
3706
#endif
3707
3708
  for (y = 0; y < height; ++y) {
3709
    AR64ToAB64Row(src_ar64, dst_ab64, width);
3710
    src_ar64 += src_stride_ar64;
3711
    dst_ab64 += dst_stride_ab64;
3712
  }
3713
  return 0;
3714
}
3715
#endif
3716
3717
// Convert RGB24 to ARGB.
3718
LIBYUV_API
3719
int RGB24ToARGB(const uint8_t* src_rgb24,
3720
                int src_stride_rgb24,
3721
                uint8_t* dst_argb,
3722
                int dst_stride_argb,
3723
                int width,
3724
0
                int height) {
3725
0
  int y;
3726
0
  void (*RGB24ToARGBRow)(const uint8_t* src_rgb, uint8_t* dst_argb, int width) =
3727
0
      RGB24ToARGBRow_C;
3728
0
  if (!src_rgb24 || !dst_argb || width <= 0 || height == 0) {
3729
0
    return -1;
3730
0
  }
3731
  // Negative height means invert the image.
3732
0
  if (height < 0) {
3733
0
    height = -height;
3734
0
    src_rgb24 = src_rgb24 + (height - 1) * src_stride_rgb24;
3735
0
    src_stride_rgb24 = -src_stride_rgb24;
3736
0
  }
3737
  // Coalesce rows.
3738
0
  if (src_stride_rgb24 == width * 3 && dst_stride_argb == width * 4) {
3739
0
    width *= height;
3740
0
    height = 1;
3741
0
    src_stride_rgb24 = dst_stride_argb = 0;
3742
0
  }
3743
0
#if defined(HAS_RGB24TOARGBROW_SSSE3)
3744
0
  if (TestCpuFlag(kCpuHasSSSE3)) {
3745
0
    RGB24ToARGBRow = RGB24ToARGBRow_Any_SSSE3;
3746
0
    if (IS_ALIGNED(width, 16)) {
3747
0
      RGB24ToARGBRow = RGB24ToARGBRow_SSSE3;
3748
0
    }
3749
0
  }
3750
0
#endif
3751
#if defined(HAS_RGB24TOARGBROW_NEON)
3752
  if (TestCpuFlag(kCpuHasNEON)) {
3753
    RGB24ToARGBRow = RGB24ToARGBRow_Any_NEON;
3754
    if (IS_ALIGNED(width, 8)) {
3755
      RGB24ToARGBRow = RGB24ToARGBRow_NEON;
3756
    }
3757
  }
3758
#endif
3759
#if defined(HAS_RGB24TOARGBROW_SVE2)
3760
  if (TestCpuFlag(kCpuHasSVE2)) {
3761
    RGB24ToARGBRow = RGB24ToARGBRow_SVE2;
3762
  }
3763
#endif
3764
#if defined(HAS_RGB24TOARGBROW_MSA)
3765
  if (TestCpuFlag(kCpuHasMSA)) {
3766
    RGB24ToARGBRow = RGB24ToARGBRow_Any_MSA;
3767
    if (IS_ALIGNED(width, 16)) {
3768
      RGB24ToARGBRow = RGB24ToARGBRow_MSA;
3769
    }
3770
  }
3771
#endif
3772
#if defined(HAS_RGB24TOARGBROW_LSX)
3773
  if (TestCpuFlag(kCpuHasLSX)) {
3774
    RGB24ToARGBRow = RGB24ToARGBRow_Any_LSX;
3775
    if (IS_ALIGNED(width, 16)) {
3776
      RGB24ToARGBRow = RGB24ToARGBRow_LSX;
3777
    }
3778
  }
3779
#endif
3780
#if defined(HAS_RGB24TOARGBROW_LASX)
3781
  if (TestCpuFlag(kCpuHasLASX)) {
3782
    RGB24ToARGBRow = RGB24ToARGBRow_Any_LASX;
3783
    if (IS_ALIGNED(width, 32)) {
3784
      RGB24ToARGBRow = RGB24ToARGBRow_LASX;
3785
    }
3786
  }
3787
#endif
3788
#if defined(HAS_RGB24TOARGBROW_RVV)
3789
  if (TestCpuFlag(kCpuHasRVV)) {
3790
    RGB24ToARGBRow = RGB24ToARGBRow_RVV;
3791
  }
3792
#endif
3793
3794
0
  for (y = 0; y < height; ++y) {
3795
0
    RGB24ToARGBRow(src_rgb24, dst_argb, width);
3796
0
    src_rgb24 += src_stride_rgb24;
3797
0
    dst_argb += dst_stride_argb;
3798
0
  }
3799
0
  return 0;
3800
0
}
3801
3802
// Convert RAW to ARGB.
3803
LIBYUV_API
3804
int RAWToARGB(const uint8_t* src_raw,
3805
              int src_stride_raw,
3806
              uint8_t* dst_argb,
3807
              int dst_stride_argb,
3808
              int width,
3809
216k
              int height) {
3810
216k
  int y;
3811
216k
  void (*RAWToARGBRow)(const uint8_t* src_rgb, uint8_t* dst_argb, int width) =
3812
216k
      RAWToARGBRow_C;
3813
216k
  if (!src_raw || !dst_argb || width <= 0 || height == 0) {
3814
0
    return -1;
3815
0
  }
3816
  // Negative height means invert the image.
3817
216k
  if (height < 0) {
3818
0
    height = -height;
3819
0
    src_raw = src_raw + (height - 1) * src_stride_raw;
3820
0
    src_stride_raw = -src_stride_raw;
3821
0
  }
3822
  // Coalesce rows.
3823
216k
  if (src_stride_raw == width * 3 && dst_stride_argb == width * 4) {
3824
216k
    width *= height;
3825
216k
    height = 1;
3826
216k
    src_stride_raw = dst_stride_argb = 0;
3827
216k
  }
3828
216k
#if defined(HAS_RAWTOARGBROW_SSSE3)
3829
216k
  if (TestCpuFlag(kCpuHasSSSE3)) {
3830
216k
    RAWToARGBRow = RAWToARGBRow_Any_SSSE3;
3831
216k
    if (IS_ALIGNED(width, 16)) {
3832
29.7k
      RAWToARGBRow = RAWToARGBRow_SSSE3;
3833
29.7k
    }
3834
216k
  }
3835
216k
#endif
3836
216k
#if defined(HAS_RAWTOARGBROW_AVX2)
3837
216k
  if (TestCpuFlag(kCpuHasAVX2)) {
3838
216k
    RAWToARGBRow = RAWToARGBRow_Any_AVX2;
3839
216k
    if (IS_ALIGNED(width, 32)) {
3840
7.60k
      RAWToARGBRow = RAWToARGBRow_AVX2;
3841
7.60k
    }
3842
216k
  }
3843
216k
#endif
3844
#if defined(HAS_RAWTOARGBROW_NEON)
3845
  if (TestCpuFlag(kCpuHasNEON)) {
3846
    RAWToARGBRow = RAWToARGBRow_Any_NEON;
3847
    if (IS_ALIGNED(width, 8)) {
3848
      RAWToARGBRow = RAWToARGBRow_NEON;
3849
    }
3850
  }
3851
#endif
3852
#if defined(HAS_RAWTOARGBROW_SVE2)
3853
  if (TestCpuFlag(kCpuHasSVE2)) {
3854
    RAWToARGBRow = RAWToARGBRow_SVE2;
3855
  }
3856
#endif
3857
#if defined(HAS_RAWTOARGBROW_MSA)
3858
  if (TestCpuFlag(kCpuHasMSA)) {
3859
    RAWToARGBRow = RAWToARGBRow_Any_MSA;
3860
    if (IS_ALIGNED(width, 16)) {
3861
      RAWToARGBRow = RAWToARGBRow_MSA;
3862
    }
3863
  }
3864
#endif
3865
#if defined(HAS_RAWTOARGBROW_LSX)
3866
  if (TestCpuFlag(kCpuHasLSX)) {
3867
    RAWToARGBRow = RAWToARGBRow_Any_LSX;
3868
    if (IS_ALIGNED(width, 16)) {
3869
      RAWToARGBRow = RAWToARGBRow_LSX;
3870
    }
3871
  }
3872
#endif
3873
#if defined(HAS_RAWTOARGBROW_LASX)
3874
  if (TestCpuFlag(kCpuHasLASX)) {
3875
    RAWToARGBRow = RAWToARGBRow_Any_LASX;
3876
    if (IS_ALIGNED(width, 32)) {
3877
      RAWToARGBRow = RAWToARGBRow_LASX;
3878
    }
3879
  }
3880
#endif
3881
#if defined(HAS_RAWTOARGBROW_RVV)
3882
  if (TestCpuFlag(kCpuHasRVV)) {
3883
    RAWToARGBRow = RAWToARGBRow_RVV;
3884
  }
3885
#endif
3886
3887
432k
  for (y = 0; y < height; ++y) {
3888
216k
    RAWToARGBRow(src_raw, dst_argb, width);
3889
216k
    src_raw += src_stride_raw;
3890
216k
    dst_argb += dst_stride_argb;
3891
216k
  }
3892
216k
  return 0;
3893
216k
}
3894
3895
// Convert RAW to RGBA.
3896
LIBYUV_API
3897
int RAWToRGBA(const uint8_t* src_raw,
3898
              int src_stride_raw,
3899
              uint8_t* dst_rgba,
3900
              int dst_stride_rgba,
3901
              int width,
3902
0
              int height) {
3903
0
  int y;
3904
0
  void (*RAWToRGBARow)(const uint8_t* src_rgb, uint8_t* dst_rgba, int width) =
3905
0
      RAWToRGBARow_C;
3906
0
  if (!src_raw || !dst_rgba || width <= 0 || height == 0) {
3907
0
    return -1;
3908
0
  }
3909
  // Negative height means invert the image.
3910
0
  if (height < 0) {
3911
0
    height = -height;
3912
0
    src_raw = src_raw + (height - 1) * src_stride_raw;
3913
0
    src_stride_raw = -src_stride_raw;
3914
0
  }
3915
  // Coalesce rows.
3916
0
  if (src_stride_raw == width * 3 && dst_stride_rgba == width * 4) {
3917
0
    width *= height;
3918
0
    height = 1;
3919
0
    src_stride_raw = dst_stride_rgba = 0;
3920
0
  }
3921
0
#if defined(HAS_RAWTORGBAROW_SSSE3)
3922
0
  if (TestCpuFlag(kCpuHasSSSE3)) {
3923
0
    RAWToRGBARow = RAWToRGBARow_Any_SSSE3;
3924
0
    if (IS_ALIGNED(width, 16)) {
3925
0
      RAWToRGBARow = RAWToRGBARow_SSSE3;
3926
0
    }
3927
0
  }
3928
0
#endif
3929
#if defined(HAS_RAWTORGBAROW_NEON)
3930
  if (TestCpuFlag(kCpuHasNEON)) {
3931
    RAWToRGBARow = RAWToRGBARow_Any_NEON;
3932
    if (IS_ALIGNED(width, 8)) {
3933
      RAWToRGBARow = RAWToRGBARow_NEON;
3934
    }
3935
  }
3936
#endif
3937
#if defined(HAS_RAWTORGBAROW_SVE2)
3938
  if (TestCpuFlag(kCpuHasSVE2)) {
3939
    RAWToRGBARow = RAWToRGBARow_SVE2;
3940
  }
3941
#endif
3942
#if defined(HAS_RAWTORGBAROW_RVV)
3943
  if (TestCpuFlag(kCpuHasRVV)) {
3944
    RAWToRGBARow = RAWToRGBARow_RVV;
3945
  }
3946
#endif
3947
3948
0
  for (y = 0; y < height; ++y) {
3949
0
    RAWToRGBARow(src_raw, dst_rgba, width);
3950
0
    src_raw += src_stride_raw;
3951
0
    dst_rgba += dst_stride_rgba;
3952
0
  }
3953
0
  return 0;
3954
0
}
3955
3956
// Convert RGB565 to ARGB.
3957
LIBYUV_API
3958
int RGB565ToARGB(const uint8_t* src_rgb565,
3959
                 int src_stride_rgb565,
3960
                 uint8_t* dst_argb,
3961
                 int dst_stride_argb,
3962
                 int width,
3963
0
                 int height) {
3964
0
  int y;
3965
0
  void (*RGB565ToARGBRow)(const uint8_t* src_rgb565, uint8_t* dst_argb,
3966
0
                          int width) = RGB565ToARGBRow_C;
3967
0
  if (!src_rgb565 || !dst_argb || width <= 0 || height == 0) {
3968
0
    return -1;
3969
0
  }
3970
  // Negative height means invert the image.
3971
0
  if (height < 0) {
3972
0
    height = -height;
3973
0
    src_rgb565 = src_rgb565 + (height - 1) * src_stride_rgb565;
3974
0
    src_stride_rgb565 = -src_stride_rgb565;
3975
0
  }
3976
  // Coalesce rows.
3977
0
  if (src_stride_rgb565 == width * 2 && dst_stride_argb == width * 4) {
3978
0
    width *= height;
3979
0
    height = 1;
3980
0
    src_stride_rgb565 = dst_stride_argb = 0;
3981
0
  }
3982
0
#if defined(HAS_RGB565TOARGBROW_SSE2)
3983
0
  if (TestCpuFlag(kCpuHasSSE2)) {
3984
0
    RGB565ToARGBRow = RGB565ToARGBRow_Any_SSE2;
3985
0
    if (IS_ALIGNED(width, 8)) {
3986
0
      RGB565ToARGBRow = RGB565ToARGBRow_SSE2;
3987
0
    }
3988
0
  }
3989
0
#endif
3990
#if defined(HAS_RGB565TOARGBROW_AVX2)
3991
  if (TestCpuFlag(kCpuHasAVX2)) {
3992
    RGB565ToARGBRow = RGB565ToARGBRow_Any_AVX2;
3993
    if (IS_ALIGNED(width, 16)) {
3994
      RGB565ToARGBRow = RGB565ToARGBRow_AVX2;
3995
    }
3996
  }
3997
#endif
3998
#if defined(HAS_RGB565TOARGBROW_NEON)
3999
  if (TestCpuFlag(kCpuHasNEON)) {
4000
    RGB565ToARGBRow = RGB565ToARGBRow_Any_NEON;
4001
    if (IS_ALIGNED(width, 16)) {
4002
      RGB565ToARGBRow = RGB565ToARGBRow_NEON;
4003
    }
4004
  }
4005
#endif
4006
#if defined(HAS_RGB565TOARGBROW_MSA)
4007
  if (TestCpuFlag(kCpuHasMSA)) {
4008
    RGB565ToARGBRow = RGB565ToARGBRow_Any_MSA;
4009
    if (IS_ALIGNED(width, 16)) {
4010
      RGB565ToARGBRow = RGB565ToARGBRow_MSA;
4011
    }
4012
  }
4013
#endif
4014
#if defined(HAS_RGB565TOARGBROW_LSX)
4015
  if (TestCpuFlag(kCpuHasLSX)) {
4016
    RGB565ToARGBRow = RGB565ToARGBRow_Any_LSX;
4017
    if (IS_ALIGNED(width, 16)) {
4018
      RGB565ToARGBRow = RGB565ToARGBRow_LSX;
4019
    }
4020
  }
4021
#endif
4022
#if defined(HAS_RGB565TOARGBROW_LASX)
4023
  if (TestCpuFlag(kCpuHasLASX)) {
4024
    RGB565ToARGBRow = RGB565ToARGBRow_Any_LASX;
4025
    if (IS_ALIGNED(width, 32)) {
4026
      RGB565ToARGBRow = RGB565ToARGBRow_LASX;
4027
    }
4028
  }
4029
#endif
4030
4031
0
  for (y = 0; y < height; ++y) {
4032
0
    RGB565ToARGBRow(src_rgb565, dst_argb, width);
4033
0
    src_rgb565 += src_stride_rgb565;
4034
0
    dst_argb += dst_stride_argb;
4035
0
  }
4036
0
  return 0;
4037
0
}
4038
4039
// Convert ARGB1555 to ARGB.
4040
LIBYUV_API
4041
int ARGB1555ToARGB(const uint8_t* src_argb1555,
4042
                   int src_stride_argb1555,
4043
                   uint8_t* dst_argb,
4044
                   int dst_stride_argb,
4045
                   int width,
4046
0
                   int height) {
4047
0
  int y;
4048
0
  void (*ARGB1555ToARGBRow)(const uint8_t* src_argb1555, uint8_t* dst_argb,
4049
0
                            int width) = ARGB1555ToARGBRow_C;
4050
0
  if (!src_argb1555 || !dst_argb || width <= 0 || height == 0) {
4051
0
    return -1;
4052
0
  }
4053
  // Negative height means invert the image.
4054
0
  if (height < 0) {
4055
0
    height = -height;
4056
0
    src_argb1555 = src_argb1555 + (height - 1) * src_stride_argb1555;
4057
0
    src_stride_argb1555 = -src_stride_argb1555;
4058
0
  }
4059
  // Coalesce rows.
4060
0
  if (src_stride_argb1555 == width * 2 && dst_stride_argb == width * 4) {
4061
0
    width *= height;
4062
0
    height = 1;
4063
0
    src_stride_argb1555 = dst_stride_argb = 0;
4064
0
  }
4065
0
#if defined(HAS_ARGB1555TOARGBROW_SSE2)
4066
0
  if (TestCpuFlag(kCpuHasSSE2)) {
4067
0
    ARGB1555ToARGBRow = ARGB1555ToARGBRow_Any_SSE2;
4068
0
    if (IS_ALIGNED(width, 8)) {
4069
0
      ARGB1555ToARGBRow = ARGB1555ToARGBRow_SSE2;
4070
0
    }
4071
0
  }
4072
0
#endif
4073
#if defined(HAS_ARGB1555TOARGBROW_AVX2)
4074
  if (TestCpuFlag(kCpuHasAVX2)) {
4075
    ARGB1555ToARGBRow = ARGB1555ToARGBRow_Any_AVX2;
4076
    if (IS_ALIGNED(width, 16)) {
4077
      ARGB1555ToARGBRow = ARGB1555ToARGBRow_AVX2;
4078
    }
4079
  }
4080
#endif
4081
#if defined(HAS_ARGB1555TOARGBROW_NEON)
4082
  if (TestCpuFlag(kCpuHasNEON)) {
4083
    ARGB1555ToARGBRow = ARGB1555ToARGBRow_Any_NEON;
4084
    if (IS_ALIGNED(width, 16)) {
4085
      ARGB1555ToARGBRow = ARGB1555ToARGBRow_NEON;
4086
    }
4087
  }
4088
#endif
4089
#if defined(HAS_ARGB1555TOARGBROW_SVE2)
4090
  if (TestCpuFlag(kCpuHasSVE2)) {
4091
    ARGB1555ToARGBRow = ARGB1555ToARGBRow_SVE2;
4092
  }
4093
#endif
4094
#if defined(HAS_ARGB1555TOARGBROW_MSA)
4095
  if (TestCpuFlag(kCpuHasMSA)) {
4096
    ARGB1555ToARGBRow = ARGB1555ToARGBRow_Any_MSA;
4097
    if (IS_ALIGNED(width, 16)) {
4098
      ARGB1555ToARGBRow = ARGB1555ToARGBRow_MSA;
4099
    }
4100
  }
4101
#endif
4102
#if defined(HAS_ARGB1555TOARGBROW_LSX)
4103
  if (TestCpuFlag(kCpuHasLSX)) {
4104
    ARGB1555ToARGBRow = ARGB1555ToARGBRow_Any_LSX;
4105
    if (IS_ALIGNED(width, 16)) {
4106
      ARGB1555ToARGBRow = ARGB1555ToARGBRow_LSX;
4107
    }
4108
  }
4109
#endif
4110
#if defined(HAS_ARGB1555TOARGBROW_LASX)
4111
  if (TestCpuFlag(kCpuHasLASX)) {
4112
    ARGB1555ToARGBRow = ARGB1555ToARGBRow_Any_LASX;
4113
    if (IS_ALIGNED(width, 32)) {
4114
      ARGB1555ToARGBRow = ARGB1555ToARGBRow_LASX;
4115
    }
4116
  }
4117
#endif
4118
4119
0
  for (y = 0; y < height; ++y) {
4120
0
    ARGB1555ToARGBRow(src_argb1555, dst_argb, width);
4121
0
    src_argb1555 += src_stride_argb1555;
4122
0
    dst_argb += dst_stride_argb;
4123
0
  }
4124
0
  return 0;
4125
0
}
4126
4127
// Convert ARGB4444 to ARGB.
4128
LIBYUV_API
4129
int ARGB4444ToARGB(const uint8_t* src_argb4444,
4130
                   int src_stride_argb4444,
4131
                   uint8_t* dst_argb,
4132
                   int dst_stride_argb,
4133
                   int width,
4134
0
                   int height) {
4135
0
  int y;
4136
0
  void (*ARGB4444ToARGBRow)(const uint8_t* src_argb4444, uint8_t* dst_argb,
4137
0
                            int width) = ARGB4444ToARGBRow_C;
4138
0
  if (!src_argb4444 || !dst_argb || width <= 0 || height == 0) {
4139
0
    return -1;
4140
0
  }
4141
  // Negative height means invert the image.
4142
0
  if (height < 0) {
4143
0
    height = -height;
4144
0
    src_argb4444 = src_argb4444 + (height - 1) * src_stride_argb4444;
4145
0
    src_stride_argb4444 = -src_stride_argb4444;
4146
0
  }
4147
  // Coalesce rows.
4148
0
  if (src_stride_argb4444 == width * 2 && dst_stride_argb == width * 4) {
4149
0
    width *= height;
4150
0
    height = 1;
4151
0
    src_stride_argb4444 = dst_stride_argb = 0;
4152
0
  }
4153
0
#if defined(HAS_ARGB4444TOARGBROW_SSE2)
4154
0
  if (TestCpuFlag(kCpuHasSSE2)) {
4155
0
    ARGB4444ToARGBRow = ARGB4444ToARGBRow_Any_SSE2;
4156
0
    if (IS_ALIGNED(width, 8)) {
4157
0
      ARGB4444ToARGBRow = ARGB4444ToARGBRow_SSE2;
4158
0
    }
4159
0
  }
4160
0
#endif
4161
#if defined(HAS_ARGB4444TOARGBROW_AVX2)
4162
  if (TestCpuFlag(kCpuHasAVX2)) {
4163
    ARGB4444ToARGBRow = ARGB4444ToARGBRow_Any_AVX2;
4164
    if (IS_ALIGNED(width, 16)) {
4165
      ARGB4444ToARGBRow = ARGB4444ToARGBRow_AVX2;
4166
    }
4167
  }
4168
#endif
4169
#if defined(HAS_ARGB4444TOARGBROW_NEON)
4170
  if (TestCpuFlag(kCpuHasNEON)) {
4171
    ARGB4444ToARGBRow = ARGB4444ToARGBRow_Any_NEON;
4172
    if (IS_ALIGNED(width, 8)) {
4173
      ARGB4444ToARGBRow = ARGB4444ToARGBRow_NEON;
4174
    }
4175
  }
4176
#endif
4177
#if defined(HAS_ARGB4444TOARGBROW_MSA)
4178
  if (TestCpuFlag(kCpuHasMSA)) {
4179
    ARGB4444ToARGBRow = ARGB4444ToARGBRow_Any_MSA;
4180
    if (IS_ALIGNED(width, 16)) {
4181
      ARGB4444ToARGBRow = ARGB4444ToARGBRow_MSA;
4182
    }
4183
  }
4184
#endif
4185
#if defined(HAS_ARGB4444TOARGBROW_LSX)
4186
  if (TestCpuFlag(kCpuHasLSX)) {
4187
    ARGB4444ToARGBRow = ARGB4444ToARGBRow_Any_LSX;
4188
    if (IS_ALIGNED(width, 16)) {
4189
      ARGB4444ToARGBRow = ARGB4444ToARGBRow_LSX;
4190
    }
4191
  }
4192
#endif
4193
#if defined(HAS_ARGB4444TOARGBROW_LASX)
4194
  if (TestCpuFlag(kCpuHasLASX)) {
4195
    ARGB4444ToARGBRow = ARGB4444ToARGBRow_Any_LASX;
4196
    if (IS_ALIGNED(width, 32)) {
4197
      ARGB4444ToARGBRow = ARGB4444ToARGBRow_LASX;
4198
    }
4199
  }
4200
#endif
4201
4202
0
  for (y = 0; y < height; ++y) {
4203
0
    ARGB4444ToARGBRow(src_argb4444, dst_argb, width);
4204
0
    src_argb4444 += src_stride_argb4444;
4205
0
    dst_argb += dst_stride_argb;
4206
0
  }
4207
0
  return 0;
4208
0
}
4209
4210
// Convert AR30 to ARGB.
4211
LIBYUV_API
4212
int AR30ToARGB(const uint8_t* src_ar30,
4213
               int src_stride_ar30,
4214
               uint8_t* dst_argb,
4215
               int dst_stride_argb,
4216
               int width,
4217
0
               int height) {
4218
0
  int y;
4219
0
  if (!src_ar30 || !dst_argb || width <= 0 || height == 0) {
4220
0
    return -1;
4221
0
  }
4222
  // Negative height means invert the image.
4223
0
  if (height < 0) {
4224
0
    height = -height;
4225
0
    src_ar30 = src_ar30 + (height - 1) * src_stride_ar30;
4226
0
    src_stride_ar30 = -src_stride_ar30;
4227
0
  }
4228
  // Coalesce rows.
4229
0
  if (src_stride_ar30 == width * 4 && dst_stride_argb == width * 4) {
4230
0
    width *= height;
4231
0
    height = 1;
4232
0
    src_stride_ar30 = dst_stride_argb = 0;
4233
0
  }
4234
0
  for (y = 0; y < height; ++y) {
4235
0
    AR30ToARGBRow_C(src_ar30, dst_argb, width);
4236
0
    src_ar30 += src_stride_ar30;
4237
0
    dst_argb += dst_stride_argb;
4238
0
  }
4239
0
  return 0;
4240
0
}
4241
4242
// Convert AR30 to ABGR.
4243
LIBYUV_API
4244
int AR30ToABGR(const uint8_t* src_ar30,
4245
               int src_stride_ar30,
4246
               uint8_t* dst_abgr,
4247
               int dst_stride_abgr,
4248
               int width,
4249
0
               int height) {
4250
0
  int y;
4251
0
  if (!src_ar30 || !dst_abgr || width <= 0 || height == 0) {
4252
0
    return -1;
4253
0
  }
4254
  // Negative height means invert the image.
4255
0
  if (height < 0) {
4256
0
    height = -height;
4257
0
    src_ar30 = src_ar30 + (height - 1) * src_stride_ar30;
4258
0
    src_stride_ar30 = -src_stride_ar30;
4259
0
  }
4260
  // Coalesce rows.
4261
0
  if (src_stride_ar30 == width * 4 && dst_stride_abgr == width * 4) {
4262
0
    width *= height;
4263
0
    height = 1;
4264
0
    src_stride_ar30 = dst_stride_abgr = 0;
4265
0
  }
4266
0
  for (y = 0; y < height; ++y) {
4267
0
    AR30ToABGRRow_C(src_ar30, dst_abgr, width);
4268
0
    src_ar30 += src_stride_ar30;
4269
0
    dst_abgr += dst_stride_abgr;
4270
0
  }
4271
0
  return 0;
4272
0
}
4273
4274
// Convert AR30 to AB30.
4275
LIBYUV_API
4276
int AR30ToAB30(const uint8_t* src_ar30,
4277
               int src_stride_ar30,
4278
               uint8_t* dst_ab30,
4279
               int dst_stride_ab30,
4280
               int width,
4281
0
               int height) {
4282
0
  int y;
4283
0
  if (!src_ar30 || !dst_ab30 || width <= 0 || height == 0) {
4284
0
    return -1;
4285
0
  }
4286
  // Negative height means invert the image.
4287
0
  if (height < 0) {
4288
0
    height = -height;
4289
0
    src_ar30 = src_ar30 + (height - 1) * src_stride_ar30;
4290
0
    src_stride_ar30 = -src_stride_ar30;
4291
0
  }
4292
  // Coalesce rows.
4293
0
  if (src_stride_ar30 == width * 4 && dst_stride_ab30 == width * 4) {
4294
0
    width *= height;
4295
0
    height = 1;
4296
0
    src_stride_ar30 = dst_stride_ab30 = 0;
4297
0
  }
4298
0
  for (y = 0; y < height; ++y) {
4299
0
    AR30ToAB30Row_C(src_ar30, dst_ab30, width);
4300
0
    src_ar30 += src_stride_ar30;
4301
0
    dst_ab30 += dst_stride_ab30;
4302
0
  }
4303
0
  return 0;
4304
0
}
4305
4306
// Convert AR64 to ARGB.
4307
LIBYUV_API
4308
int AR64ToARGB(const uint16_t* src_ar64,
4309
               int src_stride_ar64,
4310
               uint8_t* dst_argb,
4311
               int dst_stride_argb,
4312
               int width,
4313
0
               int height) {
4314
0
  int y;
4315
0
  void (*AR64ToARGBRow)(const uint16_t* src_ar64, uint8_t* dst_argb,
4316
0
                        int width) = AR64ToARGBRow_C;
4317
0
  if (!src_ar64 || !dst_argb || width <= 0 || height == 0) {
4318
0
    return -1;
4319
0
  }
4320
  // Negative height means invert the image.
4321
0
  if (height < 0) {
4322
0
    height = -height;
4323
0
    src_ar64 = src_ar64 + (height - 1) * src_stride_ar64;
4324
0
    src_stride_ar64 = -src_stride_ar64;
4325
0
  }
4326
  // Coalesce rows.
4327
0
  if (src_stride_ar64 == width * 4 && dst_stride_argb == width * 4) {
4328
0
    width *= height;
4329
0
    height = 1;
4330
0
    src_stride_ar64 = dst_stride_argb = 0;
4331
0
  }
4332
0
#if defined(HAS_AR64TOARGBROW_SSSE3)
4333
0
  if (TestCpuFlag(kCpuHasSSSE3)) {
4334
0
    AR64ToARGBRow = AR64ToARGBRow_Any_SSSE3;
4335
0
    if (IS_ALIGNED(width, 4)) {
4336
0
      AR64ToARGBRow = AR64ToARGBRow_SSSE3;
4337
0
    }
4338
0
  }
4339
0
#endif
4340
0
#if defined(HAS_AR64TOARGBROW_AVX2)
4341
0
  if (TestCpuFlag(kCpuHasAVX2)) {
4342
0
    AR64ToARGBRow = AR64ToARGBRow_Any_AVX2;
4343
0
    if (IS_ALIGNED(width, 8)) {
4344
0
      AR64ToARGBRow = AR64ToARGBRow_AVX2;
4345
0
    }
4346
0
  }
4347
0
#endif
4348
#if defined(HAS_AR64TOARGBROW_NEON)
4349
  if (TestCpuFlag(kCpuHasNEON)) {
4350
    AR64ToARGBRow = AR64ToARGBRow_Any_NEON;
4351
    if (IS_ALIGNED(width, 8)) {
4352
      AR64ToARGBRow = AR64ToARGBRow_NEON;
4353
    }
4354
  }
4355
#endif
4356
#if defined(HAS_AR64TOARGBROW_RVV)
4357
  if (TestCpuFlag(kCpuHasRVV)) {
4358
    AR64ToARGBRow = AR64ToARGBRow_RVV;
4359
  }
4360
#endif
4361
4362
0
  for (y = 0; y < height; ++y) {
4363
0
    AR64ToARGBRow(src_ar64, dst_argb, width);
4364
0
    src_ar64 += src_stride_ar64;
4365
0
    dst_argb += dst_stride_argb;
4366
0
  }
4367
0
  return 0;
4368
0
}
4369
4370
// Convert AB64 to ARGB.
4371
LIBYUV_API
4372
int AB64ToARGB(const uint16_t* src_ab64,
4373
               int src_stride_ab64,
4374
               uint8_t* dst_argb,
4375
               int dst_stride_argb,
4376
               int width,
4377
0
               int height) {
4378
0
  int y;
4379
0
  void (*AB64ToARGBRow)(const uint16_t* src_ar64, uint8_t* dst_argb,
4380
0
                        int width) = AB64ToARGBRow_C;
4381
0
  if (!src_ab64 || !dst_argb || width <= 0 || height == 0) {
4382
0
    return -1;
4383
0
  }
4384
  // Negative height means invert the image.
4385
0
  if (height < 0) {
4386
0
    height = -height;
4387
0
    src_ab64 = src_ab64 + (height - 1) * src_stride_ab64;
4388
0
    src_stride_ab64 = -src_stride_ab64;
4389
0
  }
4390
  // Coalesce rows.
4391
0
  if (src_stride_ab64 == width * 4 && dst_stride_argb == width * 4) {
4392
0
    width *= height;
4393
0
    height = 1;
4394
0
    src_stride_ab64 = dst_stride_argb = 0;
4395
0
  }
4396
0
#if defined(HAS_AB64TOARGBROW_SSSE3)
4397
0
  if (TestCpuFlag(kCpuHasSSSE3)) {
4398
0
    AB64ToARGBRow = AB64ToARGBRow_Any_SSSE3;
4399
0
    if (IS_ALIGNED(width, 4)) {
4400
0
      AB64ToARGBRow = AB64ToARGBRow_SSSE3;
4401
0
    }
4402
0
  }
4403
0
#endif
4404
0
#if defined(HAS_AB64TOARGBROW_AVX2)
4405
0
  if (TestCpuFlag(kCpuHasAVX2)) {
4406
0
    AB64ToARGBRow = AB64ToARGBRow_Any_AVX2;
4407
0
    if (IS_ALIGNED(width, 8)) {
4408
0
      AB64ToARGBRow = AB64ToARGBRow_AVX2;
4409
0
    }
4410
0
  }
4411
0
#endif
4412
#if defined(HAS_AB64TOARGBROW_NEON)
4413
  if (TestCpuFlag(kCpuHasNEON)) {
4414
    AB64ToARGBRow = AB64ToARGBRow_Any_NEON;
4415
    if (IS_ALIGNED(width, 8)) {
4416
      AB64ToARGBRow = AB64ToARGBRow_NEON;
4417
    }
4418
  }
4419
#endif
4420
#if defined(HAS_AB64TOARGBROW_RVV)
4421
  if (TestCpuFlag(kCpuHasRVV)) {
4422
    AB64ToARGBRow = AB64ToARGBRow_RVV;
4423
  }
4424
#endif
4425
4426
0
  for (y = 0; y < height; ++y) {
4427
0
    AB64ToARGBRow(src_ab64, dst_argb, width);
4428
0
    src_ab64 += src_stride_ab64;
4429
0
    dst_argb += dst_stride_argb;
4430
0
  }
4431
0
  return 0;
4432
0
}
4433
4434
// Convert NV12 to ARGB with matrix.
4435
LIBYUV_API
4436
int NV12ToARGBMatrix(const uint8_t* src_y,
4437
                     int src_stride_y,
4438
                     const uint8_t* src_uv,
4439
                     int src_stride_uv,
4440
                     uint8_t* dst_argb,
4441
                     int dst_stride_argb,
4442
                     const struct YuvConstants* yuvconstants,
4443
                     int width,
4444
0
                     int height) {
4445
0
  int y;
4446
0
  void (*NV12ToARGBRow)(
4447
0
      const uint8_t* y_buf, const uint8_t* uv_buf, uint8_t* rgb_buf,
4448
0
      const struct YuvConstants* yuvconstants, int width) = NV12ToARGBRow_C;
4449
0
  assert(yuvconstants);
4450
0
  if (!src_y || !src_uv || !dst_argb || width <= 0 || height == 0) {
4451
0
    return -1;
4452
0
  }
4453
  // Negative height means invert the image.
4454
0
  if (height < 0) {
4455
0
    height = -height;
4456
0
    dst_argb = dst_argb + (height - 1) * dst_stride_argb;
4457
0
    dst_stride_argb = -dst_stride_argb;
4458
0
  }
4459
0
#if defined(HAS_NV12TOARGBROW_SSSE3)
4460
0
  if (TestCpuFlag(kCpuHasSSSE3)) {
4461
0
    NV12ToARGBRow = NV12ToARGBRow_Any_SSSE3;
4462
0
    if (IS_ALIGNED(width, 8)) {
4463
0
      NV12ToARGBRow = NV12ToARGBRow_SSSE3;
4464
0
    }
4465
0
  }
4466
0
#endif
4467
0
#if defined(HAS_NV12TOARGBROW_AVX2)
4468
0
  if (TestCpuFlag(kCpuHasAVX2)) {
4469
0
    NV12ToARGBRow = NV12ToARGBRow_Any_AVX2;
4470
0
    if (IS_ALIGNED(width, 16)) {
4471
0
      NV12ToARGBRow = NV12ToARGBRow_AVX2;
4472
0
    }
4473
0
  }
4474
0
#endif
4475
#if defined(HAS_NV12TOARGBROW_NEON)
4476
  if (TestCpuFlag(kCpuHasNEON)) {
4477
    NV12ToARGBRow = NV12ToARGBRow_Any_NEON;
4478
    if (IS_ALIGNED(width, 8)) {
4479
      NV12ToARGBRow = NV12ToARGBRow_NEON;
4480
    }
4481
  }
4482
#endif
4483
#if defined(HAS_NV12TOARGBROW_SVE2)
4484
  if (TestCpuFlag(kCpuHasSVE2)) {
4485
    NV12ToARGBRow = NV12ToARGBRow_SVE2;
4486
  }
4487
#endif
4488
#if defined(HAS_NV12TOARGBROW_SME)
4489
  if (TestCpuFlag(kCpuHasSME)) {
4490
    NV12ToARGBRow = NV12ToARGBRow_SME;
4491
  }
4492
#endif
4493
#if defined(HAS_NV12TOARGBROW_MSA)
4494
  if (TestCpuFlag(kCpuHasMSA)) {
4495
    NV12ToARGBRow = NV12ToARGBRow_Any_MSA;
4496
    if (IS_ALIGNED(width, 8)) {
4497
      NV12ToARGBRow = NV12ToARGBRow_MSA;
4498
    }
4499
  }
4500
#endif
4501
#if defined(HAS_NV12TOARGBROW_LSX)
4502
  if (TestCpuFlag(kCpuHasLSX)) {
4503
    NV12ToARGBRow = NV12ToARGBRow_Any_LSX;
4504
    if (IS_ALIGNED(width, 8)) {
4505
      NV12ToARGBRow = NV12ToARGBRow_LSX;
4506
    }
4507
  }
4508
#endif
4509
#if defined(HAS_NV12TOARGBROW_LASX)
4510
  if (TestCpuFlag(kCpuHasLASX)) {
4511
    NV12ToARGBRow = NV12ToARGBRow_Any_LASX;
4512
    if (IS_ALIGNED(width, 16)) {
4513
      NV12ToARGBRow = NV12ToARGBRow_LASX;
4514
    }
4515
  }
4516
#endif
4517
#if defined(HAS_NV12TOARGBROW_RVV)
4518
  if (TestCpuFlag(kCpuHasRVV)) {
4519
    NV12ToARGBRow = NV12ToARGBRow_RVV;
4520
  }
4521
#endif
4522
4523
0
  for (y = 0; y < height; ++y) {
4524
0
    NV12ToARGBRow(src_y, src_uv, dst_argb, yuvconstants, width);
4525
0
    dst_argb += dst_stride_argb;
4526
0
    src_y += src_stride_y;
4527
0
    if (y & 1) {
4528
0
      src_uv += src_stride_uv;
4529
0
    }
4530
0
  }
4531
0
  return 0;
4532
0
}
4533
4534
// Convert NV21 to ARGB with matrix.
4535
LIBYUV_API
4536
int NV21ToARGBMatrix(const uint8_t* src_y,
4537
                     int src_stride_y,
4538
                     const uint8_t* src_vu,
4539
                     int src_stride_vu,
4540
                     uint8_t* dst_argb,
4541
                     int dst_stride_argb,
4542
                     const struct YuvConstants* yuvconstants,
4543
                     int width,
4544
0
                     int height) {
4545
0
  int y;
4546
0
  void (*NV21ToARGBRow)(
4547
0
      const uint8_t* y_buf, const uint8_t* uv_buf, uint8_t* rgb_buf,
4548
0
      const struct YuvConstants* yuvconstants, int width) = NV21ToARGBRow_C;
4549
0
  assert(yuvconstants);
4550
0
  if (!src_y || !src_vu || !dst_argb || width <= 0 || height == 0) {
4551
0
    return -1;
4552
0
  }
4553
  // Negative height means invert the image.
4554
0
  if (height < 0) {
4555
0
    height = -height;
4556
0
    dst_argb = dst_argb + (height - 1) * dst_stride_argb;
4557
0
    dst_stride_argb = -dst_stride_argb;
4558
0
  }
4559
0
#if defined(HAS_NV21TOARGBROW_SSSE3)
4560
0
  if (TestCpuFlag(kCpuHasSSSE3)) {
4561
0
    NV21ToARGBRow = NV21ToARGBRow_Any_SSSE3;
4562
0
    if (IS_ALIGNED(width, 8)) {
4563
0
      NV21ToARGBRow = NV21ToARGBRow_SSSE3;
4564
0
    }
4565
0
  }
4566
0
#endif
4567
0
#if defined(HAS_NV21TOARGBROW_AVX2)
4568
0
  if (TestCpuFlag(kCpuHasAVX2)) {
4569
0
    NV21ToARGBRow = NV21ToARGBRow_Any_AVX2;
4570
0
    if (IS_ALIGNED(width, 16)) {
4571
0
      NV21ToARGBRow = NV21ToARGBRow_AVX2;
4572
0
    }
4573
0
  }
4574
0
#endif
4575
#if defined(HAS_NV21TOARGBROW_NEON)
4576
  if (TestCpuFlag(kCpuHasNEON)) {
4577
    NV21ToARGBRow = NV21ToARGBRow_Any_NEON;
4578
    if (IS_ALIGNED(width, 8)) {
4579
      NV21ToARGBRow = NV21ToARGBRow_NEON;
4580
    }
4581
  }
4582
#endif
4583
#if defined(HAS_NV21TOARGBROW_SVE2)
4584
  if (TestCpuFlag(kCpuHasSVE2)) {
4585
    NV21ToARGBRow = NV21ToARGBRow_SVE2;
4586
  }
4587
#endif
4588
#if defined(HAS_NV21TOARGBROW_SME)
4589
  if (TestCpuFlag(kCpuHasSME)) {
4590
    NV21ToARGBRow = NV21ToARGBRow_SME;
4591
  }
4592
#endif
4593
#if defined(HAS_NV21TOARGBROW_MSA)
4594
  if (TestCpuFlag(kCpuHasMSA)) {
4595
    NV21ToARGBRow = NV21ToARGBRow_Any_MSA;
4596
    if (IS_ALIGNED(width, 8)) {
4597
      NV21ToARGBRow = NV21ToARGBRow_MSA;
4598
    }
4599
  }
4600
#endif
4601
#if defined(HAS_NV21TOARGBROW_LSX)
4602
  if (TestCpuFlag(kCpuHasLSX)) {
4603
    NV21ToARGBRow = NV21ToARGBRow_Any_LSX;
4604
    if (IS_ALIGNED(width, 8)) {
4605
      NV21ToARGBRow = NV21ToARGBRow_LSX;
4606
    }
4607
  }
4608
#endif
4609
#if defined(HAS_NV21TOARGBROW_LASX)
4610
  if (TestCpuFlag(kCpuHasLASX)) {
4611
    NV21ToARGBRow = NV21ToARGBRow_Any_LASX;
4612
    if (IS_ALIGNED(width, 16)) {
4613
      NV21ToARGBRow = NV21ToARGBRow_LASX;
4614
    }
4615
  }
4616
#endif
4617
#if defined(HAS_NV21TOARGBROW_RVV)
4618
  if (TestCpuFlag(kCpuHasRVV)) {
4619
    NV21ToARGBRow = NV21ToARGBRow_RVV;
4620
  }
4621
#endif
4622
4623
0
  for (y = 0; y < height; ++y) {
4624
0
    NV21ToARGBRow(src_y, src_vu, dst_argb, yuvconstants, width);
4625
0
    dst_argb += dst_stride_argb;
4626
0
    src_y += src_stride_y;
4627
0
    if (y & 1) {
4628
0
      src_vu += src_stride_vu;
4629
0
    }
4630
0
  }
4631
0
  return 0;
4632
0
}
4633
4634
// Convert NV12 to ARGB.
4635
LIBYUV_API
4636
int NV12ToARGB(const uint8_t* src_y,
4637
               int src_stride_y,
4638
               const uint8_t* src_uv,
4639
               int src_stride_uv,
4640
               uint8_t* dst_argb,
4641
               int dst_stride_argb,
4642
               int width,
4643
0
               int height) {
4644
0
  return NV12ToARGBMatrix(src_y, src_stride_y, src_uv, src_stride_uv, dst_argb,
4645
0
                          dst_stride_argb, &kYuvI601Constants, width, height);
4646
0
}
4647
4648
// Convert NV21 to ARGB.
4649
LIBYUV_API
4650
int NV21ToARGB(const uint8_t* src_y,
4651
               int src_stride_y,
4652
               const uint8_t* src_vu,
4653
               int src_stride_vu,
4654
               uint8_t* dst_argb,
4655
               int dst_stride_argb,
4656
               int width,
4657
0
               int height) {
4658
0
  return NV21ToARGBMatrix(src_y, src_stride_y, src_vu, src_stride_vu, dst_argb,
4659
0
                          dst_stride_argb, &kYuvI601Constants, width, height);
4660
0
}
4661
4662
// Convert NV12 to ABGR.
4663
// To output ABGR instead of ARGB swap the UV and use a mirrored yuv matrix.
4664
// To swap the UV use NV12 instead of NV21.LIBYUV_API
4665
LIBYUV_API
4666
int NV12ToABGR(const uint8_t* src_y,
4667
               int src_stride_y,
4668
               const uint8_t* src_uv,
4669
               int src_stride_uv,
4670
               uint8_t* dst_abgr,
4671
               int dst_stride_abgr,
4672
               int width,
4673
0
               int height) {
4674
0
  return NV21ToARGBMatrix(src_y, src_stride_y, src_uv, src_stride_uv, dst_abgr,
4675
0
                          dst_stride_abgr, &kYvuI601Constants, width, height);
4676
0
}
4677
4678
// Convert NV21 to ABGR.
4679
LIBYUV_API
4680
int NV21ToABGR(const uint8_t* src_y,
4681
               int src_stride_y,
4682
               const uint8_t* src_vu,
4683
               int src_stride_vu,
4684
               uint8_t* dst_abgr,
4685
               int dst_stride_abgr,
4686
               int width,
4687
0
               int height) {
4688
0
  return NV12ToARGBMatrix(src_y, src_stride_y, src_vu, src_stride_vu, dst_abgr,
4689
0
                          dst_stride_abgr, &kYvuI601Constants, width, height);
4690
0
}
4691
4692
// TODO(fbarchard): Consider SSSE3 2 step conversion.
4693
// Convert NV12 to RGB24 with matrix.
4694
LIBYUV_API
4695
int NV12ToRGB24Matrix(const uint8_t* src_y,
4696
                      int src_stride_y,
4697
                      const uint8_t* src_uv,
4698
                      int src_stride_uv,
4699
                      uint8_t* dst_rgb24,
4700
                      int dst_stride_rgb24,
4701
                      const struct YuvConstants* yuvconstants,
4702
                      int width,
4703
0
                      int height) {
4704
0
  int y;
4705
0
  void (*NV12ToRGB24Row)(
4706
0
      const uint8_t* y_buf, const uint8_t* uv_buf, uint8_t* rgb_buf,
4707
0
      const struct YuvConstants* yuvconstants, int width) = NV12ToRGB24Row_C;
4708
0
  assert(yuvconstants);
4709
0
  if (!src_y || !src_uv || !dst_rgb24 || width <= 0 || height == 0) {
4710
0
    return -1;
4711
0
  }
4712
  // Negative height means invert the image.
4713
0
  if (height < 0) {
4714
0
    height = -height;
4715
0
    dst_rgb24 = dst_rgb24 + (height - 1) * dst_stride_rgb24;
4716
0
    dst_stride_rgb24 = -dst_stride_rgb24;
4717
0
  }
4718
#if defined(HAS_NV12TORGB24ROW_NEON)
4719
  if (TestCpuFlag(kCpuHasNEON)) {
4720
    NV12ToRGB24Row = NV12ToRGB24Row_Any_NEON;
4721
    if (IS_ALIGNED(width, 8)) {
4722
      NV12ToRGB24Row = NV12ToRGB24Row_NEON;
4723
    }
4724
  }
4725
#endif
4726
#if defined(HAS_NV12TORGB24ROW_SVE2)
4727
  if (TestCpuFlag(kCpuHasSVE2)) {
4728
    NV12ToRGB24Row = NV12ToRGB24Row_SVE2;
4729
  }
4730
#endif
4731
#if defined(HAS_NV12TORGB24ROW_SME)
4732
  if (TestCpuFlag(kCpuHasSME)) {
4733
    NV12ToRGB24Row = NV12ToRGB24Row_SME;
4734
  }
4735
#endif
4736
0
#if defined(HAS_NV12TORGB24ROW_SSSE3)
4737
0
  if (TestCpuFlag(kCpuHasSSSE3)) {
4738
0
    NV12ToRGB24Row = NV12ToRGB24Row_Any_SSSE3;
4739
0
    if (IS_ALIGNED(width, 16)) {
4740
0
      NV12ToRGB24Row = NV12ToRGB24Row_SSSE3;
4741
0
    }
4742
0
  }
4743
0
#endif
4744
0
#if defined(HAS_NV12TORGB24ROW_AVX2)
4745
0
  if (TestCpuFlag(kCpuHasAVX2)) {
4746
0
    NV12ToRGB24Row = NV12ToRGB24Row_Any_AVX2;
4747
0
    if (IS_ALIGNED(width, 32)) {
4748
0
      NV12ToRGB24Row = NV12ToRGB24Row_AVX2;
4749
0
    }
4750
0
  }
4751
0
#endif
4752
#if defined(HAS_NV12TORGB24ROW_RVV)
4753
  if (TestCpuFlag(kCpuHasRVV)) {
4754
    NV12ToRGB24Row = NV12ToRGB24Row_RVV;
4755
  }
4756
#endif
4757
4758
0
  for (y = 0; y < height; ++y) {
4759
0
    NV12ToRGB24Row(src_y, src_uv, dst_rgb24, yuvconstants, width);
4760
0
    dst_rgb24 += dst_stride_rgb24;
4761
0
    src_y += src_stride_y;
4762
0
    if (y & 1) {
4763
0
      src_uv += src_stride_uv;
4764
0
    }
4765
0
  }
4766
0
  return 0;
4767
0
}
4768
4769
// Convert NV21 to RGB24 with matrix.
4770
LIBYUV_API
4771
int NV21ToRGB24Matrix(const uint8_t* src_y,
4772
                      int src_stride_y,
4773
                      const uint8_t* src_vu,
4774
                      int src_stride_vu,
4775
                      uint8_t* dst_rgb24,
4776
                      int dst_stride_rgb24,
4777
                      const struct YuvConstants* yuvconstants,
4778
                      int width,
4779
0
                      int height) {
4780
0
  int y;
4781
0
  void (*NV21ToRGB24Row)(
4782
0
      const uint8_t* y_buf, const uint8_t* uv_buf, uint8_t* rgb_buf,
4783
0
      const struct YuvConstants* yuvconstants, int width) = NV21ToRGB24Row_C;
4784
0
  assert(yuvconstants);
4785
0
  if (!src_y || !src_vu || !dst_rgb24 || width <= 0 || height == 0) {
4786
0
    return -1;
4787
0
  }
4788
  // Negative height means invert the image.
4789
0
  if (height < 0) {
4790
0
    height = -height;
4791
0
    dst_rgb24 = dst_rgb24 + (height - 1) * dst_stride_rgb24;
4792
0
    dst_stride_rgb24 = -dst_stride_rgb24;
4793
0
  }
4794
#if defined(HAS_NV21TORGB24ROW_NEON)
4795
  if (TestCpuFlag(kCpuHasNEON)) {
4796
    NV21ToRGB24Row = NV21ToRGB24Row_Any_NEON;
4797
    if (IS_ALIGNED(width, 8)) {
4798
      NV21ToRGB24Row = NV21ToRGB24Row_NEON;
4799
    }
4800
  }
4801
#endif
4802
#if defined(HAS_NV21TORGB24ROW_SVE2)
4803
  if (TestCpuFlag(kCpuHasSVE2)) {
4804
    NV21ToRGB24Row = NV21ToRGB24Row_SVE2;
4805
  }
4806
#endif
4807
#if defined(HAS_NV21TORGB24ROW_SME)
4808
  if (TestCpuFlag(kCpuHasSME)) {
4809
    NV21ToRGB24Row = NV21ToRGB24Row_SME;
4810
  }
4811
#endif
4812
0
#if defined(HAS_NV21TORGB24ROW_SSSE3)
4813
0
  if (TestCpuFlag(kCpuHasSSSE3)) {
4814
0
    NV21ToRGB24Row = NV21ToRGB24Row_Any_SSSE3;
4815
0
    if (IS_ALIGNED(width, 16)) {
4816
0
      NV21ToRGB24Row = NV21ToRGB24Row_SSSE3;
4817
0
    }
4818
0
  }
4819
0
#endif
4820
0
#if defined(HAS_NV21TORGB24ROW_AVX2)
4821
0
  if (TestCpuFlag(kCpuHasAVX2)) {
4822
0
    NV21ToRGB24Row = NV21ToRGB24Row_Any_AVX2;
4823
0
    if (IS_ALIGNED(width, 32)) {
4824
0
      NV21ToRGB24Row = NV21ToRGB24Row_AVX2;
4825
0
    }
4826
0
  }
4827
0
#endif
4828
#if defined(HAS_NV21TORGB24ROW_RVV)
4829
  if (TestCpuFlag(kCpuHasRVV)) {
4830
    NV21ToRGB24Row = NV21ToRGB24Row_RVV;
4831
  }
4832
#endif
4833
4834
0
  for (y = 0; y < height; ++y) {
4835
0
    NV21ToRGB24Row(src_y, src_vu, dst_rgb24, yuvconstants, width);
4836
0
    dst_rgb24 += dst_stride_rgb24;
4837
0
    src_y += src_stride_y;
4838
0
    if (y & 1) {
4839
0
      src_vu += src_stride_vu;
4840
0
    }
4841
0
  }
4842
0
  return 0;
4843
0
}
4844
4845
// Convert NV12 to RGB24.
4846
LIBYUV_API
4847
int NV12ToRGB24(const uint8_t* src_y,
4848
                int src_stride_y,
4849
                const uint8_t* src_uv,
4850
                int src_stride_uv,
4851
                uint8_t* dst_rgb24,
4852
                int dst_stride_rgb24,
4853
                int width,
4854
0
                int height) {
4855
0
  return NV12ToRGB24Matrix(src_y, src_stride_y, src_uv, src_stride_uv,
4856
0
                           dst_rgb24, dst_stride_rgb24, &kYuvI601Constants,
4857
0
                           width, height);
4858
0
}
4859
4860
// Convert NV21 to RGB24.
4861
LIBYUV_API
4862
int NV21ToRGB24(const uint8_t* src_y,
4863
                int src_stride_y,
4864
                const uint8_t* src_vu,
4865
                int src_stride_vu,
4866
                uint8_t* dst_rgb24,
4867
                int dst_stride_rgb24,
4868
                int width,
4869
0
                int height) {
4870
0
  return NV21ToRGB24Matrix(src_y, src_stride_y, src_vu, src_stride_vu,
4871
0
                           dst_rgb24, dst_stride_rgb24, &kYuvI601Constants,
4872
0
                           width, height);
4873
0
}
4874
4875
// Convert NV12 to RAW.
4876
LIBYUV_API
4877
int NV12ToRAW(const uint8_t* src_y,
4878
              int src_stride_y,
4879
              const uint8_t* src_uv,
4880
              int src_stride_uv,
4881
              uint8_t* dst_raw,
4882
              int dst_stride_raw,
4883
              int width,
4884
0
              int height) {
4885
0
  return NV21ToRGB24Matrix(src_y, src_stride_y, src_uv, src_stride_uv, dst_raw,
4886
0
                           dst_stride_raw, &kYvuI601Constants, width, height);
4887
0
}
4888
4889
// Convert NV21 to RAW.
4890
LIBYUV_API
4891
int NV21ToRAW(const uint8_t* src_y,
4892
              int src_stride_y,
4893
              const uint8_t* src_vu,
4894
              int src_stride_vu,
4895
              uint8_t* dst_raw,
4896
              int dst_stride_raw,
4897
              int width,
4898
0
              int height) {
4899
0
  return NV12ToRGB24Matrix(src_y, src_stride_y, src_vu, src_stride_vu, dst_raw,
4900
0
                           dst_stride_raw, &kYvuI601Constants, width, height);
4901
0
}
4902
4903
// Convert NV21 to YUV24
4904
int NV21ToYUV24(const uint8_t* src_y,
4905
                int src_stride_y,
4906
                const uint8_t* src_vu,
4907
                int src_stride_vu,
4908
                uint8_t* dst_yuv24,
4909
                int dst_stride_yuv24,
4910
                int width,
4911
0
                int height) {
4912
0
  int y;
4913
0
  void (*NV21ToYUV24Row)(const uint8_t* src_y, const uint8_t* src_vu,
4914
0
                         uint8_t* dst_yuv24, int width) = NV21ToYUV24Row_C;
4915
0
  if (!src_y || !src_vu || !dst_yuv24 || width <= 0 || height == 0) {
4916
0
    return -1;
4917
0
  }
4918
  // Negative height means invert the image.
4919
0
  if (height < 0) {
4920
0
    height = -height;
4921
0
    dst_yuv24 = dst_yuv24 + (height - 1) * dst_stride_yuv24;
4922
0
    dst_stride_yuv24 = -dst_stride_yuv24;
4923
0
  }
4924
#if defined(HAS_NV21TOYUV24ROW_NEON)
4925
  if (TestCpuFlag(kCpuHasNEON)) {
4926
    NV21ToYUV24Row = NV21ToYUV24Row_Any_NEON;
4927
    if (IS_ALIGNED(width, 16)) {
4928
      NV21ToYUV24Row = NV21ToYUV24Row_NEON;
4929
    }
4930
  }
4931
#endif
4932
0
#if defined(HAS_NV21TOYUV24ROW_SSSE3)
4933
0
  if (TestCpuFlag(kCpuHasSSSE3)) {
4934
0
    NV21ToYUV24Row = NV21ToYUV24Row_Any_SSSE3;
4935
0
    if (IS_ALIGNED(width, 16)) {
4936
0
      NV21ToYUV24Row = NV21ToYUV24Row_SSSE3;
4937
0
    }
4938
0
  }
4939
0
#endif
4940
0
#if defined(HAS_NV21TOYUV24ROW_AVX2)
4941
0
  if (TestCpuFlag(kCpuHasAVX2)) {
4942
0
    NV21ToYUV24Row = NV21ToYUV24Row_Any_AVX2;
4943
0
    if (IS_ALIGNED(width, 32)) {
4944
0
      NV21ToYUV24Row = NV21ToYUV24Row_AVX2;
4945
0
    }
4946
0
  }
4947
0
#endif
4948
0
  for (y = 0; y < height; ++y) {
4949
0
    NV21ToYUV24Row(src_y, src_vu, dst_yuv24, width);
4950
0
    dst_yuv24 += dst_stride_yuv24;
4951
0
    src_y += src_stride_y;
4952
0
    if (y & 1) {
4953
0
      src_vu += src_stride_vu;
4954
0
    }
4955
0
  }
4956
0
  return 0;
4957
0
}
4958
4959
// Convert YUY2 to ARGB with matrix.
4960
LIBYUV_API
4961
int YUY2ToARGBMatrix(const uint8_t* src_yuy2,
4962
                     int src_stride_yuy2,
4963
                     uint8_t* dst_argb,
4964
                     int dst_stride_argb,
4965
                     const struct YuvConstants* yuvconstants,
4966
                     int width,
4967
0
                     int height) {
4968
0
  int y;
4969
0
  void (*YUY2ToARGBRow)(const uint8_t* src_yuy2, uint8_t* dst_argb,
4970
0
                        const struct YuvConstants* yuvconstants, int width) =
4971
0
      YUY2ToARGBRow_C;
4972
0
  if (!src_yuy2 || !dst_argb || width <= 0 || height == 0) {
4973
0
    return -1;
4974
0
  }
4975
  // Negative height means invert the image.
4976
0
  if (height < 0) {
4977
0
    height = -height;
4978
0
    src_yuy2 = src_yuy2 + (height - 1) * src_stride_yuy2;
4979
0
    src_stride_yuy2 = -src_stride_yuy2;
4980
0
  }
4981
  // Coalesce rows.
4982
0
  if (src_stride_yuy2 == width * 2 && dst_stride_argb == width * 4) {
4983
0
    width *= height;
4984
0
    height = 1;
4985
0
    src_stride_yuy2 = dst_stride_argb = 0;
4986
0
  }
4987
0
#if defined(HAS_YUY2TOARGBROW_SSSE3)
4988
0
  if (TestCpuFlag(kCpuHasSSSE3)) {
4989
0
    YUY2ToARGBRow = YUY2ToARGBRow_Any_SSSE3;
4990
0
    if (IS_ALIGNED(width, 16)) {
4991
0
      YUY2ToARGBRow = YUY2ToARGBRow_SSSE3;
4992
0
    }
4993
0
  }
4994
0
#endif
4995
0
#if defined(HAS_YUY2TOARGBROW_AVX2)
4996
0
  if (TestCpuFlag(kCpuHasAVX2)) {
4997
0
    YUY2ToARGBRow = YUY2ToARGBRow_Any_AVX2;
4998
0
    if (IS_ALIGNED(width, 32)) {
4999
0
      YUY2ToARGBRow = YUY2ToARGBRow_AVX2;
5000
0
    }
5001
0
  }
5002
0
#endif
5003
#if defined(HAS_YUY2TOARGBROW_NEON)
5004
  if (TestCpuFlag(kCpuHasNEON)) {
5005
    YUY2ToARGBRow = YUY2ToARGBRow_Any_NEON;
5006
    if (IS_ALIGNED(width, 8)) {
5007
      YUY2ToARGBRow = YUY2ToARGBRow_NEON;
5008
    }
5009
  }
5010
#endif
5011
#if defined(HAS_YUY2TOARGBROW_SVE2)
5012
  if (TestCpuFlag(kCpuHasSVE2)) {
5013
    YUY2ToARGBRow = YUY2ToARGBRow_SVE2;
5014
  }
5015
#endif
5016
#if defined(HAS_YUY2TOARGBROW_SME)
5017
  if (TestCpuFlag(kCpuHasSME)) {
5018
    YUY2ToARGBRow = YUY2ToARGBRow_SME;
5019
  }
5020
#endif
5021
#if defined(HAS_YUY2TOARGBROW_MSA)
5022
  if (TestCpuFlag(kCpuHasMSA)) {
5023
    YUY2ToARGBRow = YUY2ToARGBRow_Any_MSA;
5024
    if (IS_ALIGNED(width, 8)) {
5025
      YUY2ToARGBRow = YUY2ToARGBRow_MSA;
5026
    }
5027
  }
5028
#endif
5029
#if defined(HAS_YUY2TOARGBROW_LSX)
5030
  if (TestCpuFlag(kCpuHasLSX)) {
5031
    YUY2ToARGBRow = YUY2ToARGBRow_Any_LSX;
5032
    if (IS_ALIGNED(width, 8)) {
5033
      YUY2ToARGBRow = YUY2ToARGBRow_LSX;
5034
    }
5035
  }
5036
#endif
5037
0
  for (y = 0; y < height; ++y) {
5038
0
    YUY2ToARGBRow(src_yuy2, dst_argb, yuvconstants, width);
5039
0
    src_yuy2 += src_stride_yuy2;
5040
0
    dst_argb += dst_stride_argb;
5041
0
  }
5042
0
  return 0;
5043
0
}
5044
5045
// Convert YUY2 to ARGB.
5046
LIBYUV_API
5047
int YUY2ToARGB(const uint8_t* src_yuy2,
5048
               int src_stride_yuy2,
5049
               uint8_t* dst_argb,
5050
               int dst_stride_argb,
5051
               int width,
5052
0
               int height) {
5053
0
  return YUY2ToARGBMatrix(src_yuy2, src_stride_yuy2, dst_argb, dst_stride_argb,
5054
0
                          &kYuvI601Constants, width, height);
5055
0
}
5056
5057
// Convert UYVY to ARGB with matrix.
5058
LIBYUV_API
5059
int UYVYToARGBMatrix(const uint8_t* src_uyvy,
5060
                     int src_stride_uyvy,
5061
                     uint8_t* dst_argb,
5062
                     int dst_stride_argb,
5063
                     const struct YuvConstants* yuvconstants,
5064
                     int width,
5065
0
                     int height) {
5066
0
  int y;
5067
0
  void (*UYVYToARGBRow)(const uint8_t* src_uyvy, uint8_t* dst_argb,
5068
0
                        const struct YuvConstants* yuvconstants, int width) =
5069
0
      UYVYToARGBRow_C;
5070
0
  if (!src_uyvy || !dst_argb || width <= 0 || height == 0) {
5071
0
    return -1;
5072
0
  }
5073
  // Negative height means invert the image.
5074
0
  if (height < 0) {
5075
0
    height = -height;
5076
0
    src_uyvy = src_uyvy + (height - 1) * src_stride_uyvy;
5077
0
    src_stride_uyvy = -src_stride_uyvy;
5078
0
  }
5079
  // Coalesce rows.
5080
0
  if (src_stride_uyvy == width * 2 && dst_stride_argb == width * 4) {
5081
0
    width *= height;
5082
0
    height = 1;
5083
0
    src_stride_uyvy = dst_stride_argb = 0;
5084
0
  }
5085
0
#if defined(HAS_UYVYTOARGBROW_SSSE3)
5086
0
  if (TestCpuFlag(kCpuHasSSSE3)) {
5087
0
    UYVYToARGBRow = UYVYToARGBRow_Any_SSSE3;
5088
0
    if (IS_ALIGNED(width, 16)) {
5089
0
      UYVYToARGBRow = UYVYToARGBRow_SSSE3;
5090
0
    }
5091
0
  }
5092
0
#endif
5093
0
#if defined(HAS_UYVYTOARGBROW_AVX2)
5094
0
  if (TestCpuFlag(kCpuHasAVX2)) {
5095
0
    UYVYToARGBRow = UYVYToARGBRow_Any_AVX2;
5096
0
    if (IS_ALIGNED(width, 32)) {
5097
0
      UYVYToARGBRow = UYVYToARGBRow_AVX2;
5098
0
    }
5099
0
  }
5100
0
#endif
5101
#if defined(HAS_UYVYTOARGBROW_NEON)
5102
  if (TestCpuFlag(kCpuHasNEON)) {
5103
    UYVYToARGBRow = UYVYToARGBRow_Any_NEON;
5104
    if (IS_ALIGNED(width, 8)) {
5105
      UYVYToARGBRow = UYVYToARGBRow_NEON;
5106
    }
5107
  }
5108
#endif
5109
#if defined(HAS_UYVYTOARGBROW_SVE2)
5110
  if (TestCpuFlag(kCpuHasSVE2)) {
5111
    UYVYToARGBRow = UYVYToARGBRow_SVE2;
5112
  }
5113
#endif
5114
#if defined(HAS_UYVYTOARGBROW_SME)
5115
  if (TestCpuFlag(kCpuHasSME)) {
5116
    UYVYToARGBRow = UYVYToARGBRow_SME;
5117
  }
5118
#endif
5119
#if defined(HAS_UYVYTOARGBROW_MSA)
5120
  if (TestCpuFlag(kCpuHasMSA)) {
5121
    UYVYToARGBRow = UYVYToARGBRow_Any_MSA;
5122
    if (IS_ALIGNED(width, 8)) {
5123
      UYVYToARGBRow = UYVYToARGBRow_MSA;
5124
    }
5125
  }
5126
#endif
5127
#if defined(HAS_UYVYTOARGBROW_LSX)
5128
  if (TestCpuFlag(kCpuHasLSX)) {
5129
    UYVYToARGBRow = UYVYToARGBRow_Any_LSX;
5130
    if (IS_ALIGNED(width, 8)) {
5131
      UYVYToARGBRow = UYVYToARGBRow_LSX;
5132
    }
5133
  }
5134
#endif
5135
0
  for (y = 0; y < height; ++y) {
5136
0
    UYVYToARGBRow(src_uyvy, dst_argb, yuvconstants, width);
5137
0
    src_uyvy += src_stride_uyvy;
5138
0
    dst_argb += dst_stride_argb;
5139
0
  }
5140
0
  return 0;
5141
0
}
5142
5143
// Convert UYVY to ARGB.
5144
LIBYUV_API
5145
int UYVYToARGB(const uint8_t* src_uyvy,
5146
               int src_stride_uyvy,
5147
               uint8_t* dst_argb,
5148
               int dst_stride_argb,
5149
               int width,
5150
0
               int height) {
5151
0
  return UYVYToARGBMatrix(src_uyvy, src_stride_uyvy, dst_argb, dst_stride_argb,
5152
0
                          &kYuvI601Constants, width, height);
5153
0
}
5154
5155
static void WeavePixels(const uint8_t* src_u,
5156
                        const uint8_t* src_v,
5157
                        int src_pixel_stride_uv,
5158
                        uint8_t* dst_uv,
5159
0
                        int width) {
5160
0
  int i;
5161
0
  for (i = 0; i < width; ++i) {
5162
0
    dst_uv[0] = *src_u;
5163
0
    dst_uv[1] = *src_v;
5164
0
    dst_uv += 2;
5165
0
    src_u += src_pixel_stride_uv;
5166
0
    src_v += src_pixel_stride_uv;
5167
0
  }
5168
0
}
5169
5170
// Convert Android420 to ARGB with matrix.
5171
LIBYUV_API
5172
int Android420ToARGBMatrix(const uint8_t* src_y,
5173
                           int src_stride_y,
5174
                           const uint8_t* src_u,
5175
                           int src_stride_u,
5176
                           const uint8_t* src_v,
5177
                           int src_stride_v,
5178
                           int src_pixel_stride_uv,
5179
                           uint8_t* dst_argb,
5180
                           int dst_stride_argb,
5181
                           const struct YuvConstants* yuvconstants,
5182
                           int width,
5183
0
                           int height) {
5184
0
  int y;
5185
0
  uint8_t* dst_uv;
5186
0
  const ptrdiff_t vu_off = src_v - src_u;
5187
0
  int halfwidth = (width + 1) >> 1;
5188
0
  int halfheight = (height + 1) >> 1;
5189
0
  assert(yuvconstants);
5190
0
  if (!src_y || !src_u || !src_v || !dst_argb || width <= 0 || height == 0) {
5191
0
    return -1;
5192
0
  }
5193
  // Negative height means invert the image.
5194
0
  if (height < 0) {
5195
0
    height = -height;
5196
0
    halfheight = (height + 1) >> 1;
5197
0
    dst_argb = dst_argb + (height - 1) * dst_stride_argb;
5198
0
    dst_stride_argb = -dst_stride_argb;
5199
0
  }
5200
5201
  // I420
5202
0
  if (src_pixel_stride_uv == 1) {
5203
0
    return I420ToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
5204
0
                            src_stride_v, dst_argb, dst_stride_argb,
5205
0
                            yuvconstants, width, height);
5206
    // NV21
5207
0
  }
5208
0
  if (src_pixel_stride_uv == 2 && vu_off == -1 &&
5209
0
      src_stride_u == src_stride_v) {
5210
0
    return NV21ToARGBMatrix(src_y, src_stride_y, src_v, src_stride_v, dst_argb,
5211
0
                            dst_stride_argb, yuvconstants, width, height);
5212
    // NV12
5213
0
  }
5214
0
  if (src_pixel_stride_uv == 2 && vu_off == 1 && src_stride_u == src_stride_v) {
5215
0
    return NV12ToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u, dst_argb,
5216
0
                            dst_stride_argb, yuvconstants, width, height);
5217
0
  }
5218
5219
  // General case fallback creates NV12
5220
0
  align_buffer_64(plane_uv, halfwidth * 2 * halfheight);
5221
0
  if (!plane_uv)
5222
0
    return 1;
5223
0
  dst_uv = plane_uv;
5224
0
  for (y = 0; y < halfheight; ++y) {
5225
0
    WeavePixels(src_u, src_v, src_pixel_stride_uv, dst_uv, halfwidth);
5226
0
    src_u += src_stride_u;
5227
0
    src_v += src_stride_v;
5228
0
    dst_uv += halfwidth * 2;
5229
0
  }
5230
0
  NV12ToARGBMatrix(src_y, src_stride_y, plane_uv, halfwidth * 2, dst_argb,
5231
0
                   dst_stride_argb, yuvconstants, width, height);
5232
0
  free_aligned_buffer_64(plane_uv);
5233
0
  return 0;
5234
0
}
5235
5236
// Convert Android420 to ARGB.
5237
LIBYUV_API
5238
int Android420ToARGB(const uint8_t* src_y,
5239
                     int src_stride_y,
5240
                     const uint8_t* src_u,
5241
                     int src_stride_u,
5242
                     const uint8_t* src_v,
5243
                     int src_stride_v,
5244
                     int src_pixel_stride_uv,
5245
                     uint8_t* dst_argb,
5246
                     int dst_stride_argb,
5247
                     int width,
5248
0
                     int height) {
5249
0
  return Android420ToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
5250
0
                                src_stride_v, src_pixel_stride_uv, dst_argb,
5251
0
                                dst_stride_argb, &kYuvI601Constants, width,
5252
0
                                height);
5253
0
}
5254
5255
// Convert Android420 to ABGR.
5256
LIBYUV_API
5257
int Android420ToABGR(const uint8_t* src_y,
5258
                     int src_stride_y,
5259
                     const uint8_t* src_u,
5260
                     int src_stride_u,
5261
                     const uint8_t* src_v,
5262
                     int src_stride_v,
5263
                     int src_pixel_stride_uv,
5264
                     uint8_t* dst_abgr,
5265
                     int dst_stride_abgr,
5266
                     int width,
5267
0
                     int height) {
5268
0
  return Android420ToARGBMatrix(src_y, src_stride_y, src_v, src_stride_v, src_u,
5269
0
                                src_stride_u, src_pixel_stride_uv, dst_abgr,
5270
0
                                dst_stride_abgr, &kYvuI601Constants, width,
5271
0
                                height);
5272
0
}
5273
5274
// Convert I422 to RGBA with matrix.
5275
LIBYUV_API
5276
int I422ToRGBAMatrix(const uint8_t* src_y,
5277
                     int src_stride_y,
5278
                     const uint8_t* src_u,
5279
                     int src_stride_u,
5280
                     const uint8_t* src_v,
5281
                     int src_stride_v,
5282
                     uint8_t* dst_rgba,
5283
                     int dst_stride_rgba,
5284
                     const struct YuvConstants* yuvconstants,
5285
                     int width,
5286
71
                     int height) {
5287
71
  int y;
5288
71
  void (*I422ToRGBARow)(const uint8_t* y_buf, const uint8_t* u_buf,
5289
71
                        const uint8_t* v_buf, uint8_t* rgb_buf,
5290
71
                        const struct YuvConstants* yuvconstants, int width) =
5291
71
      I422ToRGBARow_C;
5292
71
  assert(yuvconstants);
5293
71
  if (!src_y || !src_u || !src_v || !dst_rgba || width <= 0 || height == 0) {
5294
0
    return -1;
5295
0
  }
5296
  // Negative height means invert the image.
5297
71
  if (height < 0) {
5298
0
    height = -height;
5299
0
    dst_rgba = dst_rgba + (height - 1) * dst_stride_rgba;
5300
0
    dst_stride_rgba = -dst_stride_rgba;
5301
0
  }
5302
71
#if defined(HAS_I422TORGBAROW_SSSE3)
5303
71
  if (TestCpuFlag(kCpuHasSSSE3)) {
5304
71
    I422ToRGBARow = I422ToRGBARow_Any_SSSE3;
5305
71
    if (IS_ALIGNED(width, 8)) {
5306
34
      I422ToRGBARow = I422ToRGBARow_SSSE3;
5307
34
    }
5308
71
  }
5309
71
#endif
5310
71
#if defined(HAS_I422TORGBAROW_AVX2)
5311
71
  if (TestCpuFlag(kCpuHasAVX2)) {
5312
71
    I422ToRGBARow = I422ToRGBARow_Any_AVX2;
5313
71
    if (IS_ALIGNED(width, 16)) {
5314
17
      I422ToRGBARow = I422ToRGBARow_AVX2;
5315
17
    }
5316
71
  }
5317
71
#endif
5318
#if defined(HAS_I422TORGBAROW_NEON)
5319
  if (TestCpuFlag(kCpuHasNEON)) {
5320
    I422ToRGBARow = I422ToRGBARow_Any_NEON;
5321
    if (IS_ALIGNED(width, 8)) {
5322
      I422ToRGBARow = I422ToRGBARow_NEON;
5323
    }
5324
  }
5325
#endif
5326
#if defined(HAS_I422TORGBAROW_SVE2)
5327
  if (TestCpuFlag(kCpuHasSVE2)) {
5328
    I422ToRGBARow = I422ToRGBARow_SVE2;
5329
  }
5330
#endif
5331
#if defined(HAS_I422TORGBAROW_SME)
5332
  if (TestCpuFlag(kCpuHasSME)) {
5333
    I422ToRGBARow = I422ToRGBARow_SME;
5334
  }
5335
#endif
5336
#if defined(HAS_I422TORGBAROW_MSA)
5337
  if (TestCpuFlag(kCpuHasMSA)) {
5338
    I422ToRGBARow = I422ToRGBARow_Any_MSA;
5339
    if (IS_ALIGNED(width, 8)) {
5340
      I422ToRGBARow = I422ToRGBARow_MSA;
5341
    }
5342
  }
5343
#endif
5344
#if defined(HAS_I422TORGBAROW_LSX)
5345
  if (TestCpuFlag(kCpuHasLSX)) {
5346
    I422ToRGBARow = I422ToRGBARow_Any_LSX;
5347
    if (IS_ALIGNED(width, 16)) {
5348
      I422ToRGBARow = I422ToRGBARow_LSX;
5349
    }
5350
  }
5351
#endif
5352
#if defined(HAS_I422TORGBAROW_LASX)
5353
  if (TestCpuFlag(kCpuHasLASX)) {
5354
    I422ToRGBARow = I422ToRGBARow_Any_LASX;
5355
    if (IS_ALIGNED(width, 32)) {
5356
      I422ToRGBARow = I422ToRGBARow_LASX;
5357
    }
5358
  }
5359
#endif
5360
#if defined(HAS_I422TORGBAROW_RVV)
5361
  if (TestCpuFlag(kCpuHasRVV)) {
5362
    I422ToRGBARow = I422ToRGBARow_RVV;
5363
  }
5364
#endif
5365
5366
1.92k
  for (y = 0; y < height; ++y) {
5367
1.85k
    I422ToRGBARow(src_y, src_u, src_v, dst_rgba, yuvconstants, width);
5368
1.85k
    dst_rgba += dst_stride_rgba;
5369
1.85k
    src_y += src_stride_y;
5370
1.85k
    src_u += src_stride_u;
5371
1.85k
    src_v += src_stride_v;
5372
1.85k
  }
5373
71
  return 0;
5374
71
}
5375
5376
// Convert I422 to RGBA.
5377
LIBYUV_API
5378
int I422ToRGBA(const uint8_t* src_y,
5379
               int src_stride_y,
5380
               const uint8_t* src_u,
5381
               int src_stride_u,
5382
               const uint8_t* src_v,
5383
               int src_stride_v,
5384
               uint8_t* dst_rgba,
5385
               int dst_stride_rgba,
5386
               int width,
5387
0
               int height) {
5388
0
  return I422ToRGBAMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
5389
0
                          src_stride_v, dst_rgba, dst_stride_rgba,
5390
0
                          &kYuvI601Constants, width, height);
5391
0
}
5392
5393
// Convert I422 to BGRA.
5394
LIBYUV_API
5395
int I422ToBGRA(const uint8_t* src_y,
5396
               int src_stride_y,
5397
               const uint8_t* src_u,
5398
               int src_stride_u,
5399
               const uint8_t* src_v,
5400
               int src_stride_v,
5401
               uint8_t* dst_bgra,
5402
               int dst_stride_bgra,
5403
               int width,
5404
0
               int height) {
5405
0
  return I422ToRGBAMatrix(src_y, src_stride_y, src_v,
5406
0
                          src_stride_v,  // Swap U and V
5407
0
                          src_u, src_stride_u, dst_bgra, dst_stride_bgra,
5408
0
                          &kYvuI601Constants,  // Use Yvu matrix
5409
0
                          width, height);
5410
0
}
5411
5412
// Convert NV12 to RGB565 with matrix.
5413
LIBYUV_API
5414
int NV12ToRGB565Matrix(const uint8_t* src_y,
5415
                       int src_stride_y,
5416
                       const uint8_t* src_uv,
5417
                       int src_stride_uv,
5418
                       uint8_t* dst_rgb565,
5419
                       int dst_stride_rgb565,
5420
                       const struct YuvConstants* yuvconstants,
5421
                       int width,
5422
0
                       int height) {
5423
0
  int y;
5424
0
  void (*NV12ToRGB565Row)(
5425
0
      const uint8_t* y_buf, const uint8_t* uv_buf, uint8_t* rgb_buf,
5426
0
      const struct YuvConstants* yuvconstants, int width) = NV12ToRGB565Row_C;
5427
0
  assert(yuvconstants);
5428
0
  if (!src_y || !src_uv || !dst_rgb565 || width <= 0 || height == 0) {
5429
0
    return -1;
5430
0
  }
5431
  // Negative height means invert the image.
5432
0
  if (height < 0) {
5433
0
    height = -height;
5434
0
    dst_rgb565 = dst_rgb565 + (height - 1) * dst_stride_rgb565;
5435
0
    dst_stride_rgb565 = -dst_stride_rgb565;
5436
0
  }
5437
0
#if defined(HAS_NV12TORGB565ROW_SSSE3)
5438
0
  if (TestCpuFlag(kCpuHasSSSE3)) {
5439
0
    NV12ToRGB565Row = NV12ToRGB565Row_Any_SSSE3;
5440
0
    if (IS_ALIGNED(width, 8)) {
5441
0
      NV12ToRGB565Row = NV12ToRGB565Row_SSSE3;
5442
0
    }
5443
0
  }
5444
0
#endif
5445
0
#if defined(HAS_NV12TORGB565ROW_AVX2)
5446
0
  if (TestCpuFlag(kCpuHasAVX2)) {
5447
0
    NV12ToRGB565Row = NV12ToRGB565Row_Any_AVX2;
5448
0
    if (IS_ALIGNED(width, 16)) {
5449
0
      NV12ToRGB565Row = NV12ToRGB565Row_AVX2;
5450
0
    }
5451
0
  }
5452
0
#endif
5453
#if defined(HAS_NV12TORGB565ROW_NEON)
5454
  if (TestCpuFlag(kCpuHasNEON)) {
5455
    NV12ToRGB565Row = NV12ToRGB565Row_Any_NEON;
5456
    if (IS_ALIGNED(width, 8)) {
5457
      NV12ToRGB565Row = NV12ToRGB565Row_NEON;
5458
    }
5459
  }
5460
#endif
5461
#if defined(HAS_NV12TORGB565ROW_MSA)
5462
  if (TestCpuFlag(kCpuHasMSA)) {
5463
    NV12ToRGB565Row = NV12ToRGB565Row_Any_MSA;
5464
    if (IS_ALIGNED(width, 8)) {
5465
      NV12ToRGB565Row = NV12ToRGB565Row_MSA;
5466
    }
5467
  }
5468
#endif
5469
#if defined(HAS_NV12TORGB565ROW_LSX)
5470
  if (TestCpuFlag(kCpuHasLSX)) {
5471
    NV12ToRGB565Row = NV12ToRGB565Row_Any_LSX;
5472
    if (IS_ALIGNED(width, 8)) {
5473
      NV12ToRGB565Row = NV12ToRGB565Row_LSX;
5474
    }
5475
  }
5476
#endif
5477
#if defined(HAS_NV12TORGB565ROW_LASX)
5478
  if (TestCpuFlag(kCpuHasLASX)) {
5479
    NV12ToRGB565Row = NV12ToRGB565Row_Any_LASX;
5480
    if (IS_ALIGNED(width, 16)) {
5481
      NV12ToRGB565Row = NV12ToRGB565Row_LASX;
5482
    }
5483
  }
5484
#endif
5485
5486
0
  for (y = 0; y < height; ++y) {
5487
0
    NV12ToRGB565Row(src_y, src_uv, dst_rgb565, yuvconstants, width);
5488
0
    dst_rgb565 += dst_stride_rgb565;
5489
0
    src_y += src_stride_y;
5490
0
    if (y & 1) {
5491
0
      src_uv += src_stride_uv;
5492
0
    }
5493
0
  }
5494
0
  return 0;
5495
0
}
5496
5497
// Convert NV12 to RGB565.
5498
LIBYUV_API
5499
int NV12ToRGB565(const uint8_t* src_y,
5500
                 int src_stride_y,
5501
                 const uint8_t* src_uv,
5502
                 int src_stride_uv,
5503
                 uint8_t* dst_rgb565,
5504
                 int dst_stride_rgb565,
5505
                 int width,
5506
0
                 int height) {
5507
0
  return NV12ToRGB565Matrix(src_y, src_stride_y, src_uv, src_stride_uv,
5508
0
                            dst_rgb565, dst_stride_rgb565, &kYuvI601Constants,
5509
0
                            width, height);
5510
0
}
5511
5512
// Convert I422 to RGBA with matrix.
5513
LIBYUV_API
5514
int I420ToRGBAMatrix(const uint8_t* src_y,
5515
                     int src_stride_y,
5516
                     const uint8_t* src_u,
5517
                     int src_stride_u,
5518
                     const uint8_t* src_v,
5519
                     int src_stride_v,
5520
                     uint8_t* dst_rgba,
5521
                     int dst_stride_rgba,
5522
                     const struct YuvConstants* yuvconstants,
5523
                     int width,
5524
143
                     int height) {
5525
143
  int y;
5526
143
  void (*I422ToRGBARow)(const uint8_t* y_buf, const uint8_t* u_buf,
5527
143
                        const uint8_t* v_buf, uint8_t* rgb_buf,
5528
143
                        const struct YuvConstants* yuvconstants, int width) =
5529
143
      I422ToRGBARow_C;
5530
143
  assert(yuvconstants);
5531
143
  if (!src_y || !src_u || !src_v || !dst_rgba || width <= 0 || height == 0) {
5532
0
    return -1;
5533
0
  }
5534
  // Negative height means invert the image.
5535
143
  if (height < 0) {
5536
0
    height = -height;
5537
0
    dst_rgba = dst_rgba + (height - 1) * dst_stride_rgba;
5538
0
    dst_stride_rgba = -dst_stride_rgba;
5539
0
  }
5540
143
#if defined(HAS_I422TORGBAROW_SSSE3)
5541
143
  if (TestCpuFlag(kCpuHasSSSE3)) {
5542
143
    I422ToRGBARow = I422ToRGBARow_Any_SSSE3;
5543
143
    if (IS_ALIGNED(width, 8)) {
5544
35
      I422ToRGBARow = I422ToRGBARow_SSSE3;
5545
35
    }
5546
143
  }
5547
143
#endif
5548
143
#if defined(HAS_I422TORGBAROW_AVX2)
5549
143
  if (TestCpuFlag(kCpuHasAVX2)) {
5550
143
    I422ToRGBARow = I422ToRGBARow_Any_AVX2;
5551
143
    if (IS_ALIGNED(width, 16)) {
5552
18
      I422ToRGBARow = I422ToRGBARow_AVX2;
5553
18
    }
5554
143
  }
5555
143
#endif
5556
#if defined(HAS_I422TORGBAROW_NEON)
5557
  if (TestCpuFlag(kCpuHasNEON)) {
5558
    I422ToRGBARow = I422ToRGBARow_Any_NEON;
5559
    if (IS_ALIGNED(width, 8)) {
5560
      I422ToRGBARow = I422ToRGBARow_NEON;
5561
    }
5562
  }
5563
#endif
5564
#if defined(HAS_I422TORGBAROW_SVE2)
5565
  if (TestCpuFlag(kCpuHasSVE2)) {
5566
    I422ToRGBARow = I422ToRGBARow_SVE2;
5567
  }
5568
#endif
5569
#if defined(HAS_I422TORGBAROW_SME)
5570
  if (TestCpuFlag(kCpuHasSME)) {
5571
    I422ToRGBARow = I422ToRGBARow_SME;
5572
  }
5573
#endif
5574
#if defined(HAS_I422TORGBAROW_MSA)
5575
  if (TestCpuFlag(kCpuHasMSA)) {
5576
    I422ToRGBARow = I422ToRGBARow_Any_MSA;
5577
    if (IS_ALIGNED(width, 8)) {
5578
      I422ToRGBARow = I422ToRGBARow_MSA;
5579
    }
5580
  }
5581
#endif
5582
#if defined(HAS_I422TORGBAROW_LSX)
5583
  if (TestCpuFlag(kCpuHasLSX)) {
5584
    I422ToRGBARow = I422ToRGBARow_Any_LSX;
5585
    if (IS_ALIGNED(width, 16)) {
5586
      I422ToRGBARow = I422ToRGBARow_LSX;
5587
    }
5588
  }
5589
#endif
5590
#if defined(HAS_I422TORGBAROW_LASX)
5591
  if (TestCpuFlag(kCpuHasLASX)) {
5592
    I422ToRGBARow = I422ToRGBARow_Any_LASX;
5593
    if (IS_ALIGNED(width, 32)) {
5594
      I422ToRGBARow = I422ToRGBARow_LASX;
5595
    }
5596
  }
5597
#endif
5598
#if defined(HAS_I422TORGBAROW_RVV)
5599
  if (TestCpuFlag(kCpuHasRVV)) {
5600
    I422ToRGBARow = I422ToRGBARow_RVV;
5601
  }
5602
#endif
5603
5604
2.64k
  for (y = 0; y < height; ++y) {
5605
2.50k
    I422ToRGBARow(src_y, src_u, src_v, dst_rgba, yuvconstants, width);
5606
2.50k
    dst_rgba += dst_stride_rgba;
5607
2.50k
    src_y += src_stride_y;
5608
2.50k
    if (y & 1) {
5609
1.23k
      src_u += src_stride_u;
5610
1.23k
      src_v += src_stride_v;
5611
1.23k
    }
5612
2.50k
  }
5613
143
  return 0;
5614
143
}
5615
5616
// Convert I420 to RGBA.
5617
LIBYUV_API
5618
int I420ToRGBA(const uint8_t* src_y,
5619
               int src_stride_y,
5620
               const uint8_t* src_u,
5621
               int src_stride_u,
5622
               const uint8_t* src_v,
5623
               int src_stride_v,
5624
               uint8_t* dst_rgba,
5625
               int dst_stride_rgba,
5626
               int width,
5627
0
               int height) {
5628
0
  return I420ToRGBAMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
5629
0
                          src_stride_v, dst_rgba, dst_stride_rgba,
5630
0
                          &kYuvI601Constants, width, height);
5631
0
}
5632
5633
// Convert I420 to BGRA.
5634
LIBYUV_API
5635
int I420ToBGRA(const uint8_t* src_y,
5636
               int src_stride_y,
5637
               const uint8_t* src_u,
5638
               int src_stride_u,
5639
               const uint8_t* src_v,
5640
               int src_stride_v,
5641
               uint8_t* dst_bgra,
5642
               int dst_stride_bgra,
5643
               int width,
5644
0
               int height) {
5645
0
  return I420ToRGBAMatrix(src_y, src_stride_y, src_v,
5646
0
                          src_stride_v,  // Swap U and V
5647
0
                          src_u, src_stride_u, dst_bgra, dst_stride_bgra,
5648
0
                          &kYvuI601Constants,  // Use Yvu matrix
5649
0
                          width, height);
5650
0
}
5651
5652
// Convert I420 to RGB24 with matrix.
5653
LIBYUV_API
5654
int I420ToRGB24Matrix(const uint8_t* src_y,
5655
                      int src_stride_y,
5656
                      const uint8_t* src_u,
5657
                      int src_stride_u,
5658
                      const uint8_t* src_v,
5659
                      int src_stride_v,
5660
                      uint8_t* dst_rgb24,
5661
                      int dst_stride_rgb24,
5662
                      const struct YuvConstants* yuvconstants,
5663
                      int width,
5664
184
                      int height) {
5665
184
  int y;
5666
184
  void (*I422ToRGB24Row)(const uint8_t* y_buf, const uint8_t* u_buf,
5667
184
                         const uint8_t* v_buf, uint8_t* rgb_buf,
5668
184
                         const struct YuvConstants* yuvconstants, int width) =
5669
184
      I422ToRGB24Row_C;
5670
184
  assert(yuvconstants);
5671
184
  if (!src_y || !src_u || !src_v || !dst_rgb24 || width <= 0 || height == 0) {
5672
0
    return -1;
5673
0
  }
5674
  // Negative height means invert the image.
5675
184
  if (height < 0) {
5676
0
    height = -height;
5677
0
    dst_rgb24 = dst_rgb24 + (height - 1) * dst_stride_rgb24;
5678
0
    dst_stride_rgb24 = -dst_stride_rgb24;
5679
0
  }
5680
184
#if defined(HAS_I422TORGB24ROW_SSSE3)
5681
184
  if (TestCpuFlag(kCpuHasSSSE3)) {
5682
184
    I422ToRGB24Row = I422ToRGB24Row_Any_SSSE3;
5683
184
    if (IS_ALIGNED(width, 16)) {
5684
37
      I422ToRGB24Row = I422ToRGB24Row_SSSE3;
5685
37
    }
5686
184
  }
5687
184
#endif
5688
184
#if defined(HAS_I422TORGB24ROW_AVX2)
5689
184
  if (TestCpuFlag(kCpuHasAVX2)) {
5690
184
    I422ToRGB24Row = I422ToRGB24Row_Any_AVX2;
5691
184
    if (IS_ALIGNED(width, 32)) {
5692
19
      I422ToRGB24Row = I422ToRGB24Row_AVX2;
5693
19
    }
5694
184
  }
5695
184
#endif
5696
#if defined(HAS_I422TORGB24ROW_NEON)
5697
  if (TestCpuFlag(kCpuHasNEON)) {
5698
    I422ToRGB24Row = I422ToRGB24Row_Any_NEON;
5699
    if (IS_ALIGNED(width, 8)) {
5700
      I422ToRGB24Row = I422ToRGB24Row_NEON;
5701
    }
5702
  }
5703
#endif
5704
#if defined(HAS_I422TORGB24ROW_SVE2)
5705
  if (TestCpuFlag(kCpuHasSVE2)) {
5706
    I422ToRGB24Row = I422ToRGB24Row_SVE2;
5707
  }
5708
#endif
5709
#if defined(HAS_I422TORGB24ROW_SME)
5710
  if (TestCpuFlag(kCpuHasSME)) {
5711
    I422ToRGB24Row = I422ToRGB24Row_SME;
5712
  }
5713
#endif
5714
#if defined(HAS_I422TORGB24ROW_MSA)
5715
  if (TestCpuFlag(kCpuHasMSA)) {
5716
    I422ToRGB24Row = I422ToRGB24Row_Any_MSA;
5717
    if (IS_ALIGNED(width, 16)) {
5718
      I422ToRGB24Row = I422ToRGB24Row_MSA;
5719
    }
5720
  }
5721
#endif
5722
#if defined(HAS_I422TORGB24ROW_LSX)
5723
  if (TestCpuFlag(kCpuHasLSX)) {
5724
    I422ToRGB24Row = I422ToRGB24Row_Any_LSX;
5725
    if (IS_ALIGNED(width, 16)) {
5726
      I422ToRGB24Row = I422ToRGB24Row_LSX;
5727
    }
5728
  }
5729
#endif
5730
#if defined(HAS_I422TORGB24ROW_LASX)
5731
  if (TestCpuFlag(kCpuHasLASX)) {
5732
    I422ToRGB24Row = I422ToRGB24Row_Any_LASX;
5733
    if (IS_ALIGNED(width, 32)) {
5734
      I422ToRGB24Row = I422ToRGB24Row_LASX;
5735
    }
5736
  }
5737
#endif
5738
#if defined(HAS_I422TORGB24ROW_RVV)
5739
  if (TestCpuFlag(kCpuHasRVV)) {
5740
    I422ToRGB24Row = I422ToRGB24Row_RVV;
5741
  }
5742
#endif
5743
5744
3.67k
  for (y = 0; y < height; ++y) {
5745
3.49k
    I422ToRGB24Row(src_y, src_u, src_v, dst_rgb24, yuvconstants, width);
5746
3.49k
    dst_rgb24 += dst_stride_rgb24;
5747
3.49k
    src_y += src_stride_y;
5748
3.49k
    if (y & 1) {
5749
1.71k
      src_u += src_stride_u;
5750
1.71k
      src_v += src_stride_v;
5751
1.71k
    }
5752
3.49k
  }
5753
184
  return 0;
5754
184
}
5755
5756
// Convert I420 to RGB24.
5757
LIBYUV_API
5758
int I420ToRGB24(const uint8_t* src_y,
5759
                int src_stride_y,
5760
                const uint8_t* src_u,
5761
                int src_stride_u,
5762
                const uint8_t* src_v,
5763
                int src_stride_v,
5764
                uint8_t* dst_rgb24,
5765
                int dst_stride_rgb24,
5766
                int width,
5767
0
                int height) {
5768
0
  return I420ToRGB24Matrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
5769
0
                           src_stride_v, dst_rgb24, dst_stride_rgb24,
5770
0
                           &kYuvI601Constants, width, height);
5771
0
}
5772
5773
// Convert I420 to RAW.
5774
LIBYUV_API
5775
int I420ToRAW(const uint8_t* src_y,
5776
              int src_stride_y,
5777
              const uint8_t* src_u,
5778
              int src_stride_u,
5779
              const uint8_t* src_v,
5780
              int src_stride_v,
5781
              uint8_t* dst_raw,
5782
              int dst_stride_raw,
5783
              int width,
5784
0
              int height) {
5785
0
  return I420ToRGB24Matrix(src_y, src_stride_y, src_v,
5786
0
                           src_stride_v,  // Swap U and V
5787
0
                           src_u, src_stride_u, dst_raw, dst_stride_raw,
5788
0
                           &kYvuI601Constants,  // Use Yvu matrix
5789
0
                           width, height);
5790
0
}
5791
5792
// Convert J420 to RGB24.
5793
LIBYUV_API
5794
int J420ToRGB24(const uint8_t* src_y,
5795
                int src_stride_y,
5796
                const uint8_t* src_u,
5797
                int src_stride_u,
5798
                const uint8_t* src_v,
5799
                int src_stride_v,
5800
                uint8_t* dst_rgb24,
5801
                int dst_stride_rgb24,
5802
                int width,
5803
0
                int height) {
5804
0
  return I420ToRGB24Matrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
5805
0
                           src_stride_v, dst_rgb24, dst_stride_rgb24,
5806
0
                           &kYuvJPEGConstants, width, height);
5807
0
}
5808
5809
// Convert J420 to RAW.
5810
LIBYUV_API
5811
int J420ToRAW(const uint8_t* src_y,
5812
              int src_stride_y,
5813
              const uint8_t* src_u,
5814
              int src_stride_u,
5815
              const uint8_t* src_v,
5816
              int src_stride_v,
5817
              uint8_t* dst_raw,
5818
              int dst_stride_raw,
5819
              int width,
5820
0
              int height) {
5821
0
  return I420ToRGB24Matrix(src_y, src_stride_y, src_v,
5822
0
                           src_stride_v,  // Swap U and V
5823
0
                           src_u, src_stride_u, dst_raw, dst_stride_raw,
5824
0
                           &kYvuJPEGConstants,  // Use Yvu matrix
5825
0
                           width, height);
5826
0
}
5827
5828
// Convert H420 to RGB24.
5829
LIBYUV_API
5830
int H420ToRGB24(const uint8_t* src_y,
5831
                int src_stride_y,
5832
                const uint8_t* src_u,
5833
                int src_stride_u,
5834
                const uint8_t* src_v,
5835
                int src_stride_v,
5836
                uint8_t* dst_rgb24,
5837
                int dst_stride_rgb24,
5838
                int width,
5839
0
                int height) {
5840
0
  return I420ToRGB24Matrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
5841
0
                           src_stride_v, dst_rgb24, dst_stride_rgb24,
5842
0
                           &kYuvH709Constants, width, height);
5843
0
}
5844
5845
// Convert H420 to RAW.
5846
LIBYUV_API
5847
int H420ToRAW(const uint8_t* src_y,
5848
              int src_stride_y,
5849
              const uint8_t* src_u,
5850
              int src_stride_u,
5851
              const uint8_t* src_v,
5852
              int src_stride_v,
5853
              uint8_t* dst_raw,
5854
              int dst_stride_raw,
5855
              int width,
5856
0
              int height) {
5857
0
  return I420ToRGB24Matrix(src_y, src_stride_y, src_v,
5858
0
                           src_stride_v,  // Swap U and V
5859
0
                           src_u, src_stride_u, dst_raw, dst_stride_raw,
5860
0
                           &kYvuH709Constants,  // Use Yvu matrix
5861
0
                           width, height);
5862
0
}
5863
5864
// Convert I422 to RGB24 with matrix.
5865
LIBYUV_API
5866
int I422ToRGB24Matrix(const uint8_t* src_y,
5867
                      int src_stride_y,
5868
                      const uint8_t* src_u,
5869
                      int src_stride_u,
5870
                      const uint8_t* src_v,
5871
                      int src_stride_v,
5872
                      uint8_t* dst_rgb24,
5873
                      int dst_stride_rgb24,
5874
                      const struct YuvConstants* yuvconstants,
5875
                      int width,
5876
80
                      int height) {
5877
80
  int y;
5878
80
  void (*I422ToRGB24Row)(const uint8_t* y_buf, const uint8_t* u_buf,
5879
80
                         const uint8_t* v_buf, uint8_t* rgb_buf,
5880
80
                         const struct YuvConstants* yuvconstants, int width) =
5881
80
      I422ToRGB24Row_C;
5882
80
  assert(yuvconstants);
5883
80
  if (!src_y || !src_u || !src_v || !dst_rgb24 || width <= 0 || height == 0) {
5884
0
    return -1;
5885
0
  }
5886
  // Negative height means invert the image.
5887
80
  if (height < 0) {
5888
0
    height = -height;
5889
0
    dst_rgb24 = dst_rgb24 + (height - 1) * dst_stride_rgb24;
5890
0
    dst_stride_rgb24 = -dst_stride_rgb24;
5891
0
  }
5892
80
#if defined(HAS_I422TORGB24ROW_SSSE3)
5893
80
  if (TestCpuFlag(kCpuHasSSSE3)) {
5894
80
    I422ToRGB24Row = I422ToRGB24Row_Any_SSSE3;
5895
80
    if (IS_ALIGNED(width, 16)) {
5896
36
      I422ToRGB24Row = I422ToRGB24Row_SSSE3;
5897
36
    }
5898
80
  }
5899
80
#endif
5900
80
#if defined(HAS_I422TORGB24ROW_AVX2)
5901
80
  if (TestCpuFlag(kCpuHasAVX2)) {
5902
80
    I422ToRGB24Row = I422ToRGB24Row_Any_AVX2;
5903
80
    if (IS_ALIGNED(width, 32)) {
5904
19
      I422ToRGB24Row = I422ToRGB24Row_AVX2;
5905
19
    }
5906
80
  }
5907
80
#endif
5908
#if defined(HAS_I422TORGB24ROW_NEON)
5909
  if (TestCpuFlag(kCpuHasNEON)) {
5910
    I422ToRGB24Row = I422ToRGB24Row_Any_NEON;
5911
    if (IS_ALIGNED(width, 8)) {
5912
      I422ToRGB24Row = I422ToRGB24Row_NEON;
5913
    }
5914
  }
5915
#endif
5916
#if defined(HAS_I422TORGB24ROW_SVE2)
5917
  if (TestCpuFlag(kCpuHasSVE2)) {
5918
    I422ToRGB24Row = I422ToRGB24Row_SVE2;
5919
  }
5920
#endif
5921
#if defined(HAS_I422TORGB24ROW_SME)
5922
  if (TestCpuFlag(kCpuHasSME)) {
5923
    I422ToRGB24Row = I422ToRGB24Row_SME;
5924
  }
5925
#endif
5926
#if defined(HAS_I422TORGB24ROW_MSA)
5927
  if (TestCpuFlag(kCpuHasMSA)) {
5928
    I422ToRGB24Row = I422ToRGB24Row_Any_MSA;
5929
    if (IS_ALIGNED(width, 16)) {
5930
      I422ToRGB24Row = I422ToRGB24Row_MSA;
5931
    }
5932
  }
5933
#endif
5934
#if defined(HAS_I422TORGB24ROW_LSX)
5935
  if (TestCpuFlag(kCpuHasLSX)) {
5936
    I422ToRGB24Row = I422ToRGB24Row_Any_LSX;
5937
    if (IS_ALIGNED(width, 16)) {
5938
      I422ToRGB24Row = I422ToRGB24Row_LSX;
5939
    }
5940
  }
5941
#endif
5942
#if defined(HAS_I422TORGB24ROW_LASX)
5943
  if (TestCpuFlag(kCpuHasLASX)) {
5944
    I422ToRGB24Row = I422ToRGB24Row_Any_LASX;
5945
    if (IS_ALIGNED(width, 32)) {
5946
      I422ToRGB24Row = I422ToRGB24Row_LASX;
5947
    }
5948
  }
5949
#endif
5950
#if defined(HAS_I422TORGB24ROW_RVV)
5951
  if (TestCpuFlag(kCpuHasRVV)) {
5952
    I422ToRGB24Row = I422ToRGB24Row_RVV;
5953
  }
5954
#endif
5955
5956
1.57k
  for (y = 0; y < height; ++y) {
5957
1.49k
    I422ToRGB24Row(src_y, src_u, src_v, dst_rgb24, yuvconstants, width);
5958
1.49k
    dst_rgb24 += dst_stride_rgb24;
5959
1.49k
    src_y += src_stride_y;
5960
1.49k
    src_u += src_stride_u;
5961
1.49k
    src_v += src_stride_v;
5962
1.49k
  }
5963
80
  return 0;
5964
80
}
5965
5966
// Convert I422 to RGB24.
5967
LIBYUV_API
5968
int I422ToRGB24(const uint8_t* src_y,
5969
                int src_stride_y,
5970
                const uint8_t* src_u,
5971
                int src_stride_u,
5972
                const uint8_t* src_v,
5973
                int src_stride_v,
5974
                uint8_t* dst_rgb24,
5975
                int dst_stride_rgb24,
5976
                int width,
5977
0
                int height) {
5978
0
  return I422ToRGB24Matrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
5979
0
                           src_stride_v, dst_rgb24, dst_stride_rgb24,
5980
0
                           &kYuvI601Constants, width, height);
5981
0
}
5982
5983
// Convert I422 to RAW.
5984
LIBYUV_API
5985
int I422ToRAW(const uint8_t* src_y,
5986
              int src_stride_y,
5987
              const uint8_t* src_u,
5988
              int src_stride_u,
5989
              const uint8_t* src_v,
5990
              int src_stride_v,
5991
              uint8_t* dst_raw,
5992
              int dst_stride_raw,
5993
              int width,
5994
0
              int height) {
5995
0
  return I422ToRGB24Matrix(src_y, src_stride_y, src_v,
5996
0
                           src_stride_v,  // Swap U and V
5997
0
                           src_u, src_stride_u, dst_raw, dst_stride_raw,
5998
0
                           &kYvuI601Constants,  // Use Yvu matrix
5999
0
                           width, height);
6000
0
}
6001
6002
// Convert I420 to ARGB1555.
6003
LIBYUV_API
6004
int I420ToARGB1555(const uint8_t* src_y,
6005
                   int src_stride_y,
6006
                   const uint8_t* src_u,
6007
                   int src_stride_u,
6008
                   const uint8_t* src_v,
6009
                   int src_stride_v,
6010
                   uint8_t* dst_argb1555,
6011
                   int dst_stride_argb1555,
6012
                   int width,
6013
0
                   int height) {
6014
0
  int y;
6015
0
  void (*I422ToARGB1555Row)(const uint8_t* y_buf, const uint8_t* u_buf,
6016
0
                            const uint8_t* v_buf, uint8_t* rgb_buf,
6017
0
                            const struct YuvConstants* yuvconstants,
6018
0
                            int width) = I422ToARGB1555Row_C;
6019
0
  if (!src_y || !src_u || !src_v || !dst_argb1555 || width <= 0 ||
6020
0
      height == 0) {
6021
0
    return -1;
6022
0
  }
6023
  // Negative height means invert the image.
6024
0
  if (height < 0) {
6025
0
    height = -height;
6026
0
    dst_argb1555 = dst_argb1555 + (height - 1) * dst_stride_argb1555;
6027
0
    dst_stride_argb1555 = -dst_stride_argb1555;
6028
0
  }
6029
0
#if defined(HAS_I422TOARGB1555ROW_SSSE3)
6030
0
  if (TestCpuFlag(kCpuHasSSSE3)) {
6031
0
    I422ToARGB1555Row = I422ToARGB1555Row_Any_SSSE3;
6032
0
    if (IS_ALIGNED(width, 8)) {
6033
0
      I422ToARGB1555Row = I422ToARGB1555Row_SSSE3;
6034
0
    }
6035
0
  }
6036
0
#endif
6037
0
#if defined(HAS_I422TOARGB1555ROW_AVX2)
6038
0
  if (TestCpuFlag(kCpuHasAVX2)) {
6039
0
    I422ToARGB1555Row = I422ToARGB1555Row_Any_AVX2;
6040
0
    if (IS_ALIGNED(width, 16)) {
6041
0
      I422ToARGB1555Row = I422ToARGB1555Row_AVX2;
6042
0
    }
6043
0
  }
6044
0
#endif
6045
#if defined(HAS_I422TOARGB1555ROW_NEON)
6046
  if (TestCpuFlag(kCpuHasNEON)) {
6047
    I422ToARGB1555Row = I422ToARGB1555Row_Any_NEON;
6048
    if (IS_ALIGNED(width, 8)) {
6049
      I422ToARGB1555Row = I422ToARGB1555Row_NEON;
6050
    }
6051
  }
6052
#endif
6053
#if defined(HAS_I422TOARGB1555ROW_SVE2)
6054
  if (TestCpuFlag(kCpuHasSVE2)) {
6055
    I422ToARGB1555Row = I422ToARGB1555Row_SVE2;
6056
  }
6057
#endif
6058
#if defined(HAS_I422TOARGB1555ROW_SME)
6059
  if (TestCpuFlag(kCpuHasSME)) {
6060
    I422ToARGB1555Row = I422ToARGB1555Row_SME;
6061
  }
6062
#endif
6063
#if defined(HAS_I422TOARGB1555ROW_MSA)
6064
  if (TestCpuFlag(kCpuHasMSA)) {
6065
    I422ToARGB1555Row = I422ToARGB1555Row_Any_MSA;
6066
    if (IS_ALIGNED(width, 8)) {
6067
      I422ToARGB1555Row = I422ToARGB1555Row_MSA;
6068
    }
6069
  }
6070
#endif
6071
#if defined(HAS_I422TOARGB1555ROW_LSX)
6072
  if (TestCpuFlag(kCpuHasLSX)) {
6073
    I422ToARGB1555Row = I422ToARGB1555Row_Any_LSX;
6074
    if (IS_ALIGNED(width, 16)) {
6075
      I422ToARGB1555Row = I422ToARGB1555Row_LSX;
6076
    }
6077
  }
6078
#endif
6079
#if defined(HAS_I422TOARGB1555ROW_LASX)
6080
  if (TestCpuFlag(kCpuHasLASX)) {
6081
    I422ToARGB1555Row = I422ToARGB1555Row_Any_LASX;
6082
    if (IS_ALIGNED(width, 8)) {
6083
      I422ToARGB1555Row = I422ToARGB1555Row_LASX;
6084
    }
6085
  }
6086
#endif
6087
6088
0
  for (y = 0; y < height; ++y) {
6089
0
    I422ToARGB1555Row(src_y, src_u, src_v, dst_argb1555, &kYuvI601Constants,
6090
0
                      width);
6091
0
    dst_argb1555 += dst_stride_argb1555;
6092
0
    src_y += src_stride_y;
6093
0
    if (y & 1) {
6094
0
      src_u += src_stride_u;
6095
0
      src_v += src_stride_v;
6096
0
    }
6097
0
  }
6098
0
  return 0;
6099
0
}
6100
6101
// Convert I420 to ARGB4444.
6102
LIBYUV_API
6103
int I420ToARGB4444(const uint8_t* src_y,
6104
                   int src_stride_y,
6105
                   const uint8_t* src_u,
6106
                   int src_stride_u,
6107
                   const uint8_t* src_v,
6108
                   int src_stride_v,
6109
                   uint8_t* dst_argb4444,
6110
                   int dst_stride_argb4444,
6111
                   int width,
6112
0
                   int height) {
6113
0
  int y;
6114
0
  void (*I422ToARGB4444Row)(const uint8_t* y_buf, const uint8_t* u_buf,
6115
0
                            const uint8_t* v_buf, uint8_t* rgb_buf,
6116
0
                            const struct YuvConstants* yuvconstants,
6117
0
                            int width) = I422ToARGB4444Row_C;
6118
0
  if (!src_y || !src_u || !src_v || !dst_argb4444 || width <= 0 ||
6119
0
      height == 0) {
6120
0
    return -1;
6121
0
  }
6122
  // Negative height means invert the image.
6123
0
  if (height < 0) {
6124
0
    height = -height;
6125
0
    dst_argb4444 = dst_argb4444 + (height - 1) * dst_stride_argb4444;
6126
0
    dst_stride_argb4444 = -dst_stride_argb4444;
6127
0
  }
6128
0
#if defined(HAS_I422TOARGB4444ROW_SSSE3)
6129
0
  if (TestCpuFlag(kCpuHasSSSE3)) {
6130
0
    I422ToARGB4444Row = I422ToARGB4444Row_Any_SSSE3;
6131
0
    if (IS_ALIGNED(width, 8)) {
6132
0
      I422ToARGB4444Row = I422ToARGB4444Row_SSSE3;
6133
0
    }
6134
0
  }
6135
0
#endif
6136
0
#if defined(HAS_I422TOARGB4444ROW_AVX2)
6137
0
  if (TestCpuFlag(kCpuHasAVX2)) {
6138
0
    I422ToARGB4444Row = I422ToARGB4444Row_Any_AVX2;
6139
0
    if (IS_ALIGNED(width, 16)) {
6140
0
      I422ToARGB4444Row = I422ToARGB4444Row_AVX2;
6141
0
    }
6142
0
  }
6143
0
#endif
6144
#if defined(HAS_I422TOARGB4444ROW_NEON)
6145
  if (TestCpuFlag(kCpuHasNEON)) {
6146
    I422ToARGB4444Row = I422ToARGB4444Row_Any_NEON;
6147
    if (IS_ALIGNED(width, 8)) {
6148
      I422ToARGB4444Row = I422ToARGB4444Row_NEON;
6149
    }
6150
  }
6151
#endif
6152
#if defined(HAS_I422TOARGB4444ROW_SVE2)
6153
  if (TestCpuFlag(kCpuHasSVE2)) {
6154
    I422ToARGB4444Row = I422ToARGB4444Row_SVE2;
6155
  }
6156
#endif
6157
#if defined(HAS_I422TOARGB4444ROW_SME)
6158
  if (TestCpuFlag(kCpuHasSME)) {
6159
    I422ToARGB4444Row = I422ToARGB4444Row_SME;
6160
  }
6161
#endif
6162
#if defined(HAS_I422TOARGB4444ROW_MSA)
6163
  if (TestCpuFlag(kCpuHasMSA)) {
6164
    I422ToARGB4444Row = I422ToARGB4444Row_Any_MSA;
6165
    if (IS_ALIGNED(width, 8)) {
6166
      I422ToARGB4444Row = I422ToARGB4444Row_MSA;
6167
    }
6168
  }
6169
#endif
6170
#if defined(HAS_I422TOARGB4444ROW_LSX)
6171
  if (TestCpuFlag(kCpuHasLSX)) {
6172
    I422ToARGB4444Row = I422ToARGB4444Row_Any_LSX;
6173
    if (IS_ALIGNED(width, 16)) {
6174
      I422ToARGB4444Row = I422ToARGB4444Row_LSX;
6175
    }
6176
  }
6177
#endif
6178
#if defined(HAS_I422TOARGB4444ROW_LASX)
6179
  if (TestCpuFlag(kCpuHasLASX)) {
6180
    I422ToARGB4444Row = I422ToARGB4444Row_Any_LASX;
6181
    if (IS_ALIGNED(width, 8)) {
6182
      I422ToARGB4444Row = I422ToARGB4444Row_LASX;
6183
    }
6184
  }
6185
#endif
6186
6187
0
  for (y = 0; y < height; ++y) {
6188
0
    I422ToARGB4444Row(src_y, src_u, src_v, dst_argb4444, &kYuvI601Constants,
6189
0
                      width);
6190
0
    dst_argb4444 += dst_stride_argb4444;
6191
0
    src_y += src_stride_y;
6192
0
    if (y & 1) {
6193
0
      src_u += src_stride_u;
6194
0
      src_v += src_stride_v;
6195
0
    }
6196
0
  }
6197
0
  return 0;
6198
0
}
6199
6200
// Convert I420 to RGB565 with specified color matrix.
6201
LIBYUV_API
6202
int I420ToRGB565Matrix(const uint8_t* src_y,
6203
                       int src_stride_y,
6204
                       const uint8_t* src_u,
6205
                       int src_stride_u,
6206
                       const uint8_t* src_v,
6207
                       int src_stride_v,
6208
                       uint8_t* dst_rgb565,
6209
                       int dst_stride_rgb565,
6210
                       const struct YuvConstants* yuvconstants,
6211
                       int width,
6212
140
                       int height) {
6213
140
  int y;
6214
140
  void (*I422ToRGB565Row)(const uint8_t* y_buf, const uint8_t* u_buf,
6215
140
                          const uint8_t* v_buf, uint8_t* rgb_buf,
6216
140
                          const struct YuvConstants* yuvconstants, int width) =
6217
140
      I422ToRGB565Row_C;
6218
140
  assert(yuvconstants);
6219
140
  if (!src_y || !src_u || !src_v || !dst_rgb565 || width <= 0 || height == 0) {
6220
0
    return -1;
6221
0
  }
6222
  // Negative height means invert the image.
6223
140
  if (height < 0) {
6224
0
    height = -height;
6225
0
    dst_rgb565 = dst_rgb565 + (height - 1) * dst_stride_rgb565;
6226
0
    dst_stride_rgb565 = -dst_stride_rgb565;
6227
0
  }
6228
140
#if defined(HAS_I422TORGB565ROW_SSSE3)
6229
140
  if (TestCpuFlag(kCpuHasSSSE3)) {
6230
140
    I422ToRGB565Row = I422ToRGB565Row_Any_SSSE3;
6231
140
    if (IS_ALIGNED(width, 8)) {
6232
34
      I422ToRGB565Row = I422ToRGB565Row_SSSE3;
6233
34
    }
6234
140
  }
6235
140
#endif
6236
140
#if defined(HAS_I422TORGB565ROW_AVX2)
6237
140
  if (TestCpuFlag(kCpuHasAVX2)) {
6238
140
    I422ToRGB565Row = I422ToRGB565Row_Any_AVX2;
6239
140
    if (IS_ALIGNED(width, 16)) {
6240
17
      I422ToRGB565Row = I422ToRGB565Row_AVX2;
6241
17
    }
6242
140
  }
6243
140
#endif
6244
#if defined(HAS_I422TORGB565ROW_NEON)
6245
  if (TestCpuFlag(kCpuHasNEON)) {
6246
    I422ToRGB565Row = I422ToRGB565Row_Any_NEON;
6247
    if (IS_ALIGNED(width, 8)) {
6248
      I422ToRGB565Row = I422ToRGB565Row_NEON;
6249
    }
6250
  }
6251
#endif
6252
#if defined(HAS_I422TORGB565ROW_SVE2)
6253
  if (TestCpuFlag(kCpuHasSVE2)) {
6254
    I422ToRGB565Row = I422ToRGB565Row_SVE2;
6255
  }
6256
#endif
6257
#if defined(HAS_I422TORGB565ROW_SME)
6258
  if (TestCpuFlag(kCpuHasSME)) {
6259
    I422ToRGB565Row = I422ToRGB565Row_SME;
6260
  }
6261
#endif
6262
#if defined(HAS_I422TORGB565ROW_MSA)
6263
  if (TestCpuFlag(kCpuHasMSA)) {
6264
    I422ToRGB565Row = I422ToRGB565Row_Any_MSA;
6265
    if (IS_ALIGNED(width, 8)) {
6266
      I422ToRGB565Row = I422ToRGB565Row_MSA;
6267
    }
6268
  }
6269
#endif
6270
#if defined(HAS_I422TORGB565ROW_LSX)
6271
  if (TestCpuFlag(kCpuHasLSX)) {
6272
    I422ToRGB565Row = I422ToRGB565Row_Any_LSX;
6273
    if (IS_ALIGNED(width, 16)) {
6274
      I422ToRGB565Row = I422ToRGB565Row_LSX;
6275
    }
6276
  }
6277
#endif
6278
#if defined(HAS_I422TORGB565ROW_LASX)
6279
  if (TestCpuFlag(kCpuHasLASX)) {
6280
    I422ToRGB565Row = I422ToRGB565Row_Any_LASX;
6281
    if (IS_ALIGNED(width, 32)) {
6282
      I422ToRGB565Row = I422ToRGB565Row_LASX;
6283
    }
6284
  }
6285
#endif
6286
6287
2.86k
  for (y = 0; y < height; ++y) {
6288
2.72k
    I422ToRGB565Row(src_y, src_u, src_v, dst_rgb565, yuvconstants, width);
6289
2.72k
    dst_rgb565 += dst_stride_rgb565;
6290
2.72k
    src_y += src_stride_y;
6291
2.72k
    if (y & 1) {
6292
1.34k
      src_u += src_stride_u;
6293
1.34k
      src_v += src_stride_v;
6294
1.34k
    }
6295
2.72k
  }
6296
140
  return 0;
6297
140
}
6298
6299
// Convert I420 to RGB565.
6300
LIBYUV_API
6301
int I420ToRGB565(const uint8_t* src_y,
6302
                 int src_stride_y,
6303
                 const uint8_t* src_u,
6304
                 int src_stride_u,
6305
                 const uint8_t* src_v,
6306
                 int src_stride_v,
6307
                 uint8_t* dst_rgb565,
6308
                 int dst_stride_rgb565,
6309
                 int width,
6310
0
                 int height) {
6311
0
  return I420ToRGB565Matrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
6312
0
                            src_stride_v, dst_rgb565, dst_stride_rgb565,
6313
0
                            &kYuvI601Constants, width, height);
6314
0
}
6315
6316
// Convert J420 to RGB565.
6317
LIBYUV_API
6318
int J420ToRGB565(const uint8_t* src_y,
6319
                 int src_stride_y,
6320
                 const uint8_t* src_u,
6321
                 int src_stride_u,
6322
                 const uint8_t* src_v,
6323
                 int src_stride_v,
6324
                 uint8_t* dst_rgb565,
6325
                 int dst_stride_rgb565,
6326
                 int width,
6327
0
                 int height) {
6328
0
  return I420ToRGB565Matrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
6329
0
                            src_stride_v, dst_rgb565, dst_stride_rgb565,
6330
0
                            &kYuvJPEGConstants, width, height);
6331
0
}
6332
6333
// Convert H420 to RGB565.
6334
LIBYUV_API
6335
int H420ToRGB565(const uint8_t* src_y,
6336
                 int src_stride_y,
6337
                 const uint8_t* src_u,
6338
                 int src_stride_u,
6339
                 const uint8_t* src_v,
6340
                 int src_stride_v,
6341
                 uint8_t* dst_rgb565,
6342
                 int dst_stride_rgb565,
6343
                 int width,
6344
0
                 int height) {
6345
0
  return I420ToRGB565Matrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
6346
0
                            src_stride_v, dst_rgb565, dst_stride_rgb565,
6347
0
                            &kYuvH709Constants, width, height);
6348
0
}
6349
6350
// Convert I422 to RGB565 with specified color matrix.
6351
LIBYUV_API
6352
int I422ToRGB565Matrix(const uint8_t* src_y,
6353
                       int src_stride_y,
6354
                       const uint8_t* src_u,
6355
                       int src_stride_u,
6356
                       const uint8_t* src_v,
6357
                       int src_stride_v,
6358
                       uint8_t* dst_rgb565,
6359
                       int dst_stride_rgb565,
6360
                       const struct YuvConstants* yuvconstants,
6361
                       int width,
6362
88
                       int height) {
6363
88
  int y;
6364
88
  void (*I422ToRGB565Row)(const uint8_t* y_buf, const uint8_t* u_buf,
6365
88
                          const uint8_t* v_buf, uint8_t* rgb_buf,
6366
88
                          const struct YuvConstants* yuvconstants, int width) =
6367
88
      I422ToRGB565Row_C;
6368
88
  assert(yuvconstants);
6369
88
  if (!src_y || !src_u || !src_v || !dst_rgb565 || width <= 0 || height == 0) {
6370
0
    return -1;
6371
0
  }
6372
  // Negative height means invert the image.
6373
88
  if (height < 0) {
6374
0
    height = -height;
6375
0
    dst_rgb565 = dst_rgb565 + (height - 1) * dst_stride_rgb565;
6376
0
    dst_stride_rgb565 = -dst_stride_rgb565;
6377
0
  }
6378
88
#if defined(HAS_I422TORGB565ROW_SSSE3)
6379
88
  if (TestCpuFlag(kCpuHasSSSE3)) {
6380
88
    I422ToRGB565Row = I422ToRGB565Row_Any_SSSE3;
6381
88
    if (IS_ALIGNED(width, 8)) {
6382
34
      I422ToRGB565Row = I422ToRGB565Row_SSSE3;
6383
34
    }
6384
88
  }
6385
88
#endif
6386
88
#if defined(HAS_I422TORGB565ROW_AVX2)
6387
88
  if (TestCpuFlag(kCpuHasAVX2)) {
6388
88
    I422ToRGB565Row = I422ToRGB565Row_Any_AVX2;
6389
88
    if (IS_ALIGNED(width, 16)) {
6390
17
      I422ToRGB565Row = I422ToRGB565Row_AVX2;
6391
17
    }
6392
88
  }
6393
88
#endif
6394
#if defined(HAS_I422TORGB565ROW_NEON)
6395
  if (TestCpuFlag(kCpuHasNEON)) {
6396
    I422ToRGB565Row = I422ToRGB565Row_Any_NEON;
6397
    if (IS_ALIGNED(width, 8)) {
6398
      I422ToRGB565Row = I422ToRGB565Row_NEON;
6399
    }
6400
  }
6401
#endif
6402
#if defined(HAS_I422TORGB565ROW_SVE2)
6403
  if (TestCpuFlag(kCpuHasSVE2)) {
6404
    I422ToRGB565Row = I422ToRGB565Row_SVE2;
6405
  }
6406
#endif
6407
#if defined(HAS_I422TORGB565ROW_SME)
6408
  if (TestCpuFlag(kCpuHasSME)) {
6409
    I422ToRGB565Row = I422ToRGB565Row_SME;
6410
  }
6411
#endif
6412
#if defined(HAS_I422TORGB565ROW_MSA)
6413
  if (TestCpuFlag(kCpuHasMSA)) {
6414
    I422ToRGB565Row = I422ToRGB565Row_Any_MSA;
6415
    if (IS_ALIGNED(width, 8)) {
6416
      I422ToRGB565Row = I422ToRGB565Row_MSA;
6417
    }
6418
  }
6419
#endif
6420
#if defined(HAS_I422TORGB565ROW_LSX)
6421
  if (TestCpuFlag(kCpuHasLSX)) {
6422
    I422ToRGB565Row = I422ToRGB565Row_Any_LSX;
6423
    if (IS_ALIGNED(width, 16)) {
6424
      I422ToRGB565Row = I422ToRGB565Row_LSX;
6425
    }
6426
  }
6427
#endif
6428
#if defined(HAS_I422TORGB565ROW_LASX)
6429
  if (TestCpuFlag(kCpuHasLASX)) {
6430
    I422ToRGB565Row = I422ToRGB565Row_Any_LASX;
6431
    if (IS_ALIGNED(width, 32)) {
6432
      I422ToRGB565Row = I422ToRGB565Row_LASX;
6433
    }
6434
  }
6435
#endif
6436
6437
1.61k
  for (y = 0; y < height; ++y) {
6438
1.52k
    I422ToRGB565Row(src_y, src_u, src_v, dst_rgb565, yuvconstants, width);
6439
1.52k
    dst_rgb565 += dst_stride_rgb565;
6440
1.52k
    src_y += src_stride_y;
6441
1.52k
    src_u += src_stride_u;
6442
1.52k
    src_v += src_stride_v;
6443
1.52k
  }
6444
88
  return 0;
6445
88
}
6446
6447
// Convert I422 to RGB565.
6448
LIBYUV_API
6449
int I422ToRGB565(const uint8_t* src_y,
6450
                 int src_stride_y,
6451
                 const uint8_t* src_u,
6452
                 int src_stride_u,
6453
                 const uint8_t* src_v,
6454
                 int src_stride_v,
6455
                 uint8_t* dst_rgb565,
6456
                 int dst_stride_rgb565,
6457
                 int width,
6458
0
                 int height) {
6459
0
  return I422ToRGB565Matrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
6460
0
                            src_stride_v, dst_rgb565, dst_stride_rgb565,
6461
0
                            &kYuvI601Constants, width, height);
6462
0
}
6463
6464
// Ordered 8x8 dither for 888 to 565.  Values from 0 to 7.
6465
static const uint8_t kDither565_4x4[16] = {
6466
    0, 4, 1, 5, 6, 2, 7, 3, 1, 5, 0, 4, 7, 3, 6, 2,
6467
};
6468
6469
// Convert I420 to RGB565 with dithering.
6470
LIBYUV_API
6471
int I420ToRGB565Dither(const uint8_t* src_y,
6472
                       int src_stride_y,
6473
                       const uint8_t* src_u,
6474
                       int src_stride_u,
6475
                       const uint8_t* src_v,
6476
                       int src_stride_v,
6477
                       uint8_t* dst_rgb565,
6478
                       int dst_stride_rgb565,
6479
                       const uint8_t* dither4x4,
6480
                       int width,
6481
0
                       int height) {
6482
0
  int y;
6483
0
  void (*I422ToARGBRow)(const uint8_t* y_buf, const uint8_t* u_buf,
6484
0
                        const uint8_t* v_buf, uint8_t* rgb_buf,
6485
0
                        const struct YuvConstants* yuvconstants, int width) =
6486
0
      I422ToARGBRow_C;
6487
0
  void (*ARGBToRGB565DitherRow)(const uint8_t* src_argb, uint8_t* dst_rgb,
6488
0
                                uint32_t dither4, int width) =
6489
0
      ARGBToRGB565DitherRow_C;
6490
0
  if (!src_y || !src_u || !src_v || !dst_rgb565 || width <= 0 || height == 0) {
6491
0
    return -1;
6492
0
  }
6493
  // Negative height means invert the image.
6494
0
  if (height < 0) {
6495
0
    height = -height;
6496
0
    dst_rgb565 = dst_rgb565 + (height - 1) * dst_stride_rgb565;
6497
0
    dst_stride_rgb565 = -dst_stride_rgb565;
6498
0
  }
6499
0
  if (!dither4x4) {
6500
0
    dither4x4 = kDither565_4x4;
6501
0
  }
6502
0
#if defined(HAS_I422TOARGBROW_SSSE3)
6503
0
  if (TestCpuFlag(kCpuHasSSSE3)) {
6504
0
    I422ToARGBRow = I422ToARGBRow_Any_SSSE3;
6505
0
    if (IS_ALIGNED(width, 8)) {
6506
0
      I422ToARGBRow = I422ToARGBRow_SSSE3;
6507
0
    }
6508
0
  }
6509
0
#endif
6510
0
#if defined(HAS_I422TOARGBROW_AVX2)
6511
0
  if (TestCpuFlag(kCpuHasAVX2)) {
6512
0
    I422ToARGBRow = I422ToARGBRow_Any_AVX2;
6513
0
    if (IS_ALIGNED(width, 16)) {
6514
0
      I422ToARGBRow = I422ToARGBRow_AVX2;
6515
0
    }
6516
0
  }
6517
0
#endif
6518
0
#if defined(HAS_I422TOARGBROW_AVX512BW)
6519
0
  if (TestCpuFlag(kCpuHasAVX512BW | kCpuHasAVX512VL) ==
6520
0
      (kCpuHasAVX512BW | kCpuHasAVX512VL)) {
6521
0
    I422ToARGBRow = I422ToARGBRow_Any_AVX512BW;
6522
0
    if (IS_ALIGNED(width, 32)) {
6523
0
      I422ToARGBRow = I422ToARGBRow_AVX512BW;
6524
0
    }
6525
0
  }
6526
0
#endif
6527
#if defined(HAS_I422TOARGBROW_NEON)
6528
  if (TestCpuFlag(kCpuHasNEON)) {
6529
    I422ToARGBRow = I422ToARGBRow_Any_NEON;
6530
    if (IS_ALIGNED(width, 8)) {
6531
      I422ToARGBRow = I422ToARGBRow_NEON;
6532
    }
6533
  }
6534
#endif
6535
#if defined(HAS_I422TOARGBROW_SVE2)
6536
  if (TestCpuFlag(kCpuHasSVE2)) {
6537
    I422ToARGBRow = I422ToARGBRow_SVE2;
6538
  }
6539
#endif
6540
#if defined(HAS_I422TOARGBROW_SME)
6541
  if (TestCpuFlag(kCpuHasSME)) {
6542
    I422ToARGBRow = I422ToARGBRow_SME;
6543
  }
6544
#endif
6545
#if defined(HAS_I422TOARGBROW_MSA)
6546
  if (TestCpuFlag(kCpuHasMSA)) {
6547
    I422ToARGBRow = I422ToARGBRow_Any_MSA;
6548
    if (IS_ALIGNED(width, 8)) {
6549
      I422ToARGBRow = I422ToARGBRow_MSA;
6550
    }
6551
  }
6552
#endif
6553
#if defined(HAS_I422TOARGBROW_LSX)
6554
  if (TestCpuFlag(kCpuHasLSX)) {
6555
    I422ToARGBRow = I422ToARGBRow_Any_LSX;
6556
    if (IS_ALIGNED(width, 16)) {
6557
      I422ToARGBRow = I422ToARGBRow_LSX;
6558
    }
6559
  }
6560
#endif
6561
#if defined(HAS_I422TOARGBROW_LASX)
6562
  if (TestCpuFlag(kCpuHasLASX)) {
6563
    I422ToARGBRow = I422ToARGBRow_Any_LASX;
6564
    if (IS_ALIGNED(width, 32)) {
6565
      I422ToARGBRow = I422ToARGBRow_LASX;
6566
    }
6567
  }
6568
#endif
6569
#if defined(HAS_I422TOARGBROW_RVV)
6570
  if (TestCpuFlag(kCpuHasRVV)) {
6571
    I422ToARGBRow = I422ToARGBRow_RVV;
6572
  }
6573
#endif
6574
0
#if defined(HAS_ARGBTORGB565DITHERROW_SSE2)
6575
0
  if (TestCpuFlag(kCpuHasSSE2)) {
6576
0
    ARGBToRGB565DitherRow = ARGBToRGB565DitherRow_Any_SSE2;
6577
0
    if (IS_ALIGNED(width, 4)) {
6578
0
      ARGBToRGB565DitherRow = ARGBToRGB565DitherRow_SSE2;
6579
0
    }
6580
0
  }
6581
0
#endif
6582
0
#if defined(HAS_ARGBTORGB565DITHERROW_AVX2)
6583
0
  if (TestCpuFlag(kCpuHasAVX2)) {
6584
0
    ARGBToRGB565DitherRow = ARGBToRGB565DitherRow_Any_AVX2;
6585
0
    if (IS_ALIGNED(width, 8)) {
6586
0
      ARGBToRGB565DitherRow = ARGBToRGB565DitherRow_AVX2;
6587
0
    }
6588
0
  }
6589
0
#endif
6590
#if defined(HAS_ARGBTORGB565DITHERROW_NEON)
6591
  if (TestCpuFlag(kCpuHasNEON)) {
6592
    ARGBToRGB565DitherRow = ARGBToRGB565DitherRow_Any_NEON;
6593
    if (IS_ALIGNED(width, 8)) {
6594
      ARGBToRGB565DitherRow = ARGBToRGB565DitherRow_NEON;
6595
    }
6596
  }
6597
#endif
6598
#if defined(HAS_ARGBTORGB565DITHERROW_SVE2)
6599
  if (TestCpuFlag(kCpuHasSVE2)) {
6600
    ARGBToRGB565DitherRow = ARGBToRGB565DitherRow_SVE2;
6601
  }
6602
#endif
6603
#if defined(HAS_ARGBTORGB565DITHERROW_MSA)
6604
  if (TestCpuFlag(kCpuHasMSA)) {
6605
    ARGBToRGB565DitherRow = ARGBToRGB565DitherRow_Any_MSA;
6606
    if (IS_ALIGNED(width, 8)) {
6607
      ARGBToRGB565DitherRow = ARGBToRGB565DitherRow_MSA;
6608
    }
6609
  }
6610
#endif
6611
#if defined(HAS_ARGBTORGB565DITHERROW_LSX)
6612
  if (TestCpuFlag(kCpuHasLSX)) {
6613
    ARGBToRGB565DitherRow = ARGBToRGB565DitherRow_Any_LSX;
6614
    if (IS_ALIGNED(width, 8)) {
6615
      ARGBToRGB565DitherRow = ARGBToRGB565DitherRow_LSX;
6616
    }
6617
  }
6618
#endif
6619
#if defined(HAS_ARGBTORGB565DITHERROW_LASX)
6620
  if (TestCpuFlag(kCpuHasLASX)) {
6621
    ARGBToRGB565DitherRow = ARGBToRGB565DitherRow_Any_LASX;
6622
    if (IS_ALIGNED(width, 16)) {
6623
      ARGBToRGB565DitherRow = ARGBToRGB565DitherRow_LASX;
6624
    }
6625
  }
6626
#endif
6627
0
  {
6628
    // Allocate a row of argb.
6629
0
    align_buffer_64(row_argb, width * 4);
6630
0
    if (!row_argb)
6631
0
      return 1;
6632
0
    for (y = 0; y < height; ++y) {
6633
0
      I422ToARGBRow(src_y, src_u, src_v, row_argb, &kYuvI601Constants, width);
6634
0
      ARGBToRGB565DitherRow(row_argb, dst_rgb565,
6635
0
                            *(const uint32_t*)(dither4x4 + ((y & 3) << 2)),
6636
0
                            width);
6637
0
      dst_rgb565 += dst_stride_rgb565;
6638
0
      src_y += src_stride_y;
6639
0
      if (y & 1) {
6640
0
        src_u += src_stride_u;
6641
0
        src_v += src_stride_v;
6642
0
      }
6643
0
    }
6644
0
    free_aligned_buffer_64(row_argb);
6645
0
  }
6646
0
  return 0;
6647
0
}
6648
6649
// Convert I420 to AR30 with matrix.
6650
LIBYUV_API
6651
int I420ToAR30Matrix(const uint8_t* src_y,
6652
                     int src_stride_y,
6653
                     const uint8_t* src_u,
6654
                     int src_stride_u,
6655
                     const uint8_t* src_v,
6656
                     int src_stride_v,
6657
                     uint8_t* dst_ar30,
6658
                     int dst_stride_ar30,
6659
                     const struct YuvConstants* yuvconstants,
6660
                     int width,
6661
0
                     int height) {
6662
0
  int y;
6663
0
  void (*I422ToAR30Row)(const uint8_t* y_buf, const uint8_t* u_buf,
6664
0
                        const uint8_t* v_buf, uint8_t* rgb_buf,
6665
0
                        const struct YuvConstants* yuvconstants, int width) =
6666
0
      I422ToAR30Row_C;
6667
6668
0
  assert(yuvconstants);
6669
0
  if (!src_y || !src_u || !src_v || !dst_ar30 || width <= 0 || height == 0) {
6670
0
    return -1;
6671
0
  }
6672
  // Negative height means invert the image.
6673
0
  if (height < 0) {
6674
0
    height = -height;
6675
0
    dst_ar30 = dst_ar30 + (height - 1) * dst_stride_ar30;
6676
0
    dst_stride_ar30 = -dst_stride_ar30;
6677
0
  }
6678
6679
0
#if defined(HAS_I422TOAR30ROW_SSSE3)
6680
0
  if (TestCpuFlag(kCpuHasSSSE3)) {
6681
0
    I422ToAR30Row = I422ToAR30Row_Any_SSSE3;
6682
0
    if (IS_ALIGNED(width, 8)) {
6683
0
      I422ToAR30Row = I422ToAR30Row_SSSE3;
6684
0
    }
6685
0
  }
6686
0
#endif
6687
0
#if defined(HAS_I422TOAR30ROW_AVX2)
6688
0
  if (TestCpuFlag(kCpuHasAVX2)) {
6689
0
    I422ToAR30Row = I422ToAR30Row_Any_AVX2;
6690
0
    if (IS_ALIGNED(width, 16)) {
6691
0
      I422ToAR30Row = I422ToAR30Row_AVX2;
6692
0
    }
6693
0
  }
6694
0
#endif
6695
#if defined(HAS_I422TOAR30ROW_NEON)
6696
  if (TestCpuFlag(kCpuHasNEON)) {
6697
    I422ToAR30Row = I422ToAR30Row_Any_NEON;
6698
    if (IS_ALIGNED(width, 8)) {
6699
      I422ToAR30Row = I422ToAR30Row_NEON;
6700
    }
6701
  }
6702
#endif
6703
6704
0
  for (y = 0; y < height; ++y) {
6705
0
    I422ToAR30Row(src_y, src_u, src_v, dst_ar30, yuvconstants, width);
6706
0
    dst_ar30 += dst_stride_ar30;
6707
0
    src_y += src_stride_y;
6708
0
    if (y & 1) {
6709
0
      src_u += src_stride_u;
6710
0
      src_v += src_stride_v;
6711
0
    }
6712
0
  }
6713
0
  return 0;
6714
0
}
6715
6716
// Convert I420 to AR30.
6717
LIBYUV_API
6718
int I420ToAR30(const uint8_t* src_y,
6719
               int src_stride_y,
6720
               const uint8_t* src_u,
6721
               int src_stride_u,
6722
               const uint8_t* src_v,
6723
               int src_stride_v,
6724
               uint8_t* dst_ar30,
6725
               int dst_stride_ar30,
6726
               int width,
6727
0
               int height) {
6728
0
  return I420ToAR30Matrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
6729
0
                          src_stride_v, dst_ar30, dst_stride_ar30,
6730
0
                          &kYuvI601Constants, width, height);
6731
0
}
6732
6733
// Convert H420 to AR30.
6734
LIBYUV_API
6735
int H420ToAR30(const uint8_t* src_y,
6736
               int src_stride_y,
6737
               const uint8_t* src_u,
6738
               int src_stride_u,
6739
               const uint8_t* src_v,
6740
               int src_stride_v,
6741
               uint8_t* dst_ar30,
6742
               int dst_stride_ar30,
6743
               int width,
6744
0
               int height) {
6745
0
  return I420ToAR30Matrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
6746
0
                          src_stride_v, dst_ar30, dst_stride_ar30,
6747
0
                          &kYvuH709Constants, width, height);
6748
0
}
6749
6750
// Convert I420 to AB30.
6751
LIBYUV_API
6752
int I420ToAB30(const uint8_t* src_y,
6753
               int src_stride_y,
6754
               const uint8_t* src_u,
6755
               int src_stride_u,
6756
               const uint8_t* src_v,
6757
               int src_stride_v,
6758
               uint8_t* dst_ab30,
6759
               int dst_stride_ab30,
6760
               int width,
6761
0
               int height) {
6762
0
  return I420ToAR30Matrix(src_y, src_stride_y, src_v, src_stride_v, src_u,
6763
0
                          src_stride_u, dst_ab30, dst_stride_ab30,
6764
0
                          &kYvuI601Constants, width, height);
6765
0
}
6766
6767
// Convert H420 to AB30.
6768
LIBYUV_API
6769
int H420ToAB30(const uint8_t* src_y,
6770
               int src_stride_y,
6771
               const uint8_t* src_u,
6772
               int src_stride_u,
6773
               const uint8_t* src_v,
6774
               int src_stride_v,
6775
               uint8_t* dst_ab30,
6776
               int dst_stride_ab30,
6777
               int width,
6778
0
               int height) {
6779
0
  return I420ToAR30Matrix(src_y, src_stride_y, src_v, src_stride_v, src_u,
6780
0
                          src_stride_u, dst_ab30, dst_stride_ab30,
6781
0
                          &kYvuH709Constants, width, height);
6782
0
}
6783
6784
static int I420ToARGBMatrixBilinear(const uint8_t* src_y,
6785
                                    int src_stride_y,
6786
                                    const uint8_t* src_u,
6787
                                    int src_stride_u,
6788
                                    const uint8_t* src_v,
6789
                                    int src_stride_v,
6790
                                    uint8_t* dst_argb,
6791
                                    int dst_stride_argb,
6792
                                    const struct YuvConstants* yuvconstants,
6793
                                    int width,
6794
155
                                    int height) {
6795
155
  int y;
6796
155
  void (*I444ToARGBRow)(const uint8_t* y_buf, const uint8_t* u_buf,
6797
155
                        const uint8_t* v_buf, uint8_t* rgb_buf,
6798
155
                        const struct YuvConstants* yuvconstants, int width) =
6799
155
      I444ToARGBRow_C;
6800
155
  void (*Scale2RowUp_Bilinear)(const uint8_t* src_ptr, ptrdiff_t src_stride,
6801
155
                               uint8_t* dst_ptr, ptrdiff_t dst_stride,
6802
155
                               int dst_width) = ScaleRowUp2_Bilinear_Any_C;
6803
155
  void (*ScaleRowUp2_Linear)(const uint8_t* src_ptr, uint8_t* dst_ptr,
6804
155
                             int dst_width) = ScaleRowUp2_Linear_Any_C;
6805
155
  assert(yuvconstants);
6806
155
  if (!src_y || !src_u || !src_v || !dst_argb || width <= 0 || height == 0) {
6807
0
    return -1;
6808
0
  }
6809
  // Negative height means invert the image.
6810
155
  if (height < 0) {
6811
0
    height = -height;
6812
0
    dst_argb = dst_argb + (height - 1) * dst_stride_argb;
6813
0
    dst_stride_argb = -dst_stride_argb;
6814
0
  }
6815
155
#if defined(HAS_I444TOARGBROW_SSSE3)
6816
155
  if (TestCpuFlag(kCpuHasSSSE3)) {
6817
155
    I444ToARGBRow = I444ToARGBRow_Any_SSSE3;
6818
155
    if (IS_ALIGNED(width, 8)) {
6819
5
      I444ToARGBRow = I444ToARGBRow_SSSE3;
6820
5
    }
6821
155
  }
6822
155
#endif
6823
155
#if defined(HAS_I444TOARGBROW_AVX2)
6824
155
  if (TestCpuFlag(kCpuHasAVX2)) {
6825
155
    I444ToARGBRow = I444ToARGBRow_Any_AVX2;
6826
155
    if (IS_ALIGNED(width, 16)) {
6827
3
      I444ToARGBRow = I444ToARGBRow_AVX2;
6828
3
    }
6829
155
  }
6830
155
#endif
6831
#if defined(HAS_I444TOARGBROW_NEON)
6832
  if (TestCpuFlag(kCpuHasNEON)) {
6833
    I444ToARGBRow = I444ToARGBRow_Any_NEON;
6834
    if (IS_ALIGNED(width, 8)) {
6835
      I444ToARGBRow = I444ToARGBRow_NEON;
6836
    }
6837
  }
6838
#endif
6839
#if defined(HAS_I444TOARGBROW_SVE2)
6840
  if (TestCpuFlag(kCpuHasSVE2)) {
6841
    I444ToARGBRow = I444ToARGBRow_SVE2;
6842
  }
6843
#endif
6844
#if defined(HAS_I444TOARGBROW_SME)
6845
  if (TestCpuFlag(kCpuHasSME)) {
6846
    I444ToARGBRow = I444ToARGBRow_SME;
6847
  }
6848
#endif
6849
#if defined(HAS_I444TOARGBROW_MSA)
6850
  if (TestCpuFlag(kCpuHasMSA)) {
6851
    I444ToARGBRow = I444ToARGBRow_Any_MSA;
6852
    if (IS_ALIGNED(width, 8)) {
6853
      I444ToARGBRow = I444ToARGBRow_MSA;
6854
    }
6855
  }
6856
#endif
6857
#if defined(HAS_I444TOARGBROW_LASX)
6858
  if (TestCpuFlag(kCpuHasLASX)) {
6859
    I444ToARGBRow = I444ToARGBRow_Any_LASX;
6860
    if (IS_ALIGNED(width, 32)) {
6861
      I444ToARGBRow = I444ToARGBRow_LASX;
6862
    }
6863
  }
6864
#endif
6865
#if defined(HAS_I444TOARGBROW_RVV)
6866
  if (TestCpuFlag(kCpuHasRVV)) {
6867
    I444ToARGBRow = I444ToARGBRow_RVV;
6868
  }
6869
#endif
6870
6871
155
#if defined(HAS_SCALEROWUP2_BILINEAR_SSE2)
6872
155
  if (TestCpuFlag(kCpuHasSSE2)) {
6873
155
    Scale2RowUp_Bilinear = ScaleRowUp2_Bilinear_Any_SSE2;
6874
155
    ScaleRowUp2_Linear = ScaleRowUp2_Linear_Any_SSE2;
6875
155
  }
6876
155
#endif
6877
6878
155
#if defined(HAS_SCALEROWUP2_BILINEAR_SSSE3)
6879
155
  if (TestCpuFlag(kCpuHasSSSE3)) {
6880
155
    Scale2RowUp_Bilinear = ScaleRowUp2_Bilinear_Any_SSSE3;
6881
155
    ScaleRowUp2_Linear = ScaleRowUp2_Linear_Any_SSSE3;
6882
155
  }
6883
155
#endif
6884
6885
155
#if defined(HAS_SCALEROWUP2_BILINEAR_AVX2)
6886
155
  if (TestCpuFlag(kCpuHasAVX2)) {
6887
155
    Scale2RowUp_Bilinear = ScaleRowUp2_Bilinear_Any_AVX2;
6888
155
    ScaleRowUp2_Linear = ScaleRowUp2_Linear_Any_AVX2;
6889
155
  }
6890
155
#endif
6891
6892
#if defined(HAS_SCALEROWUP2_BILINEAR_NEON)
6893
  if (TestCpuFlag(kCpuHasNEON)) {
6894
    Scale2RowUp_Bilinear = ScaleRowUp2_Bilinear_Any_NEON;
6895
    ScaleRowUp2_Linear = ScaleRowUp2_Linear_Any_NEON;
6896
  }
6897
#endif
6898
#if defined(HAS_SCALEROWUP2_BILINEAR_RVV)
6899
  if (TestCpuFlag(kCpuHasRVV)) {
6900
    Scale2RowUp_Bilinear = ScaleRowUp2_Bilinear_RVV;
6901
    ScaleRowUp2_Linear = ScaleRowUp2_Linear_RVV;
6902
  }
6903
#endif
6904
6905
  // alloc 4 lines temp
6906
155
  const int row_size = (width + 31) & ~31;
6907
155
  align_buffer_64(row, row_size * 4);
6908
155
  uint8_t* temp_u_1 = row;
6909
155
  uint8_t* temp_u_2 = row + row_size;
6910
155
  uint8_t* temp_v_1 = row + row_size * 2;
6911
155
  uint8_t* temp_v_2 = row + row_size * 3;
6912
155
  if (!row)
6913
0
    return 1;
6914
6915
155
  ScaleRowUp2_Linear(src_u, temp_u_1, width);
6916
155
  ScaleRowUp2_Linear(src_v, temp_v_1, width);
6917
155
  I444ToARGBRow(src_y, temp_u_1, temp_v_1, dst_argb, yuvconstants, width);
6918
155
  dst_argb += dst_stride_argb;
6919
155
  src_y += src_stride_y;
6920
6921
2.91k
  for (y = 0; y < height - 2; y += 2) {
6922
2.76k
    Scale2RowUp_Bilinear(src_u, src_stride_u, temp_u_1, row_size, width);
6923
2.76k
    Scale2RowUp_Bilinear(src_v, src_stride_v, temp_v_1, row_size, width);
6924
2.76k
    I444ToARGBRow(src_y, temp_u_1, temp_v_1, dst_argb, yuvconstants, width);
6925
2.76k
    dst_argb += dst_stride_argb;
6926
2.76k
    src_y += src_stride_y;
6927
2.76k
    I444ToARGBRow(src_y, temp_u_2, temp_v_2, dst_argb, yuvconstants, width);
6928
2.76k
    dst_argb += dst_stride_argb;
6929
2.76k
    src_y += src_stride_y;
6930
2.76k
    src_u += src_stride_u;
6931
2.76k
    src_v += src_stride_v;
6932
2.76k
  }
6933
6934
155
  if (!(height & 1)) {
6935
38
    ScaleRowUp2_Linear(src_u, temp_u_1, width);
6936
38
    ScaleRowUp2_Linear(src_v, temp_v_1, width);
6937
38
    I444ToARGBRow(src_y, temp_u_1, temp_v_1, dst_argb, yuvconstants, width);
6938
38
  }
6939
6940
155
  free_aligned_buffer_64(row);
6941
155
  return 0;
6942
155
}
6943
6944
static int I422ToARGBMatrixLinear(const uint8_t* src_y,
6945
                                  int src_stride_y,
6946
                                  const uint8_t* src_u,
6947
                                  int src_stride_u,
6948
                                  const uint8_t* src_v,
6949
                                  int src_stride_v,
6950
                                  uint8_t* dst_argb,
6951
                                  int dst_stride_argb,
6952
                                  const struct YuvConstants* yuvconstants,
6953
                                  int width,
6954
156
                                  int height) {
6955
156
  int y;
6956
156
  void (*I444ToARGBRow)(const uint8_t* y_buf, const uint8_t* u_buf,
6957
156
                        const uint8_t* v_buf, uint8_t* rgb_buf,
6958
156
                        const struct YuvConstants* yuvconstants, int width) =
6959
156
      I444ToARGBRow_C;
6960
156
  void (*ScaleRowUp2_Linear)(const uint8_t* src_ptr, uint8_t* dst_ptr,
6961
156
                             int dst_width) = ScaleRowUp2_Linear_Any_C;
6962
156
  assert(yuvconstants);
6963
156
  if (!src_y || !src_u || !src_v || !dst_argb || width <= 0 || height == 0) {
6964
0
    return -1;
6965
0
  }
6966
  // Negative height means invert the image.
6967
156
  if (height < 0) {
6968
0
    height = -height;
6969
0
    dst_argb = dst_argb + (height - 1) * dst_stride_argb;
6970
0
    dst_stride_argb = -dst_stride_argb;
6971
0
  }
6972
156
#if defined(HAS_I444TOARGBROW_SSSE3)
6973
156
  if (TestCpuFlag(kCpuHasSSSE3)) {
6974
156
    I444ToARGBRow = I444ToARGBRow_Any_SSSE3;
6975
156
    if (IS_ALIGNED(width, 8)) {
6976
34
      I444ToARGBRow = I444ToARGBRow_SSSE3;
6977
34
    }
6978
156
  }
6979
156
#endif
6980
156
#if defined(HAS_I444TOARGBROW_AVX2)
6981
156
  if (TestCpuFlag(kCpuHasAVX2)) {
6982
156
    I444ToARGBRow = I444ToARGBRow_Any_AVX2;
6983
156
    if (IS_ALIGNED(width, 16)) {
6984
17
      I444ToARGBRow = I444ToARGBRow_AVX2;
6985
17
    }
6986
156
  }
6987
156
#endif
6988
#if defined(HAS_I444TOARGBROW_NEON)
6989
  if (TestCpuFlag(kCpuHasNEON)) {
6990
    I444ToARGBRow = I444ToARGBRow_Any_NEON;
6991
    if (IS_ALIGNED(width, 8)) {
6992
      I444ToARGBRow = I444ToARGBRow_NEON;
6993
    }
6994
  }
6995
#endif
6996
#if defined(HAS_I444TOARGBROW_SVE2)
6997
  if (TestCpuFlag(kCpuHasSVE2)) {
6998
    I444ToARGBRow = I444ToARGBRow_SVE2;
6999
  }
7000
#endif
7001
#if defined(HAS_I444TOARGBROW_SME)
7002
  if (TestCpuFlag(kCpuHasSME)) {
7003
    I444ToARGBRow = I444ToARGBRow_SME;
7004
  }
7005
#endif
7006
#if defined(HAS_I444TOARGBROW_MSA)
7007
  if (TestCpuFlag(kCpuHasMSA)) {
7008
    I444ToARGBRow = I444ToARGBRow_Any_MSA;
7009
    if (IS_ALIGNED(width, 8)) {
7010
      I444ToARGBRow = I444ToARGBRow_MSA;
7011
    }
7012
  }
7013
#endif
7014
#if defined(HAS_I444TOARGBROW_LASX)
7015
  if (TestCpuFlag(kCpuHasLASX)) {
7016
    I444ToARGBRow = I444ToARGBRow_Any_LASX;
7017
    if (IS_ALIGNED(width, 32)) {
7018
      I444ToARGBRow = I444ToARGBRow_LASX;
7019
    }
7020
  }
7021
#endif
7022
#if defined(HAS_I444TOARGBROW_RVV)
7023
  if (TestCpuFlag(kCpuHasRVV)) {
7024
    I444ToARGBRow = I444ToARGBRow_RVV;
7025
  }
7026
#endif
7027
156
#if defined(HAS_SCALEROWUP2_LINEAR_SSE2)
7028
156
  if (TestCpuFlag(kCpuHasSSE2)) {
7029
156
    ScaleRowUp2_Linear = ScaleRowUp2_Linear_Any_SSE2;
7030
156
  }
7031
156
#endif
7032
156
#if defined(HAS_SCALEROWUP2_LINEAR_SSSE3)
7033
156
  if (TestCpuFlag(kCpuHasSSSE3)) {
7034
156
    ScaleRowUp2_Linear = ScaleRowUp2_Linear_Any_SSSE3;
7035
156
  }
7036
156
#endif
7037
156
#if defined(HAS_SCALEROWUP2_LINEAR_AVX2)
7038
156
  if (TestCpuFlag(kCpuHasAVX2)) {
7039
155
    ScaleRowUp2_Linear = ScaleRowUp2_Linear_Any_AVX2;
7040
155
  }
7041
156
#endif
7042
#if defined(HAS_SCALEROWUP2_LINEAR_NEON)
7043
  if (TestCpuFlag(kCpuHasNEON)) {
7044
    ScaleRowUp2_Linear = ScaleRowUp2_Linear_Any_NEON;
7045
  }
7046
#endif
7047
#if defined(HAS_SCALEROWUP2_LINEAR_RVV)
7048
  if (TestCpuFlag(kCpuHasRVV)) {
7049
    ScaleRowUp2_Linear = ScaleRowUp2_Linear_RVV;
7050
  }
7051
#endif
7052
7053
  // alloc 2 lines temp
7054
156
  const int row_size = (width + 31) & ~31;
7055
156
  align_buffer_64(row, row_size * 2);
7056
156
  uint8_t* temp_u = row;
7057
156
  uint8_t* temp_v = row + row_size;
7058
156
  if (!row)
7059
0
    return 1;
7060
7061
7.46k
  for (y = 0; y < height; ++y) {
7062
7.30k
    ScaleRowUp2_Linear(src_u, temp_u, width);
7063
7.30k
    ScaleRowUp2_Linear(src_v, temp_v, width);
7064
7.30k
    I444ToARGBRow(src_y, temp_u, temp_v, dst_argb, yuvconstants, width);
7065
7.30k
    dst_argb += dst_stride_argb;
7066
7.30k
    src_y += src_stride_y;
7067
7.30k
    src_u += src_stride_u;
7068
7.30k
    src_v += src_stride_v;
7069
7.30k
  }
7070
7071
156
  free_aligned_buffer_64(row);
7072
156
  return 0;
7073
156
}
7074
7075
static int I420ToRGB24MatrixBilinear(const uint8_t* src_y,
7076
                                     int src_stride_y,
7077
                                     const uint8_t* src_u,
7078
                                     int src_stride_u,
7079
                                     const uint8_t* src_v,
7080
                                     int src_stride_v,
7081
                                     uint8_t* dst_rgb24,
7082
                                     int dst_stride_rgb24,
7083
                                     const struct YuvConstants* yuvconstants,
7084
                                     int width,
7085
88
                                     int height) {
7086
88
  int y;
7087
88
  void (*I444ToRGB24Row)(const uint8_t* y_buf, const uint8_t* u_buf,
7088
88
                         const uint8_t* v_buf, uint8_t* rgb_buf,
7089
88
                         const struct YuvConstants* yuvconstants, int width) =
7090
88
      I444ToRGB24Row_C;
7091
88
  void (*Scale2RowUp_Bilinear)(const uint8_t* src_ptr, ptrdiff_t src_stride,
7092
88
                               uint8_t* dst_ptr, ptrdiff_t dst_stride,
7093
88
                               int dst_width) = ScaleRowUp2_Bilinear_Any_C;
7094
88
  void (*ScaleRowUp2_Linear)(const uint8_t* src_ptr, uint8_t* dst_ptr,
7095
88
                             int dst_width) = ScaleRowUp2_Linear_Any_C;
7096
88
  assert(yuvconstants);
7097
88
  if (!src_y || !src_u || !src_v || !dst_rgb24 || width <= 0 || height == 0) {
7098
0
    return -1;
7099
0
  }
7100
  // Negative height means invert the image.
7101
88
  if (height < 0) {
7102
0
    height = -height;
7103
0
    dst_rgb24 = dst_rgb24 + (height - 1) * dst_stride_rgb24;
7104
0
    dst_stride_rgb24 = -dst_stride_rgb24;
7105
0
  }
7106
88
#if defined(HAS_I444TORGB24ROW_SSSE3)
7107
88
  if (TestCpuFlag(kCpuHasSSSE3)) {
7108
88
    I444ToRGB24Row = I444ToRGB24Row_Any_SSSE3;
7109
88
    if (IS_ALIGNED(width, 16)) {
7110
7
      I444ToRGB24Row = I444ToRGB24Row_SSSE3;
7111
7
    }
7112
88
  }
7113
88
#endif
7114
88
#if defined(HAS_I444TORGB24ROW_AVX2)
7115
88
  if (TestCpuFlag(kCpuHasAVX2)) {
7116
88
    I444ToRGB24Row = I444ToRGB24Row_Any_AVX2;
7117
88
    if (IS_ALIGNED(width, 32)) {
7118
5
      I444ToRGB24Row = I444ToRGB24Row_AVX2;
7119
5
    }
7120
88
  }
7121
88
#endif
7122
#if defined(HAS_I444TORGB24ROW_NEON)
7123
  if (TestCpuFlag(kCpuHasNEON)) {
7124
    I444ToRGB24Row = I444ToRGB24Row_Any_NEON;
7125
    if (IS_ALIGNED(width, 8)) {
7126
      I444ToRGB24Row = I444ToRGB24Row_NEON;
7127
    }
7128
  }
7129
#endif
7130
#if defined(HAS_I444TORGB24ROW_MSA)
7131
  if (TestCpuFlag(kCpuHasMSA)) {
7132
    I444ToRGB24Row = I444ToRGB24Row_Any_MSA;
7133
    if (IS_ALIGNED(width, 8)) {
7134
      I444ToRGB24Row = I444ToRGB24Row_MSA;
7135
    }
7136
  }
7137
#endif
7138
#if defined(HAS_I444TORGB24ROW_LASX)
7139
  if (TestCpuFlag(kCpuHasLASX)) {
7140
    I444ToRGB24Row = I444ToRGB24Row_Any_LASX;
7141
    if (IS_ALIGNED(width, 32)) {
7142
      I444ToRGB24Row = I444ToRGB24Row_LASX;
7143
    }
7144
  }
7145
#endif
7146
#if defined(HAS_I444TORGB24ROW_RVV)
7147
  if (TestCpuFlag(kCpuHasRVV)) {
7148
    I444ToRGB24Row = I444ToRGB24Row_RVV;
7149
  }
7150
#endif
7151
7152
88
#if defined(HAS_SCALEROWUP2_BILINEAR_SSE2)
7153
88
  if (TestCpuFlag(kCpuHasSSE2)) {
7154
88
    Scale2RowUp_Bilinear = ScaleRowUp2_Bilinear_Any_SSE2;
7155
88
    ScaleRowUp2_Linear = ScaleRowUp2_Linear_Any_SSE2;
7156
88
  }
7157
88
#endif
7158
7159
88
#if defined(HAS_SCALEROWUP2_BILINEAR_SSSE3)
7160
88
  if (TestCpuFlag(kCpuHasSSSE3)) {
7161
88
    Scale2RowUp_Bilinear = ScaleRowUp2_Bilinear_Any_SSSE3;
7162
88
    ScaleRowUp2_Linear = ScaleRowUp2_Linear_Any_SSSE3;
7163
88
  }
7164
88
#endif
7165
7166
88
#if defined(HAS_SCALEROWUP2_BILINEAR_AVX2)
7167
88
  if (TestCpuFlag(kCpuHasAVX2)) {
7168
88
    Scale2RowUp_Bilinear = ScaleRowUp2_Bilinear_Any_AVX2;
7169
88
    ScaleRowUp2_Linear = ScaleRowUp2_Linear_Any_AVX2;
7170
88
  }
7171
88
#endif
7172
7173
#if defined(HAS_SCALEROWUP2_BILINEAR_NEON)
7174
  if (TestCpuFlag(kCpuHasNEON)) {
7175
    Scale2RowUp_Bilinear = ScaleRowUp2_Bilinear_Any_NEON;
7176
    ScaleRowUp2_Linear = ScaleRowUp2_Linear_Any_NEON;
7177
  }
7178
#endif
7179
#if defined(HAS_SCALEROWUP2_BILINEAR_RVV)
7180
  if (TestCpuFlag(kCpuHasRVV)) {
7181
    Scale2RowUp_Bilinear = ScaleRowUp2_Bilinear_RVV;
7182
    ScaleRowUp2_Linear = ScaleRowUp2_Linear_RVV;
7183
  }
7184
#endif
7185
7186
  // alloc 4 lines temp
7187
88
  const int row_size = (width + 31) & ~31;
7188
88
  align_buffer_64(row, row_size * 4);
7189
88
  uint8_t* temp_u_1 = row;
7190
88
  uint8_t* temp_u_2 = row + row_size;
7191
88
  uint8_t* temp_v_1 = row + row_size * 2;
7192
88
  uint8_t* temp_v_2 = row + row_size * 3;
7193
88
  if (!row)
7194
0
    return 1;
7195
7196
88
  ScaleRowUp2_Linear(src_u, temp_u_1, width);
7197
88
  ScaleRowUp2_Linear(src_v, temp_v_1, width);
7198
88
  I444ToRGB24Row(src_y, temp_u_1, temp_v_1, dst_rgb24, yuvconstants, width);
7199
88
  dst_rgb24 += dst_stride_rgb24;
7200
88
  src_y += src_stride_y;
7201
7202
1.81k
  for (y = 0; y < height - 2; y += 2) {
7203
1.72k
    Scale2RowUp_Bilinear(src_u, src_stride_u, temp_u_1, row_size, width);
7204
1.72k
    Scale2RowUp_Bilinear(src_v, src_stride_v, temp_v_1, row_size, width);
7205
1.72k
    I444ToRGB24Row(src_y, temp_u_1, temp_v_1, dst_rgb24, yuvconstants, width);
7206
1.72k
    dst_rgb24 += dst_stride_rgb24;
7207
1.72k
    src_y += src_stride_y;
7208
1.72k
    I444ToRGB24Row(src_y, temp_u_2, temp_v_2, dst_rgb24, yuvconstants, width);
7209
1.72k
    dst_rgb24 += dst_stride_rgb24;
7210
1.72k
    src_y += src_stride_y;
7211
1.72k
    src_u += src_stride_u;
7212
1.72k
    src_v += src_stride_v;
7213
1.72k
  }
7214
7215
88
  if (!(height & 1)) {
7216
24
    ScaleRowUp2_Linear(src_u, temp_u_1, width);
7217
24
    ScaleRowUp2_Linear(src_v, temp_v_1, width);
7218
24
    I444ToRGB24Row(src_y, temp_u_1, temp_v_1, dst_rgb24, yuvconstants, width);
7219
24
  }
7220
7221
88
  free_aligned_buffer_64(row);
7222
88
  return 0;
7223
88
}
7224
7225
static int I010ToAR30MatrixBilinear(const uint16_t* src_y,
7226
                                    int src_stride_y,
7227
                                    const uint16_t* src_u,
7228
                                    int src_stride_u,
7229
                                    const uint16_t* src_v,
7230
                                    int src_stride_v,
7231
                                    uint8_t* dst_ar30,
7232
                                    int dst_stride_ar30,
7233
                                    const struct YuvConstants* yuvconstants,
7234
                                    int width,
7235
0
                                    int height) {
7236
0
  int y;
7237
0
  void (*I410ToAR30Row)(const uint16_t* y_buf, const uint16_t* u_buf,
7238
0
                        const uint16_t* v_buf, uint8_t* rgb_buf,
7239
0
                        const struct YuvConstants* yuvconstants, int width) =
7240
0
      I410ToAR30Row_C;
7241
0
  void (*Scale2RowUp_Bilinear_12)(
7242
0
      const uint16_t* src_ptr, ptrdiff_t src_stride, uint16_t* dst_ptr,
7243
0
      ptrdiff_t dst_stride, int dst_width) = ScaleRowUp2_Bilinear_16_Any_C;
7244
0
  void (*ScaleRowUp2_Linear_12)(const uint16_t* src_ptr, uint16_t* dst_ptr,
7245
0
                                int dst_width) = ScaleRowUp2_Linear_16_Any_C;
7246
0
  assert(yuvconstants);
7247
0
  if (!src_y || !src_u || !src_v || !dst_ar30 || width <= 0 || height == 0) {
7248
0
    return -1;
7249
0
  }
7250
  // Negative height means invert the image.
7251
0
  if (height < 0) {
7252
0
    height = -height;
7253
0
    dst_ar30 = dst_ar30 + (height - 1) * dst_stride_ar30;
7254
0
    dst_stride_ar30 = -dst_stride_ar30;
7255
0
  }
7256
#if defined(HAS_I410TOAR30ROW_NEON)
7257
  if (TestCpuFlag(kCpuHasNEON)) {
7258
    I410ToAR30Row = I410ToAR30Row_Any_NEON;
7259
    if (IS_ALIGNED(width, 8)) {
7260
      I410ToAR30Row = I410ToAR30Row_NEON;
7261
    }
7262
  }
7263
#endif
7264
#if defined(HAS_I410TOAR30ROW_SVE2)
7265
  if (TestCpuFlag(kCpuHasSVE2)) {
7266
    I410ToAR30Row = I410ToAR30Row_SVE2;
7267
  }
7268
#endif
7269
#if defined(HAS_I410TOAR30ROW_SME)
7270
  if (TestCpuFlag(kCpuHasSME)) {
7271
    I410ToAR30Row = I410ToAR30Row_SME;
7272
  }
7273
#endif
7274
0
#if defined(HAS_I410TOAR30ROW_SSSE3)
7275
0
  if (TestCpuFlag(kCpuHasSSSE3)) {
7276
0
    I410ToAR30Row = I410ToAR30Row_Any_SSSE3;
7277
0
    if (IS_ALIGNED(width, 8)) {
7278
0
      I410ToAR30Row = I410ToAR30Row_SSSE3;
7279
0
    }
7280
0
  }
7281
0
#endif
7282
0
#if defined(HAS_I410TOAR30ROW_AVX2)
7283
0
  if (TestCpuFlag(kCpuHasAVX2)) {
7284
0
    I410ToAR30Row = I410ToAR30Row_Any_AVX2;
7285
0
    if (IS_ALIGNED(width, 16)) {
7286
0
      I410ToAR30Row = I410ToAR30Row_AVX2;
7287
0
    }
7288
0
  }
7289
0
#endif
7290
7291
0
#if defined(HAS_SCALEROWUP2_BILINEAR_12_SSSE3)
7292
0
  if (TestCpuFlag(kCpuHasSSSE3)) {
7293
0
    Scale2RowUp_Bilinear_12 = ScaleRowUp2_Bilinear_12_Any_SSSE3;
7294
0
    ScaleRowUp2_Linear_12 = ScaleRowUp2_Linear_12_Any_SSSE3;
7295
0
  }
7296
0
#endif
7297
7298
0
#if defined(HAS_SCALEROWUP2_BILINEAR_12_AVX2)
7299
0
  if (TestCpuFlag(kCpuHasAVX2)) {
7300
0
    Scale2RowUp_Bilinear_12 = ScaleRowUp2_Bilinear_12_Any_AVX2;
7301
0
    ScaleRowUp2_Linear_12 = ScaleRowUp2_Linear_12_Any_AVX2;
7302
0
  }
7303
0
#endif
7304
7305
#if defined(HAS_SCALEROWUP2_BILINEAR_12_NEON)
7306
  if (TestCpuFlag(kCpuHasNEON)) {
7307
    Scale2RowUp_Bilinear_12 = ScaleRowUp2_Bilinear_12_Any_NEON;
7308
    ScaleRowUp2_Linear_12 = ScaleRowUp2_Linear_12_Any_NEON;
7309
  }
7310
#endif
7311
7312
  // alloc 4 lines temp
7313
0
  const int row_size = (width + 31) & ~31;
7314
0
  align_buffer_64(row, row_size * 4 * sizeof(uint16_t));
7315
0
  uint16_t* temp_u_1 = (uint16_t*)(row);
7316
0
  uint16_t* temp_u_2 = (uint16_t*)(row) + row_size;
7317
0
  uint16_t* temp_v_1 = (uint16_t*)(row) + row_size * 2;
7318
0
  uint16_t* temp_v_2 = (uint16_t*)(row) + row_size * 3;
7319
0
  if (!row)
7320
0
    return 1;
7321
7322
0
  ScaleRowUp2_Linear_12(src_u, temp_u_1, width);
7323
0
  ScaleRowUp2_Linear_12(src_v, temp_v_1, width);
7324
0
  I410ToAR30Row(src_y, temp_u_1, temp_v_1, dst_ar30, yuvconstants, width);
7325
0
  dst_ar30 += dst_stride_ar30;
7326
0
  src_y += src_stride_y;
7327
7328
0
  for (y = 0; y < height - 2; y += 2) {
7329
0
    Scale2RowUp_Bilinear_12(src_u, src_stride_u, temp_u_1, row_size, width);
7330
0
    Scale2RowUp_Bilinear_12(src_v, src_stride_v, temp_v_1, row_size, width);
7331
0
    I410ToAR30Row(src_y, temp_u_1, temp_v_1, dst_ar30, yuvconstants, width);
7332
0
    dst_ar30 += dst_stride_ar30;
7333
0
    src_y += src_stride_y;
7334
0
    I410ToAR30Row(src_y, temp_u_2, temp_v_2, dst_ar30, yuvconstants, width);
7335
0
    dst_ar30 += dst_stride_ar30;
7336
0
    src_y += src_stride_y;
7337
0
    src_u += src_stride_u;
7338
0
    src_v += src_stride_v;
7339
0
  }
7340
7341
0
  if (!(height & 1)) {
7342
0
    ScaleRowUp2_Linear_12(src_u, temp_u_1, width);
7343
0
    ScaleRowUp2_Linear_12(src_v, temp_v_1, width);
7344
0
    I410ToAR30Row(src_y, temp_u_1, temp_v_1, dst_ar30, yuvconstants, width);
7345
0
  }
7346
7347
0
  free_aligned_buffer_64(row);
7348
7349
0
  return 0;
7350
0
}
7351
7352
static int I210ToAR30MatrixLinear(const uint16_t* src_y,
7353
                                  int src_stride_y,
7354
                                  const uint16_t* src_u,
7355
                                  int src_stride_u,
7356
                                  const uint16_t* src_v,
7357
                                  int src_stride_v,
7358
                                  uint8_t* dst_ar30,
7359
                                  int dst_stride_ar30,
7360
                                  const struct YuvConstants* yuvconstants,
7361
                                  int width,
7362
0
                                  int height) {
7363
0
  int y;
7364
0
  void (*I410ToAR30Row)(const uint16_t* y_buf, const uint16_t* u_buf,
7365
0
                        const uint16_t* v_buf, uint8_t* rgb_buf,
7366
0
                        const struct YuvConstants* yuvconstants, int width) =
7367
0
      I410ToAR30Row_C;
7368
0
  void (*ScaleRowUp2_Linear_12)(const uint16_t* src_ptr, uint16_t* dst_ptr,
7369
0
                                int dst_width) = ScaleRowUp2_Linear_16_Any_C;
7370
0
  assert(yuvconstants);
7371
0
  if (!src_y || !src_u || !src_v || !dst_ar30 || width <= 0 || height == 0) {
7372
0
    return -1;
7373
0
  }
7374
  // Negative height means invert the image.
7375
0
  if (height < 0) {
7376
0
    height = -height;
7377
0
    dst_ar30 = dst_ar30 + (height - 1) * dst_stride_ar30;
7378
0
    dst_stride_ar30 = -dst_stride_ar30;
7379
0
  }
7380
#if defined(HAS_I410TOAR30ROW_NEON)
7381
  if (TestCpuFlag(kCpuHasNEON)) {
7382
    I410ToAR30Row = I410ToAR30Row_Any_NEON;
7383
    if (IS_ALIGNED(width, 8)) {
7384
      I410ToAR30Row = I410ToAR30Row_NEON;
7385
    }
7386
  }
7387
#endif
7388
#if defined(HAS_I410TOAR30ROW_SVE2)
7389
  if (TestCpuFlag(kCpuHasSVE2)) {
7390
    I410ToAR30Row = I410ToAR30Row_SVE2;
7391
  }
7392
#endif
7393
#if defined(HAS_I410TOAR30ROW_SME)
7394
  if (TestCpuFlag(kCpuHasSME)) {
7395
    I410ToAR30Row = I410ToAR30Row_SME;
7396
  }
7397
#endif
7398
0
#if defined(HAS_I410TOAR30ROW_SSSE3)
7399
0
  if (TestCpuFlag(kCpuHasSSSE3)) {
7400
0
    I410ToAR30Row = I410ToAR30Row_Any_SSSE3;
7401
0
    if (IS_ALIGNED(width, 8)) {
7402
0
      I410ToAR30Row = I410ToAR30Row_SSSE3;
7403
0
    }
7404
0
  }
7405
0
#endif
7406
0
#if defined(HAS_I410TOAR30ROW_AVX2)
7407
0
  if (TestCpuFlag(kCpuHasAVX2)) {
7408
0
    I410ToAR30Row = I410ToAR30Row_Any_AVX2;
7409
0
    if (IS_ALIGNED(width, 16)) {
7410
0
      I410ToAR30Row = I410ToAR30Row_AVX2;
7411
0
    }
7412
0
  }
7413
0
#endif
7414
7415
0
#if defined(HAS_SCALEROWUP2_LINEAR_12_SSSE3)
7416
0
  if (TestCpuFlag(kCpuHasSSSE3)) {
7417
0
    ScaleRowUp2_Linear_12 = ScaleRowUp2_Linear_12_Any_SSSE3;
7418
0
  }
7419
0
#endif
7420
0
#if defined(HAS_SCALEROWUP2_LINEAR_12_AVX2)
7421
0
  if (TestCpuFlag(kCpuHasAVX2)) {
7422
0
    ScaleRowUp2_Linear_12 = ScaleRowUp2_Linear_12_Any_AVX2;
7423
0
  }
7424
0
#endif
7425
#if defined(HAS_SCALEROWUP2_LINEAR_12_NEON)
7426
  if (TestCpuFlag(kCpuHasNEON)) {
7427
    ScaleRowUp2_Linear_12 = ScaleRowUp2_Linear_12_Any_NEON;
7428
  }
7429
#endif
7430
7431
  // alloc 2 lines temp
7432
0
  const int row_size = (width + 31) & ~31;
7433
0
  align_buffer_64(row, row_size * 2 * sizeof(uint16_t));
7434
0
  uint16_t* temp_u = (uint16_t*)(row);
7435
0
  uint16_t* temp_v = (uint16_t*)(row) + row_size;
7436
0
  if (!row)
7437
0
    return 1;
7438
7439
0
  for (y = 0; y < height; ++y) {
7440
0
    ScaleRowUp2_Linear_12(src_u, temp_u, width);
7441
0
    ScaleRowUp2_Linear_12(src_v, temp_v, width);
7442
0
    I410ToAR30Row(src_y, temp_u, temp_v, dst_ar30, yuvconstants, width);
7443
0
    dst_ar30 += dst_stride_ar30;
7444
0
    src_y += src_stride_y;
7445
0
    src_u += src_stride_u;
7446
0
    src_v += src_stride_v;
7447
0
  }
7448
0
  free_aligned_buffer_64(row);
7449
0
  return 0;
7450
0
}
7451
7452
static int I010ToARGBMatrixBilinear(const uint16_t* src_y,
7453
                                    int src_stride_y,
7454
                                    const uint16_t* src_u,
7455
                                    int src_stride_u,
7456
                                    const uint16_t* src_v,
7457
                                    int src_stride_v,
7458
                                    uint8_t* dst_argb,
7459
                                    int dst_stride_argb,
7460
                                    const struct YuvConstants* yuvconstants,
7461
                                    int width,
7462
89
                                    int height) {
7463
89
  int y;
7464
89
  void (*I410ToARGBRow)(const uint16_t* y_buf, const uint16_t* u_buf,
7465
89
                        const uint16_t* v_buf, uint8_t* rgb_buf,
7466
89
                        const struct YuvConstants* yuvconstants, int width) =
7467
89
      I410ToARGBRow_C;
7468
89
  void (*Scale2RowUp_Bilinear_12)(
7469
89
      const uint16_t* src_ptr, ptrdiff_t src_stride, uint16_t* dst_ptr,
7470
89
      ptrdiff_t dst_stride, int dst_width) = ScaleRowUp2_Bilinear_16_Any_C;
7471
89
  void (*ScaleRowUp2_Linear_12)(const uint16_t* src_ptr, uint16_t* dst_ptr,
7472
89
                                int dst_width) = ScaleRowUp2_Linear_16_Any_C;
7473
89
  assert(yuvconstants);
7474
89
  if (!src_y || !src_u || !src_v || !dst_argb || width <= 0 || height == 0) {
7475
0
    return -1;
7476
0
  }
7477
  // Negative height means invert the image.
7478
89
  if (height < 0) {
7479
0
    height = -height;
7480
0
    dst_argb = dst_argb + (height - 1) * dst_stride_argb;
7481
0
    dst_stride_argb = -dst_stride_argb;
7482
0
  }
7483
89
#if defined(HAS_I410TOARGBROW_SSSE3)
7484
89
  if (TestCpuFlag(kCpuHasSSSE3)) {
7485
89
    I410ToARGBRow = I410ToARGBRow_Any_SSSE3;
7486
89
    if (IS_ALIGNED(width, 8)) {
7487
5
      I410ToARGBRow = I410ToARGBRow_SSSE3;
7488
5
    }
7489
89
  }
7490
89
#endif
7491
#if defined(HAS_I410TOARGBROW_NEON)
7492
  if (TestCpuFlag(kCpuHasNEON)) {
7493
    I410ToARGBRow = I410ToARGBRow_Any_NEON;
7494
    if (IS_ALIGNED(width, 8)) {
7495
      I410ToARGBRow = I410ToARGBRow_NEON;
7496
    }
7497
  }
7498
#endif
7499
#if defined(HAS_I410TOARGBROW_SVE2)
7500
  if (TestCpuFlag(kCpuHasSVE2)) {
7501
    I410ToARGBRow = I410ToARGBRow_SVE2;
7502
  }
7503
#endif
7504
#if defined(HAS_I410TOARGBROW_SME)
7505
  if (TestCpuFlag(kCpuHasSME)) {
7506
    I410ToARGBRow = I410ToARGBRow_SME;
7507
  }
7508
#endif
7509
89
#if defined(HAS_I410TOARGBROW_AVX2)
7510
89
  if (TestCpuFlag(kCpuHasAVX2)) {
7511
89
    I410ToARGBRow = I410ToARGBRow_Any_AVX2;
7512
89
    if (IS_ALIGNED(width, 16)) {
7513
3
      I410ToARGBRow = I410ToARGBRow_AVX2;
7514
3
    }
7515
89
  }
7516
89
#endif
7517
7518
89
#if defined(HAS_SCALEROWUP2_BILINEAR_12_SSSE3)
7519
89
  if (TestCpuFlag(kCpuHasSSSE3)) {
7520
89
    Scale2RowUp_Bilinear_12 = ScaleRowUp2_Bilinear_12_Any_SSSE3;
7521
89
    ScaleRowUp2_Linear_12 = ScaleRowUp2_Linear_12_Any_SSSE3;
7522
89
  }
7523
89
#endif
7524
7525
89
#if defined(HAS_SCALEROWUP2_BILINEAR_12_AVX2)
7526
89
  if (TestCpuFlag(kCpuHasAVX2)) {
7527
89
    Scale2RowUp_Bilinear_12 = ScaleRowUp2_Bilinear_12_Any_AVX2;
7528
89
    ScaleRowUp2_Linear_12 = ScaleRowUp2_Linear_12_Any_AVX2;
7529
89
  }
7530
89
#endif
7531
7532
#if defined(HAS_SCALEROWUP2_BILINEAR_12_NEON)
7533
  if (TestCpuFlag(kCpuHasNEON)) {
7534
    Scale2RowUp_Bilinear_12 = ScaleRowUp2_Bilinear_12_Any_NEON;
7535
    ScaleRowUp2_Linear_12 = ScaleRowUp2_Linear_12_Any_NEON;
7536
  }
7537
#endif
7538
7539
  // alloc 4 lines temp
7540
89
  const int row_size = (width + 31) & ~31;
7541
89
  align_buffer_64(row, row_size * 4 * sizeof(uint16_t));
7542
89
  uint16_t* temp_u_1 = (uint16_t*)(row);
7543
89
  uint16_t* temp_u_2 = (uint16_t*)(row) + row_size;
7544
89
  uint16_t* temp_v_1 = (uint16_t*)(row) + row_size * 2;
7545
89
  uint16_t* temp_v_2 = (uint16_t*)(row) + row_size * 3;
7546
89
  if (!row)
7547
0
    return 1;
7548
7549
89
  ScaleRowUp2_Linear_12(src_u, temp_u_1, width);
7550
89
  ScaleRowUp2_Linear_12(src_v, temp_v_1, width);
7551
89
  I410ToARGBRow(src_y, temp_u_1, temp_v_1, dst_argb, yuvconstants, width);
7552
89
  dst_argb += dst_stride_argb;
7553
89
  src_y += src_stride_y;
7554
7555
1.53k
  for (y = 0; y < height - 2; y += 2) {
7556
1.44k
    Scale2RowUp_Bilinear_12(src_u, src_stride_u, temp_u_1, row_size, width);
7557
1.44k
    Scale2RowUp_Bilinear_12(src_v, src_stride_v, temp_v_1, row_size, width);
7558
1.44k
    I410ToARGBRow(src_y, temp_u_1, temp_v_1, dst_argb, yuvconstants, width);
7559
1.44k
    dst_argb += dst_stride_argb;
7560
1.44k
    src_y += src_stride_y;
7561
1.44k
    I410ToARGBRow(src_y, temp_u_2, temp_v_2, dst_argb, yuvconstants, width);
7562
1.44k
    dst_argb += dst_stride_argb;
7563
1.44k
    src_y += src_stride_y;
7564
1.44k
    src_u += src_stride_u;
7565
1.44k
    src_v += src_stride_v;
7566
1.44k
  }
7567
7568
89
  if (!(height & 1)) {
7569
22
    ScaleRowUp2_Linear_12(src_u, temp_u_1, width);
7570
22
    ScaleRowUp2_Linear_12(src_v, temp_v_1, width);
7571
22
    I410ToARGBRow(src_y, temp_u_1, temp_v_1, dst_argb, yuvconstants, width);
7572
22
  }
7573
7574
89
  free_aligned_buffer_64(row);
7575
89
  return 0;
7576
89
}
7577
7578
static int I210ToARGBMatrixLinear(const uint16_t* src_y,
7579
                                  int src_stride_y,
7580
                                  const uint16_t* src_u,
7581
                                  int src_stride_u,
7582
                                  const uint16_t* src_v,
7583
                                  int src_stride_v,
7584
                                  uint8_t* dst_argb,
7585
                                  int dst_stride_argb,
7586
                                  const struct YuvConstants* yuvconstants,
7587
                                  int width,
7588
175
                                  int height) {
7589
175
  int y;
7590
175
  void (*I410ToARGBRow)(const uint16_t* y_buf, const uint16_t* u_buf,
7591
175
                        const uint16_t* v_buf, uint8_t* rgb_buf,
7592
175
                        const struct YuvConstants* yuvconstants, int width) =
7593
175
      I410ToARGBRow_C;
7594
175
  void (*ScaleRowUp2_Linear_12)(const uint16_t* src_ptr, uint16_t* dst_ptr,
7595
175
                                int dst_width) = ScaleRowUp2_Linear_16_Any_C;
7596
175
  assert(yuvconstants);
7597
175
  if (!src_y || !src_u || !src_v || !dst_argb || width <= 0 || height == 0) {
7598
0
    return -1;
7599
0
  }
7600
  // Negative height means invert the image.
7601
175
  if (height < 0) {
7602
0
    height = -height;
7603
0
    dst_argb = dst_argb + (height - 1) * dst_stride_argb;
7604
0
    dst_stride_argb = -dst_stride_argb;
7605
0
  }
7606
175
#if defined(HAS_I410TOARGBROW_SSSE3)
7607
175
  if (TestCpuFlag(kCpuHasSSSE3)) {
7608
175
    I410ToARGBRow = I410ToARGBRow_Any_SSSE3;
7609
175
    if (IS_ALIGNED(width, 8)) {
7610
34
      I410ToARGBRow = I410ToARGBRow_SSSE3;
7611
34
    }
7612
175
  }
7613
175
#endif
7614
#if defined(HAS_I410TOARGBROW_NEON)
7615
  if (TestCpuFlag(kCpuHasNEON)) {
7616
    I410ToARGBRow = I410ToARGBRow_Any_NEON;
7617
    if (IS_ALIGNED(width, 8)) {
7618
      I410ToARGBRow = I410ToARGBRow_NEON;
7619
    }
7620
  }
7621
#endif
7622
#if defined(HAS_I410TOARGBROW_SVE2)
7623
  if (TestCpuFlag(kCpuHasSVE2)) {
7624
    I410ToARGBRow = I410ToARGBRow_SVE2;
7625
  }
7626
#endif
7627
#if defined(HAS_I410TOARGBROW_SME)
7628
  if (TestCpuFlag(kCpuHasSME)) {
7629
    I410ToARGBRow = I410ToARGBRow_SME;
7630
  }
7631
#endif
7632
175
#if defined(HAS_I410TOARGBROW_AVX2)
7633
175
  if (TestCpuFlag(kCpuHasAVX2)) {
7634
175
    I410ToARGBRow = I410ToARGBRow_Any_AVX2;
7635
175
    if (IS_ALIGNED(width, 16)) {
7636
17
      I410ToARGBRow = I410ToARGBRow_AVX2;
7637
17
    }
7638
175
  }
7639
175
#endif
7640
7641
175
#if defined(HAS_SCALEROWUP2_LINEAR_12_SSSE3)
7642
175
  if (TestCpuFlag(kCpuHasSSSE3)) {
7643
175
    ScaleRowUp2_Linear_12 = ScaleRowUp2_Linear_12_Any_SSSE3;
7644
175
  }
7645
175
#endif
7646
175
#if defined(HAS_SCALEROWUP2_LINEAR_12_AVX2)
7647
175
  if (TestCpuFlag(kCpuHasAVX2)) {
7648
175
    ScaleRowUp2_Linear_12 = ScaleRowUp2_Linear_12_Any_AVX2;
7649
175
  }
7650
175
#endif
7651
#if defined(HAS_SCALEROWUP2_LINEAR_12_NEON)
7652
  if (TestCpuFlag(kCpuHasNEON)) {
7653
    ScaleRowUp2_Linear_12 = ScaleRowUp2_Linear_12_Any_NEON;
7654
  }
7655
#endif
7656
7657
  // alloc 2 lines temp
7658
175
  const int row_size = (width + 31) & ~31;
7659
175
  align_buffer_64(row, row_size * 2 * sizeof(uint16_t));
7660
175
  uint16_t* temp_u = (uint16_t*)(row);
7661
175
  uint16_t* temp_v = (uint16_t*)(row) + row_size;
7662
175
  if (!row)
7663
0
    return 1;
7664
7665
3.57k
  for (y = 0; y < height; ++y) {
7666
3.39k
    ScaleRowUp2_Linear_12(src_u, temp_u, width);
7667
3.39k
    ScaleRowUp2_Linear_12(src_v, temp_v, width);
7668
3.39k
    I410ToARGBRow(src_y, temp_u, temp_v, dst_argb, yuvconstants, width);
7669
3.39k
    dst_argb += dst_stride_argb;
7670
3.39k
    src_y += src_stride_y;
7671
3.39k
    src_u += src_stride_u;
7672
3.39k
    src_v += src_stride_v;
7673
3.39k
  }
7674
7675
175
  free_aligned_buffer_64(row);
7676
175
  return 0;
7677
175
}
7678
7679
static int I420AlphaToARGBMatrixBilinear(
7680
    const uint8_t* src_y,
7681
    int src_stride_y,
7682
    const uint8_t* src_u,
7683
    int src_stride_u,
7684
    const uint8_t* src_v,
7685
    int src_stride_v,
7686
    const uint8_t* src_a,
7687
    int src_stride_a,
7688
    uint8_t* dst_argb,
7689
    int dst_stride_argb,
7690
    const struct YuvConstants* yuvconstants,
7691
    int width,
7692
    int height,
7693
48
    int attenuate) {
7694
48
  int y;
7695
48
  void (*I444AlphaToARGBRow)(const uint8_t* y_buf, const uint8_t* u_buf,
7696
48
                             const uint8_t* v_buf, const uint8_t* a_buf,
7697
48
                             uint8_t* dst_argb,
7698
48
                             const struct YuvConstants* yuvconstants,
7699
48
                             int width) = I444AlphaToARGBRow_C;
7700
48
  void (*ARGBAttenuateRow)(const uint8_t* src_argb, uint8_t* dst_argb,
7701
48
                           int width) = ARGBAttenuateRow_C;
7702
48
  void (*Scale2RowUp_Bilinear)(const uint8_t* src_ptr, ptrdiff_t src_stride,
7703
48
                               uint8_t* dst_ptr, ptrdiff_t dst_stride,
7704
48
                               int dst_width) = ScaleRowUp2_Bilinear_Any_C;
7705
48
  void (*ScaleRowUp2_Linear)(const uint8_t* src_ptr, uint8_t* dst_ptr,
7706
48
                             int dst_width) = ScaleRowUp2_Linear_Any_C;
7707
48
  assert(yuvconstants);
7708
48
  if (!src_y || !src_u || !src_v || !src_a || !dst_argb || width <= 0 ||
7709
48
      height == 0) {
7710
0
    return -1;
7711
0
  }
7712
  // Negative height means invert the image.
7713
48
  if (height < 0) {
7714
0
    height = -height;
7715
0
    dst_argb = dst_argb + (height - 1) * dst_stride_argb;
7716
0
    dst_stride_argb = -dst_stride_argb;
7717
0
  }
7718
48
#if defined(HAS_I444ALPHATOARGBROW_SSSE3)
7719
48
  if (TestCpuFlag(kCpuHasSSSE3)) {
7720
48
    I444AlphaToARGBRow = I444AlphaToARGBRow_Any_SSSE3;
7721
48
    if (IS_ALIGNED(width, 8)) {
7722
3
      I444AlphaToARGBRow = I444AlphaToARGBRow_SSSE3;
7723
3
    }
7724
48
  }
7725
48
#endif
7726
48
#if defined(HAS_I444ALPHATOARGBROW_AVX2)
7727
48
  if (TestCpuFlag(kCpuHasAVX2)) {
7728
48
    I444AlphaToARGBRow = I444AlphaToARGBRow_Any_AVX2;
7729
48
    if (IS_ALIGNED(width, 16)) {
7730
2
      I444AlphaToARGBRow = I444AlphaToARGBRow_AVX2;
7731
2
    }
7732
48
  }
7733
48
#endif
7734
#if defined(HAS_I444ALPHATOARGBROW_NEON)
7735
  if (TestCpuFlag(kCpuHasNEON)) {
7736
    I444AlphaToARGBRow = I444AlphaToARGBRow_Any_NEON;
7737
    if (IS_ALIGNED(width, 8)) {
7738
      I444AlphaToARGBRow = I444AlphaToARGBRow_NEON;
7739
    }
7740
  }
7741
#endif
7742
#if defined(HAS_I444ALPHATOARGBROW_SVE2)
7743
  if (TestCpuFlag(kCpuHasSVE2)) {
7744
    I444AlphaToARGBRow = I444AlphaToARGBRow_SVE2;
7745
  }
7746
#endif
7747
#if defined(HAS_I444ALPHATOARGBROW_SME)
7748
  if (TestCpuFlag(kCpuHasSME)) {
7749
    I444AlphaToARGBRow = I444AlphaToARGBRow_SME;
7750
  }
7751
#endif
7752
#if defined(HAS_I444ALPHATOARGBROW_MSA)
7753
  if (TestCpuFlag(kCpuHasMSA)) {
7754
    I444AlphaToARGBRow = I444AlphaToARGBRow_Any_MSA;
7755
    if (IS_ALIGNED(width, 8)) {
7756
      I444AlphaToARGBRow = I444AlphaToARGBRow_MSA;
7757
    }
7758
  }
7759
#endif
7760
#if defined(HAS_I444ALPHATOARGBROW_LASX)
7761
  if (TestCpuFlag(kCpuHasLASX)) {
7762
    I444AlphaToARGBRow = I444AlphaToARGBRow_Any_LASX;
7763
    if (IS_ALIGNED(width, 16)) {
7764
      I444AlphaToARGBRow = I444AlphaToARGBRow_LASX;
7765
    }
7766
  }
7767
#endif
7768
#if defined(HAS_I444ALPHATOARGBROW_RVV)
7769
  if (TestCpuFlag(kCpuHasRVV)) {
7770
    I444AlphaToARGBRow = I444AlphaToARGBRow_RVV;
7771
  }
7772
#endif
7773
48
#if defined(HAS_ARGBATTENUATEROW_SSSE3)
7774
48
  if (TestCpuFlag(kCpuHasSSSE3)) {
7775
48
    ARGBAttenuateRow = ARGBAttenuateRow_Any_SSSE3;
7776
48
    if (IS_ALIGNED(width, 4)) {
7777
4
      ARGBAttenuateRow = ARGBAttenuateRow_SSSE3;
7778
4
    }
7779
48
  }
7780
48
#endif
7781
48
#if defined(HAS_ARGBATTENUATEROW_AVX2)
7782
48
  if (TestCpuFlag(kCpuHasAVX2)) {
7783
48
    ARGBAttenuateRow = ARGBAttenuateRow_Any_AVX2;
7784
48
    if (IS_ALIGNED(width, 8)) {
7785
3
      ARGBAttenuateRow = ARGBAttenuateRow_AVX2;
7786
3
    }
7787
48
  }
7788
48
#endif
7789
#if defined(HAS_ARGBATTENUATEROW_NEON)
7790
  if (TestCpuFlag(kCpuHasNEON)) {
7791
    ARGBAttenuateRow = ARGBAttenuateRow_Any_NEON;
7792
    if (IS_ALIGNED(width, 8)) {
7793
      ARGBAttenuateRow = ARGBAttenuateRow_NEON;
7794
    }
7795
  }
7796
#endif
7797
#if defined(HAS_ARGBATTENUATEROW_MSA)
7798
  if (TestCpuFlag(kCpuHasMSA)) {
7799
    ARGBAttenuateRow = ARGBAttenuateRow_Any_MSA;
7800
    if (IS_ALIGNED(width, 8)) {
7801
      ARGBAttenuateRow = ARGBAttenuateRow_MSA;
7802
    }
7803
  }
7804
#endif
7805
#if defined(HAS_ARGBATTENUATEROW_RVV)
7806
  if (TestCpuFlag(kCpuHasRVV)) {
7807
    ARGBAttenuateRow = ARGBAttenuateRow_RVV;
7808
  }
7809
#endif
7810
#if defined(HAS_ARGBATTENUATEROW_LSX)
7811
  if (TestCpuFlag(kCpuHasLSX)) {
7812
    ARGBAttenuateRow = ARGBAttenuateRow_Any_LSX;
7813
    if (IS_ALIGNED(width, 8)) {
7814
      ARGBAttenuateRow = ARGBAttenuateRow_LSX;
7815
    }
7816
  }
7817
#endif
7818
#if defined(HAS_ARGBATTENUATEROW_LASX)
7819
  if (TestCpuFlag(kCpuHasLASX)) {
7820
    ARGBAttenuateRow = ARGBAttenuateRow_Any_LASX;
7821
    if (IS_ALIGNED(width, 16)) {
7822
      ARGBAttenuateRow = ARGBAttenuateRow_LASX;
7823
    }
7824
  }
7825
#endif
7826
7827
48
#if defined(HAS_SCALEROWUP2_BILINEAR_SSE2)
7828
48
  if (TestCpuFlag(kCpuHasSSE2)) {
7829
48
    Scale2RowUp_Bilinear = ScaleRowUp2_Bilinear_Any_SSE2;
7830
48
    ScaleRowUp2_Linear = ScaleRowUp2_Linear_Any_SSE2;
7831
48
  }
7832
48
#endif
7833
7834
48
#if defined(HAS_SCALEROWUP2_BILINEAR_SSSE3)
7835
48
  if (TestCpuFlag(kCpuHasSSSE3)) {
7836
48
    Scale2RowUp_Bilinear = ScaleRowUp2_Bilinear_Any_SSSE3;
7837
48
    ScaleRowUp2_Linear = ScaleRowUp2_Linear_Any_SSSE3;
7838
48
  }
7839
48
#endif
7840
7841
48
#if defined(HAS_SCALEROWUP2_BILINEAR_AVX2)
7842
48
  if (TestCpuFlag(kCpuHasAVX2)) {
7843
48
    Scale2RowUp_Bilinear = ScaleRowUp2_Bilinear_Any_AVX2;
7844
48
    ScaleRowUp2_Linear = ScaleRowUp2_Linear_Any_AVX2;
7845
48
  }
7846
48
#endif
7847
7848
#if defined(HAS_SCALEROWUP2_BILINEAR_NEON)
7849
  if (TestCpuFlag(kCpuHasNEON)) {
7850
    Scale2RowUp_Bilinear = ScaleRowUp2_Bilinear_Any_NEON;
7851
    ScaleRowUp2_Linear = ScaleRowUp2_Linear_Any_NEON;
7852
  }
7853
#endif
7854
#if defined(HAS_SCALEROWUP2_BILINEAR_RVV)
7855
  if (TestCpuFlag(kCpuHasRVV)) {
7856
    Scale2RowUp_Bilinear = ScaleRowUp2_Bilinear_RVV;
7857
    ScaleRowUp2_Linear = ScaleRowUp2_Linear_RVV;
7858
  }
7859
#endif
7860
7861
  // alloc 4 lines temp
7862
48
  const int row_size = (width + 31) & ~31;
7863
48
  align_buffer_64(row, row_size * 4);
7864
48
  uint8_t* temp_u_1 = row;
7865
48
  uint8_t* temp_u_2 = row + row_size;
7866
48
  uint8_t* temp_v_1 = row + row_size * 2;
7867
48
  uint8_t* temp_v_2 = row + row_size * 3;
7868
48
  if (!row)
7869
0
    return 1;
7870
7871
48
  ScaleRowUp2_Linear(src_u, temp_u_1, width);
7872
48
  ScaleRowUp2_Linear(src_v, temp_v_1, width);
7873
48
  I444AlphaToARGBRow(src_y, temp_u_1, temp_v_1, src_a, dst_argb, yuvconstants,
7874
48
                     width);
7875
48
  if (attenuate) {
7876
0
    ARGBAttenuateRow(dst_argb, dst_argb, width);
7877
0
  }
7878
48
  dst_argb += dst_stride_argb;
7879
48
  src_y += src_stride_y;
7880
48
  src_a += src_stride_a;
7881
7882
1.46k
  for (y = 0; y < height - 2; y += 2) {
7883
1.41k
    Scale2RowUp_Bilinear(src_u, src_stride_u, temp_u_1, row_size, width);
7884
1.41k
    Scale2RowUp_Bilinear(src_v, src_stride_v, temp_v_1, row_size, width);
7885
1.41k
    I444AlphaToARGBRow(src_y, temp_u_1, temp_v_1, src_a, dst_argb, yuvconstants,
7886
1.41k
                       width);
7887
1.41k
    if (attenuate) {
7888
0
      ARGBAttenuateRow(dst_argb, dst_argb, width);
7889
0
    }
7890
1.41k
    dst_argb += dst_stride_argb;
7891
1.41k
    src_y += src_stride_y;
7892
1.41k
    src_a += src_stride_a;
7893
1.41k
    I444AlphaToARGBRow(src_y, temp_u_2, temp_v_2, src_a, dst_argb, yuvconstants,
7894
1.41k
                       width);
7895
1.41k
    if (attenuate) {
7896
0
      ARGBAttenuateRow(dst_argb, dst_argb, width);
7897
0
    }
7898
1.41k
    dst_argb += dst_stride_argb;
7899
1.41k
    src_y += src_stride_y;
7900
1.41k
    src_u += src_stride_u;
7901
1.41k
    src_v += src_stride_v;
7902
1.41k
    src_a += src_stride_a;
7903
1.41k
  }
7904
7905
48
  if (!(height & 1)) {
7906
18
    ScaleRowUp2_Linear(src_u, temp_u_1, width);
7907
18
    ScaleRowUp2_Linear(src_v, temp_v_1, width);
7908
18
    I444AlphaToARGBRow(src_y, temp_u_1, temp_v_1, src_a, dst_argb, yuvconstants,
7909
18
                       width);
7910
18
    if (attenuate) {
7911
0
      ARGBAttenuateRow(dst_argb, dst_argb, width);
7912
0
    }
7913
18
  }
7914
7915
48
  free_aligned_buffer_64(row);
7916
48
  return 0;
7917
48
}
7918
7919
static int I422AlphaToARGBMatrixLinear(const uint8_t* src_y,
7920
                                       int src_stride_y,
7921
                                       const uint8_t* src_u,
7922
                                       int src_stride_u,
7923
                                       const uint8_t* src_v,
7924
                                       int src_stride_v,
7925
                                       const uint8_t* src_a,
7926
                                       int src_stride_a,
7927
                                       uint8_t* dst_argb,
7928
                                       int dst_stride_argb,
7929
                                       const struct YuvConstants* yuvconstants,
7930
                                       int width,
7931
                                       int height,
7932
123
                                       int attenuate) {
7933
123
  int y;
7934
123
  void (*I444AlphaToARGBRow)(const uint8_t* y_buf, const uint8_t* u_buf,
7935
123
                             const uint8_t* v_buf, const uint8_t* a_buf,
7936
123
                             uint8_t* dst_argb,
7937
123
                             const struct YuvConstants* yuvconstants,
7938
123
                             int width) = I444AlphaToARGBRow_C;
7939
123
  void (*ARGBAttenuateRow)(const uint8_t* src_argb, uint8_t* dst_argb,
7940
123
                           int width) = ARGBAttenuateRow_C;
7941
123
  void (*ScaleRowUp2_Linear)(const uint8_t* src_ptr, uint8_t* dst_ptr,
7942
123
                             int dst_width) = ScaleRowUp2_Linear_Any_C;
7943
123
  assert(yuvconstants);
7944
123
  if (!src_y || !src_u || !src_v || !src_a || !dst_argb || width <= 0 ||
7945
123
      height == 0) {
7946
0
    return -1;
7947
0
  }
7948
  // Negative height means invert the image.
7949
123
  if (height < 0) {
7950
0
    height = -height;
7951
0
    dst_argb = dst_argb + (height - 1) * dst_stride_argb;
7952
0
    dst_stride_argb = -dst_stride_argb;
7953
0
  }
7954
123
#if defined(HAS_I444ALPHATOARGBROW_SSSE3)
7955
123
  if (TestCpuFlag(kCpuHasSSSE3)) {
7956
123
    I444AlphaToARGBRow = I444AlphaToARGBRow_Any_SSSE3;
7957
123
    if (IS_ALIGNED(width, 8)) {
7958
34
      I444AlphaToARGBRow = I444AlphaToARGBRow_SSSE3;
7959
34
    }
7960
123
  }
7961
123
#endif
7962
123
#if defined(HAS_I444ALPHATOARGBROW_AVX2)
7963
123
  if (TestCpuFlag(kCpuHasAVX2)) {
7964
123
    I444AlphaToARGBRow = I444AlphaToARGBRow_Any_AVX2;
7965
123
    if (IS_ALIGNED(width, 16)) {
7966
17
      I444AlphaToARGBRow = I444AlphaToARGBRow_AVX2;
7967
17
    }
7968
123
  }
7969
123
#endif
7970
#if defined(HAS_I444ALPHATOARGBROW_NEON)
7971
  if (TestCpuFlag(kCpuHasNEON)) {
7972
    I444AlphaToARGBRow = I444AlphaToARGBRow_Any_NEON;
7973
    if (IS_ALIGNED(width, 8)) {
7974
      I444AlphaToARGBRow = I444AlphaToARGBRow_NEON;
7975
    }
7976
  }
7977
#endif
7978
#if defined(HAS_I444ALPHATOARGBROW_SVE2)
7979
  if (TestCpuFlag(kCpuHasSVE2)) {
7980
    I444AlphaToARGBRow = I444AlphaToARGBRow_SVE2;
7981
  }
7982
#endif
7983
#if defined(HAS_I444ALPHATOARGBROW_SME)
7984
  if (TestCpuFlag(kCpuHasSME)) {
7985
    I444AlphaToARGBRow = I444AlphaToARGBRow_SME;
7986
  }
7987
#endif
7988
#if defined(HAS_I444ALPHATOARGBROW_MSA)
7989
  if (TestCpuFlag(kCpuHasMSA)) {
7990
    I444AlphaToARGBRow = I444AlphaToARGBRow_Any_MSA;
7991
    if (IS_ALIGNED(width, 8)) {
7992
      I444AlphaToARGBRow = I444AlphaToARGBRow_MSA;
7993
    }
7994
  }
7995
#endif
7996
#if defined(HAS_I444ALPHATOARGBROW_LASX)
7997
  if (TestCpuFlag(kCpuHasLASX)) {
7998
    I444AlphaToARGBRow = I444AlphaToARGBRow_Any_LASX;
7999
    if (IS_ALIGNED(width, 16)) {
8000
      I444AlphaToARGBRow = I444AlphaToARGBRow_LASX;
8001
    }
8002
  }
8003
#endif
8004
#if defined(HAS_I444ALPHATOARGBROW_RVV)
8005
  if (TestCpuFlag(kCpuHasRVV)) {
8006
    I444AlphaToARGBRow = I444AlphaToARGBRow_RVV;
8007
  }
8008
#endif
8009
123
#if defined(HAS_ARGBATTENUATEROW_SSSE3)
8010
123
  if (TestCpuFlag(kCpuHasSSSE3)) {
8011
123
    ARGBAttenuateRow = ARGBAttenuateRow_Any_SSSE3;
8012
123
    if (IS_ALIGNED(width, 4)) {
8013
52
      ARGBAttenuateRow = ARGBAttenuateRow_SSSE3;
8014
52
    }
8015
123
  }
8016
123
#endif
8017
123
#if defined(HAS_ARGBATTENUATEROW_AVX2)
8018
123
  if (TestCpuFlag(kCpuHasAVX2)) {
8019
123
    ARGBAttenuateRow = ARGBAttenuateRow_Any_AVX2;
8020
123
    if (IS_ALIGNED(width, 8)) {
8021
34
      ARGBAttenuateRow = ARGBAttenuateRow_AVX2;
8022
34
    }
8023
123
  }
8024
123
#endif
8025
#if defined(HAS_ARGBATTENUATEROW_NEON)
8026
  if (TestCpuFlag(kCpuHasNEON)) {
8027
    ARGBAttenuateRow = ARGBAttenuateRow_Any_NEON;
8028
    if (IS_ALIGNED(width, 8)) {
8029
      ARGBAttenuateRow = ARGBAttenuateRow_NEON;
8030
    }
8031
  }
8032
#endif
8033
#if defined(HAS_ARGBATTENUATEROW_MSA)
8034
  if (TestCpuFlag(kCpuHasMSA)) {
8035
    ARGBAttenuateRow = ARGBAttenuateRow_Any_MSA;
8036
    if (IS_ALIGNED(width, 8)) {
8037
      ARGBAttenuateRow = ARGBAttenuateRow_MSA;
8038
    }
8039
  }
8040
#endif
8041
#if defined(HAS_ARGBATTENUATEROW_RVV)
8042
  if (TestCpuFlag(kCpuHasRVV)) {
8043
    ARGBAttenuateRow = ARGBAttenuateRow_RVV;
8044
  }
8045
#endif
8046
#if defined(HAS_ARGBATTENUATEROW_LSX)
8047
  if (TestCpuFlag(kCpuHasLSX)) {
8048
    ARGBAttenuateRow = ARGBAttenuateRow_Any_LSX;
8049
    if (IS_ALIGNED(width, 8)) {
8050
      ARGBAttenuateRow = ARGBAttenuateRow_LSX;
8051
    }
8052
  }
8053
#endif
8054
#if defined(HAS_ARGBATTENUATEROW_LASX)
8055
  if (TestCpuFlag(kCpuHasLASX)) {
8056
    ARGBAttenuateRow = ARGBAttenuateRow_Any_LASX;
8057
    if (IS_ALIGNED(width, 16)) {
8058
      ARGBAttenuateRow = ARGBAttenuateRow_LASX;
8059
    }
8060
  }
8061
#endif
8062
8063
123
#if defined(HAS_SCALEROWUP2_LINEAR_SSE2)
8064
123
  if (TestCpuFlag(kCpuHasSSE2)) {
8065
123
    ScaleRowUp2_Linear = ScaleRowUp2_Linear_Any_SSE2;
8066
123
  }
8067
123
#endif
8068
123
#if defined(HAS_SCALEROWUP2_LINEAR_SSSE3)
8069
123
  if (TestCpuFlag(kCpuHasSSSE3)) {
8070
123
    ScaleRowUp2_Linear = ScaleRowUp2_Linear_Any_SSSE3;
8071
123
  }
8072
123
#endif
8073
123
#if defined(HAS_SCALEROWUP2_LINEAR_AVX2)
8074
123
  if (TestCpuFlag(kCpuHasAVX2)) {
8075
123
    ScaleRowUp2_Linear = ScaleRowUp2_Linear_Any_AVX2;
8076
123
  }
8077
123
#endif
8078
#if defined(HAS_SCALEROWUP2_LINEAR_NEON)
8079
  if (TestCpuFlag(kCpuHasNEON)) {
8080
    ScaleRowUp2_Linear = ScaleRowUp2_Linear_Any_NEON;
8081
  }
8082
#endif
8083
#if defined(HAS_SCALEROWUP2_LINEAR_RVV)
8084
  if (TestCpuFlag(kCpuHasRVV)) {
8085
    ScaleRowUp2_Linear = ScaleRowUp2_Linear_RVV;
8086
  }
8087
#endif
8088
8089
  // alloc 2 lines temp
8090
123
  const int row_size = (width + 31) & ~31;
8091
123
  align_buffer_64(row, row_size * 2);
8092
123
  uint8_t* temp_u = row;
8093
123
  uint8_t* temp_v = row + row_size;
8094
123
  if (!row)
8095
0
    return 1;
8096
8097
1.35k
  for (y = 0; y < height; ++y) {
8098
1.23k
    ScaleRowUp2_Linear(src_u, temp_u, width);
8099
1.23k
    ScaleRowUp2_Linear(src_v, temp_v, width);
8100
1.23k
    I444AlphaToARGBRow(src_y, temp_u, temp_v, src_a, dst_argb, yuvconstants,
8101
1.23k
                       width);
8102
1.23k
    if (attenuate) {
8103
0
      ARGBAttenuateRow(dst_argb, dst_argb, width);
8104
0
    }
8105
1.23k
    dst_argb += dst_stride_argb;
8106
1.23k
    src_a += src_stride_a;
8107
1.23k
    src_y += src_stride_y;
8108
1.23k
    src_u += src_stride_u;
8109
1.23k
    src_v += src_stride_v;
8110
1.23k
  }
8111
8112
123
  free_aligned_buffer_64(row);
8113
123
  return 0;
8114
123
}
8115
8116
static int I010AlphaToARGBMatrixBilinear(
8117
    const uint16_t* src_y,
8118
    int src_stride_y,
8119
    const uint16_t* src_u,
8120
    int src_stride_u,
8121
    const uint16_t* src_v,
8122
    int src_stride_v,
8123
    const uint16_t* src_a,
8124
    int src_stride_a,
8125
    uint8_t* dst_argb,
8126
    int dst_stride_argb,
8127
    const struct YuvConstants* yuvconstants,
8128
    int width,
8129
    int height,
8130
37
    int attenuate) {
8131
37
  int y;
8132
37
  void (*I410AlphaToARGBRow)(const uint16_t* y_buf, const uint16_t* u_buf,
8133
37
                             const uint16_t* v_buf, const uint16_t* a_buf,
8134
37
                             uint8_t* dst_argb,
8135
37
                             const struct YuvConstants* yuvconstants,
8136
37
                             int width) = I410AlphaToARGBRow_C;
8137
37
  void (*ARGBAttenuateRow)(const uint8_t* src_argb, uint8_t* dst_argb,
8138
37
                           int width) = ARGBAttenuateRow_C;
8139
37
  void (*Scale2RowUp_Bilinear_12)(
8140
37
      const uint16_t* src_ptr, ptrdiff_t src_stride, uint16_t* dst_ptr,
8141
37
      ptrdiff_t dst_stride, int dst_width) = ScaleRowUp2_Bilinear_16_Any_C;
8142
37
  void (*ScaleRowUp2_Linear_12)(const uint16_t* src_ptr, uint16_t* dst_ptr,
8143
37
                                int dst_width) = ScaleRowUp2_Linear_16_Any_C;
8144
37
  assert(yuvconstants);
8145
37
  if (!src_y || !src_u || !src_v || !src_a || !dst_argb || width <= 0 ||
8146
37
      height == 0) {
8147
0
    return -1;
8148
0
  }
8149
  // Negative height means invert the image.
8150
37
  if (height < 0) {
8151
0
    height = -height;
8152
0
    dst_argb = dst_argb + (height - 1) * dst_stride_argb;
8153
0
    dst_stride_argb = -dst_stride_argb;
8154
0
  }
8155
#if defined(HAS_I410ALPHATOARGBROW_NEON)
8156
  if (TestCpuFlag(kCpuHasNEON)) {
8157
    I410AlphaToARGBRow = I410AlphaToARGBRow_Any_NEON;
8158
    if (IS_ALIGNED(width, 8)) {
8159
      I410AlphaToARGBRow = I410AlphaToARGBRow_NEON;
8160
    }
8161
  }
8162
#endif
8163
#if defined(HAS_I410ALPHATOARGBROW_SVE2)
8164
  if (TestCpuFlag(kCpuHasSVE2)) {
8165
    I410AlphaToARGBRow = I410AlphaToARGBRow_SVE2;
8166
  }
8167
#endif
8168
#if defined(HAS_I410ALPHATOARGBROW_SME)
8169
  if (TestCpuFlag(kCpuHasSME)) {
8170
    I410AlphaToARGBRow = I410AlphaToARGBRow_SME;
8171
  }
8172
#endif
8173
37
#if defined(HAS_I410ALPHATOARGBROW_SSSE3)
8174
37
  if (TestCpuFlag(kCpuHasSSSE3)) {
8175
37
    I410AlphaToARGBRow = I410AlphaToARGBRow_Any_SSSE3;
8176
37
    if (IS_ALIGNED(width, 8)) {
8177
6
      I410AlphaToARGBRow = I410AlphaToARGBRow_SSSE3;
8178
6
    }
8179
37
  }
8180
37
#endif
8181
37
#if defined(HAS_I410ALPHATOARGBROW_AVX2)
8182
37
  if (TestCpuFlag(kCpuHasAVX2)) {
8183
37
    I410AlphaToARGBRow = I410AlphaToARGBRow_Any_AVX2;
8184
37
    if (IS_ALIGNED(width, 16)) {
8185
5
      I410AlphaToARGBRow = I410AlphaToARGBRow_AVX2;
8186
5
    }
8187
37
  }
8188
37
#endif
8189
37
#if defined(HAS_ARGBATTENUATEROW_SSSE3)
8190
37
  if (TestCpuFlag(kCpuHasSSSE3)) {
8191
37
    ARGBAttenuateRow = ARGBAttenuateRow_Any_SSSE3;
8192
37
    if (IS_ALIGNED(width, 4)) {
8193
8
      ARGBAttenuateRow = ARGBAttenuateRow_SSSE3;
8194
8
    }
8195
37
  }
8196
37
#endif
8197
37
#if defined(HAS_ARGBATTENUATEROW_AVX2)
8198
37
  if (TestCpuFlag(kCpuHasAVX2)) {
8199
37
    ARGBAttenuateRow = ARGBAttenuateRow_Any_AVX2;
8200
37
    if (IS_ALIGNED(width, 8)) {
8201
6
      ARGBAttenuateRow = ARGBAttenuateRow_AVX2;
8202
6
    }
8203
37
  }
8204
37
#endif
8205
#if defined(HAS_ARGBATTENUATEROW_NEON)
8206
  if (TestCpuFlag(kCpuHasNEON)) {
8207
    ARGBAttenuateRow = ARGBAttenuateRow_Any_NEON;
8208
    if (IS_ALIGNED(width, 8)) {
8209
      ARGBAttenuateRow = ARGBAttenuateRow_NEON;
8210
    }
8211
  }
8212
#endif
8213
#if defined(HAS_ARGBATTENUATEROW_MSA)
8214
  if (TestCpuFlag(kCpuHasMSA)) {
8215
    ARGBAttenuateRow = ARGBAttenuateRow_Any_MSA;
8216
    if (IS_ALIGNED(width, 8)) {
8217
      ARGBAttenuateRow = ARGBAttenuateRow_MSA;
8218
    }
8219
  }
8220
#endif
8221
#if defined(HAS_ARGBATTENUATEROW_RVV)
8222
  if (TestCpuFlag(kCpuHasRVV)) {
8223
    ARGBAttenuateRow = ARGBAttenuateRow_RVV;
8224
  }
8225
#endif
8226
#if defined(HAS_ARGBATTENUATEROW_LSX)
8227
  if (TestCpuFlag(kCpuHasLSX)) {
8228
    ARGBAttenuateRow = ARGBAttenuateRow_Any_LSX;
8229
    if (IS_ALIGNED(width, 8)) {
8230
      ARGBAttenuateRow = ARGBAttenuateRow_LSX;
8231
    }
8232
  }
8233
#endif
8234
#if defined(HAS_ARGBATTENUATEROW_LASX)
8235
  if (TestCpuFlag(kCpuHasLASX)) {
8236
    ARGBAttenuateRow = ARGBAttenuateRow_Any_LASX;
8237
    if (IS_ALIGNED(width, 16)) {
8238
      ARGBAttenuateRow = ARGBAttenuateRow_LASX;
8239
    }
8240
  }
8241
#endif
8242
8243
37
#if defined(HAS_SCALEROWUP2_BILINEAR_12_SSSE3)
8244
37
  if (TestCpuFlag(kCpuHasSSSE3)) {
8245
37
    Scale2RowUp_Bilinear_12 = ScaleRowUp2_Bilinear_12_Any_SSSE3;
8246
37
    ScaleRowUp2_Linear_12 = ScaleRowUp2_Linear_12_Any_SSSE3;
8247
37
  }
8248
37
#endif
8249
8250
37
#if defined(HAS_SCALEROWUP2_BILINEAR_12_AVX2)
8251
37
  if (TestCpuFlag(kCpuHasAVX2)) {
8252
37
    Scale2RowUp_Bilinear_12 = ScaleRowUp2_Bilinear_12_Any_AVX2;
8253
37
    ScaleRowUp2_Linear_12 = ScaleRowUp2_Linear_12_Any_AVX2;
8254
37
  }
8255
37
#endif
8256
8257
#if defined(HAS_SCALEROWUP2_BILINEAR_12_NEON)
8258
  if (TestCpuFlag(kCpuHasNEON)) {
8259
    Scale2RowUp_Bilinear_12 = ScaleRowUp2_Bilinear_12_Any_NEON;
8260
    ScaleRowUp2_Linear_12 = ScaleRowUp2_Linear_12_Any_NEON;
8261
  }
8262
#endif
8263
8264
  // alloc 4 lines temp
8265
37
  const int row_size = (width + 31) & ~31;
8266
37
  align_buffer_64(row, row_size * 4 * sizeof(uint16_t));
8267
37
  uint16_t* temp_u_1 = (uint16_t*)(row);
8268
37
  uint16_t* temp_u_2 = (uint16_t*)(row) + row_size;
8269
37
  uint16_t* temp_v_1 = (uint16_t*)(row) + row_size * 2;
8270
37
  uint16_t* temp_v_2 = (uint16_t*)(row) + row_size * 3;
8271
37
  if (!row)
8272
0
    return 1;
8273
8274
37
  ScaleRowUp2_Linear_12(src_u, temp_u_1, width);
8275
37
  ScaleRowUp2_Linear_12(src_v, temp_v_1, width);
8276
37
  I410AlphaToARGBRow(src_y, temp_u_1, temp_v_1, src_a, dst_argb, yuvconstants,
8277
37
                     width);
8278
37
  if (attenuate) {
8279
0
    ARGBAttenuateRow(dst_argb, dst_argb, width);
8280
0
  }
8281
37
  dst_argb += dst_stride_argb;
8282
37
  src_y += src_stride_y;
8283
37
  src_a += src_stride_a;
8284
8285
579
  for (y = 0; y < height - 2; y += 2) {
8286
542
    Scale2RowUp_Bilinear_12(src_u, src_stride_u, temp_u_1, row_size, width);
8287
542
    Scale2RowUp_Bilinear_12(src_v, src_stride_v, temp_v_1, row_size, width);
8288
542
    I410AlphaToARGBRow(src_y, temp_u_1, temp_v_1, src_a, dst_argb, yuvconstants,
8289
542
                       width);
8290
542
    if (attenuate) {
8291
0
      ARGBAttenuateRow(dst_argb, dst_argb, width);
8292
0
    }
8293
542
    dst_argb += dst_stride_argb;
8294
542
    src_y += src_stride_y;
8295
542
    src_a += src_stride_a;
8296
542
    I410AlphaToARGBRow(src_y, temp_u_2, temp_v_2, src_a, dst_argb, yuvconstants,
8297
542
                       width);
8298
542
    if (attenuate) {
8299
0
      ARGBAttenuateRow(dst_argb, dst_argb, width);
8300
0
    }
8301
542
    dst_argb += dst_stride_argb;
8302
542
    src_y += src_stride_y;
8303
542
    src_a += src_stride_a;
8304
542
    src_u += src_stride_u;
8305
542
    src_v += src_stride_v;
8306
542
  }
8307
8308
37
  if (!(height & 1)) {
8309
14
    ScaleRowUp2_Linear_12(src_u, temp_u_1, width);
8310
14
    ScaleRowUp2_Linear_12(src_v, temp_v_1, width);
8311
14
    I410AlphaToARGBRow(src_y, temp_u_1, temp_v_1, src_a, dst_argb, yuvconstants,
8312
14
                       width);
8313
14
    if (attenuate) {
8314
0
      ARGBAttenuateRow(dst_argb, dst_argb, width);
8315
0
    }
8316
14
  }
8317
8318
37
  free_aligned_buffer_64(row);
8319
37
  return 0;
8320
37
}
8321
8322
static int I210AlphaToARGBMatrixLinear(const uint16_t* src_y,
8323
                                       int src_stride_y,
8324
                                       const uint16_t* src_u,
8325
                                       int src_stride_u,
8326
                                       const uint16_t* src_v,
8327
                                       int src_stride_v,
8328
                                       const uint16_t* src_a,
8329
                                       int src_stride_a,
8330
                                       uint8_t* dst_argb,
8331
                                       int dst_stride_argb,
8332
                                       const struct YuvConstants* yuvconstants,
8333
                                       int width,
8334
                                       int height,
8335
96
                                       int attenuate) {
8336
96
  int y;
8337
96
  void (*I410AlphaToARGBRow)(const uint16_t* y_buf, const uint16_t* u_buf,
8338
96
                             const uint16_t* v_buf, const uint16_t* a_buf,
8339
96
                             uint8_t* dst_argb,
8340
96
                             const struct YuvConstants* yuvconstants,
8341
96
                             int width) = I410AlphaToARGBRow_C;
8342
96
  void (*ARGBAttenuateRow)(const uint8_t* src_argb, uint8_t* dst_argb,
8343
96
                           int width) = ARGBAttenuateRow_C;
8344
96
  void (*ScaleRowUp2_Linear)(const uint16_t* src_ptr, uint16_t* dst_ptr,
8345
96
                             int dst_width) = ScaleRowUp2_Linear_16_Any_C;
8346
96
  assert(yuvconstants);
8347
96
  if (!src_y || !src_u || !src_v || !src_a || !dst_argb || width <= 0 ||
8348
96
      height == 0) {
8349
0
    return -1;
8350
0
  }
8351
  // Negative height means invert the image.
8352
96
  if (height < 0) {
8353
0
    height = -height;
8354
0
    dst_argb = dst_argb + (height - 1) * dst_stride_argb;
8355
0
    dst_stride_argb = -dst_stride_argb;
8356
0
  }
8357
#if defined(HAS_I410ALPHATOARGBROW_NEON)
8358
  if (TestCpuFlag(kCpuHasNEON)) {
8359
    I410AlphaToARGBRow = I410AlphaToARGBRow_Any_NEON;
8360
    if (IS_ALIGNED(width, 8)) {
8361
      I410AlphaToARGBRow = I410AlphaToARGBRow_NEON;
8362
    }
8363
  }
8364
#endif
8365
#if defined(HAS_I410ALPHATOARGBROW_SVE2)
8366
  if (TestCpuFlag(kCpuHasSVE2)) {
8367
    I410AlphaToARGBRow = I410AlphaToARGBRow_SVE2;
8368
  }
8369
#endif
8370
#if defined(HAS_I410ALPHATOARGBROW_SME)
8371
  if (TestCpuFlag(kCpuHasSME)) {
8372
    I410AlphaToARGBRow = I410AlphaToARGBRow_SME;
8373
  }
8374
#endif
8375
96
#if defined(HAS_I410ALPHATOARGBROW_SSSE3)
8376
96
  if (TestCpuFlag(kCpuHasSSSE3)) {
8377
96
    I410AlphaToARGBRow = I410AlphaToARGBRow_Any_SSSE3;
8378
96
    if (IS_ALIGNED(width, 8)) {
8379
34
      I410AlphaToARGBRow = I410AlphaToARGBRow_SSSE3;
8380
34
    }
8381
96
  }
8382
96
#endif
8383
96
#if defined(HAS_I410ALPHATOARGBROW_AVX2)
8384
96
  if (TestCpuFlag(kCpuHasAVX2)) {
8385
96
    I410AlphaToARGBRow = I410AlphaToARGBRow_Any_AVX2;
8386
96
    if (IS_ALIGNED(width, 16)) {
8387
17
      I410AlphaToARGBRow = I410AlphaToARGBRow_AVX2;
8388
17
    }
8389
96
  }
8390
96
#endif
8391
96
#if defined(HAS_ARGBATTENUATEROW_SSSE3)
8392
96
  if (TestCpuFlag(kCpuHasSSSE3)) {
8393
96
    ARGBAttenuateRow = ARGBAttenuateRow_Any_SSSE3;
8394
96
    if (IS_ALIGNED(width, 4)) {
8395
59
      ARGBAttenuateRow = ARGBAttenuateRow_SSSE3;
8396
59
    }
8397
96
  }
8398
96
#endif
8399
96
#if defined(HAS_ARGBATTENUATEROW_AVX2)
8400
96
  if (TestCpuFlag(kCpuHasAVX2)) {
8401
96
    ARGBAttenuateRow = ARGBAttenuateRow_Any_AVX2;
8402
96
    if (IS_ALIGNED(width, 8)) {
8403
34
      ARGBAttenuateRow = ARGBAttenuateRow_AVX2;
8404
34
    }
8405
96
  }
8406
96
#endif
8407
#if defined(HAS_ARGBATTENUATEROW_NEON)
8408
  if (TestCpuFlag(kCpuHasNEON)) {
8409
    ARGBAttenuateRow = ARGBAttenuateRow_Any_NEON;
8410
    if (IS_ALIGNED(width, 8)) {
8411
      ARGBAttenuateRow = ARGBAttenuateRow_NEON;
8412
    }
8413
  }
8414
#endif
8415
#if defined(HAS_ARGBATTENUATEROW_MSA)
8416
  if (TestCpuFlag(kCpuHasMSA)) {
8417
    ARGBAttenuateRow = ARGBAttenuateRow_Any_MSA;
8418
    if (IS_ALIGNED(width, 8)) {
8419
      ARGBAttenuateRow = ARGBAttenuateRow_MSA;
8420
    }
8421
  }
8422
#endif
8423
#if defined(HAS_ARGBATTENUATEROW_RVV)
8424
  if (TestCpuFlag(kCpuHasRVV)) {
8425
    ARGBAttenuateRow = ARGBAttenuateRow_RVV;
8426
  }
8427
#endif
8428
#if defined(HAS_ARGBATTENUATEROW_LSX)
8429
  if (TestCpuFlag(kCpuHasLSX)) {
8430
    ARGBAttenuateRow = ARGBAttenuateRow_Any_LSX;
8431
    if (IS_ALIGNED(width, 8)) {
8432
      ARGBAttenuateRow = ARGBAttenuateRow_LSX;
8433
    }
8434
  }
8435
#endif
8436
#if defined(HAS_ARGBATTENUATEROW_LASX)
8437
  if (TestCpuFlag(kCpuHasLASX)) {
8438
    ARGBAttenuateRow = ARGBAttenuateRow_Any_LASX;
8439
    if (IS_ALIGNED(width, 16)) {
8440
      ARGBAttenuateRow = ARGBAttenuateRow_LASX;
8441
    }
8442
  }
8443
#endif
8444
8445
96
#if defined(HAS_SCALEROWUP2_LINEAR_12_SSSE3)
8446
96
  if (TestCpuFlag(kCpuHasSSSE3)) {
8447
96
    ScaleRowUp2_Linear = ScaleRowUp2_Linear_12_Any_SSSE3;
8448
96
  }
8449
96
#endif
8450
96
#if defined(HAS_SCALEROWUP2_LINEAR_12_AVX2)
8451
96
  if (TestCpuFlag(kCpuHasAVX2)) {
8452
96
    ScaleRowUp2_Linear = ScaleRowUp2_Linear_12_Any_AVX2;
8453
96
  }
8454
96
#endif
8455
#if defined(HAS_SCALEROWUP2_LINEAR_12_NEON)
8456
  if (TestCpuFlag(kCpuHasNEON)) {
8457
    ScaleRowUp2_Linear = ScaleRowUp2_Linear_12_Any_NEON;
8458
  }
8459
#endif
8460
8461
  // alloc 2 lines temp
8462
96
  const int row_size = (width + 31) & ~31;
8463
96
  align_buffer_64(row, row_size * 2 * sizeof(uint16_t));
8464
96
  uint16_t* temp_u = (uint16_t*)(row);
8465
96
  uint16_t* temp_v = (uint16_t*)(row) + row_size;
8466
96
  if (!row)
8467
0
    return 1;
8468
8469
1.87k
  for (y = 0; y < height; ++y) {
8470
1.78k
    ScaleRowUp2_Linear(src_u, temp_u, width);
8471
1.78k
    ScaleRowUp2_Linear(src_v, temp_v, width);
8472
1.78k
    I410AlphaToARGBRow(src_y, temp_u, temp_v, src_a, dst_argb, yuvconstants,
8473
1.78k
                       width);
8474
1.78k
    if (attenuate) {
8475
0
      ARGBAttenuateRow(dst_argb, dst_argb, width);
8476
0
    }
8477
1.78k
    dst_argb += dst_stride_argb;
8478
1.78k
    src_a += src_stride_a;
8479
1.78k
    src_y += src_stride_y;
8480
1.78k
    src_u += src_stride_u;
8481
1.78k
    src_v += src_stride_v;
8482
1.78k
  }
8483
96
  free_aligned_buffer_64(row);
8484
96
  return 0;
8485
96
}
8486
8487
static int P010ToARGBMatrixBilinear(const uint16_t* src_y,
8488
                                    int src_stride_y,
8489
                                    const uint16_t* src_uv,
8490
                                    int src_stride_uv,
8491
                                    uint8_t* dst_argb,
8492
                                    int dst_stride_argb,
8493
                                    const struct YuvConstants* yuvconstants,
8494
                                    int width,
8495
0
                                    int height) {
8496
0
  int y;
8497
0
  void (*P410ToARGBRow)(
8498
0
      const uint16_t* y_buf, const uint16_t* uv_buf, uint8_t* rgb_buf,
8499
0
      const struct YuvConstants* yuvconstants, int width) = P410ToARGBRow_C;
8500
0
  void (*Scale2RowUp_Bilinear_16)(
8501
0
      const uint16_t* src_ptr, ptrdiff_t src_stride, uint16_t* dst_ptr,
8502
0
      ptrdiff_t dst_stride, int dst_width) = ScaleUVRowUp2_Bilinear_16_Any_C;
8503
0
  assert(yuvconstants);
8504
0
  if (!src_y || !src_uv || !dst_argb || width <= 0 || height == 0) {
8505
0
    return -1;
8506
0
  }
8507
  // Negative height means invert the image.
8508
0
  if (height < 0) {
8509
0
    height = -height;
8510
0
    dst_argb = dst_argb + (height - 1) * dst_stride_argb;
8511
0
    dst_stride_argb = -dst_stride_argb;
8512
0
  }
8513
0
#if defined(HAS_P410TOARGBROW_SSSE3)
8514
0
  if (TestCpuFlag(kCpuHasSSSE3)) {
8515
0
    P410ToARGBRow = P410ToARGBRow_Any_SSSE3;
8516
0
    if (IS_ALIGNED(width, 8)) {
8517
0
      P410ToARGBRow = P410ToARGBRow_SSSE3;
8518
0
    }
8519
0
  }
8520
0
#endif
8521
0
#if defined(HAS_P410TOARGBROW_AVX2)
8522
0
  if (TestCpuFlag(kCpuHasAVX2)) {
8523
0
    P410ToARGBRow = P410ToARGBRow_Any_AVX2;
8524
0
    if (IS_ALIGNED(width, 16)) {
8525
0
      P410ToARGBRow = P410ToARGBRow_AVX2;
8526
0
    }
8527
0
  }
8528
0
#endif
8529
#if defined(HAS_P410TOARGBROW_NEON)
8530
  if (TestCpuFlag(kCpuHasNEON)) {
8531
    P410ToARGBRow = P410ToARGBRow_Any_NEON;
8532
    if (IS_ALIGNED(width, 8)) {
8533
      P410ToARGBRow = P410ToARGBRow_NEON;
8534
    }
8535
  }
8536
#endif
8537
#if defined(HAS_P410TOARGBROW_SVE2)
8538
  if (TestCpuFlag(kCpuHasSVE2)) {
8539
    P410ToARGBRow = P410ToARGBRow_SVE2;
8540
  }
8541
#endif
8542
#if defined(HAS_P410TOARGBROW_SME)
8543
  if (TestCpuFlag(kCpuHasSME)) {
8544
    P410ToARGBRow = P410ToARGBRow_SME;
8545
  }
8546
#endif
8547
8548
0
#ifdef HAS_SCALEUVROWUP2_BILINEAR_16_SSE41
8549
0
  if (TestCpuFlag(kCpuHasSSE41)) {
8550
0
    Scale2RowUp_Bilinear_16 = ScaleUVRowUp2_Bilinear_16_Any_SSE41;
8551
0
  }
8552
0
#endif
8553
8554
0
#ifdef HAS_SCALEUVROWUP2_BILINEAR_16_AVX2
8555
0
  if (TestCpuFlag(kCpuHasAVX2)) {
8556
0
    Scale2RowUp_Bilinear_16 = ScaleUVRowUp2_Bilinear_16_Any_AVX2;
8557
0
  }
8558
0
#endif
8559
8560
#ifdef HAS_SCALEUVROWUP2_BILINEAR_16_NEON
8561
  if (TestCpuFlag(kCpuHasNEON)) {
8562
    Scale2RowUp_Bilinear_16 = ScaleUVRowUp2_Bilinear_16_Any_NEON;
8563
  }
8564
#endif
8565
8566
  // alloc 2 lines temp
8567
0
  const int row_size = (2 * width + 31) & ~31;
8568
0
  align_buffer_64(row, row_size * 2 * sizeof(uint16_t));
8569
0
  uint16_t* temp_uv_1 = (uint16_t*)(row);
8570
0
  uint16_t* temp_uv_2 = (uint16_t*)(row) + row_size;
8571
0
  if (!row)
8572
0
    return 1;
8573
8574
0
  Scale2RowUp_Bilinear_16(src_uv, 0, temp_uv_1, row_size, width);
8575
0
  P410ToARGBRow(src_y, temp_uv_1, dst_argb, yuvconstants, width);
8576
0
  dst_argb += dst_stride_argb;
8577
0
  src_y += src_stride_y;
8578
8579
0
  for (y = 0; y < height - 2; y += 2) {
8580
0
    Scale2RowUp_Bilinear_16(src_uv, src_stride_uv, temp_uv_1, row_size, width);
8581
0
    P410ToARGBRow(src_y, temp_uv_1, dst_argb, yuvconstants, width);
8582
0
    dst_argb += dst_stride_argb;
8583
0
    src_y += src_stride_y;
8584
0
    P410ToARGBRow(src_y, temp_uv_2, dst_argb, yuvconstants, width);
8585
0
    dst_argb += dst_stride_argb;
8586
0
    src_y += src_stride_y;
8587
0
    src_uv += src_stride_uv;
8588
0
  }
8589
8590
0
  if (!(height & 1)) {
8591
0
    Scale2RowUp_Bilinear_16(src_uv, 0, temp_uv_1, row_size, width);
8592
0
    P410ToARGBRow(src_y, temp_uv_1, dst_argb, yuvconstants, width);
8593
0
  }
8594
8595
0
  free_aligned_buffer_64(row);
8596
0
  return 0;
8597
0
}
8598
8599
static int P210ToARGBMatrixLinear(const uint16_t* src_y,
8600
                                  int src_stride_y,
8601
                                  const uint16_t* src_uv,
8602
                                  int src_stride_uv,
8603
                                  uint8_t* dst_argb,
8604
                                  int dst_stride_argb,
8605
                                  const struct YuvConstants* yuvconstants,
8606
                                  int width,
8607
0
                                  int height) {
8608
0
  int y;
8609
0
  void (*P410ToARGBRow)(
8610
0
      const uint16_t* y_buf, const uint16_t* uv_buf, uint8_t* rgb_buf,
8611
0
      const struct YuvConstants* yuvconstants, int width) = P410ToARGBRow_C;
8612
0
  void (*ScaleRowUp2_Linear)(const uint16_t* src_uv, uint16_t* dst_uv,
8613
0
                             int dst_width) = ScaleUVRowUp2_Linear_16_Any_C;
8614
0
  assert(yuvconstants);
8615
0
  if (!src_y || !src_uv || !dst_argb || width <= 0 || height == 0) {
8616
0
    return -1;
8617
0
  }
8618
  // Negative height means invert the image.
8619
0
  if (height < 0) {
8620
0
    height = -height;
8621
0
    dst_argb = dst_argb + (height - 1) * dst_stride_argb;
8622
0
    dst_stride_argb = -dst_stride_argb;
8623
0
  }
8624
0
#if defined(HAS_P410TOARGBROW_SSSE3)
8625
0
  if (TestCpuFlag(kCpuHasSSSE3)) {
8626
0
    P410ToARGBRow = P410ToARGBRow_Any_SSSE3;
8627
0
    if (IS_ALIGNED(width, 8)) {
8628
0
      P410ToARGBRow = P410ToARGBRow_SSSE3;
8629
0
    }
8630
0
  }
8631
0
#endif
8632
0
#if defined(HAS_P410TOARGBROW_AVX2)
8633
0
  if (TestCpuFlag(kCpuHasAVX2)) {
8634
0
    P410ToARGBRow = P410ToARGBRow_Any_AVX2;
8635
0
    if (IS_ALIGNED(width, 16)) {
8636
0
      P410ToARGBRow = P410ToARGBRow_AVX2;
8637
0
    }
8638
0
  }
8639
0
#endif
8640
#if defined(HAS_P410TOARGBROW_NEON)
8641
  if (TestCpuFlag(kCpuHasNEON)) {
8642
    P410ToARGBRow = P410ToARGBRow_Any_NEON;
8643
    if (IS_ALIGNED(width, 8)) {
8644
      P410ToARGBRow = P410ToARGBRow_NEON;
8645
    }
8646
  }
8647
#endif
8648
#if defined(HAS_P410TOARGBROW_SVE2)
8649
  if (TestCpuFlag(kCpuHasSVE2)) {
8650
    P410ToARGBRow = P410ToARGBRow_SVE2;
8651
  }
8652
#endif
8653
#if defined(HAS_P410TOARGBROW_SME)
8654
  if (TestCpuFlag(kCpuHasSME)) {
8655
    P410ToARGBRow = P410ToARGBRow_SME;
8656
  }
8657
#endif
8658
8659
0
#ifdef HAS_SCALEUVROWUP2_LINEAR_16_SSE41
8660
0
  if (TestCpuFlag(kCpuHasSSE41)) {
8661
0
    ScaleRowUp2_Linear = ScaleUVRowUp2_Linear_16_Any_SSE41;
8662
0
  }
8663
0
#endif
8664
8665
0
#ifdef HAS_SCALEUVROWUP2_LINEAR_16_AVX2
8666
0
  if (TestCpuFlag(kCpuHasAVX2)) {
8667
0
    ScaleRowUp2_Linear = ScaleUVRowUp2_Linear_16_Any_AVX2;
8668
0
  }
8669
0
#endif
8670
8671
#ifdef HAS_SCALEUVROWUP2_LINEAR_16_NEON
8672
  if (TestCpuFlag(kCpuHasNEON)) {
8673
    ScaleRowUp2_Linear = ScaleUVRowUp2_Linear_16_Any_NEON;
8674
  }
8675
#endif
8676
8677
0
  const int row_size = (2 * width + 31) & ~31;
8678
0
  align_buffer_64(row, row_size * sizeof(uint16_t));
8679
0
  uint16_t* temp_uv = (uint16_t*)(row);
8680
0
  if (!row)
8681
0
    return 1;
8682
8683
0
  for (y = 0; y < height; ++y) {
8684
0
    ScaleRowUp2_Linear(src_uv, temp_uv, width);
8685
0
    P410ToARGBRow(src_y, temp_uv, dst_argb, yuvconstants, width);
8686
0
    dst_argb += dst_stride_argb;
8687
0
    src_y += src_stride_y;
8688
0
    src_uv += src_stride_uv;
8689
0
  }
8690
8691
0
  free_aligned_buffer_64(row);
8692
0
  return 0;
8693
0
}
8694
8695
static int P010ToAR30MatrixBilinear(const uint16_t* src_y,
8696
                                    int src_stride_y,
8697
                                    const uint16_t* src_uv,
8698
                                    int src_stride_uv,
8699
                                    uint8_t* dst_ar30,
8700
                                    int dst_stride_ar30,
8701
                                    const struct YuvConstants* yuvconstants,
8702
                                    int width,
8703
0
                                    int height) {
8704
0
  int y;
8705
0
  void (*P410ToAR30Row)(
8706
0
      const uint16_t* y_buf, const uint16_t* uv_buf, uint8_t* rgb_buf,
8707
0
      const struct YuvConstants* yuvconstants, int width) = P410ToAR30Row_C;
8708
0
  void (*Scale2RowUp_Bilinear_16)(
8709
0
      const uint16_t* src_ptr, ptrdiff_t src_stride, uint16_t* dst_ptr,
8710
0
      ptrdiff_t dst_stride, int dst_width) = ScaleUVRowUp2_Bilinear_16_Any_C;
8711
0
  assert(yuvconstants);
8712
0
  if (!src_y || !src_uv || !dst_ar30 || width <= 0 || height == 0) {
8713
0
    return -1;
8714
0
  }
8715
  // Negative height means invert the image.
8716
0
  if (height < 0) {
8717
0
    height = -height;
8718
0
    dst_ar30 = dst_ar30 + (height - 1) * dst_stride_ar30;
8719
0
    dst_stride_ar30 = -dst_stride_ar30;
8720
0
  }
8721
0
#if defined(HAS_P410TOAR30ROW_SSSE3)
8722
0
  if (TestCpuFlag(kCpuHasSSSE3)) {
8723
0
    P410ToAR30Row = P410ToAR30Row_Any_SSSE3;
8724
0
    if (IS_ALIGNED(width, 8)) {
8725
0
      P410ToAR30Row = P410ToAR30Row_SSSE3;
8726
0
    }
8727
0
  }
8728
0
#endif
8729
0
#if defined(HAS_P410TOAR30ROW_AVX2)
8730
0
  if (TestCpuFlag(kCpuHasAVX2)) {
8731
0
    P410ToAR30Row = P410ToAR30Row_Any_AVX2;
8732
0
    if (IS_ALIGNED(width, 16)) {
8733
0
      P410ToAR30Row = P410ToAR30Row_AVX2;
8734
0
    }
8735
0
  }
8736
0
#endif
8737
#if defined(HAS_P410TOAR30ROW_NEON)
8738
  if (TestCpuFlag(kCpuHasNEON)) {
8739
    P410ToAR30Row = P410ToAR30Row_Any_NEON;
8740
    if (IS_ALIGNED(width, 8)) {
8741
      P410ToAR30Row = P410ToAR30Row_NEON;
8742
    }
8743
  }
8744
#endif
8745
#if defined(HAS_P410TOAR30ROW_SVE2)
8746
  if (TestCpuFlag(kCpuHasSVE2)) {
8747
    P410ToAR30Row = P410ToAR30Row_SVE2;
8748
  }
8749
#endif
8750
#if defined(HAS_P410TOAR30ROW_SME)
8751
  if (TestCpuFlag(kCpuHasSME)) {
8752
    P410ToAR30Row = P410ToAR30Row_SME;
8753
  }
8754
#endif
8755
8756
0
#ifdef HAS_SCALEUVROWUP2_BILINEAR_16_SSE41
8757
0
  if (TestCpuFlag(kCpuHasSSE41)) {
8758
0
    Scale2RowUp_Bilinear_16 = ScaleUVRowUp2_Bilinear_16_Any_SSE41;
8759
0
  }
8760
0
#endif
8761
8762
0
#ifdef HAS_SCALEUVROWUP2_BILINEAR_16_AVX2
8763
0
  if (TestCpuFlag(kCpuHasAVX2)) {
8764
0
    Scale2RowUp_Bilinear_16 = ScaleUVRowUp2_Bilinear_16_Any_AVX2;
8765
0
  }
8766
0
#endif
8767
8768
#ifdef HAS_SCALEUVROWUP2_BILINEAR_16_NEON
8769
  if (TestCpuFlag(kCpuHasNEON)) {
8770
    Scale2RowUp_Bilinear_16 = ScaleUVRowUp2_Bilinear_16_Any_NEON;
8771
  }
8772
#endif
8773
8774
  // alloc 2 lines temp
8775
0
  const int row_size = (2 * width + 31) & ~31;
8776
0
  align_buffer_64(row, row_size * 2 * sizeof(uint16_t));
8777
0
  uint16_t* temp_uv_1 = (uint16_t*)(row);
8778
0
  uint16_t* temp_uv_2 = (uint16_t*)(row) + row_size;
8779
0
  if (!row)
8780
0
    return 1;
8781
8782
0
  Scale2RowUp_Bilinear_16(src_uv, 0, temp_uv_1, row_size, width);
8783
0
  P410ToAR30Row(src_y, temp_uv_1, dst_ar30, yuvconstants, width);
8784
0
  dst_ar30 += dst_stride_ar30;
8785
0
  src_y += src_stride_y;
8786
8787
0
  for (y = 0; y < height - 2; y += 2) {
8788
0
    Scale2RowUp_Bilinear_16(src_uv, src_stride_uv, temp_uv_1, row_size, width);
8789
0
    P410ToAR30Row(src_y, temp_uv_1, dst_ar30, yuvconstants, width);
8790
0
    dst_ar30 += dst_stride_ar30;
8791
0
    src_y += src_stride_y;
8792
0
    P410ToAR30Row(src_y, temp_uv_2, dst_ar30, yuvconstants, width);
8793
0
    dst_ar30 += dst_stride_ar30;
8794
0
    src_y += src_stride_y;
8795
0
    src_uv += src_stride_uv;
8796
0
  }
8797
8798
0
  if (!(height & 1)) {
8799
0
    Scale2RowUp_Bilinear_16(src_uv, 0, temp_uv_1, row_size, width);
8800
0
    P410ToAR30Row(src_y, temp_uv_1, dst_ar30, yuvconstants, width);
8801
0
  }
8802
8803
0
  free_aligned_buffer_64(row);
8804
0
  return 0;
8805
0
}
8806
8807
static int P210ToAR30MatrixLinear(const uint16_t* src_y,
8808
                                  int src_stride_y,
8809
                                  const uint16_t* src_uv,
8810
                                  int src_stride_uv,
8811
                                  uint8_t* dst_ar30,
8812
                                  int dst_stride_ar30,
8813
                                  const struct YuvConstants* yuvconstants,
8814
                                  int width,
8815
0
                                  int height) {
8816
0
  int y;
8817
0
  void (*P410ToAR30Row)(
8818
0
      const uint16_t* y_buf, const uint16_t* uv_buf, uint8_t* rgb_buf,
8819
0
      const struct YuvConstants* yuvconstants, int width) = P410ToAR30Row_C;
8820
0
  void (*ScaleRowUp2_Linear)(const uint16_t* src_uv, uint16_t* dst_uv,
8821
0
                             int dst_width) = ScaleUVRowUp2_Linear_16_Any_C;
8822
0
  assert(yuvconstants);
8823
0
  if (!src_y || !src_uv || !dst_ar30 || width <= 0 || height == 0) {
8824
0
    return -1;
8825
0
  }
8826
  // Negative height means invert the image.
8827
0
  if (height < 0) {
8828
0
    height = -height;
8829
0
    dst_ar30 = dst_ar30 + (height - 1) * dst_stride_ar30;
8830
0
    dst_stride_ar30 = -dst_stride_ar30;
8831
0
  }
8832
0
#if defined(HAS_P410TOAR30ROW_SSSE3)
8833
0
  if (TestCpuFlag(kCpuHasSSSE3)) {
8834
0
    P410ToAR30Row = P410ToAR30Row_Any_SSSE3;
8835
0
    if (IS_ALIGNED(width, 8)) {
8836
0
      P410ToAR30Row = P410ToAR30Row_SSSE3;
8837
0
    }
8838
0
  }
8839
0
#endif
8840
0
#if defined(HAS_P410TOAR30ROW_AVX2)
8841
0
  if (TestCpuFlag(kCpuHasAVX2)) {
8842
0
    P410ToAR30Row = P410ToAR30Row_Any_AVX2;
8843
0
    if (IS_ALIGNED(width, 16)) {
8844
0
      P410ToAR30Row = P410ToAR30Row_AVX2;
8845
0
    }
8846
0
  }
8847
0
#endif
8848
#if defined(HAS_P410TOAR30ROW_NEON)
8849
  if (TestCpuFlag(kCpuHasNEON)) {
8850
    P410ToAR30Row = P410ToAR30Row_Any_NEON;
8851
    if (IS_ALIGNED(width, 8)) {
8852
      P410ToAR30Row = P410ToAR30Row_NEON;
8853
    }
8854
  }
8855
#endif
8856
#if defined(HAS_P410TOAR30ROW_SVE2)
8857
  if (TestCpuFlag(kCpuHasSVE2)) {
8858
    P410ToAR30Row = P410ToAR30Row_SVE2;
8859
  }
8860
#endif
8861
#if defined(HAS_P410TOAR30ROW_SME)
8862
  if (TestCpuFlag(kCpuHasSME)) {
8863
    P410ToAR30Row = P410ToAR30Row_SME;
8864
  }
8865
#endif
8866
8867
0
#ifdef HAS_SCALEUVROWUP2_LINEAR_16_SSE41
8868
0
  if (TestCpuFlag(kCpuHasSSE41)) {
8869
0
    ScaleRowUp2_Linear = ScaleUVRowUp2_Linear_16_Any_SSE41;
8870
0
  }
8871
0
#endif
8872
8873
0
#ifdef HAS_SCALEUVROWUP2_LINEAR_16_AVX2
8874
0
  if (TestCpuFlag(kCpuHasAVX2)) {
8875
0
    ScaleRowUp2_Linear = ScaleUVRowUp2_Linear_16_Any_AVX2;
8876
0
  }
8877
0
#endif
8878
8879
#ifdef HAS_SCALEUVROWUP2_LINEAR_16_NEON
8880
  if (TestCpuFlag(kCpuHasNEON)) {
8881
    ScaleRowUp2_Linear = ScaleUVRowUp2_Linear_16_Any_NEON;
8882
  }
8883
#endif
8884
8885
0
  const int row_size = (2 * width + 31) & ~31;
8886
0
  align_buffer_64(row, row_size * sizeof(uint16_t));
8887
0
  uint16_t* temp_uv = (uint16_t*)(row);
8888
0
  if (!row)
8889
0
    return 1;
8890
8891
0
  for (y = 0; y < height; ++y) {
8892
0
    ScaleRowUp2_Linear(src_uv, temp_uv, width);
8893
0
    P410ToAR30Row(src_y, temp_uv, dst_ar30, yuvconstants, width);
8894
0
    dst_ar30 += dst_stride_ar30;
8895
0
    src_y += src_stride_y;
8896
0
    src_uv += src_stride_uv;
8897
0
  }
8898
8899
0
  free_aligned_buffer_64(row);
8900
0
  return 0;
8901
0
}
8902
8903
static int I422ToRGB24MatrixLinear(const uint8_t* src_y,
8904
                                   int src_stride_y,
8905
                                   const uint8_t* src_u,
8906
                                   int src_stride_u,
8907
                                   const uint8_t* src_v,
8908
                                   int src_stride_v,
8909
                                   uint8_t* dst_rgb24,
8910
                                   int dst_stride_rgb24,
8911
                                   const struct YuvConstants* yuvconstants,
8912
                                   int width,
8913
146
                                   int height) {
8914
146
  int y;
8915
146
  void (*I444ToRGB24Row)(const uint8_t* y_buf, const uint8_t* u_buf,
8916
146
                         const uint8_t* v_buf, uint8_t* rgb_buf,
8917
146
                         const struct YuvConstants* yuvconstants, int width) =
8918
146
      I444ToRGB24Row_C;
8919
146
  void (*ScaleRowUp2_Linear)(const uint8_t* src_ptr, uint8_t* dst_ptr,
8920
146
                             int dst_width) = ScaleRowUp2_Linear_Any_C;
8921
146
  assert(yuvconstants);
8922
146
  if (!src_y || !src_u || !src_v || !dst_rgb24 || width <= 0 || height == 0) {
8923
0
    return -1;
8924
0
  }
8925
  // Negative height means invert the image.
8926
146
  if (height < 0) {
8927
0
    height = -height;
8928
0
    dst_rgb24 = dst_rgb24 + (height - 1) * dst_stride_rgb24;
8929
0
    dst_stride_rgb24 = -dst_stride_rgb24;
8930
0
  }
8931
146
#if defined(HAS_I444TORGB24ROW_SSSE3)
8932
146
  if (TestCpuFlag(kCpuHasSSSE3)) {
8933
146
    I444ToRGB24Row = I444ToRGB24Row_Any_SSSE3;
8934
146
    if (IS_ALIGNED(width, 16)) {
8935
42
      I444ToRGB24Row = I444ToRGB24Row_SSSE3;
8936
42
    }
8937
146
  }
8938
146
#endif
8939
146
#if defined(HAS_I444TORGB24ROW_AVX2)
8940
146
  if (TestCpuFlag(kCpuHasAVX2)) {
8941
146
    I444ToRGB24Row = I444ToRGB24Row_Any_AVX2;
8942
146
    if (IS_ALIGNED(width, 32)) {
8943
17
      I444ToRGB24Row = I444ToRGB24Row_AVX2;
8944
17
    }
8945
146
  }
8946
146
#endif
8947
#if defined(HAS_I444TORGB24ROW_NEON)
8948
  if (TestCpuFlag(kCpuHasNEON)) {
8949
    I444ToRGB24Row = I444ToRGB24Row_Any_NEON;
8950
    if (IS_ALIGNED(width, 8)) {
8951
      I444ToRGB24Row = I444ToRGB24Row_NEON;
8952
    }
8953
  }
8954
#endif
8955
#if defined(HAS_I444TORGB24ROW_RVV)
8956
  if (TestCpuFlag(kCpuHasRVV)) {
8957
    I444ToRGB24Row = I444ToRGB24Row_RVV;
8958
  }
8959
#endif
8960
146
#if defined(HAS_SCALEROWUP2_LINEAR_SSE2)
8961
146
  if (TestCpuFlag(kCpuHasSSE2)) {
8962
146
    ScaleRowUp2_Linear = ScaleRowUp2_Linear_Any_SSE2;
8963
146
  }
8964
146
#endif
8965
146
#if defined(HAS_SCALEROWUP2_LINEAR_SSSE3)
8966
146
  if (TestCpuFlag(kCpuHasSSSE3)) {
8967
146
    ScaleRowUp2_Linear = ScaleRowUp2_Linear_Any_SSSE3;
8968
146
  }
8969
146
#endif
8970
146
#if defined(HAS_SCALEROWUP2_LINEAR_AVX2)
8971
146
  if (TestCpuFlag(kCpuHasAVX2)) {
8972
146
    ScaleRowUp2_Linear = ScaleRowUp2_Linear_Any_AVX2;
8973
146
  }
8974
146
#endif
8975
#if defined(HAS_SCALEROWUP2_LINEAR_NEON)
8976
  if (TestCpuFlag(kCpuHasNEON)) {
8977
    ScaleRowUp2_Linear = ScaleRowUp2_Linear_Any_NEON;
8978
  }
8979
#endif
8980
#if defined(HAS_SCALEROWUP2_LINEAR_RVV)
8981
  if (TestCpuFlag(kCpuHasRVV)) {
8982
    ScaleRowUp2_Linear = ScaleRowUp2_Linear_RVV;
8983
  }
8984
#endif
8985
8986
  // alloc 2 lines temp
8987
146
  const int row_size = (width + 31) & ~31;
8988
146
  align_buffer_64(row, row_size * 2);
8989
146
  uint8_t* temp_u = row;
8990
146
  uint8_t* temp_v = row + row_size;
8991
146
  if (!row)
8992
0
    return 1;
8993
8994
2.23k
  for (y = 0; y < height; ++y) {
8995
2.09k
    ScaleRowUp2_Linear(src_u, temp_u, width);
8996
2.09k
    ScaleRowUp2_Linear(src_v, temp_v, width);
8997
2.09k
    I444ToRGB24Row(src_y, temp_u, temp_v, dst_rgb24, yuvconstants, width);
8998
2.09k
    dst_rgb24 += dst_stride_rgb24;
8999
2.09k
    src_y += src_stride_y;
9000
2.09k
    src_u += src_stride_u;
9001
2.09k
    src_v += src_stride_v;
9002
2.09k
  }
9003
9004
146
  free_aligned_buffer_64(row);
9005
146
  return 0;
9006
146
}
9007
9008
LIBYUV_API
9009
int I422ToRGB24MatrixFilter(const uint8_t* src_y,
9010
                            int src_stride_y,
9011
                            const uint8_t* src_u,
9012
                            int src_stride_u,
9013
                            const uint8_t* src_v,
9014
                            int src_stride_v,
9015
                            uint8_t* dst_rgb24,
9016
                            int dst_stride_rgb24,
9017
                            const struct YuvConstants* yuvconstants,
9018
                            int width,
9019
                            int height,
9020
226
                            enum FilterMode filter) {
9021
226
  switch (filter) {
9022
80
    case kFilterNone:
9023
80
      return I422ToRGB24Matrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
9024
80
                               src_stride_v, dst_rgb24, dst_stride_rgb24,
9025
80
                               yuvconstants, width, height);
9026
146
    case kFilterBilinear:
9027
146
    case kFilterBox:
9028
146
    case kFilterLinear:
9029
146
      return I422ToRGB24MatrixLinear(
9030
146
          src_y, src_stride_y, src_u, src_stride_u, src_v, src_stride_v,
9031
146
          dst_rgb24, dst_stride_rgb24, yuvconstants, width, height);
9032
226
  }
9033
9034
0
  return -1;
9035
226
}
9036
9037
LIBYUV_API
9038
int I420ToARGBMatrixFilter(const uint8_t* src_y,
9039
                           int src_stride_y,
9040
                           const uint8_t* src_u,
9041
                           int src_stride_u,
9042
                           const uint8_t* src_v,
9043
                           int src_stride_v,
9044
                           uint8_t* dst_argb,
9045
                           int dst_stride_argb,
9046
                           const struct YuvConstants* yuvconstants,
9047
                           int width,
9048
                           int height,
9049
307
                           enum FilterMode filter) {
9050
307
  switch (filter) {
9051
152
    case kFilterNone:
9052
152
      return I420ToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
9053
152
                              src_stride_v, dst_argb, dst_stride_argb,
9054
152
                              yuvconstants, width, height);
9055
155
    case kFilterBilinear:
9056
155
    case kFilterBox:
9057
155
      return I420ToARGBMatrixBilinear(
9058
155
          src_y, src_stride_y, src_u, src_stride_u, src_v, src_stride_v,
9059
155
          dst_argb, dst_stride_argb, yuvconstants, width, height);
9060
0
    case kFilterLinear:
9061
      // Actually we can do this, but probably there's no usage.
9062
0
      return -1;
9063
307
  }
9064
9065
0
  return -1;
9066
307
}
9067
9068
LIBYUV_API
9069
int I422ToARGBMatrixFilter(const uint8_t* src_y,
9070
                           int src_stride_y,
9071
                           const uint8_t* src_u,
9072
                           int src_stride_u,
9073
                           const uint8_t* src_v,
9074
                           int src_stride_v,
9075
                           uint8_t* dst_argb,
9076
                           int dst_stride_argb,
9077
                           const struct YuvConstants* yuvconstants,
9078
                           int width,
9079
                           int height,
9080
264
                           enum FilterMode filter) {
9081
264
  switch (filter) {
9082
108
    case kFilterNone:
9083
108
      return I422ToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
9084
108
                              src_stride_v, dst_argb, dst_stride_argb,
9085
108
                              yuvconstants, width, height);
9086
156
    case kFilterBilinear:
9087
156
    case kFilterBox:
9088
156
    case kFilterLinear:
9089
156
      return I422ToARGBMatrixLinear(
9090
156
          src_y, src_stride_y, src_u, src_stride_u, src_v, src_stride_v,
9091
156
          dst_argb, dst_stride_argb, yuvconstants, width, height);
9092
264
  }
9093
9094
0
  return -1;
9095
264
}
9096
9097
LIBYUV_API
9098
int I420ToRGB24MatrixFilter(const uint8_t* src_y,
9099
                            int src_stride_y,
9100
                            const uint8_t* src_u,
9101
                            int src_stride_u,
9102
                            const uint8_t* src_v,
9103
                            int src_stride_v,
9104
                            uint8_t* dst_rgb24,
9105
                            int dst_stride_rgb24,
9106
                            const struct YuvConstants* yuvconstants,
9107
                            int width,
9108
                            int height,
9109
272
                            enum FilterMode filter) {
9110
272
  switch (filter) {
9111
183
    case kFilterNone:
9112
183
      return I420ToRGB24Matrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
9113
183
                               src_stride_v, dst_rgb24, dst_stride_rgb24,
9114
183
                               yuvconstants, width, height);
9115
0
    case kFilterLinear:  // TODO(fb): Implement Linear using Bilinear stride 0
9116
88
    case kFilterBilinear:
9117
88
    case kFilterBox:
9118
88
      return I420ToRGB24MatrixBilinear(
9119
88
          src_y, src_stride_y, src_u, src_stride_u, src_v, src_stride_v,
9120
88
          dst_rgb24, dst_stride_rgb24, yuvconstants, width, height);
9121
272
  }
9122
9123
0
  return -1;
9124
272
}
9125
9126
LIBYUV_API
9127
int I010ToAR30MatrixFilter(const uint16_t* src_y,
9128
                           int src_stride_y,
9129
                           const uint16_t* src_u,
9130
                           int src_stride_u,
9131
                           const uint16_t* src_v,
9132
                           int src_stride_v,
9133
                           uint8_t* dst_ar30,
9134
                           int dst_stride_ar30,
9135
                           const struct YuvConstants* yuvconstants,
9136
                           int width,
9137
                           int height,
9138
0
                           enum FilterMode filter) {
9139
0
  switch (filter) {
9140
0
    case kFilterNone:
9141
0
      return I010ToAR30Matrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
9142
0
                              src_stride_v, dst_ar30, dst_stride_ar30,
9143
0
                              yuvconstants, width, height);
9144
0
    case kFilterLinear:  // TODO(fb): Implement Linear using Bilinear stride 0
9145
0
    case kFilterBilinear:
9146
0
    case kFilterBox:
9147
0
      return I010ToAR30MatrixBilinear(
9148
0
          src_y, src_stride_y, src_u, src_stride_u, src_v, src_stride_v,
9149
0
          dst_ar30, dst_stride_ar30, yuvconstants, width, height);
9150
0
  }
9151
9152
0
  return -1;
9153
0
}
9154
9155
LIBYUV_API
9156
int I210ToAR30MatrixFilter(const uint16_t* src_y,
9157
                           int src_stride_y,
9158
                           const uint16_t* src_u,
9159
                           int src_stride_u,
9160
                           const uint16_t* src_v,
9161
                           int src_stride_v,
9162
                           uint8_t* dst_ar30,
9163
                           int dst_stride_ar30,
9164
                           const struct YuvConstants* yuvconstants,
9165
                           int width,
9166
                           int height,
9167
0
                           enum FilterMode filter) {
9168
0
  switch (filter) {
9169
0
    case kFilterNone:
9170
0
      return I210ToAR30Matrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
9171
0
                              src_stride_v, dst_ar30, dst_stride_ar30,
9172
0
                              yuvconstants, width, height);
9173
0
    case kFilterBilinear:
9174
0
    case kFilterBox:
9175
0
    case kFilterLinear:
9176
0
      return I210ToAR30MatrixLinear(
9177
0
          src_y, src_stride_y, src_u, src_stride_u, src_v, src_stride_v,
9178
0
          dst_ar30, dst_stride_ar30, yuvconstants, width, height);
9179
0
  }
9180
9181
0
  return -1;
9182
0
}
9183
9184
LIBYUV_API
9185
int I010ToARGBMatrixFilter(const uint16_t* src_y,
9186
                           int src_stride_y,
9187
                           const uint16_t* src_u,
9188
                           int src_stride_u,
9189
                           const uint16_t* src_v,
9190
                           int src_stride_v,
9191
                           uint8_t* dst_argb,
9192
                           int dst_stride_argb,
9193
                           const struct YuvConstants* yuvconstants,
9194
                           int width,
9195
                           int height,
9196
217
                           enum FilterMode filter) {
9197
217
  switch (filter) {
9198
128
    case kFilterNone:
9199
128
      return I010ToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
9200
128
                              src_stride_v, dst_argb, dst_stride_argb,
9201
128
                              yuvconstants, width, height);
9202
0
    case kFilterLinear:  // TODO(fb): Implement Linear using Bilinear stride 0
9203
89
    case kFilterBilinear:
9204
89
    case kFilterBox:
9205
89
      return I010ToARGBMatrixBilinear(
9206
89
          src_y, src_stride_y, src_u, src_stride_u, src_v, src_stride_v,
9207
89
          dst_argb, dst_stride_argb, yuvconstants, width, height);
9208
217
  }
9209
9210
0
  return -1;
9211
217
}
9212
9213
LIBYUV_API
9214
int I210ToARGBMatrixFilter(const uint16_t* src_y,
9215
                           int src_stride_y,
9216
                           const uint16_t* src_u,
9217
                           int src_stride_u,
9218
                           const uint16_t* src_v,
9219
                           int src_stride_v,
9220
                           uint8_t* dst_argb,
9221
                           int dst_stride_argb,
9222
                           const struct YuvConstants* yuvconstants,
9223
                           int width,
9224
                           int height,
9225
240
                           enum FilterMode filter) {
9226
240
  switch (filter) {
9227
65
    case kFilterNone:
9228
65
      return I210ToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
9229
65
                              src_stride_v, dst_argb, dst_stride_argb,
9230
65
                              yuvconstants, width, height);
9231
175
    case kFilterBilinear:
9232
175
    case kFilterBox:
9233
175
    case kFilterLinear:
9234
175
      return I210ToARGBMatrixLinear(
9235
175
          src_y, src_stride_y, src_u, src_stride_u, src_v, src_stride_v,
9236
175
          dst_argb, dst_stride_argb, yuvconstants, width, height);
9237
240
  }
9238
9239
0
  return -1;
9240
240
}
9241
9242
LIBYUV_API
9243
int I420AlphaToARGBMatrixFilter(const uint8_t* src_y,
9244
                                int src_stride_y,
9245
                                const uint8_t* src_u,
9246
                                int src_stride_u,
9247
                                const uint8_t* src_v,
9248
                                int src_stride_v,
9249
                                const uint8_t* src_a,
9250
                                int src_stride_a,
9251
                                uint8_t* dst_argb,
9252
                                int dst_stride_argb,
9253
                                const struct YuvConstants* yuvconstants,
9254
                                int width,
9255
                                int height,
9256
                                int attenuate,
9257
179
                                enum FilterMode filter) {
9258
179
  switch (filter) {
9259
131
    case kFilterNone:
9260
131
      return I420AlphaToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u,
9261
131
                                   src_v, src_stride_v, src_a, src_stride_a,
9262
131
                                   dst_argb, dst_stride_argb, yuvconstants,
9263
131
                                   width, height, attenuate);
9264
0
    case kFilterLinear:  // TODO(fb): Implement Linear using Bilinear stride 0
9265
48
    case kFilterBilinear:
9266
48
    case kFilterBox:
9267
48
      return I420AlphaToARGBMatrixBilinear(
9268
48
          src_y, src_stride_y, src_u, src_stride_u, src_v, src_stride_v, src_a,
9269
48
          src_stride_a, dst_argb, dst_stride_argb, yuvconstants, width, height,
9270
48
          attenuate);
9271
179
  }
9272
9273
0
  return -1;
9274
179
}
9275
9276
LIBYUV_API
9277
int I422AlphaToARGBMatrixFilter(const uint8_t* src_y,
9278
                                int src_stride_y,
9279
                                const uint8_t* src_u,
9280
                                int src_stride_u,
9281
                                const uint8_t* src_v,
9282
                                int src_stride_v,
9283
                                const uint8_t* src_a,
9284
                                int src_stride_a,
9285
                                uint8_t* dst_argb,
9286
                                int dst_stride_argb,
9287
                                const struct YuvConstants* yuvconstants,
9288
                                int width,
9289
                                int height,
9290
                                int attenuate,
9291
216
                                enum FilterMode filter) {
9292
216
  switch (filter) {
9293
93
    case kFilterNone:
9294
93
      return I422AlphaToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u,
9295
93
                                   src_v, src_stride_v, src_a, src_stride_a,
9296
93
                                   dst_argb, dst_stride_argb, yuvconstants,
9297
93
                                   width, height, attenuate);
9298
123
    case kFilterBilinear:
9299
123
    case kFilterBox:
9300
123
    case kFilterLinear:
9301
123
      return I422AlphaToARGBMatrixLinear(
9302
123
          src_y, src_stride_y, src_u, src_stride_u, src_v, src_stride_v, src_a,
9303
123
          src_stride_a, dst_argb, dst_stride_argb, yuvconstants, width, height,
9304
123
          attenuate);
9305
216
  }
9306
9307
0
  return -1;
9308
216
}
9309
9310
LIBYUV_API
9311
int I010AlphaToARGBMatrixFilter(const uint16_t* src_y,
9312
                                int src_stride_y,
9313
                                const uint16_t* src_u,
9314
                                int src_stride_u,
9315
                                const uint16_t* src_v,
9316
                                int src_stride_v,
9317
                                const uint16_t* src_a,
9318
                                int src_stride_a,
9319
                                uint8_t* dst_argb,
9320
                                int dst_stride_argb,
9321
                                const struct YuvConstants* yuvconstants,
9322
                                int width,
9323
                                int height,
9324
                                int attenuate,
9325
162
                                enum FilterMode filter) {
9326
162
  switch (filter) {
9327
125
    case kFilterNone:
9328
125
      return I010AlphaToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u,
9329
125
                                   src_v, src_stride_v, src_a, src_stride_a,
9330
125
                                   dst_argb, dst_stride_argb, yuvconstants,
9331
125
                                   width, height, attenuate);
9332
0
    case kFilterLinear:  // TODO(fb): Implement Linear using Bilinear stride 0
9333
37
    case kFilterBilinear:
9334
37
    case kFilterBox:
9335
37
      return I010AlphaToARGBMatrixBilinear(
9336
37
          src_y, src_stride_y, src_u, src_stride_u, src_v, src_stride_v, src_a,
9337
37
          src_stride_a, dst_argb, dst_stride_argb, yuvconstants, width, height,
9338
37
          attenuate);
9339
162
  }
9340
9341
0
  return -1;
9342
162
}
9343
9344
LIBYUV_API
9345
int I210AlphaToARGBMatrixFilter(const uint16_t* src_y,
9346
                                int src_stride_y,
9347
                                const uint16_t* src_u,
9348
                                int src_stride_u,
9349
                                const uint16_t* src_v,
9350
                                int src_stride_v,
9351
                                const uint16_t* src_a,
9352
                                int src_stride_a,
9353
                                uint8_t* dst_argb,
9354
                                int dst_stride_argb,
9355
                                const struct YuvConstants* yuvconstants,
9356
                                int width,
9357
                                int height,
9358
                                int attenuate,
9359
180
                                enum FilterMode filter) {
9360
180
  switch (filter) {
9361
84
    case kFilterNone:
9362
84
      return I210AlphaToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u,
9363
84
                                   src_v, src_stride_v, src_a, src_stride_a,
9364
84
                                   dst_argb, dst_stride_argb, yuvconstants,
9365
84
                                   width, height, attenuate);
9366
96
    case kFilterBilinear:
9367
96
    case kFilterBox:
9368
96
    case kFilterLinear:
9369
96
      return I210AlphaToARGBMatrixLinear(
9370
96
          src_y, src_stride_y, src_u, src_stride_u, src_v, src_stride_v, src_a,
9371
96
          src_stride_a, dst_argb, dst_stride_argb, yuvconstants, width, height,
9372
96
          attenuate);
9373
180
  }
9374
9375
0
  return -1;
9376
180
}
9377
9378
// TODO(fb): Verify this function works correctly.  P010 is like NV12 but 10 bit
9379
// UV is biplanar.
9380
LIBYUV_API
9381
int P010ToARGBMatrixFilter(const uint16_t* src_y,
9382
                           int src_stride_y,
9383
                           const uint16_t* src_uv,
9384
                           int src_stride_uv,
9385
                           uint8_t* dst_argb,
9386
                           int dst_stride_argb,
9387
                           const struct YuvConstants* yuvconstants,
9388
                           int width,
9389
                           int height,
9390
0
                           enum FilterMode filter) {
9391
0
  switch (filter) {
9392
0
    case kFilterNone:
9393
0
      return P010ToARGBMatrix(src_y, src_stride_y, src_uv, src_stride_uv,
9394
0
                              dst_argb, dst_stride_argb, yuvconstants, width,
9395
0
                              height);
9396
0
    case kFilterLinear:  // TODO(fb): Implement Linear using Bilinear stride 0
9397
0
    case kFilterBilinear:
9398
0
    case kFilterBox:
9399
0
      return P010ToARGBMatrixBilinear(src_y, src_stride_y, src_uv,
9400
0
                                      src_stride_uv, dst_argb, dst_stride_argb,
9401
0
                                      yuvconstants, width, height);
9402
0
  }
9403
9404
0
  return -1;
9405
0
}
9406
9407
LIBYUV_API
9408
int P210ToARGBMatrixFilter(const uint16_t* src_y,
9409
                           int src_stride_y,
9410
                           const uint16_t* src_uv,
9411
                           int src_stride_uv,
9412
                           uint8_t* dst_argb,
9413
                           int dst_stride_argb,
9414
                           const struct YuvConstants* yuvconstants,
9415
                           int width,
9416
                           int height,
9417
0
                           enum FilterMode filter) {
9418
0
  switch (filter) {
9419
0
    case kFilterNone:
9420
0
      return P210ToARGBMatrix(src_y, src_stride_y, src_uv, src_stride_uv,
9421
0
                              dst_argb, dst_stride_argb, yuvconstants, width,
9422
0
                              height);
9423
0
    case kFilterBilinear:
9424
0
    case kFilterBox:
9425
0
    case kFilterLinear:
9426
0
      return P210ToARGBMatrixLinear(src_y, src_stride_y, src_uv, src_stride_uv,
9427
0
                                    dst_argb, dst_stride_argb, yuvconstants,
9428
0
                                    width, height);
9429
0
  }
9430
9431
0
  return -1;
9432
0
}
9433
9434
LIBYUV_API
9435
int P010ToAR30MatrixFilter(const uint16_t* src_y,
9436
                           int src_stride_y,
9437
                           const uint16_t* src_uv,
9438
                           int src_stride_uv,
9439
                           uint8_t* dst_ar30,
9440
                           int dst_stride_ar30,
9441
                           const struct YuvConstants* yuvconstants,
9442
                           int width,
9443
                           int height,
9444
0
                           enum FilterMode filter) {
9445
0
  switch (filter) {
9446
0
    case kFilterNone:
9447
0
      return P010ToAR30Matrix(src_y, src_stride_y, src_uv, src_stride_uv,
9448
0
                              dst_ar30, dst_stride_ar30, yuvconstants, width,
9449
0
                              height);
9450
0
    case kFilterLinear:  // TODO(fb): Implement Linear using Bilinear stride 0
9451
0
    case kFilterBilinear:
9452
0
    case kFilterBox:
9453
0
      return P010ToAR30MatrixBilinear(src_y, src_stride_y, src_uv,
9454
0
                                      src_stride_uv, dst_ar30, dst_stride_ar30,
9455
0
                                      yuvconstants, width, height);
9456
0
  }
9457
9458
0
  return -1;
9459
0
}
9460
9461
LIBYUV_API
9462
int P210ToAR30MatrixFilter(const uint16_t* src_y,
9463
                           int src_stride_y,
9464
                           const uint16_t* src_uv,
9465
                           int src_stride_uv,
9466
                           uint8_t* dst_ar30,
9467
                           int dst_stride_ar30,
9468
                           const struct YuvConstants* yuvconstants,
9469
                           int width,
9470
                           int height,
9471
0
                           enum FilterMode filter) {
9472
0
  switch (filter) {
9473
0
    case kFilterNone:
9474
0
      return P210ToAR30Matrix(src_y, src_stride_y, src_uv, src_stride_uv,
9475
0
                              dst_ar30, dst_stride_ar30, yuvconstants, width,
9476
0
                              height);
9477
0
    case kFilterBilinear:
9478
0
    case kFilterBox:
9479
0
    case kFilterLinear:
9480
0
      return P210ToAR30MatrixLinear(src_y, src_stride_y, src_uv, src_stride_uv,
9481
0
                                    dst_ar30, dst_stride_ar30, yuvconstants,
9482
0
                                    width, height);
9483
0
  }
9484
9485
0
  return -1;
9486
0
}
9487
9488
#ifdef __cplusplus
9489
}  // extern "C"
9490
}  // namespace libyuv
9491
#endif