sw_yuv2rgb.c 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239
  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. AV_PIX_FMT_GBRP,
  56. };
  57. static int cmp_off_by_n(const uint8_t *ref, const uint8_t *test, size_t n, int accuracy)
  58. {
  59. for (size_t i = 0; i < n; i++) {
  60. if (abs(ref[i] - test[i]) > accuracy)
  61. return 1;
  62. }
  63. return 0;
  64. }
  65. static int cmp_555_by_n(const uint8_t *ref, const uint8_t *test, size_t n, int accuracy)
  66. {
  67. const uint16_t *ref16 = (const uint16_t *) ref;
  68. const uint16_t *test16 = (const uint16_t *) test;
  69. for (size_t i = 0; i < n; i++) {
  70. if (abs(( ref16[i] & 0x1f) - ( test16[i] & 0x1f)) > accuracy)
  71. return 1;
  72. if (abs(((ref16[i] >> 5) & 0x1f) - ((test16[i] >> 5) & 0x1f)) > accuracy)
  73. return 1;
  74. if (abs(((ref16[i] >> 10) & 0x1f) - ((test16[i] >> 10) & 0x1f)) > accuracy)
  75. return 1;
  76. }
  77. return 0;
  78. }
  79. static int cmp_565_by_n(const uint8_t *ref, const uint8_t *test, size_t n, int accuracy)
  80. {
  81. const uint16_t *ref16 = (const uint16_t *) ref;
  82. const uint16_t *test16 = (const uint16_t *) test;
  83. for (size_t i = 0; i < n; i++) {
  84. if (abs(( ref16[i] & 0x1f) - ( test16[i] & 0x1f)) > accuracy)
  85. return 1;
  86. if (abs(((ref16[i] >> 5) & 0x3f) - ((test16[i] >> 5) & 0x3f)) > accuracy)
  87. return 1;
  88. if (abs(((ref16[i] >> 11) & 0x1f) - ((test16[i] >> 11) & 0x1f)) > accuracy)
  89. return 1;
  90. }
  91. return 0;
  92. }
  93. static void check_yuv2rgb(int src_pix_fmt)
  94. {
  95. const AVPixFmtDescriptor *src_desc = av_pix_fmt_desc_get(src_pix_fmt);
  96. #define MAX_LINE_SIZE 1920
  97. static const int input_sizes[] = {8, 128, 1080, MAX_LINE_SIZE};
  98. declare_func_emms(AV_CPU_FLAG_MMX | AV_CPU_FLAG_MMXEXT,
  99. int, SwsContext *c, const uint8_t *src[],
  100. int srcStride[], int srcSliceY, int srcSliceH,
  101. uint8_t *dst[], int dstStride[]);
  102. LOCAL_ALIGNED_8(uint8_t, src_y, [MAX_LINE_SIZE * 2]);
  103. LOCAL_ALIGNED_8(uint8_t, src_u, [MAX_LINE_SIZE]);
  104. LOCAL_ALIGNED_8(uint8_t, src_v, [MAX_LINE_SIZE]);
  105. LOCAL_ALIGNED_8(uint8_t, src_a, [MAX_LINE_SIZE * 2]);
  106. const uint8_t *src[4] = { src_y, src_u, src_v, src_a };
  107. LOCAL_ALIGNED_8(uint8_t, dst0_0, [2 * MAX_LINE_SIZE * 6]);
  108. LOCAL_ALIGNED_8(uint8_t, dst0_1, [2 * MAX_LINE_SIZE]);
  109. LOCAL_ALIGNED_8(uint8_t, dst0_2, [2 * MAX_LINE_SIZE]);
  110. uint8_t *dst0[4] = { dst0_0, dst0_1, dst0_2 };
  111. uint8_t *lines0[4][2] = {
  112. { dst0_0, dst0_0 + MAX_LINE_SIZE * 6 },
  113. { dst0_1, dst0_1 + MAX_LINE_SIZE },
  114. { dst0_2, dst0_2 + MAX_LINE_SIZE }
  115. };
  116. LOCAL_ALIGNED_8(uint8_t, dst1_0, [2 * MAX_LINE_SIZE * 6]);
  117. LOCAL_ALIGNED_8(uint8_t, dst1_1, [2 * MAX_LINE_SIZE]);
  118. LOCAL_ALIGNED_8(uint8_t, dst1_2, [2 * MAX_LINE_SIZE]);
  119. uint8_t *dst1[4] = { dst1_0, dst1_1, dst1_2 };
  120. uint8_t *lines1[4][2] = {
  121. { dst1_0, dst1_0 + MAX_LINE_SIZE * 6 },
  122. { dst1_1, dst1_1 + MAX_LINE_SIZE },
  123. { dst1_2, dst1_2 + MAX_LINE_SIZE }
  124. };
  125. randomize_buffers(src_y, MAX_LINE_SIZE * 2);
  126. randomize_buffers(src_u, MAX_LINE_SIZE);
  127. randomize_buffers(src_v, MAX_LINE_SIZE);
  128. randomize_buffers(src_a, MAX_LINE_SIZE * 2);
  129. for (int dfi = 0; dfi < FF_ARRAY_ELEMS(dst_fmts); dfi++) {
  130. int dst_pix_fmt = dst_fmts[dfi];
  131. const AVPixFmtDescriptor *dst_desc = av_pix_fmt_desc_get(dst_pix_fmt);
  132. int sample_size = av_get_padded_bits_per_pixel(dst_desc) >> 3;
  133. for (int isi = 0; isi < FF_ARRAY_ELEMS(input_sizes); isi++) {
  134. struct SwsContext *ctx;
  135. int log_level;
  136. int width = input_sizes[isi];
  137. int srcSliceY = 0;
  138. int srcSliceH = 2;
  139. int srcStride[4] = {
  140. width,
  141. width >> src_desc->log2_chroma_w,
  142. width >> src_desc->log2_chroma_w,
  143. width,
  144. };
  145. int dstStride[4] = {
  146. MAX_LINE_SIZE * 6,
  147. MAX_LINE_SIZE,
  148. MAX_LINE_SIZE,
  149. };
  150. // override log level to prevent spamming of the message
  151. // "No accelerated colorspace conversion found from %s to %s"
  152. log_level = av_log_get_level();
  153. av_log_set_level(AV_LOG_ERROR);
  154. ctx = sws_getContext(width, srcSliceH, src_pix_fmt,
  155. width, srcSliceH, dst_pix_fmt,
  156. 0, NULL, NULL, NULL);
  157. av_log_set_level(log_level);
  158. if (!ctx)
  159. fail();
  160. if (check_func(ctx->convert_unscaled, "%s_%s_%d", src_desc->name, dst_desc->name, width)) {
  161. memset(dst0_0, 0xFF, 2 * MAX_LINE_SIZE * 6);
  162. memset(dst1_0, 0xFF, 2 * MAX_LINE_SIZE * 6);
  163. if (dst_pix_fmt == AV_PIX_FMT_GBRP) {
  164. memset(dst0_1, 0xFF, MAX_LINE_SIZE);
  165. memset(dst0_2, 0xFF, MAX_LINE_SIZE);
  166. memset(dst1_1, 0xFF, MAX_LINE_SIZE);
  167. memset(dst1_2, 0xFF, MAX_LINE_SIZE);
  168. }
  169. call_ref(ctx, src, srcStride, srcSliceY,
  170. srcSliceH, dst0, dstStride);
  171. call_new(ctx, src, srcStride, srcSliceY,
  172. srcSliceH, dst1, dstStride);
  173. if (dst_pix_fmt == AV_PIX_FMT_ARGB ||
  174. dst_pix_fmt == AV_PIX_FMT_ABGR ||
  175. dst_pix_fmt == AV_PIX_FMT_RGBA ||
  176. dst_pix_fmt == AV_PIX_FMT_BGRA ||
  177. dst_pix_fmt == AV_PIX_FMT_RGB24 ||
  178. dst_pix_fmt == AV_PIX_FMT_BGR24) {
  179. if (cmp_off_by_n(lines0[0][0], lines1[0][0], width * sample_size, 3) ||
  180. cmp_off_by_n(lines0[0][1], lines1[0][1], width * sample_size, 3))
  181. fail();
  182. } else if (dst_pix_fmt == AV_PIX_FMT_RGB565 ||
  183. dst_pix_fmt == AV_PIX_FMT_BGR565) {
  184. if (cmp_565_by_n(lines0[0][0], lines1[0][0], width, 2) ||
  185. cmp_565_by_n(lines0[0][1], lines1[0][1], width, 2))
  186. fail();
  187. } else if (dst_pix_fmt == AV_PIX_FMT_RGB555 ||
  188. dst_pix_fmt == AV_PIX_FMT_BGR555) {
  189. if (cmp_555_by_n(lines0[0][0], lines1[0][0], width, 2) ||
  190. cmp_555_by_n(lines0[0][1], lines1[0][1], width, 2))
  191. fail();
  192. } else if (dst_pix_fmt == AV_PIX_FMT_GBRP) {
  193. for (int p = 0; p < 3; p++)
  194. for (int l = 0; l < 2; l++)
  195. if (cmp_off_by_n(lines0[p][l], lines1[p][l], width, 3))
  196. fail();
  197. } else {
  198. fail();
  199. }
  200. bench_new(ctx, src, srcStride, srcSliceY,
  201. srcSliceH, dst0, dstStride);
  202. }
  203. sws_freeContext(ctx);
  204. }
  205. }
  206. }
  207. #undef MAX_LINE_SIZE
  208. void checkasm_check_sw_yuv2rgb(void)
  209. {
  210. check_yuv2rgb(AV_PIX_FMT_YUV420P);
  211. report("yuv420p");
  212. check_yuv2rgb(AV_PIX_FMT_YUV422P);
  213. report("yuv422p");
  214. check_yuv2rgb(AV_PIX_FMT_YUVA420P);
  215. report("yuva420p");
  216. }