]> git.sesse.net Git - casparcg/commitdiff
2.0.2: frame_producer: Added file-nb-frames and file-frame-number.
authorronag <ronag@362d55ac-95cf-4e76-9f9a-cbaa9c17b72d>
Sun, 27 Nov 2011 20:13:28 +0000 (20:13 +0000)
committerronag <ronag@362d55ac-95cf-4e76-9f9a-cbaa9c17b72d>
Sun, 27 Nov 2011 20:13:28 +0000 (20:13 +0000)
git-svn-id: https://casparcg.svn.sourceforge.net/svnroot/casparcg/server/branches/2.0.2@1687 362d55ac-95cf-4e76-9f9a-cbaa9c17b72d

16 files changed:
core/producer/frame_producer.cpp
core/producer/frame_producer.h
core/producer/layer.cpp
core/producer/layer.h
core/producer/separated/separated_producer.cpp
core/producer/transition/transition_producer.cpp
modules/ffmpeg/producer/audio/audio_decoder.cpp
modules/ffmpeg/producer/audio/audio_decoder.h
modules/ffmpeg/producer/ffmpeg_producer.cpp
modules/ffmpeg/producer/input/input.cpp
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
protocol/amcp/AMCPCommandsImpl.cpp
shell/casparcg.config

index ce986b4fb270f0319dae224b1f4a7101002114dd..772d5647bc1825e66a5d8b7dbf6060b37880c9cf 100644 (file)
@@ -98,6 +98,9 @@ public:
        virtual safe_ptr<frame_producer>                        get_following_producer() const override                                                                 {return (*producer_)->get_following_producer();}\r
        virtual void                                                            set_leading_producer(const safe_ptr<frame_producer>& producer) override {(*producer_)->set_leading_producer(producer);}\r
        virtual int64_t                                                         nb_frames() const override                                                                                              {return (*producer_)->nb_frames();}\r
+       virtual int64_t                                                         file_nb_frames() const override                                                                                 {return (*producer_)->file_nb_frames();}\r
+       virtual int64_t                                                         frame_number() const override                                                                                   {return (*producer_)->frame_number();}\r
+       virtual int64_t                                                         file_frame_number() const override                                                                              {return (*producer_)->file_frame_number();}\r
 };\r
 \r
 safe_ptr<core::frame_producer> create_destroy_proxy(safe_ptr<core::frame_producer>&& producer)\r
index d40698b20058258fbbed023ee8d903fad032947a..d07ce3258b35931cbd5e5179160f7d70ddb689e6 100644 (file)
@@ -65,6 +65,10 @@ public:
        virtual void set_leading_producer(const safe_ptr<frame_producer>&) {}  // nothrow\r
                \r
        virtual int64_t nb_frames() const {return std::numeric_limits<int>::max();}\r
+       virtual int64_t file_nb_frames() const {return nb_frames();}\r
+\r
+       virtual int64_t frame_number() const {return 0;}\r
+       virtual int64_t file_frame_number() const {return frame_number();}\r
        \r
        virtual safe_ptr<basic_frame> receive(int hints) = 0;\r
        virtual safe_ptr<core::basic_frame> last_frame() const = 0;\r
index 9798c08d0c3c8c454252a32e824e7dc9fea30f34..14ee7045753fec6e2f7ec6612998e3e3691875b3 100644 (file)
@@ -124,11 +124,13 @@ public:
        layer_status status() const\r
        {\r
                layer_status status;\r
-               status.foreground        = foreground_->print();\r
-               status.background        = background_->print();\r
-               status.is_paused         = is_paused_;\r
-               status.total_frames      = foreground_->nb_frames();\r
-               status.current_frame = frame_number_;\r
+               status.foreground                       = foreground_->print();\r
+               status.background                       = background_->print();\r
+               status.is_paused                        = is_paused_;\r
+               status.nb_frames                        = foreground_->nb_frames();\r
+               status.frame_number                     = std::max(frame_number_, foreground_->frame_number());\r
+               status.file_nb_frames           = foreground_->file_nb_frames();\r
+               status.file_frame_number        = foreground_->file_frame_number();\r
 \r
                return status;\r
        }\r
index 5f412ac8121edaca51ecb81f9f6ba4578ae4b6b0..45eda8dadbecb7beb7ebbdd63edbc4c345157ac8 100644 (file)
@@ -37,8 +37,10 @@ struct layer_status
        std::wstring    foreground;\r
        std::wstring    background;\r
        bool                    is_paused;\r
-       int64_t                 total_frames;\r
-       int64_t                 current_frame;\r
+       int64_t                 nb_frames;\r
+       int64_t                 frame_number;\r
+       int64_t                 file_nb_frames;\r
+       int64_t                 file_frame_number;\r
 };\r
 \r
 class layer : boost::noncopyable\r
index c6f48281c3ceecd9e22a757d9120d8f23a8443d6..cd1774adcbe8096bcbb7fbaa11596353f59ec55b 100644 (file)
@@ -88,6 +88,21 @@ struct separated_producer : public frame_producer
        {\r
                return std::min(fill_producer_->nb_frames(), key_producer_->nb_frames());\r
        }\r
+               \r
+       virtual int64_t file_nb_frames() const override\r
+       {\r
+               return std::min(fill_producer_->file_nb_frames(), key_producer_->file_nb_frames());\r
+       }\r
+       \r
+       virtual int64_t frame_number() const override\r
+       {\r
+               return std::max(fill_producer_->frame_number(), key_producer_->frame_number());\r
+       }\r
+       \r
+       virtual int64_t file_frame_number() const override\r
+       {\r
+               return std::max(fill_producer_->file_frame_number(), key_producer_->file_frame_number());\r
+       }\r
 };\r
 \r
 safe_ptr<frame_producer> create_separated_producer(const safe_ptr<frame_producer>& fill, const safe_ptr<frame_producer>& key)\r
index 728f6c305d6f95c73576d496f5e5f9c6698224cb..e04f6dd792ec1e70f6dadb3b49d16833c375d6e3 100644 (file)
@@ -100,6 +100,21 @@ struct transition_producer : public frame_producer
        {\r
                return get_following_producer()->nb_frames();\r
        }\r
+       \r
+       virtual int64_t file_nb_frames() const override\r
+       {\r
+               return get_following_producer()->file_nb_frames();\r
+       }\r
+       \r
+       virtual int64_t frame_number() const override\r
+       {\r
+               return get_following_producer()->frame_number();\r
+       }\r
+       \r
+       virtual int64_t file_frame_number() const override\r
+       {\r
+               return get_following_producer()->file_frame_number();\r
+       }\r
 \r
        virtual std::wstring print() const override\r
        {\r
index 046d3c48f4d3a2fc8b741d67e2bfebe8ef79267d..880dad618ac640e171976beb63b61417f6e6983a 100644 (file)
@@ -60,6 +60,7 @@ struct audio_decoder::implementation : boost::noncopyable
        std::queue<safe_ptr<AVPacket>>                                                          packets_;\r
 \r
        const int64_t                                                                                           nb_frames_;\r
+       tbb::atomic<size_t>                                                                                     file_frame_number_;\r
 public:\r
        explicit implementation(const safe_ptr<AVFormatContext>& context, const core::video_format_desc& format_desc) \r
                : format_desc_(format_desc)     \r
@@ -70,6 +71,7 @@ public:
                , buffer1_(AVCODEC_MAX_AUDIO_FRAME_SIZE*2)\r
                , nb_frames_(context->streams[index_]->nb_frames)\r
        {               \r
+               file_frame_number_ = 0;\r
                CASPAR_LOG(debug) << "[audio_decoder] " << context->streams[index_]->codec->codec->long_name;      \r
        }\r
 \r
@@ -78,7 +80,7 @@ public:
                if(!packet)\r
                        return;\r
 \r
-               if(packet->stream_index == index_ || packet == flush_packet())\r
+               if(packet->stream_index == index_ || packet->data == nullptr)\r
                        packets_.push(make_safe_ptr(packet));\r
        }       \r
        \r
@@ -89,9 +91,10 @@ public:
                                \r
                auto packet = packets_.front();\r
 \r
-               if(packet == flush_packet())\r
+               if(packet->data == nullptr)\r
                {\r
                        packets_.pop();\r
+                       file_frame_number_ = static_cast<size_t>(packet->pos);\r
                        avcodec_flush_buffers(codec_context_.get());\r
                        return flush_audio();\r
                }\r
@@ -122,6 +125,8 @@ public:
                const auto n_samples = buffer1_.size() / av_get_bytes_per_sample(AV_SAMPLE_FMT_S32);\r
                const auto samples = reinterpret_cast<int32_t*>(buffer1_.data());\r
 \r
+               ++file_frame_number_;\r
+\r
                return std::make_shared<core::audio_buffer>(samples, samples + n_samples);\r
        }\r
 \r
@@ -136,5 +141,6 @@ void audio_decoder::push(const std::shared_ptr<AVPacket>& packet){impl_->push(pa
 bool audio_decoder::ready() const{return impl_->ready();}\r
 std::shared_ptr<core::audio_buffer> audio_decoder::poll(){return impl_->poll();}\r
 int64_t audio_decoder::nb_frames() const{return impl_->nb_frames_;}\r
+size_t audio_decoder::file_frame_number() const{return impl_->file_frame_number_;}\r
 \r
 }}
\ No newline at end of file
index e8d53758b19f7aeea87a3a83e1f13c7fad5a29ac..e72ff8e06cb70d4797d95d920f2e0170dbf5871e 100644 (file)
@@ -48,7 +48,8 @@ public:
        std::shared_ptr<core::audio_buffer> poll();\r
 \r
        int64_t nb_frames() const;\r
-\r
+       \r
+       size_t file_frame_number() const;\r
 private:\r
        struct implementation;\r
        safe_ptr<implementation> impl_;\r
index d470f2282061ce1b5059da9ac890d0a0f3e7d484..2d376690f2ecb12ca95eb2b76aaff87bdfd4be20 100644 (file)
@@ -80,6 +80,9 @@ struct ffmpeg_producer : public core::frame_producer
        safe_ptr<core::basic_frame>                                             last_frame_;\r
        \r
        std::queue<safe_ptr<core::basic_frame>>                 frame_buffer_;\r
+\r
+       int64_t                                                                                 frame_number_;\r
+       int64_t                                                                                 file_frame_number_;;\r
        \r
 public:\r
        explicit ffmpeg_producer(const safe_ptr<core::frame_factory>& frame_factory, const std::wstring& filename, const std::wstring& filter, bool loop, int start, size_t length) \r
@@ -91,6 +94,7 @@ public:
                , loop_(loop)\r
                , length_(length)\r
                , last_frame_(core::basic_frame::empty())\r
+               , frame_number_(0)\r
        {\r
                graph_->add_guide("frame-time", 0.5);\r
                graph_->set_color("frame-time", diagnostics::color(0.1f, 1.0f, 0.1f));\r
@@ -153,6 +157,7 @@ public:
 \r
                graph_->set_text(print());\r
 \r
+               ++frame_number_;\r
                return last_frame_;\r
        }\r
 \r
@@ -174,6 +179,31 @@ public:
                return nb_frames - start_;\r
        }\r
 \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
+       }\r
+\r
+       virtual int64_t frame_number() const override\r
+       {\r
+               return frame_number_;\r
+       }\r
+\r
+       virtual int64_t file_frame_number() const override\r
+       {\r
+               return file_frame_number_;\r
+       }\r
+\r
        virtual boost::unique_future<std::wstring> call(const std::wstring& param) override\r
        {\r
                boost::promise<std::wstring> promise;\r
@@ -195,22 +225,7 @@ public:
        }\r
 \r
        // ffmpeg_producer\r
-\r
-       int64_t file_nb_frames() const\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
-       }\r
-                               \r
+                                       \r
        std::wstring do_call(const std::wstring& param)\r
        {\r
                static const boost::wregex loop_exp(L"LOOP\\s*(?<VALUE>\\d?)", boost::regex::icase);\r
@@ -250,15 +265,21 @@ public:
                tbb::parallel_invoke(\r
                [&]\r
                {\r
-                       if(!muxer_->video_ready() && video_decoder_)                    \r
-                               video = video_decoder_->poll();                 \r
+                       if(!muxer_->video_ready() && video_decoder_)    \r
+                       {\r
+                               video = video_decoder_->poll(); \r
+                               file_frame_number_ = video_decoder_->file_frame_number();\r
+                       }\r
                },\r
                [&]\r
                {               \r
-                       if(!muxer_->audio_ready() && audio_decoder_)                    \r
-                               audio = audio_decoder_->poll();                 \r
+                       if(!muxer_->audio_ready() && audio_decoder_)            \r
+                       {\r
+                               audio = audio_decoder_->poll();         \r
+                               file_frame_number_ = video_decoder_->file_frame_number();\r
+                       }       \r
                });\r
-\r
+               \r
                muxer_->push(video, hints);\r
                muxer_->push(audio);\r
 \r
index 43e445397a34b36224cdded26feb23709917ada4..e9c35c651690e9100d7abf7433e0f6be449e70a4 100644 (file)
@@ -211,7 +211,7 @@ struct input::implementation : boost::noncopyable
                        // Make sure that the packet is correctly deallocated even if size and data is modified during decoding.\r
                        auto size = packet->size;\r
                        auto data = packet->data;\r
-\r
+                       \r
                        packet = safe_ptr<AVPacket>(packet.get(), [packet, size, data](AVPacket*)\r
                        {\r
                                packet->size = size;\r
@@ -258,7 +258,12 @@ struct input::implementation : boost::noncopyable
                is_eof_ = false;\r
                buffer_cond_.notify_all();\r
 \r
-               buffer_.push(flush_packet());\r
+               auto flush_packet       = create_packet();\r
+               flush_packet->data      = nullptr;\r
+               flush_packet->size      = 0;\r
+               flush_packet->pos       = target;\r
+\r
+               buffer_.push(flush_packet);\r
        }       \r
 \r
        void seek(int64_t target)\r
index c1198d015d1a316a4a693064d5a9660ed9cda379..b9559072791f05051723ca57677a4353eac98f35 100644 (file)
@@ -40,12 +40,6 @@ extern "C"
 \r
 namespace caspar { namespace ffmpeg {\r
                \r
-safe_ptr<AVPacket> flush_packet()\r
-{\r
-       static auto packet = create_packet();\r
-       return packet;\r
-}\r
-\r
 std::shared_ptr<core::audio_buffer> flush_audio()\r
 {\r
        static std::shared_ptr<core::audio_buffer> audio(new core::audio_buffer());\r
index 99f74a09bfdda6f0f8ff03b2641de2294b231318..1a957bb4ac983ccba368f7d98e510b0c4e833b21 100644 (file)
@@ -35,9 +35,7 @@ struct frame_factory;
 }\r
 \r
 namespace ffmpeg {\r
-       \r
-       \r
-safe_ptr<AVPacket> flush_packet();\r
+               \r
 std::shared_ptr<core::audio_buffer> flush_audio();\r
 std::shared_ptr<core::audio_buffer> empty_audio();\r
 std::shared_ptr<AVFrame>                       flush_video();\r
index b1738bba2af4d48a988718505548fcf842d417ba..17921d65ef1846cf0bc94e2b9e0d7dbdfcbb4a56 100644 (file)
@@ -62,6 +62,8 @@ struct video_decoder::implementation : boost::noncopyable
        const size_t                                                    height_;\r
        bool                                                                    is_progressive_;\r
 \r
+       tbb::atomic<size_t>                                             file_frame_number_;\r
+\r
 public:\r
        explicit implementation(const safe_ptr<AVFormatContext>& context) \r
                : codec_context_(open_codec(*context, AVMEDIA_TYPE_VIDEO, index_))\r
@@ -70,6 +72,7 @@ public:
                , width_(codec_context_->width)\r
                , height_(codec_context_->height)\r
        {\r
+               file_frame_number_ = 0;\r
                CASPAR_LOG(debug) << "[video_decoder] " << context->streams[index_]->codec->codec->long_name;\r
        }\r
 \r
@@ -78,7 +81,7 @@ public:
                if(!packet)\r
                        return;\r
 \r
-               if(packet->stream_index == index_ || packet == flush_packet())\r
+               if(packet->stream_index == index_ || packet->data == nullptr)\r
                        packets_.push(make_safe_ptr(packet));\r
        }\r
 \r
@@ -89,21 +92,17 @@ public:
                \r
                auto packet = packets_.front();\r
                                        \r
-               if(packet == flush_packet())\r
+               if(packet->data == nullptr)\r
                {                       \r
                        if(codec_context_->codec->capabilities & CODEC_CAP_DELAY)\r
                        {\r
-                               AVPacket pkt;\r
-                               av_init_packet(&pkt);\r
-                               pkt.data = nullptr;\r
-                               pkt.size = 0;\r
-\r
-                               auto video = decode(pkt);\r
+                               auto video = decode(*packet);\r
                                if(video)\r
                                        return video;\r
                        }\r
-               \r
+                                       \r
                        packets_.pop();\r
+                       file_frame_number_ = static_cast<size_t>(packet->pos);\r
                        avcodec_flush_buffers(codec_context_.get());\r
                        return flush_video();   \r
                }\r
@@ -131,6 +130,8 @@ public:
                if(decoded_frame->repeat_pict > 0)\r
                        CASPAR_LOG(warning) << "[video_decoder] Field repeat_pict not implemented.";\r
                \r
+               ++file_frame_number_;\r
+\r
                return decoded_frame;\r
        }\r
        \r
@@ -154,5 +155,6 @@ int64_t video_decoder::nb_frames() const{return impl_->nb_frames_;}
 size_t video_decoder::width() const{return impl_->width_;}\r
 size_t video_decoder::height() const{return impl_->height_;}\r
 bool   video_decoder::is_progressive() const{return impl_->is_progressive_;}\r
+size_t video_decoder::file_frame_number() const{return impl_->file_frame_number_;}\r
 \r
 }}
\ No newline at end of file
index 02030358a041f3684765d4b3d1263a3b3d8e1d80..19a493f509c52bea09f5c162ea99b247c9830757 100644 (file)
@@ -50,6 +50,8 @@ public:
        int64_t nb_frames() const;\r
        double  fps()           const;\r
        bool    is_progressive() const;\r
+\r
+       size_t file_frame_number() const;\r
 private:\r
        struct implementation;\r
        safe_ptr<implementation> impl_;\r
index 8d973dfb02584a725871ce4e82274dba3a65f67e..8ee4bf81f5996a5b3803189d5cf02d2793648925 100644 (file)
@@ -808,12 +808,14 @@ bool StatusCommand::DoExecute()
                status_text\r
                        << L"201 STATUS OK\r\n"\r
                        << L"<layer>"\r
-                       << L"\n\t<index>"                       << GetLayerIndex() << L"</index>"\r
-                       << L"\n\t<foreground>"          << status.foreground << L"</foreground>"\r
-                       << L"\n\t<background>"          << status.background << L"</background>"\r
-                       << L"\n\t<status>"                      << (status.is_paused ? L"paused" : L"playing") << L"</status>"\r
-                       << L"\n\t<total-frames>"        << (status.total_frames == std::numeric_limits<int64_t>::max() ? 0 : status.total_frames) << L"</total-frames>"\r
-                       << L"\n\t<current-frame>"       << status.current_frame << L"</current-frame>"\r
+                       << L"\n\t<index>"                               << GetLayerIndex() << L"</index>"\r
+                       << L"\n\t<foreground>"                  << status.foreground << L"</foreground>"\r
+                       << L"\n\t<background>"                  << status.background << L"</background>"\r
+                       << L"\n\t<status>"                              << (status.is_paused ? L"paused" : L"playing") << L"</status>"\r
+                       << L"\n\t<nb-frames>"                   << (status.nb_frames == std::numeric_limits<int64_t>::max() ? 0 : status.nb_frames) << L"</nb-frames>"\r
+                       << L"\n\t<frame-number>"                << status.frame_number << L"</frame-number>"\r
+                       << L"\n\t<file-nb-frames>"              << (status.file_nb_frames == std::numeric_limits<int64_t>::max() ? 0 : status.file_nb_frames) << L"</file-nb-frames>"\r
+                       << L"\n\t<file-frame-number>"   << status.file_frame_number << L"</file-frame-number>"\r
                        << L"\n</layer>"\r
                        << L"\r\n";\r
 \r
index 69fbb41d76514c6ba82a2eee63f964175dfe5092..362a6c81dcf83941364c5d6ce9ce03fc24e19cb9 100644 (file)
@@ -8,7 +8,7 @@
   </paths>\r
   <channels>\r
     <channel>\r
-      <video-mode>PAL</video-mode>\r
+      <video-mode>NTSC</video-mode>\r
       <consumers>\r
         <screen>\r
         </screen>\r