]> git.sesse.net Git - casparcg/commitdiff
2.0.0.2:
authorronag <ronag@362d55ac-95cf-4e76-9f9a-cbaa9c17b72d>
Tue, 10 May 2011 23:08:37 +0000 (23:08 +0000)
committerronag <ronag@362d55ac-95cf-4e76-9f9a-cbaa9c17b72d>
Tue, 10 May 2011 23:08:37 +0000 (23:08 +0000)
 - video_format: Refactored and added duration and time_scale.
 - decklink_consumer: Refactored.
 - decklink_prodicer: Refactored.
 - amcp: Added log message to PLAY command.

git-svn-id: https://casparcg.svn.sourceforge.net/svnroot/casparcg/server/branches/2.0.0.2@714 362d55ac-95cf-4e76-9f9a-cbaa9c17b72d

17 files changed:
common/diagnostics/graph.cpp
common/diagnostics/graph.h
core/consumer/frame_consumer_device.cpp
core/mixer/frame_mixer_device.cpp
core/producer/frame_producer_device.cpp
core/video_format.cpp
core/video_format.h
modules/bluefish/consumer/bluefish_consumer.cpp
modules/decklink/consumer/decklink_consumer.cpp
modules/decklink/producer/decklink_producer.cpp
modules/decklink/util/util.h
modules/ffmpeg/producer/ffmpeg_producer.cpp
modules/flash/producer/flash_producer.cpp
modules/oal/consumer/oal_consumer.cpp
modules/ogl/consumer/ogl_consumer.cpp
protocol/amcp/AMCPCommandsImpl.cpp
shell/caspar.config

index 0bd362f9ea4edaeffb8b9ee51bdd946c15b7156b..f7d66843af532303b900a1d4cd3d1577504d9a38 100644 (file)
@@ -166,7 +166,7 @@ public:
 class line : public drawable\r
 {\r
        boost::optional<diagnostics::guide> guide_;\r
-       boost::circular_buffer<std::pair<float, bool>> line_data_;\r
+       boost::circular_buffer<std::pair<double, bool>> line_data_;\r
 \r
        std::vector<float>              tick_data_;\r
        bool                                    tick_tag_;\r
@@ -180,12 +180,12 @@ public:
                line_data_.push_back(std::make_pair(-1.0f, false));\r
        }\r
        \r
-       void update(float value)\r
+       void update(double value)\r
        {\r
                tick_data_.push_back(value);\r
        }\r
 \r
-       void set(float value)\r
+       void set(double value)\r
        {\r
                tick_data_.clear();\r
                tick_data_.push_back(value);\r
@@ -235,7 +235,7 @@ public:
                glColor4f(c_.red, c_.green, c_.blue, 0.7f);             \r
                for(size_t n = 0; n < line_data_.size(); ++n)           \r
                        if(line_data_[n].first > -0.5)\r
-                               glVertex3f(x+n*dx, std::max(0.05f, std::min(0.95f, (1.0f-line_data_[n].first)*0.8f + 0.1f)), 0.0f);             \r
+                               glVertex3d(x+n*dx, std::max(0.05, std::min(0.95, (1.0f-line_data_[n].first)*0.8 + 0.1f)), 0.0);         \r
                glEnd();\r
                                \r
                glEnable(GL_LINE_STIPPLE);\r
@@ -272,12 +272,12 @@ struct graph::implementation : public drawable
                , name_(parent_printer_ ? narrow(parent_printer_()) : "")\r
                , counter_(0){}\r
 \r
-       void update(const std::string& name, float value)\r
+       void update(const std::string& name, double value)\r
        {\r
                lines_[name].update(value);\r
        }\r
 \r
-       void set(const std::string& name, float value)\r
+       void set(const std::string& name, double value)\r
        {\r
                lines_[name].set(value);\r
        }\r
@@ -292,7 +292,7 @@ struct graph::implementation : public drawable
                lines_[name].set_color(c);\r
        }\r
        \r
-       void guide(const std::string& name, float value)\r
+       void guide(const std::string& name, double value)\r
        {\r
                lines_[name].guide(diagnostics::guide(value));  \r
        }\r
@@ -368,7 +368,7 @@ graph::graph(const printer& parent_printer) : impl_(env::properties().get("confi
                context::register_drawable(impl_);\r
 }\r
 \r
-void graph::update_value(const std::string& name, float value)\r
+void graph::update_value(const std::string& name, double value)\r
 {\r
        if(impl_)\r
        {       \r
@@ -379,7 +379,7 @@ void graph::update_value(const std::string& name, float value)
                });\r
        }\r
 }\r
-void graph::set_value(const std::string& name, float value)\r
+void graph::set_value(const std::string& name, double value)\r
 {\r
        if(impl_)\r
        {               \r
@@ -412,7 +412,7 @@ void graph::add_tag(const std::string& name)
                });\r
        }\r
 }\r
-void graph::add_guide(const std::string& name, float value)\r
+void graph::add_guide(const std::string& name, double value)\r
 {      \r
        if(impl_)\r
        {               \r
index a00f85526e608be87f24b6132fbc79e92f17d47f..3f54c0a7c1b6f3ad9c18b9d84bade6b93192d4e1 100644 (file)
@@ -56,11 +56,11 @@ class graph
        graph(const std::string& name);\r
        graph(const printer& parent_printer);\r
 public:\r
-       void update_value(const std::string& name, float value);\r
-       void set_value(const std::string& name, float value);\r
+       void update_value(const std::string& name, double value);\r
+       void set_value(const std::string& name, double value);\r
        void set_color(const std::string& name, color c);\r
        void add_tag(const std::string& name);\r
-       void add_guide(const std::string& name, float value);\r
+       void add_guide(const std::string& name, double value);\r
 private:\r
        struct implementation;\r
        std::shared_ptr<implementation> impl_;\r
index e04851978cea1b9ac4393b628c97cadd138f69a2..3a1dcbc1e54698afeddaba050378fbd313e826b1 100644 (file)
@@ -121,9 +121,9 @@ public:
                                        CASPAR_LOG(error) << print() << L" " << it->second->print() << L" Removed.";\r
                                }\r
                        }\r
-                       diag_->update_value("frame-time", static_cast<float>(frame_timer_.elapsed()/format_desc_.interval*0.5));\r
+                       diag_->update_value("frame-time", static_cast<float>(frame_timer_.elapsed()*format_desc_.fps*0.5));\r
                        \r
-                       diag_->update_value("tick-time", static_cast<float>(tick_timer_.elapsed()/format_desc_.interval*0.5));\r
+                       diag_->update_value("tick-time", static_cast<float>(tick_timer_.elapsed()*format_desc_.fps*0.5));\r
                        tick_timer_.restart();\r
                });\r
                diag_->set_value("input-buffer", static_cast<float>(executor_.size())/static_cast<float>(executor_.capacity()));\r
index 73f0d8ed5ef6ff11474f16a20ab6c84b067dab3c..b1f69eeb0fab9592cb446d5060df329f48293c39 100644 (file)
@@ -188,11 +188,11 @@ public:
                        auto audio = mix_audio(frames);\r
                        auto image = image_future.get();\r
 \r
-                       diag_->update_value("frame-time", static_cast<float>(frame_timer_.elapsed()/format_desc_.interval*0.5));\r
+                       diag_->update_value("frame-time", static_cast<float>(frame_timer_.elapsed()*format_desc_.fps*0.5));\r
 \r
                        output_(make_safe<const gpu_read_frame>(std::move(image), std::move(audio)));\r
 \r
-                       diag_->update_value("tick-time", static_cast<float>(tick_timer_.elapsed()/format_desc_.interval*0.5));\r
+                       diag_->update_value("tick-time", static_cast<float>(tick_timer_.elapsed()*format_desc_.fps*0.5));\r
                        tick_timer_.restart();\r
                });\r
                diag_->set_value("input-buffer", static_cast<float>(executor_.size())/static_cast<float>(executor_.capacity()));\r
index eb6e9473e1cefbd2639b951868c5f0b1169249cc..c36fd1f7cf81354dcc9fbd4d3d6fab86ec00d7cd 100644 (file)
@@ -93,7 +93,7 @@ public:
                \r
                output_timer_.restart();\r
                output_(draw());\r
-               diag_->update_value("output-time", static_cast<float>(output_timer_.elapsed()/format_desc_.interval*0.5));\r
+               diag_->update_value("output-time", static_cast<float>(output_timer_.elapsed()*format_desc_.fps*0.5));\r
 \r
                executor_.begin_invoke([=]{tick();});\r
        }\r
@@ -117,9 +117,9 @@ public:
                        result.insert(map.begin(), map.end());\r
                });\r
 \r
-               diag_->update_value("frame-time", static_cast<float>(frame_timer_.elapsed()/format_desc_.interval*0.5));\r
+               diag_->update_value("frame-time", static_cast<float>(frame_timer_.elapsed()*format_desc_.fps*0.5));\r
                                \r
-               diag_->update_value("tick-time", static_cast<float>(tick_timer_.elapsed()/format_desc_.interval*0.5));\r
+               diag_->update_value("tick-time", static_cast<float>(tick_timer_.elapsed()*format_desc_.fps*0.5));\r
                tick_timer_.restart();\r
 \r
                return result;\r
index 20c8ea051af57ace0c2f3a6299165def20be2c18..2118fda336c86b4eb08958a6bdadec80fb5b2771 100644 (file)
 \r
 #include <array>\r
 \r
-#define DEFINE_VIDEOFORMATDESC(w, h, m, f, s, fmt) { (fmt), (w), (h), (m), (m == video_mode::progressive ? f : f/2.0), (1.0/(m == video_mode::progressive ? f : f/2.0)), ((w)*(h)*4), (s)}\r
+#define DEFINE_VIDEOFORMATDESC(fmt, w, h, m, scale, duration, name) \\r
+{ \\r
+       (fmt), \\r
+       (w), \\r
+       (h), \\r
+       (m), \\r
+       ((double)scale/(double)duration),\\r
+       (scale),\\r
+       (duration),\\r
+       (m == video_mode::progressive ? 1 : 2),\\r
+       ((w)*(h)*4),\\r
+       (name)\\r
+}\r
 \r
 namespace caspar { namespace core {\r
        \r
 const video_format_desc format_descs[video_format::count] =  \r
 {                                                                         \r
-       DEFINE_VIDEOFORMATDESC(720,  576,  video_mode::upper,                   50,                     TEXT("pal"),            video_format::pal               ), \r
-       DEFINE_VIDEOFORMATDESC(720,  486,  video_mode::lower,                   60/1.001,       TEXT("ntsc"),           video_format::ntsc              ), \r
-       DEFINE_VIDEOFORMATDESC(720,  576,  video_mode::progressive,             25,                     TEXT("576p2500"),       video_format::x576p2500 ),\r
-       DEFINE_VIDEOFORMATDESC(1280, 720,  video_mode::progressive,             25,                     TEXT("720p2500"),       video_format::x720p2500 ), \r
-       DEFINE_VIDEOFORMATDESC(1280, 720,  video_mode::progressive,             50,                     TEXT("720p5000"),       video_format::x720p5000 ), \r
-       DEFINE_VIDEOFORMATDESC(1280, 720,  video_mode::progressive,             60/1.001,       TEXT("720p5994"),       video_format::x720p5994 ),\r
-       DEFINE_VIDEOFORMATDESC(1280, 720,  video_mode::progressive,             60,                     TEXT("720p6000"),       video_format::x720p6000 ),\r
-       DEFINE_VIDEOFORMATDESC(1920, 1080, video_mode::progressive,             24/1.001,       TEXT("1080p2397"),      video_format::x1080p2397),\r
-       DEFINE_VIDEOFORMATDESC(1920, 1080, video_mode::progressive,             24,                     TEXT("1080p2400"),      video_format::x1080p2400),\r
-       DEFINE_VIDEOFORMATDESC(1920, 1080, video_mode::upper,                   50,                     TEXT("1080i5000"),      video_format::x1080i5000),\r
-       DEFINE_VIDEOFORMATDESC(1920, 1080, video_mode::upper,                   60/1.001,       TEXT("1080i5994"),      video_format::x1080i5994),\r
-       DEFINE_VIDEOFORMATDESC(1920, 1080, video_mode::upper,                   60,                     TEXT("1080i6000"),      video_format::x1080i6000),\r
-       DEFINE_VIDEOFORMATDESC(1920, 1080, video_mode::progressive,             25,                     TEXT("1080p2500"),      video_format::x1080p2500),\r
-       DEFINE_VIDEOFORMATDESC(1920, 1080, video_mode::progressive,             30/1.001,       TEXT("1080p2997"),      video_format::x1080p2997),\r
-       DEFINE_VIDEOFORMATDESC(1920, 1080, video_mode::progressive,             30,                     TEXT("1080p3000"),      video_format::x1080p3000),\r
-       DEFINE_VIDEOFORMATDESC(1920, 1080, video_mode::progressive,             50,                     TEXT("1080p5000"),      video_format::x1080p5000),\r
-       DEFINE_VIDEOFORMATDESC(0,               0, video_mode::invalid,                 -1,                     TEXT("invalid"),        video_format::invalid   )\r
+       DEFINE_VIDEOFORMATDESC(video_format::pal                ,720,  576,  video_mode::upper,                 25,             1,              TEXT("pal")             ), \r
+       DEFINE_VIDEOFORMATDESC(video_format::ntsc               ,720,  486,  video_mode::lower,                 30000,  1001,   TEXT("ntsc")    ), \r
+       DEFINE_VIDEOFORMATDESC(video_format::x576p2500  ,720,  576,  video_mode::progressive,   25,             1,              TEXT("576p2500")),\r
+       DEFINE_VIDEOFORMATDESC(video_format::x720p2500  ,1280, 720,  video_mode::progressive,   25,             1,              TEXT("720p2500")), \r
+       DEFINE_VIDEOFORMATDESC(video_format::x720p5000  ,1280, 720,  video_mode::progressive,   50,             1,              TEXT("720p5000")), \r
+       DEFINE_VIDEOFORMATDESC(video_format::x720p5994  ,1280, 720,  video_mode::progressive,   60000,  1001,   TEXT("720p5994")),\r
+       DEFINE_VIDEOFORMATDESC(video_format::x720p6000  ,1280, 720,  video_mode::progressive,   60,             1,              TEXT("720p6000")),\r
+       DEFINE_VIDEOFORMATDESC(video_format::x1080p2397 ,1920, 1080, video_mode::progressive,   24000,  1001,   TEXT("1080p2398")),\r
+       DEFINE_VIDEOFORMATDESC(video_format::x1080p2400 ,1920, 1080, video_mode::progressive,   24,             1,              TEXT("1080p2400")),\r
+       DEFINE_VIDEOFORMATDESC(video_format::x1080i5000 ,1920, 1080, video_mode::upper,                 25,             1,              TEXT("1080i5000")),\r
+       DEFINE_VIDEOFORMATDESC(video_format::x1080i5994 ,1920, 1080, video_mode::upper,                 60000,  1001,   TEXT("1080i5994")),\r
+       DEFINE_VIDEOFORMATDESC(video_format::x1080i6000 ,1920, 1080, video_mode::upper,                 60,             1,              TEXT("1080i6000")),\r
+       DEFINE_VIDEOFORMATDESC(video_format::x1080p2500 ,1920, 1080, video_mode::progressive,   25,             1,              TEXT("1080p2500")),\r
+       DEFINE_VIDEOFORMATDESC(video_format::x1080p2997 ,1920, 1080, video_mode::progressive,   30000,  1001,   TEXT("1080p2997")),\r
+       DEFINE_VIDEOFORMATDESC(video_format::x1080p3000 ,1920, 1080, video_mode::progressive,   30,             1,              TEXT("1080p3000")),\r
+       DEFINE_VIDEOFORMATDESC(video_format::x1080p5000 ,1920, 1080, video_mode::progressive,   50,             1,              TEXT("1080p5000")),\r
+       DEFINE_VIDEOFORMATDESC(video_format::invalid    ,0,             0, video_mode::invalid,                 0,              1,              TEXT("invalid"))\r
 };\r
 \r
 const video_format_desc& video_format_desc::get(video_format::type format)     \r
index 32877919b8017a92059b487a5ac7da9b512d9613..2c7ba699ababac0cdfa910f48b0a8339438579dc 100644 (file)
@@ -71,7 +71,9 @@ struct video_format_desc
        size_t                                  height;         // output frame height\r
        video_mode::type                mode;           // progressive, interlaced upper field first, interlaced lower field first\r
        double                                  fps;            // actual framerate, e.g. i50 = 25 fps, p50 = 50 fps\r
-       double                                  interval;       // time between frames\r
+       size_t                                  time_scale;\r
+       size_t                                  duration;\r
+       size_t                                  field_count;\r
        size_t                                  size;           // output frame size in bytes \r
        std::wstring                    name;           // name of output format\r
 \r
index dc4247413c7e08a92dfa193bdd9b4dc6012dcafc..5bdef668d6655fabd004c17c39427caadea26ce5 100644 (file)
@@ -277,7 +277,7 @@ public:
                                sync_timer_.restart();\r
                                unsigned long n_field = 0;\r
                                blue_->wait_output_video_synch(UPD_FMT_FRAME, n_field);\r
-                               graph_->update_value("sync-time", static_cast<float>(sync_timer_.elapsed()/format_desc_.interval*0.5));\r
+                               graph_->update_value("sync-time", static_cast<float>(sync_timer_.elapsed()*format_desc_.fps*0.5));\r
 \r
                                if(embedded_audio_)\r
                                {               \r
@@ -311,9 +311,9 @@ public:
 \r
                                std::rotate(reserved_frames_.begin(), reserved_frames_.begin() + 1, reserved_frames_.end());\r
                                \r
-                               graph_->update_value("frame-time", static_cast<float>(frame_timer_.elapsed()/format_desc_.interval*0.5));\r
+                               graph_->update_value("frame-time", static_cast<float>(frame_timer_.elapsed()*format_desc_.fps*0.5));\r
 \r
-                               graph_->update_value("tick-time", static_cast<float>(tick_timer_.elapsed()/format_desc_.interval*0.5));\r
+                               graph_->update_value("tick-time", static_cast<float>(tick_timer_.elapsed()*format_desc_.fps*0.5));\r
                                tick_timer_.restart();\r
                        }\r
                        catch(...)\r
index 1d0b1d1a653bbb902861613fb22a81096377a9d3..054aec5a4b5b8746a66465819aa93251fcd3bb44 100644 (file)
 #include <common/exception/exceptions.h>\r
 #include <common/memory/memcpy.h>\r
 #include <common/memory/memclr.h>\r
-#include <common/utility/timer.h>\r
 \r
 #include <tbb/concurrent_queue.h>\r
 \r
 #include <boost/circular_buffer.hpp>\r
 #include <boost/timer.hpp>\r
 \r
-#include <array>\r
+#include <vector>\r
 \r
 #pragma warning(push)\r
 #pragma warning(disable : 4996)\r
@@ -100,8 +99,6 @@ struct decklink_consumer : public IDeckLinkVideoOutputCallback, public IDeckLink
        const std::wstring model_name_;\r
        const core::video_format_desc format_desc_;\r
 \r
-       BMDTimeScale frame_time_scale_;\r
-       BMDTimeValue frame_duration_;\r
        unsigned long frames_scheduled_;\r
        unsigned long audio_scheduled_;\r
                \r
@@ -125,10 +122,9 @@ public:
                , keyer_(decklink_)\r
                , model_name_(get_model_name(decklink_))\r
                , format_desc_(format_desc)\r
-               , audio_container_(5)\r
                , frames_scheduled_(0)\r
                , audio_scheduled_(0)\r
-               , buffer_size_(5) // Minimum buffer-size (4 + 1 tolerance).\r
+               , buffer_size_(4) // Minimum buffer-size (3 + 1 tolerance).\r
        {\r
                is_running_ = true;\r
                                                \r
@@ -139,45 +135,72 @@ public:
                graph_->set_color("dropped-frame", diagnostics::color(0.3f, 0.6f, 0.3f));\r
                graph_->set_color("flushed-frame", diagnostics::color(0.3f, 0.3f, 0.6f));\r
                \r
-               auto display_mode = get_display_mode(output_, format_desc_.format);\r
-               if(display_mode == nullptr) \r
-                       BOOST_THROW_EXCEPTION(caspar_exception() << msg_info(narrow(print()) + " Card does not support requested videoformat."));\r
-               \r
-               display_mode->GetFrameRate(&frame_duration_, &frame_time_scale_);\r
+               enable_video(get_display_mode(output_, format_desc_.format, bmdFormat8BitBGRA, bmdVideoOutputFlagDefault));\r
+                               \r
+               if(config.embedded_audio)\r
+                       enable_audio();\r
 \r
-               BMDDisplayModeSupport displayModeSupport;\r
-               if(FAILED(output_->DoesSupportVideoMode(display_mode->GetDisplayMode(), bmdFormat8BitBGRA, bmdVideoOutputFlagDefault, &displayModeSupport, nullptr)) || displayModeSupport == bmdDisplayModeNotSupported)\r
-                       BOOST_THROW_EXCEPTION(caspar_exception() << msg_info(narrow(print()) + " Card does not support requested videoformat."));\r
-               else if(displayModeSupport == bmdDisplayModeSupportedWithConversion)\r
-                       CASPAR_LOG(warning) << print() << " Display mode is supported with conversion.";\r
+               set_latency(config.latency);                            \r
+               set_keyer(config.keyer);\r
+                                                       \r
+               audio_container_.set_capacity(buffer_size_+1);\r
+               allocate_frames(buffer_size_+1);\r
+                               \r
+               CASPAR_LOG(info) << print() << L" Buffer-depth: " << buffer_size_;\r
+               \r
+               for(size_t n = 0; n < buffer_size_; ++n)\r
+                       schedule_next_video(core::read_frame::empty());\r
 \r
+               video_frame_buffer_.set_capacity(2);\r
+               audio_frame_buffer_.set_capacity(2);\r
+               \r
                if(config.embedded_audio)\r
+                       output_->BeginAudioPreroll();\r
+               else\r
                {\r
-                       if(FAILED(output_->EnableAudioOutput(bmdAudioSampleRate48kHz, bmdAudioSampleType16bitInteger, 2, bmdAudioOutputStreamTimestamped)))\r
-                               BOOST_THROW_EXCEPTION(caspar_exception() << msg_info(narrow(print()) + " Could not enable audio output."));\r
-                               \r
-                       if(FAILED(output_->SetAudioCallback(this)))\r
-                               BOOST_THROW_EXCEPTION(caspar_exception() << msg_info(narrow(print()) + " Could not set audio callback."));\r
+                       if(FAILED(output_->StartScheduledPlayback(0, format_desc_.time_scale, 1.0))) \r
+                               BOOST_THROW_EXCEPTION(caspar_exception() << msg_info(narrow(print()) + " Failed to schedule playback."));\r
+               }\r
+               \r
+               CASPAR_LOG(info) << print() << L" Successfully initialized for " << format_desc_.name;  \r
+       }\r
 \r
-                       CASPAR_LOG(info) << print() << L" Enabled embedded-audio.";\r
+       ~decklink_consumer()\r
+       {               \r
+               is_running_ = false;\r
+               video_frame_buffer_.clear();\r
+               audio_frame_buffer_.clear();\r
+               video_frame_buffer_.try_push(core::read_frame::empty());\r
+               audio_frame_buffer_.try_push(core::read_frame::empty());\r
 \r
-                       buffer_size_ = 6; //  Minimum buffer-size with embedded-audio (5 + 1 tolerance).\r
+               if(output_ != nullptr) \r
+               {\r
+                       output_->StopScheduledPlayback(0, nullptr, 0);\r
+                       if(config_.embedded_audio)\r
+                               output_->DisableAudioOutput();\r
+                       output_->DisableVideoOutput();\r
                }\r
-\r
-               if(config.latency == normal_latency)\r
+       }\r
+                       \r
+       void set_latency(latency latency)\r
+       {               \r
+               if(latency == normal_latency)\r
                {\r
                        configuration_->SetFlag(bmdDeckLinkConfigLowLatencyVideoOutput, false);\r
                        CASPAR_LOG(info) << print() << L" Enabled normal-latency mode";\r
                }\r
-               else if(config.latency == low_latency)\r
+               else if(latency == low_latency)\r
                {                       \r
                        configuration_->SetFlag(bmdDeckLinkConfigLowLatencyVideoOutput, true);\r
                        CASPAR_LOG(info) << print() << L" Enabled low-latency mode";\r
                }\r
                else\r
                        CASPAR_LOG(info) << print() << L" Uses driver latency settings.";       \r
-                               \r
-               if(config.keyer == internal_key) \r
+       }\r
+\r
+       void set_keyer(key keyer)\r
+       {\r
+               if(keyer == internal_key) \r
                {\r
                        if(FAILED(keyer_->Enable(FALSE)))                       \r
                                CASPAR_LOG(error) << print() << L" Failed to enable internal keyer.";                   \r
@@ -186,7 +209,7 @@ public:
                        else\r
                                CASPAR_LOG(info) << print() << L" Enabled internal keyer.";             \r
                }\r
-               else if(config.keyer == external_key)\r
+               else if(keyer == external_key)\r
                {\r
                        if(FAILED(keyer_->Enable(TRUE)))                        \r
                                CASPAR_LOG(error) << print() << L" Failed to enable external keyer.";   \r
@@ -197,69 +220,50 @@ public:
                }\r
                else\r
                        CASPAR_LOG(info) << print() << L" Uses driver keyer settings."; \r
+       }\r
+       \r
+       void enable_audio()\r
+       {\r
+               if(FAILED(output_->EnableAudioOutput(bmdAudioSampleRate48kHz, bmdAudioSampleType16bitInteger, 2, bmdAudioOutputStreamTimestamped)))\r
+                               BOOST_THROW_EXCEPTION(caspar_exception() << msg_info(narrow(print()) + " Could not enable audio output."));\r
+                               \r
+               if(FAILED(output_->SetAudioCallback(this)))\r
+                       BOOST_THROW_EXCEPTION(caspar_exception() << msg_info(narrow(print()) + " Could not set audio callback."));\r
+\r
+               CASPAR_LOG(info) << print() << L" Enabled embedded-audio.";\r
+\r
+               buffer_size_ = 5; //  Minimum buffer-size with embedded-audio (4 + 1 tolerance).\r
+       }\r
 \r
-               if(FAILED(output_->EnableVideoOutput(display_mode->GetDisplayMode(), bmdVideoOutputFlagDefault))) \r
+       void enable_video(BMDDisplayMode display_mode)\r
+       {\r
+               if(FAILED(output_->EnableVideoOutput(display_mode, bmdVideoOutputFlagDefault))) \r
                        BOOST_THROW_EXCEPTION(caspar_exception() << msg_info(narrow(print()) + " Could not enable video output."));\r
                \r
                if(FAILED(output_->SetScheduledFrameCompletionCallback(this)))\r
                        BOOST_THROW_EXCEPTION(caspar_exception() << msg_info(narrow(print()) + " Failed to set playback completion callback."));\r
-                                       \r
-               for(size_t n = 0; n < buffer_size_+1; ++n)\r
-               {\r
-                       CComPtr<IDeckLinkMutableVideoFrame> frame;\r
+       }\r
 \r
-                       if(FAILED(output_->CreateVideoFrame(format_desc_.width, format_desc_.height, format_desc_.size/format_desc_.height, bmdFormat8BitBGRA, bmdFrameFlagDefault, &frame)))\r
+       void allocate_frames(size_t count)\r
+       {\r
+               std::pair<void*, CComPtr<IDeckLinkMutableVideoFrame>> frame;\r
+               std::generate_n(std::back_inserter(reserved_frames_), count, [&]() -> decltype(frame)\r
+               {\r
+                       if(FAILED(output_->CreateVideoFrame(format_desc_.width, format_desc_.height, format_desc_.size/format_desc_.height, bmdFormat8BitBGRA, bmdFrameFlagDefault, &frame.second)))\r
                                BOOST_THROW_EXCEPTION(caspar_exception() << msg_info(narrow(print()) + " Failed to create frame."));\r
 \r
-                       void* bytes = nullptr;\r
-\r
-                       if(FAILED(frame->GetBytes(&bytes)) || bytes == nullptr)\r
+                       if(FAILED(frame.second->GetBytes(&frame.first)) || frame.first == nullptr)\r
                                BOOST_THROW_EXCEPTION(caspar_exception() << msg_info(narrow(print()) + " Failed to get frame bytes."));\r
 \r
-                       reserved_frames_.push_back(std::make_pair(bytes, frame));\r
-               }\r
-               \r
-               CASPAR_LOG(info) << print() << L" Buffer-depth: " << buffer_size_;\r
-               \r
-               for(size_t n = 0; n < buffer_size_; ++n)\r
-                       schedule_next_video(core::read_frame::empty());\r
-\r
-               video_frame_buffer_.set_capacity(2);\r
-               audio_frame_buffer_.set_capacity(2);\r
-               \r
-               if(config.embedded_audio)\r
-                       output_->BeginAudioPreroll();\r
-               else\r
-               {\r
-                       if(FAILED(output_->StartScheduledPlayback(0, frame_time_scale_, 1.0))) \r
-                               BOOST_THROW_EXCEPTION(caspar_exception() << msg_info(narrow(print()) + " Failed to schedule playback."));\r
-               }\r
-               \r
-               CASPAR_LOG(info) << print() << L" Successfully initialized for " << format_desc_.name;  \r
+                       return frame;\r
+               });\r
        }\r
 \r
-       ~decklink_consumer()\r
-       {               \r
-               is_running_ = false;\r
-               video_frame_buffer_.clear();\r
-               audio_frame_buffer_.clear();\r
-               video_frame_buffer_.try_push(core::read_frame::empty());\r
-               audio_frame_buffer_.try_push(core::read_frame::empty());\r
-\r
-               if(output_ != nullptr) \r
-               {\r
-                       output_->StopScheduledPlayback(0, nullptr, 0);\r
-                       if(config_.embedded_audio)\r
-                               output_->DisableAudioOutput();\r
-                       output_->DisableVideoOutput();\r
-               }\r
-       }\r
-                       \r
-       virtual HRESULT STDMETHODCALLTYPE       QueryInterface (REFIID, LPVOID*)        {return E_NOINTERFACE;}\r
-       virtual ULONG STDMETHODCALLTYPE         AddRef ()                                                       {return 1;}\r
-       virtual ULONG STDMETHODCALLTYPE         Release ()                                                      {return 1;}\r
+       STDMETHOD (QueryInterface(REFIID, LPVOID*))     {return E_NOINTERFACE;}\r
+       STDMETHOD_(ULONG, AddRef())                                     {return 1;}\r
+       STDMETHOD_(ULONG, Release())                            {return 1;}\r
        \r
-       virtual HRESULT STDMETHODCALLTYPE ScheduledFrameCompleted(IDeckLinkVideoFrame* /*completedFrame*/, BMDOutputFrameCompletionResult result)\r
+       STDMETHOD(ScheduledFrameCompleted(IDeckLinkVideoFrame* /*completedFrame*/, BMDOutputFrameCompletionResult result))\r
        {\r
                if(!is_running_)\r
                        return E_FAIL;\r
@@ -278,14 +282,14 @@ public:
                return S_OK;\r
        }\r
 \r
-       virtual HRESULT STDMETHODCALLTYPE ScheduledPlaybackHasStopped (void)\r
+       STDMETHOD(ScheduledPlaybackHasStopped())\r
        {\r
                is_running_ = false;\r
                CASPAR_LOG(info) << print() << L" Scheduled playback has stopped.";\r
                return S_OK;\r
        }\r
                \r
-       virtual HRESULT STDMETHODCALLTYPE RenderAudioSamples(BOOL preroll)\r
+       STDMETHOD(RenderAudioSamples(BOOL preroll))\r
        {\r
                if(!is_running_)\r
                        return E_FAIL;\r
@@ -294,14 +298,13 @@ public:
                {\r
                        if(preroll)\r
                        {\r
-                               if(FAILED(output_->StartScheduledPlayback(0, frame_time_scale_, 1.0)))\r
+                               if(FAILED(output_->StartScheduledPlayback(0, format_desc_.time_scale, 1.0)))\r
                                        BOOST_THROW_EXCEPTION(caspar_exception() << msg_info(narrow(print()) + " Failed to schedule playback."));\r
                        }\r
 \r
                        std::shared_ptr<const core::read_frame> frame;\r
                        audio_frame_buffer_.pop(frame);\r
-                       schedule_next_audio(safe_ptr<const core::read_frame>(frame));\r
-               \r
+                       schedule_next_audio(safe_ptr<const core::read_frame>(frame));           \r
                }\r
                catch(...)\r
                {\r
@@ -332,30 +335,27 @@ public:
                else\r
                        fast_memclr(reserved_frames_.front().first, format_desc_.size);\r
 \r
-               if(FAILED(output_->ScheduleVideoFrame(reserved_frames_.front().second, (frames_scheduled_++) * frame_duration_, frame_duration_, frame_time_scale_)))\r
+               if(FAILED(output_->ScheduleVideoFrame(reserved_frames_.front().second, (frames_scheduled_++) * format_desc_.duration, format_desc_.duration, format_desc_.time_scale)))\r
                        CASPAR_LOG(error) << print() << L" Failed to schedule video.";\r
 \r
                std::rotate(reserved_frames_.begin(), reserved_frames_.begin() + 1, reserved_frames_.end());\r
-               graph_->update_value("tick-time", static_cast<float>(tick_timer_.elapsed()/format_desc_.interval)*0.5f);\r
+               graph_->update_value("tick-time", tick_timer_.elapsed()*format_desc_.fps*0.5);\r
                tick_timer_.restart();\r
        }\r
 \r
        void send(const safe_ptr<const core::read_frame>& frame)\r
        {\r
-               if(!is_running_)\r
-                       return;\r
-\r
                if(exception_ != nullptr)\r
                        std::rethrow_exception(exception_);\r
 \r
+               if(!is_running_)\r
+                       BOOST_THROW_EXCEPTION(caspar_exception() << msg_info(narrow(print()) + " Is not running."));\r
+\r
                video_frame_buffer_.push(frame);\r
                if(config_.embedded_audio)\r
-                       audio_frame_buffer_.push(frame);\r
-               \r
+                       audio_frame_buffer_.push(frame);                \r
        }\r
-\r
-       size_t buffer_depth() const {return 1;}\r
-\r
+       \r
        std::wstring print() const\r
        {\r
                return model_name_ + L" [" + boost::lexical_cast<std::wstring>(config_.device_index) + L"]";\r
@@ -387,11 +387,6 @@ public:
        {\r
                return context_->print();\r
        }\r
-\r
-       virtual size_t buffer_depth() const \r
-       {\r
-               return context_->buffer_depth();\r
-       }\r
 };     \r
 \r
 safe_ptr<core::frame_consumer> create_decklink_consumer(const std::vector<std::wstring>& params) \r
@@ -441,4 +436,52 @@ safe_ptr<core::frame_consumer> create_decklink_consumer(const boost::property_tr
        return make_safe<decklink_consumer_proxy>(config);\r
 }\r
 \r
-}
\ No newline at end of file
+}\r
+\r
+/*\r
+##############################################################################\r
+Pre-rolling\r
+\r
+Mail: 2011-05-09\r
+\r
+Yoshan\r
+BMD Developer Support\r
+developer@blackmagic-design.com\r
+\r
+-----------------------------------------------------------------------------\r
+\r
+Thanks for your inquiry. The minimum number of frames that you can preroll \r
+for scheduled playback is three frames for video and four frames for audio. \r
+As you mentioned if you preroll less frames then playback will not start or\r
+playback will be very sporadic. From our experience with Media Express, we \r
+recommended that at least seven frames are prerolled for smooth playback. \r
+\r
+Regarding the bmdDeckLinkConfigLowLatencyVideoOutput flag:\r
+There can be around 3 frames worth of latency on scheduled output.\r
+When the bmdDeckLinkConfigLowLatencyVideoOutput flag is used this latency is\r
+reduced  or removed for scheduled playback. If the DisplayVideoFrameSync() \r
+method is used, the bmdDeckLinkConfigLowLatencyVideoOutput setting will \r
+guarantee that the provided frame will be output as soon the previous \r
+frame output has been completed.\r
+################################################################################\r
+*/\r
+\r
+/*\r
+##############################################################################\r
+Async DMA Transfer without redundant copying\r
+\r
+Mail: 2011-05-10\r
+\r
+Yoshan\r
+BMD Developer Support\r
+developer@blackmagic-design.com\r
+\r
+-----------------------------------------------------------------------------\r
+\r
+Thanks for your inquiry. You could try subclassing IDeckLinkMutableVideoFrame \r
+and providing a pointer to your video buffer when GetBytes() is called. \r
+This may help to keep copying to a minimum. Please ensure that the pixel \r
+format is in bmdFormat10BitYUV, otherwise the DeckLink API / driver will \r
+have to colourspace convert which may result in additional copying.\r
+################################################################################\r
+*/
\ No newline at end of file
index 268cb14cb57ef01f5dcb3f58fc58b1c805fcaaaa..6fd45ae29f72c3844a5d320c3b5dbf99dac95195 100644 (file)
@@ -94,19 +94,10 @@ public:
                graph_->set_color("dropped-frame", diagnostics::color(0.3f, 0.6f, 0.3f));\r
                graph_->set_color("output-buffer", diagnostics::color(0.0f, 1.0f, 0.0f));\r
                \r
-               auto display_mode = get_display_mode(input_, format_desc_.format);\r
-               if(!display_mode) \r
-                       BOOST_THROW_EXCEPTION(caspar_exception() << msg_info(narrow(print()) + " Card does not support requested videoformat."));\r
+               auto display_mode = get_display_mode(input_, format_desc_.format, bmdFormat8BitYUV, bmdVideoInputFlagDefault);\r
                \r
-               // NOTE: For some reason the code below fails even for PAL.\r
-               //BMDDisplayModeSupport displayModeSupport;\r
-               //if(FAILED(input_->DoesSupportVideoMode(display_mode->GetDisplayMode(), bmdFormat8BitBGRA, bmdVideoOutputFlagDefault, &displayModeSupport, nullptr)) || displayModeSupport == bmdDisplayModeNotSupported)\r
-               //      BOOST_THROW_EXCEPTION(caspar_exception() << msg_info(narrow(print()) + " Card does not support requested videoformat."));\r
-               //else if(displayModeSupport == bmdDisplayModeSupportedWithConversion)\r
-               //      CASPAR_LOG(warning) << print() << " Display mode is supported with conversion.";\r
-\r
                // NOTE: bmdFormat8BitARGB is currently not supported by any decklink card. (2011-05-08)\r
-               if(FAILED(input_->EnableVideoInput(display_mode->GetDisplayMode(), bmdFormat8BitYUV, 0))) \r
+               if(FAILED(input_->EnableVideoInput(display_mode, bmdFormat8BitYUV, 0))) \r
                        BOOST_THROW_EXCEPTION(caspar_exception() << msg_info(narrow(print()) + " Could not enable video input."));\r
 \r
                if(FAILED(input_->EnableAudioInput(bmdAudioSampleRate48kHz, bmdAudioSampleType16bitInteger, 2))) \r
@@ -143,7 +134,7 @@ public:
        {       \r
                try\r
                {\r
-                       graph_->update_value("tick-time", static_cast<float>(perf_timer_.elapsed()/format_desc_.interval*0.5));\r
+                       graph_->update_value("tick-time", perf_timer_.elapsed()*format_desc_.fps*0.5);\r
                        perf_timer_.restart();\r
                                                \r
                        core::pixel_format_desc desc;\r
index 2ddfba052e025bf357b7a0a3906b369e3cab0b80..4301e37816c0e6342855875f9eb80ed77bb04f00 100644 (file)
@@ -28,6 +28,8 @@
 \r
 namespace caspar { \r
        \r
+namespace internal {\r
+\r
 static BMDDisplayMode get_decklink_video_format(core::video_format::type fmt) \r
 {\r
        switch(fmt)\r
@@ -50,29 +52,38 @@ static BMDDisplayMode get_decklink_video_format(core::video_format::type fmt)
        default:                                                                return (BMDDisplayMode)ULONG_MAX;\r
        }\r
 }\r
-       \r
-template<typename T>\r
-static CComPtr<IDeckLinkDisplayMode> get_display_mode(const T& device, BMDDisplayMode format)\r
+\r
+template<typename T, typename F>\r
+BMDDisplayMode get_display_mode(const T& device, BMDDisplayMode format, BMDPixelFormat pix_fmt, F flag)\r
 {\r
        CComPtr<IDeckLinkDisplayModeIterator> iterator;\r
        CComPtr<IDeckLinkDisplayMode>             mode;\r
        \r
-       if(FAILED(device->GetDisplayModeIterator(&iterator)))\r
-               return nullptr;\r
-\r
-       while(SUCCEEDED(iterator->Next(&mode)) && mode != nullptr)\r
-       {       \r
-               if(mode->GetDisplayMode() == format)\r
-                       return mode;\r
+       if(SUCCEEDED(device->GetDisplayModeIterator(&iterator)))\r
+       {\r
+               while(SUCCEEDED(iterator->Next(&mode)) && \r
+                               mode != nullptr && \r
+                               mode->GetDisplayMode() != format){}\r
        }\r
 \r
-       return nullptr;\r
+       if(!mode)\r
+               BOOST_THROW_EXCEPTION(caspar_exception() << msg_info("Device does not support requested video-format."));\r
+               \r
+       BMDDisplayModeSupport displayModeSupport;\r
+       if(FAILED(device->DoesSupportVideoMode(mode->GetDisplayMode(), pix_fmt, flag, &displayModeSupport, nullptr)) || displayModeSupport == bmdDisplayModeNotSupported)\r
+               BOOST_THROW_EXCEPTION(caspar_exception() << msg_info("Device does not support requested video-format."));\r
+       else if(displayModeSupport == bmdDisplayModeSupportedWithConversion)\r
+               CASPAR_LOG(warning) << L"Device supports video-format with conversion.";\r
+\r
+       return mode->GetDisplayMode();\r
 }\r
 \r
-template<typename T>\r
-static CComPtr<IDeckLinkDisplayMode> get_display_mode(const T& output, core::video_format::type fmt)\r
+}      \r
+\r
+template<typename T, typename F>\r
+static BMDDisplayMode get_display_mode(const T& device, core::video_format::type fmt, BMDPixelFormat pix_fmt, F flag)\r
 {      \r
-       return get_display_mode(output, get_decklink_video_format(fmt));\r
+       return internal::get_display_mode(device, internal::get_decklink_video_format(fmt), pix_fmt, flag);\r
 }\r
 \r
 template<typename T>\r
@@ -99,7 +110,7 @@ static CComPtr<IDeckLink> get_device(size_t device_index)
        while(n < device_index && pDecklinkIterator->Next(&decklink) == S_OK){++n;}     \r
 \r
        if(n != device_index || !decklink)\r
-               BOOST_THROW_EXCEPTION(caspar_exception() << msg_info("Decklink card not found.") << arg_name_info("device_index") << arg_value_info(boost::lexical_cast<std::string>(device_index)));\r
+               BOOST_THROW_EXCEPTION(caspar_exception() << msg_info("Decklink device not found.") << arg_name_info("device_index") << arg_value_info(boost::lexical_cast<std::string>(device_index)));\r
                \r
        return decklink;\r
 }\r
index c4cf3df072849a964a7240b75f3a88223071ceb1..9d8c9ee1c4cb620dd71a1f8d738d55942f9d0bdb 100644 (file)
@@ -170,7 +170,7 @@ public:
                                return last_frame_;                     \r
                }\r
                \r
-               graph_->update_value("frame-time", static_cast<float>(perf_timer_.elapsed()/frame_factory_->get_video_format_desc().interval*0.5));\r
+               graph_->update_value("frame-time", static_cast<float>(perf_timer_.elapsed()*frame_factory_->get_video_format_desc().fps*0.5));\r
 \r
                auto result = last_frame_;\r
                if(!ouput_channel_.empty())             \r
index c602bbfd0145deb7b36599c17d7e4f9cc5661ae0..8c1619547bbd8d3bf6b91876b95f774261458d19 100644 (file)
@@ -297,20 +297,21 @@ public:
                        {               \r
                                const auto& format_desc = frame_factory_->get_video_format_desc();\r
                                auto frame = core::basic_frame::empty();\r
-                               if(abs(context_->fps()/2.0 - format_desc.fps) < 0.1) // flash 50fps, format 50i\r
+\r
+                               if(abs(context_->fps()/2.0 - format_desc.fps) < 0.1) // flash == 2 * format -> interlace\r
                                {\r
                                        auto frame1 = context_->render_frame(frame_buffer_.size() < frame_buffer_.capacity());\r
                                        auto frame2 = context_->render_frame(frame_buffer_.size() < frame_buffer_.capacity());\r
                                        frame_buffer_.push(core::basic_frame::interlace(frame1, frame2, format_desc.mode));\r
                                        frame = frame2;\r
                                }\r
-                               else if(abs(context_->fps()- format_desc.fps/2.0 ) < 0.1) // flash 25fps, format 50p\r
+                               else if(abs(context_->fps()- format_desc.fps/2.0 ) < 0.1) // format == 2 * flash -> duplicate\r
                                {\r
                                        frame = context_->render_frame(frame_buffer_.size() < frame_buffer_.capacity());\r
                                        frame_buffer_.push(frame);\r
                                        frame_buffer_.push(frame);\r
                                }\r
-                               else //if(abs(renderer_->fps() - format_desc_.fps) < 0.1) // flash 25fps, format 50i or flash 50fps, format 50p\r
+                               else //if(abs(renderer_->fps() - format_desc_.fps) < 0.1) // format == flash -> simple\r
                                {\r
                                        frame = context_->render_frame(frame_buffer_.size() < frame_buffer_.capacity());\r
                                        frame_buffer_.push(frame);\r
index 9d43778cccc00ccea6a1a376de1465b69ad40cdf..99d0df4efee1a8f5341044fe42264d386f1e1e28 100644 (file)
@@ -95,7 +95,7 @@ public:
                data.Samples = container_.back().data();\r
                data.NbSamples = container_.back().size();      \r
                \r
-               graph_->update_value("tick-time", static_cast<float>(perf_timer_.elapsed()/format_desc_.interval*0.5));         \r
+               graph_->update_value("tick-time", perf_timer_.elapsed()*format_desc_.fps*0.5);          \r
                perf_timer_.restart();\r
 \r
                return is_running_;\r
index cd263460161dfa86add4371ac93ed76150cb597b..52e139e66cdc0ee89c4b232ffd64ee340b33411d 100644 (file)
@@ -285,7 +285,7 @@ public:
                        }\r
                        render(frame);\r
                        window_.Display();\r
-                       graph_->update_value("frame-time", static_cast<float>(perf_timer_.elapsed()/format_desc_.interval*0.5));\r
+                       graph_->update_value("frame-time", static_cast<float>(perf_timer_.elapsed()*format_desc_.fps*0.5));\r
                });\r
        }\r
 \r
index e1392cc342d46535c0daa9bc138e87567fe5fd15..11b6032816fb479fd11aa5c2e8a58fa85bdd5fa1 100644 (file)
@@ -616,6 +616,8 @@ bool PlayCommand::DoExecute()
                                lbg.AddParameter(*it);\r
                        if(!lbg.Execute())\r
                                CASPAR_LOG(warning) << " Failed to play.";\r
+\r
+                       CASPAR_LOG(info) << "Playing " << _parameters[0];\r
                }\r
 \r
                GetChannel()->producer()->play(GetLayerIndex());\r
index 77288bc9c3e9654a057cd57cc3926c26cc8ae46a..adb9044ea91e05d0f9443a5bd1f69de2a6d26e8f 100644 (file)
     <channel>\r
       <videomode>PAL</videomode>\r
       <consumers>\r
-        <!--<decklink>\r
+        <decklink>\r
           <device>1</device>\r
           <embedded-audio>true</embedded-audio>\r
           <latency>low</latency>\r
           <key>external</key>\r
         </decklink>\r
-        <ogl>\r
+        <!--<ogl>\r
           <device>0</device>\r
           <stretch>uniform</stretch>\r
           <windowed>true</windowed>\r
         </ogl>-->\r
         <!--<audio/>-->\r
-        <bluefish>\r
+        <!--<bluefish>\r
           <device>1</device>\r
           <embedded-audio>true</embedded-audio>\r
-        </bluefish>\r
+        </bluefish>-->\r
       </consumers>\r
     </channel>\r
 </channels>\r