Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Invent roundripping between BitStreamer state and byte stream position #710

Merged
merged 6 commits into from
Apr 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
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
Loading