Shaka Packager SDK
text_muxer.cc
1 // Copyright 2020 Google LLC. All rights reserved.
2 //
3 // Use of this source code is governed by a BSD-style
4 // license that can be found in the LICENSE file or at
5 // https://developers.google.com/open-source/licenses/bsd
6 
7 #include <packager/media/base/text_muxer.h>
8 
9 #include <absl/log/check.h>
10 
11 #include <packager/macros/compiler.h>
12 #include <packager/macros/status.h>
13 #include <packager/media/base/muxer_util.h>
14 
15 namespace shaka {
16 namespace media {
17 
18 TextMuxer::TextMuxer(const MuxerOptions& options) : Muxer(options) {}
19 TextMuxer::~TextMuxer() {}
20 
21 Status TextMuxer::InitializeMuxer() {
22  if (streams().size() != 1 || streams()[0]->stream_type() != kStreamText) {
23  return Status(error::MUXER_FAILURE,
24  "Incorrect streams given to WebVTT muxer");
25  }
26 
27  auto copy = streams()[0]->Clone();
28  RETURN_IF_ERROR(InitializeStream(static_cast<TextStreamInfo*>(copy.get())));
29 
30  muxer_listener()->OnMediaStart(options(), *copy, copy->time_scale(),
31  MuxerListener::kContainerText);
32 
33  last_cue_ms_ = 0;
34  return Status::OK;
35 }
36 
37 Status TextMuxer::Finalize() {
38  const float duration_ms = static_cast<float>(total_duration_ms_);
39  float duration_seconds = duration_ms / 1000;
40 
41  // If we haven't seen any segments, this is a single-file. In this case,
42  // flush the single segment.
43  MuxerListener::MediaRanges ranges;
44  if (duration_seconds == 0 && last_cue_ms_ != 0) {
45  DCHECK(options().segment_template.empty());
46  duration_seconds = static_cast<float>(last_cue_ms_) / 1000;
47 
48  uint64_t size;
49  RETURN_IF_ERROR(WriteToFile(options().output_file_name, &size));
50  // Insert a dummy value so the HLS generator will generate a segment list.
51  ranges.subsegment_ranges.emplace_back();
52 
53  // The segment number does not matter for single segment output.
54  const uint32_t kArbitrarySegmentNumber = 0;
55 
56  muxer_listener()->OnNewSegment(
57  options().output_file_name, 0,
58  duration_seconds * streams()[0]->time_scale(), size,
59  kArbitrarySegmentNumber);
60  }
61 
62  muxer_listener()->OnMediaEnd(ranges, duration_seconds);
63 
64  return Status::OK;
65 }
66 
67 Status TextMuxer::AddTextSample(size_t stream_id, const TextSample& sample) {
68  UNUSED(stream_id);
69 
70  // Ignore sync samples.
71  if (sample.body().is_empty()) {
72  return Status::OK;
73  }
74 
75  RETURN_IF_ERROR(AddTextSampleInternal(sample));
76 
77  last_cue_ms_ = sample.EndTime();
78  return Status::OK;
79 }
80 
81 Status TextMuxer::FinalizeSegment(size_t stream_id,
82  const SegmentInfo& segment_info) {
83  UNUSED(stream_id);
84 
85  total_duration_ms_ += segment_info.duration;
86 
87  const std::string& segment_template = options().segment_template;
88  DCHECK(!segment_template.empty());
89 
90  const int64_t start = segment_info.start_timestamp;
91  const int64_t duration = segment_info.duration;
92  const uint32_t segment_number = segment_info.segment_number;
93 
94  const uint32_t bandwidth = options().bandwidth;
95 
96  const std::string filename =
97  GetSegmentName(segment_template, start, segment_number, bandwidth);
98  uint64_t size;
99  RETURN_IF_ERROR(WriteToFile(filename, &size));
100 
101  muxer_listener()->OnNewSegment(filename, start, duration, size,
102  segment_number);
103  return Status::OK;
104 }
105 
106 } // namespace media
107 } // namespace shaka
All the methods that are virtual are virtual for mocking.
Definition: crypto_flags.cc:66