]> git.sesse.net Git - casparcg/blob - modules/ffmpeg/producer/filter/parallel_yadif.cpp
2.0. Renamed scalable_yadif to parallel_yadif.
[casparcg] / modules / ffmpeg / producer / filter / parallel_yadif.cpp
1 #include "../../StdAfx.h"\r
2 \r
3 #include "parallel_yadif.h"\r
4 \r
5 extern "C" \r
6 {\r
7         #include <libavfilter/avfilter.h>\r
8 }\r
9 \r
10 #include <boost/thread/once.hpp>\r
11 \r
12 typedef struct {\r
13     int mode;\r
14     int parity;\r
15     int frame_pending;\r
16     int auto_enable;\r
17     AVFilterBufferRef *cur;\r
18     AVFilterBufferRef *next;\r
19     AVFilterBufferRef *prev;\r
20     AVFilterBufferRef *out;\r
21     void (*filter_line)(uint8_t *dst,\r
22                         uint8_t *prev, uint8_t *cur, uint8_t *next,\r
23                         int w, int prefs, int mrefs, int parity, int mode);\r
24     //const AVPixFmtDescriptor *csp;\r
25 } YADIFContext;\r
26 \r
27 struct parallel_yadif_context\r
28 {\r
29         struct arg\r
30         {\r
31                 uint8_t *dst;\r
32                 uint8_t *prev;\r
33                 uint8_t *cur; \r
34                 uint8_t *next; \r
35                 int w; \r
36                 int prefs; \r
37                 int mrefs;\r
38                 int parity;\r
39                 int mode;\r
40         };\r
41 \r
42         arg     args[64];\r
43         int     index;\r
44 \r
45         parallel_yadif_context() : index(0){}\r
46 };\r
47 \r
48 void (*org_yadif_filter_line)(uint8_t *dst, uint8_t *prev, uint8_t *cur, uint8_t *next, int w, int prefs, int mrefs, int parity, int mode) = 0;\r
49 \r
50 void parallel_yadif_filter_line(parallel_yadif_context& ctx, uint8_t *dst, uint8_t *prev, uint8_t *cur, uint8_t *next, int w, int prefs, int mrefs, int parity, int mode)\r
51 {\r
52         parallel_yadif_context::arg arg = {dst, prev, cur, next, w, prefs, mrefs, parity, mode};\r
53         ctx.args[ctx.index++] = arg;\r
54         \r
55         if(ctx.index == 64)\r
56         {               \r
57                 tbb::parallel_for(tbb::blocked_range<size_t>(0, ctx.index), [=](const tbb::blocked_range<size_t>& r)\r
58                 {\r
59                         for(auto n = r.begin(); n != r.end(); ++n)\r
60                                 org_yadif_filter_line(ctx.args[n].dst, ctx.args[n].prev, ctx.args[n].cur, ctx.args[n].next, ctx.args[n].w, ctx.args[n].prefs, ctx.args[n].mrefs, ctx.args[n].parity, ctx.args[n].mode);\r
61                 });\r
62                 ctx.index = 0;\r
63         }\r
64 }\r
65 \r
66 #define RENAME(a) f ## a\r
67 \r
68 #define ff(x) \\r
69 void RENAME(x)(uint8_t *dst, uint8_t *prev, uint8_t *cur, uint8_t *next, int w, int prefs, int mrefs, int parity, int mode) \\r
70 {\\r
71         static parallel_yadif_context ctx;\\r
72         parallel_yadif_filter_line(ctx, dst, prev, cur, next, w, prefs, mrefs, parity, mode);\\r
73 }\r
74 \r
75 ff(0); ff(1); ff(2); ff(3); ff(4); ff(5); ff(6); ff(7); ff(8); ff(9); ff(10); ff(11); ff(12); ff(13); ff(14); ff(15); ff(16); ff(17);\r
76 \r
77 void (*fs[])(uint8_t *dst, uint8_t *prev, uint8_t *cur, uint8_t *next, int w, int prefs, int mrefs, int parity, int mode) = \r
78 \r
79 {f0, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, f13, f14, f15, f16, f17};\r
80 \r
81 namespace caspar {\r
82         \r
83 tbb::concurrent_bounded_queue<int> tags;\r
84 \r
85 void init_pool()\r
86 {\r
87         for(int n = 0; n < 18; ++n)\r
88                 tags.push(n);\r
89 }\r
90 \r
91 int init(AVFilterContext* ctx)\r
92 {\r
93         static boost::once_flag flag = BOOST_ONCE_INIT;\r
94         boost::call_once(&init_pool, flag);\r
95 \r
96         YADIFContext* yadif = (YADIFContext*)ctx->priv;\r
97         org_yadif_filter_line = yadif->filter_line; // Data race is not a problem.\r
98 \r
99         int tag;\r
100         if(!tags.try_pop(tag))\r
101         {\r
102                 CASPAR_LOG(warning) << "Not enough scalable-yadif instances. Running non-scalable";\r
103                 return -1;\r
104         }\r
105 \r
106         yadif->filter_line = fs[tag];\r
107         return tag;\r
108 }\r
109 \r
110 void uninit(int tag)\r
111 {\r
112         if(tag != -1)\r
113                 tags.push(tag);\r
114 }\r
115 \r
116 }