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 | 146275 | const char *av_get_sample_fmt_name(enum AVSampleFormat sample_fmt) | |
52 | { | ||
53 |
3/4✓ Branch 0 taken 146275 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9999 times.
✓ Branch 3 taken 136276 times.
|
146275 | if (sample_fmt < 0 || sample_fmt >= AV_SAMPLE_FMT_NB) |
54 | 9999 | return NULL; | |
55 | 136276 | return sample_fmt_info[sample_fmt].name; | |
56 | } | ||
57 | |||
58 | 4581 | enum AVSampleFormat av_get_sample_fmt(const char *name) | |
59 | { | ||
60 | int i; | ||
61 | |||
62 |
2/2✓ Branch 0 taken 24724 times.
✓ Branch 1 taken 2 times.
|
24726 | for (i = 0; i < AV_SAMPLE_FMT_NB; i++) |
63 |
2/2✓ Branch 0 taken 4579 times.
✓ Branch 1 taken 20145 times.
|
24724 | if (!strcmp(sample_fmt_info[i].name, name)) |
64 | 4579 | 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 | 9972 | enum AVSampleFormat av_get_packed_sample_fmt(enum AVSampleFormat sample_fmt) | |
78 | { | ||
79 |
3/4✓ Branch 0 taken 9734 times.
✓ Branch 1 taken 238 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 9734 times.
|
9972 | if (sample_fmt < 0 || sample_fmt >= AV_SAMPLE_FMT_NB) |
80 | 238 | return AV_SAMPLE_FMT_NONE; | |
81 |
2/2✓ Branch 0 taken 6350 times.
✓ Branch 1 taken 3384 times.
|
9734 | if (sample_fmt_info[sample_fmt].planar) |
82 | 6350 | return sample_fmt_info[sample_fmt].altform; | |
83 | 3384 | return sample_fmt; | |
84 | } | ||
85 | |||
86 | 3901 | enum AVSampleFormat av_get_planar_sample_fmt(enum AVSampleFormat sample_fmt) | |
87 | { | ||
88 |
2/4✓ Branch 0 taken 3901 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 3901 times.
|
3901 | if (sample_fmt < 0 || sample_fmt >= AV_SAMPLE_FMT_NB) |
89 | ✗ | return AV_SAMPLE_FMT_NONE; | |
90 |
2/2✓ Branch 0 taken 2616 times.
✓ Branch 1 taken 1285 times.
|
3901 | if (sample_fmt_info[sample_fmt].planar) |
91 | 2616 | return sample_fmt; | |
92 | 1285 | 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 | 401175 | int av_get_bytes_per_sample(enum AVSampleFormat sample_fmt) | |
109 | { | ||
110 |
2/2✓ Branch 0 taken 400666 times.
✓ Branch 1 taken 50 times.
|
400716 | return sample_fmt < 0 || sample_fmt >= AV_SAMPLE_FMT_NB ? |
111 |
2/2✓ Branch 0 taken 400716 times.
✓ Branch 1 taken 459 times.
|
801891 | 0 : sample_fmt_info[sample_fmt].bits >> 3; |
112 | } | ||
113 | |||
114 | 392691 | int av_sample_fmt_is_planar(enum AVSampleFormat sample_fmt) | |
115 | { | ||
116 |
3/4✓ Branch 0 taken 392351 times.
✓ Branch 1 taken 340 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 392351 times.
|
392691 | if (sample_fmt < 0 || sample_fmt >= AV_SAMPLE_FMT_NB) |
117 | 340 | return 0; | |
118 | 392351 | return sample_fmt_info[sample_fmt].planar; | |
119 | } | ||
120 | |||
121 | 26693 | 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 | 26693 | int sample_size = av_get_bytes_per_sample(sample_fmt); | |
126 | 26693 | int planar = av_sample_fmt_is_planar(sample_fmt); | |
127 | |||
128 | /* validate parameter ranges */ | ||
129 |
3/6✓ Branch 0 taken 26693 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 26693 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 26693 times.
|
26693 | 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 26433 times.
✓ Branch 1 taken 260 times.
|
26693 | if (!align) { |
134 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 26433 times.
|
26433 | if (nb_samples > INT_MAX - 31) |
135 | ✗ | return AVERROR(EINVAL); | |
136 | 26433 | align = 1; | |
137 | 26433 | nb_samples = FFALIGN(nb_samples, 32); | |
138 | } | ||
139 | |||
140 | /* check for integer overflow */ | ||
141 |
1/2✓ Branch 0 taken 26693 times.
✗ Branch 1 not taken.
|
26693 | if (nb_channels > INT_MAX / align || |
142 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 26693 times.
|
26693 | (int64_t)nb_channels * nb_samples > (INT_MAX - (align * nb_channels)) / sample_size) |
143 | ✗ | return AVERROR(EINVAL); | |
144 | |||
145 |
2/2✓ Branch 0 taken 8420 times.
✓ Branch 1 taken 18273 times.
|
26693 | line_size = planar ? FFALIGN(nb_samples * sample_size, align) : |
146 | 18273 | FFALIGN(nb_samples * sample_size * nb_channels, align); | |
147 |
2/2✓ Branch 0 taken 26413 times.
✓ Branch 1 taken 280 times.
|
26693 | if (linesize) |
148 | 26413 | *linesize = line_size; | |
149 | |||
150 |
2/2✓ Branch 0 taken 8420 times.
✓ Branch 1 taken 18273 times.
|
26693 | return planar ? line_size * nb_channels : line_size; |
151 | } | ||
152 | |||
153 | 280 | 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 | 280 | planar = av_sample_fmt_is_planar(sample_fmt); | |
160 | 280 | 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 280 times.
|
280 | if (buf_size < 0) |
163 | ✗ | return buf_size; | |
164 | |||
165 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 280 times.
|
280 | if (linesize) |
166 | ✗ | *linesize = line_size; | |
167 | |||
168 |
1/2✓ Branch 0 taken 280 times.
✗ Branch 1 not taken.
|
280 | memset(audio_data, 0, planar |
169 | 280 | ? sizeof(*audio_data) * nb_channels | |
170 | : sizeof(*audio_data)); | ||
171 | |||
172 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 280 times.
|
280 | if (!buf) |
173 | ✗ | return buf_size; | |
174 | |||
175 | 280 | audio_data[0] = (uint8_t *)buf; | |
176 |
3/4✓ Branch 0 taken 568 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 288 times.
✓ Branch 3 taken 280 times.
|
568 | for (ch = 1; planar && ch < nb_channels; ch++) |
177 | 288 | audio_data[ch] = audio_data[ch-1] + line_size; | |
178 | |||
179 | 280 | 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 | 31172 | 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 | 31172 | int planar = av_sample_fmt_is_planar(sample_fmt); | |
227 |
2/2✓ Branch 0 taken 2165 times.
✓ Branch 1 taken 29007 times.
|
31172 | int planes = planar ? nb_channels : 1; |
228 |
2/2✓ Branch 1 taken 29007 times.
✓ Branch 2 taken 2165 times.
|
31172 | int block_align = av_get_bytes_per_sample(sample_fmt) * (planar ? 1 : nb_channels); |
229 | 31172 | int data_size = nb_samples * block_align; | |
230 | int i; | ||
231 | |||
232 | 31172 | dst_offset *= block_align; | |
233 | 31172 | src_offset *= block_align; | |
234 | |||
235 |
4/4✓ Branch 0 taken 4146 times.
✓ Branch 1 taken 27026 times.
✓ Branch 2 taken 31107 times.
✓ Branch 3 taken 65 times.
|
31172 | if((dst[0] < src[0] ? src[0] - dst[0] : dst[0] - src[0]) >= data_size) { |
236 |
2/2✓ Branch 0 taken 32447 times.
✓ Branch 1 taken 31107 times.
|
63554 | for (i = 0; i < planes; i++) |
237 | 32447 | memcpy(dst[i] + dst_offset, src[i] + src_offset, data_size); | |
238 | } else { | ||
239 |
2/2✓ Branch 0 taken 110 times.
✓ Branch 1 taken 65 times.
|
175 | for (i = 0; i < planes; i++) |
240 | 110 | memmove(dst[i] + dst_offset, src[i] + src_offset, data_size); | |
241 | } | ||
242 | |||
243 | 31172 | return 0; | |
244 | } | ||
245 | |||
246 | 232645 | 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 | 232645 | int planar = av_sample_fmt_is_planar(sample_fmt); | |
250 |
2/2✓ Branch 0 taken 18978 times.
✓ Branch 1 taken 213667 times.
|
232645 | int planes = planar ? nb_channels : 1; |
251 |
2/2✓ Branch 1 taken 213667 times.
✓ Branch 2 taken 18978 times.
|
232645 | int block_align = av_get_bytes_per_sample(sample_fmt) * (planar ? 1 : nb_channels); |
252 | 232645 | int data_size = nb_samples * block_align; | |
253 |
2/2✓ Branch 0 taken 66 times.
✓ Branch 1 taken 232302 times.
|
232368 | int fill_char = (sample_fmt == AV_SAMPLE_FMT_U8 || |
254 |
2/2✓ Branch 0 taken 232368 times.
✓ Branch 1 taken 277 times.
|
465013 | sample_fmt == AV_SAMPLE_FMT_U8P) ? 0x80 : 0x00; |
255 | int i; | ||
256 | |||
257 | 232645 | offset *= block_align; | |
258 | |||
259 |
2/2✓ Branch 0 taken 242078 times.
✓ Branch 1 taken 232645 times.
|
474723 | for (i = 0; i < planes; i++) |
260 | 242078 | memset(audio_data[i] + offset, fill_char, data_size); | |
261 | |||
262 | 232645 | return 0; | |
263 | } | ||
264 |