summaryrefslogtreecommitdiff
path: root/gpr/source/lib/vc5_common/codec.c
blob: 2308f75003e5d4a0d3a047677a4b1d19c3470a45 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
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);
}