Skip to content

Commit f1e136f

Browse files
committed
Decoder: when we known there's a mismatch between the fountain chunk size...
... and the fountain *stream* (sink)'s chunk size, we shouldn't send it the decoded bytes. It's not going to be able to do anything useful with them. Instead, we'll have a /dev/null style "null_stream" that just tracks how many bytes were written to it.
1 parent f5607a3 commit f1e136f

File tree

4 files changed

+52
-7
lines changed

4 files changed

+52
-7
lines changed

src/lib/encoder/Decoder.h

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#include "cimb_translator/Config.h"
99
#include "cimb_translator/Interleave.h"
1010
#include "util/File.h"
11+
#include "util/null_stream.h"
1112

1213
#include <opencv2/opencv.hpp>
1314
#include <functional>
@@ -166,8 +167,22 @@ template <typename MAT, typename FOUNTAINSTREAM>
166167
inline unsigned Decoder::decode_fountain(const MAT& img, FOUNTAINSTREAM& ostream, unsigned color_mode, bool should_preprocess, int color_correction)
167168
{
168169
CimbReader reader(img, _decoder, color_mode, should_preprocess, color_correction);
169-
aligned_stream aligner(ostream, ostream.chunk_size(), 0, std::bind(&CimbReader::update_metadata, &reader, std::placeholders::_1, std::placeholders::_2));
170-
return do_decode(reader, aligner, color_mode==0);
170+
bool legacy_mode = color_mode == 0;
171+
unsigned chunk_size = cimbar::Config::fountain_chunk_size(_eccBytes, _bitsPerOp, legacy_mode);
172+
auto update_md_fun = std::bind(&CimbReader::update_metadata, &reader, std::placeholders::_1, std::placeholders::_2);
173+
174+
// we don't want to feed the fountain stream bad data, so we eat the decode if we have a mismatch
175+
// we still might succeed the decode, in which case (hopefully) the positive bytes we return will
176+
// tell our caller to fix the underlying ostream so the next round will work.
177+
if (ostream.chunk_size() != chunk_size)
178+
{
179+
null_stream devnull;
180+
aligned_stream aligner(devnull, chunk_size, 0, update_md_fun);
181+
return do_decode(reader, aligner, legacy_mode);
182+
}
183+
184+
aligned_stream aligner(ostream, ostream.chunk_size(), 0, update_md_fun);
185+
return do_decode(reader, aligner, legacy_mode);
171186
}
172187

173188
inline unsigned Decoder::decode(std::string filename, std::string output, unsigned color_mode)

src/lib/encoder/reed_solomon_stream.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ class reed_solomon_stream
8888
bool _good;
8989
};
9090

91-
inline std::ifstream& operator<<(std::ifstream& s, const ReedSolomon::BadChunk& chunk)
91+
inline std::ifstream& operator<<(std::ifstream& s, const ReedSolomon::BadChunk&)
9292
{
9393
return s;
9494
}

src/lib/encoder/test/EncoderRoundTripTest.cpp

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -64,9 +64,10 @@ TEST_CASE( "EncoderRoundTripTest/testFountain.SinkMismatch", "[unit]" )
6464

6565
// will be padded so the fountain encoding is happy. The encoded image looks suspiciously non-random!
6666
Encoder enc(30, 4, 2);
67+
enc.set_legacy_mode();
6768
assertEquals( 1, enc.encode_fountain(inputFile, outPrefix) );
6869

69-
uint64_t hash = 0xeecc8800efce8c48;
70+
uint64_t hash = 0xaecc8c00efce8c28;
7071
std::string path = fmt::format("{}_0.png", outPrefix);
7172
cv::Mat encodedImg = cv::imread(path);
7273
cv::cvtColor(encodedImg, encodedImg, cv::COLOR_BGR2RGB);
@@ -75,10 +76,11 @@ TEST_CASE( "EncoderRoundTripTest/testFountain.SinkMismatch", "[unit]" )
7576
// decoder
7677
Decoder dec(30);
7778
// sink with a mismatched fountain_chunk_size
78-
// importantly, the sink expects a *larger* chunk than we'll give it...
79-
fountain_decoder_sink<cimbar::zstd_decompressor<std::ofstream>> fds(tempdir.path(), cimbar::Config::fountain_chunk_size(30, 6, true));
79+
// importantly, the sink expects a *smaller* chunk than we'll give it...
80+
// because that's a more interesting test...
81+
fountain_decoder_sink<cimbar::zstd_decompressor<std::ofstream>> fds(tempdir.path(), cimbar::Config::fountain_chunk_size(30, 6, false));
8082

81-
unsigned bytesDecoded = dec.decode_fountain(encodedImg, fds, 1);
83+
unsigned bytesDecoded = dec.decode_fountain(encodedImg, fds, 0);
8284
assertEquals( 7500, bytesDecoded );
8385

8486
assertEquals( 0, fds.num_done() );

src/lib/util/null_stream.h

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
/* This code is subject to the terms of the Mozilla Public License, v.2.0. http://mozilla.org/MPL/2.0/. */
2+
#pragma once
3+
4+
class null_stream
5+
{
6+
public:
7+
null_stream()
8+
{}
9+
10+
null_stream& write(const char*, unsigned length)
11+
{
12+
_count += length;
13+
return *this;
14+
}
15+
16+
bool good() const
17+
{
18+
return true;
19+
}
20+
21+
long tellp() const
22+
{
23+
return _count;
24+
}
25+
26+
protected:
27+
long _count = 0;
28+
};

0 commit comments

Comments
 (0)