Skip to content

Commit

Permalink
fix: add ability to set timed text decode time.
Browse files Browse the repository at this point in the history
  • Loading branch information
lee.fordyce committed Feb 26, 2024
1 parent c786a86 commit aac18be
Show file tree
Hide file tree
Showing 7 changed files with 42 additions and 9 deletions.
4 changes: 4 additions & 0 deletions include/packager/chunking_params.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,10 @@ struct ChunkingParams {
/// and mdat atom. Each chunk is uploaded immediately upon creation,
/// decoupling latency from segment duration.
bool low_latency_dash_mode = false;

/// Used to set the decode time for only for timed text packing, specifically
/// when packaging from VTT to VTT in MP4 or TTML in MP4.
int64_t timed_text_decode_time = -1;
};

} // namespace shaka
Expand Down
7 changes: 7 additions & 0 deletions include/packager/live_packager.h
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,13 @@ struct LiveConfig {
/// audio) timestamps to compensate for possible negative timestamps in the
/// input.
int32_t m2ts_offset_ms = 0;

/// Used for timed text packaging to set the fragment decode time when the
/// output format is either VTT in MP4 or TTML in MP4.
int64_t timed_text_decode_time = -1;

/// Timed Text time scale used for packaging VTT in MP4 or TTML in MP4.
uint32_t timed_text_timescale = 10000000;
};

class LivePackager {
Expand Down
2 changes: 2 additions & 0 deletions packager/live_packager.cc
Original file line number Diff line number Diff line change
Expand Up @@ -428,6 +428,8 @@ Status LivePackager::PackageTimedText(const Segment& in,
shaka::PackagingParams packaging_params;
packaging_params.chunking_params.segment_duration_in_seconds =
DEFAULT_SEGMENT_DURATION;
packaging_params.chunking_params.timed_text_decode_time =
config_.timed_text_decode_time;
packaging_params.mp4_output_params.sequence_number = config_.segment_number;

packaging_params.mp4_output_params.include_pssh_in_stream = false;
Expand Down
25 changes: 21 additions & 4 deletions packager/live_packager_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -294,7 +294,8 @@ void CheckVideoInitSegment(const FullSegmentBuffer& buffer,

void CheckSegment(const LiveConfig& config,
const FullSegmentBuffer& buffer,
const uint32_t expected_timescale) {
const uint32_t expected_timescale,
const bool check_decode_time) {
bool err(true);
size_t bytes_to_read(buffer.SegmentSize());
const uint8_t* data(buffer.SegmentData());
Expand Down Expand Up @@ -332,6 +333,10 @@ void CheckSegment(const LiveConfig& config,

media::mp4::MovieFragment expected;
expected.header.sequence_number = config.segment_number;
expected.tracks.resize(1);
if (check_decode_time)
expected.tracks[0].decode_time.decode_time =
config.timed_text_decode_time;

MovieFragmentBoxChecker checker(expected);
checker.Check(reader.get());
Expand Down Expand Up @@ -802,7 +807,7 @@ TEST_F(LivePackagerBaseTest, CustomMoofSequenceNumber) {
ASSERT_EQ(Status::OK, packager.Package(init_seg, media_seg, out));
ASSERT_GT(out.SegmentSize(), 0);

CheckSegment(live_config, out, 10000000);
CheckSegment(live_config, out, 10000000, false);
}
}

Expand Down Expand Up @@ -950,6 +955,7 @@ struct TimedTextTestCase {
LiveConfig::TrackType track_type;
LiveConfig::OutputFormat output_format;
Status expected_status;
int64_t start_decode_time;
};

class TimedTextParameterizedTest
Expand All @@ -975,15 +981,21 @@ TEST_P(TimedTextParameterizedTest, VerifyTimedText) {
live_config.protection_scheme = LiveConfig::EncryptionScheme::NONE;
live_config.format = GetParam().output_format;
live_config.track_type = GetParam().track_type;
live_config.segment_number = i + 1;
if (live_config.format == LiveConfig::OutputFormat::VTTMP4 ||
live_config.format == LiveConfig::OutputFormat::TTMLMP4) {
live_config.segment_number = i + 1;
live_config.timed_text_decode_time =
GetParam().start_decode_time + (i * 5000);
}

SetupLivePackagerConfig(live_config);
ASSERT_EQ(GetParam().expected_status,
live_packager_->PackageTimedText(media_seg, out));
if (GetParam().expected_status == Status::OK) {
ASSERT_GT(out.SegmentSize(), 0);
if (live_config.format == LiveConfig::OutputFormat::VTTMP4 ||
live_config.format == LiveConfig::OutputFormat::TTMLMP4) {
CheckSegment(live_config, out, 1000);
CheckSegment(live_config, out, 1000, true);
}
}
}
Expand All @@ -999,33 +1011,38 @@ INSTANTIATE_TEST_CASE_P(
LiveConfig::TrackType::TEXT,
LiveConfig::OutputFormat::VTTMP4,
Status::OK,
16000,
},
// VTT in text --> TTML in Text
TimedTextTestCase{
"timed_text_vtt/%04d.vtt",
LiveConfig::TrackType::TEXT,
LiveConfig::OutputFormat::TTML,
Status::OK,
0,
},
// VTT in text --> TTML in MP4
TimedTextTestCase{
"timed_text_vtt/%04d.vtt",
LiveConfig::TrackType::TEXT,
LiveConfig::OutputFormat::TTMLMP4,
Status::OK,
16000,
},
// Invalid track type of audio
TimedTextTestCase{
"timed_text_vtt/%04d.vtt",
LiveConfig::TrackType::AUDIO,
LiveConfig::OutputFormat::TTMLMP4,
Status(error::INVALID_ARGUMENT, "Stream not available"),
0,
},
// Invalid track type of video
TimedTextTestCase{
"timed_text_vtt/%04d.vtt",
LiveConfig::TrackType::VIDEO,
LiveConfig::OutputFormat::TTMLMP4,
Status(error::INVALID_ARGUMENT, "Stream not available"),
0,
}));
} // namespace shaka
6 changes: 4 additions & 2 deletions packager/media/chunking/text_chunker.cc
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,10 @@ namespace {
const size_t kStreamIndex = 0;
} // namespace

TextChunker::TextChunker(double segment_duration_in_seconds)
: segment_duration_in_seconds_(segment_duration_in_seconds){};
TextChunker::TextChunker(double segment_duration_in_seconds,
int64_t timed_text_decode_time)
: segment_duration_in_seconds_(segment_duration_in_seconds),
segment_start_(timed_text_decode_time){};

Status TextChunker::Process(std::unique_ptr<StreamData> data) {
switch (data->stream_data_type) {
Expand Down
3 changes: 2 additions & 1 deletion packager/media/chunking/text_chunker.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@ namespace media {
// is when a cue event is seen.
class TextChunker : public MediaHandler {
public:
explicit TextChunker(double segment_duration_in_seconds);
explicit TextChunker(double segment_duration_in_seconds,
int64_t timed_text_decode_time = -1);

private:
TextChunker(const TextChunker&) = delete;
Expand Down
4 changes: 2 additions & 2 deletions packager/packager.cc
Original file line number Diff line number Diff line change
Expand Up @@ -527,8 +527,8 @@ std::unique_ptr<MediaHandler> CreateTextChunker(
const ChunkingParams& chunking_params) {
const float segment_length_in_seconds =
chunking_params.segment_duration_in_seconds;
return std::unique_ptr<MediaHandler>(
new TextChunker(segment_length_in_seconds));
return std::unique_ptr<MediaHandler>(new TextChunker(
segment_length_in_seconds, chunking_params.timed_text_decode_time));
}

Status CreateTtmlJobs(
Expand Down

0 comments on commit aac18be

Please sign in to comment.