Coverage Report

Created: 2026-02-26 06:43

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