You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

296 lines
8.3KB

  1. #include "swscale_internal.h"
  2. static void free_lines(SwsSlice *s)
  3. {
  4. int i;
  5. for (i = 0; i < 2; ++i) {
  6. int n = s->plane[i].available_lines;
  7. int j;
  8. for (j = 0; j < n; ++j) {
  9. av_freep(&s->plane[i].line[j]);
  10. if (s->is_ring)
  11. s->plane[i].line[j+n] = NULL;
  12. }
  13. }
  14. for (i = 0; i < 4; ++i)
  15. memset(s->plane[i].line, 0, sizeof(uint8_t*) * s->plane[i].available_lines * (s->is_ring ? 3 : 1));
  16. s->should_free_lines = 0;
  17. }
  18. /*
  19. slice lines contains extra bytes for vetorial code thus @size
  20. is the allocated memory size and @width is the number of pixels
  21. */
  22. static int alloc_lines(SwsSlice *s, int size, int width)
  23. {
  24. int i;
  25. int idx[2] = {3, 2};
  26. s->should_free_lines = 1;
  27. s->width = width;
  28. for (i = 0; i < 2; ++i) {
  29. int n = s->plane[i].available_lines;
  30. int j;
  31. int ii = idx[i];
  32. av_assert0(n == s->plane[ii].available_lines);
  33. for (j = 0; j < n; ++j) {
  34. // chroma plane line U and V are expected to be contiguous in memory
  35. // by mmx vertical scaler code
  36. s->plane[i].line[j] = av_malloc(size * 2 + 32);
  37. if (!s->plane[i].line[j]) {
  38. free_lines(s);
  39. return AVERROR(ENOMEM);
  40. }
  41. s->plane[ii].line[j] = s->plane[i].line[j] + size + 16;
  42. if (s->is_ring) {
  43. s->plane[i].line[j+n] = s->plane[i].line[j];
  44. s->plane[ii].line[j+n] = s->plane[ii].line[j];
  45. }
  46. }
  47. }
  48. return 0;
  49. }
  50. static int alloc_slice(SwsSlice *s, enum AVPixelFormat fmt, int lumLines, int chrLines, int h_sub_sample, int v_sub_sample, int ring)
  51. {
  52. int i;
  53. int size[4] = { lumLines,
  54. chrLines,
  55. chrLines,
  56. lumLines };
  57. s->h_chr_sub_sample = h_sub_sample;
  58. s->v_chr_sub_sample = v_sub_sample;
  59. s->fmt = fmt;
  60. s->is_ring = ring;
  61. s->should_free_lines = 0;
  62. for (i = 0; i < 4; ++i) {
  63. int n = size[i] * ( ring == 0 ? 1 : 3);
  64. s->plane[i].line = av_mallocz_array(sizeof(uint8_t*), n);
  65. if (!s->plane[i].line)
  66. return AVERROR(ENOMEM);
  67. s->plane[i].tmp = ring ? s->plane[i].line + size[i] * 2 : NULL;
  68. s->plane[i].available_lines = size[i];
  69. s->plane[i].sliceY = 0;
  70. s->plane[i].sliceH = 0;
  71. }
  72. return 0;
  73. }
  74. static void free_slice(SwsSlice *s)
  75. {
  76. int i;
  77. if (s) {
  78. if (s->should_free_lines)
  79. free_lines(s);
  80. for (i = 0; i < 4; ++i) {
  81. av_freep(&s->plane[i].line);
  82. s->plane[i].tmp = NULL;
  83. }
  84. }
  85. }
  86. int ff_rotate_slice(SwsSlice *s, int lum, int chr)
  87. {
  88. int i;
  89. if (lum) {
  90. for (i = 0; i < 4; i+=3) {
  91. int n = s->plane[i].available_lines;
  92. int l = lum - s->plane[i].sliceY;
  93. if (l >= n * 2) {
  94. s->plane[i].sliceY += n;
  95. s->plane[i].sliceH -= n;
  96. }
  97. }
  98. }
  99. if (chr) {
  100. for (i = 1; i < 3; ++i) {
  101. int n = s->plane[i].available_lines;
  102. int l = chr - s->plane[i].sliceY;
  103. if (l >= n * 2) {
  104. s->plane[i].sliceY += n;
  105. s->plane[i].sliceH -= n;
  106. }
  107. }
  108. }
  109. return 0;
  110. }
  111. int ff_init_slice_from_src(SwsSlice * s, uint8_t *src[4], int stride[4], int srcW, int lumY, int lumH, int chrY, int chrH)
  112. {
  113. int i = 0;
  114. const int start[4] = {lumY,
  115. chrY,
  116. chrY,
  117. lumY};
  118. const int end[4] = {lumY +lumH,
  119. chrY + chrH,
  120. chrY + chrH,
  121. lumY + lumH};
  122. s->width = srcW;
  123. for (i = 0; i < 4; ++i) {
  124. int j;
  125. int lines = end[i];
  126. lines = s->plane[i].available_lines < lines ? s->plane[i].available_lines : lines;
  127. if (end[i] > s->plane[i].sliceY+s->plane[i].sliceH) {
  128. if (start[i] <= s->plane[i].sliceY+1)
  129. s->plane[i].sliceY = FFMIN(start[i], s->plane[i].sliceY);
  130. else
  131. s->plane[i].sliceY = start[i];
  132. s->plane[i].sliceH = end[i] - s->plane[i].sliceY;
  133. } else {
  134. if (end[i] >= s->plane[i].sliceY)
  135. s->plane[i].sliceH = s->plane[i].sliceY + s->plane[i].sliceH - start[i];
  136. else
  137. s->plane[i].sliceH = end[i] - start[i];
  138. s->plane[i].sliceY = start[i];
  139. }
  140. for (j = start[i]; j < lines; j+= 1)
  141. s->plane[i].line[j] = src[i] + (start[i] + j) * stride[i];
  142. }
  143. return 0;
  144. }
  145. static void fill_ones(SwsSlice *s, int n, int is16bit)
  146. {
  147. int i;
  148. for (i = 0; i < 4; ++i) {
  149. int j;
  150. int size = s->plane[i].available_lines;
  151. for (j = 0; j < size; ++j) {
  152. int k;
  153. int end = is16bit ? n>>1: n;
  154. // fill also one extra element
  155. end += 1;
  156. if (is16bit)
  157. for (k = 0; k < end; ++k)
  158. ((int32_t*)(s->plane[i].line[j]))[k] = 1<<18;
  159. else
  160. for (k = 0; k < end; ++k)
  161. ((int16_t*)(s->plane[i].line[j]))[k] = 1<<14;
  162. }
  163. }
  164. }
  165. int ff_init_filters(SwsContext * c)
  166. {
  167. int i;
  168. int index;
  169. int num_ydesc;
  170. int num_cdesc;
  171. int need_lum_conv = c->lumToYV12 || c->readLumPlanar || c->alpToYV12 || c->readAlpPlanar;
  172. int need_chr_conv = c->chrToYV12 || c->readChrPlanar;
  173. int srcIdx, dstIdx;
  174. int dst_stride = FFALIGN(c->dstW * sizeof(int16_t) + 66, 16);
  175. uint32_t * pal = usePal(c->srcFormat) ? c->pal_yuv : (uint32_t*)c->input_rgb2yuv_table;
  176. int res = 0;
  177. if (c->dstBpc == 16)
  178. dst_stride <<= 1;
  179. num_ydesc = need_lum_conv ? 2 : 1;
  180. num_cdesc = need_chr_conv ? 2 : 1;
  181. c->numSlice = FFMAX(num_ydesc, num_cdesc) + 1;
  182. c->numDesc = num_ydesc + num_cdesc;
  183. c->descIndex[0] = num_ydesc;
  184. c->descIndex[1] = num_ydesc + num_cdesc;
  185. c->desc = av_mallocz_array(sizeof(SwsFilterDescriptor), c->numDesc);
  186. if (!c->desc)
  187. return AVERROR(ENOMEM);
  188. c->slice = av_mallocz_array(sizeof(SwsSlice), c->numSlice);
  189. res = alloc_slice(&c->slice[0], c->srcFormat, c->srcH, c->chrSrcH, c->chrSrcHSubSample, c->chrSrcVSubSample, 0);
  190. if (res < 0) goto cleanup;
  191. for (i = 1; i < c->numSlice-1; ++i) {
  192. res = alloc_slice(&c->slice[i], c->srcFormat, c->vLumFilterSize, c->vChrFilterSize, c->chrSrcHSubSample, c->chrSrcVSubSample, 0);
  193. if (res < 0) goto cleanup;
  194. res = alloc_lines(&c->slice[i], FFALIGN(c->srcW*2+78, 16), c->srcW);
  195. if (res < 0) goto cleanup;
  196. }
  197. res = alloc_slice(&c->slice[i], c->srcFormat, c->vLumFilterSize, c->vChrFilterSize, c->chrDstHSubSample, c->chrDstVSubSample, 1);
  198. if (res < 0) goto cleanup;
  199. res = alloc_lines(&c->slice[i], dst_stride, c->dstW);
  200. if (res < 0) goto cleanup;
  201. fill_ones(&c->slice[i], dst_stride>>1, c->dstBpc == 16);
  202. index = 0;
  203. srcIdx = 0;
  204. dstIdx = 1;
  205. if (need_lum_conv) {
  206. ff_init_desc_fmt_convert(&c->desc[index], &c->slice[srcIdx], &c->slice[dstIdx], pal);
  207. c->desc[index].alpha = c->alpPixBuf != 0;
  208. ++index;
  209. srcIdx = dstIdx;
  210. }
  211. dstIdx = FFMAX(num_ydesc, num_cdesc);
  212. ff_init_desc_hscale(&c->desc[index], &c->slice[index], &c->slice[dstIdx], c->hLumFilter, c->hLumFilterPos, c->hLumFilterSize, c->lumXInc);
  213. c->desc[index].alpha = c->alpPixBuf != 0;
  214. ++index;
  215. {
  216. srcIdx = 0;
  217. dstIdx = 1;
  218. if (need_chr_conv) {
  219. ff_init_desc_cfmt_convert(&c->desc[index], &c->slice[srcIdx], &c->slice[dstIdx], pal);
  220. ++index;
  221. srcIdx = dstIdx;
  222. }
  223. dstIdx = FFMAX(num_ydesc, num_cdesc);
  224. if (c->needs_hcscale)
  225. ff_init_desc_chscale(&c->desc[index], &c->slice[srcIdx], &c->slice[dstIdx], c->hChrFilter, c->hChrFilterPos, c->hChrFilterSize, c->chrXInc);
  226. else
  227. ff_init_desc_no_chr(&c->desc[index], &c->slice[srcIdx], &c->slice[dstIdx]);
  228. }
  229. return 0;
  230. cleanup:
  231. ff_free_filters(c);
  232. return res;
  233. }
  234. int ff_free_filters(SwsContext *c)
  235. {
  236. int i;
  237. if (c->desc) {
  238. for (i = 0; i < c->numDesc; ++i)
  239. av_freep(&c->desc[i].instance);
  240. av_freep(&c->desc);
  241. }
  242. if (c->slice) {
  243. for (i = 0; i < c->numSlice; ++i)
  244. free_slice(&c->slice[i]);
  245. av_freep(&c->slice);
  246. }
  247. return 0;
  248. }