CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In
hrydgard

CoCalc provides the best real-time collaborative environment for Jupyter Notebooks, LaTeX documents, and SageMath, scalable from individual users to large groups and classes!

GitHub Repository: hrydgard/ppsspp
Path: blob/master/Windows/CaptureDevice.h
Views: 1401
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
29
#include "Core/HLE/sceUsbMic.h"
30
31
#ifdef __cplusplus
32
extern "C" {
33
#include "libavformat/avformat.h"
34
#include "libswscale/swscale.h"
35
#include "libswresample/swresample.h"
36
#include "libavutil/imgutils.h"
37
}
38
#endif // __cplusplus
39
40
struct VideoFormatTransform {
41
GUID MFVideoFormat;
42
AVPixelFormat AVVideoFormat;
43
};
44
45
struct AudioFormatTransform {
46
GUID MFAudioFormat;
47
u32 bitsPerSample;
48
AVSampleFormat AVAudioFormat;
49
};
50
51
enum class CAPTUREDEVIDE_TYPE {
52
VIDEO,
53
Audio
54
};
55
56
enum class CAPTUREDEVIDE_STATE {
57
UNINITIALIZED,
58
LOST,
59
STOPPED,
60
STARTED,
61
SHUTDOWN
62
};
63
64
enum class CAPTUREDEVIDE_COMMAND {
65
INITIALIZE,
66
START,
67
STOP,
68
SHUTDOWN,
69
UPDATE_STATE
70
};
71
72
enum CAPTUREDEVIDE_ERROR {
73
CAPTUREDEVIDE_ERROR_NO_ERROR,
74
CAPTUREDEVIDE_ERROR_UNKNOWN_TYPE = 0x80000001,
75
CAPTUREDEVIDE_ERROR_INIT_FAILED,
76
CAPTUREDEVIDE_ERROR_START_FAILED,
77
CAPTUREDEVIDE_ERROR_STOP_FAILED,
78
CAPTUREDEVIDE_ERROR_GETNAMES_FAILED
79
};
80
81
struct CAPTUREDEVIDE_MESSAGE{
82
CAPTUREDEVIDE_COMMAND command;
83
void *opacity;
84
};
85
86
struct ChooseDeviceParam {
87
IMFActivate **ppDevices;
88
UINT32 count;
89
UINT32 selection;
90
};
91
92
union MediaParam {
93
struct {
94
UINT32 width;
95
UINT32 height;
96
LONG default_stride;
97
GUID videoFormat;
98
};
99
struct {
100
UINT32 sampleRate;
101
UINT32 channels;
102
LONG bitsPerSample;
103
GUID audioFormat;
104
};
105
};
106
107
template <class T> void SafeRelease(T **ppT) {
108
if (*ppT) {
109
(*ppT)->Release();
110
*ppT = nullptr;
111
}
112
}
113
114
class WindowsCaptureDevice;
115
116
class ReaderCallback final : public IMFSourceReaderCallback {
117
public:
118
ReaderCallback(WindowsCaptureDevice *device);
119
virtual ~ReaderCallback();
120
121
// IUnknown methods.
122
STDMETHODIMP QueryInterface(REFIID iid, void** ppv) override;
123
STDMETHODIMP_(ULONG) AddRef() override { return 0; } // Unused, just define.
124
STDMETHODIMP_(ULONG) Release() override { return 0; } // Unused, just define.
125
126
// IMFSourceReaderCallback methods.
127
STDMETHODIMP OnReadSample(
128
HRESULT hrStatus,
129
DWORD dwStreamIndex,
130
DWORD dwStreamFlags,
131
LONGLONG llTimestamp,
132
IMFSample *pSample // Can be null,even if hrStatus is success.
133
) override;
134
135
STDMETHODIMP OnEvent(DWORD, IMFMediaEvent *) override { return S_OK; }
136
STDMETHODIMP OnFlush(DWORD) override { return S_OK; }
137
138
AVPixelFormat getAVVideoFormatbyMFVideoFormat(const GUID &MFVideoFormat);
139
AVSampleFormat getAVAudioFormatbyMFAudioFormat(const GUID &MFAudioFormat, const u32 &bitsPerSample);
140
141
/*
142
* Always convert the image to RGB24
143
* @param dst/src pointer to destination/source image
144
* @param dstW/srcW, dstH/srcH destination/source image's width and height in pixels
145
* @param dstLineSizes get the linesize of each plane by av_image_fill_linesizes()
146
* @param srcFormat MF_MT_SUBTYPE attribute of source image
147
* @param srcPadding should be setted to non-zero if source image has padding
148
*/
149
void imgConvert(
150
unsigned char *dst, unsigned int &dstW, unsigned int &dstH, int dstLineSizes[4],
151
unsigned char *src, const unsigned int &srcW, const unsigned int &srcH, const GUID &srcFormat,
152
const int &srcPadding);
153
154
// Flip image start and end in memory, it is neccessary if stride of source image is a negative value
155
// Might need some tests in different machine.
156
void imgInvert(unsigned char *dst, unsigned char *src, const int &srcW, const int &srcH, const GUID &srcFormat, const int &srcStride);
157
void imgInvertRGBA(unsigned char *dst, int &dstStride, unsigned char *src, const int &srcStride, const int &h);
158
void imgInvertRGB(unsigned char *dst, int &dstStride, unsigned char *src, const int &srcStride, const int &h);
159
void imgInvertYUY2(unsigned char *dst, int &dstStride, unsigned char *src, const int &srcStride, const int &h);
160
void imgInvertNV12(unsigned char *dst, int &dstStride, unsigned char *src, const int &srcStride, const int &h);
161
162
/*
163
* Always resample to uncompressed signed 16bits
164
* @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
165
* @param dstSize pointer to size of the dst buffer, could be modified after this func
166
* @param srcFormat MF_MT_SUBTYPE attribute of the source audio data
167
* @param srcSize size of valid data in the source buffer, in bytes
168
* @return size of output in bytes
169
*/
170
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);
171
172
protected:
173
WindowsCaptureDevice *device;
174
SwsContext *img_convert_ctx = nullptr;
175
SwrContext *resample_ctx = nullptr;
176
};
177
178
class WindowsCaptureDevice {
179
public:
180
WindowsCaptureDevice(CAPTUREDEVIDE_TYPE type);
181
~WindowsCaptureDevice();
182
183
void CheckDevices();
184
185
bool init();
186
bool start(void *startParam);
187
bool stop();
188
189
CAPTUREDEVIDE_ERROR getError() const { return error; }
190
std::string getErrorMessage() const { return errorMessage; }
191
int getDeviceCounts() const { return param.count; }
192
// Get a list contained friendly device name.
193
std::vector<std::string> getDeviceList(bool forceEnum = false, int *pActuallCount = nullptr);
194
195
void setError(const CAPTUREDEVIDE_ERROR &newError, const std::string &newErrorMessage) { error = newError; errorMessage = newErrorMessage; }
196
void setSelction(const UINT32 &selection) { param.selection = selection; }
197
HRESULT setDeviceParam(IMFMediaType *pType);
198
199
bool isShutDown() const { return state == CAPTUREDEVIDE_STATE::SHUTDOWN; }
200
bool isStarted() const { return state == CAPTUREDEVIDE_STATE::STARTED; }
201
void waitShutDown();
202
203
void sendMessage(CAPTUREDEVIDE_MESSAGE message);
204
CAPTUREDEVIDE_MESSAGE getMessage();
205
206
HRESULT enumDevices();
207
208
bool needResample();
209
210
friend class ReaderCallback;
211
212
protected:
213
void updateState(const CAPTUREDEVIDE_STATE &newState);
214
// Handle message here.
215
void messageHandler();
216
217
CAPTUREDEVIDE_TYPE type;
218
MediaParam deviceParam;
219
MediaParam targetMediaParam;
220
CAPTUREDEVIDE_STATE state;
221
ChooseDeviceParam param;
222
223
CAPTUREDEVIDE_ERROR error;
224
std::string errorMessage;
225
226
bool isDeviceChanged = false;
227
228
// MF interface.
229
ReaderCallback *m_pCallback = nullptr;
230
IMFSourceReader *m_pReader = nullptr;
231
IMFMediaSource *m_pSource = nullptr;
232
233
// Message loop.
234
std::mutex mutex;
235
std::condition_variable cond;
236
std::queue<CAPTUREDEVIDE_MESSAGE> messageQueue;
237
238
// For the shutdown event safety.
239
std::mutex sdMutex;
240
241
// Param updating synchronously.
242
std::mutex paramMutex;
243
std::mutex stateMutex_;
244
std::condition_variable stateCond_;
245
246
// Camera only
247
unsigned char *imageRGB = nullptr;
248
int imgRGBLineSizes[4]{};
249
unsigned char *imageJpeg = nullptr;
250
int imgJpegSize = 0;
251
252
//Microphone only
253
u8 *resampleBuf = nullptr;
254
u32 resampleBufSize = 0;
255
};
256
257
extern WindowsCaptureDevice *winCamera;
258
extern WindowsCaptureDevice *winMic;
259
260