summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorCarl Hetherington <cth@carlh.net>2021-08-10 02:10:49 +0200
committerCarl Hetherington <cth@carlh.net>2021-08-11 23:35:46 +0200
commitc259338463b394e61504ff0e232b0ba102c1eda2 (patch)
treec2ef8349a741f579e6aa57fccdb875354576ae9d /src
parent4f9802e8a7225fc1b3db105b45e3688a64af3588 (diff)
Add verify check for empty <Text> nodes in timed text.
Diffstat (limited to 'src')
-rw-r--r--src/verify.cc33
-rw-r--r--src/verify.h2
2 files changed, 31 insertions, 4 deletions
diff --git a/src/verify.cc b/src/verify.cc
index c8307aa5..e7a55d4c 100644
--- a/src/verify.cc
+++ b/src/verify.cc
@@ -778,6 +778,7 @@ verify_closed_caption_asset (
}
+/** Check the timing of the individual subtitles and make sure there are no empty <Text> nodes */
static
void
verify_text_details (
@@ -795,11 +796,12 @@ verify_text_details (
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;
std::function<void (cxml::ConstNodePtr, optional<int>, optional<Time>, int, bool)> parse;
- parse = [&parse, &last_out, &too_short, &too_close, &too_early, &reel_offset](cxml::ConstNodePtr node, optional<int> tcr, optional<Time> start_time, int er, bool first_reel) {
+ parse = [&parse, &last_out, &too_short, &too_close, &too_early, &empty_text, &reel_offset](cxml::ConstNodePtr node, optional<int> tcr, optional<Time> start_time, int er, bool first_reel) {
if (node->name() == "Subtitle") {
Time in (node->string_attribute("TimeIn"), tcr);
if (start_time) {
@@ -824,11 +826,26 @@ verify_text_details (
}
}
last_out = reel_offset + out.as_editable_units_floor(er);
- } else {
- for (auto i: node->node_children()) {
- parse(i, tcr, start_time, er, first_reel);
+ } else if (node->name() == "Text") {
+ std::function<bool (cxml::ConstNodePtr)> node_has_content = [&](cxml::ConstNodePtr node) {
+ if (!node->content().empty()) {
+ return true;
+ }
+ for (auto i: node->node_children()) {
+ if (node_has_content(i)) {
+ return true;
+ }
+ }
+ return false;
+ };
+ if (!node_has_content(node)) {
+ empty_text = true;
}
}
+
+ for (auto i: node->node_children()) {
+ parse(i, tcr, start_time, er, first_reel);
+ }
};
for (auto i = 0U; i < reels.size(); ++i) {
@@ -896,6 +913,12 @@ verify_text_details (
VerificationNote::Type::ERROR, VerificationNote::Code::SUBTITLE_OVERLAPS_REEL_BOUNDARY
});
}
+
+ if (empty_text) {
+ notes.push_back ({
+ VerificationNote::Type::WARNING, VerificationNote::Code::EMPTY_TEXT
+ });
+ }
}
@@ -1626,6 +1649,8 @@ dcp::note_to_string (VerificationNote note)
}
case VerificationNote::Code::MISSED_CHECK_OF_ENCRYPTED:
return "Some aspect of this DCP could not be checked because it is encrypted.";
+ case VerificationNote::Code::EMPTY_TEXT:
+ return "There is an empty <Text> node in a subtitle or closed caption.";
}
return "";
diff --git a/src/verify.h b/src/verify.h
index c0491422..045c12c2 100644
--- a/src/verify.h
+++ b/src/verify.h
@@ -381,6 +381,8 @@ public:
MISMATCHED_TIMED_TEXT_DURATION,
/** Something could not be verified because content is encrypted and no key is available */
MISSED_CHECK_OF_ENCRYPTED,
+ /** Some timed-text XML has an empty <Text> node */
+ EMPTY_TEXT
};
VerificationNote (Type type, Code code)