vpx_scale.c 18 KB

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