Code Coverage Report for src/decode/packet.c


Hit Total Coverage
Lines: 165 165 100.0%
Branches: 828 828 100.0%

1 /*
2 * libnogg: a decoder library for Ogg Vorbis streams
3 * Copyright (c) 2014-2024 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 (18/18) while (len > 0) {
34 (18/18) if (handle->segment_pos >= handle->segment_size) {
35 (36/36) 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 (18/18) 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 ASSERT(!handle->last_seg);
61
62 (18/18) if (handle->packet_mode) {
63 /* If we get here, there must be data remaining in the packet, since
64 * otherwise last_seg would have been set on the previous call. */
65 ASSERT(handle->packet_len > 0);
66 const int segment_size = min(handle->packet_len, 255);
67 memcpy(handle->segment_data, handle->packet_data, segment_size);
68 handle->segment_size = segment_size;
69 handle->segment_pos = 0;
70 handle->packet_data += segment_size;
71 handle->packet_len -= segment_size;
72 handle->last_seg = (handle->packet_len == 0);
73 return true;
74 }
75
76 (18/18) if (handle->next_seg == -1) {
77 (18/18) if (!start_page(handle, true)) {
78 handle->last_seg = true;
79 handle->last_seg_index = handle->segment_count - 1;
80 return false;
81 }
82 (18/18) if (!(handle->page_flag & PAGEFLAG_continued_packet)) {
83 return error(handle, VORBIS_continued_packet_flag_invalid);
84 }
85 }
86 const uint8_t len = handle->segments[handle->next_seg++];
87 (18/18) if (len < 255) {
88 handle->last_seg = true;
89 handle->last_seg_index = handle->next_seg - 1;
90 }
91 (18/18) if (handle->next_seg >= handle->segment_count) {
92 handle->next_seg = -1;
93 }
94 (36/36) if (len > 0 && !getn(handle, handle->segment_data, len)) {
95 return error(handle, VORBIS_unexpected_eof);
96 }
97 handle->segment_size = len;
98 handle->segment_pos = 0;
99 return len > 0;
100 }
101
102 /*-----------------------------------------------------------------------*/
103
104 void reset_page(stb_vorbis *handle)
105 {
106 handle->next_seg = -1;
107 }
108
109 /*-----------------------------------------------------------------------*/
110
111 bool start_page(stb_vorbis *handle, bool check_page_number)
112 {
113 uint8_t page_header[27];
114
115 (18/18) if (handle->scan_for_next_page) {
116 /* Find the beginning of a page. */
117 static const uint8_t capture_pattern[4] = "OggS";
118 int capture_index = 0;
119 do {
120 page_header[capture_index] = get8(handle);
121 (18/18) if (UNLIKELY(handle->eof)) {
122 return error(handle, VORBIS_reached_eof);
123 }
124 (18/18) if (page_header[capture_index] == capture_pattern[capture_index]) {
125 capture_index++;
126 (18/18) } else if (page_header[capture_index] == capture_pattern[0]) {
127 capture_index = 1;
128 } else {
129 capture_index = 0;
130 }
131 (18/18) } while (capture_index < 4);
132 (18/18) if (!getn(handle, page_header+4, sizeof(page_header)-4)) {
133 return error(handle, VORBIS_reached_eof);
134 }
135 } else {
136 /* Check that a new page can be read from the stream. */
137 (18/18) if (!getn(handle, page_header, sizeof(page_header))) {
138 return error(handle, VORBIS_reached_eof);
139 }
140 (18/18) if (memcmp(page_header, "OggS", 4) != 0) {
141 return error(handle, VORBIS_missing_capture_pattern);
142 }
143 }
144
145 /* Check the Ogg bitstream version. */
146 (18/18) if (page_header[4] != 0) {
147 return error(handle, VORBIS_invalid_stream_structure_version);
148 }
149
150 /* Parse the page header. */
151 handle->page_flag = page_header[5];
152 const uint64_t sample_pos = extract_64(&page_header[6]);
153 const uint32_t bitstream_id = extract_32(&page_header[14]);
154 const uint32_t page_number = extract_32(&page_header[18]);
155 UNUSED const uint32_t crc = extract_32(&page_header[22]);
156 handle->segment_count = page_header[26];
157
158 /* Read the list of segment lengths. */
159 (18/18) if (!getn(handle, handle->segments, handle->segment_count)) {
160 return error(handle, VORBIS_unexpected_eof);
161 }
162
163 /* Skip over pages belonging to other bitstreams. */
164 (18/18) if (handle->bitstream_id_set) {
165 (18/18) if (bitstream_id != handle->bitstream_id) {
166 unsigned int page_size = 0;
167 (18/18) for (int i = 0; i < handle->segment_count; i++) {
168 page_size += handle->segments[i];
169 }
170 skip(handle, page_size);
171 return start_page(handle, check_page_number);
172 }
173 } else {
174 handle->bitstream_id = bitstream_id;
175 handle->bitstream_id_set = true;
176 }
177
178 /* If this page has a sample position, find the packet it belongs to,
179 * which will be the complete packet in this page. */
180 handle->end_seg_with_known_loc = -2; // Assume no packet with sample pos.
181 (18/18) if (sample_pos != ~UINT64_C(0)) {
182 (18/18) for (int i = (int)handle->segment_count - 1; i >= 0; i--) {
183 /* An Ogg segment with size < 255 indicates the end of a packet. */
184 (18/18) if (handle->segments[i] < 255) {
185 handle->end_seg_with_known_loc = i;
186 handle->known_loc_for_packet = sample_pos;
187 break;
188 }
189 }
190 }
191
192 /* If we haven't started decoding yet, record this page as the first
193 * page containing audio. We'll keep updating the data until we
194 * actually start decoding, at which point first_decode will be cleared. */
195 (18/18) if (handle->first_decode) {
196 int len = 27 + handle->segment_count;
197 (18/18) for (int i = 0; i < handle->segment_count; i++) {
198 len += handle->segments[i];
199 }
200 /* p_first.page_start is set by start_decoder(). */
201 handle->p_first.page_end = handle->p_first.page_start + len;
202 handle->p_first.after_previous_page_start = handle->p_first.page_start;
203 handle->p_first.first_decoded_sample = 0;
204 handle->p_first.last_decoded_sample = sample_pos;
205 }
206
207 (18/18) if (handle->segment_count > 0) {
208 handle->next_seg = 0;
209 }
210
211 /* If this page is out of sequence, return an error. We wait until
212 * the end of the function to do this so that the page is set up for
213 * reading after the error is handled. */
214 const uint32_t last_page = handle->page_number;
215 handle->page_number = page_number;
216 (36/36) if (check_page_number && page_number != last_page + 1) {
217 return error(handle, VORBIS_wrong_page_number);
218 }
219
220 return true;
221 }
222
223 /*-----------------------------------------------------------------------*/
224
225 bool start_packet(stb_vorbis *handle)
226 {
227 ASSERT(!handle->packet_mode);
228
229 handle->last_seg = false;
230 handle->valid_bits = 0;
231 handle->segment_size = 0;
232 (18/18) while (handle->next_seg == -1) {
233 (18/18) if (!start_page(handle, true)) {
234 return false;
235 }
236 (18/18) if (handle->page_flag & PAGEFLAG_continued_packet) {
237 return error(handle, VORBIS_continued_packet_flag_invalid);
238 }
239 }
240 return true;
241 }
242
243 /*-----------------------------------------------------------------------*/
244
245 void start_packet_direct(stb_vorbis *handle, const void *packet,
246 int32_t packet_len)
247 {
248 ASSERT(handle->packet_mode);
249 ASSERT(packet != NULL);
250 ASSERT(packet_len > 0);
251
252 handle->packet_data = packet;
253 handle->packet_len = packet_len;
254 handle->last_seg = false;
255 ASSERT(next_segment(handle));
256 }
257
258 /*-----------------------------------------------------------------------*/
259
260 int get8_packet(stb_vorbis *handle)
261 {
262 handle->valid_bits = 0;
263 return get8_packet_raw(handle);
264 }
265
266 /*-----------------------------------------------------------------------*/
267
268 int32_t get32_packet(stb_vorbis *handle)
269 {
270 handle->valid_bits = 0;
271 uint8_t value_buf[4];
272 getn_packet_raw(handle, (char *)value_buf, sizeof(value_buf));
273 return (int32_t)extract_32(value_buf);
274 }
275
276 /*-----------------------------------------------------------------------*/
277
278 bool getn_packet(stb_vorbis *handle, void *buf, int len)
279 {
280 handle->valid_bits = 0;
281 return getn_packet_raw(handle, buf, len);
282 }
283
284 /*-----------------------------------------------------------------------*/
285
286 uint32_t get_bits(stb_vorbis *handle, int count)
287 {
288 (18/18) if (handle->valid_bits < 0) {
289 return 0;
290 }
291 (18/18) if (handle->valid_bits < count) {
292 (18/18) if (count > 24) {
293 /* We have to handle this case specially to avoid overflow of
294 * the bit accumulator. */
295 uint32_t value = get_bits(handle, 24);
296 value |= get_bits(handle, count-24) << 24;
297 return value;
298 }
299 (18/18) if (handle->valid_bits == 0) {
300 handle->acc = 0;
301 }
302 (18/18) while (handle->valid_bits < count) {
303 int32_t byte = get8_packet_raw(handle);
304 (18/18) if (UNLIKELY(byte == EOP)) {
305 handle->valid_bits = -1;
306 return 0;
307 }
308 handle->acc |= byte << handle->valid_bits;
309 handle->valid_bits += 8;
310 }
311 }
312 const uint32_t value = handle->acc & ((UINT32_C(1) << count) - 1);
313 handle->acc >>= count;
314 handle->valid_bits -= count;
315 return value;
316 }
317
318 /*-----------------------------------------------------------------------*/
319
320 bool flush_packet(stb_vorbis *handle)
321 {
322 (18/18) while (!handle->last_seg) {
323 (18/18) if (!next_segment(handle)) { // Only fails at EOF.
324 break;
325 }
326 }
327 (18/18) if (handle->eof) {
328 return error(handle, VORBIS_unexpected_eof);
329 }
330 handle->segment_size = 0;
331 handle->valid_bits = 0;
332 return true;
333 }
334
335 /*************************************************************************/
336 /*************************************************************************/