decklink_common.cpp 17 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
/*
 * Blackmagic DeckLink output
 * Copyright (c) 2013-2014 Ramiro Polla, Luca Barbato, Deti Fliegl
 *
 * This file is part of FFmpeg.
 *
 * FFmpeg is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * FFmpeg is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with FFmpeg; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 */

22 23 24 25 26 27
/* Include internal.h first to avoid conflict between winsock.h (used by
 * DeckLink headers) and winsock2.h (used by libavformat) in MSVC++ builds */
extern "C" {
#include "libavformat/internal.h"
}

28 29 30 31
#include <DeckLinkAPI.h>
#ifdef _WIN32
#include <DeckLinkAPI_i.c>
#else
32 33 34 35 36 37 38 39
/* The file provided by the SDK is known to be missing prototypes, which doesn't
   cause issues with GCC since the warning doesn't apply to C++ files.  However
   Clang does complain (and warnings are treated as errors), so suppress the
   warning just for this one file */
#ifdef __clang__
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wmissing-prototypes"
#endif
40
#include <DeckLinkAPIDispatch.cpp>
41 42 43
#ifdef __clang__
#pragma clang diagnostic pop
#endif
44 45 46
#endif

extern "C" {
47
#include "libavformat/avformat.h"
48
#include "libavutil/imgutils.h"
49
#include "libavutil/intreadwrite.h"
50
#include "libavutil/bswap.h"
51
#include "avdevice.h"
52 53 54 55 56 57 58 59 60
}

#include "decklink_common.h"

#ifdef _WIN32
IDeckLinkIterator *CreateDeckLinkIteratorInstance(void)
{
    IDeckLinkIterator *iter;

61
    if (CoInitialize(NULL) < 0) {
62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87
        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

#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
88
#define DECKLINK_FREE(s) SysFreeString(s)
89
#elif defined(__APPLE__)
90 91 92 93 94 95 96 97
static char *dup_cfstring_to_utf8(CFStringRef w)
{
    char s[256];
    CFStringGetCString(w, s, 255, kCFStringEncodingUTF8);
    return av_strdup(s);
}
#define DECKLINK_STR    const __CFString *
#define DECKLINK_STRDUP dup_cfstring_to_utf8
98
#define DECKLINK_FREE(s) CFRelease(s)
99 100 101
#else
#define DECKLINK_STR    const char *
#define DECKLINK_STRDUP av_strdup
102 103
/* free() is needed for a string returned by the DeckLink SDL. */
#define DECKLINK_FREE(s) free((void *) s)
104 105 106 107 108 109 110 111 112
#endif

HRESULT ff_decklink_get_display_name(IDeckLink *This, const char **displayName)
{
    DECKLINK_STR tmpDisplayName;
    HRESULT hr = This->GetDisplayName(&tmpDisplayName);
    if (hr != S_OK)
        return hr;
    *displayName = DECKLINK_STRDUP(tmpDisplayName);
113
    DECKLINK_FREE(tmpDisplayName);
114 115 116
    return hr;
}

117 118
static int decklink_select_input(AVFormatContext *avctx, BMDDeckLinkConfigurationID cfg_id)
{
119
    struct decklink_cctx *cctx = (struct decklink_cctx *)avctx->priv_data;
120 121
    struct decklink_ctx *ctx = (struct decklink_ctx *)cctx->ctx;
    BMDDeckLinkAttributeID attr_id = (cfg_id == bmdDeckLinkConfigAudioInputConnection) ? BMDDeckLinkAudioInputConnections : BMDDeckLinkVideoInputConnections;
122
    int64_t bmd_input              = (cfg_id == bmdDeckLinkConfigAudioInputConnection) ? (int64_t)ctx->audio_input : (int64_t)ctx->video_input;
123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145
    const char *type_name          = (cfg_id == bmdDeckLinkConfigAudioInputConnection) ? "audio" : "video";
    int64_t supported_connections = 0;
    HRESULT res;

    if (bmd_input) {
        res = ctx->attr->GetInt(attr_id, &supported_connections);
        if (res != S_OK) {
            av_log(avctx, AV_LOG_ERROR, "Failed to query supported %s inputs.\n", type_name);
            return AVERROR_EXTERNAL;
        }
        if ((supported_connections & bmd_input) != bmd_input) {
            av_log(avctx, AV_LOG_ERROR, "Device does not support selected %s input.\n", type_name);
            return AVERROR(ENOSYS);
        }
        res = ctx->cfg->SetInt(cfg_id, bmd_input);
        if (res != S_OK) {
            av_log(avctx, AV_LOG_ERROR, "Failed to select %s input.\n", type_name);
            return AVERROR_EXTERNAL;
        }
    }
    return 0;
}

146 147 148 149 150 151 152 153 154 155 156 157 158
static DECKLINK_BOOL field_order_eq(enum AVFieldOrder field_order, BMDFieldDominance bmd_field_order)
{
    if (field_order == AV_FIELD_UNKNOWN)
        return true;
    if ((field_order == AV_FIELD_TT || field_order == AV_FIELD_TB) && bmd_field_order == bmdUpperFieldFirst)
        return true;
    if ((field_order == AV_FIELD_BB || field_order == AV_FIELD_BT) && bmd_field_order == bmdLowerFieldFirst)
        return true;
    if (field_order == AV_FIELD_PROGRESSIVE && (bmd_field_order == bmdProgressiveFrame || bmd_field_order == bmdProgressiveSegmentedFrame))
        return true;
    return false;
}

159 160
int ff_decklink_set_configs(AVFormatContext *avctx,
                            decklink_direction_t direction) {
161
    struct decklink_cctx *cctx = (struct decklink_cctx *)avctx->priv_data;
162 163 164
    struct decklink_ctx *ctx = (struct decklink_ctx *)cctx->ctx;
    HRESULT res;

165
    if (ctx->duplex_mode) {
166
        DECKLINK_BOOL duplex_supported = false;
167 168 169 170 171 172 173 174 175

        if (ctx->attr->GetFlag(BMDDeckLinkSupportsDuplexModeConfiguration, &duplex_supported) != S_OK)
            duplex_supported = false;

        if (duplex_supported) {
            res = ctx->cfg->SetInt(bmdDeckLinkConfigDuplexMode, ctx->duplex_mode == 2 ? bmdDuplexModeFull : bmdDuplexModeHalf);
            if (res != S_OK)
                av_log(avctx, AV_LOG_WARNING, "Setting duplex mode failed.\n");
            else
176
                av_log(avctx, AV_LOG_VERBOSE, "Successfully set duplex mode to %s duplex.\n", ctx->duplex_mode == 2 ? "full" : "half");
177 178 179 180
        } else {
            av_log(avctx, AV_LOG_WARNING, "Unable to set duplex mode, because it is not supported.\n");
        }
    }
181
    if (direction == DIRECTION_IN) {
182 183 184 185 186 187 188
        int ret;
        ret = decklink_select_input(avctx, bmdDeckLinkConfigAudioInputConnection);
        if (ret < 0)
            return ret;
        ret = decklink_select_input(avctx, bmdDeckLinkConfigVideoInputConnection);
        if (ret < 0)
            return ret;
189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210
    }
    return 0;
}

int ff_decklink_set_format(AVFormatContext *avctx,
                               int width, int height,
                               int tb_num, int tb_den,
                               enum AVFieldOrder field_order,
                               decklink_direction_t direction, int num)
{
    struct decklink_cctx *cctx = (struct decklink_cctx *)avctx->priv_data;
    struct decklink_ctx *ctx = (struct decklink_ctx *)cctx->ctx;
    BMDDisplayModeSupport support;
    IDeckLinkDisplayModeIterator *itermode;
    IDeckLinkDisplayMode *mode;
    int i = 1;
    HRESULT res;

    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, format code %s\n",
        width, height, tb_num, tb_den, field_order, direction, num, (cctx->format_code) ? cctx->format_code : "(unset)");

    if (direction == DIRECTION_IN) {
211 212 213 214 215 216 217 218 219 220
        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);
    }

221 222 223 224
    char format_buf[] = "    ";
    if (cctx->format_code)
        memcpy(format_buf, cctx->format_code, FFMIN(strlen(cctx->format_code), sizeof(format_buf)));
    BMDDisplayMode target_mode = (BMDDisplayMode)AV_RB32(format_buf);
225
    AVRational target_tb = av_make_q(tb_num, tb_den);
226 227 228 229 230
    ctx->bmd_mode = bmdModeUnknown;
    while ((ctx->bmd_mode == bmdModeUnknown) && itermode->Next(&mode) == S_OK) {
        BMDTimeValue bmd_tb_num, bmd_tb_den;
        int bmd_width  = mode->GetWidth();
        int bmd_height = mode->GetHeight();
231
        BMDDisplayMode bmd_mode = mode->GetDisplayMode();
232
        BMDFieldDominance bmd_field_dominance = mode->GetFieldDominance();
233 234

        mode->GetFrameRate(&bmd_tb_num, &bmd_tb_den);
235
        AVRational mode_tb = av_make_q(bmd_tb_num, bmd_tb_den);
236

237 238 239
        if ((bmd_width == width &&
             bmd_height == height &&
             !av_cmp_q(mode_tb, target_tb) &&
240 241 242 243
             field_order_eq(field_order, bmd_field_dominance))
             || i == num
             || target_mode == bmd_mode) {
            ctx->bmd_mode   = bmd_mode;
244 245 246 247
            ctx->bmd_width  = bmd_width;
            ctx->bmd_height = bmd_height;
            ctx->bmd_tb_den = bmd_tb_den;
            ctx->bmd_tb_num = bmd_tb_num;
248
            ctx->bmd_field_dominance = bmd_field_dominance;
249
            av_log(avctx, AV_LOG_INFO, "Found Decklink mode %d x %d with rate %.2f%s\n",
250
                bmd_width, bmd_height, 1/av_q2d(mode_tb),
251 252 253 254 255 256 257 258 259 260 261 262
                (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) {
263
        if (ctx->dli->DoesSupportVideoMode(ctx->bmd_mode, (BMDPixelFormat) cctx->raw_format,
264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279
                                           bmdVideoOutputFlagDefault,
                                           &support, NULL) != S_OK)
            return -1;
    } else {
        if (ctx->dlo->DoesSupportVideoMode(ctx->bmd_mode, bmdFormat8BitYUV,
                                           bmdVideoOutputFlagDefault,
                                           &support, NULL) != S_OK)
        return -1;
    }
    if (support == bmdDisplayModeSupported)
        return 0;

    return -1;
}

int ff_decklink_set_format(AVFormatContext *avctx, decklink_direction_t direction, int num) {
280
    return ff_decklink_set_format(avctx, 0, 0, 0, 0, AV_FIELD_UNKNOWN, direction, num);
281 282
}

283 284 285
int ff_decklink_list_devices(AVFormatContext *avctx,
                             struct AVDeviceInfoList *device_list,
                             int show_inputs, int show_outputs)
286 287 288
{
    IDeckLink *dl = NULL;
    IDeckLinkIterator *iter = CreateDeckLinkIteratorInstance();
289 290
    int ret = 0;

291 292 293 294
    if (!iter) {
        av_log(avctx, AV_LOG_ERROR, "Could not create DeckLink iterator\n");
        return AVERROR(EIO);
    }
295 296 297 298

    while (ret == 0 && iter->Next(&dl) == S_OK) {
        IDeckLinkOutput *output_config;
        IDeckLinkInput *input_config;
299
        const char *displayName;
300 301 302
        AVDeviceInfo *new_device = NULL;
        int add = 0;

303
        ff_decklink_get_display_name(dl, &displayName);
304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348

        if (show_outputs) {
            if (dl->QueryInterface(IID_IDeckLinkOutput, (void **)&output_config) == S_OK) {
                output_config->Release();
                add = 1;
            }
        }

        if (show_inputs) {
            if (dl->QueryInterface(IID_IDeckLinkInput, (void **)&input_config) == S_OK) {
                input_config->Release();
                add = 1;
            }
        }

        if (add == 1) {
            new_device = (AVDeviceInfo *) av_mallocz(sizeof(AVDeviceInfo));
            if (!new_device) {
                ret = AVERROR(ENOMEM);
                goto next;
            }
            new_device->device_name = av_strdup(displayName);
            if (!new_device->device_name) {
                ret = AVERROR(ENOMEM);
                goto next;
            }

            new_device->device_description = av_strdup(displayName);
            if (!new_device->device_description) {
                av_freep(&new_device->device_name);
                ret = AVERROR(ENOMEM);
                goto next;
            }

            if ((ret = av_dynarray_add_nofree(&device_list->devices,
                                              &device_list->nb_devices, new_device)) < 0) {
                av_freep(&new_device->device_name);
                av_freep(&new_device->device_description);
                av_freep(&new_device);
                goto next;
            }
        }

    next:
        av_freep(&displayName);
349 350 351
        dl->Release();
    }
    iter->Release();
352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376
    return ret;
}

/* This is a wrapper around the ff_decklink_list_devices() which dumps the
   output to av_log() and exits (for backward compatibility with the
   "-list_devices" argument). */
void ff_decklink_list_devices_legacy(AVFormatContext *avctx,
                                     int show_inputs, int show_outputs)
{
    struct AVDeviceInfoList *device_list = NULL;
    int ret;

    device_list = (struct AVDeviceInfoList *) av_mallocz(sizeof(AVDeviceInfoList));
    if (!device_list)
        return;

    ret = ff_decklink_list_devices(avctx, device_list, show_inputs, show_outputs);
    if (ret == 0) {
        av_log(avctx, AV_LOG_INFO, "Blackmagic DeckLink %s devices:\n",
               show_inputs ? "input" : "output");
        for (int i = 0; i < device_list->nb_devices; i++) {
            av_log(avctx, AV_LOG_INFO, "\t'%s'\n", device_list->devices[i]->device_name);
        }
    }
    avdevice_free_list_devices(&device_list);
377 378 379 380
}

int ff_decklink_list_formats(AVFormatContext *avctx, decklink_direction_t direction)
{
381
    struct decklink_cctx *cctx = (struct decklink_cctx *)avctx->priv_data;
382 383 384
    struct decklink_ctx *ctx = (struct decklink_ctx *)cctx->ctx;
    IDeckLinkDisplayModeIterator *itermode;
    IDeckLinkDisplayMode *mode;
385
    uint32_t format_code;
386 387 388
    HRESULT res;

    if (direction == DIRECTION_IN) {
389 390 391 392 393 394 395
        int ret;
        ret = decklink_select_input(avctx, bmdDeckLinkConfigAudioInputConnection);
        if (ret < 0)
            return ret;
        ret = decklink_select_input(avctx, bmdDeckLinkConfigVideoInputConnection);
        if (ret < 0)
            return ret;
396 397 398 399 400 401 402 403 404 405
        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);
    }

406
    av_log(avctx, AV_LOG_INFO, "Supported formats for '%s':\n\tformat_code\tdescription",
407
               avctx->url);
408 409 410
    while (itermode->Next(&mode) == S_OK) {
        BMDTimeValue tb_num, tb_den;
        mode->GetFrameRate(&tb_num, &tb_den);
411
        format_code = av_bswap32(mode->GetDisplayMode());
412 413
        av_log(avctx, AV_LOG_INFO, "\n\t%.4s\t\t%ldx%ld at %d/%d fps",
                (char*) &format_code, mode->GetWidth(), mode->GetHeight(),
414 415 416 417 418 419 420 421 422
                (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;
        }
        mode->Release();
    }
423
    av_log(avctx, AV_LOG_INFO, "\n");
424 425 426 427 428

    itermode->Release();

    return 0;
}
429 430 431

void ff_decklink_cleanup(AVFormatContext *avctx)
{
432 433
    struct decklink_cctx *cctx = (struct decklink_cctx *)avctx->priv_data;
    struct decklink_ctx *ctx = (struct decklink_ctx *)cctx->ctx;
434 435 436 437 438

    if (ctx->dli)
        ctx->dli->Release();
    if (ctx->dlo)
        ctx->dlo->Release();
439 440 441 442
    if (ctx->attr)
        ctx->attr->Release();
    if (ctx->cfg)
        ctx->cfg->Release();
443 444 445
    if (ctx->dl)
        ctx->dl->Release();
}
446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472

int ff_decklink_init_device(AVFormatContext *avctx, const char* name)
{
    struct decklink_cctx *cctx = (struct decklink_cctx *)avctx->priv_data;
    struct decklink_ctx *ctx = (struct decklink_ctx *)cctx->ctx;
    IDeckLink *dl = NULL;
    IDeckLinkIterator *iter = CreateDeckLinkIteratorInstance();
    if (!iter) {
        av_log(avctx, AV_LOG_ERROR, "Could not create DeckLink iterator\n");
        return AVERROR_EXTERNAL;
    }

    while (iter->Next(&dl) == S_OK) {
        const char *displayName;
        ff_decklink_get_display_name(dl, &displayName);
        if (!strcmp(name, displayName)) {
            av_free((void *)displayName);
            ctx->dl = dl;
            break;
        }
        av_free((void *)displayName);
        dl->Release();
    }
    iter->Release();
    if (!ctx->dl)
        return AVERROR(ENXIO);

473 474 475 476 477 478 479 480 481 482 483 484
    if (ctx->dl->QueryInterface(IID_IDeckLinkConfiguration, (void **)&ctx->cfg) != S_OK) {
        av_log(avctx, AV_LOG_ERROR, "Could not get configuration interface for '%s'\n", name);
        ff_decklink_cleanup(avctx);
        return AVERROR_EXTERNAL;
    }

    if (ctx->dl->QueryInterface(IID_IDeckLinkAttributes, (void **)&ctx->attr) != S_OK) {
        av_log(avctx, AV_LOG_ERROR, "Could not get attributes interface for '%s'\n", name);
        ff_decklink_cleanup(avctx);
        return AVERROR_EXTERNAL;
    }

485 486
    return 0;
}