vpx_scale.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529
  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. /****************************************************************************
  11. *
  12. * Module Title : scale.c
  13. *
  14. * Description : Image scaling functions.
  15. *
  16. ***************************************************************************/
  17. /****************************************************************************
  18. * Header Files
  19. ****************************************************************************/
  20. #include "./vpx_scale_rtcd.h"
  21. #include "vpx_mem/vpx_mem.h"
  22. #include "vpx_scale/vpx_scale.h"
  23. #include "vpx_scale/yv12config.h"
  24. typedef struct {
  25. int expanded_frame_width;
  26. int expanded_frame_height;
  27. int HScale;
  28. int HRatio;
  29. int VScale;
  30. int VRatio;
  31. YV12_BUFFER_CONFIG *src_yuv_config;
  32. YV12_BUFFER_CONFIG *dst_yuv_config;
  33. } SCALE_VARS;
  34. /****************************************************************************
  35. *
  36. * ROUTINE : scale1d_2t1_i
  37. *
  38. * INPUTS : const unsigned char *source : Pointer to data to be scaled.
  39. * int source_step : Number of pixels to step on in
  40. * source.
  41. * unsigned int source_scale : Scale for source (UNUSED).
  42. * unsigned int source_length : Length of source (UNUSED).
  43. * unsigned char *dest : Pointer to output data array.
  44. * int dest_step : Number of pixels to step on in
  45. * destination.
  46. * unsigned int dest_scale : Scale for destination
  47. * (UNUSED).
  48. * unsigned int dest_length : Length of destination.
  49. *
  50. * OUTPUTS : None.
  51. *
  52. * RETURNS : void
  53. *
  54. * FUNCTION : Performs 2-to-1 interpolated scaling.
  55. *
  56. * SPECIAL NOTES : None.
  57. *
  58. ****************************************************************************/
  59. static void scale1d_2t1_i(const unsigned char *source, int source_step,
  60. unsigned int source_scale, unsigned int source_length,
  61. unsigned char *dest, int dest_step,
  62. unsigned int dest_scale, unsigned int dest_length) {
  63. unsigned int i, j;
  64. unsigned int temp;
  65. int source_pitch = source_step;
  66. (void)source_length;
  67. (void)source_scale;
  68. (void)dest_scale;
  69. source_step *= 2;
  70. dest[0] = source[0];
  71. for (i = dest_step, j = source_step; i < dest_length * dest_step;
  72. i += dest_step, j += source_step) {
  73. temp = 8;
  74. temp += 3 * source[j - source_pitch];
  75. temp += 10 * source[j];
  76. temp += 3 * source[j + source_pitch];
  77. temp >>= 4;
  78. dest[i] = (char)(temp);
  79. }
  80. }
  81. /****************************************************************************
  82. *
  83. * ROUTINE : scale1d_2t1_ps
  84. *
  85. * INPUTS : const unsigned char *source : Pointer to data to be scaled.
  86. * int source_step : Number of pixels to step on in
  87. * source.
  88. * unsigned int source_scale : Scale for source (UNUSED).
  89. * unsigned int source_length : Length of source (UNUSED).
  90. * unsigned char *dest : Pointer to output data array.
  91. * int dest_step : Number of pixels to step on in
  92. * destination.
  93. * unsigned int dest_scale : Scale for destination
  94. * (UNUSED).
  95. * unsigned int dest_length : Length of destination.
  96. *
  97. * OUTPUTS : None.
  98. *
  99. * RETURNS : void
  100. *
  101. * FUNCTION : Performs 2-to-1 point subsampled scaling.
  102. *
  103. * SPECIAL NOTES : None.
  104. *
  105. ****************************************************************************/
  106. static void scale1d_2t1_ps(const unsigned char *source, int source_step,
  107. unsigned int source_scale,
  108. unsigned int source_length, unsigned char *dest,
  109. int dest_step, unsigned int dest_scale,
  110. unsigned int dest_length) {
  111. unsigned int i, j;
  112. (void)source_length;
  113. (void)source_scale;
  114. (void)dest_scale;
  115. source_step *= 2;
  116. j = 0;
  117. for (i = 0; i < dest_length * dest_step; i += dest_step, j += source_step)
  118. dest[i] = source[j];
  119. }
  120. /****************************************************************************
  121. *
  122. * ROUTINE : scale1d_c
  123. *
  124. * INPUTS : const unsigned char *source : Pointer to data to be scaled.
  125. * int source_step : Number of pixels to step on in
  126. * source.
  127. * unsigned int source_scale : Scale for source.
  128. * unsigned int source_length : Length of source (UNUSED).
  129. * unsigned char *dest : Pointer to output data array.
  130. * int dest_step : Number of pixels to step on in
  131. * destination.
  132. * unsigned int dest_scale : Scale for destination.
  133. * unsigned int dest_length : Length of destination.
  134. *
  135. * OUTPUTS : None.
  136. *
  137. * RETURNS : void
  138. *
  139. * FUNCTION : Performs linear interpolation in one dimension.
  140. *
  141. * SPECIAL NOTES : None.
  142. *
  143. ****************************************************************************/
  144. static void scale1d_c(const unsigned char *source, int source_step,
  145. unsigned int source_scale, unsigned int source_length,
  146. unsigned char *dest, int dest_step,
  147. unsigned int dest_scale, unsigned int dest_length) {
  148. unsigned int i;
  149. unsigned int round_value = dest_scale / 2;
  150. unsigned int left_modifier = dest_scale;
  151. unsigned int right_modifier = 0;
  152. unsigned char left_pixel = *source;
  153. unsigned char right_pixel = *(source + source_step);
  154. (void)source_length;
  155. /* These asserts are needed if there are boundary issues... */
  156. /*assert ( dest_scale > source_scale );*/
  157. /*assert ( (source_length-1) * dest_scale >= (dest_length-1) * source_scale
  158. * );*/
  159. for (i = 0; i < dest_length * dest_step; i += dest_step) {
  160. dest[i] = (char)((left_modifier * left_pixel +
  161. right_modifier * right_pixel + round_value) /
  162. dest_scale);
  163. right_modifier += source_scale;
  164. while (right_modifier > dest_scale) {
  165. right_modifier -= dest_scale;
  166. source += source_step;
  167. left_pixel = *source;
  168. right_pixel = *(source + source_step);
  169. }
  170. left_modifier = dest_scale - right_modifier;
  171. }
  172. }
  173. /****************************************************************************
  174. *
  175. * ROUTINE : Scale2D
  176. *
  177. * INPUTS : const unsigned char *source : Pointer to data to be
  178. * scaled.
  179. * int source_pitch : Stride of source image.
  180. * unsigned int source_width : Width of input image.
  181. * unsigned int source_height : Height of input image.
  182. * unsigned char *dest : Pointer to output data
  183. * array.
  184. * int dest_pitch : Stride of destination
  185. * image.
  186. * unsigned int dest_width : Width of destination image.
  187. * unsigned int dest_height : Height of destination
  188. * image.
  189. * unsigned char *temp_area : Pointer to temp work area.
  190. * unsigned char temp_area_height : Height of temp work area.
  191. * unsigned int hscale : Horizontal scale factor
  192. * numerator.
  193. * unsigned int hratio : Horizontal scale factor
  194. * denominator.
  195. * unsigned int vscale : Vertical scale factor
  196. * numerator.
  197. * unsigned int vratio : Vertical scale factor
  198. * denominator.
  199. * unsigned int interlaced : Interlace flag.
  200. *
  201. * OUTPUTS : None.
  202. *
  203. * RETURNS : void
  204. *
  205. * FUNCTION : Performs 2-tap linear interpolation in two dimensions.
  206. *
  207. * SPECIAL NOTES : Expansion is performed one band at a time to help with
  208. * caching.
  209. *
  210. ****************************************************************************/
  211. static void Scale2D(
  212. /*const*/
  213. unsigned char *source, int source_pitch, unsigned int source_width,
  214. unsigned int source_height, unsigned char *dest, int dest_pitch,
  215. unsigned int dest_width, unsigned int dest_height, unsigned char *temp_area,
  216. unsigned char temp_area_height, unsigned int hscale, unsigned int hratio,
  217. unsigned int vscale, unsigned int vratio, unsigned int interlaced) {
  218. /*unsigned*/
  219. int i, j, k;
  220. int bands;
  221. int dest_band_height;
  222. int source_band_height;
  223. typedef void (*Scale1D)(const unsigned char *source, int source_step,
  224. unsigned int source_scale, unsigned int source_length,
  225. unsigned char *dest, int dest_step,
  226. unsigned int dest_scale, unsigned int dest_length);
  227. Scale1D Scale1Dv = scale1d_c;
  228. Scale1D Scale1Dh = scale1d_c;
  229. void (*horiz_line_scale)(const unsigned char *, unsigned int, unsigned char *,
  230. unsigned int) = NULL;
  231. void (*vert_band_scale)(unsigned char *, unsigned int, unsigned char *,
  232. unsigned int, unsigned int) = NULL;
  233. int ratio_scalable = 1;
  234. int interpolation = 0;
  235. unsigned char *source_base;
  236. unsigned char *line_src;
  237. source_base = (unsigned char *)source;
  238. if (source_pitch < 0) {
  239. int offset;
  240. offset = (source_height - 1);
  241. offset *= source_pitch;
  242. source_base += offset;
  243. }
  244. /* find out the ratio for each direction */
  245. switch (hratio * 10 / hscale) {
  246. case 8:
  247. /* 4-5 Scale in Width direction */
  248. horiz_line_scale = vp8_horizontal_line_5_4_scale;
  249. break;
  250. case 6:
  251. /* 3-5 Scale in Width direction */
  252. horiz_line_scale = vp8_horizontal_line_5_3_scale;
  253. break;
  254. case 5:
  255. /* 1-2 Scale in Width direction */
  256. horiz_line_scale = vp8_horizontal_line_2_1_scale;
  257. break;
  258. default:
  259. /* The ratio is not acceptable now */
  260. /* throw("The ratio is not acceptable for now!"); */
  261. ratio_scalable = 0;
  262. break;
  263. }
  264. switch (vratio * 10 / vscale) {
  265. case 8:
  266. /* 4-5 Scale in vertical direction */
  267. vert_band_scale = vp8_vertical_band_5_4_scale;
  268. source_band_height = 5;
  269. dest_band_height = 4;
  270. break;
  271. case 6:
  272. /* 3-5 Scale in vertical direction */
  273. vert_band_scale = vp8_vertical_band_5_3_scale;
  274. source_band_height = 5;
  275. dest_band_height = 3;
  276. break;
  277. case 5:
  278. /* 1-2 Scale in vertical direction */
  279. if (interlaced) {
  280. /* if the content is interlaced, point sampling is used */
  281. vert_band_scale = vp8_vertical_band_2_1_scale;
  282. } else {
  283. interpolation = 1;
  284. /* if the content is progressive, interplo */
  285. vert_band_scale = vp8_vertical_band_2_1_scale_i;
  286. }
  287. source_band_height = 2;
  288. dest_band_height = 1;
  289. break;
  290. default:
  291. /* The ratio is not acceptable now */
  292. /* throw("The ratio is not acceptable for now!"); */
  293. ratio_scalable = 0;
  294. break;
  295. }
  296. if (ratio_scalable) {
  297. if (source_height == dest_height) {
  298. /* for each band of the image */
  299. for (k = 0; k < (int)dest_height; k++) {
  300. horiz_line_scale(source, source_width, dest, dest_width);
  301. source += source_pitch;
  302. dest += dest_pitch;
  303. }
  304. return;
  305. }
  306. if (interpolation) {
  307. if (source < source_base) source = source_base;
  308. horiz_line_scale(source, source_width, temp_area, dest_width);
  309. }
  310. for (k = 0;
  311. k < (int)(dest_height + dest_band_height - 1) / dest_band_height;
  312. k++) {
  313. /* scale one band horizontally */
  314. for (i = 0; i < source_band_height; i++) {
  315. /* Trap case where we could read off the base of the source buffer */
  316. line_src = (unsigned char *)source + i * source_pitch;
  317. if (line_src < source_base) line_src = source_base;
  318. horiz_line_scale(line_src, source_width,
  319. temp_area + (i + 1) * dest_pitch, dest_width);
  320. }
  321. /* Vertical scaling is in place */
  322. vert_band_scale(temp_area + dest_pitch, dest_pitch, dest, dest_pitch,
  323. dest_width);
  324. if (interpolation)
  325. memcpy(temp_area, temp_area + source_band_height * dest_pitch,
  326. dest_width);
  327. /* Next band... */
  328. source += (unsigned long)source_band_height * source_pitch;
  329. dest += (unsigned long)dest_band_height * dest_pitch;
  330. }
  331. return;
  332. }
  333. if (hscale == 2 && hratio == 1) Scale1Dh = scale1d_2t1_ps;
  334. if (vscale == 2 && vratio == 1) {
  335. if (interlaced)
  336. Scale1Dv = scale1d_2t1_ps;
  337. else
  338. Scale1Dv = scale1d_2t1_i;
  339. }
  340. if (source_height == dest_height) {
  341. /* for each band of the image */
  342. for (k = 0; k < (int)dest_height; k++) {
  343. Scale1Dh(source, 1, hscale, source_width + 1, dest, 1, hratio,
  344. dest_width);
  345. source += source_pitch;
  346. dest += dest_pitch;
  347. }
  348. return;
  349. }
  350. if (dest_height > source_height) {
  351. dest_band_height = temp_area_height - 1;
  352. source_band_height = dest_band_height * source_height / dest_height;
  353. } else {
  354. source_band_height = temp_area_height - 1;
  355. dest_band_height = source_band_height * vratio / vscale;
  356. }
  357. /* first row needs to be done so that we can stay one row ahead for vertical
  358. * zoom */
  359. Scale1Dh(source, 1, hscale, source_width + 1, temp_area, 1, hratio,
  360. dest_width);
  361. /* for each band of the image */
  362. bands = (dest_height + dest_band_height - 1) / dest_band_height;
  363. for (k = 0; k < bands; k++) {
  364. /* scale one band horizontally */
  365. for (i = 1; i < source_band_height + 1; i++) {
  366. if (k * source_band_height + i < (int)source_height) {
  367. Scale1Dh(source + i * source_pitch, 1, hscale, source_width + 1,
  368. temp_area + i * dest_pitch, 1, hratio, dest_width);
  369. } else { /* Duplicate the last row */
  370. /* copy temp_area row 0 over from last row in the past */
  371. memcpy(temp_area + i * dest_pitch, temp_area + (i - 1) * dest_pitch,
  372. dest_pitch);
  373. }
  374. }
  375. /* scale one band vertically */
  376. for (j = 0; j < (int)dest_width; j++) {
  377. Scale1Dv(&temp_area[j], dest_pitch, vscale, source_band_height + 1,
  378. &dest[j], dest_pitch, vratio, dest_band_height);
  379. }
  380. /* copy temp_area row 0 over from last row in the past */
  381. memcpy(temp_area, temp_area + source_band_height * dest_pitch, dest_pitch);
  382. /* move to the next band */
  383. source += source_band_height * source_pitch;
  384. dest += dest_band_height * dest_pitch;
  385. }
  386. }
  387. /****************************************************************************
  388. *
  389. * ROUTINE : vpx_scale_frame
  390. *
  391. * INPUTS : YV12_BUFFER_CONFIG *src : Pointer to frame to be
  392. * scaled.
  393. * YV12_BUFFER_CONFIG *dst : Pointer to buffer to hold
  394. * scaled frame.
  395. * unsigned char *temp_area : Pointer to temp work area.
  396. * unsigned char temp_area_height : Height of temp work area.
  397. * unsigned int hscale : Horizontal scale factor
  398. * numerator.
  399. * unsigned int hratio : Horizontal scale factor
  400. * denominator.
  401. * unsigned int vscale : Vertical scale factor
  402. * numerator.
  403. * unsigned int vratio : Vertical scale factor
  404. * denominator.
  405. * unsigned int interlaced : Interlace flag.
  406. *
  407. * OUTPUTS : None.
  408. *
  409. * RETURNS : void
  410. *
  411. * FUNCTION : Performs 2-tap linear interpolation in two dimensions.
  412. *
  413. * SPECIAL NOTES : Expansion is performed one band at a time to help with
  414. * caching.
  415. *
  416. ****************************************************************************/
  417. void vpx_scale_frame(YV12_BUFFER_CONFIG *src, YV12_BUFFER_CONFIG *dst,
  418. unsigned char *temp_area, unsigned char temp_height,
  419. unsigned int hscale, unsigned int hratio,
  420. unsigned int vscale, unsigned int vratio,
  421. unsigned int interlaced) {
  422. int i;
  423. int dw = (hscale - 1 + src->y_width * hratio) / hscale;
  424. int dh = (vscale - 1 + src->y_height * vratio) / vscale;
  425. /* call our internal scaling routines!! */
  426. Scale2D((unsigned char *)src->y_buffer, src->y_stride, src->y_width,
  427. src->y_height, (unsigned char *)dst->y_buffer, dst->y_stride, dw, dh,
  428. temp_area, temp_height, hscale, hratio, vscale, vratio, interlaced);
  429. if (dw < (int)dst->y_width)
  430. for (i = 0; i < dh; i++)
  431. memset(dst->y_buffer + i * dst->y_stride + dw - 1,
  432. dst->y_buffer[i * dst->y_stride + dw - 2], dst->y_width - dw + 1);
  433. if (dh < (int)dst->y_height)
  434. for (i = dh - 1; i < (int)dst->y_height; i++)
  435. memcpy(dst->y_buffer + i * dst->y_stride,
  436. dst->y_buffer + (dh - 2) * dst->y_stride, dst->y_width + 1);
  437. Scale2D((unsigned char *)src->u_buffer, src->uv_stride, src->uv_width,
  438. src->uv_height, (unsigned char *)dst->u_buffer, dst->uv_stride,
  439. dw / 2, dh / 2, temp_area, temp_height, hscale, hratio, vscale,
  440. vratio, interlaced);
  441. if (dw / 2 < (int)dst->uv_width)
  442. for (i = 0; i < dst->uv_height; i++)
  443. memset(dst->u_buffer + i * dst->uv_stride + dw / 2 - 1,
  444. dst->u_buffer[i * dst->uv_stride + dw / 2 - 2],
  445. dst->uv_width - dw / 2 + 1);
  446. if (dh / 2 < (int)dst->uv_height)
  447. for (i = dh / 2 - 1; i < (int)dst->y_height / 2; i++)
  448. memcpy(dst->u_buffer + i * dst->uv_stride,
  449. dst->u_buffer + (dh / 2 - 2) * dst->uv_stride, dst->uv_width);
  450. Scale2D((unsigned char *)src->v_buffer, src->uv_stride, src->uv_width,
  451. src->uv_height, (unsigned char *)dst->v_buffer, dst->uv_stride,
  452. dw / 2, dh / 2, temp_area, temp_height, hscale, hratio, vscale,
  453. vratio, interlaced);
  454. if (dw / 2 < (int)dst->uv_width)
  455. for (i = 0; i < dst->uv_height; i++)
  456. memset(dst->v_buffer + i * dst->uv_stride + dw / 2 - 1,
  457. dst->v_buffer[i * dst->uv_stride + dw / 2 - 2],
  458. dst->uv_width - dw / 2 + 1);
  459. if (dh / 2 < (int)dst->uv_height)
  460. for (i = dh / 2 - 1; i < (int)dst->y_height / 2; i++)
  461. memcpy(dst->v_buffer + i * dst->uv_stride,
  462. dst->v_buffer + (dh / 2 - 2) * dst->uv_stride, dst->uv_width);
  463. }