]> git.sesse.net Git - casparcg/commitdiff
2.0. ffmpeg_producer: Refactored error handling code.
authorRonag <Ronag@362d55ac-95cf-4e76-9f9a-cbaa9c17b72d>
Sat, 6 Aug 2011 15:59:40 +0000 (15:59 +0000)
committerRonag <Ronag@362d55ac-95cf-4e76-9f9a-cbaa9c17b72d>
Sat, 6 Aug 2011 15:59:40 +0000 (15:59 +0000)
git-svn-id: https://casparcg.svn.sourceforge.net/svnroot/casparcg/server/branches/2.0.0.2@1069 362d55ac-95cf-4e76-9f9a-cbaa9c17b72d

modules/ffmpeg/ffmpeg_error.h
modules/ffmpeg/producer/audio/audio_decoder.cpp
modules/ffmpeg/producer/filter/filter.cpp
modules/ffmpeg/producer/filter/parallel_yadif.cpp
modules/ffmpeg/producer/input.cpp
modules/ffmpeg/producer/video/video_decoder.cpp

index c66f9e4b71994ff84f33e006f340ab2ca8f5a46d..67e5163ee59071c28d5eba761aea17977455240b 100644 (file)
@@ -13,6 +13,8 @@ extern "C"
 \r
 namespace caspar {\r
 \r
+struct ffmpeg_error : virtual caspar_exception{};\r
+\r
 static std::string av_error_str(int errn)\r
 {\r
        char buf[256];\r
@@ -22,4 +24,34 @@ static std::string av_error_str(int errn)
        return std::string(buf);\r
 }\r
 \r
+#define THROW_ON_ERROR(ret, source, func)                                                      \\r
+       if(ret < 0)                                                                                                             \\r
+       {                                                                                                                               \\r
+               BOOST_THROW_EXCEPTION(                                                                          \\r
+                       ffmpeg_error() <<                                                                               \\r
+                       msg_info(av_error_str(ret)) <<                                                  \\r
+                       source_info(narrow(source)) <<                                                  \\r
+                       boost::errinfo_api_function(func) <<                                    \\r
+                       boost::errinfo_errno(AVUNERROR(ret)));                                  \\r
+       }\r
+\r
+#define THROW_ON_ERROR_STR_(call) #call\r
+#define THROW_ON_ERROR_STR(call) THROW_ON_ERROR_STR_(call)\r
+\r
+#define THROW_ON_ERROR2(call, source)                                                                          \\r
+       [&]() -> int                                                                                                                    \\r
+       {                                                                                                                                               \\r
+               int ret = call;                                                                                                         \\r
+               if(ret < 0)                                                                                                                     \\r
+               {                                                                                                                                       \\r
+                       BOOST_THROW_EXCEPTION(                                                                                  \\r
+                               ffmpeg_error() <<                                                                                       \\r
+                               msg_info(av_error_str(ret)) <<                                                          \\r
+                               source_info(narrow(source)) <<                                                          \\r
+                               boost::errinfo_api_function(THROW_ON_ERROR_STR(call)) <<        \\r
+                               boost::errinfo_errno(AVUNERROR(ret)));                                          \\r
+               }                                                                                                                                       \\r
+               return ret;                                                                                                                     \\r
+       }();\r
+\r
 }
\ No newline at end of file
index 519f1a5a666c8f5533c5a0d67fa5ee0d8d26029b..10f827091424d9431a183575e88f4faadada7573 100644 (file)
@@ -63,26 +63,9 @@ public:
                try\r
                {\r
                        AVCodec* dec;\r
-                       index_ = av_find_best_stream(context.get(), AVMEDIA_TYPE_AUDIO, -1, -1, &dec, 0);\r
+                       index_ = THROW_ON_ERROR2(av_find_best_stream(context.get(), AVMEDIA_TYPE_AUDIO, -1, -1, &dec, 0), "[audio_decoder]");\r
 \r
-                       if(index_ < 0)\r
-                       {\r
-                               BOOST_THROW_EXCEPTION(\r
-                                       file_read_error() <<\r
-                                       msg_info(av_error_str(index_)) <<\r
-                                       boost::errinfo_api_function("av_find_best_stream") <<\r
-                                       boost::errinfo_errno(AVUNERROR(index_)));\r
-                       }\r
-\r
-                       const int ret = avcodec_open(context->streams[index_]->codec, dec);\r
-                       if(ret < 0)\r
-                       {                               \r
-                               BOOST_THROW_EXCEPTION(\r
-                                       file_read_error() <<\r
-                                       msg_info(av_error_str(ret)) <<\r
-                                       boost::errinfo_api_function("avcodec_open") <<\r
-                                       boost::errinfo_errno(AVUNERROR(ret)));\r
-                       }\r
+                       THROW_ON_ERROR2(avcodec_open(context->streams[index_]->codec, dec), "[audio_decoder]");\r
                }\r
                catch(...)\r
                {\r
@@ -159,15 +142,7 @@ public:
                buffer1_.resize(AVCODEC_MAX_AUDIO_FRAME_SIZE*2, 0);\r
                int written_bytes = buffer1_.size() - FF_INPUT_BUFFER_PADDING_SIZE;\r
 \r
-               const int ret = avcodec_decode_audio3(codec_context_.get(), reinterpret_cast<int16_t*>(buffer1_.data()), &written_bytes, &pkt);\r
-               if(ret < 0)\r
-               {       \r
-                       BOOST_THROW_EXCEPTION(\r
-                               invalid_operation() <<\r
-                               msg_info(av_error_str(ret)) <<\r
-                               boost::errinfo_api_function("avcodec_decode_audio2") <<\r
-                               boost::errinfo_errno(AVUNERROR(ret)));\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
index a0202dd40d32c0498c04a02baf030efb2b2e6158..f890f4c15240a8c480d89a38fe6a102459beaeee 100644 (file)
@@ -76,7 +76,6 @@ struct filter::implementation
 \r
        void push(const std::shared_ptr<AVFrame>& frame)\r
        {               \r
-               int errn = 0;   \r
 \r
                if(!graph_)\r
                {\r
@@ -85,20 +84,10 @@ struct filter::implementation
                        // Input\r
                        std::stringstream args;\r
                        args << frame->width << ":" << frame->height << ":" << frame->format << ":" << 0 << ":" << 0 << ":" << 0 << ":" << 0; // don't care about pts and aspect_ratio\r
-                       errn = avfilter_graph_create_filter(&buffersrc_ctx_, avfilter_get_by_name("buffer"), "src", args.str().c_str(), NULL, graph_.get());\r
-                       if(errn < 0)\r
-                       {\r
-                               BOOST_THROW_EXCEPTION(caspar_exception() <<     msg_info(av_error_str(errn)) <<\r
-                                       boost::errinfo_api_function("avfilter_graph_create_filter") <<  boost::errinfo_errno(AVUNERROR(errn)));\r
-                       }\r
+                       THROW_ON_ERROR2(avfilter_graph_create_filter(&buffersrc_ctx_, avfilter_get_by_name("buffer"), "src", args.str().c_str(), NULL, graph_.get()), "[filter]");\r
 \r
                        // OPIX_FMT_BGRAutput\r
-                       errn = avfilter_graph_create_filter(&buffersink_ctx_, avfilter_get_by_name("buffersink"), "out", NULL, pix_fmts, graph_.get());\r
-                       if(errn < 0)\r
-                       {\r
-                               BOOST_THROW_EXCEPTION(caspar_exception() <<     msg_info(av_error_str(errn)) <<\r
-                                       boost::errinfo_api_function("avfilter_graph_create_filter") << boost::errinfo_errno(AVUNERROR(errn)));\r
-                       }\r
+                       THROW_ON_ERROR2(avfilter_graph_create_filter(&buffersink_ctx_, avfilter_get_by_name("buffersink"), "out", NULL, pix_fmts, graph_.get()), "[filter]");\r
                        \r
                        AVFilterInOut* outputs = avfilter_inout_alloc();\r
                        AVFilterInOut* inputs  = avfilter_inout_alloc();\r
@@ -113,23 +102,14 @@ struct filter::implementation
                        inputs->pad_idx                 = 0;\r
                        inputs->next                    = NULL;\r
                        \r
-                       errn = avfilter_graph_parse(graph_.get(), filters_.c_str(), &inputs, &outputs, NULL);\r
+                       int ret = avfilter_graph_parse(graph_.get(), filters_.c_str(), &inputs, &outputs, NULL);\r
 \r
                        avfilter_inout_free(&inputs);\r
                        avfilter_inout_free(&outputs);\r
-\r
-                       if(errn < 0)\r
-                       {\r
-                               BOOST_THROW_EXCEPTION(caspar_exception() <<     msg_info(av_error_str(errn)) <<\r
-                                       boost::errinfo_api_function("avfilter_graph_parse") << boost::errinfo_errno(AVUNERROR(errn)));\r
-                       }\r
                        \r
-                       errn = avfilter_graph_config(graph_.get(), NULL);\r
-                       if(errn < 0)\r
-                       {\r
-                               BOOST_THROW_EXCEPTION(caspar_exception() <<     msg_info(av_error_str(errn)) \r
-                                       <<      boost::errinfo_api_function("avfilter_graph_config") << boost::errinfo_errno(AVUNERROR(errn)));\r
-                       }\r
+                       THROW_ON_ERROR(ret, "[filter]", "avfilter_graph_parse");\r
+                                               \r
+                       THROW_ON_ERROR2(avfilter_graph_config(graph_.get(), NULL), "[filter]");\r
 \r
                        for(size_t n = 0; n < graph_->filter_count; ++n)\r
                        {\r
@@ -139,12 +119,7 @@ struct filter::implementation
                        }\r
                }\r
        \r
-               errn = av_vsrc_buffer_add_frame(buffersrc_ctx_, frame.get(), 0);\r
-               if(errn < 0)\r
-               {\r
-                       BOOST_THROW_EXCEPTION(caspar_exception() << msg_info(av_error_str(errn)) <<\r
-                               boost::errinfo_api_function("av_vsrc_buffer_add_frame") << boost::errinfo_errno(AVUNERROR(errn)));\r
-               }\r
+               THROW_ON_ERROR2(av_vsrc_buffer_add_frame(buffersrc_ctx_, frame.get(), 0), "[filter]");\r
        }\r
 \r
        std::vector<safe_ptr<AVFrame>> poll()\r
@@ -157,7 +132,8 @@ struct filter::implementation
                while (avfilter_poll_frame(buffersink_ctx_->inputs[0])) \r
                {\r
                        AVFilterBufferRef *picref;\r
-            av_vsink_buffer_get_video_buffer_ref(buffersink_ctx_, &picref, 0);\r
+                       THROW_ON_ERROR2(av_vsink_buffer_get_video_buffer_ref(buffersink_ctx_, &picref, 0), "[filter]");\r
+\r
             if (picref) \r
                        {               \r
                                safe_ptr<AVFrame> frame(avcodec_alloc_frame(), [=](AVFrame* p)\r
index 70521a1bddc45a89da649924a820ef775e988089..dcaaddd81759cb5bff7e84cadddee9f61d7e8928 100644 (file)
@@ -105,7 +105,7 @@ std::shared_ptr<void> make_parallel_yadif(AVFilterContext* ctx)
 \r
        decltype(org_yadif_filter_line) func = nullptr;\r
        if(!parallel_line_func_pool.try_pop(func))      \r
-               CASPAR_LOG(warning) << "Not enough scalable-yadif instances. Running non-scalable";\r
+               CASPAR_LOG(warning) << "Not enough scalable-yadif context instances. Running non-scalable";\r
        else\r
                yadif->filter_line = func;\r
        \r
index 56f340fb71a54610380b918853e19c7c6aec1ce1..63a088611ca0b7cd6aa29a5e36efb690f63d586d 100644 (file)
@@ -77,34 +77,13 @@ public:
                , start_(std::max(start, 0))\r
        {                       \r
                is_running_ = true;\r
-\r
-               int ret;\r
-\r
+               \r
                AVFormatContext* weak_format_context_ = nullptr;\r
-               ret = avformat_open_input(&weak_format_context_, narrow(filename).c_str(), nullptr, nullptr);\r
-               if(ret < 0 || weak_format_context_ == nullptr)\r
-               {       \r
-                       BOOST_THROW_EXCEPTION(\r
-                               file_read_error() << \r
-                               source_info(narrow(print())) << \r
-                               msg_info(av_error_str(ret)) <<\r
-                               boost::errinfo_api_function("av_open_input_file") <<\r
-                               boost::errinfo_errno(AVUNERROR(ret)) <<\r
-                               boost::errinfo_file_name(narrow(filename)));\r
-               }\r
+               THROW_ON_ERROR2(avformat_open_input(&weak_format_context_, narrow(filename).c_str(), nullptr, nullptr), print());\r
 \r
                format_context_.reset(weak_format_context_, av_close_input_file);\r
                        \r
-               ret = avformat_find_stream_info(format_context_.get(), nullptr);\r
-               if(ret < 0)\r
-               {       \r
-                       BOOST_THROW_EXCEPTION(\r
-                               file_read_error() << \r
-                               source_info(narrow(print())) << \r
-                               msg_info(av_error_str(ret)) <<\r
-                               boost::errinfo_api_function("av_find_stream_info") <<\r
-                               boost::errinfo_errno(AVUNERROR(ret)));\r
-               }\r
+               THROW_ON_ERROR2(avformat_find_stream_info(format_context_.get(), nullptr), print());\r
                \r
                if(start_ != 0)                 \r
                        seek_frame(start_);\r
@@ -172,7 +151,9 @@ private:
        }\r
                        \r
        void read_next_packet()\r
-       {                       \r
+       {               \r
+               int ret = 0;\r
+\r
                std::shared_ptr<AVPacket> read_packet(new AVPacket, [](AVPacket* p)\r
                {\r
                        av_free_packet(p);\r
@@ -180,8 +161,9 @@ private:
                });\r
                av_init_packet(read_packet.get());\r
 \r
-               const int ret = av_read_frame(format_context_.get(), read_packet.get()); // read_packet is only valid until next call of av_read_frame.\r
-               if(is_eof(ret))                                                                                                              // Use av_dup_packet to extend its life.\r
+               ret = av_read_frame(format_context_.get(), read_packet.get()); // read_packet is only valid until next call of av_read_frame. Use av_dup_packet to extend its life.     \r
+               \r
+               if(is_eof(ret))                                                                                                              \r
                {\r
                        if(loop_)\r
                        {\r
@@ -195,27 +177,11 @@ private:
                                CASPAR_LOG(trace) << print() << " Received EOF. Stopping.";\r
                        }\r
                }\r
-               else if(ret < 0)\r
-               {\r
-                       BOOST_THROW_EXCEPTION(\r
-                               file_read_error() <<\r
-                               msg_info(av_error_str(ret)) <<\r
-                               source_info(narrow(print())) << \r
-                               boost::errinfo_api_function("av_read_frame") <<\r
-                               boost::errinfo_errno(AVUNERROR(ret)));\r
-               }\r
                else\r
                {               \r
-                       const int ret = av_dup_packet(read_packet.get());\r
-                       if(ret < 0)\r
-                       {\r
-                               BOOST_THROW_EXCEPTION(\r
-                                       invalid_operation() <<\r
-                                       msg_info(av_error_str(ret)) <<\r
-                                       source_info(narrow(print())) << \r
-                                       boost::errinfo_api_function("av_dup_packet") <<\r
-                                       boost::errinfo_errno(AVUNERROR(ret)));\r
-                       }\r
+                       THROW_ON_ERROR(ret, print(), "av_read_frame");\r
+\r
+                       THROW_ON_ERROR2(av_dup_packet(read_packet.get()), print());\r
                                \r
                        // Make sure that the packet is correctly deallocated even if size and data is modified during decoding.\r
                        auto size = read_packet->size;\r
@@ -245,28 +211,11 @@ private:
                static const AVRational base_q = {1, AV_TIME_BASE};\r
 \r
                int stream_index = av_find_default_stream_index(format_context_.get());\r
-               \r
-               if(stream_index < 0)\r
-               {       \r
-                       BOOST_THROW_EXCEPTION(\r
-                               invalid_operation() << \r
-                               source_info(narrow(print())) << \r
-                               msg_info(av_error_str(stream_index)) <<\r
-                               boost::errinfo_api_function("av_find_default_stream_index") <<\r
-                               boost::errinfo_errno(AVUNERROR(stream_index)));\r
-               }\r
+               THROW_ON_ERROR(stream_index, print(), "av_find_default_stream_index");\r
                                                \r
                const int ret = av_seek_frame(format_context_.get(), stream_index, frame, flags);\r
-               if(ret < 0)\r
-               {       \r
-                       BOOST_THROW_EXCEPTION(\r
-                               invalid_operation() << \r
-                               source_info(narrow(print())) << \r
-                               msg_info(av_error_str(ret)) <<\r
-                               boost::errinfo_api_function("av_seek_frame") <<\r
-                               boost::errinfo_errno(AVUNERROR(ret)));\r
-               }\r
-\r
+               THROW_ON_ERROR(ret, print(), "av_seek_frame");\r
+               \r
                buffer_.push(nullptr);\r
        }               \r
 \r
index 1408c6e0a3fb6b35182fb9f8cd7bfffa2f39d05e..3d3091d2d430c926006e3d69ed4759a8902fd58c 100644 (file)
@@ -78,26 +78,9 @@ public:
                try\r
                {\r
                        AVCodec* dec;\r
-                       index_ = av_find_best_stream(context.get(), AVMEDIA_TYPE_VIDEO, -1, -1, &dec, 0);\r
-\r
-                       if(index_ < 0)\r
-                       {\r
-                               BOOST_THROW_EXCEPTION(\r
-                                       file_read_error() <<\r
-                                       msg_info(av_error_str(index_)) <<\r
-                                       boost::errinfo_api_function("av_find_best_stream") <<\r
-                                       boost::errinfo_errno(AVUNERROR(index_)));\r
-                       }\r
-\r
-                       const int ret = tbb_avcodec_open(context->streams[index_]->codec, dec);\r
-                       if(ret < 0)\r
-                       {                               \r
-                               BOOST_THROW_EXCEPTION(\r
-                                       file_read_error() <<\r
-                                       msg_info(av_error_str(ret)) <<\r
-                                       boost::errinfo_api_function("tbb_avcodec_open") <<\r
-                                       boost::errinfo_errno(AVUNERROR(ret)));\r
-                       }\r
+                       index_ = THROW_ON_ERROR2(av_find_best_stream(context.get(), AVMEDIA_TYPE_VIDEO, -1, -1, &dec, 0), "[video_decoder]");\r
+                                               \r
+                       THROW_ON_ERROR2(tbb_avcodec_open(context->streams[index_]->codec, dec), "[video_decoder]");\r
                }\r
                catch(...)\r
                {\r
@@ -182,20 +165,11 @@ public:
                std::shared_ptr<AVFrame> decoded_frame(avcodec_alloc_frame(), av_free);\r
 \r
                int frame_finished = 0;\r
-               const int ret = avcodec_decode_video2(codec_context_.get(), decoded_frame.get(), &frame_finished, &pkt);\r
-               \r
-               if(ret < 0)\r
-               {\r
-                       BOOST_THROW_EXCEPTION(\r
-                               invalid_operation() <<\r
-                               msg_info(av_error_str(ret)) <<\r
-                               boost::errinfo_api_function("avcodec_decode_video") <<\r
-                               boost::errinfo_errno(AVUNERROR(ret)));\r
-               }\r
+               THROW_ON_ERROR2(avcodec_decode_video2(codec_context_.get(), decoded_frame.get(), &frame_finished, &pkt), "[video_decocer]");\r
                \r
-               // if a decoder consumes less then the whole packet then something is wrong\r
-               // that might be just harmless padding at the end or a problem with the\r
-               // AVParser or demuxer which puted more then one frame in a AVPacket\r
+               // If a decoder consumes less then the whole packet then something is wrong\r
+               // that might be just harmless padding at the end, or a problem with the\r
+               // AVParser or demuxer which puted more then one frame in a AVPacket.\r
                pkt.data = nullptr;\r
                pkt.size = 0;\r
 \r