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.

2148 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 0x80000000
  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_MAX;
  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_MAX;
  787. out_min[i] = FLT_MAX;
  788. out_max[i] = -FLT_MAX;
  789. for (int j = 0; j < npoints; j++) {
  790. NEXT_FLOAT_OR_GOTO(v, end)
  791. in_min[i] = FFMIN(in_min[i], v);
  792. in_max[i] = FFMAX(in_max[i], v);
  793. in_prelut[i][j] = v;
  794. if (j > 0 && v < last) {
  795. av_log(ctx, AV_LOG_ERROR, "Invalid file, non increasing prelut.\n");
  796. ret = AVERROR(ENOMEM);
  797. goto end;
  798. }
  799. last = v;
  800. }
  801. for (int j = 0; j < npoints; j++) {
  802. NEXT_FLOAT_OR_GOTO(v, end)
  803. out_min[i] = FFMIN(out_min[i], v);
  804. out_max[i] = FFMAX(out_max[i], v);
  805. out_prelut[i][j] = v;
  806. }
  807. } else if (npoints == 2) {
  808. NEXT_LINE_OR_GOTO(skip_line(line), end);
  809. if (av_sscanf(line, "%f %f", &in_min[i], &in_max[i]) != 2) {
  810. ret = AVERROR_INVALIDDATA;
  811. goto end;
  812. }
  813. NEXT_LINE_OR_GOTO(skip_line(line), end);
  814. if (av_sscanf(line, "%f %f", &out_min[i], &out_max[i]) != 2) {
  815. ret = AVERROR_INVALIDDATA;
  816. goto end;
  817. }
  818. } else {
  819. av_log(ctx, AV_LOG_ERROR, "Unsupported number of pre-lut points.\n");
  820. ret = AVERROR_PATCHWELCOME;
  821. goto end;
  822. }
  823. NEXT_LINE_OR_GOTO(skip_line(line), end);
  824. }
  825. if (av_sscanf(line, "%d %d %d", &size_r, &size_g, &size_b) != 3) {
  826. ret = AVERROR(EINVAL);
  827. goto end;
  828. }
  829. if (size_r != size_g || size_r != size_b) {
  830. av_log(ctx, AV_LOG_ERROR, "Unsupported size combination: %dx%dx%d.\n", size_r, size_g, size_b);
  831. ret = AVERROR_PATCHWELCOME;
  832. goto end;
  833. }
  834. size = size_r;
  835. size2 = size * size;
  836. if (prelut_sizes[0] && prelut_sizes[1] && prelut_sizes[2])
  837. prelut = 1;
  838. ret = allocate_3dlut(ctx, size, prelut);
  839. if (ret < 0)
  840. return ret;
  841. for (int k = 0; k < size; k++) {
  842. for (int j = 0; j < size; j++) {
  843. for (int i = 0; i < size; i++) {
  844. struct rgbvec *vec = &lut3d->lut[i * size2 + j * size + k];
  845. NEXT_LINE_OR_GOTO(skip_line(line), end);
  846. if (av_sscanf(line, "%f %f %f", &vec->r, &vec->g, &vec->b) != 3) {
  847. ret = AVERROR_INVALIDDATA;
  848. goto end;
  849. }
  850. vec->r *= out_max[0] - out_min[0];
  851. vec->g *= out_max[1] - out_min[1];
  852. vec->b *= out_max[2] - out_min[2];
  853. }
  854. }
  855. }
  856. break;
  857. }
  858. }
  859. if (prelut) {
  860. for (int c = 0; c < 3; c++) {
  861. lut3d->prelut.min[c] = in_min[c];
  862. lut3d->prelut.max[c] = in_max[c];
  863. lut3d->prelut.scale[c] = (1.0f / (float)(in_max[c] - in_min[c])) * (lut3d->prelut.size - 1);
  864. for (int i = 0; i < lut3d->prelut.size; ++i) {
  865. float mix = (float) i / (float)(lut3d->prelut.size - 1);
  866. float x = lerpf(in_min[c], in_max[c], mix), a, b;
  867. int idx = nearest_sample_index(in_prelut[c], x, 0, prelut_sizes[c]-1);
  868. av_assert0(idx + 1 < prelut_sizes[c]);
  869. a = out_prelut[c][idx + 0];
  870. b = out_prelut[c][idx + 1];
  871. mix = x - in_prelut[c][idx];
  872. lut3d->prelut.lut[c][i] = sanitizef(lerpf(a, b, mix));
  873. }
  874. }
  875. lut3d->scale.r = 1.00f;
  876. lut3d->scale.g = 1.00f;
  877. lut3d->scale.b = 1.00f;
  878. } else {
  879. lut3d->scale.r = av_clipf(1. / (in_max[0] - in_min[0]), 0.f, 1.f);
  880. lut3d->scale.g = av_clipf(1. / (in_max[1] - in_min[1]), 0.f, 1.f);
  881. lut3d->scale.b = av_clipf(1. / (in_max[2] - in_min[2]), 0.f, 1.f);
  882. }
  883. end:
  884. for (int c = 0; c < 3; c++) {
  885. av_freep(&in_prelut[c]);
  886. av_freep(&out_prelut[c]);
  887. }
  888. return ret;
  889. }
  890. static int set_identity_matrix(AVFilterContext *ctx, int size)
  891. {
  892. LUT3DContext *lut3d = ctx->priv;
  893. int ret, i, j, k;
  894. const int size2 = size * size;
  895. const float c = 1. / (size - 1);
  896. ret = allocate_3dlut(ctx, size, 0);
  897. if (ret < 0)
  898. return ret;
  899. for (k = 0; k < size; k++) {
  900. for (j = 0; j < size; j++) {
  901. for (i = 0; i < size; i++) {
  902. struct rgbvec *vec = &lut3d->lut[k * size2 + j * size + i];
  903. vec->r = k * c;
  904. vec->g = j * c;
  905. vec->b = i * c;
  906. }
  907. }
  908. }
  909. return 0;
  910. }
  911. static int query_formats(AVFilterContext *ctx)
  912. {
  913. static const enum AVPixelFormat pix_fmts[] = {
  914. AV_PIX_FMT_RGB24, AV_PIX_FMT_BGR24,
  915. AV_PIX_FMT_RGBA, AV_PIX_FMT_BGRA,
  916. AV_PIX_FMT_ARGB, AV_PIX_FMT_ABGR,
  917. AV_PIX_FMT_0RGB, AV_PIX_FMT_0BGR,
  918. AV_PIX_FMT_RGB0, AV_PIX_FMT_BGR0,
  919. AV_PIX_FMT_RGB48, AV_PIX_FMT_BGR48,
  920. AV_PIX_FMT_RGBA64, AV_PIX_FMT_BGRA64,
  921. AV_PIX_FMT_GBRP, AV_PIX_FMT_GBRAP,
  922. AV_PIX_FMT_GBRP9,
  923. AV_PIX_FMT_GBRP10, AV_PIX_FMT_GBRAP10,
  924. AV_PIX_FMT_GBRP12, AV_PIX_FMT_GBRAP12,
  925. AV_PIX_FMT_GBRP14,
  926. AV_PIX_FMT_GBRP16, AV_PIX_FMT_GBRAP16,
  927. AV_PIX_FMT_GBRPF32, AV_PIX_FMT_GBRAPF32,
  928. AV_PIX_FMT_NONE
  929. };
  930. AVFilterFormats *fmts_list = ff_make_format_list(pix_fmts);
  931. if (!fmts_list)
  932. return AVERROR(ENOMEM);
  933. return ff_set_common_formats(ctx, fmts_list);
  934. }
  935. static int config_input(AVFilterLink *inlink)
  936. {
  937. int depth, is16bit, isfloat, planar;
  938. LUT3DContext *lut3d = inlink->dst->priv;
  939. const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(inlink->format);
  940. depth = desc->comp[0].depth;
  941. is16bit = desc->comp[0].depth > 8;
  942. planar = desc->flags & AV_PIX_FMT_FLAG_PLANAR;
  943. isfloat = desc->flags & AV_PIX_FMT_FLAG_FLOAT;
  944. ff_fill_rgba_map(lut3d->rgba_map, inlink->format);
  945. lut3d->step = av_get_padded_bits_per_pixel(desc) >> (3 + is16bit);
  946. #define SET_FUNC(name) do { \
  947. if (planar && !isfloat) { \
  948. switch (depth) { \
  949. case 8: lut3d->interp = interp_8_##name##_p8; break; \
  950. case 9: lut3d->interp = interp_16_##name##_p9; break; \
  951. case 10: lut3d->interp = interp_16_##name##_p10; break; \
  952. case 12: lut3d->interp = interp_16_##name##_p12; break; \
  953. case 14: lut3d->interp = interp_16_##name##_p14; break; \
  954. case 16: lut3d->interp = interp_16_##name##_p16; break; \
  955. } \
  956. } else if (isfloat) { lut3d->interp = interp_##name##_pf32; \
  957. } else if (is16bit) { lut3d->interp = interp_16_##name; \
  958. } else { lut3d->interp = interp_8_##name; } \
  959. } while (0)
  960. switch (lut3d->interpolation) {
  961. case INTERPOLATE_NEAREST: SET_FUNC(nearest); break;
  962. case INTERPOLATE_TRILINEAR: SET_FUNC(trilinear); break;
  963. case INTERPOLATE_TETRAHEDRAL: SET_FUNC(tetrahedral); break;
  964. default:
  965. av_assert0(0);
  966. }
  967. return 0;
  968. }
  969. static AVFrame *apply_lut(AVFilterLink *inlink, AVFrame *in)
  970. {
  971. AVFilterContext *ctx = inlink->dst;
  972. LUT3DContext *lut3d = ctx->priv;
  973. AVFilterLink *outlink = inlink->dst->outputs[0];
  974. AVFrame *out;
  975. ThreadData td;
  976. if (av_frame_is_writable(in)) {
  977. out = in;
  978. } else {
  979. out = ff_get_video_buffer(outlink, outlink->w, outlink->h);
  980. if (!out) {
  981. av_frame_free(&in);
  982. return NULL;
  983. }
  984. av_frame_copy_props(out, in);
  985. }
  986. td.in = in;
  987. td.out = out;
  988. ctx->internal->execute(ctx, lut3d->interp, &td, NULL, FFMIN(outlink->h, ff_filter_get_nb_threads(ctx)));
  989. if (out != in)
  990. av_frame_free(&in);
  991. return out;
  992. }
  993. static int filter_frame(AVFilterLink *inlink, AVFrame *in)
  994. {
  995. AVFilterLink *outlink = inlink->dst->outputs[0];
  996. AVFrame *out = apply_lut(inlink, in);
  997. if (!out)
  998. return AVERROR(ENOMEM);
  999. return ff_filter_frame(outlink, out);
  1000. }
  1001. #if CONFIG_LUT3D_FILTER
  1002. static const AVOption lut3d_options[] = {
  1003. { "file", "set 3D LUT file name", OFFSET(file), AV_OPT_TYPE_STRING, {.str=NULL}, .flags = FLAGS },
  1004. COMMON_OPTIONS
  1005. };
  1006. AVFILTER_DEFINE_CLASS(lut3d);
  1007. static av_cold int lut3d_init(AVFilterContext *ctx)
  1008. {
  1009. int ret;
  1010. FILE *f;
  1011. const char *ext;
  1012. LUT3DContext *lut3d = ctx->priv;
  1013. lut3d->scale.r = lut3d->scale.g = lut3d->scale.b = 1.f;
  1014. if (!lut3d->file) {
  1015. return set_identity_matrix(ctx, 32);
  1016. }
  1017. f = av_fopen_utf8(lut3d->file, "r");
  1018. if (!f) {
  1019. ret = AVERROR(errno);
  1020. av_log(ctx, AV_LOG_ERROR, "%s: %s\n", lut3d->file, av_err2str(ret));
  1021. return ret;
  1022. }
  1023. ext = strrchr(lut3d->file, '.');
  1024. if (!ext) {
  1025. av_log(ctx, AV_LOG_ERROR, "Unable to guess the format from the extension\n");
  1026. ret = AVERROR_INVALIDDATA;
  1027. goto end;
  1028. }
  1029. ext++;
  1030. if (!av_strcasecmp(ext, "dat")) {
  1031. ret = parse_dat(ctx, f);
  1032. } else if (!av_strcasecmp(ext, "3dl")) {
  1033. ret = parse_3dl(ctx, f);
  1034. } else if (!av_strcasecmp(ext, "cube")) {
  1035. ret = parse_cube(ctx, f);
  1036. } else if (!av_strcasecmp(ext, "m3d")) {
  1037. ret = parse_m3d(ctx, f);
  1038. } else if (!av_strcasecmp(ext, "csp")) {
  1039. ret = parse_cinespace(ctx, f);
  1040. } else {
  1041. av_log(ctx, AV_LOG_ERROR, "Unrecognized '.%s' file type\n", ext);
  1042. ret = AVERROR(EINVAL);
  1043. }
  1044. if (!ret && !lut3d->lutsize) {
  1045. av_log(ctx, AV_LOG_ERROR, "3D LUT is empty\n");
  1046. ret = AVERROR_INVALIDDATA;
  1047. }
  1048. end:
  1049. fclose(f);
  1050. return ret;
  1051. }
  1052. static av_cold void lut3d_uninit(AVFilterContext *ctx)
  1053. {
  1054. LUT3DContext *lut3d = ctx->priv;
  1055. int i;
  1056. av_freep(&lut3d->lut);
  1057. for (i = 0; i < 3; i++) {
  1058. av_freep(&lut3d->prelut.lut[i]);
  1059. }
  1060. }
  1061. static const AVFilterPad lut3d_inputs[] = {
  1062. {
  1063. .name = "default",
  1064. .type = AVMEDIA_TYPE_VIDEO,
  1065. .filter_frame = filter_frame,
  1066. .config_props = config_input,
  1067. },
  1068. { NULL }
  1069. };
  1070. static const AVFilterPad lut3d_outputs[] = {
  1071. {
  1072. .name = "default",
  1073. .type = AVMEDIA_TYPE_VIDEO,
  1074. },
  1075. { NULL }
  1076. };
  1077. AVFilter ff_vf_lut3d = {
  1078. .name = "lut3d",
  1079. .description = NULL_IF_CONFIG_SMALL("Adjust colors using a 3D LUT."),
  1080. .priv_size = sizeof(LUT3DContext),
  1081. .init = lut3d_init,
  1082. .uninit = lut3d_uninit,
  1083. .query_formats = query_formats,
  1084. .inputs = lut3d_inputs,
  1085. .outputs = lut3d_outputs,
  1086. .priv_class = &lut3d_class,
  1087. .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC | AVFILTER_FLAG_SLICE_THREADS,
  1088. };
  1089. #endif
  1090. #if CONFIG_HALDCLUT_FILTER
  1091. static void update_clut_packed(LUT3DContext *lut3d, const AVFrame *frame)
  1092. {
  1093. const uint8_t *data = frame->data[0];
  1094. const int linesize = frame->linesize[0];
  1095. const int w = lut3d->clut_width;
  1096. const int step = lut3d->clut_step;
  1097. const uint8_t *rgba_map = lut3d->clut_rgba_map;
  1098. const int level = lut3d->lutsize;
  1099. const int level2 = lut3d->lutsize2;
  1100. #define LOAD_CLUT(nbits) do { \
  1101. int i, j, k, x = 0, y = 0; \
  1102. \
  1103. for (k = 0; k < level; k++) { \
  1104. for (j = 0; j < level; j++) { \
  1105. for (i = 0; i < level; i++) { \
  1106. const uint##nbits##_t *src = (const uint##nbits##_t *) \
  1107. (data + y*linesize + x*step); \
  1108. struct rgbvec *vec = &lut3d->lut[i * level2 + j * level + k]; \
  1109. vec->r = src[rgba_map[0]] / (float)((1<<(nbits)) - 1); \
  1110. vec->g = src[rgba_map[1]] / (float)((1<<(nbits)) - 1); \
  1111. vec->b = src[rgba_map[2]] / (float)((1<<(nbits)) - 1); \
  1112. if (++x == w) { \
  1113. x = 0; \
  1114. y++; \
  1115. } \
  1116. } \
  1117. } \
  1118. } \
  1119. } while (0)
  1120. switch (lut3d->clut_bits) {
  1121. case 8: LOAD_CLUT(8); break;
  1122. case 16: LOAD_CLUT(16); break;
  1123. }
  1124. }
  1125. static void update_clut_planar(LUT3DContext *lut3d, const AVFrame *frame)
  1126. {
  1127. const uint8_t *datag = frame->data[0];
  1128. const uint8_t *datab = frame->data[1];
  1129. const uint8_t *datar = frame->data[2];
  1130. const int glinesize = frame->linesize[0];
  1131. const int blinesize = frame->linesize[1];
  1132. const int rlinesize = frame->linesize[2];
  1133. const int w = lut3d->clut_width;
  1134. const int level = lut3d->lutsize;
  1135. const int level2 = lut3d->lutsize2;
  1136. #define LOAD_CLUT_PLANAR(nbits, depth) do { \
  1137. int i, j, k, x = 0, y = 0; \
  1138. \
  1139. for (k = 0; k < level; k++) { \
  1140. for (j = 0; j < level; j++) { \
  1141. for (i = 0; i < level; i++) { \
  1142. const uint##nbits##_t *gsrc = (const uint##nbits##_t *) \
  1143. (datag + y*glinesize); \
  1144. const uint##nbits##_t *bsrc = (const uint##nbits##_t *) \
  1145. (datab + y*blinesize); \
  1146. const uint##nbits##_t *rsrc = (const uint##nbits##_t *) \
  1147. (datar + y*rlinesize); \
  1148. struct rgbvec *vec = &lut3d->lut[i * level2 + j * level + k]; \
  1149. vec->r = gsrc[x] / (float)((1<<(depth)) - 1); \
  1150. vec->g = bsrc[x] / (float)((1<<(depth)) - 1); \
  1151. vec->b = rsrc[x] / (float)((1<<(depth)) - 1); \
  1152. if (++x == w) { \
  1153. x = 0; \
  1154. y++; \
  1155. } \
  1156. } \
  1157. } \
  1158. } \
  1159. } while (0)
  1160. switch (lut3d->clut_bits) {
  1161. case 8: LOAD_CLUT_PLANAR(8, 8); break;
  1162. case 9: LOAD_CLUT_PLANAR(16, 9); break;
  1163. case 10: LOAD_CLUT_PLANAR(16, 10); break;
  1164. case 12: LOAD_CLUT_PLANAR(16, 12); break;
  1165. case 14: LOAD_CLUT_PLANAR(16, 14); break;
  1166. case 16: LOAD_CLUT_PLANAR(16, 16); break;
  1167. }
  1168. }
  1169. static void update_clut_float(LUT3DContext *lut3d, const AVFrame *frame)
  1170. {
  1171. const uint8_t *datag = frame->data[0];
  1172. const uint8_t *datab = frame->data[1];
  1173. const uint8_t *datar = frame->data[2];
  1174. const int glinesize = frame->linesize[0];
  1175. const int blinesize = frame->linesize[1];
  1176. const int rlinesize = frame->linesize[2];
  1177. const int w = lut3d->clut_width;
  1178. const int level = lut3d->lutsize;
  1179. const int level2 = lut3d->lutsize2;
  1180. int i, j, k, x = 0, y = 0;
  1181. for (k = 0; k < level; k++) {
  1182. for (j = 0; j < level; j++) {
  1183. for (i = 0; i < level; i++) {
  1184. const float *gsrc = (const float *)(datag + y*glinesize);
  1185. const float *bsrc = (const float *)(datab + y*blinesize);
  1186. const float *rsrc = (const float *)(datar + y*rlinesize);
  1187. struct rgbvec *vec = &lut3d->lut[i * level2 + j * level + k];
  1188. vec->r = rsrc[x];
  1189. vec->g = gsrc[x];
  1190. vec->b = bsrc[x];
  1191. if (++x == w) {
  1192. x = 0;
  1193. y++;
  1194. }
  1195. }
  1196. }
  1197. }
  1198. }
  1199. static int config_output(AVFilterLink *outlink)
  1200. {
  1201. AVFilterContext *ctx = outlink->src;
  1202. LUT3DContext *lut3d = ctx->priv;
  1203. int ret;
  1204. ret = ff_framesync_init_dualinput(&lut3d->fs, ctx);
  1205. if (ret < 0)
  1206. return ret;
  1207. outlink->w = ctx->inputs[0]->w;
  1208. outlink->h = ctx->inputs[0]->h;
  1209. outlink->time_base = ctx->inputs[0]->time_base;
  1210. if ((ret = ff_framesync_configure(&lut3d->fs)) < 0)
  1211. return ret;
  1212. return 0;
  1213. }
  1214. static int activate(AVFilterContext *ctx)
  1215. {
  1216. LUT3DContext *s = ctx->priv;
  1217. return ff_framesync_activate(&s->fs);
  1218. }
  1219. static int config_clut(AVFilterLink *inlink)
  1220. {
  1221. int size, level, w, h;
  1222. AVFilterContext *ctx = inlink->dst;
  1223. LUT3DContext *lut3d = ctx->priv;
  1224. const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(inlink->format);
  1225. av_assert0(desc);
  1226. lut3d->clut_bits = desc->comp[0].depth;
  1227. lut3d->clut_planar = av_pix_fmt_count_planes(inlink->format) > 1;
  1228. lut3d->clut_float = desc->flags & AV_PIX_FMT_FLAG_FLOAT;
  1229. lut3d->clut_step = av_get_padded_bits_per_pixel(desc) >> 3;
  1230. ff_fill_rgba_map(lut3d->clut_rgba_map, inlink->format);
  1231. if (inlink->w > inlink->h)
  1232. av_log(ctx, AV_LOG_INFO, "Padding on the right (%dpx) of the "
  1233. "Hald CLUT will be ignored\n", inlink->w - inlink->h);
  1234. else if (inlink->w < inlink->h)
  1235. av_log(ctx, AV_LOG_INFO, "Padding at the bottom (%dpx) of the "
  1236. "Hald CLUT will be ignored\n", inlink->h - inlink->w);
  1237. lut3d->clut_width = w = h = FFMIN(inlink->w, inlink->h);
  1238. for (level = 1; level*level*level < w; level++);
  1239. size = level*level*level;
  1240. if (size != w) {
  1241. av_log(ctx, AV_LOG_WARNING, "The Hald CLUT width does not match the level\n");
  1242. return AVERROR_INVALIDDATA;
  1243. }
  1244. av_assert0(w == h && w == size);
  1245. level *= level;
  1246. if (level > MAX_LEVEL) {
  1247. const int max_clut_level = sqrt(MAX_LEVEL);
  1248. const int max_clut_size = max_clut_level*max_clut_level*max_clut_level;
  1249. av_log(ctx, AV_LOG_ERROR, "Too large Hald CLUT "
  1250. "(maximum level is %d, or %dx%d CLUT)\n",
  1251. max_clut_level, max_clut_size, max_clut_size);
  1252. return AVERROR(EINVAL);
  1253. }
  1254. return allocate_3dlut(ctx, level, 0);
  1255. }
  1256. static int update_apply_clut(FFFrameSync *fs)
  1257. {
  1258. AVFilterContext *ctx = fs->parent;
  1259. LUT3DContext *lut3d = ctx->priv;
  1260. AVFilterLink *inlink = ctx->inputs[0];
  1261. AVFrame *master, *second, *out;
  1262. int ret;
  1263. ret = ff_framesync_dualinput_get(fs, &master, &second);
  1264. if (ret < 0)
  1265. return ret;
  1266. if (!second)
  1267. return ff_filter_frame(ctx->outputs[0], master);
  1268. if (lut3d->clut_float)
  1269. update_clut_float(ctx->priv, second);
  1270. else if (lut3d->clut_planar)
  1271. update_clut_planar(ctx->priv, second);
  1272. else
  1273. update_clut_packed(ctx->priv, second);
  1274. out = apply_lut(inlink, master);
  1275. return ff_filter_frame(ctx->outputs[0], out);
  1276. }
  1277. static av_cold int haldclut_init(AVFilterContext *ctx)
  1278. {
  1279. LUT3DContext *lut3d = ctx->priv;
  1280. lut3d->scale.r = lut3d->scale.g = lut3d->scale.b = 1.f;
  1281. lut3d->fs.on_event = update_apply_clut;
  1282. return 0;
  1283. }
  1284. static av_cold void haldclut_uninit(AVFilterContext *ctx)
  1285. {
  1286. LUT3DContext *lut3d = ctx->priv;
  1287. ff_framesync_uninit(&lut3d->fs);
  1288. av_freep(&lut3d->lut);
  1289. }
  1290. static const AVOption haldclut_options[] = {
  1291. COMMON_OPTIONS
  1292. };
  1293. FRAMESYNC_DEFINE_CLASS(haldclut, LUT3DContext, fs);
  1294. static const AVFilterPad haldclut_inputs[] = {
  1295. {
  1296. .name = "main",
  1297. .type = AVMEDIA_TYPE_VIDEO,
  1298. .config_props = config_input,
  1299. },{
  1300. .name = "clut",
  1301. .type = AVMEDIA_TYPE_VIDEO,
  1302. .config_props = config_clut,
  1303. },
  1304. { NULL }
  1305. };
  1306. static const AVFilterPad haldclut_outputs[] = {
  1307. {
  1308. .name = "default",
  1309. .type = AVMEDIA_TYPE_VIDEO,
  1310. .config_props = config_output,
  1311. },
  1312. { NULL }
  1313. };
  1314. AVFilter ff_vf_haldclut = {
  1315. .name = "haldclut",
  1316. .description = NULL_IF_CONFIG_SMALL("Adjust colors using a Hald CLUT."),
  1317. .priv_size = sizeof(LUT3DContext),
  1318. .preinit = haldclut_framesync_preinit,
  1319. .init = haldclut_init,
  1320. .uninit = haldclut_uninit,
  1321. .query_formats = query_formats,
  1322. .activate = activate,
  1323. .inputs = haldclut_inputs,
  1324. .outputs = haldclut_outputs,
  1325. .priv_class = &haldclut_class,
  1326. .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL | AVFILTER_FLAG_SLICE_THREADS,
  1327. };
  1328. #endif
  1329. #if CONFIG_LUT1D_FILTER
  1330. enum interp_1d_mode {
  1331. INTERPOLATE_1D_NEAREST,
  1332. INTERPOLATE_1D_LINEAR,
  1333. INTERPOLATE_1D_CUBIC,
  1334. INTERPOLATE_1D_COSINE,
  1335. INTERPOLATE_1D_SPLINE,
  1336. NB_INTERP_1D_MODE
  1337. };
  1338. #define MAX_1D_LEVEL 65536
  1339. typedef struct LUT1DContext {
  1340. const AVClass *class;
  1341. char *file;
  1342. int interpolation; ///<interp_1d_mode
  1343. struct rgbvec scale;
  1344. uint8_t rgba_map[4];
  1345. int step;
  1346. float lut[3][MAX_1D_LEVEL];
  1347. int lutsize;
  1348. avfilter_action_func *interp;
  1349. } LUT1DContext;
  1350. #undef OFFSET
  1351. #define OFFSET(x) offsetof(LUT1DContext, x)
  1352. static void set_identity_matrix_1d(LUT1DContext *lut1d, int size)
  1353. {
  1354. const float c = 1. / (size - 1);
  1355. int i;
  1356. lut1d->lutsize = size;
  1357. for (i = 0; i < size; i++) {
  1358. lut1d->lut[0][i] = i * c;
  1359. lut1d->lut[1][i] = i * c;
  1360. lut1d->lut[2][i] = i * c;
  1361. }
  1362. }
  1363. static int parse_cinespace_1d(AVFilterContext *ctx, FILE *f)
  1364. {
  1365. LUT1DContext *lut1d = ctx->priv;
  1366. char line[MAX_LINE_SIZE];
  1367. float in_min[3] = {0.0, 0.0, 0.0};
  1368. float in_max[3] = {1.0, 1.0, 1.0};
  1369. float out_min[3] = {0.0, 0.0, 0.0};
  1370. float out_max[3] = {1.0, 1.0, 1.0};
  1371. int inside_metadata = 0, size;
  1372. NEXT_LINE(skip_line(line));
  1373. if (strncmp(line, "CSPLUTV100", 10)) {
  1374. av_log(ctx, AV_LOG_ERROR, "Not cineSpace LUT format\n");
  1375. return AVERROR(EINVAL);
  1376. }
  1377. NEXT_LINE(skip_line(line));
  1378. if (strncmp(line, "1D", 2)) {
  1379. av_log(ctx, AV_LOG_ERROR, "Not 1D LUT format\n");
  1380. return AVERROR(EINVAL);
  1381. }
  1382. while (1) {
  1383. NEXT_LINE(skip_line(line));
  1384. if (!strncmp(line, "BEGIN METADATA", 14)) {
  1385. inside_metadata = 1;
  1386. continue;
  1387. }
  1388. if (!strncmp(line, "END METADATA", 12)) {
  1389. inside_metadata = 0;
  1390. continue;
  1391. }
  1392. if (inside_metadata == 0) {
  1393. for (int i = 0; i < 3; i++) {
  1394. int npoints = strtol(line, NULL, 0);
  1395. if (npoints != 2) {
  1396. av_log(ctx, AV_LOG_ERROR, "Unsupported number of pre-lut points.\n");
  1397. return AVERROR_PATCHWELCOME;
  1398. }
  1399. NEXT_LINE(skip_line(line));
  1400. if (av_sscanf(line, "%f %f", &in_min[i], &in_max[i]) != 2)
  1401. return AVERROR_INVALIDDATA;
  1402. NEXT_LINE(skip_line(line));
  1403. if (av_sscanf(line, "%f %f", &out_min[i], &out_max[i]) != 2)
  1404. return AVERROR_INVALIDDATA;
  1405. NEXT_LINE(skip_line(line));
  1406. }
  1407. size = strtol(line, NULL, 0);
  1408. if (size < 2 || size > MAX_1D_LEVEL) {
  1409. av_log(ctx, AV_LOG_ERROR, "Too large or invalid 1D LUT size\n");
  1410. return AVERROR(EINVAL);
  1411. }
  1412. lut1d->lutsize = size;
  1413. for (int i = 0; i < size; i++) {
  1414. NEXT_LINE(skip_line(line));
  1415. if (av_sscanf(line, "%f %f %f", &lut1d->lut[0][i], &lut1d->lut[1][i], &lut1d->lut[2][i]) != 3)
  1416. return AVERROR_INVALIDDATA;
  1417. lut1d->lut[0][i] *= out_max[0] - out_min[0];
  1418. lut1d->lut[1][i] *= out_max[1] - out_min[1];
  1419. lut1d->lut[2][i] *= out_max[2] - out_min[2];
  1420. }
  1421. break;
  1422. }
  1423. }
  1424. lut1d->scale.r = av_clipf(1. / (in_max[0] - in_min[0]), 0.f, 1.f);
  1425. lut1d->scale.g = av_clipf(1. / (in_max[1] - in_min[1]), 0.f, 1.f);
  1426. lut1d->scale.b = av_clipf(1. / (in_max[2] - in_min[2]), 0.f, 1.f);
  1427. return 0;
  1428. }
  1429. static int parse_cube_1d(AVFilterContext *ctx, FILE *f)
  1430. {
  1431. LUT1DContext *lut1d = ctx->priv;
  1432. char line[MAX_LINE_SIZE];
  1433. float min[3] = {0.0, 0.0, 0.0};
  1434. float max[3] = {1.0, 1.0, 1.0};
  1435. while (fgets(line, sizeof(line), f)) {
  1436. if (!strncmp(line, "LUT_1D_SIZE", 11)) {
  1437. const int size = strtol(line + 12, NULL, 0);
  1438. int i;
  1439. if (size < 2 || size > MAX_1D_LEVEL) {
  1440. av_log(ctx, AV_LOG_ERROR, "Too large or invalid 1D LUT size\n");
  1441. return AVERROR(EINVAL);
  1442. }
  1443. lut1d->lutsize = size;
  1444. for (i = 0; i < size; i++) {
  1445. do {
  1446. try_again:
  1447. NEXT_LINE(0);
  1448. if (!strncmp(line, "DOMAIN_", 7)) {
  1449. float *vals = NULL;
  1450. if (!strncmp(line + 7, "MIN ", 4)) vals = min;
  1451. else if (!strncmp(line + 7, "MAX ", 4)) vals = max;
  1452. if (!vals)
  1453. return AVERROR_INVALIDDATA;
  1454. av_sscanf(line + 11, "%f %f %f", vals, vals + 1, vals + 2);
  1455. av_log(ctx, AV_LOG_DEBUG, "min: %f %f %f | max: %f %f %f\n",
  1456. min[0], min[1], min[2], max[0], max[1], max[2]);
  1457. goto try_again;
  1458. } else if (!strncmp(line, "LUT_1D_INPUT_RANGE ", 19)) {
  1459. av_sscanf(line + 19, "%f %f", min, max);
  1460. min[1] = min[2] = min[0];
  1461. max[1] = max[2] = max[0];
  1462. goto try_again;
  1463. } else if (!strncmp(line, "TITLE", 5)) {
  1464. goto try_again;
  1465. }
  1466. } while (skip_line(line));
  1467. if (av_sscanf(line, "%f %f %f", &lut1d->lut[0][i], &lut1d->lut[1][i], &lut1d->lut[2][i]) != 3)
  1468. return AVERROR_INVALIDDATA;
  1469. }
  1470. break;
  1471. }
  1472. }
  1473. lut1d->scale.r = av_clipf(1. / (max[0] - min[0]), 0.f, 1.f);
  1474. lut1d->scale.g = av_clipf(1. / (max[1] - min[1]), 0.f, 1.f);
  1475. lut1d->scale.b = av_clipf(1. / (max[2] - min[2]), 0.f, 1.f);
  1476. return 0;
  1477. }
  1478. static const AVOption lut1d_options[] = {
  1479. { "file", "set 1D LUT file name", OFFSET(file), AV_OPT_TYPE_STRING, {.str=NULL}, .flags = FLAGS },
  1480. { "interp", "select interpolation mode", OFFSET(interpolation), AV_OPT_TYPE_INT, {.i64=INTERPOLATE_1D_LINEAR}, 0, NB_INTERP_1D_MODE-1, FLAGS, "interp_mode" },
  1481. { "nearest", "use values from the nearest defined points", 0, AV_OPT_TYPE_CONST, {.i64=INTERPOLATE_1D_NEAREST}, INT_MIN, INT_MAX, FLAGS, "interp_mode" },
  1482. { "linear", "use values from the linear interpolation", 0, AV_OPT_TYPE_CONST, {.i64=INTERPOLATE_1D_LINEAR}, INT_MIN, INT_MAX, FLAGS, "interp_mode" },
  1483. { "cosine", "use values from the cosine interpolation", 0, AV_OPT_TYPE_CONST, {.i64=INTERPOLATE_1D_COSINE}, INT_MIN, INT_MAX, FLAGS, "interp_mode" },
  1484. { "cubic", "use values from the cubic interpolation", 0, AV_OPT_TYPE_CONST, {.i64=INTERPOLATE_1D_CUBIC}, INT_MIN, INT_MAX, FLAGS, "interp_mode" },
  1485. { "spline", "use values from the spline interpolation", 0, AV_OPT_TYPE_CONST, {.i64=INTERPOLATE_1D_SPLINE}, INT_MIN, INT_MAX, FLAGS, "interp_mode" },
  1486. { NULL }
  1487. };
  1488. AVFILTER_DEFINE_CLASS(lut1d);
  1489. static inline float interp_1d_nearest(const LUT1DContext *lut1d,
  1490. int idx, const float s)
  1491. {
  1492. return lut1d->lut[idx][NEAR(s)];
  1493. }
  1494. #define NEXT1D(x) (FFMIN((int)(x) + 1, lut1d->lutsize - 1))
  1495. static inline float interp_1d_linear(const LUT1DContext *lut1d,
  1496. int idx, const float s)
  1497. {
  1498. const int prev = PREV(s);
  1499. const int next = NEXT1D(s);
  1500. const float d = s - prev;
  1501. const float p = lut1d->lut[idx][prev];
  1502. const float n = lut1d->lut[idx][next];
  1503. return lerpf(p, n, d);
  1504. }
  1505. static inline float interp_1d_cosine(const LUT1DContext *lut1d,
  1506. int idx, const float s)
  1507. {
  1508. const int prev = PREV(s);
  1509. const int next = NEXT1D(s);
  1510. const float d = s - prev;
  1511. const float p = lut1d->lut[idx][prev];
  1512. const float n = lut1d->lut[idx][next];
  1513. const float m = (1.f - cosf(d * M_PI)) * .5f;
  1514. return lerpf(p, n, m);
  1515. }
  1516. static inline float interp_1d_cubic(const LUT1DContext *lut1d,
  1517. int idx, const float s)
  1518. {
  1519. const int prev = PREV(s);
  1520. const int next = NEXT1D(s);
  1521. const float mu = s - prev;
  1522. float a0, a1, a2, a3, mu2;
  1523. float y0 = lut1d->lut[idx][FFMAX(prev - 1, 0)];
  1524. float y1 = lut1d->lut[idx][prev];
  1525. float y2 = lut1d->lut[idx][next];
  1526. float y3 = lut1d->lut[idx][FFMIN(next + 1, lut1d->lutsize - 1)];
  1527. mu2 = mu * mu;
  1528. a0 = y3 - y2 - y0 + y1;
  1529. a1 = y0 - y1 - a0;
  1530. a2 = y2 - y0;
  1531. a3 = y1;
  1532. return a0 * mu * mu2 + a1 * mu2 + a2 * mu + a3;
  1533. }
  1534. static inline float interp_1d_spline(const LUT1DContext *lut1d,
  1535. int idx, const float s)
  1536. {
  1537. const int prev = PREV(s);
  1538. const int next = NEXT1D(s);
  1539. const float x = s - prev;
  1540. float c0, c1, c2, c3;
  1541. float y0 = lut1d->lut[idx][FFMAX(prev - 1, 0)];
  1542. float y1 = lut1d->lut[idx][prev];
  1543. float y2 = lut1d->lut[idx][next];
  1544. float y3 = lut1d->lut[idx][FFMIN(next + 1, lut1d->lutsize - 1)];
  1545. c0 = y1;
  1546. c1 = .5f * (y2 - y0);
  1547. c2 = y0 - 2.5f * y1 + 2.f * y2 - .5f * y3;
  1548. c3 = .5f * (y3 - y0) + 1.5f * (y1 - y2);
  1549. return ((c3 * x + c2) * x + c1) * x + c0;
  1550. }
  1551. #define DEFINE_INTERP_FUNC_PLANAR_1D(name, nbits, depth) \
  1552. static int interp_1d_##nbits##_##name##_p##depth(AVFilterContext *ctx, \
  1553. void *arg, int jobnr, \
  1554. int nb_jobs) \
  1555. { \
  1556. int x, y; \
  1557. const LUT1DContext *lut1d = ctx->priv; \
  1558. const ThreadData *td = arg; \
  1559. const AVFrame *in = td->in; \
  1560. const AVFrame *out = td->out; \
  1561. const int direct = out == in; \
  1562. const int slice_start = (in->height * jobnr ) / nb_jobs; \
  1563. const int slice_end = (in->height * (jobnr+1)) / nb_jobs; \
  1564. uint8_t *grow = out->data[0] + slice_start * out->linesize[0]; \
  1565. uint8_t *brow = out->data[1] + slice_start * out->linesize[1]; \
  1566. uint8_t *rrow = out->data[2] + slice_start * out->linesize[2]; \
  1567. uint8_t *arow = out->data[3] + slice_start * out->linesize[3]; \
  1568. const uint8_t *srcgrow = in->data[0] + slice_start * in->linesize[0]; \
  1569. const uint8_t *srcbrow = in->data[1] + slice_start * in->linesize[1]; \
  1570. const uint8_t *srcrrow = in->data[2] + slice_start * in->linesize[2]; \
  1571. const uint8_t *srcarow = in->data[3] + slice_start * in->linesize[3]; \
  1572. const float factor = (1 << depth) - 1; \
  1573. const float scale_r = (lut1d->scale.r / factor) * (lut1d->lutsize - 1); \
  1574. const float scale_g = (lut1d->scale.g / factor) * (lut1d->lutsize - 1); \
  1575. const float scale_b = (lut1d->scale.b / factor) * (lut1d->lutsize - 1); \
  1576. \
  1577. for (y = slice_start; y < slice_end; y++) { \
  1578. uint##nbits##_t *dstg = (uint##nbits##_t *)grow; \
  1579. uint##nbits##_t *dstb = (uint##nbits##_t *)brow; \
  1580. uint##nbits##_t *dstr = (uint##nbits##_t *)rrow; \
  1581. uint##nbits##_t *dsta = (uint##nbits##_t *)arow; \
  1582. const uint##nbits##_t *srcg = (const uint##nbits##_t *)srcgrow; \
  1583. const uint##nbits##_t *srcb = (const uint##nbits##_t *)srcbrow; \
  1584. const uint##nbits##_t *srcr = (const uint##nbits##_t *)srcrrow; \
  1585. const uint##nbits##_t *srca = (const uint##nbits##_t *)srcarow; \
  1586. for (x = 0; x < in->width; x++) { \
  1587. float r = srcr[x] * scale_r; \
  1588. float g = srcg[x] * scale_g; \
  1589. float b = srcb[x] * scale_b; \
  1590. r = interp_1d_##name(lut1d, 0, r); \
  1591. g = interp_1d_##name(lut1d, 1, g); \
  1592. b = interp_1d_##name(lut1d, 2, b); \
  1593. dstr[x] = av_clip_uintp2(r * factor, depth); \
  1594. dstg[x] = av_clip_uintp2(g * factor, depth); \
  1595. dstb[x] = av_clip_uintp2(b * factor, depth); \
  1596. if (!direct && in->linesize[3]) \
  1597. dsta[x] = srca[x]; \
  1598. } \
  1599. grow += out->linesize[0]; \
  1600. brow += out->linesize[1]; \
  1601. rrow += out->linesize[2]; \
  1602. arow += out->linesize[3]; \
  1603. srcgrow += in->linesize[0]; \
  1604. srcbrow += in->linesize[1]; \
  1605. srcrrow += in->linesize[2]; \
  1606. srcarow += in->linesize[3]; \
  1607. } \
  1608. return 0; \
  1609. }
  1610. DEFINE_INTERP_FUNC_PLANAR_1D(nearest, 8, 8)
  1611. DEFINE_INTERP_FUNC_PLANAR_1D(linear, 8, 8)
  1612. DEFINE_INTERP_FUNC_PLANAR_1D(cosine, 8, 8)
  1613. DEFINE_INTERP_FUNC_PLANAR_1D(cubic, 8, 8)
  1614. DEFINE_INTERP_FUNC_PLANAR_1D(spline, 8, 8)
  1615. DEFINE_INTERP_FUNC_PLANAR_1D(nearest, 16, 9)
  1616. DEFINE_INTERP_FUNC_PLANAR_1D(linear, 16, 9)
  1617. DEFINE_INTERP_FUNC_PLANAR_1D(cosine, 16, 9)
  1618. DEFINE_INTERP_FUNC_PLANAR_1D(cubic, 16, 9)
  1619. DEFINE_INTERP_FUNC_PLANAR_1D(spline, 16, 9)
  1620. DEFINE_INTERP_FUNC_PLANAR_1D(nearest, 16, 10)
  1621. DEFINE_INTERP_FUNC_PLANAR_1D(linear, 16, 10)
  1622. DEFINE_INTERP_FUNC_PLANAR_1D(cosine, 16, 10)
  1623. DEFINE_INTERP_FUNC_PLANAR_1D(cubic, 16, 10)
  1624. DEFINE_INTERP_FUNC_PLANAR_1D(spline, 16, 10)
  1625. DEFINE_INTERP_FUNC_PLANAR_1D(nearest, 16, 12)
  1626. DEFINE_INTERP_FUNC_PLANAR_1D(linear, 16, 12)
  1627. DEFINE_INTERP_FUNC_PLANAR_1D(cosine, 16, 12)
  1628. DEFINE_INTERP_FUNC_PLANAR_1D(cubic, 16, 12)
  1629. DEFINE_INTERP_FUNC_PLANAR_1D(spline, 16, 12)
  1630. DEFINE_INTERP_FUNC_PLANAR_1D(nearest, 16, 14)
  1631. DEFINE_INTERP_FUNC_PLANAR_1D(linear, 16, 14)
  1632. DEFINE_INTERP_FUNC_PLANAR_1D(cosine, 16, 14)
  1633. DEFINE_INTERP_FUNC_PLANAR_1D(cubic, 16, 14)
  1634. DEFINE_INTERP_FUNC_PLANAR_1D(spline, 16, 14)
  1635. DEFINE_INTERP_FUNC_PLANAR_1D(nearest, 16, 16)
  1636. DEFINE_INTERP_FUNC_PLANAR_1D(linear, 16, 16)
  1637. DEFINE_INTERP_FUNC_PLANAR_1D(cosine, 16, 16)
  1638. DEFINE_INTERP_FUNC_PLANAR_1D(cubic, 16, 16)
  1639. DEFINE_INTERP_FUNC_PLANAR_1D(spline, 16, 16)
  1640. #define DEFINE_INTERP_FUNC_PLANAR_1D_FLOAT(name, depth) \
  1641. static int interp_1d_##name##_pf##depth(AVFilterContext *ctx, \
  1642. void *arg, int jobnr, \
  1643. int nb_jobs) \
  1644. { \
  1645. int x, y; \
  1646. const LUT1DContext *lut1d = ctx->priv; \
  1647. const ThreadData *td = arg; \
  1648. const AVFrame *in = td->in; \
  1649. const AVFrame *out = td->out; \
  1650. const int direct = out == in; \
  1651. const int slice_start = (in->height * jobnr ) / nb_jobs; \
  1652. const int slice_end = (in->height * (jobnr+1)) / nb_jobs; \
  1653. uint8_t *grow = out->data[0] + slice_start * out->linesize[0]; \
  1654. uint8_t *brow = out->data[1] + slice_start * out->linesize[1]; \
  1655. uint8_t *rrow = out->data[2] + slice_start * out->linesize[2]; \
  1656. uint8_t *arow = out->data[3] + slice_start * out->linesize[3]; \
  1657. const uint8_t *srcgrow = in->data[0] + slice_start * in->linesize[0]; \
  1658. const uint8_t *srcbrow = in->data[1] + slice_start * in->linesize[1]; \
  1659. const uint8_t *srcrrow = in->data[2] + slice_start * in->linesize[2]; \
  1660. const uint8_t *srcarow = in->data[3] + slice_start * in->linesize[3]; \
  1661. const float lutsize = lut1d->lutsize - 1; \
  1662. const float scale_r = lut1d->scale.r * lutsize; \
  1663. const float scale_g = lut1d->scale.g * lutsize; \
  1664. const float scale_b = lut1d->scale.b * lutsize; \
  1665. \
  1666. for (y = slice_start; y < slice_end; y++) { \
  1667. float *dstg = (float *)grow; \
  1668. float *dstb = (float *)brow; \
  1669. float *dstr = (float *)rrow; \
  1670. float *dsta = (float *)arow; \
  1671. const float *srcg = (const float *)srcgrow; \
  1672. const float *srcb = (const float *)srcbrow; \
  1673. const float *srcr = (const float *)srcrrow; \
  1674. const float *srca = (const float *)srcarow; \
  1675. for (x = 0; x < in->width; x++) { \
  1676. float r = av_clipf(sanitizef(srcr[x]) * scale_r, 0.0f, lutsize); \
  1677. float g = av_clipf(sanitizef(srcg[x]) * scale_g, 0.0f, lutsize); \
  1678. float b = av_clipf(sanitizef(srcb[x]) * scale_b, 0.0f, lutsize); \
  1679. r = interp_1d_##name(lut1d, 0, r); \
  1680. g = interp_1d_##name(lut1d, 1, g); \
  1681. b = interp_1d_##name(lut1d, 2, b); \
  1682. dstr[x] = r; \
  1683. dstg[x] = g; \
  1684. dstb[x] = b; \
  1685. if (!direct && in->linesize[3]) \
  1686. dsta[x] = srca[x]; \
  1687. } \
  1688. grow += out->linesize[0]; \
  1689. brow += out->linesize[1]; \
  1690. rrow += out->linesize[2]; \
  1691. arow += out->linesize[3]; \
  1692. srcgrow += in->linesize[0]; \
  1693. srcbrow += in->linesize[1]; \
  1694. srcrrow += in->linesize[2]; \
  1695. srcarow += in->linesize[3]; \
  1696. } \
  1697. return 0; \
  1698. }
  1699. DEFINE_INTERP_FUNC_PLANAR_1D_FLOAT(nearest, 32)
  1700. DEFINE_INTERP_FUNC_PLANAR_1D_FLOAT(linear, 32)
  1701. DEFINE_INTERP_FUNC_PLANAR_1D_FLOAT(cosine, 32)
  1702. DEFINE_INTERP_FUNC_PLANAR_1D_FLOAT(cubic, 32)
  1703. DEFINE_INTERP_FUNC_PLANAR_1D_FLOAT(spline, 32)
  1704. #define DEFINE_INTERP_FUNC_1D(name, nbits) \
  1705. static int interp_1d_##nbits##_##name(AVFilterContext *ctx, void *arg, \
  1706. int jobnr, int nb_jobs) \
  1707. { \
  1708. int x, y; \
  1709. const LUT1DContext *lut1d = ctx->priv; \
  1710. const ThreadData *td = arg; \
  1711. const AVFrame *in = td->in; \
  1712. const AVFrame *out = td->out; \
  1713. const int direct = out == in; \
  1714. const int step = lut1d->step; \
  1715. const uint8_t r = lut1d->rgba_map[R]; \
  1716. const uint8_t g = lut1d->rgba_map[G]; \
  1717. const uint8_t b = lut1d->rgba_map[B]; \
  1718. const uint8_t a = lut1d->rgba_map[A]; \
  1719. const int slice_start = (in->height * jobnr ) / nb_jobs; \
  1720. const int slice_end = (in->height * (jobnr+1)) / nb_jobs; \
  1721. uint8_t *dstrow = out->data[0] + slice_start * out->linesize[0]; \
  1722. const uint8_t *srcrow = in ->data[0] + slice_start * in ->linesize[0]; \
  1723. const float factor = (1 << nbits) - 1; \
  1724. const float scale_r = (lut1d->scale.r / factor) * (lut1d->lutsize - 1); \
  1725. const float scale_g = (lut1d->scale.g / factor) * (lut1d->lutsize - 1); \
  1726. const float scale_b = (lut1d->scale.b / factor) * (lut1d->lutsize - 1); \
  1727. \
  1728. for (y = slice_start; y < slice_end; y++) { \
  1729. uint##nbits##_t *dst = (uint##nbits##_t *)dstrow; \
  1730. const uint##nbits##_t *src = (const uint##nbits##_t *)srcrow; \
  1731. for (x = 0; x < in->width * step; x += step) { \
  1732. float rr = src[x + r] * scale_r; \
  1733. float gg = src[x + g] * scale_g; \
  1734. float bb = src[x + b] * scale_b; \
  1735. rr = interp_1d_##name(lut1d, 0, rr); \
  1736. gg = interp_1d_##name(lut1d, 1, gg); \
  1737. bb = interp_1d_##name(lut1d, 2, bb); \
  1738. dst[x + r] = av_clip_uint##nbits(rr * factor); \
  1739. dst[x + g] = av_clip_uint##nbits(gg * factor); \
  1740. dst[x + b] = av_clip_uint##nbits(bb * factor); \
  1741. if (!direct && step == 4) \
  1742. dst[x + a] = src[x + a]; \
  1743. } \
  1744. dstrow += out->linesize[0]; \
  1745. srcrow += in ->linesize[0]; \
  1746. } \
  1747. return 0; \
  1748. }
  1749. DEFINE_INTERP_FUNC_1D(nearest, 8)
  1750. DEFINE_INTERP_FUNC_1D(linear, 8)
  1751. DEFINE_INTERP_FUNC_1D(cosine, 8)
  1752. DEFINE_INTERP_FUNC_1D(cubic, 8)
  1753. DEFINE_INTERP_FUNC_1D(spline, 8)
  1754. DEFINE_INTERP_FUNC_1D(nearest, 16)
  1755. DEFINE_INTERP_FUNC_1D(linear, 16)
  1756. DEFINE_INTERP_FUNC_1D(cosine, 16)
  1757. DEFINE_INTERP_FUNC_1D(cubic, 16)
  1758. DEFINE_INTERP_FUNC_1D(spline, 16)
  1759. static int config_input_1d(AVFilterLink *inlink)
  1760. {
  1761. int depth, is16bit, isfloat, planar;
  1762. LUT1DContext *lut1d = inlink->dst->priv;
  1763. const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(inlink->format);
  1764. depth = desc->comp[0].depth;
  1765. is16bit = desc->comp[0].depth > 8;
  1766. planar = desc->flags & AV_PIX_FMT_FLAG_PLANAR;
  1767. isfloat = desc->flags & AV_PIX_FMT_FLAG_FLOAT;
  1768. ff_fill_rgba_map(lut1d->rgba_map, inlink->format);
  1769. lut1d->step = av_get_padded_bits_per_pixel(desc) >> (3 + is16bit);
  1770. #define SET_FUNC_1D(name) do { \
  1771. if (planar && !isfloat) { \
  1772. switch (depth) { \
  1773. case 8: lut1d->interp = interp_1d_8_##name##_p8; break; \
  1774. case 9: lut1d->interp = interp_1d_16_##name##_p9; break; \
  1775. case 10: lut1d->interp = interp_1d_16_##name##_p10; break; \
  1776. case 12: lut1d->interp = interp_1d_16_##name##_p12; break; \
  1777. case 14: lut1d->interp = interp_1d_16_##name##_p14; break; \
  1778. case 16: lut1d->interp = interp_1d_16_##name##_p16; break; \
  1779. } \
  1780. } else if (isfloat) { lut1d->interp = interp_1d_##name##_pf32; \
  1781. } else if (is16bit) { lut1d->interp = interp_1d_16_##name; \
  1782. } else { lut1d->interp = interp_1d_8_##name; } \
  1783. } while (0)
  1784. switch (lut1d->interpolation) {
  1785. case INTERPOLATE_1D_NEAREST: SET_FUNC_1D(nearest); break;
  1786. case INTERPOLATE_1D_LINEAR: SET_FUNC_1D(linear); break;
  1787. case INTERPOLATE_1D_COSINE: SET_FUNC_1D(cosine); break;
  1788. case INTERPOLATE_1D_CUBIC: SET_FUNC_1D(cubic); break;
  1789. case INTERPOLATE_1D_SPLINE: SET_FUNC_1D(spline); break;
  1790. default:
  1791. av_assert0(0);
  1792. }
  1793. return 0;
  1794. }
  1795. static av_cold int lut1d_init(AVFilterContext *ctx)
  1796. {
  1797. int ret;
  1798. FILE *f;
  1799. const char *ext;
  1800. LUT1DContext *lut1d = ctx->priv;
  1801. lut1d->scale.r = lut1d->scale.g = lut1d->scale.b = 1.f;
  1802. if (!lut1d->file) {
  1803. set_identity_matrix_1d(lut1d, 32);
  1804. return 0;
  1805. }
  1806. f = av_fopen_utf8(lut1d->file, "r");
  1807. if (!f) {
  1808. ret = AVERROR(errno);
  1809. av_log(ctx, AV_LOG_ERROR, "%s: %s\n", lut1d->file, av_err2str(ret));
  1810. return ret;
  1811. }
  1812. ext = strrchr(lut1d->file, '.');
  1813. if (!ext) {
  1814. av_log(ctx, AV_LOG_ERROR, "Unable to guess the format from the extension\n");
  1815. ret = AVERROR_INVALIDDATA;
  1816. goto end;
  1817. }
  1818. ext++;
  1819. if (!av_strcasecmp(ext, "cube") || !av_strcasecmp(ext, "1dlut")) {
  1820. ret = parse_cube_1d(ctx, f);
  1821. } else if (!av_strcasecmp(ext, "csp")) {
  1822. ret = parse_cinespace_1d(ctx, f);
  1823. } else {
  1824. av_log(ctx, AV_LOG_ERROR, "Unrecognized '.%s' file type\n", ext);
  1825. ret = AVERROR(EINVAL);
  1826. }
  1827. if (!ret && !lut1d->lutsize) {
  1828. av_log(ctx, AV_LOG_ERROR, "1D LUT is empty\n");
  1829. ret = AVERROR_INVALIDDATA;
  1830. }
  1831. end:
  1832. fclose(f);
  1833. return ret;
  1834. }
  1835. static AVFrame *apply_1d_lut(AVFilterLink *inlink, AVFrame *in)
  1836. {
  1837. AVFilterContext *ctx = inlink->dst;
  1838. LUT1DContext *lut1d = ctx->priv;
  1839. AVFilterLink *outlink = inlink->dst->outputs[0];
  1840. AVFrame *out;
  1841. ThreadData td;
  1842. if (av_frame_is_writable(in)) {
  1843. out = in;
  1844. } else {
  1845. out = ff_get_video_buffer(outlink, outlink->w, outlink->h);
  1846. if (!out) {
  1847. av_frame_free(&in);
  1848. return NULL;
  1849. }
  1850. av_frame_copy_props(out, in);
  1851. }
  1852. td.in = in;
  1853. td.out = out;
  1854. ctx->internal->execute(ctx, lut1d->interp, &td, NULL, FFMIN(outlink->h, ff_filter_get_nb_threads(ctx)));
  1855. if (out != in)
  1856. av_frame_free(&in);
  1857. return out;
  1858. }
  1859. static int filter_frame_1d(AVFilterLink *inlink, AVFrame *in)
  1860. {
  1861. AVFilterLink *outlink = inlink->dst->outputs[0];
  1862. AVFrame *out = apply_1d_lut(inlink, in);
  1863. if (!out)
  1864. return AVERROR(ENOMEM);
  1865. return ff_filter_frame(outlink, out);
  1866. }
  1867. static const AVFilterPad lut1d_inputs[] = {
  1868. {
  1869. .name = "default",
  1870. .type = AVMEDIA_TYPE_VIDEO,
  1871. .filter_frame = filter_frame_1d,
  1872. .config_props = config_input_1d,
  1873. },
  1874. { NULL }
  1875. };
  1876. static const AVFilterPad lut1d_outputs[] = {
  1877. {
  1878. .name = "default",
  1879. .type = AVMEDIA_TYPE_VIDEO,
  1880. },
  1881. { NULL }
  1882. };
  1883. AVFilter ff_vf_lut1d = {
  1884. .name = "lut1d",
  1885. .description = NULL_IF_CONFIG_SMALL("Adjust colors using a 1D LUT."),
  1886. .priv_size = sizeof(LUT1DContext),
  1887. .init = lut1d_init,
  1888. .query_formats = query_formats,
  1889. .inputs = lut1d_inputs,
  1890. .outputs = lut1d_outputs,
  1891. .priv_class = &lut1d_class,
  1892. .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC | AVFILTER_FLAG_SLICE_THREADS,
  1893. };
  1894. #endif