]> git.sesse.net Git - casparcg/commitdiff
2.0.0.2: ffmpeg_producer: Started work on audio-resampling.
authorRonag <Ronag@362d55ac-95cf-4e76-9f9a-cbaa9c17b72d>
Wed, 27 Jul 2011 20:32:59 +0000 (20:32 +0000)
committerRonag <Ronag@362d55ac-95cf-4e76-9f9a-cbaa9c17b72d>
Wed, 27 Jul 2011 20:32:59 +0000 (20:32 +0000)
git-svn-id: https://casparcg.svn.sourceforge.net/svnroot/casparcg/server/branches/2.0.0.2@995 362d55ac-95cf-4e76-9f9a-cbaa9c17b72d

modules/ffmpeg/producer/audio/audio_decoder.cpp
modules/ffmpeg/producer/video/video_decoder.cpp
shell/casparcg.config

index b96a25eec7afabee5095b26e075f496496028248..c451675585532d5639a2e661b2cb668ce660d273 100644 (file)
@@ -45,13 +45,15 @@ struct audio_decoder::implementation : boost::noncopyable
        std::shared_ptr<AVCodecContext>                                                         codec_context_;         \r
        const core::video_format_desc                                                           format_desc_;\r
        int                                                                                                                     index_;\r
-       std::vector<int16_t, tbb::cache_aligned_allocator<int16_t>>     buffer_;                // avcodec_decode_audio3 needs 4 byte alignment\r
+       std::vector<int8_t, tbb::cache_aligned_allocator<int8_t>>       buffer1_;               // avcodec_decode_audio3 needs 4 byte alignment\r
+       std::vector<int8_t, tbb::cache_aligned_allocator<int8_t>>       buffer2_;               // avcodec_decode_audio3 needs 4 byte alignment\r
        std::vector<int16_t, tbb::cache_aligned_allocator<int16_t>>     audio_samples_;         // avcodec_decode_audio3 needs 4 byte alignment\r
        std::queue<std::shared_ptr<AVPacket>>                                           packets_;\r
+       std::shared_ptr<ReSampleContext>                                                        resampler_;\r
 public:\r
        explicit implementation(const std::shared_ptr<AVFormatContext>& context, const core::video_format_desc& format_desc) \r
                : format_desc_(format_desc)     \r
-       {\r
+       {                          \r
                AVCodec* dec;\r
                index_ = av_find_best_stream(context.get(), AVMEDIA_TYPE_AUDIO, -1, -1, &dec, 0);\r
 \r
@@ -63,13 +65,20 @@ public:
 \r
                if(codec_context_ &&\r
                   (codec_context_->sample_rate != static_cast<int>(format_desc_.audio_sample_rate) || \r
-                  codec_context_->channels != static_cast<int>(format_desc_.audio_channels)))\r
+                   codec_context_->channels    != static_cast<int>(format_desc_.audio_channels)) ||\r
+                       codec_context_->sample_fmt      != AV_SAMPLE_FMT_S16)\r
                {       \r
-                       BOOST_THROW_EXCEPTION(\r
-                               file_read_error()  <<\r
-                               msg_info("Invalid sample-rate or number of channels.") <<\r
-                               arg_value_info(boost::lexical_cast<std::string>(codec_context_->sample_rate)) << \r
-                               arg_name_info("codec_context"));\r
+                       auto resampler = av_audio_resample_init(format_desc_.audio_channels,    codec_context_->channels,
+                                                                                                       format_desc_.audio_sample_rate, codec_context_->sample_rate,
+                                                                                                       AV_SAMPLE_FMT_S16,                              codec_context_->sample_fmt,
+                                                                                                       16, 10, 0, 0.8);\r
+\r
+                       CASPAR_LOG(warning) << L" Invalid audio format.";\r
+\r
+                       if(resampler)\r
+                               resampler_.reset(resampler, audio_resample_close);\r
+                       else\r
+                               codec_context_ = nullptr;\r
                }               \r
        }\r
 \r
@@ -122,10 +131,10 @@ public:
                }\r
                else\r
                {\r
-                       buffer_.resize(4*format_desc_.audio_sample_rate*2+FF_INPUT_BUFFER_PADDING_SIZE/2, 0);\r
-\r
-                       int written_bytes = buffer_.size() - FF_INPUT_BUFFER_PADDING_SIZE/2;\r
-                       const int errn = avcodec_decode_audio3(codec_context_.get(), buffer_.data(), &written_bytes, packet.get());\r
+                       buffer1_.resize(AVCODEC_MAX_AUDIO_FRAME_SIZE*2, 0);\r
+                       int written_bytes = buffer1_.size() - FF_INPUT_BUFFER_PADDING_SIZE;\r
+                       // TODO: Packet might contain multiple frames\r
+                       const int errn = avcodec_decode_audio3(codec_context_.get(), reinterpret_cast<int16_t*>(buffer1_.data()), &written_bytes, packet.get());\r
                        if(errn < 0)\r
                        {       \r
                                BOOST_THROW_EXCEPTION(\r
@@ -134,9 +143,23 @@ public:
                                        boost::errinfo_errno(AVUNERROR(errn)));\r
                        }\r
 \r
-                       buffer_.resize(written_bytes/2);\r
-                       audio_samples_.insert(audio_samples_.end(), buffer_.begin(), buffer_.end());\r
-                       buffer_.clear();        \r
+                       buffer1_.resize(written_bytes);\r
+\r
+                       if(resampler_)\r
+                       {\r
+                               buffer2_.resize(AVCODEC_MAX_AUDIO_FRAME_SIZE*2, 0);\r
+                               auto ret = audio_resample(resampler_.get(),\r
+                                                                                 reinterpret_cast<short*>(buffer2_.data()), \r
+                                                                                 reinterpret_cast<short*>(buffer1_.data()), \r
+                                                                                 buffer1_.size() / av_get_bytes_per_sample(codec_context_->sample_fmt)); \r
+                               buffer2_.resize(ret);\r
+                               std::swap(buffer1_, buffer2_);\r
+                       }\r
+\r
+                       const auto n_samples = buffer1_.size() / av_get_bytes_per_sample(AV_SAMPLE_FMT_S16);\r
+                       const auto samples = reinterpret_cast<int16_t*>(buffer1_.data());\r
+\r
+                       audio_samples_.insert(audio_samples_.end(), samples, samples + n_samples);      \r
                }\r
        }\r
 \r
index 3894bd756ea934138c9e5ece0e49e072da2b8e32..c86e7c87f27e1804bec1d8dd612a8d279f022a4b 100644 (file)
@@ -95,6 +95,12 @@ public:
                if(double_rate(filter))\r
                        fps_ *= 2;\r
        }\r
+\r
+       ~implementation()\r
+       {\r
+               filter_tasks_.cancel();\r
+               filter_tasks_.wait();\r
+       }\r
                \r
        void push(const std::shared_ptr<AVPacket>& packet)\r
        {\r
index fe01af085ab8f55bf1ef2528b297ea5a52857d05..f6f71249395751cb6220464f3c79fd5f79c860ec 100644 (file)
@@ -18,6 +18,7 @@
       <video-mode>PAL</video-mode>\r
       <consumers>\r
         <screen></screen>\r
+        <audio></audio>\r
       </consumers>\r
     </channel>\r
 </channels>\r