Browse code

avdevice/decklink: move general code of decklink encoder to common file

Signed-off-by: Michael Niedermayer <michaelni@gmx.at>

Deti Fliegl authored on 2014/09/22 08:39:50
Showing 7 changed files
... ...
@@ -16,7 +16,7 @@ OBJS-$(CONFIG_ALSA_OUTDEV)               += alsa-audio-common.o \
16 16
 OBJS-$(CONFIG_AVFOUNDATION_INDEV)        += avfoundation.o
17 17
 OBJS-$(CONFIG_BKTR_INDEV)                += bktr.o
18 18
 OBJS-$(CONFIG_CACA_OUTDEV)               += caca.o
19
-OBJS-$(CONFIG_DECKLINK_OUTDEV)           += decklink_enc.o decklink_enc_c.o
19
+OBJS-$(CONFIG_DECKLINK_OUTDEV)           += decklink_enc.o decklink_enc_c.o decklink_common.o
20 20
 OBJS-$(CONFIG_DSHOW_INDEV)               += dshow.o dshow_enummediatypes.o \
21 21
                                             dshow_enumpins.o dshow_filter.o \
22 22
                                             dshow_pin.o dshow_common.o
... ...
@@ -57,7 +57,7 @@ OBJS-$(HAVE_LIBC_MSVCRT)                 += file_open.o
57 57
 # Windows resource file
58 58
 SLIBOBJS-$(HAVE_GNU_WINDRES)             += avdeviceres.o
59 59
 
60
-SKIPHEADERS-$(CONFIG_DECKLINK)           += decklink_enc.h
60
+SKIPHEADERS-$(CONFIG_DECKLINK)           += decklink_enc.h decklink_common.h
61 61
 SKIPHEADERS-$(CONFIG_DSHOW_INDEV)        += dshow_capture.h
62 62
 SKIPHEADERS-$(CONFIG_FBDEV_INDEV)        += fbdev_common.h
63 63
 SKIPHEADERS-$(CONFIG_FBDEV_OUTDEV)       += fbdev_common.h
64 64
new file mode 100644
... ...
@@ -0,0 +1,229 @@
0
+/*
1
+ * Blackmagic DeckLink output
2
+ * Copyright (c) 2013-2014 Ramiro Polla, Luca Barbato, Deti Fliegl
3
+ *
4
+ * This file is part of FFmpeg.
5
+ *
6
+ * FFmpeg is free software; you can redistribute it and/or
7
+ * modify it under the terms of the GNU Lesser General Public
8
+ * License as published by the Free Software Foundation; either
9
+ * version 2.1 of the License, or (at your option) any later version.
10
+ *
11
+ * FFmpeg is distributed in the hope that it will be useful,
12
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14
+ * Lesser General Public License for more details.
15
+ *
16
+ * You should have received a copy of the GNU Lesser General Public
17
+ * License along with FFmpeg; if not, write to the Free Software
18
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19
+ */
20
+
21
+#include <DeckLinkAPI.h>
22
+#ifdef _WIN32
23
+#include <DeckLinkAPI_i.c>
24
+#else
25
+#include <DeckLinkAPIDispatch.cpp>
26
+#endif
27
+
28
+#include <pthread.h>
29
+#include <semaphore.h>
30
+
31
+extern "C" {
32
+#include "libavformat/avformat.h"
33
+#include "libavformat/internal.h"
34
+#include "libavutil/imgutils.h"
35
+}
36
+
37
+#include "decklink_common.h"
38
+
39
+#ifdef _WIN32
40
+IDeckLinkIterator *CreateDeckLinkIteratorInstance(void)
41
+{
42
+    IDeckLinkIterator *iter;
43
+
44
+    if (CoInitialize(NULL) != S_OK) {
45
+        av_log(NULL, AV_LOG_ERROR, "COM initialization failed.\n");
46
+        return NULL;
47
+    }
48
+
49
+    if (CoCreateInstance(CLSID_CDeckLinkIterator, NULL, CLSCTX_ALL,
50
+                         IID_IDeckLinkIterator, (void**) &iter) != S_OK) {
51
+        av_log(NULL, AV_LOG_ERROR, "DeckLink drivers not installed.\n");
52
+        return NULL;
53
+    }
54
+
55
+    return iter;
56
+}
57
+#endif
58
+
59
+#ifdef _WIN32
60
+static char *dup_wchar_to_utf8(wchar_t *w)
61
+{
62
+    char *s = NULL;
63
+    int l = WideCharToMultiByte(CP_UTF8, 0, w, -1, 0, 0, 0, 0);
64
+    s = (char *) av_malloc(l);
65
+    if (s)
66
+        WideCharToMultiByte(CP_UTF8, 0, w, -1, s, l, 0, 0);
67
+    return s;
68
+}
69
+#define DECKLINK_STR    OLECHAR *
70
+#define DECKLINK_STRDUP dup_wchar_to_utf8
71
+#else
72
+#define DECKLINK_STR    const char *
73
+#define DECKLINK_STRDUP av_strdup
74
+#endif
75
+
76
+HRESULT ff_decklink_get_display_name(IDeckLink *This, const char **displayName)
77
+{
78
+    DECKLINK_STR tmpDisplayName;
79
+    HRESULT hr = This->GetDisplayName(&tmpDisplayName);
80
+    if (hr != S_OK)
81
+        return hr;
82
+    *displayName = DECKLINK_STRDUP(tmpDisplayName);
83
+    /* free() is needed for a string returned by the DeckLink SDL. */
84
+    free((void *) tmpDisplayName);
85
+    return hr;
86
+}
87
+
88
+int ff_decklink_set_format(AVFormatContext *avctx,
89
+                               int width, int height,
90
+                               int tb_num, int tb_den,
91
+                               decklink_direction_t direction, int num)
92
+{
93
+    struct decklink_cctx *cctx = (struct decklink_cctx *) avctx->priv_data;
94
+    struct decklink_ctx *ctx = (struct decklink_ctx *)cctx->ctx;
95
+    BMDDisplayModeSupport support;
96
+    IDeckLinkDisplayModeIterator *itermode;
97
+    IDeckLinkDisplayMode *mode;
98
+    int i = 1;
99
+    HRESULT res;
100
+
101
+    if (direction == DIRECTION_IN) {
102
+        res = ctx->dli->GetDisplayModeIterator (&itermode);
103
+    } else {
104
+        res = ctx->dlo->GetDisplayModeIterator (&itermode);
105
+    }
106
+
107
+    if (res!= S_OK) {
108
+            av_log(avctx, AV_LOG_ERROR, "Could not get Display Mode Iterator\n");
109
+            return AVERROR(EIO);
110
+    }
111
+
112
+
113
+    if (tb_num == 1) {
114
+        tb_num *= 1000;
115
+        tb_den *= 1000;
116
+    }
117
+    ctx->bmd_mode = bmdModeUnknown;
118
+    while ((ctx->bmd_mode == bmdModeUnknown) && itermode->Next(&mode) == S_OK) {
119
+        BMDTimeValue bmd_tb_num, bmd_tb_den;
120
+        int bmd_width  = mode->GetWidth();
121
+        int bmd_height = mode->GetHeight();
122
+
123
+        mode->GetFrameRate(&bmd_tb_num, &bmd_tb_den);
124
+
125
+        if ((bmd_width == width && bmd_height == height &&
126
+            bmd_tb_num == tb_num && bmd_tb_den == tb_den) || i == num) {
127
+            ctx->bmd_mode   = mode->GetDisplayMode();
128
+            ctx->bmd_width  = bmd_width;
129
+            ctx->bmd_height = bmd_height;
130
+            ctx->bmd_tb_den = bmd_tb_den;
131
+            ctx->bmd_tb_num = bmd_tb_num;
132
+            ctx->bmd_field_dominance = mode->GetFieldDominance();
133
+            av_log(avctx, AV_LOG_INFO, "Found Decklink mode %d x %d with rate %.2f%s\n",
134
+                bmd_width, bmd_height, (float)bmd_tb_den/(float)bmd_tb_num,
135
+                (ctx->bmd_field_dominance==bmdLowerFieldFirst || ctx->bmd_field_dominance==bmdUpperFieldFirst)?"(i)":"");
136
+        }
137
+
138
+        mode->Release();
139
+        i++;
140
+    }
141
+
142
+    itermode->Release();
143
+
144
+    if (ctx->bmd_mode == bmdModeUnknown)
145
+        return -1;
146
+    if (direction == DIRECTION_IN) {
147
+        if (ctx->dli->DoesSupportVideoMode(ctx->bmd_mode, bmdFormat8BitYUV,
148
+                                           bmdVideoOutputFlagDefault,
149
+                                           &support, NULL) != S_OK)
150
+            return -1;
151
+    } else {
152
+        if (ctx->dlo->DoesSupportVideoMode(ctx->bmd_mode, bmdFormat8BitYUV,
153
+                                           bmdVideoOutputFlagDefault,
154
+                                           &support, NULL) != S_OK)
155
+        return -1;
156
+    }
157
+    if (support == bmdDisplayModeSupported)
158
+        return 0;
159
+
160
+    return -1;
161
+}
162
+
163
+int ff_decklink_set_format(AVFormatContext *avctx, decklink_direction_t direction, int num) {
164
+    return ff_decklink_set_format(avctx, 0, 0, 0, 0, direction, num);
165
+}
166
+
167
+int ff_decklink_list_devices(AVFormatContext *avctx)
168
+{
169
+    IDeckLink *dl = NULL;
170
+    IDeckLinkIterator *iter = CreateDeckLinkIteratorInstance();
171
+    if (!iter) {
172
+        av_log(avctx, AV_LOG_ERROR, "Could not create DeckLink iterator\n");
173
+        return AVERROR(EIO);
174
+    }
175
+    av_log(avctx, AV_LOG_INFO, "Blackmagic DeckLink devices:\n");
176
+    while (iter->Next(&dl) == S_OK) {
177
+        const char *displayName;
178
+        ff_decklink_get_display_name(dl, &displayName);
179
+        av_log(avctx, AV_LOG_INFO, "\t'%s'\n", displayName);
180
+        av_free((void *) displayName);
181
+        dl->Release();
182
+    }
183
+    iter->Release();
184
+    return 0;
185
+}
186
+
187
+int ff_decklink_list_formats(AVFormatContext *avctx, decklink_direction_t direction)
188
+{
189
+    struct decklink_cctx *cctx = (struct decklink_cctx *) avctx->priv_data;
190
+    struct decklink_ctx *ctx = (struct decklink_ctx *)cctx->ctx;
191
+    IDeckLinkDisplayModeIterator *itermode;
192
+    IDeckLinkDisplayMode *mode;
193
+    int i=0;
194
+    HRESULT res;
195
+
196
+    if (direction == DIRECTION_IN) {
197
+        res = ctx->dli->GetDisplayModeIterator (&itermode);
198
+    } else {
199
+        res = ctx->dlo->GetDisplayModeIterator (&itermode);
200
+    }
201
+
202
+    if (res!= S_OK) {
203
+            av_log(avctx, AV_LOG_ERROR, "Could not get Display Mode Iterator\n");
204
+            return AVERROR(EIO);
205
+    }
206
+
207
+    av_log(avctx, AV_LOG_INFO, "Supported formats for '%s':\n",
208
+               avctx->filename);
209
+    while (itermode->Next(&mode) == S_OK) {
210
+        BMDTimeValue tb_num, tb_den;
211
+        mode->GetFrameRate(&tb_num, &tb_den);
212
+        av_log(avctx, AV_LOG_INFO, "\t%d\t%ldx%ld at %d/%d fps",
213
+                ++i,mode->GetWidth(), mode->GetHeight(),
214
+                (int) tb_den, (int) tb_num);
215
+        switch (mode->GetFieldDominance()) {
216
+        case bmdLowerFieldFirst:
217
+        av_log(avctx, AV_LOG_INFO, " (interlaced, lower field first)"); break;
218
+        case bmdUpperFieldFirst:
219
+        av_log(avctx, AV_LOG_INFO, " (interlaced, upper field first)"); break;
220
+        }
221
+        av_log(avctx, AV_LOG_INFO, "\n");
222
+        mode->Release();
223
+    }
224
+
225
+    itermode->Release();
226
+
227
+    return 0;
228
+}
0 229
new file mode 100644
... ...
@@ -0,0 +1,98 @@
0
+/*
1
+ * Blackmagic DeckLink common code
2
+ * Copyright (c) 2013-2014 Ramiro Polla, Luca Barbato, Deti Fliegl
3
+ *
4
+ * This file is part of FFmpeg.
5
+ *
6
+ * FFmpeg is free software; you can redistribute it and/or
7
+ * modify it under the terms of the GNU Lesser General Public
8
+ * License as published by the Free Software Foundation; either
9
+ * version 2.1 of the License, or (at your option) any later version.
10
+ *
11
+ * FFmpeg is distributed in the hope that it will be useful,
12
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14
+ * Lesser General Public License for more details.
15
+ *
16
+ * You should have received a copy of the GNU Lesser General Public
17
+ * License along with FFmpeg; if not, write to the Free Software
18
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19
+ */
20
+
21
+#include "decklink_common_c.h"
22
+
23
+class decklink_output_callback;
24
+class decklink_input_callback;
25
+
26
+typedef struct AVPacketQueue {
27
+    AVPacketList *first_pkt, *last_pkt;
28
+    int nb_packets;
29
+    unsigned long long size;
30
+    int abort_request;
31
+    pthread_mutex_t mutex;
32
+    pthread_cond_t cond;
33
+    AVFormatContext *avctx;
34
+} AVPacketQueue;
35
+
36
+struct decklink_ctx {
37
+    /* DeckLink SDK interfaces */
38
+    IDeckLink *dl;
39
+    IDeckLinkOutput *dlo;
40
+    IDeckLinkInput *dli;
41
+    decklink_output_callback *output_callback;
42
+    decklink_input_callback *input_callback;
43
+
44
+    /* DeckLink mode information */
45
+    BMDTimeValue bmd_tb_den;
46
+    BMDTimeValue bmd_tb_num;
47
+    BMDDisplayMode bmd_mode;
48
+    int bmd_width;
49
+    int bmd_height;
50
+    int bmd_field_dominance;
51
+
52
+    /* Capture buffer queue */
53
+    AVPacketQueue queue;
54
+
55
+    /* Streams present */
56
+    int audio;
57
+    int video;
58
+
59
+    /* Status */
60
+    int playback_started;
61
+    int capture_started;
62
+    int64_t last_pts;
63
+    unsigned long frameCount;
64
+    unsigned int dropped;
65
+    AVStream *audio_st;
66
+    AVStream *video_st;
67
+
68
+    /* Options */
69
+    int list_devices;
70
+    int list_formats;
71
+    double preroll;
72
+
73
+    int frames_preroll;
74
+    int frames_buffer;
75
+
76
+    sem_t semaphore;
77
+
78
+    int channels;
79
+};
80
+
81
+typedef enum { DIRECTION_IN, DIRECTION_OUT} decklink_direction_t;
82
+
83
+#ifdef _WIN32
84
+typedef unsigned long buffercount_type;
85
+IDeckLinkIterator *CreateDeckLinkIteratorInstance(void);
86
+char *dup_wchar_to_utf8(wchar_t *w);
87
+#else
88
+typedef uint32_t buffercount_type;
89
+#endif
90
+
91
+
92
+HRESULT ff_decklink_get_display_name(IDeckLink *This, const char **displayName);
93
+int ff_decklink_set_format(AVFormatContext *avctx, int width, int height, int tb_num, int tb_den, decklink_direction_t direction = DIRECTION_OUT, int num = 0);
94
+int ff_decklink_set_format(AVFormatContext *avctx, decklink_direction_t direction, int num);
95
+int ff_decklink_list_devices(AVFormatContext *avctx);
96
+int ff_decklink_list_formats(AVFormatContext *avctx, decklink_direction_t direction = DIRECTION_OUT);
97
+
0 98
new file mode 100644
... ...
@@ -0,0 +1,32 @@
0
+/*
1
+ * Blackmagic DeckLink common code
2
+ * Copyright (c) 2013-2014 Ramiro Polla
3
+ *
4
+ * This file is part of FFmpeg.
5
+ *
6
+ * FFmpeg is free software; you can redistribute it and/or
7
+ * modify it under the terms of the GNU Lesser General Public
8
+ * License as published by the Free Software Foundation; either
9
+ * version 2.1 of the License, or (at your option) any later version.
10
+ *
11
+ * FFmpeg is distributed in the hope that it will be useful,
12
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14
+ * Lesser General Public License for more details.
15
+ *
16
+ * You should have received a copy of the GNU Lesser General Public
17
+ * License along with FFmpeg; if not, write to the Free Software
18
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19
+ */
20
+
21
+struct decklink_cctx {
22
+    const AVClass *cclass;
23
+
24
+    void *ctx;
25
+
26
+    /* Options */
27
+    int list_devices;
28
+    int list_formats;
29
+    double preroll;
30
+};
31
+
... ...
@@ -20,13 +20,6 @@
20 20
  */
21 21
 
22 22
 #include <DeckLinkAPI.h>
23
-#ifdef _WIN32
24
-#include <DeckLinkAPI_i.c>
25
-typedef unsigned long buffercount_type;
26
-#else
27
-#include <DeckLinkAPIDispatch.cpp>
28
-typedef uint32_t buffercount_type;
29
-#endif
30 23
 
31 24
 #include <pthread.h>
32 25
 #include <semaphore.h>
... ...
@@ -37,44 +30,9 @@ extern "C" {
37 37
 #include "libavutil/imgutils.h"
38 38
 }
39 39
 
40
+#include "decklink_common.h"
40 41
 #include "decklink_enc.h"
41 42
 
42
-class decklink_callback;
43
-
44
-struct decklink_ctx {
45
-    /* DeckLink SDK interfaces */
46
-    IDeckLink *dl;
47
-    IDeckLinkOutput *dlo;
48
-    decklink_callback *callback;
49
-
50
-    /* DeckLink mode information */
51
-    IDeckLinkDisplayModeIterator *itermode;
52
-    BMDTimeValue bmd_tb_den;
53
-    BMDTimeValue bmd_tb_num;
54
-    BMDDisplayMode bmd_mode;
55
-    int bmd_width;
56
-    int bmd_height;
57
-
58
-    /* Streams present */
59
-    int audio;
60
-    int video;
61
-
62
-    /* Status */
63
-    int playback_started;
64
-    int64_t last_pts;
65
-
66
-    /* Options */
67
-    int list_devices;
68
-    int list_formats;
69
-    double preroll;
70
-
71
-    int frames_preroll;
72
-    int frames_buffer;
73
-
74
-    sem_t semaphore;
75
-
76
-    int channels;
77
-};
78 43
 
79 44
 /* DeckLink callback class declaration */
80 45
 class decklink_frame : public IDeckLinkVideoFrame
... ...
@@ -109,7 +67,7 @@ private:
109 109
     int   _refs;
110 110
 };
111 111
 
112
-class decklink_callback : public IDeckLinkVideoOutputCallback
112
+class decklink_output_callback : public IDeckLinkVideoOutputCallback
113 113
 {
114 114
 public:
115 115
     virtual HRESULT STDMETHODCALLTYPE ScheduledFrameCompleted(IDeckLinkVideoFrame *_frame, BMDOutputFrameCompletionResult result)
... ...
@@ -130,99 +88,6 @@ public:
130 130
     virtual ULONG   STDMETHODCALLTYPE Release(void)                           { return 1; }
131 131
 };
132 132
 
133
-#ifdef _WIN32
134
-static IDeckLinkIterator *CreateDeckLinkIteratorInstance(void)
135
-{
136
-    IDeckLinkIterator *iter;
137
-
138
-    if (CoInitialize(NULL) != S_OK) {
139
-        av_log(NULL, AV_LOG_ERROR, "COM initialization failed.\n");
140
-        return NULL;
141
-    }
142
-
143
-    if (CoCreateInstance(CLSID_CDeckLinkIterator, NULL, CLSCTX_ALL,
144
-                         IID_IDeckLinkIterator, (void**) &iter) != S_OK) {
145
-        av_log(NULL, AV_LOG_ERROR, "DeckLink drivers not installed.\n");
146
-        return NULL;
147
-    }
148
-
149
-    return iter;
150
-}
151
-#endif
152
-
153
-/* free() is needed for a string returned by the DeckLink SDL. */
154
-#undef free
155
-
156
-#ifdef _WIN32
157
-static char *dup_wchar_to_utf8(wchar_t *w)
158
-{
159
-    char *s = NULL;
160
-    int l = WideCharToMultiByte(CP_UTF8, 0, w, -1, 0, 0, 0, 0);
161
-    s = (char *) av_malloc(l);
162
-    if (s)
163
-        WideCharToMultiByte(CP_UTF8, 0, w, -1, s, l, 0, 0);
164
-    return s;
165
-}
166
-#define DECKLINK_STR    OLECHAR *
167
-#define DECKLINK_STRDUP dup_wchar_to_utf8
168
-#else
169
-#define DECKLINK_STR    const char *
170
-#define DECKLINK_STRDUP av_strdup
171
-#endif
172
-
173
-static HRESULT IDeckLink_GetDisplayName(IDeckLink *This, const char **displayName)
174
-{
175
-    DECKLINK_STR tmpDisplayName;
176
-    HRESULT hr = This->GetDisplayName(&tmpDisplayName);
177
-    if (hr != S_OK)
178
-        return hr;
179
-    *displayName = DECKLINK_STRDUP(tmpDisplayName);
180
-    free((void *) tmpDisplayName);
181
-    return hr;
182
-}
183
-
184
-static int decklink_set_format(struct decklink_ctx *ctx,
185
-                               int width, int height,
186
-                               int tb_num, int tb_den)
187
-{
188
-    BMDDisplayModeSupport support;
189
-    IDeckLinkDisplayMode *mode;
190
-
191
-    if (tb_num == 1) {
192
-        tb_num *= 1000;
193
-        tb_den *= 1000;
194
-    }
195
-    ctx->bmd_mode = bmdModeUnknown;
196
-    while ((ctx->bmd_mode == bmdModeUnknown) && ctx->itermode->Next(&mode) == S_OK) {
197
-        BMDTimeValue bmd_tb_num, bmd_tb_den;
198
-        int bmd_width  = mode->GetWidth();
199
-        int bmd_height = mode->GetHeight();
200
-
201
-        mode->GetFrameRate(&bmd_tb_num, &bmd_tb_den);
202
-
203
-        if (bmd_width == width && bmd_height == height &&
204
-            bmd_tb_num == tb_num && bmd_tb_den == tb_den) {
205
-            ctx->bmd_mode   = mode->GetDisplayMode();
206
-            ctx->bmd_width  = bmd_width;
207
-            ctx->bmd_height = bmd_height;
208
-            ctx->bmd_tb_den = bmd_tb_den;
209
-            ctx->bmd_tb_num = bmd_tb_num;
210
-        }
211
-
212
-        mode->Release();
213
-    }
214
-    if (ctx->bmd_mode == bmdModeUnknown)
215
-        return -1;
216
-    if (ctx->dlo->DoesSupportVideoMode(ctx->bmd_mode, bmdFormat8BitYUV,
217
-                                       bmdVideoOutputFlagDefault,
218
-                                       &support, NULL) != S_OK)
219
-        return -1;
220
-    if (support == bmdDisplayModeSupported)
221
-        return 0;
222
-
223
-    return -1;
224
-}
225
-
226 133
 static int decklink_setup_video(AVFormatContext *avctx, AVStream *st)
227 134
 {
228 135
     struct decklink_cctx *cctx = (struct decklink_cctx *) avctx->priv_data;
... ...
@@ -239,7 +104,7 @@ static int decklink_setup_video(AVFormatContext *avctx, AVStream *st)
239 239
                " Only AV_PIX_FMT_UYVY422 is supported.\n");
240 240
         return -1;
241 241
     }
242
-    if (decklink_set_format(ctx, c->width, c->height,
242
+    if (ff_decklink_set_format(avctx, c->width, c->height,
243 243
                             c->time_base.num, c->time_base.den)) {
244 244
         av_log(avctx, AV_LOG_ERROR, "Unsupported video size or framerate!"
245 245
                " Check available formats with -list_formats 1.\n");
... ...
@@ -252,8 +117,8 @@ static int decklink_setup_video(AVFormatContext *avctx, AVStream *st)
252 252
     }
253 253
 
254 254
     /* Set callback. */
255
-    ctx->callback = new decklink_callback();
256
-    ctx->dlo->SetScheduledFrameCompletionCallback(ctx->callback);
255
+    ctx->output_callback = new decklink_output_callback();
256
+    ctx->dlo->SetScheduledFrameCompletionCallback(ctx->output_callback);
257 257
 
258 258
     /* Start video semaphore. */
259 259
     ctx->frames_preroll = c->time_base.den * ctx->preroll;
... ...
@@ -333,8 +198,8 @@ av_cold int ff_decklink_write_trailer(AVFormatContext *avctx)
333 333
     if (ctx->dl)
334 334
         ctx->dl->Release();
335 335
 
336
-    if (ctx->callback)
337
-        delete ctx->callback;
336
+    if (ctx->output_callback)
337
+        delete ctx->output_callback;
338 338
 
339 339
     sem_destroy(&ctx->semaphore);
340 340
 
... ...
@@ -450,6 +315,7 @@ av_cold int ff_decklink_write_header(AVFormatContext *avctx)
450 450
 {
451 451
     struct decklink_cctx *cctx = (struct decklink_cctx *) avctx->priv_data;
452 452
     struct decklink_ctx *ctx;
453
+    IDeckLinkDisplayModeIterator *itermode;
453 454
     IDeckLinkIterator *iter;
454 455
     IDeckLink *dl = NULL;
455 456
     unsigned int n;
... ...
@@ -470,22 +336,14 @@ av_cold int ff_decklink_write_header(AVFormatContext *avctx)
470 470
 
471 471
     /* List available devices. */
472 472
     if (ctx->list_devices) {
473
-        av_log(avctx, AV_LOG_INFO, "Blackmagic DeckLink devices:\n");
474
-        while (iter->Next(&dl) == S_OK) {
475
-            const char *displayName;
476
-            IDeckLink_GetDisplayName(dl, &displayName);
477
-            av_log(avctx, AV_LOG_INFO, "\t'%s'\n", displayName);
478
-            av_free((void *) displayName);
479
-            dl->Release();
480
-        }
481
-        iter->Release();
473
+        ff_decklink_list_devices(avctx);
482 474
         return AVERROR_EXIT;
483 475
     }
484 476
 
485 477
     /* Open device. */
486 478
     while (iter->Next(&dl) == S_OK) {
487 479
         const char *displayName;
488
-        IDeckLink_GetDisplayName(dl, &displayName);
480
+        ff_decklink_get_display_name(dl, &displayName);
489 481
         if (!strcmp(avctx->filename, displayName)) {
490 482
             av_free((void *) displayName);
491 483
             ctx->dl = dl;
... ...
@@ -508,40 +366,20 @@ av_cold int ff_decklink_write_header(AVFormatContext *avctx)
508 508
         return AVERROR(EIO);
509 509
     }
510 510
 
511
-    if (ctx->dlo->GetDisplayModeIterator(&ctx->itermode) != S_OK) {
512
-        av_log(avctx, AV_LOG_ERROR, "Could not get Display Mode Iterator\n");
513
-        ctx->dl->Release();
514
-        return AVERROR(EIO);
515
-    }
516
-
517 511
     /* List supported formats. */
518 512
     if (ctx->list_formats) {
519
-        IDeckLinkDisplayMode *mode;
520
-
521
-        av_log(avctx, AV_LOG_INFO, "Supported formats for '%s':\n",
522
-               avctx->filename);
523
-        while (ctx->itermode->Next(&mode) == S_OK) {
524
-            BMDTimeValue tb_num, tb_den;
525
-            mode->GetFrameRate(&tb_num, &tb_den);
526
-            av_log(avctx, AV_LOG_INFO, "\t%ldx%ld at %d/%d fps",
527
-                   mode->GetWidth(), mode->GetHeight(),
528
-                   (int) tb_den, (int) tb_num);
529
-            switch (mode->GetFieldDominance()) {
530
-            case bmdLowerFieldFirst:
531
-            av_log(avctx, AV_LOG_INFO, " (interlaced, lower field first)"); break;
532
-            case bmdUpperFieldFirst:
533
-            av_log(avctx, AV_LOG_INFO, " (interlaced, upper field first)"); break;
534
-            }
535
-            av_log(avctx, AV_LOG_INFO, "\n");
536
-            mode->Release();
537
-        }
538
-
539
-        ctx->itermode->Release();
513
+        ff_decklink_list_formats(avctx);
540 514
         ctx->dlo->Release();
541 515
         ctx->dl->Release();
542 516
         return AVERROR_EXIT;
543 517
     }
544 518
 
519
+    if (ctx->dlo->GetDisplayModeIterator(&itermode) != S_OK) {
520
+        av_log(avctx, AV_LOG_ERROR, "Could not get Display Mode Iterator\n");
521
+        ctx->dl->Release();
522
+        return AVERROR(EIO);
523
+    }
524
+
545 525
     /* Setup streams. */
546 526
     for (n = 0; n < avctx->nb_streams; n++) {
547 527
         AVStream *st = avctx->streams[n];
... ...
@@ -557,7 +395,7 @@ av_cold int ff_decklink_write_header(AVFormatContext *avctx)
557 557
             goto error;
558 558
         }
559 559
     }
560
-    ctx->itermode->Release();
560
+    itermode->Release();
561 561
 
562 562
     return 0;
563 563
 
... ...
@@ -19,17 +19,6 @@
19 19
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 20
  */
21 21
 
22
-struct decklink_cctx {
23
-    const AVClass *cclass;
24
-
25
-    void *ctx;
26
-
27
-    /* Options */
28
-    int list_devices;
29
-    int list_formats;
30
-    double preroll;
31
-};
32
-
33 22
 #ifdef __cplusplus
34 23
 extern "C" {
35 24
 #endif
... ...
@@ -22,6 +22,7 @@
22 22
 #include "libavformat/avformat.h"
23 23
 #include "libavutil/opt.h"
24 24
 
25
+#include "decklink_common_c.h"
25 26
 #include "decklink_enc.h"
26 27
 
27 28
 #define OFFSET(x) offsetof(struct decklink_cctx, x)