Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Decklink: Use v210 in high bitdepth color path #1573

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/CMakeModules/Bootstrap_Linux.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,9 @@ endif()
IF (CMAKE_SYSTEM_PROCESSOR MATCHES "(i[3-6]86|x64|x86_64|amd64|e2k)")
ADD_COMPILE_OPTIONS (-msse3)
ADD_COMPILE_OPTIONS (-mssse3)
ADD_COMPILE_OPTIONS (-mavx)
ADD_COMPILE_OPTIONS (-msse4.1)
ADD_COMPILE_OPTIONS (-mavx2)
ELSE ()
ADD_COMPILE_DEFINITIONS (USE_SIMDE)
ENDIF ()
Expand Down
2 changes: 1 addition & 1 deletion src/CMakeModules/Bootstrap_Windows.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -268,4 +268,4 @@ add_definitions(-D_WIN32_WINNT=0x601)

set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /EHa /Zi /W4 /WX /MP /fp:fast /Zm192 /FIcommon/compiler/vs/disable_silly_warnings.h")
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /D TBB_USE_ASSERT=1 /D TBB_USE_DEBUG /bigobj")
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /Oi /Ot /Gy /bigobj")
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /Oi /arch:AVX2 /Ot /Gy /bigobj")
4 changes: 3 additions & 1 deletion src/accelerator/ogl/image/image_mixer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@
#include "../util/device.h"
#include "../util/texture.h"

#include <boost/align/aligned_allocator.hpp>

#include <common/array.h>
#include <common/bit_depth.h>
#include <common/future.h>
Expand Down Expand Up @@ -91,7 +93,7 @@ class image_renderer
const core::video_format_desc& format_desc)
{
if (layers.empty()) { // Bypass GPU with empty frame.
static const std::vector<uint8_t> buffer(max_frame_size_, 0);
static const std::vector<uint8_t, boost::alignment::aligned_allocator<uint8_t, 32>> buffer(max_frame_size_, 0);
return make_ready_future(array<const std::uint8_t>(buffer.data(), format_desc.size, true));
}

Expand Down
6 changes: 6 additions & 0 deletions src/common/memory.h
Original file line number Diff line number Diff line change
Expand Up @@ -641,6 +641,12 @@ shared_ptr<T> make_shared()
return shared_ptr<T>(std::make_shared<T>());
}

template <typename T, typename U>
shared_ptr<T> make_shared()
{
return shared_ptr<T>(std::make_shared<U>());
}

template <typename T, typename P0>
shared_ptr<T> make_shared(P0&& p0)
{
Expand Down
7 changes: 5 additions & 2 deletions src/modules/decklink/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@ project (decklink)

set(SOURCES
consumer/decklink_consumer.cpp
consumer/frame.cpp
consumer/hdr_v210_strategy.cpp
consumer/sdr_bgra_strategy.cpp
consumer/config.cpp
consumer/monitor.cpp

Expand All @@ -13,7 +14,9 @@ set(SOURCES
)
set(HEADERS
consumer/decklink_consumer.h
consumer/frame.h
consumer/hdr_v210_strategy.h
consumer/sdr_bgra_strategy.h
consumer/format_strategy.h
consumer/config.h
consumer/monitor.h

Expand Down
69 changes: 40 additions & 29 deletions src/modules/decklink/consumer/decklink_consumer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@
#include "common/os/thread.h"
#include "config.h"
#include "decklink_consumer.h"
#include "frame.h"
#include "hdr_v210_strategy.h"
#include "sdr_bgra_strategy.h"
#include "monitor.h"

#include "../decklink.h"
Expand Down Expand Up @@ -78,8 +79,7 @@ void set_latency(const com_iface_ptr<Configuration>& config,
com_ptr<IDeckLinkDisplayMode> get_display_mode(const com_iface_ptr<IDeckLinkOutput>& device,
core::video_format fmt,
BMDPixelFormat pix_fmt,
BMDSupportedVideoModeFlags flag,
bool hdr)
BMDSupportedVideoModeFlags flag)
{
auto format = get_decklink_video_format(fmt);

Expand Down Expand Up @@ -194,6 +194,12 @@ core::video_format_desc get_decklink_format(const port_configuration& confi
return fallback_format_desc;
}

spl::shared_ptr<format_strategy> create_format_strategy(bool hdr)
{
return hdr ? spl::make_shared<format_strategy, hdr_v210_strategy>()
: spl::make_shared<format_strategy, sdr_bgra_strategy>();
}

enum EOTF
{
SDR = 0,
Expand Down Expand Up @@ -230,22 +236,26 @@ class decklink_frame
hdr_meta_configuration hdr_metadata_;
BMDFrameFlags flags_;
BMDPixelFormat pix_fmt_;
int row_bytes_;

public:
decklink_frame(std::shared_ptr<void> data,
core::video_format_desc format_desc,
int nb_samples,
bool hdr,
BMDPixelFormat pix_fmt,
int row_bytes,
core::color_space color_space,
const hdr_meta_configuration& hdr_metadata)
: format_desc_(std::move(format_desc))
, data_(std::move(data))
, nb_samples_(nb_samples)
, hdr_(hdr)
, pix_fmt_(pix_fmt)
, row_bytes_(row_bytes)
, color_space_(color_space)
, hdr_metadata_(hdr_metadata)
, flags_(hdr ? bmdFrameFlagDefault | bmdFrameContainsHDRMetadata : bmdFrameFlagDefault)
, pix_fmt_(get_pixel_format(hdr))
{
}

Expand Down Expand Up @@ -299,7 +309,7 @@ class decklink_frame

long STDMETHODCALLTYPE GetWidth() override { return static_cast<long>(format_desc_.width); }
long STDMETHODCALLTYPE GetHeight() override { return static_cast<long>(format_desc_.height); }
long STDMETHODCALLTYPE GetRowBytes() override { return static_cast<long>(get_row_bytes(format_desc_, hdr_)); }
long STDMETHODCALLTYPE GetRowBytes() override { return static_cast<long>(row_bytes_); }
BMDPixelFormat STDMETHODCALLTYPE GetPixelFormat() override { return pix_fmt_; }
BMDFrameFlags STDMETHODCALLTYPE GetFlags() override { return flags_; }

Expand Down Expand Up @@ -427,6 +437,7 @@ struct decklink_secondary_port final : public IDeckLinkVideoOutputCallback
{
const configuration config_;
const port_configuration output_config_;
spl::shared_ptr<format_strategy> format_strategy_;
com_ptr<IDeckLink> decklink_ = get_device(output_config_.device_index);
com_iface_ptr<IDeckLinkOutput> output_ = iface_cast<IDeckLinkOutput>(decklink_);
com_iface_ptr<IDeckLinkKeyer> keyer_ = iface_cast<IDeckLinkKeyer>(decklink_, true);
Expand All @@ -443,9 +454,8 @@ struct decklink_secondary_port final : public IDeckLinkVideoOutputCallback
const core::video_format_desc decklink_format_desc_;
com_ptr<IDeckLinkDisplayMode> mode_ = get_display_mode(output_,
decklink_format_desc_.format,
get_pixel_format(config_.hdr),
bmdSupportedVideoModeDefault,
config_.hdr);
format_strategy_->get_pixel_format(),
bmdSupportedVideoModeDefault);

decklink_secondary_port(const configuration& config,
port_configuration output_config,
Expand All @@ -455,6 +465,7 @@ struct decklink_secondary_port final : public IDeckLinkVideoOutputCallback
int device_sync_group)
: config_(config)
, output_config_(std::move(output_config))
, format_strategy_(new sdr_bgra_strategy())
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should this be hardcoded as sdr?

, device_sync_group_(device_sync_group)
, channel_format_desc_(std::move(channel_format_desc))
, decklink_format_desc_(get_decklink_format(output_config_, main_decklink_format_desc))
Expand Down Expand Up @@ -546,13 +557,8 @@ struct decklink_secondary_port final : public IDeckLinkVideoOutputCallback
frame1 = frame;
}

auto image_data = convert_frame_for_port(channel_format_desc_,
decklink_format_desc_,
output_config_,
frame1,
frame2,
mode_->GetFieldDominance(),
config_.hdr);
auto image_data = format_strategy_->convert_frame_for_port(
channel_format_desc_, decklink_format_desc_, output_config_, frame1, frame2, mode_->GetFieldDominance());

schedule_next_video(image_data, 0, display_time);
}
Expand All @@ -563,6 +569,8 @@ struct decklink_secondary_port final : public IDeckLinkVideoOutputCallback
decklink_format_desc_,
nb_samples,
config_.hdr,
format_strategy_->get_pixel_format(),
format_strategy_->get_row_bytes(decklink_format_desc_.width),
core::color_space::bt709,
config_.hdr_meta));
if (FAILED(output_->ScheduleVideoFrame(get_raw(packed_frame),
Expand Down Expand Up @@ -592,8 +600,9 @@ struct decklink_secondary_port final : public IDeckLinkVideoOutputCallback

struct decklink_consumer final : public IDeckLinkVideoOutputCallback
{
const int channel_index_;
const configuration config_;
const int channel_index_;
const configuration config_;
spl::shared_ptr<format_strategy> format_strategy_;

com_ptr<IDeckLink> decklink_ = get_device(config_.primary.device_index);
com_iface_ptr<IDeckLinkOutput> output_ = iface_cast<IDeckLinkOutput>(decklink_);
Expand Down Expand Up @@ -629,16 +638,16 @@ struct decklink_consumer final : public IDeckLinkVideoOutputCallback

com_ptr<IDeckLinkDisplayMode> mode_ = get_display_mode(output_,
decklink_format_desc_.format,
get_pixel_format(config_.hdr),
bmdSupportedVideoModeDefault,
config_.hdr);
format_strategy_->get_pixel_format(),
bmdSupportedVideoModeDefault);

std::atomic<bool> abort_request_{false};

public:
decklink_consumer(const configuration& config, core::video_format_desc channel_format_desc, int channel_index)
: channel_index_(channel_index)
, config_(config)
, format_strategy_(create_format_strategy(config.hdr))
, channel_format_desc_(std::move(channel_format_desc))
, decklink_format_desc_(get_decklink_format(config.primary, channel_format_desc_))
{
Expand Down Expand Up @@ -717,7 +726,7 @@ struct decklink_consumer final : public IDeckLinkVideoOutputCallback
nb_samples);
}

std::shared_ptr<void> image_data = allocate_frame_data(decklink_format_desc_, config_.hdr);
std::shared_ptr<void> image_data = format_strategy_->allocate_frame_data(decklink_format_desc_);

schedule_next_video(image_data, nb_samples, video_scheduled_, config_.hdr_meta.default_color_space);
for (auto& context : secondary_port_contexts_) {
Expand Down Expand Up @@ -933,13 +942,13 @@ struct decklink_consumer final : public IDeckLinkVideoOutputCallback
tbb::parallel_for(-1, static_cast<int>(secondary_port_contexts_.size()), [&](int i) {
if (i == -1) {
// Primary port
std::shared_ptr<void> image_data = convert_frame_for_port(channel_format_desc_,
decklink_format_desc_,
config_.primary,
frame1,
frame2,
mode_->GetFieldDominance(),
config_.hdr);
std::shared_ptr<void> image_data =
format_strategy_->convert_frame_for_port(channel_format_desc_,
decklink_format_desc_,
config_.primary,
frame1,
frame2,
mode_->GetFieldDominance());

schedule_next_video(
image_data, nb_samples, video_display_time, frame1.pixel_format_desc().color_space);
Expand Down Expand Up @@ -1007,8 +1016,10 @@ struct decklink_consumer final : public IDeckLinkVideoOutputCallback
BMDTimeValue display_time,
core::color_space color_space)
{
auto fmt = format_strategy_->get_pixel_format();
auto row_bytes = format_strategy_->get_row_bytes(decklink_format_desc_.width);
auto fill_frame = wrap_raw<com_ptr, IDeckLinkVideoFrame>(new decklink_frame(
std::move(image_data), decklink_format_desc_, nb_samples, config_.hdr, color_space, config_.hdr_meta));
std::move(image_data), decklink_format_desc_, nb_samples, config_.hdr, fmt, row_bytes, color_space, config_.hdr_meta));
if (FAILED(output_->ScheduleVideoFrame(
get_raw(fill_frame), display_time, decklink_format_desc_.duration, decklink_format_desc_.time_scale))) {
CASPAR_LOG(error) << print() << L" Failed to schedule primary video.";
Expand Down
59 changes: 59 additions & 0 deletions src/modules/decklink/consumer/format_strategy.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
/*
* Copyright (c) 2011 Sveriges Television AB <[email protected]>
*
* This file is part of CasparCG (www.casparcg.com).
*
* CasparCG is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* CasparCG is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.
*
* Author: Niklas P Andersson, [email protected]
*/

#pragma once

#include "../StdAfx.h"

#include "config.h"

#include "../decklink_api.h"

#include <core/frame/frame.h>
#include <core/video_format.h>

#include <memory>

namespace caspar { namespace decklink {

class format_strategy
{
protected:
format_strategy() = default;

public:
format_strategy& operator=(const format_strategy&) = delete;
virtual ~format_strategy() = default;

format_strategy(const format_strategy&) = delete;

virtual BMDPixelFormat get_pixel_format() = 0;
virtual int get_row_bytes(int width) = 0;
virtual std::shared_ptr<void> allocate_frame_data(const core::video_format_desc& format_desc) = 0;
virtual std::shared_ptr<void> convert_frame_for_port(const core::video_format_desc& channel_format_desc,
const core::video_format_desc& decklink_format_desc,
const port_configuration& config,
const core::const_frame& frame1,
const core::const_frame& frame2,
BMDFieldDominance field_dominance) = 0;
};

}} // namespace caspar::decklink
Loading