diff options
author | Matthias P. Braendli <matthias.braendli@mpb.li> | 2016-12-23 22:27:03 +0100 |
---|---|---|
committer | Matthias P. Braendli <matthias.braendli@mpb.li> | 2016-12-23 22:27:03 +0100 |
commit | 2b014e2f00df81eefe977b901ab601ea11ccb895 (patch) | |
tree | a5c6fe371838ff3e153c99c6a87554b55b2284d1 /src/dabOutput/edi/Interleaver.cpp | |
parent | 1d2c8bf95e8d9c7c6f282f266b149bc82f1c8371 (diff) | |
download | dabmux-2b014e2f00df81eefe977b901ab601ea11ccb895.tar.gz dabmux-2b014e2f00df81eefe977b901ab601ea11ccb895.tar.bz2 dabmux-2b014e2f00df81eefe977b901ab601ea11ccb895.zip |
Add EDI fragment interleaver
Diffstat (limited to 'src/dabOutput/edi/Interleaver.cpp')
-rw-r--r-- | src/dabOutput/edi/Interleaver.cpp | 114 |
1 files changed, 114 insertions, 0 deletions
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 <http://www.gnu.org/licenses/>. + */ + +#include "Interleaver.h" + +namespace edi { + +void Interleaver::SetLatency(size_t latency_frames) +{ + m_latency = latency_frames; +} + +void Interleaver::PushFragments(const std::vector<PFTFragment> &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<PFTFragment> Interleaver::Interleave() +{ + std::vector<PFTFragment> 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; +} + +} + + |