Shaka Packager SDK
single_segment_segmenter.cc
1 // Copyright 2015 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/formats/webm/single_segment_segmenter.h>
8 
9 #include <absl/log/check.h>
10 #include <mkvmuxer/mkvmuxer.h>
11 
12 #include <packager/media/base/muxer_options.h>
13 #include <packager/media/event/muxer_listener.h>
14 
15 namespace shaka {
16 namespace media {
17 namespace webm {
18 
19 SingleSegmentSegmenter::SingleSegmentSegmenter(const MuxerOptions& options)
20  : Segmenter(options), init_end_(0), index_start_(0) {}
21 
22 SingleSegmentSegmenter::~SingleSegmentSegmenter() {}
23 
24 Status SingleSegmentSegmenter::FinalizeSegment(int64_t start_timestamp,
25  int64_t duration_timestamp,
26  bool is_subsegment,
27  int64_t segment_number) {
28  Status status = Segmenter::FinalizeSegment(
29  start_timestamp, duration_timestamp, is_subsegment, segment_number);
30  if (!status.ok())
31  return status;
32  // No-op for subsegment in single segment mode.
33  if (is_subsegment)
34  return Status::OK;
35  CHECK(cluster());
36  if (!cluster()->Finalize())
37  return Status(error::FILE_FAILURE, "Error finalizing cluster.");
38  if (muxer_listener()) {
39  const uint64_t size = cluster()->Size();
40  muxer_listener()->OnNewSegment(options().output_file_name, start_timestamp,
41  duration_timestamp, size, segment_number);
42  }
43  return Status::OK;
44 }
45 
46 bool SingleSegmentSegmenter::GetInitRangeStartAndEnd(uint64_t* start,
47  uint64_t* end) {
48  *start = 0;
49  *end = init_end_;
50  return true;
51 }
52 
53 bool SingleSegmentSegmenter::GetIndexRangeStartAndEnd(uint64_t* start,
54  uint64_t* end) {
55  *start = index_start_;
56  *end = index_end_;
57  return true;
58 }
59 
60 std::vector<Range> SingleSegmentSegmenter::GetSegmentRanges() {
61  std::vector<Range> ranges;
62  if (cues()->cue_entries_size() == 0) {
63  return ranges;
64  }
65  for (int32_t i = 0; i < cues()->cue_entries_size() - 1; ++i) {
66  const mkvmuxer::CuePoint* cue_point = cues()->GetCueByIndex(i);
67  Range r;
68  // Cue point cluster position is relative to segment payload pos.
69  r.start = segment_payload_pos() + cue_point->cluster_pos();
70  r.end =
71  segment_payload_pos() + cues()->GetCueByIndex(i + 1)->cluster_pos() - 1;
72  ranges.push_back(r);
73  }
74 
75  Range last_range;
76  const mkvmuxer::CuePoint* last_cue_point =
77  cues()->GetCueByIndex(cues()->cue_entries_size() - 1);
78  last_range.start = segment_payload_pos() + last_cue_point->cluster_pos();
79  last_range.end = last_range.start + cluster()->Size() - 1;
80  ranges.push_back(last_range);
81  return ranges;
82 }
83 
84 Status SingleSegmentSegmenter::DoInitialize() {
85  if (!writer_) {
86  std::unique_ptr<MkvWriter> writer(new MkvWriter);
87  Status status = writer->Open(options().output_file_name);
88  if (!status.ok())
89  return status;
90  writer_ = std::move(writer);
91  }
92 
93  Status ret = WriteSegmentHeader(0, writer_.get());
94  init_end_ = writer_->Position() - 1;
95  seek_head()->set_cluster_pos(init_end_ + 1 - segment_payload_pos());
96  return ret;
97 }
98 
99 Status SingleSegmentSegmenter::DoFinalize() {
100  // Write the Cues to the end of the file.
101  index_start_ = writer_->Position();
102  seek_head()->set_cues_pos(index_start_ - segment_payload_pos());
103  if (!cues()->Write(writer_.get()))
104  return Status(error::FILE_FAILURE, "Error writing Cues data.");
105 
106  // The WebM index is at the end of the file.
107  index_end_ = writer_->Position() - 1;
108  writer_->Position(0);
109 
110  Status status = WriteSegmentHeader(index_end_ + 1, writer_.get());
111  status.Update(writer_->Close());
112  return status;
113 }
114 
115 Status SingleSegmentSegmenter::NewSegment(int64_t start_timestamp,
116  bool is_subsegment) {
117  // No-op for subsegment in single segment mode.
118  if (is_subsegment)
119  return Status::OK;
120  // Create a new Cue point.
121  uint64_t position = writer_->Position();
122  int64_t start_timecode = FromBmffTimestamp(start_timestamp);
123 
124  mkvmuxer::CuePoint* cue_point = new mkvmuxer::CuePoint;
125  cue_point->set_time(start_timecode);
126  cue_point->set_track(track_id());
127  cue_point->set_cluster_pos(position - segment_payload_pos());
128  if (!cues()->AddCue(cue_point))
129  return Status(error::INTERNAL_ERROR, "Error adding CuePoint.");
130 
131  return SetCluster(start_timecode, position, writer_.get());
132 }
133 
134 } // namespace webm
135 } // namespace media
136 } // namespace shaka
All the methods that are virtual are virtual for mocking.
Definition: crypto_flags.cc:66