ffmpeg-2.8.5
git-svn-id: svn://kolibrios.org@6147 a494cfbc-eb01-0410-851d-a64ba20cac60
This commit is contained in:
@@ -0,0 +1,241 @@
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
|
||||
#include <DeckLinkAPI.h>
|
||||
#ifdef _WIN32
|
||||
#include <DeckLinkAPI_i.c>
|
||||
#else
|
||||
#include <DeckLinkAPIDispatch.cpp>
|
||||
#endif
|
||||
|
||||
#include <pthread.h>
|
||||
#include <semaphore.h>
|
||||
|
||||
extern "C" {
|
||||
#include "libavformat/avformat.h"
|
||||
#include "libavformat/internal.h"
|
||||
#include "libavutil/imgutils.h"
|
||||
}
|
||||
|
||||
#include "decklink_common.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
IDeckLinkIterator *CreateDeckLinkIteratorInstance(void)
|
||||
{
|
||||
IDeckLinkIterator *iter;
|
||||
|
||||
if (CoInitialize(NULL) < 0) {
|
||||
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
|
||||
#define DECKLINK_FREE(s) SysFreeString(s)
|
||||
#elif defined(__APPLE__)
|
||||
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
|
||||
#define DECKLINK_FREE(s) free((void *) s)
|
||||
#else
|
||||
#define DECKLINK_STR const char *
|
||||
#define DECKLINK_STRDUP av_strdup
|
||||
/* free() is needed for a string returned by the DeckLink SDL. */
|
||||
#define DECKLINK_FREE(s) free((void *) s)
|
||||
#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);
|
||||
DECKLINK_FREE(tmpDisplayName);
|
||||
return hr;
|
||||
}
|
||||
|
||||
int ff_decklink_set_format(AVFormatContext *avctx,
|
||||
int width, int height,
|
||||
int tb_num, int tb_den,
|
||||
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;
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
if (tb_num == 1) {
|
||||
tb_num *= 1000;
|
||||
tb_den *= 1000;
|
||||
}
|
||||
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();
|
||||
|
||||
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) || i == num) {
|
||||
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;
|
||||
ctx->bmd_field_dominance = mode->GetFieldDominance();
|
||||
av_log(avctx, 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) {
|
||||
if (ctx->dli->DoesSupportVideoMode(ctx->bmd_mode, bmdFormat8BitYUV,
|
||||
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) {
|
||||
return ff_decklink_set_format(avctx, 0, 0, 0, 0, direction, num);
|
||||
}
|
||||
|
||||
int ff_decklink_list_devices(AVFormatContext *avctx)
|
||||
{
|
||||
IDeckLink *dl = NULL;
|
||||
IDeckLinkIterator *iter = CreateDeckLinkIteratorInstance();
|
||||
if (!iter) {
|
||||
av_log(avctx, AV_LOG_ERROR, "Could not create DeckLink iterator\n");
|
||||
return AVERROR(EIO);
|
||||
}
|
||||
av_log(avctx, AV_LOG_INFO, "Blackmagic DeckLink devices:\n");
|
||||
while (iter->Next(&dl) == S_OK) {
|
||||
const char *displayName;
|
||||
ff_decklink_get_display_name(dl, &displayName);
|
||||
av_log(avctx, AV_LOG_INFO, "\t'%s'\n", displayName);
|
||||
av_free((void *) displayName);
|
||||
dl->Release();
|
||||
}
|
||||
iter->Release();
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ff_decklink_list_formats(AVFormatContext *avctx, decklink_direction_t direction)
|
||||
{
|
||||
struct decklink_cctx *cctx = (struct decklink_cctx *) avctx->priv_data;
|
||||
struct decklink_ctx *ctx = (struct decklink_ctx *)cctx->ctx;
|
||||
IDeckLinkDisplayModeIterator *itermode;
|
||||
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);
|
||||
}
|
||||
|
||||
av_log(avctx, AV_LOG_INFO, "Supported formats for '%s':\n",
|
||||
avctx->filename);
|
||||
while (itermode->Next(&mode) == S_OK) {
|
||||
BMDTimeValue tb_num, tb_den;
|
||||
mode->GetFrameRate(&tb_num, &tb_den);
|
||||
av_log(avctx, AV_LOG_INFO, "\t%d\t%ldx%ld at %d/%d fps",
|
||||
++i,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();
|
||||
}
|
||||
|
||||
itermode->Release();
|
||||
|
||||
return 0;
|
||||
}
|
Reference in New Issue
Block a user