sw_yuv2rgb.c 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211
  1. /*
  2. * This file is part of FFmpeg.
  3. *
  4. * FFmpeg is free software; you can redistribute it and/or modify
  5. * it under the terms of the GNU General Public License as published by
  6. * the Free Software Foundation; either version 2 of the License, or
  7. * (at your option) any later version.
  8. *
  9. * FFmpeg is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU General Public License along
  15. * with FFmpeg; if not, write to the Free Software Foundation, Inc.,
  16. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  17. */
  18. #include <string.h>
  19. #include "libavutil/common.h"
  20. #include "libavutil/intreadwrite.h"
  21. #include "libavutil/mem_internal.h"
  22. #include "libavutil/pixdesc.h"
  23. #include "libswscale/swscale.h"
  24. #include "libswscale/swscale_internal.h"
  25. #include "checkasm.h"
  26. #define randomize_buffers(buf, size) \
  27. do { \
  28. for (int j = 0; j < size; j += 4) \
  29. AV_WN32(buf + j, rnd()); \
  30. } while (0)
  31. static const int dst_fmts[] = {
  32. // AV_PIX_FMT_BGR48BE,
  33. // AV_PIX_FMT_BGR48LE,
  34. // AV_PIX_FMT_RGB48BE,
  35. // AV_PIX_FMT_RGB48LE,
  36. AV_PIX_FMT_ARGB,
  37. AV_PIX_FMT_ABGR,
  38. AV_PIX_FMT_RGBA,
  39. AV_PIX_FMT_BGRA,
  40. AV_PIX_FMT_RGB24,
  41. AV_PIX_FMT_BGR24,
  42. AV_PIX_FMT_RGB565,
  43. AV_PIX_FMT_BGR565,
  44. AV_PIX_FMT_RGB555,
  45. AV_PIX_FMT_BGR555,
  46. // AV_PIX_FMT_RGB444,
  47. // AV_PIX_FMT_BGR444,
  48. // AV_PIX_FMT_RGB8,
  49. // AV_PIX_FMT_BGR8,
  50. // AV_PIX_FMT_RGB4,
  51. // AV_PIX_FMT_BGR4,
  52. // AV_PIX_FMT_RGB4_BYTE,
  53. // AV_PIX_FMT_BGR4_BYTE,
  54. // AV_PIX_FMT_MONOBLACK,
  55. };
  56. static int cmp_off_by_n(const uint8_t *ref, const uint8_t *test, size_t n, int accuracy)
  57. {
  58. for (size_t i = 0; i < n; i++) {
  59. if (abs(ref[i] - test[i]) > accuracy)
  60. return 1;
  61. }
  62. return 0;
  63. }
  64. static int cmp_555_by_n(const uint8_t *ref, const uint8_t *test, size_t n, int accuracy)
  65. {
  66. const uint16_t *ref16 = (const uint16_t *) ref;
  67. const uint16_t *test16 = (const uint16_t *) test;
  68. for (size_t i = 0; i < n; i++) {
  69. if (abs(( ref16[i] & 0x1f) - ( test16[i] & 0x1f)) > accuracy)
  70. return 1;
  71. if (abs(((ref16[i] >> 5) & 0x1f) - ((test16[i] >> 5) & 0x1f)) > accuracy)
  72. return 1;
  73. if (abs(((ref16[i] >> 10) & 0x1f) - ((test16[i] >> 10) & 0x1f)) > accuracy)
  74. return 1;
  75. }
  76. return 0;
  77. }
  78. static int cmp_565_by_n(const uint8_t *ref, const uint8_t *test, size_t n, int accuracy)
  79. {
  80. const uint16_t *ref16 = (const uint16_t *) ref;
  81. const uint16_t *test16 = (const uint16_t *) test;
  82. for (size_t i = 0; i < n; i++) {
  83. if (abs(( ref16[i] & 0x1f) - ( test16[i] & 0x1f)) > accuracy)
  84. return 1;
  85. if (abs(((ref16[i] >> 5) & 0x3f) - ((test16[i] >> 5) & 0x3f)) > accuracy)
  86. return 1;
  87. if (abs(((ref16[i] >> 11) & 0x1f) - ((test16[i] >> 11) & 0x1f)) > accuracy)
  88. return 1;
  89. }
  90. return 0;
  91. }
  92. static void check_yuv2rgb(int src_pix_fmt)
  93. {
  94. const AVPixFmtDescriptor *src_desc = av_pix_fmt_desc_get(src_pix_fmt);
  95. #define MAX_LINE_SIZE 1920
  96. static const int input_sizes[] = {8, 128, 1080, MAX_LINE_SIZE};
  97. declare_func_emms(AV_CPU_FLAG_MMX | AV_CPU_FLAG_MMXEXT,
  98. int, SwsContext *c, const uint8_t *src[],
  99. int srcStride[], int srcSliceY, int srcSliceH,
  100. uint8_t *dst[], int dstStride[]);
  101. LOCAL_ALIGNED_8(uint8_t, src_y, [MAX_LINE_SIZE * 2]);
  102. LOCAL_ALIGNED_8(uint8_t, src_u, [MAX_LINE_SIZE]);
  103. LOCAL_ALIGNED_8(uint8_t, src_v, [MAX_LINE_SIZE]);
  104. LOCAL_ALIGNED_8(uint8_t, src_a, [MAX_LINE_SIZE * 2]);
  105. const uint8_t *src[4] = { src_y, src_u, src_v, src_a };
  106. LOCAL_ALIGNED_8(uint8_t, dst0_, [2 * MAX_LINE_SIZE * 6]);
  107. uint8_t *dst0[4] = { dst0_ };
  108. uint8_t *lines0[2] = { dst0_, dst0_ + MAX_LINE_SIZE * 6 };
  109. LOCAL_ALIGNED_8(uint8_t, dst1_, [2 * MAX_LINE_SIZE * 6]);
  110. uint8_t *dst1[4] = { dst1_ };
  111. uint8_t *lines1[2] = { dst1_, dst1_ + MAX_LINE_SIZE * 6 };
  112. randomize_buffers(src_y, MAX_LINE_SIZE * 2);
  113. randomize_buffers(src_u, MAX_LINE_SIZE);
  114. randomize_buffers(src_v, MAX_LINE_SIZE);
  115. randomize_buffers(src_a, MAX_LINE_SIZE * 2);
  116. for (int dfi = 0; dfi < FF_ARRAY_ELEMS(dst_fmts); dfi++) {
  117. int dst_pix_fmt = dst_fmts[dfi];
  118. const AVPixFmtDescriptor *dst_desc = av_pix_fmt_desc_get(dst_pix_fmt);
  119. int sample_size = av_get_padded_bits_per_pixel(dst_desc) >> 3;
  120. for (int isi = 0; isi < FF_ARRAY_ELEMS(input_sizes); isi++) {
  121. struct SwsContext *ctx;
  122. int log_level;
  123. int width = input_sizes[isi];
  124. int srcSliceY = 0;
  125. int srcSliceH = 2;
  126. int srcStride[4] = {
  127. width,
  128. width >> src_desc->log2_chroma_w,
  129. width >> src_desc->log2_chroma_w,
  130. width,
  131. };
  132. int dstStride[4] = { MAX_LINE_SIZE * 6 };
  133. // override log level to prevent spamming of the message
  134. // "No accelerated colorspace conversion found from %s to %s"
  135. log_level = av_log_get_level();
  136. av_log_set_level(AV_LOG_ERROR);
  137. ctx = sws_getContext(width, srcSliceH, src_pix_fmt,
  138. width, srcSliceH, dst_pix_fmt,
  139. 0, NULL, NULL, NULL);
  140. av_log_set_level(log_level);
  141. if (!ctx)
  142. fail();
  143. if (check_func(ctx->convert_unscaled, "%s_%s_%d", src_desc->name, dst_desc->name, width)) {
  144. memset(dst0_, 0xFF, 2 * MAX_LINE_SIZE * 6);
  145. memset(dst1_, 0xFF, 2 * MAX_LINE_SIZE * 6);
  146. call_ref(ctx, src, srcStride, srcSliceY,
  147. srcSliceH, dst0, dstStride);
  148. call_new(ctx, src, srcStride, srcSliceY,
  149. srcSliceH, dst1, dstStride);
  150. if (dst_pix_fmt == AV_PIX_FMT_ARGB ||
  151. dst_pix_fmt == AV_PIX_FMT_ABGR ||
  152. dst_pix_fmt == AV_PIX_FMT_RGBA ||
  153. dst_pix_fmt == AV_PIX_FMT_BGRA ||
  154. dst_pix_fmt == AV_PIX_FMT_RGB24 ||
  155. dst_pix_fmt == AV_PIX_FMT_BGR24) {
  156. if (cmp_off_by_n(lines0[0], lines1[0], width * sample_size, 3) ||
  157. cmp_off_by_n(lines0[1], lines1[1], width * sample_size, 3))
  158. fail();
  159. } else if (dst_pix_fmt == AV_PIX_FMT_RGB565 ||
  160. dst_pix_fmt == AV_PIX_FMT_BGR565) {
  161. if (cmp_565_by_n(lines0[0], lines1[0], width, 2) ||
  162. cmp_565_by_n(lines0[1], lines1[1], width, 2))
  163. fail();
  164. } else if (dst_pix_fmt == AV_PIX_FMT_RGB555 ||
  165. dst_pix_fmt == AV_PIX_FMT_BGR555) {
  166. if (cmp_555_by_n(lines0[0], lines1[0], width, 2) ||
  167. cmp_555_by_n(lines0[1], lines1[1], width, 2))
  168. fail();
  169. } else {
  170. fail();
  171. }
  172. bench_new(ctx, src, srcStride, srcSliceY,
  173. srcSliceH, dst0, dstStride);
  174. }
  175. sws_freeContext(ctx);
  176. }
  177. }
  178. }
  179. #undef MAX_LINE_SIZE
  180. void checkasm_check_sw_yuv2rgb(void)
  181. {
  182. check_yuv2rgb(AV_PIX_FMT_YUV420P);
  183. report("yuv420p");
  184. check_yuv2rgb(AV_PIX_FMT_YUV422P);
  185. report("yuv422p");
  186. check_yuv2rgb(AV_PIX_FMT_YUVA420P);
  187. report("yuva420p");
  188. }