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.

2150 lines
90KB

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