minor improvements
[senf.git] / Examples / DVBAdapter / ULEdec.cc
index ea19430..695037f 100644 (file)
 
 // Definition of non-inline non-template functions
 
-#include <string>
-#include <iostream>
-#include <iomanip>
-#include <algorithm>
-#include <sys/ioctl.h>
-#include <linux/sockios.h>
-#include <linux/dvb/dmx.h> 
+#include "ULEdec.hh"
 
-#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 <linux/dvb/dmx.h> 
+#include <boost/format.hpp>
 #include "Packets/PacketData.hh"
-#include "Packets/ParseInt.hh"
-
-#include "ULEdec.hh"
+#include "Utils/hexdump.hh"
+#include "Utils/membind.hh"
 
 #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));
@@ -76,7 +66,7 @@ void ULEdec::handleEvent(senf::FileHandle, senf::Scheduler::EventId event)
     dvrHandle.read( ts_packet.data() );
    
     // Check TS error conditions: sync_byte, transport_error_indicator, scrambling_control.
-    if ( (ts_packet->sync_byte() != TS_SYNC) || 
+    if ( (ts_packet->sync_byte() != TRANSPORT_PACKET_SYNC_BYTE) || 
          (ts_packet->transport_error_indicator() == true) || 
          (ts_packet->transport_scrmbl_ctrl() != 0)) 
     {
@@ -91,10 +81,13 @@ void ULEdec::handleEvent(senf::FileHandle, senf::Scheduler::EventId event)
 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();
@@ -105,112 +98,154 @@ void ULEdec::handleTSPacket(senf::TransportPacket ts_packet)
         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 );
+                BOOST_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 );
+                payload_iter = readContSNDUPacket( payload_iter, payload_end );
                 BOOST_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()) {
+                    BOOST_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
-
 }
 
 
-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;
     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);
+        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);
+    
 }
 
 
@@ -241,7 +276,7 @@ int main(int argc, char const * argv[])
 ///////////////////////////////cc.e////////////////////////////////////////
 #undef prefix_
 
-\f
 // Local Variables:
 // mode: c++
 // fill-column: 100