WinGui: Fix another instance of the Caliburn vs Json.net sillyness where objects...
[HandBrake.git] / libhb / audio_resample.c
blobe223d98dd367c29442dd0fba5e6ad793614ddde4
1 /* audio_resample.c
3 * Copyright (c) 2003-2015 HandBrake Team
4 * This file is part of the HandBrake source code
5 * Homepage: <http://handbrake.fr/>
6 * It may be used under the terms of the GNU General Public License v2.
7 * For full terms see the file COPYING file or visit http://www.gnu.org/licenses/gpl-2.0.html
8 */
10 #include "common.h"
11 #include "hbffmpeg.h"
12 #include "audio_resample.h"
14 hb_audio_resample_t* hb_audio_resample_init(enum AVSampleFormat sample_fmt,
15 int hb_amixdown, int normalize_mix)
17 hb_audio_resample_t *resample = calloc(1, sizeof(hb_audio_resample_t));
18 if (resample == NULL)
20 hb_error("hb_audio_resample_init: failed to allocate resample");
21 goto fail;
24 // avresample context, initialized in hb_audio_resample_update()
25 resample->avresample = NULL;
27 // we don't support planar output yet
28 if (av_sample_fmt_is_planar(sample_fmt))
30 hb_error("hb_audio_resample_init: planar output not supported ('%s')",
31 av_get_sample_fmt_name(sample_fmt));
32 goto fail;
35 // convert mixdown to channel_layout/matrix_encoding combo
36 int matrix_encoding;
37 uint64_t channel_layout = hb_ff_mixdown_xlat(hb_amixdown, &matrix_encoding);
40 * When downmixing, Dual Mono to Mono is a special case:
41 * the audio must remain 2-channel until all conversions are done.
43 if (hb_amixdown == HB_AMIXDOWN_LEFT || hb_amixdown == HB_AMIXDOWN_RIGHT)
45 channel_layout = AV_CH_LAYOUT_STEREO;
46 resample->dual_mono_downmix = 1;
47 resample->dual_mono_right_only = (hb_amixdown == HB_AMIXDOWN_RIGHT);
49 else
51 resample->dual_mono_downmix = 0;
54 // requested output channel_layout, sample_fmt
55 resample->out.channels = av_get_channel_layout_nb_channels(channel_layout);
56 resample->out.channel_layout = channel_layout;
57 resample->out.matrix_encoding = matrix_encoding;
58 resample->out.normalize_mix_level = normalize_mix;
59 resample->out.sample_fmt = sample_fmt;
60 resample->out.sample_size = av_get_bytes_per_sample(sample_fmt);
62 // set default input characteristics
63 resample->in.sample_fmt = resample->out.sample_fmt;
64 resample->in.channel_layout = resample->out.channel_layout;
65 resample->in.lfe_mix_level = HB_MIXLEV_ZERO;
66 resample->in.center_mix_level = HB_MIXLEV_DEFAULT;
67 resample->in.surround_mix_level = HB_MIXLEV_DEFAULT;
69 // by default, no conversion needed
70 resample->resample_needed = 0;
71 return resample;
73 fail:
74 hb_audio_resample_free(resample);
75 return NULL;
78 void hb_audio_resample_set_channel_layout(hb_audio_resample_t *resample,
79 uint64_t channel_layout)
81 if (resample != NULL)
83 if (channel_layout == AV_CH_LAYOUT_STEREO_DOWNMIX)
85 // Dolby Surround is Stereo when it comes to remixing
86 channel_layout = AV_CH_LAYOUT_STEREO;
88 resample->in.channel_layout = channel_layout;
92 void hb_audio_resample_set_mix_levels(hb_audio_resample_t *resample,
93 double surround_mix_level,
94 double center_mix_level,
95 double lfe_mix_level)
97 if (resample != NULL)
99 resample->in.lfe_mix_level = lfe_mix_level;
100 resample->in.center_mix_level = center_mix_level;
101 resample->in.surround_mix_level = surround_mix_level;
105 void hb_audio_resample_set_sample_fmt(hb_audio_resample_t *resample,
106 enum AVSampleFormat sample_fmt)
108 if (resample != NULL)
110 resample->in.sample_fmt = sample_fmt;
114 int hb_audio_resample_update(hb_audio_resample_t *resample)
116 if (resample == NULL)
118 hb_error("hb_audio_resample_update: resample is NULL");
119 return 1;
122 int ret, resample_changed;
124 resample->resample_needed =
125 (resample->out.sample_fmt != resample->in.sample_fmt ||
126 resample->out.channel_layout != resample->in.channel_layout);
128 resample_changed =
129 (resample->resample_needed &&
130 (resample->resample.sample_fmt != resample->in.sample_fmt ||
131 resample->resample.channel_layout != resample->in.channel_layout ||
132 resample->resample.lfe_mix_level != resample->in.lfe_mix_level ||
133 resample->resample.center_mix_level != resample->in.center_mix_level ||
134 resample->resample.surround_mix_level != resample->in.surround_mix_level));
136 if (resample_changed || (resample->resample_needed &&
137 resample->avresample == NULL))
139 if (resample->avresample == NULL)
141 resample->avresample = avresample_alloc_context();
142 if (resample->avresample == NULL)
144 hb_error("hb_audio_resample_update: avresample_alloc_context() failed");
145 return 1;
148 av_opt_set_int(resample->avresample, "out_sample_fmt",
149 resample->out.sample_fmt, 0);
150 av_opt_set_int(resample->avresample, "out_channel_layout",
151 resample->out.channel_layout, 0);
152 av_opt_set_int(resample->avresample, "matrix_encoding",
153 resample->out.matrix_encoding, 0);
154 av_opt_set_int(resample->avresample, "normalize_mix_level",
155 resample->out.normalize_mix_level, 0);
157 else if (resample_changed)
159 avresample_close(resample->avresample);
162 av_opt_set_int(resample->avresample, "in_sample_fmt",
163 resample->in.sample_fmt, 0);
164 av_opt_set_int(resample->avresample, "in_channel_layout",
165 resample->in.channel_layout, 0);
166 av_opt_set_double(resample->avresample, "lfe_mix_level",
167 resample->in.lfe_mix_level, 0);
168 av_opt_set_double(resample->avresample, "center_mix_level",
169 resample->in.center_mix_level, 0);
170 av_opt_set_double(resample->avresample, "surround_mix_level",
171 resample->in.surround_mix_level, 0);
173 if ((ret = avresample_open(resample->avresample)))
175 char err_desc[64];
176 av_strerror(ret, err_desc, 63);
177 hb_error("hb_audio_resample_update: avresample_open() failed (%s)",
178 err_desc);
179 // avresample won't open, start over
180 avresample_free(&resample->avresample);
181 return ret;
184 resample->resample.sample_fmt = resample->in.sample_fmt;
185 resample->resample.channel_layout = resample->in.channel_layout;
186 resample->resample.channels =
187 av_get_channel_layout_nb_channels(resample->in.channel_layout);
188 resample->resample.lfe_mix_level = resample->in.lfe_mix_level;
189 resample->resample.center_mix_level = resample->in.center_mix_level;
190 resample->resample.surround_mix_level = resample->in.surround_mix_level;
193 return 0;
196 void hb_audio_resample_free(hb_audio_resample_t *resample)
198 if (resample != NULL)
200 if (resample->avresample != NULL)
202 avresample_free(&resample->avresample);
204 free(resample);
208 hb_buffer_t* hb_audio_resample(hb_audio_resample_t *resample,
209 uint8_t **samples, int nsamples)
211 if (resample == NULL)
213 hb_error("hb_audio_resample: resample is NULL");
214 return NULL;
216 if (resample->resample_needed && resample->avresample == NULL)
218 hb_error("hb_audio_resample: resample needed but libavresample context "
219 "is NULL");
220 return NULL;
223 hb_buffer_t *out;
224 int out_size, out_samples;
226 if (resample->resample_needed)
228 int in_linesize, out_linesize;
229 // set in/out linesize and out_size
230 av_samples_get_buffer_size(&in_linesize,
231 resample->resample.channels, nsamples,
232 resample->resample.sample_fmt, 0);
233 out_size = av_samples_get_buffer_size(&out_linesize,
234 resample->out.channels, nsamples,
235 resample->out.sample_fmt, 0);
236 out = hb_buffer_init(out_size);
238 out_samples = avresample_convert(resample->avresample,
239 &out->data, out_linesize, nsamples,
240 samples, in_linesize, nsamples);
242 if (out_samples <= 0)
244 if (out_samples < 0)
245 hb_log("hb_audio_resample: avresample_convert() failed");
246 // don't send empty buffers downstream (EOF)
247 hb_buffer_close(&out);
248 return NULL;
250 out->size = (out_samples *
251 resample->out.sample_size * resample->out.channels);
253 else
255 out_samples = nsamples;
256 out_size = (out_samples *
257 resample->out.sample_size * resample->out.channels);
258 out = hb_buffer_init(out_size);
259 memcpy(out->data, samples[0], out_size);
263 * Dual Mono to Mono.
265 * Copy all left or right samples to the first half of the buffer and halve
266 * the buffer size.
268 if (resample->dual_mono_downmix)
270 int ii, jj = !!resample->dual_mono_right_only;
271 int sample_size = resample->out.sample_size;
272 uint8_t *audio_samples = out->data;
273 for (ii = 0; ii < out_samples; ii++)
275 memcpy(audio_samples + (ii * sample_size),
276 audio_samples + (jj * sample_size), sample_size);
277 jj += 2;
279 out->size = out_samples * sample_size;
282 return out;