Mercurial > hg > pmhd
comparison ffmpeg/doc/examples/resampling_audio.c @ 10:6840f77b83aa
commit
author | Yading Song <yading.song@eecs.qmul.ac.uk> |
---|---|
date | Sun, 21 Apr 2013 10:55:35 +0200 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
9:ed610a0bbf83 | 10:6840f77b83aa |
---|---|
1 /* | |
2 * Copyright (c) 2012 Stefano Sabatini | |
3 * | |
4 * Permission is hereby granted, free of charge, to any person obtaining a copy | |
5 * of this software and associated documentation files (the "Software"), to deal | |
6 * in the Software without restriction, including without limitation the rights | |
7 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |
8 * copies of the Software, and to permit persons to whom the Software is | |
9 * furnished to do so, subject to the following conditions: | |
10 * | |
11 * The above copyright notice and this permission notice shall be included in | |
12 * all copies or substantial portions of the Software. | |
13 * | |
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | |
17 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |
19 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | |
20 * THE SOFTWARE. | |
21 */ | |
22 | |
23 /** | |
24 * @example doc/examples/resampling_audio.c | |
25 * libswresample API use example. | |
26 */ | |
27 | |
28 #include <libavutil/opt.h> | |
29 #include <libavutil/channel_layout.h> | |
30 #include <libavutil/samplefmt.h> | |
31 #include <libswresample/swresample.h> | |
32 | |
33 static int get_format_from_sample_fmt(const char **fmt, | |
34 enum AVSampleFormat sample_fmt) | |
35 { | |
36 int i; | |
37 struct sample_fmt_entry { | |
38 enum AVSampleFormat sample_fmt; const char *fmt_be, *fmt_le; | |
39 } sample_fmt_entries[] = { | |
40 { AV_SAMPLE_FMT_U8, "u8", "u8" }, | |
41 { AV_SAMPLE_FMT_S16, "s16be", "s16le" }, | |
42 { AV_SAMPLE_FMT_S32, "s32be", "s32le" }, | |
43 { AV_SAMPLE_FMT_FLT, "f32be", "f32le" }, | |
44 { AV_SAMPLE_FMT_DBL, "f64be", "f64le" }, | |
45 }; | |
46 *fmt = NULL; | |
47 | |
48 for (i = 0; i < FF_ARRAY_ELEMS(sample_fmt_entries); i++) { | |
49 struct sample_fmt_entry *entry = &sample_fmt_entries[i]; | |
50 if (sample_fmt == entry->sample_fmt) { | |
51 *fmt = AV_NE(entry->fmt_be, entry->fmt_le); | |
52 return 0; | |
53 } | |
54 } | |
55 | |
56 fprintf(stderr, | |
57 "Sample format %s not supported as output format\n", | |
58 av_get_sample_fmt_name(sample_fmt)); | |
59 return AVERROR(EINVAL); | |
60 } | |
61 | |
62 /** | |
63 * Fill dst buffer with nb_samples, generated starting from t. | |
64 */ | |
65 void fill_samples(double *dst, int nb_samples, int nb_channels, int sample_rate, double *t) | |
66 { | |
67 int i, j; | |
68 double tincr = 1.0 / sample_rate, *dstp = dst; | |
69 const double c = 2 * M_PI * 440.0; | |
70 | |
71 /* generate sin tone with 440Hz frequency and duplicated channels */ | |
72 for (i = 0; i < nb_samples; i++) { | |
73 *dstp = sin(c * *t); | |
74 for (j = 1; j < nb_channels; j++) | |
75 dstp[j] = dstp[0]; | |
76 dstp += nb_channels; | |
77 *t += tincr; | |
78 } | |
79 } | |
80 | |
81 int main(int argc, char **argv) | |
82 { | |
83 int64_t src_ch_layout = AV_CH_LAYOUT_STEREO, dst_ch_layout = AV_CH_LAYOUT_SURROUND; | |
84 int src_rate = 48000, dst_rate = 44100; | |
85 uint8_t **src_data = NULL, **dst_data = NULL; | |
86 int src_nb_channels = 0, dst_nb_channels = 0; | |
87 int src_linesize, dst_linesize; | |
88 int src_nb_samples = 1024, dst_nb_samples, max_dst_nb_samples; | |
89 enum AVSampleFormat src_sample_fmt = AV_SAMPLE_FMT_DBL, dst_sample_fmt = AV_SAMPLE_FMT_S16; | |
90 const char *dst_filename = NULL; | |
91 FILE *dst_file; | |
92 int dst_bufsize; | |
93 const char *fmt; | |
94 struct SwrContext *swr_ctx; | |
95 double t; | |
96 int ret; | |
97 | |
98 if (argc != 2) { | |
99 fprintf(stderr, "Usage: %s output_file\n" | |
100 "API example program to show how to resample an audio stream with libswresample.\n" | |
101 "This program generates a series of audio frames, resamples them to a specified " | |
102 "output format and rate and saves them to an output file named output_file.\n", | |
103 argv[0]); | |
104 exit(1); | |
105 } | |
106 dst_filename = argv[1]; | |
107 | |
108 dst_file = fopen(dst_filename, "wb"); | |
109 if (!dst_file) { | |
110 fprintf(stderr, "Could not open destination file %s\n", dst_filename); | |
111 exit(1); | |
112 } | |
113 | |
114 /* create resampler context */ | |
115 swr_ctx = swr_alloc(); | |
116 if (!swr_ctx) { | |
117 fprintf(stderr, "Could not allocate resampler context\n"); | |
118 ret = AVERROR(ENOMEM); | |
119 goto end; | |
120 } | |
121 | |
122 /* set options */ | |
123 av_opt_set_int(swr_ctx, "in_channel_layout", src_ch_layout, 0); | |
124 av_opt_set_int(swr_ctx, "in_sample_rate", src_rate, 0); | |
125 av_opt_set_sample_fmt(swr_ctx, "in_sample_fmt", src_sample_fmt, 0); | |
126 | |
127 av_opt_set_int(swr_ctx, "out_channel_layout", dst_ch_layout, 0); | |
128 av_opt_set_int(swr_ctx, "out_sample_rate", dst_rate, 0); | |
129 av_opt_set_sample_fmt(swr_ctx, "out_sample_fmt", dst_sample_fmt, 0); | |
130 | |
131 /* initialize the resampling context */ | |
132 if ((ret = swr_init(swr_ctx)) < 0) { | |
133 fprintf(stderr, "Failed to initialize the resampling context\n"); | |
134 goto end; | |
135 } | |
136 | |
137 /* allocate source and destination samples buffers */ | |
138 | |
139 src_nb_channels = av_get_channel_layout_nb_channels(src_ch_layout); | |
140 ret = av_samples_alloc_array_and_samples(&src_data, &src_linesize, src_nb_channels, | |
141 src_nb_samples, src_sample_fmt, 0); | |
142 if (ret < 0) { | |
143 fprintf(stderr, "Could not allocate source samples\n"); | |
144 goto end; | |
145 } | |
146 | |
147 /* compute the number of converted samples: buffering is avoided | |
148 * ensuring that the output buffer will contain at least all the | |
149 * converted input samples */ | |
150 max_dst_nb_samples = dst_nb_samples = | |
151 av_rescale_rnd(src_nb_samples, dst_rate, src_rate, AV_ROUND_UP); | |
152 | |
153 /* buffer is going to be directly written to a rawaudio file, no alignment */ | |
154 dst_nb_channels = av_get_channel_layout_nb_channels(dst_ch_layout); | |
155 ret = av_samples_alloc_array_and_samples(&dst_data, &dst_linesize, dst_nb_channels, | |
156 dst_nb_samples, dst_sample_fmt, 0); | |
157 if (ret < 0) { | |
158 fprintf(stderr, "Could not allocate destination samples\n"); | |
159 goto end; | |
160 } | |
161 | |
162 t = 0; | |
163 do { | |
164 /* generate synthetic audio */ | |
165 fill_samples((double *)src_data[0], src_nb_samples, src_nb_channels, src_rate, &t); | |
166 | |
167 /* compute destination number of samples */ | |
168 dst_nb_samples = av_rescale_rnd(swr_get_delay(swr_ctx, src_rate) + | |
169 src_nb_samples, dst_rate, src_rate, AV_ROUND_UP); | |
170 if (dst_nb_samples > max_dst_nb_samples) { | |
171 av_free(dst_data[0]); | |
172 ret = av_samples_alloc(dst_data, &dst_linesize, dst_nb_channels, | |
173 dst_nb_samples, dst_sample_fmt, 1); | |
174 if (ret < 0) | |
175 break; | |
176 max_dst_nb_samples = dst_nb_samples; | |
177 } | |
178 | |
179 /* convert to destination format */ | |
180 ret = swr_convert(swr_ctx, dst_data, dst_nb_samples, (const uint8_t **)src_data, src_nb_samples); | |
181 if (ret < 0) { | |
182 fprintf(stderr, "Error while converting\n"); | |
183 goto end; | |
184 } | |
185 dst_bufsize = av_samples_get_buffer_size(&dst_linesize, dst_nb_channels, | |
186 ret, dst_sample_fmt, 1); | |
187 printf("t:%f in:%d out:%d\n", t, src_nb_samples, ret); | |
188 fwrite(dst_data[0], 1, dst_bufsize, dst_file); | |
189 } while (t < 10); | |
190 | |
191 if ((ret = get_format_from_sample_fmt(&fmt, dst_sample_fmt)) < 0) | |
192 goto end; | |
193 fprintf(stderr, "Resampling succeeded. Play the output file with the command:\n" | |
194 "ffplay -f %s -channel_layout %"PRId64" -channels %d -ar %d %s\n", | |
195 fmt, dst_ch_layout, dst_nb_channels, dst_rate, dst_filename); | |
196 | |
197 end: | |
198 if (dst_file) | |
199 fclose(dst_file); | |
200 | |
201 if (src_data) | |
202 av_freep(&src_data[0]); | |
203 av_freep(&src_data); | |
204 | |
205 if (dst_data) | |
206 av_freep(&dst_data[0]); | |
207 av_freep(&dst_data); | |
208 | |
209 swr_free(&swr_ctx); | |
210 return ret < 0; | |
211 } |