The default memory allocator is limited in the max number of frames available, and therefore caused frame drops if the frames were not freed fast enough.
Unified · Split
| @@ -21,6 +21,9 @@ · 20 unmodified lines | ||
| 21 | 21 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
| 22 | 22 | */ |
| 23 | 23 | |
| 24 | +#include <atomic> | |
| 25 | +using std::atomic; | |
| 26 | + | |
| 24 | 27 | /* Include internal.h first to avoid conflict between winsock.h (used by |
| 25 | 28 | * DeckLink headers) and winsock2.h (used by libavformat) in MSVC++ builds */ |
| 26 | 29 | extern "C" { |
| @@ -98,6 +101,44 @@ static VANCLineNumber vanc_line_numbers[] = { · 71 unmodified lines | ||
| 98 | 101 | {bmdModeUnknown, 0, -1, -1, -1} |
| 99 | 102 | }; |
| 100 | 103 | |
| 104 | +class decklink_allocator : public IDeckLinkMemoryAllocator | |
| 105 | +{ | |
| 106 | +public: | |
| 107 | + decklink_allocator(): _refs(1) { } | |
| 108 | + virtual ~decklink_allocator() { } | |
| 109 | + | |
| 110 | + // IDeckLinkMemoryAllocator methods | |
| 111 | + virtual HRESULT STDMETHODCALLTYPE AllocateBuffer(unsigned int bufferSize, void* *allocatedBuffer) | |
| 112 | + { | |
| 113 | + void *buf = av_malloc(bufferSize + AV_INPUT_BUFFER_PADDING_SIZE); | |
| 114 | + if (!buf) | |
| 115 | + return E_OUTOFMEMORY; | |
| 116 | + *allocatedBuffer = buf; | |
| 117 | + return S_OK; | |
| 118 | + } | |
| 119 | + virtual HRESULT STDMETHODCALLTYPE ReleaseBuffer(void* buffer) | |
| 120 | + { | |
| 121 | + av_free(buffer); | |
| 122 | + return S_OK; | |
| 123 | + } | |
| 124 | + virtual HRESULT STDMETHODCALLTYPE Commit() { return S_OK; } | |
| 125 | + virtual HRESULT STDMETHODCALLTYPE Decommit() { return S_OK; } | |
| 126 | + | |
| 127 | + // IUnknown methods | |
| 128 | + virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, LPVOID *ppv) { return E_NOINTERFACE; } | |
| 129 | + virtual ULONG STDMETHODCALLTYPE AddRef(void) { return ++_refs; } | |
| 130 | + virtual ULONG STDMETHODCALLTYPE Release(void) | |
| 131 | + { | |
| 132 | + int ret = --_refs; | |
| 133 | + if (!ret) | |
| 134 | + delete this; | |
| 135 | + return ret; | |
| 136 | + } | |
| 137 | + | |
| 138 | +private: | |
| 139 | + std::atomic<int> _refs; | |
| 140 | +}; | |
| 141 | + | |
| 101 | 142 | extern "C" { |
| 102 | 143 | static void decklink_object_free(void *opaque, uint8_t *data) |
| 103 | 144 | { |
| @@ -924,6 +965,7 @@ av_cold int ff_decklink_read_header(AVFormatContext *avctx) · 820 unmodified lines | ||
| 924 | 965 | { |
| 925 | 966 | struct decklink_cctx *cctx = (struct decklink_cctx *)avctx->priv_data; |
| 926 | 967 | struct decklink_ctx *ctx; |
| 968 | + class decklink_allocator *allocator; | |
| 927 | 969 | AVStream *st; |
| 928 | 970 | HRESULT result; |
| 929 | 971 | char fname[1024]; |
| @@ -1017,6 +1059,14 @@ av_cold int ff_decklink_read_header(AVFormatContext *avctx) · 87 unmodified lines | ||
| 1017 | 1059 | ctx->input_callback = new decklink_input_callback(avctx); |
| 1018 | 1060 | ctx->dli->SetCallback(ctx->input_callback); |
| 1019 | 1061 | |
| 1062 | + allocator = new decklink_allocator(); | |
| 1063 | + ret = (ctx->dli->SetVideoInputFrameMemoryAllocator(allocator) == S_OK ? 0 : AVERROR_EXTERNAL); | |
| 1064 | + allocator->Release(); | |
| 1065 | + if (ret < 0) { | |
| 1066 | + av_log(avctx, AV_LOG_ERROR, "Cannot set custom memory allocator\n"); | |
| 1067 | + goto error; | |
| 1068 | + } | |
| 1069 | + | |
| 1020 | 1070 | if (mode_num == 0 && !cctx->format_code) { |
| 1021 | 1071 | if (decklink_autodetect(cctx) < 0) { |
| 1022 | 1072 | av_log(avctx, AV_LOG_ERROR, "Cannot Autodetect input stream or No signal\n"); |