New upstream version 24.0.1+dfsg1
This commit is contained in:
parent
b14f9eae6d
commit
5a730d6ec3
842 changed files with 42245 additions and 33385 deletions
|
|
@ -1,7 +1,7 @@
|
|||
#include "DecklinkBase.h"
|
||||
|
||||
DecklinkBase::DecklinkBase(DeckLinkDeviceDiscovery *discovery_)
|
||||
: discovery(discovery_)
|
||||
: discovery(discovery_)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
@ -10,11 +10,9 @@ DeckLinkDevice *DecklinkBase::GetDevice() const
|
|||
return instance ? instance->GetDevice() : nullptr;
|
||||
}
|
||||
|
||||
bool DecklinkBase::Activate(DeckLinkDevice*, long long)
|
||||
bool DecklinkBase::Activate(DeckLinkDevice *, long long)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
void DecklinkBase::Deactivate()
|
||||
{
|
||||
}
|
||||
void DecklinkBase::Deactivate() {}
|
||||
|
|
|
|||
|
|
@ -16,14 +16,14 @@ class DecklinkBase {
|
|||
|
||||
protected:
|
||||
DecklinkBase(DeckLinkDeviceDiscovery *discovery_);
|
||||
ComPtr<DeckLinkDeviceInstance> instance;
|
||||
DeckLinkDeviceDiscovery *discovery;
|
||||
std::recursive_mutex deviceMutex;
|
||||
volatile long activateRefs = 0;
|
||||
BMDPixelFormat pixelFormat = bmdFormat8BitYUV;
|
||||
video_colorspace colorSpace = VIDEO_CS_DEFAULT;
|
||||
video_range_type colorRange = VIDEO_RANGE_DEFAULT;
|
||||
speaker_layout channelFormat = SPEAKERS_STEREO;
|
||||
ComPtr<DeckLinkDeviceInstance> instance;
|
||||
DeckLinkDeviceDiscovery *discovery;
|
||||
std::recursive_mutex deviceMutex;
|
||||
volatile long activateRefs = 0;
|
||||
BMDPixelFormat pixelFormat = bmdFormat8BitYUV;
|
||||
video_colorspace colorSpace = VIDEO_CS_DEFAULT;
|
||||
video_range_type colorRange = VIDEO_RANGE_DEFAULT;
|
||||
speaker_layout channelFormat = SPEAKERS_STEREO;
|
||||
|
||||
public:
|
||||
virtual bool Activate(DeckLinkDevice *device, long long modeId);
|
||||
|
|
|
|||
|
|
@ -2,9 +2,9 @@
|
|||
|
||||
#include <util/threading.h>
|
||||
|
||||
DeckLinkInput::DeckLinkInput(obs_source_t *source, DeckLinkDeviceDiscovery *discovery_)
|
||||
: DecklinkBase(discovery_),
|
||||
source(source)
|
||||
DeckLinkInput::DeckLinkInput(obs_source_t *source,
|
||||
DeckLinkDeviceDiscovery *discovery_)
|
||||
: DecklinkBase(discovery_), source(source)
|
||||
{
|
||||
discovery->AddCallback(DeckLinkInput::DevicesChanged, this);
|
||||
}
|
||||
|
|
@ -15,9 +15,10 @@ DeckLinkInput::~DeckLinkInput(void)
|
|||
Deactivate();
|
||||
}
|
||||
|
||||
void DeckLinkInput::DevicesChanged(void *param, DeckLinkDevice *device, bool added)
|
||||
void DeckLinkInput::DevicesChanged(void *param, DeckLinkDevice *device,
|
||||
bool added)
|
||||
{
|
||||
DeckLinkInput *decklink = reinterpret_cast<DeckLinkInput*>(param);
|
||||
DeckLinkInput *decklink = reinterpret_cast<DeckLinkInput *>(param);
|
||||
std::lock_guard<std::recursive_mutex> lock(decklink->deviceMutex);
|
||||
|
||||
obs_source_update_properties(decklink->source);
|
||||
|
|
@ -31,15 +32,18 @@ void DeckLinkInput::DevicesChanged(void *param, DeckLinkDevice *device, bool add
|
|||
|
||||
settings = obs_source_get_settings(decklink->source);
|
||||
hash = obs_data_get_string(settings, "device_hash");
|
||||
videoConnection = (BMDVideoConnection) obs_data_get_int(settings, "video_connection");
|
||||
audioConnection = (BMDAudioConnection) obs_data_get_int(settings, "audio_connection");
|
||||
videoConnection = (BMDVideoConnection)obs_data_get_int(
|
||||
settings, "video_connection");
|
||||
audioConnection = (BMDAudioConnection)obs_data_get_int(
|
||||
settings, "audio_connection");
|
||||
mode = obs_data_get_int(settings, "mode_id");
|
||||
obs_data_release(settings);
|
||||
|
||||
if (device->GetHash().compare(hash) == 0) {
|
||||
if (!decklink->activateRefs)
|
||||
return;
|
||||
if (decklink->Activate(device, mode, videoConnection, audioConnection))
|
||||
if (decklink->Activate(device, mode, videoConnection,
|
||||
audioConnection))
|
||||
os_atomic_dec_long(&decklink->activateRefs);
|
||||
}
|
||||
|
||||
|
|
@ -52,8 +56,8 @@ void DeckLinkInput::DevicesChanged(void *param, DeckLinkDevice *device, bool add
|
|||
}
|
||||
|
||||
bool DeckLinkInput::Activate(DeckLinkDevice *device, long long modeId,
|
||||
BMDVideoConnection bmdVideoConnection,
|
||||
BMDAudioConnection bmdAudioConnection)
|
||||
BMDVideoConnection bmdVideoConnection,
|
||||
BMDAudioConnection bmdAudioConnection)
|
||||
{
|
||||
std::lock_guard<std::recursive_mutex> lock(deviceMutex);
|
||||
DeckLinkDevice *curDevice = GetDevice();
|
||||
|
|
@ -85,7 +89,8 @@ bool DeckLinkInput::Activate(DeckLinkDevice *device, long long modeId,
|
|||
return false;
|
||||
|
||||
if (GetDevice() == nullptr) {
|
||||
LOG(LOG_ERROR, "Tried to activate an input with nullptr device.");
|
||||
LOG(LOG_ERROR,
|
||||
"Tried to activate an input with nullptr device.");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -95,7 +100,8 @@ bool DeckLinkInput::Activate(DeckLinkDevice *device, long long modeId,
|
|||
return false;
|
||||
}
|
||||
|
||||
if (!instance->StartCapture(mode, bmdVideoConnection, bmdAudioConnection)) {
|
||||
if (!instance->StartCapture(mode, bmdVideoConnection,
|
||||
bmdAudioConnection)) {
|
||||
instance = nullptr;
|
||||
return false;
|
||||
}
|
||||
|
|
@ -133,10 +139,9 @@ void DeckLinkInput::SaveSettings()
|
|||
|
||||
obs_data_t *settings = obs_source_get_settings(source);
|
||||
|
||||
obs_data_set_string(settings, "device_hash",
|
||||
device->GetHash().c_str());
|
||||
obs_data_set_string(settings, "device_hash", device->GetHash().c_str());
|
||||
obs_data_set_string(settings, "device_name",
|
||||
device->GetDisplayName().c_str());
|
||||
device->GetDisplayName().c_str());
|
||||
obs_data_set_int(settings, "mode_id", instance->GetActiveModeId());
|
||||
obs_data_set_string(settings, "mode_name", mode->GetName().c_str());
|
||||
|
||||
|
|
|
|||
|
|
@ -4,12 +4,12 @@
|
|||
|
||||
class DeckLinkInput : public DecklinkBase {
|
||||
protected:
|
||||
bool isCapturing = false;
|
||||
obs_source_t *source;
|
||||
bool isCapturing = false;
|
||||
obs_source_t *source;
|
||||
|
||||
void SaveSettings();
|
||||
static void DevicesChanged(void *param, DeckLinkDevice *device,
|
||||
bool added);
|
||||
bool added);
|
||||
|
||||
public:
|
||||
DeckLinkInput(obs_source_t *source, DeckLinkDeviceDiscovery *discovery);
|
||||
|
|
@ -18,30 +18,30 @@ public:
|
|||
long long GetActiveModeId(void) const;
|
||||
obs_source_t *GetSource(void) const;
|
||||
|
||||
inline BMDPixelFormat GetPixelFormat() const {return pixelFormat;}
|
||||
inline BMDPixelFormat GetPixelFormat() const { return pixelFormat; }
|
||||
inline void SetPixelFormat(BMDPixelFormat format)
|
||||
{
|
||||
pixelFormat = format;
|
||||
}
|
||||
inline video_colorspace GetColorSpace() const {return colorSpace;}
|
||||
inline video_colorspace GetColorSpace() const { return colorSpace; }
|
||||
inline void SetColorSpace(video_colorspace format)
|
||||
{
|
||||
colorSpace = format;
|
||||
}
|
||||
inline video_range_type GetColorRange() const {return colorRange;}
|
||||
inline video_range_type GetColorRange() const { return colorRange; }
|
||||
inline void SetColorRange(video_range_type format)
|
||||
{
|
||||
colorRange = format;
|
||||
}
|
||||
inline speaker_layout GetChannelFormat() const {return channelFormat;}
|
||||
inline speaker_layout GetChannelFormat() const { return channelFormat; }
|
||||
inline void SetChannelFormat(speaker_layout format)
|
||||
{
|
||||
channelFormat = format;
|
||||
}
|
||||
|
||||
bool Activate(DeckLinkDevice *device, long long modeId,
|
||||
BMDVideoConnection bmdVideoConnection,
|
||||
BMDAudioConnection bmdAudioConnection);
|
||||
BMDVideoConnection bmdVideoConnection,
|
||||
BMDAudioConnection bmdAudioConnection);
|
||||
void Deactivate();
|
||||
bool Capturing();
|
||||
|
||||
|
|
|
|||
|
|
@ -2,9 +2,9 @@
|
|||
|
||||
#include <util/threading.h>
|
||||
|
||||
DeckLinkOutput::DeckLinkOutput(obs_output_t *output, DeckLinkDeviceDiscovery *discovery_)
|
||||
: DecklinkBase(discovery_),
|
||||
output(output)
|
||||
DeckLinkOutput::DeckLinkOutput(obs_output_t *output,
|
||||
DeckLinkDeviceDiscovery *discovery_)
|
||||
: DecklinkBase(discovery_), output(output)
|
||||
{
|
||||
discovery->AddCallback(DeckLinkOutput::DevicesChanged, this);
|
||||
}
|
||||
|
|
@ -17,7 +17,7 @@ DeckLinkOutput::~DeckLinkOutput(void)
|
|||
|
||||
void DeckLinkOutput::DevicesChanged(void *param, DeckLinkDevice *device, bool)
|
||||
{
|
||||
auto *decklink = reinterpret_cast<DeckLinkOutput*>(param);
|
||||
auto *decklink = reinterpret_cast<DeckLinkOutput *>(param);
|
||||
std::lock_guard<std::recursive_mutex> lock(decklink->deviceMutex);
|
||||
|
||||
blog(LOG_DEBUG, "%s", device->GetHash().c_str());
|
||||
|
|
@ -35,10 +35,10 @@ bool DeckLinkOutput::Activate(DeckLinkDevice *device, long long modeId)
|
|||
return false;
|
||||
|
||||
if (instance->GetActiveModeId() == modeId &&
|
||||
instance->GetActivePixelFormat() == pixelFormat &&
|
||||
instance->GetActiveColorSpace() == colorSpace &&
|
||||
instance->GetActiveColorRange() == colorRange &&
|
||||
instance->GetActiveChannelFormat() == channelFormat)
|
||||
instance->GetActivePixelFormat() == pixelFormat &&
|
||||
instance->GetActiveColorSpace() == colorSpace &&
|
||||
instance->GetActiveColorRange() == colorRange &&
|
||||
instance->GetActiveChannelFormat() == channelFormat)
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -57,7 +57,6 @@ bool DeckLinkOutput::Activate(DeckLinkDevice *device, long long modeId)
|
|||
return false;
|
||||
}
|
||||
|
||||
|
||||
if (!instance->StartOutput(mode)) {
|
||||
instance = nullptr;
|
||||
return false;
|
||||
|
|
|
|||
|
|
@ -10,7 +10,8 @@ protected:
|
|||
int width;
|
||||
int height;
|
||||
|
||||
static void DevicesChanged(void *param, DeckLinkDevice *device, bool added);
|
||||
static void DevicesChanged(void *param, DeckLinkDevice *device,
|
||||
bool added);
|
||||
|
||||
public:
|
||||
const char *deviceHash;
|
||||
|
|
@ -21,7 +22,8 @@ public:
|
|||
size_t audio_size;
|
||||
int keyerMode;
|
||||
|
||||
DeckLinkOutput(obs_output_t *output, DeckLinkDeviceDiscovery *discovery);
|
||||
DeckLinkOutput(obs_output_t *output,
|
||||
DeckLinkDeviceDiscovery *discovery);
|
||||
virtual ~DeckLinkOutput(void);
|
||||
obs_output_t *GetOutput(void) const;
|
||||
bool Activate(DeckLinkDevice *device, long long modeId) override;
|
||||
|
|
|
|||
|
|
@ -2,15 +2,14 @@
|
|||
|
||||
#include <emmintrin.h>
|
||||
|
||||
int check_buffer(struct audio_repack *repack,
|
||||
uint32_t frame_count)
|
||||
int check_buffer(struct audio_repack *repack, uint32_t frame_count)
|
||||
{
|
||||
const uint32_t new_size = frame_count * repack->base_dst_size
|
||||
+ repack->extra_dst_size;
|
||||
const uint32_t new_size =
|
||||
frame_count * repack->base_dst_size + repack->extra_dst_size;
|
||||
|
||||
if (repack->packet_size < new_size) {
|
||||
repack->packet_buffer = brealloc(
|
||||
repack->packet_buffer, new_size);
|
||||
repack->packet_buffer =
|
||||
brealloc(repack->packet_buffer, new_size);
|
||||
if (!repack->packet_buffer)
|
||||
return -1;
|
||||
|
||||
|
|
@ -30,8 +29,8 @@ int check_buffer(struct audio_repack *repack,
|
|||
* | FL | FR | LFE |
|
||||
*/
|
||||
|
||||
int repack_squash(struct audio_repack *repack,
|
||||
const uint8_t *bsrc, uint32_t frame_count)
|
||||
int repack_squash(struct audio_repack *repack, const uint8_t *bsrc,
|
||||
uint32_t frame_count)
|
||||
{
|
||||
if (check_buffer(repack, frame_count) < 0)
|
||||
return -1;
|
||||
|
|
@ -55,8 +54,8 @@ int repack_squash(struct audio_repack *repack,
|
|||
return 0;
|
||||
}
|
||||
|
||||
int repack_squash_swap(struct audio_repack *repack,
|
||||
const uint8_t *bsrc, uint32_t frame_count)
|
||||
int repack_squash_swap(struct audio_repack *repack, const uint8_t *bsrc,
|
||||
uint32_t frame_count)
|
||||
{
|
||||
if (check_buffer(repack, frame_count) < 0)
|
||||
return -1;
|
||||
|
|
@ -66,7 +65,8 @@ int repack_squash_swap(struct audio_repack *repack,
|
|||
uint16_t *dst = (uint16_t *)repack->packet_buffer;
|
||||
while (src != esrc) {
|
||||
__m128i target = _mm_load_si128(src++);
|
||||
__m128i buf = _mm_shufflelo_epi16(target, _MM_SHUFFLE(2, 3, 1, 0));
|
||||
__m128i buf =
|
||||
_mm_shufflelo_epi16(target, _MM_SHUFFLE(2, 3, 1, 0));
|
||||
_mm_storeu_si128((__m128i *)dst, buf);
|
||||
dst += 8 - squash;
|
||||
}
|
||||
|
|
@ -74,20 +74,20 @@ int repack_squash_swap(struct audio_repack *repack,
|
|||
}
|
||||
|
||||
int audio_repack_init(struct audio_repack *repack,
|
||||
audio_repack_mode_t repack_mode, uint8_t sample_bit)
|
||||
audio_repack_mode_t repack_mode, uint8_t sample_bit)
|
||||
{
|
||||
memset(repack, 0, sizeof(*repack));
|
||||
|
||||
if (sample_bit != 16)
|
||||
return -1;
|
||||
int _audio_repack_ch[8] = { 3, 4, 5, 6, 5, 6, 8, 8 };
|
||||
int _audio_repack_ch[8] = {3, 4, 5, 6, 5, 6, 8, 8};
|
||||
repack->base_src_size = 8 * (16 / 8);
|
||||
repack->base_dst_size = _audio_repack_ch[repack_mode] * (16 / 8);
|
||||
repack->extra_dst_size = 8 - _audio_repack_ch[repack_mode];
|
||||
repack->repack_func = &repack_squash;
|
||||
if (repack_mode == repack_mode_8to5ch_swap ||
|
||||
repack_mode == repack_mode_8to6ch_swap ||
|
||||
repack_mode == repack_mode_8ch_swap)
|
||||
repack_mode == repack_mode_8to6ch_swap ||
|
||||
repack_mode == repack_mode_8ch_swap)
|
||||
repack->repack_func = &repack_squash_swap;
|
||||
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -11,22 +11,22 @@ extern "C" {
|
|||
|
||||
struct audio_repack;
|
||||
|
||||
typedef int (*audio_repack_func_t)(struct audio_repack *,
|
||||
const uint8_t *, uint32_t);
|
||||
typedef int (*audio_repack_func_t)(struct audio_repack *, const uint8_t *,
|
||||
uint32_t);
|
||||
|
||||
struct audio_repack {
|
||||
uint8_t *packet_buffer;
|
||||
uint32_t packet_size;
|
||||
uint8_t *packet_buffer;
|
||||
uint32_t packet_size;
|
||||
|
||||
uint32_t base_src_size;
|
||||
uint32_t base_dst_size;
|
||||
uint32_t extra_dst_size;
|
||||
uint32_t base_src_size;
|
||||
uint32_t base_dst_size;
|
||||
uint32_t extra_dst_size;
|
||||
|
||||
audio_repack_func_t repack_func;
|
||||
};
|
||||
|
||||
enum _audio_repack_mode {
|
||||
repack_mode_8to3ch=0,
|
||||
repack_mode_8to3ch = 0,
|
||||
repack_mode_8to4ch,
|
||||
repack_mode_8to5ch,
|
||||
repack_mode_8to6ch,
|
||||
|
|
@ -39,7 +39,8 @@ enum _audio_repack_mode {
|
|||
typedef enum _audio_repack_mode audio_repack_mode_t;
|
||||
|
||||
extern int audio_repack_init(struct audio_repack *repack,
|
||||
audio_repack_mode_t repack_mode, uint8_t sample_bit);
|
||||
audio_repack_mode_t repack_mode,
|
||||
uint8_t sample_bit);
|
||||
extern void audio_repack_free(struct audio_repack *repack);
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
|
|
|||
|
|
@ -10,16 +10,13 @@ public:
|
|||
{
|
||||
audio_repack_init(&arepack, repack_mode, 16);
|
||||
}
|
||||
inline ~AudioRepacker()
|
||||
{
|
||||
audio_repack_free(&arepack);
|
||||
}
|
||||
inline ~AudioRepacker() { audio_repack_free(&arepack); }
|
||||
|
||||
inline int repack(const uint8_t *src, uint32_t frame_size)
|
||||
{
|
||||
return (*arepack.repack_func)(&arepack, src, frame_size);
|
||||
}
|
||||
|
||||
inline operator struct audio_repack*() {return &arepack;}
|
||||
inline struct audio_repack *operator->() {return &arepack;}
|
||||
inline operator struct audio_repack *() { return &arepack; }
|
||||
inline struct audio_repack *operator->() { return &arepack; }
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,41 +1,41 @@
|
|||
#define DEVICE_HASH "device_hash"
|
||||
#define DEVICE_NAME "device_name"
|
||||
#define VIDEO_CONNECTION "video_connection"
|
||||
#define AUDIO_CONNECTION "audio_connection"
|
||||
#define MODE_ID "mode_id"
|
||||
#define MODE_NAME "mode_name"
|
||||
#define CHANNEL_FORMAT "channel_format"
|
||||
#define PIXEL_FORMAT "pixel_format"
|
||||
#define COLOR_SPACE "color_space"
|
||||
#define COLOR_RANGE "color_range"
|
||||
#define BUFFERING "buffering"
|
||||
#define DEACTIVATE_WNS "deactivate_when_not_showing"
|
||||
#define AUTO_START "auto_start"
|
||||
#define KEYER "keyer"
|
||||
#define SWAP "swap"
|
||||
#define DEVICE_HASH "device_hash"
|
||||
#define DEVICE_NAME "device_name"
|
||||
#define VIDEO_CONNECTION "video_connection"
|
||||
#define AUDIO_CONNECTION "audio_connection"
|
||||
#define MODE_ID "mode_id"
|
||||
#define MODE_NAME "mode_name"
|
||||
#define CHANNEL_FORMAT "channel_format"
|
||||
#define PIXEL_FORMAT "pixel_format"
|
||||
#define COLOR_SPACE "color_space"
|
||||
#define COLOR_RANGE "color_range"
|
||||
#define BUFFERING "buffering"
|
||||
#define DEACTIVATE_WNS "deactivate_when_not_showing"
|
||||
#define AUTO_START "auto_start"
|
||||
#define KEYER "keyer"
|
||||
#define SWAP "swap"
|
||||
|
||||
#define TEXT_DEVICE obs_module_text("Device")
|
||||
#define TEXT_VIDEO_CONNECTION obs_module_text("VideoConnection")
|
||||
#define TEXT_AUDIO_CONNECTION obs_module_text("AudioConnection")
|
||||
#define TEXT_MODE obs_module_text("Mode")
|
||||
#define TEXT_PIXEL_FORMAT obs_module_text("PixelFormat")
|
||||
#define TEXT_COLOR_SPACE obs_module_text("ColorSpace")
|
||||
#define TEXT_COLOR_SPACE_DEFAULT obs_module_text("ColorSpace.Default")
|
||||
#define TEXT_COLOR_RANGE obs_module_text("ColorRange")
|
||||
#define TEXT_COLOR_RANGE_DEFAULT obs_module_text("ColorRange.Default")
|
||||
#define TEXT_COLOR_RANGE_PARTIAL obs_module_text("ColorRange.Partial")
|
||||
#define TEXT_COLOR_RANGE_FULL obs_module_text("ColorRange.Full")
|
||||
#define TEXT_CHANNEL_FORMAT obs_module_text("ChannelFormat")
|
||||
#define TEXT_CHANNEL_FORMAT_NONE obs_module_text("ChannelFormat.None")
|
||||
#define TEXT_CHANNEL_FORMAT_2_0CH obs_module_text("ChannelFormat.2_0ch")
|
||||
#define TEXT_CHANNEL_FORMAT_2_1CH obs_module_text("ChannelFormat.2_1ch")
|
||||
#define TEXT_CHANNEL_FORMAT_4_0CH obs_module_text("ChannelFormat.4_0ch")
|
||||
#define TEXT_CHANNEL_FORMAT_4_1CH obs_module_text("ChannelFormat.4_1ch")
|
||||
#define TEXT_CHANNEL_FORMAT_5_1CH obs_module_text("ChannelFormat.5_1ch")
|
||||
#define TEXT_CHANNEL_FORMAT_7_1CH obs_module_text("ChannelFormat.7_1ch")
|
||||
#define TEXT_BUFFERING obs_module_text("Buffering")
|
||||
#define TEXT_DWNS obs_module_text("DeactivateWhenNotShowing")
|
||||
#define TEXT_AUTO_START obs_module_text("AutoStart")
|
||||
#define TEXT_ENABLE_KEYER obs_module_text("Keyer")
|
||||
#define TEXT_SWAP obs_module_text("SwapFC-LFE")
|
||||
#define TEXT_SWAP_TOOLTIP obs_module_text("SwapFC-LFE.Tooltip")
|
||||
#define TEXT_DEVICE obs_module_text("Device")
|
||||
#define TEXT_VIDEO_CONNECTION obs_module_text("VideoConnection")
|
||||
#define TEXT_AUDIO_CONNECTION obs_module_text("AudioConnection")
|
||||
#define TEXT_MODE obs_module_text("Mode")
|
||||
#define TEXT_PIXEL_FORMAT obs_module_text("PixelFormat")
|
||||
#define TEXT_COLOR_SPACE obs_module_text("ColorSpace")
|
||||
#define TEXT_COLOR_SPACE_DEFAULT obs_module_text("ColorSpace.Default")
|
||||
#define TEXT_COLOR_RANGE obs_module_text("ColorRange")
|
||||
#define TEXT_COLOR_RANGE_DEFAULT obs_module_text("ColorRange.Default")
|
||||
#define TEXT_COLOR_RANGE_PARTIAL obs_module_text("ColorRange.Partial")
|
||||
#define TEXT_COLOR_RANGE_FULL obs_module_text("ColorRange.Full")
|
||||
#define TEXT_CHANNEL_FORMAT obs_module_text("ChannelFormat")
|
||||
#define TEXT_CHANNEL_FORMAT_NONE obs_module_text("ChannelFormat.None")
|
||||
#define TEXT_CHANNEL_FORMAT_2_0CH obs_module_text("ChannelFormat.2_0ch")
|
||||
#define TEXT_CHANNEL_FORMAT_2_1CH obs_module_text("ChannelFormat.2_1ch")
|
||||
#define TEXT_CHANNEL_FORMAT_4_0CH obs_module_text("ChannelFormat.4_0ch")
|
||||
#define TEXT_CHANNEL_FORMAT_4_1CH obs_module_text("ChannelFormat.4_1ch")
|
||||
#define TEXT_CHANNEL_FORMAT_5_1CH obs_module_text("ChannelFormat.5_1ch")
|
||||
#define TEXT_CHANNEL_FORMAT_7_1CH obs_module_text("ChannelFormat.7_1ch")
|
||||
#define TEXT_BUFFERING obs_module_text("Buffering")
|
||||
#define TEXT_DWNS obs_module_text("DeactivateWhenNotShowing")
|
||||
#define TEXT_AUTO_START obs_module_text("AutoStart")
|
||||
#define TEXT_ENABLE_KEYER obs_module_text("Keyer")
|
||||
#define TEXT_SWAP obs_module_text("SwapFC-LFE")
|
||||
#define TEXT_SWAP_TOOLTIP obs_module_text("SwapFC-LFE.Tooltip")
|
||||
|
|
|
|||
|
|
@ -17,4 +17,6 @@ ChannelFormat.5_1ch="5.1ch"
|
|||
ChannelFormat.7_1ch="7.1ch"
|
||||
DeactivateWhenNotShowing="التعطيل عندما لا يكون ظاهراً"
|
||||
AutoStart="البدء تلقائياً مع التشغيل"
|
||||
VideoConnection="مدخل الفيديو"
|
||||
AudioConnection="مدخل الصوت"
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
BlackmagicDevice="Blackmagic-Gerät"
|
||||
BlackmagicDevice="Blackmagic‐Gerät"
|
||||
Device="Gerät"
|
||||
Mode="Modus"
|
||||
Buffering="Puffern benutzen"
|
||||
|
|
@ -11,16 +11,16 @@ ColorRange.Partial="Begrenzt"
|
|||
ColorRange.Full="Voll"
|
||||
ChannelFormat="Kanal"
|
||||
ChannelFormat.None="Keins"
|
||||
ChannelFormat.2_0ch="2 Kanal"
|
||||
ChannelFormat.2_1ch="2.1 Kanal"
|
||||
ChannelFormat.4_0ch="4 Kanal"
|
||||
ChannelFormat.4_1ch="4.1 Kanal"
|
||||
ChannelFormat.5_1ch="5.1 Kanal"
|
||||
ChannelFormat.7_1ch="7.1 Kanal"
|
||||
ChannelFormat.2_0ch="2‐Kanal"
|
||||
ChannelFormat.2_1ch="2.1‐Kanal"
|
||||
ChannelFormat.4_0ch="4‐Kanal"
|
||||
ChannelFormat.4_1ch="4.1‐Kanal"
|
||||
ChannelFormat.5_1ch="5.1‐Kanal"
|
||||
ChannelFormat.7_1ch="7.1‐Kanal"
|
||||
DeactivateWhenNotShowing="Deaktivieren, wenn die Quelle nicht angezeigt wird"
|
||||
AutoStart="Automatisch beim Öffnen starten"
|
||||
SwapFC-LFE="FC und LFE tauschen"
|
||||
SwapFC-LFE.Tooltip="Vorderen Front-Center-Kanal und LFE-Kanal tauschen"
|
||||
SwapFC-LFE.Tooltip="Vorderen Front‐Center‐Kanal und LFE‐Kanal tauschen"
|
||||
VideoConnection="Videoverbindung"
|
||||
AudioConnection="Audioverbindung"
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,26 @@
|
|||
BlackmagicDevice="Dispositivo Blackmagic"
|
||||
Device="Dispositivo"
|
||||
Mode="Modo"
|
||||
Buffering="Utilizar o almacenamento no búfer"
|
||||
Buffering="Utilizar o almacenamento na memoria temporal"
|
||||
PixelFormat="Formato do píxel"
|
||||
ColorSpace="Espazo de cor"
|
||||
ColorSpace.Default="Predeterminado"
|
||||
ColorRange="Gama de cores"
|
||||
ColorRange.Default="Predeterminado"
|
||||
ColorRange.Partial="Parcial"
|
||||
ColorRange.Full="Total"
|
||||
ChannelFormat="Canle"
|
||||
ChannelFormat.None="Ningún"
|
||||
ChannelFormat.2_0ch="2ch"
|
||||
ChannelFormat.2_1ch="2.1ch"
|
||||
ChannelFormat.4_0ch="4ch"
|
||||
ChannelFormat.4_1ch="4.1ch"
|
||||
ChannelFormat.5_1ch="5.1ch"
|
||||
ChannelFormat.7_1ch="7.1ch"
|
||||
DeactivateWhenNotShowing="Desactivado cando non se amose"
|
||||
AutoStart="Comezar no inicio"
|
||||
SwapFC-LFE="Intercambiar FC e LFE"
|
||||
SwapFC-LFE.Tooltip="Intercambiar a canle central frontal e a canle LFE"
|
||||
VideoConnection="Conexión de vídeo"
|
||||
AudioConnection="Conexión de son"
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,13 @@ BlackmagicDevice="Dispozitiv Blackmagic"
|
|||
Device="Dispozitiv"
|
||||
Mode="Mod"
|
||||
Buffering="Folosește zona tampon"
|
||||
PixelFormat="Formatul pixelilor"
|
||||
PixelFormat="Format pentru pixeli"
|
||||
ColorSpace="Spațiu de culori"
|
||||
ColorSpace.Default="Implicit"
|
||||
ColorRange="Gamă de culori"
|
||||
ColorRange.Default="Implicit"
|
||||
ColorRange.Partial="Parțială"
|
||||
ColorRange.Full="Completă"
|
||||
VideoConnection="Conexiune video"
|
||||
AudioConnection="Conexiune audio"
|
||||
|
||||
|
|
|
|||
|
|
@ -2,4 +2,25 @@ BlackmagicDevice="Blackmagic naprave"
|
|||
Device="Naprava"
|
||||
Mode="Način"
|
||||
Buffering="Uporabi medpomnilnik"
|
||||
PixelFormat="Oblika sl. točk"
|
||||
ColorSpace="Barvni prostor"
|
||||
ColorSpace.Default="Privzeto"
|
||||
ColorRange="Barvni razpon"
|
||||
ColorRange.Default="Privzeto"
|
||||
ColorRange.Partial="Delno"
|
||||
ColorRange.Full="Polno"
|
||||
ChannelFormat="Kanal"
|
||||
ChannelFormat.None="Brez"
|
||||
ChannelFormat.2_0ch="2 kan."
|
||||
ChannelFormat.2_1ch="2.1 kan."
|
||||
ChannelFormat.4_0ch="4 kan."
|
||||
ChannelFormat.4_1ch="4.1 kan."
|
||||
ChannelFormat.5_1ch="5.1 kan."
|
||||
ChannelFormat.7_1ch="7.1 kan."
|
||||
DeactivateWhenNotShowing="Onemogoči, ko ni prikazano"
|
||||
AutoStart="Samodejno zaženi ob zagonu"
|
||||
SwapFC-LFE="Zamenjaj SS in nizke tone"
|
||||
SwapFC-LFE.Tooltip="Zamenjaj sprednji sredinski kanal in kanal z nizkimi toni"
|
||||
VideoConnection="Slikovna povezava"
|
||||
AudioConnection="Zvočna povezava"
|
||||
|
||||
|
|
|
|||
|
|
@ -3,7 +3,9 @@ Device="Пристрій"
|
|||
Mode="Режим"
|
||||
Buffering="Увімкнути буферизацію"
|
||||
PixelFormat="Формат пікселів"
|
||||
ColorSpace="Колірний простір"
|
||||
ColorSpace.Default="За замовчуванням"
|
||||
ColorRange="Колірний діапазон"
|
||||
ColorRange.Default="За замовчуванням"
|
||||
ColorRange.Partial="Частковий"
|
||||
ColorRange.Full="Повний"
|
||||
|
|
|
|||
|
|
@ -54,8 +54,8 @@ DeckLinkDevice *DeckLinkDeviceDiscovery::FindByHash(const char *hash)
|
|||
return ret;
|
||||
}
|
||||
|
||||
HRESULT STDMETHODCALLTYPE DeckLinkDeviceDiscovery::DeckLinkDeviceArrived(
|
||||
IDeckLink *device)
|
||||
HRESULT STDMETHODCALLTYPE
|
||||
DeckLinkDeviceDiscovery::DeckLinkDeviceArrived(IDeckLink *device)
|
||||
{
|
||||
DeckLinkDevice *newDev = new DeckLinkDevice(device);
|
||||
if (!newDev->Init()) {
|
||||
|
|
@ -73,8 +73,8 @@ HRESULT STDMETHODCALLTYPE DeckLinkDeviceDiscovery::DeckLinkDeviceArrived(
|
|||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT STDMETHODCALLTYPE DeckLinkDeviceDiscovery::DeckLinkDeviceRemoved(
|
||||
IDeckLink *device)
|
||||
HRESULT STDMETHODCALLTYPE
|
||||
DeckLinkDeviceDiscovery::DeckLinkDeviceRemoved(IDeckLink *device)
|
||||
{
|
||||
std::lock_guard<std::recursive_mutex> lock(deviceMutex);
|
||||
|
||||
|
|
@ -98,7 +98,7 @@ ULONG STDMETHODCALLTYPE DeckLinkDeviceDiscovery::AddRef(void)
|
|||
}
|
||||
|
||||
HRESULT STDMETHODCALLTYPE DeckLinkDeviceDiscovery::QueryInterface(REFIID iid,
|
||||
LPVOID *ppv)
|
||||
LPVOID *ppv)
|
||||
{
|
||||
HRESULT result = E_NOINTERFACE;
|
||||
|
||||
|
|
@ -110,7 +110,7 @@ HRESULT STDMETHODCALLTYPE DeckLinkDeviceDiscovery::QueryInterface(REFIID iid,
|
|||
AddRef();
|
||||
result = S_OK;
|
||||
} else if (memcmp(&iid, &IID_IDeckLinkDeviceNotificationCallback,
|
||||
sizeof(REFIID)) == 0) {
|
||||
sizeof(REFIID)) == 0) {
|
||||
*ppv = (IDeckLinkDeviceNotificationCallback *)this;
|
||||
AddRef();
|
||||
result = S_OK;
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@
|
|||
class DeckLinkDevice;
|
||||
|
||||
typedef void (*DeviceChangeCallback)(void *param, DeckLinkDevice *device,
|
||||
bool added);
|
||||
bool added);
|
||||
|
||||
struct DeviceChangeInfo {
|
||||
DeviceChangeCallback callback;
|
||||
|
|
@ -19,11 +19,11 @@ struct DeviceChangeInfo {
|
|||
class DeckLinkDeviceDiscovery : public IDeckLinkDeviceNotificationCallback {
|
||||
protected:
|
||||
ComPtr<IDeckLinkDiscovery> discovery;
|
||||
long refCount = 1;
|
||||
bool initialized = false;
|
||||
long refCount = 1;
|
||||
bool initialized = false;
|
||||
|
||||
std::recursive_mutex deviceMutex;
|
||||
std::vector<DeckLinkDevice*> devices;
|
||||
std::vector<DeckLinkDevice *> devices;
|
||||
std::vector<DeviceChangeInfo> callbacks;
|
||||
|
||||
public:
|
||||
|
|
@ -44,8 +44,7 @@ public:
|
|||
info.param = param;
|
||||
|
||||
for (DeviceChangeInfo &curCB : callbacks) {
|
||||
if (curCB.callback == callback &&
|
||||
curCB.param == param)
|
||||
if (curCB.callback == callback && curCB.param == param)
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -60,7 +59,7 @@ public:
|
|||
DeviceChangeInfo &curCB = callbacks[i];
|
||||
|
||||
if (curCB.callback == callback &&
|
||||
curCB.param == param) {
|
||||
curCB.param == param) {
|
||||
callbacks.erase(callbacks.begin() + i);
|
||||
return;
|
||||
}
|
||||
|
|
@ -69,9 +68,9 @@ public:
|
|||
|
||||
DeckLinkDevice *FindByHash(const char *hash);
|
||||
|
||||
inline void Lock() {deviceMutex.lock();}
|
||||
inline void Unlock() {deviceMutex.unlock();}
|
||||
inline const std::vector<DeckLinkDevice*> &GetDevices() const
|
||||
inline void Lock() { deviceMutex.lock(); }
|
||||
inline void Unlock() { deviceMutex.unlock(); }
|
||||
inline const std::vector<DeckLinkDevice *> &GetDevices() const
|
||||
{
|
||||
return devices;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,7 +13,8 @@
|
|||
static inline enum video_format ConvertPixelFormat(BMDPixelFormat format)
|
||||
{
|
||||
switch (format) {
|
||||
case bmdFormat8BitBGRA: return VIDEO_FORMAT_BGRX;
|
||||
case bmdFormat8BitBGRA:
|
||||
return VIDEO_FORMAT_BGRX;
|
||||
|
||||
default:
|
||||
case bmdFormat8BitYUV:;
|
||||
|
|
@ -38,7 +39,8 @@ static inline int ConvertChannelFormat(speaker_layout format)
|
|||
}
|
||||
}
|
||||
|
||||
static inline audio_repack_mode_t ConvertRepackFormat(speaker_layout format, bool swap)
|
||||
static inline audio_repack_mode_t ConvertRepackFormat(speaker_layout format,
|
||||
bool swap)
|
||||
{
|
||||
switch (format) {
|
||||
case SPEAKERS_2POINT1:
|
||||
|
|
@ -46,11 +48,11 @@ static inline audio_repack_mode_t ConvertRepackFormat(speaker_layout format, boo
|
|||
case SPEAKERS_4POINT0:
|
||||
return repack_mode_8to4ch;
|
||||
case SPEAKERS_4POINT1:
|
||||
return swap? repack_mode_8to5ch_swap:repack_mode_8to5ch;
|
||||
return swap ? repack_mode_8to5ch_swap : repack_mode_8to5ch;
|
||||
case SPEAKERS_5POINT1:
|
||||
return swap ? repack_mode_8to6ch_swap : repack_mode_8to6ch;
|
||||
case SPEAKERS_7POINT1:
|
||||
return swap ? repack_mode_8ch_swap: repack_mode_8ch;
|
||||
return swap ? repack_mode_8ch_swap : repack_mode_8ch;
|
||||
default:
|
||||
assert(false && "No repack requested");
|
||||
return (audio_repack_mode_t)-1;
|
||||
|
|
@ -58,21 +60,18 @@ static inline audio_repack_mode_t ConvertRepackFormat(speaker_layout format, boo
|
|||
}
|
||||
|
||||
DeckLinkDeviceInstance::DeckLinkDeviceInstance(DecklinkBase *decklink_,
|
||||
DeckLinkDevice *device_) :
|
||||
currentFrame(), currentPacket(), decklink(decklink_), device(device_)
|
||||
DeckLinkDevice *device_)
|
||||
: currentFrame(), currentPacket(), decklink(decklink_), device(device_)
|
||||
{
|
||||
currentPacket.samples_per_sec = 48000;
|
||||
currentPacket.speakers = SPEAKERS_STEREO;
|
||||
currentPacket.format = AUDIO_FORMAT_16BIT;
|
||||
currentPacket.speakers = SPEAKERS_STEREO;
|
||||
currentPacket.format = AUDIO_FORMAT_16BIT;
|
||||
}
|
||||
|
||||
DeckLinkDeviceInstance::~DeckLinkDeviceInstance()
|
||||
{
|
||||
}
|
||||
DeckLinkDeviceInstance::~DeckLinkDeviceInstance() {}
|
||||
|
||||
void DeckLinkDeviceInstance::HandleAudioPacket(
|
||||
IDeckLinkAudioInputPacket *audioPacket,
|
||||
const uint64_t timestamp)
|
||||
IDeckLinkAudioInputPacket *audioPacket, const uint64_t timestamp)
|
||||
{
|
||||
if (audioPacket == nullptr)
|
||||
return;
|
||||
|
|
@ -83,11 +82,12 @@ void DeckLinkDeviceInstance::HandleAudioPacket(
|
|||
return;
|
||||
}
|
||||
|
||||
const uint32_t frameCount = (uint32_t)audioPacket->GetSampleFrameCount();
|
||||
currentPacket.frames = frameCount;
|
||||
currentPacket.timestamp = timestamp;
|
||||
const uint32_t frameCount =
|
||||
(uint32_t)audioPacket->GetSampleFrameCount();
|
||||
currentPacket.frames = frameCount;
|
||||
currentPacket.timestamp = timestamp;
|
||||
|
||||
if (decklink && !static_cast<DeckLinkInput*>(decklink)->buffering) {
|
||||
if (decklink && !static_cast<DeckLinkInput *>(decklink)->buffering) {
|
||||
currentPacket.timestamp = os_gettime_ns();
|
||||
currentPacket.timestamp -=
|
||||
(uint64_t)frameCount * 1000000000ULL /
|
||||
|
|
@ -99,8 +99,9 @@ void DeckLinkDeviceInstance::HandleAudioPacket(
|
|||
if (channelFormat != SPEAKERS_UNKNOWN &&
|
||||
channelFormat != SPEAKERS_MONO &&
|
||||
channelFormat != SPEAKERS_STEREO &&
|
||||
(channelFormat != SPEAKERS_7POINT1 || static_cast<DeckLinkInput*>(decklink)->swap)
|
||||
&& maxdevicechannel >= 8) {
|
||||
(channelFormat != SPEAKERS_7POINT1 ||
|
||||
static_cast<DeckLinkInput *>(decklink)->swap) &&
|
||||
maxdevicechannel >= 8) {
|
||||
|
||||
if (audioRepacker->repack((uint8_t *)bytes, frameCount) < 0) {
|
||||
LOG(LOG_ERROR, "Failed to convert audio packet data");
|
||||
|
|
@ -112,13 +113,15 @@ void DeckLinkDeviceInstance::HandleAudioPacket(
|
|||
}
|
||||
|
||||
nextAudioTS = timestamp +
|
||||
((uint64_t)frameCount * 1000000000ULL / 48000ULL) + 1;
|
||||
((uint64_t)frameCount * 1000000000ULL / 48000ULL) + 1;
|
||||
|
||||
obs_source_output_audio(static_cast<DeckLinkInput*>(decklink)->GetSource(), ¤tPacket);
|
||||
obs_source_output_audio(
|
||||
static_cast<DeckLinkInput *>(decklink)->GetSource(),
|
||||
¤tPacket);
|
||||
}
|
||||
|
||||
void DeckLinkDeviceInstance::HandleVideoFrame(
|
||||
IDeckLinkVideoInputFrame *videoFrame, const uint64_t timestamp)
|
||||
IDeckLinkVideoInputFrame *videoFrame, const uint64_t timestamp)
|
||||
{
|
||||
if (videoFrame == nullptr)
|
||||
return;
|
||||
|
|
@ -129,13 +132,15 @@ void DeckLinkDeviceInstance::HandleVideoFrame(
|
|||
return;
|
||||
}
|
||||
|
||||
currentFrame.data[0] = (uint8_t *)bytes;
|
||||
currentFrame.data[0] = (uint8_t *)bytes;
|
||||
currentFrame.linesize[0] = (uint32_t)videoFrame->GetRowBytes();
|
||||
currentFrame.width = (uint32_t)videoFrame->GetWidth();
|
||||
currentFrame.height = (uint32_t)videoFrame->GetHeight();
|
||||
currentFrame.timestamp = timestamp;
|
||||
currentFrame.width = (uint32_t)videoFrame->GetWidth();
|
||||
currentFrame.height = (uint32_t)videoFrame->GetHeight();
|
||||
currentFrame.timestamp = timestamp;
|
||||
|
||||
obs_source_output_video2(static_cast<DeckLinkInput*>(decklink)->GetSource(), ¤tFrame);
|
||||
obs_source_output_video2(
|
||||
static_cast<DeckLinkInput *>(decklink)->GetSource(),
|
||||
¤tFrame);
|
||||
}
|
||||
|
||||
void DeckLinkDeviceInstance::FinalizeStream()
|
||||
|
|
@ -145,8 +150,7 @@ void DeckLinkDeviceInstance::FinalizeStream()
|
|||
if (channelFormat != SPEAKERS_UNKNOWN)
|
||||
input->DisableAudioInput();
|
||||
|
||||
if (audioRepacker != nullptr)
|
||||
{
|
||||
if (audioRepacker != nullptr) {
|
||||
delete audioRepacker;
|
||||
audioRepacker = nullptr;
|
||||
}
|
||||
|
|
@ -163,7 +167,7 @@ void DeckLinkDeviceInstance::SetupVideoFormat(DeckLinkDeviceMode *mode_)
|
|||
|
||||
currentFrame.format = ConvertPixelFormat(pixelFormat);
|
||||
|
||||
colorSpace = static_cast<DeckLinkInput*>(decklink)->GetColorSpace();
|
||||
colorSpace = static_cast<DeckLinkInput *>(decklink)->GetColorSpace();
|
||||
if (colorSpace == VIDEO_CS_DEFAULT) {
|
||||
const BMDDisplayModeFlags flags = mode_->GetDisplayModeFlags();
|
||||
if (flags & bmdDisplayModeColorspaceRec709)
|
||||
|
|
@ -176,24 +180,25 @@ void DeckLinkDeviceInstance::SetupVideoFormat(DeckLinkDeviceMode *mode_)
|
|||
activeColorSpace = colorSpace;
|
||||
}
|
||||
|
||||
colorRange = static_cast<DeckLinkInput*>(decklink)->GetColorRange();
|
||||
colorRange = static_cast<DeckLinkInput *>(decklink)->GetColorRange();
|
||||
currentFrame.range = colorRange;
|
||||
|
||||
video_format_get_parameters(activeColorSpace, colorRange,
|
||||
currentFrame.color_matrix, currentFrame.color_range_min,
|
||||
currentFrame.color_range_max);
|
||||
currentFrame.color_matrix,
|
||||
currentFrame.color_range_min,
|
||||
currentFrame.color_range_max);
|
||||
|
||||
#ifdef LOG_SETUP_VIDEO_FORMAT
|
||||
LOG(LOG_INFO, "Setup video format: %s, %s, %s",
|
||||
pixelFormat == bmdFormat8BitYUV ? "YUV" : "RGB",
|
||||
activeColorSpace == VIDEO_CS_709 ? "BT.709" : "BT.601",
|
||||
colorRange == VIDEO_RANGE_FULL ? "full" : "limited");
|
||||
pixelFormat == bmdFormat8BitYUV ? "YUV" : "RGB",
|
||||
activeColorSpace == VIDEO_CS_709 ? "BT.709" : "BT.601",
|
||||
colorRange == VIDEO_RANGE_FULL ? "full" : "limited");
|
||||
#endif
|
||||
}
|
||||
|
||||
bool DeckLinkDeviceInstance::StartCapture(DeckLinkDeviceMode *mode_,
|
||||
BMDVideoConnection bmdVideoConnection,
|
||||
BMDAudioConnection bmdAudioConnection)
|
||||
BMDVideoConnection bmdVideoConnection,
|
||||
BMDAudioConnection bmdAudioConnection)
|
||||
{
|
||||
if (mode != nullptr)
|
||||
return false;
|
||||
|
|
@ -205,33 +210,33 @@ bool DeckLinkDeviceInstance::StartCapture(DeckLinkDeviceMode *mode_,
|
|||
if (!device->GetInput(&input))
|
||||
return false;
|
||||
|
||||
|
||||
IDeckLinkConfiguration *deckLinkConfiguration = NULL;
|
||||
HRESULT result = input->QueryInterface(IID_IDeckLinkConfiguration,
|
||||
(void**)&deckLinkConfiguration);
|
||||
if (result != S_OK)
|
||||
{
|
||||
(void **)&deckLinkConfiguration);
|
||||
if (result != S_OK) {
|
||||
LOG(LOG_ERROR,
|
||||
"Could not obtain the IDeckLinkConfiguration interface: %08x\n",
|
||||
result);
|
||||
"Could not obtain the IDeckLinkConfiguration interface: %08x\n",
|
||||
result);
|
||||
} else {
|
||||
if (bmdVideoConnection > 0) {
|
||||
result = deckLinkConfiguration->SetInt(
|
||||
bmdDeckLinkConfigVideoInputConnection, bmdVideoConnection);
|
||||
bmdDeckLinkConfigVideoInputConnection,
|
||||
bmdVideoConnection);
|
||||
if (result != S_OK) {
|
||||
LOG(LOG_ERROR,
|
||||
"Couldn't set input video port to %d\n\n",
|
||||
bmdVideoConnection);
|
||||
"Couldn't set input video port to %d\n\n",
|
||||
bmdVideoConnection);
|
||||
}
|
||||
}
|
||||
|
||||
if (bmdAudioConnection > 0) {
|
||||
result = deckLinkConfiguration->SetInt(
|
||||
bmdDeckLinkConfigAudioInputConnection, bmdAudioConnection);
|
||||
bmdDeckLinkConfigAudioInputConnection,
|
||||
bmdAudioConnection);
|
||||
if (result != S_OK) {
|
||||
LOG(LOG_ERROR,
|
||||
"Couldn't set input audio port to %d\n\n",
|
||||
bmdVideoConnection);
|
||||
"Couldn't set input audio port to %d\n\n",
|
||||
bmdVideoConnection);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -248,12 +253,13 @@ bool DeckLinkDeviceInstance::StartCapture(DeckLinkDeviceMode *mode_,
|
|||
flags = bmdVideoInputEnableFormatDetection;
|
||||
} else {
|
||||
displayMode = mode_->GetDisplayMode();
|
||||
pixelFormat = static_cast<DeckLinkInput*>(decklink)->GetPixelFormat();
|
||||
pixelFormat =
|
||||
static_cast<DeckLinkInput *>(decklink)->GetPixelFormat();
|
||||
flags = bmdVideoInputFlagDefault;
|
||||
}
|
||||
|
||||
const HRESULT videoResult = input->EnableVideoInput(displayMode,
|
||||
pixelFormat, flags);
|
||||
const HRESULT videoResult =
|
||||
input->EnableVideoInput(displayMode, pixelFormat, flags);
|
||||
if (videoResult != S_OK) {
|
||||
LOG(LOG_ERROR, "Failed to enable video input");
|
||||
return false;
|
||||
|
|
@ -261,28 +267,30 @@ bool DeckLinkDeviceInstance::StartCapture(DeckLinkDeviceMode *mode_,
|
|||
|
||||
SetupVideoFormat(mode_);
|
||||
|
||||
channelFormat = static_cast<DeckLinkInput*>(decklink)->GetChannelFormat();
|
||||
channelFormat =
|
||||
static_cast<DeckLinkInput *>(decklink)->GetChannelFormat();
|
||||
currentPacket.speakers = channelFormat;
|
||||
swap = static_cast<DeckLinkInput*>(decklink)->swap;
|
||||
swap = static_cast<DeckLinkInput *>(decklink)->swap;
|
||||
|
||||
int maxdevicechannel = device->GetMaxChannel();
|
||||
|
||||
if (channelFormat != SPEAKERS_UNKNOWN) {
|
||||
const int channel = ConvertChannelFormat(channelFormat);
|
||||
const HRESULT audioResult = input->EnableAudioInput(
|
||||
bmdAudioSampleRate48kHz, bmdAudioSampleType16bitInteger,
|
||||
channel);
|
||||
bmdAudioSampleRate48kHz, bmdAudioSampleType16bitInteger,
|
||||
channel);
|
||||
if (audioResult != S_OK)
|
||||
LOG(LOG_WARNING, "Failed to enable audio input; continuing...");
|
||||
LOG(LOG_WARNING,
|
||||
"Failed to enable audio input; continuing...");
|
||||
|
||||
if (channelFormat != SPEAKERS_UNKNOWN &&
|
||||
channelFormat != SPEAKERS_MONO &&
|
||||
channelFormat != SPEAKERS_STEREO &&
|
||||
(channelFormat != SPEAKERS_7POINT1 || swap)
|
||||
&& maxdevicechannel >= 8) {
|
||||
(channelFormat != SPEAKERS_7POINT1 || swap) &&
|
||||
maxdevicechannel >= 8) {
|
||||
|
||||
const audio_repack_mode_t repack_mode = ConvertRepackFormat
|
||||
(channelFormat, swap);
|
||||
const audio_repack_mode_t repack_mode =
|
||||
ConvertRepackFormat(channelFormat, swap);
|
||||
audioRepacker = new AudioRepacker(repack_mode);
|
||||
}
|
||||
}
|
||||
|
|
@ -310,7 +318,7 @@ bool DeckLinkDeviceInstance::StopCapture(void)
|
|||
return false;
|
||||
|
||||
LOG(LOG_INFO, "Stopping capture of '%s'...",
|
||||
GetDevice()->GetDisplayName().c_str());
|
||||
GetDevice()->GetDisplayName().c_str());
|
||||
|
||||
input->StopStreams();
|
||||
FinalizeStream();
|
||||
|
|
@ -331,18 +339,15 @@ bool DeckLinkDeviceInstance::StartOutput(DeckLinkDeviceMode *mode_)
|
|||
return false;
|
||||
|
||||
const HRESULT videoResult = output->EnableVideoOutput(
|
||||
mode_->GetDisplayMode(),
|
||||
bmdVideoOutputFlagDefault);
|
||||
mode_->GetDisplayMode(), bmdVideoOutputFlagDefault);
|
||||
if (videoResult != S_OK) {
|
||||
LOG(LOG_ERROR, "Failed to enable video output");
|
||||
return false;
|
||||
}
|
||||
|
||||
const HRESULT audioResult = output->EnableAudioOutput(
|
||||
bmdAudioSampleRate48kHz,
|
||||
bmdAudioSampleType16bitInteger,
|
||||
2,
|
||||
bmdAudioOutputStreamTimestamped);
|
||||
bmdAudioSampleRate48kHz, bmdAudioSampleType16bitInteger, 2,
|
||||
bmdAudioOutputStreamTimestamped);
|
||||
if (audioResult != S_OK) {
|
||||
LOG(LOG_ERROR, "Failed to enable audio output");
|
||||
return false;
|
||||
|
|
@ -362,7 +367,7 @@ bool DeckLinkDeviceInstance::StartOutput(DeckLinkDeviceMode *mode_)
|
|||
}
|
||||
}
|
||||
|
||||
auto decklinkOutput = dynamic_cast<DeckLinkOutput*>(decklink);
|
||||
auto decklinkOutput = dynamic_cast<DeckLinkOutput *>(decklink);
|
||||
if (decklinkOutput == nullptr)
|
||||
return false;
|
||||
|
||||
|
|
@ -378,13 +383,11 @@ bool DeckLinkDeviceInstance::StartOutput(DeckLinkDeviceMode *mode_)
|
|||
|
||||
HRESULT result;
|
||||
result = output->CreateVideoFrame(decklinkOutput->GetWidth(),
|
||||
decklinkOutput->GetHeight(),
|
||||
rowBytes,
|
||||
pixelFormat,
|
||||
bmdFrameFlagDefault,
|
||||
&decklinkOutputFrame);
|
||||
decklinkOutput->GetHeight(), rowBytes,
|
||||
pixelFormat, bmdFrameFlagDefault,
|
||||
&decklinkOutputFrame);
|
||||
if (result != S_OK) {
|
||||
blog(LOG_ERROR ,"failed to make frame 0x%X", result);
|
||||
blog(LOG_ERROR, "failed to make frame 0x%X", result);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -397,7 +400,7 @@ bool DeckLinkDeviceInstance::StopOutput()
|
|||
return false;
|
||||
|
||||
LOG(LOG_INFO, "Stopping output of '%s'...",
|
||||
GetDevice()->GetDisplayName().c_str());
|
||||
GetDevice()->GetDisplayName().c_str());
|
||||
|
||||
output->DisableVideoOutput();
|
||||
output->DisableAudioOutput();
|
||||
|
|
@ -412,12 +415,12 @@ bool DeckLinkDeviceInstance::StopOutput()
|
|||
|
||||
void DeckLinkDeviceInstance::DisplayVideoFrame(video_data *frame)
|
||||
{
|
||||
auto decklinkOutput = dynamic_cast<DeckLinkOutput*>(decklink);
|
||||
auto decklinkOutput = dynamic_cast<DeckLinkOutput *>(decklink);
|
||||
if (decklinkOutput == nullptr)
|
||||
return;
|
||||
|
||||
uint8_t *destData;
|
||||
decklinkOutputFrame->GetBytes((void**)&destData);
|
||||
decklinkOutputFrame->GetBytes((void **)&destData);
|
||||
|
||||
uint8_t *outData = frame->data[0];
|
||||
|
||||
|
|
@ -426,8 +429,8 @@ void DeckLinkDeviceInstance::DisplayVideoFrame(video_data *frame)
|
|||
rowBytes = decklinkOutput->GetWidth() * 4;
|
||||
}
|
||||
|
||||
std::copy(outData, outData + (decklinkOutput->GetHeight() *
|
||||
rowBytes), destData);
|
||||
std::copy(outData, outData + (decklinkOutput->GetHeight() * rowBytes),
|
||||
destData);
|
||||
|
||||
output->DisplayVideoFrameSync(decklinkOutputFrame);
|
||||
}
|
||||
|
|
@ -435,16 +438,15 @@ void DeckLinkDeviceInstance::DisplayVideoFrame(video_data *frame)
|
|||
void DeckLinkDeviceInstance::WriteAudio(audio_data *frames)
|
||||
{
|
||||
uint32_t sampleFramesWritten;
|
||||
output->WriteAudioSamplesSync(frames->data[0],
|
||||
frames->frames,
|
||||
&sampleFramesWritten);
|
||||
output->WriteAudioSamplesSync(frames->data[0], frames->frames,
|
||||
&sampleFramesWritten);
|
||||
}
|
||||
|
||||
#define TIME_BASE 1000000000
|
||||
|
||||
HRESULT STDMETHODCALLTYPE DeckLinkDeviceInstance::VideoInputFrameArrived(
|
||||
IDeckLinkVideoInputFrame *videoFrame,
|
||||
IDeckLinkAudioInputPacket *audioPacket)
|
||||
IDeckLinkVideoInputFrame *videoFrame,
|
||||
IDeckLinkAudioInputPacket *audioPacket)
|
||||
{
|
||||
BMDTimeValue videoTS = 0;
|
||||
BMDTimeValue videoDur = 0;
|
||||
|
|
@ -481,9 +483,8 @@ HRESULT STDMETHODCALLTYPE DeckLinkDeviceInstance::VideoInputFrameArrived(
|
|||
}
|
||||
|
||||
HRESULT STDMETHODCALLTYPE DeckLinkDeviceInstance::VideoInputFormatChanged(
|
||||
BMDVideoInputFormatChangedEvents events,
|
||||
IDeckLinkDisplayMode *newMode,
|
||||
BMDDetectedVideoInputFormatFlags detectedSignalFlags)
|
||||
BMDVideoInputFormatChangedEvents events, IDeckLinkDisplayMode *newMode,
|
||||
BMDDetectedVideoInputFormatFlags detectedSignalFlags)
|
||||
{
|
||||
input->PauseStreams();
|
||||
|
||||
|
|
@ -506,8 +507,8 @@ HRESULT STDMETHODCALLTYPE DeckLinkDeviceInstance::VideoInputFormatChanged(
|
|||
}
|
||||
}
|
||||
|
||||
const HRESULT videoResult = input->EnableVideoInput(displayMode,
|
||||
pixelFormat, bmdVideoInputEnableFormatDetection);
|
||||
const HRESULT videoResult = input->EnableVideoInput(
|
||||
displayMode, pixelFormat, bmdVideoInputEnableFormatDetection);
|
||||
if (videoResult != S_OK) {
|
||||
LOG(LOG_ERROR, "Failed to enable video input");
|
||||
input->StopStreams();
|
||||
|
|
@ -530,7 +531,7 @@ ULONG STDMETHODCALLTYPE DeckLinkDeviceInstance::AddRef(void)
|
|||
}
|
||||
|
||||
HRESULT STDMETHODCALLTYPE DeckLinkDeviceInstance::QueryInterface(REFIID iid,
|
||||
LPVOID *ppv)
|
||||
LPVOID *ppv)
|
||||
{
|
||||
HRESULT result = E_NOINTERFACE;
|
||||
|
||||
|
|
@ -542,7 +543,7 @@ HRESULT STDMETHODCALLTYPE DeckLinkDeviceInstance::QueryInterface(REFIID iid,
|
|||
AddRef();
|
||||
result = S_OK;
|
||||
} else if (memcmp(&iid, &IID_IDeckLinkNotificationCallback,
|
||||
sizeof(REFIID)) == 0) {
|
||||
sizeof(REFIID)) == 0) {
|
||||
*ppv = (IDeckLinkNotificationCallback *)this;
|
||||
AddRef();
|
||||
result = S_OK;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
#pragma once
|
||||
|
||||
#define LOG(level, message, ...) blog(level, "%s: " message, "decklink", ##__VA_ARGS__)
|
||||
#define LOG(level, message, ...) \
|
||||
blog(level, "%s: " message, "decklink", ##__VA_ARGS__)
|
||||
|
||||
#include <obs-module.h>
|
||||
#include "decklink-device.hpp"
|
||||
|
|
@ -13,25 +14,25 @@ class DeckLinkDeviceInstance : public IDeckLinkInputCallback {
|
|||
protected:
|
||||
struct obs_source_frame2 currentFrame;
|
||||
struct obs_source_audio currentPacket;
|
||||
DecklinkBase *decklink = nullptr;
|
||||
DeckLinkDevice *device = nullptr;
|
||||
DeckLinkDeviceMode *mode = nullptr;
|
||||
BMDVideoConnection videoConnection;
|
||||
BMDAudioConnection audioConnection;
|
||||
BMDDisplayMode displayMode = bmdModeNTSC;
|
||||
BMDPixelFormat pixelFormat = bmdFormat8BitYUV;
|
||||
video_colorspace colorSpace = VIDEO_CS_DEFAULT;
|
||||
video_colorspace activeColorSpace = VIDEO_CS_DEFAULT;
|
||||
video_range_type colorRange = VIDEO_RANGE_DEFAULT;
|
||||
ComPtr<IDeckLinkInput> input;
|
||||
DecklinkBase *decklink = nullptr;
|
||||
DeckLinkDevice *device = nullptr;
|
||||
DeckLinkDeviceMode *mode = nullptr;
|
||||
BMDVideoConnection videoConnection;
|
||||
BMDAudioConnection audioConnection;
|
||||
BMDDisplayMode displayMode = bmdModeNTSC;
|
||||
BMDPixelFormat pixelFormat = bmdFormat8BitYUV;
|
||||
video_colorspace colorSpace = VIDEO_CS_DEFAULT;
|
||||
video_colorspace activeColorSpace = VIDEO_CS_DEFAULT;
|
||||
video_range_type colorRange = VIDEO_RANGE_DEFAULT;
|
||||
ComPtr<IDeckLinkInput> input;
|
||||
ComPtr<IDeckLinkOutput> output;
|
||||
volatile long refCount = 1;
|
||||
int64_t audioOffset = 0;
|
||||
uint64_t nextAudioTS = 0;
|
||||
uint64_t lastVideoTS = 0;
|
||||
AudioRepacker *audioRepacker = nullptr;
|
||||
speaker_layout channelFormat = SPEAKERS_STEREO;
|
||||
bool swap;
|
||||
volatile long refCount = 1;
|
||||
int64_t audioOffset = 0;
|
||||
uint64_t nextAudioTS = 0;
|
||||
uint64_t lastVideoTS = 0;
|
||||
AudioRepacker *audioRepacker = nullptr;
|
||||
speaker_layout channelFormat = SPEAKERS_STEREO;
|
||||
bool swap;
|
||||
|
||||
IDeckLinkMutableVideoFrame *decklinkOutputFrame = nullptr;
|
||||
|
||||
|
|
@ -39,45 +40,63 @@ protected:
|
|||
void SetupVideoFormat(DeckLinkDeviceMode *mode_);
|
||||
|
||||
void HandleAudioPacket(IDeckLinkAudioInputPacket *audioPacket,
|
||||
const uint64_t timestamp);
|
||||
const uint64_t timestamp);
|
||||
void HandleVideoFrame(IDeckLinkVideoInputFrame *videoFrame,
|
||||
const uint64_t timestamp);
|
||||
const uint64_t timestamp);
|
||||
|
||||
public:
|
||||
DeckLinkDeviceInstance(DecklinkBase *decklink, DeckLinkDevice *device);
|
||||
virtual ~DeckLinkDeviceInstance();
|
||||
|
||||
inline DeckLinkDevice *GetDevice() const {return device;}
|
||||
inline DeckLinkDevice *GetDevice() const { return device; }
|
||||
inline long long GetActiveModeId() const
|
||||
{
|
||||
return mode ? mode->GetId() : 0;
|
||||
}
|
||||
|
||||
inline BMDPixelFormat GetActivePixelFormat() const {return pixelFormat;}
|
||||
inline video_colorspace GetActiveColorSpace() const {return colorSpace;}
|
||||
inline video_range_type GetActiveColorRange() const {return colorRange;}
|
||||
inline speaker_layout GetActiveChannelFormat() const {return channelFormat;}
|
||||
inline bool GetActiveSwapState() const {return swap;}
|
||||
inline BMDVideoConnection GetVideoConnection() const {return videoConnection;}
|
||||
inline BMDAudioConnection GetAudioConnection() const {return audioConnection;}
|
||||
inline BMDPixelFormat GetActivePixelFormat() const
|
||||
{
|
||||
return pixelFormat;
|
||||
}
|
||||
inline video_colorspace GetActiveColorSpace() const
|
||||
{
|
||||
return colorSpace;
|
||||
}
|
||||
inline video_range_type GetActiveColorRange() const
|
||||
{
|
||||
return colorRange;
|
||||
}
|
||||
inline speaker_layout GetActiveChannelFormat() const
|
||||
{
|
||||
return channelFormat;
|
||||
}
|
||||
inline bool GetActiveSwapState() const { return swap; }
|
||||
inline BMDVideoConnection GetVideoConnection() const
|
||||
{
|
||||
return videoConnection;
|
||||
}
|
||||
inline BMDAudioConnection GetAudioConnection() const
|
||||
{
|
||||
return audioConnection;
|
||||
}
|
||||
|
||||
inline DeckLinkDeviceMode *GetMode() const {return mode;}
|
||||
inline DeckLinkDeviceMode *GetMode() const { return mode; }
|
||||
|
||||
bool StartCapture(DeckLinkDeviceMode *mode,
|
||||
BMDVideoConnection bmdVideoConnection,
|
||||
BMDAudioConnection bmdAudioConnection);
|
||||
BMDVideoConnection bmdVideoConnection,
|
||||
BMDAudioConnection bmdAudioConnection);
|
||||
bool StopCapture(void);
|
||||
|
||||
bool StartOutput(DeckLinkDeviceMode *mode_);
|
||||
bool StopOutput(void);
|
||||
|
||||
HRESULT STDMETHODCALLTYPE VideoInputFrameArrived(
|
||||
IDeckLinkVideoInputFrame *videoFrame,
|
||||
IDeckLinkAudioInputPacket *audioPacket);
|
||||
HRESULT STDMETHODCALLTYPE
|
||||
VideoInputFrameArrived(IDeckLinkVideoInputFrame *videoFrame,
|
||||
IDeckLinkAudioInputPacket *audioPacket);
|
||||
HRESULT STDMETHODCALLTYPE VideoInputFormatChanged(
|
||||
BMDVideoInputFormatChangedEvents events,
|
||||
IDeckLinkDisplayMode *newMode,
|
||||
BMDDetectedVideoInputFormatFlags detectedSignalFlags);
|
||||
BMDVideoInputFormatChangedEvents events,
|
||||
IDeckLinkDisplayMode *newMode,
|
||||
BMDDetectedVideoInputFormatFlags detectedSignalFlags);
|
||||
|
||||
ULONG STDMETHODCALLTYPE AddRef(void);
|
||||
HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, LPVOID *ppv);
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
#include "decklink-device-mode.hpp"
|
||||
|
||||
DeckLinkDeviceMode::DeckLinkDeviceMode(IDeckLinkDisplayMode *mode,
|
||||
long long id) : id(id), mode(mode)
|
||||
DeckLinkDeviceMode::DeckLinkDeviceMode(IDeckLinkDisplayMode *mode, long long id)
|
||||
: id(id), mode(mode)
|
||||
{
|
||||
if (mode == nullptr)
|
||||
return;
|
||||
|
|
@ -13,8 +13,8 @@ DeckLinkDeviceMode::DeckLinkDeviceMode(IDeckLinkDisplayMode *mode,
|
|||
DeckLinkStringToStdString(decklinkStringName, name);
|
||||
}
|
||||
|
||||
DeckLinkDeviceMode::DeckLinkDeviceMode(const std::string& name, long long id) :
|
||||
id(id), mode(nullptr), name(name)
|
||||
DeckLinkDeviceMode::DeckLinkDeviceMode(const std::string &name, long long id)
|
||||
: id(id), mode(nullptr), name(name)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
@ -61,7 +61,7 @@ long long DeckLinkDeviceMode::GetId(void) const
|
|||
return id;
|
||||
}
|
||||
|
||||
const std::string& DeckLinkDeviceMode::GetName(void) const
|
||||
const std::string &DeckLinkDeviceMode::GetName(void) const
|
||||
{
|
||||
return name;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,23 +4,23 @@
|
|||
|
||||
#include <string>
|
||||
|
||||
#define MODE_ID_AUTO -1
|
||||
#define MODE_ID_AUTO -1
|
||||
|
||||
class DeckLinkDeviceMode {
|
||||
protected:
|
||||
long long id;
|
||||
long long id;
|
||||
IDeckLinkDisplayMode *mode;
|
||||
std::string name;
|
||||
std::string name;
|
||||
|
||||
public:
|
||||
DeckLinkDeviceMode(IDeckLinkDisplayMode *mode, long long id);
|
||||
DeckLinkDeviceMode(const std::string& name, long long id);
|
||||
DeckLinkDeviceMode(const std::string &name, long long id);
|
||||
virtual ~DeckLinkDeviceMode(void);
|
||||
|
||||
BMDDisplayMode GetDisplayMode(void) const;
|
||||
BMDDisplayModeFlags GetDisplayModeFlags(void) const;
|
||||
long long GetId(void) const;
|
||||
const std::string& GetName(void) const;
|
||||
const std::string &GetName(void) const;
|
||||
|
||||
void SetMode(IDeckLinkDisplayMode *mode);
|
||||
|
||||
|
|
|
|||
|
|
@ -4,9 +4,7 @@
|
|||
|
||||
#include <util/threading.h>
|
||||
|
||||
DeckLinkDevice::DeckLinkDevice(IDeckLink *device_) : device(device_)
|
||||
{
|
||||
}
|
||||
DeckLinkDevice::DeckLinkDevice(IDeckLink *device_) : device(device_) {}
|
||||
|
||||
DeckLinkDevice::~DeckLinkDevice(void)
|
||||
{
|
||||
|
|
@ -34,15 +32,15 @@ bool DeckLinkDevice::Init()
|
|||
{
|
||||
ComPtr<IDeckLinkAttributes> attributes;
|
||||
const HRESULT result = device->QueryInterface(IID_IDeckLinkAttributes,
|
||||
(void **)&attributes);
|
||||
(void **)&attributes);
|
||||
|
||||
if (result == S_OK) {
|
||||
decklink_bool_t detectable = false;
|
||||
if (attributes->GetFlag(BMDDeckLinkSupportsInputFormatDetection,
|
||||
&detectable) == S_OK && !!detectable) {
|
||||
DeckLinkDeviceMode *mode = new DeckLinkDeviceMode(
|
||||
"Auto",
|
||||
MODE_ID_AUTO);
|
||||
&detectable) == S_OK &&
|
||||
!!detectable) {
|
||||
DeckLinkDeviceMode *mode =
|
||||
new DeckLinkDeviceMode("Auto", MODE_ID_AUTO);
|
||||
inputModes.push_back(mode);
|
||||
inputModeIdMap[MODE_ID_AUTO] = mode;
|
||||
}
|
||||
|
|
@ -50,7 +48,8 @@ bool DeckLinkDevice::Init()
|
|||
|
||||
// Find input modes
|
||||
ComPtr<IDeckLinkInput> input;
|
||||
if (device->QueryInterface(IID_IDeckLinkInput, (void **) &input) == S_OK) {
|
||||
if (device->QueryInterface(IID_IDeckLinkInput, (void **)&input) ==
|
||||
S_OK) {
|
||||
IDeckLinkDisplayModeIterator *modeIterator;
|
||||
if (input->GetDisplayModeIterator(&modeIterator) == S_OK) {
|
||||
IDeckLinkDisplayMode *displayMode;
|
||||
|
|
@ -61,7 +60,8 @@ bool DeckLinkDevice::Init()
|
|||
continue;
|
||||
|
||||
DeckLinkDeviceMode *mode =
|
||||
new DeckLinkDeviceMode(displayMode, modeId);
|
||||
new DeckLinkDeviceMode(displayMode,
|
||||
modeId);
|
||||
inputModes.push_back(mode);
|
||||
inputModeIdMap[modeId] = mode;
|
||||
displayMode->Release();
|
||||
|
|
@ -74,19 +74,20 @@ bool DeckLinkDevice::Init()
|
|||
|
||||
// Get supported video connections
|
||||
attributes->GetInt(BMDDeckLinkVideoInputConnections,
|
||||
&supportedVideoInputConnections);
|
||||
&supportedVideoInputConnections);
|
||||
attributes->GetInt(BMDDeckLinkVideoOutputConnections,
|
||||
&supportedVideoOutputConnections);
|
||||
&supportedVideoOutputConnections);
|
||||
|
||||
// Get supported audio connections
|
||||
attributes->GetInt(BMDDeckLinkAudioInputConnections,
|
||||
&supportedAudioInputConnections);
|
||||
&supportedAudioInputConnections);
|
||||
attributes->GetInt(BMDDeckLinkAudioOutputConnections,
|
||||
&supportedAudioOutputConnections);
|
||||
&supportedAudioOutputConnections);
|
||||
|
||||
// find output modes
|
||||
ComPtr<IDeckLinkOutput> output;
|
||||
if (device->QueryInterface(IID_IDeckLinkOutput, (void **) &output) == S_OK) {
|
||||
if (device->QueryInterface(IID_IDeckLinkOutput, (void **)&output) ==
|
||||
S_OK) {
|
||||
|
||||
IDeckLinkDisplayModeIterator *modeIterator;
|
||||
if (output->GetDisplayModeIterator(&modeIterator) == S_OK) {
|
||||
|
|
@ -98,7 +99,8 @@ bool DeckLinkDevice::Init()
|
|||
continue;
|
||||
|
||||
DeckLinkDeviceMode *mode =
|
||||
new DeckLinkDeviceMode(displayMode, modeId);
|
||||
new DeckLinkDeviceMode(displayMode,
|
||||
modeId);
|
||||
outputModes.push_back(mode);
|
||||
outputModeIdMap[modeId] = mode;
|
||||
displayMode->Release();
|
||||
|
|
@ -111,9 +113,9 @@ bool DeckLinkDevice::Init()
|
|||
|
||||
// get keyer support
|
||||
attributes->GetFlag(BMDDeckLinkSupportsExternalKeying,
|
||||
&supportsExternalKeyer);
|
||||
&supportsExternalKeyer);
|
||||
attributes->GetFlag(BMDDeckLinkSupportsInternalKeying,
|
||||
&supportsInternalKeyer);
|
||||
&supportsInternalKeyer);
|
||||
|
||||
// Sub Device Counts
|
||||
attributes->GetInt(BMDDeckLinkSubDeviceIndex, &subDeviceIndex);
|
||||
|
|
@ -139,7 +141,8 @@ bool DeckLinkDevice::Init()
|
|||
/* Intensity Shuttle for Thunderbolt return 2; however, it supports 8 channels */
|
||||
if (name == "Intensity Shuttle Thunderbolt")
|
||||
maxChannel = 8;
|
||||
else if (attributes->GetInt(BMDDeckLinkMaximumAudioChannels, &channels) == S_OK)
|
||||
else if (attributes->GetInt(BMDDeckLinkMaximumAudioChannels,
|
||||
&channels) == S_OK)
|
||||
maxChannel = (int32_t)channels;
|
||||
else
|
||||
maxChannel = 2;
|
||||
|
|
@ -149,7 +152,7 @@ bool DeckLinkDevice::Init()
|
|||
* BMDDeckLinkPersistentID for newer ones */
|
||||
|
||||
int64_t value;
|
||||
if (attributes->GetInt(BMDDeckLinkPersistentID, &value) != S_OK &&
|
||||
if (attributes->GetInt(BMDDeckLinkPersistentID, &value) != S_OK &&
|
||||
attributes->GetInt(BMDDeckLinkTopologicalID, &value) != S_OK)
|
||||
return true;
|
||||
|
||||
|
|
@ -161,14 +164,15 @@ bool DeckLinkDevice::Init()
|
|||
|
||||
bool DeckLinkDevice::GetInput(IDeckLinkInput **input)
|
||||
{
|
||||
if (device->QueryInterface(IID_IDeckLinkInput, (void**)input) != S_OK)
|
||||
if (device->QueryInterface(IID_IDeckLinkInput, (void **)input) != S_OK)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool DeckLinkDevice::GetOutput(IDeckLinkOutput **output)
|
||||
{
|
||||
if (device->QueryInterface(IID_IDeckLinkOutput, (void**)output) != S_OK)
|
||||
if (device->QueryInterface(IID_IDeckLinkOutput, (void **)output) !=
|
||||
S_OK)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
|
|
@ -176,9 +180,10 @@ bool DeckLinkDevice::GetOutput(IDeckLinkOutput **output)
|
|||
|
||||
bool DeckLinkDevice::GetKeyer(IDeckLinkKeyer **deckLinkKeyer)
|
||||
{
|
||||
if (device->QueryInterface(IID_IDeckLinkKeyer, (void**)deckLinkKeyer) != S_OK)
|
||||
{
|
||||
fprintf(stderr, "Could not obtain the IDeckLinkKeyer interface\n");
|
||||
if (device->QueryInterface(IID_IDeckLinkKeyer,
|
||||
(void **)deckLinkKeyer) != S_OK) {
|
||||
fprintf(stderr,
|
||||
"Could not obtain the IDeckLinkKeyer interface\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -205,22 +210,24 @@ DeckLinkDeviceMode *DeckLinkDevice::FindOutputMode(long long id)
|
|||
return outputModeIdMap[id];
|
||||
}
|
||||
|
||||
const std::string& DeckLinkDevice::GetDisplayName(void)
|
||||
const std::string &DeckLinkDevice::GetDisplayName(void)
|
||||
{
|
||||
return displayName;
|
||||
}
|
||||
|
||||
const std::string& DeckLinkDevice::GetHash(void) const
|
||||
const std::string &DeckLinkDevice::GetHash(void) const
|
||||
{
|
||||
return hash;
|
||||
}
|
||||
|
||||
const std::vector<DeckLinkDeviceMode *>& DeckLinkDevice::GetInputModes(void) const
|
||||
const std::vector<DeckLinkDeviceMode *> &
|
||||
DeckLinkDevice::GetInputModes(void) const
|
||||
{
|
||||
return inputModes;
|
||||
}
|
||||
|
||||
const std::vector<DeckLinkDeviceMode *>& DeckLinkDevice::GetOutputModes(void) const
|
||||
const std::vector<DeckLinkDeviceMode *> &
|
||||
DeckLinkDevice::GetOutputModes(void) const
|
||||
{
|
||||
return outputModes;
|
||||
}
|
||||
|
|
@ -235,7 +242,6 @@ int64_t DeckLinkDevice::GetAudioInputConnections()
|
|||
return supportedAudioInputConnections;
|
||||
}
|
||||
|
||||
|
||||
bool DeckLinkDevice::GetSupportsExternalKeyer(void) const
|
||||
{
|
||||
return supportsExternalKeyer;
|
||||
|
|
@ -256,7 +262,7 @@ int64_t DeckLinkDevice::GetSubDeviceIndex()
|
|||
return subDeviceIndex;
|
||||
}
|
||||
|
||||
const std::string& DeckLinkDevice::GetName(void) const
|
||||
const std::string &DeckLinkDevice::GetName(void) const
|
||||
{
|
||||
return name;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,28 +7,26 @@
|
|||
#include <vector>
|
||||
#include <stdint.h>
|
||||
|
||||
|
||||
|
||||
class DeckLinkDevice {
|
||||
ComPtr<IDeckLink> device;
|
||||
ComPtr<IDeckLink> device;
|
||||
std::map<long long, DeckLinkDeviceMode *> inputModeIdMap;
|
||||
std::vector<DeckLinkDeviceMode *> inputModes;
|
||||
std::vector<DeckLinkDeviceMode *> inputModes;
|
||||
std::map<long long, DeckLinkDeviceMode *> outputModeIdMap;
|
||||
std::vector<DeckLinkDeviceMode *> outputModes;
|
||||
std::string name;
|
||||
std::string displayName;
|
||||
std::string hash;
|
||||
int32_t maxChannel = 0;
|
||||
decklink_bool_t supportsExternalKeyer = false;
|
||||
decklink_bool_t supportsInternalKeyer = false;
|
||||
int64_t subDeviceIndex = 0;
|
||||
int64_t numSubDevices = 0;
|
||||
int64_t supportedVideoInputConnections = -1;
|
||||
int64_t supportedVideoOutputConnections = -1;
|
||||
int64_t supportedAudioInputConnections = -1;
|
||||
int64_t supportedAudioOutputConnections = -1;
|
||||
int keyerMode = 0;
|
||||
volatile long refCount = 1;
|
||||
std::vector<DeckLinkDeviceMode *> outputModes;
|
||||
std::string name;
|
||||
std::string displayName;
|
||||
std::string hash;
|
||||
int32_t maxChannel = 0;
|
||||
decklink_bool_t supportsExternalKeyer = false;
|
||||
decklink_bool_t supportsInternalKeyer = false;
|
||||
int64_t subDeviceIndex = 0;
|
||||
int64_t numSubDevices = 0;
|
||||
int64_t supportedVideoInputConnections = -1;
|
||||
int64_t supportedVideoOutputConnections = -1;
|
||||
int64_t supportedAudioInputConnections = -1;
|
||||
int64_t supportedAudioOutputConnections = -1;
|
||||
int keyerMode = 0;
|
||||
volatile long refCount = 1;
|
||||
|
||||
public:
|
||||
DeckLinkDevice(IDeckLink *device);
|
||||
|
|
@ -41,10 +39,10 @@ public:
|
|||
|
||||
DeckLinkDeviceMode *FindInputMode(long long id);
|
||||
DeckLinkDeviceMode *FindOutputMode(long long id);
|
||||
const std::string& GetDisplayName(void);
|
||||
const std::string& GetHash(void) const;
|
||||
const std::vector<DeckLinkDeviceMode *>& GetInputModes(void) const;
|
||||
const std::vector<DeckLinkDeviceMode *>& GetOutputModes(void) const;
|
||||
const std::string &GetDisplayName(void);
|
||||
const std::string &GetHash(void) const;
|
||||
const std::vector<DeckLinkDeviceMode *> &GetInputModes(void) const;
|
||||
const std::vector<DeckLinkDeviceMode *> &GetOutputModes(void) const;
|
||||
int64_t GetVideoInputConnections();
|
||||
int64_t GetAudioInputConnections();
|
||||
bool GetSupportsExternalKeyer(void) const;
|
||||
|
|
@ -53,15 +51,12 @@ public:
|
|||
int64_t GetSubDeviceIndex();
|
||||
int GetKeyerMode(void);
|
||||
void SetKeyerMode(int newKeyerMode);
|
||||
const std::string& GetName(void) const;
|
||||
const std::string &GetName(void) const;
|
||||
int32_t GetMaxChannel(void) const;
|
||||
|
||||
bool GetInput(IDeckLinkInput **input);
|
||||
bool GetOutput(IDeckLinkOutput **output);
|
||||
bool GetKeyer(IDeckLinkKeyer **keyer);
|
||||
|
||||
inline bool IsDevice(IDeckLink *device_)
|
||||
{
|
||||
return device_ == device;
|
||||
}
|
||||
inline bool IsDevice(IDeckLink *device_) { return device_ == device; }
|
||||
};
|
||||
|
|
|
|||
|
|
@ -6,11 +6,11 @@ void fill_out_devices(obs_property_t *list)
|
|||
{
|
||||
deviceEnum->Lock();
|
||||
|
||||
const std::vector<DeckLinkDevice*> &devices = deviceEnum->GetDevices();
|
||||
const std::vector<DeckLinkDevice *> &devices = deviceEnum->GetDevices();
|
||||
for (DeckLinkDevice *device : devices) {
|
||||
obs_property_list_add_string(list,
|
||||
device->GetDisplayName().c_str(),
|
||||
device->GetHash().c_str());
|
||||
device->GetDisplayName().c_str(),
|
||||
device->GetHash().c_str());
|
||||
}
|
||||
|
||||
deviceEnum->Unlock();
|
||||
|
|
|
|||
|
|
@ -48,7 +48,8 @@ static bool decklink_output_start(void *data)
|
|||
|
||||
decklink->audio_samplerate = aoi.samples_per_sec;
|
||||
decklink->audio_planes = 2;
|
||||
decklink->audio_size = get_audio_size(AUDIO_FORMAT_16BIT, aoi.speakers, 1);
|
||||
decklink->audio_size =
|
||||
get_audio_size(AUDIO_FORMAT_16BIT, aoi.speakers, 1);
|
||||
|
||||
decklink->start_timestamp = 0;
|
||||
|
||||
|
|
@ -68,7 +69,7 @@ static bool decklink_output_start(void *data)
|
|||
to.format = VIDEO_FORMAT_UYVY;
|
||||
}
|
||||
to.width = mode->GetWidth();
|
||||
to.height = mode->GetHeight();
|
||||
to.height = mode->GetHeight();
|
||||
|
||||
obs_output_set_video_conversion(decklink->GetOutput(), &to);
|
||||
|
||||
|
|
@ -78,7 +79,7 @@ static bool decklink_output_start(void *data)
|
|||
struct audio_convert_info conversion = {};
|
||||
conversion.format = AUDIO_FORMAT_16BIT;
|
||||
conversion.speakers = SPEAKERS_STEREO;
|
||||
conversion.samples_per_sec = 48000; // Only format the decklink supports
|
||||
conversion.samples_per_sec = 48000; // Only format the decklink supports
|
||||
|
||||
obs_output_set_audio_conversion(decklink->GetOutput(), &conversion);
|
||||
|
||||
|
|
@ -112,14 +113,14 @@ static void decklink_output_raw_video(void *data, struct video_data *frame)
|
|||
}
|
||||
|
||||
static bool prepare_audio(DeckLinkOutput *decklink,
|
||||
const struct audio_data *frame,
|
||||
struct audio_data *output)
|
||||
const struct audio_data *frame,
|
||||
struct audio_data *output)
|
||||
{
|
||||
*output = *frame;
|
||||
|
||||
if (frame->timestamp < decklink->start_timestamp) {
|
||||
uint64_t duration = (uint64_t)frame->frames * 1000000000 /
|
||||
(uint64_t)decklink->audio_samplerate;
|
||||
(uint64_t)decklink->audio_samplerate;
|
||||
uint64_t end_ts = frame->timestamp + duration;
|
||||
uint64_t cutoff;
|
||||
|
||||
|
|
@ -132,8 +133,8 @@ static bool prepare_audio(DeckLinkOutput *decklink,
|
|||
cutoff *= (uint64_t)decklink->audio_samplerate / 1000000000;
|
||||
|
||||
for (size_t i = 0; i < decklink->audio_planes; i++)
|
||||
output->data[i] += decklink->audio_size *
|
||||
(uint32_t)cutoff;
|
||||
output->data[i] +=
|
||||
decklink->audio_size * (uint32_t)cutoff;
|
||||
|
||||
output->frames -= (uint32_t)cutoff;
|
||||
}
|
||||
|
|
@ -156,7 +157,8 @@ static void decklink_output_raw_audio(void *data, struct audio_data *frames)
|
|||
}
|
||||
|
||||
static bool decklink_output_device_changed(obs_properties_t *props,
|
||||
obs_property_t *list, obs_data_t *settings)
|
||||
obs_property_t *list,
|
||||
obs_data_t *settings)
|
||||
{
|
||||
const char *name = obs_data_get_string(settings, DEVICE_NAME);
|
||||
const char *hash = obs_data_get_string(settings, DEVICE_HASH);
|
||||
|
|
@ -193,13 +195,13 @@ static bool decklink_output_device_changed(obs_properties_t *props,
|
|||
obs_property_list_item_disable(modeList, 0, true);
|
||||
obs_property_list_item_disable(keyerList, 0, true);
|
||||
} else {
|
||||
const std::vector<DeckLinkDeviceMode*> &modes =
|
||||
device->GetOutputModes();
|
||||
const std::vector<DeckLinkDeviceMode *> &modes =
|
||||
device->GetOutputModes();
|
||||
|
||||
for (DeckLinkDeviceMode *mode : modes) {
|
||||
obs_property_list_add_int(modeList,
|
||||
mode->GetName().c_str(),
|
||||
mode->GetId());
|
||||
mode->GetName().c_str(),
|
||||
mode->GetId());
|
||||
}
|
||||
|
||||
obs_property_list_add_int(keyerList, "Disabled", 0);
|
||||
|
|
@ -222,22 +224,26 @@ static obs_properties_t *decklink_output_properties(void *unused)
|
|||
obs_properties_t *props = obs_properties_create();
|
||||
|
||||
obs_property_t *list = obs_properties_add_list(props, DEVICE_HASH,
|
||||
TEXT_DEVICE, OBS_COMBO_TYPE_LIST, OBS_COMBO_FORMAT_STRING);
|
||||
obs_property_set_modified_callback(list, decklink_output_device_changed);
|
||||
TEXT_DEVICE,
|
||||
OBS_COMBO_TYPE_LIST,
|
||||
OBS_COMBO_FORMAT_STRING);
|
||||
obs_property_set_modified_callback(list,
|
||||
decklink_output_device_changed);
|
||||
|
||||
fill_out_devices(list);
|
||||
|
||||
obs_properties_add_list(props,
|
||||
MODE_ID, TEXT_MODE, OBS_COMBO_TYPE_LIST, OBS_COMBO_FORMAT_INT);
|
||||
obs_properties_add_list(props, MODE_ID, TEXT_MODE, OBS_COMBO_TYPE_LIST,
|
||||
OBS_COMBO_FORMAT_INT);
|
||||
|
||||
obs_properties_add_bool(props, AUTO_START, TEXT_AUTO_START);
|
||||
|
||||
obs_properties_add_list(props, KEYER, TEXT_ENABLE_KEYER, OBS_COMBO_TYPE_LIST, OBS_COMBO_FORMAT_INT);
|
||||
obs_properties_add_list(props, KEYER, TEXT_ENABLE_KEYER,
|
||||
OBS_COMBO_TYPE_LIST, OBS_COMBO_FORMAT_INT);
|
||||
|
||||
return props;
|
||||
}
|
||||
|
||||
static const char *decklink_output_get_name(void*)
|
||||
static const char *decklink_output_get_name(void *)
|
||||
{
|
||||
return obs_module_text("BlackmagicDevice");
|
||||
}
|
||||
|
|
@ -246,17 +252,17 @@ struct obs_output_info create_decklink_output_info()
|
|||
{
|
||||
struct obs_output_info decklink_output_info = {};
|
||||
|
||||
decklink_output_info.id = "decklink_output";
|
||||
decklink_output_info.flags = OBS_OUTPUT_AV;
|
||||
decklink_output_info.get_name = decklink_output_get_name;
|
||||
decklink_output_info.create = decklink_output_create;
|
||||
decklink_output_info.destroy = decklink_output_destroy;
|
||||
decklink_output_info.start = decklink_output_start;
|
||||
decklink_output_info.stop = decklink_output_stop;
|
||||
decklink_output_info.id = "decklink_output";
|
||||
decklink_output_info.flags = OBS_OUTPUT_AV;
|
||||
decklink_output_info.get_name = decklink_output_get_name;
|
||||
decklink_output_info.create = decklink_output_create;
|
||||
decklink_output_info.destroy = decklink_output_destroy;
|
||||
decklink_output_info.start = decklink_output_start;
|
||||
decklink_output_info.stop = decklink_output_stop;
|
||||
decklink_output_info.get_properties = decklink_output_properties;
|
||||
decklink_output_info.raw_video = decklink_output_raw_video;
|
||||
decklink_output_info.raw_audio = decklink_output_raw_audio;
|
||||
decklink_output_info.update = decklink_output_update;
|
||||
decklink_output_info.raw_video = decklink_output_raw_video;
|
||||
decklink_output_info.raw_audio = decklink_output_raw_audio;
|
||||
decklink_output_info.update = decklink_output_update;
|
||||
|
||||
return decklink_output_info;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,7 +15,8 @@ static void decklink_enable_buffering(DeckLinkInput *decklink, bool enabled)
|
|||
decklink->buffering = enabled;
|
||||
}
|
||||
|
||||
static void decklink_deactivate_when_not_showing(DeckLinkInput *decklink, bool dwns)
|
||||
static void decklink_deactivate_when_not_showing(DeckLinkInput *decklink,
|
||||
bool dwns)
|
||||
{
|
||||
decklink->dwns = dwns;
|
||||
}
|
||||
|
|
@ -26,7 +27,7 @@ static void *decklink_create(obs_data_t *settings, obs_source_t *source)
|
|||
|
||||
obs_source_set_async_decoupled(source, true);
|
||||
decklink_enable_buffering(decklink,
|
||||
obs_data_get_bool(settings, BUFFERING));
|
||||
obs_data_get_bool(settings, BUFFERING));
|
||||
|
||||
obs_source_update(source, settings);
|
||||
return decklink;
|
||||
|
|
@ -43,16 +44,18 @@ static void decklink_update(void *data, obs_data_t *settings)
|
|||
DeckLinkInput *decklink = (DeckLinkInput *)data;
|
||||
const char *hash = obs_data_get_string(settings, DEVICE_HASH);
|
||||
long long id = obs_data_get_int(settings, MODE_ID);
|
||||
BMDVideoConnection videoConnection = (BMDVideoConnection) obs_data_get_int(settings,
|
||||
VIDEO_CONNECTION);
|
||||
BMDAudioConnection audioConnection = (BMDAudioConnection) obs_data_get_int(settings,
|
||||
AUDIO_CONNECTION);
|
||||
BMDPixelFormat pixelFormat = (BMDPixelFormat)obs_data_get_int(settings,
|
||||
PIXEL_FORMAT);
|
||||
video_colorspace colorSpace = (video_colorspace)obs_data_get_int(settings,
|
||||
COLOR_SPACE);
|
||||
video_range_type colorRange = (video_range_type)obs_data_get_int(settings,
|
||||
COLOR_RANGE);
|
||||
BMDVideoConnection videoConnection =
|
||||
(BMDVideoConnection)obs_data_get_int(settings,
|
||||
VIDEO_CONNECTION);
|
||||
BMDAudioConnection audioConnection =
|
||||
(BMDAudioConnection)obs_data_get_int(settings,
|
||||
AUDIO_CONNECTION);
|
||||
BMDPixelFormat pixelFormat =
|
||||
(BMDPixelFormat)obs_data_get_int(settings, PIXEL_FORMAT);
|
||||
video_colorspace colorSpace =
|
||||
(video_colorspace)obs_data_get_int(settings, COLOR_SPACE);
|
||||
video_range_type colorRange =
|
||||
(video_range_type)obs_data_get_int(settings, COLOR_RANGE);
|
||||
int chFmtInt = (int)obs_data_get_int(settings, CHANNEL_FORMAT);
|
||||
|
||||
if (chFmtInt == 7)
|
||||
|
|
@ -63,10 +66,10 @@ static void decklink_update(void *data, obs_data_t *settings)
|
|||
speaker_layout channelFormat = (speaker_layout)chFmtInt;
|
||||
|
||||
decklink_enable_buffering(decklink,
|
||||
obs_data_get_bool(settings, BUFFERING));
|
||||
obs_data_get_bool(settings, BUFFERING));
|
||||
|
||||
decklink_deactivate_when_not_showing(decklink,
|
||||
obs_data_get_bool(settings, DEACTIVATE_WNS));
|
||||
decklink_deactivate_when_not_showing(
|
||||
decklink, obs_data_get_bool(settings, DEACTIVATE_WNS));
|
||||
|
||||
ComPtr<DeckLinkDevice> device;
|
||||
device.Set(deviceEnum->FindByHash(hash));
|
||||
|
|
@ -88,8 +91,9 @@ static void decklink_show(void *data)
|
|||
if (decklink->dwns && showing && !decklink->Capturing()) {
|
||||
ComPtr<DeckLinkDevice> device;
|
||||
device.Set(deviceEnum->FindByHash(decklink->hash.c_str()));
|
||||
decklink->Activate(device, decklink->id, decklink->videoConnection,
|
||||
decklink->audioConnection);
|
||||
decklink->Activate(device, decklink->id,
|
||||
decklink->videoConnection,
|
||||
decklink->audioConnection);
|
||||
}
|
||||
}
|
||||
static void decklink_hide(void *data)
|
||||
|
|
@ -111,13 +115,13 @@ static void decklink_get_defaults(obs_data_t *settings)
|
|||
obs_data_set_default_bool(settings, SWAP, false);
|
||||
}
|
||||
|
||||
static const char *decklink_get_name(void*)
|
||||
static const char *decklink_get_name(void *)
|
||||
{
|
||||
return obs_module_text("BlackmagicDevice");
|
||||
}
|
||||
|
||||
static bool decklink_device_changed(obs_properties_t *props,
|
||||
obs_property_t *list, obs_data_t *settings)
|
||||
obs_property_t *list, obs_data_t *settings)
|
||||
{
|
||||
const char *name = obs_data_get_string(settings, DEVICE_NAME);
|
||||
const char *hash = obs_data_get_string(settings, DEVICE_HASH);
|
||||
|
|
@ -140,10 +144,10 @@ static bool decklink_device_changed(obs_properties_t *props,
|
|||
obs_property_list_item_disable(list, 0, true);
|
||||
}
|
||||
|
||||
obs_property_t *videoConnectionList = obs_properties_get(props,
|
||||
VIDEO_CONNECTION);
|
||||
obs_property_t *audioConnectionList = obs_properties_get(props,
|
||||
AUDIO_CONNECTION);
|
||||
obs_property_t *videoConnectionList =
|
||||
obs_properties_get(props, VIDEO_CONNECTION);
|
||||
obs_property_t *audioConnectionList =
|
||||
obs_properties_get(props, AUDIO_CONNECTION);
|
||||
obs_property_t *modeList = obs_properties_get(props, MODE_ID);
|
||||
obs_property_t *channelList = obs_properties_get(props, CHANNEL_FORMAT);
|
||||
|
||||
|
|
@ -154,9 +158,9 @@ static bool decklink_device_changed(obs_properties_t *props,
|
|||
|
||||
obs_property_list_clear(channelList);
|
||||
obs_property_list_add_int(channelList, TEXT_CHANNEL_FORMAT_NONE,
|
||||
SPEAKERS_UNKNOWN);
|
||||
SPEAKERS_UNKNOWN);
|
||||
obs_property_list_add_int(channelList, TEXT_CHANNEL_FORMAT_2_0CH,
|
||||
SPEAKERS_STEREO);
|
||||
SPEAKERS_STEREO);
|
||||
|
||||
ComPtr<DeckLinkDevice> device;
|
||||
device.Set(deviceEnum->FindByHash(hash));
|
||||
|
|
@ -168,60 +172,75 @@ static bool decklink_device_changed(obs_properties_t *props,
|
|||
obs_property_list_item_disable(modeList, 0, true);
|
||||
} else {
|
||||
const BMDVideoConnection BMDVideoConnections[] = {
|
||||
bmdVideoConnectionSDI, bmdVideoConnectionHDMI,
|
||||
bmdVideoConnectionOpticalSDI, bmdVideoConnectionComponent,
|
||||
bmdVideoConnectionComposite, bmdVideoConnectionSVideo
|
||||
};
|
||||
bmdVideoConnectionSDI,
|
||||
bmdVideoConnectionHDMI,
|
||||
bmdVideoConnectionOpticalSDI,
|
||||
bmdVideoConnectionComponent,
|
||||
bmdVideoConnectionComposite,
|
||||
bmdVideoConnectionSVideo};
|
||||
|
||||
for (BMDVideoConnection conn : BMDVideoConnections) {
|
||||
if ((device->GetVideoInputConnections() & conn) == conn) {
|
||||
obs_property_list_add_int(videoConnectionList,
|
||||
bmd_video_connection_to_name(conn), conn);
|
||||
if ((device->GetVideoInputConnections() & conn) ==
|
||||
conn) {
|
||||
obs_property_list_add_int(
|
||||
videoConnectionList,
|
||||
bmd_video_connection_to_name(conn),
|
||||
conn);
|
||||
}
|
||||
}
|
||||
|
||||
const BMDAudioConnection BMDAudioConnections[] = {
|
||||
bmdAudioConnectionEmbedded, bmdAudioConnectionAESEBU,
|
||||
bmdAudioConnectionAnalog, bmdAudioConnectionAnalogXLR,
|
||||
bmdAudioConnectionAnalogRCA, bmdAudioConnectionMicrophone,
|
||||
bmdAudioConnectionHeadphones
|
||||
};
|
||||
bmdAudioConnectionEmbedded,
|
||||
bmdAudioConnectionAESEBU,
|
||||
bmdAudioConnectionAnalog,
|
||||
bmdAudioConnectionAnalogXLR,
|
||||
bmdAudioConnectionAnalogRCA,
|
||||
bmdAudioConnectionMicrophone,
|
||||
bmdAudioConnectionHeadphones};
|
||||
|
||||
for (BMDAudioConnection conn : BMDAudioConnections) {
|
||||
if ((device->GetAudioInputConnections() & conn) == conn) {
|
||||
obs_property_list_add_int(audioConnectionList,
|
||||
bmd_audio_connection_to_name(conn), conn);
|
||||
if ((device->GetAudioInputConnections() & conn) ==
|
||||
conn) {
|
||||
obs_property_list_add_int(
|
||||
audioConnectionList,
|
||||
bmd_audio_connection_to_name(conn),
|
||||
conn);
|
||||
}
|
||||
}
|
||||
|
||||
const std::vector<DeckLinkDeviceMode*> &modes =
|
||||
device->GetInputModes();
|
||||
const std::vector<DeckLinkDeviceMode *> &modes =
|
||||
device->GetInputModes();
|
||||
|
||||
for (DeckLinkDeviceMode *mode : modes) {
|
||||
obs_property_list_add_int(modeList,
|
||||
mode->GetName().c_str(),
|
||||
mode->GetId());
|
||||
mode->GetName().c_str(),
|
||||
mode->GetId());
|
||||
}
|
||||
|
||||
if (device->GetMaxChannel() >= 8) {
|
||||
obs_property_list_add_int(channelList,
|
||||
TEXT_CHANNEL_FORMAT_2_1CH, SPEAKERS_2POINT1);
|
||||
TEXT_CHANNEL_FORMAT_2_1CH,
|
||||
SPEAKERS_2POINT1);
|
||||
obs_property_list_add_int(channelList,
|
||||
TEXT_CHANNEL_FORMAT_4_0CH, SPEAKERS_4POINT0);
|
||||
TEXT_CHANNEL_FORMAT_4_0CH,
|
||||
SPEAKERS_4POINT0);
|
||||
obs_property_list_add_int(channelList,
|
||||
TEXT_CHANNEL_FORMAT_4_1CH, SPEAKERS_4POINT1);
|
||||
TEXT_CHANNEL_FORMAT_4_1CH,
|
||||
SPEAKERS_4POINT1);
|
||||
obs_property_list_add_int(channelList,
|
||||
TEXT_CHANNEL_FORMAT_5_1CH, SPEAKERS_5POINT1);
|
||||
TEXT_CHANNEL_FORMAT_5_1CH,
|
||||
SPEAKERS_5POINT1);
|
||||
obs_property_list_add_int(channelList,
|
||||
TEXT_CHANNEL_FORMAT_7_1CH, SPEAKERS_7POINT1);
|
||||
TEXT_CHANNEL_FORMAT_7_1CH,
|
||||
SPEAKERS_7POINT1);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool mode_id_changed(obs_properties_t *props,
|
||||
obs_property_t *list, obs_data_t *settings)
|
||||
static bool mode_id_changed(obs_properties_t *props, obs_property_t *list,
|
||||
obs_data_t *settings)
|
||||
{
|
||||
long long id = obs_data_get_int(settings, MODE_ID);
|
||||
|
||||
|
|
@ -236,56 +255,65 @@ static obs_properties_t *decklink_get_properties(void *data)
|
|||
obs_properties_t *props = obs_properties_create();
|
||||
|
||||
obs_property_t *list = obs_properties_add_list(props, DEVICE_HASH,
|
||||
TEXT_DEVICE, OBS_COMBO_TYPE_LIST, OBS_COMBO_FORMAT_STRING);
|
||||
TEXT_DEVICE,
|
||||
OBS_COMBO_TYPE_LIST,
|
||||
OBS_COMBO_FORMAT_STRING);
|
||||
obs_property_set_modified_callback(list, decklink_device_changed);
|
||||
|
||||
fill_out_devices(list);
|
||||
|
||||
obs_properties_add_list(props, VIDEO_CONNECTION, TEXT_VIDEO_CONNECTION,
|
||||
OBS_COMBO_TYPE_LIST, OBS_COMBO_FORMAT_INT);
|
||||
OBS_COMBO_TYPE_LIST, OBS_COMBO_FORMAT_INT);
|
||||
obs_properties_add_list(props, AUDIO_CONNECTION, TEXT_AUDIO_CONNECTION,
|
||||
OBS_COMBO_TYPE_LIST, OBS_COMBO_FORMAT_INT);
|
||||
OBS_COMBO_TYPE_LIST, OBS_COMBO_FORMAT_INT);
|
||||
|
||||
list = obs_properties_add_list(props, MODE_ID, TEXT_MODE,
|
||||
OBS_COMBO_TYPE_LIST, OBS_COMBO_FORMAT_INT);
|
||||
OBS_COMBO_TYPE_LIST,
|
||||
OBS_COMBO_FORMAT_INT);
|
||||
obs_property_set_modified_callback(list, mode_id_changed);
|
||||
|
||||
list = obs_properties_add_list(props, PIXEL_FORMAT,
|
||||
TEXT_PIXEL_FORMAT, OBS_COMBO_TYPE_LIST,
|
||||
OBS_COMBO_FORMAT_INT);
|
||||
list = obs_properties_add_list(props, PIXEL_FORMAT, TEXT_PIXEL_FORMAT,
|
||||
OBS_COMBO_TYPE_LIST,
|
||||
OBS_COMBO_FORMAT_INT);
|
||||
|
||||
obs_property_list_add_int(list, "8-bit YUV", bmdFormat8BitYUV);
|
||||
obs_property_list_add_int(list, "8-bit BGRA", bmdFormat8BitBGRA);
|
||||
|
||||
list = obs_properties_add_list(props, COLOR_SPACE, TEXT_COLOR_SPACE,
|
||||
OBS_COMBO_TYPE_LIST, OBS_COMBO_FORMAT_INT);
|
||||
obs_property_list_add_int(list, TEXT_COLOR_SPACE_DEFAULT, VIDEO_CS_DEFAULT);
|
||||
OBS_COMBO_TYPE_LIST,
|
||||
OBS_COMBO_FORMAT_INT);
|
||||
obs_property_list_add_int(list, TEXT_COLOR_SPACE_DEFAULT,
|
||||
VIDEO_CS_DEFAULT);
|
||||
obs_property_list_add_int(list, "BT.601", VIDEO_CS_601);
|
||||
obs_property_list_add_int(list, "BT.709", VIDEO_CS_709);
|
||||
|
||||
list = obs_properties_add_list(props, COLOR_RANGE, TEXT_COLOR_RANGE,
|
||||
OBS_COMBO_TYPE_LIST, OBS_COMBO_FORMAT_INT);
|
||||
obs_property_list_add_int(list, TEXT_COLOR_RANGE_DEFAULT, VIDEO_RANGE_DEFAULT);
|
||||
obs_property_list_add_int(list, TEXT_COLOR_RANGE_PARTIAL, VIDEO_RANGE_PARTIAL);
|
||||
obs_property_list_add_int(list, TEXT_COLOR_RANGE_FULL, VIDEO_RANGE_FULL);
|
||||
OBS_COMBO_TYPE_LIST,
|
||||
OBS_COMBO_FORMAT_INT);
|
||||
obs_property_list_add_int(list, TEXT_COLOR_RANGE_DEFAULT,
|
||||
VIDEO_RANGE_DEFAULT);
|
||||
obs_property_list_add_int(list, TEXT_COLOR_RANGE_PARTIAL,
|
||||
VIDEO_RANGE_PARTIAL);
|
||||
obs_property_list_add_int(list, TEXT_COLOR_RANGE_FULL,
|
||||
VIDEO_RANGE_FULL);
|
||||
|
||||
list = obs_properties_add_list(props, CHANNEL_FORMAT,
|
||||
TEXT_CHANNEL_FORMAT, OBS_COMBO_TYPE_LIST,
|
||||
OBS_COMBO_FORMAT_INT);
|
||||
TEXT_CHANNEL_FORMAT, OBS_COMBO_TYPE_LIST,
|
||||
OBS_COMBO_FORMAT_INT);
|
||||
obs_property_list_add_int(list, TEXT_CHANNEL_FORMAT_NONE,
|
||||
SPEAKERS_UNKNOWN);
|
||||
SPEAKERS_UNKNOWN);
|
||||
obs_property_list_add_int(list, TEXT_CHANNEL_FORMAT_2_0CH,
|
||||
SPEAKERS_STEREO);
|
||||
SPEAKERS_STEREO);
|
||||
obs_property_list_add_int(list, TEXT_CHANNEL_FORMAT_2_1CH,
|
||||
SPEAKERS_2POINT1);
|
||||
SPEAKERS_2POINT1);
|
||||
obs_property_list_add_int(list, TEXT_CHANNEL_FORMAT_4_0CH,
|
||||
SPEAKERS_4POINT0);
|
||||
SPEAKERS_4POINT0);
|
||||
obs_property_list_add_int(list, TEXT_CHANNEL_FORMAT_4_1CH,
|
||||
SPEAKERS_4POINT1);
|
||||
SPEAKERS_4POINT1);
|
||||
obs_property_list_add_int(list, TEXT_CHANNEL_FORMAT_5_1CH,
|
||||
SPEAKERS_5POINT1);
|
||||
SPEAKERS_5POINT1);
|
||||
obs_property_list_add_int(list, TEXT_CHANNEL_FORMAT_7_1CH,
|
||||
SPEAKERS_7POINT1);
|
||||
SPEAKERS_7POINT1);
|
||||
|
||||
obs_property_t *swap = obs_properties_add_bool(props, SWAP, TEXT_SWAP);
|
||||
obs_property_set_long_description(swap, TEXT_SWAP_TOOLTIP);
|
||||
|
|
@ -298,21 +326,22 @@ static obs_properties_t *decklink_get_properties(void *data)
|
|||
return props;
|
||||
}
|
||||
|
||||
|
||||
struct obs_source_info create_decklink_source_info()
|
||||
{
|
||||
struct obs_source_info decklink_source_info = {};
|
||||
decklink_source_info.id = "decklink-input";
|
||||
decklink_source_info.type = OBS_SOURCE_TYPE_INPUT;
|
||||
decklink_source_info.output_flags = OBS_SOURCE_ASYNC_VIDEO | OBS_SOURCE_AUDIO | OBS_SOURCE_DO_NOT_DUPLICATE;
|
||||
decklink_source_info.create = decklink_create;
|
||||
decklink_source_info.destroy = decklink_destroy;
|
||||
decklink_source_info.get_defaults = decklink_get_defaults;
|
||||
decklink_source_info.get_name = decklink_get_name;
|
||||
decklink_source_info.id = "decklink-input";
|
||||
decklink_source_info.type = OBS_SOURCE_TYPE_INPUT;
|
||||
decklink_source_info.output_flags = OBS_SOURCE_ASYNC_VIDEO |
|
||||
OBS_SOURCE_AUDIO |
|
||||
OBS_SOURCE_DO_NOT_DUPLICATE;
|
||||
decklink_source_info.create = decklink_create;
|
||||
decklink_source_info.destroy = decklink_destroy;
|
||||
decklink_source_info.get_defaults = decklink_get_defaults;
|
||||
decklink_source_info.get_name = decklink_get_name;
|
||||
decklink_source_info.get_properties = decklink_get_properties;
|
||||
decklink_source_info.update = decklink_update;
|
||||
decklink_source_info.show = decklink_show;
|
||||
decklink_source_info.hide = decklink_hide;
|
||||
decklink_source_info.update = decklink_update;
|
||||
decklink_source_info.show = decklink_show;
|
||||
decklink_source_info.hide = decklink_hide;
|
||||
|
||||
return decklink_source_info;
|
||||
}
|
||||
|
|
|
|||
3
plugins/decklink/linux/decklink-sdk/.clang-format
Normal file
3
plugins/decklink/linux/decklink-sdk/.clang-format
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
Language: Cpp
|
||||
SortIncludes: false
|
||||
DisableFormat: true
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
#include "../platform.hpp"
|
||||
|
||||
bool DeckLinkStringToStdString(decklink_string_t input, std::string& output)
|
||||
bool DeckLinkStringToStdString(decklink_string_t input, std::string &output)
|
||||
{
|
||||
if (input == nullptr)
|
||||
return false;
|
||||
|
|
|
|||
3
plugins/decklink/mac/decklink-sdk/.clang-format
Normal file
3
plugins/decklink/mac/decklink-sdk/.clang-format
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
Language: Cpp
|
||||
SortIncludes: false
|
||||
DisableFormat: true
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
#include "../platform.hpp"
|
||||
#include <util/apple/cfstring-utils.h>
|
||||
|
||||
bool DeckLinkStringToStdString(decklink_string_t input, std::string& output)
|
||||
bool DeckLinkStringToStdString(decklink_string_t input, std::string &output)
|
||||
{
|
||||
const CFStringRef string = static_cast<CFStringRef>(input);
|
||||
|
||||
|
|
|
|||
|
|
@ -24,4 +24,4 @@ typedef const char *decklink_string_t;
|
|||
|
||||
#include <string>
|
||||
|
||||
bool DeckLinkStringToStdString(decklink_string_t input, std::string& output);
|
||||
bool DeckLinkStringToStdString(decklink_string_t input, std::string &output);
|
||||
|
|
|
|||
|
|
@ -3,41 +3,41 @@
|
|||
const char *bmd_video_connection_to_name(BMDVideoConnection connection)
|
||||
{
|
||||
switch (connection) {
|
||||
case bmdVideoConnectionSDI:
|
||||
return "SDI";
|
||||
case bmdVideoConnectionHDMI:
|
||||
return "HDMI";
|
||||
case bmdVideoConnectionOpticalSDI:
|
||||
return "Optical SDI";
|
||||
case bmdVideoConnectionComponent:
|
||||
return "Component";
|
||||
case bmdVideoConnectionComposite:
|
||||
return "Composite";
|
||||
case bmdVideoConnectionSVideo:
|
||||
return "S-Video";
|
||||
default:
|
||||
return "Unknown";
|
||||
case bmdVideoConnectionSDI:
|
||||
return "SDI";
|
||||
case bmdVideoConnectionHDMI:
|
||||
return "HDMI";
|
||||
case bmdVideoConnectionOpticalSDI:
|
||||
return "Optical SDI";
|
||||
case bmdVideoConnectionComponent:
|
||||
return "Component";
|
||||
case bmdVideoConnectionComposite:
|
||||
return "Composite";
|
||||
case bmdVideoConnectionSVideo:
|
||||
return "S-Video";
|
||||
default:
|
||||
return "Unknown";
|
||||
}
|
||||
}
|
||||
|
||||
const char *bmd_audio_connection_to_name(BMDAudioConnection connection)
|
||||
{
|
||||
switch (connection) {
|
||||
case bmdAudioConnectionEmbedded:
|
||||
return "Embedded";
|
||||
case bmdAudioConnectionAESEBU:
|
||||
return "AES/EBU";
|
||||
case bmdAudioConnectionAnalog:
|
||||
return "Analog";
|
||||
case bmdAudioConnectionAnalogXLR:
|
||||
return "Analog XLR";
|
||||
case bmdAudioConnectionAnalogRCA:
|
||||
return "Analog RCA";
|
||||
case bmdAudioConnectionMicrophone:
|
||||
return "Microphone";
|
||||
case bmdAudioConnectionHeadphones:
|
||||
return "Headphones";
|
||||
default:
|
||||
return "Unknown";
|
||||
case bmdAudioConnectionEmbedded:
|
||||
return "Embedded";
|
||||
case bmdAudioConnectionAESEBU:
|
||||
return "AES/EBU";
|
||||
case bmdAudioConnectionAnalog:
|
||||
return "Analog";
|
||||
case bmdAudioConnectionAnalogXLR:
|
||||
return "Analog XLR";
|
||||
case bmdAudioConnectionAnalogRCA:
|
||||
return "Analog RCA";
|
||||
case bmdAudioConnectionMicrophone:
|
||||
return "Microphone";
|
||||
case bmdAudioConnectionHeadphones:
|
||||
return "Headphones";
|
||||
default:
|
||||
return "Unknown";
|
||||
}
|
||||
}
|
||||
|
|
@ -5,13 +5,13 @@
|
|||
IDeckLinkDiscovery *CreateDeckLinkDiscoveryInstance(void)
|
||||
{
|
||||
IDeckLinkDiscovery *instance;
|
||||
const HRESULT result = CoCreateInstance(CLSID_CDeckLinkDiscovery,
|
||||
nullptr, CLSCTX_ALL, IID_IDeckLinkDiscovery,
|
||||
(void **)&instance);
|
||||
const HRESULT result =
|
||||
CoCreateInstance(CLSID_CDeckLinkDiscovery, nullptr, CLSCTX_ALL,
|
||||
IID_IDeckLinkDiscovery, (void **)&instance);
|
||||
return result == S_OK ? instance : nullptr;
|
||||
}
|
||||
|
||||
bool DeckLinkStringToStdString(decklink_string_t input, std::string& output)
|
||||
bool DeckLinkStringToStdString(decklink_string_t input, std::string &output)
|
||||
{
|
||||
if (input == nullptr)
|
||||
return false;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue