FFmpeg coverage


Directory: ../../../ffmpeg/
File: src/libavutil/samplefmt.c
Date: 2026-09-07 08:47:58
Exec Total Coverage
Lines: 112 123 91.1%
Functions: 14 14 100.0%
Branches: 87 106 82.1%

Line Branch Exec Source
1 /*
2 * This file is part of FFmpeg.
3 *
4 * FFmpeg is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
8 *
9 * FFmpeg is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with FFmpeg; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17 */
18
19 #include "error.h"
20 #include "macros.h"
21 #include "mem.h"
22 #include "samplefmt.h"
23
24 #include <limits.h>
25 #include <stdio.h>
26 #include <string.h>
27
28 typedef struct SampleFmtInfo {
29 char name[8];
30 int bits;
31 int planar;
32 enum AVSampleFormat altform; ///< planar<->packed alternative form
33 } SampleFmtInfo;
34
35 /** this table gives more information about formats */
36 static const SampleFmtInfo sample_fmt_info[AV_SAMPLE_FMT_NB] = {
37 [AV_SAMPLE_FMT_U8] = { .name = "u8", .bits = 8, .planar = 0, .altform = AV_SAMPLE_FMT_U8P },
38 [AV_SAMPLE_FMT_S16] = { .name = "s16", .bits = 16, .planar = 0, .altform = AV_SAMPLE_FMT_S16P },
39 [AV_SAMPLE_FMT_S32] = { .name = "s32", .bits = 32, .planar = 0, .altform = AV_SAMPLE_FMT_S32P },
40 [AV_SAMPLE_FMT_S64] = { .name = "s64", .bits = 64, .planar = 0, .altform = AV_SAMPLE_FMT_S64P },
41 [AV_SAMPLE_FMT_FLT] = { .name = "flt", .bits = 32, .planar = 0, .altform = AV_SAMPLE_FMT_FLTP },
42 [AV_SAMPLE_FMT_DBL] = { .name = "dbl", .bits = 64, .planar = 0, .altform = AV_SAMPLE_FMT_DBLP },
43 [AV_SAMPLE_FMT_U8P] = { .name = "u8p", .bits = 8, .planar = 1, .altform = AV_SAMPLE_FMT_U8 },
44 [AV_SAMPLE_FMT_S16P] = { .name = "s16p", .bits = 16, .planar = 1, .altform = AV_SAMPLE_FMT_S16 },
45 [AV_SAMPLE_FMT_S32P] = { .name = "s32p", .bits = 32, .planar = 1, .altform = AV_SAMPLE_FMT_S32 },
46 [AV_SAMPLE_FMT_S64P] = { .name = "s64p", .bits = 64, .planar = 1, .altform = AV_SAMPLE_FMT_S64 },
47 [AV_SAMPLE_FMT_FLTP] = { .name = "fltp", .bits = 32, .planar = 1, .altform = AV_SAMPLE_FMT_FLT },
48 [AV_SAMPLE_FMT_DBLP] = { .name = "dblp", .bits = 64, .planar = 1, .altform = AV_SAMPLE_FMT_DBL },
49 [AV_SAMPLE_FMT_DSD] = { .name = "dsd", .bits = 8, .planar = 0, .altform = AV_SAMPLE_FMT_DSD },
50 };
51
52 170695 const char *av_get_sample_fmt_name(enum AVSampleFormat sample_fmt)
53 {
54
4/4
✓ Branch 0 taken 170694 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 10888 times.
✓ Branch 3 taken 159806 times.
170695 if (sample_fmt < 0 || sample_fmt >= AV_SAMPLE_FMT_NB)
55 10889 return NULL;
56 159806 return sample_fmt_info[sample_fmt].name;
57 }
58
59 4890 enum AVSampleFormat av_get_sample_fmt(const char *name)
60 {
61 int i;
62
63
2/2
✓ Branch 0 taken 26066 times.
✓ Branch 1 taken 3 times.
26069 for (i = 0; i < AV_SAMPLE_FMT_NB; i++)
64
2/2
✓ Branch 0 taken 4887 times.
✓ Branch 1 taken 21179 times.
26066 if (!strcmp(sample_fmt_info[i].name, name))
65 4887 return i;
66 3 return AV_SAMPLE_FMT_NONE;
67 }
68
69 26 enum AVSampleFormat av_get_alt_sample_fmt(enum AVSampleFormat sample_fmt, int planar)
70 {
71
2/4
✓ Branch 0 taken 26 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 26 times.
26 if (sample_fmt < 0 || sample_fmt >= AV_SAMPLE_FMT_NB)
72 return AV_SAMPLE_FMT_NONE;
73
2/2
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 13 times.
26 if (sample_fmt_info[sample_fmt].planar == planar)
74 13 return sample_fmt;
75 13 return sample_fmt_info[sample_fmt].altform;
76 }
77
78 11101 enum AVSampleFormat av_get_packed_sample_fmt(enum AVSampleFormat sample_fmt)
79 {
80
3/4
✓ Branch 0 taken 10795 times.
✓ Branch 1 taken 306 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 10795 times.
11101 if (sample_fmt < 0 || sample_fmt >= AV_SAMPLE_FMT_NB)
81 306 return AV_SAMPLE_FMT_NONE;
82
2/2
✓ Branch 0 taken 7006 times.
✓ Branch 1 taken 3789 times.
10795 if (sample_fmt_info[sample_fmt].planar)
83 7006 return sample_fmt_info[sample_fmt].altform;
84 3789 return sample_fmt;
85 }
86
87 4037 enum AVSampleFormat av_get_planar_sample_fmt(enum AVSampleFormat sample_fmt)
88 {
89
2/4
✓ Branch 0 taken 4037 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 4037 times.
4037 if (sample_fmt < 0 || sample_fmt >= AV_SAMPLE_FMT_NB)
90 return AV_SAMPLE_FMT_NONE;
91
2/2
✓ Branch 0 taken 2690 times.
✓ Branch 1 taken 1347 times.
4037 if (sample_fmt_info[sample_fmt].planar)
92 2690 return sample_fmt;
93 1347 return sample_fmt_info[sample_fmt].altform;
94 }
95
96 14 char *av_get_sample_fmt_string (char *buf, int buf_size, enum AVSampleFormat sample_fmt)
97 {
98 /* print header */
99
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 13 times.
14 if (sample_fmt < 0)
100 1 snprintf(buf, buf_size, "name " " depth");
101
1/2
✓ Branch 0 taken 13 times.
✗ Branch 1 not taken.
13 else if (sample_fmt < AV_SAMPLE_FMT_NB) {
102 13 SampleFmtInfo info = sample_fmt_info[sample_fmt];
103 13 snprintf (buf, buf_size, "%-6s" " %2d ", info.name, info.bits);
104 }
105
106 14 return buf;
107 }
108
109 506234 int av_get_bytes_per_sample(enum AVSampleFormat sample_fmt)
110 {
111
2/2
✓ Branch 0 taken 505567 times.
✓ Branch 1 taken 65 times.
505632 return sample_fmt < 0 || sample_fmt >= AV_SAMPLE_FMT_NB ?
112
2/2
✓ Branch 0 taken 505632 times.
✓ Branch 1 taken 602 times.
1011866 0 : sample_fmt_info[sample_fmt].bits >> 3;
113 }
114
115 506033 int av_sample_fmt_is_planar(enum AVSampleFormat sample_fmt)
116 {
117
3/4
✓ Branch 0 taken 505584 times.
✓ Branch 1 taken 449 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 505584 times.
506033 if (sample_fmt < 0 || sample_fmt >= AV_SAMPLE_FMT_NB)
118 449 return 0;
119 505584 return sample_fmt_info[sample_fmt].planar;
120 }
121
122 38552 int av_samples_get_buffer_size(int *linesize, int nb_channels, int nb_samples,
123 enum AVSampleFormat sample_fmt, int align)
124 {
125 int line_size;
126 38552 int sample_size = av_get_bytes_per_sample(sample_fmt);
127 38552 int planar = av_sample_fmt_is_planar(sample_fmt);
128
129 /* validate parameter ranges */
130
4/6
✓ Branch 0 taken 38552 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 38552 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 38551 times.
38552 if (!sample_size || nb_samples <= 0 || nb_channels <= 0)
131 1 return AVERROR(EINVAL);
132
133 /* auto-select alignment if not specified */
134
2/2
✓ Branch 0 taken 38189 times.
✓ Branch 1 taken 362 times.
38551 if (!align) {
135
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 38189 times.
38189 if (nb_samples > INT_MAX - 31)
136 return AVERROR(EINVAL);
137 38189 align = 1;
138 38189 nb_samples = FFALIGN(nb_samples, 32);
139 }
140
141 /* check for integer overflow */
142
1/2
✓ Branch 0 taken 38551 times.
✗ Branch 1 not taken.
38551 if (nb_channels > INT_MAX / align ||
143
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 38551 times.
38551 (int64_t)nb_channels * nb_samples > (INT_MAX - (align * nb_channels)) / sample_size)
144 return AVERROR(EINVAL);
145
146
2/2
✓ Branch 0 taken 10293 times.
✓ Branch 1 taken 28258 times.
38551 line_size = planar ? FFALIGN(nb_samples * sample_size, align) :
147 28258 FFALIGN(nb_samples * sample_size * nb_channels, align);
148
2/2
✓ Branch 0 taken 38170 times.
✓ Branch 1 taken 381 times.
38551 if (linesize)
149 38170 *linesize = line_size;
150
151
2/2
✓ Branch 0 taken 10293 times.
✓ Branch 1 taken 28258 times.
38551 return planar ? line_size * nb_channels : line_size;
152 }
153
154 377 int av_samples_fill_arrays(uint8_t **audio_data, int *linesize,
155 const uint8_t *buf, int nb_channels, int nb_samples,
156 enum AVSampleFormat sample_fmt, int align)
157 {
158 int ch, planar, buf_size, line_size;
159
160 377 planar = av_sample_fmt_is_planar(sample_fmt);
161 377 buf_size = av_samples_get_buffer_size(&line_size, nb_channels, nb_samples,
162 sample_fmt, align);
163
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 377 times.
377 if (buf_size < 0)
164 return buf_size;
165
166
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 370 times.
377 if (linesize)
167 7 *linesize = line_size;
168
169
2/2
✓ Branch 0 taken 372 times.
✓ Branch 1 taken 5 times.
377 memset(audio_data, 0, planar
170 372 ? sizeof(*audio_data) * nb_channels
171 : sizeof(*audio_data));
172
173
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 377 times.
377 if (!buf)
174 return buf_size;
175
176 377 audio_data[0] = (uint8_t *)buf;
177
4/4
✓ Branch 0 taken 740 times.
✓ Branch 1 taken 5 times.
✓ Branch 2 taken 368 times.
✓ Branch 3 taken 372 times.
745 for (ch = 1; planar && ch < nb_channels; ch++)
178 368 audio_data[ch] = audio_data[ch-1] + line_size;
179
180 377 return buf_size;
181 }
182
183 26 int av_samples_alloc(uint8_t **audio_data, int *linesize, int nb_channels,
184 int nb_samples, enum AVSampleFormat sample_fmt, int align)
185 {
186 uint8_t *buf;
187 26 int size = av_samples_get_buffer_size(NULL, nb_channels, nb_samples,
188 sample_fmt, align);
189
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 26 times.
26 if (size < 0)
190 return size;
191
192 26 buf = av_malloc(size);
193
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 25 times.
26 if (!buf)
194 1 return AVERROR(ENOMEM);
195
196 25 size = av_samples_fill_arrays(audio_data, linesize, buf, nb_channels,
197 nb_samples, sample_fmt, align);
198
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 25 times.
25 if (size < 0) {
199 av_free(buf);
200 return size;
201 }
202
203 25 av_samples_set_silence(audio_data, 0, nb_samples, nb_channels, sample_fmt);
204
205 25 return size;
206 }
207
208 4 int av_samples_alloc_array_and_samples(uint8_t ***audio_data, int *linesize, int nb_channels,
209 int nb_samples, enum AVSampleFormat sample_fmt, int align)
210 {
211
1/2
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
4 int ret, nb_planes = av_sample_fmt_is_planar(sample_fmt) ? nb_channels : 1;
212
213 4 *audio_data = av_calloc(nb_planes, sizeof(**audio_data));
214
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 3 times.
4 if (!*audio_data)
215 1 return AVERROR(ENOMEM);
216 3 ret = av_samples_alloc(*audio_data, linesize, nb_channels,
217 nb_samples, sample_fmt, align);
218
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (ret < 0)
219 av_freep(audio_data);
220 3 return ret;
221 }
222
223 32171 int av_samples_copy(uint8_t * const *dst, uint8_t * const *src, int dst_offset,
224 int src_offset, int nb_samples, int nb_channels,
225 enum AVSampleFormat sample_fmt)
226 {
227 32171 int planar = av_sample_fmt_is_planar(sample_fmt);
228
2/2
✓ Branch 0 taken 2557 times.
✓ Branch 1 taken 29614 times.
32171 int planes = planar ? nb_channels : 1;
229
2/2
✓ Branch 1 taken 29614 times.
✓ Branch 2 taken 2557 times.
32171 int block_align = av_get_bytes_per_sample(sample_fmt) * (planar ? 1 : nb_channels);
230 32171 int data_size = nb_samples * block_align;
231 int i;
232
233 32171 dst_offset *= block_align;
234 32171 src_offset *= block_align;
235
236
4/4
✓ Branch 0 taken 2575 times.
✓ Branch 1 taken 29596 times.
✓ Branch 2 taken 32026 times.
✓ Branch 3 taken 145 times.
32171 if((dst[0] < src[0] ? src[0] - dst[0] : dst[0] - src[0]) >= data_size) {
237
2/2
✓ Branch 0 taken 33900 times.
✓ Branch 1 taken 32026 times.
65926 for (i = 0; i < planes; i++)
238 33900 memcpy(dst[i] + dst_offset, src[i] + src_offset, data_size);
239 } else {
240
2/2
✓ Branch 0 taken 257 times.
✓ Branch 1 taken 145 times.
402 for (i = 0; i < planes; i++)
241 257 memmove(dst[i] + dst_offset, src[i] + src_offset, data_size);
242 }
243
244 32171 return 0;
245 }
246
247 287510 int av_samples_set_silence(uint8_t * const *audio_data, int offset, int nb_samples,
248 int nb_channels, enum AVSampleFormat sample_fmt)
249 {
250 287510 int planar = av_sample_fmt_is_planar(sample_fmt);
251
2/2
✓ Branch 0 taken 20569 times.
✓ Branch 1 taken 266941 times.
287510 int planes = planar ? nb_channels : 1;
252
2/2
✓ Branch 1 taken 266941 times.
✓ Branch 2 taken 20569 times.
287510 int block_align = av_get_bytes_per_sample(sample_fmt) * (planar ? 1 : nb_channels);
253 287510 int data_size = nb_samples * block_align;
254 int fill_char, i;
255
256
4/4
✓ Branch 0 taken 286982 times.
✓ Branch 1 taken 528 times.
✓ Branch 2 taken 66 times.
✓ Branch 3 taken 286916 times.
287510 if (sample_fmt == AV_SAMPLE_FMT_U8 || sample_fmt == AV_SAMPLE_FMT_U8P)
257 594 fill_char = 0x80;
258
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 286916 times.
286916 else if (sample_fmt == AV_SAMPLE_FMT_DSD)
259 fill_char = 0x69; // only ultrasonic tones, filtered out on playback
260 else
261 286916 fill_char = 0x00;
262
263 287510 offset *= block_align;
264
265
2/2
✓ Branch 0 taken 299359 times.
✓ Branch 1 taken 287510 times.
586869 for (i = 0; i < planes; i++)
266 299359 memset(audio_data[i] + offset, fill_char, data_size);
267
268 287510 return 0;
269 }
270