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.

2301 lines
98KB

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