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 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | 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 | /* Include internal.h first to avoid conflict between winsock.h (used by | 27 | /* Include internal.h first to avoid conflict between winsock.h (used by |
| 25 | * DeckLink headers) and winsock2.h (used by libavformat) in MSVC++ builds */ | 28 | * DeckLink headers) and winsock2.h (used by libavformat) in MSVC++ builds */ |
| 26 | extern "C" { | 29 | extern "C" { |
| @@ -98,6 +101,44 @@ static VANCLineNumber vanc_line_numbers[] = { · 71 unmodified lines | |||
| 98 | {bmdModeUnknown, 0, -1, -1, -1} | 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 | extern "C" { | 142 | extern "C" { |
| 102 | static void decklink_object_free(void *opaque, uint8_t *data) | 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 | struct decklink_cctx *cctx = (struct decklink_cctx *)avctx->priv_data; | 966 | struct decklink_cctx *cctx = (struct decklink_cctx *)avctx->priv_data; |
| 926 | struct decklink_ctx *ctx; | 967 | struct decklink_ctx *ctx; |
| 968 | class decklink_allocator *allocator; | ||
| 927 | AVStream *st; | 969 | AVStream *st; |
| 928 | HRESULT result; | 970 | HRESULT result; |
| 929 | char fname[1024]; | 971 | char fname[1024]; |
| @@ -1017,6 +1059,14 @@ av_cold int ff_decklink_read_header(AVFormatContext *avctx) · 87 unmodified lines | |||
| 1017 | ctx->input_callback = new decklink_input_callback(avctx); | 1059 | ctx->input_callback = new decklink_input_callback(avctx); |
| 1018 | ctx->dli->SetCallback(ctx->input_callback); | 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 | if (mode_num == 0 && !cctx->format_code) { | 1070 | if (mode_num == 0 && !cctx->format_code) { |
| 1021 | if (decklink_autodetect(cctx) < 0) { | 1071 | if (decklink_autodetect(cctx) < 0) { |
| 1022 | av_log(avctx, AV_LOG_ERROR, "Cannot Autodetect input stream or No signal\n"); | 1072 | av_log(avctx, AV_LOG_ERROR, "Cannot Autodetect input stream or No signal\n"); |