Shaka Packager SDK
Loading...
Searching...
No Matches
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
15namespace shaka {
16namespace media {
17
18TextMuxer::TextMuxer(const MuxerOptions& options) : Muxer(options) {}
19TextMuxer::~TextMuxer() {}
20
21Status 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
37Status 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
67Status 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
81Status 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.