7 #include "packager/media/chunking/text_chunker.h"
9 #include "packager/status_macros.h"
14 const size_t kStreamIndex = 0;
17 TextChunker::TextChunker(
double segment_duration_in_seconds)
18 : segment_duration_in_seconds_(segment_duration_in_seconds){};
20 Status TextChunker::Process(std::unique_ptr<StreamData> data) {
21 switch (data->stream_data_type) {
22 case StreamDataType::kStreamInfo:
23 return OnStreamInfo(std::move(data->stream_info));
24 case StreamDataType::kTextSample:
25 return OnTextSample(data->text_sample);
26 case StreamDataType::kCueEvent:
27 return OnCueEvent(data->cue_event);
29 return Status(error::INTERNAL_ERROR,
30 "Invalid stream data type for this handler");
34 Status TextChunker::OnFlushRequest(
size_t input_stream_index) {
37 while (samples_in_current_segment_.size()) {
38 RETURN_IF_ERROR(DispatchSegment(segment_duration_));
41 return FlushAllDownstreams();
44 Status TextChunker::OnStreamInfo(std::shared_ptr<const StreamInfo> info) {
45 time_scale_ = info->time_scale();
46 segment_duration_ = ScaleTime(segment_duration_in_seconds_);
48 return DispatchStreamInfo(kStreamIndex, std::move(info));
51 Status TextChunker::OnCueEvent(std::shared_ptr<const CueEvent> event) {
60 const int64_t event_time = ScaleTime(event->time_in_seconds);
63 while (segment_start_ + segment_duration_ < event_time) {
64 RETURN_IF_ERROR(DispatchSegment(segment_duration_));
67 const int64_t shorten_duration = event_time - segment_start_;
69 RETURN_IF_ERROR(DispatchSegment(shorten_duration));
70 return DispatchCueEvent(kStreamIndex, std::move(event));
73 Status TextChunker::OnTextSample(std::shared_ptr<const TextSample> sample) {
75 const int64_t sample_start = sample->start_time();
79 if (segment_start_ < 0) {
83 segment_start_ = (sample_start / segment_duration_) * segment_duration_;
88 while (sample_start >= segment_start_ + segment_duration_) {
90 RETURN_IF_ERROR(DispatchSegment(segment_duration_));
93 samples_in_current_segment_.push_back(std::move(sample));
98 Status TextChunker::DispatchSegment(int64_t duration) {
99 DCHECK_GT(duration, 0) <<
"Segment duration should always be positive";
102 for (
const auto& sample : samples_in_current_segment_) {
103 RETURN_IF_ERROR(DispatchTextSample(kStreamIndex, sample));
107 std::shared_ptr<SegmentInfo> info = std::make_shared<SegmentInfo>();
108 info->start_timestamp = segment_start_;
109 info->duration = duration;
110 RETURN_IF_ERROR(DispatchSegmentInfo(kStreamIndex, std::move(info)));
113 const int64_t new_segment_start = segment_start_ + duration;
114 segment_start_ = new_segment_start;
117 samples_in_current_segment_.remove_if(
118 [new_segment_start](
const std::shared_ptr<const TextSample>& sample) {
121 DCHECK_LT(sample->start_time(), new_segment_start);
122 return sample->EndTime() <= new_segment_start;
128 int64_t TextChunker::ScaleTime(
double seconds)
const {
129 DCHECK_GT(time_scale_, 0) <<
"Need positive time scale to scale time.";
130 return static_cast<int64_t
>(seconds * time_scale_);
All the methods that are virtual are virtual for mocking.