Code Coverage Report for src/api/info.c


Hit Total Coverage
Lines: 28 28 100.0%
Branches: 126 126 100.0%

1 /*
2 * libnogg: a decoder library for Ogg Vorbis streams
3 * Copyright (c) 2014-2023 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
13
14 int vorbis_channels(const vorbis_t *handle)
15 {
16 return handle->channels;
17 }
18
19
20 uint32_t vorbis_rate(const vorbis_t *handle)
21 {
22 return handle->rate;
23 }
24
25
26 int64_t vorbis_length(const vorbis_t *handle)
27 {
28 /* stb_vorbis_stream_length_in_samples() doesn't differentiate between
29 * "empty file" and "error" in the return value, so we use the error
30 * flag to tell the difference. */
31 (void) stb_vorbis_get_error(handle->decoder);
32 const int64_t length = stb_vorbis_stream_length_in_samples(handle->decoder);
33 (18/18) if (stb_vorbis_get_error(handle->decoder) != VORBIS__no_error) {
34 return -1;
35 }
36 return length;
37 }
38
39
40 int32_t vorbis_bitrate(const vorbis_t *handle)
41 {
42 const int64_t length = vorbis_length(handle);
43 (18/18) if (length > 0) {
44 ASSERT(handle->rate != 0);
45 const int64_t bits_limit = (INT64_MAX - length/2) / handle->rate;
46 (18/18) if (handle->data_length > bits_limit / 8) {
47 return INT32_MAX;
48 }
49 const int64_t bits = handle->data_length * 8;
50 /* This next calculation is guaranteed not to overflow by the
51 * above check. */
52 const int64_t bitrate = (bits * handle->rate + length/2) / length;
53 (18/18) if (bitrate <= INT32_MAX) {
54 return (int32_t)bitrate;
55 } else {
56 return INT32_MAX;
57 }
58 } else { // Not a seekable stream.
59 const stb_vorbis_info info = stb_vorbis_get_info(handle->decoder);
60 (18/18) if (info.nominal_bitrate > 0) {
61 return info.nominal_bitrate;
62 (36/36) } else if (info.min_bitrate > 0 && info.max_bitrate > 0) {
63 return (info.min_bitrate + info.max_bitrate + 1) / 2;
64 } else {
65 return 0;
66 }
67 }
68 }