renderer.cpp
5.23 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
#include "renderer.h"
Renderer::Renderer(char* path_Contents, char* id) {
this->pathOutVideo = path_Contents;
this->userID = id;
cSocket = new StreamSocket();
listeners = new list<ListenerRenderer*>();
PRINTL(util::_DEBUG, "Renderer Done!\n");
}
Renderer::~Renderer() {
listeners->clear();
delete listeners;
if(cSocket) delete cSocket;
PRINTL(util::_DEBUG, "Renderer finalized!\n");
}
void Renderer::addListener(ListenerRenderer* listener) {
listeners->push_back(listener);
}
void Renderer::notifyListeners() {
PRINTL(util::_DEBUG, "Renderização finalizada!\n");
for (list<ListenerRenderer*>::iterator i = listeners->begin(); i != listeners->end(); i++) {
(*i)->notifyEndOfRenderization();
}
}
void Renderer::executeServerScript() {
PRINTL(util::_DEBUG, "Executando o Script de inicialização do servidor\n");
string command = "cd ";
char* renderPath;
renderPath = getenv("RENDERER");
if(renderPath != NULL)
command.append(renderPath);
else
command.append(PATH_RENDERER);
command.append(" && ").append("python render.py ")
.append(userID).append(" >/dev/null 2>&1 &");
system(command.c_str());
}
void Renderer::connectToUnityPlayer() {
try{
int i = 0; // Contador de tentativas
static InetAddress* addr = InetAddress::createByName(HOST);
PRINTL(util::_DEBUG, "Conectando ao UnityPlayer...\n");
while(!cSocket->isConnected()){
try{
cSocket->connect(addr, PORT);
}catch(lavidlib::SocketException &ex){
if(i < 10) { // Numeros de tentativas de conexão (pode ser alterado)
i++;
sleep(1);
}else{
PRINTL(util::_ERROR, "Número de tentativas de conexão excedido!\n");
throw lavidlib::RuntimeException(ex.getMessage().c_str());
}
}
}
}catch(lavidlib::UnknownHostException &ex){
throw lavidlib::RuntimeException(ex.getMessage().c_str());
}
}
//Armazena as glosas em uma fila até q o método initialize() seja chamado p/ fazer os envios
void Renderer::receiveGlosa(string glosa, int64_t pts) {
ostringstream oss;
string formatedGlosa; //Formato da glosa que será enviada para o player: "glosa#pts"
if(glosa == BADSENTENCE || glosa == BADTEXT)
formatedGlosa = ""; //O player entende "#pts" como pose neutra
else
formatedGlosa = glosa;
oss << pts;
formatedGlosa += "#";
formatedGlosa += oss.str();
glosaQueue.push(formatedGlosa);
}
void Renderer::exportGlosa() {
if(glosaQueue.empty())
throw lavidlib::RuntimeException("Fila de glosas vazia!");
int glosaSize;
char* glosaBff;
string glosaCpy = glosaQueue.front(); //Pega quem estiver na frente da fila
glosaSize = strlen(glosaCpy.c_str())+1;
glosaBff = new char[glosaSize];
strcpy(glosaBff, glosaCpy.c_str());
try {
cSocket->write(glosaBff, glosaSize); //Envia a glosa formatada p/ o player
}catch(lavidlib::IOException &ex){
throw lavidlib::RuntimeException(ex.getMessage().c_str());
}
char* received = new char[3]; //Mensagem de confirmação de recebimento da glosa: "OK\0"
do {
try {
cSocket->read(received, 3); //Aguarda a confirmação
}catch(lavidlib::IOException &ex){
throw lavidlib::RuntimeException(ex.getMessage().c_str());
}
}while(strcmp(received, OK_FLAG) != 0); //Verifica se é a confirmação correta
glosaQueue.pop(); //Se o envio foi bem sucedido, remove a glosa da fila
delete [] glosaBff;
delete [] received;
}
void Renderer::waitScreenShots() {
int endSize;
char* finalize;
endSize = strlen(END_FLAG)+1;
finalize = new char[endSize];
PRINTL(util::_DEBUG, "Aguardando a captura das ScreenShots.\n");
do {
try {
cSocket->read(finalize, endSize); //Aguarda o player notificar o fim da captura das ScreenShots
}catch(lavidlib::IOException &ex){
throw lavidlib::RuntimeException(ex.getMessage().c_str());
}
}while(strcmp(finalize, END_FLAG) != 0); //Verifica se é a mensagem correta ("FINALIZE\0")
cSocket->close();
}
void Renderer::renderVideo() {
PRINTL(util::_DEBUG, "Renderizando...\n");
string command = "ffmpeg -y -loglevel quiet -framerate 30 -i ";
command.append(PATH_SCREENS).append(userID).append("/frame_%d.png ")
.append("-vcodec libx264 -pix_fmt yuv420p ").append(pathOutVideo);
system(command.c_str());
}
void Renderer::initialize() {
executeServerScript();
try{
connectToUnityPlayer();
}catch(lavidlib::RuntimeException &ex){
throw lavidlib::RuntimeException(ex.getMessage().c_str());
}
this->Start();
}
void Renderer::Run() {
PRINTL(util::_DEBUG, "Enviando glosas para o player...\n");
while(!glosaQueue.empty()){ //Inicia o envio das glosas que estão na fila
try{
exportGlosa();
}catch(lavidlib::RuntimeException &ex){
throw lavidlib::RuntimeException(ex.getMessage().c_str());
}
}
PRINTL(util::_INFO, "Gerando vídeo...\n");
receiveGlosa(END_FLAG, -1); //Quando a fila estiver vazia, a flag "FINALIZE" será enviada
try{
exportGlosa();
waitScreenShots();
}catch(lavidlib::RuntimeException &ex){
throw lavidlib::RuntimeException(ex.getMessage().c_str());
}
renderVideo();
notifyListeners();
cleanFiles();
}
void Renderer::cleanFiles() {
string clean = "rm -rf ";
clean.append(PATH_SCREENS).append(userID).append("/");
system(clean.c_str());
}