Advertisement
Guest User

Untitled

a guest
Jan 25th, 2025
65
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 35.21 KB | None | 0 0
  1. From eb912c0825e80007ed5a704ebf61321b2573ece0 Mon Sep 17 00:00:00 2001
  2. From: Paul B Mahol <[email protected]>
  3. Date: Wed, 22 Jan 2025 20:17:45 +0000
  4. Subject: [PATCH] avfilter: add pf2pf video filter
  5.  
  6. ---
  7. libavfilter/Makefile | 1 +
  8. libavfilter/allfilters.c | 1 +
  9. libavfilter/pf2pf_dst_depth_template.c | 46 +++
  10. libavfilter/pf2pf_dst_endian_template.c | 30 ++
  11. libavfilter/pf2pf_special_template.c | 61 ++++
  12. libavfilter/pf2pf_src_depth_template.c | 36 ++
  13. libavfilter/pf2pf_src_endian_template.c | 30 ++
  14. libavfilter/pf2pf_step_offset_template.c | 47 +++
  15. libavfilter/pf2pf_template.c | 155 +++++++++
  16. libavfilter/vf_pf2pf.c | 409 +++++++++++++++++++++++
  17. libavutil/imgutils.c | 3 +-
  18. 11 files changed, 817 insertions(+), 2 deletions(-)
  19. create mode 100644 libavfilter/pf2pf_dst_depth_template.c
  20. create mode 100644 libavfilter/pf2pf_dst_endian_template.c
  21. create mode 100644 libavfilter/pf2pf_special_template.c
  22. create mode 100644 libavfilter/pf2pf_src_depth_template.c
  23. create mode 100644 libavfilter/pf2pf_src_endian_template.c
  24. create mode 100644 libavfilter/pf2pf_step_offset_template.c
  25. create mode 100644 libavfilter/pf2pf_template.c
  26. create mode 100644 libavfilter/vf_pf2pf.c
  27.  
  28. diff --git a/libavfilter/Makefile b/libavfilter/Makefile
  29. index b9089195f9..4d7bfeef41 100644
  30. --- a/libavfilter/Makefile
  31. +++ b/libavfilter/Makefile
  32. @@ -457,6 +457,7 @@ OBJS-$(CONFIG_PALETTEGEN_FILTER) += vf_palettegen.o palette.o
  33. OBJS-$(CONFIG_PALETTEUSE_FILTER) += vf_paletteuse.o framesync.o palette.o
  34. OBJS-$(CONFIG_PERMS_FILTER) += f_perms.o
  35. OBJS-$(CONFIG_PERSPECTIVE_FILTER) += vf_perspective.o
  36. +OBJS-$(CONFIG_PF2PF_FILTER) += vf_pf2pf.o
  37. OBJS-$(CONFIG_PHASE_FILTER) += vf_phase.o
  38. OBJS-$(CONFIG_PHOTOSENSITIVITY_FILTER) += vf_photosensitivity.o
  39. OBJS-$(CONFIG_PIXDESCTEST_FILTER) += vf_pixdesctest.o
  40. diff --git a/libavfilter/allfilters.c b/libavfilter/allfilters.c
  41. index 3d435bc7a4..3bc6d62396 100644
  42. --- a/libavfilter/allfilters.c
  43. +++ b/libavfilter/allfilters.c
  44. @@ -430,6 +430,7 @@ extern const FFFilter ff_vf_palettegen;
  45. extern const FFFilter ff_vf_paletteuse;
  46. extern const FFFilter ff_vf_perms;
  47. extern const FFFilter ff_vf_perspective;
  48. +extern const FFFilter ff_vf_pf2pf;
  49. extern const FFFilter ff_vf_phase;
  50. extern const FFFilter ff_vf_photosensitivity;
  51. extern const FFFilter ff_vf_pixdesctest;
  52. diff --git a/libavfilter/pf2pf_dst_depth_template.c b/libavfilter/pf2pf_dst_depth_template.c
  53. new file mode 100644
  54. index 0000000000..9359edb193
  55. --- /dev/null
  56. +++ b/libavfilter/pf2pf_dst_depth_template.c
  57. @@ -0,0 +1,46 @@
  58. +/*
  59. + * This file is part of FFmpeg.
  60. + *
  61. + * FFmpeg is free software; you can redistribute it and/or
  62. + * modify it under the terms of the GNU Lesser General Public
  63. + * License as published by the Free Software Foundation; either
  64. + * version 2.1 of the License, or (at your option) any later version.
  65. + *
  66. + * FFmpeg is distributed in the hope that it will be useful,
  67. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  68. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  69. + * Lesser General Public License for more details.
  70. + *
  71. + * You should have received a copy of the GNU Lesser General Public
  72. + * License along with FFmpeg; if not, write to the Free Software
  73. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  74. + */
  75. +
  76. +#include "avfilter.h"
  77. +#include "video.h"
  78. +
  79. +#undef DST_F
  80. +#undef DWP
  81. +#undef DRP
  82. +#if DST_DEPTH == 8
  83. +#define DST_F 0
  84. +#define DWP(x, y) ((x)[0] = (y))
  85. +#define DRP(x) ((x)[0])
  86. +#elif DST_DEPTH == 16
  87. +#define DST_F 1
  88. +#if DST_E == 0
  89. +#define DWP(x, y) AV_WL16((x), (y))
  90. +#define DRP(x) AV_RL16(x)
  91. +#elif DST_E == 1
  92. +#define DWP(x, y) AV_WB16((x), (y))
  93. +#define DRP(x) AV_RB16(x)
  94. +#endif
  95. +#endif
  96. +
  97. +#undef SRC_DEPTH
  98. +#define SRC_DEPTH 8
  99. +#include "pf2pf_src_depth_template.c"
  100. +
  101. +#undef SRC_DEPTH
  102. +#define SRC_DEPTH 16
  103. +#include "pf2pf_src_depth_template.c"
  104. diff --git a/libavfilter/pf2pf_dst_endian_template.c b/libavfilter/pf2pf_dst_endian_template.c
  105. new file mode 100644
  106. index 0000000000..1007ce6a80
  107. --- /dev/null
  108. +++ b/libavfilter/pf2pf_dst_endian_template.c
  109. @@ -0,0 +1,30 @@
  110. +/*
  111. + * This file is part of FFmpeg.
  112. + *
  113. + * FFmpeg is free software; you can redistribute it and/or
  114. + * modify it under the terms of the GNU Lesser General Public
  115. + * License as published by the Free Software Foundation; either
  116. + * version 2.1 of the License, or (at your option) any later version.
  117. + *
  118. + * FFmpeg is distributed in the hope that it will be useful,
  119. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  120. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  121. + * Lesser General Public License for more details.
  122. + *
  123. + * You should have received a copy of the GNU Lesser General Public
  124. + * License along with FFmpeg; if not, write to the Free Software
  125. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  126. + */
  127. +
  128. +#include "avfilter.h"
  129. +#include "video.h"
  130. +
  131. +#undef DST_E
  132. +#define DST_E 0
  133. +#include "pf2pf_src_endian_template.c"
  134. +
  135. +#if DST_DEPTH == 16
  136. +#undef DST_E
  137. +#define DST_E 1
  138. +#include "pf2pf_src_endian_template.c"
  139. +#endif
  140. diff --git a/libavfilter/pf2pf_special_template.c b/libavfilter/pf2pf_special_template.c
  141. new file mode 100644
  142. index 0000000000..8683c8c69d
  143. --- /dev/null
  144. +++ b/libavfilter/pf2pf_special_template.c
  145. @@ -0,0 +1,61 @@
  146. +/*
  147. + * This file is part of FFmpeg.
  148. + *
  149. + * FFmpeg is free software; you can redistribute it and/or
  150. + * modify it under the terms of the GNU Lesser General Public
  151. + * License as published by the Free Software Foundation; either
  152. + * version 2.1 of the License, or (at your option) any later version.
  153. + *
  154. + * FFmpeg is distributed in the hope that it will be useful,
  155. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  156. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  157. + * Lesser General Public License for more details.
  158. + *
  159. + * You should have received a copy of the GNU Lesser General Public
  160. + * License along with FFmpeg; if not, write to the Free Software
  161. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  162. + */
  163. +
  164. +#include "avfilter.h"
  165. +#include "video.h"
  166. +
  167. +#if SRC_DEPTH > 8 || SRC_E == 0
  168. +#define fns3(a,b,c,d,e,f,g) a##_##b##_##c##_##d##_to_##e##_##f##_##g
  169. +#define fns2(a,b,c,d,e,f,g) fns3(a,b,c,d,e,f,g)
  170. +#define fns(a) fns2(a, SRC_F, SRC_E, SRC_OFFSET_NAME, DST_F, DST_E, DST_OFFSET_NAME)
  171. +
  172. +static void fns(pf2pf_special_loop)(uint8_t **dstp,
  173. + const uint8_t **srcp,
  174. + const int *dst_linesizep,
  175. + const int *src_linesizep,
  176. + const int w, const int h,
  177. + const int dst_plane,
  178. + const int dst_shift,
  179. + const int dst_depth,
  180. + const int src_plane,
  181. + const int src_shift,
  182. + const int src_depth)
  183. +{
  184. + const ptrdiff_t dst_linesize = dst_linesizep[dst_plane];
  185. + const ptrdiff_t src_linesize = src_linesizep[src_plane];
  186. + const unsigned dst_mask = (1U << dst_depth) - 1;
  187. + const unsigned src_mask = (1U << src_depth) - 1;
  188. + const unsigned dst_rshift = FFMAX(src_depth - dst_depth, 0);
  189. + const unsigned dst_lshift = dst_shift + FFMAX(dst_depth-src_depth, 0);
  190. + const uint8_t *src = srcp[src_plane];
  191. + uint8_t *dst = dstp[dst_plane];
  192. +
  193. + for (int y = 0; y < h; y++) {
  194. + for (int x = 0, i = 0, j = 0; x < w; x++) {
  195. + unsigned odst = DRP(dst + i + DST_OFFSET);
  196. + DWP(dst + i + DST_OFFSET, odst | (((((SRP(src + j + SRC_OFFSET) >> src_shift) & src_mask) >> dst_rshift) & dst_mask) << dst_lshift));
  197. + i += DST_STEP;
  198. + j += SRC_STEP;
  199. + }
  200. +
  201. + dst += dst_linesize;
  202. + src += src_linesize;
  203. + }
  204. +}
  205. +
  206. +#endif
  207. diff --git a/libavfilter/pf2pf_src_depth_template.c b/libavfilter/pf2pf_src_depth_template.c
  208. new file mode 100644
  209. index 0000000000..bc5598ee7c
  210. --- /dev/null
  211. +++ b/libavfilter/pf2pf_src_depth_template.c
  212. @@ -0,0 +1,36 @@
  213. +/*
  214. + * This file is part of FFmpeg.
  215. + *
  216. + * FFmpeg is free software; you can redistribute it and/or
  217. + * modify it under the terms of the GNU Lesser General Public
  218. + * License as published by the Free Software Foundation; either
  219. + * version 2.1 of the License, or (at your option) any later version.
  220. + *
  221. + * FFmpeg is distributed in the hope that it will be useful,
  222. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  223. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  224. + * Lesser General Public License for more details.
  225. + *
  226. + * You should have received a copy of the GNU Lesser General Public
  227. + * License along with FFmpeg; if not, write to the Free Software
  228. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  229. + */
  230. +
  231. +#include "avfilter.h"
  232. +#include "video.h"
  233. +
  234. +#undef SRC_F
  235. +#undef SRP
  236. +#if SRC_DEPTH == 8
  237. +#define SRC_F 0
  238. +#define SRP(x) ((x)[0])
  239. +#elif SRC_DEPTH == 16
  240. +#define SRC_F 1
  241. +#if SRC_E == 0
  242. +#define SRP(x) AV_RL16((x))
  243. +#elif SRC_E == 1
  244. +#define SRP(x) AV_RB16((x))
  245. +#endif
  246. +#endif
  247. +
  248. +#include "pf2pf_template.c"
  249. diff --git a/libavfilter/pf2pf_src_endian_template.c b/libavfilter/pf2pf_src_endian_template.c
  250. new file mode 100644
  251. index 0000000000..6c3d0d30f5
  252. --- /dev/null
  253. +++ b/libavfilter/pf2pf_src_endian_template.c
  254. @@ -0,0 +1,30 @@
  255. +/*
  256. + * This file is part of FFmpeg.
  257. + *
  258. + * FFmpeg is free software; you can redistribute it and/or
  259. + * modify it under the terms of the GNU Lesser General Public
  260. + * License as published by the Free Software Foundation; either
  261. + * version 2.1 of the License, or (at your option) any later version.
  262. + *
  263. + * FFmpeg is distributed in the hope that it will be useful,
  264. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  265. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  266. + * Lesser General Public License for more details.
  267. + *
  268. + * You should have received a copy of the GNU Lesser General Public
  269. + * License along with FFmpeg; if not, write to the Free Software
  270. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  271. + */
  272. +
  273. +#include "avfilter.h"
  274. +#include "video.h"
  275. +
  276. +#undef SRC_E
  277. +#define SRC_E 0
  278. +#include "pf2pf_dst_depth_template.c"
  279. +
  280. +#if SRC_DEPTH == 16
  281. +#undef SRC_E
  282. +#define SRC_E 1
  283. +#include "pf2pf_dst_depth_template.c"
  284. +#endif
  285. diff --git a/libavfilter/pf2pf_step_offset_template.c b/libavfilter/pf2pf_step_offset_template.c
  286. new file mode 100644
  287. index 0000000000..5d4919f756
  288. --- /dev/null
  289. +++ b/libavfilter/pf2pf_step_offset_template.c
  290. @@ -0,0 +1,47 @@
  291. +/*
  292. + * This file is part of FFmpeg.
  293. + *
  294. + * FFmpeg is free software; you can redistribute it and/or
  295. + * modify it under the terms of the GNU Lesser General Public
  296. + * License as published by the Free Software Foundation; either
  297. + * version 2.1 of the License, or (at your option) any later version.
  298. + *
  299. + * FFmpeg is distributed in the hope that it will be useful,
  300. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  301. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  302. + * Lesser General Public License for more details.
  303. + *
  304. + * You should have received a copy of the GNU Lesser General Public
  305. + * License along with FFmpeg; if not, write to the Free Software
  306. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  307. + */
  308. +
  309. +#include "avfilter.h"
  310. +#include "video.h"
  311. +
  312. +#undef DST_STEP
  313. +#undef DST_OFFSET
  314. +#undef DST_OFFSET_NAME
  315. +
  316. +#define DST_STEP 1
  317. +#define DST_OFFSET 0
  318. +#define DST_OFFSET_NAME 0
  319. +#include "pf2pf_special_template.c"
  320. +
  321. +#undef DST_STEP
  322. +#undef DST_OFFSET
  323. +#undef DST_OFFSET_NAME
  324. +
  325. +#define DST_STEP 2
  326. +#define DST_OFFSET -1
  327. +#define DST_OFFSET_NAME 1
  328. +#include "pf2pf_special_template.c"
  329. +
  330. +#undef DST_STEP
  331. +#undef DST_OFFSET
  332. +#undef DST_OFFSET_NAME
  333. +
  334. +#define DST_STEP 2
  335. +#define DST_OFFSET 0
  336. +#define DST_OFFSET_NAME 2
  337. +#include "pf2pf_special_template.c"
  338. diff --git a/libavfilter/pf2pf_template.c b/libavfilter/pf2pf_template.c
  339. new file mode 100644
  340. index 0000000000..9484135149
  341. --- /dev/null
  342. +++ b/libavfilter/pf2pf_template.c
  343. @@ -0,0 +1,155 @@
  344. +/*
  345. + * This file is part of FFmpeg.
  346. + *
  347. + * FFmpeg is free software; you can redistribute it and/or
  348. + * modify it under the terms of the GNU Lesser General Public
  349. + * License as published by the Free Software Foundation; either
  350. + * version 2.1 of the License, or (at your option) any later version.
  351. + *
  352. + * FFmpeg is distributed in the hope that it will be useful,
  353. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  354. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  355. + * Lesser General Public License for more details.
  356. + *
  357. + * You should have received a copy of the GNU Lesser General Public
  358. + * License along with FFmpeg; if not, write to the Free Software
  359. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  360. + */
  361. +
  362. +#include "avfilter.h"
  363. +#include "video.h"
  364. +
  365. +#if SRC_DEPTH > 8 || SRC_E == 0
  366. +#define fn3(a,b,c,d,e) a##_##b##_##c##_to_##d##_##e
  367. +#define fn2(a,b,c,d,e) fn3(a,b,c,d,e)
  368. +#define fn(a) fn2(a, SRC_F, SRC_E, DST_F, DST_E)
  369. +
  370. +static void fn(pf2pf_loop)(uint8_t **dstp,
  371. + const uint8_t **srcp,
  372. + const int *dst_linesizep,
  373. + const int *src_linesizep,
  374. + const int w, const int h,
  375. + const int dst_plane,
  376. + const int dst_step, const int dst_shift,
  377. + const int dst_offset, const int dst_depth,
  378. + const int src_plane,
  379. + const int src_step, const int src_shift,
  380. + const int src_offset, const int src_depth)
  381. +{
  382. + const ptrdiff_t dst_linesize = dst_linesizep[dst_plane];
  383. + const ptrdiff_t src_linesize = src_linesizep[src_plane];
  384. + const unsigned dst_mask = (1U << dst_depth) - 1;
  385. + const unsigned src_mask = (1U << src_depth) - 1;
  386. + const unsigned dst_rshift = FFMAX(src_depth - dst_depth, 0);
  387. + const unsigned dst_lshift = dst_shift + FFMAX(dst_depth-src_depth, 0);
  388. + const uint8_t *src = srcp[src_plane];
  389. + uint8_t *dst = dstp[dst_plane];
  390. +
  391. + for (int y = 0; y < h; y++) {
  392. + for (int x = 0, i = 0, j = 0; x < w; x++) {
  393. + unsigned odst = DRP(dst + i + dst_offset);
  394. + DWP(dst + i + dst_offset, odst | (((((SRP(src + j + src_offset) >> src_shift) & src_mask) >> dst_rshift) & dst_mask) << dst_lshift));
  395. + i += dst_step;
  396. + j += src_step;
  397. + }
  398. +
  399. + dst += dst_linesize;
  400. + src += src_linesize;
  401. + }
  402. +}
  403. +
  404. +static int fn(pf2pf)(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
  405. +{
  406. + PF2PFContext *s = ctx->priv;
  407. + const int nb_components = s->dst_desc->nb_components;
  408. + const int *linesize = s->linesize;
  409. + ThreadData *td = arg;
  410. + AVFrame *restrict out = td->out;
  411. + AVFrame *restrict in = td->in;
  412. + const int w = in->width;
  413. + const int h = in->height;
  414. + const int start = (h * jobnr) / nb_jobs;
  415. + const int end = (h * (jobnr+1)) / nb_jobs;
  416. +
  417. + for (int comp = 0; comp < nb_components; comp++) {
  418. + if (out->data[comp]) {
  419. + const int dst_sh = (comp > 0) ? s->dst_desc->log2_chroma_h : 0;
  420. + const int cstart = start >> dst_sh;
  421. + const int cend = end >> dst_sh;
  422. + uint8_t *dst_data = out->data[comp] + cstart * out->linesize[comp];
  423. +
  424. + for (int y = cstart; y < cend; y++) {
  425. + memset(dst_data, 0, linesize[comp]);
  426. + dst_data += out->linesize[comp];
  427. + }
  428. + }
  429. + }
  430. +
  431. + for (int comp = 0; comp < nb_components; comp++) {
  432. + const int dst_plane = s->dst_desc->comp[comp].plane;
  433. + const int dst_step = s->dst_desc->comp[comp].step;
  434. + const int dst_shift = s->dst_desc->comp[comp].shift;
  435. + const int dst_offset= s->dst_desc->comp[comp].offset;
  436. + const int dst_depth = s->dst_desc->comp[comp].depth;
  437. + const int src_plane = s->src_desc->comp[comp].plane;
  438. + const int src_step = s->src_desc->comp[comp].step;
  439. + const int src_shift = s->src_desc->comp[comp].shift;
  440. + const int src_offset= s->src_desc->comp[comp].offset;
  441. + const int src_depth = s->src_desc->comp[comp].depth;
  442. + const int dst_sw = (comp > 0) ? s->dst_desc->log2_chroma_w : 0;
  443. + const int dst_sh = (comp > 0) ? s->dst_desc->log2_chroma_h : 0;
  444. + uint8_t *dst_data[4] = {NULL}, *src_data[4] = {NULL};
  445. + const int cstart = start >> dst_sh;
  446. + const int cend = end >> dst_sh;
  447. + const int cw = w >> dst_sw;
  448. +
  449. + for (int i = 0; i < 4; i++) {
  450. + if (out->data[i])
  451. + dst_data[i] = out->data[i] + cstart * out->linesize[i];
  452. + if (in->data[i])
  453. + src_data[i] = in->data[i] + cstart * in->linesize[i];
  454. + }
  455. +
  456. + if (s->fun[comp]) {
  457. + s->fun[comp]((uint8_t **)dst_data, (const uint8_t **)src_data, out->linesize, in->linesize,
  458. + cw, cend - cstart,
  459. + dst_plane, dst_shift, dst_depth,
  460. + src_plane, src_shift, src_depth);
  461. + } else {
  462. + fn(pf2pf_loop)((uint8_t **)dst_data, (const uint8_t **)src_data, out->linesize, in->linesize,
  463. + cw, cend - cstart,
  464. + dst_plane, dst_step, dst_shift, dst_offset, dst_depth,
  465. + src_plane, src_step, src_shift, src_offset, src_depth);
  466. + }
  467. + }
  468. +
  469. + return 0;
  470. +}
  471. +#endif
  472. +
  473. +#undef SRC_STEP
  474. +#undef SRC_OFFSET
  475. +#undef SRC_OFFSET_NAME
  476. +
  477. +#define SRC_STEP 1
  478. +#define SRC_OFFSET 0
  479. +#define SRC_OFFSET_NAME 0
  480. +#include "pf2pf_step_offset_template.c"
  481. +
  482. +#undef SRC_STEP
  483. +#undef SRC_OFFSET
  484. +#undef SRC_OFFSET_NAME
  485. +
  486. +#define SRC_STEP 2
  487. +#define SRC_OFFSET -1
  488. +#define SRC_OFFSET_NAME 1
  489. +#include "pf2pf_step_offset_template.c"
  490. +
  491. +#undef SRC_STEP
  492. +#undef SRC_OFFSET
  493. +#undef SRC_OFFSET_NAME
  494. +
  495. +#define SRC_STEP 2
  496. +#define SRC_OFFSET 0
  497. +#define SRC_OFFSET_NAME 2
  498. +#include "pf2pf_step_offset_template.c"
  499. diff --git a/libavfilter/vf_pf2pf.c b/libavfilter/vf_pf2pf.c
  500. new file mode 100644
  501. index 0000000000..80513a5b5c
  502. --- /dev/null
  503. +++ b/libavfilter/vf_pf2pf.c
  504. @@ -0,0 +1,409 @@
  505. +/*
  506. + * This file is part of FFmpeg.
  507. + *
  508. + * FFmpeg is free software; you can redistribute it and/or
  509. + * modify it under the terms of the GNU Lesser General Public
  510. + * License as published by the Free Software Foundation; either
  511. + * version 2.1 of the License, or (at your option) any later version.
  512. + *
  513. + * FFmpeg is distributed in the hope that it will be useful,
  514. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  515. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  516. + * Lesser General Public License for more details.
  517. + *
  518. + * You should have received a copy of the GNU Lesser General Public
  519. + * License along with FFmpeg; if not, write to the Free Software
  520. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  521. + */
  522. +
  523. +#include "libavutil/imgutils.h"
  524. +#include "libavutil/intreadwrite.h"
  525. +#include "libavutil/opt.h"
  526. +#include "libavutil/pixdesc.h"
  527. +#include "libavutil/pixfmt.h"
  528. +#include "avfilter.h"
  529. +#include "video.h"
  530. +#include "filters.h"
  531. +#include "formats.h"
  532. +
  533. +static const int8_t step_offset_tab[][2] = {
  534. + { 1, 0 }, { 2, -1 },
  535. + { 2, 0 }, { 2, 1 },
  536. + { 3, 0 }, { 3, 1 },
  537. + { 3, 2 }, { 4, 0 },
  538. + { 4, 1 }, { 4, 2 },
  539. + { 4, 3 }, { 6, 0 },
  540. + { 6, 2 }, { 6, 3 },
  541. + { 6, 4 }, { 8, 0 },
  542. + { 8, 2 }, { 8, 4 },
  543. + { 8, 6 }, { 12, 0 },
  544. + { 12, 4 }, { 12, 8 },
  545. + { 16, 0 }, { 16, 4 },
  546. + { 16, 8 }, { 16, 12 },
  547. +};
  548. +
  549. +typedef void (*pf2pf_fun)(uint8_t **dstp,
  550. + const uint8_t **srcp,
  551. + const int *dst_linesizep,
  552. + const int *src_linesizep,
  553. + const int w, const int h,
  554. + const int dst_plane,
  555. + const int dst_shift,
  556. + const int dst_depth,
  557. + const int src_plane,
  558. + const int src_shift,
  559. + const int src_depth);
  560. +
  561. +typedef struct PF2PFContext {
  562. + const AVClass *class;
  563. +
  564. + const AVPixFmtDescriptor *dst_desc, *src_desc;
  565. +
  566. + pf2pf_fun special[2][2][26][2][2][26];
  567. +
  568. + int linesize[4];
  569. + int format;
  570. + int pass;
  571. +
  572. + void (*fun[4])(uint8_t **dstp,
  573. + const uint8_t **srcp,
  574. + const int *dst_linesizep,
  575. + const int *src_linesizep,
  576. + const int w, const int h,
  577. + const int dst_plane,
  578. + const int dst_shift,
  579. + const int dst_depth,
  580. + const int src_plane,
  581. + const int src_shift,
  582. + const int src_depth);
  583. +
  584. + int (*do_pf2pf)(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs);
  585. +} PF2PFContext;
  586. +
  587. +#define OFFSET(x) offsetof(PF2PFContext, x)
  588. +#define FLAGS AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_FILTERING_PARAM
  589. +
  590. +static const AVOption pf2pf_options[] = {
  591. + { "format", "set the pixel format", OFFSET(format), AV_OPT_TYPE_PIXEL_FMT, {.i64=AV_PIX_FMT_NONE}, AV_PIX_FMT_NONE, AV_PIX_FMT_NB-1, FLAGS },
  592. + {NULL}
  593. +};
  594. +
  595. +AVFILTER_DEFINE_CLASS(pf2pf);
  596. +
  597. +static int query_formats(const AVFilterContext *ctx,
  598. + AVFilterFormatsConfig **cfg_in,
  599. + AVFilterFormatsConfig **cfg_out)
  600. +{
  601. + const PF2PFContext *s = ctx->priv;
  602. + AVFilterFormats *formats;
  603. + int ret;
  604. +
  605. + formats = ff_all_formats(AVMEDIA_TYPE_VIDEO);
  606. + if (!formats)
  607. + return AVERROR(ENOMEM);
  608. +
  609. + if ((ret = ff_formats_ref(formats, &cfg_in[0]->formats)) < 0)
  610. + return ret;
  611. +
  612. + if (s->format != AV_PIX_FMT_NONE) {
  613. + formats = NULL;
  614. +
  615. + ret = ff_add_format(&formats, s->format);
  616. + if (ret)
  617. + return ret;
  618. +
  619. + return ff_formats_ref(formats, &cfg_out[0]->formats);
  620. + }
  621. +
  622. + formats = ff_all_formats(AVMEDIA_TYPE_VIDEO);
  623. + if (!formats)
  624. + return AVERROR(ENOMEM);
  625. +
  626. + return ff_formats_ref(formats, &cfg_out[0]->formats);
  627. +}
  628. +
  629. +typedef struct ThreadData {
  630. + AVFrame *in, *out;
  631. +} ThreadData;
  632. +
  633. +#define DST_DEPTH 8
  634. +#include "pf2pf_dst_endian_template.c"
  635. +
  636. +#undef DST_DEPTH
  637. +#define DST_DEPTH 16
  638. +#include "pf2pf_dst_endian_template.c"
  639. +
  640. +static int config_output(AVFilterLink *outlink)
  641. +{
  642. + AVFilterContext *ctx = outlink->src;
  643. + AVFilterLink *inlink = ctx->inputs[0];
  644. + PF2PFContext *s = ctx->priv;
  645. + int ret;
  646. +
  647. + if (outlink->format == inlink->format) {
  648. + s->pass = 1;
  649. + return 0;
  650. + }
  651. +
  652. + s->dst_desc = av_pix_fmt_desc_get(outlink->format);
  653. + s->src_desc = av_pix_fmt_desc_get(inlink->format);
  654. +
  655. + s->special[0][0][0][0][0][0] = pf2pf_special_loop_0_0_0_to_0_0_0;
  656. + s->special[0][0][0][0][0][1] = pf2pf_special_loop_0_0_0_to_0_0_1;
  657. + s->special[0][0][0][0][0][2] = pf2pf_special_loop_0_0_0_to_0_0_2;
  658. + s->special[0][0][1][0][0][0] = pf2pf_special_loop_0_0_1_to_0_0_0;
  659. + s->special[0][0][1][0][0][1] = pf2pf_special_loop_0_0_1_to_0_0_1;
  660. + s->special[0][0][1][0][0][2] = pf2pf_special_loop_0_0_1_to_0_0_2;
  661. + s->special[0][0][2][0][0][0] = pf2pf_special_loop_0_0_2_to_0_0_0;
  662. + s->special[0][0][2][0][0][1] = pf2pf_special_loop_0_0_2_to_0_0_1;
  663. + s->special[0][0][2][0][0][2] = pf2pf_special_loop_0_0_2_to_0_0_2;
  664. + s->special[0][0][2][1][0][0] = pf2pf_special_loop_0_0_2_to_1_0_0;
  665. + s->special[0][0][2][1][0][1] = pf2pf_special_loop_0_0_2_to_1_0_1;
  666. + s->special[0][0][2][1][0][2] = pf2pf_special_loop_0_0_2_to_1_0_2;
  667. + s->special[0][0][2][1][1][0] = pf2pf_special_loop_0_0_2_to_1_1_0;
  668. + s->special[0][0][2][1][1][1] = pf2pf_special_loop_0_0_2_to_1_1_1;
  669. + s->special[0][0][2][1][1][2] = pf2pf_special_loop_0_0_2_to_1_1_2;
  670. + s->special[0][0][0][1][0][0] = pf2pf_special_loop_0_0_0_to_1_0_0;
  671. + s->special[0][0][0][1][0][1] = pf2pf_special_loop_0_0_0_to_1_0_1;
  672. + s->special[0][0][0][1][0][2] = pf2pf_special_loop_0_0_0_to_1_0_2;
  673. + s->special[0][0][0][1][1][0] = pf2pf_special_loop_0_0_0_to_1_1_0;
  674. + s->special[0][0][0][1][1][1] = pf2pf_special_loop_0_0_0_to_1_1_1;
  675. + s->special[0][0][0][1][1][2] = pf2pf_special_loop_0_0_0_to_1_1_2;
  676. + s->special[0][0][1][1][0][0] = pf2pf_special_loop_0_0_1_to_1_0_0;
  677. + s->special[0][0][1][1][0][1] = pf2pf_special_loop_0_0_1_to_1_0_1;
  678. + s->special[0][0][1][1][0][2] = pf2pf_special_loop_0_0_1_to_1_0_2;
  679. + s->special[0][0][1][1][1][0] = pf2pf_special_loop_0_0_1_to_1_1_0;
  680. + s->special[0][0][1][1][1][1] = pf2pf_special_loop_0_0_1_to_1_1_1;
  681. + s->special[0][0][1][1][1][2] = pf2pf_special_loop_0_0_1_to_1_1_2;
  682. + s->special[1][0][0][0][0][0] = pf2pf_special_loop_1_0_0_to_0_0_0;
  683. + s->special[1][0][0][0][0][1] = pf2pf_special_loop_1_0_0_to_0_0_1;
  684. + s->special[1][0][0][0][0][2] = pf2pf_special_loop_1_0_0_to_0_0_2;
  685. + s->special[1][1][0][0][0][0] = pf2pf_special_loop_1_1_0_to_0_0_0;
  686. + s->special[1][1][0][0][0][1] = pf2pf_special_loop_1_1_0_to_0_0_1;
  687. + s->special[1][1][0][0][0][2] = pf2pf_special_loop_1_1_0_to_0_0_2;
  688. + s->special[1][0][1][0][0][0] = pf2pf_special_loop_1_0_1_to_0_0_0;
  689. + s->special[1][0][1][0][0][1] = pf2pf_special_loop_1_0_1_to_0_0_1;
  690. + s->special[1][0][1][0][0][2] = pf2pf_special_loop_1_0_1_to_0_0_2;
  691. + s->special[1][1][1][0][0][0] = pf2pf_special_loop_1_1_1_to_0_0_0;
  692. + s->special[1][1][1][0][0][1] = pf2pf_special_loop_1_1_1_to_0_0_1;
  693. + s->special[1][1][1][0][0][2] = pf2pf_special_loop_1_1_1_to_0_0_2;
  694. + s->special[1][0][0][1][0][0] = pf2pf_special_loop_1_0_0_to_1_0_0;
  695. + s->special[1][0][0][1][0][1] = pf2pf_special_loop_1_0_0_to_1_0_1;
  696. + s->special[1][0][0][1][0][2] = pf2pf_special_loop_1_0_0_to_1_0_2;
  697. + s->special[1][1][0][1][0][0] = pf2pf_special_loop_1_1_0_to_1_0_0;
  698. + s->special[1][1][0][1][0][1] = pf2pf_special_loop_1_1_0_to_1_0_1;
  699. + s->special[1][1][0][1][0][2] = pf2pf_special_loop_1_1_0_to_1_0_2;
  700. + s->special[1][0][0][1][1][0] = pf2pf_special_loop_1_0_0_to_1_1_0;
  701. + s->special[1][0][0][1][1][1] = pf2pf_special_loop_1_0_0_to_1_1_1;
  702. + s->special[1][0][0][1][1][2] = pf2pf_special_loop_1_0_0_to_1_1_2;
  703. + s->special[1][1][0][1][1][0] = pf2pf_special_loop_1_1_0_to_1_1_0;
  704. + s->special[1][1][0][1][1][1] = pf2pf_special_loop_1_1_0_to_1_1_1;
  705. + s->special[1][1][0][1][1][2] = pf2pf_special_loop_1_1_0_to_1_1_2;
  706. + s->special[1][0][1][1][0][0] = pf2pf_special_loop_1_0_1_to_1_0_0;
  707. + s->special[1][0][1][1][0][1] = pf2pf_special_loop_1_0_1_to_1_0_1;
  708. + s->special[1][0][1][1][0][2] = pf2pf_special_loop_1_0_1_to_1_0_2;
  709. + s->special[1][1][1][1][0][0] = pf2pf_special_loop_1_1_1_to_1_0_0;
  710. + s->special[1][1][1][1][0][1] = pf2pf_special_loop_1_1_1_to_1_0_1;
  711. + s->special[1][1][1][1][0][2] = pf2pf_special_loop_1_1_1_to_1_0_2;
  712. + s->special[1][0][1][1][1][0] = pf2pf_special_loop_1_0_1_to_1_1_0;
  713. + s->special[1][0][1][1][1][1] = pf2pf_special_loop_1_0_1_to_1_1_1;
  714. + s->special[1][0][1][1][1][2] = pf2pf_special_loop_1_0_1_to_1_1_2;
  715. + s->special[1][0][2][0][0][0] = pf2pf_special_loop_1_0_2_to_0_0_0;
  716. + s->special[1][0][2][0][0][1] = pf2pf_special_loop_1_0_2_to_0_0_1;
  717. + s->special[1][0][2][0][0][2] = pf2pf_special_loop_1_0_2_to_0_0_2;
  718. + s->special[1][0][2][1][0][0] = pf2pf_special_loop_1_0_2_to_1_0_0;
  719. + s->special[1][0][2][1][0][1] = pf2pf_special_loop_1_0_2_to_1_0_1;
  720. + s->special[1][0][2][1][0][2] = pf2pf_special_loop_1_0_2_to_1_0_2;
  721. + s->special[1][0][2][1][1][0] = pf2pf_special_loop_1_0_2_to_1_1_0;
  722. + s->special[1][0][2][1][1][1] = pf2pf_special_loop_1_0_2_to_1_1_1;
  723. + s->special[1][0][2][1][1][2] = pf2pf_special_loop_1_0_2_to_1_1_2;
  724. + s->special[1][1][1][1][1][0] = pf2pf_special_loop_1_1_1_to_1_1_0;
  725. + s->special[1][1][1][1][1][1] = pf2pf_special_loop_1_1_1_to_1_1_1;
  726. + s->special[1][1][1][1][1][2] = pf2pf_special_loop_1_1_1_to_1_1_2;
  727. + s->special[1][1][2][0][0][0] = pf2pf_special_loop_1_1_2_to_0_0_0;
  728. + s->special[1][1][2][0][0][1] = pf2pf_special_loop_1_1_2_to_0_0_1;
  729. + s->special[1][1][2][0][0][2] = pf2pf_special_loop_1_1_2_to_0_0_2;
  730. + s->special[1][1][2][1][0][0] = pf2pf_special_loop_1_1_2_to_1_0_0;
  731. + s->special[1][1][2][1][0][1] = pf2pf_special_loop_1_1_2_to_1_0_1;
  732. + s->special[1][1][2][1][0][2] = pf2pf_special_loop_1_1_2_to_1_0_2;
  733. + s->special[1][1][2][1][1][0] = pf2pf_special_loop_1_1_2_to_1_1_0;
  734. + s->special[1][1][2][1][1][1] = pf2pf_special_loop_1_1_2_to_1_1_1;
  735. + s->special[1][1][2][1][1][2] = pf2pf_special_loop_1_1_2_to_1_1_2;
  736. +
  737. + for (int i = 0; i < s->dst_desc->nb_components; i++) {
  738. + unsigned dst_be = !!(s->dst_desc->flags & AV_PIX_FMT_FLAG_BE);
  739. + unsigned src_be = !!(s->src_desc->flags & AV_PIX_FMT_FLAG_BE);
  740. + unsigned dst_by = ((s->dst_desc->comp[i].depth + 7) / 8) - 1;
  741. + unsigned src_by = ((s->src_desc->comp[i].depth + 7) / 8) - 1;
  742. + unsigned dst_so = UINT_MAX, src_so = UINT_MAX;
  743. +
  744. + for (int j = 0; j < FF_ARRAY_ELEMS(step_offset_tab); j++) {
  745. + if (step_offset_tab[j][0] == s->dst_desc->comp[i].step &&
  746. + step_offset_tab[j][1] == s->dst_desc->comp[i].offset) {
  747. + dst_so = j;
  748. + break;
  749. + }
  750. + }
  751. +
  752. + for (int j = 0; j < FF_ARRAY_ELEMS(step_offset_tab); j++) {
  753. + if (step_offset_tab[j][0] == s->src_desc->comp[i].step &&
  754. + step_offset_tab[j][1] == s->src_desc->comp[i].offset) {
  755. + src_so = j;
  756. + break;
  757. + }
  758. + }
  759. +
  760. + if (src_so >= 3 || dst_so >= 3) {
  761. + printf("%d %d\n", src_so, dst_so);
  762. + continue;
  763. + }
  764. +
  765. + if (src_so == UINT_MAX || dst_so == UINT_MAX)
  766. + continue;
  767. +
  768. + s->fun[i] = s->special[src_by][src_be][src_so][dst_by][dst_be][dst_so];
  769. + }
  770. +
  771. + if ((ret = av_image_fill_linesizes(s->linesize, outlink->format, inlink->w)) < 0)
  772. + return ret;
  773. +
  774. + if (s->dst_desc->comp[0].depth > 8) {
  775. + if (s->src_desc->comp[0].depth > 8) {
  776. + if (s->dst_desc->flags & AV_PIX_FMT_FLAG_BE) {
  777. + if (s->src_desc->flags & AV_PIX_FMT_FLAG_BE) {
  778. + s->do_pf2pf = pf2pf_1_1_to_1_1;
  779. + } else {
  780. + s->do_pf2pf = pf2pf_1_0_to_1_1;
  781. + }
  782. + } else {
  783. + if (s->src_desc->flags & AV_PIX_FMT_FLAG_BE) {
  784. + s->do_pf2pf = pf2pf_1_1_to_1_0;
  785. + } else {
  786. + s->do_pf2pf = pf2pf_1_0_to_1_0;
  787. + }
  788. + }
  789. + } else {
  790. + if (s->dst_desc->flags & AV_PIX_FMT_FLAG_BE) {
  791. + s->do_pf2pf = pf2pf_0_0_to_1_1;
  792. + } else {
  793. + s->do_pf2pf = pf2pf_0_0_to_1_0;
  794. + }
  795. + }
  796. + } else {
  797. + if (s->src_desc->comp[0].depth > 8) {
  798. + if (s->src_desc->flags & AV_PIX_FMT_FLAG_BE) {
  799. + s->do_pf2pf = pf2pf_1_1_to_0_0;
  800. + } else {
  801. + s->do_pf2pf = pf2pf_1_0_to_0_0;
  802. + }
  803. + } else {
  804. + s->do_pf2pf = pf2pf_0_0_to_0_0;
  805. + }
  806. + }
  807. +
  808. + return 0;
  809. +}
  810. +
  811. +static int filter_frame(AVFilterLink *inlink, AVFrame *in)
  812. +{
  813. + AVFilterContext *ctx = inlink->dst;
  814. + AVFilterLink *outlink = ctx->outputs[0];
  815. + PF2PFContext *s = ctx->priv;
  816. + AVFrame *out;
  817. +
  818. + if (s->pass) {
  819. + out = in;
  820. + } else {
  821. + ThreadData td;
  822. + int nb_jobs;
  823. +
  824. + out = ff_get_video_buffer(outlink, in->width, in->height);
  825. + if (!out) {
  826. + av_frame_free(&in);
  827. + return AVERROR(ENOMEM);
  828. + }
  829. +
  830. + td.in = in;
  831. + td.out = out;
  832. +
  833. + nb_jobs = in->height;
  834. +
  835. + ff_filter_execute(ctx, s->do_pf2pf, &td, NULL,
  836. + FFMIN(nb_jobs, ff_filter_get_nb_threads(ctx)));
  837. +
  838. + av_frame_copy_props(out, in);
  839. + av_frame_free(&in);
  840. + }
  841. +
  842. + return ff_filter_frame(outlink, out);
  843. +}
  844. +
  845. +static int activate(AVFilterContext *ctx)
  846. +{
  847. + AVFilterLink *inlink = ctx->inputs[0];
  848. + AVFilterLink *outlink = ctx->outputs[0];
  849. + AVFrame *in;
  850. + int ret;
  851. +
  852. + FF_FILTER_FORWARD_STATUS_BACK(outlink, inlink);
  853. +
  854. + ret = ff_inlink_consume_frame(inlink, &in);
  855. + if (ret < 0)
  856. + return ret;
  857. + if (ret > 0)
  858. + return filter_frame(inlink, in);
  859. +
  860. + FF_FILTER_FORWARD_STATUS(inlink, outlink);
  861. + FF_FILTER_FORWARD_WANTED(outlink, inlink);
  862. +
  863. + return FFERROR_NOT_READY;
  864. +}
  865. +
  866. +static AVFrame *get_in_video_buffer(AVFilterLink *inlink, int w, int h)
  867. +{
  868. + AVFilterContext *ctx = inlink->dst;
  869. + PF2PFContext *s = ctx->priv;
  870. +
  871. + return s->pass ?
  872. + ff_null_get_video_buffer (inlink, w, h) :
  873. + ff_default_get_video_buffer(inlink, w, h);
  874. +}
  875. +
  876. +static AVFrame *get_out_video_buffer(AVFilterLink *outlink, int w, int h)
  877. +{
  878. + AVFilterContext *ctx = outlink->src;
  879. + PF2PFContext *s = ctx->priv;
  880. +
  881. + return s->pass ?
  882. + ff_null_get_video_buffer (outlink, w, h) :
  883. + ff_default_get_video_buffer(outlink, w, h);
  884. +}
  885. +
  886. +static const AVFilterPad inputs[] = {
  887. + {
  888. + .name = "default",
  889. + .type = AVMEDIA_TYPE_VIDEO,
  890. + .get_buffer.video = get_in_video_buffer,
  891. + },
  892. +};
  893. +
  894. +static const AVFilterPad outputs[] = {
  895. + {
  896. + .name = "default",
  897. + .type = AVMEDIA_TYPE_VIDEO,
  898. + .config_props = config_output,
  899. + .get_buffer.video = get_out_video_buffer,
  900. + },
  901. +};
  902. +
  903. +const FFFilter ff_vf_pf2pf = {
  904. + .p.name = "pf2pf",
  905. + .p.description = NULL_IF_CONFIG_SMALL("Switch video pixel format."),
  906. + .p.priv_class = &pf2pf_class,
  907. + .priv_size = sizeof(PF2PFContext),
  908. + .activate = activate,
  909. + FILTER_QUERY_FUNC2(query_formats),
  910. + FILTER_INPUTS(inputs),
  911. + FILTER_OUTPUTS(outputs),
  912. + .p.flags = AVFILTER_FLAG_SLICE_THREADS,
  913. +};
  914. diff --git a/libavutil/imgutils.c b/libavutil/imgutils.c
  915. index 119372e418..2b1dc10215 100644
  916. --- a/libavutil/imgutils.c
  917. +++ b/libavutil/imgutils.c
  918. @@ -35,12 +35,11 @@
  919. void av_image_fill_max_pixsteps(int max_pixsteps[4], int max_pixstep_comps[4],
  920. const AVPixFmtDescriptor *pixdesc)
  921. {
  922. - int i;
  923. memset(max_pixsteps, 0, 4*sizeof(max_pixsteps[0]));
  924. if (max_pixstep_comps)
  925. memset(max_pixstep_comps, 0, 4*sizeof(max_pixstep_comps[0]));
  926.  
  927. - for (i = 0; i < 4; i++) {
  928. + for (int i = 0; i < pixdesc->nb_components; i++) {
  929. const AVComponentDescriptor *comp = &(pixdesc->comp[i]);
  930. if (comp->step > max_pixsteps[comp->plane]) {
  931. max_pixsteps[comp->plane] = comp->step;
  932. --
  933. 2.47.1
  934.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement