From 643123b29d4072f27be9b348d03069b648dbddf9 Mon Sep 17 00:00:00 2001 From: Marton Balint Date: Mon, 4 Jun 2018 10:02:46 +0200 Subject: [PATCH] avdevice/decklink_dec: use a custom memory allocator 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. Signed-off-by: Marton Balint --- libavdevice/decklink_dec.cpp | 50 ++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/libavdevice/decklink_dec.cpp b/libavdevice/decklink_dec.cpp index 510637676c..897fca1003 100644 --- a/libavdevice/decklink_dec.cpp +++ b/libavdevice/decklink_dec.cpp @@ -21,6 +21,9 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include +using std::atomic; + /* Include internal.h first to avoid conflict between winsock.h (used by * DeckLink headers) and winsock2.h (used by libavformat) in MSVC++ builds */ extern "C" { @@ -98,6 +101,44 @@ static VANCLineNumber vanc_line_numbers[] = { {bmdModeUnknown, 0, -1, -1, -1} }; +class decklink_allocator : public IDeckLinkMemoryAllocator +{ +public: + decklink_allocator(): _refs(1) { } + virtual ~decklink_allocator() { } + + // IDeckLinkMemoryAllocator methods + virtual HRESULT STDMETHODCALLTYPE AllocateBuffer(unsigned int bufferSize, void* *allocatedBuffer) + { + void *buf = av_malloc(bufferSize + AV_INPUT_BUFFER_PADDING_SIZE); + if (!buf) + return E_OUTOFMEMORY; + *allocatedBuffer = buf; + return S_OK; + } + virtual HRESULT STDMETHODCALLTYPE ReleaseBuffer(void* buffer) + { + av_free(buffer); + return S_OK; + } + virtual HRESULT STDMETHODCALLTYPE Commit() { return S_OK; } + virtual HRESULT STDMETHODCALLTYPE Decommit() { return S_OK; } + + // IUnknown methods + virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, LPVOID *ppv) { return E_NOINTERFACE; } + virtual ULONG STDMETHODCALLTYPE AddRef(void) { return ++_refs; } + virtual ULONG STDMETHODCALLTYPE Release(void) + { + int ret = --_refs; + if (!ret) + delete this; + return ret; + } + +private: + std::atomic _refs; +}; + extern "C" { static void decklink_object_free(void *opaque, uint8_t *data) { @@ -924,6 +965,7 @@ av_cold int ff_decklink_read_header(AVFormatContext *avctx) { struct decklink_cctx *cctx = (struct decklink_cctx *)avctx->priv_data; struct decklink_ctx *ctx; + class decklink_allocator *allocator; AVStream *st; HRESULT result; char fname[1024]; @@ -1017,6 +1059,14 @@ av_cold int ff_decklink_read_header(AVFormatContext *avctx) ctx->input_callback = new decklink_input_callback(avctx); ctx->dli->SetCallback(ctx->input_callback); + allocator = new decklink_allocator(); + ret = (ctx->dli->SetVideoInputFrameMemoryAllocator(allocator) == S_OK ? 0 : AVERROR_EXTERNAL); + allocator->Release(); + if (ret < 0) { + av_log(avctx, AV_LOG_ERROR, "Cannot set custom memory allocator\n"); + goto error; + } + if (mode_num == 0 && !cctx->format_code) { if (decklink_autodetect(cctx) < 0) { av_log(avctx, AV_LOG_ERROR, "Cannot Autodetect input stream or No signal\n");