@@ -892,6 +892,8 @@ struct DESKTOPCAPTUREPARAMS
892892 GUID VIDEO_ENCODING_FORMAT = MFVideoFormat_H264;
893893 GUID AUDIO_ENCODING_FORMAT = MFAudioFormat_MP3;
894894 std::wstring f;
895+ std::function<HRESULT(const BYTE* d, size_t sz)> Streamer;
896+ std::function<void (IMFAttributes* a)> PrepareAttributes;
895897 int fps = 25 ;
896898 int NumThreads = 0 ;
897899 int Qu = -1 ;
@@ -913,6 +915,245 @@ struct DESKTOPCAPTUREPARAMS
913915 bool Pause = false ;
914916};
915917
918+
919+ struct VectorStreamX2 : public IMFByteStream
920+ {
921+ ULONG r = 1 ;
922+ std::vector<char > d;
923+ size_t p = 0 ;
924+
925+ // IUnknown
926+ virtual HRESULT STDMETHODCALLTYPE QueryInterface (
927+ /* [in] */ REFIID riid,
928+ /* [iid_is][out] */ _COM_Outptr_ void __RPC_FAR* __RPC_FAR* ppvObject)
929+ {
930+ if (riid == __uuidof (IUnknown) || riid == __uuidof (IMFByteStream))
931+ {
932+ *ppvObject = (IStream*)this ;
933+ r++;
934+ return S_OK;
935+ }
936+ return E_NOINTERFACE;
937+ }
938+
939+ virtual ULONG STDMETHODCALLTYPE AddRef (void )
940+ {
941+ return ++r;
942+ }
943+
944+ virtual ULONG STDMETHODCALLTYPE Release (void )
945+ {
946+ return --r;
947+ }
948+
949+ HRESULT __stdcall BeginRead (
950+ BYTE* pb,
951+ ULONG cb,
952+ IMFAsyncCallback* pCallback,
953+ IUnknown* punkState
954+ )
955+ {
956+ ULONG pcb = 0 ;
957+ Read (pb, cb, &pcb);
958+ NextCB = pcb;
959+ CComPtr<IMFAsyncResult> ar;
960+ MFCreateAsyncResult (0 , pCallback, punkState, &ar);
961+ pCallback->Invoke (ar);
962+ return S_OK;
963+ }
964+
965+ ULONG NextCB = 0 ;
966+ HRESULT __stdcall BeginWrite (
967+ const BYTE* pb,
968+ ULONG cb,
969+ IMFAsyncCallback* pCallback,
970+ IUnknown* punkState
971+ )
972+ {
973+ ULONG pcb = 0 ;
974+ Write (pb, cb, &pcb);
975+ NextCB = pcb;
976+ CComPtr<IMFAsyncResult> ar;
977+ MFCreateAsyncResult (0 , pCallback, punkState, &ar);
978+ pCallback->Invoke (ar);
979+ return S_OK;
980+ }
981+
982+ HRESULT __stdcall Close (
983+
984+ )
985+ {
986+ return S_OK;
987+ }
988+
989+ HRESULT __stdcall EndRead (
990+ IMFAsyncResult* pResult,
991+ ULONG* pcbRead
992+ )
993+ {
994+ if (!pcbRead)
995+ return E_POINTER;
996+ *pcbRead = NextCB;
997+ return S_OK;
998+ }
999+
1000+ HRESULT __stdcall EndWrite (
1001+ IMFAsyncResult* pResult,
1002+ ULONG* pcbWritten
1003+ )
1004+ {
1005+ if (!pcbWritten)
1006+ return E_POINTER;
1007+ *pcbWritten = NextCB;
1008+ return S_OK;
1009+ }
1010+
1011+ HRESULT __stdcall Flush ()
1012+ {
1013+ return S_OK;
1014+ }
1015+
1016+ HRESULT __stdcall GetCapabilities (
1017+ DWORD* pdwCapabilities
1018+ )
1019+ {
1020+ if (!pdwCapabilities)
1021+ return E_POINTER;
1022+ *pdwCapabilities = MFBYTESTREAM_IS_READABLE | MFBYTESTREAM_IS_WRITABLE | MFBYTESTREAM_IS_SEEKABLE;
1023+ return S_OK;
1024+ }
1025+
1026+ HRESULT __stdcall GetCurrentPosition (
1027+ QWORD* pqwPosition
1028+ )
1029+ {
1030+ if (!pqwPosition)
1031+ return E_POINTER;
1032+ *pqwPosition = p;
1033+ return S_OK;
1034+ }
1035+
1036+ HRESULT __stdcall GetLength (
1037+ QWORD* q
1038+ )
1039+ {
1040+ if (!q)
1041+ return E_POINTER;
1042+ *q = d.size ();
1043+ return S_OK;
1044+ }
1045+
1046+ HRESULT __stdcall IsEndOfStream (
1047+ BOOL* q
1048+ )
1049+ {
1050+ if (!q)
1051+ return E_POINTER;
1052+ *q = FALSE ;
1053+ if (p == d.size ())
1054+ *q = TRUE ;
1055+ return S_OK;
1056+ }
1057+
1058+ HRESULT __stdcall Read (
1059+ BYTE* pv,
1060+ ULONG cb,
1061+ ULONG* pcbRead
1062+ )
1063+ {
1064+ auto av = d.size () - p;
1065+ if (cb < av)
1066+ av = cb;
1067+ memcpy (pv, d.data () + p, av);
1068+ p += av;
1069+ if (pcbRead)
1070+ *pcbRead = (ULONG)av;
1071+ if (av < cb)
1072+ return S_FALSE;
1073+ return S_OK;
1074+ }
1075+
1076+ std::function<HRESULT(const BYTE*, size_t )> func;
1077+
1078+ HRESULT __stdcall Write (
1079+ const BYTE* pv,
1080+ ULONG cb,
1081+ ULONG* pcbWritten
1082+ )
1083+ {
1084+ if (d.size () < (p + cb))
1085+ {
1086+ auto exc = (p + cb) - d.size ();
1087+ d.resize (d.size () + exc);
1088+ }
1089+ memcpy (d.data () + p, pv, cb);
1090+
1091+ if (func)
1092+ {
1093+ auto hr = func (pv, cb);
1094+ if (FAILED (hr))
1095+ return hr;
1096+ }
1097+
1098+
1099+ p += cb;
1100+ if (pcbWritten)
1101+ *pcbWritten = cb;
1102+ return S_OK;
1103+ }
1104+
1105+ HRESULT __stdcall SetLength (
1106+ QWORD qwLength
1107+ )
1108+
1109+ {
1110+ d.resize (qwLength);
1111+ if (p >= qwLength)
1112+ p = qwLength;
1113+ return S_OK;
1114+ }
1115+
1116+ HRESULT __stdcall SetCurrentPosition (
1117+ QWORD q
1118+ )
1119+ {
1120+ if (q > d.size ())
1121+ return E_FAIL;
1122+ p = q;
1123+ return S_OK;
1124+
1125+ }
1126+
1127+
1128+ HRESULT __stdcall Seek (
1129+ MFBYTESTREAM_SEEK_ORIGIN dwOrigin,
1130+ LONGLONG llSeekOffset,
1131+ DWORD dwSeekFlags,
1132+ QWORD* pqwCurrentPosition
1133+ )
1134+ {
1135+ LARGE_INTEGER lo = { 0 };
1136+ if (dwOrigin == msoBegin)
1137+ {
1138+ p = llSeekOffset;
1139+ }
1140+ if (dwOrigin == msoCurrent)
1141+ {
1142+ p += llSeekOffset;
1143+ }
1144+ if (p >= d.size ())
1145+ p = d.size ();
1146+ if (pqwCurrentPosition)
1147+ *pqwCurrentPosition = p;
1148+
1149+ return S_OK;
1150+ }
1151+
1152+
1153+ };
1154+
1155+
1156+
9161157int DesktopCapture (DESKTOPCAPTUREPARAMS& dp)
9171158{
9181159 HRESULT hr = S_OK;
@@ -1112,8 +1353,21 @@ int DesktopCapture(DESKTOPCAPTUREPARAMS& dp)
11121353 MFCreateAttributes (&attrs, 0 );
11131354 attrs->SetUINT32 (MF_READWRITE_ENABLE_HARDWARE_TRANSFORMS, true );
11141355
1356+ VectorStreamX2 bs;
1357+ bs.func = dp.Streamer ;
11151358 CComPtr<IMFSinkWriter> pSinkWriter;
1116- hr = MFCreateSinkWriterFromURL (dp.f .c_str (), NULL , attrs, &pSinkWriter);
1359+ if (dp.f .empty ())
1360+ {
1361+ if (dp.HasVideo )
1362+ attrs->SetGUID (MF_TRANSCODE_CONTAINERTYPE, MFTranscodeContainerType_MPEG4);
1363+ else
1364+ attrs->SetGUID (MF_TRANSCODE_CONTAINERTYPE, MFTranscodeContainerType_MP3);
1365+ if (dp.PrepareAttributes )
1366+ dp.PrepareAttributes (attrs);
1367+ hr = MFCreateSinkWriterFromURL (NULL , &bs, attrs, &pSinkWriter);
1368+ }
1369+ else
1370+ hr = MFCreateSinkWriterFromURL (dp.f .c_str (), NULL , attrs, &pSinkWriter);
11171371 if (FAILED (hr)) return -3 ;
11181372
11191373
@@ -1827,6 +2081,8 @@ int DesktopCapture(DESKTOPCAPTUREPARAMS& dp)
18272081 }
18282082
18292083 hr = pSinkWriter->Finalize ();
2084+ if (FAILED (hr))
2085+ return -14 ;
18302086 return 0 ;
18312087}
18322088
0 commit comments