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.

2267 lines
97KB

  1. /*
  2. * Copyright (c) 2013 Clément Bœsch
  3. * Copyright (c) 2018 Paul B Mahol
  4. *
  5. * This file is part of FFmpeg.
  6. *
  7. * FFmpeg is free software; you can redistribute it and/or
  8. * modify it under the terms of the GNU Lesser General Public
  9. * License as published by the Free Software Foundation; either
  10. * version 2.1 of the License, or (at your option) any later version.
  11. *
  12. * FFmpeg is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  15. * Lesser General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU Lesser General Public
  18. * License along with FFmpeg; if not, write to the Free Software
  19. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  20. */
  21. /**
  22. * @file
  23. * 3D Lookup table filter
  24. */
  25. #include "float.h"
  26. #include "libavutil/opt.h"
  27. #include "libavutil/file.h"
  28. #include "libavutil/intreadwrite.h"
  29. #include "libavutil/intfloat.h"
  30. #include "libavutil/avassert.h"
  31. #include "libavutil/pixdesc.h"
  32. #include "libavutil/avstring.h"
  33. #include "avfilter.h"
  34. #include "drawutils.h"
  35. #include "formats.h"
  36. #include "framesync.h"
  37. #include "internal.h"
  38. #include "video.h"
  39. #define R 0
  40. #define G 1
  41. #define B 2
  42. #define A 3
  43. enum interp_mode {
  44. INTERPOLATE_NEAREST,
  45. INTERPOLATE_TRILINEAR,
  46. INTERPOLATE_TETRAHEDRAL,
  47. INTERPOLATE_PYRAMID,
  48. INTERPOLATE_PRISM,
  49. NB_INTERP_MODE
  50. };
  51. struct rgbvec {
  52. float r, g, b;
  53. };
  54. /* 3D LUT don't often go up to level 32, but it is common to have a Hald CLUT
  55. * of 512x512 (64x64x64) */
  56. #define MAX_LEVEL 256
  57. #define PRELUT_SIZE 65536
  58. typedef struct Lut3DPreLut {
  59. int size;
  60. float min[3];
  61. float max[3];
  62. float scale[3];
  63. float* lut[3];
  64. } Lut3DPreLut;
  65. typedef struct LUT3DContext {
  66. const AVClass *class;
  67. int interpolation; ///<interp_mode
  68. char *file;
  69. uint8_t rgba_map[4];
  70. int step;
  71. avfilter_action_func *interp;
  72. struct rgbvec scale;
  73. struct rgbvec *lut;
  74. int lutsize;
  75. int lutsize2;
  76. Lut3DPreLut prelut;
  77. #if CONFIG_HALDCLUT_FILTER
  78. uint8_t clut_rgba_map[4];
  79. int clut_step;
  80. int clut_bits;
  81. int clut_planar;
  82. int clut_float;
  83. int clut_width;
  84. FFFrameSync fs;
  85. #endif
  86. } LUT3DContext;
  87. typedef struct ThreadData {
  88. AVFrame *in, *out;
  89. } ThreadData;
  90. #define OFFSET(x) offsetof(LUT3DContext, x)
  91. #define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM
  92. #define COMMON_OPTIONS \
  93. { "interp", "select interpolation mode", OFFSET(interpolation), AV_OPT_TYPE_INT, {.i64=INTERPOLATE_TETRAHEDRAL}, 0, NB_INTERP_MODE-1, FLAGS, "interp_mode" }, \
  94. { "nearest", "use values from the nearest defined points", 0, AV_OPT_TYPE_CONST, {.i64=INTERPOLATE_NEAREST}, INT_MIN, INT_MAX, FLAGS, "interp_mode" }, \
  95. { "trilinear", "interpolate values using the 8 points defining a cube", 0, AV_OPT_TYPE_CONST, {.i64=INTERPOLATE_TRILINEAR}, INT_MIN, INT_MAX, FLAGS, "interp_mode" }, \
  96. { "tetrahedral", "interpolate values using a tetrahedron", 0, AV_OPT_TYPE_CONST, {.i64=INTERPOLATE_TETRAHEDRAL}, INT_MIN, INT_MAX, FLAGS, "interp_mode" }, \
  97. { "pyramid", "interpolate values using a pyramid", 0, AV_OPT_TYPE_CONST, {.i64=INTERPOLATE_PYRAMID}, INT_MIN, INT_MAX, FLAGS, "interp_mode" }, \
  98. { "prism", "interpolate values using a prism", 0, AV_OPT_TYPE_CONST, {.i64=INTERPOLATE_PRISM}, INT_MIN, INT_MAX, FLAGS, "interp_mode" }, \
  99. { NULL }
  100. #define EXPONENT_MASK 0x7F800000
  101. #define MANTISSA_MASK 0x007FFFFF
  102. #define SIGN_MASK 0x80000000
  103. static inline float sanitizef(float f)
  104. {
  105. union av_intfloat32 t;
  106. t.f = f;
  107. if ((t.i & EXPONENT_MASK) == EXPONENT_MASK) {
  108. if ((t.i & MANTISSA_MASK) != 0) {
  109. // NAN
  110. return 0.0f;
  111. } else if (t.i & SIGN_MASK) {
  112. // -INF
  113. return -FLT_MAX;
  114. } else {
  115. // +INF
  116. return FLT_MAX;
  117. }
  118. }
  119. return f;
  120. }
  121. static inline float lerpf(float v0, float v1, float f)
  122. {
  123. return v0 + (v1 - v0) * f;
  124. }
  125. static inline struct rgbvec lerp(const struct rgbvec *v0, const struct rgbvec *v1, float f)
  126. {
  127. struct rgbvec v = {
  128. lerpf(v0->r, v1->r, f), lerpf(v0->g, v1->g, f), lerpf(v0->b, v1->b, f)
  129. };
  130. return v;
  131. }
  132. #define NEAR(x) ((int)((x) + .5))
  133. #define PREV(x) ((int)(x))
  134. #define NEXT(x) (FFMIN((int)(x) + 1, lut3d->lutsize - 1))
  135. /**
  136. * Get the nearest defined point
  137. */
  138. static inline struct rgbvec interp_nearest(const LUT3DContext *lut3d,
  139. const struct rgbvec *s)
  140. {
  141. return lut3d->lut[NEAR(s->r) * lut3d->lutsize2 + NEAR(s->g) * lut3d->lutsize + NEAR(s->b)];
  142. }
  143. /**
  144. * Interpolate using the 8 vertices of a cube
  145. * @see https://en.wikipedia.org/wiki/Trilinear_interpolation
  146. */
  147. static inline struct rgbvec interp_trilinear(const LUT3DContext *lut3d,
  148. const struct rgbvec *s)
  149. {
  150. const int lutsize2 = lut3d->lutsize2;
  151. const int lutsize = lut3d->lutsize;
  152. const int prev[] = {PREV(s->r), PREV(s->g), PREV(s->b)};
  153. const int next[] = {NEXT(s->r), NEXT(s->g), NEXT(s->b)};
  154. const struct rgbvec d = {s->r - prev[0], s->g - prev[1], s->b - prev[2]};
  155. const struct rgbvec c000 = lut3d->lut[prev[0] * lutsize2 + prev[1] * lutsize + prev[2]];
  156. const struct rgbvec c001 = lut3d->lut[prev[0] * lutsize2 + prev[1] * lutsize + next[2]];
  157. const struct rgbvec c010 = lut3d->lut[prev[0] * lutsize2 + next[1] * lutsize + prev[2]];
  158. const struct rgbvec c011 = lut3d->lut[prev[0] * lutsize2 + next[1] * lutsize + next[2]];
  159. const struct rgbvec c100 = lut3d->lut[next[0] * lutsize2 + prev[1] * lutsize + prev[2]];
  160. const struct rgbvec c101 = lut3d->lut[next[0] * lutsize2 + prev[1] * lutsize + next[2]];
  161. const struct rgbvec c110 = lut3d->lut[next[0] * lutsize2 + next[1] * lutsize + prev[2]];
  162. const struct rgbvec c111 = lut3d->lut[next[0] * lutsize2 + next[1] * lutsize + next[2]];
  163. const struct rgbvec c00 = lerp(&c000, &c100, d.r);
  164. const struct rgbvec c10 = lerp(&c010, &c110, d.r);
  165. const struct rgbvec c01 = lerp(&c001, &c101, d.r);
  166. const struct rgbvec c11 = lerp(&c011, &c111, d.r);
  167. const struct rgbvec c0 = lerp(&c00, &c10, d.g);
  168. const struct rgbvec c1 = lerp(&c01, &c11, d.g);
  169. const struct rgbvec c = lerp(&c0, &c1, d.b);
  170. return c;
  171. }
  172. static inline struct rgbvec interp_pyramid(const LUT3DContext *lut3d,
  173. const struct rgbvec *s)
  174. {
  175. const int lutsize2 = lut3d->lutsize2;
  176. const int lutsize = lut3d->lutsize;
  177. const int prev[] = {PREV(s->r), PREV(s->g), PREV(s->b)};
  178. const int next[] = {NEXT(s->r), NEXT(s->g), NEXT(s->b)};
  179. const struct rgbvec d = {s->r - prev[0], s->g - prev[1], s->b - prev[2]};
  180. const struct rgbvec c000 = lut3d->lut[prev[0] * lutsize2 + prev[1] * lutsize + prev[2]];
  181. const struct rgbvec c111 = lut3d->lut[next[0] * lutsize2 + next[1] * lutsize + next[2]];
  182. struct rgbvec c;
  183. if (d.g > d.r && d.b > d.r) {
  184. const struct rgbvec c001 = lut3d->lut[prev[0] * lutsize2 + prev[1] * lutsize + next[2]];
  185. const struct rgbvec c010 = lut3d->lut[prev[0] * lutsize2 + next[1] * lutsize + prev[2]];
  186. const struct rgbvec c011 = lut3d->lut[prev[0] * lutsize2 + next[1] * lutsize + next[2]];
  187. c.r = c000.r + (c111.r - c011.r) * d.r + (c010.r - c000.r) * d.g + (c001.r - c000.r) * d.b +
  188. (c011.r - c001.r - c010.r + c000.r) * d.g * d.b;
  189. c.g = c000.g + (c111.g - c011.g) * d.r + (c010.g - c000.g) * d.g + (c001.g - c000.g) * d.b +
  190. (c011.g - c001.g - c010.g + c000.g) * d.g * d.b;
  191. c.b = c000.b + (c111.b - c011.b) * d.r + (c010.b - c000.b) * d.g + (c001.b - c000.b) * d.b +
  192. (c011.b - c001.b - c010.b + c000.b) * d.g * d.b;
  193. } else if (d.r > d.g && d.b > d.g) {
  194. const struct rgbvec c001 = lut3d->lut[prev[0] * lutsize2 + prev[1] * lutsize + next[2]];
  195. const struct rgbvec c100 = lut3d->lut[next[0] * lutsize2 + prev[1] * lutsize + prev[2]];
  196. const struct rgbvec c101 = lut3d->lut[next[0] * lutsize2 + prev[1] * lutsize + next[2]];
  197. c.r = c000.r + (c100.r - c000.r) * d.r + (c111.r - c101.r) * d.g + (c001.r - c000.r) * d.b +
  198. (c101.r - c001.r - c100.r + c000.r) * d.r * d.b;
  199. c.g = c000.g + (c100.g - c000.g) * d.r + (c111.g - c101.g) * d.g + (c001.g - c000.g) * d.b +
  200. (c101.g - c001.g - c100.g + c000.g) * d.r * d.b;
  201. c.b = c000.b + (c100.b - c000.b) * d.r + (c111.b - c101.b) * d.g + (c001.b - c000.b) * d.b +
  202. (c101.b - c001.b - c100.b + c000.b) * d.r * d.b;
  203. } else {
  204. const struct rgbvec c010 = lut3d->lut[prev[0] * lutsize2 + next[1] * lutsize + prev[2]];
  205. const struct rgbvec c110 = lut3d->lut[next[0] * lutsize2 + next[1] * lutsize + prev[2]];
  206. const struct rgbvec c100 = lut3d->lut[next[0] * lutsize2 + prev[1] * lutsize + prev[2]];
  207. c.r = c000.r + (c100.r - c000.r) * d.r + (c010.r - c000.r) * d.g + (c111.r - c110.r) * d.b +
  208. (c110.r - c100.r - c010.r + c000.r) * d.r * d.g;
  209. c.g = c000.g + (c100.g - c000.g) * d.r + (c010.g - c000.g) * d.g + (c111.g - c110.g) * d.b +
  210. (c110.g - c100.g - c010.g + c000.g) * d.r * d.g;
  211. c.b = c000.b + (c100.b - c000.b) * d.r + (c010.b - c000.b) * d.g + (c111.b - c110.b) * d.b +
  212. (c110.b - c100.b - c010.b + c000.b) * d.r * d.g;
  213. }
  214. return c;
  215. }
  216. static inline struct rgbvec interp_prism(const LUT3DContext *lut3d,
  217. const struct rgbvec *s)
  218. {
  219. const int lutsize2 = lut3d->lutsize2;
  220. const int lutsize = lut3d->lutsize;
  221. const int prev[] = {PREV(s->r), PREV(s->g), PREV(s->b)};
  222. const int next[] = {NEXT(s->r), NEXT(s->g), NEXT(s->b)};
  223. const struct rgbvec d = {s->r - prev[0], s->g - prev[1], s->b - prev[2]};
  224. const struct rgbvec c000 = lut3d->lut[prev[0] * lutsize2 + prev[1] * lutsize + prev[2]];
  225. const struct rgbvec c010 = lut3d->lut[prev[0] * lutsize2 + next[1] * lutsize + prev[2]];
  226. const struct rgbvec c101 = lut3d->lut[next[0] * lutsize2 + prev[1] * lutsize + next[2]];
  227. const struct rgbvec c111 = lut3d->lut[next[0] * lutsize2 + next[1] * lutsize + next[2]];
  228. struct rgbvec c;
  229. if (d.b > d.r) {
  230. const struct rgbvec c001 = lut3d->lut[prev[0] * lutsize2 + prev[1] * lutsize + next[2]];
  231. const struct rgbvec c011 = lut3d->lut[prev[0] * lutsize2 + next[1] * lutsize + next[2]];
  232. c.r = c000.r + (c001.r - c000.r) * d.b + (c101.r - c001.r) * d.r + (c010.r - c000.r) * d.g +
  233. (c000.r - c010.r - c001.r + c011.r) * d.b * d.g +
  234. (c001.r - c011.r - c101.r + c111.r) * d.r * d.g;
  235. c.g = c000.g + (c001.g - c000.g) * d.b + (c101.g - c001.g) * d.r + (c010.g - c000.g) * d.g +
  236. (c000.g - c010.g - c001.g + c011.g) * d.b * d.g +
  237. (c001.g - c011.g - c101.g + c111.g) * d.r * d.g;
  238. c.b = c000.b + (c001.b - c000.b) * d.b + (c101.b - c001.b) * d.r + (c010.b - c000.b) * d.g +
  239. (c000.b - c010.b - c001.b + c011.b) * d.b * d.g +
  240. (c001.b - c011.b - c101.b + c111.b) * d.r * d.g;
  241. } else {
  242. const struct rgbvec c110 = lut3d->lut[next[0] * lutsize2 + next[1] * lutsize + prev[2]];
  243. const struct rgbvec c100 = lut3d->lut[next[0] * lutsize2 + prev[1] * lutsize + prev[2]];
  244. c.r = c000.r + (c101.r - c100.r) * d.b + (c100.r - c000.r) * d.r + (c010.r - c000.r) * d.g +
  245. (c100.r - c110.r - c101.r + c111.r) * d.b * d.g +
  246. (c000.r - c010.r - c100.r + c110.r) * d.r * d.g;
  247. c.g = c000.g + (c101.g - c100.g) * d.b + (c100.g - c000.g) * d.r + (c010.g - c000.g) * d.g +
  248. (c100.g - c110.g - c101.g + c111.g) * d.b * d.g +
  249. (c000.g - c010.g - c100.g + c110.g) * d.r * d.g;
  250. c.b = c000.b + (c101.b - c100.b) * d.b + (c100.b - c000.b) * d.r + (c010.b - c000.b) * d.g +
  251. (c100.b - c110.b - c101.b + c111.b) * d.b * d.g +
  252. (c000.b - c010.b - c100.b + c110.b) * d.r * d.g;
  253. }
  254. return c;
  255. }
  256. /**
  257. * Tetrahedral interpolation. Based on code found in Truelight Software Library paper.
  258. * @see http://www.filmlight.ltd.uk/pdf/whitepapers/FL-TL-TN-0057-SoftwareLib.pdf
  259. */
  260. static inline struct rgbvec interp_tetrahedral(const LUT3DContext *lut3d,
  261. const struct rgbvec *s)
  262. {
  263. const int lutsize2 = lut3d->lutsize2;
  264. const int lutsize = lut3d->lutsize;
  265. const int prev[] = {PREV(s->r), PREV(s->g), PREV(s->b)};
  266. const int next[] = {NEXT(s->r), NEXT(s->g), NEXT(s->b)};
  267. const struct rgbvec d = {s->r - prev[0], s->g - prev[1], s->b - prev[2]};
  268. const struct rgbvec c000 = lut3d->lut[prev[0] * lutsize2 + prev[1] * lutsize + prev[2]];
  269. const struct rgbvec c111 = lut3d->lut[next[0] * lutsize2 + next[1] * lutsize + next[2]];
  270. struct rgbvec c;
  271. if (d.r > d.g) {
  272. if (d.g > d.b) {
  273. const struct rgbvec c100 = lut3d->lut[next[0] * lutsize2 + prev[1] * lutsize + prev[2]];
  274. const struct rgbvec c110 = lut3d->lut[next[0] * lutsize2 + next[1] * lutsize + prev[2]];
  275. c.r = (1-d.r) * c000.r + (d.r-d.g) * c100.r + (d.g-d.b) * c110.r + (d.b) * c111.r;
  276. c.g = (1-d.r) * c000.g + (d.r-d.g) * c100.g + (d.g-d.b) * c110.g + (d.b) * c111.g;
  277. c.b = (1-d.r) * c000.b + (d.r-d.g) * c100.b + (d.g-d.b) * c110.b + (d.b) * c111.b;
  278. } else if (d.r > d.b) {
  279. const struct rgbvec c100 = lut3d->lut[next[0] * lutsize2 + prev[1] * lutsize + prev[2]];
  280. const struct rgbvec c101 = lut3d->lut[next[0] * lutsize2 + prev[1] * lutsize + next[2]];
  281. c.r = (1-d.r) * c000.r + (d.r-d.b) * c100.r + (d.b-d.g) * c101.r + (d.g) * c111.r;
  282. c.g = (1-d.r) * c000.g + (d.r-d.b) * c100.g + (d.b-d.g) * c101.g + (d.g) * c111.g;
  283. c.b = (1-d.r) * c000.b + (d.r-d.b) * c100.b + (d.b-d.g) * c101.b + (d.g) * c111.b;
  284. } else {
  285. const struct rgbvec c001 = lut3d->lut[prev[0] * lutsize2 + prev[1] * lutsize + next[2]];
  286. const struct rgbvec c101 = lut3d->lut[next[0] * lutsize2 + prev[1] * lutsize + next[2]];
  287. c.r = (1-d.b) * c000.r + (d.b-d.r) * c001.r + (d.r-d.g) * c101.r + (d.g) * c111.r;
  288. c.g = (1-d.b) * c000.g + (d.b-d.r) * c001.g + (d.r-d.g) * c101.g + (d.g) * c111.g;
  289. c.b = (1-d.b) * c000.b + (d.b-d.r) * c001.b + (d.r-d.g) * c101.b + (d.g) * c111.b;
  290. }
  291. } else {
  292. if (d.b > d.g) {
  293. const struct rgbvec c001 = lut3d->lut[prev[0] * lutsize2 + prev[1] * lutsize + next[2]];
  294. const struct rgbvec c011 = lut3d->lut[prev[0] * lutsize2 + next[1] * lutsize + next[2]];
  295. c.r = (1-d.b) * c000.r + (d.b-d.g) * c001.r + (d.g-d.r) * c011.r + (d.r) * c111.r;
  296. c.g = (1-d.b) * c000.g + (d.b-d.g) * c001.g + (d.g-d.r) * c011.g + (d.r) * c111.g;
  297. c.b = (1-d.b) * c000.b + (d.b-d.g) * c001.b + (d.g-d.r) * c011.b + (d.r) * c111.b;
  298. } else if (d.b > d.r) {
  299. const struct rgbvec c010 = lut3d->lut[prev[0] * lutsize2 + next[1] * lutsize + prev[2]];
  300. const struct rgbvec c011 = lut3d->lut[prev[0] * lutsize2 + next[1] * lutsize + next[2]];
  301. c.r = (1-d.g) * c000.r + (d.g-d.b) * c010.r + (d.b-d.r) * c011.r + (d.r) * c111.r;
  302. c.g = (1-d.g) * c000.g + (d.g-d.b) * c010.g + (d.b-d.r) * c011.g + (d.r) * c111.g;
  303. c.b = (1-d.g) * c000.b + (d.g-d.b) * c010.b + (d.b-d.r) * c011.b + (d.r) * c111.b;
  304. } else {
  305. const struct rgbvec c010 = lut3d->lut[prev[0] * lutsize2 + next[1] * lutsize + prev[2]];
  306. const struct rgbvec c110 = lut3d->lut[next[0] * lutsize2 + next[1] * lutsize + prev[2]];
  307. c.r = (1-d.g) * c000.r + (d.g-d.r) * c010.r + (d.r-d.b) * c110.r + (d.b) * c111.r;
  308. c.g = (1-d.g) * c000.g + (d.g-d.r) * c010.g + (d.r-d.b) * c110.g + (d.b) * c111.g;
  309. c.b = (1-d.g) * c000.b + (d.g-d.r) * c010.b + (d.r-d.b) * c110.b + (d.b) * c111.b;
  310. }
  311. }
  312. return c;
  313. }
  314. static inline float prelut_interp_1d_linear(const Lut3DPreLut *prelut,
  315. int idx, const float s)
  316. {
  317. const int lut_max = prelut->size - 1;
  318. const float scaled = (s - prelut->min[idx]) * prelut->scale[idx];
  319. const float x = av_clipf(scaled, 0.0f, lut_max);
  320. const int prev = PREV(x);
  321. const int next = FFMIN((int)(x) + 1, lut_max);
  322. const float p = prelut->lut[idx][prev];
  323. const float n = prelut->lut[idx][next];
  324. const float d = x - (float)prev;
  325. return lerpf(p, n, d);
  326. }
  327. static inline struct rgbvec apply_prelut(const Lut3DPreLut *prelut,
  328. const struct rgbvec *s)
  329. {
  330. struct rgbvec c;
  331. if (prelut->size <= 0)
  332. return *s;
  333. c.r = prelut_interp_1d_linear(prelut, 0, s->r);
  334. c.g = prelut_interp_1d_linear(prelut, 1, s->g);
  335. c.b = prelut_interp_1d_linear(prelut, 2, s->b);
  336. return c;
  337. }
  338. #define DEFINE_INTERP_FUNC_PLANAR(name, nbits, depth) \
  339. static int interp_##nbits##_##name##_p##depth(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) \
  340. { \
  341. int x, y; \
  342. const LUT3DContext *lut3d = ctx->priv; \
  343. const Lut3DPreLut *prelut = &lut3d->prelut; \
  344. const ThreadData *td = arg; \
  345. const AVFrame *in = td->in; \
  346. const AVFrame *out = td->out; \
  347. const int direct = out == in; \
  348. const int slice_start = (in->height * jobnr ) / nb_jobs; \
  349. const int slice_end = (in->height * (jobnr+1)) / nb_jobs; \
  350. uint8_t *grow = out->data[0] + slice_start * out->linesize[0]; \
  351. uint8_t *brow = out->data[1] + slice_start * out->linesize[1]; \
  352. uint8_t *rrow = out->data[2] + slice_start * out->linesize[2]; \
  353. uint8_t *arow = out->data[3] + slice_start * out->linesize[3]; \
  354. const uint8_t *srcgrow = in->data[0] + slice_start * in->linesize[0]; \
  355. const uint8_t *srcbrow = in->data[1] + slice_start * in->linesize[1]; \
  356. const uint8_t *srcrrow = in->data[2] + slice_start * in->linesize[2]; \
  357. const uint8_t *srcarow = in->data[3] + slice_start * in->linesize[3]; \
  358. const float lut_max = lut3d->lutsize - 1; \
  359. const float scale_f = 1.0f / ((1<<depth) - 1); \
  360. const float scale_r = lut3d->scale.r * lut_max; \
  361. const float scale_g = lut3d->scale.g * lut_max; \
  362. const float scale_b = lut3d->scale.b * lut_max; \
  363. \
  364. for (y = slice_start; y < slice_end; y++) { \
  365. uint##nbits##_t *dstg = (uint##nbits##_t *)grow; \
  366. uint##nbits##_t *dstb = (uint##nbits##_t *)brow; \
  367. uint##nbits##_t *dstr = (uint##nbits##_t *)rrow; \
  368. uint##nbits##_t *dsta = (uint##nbits##_t *)arow; \
  369. const uint##nbits##_t *srcg = (const uint##nbits##_t *)srcgrow; \
  370. const uint##nbits##_t *srcb = (const uint##nbits##_t *)srcbrow; \
  371. const uint##nbits##_t *srcr = (const uint##nbits##_t *)srcrrow; \
  372. const uint##nbits##_t *srca = (const uint##nbits##_t *)srcarow; \
  373. for (x = 0; x < in->width; x++) { \
  374. const struct rgbvec rgb = {srcr[x] * scale_f, \
  375. srcg[x] * scale_f, \
  376. srcb[x] * scale_f}; \
  377. const struct rgbvec prelut_rgb = apply_prelut(prelut, &rgb); \
  378. const struct rgbvec scaled_rgb = {av_clipf(prelut_rgb.r * scale_r, 0, lut_max), \
  379. av_clipf(prelut_rgb.g * scale_g, 0, lut_max), \
  380. av_clipf(prelut_rgb.b * scale_b, 0, lut_max)}; \
  381. struct rgbvec vec = interp_##name(lut3d, &scaled_rgb); \
  382. dstr[x] = av_clip_uintp2(vec.r * (float)((1<<depth) - 1), depth); \
  383. dstg[x] = av_clip_uintp2(vec.g * (float)((1<<depth) - 1), depth); \
  384. dstb[x] = av_clip_uintp2(vec.b * (float)((1<<depth) - 1), depth); \
  385. if (!direct && in->linesize[3]) \
  386. dsta[x] = srca[x]; \
  387. } \
  388. grow += out->linesize[0]; \
  389. brow += out->linesize[1]; \
  390. rrow += out->linesize[2]; \
  391. arow += out->linesize[3]; \
  392. srcgrow += in->linesize[0]; \
  393. srcbrow += in->linesize[1]; \
  394. srcrrow += in->linesize[2]; \
  395. srcarow += in->linesize[3]; \
  396. } \
  397. return 0; \
  398. }
  399. DEFINE_INTERP_FUNC_PLANAR(nearest, 8, 8)
  400. DEFINE_INTERP_FUNC_PLANAR(trilinear, 8, 8)
  401. DEFINE_INTERP_FUNC_PLANAR(tetrahedral, 8, 8)
  402. DEFINE_INTERP_FUNC_PLANAR(pyramid, 8, 8)
  403. DEFINE_INTERP_FUNC_PLANAR(prism, 8, 8)
  404. DEFINE_INTERP_FUNC_PLANAR(nearest, 16, 9)
  405. DEFINE_INTERP_FUNC_PLANAR(trilinear, 16, 9)
  406. DEFINE_INTERP_FUNC_PLANAR(tetrahedral, 16, 9)
  407. DEFINE_INTERP_FUNC_PLANAR(pyramid, 16, 9)
  408. DEFINE_INTERP_FUNC_PLANAR(prism, 16, 9)
  409. DEFINE_INTERP_FUNC_PLANAR(nearest, 16, 10)
  410. DEFINE_INTERP_FUNC_PLANAR(trilinear, 16, 10)
  411. DEFINE_INTERP_FUNC_PLANAR(tetrahedral, 16, 10)
  412. DEFINE_INTERP_FUNC_PLANAR(pyramid, 16, 10)
  413. DEFINE_INTERP_FUNC_PLANAR(prism, 16, 10)
  414. DEFINE_INTERP_FUNC_PLANAR(nearest, 16, 12)
  415. DEFINE_INTERP_FUNC_PLANAR(trilinear, 16, 12)
  416. DEFINE_INTERP_FUNC_PLANAR(tetrahedral, 16, 12)
  417. DEFINE_INTERP_FUNC_PLANAR(pyramid, 16, 12)
  418. DEFINE_INTERP_FUNC_PLANAR(prism, 16, 12)
  419. DEFINE_INTERP_FUNC_PLANAR(nearest, 16, 14)
  420. DEFINE_INTERP_FUNC_PLANAR(trilinear, 16, 14)
  421. DEFINE_INTERP_FUNC_PLANAR(tetrahedral, 16, 14)
  422. DEFINE_INTERP_FUNC_PLANAR(pyramid, 16, 14)
  423. DEFINE_INTERP_FUNC_PLANAR(prism, 16, 14)
  424. DEFINE_INTERP_FUNC_PLANAR(nearest, 16, 16)
  425. DEFINE_INTERP_FUNC_PLANAR(trilinear, 16, 16)
  426. DEFINE_INTERP_FUNC_PLANAR(tetrahedral, 16, 16)
  427. DEFINE_INTERP_FUNC_PLANAR(pyramid, 16, 16)
  428. DEFINE_INTERP_FUNC_PLANAR(prism, 16, 16)
  429. #define DEFINE_INTERP_FUNC_PLANAR_FLOAT(name, depth) \
  430. static int interp_##name##_pf##depth(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) \
  431. { \
  432. int x, y; \
  433. const LUT3DContext *lut3d = ctx->priv; \
  434. const Lut3DPreLut *prelut = &lut3d->prelut; \
  435. const ThreadData *td = arg; \
  436. const AVFrame *in = td->in; \
  437. const AVFrame *out = td->out; \
  438. const int direct = out == in; \
  439. const int slice_start = (in->height * jobnr ) / nb_jobs; \
  440. const int slice_end = (in->height * (jobnr+1)) / nb_jobs; \
  441. uint8_t *grow = out->data[0] + slice_start * out->linesize[0]; \
  442. uint8_t *brow = out->data[1] + slice_start * out->linesize[1]; \
  443. uint8_t *rrow = out->data[2] + slice_start * out->linesize[2]; \
  444. uint8_t *arow = out->data[3] + slice_start * out->linesize[3]; \
  445. const uint8_t *srcgrow = in->data[0] + slice_start * in->linesize[0]; \
  446. const uint8_t *srcbrow = in->data[1] + slice_start * in->linesize[1]; \
  447. const uint8_t *srcrrow = in->data[2] + slice_start * in->linesize[2]; \
  448. const uint8_t *srcarow = in->data[3] + slice_start * in->linesize[3]; \
  449. const float lut_max = lut3d->lutsize - 1; \
  450. const float scale_r = lut3d->scale.r * lut_max; \
  451. const float scale_g = lut3d->scale.g * lut_max; \
  452. const float scale_b = lut3d->scale.b * lut_max; \
  453. \
  454. for (y = slice_start; y < slice_end; y++) { \
  455. float *dstg = (float *)grow; \
  456. float *dstb = (float *)brow; \
  457. float *dstr = (float *)rrow; \
  458. float *dsta = (float *)arow; \
  459. const float *srcg = (const float *)srcgrow; \
  460. const float *srcb = (const float *)srcbrow; \
  461. const float *srcr = (const float *)srcrrow; \
  462. const float *srca = (const float *)srcarow; \
  463. for (x = 0; x < in->width; x++) { \
  464. const struct rgbvec rgb = {sanitizef(srcr[x]), \
  465. sanitizef(srcg[x]), \
  466. sanitizef(srcb[x])}; \
  467. const struct rgbvec prelut_rgb = apply_prelut(prelut, &rgb); \
  468. const struct rgbvec scaled_rgb = {av_clipf(prelut_rgb.r * scale_r, 0, lut_max), \
  469. av_clipf(prelut_rgb.g * scale_g, 0, lut_max), \
  470. av_clipf(prelut_rgb.b * scale_b, 0, lut_max)}; \
  471. struct rgbvec vec = interp_##name(lut3d, &scaled_rgb); \
  472. dstr[x] = vec.r; \
  473. dstg[x] = vec.g; \
  474. dstb[x] = vec.b; \
  475. if (!direct && in->linesize[3]) \
  476. dsta[x] = srca[x]; \
  477. } \
  478. grow += out->linesize[0]; \
  479. brow += out->linesize[1]; \
  480. rrow += out->linesize[2]; \
  481. arow += out->linesize[3]; \
  482. srcgrow += in->linesize[0]; \
  483. srcbrow += in->linesize[1]; \
  484. srcrrow += in->linesize[2]; \
  485. srcarow += in->linesize[3]; \
  486. } \
  487. return 0; \
  488. }
  489. DEFINE_INTERP_FUNC_PLANAR_FLOAT(nearest, 32)
  490. DEFINE_INTERP_FUNC_PLANAR_FLOAT(trilinear, 32)
  491. DEFINE_INTERP_FUNC_PLANAR_FLOAT(tetrahedral, 32)
  492. DEFINE_INTERP_FUNC_PLANAR_FLOAT(pyramid, 32)
  493. DEFINE_INTERP_FUNC_PLANAR_FLOAT(prism, 32)
  494. #define DEFINE_INTERP_FUNC(name, nbits) \
  495. static int interp_##nbits##_##name(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) \
  496. { \
  497. int x, y; \
  498. const LUT3DContext *lut3d = ctx->priv; \
  499. const Lut3DPreLut *prelut = &lut3d->prelut; \
  500. const ThreadData *td = arg; \
  501. const AVFrame *in = td->in; \
  502. const AVFrame *out = td->out; \
  503. const int direct = out == in; \
  504. const int step = lut3d->step; \
  505. const uint8_t r = lut3d->rgba_map[R]; \
  506. const uint8_t g = lut3d->rgba_map[G]; \
  507. const uint8_t b = lut3d->rgba_map[B]; \
  508. const uint8_t a = lut3d->rgba_map[A]; \
  509. const int slice_start = (in->height * jobnr ) / nb_jobs; \
  510. const int slice_end = (in->height * (jobnr+1)) / nb_jobs; \
  511. uint8_t *dstrow = out->data[0] + slice_start * out->linesize[0]; \
  512. const uint8_t *srcrow = in ->data[0] + slice_start * in ->linesize[0]; \
  513. const float lut_max = lut3d->lutsize - 1; \
  514. const float scale_f = 1.0f / ((1<<nbits) - 1); \
  515. const float scale_r = lut3d->scale.r * lut_max; \
  516. const float scale_g = lut3d->scale.g * lut_max; \
  517. const float scale_b = lut3d->scale.b * lut_max; \
  518. \
  519. for (y = slice_start; y < slice_end; y++) { \
  520. uint##nbits##_t *dst = (uint##nbits##_t *)dstrow; \
  521. const uint##nbits##_t *src = (const uint##nbits##_t *)srcrow; \
  522. for (x = 0; x < in->width * step; x += step) { \
  523. const struct rgbvec rgb = {src[x + r] * scale_f, \
  524. src[x + g] * scale_f, \
  525. src[x + b] * scale_f}; \
  526. const struct rgbvec prelut_rgb = apply_prelut(prelut, &rgb); \
  527. const struct rgbvec scaled_rgb = {av_clipf(prelut_rgb.r * scale_r, 0, lut_max), \
  528. av_clipf(prelut_rgb.g * scale_g, 0, lut_max), \
  529. av_clipf(prelut_rgb.b * scale_b, 0, lut_max)}; \
  530. struct rgbvec vec = interp_##name(lut3d, &scaled_rgb); \
  531. dst[x + r] = av_clip_uint##nbits(vec.r * (float)((1<<nbits) - 1)); \
  532. dst[x + g] = av_clip_uint##nbits(vec.g * (float)((1<<nbits) - 1)); \
  533. dst[x + b] = av_clip_uint##nbits(vec.b * (float)((1<<nbits) - 1)); \
  534. if (!direct && step == 4) \
  535. dst[x + a] = src[x + a]; \
  536. } \
  537. dstrow += out->linesize[0]; \
  538. srcrow += in ->linesize[0]; \
  539. } \
  540. return 0; \
  541. }
  542. DEFINE_INTERP_FUNC(nearest, 8)
  543. DEFINE_INTERP_FUNC(trilinear, 8)
  544. DEFINE_INTERP_FUNC(tetrahedral, 8)
  545. DEFINE_INTERP_FUNC(pyramid, 8)
  546. DEFINE_INTERP_FUNC(prism, 8)
  547. DEFINE_INTERP_FUNC(nearest, 16)
  548. DEFINE_INTERP_FUNC(trilinear, 16)
  549. DEFINE_INTERP_FUNC(tetrahedral, 16)
  550. DEFINE_INTERP_FUNC(pyramid, 16)
  551. DEFINE_INTERP_FUNC(prism, 16)
  552. #define MAX_LINE_SIZE 512
  553. static int skip_line(const char *p)
  554. {
  555. while (*p && av_isspace(*p))
  556. p++;
  557. return !*p || *p == '#';
  558. }
  559. static char* fget_next_word(char* dst, int max, FILE* f)
  560. {
  561. int c;
  562. char *p = dst;
  563. /* for null */
  564. max--;
  565. /* skip until next non whitespace char */
  566. while ((c = fgetc(f)) != EOF) {
  567. if (av_isspace(c))
  568. continue;
  569. *p++ = c;
  570. max--;
  571. break;
  572. }
  573. /* get max bytes or up until next whitespace char */
  574. for (; max > 0; max--) {
  575. if ((c = fgetc(f)) == EOF)
  576. break;
  577. if (av_isspace(c))
  578. break;
  579. *p++ = c;
  580. }
  581. *p = 0;
  582. if (p == dst)
  583. return NULL;
  584. return p;
  585. }
  586. #define NEXT_LINE(loop_cond) do { \
  587. if (!fgets(line, sizeof(line), f)) { \
  588. av_log(ctx, AV_LOG_ERROR, "Unexpected EOF\n"); \
  589. return AVERROR_INVALIDDATA; \
  590. } \
  591. } while (loop_cond)
  592. #define NEXT_LINE_OR_GOTO(loop_cond, label) do { \
  593. if (!fgets(line, sizeof(line), f)) { \
  594. av_log(ctx, AV_LOG_ERROR, "Unexpected EOF\n"); \
  595. ret = AVERROR_INVALIDDATA; \
  596. goto label; \
  597. } \
  598. } while (loop_cond)
  599. static int allocate_3dlut(AVFilterContext *ctx, int lutsize, int prelut)
  600. {
  601. LUT3DContext *lut3d = ctx->priv;
  602. int i;
  603. if (lutsize < 2 || lutsize > MAX_LEVEL) {
  604. av_log(ctx, AV_LOG_ERROR, "Too large or invalid 3D LUT size\n");
  605. return AVERROR(EINVAL);
  606. }
  607. av_freep(&lut3d->lut);
  608. lut3d->lut = av_malloc_array(lutsize * lutsize * lutsize, sizeof(*lut3d->lut));
  609. if (!lut3d->lut)
  610. return AVERROR(ENOMEM);
  611. if (prelut) {
  612. lut3d->prelut.size = PRELUT_SIZE;
  613. for (i = 0; i < 3; i++) {
  614. av_freep(&lut3d->prelut.lut[i]);
  615. lut3d->prelut.lut[i] = av_malloc_array(PRELUT_SIZE, sizeof(*lut3d->prelut.lut[0]));
  616. if (!lut3d->prelut.lut[i])
  617. return AVERROR(ENOMEM);
  618. }
  619. } else {
  620. lut3d->prelut.size = 0;
  621. for (i = 0; i < 3; i++) {
  622. av_freep(&lut3d->prelut.lut[i]);
  623. }
  624. }
  625. lut3d->lutsize = lutsize;
  626. lut3d->lutsize2 = lutsize * lutsize;
  627. return 0;
  628. }
  629. /* Basically r g and b float values on each line, with a facultative 3DLUTSIZE
  630. * directive; seems to be generated by Davinci */
  631. static int parse_dat(AVFilterContext *ctx, FILE *f)
  632. {
  633. LUT3DContext *lut3d = ctx->priv;
  634. char line[MAX_LINE_SIZE];
  635. int ret, i, j, k, size, size2;
  636. lut3d->lutsize = size = 33;
  637. size2 = size * size;
  638. NEXT_LINE(skip_line(line));
  639. if (!strncmp(line, "3DLUTSIZE ", 10)) {
  640. size = strtol(line + 10, NULL, 0);
  641. NEXT_LINE(skip_line(line));
  642. }
  643. ret = allocate_3dlut(ctx, size, 0);
  644. if (ret < 0)
  645. return ret;
  646. for (k = 0; k < size; k++) {
  647. for (j = 0; j < size; j++) {
  648. for (i = 0; i < size; i++) {
  649. struct rgbvec *vec = &lut3d->lut[k * size2 + j * size + i];
  650. if (k != 0 || j != 0 || i != 0)
  651. NEXT_LINE(skip_line(line));
  652. if (av_sscanf(line, "%f %f %f", &vec->r, &vec->g, &vec->b) != 3)
  653. return AVERROR_INVALIDDATA;
  654. }
  655. }
  656. }
  657. return 0;
  658. }
  659. /* Iridas format */
  660. static int parse_cube(AVFilterContext *ctx, FILE *f)
  661. {
  662. LUT3DContext *lut3d = ctx->priv;
  663. char line[MAX_LINE_SIZE];
  664. float min[3] = {0.0, 0.0, 0.0};
  665. float max[3] = {1.0, 1.0, 1.0};
  666. while (fgets(line, sizeof(line), f)) {
  667. if (!strncmp(line, "LUT_3D_SIZE", 11)) {
  668. int ret, i, j, k;
  669. const int size = strtol(line + 12, NULL, 0);
  670. const int size2 = size * size;
  671. ret = allocate_3dlut(ctx, size, 0);
  672. if (ret < 0)
  673. return ret;
  674. for (k = 0; k < size; k++) {
  675. for (j = 0; j < size; j++) {
  676. for (i = 0; i < size; i++) {
  677. struct rgbvec *vec = &lut3d->lut[i * size2 + j * size + k];
  678. do {
  679. try_again:
  680. NEXT_LINE(0);
  681. if (!strncmp(line, "DOMAIN_", 7)) {
  682. float *vals = NULL;
  683. if (!strncmp(line + 7, "MIN ", 4)) vals = min;
  684. else if (!strncmp(line + 7, "MAX ", 4)) vals = max;
  685. if (!vals)
  686. return AVERROR_INVALIDDATA;
  687. av_sscanf(line + 11, "%f %f %f", vals, vals + 1, vals + 2);
  688. av_log(ctx, AV_LOG_DEBUG, "min: %f %f %f | max: %f %f %f\n",
  689. min[0], min[1], min[2], max[0], max[1], max[2]);
  690. goto try_again;
  691. } else if (!strncmp(line, "TITLE", 5)) {
  692. goto try_again;
  693. }
  694. } while (skip_line(line));
  695. if (av_sscanf(line, "%f %f %f", &vec->r, &vec->g, &vec->b) != 3)
  696. return AVERROR_INVALIDDATA;
  697. }
  698. }
  699. }
  700. break;
  701. }
  702. }
  703. lut3d->scale.r = av_clipf(1. / (max[0] - min[0]), 0.f, 1.f);
  704. lut3d->scale.g = av_clipf(1. / (max[1] - min[1]), 0.f, 1.f);
  705. lut3d->scale.b = av_clipf(1. / (max[2] - min[2]), 0.f, 1.f);
  706. return 0;
  707. }
  708. /* Assume 17x17x17 LUT with a 16-bit depth
  709. * FIXME: it seems there are various 3dl formats */
  710. static int parse_3dl(AVFilterContext *ctx, FILE *f)
  711. {
  712. char line[MAX_LINE_SIZE];
  713. LUT3DContext *lut3d = ctx->priv;
  714. int ret, i, j, k;
  715. const int size = 17;
  716. const int size2 = 17 * 17;
  717. const float scale = 16*16*16;
  718. lut3d->lutsize = size;
  719. ret = allocate_3dlut(ctx, size, 0);
  720. if (ret < 0)
  721. return ret;
  722. NEXT_LINE(skip_line(line));
  723. for (k = 0; k < size; k++) {
  724. for (j = 0; j < size; j++) {
  725. for (i = 0; i < size; i++) {
  726. int r, g, b;
  727. struct rgbvec *vec = &lut3d->lut[k * size2 + j * size + i];
  728. NEXT_LINE(skip_line(line));
  729. if (av_sscanf(line, "%d %d %d", &r, &g, &b) != 3)
  730. return AVERROR_INVALIDDATA;
  731. vec->r = r / scale;
  732. vec->g = g / scale;
  733. vec->b = b / scale;
  734. }
  735. }
  736. }
  737. return 0;
  738. }
  739. /* Pandora format */
  740. static int parse_m3d(AVFilterContext *ctx, FILE *f)
  741. {
  742. LUT3DContext *lut3d = ctx->priv;
  743. float scale;
  744. int ret, i, j, k, size, size2, in = -1, out = -1;
  745. char line[MAX_LINE_SIZE];
  746. uint8_t rgb_map[3] = {0, 1, 2};
  747. while (fgets(line, sizeof(line), f)) {
  748. if (!strncmp(line, "in", 2)) in = strtol(line + 2, NULL, 0);
  749. else if (!strncmp(line, "out", 3)) out = strtol(line + 3, NULL, 0);
  750. else if (!strncmp(line, "values", 6)) {
  751. const char *p = line + 6;
  752. #define SET_COLOR(id) do { \
  753. while (av_isspace(*p)) \
  754. p++; \
  755. switch (*p) { \
  756. case 'r': rgb_map[id] = 0; break; \
  757. case 'g': rgb_map[id] = 1; break; \
  758. case 'b': rgb_map[id] = 2; break; \
  759. } \
  760. while (*p && !av_isspace(*p)) \
  761. p++; \
  762. } while (0)
  763. SET_COLOR(0);
  764. SET_COLOR(1);
  765. SET_COLOR(2);
  766. break;
  767. }
  768. }
  769. if (in == -1 || out == -1) {
  770. av_log(ctx, AV_LOG_ERROR, "in and out must be defined\n");
  771. return AVERROR_INVALIDDATA;
  772. }
  773. if (in < 2 || out < 2 ||
  774. in > MAX_LEVEL*MAX_LEVEL*MAX_LEVEL ||
  775. out > MAX_LEVEL*MAX_LEVEL*MAX_LEVEL) {
  776. av_log(ctx, AV_LOG_ERROR, "invalid in (%d) or out (%d)\n", in, out);
  777. return AVERROR_INVALIDDATA;
  778. }
  779. for (size = 1; size*size*size < in; size++);
  780. lut3d->lutsize = size;
  781. size2 = size * size;
  782. ret = allocate_3dlut(ctx, size, 0);
  783. if (ret < 0)
  784. return ret;
  785. scale = 1. / (out - 1);
  786. for (k = 0; k < size; k++) {
  787. for (j = 0; j < size; j++) {
  788. for (i = 0; i < size; i++) {
  789. struct rgbvec *vec = &lut3d->lut[k * size2 + j * size + i];
  790. float val[3];
  791. NEXT_LINE(0);
  792. if (av_sscanf(line, "%f %f %f", val, val + 1, val + 2) != 3)
  793. return AVERROR_INVALIDDATA;
  794. vec->r = val[rgb_map[0]] * scale;
  795. vec->g = val[rgb_map[1]] * scale;
  796. vec->b = val[rgb_map[2]] * scale;
  797. }
  798. }
  799. }
  800. return 0;
  801. }
  802. static int nearest_sample_index(float *data, float x, int low, int hi)
  803. {
  804. int mid;
  805. if (x < data[low])
  806. return low;
  807. if (x > data[hi])
  808. return hi;
  809. for (;;) {
  810. av_assert0(x >= data[low]);
  811. av_assert0(x <= data[hi]);
  812. av_assert0((hi-low) > 0);
  813. if (hi - low == 1)
  814. return low;
  815. mid = (low + hi) / 2;
  816. if (x < data[mid])
  817. hi = mid;
  818. else
  819. low = mid;
  820. }
  821. return 0;
  822. }
  823. #define NEXT_FLOAT_OR_GOTO(value, label) \
  824. if (!fget_next_word(line, sizeof(line) ,f)) { \
  825. ret = AVERROR_INVALIDDATA; \
  826. goto label; \
  827. } \
  828. if (av_sscanf(line, "%f", &value) != 1) { \
  829. ret = AVERROR_INVALIDDATA; \
  830. goto label; \
  831. }
  832. static int parse_cinespace(AVFilterContext *ctx, FILE *f)
  833. {
  834. LUT3DContext *lut3d = ctx->priv;
  835. char line[MAX_LINE_SIZE];
  836. float in_min[3] = {0.0, 0.0, 0.0};
  837. float in_max[3] = {1.0, 1.0, 1.0};
  838. float out_min[3] = {0.0, 0.0, 0.0};
  839. float out_max[3] = {1.0, 1.0, 1.0};
  840. int inside_metadata = 0, size, size2;
  841. int prelut = 0;
  842. int ret = 0;
  843. int prelut_sizes[3] = {0, 0, 0};
  844. float *in_prelut[3] = {NULL, NULL, NULL};
  845. float *out_prelut[3] = {NULL, NULL, NULL};
  846. NEXT_LINE_OR_GOTO(skip_line(line), end);
  847. if (strncmp(line, "CSPLUTV100", 10)) {
  848. av_log(ctx, AV_LOG_ERROR, "Not cineSpace LUT format\n");
  849. ret = AVERROR(EINVAL);
  850. goto end;
  851. }
  852. NEXT_LINE_OR_GOTO(skip_line(line), end);
  853. if (strncmp(line, "3D", 2)) {
  854. av_log(ctx, AV_LOG_ERROR, "Not 3D LUT format\n");
  855. ret = AVERROR(EINVAL);
  856. goto end;
  857. }
  858. while (1) {
  859. NEXT_LINE_OR_GOTO(skip_line(line), end);
  860. if (!strncmp(line, "BEGIN METADATA", 14)) {
  861. inside_metadata = 1;
  862. continue;
  863. }
  864. if (!strncmp(line, "END METADATA", 12)) {
  865. inside_metadata = 0;
  866. continue;
  867. }
  868. if (inside_metadata == 0) {
  869. int size_r, size_g, size_b;
  870. for (int i = 0; i < 3; i++) {
  871. int npoints = strtol(line, NULL, 0);
  872. if (npoints > 2) {
  873. float v,last;
  874. if (npoints > PRELUT_SIZE) {
  875. av_log(ctx, AV_LOG_ERROR, "Prelut size too large.\n");
  876. ret = AVERROR_INVALIDDATA;
  877. goto end;
  878. }
  879. if (in_prelut[i] || out_prelut[i]) {
  880. av_log(ctx, AV_LOG_ERROR, "Invalid file has multiple preluts.\n");
  881. ret = AVERROR_INVALIDDATA;
  882. goto end;
  883. }
  884. in_prelut[i] = (float*)av_malloc(npoints * sizeof(float));
  885. out_prelut[i] = (float*)av_malloc(npoints * sizeof(float));
  886. if (!in_prelut[i] || !out_prelut[i]) {
  887. ret = AVERROR(ENOMEM);
  888. goto end;
  889. }
  890. prelut_sizes[i] = npoints;
  891. in_min[i] = FLT_MAX;
  892. in_max[i] = -FLT_MAX;
  893. out_min[i] = FLT_MAX;
  894. out_max[i] = -FLT_MAX;
  895. for (int j = 0; j < npoints; j++) {
  896. NEXT_FLOAT_OR_GOTO(v, end)
  897. in_min[i] = FFMIN(in_min[i], v);
  898. in_max[i] = FFMAX(in_max[i], v);
  899. in_prelut[i][j] = v;
  900. if (j > 0 && v < last) {
  901. av_log(ctx, AV_LOG_ERROR, "Invalid file, non increasing prelut.\n");
  902. ret = AVERROR(ENOMEM);
  903. goto end;
  904. }
  905. last = v;
  906. }
  907. for (int j = 0; j < npoints; j++) {
  908. NEXT_FLOAT_OR_GOTO(v, end)
  909. out_min[i] = FFMIN(out_min[i], v);
  910. out_max[i] = FFMAX(out_max[i], v);
  911. out_prelut[i][j] = v;
  912. }
  913. } else if (npoints == 2) {
  914. NEXT_LINE_OR_GOTO(skip_line(line), end);
  915. if (av_sscanf(line, "%f %f", &in_min[i], &in_max[i]) != 2) {
  916. ret = AVERROR_INVALIDDATA;
  917. goto end;
  918. }
  919. NEXT_LINE_OR_GOTO(skip_line(line), end);
  920. if (av_sscanf(line, "%f %f", &out_min[i], &out_max[i]) != 2) {
  921. ret = AVERROR_INVALIDDATA;
  922. goto end;
  923. }
  924. } else {
  925. av_log(ctx, AV_LOG_ERROR, "Unsupported number of pre-lut points.\n");
  926. ret = AVERROR_PATCHWELCOME;
  927. goto end;
  928. }
  929. NEXT_LINE_OR_GOTO(skip_line(line), end);
  930. }
  931. if (av_sscanf(line, "%d %d %d", &size_r, &size_g, &size_b) != 3) {
  932. ret = AVERROR(EINVAL);
  933. goto end;
  934. }
  935. if (size_r != size_g || size_r != size_b) {
  936. av_log(ctx, AV_LOG_ERROR, "Unsupported size combination: %dx%dx%d.\n", size_r, size_g, size_b);
  937. ret = AVERROR_PATCHWELCOME;
  938. goto end;
  939. }
  940. size = size_r;
  941. size2 = size * size;
  942. if (prelut_sizes[0] && prelut_sizes[1] && prelut_sizes[2])
  943. prelut = 1;
  944. ret = allocate_3dlut(ctx, size, prelut);
  945. if (ret < 0)
  946. return ret;
  947. for (int k = 0; k < size; k++) {
  948. for (int j = 0; j < size; j++) {
  949. for (int i = 0; i < size; i++) {
  950. struct rgbvec *vec = &lut3d->lut[i * size2 + j * size + k];
  951. NEXT_LINE_OR_GOTO(skip_line(line), end);
  952. if (av_sscanf(line, "%f %f %f", &vec->r, &vec->g, &vec->b) != 3) {
  953. ret = AVERROR_INVALIDDATA;
  954. goto end;
  955. }
  956. vec->r *= out_max[0] - out_min[0];
  957. vec->g *= out_max[1] - out_min[1];
  958. vec->b *= out_max[2] - out_min[2];
  959. }
  960. }
  961. }
  962. break;
  963. }
  964. }
  965. if (prelut) {
  966. for (int c = 0; c < 3; c++) {
  967. lut3d->prelut.min[c] = in_min[c];
  968. lut3d->prelut.max[c] = in_max[c];
  969. lut3d->prelut.scale[c] = (1.0f / (float)(in_max[c] - in_min[c])) * (lut3d->prelut.size - 1);
  970. for (int i = 0; i < lut3d->prelut.size; ++i) {
  971. float mix = (float) i / (float)(lut3d->prelut.size - 1);
  972. float x = lerpf(in_min[c], in_max[c], mix), a, b;
  973. int idx = nearest_sample_index(in_prelut[c], x, 0, prelut_sizes[c]-1);
  974. av_assert0(idx + 1 < prelut_sizes[c]);
  975. a = out_prelut[c][idx + 0];
  976. b = out_prelut[c][idx + 1];
  977. mix = x - in_prelut[c][idx];
  978. lut3d->prelut.lut[c][i] = sanitizef(lerpf(a, b, mix));
  979. }
  980. }
  981. lut3d->scale.r = 1.00f;
  982. lut3d->scale.g = 1.00f;
  983. lut3d->scale.b = 1.00f;
  984. } else {
  985. lut3d->scale.r = av_clipf(1. / (in_max[0] - in_min[0]), 0.f, 1.f);
  986. lut3d->scale.g = av_clipf(1. / (in_max[1] - in_min[1]), 0.f, 1.f);
  987. lut3d->scale.b = av_clipf(1. / (in_max[2] - in_min[2]), 0.f, 1.f);
  988. }
  989. end:
  990. for (int c = 0; c < 3; c++) {
  991. av_freep(&in_prelut[c]);
  992. av_freep(&out_prelut[c]);
  993. }
  994. return ret;
  995. }
  996. static int set_identity_matrix(AVFilterContext *ctx, int size)
  997. {
  998. LUT3DContext *lut3d = ctx->priv;
  999. int ret, i, j, k;
  1000. const int size2 = size * size;
  1001. const float c = 1. / (size - 1);
  1002. ret = allocate_3dlut(ctx, size, 0);
  1003. if (ret < 0)
  1004. return ret;
  1005. for (k = 0; k < size; k++) {
  1006. for (j = 0; j < size; j++) {
  1007. for (i = 0; i < size; i++) {
  1008. struct rgbvec *vec = &lut3d->lut[k * size2 + j * size + i];
  1009. vec->r = k * c;
  1010. vec->g = j * c;
  1011. vec->b = i * c;
  1012. }
  1013. }
  1014. }
  1015. return 0;
  1016. }
  1017. static int query_formats(AVFilterContext *ctx)
  1018. {
  1019. static const enum AVPixelFormat pix_fmts[] = {
  1020. AV_PIX_FMT_RGB24, AV_PIX_FMT_BGR24,
  1021. AV_PIX_FMT_RGBA, AV_PIX_FMT_BGRA,
  1022. AV_PIX_FMT_ARGB, AV_PIX_FMT_ABGR,
  1023. AV_PIX_FMT_0RGB, AV_PIX_FMT_0BGR,
  1024. AV_PIX_FMT_RGB0, AV_PIX_FMT_BGR0,
  1025. AV_PIX_FMT_RGB48, AV_PIX_FMT_BGR48,
  1026. AV_PIX_FMT_RGBA64, AV_PIX_FMT_BGRA64,
  1027. AV_PIX_FMT_GBRP, AV_PIX_FMT_GBRAP,
  1028. AV_PIX_FMT_GBRP9,
  1029. AV_PIX_FMT_GBRP10, AV_PIX_FMT_GBRAP10,
  1030. AV_PIX_FMT_GBRP12, AV_PIX_FMT_GBRAP12,
  1031. AV_PIX_FMT_GBRP14,
  1032. AV_PIX_FMT_GBRP16, AV_PIX_FMT_GBRAP16,
  1033. AV_PIX_FMT_GBRPF32, AV_PIX_FMT_GBRAPF32,
  1034. AV_PIX_FMT_NONE
  1035. };
  1036. AVFilterFormats *fmts_list = ff_make_format_list(pix_fmts);
  1037. if (!fmts_list)
  1038. return AVERROR(ENOMEM);
  1039. return ff_set_common_formats(ctx, fmts_list);
  1040. }
  1041. static int config_input(AVFilterLink *inlink)
  1042. {
  1043. int depth, is16bit, isfloat, planar;
  1044. LUT3DContext *lut3d = inlink->dst->priv;
  1045. const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(inlink->format);
  1046. depth = desc->comp[0].depth;
  1047. is16bit = desc->comp[0].depth > 8;
  1048. planar = desc->flags & AV_PIX_FMT_FLAG_PLANAR;
  1049. isfloat = desc->flags & AV_PIX_FMT_FLAG_FLOAT;
  1050. ff_fill_rgba_map(lut3d->rgba_map, inlink->format);
  1051. lut3d->step = av_get_padded_bits_per_pixel(desc) >> (3 + is16bit);
  1052. #define SET_FUNC(name) do { \
  1053. if (planar && !isfloat) { \
  1054. switch (depth) { \
  1055. case 8: lut3d->interp = interp_8_##name##_p8; break; \
  1056. case 9: lut3d->interp = interp_16_##name##_p9; break; \
  1057. case 10: lut3d->interp = interp_16_##name##_p10; break; \
  1058. case 12: lut3d->interp = interp_16_##name##_p12; break; \
  1059. case 14: lut3d->interp = interp_16_##name##_p14; break; \
  1060. case 16: lut3d->interp = interp_16_##name##_p16; break; \
  1061. } \
  1062. } else if (isfloat) { lut3d->interp = interp_##name##_pf32; \
  1063. } else if (is16bit) { lut3d->interp = interp_16_##name; \
  1064. } else { lut3d->interp = interp_8_##name; } \
  1065. } while (0)
  1066. switch (lut3d->interpolation) {
  1067. case INTERPOLATE_NEAREST: SET_FUNC(nearest); break;
  1068. case INTERPOLATE_TRILINEAR: SET_FUNC(trilinear); break;
  1069. case INTERPOLATE_TETRAHEDRAL: SET_FUNC(tetrahedral); break;
  1070. case INTERPOLATE_PYRAMID: SET_FUNC(pyramid); break;
  1071. case INTERPOLATE_PRISM: SET_FUNC(prism); break;
  1072. default:
  1073. av_assert0(0);
  1074. }
  1075. return 0;
  1076. }
  1077. static AVFrame *apply_lut(AVFilterLink *inlink, AVFrame *in)
  1078. {
  1079. AVFilterContext *ctx = inlink->dst;
  1080. LUT3DContext *lut3d = ctx->priv;
  1081. AVFilterLink *outlink = inlink->dst->outputs[0];
  1082. AVFrame *out;
  1083. ThreadData td;
  1084. if (av_frame_is_writable(in)) {
  1085. out = in;
  1086. } else {
  1087. out = ff_get_video_buffer(outlink, outlink->w, outlink->h);
  1088. if (!out) {
  1089. av_frame_free(&in);
  1090. return NULL;
  1091. }
  1092. av_frame_copy_props(out, in);
  1093. }
  1094. td.in = in;
  1095. td.out = out;
  1096. ctx->internal->execute(ctx, lut3d->interp, &td, NULL, FFMIN(outlink->h, ff_filter_get_nb_threads(ctx)));
  1097. if (out != in)
  1098. av_frame_free(&in);
  1099. return out;
  1100. }
  1101. static int filter_frame(AVFilterLink *inlink, AVFrame *in)
  1102. {
  1103. AVFilterLink *outlink = inlink->dst->outputs[0];
  1104. AVFrame *out = apply_lut(inlink, in);
  1105. if (!out)
  1106. return AVERROR(ENOMEM);
  1107. return ff_filter_frame(outlink, out);
  1108. }
  1109. #if CONFIG_LUT3D_FILTER
  1110. static const AVOption lut3d_options[] = {
  1111. { "file", "set 3D LUT file name", OFFSET(file), AV_OPT_TYPE_STRING, {.str=NULL}, .flags = FLAGS },
  1112. COMMON_OPTIONS
  1113. };
  1114. AVFILTER_DEFINE_CLASS(lut3d);
  1115. static av_cold int lut3d_init(AVFilterContext *ctx)
  1116. {
  1117. int ret;
  1118. FILE *f;
  1119. const char *ext;
  1120. LUT3DContext *lut3d = ctx->priv;
  1121. lut3d->scale.r = lut3d->scale.g = lut3d->scale.b = 1.f;
  1122. if (!lut3d->file) {
  1123. return set_identity_matrix(ctx, 32);
  1124. }
  1125. f = av_fopen_utf8(lut3d->file, "r");
  1126. if (!f) {
  1127. ret = AVERROR(errno);
  1128. av_log(ctx, AV_LOG_ERROR, "%s: %s\n", lut3d->file, av_err2str(ret));
  1129. return ret;
  1130. }
  1131. ext = strrchr(lut3d->file, '.');
  1132. if (!ext) {
  1133. av_log(ctx, AV_LOG_ERROR, "Unable to guess the format from the extension\n");
  1134. ret = AVERROR_INVALIDDATA;
  1135. goto end;
  1136. }
  1137. ext++;
  1138. if (!av_strcasecmp(ext, "dat")) {
  1139. ret = parse_dat(ctx, f);
  1140. } else if (!av_strcasecmp(ext, "3dl")) {
  1141. ret = parse_3dl(ctx, f);
  1142. } else if (!av_strcasecmp(ext, "cube")) {
  1143. ret = parse_cube(ctx, f);
  1144. } else if (!av_strcasecmp(ext, "m3d")) {
  1145. ret = parse_m3d(ctx, f);
  1146. } else if (!av_strcasecmp(ext, "csp")) {
  1147. ret = parse_cinespace(ctx, f);
  1148. } else {
  1149. av_log(ctx, AV_LOG_ERROR, "Unrecognized '.%s' file type\n", ext);
  1150. ret = AVERROR(EINVAL);
  1151. }
  1152. if (!ret && !lut3d->lutsize) {
  1153. av_log(ctx, AV_LOG_ERROR, "3D LUT is empty\n");
  1154. ret = AVERROR_INVALIDDATA;
  1155. }
  1156. end:
  1157. fclose(f);
  1158. return ret;
  1159. }
  1160. static av_cold void lut3d_uninit(AVFilterContext *ctx)
  1161. {
  1162. LUT3DContext *lut3d = ctx->priv;
  1163. int i;
  1164. av_freep(&lut3d->lut);
  1165. for (i = 0; i < 3; i++) {
  1166. av_freep(&lut3d->prelut.lut[i]);
  1167. }
  1168. }
  1169. static const AVFilterPad lut3d_inputs[] = {
  1170. {
  1171. .name = "default",
  1172. .type = AVMEDIA_TYPE_VIDEO,
  1173. .filter_frame = filter_frame,
  1174. .config_props = config_input,
  1175. },
  1176. { NULL }
  1177. };
  1178. static const AVFilterPad lut3d_outputs[] = {
  1179. {
  1180. .name = "default",
  1181. .type = AVMEDIA_TYPE_VIDEO,
  1182. },
  1183. { NULL }
  1184. };
  1185. AVFilter ff_vf_lut3d = {
  1186. .name = "lut3d",
  1187. .description = NULL_IF_CONFIG_SMALL("Adjust colors using a 3D LUT."),
  1188. .priv_size = sizeof(LUT3DContext),
  1189. .init = lut3d_init,
  1190. .uninit = lut3d_uninit,
  1191. .query_formats = query_formats,
  1192. .inputs = lut3d_inputs,
  1193. .outputs = lut3d_outputs,
  1194. .priv_class = &lut3d_class,
  1195. .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC | AVFILTER_FLAG_SLICE_THREADS,
  1196. };
  1197. #endif
  1198. #if CONFIG_HALDCLUT_FILTER
  1199. static void update_clut_packed(LUT3DContext *lut3d, const AVFrame *frame)
  1200. {
  1201. const uint8_t *data = frame->data[0];
  1202. const int linesize = frame->linesize[0];
  1203. const int w = lut3d->clut_width;
  1204. const int step = lut3d->clut_step;
  1205. const uint8_t *rgba_map = lut3d->clut_rgba_map;
  1206. const int level = lut3d->lutsize;
  1207. const int level2 = lut3d->lutsize2;
  1208. #define LOAD_CLUT(nbits) do { \
  1209. int i, j, k, x = 0, y = 0; \
  1210. \
  1211. for (k = 0; k < level; k++) { \
  1212. for (j = 0; j < level; j++) { \
  1213. for (i = 0; i < level; i++) { \
  1214. const uint##nbits##_t *src = (const uint##nbits##_t *) \
  1215. (data + y*linesize + x*step); \
  1216. struct rgbvec *vec = &lut3d->lut[i * level2 + j * level + k]; \
  1217. vec->r = src[rgba_map[0]] / (float)((1<<(nbits)) - 1); \
  1218. vec->g = src[rgba_map[1]] / (float)((1<<(nbits)) - 1); \
  1219. vec->b = src[rgba_map[2]] / (float)((1<<(nbits)) - 1); \
  1220. if (++x == w) { \
  1221. x = 0; \
  1222. y++; \
  1223. } \
  1224. } \
  1225. } \
  1226. } \
  1227. } while (0)
  1228. switch (lut3d->clut_bits) {
  1229. case 8: LOAD_CLUT(8); break;
  1230. case 16: LOAD_CLUT(16); break;
  1231. }
  1232. }
  1233. static void update_clut_planar(LUT3DContext *lut3d, const AVFrame *frame)
  1234. {
  1235. const uint8_t *datag = frame->data[0];
  1236. const uint8_t *datab = frame->data[1];
  1237. const uint8_t *datar = frame->data[2];
  1238. const int glinesize = frame->linesize[0];
  1239. const int blinesize = frame->linesize[1];
  1240. const int rlinesize = frame->linesize[2];
  1241. const int w = lut3d->clut_width;
  1242. const int level = lut3d->lutsize;
  1243. const int level2 = lut3d->lutsize2;
  1244. #define LOAD_CLUT_PLANAR(nbits, depth) do { \
  1245. int i, j, k, x = 0, y = 0; \
  1246. \
  1247. for (k = 0; k < level; k++) { \
  1248. for (j = 0; j < level; j++) { \
  1249. for (i = 0; i < level; i++) { \
  1250. const uint##nbits##_t *gsrc = (const uint##nbits##_t *) \
  1251. (datag + y*glinesize); \
  1252. const uint##nbits##_t *bsrc = (const uint##nbits##_t *) \
  1253. (datab + y*blinesize); \
  1254. const uint##nbits##_t *rsrc = (const uint##nbits##_t *) \
  1255. (datar + y*rlinesize); \
  1256. struct rgbvec *vec = &lut3d->lut[i * level2 + j * level + k]; \
  1257. vec->r = gsrc[x] / (float)((1<<(depth)) - 1); \
  1258. vec->g = bsrc[x] / (float)((1<<(depth)) - 1); \
  1259. vec->b = rsrc[x] / (float)((1<<(depth)) - 1); \
  1260. if (++x == w) { \
  1261. x = 0; \
  1262. y++; \
  1263. } \
  1264. } \
  1265. } \
  1266. } \
  1267. } while (0)
  1268. switch (lut3d->clut_bits) {
  1269. case 8: LOAD_CLUT_PLANAR(8, 8); break;
  1270. case 9: LOAD_CLUT_PLANAR(16, 9); break;
  1271. case 10: LOAD_CLUT_PLANAR(16, 10); break;
  1272. case 12: LOAD_CLUT_PLANAR(16, 12); break;
  1273. case 14: LOAD_CLUT_PLANAR(16, 14); break;
  1274. case 16: LOAD_CLUT_PLANAR(16, 16); break;
  1275. }
  1276. }
  1277. static void update_clut_float(LUT3DContext *lut3d, const AVFrame *frame)
  1278. {
  1279. const uint8_t *datag = frame->data[0];
  1280. const uint8_t *datab = frame->data[1];
  1281. const uint8_t *datar = frame->data[2];
  1282. const int glinesize = frame->linesize[0];
  1283. const int blinesize = frame->linesize[1];
  1284. const int rlinesize = frame->linesize[2];
  1285. const int w = lut3d->clut_width;
  1286. const int level = lut3d->lutsize;
  1287. const int level2 = lut3d->lutsize2;
  1288. int i, j, k, x = 0, y = 0;
  1289. for (k = 0; k < level; k++) {
  1290. for (j = 0; j < level; j++) {
  1291. for (i = 0; i < level; i++) {
  1292. const float *gsrc = (const float *)(datag + y*glinesize);
  1293. const float *bsrc = (const float *)(datab + y*blinesize);
  1294. const float *rsrc = (const float *)(datar + y*rlinesize);
  1295. struct rgbvec *vec = &lut3d->lut[i * level2 + j * level + k];
  1296. vec->r = rsrc[x];
  1297. vec->g = gsrc[x];
  1298. vec->b = bsrc[x];
  1299. if (++x == w) {
  1300. x = 0;
  1301. y++;
  1302. }
  1303. }
  1304. }
  1305. }
  1306. }
  1307. static int config_output(AVFilterLink *outlink)
  1308. {
  1309. AVFilterContext *ctx = outlink->src;
  1310. LUT3DContext *lut3d = ctx->priv;
  1311. int ret;
  1312. ret = ff_framesync_init_dualinput(&lut3d->fs, ctx);
  1313. if (ret < 0)
  1314. return ret;
  1315. outlink->w = ctx->inputs[0]->w;
  1316. outlink->h = ctx->inputs[0]->h;
  1317. outlink->time_base = ctx->inputs[0]->time_base;
  1318. if ((ret = ff_framesync_configure(&lut3d->fs)) < 0)
  1319. return ret;
  1320. return 0;
  1321. }
  1322. static int activate(AVFilterContext *ctx)
  1323. {
  1324. LUT3DContext *s = ctx->priv;
  1325. return ff_framesync_activate(&s->fs);
  1326. }
  1327. static int config_clut(AVFilterLink *inlink)
  1328. {
  1329. int size, level, w, h;
  1330. AVFilterContext *ctx = inlink->dst;
  1331. LUT3DContext *lut3d = ctx->priv;
  1332. const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(inlink->format);
  1333. av_assert0(desc);
  1334. lut3d->clut_bits = desc->comp[0].depth;
  1335. lut3d->clut_planar = av_pix_fmt_count_planes(inlink->format) > 1;
  1336. lut3d->clut_float = desc->flags & AV_PIX_FMT_FLAG_FLOAT;
  1337. lut3d->clut_step = av_get_padded_bits_per_pixel(desc) >> 3;
  1338. ff_fill_rgba_map(lut3d->clut_rgba_map, inlink->format);
  1339. if (inlink->w > inlink->h)
  1340. av_log(ctx, AV_LOG_INFO, "Padding on the right (%dpx) of the "
  1341. "Hald CLUT will be ignored\n", inlink->w - inlink->h);
  1342. else if (inlink->w < inlink->h)
  1343. av_log(ctx, AV_LOG_INFO, "Padding at the bottom (%dpx) of the "
  1344. "Hald CLUT will be ignored\n", inlink->h - inlink->w);
  1345. lut3d->clut_width = w = h = FFMIN(inlink->w, inlink->h);
  1346. for (level = 1; level*level*level < w; level++);
  1347. size = level*level*level;
  1348. if (size != w) {
  1349. av_log(ctx, AV_LOG_WARNING, "The Hald CLUT width does not match the level\n");
  1350. return AVERROR_INVALIDDATA;
  1351. }
  1352. av_assert0(w == h && w == size);
  1353. level *= level;
  1354. if (level > MAX_LEVEL) {
  1355. const int max_clut_level = sqrt(MAX_LEVEL);
  1356. const int max_clut_size = max_clut_level*max_clut_level*max_clut_level;
  1357. av_log(ctx, AV_LOG_ERROR, "Too large Hald CLUT "
  1358. "(maximum level is %d, or %dx%d CLUT)\n",
  1359. max_clut_level, max_clut_size, max_clut_size);
  1360. return AVERROR(EINVAL);
  1361. }
  1362. return allocate_3dlut(ctx, level, 0);
  1363. }
  1364. static int update_apply_clut(FFFrameSync *fs)
  1365. {
  1366. AVFilterContext *ctx = fs->parent;
  1367. LUT3DContext *lut3d = ctx->priv;
  1368. AVFilterLink *inlink = ctx->inputs[0];
  1369. AVFrame *master, *second, *out;
  1370. int ret;
  1371. ret = ff_framesync_dualinput_get(fs, &master, &second);
  1372. if (ret < 0)
  1373. return ret;
  1374. if (!second)
  1375. return ff_filter_frame(ctx->outputs[0], master);
  1376. if (lut3d->clut_float)
  1377. update_clut_float(ctx->priv, second);
  1378. else if (lut3d->clut_planar)
  1379. update_clut_planar(ctx->priv, second);
  1380. else
  1381. update_clut_packed(ctx->priv, second);
  1382. out = apply_lut(inlink, master);
  1383. return ff_filter_frame(ctx->outputs[0], out);
  1384. }
  1385. static av_cold int haldclut_init(AVFilterContext *ctx)
  1386. {
  1387. LUT3DContext *lut3d = ctx->priv;
  1388. lut3d->scale.r = lut3d->scale.g = lut3d->scale.b = 1.f;
  1389. lut3d->fs.on_event = update_apply_clut;
  1390. return 0;
  1391. }
  1392. static av_cold void haldclut_uninit(AVFilterContext *ctx)
  1393. {
  1394. LUT3DContext *lut3d = ctx->priv;
  1395. ff_framesync_uninit(&lut3d->fs);
  1396. av_freep(&lut3d->lut);
  1397. }
  1398. static const AVOption haldclut_options[] = {
  1399. COMMON_OPTIONS
  1400. };
  1401. FRAMESYNC_DEFINE_CLASS(haldclut, LUT3DContext, fs);
  1402. static const AVFilterPad haldclut_inputs[] = {
  1403. {
  1404. .name = "main",
  1405. .type = AVMEDIA_TYPE_VIDEO,
  1406. .config_props = config_input,
  1407. },{
  1408. .name = "clut",
  1409. .type = AVMEDIA_TYPE_VIDEO,
  1410. .config_props = config_clut,
  1411. },
  1412. { NULL }
  1413. };
  1414. static const AVFilterPad haldclut_outputs[] = {
  1415. {
  1416. .name = "default",
  1417. .type = AVMEDIA_TYPE_VIDEO,
  1418. .config_props = config_output,
  1419. },
  1420. { NULL }
  1421. };
  1422. AVFilter ff_vf_haldclut = {
  1423. .name = "haldclut",
  1424. .description = NULL_IF_CONFIG_SMALL("Adjust colors using a Hald CLUT."),
  1425. .priv_size = sizeof(LUT3DContext),
  1426. .preinit = haldclut_framesync_preinit,
  1427. .init = haldclut_init,
  1428. .uninit = haldclut_uninit,
  1429. .query_formats = query_formats,
  1430. .activate = activate,
  1431. .inputs = haldclut_inputs,
  1432. .outputs = haldclut_outputs,
  1433. .priv_class = &haldclut_class,
  1434. .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL | AVFILTER_FLAG_SLICE_THREADS,
  1435. };
  1436. #endif
  1437. #if CONFIG_LUT1D_FILTER
  1438. enum interp_1d_mode {
  1439. INTERPOLATE_1D_NEAREST,
  1440. INTERPOLATE_1D_LINEAR,
  1441. INTERPOLATE_1D_CUBIC,
  1442. INTERPOLATE_1D_COSINE,
  1443. INTERPOLATE_1D_SPLINE,
  1444. NB_INTERP_1D_MODE
  1445. };
  1446. #define MAX_1D_LEVEL 65536
  1447. typedef struct LUT1DContext {
  1448. const AVClass *class;
  1449. char *file;
  1450. int interpolation; ///<interp_1d_mode
  1451. struct rgbvec scale;
  1452. uint8_t rgba_map[4];
  1453. int step;
  1454. float lut[3][MAX_1D_LEVEL];
  1455. int lutsize;
  1456. avfilter_action_func *interp;
  1457. } LUT1DContext;
  1458. #undef OFFSET
  1459. #define OFFSET(x) offsetof(LUT1DContext, x)
  1460. static void set_identity_matrix_1d(LUT1DContext *lut1d, int size)
  1461. {
  1462. const float c = 1. / (size - 1);
  1463. int i;
  1464. lut1d->lutsize = size;
  1465. for (i = 0; i < size; i++) {
  1466. lut1d->lut[0][i] = i * c;
  1467. lut1d->lut[1][i] = i * c;
  1468. lut1d->lut[2][i] = i * c;
  1469. }
  1470. }
  1471. static int parse_cinespace_1d(AVFilterContext *ctx, FILE *f)
  1472. {
  1473. LUT1DContext *lut1d = ctx->priv;
  1474. char line[MAX_LINE_SIZE];
  1475. float in_min[3] = {0.0, 0.0, 0.0};
  1476. float in_max[3] = {1.0, 1.0, 1.0};
  1477. float out_min[3] = {0.0, 0.0, 0.0};
  1478. float out_max[3] = {1.0, 1.0, 1.0};
  1479. int inside_metadata = 0, size;
  1480. NEXT_LINE(skip_line(line));
  1481. if (strncmp(line, "CSPLUTV100", 10)) {
  1482. av_log(ctx, AV_LOG_ERROR, "Not cineSpace LUT format\n");
  1483. return AVERROR(EINVAL);
  1484. }
  1485. NEXT_LINE(skip_line(line));
  1486. if (strncmp(line, "1D", 2)) {
  1487. av_log(ctx, AV_LOG_ERROR, "Not 1D LUT format\n");
  1488. return AVERROR(EINVAL);
  1489. }
  1490. while (1) {
  1491. NEXT_LINE(skip_line(line));
  1492. if (!strncmp(line, "BEGIN METADATA", 14)) {
  1493. inside_metadata = 1;
  1494. continue;
  1495. }
  1496. if (!strncmp(line, "END METADATA", 12)) {
  1497. inside_metadata = 0;
  1498. continue;
  1499. }
  1500. if (inside_metadata == 0) {
  1501. for (int i = 0; i < 3; i++) {
  1502. int npoints = strtol(line, NULL, 0);
  1503. if (npoints != 2) {
  1504. av_log(ctx, AV_LOG_ERROR, "Unsupported number of pre-lut points.\n");
  1505. return AVERROR_PATCHWELCOME;
  1506. }
  1507. NEXT_LINE(skip_line(line));
  1508. if (av_sscanf(line, "%f %f", &in_min[i], &in_max[i]) != 2)
  1509. return AVERROR_INVALIDDATA;
  1510. NEXT_LINE(skip_line(line));
  1511. if (av_sscanf(line, "%f %f", &out_min[i], &out_max[i]) != 2)
  1512. return AVERROR_INVALIDDATA;
  1513. NEXT_LINE(skip_line(line));
  1514. }
  1515. size = strtol(line, NULL, 0);
  1516. if (size < 2 || size > MAX_1D_LEVEL) {
  1517. av_log(ctx, AV_LOG_ERROR, "Too large or invalid 1D LUT size\n");
  1518. return AVERROR(EINVAL);
  1519. }
  1520. lut1d->lutsize = size;
  1521. for (int i = 0; i < size; i++) {
  1522. NEXT_LINE(skip_line(line));
  1523. if (av_sscanf(line, "%f %f %f", &lut1d->lut[0][i], &lut1d->lut[1][i], &lut1d->lut[2][i]) != 3)
  1524. return AVERROR_INVALIDDATA;
  1525. lut1d->lut[0][i] *= out_max[0] - out_min[0];
  1526. lut1d->lut[1][i] *= out_max[1] - out_min[1];
  1527. lut1d->lut[2][i] *= out_max[2] - out_min[2];
  1528. }
  1529. break;
  1530. }
  1531. }
  1532. lut1d->scale.r = av_clipf(1. / (in_max[0] - in_min[0]), 0.f, 1.f);
  1533. lut1d->scale.g = av_clipf(1. / (in_max[1] - in_min[1]), 0.f, 1.f);
  1534. lut1d->scale.b = av_clipf(1. / (in_max[2] - in_min[2]), 0.f, 1.f);
  1535. return 0;
  1536. }
  1537. static int parse_cube_1d(AVFilterContext *ctx, FILE *f)
  1538. {
  1539. LUT1DContext *lut1d = ctx->priv;
  1540. char line[MAX_LINE_SIZE];
  1541. float min[3] = {0.0, 0.0, 0.0};
  1542. float max[3] = {1.0, 1.0, 1.0};
  1543. while (fgets(line, sizeof(line), f)) {
  1544. if (!strncmp(line, "LUT_1D_SIZE", 11)) {
  1545. const int size = strtol(line + 12, NULL, 0);
  1546. int i;
  1547. if (size < 2 || size > MAX_1D_LEVEL) {
  1548. av_log(ctx, AV_LOG_ERROR, "Too large or invalid 1D LUT size\n");
  1549. return AVERROR(EINVAL);
  1550. }
  1551. lut1d->lutsize = size;
  1552. for (i = 0; i < size; i++) {
  1553. do {
  1554. try_again:
  1555. NEXT_LINE(0);
  1556. if (!strncmp(line, "DOMAIN_", 7)) {
  1557. float *vals = NULL;
  1558. if (!strncmp(line + 7, "MIN ", 4)) vals = min;
  1559. else if (!strncmp(line + 7, "MAX ", 4)) vals = max;
  1560. if (!vals)
  1561. return AVERROR_INVALIDDATA;
  1562. av_sscanf(line + 11, "%f %f %f", vals, vals + 1, vals + 2);
  1563. av_log(ctx, AV_LOG_DEBUG, "min: %f %f %f | max: %f %f %f\n",
  1564. min[0], min[1], min[2], max[0], max[1], max[2]);
  1565. goto try_again;
  1566. } else if (!strncmp(line, "LUT_1D_INPUT_RANGE ", 19)) {
  1567. av_sscanf(line + 19, "%f %f", min, max);
  1568. min[1] = min[2] = min[0];
  1569. max[1] = max[2] = max[0];
  1570. goto try_again;
  1571. } else if (!strncmp(line, "TITLE", 5)) {
  1572. goto try_again;
  1573. }
  1574. } while (skip_line(line));
  1575. if (av_sscanf(line, "%f %f %f", &lut1d->lut[0][i], &lut1d->lut[1][i], &lut1d->lut[2][i]) != 3)
  1576. return AVERROR_INVALIDDATA;
  1577. }
  1578. break;
  1579. }
  1580. }
  1581. lut1d->scale.r = av_clipf(1. / (max[0] - min[0]), 0.f, 1.f);
  1582. lut1d->scale.g = av_clipf(1. / (max[1] - min[1]), 0.f, 1.f);
  1583. lut1d->scale.b = av_clipf(1. / (max[2] - min[2]), 0.f, 1.f);
  1584. return 0;
  1585. }
  1586. static const AVOption lut1d_options[] = {
  1587. { "file", "set 1D LUT file name", OFFSET(file), AV_OPT_TYPE_STRING, {.str=NULL}, .flags = FLAGS },
  1588. { "interp", "select interpolation mode", OFFSET(interpolation), AV_OPT_TYPE_INT, {.i64=INTERPOLATE_1D_LINEAR}, 0, NB_INTERP_1D_MODE-1, FLAGS, "interp_mode" },
  1589. { "nearest", "use values from the nearest defined points", 0, AV_OPT_TYPE_CONST, {.i64=INTERPOLATE_1D_NEAREST}, INT_MIN, INT_MAX, FLAGS, "interp_mode" },
  1590. { "linear", "use values from the linear interpolation", 0, AV_OPT_TYPE_CONST, {.i64=INTERPOLATE_1D_LINEAR}, INT_MIN, INT_MAX, FLAGS, "interp_mode" },
  1591. { "cosine", "use values from the cosine interpolation", 0, AV_OPT_TYPE_CONST, {.i64=INTERPOLATE_1D_COSINE}, INT_MIN, INT_MAX, FLAGS, "interp_mode" },
  1592. { "cubic", "use values from the cubic interpolation", 0, AV_OPT_TYPE_CONST, {.i64=INTERPOLATE_1D_CUBIC}, INT_MIN, INT_MAX, FLAGS, "interp_mode" },
  1593. { "spline", "use values from the spline interpolation", 0, AV_OPT_TYPE_CONST, {.i64=INTERPOLATE_1D_SPLINE}, INT_MIN, INT_MAX, FLAGS, "interp_mode" },
  1594. { NULL }
  1595. };
  1596. AVFILTER_DEFINE_CLASS(lut1d);
  1597. static inline float interp_1d_nearest(const LUT1DContext *lut1d,
  1598. int idx, const float s)
  1599. {
  1600. return lut1d->lut[idx][NEAR(s)];
  1601. }
  1602. #define NEXT1D(x) (FFMIN((int)(x) + 1, lut1d->lutsize - 1))
  1603. static inline float interp_1d_linear(const LUT1DContext *lut1d,
  1604. int idx, const float s)
  1605. {
  1606. const int prev = PREV(s);
  1607. const int next = NEXT1D(s);
  1608. const float d = s - prev;
  1609. const float p = lut1d->lut[idx][prev];
  1610. const float n = lut1d->lut[idx][next];
  1611. return lerpf(p, n, d);
  1612. }
  1613. static inline float interp_1d_cosine(const LUT1DContext *lut1d,
  1614. int idx, const float s)
  1615. {
  1616. const int prev = PREV(s);
  1617. const int next = NEXT1D(s);
  1618. const float d = s - prev;
  1619. const float p = lut1d->lut[idx][prev];
  1620. const float n = lut1d->lut[idx][next];
  1621. const float m = (1.f - cosf(d * M_PI)) * .5f;
  1622. return lerpf(p, n, m);
  1623. }
  1624. static inline float interp_1d_cubic(const LUT1DContext *lut1d,
  1625. int idx, const float s)
  1626. {
  1627. const int prev = PREV(s);
  1628. const int next = NEXT1D(s);
  1629. const float mu = s - prev;
  1630. float a0, a1, a2, a3, mu2;
  1631. float y0 = lut1d->lut[idx][FFMAX(prev - 1, 0)];
  1632. float y1 = lut1d->lut[idx][prev];
  1633. float y2 = lut1d->lut[idx][next];
  1634. float y3 = lut1d->lut[idx][FFMIN(next + 1, lut1d->lutsize - 1)];
  1635. mu2 = mu * mu;
  1636. a0 = y3 - y2 - y0 + y1;
  1637. a1 = y0 - y1 - a0;
  1638. a2 = y2 - y0;
  1639. a3 = y1;
  1640. return a0 * mu * mu2 + a1 * mu2 + a2 * mu + a3;
  1641. }
  1642. static inline float interp_1d_spline(const LUT1DContext *lut1d,
  1643. int idx, const float s)
  1644. {
  1645. const int prev = PREV(s);
  1646. const int next = NEXT1D(s);
  1647. const float x = s - prev;
  1648. float c0, c1, c2, c3;
  1649. float y0 = lut1d->lut[idx][FFMAX(prev - 1, 0)];
  1650. float y1 = lut1d->lut[idx][prev];
  1651. float y2 = lut1d->lut[idx][next];
  1652. float y3 = lut1d->lut[idx][FFMIN(next + 1, lut1d->lutsize - 1)];
  1653. c0 = y1;
  1654. c1 = .5f * (y2 - y0);
  1655. c2 = y0 - 2.5f * y1 + 2.f * y2 - .5f * y3;
  1656. c3 = .5f * (y3 - y0) + 1.5f * (y1 - y2);
  1657. return ((c3 * x + c2) * x + c1) * x + c0;
  1658. }
  1659. #define DEFINE_INTERP_FUNC_PLANAR_1D(name, nbits, depth) \
  1660. static int interp_1d_##nbits##_##name##_p##depth(AVFilterContext *ctx, \
  1661. void *arg, int jobnr, \
  1662. int nb_jobs) \
  1663. { \
  1664. int x, y; \
  1665. const LUT1DContext *lut1d = ctx->priv; \
  1666. const ThreadData *td = arg; \
  1667. const AVFrame *in = td->in; \
  1668. const AVFrame *out = td->out; \
  1669. const int direct = out == in; \
  1670. const int slice_start = (in->height * jobnr ) / nb_jobs; \
  1671. const int slice_end = (in->height * (jobnr+1)) / nb_jobs; \
  1672. uint8_t *grow = out->data[0] + slice_start * out->linesize[0]; \
  1673. uint8_t *brow = out->data[1] + slice_start * out->linesize[1]; \
  1674. uint8_t *rrow = out->data[2] + slice_start * out->linesize[2]; \
  1675. uint8_t *arow = out->data[3] + slice_start * out->linesize[3]; \
  1676. const uint8_t *srcgrow = in->data[0] + slice_start * in->linesize[0]; \
  1677. const uint8_t *srcbrow = in->data[1] + slice_start * in->linesize[1]; \
  1678. const uint8_t *srcrrow = in->data[2] + slice_start * in->linesize[2]; \
  1679. const uint8_t *srcarow = in->data[3] + slice_start * in->linesize[3]; \
  1680. const float factor = (1 << depth) - 1; \
  1681. const float scale_r = (lut1d->scale.r / factor) * (lut1d->lutsize - 1); \
  1682. const float scale_g = (lut1d->scale.g / factor) * (lut1d->lutsize - 1); \
  1683. const float scale_b = (lut1d->scale.b / factor) * (lut1d->lutsize - 1); \
  1684. \
  1685. for (y = slice_start; y < slice_end; y++) { \
  1686. uint##nbits##_t *dstg = (uint##nbits##_t *)grow; \
  1687. uint##nbits##_t *dstb = (uint##nbits##_t *)brow; \
  1688. uint##nbits##_t *dstr = (uint##nbits##_t *)rrow; \
  1689. uint##nbits##_t *dsta = (uint##nbits##_t *)arow; \
  1690. const uint##nbits##_t *srcg = (const uint##nbits##_t *)srcgrow; \
  1691. const uint##nbits##_t *srcb = (const uint##nbits##_t *)srcbrow; \
  1692. const uint##nbits##_t *srcr = (const uint##nbits##_t *)srcrrow; \
  1693. const uint##nbits##_t *srca = (const uint##nbits##_t *)srcarow; \
  1694. for (x = 0; x < in->width; x++) { \
  1695. float r = srcr[x] * scale_r; \
  1696. float g = srcg[x] * scale_g; \
  1697. float b = srcb[x] * scale_b; \
  1698. r = interp_1d_##name(lut1d, 0, r); \
  1699. g = interp_1d_##name(lut1d, 1, g); \
  1700. b = interp_1d_##name(lut1d, 2, b); \
  1701. dstr[x] = av_clip_uintp2(r * factor, depth); \
  1702. dstg[x] = av_clip_uintp2(g * factor, depth); \
  1703. dstb[x] = av_clip_uintp2(b * factor, depth); \
  1704. if (!direct && in->linesize[3]) \
  1705. dsta[x] = srca[x]; \
  1706. } \
  1707. grow += out->linesize[0]; \
  1708. brow += out->linesize[1]; \
  1709. rrow += out->linesize[2]; \
  1710. arow += out->linesize[3]; \
  1711. srcgrow += in->linesize[0]; \
  1712. srcbrow += in->linesize[1]; \
  1713. srcrrow += in->linesize[2]; \
  1714. srcarow += in->linesize[3]; \
  1715. } \
  1716. return 0; \
  1717. }
  1718. DEFINE_INTERP_FUNC_PLANAR_1D(nearest, 8, 8)
  1719. DEFINE_INTERP_FUNC_PLANAR_1D(linear, 8, 8)
  1720. DEFINE_INTERP_FUNC_PLANAR_1D(cosine, 8, 8)
  1721. DEFINE_INTERP_FUNC_PLANAR_1D(cubic, 8, 8)
  1722. DEFINE_INTERP_FUNC_PLANAR_1D(spline, 8, 8)
  1723. DEFINE_INTERP_FUNC_PLANAR_1D(nearest, 16, 9)
  1724. DEFINE_INTERP_FUNC_PLANAR_1D(linear, 16, 9)
  1725. DEFINE_INTERP_FUNC_PLANAR_1D(cosine, 16, 9)
  1726. DEFINE_INTERP_FUNC_PLANAR_1D(cubic, 16, 9)
  1727. DEFINE_INTERP_FUNC_PLANAR_1D(spline, 16, 9)
  1728. DEFINE_INTERP_FUNC_PLANAR_1D(nearest, 16, 10)
  1729. DEFINE_INTERP_FUNC_PLANAR_1D(linear, 16, 10)
  1730. DEFINE_INTERP_FUNC_PLANAR_1D(cosine, 16, 10)
  1731. DEFINE_INTERP_FUNC_PLANAR_1D(cubic, 16, 10)
  1732. DEFINE_INTERP_FUNC_PLANAR_1D(spline, 16, 10)
  1733. DEFINE_INTERP_FUNC_PLANAR_1D(nearest, 16, 12)
  1734. DEFINE_INTERP_FUNC_PLANAR_1D(linear, 16, 12)
  1735. DEFINE_INTERP_FUNC_PLANAR_1D(cosine, 16, 12)
  1736. DEFINE_INTERP_FUNC_PLANAR_1D(cubic, 16, 12)
  1737. DEFINE_INTERP_FUNC_PLANAR_1D(spline, 16, 12)
  1738. DEFINE_INTERP_FUNC_PLANAR_1D(nearest, 16, 14)
  1739. DEFINE_INTERP_FUNC_PLANAR_1D(linear, 16, 14)
  1740. DEFINE_INTERP_FUNC_PLANAR_1D(cosine, 16, 14)
  1741. DEFINE_INTERP_FUNC_PLANAR_1D(cubic, 16, 14)
  1742. DEFINE_INTERP_FUNC_PLANAR_1D(spline, 16, 14)
  1743. DEFINE_INTERP_FUNC_PLANAR_1D(nearest, 16, 16)
  1744. DEFINE_INTERP_FUNC_PLANAR_1D(linear, 16, 16)
  1745. DEFINE_INTERP_FUNC_PLANAR_1D(cosine, 16, 16)
  1746. DEFINE_INTERP_FUNC_PLANAR_1D(cubic, 16, 16)
  1747. DEFINE_INTERP_FUNC_PLANAR_1D(spline, 16, 16)
  1748. #define DEFINE_INTERP_FUNC_PLANAR_1D_FLOAT(name, depth) \
  1749. static int interp_1d_##name##_pf##depth(AVFilterContext *ctx, \
  1750. void *arg, int jobnr, \
  1751. int nb_jobs) \
  1752. { \
  1753. int x, y; \
  1754. const LUT1DContext *lut1d = ctx->priv; \
  1755. const ThreadData *td = arg; \
  1756. const AVFrame *in = td->in; \
  1757. const AVFrame *out = td->out; \
  1758. const int direct = out == in; \
  1759. const int slice_start = (in->height * jobnr ) / nb_jobs; \
  1760. const int slice_end = (in->height * (jobnr+1)) / nb_jobs; \
  1761. uint8_t *grow = out->data[0] + slice_start * out->linesize[0]; \
  1762. uint8_t *brow = out->data[1] + slice_start * out->linesize[1]; \
  1763. uint8_t *rrow = out->data[2] + slice_start * out->linesize[2]; \
  1764. uint8_t *arow = out->data[3] + slice_start * out->linesize[3]; \
  1765. const uint8_t *srcgrow = in->data[0] + slice_start * in->linesize[0]; \
  1766. const uint8_t *srcbrow = in->data[1] + slice_start * in->linesize[1]; \
  1767. const uint8_t *srcrrow = in->data[2] + slice_start * in->linesize[2]; \
  1768. const uint8_t *srcarow = in->data[3] + slice_start * in->linesize[3]; \
  1769. const float lutsize = lut1d->lutsize - 1; \
  1770. const float scale_r = lut1d->scale.r * lutsize; \
  1771. const float scale_g = lut1d->scale.g * lutsize; \
  1772. const float scale_b = lut1d->scale.b * lutsize; \
  1773. \
  1774. for (y = slice_start; y < slice_end; y++) { \
  1775. float *dstg = (float *)grow; \
  1776. float *dstb = (float *)brow; \
  1777. float *dstr = (float *)rrow; \
  1778. float *dsta = (float *)arow; \
  1779. const float *srcg = (const float *)srcgrow; \
  1780. const float *srcb = (const float *)srcbrow; \
  1781. const float *srcr = (const float *)srcrrow; \
  1782. const float *srca = (const float *)srcarow; \
  1783. for (x = 0; x < in->width; x++) { \
  1784. float r = av_clipf(sanitizef(srcr[x]) * scale_r, 0.0f, lutsize); \
  1785. float g = av_clipf(sanitizef(srcg[x]) * scale_g, 0.0f, lutsize); \
  1786. float b = av_clipf(sanitizef(srcb[x]) * scale_b, 0.0f, lutsize); \
  1787. r = interp_1d_##name(lut1d, 0, r); \
  1788. g = interp_1d_##name(lut1d, 1, g); \
  1789. b = interp_1d_##name(lut1d, 2, b); \
  1790. dstr[x] = r; \
  1791. dstg[x] = g; \
  1792. dstb[x] = b; \
  1793. if (!direct && in->linesize[3]) \
  1794. dsta[x] = srca[x]; \
  1795. } \
  1796. grow += out->linesize[0]; \
  1797. brow += out->linesize[1]; \
  1798. rrow += out->linesize[2]; \
  1799. arow += out->linesize[3]; \
  1800. srcgrow += in->linesize[0]; \
  1801. srcbrow += in->linesize[1]; \
  1802. srcrrow += in->linesize[2]; \
  1803. srcarow += in->linesize[3]; \
  1804. } \
  1805. return 0; \
  1806. }
  1807. DEFINE_INTERP_FUNC_PLANAR_1D_FLOAT(nearest, 32)
  1808. DEFINE_INTERP_FUNC_PLANAR_1D_FLOAT(linear, 32)
  1809. DEFINE_INTERP_FUNC_PLANAR_1D_FLOAT(cosine, 32)
  1810. DEFINE_INTERP_FUNC_PLANAR_1D_FLOAT(cubic, 32)
  1811. DEFINE_INTERP_FUNC_PLANAR_1D_FLOAT(spline, 32)
  1812. #define DEFINE_INTERP_FUNC_1D(name, nbits) \
  1813. static int interp_1d_##nbits##_##name(AVFilterContext *ctx, void *arg, \
  1814. int jobnr, int nb_jobs) \
  1815. { \
  1816. int x, y; \
  1817. const LUT1DContext *lut1d = ctx->priv; \
  1818. const ThreadData *td = arg; \
  1819. const AVFrame *in = td->in; \
  1820. const AVFrame *out = td->out; \
  1821. const int direct = out == in; \
  1822. const int step = lut1d->step; \
  1823. const uint8_t r = lut1d->rgba_map[R]; \
  1824. const uint8_t g = lut1d->rgba_map[G]; \
  1825. const uint8_t b = lut1d->rgba_map[B]; \
  1826. const uint8_t a = lut1d->rgba_map[A]; \
  1827. const int slice_start = (in->height * jobnr ) / nb_jobs; \
  1828. const int slice_end = (in->height * (jobnr+1)) / nb_jobs; \
  1829. uint8_t *dstrow = out->data[0] + slice_start * out->linesize[0]; \
  1830. const uint8_t *srcrow = in ->data[0] + slice_start * in ->linesize[0]; \
  1831. const float factor = (1 << nbits) - 1; \
  1832. const float scale_r = (lut1d->scale.r / factor) * (lut1d->lutsize - 1); \
  1833. const float scale_g = (lut1d->scale.g / factor) * (lut1d->lutsize - 1); \
  1834. const float scale_b = (lut1d->scale.b / factor) * (lut1d->lutsize - 1); \
  1835. \
  1836. for (y = slice_start; y < slice_end; y++) { \
  1837. uint##nbits##_t *dst = (uint##nbits##_t *)dstrow; \
  1838. const uint##nbits##_t *src = (const uint##nbits##_t *)srcrow; \
  1839. for (x = 0; x < in->width * step; x += step) { \
  1840. float rr = src[x + r] * scale_r; \
  1841. float gg = src[x + g] * scale_g; \
  1842. float bb = src[x + b] * scale_b; \
  1843. rr = interp_1d_##name(lut1d, 0, rr); \
  1844. gg = interp_1d_##name(lut1d, 1, gg); \
  1845. bb = interp_1d_##name(lut1d, 2, bb); \
  1846. dst[x + r] = av_clip_uint##nbits(rr * factor); \
  1847. dst[x + g] = av_clip_uint##nbits(gg * factor); \
  1848. dst[x + b] = av_clip_uint##nbits(bb * factor); \
  1849. if (!direct && step == 4) \
  1850. dst[x + a] = src[x + a]; \
  1851. } \
  1852. dstrow += out->linesize[0]; \
  1853. srcrow += in ->linesize[0]; \
  1854. } \
  1855. return 0; \
  1856. }
  1857. DEFINE_INTERP_FUNC_1D(nearest, 8)
  1858. DEFINE_INTERP_FUNC_1D(linear, 8)
  1859. DEFINE_INTERP_FUNC_1D(cosine, 8)
  1860. DEFINE_INTERP_FUNC_1D(cubic, 8)
  1861. DEFINE_INTERP_FUNC_1D(spline, 8)
  1862. DEFINE_INTERP_FUNC_1D(nearest, 16)
  1863. DEFINE_INTERP_FUNC_1D(linear, 16)
  1864. DEFINE_INTERP_FUNC_1D(cosine, 16)
  1865. DEFINE_INTERP_FUNC_1D(cubic, 16)
  1866. DEFINE_INTERP_FUNC_1D(spline, 16)
  1867. static int config_input_1d(AVFilterLink *inlink)
  1868. {
  1869. int depth, is16bit, isfloat, planar;
  1870. LUT1DContext *lut1d = inlink->dst->priv;
  1871. const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(inlink->format);
  1872. depth = desc->comp[0].depth;
  1873. is16bit = desc->comp[0].depth > 8;
  1874. planar = desc->flags & AV_PIX_FMT_FLAG_PLANAR;
  1875. isfloat = desc->flags & AV_PIX_FMT_FLAG_FLOAT;
  1876. ff_fill_rgba_map(lut1d->rgba_map, inlink->format);
  1877. lut1d->step = av_get_padded_bits_per_pixel(desc) >> (3 + is16bit);
  1878. #define SET_FUNC_1D(name) do { \
  1879. if (planar && !isfloat) { \
  1880. switch (depth) { \
  1881. case 8: lut1d->interp = interp_1d_8_##name##_p8; break; \
  1882. case 9: lut1d->interp = interp_1d_16_##name##_p9; break; \
  1883. case 10: lut1d->interp = interp_1d_16_##name##_p10; break; \
  1884. case 12: lut1d->interp = interp_1d_16_##name##_p12; break; \
  1885. case 14: lut1d->interp = interp_1d_16_##name##_p14; break; \
  1886. case 16: lut1d->interp = interp_1d_16_##name##_p16; break; \
  1887. } \
  1888. } else if (isfloat) { lut1d->interp = interp_1d_##name##_pf32; \
  1889. } else if (is16bit) { lut1d->interp = interp_1d_16_##name; \
  1890. } else { lut1d->interp = interp_1d_8_##name; } \
  1891. } while (0)
  1892. switch (lut1d->interpolation) {
  1893. case INTERPOLATE_1D_NEAREST: SET_FUNC_1D(nearest); break;
  1894. case INTERPOLATE_1D_LINEAR: SET_FUNC_1D(linear); break;
  1895. case INTERPOLATE_1D_COSINE: SET_FUNC_1D(cosine); break;
  1896. case INTERPOLATE_1D_CUBIC: SET_FUNC_1D(cubic); break;
  1897. case INTERPOLATE_1D_SPLINE: SET_FUNC_1D(spline); break;
  1898. default:
  1899. av_assert0(0);
  1900. }
  1901. return 0;
  1902. }
  1903. static av_cold int lut1d_init(AVFilterContext *ctx)
  1904. {
  1905. int ret;
  1906. FILE *f;
  1907. const char *ext;
  1908. LUT1DContext *lut1d = ctx->priv;
  1909. lut1d->scale.r = lut1d->scale.g = lut1d->scale.b = 1.f;
  1910. if (!lut1d->file) {
  1911. set_identity_matrix_1d(lut1d, 32);
  1912. return 0;
  1913. }
  1914. f = av_fopen_utf8(lut1d->file, "r");
  1915. if (!f) {
  1916. ret = AVERROR(errno);
  1917. av_log(ctx, AV_LOG_ERROR, "%s: %s\n", lut1d->file, av_err2str(ret));
  1918. return ret;
  1919. }
  1920. ext = strrchr(lut1d->file, '.');
  1921. if (!ext) {
  1922. av_log(ctx, AV_LOG_ERROR, "Unable to guess the format from the extension\n");
  1923. ret = AVERROR_INVALIDDATA;
  1924. goto end;
  1925. }
  1926. ext++;
  1927. if (!av_strcasecmp(ext, "cube") || !av_strcasecmp(ext, "1dlut")) {
  1928. ret = parse_cube_1d(ctx, f);
  1929. } else if (!av_strcasecmp(ext, "csp")) {
  1930. ret = parse_cinespace_1d(ctx, f);
  1931. } else {
  1932. av_log(ctx, AV_LOG_ERROR, "Unrecognized '.%s' file type\n", ext);
  1933. ret = AVERROR(EINVAL);
  1934. }
  1935. if (!ret && !lut1d->lutsize) {
  1936. av_log(ctx, AV_LOG_ERROR, "1D LUT is empty\n");
  1937. ret = AVERROR_INVALIDDATA;
  1938. }
  1939. end:
  1940. fclose(f);
  1941. return ret;
  1942. }
  1943. static AVFrame *apply_1d_lut(AVFilterLink *inlink, AVFrame *in)
  1944. {
  1945. AVFilterContext *ctx = inlink->dst;
  1946. LUT1DContext *lut1d = ctx->priv;
  1947. AVFilterLink *outlink = inlink->dst->outputs[0];
  1948. AVFrame *out;
  1949. ThreadData td;
  1950. if (av_frame_is_writable(in)) {
  1951. out = in;
  1952. } else {
  1953. out = ff_get_video_buffer(outlink, outlink->w, outlink->h);
  1954. if (!out) {
  1955. av_frame_free(&in);
  1956. return NULL;
  1957. }
  1958. av_frame_copy_props(out, in);
  1959. }
  1960. td.in = in;
  1961. td.out = out;
  1962. ctx->internal->execute(ctx, lut1d->interp, &td, NULL, FFMIN(outlink->h, ff_filter_get_nb_threads(ctx)));
  1963. if (out != in)
  1964. av_frame_free(&in);
  1965. return out;
  1966. }
  1967. static int filter_frame_1d(AVFilterLink *inlink, AVFrame *in)
  1968. {
  1969. AVFilterLink *outlink = inlink->dst->outputs[0];
  1970. AVFrame *out = apply_1d_lut(inlink, in);
  1971. if (!out)
  1972. return AVERROR(ENOMEM);
  1973. return ff_filter_frame(outlink, out);
  1974. }
  1975. static const AVFilterPad lut1d_inputs[] = {
  1976. {
  1977. .name = "default",
  1978. .type = AVMEDIA_TYPE_VIDEO,
  1979. .filter_frame = filter_frame_1d,
  1980. .config_props = config_input_1d,
  1981. },
  1982. { NULL }
  1983. };
  1984. static const AVFilterPad lut1d_outputs[] = {
  1985. {
  1986. .name = "default",
  1987. .type = AVMEDIA_TYPE_VIDEO,
  1988. },
  1989. { NULL }
  1990. };
  1991. AVFilter ff_vf_lut1d = {
  1992. .name = "lut1d",
  1993. .description = NULL_IF_CONFIG_SMALL("Adjust colors using a 1D LUT."),
  1994. .priv_size = sizeof(LUT1DContext),
  1995. .init = lut1d_init,
  1996. .query_formats = query_formats,
  1997. .inputs = lut1d_inputs,
  1998. .outputs = lut1d_outputs,
  1999. .priv_class = &lut1d_class,
  2000. .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC | AVFILTER_FLAG_SLICE_THREADS,
  2001. };
  2002. #endif