Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
hrydgard
GitHub Repository: hrydgard/ppsspp
Path: blob/master/Windows/CaptureDevice.h
3185 views
1
// Copyright (c) 2020- PPSSPP Project.
2
3
// This program is free software: you can redistribute it and/or modify
4
// it under the terms of the GNU General Public License as published by
5
// the Free Software Foundation, version 2.0 or later versions.
6
7
// This program is distributed in the hope that it will be useful,
8
// but WITHOUT ANY WARRANTY; without even the implied warranty of
9
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10
// GNU General Public License 2.0 for more details.
11
12
// A copy of the GPL 2.0 should have been included with the program.
13
// If not, see http://www.gnu.org/licenses/
14
15
// Official git repository and contact information can be found at
16
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
17
18
#pragma once
19
20
#include <mfapi.h>
21
#include <mfidl.h>
22
#include <mfreadwrite.h>
23
#include <mutex>
24
#include <condition_variable>
25
#include <vector>
26
#include <queue>
27
#include <thread>
28
#include <wrl/client.h>
29
30
#include "Core/HLE/sceUsbMic.h"
31
32
#ifdef __cplusplus
33
extern "C" {
34
#include "libavformat/avformat.h"
35
#include "libswscale/swscale.h"
36
#include "libswresample/swresample.h"
37
#include "libavutil/imgutils.h"
38
}
39
#endif // __cplusplus
40
41
struct VideoFormatTransform {
42
GUID MFVideoFormat;
43
AVPixelFormat AVVideoFormat;
44
};
45
46
struct AudioFormatTransform {
47
GUID MFAudioFormat;
48
u32 bitsPerSample;
49
AVSampleFormat AVAudioFormat;
50
};
51
52
enum class CAPTUREDEVIDE_TYPE {
53
VIDEO,
54
Audio
55
};
56
57
enum class CAPTUREDEVIDE_STATE {
58
UNINITIALIZED,
59
LOST,
60
STOPPED,
61
STARTED,
62
SHUTDOWN
63
};
64
65
enum class CAPTUREDEVIDE_COMMAND {
66
INITIALIZE,
67
START,
68
STOP,
69
SHUTDOWN,
70
UPDATE_STATE
71
};
72
73
enum CAPTUREDEVIDE_ERROR {
74
CAPTUREDEVIDE_ERROR_NO_ERROR,
75
CAPTUREDEVIDE_ERROR_UNKNOWN_TYPE = 0x80000001,
76
CAPTUREDEVIDE_ERROR_INIT_FAILED,
77
CAPTUREDEVIDE_ERROR_START_FAILED,
78
CAPTUREDEVIDE_ERROR_STOP_FAILED,
79
CAPTUREDEVIDE_ERROR_GETNAMES_FAILED
80
};
81
82
struct CAPTUREDEVIDE_MESSAGE{
83
CAPTUREDEVIDE_COMMAND command;
84
void *opacity;
85
};
86
87
struct ChooseDeviceParam {
88
IMFActivate **ppDevices;
89
UINT32 count;
90
UINT32 selection;
91
};
92
93
union MediaParam {
94
struct {
95
UINT32 width;
96
UINT32 height;
97
LONG default_stride;
98
GUID videoFormat;
99
};
100
struct {
101
UINT32 sampleRate;
102
UINT32 channels;
103
LONG bitsPerSample;
104
GUID audioFormat;
105
};
106
};
107
108
template <class T> void SafeRelease(T **ppT) {
109
if (*ppT) {
110
(*ppT)->Release();
111
*ppT = nullptr;
112
}
113
}
114
115
class WindowsCaptureDevice;
116
117
class ReaderCallback final : public IMFSourceReaderCallback {
118
public:
119
ReaderCallback(WindowsCaptureDevice *device);
120
virtual ~ReaderCallback();
121
122
// IUnknown methods.
123
STDMETHODIMP QueryInterface(REFIID iid, void** ppv) override;
124
STDMETHODIMP_(ULONG) AddRef() override { return 0; } // Unused, just define.
125
STDMETHODIMP_(ULONG) Release() override { return 0; } // Unused, just define.
126
127
// IMFSourceReaderCallback methods.
128
STDMETHODIMP OnReadSample(
129
HRESULT hrStatus,
130
DWORD dwStreamIndex,
131
DWORD dwStreamFlags,
132
LONGLONG llTimestamp,
133
IMFSample *pSample // Can be null,even if hrStatus is success.
134
) override;
135
136
STDMETHODIMP OnEvent(DWORD, IMFMediaEvent *) override { return S_OK; }
137
STDMETHODIMP OnFlush(DWORD) override { return S_OK; }
138
139
AVPixelFormat getAVVideoFormatbyMFVideoFormat(const GUID &MFVideoFormat);
140
AVSampleFormat getAVAudioFormatbyMFAudioFormat(const GUID &MFAudioFormat, const u32 &bitsPerSample);
141
142
/*
143
* Always convert the image to RGB24
144
* @param dst/src pointer to destination/source image
145
* @param dstW/srcW, dstH/srcH destination/source image's width and height in pixels
146
* @param dstLineSizes get the linesize of each plane by av_image_fill_linesizes()
147
* @param srcFormat MF_MT_SUBTYPE attribute of source image
148
* @param srcPadding should be setted to non-zero if source image has padding
149
*/
150
void imgConvert(
151
unsigned char *dst, unsigned int &dstW, unsigned int &dstH, int dstLineSizes[4],
152
unsigned char *src, const unsigned int &srcW, const unsigned int &srcH, const GUID &srcFormat,
153
const int &srcPadding);
154
155
// Flip image start and end in memory, it is neccessary if stride of source image is a negative value
156
// Might need some tests in different machine.
157
void imgInvert(unsigned char *dst, unsigned char *src, const int &srcW, const int &srcH, const GUID &srcFormat, const int &srcStride);
158
void imgInvertRGBA(unsigned char *dst, int &dstStride, unsigned char *src, const int &srcStride, const int &h);
159
void imgInvertRGB(unsigned char *dst, int &dstStride, unsigned char *src, const int &srcStride, const int &h);
160
void imgInvertYUY2(unsigned char *dst, int &dstStride, unsigned char *src, const int &srcStride, const int &h);
161
void imgInvertNV12(unsigned char *dst, int &dstStride, unsigned char *src, const int &srcStride, const int &h);
162
163
/*
164
* Always resample to uncompressed signed 16bits
165
* @param dst pointer to pointer of dst buffer could be a nullptr, would be overwritten by a new pointer if space too small or a nullptr, should be freed by av_free/av_freep by caller
166
* @param dstSize pointer to size of the dst buffer, could be modified after this func
167
* @param srcFormat MF_MT_SUBTYPE attribute of the source audio data
168
* @param srcSize size of valid data in the source buffer, in bytes
169
* @return size of output in bytes
170
*/
171
u32 doResample(u8 **dst, u32 &dstSampleRate, u32 &dstChannels, u32 *dstSize, u8 *src, const u32 &srcSampleRate, const u32 &srcChannels, const GUID &srcFormat, const u32 &srcSize, const u32& srcBitsPerSamples);
172
173
protected:
174
WindowsCaptureDevice *device;
175
SwsContext *img_convert_ctx = nullptr;
176
SwrContext *resample_ctx = nullptr;
177
};
178
179
class WindowsCaptureDevice {
180
public:
181
WindowsCaptureDevice(CAPTUREDEVIDE_TYPE type);
182
~WindowsCaptureDevice();
183
184
void CheckDevices();
185
186
bool init();
187
bool start(void *startParam);
188
bool stop();
189
190
CAPTUREDEVIDE_ERROR getError() const { return error; }
191
std::string getErrorMessage() const { return errorMessage; }
192
int getDeviceCounts() const { return param.count; }
193
// Get a list contained friendly device name.
194
std::vector<std::string> getDeviceList(bool forceEnum = false, int *pActuallCount = nullptr);
195
196
void setError(const CAPTUREDEVIDE_ERROR &newError, const std::string &newErrorMessage) { error = newError; errorMessage = newErrorMessage; }
197
void setSelection(const UINT32 &selection) { param.selection = selection; }
198
HRESULT setDeviceParam(IMFMediaType *pType);
199
200
bool isShutDown() const { return state == CAPTUREDEVIDE_STATE::SHUTDOWN; }
201
bool isStarted() const { return state == CAPTUREDEVIDE_STATE::STARTED; }
202
void waitShutDown();
203
204
void sendMessage(CAPTUREDEVIDE_MESSAGE message);
205
CAPTUREDEVIDE_MESSAGE getMessage();
206
207
HRESULT enumDevices();
208
209
bool needResample();
210
211
friend class ReaderCallback;
212
213
protected:
214
void updateState(const CAPTUREDEVIDE_STATE &newState);
215
// Handle message here.
216
void messageHandler();
217
218
CAPTUREDEVIDE_TYPE type;
219
MediaParam deviceParam;
220
MediaParam targetMediaParam;
221
CAPTUREDEVIDE_STATE state;
222
ChooseDeviceParam param;
223
224
CAPTUREDEVIDE_ERROR error;
225
std::string errorMessage;
226
227
bool isDeviceChanged = false;
228
229
// MF interface.
230
Microsoft::WRL::ComPtr<ReaderCallback> m_pCallback;
231
Microsoft::WRL::ComPtr<IMFSourceReader> m_pReader;
232
Microsoft::WRL::ComPtr<IMFMediaSource> m_pSource;
233
234
// Message loop.
235
std::mutex mutex;
236
std::condition_variable cond;
237
std::queue<CAPTUREDEVIDE_MESSAGE> messageQueue;
238
239
// For the shutdown event safety.
240
std::mutex sdMutex;
241
242
// Param updating synchronously.
243
std::mutex paramMutex;
244
std::mutex stateMutex_;
245
std::condition_variable stateCond_;
246
247
// Camera only
248
unsigned char *imageRGB = nullptr;
249
int imgRGBLineSizes[4]{};
250
unsigned char *imageJpeg = nullptr;
251
int imgJpegSize = 0;
252
253
//Microphone only
254
u8 *resampleBuf = nullptr;
255
u32 resampleBufSize = 0;
256
};
257
258
extern WindowsCaptureDevice *winCamera;
259
extern WindowsCaptureDevice *winMic;
260
261