diff options
-rw-r--r-- | CMakeLists.txt | 8 | ||||
-rw-r--r-- | cmake/Modules/FindFec.cmake | 34 | ||||
-rw-r--r-- | dabplussnoop.cpp | 19 | ||||
-rw-r--r-- | etisnoop.cpp | 2 | ||||
-rw-r--r-- | rsdecoder.cpp | 83 | ||||
-rw-r--r-- | rsdecoder.h | 43 |
6 files changed, 181 insertions, 8 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 8fbe524..8a0c139 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -25,7 +25,7 @@ set(VERSION_INFO_MAINT_VERSION git) # Compiler specific setup ######################################################################## -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -W -Wall") +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -W -Wall -std=c++11") ######################################################################## @@ -36,6 +36,9 @@ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -W -Wall") find_package(Faad REQUIRED) include_directories(${FAAD_INCLUDE_DIRS}) +# libfec +find_package(Fec REQUIRED) +include_directories(${FEC_INCLUDE_DIRS}) ######################################################################## # Setup apps @@ -49,11 +52,12 @@ list(APPEND etisnoop_sources wavfile.c etiinput.cpp etisnoop.cpp + rsdecoder.cpp ) set_source_files_properties(${etisnoop_sources} PROPERTIES LANGUAGE "CXX") add_executable(etisnoop ${etisnoop_sources}) -target_link_libraries(etisnoop ${FAAD_LIBRARIES}) +target_link_libraries(etisnoop ${FAAD_LIBRARIES} ${FEC_LIBRARIES}) install(TARGETS etisnoop DESTINATION bin) diff --git a/cmake/Modules/FindFec.cmake b/cmake/Modules/FindFec.cmake new file mode 100644 index 0000000..59dc525 --- /dev/null +++ b/cmake/Modules/FindFec.cmake @@ -0,0 +1,34 @@ +# Try to find FEC library and include path. +# Once done this will define +# +# FEC_INCLUDE_DIRS - where to find fec.h, etc. +# FEC_LIBRARIES - List of libraries when using libFEC. +# FEC_FOUND - True if libFEC found. + +find_path(FEC_INCLUDE_DIR fec.h DOC "The directory where fec.h resides") +find_library(FEC_LIBRARY NAMES fec DOC "The libFEC library") + +if(FEC_INCLUDE_DIR AND FEC_LIBRARY) + set(FEC_FOUND 1) + set(FEC_LIBRARIES ${FEC_LIBRARY}) + set(FEC_INCLUDE_DIRS ${FEC_INCLUDE_DIR}) +else(FEC_INCLUDE_DIR AND FEC_LIBRARY) + set(FEC_FOUND 0) + set(FEC_LIBRARIES) + set(FEC_INCLUDE_DIRS) +endif(FEC_INCLUDE_DIR AND FEC_LIBRARY) + +mark_as_advanced(FEC_INCLUDE_DIR) +mark_as_advanced(FEC_LIBRARY) +mark_as_advanced(FEC_FOUND) + +if(NOT FEC_FOUND) + set(FEC_DIR_MESSAGE "libfec was not found. Make sure FEC_LIBRARY and FEC_INCLUDE_DIR are set.") + if(NOT FEC_FIND_QUIETLY) + message(STATUS "${FEC_DIR_MESSAGE}") + else(NOT FEC_FIND_QUIETLY) + if(FEC_FIND_REQUIRED) + message(FATAL_ERROR "${FEC_DIR_MESSAGE}") + endif(FEC_FIND_REQUIRED) + endif(NOT FEC_FIND_QUIETLY) +endif(NOT FEC_FOUND) diff --git a/dabplussnoop.cpp b/dabplussnoop.cpp index 2728a21..7073e7f 100644 --- a/dabplussnoop.cpp +++ b/dabplussnoop.cpp @@ -34,6 +34,7 @@ #include "firecode.h" #include "lib_crc.h" #include "faad_decoder.h" +#include "rsdecoder.h" #define DPS_INDENT "\t\t" #define DPS_PREFIX "DAB+ decode:" @@ -124,9 +125,17 @@ bool DabPlusSnoop::decode() printf(DPS_PREFIX " We have %zu bytes of data\n", m_data.size()); #endif - if (m_subchannel_index && m_data.size() >= m_subchannel_index * 120) { + const size_t sf_len = m_subchannel_index * 120; + if (m_subchannel_index && m_data.size() >= sf_len) { + std::vector<uint8_t> b(sf_len); + std::copy(m_data.begin(), m_data.begin() + sf_len, b.begin()); - uint8_t* b = &m_data[0]; + RSDecoder rs_dec; + int rs_errors = rs_dec.DecodeSuperframe(b, m_subchannel_index); + + if (rs_errors == -1) { + return false; + } // -- Parse he_aac_super_frame // ---- Parse he_aac_super_frame_header @@ -171,7 +180,7 @@ bool DabPlusSnoop::decode() // ------ Parse au_start - b += 3; + auto au_starts = b.begin() + 3; vector<uint8_t> au_start_nibbles(0); @@ -179,12 +188,12 @@ bool DabPlusSnoop::decode() * When we have n AUs, we have n-1 au_start values. */ for (int i = 0; i < (num_aus-1)*3; i++) { if (i % 2 == 0) { - char nibble = b[i/2] >> 4; + char nibble = au_starts[i/2] >> 4; au_start_nibbles.push_back( nibble ); } else { - char nibble = b[i/2] & 0x0F; + char nibble = au_starts[i/2] & 0x0F; au_start_nibbles.push_back( nibble ); } diff --git a/etisnoop.cpp b/etisnoop.cpp index 8f95455..9503e6f 100644 --- a/etisnoop.cpp +++ b/etisnoop.cpp @@ -596,7 +596,7 @@ int main(int argc, char *argv[]) switch (ch) { case 'd': { - int subchix = atoi(optarg); + int subchix = atoi(optarg); DabPlusSnoop dps; streams_to_decode[subchix] = dps; } diff --git a/rsdecoder.cpp b/rsdecoder.cpp new file mode 100644 index 0000000..f225bf6 --- /dev/null +++ b/rsdecoder.cpp @@ -0,0 +1,83 @@ +/* + Copyright (C) 2015 Stefan Pöschel + + Copyright (C) 2015 Matthias P. Braendli (http://www.opendigitalradio.org) + + 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 + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <stdexcept> +#include "rsdecoder.h" + +RSDecoder::RSDecoder() +{ + rs_handle = init_rs_char(8, 0x11D, 0, 1, 10, 135); + if(!rs_handle) + throw std::runtime_error("RSDecoder: error while init_rs_char"); +} + +RSDecoder::~RSDecoder() +{ + free_rs_char(rs_handle); +} + +int RSDecoder::DecodeSuperframe(std::vector<uint8_t> &sf, int subch_index) +{ + int total_corr_count = 0; + bool uncorr_errors = false; + + std::vector<int> errors_per_index(subch_index); + + // process all RS packets + for(int i = 0; i < subch_index; i++) { + for(int pos = 0; pos < 120; pos++) + rs_packet[pos] = sf[pos * subch_index + i]; + + // detect errors + int corr_count = decode_rs_char(rs_handle, rs_packet, corr_pos, 0); + errors_per_index[i] = corr_count; + + if(corr_count == -1) { + uncorr_errors = true; + } + else { + total_corr_count += corr_count; + } + + // correct errors + for(int j = 0; j < corr_count; j++) { + + int pos = corr_pos[j] - 135; + if(pos < 0) + continue; + + // fprintf(stderr, "j: %d, pos: %d, sf-index: %d\n", j, pos, pos * subch_index + i); + sf[pos * subch_index + i] = rs_packet[pos]; + } + } + + // output statistics + if (total_corr_count || uncorr_errors) { + printf("RS uncorrected errors:\n"); + for (size_t i = 0; i < errors_per_index.size(); i++) { + int e = errors_per_index[i]; + printf(" (%zu: %d)", i, e); + } + printf("\n"); + } + + return uncorr_errors ? -1 : total_corr_count; +} + + diff --git a/rsdecoder.h b/rsdecoder.h new file mode 100644 index 0000000..ca97c91 --- /dev/null +++ b/rsdecoder.h @@ -0,0 +1,43 @@ +/* + Copyright (C) 2015 Stefan Pöschel + + Copyright (C) 2015 Matthias P. Braendli (http://www.opendigitalradio.org) + + 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 + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <stdint.h> +#include <vector> + +extern "C" { +#include <fec.h> +} + +class RSDecoder { + private: + void *rs_handle; + uint8_t rs_packet[120]; + int corr_pos[10]; + public: + RSDecoder(); + ~RSDecoder(); + + /* Correct errors using reed-solomon decoder. + * Returns number of errors corrected, or -1 if some errors could not + * be corrected + */ + int DecodeSuperframe(std::vector<uint8_t> &sf, int subch_index); +}; + + |