obs/DShowPlugin/DeviceSource.h

259 lines
7.0 KiB
C++

/********************************************************************************
Copyright (C) 2012 Hugh Bailey <obs.jim@gmail.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
********************************************************************************/
#pragma once
#include <memory>
void PackPlanar(LPBYTE convertBuffer, LPBYTE lpPlanar, UINT renderCX, UINT renderCY, UINT pitch, UINT startY, UINT endY, UINT linePitch, UINT lineShift);
enum DeviceColorType
{
DeviceOutputType_RGB,
//planar 4:2:0
DeviceOutputType_I420,
DeviceOutputType_YV12,
//packed 4:2:2
DeviceOutputType_YVYU,
DeviceOutputType_YUY2,
DeviceOutputType_UYVY,
DeviceOutputType_HDYC,
};
struct SampleData {
//IMediaSample *sample;
LPBYTE lpData;
long dataLength;
int cx, cy;
bool bAudio;
LONGLONG timestamp;
volatile long refs;
inline SampleData() {refs = 1;}
inline ~SampleData() {Free(lpData);} //sample->Release();}
inline void AddRef() {++refs;}
inline void Release()
{
if(!InterlockedDecrement(&refs))
delete this;
}
};
struct ConvertData
{
LPBYTE input, output;
SampleData *sample;
HANDLE hSignalConvert, hSignalComplete;
bool bKillThread;
UINT width, height;
UINT pitch;
UINT startY, endY;
UINT linePitch, lineShift;
};
class DeviceSource;
class DeviceAudioSource : public AudioSource
{
DeviceSource *device;
UINT sampleSegmentSize, sampleFrameCount;
HANDLE hAudioMutex;
List<BYTE> sampleBuffer;
List<BYTE> outputBuffer;
int offset;
protected:
virtual bool GetNextBuffer(void **buffer, UINT *numFrames, QWORD *timestamp);
virtual void ReleaseBuffer();
virtual CTSTR GetDeviceName() const;
public:
bool Initialize(DeviceSource *parent);
~DeviceAudioSource();
void ReceiveAudio(LPBYTE lpData, UINT dataLength);
void FlushSamples();
inline void SetAudioOffset(int offset) {this->offset = offset; SetTimeOffset(offset);}
};
class DeviceSource : public ImageSource
{
friend class DeviceAudioSource;
friend class CapturePin;
IGraphBuilder *graph;
ICaptureGraphBuilder2 *capture;
IMediaControl *control;
IBaseFilter *deviceFilter;
IBaseFilter *audioDeviceFilter;
CaptureFilter *captureFilter;
IBaseFilter *audioFilter; // Audio renderer filter
//---------------------------------
WAVEFORMATEX audioFormat;
DeviceAudioSource *audioOut;
bool bRequestVolume;
float fNewVol;
UINT enteredSceneCount;
//---------------------------------
DeviceColorType colorType;
String strDevice, strDeviceName, strDeviceID;
String strAudioDevice, strAudioName, strAudioID;
bool bFlipVertical, bFlipHorizontal, bDeviceHasAudio, bUsePointFiltering, bUseAudioRender;
UINT64 frameInterval;
UINT renderCX, renderCY;
UINT newCX, newCY;
UINT lastSampleCX, lastSampleCY;
UINT imageCX, imageCY;
UINT linePitch, lineShift, lineSize;
BOOL bUseCustomResolution;
UINT preferredOutputType;
BOOL fullRange;
int colorSpace;
BOOL use709;
struct {
int type; //DeinterlacingType
char fieldOrder; //DeinterlacingFieldOrder
char processor; //DeinterlacingProcessor
bool curField, bNewFrame;
bool doublesFramerate;
bool needsPreviousFrame;
bool isReady;
std::unique_ptr<Texture> texture;
UINT imageCX, imageCY;
std::unique_ptr<Shader> vertexShader;
FuturePixelShader pixelShader;
} deinterlacer;
bool bFirstFrame;
bool bUseThreadedConversion;
bool bReadyToDraw;
int soundOutputType;
bool bOutputAudioToDesktop;
Texture *texture, *previousTexture;
XElement *data;
UINT texturePitch;
bool bCapturing, bFiltersLoaded;
Shader *colorConvertShader;
Shader *drawShader;
bool bUseBuffering;
HANDLE hStopSampleEvent;
HANDLE hSampleMutex;
HANDLE hSampleThread;
UINT bufferTime; // 100-nsec units (same as REFERENCE_TIME)
SampleData *latestVideoSample;
List<SampleData*> samples;
UINT opacity;
int gamma;
//---------------------------------
LPBYTE lpImageBuffer;
ConvertData *convertData;
HANDLE *hConvertThreads;
//---------------------------------
bool bUseChromaKey;
DWORD keyColor;
Color4 keyChroma;
Color4 keyBaseColor;
int keySimilarity;
int keyBlend;
int keySpillReduction;
//---------------------------------
void ChangeSize(bool bSucceeded = true, bool bForce = false);
void KillThreads();
String ChooseShader();
String ChooseDeinterlacingShader();
void Convert422To444(LPBYTE convertBuffer, LPBYTE lp422, UINT pitch, bool bLeadingY);
void FlushSamples()
{
OSEnterMutex(hSampleMutex);
for (UINT i=0; i<samples.Num(); i++)
delete samples[i];
samples.Clear();
SafeRelease(latestVideoSample);
OSLeaveMutex(hSampleMutex);
}
void SetAudioInfo(AM_MEDIA_TYPE *audioMediaType, GUID &expectedAudioType);
UINT GetSampleInsertIndex(LONGLONG timestamp);
void ReceiveMediaSample(IMediaSample *sample, bool bAudio);
bool LoadFilters();
void UnloadFilters();
void Start();
void Stop();
static DWORD WINAPI SampleThread(DeviceSource *source);
public:
bool Init(XElement *data);
~DeviceSource();
void UpdateSettings();
void Preprocess();
void Render(const Vect2 &pos, const Vect2 &size);
void BeginScene();
void EndScene();
void GlobalSourceEnterScene();
void GlobalSourceLeaveScene();
void SetInt(CTSTR lpName, int iVal);
void SetFloat(CTSTR lpName, float fValue);
Vect2 GetSize() const {return Vect2(float(imageCX), float(imageCY));}
};