Skip to content

Commit df0473d

Browse files
committed
Buffer capture
1 parent f745a2e commit df0473d

File tree

4 files changed

+284
-1
lines changed

4 files changed

+284
-1
lines changed

ScreenCapture.exe.recipe

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<Project>
3+
<ProjectOutputs>
4+
<ProjectOutput>
5+
<FullPath>F:\TP2\sc\ScreenCapture\ScreenCapture.exe</FullPath>
6+
</ProjectOutput>
7+
</ProjectOutputs>
8+
<ContentFiles />
9+
<SatelliteDlls />
10+
<NonRecipeFileRefs />
11+
</Project>

capture.asf

2.5 MB
Binary file not shown.

capture.hpp

Lines changed: 257 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -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+
9161157
int 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

main.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,23 @@ int wmain()
88
MFStartup(MF_VERSION);
99
std::cout << "Capturing screen for 10 seconds...";
1010
DESKTOPCAPTUREPARAMS dp;
11+
dp.VIDEO_ENCODING_FORMAT = MFVideoFormat_H265;
1112
dp.f = L"capture.mp4";
13+
14+
dp.f = L"";
15+
dp.PrepareAttributes = [](IMFAttributes* attrs)
16+
{
17+
attrs->SetGUID(MF_TRANSCODE_CONTAINERTYPE, MFTranscodeContainerType_ASF);
18+
};
19+
dp.Streamer = [](const BYTE* b,size_t sz)
20+
{
21+
FILE* fp = 0;
22+
_wfopen_s(&fp, L"capture.asf", L"a+b");
23+
fwrite(b, 1, sz, fp);
24+
fclose(fp);
25+
return S_OK;
26+
};
27+
1228
dp.EndMS = 10000;
1329
DesktopCapture(dp);
1430
std::cout << "Done.\r\n";

0 commit comments

Comments
 (0)