Code Coverage Report for src/decode/packet.c


Hit Total Coverage
Lines: 143 144 99.3%
Branches: 176 180 97.7%

1 /*
2 * libnogg: a decoder library for Ogg Vorbis streams
3 * Copyright (c) 2014-2019 Andrew Church <achurch@achurch.org>
4 *
5 * This software may be copied and redistributed under certain conditions;
6 * see the file "COPYING" in the source code distribution for details.
7 * NO WARRANTY is provided with this software.
8 */
9
10 #include "include/nogg.h"
11 #include "src/common.h"
12 #include "src/decode/common.h"
13 #include "src/decode/inlines.h"
14 #include "src/decode/io.h"
15 #include "src/decode/packet.h"
16
17 #include <string.h>
18
19 /*************************************************************************/
20 /**************************** Helper routines ****************************/
21 /*************************************************************************/
22
23 /**
24 * getn_packet_raw: Read a sequence of bytes from the current packet.
25 *
26 * [Parameters]
27 * handle: Stream handle.
28 * [Return value]
29 * True on success, false on end of packet or error.
30 */
31 static bool getn_packet_raw(stb_vorbis *handle, char *buf, int len)
32 {
33 (4/4) while (len > 0) {
34 (4/4) if (handle->segment_pos >= handle->segment_size) {
35 (6/8) if (handle->last_seg || !next_segment(handle)) {
36 return false;
37 }
38 }
39 int to_copy = len;
40 /* Note that currently, this comparison always evaluates to false
41 * because this function is only called for data which is known to
42 * fully reside within the first segment of a packet. */
43 (2/4) if (to_copy > handle->segment_size - handle->segment_pos) {
44 to_copy = handle->segment_size - handle->segment_pos;
45 }
46 memcpy(buf, &handle->segment_data[handle->segment_pos], to_copy);
47 handle->segment_pos += to_copy;
48 buf += to_copy;
49 len -= to_copy;
50 }
51 return true;
52 }
53
54 /*************************************************************************/
55 /************************** Interface routines ***************************/
56 /*************************************************************************/
57
58 bool next_segment(stb_vorbis *handle)
59 {
60 (4/4) if (handle->last_seg) {
61 return false;
62 }
63 (4/4) if (handle->next_seg == -1) {
64 (4/4) if (!start_page(handle, true)) {
65 handle->last_seg = true;
66 handle->last_seg_index = handle->segment_count - 1;
67 return false;
68 }
69 (4/4) if (!(handle->page_flag & PAGEFLAG_continued_packet)) {
70 return error(handle, VORBIS_continued_packet_flag_invalid);
71 }
72 }
73 const uint8_t len = handle->segments[handle->next_seg++];
74 (4/4) if (len < 255) {
75 handle->last_seg = true;
76 handle->last_seg_index = handle->next_seg - 1;
77 }
78 (4/4) if (handle->next_seg >= handle->segment_count) {
79 handle->next_seg = -1;
80 }
81 (8/8) if (len > 0 && !getn(handle, handle->segment_data, len)) {
82 return error(handle, VORBIS_unexpected_eof);
83 }
84 handle->segment_size = len;
85 handle->segment_pos = 0;
86 return len > 0;
87 }
88
89 /*-----------------------------------------------------------------------*/
90
91 void reset_page(stb_vorbis *handle)
92 {
93 handle->next_seg = -1;
94 }
95
96 /*-----------------------------------------------------------------------*/
97
98 bool start_page(stb_vorbis *handle, bool check_page_number)
99 {
100 uint8_t page_header[27];
101
102 (4/4) if (handle->scan_for_next_page) {
103 /* Find the beginning of a page. */
104 static const uint8_t capture_pattern[4] = "OggS";
105 int capture_index = 0;
106 do {
107 page_header[capture_index] = get8(handle);
108 (4/4) if (UNLIKELY(handle->eof)) {
109 return error(handle, VORBIS_reached_eof);
110 }
111 (4/4) if (page_header[capture_index] == capture_pattern[capture_index]) {
112 capture_index++;
113 (4/4) } else if (page_header[capture_index] == capture_pattern[0]) {
114 capture_index = 1;
115 } else {
116 capture_index = 0;
117 }
118 (4/4) } while (capture_index < 4);
119 (4/4) if (!getn(handle, page_header+4, sizeof(page_header)-4)) {
120 return error(handle, VORBIS_reached_eof);
121 }
122 } else {
123 /* Check that a new page can be read from the stream. */
124 (4/4) if (!getn(handle, page_header, sizeof(page_header))) {
125 return error(handle, VORBIS_reached_eof);
126 }
127 (4/4) if (memcmp(page_header, "OggS", 4) != 0) {
128 return error(handle, VORBIS_missing_capture_pattern);
129 }
130 }
131
132 /* Check the Ogg bitstream version. */
133 (4/4) if (page_header[4] != 0) {
134 return error(handle, VORBIS_invalid_stream_structure_version);
135 }
136
137 /* Parse the page header. */
138 handle->page_flag = page_header[5];
139 const uint64_t sample_pos = extract_64(&page_header[6]);
140 const uint32_t bitstream_id = extract_32(&page_header[14]);
141 const uint32_t page_number = extract_32(&page_header[18]);
142 UNUSED const uint32_t crc = extract_32(&page_header[22]);
143 handle->segment_count = page_header[26];
144
145 /* Read the list of segment lengths. */
146 (4/4) if (!getn(handle, handle->segments, handle->segment_count)) {
147 return error(handle, VORBIS_unexpected_eof);
148 }
149
150 /* Skip over pages belonging to other bitstreams. */
151 (4/4) if (handle->bitstream_id_set) {
152 (4/4) if (bitstream_id != handle->bitstream_id) {
153 unsigned int page_size = 0;
154 (4/4) for (int i = 0; i < handle->segment_count; i++) {
155 page_size += handle->segments[i];
156 }
157 skip(handle, page_size);
158 return start_page(handle, check_page_number);
159 }
160 } else {
161 handle->bitstream_id = bitstream_id;
162 handle->bitstream_id_set = true;
163 }
164
165 /* If this page has a sample position, find the packet it belongs to,
166 * which will be the complete packet in this page. */
167 handle->end_seg_with_known_loc = -2; // Assume no packet with sample pos.
168 (4/4) if (sample_pos != ~UINT64_C(0)) {
169 (4/4) for (int i = (int)handle->segment_count - 1; i >= 0; i--) {
170 /* An Ogg segment with size < 255 indicates the end of a packet. */
171 (4/4) if (handle->segments[i] < 255) {
172 handle->end_seg_with_known_loc = i;
173 handle->known_loc_for_packet = sample_pos;
174 break;
175 }
176 }
177 }
178
179 /* If we haven't started decoding yet, record this page as the first
180 * page containing audio. We'll keep updating the data until we
181 * actually start decoding, at which point first_decode will be cleared. */
182 (4/4) if (handle->first_decode) {
183 int len = 27 + handle->segment_count;
184 (4/4) for (int i = 0; i < handle->segment_count; i++) {
185 len += handle->segments[i];
186 }
187 /* p_first.page_start is set by start_decoder(). */
188 handle->p_first.page_end = handle->p_first.page_start + len;
189 handle->p_first.after_previous_page_start = handle->p_first.page_start;
190 handle->p_first.first_decoded_sample = 0;
191 handle->p_first.last_decoded_sample = sample_pos;
192 }
193
194 (4/4) if (handle->segment_count > 0) {
195 handle->next_seg = 0;
196 }
197
198 /* If this page is out of sequence, return an error. We wait until
199 * the end of the function to do this so that the page is set up for
200 * reading after the error is handled. */
201 const uint32_t last_page = handle->page_number;
202 handle->page_number = page_number;
203 (8/8) if (check_page_number && page_number != last_page + 1) {
204 return error(handle, VORBIS_wrong_page_number);
205 }
206
207 return true;
208 }
209
210 /*-----------------------------------------------------------------------*/
211
212 bool start_packet(stb_vorbis *handle)
213 {
214 handle->last_seg = false;
215 handle->valid_bits = 0;
216 handle->segment_size = 0;
217 (4/4) while (handle->next_seg == -1) {
218 (4/4) if (!start_page(handle, true)) {
219 return false;
220 }
221 (4/4) if (handle->page_flag & PAGEFLAG_continued_packet) {
222 return error(handle, VORBIS_continued_packet_flag_invalid);
223 }
224 }
225 return true;
226 }
227
228 /*-----------------------------------------------------------------------*/
229
230 int get8_packet(stb_vorbis *handle)
231 {
232 handle->valid_bits = 0;
233 return get8_packet_raw(handle);
234 }
235
236 /*-----------------------------------------------------------------------*/
237
238 int32_t get32_packet(stb_vorbis *handle)
239 {
240 handle->valid_bits = 0;
241 uint8_t value_buf[4];
242 getn_packet_raw(handle, (char *)value_buf, sizeof(value_buf));
243 return (int32_t)extract_32(value_buf);
244 }
245
246 /*-----------------------------------------------------------------------*/
247
248 bool getn_packet(stb_vorbis *handle, void *buf, int len)
249 {
250 handle->valid_bits = 0;
251 return getn_packet_raw(handle, buf, len);
252 }
253
254 /*-----------------------------------------------------------------------*/
255
256 uint32_t get_bits(stb_vorbis *handle, int count)
257 {
258 (4/4) if (handle->valid_bits < 0) {
259 return 0;
260 }
261 (4/4) if (handle->valid_bits < count) {
262 (4/4) if (count > 24) {
263 /* We have to handle this case specially to avoid overflow of
264 * the bit accumulator. */
265 uint32_t value = get_bits(handle, 24);
266 value |= get_bits(handle, count-24) << 24;
267 return value;
268 }
269 (4/4) if (handle->valid_bits == 0) {
270 handle->acc = 0;
271 }
272 (4/4) while (handle->valid_bits < count) {
273 int32_t byte = get8_packet_raw(handle);
274 (4/4) if (UNLIKELY(byte == EOP)) {
275 handle->valid_bits = -1;
276 return 0;
277 }
278 handle->acc |= byte << handle->valid_bits;
279 handle->valid_bits += 8;
280 }
281 }
282 const uint32_t value = handle->acc & ((UINT32_C(1) << count) - 1);
283 handle->acc >>= count;
284 handle->valid_bits -= count;
285 return value;
286 }
287
288 /*-----------------------------------------------------------------------*/
289
290 bool flush_packet(stb_vorbis *handle)
291 {
292 (4/4) while (next_segment(handle)) { /*loop*/ }
293 (4/4) if (handle->eof) {
294 return error(handle, VORBIS_unexpected_eof);
295 }
296 handle->segment_size = 0;
297 handle->valid_bits = 0;
298 return true;
299 }
300
301 /*************************************************************************/
302 /*************************************************************************/