X-Git-Url: http://g0dil.de/git?a=blobdiff_plain;f=Examples%2FDVBAdapter%2FULEdec.cc;h=1a36b5ec2f8f70bab7bc953d55e8d378fcf07762;hb=834416e1c5669c1687d63e29b8055afe3b44ad63;hp=ea194308e4233238c4682a575cf3d6742717283d;hpb=9cd0c7d8fc22ecf342c5d2a45980c245b827a67f;p=senf.git diff --git a/Examples/DVBAdapter/ULEdec.cc b/Examples/DVBAdapter/ULEdec.cc index ea19430..1a36b5e 100644 --- a/Examples/DVBAdapter/ULEdec.cc +++ b/Examples/DVBAdapter/ULEdec.cc @@ -1,9 +1,9 @@ // $Id$ // -// Copyright (C) 2006 -// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS) -// Kompetenzzentrum fuer Satelitenkommunikation (SatCom) -// Stefan Bund +// Copyright (C) 2007 +// Fraunhofer Institute for Open Communication Systems (FOKUS) +// Competence Center NETwork research (NET), St. Augustin, GERMANY +// Thorsten Horstmann // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by @@ -22,36 +22,27 @@ // Definition of non-inline non-template functions -#include -#include -#include -#include -#include -#include -#include - -#include "Scheduler/Scheduler.hh" -#include "Packets/DefaultBundle/EthernetPacket.hh" -#include "Packets/MPEGDVBBundle/TransportPacket.hh" -#include "Packets/MPEGDVBBundle/SNDUPacket.hh" -#include "Utils/membind.hh" -#include "Utils/hexdump.hh" -#include "Socket/Protocols/DVB/DVBDemuxHandles.hh" -#include "Packets/ParseInt.hh" -#include "Packets/Packet.hh" -#include "Packets/PacketData.hh" -#include "Packets/ParseInt.hh" - #include "ULEdec.hh" +#include +#include +#include +#include +#include +#include + #define PID 271 -#define TS_SYNC 0x47 +#define TRANSPORT_PACKET_SIZE 188 +// max. payload_pointer = ts packet payload size ( = ts packet size - ts header - payload_pointer) +// - 2 bytes min. sndu header +#define MAX_PAYLOAD_POINTER ( TRANSPORT_PACKET_SIZE - 4 - 1 - 2 ) #define prefix_ ///////////////////////////////cc.p//////////////////////////////////////// -ULEdec::ULEdec() +ULEdec::ULEdec(unsigned short adapter, unsigned short device) + : demuxHandle( adapter, device ), dvrHandle( adapter, device ) { struct dmx_pes_filter_params pes_filter; memset(&pes_filter, 0, sizeof (struct dmx_pes_filter_params)); @@ -61,156 +52,205 @@ ULEdec::ULEdec() pes_filter.pes_type = DMX_PES_OTHER; pes_filter.flags = DMX_IMMEDIATE_START; demuxHandle.protocol().setPESFilter( &pes_filter ); - + senf::Scheduler::instance().add( dvrHandle, senf::membind(&ULEdec::handleEvent, this)); - + this->receiver_state = Idle; this->priv_sndu_type_1 = false; } -void ULEdec::handleEvent(senf::FileHandle, senf::Scheduler::EventId event) +void ULEdec::handleEvent(senf::Scheduler::EventId event) { senf::TransportPacket ts_packet ( - senf::TransportPacket::create(188, senf::TransportPacket::noinit)); + senf::TransportPacket::create(188, senf::noinit)); dvrHandle.read( ts_packet.data() ); - + // Check TS error conditions: sync_byte, transport_error_indicator, scrambling_control. - if ( (ts_packet->sync_byte() != TS_SYNC) || - (ts_packet->transport_error_indicator() == true) || - (ts_packet->transport_scrmbl_ctrl() != 0)) + if ( (ts_packet->sync_byte() != senf::TransportPacketType::SYNC_BYTE) || + (ts_packet->transport_error_indicator() == true) || + (ts_packet->transport_scrmbl_ctrl() != 0)) { std::cerr << "invalid ts packet\n"; // drop partly decoded SNDU, reset state, resync on PUSI. return; } - + handleTSPacket(ts_packet); } - + void ULEdec::handleTSPacket(senf::TransportPacket ts_packet) { senf::PacketData & payloadData (ts_packet.next().data()); - iterator payload_start = payloadData.begin(); + iterator payload_iter = payloadData.begin(); iterator payload_end = payloadData.end(); - - senf::hexdump(payload_start, payload_end, std::cout); - + + std::cout << "New TS Packet:\n" + << "----------------------------------------------------------------------------\n"; + senf::hexdump(payload_iter, payload_end, std::cout); + std::cout << "----------------------------------------------------------------------------\n"; + // Synchronize continuity counter this->priv_tscc = ts_packet->continuity_counter(); - + switch (ts_packet->pusi()) { case 0: { switch (this->receiver_state) { case Idle: return; case Reassembly: - payload_start = readContSNDUPacket( payload_start, payload_end ); + payload_iter = readContSNDUPacket( payload_iter, payload_end ); if (isSDNUPacketComplete()) { - handleSNDUPacket(); this->receiver_state = Idle; - switch (std::distance( payload_start, payload_end )) + try { + handleSNDUPacket(); + } catch (ULEdecException const & ex) { + std::cerr << ex.what() << "\n"; + return; + } + switch (std::distance( payload_iter, payload_end )) case 0: case 1: return; default: - if ( (*payload_start++ | *payload_start++) != ULE_END_INDICATOR ) + if ( (*payload_iter++ << 8 | *payload_iter++) != ULE_END_INDICATOR ) std::cerr << "delimiting error\n"; } else { - BOOST_ASSERT( std::distance( payload_start, payload_end ) == 0 ); + assert( std::distance( payload_iter, payload_end ) == 0 ); } } break; } case 1: { // a PUSI value of 1 indicates the presence of a Payload Pointer. - unsigned char payload_pointer = *payload_start++; - if (payload_pointer > 181) { - std::cerr << "invalid payload_pointer\n"; + unsigned char payload_pointer = *payload_iter++; + if (payload_pointer > MAX_PAYLOAD_POINTER) { + std::cerr << str( boost::format( + "invalid payload_pointer (%d)\n") % unsigned(payload_pointer) ) ; + this->receiver_state = Idle; return; } switch (this->receiver_state) { case Idle: - payload_start += payload_pointer; - readNewSNDUPacket( payload_start, payload_end ); + std::advance(payload_iter, payload_pointer); break; case Reassembly: // Reassembly Payload Pointer Checking - unsigned char sndu_bytes_left = snduPacketBytesLeft(); - if (sndu_bytes_left != payload_pointer) { + if (snduPacketBytesLeft() != payload_pointer) { // delimiting error - std::cerr << "delimiting error\n"; - payload_start += payload_pointer; + std::cerr << str( boost::format( + "delimiting error: bytes left in SNDU packet != payload_pointer (" + "(%d != %d)\n") % snduPacketBytesLeft() % payload_pointer ); + std::advance(payload_iter, payload_pointer); } else { - readContSNDUPacket( payload_start, payload_end ); - BOOST_ASSERT( isSDNUPacketComplete() ); + payload_iter = readContSNDUPacket( payload_iter, payload_end ); + assert( isSDNUPacketComplete() ); + try { + handleSNDUPacket(); + } catch (ULEdecException const & ex) { + std::cerr << ex.what() << "\n"; + this->receiver_state = Idle; + return; + } } - readNewSNDUPacket( payload_start, payload_end ); + } + this->receiver_state = Idle; + try { + do { + payload_iter = readNewSNDUPacket( payload_iter, payload_end ); + if (! isSDNUPacketComplete()) { + assert( std::distance( payload_iter, payload_end ) == 0 ); + this->receiver_state = Reassembly; + break; + } + handleSNDUPacket(); + } while (std::distance(payload_iter, payload_end) < 2 ); + } + catch (ULEdecException const & ex) { + std::cerr << ex.what() << "\n"; + return; } } - } // end pusi-switch + } // end pusi-switch } -ULEdec::iterator ULEdec::readContSNDUPacket(iterator i_start, iterator i_end) +ULEdec::iterator ULEdec::readContSNDUPacket(iterator i, iterator const i_end) { if (priv_sndu_type_1) { - this->snduPacket->type() |= *i_start++; + this->snduPacket->type() |= *i++; } - i_start = readRawSNDUPacketData(i_start, i_end); - - return i_start; + return readRawSNDUPacketData(i, i_end); } -ULEdec::iterator ULEdec::readNewSNDUPacket(iterator i_start, iterator i_end) -{ +ULEdec::iterator ULEdec::readNewSNDUPacket(iterator i, iterator const i_end) +{ bool dbit = false; - senf::Packet::size_type sndu_length; - sndu_length = *i_start++ << 8 | *i_start++; + senf::Packet::size_type sndu_length = *i++ << 8 | *i++; if (sndu_length & 0x8000) { sndu_length &= 0x7FFF; dbit = true; } + if (sndu_length < 5 || sndu_length == 0xffff) { + throw ULEdecException( str( boost::format( + "SNDU length error. length=%d") % sndu_length) ); + } this->snduPacket = senf::SNDUPacket::create(sndu_length+4); - this->snduPacket->d_bit() = dbit; + + if (dbit) + this->snduPacket->withoutDestination(); + // else not needed since default on newly created packet is withDestination() + this->snduPacket->length() = sndu_length; - this->snduPacketData_iter = this->snduPacket.data().begin() + 2; + this->snduPacketData_iter = boost::next(this->snduPacket.data().begin(), 2); this->priv_sndu_type_1 = false; - - switch (std::distance(i_start, i_end)) { + + switch (std::distance(i, i_end)) { case 1: this->priv_sndu_type_1 = true; - this->snduPacket->type() = *i_start++; + this->snduPacket->type() = *i++ << 8; this->snduPacketData_iter++; case 0: break; - - default: - this->snduPacket->type() = *i_start++ | *i_start++; - this->snduPacketData_iter += 2; - i_start = readRawSNDUPacketData(i_start, i_end); + + default: + this->snduPacket->type() = *i++ << 8 | *i++; + std::advance(this->snduPacketData_iter, 2); + i = readRawSNDUPacketData(i, i_end); } - - return i_start; + + return i; } -ULEdec::iterator ULEdec::readRawSNDUPacketData(iterator i_start, iterator i_end) +ULEdec::iterator ULEdec::readRawSNDUPacketData(iterator i, iterator i_end) { unsigned char how_much = std::min( - snduPacketBytesLeft(), std::distance( i_start, i_end ) ); - copy_n(i_start, how_much, this->snduPacketData_iter); - i_start += how_much; - this->snduPacketData_iter += how_much; - return i_start; + snduPacketBytesLeft(), std::distance(i, i_end) ); + copy_n(i, how_much, this->snduPacketData_iter); + std::advance(i, how_much); + std::advance(this->snduPacketData_iter, how_much); + return i; } void ULEdec::handleSNDUPacket() { this->snduPacket.dump(std::cout); + std::cout << "----------------------------------------------------------------------------\n\n"; + if (this->snduPacket->crc() != this->snduPacket->calcCrc()) { + throw ULEdecException( str( boost::format( + "CRC Error. received crc:%d calculated crc:%d") + % this->snduPacket->crc() % this->snduPacket->calcCrc() ) ); + } +// senf::Packet nextPacket = this->snduPacket.next(); +// senf::hexdump( +// nextPacket.data().begin(), +// nextPacket.data().end(), +// std::cout); + } @@ -248,6 +288,6 @@ int main(int argc, char const * argv[]) // c-file-style: "senf" // indent-tabs-mode: nil // ispell-local-dictionary: "american" -// compile-command: "scons -u test" +// compile-command: "scons -U" // comment-column: 40 // End: