Skip to content

Commit 5189559

Browse files
committed
decode: added ability to decoder to resuse device in multisession decode mode
1 parent 8102c9b commit 5189559

6 files changed

Lines changed: 445 additions & 32 deletions

File tree

common/libs/VkCodecUtils/ProgramConfig.h

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,9 @@ struct ProgramConfig {
8080
outputcrcPerFrame = false;
8181
outputcrc = false;
8282
crcOutputFile = nullptr;
83+
numberOfDecodeWorkers = 0;
84+
enableWorkerProcessesPoll = false;
85+
ipcType = 0;
8386
}
8487

8588
using ProgramArgs = std::vector<ArgSpec>;
@@ -187,8 +190,7 @@ struct ProgramConfig {
187190
{"--input", "-i", 1, "Input filename to decode",
188191
[this](const char **args, const ProgramArgs &a) {
189192
videoFileName = args[0];
190-
std::ifstream validVideoFileStream(videoFileName, std::ifstream::in);
191-
return (bool)validVideoFileStream;
193+
return true;
192194
}},
193195
{"--output", "-o", 1, "Output filename to dump raw video to",
194196
[this](const char **args, const ProgramArgs &a) {
@@ -322,6 +324,17 @@ struct ProgramConfig {
322324
crcInitValue = crcInitValueTemp;
323325
return true;
324326
}},
327+
{"--poll-of-processes", nullptr, 1, "Use poll of worker processes and specify number of workers.",
328+
[this](const char **args, const ProgramArgs &a) {
329+
enableWorkerProcessesPoll = true;
330+
numberOfDecodeWorkers = std::atoi(args[0]);
331+
return true;
332+
}},
333+
{"--files-to-decode", nullptr, 1, "Specify a file location where command lines for the poll of worker processes are saved.",
334+
[this](const char **args, const ProgramArgs &a) {
335+
fileListIpc = args[0];
336+
return true;
337+
}},
325338
};
326339

327340
for (int i = 1; i < argc; i++) {
@@ -391,6 +404,18 @@ struct ProgramConfig {
391404
crcOutputFile = stdout;
392405
}
393406
}
407+
408+
if (!enableWorkerProcessesPoll) {
409+
if (videoFileName.length() == 0) {
410+
std::cerr << "Input file should be specified" << std::endl;
411+
exit(EXIT_FAILURE);
412+
}
413+
std::ifstream validVideoFileStream(videoFileName, std::ifstream::in);
414+
if (!(bool)validVideoFileStream) {
415+
std::cerr << "Can't open input file: invalid file name" << std::endl;
416+
exit(EXIT_FAILURE);
417+
}
418+
}
394419
}
395420

396421
// Assuming we have the length as a parameter:
@@ -461,6 +486,7 @@ struct ProgramConfig {
461486
uint32_t decoderQueueSize;
462487
int32_t enablePostProcessFilter;
463488
uint32_t *crcOutput;
489+
uint32_t numberOfDecodeWorkers;
464490
uint32_t enableStreamDemuxing : 1;
465491
uint32_t directMode : 1;
466492
uint32_t vsync : 1;
@@ -474,6 +500,9 @@ struct ProgramConfig {
474500
uint32_t outputy4m : 1;
475501
uint32_t outputcrc : 1;
476502
uint32_t outputcrcPerFrame : 1;
503+
uint32_t enableWorkerProcessesPoll : 1;
504+
uint32_t ipcType : 1;
505+
std::string fileListIpc;
477506
};
478507

479508
#endif /* _PROGRAMSETTINGS_H_ */
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
#include <vector>
2+
#include <string>
3+
#include <iostream>
4+
#include <sstream>
5+
6+
enum IPC_TYPE { UNIX_DOMAIN_SOCKETS = 0 };
7+
constexpr int DEFAULT_BUFLEN = 512;
8+
9+
int usoc_manager(int isNoPresent, std::string& inputCmdsList);
10+
int clientConnectServer(std::string& recvbuf, const char* usocfilename = NULL);
11+
12+
#ifdef _WIN32
13+
14+
static int cloneTheProcess(int argc, const char** argv, PROCESS_INFORMATION& pi, STARTUPINFO& si) {
15+
ZeroMemory(&si, sizeof(si));
16+
si.cb = sizeof(si);
17+
ZeroMemory(&pi, sizeof(pi));
18+
std::string argsToPass;
19+
for (int i = 0; i < argc; i++) {
20+
argsToPass += argv[i];
21+
argsToPass += " ";
22+
}
23+
argsToPass += "spawn";
24+
if (!CreateProcess(NULL, (LPTSTR)argsToPass.c_str(), NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi)) {
25+
printf("CreateProcess failed (%d).\n", GetLastError());
26+
return -1;
27+
}
28+
return 0;
29+
}
30+
#endif
31+
32+
static int parseCharArray(std::vector<std::string>& w, const char* messageString, int& argc, const char** argv) {
33+
std::stringstream ss(messageString);
34+
std::string word;
35+
argc = 0;
36+
std::cout << std::endl;
37+
while (ss >> w[argc]) {
38+
if (w[argc][0] == '~') {
39+
w[argc] = getenv("HOME") + w[argc].substr(1);
40+
}
41+
if (w[argc].substr(0, 6) == "finish") {
42+
printf("Received a request to finish this decode worker. The worker process is terminated (completed).\n");
43+
return 0;
44+
}
45+
if (w[argc].substr(0, 6) == "nodata") {
46+
printf("Received a request to wait for a data...\n");
47+
return 0;
48+
}
49+
argv[argc] = w[argc].c_str();
50+
argc++;
51+
}
52+
return argc >= 1;
53+
}
54+
55+
static int receiveNewBitstream(IPC_TYPE ipcType, bool enableWorkerProcessesPoll, std::string& receivedMessage) {
56+
if (!enableWorkerProcessesPoll) {
57+
return 0;
58+
}
59+
int isDataReceived = 0;
60+
if (ipcType == IPC_TYPE::UNIX_DOMAIN_SOCKETS) {
61+
isDataReceived = clientConnectServer(receivedMessage);
62+
}
63+
return isDataReceived;
64+
}
Lines changed: 244 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,244 @@
1+
// The MIT License (MIT)
2+
3+
// Copyright (c) Microsoft Corporation
4+
5+
// Permission is hereby granted, free of charge, to any person obtaining a copy
6+
// of this software and associated documentation files (the "Software"), to deal
7+
// in the Software without restriction, including without limitation the rights
8+
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
// copies of the Software, and to permit persons to whom the Software is
10+
// furnished to do so, subject to the following conditions:
11+
12+
// The above copyright notice and this permission notice shall be included in
13+
// all copies or substantial portions of the Software.
14+
15+
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21+
// THE SOFTWARE.
22+
23+
// Portions of this repo are provided under the SIL Open Font License.
24+
// See the LICENSE file in individual samples for additional details.
25+
26+
#include <iostream>
27+
#include <fstream>
28+
#include <stdlib.h>
29+
#include <vector>
30+
#include <string>
31+
#include <chrono>
32+
33+
#ifndef _WIN32
34+
#include <netdb.h>
35+
#include <sys/select.h>
36+
#include <sys/socket.h>
37+
#include <sys/un.h>
38+
#include <unistd.h>
39+
#include <poll.h>
40+
#include <cerrno>
41+
#else
42+
#include <winsock2.h>
43+
#include <ws2tcpip.h>
44+
#include <mstcpip.h>
45+
#include <process.h>
46+
#endif
47+
48+
constexpr char socket_path[14]{"tmpsoc"};
49+
50+
#ifndef _WIN32
51+
constexpr int INVALID_SOCKET = -1;
52+
constexpr int SOCKET_ERROR = -1;
53+
using SOCKET = int;
54+
static inline int WSAGetLastError() {
55+
return errno;
56+
}
57+
#else
58+
static inline const int poll(LPWSAPOLLFD fdArray, ULONG fds, INT timeout) {
59+
return WSAPoll(fdArray, fds, timeout);
60+
}
61+
static inline const int close(SOCKET ConnectSocket) {
62+
int result = closesocket(ConnectSocket);
63+
WSACleanup();
64+
return result;
65+
}
66+
#endif
67+
68+
static int readDataFromFile(std::string inputCmdsList, std::vector<std::string>& filenames) {
69+
std::ifstream inputf;
70+
inputf.open(inputCmdsList);
71+
if (inputf.is_open()) {
72+
std::string line;
73+
while (getline(inputf, line)) {
74+
filenames.push_back(line);
75+
}
76+
filenames.push_back("finish");
77+
inputf.close();
78+
return 0;
79+
}
80+
std::cout << "Error opening file";
81+
return -1;
82+
}
83+
84+
int usoc_manager(int isNoPresent, std::string& inputCmdsList) {
85+
sockaddr addr;
86+
std::vector<std::string> filenames;
87+
if (readDataFromFile(inputCmdsList, filenames) == -1) {
88+
return 1;
89+
}
90+
91+
SOCKET listen_sd;
92+
if ((listen_sd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
93+
perror("socket error");
94+
exit(-1);
95+
}
96+
97+
unlink(socket_path);
98+
99+
memset(&addr, 0, sizeof(addr));
100+
addr.sa_family = AF_UNIX;
101+
strncpy(addr.sa_data, socket_path, sizeof(addr.sa_data) - 1);
102+
103+
if (bind(listen_sd, (struct sockaddr*)&addr, sizeof(addr)) == -1) {
104+
perror("bind error");
105+
exit(-1);
106+
}
107+
108+
if (listen(listen_sd, 256) == -1) {
109+
perror("listen error");
110+
exit(-1);
111+
}
112+
113+
pollfd fdarray;
114+
constexpr int DEFAULT_WAIT = 30000;
115+
int ret;
116+
SOCKET lsock = INVALID_SOCKET, asock = INVALID_SOCKET;
117+
int stop_server = 0;
118+
for (int i = 0; !stop_server;) {
119+
fdarray.fd = listen_sd;
120+
fdarray.events = POLLIN | POLLOUT;
121+
int data_sent = 0;
122+
123+
data_sent = 0;
124+
printf("Manager: poll is waiting for incoming events (timeout %d s)\n", DEFAULT_WAIT / 1000);
125+
if (SOCKET_ERROR == (ret = poll(&fdarray, 1, DEFAULT_WAIT))) {
126+
printf("Main: poll operation failed: %d\n", WSAGetLastError());
127+
return 1;
128+
}
129+
130+
if (ret == 0) {
131+
stop_server = 1;
132+
}
133+
134+
if (ret) {
135+
if (fdarray.revents & POLLIN) {
136+
printf("Manager: Connection established.\n");
137+
138+
if (INVALID_SOCKET == (asock = accept(listen_sd, NULL, NULL))) {
139+
WSAGetLastError();
140+
return 1;
141+
}
142+
char buf[512] = {0};
143+
if (SOCKET_ERROR == (ret = recv(asock, buf, sizeof(buf), 0))) {
144+
WSAGetLastError();
145+
return 1;
146+
} else
147+
printf("Manager: recvd %d bytes\n", ret);
148+
if (ret) {
149+
i = std::min<int>(i, (int)filenames.size() - 1);
150+
if (SOCKET_ERROR == (ret = send(asock, filenames[i].c_str(), (int)filenames[i].length() + 1, 0))) {
151+
printf("Manager: send socket failed %d \n", WSAGetLastError());
152+
return 1;
153+
}
154+
printf("Manager: sent %d bytes\n", ret);
155+
data_sent = 1;
156+
}
157+
if (ret) {
158+
if (SOCKET_ERROR == (ret = recv(asock, buf, sizeof(buf), 0))) {
159+
WSAGetLastError();
160+
return 1;
161+
} else if (ret >= 8) {
162+
printf("Manager: recvd confirm %d bytes\n", ret);
163+
if (strncmp("received", buf, 8) == 0) {
164+
i++;
165+
}
166+
}
167+
}
168+
}
169+
}
170+
}
171+
172+
close(fdarray.fd);
173+
return 0;
174+
}
175+
176+
constexpr int DEFAULT_BUFLEN = 512;
177+
178+
// The following function is a further modification of the main function from the file at the link below:
179+
// https://learn.microsoft.com/en-us/windows/win32/winsock/complete-client-code
180+
int clientConnectServer(std::string& recvbuf, const char* usocfilename) {
181+
int iResult;
182+
#if defined(_WIN32)
183+
WSADATA wsaData;
184+
iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
185+
if (iResult != 0) {
186+
printf("WSAStartup failed with error: %d\n", iResult);
187+
return 1;
188+
}
189+
#endif
190+
sockaddr saddr{saddr.sa_family = AF_UNIX};
191+
strncpy(saddr.sa_data, socket_path, sizeof(socket_path));
192+
SOCKET ConnectSocket = socket(AF_UNIX, SOCK_STREAM, IPPROTO_IP);
193+
if (ConnectSocket == INVALID_SOCKET) {
194+
printf("socket failed with error: %d\n", WSAGetLastError());
195+
return -1;
196+
}
197+
do {
198+
iResult = connect(ConnectSocket, &saddr, sizeof(saddr) + (int)strlen(saddr.sa_data));
199+
if (iResult == -1) {
200+
#if defined(_WIN32)
201+
closesocket(ConnectSocket);
202+
#else
203+
close(ConnectSocket);
204+
#endif
205+
ConnectSocket = INVALID_SOCKET;
206+
}
207+
} while (iResult == -1);
208+
209+
if (ConnectSocket == INVALID_SOCKET) {
210+
printf("Unable to connect to server! %d\n", WSAGetLastError());
211+
#if defined(_WIN32)
212+
WSACleanup();
213+
#endif
214+
return -1;
215+
}
216+
int hasNewBitstreamReceived = 0;
217+
int recvbuflen = DEFAULT_BUFLEN;
218+
std::string sendbuf{"data request"};
219+
iResult = send(ConnectSocket, sendbuf.c_str(), (int)sendbuf.length(), 0);
220+
if (iResult == SOCKET_ERROR) {
221+
printf("send failed with error: %d\n", WSAGetLastError());
222+
close(ConnectSocket);
223+
return -1;
224+
}
225+
printf("bytes Sent: %d (pid %d)\n", iResult, getpid());
226+
iResult = recv(ConnectSocket, (char*)recvbuf.c_str(), recvbuflen, 0);
227+
if (iResult == SOCKET_ERROR) {
228+
printf("recv failed with error: %d\n", WSAGetLastError());
229+
close(ConnectSocket);
230+
return -1;
231+
}
232+
if (iResult > 0) {
233+
hasNewBitstreamReceived = 1;
234+
}
235+
sendbuf = {"received"};
236+
iResult = send(ConnectSocket, (char*)sendbuf.c_str(), (int)sendbuf.length(), 0);
237+
if (iResult == SOCKET_ERROR) {
238+
printf("send failed with error: %d\n", WSAGetLastError());
239+
close(ConnectSocket);
240+
return -1;
241+
}
242+
close(ConnectSocket);
243+
return hasNewBitstreamReceived;
244+
}

common/libs/VkShell/ShellWin32.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,7 @@ LRESULT ShellWin32::HandleMessage(UINT msg, WPARAM wparam, LPARAM lparam) {
130130
}
131131
break;
132132
case WM_DESTROY:
133-
QuitLoop();
133+
SendMessage(m_hwnd, WM_QUIT, 0, 0);
134134
break;
135135
default:
136136
return DefWindowProc(m_hwnd, msg, wparam, lparam);

0 commit comments

Comments
 (0)