summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorCarl Hetherington <cth@carlh.net>2026-03-26 23:43:00 +0100
committerCarl Hetherington <cth@carlh.net>2026-03-26 23:43:00 +0100
commit1c42e6a464ad25a2230540f639fe513d2761d27d (patch)
treeb4c8b1c32111a4ddfbeb6429c5eada703edd3271 /src
parent01bf601526da5d6eec21e8a54dbd82f646bfedb9 (diff)
Put asset/reel index context into all text reels.
Diffstat (limited to 'src')
-rw-r--r--src/verify.cc103
1 files changed, 57 insertions, 46 deletions
diff --git a/src/verify.cc b/src/verify.cc
index 8dcd6410..f071f53e 100644
--- a/src/verify.cc
+++ b/src/verify.cc
@@ -878,6 +878,7 @@ verify_text_details (
Context& context,
vector<shared_ptr<Reel>> reels,
int edit_rate,
+ std::function<std::string (shared_ptr<Reel>)> asset_id,
std::function<bool (shared_ptr<Reel>)> check,
std::function<optional<string> (shared_ptr<Reel>)> xml,
std::function<int64_t (shared_ptr<Reel>)> duration,
@@ -886,19 +887,22 @@ verify_text_details (
{
/* end of last subtitle (in editable units) */
optional<int64_t> last_out;
- auto too_short = false;
- auto too_short_bv21 = false;
- auto too_close = false;
- auto too_early = false;
- auto reel_overlap = false;
- auto empty_text = false;
/* current reel start time (in editable units) */
int64_t reel_offset = 0;
- optional<string> missing_load_font_id;
- std::function<void (cxml::ConstNodePtr, optional<int>, optional<Time>, int, bool, bool&, vector<string>&)> parse;
+ struct Errors {
+ bool too_short = false;
+ bool too_short_bv21 = false;
+ bool too_close = false;
+ bool too_early = false;
+ bool empty_text = false;
+ optional<string> missing_load_font_id;
+ };
+
+ std::function<void (Errors&, cxml::ConstNodePtr, optional<int>, optional<Time>, int, bool, bool&, vector<string>&)> parse;
- parse = [&parse, &last_out, &too_short, &too_short_bv21, &too_close, &too_early, &empty_text, &reel_offset, &missing_load_font_id](
+ parse = [&parse, &last_out, &reel_offset](
+ Errors& errors,
cxml::ConstNodePtr node,
optional<int> tcr,
optional<Time> start_time,
@@ -917,19 +921,19 @@ verify_text_details (
out -= *start_time;
}
if (first_reel && tcr && in < Time(0, 0, 4, 0, *tcr)) {
- too_early = true;
+ errors.too_early = true;
}
auto length = out - in;
if (length.as_editable_units_ceil(er) <= 0) {
- too_short = true;
+ errors.too_short = true;
} else if (length.as_editable_units_ceil(er) < 15) {
- too_short_bv21 = true;
+ errors.too_short_bv21 = true;
}
if (last_out) {
/* XXX: this feels dubious - is it really what Bv2.1 means? */
auto distance = reel_offset + in.as_editable_units_ceil(er) - *last_out;
if (distance >= 0 && distance < 2) {
- too_close = true;
+ errors.too_close = true;
}
}
last_out = reel_offset + out.as_editable_units_floor(er);
@@ -946,7 +950,7 @@ verify_text_details (
return false;
};
if (!node_has_content(node)) {
- empty_text = true;
+ errors.empty_text = true;
}
has_text = true;
} else if (node->name() == "LoadFont") {
@@ -958,18 +962,23 @@ verify_text_details (
} else if (node->name() == "Font") {
if (auto const font_id = node->optional_string_attribute("Id")) {
if (std::find_if(font_ids.begin(), font_ids.end(), [font_id](string const& id) { return id == font_id; }) == font_ids.end()) {
- missing_load_font_id = font_id;
+ errors.missing_load_font_id = font_id;
}
}
}
for (auto i: node->node_children()) {
- parse(i, tcr, start_time, er, first_reel, has_text, font_ids);
+ parse(errors, i, tcr, start_time, er, first_reel, has_text, font_ids);
}
};
for (auto i = 0U; i < reels.size(); ++i) {
+
+ bool reel_overlap = false;
+ Errors errors;
+
context.reel_index = i;
- dcp::ScopeGuard sg = [&context]() { context.reel_index = boost::none; };
+ context.asset_id = asset_id(reels[i]);
+ dcp::ScopeGuard sg = [&context]() { context.reel_index = boost::none; context.asset_id = boost::none; };
if (!check(reels[i])) {
continue;
@@ -1004,7 +1013,7 @@ verify_text_details (
}
bool has_text = false;
vector<string> font_ids;
- parse(doc, tcr, start_time, edit_rate, i == 0, has_text, font_ids);
+ parse(errors, doc, tcr, start_time, edit_rate, i == 0, has_text, font_ids);
auto end = reel_offset + duration(reels[i]);
if (last_out && *last_out > end) {
reel_overlap = true;
@@ -1014,38 +1023,38 @@ verify_text_details (
if (context.dcp->standard() && *context.dcp->standard() == dcp::Standard::SMPTE && has_text && font_ids.empty()) {
context.add_note(dcp::VerificationNote(VerificationNote::Code::MISSING_LOAD_FONT).set_asset_id(id(reels[i])));
}
- }
- if (last_out && *last_out > reel_offset) {
- reel_overlap = true;
- }
+ if (last_out && *last_out > reel_offset) {
+ reel_overlap = true;
+ }
- if (too_early) {
- context.add_note(VerificationNote::Code::INVALID_SUBTITLE_FIRST_TEXT_TIME);
- }
+ if (reel_overlap) {
+ context.add_note(VerificationNote::Code::SUBTITLE_OVERLAPS_REEL_BOUNDARY);
+ }
- if (too_short) {
- context.add_note(VerificationNote::Code::INVALID_SUBTITLE_DURATION);
- }
+ if (errors.too_early) {
+ context.add_note(VerificationNote::Code::INVALID_SUBTITLE_FIRST_TEXT_TIME);
+ }
- if (too_short_bv21) {
- context.add_note(VerificationNote::Code::INVALID_SUBTITLE_DURATION_BV21);
- }
+ if (errors.too_short) {
+ context.add_note(VerificationNote::Code::INVALID_SUBTITLE_DURATION);
+ }
- if (too_close) {
- context.add_note(VerificationNote::Code::INVALID_SUBTITLE_SPACING);
- }
+ if (errors.too_short_bv21) {
+ context.add_note(VerificationNote::Code::INVALID_SUBTITLE_DURATION_BV21);
+ }
- if (reel_overlap) {
- context.add_note(VerificationNote::Code::SUBTITLE_OVERLAPS_REEL_BOUNDARY);
- }
+ if (errors.too_close) {
+ context.add_note(VerificationNote::Code::INVALID_SUBTITLE_SPACING);
+ }
- if (empty_text) {
- context.add_note(VerificationNote::Code::EMPTY_TEXT);
- }
+ if (errors.empty_text) {
+ context.add_note(VerificationNote::Code::EMPTY_TEXT);
+ }
- if (missing_load_font_id) {
- context.add_note(dcp::VerificationNote(VerificationNote::Code::MISSING_LOAD_FONT_FOR_FONT).set_load_font_id(*missing_load_font_id));
+ if (errors.missing_load_font_id) {
+ context.add_note(dcp::VerificationNote(VerificationNote::Code::MISSING_LOAD_FONT_FOR_FONT).set_load_font_id(*errors.missing_load_font_id));
+ }
}
}
@@ -1268,10 +1277,11 @@ verify_text_details(Context& context, vector<shared_ptr<Reel>> reels)
}
if (reels[0]->main_subtitle() && reels[0]->main_subtitle()->asset_ref().resolved()) {
- context.asset_id = reels[0]->main_subtitle()->asset()->id();
- dcp::ScopeGuard sg = [&context]() { context.asset_id = boost::none; };
verify_text_details(context, reels, reels[0]->main_subtitle()->edit_rate().numerator,
[](shared_ptr<Reel> reel) {
+ return reel->main_subtitle() ? reel->main_subtitle()->id() : string{};
+ },
+ [](shared_ptr<Reel> reel) {
return static_cast<bool>(reel->main_subtitle());
},
[](shared_ptr<Reel> reel) {
@@ -1287,10 +1297,11 @@ verify_text_details(Context& context, vector<shared_ptr<Reel>> reels)
}
for (auto i = 0U; i < reels[0]->closed_captions().size(); ++i) {
- context.asset_id = reels[0]->closed_captions()[i]->asset()->id();
- dcp::ScopeGuard sg = [&context]() { context.asset_id = boost::none; };
verify_text_details(context, reels, reels[0]->closed_captions()[i]->edit_rate().numerator,
[i](shared_ptr<Reel> reel) {
+ return reel->closed_captions()[i]->id();
+ },
+ [i](shared_ptr<Reel> reel) {
return i < reel->closed_captions().size();
},
[i](shared_ptr<Reel> reel) {