fix output res&frame rate
This commit is contained in:
@@ -54,13 +54,13 @@ void DeckLinkOutNode::on_add_reader(const std::string& port_id, mxlFlowReader re
|
|||||||
|
|
||||||
mxlFlowConfigInfo config{};
|
mxlFlowConfigInfo config{};
|
||||||
mxlFlowReaderGetConfigInfo(*reader_, &config);
|
mxlFlowReaderGetConfigInfo(*reader_, &config);
|
||||||
grain_rate_ = config.common.grainRate;
|
flow_rate_ = config.common.grainRate;
|
||||||
|
|
||||||
auto now = mxlGetTime();
|
auto now = mxlGetTime();
|
||||||
auto current_index = mxlTimestampToIndex(&grain_rate_, now);
|
auto current_index = mxlTimestampToIndex(&flow_rate_, now);
|
||||||
read_index_ = current_index - 2;
|
read_index_ = current_index - 2;
|
||||||
|
|
||||||
spdlog::info("DeckLink-out: reader added, grain_rate={}/{}", grain_rate_.numerator, grain_rate_.denominator);
|
spdlog::info("DeckLink-out: reader added, flow_rate={}/{}", flow_rate_.numerator, flow_rate_.denominator);
|
||||||
|
|
||||||
if (!open_device()) {
|
if (!open_device()) {
|
||||||
spdlog::error("DeckLink-out: failed to open device");
|
spdlog::error("DeckLink-out: failed to open device");
|
||||||
@@ -133,12 +133,28 @@ bool DeckLinkOutNode::open_device() {
|
|||||||
|
|
||||||
IDeckLinkDisplayMode* mode = nullptr;
|
IDeckLinkDisplayMode* mode = nullptr;
|
||||||
if (output_->GetDisplayMode(display_mode_, &mode) == S_OK) {
|
if (output_->GetDisplayMode(display_mode_, &mode) == S_OK) {
|
||||||
|
out_width_ = mode->GetWidth();
|
||||||
|
out_height_ = mode->GetHeight();
|
||||||
BMDTimeValue duration = 0;
|
BMDTimeValue duration = 0;
|
||||||
BMDTimeScale scale = 0;
|
BMDTimeScale scale = 0;
|
||||||
mode->GetFrameRate(&duration, &scale);
|
mode->GetFrameRate(&duration, &scale);
|
||||||
frame_duration_ = duration;
|
frame_duration_ = duration;
|
||||||
time_scale_ = scale;
|
time_scale_ = scale;
|
||||||
mode->Release();
|
mode->Release();
|
||||||
|
|
||||||
|
output_rate_.numerator = static_cast<int32_t>(scale);
|
||||||
|
output_rate_.denominator = static_cast<int32_t>(duration);
|
||||||
|
auto g = std::__gcd(output_rate_.numerator, output_rate_.denominator);
|
||||||
|
output_rate_.numerator /= g;
|
||||||
|
output_rate_.denominator /= g;
|
||||||
|
|
||||||
|
is_interlaced_ = (display_mode_ == bmdModeHD1080i50 ||
|
||||||
|
display_mode_ == bmdModeHD1080i5994);
|
||||||
|
|
||||||
|
spdlog::info("DeckLink-out: {}x{} @ {}/{} fps, interlaced={}",
|
||||||
|
out_width_, out_height_,
|
||||||
|
output_rate_.numerator, output_rate_.denominator,
|
||||||
|
is_interlaced_);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (output_->StartScheduledPlayback(0, time_scale_, 1.0) != S_OK) {
|
if (output_->StartScheduledPlayback(0, time_scale_, 1.0) != S_OK) {
|
||||||
@@ -210,19 +226,22 @@ void DeckLinkOutNode::process() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto deadline = mxlIndexToTimestamp(&grain_rate_, read_index_ + 1);
|
auto deadline = mxlIndexToTimestamp(&output_rate_, grains_read_ + 1);
|
||||||
mxlSleepUntil(deadline);
|
mxlSleepUntil(deadline);
|
||||||
|
|
||||||
|
auto out_timestamp = mxlIndexToTimestamp(&output_rate_, grains_read_);
|
||||||
|
auto source_index = mxlTimestampToIndex(&flow_rate_, out_timestamp);
|
||||||
|
|
||||||
mxlGrainInfo grain_info{};
|
mxlGrainInfo grain_info{};
|
||||||
uint8_t* payload = nullptr;
|
uint8_t* payload = nullptr;
|
||||||
auto status = mxlFlowReaderGetGrain(*reader_, read_index_, 5000000ULL, &grain_info, &payload);
|
auto status = mxlFlowReaderGetGrain(*reader_, source_index, 5000000ULL, &grain_info, &payload);
|
||||||
if (status != MXL_STATUS_OK) {
|
if (status != MXL_STATUS_OK) {
|
||||||
if (status == MXL_ERR_OUT_OF_RANGE_TOO_LATE || status == MXL_ERR_OUT_OF_RANGE_TOO_EARLY) {
|
if (status == MXL_ERR_OUT_OF_RANGE_TOO_LATE || status == MXL_ERR_OUT_OF_RANGE_TOO_EARLY) {
|
||||||
auto now = mxlGetTime();
|
auto now = mxlGetTime();
|
||||||
auto current_index = mxlTimestampToIndex(&grain_rate_, now);
|
auto current_index = mxlTimestampToIndex(&flow_rate_, now);
|
||||||
read_index_ = current_index - 2;
|
read_index_ = current_index - 2;
|
||||||
if (grains_read_ == 0) {
|
if (grains_read_ == 0) {
|
||||||
spdlog::warn("DeckLink-out: realigned to index {}", read_index_);
|
spdlog::warn("DeckLink-out: realigned to source index {}", read_index_);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
@@ -232,20 +251,17 @@ void DeckLinkOutNode::process() {
|
|||||||
mxlFlowReaderGetConfigInfo(*reader_, &config);
|
mxlFlowReaderGetConfigInfo(*reader_, &config);
|
||||||
auto grain_size = grain_info.grainSize;
|
auto grain_size = grain_info.grainSize;
|
||||||
|
|
||||||
long height = 1080;
|
long src_row_bytes = (config.discrete.sliceSizes[0] > 0) ? static_cast<long>(config.discrete.sliceSizes[0]) : (grain_size / out_height_);
|
||||||
if (config.discrete.sliceSizes[0] > 0) {
|
long src_height = (src_row_bytes > 0) ? (grain_size / src_row_bytes) : out_height_;
|
||||||
height = grain_size / config.discrete.sliceSizes[0];
|
long src_width = (src_row_bytes * 3) / 8;
|
||||||
}
|
|
||||||
long row_bytes = (config.discrete.sliceSizes[0] > 0) ? static_cast<long>(config.discrete.sliceSizes[0]) : (grain_size / height);
|
|
||||||
long width = (row_bytes * 3) / 8;
|
|
||||||
|
|
||||||
schedule_frame(payload, width, height, row_bytes);
|
schedule_frame(payload, src_width, src_height, src_row_bytes);
|
||||||
|
|
||||||
read_index_ = grain_info.index + 1;
|
read_index_ = source_index + 1;
|
||||||
grains_read_++;
|
grains_read_++;
|
||||||
|
|
||||||
if (grains_read_ == 1) {
|
if (grains_read_ == 1) {
|
||||||
spdlog::info("DeckLink-out: first grain output, index={}", grain_info.index);
|
spdlog::info("DeckLink-out: first grain output, source_index={}", source_index);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -256,7 +272,10 @@ nlohmann::json DeckLinkOutNode::status() const {
|
|||||||
{"read_index", read_index_},
|
{"read_index", read_index_},
|
||||||
{"playing", playing_.load()},
|
{"playing", playing_.load()},
|
||||||
{"has_reader", reader_.has_value()},
|
{"has_reader", reader_.has_value()},
|
||||||
{"grain_rate", {{"numerator", grain_rate_.numerator}, {"denominator", grain_rate_.denominator}}},
|
{"flow_rate", {{"numerator", flow_rate_.numerator}, {"denominator", flow_rate_.denominator}}},
|
||||||
|
{"output_rate", {{"numerator", output_rate_.numerator}, {"denominator", output_rate_.denominator}}},
|
||||||
|
{"width", out_width_},
|
||||||
|
{"height", out_height_},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -41,7 +41,8 @@ private:
|
|||||||
void schedule_frame(void* mxl_payload, long width, long height, long row_bytes);
|
void schedule_frame(void* mxl_payload, long width, long height, long row_bytes);
|
||||||
|
|
||||||
std::optional<mxlFlowReader> reader_;
|
std::optional<mxlFlowReader> reader_;
|
||||||
mxlRational grain_rate_{50, 1};
|
mxlRational flow_rate_{50, 1};
|
||||||
|
mxlRational output_rate_{50, 1};
|
||||||
uint64_t read_index_ = 0;
|
uint64_t read_index_ = 0;
|
||||||
uint64_t grains_read_ = 0;
|
uint64_t grains_read_ = 0;
|
||||||
|
|
||||||
@@ -55,6 +56,9 @@ private:
|
|||||||
BMDTimeScale time_scale_ = 50000;
|
BMDTimeScale time_scale_ = 50000;
|
||||||
|
|
||||||
std::atomic<bool> playing_{false};
|
std::atomic<bool> playing_{false};
|
||||||
|
bool is_interlaced_ = false;
|
||||||
|
long out_width_ = 1920;
|
||||||
|
long out_height_ = 1080;
|
||||||
|
|
||||||
class OutputCallback : public IDeckLinkVideoOutputCallback {
|
class OutputCallback : public IDeckLinkVideoOutputCallback {
|
||||||
public:
|
public:
|
||||||
|
|||||||
Reference in New Issue
Block a user