yv12extend.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310
  1. /*
  2. * Copyright (c) 2010 The WebM 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. #include <assert.h>
  11. #include "./vpx_config.h"
  12. #include "./vpx_scale_rtcd.h"
  13. #include "vpx/vpx_integer.h"
  14. #include "vpx_mem/vpx_mem.h"
  15. #include "vpx_ports/mem.h"
  16. #include "vpx_scale/yv12config.h"
  17. #if CONFIG_VP9_HIGHBITDEPTH
  18. #include "vp9/common/vp9_common.h"
  19. #endif
  20. static void extend_plane(uint8_t *const src, int src_stride, int width,
  21. int height, int extend_top, int extend_left,
  22. int extend_bottom, int extend_right) {
  23. int i;
  24. const int linesize = extend_left + extend_right + width;
  25. /* copy the left and right most columns out */
  26. uint8_t *src_ptr1 = src;
  27. uint8_t *src_ptr2 = src + width - 1;
  28. uint8_t *dst_ptr1 = src - extend_left;
  29. uint8_t *dst_ptr2 = src + width;
  30. for (i = 0; i < height; ++i) {
  31. memset(dst_ptr1, src_ptr1[0], extend_left);
  32. memset(dst_ptr2, src_ptr2[0], extend_right);
  33. src_ptr1 += src_stride;
  34. src_ptr2 += src_stride;
  35. dst_ptr1 += src_stride;
  36. dst_ptr2 += src_stride;
  37. }
  38. /* Now copy the top and bottom lines into each line of the respective
  39. * borders
  40. */
  41. src_ptr1 = src - extend_left;
  42. src_ptr2 = src + src_stride * (height - 1) - extend_left;
  43. dst_ptr1 = src + src_stride * -extend_top - extend_left;
  44. dst_ptr2 = src + src_stride * height - extend_left;
  45. for (i = 0; i < extend_top; ++i) {
  46. memcpy(dst_ptr1, src_ptr1, linesize);
  47. dst_ptr1 += src_stride;
  48. }
  49. for (i = 0; i < extend_bottom; ++i) {
  50. memcpy(dst_ptr2, src_ptr2, linesize);
  51. dst_ptr2 += src_stride;
  52. }
  53. }
  54. #if CONFIG_VP9_HIGHBITDEPTH
  55. static void extend_plane_high(uint8_t *const src8, int src_stride, int width,
  56. int height, int extend_top, int extend_left,
  57. int extend_bottom, int extend_right) {
  58. int i;
  59. const int linesize = extend_left + extend_right + width;
  60. uint16_t *src = CONVERT_TO_SHORTPTR(src8);
  61. /* copy the left and right most columns out */
  62. uint16_t *src_ptr1 = src;
  63. uint16_t *src_ptr2 = src + width - 1;
  64. uint16_t *dst_ptr1 = src - extend_left;
  65. uint16_t *dst_ptr2 = src + width;
  66. for (i = 0; i < height; ++i) {
  67. vpx_memset16(dst_ptr1, src_ptr1[0], extend_left);
  68. vpx_memset16(dst_ptr2, src_ptr2[0], extend_right);
  69. src_ptr1 += src_stride;
  70. src_ptr2 += src_stride;
  71. dst_ptr1 += src_stride;
  72. dst_ptr2 += src_stride;
  73. }
  74. /* Now copy the top and bottom lines into each line of the respective
  75. * borders
  76. */
  77. src_ptr1 = src - extend_left;
  78. src_ptr2 = src + src_stride * (height - 1) - extend_left;
  79. dst_ptr1 = src + src_stride * -extend_top - extend_left;
  80. dst_ptr2 = src + src_stride * height - extend_left;
  81. for (i = 0; i < extend_top; ++i) {
  82. memcpy(dst_ptr1, src_ptr1, linesize * sizeof(uint16_t));
  83. dst_ptr1 += src_stride;
  84. }
  85. for (i = 0; i < extend_bottom; ++i) {
  86. memcpy(dst_ptr2, src_ptr2, linesize * sizeof(uint16_t));
  87. dst_ptr2 += src_stride;
  88. }
  89. }
  90. #endif
  91. void vp8_yv12_extend_frame_borders_c(YV12_BUFFER_CONFIG *ybf) {
  92. const int uv_border = ybf->border / 2;
  93. assert(ybf->border % 2 == 0);
  94. assert(ybf->y_height - ybf->y_crop_height < 16);
  95. assert(ybf->y_width - ybf->y_crop_width < 16);
  96. assert(ybf->y_height - ybf->y_crop_height >= 0);
  97. assert(ybf->y_width - ybf->y_crop_width >= 0);
  98. #if CONFIG_VP9_HIGHBITDEPTH
  99. if (ybf->flags & YV12_FLAG_HIGHBITDEPTH) {
  100. extend_plane_high(ybf->y_buffer, ybf->y_stride, ybf->y_crop_width,
  101. ybf->y_crop_height, ybf->border, ybf->border,
  102. ybf->border + ybf->y_height - ybf->y_crop_height,
  103. ybf->border + ybf->y_width - ybf->y_crop_width);
  104. extend_plane_high(ybf->u_buffer, ybf->uv_stride, ybf->uv_crop_width,
  105. ybf->uv_crop_height, uv_border, uv_border,
  106. uv_border + ybf->uv_height - ybf->uv_crop_height,
  107. uv_border + ybf->uv_width - ybf->uv_crop_width);
  108. extend_plane_high(ybf->v_buffer, ybf->uv_stride, ybf->uv_crop_width,
  109. ybf->uv_crop_height, uv_border, uv_border,
  110. uv_border + ybf->uv_height - ybf->uv_crop_height,
  111. uv_border + ybf->uv_width - ybf->uv_crop_width);
  112. return;
  113. }
  114. #endif
  115. extend_plane(ybf->y_buffer, ybf->y_stride, ybf->y_crop_width,
  116. ybf->y_crop_height, ybf->border, ybf->border,
  117. ybf->border + ybf->y_height - ybf->y_crop_height,
  118. ybf->border + ybf->y_width - ybf->y_crop_width);
  119. extend_plane(ybf->u_buffer, ybf->uv_stride, ybf->uv_crop_width,
  120. ybf->uv_crop_height, uv_border, uv_border,
  121. uv_border + ybf->uv_height - ybf->uv_crop_height,
  122. uv_border + ybf->uv_width - ybf->uv_crop_width);
  123. extend_plane(ybf->v_buffer, ybf->uv_stride, ybf->uv_crop_width,
  124. ybf->uv_crop_height, uv_border, uv_border,
  125. uv_border + ybf->uv_height - ybf->uv_crop_height,
  126. uv_border + ybf->uv_width - ybf->uv_crop_width);
  127. }
  128. #if CONFIG_VP9
  129. static void extend_frame(YV12_BUFFER_CONFIG *const ybf, int ext_size) {
  130. const int c_w = ybf->uv_crop_width;
  131. const int c_h = ybf->uv_crop_height;
  132. const int ss_x = ybf->uv_width < ybf->y_width;
  133. const int ss_y = ybf->uv_height < ybf->y_height;
  134. const int c_et = ext_size >> ss_y;
  135. const int c_el = ext_size >> ss_x;
  136. const int c_eb = c_et + ybf->uv_height - ybf->uv_crop_height;
  137. const int c_er = c_el + ybf->uv_width - ybf->uv_crop_width;
  138. assert(ybf->y_height - ybf->y_crop_height < 16);
  139. assert(ybf->y_width - ybf->y_crop_width < 16);
  140. assert(ybf->y_height - ybf->y_crop_height >= 0);
  141. assert(ybf->y_width - ybf->y_crop_width >= 0);
  142. #if CONFIG_VP9_HIGHBITDEPTH
  143. if (ybf->flags & YV12_FLAG_HIGHBITDEPTH) {
  144. extend_plane_high(ybf->y_buffer, ybf->y_stride, ybf->y_crop_width,
  145. ybf->y_crop_height, ext_size, ext_size,
  146. ext_size + ybf->y_height - ybf->y_crop_height,
  147. ext_size + ybf->y_width - ybf->y_crop_width);
  148. extend_plane_high(ybf->u_buffer, ybf->uv_stride, c_w, c_h, c_et, c_el, c_eb,
  149. c_er);
  150. extend_plane_high(ybf->v_buffer, ybf->uv_stride, c_w, c_h, c_et, c_el, c_eb,
  151. c_er);
  152. return;
  153. }
  154. #endif
  155. extend_plane(ybf->y_buffer, ybf->y_stride, ybf->y_crop_width,
  156. ybf->y_crop_height, ext_size, ext_size,
  157. ext_size + ybf->y_height - ybf->y_crop_height,
  158. ext_size + ybf->y_width - ybf->y_crop_width);
  159. extend_plane(ybf->u_buffer, ybf->uv_stride, c_w, c_h, c_et, c_el, c_eb, c_er);
  160. extend_plane(ybf->v_buffer, ybf->uv_stride, c_w, c_h, c_et, c_el, c_eb, c_er);
  161. }
  162. void vpx_extend_frame_borders_c(YV12_BUFFER_CONFIG *ybf) {
  163. extend_frame(ybf, ybf->border);
  164. }
  165. void vpx_extend_frame_inner_borders_c(YV12_BUFFER_CONFIG *ybf) {
  166. const int inner_bw = (ybf->border > VP9INNERBORDERINPIXELS)
  167. ? VP9INNERBORDERINPIXELS
  168. : ybf->border;
  169. extend_frame(ybf, inner_bw);
  170. }
  171. #if CONFIG_VP9_HIGHBITDEPTH
  172. static void memcpy_short_addr(uint8_t *dst8, const uint8_t *src8, int num) {
  173. uint16_t *dst = CONVERT_TO_SHORTPTR(dst8);
  174. uint16_t *src = CONVERT_TO_SHORTPTR(src8);
  175. memcpy(dst, src, num * sizeof(uint16_t));
  176. }
  177. #endif // CONFIG_VP9_HIGHBITDEPTH
  178. #endif // CONFIG_VP9
  179. // Copies the source image into the destination image and updates the
  180. // destination's UMV borders.
  181. // Note: The frames are assumed to be identical in size.
  182. void vp8_yv12_copy_frame_c(const YV12_BUFFER_CONFIG *src_ybc,
  183. YV12_BUFFER_CONFIG *dst_ybc) {
  184. int row;
  185. const uint8_t *src = src_ybc->y_buffer;
  186. uint8_t *dst = dst_ybc->y_buffer;
  187. #if 0
  188. /* These assertions are valid in the codec, but the libvpx-tester uses
  189. * this code slightly differently.
  190. */
  191. assert(src_ybc->y_width == dst_ybc->y_width);
  192. assert(src_ybc->y_height == dst_ybc->y_height);
  193. #endif
  194. #if CONFIG_VP9_HIGHBITDEPTH
  195. if (src_ybc->flags & YV12_FLAG_HIGHBITDEPTH) {
  196. assert(dst_ybc->flags & YV12_FLAG_HIGHBITDEPTH);
  197. for (row = 0; row < src_ybc->y_height; ++row) {
  198. memcpy_short_addr(dst, src, src_ybc->y_width);
  199. src += src_ybc->y_stride;
  200. dst += dst_ybc->y_stride;
  201. }
  202. src = src_ybc->u_buffer;
  203. dst = dst_ybc->u_buffer;
  204. for (row = 0; row < src_ybc->uv_height; ++row) {
  205. memcpy_short_addr(dst, src, src_ybc->uv_width);
  206. src += src_ybc->uv_stride;
  207. dst += dst_ybc->uv_stride;
  208. }
  209. src = src_ybc->v_buffer;
  210. dst = dst_ybc->v_buffer;
  211. for (row = 0; row < src_ybc->uv_height; ++row) {
  212. memcpy_short_addr(dst, src, src_ybc->uv_width);
  213. src += src_ybc->uv_stride;
  214. dst += dst_ybc->uv_stride;
  215. }
  216. vp8_yv12_extend_frame_borders_c(dst_ybc);
  217. return;
  218. } else {
  219. assert(!(dst_ybc->flags & YV12_FLAG_HIGHBITDEPTH));
  220. }
  221. #endif
  222. for (row = 0; row < src_ybc->y_height; ++row) {
  223. memcpy(dst, src, src_ybc->y_width);
  224. src += src_ybc->y_stride;
  225. dst += dst_ybc->y_stride;
  226. }
  227. src = src_ybc->u_buffer;
  228. dst = dst_ybc->u_buffer;
  229. for (row = 0; row < src_ybc->uv_height; ++row) {
  230. memcpy(dst, src, src_ybc->uv_width);
  231. src += src_ybc->uv_stride;
  232. dst += dst_ybc->uv_stride;
  233. }
  234. src = src_ybc->v_buffer;
  235. dst = dst_ybc->v_buffer;
  236. for (row = 0; row < src_ybc->uv_height; ++row) {
  237. memcpy(dst, src, src_ybc->uv_width);
  238. src += src_ybc->uv_stride;
  239. dst += dst_ybc->uv_stride;
  240. }
  241. vp8_yv12_extend_frame_borders_c(dst_ybc);
  242. }
  243. void vpx_yv12_copy_y_c(const YV12_BUFFER_CONFIG *src_ybc,
  244. YV12_BUFFER_CONFIG *dst_ybc) {
  245. int row;
  246. const uint8_t *src = src_ybc->y_buffer;
  247. uint8_t *dst = dst_ybc->y_buffer;
  248. #if CONFIG_VP9_HIGHBITDEPTH
  249. if (src_ybc->flags & YV12_FLAG_HIGHBITDEPTH) {
  250. const uint16_t *src16 = CONVERT_TO_SHORTPTR(src);
  251. uint16_t *dst16 = CONVERT_TO_SHORTPTR(dst);
  252. for (row = 0; row < src_ybc->y_height; ++row) {
  253. memcpy(dst16, src16, src_ybc->y_width * sizeof(uint16_t));
  254. src16 += src_ybc->y_stride;
  255. dst16 += dst_ybc->y_stride;
  256. }
  257. return;
  258. }
  259. #endif
  260. for (row = 0; row < src_ybc->y_height; ++row) {
  261. memcpy(dst, src, src_ybc->y_width);
  262. src += src_ybc->y_stride;
  263. dst += dst_ybc->y_stride;
  264. }
  265. }