]> git.sesse.net Git - casparcg/commitdiff
2.0. Improved ffmpeg nb_frames accuracy.
authorRonag <Ronag@362d55ac-95cf-4e76-9f9a-cbaa9c17b72d>
Tue, 9 Aug 2011 15:44:26 +0000 (15:44 +0000)
committerRonag <Ronag@362d55ac-95cf-4e76-9f9a-cbaa9c17b72d>
Tue, 9 Aug 2011 15:44:26 +0000 (15:44 +0000)
git-svn-id: https://casparcg.svn.sourceforge.net/svnroot/casparcg/server/branches/2.0.0.2@1111 362d55ac-95cf-4e76-9f9a-cbaa9c17b72d

modules/ffmpeg/producer/ffmpeg_producer.cpp
modules/ffmpeg/producer/input.cpp
modules/ffmpeg/producer/input.h

index 1aba5c3233b72a25f6807ba597352473b63bbd8e..103ede1efe561aa5af37641902a68e9719b8faad 100644 (file)
@@ -188,19 +188,24 @@ public:
                }\r
        }\r
 \r
-       virtual int64_t nb_frames() const\r
+       virtual int64_t nb_frames() const \r
        {\r
                if(loop_)\r
                        return 0;\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
+                       int64_t video_nb_frames = video_decoder_.nb_frames();\r
+                       int64_t audio_nb_frames = audio_decoder_.nb_frames();\r
+\r
+                       nb_frames = std::max(nb_frames, std::max(video_nb_frames, audio_nb_frames));\r
+               }\r
+\r
+               // TODO: Might need to scale nb_frames av frame_muxer transformations.\r
 \r
-               if(nb_frames == 0)\r
-                       nb_frames = video_decoder_.nb_frames();\r
-               \r
-               if(nb_frames == 0)\r
-                       nb_frames = audio_decoder_.nb_frames();\r
-               \r
                return nb_frames + late_frames_ - start_;\r
        }\r
                                \r
index 07d45a505b63aa6970821cee80e1ac6be619c85d..a38f311afdfccb1b46ba3b23b54ac8c990db5f54 100644 (file)
@@ -63,6 +63,7 @@ static const size_t MAX_BUFFER_SIZE  = 32 * 1000000;
 struct input::implementation : boost::noncopyable\r
 {              \r
        std::shared_ptr<AVFormatContext>                                                        format_context_; // Destroy this last\r
+       int                                                                                                                     default_stream_index_;\r
 \r
        safe_ptr<diagnostics::graph>                                                            graph_;\r
                \r
@@ -77,20 +78,20 @@ struct input::implementation : boost::noncopyable
                \r
        boost::thread                                                                                           thread_;\r
        tbb::atomic<bool>                                                                                       is_running_;\r
+\r
        tbb::atomic<size_t>                                                                                     nb_frames_;\r
-       int64_t                                                                                                         frame_number_;\r
+       tbb::atomic<size_t>                                                                                     nb_loops_;\r
 \r
-       int                                                                                                                     default_stream_index_;\r
 public:\r
        explicit implementation(const safe_ptr<diagnostics::graph>& graph, const std::wstring& filename, bool loop, int start) \r
                : graph_(graph)\r
                , loop_(loop)\r
                , filename_(filename)\r
                , start_(std::max(start, 0))\r
-               , frame_number_(0)\r
        {                       \r
                is_running_ = true;\r
-               nb_frames_ = 0;\r
+               nb_frames_      = 0;\r
+               nb_loops_       = 0;\r
                \r
                AVFormatContext* weak_format_context_ = nullptr;\r
                THROW_ON_ERROR2(avformat_open_input(&weak_format_context_, narrow(filename).c_str(), nullptr, nullptr), print());\r
@@ -143,6 +144,11 @@ public:
                return nb_frames_;\r
        }\r
 \r
+       size_t nb_loops() const\r
+       {\r
+               return nb_loops_;\r
+       }\r
+\r
 private:\r
        \r
        void run()\r
@@ -186,8 +192,7 @@ private:
                \r
                if(is_eof(ret))                                                                                                              \r
                {\r
-                       if(nb_frames_ == 0)\r
-                               nb_frames_ = static_cast<size_t>(frame_number_);\r
+                       ++nb_loops_;\r
 \r
                        if(loop_)\r
                        {\r
@@ -205,8 +210,8 @@ private:
                {               \r
                        THROW_ON_ERROR(ret, print(), "av_read_frame");\r
 \r
-                       if(read_packet->stream_index == default_stream_index_)\r
-                               ++frame_number_;\r
+                       if(read_packet->stream_index == default_stream_index_ && nb_loops_ == 0)\r
+                               ++nb_frames_;\r
 \r
                        THROW_ON_ERROR2(av_dup_packet(read_packet.get()), print());\r
                                \r
@@ -261,4 +266,5 @@ bool input::eof() const {return !impl_->is_running_;}
 bool input::try_pop(std::shared_ptr<AVPacket>& packet){return impl_->try_pop(packet);}\r
 safe_ptr<AVFormatContext> input::context(){return make_safe(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
 }
\ No newline at end of file
index 5736a4eedbb04dbc5cb06766134338b7248d1373..1d5b729d49b9dde64584f99c53bfe51e5812999d 100644 (file)
@@ -46,6 +46,7 @@ public:
        bool eof() const;\r
 \r
        size_t nb_frames() const;\r
+       size_t nb_loops() const;\r
 \r
        safe_ptr<AVFormatContext> context();\r
 private:\r