-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcapture.h
More file actions
160 lines (135 loc) · 5.36 KB
/
capture.h
File metadata and controls
160 lines (135 loc) · 5.36 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
//////////////////////////////////////////////////////////////////////////
//
// capture.h: Manages video capture.
//
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
// PARTICULAR PURPOSE.
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//////////////////////////////////////////////////////////////////////////
#pragma once
#include <windows.h>
#include <Dbt.h>
#include <mfapi.h>
#include <mfidl.h>
#include <mfreadwrite.h>
#include <wincodec.h>
#include <string>
#include <functional>
#include <utility>
#include <vector>
#include <tuple>
template <class T>
inline void SafeRelease(T** ppT) {
if (ppT && *ppT) {
(*ppT)->Release();
*ppT = NULL;
}
}
const UINT WM_APP_PREVIEW_ERROR = WM_APP + 1; // wparam = HRESULT
class DeviceList {
UINT32 m_cDevices;
IMFActivate** m_ppDevices;
public:
DeviceList() : m_ppDevices(NULL), m_cDevices(0) {
}
~DeviceList() {
Clear();
}
UINT32 Count() const { return m_cDevices; }
void Clear();
// Find and return the IMFActivate whose friendly name or symbolic link matches
// the provided identifier (case-insensitive). The returned IMFActivate is AddRef'd.
HRESULT GetDevice(const WCHAR* identifier, IMFActivate** ppActivate);
// Returns a vector of (friendlyName, symbolicLink) copied into std::wstring
HRESULT GetAllDevices(std::vector<std::pair<std::wstring, std::wstring>>& outDevices);
};
struct EncodingParameters {
GUID subtype;
UINT32 bitrate;
};
class CCapture : public IMFSourceReaderCallback {
public:
static HRESULT CreateInstance(
HWND hwnd,
CCapture** ppPlayer);
// IUnknown methods
STDMETHODIMP QueryInterface(REFIID iid, void** ppv);
STDMETHODIMP_(ULONG)
AddRef();
STDMETHODIMP_(ULONG)
Release();
// IMFSourceReaderCallback methods
STDMETHODIMP OnReadSample(
HRESULT hrStatus,
DWORD dwStreamIndex,
DWORD dwStreamFlags,
LONGLONG llTimestamp,
IMFSample* pSample);
STDMETHODIMP OnEvent(DWORD, IMFMediaEvent*) {
return S_OK;
}
STDMETHODIMP OnFlush(DWORD) {
return S_OK;
}
HRESULT StartCapture(IMFActivate* pActivate, const EncodingParameters& param);
HRESULT EndCaptureSession();
BOOL IsCapturing();
HRESULT CheckDeviceLost(DEV_BROADCAST_HDR* pHdr, BOOL* pbDeviceLost);
// Initialize internal reader from an IMFActivate without starting capture
HRESULT InitFromActivate(IMFActivate* pActivate);
// Enumerate native media types including subtype GUID for richer info
HRESULT GetSupportedFormats(std::vector<std::tuple<GUID, UINT32, UINT32, double>>& outTypes);
// Set the desired native media type on the source reader by explicit native subtype GUID
HRESULT SetFormat(const GUID& subtype, UINT32 width, UINT32 height, double frameRate);
// Get current dimensions from the source reader (width, height, frameRate)
HRESULT GetCurrentDimensions(UINT32* pWidth, UINT32* pHeight, double* pFrameRate);
// Provide a callback to receive raw frame buffers (moved into the callback)
void SetFrameCallback(std::function<void(std::vector<uint8_t>&&)> cb) { m_frameCallback = std::move(cb); }
// Set output format for conversion (GUID_NULL = no conversion, pass-through)
// Supported: MFVideoFormat_RGB32, MFVideoFormat_RGB24, MFVideoFormat_NV12, MFVideoFormat_YUY2, etc.
HRESULT SetOutputFormat(const GUID& outputSubtype);
// Clear output format (disable conversion, return raw frames)
void ClearOutputFormat();
// Return last enumerated supported formats (stored internally)
// Deprecated: removed internal cached supported formats
// (EnumerateFormatsFromActivate removed; CCapture now supports InitFromActivate and GetSupportedFormats)
// Release all claimed device resources and reset state
HRESULT ReleaseDevice();
HRESULT EndCaptureInternal();
protected:
enum State {
State_NotReady = 0,
State_Ready,
State_Capturing,
};
// Constructor is private. Use static CreateInstance method to instantiate.
CCapture(HWND hwnd);
// Destructor is private. Caller should call Release.
virtual ~CCapture();
void NotifyError(HRESULT hr) { PostMessage(m_hwndEvent, WM_APP_PREVIEW_ERROR, (WPARAM)hr, 0L); }
HRESULT OpenMediaSource(IMFMediaSource* pSource);
HRESULT ConfigureCapture(const EncodingParameters& param);
long m_nRefCount; // Reference count.
CRITICAL_SECTION m_critsec;
HWND m_hwndEvent; // Application window to receive events.
IMFSourceReader* m_pReader;
BOOL m_bFirstSample;
LONGLONG m_llBaseTime;
WCHAR* m_pwszSymbolicLink;
// (removed) cache of last enumerated formats
// Frame callback used when delivering frames to the embedding (JS)
std::function<void(std::vector<uint8_t>&&)> m_frameCallback;
// Reusable buffer for frame conversion
std::vector<uint8_t> m_rgbaBuffer;
// Output format conversion
GUID m_outputFormat; // Target output subtype (GUID_NULL = no conversion)
IWICImagingFactory* m_pWicFactory; // WIC factory for JPEG encoding
// Internal: encode frame to JPEG using WIC
HRESULT EncodeToJpeg(const uint8_t* rgbData, UINT32 width, UINT32 height, bool isBGRA, std::vector<uint8_t>& outBuffer);
// Internal: convert sample to output format
HRESULT ConvertFrame(IMFSample* pSample, const GUID& inputSubtype, UINT32 width, UINT32 height, std::vector<uint8_t>& outBuffer);
};