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.

1693 lines
68KB

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