Add support for text cue heights.
Issue #832 Change-Id: Ifccbd6c6c46916d3d28ac4afaba01fc158c9c361
This commit is contained in:
parent
fe44b5e13c
commit
c4a11aaed4
|
@ -59,9 +59,14 @@ struct TextSettings {
|
||||||
/// The position offset of the cue. For horizontal cues, this is the
|
/// The position offset of the cue. For horizontal cues, this is the
|
||||||
/// horizontal offset. Percent units are relative to the window.
|
/// horizontal offset. Percent units are relative to the window.
|
||||||
base::Optional<TextNumber> position;
|
base::Optional<TextNumber> position;
|
||||||
/// The size of the space used to draw text. For horizontal cues, this is the
|
/// For horizontal cues, this is the width of the area to draw cues. For
|
||||||
/// width. Percent units are relative to the window.
|
/// vertical cues, this is the height. Percent units are relative to the
|
||||||
base::Optional<TextNumber> size;
|
/// window.
|
||||||
|
base::Optional<TextNumber> width;
|
||||||
|
/// For horizontal cues, this is the height of the area to draw cues. For
|
||||||
|
/// vertical cues, this is the width. Percent units are relative to the
|
||||||
|
/// window.
|
||||||
|
base::Optional<TextNumber> height;
|
||||||
|
|
||||||
/// The region to draw the cue in.
|
/// The region to draw the cue in.
|
||||||
std::string region;
|
std::string region;
|
||||||
|
|
|
@ -16,6 +16,8 @@ namespace ttml {
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
|
constexpr const char* kRegionIdPrefix = "_shaka_region_";
|
||||||
|
|
||||||
std::string ToTtmlTime(int64_t time, uint32_t timescale) {
|
std::string ToTtmlTime(int64_t time, uint32_t timescale) {
|
||||||
int64_t remaining = time * 1000 / timescale;
|
int64_t remaining = time * 1000 / timescale;
|
||||||
|
|
||||||
|
@ -122,15 +124,31 @@ bool TtmlGenerator::AddSampleToXml(const TextSample& sample,
|
||||||
RCHECK(p.SetStringAttribute("xml:id", sample.id()));
|
RCHECK(p.SetStringAttribute("xml:id", sample.id()));
|
||||||
|
|
||||||
const auto& settings = sample.settings();
|
const auto& settings = sample.settings();
|
||||||
if (!settings.region.empty())
|
if (settings.line || settings.position || settings.width || settings.height) {
|
||||||
RCHECK(p.SetStringAttribute("region", settings.region));
|
// TTML positioning needs to be from a region.
|
||||||
if (settings.line || settings.position) {
|
if (!settings.region.empty()) {
|
||||||
|
LOG(WARNING)
|
||||||
|
<< "Using both text regions and positioning isn't supported in TTML";
|
||||||
|
}
|
||||||
|
|
||||||
const auto origin = ToTtmlSize(
|
const auto origin = ToTtmlSize(
|
||||||
settings.position.value_or(TextNumber(0, TextUnitType::kPixels)),
|
settings.position.value_or(TextNumber(0, TextUnitType::kPixels)),
|
||||||
settings.line.value_or(TextNumber(0, TextUnitType::kPixels)));
|
settings.line.value_or(TextNumber(0, TextUnitType::kPixels)));
|
||||||
|
const auto extent = ToTtmlSize(
|
||||||
|
settings.width.value_or(TextNumber(100, TextUnitType::kPercent)),
|
||||||
|
settings.height.value_or(TextNumber(100, TextUnitType::kPercent)));
|
||||||
|
|
||||||
RCHECK(p.SetStringAttribute("tts:origin", origin));
|
const std::string id = kRegionIdPrefix + std::to_string(region_id_++);
|
||||||
|
xml::XmlNode region("region");
|
||||||
|
RCHECK(region.SetStringAttribute("xml:id", id));
|
||||||
|
RCHECK(region.SetStringAttribute("tts:origin", origin));
|
||||||
|
RCHECK(region.SetStringAttribute("tts:extent", extent));
|
||||||
|
RCHECK(p.SetStringAttribute("region", id));
|
||||||
|
RCHECK(body->AddChild(std::move(region)));
|
||||||
|
} else if (!settings.region.empty()) {
|
||||||
|
RCHECK(p.SetStringAttribute("region", settings.region));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (settings.writing_direction != WritingDirection::kHorizontal) {
|
if (settings.writing_direction != WritingDirection::kHorizontal) {
|
||||||
const char* dir =
|
const char* dir =
|
||||||
settings.writing_direction == WritingDirection::kVerticalGrowingLeft
|
settings.writing_direction == WritingDirection::kVerticalGrowingLeft
|
||||||
|
|
|
@ -48,6 +48,8 @@ class TtmlGenerator {
|
||||||
std::map<std::string, TextRegion> regions_;
|
std::map<std::string, TextRegion> regions_;
|
||||||
std::string language_;
|
std::string language_;
|
||||||
uint32_t time_scale_;
|
uint32_t time_scale_;
|
||||||
|
// This is modified in "const" methods to create unique IDs.
|
||||||
|
mutable uint32_t region_id_ = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace ttml
|
} // namespace ttml
|
||||||
|
|
|
@ -190,8 +190,10 @@ TEST_F(TtmlMuxerTest, HandlesPosition) {
|
||||||
" <head/>\n"
|
" <head/>\n"
|
||||||
" <body>\n"
|
" <body>\n"
|
||||||
" <div>\n"
|
" <div>\n"
|
||||||
|
" <region xml:id=\"_shaka_region_0\" tts:origin=\"30% 4em\" "
|
||||||
|
"tts:extent=\"100px 1em\"/>\n"
|
||||||
" <p xml:space=\"preserve\" begin=\"00:00:05.00\" "
|
" <p xml:space=\"preserve\" begin=\"00:00:05.00\" "
|
||||||
"end=\"00:00:06.00\" tts:origin=\"30% 4em\">bar</p>\n"
|
"end=\"00:00:06.00\" region=\"_shaka_region_0\">bar</p>\n"
|
||||||
" </div>\n"
|
" </div>\n"
|
||||||
" </body>\n"
|
" </body>\n"
|
||||||
"</tt>\n";
|
"</tt>\n";
|
||||||
|
@ -199,6 +201,8 @@ TEST_F(TtmlMuxerTest, HandlesPosition) {
|
||||||
TestProperties properties;
|
TestProperties properties;
|
||||||
properties.settings.position.emplace(30, TextUnitType::kPercent);
|
properties.settings.position.emplace(30, TextUnitType::kPercent);
|
||||||
properties.settings.line.emplace(4, TextUnitType::kLines);
|
properties.settings.line.emplace(4, TextUnitType::kLines);
|
||||||
|
properties.settings.width.emplace(100, TextUnitType::kPixels);
|
||||||
|
properties.settings.height.emplace(1, TextUnitType::kLines);
|
||||||
properties.body.body = "bar";
|
properties.body.body = "bar";
|
||||||
|
|
||||||
ParseSingleCue(kExpectedOutput, properties);
|
ParseSingleCue(kExpectedOutput, properties);
|
||||||
|
|
|
@ -169,7 +169,7 @@ void ParseSettings(const std::string& id,
|
||||||
} else if (id == "size") {
|
} else if (id == "size") {
|
||||||
float temp;
|
float temp;
|
||||||
if (ParsePercent(value, &temp)) {
|
if (ParsePercent(value, &temp)) {
|
||||||
settings->size.emplace(temp, TextUnitType::kPercent);
|
settings->width.emplace(temp, TextUnitType::kPercent);
|
||||||
} else {
|
} else {
|
||||||
LOG(WARNING) << "Invalid WebVTT size: " << value;
|
LOG(WARNING) << "Invalid WebVTT size: " << value;
|
||||||
}
|
}
|
||||||
|
|
|
@ -201,7 +201,8 @@ TEST_F(WebVttParserTest, ParseOneCue) {
|
||||||
const auto& settings = samples_[0]->settings();
|
const auto& settings = samples_[0]->settings();
|
||||||
EXPECT_FALSE(settings.line);
|
EXPECT_FALSE(settings.line);
|
||||||
EXPECT_FALSE(settings.position);
|
EXPECT_FALSE(settings.position);
|
||||||
EXPECT_FALSE(settings.size);
|
EXPECT_FALSE(settings.width);
|
||||||
|
EXPECT_FALSE(settings.height);
|
||||||
EXPECT_EQ(settings.region, "");
|
EXPECT_EQ(settings.region, "");
|
||||||
EXPECT_EQ(settings.writing_direction, WritingDirection::kHorizontal);
|
EXPECT_EQ(settings.writing_direction, WritingDirection::kHorizontal);
|
||||||
EXPECT_EQ(settings.text_alignment, TextAlignment::kCenter);
|
EXPECT_EQ(settings.text_alignment, TextAlignment::kCenter);
|
||||||
|
@ -320,9 +321,9 @@ TEST_F(WebVttParserTest, ParseSettingSize) {
|
||||||
|
|
||||||
ASSERT_EQ(streams_.size(), 1u);
|
ASSERT_EQ(streams_.size(), 1u);
|
||||||
ASSERT_EQ(samples_.size(), 1u);
|
ASSERT_EQ(samples_.size(), 1u);
|
||||||
ASSERT_TRUE(samples_[0]->settings().size);
|
ASSERT_TRUE(samples_[0]->settings().width);
|
||||||
EXPECT_EQ(samples_[0]->settings().size->type, TextUnitType::kPercent);
|
EXPECT_EQ(samples_[0]->settings().width->type, TextUnitType::kPercent);
|
||||||
EXPECT_EQ(samples_[0]->settings().size->value, 50.0f);
|
EXPECT_EQ(samples_[0]->settings().width->value, 50.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(WebVttParserTest, ParseOneCueWithManySettings) {
|
TEST_F(WebVttParserTest, ParseOneCueWithManySettings) {
|
||||||
|
@ -343,7 +344,7 @@ TEST_F(WebVttParserTest, ParseOneCueWithManySettings) {
|
||||||
EXPECT_EQ(samples_[0]->settings().writing_direction,
|
EXPECT_EQ(samples_[0]->settings().writing_direction,
|
||||||
WritingDirection::kVerticalGrowingRight);
|
WritingDirection::kVerticalGrowingRight);
|
||||||
EXPECT_EQ(samples_[0]->settings().text_alignment, TextAlignment::kRight);
|
EXPECT_EQ(samples_[0]->settings().text_alignment, TextAlignment::kRight);
|
||||||
EXPECT_FALSE(samples_[0]->settings().size);
|
EXPECT_FALSE(samples_[0]->settings().width);
|
||||||
ASSERT_TRUE(samples_[0]->settings().position);
|
ASSERT_TRUE(samples_[0]->settings().position);
|
||||||
EXPECT_EQ(samples_[0]->settings().position->type, TextUnitType::kPercent);
|
EXPECT_EQ(samples_[0]->settings().position->type, TextUnitType::kPercent);
|
||||||
EXPECT_EQ(samples_[0]->settings().position->value, 20.0f);
|
EXPECT_EQ(samples_[0]->settings().position->value, 20.0f);
|
||||||
|
|
|
@ -215,15 +215,18 @@ std::string WebVttSettingsToString(const TextSettings& settings) {
|
||||||
LOG(WARNING) << "WebVTT only supports percent position settings";
|
LOG(WARNING) << "WebVTT only supports percent position settings";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (settings.size) {
|
if (settings.width) {
|
||||||
if (settings.size->type == TextUnitType::kPercent) {
|
if (settings.width->type == TextUnitType::kPercent) {
|
||||||
ret += " size:";
|
ret += " size:";
|
||||||
ret += base::DoubleToString(settings.size->value);
|
ret += base::DoubleToString(settings.width->value);
|
||||||
ret += "%";
|
ret += "%";
|
||||||
} else {
|
} else {
|
||||||
LOG(WARNING) << "WebVTT only supports percent size settings";
|
LOG(WARNING) << "WebVTT only supports percent width settings";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (settings.height) {
|
||||||
|
LOG(WARNING) << "WebVTT doesn't support cue heights";
|
||||||
|
}
|
||||||
if (settings.writing_direction != WritingDirection::kHorizontal) {
|
if (settings.writing_direction != WritingDirection::kHorizontal) {
|
||||||
ret += " direction:";
|
ret += " direction:";
|
||||||
if (settings.writing_direction == WritingDirection::kVerticalGrowingLeft) {
|
if (settings.writing_direction == WritingDirection::kVerticalGrowingLeft) {
|
||||||
|
|
|
@ -151,7 +151,7 @@ TEST(WebVttUtilsTest, SettingsToString) {
|
||||||
settings.region = "foo";
|
settings.region = "foo";
|
||||||
settings.line = TextNumber(27, TextUnitType::kPercent);
|
settings.line = TextNumber(27, TextUnitType::kPercent);
|
||||||
settings.position = TextNumber(42, TextUnitType::kPercent);
|
settings.position = TextNumber(42, TextUnitType::kPercent);
|
||||||
settings.size = TextNumber(54, TextUnitType::kPercent);
|
settings.width = TextNumber(54, TextUnitType::kPercent);
|
||||||
settings.writing_direction = WritingDirection::kVerticalGrowingLeft;
|
settings.writing_direction = WritingDirection::kVerticalGrowingLeft;
|
||||||
settings.text_alignment = TextAlignment::kEnd;
|
settings.text_alignment = TextAlignment::kEnd;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue