Advertisement
Guest User

Untitled

a guest
Jan 24th, 2025
47
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 33.96 KB | None | 0 0
  1. From 4bfb2ebbdc3bde44b08219128686843a2184c9b6 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 | 49 +++
  10. libavfilter/pf2pf_dst_endian_template.c | 30 ++
  11. libavfilter/pf2pf_special_template.c | 60 ++++
  12. libavfilter/pf2pf_src_depth_template.c | 39 +++
  13. libavfilter/pf2pf_src_endian_template.c | 30 ++
  14. libavfilter/pf2pf_step_offset_template.c | 47 +++
  15. libavfilter/pf2pf_template.c | 147 +++++++++
  16. libavfilter/vf_pf2pf.c | 385 +++++++++++++++++++++++
  17. libavutil/imgutils.c | 3 +-
  18. 11 files changed, 790 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..d632acdd58
  55. --- /dev/null
  56. +++ b/libavfilter/pf2pf_dst_depth_template.c
  57. @@ -0,0 +1,49 @@
  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 dtype
  80. +#undef DST_F
  81. +#undef DWP
  82. +#undef DRP
  83. +#if DST_DEPTH == 8
  84. +#define dtype uint8_t
  85. +#define DST_F u8
  86. +#define DWP(x, y) ((x)[0] = (y))
  87. +#define DRP(x) ((x)[0])
  88. +#elif DST_DEPTH == 16
  89. +#define dtype uint16_t
  90. +#define DST_F u16
  91. +#if DST_E == 0
  92. +#define DWP(x, y) AV_WL16((x), (y))
  93. +#define DRP(x) AV_RL16(x)
  94. +#elif DST_E == 1
  95. +#define DWP(x, y) AV_WB16((x), (y))
  96. +#define DRP(x) AV_RB16(x)
  97. +#endif
  98. +#endif
  99. +
  100. +#undef SRC_DEPTH
  101. +#define SRC_DEPTH 8
  102. +#include "pf2pf_src_depth_template.c"
  103. +
  104. +#undef SRC_DEPTH
  105. +#define SRC_DEPTH 16
  106. +#include "pf2pf_src_depth_template.c"
  107. diff --git a/libavfilter/pf2pf_dst_endian_template.c b/libavfilter/pf2pf_dst_endian_template.c
  108. new file mode 100644
  109. index 0000000000..1007ce6a80
  110. --- /dev/null
  111. +++ b/libavfilter/pf2pf_dst_endian_template.c
  112. @@ -0,0 +1,30 @@
  113. +/*
  114. + * This file is part of FFmpeg.
  115. + *
  116. + * FFmpeg is free software; you can redistribute it and/or
  117. + * modify it under the terms of the GNU Lesser General Public
  118. + * License as published by the Free Software Foundation; either
  119. + * version 2.1 of the License, or (at your option) any later version.
  120. + *
  121. + * FFmpeg is distributed in the hope that it will be useful,
  122. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  123. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  124. + * Lesser General Public License for more details.
  125. + *
  126. + * You should have received a copy of the GNU Lesser General Public
  127. + * License along with FFmpeg; if not, write to the Free Software
  128. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  129. + */
  130. +
  131. +#include "avfilter.h"
  132. +#include "video.h"
  133. +
  134. +#undef DST_E
  135. +#define DST_E 0
  136. +#include "pf2pf_src_endian_template.c"
  137. +
  138. +#if DST_DEPTH == 16
  139. +#undef DST_E
  140. +#define DST_E 1
  141. +#include "pf2pf_src_endian_template.c"
  142. +#endif
  143. diff --git a/libavfilter/pf2pf_special_template.c b/libavfilter/pf2pf_special_template.c
  144. new file mode 100644
  145. index 0000000000..c975b2657b
  146. --- /dev/null
  147. +++ b/libavfilter/pf2pf_special_template.c
  148. @@ -0,0 +1,60 @@
  149. +/*
  150. + * This file is part of FFmpeg.
  151. + *
  152. + * FFmpeg is free software; you can redistribute it and/or
  153. + * modify it under the terms of the GNU Lesser General Public
  154. + * License as published by the Free Software Foundation; either
  155. + * version 2.1 of the License, or (at your option) any later version.
  156. + *
  157. + * FFmpeg is distributed in the hope that it will be useful,
  158. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  159. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  160. + * Lesser General Public License for more details.
  161. + *
  162. + * You should have received a copy of the GNU Lesser General Public
  163. + * License along with FFmpeg; if not, write to the Free Software
  164. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  165. + */
  166. +
  167. +#include "avfilter.h"
  168. +#include "video.h"
  169. +
  170. +#if SRC_DEPTH > 8 || SRC_E == 0
  171. +#define fns3(a,b,c,d,e,f,g,h,i) a##_##b##_##c##_##d##_##e##_to_##f##_##g##_##h##_##i
  172. +#define fns2(a,b,c,d,e,f,g,h,i) fns3(a,b,c,d,e,f,g,h,i)
  173. +#define fns(a) fns2(a, SRC_F, SRC_E, SRC_STEP, SRC_OFFSET_NAME, DST_F, DST_E, DST_STEP, DST_OFFSET_NAME)
  174. +
  175. +static void fns(pf2pf_special_loop)(uint8_t **dstp,
  176. + const uint8_t **srcp,
  177. + const int *dst_linesizep,
  178. + const int *src_linesizep,
  179. + const int w, const int h,
  180. + const int dst_plane,
  181. + const int dst_shift,
  182. + const int dst_depth,
  183. + const int src_plane,
  184. + const int src_shift,
  185. + const int src_depth)
  186. +{
  187. + const ptrdiff_t dst_linesize = dst_linesizep[dst_plane];
  188. + const ptrdiff_t src_linesize = src_linesizep[src_plane];
  189. + const unsigned dst_mask = (1U << dst_depth) - 1;
  190. + const unsigned src_mask = (1U << src_depth) - 1;
  191. + const unsigned dst_rshift = FFMAX(src_depth - dst_depth, 0);
  192. + const unsigned dst_lshift = dst_shift + FFMAX(dst_depth-src_depth, 0);
  193. + const uint8_t *src = srcp[src_plane];
  194. + uint8_t *dst = dstp[dst_plane];
  195. +
  196. + for (int y = 0; y < h; y++) {
  197. + for (int x = 0, i = 0, j = 0; x < w; x++) {
  198. + unsigned odst = DRP(dst + i + DST_OFFSET);
  199. + DWP(dst + i + DST_OFFSET, odst | (((((SRP(src + j + SRC_OFFSET) >> src_shift) & src_mask) >> dst_rshift) & dst_mask) << dst_lshift));
  200. + i += DST_STEP;
  201. + j += SRC_STEP;
  202. + }
  203. +
  204. + dst += dst_linesize;
  205. + src += src_linesize;
  206. + }
  207. +}
  208. +#endif
  209. diff --git a/libavfilter/pf2pf_src_depth_template.c b/libavfilter/pf2pf_src_depth_template.c
  210. new file mode 100644
  211. index 0000000000..cf5cf4cb1e
  212. --- /dev/null
  213. +++ b/libavfilter/pf2pf_src_depth_template.c
  214. @@ -0,0 +1,39 @@
  215. +/*
  216. + * This file is part of FFmpeg.
  217. + *
  218. + * FFmpeg is free software; you can redistribute it and/or
  219. + * modify it under the terms of the GNU Lesser General Public
  220. + * License as published by the Free Software Foundation; either
  221. + * version 2.1 of the License, or (at your option) any later version.
  222. + *
  223. + * FFmpeg is distributed in the hope that it will be useful,
  224. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  225. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  226. + * Lesser General Public License for more details.
  227. + *
  228. + * You should have received a copy of the GNU Lesser General Public
  229. + * License along with FFmpeg; if not, write to the Free Software
  230. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  231. + */
  232. +
  233. +#include "avfilter.h"
  234. +#include "video.h"
  235. +
  236. +#undef stype
  237. +#undef SRC_F
  238. +#undef SRP
  239. +#if SRC_DEPTH == 8
  240. +#define stype uint8_t
  241. +#define SRC_F u8
  242. +#define SRP(x) ((x)[0])
  243. +#elif SRC_DEPTH == 16
  244. +#define stype uint16_t
  245. +#define SRC_F u16
  246. +#if SRC_E == 0
  247. +#define SRP(x) AV_RL16((x))
  248. +#elif SRC_E == 1
  249. +#define SRP(x) AV_RB16((x))
  250. +#endif
  251. +#endif
  252. +
  253. +#include "pf2pf_template.c"
  254. diff --git a/libavfilter/pf2pf_src_endian_template.c b/libavfilter/pf2pf_src_endian_template.c
  255. new file mode 100644
  256. index 0000000000..6c3d0d30f5
  257. --- /dev/null
  258. +++ b/libavfilter/pf2pf_src_endian_template.c
  259. @@ -0,0 +1,30 @@
  260. +/*
  261. + * This file is part of FFmpeg.
  262. + *
  263. + * FFmpeg is free software; you can redistribute it and/or
  264. + * modify it under the terms of the GNU Lesser General Public
  265. + * License as published by the Free Software Foundation; either
  266. + * version 2.1 of the License, or (at your option) any later version.
  267. + *
  268. + * FFmpeg is distributed in the hope that it will be useful,
  269. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  270. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  271. + * Lesser General Public License for more details.
  272. + *
  273. + * You should have received a copy of the GNU Lesser General Public
  274. + * License along with FFmpeg; if not, write to the Free Software
  275. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  276. + */
  277. +
  278. +#include "avfilter.h"
  279. +#include "video.h"
  280. +
  281. +#undef SRC_E
  282. +#define SRC_E 0
  283. +#include "pf2pf_dst_depth_template.c"
  284. +
  285. +#if SRC_DEPTH == 16
  286. +#undef SRC_E
  287. +#define SRC_E 1
  288. +#include "pf2pf_dst_depth_template.c"
  289. +#endif
  290. diff --git a/libavfilter/pf2pf_step_offset_template.c b/libavfilter/pf2pf_step_offset_template.c
  291. new file mode 100644
  292. index 0000000000..096b68f9e8
  293. --- /dev/null
  294. +++ b/libavfilter/pf2pf_step_offset_template.c
  295. @@ -0,0 +1,47 @@
  296. +/*
  297. + * This file is part of FFmpeg.
  298. + *
  299. + * FFmpeg is free software; you can redistribute it and/or
  300. + * modify it under the terms of the GNU Lesser General Public
  301. + * License as published by the Free Software Foundation; either
  302. + * version 2.1 of the License, or (at your option) any later version.
  303. + *
  304. + * FFmpeg is distributed in the hope that it will be useful,
  305. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  306. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  307. + * Lesser General Public License for more details.
  308. + *
  309. + * You should have received a copy of the GNU Lesser General Public
  310. + * License along with FFmpeg; if not, write to the Free Software
  311. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  312. + */
  313. +
  314. +#include "avfilter.h"
  315. +#include "video.h"
  316. +
  317. +#undef DST_STEP
  318. +#undef DST_OFFSET
  319. +#undef DST_OFFSET_NAME
  320. +
  321. +#define DST_STEP 1
  322. +#define DST_OFFSET 0
  323. +#define DST_OFFSET_NAME 0
  324. +#include "pf2pf_special_template.c"
  325. +
  326. +#undef DST_STEP
  327. +#undef DST_OFFSET
  328. +#undef DST_OFFSET_NAME
  329. +
  330. +#define DST_STEP 2
  331. +#define DST_OFFSET -1
  332. +#define DST_OFFSET_NAME n1
  333. +#include "pf2pf_special_template.c"
  334. +
  335. +#undef DST_STEP
  336. +#undef DST_OFFSET
  337. +#undef DST_OFFSET_NAME
  338. +
  339. +#define DST_STEP 2
  340. +#define DST_OFFSET 0
  341. +#define DST_OFFSET_NAME 0
  342. +#include "pf2pf_special_template.c"
  343. diff --git a/libavfilter/pf2pf_template.c b/libavfilter/pf2pf_template.c
  344. new file mode 100644
  345. index 0000000000..c269242615
  346. --- /dev/null
  347. +++ b/libavfilter/pf2pf_template.c
  348. @@ -0,0 +1,147 @@
  349. +/*
  350. + * This file is part of FFmpeg.
  351. + *
  352. + * FFmpeg is free software; you can redistribute it and/or
  353. + * modify it under the terms of the GNU Lesser General Public
  354. + * License as published by the Free Software Foundation; either
  355. + * version 2.1 of the License, or (at your option) any later version.
  356. + *
  357. + * FFmpeg is distributed in the hope that it will be useful,
  358. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  359. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  360. + * Lesser General Public License for more details.
  361. + *
  362. + * You should have received a copy of the GNU Lesser General Public
  363. + * License along with FFmpeg; if not, write to the Free Software
  364. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  365. + */
  366. +
  367. +#include "avfilter.h"
  368. +#include "video.h"
  369. +
  370. +#if SRC_DEPTH > 8 || SRC_E == 0
  371. +#define fn3(a,b,c,d,e) a##_##b##_##c##_to_##d##_##e
  372. +#define fn2(a,b,c,d,e) fn3(a,b,c,d,e)
  373. +#define fn(a) fn2(a, SRC_F, SRC_E, DST_F, DST_E)
  374. +
  375. +static void fn(pf2pf_loop)(uint8_t **dstp,
  376. + const uint8_t **srcp,
  377. + const int *dst_linesizep,
  378. + const int *src_linesizep,
  379. + const int w, const int h,
  380. + const int dst_plane,
  381. + const int dst_step, const int dst_shift,
  382. + const int dst_offset, const int dst_depth,
  383. + const int src_plane,
  384. + const int src_step, const int src_shift,
  385. + const int src_offset, const int src_depth)
  386. +{
  387. + const ptrdiff_t dst_linesize = dst_linesizep[dst_plane];
  388. + const ptrdiff_t src_linesize = src_linesizep[src_plane];
  389. + const unsigned dst_mask = (1U << dst_depth) - 1;
  390. + const unsigned src_mask = (1U << src_depth) - 1;
  391. + const unsigned dst_rshift = FFMAX(src_depth - dst_depth, 0);
  392. + const unsigned dst_lshift = dst_shift + FFMAX(dst_depth-src_depth, 0);
  393. + const uint8_t *src = srcp[src_plane];
  394. + uint8_t *dst = dstp[dst_plane];
  395. +
  396. + for (int y = 0; y < h; y++) {
  397. + for (int x = 0, i = 0, j = 0; x < w; x++) {
  398. + unsigned odst = DRP(dst + i + dst_offset);
  399. + DWP(dst + i + dst_offset, odst | (((((SRP(src + j + src_offset) >> src_shift) & src_mask) >> dst_rshift) & dst_mask) << dst_lshift));
  400. + i += dst_step;
  401. + j += src_step;
  402. + }
  403. +
  404. + dst += dst_linesize;
  405. + src += src_linesize;
  406. + }
  407. +}
  408. +
  409. +static int fn(pf2pf)(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
  410. +{
  411. + PF2PFContext *s = ctx->priv;
  412. + const int nb_components = s->dst_desc->nb_components;
  413. + const int *linesize = s->linesize;
  414. + ThreadData *td = arg;
  415. + AVFrame *restrict out = td->out;
  416. + AVFrame *restrict in = td->in;
  417. + const int w = in->width;
  418. + const int h = in->height;
  419. + const int start = (h * jobnr) / nb_jobs;
  420. + const int end = (h * (jobnr+1)) / nb_jobs;
  421. +
  422. + for (int comp = 0; comp < nb_components; comp++) {
  423. + if (out->data[comp]) {
  424. + uint8_t *dst_data = out->data[comp] + start * out->linesize[comp];
  425. +
  426. + for (int y = start; y < end; y++) {
  427. + memset(dst_data, 0, linesize[comp]);
  428. + dst_data += out->linesize[comp];
  429. + }
  430. + }
  431. + }
  432. +
  433. + for (int comp = 0; comp < nb_components; comp++) {
  434. + const int dst_plane = s->dst_desc->comp[comp].plane;
  435. + const int dst_step = s->dst_desc->comp[comp].step;
  436. + const int dst_shift = s->dst_desc->comp[comp].shift;
  437. + const int dst_offset= s->dst_desc->comp[comp].offset;
  438. + const int dst_depth = s->dst_desc->comp[comp].depth;
  439. + const int src_plane = s->src_desc->comp[comp].plane;
  440. + const int src_step = s->src_desc->comp[comp].step;
  441. + const int src_shift = s->src_desc->comp[comp].shift;
  442. + const int src_offset= s->src_desc->comp[comp].offset;
  443. + const int src_depth = s->src_desc->comp[comp].depth;
  444. + uint8_t *dst_data[4] = {NULL}, *src_data[4] = {NULL};
  445. +
  446. + for (int i = 0; i < 4; i++) {
  447. + if (out->data[i])
  448. + dst_data[i] = out->data[i] + start * out->linesize[i];
  449. + if (in->data[i])
  450. + src_data[i] = in->data[i] + start * in->linesize[i];
  451. + }
  452. +
  453. + if (s->fun[comp]) {
  454. + s->fun[comp]((uint8_t **)dst_data, (const uint8_t **)src_data, out->linesize, in->linesize,
  455. + w, end - start,
  456. + dst_plane, dst_shift, dst_depth,
  457. + src_plane, src_shift, src_depth);
  458. + } else {
  459. + fn(pf2pf_loop)((uint8_t **)dst_data, (const uint8_t **)src_data, out->linesize, in->linesize,
  460. + w, end - start,
  461. + dst_plane, dst_step, dst_shift, dst_offset, dst_depth,
  462. + src_plane, src_step, src_shift, src_offset, src_depth);
  463. + }
  464. + }
  465. +
  466. + return 0;
  467. +}
  468. +#endif
  469. +
  470. +#undef SRC_STEP
  471. +#undef SRC_OFFSET
  472. +#undef SRC_OFFSET_NAME
  473. +
  474. +#define SRC_STEP 1
  475. +#define SRC_OFFSET 0
  476. +#define SRC_OFFSET_NAME 0
  477. +#include "pf2pf_step_offset_template.c"
  478. +
  479. +#undef SRC_STEP
  480. +#undef SRC_OFFSET
  481. +#undef SRC_OFFSET_NAME
  482. +
  483. +#define SRC_STEP 2
  484. +#define SRC_OFFSET -1
  485. +#define SRC_OFFSET_NAME n1
  486. +#include "pf2pf_step_offset_template.c"
  487. +
  488. +#undef SRC_STEP
  489. +#undef SRC_OFFSET
  490. +#undef SRC_OFFSET_NAME
  491. +
  492. +#define SRC_STEP 2
  493. +#define SRC_OFFSET 0
  494. +#define SRC_OFFSET_NAME 0
  495. +#include "pf2pf_step_offset_template.c"
  496. diff --git a/libavfilter/vf_pf2pf.c b/libavfilter/vf_pf2pf.c
  497. new file mode 100644
  498. index 0000000000..64b444cd5b
  499. --- /dev/null
  500. +++ b/libavfilter/vf_pf2pf.c
  501. @@ -0,0 +1,385 @@
  502. +/*
  503. + * This file is part of FFmpeg.
  504. + *
  505. + * FFmpeg is free software; you can redistribute it and/or
  506. + * modify it under the terms of the GNU Lesser General Public
  507. + * License as published by the Free Software Foundation; either
  508. + * version 2.1 of the License, or (at your option) any later version.
  509. + *
  510. + * FFmpeg is distributed in the hope that it will be useful,
  511. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  512. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  513. + * Lesser General Public License for more details.
  514. + *
  515. + * You should have received a copy of the GNU Lesser General Public
  516. + * License along with FFmpeg; if not, write to the Free Software
  517. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  518. + */
  519. +
  520. +#include "libavutil/imgutils.h"
  521. +#include "libavutil/intreadwrite.h"
  522. +#include "libavutil/opt.h"
  523. +#include "libavutil/pixdesc.h"
  524. +#include "libavutil/pixfmt.h"
  525. +#include "avfilter.h"
  526. +#include "video.h"
  527. +#include "filters.h"
  528. +#include "formats.h"
  529. +
  530. +static int8_t step_offset_tab[][2] = {
  531. + { 1, 0 }, { 2, -1 },
  532. + { 2, 0 }, { 2, 1 },
  533. + { 3, 0 }, { 3, 1 },
  534. + { 3, 2 }, { 4, 0 },
  535. + { 4, 1 }, { 4, 2 },
  536. + { 4, 3 }, { 6, 0 },
  537. + { 6, 2 }, { 6, 3 },
  538. + { 6, 4 }, { 8, 0 },
  539. + { 8, 2 }, { 8, 4 },
  540. + { 8, 6 }, { 12, 0 },
  541. + { 12, 4 }, { 12, 8 },
  542. + { 16, 0 }, { 16, 4 },
  543. + { 16, 8 }, { 16, 12 },
  544. +};
  545. +
  546. +typedef struct PF2PFContext {
  547. + const AVClass *class;
  548. +
  549. + const AVPixFmtDescriptor *dst_desc, *src_desc;
  550. +
  551. + int linesize[4];
  552. + int format;
  553. + int pass;
  554. +
  555. + void (*special[2][2][3][2][2][3])(uint8_t **dstp,
  556. + const uint8_t **srcp,
  557. + const int *dst_linesizep,
  558. + const int *src_linesizep,
  559. + const int w, const int h,
  560. + const int dst_plane,
  561. + const int dst_shift,
  562. + const int dst_depth,
  563. + const int src_plane,
  564. + const int src_shift,
  565. + const int src_depth);
  566. +
  567. + void (*fun[4])(uint8_t **dstp,
  568. + const uint8_t **srcp,
  569. + const int *dst_linesizep,
  570. + const int *src_linesizep,
  571. + const int w, const int h,
  572. + const int dst_plane,
  573. + const int dst_shift,
  574. + const int dst_depth,
  575. + const int src_plane,
  576. + const int src_shift,
  577. + const int src_depth);
  578. +
  579. + int (*do_pf2pf)(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs);
  580. +} PF2PFContext;
  581. +
  582. +#define OFFSET(x) offsetof(PF2PFContext, x)
  583. +#define FLAGS AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_FILTERING_PARAM
  584. +
  585. +static const AVOption pf2pf_options[] = {
  586. + { "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 },
  587. + {NULL}
  588. +};
  589. +
  590. +AVFILTER_DEFINE_CLASS(pf2pf);
  591. +
  592. +static int query_formats(const AVFilterContext *ctx,
  593. + AVFilterFormatsConfig **cfg_in,
  594. + AVFilterFormatsConfig **cfg_out)
  595. +{
  596. + const PF2PFContext *s = ctx->priv;
  597. + AVFilterFormats *formats;
  598. + int ret;
  599. +
  600. + formats = ff_all_formats(AVMEDIA_TYPE_VIDEO);
  601. + if (!formats)
  602. + return AVERROR(ENOMEM);
  603. +
  604. + if ((ret = ff_formats_ref(formats, &cfg_in[0]->formats)) < 0)
  605. + return ret;
  606. +
  607. + if (s->format != AV_PIX_FMT_NONE) {
  608. + formats = NULL;
  609. +
  610. + ret = ff_add_format(&formats, s->format);
  611. + if (ret)
  612. + return ret;
  613. +
  614. + return ff_formats_ref(formats, &cfg_out[0]->formats);
  615. + }
  616. +
  617. + formats = ff_all_formats(AVMEDIA_TYPE_VIDEO);
  618. + if (!formats)
  619. + return AVERROR(ENOMEM);
  620. +
  621. + return ff_formats_ref(formats, &cfg_out[0]->formats);
  622. +}
  623. +
  624. +typedef struct ThreadData {
  625. + AVFrame *in, *out;
  626. +} ThreadData;
  627. +
  628. +#define DST_DEPTH 8
  629. +#include "pf2pf_dst_endian_template.c"
  630. +
  631. +#undef DST_DEPTH
  632. +#define DST_DEPTH 16
  633. +#include "pf2pf_dst_endian_template.c"
  634. +
  635. +static int config_output(AVFilterLink *outlink)
  636. +{
  637. + AVFilterContext *ctx = outlink->src;
  638. + AVFilterLink *inlink = ctx->inputs[0];
  639. + PF2PFContext *s = ctx->priv;
  640. + int ret;
  641. +
  642. + if (outlink->format == inlink->format) {
  643. + s->pass = 1;
  644. + return 0;
  645. + }
  646. +
  647. + s->special[0][0][0][0][0][0] = pf2pf_special_loop_u8_0_1_0_to_u8_0_1_0;
  648. + s->special[0][0][0][0][0][1] = pf2pf_special_loop_u8_0_1_0_to_u8_0_2_n1;
  649. + s->special[0][0][0][0][0][2] = pf2pf_special_loop_u8_0_1_0_to_u8_0_2_0;
  650. + s->special[0][0][1][0][0][0] = pf2pf_special_loop_u8_0_2_n1_to_u8_0_1_0;
  651. + s->special[0][0][1][0][0][1] = pf2pf_special_loop_u8_0_2_n1_to_u8_0_2_n1;
  652. + s->special[0][0][1][0][0][2] = pf2pf_special_loop_u8_0_2_n1_to_u8_0_2_0;
  653. + s->special[0][0][2][0][0][0] = pf2pf_special_loop_u8_0_2_0_to_u8_0_1_0;
  654. + s->special[0][0][2][0][0][1] = pf2pf_special_loop_u8_0_2_0_to_u8_0_2_n1;
  655. + s->special[0][0][2][0][0][2] = pf2pf_special_loop_u8_0_2_0_to_u8_0_2_0;
  656. + s->special[0][0][0][1][0][0] = pf2pf_special_loop_u8_0_1_0_to_u16_0_1_0;
  657. + s->special[0][0][0][1][0][1] = pf2pf_special_loop_u8_0_1_0_to_u16_0_2_n1;
  658. + s->special[0][0][0][1][0][2] = pf2pf_special_loop_u8_0_1_0_to_u16_0_2_0;
  659. + s->special[0][0][0][1][1][0] = pf2pf_special_loop_u8_0_1_0_to_u16_1_1_0;
  660. + s->special[0][0][0][1][1][1] = pf2pf_special_loop_u8_0_1_0_to_u16_1_2_n1;
  661. + s->special[0][0][0][1][1][2] = pf2pf_special_loop_u8_0_1_0_to_u16_1_2_0;
  662. + s->special[0][0][1][1][0][0] = pf2pf_special_loop_u8_0_2_n1_to_u16_0_1_0;
  663. + s->special[0][0][1][1][0][1] = pf2pf_special_loop_u8_0_2_n1_to_u16_0_2_n1;
  664. + s->special[0][0][1][1][0][2] = pf2pf_special_loop_u8_0_2_n1_to_u16_0_2_0;
  665. + s->special[0][0][1][1][1][0] = pf2pf_special_loop_u8_0_2_n1_to_u16_1_1_0;
  666. + s->special[0][0][1][1][1][1] = pf2pf_special_loop_u8_0_2_n1_to_u16_1_2_n1;
  667. + s->special[0][0][1][1][1][2] = pf2pf_special_loop_u8_0_2_n1_to_u16_1_2_0;
  668. + s->special[1][0][0][0][0][0] = pf2pf_special_loop_u16_0_1_0_to_u8_0_1_0;
  669. + s->special[1][0][0][0][0][1] = pf2pf_special_loop_u16_0_1_0_to_u8_0_2_n1;
  670. + s->special[1][0][0][0][0][2] = pf2pf_special_loop_u16_0_1_0_to_u8_0_2_0;
  671. + s->special[1][1][0][0][0][0] = pf2pf_special_loop_u16_1_1_0_to_u8_0_1_0;
  672. + s->special[1][1][0][0][0][1] = pf2pf_special_loop_u16_1_1_0_to_u8_0_2_n1;
  673. + s->special[1][1][0][0][0][2] = pf2pf_special_loop_u16_1_1_0_to_u8_0_2_0;
  674. + s->special[1][0][1][0][0][0] = pf2pf_special_loop_u16_0_2_n1_to_u8_0_1_0;
  675. + s->special[1][0][2][0][0][0] = pf2pf_special_loop_u16_0_2_0_to_u8_0_1_0;
  676. + s->special[1][0][1][0][0][1] = pf2pf_special_loop_u16_0_2_n1_to_u8_0_2_n1;
  677. + s->special[1][0][1][0][0][2] = pf2pf_special_loop_u16_0_2_n1_to_u8_0_2_0;
  678. + s->special[1][1][1][0][0][0] = pf2pf_special_loop_u16_1_2_n1_to_u8_0_1_0;
  679. + s->special[1][1][1][0][0][1] = pf2pf_special_loop_u16_1_2_n1_to_u8_0_2_n1;
  680. + s->special[1][1][1][0][0][2] = pf2pf_special_loop_u16_1_2_n1_to_u8_0_2_0;
  681. + s->special[1][0][0][1][0][0] = pf2pf_special_loop_u16_0_1_0_to_u16_0_1_0;
  682. + s->special[1][0][0][1][0][1] = pf2pf_special_loop_u16_0_1_0_to_u16_0_2_n1;
  683. + s->special[1][0][0][1][0][2] = pf2pf_special_loop_u16_0_1_0_to_u16_0_2_0;
  684. + s->special[1][1][0][1][0][0] = pf2pf_special_loop_u16_1_1_0_to_u16_0_1_0;
  685. + s->special[1][1][0][1][0][1] = pf2pf_special_loop_u16_1_1_0_to_u16_0_2_n1;
  686. + s->special[1][1][0][1][0][2] = pf2pf_special_loop_u16_1_1_0_to_u16_0_2_0;
  687. + s->special[1][0][0][1][1][0] = pf2pf_special_loop_u16_0_1_0_to_u16_1_1_0;
  688. + s->special[1][0][0][1][1][1] = pf2pf_special_loop_u16_0_1_0_to_u16_1_2_n1;
  689. + s->special[1][0][0][1][1][2] = pf2pf_special_loop_u16_0_1_0_to_u16_1_2_0;
  690. + s->special[1][1][0][1][1][0] = pf2pf_special_loop_u16_1_1_0_to_u16_1_1_0;
  691. + s->special[1][1][0][1][1][1] = pf2pf_special_loop_u16_1_1_0_to_u16_1_2_n1;
  692. + s->special[1][1][0][1][1][2] = pf2pf_special_loop_u16_1_1_0_to_u16_1_2_0;
  693. + s->special[1][0][1][1][0][0] = pf2pf_special_loop_u16_0_2_n1_to_u16_0_1_0;
  694. + s->special[1][0][1][1][0][1] = pf2pf_special_loop_u16_0_2_n1_to_u16_0_2_n1;
  695. + s->special[1][0][1][1][0][2] = pf2pf_special_loop_u16_0_2_n1_to_u16_0_2_0;
  696. + s->special[1][0][2][1][0][2] = pf2pf_special_loop_u16_0_2_0_to_u16_0_2_0;
  697. + s->special[1][1][1][1][0][0] = pf2pf_special_loop_u16_1_2_n1_to_u16_0_1_0;
  698. + s->special[1][1][1][1][0][1] = pf2pf_special_loop_u16_1_2_n1_to_u16_0_2_n1;
  699. + s->special[1][1][1][1][0][2] = pf2pf_special_loop_u16_1_2_n1_to_u16_0_2_0;
  700. + s->special[1][0][1][1][1][0] = pf2pf_special_loop_u16_0_2_n1_to_u16_1_1_0;
  701. + s->special[1][0][1][1][1][1] = pf2pf_special_loop_u16_0_2_n1_to_u16_1_2_n1;
  702. + s->special[1][0][1][1][1][2] = pf2pf_special_loop_u16_0_2_n1_to_u16_1_2_0;
  703. + s->special[1][1][1][1][1][0] = pf2pf_special_loop_u16_1_2_n1_to_u16_1_1_0;
  704. + s->special[1][1][1][1][1][1] = pf2pf_special_loop_u16_1_2_n1_to_u16_1_2_n1;
  705. + s->special[1][1][1][1][1][2] = pf2pf_special_loop_u16_1_2_n1_to_u16_1_2_0;
  706. +
  707. + s->dst_desc = av_pix_fmt_desc_get(outlink->format);
  708. + s->src_desc = av_pix_fmt_desc_get(inlink->format);
  709. +
  710. + for (int i = 0; i < s->dst_desc->nb_components; i++) {
  711. + unsigned dst_be = !!(s->dst_desc->flags & AV_PIX_FMT_FLAG_BE);
  712. + unsigned src_be = !!(s->src_desc->flags & AV_PIX_FMT_FLAG_BE);
  713. + unsigned dst_by = ((s->dst_desc->comp[i].depth + 7) / 8) - 1;
  714. + unsigned src_by = ((s->src_desc->comp[i].depth + 7) / 8) - 1;
  715. + unsigned dst_so = UINT_MAX, src_so = UINT_MAX;
  716. +
  717. + for (int j = 0; j < FF_ARRAY_ELEMS(step_offset_tab); j++) {
  718. + if (step_offset_tab[j][0] == s->dst_desc->comp[i].step &&
  719. + step_offset_tab[j][1] == s->dst_desc->comp[i].offset) {
  720. + dst_so = j;
  721. + break;
  722. + }
  723. + }
  724. +
  725. + for (int j = 0; j < FF_ARRAY_ELEMS(step_offset_tab); j++) {
  726. + if (step_offset_tab[j][0] == s->src_desc->comp[i].step &&
  727. + step_offset_tab[j][1] == s->src_desc->comp[i].offset) {
  728. + src_so = j;
  729. + break;
  730. + }
  731. + }
  732. +
  733. + if (src_so >= 3 || dst_so >= 3) {
  734. + printf("%d %d\n", src_so, dst_so);
  735. + continue;
  736. + }
  737. +
  738. + if (src_so == UINT_MAX || dst_so == UINT_MAX)
  739. + continue;
  740. +
  741. + s->fun[i] = s->special[src_by][src_be][src_so][dst_by][dst_be][dst_so];
  742. + }
  743. +
  744. + if ((ret = av_image_fill_linesizes(s->linesize, outlink->format, inlink->w)) < 0)
  745. + return ret;
  746. +
  747. + if (s->dst_desc->comp[0].depth > 8) {
  748. + if (s->src_desc->comp[0].depth > 8) {
  749. + if (s->dst_desc->flags & AV_PIX_FMT_FLAG_BE) {
  750. + if (s->src_desc->flags & AV_PIX_FMT_FLAG_BE) {
  751. + s->do_pf2pf = pf2pf_u16_1_to_u16_1;
  752. + } else {
  753. + s->do_pf2pf = pf2pf_u16_0_to_u16_1;
  754. + }
  755. + } else {
  756. + if (s->src_desc->flags & AV_PIX_FMT_FLAG_BE) {
  757. + s->do_pf2pf = pf2pf_u16_1_to_u16_0;
  758. + } else {
  759. + s->do_pf2pf = pf2pf_u16_0_to_u16_0;
  760. + }
  761. + }
  762. + } else {
  763. + if (s->dst_desc->flags & AV_PIX_FMT_FLAG_BE) {
  764. + s->do_pf2pf = pf2pf_u8_0_to_u16_1;
  765. + } else {
  766. + s->do_pf2pf = pf2pf_u8_0_to_u16_0;
  767. + }
  768. + }
  769. + } else {
  770. + if (s->src_desc->comp[0].depth > 8) {
  771. + if (s->src_desc->flags & AV_PIX_FMT_FLAG_BE) {
  772. + s->do_pf2pf = pf2pf_u16_1_to_u8_0;
  773. + } else {
  774. + s->do_pf2pf = pf2pf_u16_0_to_u8_0;
  775. + }
  776. + } else {
  777. + s->do_pf2pf = pf2pf_u8_0_to_u8_0;
  778. + }
  779. + }
  780. +
  781. + return 0;
  782. +}
  783. +
  784. +static int filter_frame(AVFilterLink *inlink, AVFrame *in)
  785. +{
  786. + AVFilterContext *ctx = inlink->dst;
  787. + AVFilterLink *outlink = ctx->outputs[0];
  788. + PF2PFContext *s = ctx->priv;
  789. + AVFrame *out;
  790. +
  791. + if (s->pass) {
  792. + out = in;
  793. + } else {
  794. + ThreadData td;
  795. + int nb_jobs;
  796. +
  797. + out = ff_get_video_buffer(outlink, in->width, in->height);
  798. + if (!out) {
  799. + av_frame_free(&in);
  800. + return AVERROR(ENOMEM);
  801. + }
  802. +
  803. + td.in = in;
  804. + td.out = out;
  805. +
  806. + nb_jobs = in->height;
  807. +
  808. + ff_filter_execute(ctx, s->do_pf2pf, &td, NULL,
  809. + FFMIN(nb_jobs, ff_filter_get_nb_threads(ctx)));
  810. +
  811. + av_frame_copy_props(out, in);
  812. + av_frame_free(&in);
  813. + }
  814. +
  815. + return ff_filter_frame(outlink, out);
  816. +}
  817. +
  818. +static int activate(AVFilterContext *ctx)
  819. +{
  820. + AVFilterLink *inlink = ctx->inputs[0];
  821. + AVFilterLink *outlink = ctx->outputs[0];
  822. + AVFrame *in;
  823. + int ret;
  824. +
  825. + FF_FILTER_FORWARD_STATUS_BACK(outlink, inlink);
  826. +
  827. + ret = ff_inlink_consume_frame(inlink, &in);
  828. + if (ret < 0)
  829. + return ret;
  830. + if (ret > 0)
  831. + return filter_frame(inlink, in);
  832. +
  833. + FF_FILTER_FORWARD_STATUS(inlink, outlink);
  834. + FF_FILTER_FORWARD_WANTED(outlink, inlink);
  835. +
  836. + return FFERROR_NOT_READY;
  837. +}
  838. +
  839. +static AVFrame *get_in_video_buffer(AVFilterLink *inlink, int w, int h)
  840. +{
  841. + AVFilterContext *ctx = inlink->dst;
  842. + PF2PFContext *s = ctx->priv;
  843. +
  844. + return s->pass ?
  845. + ff_null_get_video_buffer (inlink, w, h) :
  846. + ff_default_get_video_buffer(inlink, w, h);
  847. +}
  848. +
  849. +static AVFrame *get_out_video_buffer(AVFilterLink *outlink, int w, int h)
  850. +{
  851. + AVFilterContext *ctx = outlink->src;
  852. + PF2PFContext *s = ctx->priv;
  853. +
  854. + return s->pass ?
  855. + ff_null_get_video_buffer (outlink, w, h) :
  856. + ff_default_get_video_buffer(outlink, w, h);
  857. +}
  858. +
  859. +static const AVFilterPad inputs[] = {
  860. + {
  861. + .name = "default",
  862. + .type = AVMEDIA_TYPE_VIDEO,
  863. + .get_buffer.video = get_in_video_buffer,
  864. + },
  865. +};
  866. +
  867. +static const AVFilterPad outputs[] = {
  868. + {
  869. + .name = "default",
  870. + .type = AVMEDIA_TYPE_VIDEO,
  871. + .config_props = config_output,
  872. + .get_buffer.video = get_out_video_buffer,
  873. + },
  874. +};
  875. +
  876. +const FFFilter ff_vf_pf2pf = {
  877. + .p.name = "pf2pf",
  878. + .p.description = NULL_IF_CONFIG_SMALL("Switch video pixel format."),
  879. + .p.priv_class = &pf2pf_class,
  880. + .priv_size = sizeof(PF2PFContext),
  881. + .activate = activate,
  882. + FILTER_QUERY_FUNC2(query_formats),
  883. + FILTER_INPUTS(inputs),
  884. + FILTER_OUTPUTS(outputs),
  885. + .p.flags = AVFILTER_FLAG_SLICE_THREADS,
  886. +};
  887. diff --git a/libavutil/imgutils.c b/libavutil/imgutils.c
  888. index 119372e418..2b1dc10215 100644
  889. --- a/libavutil/imgutils.c
  890. +++ b/libavutil/imgutils.c
  891. @@ -35,12 +35,11 @@
  892. void av_image_fill_max_pixsteps(int max_pixsteps[4], int max_pixstep_comps[4],
  893. const AVPixFmtDescriptor *pixdesc)
  894. {
  895. - int i;
  896. memset(max_pixsteps, 0, 4*sizeof(max_pixsteps[0]));
  897. if (max_pixstep_comps)
  898. memset(max_pixstep_comps, 0, 4*sizeof(max_pixstep_comps[0]));
  899.  
  900. - for (i = 0; i < 4; i++) {
  901. + for (int i = 0; i < pixdesc->nb_components; i++) {
  902. const AVComponentDescriptor *comp = &(pixdesc->comp[i]);
  903. if (comp->step > max_pixsteps[comp->plane]) {
  904. max_pixsteps[comp->plane] = comp->step;
  905. --
  906. 2.47.1
  907.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement