summaryrefslogtreecommitdiff
path: root/gpr/source/lib/vc5_encoder/sections.c
diff options
context:
space:
mode:
Diffstat (limited to 'gpr/source/lib/vc5_encoder/sections.c')
-rwxr-xr-xgpr/source/lib/vc5_encoder/sections.c293
1 files changed, 293 insertions, 0 deletions
diff --git a/gpr/source/lib/vc5_encoder/sections.c b/gpr/source/lib/vc5_encoder/sections.c
new file mode 100755
index 0000000..47efc0d
--- /dev/null
+++ b/gpr/source/lib/vc5_encoder/sections.c
@@ -0,0 +1,293 @@
+/*! @file sections.c
+ *
+ * @brief Implementation of code for encoding sections
+ *
+ * (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 "headers.h"
+
+#if VC5_ENABLED_PART(VC5_PART_SECTIONS)
+
+/*
+ @brief Write codec state parameters used for decoding the section into the bitstream
+
+ A section element may be decoded independently from other sections of the same type.
+ Concurrent decoding implies that all codec state parameters needed to decode a section
+ element be present in that section element.
+
+ In principle, it is only necessary to write the codec state parameters that may be changed
+ as other section elements are decoded independently. This sample encoder takes the simple
+ approach and writes all non-header codec state parameters into the bitstream.
+ */
+static CODEC_ERROR PutCodecState(ENCODER *encoder, BITSTREAM *stream, SECTION_NUMBER section_number)
+{
+ CODEC_STATE *codec = &encoder->codec;
+ TAGWORD prescale_shift = 0;
+
+ switch (section_number)
+ {
+ case SECTION_NUMBER_IMAGE:
+ assert(0);
+ break;
+
+ case SECTION_NUMBER_HEADER:
+ // No codec state parameters to be written into the bitstream
+ break;
+
+ case SECTION_NUMBER_CHANNEL:
+ // Encode the transform prescale for the first channel (assume all channels are the same)
+ prescale_shift = PackTransformPrescale(&encoder->transform[0]);
+
+ PutTagPair(stream, CODEC_TAG_ChannelNumber, codec->channel_number);
+ PutTagPair(stream, CODEC_TAG_SubbandNumber, codec->subband_number);
+ PutTagPair(stream, CODEC_TAG_LowpassPrecision, codec->lowpass_precision);
+ PutTagPair(stream, CODEC_TAG_Quantization, codec->band.quantization);
+ PutTagPair(stream, CODEC_TAG_PrescaleShift, prescale_shift);
+
+#if VC5_ENABLED_PART(VC5_PART_IMAGE_FORMATS)
+ if (!IsPartEnabled(encoder->enabled_parts, VC5_PART_IMAGE_FORMATS))
+ {
+ PutTagPair(stream, CODEC_TAG_ChannelWidth, codec->channel_width);
+ PutTagPair(stream, CODEC_TAG_ChannelHeight, codec->channel_height);
+ }
+#endif
+#if VC5_ENABLED_PART(VC5_PART_LAYERS)
+ if (IsPartEnabled(encoder->enabled_parts, VC5_PART_LAYERS))
+ {
+ PutTagPair(stream, CODEC_TAG_LayerNumber, codec->layer_number);
+ }
+#endif
+ break;
+
+ case SECTION_NUMBER_WAVELET:
+ PutTagPair(stream, CODEC_TAG_ChannelNumber, codec->channel_number);
+ PutTagPair(stream, CODEC_TAG_SubbandNumber, codec->subband_number);
+ PutTagPair(stream, CODEC_TAG_LowpassPrecision, codec->lowpass_precision);
+ //PutTagPair(stream, CODEC_TAG_Quantization, codec->band.quantization);
+ //PutTagPair(stream, CODEC_TAG_PrescaleShift, prescale_shift);
+ break;
+
+ case SECTION_NUMBER_SUBBAND:
+ PutTagPair(stream, CODEC_TAG_ChannelNumber, codec->channel_number);
+ PutTagPair(stream, CODEC_TAG_SubbandNumber, codec->subband_number);
+ PutTagPair(stream, CODEC_TAG_LowpassPrecision, codec->lowpass_precision);
+ PutTagPair(stream, CODEC_TAG_Quantization, codec->band.quantization);
+ //PutTagPair(stream, CODEC_TAG_PrescaleShift, prescale_shift);
+ break;
+
+ default:
+ assert(0);
+ return CODEC_ERROR_UNEXPECTED;
+ }
+
+ return CODEC_ERROR_OKAY;
+}
+
+/*
+ @brief Return true if specified type of section is enabled
+ */
+bool IsSectionEnabled(ENCODER *encoder, SECTION_NUMBER section_number)
+{
+ if (IsPartEnabled(encoder->enabled_parts, VC5_PART_SECTIONS))
+ {
+ if (SECTION_NUMBER_MINIMUM <= section_number && section_number <= SECTION_NUMBER_MAXIMUM)
+ {
+ uint32_t section_mask = SECTION_NUMBER_MASK(section_number);
+
+ if (encoder->enabled_sections & section_mask) {
+ return true;
+ }
+ }
+ }
+
+ // None of the predefined VC-5 sections are enabled
+ return false;
+}
+
+/*
+ @brief Start a new section with the specified tag
+
+ The location of the the tag-value pair that marks the beginning of the new
+ section is pushed onto a stack so that the tag-value pair can be updated with
+ the actual size of the section when the section is ended by a call to the
+ @ref EndSection function.
+ */
+CODEC_ERROR BeginSection(BITSTREAM *bitstream, TAGWORD tag)
+{
+ return PushSampleSize(bitstream, tag);
+}
+
+/*
+ @brief End a section
+
+ Update the tag-value pair that marks the section with the actual size of the section.
+ */
+CODEC_ERROR EndSection(BITSTREAM *bitstream)
+{
+ return PopSampleSize(bitstream);
+}
+
+/*!
+ @brief Write an image section header into the bitstream
+ */
+CODEC_ERROR BeginImageSection(struct _encoder *encoder, BITSTREAM *stream)
+{
+ assert(0);
+ return CODEC_ERROR_OKAY;
+}
+
+/*
+ @brief Write a section header for the bitstream header into the bitstream
+ */
+CODEC_ERROR BeginHeaderSection(struct _encoder *encoder, BITSTREAM *stream)
+{
+ // Write the section header for the bitstream header into the bitstream
+ return BeginSection(stream, CODEC_TAG_HeaderSectionTag);
+}
+
+/*
+ @brief Write a layer section header into the bitstream
+
+ Any codec state parameters that are required to decode the layer must be explicitly
+ written into the bitstream so that the layer sections and be decoded concurrently.
+ */
+CODEC_ERROR BeginLayerSection(struct _encoder *encoder, BITSTREAM *stream)
+{
+ CODEC_ERROR error = CODEC_ERROR_OKAY;
+
+ // Duplicate all codec state parameters required for decoding the layer
+ PutCodecState(encoder, stream, SECTION_NUMBER_LAYER);
+
+ // Write the section header for the layer into the bitstream
+ error = BeginSection(stream, CODEC_TAG_LayerSectionTag);
+
+ return error;
+}
+
+/*
+ @brief Write a channel section header into the bitstream
+
+ Any codec state parameters that are required to decode the channel must be explicitly
+ written into the bitstream so that the channel sections and be decoded concurrently.
+ */
+CODEC_ERROR BeginChannelSection(ENCODER *encoder, BITSTREAM *stream)
+{
+ CODEC_ERROR error = CODEC_ERROR_OKAY;
+
+ // Duplicate all codec state parameters required for decoding the channel
+ PutCodecState(encoder, stream, SECTION_NUMBER_CHANNEL);
+
+ // Write the section header for the channel into the bitstream
+ error = BeginSection(stream, CODEC_TAG_ChannelSectionTag);
+
+ return error;
+}
+
+/*
+ @brief Write a wavelet section header into the bitstream
+
+ Any codec state parameters that are required to decode the wavelet must be explicitly
+ written into the bitstream so that the wavelet sections and be decoded concurrently.
+ */
+CODEC_ERROR BeginWaveletSection(struct _encoder *encoder, BITSTREAM *stream)
+{
+ CODEC_ERROR error = CODEC_ERROR_OKAY;
+
+ // Duplicate all codec state parameters required for decoding the wavelet
+ PutCodecState(encoder, stream, SECTION_NUMBER_WAVELET);
+
+ // Write the section header for the wavelet into the bitstream
+ error = BeginSection(stream, CODEC_TAG_WaveletSectionTag);
+
+ return error;
+}
+
+/*
+ @brief Write a subband section header into the bitstream
+
+ Any codec state parameters that are required to decode the subband must be explicitly
+ written into the bitstream so that the subband sections and be decoded concurrently.
+ */
+CODEC_ERROR BeginSubbandSection(struct _encoder *encoder, BITSTREAM *stream)
+{
+ CODEC_ERROR error = CODEC_ERROR_OKAY;
+
+ // Duplicate all codec state parameters required for decoding the subband
+ PutCodecState(encoder, stream, SECTION_NUMBER_SUBBAND);
+
+ // Write the section header for the subband into the bitstream
+ error = BeginSection(stream, CODEC_TAG_SubbandSectionTag);
+
+ return error;
+}
+
+/*!
+ @brief Set the flags that indicate which sections in VC-5 Part 6 are enabled
+
+ The argument is a list of comma-separated integers for the section numbers
+ in the VC-5 Part 2 conformance specification that are enabled for this invocation
+ of the encoder.
+
+ Note: Enabling sections at runtime has no effect unless support for sections
+ is compiled into the program by enabling the corresponding compile-time switch
+ for VC-5 part 6 (sections).
+ */
+bool GetEnabledSections(const char *string, uint32_t *enabled_sections_out)
+{
+ if (string != NULL && enabled_sections_out != NULL)
+ {
+ // No sections are enabled by default
+ ENABLED_SECTIONS enabled_sections = 0;
+
+ const char *p = string;
+ assert(p != NULL);
+ while (*p != '\0')
+ {
+ char *q = NULL;
+ long section_number;
+ if (!isdigit((int)*p)) break;
+ section_number = strtol(p, &q, 10);
+
+ // Is the section number in bounds?
+ if (SECTION_NUMBER_MINIMUM <= section_number && section_number <= SECTION_NUMBER_MAXIMUM)
+ {
+ // Set the bit that corresponds to this section number
+ enabled_sections |= SECTION_NUMBER_MASK(section_number);
+
+ // Advance to the next section number in the command-line argument
+ p = (*q != '\0') ? q + 1 : q;
+ }
+ else
+ {
+ // Invalid section number
+ assert(0);
+ return false;
+ }
+ }
+
+ // Return the bit mask for the enabled sections
+ *enabled_sections_out = enabled_sections;
+
+ // Should have parsed all section numbers in the argument string
+ assert(*p == '\0');
+ return true;
+ }
+
+ // Invalid input arguments
+ return false;
+}
+
+
+#endif