@@ -892,6 +892,8 @@ struct DESKTOPCAPTUREPARAMS
892
892
GUID VIDEO_ENCODING_FORMAT = MFVideoFormat_H264;
893
893
GUID AUDIO_ENCODING_FORMAT = MFAudioFormat_MP3;
894
894
std::wstring f;
895
+ std::function<HRESULT(const BYTE* d, size_t sz)> Streamer;
896
+ std::function<void (IMFAttributes* a)> PrepareAttributes;
895
897
int fps = 25 ;
896
898
int NumThreads = 0 ;
897
899
int Qu = -1 ;
@@ -913,6 +915,245 @@ struct DESKTOPCAPTUREPARAMS
913
915
bool Pause = false ;
914
916
};
915
917
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
+
916
1157
int DesktopCapture (DESKTOPCAPTUREPARAMS& dp)
917
1158
{
918
1159
HRESULT hr = S_OK;
@@ -1112,8 +1353,21 @@ int DesktopCapture(DESKTOPCAPTUREPARAMS& dp)
1112
1353
MFCreateAttributes (&attrs, 0 );
1113
1354
attrs->SetUINT32 (MF_READWRITE_ENABLE_HARDWARE_TRANSFORMS, true );
1114
1355
1356
+ VectorStreamX2 bs;
1357
+ bs.func = dp.Streamer ;
1115
1358
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);
1117
1371
if (FAILED (hr)) return -3 ;
1118
1372
1119
1373
@@ -1827,6 +2081,8 @@ int DesktopCapture(DESKTOPCAPTUREPARAMS& dp)
1827
2081
}
1828
2082
1829
2083
hr = pSinkWriter->Finalize ();
2084
+ if (FAILED (hr))
2085
+ return -14 ;
1830
2086
return 0 ;
1831
2087
}
1832
2088
0 commit comments