demux.cpp 7.15 KB
/*
 * Demux.cpp
 *
 *  Created on: 09/10/2008
 *      Author: lacet
 */

#include "filter.h"
#include "packet.h"
#include "section_hal.h"

#include <stdio.h>
#include <string.h>

#include "demux.h"
#include "demuxListener.h"
#include "jmutex.h"
#include "util.h"
#define OK (0)

//debug
#define DEBUG 0
#define DEBUG_ARQ 0

FILE *file = NULL;

Packet* myPacket = NULL;

Mutex* mutex = new Mutex();

Demux::Demux(int pid) {
    //mutex->Lock();
    //filters = new vector<Filter*> ();
    filter = new Filter(pid, 0, 0);
    //printf("\nFiltro Setado\n");
    mySectionBuffer = new SectionBuffer();
    mySectionBuffer->initSectionsBuffer();
    sectionSize = -1;
    sectionRead = 0;
    countPacotes = 0;
    continuityCounter = 0;
    lastContinuityCounter = 0;
    flagShiftPointerField = 1;
    //setDemuxListener();
    //mutex->Unlock();
}

Demux::Demux(int pid, DemuxListener* listener) {
    //mutex->Lock();
    //filters = new vector<Filter*> ();
    filter = new Filter(pid, 0, 0);
    //printf("\nFiltro Setado\n");
    mySectionBuffer = new SectionBuffer();
    mySectionBuffer->initSectionsBuffer();
    sectionSize = -1;
    sectionRead = 0;
    countPacotes = 0;
    continuityCounter = 0;
    lastContinuityCounter = 0;
    setDemuxListener(listener);
    //mutex->Unlock();
    ouvintes = new list<OuvinteDemux*>();

    // Inicia o mutex
    mutex = (pthread_mutex_t *) malloc(sizeof (pthread_mutex_t));
    pthread_mutex_init(mutex, NULL);
}

void Demux::setDemuxListener(DemuxListener* listener) {
    this->listener = listener;
}

void Demux::chegouInput(unsigned char *pacote) {
    // Mutex para evitar bug multiplas chamadas dos notificadores
    pthread_mutex_lock(mutex);
    Packet *mypack = new Packet(pacote);
    getNextSection(pacote, mypack);

    pthread_mutex_unlock(mutex);

}

Demux::~Demux() {

    delete filter;
    delete mySectionBuffer;

    if (ouvintes) {
        // nao deleta os ouvintes mesmo, apenas a lista
        ouvintes->clear();
        delete ouvintes;
    }

    if (mutex) {
        int ret = pthread_mutex_destroy(mutex);
        if (ret)
            printf("erro destruindo mutex\n");
        free(mutex);
    }


}

Filter* Demux::getFilter() {
    return filter;
}

int getPESSize(unsigned char* pacote) {
    return getIntAtBits(pacote, 32, 16) + 6;
}
int start = 0;
//int countPacotes = 0;

int Demux::getNextSection(unsigned char* packet, Packet *myPacket) {
    //countPacotes++;
    //unsigned char* packet = new unsigned char[PACKET_SIZE]; // TODO desalocar
    unsigned char *payloadData;
    static utils::Util util;
    int packetControl = OK;
    //Filter* filter;
    //int packetControl;
    int count1, count2;
    count1 = count2 = 0;
    //printf("\nPacket Notified - PID: %d\nSection Read: %d\n", myPacket->getPid(), sectionRead);
    //this->flagShiftPointerField = 1;

    if (myPacket && filter) {

        if (packetControl == OK) {

            if (myPacket->getPid() != filter->getFilterPid()) {
                //printf("\nRefused Packet - PID: %d\n", myPacket->getPid());
                //invalid pid

                return 0;
            } else if (myPacket->getPayloadLength() < 1) {
                //printf("\nEmpty Payload\n");
                return 0;
                //empty payload
            } else {
                //cout << "Accepted Packet - PID: " << myPacket->getPid() << endl;
                continuityCounter = myPacket->getContinuityCounter();
                //printf("\nContinuity Counter: %d\n", continuityCounter);

                if (start == 0) {
                    start = 1;
                } else {
                    if (lastContinuityCounter == 15) {
                        if (continuityCounter != 0) {
                            //cout << "ERRO DE CONTINUIDADE!!" << endl;
                            //cout << "PID: " << myPacket->getPid() << endl;
                            //cout << "CC: " << continuityCounter << endl;
                            //cout << "LCC: " << lastContinuityCounter << endl;
                            lastContinuityCounter = continuityCounter;
                            sectionRead = 0;
                            sectionSize = -1;
                            return OK;

                        }
                    } else if (continuityCounter != (lastContinuityCounter + 1)) {
                        //cout << "ERRO DE CONTINUIDADE!" << endl;
                        //cout << "PID: " << myPacket->getPid() << endl;
                        //cout << "CC: " << continuityCounter << endl;
                        //cout << "LCC: " << lastContinuityCounter << endl;

                        lastContinuityCounter = continuityCounter;
                        sectionRead = 0;
                        sectionSize = -1;
                        return OK;
                    }
                }
            }
            lastContinuityCounter = continuityCounter;

        }
    } else {
        //printf("\nInvalid Packet\n");
        return 0;
        //invalid packet
    }

    payloadData = myPacket->getPayloadCopy();
    payloadSize = myPacket->getPayloadLength();
    // TODO validate continuity_counter
    if (myPacket->hasAdaptationField()) {
        int tamanho = packet[4];
        payloadData = (unsigned char *) myPacket->getPayloadBeginingAtUnitStarted();
        payloadSize = myPacket->getPayloadBeginingAtUnitStartedLength();
        if (payloadData[0] == 0x00 && payloadData[1] == 0x00 && payloadData[2] == 0x01) {
            //cout << "Pegou Payload Correto" << endl;
        } else {
            cout << "Pegou Payload Errado" << endl;
        }

    } else {

    }

    if (sectionRead == 0) {

        sectionSize = getPESSize(payloadData);

        if (sectionSize > payloadSize) {
            memcpy(sectionData, payloadData, payloadSize);
            sectionRead += payloadSize;
        } else {
            memcpy(sectionData, payloadData, sectionSize);
            sectionRead += sectionSize;
        }

        if (sectionData[0] == 0x00 && sectionData[1] == 0x00 && sectionData[2] == 0x01) {
            //cout << "Pacote PES OK!" << endl;
        } else {
            sectionRead = 0;
            sectionSize = -1;
            cout << "Pacote PES ERRADO!" << endl;
        }

    } else {

        if ((sectionSize - sectionRead) > payloadSize) {
            memcpy(sectionData + sectionRead, payloadData, payloadSize);
            sectionRead += payloadSize;
        } else {
            memcpy(sectionData + sectionRead, payloadData, (sectionSize - sectionRead));
            sectionRead += (sectionSize - sectionRead);
        }

    }

    if (sectionRead == sectionSize) {
        sectionSize = getPESSize(sectionData);
        //cout << "PES NOTIFIED - PES Size: " << sectionSize << endl;
        listener->notifySection(myPacket->getPid(), sectionData, sectionSize);
        sectionRead = 0;
        sectionSize = -1;

    }

    delete myPacket;
    return OK;
}

void Demux::registraOuvinte(OuvinteDemux * ouvinte) {
    ouvintes->push_back(ouvinte);
}

void Demux::removeOuvinte(OuvinteDemux * ouvinte) {
    ouvintes->remove(ouvinte);
}

void Demux::notificaOuvintes(unsigned char * sec) {
    for (list<OuvinteDemux*>::iterator i = ouvintes->begin(); i != ouvintes->end(); i++) {
        (*i)->chegou(sec);
    }
}