Signed-off-by: Michael Niedermayer <michaelni@gmx.at>
Deti Fliegl authored on 2014/09/22 08:39:50... | ... |
@@ -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 |