8#include <private/qmemoryvideobuffer_p.h>
9#include <private/qwindowsmfdefs_p.h>
10#include <private/qwindowsmultimediautils_p.h>
11#include <private/qcomobject_p.h>
16#include <mfreadwrite.h>
18#include <system_error>
28 STDMETHODIMP
OnReadSample(
HRESULT status, DWORD, DWORD, LONGLONG timestamp, IMFSample *sample)
override;
29 STDMETHODIMP
OnFlush(DWORD)
override;
30 STDMETHODIMP
OnEvent(DWORD, IMFMediaEvent *)
override {
return S_OK; }
35 m_activeCamera = activeCamera;
46 const ComPtr<CameraReaderCallback> &callback)
48 ComPtr<IMFSourceReader> sourceReader;
49 ComPtr<IMFAttributes> readerAttributes;
51 HRESULT hr = MFCreateAttributes(readerAttributes.GetAddressOf(), 1);
53 hr = readerAttributes->SetUnknown(MF_SOURCE_READER_ASYNC_CALLBACK, callback.Get());
55 hr = MFCreateSourceReaderFromMediaSource(mediaSource, readerAttributes.Get(), sourceReader.GetAddressOf());
61 qWarning() <<
"Failed to create camera IMFSourceReader" << hr;
67 ComPtr<IMFMediaSource> mediaSource;
68 ComPtr<IMFAttributes> sourceAttributes;
69 HRESULT hr = MFCreateAttributes(sourceAttributes.GetAddressOf(), 2);
73 hr = sourceAttributes->SetString(MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_SYMBOLIC_LINK,
74 reinterpret_cast<LPCWSTR
>(deviceId.
utf16()));
82 qWarning() <<
"Failed to create camera IMFMediaSource" << hr;
90 GUID subtype = GUID_NULL;
91 HRESULT hr = videoType->GetGUID(MF_MT_SUBTYPE, &subtype);
94 hr = MFGetStrideForBitmapInfoHeader(subtype.Data1,
width, &
stride);
108 HRESULT hr = sourceReader->SetCurrentMediaType(MF_SOURCE_READER_FIRST_VIDEO_STREAM,
nullptr,
113 return SUCCEEDED(hr);
119 for (DWORD
i = 0;; ++
i) {
120 ComPtr<IMFMediaType> candidate;
121 HRESULT hr = reader->GetNativeMediaType(MF_SOURCE_READER_FIRST_VIDEO_STREAM,
i,
122 candidate.GetAddressOf());
126 GUID subtype = GUID_NULL;
127 if (FAILED(candidate->GetGUID(MF_MT_SUBTYPE, &subtype)))
135 if (FAILED(MFGetAttributeSize(candidate.Get(), MF_MT_FRAME_SIZE, &
width, &
height)))
138 if (
format.resolution() !=
QSize{ int(width), int(height) })
150 auto ac = std::unique_ptr<ActiveCamera>(
new ActiveCamera(wc));
155 ac->m_readerCallback = makeComObject<CameraReaderCallback>();
156 ac->m_readerCallback->setActiveCamera(ac.get());
161 if (!ac->setFormat(
format))
180 m_reader->ReadSample(MF_SOURCE_READER_FIRST_VIDEO_STREAM, 0,
nullptr,
nullptr,
nullptr,
187 if (FAILED(status)) {
188 const std::string msg{ std::system_category().message(status) };
194 ComPtr<IMFMediaBuffer> mediaBuffer;
195 if (SUCCEEDED(sample->ConvertToContiguousBuffer(mediaBuffer.GetAddressOf()))) {
199 if (SUCCEEDED(mediaBuffer->Lock(&
buffer,
nullptr, &bufLen))) {
204 frame.setStartTime(timestamp / 10);
206 LONGLONG duration = -1;
207 if (SUCCEEDED(sample->GetSampleDuration(&duration)))
208 frame.setEndTime((timestamp + duration) / 10);
211 mediaBuffer->Unlock();
216 m_reader->ReadSample(MF_SOURCE_READER_FIRST_VIDEO_STREAM, 0,
nullptr,
217 nullptr,
nullptr,
nullptr);
228 m_readerCallback->setActiveCamera(
nullptr);
236 if (SUCCEEDED(m_reader->Flush(MF_SOURCE_READER_FIRST_VIDEO_STREAM))) {
245 ComPtr<IMFMediaSource> m_source;
246 ComPtr<IMFSourceReader> m_reader;
247 ComPtr<CameraReaderCallback> m_readerCallback;
250 int m_videoFrameStride = 0;
257 m_activeCamera->
onReadSample(status, timestamp, sample);
283 if (
bool(m_active) == active)
287 if (m_cameraDevice.
isNull())
290 if (m_cameraFormat.
isNull())
305 bool active = bool(m_active);
319 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 OnEvent(DWORD, IMFMediaEvent *) override
STDMETHODIMP OnFlush(DWORD) override
void setActiveCamera(ActiveCamera *activeCamera)
~CameraReaderCallback() override=default
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.
static QString fromStdString(const std::string &s)
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
GLint GLsizei GLsizei GLenum format
const GUID QMM_MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_GUID
HRESULT WINAPI MFCreateDeviceSource(IMFAttributes *pAttributes, IMFMediaSource **ppSource)