summaryrefslogtreecommitdiff
path: root/gpr/source/lib/vc5_common
diff options
context:
space:
mode:
Diffstat (limited to 'gpr/source/lib/vc5_common')
-rw-r--r--gpr/source/lib/vc5_common/CMakeLists.txt20
-rwxr-xr-xgpr/source/lib/vc5_common/bitstream.c445
-rwxr-xr-xgpr/source/lib/vc5_common/bitstream.h135
-rwxr-xr-xgpr/source/lib/vc5_common/codec.c201
-rwxr-xr-xgpr/source/lib/vc5_common/codec.h315
-rwxr-xr-xgpr/source/lib/vc5_common/codeset.h44
-rwxr-xr-xgpr/source/lib/vc5_common/common.h53
-rwxr-xr-xgpr/source/lib/vc5_common/companding.c259
-rwxr-xr-xgpr/source/lib/vc5_common/companding.h46
-rwxr-xr-xgpr/source/lib/vc5_common/config.h87
-rwxr-xr-xgpr/source/lib/vc5_common/error.h88
-rwxr-xr-xgpr/source/lib/vc5_common/image.c321
-rwxr-xr-xgpr/source/lib/vc5_common/image.h165
-rwxr-xr-xgpr/source/lib/vc5_common/logcurve.c58
-rwxr-xr-xgpr/source/lib/vc5_common/logcurve.h42
-rwxr-xr-xgpr/source/lib/vc5_common/pixel.h100
-rwxr-xr-xgpr/source/lib/vc5_common/stream.c524
-rwxr-xr-xgpr/source/lib/vc5_common/stream.h133
-rwxr-xr-xgpr/source/lib/vc5_common/syntax.c150
-rwxr-xr-xgpr/source/lib/vc5_common/syntax.h129
-rwxr-xr-xgpr/source/lib/vc5_common/table17.inc290
-rwxr-xr-xgpr/source/lib/vc5_common/types.h94
-rwxr-xr-xgpr/source/lib/vc5_common/unique.h42
-rwxr-xr-xgpr/source/lib/vc5_common/utilities.c82
-rwxr-xr-xgpr/source/lib/vc5_common/utilities.h36
-rw-r--r--gpr/source/lib/vc5_common/vc5_common.h34
-rwxr-xr-xgpr/source/lib/vc5_common/wavelet.c519
-rwxr-xr-xgpr/source/lib/vc5_common/wavelet.h126
28 files changed, 4538 insertions, 0 deletions
diff --git a/gpr/source/lib/vc5_common/CMakeLists.txt b/gpr/source/lib/vc5_common/CMakeLists.txt
new file mode 100644
index 0000000..090b212
--- /dev/null
+++ b/gpr/source/lib/vc5_common/CMakeLists.txt
@@ -0,0 +1,20 @@
+# library
+set( LIB_NAME vc5_common )
+
+# get source files
+file( GLOB SRC_FILES "*.c" )
+
+# get include files
+file( GLOB INC_FILES "*.h" )
+
+# add include files from other folders
+include_directories( "../common/private" )
+include_directories( "../common/public" )
+
+# library
+add_library( ${LIB_NAME} STATIC ${SRC_FILES} ${INC_FILES} )
+
+target_link_libraries( ${LIB_NAME} )
+
+# set the folder where to place the projects
+set_target_properties( ${LIB_NAME} PROPERTIES FOLDER lib )
diff --git a/gpr/source/lib/vc5_common/bitstream.c b/gpr/source/lib/vc5_common/bitstream.c
new file mode 100755
index 0000000..cef4312
--- /dev/null
+++ b/gpr/source/lib/vc5_common/bitstream.c
@@ -0,0 +1,445 @@
+/*! @file bitstream.c
+ *
+ * @brief Implementation of a bitstream for reading bits from a byte stream.
+ *
+ * @version 1.0.0
+ *
+ * (C) Copyright 2018 GoPro Inc (http://gopro.com/).
+ *
+ * Licensed under either:
+ * - Apache License, Version 2.0, http://www.apache.org/licenses/LICENSE-2.0
+ * - MIT license, http://opensource.org/licenses/MIT
+ * at your option.
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "common.h"
+
+/*!
+ @brief Return a mask with the specified number of bits set to one
+ */
+BITWORD BitMask(int n)
+{
+ if (n < bit_word_count)
+ {
+ BITWORD mask = 0;
+ if (n > 0) {
+ mask = ((1 << n) - 1);
+ }
+ return mask;
+ }
+ return BIT_WORD_MAX;
+}
+
+/*!
+ @brief Initialize a bitstream data structure
+
+ This routine is the constructor for the bitstream data type.
+
+ The sample offset stack is used to mark the offset to a position
+ in the bitstream for computing the size field of sample chunks.
+ */
+CODEC_ERROR InitBitstream(BITSTREAM *bitstream)
+{
+ if (bitstream != NULL)
+ {
+ bitstream->error = BITSTREAM_ERROR_OKAY;
+ bitstream->stream = NULL;
+ bitstream->buffer = 0;
+ bitstream->count = 0;
+
+#if VC5_ENABLED_PART(VC5_PART_SECTIONS)
+ // Initialize the stack of sample offsets
+ memset(bitstream->sample_offset_stack, 0, sizeof(bitstream->sample_offset_stack));
+ bitstream->sample_offset_count = 0;
+#endif
+
+ return CODEC_ERROR_OKAY;
+ }
+
+ return CODEC_ERROR_NULLPTR;
+}
+
+/*!
+ @brief Attach a bitstream to a byte stream.
+
+ It is permitted for the byte stream to be NULL, in which case the
+ bitstream will not be able to replenish its internal buffer, but
+ the consequences are undefined.
+ */
+CODEC_ERROR AttachBitstream(struct _bitstream *bitstream, struct _stream *stream)
+{
+ assert(bitstream != NULL);
+ bitstream->stream = stream;
+ return CODEC_ERROR_OKAY;
+}
+
+/*!
+ @brief Detach a bitstream from a byte stream.
+
+ Any resources allocated by the bitstream are released without deallocating
+ the bitstream data structure itself. The byte stream associated with the
+ bitstream is not closed by this routine. The byte stream must be closed,
+ if and when appropriate, by the caller.
+ */
+CODEC_ERROR ReleaseBitstream(BITSTREAM *bitstream)
+{
+ //TODO: What cleanup needs to be performed?
+ (void) bitstream;
+ return CODEC_ERROR_OKAY;
+}
+
+/*!
+ @brief Return the specified number of bits from the bitstream
+ */
+BITWORD GetBits(BITSTREAM *stream, BITCOUNT count)
+{
+ // Return zero if the request cannot be satisfied
+ BITWORD bits = 0;
+
+ // Check that the number of requested bits is valid
+ //assert(0 <= count && count <= bit_word_count);
+ assert(count <= bit_word_count);
+
+ // Check that the unused portion of the bit buffer is empty
+ assert((stream->buffer & BitMask(bit_word_count - stream->count)) == 0);
+
+ if (count == 0) goto finish;
+
+ // Are there enough bits in the buffer to satisfy the request?
+ if (count <= stream->count)
+ {
+ // Right align the requested number of bits in the bit buffer
+ bits = (stream->buffer >> (bit_word_count - count));
+
+ // Reduce the number of bits in the bit buffer
+ stream->buffer <<= count;
+ stream->count = (stream->count - count);
+ }
+ else
+ {
+ BITCOUNT low_bit_count;
+
+ // Use the remaining bits in the bit buffer
+ assert(stream->count > 0 || stream->buffer == 0);
+ bits = (stream->buffer >> (bit_word_count - count));
+
+ // Compute the number of bits to be used from the next word
+ low_bit_count = count - stream->count;
+ stream->count = 0;
+ assert(low_bit_count > 0);
+
+ // Fill the bit buffer
+ assert(stream->count == 0);
+ GetBuffer(stream);
+ assert(stream->count >= low_bit_count);
+
+ // Use the new bits in the bit buffer
+ bits |= (stream->buffer >> (bit_word_count - low_bit_count));
+
+ // Reduce the number of bits in the bit buffer
+ if (low_bit_count < bit_word_count) {
+ stream->buffer <<= low_bit_count;
+ }
+ else {
+ stream->buffer = 0;
+ }
+ assert(low_bit_count <= stream->count);
+ stream->count = (stream->count - low_bit_count);
+ }
+
+finish:
+ // The bit count should never be negative or larger than the size of the bit buffer
+ //assert(0 <= stream->count && stream->count <= bit_word_count);
+ assert(stream->count <= bit_word_count);
+
+ // The unused bits in the bit buffer should all be zero
+ assert((stream->buffer & BitMask(bit_word_count - stream->count)) == 0);
+
+ // The unused bits in the result should all be zero
+ assert((bits & ~BitMask(count)) == 0);
+
+ return bits;
+}
+
+/*!
+ @brief Read more bits and append to an existing word of bits
+
+ Read the specified number of bits from the bitstream and append
+ the new bits to the right end of the word supplied as an argument.
+ This is a convenience routine that is used to accumulate bits that
+ may match a codeword.
+ */
+BITWORD AddBits(BITSTREAM *bitstream, BITWORD bits, BITCOUNT count)
+{
+ BITWORD new_bits = GetBits(bitstream, count);
+ assert((new_bits & ~BitMask(count)) == 0);
+
+ bits = (bits << count) | new_bits;
+
+ return bits;
+}
+
+/*!
+ @brief Write a longword (32 bits) to the stream
+ */
+CODEC_ERROR PutLong(BITSTREAM *stream, BITWORD longword)
+{
+ return PutBits(stream, longword, bit_word_count);
+}
+
+/*!
+ @brief Write the specified number of bits to the bitstream
+ */
+CODEC_ERROR PutBits(BITSTREAM *stream, BITWORD bits, BITCOUNT count)
+{
+ BITCOUNT unused_bit_count;
+
+ if (count == 0) {
+ return CODEC_ERROR_OKAY;
+ }
+
+ // Check that the unused portion of the input bits is empty
+ assert((bits & (BitMask(bit_word_count - count) << count)) == 0);
+
+ // Check that the number of input bits is valid
+ //assert(0 <= count && count <= bit_word_count);
+ assert(count <= bit_word_count);
+
+ // Check that the unused portion of the bit buffer is empty
+ unused_bit_count = bit_word_count - stream->count;
+ assert((stream->buffer & BitMask(unused_bit_count)) == 0);
+
+ // Is there room in the bit buffer for the new bits?
+ if (count <= unused_bit_count)
+ {
+ // Fill the remaining space in the bit buffer
+ stream->buffer |= (bits << (unused_bit_count - count));
+
+ // Reduce the number of unused bits in the bit buffer
+ stream->count += count;
+ }
+ else
+ {
+ // Any room in the bit buffer?
+ if (unused_bit_count > 0)
+ {
+ // Use the number of input bits that will fit in the bit buffer
+ stream->buffer |= (bits >> (count - unused_bit_count));
+
+ // Reduce the number of input bits by the amount used
+ count -= unused_bit_count;
+ //assert(count >= 0);
+ }
+
+ // Write the bit buffer to the byte stream
+ PutWord(stream->stream, stream->buffer );
+
+ // Insert the remaining input bits into the bit buffer
+ stream->buffer = (bits << (bit_word_count - count));
+
+ // Increment the number of bits in the bit buffer
+ stream->count = count;
+ }
+
+ return CODEC_ERROR_OKAY;
+}
+
+/*!
+ @brief Fill the internal bitstream buffer by reading a byte stream
+
+ @todo Need to modify this routine to return an error code if it cannot
+ read from the byte stream associated with the bitstream.
+ */
+CODEC_ERROR GetBuffer(BITSTREAM *bitstream)
+{
+ // Need to signal an underflow error?
+ if (! (bitstream != NULL && bitstream->stream != NULL)) {
+ assert(0);
+
+ if( bitstream->error == BITSTREAM_ERROR_UNDERFLOW )
+ return CODEC_ERROR_OUTOFMEMORY;
+ }
+
+ // The bit buffer should be empty
+ assert(bitstream->count == 0);
+
+ // Fill the bit buffer with a word from the byte stream
+ bitstream->buffer = Swap32(GetWord(bitstream->stream));
+ bitstream->count = bit_word_count;
+
+ return CODEC_ERROR_OKAY;
+}
+
+/*!
+ @brief Write the internal bitstream buffer to a byte stream
+
+ @todo Need to modify this routine to return an error code if it cannot
+ write to the byte stream associated with the bitstream.
+ */
+CODEC_ERROR PutBuffer(BITSTREAM *bitstream)
+{
+ //TODO: Need to signal an overflow error
+ assert(bitstream != NULL && bitstream->stream != NULL);
+
+ // The bit buffer should be full
+ assert(bitstream->count == bit_word_count);
+
+ // Write the bit buffer to the byte stream
+ PutWord(bitstream->stream, bitstream->buffer );
+
+ // Empty the bit buffer
+ bitstream->buffer = 0;
+ bitstream->count = 0;
+
+ return CODEC_ERROR_OKAY;
+}
+
+/*!
+ @brief Convert a bitstream error code to a codec error codec
+
+ The bitstream and byte stream modules use a separate enumeration
+ for error codes since these modules are used in other applications.
+ The bistream error code is embedded in a range of codec error codes
+ that are reserved for bitstream errors.
+ */
+CODEC_ERROR CodecErrorBitstream(BITSTREAM_ERROR error)
+{
+ uint32_t codec_error = CODEC_ERROR_BITSTREAM;
+ codec_error |= (uint32_t)error;
+ return (CODEC_ERROR)codec_error;
+}
+
+/*!
+ @brief Convert a bitstream error code into a codec error code
+
+ The bitstream and byte stream modules might be used in other
+ applications and have their own errors codes. This routine
+ embeds a bitstream error code into a codec error code. The
+ bitstream error code is carried in the low bits of the codec
+ error code.
+
+ @todo Eliminate separate error codes for bitstreams?
+ */
+CODEC_ERROR BitstreamCodecError(BITSTREAM *bitstream)
+{
+ assert(bitstream != NULL);
+ if (! (bitstream != NULL)) {
+ return CODEC_ERROR_NULLPTR;
+ }
+
+ return CodecErrorBitstream(bitstream->error);
+}
+
+/*!
+ @brief Read a block of bytes from the bitstream
+ */
+CODEC_ERROR GetByteArray(BITSTREAM *bitstream, uint8_t *array, size_t size)
+{
+ size_t i;
+
+ for (i = 0; i < size; i++)
+ {
+ array[i] = GetBits(bitstream, 8);
+ }
+
+ return CODEC_ERROR_OKAY;
+}
+
+/*!
+ @brief Write a block of bytes into the bitstream
+ */
+CODEC_ERROR PutByteArray(BITSTREAM *bitstream, const uint8_t *array, size_t size)
+{
+ size_t i;
+
+ for (i = 0; i < size; i++)
+ {
+ PutBits(bitstream, array[i], 8);
+ }
+
+ return CODEC_ERROR_OKAY;
+}
+
+/*!
+ @brief Write any bits in the buffer to the byte stream
+ */
+CODEC_ERROR FlushBitstream(BITSTREAM *bitstream)
+{
+ // Any bits remaining in the bit buffer?
+ if (bitstream->count > 0)
+ {
+ // Write the bit buffer to the output stream
+ PutBuffer(bitstream);
+ }
+
+ // Indicate that the bitstream buffer is empty
+ bitstream->count = 0;
+ bitstream->buffer = 0;
+
+ // Flush the output stream
+ FlushStream(bitstream->stream);
+
+ return CODEC_ERROR_OKAY;
+}
+
+/*!
+ @brief Get the current position in the byte stream
+
+ The current position in the byte stream associated with the
+ bitstream is returned. The intent is to allow the bitstream
+ (and the associated byte stream) to be restored to the saved
+ position.
+
+ @todo Need to record the state of the bitstream buffer and
+ bit count so that the entire bitstream state can be restored.
+ */
+size_t GetBitstreamPosition(BITSTREAM *bitstream)
+{
+ if (bitstream->count == bit_word_count) {
+ PutBuffer(bitstream);
+ }
+
+ // The bit buffer must be empty
+ assert(bitstream->count == 0);
+
+ // The bit buffer must be empty
+ return (bitstream->stream->byte_count);
+}
+
+/*!
+ @brief Rewind the bitstream
+
+ This routine rewinds the bitstream to the beginning of the byte stream
+ that has been attached to the bitstream. The byte stream is also reset.
+
+ If the byte stream could not be reset, then the internal bitstream state
+ is not reset.
+ */
+CODEC_ERROR RewindBitstream(BITSTREAM *bitstream)
+{
+ assert(bitstream != NULL);
+ if (! (bitstream != NULL)) {
+ return CODEC_ERROR_NULLPTR;
+ }
+
+ if (bitstream->stream != NULL) {
+ CODEC_ERROR error = RewindStream(bitstream->stream);
+ if (error != CODEC_ERROR_OKAY) {
+ return error;
+ }
+ }
+
+ // Reset the bitstream internal state
+ bitstream->buffer = 0;
+ bitstream->count = 0;
+ bitstream->error = BITSTREAM_ERROR_OKAY;
+
+ return CODEC_ERROR_OKAY;
+}
+
diff --git a/gpr/source/lib/vc5_common/bitstream.h b/gpr/source/lib/vc5_common/bitstream.h
new file mode 100755
index 0000000..85c2a25
--- /dev/null
+++ b/gpr/source/lib/vc5_common/bitstream.h
@@ -0,0 +1,135 @@
+/*! @file bitstream.h
+ *
+ * @brief Declaration of the bitstream data structure.
+ *
+ * @version 1.0.0
+ *
+ * (C) Copyright 2018 GoPro Inc (http://gopro.com/).
+ *
+ * Licensed under either:
+ * - Apache License, Version 2.0, http://www.apache.org/licenses/LICENSE-2.0
+ * - MIT license, http://opensource.org/licenses/MIT
+ * at your option.
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef BITSTREAM_H
+#define BITSTREAM_H
+
+/*!
+ @brief Bitstream error codes
+
+ The bitstream contains its own enumeration of error codes since this
+ module may be used in other applications.
+ */
+typedef enum _bitstream_error
+{
+ BITSTREAM_ERROR_OKAY = 0, //!< No error
+ BITSTREAM_ERROR_UNDERFLOW, //!< No unread bits remaining in the bitstream
+ BITSTREAM_ERROR_OVERFLOW, //!< No more bits can be written to the bitstream
+ BITSTREAM_ERROR_BADTAG, //!< Unexpected tag found in the bitstream
+
+ //TODO: Add more bitstream errors
+
+} BITSTREAM_ERROR;
+
+typedef uint32_t BITWORD; //!< Data type of the internal bitstream buffer
+
+typedef uint_fast8_t BITCOUNT; //!< Number of bits in the bitsteam buffer
+
+//! Maximum number of bits in a bit word
+static const BITCOUNT bit_word_count = 32;
+
+//! Maximum value of a bit word
+#define BIT_WORD_MAX 0xFFFFFFFF
+
+//! Sample offset stack depth
+#define MAX_SAMPLE_OFFSET_COUNT 8
+
+/*!
+ @brief Declaration of the bitstream data structure
+
+ The bitstream uses a byte stream to read bytes from a file or a buffer
+ in memory. This isolates that bitstream module from the type of byte
+ stream.
+ */
+typedef struct _bitstream
+{
+ BITSTREAM_ERROR error; //!< Error while processing the bitstream
+ struct _stream *stream; //!< Stream for reading bytes into the buffer
+ BITWORD buffer; //!< Internal buffer holds remaining bits
+ BITCOUNT count; //!< Number of bits remaining in the buffer
+
+#if VC5_ENABLED_PART(VC5_PART_SECTIONS)
+ /*!
+ The sample offset stack is used to record offsets to the start of nested
+ syntax structures. For example, a sample size segment is written into the
+ bitstream with a size of zero, since the size of the syntax element is not
+ known in advance. The offset to the sample size segment is pushed onto the
+ sample offset stack so that the location of the sample size segment can be
+ updated with the actual size of a syntax element after the complete element
+ is written into the bitstream.
+
+ This data structure is called the ChunkSizeOffset in the current codec
+ implementation.
+ */
+ uint32_t sample_offset_stack[MAX_SAMPLE_OFFSET_COUNT];
+
+ //! Number of entries in the sample offset stack
+ uint_fast8_t sample_offset_count;
+#endif
+
+} BITSTREAM;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+ BITWORD BitMask(int n);
+
+ CODEC_ERROR CodecErrorBitstream(BITSTREAM_ERROR error);
+
+ // Initialize a bitstream data structure
+ CODEC_ERROR InitBitstream(BITSTREAM *bitstream);
+
+ // Bind the bitstream to a byte stream
+ CODEC_ERROR AttachBitstream(struct _bitstream *bitstream, struct _stream *stream);
+
+ CODEC_ERROR ReleaseBitstream(BITSTREAM *stream);
+
+ BITWORD GetBits(BITSTREAM *stream, BITCOUNT count);
+
+ CODEC_ERROR PutBits(BITSTREAM *stream, BITWORD bits, BITCOUNT count);
+
+ BITWORD AddBits(BITSTREAM *stream, BITWORD bits, BITCOUNT count);
+
+ CODEC_ERROR GetBuffer(BITSTREAM *stream);
+
+ CODEC_ERROR PutBuffer(BITSTREAM *stream);
+
+ CODEC_ERROR PutLong(BITSTREAM *stream, BITWORD longword);
+
+ // Rewind the bitstream and the associated byte stream
+ CODEC_ERROR RewindBitstream(BITSTREAM *bitstream);
+
+ CODEC_ERROR BitstreamCodecError(BITSTREAM *bitstream);
+
+ // Return the current position of the bitstream pointer in the sample
+ size_t GetBitstreamPosition(BITSTREAM *stream);
+
+ CODEC_ERROR FlushBitstream(BITSTREAM *bitstream);
+
+ CODEC_ERROR GetByteArray(BITSTREAM *bitstream, uint8_t *array, size_t size);
+
+ CODEC_ERROR PutByteArray(BITSTREAM *bitstream, const uint8_t *block, size_t size);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // BITSTREAM_H
diff --git a/gpr/source/lib/vc5_common/codec.c b/gpr/source/lib/vc5_common/codec.c
new file mode 100755
index 0000000..2308f75
--- /dev/null
+++ b/gpr/source/lib/vc5_common/codec.c
@@ -0,0 +1,201 @@
+/*! @file codec.c
+ *
+ * @brief Implementation of functions that are common to the
+ * reference decoder and encoder
+ *
+ * @version 1.0.0
+ *
+ * (C) Copyright 2018 GoPro Inc (http://gopro.com/).
+ *
+ * Licensed under either:
+ * - Apache License, Version 2.0, http://www.apache.org/licenses/LICENSE-2.0
+ * - MIT license, http://opensource.org/licenses/MIT
+ * at your option.
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "common.h"
+
+/*!
+ @brief Initialize the codec state to before encoding or decoding the bitstream
+
+ Most of the codec state can be deduced from the decoding parameters.
+ For example, the dimensions of the first wavelet band in the bitstream
+ can be deduced from the encoded frame dimensions and the structure of
+ the wavelet tree.
+
+ The encoder will not insert parameters into the bitstream if the values
+ of the parameters are the same as in the codec state. This routine
+ should initialize the codec state with correct values if those values
+ can be inferred by the decoder, otherwise the use incorrect or default
+ values.
+
+ Note that the default encoded format is YUV 4:2:2, but this format is not
+ supported by the baseline profile encoder so the encoded format must be
+ explicitly written into the bitstream.
+
+ @todo Add more default values required to properly initialize the codec state.
+*/
+CODEC_ERROR PrepareCodecState(CODEC_STATE *codec)
+{
+ // Initialize the channel to channel number zero
+ codec->channel_number = 0;
+
+ // Initialize the subband number to subband zero (the lowpass band)
+ codec->subband_number = 0;
+
+ // The number of subbands per channel is a constant
+ codec->subband_count = 10;
+
+ // The default precision of pixels in the input frame is ten bits
+ codec->bits_per_component = 12;
+
+ // Force the encoder to insert the encoded dimensions into the bitstream
+ //codec->encoded.width = 0;
+ //codec->encoded.height = 0;
+
+ /*
+ TODO: Do not have to encode the display dimensions into the bitstream if the decoder
+ can infer the display dimensions from the encoded dimensions and format, but must
+ encode the display dimensions if the encoded dimensions include padding.
+
+ TODO: Check that this matches the current decoder implementation.
+ */
+
+ // Set the default precision for encoding lowpass band coefficients
+ codec->lowpass_precision = 16;
+
+ //TODO: Set more default values in the codec state
+
+ return CODEC_ERROR_OKAY;
+}
+
+/*!
+ @brief Reformat a segment value into the encoder version
+
+ The version of the encoder that created the clip may be encoded into every sample.
+
+ @todo Document the encoder version number format
+*/
+uint32_t EncoderVersion(uint32_t value)
+{
+ return (((value >> 12) & 0x0F) << 16) |
+ (((value >> 8) & 0x0F) << 8) |
+ ((value) & 0xFF);
+}
+
+/*!
+ @brief Unpack the version tag value into its components
+*/
+void SetCodecVersion(uint8_t version[3], uint16_t value)
+{
+ version[0] = (uint8_t)((value >> 12) & 0x0F); // Major version
+ version[1] = (uint8_t)((value >> 8) & 0x0F); // Minor version
+ version[2] = (uint8_t)(value & 0xFF); // Revision
+}
+
+#if VC5_ENABLED_PART(VC5_PART_IMAGE_FORMATS)
+/*!
+ @brief Return true if the image format is valid
+*/
+bool ValidImageFormat(IMAGE_FORMAT image_format)
+{
+ if (0 < image_format && image_format < IMAGE_FORMAT_COUNT) {
+ return true;
+ }
+ return false;
+}
+#endif
+
+/*!
+ @brief Unpack the tag value into the prescale table
+
+ The prescale table contains the prescale value for each wavelet in the
+ transform. The prescale value is a right shift that is applied to the
+ input data before the wavelet is computed.
+
+ The prescale table is used for all transforms and does not depend on the
+ channel number.
+*/
+CODEC_ERROR UpdatePrescaleTable(CODEC_STATE *codec, TAGWORD value)
+{
+ int wavelet_index;
+
+ for (wavelet_index = 0; wavelet_index < MAX_WAVELET_COUNT; wavelet_index++)
+ {
+ // Unpack the prescale value
+ int prescale_value = (value >> (14 - wavelet_index * 2)) & 0x03;
+ assert(0 <= prescale_value && prescale_value < UINT8_MAX);
+
+ // Store the prescale value in the codec state
+ codec->prescale_table[wavelet_index] = (uint_fast8_t)prescale_value;
+ }
+
+ return CODEC_ERROR_OKAY;
+}
+
+/*!
+ @brief Update the flags that describe the frame structure
+
+ The frame structure includes characteristics such as interlaced versus
+ progressive and top or bottom field first.
+*/
+CODEC_ERROR UpdateFrameStructureFlags(CODEC_STATE *codec, TAGWORD value)
+{
+ codec->progressive = !(value & IMAGE_STRUCTURE_INTERLACED);
+ codec->top_field_first = !(value & IMAGE_STRUCTURE_BOTTOM_FIELD_FIRST);
+ codec->frame_inverted = (value & IMAGE_STRUCTURE_BOTTOM_ROW_FIRST);
+
+ return CODEC_ERROR_OKAY;
+}
+
+/*!
+ @brief Initialize the codec state using the default constructor
+
+ This routine is like a default constructor in C++ as it guarantees that
+ the codec state is initialized to a know starting state with all pointers
+ set to NULL and all counters set to zero.
+
+ The routine @ref PrepareCodecState is used to set default values for the
+ codec state prior to decoding a sample.
+*/
+CODEC_ERROR InitCodecState(CODEC_STATE *state)
+{
+ // Clear the codec state
+ memset(state, 0, sizeof(CODEC_STATE));
+ return CODEC_ERROR_OKAY;
+}
+
+/*!
+ @brief Set the flags that determine the band coding
+
+ There can be up to 15 different codebooks as specified by the lower
+ four bigs in the band coding flags. Use the default codebook if the
+ active codebook is zero.
+
+ The baseline profile does not allow difference coding or alternative
+ codebooks.
+*/
+CODEC_ERROR SetBandCoding(CODEC_STATE *codec, TAGWORD value)
+{
+ (void) codec;
+ return CODEC_ERROR_OKAY;
+}
+
+/*!
+ @brief Return true if the specified part is enabled at runtime
+
+ This predicate is used to test whether a specific part in the VC-5 standard is
+ enabled at runtime by this codec implementation.
+
+*/
+bool IsPartEnabled(ENABLED_PARTS enabled_parts, int part_number)
+{
+ return ((enabled_parts & VC5_PART_MASK(part_number)) != 0);
+}
+
diff --git a/gpr/source/lib/vc5_common/codec.h b/gpr/source/lib/vc5_common/codec.h
new file mode 100755
index 0000000..6763091
--- /dev/null
+++ b/gpr/source/lib/vc5_common/codec.h
@@ -0,0 +1,315 @@
+/*! @file codec.h
+ *
+ * @brief State of the decoder while decoding a sample. The codec state
+ * contains information about the current state of the decoding process.
+ * The codec state is updated as the bitstream is decoded.
+ *
+ * @version 1.0.0
+ *
+ * (C) Copyright 2018 GoPro Inc (http://gopro.com/).
+ *
+ * Licensed under either:
+ * - Apache License, Version 2.0, http://www.apache.org/licenses/LICENSE-2.0
+ * - MIT license, http://opensource.org/licenses/MIT
+ * at your option.
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef CODEC_H
+#define CODEC_H
+
+#include "syntax.h"
+
+static const SEGMENT StartMarkerSegment = ((0x56 << 24) | (0x43 << 16) | (0x2D << 8) | 0x35);
+
+/*!
+ @brief Tags that define elements in the bitstream
+
+ All syntax elements in the encoded bitstream begin with a 16-bit tag that
+ specifies the type of element. The 16-bit tag is followed by a 16-bit value,
+ forming a tag-value pair.
+
+ If the tag is a negative number, then the actual tag is the negation of the
+ tag value and the negative sign indicates that the tag and its value are an
+ optional tag value pair. If the tag is a positive value, then the segment
+ is required. A decoder must be able to decode all required tag-value pairs,
+ but can skip tag-value pairs that are optional.
+
+ In a VC-5 Part 1 bitstream, the image width and height are an upper bound on the
+ dimensions of each channel represented in the bitstream. In a VC-5 Part 3 bitstream,
+ the image width and height are the actual dimensions of the image represented in the
+ bitstream. The width and height of the image and each pattern element is sufficient
+ to determine the width and height of each component array.
+
+ A range of tags is reserved for chunks and the value is the size of the chunk.
+*/
+typedef enum _codec_tag
+{
+ CODEC_TAG_ImageWidth = 20, //!< Upper bound on the width of the image
+ CODEC_TAG_ImageHeight = 21, //!< Upper bound on the height of the image
+ CODEC_TAG_BitsPerComponent = 101, //!< Number of bits in the source image
+ CODEC_TAG_ChannelCount = 12, //!< Number of channels in the transform
+ CODEC_TAG_SubbandCount = 14, //!< Number of encoded subbands
+ CODEC_TAG_ChannelNumber = 62, //!< Channel number
+ CODEC_TAG_SubbandNumber = 48, //!< Subband number of this wavelet band
+ CODEC_TAG_LowpassPrecision = 35, //!< Number of bits per lowpass coefficient
+ CODEC_TAG_Quantization = 53, //!< Quantization applied to band
+ CODEC_TAG_PrescaleShift = 109, //!< Packed prescale shift for each wavelet level
+ CODEC_TAG_ChannelWidth = 104, //!< Width of the next channel in the bitstream
+ CODEC_TAG_ChannelHeight = 105, //!< Height of the next channel in the bitstream
+
+ CODEC_TAG_LargeCodeblock = 0x6000, //!< Large chunk that contains a codeblock
+
+ CODEC_TAG_SMALL_CHUNK = 0x4000, //!< Small chunk with a 16-bit payload size (in segments)
+ CODEC_TAG_LARGE_CHUNK = 0x2000, //!< Large chunk with a 24-bit payload size (in segments)
+
+ //! Mask for detecting the tag for a small or large chunk (including codeblocks)
+ CODEC_TAG_CHUNK_MASK = (CODEC_TAG_SMALL_CHUNK | CODEC_TAG_LARGE_CHUNK),
+
+#if VC5_ENABLED_PART(VC5_PART_IMAGE_FORMATS)
+ // Codec tags used by VC-5 Part 3 bitstreams
+ CODEC_TAG_PatternWidth = 106, //!< Number of samples per row in each pattern element
+ CODEC_TAG_PatternHeight = 107, //!< Number of rows of samples in each pattern element
+ CODEC_TAG_ComponentsPerSample = 108, //!< Number of components in each sample in the pattern element
+ CODEC_TAG_ImageFormat = 84, //!< Format of the image represented by the bitstream
+ CODEC_TAG_MaxBitsPerComponent = 102, //!< Upper bound on the number of bits per component
+
+ // Small chunk elements defined by VC-5 Part 3
+ CODEC_TAG_VendorSpecificData = 0x4000, //!< Small chunk containing vendor-specific data
+ CODEC_TAG_InversePermutation = 0x4001, //!< Small chunk containing the inverse component permutation
+ CODEC_TAG_InverseTransform = 0x4002, //!< Small chunk containing the inverse component transform (8 bit representation)
+ CODEC_TAG_InverseTransform16 = 0x4003, //!< Small chunk containing the inverse component transform (16 bit representation)
+ CODEC_TAG_UniqueImageIdentifier = 0x4004, //!< Small chunk containing the identifier and sequence number for the image
+#endif
+
+#if VC5_ENABLED_PART(VC5_PART_LAYERS)
+ CODEC_TAG_LayerCount = 120, //!< Number of layers in the bitstream
+ CODEC_TAG_LayerNumber = 121, //!< Number of the next layer in the bitstream
+ CODEC_TAG_LayerPattern = 122, //!< Mask indicating the use cases in the bitstream
+#endif
+
+#if VC5_ENABLED_PART(VC5_PART_SECTIONS)
+ CODEC_TAG_ImageCount = 130, //!< Number of image bitstream sections in the bitstream
+ CODEC_TAG_ImageNumber = 131, //!< Unique number assigned to an image bitstream section
+
+ // Predefined codec tags for structures in the VC-5 bitstream
+ CODEC_TAG_ImageSectionTag = 0x2700, //!< Section that contains a single image
+ CODEC_TAG_HeaderSectionTag = 0x2500, //!< Section that contains the bitstream header
+ CODEC_TAG_LayerSectionTag = 0x2600, //!< Section that contains a single layer
+ CODEC_TAG_ChannelSectionTag = 0x2400, //!< Section that contains a single channel
+ CODEC_TAG_WaveletSectionTag = 0x2100, //!< Section that contains all subbands for one wavelet
+ CODEC_TAG_SubbandSectionTag = 0x2000, //!< Section that contains a single subband
+#endif
+
+#if VC5_ENABLED_PART(VC5_PART_METADATA)
+ // Small and large chunks of metadata
+ CODEC_TAG_SmallMetadata = 0x4010, //!< Small chunk containing metadata tuples (VC-5 Part 7)
+ CODEC_TAG_LargeMetadata = 0x6100, //!< Large chunk containing metadata tuples (VC-5 Part 7)
+#endif
+
+} CODEC_TAG;
+
+#if VC5_ENABLED_PART(VC5_PART_IMAGE_FORMATS)
+/*!
+ @brief Format of the encoded sample
+
+ The VC-5 Part 3 can support four bitstream representations of the encoded image.
+
+ The image format must be specified for any VC-5 Part 3 bitstream.
+*/
+typedef enum _image_format
+{
+ IMAGE_FORMAT_UNKNOWN = 0, //!< The image format has not been specified
+ IMAGE_FORMAT_RAW = 4, //!< RAW image format (special case of CFA)
+
+ /***** Add new encoded formats above this line *****/
+
+ IMAGE_FORMAT_COUNT, //!< Number of image formats that have been defined
+
+} IMAGE_FORMAT;
+
+#endif
+
+
+/*!
+ @brief Band encoding method
+
+ Several different schemes have been tried for entropy coding the highpass bands.
+ The baseline profile only supports the run lengths encoding method.
+
+ The run lengths encoding method using a Huffman code to encode runs of zeros and
+ highpass coefficient magnitudes (unsigned). Runs of zeros can extend across row
+ boundaries, so large sections of a highpass band that are mostly zeros can be
+ encoded very efficiently.
+
+ @todo Need to cull this list as many band encoding methods are no longer supported.
+*/
+enum band_encoding {
+ BAND_ENCODING_ZEROTREE = 1,
+ BAND_ENCODING_CODEBOOK,
+ BAND_ENCODING_RUNLENGTHS,
+ BAND_ENCODING_16BIT,
+ BAND_ENCODING_LOSSLESS
+};
+
+/*!
+ The codec state contains information about the decoding process obtained
+ as a sample is decoded. The information is transient and is only used
+ while decoding a sample. The decoder data structure contains information
+ that should persist from onen sample to the next.
+
+ The codec state is initialized using information in the decoder data structure
+ at the start of decoding a sample.
+
+ The intent is that the encoder can operate the same state machine during encoding
+ and any information available in the state machine does not have to be encoded into
+ the sample as it is assumed that the decoder can and will derive the same information.
+ For example, the dimensions of the first subband can be computed from the encoded
+ dimensions and the number of wavelet levels, so it is not necessary to encode this
+ information. Likewise, after the last band in a wavelet is decoded the dimensions
+ of the bands in the wavelet at the next level can be deduced and it is not necessary
+ to encode this information into the sample.
+*/
+typedef struct _codec_state
+{
+ uint16_t channel_number; //!< Index of current channel being decoded
+ DIMENSION channel_width; //!< Width of the next channel in the bitstream
+ DIMENSION channel_height; //!< Height of the next channel in the bitstream
+ PRECISION bits_per_component; //!< Precision of the component array (in bits)
+
+ uint16_t subband_number; //!< Index of current subband being decoded
+
+#if VC5_ENABLED_PART(VC5_PART_IMAGE_FORMATS)
+ IMAGE_FORMAT image_format; //!< Format of the image represented by the bitstream
+ DIMENSION pattern_width; //!< Width of the pattern elements (in samples)
+ DIMENSION pattern_height; //!< Height of the pattern elements (in rows)
+ DIMENSION components_per_sample; //!< Number of components in each sample in the pattern element
+ PRECISION max_bits_per_component; //!< Maximum number of bits for each value in the component arrays
+#endif
+
+#if VC5_ENABLED_PART(VC5_PART_LAYERS)
+ uint_least8_t layer_count;
+#endif
+
+ uint_least8_t channel_count; //!< Number of channels in the current layer
+ uint_least8_t wavelet_count; //!< Number of wavelets in the current layer
+ uint_least8_t subband_count; //!< Number of suibbands in the current layer
+
+ //! The channel position is used for skipping subbands and jumping to particular channels
+ size_t channel_position;
+
+ uint32_t encoded_format; //!< Internal encoded representation
+ uint32_t encoded_quality; //!< Quality setting of the encoded video
+
+ uint32_t decoded_subband_mask; //!< Indicates which subbands have been decoded
+
+ bool progressive; //!< True if the encoded frame is progressive
+
+ bool top_field_first; //!< True if the top field is encoded first
+
+ bool frame_inverted; //!< True if the frame is encoded upside down
+
+ uint_least8_t group_length; //!< Number of frames in a group of pictures (GOP)
+
+ //! Indicates that enough of the sample has been read to allow decoding the sample
+ bool end_of_sample;
+
+ //! Indicates that the layer has been decoded
+ bool end_of_layer;
+
+ //! Most recent tag-value pair was a header parameter
+ bool header;
+
+ //! Most recent syntax element was a codeblock (large chunk element)
+ bool codeblock;
+
+ //! Parameters of the most recently decoded subband
+ struct
+ {
+ //DIMENSION width; //!< Width of the decoded band
+ //DIMENSION height; //!< Height of the decoded band
+ uint_least8_t subband; //!< Subband index
+ //uint_least8_t encoding; //!< Band encoding method
+ uint16_t quantization; //!< Quantization parameter
+
+ } band; //!< Information about the current highpass band
+
+ DIMENSION image_width; //!< Upper bound on the channel width
+ DIMENSION image_height; //!< Upper bound on the channel height
+
+ PRECISION lowpass_precision; //!< Number of bits per lowpass coefficient
+
+ /*!
+ @brief Table of prescale shifts applied before computing each wavelet transform
+
+ The prescale shift was applied by the encoder to each input to the forward
+ wavelet transform. The table of prescale values is indexed by the same
+ index used for the wavelets in the transform.
+ */
+ //uint_fast8_t prescale_table[MAX_WAVELET_COUNT];
+ PRESCALE prescale_table[MAX_WAVELET_COUNT];
+
+ //! Picture aspect ratio read from the encoded sample
+ struct _picture_aspect_ratio
+ {
+ uint_least16_t x; //!< Relative width of the picture
+ uint_least16_t y; //!< Relative height of the picture
+
+ } picture_aspect_ratio; //!< Picture aspect ratio read from the sample
+
+#if VC5_ENABLED_PART(VC5_PART_LAYERS)
+ uint32_t interlaced_flags;
+ uint32_t protection_flags;
+
+ //!< Parameters of the current layer
+ struct
+ {
+ int width; //!< Width of the current layer
+ int height; //!< Height of the current layer
+
+ } layer; //!< Information about the encoded layer from the sample
+
+#endif
+
+#if VC5_ENABLED_PART(VC5_PART_SECTIONS)
+ int section_number; //!< Number of the most recent section encountered in the bitstream
+ int section_length; //!< Length of the most recent section element payload (in segments)
+#endif
+
+} CODEC_STATE;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+ // Initialize the codec state
+ CODEC_ERROR PrepareCodecState(CODEC_STATE *codec);
+
+ uint32_t EncoderVersion(uint32_t value);
+
+ uint32_t RepackedEncoderVersion(uint32_t value);
+
+ void SetCodecVersion(uint8_t version[3], uint16_t value);
+
+ CODEC_ERROR UpdatePrescaleTable(CODEC_STATE *codec, TAGWORD value);
+
+ CODEC_ERROR UpdateSampleFlags(CODEC_STATE *codec, TAGWORD value);
+
+ CODEC_ERROR UpdateCodecFlags(CODEC_STATE *codec, TAGWORD value);
+
+ CODEC_ERROR UpdateFrameStructureFlags(CODEC_STATE *codec, TAGWORD value);
+
+ CODEC_ERROR SetBandCoding(CODEC_STATE *codec, TAGWORD value);
+
+ bool IsPartEnabled(ENABLED_PARTS enabled_parts, int part_number);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // CODEC_H
diff --git a/gpr/source/lib/vc5_common/codeset.h b/gpr/source/lib/vc5_common/codeset.h
new file mode 100755
index 0000000..e220239
--- /dev/null
+++ b/gpr/source/lib/vc5_common/codeset.h
@@ -0,0 +1,44 @@
+/*! @file codeset.h
+ *
+ * @brief The codeset data structure includes the codebook and flags that
+ * indicate how to use the codebook. The codeset may also include tables
+ * that are derived from the codebook to facilite encoding and decoding.
+ *
+ * @version 1.0.0
+ *
+ * (C) Copyright 2018 GoPro Inc (http://gopro.com/).
+ *
+ * Licensed under either:
+ * - Apache License, Version 2.0, http://www.apache.org/licenses/LICENSE-2.0
+ * - MIT license, http://opensource.org/licenses/MIT
+ * at your option.
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef CODESET_H
+#define CODESET_H
+
+/*!
+ @brief Codeset flags that determine how the codebook is used for encoding
+
+ The codeset flags determine how the codebook in the codeset is used to
+ compute the tables for encoding coefficient magnitudes and runs of zeros.
+
+ The companding curve is applied to the quantized coefficients before the
+ values are entropy coded to fit the coefficient magnitudes into the range
+ of magnitudes provided by the codebook. The companding curve is applied
+ when the encoding table for coefficient magnitudes is computed.
+*/
+typedef enum _codeset_flags
+{
+ CODESET_FLAGS_COMPANDING_NONE = 0x0002, //!< Do not apply a companding curve
+ CODESET_FLAGS_COMPANDING_CUBIC = 0x0004, //!< Apply a cubic companding curve
+
+} CODESET_FLAGS;
+
+#endif // CODESET_H
diff --git a/gpr/source/lib/vc5_common/common.h b/gpr/source/lib/vc5_common/common.h
new file mode 100755
index 0000000..c0ff501
--- /dev/null
+++ b/gpr/source/lib/vc5_common/common.h
@@ -0,0 +1,53 @@
+/*! @file common.h
+ *
+ * @brief This file includes all of the header files that are used by
+ * the encoder and decoder. Including a single header file in all
+ * reference encoder and decoder source files ensures that all
+ * modules see the same header files in the same order.
+ *
+ * @version 1.0.0
+ *
+ * (C) Copyright 2018 GoPro Inc (http://gopro.com/).
+ *
+ * Licensed under either:
+ * - Apache License, Version 2.0, http://www.apache.org/licenses/LICENSE-2.0
+ * - MIT license, http://opensource.org/licenses/MIT
+ * at your option.
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef COMMON_H
+#define COMMON_H
+
+#include "gpr_platform.h"
+#include "gpr_allocator.h"
+#include "gpr_buffer.h"
+#include "gpr_rgb_buffer.h"
+
+#include "stdc_includes.h"
+
+#include "log.h"
+#include "types.h"
+#include "timer.h"
+#include "config.h"
+#include "macros.h"
+#include "error.h"
+#include "pixel.h"
+#include "image.h"
+#include "logcurve.h"
+#include "wavelet.h"
+#include "bitstream.h"
+#include "stream.h"
+#include "companding.h"
+#include "syntax.h"
+#include "codec.h"
+#include "codeset.h"
+#include "utilities.h"
+#include "unique.h"
+
+#endif // COMMON_H
diff --git a/gpr/source/lib/vc5_common/companding.c b/gpr/source/lib/vc5_common/companding.c
new file mode 100755
index 0000000..00b0fb5
--- /dev/null
+++ b/gpr/source/lib/vc5_common/companding.c
@@ -0,0 +1,259 @@
+/*! @file companding.c
+ *
+ * @brief Implementation of the routines for computing the companding curves
+ * that is applied to the quantized coefficient magnitudes.
+ *
+ * @version 1.0.0
+ *
+ * (C) Copyright 2018 GoPro Inc (http://gopro.com/).
+ *
+ * Licensed under either:
+ * - Apache License, Version 2.0, http://www.apache.org/licenses/LICENSE-2.0
+ * - MIT license, http://opensource.org/licenses/MIT
+ * at your option.
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "common.h"
+
+//TODO: Change the companding parameter into a global constant
+
+#ifndef COMPANDING
+#define COMPANDING 1
+#define COMPANDING_MORE (54) // Zero means no companding (54 is a good value)
+#endif
+
+
+/*!
+ @brief Maximum coefficient magnitude in the codebook
+
+ @todo Need to calculate the maximum value from the codebook
+*/
+const int maximum_codebook_value = 255;
+
+
+/*!
+ @brief Apply the default companding curve to the specified value
+
+ Note that this companding curve has been superceeded by the cubic curve.
+*/
+int32_t CompandedValue(int32_t value)
+{
+ const int midpoint_rounding = 2;
+
+ int32_t magnitude = absolute(value);
+
+#if COMPANDING
+ if (magnitude >= 40)
+ {
+ magnitude -= 40;
+ magnitude += midpoint_rounding;
+ magnitude >>= 2;
+ magnitude += 40;
+
+ #if COMPANDING_MORE
+ if (magnitude >= COMPANDING_MORE)
+ {
+ magnitude -= COMPANDING_MORE;
+ magnitude += midpoint_rounding;
+ magnitude >>= 2;
+ magnitude += COMPANDING_MORE;
+ }
+#endif
+ }
+#endif
+
+ // Restore the sign to the companded value
+ return ((value >= 0) ? magnitude : neg(magnitude));
+}
+
+/*!
+ @brief Return the parameter that controls the companding curve
+
+ This parameter does not apply if the cubic companding curve is used.
+*/
+uint32_t CompandingParameter()
+{
+ return COMPANDING_MORE;
+}
+
+/*!
+ @brief Compute a table of values for the cubic companding curve
+
+ The companding curve is f(x) = x + (x ^ 3 / (255 ^ 3)) * 768
+ so the range of coefficient magnitudes from 0 to 255 becomess 0 to 1023.
+*/
+CODEC_ERROR ComputeCubicTable(int16_t cubic_table[], int cubic_table_length, int16_t maximum_value)
+{
+ size_t cubic_table_size = cubic_table_length * sizeof(cubic_table[0]);
+ int last_cubic_table_index = cubic_table_length - 2;
+ int16_t last_magnitude;
+ int16_t index;
+
+ // Clear the cubic table
+ memset(cubic_table, 0, cubic_table_size);
+
+ for (index = 1; index <= maximum_value; index++)
+ {
+ double cubic = index;
+
+ int magnitude = index;
+
+ cubic *= index;
+ cubic *= index;
+ cubic *= 768;
+ //cubic /= 256*256*256;
+ cubic /= 255*255*255;
+
+ magnitude += (int)cubic;
+
+ //if (mag > 1023) mag = 1023;
+ if (magnitude > last_cubic_table_index) {
+ magnitude = last_cubic_table_index;
+ }
+
+ cubic_table[magnitude] = index;
+ }
+
+ // Fill unused entries in the cubic table
+ last_magnitude = 0;
+ for (index = 0; index < cubic_table_length; index++)
+ {
+ if (cubic_table[index])
+ {
+ last_magnitude = cubic_table[index];
+ }
+ else
+ {
+ cubic_table[index] = last_magnitude;
+ }
+ }
+
+ return CODEC_ERROR_OKAY;
+}
+
+/*!
+ @brief Invert the companding curve applied during encoding
+*/
+int32_t UncompandedValue(int32_t value)
+{
+#if 1 //CUBIC_COMPANDING
+ double cubic;
+ int32_t magnitude = absolute(value);
+
+ cubic = magnitude;
+ cubic *= magnitude;
+ cubic *= magnitude;
+ cubic *= 768;
+ //cubic /= 256*256*256;
+ cubic /= 255*255*255;
+
+ magnitude += (int32_t)cubic;
+
+ // Restore the sign
+ value = ((value < 0) ? neg(magnitude) : magnitude);
+#else
+ if (40 <= value && value < 264)
+ {
+#if COMPANDING_MORE
+ if (value >= COMPANDING_MORE)
+ {
+ value -= COMPANDING_MORE;
+ value <<= 2;
+ value += COMPANDING_MORE;
+ }
+#endif
+ value -= 40;
+ value <<= 2;
+ value += 40;
+ }
+ else if (value <= -40)
+ {
+ // Apply the inverse companding formula to the absolute value
+ value = -value;
+
+#if COMPANDING_MORE
+ if (value >= COMPANDING_MORE)
+ {
+ value -= COMPANDING_MORE;
+ value <<= 2;
+ value += COMPANDING_MORE;
+ }
+#endif
+ value -= 40;
+ value <<= 2;
+ value += 40;
+
+ // Restore the sign
+ value = -value;
+ }
+#endif
+
+ return value;
+}
+
+/*!
+ @brief Invert the companding curve applied to a pixel
+*/
+PIXEL UncompandedPixel(PIXEL value)
+{
+#if 1 //CUBIC_COMPANDING
+ double cubic;
+ int32_t magnitude = absolute(value);
+
+ cubic = magnitude;
+ cubic *= magnitude;
+ cubic *= magnitude;
+ cubic *= 768;
+ //cubic /= 256*256*256;
+ cubic /= 255*255*255;
+
+ magnitude += (int32_t)cubic;
+
+ // Restore the sign
+ value = ClampPixel((value < 0) ? neg(magnitude) : magnitude);
+#else
+ if (40 <= value && value < 264)
+ {
+#if COMPANDING_MORE
+ if (value >= COMPANDING_MORE)
+ {
+ value -= COMPANDING_MORE;
+ value <<= 2;
+ value += COMPANDING_MORE;
+ }
+#endif
+ value -= 40;
+ value <<= 2;
+ value += 40;
+ }
+ else if (value <= -40)
+ {
+ // Apply the inverse companding formula to the absolute value
+ value = neg(value);
+
+#if COMPANDING_MORE
+ if (value >= COMPANDING_MORE)
+ {
+ value -= COMPANDING_MORE;
+ value <<= 2;
+ value += COMPANDING_MORE;
+ }
+#endif
+ value -= 40;
+ value <<= 2;
+ value += 40;
+
+ // Restore the sign
+ value = neg(value);
+ }
+#endif
+
+ return value;
+}
+
diff --git a/gpr/source/lib/vc5_common/companding.h b/gpr/source/lib/vc5_common/companding.h
new file mode 100755
index 0000000..5931e73
--- /dev/null
+++ b/gpr/source/lib/vc5_common/companding.h
@@ -0,0 +1,46 @@
+/*! @file companding.h
+ *
+ * @brief Declaration of the routines for computing the companding curves
+ * that is applied to the quantized coefficient magnitudes.
+ *
+ * @version 1.0.0
+ *
+ * (C) Copyright 2018 GoPro Inc (http://gopro.com/).
+ *
+ * Licensed under either:
+ * - Apache License, Version 2.0, http://www.apache.org/licenses/LICENSE-2.0
+ * - MIT license, http://opensource.org/licenses/MIT
+ * at your option.
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef COMPANDING_H
+#define COMPANDING_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+ int32_t CompandedValue(int32_t value);
+
+ uint32_t CompandingParameter(void);
+
+ CODEC_ERROR ComputeCubicTable(int16_t cubic_table[], int cubic_table_length, int16_t maximum_value);
+
+ // Invert the companding curve applied to a quantized coefficient magnitude (for debugging)
+ int32_t UncompandedValue(int32_t value);
+
+ PIXEL UncompandedPixel(PIXEL value);
+
+ CODEC_ERROR InvertCompanding(PIXEL *image, DIMENSION width, DIMENSION height, DIMENSION pitch);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // COMPANDING_H
diff --git a/gpr/source/lib/vc5_common/config.h b/gpr/source/lib/vc5_common/config.h
new file mode 100755
index 0000000..5169510
--- /dev/null
+++ b/gpr/source/lib/vc5_common/config.h
@@ -0,0 +1,87 @@
+/*! @file config.h
+ *
+ * @brief Parameters that control the configuration of the codec.
+ *
+ * @version 1.0.0
+ *
+ * (C) Copyright 2018 GoPro Inc (http://gopro.com/).
+ *
+ * Licensed under either:
+ * - Apache License, Version 2.0, http://www.apache.org/licenses/LICENSE-2.0
+ * - MIT license, http://opensource.org/licenses/MIT
+ * at your option.
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef CONFIG_H
+#define CONFIG_H
+
+// Maximum number of layers
+#define MAX_LAYER_COUNT 10
+
+// Maximum number of color channels
+#define MAX_CHANNEL_COUNT 4
+//const int MAX_CHANNEL_COUNT = 4;
+
+// Maximum number of wavelets per channel
+#define MAX_WAVELET_COUNT 3
+//const int MAX_WAVELET_COUNT = 3;
+
+// Maximum number of bands per wavelet
+#define MAX_BAND_COUNT 4
+//const int MAX_BAND_COUNT = 4;
+
+// Maximum number of subbands in all wavelets (including the lowpass band in the first wavelet)
+#define MAX_SUBBAND_COUNT 10
+
+// The number of prescale values that are encoded into the bitstream
+#define MAX_PRESCALE_COUNT 8
+
+//TODO: The maximum number of channels and wavelets depends on the profile
+
+//! Internal precision of the intermediate results after unpacking
+static const int default_internal_precision = 12;
+
+//TODO: Change the global variable from internal_precision to encoded_precision?
+
+// Definitions of VC-5 parts
+#define VC5_PART_ELEMENTARY 1
+#define VC5_PART_CONFORMANCE 2 // Conformance does not affect what capabilities are included
+#define VC5_PART_IMAGE_FORMATS 3
+#define VC5_PART_COLOR_SAMPLING 4
+#define VC5_PART_LAYERS 5
+#define VC5_PART_SECTIONS 6
+#define VC5_PART_METADATA 7
+
+// Convert a part number into a part mask
+#define VC5_PART_MASK(n) (1 << ((n)-1))
+
+// Define the parts supported by this codec implementation
+#define VC5_ENABLED_PARTS (VC5_PART_MASK(VC5_PART_ELEMENTARY) | \
+ VC5_PART_MASK(VC5_PART_IMAGE_FORMATS) | \
+ VC5_PART_MASK(VC5_PART_COLOR_SAMPLING) | \
+ VC5_PART_MASK(VC5_PART_SECTIONS))
+
+// Compile code if any of the parts in the specified mask are supported
+#define VC5_ENABLED_MASK(m) ((VC5_ENABLED_PARTS & (m)) != 0)
+
+// Macro for testing support for a specific part of the VC-5 standard
+#define VC5_ENABLED_PART(n) (VC5_ENABLED_MASK(VC5_PART_MASK(n)))
+
+
+#if VC5_ENABLED_PART(VC5_PART_LAYERS)
+
+// Maximum number of layers supported by the reference codec
+#define MAX_LAYER_COUNT 10
+
+#endif
+
+//! Number of rows of intermediate horizontal transform results
+#define ROW_BUFFER_COUNT 6
+
+#endif // CONFIG_H
diff --git a/gpr/source/lib/vc5_common/error.h b/gpr/source/lib/vc5_common/error.h
new file mode 100755
index 0000000..fbb1573
--- /dev/null
+++ b/gpr/source/lib/vc5_common/error.h
@@ -0,0 +1,88 @@
+/*! @file config.h
+ *
+ * @brief Definitions of the error codes reported by this codec implementation
+ *
+ * @version 1.0.0
+ *
+ * (C) Copyright 2018 GoPro Inc (http://gopro.com/).
+ *
+ * Licensed under either:
+ * - Apache License, Version 2.0, http://www.apache.org/licenses/LICENSE-2.0
+ * - MIT license, http://opensource.org/licenses/MIT
+ * at your option.
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ERROR_H
+#define ERROR_H
+
+/*!
+ @brief Codec error codes
+*/
+typedef enum _codec_error
+{
+ CODEC_ERROR_OKAY = 0, //!< No error
+ CODEC_ERROR_UNEXPECTED, //!< Encountered an unexpected condition
+ CODEC_ERROR_OUTOFMEMORY, //!< Memory allocation failed
+ CODEC_ERROR_UNIMPLEMENTED, //!< Function has not been implemented
+ CODEC_ERROR_NULLPTR, //!< Data structure or argument pointer was null
+ CODEC_ERROR_BITSTREAM_SYNTAX, //!< Error in the sequence of tag value pairs
+ CODEC_ERROR_IMAGE_DIMENSIONS, //!< Wrong or unknown image dimensions
+ CODEC_ERROR_INVALID_TAG, //!< Found a tag that should not be present
+ CODEC_ERROR_INVALID_BAND, //!< Wavelet band index is out of range
+ CODEC_ERROR_DECODING_SUBBAND, //!< Error decoding a wavetet subband
+ CODEC_ERROR_NOTFOUND, //!< Did not find a value codeword
+ CODEC_ERROR_BAND_END_MARKER, //!< Could not find special codeword after end of band
+ CODEC_ERROR_BAND_END_TRAILER, //!< Could not find start of highpass band trailer
+ CODEC_ERROR_PIXEL_FORMAT, //!< Unsupported pixel format
+ CODEC_ERROR_INVALID_MARKER, //!< Bitstream marker was not found in the codebook
+ CODEC_ERROR_FILE_GET_POSITION, //!< Could not get position of the file stream
+ CODEC_ERROR_FILE_SEEK, //!< Could not seek to a position in a file stream
+ CODEC_ERROR_FILE_READ, //!< Read from a file stream failed
+ CODEC_ERROR_FILE_WRITE, //!< Write to a file stream failed
+ CODEC_ERROR_CHANNEL_SIZE_TABLE, //!< Could not write the channel size table
+ CODEC_ERROR_UNSUPPORTED_FORMAT, //!< Pixel or encoded format is not supported
+ CODEC_ERROR_MISSING_START_MARKER, //!< Bitstream does not begin with the start marker
+ CODEC_ERROR_DUPLICATE_HEADER_PARAMETER, //!< Header parameter occurs more than once
+ CODEC_ERROR_REQUIRED_PARAMETER, //!< Optional tag-value pair for a required parameter
+ CODEC_ERROR_LOWPASS_PRECISION, //!< Number of bits per lowpass coefficient out of range
+ CODEC_ERROR_LOWPASS_VALUE, //!< Lowpass coefficient value is out of range
+ CODEC_ERROR_IMAGE_TYPE, //!< Could not determine the characteristics of the input image
+ CODEC_ERROR_BAD_IMAGE_FORMAT, //!< Bad image format (VC-5 Part 3 only)
+ CODEC_ERROR_PATTERN_DIMENSIONS, //!< Bad pattern dimensions (VC-5 Part 3 only)
+ CODEC_ERROR_ENABLED_PARTS, //!< Incorrect enabled parts of the VC-5 standard
+ CODEC_ERROR_SYNTAX_ERROR, //!< Unspecified error in the bitstream syntax
+ CODEC_ERROR_UMID_LABEL, //!< Incorrect UMID label
+ CODEC_ERROR_BAD_SECTION_TAG, //!< The specified tag does not correspond to a section header
+
+
+ /***** Reserve a block of error codes for the bitstream *****/
+
+ CODEC_ERROR_BITSTREAM = (1 << 10), //!< Block of bitstream error codes
+
+
+ /***** Reserve a block of error codes for the calling application *****/
+
+ CODEC_ERROR_APPLICATION = (16 << 10), //!< Block of error codes for the application
+ CODEC_ERROR_MISSING_ARGUMENT, //!< Program did not have enough arguments
+ CODEC_ERROR_BAD_ARGUMENT, //!< Invalid value for one of the arguments
+ CODEC_ERROR_OPEN_FILE_FAILED, //!< Could not open the file for reading
+ CODEC_ERROR_CREATE_FILE_FAILED, //!< Could not open the file for writing
+ CODEC_ERROR_UNSUPPORTED_FILE_TYPE, //!< The output file type is not supported
+ CODEC_ERROR_FILE_SIZE_FAILED, //!< Could not determine the size of the file
+ CODEC_ERROR_READ_FILE_FAILED, //!< Could not read a file
+ CODEC_ERROR_FILE_WRITE_FAILED, //!< Could not write to the file
+ CODEC_ERROR_FILE_FLUSH_FAILED, //!< Could not flush the file buffer
+ CODEC_ERROR_PARSE_ARGUMENTS, //!< Error while parsing the command-line arguments
+ CODEC_ERROR_USAGE_INFO, //!< User asked for help with program usage
+ CODEC_ERROR_BANDFILE_FAILED, //!< Could not write the bandfile
+ CODEC_ERROR_BAD_PARAMETER, //!< Missing or inconsistent parameters
+
+} CODEC_ERROR;
+
+#endif // ERROR_H
diff --git a/gpr/source/lib/vc5_common/image.c b/gpr/source/lib/vc5_common/image.c
new file mode 100755
index 0000000..0af14fe
--- /dev/null
+++ b/gpr/source/lib/vc5_common/image.c
@@ -0,0 +1,321 @@
+/*! @file image.c
+ *
+ * @brief Implementation of the data structure for the image that is
+ * input to the image unpacking process.
+ *
+ * @version 1.0.0
+ *
+ * (C) Copyright 2018 GoPro Inc (http://gopro.com/).
+ *
+ * Licensed under either:
+ * - Apache License, Version 2.0, http://www.apache.org/licenses/LICENSE-2.0
+ * - MIT license, http://opensource.org/licenses/MIT
+ * at your option.
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "common.h"
+
+/*!
+ @brief Initialize the fields in an image data structure
+ This routine is the constructor for the image data type that
+ initializes an image instance to default values.
+ */
+CODEC_ERROR InitImage(IMAGE *image)
+{
+ if (image != NULL)
+ {
+ image->width = 0;
+ image->height = 0;
+ image->pitch = 0;
+ image->offset = 0;
+ image->format = PIXEL_FORMAT_UNKNOWN;
+ image->buffer = NULL;
+ image->size = 0;
+ return CODEC_ERROR_OKAY;
+ }
+
+ return CODEC_ERROR_NULLPTR;
+}
+
+CODEC_ERROR InitRGBImage(RGB_IMAGE *image)
+{
+ if (image != NULL)
+ {
+ image->width = 0;
+ image->height = 0;
+ image->pitch = 0;
+ image->buffer = NULL;
+ image->size = 0;
+ return CODEC_ERROR_OKAY;
+ }
+
+ return CODEC_ERROR_NULLPTR;
+}
+/*!
+ @brief Allocate the buffer for a image with the sepcified dimensions and format.
+ This routine calculates the image pitch from the width and format, rounding up
+ the pitch to satisfy memory alignment requirements in the codec.
+ This routine will cause a memory leak if it is called with a image that has
+ already been allocated.
+ */
+CODEC_ERROR AllocImage(gpr_allocator *allocator, IMAGE *image, DIMENSION width, DIMENSION height, PIXEL_FORMAT format)
+{
+ size_t size = 0;
+ DIMENSION pitch = 0;
+
+ assert(image != NULL);
+
+ // Compute the pitch from the width and format
+ pitch = ImagePitch(width, format);
+ assert(pitch > 0);
+
+#if VC5_ENABLED_PART(VC5_PART_COLOR_SAMPLING)
+ size = height * pitch;
+#else
+ size = height * pitch;
+#endif
+ assert(size > 0);
+
+ // Allocate the image buffer
+ image->buffer = allocator->Alloc(size);
+ if (image->buffer != NULL)
+ {
+ image->width = width;
+ image->height = height;
+ image->pitch = pitch;
+ image->format = format;
+ image->offset = 0;
+ image->size = size;
+ return CODEC_ERROR_OKAY;
+ }
+
+ return CODEC_ERROR_OUTOFMEMORY;
+}
+
+/*!
+ @brief Deallocate the buffer in a image data structure
+ This routine does not deallocate the image data structure itself.
+ In the typical use case, the image data structure is allocated on
+ the stack and teh decoder allocates the buffer for the output image
+ after determining the size of the image. The image data structure
+ is deallocated automatically by a calling routine.
+ */
+CODEC_ERROR ReleaseImage(gpr_allocator *allocator, IMAGE *image)
+{
+ allocator->Free(image->buffer);
+ return CODEC_ERROR_OKAY;
+}
+
+/*!
+ @brief Compute the image pitch for the specified width and pixel format
+ The pitch of the image (in bytes) is computed for a image with the width
+ and pixel format that is specified. The pitch is rounted up to satisfy
+ memory alignment constraints required by the codec.
+ The return value is zero if the pitch could not be computed for the
+ specified width and format.
+ */
+DIMENSION ImagePitch(DIMENSION width, PIXEL_FORMAT format)
+{
+ DIMENSION pitch = 0;
+
+ switch (format)
+ {
+ case PIXEL_FORMAT_RAW_RGGB_14:
+ case PIXEL_FORMAT_RAW_GBRG_12:
+ case PIXEL_FORMAT_RAW_GBRG_12P:
+ case PIXEL_FORMAT_RAW_RGGB_16:
+ // Half the width of the image times 2 samples times 2 bytes per sample
+ pitch = width * sizeof(uint16_t);
+ break;
+
+ default:
+ assert(0);
+ }
+
+ return pitch;
+}
+
+/*!
+ @brief Set the dimensions and pixel format of a image
+ This routine is used to set the dimensions and format of a image
+ that was allocated with unknown parameters.
+ */
+CODEC_ERROR SetImageFormat(IMAGE *image,
+ DIMENSION width,
+ DIMENSION height,
+ DIMENSION pitch,
+ PIXEL_FORMAT format,
+ size_t offset)
+{
+ assert(image != NULL);
+
+ image->width = width;
+ image->height = height;
+ image->pitch = pitch;
+ image->format = format;
+ image->offset = offset;
+
+ return CODEC_ERROR_OKAY;
+}
+
+/*!
+ @brief Return the address of the image in the buffer
+ This routine should be used to obtain the starting address of
+ a image in a image buffer since the image may be offset from the
+ beginning of the buffer.
+ */
+void *ImageData(IMAGE *image)
+{
+ uint8_t *buffer = image->buffer;
+ buffer += image->offset;
+ return buffer;
+}
+
+/*!
+ @brief Return the address of the specified row in the image
+ The routine returns NULL if the image argument is null or the
+ specified row is out of bounds.
+ */
+void *RowAddress(IMAGE *image, DIMENSION row)
+{
+ size_t pitch = image->pitch;
+
+ if (image != NULL && image->pitch != 0)
+ {
+ //if (0 <= row && row < image->height)
+ if (row < image->height)
+ {
+ void *address = (void *)((uintptr_t)ImageData(image) + row * pitch);
+ return address;
+ }
+ }
+
+ // Could not compute the address of a valid row
+ return NULL;
+}
+
+CODEC_ERROR ReleaseComponentArrays(gpr_allocator *allocator,
+ UNPACKED_IMAGE *image,
+ int channel_count )
+{
+ int channel;
+
+ for (channel = 0; channel < channel_count; channel++)
+ {
+ allocator->Free( image->component_array_list[channel].data );
+ }
+
+ allocator->Free( image->component_array_list );
+
+ return CODEC_ERROR_OKAY;
+}
+
+CODEC_ERROR AllocateComponentArrays(gpr_allocator *allocator,
+ UNPACKED_IMAGE *image,
+ int channel_count,
+ DIMENSION max_channel_width,
+ DIMENSION max_channel_height,
+ PIXEL_FORMAT format,
+ int bits_per_component)
+{
+ int channel;
+
+ // Allocate the vector of component arrays
+ size_t size = channel_count * sizeof(COMPONENT_ARRAY);
+ image->component_array_list = allocator->Alloc(size);
+ if (image->component_array_list == NULL) {
+ return CODEC_ERROR_OUTOFMEMORY;
+ }
+
+ // Clear the component array information so that the state is consistent
+ image->component_count = 0;
+ memset(image->component_array_list, 0, size);
+
+ // Initialize each component array
+ for (channel = 0; channel < channel_count; channel++)
+ {
+ DIMENSION channel_width = max_channel_width;
+ DIMENSION channel_height = max_channel_height;
+
+ // Allocate space for the data in the component array
+ CODEC_ERROR error = AllocateComponentArray( allocator, &image->component_array_list[channel], channel_width, channel_height, (uint_least8_t)bits_per_component );
+
+ if( error != CODEC_ERROR_OKAY ) {
+ return error;
+ }
+ }
+
+ // Set the number of component arrays
+ image->component_count = channel_count;
+
+ return CODEC_ERROR_OKAY;
+}
+
+CODEC_ERROR AllocateComponentArray(gpr_allocator *allocator,
+ COMPONENT_ARRAY *component_array,
+ DIMENSION width,
+ DIMENSION height,
+ PRECISION bits_per_component)
+{
+ //COMPONENT_ARRAY *component_array = Alloc(allocator, sizeof(COMPONENT_ARRAY));
+
+ // Allocate space for the data in the component array
+ size_t pitch = width * sizeof(COMPONENT_VALUE);
+ size_t size = height * pitch;
+ void *buffer = allocator->Alloc(size);
+ assert(buffer != NULL);
+ if (! (buffer != NULL)) {
+ return CODEC_ERROR_OUTOFMEMORY;
+ }
+
+ component_array->width = width;
+ component_array->height = height;
+ component_array->pitch = pitch;
+ component_array->data = buffer;
+ component_array->bits_per_component = bits_per_component;
+
+ return CODEC_ERROR_OKAY;
+}
+
+/*!
+ @brief Initialize the data structure for the unpacked image
+ Note that the component arrays will be allocated after the bitstream
+ has been decoded and the dimensions of the component arrys are known.
+ */
+CODEC_ERROR InitUnpackedImage(UNPACKED_IMAGE *unpacked_image)
+{
+ if (unpacked_image == NULL) {
+ return CODEC_ERROR_UNEXPECTED;
+ }
+
+ // Clear the fields in the unpacked iamge
+ memset(unpacked_image, 0, sizeof(UNPACKED_IMAGE));
+
+ return CODEC_ERROR_OKAY;
+}
+
+/*!
+ @brief Return the maximum number of bits per component across all channels in the unpacked image
+ */
+PRECISION MaxBitsPerComponent(const UNPACKED_IMAGE *image)
+{
+ PRECISION max_bits_per_component = 0;
+ int channel;
+
+ for (channel = 0; channel < image->component_count; channel++)
+ {
+ COMPONENT_ARRAY *component_array = &image->component_array_list[channel];
+
+ if (max_bits_per_component < component_array->bits_per_component) {
+ max_bits_per_component = component_array->bits_per_component;
+ }
+ }
+
+ return max_bits_per_component;
+}
diff --git a/gpr/source/lib/vc5_common/image.h b/gpr/source/lib/vc5_common/image.h
new file mode 100755
index 0000000..4739727
--- /dev/null
+++ b/gpr/source/lib/vc5_common/image.h
@@ -0,0 +1,165 @@
+/*! @file image.h
+ *
+ * @brief Declaration of structures and functions for images
+ *
+ * @version 1.0.0
+ *
+ * (C) Copyright 2018 GoPro Inc (http://gopro.com/).
+ *
+ * Licensed under either:
+ * - Apache License, Version 2.0, http://www.apache.org/licenses/LICENSE-2.0
+ * - MIT license, http://opensource.org/licenses/MIT
+ * at your option.
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef IMAGE_H
+#define IMAGE_H
+
+//! Data type for the values in a component array
+typedef uint16_t COMPONENT_VALUE;
+
+/*!
+ @brief Data structure for an image input to the unpacking process
+
+ This data structure is used to represent the image that is the input to the
+ image unpacking process that unpacks an image into component arrays for encoding.
+ Unlike the wavelet data structures, an image contains multiple color components,
+ usually in a packed pixel format.
+*/
+typedef struct _packed_image
+{
+ DIMENSION width; //!< Width of the frame (in pixels)
+ DIMENSION height; //!< Height of the frame
+ size_t pitch; //!< Distance between rows (in bytes)
+ PIXEL_FORMAT format; //!< Format of the pixels
+ void *buffer; //!< Address of the buffer for the frame
+ size_t size; //!< Allocated size of the buffer (in bytes)
+ size_t offset; //!< Offset to the start of the frame
+} PACKED_IMAGE;
+
+/*!
+ @brief Data structure for an image input to the unpacking process
+
+ This data structure is used to represent the image that is the input to the
+ image unpacking process that unpacks an image into component arrays for encoding.
+ Unlike the wavelet data structures, an image contains multiple color components,
+ usually in a packed pixel format.
+ */
+typedef struct _rgb_image
+{
+ DIMENSION width; //!< Width of the frame (in pixels)
+ DIMENSION height; //!< Height of the frame
+ size_t pitch; //!< Distance between rows (in bytes)
+ void *buffer; //!< Address of the buffer for the frame
+ size_t size; //!< Allocated size of the buffer (in bytes)
+} RGB_IMAGE;
+
+//! Short name for the packed image data type
+typedef PACKED_IMAGE IMAGE;
+
+/*!
+ @brief Data structure for an array that contains a single type of component
+
+ This data structure is used to represent the component array output by the image
+ unpacking process. The image unpacking process unpacks an image into component
+ arrays for encoding.
+*/
+typedef struct _component_array
+{
+ DIMENSION width; //!< Width of the frame (in pixels)
+ DIMENSION height; //!< Height of the frame
+ size_t pitch; //!< Distance between rows (in bytes)
+ COMPONENT_VALUE *data; //!< Buffer for the array of component values
+
+ //! Number of bits per in each component value
+ PRECISION bits_per_component;
+
+} COMPONENT_ARRAY;
+
+/*!
+ @brief Image represented as an ordered set of component arrays
+
+ The decoder outputs a set of component arrays that represent an image.
+
+ The image repacking process can pack the component arrays output by the
+ decoder into a packed image.
+*/
+typedef struct _unpacked_image
+{
+ //! Number of component arrays in the unpacked image
+ int component_count;
+
+ //! Vector of component arrays
+ COMPONENT_ARRAY *component_array_list;
+
+} UNPACKED_IMAGE;
+
+/*!
+ @brief Flags that describe the image structure
+*/
+typedef enum
+{
+ IMAGE_STRUCTURE_INTERLACED = 0x0001, //!< Set the first bit if the image is interlaced
+ IMAGE_STRUCTURE_BOTTOM_FIELD_FIRST = 0x0002, //!< The bottom field is encoded before the top field
+ IMAGE_STRUCTURE_BOTTOM_ROW_FIRST = 0x0010, //!< The encoded image is upside down
+} IMAGE_STRUCTURE;
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+ CODEC_ERROR InitImage(IMAGE *image);
+
+ CODEC_ERROR InitRGBImage(RGB_IMAGE *image);
+
+ CODEC_ERROR AllocImage(gpr_allocator *allocator, IMAGE *image, DIMENSION width, DIMENSION height, PIXEL_FORMAT format);
+
+ CODEC_ERROR ReleaseImage(gpr_allocator *allocator, IMAGE *image);
+
+ DIMENSION ImagePitch(DIMENSION width, PIXEL_FORMAT format);
+
+ CODEC_ERROR SetImageFormat(IMAGE *image,
+ DIMENSION width,
+ DIMENSION height,
+ DIMENSION pitch,
+ PIXEL_FORMAT format,
+ size_t offset);
+
+ void *ImageData(IMAGE *image);
+
+ void *RowAddress(IMAGE *image, DIMENSION row);
+
+ CODEC_ERROR ReleaseComponentArrays(gpr_allocator *allocator,
+ UNPACKED_IMAGE *image,
+ int channel_count );
+
+ CODEC_ERROR AllocateComponentArrays(gpr_allocator *allocator,
+ UNPACKED_IMAGE *image,
+ int channel_count,
+ DIMENSION max_channel_width,
+ DIMENSION max_channel_height,
+ PIXEL_FORMAT format,
+ int bits_per_component);
+
+ CODEC_ERROR AllocateComponentArray(gpr_allocator *allocator,
+ COMPONENT_ARRAY *component_array,
+ DIMENSION width,
+ DIMENSION height,
+ PRECISION bits_per_component);
+
+ CODEC_ERROR InitUnpackedImage(UNPACKED_IMAGE *image);
+
+ PRECISION MaxBitsPerComponent(const UNPACKED_IMAGE *image);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // IMAGE_H
diff --git a/gpr/source/lib/vc5_common/logcurve.c b/gpr/source/lib/vc5_common/logcurve.c
new file mode 100755
index 0000000..45aecbf
--- /dev/null
+++ b/gpr/source/lib/vc5_common/logcurve.c
@@ -0,0 +1,58 @@
+/*! @file logcurve.c
+ *
+ * @brief Implementation of functions used to do log conversion.
+ *
+ * @version 1.0.0
+ *
+ * (C) Copyright 2018 GoPro Inc (http://gopro.com/).
+ *
+ * Licensed under either:
+ * - Apache License, Version 2.0, http://www.apache.org/licenses/LICENSE-2.0
+ * - MIT license, http://opensource.org/licenses/MIT
+ * at your option.
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "common.h"
+
+uint16_t EncoderLogCurve[LOG_CURVE_TABLE_LENGTH];
+
+uint16_t DecoderLogCurve[LOG_CURVE_TABLE_LENGTH];
+
+void SetupDecoderLogCurve(void)
+{
+ int i;
+ const int log_table_size = sizeof(DecoderLogCurve) / sizeof(DecoderLogCurve[0]);
+
+ const int max_16_bit = (1 << 16) - 1;
+
+ for( i = 0; i < log_table_size; i++ )
+ {
+ //input 12-bit, output 16-bit
+ float input = i;
+ float output = max_16_bit * (pow(113.0, input/4095.0) - 1.0)/112.0;
+
+ DecoderLogCurve[i] = minimum( (int)output, max_16_bit );
+ }
+}
+
+void SetupEncoderLogCurve(void)
+{
+ int i;
+ const int max_input_val = LOG_CURVE_TABLE_LENGTH - 1;
+
+ for( i = 0; i < LOG_CURVE_TABLE_LENGTH; i++ )
+ {
+ //input 16-bit, output 12-bit
+ float input = maximum( 0, i );
+ float output = 4095.0 * (log10(input/max_input_val * 112.0 + 1.0)/log10(113));
+
+ EncoderLogCurve[i] = ( (uint16_t)output );
+ }
+}
+
diff --git a/gpr/source/lib/vc5_common/logcurve.h b/gpr/source/lib/vc5_common/logcurve.h
new file mode 100755
index 0000000..3e6a269
--- /dev/null
+++ b/gpr/source/lib/vc5_common/logcurve.h
@@ -0,0 +1,42 @@
+/*! @file logcurve.h
+ *
+ * @brief Declaration of the data structures and constants used to do log conversion.
+ *
+ * @version 1.0.0
+ *
+ * (C) Copyright 2018 GoPro Inc (http://gopro.com/).
+ *
+ * Licensed under either:
+ * - Apache License, Version 2.0, http://www.apache.org/licenses/LICENSE-2.0
+ * - MIT license, http://opensource.org/licenses/MIT
+ * at your option.
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LOGCURVE_H
+#define LOGCURVE_H
+
+#define LOG_CURVE_TABLE_LENGTH (1 << 12)
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+ extern uint16_t EncoderLogCurve[];
+
+ extern uint16_t DecoderLogCurve[];
+
+ void SetupDecoderLogCurve(void);
+
+ void SetupEncoderLogCurve(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // LOGCURVE_H
diff --git a/gpr/source/lib/vc5_common/pixel.h b/gpr/source/lib/vc5_common/pixel.h
new file mode 100755
index 0000000..7c3b9e0
--- /dev/null
+++ b/gpr/source/lib/vc5_common/pixel.h
@@ -0,0 +1,100 @@
+/*! @file pixel.h
+ *
+ * @brief The pixel format enumerations define the pixel packing formats that are
+ * supported by the codec for input to the image unpacking process and for
+ * output from the image repacking process.
+ *
+ * @version 1.0.0
+ *
+ * (C) Copyright 2018 GoPro Inc (http://gopro.com/).
+ *
+ * Licensed under either:
+ * - Apache License, Version 2.0, http://www.apache.org/licenses/LICENSE-2.0
+ * - MIT license, http://opensource.org/licenses/MIT
+ * at your option.
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef PIXEL_H
+#define PIXEL_H
+
+//! Data type for pixels
+typedef int16_t PIXEL;
+
+//! Minimum and maximum pixel values
+enum {
+ PIXEL_MIN = INT16_MIN,
+ PIXEL_MAX = INT16_MAX,
+};
+
+//! Alternative definition for wavelet coefficients
+typedef int16_t COEFFICIENT;
+
+//! Minimum and maximum coefficient values
+enum
+{
+ COEFFICIENT_MIN = INT16_MIN,
+ COEFFICIENT_MAX = INT16_MAX,
+};
+
+/*!
+ @brief Pixels formats supported by the codec
+
+ The pixel format is only the packing arrangement for color components and
+ does not specify whether the image is interlaced or the bottom row is first.
+
+ @todo Need to add support for more pixel formats to the reference decoder
+*/
+typedef enum
+{
+ PIXEL_FORMAT_UNKNOWN = 0,
+
+ PIXEL_FORMAT_RAW_RGGB_16 = 104,
+
+ PIXEL_FORMAT_RAW_RGGB_12 = 106,
+ PIXEL_FORMAT_RAW_RGGB_12P = 107,
+ PIXEL_FORMAT_RAW_RGGB_14 = 108,
+
+ PIXEL_FORMAT_RAW_GBRG_12 = 109,
+ PIXEL_FORMAT_RAW_GBRG_12P = 110,
+ PIXEL_FORMAT_RAW_GBRG_14 = 111,
+
+ PIXEL_FORMAT_RAW_DEFAULT = PIXEL_FORMAT_RAW_RGGB_14,
+
+ //! Input pixel formats above this value must be encoded into the sample
+ PIXEL_FORMAT_TAG_REQUIRED = 100,
+
+} PIXEL_FORMAT;
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*!
+@brief Force a pixel value to be in range
+*/
+STATIC_INLINE PIXEL ClampPixel(int32_t value)
+{
+ // Check for values that are outside the range (for debugging)
+ assert(PIXEL_MIN <= value && value <= PIXEL_MAX);
+
+ if (value < PIXEL_MIN)
+ value = PIXEL_MIN;
+ else
+ if (value > PIXEL_MAX)
+ value = PIXEL_MAX;
+
+ return (PIXEL)value;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // PIXEL_H
diff --git a/gpr/source/lib/vc5_common/stream.c b/gpr/source/lib/vc5_common/stream.c
new file mode 100755
index 0000000..59ecc7d
--- /dev/null
+++ b/gpr/source/lib/vc5_common/stream.c
@@ -0,0 +1,524 @@
+/*! @file stream.h
+ *
+ * @brief This module implements a byte stream abstraction that hides the details
+ * of how a stream of bytes is read or written on demand by the bitstream.
+ * The byte stream can be bound to a binary file opened for reading (writing),
+ * to a buffer in memory, or to a module that reads (writes) a video track
+ * in a media container.
+ *
+ * @version 1.0.0
+ *
+ * (C) Copyright 2018 GoPro Inc (http://gopro.com/).
+ *
+ * Licensed under either:
+ * - Apache License, Version 2.0, http://www.apache.org/licenses/LICENSE-2.0
+ * - MIT license, http://opensource.org/licenses/MIT
+ * at your option.
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "common.h"
+
+// Local functions
+CODEC_ERROR GetBlockFile(STREAM *stream, void *buffer, size_t size, size_t offset);
+CODEC_ERROR PutBlockFile(STREAM *stream, void *buffer, size_t size, size_t offset);
+CODEC_ERROR GetBlockMemory(STREAM *stream, void *buffer, size_t size, size_t offset);
+CODEC_ERROR PutBlockMemory(STREAM *stream, void *buffer, size_t size, size_t offset);
+
+/*!
+ @brief Open a stream for reading bytes from the specified file
+
+*/
+CODEC_ERROR OpenStream(STREAM *stream, const char *pathname)
+{
+ assert(stream != NULL);
+ if (! (stream != NULL)) {
+ return CODEC_ERROR_NULLPTR;
+ }
+
+ // Clear all members of the stream data structure
+ memset(stream, 0, sizeof(STREAM));
+
+ // Open the file and bind it to the stream
+ stream->location.file.iobuf = fopen(pathname, "rb");
+ assert(stream->location.file.iobuf != NULL);
+ if (! (stream->location.file.iobuf != NULL)) {
+ return CODEC_ERROR_OPEN_FILE_FAILED;
+ }
+
+ // Set the stream type and access
+ stream->type = STREAM_TYPE_FILE;
+ stream->access = STREAM_ACCESS_READ;
+
+ // Clear the number of bytes read from the stream
+ stream->byte_count = 0;
+
+ return CODEC_ERROR_OKAY;
+}
+
+/*!
+ @brief Create a stream for writing bytes to a specified file
+
+*/
+CODEC_ERROR CreateStream(STREAM *stream, const char *pathname)
+{
+ assert(stream != NULL);
+ if (! (stream != NULL)) {
+ return CODEC_ERROR_NULLPTR;
+ }
+
+ // Clear all members of the stream data structure
+ memset(stream, 0, sizeof(STREAM));
+
+ // Open the file and bind it to the stream
+ stream->location.file.iobuf = fopen(pathname, "wb+");
+ assert(stream->location.file.iobuf != NULL);
+ if (! (stream->location.file.iobuf != NULL)) {
+ return CODEC_ERROR_CREATE_FILE_FAILED;
+ }
+
+ // Set the stream type and access
+ stream->type = STREAM_TYPE_FILE;
+ stream->access = STREAM_ACCESS_WRITE;
+
+ // Clear the number of bytes written to the stream
+ stream->byte_count = 0;
+
+ return CODEC_ERROR_OKAY;
+}
+
+/*!
+ @brief Read a word from a byte stream
+
+ This routine is used by the bitstream to read a word from a byte stream.
+ A word is the number of bytes that can be stored in the internal buffer
+ used by the bitstream.
+
+ @todo Need to modify the routine to return an indication of end of file
+ or an error reading from the byte stream.
+*/
+BITWORD GetWord(STREAM *stream)
+{
+ BITWORD buffer = 0;
+ size_t bytes_read = sizeof(buffer);
+
+ assert(stream != NULL);
+
+ switch (stream->type)
+ {
+ case STREAM_TYPE_FILE:
+ bytes_read = fread(&buffer, 1, sizeof(buffer), stream->location.file.iobuf);
+ assert(bytes_read == sizeof(buffer));
+ break;
+
+ case STREAM_TYPE_MEMORY:
+ memcpy(&buffer, (uint8_t *)stream->location.memory.buffer + stream->byte_count, sizeof(buffer));
+ break;
+
+ default:
+ assert(0);
+ break;
+ }
+
+ if (bytes_read > 0)
+ stream->byte_count += sizeof(buffer);
+
+ return buffer;
+}
+
+/*!
+ @brief Read a byte from a byte stream
+*/
+uint8_t GetByte(STREAM *stream)
+{
+ assert(stream != NULL);
+ int byte = 0;
+
+ switch (stream->type)
+ {
+ case STREAM_TYPE_FILE:
+ byte = fgetc(stream->location.file.iobuf);
+ break;
+
+ case STREAM_TYPE_MEMORY:
+ byte = ((uint8_t *)stream->location.memory.buffer)[stream->byte_count];
+ break;
+
+ default:
+ assert(0);
+ break;
+ }
+
+ stream->byte_count++;
+ assert(byte >= 0 && (byte & ~0xFF) == 0);
+
+ return (uint8_t)byte;
+}
+
+/*!
+ @brief Write a word to a byte stream
+
+ This routine is used by the bitstream to write a word to a byte stream.
+ A word is the number of bytes that can be stored in the internal buffer
+ used by the bitstream.
+
+ @todo Need to modify the routine to return an indication of an error
+ writing to the byte stream.
+*/
+CODEC_ERROR PutWord(STREAM *stream, BITWORD word)
+{
+ size_t written;
+
+ word = Swap32(word);
+
+ assert(stream != NULL);
+
+ switch (stream->type)
+ {
+ case STREAM_TYPE_FILE:
+ written = fwrite(&word, sizeof(word), 1, stream->location.file.iobuf);
+ if (written == 0)
+ return CODEC_ERROR_FILE_WRITE_FAILED;
+ break;
+
+ case STREAM_TYPE_MEMORY:
+ {
+ uint8_t* buffer = (uint8_t *)stream->location.memory.buffer + stream->byte_count;
+
+ memcpy(buffer, &word, sizeof(word));
+ }
+ break;
+
+ default:
+ assert(0);
+ break;
+ }
+
+ stream->byte_count += sizeof(word);
+
+ return CODEC_ERROR_OKAY;
+}
+
+/*!
+ @brief Write a byte to a byte stream
+*/
+CODEC_ERROR PutByte(STREAM *stream, uint8_t byte)
+{
+ assert(stream != NULL);
+
+ //assert(byte >= 0 && (byte & ~0xFF) == 0);
+
+ switch (stream->type)
+ {
+ case STREAM_TYPE_FILE:
+ if (fputc(byte, stream->location.file.iobuf) == EOF)
+ return CODEC_ERROR_FILE_WRITE_FAILED;
+ break;
+
+ case STREAM_TYPE_MEMORY:
+ ((uint8_t *)stream->location.memory.buffer)[stream->byte_count] = byte;
+ break;
+
+ default:
+ assert(0);
+ break;
+ }
+
+ stream->byte_count++;
+
+ return CODEC_ERROR_OKAY;
+}
+
+/*!
+ @brief Rewind the stream to the beginning of the buffer or file
+*/
+CODEC_ERROR RewindStream(STREAM *stream)
+{
+ assert(stream != NULL);
+ if (! (stream != NULL)) {
+ return CODEC_ERROR_NULLPTR;
+ }
+
+ if( stream->type == STREAM_TYPE_FILE )
+ {
+ if (stream->location.file.iobuf != NULL) {
+ assert(fseek(stream->location.file.iobuf, 0, SEEK_SET) == 0);
+ return CODEC_ERROR_BITSTREAM;
+ }
+ }
+
+ stream->byte_count = 0;
+
+ return CODEC_ERROR_OKAY;
+}
+
+/*!
+ @brief Skip the specified number of bytes in the stream
+*/
+CODEC_ERROR SkipBytes(STREAM *stream, size_t size)
+{
+ for (; size > 0; size--)
+ {
+ (void)GetByte(stream);
+ }
+ return CODEC_ERROR_OKAY;
+}
+
+/*!
+ @brief Pad the specified number of bytes in the stream
+*/
+CODEC_ERROR PadBytes(STREAM *stream, size_t size)
+{
+ const uint8_t byte = 0;
+ for (; size > 0; size--)
+ {
+ PutByte(stream, byte);
+ }
+ return CODEC_ERROR_OKAY;
+}
+
+/*!
+ @brief Write the stream buffer to the file
+*/
+CODEC_ERROR FlushStream(STREAM *stream)
+{
+ assert(stream != NULL);
+ if (! (stream != NULL)) {
+ return CODEC_ERROR_NULLPTR;
+ }
+
+ if (stream->type == STREAM_TYPE_FILE)
+ {
+ int result = fflush(stream->location.file.iobuf);
+ if (result != 0) {
+ return CODEC_ERROR_FILE_FLUSH_FAILED;
+ }
+ }
+
+ return CODEC_ERROR_OKAY;
+}
+
+/*!
+ @brief Create a byte stream for reading from a memory location
+ */
+CODEC_ERROR OpenStreamBuffer(STREAM *stream, void *buffer, size_t size)
+{
+ assert(stream != NULL);
+ if (! (stream != NULL)) {
+ return CODEC_ERROR_NULLPTR;
+ }
+
+ // Clear all members of the stream data structure
+ memset(stream, 0, sizeof(STREAM));
+
+ // Bind the stream to the buffer
+ stream->location.memory.buffer = buffer;
+ stream->location.memory.size = size;
+
+ // Set the stream type and access
+ stream->type = STREAM_TYPE_MEMORY;
+ stream->access = STREAM_ACCESS_READ;
+
+ // Clear the number of bytes written to the stream
+ stream->byte_count = 0;
+
+ return CODEC_ERROR_OKAY;
+}
+
+/*!
+ @brief Create a byte stream for writing to a memory location
+*/
+CODEC_ERROR CreateStreamBuffer(STREAM *stream, void *buffer, size_t size)
+{
+ assert(stream != NULL);
+ if (! (stream != NULL)) {
+ return CODEC_ERROR_NULLPTR;
+ }
+
+ // Clear all members of the stream data structure
+ memset(stream, 0, sizeof(STREAM));
+
+ // Bind the stream to the buffer
+ stream->location.memory.buffer = buffer;
+ stream->location.memory.size = size;
+
+ // Set the stream type and access
+ stream->type = STREAM_TYPE_MEMORY;
+ stream->access = STREAM_ACCESS_WRITE;
+
+ // Clear the number of bytes written to the stream
+ stream->byte_count = 0;
+
+ return CODEC_ERROR_OKAY;
+}
+
+/*!
+ @brief Return the starting address and number of bytes in a buffer
+
+ This routine is used to get the address and count of the bytes written
+ to a memory stream (buffer).
+*/
+CODEC_ERROR GetStreamBuffer(STREAM *stream, void **buffer_out, size_t *size_out)
+{
+ assert(stream != NULL);
+ if (! (stream != NULL)) {
+ return CODEC_ERROR_NULLPTR;
+ }
+
+ assert(stream->type == STREAM_TYPE_MEMORY);
+
+ if (buffer_out != NULL) {
+ *buffer_out = stream->location.memory.buffer;
+ }
+
+ if (size_out != NULL) {
+ *size_out = stream->byte_count;
+ }
+
+ return CODEC_ERROR_OKAY;
+}
+
+/*!
+ @brief Read a block of data at the specified offset in the byte stream
+*/
+CODEC_ERROR GetBlock(STREAM *stream, void *buffer, size_t size, size_t offset)
+{
+ switch (stream->type)
+ {
+ case STREAM_TYPE_FILE:
+ return GetBlockFile(stream, buffer, size, offset);
+ break;
+
+ case STREAM_TYPE_MEMORY:
+ return GetBlockMemory(stream, buffer, size, offset);
+ break;
+
+ case STREAM_TYPE_UNKNOWN:
+ assert(0);
+ break;
+ }
+
+ return CODEC_ERROR_UNEXPECTED;
+}
+
+/*!
+ @brief Read a block of data from a file stream
+*/
+CODEC_ERROR GetBlockFile(STREAM *stream, void *buffer, size_t size, size_t offset)
+{
+ FILE *file = stream->location.file.iobuf;
+ fpos_t position;
+
+ (void)file;
+ (void)position;
+
+ // Save the current position in the file
+ if (fgetpos(file, &position) != 0) {
+ return CODEC_ERROR_FILE_GET_POSITION;
+ }
+
+ // Seek to the specified offset
+ assert(offset <= LONG_MAX);
+ if (fseek(file, (long)offset, SEEK_SET) != 0) {
+ return CODEC_ERROR_FILE_SEEK;
+ }
+
+ // Read data from the file
+ if (fread(buffer, size, 1, file) != 1) {
+ return CODEC_ERROR_FILE_READ;
+ }
+
+ // Return to the previous position in the file
+ // if (fseek(file, (long)position, SEEK_SET) != 0) {
+ if (fsetpos(file, &position) != 0) {
+ return CODEC_ERROR_FILE_SEEK;
+ }
+
+ return CODEC_ERROR_OKAY;
+}
+
+/*!
+ @brief Read a block of data from a memory stream (buffer)
+*/
+CODEC_ERROR GetBlockMemory(STREAM *stream, void *buffer, size_t size, size_t offset)
+{
+ uint8_t *block = (uint8_t *)stream->location.memory.buffer + offset;
+ memcpy(buffer, block, size);
+ return CODEC_ERROR_OKAY;
+}
+
+/*!
+ @brief Write a block of data at the specified offset in the byte stream
+*/
+CODEC_ERROR PutBlock(STREAM *stream, void *buffer, size_t size, size_t offset)
+{
+ switch (stream->type)
+ {
+ case STREAM_TYPE_FILE:
+ return PutBlockFile(stream, buffer, size, offset);
+ break;
+
+ case STREAM_TYPE_MEMORY:
+ return PutBlockMemory(stream, buffer, size, offset);
+ break;
+
+ case STREAM_TYPE_UNKNOWN:
+ assert(0);
+ break;
+ }
+
+ return CODEC_ERROR_UNEXPECTED;
+}
+
+/*!
+ @brief Write a block of data at the specified offset in a file stream
+*/
+CODEC_ERROR PutBlockFile(STREAM *stream, void *buffer, size_t size, size_t offset)
+{
+ FILE *file = stream->location.file.iobuf;
+ fpos_t position;
+
+ (void)file;
+ (void)position;
+
+ // Save the current position in the file
+ if (fgetpos(file, &position) != 0) {
+ return CODEC_ERROR_FILE_GET_POSITION;
+ }
+
+ // Seek to the specified offset and write to the file
+ assert(offset <= LONG_MAX);
+ if (fseek(file, (long)offset, SEEK_SET) != 0) {
+ return CODEC_ERROR_FILE_SEEK;
+ }
+
+ // Write data to the file
+ if (fwrite(buffer, size, 1, file) != 1) {
+ return CODEC_ERROR_FILE_WRITE;
+ }
+
+ // Return to the previous position in the file
+ // if (fseek(file, (long)position, SEEK_SET) != 0) {
+ if (fsetpos(file, &position) != 0) {
+ return CODEC_ERROR_FILE_SEEK;
+ }
+
+ return CODEC_ERROR_OKAY;
+}
+
+/*!
+ @brief Write a block of data at the specified offset in a memory stream
+*/
+CODEC_ERROR PutBlockMemory(STREAM *stream, void *buffer, size_t size, size_t offset)
+{
+ uint8_t *block = (uint8_t *)stream->location.memory.buffer + offset;
+ memcpy(block, buffer, size);
+ return CODEC_ERROR_OKAY;
+}
+
+
diff --git a/gpr/source/lib/vc5_common/stream.h b/gpr/source/lib/vc5_common/stream.h
new file mode 100755
index 0000000..df70a4f
--- /dev/null
+++ b/gpr/source/lib/vc5_common/stream.h
@@ -0,0 +1,133 @@
+/*! @file stream.h
+ *
+ * @brief The stream abstracts the methods used by bitstreams to output bytes
+ *
+ * @version 1.0.0
+ *
+ * (C) Copyright 2018 GoPro Inc (http://gopro.com/).
+ *
+ * Licensed under either:
+ * - Apache License, Version 2.0, http://www.apache.org/licenses/LICENSE-2.0
+ * - MIT license, http://opensource.org/licenses/MIT
+ * at your option.
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef STREAM_H
+#define STREAM_H
+
+//! Type of stream (binary file or memory buffer)
+typedef enum _stream_type
+{
+ STREAM_TYPE_UNKNOWN = 0, //!< Unknown type of stream
+ STREAM_TYPE_FILE, //!< Simple binary file
+ STREAM_TYPE_MEMORY, //!< Buffer in memory
+
+} STREAM_TYPE;
+
+/*!
+ @brief Stream access (read or write)
+
+ The stream provided with the reference decoder only supports
+ read access.
+*/
+typedef enum _stream_access
+{
+ STREAM_ACCESS_UNKNOWN = 0,
+ STREAM_ACCESS_READ,
+ STREAM_ACCESS_WRITE,
+
+} STREAM_ACCESS;
+
+
+/*!
+ @brief Declaration of the data structure for a byte stream
+
+ The byte stream encapsulates the location of encoded images and the
+ means for reading (writing) encoded images samples. The byte stream
+ could be a binary file that has been opened for reading (writing) or
+ a buffer in memory. The reference codec uses a binary file as the byte
+ stream so the functionality for streams attached to memory buffers has
+ not been tested.
+
+ It is intended that the byte stream can be enhanced to read (write)
+ encoded images from (into) a track in a media container.
+*/
+#define STREAM_CACHE_SIZE 16
+typedef struct _stream
+{
+ STREAM_TYPE type; //!< Type of stream (file or memory buffer)
+ STREAM_ACCESS access; //!< Type of access (read or write)
+
+ //! Union of parameters for different types of streams
+ union _location
+ {
+ //! Parameters for a binary file stream
+ struct _file
+ {
+ FILE *iobuf; //!< Binary file that contains the stream
+ BITWORD cache[STREAM_CACHE_SIZE];
+ int cache_index;
+
+ } file; //!< Parameters for a stream in a binary file
+
+ //! Parameters for a stream bound to a memory buffer
+ struct _memory
+ {
+ void *buffer; //!< Memory buffer that contains the stream
+ size_t size; //!< Length of the stream (in bytes)
+
+ } memory; //!< Parameters for a stream in a memory buffer
+
+ //TODO: Add other stream types for media containers
+
+ } location; //!< Location of the byte stream (file or memory buffer)
+
+ size_t byte_count; //!< Number of bytes read or written to the stream
+
+} STREAM;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+ CODEC_ERROR OpenStream(STREAM *stream, const char *pathname);
+
+ CODEC_ERROR CreateStream(STREAM *stream, const char *pathname);
+
+ CODEC_ERROR RewindStream(STREAM *stream);
+
+ BITWORD GetWord(STREAM *stream);
+
+ uint8_t GetByte(STREAM *stream);
+
+ CODEC_ERROR SkipBytes(STREAM *stream, size_t size);
+
+ CODEC_ERROR PutWord(STREAM *stream, BITWORD word);
+
+ CODEC_ERROR PutByte(STREAM *stream, uint8_t byte);
+
+ CODEC_ERROR PadBytes(STREAM *stream, size_t size);
+
+ CODEC_ERROR FlushStream(STREAM *stream);
+
+ CODEC_ERROR OpenStreamBuffer(STREAM *stream, void *buffer, size_t size);
+
+ CODEC_ERROR CreateStreamBuffer(STREAM *stream, void *buffer, size_t size);
+
+ CODEC_ERROR GetStreamBuffer(STREAM *stream, void **buffer_out, size_t *size_out);
+
+ CODEC_ERROR GetBlock(STREAM *stream, void *buffer, size_t size, size_t offset);
+
+ CODEC_ERROR PutBlock(STREAM *stream, void *buffer, size_t size, size_t offset);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/gpr/source/lib/vc5_common/syntax.c b/gpr/source/lib/vc5_common/syntax.c
new file mode 100755
index 0000000..bf64afe
--- /dev/null
+++ b/gpr/source/lib/vc5_common/syntax.c
@@ -0,0 +1,150 @@
+/*! @file syntax.c
+ *
+ * @brief Implementation of functions for parsing the bitstream syntax of encoded samples.
+ *
+ * @version 1.0.0
+ *
+ * (C) Copyright 2018 GoPro Inc (http://gopro.com/).
+ *
+ * Licensed under either:
+ * - Apache License, Version 2.0, http://www.apache.org/licenses/LICENSE-2.0
+ * - MIT license, http://opensource.org/licenses/MIT
+ * at your option.
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "common.h"
+
+//TODO: Simplify the definition of the marker bits
+#define CODEC_LOWPASS_START_CODE 0x1A4A
+#define CODEC_LOWPASS_START_SIZE 16
+#define CODEC_LOWPASS_END_CODE 0x1B4B
+#define CODEC_LOWPASS_END_SIZE 16
+
+#define CODEC_HIGHPASS_START_CODE 0x0D0D
+#define CODEC_HIGHPASS_START_SIZE 16
+#define CODEC_HIGHPASS_END_CODE 0x0C0C
+#define CODEC_HIGHPASS_END_SIZE 16
+
+#define CODEC_BAND_START_CODE 0x0E0E
+#define CODEC_BAND_START_SIZE 16
+//#define CODEC_BAND_END_CODE 0x038F0B3E //Codeset dependent cs9
+//#define CODEC_BAND_END_SIZE 26 //Codeset dependent cs9
+#define CODEC_BAND_END_CODE 0x0000E33F //Codeset dependent cs15
+#define CODEC_BAND_END_SIZE 16 //Codeset dependent cs15
+
+#define CODEC_SAMPLE_STOP_CODE 0x1E1E
+#define CODEC_SAMPLE_STOP_SIZE 16
+
+#define CODEC_COEFFICIENT_START_CODE 0x0F0F
+#define CODEC_COEFFICIENT_START_SIZE 16
+
+//! Size of a tag or value (in bits)
+#define BITSTREAM_TAG_SIZE 16
+
+
+// Bits in the interlace structure flags
+
+#define CODEC_FLAGS_INTERLACED 0x01 //!< Interlaced flags
+#define CODEC_FLAGS_FIELD1_FIRST 0x02 //!< NTSC has this bit cleared
+#define CODEC_FLAGS_FIELD1_ONLY 0x04 //!< Indicates missing fields
+#define CODEC_FLAGS_FIELD2_ONLY 0x08
+#define CODEC_FLAGS_DOMINANCE 0x10
+
+#define CODEC_FLAGS_INTERLACED_MASK 0x1F //!< Unused bits must be zero
+
+// Useful macros for testing the interlaced flags
+
+#define INTERLACED(flags) (((flags) & CODEC_FLAGS_INTERLACED) != 0)
+#define PROGRESSIVE(flags) (((flags) & CODEC_FLAGS_INTERLACED) == 0)
+#define FIELD_ORDER_NTSC(flags) (((flags) & CODEC_FLAGS_FIELD1_FIRST) == 0)
+#define FIELD_ORDER_PAL(flags) (((flags) & CODEC_FLAGS_FIELD1_FIRST) != 0)
+#define FIELD_ONE_ONLY(flags) (((flags) & CODEC_FLAGS_FIELD1_ONLY) != 0)
+#define FIELD_TWO_ONLY(flags) (((flags) & CODEC_FLAGS_FIELD2_ONLY) != 0)
+#define FIELD_ONE_PRESENT(flags) (((flags) & CODEC_FLAGS_FIELD2_ONLY) == 0)
+#define FIELD_TWO_PRESENT(flags) (((flags) & CODEC_FLAGS_FIELD1_ONLY) == 0)
+#define FIELD_BOTH_PRESENT(flags) (((flags) & (CODEC_FLAGS_FIELD1_ONLY | CODEC_FLAGS_FIELD1_ONLY)) == 0)
+
+// Bits in the copy protection flags
+
+#define CODEC_FLAGS_PROTECTED 0x01 //!< Copy protection flags
+#define CODEC_FLAGS_PROTECTION_MASK 0x01 //!< Unused bits must be zero
+
+/*!
+ @brief Check that the bitstream is aligned to a segment boundary
+
+ This function definition duplicates the same function in common/src/syntax.c,
+ but that file includes definitions intended only for the encoder.
+
+ @todo Remove duplicate function definitions.
+ */
+bool IsAlignedSegment(BITSTREAM *stream)
+{
+ return (stream->count == 0 || stream->count == bit_word_count);
+}
+
+/*!
+ @brief Convert the tag to an optional tag
+
+ An optional tag has a negative value.
+*/
+TAGWORD OptionalTag(TAGWORD tag)
+{
+ return ((tag < 0) ? tag : neg(tag));
+}
+
+/*!
+ @brief Convert the tag to a required tag
+
+ An optional tag has a negative value.
+*/
+TAGWORD RequiredTag(TAGWORD tag)
+{
+ return ((tag >= 0) ? tag : neg(tag));
+}
+
+
+/*!
+ @brief Check that the bitstream is aligned to a tag word boundary
+
+ @todo Check the places in the code where this function is used to
+ determine whether the bitstream should actually be aligned to a
+ segment boundary.
+*/
+bool IsAlignedTag(BITSTREAM *stream)
+{
+ return ((stream->count % BITSTREAM_TAG_SIZE) == 0);
+}
+
+/*!
+ @brief Pack the vector of prescale values into a single word
+
+ The wavelet transform uses a vector of prescale values indexed by the
+ wavelet level with the input image at level zero to specify the amount
+ of prescaling that should be performed on the input the wavelet transform.
+
+ This routine packs the prescale values into a segment value that can be
+ written into the bitstream.
+*/
+TAGWORD PackTransformPrescale(TRANSFORM *transform)
+{
+ TAGWORD packed_prescale = 0;
+ int i;
+
+ // Encode the prescale values that are actually used
+ for (i = 0; i < MAX_WAVELET_COUNT; i++)
+ {
+ assert((transform->prescale[i] & ~0x03) == 0);
+ packed_prescale += transform->prescale[i] << (14 - i * 2);
+ }
+
+ // The remaining prescale values with filled with zeros
+
+ return packed_prescale;
+}
+
diff --git a/gpr/source/lib/vc5_common/syntax.h b/gpr/source/lib/vc5_common/syntax.h
new file mode 100755
index 0000000..699c72e
--- /dev/null
+++ b/gpr/source/lib/vc5_common/syntax.h
@@ -0,0 +1,129 @@
+/*! @file syntax.h
+ *
+ * @brief Declaration of bitstream elements and functions that define the syntax
+ * of an encoded sample.
+ *
+ * @version 1.0.0
+ *
+ * (C) Copyright 2018 GoPro Inc (http://gopro.com/).
+ *
+ * Licensed under either:
+ * - Apache License, Version 2.0, http://www.apache.org/licenses/LICENSE-2.0
+ * - MIT license, http://opensource.org/licenses/MIT
+ * at your option.
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef SYNTAX_H
+#define SYNTAX_H
+
+#define CODEC_TAG_SIZE 16 //!< Size of a codec tag (in bits)
+#define CODEC_TAG_MASK 0xFFFF //!< Mask for usable part of tag or value
+
+typedef uint32_t SEGMENT; //!< The bitstream is a sequence of segments
+
+typedef int16_t TAGWORD; //!< Bitstream tag or value
+
+//! Number of bits in a tag or value
+static const BITCOUNT tagword_count = 16;
+
+//! Number of bits in a segment (tag value pair)
+static const BITCOUNT segment_count = 32;
+
+typedef union tagvalue //!< Bitstream tag and value pair
+{
+ struct { // Fields are in the order for byte swapping
+ TAGWORD value;
+ TAGWORD tag;
+ } tuple; //!< Tag value pair as separate members
+
+ uint32_t longword; //!< Tag value pair as a int32_t word
+
+} TAGVALUE;
+
+/*!
+ @brief Values corresponding to the special codewords
+
+ Special codewords are inserted into an entropy coded band to
+ mark certain locations in the bitstream. For example, the end
+ of an encoded band is marked by the band end codeword. Special
+ codewords are recorded in the codebook as entries that have a
+ run length of zero. The value indicates the syntax element that
+ is represented by the codeword.
+*/
+typedef enum _special_marker
+{
+ SPECIAL_MARKER_BAND_END = 1,
+
+} SPECIAL_MARKER;
+
+
+// The encoded quality is inserted into the bitstream using two tag value pairs
+#define ENCODED_QUALITY_LOW_SHIFT 0 //!< Shift for the low part of the quality
+#define ENCODED_QUALITY_LOW_MASK 0xFFFF //!< Mask for the low part of the quality
+#define ENCODED_QUALITY_HIGH_SHIFT 16 //!< Shift for the high part of the quality
+#define ENCODED_QUALITY_HIGH_MASK 0xFFFF //!< Mask for the high part of the quality
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+TAGWORD RequiredTag(TAGWORD tag);
+
+//TAGVALUE GetSegment(BITSTREAM *stream);
+
+//TAGWORD GetValue(BITSTREAM *stream, int tag);
+
+// Output a tagged value with double word alignment
+CODEC_ERROR PutTagPair(BITSTREAM *stream, int tag, int value);
+
+// Output an optional tagged value
+CODEC_ERROR PutTagPairOptional(BITSTREAM *stream, int tag, int value);
+
+// Output a tag that marks a place in the bitstream for debugging
+CODEC_ERROR PutTagMarker(BITSTREAM *stream, uint32_t marker, int size);
+
+TAGWORD OptionalTag(TAGWORD tag);
+
+//bool IsTagOptional(TAGWORD tag);
+
+//bool IsTagRequired(TAGWORD tag);
+
+//bool IsValidSegment(BITSTREAM *stream, TAGVALUE segment, TAGWORD tag);
+
+//CODEC_ERROR AlignBitsTag(BITSTREAM *stream);
+
+bool IsLowPassHeaderMarker(int marker);
+bool IsLowPassBandMarker(int marker);
+bool IsHighPassBandMarker(int marker);
+
+bool IsAlignedTag(BITSTREAM *stream);
+
+bool IsAlignedSegment(BITSTREAM *stream);
+
+// Write an index block for the sample bands
+CODEC_ERROR PutGroupIndex(BITSTREAM *stream,
+ void *index_table[],
+ int index_table_length,
+ size_t *channel_size_table_offset);
+
+TAGWORD PackTransformPrescale(TRANSFORM *transform);
+
+//TODO: Move other declarations for routines that write syntax elements here
+struct _encoder ;
+
+CODEC_ERROR PutFrameStructureFlags(struct _encoder *encoder, BITSTREAM *stream);
+
+// Output a tag and marker before the lowpass coefficients for debugging
+CODEC_ERROR PutVideoLowpassMarker(BITSTREAM *stream);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // SYNTAX_H
diff --git a/gpr/source/lib/vc5_common/table17.inc b/gpr/source/lib/vc5_common/table17.inc
new file mode 100755
index 0000000..973f297
--- /dev/null
+++ b/gpr/source/lib/vc5_common/table17.inc
@@ -0,0 +1,290 @@
+/*! @file bitstream.h
+ *
+ * @brief Declaration of the bitstream data structure.
+ *
+ * @version 1.0.0
+ *
+ * (C) Copyright 2018 GoPro Inc (http://gopro.com/).
+ *
+ * Licensed under either:
+ * - Apache License, Version 2.0, http://www.apache.org/licenses/LICENSE-2.0
+ * - MIT license, http://opensource.org/licenses/MIT
+ * at your option.
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+RLVTABLE(264) table17 =
+{
+ 264,
+ {
+ {1, 0x00000000, 1, 0}, // m0
+ {2, 0x00000002, 1, 1}, // m1
+ {3, 0x00000007, 1, 2}, // m2
+ {5, 0x00000019, 1, 3}, // m3
+ {6, 0x00000030, 1, 4}, // m4
+ {6, 0x00000036, 1, 5}, // m5
+ {7, 0x0000006F, 1, 8}, // m8
+ {7, 0x00000063, 1, 6}, // m6
+ {7, 0x00000069, 12, 0}, // z12
+ {7, 0x0000006B, 1, 7}, // m7
+ {8, 0x000000D1, 20, 0}, // z20
+ {8, 0x000000D4, 1, 9}, // m9
+ {8, 0x000000DC, 1, 10}, // m10
+ {9, 0x00000189, 1, 11}, // m11
+ {9, 0x0000018A, 32, 0}, // z32
+ {9, 0x000001A0, 1, 12}, // m12
+ {9, 0x000001AB, 1, 13}, // m13
+ {10, 0x00000377, 1, 18}, // m18
+ {10, 0x00000310, 1, 14}, // m14
+ {10, 0x00000316, 1, 15}, // m15
+ {10, 0x00000343, 60, 0}, // z60
+ {10, 0x00000354, 1, 16}, // m16
+ {10, 0x00000375, 1, 17}, // m17
+ {11, 0x00000623, 1, 19}, // m19
+ {11, 0x00000684, 1, 20}, // m20
+ {11, 0x00000685, 100, 0}, // z100
+ {11, 0x000006AB, 1, 21}, // m21
+ {11, 0x000006EC, 1, 22}, // m22
+ {12, 0x00000DDB, 1, 29}, // m29
+ {12, 0x00000C5C, 1, 24}, // m24
+ {12, 0x00000C5E, 1, 25}, // m25
+ {12, 0x00000C44, 1, 23}, // m23
+ {12, 0x00000D55, 1, 26}, // m26
+ {12, 0x00000DD1, 1, 27}, // m27
+ {12, 0x00000DD3, 1, 28}, // m28
+ {13, 0x00001BB5, 1, 35}, // m35
+ {13, 0x0000188B, 1, 30}, // m30
+ {13, 0x000018BB, 1, 31}, // m31
+ {13, 0x000018BF, 180, 0}, // z180
+ {13, 0x00001AA8, 1, 32}, // m32
+ {13, 0x00001BA0, 1, 33}, // m33
+ {13, 0x00001BA5, 320, 0}, // z320
+ {13, 0x00001BA4, 1, 34}, // m34
+ {14, 0x00003115, 1, 36}, // m36
+ {14, 0x00003175, 1, 37}, // m37
+ {14, 0x0000317D, 1, 38}, // m38
+ {14, 0x00003553, 1, 39}, // m39
+ {14, 0x00003768, 1, 40}, // m40
+ {15, 0x00006E87, 1, 46}, // m46
+ {15, 0x00006ED3, 1, 47}, // m47
+ {15, 0x000062E8, 1, 42}, // m42
+ {15, 0x000062F8, 1, 43}, // m43
+ {15, 0x00006228, 1, 41}, // m41
+ {15, 0x00006AA4, 1, 44}, // m44
+ {15, 0x00006E85, 1, 45}, // m45
+ {16, 0x0000C453, 1, 48}, // m48
+ {16, 0x0000C5D3, 1, 49}, // m49
+ {16, 0x0000C5F3, 1, 50}, // m50
+ {16, 0x0000DDA4, 1, 53}, // m53
+ {16, 0x0000DD08, 1, 51}, // m51
+ {16, 0x0000DD0C, 1, 52}, // m52
+ {17, 0x0001BB4B, 1, 61}, // m61
+ {17, 0x0001BB4A, 1, 60}, // m60
+ {17, 0x00018BA5, 1, 55}, // m55
+ {17, 0x00018BE5, 1, 56}, // m56
+ {17, 0x0001AA95, 1, 57}, // m57
+ {17, 0x0001AA97, 1, 58}, // m58
+ {17, 0x000188A4, 1, 54}, // m54
+ {17, 0x0001BA13, 1, 59}, // m59
+ {18, 0x00031748, 1, 62}, // m62
+ {18, 0x000317C8, 1, 63}, // m63
+ {18, 0x00035528, 1, 64}, // m64
+ {18, 0x0003552C, 1, 65}, // m65
+ {18, 0x00037424, 1, 66}, // m66
+ {18, 0x00037434, 1, 67}, // m67
+ {18, 0x00037436, 1, 68}, // m68
+ {19, 0x00062294, 1, 69}, // m69
+ {19, 0x00062E92, 1, 70}, // m70
+ {19, 0x00062F92, 1, 71}, // m71
+ {19, 0x0006AA52, 1, 72}, // m72
+ {19, 0x0006AA5A, 1, 73}, // m73
+ {19, 0x0006E86A, 1, 75}, // m75
+ {19, 0x0006E86E, 1, 76}, // m76
+ {19, 0x0006E84A, 1, 74}, // m74
+ {20, 0x000C452A, 1, 77}, // m77
+ {20, 0x000C5D27, 1, 78}, // m78
+ {20, 0x000C5F26, 1, 79}, // m79
+ {20, 0x000D54A6, 1, 80}, // m80
+ {20, 0x000D54B6, 1, 81}, // m81
+ {20, 0x000DD096, 1, 82}, // m82
+ {20, 0x000DD0D6, 1, 83}, // m83
+ {20, 0x000DD0DE, 1, 84}, // m84
+ {21, 0x00188A56, 1, 85}, // m85
+ {21, 0x0018BA4D, 1, 86}, // m86
+ {21, 0x0018BE4E, 1, 87}, // m87
+ {21, 0x0018BE4F, 1, 88}, // m88
+ {21, 0x001AA96E, 1, 89}, // m89
+ {21, 0x001BA12E, 1, 90}, // m90
+ {21, 0x001BA12F, 1, 91}, // m91
+ {21, 0x001BA1AF, 1, 92}, // m92
+ {21, 0x001BA1BF, 1, 93}, // m93
+ {22, 0x0037435D, 1, 99}, // m99
+ {22, 0x0037437D, 1, 100}, // m100
+ {22, 0x00317498, 1, 94}, // m94
+ {22, 0x0035529C, 1, 95}, // m95
+ {22, 0x0035529D, 1, 96}, // m96
+ {22, 0x003552DE, 1, 97}, // m97
+ {22, 0x003552DF, 1, 98}, // m98
+ {23, 0x0062E933, 1, 102}, // m102
+ {23, 0x0062295D, 1, 101}, // m101
+ {23, 0x006AA53D, 1, 103}, // m103
+ {23, 0x006AA53F, 1, 105}, // m105
+ {23, 0x006AA53E, 1, 104}, // m104
+ {23, 0x006E86B9, 1, 106}, // m106
+ {23, 0x006E86F8, 1, 107}, // m107
+ {24, 0x00D54A79, 1, 111}, // m111
+ {24, 0x00C5D265, 1, 109}, // m109
+ {24, 0x00C452B8, 1, 108}, // m108
+ {24, 0x00DD0D71, 1, 113}, // m113
+ {24, 0x00D54A78, 1, 110}, // m110
+ {24, 0x00DD0D70, 1, 112}, // m112
+ {24, 0x00DD0DF2, 1, 114}, // m114
+ {24, 0x00DD0DF3, 1, 115}, // m115
+ {25, 0x0188A5F6, 1, 225}, // m225
+ {25, 0x0188A5F5, 1, 189}, // m189
+ {25, 0x0188A5F4, 1, 188}, // m188
+ {25, 0x0188A5F3, 1, 203}, // m203
+ {25, 0x0188A5F2, 1, 202}, // m202
+ {25, 0x0188A5F1, 1, 197}, // m197
+ {25, 0x0188A5F0, 1, 207}, // m207
+ {25, 0x0188A5EF, 1, 169}, // m169
+ {25, 0x0188A5EE, 1, 223}, // m223
+ {25, 0x0188A5ED, 1, 159}, // m159
+ {25, 0x0188A5AA, 1, 235}, // m235
+ {25, 0x0188A5E3, 1, 152}, // m152
+ {25, 0x0188A5DF, 1, 192}, // m192
+ {25, 0x0188A589, 1, 179}, // m179
+ {25, 0x0188A5DD, 1, 201}, // m201
+ {25, 0x0188A578, 1, 172}, // m172
+ {25, 0x0188A5E0, 1, 149}, // m149
+ {25, 0x0188A588, 1, 178}, // m178
+ {25, 0x0188A5D6, 1, 120}, // m120
+ {25, 0x0188A5DB, 1, 219}, // m219
+ {25, 0x0188A5E1, 1, 150}, // m150
+ {25, 0x0188A587, 1, 127}, // m127
+ {25, 0x0188A59A, 1, 211}, // m211
+ {25, 0x0188A5C4, 1, 125}, // m125
+ {25, 0x0188A5EC, 1, 158}, // m158
+ {25, 0x0188A586, 1, 247}, // m247
+ {25, 0x0188A573, 1, 238}, // m238
+ {25, 0x0188A59C, 1, 163}, // m163
+ {25, 0x0188A5C8, 1, 228}, // m228
+ {25, 0x0188A5FB, 1, 183}, // m183
+ {25, 0x0188A5A1, 1, 217}, // m217
+ {25, 0x0188A5EB, 1, 168}, // m168
+ {25, 0x0188A5A8, 1, 122}, // m122
+ {25, 0x0188A584, 1, 128}, // m128
+ {25, 0x0188A5D2, 1, 249}, // m249
+ {25, 0x0188A599, 1, 187}, // m187
+ {25, 0x0188A598, 1, 186}, // m186
+ {25, 0x0188A583, 1, 136}, // m136
+ {25, 0x018BA4C9, 1, 181}, // m181
+ {25, 0x0188A5D0, 1, 255}, // m255
+ {25, 0x0188A594, 1, 230}, // m230
+ {25, 0x0188A582, 1, 135}, // m135
+ {25, 0x0188A5CB, 1, 233}, // m233
+ {25, 0x0188A5D8, 1, 222}, // m222
+ {25, 0x0188A5E7, 1, 145}, // m145
+ {25, 0x0188A581, 1, 134}, // m134
+ {25, 0x0188A5EA, 1, 167}, // m167
+ {25, 0x0188A5A9, 1, 248}, // m248
+ {25, 0x0188A5A6, 1, 209}, // m209
+ {25, 0x0188A580, 1, 243}, // m243
+ {25, 0x0188A5A0, 1, 216}, // m216
+ {25, 0x0188A59D, 1, 164}, // m164
+ {25, 0x0188A5C3, 1, 140}, // m140
+ {25, 0x0188A57F, 1, 157}, // m157
+ {25, 0x0188A5C0, 1, 239}, // m239
+ {25, 0x0188A5DE, 1, 191}, // m191
+ {25, 0x0188A5D4, 1, 251}, // m251
+ {25, 0x0188A57E, 1, 156}, // m156
+ {25, 0x0188A5C2, 1, 139}, // m139
+ {25, 0x0188A592, 1, 242}, // m242
+ {25, 0x0188A5CD, 1, 133}, // m133
+ {25, 0x0188A57D, 1, 162}, // m162
+ {25, 0x0188A5A3, 1, 213}, // m213
+ {25, 0x0188A5E8, 1, 165}, // m165
+ {25, 0x0188A5A2, 1, 212}, // m212
+ {25, 0x0188A57C, 1, 227}, // m227
+ {25, 0x0188A58E, 1, 198}, // m198
+ {25, 0x0188A5B3, 1, 236}, // m236
+ {25, 0x0188A5B2, 1, 234}, // m234
+ {25, 0x0188A5B1, 1, 117}, // m117
+ {25, 0x0188A5B0, 1, 215}, // m215
+ {25, 0x0188A5AF, 1, 124}, // m124
+ {25, 0x0188A5AE, 1, 123}, // m123
+ {25, 0x0188A5AD, 1, 254}, // m254
+ {25, 0x0188A5AC, 1, 253}, // m253
+ {25, 0x0188A5AB, 1, 148}, // m148
+ {25, 0x0188A5DA, 1, 218}, // m218
+ {25, 0x0188A5E4, 1, 146}, // m146
+ {25, 0x0188A5E5, 1, 147}, // m147
+ {25, 0x0188A5D9, 1, 224}, // m224
+ {25, 0x0188A5B5, 1, 143}, // m143
+ {25, 0x0188A5BC, 1, 184}, // m184
+ {25, 0x0188A5BD, 1, 185}, // m185
+ {25, 0x0188A5E9, 1, 166}, // m166
+ {25, 0x0188A5CC, 1, 132}, // m132
+ {25, 0x0188A585, 1, 129}, // m129
+ {25, 0x0188A5D3, 1, 250}, // m250
+ {25, 0x0188A5E2, 1, 151}, // m151
+ {25, 0x0188A595, 1, 119}, // m119
+ {25, 0x0188A596, 1, 193}, // m193
+ {25, 0x0188A5B8, 1, 176}, // m176
+ {25, 0x0188A590, 1, 245}, // m245
+ {25, 0x0188A5C9, 1, 229}, // m229
+ {25, 0x0188A5A4, 1, 206}, // m206
+ {25, 0x0188A5E6, 1, 144}, // m144
+ {25, 0x0188A5A5, 1, 208}, // m208
+ {25, 0x0188A5CE, 1, 137}, // m137
+ {25, 0x0188A5BF, 1, 241}, // m241
+ {25, 0x0188A572, 1, 237}, // m237
+ {25, 0x0188A59B, 1, 190}, // m190
+ {25, 0x0188A5BE, 1, 240}, // m240
+ {25, 0x0188A5C7, 1, 131}, // m131
+ {25, 0x0188A5CA, 1, 232}, // m232
+ {25, 0x0188A5D5, 1, 252}, // m252
+ {25, 0x0188A57B, 1, 171}, // m171
+ {25, 0x0188A58D, 1, 205}, // m205
+ {25, 0x0188A58C, 1, 204}, // m204
+ {25, 0x0188A58B, 1, 118}, // m118
+ {25, 0x0188A58A, 1, 214}, // m214
+ {25, 0x018BA4C8, 1, 180}, // m180
+ {25, 0x0188A5C5, 1, 126}, // m126
+ {25, 0x0188A5FA, 1, 182}, // m182
+ {25, 0x0188A5BB, 1, 175}, // m175
+ {25, 0x0188A5C1, 1, 141}, // m141
+ {25, 0x0188A5CF, 1, 138}, // m138
+ {25, 0x0188A5B9, 1, 177}, // m177
+ {25, 0x0188A5B6, 1, 153}, // m153
+ {25, 0x0188A597, 1, 194}, // m194
+ {25, 0x0188A5FE, 1, 160}, // m160
+ {25, 0x0188A5D7, 1, 121}, // m121
+ {25, 0x0188A5BA, 1, 174}, // m174
+ {25, 0x0188A591, 1, 246}, // m246
+ {25, 0x0188A5C6, 1, 130}, // m130
+ {25, 0x0188A5DC, 1, 200}, // m200
+ {25, 0x0188A57A, 1, 170}, // m170
+ {25, 0x0188A59F, 1, 221}, // m221
+ {25, 0x0188A5F9, 1, 196}, // m196
+ {25, 0x0188A5B4, 1, 142}, // m142
+ {25, 0x0188A5A7, 1, 210}, // m210
+ {25, 0x0188A58F, 1, 199}, // m199
+ {25, 0x0188A5FD, 1, 155}, // m155
+ {25, 0x0188A5B7, 1, 154}, // m154
+ {25, 0x0188A593, 1, 244}, // m244
+ {25, 0x0188A59E, 1, 220}, // m220
+ {25, 0x0188A5F8, 1, 195}, // m195
+ {25, 0x0188A5FF, 1, 161}, // m161
+ {25, 0x0188A5FC, 1, 231}, // m231
+ {25, 0x0188A579, 1, 173}, // m173
+ {25, 0x0188A5F7, 1, 226}, // m226
+ {26, 0x03114BA2, 1, 116}, // m116
+ {26, 0x03114BA3, 0, 1}, // c256
+ }
+};
diff --git a/gpr/source/lib/vc5_common/types.h b/gpr/source/lib/vc5_common/types.h
new file mode 100755
index 0000000..2e5f5b9
--- /dev/null
+++ b/gpr/source/lib/vc5_common/types.h
@@ -0,0 +1,94 @@
+/*! @file types.h
+ *
+ * @brief Definition of some common data types used by the codec.
+ *
+ * @version 1.0.0
+ *
+ * (C) Copyright 2018 GoPro Inc (http://gopro.com/).
+ *
+ * Licensed under either:
+ * - Apache License, Version 2.0, http://www.apache.org/licenses/LICENSE-2.0
+ * - MIT license, http://opensource.org/licenses/MIT
+ * at your option.
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef TYPES_H
+#define TYPES_H
+
+//! Data type for Boolean variables
+typedef uint_fast8_t BOOLEAN;
+
+//! Data type for image and frame dimensions
+typedef uint_least16_t DIMENSION;
+
+//! Data type for an unsigned number (count) that can be the value in a tag-value pair
+typedef uint_least16_t COUNT;
+
+/*!
+ @brief Define a data type large enough to hold a quantization value
+
+ Define a data type that is large enough to hold any quantization value.
+ Older code assumed that the quantization data type was an int, but newer
+ could should use the QUANT data type. After all quantization values are
+ stored in a QUANT data type, the data type can be redefined as a byte.
+*/
+typedef int QUANT;
+
+/*!
+ @brief Integer value for the amount of prescale shift
+
+ @todo Redefine this data type to be uint_fast8_t?
+*/
+typedef uint16_t PRESCALE;
+
+
+/*!
+ @brief Number of bits in a component value
+*/
+typedef uint_least8_t PRECISION;
+
+enum
+{
+ PRECISION_MIN = 8,
+ PRECISION_MAX = 32,
+};
+
+/*!
+ @brief Data type for the channel number
+*/
+typedef uint_least8_t CHANNEL;
+
+/*!
+ @brief Data type for the bit mask that represents enabled parts
+
+ The bit mask indicates which parts of the VC-5 standard are enabled
+ at runtime.
+*/
+typedef uint32_t ENABLED_PARTS;
+
+/*!
+ @brief Codec version number (major, minor, revision, build)
+
+ The major and minor product numbers identify versions that are released.
+ Revision numbers are used to identify interim releases for bug fixes.
+ The build number is incremented for every build, independent of product
+ numbering, to uniquely identify every build that is a release candidate.
+*/
+typedef struct _version
+{
+ uint8_t major; //!< Major product number
+ uint8_t minor; //!< Minor product number
+ uint8_t revision; //!< Product revision
+ uint8_t padding; //!< Padding to a multiple of 4 bytes
+ uint32_t build; //!< Unique number for each codec build
+} VERSION;
+
+#define VERSION_INITIALIZER(major, minor, revision, build) {major, minor, revision, 0, build}
+
+#endif // TYPES_H
diff --git a/gpr/source/lib/vc5_common/unique.h b/gpr/source/lib/vc5_common/unique.h
new file mode 100755
index 0000000..b90942e
--- /dev/null
+++ b/gpr/source/lib/vc5_common/unique.h
@@ -0,0 +1,42 @@
+/*! @file unique.h
+ *
+ * @brief Declaration of data structures for the unique image identifier.
+ *
+ * @version 1.0.0
+ *
+ * (C) Copyright 2018 GoPro Inc (http://gopro.com/).
+ *
+ * Licensed under either:
+ * - Apache License, Version 2.0, http://www.apache.org/licenses/LICENSE-2.0
+ * - MIT license, http://opensource.org/licenses/MIT
+ * at your option.
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef UNIQUE_H
+#define UNIQUE_H
+
+// Basic UMID label using the UUID method
+
+static const uint8_t UMID_label[] = {
+ 0x06, 0x0A, 0x2B, 0x34, 0x01, 0x01, 0x01, 0x05, 0x01, 0x01, 0x01, 0x20,
+};
+
+// Length of the UMID (in bytes)
+#define UMID_size 32
+
+// Length of the unique identifier chunk payload (in segments)
+#define UMID_length (UMID_size/sizeof(SEGMENT))
+
+// Length of the image sequence number (in bytes)
+#define sequence_number_size sizeof(uint32_t)
+
+// Length of the image sequence number (in segments)
+#define sequence_number_length (sequence_number_size/sizeof(SEGMENT))
+
+#endif // UNIQUE_H
diff --git a/gpr/source/lib/vc5_common/utilities.c b/gpr/source/lib/vc5_common/utilities.c
new file mode 100755
index 0000000..adc8678
--- /dev/null
+++ b/gpr/source/lib/vc5_common/utilities.c
@@ -0,0 +1,82 @@
+/*! @file utilities.c
+ *
+ * @brief The utilities in this file are included to allow the codec to be tested.
+ *
+ * @version 1.0.0
+ *
+ * (C) Copyright 2018 GoPro Inc (http://gopro.com/).
+ *
+ * Licensed under either:
+ * - Apache License, Version 2.0, http://www.apache.org/licenses/LICENSE-2.0
+ * - MIT license, http://opensource.org/licenses/MIT
+ * at your option.
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "common.h"
+
+/*!
+ @brief Check that the enabled parts are correct
+*/
+CODEC_ERROR CheckEnabledParts(ENABLED_PARTS *enabled_parts_ref)
+{
+ ENABLED_PARTS enabled_parts = (*enabled_parts_ref);
+
+ // The elementary bitstream is always enabled
+ if ((enabled_parts & VC5_PART_MASK(VC5_PART_ELEMENTARY)) == 0) {
+ enabled_parts |= VC5_PART_MASK(VC5_PART_ELEMENTARY);
+ }
+
+ // The conformance specification is never enabled
+ enabled_parts &= ~((uint32_t)VC5_PART_MASK(VC5_PART_CONFORMANCE));
+
+ // Image formats must be enabled if subsampled color differences are enabled
+ if ((enabled_parts & VC5_PART_MASK(VC5_PART_COLOR_SAMPLING)) != 0) {
+ enabled_parts |= VC5_PART_MASK(VC5_PART_IMAGE_FORMATS);
+ }
+
+ // Check that the enabled parts were built at compile-time
+ //assert((enabled_parts & VC5_ENABLED_PARTS) == enabled_parts);
+ if (! ((enabled_parts & VC5_ENABLED_PARTS) == enabled_parts)) {
+ return CODEC_ERROR_ENABLED_PARTS;
+ }
+
+ // Return the correct enabled parts mask
+ *enabled_parts_ref = enabled_parts;
+ return CODEC_ERROR_OKAY;
+}
+
+/*!
+ @brief Verify that the enabled parts are correct
+*/
+CODEC_ERROR VerifyEnabledParts(ENABLED_PARTS enabled_parts)
+{
+ // The elementary bitstream must always be enabled
+ if ((enabled_parts & VC5_PART_MASK(VC5_PART_ELEMENTARY)) == 0) {
+ return CODEC_ERROR_ENABLED_PARTS;
+ }
+
+ // The conformance specification must not be enabled
+ if ((enabled_parts & VC5_PART_MASK(VC5_PART_CONFORMANCE)) != 0) {
+ return CODEC_ERROR_ENABLED_PARTS;
+ }
+
+ // Image formats must be enabled if subsampled color differences are enabled
+ if ((enabled_parts & VC5_PART_MASK(VC5_PART_COLOR_SAMPLING)) != 0 &&
+ (enabled_parts & VC5_PART_MASK(VC5_PART_IMAGE_FORMATS)) == 0) {
+ return CODEC_ERROR_ENABLED_PARTS;
+ }
+
+ // All enabled parts must be compiled into this codec implementation
+ if ((enabled_parts & VC5_ENABLED_PARTS) != enabled_parts) {
+ return CODEC_ERROR_ENABLED_PARTS;
+ }
+
+ // This codec implementation supports the enabled parts of the VC-5 standard
+ return CODEC_ERROR_OKAY;
+}
diff --git a/gpr/source/lib/vc5_common/utilities.h b/gpr/source/lib/vc5_common/utilities.h
new file mode 100755
index 0000000..851515b
--- /dev/null
+++ b/gpr/source/lib/vc5_common/utilities.h
@@ -0,0 +1,36 @@
+/*! @file utilities.c
+ *
+ * @brief Utility routines used by the code for testing the codec.
+ *
+ * @version 1.0.0
+ *
+ * (C) Copyright 2018 GoPro Inc (http://gopro.com/).
+ *
+ * Licensed under either:
+ * - Apache License, Version 2.0, http://www.apache.org/licenses/LICENSE-2.0
+ * - MIT license, http://opensource.org/licenses/MIT
+ * at your option.
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef UTILITIES_H
+#define UTILITIES_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+ CODEC_ERROR CheckEnabledParts(ENABLED_PARTS *enabled_parts_ref);
+
+ CODEC_ERROR VerifyEnabledParts(ENABLED_PARTS enabled_parts);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // UTILITIES_H
diff --git a/gpr/source/lib/vc5_common/vc5_common.h b/gpr/source/lib/vc5_common/vc5_common.h
new file mode 100644
index 0000000..a83dc41
--- /dev/null
+++ b/gpr/source/lib/vc5_common/vc5_common.h
@@ -0,0 +1,34 @@
+/*! @file vc5_common.h
+ *
+ * @brief Declaration of items that are used by encoder and decoder API
+ *
+ * @version 1.0.0
+ *
+ * (C) Copyright 2018 GoPro Inc (http://gopro.com/).
+ *
+ * Licensed under either:
+ * - Apache License, Version 2.0, http://www.apache.org/licenses/LICENSE-2.0
+ * - MIT license, http://opensource.org/licenses/MIT
+ * at your option.
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef VC5_COMMON_H
+#define VC5_COMMON_H
+
+#include "config.h"
+
+// =================================================================================================
+// VC5 version numbering
+// =================================================================================================
+
+#define VC5_VERSION_MAJOR 1
+#define VC5_VERSION_MINOR 0
+#define VC5_VERSION_REVISION 0
+
+#endif // VC5_COMMON_H
diff --git a/gpr/source/lib/vc5_common/wavelet.c b/gpr/source/lib/vc5_common/wavelet.c
new file mode 100755
index 0000000..ec7e31a
--- /dev/null
+++ b/gpr/source/lib/vc5_common/wavelet.c
@@ -0,0 +1,519 @@
+/*! @file wavelet.c
+ *
+ * @brief Implementation of the module for wavelet data structures and transforms
+ *
+ * @version 1.0.0
+ *
+ * (C) Copyright 2018 GoPro Inc (http://gopro.com/).
+ *
+ * Licensed under either:
+ * - Apache License, Version 2.0, http://www.apache.org/licenses/LICENSE-2.0
+ * - MIT license, http://opensource.org/licenses/MIT
+ * at your option.
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "common.h"
+
+/*!
+ @brief Table of prescale values for the spatial wavelet transform
+
+ Each prescale value is indexed by the wavelet level. Index level zero
+ corresponds to the input frame, the other prescale values correspond to
+ wavelets in the transform: frame, spatial, spatial, ...
+
+ Note that the prescale values depend on the encoded precision. The default
+ precale values are for 10-bit precision and the actual will depend on the
+ encoded precision.
+*/
+const int spatial_prescale[] = {0, 2, 0, 0, 0, 0, 0, 0};
+
+/*!
+ @brief Initialize a wavelet data structure with the specified dimensions
+*/
+CODEC_ERROR InitWavelet(WAVELET *wavelet, DIMENSION width, DIMENSION height)
+{
+ assert(wavelet != NULL);
+ if (! (wavelet != NULL)) {
+ return CODEC_ERROR_NULLPTR;
+ }
+
+ memset(wavelet, 0, sizeof(WAVELET));
+
+ wavelet->width = width;
+ wavelet->height = height;
+ wavelet->band_count = 4;
+
+ return CODEC_ERROR_OKAY;
+}
+
+/*!
+ @brief Allocate a wavelet data structure with the specified dimensions
+*/
+CODEC_ERROR AllocWavelet(gpr_allocator *allocator, WAVELET *wavelet, DIMENSION width, DIMENSION height)
+{
+ // Initialize the fields in the wavelet data structure
+ InitWavelet(wavelet, width, height);
+
+ if (width > 0 && height > 0)
+ {
+ int band;
+
+ //TODO: Align the pitch?
+ DIMENSION pitch = width * sizeof(PIXEL);
+
+ size_t band_data_size = height * pitch;
+
+ PIXEL* data_all_bands = (PIXEL *)allocator->Alloc(band_data_size * MAX_BAND_COUNT);
+
+ if ( data_all_bands == NULL )
+ {
+ ReleaseWavelet(allocator, wavelet);
+ return CODEC_ERROR_OUTOFMEMORY;
+ }
+
+ // Allocate the wavelet bands
+ for (band = 0; band < MAX_BAND_COUNT; band++)
+ {
+ wavelet->data[band] = data_all_bands + band * height * width;
+ }
+
+ wavelet->pitch = pitch;
+ }
+
+ return CODEC_ERROR_OKAY;
+}
+
+/*!
+ @brief Release all resources allocated to the wavelet
+
+ The wavelet data structure itself is not reallocated.
+*/
+CODEC_ERROR ReleaseWavelet(gpr_allocator *allocator, WAVELET *wavelet)
+{
+ int band;
+
+ PIXEL* data_all_bands = wavelet->data[0];
+
+ allocator->Free(data_all_bands);
+
+ for (band = 0; band < MAX_BAND_COUNT; band++) {
+ wavelet->data[band] = NULL;
+ }
+
+ return CODEC_ERROR_OKAY;
+}
+
+/*!
+ @brief Create and allocate a wavelet data structure
+*/
+WAVELET *CreateWavelet(gpr_allocator *allocator, DIMENSION width, DIMENSION height)
+{
+ CODEC_ERROR error = CODEC_ERROR_OKAY;
+
+ if (width > 0 && height > 0)
+ {
+ // Allocate the image data structure for the wavelet
+ WAVELET *wavelet = (WAVELET *)allocator->Alloc(sizeof(WAVELET));
+ assert(wavelet != NULL);
+ if (! (wavelet != NULL)) {
+ return NULL;
+ }
+
+ // Allocate space for the wavelet bands
+ error = AllocWavelet(allocator, wavelet, width, height);
+ if (error == CODEC_ERROR_OKAY) {
+ return wavelet;
+ }
+
+ // Avoid a memory leak
+ DeleteWavelet(allocator, wavelet);
+ }
+
+ return NULL;
+}
+
+/*!
+ @brief Release all resources the free the wavelet data structure
+*/
+CODEC_ERROR DeleteWavelet(gpr_allocator *allocator, WAVELET *wavelet)
+{
+ ReleaseWavelet(allocator, wavelet);
+ allocator->Free(wavelet);
+ return CODEC_ERROR_OKAY;
+}
+
+/*!
+ @brief Compute the amount of scaling for each band in the wavelet tree
+
+ The forward wavelet transforms increase the number of bits required to
+ represent the coefficients. This routine computes the amount by which
+ the input pixels are scaled as each band is computed. The horizontal or
+ vertical transform scales the lowpass values by one bit, but the hgihpass
+ values are not scaled. The lowpass wavelet band will be scaled by two
+ bits, the first and second highpass bands will be scaled by one bit, and
+ the third highpass band will not be scaled.
+*/
+CODEC_ERROR SetTransformScale(TRANSFORM *transform)
+{
+ //int num_wavelets = 3;
+ int num_spatial = 2;
+
+ int num_lowpass_spatial; // Number of spatial transforms for lowpass temporal band
+ //int num_highpass_spatial; // Number of spatial transforms for highpass temporal band
+ int num_frame_wavelets; // Number of frame wavelets at the base of the pyramid
+
+ // Area of the temporal lowpass filter
+ int temporal_lowpass_area = 2;
+
+ // Area of the each wavelet filter
+ int horizontal_lowpass_area = 2;
+ int vertical_lowpass_area = 2;
+
+ // Combination of the horizontal and vertical wavelet transforms
+ int spatial_lowpass_area = (horizontal_lowpass_area * vertical_lowpass_area);
+
+ int temporal_lowpass_scale;
+ int temporal_highpass_scale;
+
+ WAVELET *wavelet = NULL;
+ //WAVELET *temporal;
+
+ int k;
+ int i;
+
+ // Coefficients in each band are scaled by the forward wavelet filters
+ int scale[4] = {1, 1, 1, 1};
+
+ // Compute the number of frame and spatial wavelets
+ num_frame_wavelets = 1;
+ num_lowpass_spatial = num_spatial;
+
+ // Compute the change in scale due to the filters used in the frame transform
+ temporal_lowpass_scale = temporal_lowpass_area * scale[0];
+ temporal_highpass_scale = scale[0];
+
+ // Compute the scale factors for the first wavelet
+ scale[0] = horizontal_lowpass_area * temporal_lowpass_scale;
+ scale[1] = temporal_lowpass_scale;
+ scale[2] = horizontal_lowpass_area * temporal_highpass_scale;
+ scale[3] = temporal_highpass_scale;
+
+ for (k = 0; k < num_frame_wavelets; k++)
+ {
+ wavelet = transform->wavelet[k];
+ assert(wavelet != NULL);
+ if (! (wavelet != NULL)) {
+ return CODEC_ERROR_UNEXPECTED;
+ }
+
+ wavelet->scale[0] = scale[0];
+ wavelet->scale[1] = scale[1];
+ wavelet->scale[2] = scale[2];
+ wavelet->scale[3] = scale[3];
+ }
+
+ // Compute the scale factors for the spatial wavelets
+ for (i = 0; i < num_lowpass_spatial; i++)
+ {
+ WAVELET *spatial = transform->wavelet[k++];
+ //int k;
+
+ assert(spatial != NULL);
+ if (! (spatial != NULL)) {
+ return CODEC_ERROR_UNEXPECTED;
+ }
+
+ assert(wavelet != NULL);
+ if (! (wavelet != NULL)) {
+ return CODEC_ERROR_UNEXPECTED;
+ }
+
+ // The lowpass band is the input to the spatial transform
+ temporal_lowpass_scale = wavelet->scale[0];
+
+ spatial->scale[0] = (spatial_lowpass_area * temporal_lowpass_scale);// >> _LOWPASS_PRESCALE;
+ spatial->scale[1] = (vertical_lowpass_area * temporal_lowpass_scale);// >> _LOWPASS_PRESCALE;
+ spatial->scale[2] = (horizontal_lowpass_area * temporal_lowpass_scale);// >> _LOWPASS_PRESCALE;
+ spatial->scale[3] = (temporal_lowpass_scale);// >> _LOWPASS_PRESCALE;
+
+ // The spatial wavelet is the input for the next level
+ wavelet = spatial;
+ }
+
+ return CODEC_ERROR_OKAY;
+}
+
+/*!
+ @brief Calculate the amount of prescaling required to prevent overflow
+
+ This routine calculates the arithmetic right shift that is applied to each
+ lowpass band prior to computation of the wavelet transform. Prescaling is
+ required to prevent overflow in the wavelet transforms.
+*/
+CODEC_ERROR SetTransformPrescale(TRANSFORM *transform, int precision)
+{
+ if (precision == 8)
+ {
+ memset(transform->prescale, 0, sizeof(transform->prescale));
+ return CODEC_ERROR_OKAY;
+ }
+ else if (precision == 10)
+ {
+ PRESCALE spatial_prescale[] = {0, 2, 2, 0, 0, 0, 0, 0};
+ memcpy(transform->prescale, spatial_prescale, sizeof(transform->prescale));
+ }
+ else if (precision == 12)
+ {
+ // frame, spatial, spatial, ...
+ PRESCALE spatial_prescale[] = {0, 2, 2, 0, 0, 0, 0, 0};
+ memcpy(transform->prescale, spatial_prescale, sizeof(transform->prescale));
+ }
+ else
+ {
+ //TODO: Need to handle other precisions
+ assert(0);
+ }
+
+ return CODEC_ERROR_OKAY;
+}
+
+/*!
+ @brief Return a mask for the specified wavelet band
+
+ The wavelet data structure contains a mask that indicates which
+ bands have been decoded.
+*/
+bool BandValidMask(int band)
+{
+ return (1 << band);
+}
+
+/*!
+ @brief Check that all bands are valid
+
+ The wavelet valid band mask is checked to determine whether
+ all of the bands in the wavelet have been decoded.
+*/
+bool BandsAllValid(WAVELET *wavelet)
+{
+ uint32_t all_bands_valid_mask = ((1 << wavelet->band_count) - 1);
+ return (wavelet->valid_band_mask == all_bands_valid_mask);
+}
+
+/*!
+ @brief Set the bit for the specified band in the valid band mask
+*/
+CODEC_ERROR UpdateWaveletValidBandMask(WAVELET *wavelet, int band)
+{
+ if (0 <= band && band < MAX_BAND_COUNT)
+ {
+ // Update the valid wavelet band flags
+ wavelet->valid_band_mask |= (1 << band);
+ return CODEC_ERROR_OKAY;
+ }
+ return CODEC_ERROR_INVALID_BAND;
+}
+
+/*!
+ @brief Compute the wavelet index from the subband index
+
+ All subbands that are encoded into the bitstream, including the
+ lowpass band at the highest wavelet level, are numbered in decode
+ order starting with zero for the lowpass band.
+
+ This routine maps the subband index to the index of the wavelet
+ that contains the specified subband.
+
+ Note the sifference between a wavelet band and a subband: The bands in
+ each wavelet are numbered starting at zero, while the subband index
+ applies to all wavelet bands in the encoded sample and does not include
+ the lowpass bands that are reconstructed during decoding from the bands
+ that were encoded into the bitstream.
+*/
+int SubbandWaveletIndex(int subband)
+{
+ //TODO: Adjust for other transform types and decoded resolutions
+ static int subband_wavelet_index[] = {2, 2, 2, 2, 1, 1, 1, 0, 0, 0};
+
+ assert(0 <= subband && subband < MAX_SUBBAND_COUNT);
+
+ // Return the index of the wavelet corresponding to this subband
+ return subband_wavelet_index[subband];
+}
+
+/*!
+ @brief Compute the index for the band in a wavelet from the subband index
+
+ See the explanation of wavelet bands and subbands in the documentation for
+ @ref SubbandWaveletIndex.
+*/
+int SubbandBandIndex(int subband)
+{
+ //TODO: Adjust for other transform types and decoded resolutions
+ static int subband_band_index[] = {0, 1, 2, 3, 1, 2, 3, 1, 2, 3};
+
+ assert(0 <= subband && subband < MAX_SUBBAND_COUNT);
+
+ // Return the index to the band within the wavelet
+ return subband_band_index[subband];
+}
+
+/*!
+ @brief Free the wavelets allocated for this transform
+*/
+CODEC_ERROR ReleaseTransform(gpr_allocator *allocator, TRANSFORM *transform)
+{
+ int wavelet_index;
+
+ for (wavelet_index = 0; wavelet_index < MAX_WAVELET_COUNT; wavelet_index++)
+ {
+ WAVELET *wavelet = transform->wavelet[wavelet_index];
+ if (wavelet != NULL) {
+ DeleteWavelet(allocator, wavelet);
+ transform->wavelet[wavelet_index] = NULL;
+ }
+ }
+
+ return CODEC_ERROR_OKAY;
+}
+
+/*!
+ @brief Return true if the prescale table is the same as the default table
+
+ This routine compares the prescale values used by the transform with the default
+ table of prescale values. If the actual prescale values are the same as the
+ default values, then the table of prescale values do not have to be encoded
+ into the bitstream.
+*/
+bool IsTransformPrescaleDefault(TRANSFORM *transform, int precision)
+{
+ int prescale_count = sizeof(transform->prescale) / sizeof(transform->prescale[0]);
+ int total = 0;
+ int i;
+
+ if (precision == 8)
+ {
+ for (i = 0; i < prescale_count; i++) {
+ total += transform->prescale[i];
+ }
+ return (total == 0);
+ }
+
+ for (i = 0; i < prescale_count; i++) {
+ total += absolute(transform->prescale[i] - spatial_prescale[i]);
+ }
+ for(; i < MAX_PRESCALE_COUNT; i++) {
+ total += spatial_prescale[i];
+ }
+ return (total == 0);
+}
+
+PIXEL *WaveletRowAddress(WAVELET *wavelet, int band, int row)
+{
+ assert(wavelet != NULL);
+ if (! (wavelet != NULL)) {
+ return NULL;
+ }
+
+ assert(0 <= row && row < wavelet->height);
+ if (! (0 <= row && row < wavelet->height))
+ {
+ return NULL;
+ }
+ else
+ {
+ uint8_t *address = (uint8_t *)wavelet->data[band];
+ address += row * wavelet->pitch;
+ return (PIXEL *)address;
+ }
+}
+
+void WaveletToRGB( gpr_allocator allocator, PIXEL* GS_src, PIXEL* RG_src, PIXEL* BG_src, DIMENSION src_width, DIMENSION src_height, DIMENSION src_pitch, RGB_IMAGE *dst_image,
+ int input_precision_bits, int output_precision_bits, gpr_rgb_gain* rgb_gain )
+{
+ TIMESTAMP("[BEG]", 2)
+
+ assert( dst_image );
+ assert( dst_image->buffer == NULL );
+
+ size_t size;
+ if( output_precision_bits == 8 )
+ {
+ size = src_width * src_height * 3;
+ }
+ else
+ {
+ size = src_width * src_height * 6;
+ }
+
+ dst_image->width = src_width;
+ dst_image->height = src_height;
+ dst_image->pitch = src_width * 3;
+ dst_image->size = size;
+ dst_image->buffer = allocator.Alloc( size );
+
+ const int32_t midpoint = (1 << (input_precision_bits - 1));
+ const int32_t shift = input_precision_bits - 12;
+
+ unsigned char* RGB_dst_8bits = dst_image->buffer;
+ unsigned short* RGB_dst_16bits = dst_image->buffer;
+
+ DIMENSION x, y;
+
+ for ( y = 0; y < src_height; y++)
+ {
+ for ( x = 0; x < src_width; x++)
+ {
+ int32_t G = GS_src[ (src_width - x - 1) + y * src_pitch];
+ int32_t R = 2 * ( RG_src[(src_width - x - 1) + y * src_pitch] - midpoint) + G;
+ int32_t B = 2 * ( BG_src[(src_width - x - 1) + y * src_pitch] - midpoint) + G;
+
+ // R,G,B are in 16-bit range since DecoderLogCurve outputs in 16 bits (although it's input is 12 bits)
+ R = DecoderLogCurve[ clamp_uint( (R >> shift), 12) ];
+ G = DecoderLogCurve[ clamp_uint( (G >> shift), 12) ];
+ B = DecoderLogCurve[ clamp_uint( (B >> shift), 12) ];
+
+ if( output_precision_bits == 8 )
+ {
+ R *= rgb_gain->r_gain_num;
+ R >>= rgb_gain->r_gain_pow2_den;
+
+ G *= rgb_gain->g_gain_num;
+ G >>= rgb_gain->g_gain_pow2_den;
+
+ B *= rgb_gain->b_gain_num;
+ B >>= rgb_gain->b_gain_pow2_den;
+
+ R = sqrtf((float)R);
+ G = sqrtf((float)G);
+ B = sqrtf((float)B);
+
+ R = clamp_uint8( R );
+ G = clamp_uint8( G );
+ B = clamp_uint8( B );
+
+ RGB_dst_8bits[3 * (x) + 0 + y * dst_image->pitch] = R;
+ RGB_dst_8bits[3 * (x) + 1 + y * dst_image->pitch] = G;
+ RGB_dst_8bits[3 * (x) + 2 + y * dst_image->pitch] = B;
+ }
+ else
+ {
+ R = clamp_uint16( R );
+ G = clamp_uint16( G );
+ B = clamp_uint16( B );
+
+ RGB_dst_16bits[3 * (x) + 0 + y * dst_image->pitch] = ( (R & 0x00FF) << 8 ) | ( (R & 0xFF00) >> 8 );
+ RGB_dst_16bits[3 * (x) + 1 + y * dst_image->pitch] = ( (G & 0x00FF) << 8 ) | ( (G & 0xFF00) >> 8 );
+ RGB_dst_16bits[3 * (x) + 2 + y * dst_image->pitch] = ( (B & 0x00FF) << 8 ) | ( (B & 0xFF00) >> 8 );
+ }
+ }
+ }
+
+ TIMESTAMP("[BEG]", 2)
+}
diff --git a/gpr/source/lib/vc5_common/wavelet.h b/gpr/source/lib/vc5_common/wavelet.h
new file mode 100755
index 0000000..cc5e2b6
--- /dev/null
+++ b/gpr/source/lib/vc5_common/wavelet.h
@@ -0,0 +1,126 @@
+/*! @file vlc.h
+ *
+ * @brief This file defines the data structures for the wavelet tree
+ *
+ * @version 1.0.0
+ *
+ * (C) Copyright 2018 GoPro Inc (http://gopro.com/).
+ *
+ * Licensed under either:
+ * - Apache License, Version 2.0, http://www.apache.org/licenses/LICENSE-2.0
+ * - MIT license, http://opensource.org/licenses/MIT
+ * at your option.
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef WAVELET_H
+#define WAVELET_H
+
+#include "common.h"
+
+/*!
+ @brief Data structure used for wavelets
+
+ This data structure is used for wavelets and can be used for images since
+ an image with multiple planar channels and a wavelet with multiple bands
+ are similar data structures.
+
+ The pitch is the distance between rows in bytes and must always be
+ an integer multiple of the pixel size in bytes.
+
+ The wavelet data structure contains an array of the scale factor for
+ each band that is the cummulative result of the application of the
+ wavelet transforms that created the wavelet.
+*/
+typedef struct _wavelet
+{
+ DIMENSION width; //!< Width of the image in pixels
+ DIMENSION height; //!< Height of the image in lines
+ DIMENSION pitch; //!< Distance between rows (in bytes)
+ uint16_t band_count; //!< Number of bands in a wavelet
+ uint32_t valid_band_mask; //!< Mask indicating which bands have been decoded
+ uint16_t scale[MAX_BAND_COUNT]; //!< Cumulative scaling by the wavelet transforms
+ QUANT quant[MAX_BAND_COUNT]; //!< Quantization value for each band
+ PIXEL *data[MAX_BAND_COUNT]; //!< Data buffer for each band
+
+} WAVELET;
+
+//! Indices for the wavelet bands in the image data structure
+typedef enum
+{
+ LL_BAND = 0, //!< Lowpass transform of lowpass intermediate result
+ LH_BAND, //!< Lowpass transform of highpass intermediate result
+ HL_BAND, //!< Highpass transform of lowpass intermediate result
+ HH_BAND //!< Highpass transform of highpass intermediate result
+} WAVELET_BAND;
+
+//! Types of wavelet tranforms
+enum
+{
+ WAVELET_TYPE_HORIZONTAL = 1,
+ WAVELET_TYPE_VERTICAL = 2,
+ WAVELET_TYPE_TEMPORAL = 4,
+
+ //! The baseline profile only supports spatial wavelets
+ WAVELET_TYPE_SPATIAL = (WAVELET_TYPE_HORIZONTAL | WAVELET_TYPE_VERTICAL),
+
+};
+
+//! Data structure for the wavelet tree (one channel)
+typedef struct _transform
+{
+ //! Prescale the input by the specified shift before the transform
+ PRESCALE prescale[MAX_WAVELET_COUNT];
+
+ //! List of the wavelets in the transform for one channel
+ WAVELET *wavelet[MAX_WAVELET_COUNT];
+
+} TRANSFORM;
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+ CODEC_ERROR AllocWavelet(gpr_allocator *allocator, WAVELET *wavelet, DIMENSION width, DIMENSION height);
+ CODEC_ERROR ReleaseWavelet(gpr_allocator *allocator, WAVELET *wavelet);
+
+ WAVELET *CreateWavelet(gpr_allocator *allocator, DIMENSION width, DIMENSION height);
+ CODEC_ERROR DeleteWavelet(gpr_allocator *allocator, WAVELET *wavelet);
+
+ CODEC_ERROR SetTransformScale(TRANSFORM *transform);
+
+ CODEC_ERROR SetTransformPrescale(TRANSFORM *transform, int precision);
+
+ bool BandValidMask(int band);
+
+ bool BandsAllValid(WAVELET *wavelet);
+ #define AllBandsValid BandsAllValid
+
+ CODEC_ERROR UpdateWaveletValidBandMask(WAVELET *wavelet, int band);
+
+ int SubbandWaveletIndex(int subband);
+
+ int SubbandBandIndex(int subband);
+
+ CODEC_ERROR ResetTransformFlags(TRANSFORM transform[], int transform_count);
+
+ CODEC_ERROR ReleaseTransform(gpr_allocator *allocator, TRANSFORM *transform);
+
+ bool IsTransformPrescaleDefault(TRANSFORM *transform, int precision);
+
+ PIXEL *WaveletRowAddress(WAVELET *wavelet, int band, int row);
+
+ void WaveletToRGB( gpr_allocator allocator, PIXEL* GS_src, PIXEL* RG_src, PIXEL* BG_src, DIMENSION src_width, DIMENSION src_height, DIMENSION src_pitch, RGB_IMAGE *dst_image,
+ int input_precision_bits, int output_precision_bits, gpr_rgb_gain* rgb_gain );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // WAVELET_H