[FFmpeg-devel] [PATCH] Add input support for DeckLink devices.

Deti Fliegl deti at fliegl.de
Mon Aug 18 19:48:27 CEST 2014


On 18.08.14 19:23, Carl Eugen Hoyos wrote:
> Deti Fliegl <deti <at> fliegl.de> writes:
> 
>> +/* free() is needed for a string returned by the DeckLink SDL. */
>> +#undef free
> 
> I believe this is not needed anymore but ...
removed it - but this has been part of the existing code which I simply
moved to a new file.

> 
>> +    free((void *) tmpDisplayName);
> 
> ... please move the comment here.
Done.

> Is the cast necessary?
Yes.

> 
>> +            av_log(NULL, AV_LOG_ERROR,
> 
> Context should not be NULL.
Can hardly be done in this file unless you supply avctx as argument in
every function only for av_log purposes.

> 
>> +            av_log(NULL, AV_LOG_INFO, "Found Decklink mode %d x 
>> %d with rate %.2f%s\n",  bmd_width, bmd_height,
>> (float)bmd_tb_den/(float)bmd_tb_num, 
>> (ctx->bmd_field_dominance==bmdLowerFieldFirst || 
>> ctx->bmd_field_dominance==bmdUpperFieldFirst)?"(i)":"");
> 
> Please split this line.
done.

> Isn't your patch missing a configure check and 
> a change to Makefile?
Must have missed some files to commit. Fixing patch attached to this mail.

> (What is the license of the decklink libraries?)
There is no DeckLink library code in my patch. The already existing
decklink encoder support covers how to build ffmpeg with the DeckLink SDK.

Deti
-------------- next part --------------
Signed-off-by: Deti fliegl <fliegl at baycom.de>
---
 configure                       |   4 +-
 doc/indevs.texi                 |  54 +++++++++++
 libavdevice/Makefile            |   5 +-
 libavdevice/alldevices.c        |   2 +-
 libavdevice/decklink_common.cpp |  30 +++----
 libavdevice/decklink_dec.cpp    |  14 +--
 libavdevice/decklink_enc.cpp    | 194 ++++------------------------------------
 libavdevice/decklink_enc.h      |  11 ---
 libavdevice/decklink_enc_c.c    |   1 +
 9 files changed, 100 insertions(+), 215 deletions(-)

diff --git a/configure b/configure
index f355dad..189542f 100755
--- a/configure
+++ b/configure
@@ -253,7 +253,7 @@ External library support:
                            native MPEG-4/Xvid encoder exists [no]
   --enable-libzmq          enable message passing via libzmq [no]
   --enable-libzvbi         enable teletext support via libzvbi [no]
-  --enable-decklink        enable Blackmagick DeckLink output [no]
+  --enable-decklink        enable Blackmagick DeckLink I/O support [no]
   --enable-openal          enable OpenAL 1.1 capture support [no]
   --enable-opencl          enable OpenCL code
   --enable-opengl          enable OpenGL rendering [no]
@@ -2441,6 +2441,8 @@ bktr_indev_deps_any="dev_bktr_ioctl_bt848_h machine_ioctl_bt848_h dev_video_bktr
 caca_outdev_deps="libcaca"
 decklink_outdev_deps="decklink pthreads"
 decklink_outdev_extralibs="-lstdc++"
+decklink_indev_deps="decklink pthreads"
+decklink_indev_extralibs="-lstdc++"
 dshow_indev_deps="IBaseFilter"
 dshow_indev_extralibs="-lpsapi -lole32 -lstrmiids -luuid"
 dv1394_indev_deps="dv1394"
diff --git a/doc/indevs.texi b/doc/indevs.texi
index ce409b9..ddf4c44 100644
--- a/doc/indevs.texi
+++ b/doc/indevs.texi
@@ -922,4 +922,58 @@ Use the MIT-SHM extension for shared memory. Default value is @code{1}.
 It may be necessary to disable it for remote displays.
 @end table
 
+ at section decklink
+
+The decklink input device provides capture capabilities for Blackmagic
+DeckLink devices.
+
+To enable this input device, you need the Blackmagic DeckLink SDK and you
+need to configure with the appropriate @code{--extra-cflags}
+and @code{--extra-ldflags}.
+On Windows, you need to run the IDL files through @command{widl}.
+
+DeckLink is very picky about the formats it supports. Pixel format is always
+uyvy422, framerate and video size must be determined for your device with
+ at command{-list_formats 1}. Audio sample rate is always 48 kHz and the number
+of channels currently is limited to 2 (stereo).
+
+ at subsection Options
+
+ at table @option
+
+ at item list_devices
+If set to @option{true}, print a list of devices and exit.
+Defaults to @option{false}.
+
+ at item list_formats
+If set to @option{true}, print a list of supported formats and exit.
+Defaults to @option{false}.
+
+ at end table
+
+ at subsection Examples
+
+ at itemize
+
+ at item
+List input devices:
+ at example
+ffmpeg -f decklink -list_devices 1 -i dummy
+ at end example
+
+ at item
+List supported formats:
+ at example
+ffmpeg -f decklink -list_formats 1 -i 'Intensity Pro'
+ at end example
+
+ at item
+Capture video clip at 1080i50 (format 11):
+ at example
+ffmpeg -f decklink -r 25 -i 'Intensity Pro@@11' -acodec copy -vcodec copy output.avi
+ at end example
+
+ at end itemize
+
+
 @c man end INPUT DEVICES
diff --git a/libavdevice/Makefile b/libavdevice/Makefile
index db301e7..8cf98f0 100644
--- a/libavdevice/Makefile
+++ b/libavdevice/Makefile
@@ -16,7 +16,8 @@ OBJS-$(CONFIG_ALSA_OUTDEV)               += alsa-audio-common.o \
 OBJS-$(CONFIG_AVFOUNDATION_INDEV)        += avfoundation.o
 OBJS-$(CONFIG_BKTR_INDEV)                += bktr.o
 OBJS-$(CONFIG_CACA_OUTDEV)               += caca.o
-OBJS-$(CONFIG_DECKLINK_OUTDEV)           += decklink_enc.o decklink_enc_c.o
+OBJS-$(CONFIG_DECKLINK_OUTDEV)           += decklink_enc.o decklink_enc_c.o decklink_common.o
+OBJS-$(CONFIG_DECKLINK_INDEV)            += decklink_dec.o decklink_dec_c.o decklink_common.o
 OBJS-$(CONFIG_DSHOW_INDEV)               += dshow.o dshow_enummediatypes.o \
                                             dshow_enumpins.o dshow_filter.o \
                                             dshow_pin.o dshow_common.o
@@ -57,7 +58,7 @@ OBJS-$(HAVE_LIBC_MSVCRT)                 += file_open.o
 # Windows resource file
 SLIBOBJS-$(HAVE_GNU_WINDRES)             += avdeviceres.o
 
-SKIPHEADERS-$(CONFIG_DECKLINK)           += decklink_enc.h
+SKIPHEADERS-$(CONFIG_DECKLINK)           += decklink_enc.h decklink_dec.h decklink_common.h
 SKIPHEADERS-$(CONFIG_DSHOW_INDEV)        += dshow_capture.h
 SKIPHEADERS-$(CONFIG_FBDEV_INDEV)        += fbdev_common.h
 SKIPHEADERS-$(CONFIG_FBDEV_OUTDEV)       += fbdev_common.h
diff --git a/libavdevice/alldevices.c b/libavdevice/alldevices.c
index ca34959..b8e7854 100644
--- a/libavdevice/alldevices.c
+++ b/libavdevice/alldevices.c
@@ -50,7 +50,7 @@ void avdevice_register_all(void)
     REGISTER_INDEV   (AVFOUNDATION,     avfoundation);
     REGISTER_INDEV   (BKTR,             bktr);
     REGISTER_OUTDEV  (CACA,             caca);
-    REGISTER_OUTDEV  (DECKLINK,         decklink);
+    REGISTER_INOUTDEV(DECKLINK,         decklink);
     REGISTER_INDEV   (DSHOW,            dshow);
     REGISTER_INDEV   (DV1394,           dv1394);
     REGISTER_INOUTDEV(FBDEV,            fbdev);
diff --git a/libavdevice/decklink_common.cpp b/libavdevice/decklink_common.cpp
index 7a9fed5..73628c4 100644
--- a/libavdevice/decklink_common.cpp
+++ b/libavdevice/decklink_common.cpp
@@ -57,9 +57,6 @@ IDeckLinkIterator *CreateDeckLinkIteratorInstance(void)
 }
 #endif
 
-/* free() is needed for a string returned by the DeckLink SDL. */
-#undef free
-
 #ifdef _WIN32
 char *dup_wchar_to_utf8(wchar_t *w)
 {
@@ -84,27 +81,28 @@ HRESULT IDeckLink_GetDisplayName(IDeckLink *This, const char **displayName)
     if (hr != S_OK)
         return hr;
     *displayName = DECKLINK_STRDUP(tmpDisplayName);
+    /* free() is needed for a string returned by the DeckLink SDL. */
     free((void *) tmpDisplayName);
     return hr;
 }
 
 int decklink_set_format(struct decklink_ctx *ctx,
                                int width, int height,
-                               int tb_num, int tb_den, 
+                               int tb_num, int tb_den,
                                decklink_direction_t direction, int num)
 {
     BMDDisplayModeSupport support;
-    IDeckLinkDisplayModeIterator *itermode; 
+    IDeckLinkDisplayModeIterator *itermode;
     IDeckLinkDisplayMode *mode;
     int i = 1;
     HRESULT res;
-    
+
     if (direction == DIRECTION_IN) {
         res = ctx->dli->GetDisplayModeIterator (&itermode);
     } else {
         res = ctx->dlo->GetDisplayModeIterator (&itermode);
-    }    
-    
+    }
+
     if (res!= S_OK) {
             av_log(NULL, AV_LOG_ERROR, "Could not get Display Mode Iterator\n");
             return AVERROR(EIO);
@@ -131,15 +129,17 @@ int decklink_set_format(struct decklink_ctx *ctx,
             ctx->bmd_tb_den = bmd_tb_den;
             ctx->bmd_tb_num = bmd_tb_num;
             ctx->bmd_field_dominance = mode->GetFieldDominance();
-            av_log(NULL, AV_LOG_INFO, "Found Decklink mode %d x %d with rate %.2f%s\n",  bmd_width, bmd_height, (float)bmd_tb_den/(float)bmd_tb_num, (ctx->bmd_field_dominance==bmdLowerFieldFirst || ctx->bmd_field_dominance==bmdUpperFieldFirst)?"(i)":"");
+            av_log(NULL, AV_LOG_INFO, "Found Decklink mode %d x %d with rate %.2f%s\n",  
+                bmd_width, bmd_height, (float)bmd_tb_den/(float)bmd_tb_num, 
+                (ctx->bmd_field_dominance==bmdLowerFieldFirst || ctx->bmd_field_dominance==bmdUpperFieldFirst)?"(i)":"");
         }
 
         mode->Release();
         i++;
     }
-    
+
     itermode->Release();
-    
+
     if (ctx->bmd_mode == bmdModeUnknown)
         return -1;
     if (direction == DIRECTION_IN) {
@@ -163,7 +163,7 @@ int decklink_set_format(struct decklink_ctx *ctx, decklink_direction_t direction
     return decklink_set_format(ctx, 0, 0, 0, 0, direction, num);
 }
 
-int decklink_list_devices(AVFormatContext *avctx) 
+int decklink_list_devices(AVFormatContext *avctx)
 {
     IDeckLink *dl = NULL;
     IDeckLinkIterator *iter = CreateDeckLinkIteratorInstance();
@@ -191,13 +191,13 @@ int decklink_list_formats(AVFormatContext *avctx, decklink_direction_t direction
     IDeckLinkDisplayMode *mode;
     int i=0;
     HRESULT res;
-    
+
     if (direction == DIRECTION_IN) {
         res = ctx->dli->GetDisplayModeIterator (&itermode);
     } else {
         res = ctx->dlo->GetDisplayModeIterator (&itermode);
-    }    
-    
+    }
+
     if (res!= S_OK) {
             av_log(avctx, AV_LOG_ERROR, "Could not get Display Mode Iterator\n");
             return AVERROR(EIO);
diff --git a/libavdevice/decklink_dec.cpp b/libavdevice/decklink_dec.cpp
index ebf555f..f607fbd 100644
--- a/libavdevice/decklink_dec.cpp
+++ b/libavdevice/decklink_dec.cpp
@@ -323,7 +323,7 @@ HRESULT decklink_input_callback::VideoInputFormatChanged(
     return S_OK;
 }
 
-static HRESULT decklink_start_input(AVFormatContext *avctx) 
+static HRESULT decklink_start_input(AVFormatContext *avctx)
 {
     struct decklink_cctx *cctx = (struct decklink_cctx *) avctx->priv_data;
     struct decklink_ctx *ctx = (struct decklink_ctx *) cctx->ctx;
@@ -362,7 +362,7 @@ av_cold int ff_decklink_read_header(AVFormatContext *avctx)
 {
     struct decklink_cctx *cctx = (struct decklink_cctx *) avctx->priv_data;
     struct decklink_ctx *ctx;
-    IDeckLinkDisplayModeIterator *itermode; 
+    IDeckLinkDisplayModeIterator *itermode;
     IDeckLinkIterator *iter;
     IDeckLink *dl = NULL;
     AVStream *st;
@@ -390,7 +390,7 @@ av_cold int ff_decklink_read_header(AVFormatContext *avctx)
         decklink_list_devices(avctx);
         return AVERROR_EXIT;
     }
-    
+
     strcpy (fname, avctx->filename);
     tmp=strchr (fname, '@');
     if (tmp != NULL) {
@@ -459,7 +459,7 @@ av_cold int ff_decklink_read_header(AVFormatContext *avctx)
     st->codec->channels    = 2;
     avpriv_set_pts_info(st, 64, 1, 1000000);  /* 64 bits pts in us */
     ctx->audio_st=st;
-    
+
     st = avformat_new_stream(avctx, NULL);
     if (!st) {
         av_log(avctx, AV_LOG_ERROR, "Cannot add stream\n");
@@ -469,13 +469,13 @@ av_cold int ff_decklink_read_header(AVFormatContext *avctx)
     st->codec->codec_id    = AV_CODEC_ID_RAWVIDEO;
     st->codec->width       = 1920;
     st->codec->height      = 1080;
-    
+
     st->codec->pix_fmt	   = AV_PIX_FMT_UYVY422;
     st->codec->bit_rate    = avpicture_get_size(st->codec->pix_fmt, 1920, 1080) * /*av_q2d(25)*/ 25 * 8;
     st->codec->codec_tag   = MKTAG('U', 'Y', 'V', 'Y');
     avpriv_set_pts_info(st, 64, 1, 1000000);  /* 64 bits pts in us */
     ctx->video_st=st;
-    
+
     result = ctx->dli->EnableAudioInput(bmdAudioSampleRate48kHz, bmdAudioSampleType16bitInteger, 2);
 
     if (result != S_OK) {
@@ -491,7 +491,7 @@ av_cold int ff_decklink_read_header(AVFormatContext *avctx)
     }
     
     avpacket_queue_init (avctx, &ctx->queue);
-                
+
     if (decklink_start_input (avctx) != S_OK) {
         av_log(avctx, AV_LOG_ERROR, "Cannot start input stream\n");
         goto error;
diff --git a/libavdevice/decklink_enc.cpp b/libavdevice/decklink_enc.cpp
index 3d7cbe2..c56eac2 100644
--- a/libavdevice/decklink_enc.cpp
+++ b/libavdevice/decklink_enc.cpp
@@ -20,13 +20,6 @@
  */
 
 #include <DeckLinkAPI.h>
-#ifdef _WIN32
-#include <DeckLinkAPI_i.c>
-typedef unsigned long buffercount_type;
-#else
-#include <DeckLinkAPIDispatch.cpp>
-typedef uint32_t buffercount_type;
-#endif
 
 #include <pthread.h>
 #include <semaphore.h>
@@ -37,44 +30,9 @@ extern "C" {
 #include "libavutil/imgutils.h"
 }
 
+#include "decklink_common.h"
 #include "decklink_enc.h"
 
-class decklink_callback;
-
-struct decklink_ctx {
-    /* DeckLink SDK interfaces */
-    IDeckLink *dl;
-    IDeckLinkOutput *dlo;
-    decklink_callback *callback;
-
-    /* DeckLink mode information */
-    IDeckLinkDisplayModeIterator *itermode;
-    BMDTimeValue bmd_tb_den;
-    BMDTimeValue bmd_tb_num;
-    BMDDisplayMode bmd_mode;
-    int bmd_width;
-    int bmd_height;
-
-    /* Streams present */
-    int audio;
-    int video;
-
-    /* Status */
-    int playback_started;
-    int64_t last_pts;
-
-    /* Options */
-    int list_devices;
-    int list_formats;
-    double preroll;
-
-    int frames_preroll;
-    int frames_buffer;
-
-    sem_t semaphore;
-
-    int channels;
-};
 
 /* DeckLink callback class declaration */
 class decklink_frame : public IDeckLinkVideoFrame
@@ -109,7 +67,7 @@ private:
     int   _refs;
 };
 
-class decklink_callback : public IDeckLinkVideoOutputCallback
+class decklink_output_callback : public IDeckLinkVideoOutputCallback
 {
 public:
     virtual HRESULT STDMETHODCALLTYPE ScheduledFrameCompleted(IDeckLinkVideoFrame *_frame, BMDOutputFrameCompletionResult result)
@@ -130,99 +88,6 @@ public:
     virtual ULONG   STDMETHODCALLTYPE Release(void)                           { return 1; }
 };
 
-#ifdef _WIN32
-static IDeckLinkIterator *CreateDeckLinkIteratorInstance(void)
-{
-    IDeckLinkIterator *iter;
-
-    if (CoInitialize(NULL) != S_OK) {
-        av_log(NULL, AV_LOG_ERROR, "COM initialization failed.\n");
-        return NULL;
-    }
-
-    if (CoCreateInstance(CLSID_CDeckLinkIterator, NULL, CLSCTX_ALL,
-                         IID_IDeckLinkIterator, (void**) &iter) != S_OK) {
-        av_log(NULL, AV_LOG_ERROR, "DeckLink drivers not installed.\n");
-        return NULL;
-    }
-
-    return iter;
-}
-#endif
-
-/* free() is needed for a string returned by the DeckLink SDL. */
-#undef free
-
-#ifdef _WIN32
-static char *dup_wchar_to_utf8(wchar_t *w)
-{
-    char *s = NULL;
-    int l = WideCharToMultiByte(CP_UTF8, 0, w, -1, 0, 0, 0, 0);
-    s = (char *) av_malloc(l);
-    if (s)
-        WideCharToMultiByte(CP_UTF8, 0, w, -1, s, l, 0, 0);
-    return s;
-}
-#define DECKLINK_STR    OLECHAR *
-#define DECKLINK_STRDUP dup_wchar_to_utf8
-#else
-#define DECKLINK_STR    const char *
-#define DECKLINK_STRDUP av_strdup
-#endif
-
-static HRESULT IDeckLink_GetDisplayName(IDeckLink *This, const char **displayName)
-{
-    DECKLINK_STR tmpDisplayName;
-    HRESULT hr = This->GetDisplayName(&tmpDisplayName);
-    if (hr != S_OK)
-        return hr;
-    *displayName = DECKLINK_STRDUP(tmpDisplayName);
-    free((void *) tmpDisplayName);
-    return hr;
-}
-
-static int decklink_set_format(struct decklink_ctx *ctx,
-                               int width, int height,
-                               int tb_num, int tb_den)
-{
-    BMDDisplayModeSupport support;
-    IDeckLinkDisplayMode *mode;
-
-    if (tb_num == 1) {
-        tb_num *= 1000;
-        tb_den *= 1000;
-    }
-    ctx->bmd_mode = bmdModeUnknown;
-    while ((ctx->bmd_mode == bmdModeUnknown) && ctx->itermode->Next(&mode) == S_OK) {
-        BMDTimeValue bmd_tb_num, bmd_tb_den;
-        int bmd_width  = mode->GetWidth();
-        int bmd_height = mode->GetHeight();
-
-        mode->GetFrameRate(&bmd_tb_num, &bmd_tb_den);
-
-        if (bmd_width == width && bmd_height == height &&
-            bmd_tb_num == tb_num && bmd_tb_den == tb_den) {
-            ctx->bmd_mode   = mode->GetDisplayMode();
-            ctx->bmd_width  = bmd_width;
-            ctx->bmd_height = bmd_height;
-            ctx->bmd_tb_den = bmd_tb_den;
-            ctx->bmd_tb_num = bmd_tb_num;
-        }
-
-        mode->Release();
-    }
-    if (ctx->bmd_mode == bmdModeUnknown)
-        return -1;
-    if (ctx->dlo->DoesSupportVideoMode(ctx->bmd_mode, bmdFormat8BitYUV,
-                                       bmdVideoOutputFlagDefault,
-                                       &support, NULL) != S_OK)
-        return -1;
-    if (support == bmdDisplayModeSupported)
-        return 0;
-
-    return -1;
-}
-
 static int decklink_setup_video(AVFormatContext *avctx, AVStream *st)
 {
     struct decklink_cctx *cctx = (struct decklink_cctx *) avctx->priv_data;
@@ -252,8 +117,8 @@ static int decklink_setup_video(AVFormatContext *avctx, AVStream *st)
     }
 
     /* Set callback. */
-    ctx->callback = new decklink_callback();
-    ctx->dlo->SetScheduledFrameCompletionCallback(ctx->callback);
+    ctx->output_callback = new decklink_output_callback();
+    ctx->dlo->SetScheduledFrameCompletionCallback(ctx->output_callback);
 
     /* Start video semaphore. */
     ctx->frames_preroll = c->time_base.den * ctx->preroll;
@@ -333,8 +198,8 @@ av_cold int ff_decklink_write_trailer(AVFormatContext *avctx)
     if (ctx->dl)
         ctx->dl->Release();
 
-    if (ctx->callback)
-        delete ctx->callback;
+    if (ctx->output_callback)
+        delete ctx->output_callback;
 
     sem_destroy(&ctx->semaphore);
 
@@ -450,6 +315,7 @@ av_cold int ff_decklink_write_header(AVFormatContext *avctx)
 {
     struct decklink_cctx *cctx = (struct decklink_cctx *) avctx->priv_data;
     struct decklink_ctx *ctx;
+    IDeckLinkDisplayModeIterator *itermode;
     IDeckLinkIterator *iter;
     IDeckLink *dl = NULL;
     unsigned int n;
@@ -470,15 +336,7 @@ av_cold int ff_decklink_write_header(AVFormatContext *avctx)
 
     /* List available devices. */
     if (ctx->list_devices) {
-        av_log(avctx, AV_LOG_INFO, "Blackmagic DeckLink devices:\n");
-        while (iter->Next(&dl) == S_OK) {
-            const char *displayName;
-            IDeckLink_GetDisplayName(dl, &displayName);
-            av_log(avctx, AV_LOG_INFO, "\t'%s'\n", displayName);
-            av_free((void *) displayName);
-            dl->Release();
-        }
-        iter->Release();
+        decklink_list_devices(avctx);
         return AVERROR_EXIT;
     }
 
@@ -508,40 +366,20 @@ av_cold int ff_decklink_write_header(AVFormatContext *avctx)
         return AVERROR(EIO);
     }
 
-    if (ctx->dlo->GetDisplayModeIterator(&ctx->itermode) != S_OK) {
-        av_log(avctx, AV_LOG_ERROR, "Could not get Display Mode Iterator\n");
-        ctx->dl->Release();
-        return AVERROR(EIO);
-    }
-
     /* List supported formats. */
     if (ctx->list_formats) {
-        IDeckLinkDisplayMode *mode;
-
-        av_log(avctx, AV_LOG_INFO, "Supported formats for '%s':\n",
-               avctx->filename);
-        while (ctx->itermode->Next(&mode) == S_OK) {
-            BMDTimeValue tb_num, tb_den;
-            mode->GetFrameRate(&tb_num, &tb_den);
-            av_log(avctx, AV_LOG_INFO, "\t%ldx%ld at %d/%d fps",
-                   mode->GetWidth(), mode->GetHeight(),
-                   (int) tb_den, (int) tb_num);
-            switch (mode->GetFieldDominance()) {
-            case bmdLowerFieldFirst:
-            av_log(avctx, AV_LOG_INFO, " (interlaced, lower field first)"); break;
-            case bmdUpperFieldFirst:
-            av_log(avctx, AV_LOG_INFO, " (interlaced, upper field first)"); break;
-            }
-            av_log(avctx, AV_LOG_INFO, "\n");
-            mode->Release();
-        }
-
-        ctx->itermode->Release();
+        decklink_list_formats(avctx);
         ctx->dlo->Release();
         ctx->dl->Release();
         return AVERROR_EXIT;
     }
 
+    if (ctx->dlo->GetDisplayModeIterator(&itermode) != S_OK) {
+        av_log(avctx, AV_LOG_ERROR, "Could not get Display Mode Iterator\n");
+        ctx->dl->Release();
+        return AVERROR(EIO);
+    }
+
     /* Setup streams. */
     for (n = 0; n < avctx->nb_streams; n++) {
         AVStream *st = avctx->streams[n];
@@ -557,7 +395,7 @@ av_cold int ff_decklink_write_header(AVFormatContext *avctx)
             goto error;
         }
     }
-    ctx->itermode->Release();
+    itermode->Release();
 
     return 0;
 
diff --git a/libavdevice/decklink_enc.h b/libavdevice/decklink_enc.h
index 0b9ad8f..6086947 100644
--- a/libavdevice/decklink_enc.h
+++ b/libavdevice/decklink_enc.h
@@ -19,17 +19,6 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  */
 
-struct decklink_cctx {
-    const AVClass *cclass;
-
-    void *ctx;
-
-    /* Options */
-    int list_devices;
-    int list_formats;
-    double preroll;
-};
-
 #ifdef __cplusplus
 extern "C" {
 #endif
diff --git a/libavdevice/decklink_enc_c.c b/libavdevice/decklink_enc_c.c
index 7c18043..c3c9018 100644
--- a/libavdevice/decklink_enc_c.c
+++ b/libavdevice/decklink_enc_c.c
@@ -22,6 +22,7 @@
 #include "libavformat/avformat.h"
 #include "libavutil/opt.h"
 
+#include "decklink_common_c.h"
 #include "decklink_enc.h"
 
 #define OFFSET(x) offsetof(struct decklink_cctx, x)
-- 
1.9.1



More information about the ffmpeg-devel mailing list