Coverage Report

Created: 2025-06-12 07:21

/src/mpv/audio/format.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Copyright (C) 2005 Alex Beregszaszi
3
 *
4
 * This file is part of mpv.
5
 *
6
 * mpv is free software; you can redistribute it and/or
7
 * modify it under the terms of the GNU Lesser General Public
8
 * License as published by the Free Software Foundation; either
9
 * version 2.1 of the License, or (at your option) any later version.
10
 *
11
 * mpv is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 * GNU Lesser General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU Lesser General Public
17
 * License along with mpv.  If not, see <http://www.gnu.org/licenses/>.
18
 */
19
20
#include <limits.h>
21
22
#include "common/common.h"
23
#include "format.h"
24
25
// number of bytes per sample, 0 if invalid/unknown
26
int af_fmt_to_bytes(int format)
27
121M
{
28
121M
    switch (af_fmt_from_planar(format)) {
29
1.27k
    case AF_FORMAT_U8:      return 1;
30
106M
    case AF_FORMAT_S16:     return 2;
31
4.24k
    case AF_FORMAT_S32:     return 4;
32
156
    case AF_FORMAT_S64:     return 8;
33
15.2M
    case AF_FORMAT_FLOAT:   return 4;
34
1
    case AF_FORMAT_DOUBLE:  return 8;
35
121M
    }
36
0
    if (af_fmt_is_spdif(format))
37
0
        return 2;
38
0
    return 0;
39
0
}
40
41
// All formats are considered signed, except explicitly unsigned int formats.
42
bool af_fmt_is_unsigned(int format)
43
62.6M
{
44
62.6M
    return format == AF_FORMAT_U8 || format == AF_FORMAT_U8P;
45
62.6M
}
46
47
bool af_fmt_is_float(int format)
48
4.79k
{
49
4.79k
    format = af_fmt_from_planar(format);
50
4.79k
    return format == AF_FORMAT_FLOAT || format == AF_FORMAT_DOUBLE;
51
4.79k
}
52
53
// true for both unsigned and signed ints
54
bool af_fmt_is_int(int format)
55
0
{
56
0
    return format && !af_fmt_is_spdif(format) && !af_fmt_is_float(format);
57
0
}
58
59
bool af_fmt_is_spdif(int format)
60
443k
{
61
443k
    return af_format_sample_alignment(format) > 1;
62
443k
}
63
64
bool af_fmt_is_pcm(int format)
65
378k
{
66
378k
    return af_fmt_is_valid(format) && !af_fmt_is_spdif(format);
67
378k
}
68
69
static const int planar_formats[][2] = {
70
    {AF_FORMAT_U8P,     AF_FORMAT_U8},
71
    {AF_FORMAT_S16P,    AF_FORMAT_S16},
72
    {AF_FORMAT_S32P,    AF_FORMAT_S32},
73
    {AF_FORMAT_S64P,    AF_FORMAT_S64},
74
    {AF_FORMAT_FLOATP,  AF_FORMAT_FLOAT},
75
    {AF_FORMAT_DOUBLEP, AF_FORMAT_DOUBLE},
76
};
77
78
bool af_fmt_is_planar(int format)
79
314M
{
80
2.09G
    for (int n = 0; n < MP_ARRAY_SIZE(planar_formats); n++) {
81
1.83G
        if (planar_formats[n][0] == format)
82
47.8M
            return true;
83
1.83G
    }
84
266M
    return false;
85
314M
}
86
87
// Return the planar format corresponding to the given format.
88
// If the format is already planar or if there's no equivalent,
89
// return it.
90
int af_fmt_to_planar(int format)
91
0
{
92
0
    for (int n = 0; n < MP_ARRAY_SIZE(planar_formats); n++) {
93
0
        if (planar_formats[n][1] == format)
94
0
            return planar_formats[n][0];
95
0
    }
96
0
    return format;
97
0
}
98
99
// Return the interleaved format corresponding to the given format.
100
// If the format is already interleaved or if there's no equivalent,
101
// return it.
102
int af_fmt_from_planar(int format)
103
159M
{
104
1.07G
    for (int n = 0; n < MP_ARRAY_SIZE(planar_formats); n++) {
105
935M
        if (planar_formats[n][0] == format)
106
19.6M
            return planar_formats[n][1];
107
935M
    }
108
139M
    return format;
109
159M
}
110
111
bool af_fmt_is_valid(int format)
112
378k
{
113
378k
    return format > 0 && format < AF_FORMAT_COUNT;
114
378k
}
115
116
const char *af_fmt_to_str(int format)
117
241k
{
118
241k
    switch (format) {
119
3.16k
    case AF_FORMAT_U8:          return "u8";
120
59.8k
    case AF_FORMAT_S16:         return "s16";
121
3.32k
    case AF_FORMAT_S32:         return "s32";
122
2.83k
    case AF_FORMAT_S64:         return "s64";
123
2.95k
    case AF_FORMAT_FLOAT:       return "float";
124
2.82k
    case AF_FORMAT_DOUBLE:      return "double";
125
2.81k
    case AF_FORMAT_U8P:         return "u8p";
126
36.6k
    case AF_FORMAT_S16P:        return "s16p";
127
2.83k
    case AF_FORMAT_S32P:        return "s32p";
128
2.84k
    case AF_FORMAT_S64P:        return "s64p";
129
99.2k
    case AF_FORMAT_FLOATP:      return "floatp";
130
2.81k
    case AF_FORMAT_DOUBLEP:     return "doublep";
131
2.81k
    case AF_FORMAT_S_AAC:       return "spdif-aac";
132
2.81k
    case AF_FORMAT_S_AC3:       return "spdif-ac3";
133
2.81k
    case AF_FORMAT_S_DTS:       return "spdif-dts";
134
2.81k
    case AF_FORMAT_S_DTSHD:     return "spdif-dtshd";
135
2.81k
    case AF_FORMAT_S_EAC3:      return "spdif-eac3";
136
2.81k
    case AF_FORMAT_S_MP3:       return "spdif-mp3";
137
2.81k
    case AF_FORMAT_S_TRUEHD:    return "spdif-truehd";
138
241k
    }
139
0
    return "??";
140
241k
}
141
142
void af_fill_silence(void *dst, size_t bytes, int format)
143
62.6M
{
144
62.6M
    memset(dst, af_fmt_is_unsigned(format) ? 0x80 : 0, bytes);
145
62.6M
}
146
147
// Returns a "score" that serves as heuristic how lossy or hard a conversion is.
148
// If the formats are equal, 1024 is returned. If they are gravely incompatible
149
// (like s16<->ac3), INT_MIN is returned. If there is implied loss of precision
150
// (like s16->s8), a value <0 is returned.
151
int af_format_conversion_score(int dst_format, int src_format)
152
37.1k
{
153
37.1k
    if (dst_format == AF_FORMAT_UNKNOWN || src_format == AF_FORMAT_UNKNOWN)
154
0
        return INT_MIN;
155
37.1k
    if (dst_format == src_format)
156
35.5k
        return 1024;
157
    // Can't be normally converted
158
1.60k
    if (!af_fmt_is_pcm(dst_format) || !af_fmt_is_pcm(src_format))
159
0
        return INT_MIN;
160
1.60k
    int score = 1024;
161
1.60k
    if (af_fmt_is_planar(dst_format) != af_fmt_is_planar(src_format))
162
1.39k
        score -= 1;     // has to (de-)planarize
163
1.60k
    if (af_fmt_is_float(dst_format) != af_fmt_is_float(src_format)) {
164
1.59k
        int dst_bytes = af_fmt_to_bytes(dst_format);
165
1.59k
        if (af_fmt_is_float(dst_format)) {
166
            // For int->float, consider a lower bound on the precision difference.
167
1.38k
            int bytes = (dst_bytes == 4 ? 3 : 6) - af_fmt_to_bytes(src_format);
168
1.38k
            if (bytes >= 0) {
169
1.38k
                score -= 8 * bytes;          // excess precision
170
1.38k
            } else {
171
0
                score += 1024 * (bytes - 1); // precision is lost (i.e. s32 -> float)
172
0
            }
173
1.38k
        } else {
174
            // float->int is the worst case. Penalize heavily and
175
            // prefer highest bit depth int.
176
209
            score -= 1048576 * (8 - dst_bytes);
177
209
        }
178
1.59k
        score -= 512; // penalty for any float <-> int conversion
179
1.59k
    } else {
180
10
        int bytes = af_fmt_to_bytes(dst_format) - af_fmt_to_bytes(src_format);
181
10
        if (bytes > 0) {
182
8
            score -= 8 * bytes;          // has to add padding
183
8
        } else if (bytes < 0) {
184
0
            score += 1024 * (bytes - 1); // has to reduce bit depth
185
0
        }
186
10
    }
187
1.60k
    return score;
188
1.60k
}
189
190
struct mp_entry {
191
    int fmt;
192
    int score;
193
};
194
195
static int cmp_entry(const void *a, const void *b)
196
0
{
197
0
#define CMP_INT(a, b) (a > b ? 1 : (a < b ? -1 : 0))
198
0
    return -CMP_INT(((struct mp_entry *)a)->score, ((struct mp_entry *)b)->score);
199
0
}
200
201
// Return a list of sample format compatible to src_format, sorted by order
202
// of preference. out_formats[0] will be src_format (as long as it's valid),
203
// and the list is terminated with 0 (AF_FORMAT_UNKNOWN).
204
// Keep in mind that this also returns formats with flipped interleaving
205
// (e.g. for s16, it returns [s16, s16p, ...]).
206
// out_formats must be an int[AF_FORMAT_COUNT + 1] array.
207
void af_get_best_sample_formats(int src_format, int *out_formats)
208
0
{
209
0
    int num = 0;
210
0
    struct mp_entry e[AF_FORMAT_COUNT + 1];
211
0
    for (int fmt = 1; fmt < AF_FORMAT_COUNT; fmt++) {
212
0
        int score = af_format_conversion_score(fmt, src_format);
213
0
        if (score > INT_MIN)
214
0
            e[num++] = (struct mp_entry){fmt, score};
215
0
    }
216
0
    qsort(e, num, sizeof(e[0]), cmp_entry);
217
0
    for (int n = 0; n < num; n++)
218
0
        out_formats[n] = e[n].fmt;
219
0
    out_formats[num] = 0;
220
0
}
221
222
// Return the best match to src_samplerate from the list provided in the array
223
// *available, which must be terminated by 0, or itself NULL. If *available is
224
// empty or NULL, return a negative value. Exact match to src_samplerate is
225
// most preferred, followed by the lowest integer multiple, followed by the
226
// maximum of *available.
227
int af_select_best_samplerate(int src_samplerate, const int *available)
228
32.0k
{
229
32.0k
    if (!available)
230
1.77k
        return -1;
231
232
30.2k
    int min_mult_rate = INT_MAX;
233
30.2k
    int max_rate      = INT_MIN;
234
30.4k
    for (int i = 0; available[i]; i++) {
235
30.2k
        if (available[i] == src_samplerate)
236
30.0k
            return available[i];
237
238
218
        if (!(available[i] % src_samplerate))
239
1
            min_mult_rate = MPMIN(min_mult_rate, available[i]);
240
241
218
        max_rate = MPMAX(max_rate, available[i]);
242
218
    }
243
244
218
    if (min_mult_rate < INT_MAX)
245
1
        return min_mult_rate;
246
247
217
    if (max_rate > INT_MIN)
248
217
        return max_rate;
249
250
0
    return -1;
251
217
}
252
253
// Return the number of samples that make up one frame in this format.
254
// You get the byte size by multiplying them with sample size and channel count.
255
int af_format_sample_alignment(int format)
256
473k
{
257
473k
    switch (format) {
258
0
    case AF_FORMAT_S_AAC:       return 16384 / 4;
259
0
    case AF_FORMAT_S_AC3:       return 6144 / 4;
260
0
    case AF_FORMAT_S_DTSHD:     return 32768 / 16;
261
0
    case AF_FORMAT_S_DTS:       return 2048 / 4;
262
0
    case AF_FORMAT_S_EAC3:      return 24576 / 4;
263
0
    case AF_FORMAT_S_MP3:       return 4608 / 4;
264
0
    case AF_FORMAT_S_TRUEHD:    return 61440 / 16;
265
473k
    default:                    return 1;
266
473k
    }
267
473k
}