]> git.sesse.net Git - casparcg/commitdiff
ffmpeg:
authorRobert Nagy <ronag@live.com>
Tue, 17 Dec 2013 18:04:18 +0000 (19:04 +0100)
committerRobert Nagy <ronag@live.com>
Tue, 17 Dec 2013 18:04:18 +0000 (19:04 +0100)
 - Fixed resampling of planar audio sample formats.
 - Removed filter configuration logging.

modules/ffmpeg/ffmpeg.vcxproj
modules/ffmpeg/ffmpeg.vcxproj.filters
modules/ffmpeg/producer/audio/audio_decoder.cpp
modules/ffmpeg/producer/audio/audio_resampler.cpp [deleted file]
modules/ffmpeg/producer/audio/audio_resampler.h [deleted file]
modules/ffmpeg/producer/filter/filter.cpp
shell/shell.vcxproj

index 303f39ae51eab07761bcdb9cc666fa38bd6b09b2..f72856e6e68ca30eac6bef151379b04e8d218f57 100644 (file)
     </ClCompile>\r
     <ClCompile Include="producer\audio\audio_resampler.cpp">\r
       <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">../../StdAfx.h</PrecompiledHeaderFile>\r
-      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">../../StdAfx.h</PrecompiledHeaderFile>\r
       <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Develop|Win32'">../../StdAfx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">../../StdAfx.h</PrecompiledHeaderFile>\r
       <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">../../StdAfx.h</PrecompiledHeaderFile>\r
     </ClCompile>\r
     <ClCompile Include="producer\ffmpeg_producer.cpp">\r
index 2c75f48d3e2b088375ef901c5b7a8cee4abbc676..30e946f14a4f39318f17a8565f25d042f7a3cefc 100644 (file)
@@ -46,9 +46,6 @@
     <ClCompile Include="producer\filter\filter.cpp">\r
       <Filter>source\producer\filter</Filter>\r
     </ClCompile>\r
-    <ClCompile Include="producer\audio\audio_resampler.cpp">\r
-      <Filter>source\producer\audio</Filter>\r
-    </ClCompile>\r
     <ClCompile Include="producer\util\util.cpp">\r
       <Filter>source\producer\util</Filter>\r
     </ClCompile>\r
@@ -67,6 +64,9 @@
     <ClCompile Include="producer\ffmpeg_producer.cpp">\r
       <Filter>source\producer</Filter>\r
     </ClCompile>\r
+    <ClCompile Include="producer\audio\audio_resampler.cpp">\r
+      <Filter>source\producer\audio</Filter>\r
+    </ClCompile>\r
   </ItemGroup>\r
   <ItemGroup>\r
     <ClInclude Include="producer\ffmpeg_producer.h">\r
@@ -94,9 +94,6 @@
     <ClInclude Include="producer\filter\filter.h">\r
       <Filter>source\producer\filter</Filter>\r
     </ClInclude>\r
-    <ClInclude Include="producer\audio\audio_resampler.h">\r
-      <Filter>source\producer\audio</Filter>\r
-    </ClInclude>\r
     <ClInclude Include="producer\util\flv.h">\r
       <Filter>source\producer\util</Filter>\r
     </ClInclude>\r
     <ClInclude Include="producer\tbb_avcodec.h">\r
       <Filter>source\producer</Filter>\r
     </ClInclude>\r
+    <ClInclude Include="producer\audio\audio_resampler.h">\r
+      <Filter>source\producer\audio</Filter>\r
+    </ClInclude>\r
   </ItemGroup>\r
 </Project>
\ No newline at end of file
index 4ac083b9efb4407ca25fee009148880f91c611a9..62251a4848afd67d84710c5d2972b63b6e2fd3d0 100644 (file)
@@ -43,6 +43,7 @@ extern "C"
 {\r
        #include <libavformat/avformat.h>\r
        #include <libavcodec/avcodec.h>\r
+       #include <libswresample/swresample.h>\r
 }\r
 #if defined(_MSC_VER)\r
 #pragma warning (pop)\r
@@ -52,30 +53,37 @@ namespace caspar { namespace ffmpeg {
        \r
 struct audio_decoder::implementation : boost::noncopyable\r
 {      \r
-       int                                                                                                                     index_;\r
-       const safe_ptr<AVCodecContext>                                                          codec_context_;         \r
-       const core::video_format_desc                                                           format_desc_;\r
+       int                                                                                                                             index_;\r
+       const safe_ptr<AVCodecContext>                                                                  codec_context_;         \r
+       const core::video_format_desc                                                                   format_desc_;\r
+       \r
+       std::vector<int32_t,  tbb::cache_aligned_allocator<int32_t>>    buffer_;\r
 \r
-       audio_resampler                                                                                         resampler_;\r
+       std::queue<safe_ptr<AVPacket>>                                                                  packets_;\r
 \r
-       std::vector<int8_t,  tbb::cache_aligned_allocator<int8_t>>      buffer1_;\r
+       const int64_t                                                                                                   nb_frames_;\r
+       tbb::atomic<size_t>                                                                                             file_frame_number_;\r
+       core::channel_layout                                                                                    channel_layout_;\r
 \r
-       std::queue<safe_ptr<AVPacket>>                                                          packets_;\r
+       std::shared_ptr<SwrContext>                                                                             swr_;\r
 \r
-       const int64_t                                                                                           nb_frames_;\r
-       tbb::atomic<size_t>                                                                                     file_frame_number_;\r
-       core::channel_layout                                                                            channel_layout_;\r
 public:\r
        explicit implementation(const safe_ptr<AVFormatContext>& context, const core::video_format_desc& format_desc, const std::wstring& custom_channel_order) \r
                : format_desc_(format_desc)     \r
                , codec_context_(open_codec(*context, AVMEDIA_TYPE_AUDIO, index_))\r
-               , resampler_(codec_context_->channels,          codec_context_->channels,\r
-                                        format_desc.audio_sample_rate, codec_context_->sample_rate,\r
-                                        AV_SAMPLE_FMT_S32,                             codec_context_->sample_fmt)\r
-               , buffer1_(480000*2)\r
+               , buffer_(480000*2)\r
                , nb_frames_(0)//context->streams[index_]->nb_frames)\r
                , channel_layout_(get_audio_channel_layout(*codec_context_, custom_channel_order))\r
-       {\r
+               , swr_(swr_alloc_set_opts(nullptr,\r
+                                                               codec_context_->channel_layout ? codec_context_->channel_layout : av_get_default_channel_layout(codec_context_->channels), AV_SAMPLE_FMT_S32, format_desc_.audio_sample_rate,\r
+                                                               codec_context_->channel_layout ? codec_context_->channel_layout : av_get_default_channel_layout(codec_context_->channels), codec_context_->sample_fmt, codec_context_->sample_rate,\r
+                                                               0, nullptr), [](SwrContext* p){swr_free(&p);})\r
+       {       \r
+               if(!swr_)\r
+                       BOOST_THROW_EXCEPTION(bad_alloc());\r
+               \r
+               THROW_ON_ERROR2(swr_init(swr_.get()), "[audio_decoder]");\r
+\r
                file_frame_number_ = 0;\r
 \r
                CASPAR_LOG(debug) << print() \r
@@ -115,26 +123,39 @@ public:
        }\r
 \r
        std::shared_ptr<core::audio_buffer> decode(AVPacket& pkt)\r
-       {               \r
-               buffer1_.resize(480000*2);\r
-               int written_bytes = buffer1_.size() - FF_INPUT_BUFFER_PADDING_SIZE;\r
+       {                               \r
+               std::shared_ptr<AVFrame> frame(\r
+                       av_frame_alloc(), \r
+                       [](AVFrame* p)\r
+                       {\r
+                               av_frame_free(&p);\r
+                       });\r
                \r
-               int ret = THROW_ON_ERROR2(avcodec_decode_audio3(codec_context_.get(), reinterpret_cast<int16_t*>(buffer1_.data()), &written_bytes, &pkt), "[audio_decoder]");\r
-\r
-               // There might be several frames in one packet.\r
-               pkt.size -= ret;\r
-               pkt.data += ret;\r
-                       \r
-               buffer1_.resize(written_bytes);\r
+               int got_frame = 0;\r
+               auto len = THROW_ON_ERROR2(avcodec_decode_audio4(codec_context_.get(), frame.get(), &got_frame, &pkt), "[audio_decoder]");\r
+                                       \r
+               if(len == 0)\r
+               {\r
+                       pkt.size = 0;\r
+                       return nullptr;\r
+               }\r
 \r
-               buffer1_ = resampler_.resample(std::move(buffer1_));\r
+        pkt.data += len;\r
+        pkt.size -= len;\r
+                                       \r
+               if(!got_frame)\r
+                       return nullptr;\r
+                               \r
+               const uint8_t **in = const_cast<const uint8_t**>(frame->extended_data);                 \r
+               uint8_t* out[]     = { reinterpret_cast<uint8_t*>(buffer_.data()) };\r
+               \r
+               const auto channel_samples = swr_convert(swr_.get(), \r
+                                                                                                out, static_cast<int>(buffer_.size()) / codec_context_->channels, \r
+                                                                                                in, frame->nb_samples);\r
                \r
-               const auto n_samples = buffer1_.size() / av_get_bytes_per_sample(AV_SAMPLE_FMT_S32);\r
-               const auto samples = reinterpret_cast<int32_t*>(buffer1_.data());\r
-\r
                ++file_frame_number_;\r
 \r
-               return std::make_shared<core::audio_buffer>(samples, samples + n_samples);\r
+               return std::make_shared<core::audio_buffer>(buffer_.begin(), buffer_.begin() + channel_samples * frame->channels);\r
        }\r
 \r
        bool ready() const\r
diff --git a/modules/ffmpeg/producer/audio/audio_resampler.cpp b/modules/ffmpeg/producer/audio/audio_resampler.cpp
deleted file mode 100644 (file)
index 3e7fd57..0000000
+++ /dev/null
@@ -1,109 +0,0 @@
-/*\r
-* Copyright 2013 Sveriges Television AB http://casparcg.com/\r
-*\r
-* This file is part of CasparCG (www.casparcg.com).\r
-*\r
-* CasparCG is free software: you can redistribute it and/or modify\r
-* it under the terms of the GNU General Public License as published by\r
-* the Free Software Foundation, either version 3 of the License, or\r
-* (at your option) any later version.\r
-*\r
-* CasparCG is distributed in the hope that it will be useful,\r
-* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
-* GNU General Public License for more details.\r
-*\r
-* You should have received a copy of the GNU General Public License\r
-* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
-*\r
-* Author: Robert Nagy, ronag89@gmail.com\r
-*/\r
-\r
-#include "../../StdAfx.h"\r
-\r
-#include "audio_resampler.h"\r
-\r
-#include <common/exception/exceptions.h>\r
-\r
-#if defined(_MSC_VER)\r
-#pragma warning (push)\r
-#pragma warning (disable : 4244)\r
-#endif\r
-extern "C" \r
-{\r
-       #include <libavcodec/avcodec.h>\r
-}\r
-#if defined(_MSC_VER)\r
-#pragma warning (pop)\r
-#endif\r
-\r
-namespace caspar { namespace ffmpeg {\r
-\r
-struct audio_resampler::implementation\r
-{      \r
-       std::shared_ptr<ReSampleContext> resampler_;\r
-       \r
-       std::vector<int8_t, tbb::cache_aligned_allocator<int8_t>> copy_buffer_;\r
-       std::vector<int8_t, tbb::cache_aligned_allocator<int8_t>> buffer2_;\r
-\r
-       const size_t                    output_channels_;\r
-       const AVSampleFormat    output_sample_format_;\r
-\r
-       const size_t                    input_channels_;\r
-       const AVSampleFormat    input_sample_format_;\r
-\r
-       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
-               : output_channels_(output_channels)\r
-               , output_sample_format_(output_sample_format)\r
-               , input_channels_(input_channels)\r
-               , input_sample_format_(input_sample_format)\r
-       {\r
-               if(input_channels               != output_channels || \r
-                  input_sample_rate    != output_sample_rate ||\r
-                  input_sample_format  != output_sample_format)\r
-               {       \r
-                       auto resampler = av_audio_resample_init(output_channels,                input_channels,\r
-                                                                                                       output_sample_rate,             input_sample_rate,\r
-                                                                                                       output_sample_format,   input_sample_format,\r
-                                                                                                       16, 10, 0, 0.8);\r
-\r
-                       buffer2_.resize(480000*2);\r
-\r
-                       char sample_fmt_string[200];\r
-                       av_get_sample_fmt_string(sample_fmt_string, 200, input_sample_format);\r
-\r
-                       CASPAR_LOG(warning) << L"[audio-resampler]"             \r
-                                                               << L" sample-rate: "    << input_sample_rate \r
-                                                               << L" channels: "               << input_channels \r
-                                                               << L" sample-fmt: "             << widen(sample_fmt_string);\r
-\r
-                       if(resampler)\r
-                               resampler_.reset(resampler, audio_resample_close);\r
-                       else\r
-                               BOOST_THROW_EXCEPTION(caspar_exception());\r
-               }               \r
-       }\r
-\r
-       std::vector<int8_t, tbb::cache_aligned_allocator<int8_t>> resample(std::vector<int8_t, tbb::cache_aligned_allocator<int8_t>>&& data)\r
-       {\r
-               if(resampler_ && !data.empty())\r
-               {\r
-                       buffer2_.resize(480000*2);\r
-                       auto ret = audio_resample(resampler_.get(),\r
-                                                                         reinterpret_cast<short*>(buffer2_.data()), \r
-                                                                         reinterpret_cast<short*>(data.data()), \r
-                                                                         data.size() / (av_get_bytes_per_sample(input_sample_format_) * input_channels_)); \r
-                       buffer2_.resize(ret * av_get_bytes_per_sample(output_sample_format_) * output_channels_);\r
-                       std::swap(data, buffer2_);\r
-               }\r
-\r
-               return std::move(data);\r
-       }\r
-};\r
-\r
-\r
-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
-                               : impl_(new implementation(output_channels, input_channels, output_sample_rate, input_sample_rate, output_sample_format, input_sample_format)){}\r
-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
-\r
-}}
\ No newline at end of file
diff --git a/modules/ffmpeg/producer/audio/audio_resampler.h b/modules/ffmpeg/producer/audio/audio_resampler.h
deleted file mode 100644 (file)
index ebc734e..0000000
+++ /dev/null
@@ -1,43 +0,0 @@
-/*\r
-* Copyright 2013 Sveriges Television AB http://casparcg.com/\r
-*\r
-* This file is part of CasparCG (www.casparcg.com).\r
-*\r
-* CasparCG is free software: you can redistribute it and/or modify\r
-* it under the terms of the GNU General Public License as published by\r
-* the Free Software Foundation, either version 3 of the License, or\r
-* (at your option) any later version.\r
-*\r
-* CasparCG is distributed in the hope that it will be useful,\r
-* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
-* GNU General Public License for more details.\r
-*\r
-* You should have received a copy of the GNU General Public License\r
-* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
-*\r
-* Author: Robert Nagy, ronag89@gmail.com\r
-*/\r
-\r
-#pragma once\r
-\r
-#include <memory>\r
-\r
-#include <libavutil/samplefmt.h>\r
-\r
-namespace caspar { namespace ffmpeg {\r
-\r
-class audio_resampler\r
-{\r
-public:\r
-       audio_resampler(size_t                  output_channels,                size_t                  input_channels, \r
-                                       size_t                  output_sample_rate,             size_t                  input_sample_rate, \r
-                                       AVSampleFormat  output_sample_format,   AVSampleFormat  input_sample_format);\r
-       \r
-       std::vector<int8_t, tbb::cache_aligned_allocator<int8_t>> resample(std::vector<int8_t, tbb::cache_aligned_allocator<int8_t>>&& data);\r
-private:\r
-       struct implementation;\r
-       std::shared_ptr<implementation> impl_;\r
-};\r
-\r
-}}
\ No newline at end of file
index 5c608e978615762b88f12cf7f5c695313a1f5ecb..de6486d9b1dff728c9f1c91c376aadd5330b4b50 100644 (file)
@@ -153,11 +153,11 @@ struct filter::implementation
                video_graph_in_  = filt_vsrc;\r
                video_graph_out_ = filt_vsink;\r
                \r
-               CASPAR_LOG(info)\r
-                       <<      widen(std::string("\n") \r
-                               + avfilter_graph_dump(\r
-                                               video_graph_.get(), \r
-                                               nullptr));\r
+               //CASPAR_LOG(info)\r
+               //      <<      widen(std::string("\n") \r
+               //              + avfilter_graph_dump(\r
+               //                              video_graph_.get(), \r
+               //                              nullptr));\r
        }\r
        \r
        void configure_filtergraph(\r
index e959d6e0a373dd0c3191448f3175aa165e7de8bf..278b9eae822368c3865778325107e7d65aae4bda 100644 (file)
       <ForcedIncludeFiles>common/compiler/vs/disable_silly_warnings.h</ForcedIncludeFiles>\r
     </ClCompile>\r
     <Link>\r
-      <AdditionalDependencies>sfml-system-s-d.lib;sfml-audio-s-d.lib;sfml-window-s-d.lib;sfml-graphics-s-d.lib;OpenGL32.lib;FreeImage.lib;Winmm.lib;Ws2_32.lib;avformat.lib;avcodec.lib;avdevice.lib;avutil.lib;avfilter.lib;swscale.lib;tbb.lib;glew32.lib;zdll.lib</AdditionalDependencies>\r
+      <AdditionalDependencies>sfml-system-s-d.lib;sfml-audio-s-d.lib;sfml-window-s-d.lib;sfml-graphics-s-d.lib;OpenGL32.lib;FreeImage.lib;Winmm.lib;Ws2_32.lib;avformat.lib;avcodec.lib;avdevice.lib;avutil.lib;avfilter.lib;swscale.lib;swresample.lib;tbb.lib;glew32.lib;zdll.lib</AdditionalDependencies>\r
       <Version>\r
       </Version>\r
       <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>\r
@@ -242,7 +242,7 @@ copy "$(ProjectDir)casparcg_auto_restart.bat" "$(OutDir)"</Command>
       </Command>\r
     </PreLinkEvent>\r
     <Link>\r
-      <AdditionalDependencies>sfml-system-s.lib;sfml-audio-s.lib;sfml-window-s.lib;sfml-graphics-s.lib;OpenGL32.lib;FreeImage.lib;Winmm.lib;Ws2_32.lib;avformat.lib;avcodec.lib;avdevice.lib;avutil.lib;avfilter.lib;swscale.lib;tbb.lib;glew32.lib;zdll.lib</AdditionalDependencies>\r
+      <AdditionalDependencies>sfml-system-s.lib;sfml-audio-s.lib;sfml-window-s.lib;sfml-graphics-s.lib;OpenGL32.lib;FreeImage.lib;Winmm.lib;Ws2_32.lib;avformat.lib;avcodec.lib;avdevice.lib;avutil.lib;avfilter.lib;swscale.lib;swresample.lib;tbb.lib;glew32.lib;zdll.lib</AdditionalDependencies>\r
       <Version>\r
       </Version>\r
       <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>\r