fix(capture): proper SDK 16 patch via upstream FFmpeg master diff
The previous patch_decklink.py mixed v14_2_1 versioned types (Fix 1 renamed the allocator class) with no-ops for SetVideoInputFrameMemoryAllocator + QueryInterface-around-GetBytes (Fixes 2 & 3). That inconsistency compiled but silently dropped every video frame: VideoInputFrameArrived saw _v14_2_1 allocator output but tried to read it via the SDK 16 unversioned IDeckLinkVideoBuffer path, and the SDK released the buffer before FFmpeg could consume it.
Bisected with the BMD-provided Capture sample at SDK 16 mode 5 (Hp29) which got frames cleanly, confirming the signal was fine and the bug was in FFmpegs decklink demuxer.
Fix: pull libavdevice/decklink_{enc,dec,common}{.cpp,.h} from upstream FFmpeg master (commits past 7.1 that fully rename every decklink interface to its _v14_2_1 versioned form) and apply that diff in reverse during build. Now build is internally consistent and frames flow.
Verified: SDI1 recorder on zampp2 hits 423 frames in 14s @ 29 fps, ProRes HQ at 91 Mbps.
This commit is contained in:
parent
96f0f58e68
commit
30b4deffc6
3 changed files with 367 additions and 50 deletions
|
|
@ -11,6 +11,7 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
|
|||
# Copy in BMD DeckLink SDK headers and patch script
|
||||
COPY sdk/ /decklink-sdk/
|
||||
COPY patch_decklink.py /patch_decklink.py
|
||||
COPY decklink-sdk16.patch /decklink-sdk16.patch
|
||||
|
||||
# Pull FFmpeg 7.1 source
|
||||
RUN git clone --depth=1 --branch release/7.1 https://git.ffmpeg.org/ffmpeg.git /ffmpeg
|
||||
|
|
|
|||
346
services/capture/decklink-sdk16.patch
Normal file
346
services/capture/decklink-sdk16.patch
Normal file
|
|
@ -0,0 +1,346 @@
|
|||
diff --git a/libavdevice/decklink_common.cpp b/libavdevice/decklink_common.cpp
|
||||
index fe187cd..47de7ef 100644
|
||||
--- a/libavdevice/decklink_common.cpp
|
||||
+++ b/libavdevice/decklink_common.cpp
|
||||
@@ -25,12 +25,7 @@ extern "C" {
|
||||
#include "libavformat/internal.h"
|
||||
}
|
||||
|
||||
-#include <DeckLinkAPIVersion.h>
|
||||
#include <DeckLinkAPI.h>
|
||||
-#if BLACKMAGIC_DECKLINK_API_VERSION >= 0x0e030000
|
||||
-#include <DeckLinkAPI_v14_2_1.h>
|
||||
-#endif
|
||||
-
|
||||
#ifdef _WIN32
|
||||
#include <DeckLinkAPI_i.c>
|
||||
#else
|
||||
@@ -517,8 +512,8 @@ int ff_decklink_list_devices(AVFormatContext *avctx,
|
||||
return AVERROR(EIO);
|
||||
|
||||
while (ret == 0 && iter->Next(&dl) == S_OK) {
|
||||
- IDeckLinkOutput_v14_2_1 *output_config;
|
||||
- IDeckLinkInput_v14_2_1 *input_config;
|
||||
+ IDeckLinkOutput *output_config;
|
||||
+ IDeckLinkInput *input_config;
|
||||
const char *display_name = NULL;
|
||||
const char *unique_name = NULL;
|
||||
AVDeviceInfo *new_device = NULL;
|
||||
@@ -532,14 +527,14 @@ int ff_decklink_list_devices(AVFormatContext *avctx,
|
||||
goto next;
|
||||
|
||||
if (show_outputs) {
|
||||
- if (dl->QueryInterface(IID_IDeckLinkOutput_v14_2_1, (void **)&output_config) == S_OK) {
|
||||
+ if (dl->QueryInterface(IID_IDeckLinkOutput, (void **)&output_config) == S_OK) {
|
||||
output_config->Release();
|
||||
add = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (show_inputs) {
|
||||
- if (dl->QueryInterface(IID_IDeckLinkInput_v14_2_1, (void **)&input_config) == S_OK) {
|
||||
+ if (dl->QueryInterface(IID_IDeckLinkInput, (void **)&input_config) == S_OK) {
|
||||
input_config->Release();
|
||||
add = 1;
|
||||
}
|
||||
diff --git a/libavdevice/decklink_common.h b/libavdevice/decklink_common.h
|
||||
index 095b438..6b32dc2 100644
|
||||
--- a/libavdevice/decklink_common.h
|
||||
+++ b/libavdevice/decklink_common.h
|
||||
@@ -29,23 +29,6 @@
|
||||
#define IDeckLinkProfileAttributes IDeckLinkAttributes
|
||||
#endif
|
||||
|
||||
-#if BLACKMAGIC_DECKLINK_API_VERSION < 0x0e030000
|
||||
-#define IDeckLinkInput_v14_2_1 IDeckLinkInput
|
||||
-#define IDeckLinkInputCallback_v14_2_1 IDeckLinkInputCallback
|
||||
-#define IDeckLinkMemoryAllocator_v14_2_1 IDeckLinkMemoryAllocator
|
||||
-#define IDeckLinkOutput_v14_2_1 IDeckLinkOutput
|
||||
-#define IDeckLinkVideoFrame_v14_2_1 IDeckLinkVideoFrame
|
||||
-#define IDeckLinkVideoInputFrame_v14_2_1 IDeckLinkVideoInputFrame
|
||||
-#define IDeckLinkVideoOutputCallback_v14_2_1 IDeckLinkVideoOutputCallback
|
||||
-#define IID_IDeckLinkInput_v14_2_1 IID_IDeckLinkInput
|
||||
-#define IID_IDeckLinkInputCallback_v14_2_1 IID_IDeckLinkInputCallback
|
||||
-#define IID_IDeckLinkMemoryAllocator_v14_2_1 IID_IDeckLinkMemoryAllocator
|
||||
-#define IID_IDeckLinkOutput_v14_2_1 IID_IDeckLinkOutput
|
||||
-#define IID_IDeckLinkVideoFrame_v14_2_1 IID_IDeckLinkVideoFrame
|
||||
-#define IID_IDeckLinkVideoInputFrame_v14_2_1 IID_IDeckLinkVideoInputFrame
|
||||
-#define IID_IDeckLinkVideoOutputCallback_v14_2_1 IID_IDeckLinkVideoOutputCallback
|
||||
-#endif
|
||||
-
|
||||
extern "C" {
|
||||
#include "libavutil/mem.h"
|
||||
#include "libavcodec/packet_internal.h"
|
||||
@@ -93,16 +76,6 @@ static char *dup_cfstring_to_utf8(CFStringRef w)
|
||||
#define DECKLINK_FREE(s) free((void *) s)
|
||||
#endif
|
||||
|
||||
-#ifdef _WIN32
|
||||
-#include <guiddef.h> // REFIID, IsEqualIID()
|
||||
-#define DECKLINK_IsEqualIID IsEqualIID
|
||||
-#else
|
||||
-static inline bool DECKLINK_IsEqualIID(const REFIID& riid1, const REFIID& riid2)
|
||||
-{
|
||||
- return memcmp(&riid1, &riid2, sizeof(REFIID)) == 0;
|
||||
-}
|
||||
-#endif
|
||||
-
|
||||
class decklink_output_callback;
|
||||
class decklink_input_callback;
|
||||
|
||||
@@ -120,8 +93,8 @@ typedef struct DecklinkPacketQueue {
|
||||
struct decklink_ctx {
|
||||
/* DeckLink SDK interfaces */
|
||||
IDeckLink *dl;
|
||||
- IDeckLinkOutput_v14_2_1 *dlo;
|
||||
- IDeckLinkInput_v14_2_1 *dli;
|
||||
+ IDeckLinkOutput *dlo;
|
||||
+ IDeckLinkInput *dli;
|
||||
IDeckLinkConfiguration *cfg;
|
||||
IDeckLinkProfileAttributes *attr;
|
||||
decklink_output_callback *output_callback;
|
||||
diff --git a/libavdevice/decklink_dec.cpp b/libavdevice/decklink_dec.cpp
|
||||
index 8830779..418701e 100644
|
||||
--- a/libavdevice/decklink_dec.cpp
|
||||
+++ b/libavdevice/decklink_dec.cpp
|
||||
@@ -31,11 +31,7 @@ extern "C" {
|
||||
#include "libavformat/internal.h"
|
||||
}
|
||||
|
||||
-#include <DeckLinkAPIVersion.h>
|
||||
#include <DeckLinkAPI.h>
|
||||
-#if BLACKMAGIC_DECKLINK_API_VERSION >= 0x0e030000
|
||||
-#include <DeckLinkAPI_v14_2_1.h>
|
||||
-#endif
|
||||
|
||||
extern "C" {
|
||||
#include "config.h"
|
||||
@@ -109,7 +105,7 @@ static VANCLineNumber vanc_line_numbers[] = {
|
||||
{bmdModeUnknown, 0, -1, -1, -1}
|
||||
};
|
||||
|
||||
-class decklink_allocator : public IDeckLinkMemoryAllocator_v14_2_1
|
||||
+class decklink_allocator : public IDeckLinkMemoryAllocator
|
||||
{
|
||||
public:
|
||||
decklink_allocator(): _refs(1) { }
|
||||
@@ -133,21 +129,7 @@ public:
|
||||
virtual HRESULT STDMETHODCALLTYPE Decommit() { return S_OK; }
|
||||
|
||||
// IUnknown methods
|
||||
- virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, LPVOID *ppv)
|
||||
- {
|
||||
- if (DECKLINK_IsEqualIID(riid, IID_IUnknown)) {
|
||||
- *ppv = static_cast<IUnknown*>(this);
|
||||
- } else if (DECKLINK_IsEqualIID(riid, IID_IDeckLinkMemoryAllocator_v14_2_1)) {
|
||||
- *ppv = static_cast<IDeckLinkMemoryAllocator_v14_2_1*>(this);
|
||||
- } else {
|
||||
- *ppv = NULL;
|
||||
- return E_NOINTERFACE;
|
||||
- }
|
||||
-
|
||||
- AddRef();
|
||||
- return S_OK;
|
||||
- }
|
||||
-
|
||||
+ virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, LPVOID *ppv) { return E_NOINTERFACE; }
|
||||
virtual ULONG STDMETHODCALLTYPE AddRef(void) { return ++_refs; }
|
||||
virtual ULONG STDMETHODCALLTYPE Release(void)
|
||||
{
|
||||
@@ -490,7 +472,7 @@ skip_packet:
|
||||
}
|
||||
|
||||
|
||||
-static void handle_klv(AVFormatContext *avctx, decklink_ctx *ctx, IDeckLinkVideoInputFrame_v14_2_1 *videoFrame, int64_t pts)
|
||||
+static void handle_klv(AVFormatContext *avctx, decklink_ctx *ctx, IDeckLinkVideoInputFrame *videoFrame, int64_t pts)
|
||||
{
|
||||
const uint8_t KLV_DID = 0x44;
|
||||
const uint8_t KLV_IN_VANC_SDID = 0x04;
|
||||
@@ -592,30 +574,17 @@ static void handle_klv(AVFormatContext *avctx, decklink_ctx *ctx, IDeckLinkVideo
|
||||
}
|
||||
}
|
||||
|
||||
-class decklink_input_callback : public IDeckLinkInputCallback_v14_2_1
|
||||
+class decklink_input_callback : public IDeckLinkInputCallback
|
||||
{
|
||||
public:
|
||||
explicit decklink_input_callback(AVFormatContext *_avctx);
|
||||
~decklink_input_callback();
|
||||
|
||||
- virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, LPVOID *ppv)
|
||||
- {
|
||||
- if (DECKLINK_IsEqualIID(riid, IID_IUnknown)) {
|
||||
- *ppv = static_cast<IUnknown*>(this);
|
||||
- } else if (DECKLINK_IsEqualIID(riid, IID_IDeckLinkInputCallback_v14_2_1)) {
|
||||
- *ppv = static_cast<IDeckLinkInputCallback_v14_2_1*>(this);
|
||||
- } else {
|
||||
- *ppv = NULL;
|
||||
- return E_NOINTERFACE;
|
||||
- }
|
||||
-
|
||||
- AddRef();
|
||||
- return S_OK;
|
||||
- }
|
||||
+ virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, LPVOID *ppv) { return E_NOINTERFACE; }
|
||||
virtual ULONG STDMETHODCALLTYPE AddRef(void);
|
||||
virtual ULONG STDMETHODCALLTYPE Release(void);
|
||||
virtual HRESULT STDMETHODCALLTYPE VideoInputFormatChanged(BMDVideoInputFormatChangedEvents, IDeckLinkDisplayMode*, BMDDetectedVideoInputFormatFlags);
|
||||
- virtual HRESULT STDMETHODCALLTYPE VideoInputFrameArrived(IDeckLinkVideoInputFrame_v14_2_1*, IDeckLinkAudioInputPacket*);
|
||||
+ virtual HRESULT STDMETHODCALLTYPE VideoInputFrameArrived(IDeckLinkVideoInputFrame*, IDeckLinkAudioInputPacket*);
|
||||
|
||||
private:
|
||||
std::atomic<int> _refs;
|
||||
@@ -624,7 +593,7 @@ private:
|
||||
int no_video;
|
||||
int64_t initial_video_pts;
|
||||
int64_t initial_audio_pts;
|
||||
- IDeckLinkVideoInputFrame_v14_2_1* last_video_frame;
|
||||
+ IDeckLinkVideoInputFrame* last_video_frame;
|
||||
};
|
||||
|
||||
decklink_input_callback::decklink_input_callback(AVFormatContext *_avctx) : _refs(1)
|
||||
@@ -656,7 +625,7 @@ ULONG decklink_input_callback::Release(void)
|
||||
return ret;
|
||||
}
|
||||
|
||||
-static int64_t get_pkt_pts(IDeckLinkVideoInputFrame_v14_2_1 *videoFrame,
|
||||
+static int64_t get_pkt_pts(IDeckLinkVideoInputFrame *videoFrame,
|
||||
IDeckLinkAudioInputPacket *audioFrame,
|
||||
int64_t wallclock,
|
||||
int64_t abs_wallclock,
|
||||
@@ -710,7 +679,7 @@ static int64_t get_pkt_pts(IDeckLinkVideoInputFrame_v14_2_1 *videoFrame,
|
||||
return pts;
|
||||
}
|
||||
|
||||
-static int get_bmd_timecode(AVFormatContext *avctx, AVTimecode *tc, AVRational frame_rate, BMDTimecodeFormat tc_format, IDeckLinkVideoInputFrame_v14_2_1 *videoFrame)
|
||||
+static int get_bmd_timecode(AVFormatContext *avctx, AVTimecode *tc, AVRational frame_rate, BMDTimecodeFormat tc_format, IDeckLinkVideoInputFrame *videoFrame)
|
||||
{
|
||||
IDeckLinkTimecode *timecode;
|
||||
int ret = AVERROR(ENOENT);
|
||||
@@ -732,7 +701,7 @@ static int get_bmd_timecode(AVFormatContext *avctx, AVTimecode *tc, AVRational f
|
||||
return ret;
|
||||
}
|
||||
|
||||
-static int get_frame_timecode(AVFormatContext *avctx, decklink_ctx *ctx, AVTimecode *tc, IDeckLinkVideoInputFrame_v14_2_1 *videoFrame)
|
||||
+static int get_frame_timecode(AVFormatContext *avctx, decklink_ctx *ctx, AVTimecode *tc, IDeckLinkVideoInputFrame *videoFrame)
|
||||
{
|
||||
AVRational frame_rate = ctx->video_st->r_frame_rate;
|
||||
int ret;
|
||||
@@ -757,7 +726,7 @@ static int get_frame_timecode(AVFormatContext *avctx, decklink_ctx *ctx, AVTimec
|
||||
}
|
||||
|
||||
HRESULT decklink_input_callback::VideoInputFrameArrived(
|
||||
- IDeckLinkVideoInputFrame_v14_2_1 *videoFrame, IDeckLinkAudioInputPacket *audioFrame)
|
||||
+ IDeckLinkVideoInputFrame *videoFrame, IDeckLinkAudioInputPacket *audioFrame)
|
||||
{
|
||||
void *frameBytes;
|
||||
void *audioFrameBytes;
|
||||
@@ -1172,7 +1141,7 @@ av_cold int ff_decklink_read_header(AVFormatContext *avctx)
|
||||
goto error;
|
||||
|
||||
/* Get input device. */
|
||||
- if (ctx->dl->QueryInterface(IID_IDeckLinkInput_v14_2_1, (void **) &ctx->dli) != S_OK) {
|
||||
+ if (ctx->dl->QueryInterface(IID_IDeckLinkInput, (void **) &ctx->dli) != S_OK) {
|
||||
av_log(avctx, AV_LOG_ERROR, "Could not open input device from '%s'\n",
|
||||
avctx->url);
|
||||
ret = AVERROR(EIO);
|
||||
diff --git a/libavdevice/decklink_enc.cpp b/libavdevice/decklink_enc.cpp
|
||||
index d2e246c..cb8f917 100644
|
||||
--- a/libavdevice/decklink_enc.cpp
|
||||
+++ b/libavdevice/decklink_enc.cpp
|
||||
@@ -28,11 +28,7 @@ extern "C" {
|
||||
#include "libavformat/internal.h"
|
||||
}
|
||||
|
||||
-#include <DeckLinkAPIVersion.h>
|
||||
#include <DeckLinkAPI.h>
|
||||
-#if BLACKMAGIC_DECKLINK_API_VERSION >= 0x0e030000
|
||||
-#include <DeckLinkAPI_v14_2_1.h>
|
||||
-#endif
|
||||
|
||||
extern "C" {
|
||||
#include "libavformat/avformat.h"
|
||||
@@ -52,7 +48,7 @@ extern "C" {
|
||||
#endif
|
||||
|
||||
/* DeckLink callback class declaration */
|
||||
-class decklink_frame : public IDeckLinkVideoFrame_v14_2_1
|
||||
+class decklink_frame : public IDeckLinkVideoFrame
|
||||
{
|
||||
public:
|
||||
decklink_frame(struct decklink_ctx *ctx, AVFrame *avframe, AVCodecID codec_id, int height, int width) :
|
||||
@@ -115,20 +111,7 @@ public:
|
||||
_ancillary->AddRef();
|
||||
return S_OK;
|
||||
}
|
||||
- virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, LPVOID *ppv)
|
||||
- {
|
||||
- if (DECKLINK_IsEqualIID(riid, IID_IUnknown)) {
|
||||
- *ppv = static_cast<IUnknown*>(this);
|
||||
- } else if (DECKLINK_IsEqualIID(riid, IID_IDeckLinkVideoFrame_v14_2_1)) {
|
||||
- *ppv = static_cast<IDeckLinkVideoFrame_v14_2_1*>(this);
|
||||
- } else {
|
||||
- *ppv = NULL;
|
||||
- return E_NOINTERFACE;
|
||||
- }
|
||||
-
|
||||
- AddRef();
|
||||
- return S_OK;
|
||||
- }
|
||||
+ virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, LPVOID *ppv) { return E_NOINTERFACE; }
|
||||
virtual ULONG STDMETHODCALLTYPE AddRef(void) { return ++_refs; }
|
||||
virtual ULONG STDMETHODCALLTYPE Release(void)
|
||||
{
|
||||
@@ -155,10 +138,10 @@ private:
|
||||
std::atomic<int> _refs;
|
||||
};
|
||||
|
||||
-class decklink_output_callback : public IDeckLinkVideoOutputCallback_v14_2_1
|
||||
+class decklink_output_callback : public IDeckLinkVideoOutputCallback
|
||||
{
|
||||
public:
|
||||
- virtual HRESULT STDMETHODCALLTYPE ScheduledFrameCompleted(IDeckLinkVideoFrame_v14_2_1 *_frame, BMDOutputFrameCompletionResult result)
|
||||
+ virtual HRESULT STDMETHODCALLTYPE ScheduledFrameCompleted(IDeckLinkVideoFrame *_frame, BMDOutputFrameCompletionResult result)
|
||||
{
|
||||
decklink_frame *frame = static_cast<decklink_frame *>(_frame);
|
||||
struct decklink_ctx *ctx = frame->_ctx;
|
||||
@@ -176,20 +159,7 @@ public:
|
||||
return S_OK;
|
||||
}
|
||||
virtual HRESULT STDMETHODCALLTYPE ScheduledPlaybackHasStopped(void) { return S_OK; }
|
||||
- virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, LPVOID *ppv)
|
||||
- {
|
||||
- if (DECKLINK_IsEqualIID(riid, IID_IUnknown)) {
|
||||
- *ppv = static_cast<IUnknown*>(this);
|
||||
- } else if (DECKLINK_IsEqualIID(riid, IID_IDeckLinkVideoOutputCallback_v14_2_1)) {
|
||||
- *ppv = static_cast<IDeckLinkVideoOutputCallback_v14_2_1*>(this);
|
||||
- } else {
|
||||
- *ppv = NULL;
|
||||
- return E_NOINTERFACE;
|
||||
- }
|
||||
-
|
||||
- AddRef();
|
||||
- return S_OK;
|
||||
- }
|
||||
+ virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, LPVOID *ppv) { return E_NOINTERFACE; }
|
||||
virtual ULONG STDMETHODCALLTYPE AddRef(void) { return 1; }
|
||||
virtual ULONG STDMETHODCALLTYPE Release(void) { return 1; }
|
||||
};
|
||||
@@ -769,7 +739,7 @@ static int decklink_write_video_packet(AVFormatContext *avctx, AVPacket *pkt)
|
||||
ctx->first_pts = pkt->pts;
|
||||
|
||||
/* Schedule frame for playback. */
|
||||
- hr = ctx->dlo->ScheduleVideoFrame(frame,
|
||||
+ hr = ctx->dlo->ScheduleVideoFrame((class IDeckLinkVideoFrame *) frame,
|
||||
pkt->pts * ctx->bmd_tb_num,
|
||||
ctx->bmd_tb_num, ctx->bmd_tb_den);
|
||||
/* Pass ownership to DeckLink, or release on failure */
|
||||
@@ -904,7 +874,7 @@ av_cold int ff_decklink_write_header(AVFormatContext *avctx)
|
||||
return ret;
|
||||
|
||||
/* Get output device. */
|
||||
- if (ctx->dl->QueryInterface(IID_IDeckLinkOutput_v14_2_1, (void **) &ctx->dlo) != S_OK) {
|
||||
+ if (ctx->dl->QueryInterface(IID_IDeckLinkOutput, (void **) &ctx->dlo) != S_OK) {
|
||||
av_log(avctx, AV_LOG_ERROR, "Could not open output device from '%s'\n",
|
||||
avctx->url);
|
||||
ret = AVERROR(EIO);
|
||||
|
|
@ -1,51 +1,21 @@
|
|||
import re
|
||||
|
||||
dec_path = '/ffmpeg/libavdevice/decklink_dec.cpp'
|
||||
|
||||
with open(dec_path) as f:
|
||||
content = f.read()
|
||||
|
||||
# Fix 1: IDeckLinkMemoryAllocator -> IDeckLinkMemoryAllocator_v14_2_1
|
||||
# SDK 16 removed the unversioned alias
|
||||
for old, new in [
|
||||
(': public IDeckLinkMemoryAllocator\n', ': public IDeckLinkMemoryAllocator_v14_2_1\n'),
|
||||
('IDeckLinkMemoryAllocator *', 'IDeckLinkMemoryAllocator_v14_2_1 *'),
|
||||
('IDeckLinkMemoryAllocator*', 'IDeckLinkMemoryAllocator_v14_2_1*'),
|
||||
]:
|
||||
content = content.replace(old, new)
|
||||
print('Fix 1: IDeckLinkMemoryAllocator renamed')
|
||||
|
||||
# Fix 2: SetVideoInputFrameMemoryAllocator removed from IDeckLinkInput in SDK 16
|
||||
content = re.sub(
|
||||
r'ret = \(ctx->dli->SetVideoInputFrameMemoryAllocator\(allocator\)[^;]*;',
|
||||
'ret = 0; /* SDK16: SetVideoInputFrameMemoryAllocator removed */',
|
||||
content
|
||||
#!/usr/bin/env python3
|
||||
# Apply the upstream FFmpeg master decklink SDK-16 compatibility patch on top
|
||||
# of the release/7.1 source. The patch renames every IDeckLink* interface and
|
||||
# helper to its _v14_2_1 versioned form so the call sites keep working against
|
||||
# SDK 16's headers (which only retain the versioned aliases). Cherry-picking
|
||||
# individual replacements like the previous regex patch produced inconsistent
|
||||
# code that compiled but silently dropped every video frame.
|
||||
import subprocess, sys, pathlib
|
||||
patch = pathlib.Path('/decklink-sdk16.patch')
|
||||
if not patch.exists():
|
||||
print('FATAL: /decklink-sdk16.patch not found in build context', file=sys.stderr)
|
||||
sys.exit(1)
|
||||
# Patch was produced as `git diff HEAD FETCH_HEAD` where HEAD=release/7.1 and
|
||||
# FETCH_HEAD=master, so we apply it in REVERSE to move 7.1 → master.
|
||||
result = subprocess.run(
|
||||
['git', 'apply', '-R', '--verbose', str(patch)],
|
||||
cwd='/ffmpeg', capture_output=True, text=True,
|
||||
)
|
||||
print('Fix 2: SetVideoInputFrameMemoryAllocator patched')
|
||||
|
||||
# Fix 3: IDeckLinkVideoFrame::GetBytes removed in SDK 16 - moved to IDeckLinkVideoBuffer
|
||||
# Replace: videoFrame->GetBytes(&frameBytes);
|
||||
# With: { IDeckLinkVideoBuffer *vbuf = nullptr; videoFrame->QueryInterface(IID_IDeckLinkVideoBuffer, (void**)&vbuf); if (vbuf) { vbuf->GetBytes(&frameBytes); vbuf->Release(); } }
|
||||
getbytes_replacement = (
|
||||
'{ IDeckLinkVideoBuffer *_vbuf = nullptr; '
|
||||
'videoFrame->QueryInterface(IID_IDeckLinkVideoBuffer, (void**)&_vbuf); '
|
||||
'if (_vbuf) { _vbuf->GetBytes(&frameBytes); _vbuf->Release(); } }'
|
||||
)
|
||||
content = content.replace(
|
||||
'videoFrame->GetBytes(&frameBytes);',
|
||||
getbytes_replacement + ';'
|
||||
)
|
||||
print('Fix 3: videoFrame->GetBytes replaced with QueryInterface(IDeckLinkVideoBuffer)')
|
||||
|
||||
# Fix 4: Add include for versioned allocator header
|
||||
if 'DeckLinkAPIMemoryAllocator_v14_2_1.h' not in content:
|
||||
content = content.replace(
|
||||
'#include "decklink_common.h"',
|
||||
'#include "decklink_common.h"\n#include "DeckLinkAPIMemoryAllocator_v14_2_1.h"'
|
||||
)
|
||||
print('Fix 4: DeckLinkAPIMemoryAllocator_v14_2_1.h include added')
|
||||
|
||||
with open(dec_path, 'w') as f:
|
||||
f.write(content)
|
||||
|
||||
print('All patches applied successfully')
|
||||
print(result.stdout)
|
||||
print(result.stderr, file=sys.stderr)
|
||||
sys.exit(result.returncode)
|
||||
|
|
|
|||
Loading…
Reference in a new issue