Example #1
0
void EQProtocolPacket::init()
{
  // Get the net op code. Leave in network order.
  m_netOp = *(uint16_t*)(m_packet);

  // get the location of the payload
  m_payload = &m_packet[2];
    
  // calculate the length of the payload (len - net op - crc)
  m_payloadLength = m_length - 2 - (hasCRC() ? 2 : 0);
    
  // make a local copy of the arq to speed up comparisons
  m_arqSeq = eqntohuint16(m_payload);
}
void AbstractPidHandler::parse(const QByteArray &packet)
{
    // If the packet is empty return
    if (packet.isNull())
        return;

    // Build pointer to packet content
    const quint8 *data = (quint8 *)packet.constData(), *p = 0;

    // Return if the packet does not start with 0x47
    if (data[0] != 0x47) {
        qWarning() << "Not a TS packet!";
        return;
    }

    // Check validity of continuity counter
    quint8 ccc = data[3] & 0x0F;
    if (d->ecc == INVALID_CC) { // Conintuity counter has not been yet initialized
        d->ecc = ccc; // Initialize continuity counter with currrent value
    } else {
        // Check if packet is duplicate and just ignore it if it the case
        if (d->ecc == ccc) {
            qWarning() << "Duplicate TS packet?!?!?!";
            return;
        }

        // Compute next continuity counter
        d->ecc = ++d->ecc & 0x0F;

        // Check if discontinuity
        if (d->ecc != ccc) {
            qDebug() << "Discontinuity!\n";
            d->ecc = ccc;
            emit discontinuity();
        }
    }

    // Return if no payload in the TS packet
    if (!data[3] & 0x10)
        return;

    // Skip the adaptation field if present
    if (data[3] & 0x20) //  Check if "Adaptation field exists" bit is set
        p = data + 5 + data[4]; // Point after adaptation field
    else
        p = data + 4; // Point to first byte after header

    // Compute Payload Start Unit Indicator
    quint8 pusi = data[1] & 0x40;

    // Skip new section begins if present
    if (pusi) // Check if "Payload unit start" bit is set
        p = p + *p + 1;


    // If no section yet started and the current packet contains the start of a new section then build a new one
    if (!d->section) {
        if (!pusi)
            return;

        d->section = new Section(this);
    }

    // Compute availability of data
    quint8 available = 188 + data - p;

    while (available) {
        // Check if there is enough bytes in the current data buffer to complete the need of the section
        if (available >= d->section->need) {

            // Add the needed bytes to the data buffer of the section
            d->section->data += QByteArray((const char *)p, (int)d->section->need);
            p += d->section->need;
            available -= d->section->need;

            // Check if the section's header has been parsed so far
            if (!d->section->headerComplete) {
                // Apparently not! So let's do the job
                d->section->need = d->section->sectionLength = (((quint16)d->section->data[1] & 0x0F) << 8) | ((quint16)d->section->data[2] & 0xFF);

                // Done! Let's indicate it
                d->section->headerComplete = true;

                // We still need to check if the section isn't too long
                if (d->section->need > sectionMaxSize() - 3) {
                    qWarning() << "Section too long!";
                    deleteCurrentSection();
                    return;

                    // What about remaining bytes? What do we do if there is other sections in the packet?
                    // ...
                }
            } else {
                // Apparently the header is parsed already. We can take care of the payload now and we
                // will start with checking the CRC if there is one
                if (hasCRC()) {
                    d->section->validCRC = checkCRC();
                }

                d->section->tableID = d->section->data[0];
                d->section->sectionSyntaxIndicator = (d->section->data[1] & 0x80) >> 7;
                d->section->serviceID = (((quint16)d->section->data[3] & 0xFF) << 8) | ((quint16)d->section->data[4] & 0xFF);
                d->section->versionNumber = (d->section->data[5] & 0x3E) >> 1;
                d->section->currentNextIndicator = d->section->data[5] & 0x01;
                d->section->sectionNumber = d->section->data[6];
                d->section->lastSectionNumber = d->section->data[7];

                d->section->payload = (const quint8 *)&d->section->data.constData()[8];
                d->section->payloadSize = d->section->data.size() - 8;
                tableComplete();

                // We can now dispose of the current section
                deleteCurrentSection();

                // A TS packet may contain any number of sections, only the first
                // new one is flagged by the pointer_field. If the next payload
                // byte isn't 0xff then a new section starts.
                if (available && *p != 0xff) {
                    d->section = new Section(this);
                } else {
                    available = 0;
                }
            }
        } else {