#include "serviceWindowGeneration.h" #define VIDEO_POSE_NEUTRA "poseneutra" #define BASEDIR "vlibras_user/dicionario_libras/" #define BASEDIRTRANSP "vlibras_user/dicionarioTransp_libras/" #define EXTENSAO_DICIONARIO ".ts" #define PATH_API "vlibras_user/vlibras-api/videos/" #define MAX_SIZE_PATH 256 ServiceWindowGeneration::ServiceWindowGeneration() { if (getRunningOption() != '3') { tradutor = new TradutorPortGlosa(); } vetor_pts = new vector(); numero_legendas = INT_MAX; legendas_enviadas = 0; this->running = true; serviceType = 0; DPRINTF("Done!\n"); } ServiceWindowGeneration::~ServiceWindowGeneration() { free(vetor_pts); //free(path_input); free(path_libras); if (inputfile) delete inputfile; if (monitor_pcr_base) delete monitor_pcr_base; if (mixer) delete mixer; if (tradutor) delete tradutor; if (sincronizador) delete sincronizador; DDDPRINTF("Service finalized!\n"); } void ServiceWindowGeneration::adicionaPTS(int64_t pts) { vetor_pts->push_back(pts); } /* Checado pela subclasse para saber quando o sincronizador terminar. */ bool ServiceWindowGeneration::isRunning() { return this->running; } /* Quando o sincronizador termina, ele invoca esse método para avisar! */ void ServiceWindowGeneration::finalizouSincronizacao() { if (getRunningOption() != '2' && serviceType != SERVICE_TYPE_TEXT && serviceType != SERVICE_TYPE_SRT_ONLY) { mixer = new Mixer(); mixer->initialize(this->path_input, this->path_libras,this->position,this->size,this->transparency, this->user_id); createThumbnail(); }else transcodeVideoToMp4(); this->running = false; } char ServiceWindowGeneration::getRunningOption() { char option; if(!option){ int file_d = open("vlibras_user/vlibras-core/data/runningoption.xml", O_RDONLY); int cont = read(file_d, &option, 1); close(file_d); } return option; } void ServiceWindowGeneration::setSizeOfSubtitles(int sub_size) { numero_legendas = sub_size; if (legendas_enviadas >= numero_legendas) { sincronizador->stop(); } } void ServiceWindowGeneration::setPathLibras() { char* final_path = new char[MAX_SIZE_PATH]; strcpy(final_path, "vlibras_user/vlibras-api/uploads/"); strcat(final_path, this->user_id); strcat(final_path, "/libras.ts"); this->path_libras = final_path; //DDPRINTF("Path TS File: %s\n", this->path_libras); } char* ServiceWindowGeneration::getPathLibras() { return path_libras; } void ServiceWindowGeneration::setPathInput(char* _path_input) { this->path_input = _path_input; } char* ServiceWindowGeneration::getPathInput() { return path_input; } string ServiceWindowGeneration::getPathAPI() { return PATH_API; } void ServiceWindowGeneration::setUserId(char* _userId) { this->user_id = _userId; } char* ServiceWindowGeneration::getClientType(){ return client_type; } char* ServiceWindowGeneration::getUserId() { return user_id; } void ServiceWindowGeneration::setServiceType(int type) { serviceType = type; } void ServiceWindowGeneration::setClientType(char* client_type) { this->client_type = client_type; } void ServiceWindowGeneration::setSize(int size){ this->size = size; } void ServiceWindowGeneration::setPosition(int position){ this->position = position; } void ServiceWindowGeneration::setTransparency(int transparency){ this->transparency = transparency; } void ServiceWindowGeneration::setSubLanguage(int sublang){ this->sublanguage = sublang; } void ServiceWindowGeneration::initialize() { setPathLibras(); this->finish = false; if (getRunningOption() != '3' && this->sublanguage == 1) { tradutor->registraOuvinte(this); } // o path do arquivo só poderá conter um "."(ponto), esse identifica a extensão. vector tokens; /* Se for texto não é necessário vídeo de entrada (path_input) */ if (serviceType != SERVICE_TYPE_TEXT && serviceType != SERVICE_TYPE_SRT_ONLY && serviceType != SERVICE_TYPE_REC_ONLY_LIBRAS) { char * pathtmp = this->path_input; int size = strlen(pathtmp); char vtemp [size]; strcpy(vtemp, pathtmp); pathtmp = strtok(vtemp, "."); while (pathtmp != NULL) { tokens.push_back(string(pathtmp)); pathtmp = strtok(NULL, "."); } string buildstrpath = tokens[0] + "_libras" + EXTENSAO_DICIONARIO; this->path_libras = new char[buildstrpath.size()]; strcpy(this->path_libras, buildstrpath.c_str()); //printf("O ServiceWGeneration montou o seguinte path para o vídeo de Libras: %s\n", path_libras); } else { tradutor->registraOuvinte(this); } if(this->transparency == 0) { //pega dicionario com BackGround opaco sincronizador = new Synchronizer(BASEDIR, EXTENSAO_DICIONARIO, this->path_libras, this->transparency); } else { if(this->transparency == 1) { //pega dicionario com BackGround transparente sincronizador = new Synchronizer(BASEDIRTRANSP, EXTENSAO_DICIONARIO, this->path_libras,this->transparency); } } /* Se for SERVICE_TYPE_REC (Recognized) não é necessário usar o monitor_pcr_base */ if (serviceType == SERVICE_TYPE_CC || serviceType == SERVICE_TYPE_SRT) { char* extensao = (char*) tokens[1].c_str(); this->monitor_pcr_base->extvideo = new char[strlen(extensao)]; strcpy(this->monitor_pcr_base->extvideo, extensao); monitor_pcr_base->addListenerPCRBase(sincronizador); } else { uint64_t pcr_base = (uint64_t) 1000; //FIXME: macro sincronizador->setPCRBase(pcr_base); if (serviceType == SERVICE_TYPE_SRT_ONLY) { monitor_pcr_base->addListenerPCRBase(sincronizador); } } sincronizador->registraOuvinte(this); sincronizador->Start(); } /* Método utilizado pelo Tradutor para notificar o texto traduzido. */ void ServiceWindowGeneration::codifica(vector * glosas) { if (serviceType != SERVICE_TYPE_TEXT) { for (int i = 0; i < glosas->size(); i++) { std::locale loc; std::string glosa_lower = ""; for (int k = 0; k < glosas->at(i).length(); k++) glosa_lower += std::tolower(glosas->at(i).at(k), loc); //cout << "__Glosa [" << i << "] = " << glosa_lower << endl; int64_t pts_notificado = vetor_pts->front(); sincronizador->recebeglosa(glosa_lower, pts_notificado); } /* O 'numero_legendas' é informado pela subclasse através do método setSizeOfSubtitles. Então, inicialmente, seu valor corresponde a um número inteiro máximo. */ /*printf("numero_legendas = %d\nlegendas_enviadas = %d\n", numero_legendas, legendas_enviadas); if (legendas_enviadas >= numero_legendas) { sincronizador->stop(); }*/ vetor_pts->erase(vetor_pts->begin()); } else { //Nova versão! for (int i = 0; i < glosas->size(); i++) { std::locale loc; std::string glosa_lower = ""; for (int k = 0; k < glosas->at(i).length(); k++) glosa_lower += std::tolower(glosas->at(i).at(k), loc); //cout << "__Glosa [" << i << "] = " << glosa_lower << endl; sincronizador->recebeglosa(glosa_lower, 1000); } sincronizador->stop(); } legendas_enviadas++; } void ServiceWindowGeneration::transcodeVideoToWebm() { //printf("[INFO]: A transcodificação para .webm está ativada!\n"); string command = "ffmpeg -i "; command.append(path_libras) .append(" -vcodec libvpx -acodec libvorbis ") .append(PATH_API) .append(getUserId()) .append(".webm"); //printf("[INFO]: Transcodification command -> %s\n", command.c_str()); system(command.c_str()); } void ServiceWindowGeneration::transcodeVideoToMp4() { if (serviceType == SERVICE_TYPE_TEXT && strcmp(client_type, (char*)"WEB") == 0) transcodeVideoToWebm(); else{ //printf("[INFO]: A transcodificação para .mp4 está ativada!\n"); string command = "ffmpeg -i "; command.append(path_libras) .append(" -strict experimental -vcodec mpeg2video -r 30 ") .append(PATH_API) .append(getUserId()) .append(".mp4"); //printf("[INFO]: Transcodification command -> %s\n", command.c_str()); system(command.c_str()); //.append(" -strict experimental -vcodec mjpeg -r 30 -pix_fmt yuvj422p ") } } void ServiceWindowGeneration::createThumbnail(){ string command = "ffmpeg -ss 10 -i "; command.append(getPathInput()) .append(" -vcodec png -vframes 1 -an -f rawvideo -y -vf scale=200:200 ") .append(PATH_API).append(user_id).append(".png"); system(command.c_str()); }