mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-01-26 17:18:15 +00:00
decklink: Add decklink plugin
Source and sink elements for BlackMagic DeckLink SDI cards.
This commit is contained in:
parent
e319b82842
commit
8961f6a900
13 changed files with 4176 additions and 1 deletions
10
configure.ac
10
configure.ac
|
@ -694,6 +694,15 @@ AG_GST_CHECK_FEATURE(DC1394, [libdc1394], dc1394, [
|
|||
AC_SUBST(LIBDC1394_LIBS)
|
||||
])
|
||||
|
||||
dnl *** decklink ***
|
||||
translit(dnm, m, l) AM_CONDITIONAL(USE_DECKLINK, true)
|
||||
AG_GST_CHECK_FEATURE(DECKLINK, [decklink], decklink, [
|
||||
HAVE_DECKLINK=yes
|
||||
DECKLINK_CXXFLAGS=
|
||||
DECKLINK_LIBS=
|
||||
AC_SUBST(DECKLINK_CXXFLAGS)
|
||||
AC_SUBST(DECKLINK_LIBS)
|
||||
])
|
||||
|
||||
dnl **** DirectFB ****
|
||||
translit(dnm, m, l) AM_CONDITIONAL(USE_DIRECTFB, true)
|
||||
|
@ -1799,6 +1808,7 @@ sys/dshowdecwrapper/Makefile
|
|||
sys/acmenc/Makefile
|
||||
sys/acmmp3dec/Makefile
|
||||
sys/applemedia/Makefile
|
||||
sys/decklink/Makefile
|
||||
sys/directdraw/Makefile
|
||||
sys/directsound/Makefile
|
||||
sys/dshowsrcwrapper/Makefile
|
||||
|
|
|
@ -22,6 +22,12 @@ endif
|
|||
# CDROM_DIR=
|
||||
# endif
|
||||
|
||||
if USE_DECKLINK
|
||||
DECKLINK_DIR=decklink
|
||||
else
|
||||
DECKLINK_DIR=
|
||||
endif
|
||||
|
||||
if USE_DIRECTDRAW
|
||||
DIRECTDRAW_DIR=directdraw
|
||||
else
|
||||
|
@ -97,7 +103,7 @@ endif
|
|||
|
||||
SUBDIRS = $(ACM_DIR) $(APPLE_MEDIA_DIR) $(DIRECTDRAW_DIR) $(DIRECTSOUND_DIR) $(DVB_DIR) $(FBDEV_DIR) $(LINSYS_DIR) $(OSX_VIDEO_DIR) $(QT_DIR) $(SHM_DIR) $(VCD_DIR) $(VDPAU_DIR) $(WININET_DIR)
|
||||
|
||||
DIST_SUBDIRS = acmenc acmmp3dec applemedia directdraw directsound dvb linsys fbdev dshowdecwrapper dshowsrcwrapper dshowvideosink \
|
||||
DIST_SUBDIRS = acmenc acmmp3dec applemedia decklink directdraw directsound dvb linsys fbdev dshowdecwrapper dshowsrcwrapper dshowvideosink \
|
||||
osxvideo qtwrapper shm vcd vdpau wasapi wininet winks winscreencap
|
||||
|
||||
include $(top_srcdir)/common/parallel-subdirs.mak
|
||||
|
|
1095
sys/decklink/DeckLinkAPI.h
Normal file
1095
sys/decklink/DeckLinkAPI.h
Normal file
File diff suppressed because it is too large
Load diff
110
sys/decklink/DeckLinkAPIDispatch.cpp
Normal file
110
sys/decklink/DeckLinkAPIDispatch.cpp
Normal file
|
@ -0,0 +1,110 @@
|
|||
/* -LICENSE-START-
|
||||
** Copyright (c) 2009 Blackmagic Design
|
||||
**
|
||||
** Permission is hereby granted, free of charge, to any person or organization
|
||||
** obtaining a copy of the software and accompanying documentation covered by
|
||||
** this license (the "Software") to use, reproduce, display, distribute,
|
||||
** execute, and transmit the Software, and to prepare derivative works of the
|
||||
** Software, and to permit third-parties to whom the Software is furnished to
|
||||
** do so, all subject to the following:
|
||||
**
|
||||
** The copyright notices in the Software and this entire statement, including
|
||||
** the above license grant, this restriction and the following disclaimer,
|
||||
** must be included in all copies of the Software, in whole or in part, and
|
||||
** all derivative works of the Software, unless such copies or derivative
|
||||
** works are solely in the form of machine-executable object code generated by
|
||||
** a source language processor.
|
||||
**
|
||||
** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
** FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
|
||||
** SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
|
||||
** FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
|
||||
** ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
** DEALINGS IN THE SOFTWARE.
|
||||
** -LICENSE-END-
|
||||
**/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <pthread.h>
|
||||
#include <dlfcn.h>
|
||||
|
||||
#include "DeckLinkAPI.h"
|
||||
|
||||
#define kDeckLinkAPI_Name "libDeckLinkAPI.so"
|
||||
#define KDeckLinkPreviewAPI_Name "libDeckLinkPreviewAPI.so"
|
||||
|
||||
typedef IDeckLinkIterator* (*CreateIteratorFunc)(void);
|
||||
typedef IDeckLinkGLScreenPreviewHelper* (*CreateOpenGLScreenPreviewHelperFunc)(void);
|
||||
typedef IDeckLinkVideoConversion* (*CreateVideoConversionInstanceFunc)(void);
|
||||
|
||||
static pthread_once_t gDeckLinkOnceControl = PTHREAD_ONCE_INIT;
|
||||
static pthread_once_t gPreviewOnceControl = PTHREAD_ONCE_INIT;
|
||||
|
||||
static CreateIteratorFunc gCreateIteratorFunc = NULL;
|
||||
static CreateOpenGLScreenPreviewHelperFunc gCreateOpenGLPreviewFunc = NULL;
|
||||
static CreateVideoConversionInstanceFunc gCreateVideoConversionFunc = NULL;
|
||||
|
||||
static
|
||||
void InitDeckLinkAPI (void)
|
||||
{
|
||||
void *libraryHandle;
|
||||
|
||||
libraryHandle = dlopen(kDeckLinkAPI_Name, RTLD_NOW|RTLD_GLOBAL);
|
||||
if (!libraryHandle)
|
||||
{
|
||||
fprintf(stderr, "%s\n", dlerror());
|
||||
return;
|
||||
}
|
||||
gCreateIteratorFunc = (CreateIteratorFunc)dlsym(libraryHandle, "CreateDeckLinkIteratorInstance_0001");
|
||||
if (!gCreateIteratorFunc)
|
||||
fprintf(stderr, "%s\n", dlerror());
|
||||
gCreateVideoConversionFunc = (CreateVideoConversionInstanceFunc)dlsym(libraryHandle, "CreateVideoConversionInstance_0001");
|
||||
if (!gCreateVideoConversionFunc)
|
||||
fprintf(stderr, "%s\n", dlerror());
|
||||
}
|
||||
|
||||
static
|
||||
void InitDeckLinkPreviewAPI (void)
|
||||
{
|
||||
void *libraryHandle;
|
||||
|
||||
libraryHandle = dlopen(KDeckLinkPreviewAPI_Name, RTLD_NOW|RTLD_GLOBAL);
|
||||
if (!libraryHandle)
|
||||
{
|
||||
fprintf(stderr, "%s\n", dlerror());
|
||||
return;
|
||||
}
|
||||
gCreateOpenGLPreviewFunc = (CreateOpenGLScreenPreviewHelperFunc)dlsym(libraryHandle, "CreateOpenGLScreenPreviewHelper_0001");
|
||||
if (!gCreateOpenGLPreviewFunc)
|
||||
fprintf(stderr, "%s\n", dlerror());
|
||||
}
|
||||
|
||||
IDeckLinkIterator* CreateDeckLinkIteratorInstance (void)
|
||||
{
|
||||
pthread_once(&gDeckLinkOnceControl, InitDeckLinkAPI);
|
||||
|
||||
if (gCreateIteratorFunc == NULL)
|
||||
return NULL;
|
||||
return gCreateIteratorFunc();
|
||||
}
|
||||
|
||||
IDeckLinkGLScreenPreviewHelper* CreateOpenGLScreenPreviewHelper (void)
|
||||
{
|
||||
pthread_once(&gDeckLinkOnceControl, InitDeckLinkAPI);
|
||||
pthread_once(&gPreviewOnceControl, InitDeckLinkPreviewAPI);
|
||||
|
||||
if (gCreateOpenGLPreviewFunc == NULL)
|
||||
return NULL;
|
||||
return gCreateOpenGLPreviewFunc();
|
||||
}
|
||||
|
||||
IDeckLinkVideoConversion* CreateVideoConversionInstance (void)
|
||||
{
|
||||
pthread_once(&gDeckLinkOnceControl, InitDeckLinkAPI);
|
||||
|
||||
if (gCreateVideoConversionFunc == NULL)
|
||||
return NULL;
|
||||
return gCreateVideoConversionFunc();
|
||||
}
|
||||
|
99
sys/decklink/LinuxCOM.h
Normal file
99
sys/decklink/LinuxCOM.h
Normal file
|
@ -0,0 +1,99 @@
|
|||
/* -LICENSE-START-
|
||||
** Copyright (c) 2009 Blackmagic Design
|
||||
**
|
||||
** Permission is hereby granted, free of charge, to any person or organization
|
||||
** obtaining a copy of the software and accompanying documentation covered by
|
||||
** this license (the "Software") to use, reproduce, display, distribute,
|
||||
** execute, and transmit the Software, and to prepare derivative works of the
|
||||
** Software, and to permit third-parties to whom the Software is furnished to
|
||||
** do so, all subject to the following:
|
||||
**
|
||||
** The copyright notices in the Software and this entire statement, including
|
||||
** the above license grant, this restriction and the following disclaimer,
|
||||
** must be included in all copies of the Software, in whole or in part, and
|
||||
** all derivative works of the Software, unless such copies or derivative
|
||||
** works are solely in the form of machine-executable object code generated by
|
||||
** a source language processor.
|
||||
**
|
||||
** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
** FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
|
||||
** SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
|
||||
** FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
|
||||
** ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
** DEALINGS IN THE SOFTWARE.
|
||||
** -LICENSE-END-
|
||||
*/
|
||||
|
||||
#ifndef __LINUX_COM_H_
|
||||
#define __LINUX_COM_H_
|
||||
|
||||
struct REFIID
|
||||
{
|
||||
unsigned char byte0;
|
||||
unsigned char byte1;
|
||||
unsigned char byte2;
|
||||
unsigned char byte3;
|
||||
unsigned char byte4;
|
||||
unsigned char byte5;
|
||||
unsigned char byte6;
|
||||
unsigned char byte7;
|
||||
unsigned char byte8;
|
||||
unsigned char byte9;
|
||||
unsigned char byte10;
|
||||
unsigned char byte11;
|
||||
unsigned char byte12;
|
||||
unsigned char byte13;
|
||||
unsigned char byte14;
|
||||
unsigned char byte15;
|
||||
};
|
||||
|
||||
typedef REFIID CFUUIDBytes;
|
||||
#define CFUUIDGetUUIDBytes(x) x
|
||||
|
||||
typedef int HRESULT;
|
||||
typedef unsigned long ULONG;
|
||||
typedef void *LPVOID;
|
||||
|
||||
#define SUCCEEDED(Status) ((HRESULT)(Status) >= 0)
|
||||
#define FAILED(Status) ((HRESULT)(Status)<0)
|
||||
|
||||
#define IS_ERROR(Status) ((unsigned long)(Status) >> 31 == SEVERITY_ERROR)
|
||||
#define HRESULT_CODE(hr) ((hr) & 0xFFFF)
|
||||
#define HRESULT_FACILITY(hr) (((hr) >> 16) & 0x1fff)
|
||||
#define HRESULT_SEVERITY(hr) (((hr) >> 31) & 0x1)
|
||||
#define SEVERITY_SUCCESS 0
|
||||
#define SEVERITY_ERROR 1
|
||||
|
||||
#define MAKE_HRESULT(sev,fac,code) ((HRESULT) (((unsigned long)(sev)<<31) | ((unsigned long)(fac)<<16) | ((unsigned long)(code))) )
|
||||
|
||||
#define S_OK ((HRESULT)0x00000000L)
|
||||
#define S_FALSE ((HRESULT)0x00000001L)
|
||||
#define E_UNEXPECTED ((HRESULT)0x8000FFFFL)
|
||||
#define E_NOTIMPL ((HRESULT)0x80000001L)
|
||||
#define E_OUTOFMEMORY ((HRESULT)0x80000002L)
|
||||
#define E_INVALIDARG ((HRESULT)0x80000003L)
|
||||
#define E_NOINTERFACE ((HRESULT)0x80000004L)
|
||||
#define E_POINTER ((HRESULT)0x80000005L)
|
||||
#define E_HANDLE ((HRESULT)0x80000006L)
|
||||
#define E_ABORT ((HRESULT)0x80000007L)
|
||||
#define E_FAIL ((HRESULT)0x80000008L)
|
||||
#define E_ACCESSDENIED ((HRESULT)0x80000009L)
|
||||
|
||||
#define STDMETHODCALLTYPE
|
||||
|
||||
#define IID_IUnknown (REFIID){0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x46}
|
||||
#define IUnknownUUID IID_IUnknown
|
||||
|
||||
#ifdef __cplusplus
|
||||
class IUnknown
|
||||
{
|
||||
public:
|
||||
virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, LPVOID *ppv) = 0;
|
||||
virtual ULONG STDMETHODCALLTYPE AddRef(void) = 0;
|
||||
virtual ULONG STDMETHODCALLTYPE Release(void) = 0;
|
||||
};
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
25
sys/decklink/Makefile.am
Normal file
25
sys/decklink/Makefile.am
Normal file
|
@ -0,0 +1,25 @@
|
|||
plugin_LTLIBRARIES = libgstdecklink.la
|
||||
|
||||
libgstdecklink_la_CPPFLAGS = \
|
||||
$(GST_PLUGINS_BAD_CXXFLAGS) \
|
||||
$(GST_PLUGINS_BASE_CXXFLAGS) \
|
||||
$(GST_CXXFLAGS) \
|
||||
$(DECKLINK_CXXFLAGS)
|
||||
libgstdecklink_la_LIBADD = \
|
||||
$(GST_PLUGINS_BASE_LIBS) -lgstvideo-$(GST_MAJORMINOR) \
|
||||
$(GST_BASE_LIBS) \
|
||||
$(GST_LIBS) \
|
||||
$(DECKLINK_LIBS)
|
||||
libgstdecklink_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) $(LIBM)
|
||||
libgstdecklink_la_LIBTOOLFLAGS = --tag=disable-static
|
||||
|
||||
libgstdecklink_la_SOURCES = \
|
||||
gstdecklinksrc.cpp \
|
||||
gstdecklinksrc.h \
|
||||
gstdecklinksink.cpp \
|
||||
gstdecklinksink.h \
|
||||
gstdecklink.cpp \
|
||||
capture.cpp \
|
||||
capture.h \
|
||||
DeckLinkAPIDispatch.cpp
|
||||
|
430
sys/decklink/capture.cpp
Normal file
430
sys/decklink/capture.cpp
Normal file
|
@ -0,0 +1,430 @@
|
|||
/* -LICENSE-START-
|
||||
** Copyright (c) 2009 Blackmagic Design
|
||||
**
|
||||
** Permission is hereby granted, free of charge, to any person or organization
|
||||
** obtaining a copy of the software and accompanying documentation covered by
|
||||
** this license (the "Software") to use, reproduce, display, distribute,
|
||||
** execute, and transmit the Software, and to prepare derivative works of the
|
||||
** Software, and to permit third-parties to whom the Software is furnished to
|
||||
** do so, all subject to the following:
|
||||
**
|
||||
** The copyright notices in the Software and this entire statement, including
|
||||
** the above license grant, this restriction and the following disclaimer,
|
||||
** must be included in all copies of the Software, in whole or in part, and
|
||||
** all derivative works of the Software, unless such copies or derivative
|
||||
** works are solely in the form of machine-executable object code generated by
|
||||
** a source language processor.
|
||||
**
|
||||
** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
** FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
|
||||
** SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
|
||||
** FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
|
||||
** ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
** DEALINGS IN THE SOFTWARE.
|
||||
** -LICENSE-END-
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <pthread.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#include "gstdecklinksrc.h"
|
||||
|
||||
#include "DeckLinkAPI.h"
|
||||
#include "capture.h"
|
||||
|
||||
|
||||
int videoOutputFile = -1;
|
||||
int audioOutputFile = -1;
|
||||
|
||||
IDeckLink *deckLink;
|
||||
IDeckLinkInput *deckLinkInput;
|
||||
IDeckLinkDisplayModeIterator *displayModeIterator;
|
||||
|
||||
static BMDTimecodeFormat g_timecodeFormat = 0;
|
||||
|
||||
DeckLinkCaptureDelegate::DeckLinkCaptureDelegate ():m_refCount (0)
|
||||
{
|
||||
pthread_mutex_init (&m_mutex, NULL);
|
||||
}
|
||||
|
||||
DeckLinkCaptureDelegate::~DeckLinkCaptureDelegate ()
|
||||
{
|
||||
pthread_mutex_destroy (&m_mutex);
|
||||
}
|
||||
|
||||
ULONG
|
||||
DeckLinkCaptureDelegate::AddRef (void)
|
||||
{
|
||||
pthread_mutex_lock (&m_mutex);
|
||||
m_refCount++;
|
||||
pthread_mutex_unlock (&m_mutex);
|
||||
|
||||
return (ULONG) m_refCount;
|
||||
}
|
||||
|
||||
ULONG
|
||||
DeckLinkCaptureDelegate::Release (void)
|
||||
{
|
||||
pthread_mutex_lock (&m_mutex);
|
||||
m_refCount--;
|
||||
pthread_mutex_unlock (&m_mutex);
|
||||
|
||||
if (m_refCount == 0) {
|
||||
delete this;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return (ULONG) m_refCount;
|
||||
}
|
||||
|
||||
HRESULT
|
||||
DeckLinkCaptureDelegate::VideoInputFrameArrived (IDeckLinkVideoInputFrame *
|
||||
videoFrame, IDeckLinkAudioInputPacket * audioFrame)
|
||||
{
|
||||
GstDecklinkSrc *decklinksrc = GST_DECKLINK_SRC (priv);
|
||||
|
||||
// Handle Video Frame
|
||||
if (videoFrame) {
|
||||
if (videoFrame->GetFlags () & bmdFrameHasNoInputSource) {
|
||||
GST_DEBUG("Frame received - No input signal detected");
|
||||
} else {
|
||||
const char *timecodeString = NULL;
|
||||
if (g_timecodeFormat != 0) {
|
||||
IDeckLinkTimecode *timecode;
|
||||
if (videoFrame->GetTimecode (g_timecodeFormat, &timecode) == S_OK) {
|
||||
timecode->GetString (&timecodeString);
|
||||
}
|
||||
}
|
||||
|
||||
GST_DEBUG("Frame received [%s] - %s - Size: %li bytes",
|
||||
timecodeString != NULL ? timecodeString : "No timecode",
|
||||
"Valid Frame",
|
||||
videoFrame->GetRowBytes () * videoFrame->GetHeight ());
|
||||
|
||||
if (timecodeString)
|
||||
free ((void *) timecodeString);
|
||||
|
||||
g_mutex_lock (decklinksrc->mutex);
|
||||
if (decklinksrc->video_frame != NULL) {
|
||||
decklinksrc->dropped_frames++;
|
||||
} else {
|
||||
videoFrame->AddRef();
|
||||
decklinksrc->video_frame = videoFrame;
|
||||
if (audioFrame) {
|
||||
audioFrame->AddRef();
|
||||
decklinksrc->audio_frame = audioFrame;
|
||||
}
|
||||
}
|
||||
g_cond_signal (decklinksrc->cond);
|
||||
g_mutex_unlock (decklinksrc->mutex);
|
||||
}
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT
|
||||
DeckLinkCaptureDelegate::
|
||||
VideoInputFormatChanged (BMDVideoInputFormatChangedEvents events,
|
||||
IDeckLinkDisplayMode * mode, BMDDetectedVideoInputFormatFlags)
|
||||
{
|
||||
GST_ERROR("moo");
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
#ifdef unused
|
||||
int
|
||||
usage (int status)
|
||||
{
|
||||
HRESULT result;
|
||||
IDeckLinkDisplayMode *displayMode;
|
||||
int displayModeCount = 0;
|
||||
|
||||
fprintf (stderr,
|
||||
"Usage: Capture -m <mode id> [OPTIONS]\n" "\n" " -m <mode id>:\n");
|
||||
|
||||
while (displayModeIterator->Next (&displayMode) == S_OK) {
|
||||
char *displayModeString = NULL;
|
||||
|
||||
result = displayMode->GetName ((const char **) &displayModeString);
|
||||
if (result == S_OK) {
|
||||
BMDTimeValue frameRateDuration, frameRateScale;
|
||||
displayMode->GetFrameRate (&frameRateDuration, &frameRateScale);
|
||||
|
||||
fprintf (stderr, " %2d: %-20s \t %li x %li \t %g FPS\n",
|
||||
displayModeCount, displayModeString, displayMode->GetWidth (),
|
||||
displayMode->GetHeight (),
|
||||
(double) frameRateScale / (double) frameRateDuration);
|
||||
|
||||
free (displayModeString);
|
||||
displayModeCount++;
|
||||
}
|
||||
// Release the IDeckLinkDisplayMode object to prevent a leak
|
||||
displayMode->Release ();
|
||||
}
|
||||
|
||||
fprintf (stderr,
|
||||
" -p <pixelformat>\n"
|
||||
" 0: 8 bit YUV (4:2:2) (default)\n"
|
||||
" 1: 10 bit YUV (4:2:2)\n"
|
||||
" 2: 10 bit RGB (4:4:4)\n"
|
||||
" -t <format> Print timecode\n"
|
||||
" rp188: RP 188\n"
|
||||
" vitc: VITC\n"
|
||||
" serial: Serial Timecode\n"
|
||||
" -f <filename> Filename raw video will be written to\n"
|
||||
" -a <filename> Filename raw audio will be written to\n"
|
||||
" -c <channels> Audio Channels (2, 8 or 16 - default is 2)\n"
|
||||
" -s <depth> Audio Sample Depth (16 or 32 - default is 16)\n"
|
||||
" -n <frames> Number of frames to capture (default is unlimited)\n"
|
||||
" -3 Capture Stereoscopic 3D (Requires 3D Hardware support)\n"
|
||||
"\n"
|
||||
"Capture video and/or audio to a file. Raw video and/or audio can be viewed with mplayer eg:\n"
|
||||
"\n"
|
||||
" Capture -m2 -n 50 -f video.raw -a audio.raw\n"
|
||||
" mplayer video.raw -demuxer rawvideo -rawvideo pal:uyvy -audiofile audio.raw -audio-demuxer 20 -rawaudio rate=48000\n");
|
||||
|
||||
exit (status);
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc, char *argv[])
|
||||
{
|
||||
IDeckLinkIterator *deckLinkIterator = CreateDeckLinkIteratorInstance ();
|
||||
DeckLinkCaptureDelegate *delegate;
|
||||
IDeckLinkDisplayMode *displayMode;
|
||||
BMDVideoInputFlags inputFlags = 0;
|
||||
BMDDisplayMode selectedDisplayMode = bmdModeNTSC;
|
||||
BMDPixelFormat pixelFormat = bmdFormat8BitYUV;
|
||||
int displayModeCount = 0;
|
||||
int exitStatus = 1;
|
||||
int ch;
|
||||
bool foundDisplayMode = false;
|
||||
HRESULT result;
|
||||
|
||||
pthread_mutex_init (&sleepMutex, NULL);
|
||||
pthread_cond_init (&sleepCond, NULL);
|
||||
|
||||
if (!deckLinkIterator) {
|
||||
fprintf (stderr,
|
||||
"This application requires the DeckLink drivers installed.\n");
|
||||
goto bail;
|
||||
}
|
||||
|
||||
/* Connect to the first DeckLink instance */
|
||||
result = deckLinkIterator->Next (&deckLink);
|
||||
if (result != S_OK) {
|
||||
fprintf (stderr, "No DeckLink PCI cards found.\n");
|
||||
goto bail;
|
||||
}
|
||||
|
||||
if (deckLink->QueryInterface (IID_IDeckLinkInput,
|
||||
(void **) &deckLinkInput) != S_OK)
|
||||
goto bail;
|
||||
|
||||
delegate = new DeckLinkCaptureDelegate ();
|
||||
deckLinkInput->SetCallback (delegate);
|
||||
|
||||
// Obtain an IDeckLinkDisplayModeIterator to enumerate the display modes supported on output
|
||||
result = deckLinkInput->GetDisplayModeIterator (&displayModeIterator);
|
||||
if (result != S_OK) {
|
||||
fprintf (stderr,
|
||||
"Could not obtain the video output display mode iterator - result = %08x\n",
|
||||
result);
|
||||
goto bail;
|
||||
}
|
||||
// Parse command line options
|
||||
while ((ch = getopt (argc, argv, "?h3c:s:f:a:m:n:p:t:")) != -1) {
|
||||
switch (ch) {
|
||||
case 'm':
|
||||
g_videoModeIndex = atoi (optarg);
|
||||
break;
|
||||
case 'c':
|
||||
g_audioChannels = atoi (optarg);
|
||||
if (g_audioChannels != 2 &&
|
||||
g_audioChannels != 8 && g_audioChannels != 16) {
|
||||
fprintf (stderr,
|
||||
"Invalid argument: Audio Channels must be either 2, 8 or 16\n");
|
||||
goto bail;
|
||||
}
|
||||
break;
|
||||
case 's':
|
||||
g_audioSampleDepth = atoi (optarg);
|
||||
if (g_audioSampleDepth != 16 && g_audioSampleDepth != 32) {
|
||||
fprintf (stderr,
|
||||
"Invalid argument: Audio Sample Depth must be either 16 bits or 32 bits\n");
|
||||
goto bail;
|
||||
}
|
||||
break;
|
||||
case 'f':
|
||||
g_videoOutputFile = optarg;
|
||||
break;
|
||||
case 'a':
|
||||
g_audioOutputFile = optarg;
|
||||
break;
|
||||
case 'n':
|
||||
g_maxFrames = atoi (optarg);
|
||||
break;
|
||||
case '3':
|
||||
inputFlags |= bmdVideoInputDualStream3D;
|
||||
break;
|
||||
case 'p':
|
||||
switch (atoi (optarg)) {
|
||||
case 0:
|
||||
pixelFormat = bmdFormat8BitYUV;
|
||||
break;
|
||||
case 1:
|
||||
pixelFormat = bmdFormat10BitYUV;
|
||||
break;
|
||||
case 2:
|
||||
pixelFormat = bmdFormat10BitRGB;
|
||||
break;
|
||||
default:
|
||||
fprintf (stderr, "Invalid argument: Pixel format %d is not valid",
|
||||
atoi (optarg));
|
||||
goto bail;
|
||||
}
|
||||
break;
|
||||
case 't':
|
||||
if (!strcmp (optarg, "rp188"))
|
||||
g_timecodeFormat = bmdTimecodeRP188;
|
||||
else if (!strcmp (optarg, "vitc"))
|
||||
g_timecodeFormat = bmdTimecodeVITC;
|
||||
else if (!strcmp (optarg, "serial"))
|
||||
g_timecodeFormat = bmdTimecodeSerial;
|
||||
else {
|
||||
fprintf (stderr,
|
||||
"Invalid argument: Timecode format \"%s\" is invalid\n", optarg);
|
||||
goto bail;
|
||||
}
|
||||
break;
|
||||
case '?':
|
||||
case 'h':
|
||||
usage (0);
|
||||
}
|
||||
}
|
||||
|
||||
if (g_videoModeIndex < 0) {
|
||||
fprintf (stderr, "No video mode specified\n");
|
||||
usage (0);
|
||||
}
|
||||
|
||||
if (g_videoOutputFile != NULL) {
|
||||
videoOutputFile =
|
||||
open (g_videoOutputFile, O_WRONLY | O_CREAT | O_TRUNC, 0664);
|
||||
if (videoOutputFile < 0) {
|
||||
fprintf (stderr, "Could not open video output file \"%s\"\n",
|
||||
g_videoOutputFile);
|
||||
goto bail;
|
||||
}
|
||||
}
|
||||
if (g_audioOutputFile != NULL) {
|
||||
audioOutputFile =
|
||||
open (g_audioOutputFile, O_WRONLY | O_CREAT | O_TRUNC, 0664);
|
||||
if (audioOutputFile < 0) {
|
||||
fprintf (stderr, "Could not open audio output file \"%s\"\n",
|
||||
g_audioOutputFile);
|
||||
goto bail;
|
||||
}
|
||||
}
|
||||
|
||||
while (displayModeIterator->Next (&displayMode) == S_OK) {
|
||||
if (g_videoModeIndex == displayModeCount) {
|
||||
BMDDisplayModeSupport result;
|
||||
const char *displayModeName;
|
||||
|
||||
foundDisplayMode = true;
|
||||
displayMode->GetName (&displayModeName);
|
||||
selectedDisplayMode = displayMode->GetDisplayMode ();
|
||||
|
||||
deckLinkInput->DoesSupportVideoMode (selectedDisplayMode, pixelFormat,
|
||||
bmdVideoInputFlagDefault, &result, NULL);
|
||||
|
||||
if (result == bmdDisplayModeNotSupported) {
|
||||
fprintf (stderr,
|
||||
"The display mode %s is not supported with the selected pixel format\n",
|
||||
displayModeName);
|
||||
goto bail;
|
||||
}
|
||||
|
||||
if (inputFlags & bmdVideoInputDualStream3D) {
|
||||
if (!(displayMode->GetFlags () & bmdDisplayModeSupports3D)) {
|
||||
fprintf (stderr, "The display mode %s is not supported with 3D\n",
|
||||
displayModeName);
|
||||
goto bail;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
displayModeCount++;
|
||||
displayMode->Release ();
|
||||
}
|
||||
|
||||
if (!foundDisplayMode) {
|
||||
fprintf (stderr, "Invalid mode %d specified\n", g_videoModeIndex);
|
||||
goto bail;
|
||||
}
|
||||
|
||||
result =
|
||||
deckLinkInput->EnableVideoInput (selectedDisplayMode, pixelFormat,
|
||||
inputFlags);
|
||||
if (result != S_OK) {
|
||||
fprintf (stderr,
|
||||
"Failed to enable video input. Is another application using the card?\n");
|
||||
goto bail;
|
||||
}
|
||||
|
||||
result =
|
||||
deckLinkInput->EnableAudioInput (bmdAudioSampleRate48kHz,
|
||||
g_audioSampleDepth, g_audioChannels);
|
||||
if (result != S_OK) {
|
||||
goto bail;
|
||||
}
|
||||
|
||||
result = deckLinkInput->StartStreams ();
|
||||
if (result != S_OK) {
|
||||
goto bail;
|
||||
}
|
||||
// All Okay.
|
||||
exitStatus = 0;
|
||||
|
||||
// Block main thread until signal occurs
|
||||
pthread_mutex_lock (&sleepMutex);
|
||||
pthread_cond_wait (&sleepCond, &sleepMutex);
|
||||
pthread_mutex_unlock (&sleepMutex);
|
||||
fprintf (stderr, "Stopping Capture\n");
|
||||
|
||||
bail:
|
||||
|
||||
if (videoOutputFile)
|
||||
close (videoOutputFile);
|
||||
if (audioOutputFile)
|
||||
close (audioOutputFile);
|
||||
|
||||
if (displayModeIterator != NULL) {
|
||||
displayModeIterator->Release ();
|
||||
displayModeIterator = NULL;
|
||||
}
|
||||
|
||||
if (deckLinkInput != NULL) {
|
||||
deckLinkInput->Release ();
|
||||
deckLinkInput = NULL;
|
||||
}
|
||||
|
||||
if (deckLink != NULL) {
|
||||
deckLink->Release ();
|
||||
deckLink = NULL;
|
||||
}
|
||||
|
||||
if (deckLinkIterator != NULL)
|
||||
deckLinkIterator->Release ();
|
||||
|
||||
return exitStatus;
|
||||
}
|
||||
#endif
|
||||
|
25
sys/decklink/capture.h
Normal file
25
sys/decklink/capture.h
Normal file
|
@ -0,0 +1,25 @@
|
|||
#ifndef __CAPTURE_H__
|
||||
#define __CAPTURE_H__
|
||||
|
||||
#include "DeckLinkAPI.h"
|
||||
|
||||
class DeckLinkCaptureDelegate : public IDeckLinkInputCallback
|
||||
{
|
||||
public:
|
||||
DeckLinkCaptureDelegate();
|
||||
~DeckLinkCaptureDelegate();
|
||||
|
||||
virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, LPVOID *ppv) { return E_NOINTERFACE; }
|
||||
virtual ULONG STDMETHODCALLTYPE AddRef(void);
|
||||
virtual ULONG STDMETHODCALLTYPE Release(void);
|
||||
virtual HRESULT STDMETHODCALLTYPE VideoInputFormatChanged(BMDVideoInputFormatChangedEvents, IDeckLinkDisplayMode*, BMDDetectedVideoInputFormatFlags);
|
||||
virtual HRESULT STDMETHODCALLTYPE VideoInputFrameArrived(IDeckLinkVideoInputFrame*, IDeckLinkAudioInputPacket*);
|
||||
|
||||
void *priv;
|
||||
|
||||
private:
|
||||
ULONG m_refCount;
|
||||
pthread_mutex_t m_mutex;
|
||||
};
|
||||
|
||||
#endif
|
44
sys/decklink/gstdecklink.cpp
Normal file
44
sys/decklink/gstdecklink.cpp
Normal file
|
@ -0,0 +1,44 @@
|
|||
/* GStreamer
|
||||
* Copyright (C) 2011 David Schleef <ds@schleef.org>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin Street, Suite 500,
|
||||
* Boston, MA 02110-1335, USA.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <gst/gst.h>
|
||||
#include "gstdecklinksrc.h"
|
||||
#include "gstdecklinksink.h"
|
||||
|
||||
static gboolean
|
||||
plugin_init (GstPlugin * plugin)
|
||||
{
|
||||
|
||||
gst_element_register (plugin, "decklinksrc", GST_RANK_NONE,
|
||||
gst_decklink_src_get_type ());
|
||||
gst_element_register (plugin, "decklinksink", GST_RANK_NONE,
|
||||
gst_decklink_sink_get_type ());
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
|
||||
GST_VERSION_MINOR,
|
||||
"decklink",
|
||||
"Blackmagic Decklink plugin",
|
||||
plugin_init, VERSION, "LGPL", PACKAGE_NAME, GST_PACKAGE_ORIGIN)
|
1059
sys/decklink/gstdecklinksink.cpp
Normal file
1059
sys/decklink/gstdecklinksink.cpp
Normal file
File diff suppressed because it is too large
Load diff
92
sys/decklink/gstdecklinksink.h
Normal file
92
sys/decklink/gstdecklinksink.h
Normal file
|
@ -0,0 +1,92 @@
|
|||
/* GStreamer
|
||||
* Copyright (C) 2011 David Schleef <ds@schleef.org>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef _GST_DECKLINK_SINK_H_
|
||||
#define _GST_DECKLINK_SINK_H_
|
||||
|
||||
#include <gst/gst.h>
|
||||
#include "DeckLinkAPI.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GST_TYPE_DECKLINK_SINK (gst_decklink_sink_get_type())
|
||||
#define GST_DECKLINK_SINK(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_DECKLINK_SINK,GstDecklinkSink))
|
||||
#define GST_DECKLINK_SINK_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_DECKLINK_SINK,GstDecklinkSinkClass))
|
||||
#define GST_IS_DECKLINK_SINK(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_DECKLINK_SINK))
|
||||
#define GST_IS_DECKLINK_SINK_CLASS(obj) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_DECKLINK_SINK))
|
||||
|
||||
typedef struct _GstDecklinkSink GstDecklinkSink;
|
||||
typedef struct _GstDecklinkSinkClass GstDecklinkSinkClass;
|
||||
|
||||
class Output : public IDeckLinkVideoOutputCallback,
|
||||
public IDeckLinkAudioOutputCallback
|
||||
{
|
||||
public:
|
||||
GstDecklinkSink *decklinksink;
|
||||
|
||||
virtual HRESULT STDMETHODCALLTYPE QueryInterface (REFIID iid, LPVOID *ppv) {return E_NOINTERFACE;}
|
||||
virtual ULONG STDMETHODCALLTYPE AddRef () {return 1;}
|
||||
virtual ULONG STDMETHODCALLTYPE Release () {return 1;}
|
||||
virtual HRESULT STDMETHODCALLTYPE ScheduledFrameCompleted (IDeckLinkVideoFrame* completedFrame, BMDOutputFrameCompletionResult result);
|
||||
virtual HRESULT STDMETHODCALLTYPE ScheduledPlaybackHasStopped ();
|
||||
virtual HRESULT STDMETHODCALLTYPE RenderAudioSamples (bool preroll);
|
||||
};
|
||||
|
||||
struct _GstDecklinkSink
|
||||
{
|
||||
GstElement base_decklinksink;
|
||||
|
||||
GstPad *videosinkpad;
|
||||
GstPad *audiosinkpad;
|
||||
|
||||
GMutex *mutex;
|
||||
GCond *cond;
|
||||
int queued_frames;
|
||||
gboolean stop;
|
||||
|
||||
IDeckLink *decklink;
|
||||
IDeckLinkOutput *output;
|
||||
Output *callback;
|
||||
BMDDisplayMode display_mode;
|
||||
gboolean video_enabled;
|
||||
gboolean sched_started;
|
||||
|
||||
int num_frames;
|
||||
int fps_n;
|
||||
int fps_d;
|
||||
int width;
|
||||
int height;
|
||||
gboolean interlaced;
|
||||
BMDDisplayMode bmd_mode;
|
||||
|
||||
/* properties */
|
||||
int mode;
|
||||
|
||||
};
|
||||
|
||||
struct _GstDecklinkSinkClass
|
||||
{
|
||||
GstElementClass base_decklinksink_class;
|
||||
};
|
||||
|
||||
GType gst_decklink_sink_get_type (void);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif
|
1096
sys/decklink/gstdecklinksrc.cpp
Normal file
1096
sys/decklink/gstdecklinksrc.cpp
Normal file
File diff suppressed because it is too large
Load diff
84
sys/decklink/gstdecklinksrc.h
Normal file
84
sys/decklink/gstdecklinksrc.h
Normal file
|
@ -0,0 +1,84 @@
|
|||
/* GStreamer
|
||||
* Copyright (C) 2011 David Schleef <ds@schleef.org>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef _GST_DECKLINK_SRC_H_
|
||||
#define _GST_DECKLINK_SRC_H_
|
||||
|
||||
#include <gst/gst.h>
|
||||
#include "DeckLinkAPI.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GST_TYPE_DECKLINK_SRC (gst_decklink_src_get_type())
|
||||
#define GST_DECKLINK_SRC(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_DECKLINK_SRC,GstDecklinkSrc))
|
||||
#define GST_DECKLINK_SRC_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_DECKLINK_SRC,GstDecklinkSrcClass))
|
||||
#define GST_IS_DECKLINK_SRC(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_DECKLINK_SRC))
|
||||
#define GST_IS_DECKLINK_SRC_CLASS(obj) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_DECKLINK_SRC))
|
||||
|
||||
typedef struct _GstDecklinkSrc GstDecklinkSrc;
|
||||
typedef struct _GstDecklinkSrcClass GstDecklinkSrcClass;
|
||||
|
||||
struct _GstDecklinkSrc
|
||||
{
|
||||
GstElement base_decklinksrc;
|
||||
|
||||
GstPad *audiosrcpad;
|
||||
GstPad *videosrcpad;
|
||||
|
||||
GstCaps *audio_caps;
|
||||
|
||||
IDeckLink *decklink;
|
||||
IDeckLinkInput *input;
|
||||
|
||||
GMutex *mutex;
|
||||
GCond *cond;
|
||||
int dropped_frames;
|
||||
gboolean stop;
|
||||
IDeckLinkVideoInputFrame *video_frame;
|
||||
IDeckLinkAudioInputPacket * audio_frame;
|
||||
|
||||
GstTask *task;
|
||||
GStaticRecMutex task_mutex;
|
||||
|
||||
int num_audio_samples;
|
||||
|
||||
GstCaps *video_caps;
|
||||
int num_frames;
|
||||
int fps_n;
|
||||
int fps_d;
|
||||
int width;
|
||||
int height;
|
||||
gboolean interlaced;
|
||||
BMDDisplayMode bmd_mode;
|
||||
|
||||
/* properties */
|
||||
gboolean copy_data;
|
||||
int mode;
|
||||
};
|
||||
|
||||
struct _GstDecklinkSrcClass
|
||||
{
|
||||
GstElementClass base_decklinksrc_class;
|
||||
};
|
||||
|
||||
GType gst_decklink_src_get_type (void);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif
|
Loading…
Reference in a new issue