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