summaryrefslogtreecommitdiff
path: root/gpr/source/lib/vc5_decoder/syntax.c
blob: f0c4b5881af404040f6b1433fd4df12cc6720d3a (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
/*! @file syntax.c
 *
 *  @brief Implementation of functions for parsing the bitstream syntax of encoded samples.
 *
 *  (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"

//! Size of a tag or value (in bits)
#define BITSTREAM_TAG_SIZE				16

/*!
	@brief Read the next tag-valie pair from the bitstream.

	The next tag is read from the bitstream and the next value that
	immediately follows the tag in the bitstreeam are read from the
	bitstream.

	The value may be the length of the payload in bytes or the value
	may be a single scalar.  This routine only reads the next tag and
	value and does not intepret the tag or value and does not read any
	data that may follow the segment in the bitstream.

	The tag and value are interpreted by @ref UpdateCodecState and that
	routine may read additional information from the bitstream.

	If the value is the length of the payload then it encodes the number
	of bytes in the segment payload, not counting the segment header.
*/
TAGVALUE GetSegment(BITSTREAM *stream)
{
	TAGVALUE segment;
	segment.tuple.tag = (TAGWORD)GetBits(stream, 16);
	segment.tuple.value = (TAGWORD)GetBits(stream, 16);
	return segment;
}

/*!
	@brief Read the specified tag from the bitstream and return the value
*/
TAGWORD GetValue(BITSTREAM *stream, int tag)
{
	TAGVALUE segment = GetTagValue(stream);

	assert(stream->error == BITSTREAM_ERROR_OKAY);
	if (stream->error == BITSTREAM_ERROR_OKAY) {
		assert(segment.tuple.tag == tag);
		if (segment.tuple.tag == tag) {
			return segment.tuple.value;
		}
		else {
			stream->error = BITSTREAM_ERROR_BADTAG;
		}
	}

	// An error has occurred so return zero (error code was set above)
	return 0;
}

/*!
	@brief Read the next tag value pair from the bitstream
*/
TAGVALUE GetTagValue(BITSTREAM *stream)
{
	TAGVALUE segment = GetSegment(stream);
	while (segment.tuple.tag < 0) {
		segment = GetSegment(stream);
	}

	return segment;
}

/*!
	@brief Return true if the tag is optional
*/
bool IsTagOptional(TAGWORD tag)
{
	return (tag < 0);
}

/*!
	@brief Return true if the tag is required
*/
bool IsTagRequired(TAGWORD tag)
{
	return (tag >= 0);
}

/*!
	@brief Return true if a valid tag read from the bitstream
*/
bool IsValidSegment(BITSTREAM *stream, TAGVALUE segment, TAGWORD tag)
{
	return (stream->error == BITSTREAM_ERROR_OKAY &&
			segment.tuple.tag == tag);
}

/*!
	@brief Return true if the tag value pair has the specified tag and value
*/
bool IsTagValue(TAGVALUE segment, int tag, TAGWORD value)
{
	return (segment.tuple.tag == tag && segment.tuple.value == value);
}