8#include <private/qmemoryvideobuffer_p.h>
9#include <private/qwindowsmfdefs_p.h>
10#include <private/qwindowsmultimediautils_p.h>
15#include <mfreadwrite.h>
17#include <system_error>
34 if (
riid == IID_IMFSourceReaderCallback) {
35 *ppvObject =
static_cast<IMFSourceReaderCallback*
>(
this);
36 }
else if (
riid == IID_IUnknown) {
37 *ppvObject =
static_cast<IUnknown*
>(
static_cast<IMFSourceReaderCallback*
>(
this));
48 return InterlockedIncrement(&m_cRef);
53 LONG cRef = InterlockedDecrement(&m_cRef);
61 STDMETHODIMP
OnReadSample(
HRESULT status, DWORD, DWORD, LONGLONG timestamp, IMFSample *sample)
override;
62 STDMETHODIMP
OnFlush(DWORD)
override;
63 STDMETHODIMP
OnEvent(DWORD, IMFMediaEvent *)
override {
return S_OK; }
68 m_activeCamera = activeCamera;
77 const ComPtr<CameraReaderCallback> &callback)
79 ComPtr<IMFSourceReader> sourceReader;
80 ComPtr<IMFAttributes> readerAttributes;
82 HRESULT hr = MFCreateAttributes(readerAttributes.GetAddressOf(), 1);
84 hr = readerAttributes->SetUnknown(MF_SOURCE_READER_ASYNC_CALLBACK, callback.Get());
86 hr = MFCreateSourceReaderFromMediaSource(mediaSource, readerAttributes.Get(), sourceReader.GetAddressOf());
92 qWarning() <<
"Failed to create camera IMFSourceReader" << hr;
98 ComPtr<IMFMediaSource> mediaSource;
99 ComPtr<IMFAttributes> sourceAttributes;
100 HRESULT hr = MFCreateAttributes(sourceAttributes.GetAddressOf(), 2);
104 hr = sourceAttributes->SetString(MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_SYMBOLIC_LINK,
105 reinterpret_cast<LPCWSTR
>(deviceId.
utf16()));
113 qWarning() <<
"Failed to create camera IMFMediaSource" << hr;
121 GUID subtype = GUID_NULL;
122 HRESULT hr = videoType->GetGUID(MF_MT_SUBTYPE, &subtype);
125 hr = MFGetStrideForBitmapInfoHeader(subtype.Data1,
width, &
stride);
139 HRESULT hr = sourceReader->SetCurrentMediaType(MF_SOURCE_READER_FIRST_VIDEO_STREAM,
nullptr,
144 return SUCCEEDED(hr);
150 for (DWORD
i = 0;; ++
i) {
151 ComPtr<IMFMediaType> candidate;
152 HRESULT hr = reader->GetNativeMediaType(MF_SOURCE_READER_FIRST_VIDEO_STREAM,
i,
153 candidate.GetAddressOf());
157 GUID subtype = GUID_NULL;
158 if (FAILED(candidate->GetGUID(MF_MT_SUBTYPE, &subtype)))
166 if (FAILED(MFGetAttributeSize(candidate.Get(), MF_MT_FRAME_SIZE, &
width, &
height)))
169 if (
format.resolution() !=
QSize{ int(width), int(height) })
183 auto ac = std::unique_ptr<ActiveCamera>(
new ActiveCamera(wc));
188 ac->m_readerCallback = makeComObject<CameraReaderCallback>();
189 ac->m_readerCallback->setActiveCamera(ac.get());
194 if (!ac->setFormat(
format))
202 m_reader->Flush(MF_SOURCE_READER_FIRST_VIDEO_STREAM);
214 m_reader->ReadSample(MF_SOURCE_READER_FIRST_VIDEO_STREAM, 0,
nullptr,
nullptr,
nullptr,
221 if (FAILED(status)) {
222 emit m_windowsCamera.
error(
int(status), std::system_category().
message(status).c_str());
227 ComPtr<IMFMediaBuffer> mediaBuffer;
228 if (SUCCEEDED(sample->ConvertToContiguousBuffer(mediaBuffer.GetAddressOf()))) {
232 if (SUCCEEDED(mediaBuffer->Lock(&
buffer,
nullptr, &bufLen))) {
237 frame.setStartTime(timestamp / 10);
239 LONGLONG duration = -1;
240 if (SUCCEEDED(sample->GetSampleDuration(&duration)))
241 frame.setEndTime((timestamp + duration) / 10);
244 mediaBuffer->Unlock();
249 m_reader->ReadSample(MF_SOURCE_READER_FIRST_VIDEO_STREAM, 0,
nullptr,
250 nullptr,
nullptr,
nullptr);
260 m_reader->Flush(MF_SOURCE_READER_FIRST_VIDEO_STREAM);
262 m_readerCallback->setActiveCamera(
nullptr);
272 ComPtr<IMFMediaSource> m_source;
273 ComPtr<IMFSourceReader> m_reader;
274 ComPtr<CameraReaderCallback> m_readerCallback;
277 int m_videoFrameStride = 0;
284 m_activeCamera->
onReadSample(status, timestamp, sample);
310 if (
bool(m_active) == active)
314 if (m_cameraDevice.
isNull())
317 if (m_cameraFormat.
isNull())
332 bool active = bool(m_active);
346 bool ok = m_active ? m_active->setFormat(
format) :
true;
IOBluetoothDevice * device
bool setFormat(const QCameraFormat &format)
static std::unique_ptr< ActiveCamera > create(QWindowsCamera &wc, const QCameraDevice &device, const QCameraFormat &format)
void onReadSample(HRESULT status, LONGLONG timestamp, IMFSample *sample)
STDMETHODIMP OnReadSample(HRESULT status, DWORD, DWORD, LONGLONG timestamp, IMFSample *sample) override
STDMETHODIMP_(ULONG) Release() override
virtual ~CameraReaderCallback()
STDMETHODIMP OnEvent(DWORD, IMFMediaEvent *) override
STDMETHODIMP OnFlush(DWORD) override
void setActiveCamera(ActiveCamera *activeCamera)
STDMETHODIMP QueryInterface(REFIID riid, LPVOID *ppvObject) override
STDMETHODIMP_(ULONG) AddRef() override
The QCameraDevice class provides general information about camera devices.
bool isNull() const
Returns true if this QCameraDevice is null or invalid.
The QCamera class provides interface for system camera devices.
QCameraDevice cameraDevice
\qmlproperty cameraDevice QtMultimedia::Camera::cameraDevice
The QMemoryVideoBuffer class provides a system memory allocated video data buffer.
void acquire(int n=1)
Tries to acquire n resources guarded by the semaphore.
void release(int n=1)
Releases n resources guarded by the semaphore.
\macro QT_RESTRICTED_CAST_FROM_ASCII
const ushort * utf16() const
Returns the QString as a '\0\'-terminated array of unsigned shorts.
The QVideoFrame class represents a frame of video data.
bool setCameraFormat(const QCameraFormat &) override
void setCamera(const QCameraDevice &camera) override
void setActive(bool active) override
QWindowsCamera(QCamera *parent)
~QWindowsCamera() override
static int calculateVideoFrameStride(IMFMediaType *videoType, int width)
static bool setCameraReaderFormat(IMFSourceReader *sourceReader, IMFMediaType *videoType)
static ComPtr< IMFSourceReader > createCameraReader(IMFMediaSource *mediaSource, const ComPtr< CameraReaderCallback > &callback)
static ComPtr< IMFMediaType > findVideoType(IMFSourceReader *reader, const QCameraFormat &format)
static ComPtr< IMFMediaSource > createCameraSource(const QString &deviceId)
Combined button and popup list for selecting options.
constexpr T qAbs(const T &t)
GLint GLsizei GLsizei height
const void GLsizei GLsizei stride
GLuint GLsizei const GLchar * message
GLint GLsizei GLsizei GLenum format
IUIViewSettingsInterop __RPC__in REFIID riid
const GUID QMM_MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_GUID
HRESULT WINAPI MFCreateDeviceSource(IMFAttributes *pAttributes, IMFMediaSource **ppSource)