CoCalc provides the best real-time collaborative environment for Jupyter Notebooks, LaTeX documents, and SageMath, scalable from individual users to large groups and classes!
CoCalc provides the best real-time collaborative environment for Jupyter Notebooks, LaTeX documents, and SageMath, scalable from individual users to large groups and classes!
Path: blob/master/Windows/CaptureDevice.h
Views: 1401
// Copyright (c) 2020- PPSSPP Project.12// This program is free software: you can redistribute it and/or modify3// it under the terms of the GNU General Public License as published by4// the Free Software Foundation, version 2.0 or later versions.56// This program is distributed in the hope that it will be useful,7// but WITHOUT ANY WARRANTY; without even the implied warranty of8// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the9// GNU General Public License 2.0 for more details.1011// A copy of the GPL 2.0 should have been included with the program.12// If not, see http://www.gnu.org/licenses/1314// Official git repository and contact information can be found at15// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.1617#pragma once1819#include <mfapi.h>20#include <mfidl.h>21#include <mfreadwrite.h>22#include <mutex>23#include <condition_variable>24#include <vector>25#include <queue>26#include <thread>2728#include "Core/HLE/sceUsbMic.h"2930#ifdef __cplusplus31extern "C" {32#include "libavformat/avformat.h"33#include "libswscale/swscale.h"34#include "libswresample/swresample.h"35#include "libavutil/imgutils.h"36}37#endif // __cplusplus3839struct VideoFormatTransform {40GUID MFVideoFormat;41AVPixelFormat AVVideoFormat;42};4344struct AudioFormatTransform {45GUID MFAudioFormat;46u32 bitsPerSample;47AVSampleFormat AVAudioFormat;48};4950enum class CAPTUREDEVIDE_TYPE {51VIDEO,52Audio53};5455enum class CAPTUREDEVIDE_STATE {56UNINITIALIZED,57LOST,58STOPPED,59STARTED,60SHUTDOWN61};6263enum class CAPTUREDEVIDE_COMMAND {64INITIALIZE,65START,66STOP,67SHUTDOWN,68UPDATE_STATE69};7071enum CAPTUREDEVIDE_ERROR {72CAPTUREDEVIDE_ERROR_NO_ERROR,73CAPTUREDEVIDE_ERROR_UNKNOWN_TYPE = 0x80000001,74CAPTUREDEVIDE_ERROR_INIT_FAILED,75CAPTUREDEVIDE_ERROR_START_FAILED,76CAPTUREDEVIDE_ERROR_STOP_FAILED,77CAPTUREDEVIDE_ERROR_GETNAMES_FAILED78};7980struct CAPTUREDEVIDE_MESSAGE{81CAPTUREDEVIDE_COMMAND command;82void *opacity;83};8485struct ChooseDeviceParam {86IMFActivate **ppDevices;87UINT32 count;88UINT32 selection;89};9091union MediaParam {92struct {93UINT32 width;94UINT32 height;95LONG default_stride;96GUID videoFormat;97};98struct {99UINT32 sampleRate;100UINT32 channels;101LONG bitsPerSample;102GUID audioFormat;103};104};105106template <class T> void SafeRelease(T **ppT) {107if (*ppT) {108(*ppT)->Release();109*ppT = nullptr;110}111}112113class WindowsCaptureDevice;114115class ReaderCallback final : public IMFSourceReaderCallback {116public:117ReaderCallback(WindowsCaptureDevice *device);118virtual ~ReaderCallback();119120// IUnknown methods.121STDMETHODIMP QueryInterface(REFIID iid, void** ppv) override;122STDMETHODIMP_(ULONG) AddRef() override { return 0; } // Unused, just define.123STDMETHODIMP_(ULONG) Release() override { return 0; } // Unused, just define.124125// IMFSourceReaderCallback methods.126STDMETHODIMP OnReadSample(127HRESULT hrStatus,128DWORD dwStreamIndex,129DWORD dwStreamFlags,130LONGLONG llTimestamp,131IMFSample *pSample // Can be null,even if hrStatus is success.132) override;133134STDMETHODIMP OnEvent(DWORD, IMFMediaEvent *) override { return S_OK; }135STDMETHODIMP OnFlush(DWORD) override { return S_OK; }136137AVPixelFormat getAVVideoFormatbyMFVideoFormat(const GUID &MFVideoFormat);138AVSampleFormat getAVAudioFormatbyMFAudioFormat(const GUID &MFAudioFormat, const u32 &bitsPerSample);139140/*141* Always convert the image to RGB24142* @param dst/src pointer to destination/source image143* @param dstW/srcW, dstH/srcH destination/source image's width and height in pixels144* @param dstLineSizes get the linesize of each plane by av_image_fill_linesizes()145* @param srcFormat MF_MT_SUBTYPE attribute of source image146* @param srcPadding should be setted to non-zero if source image has padding147*/148void imgConvert(149unsigned char *dst, unsigned int &dstW, unsigned int &dstH, int dstLineSizes[4],150unsigned char *src, const unsigned int &srcW, const unsigned int &srcH, const GUID &srcFormat,151const int &srcPadding);152153// Flip image start and end in memory, it is neccessary if stride of source image is a negative value154// Might need some tests in different machine.155void imgInvert(unsigned char *dst, unsigned char *src, const int &srcW, const int &srcH, const GUID &srcFormat, const int &srcStride);156void imgInvertRGBA(unsigned char *dst, int &dstStride, unsigned char *src, const int &srcStride, const int &h);157void imgInvertRGB(unsigned char *dst, int &dstStride, unsigned char *src, const int &srcStride, const int &h);158void imgInvertYUY2(unsigned char *dst, int &dstStride, unsigned char *src, const int &srcStride, const int &h);159void imgInvertNV12(unsigned char *dst, int &dstStride, unsigned char *src, const int &srcStride, const int &h);160161/*162* Always resample to uncompressed signed 16bits163* @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 caller164* @param dstSize pointer to size of the dst buffer, could be modified after this func165* @param srcFormat MF_MT_SUBTYPE attribute of the source audio data166* @param srcSize size of valid data in the source buffer, in bytes167* @return size of output in bytes168*/169u32 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);170171protected:172WindowsCaptureDevice *device;173SwsContext *img_convert_ctx = nullptr;174SwrContext *resample_ctx = nullptr;175};176177class WindowsCaptureDevice {178public:179WindowsCaptureDevice(CAPTUREDEVIDE_TYPE type);180~WindowsCaptureDevice();181182void CheckDevices();183184bool init();185bool start(void *startParam);186bool stop();187188CAPTUREDEVIDE_ERROR getError() const { return error; }189std::string getErrorMessage() const { return errorMessage; }190int getDeviceCounts() const { return param.count; }191// Get a list contained friendly device name.192std::vector<std::string> getDeviceList(bool forceEnum = false, int *pActuallCount = nullptr);193194void setError(const CAPTUREDEVIDE_ERROR &newError, const std::string &newErrorMessage) { error = newError; errorMessage = newErrorMessage; }195void setSelction(const UINT32 &selection) { param.selection = selection; }196HRESULT setDeviceParam(IMFMediaType *pType);197198bool isShutDown() const { return state == CAPTUREDEVIDE_STATE::SHUTDOWN; }199bool isStarted() const { return state == CAPTUREDEVIDE_STATE::STARTED; }200void waitShutDown();201202void sendMessage(CAPTUREDEVIDE_MESSAGE message);203CAPTUREDEVIDE_MESSAGE getMessage();204205HRESULT enumDevices();206207bool needResample();208209friend class ReaderCallback;210211protected:212void updateState(const CAPTUREDEVIDE_STATE &newState);213// Handle message here.214void messageHandler();215216CAPTUREDEVIDE_TYPE type;217MediaParam deviceParam;218MediaParam targetMediaParam;219CAPTUREDEVIDE_STATE state;220ChooseDeviceParam param;221222CAPTUREDEVIDE_ERROR error;223std::string errorMessage;224225bool isDeviceChanged = false;226227// MF interface.228ReaderCallback *m_pCallback = nullptr;229IMFSourceReader *m_pReader = nullptr;230IMFMediaSource *m_pSource = nullptr;231232// Message loop.233std::mutex mutex;234std::condition_variable cond;235std::queue<CAPTUREDEVIDE_MESSAGE> messageQueue;236237// For the shutdown event safety.238std::mutex sdMutex;239240// Param updating synchronously.241std::mutex paramMutex;242std::mutex stateMutex_;243std::condition_variable stateCond_;244245// Camera only246unsigned char *imageRGB = nullptr;247int imgRGBLineSizes[4]{};248unsigned char *imageJpeg = nullptr;249int imgJpegSize = 0;250251//Microphone only252u8 *resampleBuf = nullptr;253u32 resampleBufSize = 0;254};255256extern WindowsCaptureDevice *winCamera;257extern WindowsCaptureDevice *winMic;258259260