]> git.sesse.net Git - casparcg/blobdiff - modules/ffmpeg/producer/tbb_avcodec.cpp
[ffmpeg] Remove usage of deprecated API usage to easier support a newer version of...
[casparcg] / modules / ffmpeg / producer / tbb_avcodec.cpp
index 2e21622379b26886664d4a5e0e3b49aa59561fa8..44857ccf3e93d96347b501f2af0b4e37138e9832 100644 (file)
-/*\r
-* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
-*\r
-* This file is part of CasparCG (www.casparcg.com).\r
-*\r
-* CasparCG is free software: you can redistribute it and/or modify\r
-* it under the terms of the GNU General Public License as published by\r
-* the Free Software Foundation, either version 3 of the License, or\r
-* (at your option) any later version.\r
-*\r
-* CasparCG is distributed in the hope that it will be useful,\r
-* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
-* GNU General Public License for more details.\r
-*\r
-* You should have received a copy of the GNU General Public License\r
-* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
-*\r
-* Author: Robert Nagy, ronag89@gmail.com\r
-*/\r
-\r
-#include "../stdafx.h"\r
-\r
-#include "tbb_avcodec.h"\r
-\r
-#include <common/assert.h>\r
-#include <common/log.h>\r
-#include <common/env.h>\r
-\r
-#include <tbb/atomic.h>\r
-#include <tbb/parallel_for.h>\r
-#include <tbb/tbb_thread.h>\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
-               \r
-int thread_execute(AVCodecContext* s, int (*func)(AVCodecContext *c2, void *arg2), void* arg, int* ret, int count, int size)\r
-{\r
-       tbb::parallel_for(0, count, 1, [&](int i)\r
-       {\r
-        int r = func(s, (char*)arg + i*size);\r
-        if(ret) \r
-                       ret[i] = r;\r
-    });\r
-\r
-       return 0;\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
-       CASPAR_VERIFY(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
-       static const size_t MAX_THREADS = 16; // See mpegvideo.h\r
-       static int dummy_opaque;\r
-\r
-    s->active_thread_type = FF_THREAD_SLICE;\r
-       s->thread_opaque          = &dummy_opaque; \r
-    s->execute                   = thread_execute;\r
-    s->execute2                          = thread_execute2;\r
-    s->thread_count              = MAX_THREADS; // We are using a task-scheduler, so use as many "threads/tasks" as possible. \r
-}\r
-\r
-void thread_free(AVCodecContext* s)\r
-{\r
-       if(!s->thread_opaque)\r
-               return;\r
-\r
-       s->thread_opaque = nullptr;\r
-}\r
-\r
-int tbb_avcodec_open(AVCodecContext* avctx, AVCodec* codec)\r
-{\r
-       //CodecID supported_codecs[] = {CODEC_ID_MPEG2VIDEO, CODEC_ID_PRORES, CODEC_ID_FFV1};\r
-\r
-       avctx->thread_count = 1;\r
-       // Some codecs don't like to have multiple multithreaded decoding instances. Only enable for those we know work.\r
-       if(//std::find(std::begin(supported_codecs), std::end(supported_codecs), codec->id) != std::end(supported_codecs) && \r
-         (codec->capabilities & CODEC_CAP_SLICE_THREADS) && \r
-         (avctx->thread_type & FF_THREAD_SLICE)) \r
-       {\r
-               thread_init(avctx);\r
-       }       \r
-       // ff_thread_init will not be executed since thread_opaque != nullptr || thread_count == 1.\r
-       return avcodec_open(avctx, codec); \r
-}\r
-\r
-int tbb_avcodec_close(AVCodecContext* avctx)\r
-{\r
-       thread_free(avctx);\r
-       // ff_thread_free will not be executed since thread_opaque == nullptr.\r
-       return avcodec_close(avctx); \r
-}\r
-\r
-}
\ No newline at end of file
+/*
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>
+*
+* This file is part of CasparCG (www.casparcg.com).
+*
+* CasparCG is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* CasparCG is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.
+*
+* Author: Robert Nagy, ronag89@gmail.com
+*/
+
+#include "../StdAfx.h"
+
+#include "tbb_avcodec.h"
+
+#include <common/assert.h>
+#include <common/except.h>
+#include <common/log.h>
+#include <common/env.h>
+
+#include <tbb/atomic.h>
+#include <tbb/parallel_for.h>
+#include <tbb/tbb_thread.h>
+
+#if defined(_MSC_VER)
+#pragma warning (push)
+#pragma warning (disable : 4244)
+#endif
+extern "C"
+{
+       #define __STDC_CONSTANT_MACROS
+       #define __STDC_LIMIT_MACROS
+       #include <libavformat/avformat.h>
+}
+#if defined(_MSC_VER)
+#pragma warning (pop)
+#endif
+
+namespace caspar {
+
+static const int MAX_THREADS = 16; // See mpegvideo.h
+
+int thread_execute(AVCodecContext* s, int (*func)(AVCodecContext *c2, void *arg2), void* arg, int* ret, int count, int size)
+{
+       tbb::parallel_for(0, count, 1, [&](int i)
+       {
+        int r = func(s, (char*)arg + i*size);
+        if(ret)
+                       ret[i] = r;
+    });
+
+       return 0;
+}
+
+int thread_execute2(AVCodecContext* s, int (*func)(AVCodecContext* c2, void* arg2, int, int), void* arg, int* ret, int count)
+{
+       // TODO: Micro-optimize...
+
+       std::array<std::vector<int>, 16> jobs;
+
+       for(int n = 0; n < count; ++n)
+               jobs[(n*MAX_THREADS) / count].push_back(n);
+
+       tbb::parallel_for(0, MAX_THREADS, [&](int n)
+    {
+               for (auto k : jobs[n])
+               {
+                       int r = func(s, arg, k, n);
+                       if(ret)
+                               ret[k]= r;
+               }
+    });
+
+       return 0;
+}
+
+void thread_init(AVCodecContext* s)
+{
+       static int dummy_opaque;
+
+    s->active_thread_type      = FF_THREAD_SLICE;
+       s->opaque                               = &dummy_opaque;
+    s->execute                         = thread_execute;
+    s->execute2                                = thread_execute2;
+    s->thread_count                    = MAX_THREADS; // We are using a task-scheduler, so use as many "threads/tasks" as possible.
+}
+
+void thread_free(AVCodecContext* s)
+{
+       if(!s->opaque)
+               return;
+
+       s->opaque = nullptr;
+}
+
+int tbb_avcodec_open(AVCodecContext* avctx, AVCodec* codec, bool single_threaded)
+{
+       if(codec->capabilities & CODEC_CAP_EXPERIMENTAL)
+               CASPAR_THROW_EXCEPTION(invalid_argument() << msg_info("Experimental codecs are not supported."));
+
+       avctx->thread_count = 1;
+
+       if(!single_threaded && codec->capabilities & CODEC_CAP_SLICE_THREADS)
+               thread_init(avctx);
+
+       // ff_thread_init will not be executed since thread_opaque != nullptr || thread_count == 1.
+       return avcodec_open2(avctx, codec, nullptr);
+}
+
+int tbb_avcodec_close(AVCodecContext* avctx)
+{
+       thread_free(avctx);
+       // ff_thread_free will not be executed since thread_opaque == nullptr.
+       return avcodec_close(avctx);
+}
+
+}