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