tiny-nv12-scale.c 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. #include <string.h>
  2. #include "tiny-nv12-scale.h"
  3. /* TODO: optimize this stuff later, or replace with something better. it's
  4. * kind of garbage. although normally it shouldn't be called that often. plus
  5. * it's nearest neighbor so not really a huge deal. at the very least it
  6. * should be sse2 at some point. */
  7. void nv12_scale_init(nv12_scale_t *s, bool convert_to_i420, int dst_cx,
  8. int dst_cy, int src_cx, int src_cy)
  9. {
  10. s->convert_to_i420 = convert_to_i420;
  11. s->src_cx = src_cx;
  12. s->src_cy = src_cy;
  13. s->dst_cx = dst_cx;
  14. s->dst_cy = dst_cy;
  15. }
  16. static void nv12_scale_nearest(nv12_scale_t *s, uint8_t *dst_start,
  17. const uint8_t *src)
  18. {
  19. register uint8_t *dst = dst_start;
  20. const int src_cx = s->src_cx;
  21. const int src_cy = s->src_cy;
  22. const int dst_cx = s->dst_cx;
  23. const int dst_cy = s->dst_cy;
  24. /* lum */
  25. for (int y = 0; y < dst_cy; y++) {
  26. const int src_line = y * src_cy / dst_cy * s->src_cx;
  27. for (int x = 0; x < dst_cx; x++) {
  28. const int src_x = x * src_cx / dst_cx;
  29. *(dst++) = src[src_line + src_x];
  30. }
  31. }
  32. src += src_cx * src_cy;
  33. /* uv */
  34. const int dst_cx_d2 = dst_cx / 2;
  35. const int dst_cy_d2 = dst_cy / 2;
  36. for (int y = 0; y < dst_cy_d2; y++) {
  37. const int src_line = y * src_cy / dst_cy * src_cx;
  38. for (int x = 0; x < dst_cx_d2; x++) {
  39. const int src_x = x * src_cx / dst_cx * 2;
  40. const int pos = src_line + src_x;
  41. *(dst++) = src[pos];
  42. *(dst++) = src[pos + 1];
  43. }
  44. }
  45. }
  46. static void nv12_scale_nearest_to_i420(nv12_scale_t *s, uint8_t *dst_start,
  47. const uint8_t *src)
  48. {
  49. register uint8_t *dst = dst_start;
  50. const int src_cx = s->src_cx;
  51. const int src_cy = s->src_cy;
  52. const int dst_cx = s->dst_cx;
  53. const int dst_cy = s->dst_cy;
  54. const int size = src_cx * src_cy;
  55. /* lum */
  56. for (int y = 0; y < dst_cy; y++) {
  57. const int src_line = y * src_cy / dst_cy * s->src_cx;
  58. for (int x = 0; x < dst_cx; x++) {
  59. const int src_x = x * src_cx / dst_cx;
  60. *(dst++) = src[src_line + src_x];
  61. }
  62. }
  63. src += size;
  64. /* uv */
  65. const int dst_cx_d2 = dst_cx / 2;
  66. const int dst_cy_d2 = dst_cy / 2;
  67. register uint8_t *dst2 = dst + dst_cx * dst_cy / 4;
  68. for (int y = 0; y < dst_cy_d2; y++) {
  69. const int src_line = y * src_cy / dst_cy * src_cx;
  70. for (int x = 0; x < dst_cx_d2; x++) {
  71. const int src_x = x * src_cx / dst_cx * 2;
  72. const int pos = src_line + src_x;
  73. *(dst++) = src[pos];
  74. *(dst2++) = src[pos + 1];
  75. }
  76. }
  77. }
  78. static void nv12_convert_to_i420(nv12_scale_t *s, uint8_t *dst_start,
  79. const uint8_t *src_start)
  80. {
  81. const int size = s->src_cx * s->src_cy;
  82. const int size_d4 = size / 4;
  83. memcpy(dst_start, src_start, size);
  84. register uint8_t *dst1 = dst_start + size;
  85. register uint8_t *dst2 = dst1 + size_d4;
  86. register uint8_t *dst_end = dst2 + size_d4;
  87. register const uint8_t *src = src_start + size;
  88. while (dst2 < dst_end) {
  89. *(dst1++) = *(src++);
  90. *(dst2++) = *(src++);
  91. }
  92. }
  93. void nv12_do_scale(nv12_scale_t *s, uint8_t *dst, const uint8_t *src)
  94. {
  95. if (s->src_cx == s->dst_cx && s->src_cy == s->dst_cy) {
  96. if (s->convert_to_i420)
  97. nv12_convert_to_i420(s, dst, src);
  98. else
  99. memcpy(dst, src, s->src_cx * s->src_cy * 3 / 2);
  100. } else {
  101. if (s->convert_to_i420)
  102. nv12_scale_nearest_to_i420(s, dst, src);
  103. else
  104. nv12_scale_nearest(s, dst, src);
  105. }
  106. }