yv12extend.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335
  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. extend_plane(ybf->y_buffer, ybf->y_stride, ybf->y_crop_width,
  99. ybf->y_crop_height, ybf->border, ybf->border,
  100. ybf->border + ybf->y_height - ybf->y_crop_height,
  101. ybf->border + ybf->y_width - ybf->y_crop_width);
  102. extend_plane(ybf->u_buffer, ybf->uv_stride, ybf->uv_crop_width,
  103. ybf->uv_crop_height, uv_border, uv_border,
  104. uv_border + ybf->uv_height - ybf->uv_crop_height,
  105. uv_border + ybf->uv_width - ybf->uv_crop_width);
  106. extend_plane(ybf->v_buffer, ybf->uv_stride, ybf->uv_crop_width,
  107. ybf->uv_crop_height, uv_border, uv_border,
  108. uv_border + ybf->uv_height - ybf->uv_crop_height,
  109. uv_border + ybf->uv_width - ybf->uv_crop_width);
  110. }
  111. #if CONFIG_VP9
  112. static void extend_frame(YV12_BUFFER_CONFIG *const ybf, int ext_size) {
  113. const int c_w = ybf->uv_crop_width;
  114. const int c_h = ybf->uv_crop_height;
  115. const int ss_x = ybf->uv_width < ybf->y_width;
  116. const int ss_y = ybf->uv_height < ybf->y_height;
  117. const int c_et = ext_size >> ss_y;
  118. const int c_el = ext_size >> ss_x;
  119. const int c_eb = c_et + ybf->uv_height - ybf->uv_crop_height;
  120. const int c_er = c_el + ybf->uv_width - ybf->uv_crop_width;
  121. assert(ybf->y_height - ybf->y_crop_height < 16);
  122. assert(ybf->y_width - ybf->y_crop_width < 16);
  123. assert(ybf->y_height - ybf->y_crop_height >= 0);
  124. assert(ybf->y_width - ybf->y_crop_width >= 0);
  125. #if CONFIG_VP9_HIGHBITDEPTH
  126. if (ybf->flags & YV12_FLAG_HIGHBITDEPTH) {
  127. extend_plane_high(ybf->y_buffer, ybf->y_stride, ybf->y_crop_width,
  128. ybf->y_crop_height, ext_size, ext_size,
  129. ext_size + ybf->y_height - ybf->y_crop_height,
  130. ext_size + ybf->y_width - ybf->y_crop_width);
  131. extend_plane_high(ybf->u_buffer, ybf->uv_stride, c_w, c_h, c_et, c_el, c_eb,
  132. c_er);
  133. extend_plane_high(ybf->v_buffer, ybf->uv_stride, c_w, c_h, c_et, c_el, c_eb,
  134. c_er);
  135. return;
  136. }
  137. #endif
  138. extend_plane(ybf->y_buffer, ybf->y_stride, ybf->y_crop_width,
  139. ybf->y_crop_height, ext_size, ext_size,
  140. ext_size + ybf->y_height - ybf->y_crop_height,
  141. ext_size + ybf->y_width - ybf->y_crop_width);
  142. extend_plane(ybf->u_buffer, ybf->uv_stride, c_w, c_h, c_et, c_el, c_eb, c_er);
  143. extend_plane(ybf->v_buffer, ybf->uv_stride, c_w, c_h, c_et, c_el, c_eb, c_er);
  144. }
  145. void vpx_extend_frame_borders_c(YV12_BUFFER_CONFIG *ybf) {
  146. extend_frame(ybf, ybf->border);
  147. }
  148. void vpx_extend_frame_inner_borders_c(YV12_BUFFER_CONFIG *ybf) {
  149. const int inner_bw = (ybf->border > VP9INNERBORDERINPIXELS)
  150. ? VP9INNERBORDERINPIXELS
  151. : ybf->border;
  152. extend_frame(ybf, inner_bw);
  153. }
  154. #if CONFIG_VP9_HIGHBITDEPTH
  155. static void memcpy_short_addr(uint8_t *dst8, const uint8_t *src8, int num) {
  156. uint16_t *dst = CONVERT_TO_SHORTPTR(dst8);
  157. uint16_t *src = CONVERT_TO_SHORTPTR(src8);
  158. memcpy(dst, src, num * sizeof(uint16_t));
  159. }
  160. #endif // CONFIG_VP9_HIGHBITDEPTH
  161. #endif // CONFIG_VP9
  162. // Copies the source image into the destination image and updates the
  163. // destination's UMV borders.
  164. // Note: The frames are assumed to be identical in size.
  165. void vp8_yv12_copy_frame_c(const YV12_BUFFER_CONFIG *src_ybc,
  166. YV12_BUFFER_CONFIG *dst_ybc) {
  167. int row;
  168. const uint8_t *src = src_ybc->y_buffer;
  169. uint8_t *dst = dst_ybc->y_buffer;
  170. #if 0
  171. /* These assertions are valid in the codec, but the libvpx-tester uses
  172. * this code slightly differently.
  173. */
  174. assert(src_ybc->y_width == dst_ybc->y_width);
  175. assert(src_ybc->y_height == dst_ybc->y_height);
  176. #endif
  177. for (row = 0; row < src_ybc->y_height; ++row) {
  178. memcpy(dst, src, src_ybc->y_width);
  179. src += src_ybc->y_stride;
  180. dst += dst_ybc->y_stride;
  181. }
  182. src = src_ybc->u_buffer;
  183. dst = dst_ybc->u_buffer;
  184. for (row = 0; row < src_ybc->uv_height; ++row) {
  185. memcpy(dst, src, src_ybc->uv_width);
  186. src += src_ybc->uv_stride;
  187. dst += dst_ybc->uv_stride;
  188. }
  189. src = src_ybc->v_buffer;
  190. dst = dst_ybc->v_buffer;
  191. for (row = 0; row < src_ybc->uv_height; ++row) {
  192. memcpy(dst, src, src_ybc->uv_width);
  193. src += src_ybc->uv_stride;
  194. dst += dst_ybc->uv_stride;
  195. }
  196. vp8_yv12_extend_frame_borders_c(dst_ybc);
  197. }
  198. #if CONFIG_VP9
  199. void vpx_yv12_copy_frame_c(const YV12_BUFFER_CONFIG *src_ybc,
  200. YV12_BUFFER_CONFIG *dst_ybc) {
  201. int row;
  202. const uint8_t *src = src_ybc->y_buffer;
  203. uint8_t *dst = dst_ybc->y_buffer;
  204. #if 0
  205. /* These assertions are valid in the codec, but the libvpx-tester uses
  206. * this code slightly differently.
  207. */
  208. assert(src_ybc->y_width == dst_ybc->y_width);
  209. assert(src_ybc->y_height == dst_ybc->y_height);
  210. #endif
  211. #if CONFIG_VP9_HIGHBITDEPTH
  212. if (src_ybc->flags & YV12_FLAG_HIGHBITDEPTH) {
  213. assert(dst_ybc->flags & YV12_FLAG_HIGHBITDEPTH);
  214. for (row = 0; row < src_ybc->y_height; ++row) {
  215. memcpy_short_addr(dst, src, src_ybc->y_width);
  216. src += src_ybc->y_stride;
  217. dst += dst_ybc->y_stride;
  218. }
  219. src = src_ybc->u_buffer;
  220. dst = dst_ybc->u_buffer;
  221. for (row = 0; row < src_ybc->uv_height; ++row) {
  222. memcpy_short_addr(dst, src, src_ybc->uv_width);
  223. src += src_ybc->uv_stride;
  224. dst += dst_ybc->uv_stride;
  225. }
  226. src = src_ybc->v_buffer;
  227. dst = dst_ybc->v_buffer;
  228. for (row = 0; row < src_ybc->uv_height; ++row) {
  229. memcpy_short_addr(dst, src, src_ybc->uv_width);
  230. src += src_ybc->uv_stride;
  231. dst += dst_ybc->uv_stride;
  232. }
  233. vpx_extend_frame_borders_c(dst_ybc);
  234. return;
  235. } else {
  236. assert(!(dst_ybc->flags & YV12_FLAG_HIGHBITDEPTH));
  237. }
  238. #endif
  239. for (row = 0; row < src_ybc->y_height; ++row) {
  240. memcpy(dst, src, src_ybc->y_width);
  241. src += src_ybc->y_stride;
  242. dst += dst_ybc->y_stride;
  243. }
  244. src = src_ybc->u_buffer;
  245. dst = dst_ybc->u_buffer;
  246. for (row = 0; row < src_ybc->uv_height; ++row) {
  247. memcpy(dst, src, src_ybc->uv_width);
  248. src += src_ybc->uv_stride;
  249. dst += dst_ybc->uv_stride;
  250. }
  251. src = src_ybc->v_buffer;
  252. dst = dst_ybc->v_buffer;
  253. for (row = 0; row < src_ybc->uv_height; ++row) {
  254. memcpy(dst, src, src_ybc->uv_width);
  255. src += src_ybc->uv_stride;
  256. dst += dst_ybc->uv_stride;
  257. }
  258. vpx_extend_frame_borders_c(dst_ybc);
  259. }
  260. #endif // CONFIG_VP9
  261. void vpx_yv12_copy_y_c(const YV12_BUFFER_CONFIG *src_ybc,
  262. YV12_BUFFER_CONFIG *dst_ybc) {
  263. int row;
  264. const uint8_t *src = src_ybc->y_buffer;
  265. uint8_t *dst = dst_ybc->y_buffer;
  266. #if CONFIG_VP9_HIGHBITDEPTH
  267. if (src_ybc->flags & YV12_FLAG_HIGHBITDEPTH) {
  268. const uint16_t *src16 = CONVERT_TO_SHORTPTR(src);
  269. uint16_t *dst16 = CONVERT_TO_SHORTPTR(dst);
  270. for (row = 0; row < src_ybc->y_height; ++row) {
  271. memcpy(dst16, src16, src_ybc->y_width * sizeof(uint16_t));
  272. src16 += src_ybc->y_stride;
  273. dst16 += dst_ybc->y_stride;
  274. }
  275. return;
  276. }
  277. #endif
  278. for (row = 0; row < src_ybc->y_height; ++row) {
  279. memcpy(dst, src, src_ybc->y_width);
  280. src += src_ybc->y_stride;
  281. dst += dst_ybc->y_stride;
  282. }
  283. }