From 6eb9a403558d4dfde1de36e5c6744b58dc26ea79 Mon Sep 17 00:00:00 2001 From: "Matthias P. Braendli" Date: Sun, 12 Feb 2017 17:51:48 +0100 Subject: Fix incorrect frame size bug due to missing puncturing padding --- src/ConvEncoder.cpp | 7 +++++++ src/DabModulator.cpp | 2 +- src/PuncturingEncoder.cpp | 33 +++++++++++++++++++++++++++++++-- src/PuncturingEncoder.h | 17 +++++++++++++++-- src/SubchannelSource.cpp | 47 +++++++++++++++++++++++++---------------------- src/SubchannelSource.h | 4 +++- 6 files changed, 82 insertions(+), 28 deletions(-) diff --git a/src/ConvEncoder.cpp b/src/ConvEncoder.cpp index 74de34f..06b2e85 100644 --- a/src/ConvEncoder.cpp +++ b/src/ConvEncoder.cpp @@ -111,6 +111,7 @@ int ConvEncoder::process(Buffer* const dataIn, Buffer* dataOut) } ++in_offset; } + for (unsigned pad_count = 0; pad_count < 3; ++pad_count) { out[out_offset] = 0; // For each 4-bit output word @@ -138,5 +139,11 @@ int ConvEncoder::process(Buffer* const dataIn, Buffer* dataOut) PDEBUG(" Consume: %zu\n", in_offset); PDEBUG(" Return: %zu\n", out_offset); + + if (out_offset != dataOut->getLength()) { + throw std::runtime_error("Assertion error: ConvEncoder output " + + std::to_string(out_offset) + " == " + + std::to_string(dataOut->getLength()) + " fail"); + } return out_offset; } diff --git a/src/DabModulator.cpp b/src/DabModulator.cpp index cbe8f07..827b73f 100644 --- a/src/DabModulator.cpp +++ b/src/DabModulator.cpp @@ -302,7 +302,7 @@ int DabModulator::process(Buffer* dataOut) auto subchConv = make_shared(subchSizeIn); // Configuring puncturing encoder - auto subchPunc = make_shared(); + auto subchPunc = make_shared(subchannel->framesizeCu()); for (const auto& rule : subchannel->get_rules()) { PDEBUG(" Adding rule:\n"); diff --git a/src/PuncturingEncoder.cpp b/src/PuncturingEncoder.cpp index a212a93..9bd9004 100644 --- a/src/PuncturingEncoder.cpp +++ b/src/PuncturingEncoder.cpp @@ -35,12 +35,23 @@ PuncturingEncoder::PuncturingEncoder() : ModCodec(), + d_num_cu(0), d_in_block_size(0), d_out_block_size(0), d_tail_rule() { PDEBUG("PuncturingEncoder() @ %p\n", this); +} +PuncturingEncoder::PuncturingEncoder( + size_t num_cu) : + ModCodec(), + d_num_cu(num_cu), + d_in_block_size(0), + d_out_block_size(0), + d_tail_rule() +{ + PDEBUG("PuncturingEncoder(%zu) @ %p\n", num_cu, this); } void PuncturingEncoder::adjust_item_size() @@ -104,12 +115,29 @@ int PuncturingEncoder::process(Buffer* const dataIn, Buffer* dataOut) PDEBUG(" in block size: %zu\n", d_in_block_size); PDEBUG(" out block size: %zu\n", d_out_block_size); + if (d_num_cu > 0) { + if (d_num_cu * 8 == d_out_block_size + 1) { + /* EN 300 401 Table 31 in 11.3.1 UEP coding specifies + * that we need one byte of padding + */ + d_out_block_size = d_num_cu * 8; + } + + if (d_num_cu * 8 != d_out_block_size) { + throw std::runtime_error( + "PuncturingEncoder encoder initialisation failed. " + " CU: " + std::to_string(d_num_cu) + + " block_size: " + std::to_string(d_out_block_size)); + } + } + dataOut->setLength(d_out_block_size); const unsigned char* in = reinterpret_cast(dataIn->getData()); unsigned char* out = reinterpret_cast(dataOut->getData()); if (dataIn->getLength() != d_in_block_size) { - throw std::runtime_error("PuncturingEncoder::process wrong input size"); + throw std::runtime_error( + "PuncturingEncoder::process wrong input size"); } if (d_tail_rule) { @@ -167,7 +195,8 @@ int PuncturingEncoder::process(Buffer* const dataIn, Buffer* dataOut) ++out_count; } } - for (size_t i = d_out_block_size; i < dataOut->getLength(); ++i) { + + for (size_t i = out_count; i < dataOut->getLength(); ++i) { out[out_count++] = 0; } diff --git a/src/PuncturingEncoder.h b/src/PuncturingEncoder.h index 19be53e..b6f9f0e 100644 --- a/src/PuncturingEncoder.h +++ b/src/PuncturingEncoder.h @@ -35,13 +35,26 @@ #include "ModPlugin.h" #include +#include #include #include class PuncturingEncoder : public ModCodec { public: - PuncturingEncoder(); + /* Initialise a puncturer that does not check if the + * outgoing data requires padding. To be used for the + * FIC. The size of the output buffer is derived from + * the puncturing rules only + */ + PuncturingEncoder(void); + + /* Initialise a puncturer that checks if there is up to + * one byte padding needed in the output buffer. See + * EN 300 401 Table 31 in 11.3.1 UEP coding. Up to one + * byte of padding is added + */ + PuncturingEncoder(size_t num_cu); void append_rule(const PuncturingRule& rule); void append_tail_rule(const PuncturingRule& rule); @@ -51,12 +64,12 @@ public: size_t getOutputSize() { return d_out_block_size; } private: + size_t d_num_cu; size_t d_in_block_size; size_t d_out_block_size; std::vector d_rules; boost::optional d_tail_rule; void adjust_item_size(); - }; diff --git a/src/SubchannelSource.cpp b/src/SubchannelSource.cpp index 82636f9..a6b3bc4 100644 --- a/src/SubchannelSource.cpp +++ b/src/SubchannelSource.cpp @@ -2,7 +2,7 @@ Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011 Her Majesty the Queen in Right of Canada (Communications Research Center Canada) - Copyright (C) 2016 + Copyright (C) 2017 Matthias P. Braendli, matthias.braendli@mpb.li http://opendigitalradio.org @@ -26,6 +26,7 @@ #include "SubchannelSource.h" #include "PcDebug.h" +#include "Log.h" #include #include @@ -159,8 +160,9 @@ SubchannelSource::SubchannelSource( throw std::runtime_error("SubchannelSource::SubchannelSource " "unknown protection option!"); } - } else { - bool error = false; + } + else { + bool rule_error = false; switch (bitrate()) { case 32: switch (protectionLevel()) { @@ -193,7 +195,7 @@ SubchannelSource::SubchannelSource( d_puncturing_rules.emplace_back(17 * 16, P2 ); break; default: - error = true; + rule_error = true; } break; case 48: @@ -229,7 +231,7 @@ SubchannelSource::SubchannelSource( d_puncturing_rules.emplace_back(3 * 16, P3 ); break; default: - error = true; + rule_error = true; } break; case 56: @@ -259,7 +261,7 @@ SubchannelSource::SubchannelSource( d_puncturing_rules.emplace_back(3 * 16, P3 ); break; default: - error = true; + rule_error = true; } break; case 64: @@ -294,7 +296,7 @@ SubchannelSource::SubchannelSource( d_puncturing_rules.emplace_back(2 * 16, P3 ); break; default: - error = true; + rule_error = true; } break; case 80: @@ -330,7 +332,7 @@ SubchannelSource::SubchannelSource( d_puncturing_rules.emplace_back(3 * 16, P3 ); break; default: - error = true; + rule_error = true; } break; case 96: @@ -366,7 +368,7 @@ SubchannelSource::SubchannelSource( d_puncturing_rules.emplace_back(3 * 16, P4 ); break; default: - error = true; + rule_error = true; } break; case 112: @@ -396,7 +398,7 @@ SubchannelSource::SubchannelSource( d_puncturing_rules.emplace_back(3 * 16, P5 ); break; default: - error = true; + rule_error = true; } break; case 128: @@ -432,7 +434,7 @@ SubchannelSource::SubchannelSource( d_puncturing_rules.emplace_back(3 * 16, P4 ); break; default: - error = true; + rule_error = true; } break; case 160: @@ -468,7 +470,7 @@ SubchannelSource::SubchannelSource( d_puncturing_rules.emplace_back(3 * 16, P4 ); break; default: - error = true; + rule_error = true; } break; case 192: @@ -504,7 +506,7 @@ SubchannelSource::SubchannelSource( d_puncturing_rules.emplace_back(3 * 16, P5); break; default: - error = true; + rule_error = true; } break; case 224: @@ -540,7 +542,7 @@ SubchannelSource::SubchannelSource( d_puncturing_rules.emplace_back(3 * 16, P6); break; default: - error = true; + rule_error = true; } break; case 256: @@ -576,7 +578,7 @@ SubchannelSource::SubchannelSource( d_puncturing_rules.emplace_back(3 * 16, P5); break; default: - error = true; + rule_error = true; } break; case 320: @@ -600,7 +602,7 @@ SubchannelSource::SubchannelSource( d_puncturing_rules.emplace_back(3 * 16, P6); break; default: - error = true; + rule_error = true; } break; case 384: @@ -624,17 +626,18 @@ SubchannelSource::SubchannelSource( d_puncturing_rules.emplace_back(3 * 16, P7); break; default: - error = true; + rule_error = true; } break; default: - error = true; + rule_error = true; } - if (error) { - fprintf(stderr, " Protection: UEP-%zu @ %zukb/s\n", + + if (rule_error) { + etiLog.log(error, " Protection: UEP-%zu @ %zukb/s\n", protectionLevel(), bitrate()); - throw std::runtime_error("SubchannelSource::SubchannelSource " - "UEP puncturing rules does not exist!"); + throw std::runtime_error("ubchannelSource " + "UEP puncturing rules do not exist!"); } } } diff --git a/src/SubchannelSource.h b/src/SubchannelSource.h index 2dab941..367bb5a 100644 --- a/src/SubchannelSource.h +++ b/src/SubchannelSource.h @@ -2,7 +2,7 @@ Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011 Her Majesty the Queen in Right of Canada (Communications Research Center Canada) - Copyright (C) 2016 + Copyright (C) 2017 Matthias P. Braendli, matthias.braendli@mpb.li http://opendigitalradio.org @@ -52,6 +52,8 @@ public: size_t framesizeCu() const; size_t bitrate() const; size_t protection() const; + + /* Return 1 if long form is used, 0 otherwise */ size_t protectionForm() const; size_t protectionLevel() const; size_t protectionOption() const; -- cgit v1.2.3