]> 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>
Mon, 28 Nov 2011 20:56:14 +0000 (20:56 +0000)
committerronag <ronag@362d55ac-95cf-4e76-9f9a-cbaa9c17b72d>
Mon, 28 Nov 2011 20:56:14 +0000 (20:56 +0000)
modules/ffmpeg/producer/ffmpeg_producer.cpp
modules/ffmpeg/producer/input/input.cpp
modules/ffmpeg/producer/input/input.h
modules/ffmpeg/producer/util/util.cpp
modules/ffmpeg/producer/util/util.h
modules/ffmpeg/producer/video/video_decoder.cpp
modules/ffmpeg/producer/video/video_decoder.h

index 77f9db12f26df94797fb7d05e3f2189b1648df94..522da375a095076bf5b4872fdeb63c2c38975d6c 100644 (file)
@@ -73,6 +73,7 @@ struct ffmpeg_producer : public core::frame_producer
        std::unique_ptr<audio_decoder>                                                          audio_decoder_; \r
        std::unique_ptr<frame_muxer>                                                            muxer_;\r
 \r
+       const double                                                                                            fps_;\r
        const int                                                                                                       start_;\r
        const bool                                                                                                      loop_;\r
        const size_t                                                                                            length_;\r
@@ -90,6 +91,7 @@ public:
                , frame_factory_(frame_factory)         \r
                , format_desc_(frame_factory->get_video_format_desc())\r
                , input_(graph_, filename_, loop, start, length)\r
+               , fps_(read_fps(*input_.context(), format_desc_.fps))\r
                , start_(start)\r
                , loop_(loop)\r
                , length_(length)\r
@@ -132,7 +134,7 @@ public:
                if(!video_decoder_ && !audio_decoder_)\r
                        BOOST_THROW_EXCEPTION(averror_stream_not_found() << msg_info("No streams found"));\r
 \r
-               muxer_.reset(new frame_muxer(video_decoder_ ? video_decoder_->fps() : frame_factory->get_video_format_desc().fps, frame_factory, filter));\r
+               muxer_.reset(new frame_muxer(fps_, frame_factory, filter));\r
        }\r
 \r
        // frame_producer\r
@@ -186,17 +188,7 @@ public:
 \r
        virtual int64_t file_nb_frames() const override\r
        {\r
-               // This function estimates nb_frames until input has read all packets for one loop, at which point the count should be accurate.\r
-\r
-               int64_t nb_frames = input_.nb_frames();\r
-               if(input_.nb_loops() < 1) // input still hasn't counted all frames\r
-               {\r
-                       auto video_nb_frames = video_decoder_ ? video_decoder_->nb_frames() : std::numeric_limits<int64_t>::max();\r
-                       //auto audio_nb_frames = audio_decoder_ ? audio_decoder_->nb_frames() : std::numeric_limits<int64_t>::max();\r
-\r
-                       nb_frames = std::max(nb_frames, video_nb_frames);\r
-               }\r
-               return nb_frames;\r
+               return video_decoder_ ? video_decoder_->nb_frames() : std::numeric_limits<int64_t>::max();\r
        }\r
 \r
        virtual int64_t frame_number() const override\r
@@ -221,7 +213,7 @@ public:
                if(video_decoder_)\r
                {\r
                        std::wostringstream fps_ss;\r
-                       fps_ss << std::fixed << std::setprecision(2) << (video_decoder_->is_progressive() ? video_decoder_->fps() : 2.0 * video_decoder_->fps());\r
+                       fps_ss << std::fixed << std::setprecision(2) << (video_decoder_->is_progressive() ? fps_ : 2.0 * fps_);\r
 \r
                        return L"ffmpeg[" + boost::filesystem::wpath(filename_).filename() + L"|" \r
                                                          + boost::lexical_cast<std::wstring>(video_decoder_->width()) + L"x" + boost::lexical_cast<std::wstring>(video_decoder_->height())\r
@@ -303,7 +295,7 @@ public:
                \r
                size_t file_frame_number = 0;\r
                file_frame_number = std::max(file_frame_number, video_decoder_ ? video_decoder_->file_frame_number() : 0);\r
-               file_frame_number = std::max(file_frame_number, audio_decoder_ ? audio_decoder_->file_frame_number() : 0);\r
+               //file_frame_number = std::max(file_frame_number, audio_decoder_ ? audio_decoder_->file_frame_number() : 0);\r
 \r
                for(auto frame = muxer_->poll(); frame; frame = muxer_->poll())\r
                        frame_buffer_.push(std::make_pair(make_safe_ptr(frame), file_frame_number));\r
index 9e18f4564c218c6d3bb63542f514b442e97d372b..c0e5cdda86b858518520832e0aa59f52639687f5 100644 (file)
@@ -81,9 +81,6 @@ struct input::implementation : boost::noncopyable
        boost::condition_variable                                                                       buffer_cond_;\r
        boost::mutex                                                                                            buffer_mutex_;\r
                \r
-       tbb::atomic<size_t>                                                                                     nb_frames_;\r
-       tbb::atomic<size_t>                                                                                     nb_loops_;\r
-\r
        boost::thread                                                                                           thread_;\r
        tbb::atomic<bool>                                                                                       is_running_;\r
        tbb::atomic<bool>                                                                                       is_eof_;\r
@@ -102,12 +99,6 @@ struct input::implementation : boost::noncopyable
                is_eof_                 = false;\r
                loop_                   = loop;\r
                buffer_size_    = 0;\r
-               nb_frames_              = 0;\r
-               nb_loops_               = 0;\r
-\r
-               buffer_size_    = 0;\r
-               nb_frames_              = 0;\r
-               nb_loops_               = 0;\r
 \r
                if(start_ > 0)                  \r
                        do_seek(start_);\r
@@ -153,8 +144,6 @@ struct input::implementation : boost::noncopyable
                try\r
                {\r
                        CASPAR_LOG(info) << print() << " Thread Started.";\r
-                       \r
-                       CASPAR_ASSERT(nb_frames_ < 1000);\r
 \r
                        while(is_running_)\r
                        {\r
@@ -184,7 +173,6 @@ struct input::implementation : boost::noncopyable
                \r
                if(is_eof(ret))                                                                                                              \r
                {\r
-                       ++nb_loops_;\r
                        frame_number_   = 0;\r
                        is_eof_                 = true;\r
 \r
@@ -200,11 +188,7 @@ struct input::implementation : boost::noncopyable
                        THROW_ON_ERROR(ret, "av_read_frame", print());\r
 \r
                        if(packet->stream_index == default_stream_index_)\r
-                       {\r
-                               if(nb_loops_ == 0)\r
-                                       ++nb_frames_;\r
                                ++frame_number_;\r
-                       }\r
 \r
                        THROW_ON_ERROR2(av_dup_packet(packet.get()), print());\r
                                \r
@@ -248,12 +232,10 @@ struct input::implementation : boost::noncopyable
                        }\r
                }\r
                \r
-               auto time_base = format_context_->streams[default_stream_index_]->time_base;\r
-               auto fixed_target = (target*time_base.den)/time_base.num;\r
-               auto fixed_time_base = fix_time_base(time_base);\r
-               fixed_target = (fixed_target * fixed_time_base.num) / fixed_time_base.den;\r
-               fixed_target = fixed_target * format_context_->streams[default_stream_index_]->codec->ticks_per_frame;\r
-\r
+               auto stream = format_context_->streams[default_stream_index_];\r
+               auto codec  = stream->codec;\r
+               auto fixed_target = (target*stream->time_base.den*codec->time_base.num)/(stream->time_base.num*codec->time_base.den);\r
+               \r
                THROW_ON_ERROR2(avformat_seek_file(format_context_.get(), default_stream_index_, std::numeric_limits<int64_t>::min(), fixed_target, std::numeric_limits<int64_t>::max(), 0), print());          \r
 \r
                is_eof_ = false;\r
@@ -282,9 +264,9 @@ struct input::implementation : boost::noncopyable
        bool is_eof(int ret)\r
        {\r
                if(ret == AVERROR(EIO))\r
-                       CASPAR_LOG(trace) << print() << " Received EIO, assuming EOF. " << nb_frames_;\r
+                       CASPAR_LOG(trace) << print() << " Received EIO, assuming EOF. ";\r
                if(ret == AVERROR_EOF)\r
-                       CASPAR_LOG(debug) << print() << " Received EOF. " << nb_frames_;\r
+                       CASPAR_LOG(debug) << print() << " Received EOF. ";\r
 \r
                return ret == AVERROR_EOF || ret == AVERROR(EIO) || frame_number_ >= length_; // av_read_frame doesn't always correctly return AVERROR_EOF;\r
        }\r
@@ -300,8 +282,6 @@ input::input(const safe_ptr<diagnostics::graph>& graph, const std::wstring& file
 bool input::eof() const {return impl_->is_eof_;}\r
 bool input::try_pop(std::shared_ptr<AVPacket>& packet){return impl_->try_pop(packet);}\r
 safe_ptr<AVFormatContext> input::context(){return impl_->format_context_;}\r
-size_t input::nb_frames() const {return impl_->nb_frames_;}\r
-size_t input::nb_loops() const {return impl_->nb_loops_;}\r
 void input::loop(bool value){impl_->loop_ = value;}\r
 bool input::loop() const{return impl_->loop_;}\r
 void input::seek(int64_t target){impl_->seek(target);}\r
index b434b208916e6bee397fc116d3b55133899541f8..29495c39072292095636476ccab30895f4a0de9e 100644 (file)
@@ -48,9 +48,6 @@ public:
        bool try_pop(std::shared_ptr<AVPacket>& packet);\r
        bool eof() const;\r
 \r
-       size_t nb_frames() const;\r
-       size_t nb_loops() const;\r
-\r
        void loop(bool value);\r
        bool loop() const;\r
 \r
index b9559072791f05051723ca57677a4353eac98f35..7b81fcfb69aa3f8f3829d7bd176dcd9c2f7603a2 100644 (file)
@@ -273,74 +273,52 @@ AVRational fix_time_base(AVRational time_base)
        return time_base;\r
 }\r
 \r
-void fix_meta_data(AVFormatContext& context)\r
-{\r
+double read_fps(AVFormatContext& context, double fail_value)\r
+{                                              \r
        auto video_index = av_find_best_stream(&context, AVMEDIA_TYPE_VIDEO, -1, -1, 0, 0);\r
        auto audio_index = av_find_best_stream(&context, AVMEDIA_TYPE_AUDIO, -1, -1, 0, 0);\r
-\r
+       \r
        if(video_index > -1)\r
        {\r
-               auto video_context = context.streams[video_index]->codec;\r
-               auto video_stream  = context.streams[video_index];\r
+               const auto video_context = context.streams[video_index]->codec;\r
+               const auto video_stream  = context.streams[video_index];\r
                                                \r
+               AVRational time_base = video_context->time_base;\r
+\r
                if(boost::filesystem2::path(context.filename).extension() == ".flv")\r
                {\r
                        try\r
                        {\r
                                auto meta = read_flv_meta_info(context.filename);\r
-                               double fps = boost::lexical_cast<double>(meta["framerate"]);\r
-                               video_context->time_base.num = 1000000;\r
-                               video_context->time_base.den = static_cast<int>(fps*1000000.0);\r
-                               video_stream->nb_frames = static_cast<int64_t>(boost::lexical_cast<double>(meta["duration"])*fps);\r
+                               return boost::lexical_cast<double>(meta["framerate"]);\r
+                       }\r
+                       catch(...)\r
+                       {\r
+                               return 0.0;\r
                        }\r
-                       catch(...){}\r
                }\r
                else\r
                {\r
-                       video_context->time_base.num *= video_context->ticks_per_frame;\r
+                       time_base.num *= video_context->ticks_per_frame;\r
 \r
-                       if(!is_sane_fps(video_context->time_base))\r
+                       if(!is_sane_fps(time_base))\r
                        {                       \r
-                               video_context->time_base = fix_time_base(video_context->time_base);\r
+                               time_base = fix_time_base(time_base);\r
 \r
-                               if(!is_sane_fps(video_context->time_base) && audio_index > -1)\r
+                               if(!is_sane_fps(time_base) && audio_index > -1)\r
                                {\r
                                        auto& audio_context = *context.streams[audio_index]->codec;\r
                                        auto& audio_stream  = *context.streams[audio_index];\r
 \r
                                        double duration_sec = audio_stream.duration / static_cast<double>(audio_context.sample_rate);\r
                                                                \r
-                                       video_context->time_base.num = static_cast<int>(duration_sec*100000.0);\r
-                                       video_context->time_base.den = static_cast<int>(video_stream->nb_frames*100000);\r
+                                       time_base.num = static_cast<int>(duration_sec*100000.0);\r
+                                       time_base.den = static_cast<int>(video_stream->nb_frames*100000);\r
                                }\r
                        }\r
-                               \r
-                       //if(audio_index > -1) // Check for invalid double frame-rate\r
-                       //{\r
-                       //      auto& audio_context             = *context.streams[audio_index]->codec;\r
-                       //      auto& audio_stream              = *context.streams[audio_index];\r
-                       //      \r
-                       //      double duration_sec             = audio_stream.duration / static_cast<double>(audio_context.sample_rate);\r
-                       //      double fps                              = static_cast<double>(video_context->time_base.den) / static_cast<double>(video_context->time_base.num);\r
-\r
-                       //      double fps_nb_frames    = static_cast<double>(duration_sec*fps);\r
-                       //      double stream_nb_frames = static_cast<double>(video_stream->nb_frames);\r
-                       //      double diff                             = std::abs(fps_nb_frames - stream_nb_frames*2.0);\r
-                       //      if(diff < fps_nb_frames*0.05)\r
-                       //              video_context->time_base.num *= 2;\r
-                       //}\r
-                       //else\r
-                       //{\r
-                       //      video_context->time_base.den = video_stream->r_frame_rate.num;\r
-                       //      video_context->time_base.num = video_stream->r_frame_rate.den;\r
-                       //}\r
                }\r
-\r
-               auto nb_frames = static_cast<double>(video_stream->duration*video_stream->time_base.num)/static_cast<double>(video_stream->time_base.den);\r
-               nb_frames = (nb_frames*video_context->time_base.den)/video_context->time_base.num;\r
-               video_stream->nb_frames = static_cast<int64_t>(nb_frames+0.5);\r
-\r
-               double fps = static_cast<double>(video_context->time_base.den) / static_cast<double>(video_context->time_base.num);\r
+               \r
+               double fps = static_cast<double>(time_base.den) / static_cast<double>(time_base.num);\r
 \r
                double closest_fps = 0.0;\r
                for(int n = 0; n < core::video_format::count; ++n)\r
@@ -354,8 +332,35 @@ void fix_meta_data(AVFormatContext& context)
                                closest_fps = format.fps;\r
                }\r
        \r
-               video_context->time_base.num = 1000000;\r
-               video_context->time_base.den = static_cast<int>(closest_fps*1000000.0);\r
+               return closest_fps;\r
+       }\r
+\r
+       return fail_value;      \r
+}\r
+\r
+void fix_meta_data(AVFormatContext& context)\r
+{\r
+       auto video_index = av_find_best_stream(&context, AVMEDIA_TYPE_VIDEO, -1, -1, 0, 0);\r
+\r
+       if(video_index > -1)\r
+       {\r
+               auto video_stream   = context.streams[video_index];\r
+               auto video_context  = context.streams[video_index]->codec;\r
+                                               \r
+               if(boost::filesystem2::path(context.filename).extension() == ".flv")\r
+               {\r
+                       try\r
+                       {\r
+                               auto meta = read_flv_meta_info(context.filename);\r
+                               double fps = boost::lexical_cast<double>(meta["framerate"]);\r
+                               video_stream->nb_frames = static_cast<int64_t>(boost::lexical_cast<double>(meta["duration"])*fps);\r
+                       }\r
+                       catch(...){}\r
+               }\r
+               else\r
+               {\r
+                       video_stream->nb_frames = (video_stream->duration*video_stream->time_base.num*video_context->time_base.den)/(video_stream->time_base.den*video_context->time_base.num*video_context->ticks_per_frame);          \r
+               }\r
        }\r
 }\r
 \r
index 1a957bb4ac983ccba368f7d98e510b0c4e833b21..cc448b0aa01bb8c596e9b82fc5899cab9524de4a 100644 (file)
@@ -57,6 +57,6 @@ safe_ptr<AVFormatContext> open_input(const std::wstring& filename);
 bool is_sane_fps(AVRational time_base);\r
 AVRational fix_time_base(AVRational time_base);\r
 \r
-//void av_dup_frame(AVFrame* frame);\r
+double read_fps(AVFormatContext& context, double fail_value);\r
 \r
 }}
\ No newline at end of file
index 17921d65ef1846cf0bc94e2b9e0d7dbdfcbb4a56..4dc758384635aaefa9c05efdcb8d5ca16aca8b20 100644 (file)
@@ -55,7 +55,6 @@ struct video_decoder::implementation : boost::noncopyable
 \r
        std::queue<safe_ptr<AVPacket>>                  packets_;\r
        \r
-       const double                                                    fps_;\r
        const int64_t                                                   nb_frames_;\r
 \r
        const size_t                                                    width_;\r
@@ -67,7 +66,6 @@ struct video_decoder::implementation : boost::noncopyable
 public:\r
        explicit implementation(const safe_ptr<AVFormatContext>& context) \r
                : codec_context_(open_codec(*context, AVMEDIA_TYPE_VIDEO, index_))\r
-               , fps_(static_cast<double>(codec_context_->time_base.den) / static_cast<double>(codec_context_->time_base.num))\r
                , nb_frames_(context->streams[index_]->nb_frames)\r
                , width_(codec_context_->width)\r
                , height_(codec_context_->height)\r
@@ -139,18 +137,12 @@ public:
        {\r
                return packets_.size() > 10;\r
        }\r
-       \r
-       double fps() const\r
-       {\r
-               return fps_;\r
-       }\r
 };\r
 \r
 video_decoder::video_decoder(const safe_ptr<AVFormatContext>& context) : impl_(new implementation(context)){}\r
 void video_decoder::push(const std::shared_ptr<AVPacket>& packet){impl_->push(packet);}\r
 std::shared_ptr<AVFrame> video_decoder::poll(){return impl_->poll();}\r
 bool video_decoder::ready() const{return impl_->ready();}\r
-double video_decoder::fps() const{return impl_->fps();}\r
 int64_t video_decoder::nb_frames() const{return impl_->nb_frames_;}\r
 size_t video_decoder::width() const{return impl_->width_;}\r
 size_t video_decoder::height() const{return impl_->height_;}\r
index 19a493f509c52bea09f5c162ea99b247c9830757..30d7a054097d4cc2f0a949bf6a417bfa26cbae3e 100644 (file)
@@ -48,7 +48,6 @@ public:
        size_t  width()         const;\r
        size_t  height()        const;\r
        int64_t nb_frames() const;\r
-       double  fps()           const;\r
        bool    is_progressive() const;\r
 \r
        size_t file_frame_number() const;\r