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 | }; | ||
50 | |||
51 | 148009 | const char *av_get_sample_fmt_name(enum AVSampleFormat sample_fmt) | |
52 | { | ||
53 |
3/4✓ Branch 0 taken 148009 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 10114 times.
✓ Branch 3 taken 137895 times.
|
148009 | if (sample_fmt < 0 || sample_fmt >= AV_SAMPLE_FMT_NB) |
54 | 10114 | return NULL; | |
55 | 137895 | return sample_fmt_info[sample_fmt].name; | |
56 | } | ||
57 | |||
58 | 4612 | enum AVSampleFormat av_get_sample_fmt(const char *name) | |
59 | { | ||
60 | int i; | ||
61 | |||
62 |
2/2✓ Branch 0 taken 24796 times.
✓ Branch 1 taken 2 times.
|
24798 | for (i = 0; i < AV_SAMPLE_FMT_NB; i++) |
63 |
2/2✓ Branch 0 taken 4610 times.
✓ Branch 1 taken 20186 times.
|
24796 | if (!strcmp(sample_fmt_info[i].name, name)) |
64 | 4610 | return i; | |
65 | 2 | return AV_SAMPLE_FMT_NONE; | |
66 | } | ||
67 | |||
68 | ✗ | enum AVSampleFormat av_get_alt_sample_fmt(enum AVSampleFormat sample_fmt, int planar) | |
69 | { | ||
70 | ✗ | if (sample_fmt < 0 || sample_fmt >= AV_SAMPLE_FMT_NB) | |
71 | ✗ | return AV_SAMPLE_FMT_NONE; | |
72 | ✗ | if (sample_fmt_info[sample_fmt].planar == planar) | |
73 | ✗ | return sample_fmt; | |
74 | ✗ | return sample_fmt_info[sample_fmt].altform; | |
75 | } | ||
76 | |||
77 | 10422 | enum AVSampleFormat av_get_packed_sample_fmt(enum AVSampleFormat sample_fmt) | |
78 | { | ||
79 |
3/4✓ Branch 0 taken 10144 times.
✓ Branch 1 taken 278 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 10144 times.
|
10422 | if (sample_fmt < 0 || sample_fmt >= AV_SAMPLE_FMT_NB) |
80 | 278 | return AV_SAMPLE_FMT_NONE; | |
81 |
2/2✓ Branch 0 taken 6650 times.
✓ Branch 1 taken 3494 times.
|
10144 | if (sample_fmt_info[sample_fmt].planar) |
82 | 6650 | return sample_fmt_info[sample_fmt].altform; | |
83 | 3494 | return sample_fmt; | |
84 | } | ||
85 | |||
86 | 3915 | enum AVSampleFormat av_get_planar_sample_fmt(enum AVSampleFormat sample_fmt) | |
87 | { | ||
88 |
2/4✓ Branch 0 taken 3915 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 3915 times.
|
3915 | if (sample_fmt < 0 || sample_fmt >= AV_SAMPLE_FMT_NB) |
89 | ✗ | return AV_SAMPLE_FMT_NONE; | |
90 |
2/2✓ Branch 0 taken 2628 times.
✓ Branch 1 taken 1287 times.
|
3915 | if (sample_fmt_info[sample_fmt].planar) |
91 | 2628 | return sample_fmt; | |
92 | 1287 | return sample_fmt_info[sample_fmt].altform; | |
93 | } | ||
94 | |||
95 | ✗ | char *av_get_sample_fmt_string (char *buf, int buf_size, enum AVSampleFormat sample_fmt) | |
96 | { | ||
97 | /* print header */ | ||
98 | ✗ | if (sample_fmt < 0) | |
99 | ✗ | snprintf(buf, buf_size, "name " " depth"); | |
100 | ✗ | else if (sample_fmt < AV_SAMPLE_FMT_NB) { | |
101 | ✗ | SampleFmtInfo info = sample_fmt_info[sample_fmt]; | |
102 | ✗ | snprintf (buf, buf_size, "%-6s" " %2d ", info.name, info.bits); | |
103 | } | ||
104 | |||
105 | ✗ | return buf; | |
106 | } | ||
107 | |||
108 | 403723 | int av_get_bytes_per_sample(enum AVSampleFormat sample_fmt) | |
109 | { | ||
110 |
2/2✓ Branch 0 taken 403130 times.
✓ Branch 1 taken 60 times.
|
403190 | return sample_fmt < 0 || sample_fmt >= AV_SAMPLE_FMT_NB ? |
111 |
2/2✓ Branch 0 taken 403190 times.
✓ Branch 1 taken 533 times.
|
806913 | 0 : sample_fmt_info[sample_fmt].bits >> 3; |
112 | } | ||
113 | |||
114 | 394954 | int av_sample_fmt_is_planar(enum AVSampleFormat sample_fmt) | |
115 | { | ||
116 |
3/4✓ Branch 0 taken 394560 times.
✓ Branch 1 taken 394 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 394560 times.
|
394954 | if (sample_fmt < 0 || sample_fmt >= AV_SAMPLE_FMT_NB) |
117 | 394 | return 0; | |
118 | 394560 | return sample_fmt_info[sample_fmt].planar; | |
119 | } | ||
120 | |||
121 | 26917 | int av_samples_get_buffer_size(int *linesize, int nb_channels, int nb_samples, | |
122 | enum AVSampleFormat sample_fmt, int align) | ||
123 | { | ||
124 | int line_size; | ||
125 | 26917 | int sample_size = av_get_bytes_per_sample(sample_fmt); | |
126 | 26917 | int planar = av_sample_fmt_is_planar(sample_fmt); | |
127 | |||
128 | /* validate parameter ranges */ | ||
129 |
3/6✓ Branch 0 taken 26917 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 26917 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 26917 times.
|
26917 | if (!sample_size || nb_samples <= 0 || nb_channels <= 0) |
130 | ✗ | return AVERROR(EINVAL); | |
131 | |||
132 | /* auto-select alignment if not specified */ | ||
133 |
2/2✓ Branch 0 taken 26618 times.
✓ Branch 1 taken 299 times.
|
26917 | if (!align) { |
134 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 26618 times.
|
26618 | if (nb_samples > INT_MAX - 31) |
135 | ✗ | return AVERROR(EINVAL); | |
136 | 26618 | align = 1; | |
137 | 26618 | nb_samples = FFALIGN(nb_samples, 32); | |
138 | } | ||
139 | |||
140 | /* check for integer overflow */ | ||
141 |
1/2✓ Branch 0 taken 26917 times.
✗ Branch 1 not taken.
|
26917 | if (nb_channels > INT_MAX / align || |
142 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 26917 times.
|
26917 | (int64_t)nb_channels * nb_samples > (INT_MAX - (align * nb_channels)) / sample_size) |
143 | ✗ | return AVERROR(EINVAL); | |
144 | |||
145 |
2/2✓ Branch 0 taken 8540 times.
✓ Branch 1 taken 18377 times.
|
26917 | line_size = planar ? FFALIGN(nb_samples * sample_size, align) : |
146 | 18377 | FFALIGN(nb_samples * sample_size * nb_channels, align); | |
147 |
2/2✓ Branch 0 taken 26603 times.
✓ Branch 1 taken 314 times.
|
26917 | if (linesize) |
148 | 26603 | *linesize = line_size; | |
149 | |||
150 |
2/2✓ Branch 0 taken 8540 times.
✓ Branch 1 taken 18377 times.
|
26917 | return planar ? line_size * nb_channels : line_size; |
151 | } | ||
152 | |||
153 | 314 | int av_samples_fill_arrays(uint8_t **audio_data, int *linesize, | |
154 | const uint8_t *buf, int nb_channels, int nb_samples, | ||
155 | enum AVSampleFormat sample_fmt, int align) | ||
156 | { | ||
157 | int ch, planar, buf_size, line_size; | ||
158 | |||
159 | 314 | planar = av_sample_fmt_is_planar(sample_fmt); | |
160 | 314 | buf_size = av_samples_get_buffer_size(&line_size, nb_channels, nb_samples, | |
161 | sample_fmt, align); | ||
162 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 314 times.
|
314 | if (buf_size < 0) |
163 | ✗ | return buf_size; | |
164 | |||
165 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 314 times.
|
314 | if (linesize) |
166 | ✗ | *linesize = line_size; | |
167 | |||
168 |
1/2✓ Branch 0 taken 314 times.
✗ Branch 1 not taken.
|
314 | memset(audio_data, 0, planar |
169 | 314 | ? sizeof(*audio_data) * nb_channels | |
170 | : sizeof(*audio_data)); | ||
171 | |||
172 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 314 times.
|
314 | if (!buf) |
173 | ✗ | return buf_size; | |
174 | |||
175 | 314 | audio_data[0] = (uint8_t *)buf; | |
176 |
3/4✓ Branch 0 taken 646 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 332 times.
✓ Branch 3 taken 314 times.
|
646 | for (ch = 1; planar && ch < nb_channels; ch++) |
177 | 332 | audio_data[ch] = audio_data[ch-1] + line_size; | |
178 | |||
179 | 314 | return buf_size; | |
180 | } | ||
181 | |||
182 | 2 | int av_samples_alloc(uint8_t **audio_data, int *linesize, int nb_channels, | |
183 | int nb_samples, enum AVSampleFormat sample_fmt, int align) | ||
184 | { | ||
185 | uint8_t *buf; | ||
186 | 2 | int size = av_samples_get_buffer_size(NULL, nb_channels, nb_samples, | |
187 | sample_fmt, align); | ||
188 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
|
2 | if (size < 0) |
189 | ✗ | return size; | |
190 | |||
191 | 2 | buf = av_malloc(size); | |
192 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
|
2 | if (!buf) |
193 | ✗ | return AVERROR(ENOMEM); | |
194 | |||
195 | 2 | size = av_samples_fill_arrays(audio_data, linesize, buf, nb_channels, | |
196 | nb_samples, sample_fmt, align); | ||
197 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
|
2 | if (size < 0) { |
198 | ✗ | av_free(buf); | |
199 | ✗ | return size; | |
200 | } | ||
201 | |||
202 | 2 | av_samples_set_silence(audio_data, 0, nb_samples, nb_channels, sample_fmt); | |
203 | |||
204 | 2 | return size; | |
205 | } | ||
206 | |||
207 | 2 | int av_samples_alloc_array_and_samples(uint8_t ***audio_data, int *linesize, int nb_channels, | |
208 | int nb_samples, enum AVSampleFormat sample_fmt, int align) | ||
209 | { | ||
210 |
1/2✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
|
2 | int ret, nb_planes = av_sample_fmt_is_planar(sample_fmt) ? nb_channels : 1; |
211 | |||
212 | 2 | *audio_data = av_calloc(nb_planes, sizeof(**audio_data)); | |
213 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
|
2 | if (!*audio_data) |
214 | ✗ | return AVERROR(ENOMEM); | |
215 | 2 | ret = av_samples_alloc(*audio_data, linesize, nb_channels, | |
216 | nb_samples, sample_fmt, align); | ||
217 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
|
2 | if (ret < 0) |
218 | ✗ | av_freep(audio_data); | |
219 | 2 | return ret; | |
220 | } | ||
221 | |||
222 | 31760 | int av_samples_copy(uint8_t * const *dst, uint8_t * const *src, int dst_offset, | |
223 | int src_offset, int nb_samples, int nb_channels, | ||
224 | enum AVSampleFormat sample_fmt) | ||
225 | { | ||
226 | 31760 | int planar = av_sample_fmt_is_planar(sample_fmt); | |
227 |
2/2✓ Branch 0 taken 2164 times.
✓ Branch 1 taken 29596 times.
|
31760 | int planes = planar ? nb_channels : 1; |
228 |
2/2✓ Branch 1 taken 29596 times.
✓ Branch 2 taken 2164 times.
|
31760 | int block_align = av_get_bytes_per_sample(sample_fmt) * (planar ? 1 : nb_channels); |
229 | 31760 | int data_size = nb_samples * block_align; | |
230 | int i; | ||
231 | |||
232 | 31760 | dst_offset *= block_align; | |
233 | 31760 | src_offset *= block_align; | |
234 | |||
235 |
4/4✓ Branch 0 taken 9870 times.
✓ Branch 1 taken 21890 times.
✓ Branch 2 taken 31692 times.
✓ Branch 3 taken 68 times.
|
31760 | if((dst[0] < src[0] ? src[0] - dst[0] : dst[0] - src[0]) >= data_size) { |
236 |
2/2✓ Branch 0 taken 33032 times.
✓ Branch 1 taken 31692 times.
|
64724 | for (i = 0; i < planes; i++) |
237 | 33032 | memcpy(dst[i] + dst_offset, src[i] + src_offset, data_size); | |
238 | } else { | ||
239 |
2/2✓ Branch 0 taken 128 times.
✓ Branch 1 taken 68 times.
|
196 | for (i = 0; i < planes; i++) |
240 | 128 | memmove(dst[i] + dst_offset, src[i] + src_offset, data_size); | |
241 | } | ||
242 | |||
243 | 31760 | return 0; | |
244 | } | ||
245 | |||
246 | 233286 | int av_samples_set_silence(uint8_t * const *audio_data, int offset, int nb_samples, | |
247 | int nb_channels, enum AVSampleFormat sample_fmt) | ||
248 | { | ||
249 | 233286 | int planar = av_sample_fmt_is_planar(sample_fmt); | |
250 |
2/2✓ Branch 0 taken 19095 times.
✓ Branch 1 taken 214191 times.
|
233286 | int planes = planar ? nb_channels : 1; |
251 |
2/2✓ Branch 1 taken 214191 times.
✓ Branch 2 taken 19095 times.
|
233286 | int block_align = av_get_bytes_per_sample(sample_fmt) * (planar ? 1 : nb_channels); |
252 | 233286 | int data_size = nb_samples * block_align; | |
253 |
2/2✓ Branch 0 taken 66 times.
✓ Branch 1 taken 232943 times.
|
233009 | int fill_char = (sample_fmt == AV_SAMPLE_FMT_U8 || |
254 |
2/2✓ Branch 0 taken 233009 times.
✓ Branch 1 taken 277 times.
|
466295 | sample_fmt == AV_SAMPLE_FMT_U8P) ? 0x80 : 0x00; |
255 | int i; | ||
256 | |||
257 | 233286 | offset *= block_align; | |
258 | |||
259 |
2/2✓ Branch 0 taken 244039 times.
✓ Branch 1 taken 233286 times.
|
477325 | for (i = 0; i < planes; i++) |
260 | 244039 | memset(audio_data[i] + offset, fill_char, data_size); | |
261 | |||
262 | 233286 | return 0; | |
263 | } | ||
264 |