New upstream version 24.0.1+dfsg1

This commit is contained in:
Sebastian Ramacher 2019-09-22 23:19:10 +02:00
parent b14f9eae6d
commit 5a730d6ec3
842 changed files with 42245 additions and 33385 deletions

View file

@ -1,6 +1,6 @@
CoreAudioAAC="CoreAudio AAC Kodierer"
Bitrate="Bitrate"
AllowHEAAC="Erlaube HE-AAC"
AllowHEAAC="Erlaube HEAAC"
OutputSamplerate="Ausgabeabtastrate"
UseInputSampleRate="Verwenden Sie Eingabe (OBS) Abtastrate (kann nicht unterstützte Bitraten auflisten)"

View file

@ -1,4 +1,6 @@
CoreAudioAAC="Codificador CoreAudio AAC"
Bitrate="Velocidade de bits"
CoreAudioAAC="Codificador AAC de CoreAudio"
Bitrate="Taxa de bits"
AllowHEAAC="Permitir HE-AAC"
OutputSamplerate="Taxa de mostra de saída"
UseInputSampleRate="Utilizar a taxa de mostra de entrada do OBS (pode listar as taxas de bits que non son compatíbeis)"

View file

@ -0,0 +1,6 @@
CoreAudioAAC="Kodirnik AAC CoreAudio"
Bitrate="Bitna hitrost"
AllowHEAAC="Omogoči HE-AAC"
OutputSamplerate="Izhodna hitrost vzorčenja"
UseInputSampleRate="Uporabo vhodno hitrost vzorčenja (OBS) (lahko so prikazane nepodprte bitne hitrosti)"

File diff suppressed because it is too large Load diff

View file

@ -5,18 +5,17 @@
#include <util/dstr.h>
typedef unsigned long UInt32;
typedef signed long SInt32;
typedef signed long long SInt64;
typedef double Float64;
typedef unsigned long UInt32;
typedef signed long SInt32;
typedef signed long long SInt64;
typedef double Float64;
typedef SInt32 OSStatus;
typedef unsigned char Boolean;
typedef SInt32 OSStatus;
typedef unsigned char Boolean;
typedef UInt32 AudioFormatPropertyID;
enum {
kVariableLengthArray = 1
enum { kVariableLengthArray = 1,
};
struct OpaqueAudioConverter;
@ -30,344 +29,305 @@ struct AudioValueRange {
typedef struct AudioValueRange AudioValueRange;
struct AudioBuffer {
UInt32 mNumberChannels;
UInt32 mDataByteSize;
void* mData;
UInt32 mNumberChannels;
UInt32 mDataByteSize;
void *mData;
};
typedef struct AudioBuffer AudioBuffer;
struct AudioBufferList {
UInt32 mNumberBuffers;
UInt32 mNumberBuffers;
AudioBuffer mBuffers[kVariableLengthArray];
};
typedef struct AudioBufferList AudioBufferList;
struct AudioStreamBasicDescription {
Float64 mSampleRate;
UInt32 mFormatID;
UInt32 mFormatFlags;
UInt32 mBytesPerPacket;
UInt32 mFramesPerPacket;
UInt32 mBytesPerFrame;
UInt32 mChannelsPerFrame;
UInt32 mBitsPerChannel;
UInt32 mReserved;
UInt32 mFormatID;
UInt32 mFormatFlags;
UInt32 mBytesPerPacket;
UInt32 mFramesPerPacket;
UInt32 mBytesPerFrame;
UInt32 mChannelsPerFrame;
UInt32 mBitsPerChannel;
UInt32 mReserved;
};
typedef struct AudioStreamBasicDescription AudioStreamBasicDescription;
struct AudioStreamPacketDescription {
SInt64 mStartOffset;
UInt32 mVariableFramesInPacket;
UInt32 mDataByteSize;
SInt64 mStartOffset;
UInt32 mVariableFramesInPacket;
UInt32 mDataByteSize;
};
typedef struct AudioStreamPacketDescription AudioStreamPacketDescription;
typedef OSStatus (*AudioConverterComplexInputDataProc) (
AudioConverterRef inAudioConverter,
UInt32 *ioNumberDataPackets,
AudioBufferList *ioData,
AudioStreamPacketDescription **outDataPacketDescription,
void *inUserData
);
typedef OSStatus (*AudioConverterComplexInputDataProc)(
AudioConverterRef inAudioConverter, UInt32 *ioNumberDataPackets,
AudioBufferList *ioData,
AudioStreamPacketDescription **outDataPacketDescription,
void *inUserData);
enum {
kAudioCodecPropertyNameCFString = 'lnam',
kAudioCodecPropertyManufacturerCFString = 'lmak',
kAudioCodecPropertyFormatCFString = 'lfor',
//kAudioCodecPropertyHasVariablePacketByteSizes = 'vpk?',
kAudioCodecPropertySupportedInputFormats = 'ifm#',
kAudioCodecPropertySupportedOutputFormats = 'ofm#',
kAudioCodecPropertyAvailableInputSampleRates = 'aisr',
kAudioCodecPropertyAvailableOutputSampleRates = 'aosr',
kAudioCodecPropertyAvailableBitRateRange = 'abrt',
kAudioCodecPropertyMinimumNumberInputPackets = 'mnip',
kAudioCodecPropertyMinimumNumberOutputPackets = 'mnop',
kAudioCodecPropertyAvailableNumberChannels = 'cmnc',
kAudioCodecPropertyDoesSampleRateConversion = 'lmrc',
kAudioCodecPropertyAvailableInputChannelLayoutTags = 'aicl',
kAudioCodecPropertyAvailableOutputChannelLayoutTags = 'aocl',
kAudioCodecPropertyInputFormatsForOutputFormat = 'if4o',
kAudioCodecPropertyOutputFormatsForInputFormat = 'of4i',
kAudioCodecPropertyFormatInfo = 'acfi',
enum { kAudioCodecPropertyNameCFString = 'lnam',
kAudioCodecPropertyManufacturerCFString = 'lmak',
kAudioCodecPropertyFormatCFString = 'lfor',
//kAudioCodecPropertyHasVariablePacketByteSizes = 'vpk?',
kAudioCodecPropertySupportedInputFormats = 'ifm#',
kAudioCodecPropertySupportedOutputFormats = 'ofm#',
kAudioCodecPropertyAvailableInputSampleRates = 'aisr',
kAudioCodecPropertyAvailableOutputSampleRates = 'aosr',
kAudioCodecPropertyAvailableBitRateRange = 'abrt',
kAudioCodecPropertyMinimumNumberInputPackets = 'mnip',
kAudioCodecPropertyMinimumNumberOutputPackets = 'mnop',
kAudioCodecPropertyAvailableNumberChannels = 'cmnc',
kAudioCodecPropertyDoesSampleRateConversion = 'lmrc',
kAudioCodecPropertyAvailableInputChannelLayoutTags = 'aicl',
kAudioCodecPropertyAvailableOutputChannelLayoutTags = 'aocl',
kAudioCodecPropertyInputFormatsForOutputFormat = 'if4o',
kAudioCodecPropertyOutputFormatsForInputFormat = 'of4i',
kAudioCodecPropertyFormatInfo = 'acfi',
};
enum {
kAudioCodecPropertyInputBufferSize = 'tbuf',
kAudioCodecPropertyPacketFrameSize = 'pakf',
kAudioCodecPropertyMaximumPacketByteSize = 'pakb',
kAudioCodecPropertyCurrentInputFormat = 'ifmt',
kAudioCodecPropertyCurrentOutputFormat = 'ofmt',
kAudioCodecPropertyMagicCookie = 'kuki',
kAudioCodecPropertyUsedInputBufferSize = 'ubuf',
kAudioCodecPropertyIsInitialized = 'init',
kAudioCodecPropertyCurrentTargetBitRate = 'brat',
kAudioCodecPropertyCurrentInputSampleRate = 'cisr',
kAudioCodecPropertyCurrentOutputSampleRate = 'cosr',
kAudioCodecPropertyQualitySetting = 'srcq',
kAudioCodecPropertyApplicableBitRateRange = 'brta',
kAudioCodecPropertyApplicableInputSampleRates = 'isra',
kAudioCodecPropertyApplicableOutputSampleRates = 'osra',
kAudioCodecPropertyPaddedZeros = 'pad0',
kAudioCodecPropertyPrimeMethod = 'prmm',
kAudioCodecPropertyPrimeInfo = 'prim',
kAudioCodecPropertyCurrentInputChannelLayout = 'icl ',
kAudioCodecPropertyCurrentOutputChannelLayout = 'ocl ',
kAudioCodecPropertySettings = 'acs ',
kAudioCodecPropertyFormatList = 'acfl',
kAudioCodecPropertyBitRateControlMode = 'acbf',
kAudioCodecPropertySoundQualityForVBR = 'vbrq',
kAudioCodecPropertyMinimumDelayMode = 'mdel'
enum { kAudioCodecPropertyInputBufferSize = 'tbuf',
kAudioCodecPropertyPacketFrameSize = 'pakf',
kAudioCodecPropertyMaximumPacketByteSize = 'pakb',
kAudioCodecPropertyCurrentInputFormat = 'ifmt',
kAudioCodecPropertyCurrentOutputFormat = 'ofmt',
kAudioCodecPropertyMagicCookie = 'kuki',
kAudioCodecPropertyUsedInputBufferSize = 'ubuf',
kAudioCodecPropertyIsInitialized = 'init',
kAudioCodecPropertyCurrentTargetBitRate = 'brat',
kAudioCodecPropertyCurrentInputSampleRate = 'cisr',
kAudioCodecPropertyCurrentOutputSampleRate = 'cosr',
kAudioCodecPropertyQualitySetting = 'srcq',
kAudioCodecPropertyApplicableBitRateRange = 'brta',
kAudioCodecPropertyApplicableInputSampleRates = 'isra',
kAudioCodecPropertyApplicableOutputSampleRates = 'osra',
kAudioCodecPropertyPaddedZeros = 'pad0',
kAudioCodecPropertyPrimeMethod = 'prmm',
kAudioCodecPropertyPrimeInfo = 'prim',
kAudioCodecPropertyCurrentInputChannelLayout = 'icl ',
kAudioCodecPropertyCurrentOutputChannelLayout = 'ocl ',
kAudioCodecPropertySettings = 'acs ',
kAudioCodecPropertyFormatList = 'acfl',
kAudioCodecPropertyBitRateControlMode = 'acbf',
kAudioCodecPropertySoundQualityForVBR = 'vbrq',
kAudioCodecPropertyMinimumDelayMode = 'mdel' };
enum { kAudioCodecBitRateControlMode_Constant = 0,
kAudioCodecBitRateControlMode_LongTermAverage = 1,
kAudioCodecBitRateControlMode_VariableConstrained = 2,
kAudioCodecBitRateControlMode_Variable = 3,
};
enum {
kAudioCodecBitRateControlMode_Constant = 0,
kAudioCodecBitRateControlMode_LongTermAverage = 1,
kAudioCodecBitRateControlMode_VariableConstrained = 2,
kAudioCodecBitRateControlMode_Variable = 3,
enum { kAudioFormatLinearPCM = 'lpcm',
kAudioFormatAC3 = 'ac-3',
kAudioFormat60958AC3 = 'cac3',
kAudioFormatAppleIMA4 = 'ima4',
kAudioFormatMPEG4AAC = 'aac ',
kAudioFormatMPEG4CELP = 'celp',
kAudioFormatMPEG4HVXC = 'hvxc',
kAudioFormatMPEG4TwinVQ = 'twvq',
kAudioFormatMACE3 = 'MAC3',
kAudioFormatMACE6 = 'MAC6',
kAudioFormatULaw = 'ulaw',
kAudioFormatALaw = 'alaw',
kAudioFormatQDesign = 'QDMC',
kAudioFormatQDesign2 = 'QDM2',
kAudioFormatQUALCOMM = 'Qclp',
kAudioFormatMPEGLayer1 = '.mp1',
kAudioFormatMPEGLayer2 = '.mp2',
kAudioFormatMPEGLayer3 = '.mp3',
kAudioFormatTimeCode = 'time',
kAudioFormatMIDIStream = 'midi',
kAudioFormatParameterValueStream = 'apvs',
kAudioFormatAppleLossless = 'alac',
kAudioFormatMPEG4AAC_HE = 'aach',
kAudioFormatMPEG4AAC_LD = 'aacl',
kAudioFormatMPEG4AAC_ELD = 'aace',
kAudioFormatMPEG4AAC_ELD_SBR = 'aacf',
kAudioFormatMPEG4AAC_ELD_V2 = 'aacg',
kAudioFormatMPEG4AAC_HE_V2 = 'aacp',
kAudioFormatMPEG4AAC_Spatial = 'aacs',
kAudioFormatAMR = 'samr',
kAudioFormatAudible = 'AUDB',
kAudioFormatiLBC = 'ilbc',
kAudioFormatDVIIntelIMA = 0x6D730011,
kAudioFormatMicrosoftGSM = 0x6D730031,
kAudioFormatAES3 = 'aes3',
};
enum {
kAudioFormatLinearPCM = 'lpcm',
kAudioFormatAC3 = 'ac-3',
kAudioFormat60958AC3 = 'cac3',
kAudioFormatAppleIMA4 = 'ima4',
kAudioFormatMPEG4AAC = 'aac ',
kAudioFormatMPEG4CELP = 'celp',
kAudioFormatMPEG4HVXC = 'hvxc',
kAudioFormatMPEG4TwinVQ = 'twvq',
kAudioFormatMACE3 = 'MAC3',
kAudioFormatMACE6 = 'MAC6',
kAudioFormatULaw = 'ulaw',
kAudioFormatALaw = 'alaw',
kAudioFormatQDesign = 'QDMC',
kAudioFormatQDesign2 = 'QDM2',
kAudioFormatQUALCOMM = 'Qclp',
kAudioFormatMPEGLayer1 = '.mp1',
kAudioFormatMPEGLayer2 = '.mp2',
kAudioFormatMPEGLayer3 = '.mp3',
kAudioFormatTimeCode = 'time',
kAudioFormatMIDIStream = 'midi',
kAudioFormatParameterValueStream = 'apvs',
kAudioFormatAppleLossless = 'alac',
kAudioFormatMPEG4AAC_HE = 'aach',
kAudioFormatMPEG4AAC_LD = 'aacl',
kAudioFormatMPEG4AAC_ELD = 'aace',
kAudioFormatMPEG4AAC_ELD_SBR = 'aacf',
kAudioFormatMPEG4AAC_ELD_V2 = 'aacg',
kAudioFormatMPEG4AAC_HE_V2 = 'aacp',
kAudioFormatMPEG4AAC_Spatial = 'aacs',
kAudioFormatAMR = 'samr',
kAudioFormatAudible = 'AUDB',
kAudioFormatiLBC = 'ilbc',
kAudioFormatDVIIntelIMA = 0x6D730011,
kAudioFormatMicrosoftGSM = 0x6D730031,
kAudioFormatAES3 = 'aes3'
enum { kAudioFormatFlagIsFloat = (1L << 0),
kAudioFormatFlagIsBigEndian = (1L << 1),
kAudioFormatFlagIsSignedInteger = (1L << 2),
kAudioFormatFlagIsPacked = (1L << 3),
kAudioFormatFlagIsAlignedHigh = (1L << 4),
kAudioFormatFlagIsNonInterleaved = (1L << 5),
kAudioFormatFlagIsNonMixable = (1L << 6),
kAudioFormatFlagsAreAllClear = (1L << 31),
kLinearPCMFormatFlagIsFloat = kAudioFormatFlagIsFloat,
kLinearPCMFormatFlagIsBigEndian = kAudioFormatFlagIsBigEndian,
kLinearPCMFormatFlagIsSignedInteger = kAudioFormatFlagIsSignedInteger,
kLinearPCMFormatFlagIsPacked = kAudioFormatFlagIsPacked,
kLinearPCMFormatFlagIsAlignedHigh = kAudioFormatFlagIsAlignedHigh,
kLinearPCMFormatFlagIsNonInterleaved = kAudioFormatFlagIsNonInterleaved,
kLinearPCMFormatFlagIsNonMixable = kAudioFormatFlagIsNonMixable,
kLinearPCMFormatFlagsAreAllClear = kAudioFormatFlagsAreAllClear,
kAppleLosslessFormatFlag_16BitSourceData = 1,
kAppleLosslessFormatFlag_20BitSourceData = 2,
kAppleLosslessFormatFlag_24BitSourceData = 3,
kAppleLosslessFormatFlag_32BitSourceData = 4,
};
enum {
kAudioFormatFlagIsFloat = (1L << 0),
kAudioFormatFlagIsBigEndian = (1L << 1),
kAudioFormatFlagIsSignedInteger = (1L << 2),
kAudioFormatFlagIsPacked = (1L << 3),
kAudioFormatFlagIsAlignedHigh = (1L << 4),
kAudioFormatFlagIsNonInterleaved = (1L << 5),
kAudioFormatFlagIsNonMixable = (1L << 6),
kAudioFormatFlagsAreAllClear = (1L << 31),
kLinearPCMFormatFlagIsFloat =
kAudioFormatFlagIsFloat,
kLinearPCMFormatFlagIsBigEndian =
kAudioFormatFlagIsBigEndian,
kLinearPCMFormatFlagIsSignedInteger =
kAudioFormatFlagIsSignedInteger,
kLinearPCMFormatFlagIsPacked =
kAudioFormatFlagIsPacked,
kLinearPCMFormatFlagIsAlignedHigh =
kAudioFormatFlagIsAlignedHigh,
kLinearPCMFormatFlagIsNonInterleaved =
kAudioFormatFlagIsNonInterleaved,
kLinearPCMFormatFlagIsNonMixable =
kAudioFormatFlagIsNonMixable,
kLinearPCMFormatFlagsAreAllClear =
kAudioFormatFlagsAreAllClear,
kAppleLosslessFormatFlag_16BitSourceData = 1,
kAppleLosslessFormatFlag_20BitSourceData = 2,
kAppleLosslessFormatFlag_24BitSourceData = 3,
kAppleLosslessFormatFlag_32BitSourceData = 4
};
enum {
kAudioFormatFlagsNativeEndian = 0,
};
enum { kAudioFormatFlagsNativeEndian = 0 };
enum {
// AudioStreamBasicDescription structure properties
kAudioFormatProperty_FormatInfo = 'fmti',
kAudioFormatProperty_FormatName = 'fnam',
kAudioFormatProperty_EncodeFormatIDs = 'acof',
kAudioFormatProperty_DecodeFormatIDs = 'acif',
kAudioFormatProperty_FormatList = 'flst',
kAudioFormatProperty_ASBDFromESDS = 'essd',
kAudioFormatProperty_ChannelLayoutFromESDS = 'escl',
kAudioFormatProperty_OutputFormatList = 'ofls',
kAudioFormatProperty_Encoders = 'aven',
kAudioFormatProperty_Decoders = 'avde',
kAudioFormatProperty_FormatIsVBR = 'fvbr',
kAudioFormatProperty_FormatIsExternallyFramed = 'fexf',
kAudioFormatProperty_AvailableEncodeBitRates = 'aebr',
kAudioFormatProperty_AvailableEncodeSampleRates = 'aesr',
kAudioFormatProperty_FormatInfo = 'fmti',
kAudioFormatProperty_FormatName = 'fnam',
kAudioFormatProperty_EncodeFormatIDs = 'acof',
kAudioFormatProperty_DecodeFormatIDs = 'acif',
kAudioFormatProperty_FormatList = 'flst',
kAudioFormatProperty_ASBDFromESDS = 'essd',
kAudioFormatProperty_ChannelLayoutFromESDS = 'escl',
kAudioFormatProperty_OutputFormatList = 'ofls',
kAudioFormatProperty_Encoders = 'aven',
kAudioFormatProperty_Decoders = 'avde',
kAudioFormatProperty_FormatIsVBR = 'fvbr',
kAudioFormatProperty_FormatIsExternallyFramed = 'fexf',
kAudioFormatProperty_AvailableEncodeBitRates = 'aebr',
kAudioFormatProperty_AvailableEncodeSampleRates = 'aesr',
kAudioFormatProperty_AvailableEncodeChannelLayoutTags = 'aecl',
kAudioFormatProperty_AvailableEncodeNumberChannels = 'avnc',
kAudioFormatProperty_ASBDFromMPEGPacket = 'admp',
kAudioFormatProperty_AvailableEncodeNumberChannels = 'avnc',
kAudioFormatProperty_ASBDFromMPEGPacket = 'admp',
//
// AudioChannelLayout structure properties
kAudioFormatProperty_BitmapForLayoutTag = 'bmtg',
kAudioFormatProperty_MatrixMixMap = 'mmap',
kAudioFormatProperty_ChannelMap = 'chmp',
kAudioFormatProperty_NumberOfChannelsForLayout = 'nchm',
kAudioFormatProperty_ValidateChannelLayout = 'vacl',
kAudioFormatProperty_ChannelLayoutForTag = 'cmpl',
kAudioFormatProperty_TagForChannelLayout = 'cmpt',
kAudioFormatProperty_ChannelLayoutName = 'lonm',
kAudioFormatProperty_ChannelLayoutSimpleName = 'lsnm',
kAudioFormatProperty_ChannelLayoutForBitmap = 'cmpb',
kAudioFormatProperty_ChannelName = 'cnam',
kAudioFormatProperty_ChannelShortName = 'csnm',
kAudioFormatProperty_TagsForNumberOfChannels = 'tagc',
kAudioFormatProperty_PanningMatrix = 'panm',
kAudioFormatProperty_BalanceFade = 'balf',
kAudioFormatProperty_BitmapForLayoutTag = 'bmtg',
kAudioFormatProperty_MatrixMixMap = 'mmap',
kAudioFormatProperty_ChannelMap = 'chmp',
kAudioFormatProperty_NumberOfChannelsForLayout = 'nchm',
kAudioFormatProperty_ValidateChannelLayout = 'vacl',
kAudioFormatProperty_ChannelLayoutForTag = 'cmpl',
kAudioFormatProperty_TagForChannelLayout = 'cmpt',
kAudioFormatProperty_ChannelLayoutName = 'lonm',
kAudioFormatProperty_ChannelLayoutSimpleName = 'lsnm',
kAudioFormatProperty_ChannelLayoutForBitmap = 'cmpb',
kAudioFormatProperty_ChannelName = 'cnam',
kAudioFormatProperty_ChannelShortName = 'csnm',
kAudioFormatProperty_TagsForNumberOfChannels = 'tagc',
kAudioFormatProperty_PanningMatrix = 'panm',
kAudioFormatProperty_BalanceFade = 'balf',
//
// ID3 tag (MP3 metadata) properties
kAudioFormatProperty_ID3TagSize = 'id3s',
kAudioFormatProperty_ID3TagToDictionary = 'id3d'
kAudioFormatProperty_ID3TagSize = 'id3s',
kAudioFormatProperty_ID3TagToDictionary = 'id3d',
};
enum {
kAudioConverterPropertyMinimumInputBufferSize = 'mibs',
kAudioConverterPropertyMinimumOutputBufferSize = 'mobs',
kAudioConverterPropertyMaximumInputBufferSize = 'xibs',
kAudioConverterPropertyMaximumInputPacketSize = 'xips',
kAudioConverterPropertyMaximumOutputPacketSize = 'xops',
kAudioConverterPropertyCalculateInputBufferSize = 'cibs',
kAudioConverterPropertyCalculateOutputBufferSize = 'cobs',
kAudioConverterPropertyInputCodecParameters = 'icdp',
kAudioConverterPropertyOutputCodecParameters = 'ocdp',
kAudioConverterSampleRateConverterAlgorithm = 'srci',
kAudioConverterSampleRateConverterComplexity = 'srca',
kAudioConverterSampleRateConverterQuality = 'srcq',
kAudioConverterSampleRateConverterInitialPhase = 'srcp',
kAudioConverterCodecQuality = 'cdqu',
kAudioConverterPrimeMethod = 'prmm',
kAudioConverterPrimeInfo = 'prim',
kAudioConverterChannelMap = 'chmp',
kAudioConverterDecompressionMagicCookie = 'dmgc',
kAudioConverterCompressionMagicCookie = 'cmgc',
kAudioConverterEncodeBitRate = 'brat',
kAudioConverterEncodeAdjustableSampleRate = 'ajsr',
kAudioConverterInputChannelLayout = 'icl ',
kAudioConverterOutputChannelLayout = 'ocl ',
kAudioConverterApplicableEncodeBitRates = 'aebr',
kAudioConverterAvailableEncodeBitRates = 'vebr',
kAudioConverterApplicableEncodeSampleRates = 'aesr',
kAudioConverterAvailableEncodeSampleRates = 'vesr',
kAudioConverterAvailableEncodeChannelLayoutTags = 'aecl',
kAudioConverterCurrentOutputStreamDescription = 'acod',
kAudioConverterCurrentInputStreamDescription = 'acid',
kAudioConverterPropertySettings = 'acps',
kAudioConverterPropertyBitDepthHint = 'acbd',
kAudioConverterPropertyFormatList = 'flst',
enum { kAudioConverterPropertyMinimumInputBufferSize = 'mibs',
kAudioConverterPropertyMinimumOutputBufferSize = 'mobs',
kAudioConverterPropertyMaximumInputBufferSize = 'xibs',
kAudioConverterPropertyMaximumInputPacketSize = 'xips',
kAudioConverterPropertyMaximumOutputPacketSize = 'xops',
kAudioConverterPropertyCalculateInputBufferSize = 'cibs',
kAudioConverterPropertyCalculateOutputBufferSize = 'cobs',
kAudioConverterPropertyInputCodecParameters = 'icdp',
kAudioConverterPropertyOutputCodecParameters = 'ocdp',
kAudioConverterSampleRateConverterAlgorithm = 'srci',
kAudioConverterSampleRateConverterComplexity = 'srca',
kAudioConverterSampleRateConverterQuality = 'srcq',
kAudioConverterSampleRateConverterInitialPhase = 'srcp',
kAudioConverterCodecQuality = 'cdqu',
kAudioConverterPrimeMethod = 'prmm',
kAudioConverterPrimeInfo = 'prim',
kAudioConverterChannelMap = 'chmp',
kAudioConverterDecompressionMagicCookie = 'dmgc',
kAudioConverterCompressionMagicCookie = 'cmgc',
kAudioConverterEncodeBitRate = 'brat',
kAudioConverterEncodeAdjustableSampleRate = 'ajsr',
kAudioConverterInputChannelLayout = 'icl ',
kAudioConverterOutputChannelLayout = 'ocl ',
kAudioConverterApplicableEncodeBitRates = 'aebr',
kAudioConverterAvailableEncodeBitRates = 'vebr',
kAudioConverterApplicableEncodeSampleRates = 'aesr',
kAudioConverterAvailableEncodeSampleRates = 'vesr',
kAudioConverterAvailableEncodeChannelLayoutTags = 'aecl',
kAudioConverterCurrentOutputStreamDescription = 'acod',
kAudioConverterCurrentInputStreamDescription = 'acid',
kAudioConverterPropertySettings = 'acps',
kAudioConverterPropertyBitDepthHint = 'acbd',
kAudioConverterPropertyFormatList = 'flst',
};
enum {
kAudioConverterQuality_Max = 0x7F,
kAudioConverterQuality_High = 0x60,
kAudioConverterQuality_Medium = 0x40,
kAudioConverterQuality_Low = 0x20,
kAudioConverterQuality_Min = 0
enum { kAudioConverterQuality_Max = 0x7F,
kAudioConverterQuality_High = 0x60,
kAudioConverterQuality_Medium = 0x40,
kAudioConverterQuality_Low = 0x20,
kAudioConverterQuality_Min = 0,
};
enum {
kAudio_UnimplementedError = -4,
kAudio_FileNotFoundError = -43,
kAudio_FilePermissionError = -54,
kAudio_TooManyFilesOpenError = -42,
kAudio_BadFilePathError = '!pth', // 0x21707468, 561017960
kAudio_ParamError = -50,
kAudio_MemFullError = -108,
enum { kAudio_UnimplementedError = -4,
kAudio_FileNotFoundError = -43,
kAudio_FilePermissionError = -54,
kAudio_TooManyFilesOpenError = -42,
kAudio_BadFilePathError = '!pth', // 0x21707468, 561017960
kAudio_ParamError = -50,
kAudio_MemFullError = -108,
kAudioConverterErr_FormatNotSupported = 'fmt?',
kAudioConverterErr_OperationNotSupported = 0x6F703F3F,
// 'op??', integer used because of trigraph
kAudioConverterErr_PropertyNotSupported = 'prop',
kAudioConverterErr_InvalidInputSize = 'insz',
kAudioConverterErr_InvalidOutputSize = 'otsz',
// e.g. byte size is not a multiple of the frame size
kAudioConverterErr_UnspecifiedError = 'what',
kAudioConverterErr_BadPropertySizeError = '!siz',
kAudioConverterErr_RequiresPacketDescriptionsError = '!pkd',
kAudioConverterErr_InputSampleRateOutOfRange = '!isr',
kAudioConverterErr_OutputSampleRateOutOfRange = '!osr'
kAudioConverterErr_FormatNotSupported = 'fmt?',
kAudioConverterErr_OperationNotSupported = 0x6F703F3F,
// 'op??', integer used because of trigraph
kAudioConverterErr_PropertyNotSupported = 'prop',
kAudioConverterErr_InvalidInputSize = 'insz',
kAudioConverterErr_InvalidOutputSize = 'otsz',
// e.g. byte size is not a multiple of the frame size
kAudioConverterErr_UnspecifiedError = 'what',
kAudioConverterErr_BadPropertySizeError = '!siz',
kAudioConverterErr_RequiresPacketDescriptionsError = '!pkd',
kAudioConverterErr_InputSampleRateOutOfRange = '!isr',
kAudioConverterErr_OutputSampleRateOutOfRange = '!osr',
};
typedef OSStatus (*AudioConverterNew_t) (
typedef OSStatus (*AudioConverterNew_t)(
const AudioStreamBasicDescription *inSourceFormat,
const AudioStreamBasicDescription *inDestinationFormat,
AudioConverterRef *outAudioConverter
);
AudioConverterRef *outAudioConverter);
typedef OSStatus (*AudioConverterDispose_t) (
AudioConverterRef inAudioConverter
);
typedef OSStatus (*AudioConverterDispose_t)(AudioConverterRef inAudioConverter);
typedef OSStatus (*AudioConverterReset_t) (
AudioConverterRef inAudioConverter
);
typedef OSStatus (*AudioConverterReset_t)(AudioConverterRef inAudioConverter);
typedef OSStatus (*AudioConverterGetProperty_t) (
AudioConverterRef inAudioConverter,
AudioConverterPropertyID inPropertyID,
UInt32 *ioPropertyDataSize,
void *outPropertyData
);
typedef OSStatus (*AudioConverterGetProperty_t)(
AudioConverterRef inAudioConverter,
AudioConverterPropertyID inPropertyID, UInt32 *ioPropertyDataSize,
void *outPropertyData);
typedef OSStatus (*AudioConverterGetPropertyInfo_t) (
AudioConverterRef inAudioConverter,
AudioConverterPropertyID inPropertyID,
UInt32 *outSize,
Boolean *outWritable
);
typedef OSStatus (*AudioConverterGetPropertyInfo_t)(
AudioConverterRef inAudioConverter,
AudioConverterPropertyID inPropertyID, UInt32 *outSize,
Boolean *outWritable);
typedef OSStatus (*AudioConverterSetProperty_t) (
AudioConverterRef inAudioConverter,
AudioConverterPropertyID inPropertyID,
UInt32 inPropertyDataSize,
const void *inPropertyData
);
typedef OSStatus (*AudioConverterSetProperty_t)(
AudioConverterRef inAudioConverter,
AudioConverterPropertyID inPropertyID, UInt32 inPropertyDataSize,
const void *inPropertyData);
typedef OSStatus (*AudioConverterFillComplexBuffer_t) (
AudioConverterRef inAudioConverter,
typedef OSStatus (*AudioConverterFillComplexBuffer_t)(
AudioConverterRef inAudioConverter,
AudioConverterComplexInputDataProc inInputDataProc,
void *inInputDataProcUserData,
UInt32 *ioOutputDataPacketSize,
AudioBufferList *outOutputData,
AudioStreamPacketDescription *outPacketDescription
);
void *inInputDataProcUserData, UInt32 *ioOutputDataPacketSize,
AudioBufferList *outOutputData,
AudioStreamPacketDescription *outPacketDescription);
typedef OSStatus (*AudioFormatGetProperty_t) (
AudioFormatPropertyID inPropertyID,
UInt32 inSpecifierSize,
const void *inSpecifier,
UInt32 *ioPropertyDataSize,
void *outPropertyData
);
typedef OSStatus (*AudioFormatGetProperty_t)(AudioFormatPropertyID inPropertyID,
UInt32 inSpecifierSize,
const void *inSpecifier,
UInt32 *ioPropertyDataSize,
void *outPropertyData);
typedef OSStatus (*AudioFormatGetPropertyInfo_t) (
AudioFormatPropertyID inPropertyID,
UInt32 inSpecifierSize,
const void *inSpecifier,
UInt32 *outPropertyDataSize
);
typedef OSStatus (*AudioFormatGetPropertyInfo_t)(
AudioFormatPropertyID inPropertyID, UInt32 inSpecifierSize,
const void *inSpecifier, UInt32 *outPropertyDataSize);
static AudioConverterNew_t AudioConverterNew = NULL;
static AudioConverterDispose_t AudioConverterDispose = NULL;
@ -383,9 +343,10 @@ static HMODULE audio_toolbox = NULL;
static void release_lib(void)
{
#define RELEASE_LIB(x) if (x) { \
#define RELEASE_LIB(x) \
if (x) { \
FreeLibrary(x); \
x = NULL; \
x = NULL; \
}
RELEASE_LIB(audio_toolbox);
@ -396,12 +357,12 @@ static bool load_lib(void)
{
PWSTR common_path;
if (SHGetKnownFolderPath(FOLDERID_ProgramFilesCommon, 0, NULL,
&common_path) != S_OK) {
&common_path) != S_OK) {
CA_LOG(LOG_WARNING, "Could not retrieve common files path");
return false;
}
struct dstr path = { 0 };
struct dstr path = {0};
dstr_printf(&path, "%S\\Apple\\Apple Application Support", common_path);
CoTaskMemFree(common_path);
@ -411,8 +372,9 @@ static bool load_lib(void)
SetDllDirectory(w_path);
bfree(w_path);
#define LOAD_LIB(x, n) x = LoadLibrary(TEXT(n)); \
if (!x) \
#define LOAD_LIB(x, n) \
x = LoadLibrary(TEXT(n)); \
if (!x) \
CA_LOG(LOG_DEBUG, "Failed loading library '" n "'");
LOAD_LIB(audio_toolbox, "CoreAudioToolbox.dll");
@ -444,19 +406,20 @@ static void unload_core_audio(void)
#ifdef _MSC_VER
#pragma warning(push)
#pragma warning(disable: 4706)
#pragma warning(disable : 4706)
#endif
static bool load_core_audio(void)
{
if (!load_lib())
return false;
#define LOAD_SYM_FROM_LIB(sym, lib, dll) \
if (!(sym = (sym ## _t)GetProcAddress(lib, #sym))) { \
DWORD err = GetLastError(); \
CA_LOG(LOG_ERROR, "Couldn't load " #sym " from " \
dll ": %lu (0x%lx)", err, err); \
goto unload_everything; \
#define LOAD_SYM_FROM_LIB(sym, lib, dll) \
if (!(sym = (sym##_t)GetProcAddress(lib, #sym))) { \
DWORD err = GetLastError(); \
CA_LOG(LOG_ERROR, \
"Couldn't load " #sym " from " dll ": %lu (0x%lx)", \
err, err); \
goto unload_everything; \
}
#define LOAD_SYM(sym) \

View file

@ -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() {}

View file

@ -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);

View file

@ -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());

View file

@ -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();

View file

@ -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;

View file

@ -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;

View file

@ -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;

View file

@ -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

View file

@ -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; }
};

View file

@ -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")

View file

@ -17,4 +17,6 @@ ChannelFormat.5_1ch="5.1ch"
ChannelFormat.7_1ch="7.1ch"
DeactivateWhenNotShowing="التعطيل عندما لا يكون ظاهراً"
AutoStart="البدء تلقائياً مع التشغيل"
VideoConnection="مدخل الفيديو"
AudioConnection="مدخل الصوت"

View file

@ -1,4 +1,4 @@
BlackmagicDevice="Blackmagic-Gerät"
BlackmagicDevice="BlackmagicGerä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="2Kanal"
ChannelFormat.2_1ch="2.1Kanal"
ChannelFormat.4_0ch="4Kanal"
ChannelFormat.4_1ch="4.1Kanal"
ChannelFormat.5_1ch="5.1Kanal"
ChannelFormat.7_1ch="7.1Kanal"
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 FrontCenterKanal und LFEKanal tauschen"
VideoConnection="Videoverbindung"
AudioConnection="Audioverbindung"

View file

@ -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"

View file

@ -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"

View file

@ -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"

View file

@ -3,7 +3,9 @@ Device="Пристрій"
Mode="Режим"
Buffering="Увімкнути буферизацію"
PixelFormat="Формат пікселів"
ColorSpace="Колірний простір"
ColorSpace.Default="За замовчуванням"
ColorRange="Колірний діапазон"
ColorRange.Default="За замовчуванням"
ColorRange.Partial="Частковий"
ColorRange.Full="Повний"

View file

@ -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;

View file

@ -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;
}

View file

@ -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(), &currentPacket);
obs_source_output_audio(
static_cast<DeckLinkInput *>(decklink)->GetSource(),
&currentPacket);
}
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(), &currentFrame);
obs_source_output_video2(
static_cast<DeckLinkInput *>(decklink)->GetSource(),
&currentFrame);
}
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;

View file

@ -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);

View file

@ -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;
}

View file

@ -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);

View file

@ -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;
}

View file

@ -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; }
};

View file

@ -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();

View file

@ -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;
}

View file

@ -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;
}

View file

@ -0,0 +1,3 @@
Language: Cpp
SortIncludes: false
DisableFormat: true

View file

@ -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;

View file

@ -0,0 +1,3 @@
Language: Cpp
SortIncludes: false
DisableFormat: true

View file

@ -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);

View file

@ -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);

View file

@ -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";
}
}

View file

@ -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;

View file

@ -51,13 +51,15 @@ static obs_properties_t *color_source_properties(void *unused)
obs_properties_t *props = obs_properties_create();
obs_properties_add_color(props, "color",
obs_module_text("ColorSource.Color"));
obs_module_text("ColorSource.Color"));
obs_properties_add_int(props, "width",
obs_module_text("ColorSource.Width"), 0, 4096, 1);
obs_module_text("ColorSource.Width"), 0, 4096,
1);
obs_properties_add_int(props, "height",
obs_module_text("ColorSource.Height"), 0, 4096, 1);
obs_module_text("ColorSource.Height"), 0, 4096,
1);
return props;
}
@ -68,9 +70,9 @@ static void color_source_render(void *data, gs_effect_t *effect)
struct color_source *context = data;
gs_effect_t *solid = obs_get_base_effect(OBS_EFFECT_SOLID);
gs_eparam_t *color = gs_effect_get_param_by_name(solid, "color");
gs_technique_t *tech = gs_effect_get_technique(solid, "Solid");
gs_effect_t *solid = obs_get_base_effect(OBS_EFFECT_SOLID);
gs_eparam_t *color = gs_effect_get_param_by_name(solid, "color");
gs_technique_t *tech = gs_effect_get_technique(solid, "Solid");
struct vec4 colorVal;
vec4_from_rgba(&colorVal, context->color);
@ -99,25 +101,22 @@ static uint32_t color_source_getheight(void *data)
static void color_source_defaults(obs_data_t *settings)
{
struct obs_video_info ovi;
obs_get_video_info(&ovi);
obs_data_set_default_int(settings, "color", 0xFFFFFFFF);
obs_data_set_default_int(settings, "width", ovi.base_width);
obs_data_set_default_int(settings, "height", ovi.base_height);
obs_data_set_default_int(settings, "width", 400);
obs_data_set_default_int(settings, "height", 400);
}
struct obs_source_info color_source_info = {
.id = "color_source",
.type = OBS_SOURCE_TYPE_INPUT,
.output_flags = OBS_SOURCE_VIDEO | OBS_SOURCE_CUSTOM_DRAW,
.create = color_source_create,
.destroy = color_source_destroy,
.update = color_source_update,
.get_name = color_source_get_name,
.get_defaults = color_source_defaults,
.get_width = color_source_getwidth,
.get_height = color_source_getheight,
.video_render = color_source_render,
.get_properties = color_source_properties
.id = "color_source",
.type = OBS_SOURCE_TYPE_INPUT,
.output_flags = OBS_SOURCE_VIDEO | OBS_SOURCE_CUSTOM_DRAW,
.create = color_source_create,
.destroy = color_source_destroy,
.update = color_source_update,
.get_name = color_source_get_name,
.get_defaults = color_source_defaults,
.get_width = color_source_getwidth,
.get_height = color_source_getheight,
.video_render = color_source_render,
.get_properties = color_source_properties,
};

View file

@ -13,8 +13,8 @@ SlideShow.Loop="Bucle"
SlideShow.Transition="Transición"
SlideShow.Transition.Cut="Corte"
SlideShow.Transition.Fade="Desvanecimiento"
SlideShow.Transition.Swipe="Deslizar Rapido"
SlideShow.Transition.Slide="Deslizar"
SlideShow.Transition.Swipe="Deslizar"
SlideShow.Transition.Slide="Diapositiva"
SlideShow.PlaybackBehavior="Comportamiento de visibilidad"
SlideShow.PlaybackBehavior.StopRestart="Detener cuando no sea visible, reiniciar cuando sea visible"
SlideShow.PlaybackBehavior.PauseUnpause="Pausar cuando no sea visible, reanudar cuando sea visible"

View file

@ -1,6 +1,36 @@
ImageInput="Imaxe"
File="Ficheiro de imaxe"
UnloadWhenNotShowing="Non descargar a imaxe cando non se mostre"
UnloadWhenNotShowing="Descargar a imaxe cando non se amosa"
SlideShow="Diaporama"
SlideShow.TransitionSpeed="Velocidade da transición (milisegundos)"
SlideShow.SlideTime="Tempo entre diapositivas (milisegundos)"
SlideShow.Files="Ficheiros de imaxe"
SlideShow.CustomSize="Límite do tamaño/relación de aspecto"
SlideShow.CustomSize.Auto="Automático"
SlideShow.Randomize="Reproducir ao chou"
SlideShow.Loop="Bucle"
SlideShow.Transition="Transición"
SlideShow.Transition.Cut="Cortar"
SlideShow.Transition.Fade="Esvaecer"
SlideShow.Transition.Swipe="Esvarar"
SlideShow.Transition.Slide="Diapositiva"
SlideShow.PlaybackBehavior="Comportamento da visibilidade"
SlideShow.PlaybackBehavior.StopRestart="Parar cando non é visíbel, reiniciar cando sexa visíbel"
SlideShow.PlaybackBehavior.PauseUnpause="Pór en pausa cando non é visíbel, reiniciar cando sexa visíbel"
SlideShow.PlaybackBehavior.AlwaysPlay="Reproducir sempre cando non estea visíbel"
SlideShow.SlideMode="Modo de diapositiva"
SlideShow.SlideMode.Auto="Automático"
SlideShow.SlideMode.Manual="Manual (use as teclas rápidas para controlar o disporama)"
SlideShow.PlayPause="Reproducir/Pór en pausa"
SlideShow.Restart="Reiniciar"
SlideShow.Stop="Parar"
SlideShow.NextSlide="Seguinte diapositiva"
SlideShow.PreviousSlide="Diapositiva anterior"
SlideShow.HideWhenDone="Agochar cando se reproduce o diaporama"
ColorSource="Orixe da cor"
ColorSource.Color="Cor"
ColorSource.Width="Largo"
ColorSource.Height="Alto"

View file

@ -13,6 +13,7 @@ SlideShow.Transition.Cut="Decupare"
SlideShow.Transition.Fade="Estompare"
SlideShow.Transition.Swipe="Glisare"
SlideShow.Transition.Slide="Culisare"
SlideShow.SlideMode="Mod de culisare"
SlideShow.SlideMode.Auto="Automat"
SlideShow.PlayPause="Redă/Pune pe pauză"
SlideShow.Restart="Repornește"

View file

@ -1,6 +1,36 @@
ImageInput="Slika"
File="Slikovna datoteka"
UnloadWhenNotShowing="Ne naloži slike, ko ni prikazana"
UnloadWhenNotShowing="Razloži sliko, ko ni prikazana"
SlideShow="Slikovna predstavitev"
SlideShow.TransitionSpeed="Hitrost prehodov (ms)"
SlideShow.SlideTime="Čas med slikami (ms)"
SlideShow.Files="Slikovne datoteke"
SlideShow.CustomSize="Omejitev velikost/Razmerje"
SlideShow.CustomSize.Auto="Samodejno"
SlideShow.Randomize="Naključno predvajanje"
SlideShow.Loop="Ponavljaj"
SlideShow.Transition="Prehod"
SlideShow.Transition.Cut="Izreži"
SlideShow.Transition.Fade="Pojemaj"
SlideShow.Transition.Swipe="Potegni"
SlideShow.Transition.Slide="Podrsaj"
SlideShow.PlaybackBehavior="Vedenje vidnosti"
SlideShow.PlaybackBehavior.StopRestart="Ustavi, ko ni vidno; ponovno zaženi, ko je vidno"
SlideShow.PlaybackBehavior.PauseUnpause="Premor, ko ni vidno; nadaljuj, ko je vidno"
SlideShow.PlaybackBehavior.AlwaysPlay="Vedno predvajaj, ko ni vidno"
SlideShow.SlideMode="Način predstavitve"
SlideShow.SlideMode.Auto="Samodejno"
SlideShow.SlideMode.Manual="Ročno (uporabi hitre tipke na nadzor predstavitve)"
SlideShow.PlayPause="Predvajaj/Premor"
SlideShow.Restart="Ponovno zaženi"
SlideShow.Stop="Ustavi"
SlideShow.NextSlide="Naslednja slika"
SlideShow.PreviousSlide="Prejšnja slika"
SlideShow.HideWhenDone="Skrij, ko je predstavitev končana"
ColorSource="Barvni vir"
ColorSource.Color="Barva"
ColorSource.Width="Širina"
ColorSource.Height="Višina"

View file

@ -4,31 +4,27 @@
#include <util/dstr.h>
#include <sys/stat.h>
#define blog(log_level, format, ...) \
#define blog(log_level, format, ...) \
blog(log_level, "[image_source: '%s'] " format, \
obs_source_get_name(context->source), ##__VA_ARGS__)
obs_source_get_name(context->source), ##__VA_ARGS__)
#define debug(format, ...) \
blog(LOG_DEBUG, format, ##__VA_ARGS__)
#define info(format, ...) \
blog(LOG_INFO, format, ##__VA_ARGS__)
#define warn(format, ...) \
blog(LOG_WARNING, format, ##__VA_ARGS__)
#define debug(format, ...) blog(LOG_DEBUG, format, ##__VA_ARGS__)
#define info(format, ...) blog(LOG_INFO, format, ##__VA_ARGS__)
#define warn(format, ...) blog(LOG_WARNING, format, ##__VA_ARGS__)
struct image_source {
obs_source_t *source;
char *file;
bool persistent;
time_t file_timestamp;
float update_time_elapsed;
uint64_t last_time;
bool active;
char *file;
bool persistent;
time_t file_timestamp;
float update_time_elapsed;
uint64_t last_time;
bool active;
gs_image_file2_t if2;
};
static time_t get_modified_timestamp(const char *filename)
{
struct stat stats;
@ -152,9 +148,9 @@ static void image_source_render(void *data, gs_effect_t *effect)
return;
gs_effect_set_texture(gs_effect_get_param_by_name(effect, "image"),
context->if2.image.texture);
gs_draw_sprite(context->if2.image.texture, 0,
context->if2.image.cx, context->if2.image.cy);
context->if2.image.texture);
gs_draw_sprite(context->if2.image.texture, 0, context->if2.image.cx,
context->if2.image.cy);
}
static void image_source_tick(void *data, float seconds)
@ -212,7 +208,6 @@ static void image_source_tick(void *data, float seconds)
context->last_time = frame_time;
}
static const char *image_filter =
"All formats (*.bmp *.tga *.png *.jpeg *.jpg *.gif *.psd);;"
"BMP Files (*.bmp);;"
@ -240,11 +235,10 @@ static obs_properties_t *image_source_properties(void *data)
dstr_resize(&path, slash - path.array + 1);
}
obs_properties_add_path(props,
"file", obs_module_text("File"),
OBS_PATH_FILE, image_filter, path.array);
obs_properties_add_bool(props,
"unload", obs_module_text("UnloadWhenNotShowing"));
obs_properties_add_path(props, "file", obs_module_text("File"),
OBS_PATH_FILE, image_filter, path.array);
obs_properties_add_bool(props, "unload",
obs_module_text("UnloadWhenNotShowing"));
dstr_free(&path);
return props;
@ -257,22 +251,21 @@ uint64_t image_source_get_memory_usage(void *data)
}
static struct obs_source_info image_source_info = {
.id = "image_source",
.type = OBS_SOURCE_TYPE_INPUT,
.output_flags = OBS_SOURCE_VIDEO,
.get_name = image_source_get_name,
.create = image_source_create,
.destroy = image_source_destroy,
.update = image_source_update,
.get_defaults = image_source_defaults,
.show = image_source_show,
.hide = image_source_hide,
.get_width = image_source_getwidth,
.get_height = image_source_getheight,
.video_render = image_source_render,
.video_tick = image_source_tick,
.get_properties = image_source_properties
};
.id = "image_source",
.type = OBS_SOURCE_TYPE_INPUT,
.output_flags = OBS_SOURCE_VIDEO,
.get_name = image_source_get_name,
.create = image_source_create,
.destroy = image_source_destroy,
.update = image_source_update,
.get_defaults = image_source_defaults,
.show = image_source_show,
.hide = image_source_hide,
.get_width = image_source_getwidth,
.get_height = image_source_getheight,
.video_render = image_source_render,
.video_tick = image_source_tick,
.get_properties = image_source_properties};
OBS_DECLARE_MODULE()
OBS_MODULE_USE_DEFAULT_LOCALE("image-source", "en-US")

View file

@ -4,11 +4,13 @@
#include <util/darray.h>
#include <util/dstr.h>
#define do_log(level, format, ...) \
#define do_log(level, format, ...) \
blog(level, "[slideshow: '%s'] " format, \
obs_source_get_name(ss->source), ##__VA_ARGS__)
obs_source_get_name(ss->source), ##__VA_ARGS__)
#define warn(format, ...) do_log(LOG_WARNING, format, ##__VA_ARGS__)
#define warn(format, ...) do_log(LOG_WARNING, format, ##__VA_ARGS__)
/* clang-format off */
#define S_TR_SPEED "transition_speed"
#define S_CUSTOM_SIZE "use_custom_size"
@ -55,12 +57,14 @@
#define T_TR_SWIPE T_TR_("Swipe")
#define T_TR_SLIDE T_TR_("Slide")
/* clang-format on */
/* ------------------------------------------------------------------------- */
extern uint64_t image_source_get_memory_usage(void *data);
#define BYTES_TO_MBYTES (1024 * 1024)
#define MAX_MEM_USAGE (250 * BYTES_TO_MBYTES)
#define MAX_MEM_USAGE (250 * BYTES_TO_MBYTES)
struct image_file_data {
char *path;
@ -182,7 +186,7 @@ static const char *ss_getname(void *unused)
}
static void add_file(struct slideshow *ss, struct darray *array,
const char *path, uint32_t *cx, uint32_t *cy)
const char *path, uint32_t *cx, uint32_t *cy)
{
DARRAY(struct image_file_data) new_files;
struct image_file_data data;
@ -207,8 +211,10 @@ static void add_file(struct slideshow *ss, struct darray *array,
data.source = new_source;
da_push_back(new_files, &data);
if (new_cx > *cx) *cx = new_cx;
if (new_cy > *cy) *cy = new_cy;
if (new_cx > *cx)
*cx = new_cx;
if (new_cy > *cy)
*cy = new_cy;
void *source_data = obs_obj_get_data(new_source);
ss->mem_usage += image_source_get_memory_usage(source_data);
@ -221,12 +227,9 @@ static bool valid_extension(const char *ext)
{
if (!ext)
return false;
return astrcmpi(ext, ".bmp") == 0 ||
astrcmpi(ext, ".tga") == 0 ||
astrcmpi(ext, ".png") == 0 ||
astrcmpi(ext, ".jpeg") == 0 ||
astrcmpi(ext, ".jpg") == 0 ||
astrcmpi(ext, ".gif") == 0;
return astrcmpi(ext, ".bmp") == 0 || astrcmpi(ext, ".tga") == 0 ||
astrcmpi(ext, ".png") == 0 || astrcmpi(ext, ".jpeg") == 0 ||
astrcmpi(ext, ".jpg") == 0 || astrcmpi(ext, ".gif") == 0;
}
static inline bool item_valid(struct slideshow *ss)
@ -241,19 +244,16 @@ static void do_transition(void *data, bool to_null)
if (valid && ss->use_cut)
obs_transition_set(ss->transition,
ss->files.array[ss->cur_item].source);
ss->files.array[ss->cur_item].source);
else if (valid && !to_null)
obs_transition_start(ss->transition,
OBS_TRANSITION_MODE_AUTO,
ss->tr_speed,
ss->files.array[ss->cur_item].source);
obs_transition_start(ss->transition, OBS_TRANSITION_MODE_AUTO,
ss->tr_speed,
ss->files.array[ss->cur_item].source);
else
obs_transition_start(ss->transition,
OBS_TRANSITION_MODE_AUTO,
ss->tr_speed,
NULL);
obs_transition_start(ss->transition, OBS_TRANSITION_MODE_AUTO,
ss->tr_speed, NULL);
}
static void ss_update(void *data, obs_data_t *settings)
@ -344,8 +344,8 @@ static void ss_update(void *data, obs_data_t *settings)
dstr_copy(&dir_path, path);
dstr_cat_ch(&dir_path, '/');
dstr_cat(&dir_path, ent->d_name);
add_file(ss, &new_files.da, dir_path.array,
&cx, &cy);
add_file(ss, &new_files.da, dir_path.array, &cx,
&cy);
if (ss->mem_usage >= MAX_MEM_USAGE)
break;
@ -447,7 +447,7 @@ static void ss_update(void *data, obs_data_t *settings)
obs_transition_set_size(ss->transition, cx, cy);
obs_transition_set_alignment(ss->transition, OBS_ALIGN_CENTER);
obs_transition_set_scale_type(ss->transition,
OBS_TRANSITION_SCALE_ASPECT);
OBS_TRANSITION_SCALE_ASPECT);
if (ss->randomize && ss->files.num)
ss->cur_item = random_file(ss);
@ -475,7 +475,7 @@ static void ss_restart(void *data)
ss->cur_item = 0;
obs_transition_set(ss->transition,
ss->files.array[ss->cur_item].source);
ss->files.array[ss->cur_item].source);
ss->stop = false;
ss->paused = false;
@ -522,7 +522,7 @@ static void ss_previous_slide(void *data)
}
static void play_pause_hotkey(void *data, obs_hotkey_id id,
obs_hotkey_t *hotkey, bool pressed)
obs_hotkey_t *hotkey, bool pressed)
{
UNUSED_PARAMETER(id);
UNUSED_PARAMETER(hotkey);
@ -533,8 +533,8 @@ static void play_pause_hotkey(void *data, obs_hotkey_id id,
ss_play_pause(ss);
}
static void restart_hotkey(void *data, obs_hotkey_id id,
obs_hotkey_t *hotkey, bool pressed)
static void restart_hotkey(void *data, obs_hotkey_id id, obs_hotkey_t *hotkey,
bool pressed)
{
UNUSED_PARAMETER(id);
UNUSED_PARAMETER(hotkey);
@ -545,8 +545,8 @@ static void restart_hotkey(void *data, obs_hotkey_id id,
ss_restart(ss);
}
static void stop_hotkey(void *data, obs_hotkey_id id,
obs_hotkey_t *hotkey, bool pressed)
static void stop_hotkey(void *data, obs_hotkey_id id, obs_hotkey_t *hotkey,
bool pressed)
{
UNUSED_PARAMETER(id);
UNUSED_PARAMETER(hotkey);
@ -558,7 +558,7 @@ static void stop_hotkey(void *data, obs_hotkey_id id,
}
static void next_slide_hotkey(void *data, obs_hotkey_id id,
obs_hotkey_t *hotkey, bool pressed)
obs_hotkey_t *hotkey, bool pressed)
{
UNUSED_PARAMETER(id);
UNUSED_PARAMETER(hotkey);
@ -573,7 +573,7 @@ static void next_slide_hotkey(void *data, obs_hotkey_id id,
}
static void previous_slide_hotkey(void *data, obs_hotkey_id id,
obs_hotkey_t *hotkey, bool pressed)
obs_hotkey_t *hotkey, bool pressed)
{
UNUSED_PARAMETER(id);
UNUSED_PARAMETER(hotkey);
@ -607,30 +607,26 @@ static void *ss_create(obs_data_t *settings, obs_source_t *source)
ss->paused = false;
ss->stop = false;
ss->play_pause_hotkey = obs_hotkey_register_source(source,
"SlideShow.PlayPause",
obs_module_text("SlideShow.PlayPause"),
play_pause_hotkey, ss);
ss->play_pause_hotkey = obs_hotkey_register_source(
source, "SlideShow.PlayPause",
obs_module_text("SlideShow.PlayPause"), play_pause_hotkey, ss);
ss->restart_hotkey = obs_hotkey_register_source(source,
"SlideShow.Restart",
obs_module_text("SlideShow.Restart"),
restart_hotkey, ss);
ss->restart_hotkey = obs_hotkey_register_source(
source, "SlideShow.Restart",
obs_module_text("SlideShow.Restart"), restart_hotkey, ss);
ss->stop_hotkey = obs_hotkey_register_source(source,
"SlideShow.Stop",
obs_module_text("SlideShow.Stop"),
stop_hotkey, ss);
ss->stop_hotkey = obs_hotkey_register_source(
source, "SlideShow.Stop", obs_module_text("SlideShow.Stop"),
stop_hotkey, ss);
ss->prev_hotkey = obs_hotkey_register_source(source,
"SlideShow.NextSlide",
obs_module_text("SlideShow.NextSlide"),
next_slide_hotkey, ss);
ss->prev_hotkey = obs_hotkey_register_source(
source, "SlideShow.NextSlide",
obs_module_text("SlideShow.NextSlide"), next_slide_hotkey, ss);
ss->prev_hotkey = obs_hotkey_register_source(source,
"SlideShow.PreviousSlide",
obs_module_text("SlideShow.PreviousSlide"),
previous_slide_hotkey, ss);
ss->prev_hotkey = obs_hotkey_register_source(
source, "SlideShow.PreviousSlide",
obs_module_text("SlideShow.PreviousSlide"),
previous_slide_hotkey, ss);
pthread_mutex_init_value(&ss->mutex);
if (pthread_mutex_init(&ss->mutex, NULL) != 0)
@ -682,7 +678,7 @@ static void ss_video_tick(void *data, float seconds)
/* ----------------------------------------------------- */
/* fade to transparency when the file list becomes empty */
if (!ss->files.num) {
obs_source_t* active_transition_source =
obs_source_t *active_transition_source =
obs_transition_get_active_source(ss->transition);
if (active_transition_source) {
@ -725,8 +721,9 @@ static void ss_video_tick(void *data, float seconds)
}
static inline bool ss_audio_render_(obs_source_t *transition, uint64_t *ts_out,
struct obs_source_audio_mix *audio_output,
uint32_t mixers, size_t channels, size_t sample_rate)
struct obs_source_audio_mix *audio_output,
uint32_t mixers, size_t channels,
size_t sample_rate)
{
struct obs_source_audio_mix child_audio;
uint64_t source_ts;
@ -747,8 +744,9 @@ static inline bool ss_audio_render_(obs_source_t *transition, uint64_t *ts_out,
float *out = audio_output->output[mix].data[ch];
float *in = child_audio.output[mix].data[ch];
memcpy(out, in, AUDIO_OUTPUT_FRAMES *
MAX_AUDIO_CHANNELS * sizeof(float));
memcpy(out, in,
AUDIO_OUTPUT_FRAMES * MAX_AUDIO_CHANNELS *
sizeof(float));
}
}
@ -759,8 +757,9 @@ static inline bool ss_audio_render_(obs_source_t *transition, uint64_t *ts_out,
}
static bool ss_audio_render(void *data, uint64_t *ts_out,
struct obs_source_audio_mix *audio_output,
uint32_t mixers, size_t channels, size_t sample_rate)
struct obs_source_audio_mix *audio_output,
uint32_t mixers, size_t channels,
size_t sample_rate)
{
struct slideshow *ss = data;
obs_source_t *transition = get_transition(ss);
@ -770,7 +769,7 @@ static bool ss_audio_render(void *data, uint64_t *ts_out,
return false;
success = ss_audio_render_(transition, ts_out, audio_output, mixers,
channels, sample_rate);
channels, sample_rate);
obs_source_release(transition);
return success;
@ -803,9 +802,10 @@ static void ss_defaults(obs_data_t *settings)
obs_data_set_default_string(settings, S_TRANSITION, "fade");
obs_data_set_default_int(settings, S_SLIDE_TIME, 8000);
obs_data_set_default_int(settings, S_TR_SPEED, 700);
obs_data_set_default_string(settings, S_CUSTOM_SIZE, T_CUSTOM_SIZE_AUTO);
obs_data_set_default_string(settings, S_CUSTOM_SIZE,
T_CUSTOM_SIZE_AUTO);
obs_data_set_default_string(settings, S_BEHAVIOR,
S_BEHAVIOR_ALWAYS_PLAY);
S_BEHAVIOR_ALWAYS_PLAY);
obs_data_set_default_string(settings, S_MODE, S_MODE_AUTO);
obs_data_set_default_bool(settings, S_LOOP, true);
}
@ -813,12 +813,7 @@ static void ss_defaults(obs_data_t *settings)
static const char *file_filter =
"Image files (*.bmp *.tga *.png *.jpeg *.jpg *.gif)";
static const char *aspects[] = {
"16:9",
"16:10",
"4:3",
"1:1"
};
static const char *aspects[] = {"16:9", "16:10", "4:3", "1:1"};
#define NUM_ASPECTS (sizeof(aspects) / sizeof(const char *))
@ -841,36 +836,38 @@ static obs_properties_t *ss_properties(void *data)
/* ----------------- */
p = obs_properties_add_list(ppts, S_BEHAVIOR, T_BEHAVIOR,
OBS_COMBO_TYPE_LIST, OBS_COMBO_FORMAT_STRING);
OBS_COMBO_TYPE_LIST,
OBS_COMBO_FORMAT_STRING);
obs_property_list_add_string(p, T_BEHAVIOR_ALWAYS_PLAY,
S_BEHAVIOR_ALWAYS_PLAY);
S_BEHAVIOR_ALWAYS_PLAY);
obs_property_list_add_string(p, T_BEHAVIOR_STOP_RESTART,
S_BEHAVIOR_STOP_RESTART);
S_BEHAVIOR_STOP_RESTART);
obs_property_list_add_string(p, T_BEHAVIOR_PAUSE_UNPAUSE,
S_BEHAVIOR_PAUSE_UNPAUSE);
S_BEHAVIOR_PAUSE_UNPAUSE);
p = obs_properties_add_list(ppts, S_MODE, T_MODE,
OBS_COMBO_TYPE_LIST, OBS_COMBO_FORMAT_STRING);
p = obs_properties_add_list(ppts, S_MODE, T_MODE, OBS_COMBO_TYPE_LIST,
OBS_COMBO_FORMAT_STRING);
obs_property_list_add_string(p, T_MODE_AUTO, S_MODE_AUTO);
obs_property_list_add_string(p, T_MODE_MANUAL, S_MODE_MANUAL);
p = obs_properties_add_list(ppts, S_TRANSITION, T_TRANSITION,
OBS_COMBO_TYPE_LIST, OBS_COMBO_FORMAT_STRING);
OBS_COMBO_TYPE_LIST,
OBS_COMBO_FORMAT_STRING);
obs_property_list_add_string(p, T_TR_CUT, TR_CUT);
obs_property_list_add_string(p, T_TR_FADE, TR_FADE);
obs_property_list_add_string(p, T_TR_SWIPE, TR_SWIPE);
obs_property_list_add_string(p, T_TR_SLIDE, TR_SLIDE);
obs_properties_add_int(ppts, S_SLIDE_TIME, T_SLIDE_TIME,
50, 3600000, 50);
obs_properties_add_int(ppts, S_TR_SPEED, T_TR_SPEED,
0, 3600000, 50);
obs_properties_add_int(ppts, S_SLIDE_TIME, T_SLIDE_TIME, 50, 3600000,
50);
obs_properties_add_int(ppts, S_TR_SPEED, T_TR_SPEED, 0, 3600000, 50);
obs_properties_add_bool(ppts, S_LOOP, T_LOOP);
obs_properties_add_bool(ppts, S_HIDE, T_HIDE);
obs_properties_add_bool(ppts, S_RANDOMIZE, T_RANDOMIZE);
p = obs_properties_add_list(ppts, S_CUSTOM_SIZE, T_CUSTOM_SIZE,
OBS_COMBO_TYPE_EDITABLE, OBS_COMBO_FORMAT_STRING);
OBS_COMBO_TYPE_EDITABLE,
OBS_COMBO_FORMAT_STRING);
obs_property_list_add_string(p, T_CUSTOM_SIZE_AUTO, T_CUSTOM_SIZE_AUTO);
@ -897,7 +894,8 @@ static obs_properties_t *ss_properties(void *data)
}
obs_properties_add_editable_list(ppts, S_FILES, T_FILES,
OBS_EDITABLE_LIST_TYPE_FILES, file_filter, path.array);
OBS_EDITABLE_LIST_TYPE_FILES,
file_filter, path.array);
dstr_free(&path);
return ppts;
@ -924,23 +922,22 @@ static void ss_deactivate(void *data)
}
struct obs_source_info slideshow_info = {
.id = "slideshow",
.type = OBS_SOURCE_TYPE_INPUT,
.output_flags = OBS_SOURCE_VIDEO |
OBS_SOURCE_CUSTOM_DRAW |
OBS_SOURCE_COMPOSITE,
.get_name = ss_getname,
.create = ss_create,
.destroy = ss_destroy,
.update = ss_update,
.activate = ss_activate,
.deactivate = ss_deactivate,
.video_render = ss_video_render,
.video_tick = ss_video_tick,
.audio_render = ss_audio_render,
.id = "slideshow",
.type = OBS_SOURCE_TYPE_INPUT,
.output_flags = OBS_SOURCE_VIDEO | OBS_SOURCE_CUSTOM_DRAW |
OBS_SOURCE_COMPOSITE,
.get_name = ss_getname,
.create = ss_create,
.destroy = ss_destroy,
.update = ss_update,
.activate = ss_activate,
.deactivate = ss_deactivate,
.video_render = ss_video_render,
.video_tick = ss_video_tick,
.audio_render = ss_audio_render,
.enum_active_sources = ss_enum_sources,
.get_width = ss_width,
.get_height = ss_height,
.get_defaults = ss_defaults,
.get_properties = ss_properties
.get_width = ss_width,
.get_height = ss_height,
.get_defaults = ss_defaults,
.get_properties = ss_properties,
};

View file

@ -29,7 +29,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#define blog(level, msg, ...) blog(level, "alsa-input: " msg, ##__VA_ARGS__)
#define NSEC_PER_SEC 1000000000LL
#define NSEC_PER_SEC 1000000000LL
#define NSEC_PER_MSEC 1000000L
#define STARTUP_TIMEOUT_NS (500 * NSEC_PER_MSEC)
#define REOPEN_TIMEOUT 1000UL
@ -63,11 +63,11 @@ struct alsa_data {
uint64_t first_ts;
};
static const char * alsa_get_name(void *);
static bool alsa_devices_changed(obs_properties_t *props,
obs_property_t *p, obs_data_t *settings);
static obs_properties_t * alsa_get_properties(void *);
static void * alsa_create(obs_data_t *, obs_source_t *);
static const char *alsa_get_name(void *);
static bool alsa_devices_changed(obs_properties_t *props, obs_property_t *p,
obs_data_t *settings);
static obs_properties_t *alsa_get_properties(void *);
static void *alsa_create(obs_data_t *, obs_source_t *);
static void alsa_destroy(void *);
static void alsa_activate(void *);
static void alsa_deactivate(void *);
@ -75,19 +75,19 @@ static void alsa_get_defaults(obs_data_t *);
static void alsa_update(void *, obs_data_t *);
struct obs_source_info alsa_input_capture = {
.id = "alsa_input_capture",
.type = OBS_SOURCE_TYPE_INPUT,
.output_flags = OBS_SOURCE_AUDIO,
.create = alsa_create,
.destroy = alsa_destroy,
.id = "alsa_input_capture",
.type = OBS_SOURCE_TYPE_INPUT,
.output_flags = OBS_SOURCE_AUDIO,
.create = alsa_create,
.destroy = alsa_destroy,
#if SHUTDOWN_ON_DEACTIVATE
.activate = alsa_activate,
.deactivate = alsa_deactivate,
.activate = alsa_activate,
.deactivate = alsa_deactivate,
#endif
.update = alsa_update,
.get_defaults = alsa_get_defaults,
.get_name = alsa_get_name,
.get_properties = alsa_get_properties
.update = alsa_update,
.get_defaults = alsa_get_defaults,
.get_name = alsa_get_name,
.get_properties = alsa_get_properties,
};
static bool _alsa_try_open(struct alsa_data *);
@ -96,28 +96,28 @@ static void _alsa_close(struct alsa_data *);
static bool _alsa_configure(struct alsa_data *);
static void _alsa_start_reopen(struct alsa_data *);
static void _alsa_stop_reopen(struct alsa_data *);
static void * _alsa_listen(void *);
static void * _alsa_reopen(void *);
static void *_alsa_listen(void *);
static void *_alsa_reopen(void *);
static enum audio_format _alsa_to_obs_audio_format(snd_pcm_format_t);
static enum speaker_layout _alsa_channels_to_obs_speakers(unsigned int);
/*****************************************************************************/
void * alsa_create(obs_data_t *settings, obs_source_t *source)
void *alsa_create(obs_data_t *settings, obs_source_t *source)
{
struct alsa_data *data = bzalloc(sizeof(struct alsa_data));
data->source = source;
data->source = source;
#if SHUTDOWN_ON_DEACTIVATE
data->active = false;
data->active = false;
#endif
data->buffer = NULL;
data->device = NULL;
data->buffer = NULL;
data->device = NULL;
data->first_ts = 0;
data->handle = NULL;
data->listen = false;
data->reopen = false;
data->handle = NULL;
data->listen = false;
data->reopen = false;
data->listen_thread = 0;
data->reopen_thread = 0;
@ -217,7 +217,7 @@ void alsa_update(void *vptr, obs_data_t *settings)
#endif
}
const char * alsa_get_name(void *unused)
const char *alsa_get_name(void *unused)
{
UNUSED_PARAMETER(unused);
return obs_module_text("AlsaInput");
@ -230,8 +230,8 @@ void alsa_get_defaults(obs_data_t *settings)
obs_data_set_default_int(settings, "rate", 44100);
}
static bool alsa_devices_changed(obs_properties_t *props,
obs_property_t *p, obs_data_t *settings)
static bool alsa_devices_changed(obs_properties_t *props, obs_property_t *p,
obs_data_t *settings)
{
UNUSED_PARAMETER(p);
bool visible = false;
@ -248,14 +248,14 @@ static bool alsa_devices_changed(obs_properties_t *props,
return true;
}
obs_properties_t * alsa_get_properties(void *unused)
obs_properties_t *alsa_get_properties(void *unused)
{
void **hints;
void **hint;
char *name = NULL;
char *descr = NULL;
char *io = NULL;
char *descr_i;
char *descr_i;
obs_properties_t *props;
obs_property_t *devices;
obs_property_t *rate;
@ -265,17 +265,18 @@ obs_properties_t * alsa_get_properties(void *unused)
props = obs_properties_create();
devices = obs_properties_add_list(props, "device_id",
obs_module_text("Device"), OBS_COMBO_TYPE_LIST,
OBS_COMBO_FORMAT_STRING);
obs_module_text("Device"),
OBS_COMBO_TYPE_LIST,
OBS_COMBO_FORMAT_STRING);
obs_property_list_add_string(devices, "Default", "default");
obs_properties_add_text(props, "custom_pcm",
obs_module_text("PCM"), OBS_TEXT_DEFAULT);
obs_properties_add_text(props, "custom_pcm", obs_module_text("PCM"),
OBS_TEXT_DEFAULT);
rate = obs_properties_add_list(props, "rate",
obs_module_text("Rate"), OBS_COMBO_TYPE_LIST,
OBS_COMBO_FORMAT_INT);
rate = obs_properties_add_list(props, "rate", obs_module_text("Rate"),
OBS_COMBO_TYPE_LIST,
OBS_COMBO_FORMAT_INT);
obs_property_set_modified_callback(devices, alsa_devices_changed);
@ -304,10 +305,10 @@ obs_properties_t * alsa_get_properties(void *unused)
descr_i = descr;
while (*descr_i) {
if (*descr_i == '\n') {
*descr_i = '\0';
break;
}
else ++descr_i;
*descr_i = '\0';
break;
} else
++descr_i;
}
obs_property_list_add_string(devices, descr, name);
@ -350,11 +351,11 @@ bool _alsa_open(struct alsa_data *data)
pthread_attr_t attr;
int err;
err = snd_pcm_open(&data->handle, data->device,
SND_PCM_STREAM_CAPTURE, 0);
err = snd_pcm_open(&data->handle, data->device, SND_PCM_STREAM_CAPTURE,
0);
if (err < 0) {
blog(LOG_ERROR, "Failed to open '%s': %s",
data->device, snd_strerror(err));
blog(LOG_ERROR, "Failed to open '%s': %s", data->device,
snd_strerror(err));
return false;
}
@ -362,8 +363,7 @@ bool _alsa_open(struct alsa_data *data)
goto cleanup;
if (snd_pcm_state(data->handle) != SND_PCM_STATE_PREPARED) {
blog(LOG_ERROR, "Device not prepared: '%s'",
data->device);
blog(LOG_ERROR, "Device not prepared: '%s'", data->device);
goto cleanup;
}
@ -371,8 +371,8 @@ bool _alsa_open(struct alsa_data *data)
err = snd_pcm_start(data->handle);
if (err < 0) {
blog(LOG_ERROR, "Failed to start '%s': %s",
data->device, snd_strerror(err));
blog(LOG_ERROR, "Failed to start '%s': %s", data->device,
snd_strerror(err));
goto cleanup;
}
@ -385,8 +385,8 @@ bool _alsa_open(struct alsa_data *data)
if (err) {
pthread_attr_destroy(&attr);
blog(LOG_ERROR,
"Failed to create capture thread for device '%s'.",
data->device);
"Failed to create capture thread for device '%s'.",
data->device);
goto cleanup;
}
@ -412,7 +412,7 @@ void _alsa_close(struct alsa_data *data)
}
if (data->buffer)
bfree(data->buffer), data->buffer = NULL;
bfree(data->buffer), data->buffer = NULL;
}
bool _alsa_configure(struct alsa_data *data)
@ -425,37 +425,33 @@ bool _alsa_configure(struct alsa_data *data)
err = snd_pcm_hw_params_any(data->handle, hwparams);
if (err < 0) {
blog(LOG_ERROR,
"snd_pcm_hw_params_any failed: %s",
snd_strerror(err));
blog(LOG_ERROR, "snd_pcm_hw_params_any failed: %s",
snd_strerror(err));
return false;
}
err = snd_pcm_hw_params_set_access(data->handle, hwparams,
SND_PCM_ACCESS_RW_INTERLEAVED);
SND_PCM_ACCESS_RW_INTERLEAVED);
if (err < 0) {
blog(LOG_ERROR,
"snd_pcm_hw_params_set_access failed: %s",
snd_strerror(err));
blog(LOG_ERROR, "snd_pcm_hw_params_set_access failed: %s",
snd_strerror(err));
return false;
}
data->format = SND_PCM_FORMAT_S16;
err = snd_pcm_hw_params_set_format(data->handle, hwparams,
data->format);
data->format);
if (err < 0) {
blog(LOG_ERROR,
"snd_pcm_hw_params_set_format failed: %s",
snd_strerror(err));
blog(LOG_ERROR, "snd_pcm_hw_params_set_format failed: %s",
snd_strerror(err));
return false;
}
err = snd_pcm_hw_params_set_rate_near(data->handle, hwparams,
&data->rate, 0);
&data->rate, 0);
if (err < 0) {
blog(LOG_ERROR,
"snd_pcm_hw_params_set_rate_near failed: %s",
snd_strerror(err));
blog(LOG_ERROR, "snd_pcm_hw_params_set_rate_near failed: %s",
snd_strerror(err));
return false;
}
blog(LOG_INFO, "PCM '%s' rate set to %d", data->device, data->rate);
@ -465,34 +461,34 @@ bool _alsa_configure(struct alsa_data *data)
data->channels = 2;
err = snd_pcm_hw_params_set_channels_near(data->handle, hwparams,
&data->channels);
&data->channels);
if (err < 0) {
blog(LOG_ERROR,
"snd_pcm_hw_params_set_channels_near failed: %s",
snd_strerror(err));
"snd_pcm_hw_params_set_channels_near failed: %s",
snd_strerror(err));
return false;
}
blog(LOG_INFO, "PCM '%s' channels set to %d",
data->device, data->channels);
blog(LOG_INFO, "PCM '%s' channels set to %d", data->device,
data->channels);
err = snd_pcm_hw_params(data->handle, hwparams);
if (err < 0) {
blog(LOG_ERROR, "snd_pcm_hw_params failed: %s",
snd_strerror(err));
snd_strerror(err));
return false;
}
err = snd_pcm_hw_params_get_period_size(hwparams, &data->period_size,
&dir);
&dir);
if (err < 0) {
blog(LOG_ERROR,
"snd_pcm_hw_params_get_period_size failed: %s",
snd_strerror(err));
blog(LOG_ERROR, "snd_pcm_hw_params_get_period_size failed: %s",
snd_strerror(err));
return false;
}
data->sample_size = (data->channels
* snd_pcm_format_physical_width(data->format)) / 8;
data->sample_size =
(data->channels * snd_pcm_format_physical_width(data->format)) /
8;
if (data->buffer)
bfree(data->buffer);
@ -515,8 +511,8 @@ void _alsa_start_reopen(struct alsa_data *data)
err = pthread_create(&data->reopen_thread, &attr, _alsa_reopen, data);
if (err) {
blog(LOG_ERROR,
"Failed to create reopen thread for device '%s'.",
data->device);
"Failed to create reopen thread for device '%s'.",
data->device);
}
pthread_attr_destroy(&attr);
@ -535,23 +531,23 @@ void _alsa_stop_reopen(struct alsa_data *data)
os_event_reset(data->abort_event);
}
void * _alsa_listen(void *attr)
void *_alsa_listen(void *attr)
{
struct alsa_data *data = attr;
struct obs_source_audio out;
blog(LOG_DEBUG, "Capture thread started.");
out.data[0] = data->buffer;
out.format = _alsa_to_obs_audio_format(data->format);
out.data[0] = data->buffer;
out.format = _alsa_to_obs_audio_format(data->format);
out.speakers = _alsa_channels_to_obs_speakers(data->channels);
out.samples_per_sec = data->rate;
os_atomic_set_bool(&data->listen, true);
do {
snd_pcm_sframes_t frames = snd_pcm_readi(data->handle,
data->buffer, data->period_size);
snd_pcm_sframes_t frames = snd_pcm_readi(
data->handle, data->buffer, data->period_size);
if (!os_atomic_load_bool(&data->listen))
break;
@ -565,8 +561,8 @@ void * _alsa_listen(void *attr)
}
out.frames = frames;
out.timestamp = os_gettime_ns()
- ((frames * NSEC_PER_SEC) / data->rate);
out.timestamp = os_gettime_ns() -
((frames * NSEC_PER_SEC) / data->rate);
if (!data->first_ts)
data->first_ts = out.timestamp + STARTUP_TIMEOUT_NS;
@ -581,7 +577,7 @@ void * _alsa_listen(void *attr)
return NULL;
}
void * _alsa_reopen(void *attr)
void *_alsa_reopen(void *attr)
{
struct alsa_data *data = attr;
unsigned long timeout = REOPEN_TIMEOUT;
@ -609,11 +605,16 @@ void * _alsa_reopen(void *attr)
enum audio_format _alsa_to_obs_audio_format(snd_pcm_format_t format)
{
switch (format) {
case SND_PCM_FORMAT_U8: return AUDIO_FORMAT_U8BIT;
case SND_PCM_FORMAT_S16_LE: return AUDIO_FORMAT_16BIT;
case SND_PCM_FORMAT_S32_LE: return AUDIO_FORMAT_32BIT;
case SND_PCM_FORMAT_FLOAT_LE: return AUDIO_FORMAT_FLOAT;
default: break;
case SND_PCM_FORMAT_U8:
return AUDIO_FORMAT_U8BIT;
case SND_PCM_FORMAT_S16_LE:
return AUDIO_FORMAT_16BIT;
case SND_PCM_FORMAT_S32_LE:
return AUDIO_FORMAT_32BIT;
case SND_PCM_FORMAT_FLOAT_LE:
return AUDIO_FORMAT_FLOAT;
default:
break;
}
return AUDIO_FORMAT_UNKNOWN;
@ -621,16 +622,22 @@ enum audio_format _alsa_to_obs_audio_format(snd_pcm_format_t format)
enum speaker_layout _alsa_channels_to_obs_speakers(unsigned int channels)
{
switch(channels) {
case 1: return SPEAKERS_MONO;
case 2: return SPEAKERS_STEREO;
case 3: return SPEAKERS_2POINT1;
case 4: return SPEAKERS_4POINT0;
case 5: return SPEAKERS_4POINT1;
case 6: return SPEAKERS_5POINT1;
case 8: return SPEAKERS_7POINT1;
switch (channels) {
case 1:
return SPEAKERS_MONO;
case 2:
return SPEAKERS_STEREO;
case 3:
return SPEAKERS_2POINT1;
case 4:
return SPEAKERS_4POINT0;
case 5:
return SPEAKERS_4POINT1;
case 6:
return SPEAKERS_5POINT1;
case 8:
return SPEAKERS_7POINT1;
}
return SPEAKERS_UNKNOWN;
}

View file

@ -0,0 +1,3 @@
AlsaInput="Устройство за улавяне на звука (ALSA)"
Device="Устройство"

View file

@ -1,3 +1,3 @@
AlsaInput="Dispositivo de captura de audio (ALSA)"
AlsaInput="Dispositivo de captura de son (ALSA)"
Device="Dispositivo"

View file

@ -0,0 +1,2 @@
AlsaInput="Naprava za zajemanje zvoka (ALSA)"

View file

@ -30,4 +30,3 @@ bool obs_module_load(void)
obs_register_source(&alsa_input_capture);
return true;
}

View file

@ -2,7 +2,7 @@ X11SharedMemoryScreenInput="Bildschirmaufnahme (XSHM)"
Screen="Bildschirm"
CaptureCursor="Mauszeiger aufnehmen"
AdvancedSettings="Erweiterte Einstellungen"
XServer="X-Server"
XServer="XServer"
XCCapture="Fensteraufnahme (Xcomposite)"
Window="Fenster"
CropTop="Oben abschneiden (Pixel)"
@ -10,7 +10,7 @@ CropLeft="Links abschneiden (Pixel)"
CropRight="Rechts abschneiden (Pixel)"
CropBottom="Unten abschneiden (Pixel)"
SwapRedBlue="Rot und Blau tauschen"
LockX="X-Server während der Aufnahme sperren"
IncludeXBorder="X-Rahmen anzeigen"
ExcludeAlpha="Alphaloses Texturformat verwenden (Mesa-Problemumgehung)"
LockX="XServer während der Aufnahme sperren"
IncludeXBorder="XRahmen anzeigen"
ExcludeAlpha="Alphaloses Texturformat verwenden (MesaProblemumgehung)"

View file

@ -1,15 +1,16 @@
X11SharedMemoryScreenInput="Captura de pantalla (XSHM)"
Screen="Pantalla"
CaptureCursor="Captura de cursor"
CaptureCursor="Capturar o cursor"
AdvancedSettings="Axustes avanzados"
XServer="X Server"
XServer="Servidor das X"
XCCapture="Captura de xanela (Xcomposite)"
Window="Xanela"
CropTop="Recortar por arriba (píxeles)"
CropLeft="Recortar pola esquerda (píxeles)"
CropRight="Recortar pola dereita (píxeles)"
CropBottom="Recortar por abaixo (píxeles)"
SwapRedBlue="Trocar vermello e azul"
LockX="Bloquear o servidor X durante a captura"
CropTop="Recortar por riba (píxeis)"
CropLeft="Recortar pola esquerda (píxeis)"
CropRight="Recortar pola dereita (píxeis)"
CropBottom="Recortar por baixo (píxeis)"
SwapRedBlue="Intercambiar vermello e azul"
LockX="Bloquear o servidor das X durante a captura"
IncludeXBorder="Incluír o bordo da xanela X"
ExcludeAlpha="Empregar o formato de textura sen alfa (solución Mesa)"

View file

@ -10,7 +10,7 @@ CropLeft="Trunchiază stânga (pixeli)"
CropRight="Trunchiază dreapta (pixeli)"
CropBottom="Trunchiază partea inferioară (pixeli)"
SwapRedBlue="Schimbă roșu cu albastru"
LockX="Blochează serverul X atunci când se capturează"
LockX="Blochează X server când se capturează"
IncludeXBorder="Include marginea cu X"
ExcludeAlpha="Folosește formatul de texturi fără alpha (soluție de evitare pentru Mesa)"

View file

@ -1,6 +1,6 @@
X11SharedMemoryScreenInput="Zajemanje zaslona (XSHM)"
Screen="Zaslon"
CaptureCursor="Zajemaj kazalec"
CaptureCursor="Zajemi kazalec"
AdvancedSettings="Napredne nastavitve"
XServer="X Server"
XCCapture="Zajemanje okna (Xcomposite)"

View file

@ -11,291 +11,259 @@
#include "xcompcap-helper.hpp"
namespace XCompcap
namespace XCompcap {
static Display *xdisplay = 0;
Display *disp()
{
static Display* xdisplay = 0;
if (!xdisplay)
xdisplay = XOpenDisplay(NULL);
Display *disp()
{
if (!xdisplay)
xdisplay = XOpenDisplay(NULL);
return xdisplay;
}
return xdisplay;
}
void cleanupDisplay()
{
if (!xdisplay)
return;
void cleanupDisplay()
{
if (!xdisplay)
return;
XCloseDisplay(xdisplay);
xdisplay = 0;
}
XCloseDisplay(xdisplay);
xdisplay = 0;
}
static void getAllWindows(Window parent, std::list<Window> &windows)
{
UNUSED_PARAMETER(parent);
UNUSED_PARAMETER(windows);
}
static void getAllWindows(Window parent, std::list<Window>& windows)
{
UNUSED_PARAMETER(parent);
UNUSED_PARAMETER(windows);
}
std::list<Window> getAllWindows()
{
std::list<Window> res;
std::list<Window> getAllWindows()
{
std::list<Window> res;
for (int i = 0; i < ScreenCount(disp()); ++i)
getAllWindows(RootWindow(disp(), i), res);
for (int i = 0; i < ScreenCount(disp()); ++i)
getAllWindows(RootWindow(disp(), i), res);
return res;
}
return res;
}
// Specification for checking for ewmh support at
// http://standards.freedesktop.org/wm-spec/wm-spec-latest.html#idm140200472693600
// Specification for checking for ewmh support at
// http://standards.freedesktop.org/wm-spec/wm-spec-latest.html#idm140200472693600
bool ewmhIsSupported()
{
Display *display = disp();
Atom netSupportingWmCheck =
XInternAtom(display, "_NET_SUPPORTING_WM_CHECK", true);
Atom actualType;
int format = 0;
unsigned long num = 0, bytes = 0;
unsigned char *data = NULL;
Window ewmh_window = 0;
bool ewmhIsSupported()
{
Display *display = disp();
Atom netSupportingWmCheck = XInternAtom(display,
"_NET_SUPPORTING_WM_CHECK", true);
Atom actualType;
int format = 0;
unsigned long num = 0, bytes = 0;
unsigned char *data = NULL;
Window ewmh_window = 0;
int status = XGetWindowProperty(display, DefaultRootWindow(display),
netSupportingWmCheck, 0L, 1L, false,
XA_WINDOW, &actualType, &format, &num,
&bytes, &data);
int status = XGetWindowProperty(
display,
DefaultRootWindow(display),
netSupportingWmCheck,
0L,
1L,
false,
XA_WINDOW,
&actualType,
&format,
&num,
&bytes,
&data);
if (status == Success) {
if (num > 0) {
ewmh_window = ((Window*)data)[0];
}
if (data) {
XFree(data);
data = NULL;
}
if (status == Success) {
if (num > 0) {
ewmh_window = ((Window *)data)[0];
}
if (ewmh_window) {
status = XGetWindowProperty(
display,
ewmh_window,
netSupportingWmCheck,
0L,
1L,
false,
XA_WINDOW,
&actualType,
&format,
&num,
&bytes,
&data);
if (status != Success || num == 0 ||
ewmh_window != ((Window*)data)[0]) {
ewmh_window = 0;
}
if (status == Success && data) {
XFree(data);
}
if (data) {
XFree(data);
data = NULL;
}
return ewmh_window != 0;
}
std::list<Window> getTopLevelWindows()
{
std::list<Window> res;
if (!ewmhIsSupported()) {
blog(LOG_WARNING, "Unable to query window list "
"because window manager "
"does not support extended "
"window manager Hints");
return res;
if (ewmh_window) {
status = XGetWindowProperty(display, ewmh_window,
netSupportingWmCheck, 0L, 1L, false,
XA_WINDOW, &actualType, &format,
&num, &bytes, &data);
if (status != Success || num == 0 ||
ewmh_window != ((Window *)data)[0]) {
ewmh_window = 0;
}
Atom netClList = XInternAtom(disp(), "_NET_CLIENT_LIST", true);
Atom actualType;
int format;
unsigned long num, bytes;
Window* data = 0;
for (int i = 0; i < ScreenCount(disp()); ++i) {
Window rootWin = RootWindow(disp(), i);
int status = XGetWindowProperty(
disp(),
rootWin,
netClList,
0L,
~0L,
false,
AnyPropertyType,
&actualType,
&format,
&num,
&bytes,
(uint8_t**)&data);
if (status != Success) {
blog(LOG_WARNING, "Failed getting root "
"window properties");
continue;
}
for (unsigned long i = 0; i < num; ++i)
res.push_back(data[i]);
if (status == Success && data) {
XFree(data);
}
}
return ewmh_window != 0;
}
std::list<Window> getTopLevelWindows()
{
std::list<Window> res;
if (!ewmhIsSupported()) {
blog(LOG_WARNING, "Unable to query window list "
"because window manager "
"does not support extended "
"window manager Hints");
return res;
}
int getRootWindowScreen(Window root)
{
XWindowAttributes attr;
Atom netClList = XInternAtom(disp(), "_NET_CLIENT_LIST", true);
Atom actualType;
int format;
unsigned long num, bytes;
Window *data = 0;
if (!XGetWindowAttributes(disp(), root, &attr))
return DefaultScreen(disp());
for (int i = 0; i < ScreenCount(disp()); ++i) {
Window rootWin = RootWindow(disp(), i);
return XScreenNumberOfScreen(attr.screen);
}
int status = XGetWindowProperty(disp(), rootWin, netClList, 0L,
~0L, false, AnyPropertyType,
&actualType, &format, &num,
&bytes, (uint8_t **)&data);
std::string getWindowAtom(Window win, const char *atom)
{
Atom netWmName = XInternAtom(disp(), atom, false);
int n;
char **list = 0;
XTextProperty tp;
std::string res = "unknown";
XGetTextProperty(disp(), win, &tp, netWmName);
if (!tp.nitems)
XGetWMName(disp(), win, &tp);
if (!tp.nitems)
return "error";
if (tp.encoding == XA_STRING) {
res = (char*)tp.value;
} else {
int ret = XmbTextPropertyToTextList(disp(), &tp, &list,
&n);
if (ret >= Success && n > 0 && *list) {
res = *list;
XFreeStringList(list);
}
if (status != Success) {
blog(LOG_WARNING, "Failed getting root "
"window properties");
continue;
}
char *conv = nullptr;
if (os_mbs_to_utf8_ptr(res.c_str(), 0, &conv))
res = conv;
bfree(conv);
for (unsigned long i = 0; i < num; ++i)
res.push_back(data[i]);
XFree(tp.value);
return res;
XFree(data);
}
std::string getWindowCommand(Window win)
{
Atom xi = XInternAtom(disp(), "WM_COMMAND", false);
int n;
char **list = 0;
XTextProperty tp;
std::string res = "error";
return res;
}
XGetTextProperty(disp(), win, &tp, xi);
int getRootWindowScreen(Window root)
{
XWindowAttributes attr;
if (!tp.nitems)
return std::string();
if (!XGetWindowAttributes(disp(), root, &attr))
return DefaultScreen(disp());
if (tp.encoding == XA_STRING) {
res = (char*)tp.value;
} else {
int ret = XmbTextPropertyToTextList(disp(), &tp, &list,
&n);
if (ret >= Success && n > 0 && *list) {
res = *list;
XFreeStringList(list);
}
return XScreenNumberOfScreen(attr.screen);
}
std::string getWindowAtom(Window win, const char *atom)
{
Atom netWmName = XInternAtom(disp(), atom, false);
int n;
char **list = 0;
XTextProperty tp;
std::string res = "unknown";
XGetTextProperty(disp(), win, &tp, netWmName);
if (!tp.nitems)
XGetWMName(disp(), win, &tp);
if (!tp.nitems)
return "error";
if (tp.encoding == XA_STRING) {
res = (char *)tp.value;
} else {
int ret = XmbTextPropertyToTextList(disp(), &tp, &list, &n);
if (ret >= Success && n > 0 && *list) {
res = *list;
XFreeStringList(list);
}
XFree(tp.value);
return res;
}
int getWindowPid(Window win)
{
UNUSED_PARAMETER(win);
return 1234; //TODO
}
char *conv = nullptr;
if (os_mbs_to_utf8_ptr(res.c_str(), 0, &conv))
res = conv;
bfree(conv);
static std::unordered_set<Window> changedWindows;
static pthread_mutex_t changeLock = PTHREAD_MUTEX_INITIALIZER;
void processEvents()
{
PLock lock(&changeLock);
XFree(tp.value);
XLockDisplay(disp());
return res;
}
while (XEventsQueued(disp(), QueuedAfterReading) > 0) {
XEvent ev;
std::string getWindowCommand(Window win)
{
Atom xi = XInternAtom(disp(), "WM_COMMAND", false);
int n;
char **list = 0;
XTextProperty tp;
std::string res = "error";
XNextEvent(disp(), &ev);
XGetTextProperty(disp(), win, &tp, xi);
if (ev.type == ConfigureNotify)
changedWindows.insert(ev.xconfigure.event);
if (!tp.nitems)
return std::string();
if (ev.type == MapNotify)
changedWindows.insert(ev.xmap.event);
if (ev.type == Expose)
changedWindows.insert(ev.xexpose.window);
if (ev.type == VisibilityNotify)
changedWindows.insert(ev.xvisibility.window);
if (ev.type == DestroyNotify)
changedWindows.insert(ev.xdestroywindow.event);
if (tp.encoding == XA_STRING) {
res = (char *)tp.value;
} else {
int ret = XmbTextPropertyToTextList(disp(), &tp, &list, &n);
if (ret >= Success && n > 0 && *list) {
res = *list;
XFreeStringList(list);
}
XUnlockDisplay(disp());
}
bool windowWasReconfigured(Window win)
{
PLock lock(&changeLock);
XFree(tp.value);
auto it = changedWindows.find(win);
return res;
}
if (it != changedWindows.end()) {
changedWindows.erase(it);
return true;
}
int getWindowPid(Window win)
{
UNUSED_PARAMETER(win);
return 1234; //TODO
}
return false;
static std::unordered_set<Window> changedWindows;
static pthread_mutex_t changeLock = PTHREAD_MUTEX_INITIALIZER;
void processEvents()
{
PLock lock(&changeLock);
XLockDisplay(disp());
while (XEventsQueued(disp(), QueuedAfterReading) > 0) {
XEvent ev;
XNextEvent(disp(), &ev);
if (ev.type == ConfigureNotify)
changedWindows.insert(ev.xconfigure.event);
if (ev.type == MapNotify)
changedWindows.insert(ev.xmap.event);
if (ev.type == Expose)
changedWindows.insert(ev.xexpose.window);
if (ev.type == VisibilityNotify)
changedWindows.insert(ev.xvisibility.window);
if (ev.type == DestroyNotify)
changedWindows.insert(ev.xdestroywindow.event);
}
XUnlockDisplay(disp());
}
bool windowWasReconfigured(Window win)
{
PLock lock(&changeLock);
auto it = changedWindows.find(win);
if (it != changedWindows.end()) {
changedWindows.erase(it);
return true;
}
return false;
}
}
PLock::PLock(pthread_mutex_t* mtx, bool trylock)
:m(mtx)
PLock::PLock(pthread_mutex_t *mtx, bool trylock) : m(mtx)
{
if (trylock)
islock = mtx && pthread_mutex_trylock(mtx) == 0;
@ -331,11 +299,9 @@ void PLock::lock()
}
}
static bool* curErrorTarget = 0;
static bool *curErrorTarget = 0;
static char curErrorText[200];
static int xerrorlock_handler(Display* disp, XErrorEvent* err)
static int xerrorlock_handler(Display *disp, XErrorEvent *err)
{
if (curErrorTarget)
@ -451,7 +417,6 @@ void XDisplayLock::unlock()
}
}
ObsGsContextHolder::ObsGsContextHolder()
{
obs_enter_graphics();

View file

@ -5,17 +5,15 @@
#define blog(level, msg, ...) blog(level, "xcompcap: " msg, ##__VA_ARGS__)
class PLock
{
class PLock {
pthread_mutex_t *m;
bool islock;
public:
PLock(const PLock&) = delete;
PLock& operator=(const PLock&) = delete;
public:
PLock(const PLock &) = delete;
PLock &operator=(const PLock &) = delete;
PLock(pthread_mutex_t* mtx, bool trylock = false);
PLock(pthread_mutex_t *mtx, bool trylock = false);
~PLock();
@ -25,15 +23,14 @@ class PLock
void lock();
};
class XErrorLock
{
class XErrorLock {
bool islock;
bool goterr;
XErrorHandler prevhandler;
public:
XErrorLock(const XErrorLock&) = delete;
XErrorLock& operator=(const XErrorLock&) = delete;
public:
XErrorLock(const XErrorLock &) = delete;
XErrorLock &operator=(const XErrorLock &) = delete;
XErrorLock();
~XErrorLock();
@ -48,13 +45,12 @@ class XErrorLock
void resetError();
};
class XDisplayLock
{
class XDisplayLock {
bool islock;
public:
XDisplayLock(const XDisplayLock&) = delete;
XDisplayLock& operator=(const XDisplayLock&) = delete;
public:
XDisplayLock(const XDisplayLock &) = delete;
XDisplayLock &operator=(const XDisplayLock &) = delete;
XDisplayLock();
~XDisplayLock();
@ -65,39 +61,37 @@ class XDisplayLock
void lock();
};
class ObsGsContextHolder
{
public:
ObsGsContextHolder(const ObsGsContextHolder&) = delete;
ObsGsContextHolder& operator=(const ObsGsContextHolder&) = delete;
class ObsGsContextHolder {
public:
ObsGsContextHolder(const ObsGsContextHolder &) = delete;
ObsGsContextHolder &operator=(const ObsGsContextHolder &) = delete;
ObsGsContextHolder();
~ObsGsContextHolder();
};
namespace XCompcap
namespace XCompcap {
Display *disp();
void cleanupDisplay();
std::string getWindowCommand(Window win);
int getRootWindowScreen(Window root);
std::string getWindowAtom(Window win, const char *atom);
int getWindowPid(Window win);
bool ewmhIsSupported();
std::list<Window> getTopLevelWindows();
std::list<Window> getAllWindows();
inline std::string getWindowName(Window win)
{
Display* disp();
void cleanupDisplay();
std::string getWindowCommand(Window win);
int getRootWindowScreen(Window root);
std::string getWindowAtom(Window win, const char *atom);
int getWindowPid(Window win);
bool ewmhIsSupported();
std::list<Window> getTopLevelWindows();
std::list<Window> getAllWindows();
inline std::string getWindowName(Window win)
{
return getWindowAtom(win, "_NET_WM_NAME");
}
inline std::string getWindowClass(Window win)
{
return getWindowAtom(win, "WM_CLASS");
}
void processEvents();
bool windowWasReconfigured(Window win);
return getWindowAtom(win, "_NET_WM_NAME");
}
inline std::string getWindowClass(Window win)
{
return getWindowAtom(win, "WM_CLASS");
}
void processEvents();
bool windowWasReconfigured(Window win);
}

View file

@ -35,7 +35,7 @@ bool XCompcapMain::init()
if (major == 0 && minor < 2) {
blog(LOG_ERROR, "Xcomposite extension is too old: %d.%d < 0.2",
major, minor);
major, minor);
return false;
}
@ -51,43 +51,41 @@ obs_properties_t *XCompcapMain::properties()
{
obs_properties_t *props = obs_properties_create();
obs_property_t *wins = obs_properties_add_list(props, "capture_window",
obs_module_text("Window"),
OBS_COMBO_TYPE_LIST, OBS_COMBO_FORMAT_STRING);
obs_property_t *wins = obs_properties_add_list(
props, "capture_window", obs_module_text("Window"),
OBS_COMBO_TYPE_LIST, OBS_COMBO_FORMAT_STRING);
for (Window win: XCompcap::getTopLevelWindows()) {
for (Window win : XCompcap::getTopLevelWindows()) {
std::string wname = XCompcap::getWindowName(win);
std::string cls = XCompcap::getWindowClass(win);
std::string winid = std::to_string((long long)win);
std::string desc =
(winid + WIN_STRING_DIV + wname +
WIN_STRING_DIV + cls);
(winid + WIN_STRING_DIV + wname + WIN_STRING_DIV + cls);
obs_property_list_add_string(wins, wname.c_str(),
desc.c_str());
obs_property_list_add_string(wins, wname.c_str(), desc.c_str());
}
obs_properties_add_int(props, "cut_top", obs_module_text("CropTop"),
0, 4096, 1);
obs_properties_add_int(props, "cut_top", obs_module_text("CropTop"), 0,
4096, 1);
obs_properties_add_int(props, "cut_left", obs_module_text("CropLeft"),
0, 4096, 1);
0, 4096, 1);
obs_properties_add_int(props, "cut_right", obs_module_text("CropRight"),
0, 4096, 1);
0, 4096, 1);
obs_properties_add_int(props, "cut_bot", obs_module_text("CropBottom"),
0, 4096, 1);
0, 4096, 1);
obs_properties_add_bool(props, "swap_redblue",
obs_module_text("SwapRedBlue"));
obs_module_text("SwapRedBlue"));
obs_properties_add_bool(props, "lock_x", obs_module_text("LockX"));
obs_properties_add_bool(props, "show_cursor",
obs_module_text("CaptureCursor"));
obs_module_text("CaptureCursor"));
obs_properties_add_bool(props, "include_border",
obs_module_text("IncludeXBorder"));
obs_module_text("IncludeXBorder"));
obs_properties_add_bool(props, "exclude_alpha",
obs_module_text("ExcludeAlpha"));
obs_module_text("ExcludeAlpha"));
return props;
}
@ -108,20 +106,24 @@ void XCompcapMain::defaults(obs_data_t *settings)
#define FIND_WINDOW_INTERVAL 2.0
struct XCompcapMain_private
{
struct XCompcapMain_private {
XCompcapMain_private()
:win(0)
,cut_top(0), cur_cut_top(0)
,cut_left(0), cur_cut_left(0)
,cut_right(0), cur_cut_right(0)
,cut_bot(0), cur_cut_bot(0)
,inverted(false)
,width(0),height(0)
,pixmap(0)
,glxpixmap(0)
,tex(0)
,gltex(0)
: win(0),
cut_top(0),
cur_cut_top(0),
cut_left(0),
cur_cut_left(0),
cut_right(0),
cur_cut_right(0),
cut_bot(0),
cur_cut_bot(0),
inverted(false),
width(0),
height(0),
pixmap(0),
glxpixmap(0),
tex(0),
gltex(0)
{
pthread_mutexattr_init(&lockattr);
pthread_mutexattr_settype(&lockattr, PTHREAD_MUTEX_RECURSIVE);
@ -169,7 +171,6 @@ struct XCompcapMain_private
xcursor_t *cursor = nullptr;
};
XCompcapMain::XCompcapMain(obs_data_t *settings, obs_source_t *source)
{
p = new XCompcapMain_private;
@ -231,7 +232,7 @@ static Window getWindowFromString(std::string wstr)
std::string wcls = wstr.substr(lastMark + markSize);
Window matchedNameWin = wid;
for (Window cwin: XCompcap::getTopLevelWindows()) {
for (Window cwin : XCompcap::getTopLevelWindows()) {
std::string cwinname = XCompcap::getWindowName(cwin);
std::string ccls = XCompcap::getWindowClass(cwin);
@ -249,38 +250,103 @@ static Window getWindowFromString(std::string wstr)
static void xcc_cleanup(XCompcapMain_private *p)
{
PLock lock(&p->lock);
XDisplayLock xlock;
XErrorLock xlock;
if (p->gltex) {
GLuint gltex = *(GLuint*)gs_texture_get_obj(p->gltex);
GLuint gltex = *(GLuint *)gs_texture_get_obj(p->gltex);
glBindTexture(GL_TEXTURE_2D, gltex);
glXReleaseTexImageEXT(xdisp, p->glxpixmap, GLX_FRONT_LEFT_EXT);
if (p->glxpixmap) {
glXReleaseTexImageEXT(xdisp, p->glxpixmap,
GLX_FRONT_LEFT_EXT);
if (xlock.gotError()) {
blog(LOG_ERROR,
"cleanup glXReleaseTexImageEXT failed: %s",
xlock.getErrorText().c_str());
xlock.resetError();
}
glXDestroyPixmap(xdisp, p->glxpixmap);
if (xlock.gotError()) {
blog(LOG_ERROR,
"cleanup glXDestroyPixmap failed: %s",
xlock.getErrorText().c_str());
xlock.resetError();
}
p->glxpixmap = 0;
}
gs_texture_destroy(p->gltex);
p->gltex = 0;
}
if (p->glxpixmap) {
glXDestroyPixmap(xdisp, p->glxpixmap);
p->glxpixmap = 0;
}
if (p->pixmap) {
XFreePixmap(xdisp, p->pixmap);
if (xlock.gotError()) {
blog(LOG_ERROR, "cleanup glXDestroyPixmap failed: %s",
xlock.getErrorText().c_str());
xlock.resetError();
}
p->pixmap = 0;
}
if (p->win) {
XCompositeUnredirectWindow(xdisp, p->win,
CompositeRedirectAutomatic);
CompositeRedirectAutomatic);
XSelectInput(xdisp, p->win, 0);
p->win = 0;
}
if (p->tex) {
gs_texture_destroy(p->tex);
p->tex = 0;
}
}
static gs_color_format gs_format_from_tex()
{
GLint iformat = 0;
// consider GL_ARB_internalformat_query
glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_INTERNAL_FORMAT,
&iformat);
// These formats are known to be wrong on Intel platforms. We intentionally
// use swapped internal formats here to preserve historic behavior which
// swapped colors accidentally and because D3D11 would not support a
// GS_RGBX format
switch (iformat) {
case GL_RGB:
return GS_BGRX;
case GL_RGBA:
return GS_RGBA;
default:
return GS_RGBA;
}
}
// from libobs-opengl/gl-subsystem.h because we need to handle GLX modifying textures outside libobs.
struct fb_info;
struct gs_texture {
gs_device_t *device;
enum gs_texture_type type;
enum gs_color_format format;
GLenum gl_format;
GLenum gl_target;
GLenum gl_internal_format;
GLenum gl_type;
GLuint texture;
uint32_t levels;
bool is_dynamic;
bool is_render_target;
bool is_dummy;
bool gen_mipmaps;
gs_samplerstate_t *cur_sampler;
struct fbo_info *fbo;
};
// End shitty hack.
void XCompcapMain::updateSettings(obs_data_t *settings)
{
PLock lock(&p->lock);
XErrorLock xlock;
ObsGsContextHolder obsctx;
blog(LOG_DEBUG, "Settings updating");
@ -290,8 +356,8 @@ void XCompcapMain::updateSettings(obs_data_t *settings)
xcc_cleanup(p);
if (settings) {
const char *windowName = obs_data_get_string(settings,
"capture_window");
const char *windowName =
obs_data_get_string(settings, "capture_window");
p->windowName = windowName;
p->win = getWindowFromString(windowName);
@ -303,30 +369,28 @@ void XCompcapMain::updateSettings(obs_data_t *settings)
p->lockX = obs_data_get_bool(settings, "lock_x");
p->swapRedBlue = obs_data_get_bool(settings, "swap_redblue");
p->show_cursor = obs_data_get_bool(settings, "show_cursor");
p->include_border = obs_data_get_bool(settings, "include_border");
p->include_border =
obs_data_get_bool(settings, "include_border");
p->exclude_alpha = obs_data_get_bool(settings, "exclude_alpha");
p->draw_opaque = false;
} else {
p->win = prevWin;
}
xlock.resetError();
XErrorLock xlock;
if (p->win)
XCompositeRedirectWindow(xdisp, p->win,
CompositeRedirectAutomatic);
CompositeRedirectAutomatic);
if (xlock.gotError()) {
blog(LOG_ERROR, "XCompositeRedirectWindow failed: %s",
xlock.getErrorText().c_str());
xlock.getErrorText().c_str());
return;
}
if (p->win)
XSelectInput(xdisp, p->win,
StructureNotifyMask
| ExposureMask
| VisibilityChangeMask);
StructureNotifyMask | ExposureMask |
VisibilityChangeMask);
XSync(xdisp, 0);
XWindowAttributes attr;
@ -342,75 +406,26 @@ void XCompcapMain::updateSettings(obs_data_t *settings)
int x, y;
XTranslateCoordinates(xdisp, p->win, attr.root, 0, 0, &x, &y,
&child);
&child);
xcursor_offset(p->cursor, x, y);
}
gs_color_format cf = GS_RGBA;
if (p->exclude_alpha) {
cf = GS_BGRX;
}
bool has_alpha = true;
const int attrs[] =
{
GLX_BIND_TO_TEXTURE_RGBA_EXT, GL_TRUE,
GLX_DRAWABLE_TYPE, GLX_PIXMAP_BIT,
GLX_BIND_TO_TEXTURE_TARGETS_EXT, GLX_TEXTURE_2D_BIT_EXT,
GLX_ALPHA_SIZE, 8,
GLX_DOUBLEBUFFER, GL_FALSE,
None
};
const int config_attrs[] = {GLX_BIND_TO_TEXTURE_RGBA_EXT,
GL_TRUE,
GLX_DRAWABLE_TYPE,
GLX_PIXMAP_BIT,
GLX_BIND_TO_TEXTURE_TARGETS_EXT,
GLX_TEXTURE_2D_BIT_EXT,
GLX_DOUBLEBUFFER,
GL_FALSE,
None};
int nelem = 0;
GLXFBConfig *configs = glXGetFBConfigs(xdisp,
XCompcap::getRootWindowScreen(attr.root),
&nelem);
GLXFBConfig *configs = glXChooseFBConfig(
xdisp, XCompcap::getRootWindowScreen(attr.root), config_attrs,
&nelem);
if (nelem <= 0) {
blog(LOG_ERROR, "no fb configs available");
p->win = 0;
p->height = 0;
p->width = 0;
return;
}
GLXFBConfig config;
for (int i = 0; i < nelem; i++) {
config = configs[i];
XVisualInfo *visual = glXGetVisualFromFBConfig(xdisp, config);
if (!visual)
continue;
if (attr.visual->visualid != visual->visualid) {
XFree(visual);
continue;
}
XFree(visual);
int value;
glXGetFBConfigAttrib(xdisp, config, GLX_ALPHA_SIZE, &value);
if (value != 8)
has_alpha = false;
break;
}
XFree(configs);
configs = glXChooseFBConfig(xdisp,
XCompcap::getRootWindowScreen(attr.root),
attrs, &nelem);
if (nelem <= 0) {
blog(LOG_ERROR, "no matching fb config found");
p->win = 0;
p->height = 0;
p->width = 0;
return;
}
bool found = false;
GLXFBConfig config;
for (int i = 0; i < nelem; i++) {
config = configs[i];
XVisualInfo *visual = glXGetVisualFromFBConfig(xdisp, config);
@ -425,10 +440,16 @@ void XCompcapMain::updateSettings(obs_data_t *settings)
found = true;
break;
}
if (!found)
config = configs[0];
if (!found) {
blog(LOG_ERROR, "no matching fb config found");
p->win = 0;
p->height = 0;
p->width = 0;
XFree(configs);
return;
}
if (cf == GS_BGRX || !has_alpha) {
if (p->exclude_alpha || attr.depth != 32) {
p->draw_opaque = true;
}
@ -462,93 +483,83 @@ void XCompcapMain::updateSettings(obs_data_t *settings)
p->cur_cut_right = 0;
}
if (p->tex)
gs_texture_destroy(p->tex);
uint8_t *texData = new uint8_t[width() * height() * 4];
memset(texData, 0, width() * height() * 4);
const uint8_t* texDataArr[] = { texData, 0 };
p->tex = gs_texture_create(width(), height(), cf, 1,
texDataArr, 0);
delete[] texData;
if (p->swapRedBlue) {
GLuint tex = *(GLuint*)gs_texture_get_obj(p->tex);
glBindTexture(GL_TEXTURE_2D, tex);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_B, GL_RED);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_R, GL_BLUE);
glBindTexture(GL_TEXTURE_2D, 0);
}
// Precautionary since we dont error check every GLX call above.
xlock.resetError();
p->pixmap = XCompositeNameWindowPixmap(xdisp, p->win);
if (xlock.gotError()) {
blog(LOG_ERROR, "XCompositeNameWindowPixmap failed: %s",
xlock.getErrorText().c_str());
xlock.getErrorText().c_str());
p->pixmap = 0;
XFree(configs);
return;
}
const int attribs_alpha[] =
{
GLX_TEXTURE_TARGET_EXT, GLX_TEXTURE_2D_EXT,
GLX_TEXTURE_FORMAT_EXT, GLX_TEXTURE_FORMAT_RGBA_EXT,
None
};
const int attribs_no_alpha[] =
{
GLX_TEXTURE_TARGET_EXT, GLX_TEXTURE_2D_EXT,
GLX_TEXTURE_FORMAT_EXT, GLX_TEXTURE_FORMAT_RGB_EXT,
None
};
const int *attribs = cf == GS_RGBA ? attribs_alpha : attribs_no_alpha;
p->glxpixmap = glXCreatePixmap(xdisp, config, p->pixmap, attribs);
// Should be consistent format with config we are using. Since we searched on RGBA lets use RGBA here.
const int pixmap_attrs[] = {GLX_TEXTURE_TARGET_EXT, GLX_TEXTURE_2D_EXT,
GLX_TEXTURE_FORMAT_EXT,
GLX_TEXTURE_FORMAT_RGBA_EXT, None};
p->glxpixmap = glXCreatePixmap(xdisp, config, p->pixmap, pixmap_attrs);
if (xlock.gotError()) {
blog(LOG_ERROR, "glXCreatePixmap failed: %s",
xlock.getErrorText().c_str());
xlock.getErrorText().c_str());
XFreePixmap(xdisp, p->pixmap);
XFree(configs);
p->pixmap = 0;
p->glxpixmap = 0;
return;
}
XFree(configs);
p->gltex = gs_texture_create(p->width, p->height, cf, 1, 0,
GS_GL_DUMMYTEX);
GLuint gltex = *(GLuint*)gs_texture_get_obj(p->gltex);
// Build an OBS texture to bind the pixmap to.
p->gltex = gs_texture_create(p->width, p->height, GS_RGBA, 1, 0,
GS_GL_DUMMYTEX);
GLuint gltex = *(GLuint *)gs_texture_get_obj(p->gltex);
glBindTexture(GL_TEXTURE_2D, gltex);
glXBindTexImageEXT(xdisp, p->glxpixmap, GLX_FRONT_LEFT_EXT, NULL);
if (xlock.gotError()) {
blog(LOG_ERROR, "glXBindTexImageEXT failed: %s",
xlock.getErrorText().c_str());
XFreePixmap(xdisp, p->pixmap);
XFree(configs);
p->pixmap = 0;
p->glxpixmap = 0;
return;
}
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
// glxBindTexImageEXT might modify the textures format.
gs_color_format format = gs_format_from_tex();
glBindTexture(GL_TEXTURE_2D, 0);
// sync OBS texture format based on any glxBindTexImageEXT changes
p->gltex->format = format;
// Create a pure OBS texture to use for rendering. Using the same
// format so we can copy instead of drawing from the source gltex.
if (p->tex)
gs_texture_destroy(p->tex);
p->tex = gs_texture_create(width(), height(), format, 1, 0,
GS_GL_DUMMYTEX);
if (p->swapRedBlue) {
GLuint tex = *(GLuint *)gs_texture_get_obj(p->tex);
glBindTexture(GL_TEXTURE_2D, tex);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_B, GL_RED);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_R, GL_BLUE);
glBindTexture(GL_TEXTURE_2D, 0);
}
if (!p->windowName.empty()) {
blog(LOG_INFO, "[window-capture: '%s'] update settings:\n"
"\ttitle: %s\n"
"\tclass: %s\n"
"\tHas alpha: %s\n"
"\tFound proper GLXFBConfig: %s\n",
obs_source_get_name(p->source),
XCompcap::getWindowName(p->win).c_str(),
XCompcap::getWindowClass(p->win).c_str(),
has_alpha ? "yes" : "no",
found ? "yes" : "no");
blog(LOG_DEBUG, "\n"
"\tid: %s",
std::to_string((long long)p->win).c_str());
blog(LOG_INFO,
"[window-capture: '%s'] update settings:\n"
"\ttitle: %s\n"
"\tclass: %s\n"
"\tBit depth: %i\n"
"\tFound proper GLXFBConfig (in %i): %s\n",
obs_source_get_name(p->source),
XCompcap::getWindowName(p->win).c_str(),
XCompcap::getWindowClass(p->win).c_str(), attr.depth,
nelem, found ? "yes" : "no");
}
}
@ -596,33 +607,28 @@ void XCompcapMain::tick(float seconds)
obs_enter_graphics();
if (p->lockX) {
// XDisplayLock is still live so we should already be locked.
XLockDisplay(xdisp);
XSync(xdisp, 0);
}
if (p->include_border) {
gs_copy_texture_region(
p->tex, 0, 0,
p->gltex,
p->cur_cut_left,
p->cur_cut_top,
width(), height());
gs_copy_texture_region(p->tex, 0, 0, p->gltex, p->cur_cut_left,
p->cur_cut_top, width(), height());
} else {
gs_copy_texture_region(
p->tex, 0, 0,
p->gltex,
p->cur_cut_left + p->border,
p->cur_cut_top + p->border,
width(), height());
gs_copy_texture_region(p->tex, 0, 0, p->gltex,
p->cur_cut_left + p->border,
p->cur_cut_top + p->border, width(),
height());
}
if (p->cursor && p->show_cursor) {
xcursor_tick(p->cursor);
p->cursor_outside =
p->cursor->x < p->cur_cut_left ||
p->cursor->y < p->cur_cut_top ||
p->cursor->x > int(p->width - p->cur_cut_right) ||
p->cursor->x < p->cur_cut_left ||
p->cursor->y < p->cur_cut_top ||
p->cursor->x > int(p->width - p->cur_cut_right) ||
p->cursor->y > int(p->height - p->cur_cut_bot);
}

View file

@ -2,9 +2,8 @@
struct XCompcapMain_private;
class XCompcapMain
{
public:
class XCompcapMain {
public:
static bool init();
static void deinit();
@ -22,6 +21,6 @@ class XCompcapMain
uint32_t width();
uint32_t height();
private:
private:
XCompcapMain_private *p;
};

View file

@ -2,38 +2,38 @@
#include "xcompcap-main.hpp"
static void* xcompcap_create(obs_data_t *settings, obs_source_t *source)
static void *xcompcap_create(obs_data_t *settings, obs_source_t *source)
{
return new XCompcapMain(settings, source);
}
static void xcompcap_destroy(void *data)
{
XCompcapMain* cc = (XCompcapMain*)data;
XCompcapMain *cc = (XCompcapMain *)data;
delete cc;
}
static void xcompcap_video_tick(void* data, float seconds)
static void xcompcap_video_tick(void *data, float seconds)
{
XCompcapMain* cc = (XCompcapMain*)data;
XCompcapMain *cc = (XCompcapMain *)data;
cc->tick(seconds);
}
static void xcompcap_video_render(void* data, gs_effect_t *effect)
static void xcompcap_video_render(void *data, gs_effect_t *effect)
{
XCompcapMain* cc = (XCompcapMain*)data;
XCompcapMain *cc = (XCompcapMain *)data;
cc->render(effect);
}
static uint32_t xcompcap_getwidth(void* data)
static uint32_t xcompcap_getwidth(void *data)
{
XCompcapMain* cc = (XCompcapMain*)data;
XCompcapMain *cc = (XCompcapMain *)data;
return cc->width();
}
static uint32_t xcompcap_getheight(void* data)
static uint32_t xcompcap_getheight(void *data)
{
XCompcapMain* cc = (XCompcapMain*)data;
XCompcapMain *cc = (XCompcapMain *)data;
return cc->height();
}
@ -51,11 +51,11 @@ void xcompcap_defaults(obs_data_t *settings)
void xcompcap_update(void *data, obs_data_t *settings)
{
XCompcapMain* cc = (XCompcapMain*)data;
XCompcapMain *cc = (XCompcapMain *)data;
cc->updateSettings(settings);
}
static const char* xcompcap_getname(void*)
static const char *xcompcap_getname(void *)
{
return obs_module_text("XCCapture");
}
@ -69,20 +69,19 @@ extern "C" void xcomposite_load(void)
memset(&sinfo, 0, sizeof(obs_source_info));
sinfo.id = "xcomposite_input";
sinfo.output_flags = OBS_SOURCE_VIDEO |
OBS_SOURCE_CUSTOM_DRAW |
OBS_SOURCE_DO_NOT_DUPLICATE;
sinfo.output_flags = OBS_SOURCE_VIDEO | OBS_SOURCE_CUSTOM_DRAW |
OBS_SOURCE_DO_NOT_DUPLICATE;
sinfo.get_name = xcompcap_getname;
sinfo.create = xcompcap_create;
sinfo.destroy = xcompcap_destroy;
sinfo.get_name = xcompcap_getname;
sinfo.create = xcompcap_create;
sinfo.destroy = xcompcap_destroy;
sinfo.get_properties = xcompcap_props;
sinfo.get_defaults = xcompcap_defaults;
sinfo.update = xcompcap_update;
sinfo.video_tick = xcompcap_video_tick;
sinfo.video_render = xcompcap_video_render;
sinfo.get_width = xcompcap_getwidth;
sinfo.get_height = xcompcap_getheight;
sinfo.get_defaults = xcompcap_defaults;
sinfo.update = xcompcap_update;
sinfo.video_tick = xcompcap_video_tick;
sinfo.video_render = xcompcap_video_render;
sinfo.get_width = xcompcap_getwidth;
sinfo.get_height = xcompcap_getheight;
obs_register_source(&sinfo);
}

View file

@ -26,26 +26,27 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
* size or by creating a new texture if the size is different
*/
static void xcb_xcursor_create(xcb_xcursor_t *data,
xcb_xfixes_get_cursor_image_reply_t *xc)
xcb_xfixes_get_cursor_image_reply_t *xc)
{
uint32_t *pixels = xcb_xfixes_get_cursor_image_cursor_image(xc);
if (!pixels)
return;
if (data->tex && data->last_height == xc->width &&
data->last_width == xc->height) {
gs_texture_set_image(data->tex, (const uint8_t *) pixels,
xc->width * sizeof(uint32_t), false);
data->last_width == xc->height) {
gs_texture_set_image(data->tex, (const uint8_t *)pixels,
xc->width * sizeof(uint32_t), false);
} else {
if (data->tex)
gs_texture_destroy(data->tex);
data->tex = gs_texture_create(xc->width, xc->height,
GS_BGRA, 1, (const uint8_t **) &pixels, GS_DYNAMIC);
data->tex = gs_texture_create(xc->width, xc->height, GS_BGRA, 1,
(const uint8_t **)&pixels,
GS_DYNAMIC);
}
data->last_serial = xc->cursor_serial;
data->last_width = xc->width;
data->last_width = xc->width;
data->last_height = xc->height;
}
@ -58,8 +59,8 @@ xcb_xcursor_t *xcb_xcursor_init(xcb_connection_t *xcb)
xcb_xfixes_query_version_cookie_t xfix_c;
xfix_c = xcb_xfixes_query_version_unchecked(xcb,
XCB_XFIXES_MAJOR_VERSION, XCB_XFIXES_MINOR_VERSION);
xfix_c = xcb_xfixes_query_version_unchecked(
xcb, XCB_XFIXES_MAJOR_VERSION, XCB_XFIXES_MINOR_VERSION);
free(xcb_xfixes_query_version_reply(xcb, xfix_c, NULL));
return data;
@ -73,7 +74,7 @@ void xcb_xcursor_destroy(xcb_xcursor_t *data)
}
void xcb_xcursor_update(xcb_xcursor_t *data,
xcb_xfixes_get_cursor_image_reply_t *xc)
xcb_xfixes_get_cursor_image_reply_t *xc)
{
if (!data || !xc)
return;
@ -81,8 +82,8 @@ void xcb_xcursor_update(xcb_xcursor_t *data,
if (!data->tex || data->last_serial != xc->cursor_serial)
xcb_xcursor_create(data, xc);
data->x = xc->x - data->x_org;
data->y = xc->y - data->y_org;
data->x = xc->x - data->x_org;
data->y = xc->y - data->y_org;
data->x_render = data->x - xc->xhot;
data->y_render = data->y - xc->yhot;
}
@ -92,7 +93,7 @@ void xcb_xcursor_render(xcb_xcursor_t *data)
if (!data->tex)
return;
gs_effect_t *effect = gs_get_effect();
gs_effect_t *effect = gs_get_effect();
gs_eparam_t *image = gs_effect_get_param_by_name(effect, "image");
gs_effect_set_texture(image, data->tex);
@ -109,9 +110,8 @@ void xcb_xcursor_render(xcb_xcursor_t *data)
gs_blend_state_pop();
}
void xcb_xcursor_offset(xcb_xcursor_t* data, const int x_org, const int y_org)
void xcb_xcursor_offset(xcb_xcursor_t *data, const int x_org, const int y_org)
{
data->x_org = x_org;
data->y_org = y_org;
}

View file

@ -30,12 +30,12 @@ typedef struct {
unsigned int last_height;
gs_texture_t *tex;
int x;
int y;
int x_org;
int y_org;
float x_render;
float y_render;
int x;
int y;
int x_org;
int y_org;
float x_render;
float y_render;
} xcb_xcursor_t;
/**
@ -60,7 +60,7 @@ void xcb_xcursor_destroy(xcb_xcursor_t *data);
*
*/
void xcb_xcursor_update(xcb_xcursor_t *data,
xcb_xfixes_get_cursor_image_reply_t *xc);
xcb_xfixes_get_cursor_image_reply_t *xc);
/**
* Draw the cursor

View file

@ -28,12 +28,13 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
* Theres a lot of talk about this in other implementation and they tend to
* be really complicated, but this naive approach seems to work fine ...
*/
static uint32_t *xcursor_pixels(XFixesCursorImage *xc) {
static uint32_t *xcursor_pixels(XFixesCursorImage *xc)
{
uint_fast32_t size = xc->width * xc->height;
uint32_t *pixels = bmalloc(size * sizeof(uint32_t));
for (uint_fast32_t i = 0; i < size; ++i)
pixels[i] = (uint32_t) xc->pixels[i];
pixels[i] = (uint32_t)xc->pixels[i];
return pixels;
}
@ -42,22 +43,23 @@ static uint32_t *xcursor_pixels(XFixesCursorImage *xc) {
* Create the cursor texture, either by updating if the new cursor has the same
* size or by creating a new texture if the size is different
*/
static void xcursor_create(xcursor_t *data, XFixesCursorImage *xc) {
static void xcursor_create(xcursor_t *data, XFixesCursorImage *xc)
{
uint32_t *pixels = xcursor_pixels(xc);
if (!pixels)
return;
if (data->tex
&& data->last_height == xc->width
&& data->last_width == xc->height) {
gs_texture_set_image(data->tex, (const uint8_t *) pixels,
xc->width * sizeof(uint32_t), False);
if (data->tex && data->last_height == xc->width &&
data->last_width == xc->height) {
gs_texture_set_image(data->tex, (const uint8_t *)pixels,
xc->width * sizeof(uint32_t), False);
} else {
if (data->tex)
gs_texture_destroy(data->tex);
data->tex = gs_texture_create(xc->width, xc->height,
GS_BGRA, 1, (const uint8_t **) &pixels, GS_DYNAMIC);
data->tex = gs_texture_create(xc->width, xc->height, GS_BGRA, 1,
(const uint8_t **)&pixels,
GS_DYNAMIC);
}
bfree(pixels);
@ -67,7 +69,8 @@ static void xcursor_create(xcursor_t *data, XFixesCursorImage *xc) {
data->last_height = xc->height;
}
xcursor_t *xcursor_init(Display *dpy) {
xcursor_t *xcursor_init(Display *dpy)
{
xcursor_t *data = bzalloc(sizeof(xcursor_t));
data->dpy = dpy;
@ -76,13 +79,15 @@ xcursor_t *xcursor_init(Display *dpy) {
return data;
}
void xcursor_destroy(xcursor_t *data) {
void xcursor_destroy(xcursor_t *data)
{
if (data->tex)
gs_texture_destroy(data->tex);
bfree(data);
}
void xcursor_tick(xcursor_t *data) {
void xcursor_tick(xcursor_t *data)
{
XFixesCursorImage *xc = XFixesGetCursorImage(data->dpy);
if (!xc)
return;
@ -98,11 +103,12 @@ void xcursor_tick(xcursor_t *data) {
XFree(xc);
}
void xcursor_render(xcursor_t *data) {
void xcursor_render(xcursor_t *data)
{
if (!data->tex)
return;
gs_effect_t *effect = gs_get_effect();
gs_effect_t *effect = gs_get_effect();
gs_eparam_t *image = gs_effect_get_param_by_name(effect, "image");
gs_effect_set_texture(image, data->tex);
@ -119,9 +125,8 @@ void xcursor_render(xcursor_t *data) {
gs_blend_state_pop();
}
void xcursor_offset(xcursor_t* data, int_fast32_t x_org, int_fast32_t y_org)
void xcursor_offset(xcursor_t *data, int_fast32_t x_org, int_fast32_t y_org)
{
data->x_org = x_org;
data->y_org = y_org;
}

View file

@ -30,7 +30,7 @@ bool xinerama_is_active(xcb_connection_t *xcb)
bool active = true;
xcb_xinerama_is_active_cookie_t xnr_c;
xcb_xinerama_is_active_reply_t *xnr_r;
xcb_xinerama_is_active_reply_t *xnr_r;
xnr_c = xcb_xinerama_is_active_unchecked(xcb);
xnr_r = xcb_xinerama_is_active_reply(xcb, xnr_c, NULL);
@ -48,7 +48,7 @@ int xinerama_screen_count(xcb_connection_t *xcb)
int screens = 0;
xcb_xinerama_query_screens_cookie_t scr_c;
xcb_xinerama_query_screens_reply_t *scr_r;
xcb_xinerama_query_screens_reply_t *scr_r;
scr_c = xcb_xinerama_query_screens_unchecked(xcb);
scr_r = xcb_xinerama_query_screens_reply(xcb, scr_c, NULL);
@ -60,15 +60,15 @@ int xinerama_screen_count(xcb_connection_t *xcb)
}
int xinerama_screen_geo(xcb_connection_t *xcb, int_fast32_t screen,
int_fast32_t *x, int_fast32_t *y,
int_fast32_t *w, int_fast32_t *h)
int_fast32_t *x, int_fast32_t *y, int_fast32_t *w,
int_fast32_t *h)
{
if (!xcb)
goto fail;
bool success = false;
xcb_xinerama_query_screens_cookie_t scr_c;
xcb_xinerama_query_screens_reply_t *scr_r;
xcb_xinerama_query_screens_reply_t *scr_r;
xcb_xinerama_screen_info_iterator_t iter;
scr_c = xcb_xinerama_query_screens_unchecked(xcb);
@ -113,7 +113,7 @@ int randr_screen_count(xcb_connection_t *xcb)
screen = xcb_setup_roots_iterator(xcb_get_setup(xcb)).data;
xcb_randr_get_screen_resources_cookie_t res_c;
xcb_randr_get_screen_resources_reply_t* res_r;
xcb_randr_get_screen_resources_reply_t *res_r;
res_c = xcb_randr_get_screen_resources(xcb, screen->root);
res_r = xcb_randr_get_screen_resources_reply(xcb, res_c, 0);
@ -124,15 +124,14 @@ int randr_screen_count(xcb_connection_t *xcb)
}
int randr_screen_geo(xcb_connection_t *xcb, int_fast32_t screen,
int_fast32_t *x, int_fast32_t *y,
int_fast32_t *w, int_fast32_t *h,
xcb_screen_t **rscreen)
int_fast32_t *x, int_fast32_t *y, int_fast32_t *w,
int_fast32_t *h, xcb_screen_t **rscreen)
{
xcb_screen_t *xscreen;
xscreen = xcb_setup_roots_iterator(xcb_get_setup(xcb)).data;
xcb_randr_get_screen_resources_cookie_t res_c;
xcb_randr_get_screen_resources_reply_t* res_r;
xcb_randr_get_screen_resources_reply_t *res_r;
res_c = xcb_randr_get_screen_resources(xcb, xscreen->root);
res_r = xcb_randr_get_screen_resources_reply(xcb, res_c, 0);
@ -168,8 +167,8 @@ fail:
return -1;
}
int x11_screen_geo(xcb_connection_t *xcb, int_fast32_t screen,
int_fast32_t *w, int_fast32_t *h)
int x11_screen_geo(xcb_connection_t *xcb, int_fast32_t screen, int_fast32_t *w,
int_fast32_t *h)
{
if (!xcb)
goto fail;
@ -194,14 +193,14 @@ fail:
return -1;
}
xcb_shm_t* xshm_xcb_attach(xcb_connection_t *xcb, const int w, const int h)
xcb_shm_t *xshm_xcb_attach(xcb_connection_t *xcb, const int w, const int h)
{
if (!xcb)
return NULL;
xcb_shm_t *shm = bzalloc(sizeof(xcb_shm_t));
shm->xcb = xcb;
shm->seg = xcb_generate_id(shm->xcb);
shm->xcb = xcb;
shm->seg = xcb_generate_id(shm->xcb);
shm->shmid = shmget(IPC_PRIVATE, w * h * 4, IPC_CREAT | 0777);
if (shm->shmid == -1)
@ -224,7 +223,7 @@ void xshm_xcb_detach(xcb_shm_t *shm)
xcb_shm_detach(shm->xcb, shm->seg);
if ((char *) shm->data != (char *) -1)
if ((char *)shm->data != (char *)-1)
shmdt(shm->data);
if (shm->shmid != -1)

View file

@ -27,9 +27,9 @@ extern "C" {
typedef struct {
xcb_connection_t *xcb;
xcb_shm_seg_t seg;
int shmid;
uint8_t *data;
xcb_shm_seg_t seg;
int shmid;
uint8_t *data;
} xcb_shm_t;
/**
@ -61,8 +61,8 @@ int xinerama_screen_count(xcb_connection_t *xcb);
* @return < 0 on error
*/
int xinerama_screen_geo(xcb_connection_t *xcb, int_fast32_t screen,
int_fast32_t *x, int_fast32_t *y,
int_fast32_t *w, int_fast32_t *h);
int_fast32_t *x, int_fast32_t *y, int_fast32_t *w,
int_fast32_t *h);
/**
* Check for Randr extension
@ -93,9 +93,8 @@ int randr_screen_count(xcb_connection_t *xcb);
* @return < 0 on error
*/
int randr_screen_geo(xcb_connection_t *xcb, int_fast32_t screen,
int_fast32_t *x, int_fast32_t *y,
int_fast32_t *w, int_fast32_t *h,
xcb_screen_t **rscreen);
int_fast32_t *x, int_fast32_t *y, int_fast32_t *w,
int_fast32_t *h, xcb_screen_t **rscreen);
/**
* Get screen geometry for a X11 screen
@ -109,8 +108,8 @@ int randr_screen_geo(xcb_connection_t *xcb, int_fast32_t screen,
*
* @return < 0 on error
*/
int x11_screen_geo(xcb_connection_t *xcb, int_fast32_t screen,
int_fast32_t *w, int_fast32_t *h);
int x11_screen_geo(xcb_connection_t *xcb, int_fast32_t screen, int_fast32_t *w,
int_fast32_t *h);
/**
* Attach a shared memory segment to the X-Server

View file

@ -33,26 +33,26 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#define blog(level, msg, ...) blog(level, "xshm-input: " msg, ##__VA_ARGS__)
struct xshm_data {
obs_source_t *source;
obs_source_t *source;
xcb_connection_t *xcb;
xcb_screen_t *xcb_screen;
xcb_shm_t *xshm;
xcb_xcursor_t *cursor;
xcb_screen_t *xcb_screen;
xcb_shm_t *xshm;
xcb_xcursor_t *cursor;
char *server;
uint_fast32_t screen_id;
int_fast32_t x_org;
int_fast32_t y_org;
int_fast32_t width;
int_fast32_t height;
char *server;
uint_fast32_t screen_id;
int_fast32_t x_org;
int_fast32_t y_org;
int_fast32_t width;
int_fast32_t height;
gs_texture_t *texture;
gs_texture_t *texture;
bool show_cursor;
bool use_xinerama;
bool use_randr;
bool advanced;
bool show_cursor;
bool use_xinerama;
bool use_randr;
bool advanced;
};
/**
@ -66,8 +66,8 @@ static inline void xshm_resize_texture(struct xshm_data *data)
{
if (data->texture)
gs_texture_destroy(data->texture);
data->texture = gs_texture_create(data->width, data->height,
GS_BGRA, 1, NULL, GS_DYNAMIC);
data->texture = gs_texture_create(data->width, data->height, GS_BGRA, 1,
NULL, GS_DYNAMIC);
}
/**
@ -102,26 +102,23 @@ static int_fast32_t xshm_update_geometry(struct xshm_data *data)
int_fast32_t old_height = data->height;
if (data->use_randr) {
if (randr_screen_geo(data->xcb, data->screen_id,
&data->x_org, &data->y_org,
&data->width, &data->height,
&data->xcb_screen) < 0) {
if (randr_screen_geo(data->xcb, data->screen_id, &data->x_org,
&data->y_org, &data->width, &data->height,
&data->xcb_screen) < 0) {
return -1;
}
}
else if (data->use_xinerama) {
} else if (data->use_xinerama) {
if (xinerama_screen_geo(data->xcb, data->screen_id,
&data->x_org, &data->y_org,
&data->width, &data->height) < 0) {
&data->x_org, &data->y_org,
&data->width, &data->height) < 0) {
return -1;
}
data->xcb_screen = xcb_get_screen(data->xcb, 0);
}
else {
} else {
data->x_org = 0;
data->y_org = 0;
if (x11_screen_geo(data->xcb, data->screen_id,
&data->width, &data->height) < 0) {
if (x11_screen_geo(data->xcb, data->screen_id, &data->width,
&data->height) < 0) {
return -1;
}
data->xcb_screen = xcb_get_screen(data->xcb, data->screen_id);
@ -132,9 +129,10 @@ static int_fast32_t xshm_update_geometry(struct xshm_data *data)
return -1;
}
blog(LOG_INFO, "Geometry %"PRIdFAST32"x%"PRIdFAST32
" @ %"PRIdFAST32",%"PRIdFAST32,
data->width, data->height, data->x_org, data->y_org);
blog(LOG_INFO,
"Geometry %" PRIdFAST32 "x%" PRIdFAST32 " @ %" PRIdFAST32
",%" PRIdFAST32,
data->width, data->height, data->x_org, data->y_org);
if (old_width == data->width && old_height == data->height)
return 0;
@ -145,7 +143,7 @@ static int_fast32_t xshm_update_geometry(struct xshm_data *data)
/**
* Returns the name of the plugin
*/
static const char* xshm_getname(void *unused)
static const char *xshm_getname(void *unused)
{
UNUSED_PARAMETER(unused);
return obs_module_text("X11SharedMemoryScreenInput");
@ -190,8 +188,8 @@ static void xshm_capture_stop(struct xshm_data *data)
*/
static void xshm_capture_start(struct xshm_data *data)
{
const char *server = (data->advanced && *data->server)
? data->server : NULL;
const char *server = (data->advanced && *data->server) ? data->server
: NULL;
data->xcb = xcb_connect(server, NULL);
if (!data->xcb || xcb_connection_has_error(data->xcb)) {
@ -239,10 +237,10 @@ static void xshm_update(void *vptr, obs_data_t *settings)
xshm_capture_stop(data);
data->screen_id = obs_data_get_int(settings, "screen");
data->screen_id = obs_data_get_int(settings, "screen");
data->show_cursor = obs_data_get_bool(settings, "show_cursor");
data->advanced = obs_data_get_bool(settings, "advanced");
data->server = bstrdup(obs_data_get_string(settings, "server"));
data->advanced = obs_data_get_bool(settings, "advanced");
data->server = bstrdup(obs_data_get_string(settings, "server"));
xshm_capture_start(data);
}
@ -260,11 +258,11 @@ static void xshm_defaults(obs_data_t *defaults)
/**
* Toggle visibility of advanced settings
*/
static bool xshm_toggle_advanced(obs_properties_t *props,
obs_property_t *p, obs_data_t *settings)
static bool xshm_toggle_advanced(obs_properties_t *props, obs_property_t *p,
obs_data_t *settings)
{
UNUSED_PARAMETER(p);
const bool visible = obs_data_get_bool(settings, "advanced");
const bool visible = obs_data_get_bool(settings, "advanced");
obs_property_t *server = obs_properties_get(props, "server");
obs_property_set_visible(server, visible);
@ -278,14 +276,14 @@ static bool xshm_toggle_advanced(obs_properties_t *props,
/**
* The x server was changed
*/
static bool xshm_server_changed(obs_properties_t *props,
obs_property_t *p, obs_data_t *settings)
static bool xshm_server_changed(obs_properties_t *props, obs_property_t *p,
obs_data_t *settings)
{
UNUSED_PARAMETER(p);
bool advanced = obs_data_get_bool(settings, "advanced");
bool advanced = obs_data_get_bool(settings, "advanced");
int_fast32_t old_screen = obs_data_get_int(settings, "screen");
const char *server = obs_data_get_string(settings, "server");
const char *server = obs_data_get_string(settings, "server");
obs_property_t *screens = obs_properties_get(props, "screen");
/* we want a real NULL here in case there is no string here */
@ -303,11 +301,11 @@ static bool xshm_server_changed(obs_properties_t *props,
dstr_init(&screen_info);
bool randr = randr_is_active(xcb);
bool xinerama = xinerama_is_active(xcb);
int_fast32_t count = (randr) ?
randr_screen_count(xcb) :
(xinerama) ?
xinerama_screen_count(xcb) :
xcb_setup_roots_length(xcb_get_setup(xcb));
int_fast32_t count =
(randr) ? randr_screen_count(xcb)
: (xinerama)
? xinerama_screen_count(xcb)
: xcb_setup_roots_length(xcb_get_setup(xcb));
for (int_fast32_t i = 0; i < count; ++i) {
int_fast32_t x, y, w, h;
@ -320,21 +318,22 @@ static bool xshm_server_changed(obs_properties_t *props,
else
x11_screen_geo(xcb, i, &w, &h);
dstr_printf(&screen_info, "Screen %"PRIuFAST32" (%"PRIuFAST32
"x%"PRIuFAST32" @ %"PRIuFAST32
",%"PRIuFAST32")", i, w, h, x, y);
dstr_printf(&screen_info,
"Screen %" PRIuFAST32 " (%" PRIuFAST32
"x%" PRIuFAST32 " @ %" PRIuFAST32 ",%" PRIuFAST32
")",
i, w, h, x, y);
obs_property_list_add_int(screens, screen_info.array, i);
}
/* handle missing screen */
if (old_screen + 1 > count) {
dstr_printf(&screen_info, "Screen %"PRIuFAST32" (not found)",
old_screen);
size_t index = obs_property_list_add_int(screens,
screen_info.array, old_screen);
dstr_printf(&screen_info, "Screen %" PRIuFAST32 " (not found)",
old_screen);
size_t index = obs_property_list_add_int(
screens, screen_info.array, old_screen);
obs_property_list_item_disable(screens, index, true);
}
dstr_free(&screen_info);
@ -355,13 +354,13 @@ static obs_properties_t *xshm_properties(void *vptr)
obs_properties_t *props = obs_properties_create();
obs_properties_add_list(props, "screen", obs_module_text("Screen"),
OBS_COMBO_TYPE_LIST, OBS_COMBO_FORMAT_INT);
OBS_COMBO_TYPE_LIST, OBS_COMBO_FORMAT_INT);
obs_properties_add_bool(props, "show_cursor",
obs_module_text("CaptureCursor"));
obs_property_t *advanced = obs_properties_add_bool(props, "advanced",
obs_module_text("AdvancedSettings"));
obs_property_t *server = obs_properties_add_text(props, "server",
obs_module_text("XServer"), OBS_TEXT_DEFAULT);
obs_module_text("CaptureCursor"));
obs_property_t *advanced = obs_properties_add_bool(
props, "advanced", obs_module_text("AdvancedSettings"));
obs_property_t *server = obs_properties_add_text(
props, "server", obs_module_text("XServer"), OBS_TEXT_DEFAULT);
obs_property_set_modified_callback(advanced, xshm_toggle_advanced);
obs_property_set_modified_callback(server, xshm_server_changed);
@ -415,14 +414,16 @@ static void xshm_video_tick(void *vptr, float seconds)
if (!obs_source_showing(data->source))
return;
xcb_shm_get_image_cookie_t img_c;
xcb_shm_get_image_reply_t *img_r;
xcb_shm_get_image_cookie_t img_c;
xcb_shm_get_image_reply_t *img_r;
xcb_xfixes_get_cursor_image_cookie_t cur_c;
xcb_xfixes_get_cursor_image_reply_t *cur_r;
xcb_xfixes_get_cursor_image_reply_t *cur_r;
img_c = xcb_shm_get_image_unchecked(data->xcb, data->xcb_screen->root,
data->x_org, data->y_org, data->width, data->height,
~0, XCB_IMAGE_FORMAT_Z_PIXMAP, data->xshm->seg, 0);
data->x_org, data->y_org,
data->width, data->height, ~0,
XCB_IMAGE_FORMAT_Z_PIXMAP,
data->xshm->seg, 0);
cur_c = xcb_xfixes_get_cursor_image_unchecked(data->xcb);
img_r = xcb_shm_get_image_reply(data->xcb, img_c, NULL);
@ -433,8 +434,8 @@ static void xshm_video_tick(void *vptr, float seconds)
obs_enter_graphics();
gs_texture_set_image(data->texture, (void *) data->xshm->data,
data->width * 4, false);
gs_texture_set_image(data->texture, (void *)data->xshm->data,
data->width * 4, false);
xcb_xcursor_update(data->cursor, cur_r);
obs_leave_graphics();
@ -491,19 +492,18 @@ static uint32_t xshm_getheight(void *vptr)
}
struct obs_source_info xshm_input = {
.id = "xshm_input",
.type = OBS_SOURCE_TYPE_INPUT,
.output_flags = OBS_SOURCE_VIDEO |
OBS_SOURCE_CUSTOM_DRAW |
OBS_SOURCE_DO_NOT_DUPLICATE,
.get_name = xshm_getname,
.create = xshm_create,
.destroy = xshm_destroy,
.update = xshm_update,
.get_defaults = xshm_defaults,
.id = "xshm_input",
.type = OBS_SOURCE_TYPE_INPUT,
.output_flags = OBS_SOURCE_VIDEO | OBS_SOURCE_CUSTOM_DRAW |
OBS_SOURCE_DO_NOT_DUPLICATE,
.get_name = xshm_getname,
.create = xshm_create,
.destroy = xshm_destroy,
.update = xshm_update,
.get_defaults = xshm_defaults,
.get_properties = xshm_properties,
.video_tick = xshm_video_tick,
.video_render = xshm_video_render,
.get_width = xshm_getwidth,
.get_height = xshm_getheight
.video_tick = xshm_video_tick,
.video_render = xshm_video_render,
.get_width = xshm_getwidth,
.get_height = xshm_getheight,
};

View file

@ -1,4 +1,4 @@
StartJACKServer="JACK-Server starten"
StartJACKServer="JACKServer starten"
Channels="Anzahl der Kanäle"
JACKInput="JACK-Eingabe-Client"
JACKInput="JACKEingabeClient"

View file

@ -33,7 +33,7 @@ static const char *jack_input_getname(void *unused)
*/
static void jack_destroy(void *vptr)
{
struct jack_data* data = (struct jack_data*)vptr;
struct jack_data *data = (struct jack_data *)vptr;
if (!data)
return;
@ -51,14 +51,14 @@ static void jack_destroy(void *vptr)
*/
static void jack_update(void *vptr, obs_data_t *settings)
{
struct jack_data* data = (struct jack_data*)vptr;
struct jack_data *data = (struct jack_data *)vptr;
if (!data)
return;
const char *new_device;
bool settings_changed = false;
bool settings_changed = false;
bool new_jack_start_server = obs_data_get_bool(settings, "startjack");
int new_channel_count = obs_data_get_int(settings, "channels");
int new_channel_count = obs_data_get_int(settings, "channels");
if (new_jack_start_server != data->start_jack_server) {
data->start_jack_server = new_jack_start_server;
@ -99,7 +99,7 @@ static void *jack_create(obs_data_t *settings, obs_source_t *source)
struct jack_data *data = bzalloc(sizeof(struct jack_data));
pthread_mutex_init(&data->jack_mutex, NULL);
data->source = source;
data->source = source;
data->channels = -1;
jack_update(data, settings);
@ -129,22 +129,22 @@ static obs_properties_t *jack_input_properties(void *unused)
obs_properties_t *props = obs_properties_create();
obs_properties_add_int(props, "channels",
obs_module_text("Channels"), 1, 8, 1);
obs_properties_add_int(props, "channels", obs_module_text("Channels"),
1, 8, 1);
obs_properties_add_bool(props, "startjack",
obs_module_text("StartJACKServer"));
obs_module_text("StartJACKServer"));
return props;
}
struct obs_source_info jack_output_capture = {
.id = "jack_output_capture",
.type = OBS_SOURCE_TYPE_INPUT,
.output_flags = OBS_SOURCE_AUDIO,
.get_name = jack_input_getname,
.create = jack_create,
.destroy = jack_destroy,
.update = jack_update,
.get_defaults = jack_input_defaults,
.get_properties = jack_input_properties
.id = "jack_output_capture",
.type = OBS_SOURCE_TYPE_INPUT,
.output_flags = OBS_SOURCE_AUDIO,
.get_name = jack_input_getname,
.create = jack_create,
.destroy = jack_destroy,
.update = jack_update,
.get_defaults = jack_input_defaults,
.get_properties = jack_input_properties,
};

View file

@ -36,33 +36,39 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
static enum speaker_layout jack_channels_to_obs_speakers(uint_fast32_t channels)
{
switch(channels) {
case 1: return SPEAKERS_MONO;
case 2: return SPEAKERS_STEREO;
case 3: return SPEAKERS_2POINT1;
case 5: return SPEAKERS_4POINT1;
case 6: return SPEAKERS_5POINT1;
switch (channels) {
case 1:
return SPEAKERS_MONO;
case 2:
return SPEAKERS_STEREO;
case 3:
return SPEAKERS_2POINT1;
case 5:
return SPEAKERS_4POINT1;
case 6:
return SPEAKERS_5POINT1;
/* What should we do with 7 channels? */
/* case 7: return SPEAKERS_...; */
case 8: return SPEAKERS_7POINT1;
case 8:
return SPEAKERS_7POINT1;
}
return SPEAKERS_UNKNOWN;
}
int jack_process_callback(jack_nframes_t nframes, void* arg)
int jack_process_callback(jack_nframes_t nframes, void *arg)
{
struct jack_data* data = (struct jack_data*)arg;
struct jack_data *data = (struct jack_data *)arg;
if (data == 0)
return 0;
pthread_mutex_lock(&data->jack_mutex);
struct obs_source_audio out;
out.speakers = jack_channels_to_obs_speakers(data->channels);
out.samples_per_sec = jack_get_sample_rate (data->jack_client);
out.speakers = jack_channels_to_obs_speakers(data->channels);
out.samples_per_sec = jack_get_sample_rate(data->jack_client);
/* format is always 32 bit float for jack */
out.format = AUDIO_FORMAT_FLOAT_PLANAR;
out.format = AUDIO_FORMAT_FLOAT_PLANAR;
for (unsigned int i = 0; i < data->channels; ++i) {
jack_default_audio_sample_t *jack_buffer =
@ -71,61 +77,61 @@ int jack_process_callback(jack_nframes_t nframes, void* arg)
out.data[i] = (uint8_t *)jack_buffer;
}
out.frames = nframes;
out.frames = nframes;
out.timestamp = os_gettime_ns() -
jack_frames_to_time(data->jack_client, nframes);
jack_frames_to_time(data->jack_client, nframes);
obs_source_output_audio(data->source, &out);
pthread_mutex_unlock(&data->jack_mutex);
return 0;
}
int_fast32_t jack_init(struct jack_data* data)
int_fast32_t jack_init(struct jack_data *data)
{
pthread_mutex_lock(&data->jack_mutex);
if (data->jack_client != NULL)
goto good;
jack_options_t jack_option = data->start_jack_server ?
JackNullOption : JackNoStartServer;
jack_options_t jack_option =
data->start_jack_server ? JackNullOption : JackNoStartServer;
data->jack_client = jack_client_open(data->device, jack_option, 0);
if (data->jack_client == NULL) {
blog(LOG_ERROR,
"jack_client_open Error:"
"Could not create JACK client! %s",
data->device);
"jack_client_open Error:"
"Could not create JACK client! %s",
data->device);
goto error;
}
data->jack_ports = (jack_port_t**)bzalloc(
sizeof(jack_port_t*) * data->channels);
data->jack_ports =
(jack_port_t **)bzalloc(sizeof(jack_port_t *) * data->channels);
for (unsigned int i = 0; i < data->channels; ++i) {
char port_name[10] = {'\0'};
snprintf(port_name, sizeof(port_name), "in_%u", i+1);
snprintf(port_name, sizeof(port_name), "in_%u", i + 1);
data->jack_ports[i] = jack_port_register(data->jack_client,
port_name, JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0);
data->jack_ports[i] = jack_port_register(
data->jack_client, port_name, JACK_DEFAULT_AUDIO_TYPE,
JackPortIsInput, 0);
if (data->jack_ports[i] == NULL) {
blog(LOG_ERROR,
"jack_port_register Error:"
"Could not create JACK port! %s",
port_name);
"jack_port_register Error:"
"Could not create JACK port! %s",
port_name);
goto error;
}
}
if (jack_set_process_callback(data->jack_client,
jack_process_callback, data) != 0) {
if (jack_set_process_callback(data->jack_client, jack_process_callback,
data) != 0) {
blog(LOG_ERROR, "jack_set_process_callback Error");
goto error;
}
if (jack_activate(data->jack_client) != 0) {
blog(LOG_ERROR,
"jack_activate Error:"
"Could not activate JACK client!");
blog(LOG_ERROR, "jack_activate Error:"
"Could not activate JACK client!");
goto error;
}
@ -138,7 +144,7 @@ error:
return 1;
}
void deactivate_jack(struct jack_data* data)
void deactivate_jack(struct jack_data *data)
{
pthread_mutex_lock(&data->jack_mutex);
@ -146,7 +152,8 @@ void deactivate_jack(struct jack_data* data)
if (data->jack_ports != NULL) {
for (int i = 0; i < data->channels; ++i) {
if (data->jack_ports[i] != NULL)
jack_port_unregister(data->jack_client,
jack_port_unregister(
data->jack_client,
data->jack_ports[i]);
}
bfree(data->jack_ports);

View file

@ -43,9 +43,9 @@ struct jack_data {
/**
* Initialize the jack client and register the ports
*/
int_fast32_t jack_init(struct jack_data* data);
int_fast32_t jack_init(struct jack_data *data);
/**
* Destroys the jack client and unregisters the ports
*/
void deactivate_jack(struct jack_data* data);
void deactivate_jack(struct jack_data *data);

View file

@ -1,4 +1,4 @@
PulseInput="Captura de entrada audio (PulseAudio)"
PulseOutput="Captura de saída de audio (PulseAudio)"
PulseInput="Captura de entrada son (PulseAudio)"
PulseOutput="Captura de saída de son (PulseAudio)"
Device="Dispositivo"

View file

@ -1,4 +1,4 @@
PulseInput="შემავალი ხმოვანი სიგნალის ჩაწერა (PulseAudio)"
PulseInput="შემავალი ხმის ჩაწერა (PulseAudio)"
PulseOutput="გამოტანილი ხმის ჩაწერა (PulseAudio)"
Device="მოწყობილობა"

View file

@ -21,7 +21,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "pulse-wrapper.h"
#define NSEC_PER_SEC 1000000000LL
#define NSEC_PER_SEC 1000000000LL
#define NSEC_PER_MSEC 1000000L
#define PULSE_DATA(voidptr) struct pulse_data *data = voidptr;
@ -53,15 +53,19 @@ static void pulse_stop_recording(struct pulse_data *data);
/**
* get obs from pulse audio format
*/
static enum audio_format pulse_to_obs_audio_format(
pa_sample_format_t format)
static enum audio_format pulse_to_obs_audio_format(pa_sample_format_t format)
{
switch (format) {
case PA_SAMPLE_U8: return AUDIO_FORMAT_U8BIT;
case PA_SAMPLE_S16LE: return AUDIO_FORMAT_16BIT;
case PA_SAMPLE_S32LE: return AUDIO_FORMAT_32BIT;
case PA_SAMPLE_FLOAT32LE: return AUDIO_FORMAT_FLOAT;
default: return AUDIO_FORMAT_UNKNOWN;
case PA_SAMPLE_U8:
return AUDIO_FORMAT_U8BIT;
case PA_SAMPLE_S16LE:
return AUDIO_FORMAT_16BIT;
case PA_SAMPLE_S32LE:
return AUDIO_FORMAT_32BIT;
case PA_SAMPLE_FLOAT32LE:
return AUDIO_FORMAT_FLOAT;
default:
return AUDIO_FORMAT_UNKNOWN;
}
return AUDIO_FORMAT_UNKNOWN;
@ -77,17 +81,24 @@ static enum audio_format pulse_to_obs_audio_format(
* @note This *might* not work for some rather unusual setups, but should work
* fine for the majority of cases.
*/
static enum speaker_layout pulse_channels_to_obs_speakers(
uint_fast32_t channels)
static enum speaker_layout
pulse_channels_to_obs_speakers(uint_fast32_t channels)
{
switch(channels) {
case 1: return SPEAKERS_MONO;
case 2: return SPEAKERS_STEREO;
case 3: return SPEAKERS_2POINT1;
case 4: return SPEAKERS_4POINT0;
case 5: return SPEAKERS_4POINT1;
case 6: return SPEAKERS_5POINT1;
case 8: return SPEAKERS_7POINT1;
switch (channels) {
case 1:
return SPEAKERS_MONO;
case 2:
return SPEAKERS_STEREO;
case 3:
return SPEAKERS_2POINT1;
case 4:
return SPEAKERS_4POINT0;
case 5:
return SPEAKERS_4POINT1;
case 6:
return SPEAKERS_5POINT1;
case 8:
return SPEAKERS_7POINT1;
}
return SPEAKERS_UNKNOWN;
@ -185,19 +196,18 @@ static void pulse_stream_read(pa_stream *p, size_t nbytes, void *userdata)
if (!frames) {
blog(LOG_ERROR, "Got audio hole of %u bytes",
(unsigned int) bytes);
(unsigned int)bytes);
pa_stream_drop(data->stream);
goto exit;
}
struct obs_source_audio out;
out.speakers = data->speakers;
out.speakers = data->speakers;
out.samples_per_sec = data->samples_per_sec;
out.format = pulse_to_obs_audio_format(data->format);
out.data[0] = (uint8_t *) frames;
out.frames = bytes / data->bytes_per_frame;
out.timestamp = get_sample_time(out.frames,
out.samples_per_sec);
out.format = pulse_to_obs_audio_format(data->format);
out.data[0] = (uint8_t *)frames;
out.frames = bytes / data->bytes_per_frame;
out.timestamp = get_sample_time(out.frames, out.samples_per_sec);
if (!data->first_ts)
data->first_ts = out.timestamp + STARTUP_TIMEOUT_NS;
@ -217,29 +227,32 @@ exit:
* Server info callback
*/
static void pulse_server_info(pa_context *c, const pa_server_info *i,
void *userdata)
void *userdata)
{
UNUSED_PARAMETER(c);
PULSE_DATA(userdata);
blog(LOG_INFO, "Server name: '%s %s'",
i->server_name, i->server_version);
blog(LOG_INFO, "Server name: '%s %s'", i->server_name,
i->server_version);
if (data->device && strcmp("default", data->device) == 0) {
if (data->input) {
bfree(data->device);
data->device = bstrdup(i->default_source_name);
blog(LOG_DEBUG, "Default input device: '%s'", data->device);
blog(LOG_DEBUG, "Default input device: '%s'",
data->device);
} else {
char *monitor = bzalloc(strlen(i->default_sink_name) + 9);
char *monitor =
bzalloc(strlen(i->default_sink_name) + 9);
strcat(monitor, i->default_sink_name);
strcat(monitor, ".monitor");
bfree(data->device);
data->device = bstrdup(monitor);
blog(LOG_DEBUG, "Default output device: '%s'", data->device);
blog(LOG_DEBUG, "Default output device: '%s'",
data->device);
bfree(monitor);
}
}
@ -254,7 +267,7 @@ static void pulse_server_info(pa_context *c, const pa_server_info *i,
* configured to something obs can't deal with.
*/
static void pulse_source_info(pa_context *c, const pa_source_info *i, int eol,
void *userdata)
void *userdata)
{
UNUSED_PARAMETER(c);
PULSE_DATA(userdata);
@ -267,35 +280,36 @@ static void pulse_source_info(pa_context *c, const pa_source_info *i, int eol,
if (eol > 0)
goto skip;
blog(LOG_INFO, "Audio format: %s, %"PRIu32" Hz"
", %"PRIu8" channels",
pa_sample_format_to_string(i->sample_spec.format),
i->sample_spec.rate,
i->sample_spec.channels);
blog(LOG_INFO,
"Audio format: %s, %" PRIu32 " Hz"
", %" PRIu8 " channels",
pa_sample_format_to_string(i->sample_spec.format),
i->sample_spec.rate, i->sample_spec.channels);
pa_sample_format_t format = i->sample_spec.format;
if (pulse_to_obs_audio_format(format) == AUDIO_FORMAT_UNKNOWN) {
format = PA_SAMPLE_FLOAT32LE;
blog(LOG_INFO, "Sample format %s not supported by OBS,"
"using %s instead for recording",
pa_sample_format_to_string(i->sample_spec.format),
pa_sample_format_to_string(format));
blog(LOG_INFO,
"Sample format %s not supported by OBS,"
"using %s instead for recording",
pa_sample_format_to_string(i->sample_spec.format),
pa_sample_format_to_string(format));
}
uint8_t channels = i->sample_spec.channels;
if (pulse_channels_to_obs_speakers(channels) == SPEAKERS_UNKNOWN) {
channels = 2;
blog(LOG_INFO, "%c channels not supported by OBS,"
"using %c instead for recording",
i->sample_spec.channels,
channels);
blog(LOG_INFO,
"%c channels not supported by OBS,"
"using %c instead for recording",
i->sample_spec.channels, channels);
}
data->format = format;
data->format = format;
data->samples_per_sec = i->sample_spec.rate;
data->channels = channels;
data->channels = channels;
skip:
pulse_signal(0);
@ -313,24 +327,25 @@ skip:
*/
static int_fast32_t pulse_start_recording(struct pulse_data *data)
{
if (pulse_get_server_info(pulse_server_info, (void *) data) < 0) {
if (pulse_get_server_info(pulse_server_info, (void *)data) < 0) {
blog(LOG_ERROR, "Unable to get server info !");
return -1;
}
if (pulse_get_source_info(pulse_source_info, data->device,
(void *) data) < 0) {
(void *)data) < 0) {
blog(LOG_ERROR, "Unable to get source info !");
return -1;
}
if (data->format == PA_SAMPLE_INVALID) {
blog(LOG_ERROR, "An error occurred while getting the source info!");
blog(LOG_ERROR,
"An error occurred while getting the source info!");
return -1;
}
pa_sample_spec spec;
spec.format = data->format;
spec.rate = data->samples_per_sec;
spec.format = data->format;
spec.rate = data->samples_per_sec;
spec.channels = data->channels;
if (!pa_sample_spec_valid(&spec)) {
@ -344,7 +359,7 @@ static int_fast32_t pulse_start_recording(struct pulse_data *data)
pa_channel_map channel_map = pulse_channel_map(data->speakers);
data->stream = pulse_stream_new(obs_source_get_name(data->source),
&spec, &channel_map);
&spec, &channel_map);
if (!data->stream) {
blog(LOG_ERROR, "Unable to create stream");
return -1;
@ -352,21 +367,21 @@ static int_fast32_t pulse_start_recording(struct pulse_data *data)
pulse_lock();
pa_stream_set_read_callback(data->stream, pulse_stream_read,
(void *) data);
(void *)data);
pulse_unlock();
pa_buffer_attr attr;
attr.fragsize = pa_usec_to_bytes(25000, &spec);
attr.maxlength = (uint32_t) -1;
attr.minreq = (uint32_t) -1;
attr.prebuf = (uint32_t) -1;
attr.tlength = (uint32_t) -1;
attr.fragsize = pa_usec_to_bytes(25000, &spec);
attr.maxlength = (uint32_t)-1;
attr.minreq = (uint32_t)-1;
attr.prebuf = (uint32_t)-1;
attr.tlength = (uint32_t)-1;
pa_stream_flags_t flags = PA_STREAM_ADJUST_LATENCY;
pulse_lock();
int_fast32_t ret = pa_stream_connect_record(data->stream, data->device,
&attr, flags);
&attr, flags);
pulse_unlock();
if (ret < 0) {
pulse_stop_recording(data);
@ -392,8 +407,9 @@ static void pulse_stop_recording(struct pulse_data *data)
}
blog(LOG_INFO, "Stopped recording from '%s'", data->device);
blog(LOG_INFO, "Got %"PRIuFAST32" packets with %"PRIuFAST64" frames",
data->packets, data->frames);
blog(LOG_INFO,
"Got %" PRIuFAST32 " packets with %" PRIuFAST64 " frames",
data->packets, data->frames);
data->first_ts = 0;
data->packets = 0;
@ -404,14 +420,14 @@ static void pulse_stop_recording(struct pulse_data *data)
* input info callback
*/
static void pulse_input_info(pa_context *c, const pa_source_info *i, int eol,
void *userdata)
void *userdata)
{
UNUSED_PARAMETER(c);
if (eol != 0 || i->monitor_of_sink != PA_INVALID_INDEX)
goto skip;
obs_property_list_add_string((obs_property_t*) userdata,
i->description, i->name);
obs_property_list_add_string((obs_property_t *)userdata, i->description,
i->name);
skip:
pulse_signal(0);
@ -421,14 +437,14 @@ skip:
* output info callback
*/
static void pulse_output_info(pa_context *c, const pa_sink_info *i, int eol,
void *userdata)
void *userdata)
{
UNUSED_PARAMETER(c);
if (eol != 0 || i->monitor_source == PA_INVALID_INDEX)
goto skip;
obs_property_list_add_string((obs_property_t*) userdata,
i->description, i->monitor_source_name);
obs_property_list_add_string((obs_property_t *)userdata, i->description,
i->monitor_source_name);
skip:
pulse_signal(0);
@ -440,22 +456,22 @@ skip:
static obs_properties_t *pulse_properties(bool input)
{
obs_properties_t *props = obs_properties_create();
obs_property_t *devices = obs_properties_add_list(props, "device_id",
obs_module_text("Device"), OBS_COMBO_TYPE_LIST,
OBS_COMBO_FORMAT_STRING);
obs_property_t *devices = obs_properties_add_list(
props, "device_id", obs_module_text("Device"),
OBS_COMBO_TYPE_LIST, OBS_COMBO_FORMAT_STRING);
pulse_init();
if (input)
pulse_get_source_info_list(pulse_input_info, (void *) devices);
pulse_get_source_info_list(pulse_input_info, (void *)devices);
else
pulse_get_sink_info_list(pulse_output_info, (void *) devices);
pulse_get_sink_info_list(pulse_output_info, (void *)devices);
pulse_unref();
size_t count = obs_property_list_item_count(devices);
if (count > 0)
obs_property_list_insert_string(devices, 0,
obs_module_text("Default"), "default");
obs_property_list_insert_string(
devices, 0, obs_module_text("Default"), "default");
return props;
}
@ -544,12 +560,13 @@ static void pulse_update(void *vptr, obs_data_t *settings)
/**
* Create the plugin object
*/
static void *pulse_create(obs_data_t *settings, obs_source_t *source, bool input)
static void *pulse_create(obs_data_t *settings, obs_source_t *source,
bool input)
{
struct pulse_data *data = bzalloc(sizeof(struct pulse_data));
data->input = input;
data->source = source;
data->input = input;
data->source = source;
pulse_init();
pulse_update(data, settings);
@ -568,28 +585,26 @@ static void *pulse_output_create(obs_data_t *settings, obs_source_t *source)
}
struct obs_source_info pulse_input_capture = {
.id = "pulse_input_capture",
.type = OBS_SOURCE_TYPE_INPUT,
.output_flags = OBS_SOURCE_AUDIO |
OBS_SOURCE_DO_NOT_DUPLICATE,
.get_name = pulse_input_getname,
.create = pulse_input_create,
.destroy = pulse_destroy,
.update = pulse_update,
.get_defaults = pulse_defaults,
.get_properties = pulse_input_properties
.id = "pulse_input_capture",
.type = OBS_SOURCE_TYPE_INPUT,
.output_flags = OBS_SOURCE_AUDIO | OBS_SOURCE_DO_NOT_DUPLICATE,
.get_name = pulse_input_getname,
.create = pulse_input_create,
.destroy = pulse_destroy,
.update = pulse_update,
.get_defaults = pulse_defaults,
.get_properties = pulse_input_properties,
};
struct obs_source_info pulse_output_capture = {
.id = "pulse_output_capture",
.type = OBS_SOURCE_TYPE_INPUT,
.output_flags = OBS_SOURCE_AUDIO |
OBS_SOURCE_DO_NOT_DUPLICATE |
OBS_SOURCE_DO_NOT_SELF_MONITOR,
.get_name = pulse_output_getname,
.create = pulse_output_create,
.destroy = pulse_destroy,
.update = pulse_update,
.get_defaults = pulse_defaults,
.get_properties = pulse_output_properties
.id = "pulse_output_capture",
.type = OBS_SOURCE_TYPE_INPUT,
.output_flags = OBS_SOURCE_AUDIO | OBS_SOURCE_DO_NOT_DUPLICATE |
OBS_SOURCE_DO_NOT_SELF_MONITOR,
.get_name = pulse_output_getname,
.create = pulse_output_create,
.destroy = pulse_destroy,
.update = pulse_update,
.get_defaults = pulse_defaults,
.get_properties = pulse_output_properties,
};

View file

@ -70,7 +70,7 @@ static void pulse_init_context()
pa_threaded_mainloop_get_api(pulse_mainloop), "OBS", p);
pa_context_set_state_callback(pulse_context,
pulse_context_state_changed, NULL);
pulse_context_state_changed, NULL);
pa_context_connect(pulse_context, NULL, PA_CONTEXT_NOAUTOSPAWN, NULL);
pa_proplist_free(p);
@ -163,15 +163,15 @@ void pulse_accept()
pa_threaded_mainloop_accept(pulse_mainloop);
}
int_fast32_t pulse_get_source_info_list(pa_source_info_cb_t cb, void* userdata)
int_fast32_t pulse_get_source_info_list(pa_source_info_cb_t cb, void *userdata)
{
if (pulse_context_ready() < 0)
return -1;
pulse_lock();
pa_operation *op = pa_context_get_source_info_list(
pulse_context, cb, userdata);
pa_operation *op =
pa_context_get_source_info_list(pulse_context, cb, userdata);
if (!op) {
pulse_unlock();
return -1;
@ -192,8 +192,8 @@ int_fast32_t pulse_get_sink_info_list(pa_sink_info_cb_t cb, void *userdata)
pulse_lock();
pa_operation *op = pa_context_get_sink_info_list(
pulse_context, cb, userdata);
pa_operation *op =
pa_context_get_sink_info_list(pulse_context, cb, userdata);
if (!op) {
pulse_unlock();
return -1;
@ -208,7 +208,7 @@ int_fast32_t pulse_get_sink_info_list(pa_sink_info_cb_t cb, void *userdata)
}
int_fast32_t pulse_get_source_info(pa_source_info_cb_t cb, const char *name,
void *userdata)
void *userdata)
{
if (pulse_context_ready() < 0)
return -1;
@ -230,15 +230,15 @@ int_fast32_t pulse_get_source_info(pa_source_info_cb_t cb, const char *name,
return 0;
}
int_fast32_t pulse_get_server_info(pa_server_info_cb_t cb, void* userdata)
int_fast32_t pulse_get_server_info(pa_server_info_cb_t cb, void *userdata)
{
if (pulse_context_ready() < 0)
return -1;
pulse_lock();
pa_operation *op = pa_context_get_server_info(
pulse_context, cb, userdata);
pa_operation *op =
pa_context_get_server_info(pulse_context, cb, userdata);
if (!op) {
pulse_unlock();
return -1;
@ -251,8 +251,8 @@ int_fast32_t pulse_get_server_info(pa_server_info_cb_t cb, void* userdata)
return 0;
}
pa_stream* pulse_stream_new(const char* name, const pa_sample_spec* ss,
const pa_channel_map* map)
pa_stream *pulse_stream_new(const char *name, const pa_sample_spec *ss,
const pa_channel_map *map)
{
if (pulse_context_ready() < 0)
return NULL;
@ -260,11 +260,10 @@ pa_stream* pulse_stream_new(const char* name, const pa_sample_spec* ss,
pulse_lock();
pa_proplist *p = pulse_properties();
pa_stream *s = pa_stream_new_with_proplist(
pulse_context, name, ss, map, p);
pa_stream *s =
pa_stream_new_with_proplist(pulse_context, name, ss, map, p);
pa_proplist_free(p);
pulse_unlock();
return s;
}

View file

@ -124,7 +124,7 @@ int_fast32_t pulse_get_sink_info_list(pa_sink_info_cb_t cb, void *userdata);
* @warning call without active locks
*/
int_fast32_t pulse_get_source_info(pa_source_info_cb_t cb, const char *name,
void *userdata);
void *userdata);
/**
* Request server information
@ -148,4 +148,4 @@ int_fast32_t pulse_get_server_info(pa_server_info_cb_t cb, void *userdata);
* @warning call without active locks
*/
pa_stream *pulse_stream_new(const char *name, const pa_sample_spec *ss,
const pa_channel_map *map);
const pa_channel_map *map);

View file

@ -1,5 +1,6 @@
V4L2Input="جهاز التقاط الفيديو (V4L2)"
Device="الجهاز"
Input="الوارد"
VideoFormat="تنسيق الفيديو"
VideoStandard="معيار الفيديو"
DVTiming="توقيت DV"

View file

@ -9,6 +9,7 @@ FrameRate="Fotogrames per segon"
LeaveUnchanged="No ho canviïs"
UseBuffering="Usa memòria intermèdia"
ColorRange="Gamma de colors"
ColorRange.Default="Per defecte"
ColorRange.Partial="Parcial"
ColorRange.Full="Complet"

View file

@ -9,6 +9,7 @@ FrameRate="Snímkovací frekvence"
LeaveUnchanged="Ponechat nezměněné"
UseBuffering="Použít vyrovnávací paměť"
ColorRange="Rozsah barev"
ColorRange.Default="Výchozí"
ColorRange.Partial="Částečný"
ColorRange.Full="Plný"

View file

@ -9,6 +9,7 @@ FrameRate="Billedhastighed"
LeaveUnchanged="Behold uændret"
UseBuffering="Benyt buffering"
ColorRange="Farveområde"
ColorRange.Default="Standard"
ColorRange.Partial="Delvist"
ColorRange.Full="Fuldt"

View file

@ -3,12 +3,13 @@ Device="Gerät"
Input="Eingabe"
VideoFormat="Videoformat"
VideoStandard="Videostandard"
DVTiming="DV-Timing"
DVTiming="DVTiming"
Resolution="Auflösung"
FrameRate="Bildrate"
LeaveUnchanged="Unverändert lassen"
UseBuffering="Puffern benutzen"
ColorRange="Farbbereich"
ColorRange.Default="Standard"
ColorRange.Partial="Begrenzt"
ColorRange.Full="Voll"

View file

@ -9,5 +9,6 @@ FrameRate="Frame Rate"
LeaveUnchanged="Leave Unchanged"
UseBuffering="Use Buffering"
ColorRange="Color Range"
ColorRange.Default="Default"
ColorRange.Partial="Partial"
ColorRange.Full="Full"

View file

@ -9,6 +9,7 @@ FrameRate="Frecuencia de imágenes"
LeaveUnchanged="Dejar sin cambios"
UseBuffering="Utilizar el almacenamiento en búfer"
ColorRange="Gama de Colores"
ColorRange.Default="Predeterminado"
ColorRange.Partial="Parcial"
ColorRange.Full="Completo"

View file

@ -9,6 +9,7 @@ FrameRate="Fotograma emaria"
LeaveUnchanged="Utzi aldatu gabe"
UseBuffering="Erabili bufferreratzea"
ColorRange="Kolore tartea"
ColorRange.Default="Lehenetsia"
ColorRange.Partial="Partziala"
ColorRange.Full="Osoa"

View file

@ -9,6 +9,7 @@ FrameRate="Kuvanopeus"
LeaveUnchanged="Jätä ennalleen"
UseBuffering="Käytä puskurointia"
ColorRange="Värialue"
ColorRange.Default="Oletus"
ColorRange.Partial="Osittainen"
ColorRange.Full="Täysi"

View file

@ -9,6 +9,7 @@ FrameRate="Images par seconde"
LeaveUnchanged="Annuler les modifications"
UseBuffering="Utiliser le tampon mémoire"
ColorRange="Gamme de couleurs"
ColorRange.Default="Par défaut"
ColorRange.Partial="Partielle"
ColorRange.Full="Complète"

View file

@ -3,9 +3,13 @@ Device="Dispositivo"
Input="Entrada"
VideoFormat="Formato de vídeo"
VideoStandard="Vídeo estándar"
DVTiming="Axuste DV"
DVTiming="Sincronización do vídeo dixital (DV)"
Resolution="Resolución"
FrameRate="Velocidade de fotogramas"
FrameRate="Taxa de fotogramas"
LeaveUnchanged="Deixar sen cambios"
UseBuffering="Utilizar o almacenamento no búfer"
UseBuffering="Utilizar o almacenamento na memoria temporal"
ColorRange="Gama de cores"
ColorRange.Default="Predeterminado"
ColorRange.Partial="Parcial"
ColorRange.Full="Total"

View file

@ -9,6 +9,7 @@ FrameRate="Képkockasebesség"
LeaveUnchanged="Változatlanul hagyni"
UseBuffering="Pufferelés használata"
ColorRange="Színtartomány"
ColorRange.Default="Alapértelmezett"
ColorRange.Partial="Részleges"
ColorRange.Full="Teljes"

View file

@ -9,6 +9,7 @@ FrameRate="Velocità dei fotogrammi"
LeaveUnchanged="Lascia invariato"
UseBuffering="Utilizza il buffering"
ColorRange="Gamma di colori"
ColorRange.Default="Predefinito"
ColorRange.Partial="Parziale"
ColorRange.Full="Intero"

View file

@ -9,6 +9,7 @@ FrameRate="フレームレート"
LeaveUnchanged="変更せずに戻る"
UseBuffering="バッファリングを使用する"
ColorRange="色範囲"
ColorRange.Default="既定"
ColorRange.Partial="一部"
ColorRange.Full="全部"

View file

@ -1,6 +1,6 @@
V4L2Input="ვიდეოს გადამღები მოწყობილობა (V4L2)"
V4L2Input="ვიდეოჩამწერი მოწყობილობა (V4L2)"
Device="მოწყობილობა"
Input="შემავალი"
Input="შეტანა"
VideoFormat="ვიდეოს ფორმატი"
VideoStandard="ვიდეოს სტანდარტი"
DVTiming="ციფრული ვიდეოს სინქრონიზაცია"
@ -9,6 +9,7 @@ FrameRate="კადრის სიხშირე"
LeaveUnchanged="უცვლელად დატოვება"
UseBuffering="ბუფერიზაციის გამოყენება"
ColorRange="ფერთა გამა"
ColorRange.Default="ნაგულისხმევი"
ColorRange.Partial="ნაწილობრივი"
ColorRange.Full="სრული"

View file

@ -9,6 +9,7 @@ FrameRate="프레임 레이트"
LeaveUnchanged="저장하지 않고 두기"
UseBuffering="버퍼링 사용"
ColorRange="색상 범위"
ColorRange.Default="기본값"
ColorRange.Partial="부분"
ColorRange.Full="전체"

View file

@ -9,6 +9,7 @@ FrameRate="Frame Rate"
LeaveUnchanged="Ongewijzigd Laten"
UseBuffering="Buffering Gebruiken"
ColorRange="Kleurbereik"
ColorRange.Default="Standaard"
ColorRange.Partial="Gedeeltelijk"
ColorRange.Full="Volledig"

View file

@ -9,6 +9,7 @@ FrameRate="Klatki na sekundę"
LeaveUnchanged="Pozostaw bez zmian"
UseBuffering="Użyj buforowania"
ColorRange="Zakres kolorów"
ColorRange.Default="Domyślny"
ColorRange.Partial="Częściowy"
ColorRange.Full="Pełny"

View file

@ -9,6 +9,7 @@ FrameRate="Taxa de quadros"
LeaveUnchanged="Deixar inalterado"
UseBuffering="Utilizar Buffering"
ColorRange="Intervalo de Cor"
ColorRange.Default="Padrão"
ColorRange.Partial="Parcial"
ColorRange.Full="Completo"

View file

@ -8,4 +8,8 @@ Resolution="Rezoluție"
FrameRate="Frecvență de cadre"
LeaveUnchanged="Lasă neschimbat"
UseBuffering="Folosește zona tampon"
ColorRange="Gamă de culori"
ColorRange.Default="Implicită"
ColorRange.Partial="Parțială"
ColorRange.Full="Completă"

View file

@ -9,6 +9,7 @@ FrameRate="Частота кадров"
LeaveUnchanged="Оставить без изменений"
UseBuffering="Использовать буферизацию"
ColorRange="Цветовой диапазон"
ColorRange.Default="По умолчанию"
ColorRange.Partial="Частичный"
ColorRange.Full="Полный"

View file

@ -9,6 +9,7 @@ FrameRate="Bildhastighet"
LeaveUnchanged="Lämna oförändrat"
UseBuffering="Använd buffer"
ColorRange="Färgintervall"
ColorRange.Default="Standard"
ColorRange.Partial="Delvis"
ColorRange.Full="Full"

View file

@ -9,6 +9,7 @@ FrameRate="Kare Hızı"
LeaveUnchanged="Değişmeden Bırak"
UseBuffering="Arabelleğe Almayı Kullan"
ColorRange="Renk Aralığı"
ColorRange.Default="Varsayılan"
ColorRange.Partial="Kısmi"
ColorRange.Full="Tam"

View file

@ -9,6 +9,7 @@ FrameRate="Частота кадрів"
LeaveUnchanged="Залишити без змін"
UseBuffering="Увімкнути буферизацію"
ColorRange="Колірний діапазон"
ColorRange.Default="За замовчанням"
ColorRange.Partial="Частковий"
ColorRange.Full="Повний"

View file

@ -9,6 +9,7 @@ FrameRate="帧率"
LeaveUnchanged="保持不变"
UseBuffering="使用缓冲"
ColorRange="颜色范围"
ColorRange.Default="默认"
ColorRange.Partial="部分"
ColorRange.Full="全部"

Some files were not shown because too many files have changed in this diff Show more