From 2b014e2f00df81eefe977b901ab601ea11ccb895 Mon Sep 17 00:00:00 2001 From: "Matthias P. Braendli" Date: Fri, 23 Dec 2016 22:27:03 +0100 Subject: Add EDI fragment interleaver --- src/dabOutput/dabOutput.h | 4 +- src/dabOutput/edi/Interleaver.cpp | 114 ++++++++++++++++++++++++++++++++++++++ src/dabOutput/edi/Interleaver.h | 66 ++++++++++++++++++++++ 3 files changed, 183 insertions(+), 1 deletion(-) create mode 100644 src/dabOutput/edi/Interleaver.cpp create mode 100644 src/dabOutput/edi/Interleaver.h (limited to 'src/dabOutput') diff --git a/src/dabOutput/dabOutput.h b/src/dabOutput/dabOutput.h index a023da9..11b78e6 100644 --- a/src/dabOutput/dabOutput.h +++ b/src/dabOutput/dabOutput.h @@ -69,8 +69,10 @@ struct edi_configuration_t { unsigned int tagpacket_alignment; std::vector destinations; unsigned int dest_port; // common destination port, because it's encoded in the transport layer + unsigned int latency_frames; // if nonzero, enable interleaver with a latency of latency_frames * 24ms - bool enabled() { return destinations.size() > 0; } + bool enabled() const { return destinations.size() > 0; } + bool interleaver_enabled() const { return latency_frames > 0; } }; diff --git a/src/dabOutput/edi/Interleaver.cpp b/src/dabOutput/edi/Interleaver.cpp new file mode 100644 index 0000000..ab3a5fc --- /dev/null +++ b/src/dabOutput/edi/Interleaver.cpp @@ -0,0 +1,114 @@ +/* + Copyright (C) 2016 + Matthias P. Braendli, matthias.braendli@mpb.li + + http://www.opendigitalradio.org + + EDI output, + Interleaving of PFT fragments to increase robustness against + burst packet loss. + + This is possible because EDI has to assume that fragments may reach + the receiver out of order. + + */ +/* + This file is part of ODR-DabMux. + + ODR-DabMux 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. + + ODR-DabMux 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 ODR-DabMux. If not, see . + */ + +#include "Interleaver.h" + +namespace edi { + +void Interleaver::SetLatency(size_t latency_frames) +{ + m_latency = latency_frames; +} + +void Interleaver::PushFragments(const std::vector &fragments) +{ + // Create vectors containing Fcount*latency fragments in total + // and store them into the deque + if (m_buffer.empty()) { + m_buffer.push_back(fragments); + } + else { + auto& last_buffer = m_buffer.back(); + + const bool last_buffer_is_complete = + (last_buffer.size() >= m_fragment_count * m_latency); + + if (last_buffer_is_complete) { + m_buffer.push_back(fragments); + } + else { + std::copy(fragments.begin(), fragments.end(), + std::back_inserter(last_buffer)); + } + } + + m_fragment_count = fragments.size(); +} + +std::vector Interleaver::Interleave() +{ + std::vector fragments; + + while ( not m_buffer.empty() and + (m_buffer.front().size() >= m_fragment_count * m_latency)) { + + auto& first_buffer = m_buffer.front(); + + assert(first_buffer.size() == m_fragment_count * m_latency); + + /* Assume we have 5 fragments per AF frame, and latency of 3. + * This will give the following strides: + * 0 1 2 + * +-------+-------+---+ + * | 0 1 | 2 3 | 4 | + * | | +---+ | + * | 5 6 | 7 | 8 9 | + * | +---+ | | + * |10 |11 12 |13 14 | + * +---+-------+-------+ + * + * ix will be 0, 5, 10, 1, 6 in the first loop + */ + + for (size_t i = 0; i < m_fragment_count; i++) { + const size_t ix = m_interleave_offset + m_fragment_count * m_stride; + fragments.push_back(first_buffer.at(ix)); + + m_stride += 1; + if (m_stride >= m_latency) { + m_interleave_offset++; + m_stride = 0; + } + } + + if (m_interleave_offset >= m_fragment_count) { + m_interleave_offset = 0; + m_stride = 0; + m_buffer.pop_front(); + } + } + + return fragments; +} + +} + + diff --git a/src/dabOutput/edi/Interleaver.h b/src/dabOutput/edi/Interleaver.h new file mode 100644 index 0000000..1a2e26d --- /dev/null +++ b/src/dabOutput/edi/Interleaver.h @@ -0,0 +1,66 @@ +/* + Copyright (C) 2016 + Matthias P. Braendli, matthias.braendli@mpb.li + + http://www.opendigitalradio.org + + EDI output, + Interleaving of PFT fragments to increase robustness against + burst packet loss. + + This is possible because EDI has to assume that fragments may reach + the receiver out of order. + + */ +/* + This file is part of ODR-DabMux. + + ODR-DabMux 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. + + ODR-DabMux 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 ODR-DabMux. If not, see . + */ + +#pragma once + +#include "config.h" +#include +#include +#include +#include +#include "Log.h" +#include "PFT.h" + +namespace edi { + +class Interleaver { + public: + /* Configure the interleaver to use latency_frames number of AF + * packets for interleaving. Total delay through the interleaver + * will be latency_frames * 24ms + */ + void SetLatency(size_t latency_frames); + + /* Push the fragments for an AF Packet into the interleaver */ + void PushFragments(const std::vector< PFTFragment > &fragments); + + std::vector< PFTFragment > Interleave(void); + + private: + size_t m_latency = 0; + size_t m_fragment_count = 0; + size_t m_interleave_offset = 0; + size_t m_stride = 0; + std::deque > m_buffer; +}; + +} + -- cgit v1.2.3