renderer.cpp 4.17 KB
#include "renderer.h"

Renderer::Renderer(char* videoPath, char* user_id) {
    this->folder_id = user_id;
    this->path_video = videoPath;
    serverInitialize();
    running = true;
    count_task = 0;
    glosa_processed = 0;
    core_socket = new StreamSocket();
    listeners = new list<ListenerRenderer*>();
    DPRINTF("Done!\n");
}

Renderer::~Renderer() {
    listeners->clear(); 
    delete listeners;
    if(core_socket) delete core_socket;
    DDDPRINTF("Renderer finalized!\n");
}

void Renderer::serverInitialize(){
    string render = "python render.py ";
    render.append(folder_id).append(" >/dev/null 2>&1 &");
    
    string command = "cd ";
    char* shPath;
    shPath = getenv("RENDERER");
    if(shPath != NULL)
        command.append(shPath);
    else
        command.append(PATH_RENDERER);

    command.append(" && ").append(render);
    system(command.c_str());
    sleep(5);
}

void Renderer::receiveGlosa(std::string glosa, int64_t pts) {
    glosa_copy = glosa;
    ostringstream oss;
    oss << pts;
    glosa_copy += "#"; // formato da string enviada p/ o player: Glosa#pts
    glosa_copy += oss.str();
    count_task++;
}

void Renderer::sendGlosa() {
    try{
        int glosa_size = strlen(glosa_copy.c_str())+1;
        char* glosa_buffer = new char[glosa_size];
        strcpy(glosa_buffer, glosa_copy.c_str());
        core_socket->write(glosa_buffer, glosa_size);

        char* ok_core = new char[3];
        do {
            core_socket->read(ok_core, 3); //aguarda o unity confirmar o recebimento da glosa
        }while(strcmp(ok_core, "OK") != 0);
        glosa_processed++;

        delete [] ok_core;
        delete [] glosa_buffer;

    }catch(lavidlib::RuntimeException &ex){
        throw lavidlib::RuntimeException(ex.getMessage().c_str());
    }catch(lavidlib::IOException &ex){
        throw lavidlib::RuntimeException(ex.getMessage().c_str());
    }
}

void Renderer::connectToUnity() {
    try{
        static InetAddress* addr = InetAddress::createByName(HOST);
        core_socket->connect(addr, PORTNO);
    }catch(lavidlib::UnknownHostException &ex){
        throw RuntimeException(ex.getMessage().c_str());
    }catch(lavidlib::SocketException &ex){
        throw RuntimeException(ex.getMessage().c_str());
    }
}

void Renderer::waitScreenShots() {
    DPRINTF("[AGUARDE] Gerando vídeo...\n");
    char* endgeneration = new char[strlen(END_FLAG)+1];
    int connected;
    try{
        do{
            connected = core_socket->read(endgeneration, sizeof(endgeneration));
        }while(strcmp(endgeneration, END_FLAG) != 0 && connected != 0);
        core_socket->close();
    }catch(IOException &ex){
        throw RuntimeException(ex.getMessage().c_str());
    }
}

void Renderer::addListener(ListenerRenderer* listener) {
    listeners->push_back(listener);
}

void Renderer::notifyListeners() {
    for (list<ListenerRenderer*>::iterator i = listeners->begin(); i != listeners->end(); i++) {
        (*i)->notifyEndOfRenderization();
    }
}

void Renderer::finalize() {
    while(glosa_processed < count_task)
        usleep(10000);
    receiveGlosa(END_FLAG, (int64_t) -1);
    this->running = false;
}

bool Renderer::isSending() {
    if(glosa_processed < count_task)
        return true;
    else
        return false;
}

void Renderer::Run() {
    try{
        while(running){
            while(count_task <= glosa_processed){
                usleep(10000);
            }
            if(!core_socket->isConnected())
                connectToUnity();
            sendGlosa();
        }
        waitScreenShots();
        render();
        cleanFiles();
    }catch(lavidlib::RuntimeException &ex){
        DDDDPRINTF("Erro: %s\n", ex.getMessage().c_str());
        throw RuntimeException(ex.getMessage().c_str());
    }
}

void Renderer::render() {
    string command = "avconv -loglevel quiet -framerate 30 -i ";
    command.append(PATH_SCREENS).append("[\'").append(folder_id).append("\']").append("/frame_%d.png ")
    .append("-vcodec libx264 -pix_fmt yuv420p ").append(path_video);
    system(command.c_str());
    notifyListeners();
}

void Renderer::cleanFiles() {
    string clean = "rm -rf ";
    clean.append(PATH_SCREENS).append(folder_id).append("/");
    system(clean.c_str());
}