7 #include "packager/media/formats/webm/webm_muxer.h"
9 #include "packager/media/base/fourccs.h"
10 #include "packager/media/base/media_sample.h"
11 #include "packager/media/base/stream_info.h"
12 #include "packager/media/formats/webm/mkv_writer.h"
13 #include "packager/media/formats/webm/multi_segment_segmenter.h"
14 #include "packager/media/formats/webm/single_segment_segmenter.h"
15 #include "packager/media/formats/webm/two_pass_single_segment_segmenter.h"
22 WebMMuxer::~WebMMuxer() {}
24 Status WebMMuxer::InitializeMuxer() {
25 CHECK_EQ(streams().size(), 1U);
27 if (crypto_period_duration_in_seconds() > 0) {
28 NOTIMPLEMENTED() <<
"Key rotation is not implemented for WebM";
29 return Status(error::UNIMPLEMENTED,
30 "Key rotation is not implemented for WebM");
33 if (encryption_key_source() && (protection_scheme() != FOURCC_cenc)) {
35 <<
"WebM does not support protection scheme other than 'cenc'.";
36 return Status(error::UNIMPLEMENTED,
37 "WebM does not support protection scheme other than 'cenc'.");
40 std::unique_ptr<MkvWriter> writer(
new MkvWriter);
41 Status status = writer->Open(options().output_file_name);
46 segmenter_.reset(
new MultiSegmentSegmenter(options()));
48 segmenter_.reset(
new TwoPassSingleSegmentSegmenter(options()));
51 Status initialized = segmenter_->Initialize(
52 std::move(writer), streams()[0].
get(), progress_listener(),
53 muxer_listener(), encryption_key_source(), max_sd_pixels(),
54 max_hd_pixels(), max_uhd1_pixels(), clear_lead_in_seconds());
56 if (!initialized.ok())
59 FireOnMediaStartEvent();
63 Status WebMMuxer::Finalize() {
65 Status segmenter_finalized = segmenter_->Finalize();
67 if (!segmenter_finalized.ok())
68 return segmenter_finalized;
70 FireOnMediaEndEvent();
75 Status WebMMuxer::AddSample(
size_t stream_id,
76 std::shared_ptr<MediaSample> sample) {
78 DCHECK_EQ(stream_id, 0u);
79 return segmenter_->AddSample(sample);
82 Status WebMMuxer::FinalizeSegment(
size_t stream_id,
83 std::shared_ptr<SegmentInfo> segment_info) {
85 DCHECK_EQ(stream_id, 0u);
86 return segmenter_->FinalizeSegment(segment_info->start_timestamp,
87 segment_info->duration,
88 segment_info->is_subsegment);
91 void WebMMuxer::FireOnMediaStartEvent() {
92 if (!muxer_listener())
95 DCHECK(!streams().empty()) <<
"Media started without a stream.";
97 const uint32_t timescale = streams().front()->time_scale();
98 muxer_listener()->
OnMediaStart(options(), *streams().front(), timescale,
99 MuxerListener::kContainerWebM);
102 void WebMMuxer::FireOnMediaEndEvent() {
103 if (!muxer_listener())
106 uint64_t init_range_start = 0;
107 uint64_t init_range_end = 0;
108 const bool has_init_range =
109 segmenter_->GetInitRangeStartAndEnd(&init_range_start, &init_range_end);
111 uint64_t index_range_start = 0;
112 uint64_t index_range_end = 0;
113 const bool has_index_range = segmenter_->GetIndexRangeStartAndEnd(
114 &index_range_start, &index_range_end);
116 const float duration_seconds = segmenter_->GetDuration();
118 const int64_t file_size =
120 if (file_size <= 0) {
121 LOG(ERROR) <<
"Invalid file size: " << file_size;
125 muxer_listener()->
OnMediaEnd(has_init_range, init_range_start, init_range_end,
126 has_index_range, index_range_start,
127 index_range_end, duration_seconds, file_size);