\r
#include <common/log/log.h>\r
#include <common/env.h>\r
+#include <common/utility/assert.h>\r
\r
#include <tbb/task.h>\r
#include <tbb/atomic.h>\r
+#include <tbb/parallel_for.h>\r
+#include <tbb/tbb_thread.h>\r
\r
-#include <regex>\r
-#include <boost/algorithm/string.hpp>\r
-\r
+#if defined(_MSC_VER)\r
+#pragma warning (push)\r
+#pragma warning (disable : 4244)\r
+#endif\r
extern "C" \r
{\r
#define __STDC_CONSTANT_MACROS\r
#define __STDC_LIMIT_MACROS\r
#include <libavformat/avformat.h>\r
}\r
+#if defined(_MSC_VER)\r
+#pragma warning (pop)\r
+#endif\r
\r
-namespace caspar {\r
+namespace caspar { namespace ffmpeg {\r
\r
int thread_execute(AVCodecContext* s, int (*func)(AVCodecContext *c2, void *arg2), void* arg, int* ret, int count, int size)\r
{\r
\r
int thread_execute2(AVCodecContext* s, int (*func)(AVCodecContext* c2, void* arg2, int, int), void* arg, int* ret, int count)\r
{ \r
- tbb::atomic<int> counter;\r
- counter = 0;\r
- \r
- // Execute s->thread_count number of tasks in parallel.\r
- tbb::parallel_for(0, s->thread_count, 1, [&](int threadnr) \r
- {\r
- while(true)\r
- {\r
- int jobnr = counter++;\r
- if(jobnr >= count)\r
- break;\r
-\r
- int r = func(s, arg, jobnr, threadnr);\r
- if (ret)\r
- ret[jobnr] = r;\r
- }\r
- });\r
-\r
- return 0;\r
+ tbb::atomic<int> counter; \r
+ counter = 0; \r
+\r
+ CASPAR_ASSERT(tbb::tbb_thread::hardware_concurrency() < 16);\r
+ // Note: this will probably only work when tbb::task_scheduler_init::num_threads() < 16.\r
+ tbb::parallel_for(tbb::blocked_range<int>(0, count, 2), [&](const tbb::blocked_range<int> &r) \r
+ { \r
+ int threadnr = counter++; \r
+ for(int jobnr = r.begin(); jobnr != r.end(); ++jobnr)\r
+ { \r
+ int r = func(s, arg, jobnr, threadnr); \r
+ if (ret) \r
+ ret[jobnr] = r; \r
+ }\r
+ --counter;\r
+ }); \r
+\r
+ return 0; \r
}\r
\r
void thread_init(AVCodecContext* s)\r
\r
void thread_free(AVCodecContext* s)\r
{\r
- s->thread_opaque = nullptr;\r
+ if(!s->thread_opaque)\r
+ return;\r
\r
+ s->thread_opaque = nullptr;\r
+ \r
CASPAR_LOG(info) << "Released ffmpeg tbb context.";\r
}\r
\r
-std::regex get_slice_regex()\r
-{\r
- auto s = env::properties().get("configuration.ffmpeg.slice-threads-regex", "");\r
- boost::algorithm::erase_all(s, " ");\r
- boost::algorithm::erase_all(s, "\n");\r
- return std::regex(s);\r
-}\r
-\r
-bool allow_slice_thread(int id)\r
-{\r
- static std::regex e = get_slice_regex();\r
- return std::regex_match(boost::lexical_cast<std::string>(id), e);\r
-}\r
-\r
int tbb_avcodec_open(AVCodecContext* avctx, AVCodec* codec)\r
{\r
- auto id = codec->id;\r
avctx->thread_count = 1;\r
- if(allow_slice_thread(id) && // Some codecs don't like to have multiple multithreaded decoding instances. Only enable for those we know work.\r
+ // Some codecs don't like to have multiple multithreaded decoding instances. Only enable for those we know work.\r
+ if((codec->id == CODEC_ID_MPEG2VIDEO) && \r
(codec->capabilities & CODEC_CAP_SLICE_THREADS) && \r
(avctx->thread_type & FF_THREAD_SLICE))\r
{\r
return avcodec_close(avctx); \r
}\r
\r
-}
\ No newline at end of file
+}}
\ No newline at end of file