26c0776b020a88a3cdbe0b802595fc292b7b2522
[ffmpeg.git] / libavdevice / decklink_common.cpp
1 /*
2  * Blackmagic DeckLink output
3  * Copyright (c) 2013-2014 Ramiro Polla, Luca Barbato, Deti Fliegl
4  *
5  * This file is part of FFmpeg.
6  *
7  * FFmpeg is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * FFmpeg is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with FFmpeg; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20  */
21
22 #include <DeckLinkAPI.h>
23 #ifdef _WIN32
24 #include <DeckLinkAPI_i.c>
25 #else
26 #include <DeckLinkAPIDispatch.cpp>
27 #endif
28
29 #include <pthread.h>
30 #include <semaphore.h>
31
32 extern "C" {
33 #include "libavformat/avformat.h"
34 #include "libavformat/internal.h"
35 #include "libavutil/imgutils.h"
36 #include "libavutil/bswap.h"
37 }
38
39 #include "decklink_common.h"
40
41 #ifdef _WIN32
42 IDeckLinkIterator *CreateDeckLinkIteratorInstance(void)
43 {
44     IDeckLinkIterator *iter;
45
46     if (CoInitialize(NULL) < 0) {
47         av_log(NULL, AV_LOG_ERROR, "COM initialization failed.\n");
48         return NULL;
49     }
50
51     if (CoCreateInstance(CLSID_CDeckLinkIterator, NULL, CLSCTX_ALL,
52                          IID_IDeckLinkIterator, (void**) &iter) != S_OK) {
53         av_log(NULL, AV_LOG_ERROR, "DeckLink drivers not installed.\n");
54         return NULL;
55     }
56
57     return iter;
58 }
59 #endif
60
61 #ifdef _WIN32
62 static char *dup_wchar_to_utf8(wchar_t *w)
63 {
64     char *s = NULL;
65     int l = WideCharToMultiByte(CP_UTF8, 0, w, -1, 0, 0, 0, 0);
66     s = (char *) av_malloc(l);
67     if (s)
68         WideCharToMultiByte(CP_UTF8, 0, w, -1, s, l, 0, 0);
69     return s;
70 }
71 #define DECKLINK_STR    OLECHAR *
72 #define DECKLINK_STRDUP dup_wchar_to_utf8
73 #define DECKLINK_FREE(s) SysFreeString(s)
74 #define DECKLINK_BOOL BOOL
75 #elif defined(__APPLE__)
76 static char *dup_cfstring_to_utf8(CFStringRef w)
77 {
78     char s[256];
79     CFStringGetCString(w, s, 255, kCFStringEncodingUTF8);
80     return av_strdup(s);
81 }
82 #define DECKLINK_STR    const __CFString *
83 #define DECKLINK_STRDUP dup_cfstring_to_utf8
84 #define DECKLINK_FREE(s) free((void *) s)
85 #define DECKLINK_BOOL bool
86 #else
87 #define DECKLINK_STR    const char *
88 #define DECKLINK_STRDUP av_strdup
89 /* free() is needed for a string returned by the DeckLink SDL. */
90 #define DECKLINK_FREE(s) free((void *) s)
91 #define DECKLINK_BOOL bool
92 #endif
93
94 HRESULT ff_decklink_get_display_name(IDeckLink *This, const char **displayName)
95 {
96     DECKLINK_STR tmpDisplayName;
97     HRESULT hr = This->GetDisplayName(&tmpDisplayName);
98     if (hr != S_OK)
99         return hr;
100     *displayName = DECKLINK_STRDUP(tmpDisplayName);
101     DECKLINK_FREE(tmpDisplayName);
102     return hr;
103 }
104
105 static int decklink_select_input(AVFormatContext *avctx, BMDDeckLinkConfigurationID cfg_id)
106 {
107     struct decklink_cctx *cctx = (struct decklink_cctx *)avctx->priv_data;
108     struct decklink_ctx *ctx = (struct decklink_ctx *)cctx->ctx;
109     BMDDeckLinkAttributeID attr_id = (cfg_id == bmdDeckLinkConfigAudioInputConnection) ? BMDDeckLinkAudioInputConnections : BMDDeckLinkVideoInputConnections;
110     int64_t bmd_input              = (cfg_id == bmdDeckLinkConfigAudioInputConnection) ? (int64_t)ctx->audio_input : (int64_t)ctx->video_input;
111     const char *type_name          = (cfg_id == bmdDeckLinkConfigAudioInputConnection) ? "audio" : "video";
112     int64_t supported_connections = 0;
113     HRESULT res;
114
115     if (bmd_input) {
116         res = ctx->attr->GetInt(attr_id, &supported_connections);
117         if (res != S_OK) {
118             av_log(avctx, AV_LOG_ERROR, "Failed to query supported %s inputs.\n", type_name);
119             return AVERROR_EXTERNAL;
120         }
121         if ((supported_connections & bmd_input) != bmd_input) {
122             av_log(avctx, AV_LOG_ERROR, "Device does not support selected %s input.\n", type_name);
123             return AVERROR(ENOSYS);
124         }
125         res = ctx->cfg->SetInt(cfg_id, bmd_input);
126         if (res != S_OK) {
127             av_log(avctx, AV_LOG_ERROR, "Failed to select %s input.\n", type_name);
128             return AVERROR_EXTERNAL;
129         }
130     }
131     return 0;
132 }
133
134 static DECKLINK_BOOL field_order_eq(enum AVFieldOrder field_order, BMDFieldDominance bmd_field_order)
135 {
136     if (field_order == AV_FIELD_UNKNOWN)
137         return true;
138     if ((field_order == AV_FIELD_TT || field_order == AV_FIELD_TB) && bmd_field_order == bmdUpperFieldFirst)
139         return true;
140     if ((field_order == AV_FIELD_BB || field_order == AV_FIELD_BT) && bmd_field_order == bmdLowerFieldFirst)
141         return true;
142     if (field_order == AV_FIELD_PROGRESSIVE && (bmd_field_order == bmdProgressiveFrame || bmd_field_order == bmdProgressiveSegmentedFrame))
143         return true;
144     return false;
145 }
146
147 int ff_decklink_set_format(AVFormatContext *avctx,
148                                int width, int height,
149                                int tb_num, int tb_den,
150                                enum AVFieldOrder field_order,
151                                decklink_direction_t direction, int num)
152 {
153     struct decklink_cctx *cctx = (struct decklink_cctx *)avctx->priv_data;
154     struct decklink_ctx *ctx = (struct decklink_ctx *)cctx->ctx;
155     BMDDisplayModeSupport support;
156     IDeckLinkDisplayModeIterator *itermode;
157     IDeckLinkDisplayMode *mode;
158     int i = 1;
159     HRESULT res;
160
161     av_log(avctx, AV_LOG_DEBUG, "Trying to find mode for frame size %dx%d, frame timing %d/%d, field order %d, direction %d, mode number %d\n",
162         width, height, tb_num, tb_den, field_order, direction, num);
163
164     if (ctx->duplex_mode) {
165         DECKLINK_BOOL duplex_supported = false;
166
167         if (ctx->attr->GetFlag(BMDDeckLinkSupportsDuplexModeConfiguration, &duplex_supported) != S_OK)
168             duplex_supported = false;
169
170         if (duplex_supported) {
171             res = ctx->cfg->SetInt(bmdDeckLinkConfigDuplexMode, ctx->duplex_mode == 2 ? bmdDuplexModeFull : bmdDuplexModeHalf);
172             if (res != S_OK)
173                 av_log(avctx, AV_LOG_WARNING, "Setting duplex mode failed.\n");
174             else
175                 av_log(avctx, AV_LOG_VERBOSE, "Successfully set duplex mode to %s duplex.\n", ctx->duplex_mode == 2 ? "full" : "half");
176         } else {
177             av_log(avctx, AV_LOG_WARNING, "Unable to set duplex mode, because it is not supported.\n");
178         }
179     }
180
181     if (direction == DIRECTION_IN) {
182         int ret;
183         ret = decklink_select_input(avctx, bmdDeckLinkConfigAudioInputConnection);
184         if (ret < 0)
185             return ret;
186         ret = decklink_select_input(avctx, bmdDeckLinkConfigVideoInputConnection);
187         if (ret < 0)
188             return ret;
189         res = ctx->dli->GetDisplayModeIterator (&itermode);
190     } else {
191         res = ctx->dlo->GetDisplayModeIterator (&itermode);
192     }
193
194     if (res!= S_OK) {
195             av_log(avctx, AV_LOG_ERROR, "Could not get Display Mode Iterator\n");
196             return AVERROR(EIO);
197     }
198
199     AVRational target_tb = av_make_q(tb_num, tb_den);
200     ctx->bmd_mode = bmdModeUnknown;
201     while ((ctx->bmd_mode == bmdModeUnknown) && itermode->Next(&mode) == S_OK) {
202         BMDTimeValue bmd_tb_num, bmd_tb_den;
203         int bmd_width  = mode->GetWidth();
204         int bmd_height = mode->GetHeight();
205         BMDFieldDominance bmd_field_dominance = mode->GetFieldDominance();
206
207         mode->GetFrameRate(&bmd_tb_num, &bmd_tb_den);
208         AVRational mode_tb = av_make_q(bmd_tb_num, bmd_tb_den);
209
210         if ((bmd_width == width &&
211              bmd_height == height &&
212              !av_cmp_q(mode_tb, target_tb) &&
213              field_order_eq(field_order, bmd_field_dominance)) || i == num) {
214             ctx->bmd_mode   = mode->GetDisplayMode();
215             ctx->bmd_width  = bmd_width;
216             ctx->bmd_height = bmd_height;
217             ctx->bmd_tb_den = bmd_tb_den;
218             ctx->bmd_tb_num = bmd_tb_num;
219             ctx->bmd_field_dominance = bmd_field_dominance;
220             av_log(avctx, AV_LOG_INFO, "Found Decklink mode %d x %d with rate %.2f%s\n",
221                 bmd_width, bmd_height, 1/av_q2d(mode_tb),
222                 (ctx->bmd_field_dominance==bmdLowerFieldFirst || ctx->bmd_field_dominance==bmdUpperFieldFirst)?"(i)":"");
223         }
224
225         mode->Release();
226         i++;
227     }
228
229     itermode->Release();
230
231     if (ctx->bmd_mode == bmdModeUnknown)
232         return -1;
233     if (direction == DIRECTION_IN) {
234         if (ctx->dli->DoesSupportVideoMode(ctx->bmd_mode, bmdFormat8BitYUV,
235                                            bmdVideoOutputFlagDefault,
236                                            &support, NULL) != S_OK)
237             return -1;
238     } else {
239         if (ctx->dlo->DoesSupportVideoMode(ctx->bmd_mode, bmdFormat8BitYUV,
240                                            bmdVideoOutputFlagDefault,
241                                            &support, NULL) != S_OK)
242         return -1;
243     }
244     if (support == bmdDisplayModeSupported)
245         return 0;
246
247     return -1;
248 }
249
250 int ff_decklink_set_format(AVFormatContext *avctx, decklink_direction_t direction, int num) {
251     return ff_decklink_set_format(avctx, 0, 0, 0, 0, AV_FIELD_UNKNOWN, direction, num);
252 }
253
254 int ff_decklink_list_devices(AVFormatContext *avctx)
255 {
256     IDeckLink *dl = NULL;
257     IDeckLinkIterator *iter = CreateDeckLinkIteratorInstance();
258     if (!iter) {
259         av_log(avctx, AV_LOG_ERROR, "Could not create DeckLink iterator\n");
260         return AVERROR(EIO);
261     }
262     av_log(avctx, AV_LOG_INFO, "Blackmagic DeckLink devices:\n");
263     while (iter->Next(&dl) == S_OK) {
264         const char *displayName;
265         ff_decklink_get_display_name(dl, &displayName);
266         av_log(avctx, AV_LOG_INFO, "\t'%s'\n", displayName);
267         av_free((void *) displayName);
268         dl->Release();
269     }
270     iter->Release();
271     return 0;
272 }
273
274 int ff_decklink_list_formats(AVFormatContext *avctx, decklink_direction_t direction)
275 {
276     struct decklink_cctx *cctx = (struct decklink_cctx *)avctx->priv_data;
277     struct decklink_ctx *ctx = (struct decklink_ctx *)cctx->ctx;
278     IDeckLinkDisplayModeIterator *itermode;
279     IDeckLinkDisplayMode *mode;
280     uint32_t format_code;
281     int i=0;
282     HRESULT res;
283
284     if (direction == DIRECTION_IN) {
285         int ret;
286         ret = decklink_select_input(avctx, bmdDeckLinkConfigAudioInputConnection);
287         if (ret < 0)
288             return ret;
289         ret = decklink_select_input(avctx, bmdDeckLinkConfigVideoInputConnection);
290         if (ret < 0)
291             return ret;
292         res = ctx->dli->GetDisplayModeIterator (&itermode);
293     } else {
294         res = ctx->dlo->GetDisplayModeIterator (&itermode);
295     }
296
297     if (res!= S_OK) {
298             av_log(avctx, AV_LOG_ERROR, "Could not get Display Mode Iterator\n");
299             return AVERROR(EIO);
300     }
301
302     av_log(avctx, AV_LOG_INFO, "Supported formats for '%s':\n\tmode\tformat_code\tdescription",
303                avctx->filename);
304     while (itermode->Next(&mode) == S_OK) {
305         BMDTimeValue tb_num, tb_den;
306         mode->GetFrameRate(&tb_num, &tb_den);
307         format_code = av_bswap32(mode->GetDisplayMode());
308         av_log(avctx, AV_LOG_INFO, "\n\t%d\t%.4s\t\t%ldx%ld at %d/%d fps",
309                 ++i, (char*) &format_code, mode->GetWidth(), mode->GetHeight(),
310                 (int) tb_den, (int) tb_num);
311         switch (mode->GetFieldDominance()) {
312         case bmdLowerFieldFirst:
313         av_log(avctx, AV_LOG_INFO, " (interlaced, lower field first)"); break;
314         case bmdUpperFieldFirst:
315         av_log(avctx, AV_LOG_INFO, " (interlaced, upper field first)"); break;
316         }
317         mode->Release();
318     }
319     av_log(avctx, AV_LOG_INFO, "\n");
320
321     itermode->Release();
322
323     return 0;
324 }
325
326 void ff_decklink_cleanup(AVFormatContext *avctx)
327 {
328     struct decklink_cctx *cctx = (struct decklink_cctx *)avctx->priv_data;
329     struct decklink_ctx *ctx = (struct decklink_ctx *)cctx->ctx;
330
331     if (ctx->dli)
332         ctx->dli->Release();
333     if (ctx->dlo)
334         ctx->dlo->Release();
335     if (ctx->attr)
336         ctx->attr->Release();
337     if (ctx->cfg)
338         ctx->cfg->Release();
339     if (ctx->dl)
340         ctx->dl->Release();
341 }
342
343 int ff_decklink_init_device(AVFormatContext *avctx, const char* name)
344 {
345     struct decklink_cctx *cctx = (struct decklink_cctx *)avctx->priv_data;
346     struct decklink_ctx *ctx = (struct decklink_ctx *)cctx->ctx;
347     IDeckLink *dl = NULL;
348     IDeckLinkIterator *iter = CreateDeckLinkIteratorInstance();
349     if (!iter) {
350         av_log(avctx, AV_LOG_ERROR, "Could not create DeckLink iterator\n");
351         return AVERROR_EXTERNAL;
352     }
353
354     while (iter->Next(&dl) == S_OK) {
355         const char *displayName;
356         ff_decklink_get_display_name(dl, &displayName);
357         if (!strcmp(name, displayName)) {
358             av_free((void *)displayName);
359             ctx->dl = dl;
360             break;
361         }
362         av_free((void *)displayName);
363         dl->Release();
364     }
365     iter->Release();
366     if (!ctx->dl)
367         return AVERROR(ENXIO);
368
369     if (ctx->dl->QueryInterface(IID_IDeckLinkConfiguration, (void **)&ctx->cfg) != S_OK) {
370         av_log(avctx, AV_LOG_ERROR, "Could not get configuration interface for '%s'\n", name);
371         ff_decklink_cleanup(avctx);
372         return AVERROR_EXTERNAL;
373     }
374
375     if (ctx->dl->QueryInterface(IID_IDeckLinkAttributes, (void **)&ctx->attr) != S_OK) {
376         av_log(avctx, AV_LOG_ERROR, "Could not get attributes interface for '%s'\n", name);
377         ff_decklink_cleanup(avctx);
378         return AVERROR_EXTERNAL;
379     }
380
381     return 0;
382 }