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 {