Coverage Report

Created: 2025-10-27 07:04

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/mpv/audio/format.c
Line
Count
Source
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
16.3M
{
28
16.3M
    switch (af_fmt_from_planar(format)) {
29
12.3k
    case AF_FORMAT_U8:      return 1;
30
5.82M
    case AF_FORMAT_S16:     return 2;
31
8.14k
    case AF_FORMAT_S32:     return 4;
32
24.6k
    case AF_FORMAT_S64:     return 8;
33
10.4M
    case AF_FORMAT_FLOAT:   return 4;
34
2.14k
    case AF_FORMAT_DOUBLE:  return 8;
35
16.3M
    }
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
6.89M
{
44
6.89M
    return format == AF_FORMAT_U8 || format == AF_FORMAT_U8P;
45
6.89M
}
46
47
bool af_fmt_is_float(int format)
48
5.99k
{
49
5.99k
    format = af_fmt_from_planar(format);
50
5.99k
    return format == AF_FORMAT_FLOAT || format == AF_FORMAT_DOUBLE;
51
5.99k
}
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
492k
{
61
492k
    return af_format_sample_alignment(format) > 1;
62
492k
}
63
64
bool af_fmt_is_pcm(int format)
65
430k
{
66
430k
    return af_fmt_is_valid(format) && !af_fmt_is_spdif(format);
67
430k
}
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
45.6M
{
80
228M
    for (int n = 0; n < MP_ARRAY_SIZE(planar_formats); n++) {
81
219M
        if (planar_formats[n][0] == format)
82
36.7M
            return true;
83
219M
    }
84
8.96M
    return false;
85
45.6M
}
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
19.6M
{
104
97.2M
    for (int n = 0; n < MP_ARRAY_SIZE(planar_formats); n++) {
105
93.3M
        if (planar_formats[n][0] == format)
106
15.7M
            return planar_formats[n][1];
107
93.3M
    }
108
3.92M
    return format;
109
19.6M
}
110
111
bool af_fmt_is_valid(int format)
112
430k
{
113
430k
    return format > 0 && format < AF_FORMAT_COUNT;
114
430k
}
115
116
const char *af_fmt_to_str(int format)
117
355k
{
118
355k
    switch (format) {
119
8.58k
    case AF_FORMAT_U8:          return "u8";
120
110k
    case AF_FORMAT_S16:         return "s16";
121
8.52k
    case AF_FORMAT_S32:         return "s32";
122
9.68k
    case AF_FORMAT_S64:         return "s64";
123
7.32k
    case AF_FORMAT_FLOAT:       return "float";
124
7.88k
    case AF_FORMAT_DOUBLE:      return "double";
125
9.77k
    case AF_FORMAT_U8P:         return "u8p";
126
45.1k
    case AF_FORMAT_S16P:        return "s16p";
127
7.34k
    case AF_FORMAT_S32P:        return "s32p";
128
7.11k
    case AF_FORMAT_S64P:        return "s64p";
129
77.3k
    case AF_FORMAT_FLOATP:      return "floatp";
130
7.05k
    case AF_FORMAT_DOUBLEP:     return "doublep";
131
7.05k
    case AF_FORMAT_S_AAC:       return "spdif-aac";
132
7.05k
    case AF_FORMAT_S_AC3:       return "spdif-ac3";
133
7.05k
    case AF_FORMAT_S_DTS:       return "spdif-dts";
134
7.05k
    case AF_FORMAT_S_DTSHD:     return "spdif-dtshd";
135
7.05k
    case AF_FORMAT_S_EAC3:      return "spdif-eac3";
136
7.06k
    case AF_FORMAT_S_MP3:       return "spdif-mp3";
137
7.05k
    case AF_FORMAT_S_TRUEHD:    return "spdif-truehd";
138
355k
    }
139
0
    return "??";
140
355k
}
141
142
void af_fill_silence(void *dst, size_t bytes, int format)
143
6.89M
{
144
6.89M
    memset(dst, af_fmt_is_unsigned(format) ? 0x80 : 0, bytes);
145
6.89M
}
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
38.0k
{
153
38.0k
    if (dst_format == AF_FORMAT_UNKNOWN || src_format == AF_FORMAT_UNKNOWN)
154
0
        return INT_MIN;
155
38.0k
    if (dst_format == src_format)
156
35.8k
        return 1024;
157
    // Can't be normally converted
158
2.24k
    if (!af_fmt_is_pcm(dst_format) || !af_fmt_is_pcm(src_format))
159
1
        return INT_MIN;
160
2.23k
    int score = 1024;
161
2.23k
    if (af_fmt_is_planar(dst_format) != af_fmt_is_planar(src_format))
162
1.68k
        score -= 1;     // has to (de-)planarize
163
2.23k
    if (af_fmt_is_float(dst_format) != af_fmt_is_float(src_format)) {
164
1.52k
        int dst_bytes = af_fmt_to_bytes(dst_format);
165
1.52k
        if (af_fmt_is_float(dst_format)) {
166
            // For int->float, consider a lower bound on the precision difference.
167
1.32k
            int bytes = (dst_bytes == 4 ? 3 : 6) - af_fmt_to_bytes(src_format);
168
1.32k
            if (bytes >= 0) {
169
1.32k
                score -= 8 * bytes;          // excess precision
170
1.32k
            } else {
171
0
                score += 1024 * (bytes - 1); // precision is lost (i.e. s32 -> float)
172
0
            }
173
1.32k
        } else {
174
            // float->int is the worst case. Penalize heavily and
175
            // prefer highest bit depth int.
176
191
            score -= 1048576 * (8 - dst_bytes);
177
191
        }
178
1.52k
        score -= 512; // penalty for any float <-> int conversion
179
1.52k
    } else {
180
719
        int bytes = af_fmt_to_bytes(dst_format) - af_fmt_to_bytes(src_format);
181
719
        if (bytes > 0) {
182
444
            score -= 8 * bytes;          // has to add padding
183
444
        } else if (bytes < 0) {
184
251
            score += 1024 * (bytes - 1); // has to reduce bit depth
185
251
        }
186
719
    }
187
2.23k
    return score;
188
2.24k
}
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
47.2k
{
229
47.2k
    if (!available)
230
14.0k
        return -1;
231
232
33.2k
    int min_mult_rate = INT_MAX;
233
33.2k
    int max_rate      = INT_MIN;
234
36.2k
    for (int i = 0; available[i]; i++) {
235
33.2k
        if (available[i] == src_samplerate)
236
30.2k
            return available[i];
237
238
3.04k
        if (!(available[i] % src_samplerate))
239
14
            min_mult_rate = MPMIN(min_mult_rate, available[i]);
240
241
3.04k
        max_rate = MPMAX(max_rate, available[i]);
242
3.04k
    }
243
244
3.04k
    if (min_mult_rate < INT_MAX)
245
14
        return min_mult_rate;
246
247
3.02k
    if (max_rate > INT_MIN)
248
3.02k
        return max_rate;
249
250
0
    return -1;
251
3.02k
}
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
522k
{
257
522k
    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
1
    case AF_FORMAT_S_MP3:       return 4608 / 4;
264
0
    case AF_FORMAT_S_TRUEHD:    return 61440 / 16;
265
522k
    default:                    return 1;
266
522k
    }
267
522k
}