Commit cb261e2d authored by David Flynn's avatar David Flynn
Browse files

entropy/m43649: use schroarith for arithmetic coding

This commit provides an implementation of the entropy coding interface
using the dirac (schroedinger) arithmetic codec.

In order to handle any remaining m-ary symbols, a naïve unary
binarisation is employed.
parent 0d777487
cmake_minimum_required(VERSION 3.0) cmake_minimum_required(VERSION 3.0)
enable_language(C)
if (UNIX) if (UNIX)
add_definitions(-D_POSIX_C_SOURCE=200809L) add_definitions(-D_POSIX_C_SOURCE=200809L)
...@@ -73,6 +74,7 @@ file(GLOB PROJECT_INC_FILES ...@@ -73,6 +74,7 @@ file(GLOB PROJECT_INC_FILES
"TMC3.h" "TMC3.h"
"constants.h" "constants.h"
"entropy.h" "entropy.h"
"entropydirac.h"
"entropyo3dgc.h" "entropyo3dgc.h"
"entropyutils.h" "entropyutils.h"
"geometry.h" "geometry.h"
...@@ -91,6 +93,7 @@ file(GLOB PROJECT_INC_FILES ...@@ -91,6 +93,7 @@ file(GLOB PROJECT_INC_FILES
"../dependencies/nanoflann/*.h" "../dependencies/nanoflann/*.h"
"../dependencies/arithmetic-coding/inc/*.h" "../dependencies/arithmetic-coding/inc/*.h"
"../dependencies/program-options-lite/*.h" "../dependencies/program-options-lite/*.h"
"../dependencies/schroedinger/schroarith.h"
) )
file(GLOB PROJECT_CPP_FILES file(GLOB PROJECT_CPP_FILES
...@@ -102,6 +105,7 @@ file(GLOB PROJECT_CPP_FILES ...@@ -102,6 +105,7 @@ file(GLOB PROJECT_CPP_FILES
"TMC3.cpp" "TMC3.cpp"
"decoder.cpp" "decoder.cpp"
"encoder.cpp" "encoder.cpp"
"entropydirac.cpp"
"geometry_intra_pred.cpp" "geometry_intra_pred.cpp"
"geometry_octree.cpp" "geometry_octree.cpp"
"geometry_octree_decoder.cpp" "geometry_octree_decoder.cpp"
...@@ -115,6 +119,7 @@ file(GLOB PROJECT_CPP_FILES ...@@ -115,6 +119,7 @@ file(GLOB PROJECT_CPP_FILES
"tables.cpp" "tables.cpp"
"../dependencies/arithmetic-coding/src/*.cpp" "../dependencies/arithmetic-coding/src/*.cpp"
"../dependencies/program-options-lite/*.cpp" "../dependencies/program-options-lite/*.cpp"
"../dependencies/schroedinger/schroarith.c"
) )
source_group (inc FILES ${PROJECT_INC_FILES}) source_group (inc FILES ${PROJECT_INC_FILES})
...@@ -123,6 +128,7 @@ source_group (cpp FILES ${PROJECT_CPP_FILES}) ...@@ -123,6 +128,7 @@ source_group (cpp FILES ${PROJECT_CPP_FILES})
include_directories( include_directories(
"${PROJECT_BINARY_DIR}/tmc3" "${PROJECT_BINARY_DIR}/tmc3"
"${PROJECT_SOURCE_DIR}"
"${CMAKE_CURRENT_SOURCE_DIR}" "${CMAKE_CURRENT_SOURCE_DIR}"
"${CMAKE_CURRENT_SOURCE_DIR}/../dependencies/nanoflann" "${CMAKE_CURRENT_SOURCE_DIR}/../dependencies/nanoflann"
"${CMAKE_CURRENT_SOURCE_DIR}/../dependencies/arithmetic-coding/inc" "${CMAKE_CURRENT_SOURCE_DIR}/../dependencies/arithmetic-coding/inc"
......
...@@ -35,17 +35,26 @@ ...@@ -35,17 +35,26 @@
#pragma once #pragma once
#define ENTROPY_O3DGC 1 #define ENTROPY_O3DGC 0
#define ENTROPY_DIRAC 1
#if ENTROPY_O3DGC #if ENTROPY_O3DGC
# include "entropyo3dgc.h" # include "entropyo3dgc.h"
#endif #endif
#if ENTROPY_DIRAC
# include "entropydirac.h"
#endif
#include "entropyutils.h" #include "entropyutils.h"
#if ENTROPY_O3DGC
namespace pcc { namespace pcc {
#if ENTROPY_O3DGC
using EntropyEncoder = EntropyEncoderWrapper<o3dgc::ArithmeticEncoder>; using EntropyEncoder = EntropyEncoderWrapper<o3dgc::ArithmeticEncoder>;
using EntropyDecoder = EntropyDecoderWrapper<o3dgc::ArithmeticDecoder>; using EntropyDecoder = EntropyDecoderWrapper<o3dgc::ArithmeticDecoder>;
} // namespace pcc
#endif #endif
#if ENTROPY_DIRAC
using EntropyEncoder = EntropyEncoderWrapper<dirac::ArithmeticEncoder>;
using EntropyDecoder = EntropyDecoderWrapper<dirac::ArithmeticDecoder>;
#endif
} // namespace pcc
/* The copyright in this software is being made available under the BSD
* Licence, included below. This software may be subject to other third
* party and contributor rights, including patent rights, and no such
* rights are granted under this licence.
*
* Copyright (c) 2017-2018, ISO/IEC
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* * Neither the name of the ISO/IEC nor the names of its contributors
* may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include "entropydirac.h"
#include "PCCMisc.h"
#include <algorithm>
namespace pcc {
namespace dirac {
//=========================================================================
void SchroMAryContext::set_alphabet(int numsyms)
{
// initialise all contexts with p = 0.5
this->numsyms = numsyms;
this->probabilities = std::vector<uint16_t>(numsyms, 0x8000);
}
//=========================================================================
void ArithmeticEncoder::encode(int sym, SchroMAryContext& model)
{
int ctxidx = 0;
while (sym-- > 0) {
schro_arith_encode_bit(&impl, &model.probabilities[ctxidx++], 1);
}
// todo(df): this should be truncated unary coded
schro_arith_encode_bit(&impl, &model.probabilities[ctxidx], 0);
}
//=========================================================================
int ArithmeticDecoder::decode(SchroMAryContext& model)
{
int ctxidx = 0;
int sym = 0;
while (schro_arith_decode_bit(&impl, &model.probabilities[ctxidx++])) {
sym++;
}
return sym;
}
//==========================================================================
} // namespace dirac
} // namespace pcc
/* The copyright in this software is being made available under the BSD
* Licence, included below. This software may be subject to other third
* party and contributor rights, including patent rights, and no such
* rights are granted under this licence.
*
* Copyright (c) 2017-2018, ISO/IEC
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* * Neither the name of the ISO/IEC nor the names of its contributors
* may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#pragma once
#include "dependencies/schroedinger/schroarith.h"
#include <assert.h>
#include <stdlib.h>
#include <memory>
#include <vector>
namespace pcc {
namespace dirac {
//==========================================================================
struct SchroContext {
uint16_t probability = 0x8000; // p=0.5
template<class... Args>
void reset(Args...)
{
probability = 0x8000;
}
};
//==========================================================================
struct SchroContextFixed {
//uint16_t probability = 0x8000; // p=0.5
};
//==========================================================================
// context definition that automatically binarises an m-ary symbol
struct SchroMAryContext {
SchroMAryContext() = default;
SchroMAryContext(int numsyms) { set_alphabet(numsyms); }
void set_alphabet(int numsyms);
int numsyms;
std::vector<uint16_t> probabilities;
};
//==========================================================================
struct InvalidContext {
void set_alphabet(int) {}
};
//==========================================================================
class ArithmeticEncoder {
public:
ArithmeticEncoder() = default;
ArithmeticEncoder(size_t bufferSize, std::nullptr_t)
{
setBuffer(bufferSize, nullptr);
}
//------------------------------------------------------------------------
void setBuffer(size_t size, uint8_t* buffer)
{
buf.length = int(size);
if (buffer)
buf.data = buffer;
else {
allocatedBuffer.reset(new uint8_t[size]);
buf.data = allocatedBuffer.get();
}
}
//------------------------------------------------------------------------
void start() { schro_arith_encode_init(&impl, &buf); }
//------------------------------------------------------------------------
size_t stop()
{
schro_arith_flush(&impl);
return impl.offset;
}
//------------------------------------------------------------------------
const char* buffer() { return reinterpret_cast<char*>(buf.data); }
//------------------------------------------------------------------------
void encode(int bit, SchroContextFixed& model)
{
uint16_t probability = 0x8000; // p=0.5
schro_arith_encode_bit(&impl, &probability, bit);
}
//------------------------------------------------------------------------
void encode(int data, SchroMAryContext& model);
//------------------------------------------------------------------------
void encode(int data, InvalidContext& model) { assert(0); }
void encode(int bit, SchroContext& model)
{
schro_arith_encode_bit(&impl, &model.probability, bit);
}
//------------------------------------------------------------------------
private:
::SchroArith impl;
::SchroBuffer buf;
std::unique_ptr<uint8_t[]> allocatedBuffer;
};
//==========================================================================
class ArithmeticDecoder {
public:
void setBuffer(size_t size, const char* buffer)
{
buf.data = reinterpret_cast<uint8_t*>(const_cast<char*>(buffer));
buf.length = int(size);
}
//------------------------------------------------------------------------
void start() { schro_arith_decode_init(&impl, &buf); }
//------------------------------------------------------------------------
void stop() { schro_arith_decode_flush(&impl); }
//------------------------------------------------------------------------
int decode(SchroContextFixed& model)
{
uint16_t probability = 0x8000; // p=0.5
return schro_arith_decode_bit(&impl, &probability);
}
//------------------------------------------------------------------------
int decode(SchroMAryContext& model);
//------------------------------------------------------------------------
int decode(InvalidContext& model)
{
assert(0);
return 0;
}
//------------------------------------------------------------------------
int decode(SchroContext& model)
{
return schro_arith_decode_bit(&impl, &model.probability);
}
//------------------------------------------------------------------------
private:
::SchroArith impl;
::SchroBuffer buf;
};
//==========================================================================
} // namespace dirac
using StaticBitModel = dirac::SchroContextFixed;
using StaticMAryModel = dirac::InvalidContext;
using AdaptiveBitModel = dirac::SchroContext;
using AdaptiveBitModelFast = dirac::SchroContext;
using AdaptiveMAryModel = dirac::SchroMAryContext;
//============================================================================
} // namespace pcc
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment