]> git.sesse.net Git - casparcg/blob - modules/ffmpeg/producer/audio/audio_resampler.cpp
ffmpeg: Cleanup and bug fixes.
[casparcg] / modules / ffmpeg / producer / audio / audio_resampler.cpp
1 /*\r
2 * Copyright 2013 Sveriges Television AB http://casparcg.com/\r
3 *\r
4 * This file is part of CasparCG (www.casparcg.com).\r
5 *\r
6 * CasparCG is free software: you can redistribute it and/or modify\r
7 * it under the terms of the GNU General Public License as published by\r
8 * the Free Software Foundation, either version 3 of the License, or\r
9 * (at your option) any later version.\r
10 *\r
11 * CasparCG is distributed in the hope that it will be useful,\r
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
14 * GNU General Public License for more details.\r
15 *\r
16 * You should have received a copy of the GNU General Public License\r
17 * along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
18 *\r
19 * Author: Robert Nagy, ronag89@gmail.com\r
20 */\r
21 \r
22 #include "../../StdAfx.h"\r
23 \r
24 #include "audio_resampler.h"\r
25 \r
26 #include <common/exception/exceptions.h>\r
27 \r
28 #if defined(_MSC_VER)\r
29 #pragma warning (push)\r
30 #pragma warning (disable : 4244)\r
31 #endif\r
32 extern "C" \r
33 {\r
34         #include <libavcodec/avcodec.h>\r
35 }\r
36 #if defined(_MSC_VER)\r
37 #pragma warning (pop)\r
38 #endif\r
39 \r
40 namespace caspar { namespace ffmpeg {\r
41 \r
42 struct audio_resampler::implementation\r
43 {       \r
44         std::shared_ptr<ReSampleContext> resampler_;\r
45         \r
46         std::vector<int8_t, tbb::cache_aligned_allocator<int8_t>> copy_buffer_;\r
47         std::vector<int8_t, tbb::cache_aligned_allocator<int8_t>> buffer2_;\r
48 \r
49         const size_t                    output_channels_;\r
50         const AVSampleFormat    output_sample_format_;\r
51 \r
52         const size_t                    input_channels_;\r
53         const AVSampleFormat    input_sample_format_;\r
54 \r
55         implementation(size_t output_channels, size_t input_channels, size_t output_sample_rate, size_t input_sample_rate, AVSampleFormat output_sample_format, AVSampleFormat input_sample_format)\r
56                 : output_channels_(output_channels)\r
57                 , output_sample_format_(output_sample_format)\r
58                 , input_channels_(input_channels)\r
59                 , input_sample_format_(input_sample_format)\r
60         {\r
61                 if(input_channels               != output_channels || \r
62                    input_sample_rate    != output_sample_rate ||\r
63                    input_sample_format  != output_sample_format)\r
64                 {       \r
65                         auto resampler = av_audio_resample_init(output_channels,                input_channels,\r
66                                                                                                         output_sample_rate,             input_sample_rate,\r
67                                                                                                         output_sample_format,   input_sample_format,\r
68                                                                                                         16, 10, 0, 0.8);\r
69 \r
70                         buffer2_.resize(480000*2);\r
71 \r
72                         char sample_fmt_string[200];\r
73                         av_get_sample_fmt_string(sample_fmt_string, 200, input_sample_format);\r
74 \r
75                         CASPAR_LOG(warning) << L"[audio-resampler]"             \r
76                                                                 << L" sample-rate: "    << input_sample_rate \r
77                                                                 << L" channels: "               << input_channels \r
78                                                                 << L" sample-fmt: "             << widen(sample_fmt_string);\r
79 \r
80                         if(resampler)\r
81                                 resampler_.reset(resampler, audio_resample_close);\r
82                         else\r
83                                 BOOST_THROW_EXCEPTION(caspar_exception());\r
84                 }               \r
85         }\r
86 \r
87         std::vector<int8_t, tbb::cache_aligned_allocator<int8_t>> resample(std::vector<int8_t, tbb::cache_aligned_allocator<int8_t>>&& data)\r
88         {\r
89                 if(resampler_ && !data.empty())\r
90                 {\r
91                         buffer2_.resize(480000*2);\r
92                         auto ret = audio_resample(resampler_.get(),\r
93                                                                           reinterpret_cast<short*>(buffer2_.data()), \r
94                                                                           reinterpret_cast<short*>(data.data()), \r
95                                                                           data.size() / (av_get_bytes_per_sample(input_sample_format_) * input_channels_)); \r
96                         buffer2_.resize(ret * av_get_bytes_per_sample(output_sample_format_) * output_channels_);\r
97                         std::swap(data, buffer2_);\r
98                 }\r
99 \r
100                 return std::move(data);\r
101         }\r
102 };\r
103 \r
104 \r
105 audio_resampler::audio_resampler(size_t output_channels, size_t input_channels, size_t output_sample_rate, size_t input_sample_rate, AVSampleFormat output_sample_format, AVSampleFormat input_sample_format)\r
106                                 : impl_(new implementation(output_channels, input_channels, output_sample_rate, input_sample_rate, output_sample_format, input_sample_format)){}\r
107 std::vector<int8_t, tbb::cache_aligned_allocator<int8_t>> audio_resampler::resample(std::vector<int8_t, tbb::cache_aligned_allocator<int8_t>>&& data){return impl_->resample(std::move(data));}\r
108 \r
109 }}