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.
Showing the changes to libavdevice/decklink_dec.cpp (1 of 1 file). Show all
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"); |