]> git.sesse.net Git - casparcg/commitdiff
git-svn-id: https://casparcg.svn.sourceforge.net/svnroot/casparcg/server/branches...
authorronag <ronag@362d55ac-95cf-4e76-9f9a-cbaa9c17b72d>
Fri, 23 Mar 2012 21:23:31 +0000 (21:23 +0000)
committerronag <ronag@362d55ac-95cf-4e76-9f9a-cbaa9c17b72d>
Fri, 23 Mar 2012 21:23:31 +0000 (21:23 +0000)
modules/decklink/consumer/decklink_consumer.cpp
modules/ffmpeg/consumer/ffmpeg_consumer.cpp

index 3bd0cc37060707248d9b63b93bf80460023ed277..db0b2bf254768d0e2a8cf71b06f29736f86a6ceb 100644 (file)
@@ -92,7 +92,7 @@ struct configuration
 class decklink_frame : public IDeckLinkVideoFrame\r
 {\r
        tbb::atomic<int>                                                                                        ref_count_;\r
-       core::const_frame                                                                               frame_;\r
+       core::const_frame                                                                                       frame_;\r
        const core::video_format_desc                                                           format_desc_;\r
 \r
        const bool                                                                                                      key_only_;\r
index 55fe20e25480b78fb6b5389a6ae07bf4bd540f71..280a8e9a6a9cdd4649384e03a60f1a3383207417 100644 (file)
 #include <core/consumer/frame_consumer.h>\r
 #include <core/video_format.h>\r
 \r
+#include <common/array.h>\r
 #include <common/env.h>\r
-#include <common/utf.h>\r
-#include <common/param.h>\r
+#include <common/except.h>\r
 #include <common/executor.h>\r
 #include <common/diagnostics/graph.h>\r
-#include <common/array.h>\r
+#include <common/lock.h>\r
 #include <common/memory.h>\r
+#include <common/param.h>\r
+#include <common/utf.h>\r
 \r
 #include <boost/algorithm/string.hpp>\r
 #include <boost/timer.hpp>\r
@@ -48,6 +50,8 @@
 #include <boost/range/algorithm_ext.hpp>\r
 #include <boost/lexical_cast.hpp>\r
 \r
+#include <tbb/spin_mutex.h>\r
+\r
 #if defined(_MSC_VER)\r
 #pragma warning (push)\r
 #pragma warning (disable : 4244)\r
@@ -238,7 +242,9 @@ struct ffmpeg_consumer : boost::noncopyable
        const core::video_format_desc                   format_desc_;\r
        \r
        const spl::shared_ptr<diagnostics::graph>               graph_;\r
-\r
+       \r
+       tbb::spin_mutex                                                 exception_mutex_;\r
+       std::exception_ptr                                              exception_;\r
        \r
        std::shared_ptr<AVStream>                               audio_st_;\r
        std::shared_ptr<AVStream>                               video_st_;\r
@@ -454,40 +460,32 @@ public:
                        return;\r
                \r
                auto enc = video_st_->codec;\r
-\r
-               try\r
-               {                \r
-                       auto av_frame                           = convert_video(frame, enc);\r
-                       av_frame->interlaced_frame      = format_desc_.field_mode != core::field_mode::progressive;\r
-                       av_frame->top_field_first       = format_desc_.field_mode == core::field_mode::upper;\r
-                       av_frame->pts                           = frame_number_++;\r
-\r
-                       AVPacket pkt;\r
-                       av_init_packet(&pkt);\r
-                       pkt.data = nullptr;\r
-                       pkt.size = 0;\r
-\r
-                       int got_packet = 0;\r
-                       THROW_ON_ERROR2(avcodec_encode_video2(enc, &pkt, av_frame.get(), &got_packet), "[ffmpeg_consumer]");\r
-                       std::shared_ptr<AVPacket> guard(&pkt, av_free_packet);\r
-\r
-                       if(!got_packet)\r
-                               return;\r
+        \r
+               auto av_frame                           = convert_video(frame, enc);\r
+               av_frame->interlaced_frame      = format_desc_.field_mode != core::field_mode::progressive;\r
+               av_frame->top_field_first       = format_desc_.field_mode == core::field_mode::upper;\r
+               av_frame->pts                           = frame_number_++;\r
+\r
+               AVPacket pkt;\r
+               av_init_packet(&pkt);\r
+               pkt.data = nullptr;\r
+               pkt.size = 0;\r
+\r
+               int got_packet = 0;\r
+               THROW_ON_ERROR2(avcodec_encode_video2(enc, &pkt, av_frame.get(), &got_packet), "[ffmpeg_consumer]");\r
+               std::shared_ptr<AVPacket> guard(&pkt, av_free_packet);\r
+\r
+               if(!got_packet)\r
+                       return;\r
                 \r
-                       if (pkt.pts != AV_NOPTS_VALUE)\r
-                               pkt.pts = av_rescale_q(pkt.pts, enc->time_base, video_st_->time_base);\r
-                       if (pkt.dts != AV_NOPTS_VALUE)\r
-                               pkt.dts = av_rescale_q(pkt.dts, enc->time_base, video_st_->time_base);\r
+               if (pkt.pts != AV_NOPTS_VALUE)\r
+                       pkt.pts = av_rescale_q(pkt.pts, enc->time_base, video_st_->time_base);\r
+               if (pkt.dts != AV_NOPTS_VALUE)\r
+                       pkt.dts = av_rescale_q(pkt.dts, enc->time_base, video_st_->time_base);\r
                 \r
-                       pkt.stream_index = video_st_->index;\r
+               pkt.stream_index = video_st_->index;\r
                        \r
-                       THROW_ON_ERROR2(av_interleaved_write_frame(oc_.get(), &pkt), "[ffmpeg_consumer]");\r
-               }\r
-               catch(...)\r
-               {\r
-                       CASPAR_LOG_CURRENT_EXCEPTION();\r
-                       executor_.stop();\r
-               }\r
+               THROW_ON_ERROR2(av_interleaved_write_frame(oc_.get(), &pkt), "[ffmpeg_consumer]");\r
        }\r
                \r
        uint64_t get_channel_layout(AVCodecContext* dec)\r
@@ -503,50 +501,42 @@ public:
                \r
                auto enc = audio_st_->codec;\r
 \r
-               try\r
-               {\r
-                       boost::push_back(audio_buffer_, convert_audio(frame, enc));\r
+               boost::push_back(audio_buffer_, convert_audio(frame, enc));\r
                        \r
-                       auto frame_size = enc->frame_size != 0 ? enc->frame_size * enc->channels * av_get_bytes_per_sample(enc->sample_fmt) : static_cast<int>(audio_buffer_.size());\r
+               auto frame_size = enc->frame_size != 0 ? enc->frame_size * enc->channels * av_get_bytes_per_sample(enc->sample_fmt) : static_cast<int>(audio_buffer_.size());\r
                        \r
-                       while(audio_buffer_.size() >= frame_size)\r
-                       {                       \r
-                               std::shared_ptr<AVFrame> av_frame(avcodec_alloc_frame(), av_free);\r
-                               avcodec_get_frame_defaults(av_frame.get());             \r
-                               av_frame->nb_samples = frame_size / (enc->channels * av_get_bytes_per_sample(enc->sample_fmt));\r
-\r
-                               AVPacket pkt;\r
-                               av_init_packet(&pkt);\r
-                               pkt.data = nullptr;\r
-                               pkt.size = 0;                           \r
+               while(audio_buffer_.size() >= frame_size)\r
+               {                       \r
+                       std::shared_ptr<AVFrame> av_frame(avcodec_alloc_frame(), av_free);\r
+                       avcodec_get_frame_defaults(av_frame.get());             \r
+                       av_frame->nb_samples = frame_size / (enc->channels * av_get_bytes_per_sample(enc->sample_fmt));\r
+\r
+                       AVPacket pkt;\r
+                       av_init_packet(&pkt);\r
+                       pkt.data = nullptr;\r
+                       pkt.size = 0;                           \r
                        \r
-                               THROW_ON_ERROR2(avcodec_fill_audio_frame(av_frame.get(), enc->channels, enc->sample_fmt, audio_buffer_.data(), frame_size, 1), "[ffmpeg_consumer]");\r
+                       THROW_ON_ERROR2(avcodec_fill_audio_frame(av_frame.get(), enc->channels, enc->sample_fmt, audio_buffer_.data(), frame_size, 1), "[ffmpeg_consumer]");\r
 \r
-                               int got_packet = 0;\r
-                               THROW_ON_ERROR2(avcodec_encode_audio2(enc, &pkt, av_frame.get(), &got_packet), "[ffmpeg_consumer]");\r
-                               std::shared_ptr<AVPacket> guard(&pkt, av_free_packet);\r
+                       int got_packet = 0;\r
+                       THROW_ON_ERROR2(avcodec_encode_audio2(enc, &pkt, av_frame.get(), &got_packet), "[ffmpeg_consumer]");\r
+                       std::shared_ptr<AVPacket> guard(&pkt, av_free_packet);\r
                                \r
-                               audio_buffer_.erase(audio_buffer_.begin(), audio_buffer_.begin() + frame_size);\r
+                       audio_buffer_.erase(audio_buffer_.begin(), audio_buffer_.begin() + frame_size);\r
 \r
-                               if(!got_packet)\r
-                                       return;\r
+                       if(!got_packet)\r
+                               return;\r
                \r
-                               if (pkt.pts != AV_NOPTS_VALUE)\r
-                                       pkt.pts      = av_rescale_q(pkt.pts, enc->time_base, audio_st_->time_base);\r
-                               if (pkt.dts != AV_NOPTS_VALUE)\r
-                                       pkt.dts      = av_rescale_q(pkt.dts, enc->time_base, audio_st_->time_base);\r
-                               if (pkt.duration > 0)\r
-                                       pkt.duration = static_cast<int>(av_rescale_q(pkt.duration, enc->time_base, audio_st_->time_base));\r
+                       if (pkt.pts != AV_NOPTS_VALUE)\r
+                               pkt.pts      = av_rescale_q(pkt.pts, enc->time_base, audio_st_->time_base);\r
+                       if (pkt.dts != AV_NOPTS_VALUE)\r
+                               pkt.dts      = av_rescale_q(pkt.dts, enc->time_base, audio_st_->time_base);\r
+                       if (pkt.duration > 0)\r
+                               pkt.duration = static_cast<int>(av_rescale_q(pkt.duration, enc->time_base, audio_st_->time_base));\r
                \r
-                               pkt.stream_index = audio_st_->index;\r
+                       pkt.stream_index = audio_st_->index;\r
                                                \r
-                               THROW_ON_ERROR2(av_interleaved_write_frame(oc_.get(), &pkt), "[ffmpeg_consumer]");\r
-                       }\r
-               }\r
-               catch(...)\r
-               {\r
-                       CASPAR_LOG_CURRENT_EXCEPTION();\r
-                       executor_.stop();\r
+                       THROW_ON_ERROR2(av_interleaved_write_frame(oc_.get(), &pkt), "[ffmpeg_consumer]");\r
                }\r
        }                \r
        \r
@@ -627,17 +617,43 @@ public:
                return buffer;\r
        }\r
 \r
-       void send(core::const_frame& frame)\r
+       void encode(const core::const_frame& frame)\r
        {\r
-               executor_.begin_invoke([=]\r
-               {               \r
+               try\r
+               {\r
                        boost::timer frame_timer;\r
 \r
                        encode_video_frame(frame);\r
                        encode_audio_frame(frame);\r
 \r
                        graph_->set_value("frame-time", frame_timer.elapsed()*format_desc_.fps*0.5);\r
+               }\r
+               catch(...)\r
+               {                       \r
+                       lock(exception_mutex_, [&]\r
+                       {\r
+                               exception_ = std::current_exception();\r
+                       });\r
+                       executor_.stop();\r
+               }\r
+       }\r
+\r
+       bool send(core::const_frame& frame)\r
+       {\r
+               auto exception = lock(exception_mutex_, [&]\r
+               {\r
+                       return exception_;\r
                });\r
+\r
+               if(exception != nullptr)\r
+                       std::rethrow_exception(exception);\r
+                       \r
+               executor_.begin_invoke([=]\r
+               {               \r
+                       encode(frame);\r
+               });\r
+               \r
+               return true;\r
        }\r
 };\r
 \r
@@ -664,8 +680,7 @@ public:
        \r
        bool send(core::const_frame frame) override\r
        {\r
-               consumer_->send(frame);\r
-               return true;\r
+               return consumer_->send(frame);\r
        }\r
        \r
        std::wstring print() const override\r