yv12extend.c 10 KB

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