Shaka Packager SDK
Loading...
Searching...
No Matches
webm_muxer.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/webm_muxer.h>
8
9#include <cstddef>
10#include <cstdint>
11
12#include <absl/log/check.h>
13#include <absl/log/log.h>
14
15#include <packager/macros/logging.h>
16#include <packager/media/base/fourccs.h>
17#include <packager/media/base/media_handler.h>
18#include <packager/media/base/media_sample.h>
19#include <packager/media/base/muxer.h>
20#include <packager/media/base/range.h>
21#include <packager/media/event/muxer_listener.h>
22#include <packager/media/formats/webm/multi_segment_segmenter.h>
23#include <packager/media/formats/webm/single_segment_segmenter.h>
24#include <packager/media/formats/webm/two_pass_single_segment_segmenter.h>
25#include <packager/status.h>
26
27namespace shaka {
28namespace media {
29namespace webm {
30
31WebMMuxer::WebMMuxer(const MuxerOptions& options) : Muxer(options) {}
32WebMMuxer::~WebMMuxer() {}
33
34Status WebMMuxer::InitializeMuxer() {
35 CHECK_EQ(streams().size(), 1U);
36
37 if (streams()[0]->is_encrypted() &&
38 streams()[0]->encryption_config().protection_scheme != FOURCC_cenc) {
39 LOG(ERROR) << "WebM does not support protection scheme other than 'cenc'.";
40 return Status(error::INVALID_ARGUMENT,
41 "WebM does not support protection scheme other than 'cenc'.");
42 }
43
44 if (!options().segment_template.empty()) {
45 segmenter_.reset(new MultiSegmentSegmenter(options()));
46 } else {
47 segmenter_.reset(new TwoPassSingleSegmentSegmenter(options()));
48 }
49
50 Status initialized = segmenter_->Initialize(
51 *streams()[0], progress_listener(), muxer_listener());
52 if (!initialized.ok())
53 return initialized;
54
55 FireOnMediaStartEvent();
56 return Status::OK;
57}
58
59Status WebMMuxer::Finalize() {
60 if (!segmenter_)
61 return Status::OK;
62 Status segmenter_finalized = segmenter_->Finalize();
63
64 if (!segmenter_finalized.ok())
65 return segmenter_finalized;
66
67 FireOnMediaEndEvent();
68 LOG(INFO) << "WEBM file '" << options().output_file_name << "' finalized.";
69 return Status::OK;
70}
71
72Status WebMMuxer::AddMediaSample(size_t stream_id, const MediaSample& sample) {
73 DCHECK(segmenter_);
74 DCHECK_EQ(stream_id, 0u);
75 if (sample.pts() < 0) {
76 LOG(ERROR) << "Seeing negative timestamp " << sample.pts();
77 return Status(error::MUXER_FAILURE, "Unsupported negative timestamp.");
78 }
79 return segmenter_->AddSample(sample);
80}
81
82Status WebMMuxer::FinalizeSegment(size_t stream_id,
83 const SegmentInfo& segment_info) {
84 DCHECK(segmenter_);
85 DCHECK_EQ(stream_id, 0u);
86
87 if (segment_info.key_rotation_encryption_config) {
88 NOTIMPLEMENTED() << "Key rotation is not implemented for WebM.";
89 return Status(error::UNIMPLEMENTED,
90 "Key rotation is not implemented for WebM");
91 }
92 return segmenter_->FinalizeSegment(
93 segment_info.start_timestamp, segment_info.duration,
94 segment_info.is_subsegment, segment_info.segment_number);
95}
96
97void WebMMuxer::FireOnMediaStartEvent() {
98 if (!muxer_listener())
99 return;
100
101 DCHECK(!streams().empty()) << "Media started without a stream.";
102
103 const int32_t timescale = streams().front()->time_scale();
104 muxer_listener()->OnMediaStart(options(), *streams().front(), timescale,
105 MuxerListener::kContainerWebM);
106}
107
108void WebMMuxer::FireOnMediaEndEvent() {
109 if (!muxer_listener())
110 return;
111
112 MuxerListener::MediaRanges media_range;
113
114 uint64_t init_range_start = 0;
115 uint64_t init_range_end = 0;
116 const bool has_init_range =
117 segmenter_->GetInitRangeStartAndEnd(&init_range_start, &init_range_end);
118 if (has_init_range) {
119 Range r;
120 r.start = init_range_start;
121 r.end = init_range_end;
122 media_range.init_range = r;
123 }
124
125 uint64_t index_range_start = 0;
126 uint64_t index_range_end = 0;
127 const bool has_index_range = segmenter_->GetIndexRangeStartAndEnd(
128 &index_range_start, &index_range_end);
129 if (has_index_range) {
130 Range r;
131 r.start = index_range_start;
132 r.end = index_range_end;
133 media_range.index_range = r;
134 }
135
136 media_range.subsegment_ranges = segmenter_->GetSegmentRanges();
137
138 const float duration_seconds = segmenter_->GetDurationInSeconds();
139 muxer_listener()->OnMediaEnd(media_range, duration_seconds);
140}
141
142} // namespace webm
143} // namespace media
144} // namespace shaka
virtual void OnMediaEnd(const MediaRanges &media_ranges, float duration_seconds)=0
virtual void OnMediaStart(const MuxerOptions &muxer_options, const StreamInfo &stream_info, int32_t time_scale, ContainerType container_type)=0
WebMMuxer(const MuxerOptions &options)
Create a WebMMuxer object from MuxerOptions.
Definition webm_muxer.cc:31
All the methods that are virtual are virtual for mocking.
This structure contains the list of configuration options for Muxer.