Skip to content

Commit

Permalink
Merge pull request #710 from LebedevRI/bs-pos
Browse files Browse the repository at this point in the history
Invent roundripping between `BitStreamer` state and byte stream position
  • Loading branch information
LebedevRI authored Apr 10, 2024
2 parents 57f9405 + caa47f1 commit 19a74a7
Show file tree
Hide file tree
Showing 54 changed files with 438 additions and 51 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
#include "adt/Casts.h"
#include "adt/Point.h"
#include "bench/Common.h"
#include "bitstreams/BitStreams.h"
#include "common/Common.h"
#include "common/RawImage.h"
#include "io/Buffer.h"
Expand Down
5 changes: 5 additions & 0 deletions cmake/Modules/cpu-cache-line-size.cpp
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
#include <cerrno>
#include <cstdint>
#include <iostream>
#include <optional>
Expand All @@ -6,6 +7,10 @@
#include <unistd.h>
#endif

#if defined(__GLIBC__)
#include <elf.h>
#endif

#if defined(_POSIX_C_SOURCE) && defined(_SC_LEVEL1_DCACHE_LINESIZE)
static std::optional<int64_t> get_cachelinesize_from_sysconf() {
long val = ::sysconf(_SC_LEVEL1_DCACHE_LINESIZE);
Expand Down
1 change: 1 addition & 0 deletions cmake/Modules/cpu-large-page-size.cpp
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
#include <cstddef>
#include <iostream>

#if defined(__i386__) || defined(__x86_64__)
Expand Down
3 changes: 2 additions & 1 deletion fuzz/librawspeed/decompressors/UncompressedDecompressor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
#include "MemorySanitizer.h"
#include "adt/Casts.h"
#include "adt/Point.h"
#include "common/Common.h"
#include "bitstreams/BitStreams.h"
#include "common/RawImage.h"
#include "common/RawspeedException.h"
#include "fuzz/Common.h"
Expand Down Expand Up @@ -54,6 +54,7 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* Data, size_t Size) {
case static_cast<int>(rawspeed::BitOrder::MSB):
case static_cast<int>(rawspeed::BitOrder::MSB16):
case static_cast<int>(rawspeed::BitOrder::MSB32):
case static_cast<int>(rawspeed::BitOrder::JPEG):
return rawspeed::BitOrder(val);
default:
ThrowRSE("Unknown bit order: %u", val);
Expand Down
3 changes: 2 additions & 1 deletion src/librawspeed/bitstreams/BitStream.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,12 @@
#include "adt/Bit.h"
#include "adt/Casts.h"
#include "adt/Invariant.h"
#include "bitstreams/BitStreams.h"
#include <cstdint>

namespace rawspeed {

template <typename BIT_STREAM> struct BitStreamTraits;
template <BitOrder bo> struct BitStreamTraits;

// simple 64-bit wide cache implementation that acts like a FiFo.
// There are two variants:
Expand Down
4 changes: 2 additions & 2 deletions src/librawspeed/bitstreams/BitStreamJPEG.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,9 @@

namespace rawspeed {

class BitStreamJPEG;
template <> struct BitStreamTraits<BitOrder::JPEG> final {
static constexpr BitOrder Tag = BitOrder::JPEG;

template <> struct BitStreamTraits<BitStreamJPEG> final {
using StreamFlow = BitStreamCacheRightInLeftOut;

static constexpr bool FixedSizeChunks = false; // Stuffing byte...
Expand Down
4 changes: 2 additions & 2 deletions src/librawspeed/bitstreams/BitStreamLSB.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,9 @@

namespace rawspeed {

class BitStreamLSB;
template <> struct BitStreamTraits<BitOrder::LSB> final {
static constexpr BitOrder Tag = BitOrder::LSB;

template <> struct BitStreamTraits<BitStreamLSB> final {
using StreamFlow = BitStreamCacheLeftInRightOut;

static constexpr bool FixedSizeChunks = true;
Expand Down
4 changes: 2 additions & 2 deletions src/librawspeed/bitstreams/BitStreamMSB.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,9 @@

namespace rawspeed {

class BitStreamMSB;
template <> struct BitStreamTraits<BitOrder::MSB> final {
static constexpr BitOrder Tag = BitOrder::MSB;

template <> struct BitStreamTraits<BitStreamMSB> final {
using StreamFlow = BitStreamCacheRightInLeftOut;

static constexpr bool FixedSizeChunks = true;
Expand Down
4 changes: 2 additions & 2 deletions src/librawspeed/bitstreams/BitStreamMSB16.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,9 @@

namespace rawspeed {

class BitStreamMSB16;
template <> struct BitStreamTraits<BitOrder::MSB16> final {
static constexpr BitOrder Tag = BitOrder::MSB16;

template <> struct BitStreamTraits<BitStreamMSB16> final {
using StreamFlow = BitStreamCacheRightInLeftOut;

static constexpr bool FixedSizeChunks = true;
Expand Down
4 changes: 2 additions & 2 deletions src/librawspeed/bitstreams/BitStreamMSB32.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,9 @@

namespace rawspeed {

class BitStreamMSB32;
template <> struct BitStreamTraits<BitOrder::MSB32> final {
static constexpr BitOrder Tag = BitOrder::MSB32;

template <> struct BitStreamTraits<BitStreamMSB32> final {
using StreamFlow = BitStreamCacheRightInLeftOut;

static constexpr bool FixedSizeChunks = true;
Expand Down
78 changes: 78 additions & 0 deletions src/librawspeed/bitstreams/BitStreamPosition.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
/*
RawSpeed - RAW file decoder.
Copyright (C) 2024 Roman Lebedev
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library 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
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/

#pragma once

#include "adt/Casts.h"
#include "adt/Invariant.h"
#include "bitstreams/BitStreams.h"
#include "common/Common.h"

namespace rawspeed {

template <BitOrder bo> struct BitStreamTraits;

template <BitOrder bo> struct BitStreamPosition {
int pos;
int fillLevel;
};

template <BitOrder bo> struct ByteStreamPosition {
int bytePos;
int numBitsToSkip;
};

template <BitOrder bo>
requires BitStreamTraits<bo>::FixedSizeChunks
ByteStreamPosition<bo> getAsByteStreamPosition(BitStreamPosition<bo> state) {
const int MinByteStepMultiple = BitStreamTraits<bo>::MinLoadStepByteMultiple;

invariant(state.pos >= 0);
invariant(state.pos % MinByteStepMultiple == 0);
invariant(state.fillLevel >= 0);

auto numBytesRemainingInCache =
implicit_cast<int>(roundUpDivision(state.fillLevel, CHAR_BIT));
invariant(numBytesRemainingInCache >= 0);
invariant(numBytesRemainingInCache <= state.pos);

auto numBytesToBacktrack = implicit_cast<int>(
roundUp(numBytesRemainingInCache, MinByteStepMultiple));
invariant(numBytesToBacktrack >= 0);
invariant(numBytesToBacktrack <= state.pos);
invariant(numBytesToBacktrack % MinByteStepMultiple == 0);

auto numBitsToBacktrack = CHAR_BIT * numBytesToBacktrack;
invariant(numBitsToBacktrack >= 0);

ByteStreamPosition<bo> res;
invariant(state.pos >= numBytesToBacktrack);
res.bytePos = state.pos - numBytesToBacktrack;
invariant(numBitsToBacktrack >= state.fillLevel);
res.numBitsToSkip = numBitsToBacktrack - state.fillLevel;

invariant(res.bytePos >= 0);
invariant(res.bytePos <= state.pos);
invariant(res.bytePos % MinByteStepMultiple == 0);
invariant(res.numBitsToSkip >= 0);
return res;
}

} // namespace rawspeed
20 changes: 14 additions & 6 deletions src/librawspeed/bitstreams/BitStreamer.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ template <typename Tag> struct BitStreamerReplenisherBase {
using size_type = int32_t;

using Traits = BitStreamerTraits<Tag>;
using StreamTraits = BitStreamTraits<typename Traits::Stream>;
using StreamTraits = BitStreamTraits<Traits::Tag>;

Array1DRef<const std::byte> input;
int pos = 0;
Expand Down Expand Up @@ -74,7 +74,7 @@ struct BitStreamerForwardSequentialReplenisher final
: public BitStreamerReplenisherBase<Tag> {
using Base = BitStreamerReplenisherBase<Tag>;
using Traits = BitStreamerTraits<Tag>;
using StreamTraits = BitStreamTraits<typename Traits::Stream>;
using StreamTraits = BitStreamTraits<Traits::Tag>;

using Base::BitStreamerReplenisherBase;

Expand Down Expand Up @@ -138,7 +138,7 @@ class BitStreamer {
public:
using size_type = int32_t;
using Traits = BitStreamerTraits<Derived>;
using StreamTraits = BitStreamTraits<typename Traits::Stream>;
using StreamTraits = BitStreamTraits<Traits::Tag>;

using Cache = typename StreamTraits::StreamFlow;

Expand Down Expand Up @@ -278,11 +278,11 @@ class BitStreamer {
return getBitsNoFill(nbits);
}

// This may be used to skip arbitrarily large number of *bytes*,
// This may be used to skip arbitrarily large number of *bits*,
// not limited by the fill level.
void skipBytes(int nbytes) {
void skipManyBits(int nbits) {
establishClassInvariants();
int remainingBitsToSkip = 8 * nbytes;
int remainingBitsToSkip = nbits;
for (; remainingBitsToSkip >= Cache::MaxGetBits;
remainingBitsToSkip -= Cache::MaxGetBits) {
fill(Cache::MaxGetBits);
Expand All @@ -293,6 +293,14 @@ class BitStreamer {
skipBitsNoFill(remainingBitsToSkip);
}
}

// This may be used to skip arbitrarily large number of *bytes*,
// not limited by the fill level.
void skipBytes(int nbytes) {
establishClassInvariants();
int nbits = 8 * nbytes;
skipManyBits(nbits);
}
};

} // namespace rawspeed
4 changes: 2 additions & 2 deletions src/librawspeed/bitstreams/BitStreamerJPEG.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,12 @@
#include "rawspeedconfig.h"
#include "adt/Array1DRef.h"
#include "adt/Bit.h"
#include "adt/Casts.h"
#include "adt/Invariant.h"
#include "bitstreams/BitStream.h"
#include "bitstreams/BitStreamJPEG.h"
#include "bitstreams/BitStreamer.h"
#include "io/Endianness.h"
#include <algorithm>
#include <array>
#include <concepts>
#include <cstddef>
Expand Down Expand Up @@ -68,7 +68,7 @@ class PosOrUnknown final {
class BitStreamerJPEG;

template <> struct BitStreamerTraits<BitStreamerJPEG> final {
using Stream = BitStreamJPEG;
static constexpr BitOrder Tag = BitOrder::JPEG;

static constexpr bool canUseWithPrefixCodeDecoder = true;

Expand Down
2 changes: 1 addition & 1 deletion src/librawspeed/bitstreams/BitStreamerLSB.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ namespace rawspeed {
class BitStreamerLSB;

template <> struct BitStreamerTraits<BitStreamerLSB> final {
using Stream = BitStreamLSB;
static constexpr BitOrder Tag = BitOrder::LSB;

// How many bytes can we read from the input per each fillCache(), at most?
static constexpr int MaxProcessBytes = 4;
Expand Down
2 changes: 1 addition & 1 deletion src/librawspeed/bitstreams/BitStreamerMSB.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ namespace rawspeed {
class BitStreamerMSB;

template <> struct BitStreamerTraits<BitStreamerMSB> final {
using Stream = BitStreamMSB;
static constexpr BitOrder Tag = BitOrder::MSB;

static constexpr bool canUseWithPrefixCodeDecoder = true;

Expand Down
2 changes: 1 addition & 1 deletion src/librawspeed/bitstreams/BitStreamerMSB16.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ namespace rawspeed {
class BitStreamerMSB16;

template <> struct BitStreamerTraits<BitStreamerMSB16> final {
using Stream = BitStreamMSB16;
static constexpr BitOrder Tag = BitOrder::MSB16;

// How many bytes can we read from the input per each fillCache(), at most?
static constexpr int MaxProcessBytes = 4;
Expand Down
2 changes: 1 addition & 1 deletion src/librawspeed/bitstreams/BitStreamerMSB32.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ namespace rawspeed {
class BitStreamerMSB32;

template <> struct BitStreamerTraits<BitStreamerMSB32> final {
using Stream = BitStreamMSB32;
static constexpr BitOrder Tag = BitOrder::MSB32;

static constexpr bool canUseWithPrefixCodeDecoder = true;

Expand Down
37 changes: 37 additions & 0 deletions src/librawspeed/bitstreams/BitStreams.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
/*
RawSpeed - RAW file decoder.
Copyright (C) 2009-2014 Klaus Post
Copyright (C) 2024 Roman Lebedev
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library 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
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/

#pragma once

#include <cstdint>

namespace rawspeed {

enum class BitOrder : uint8_t {
LSB, /* Memory order */
MSB, /* Input is added to stack byte by byte, and output is lifted
from top */
MSB16, /* Same as above, but 16 bits at the time */
MSB32, /* Same as above, but 32 bits at the time */
JPEG, /* Same as MSB, but 0xFF byte is followed by an 0x00 stuffing byte */
};

} // namespace rawspeed
2 changes: 1 addition & 1 deletion src/librawspeed/bitstreams/BitVacuumer.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ template <typename Derived_, typename OutputIterator_>
class BitVacuumer {
public:
using Traits = BitVacuumerTraits<Derived_>;
using StreamTraits = BitStreamTraits<typename Traits::Stream>;
using StreamTraits = BitStreamTraits<Traits::Tag>;

using Cache = typename StreamTraits::StreamFlow;

Expand Down
2 changes: 1 addition & 1 deletion src/librawspeed/bitstreams/BitVacuumerJPEG.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ template <typename OutputIterator> class BitVacuumerJPEG;

template <typename OutputIterator>
struct BitVacuumerTraits<BitVacuumerJPEG<OutputIterator>> final {
using Stream = BitStreamJPEG;
static constexpr BitOrder Tag = BitOrder::JPEG;

static constexpr bool canUseWithPrefixCodeEncoder = true;
};
Expand Down
2 changes: 1 addition & 1 deletion src/librawspeed/bitstreams/BitVacuumerLSB.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ template <typename OutputIterator> class BitVacuumerLSB;

template <typename OutputIterator>
struct BitVacuumerTraits<BitVacuumerLSB<OutputIterator>> final {
using Stream = BitStreamLSB;
static constexpr BitOrder Tag = BitOrder::LSB;
};

template <typename OutputIterator>
Expand Down
2 changes: 1 addition & 1 deletion src/librawspeed/bitstreams/BitVacuumerMSB.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ template <typename OutputIterator> class BitVacuumerMSB;

template <typename OutputIterator>
struct BitVacuumerTraits<BitVacuumerMSB<OutputIterator>> final {
using Stream = BitStreamMSB;
static constexpr BitOrder Tag = BitOrder::MSB;

static constexpr bool canUseWithPrefixCodeEncoder = true;
};
Expand Down
2 changes: 1 addition & 1 deletion src/librawspeed/bitstreams/BitVacuumerMSB16.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ template <typename OutputIterator> class BitVacuumerMSB16;

template <typename OutputIterator>
struct BitVacuumerTraits<BitVacuumerMSB16<OutputIterator>> final {
using Stream = BitStreamMSB16;
static constexpr BitOrder Tag = BitOrder::MSB16;
};

template <typename OutputIterator>
Expand Down
Loading

0 comments on commit 19a74a7

Please sign in to comment.