Shaka Packager SDK
muxer.cc
1 // Copyright 2014 Google Inc. 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/muxer.h"
8 
9 #include <algorithm>
10 
11 #include "packager/media/base/media_sample.h"
12 #include "packager/media/base/muxer_util.h"
13 #include "packager/status_macros.h"
14 
15 namespace shaka {
16 namespace media {
17 namespace {
18 const bool kInitialEncryptionInfo = true;
19 const int64_t kStartTime = 0;
20 } // namespace
21 
22 Muxer::Muxer(const MuxerOptions& options) : options_(options) {
23  // "$" is only allowed if the output file name is a template, which is used to
24  // support one file per Representation per Period when there are Ad Cues.
25  if (options_.output_file_name.find("$") != std::string::npos)
26  output_file_template_ = options_.output_file_name;
27 }
28 
29 Muxer::~Muxer() {}
30 
31 void Muxer::Cancel() {
32  cancelled_ = true;
33 }
34 
35 void Muxer::SetMuxerListener(std::unique_ptr<MuxerListener> muxer_listener) {
36  muxer_listener_ = std::move(muxer_listener);
37 }
38 
40  std::unique_ptr<ProgressListener> progress_listener) {
41  progress_listener_ = std::move(progress_listener);
42 }
43 
44 Status Muxer::Process(std::unique_ptr<StreamData> stream_data) {
45  Status status;
46  switch (stream_data->stream_data_type) {
47  case StreamDataType::kStreamInfo:
48  streams_.push_back(std::move(stream_data->stream_info));
49  return ReinitializeMuxer(kStartTime);
50  case StreamDataType::kSegmentInfo: {
51  const auto& segment_info = *stream_data->segment_info;
52  if (muxer_listener_ && segment_info.is_encrypted) {
53  const EncryptionConfig* encryption_config =
54  segment_info.key_rotation_encryption_config.get();
55  // Only call OnEncryptionInfoReady again when key updates.
56  if (encryption_config && encryption_config->key_id != current_key_id_) {
57  muxer_listener_->OnEncryptionInfoReady(
58  !kInitialEncryptionInfo, encryption_config->protection_scheme,
59  encryption_config->key_id, encryption_config->constant_iv,
60  encryption_config->key_system_info);
61  current_key_id_ = encryption_config->key_id;
62  }
63  if (!encryption_started_) {
64  encryption_started_ = true;
65  muxer_listener_->OnEncryptionStart();
66  }
67  }
68  return FinalizeSegment(stream_data->stream_index, segment_info);
69  }
70  case StreamDataType::kMediaSample:
71  return AddMediaSample(stream_data->stream_index,
72  *stream_data->media_sample);
73  case StreamDataType::kTextSample:
74  return AddTextSample(stream_data->stream_index,
75  *stream_data->text_sample);
76  case StreamDataType::kCueEvent:
77  if (muxer_listener_) {
78  const int64_t time_scale =
79  streams_[stream_data->stream_index]->time_scale();
80  const double time_in_seconds = stream_data->cue_event->time_in_seconds;
81  const int64_t scaled_time =
82  static_cast<int64_t>(time_in_seconds * time_scale);
83  muxer_listener_->OnCueEvent(scaled_time,
84  stream_data->cue_event->cue_data);
85 
86  // Finalize and re-initialize Muxer to generate different content files.
87  if (!output_file_template_.empty()) {
88  RETURN_IF_ERROR(Finalize());
89  RETURN_IF_ERROR(ReinitializeMuxer(scaled_time));
90  }
91  }
92  break;
93  default:
94  VLOG(3) << "Stream data type "
95  << static_cast<int>(stream_data->stream_data_type) << " ignored.";
96  break;
97  }
98  // No dispatch for muxer.
99  return Status::OK;
100 }
101 
102 Status Muxer::OnFlushRequest(size_t input_stream_index) {
103  return Finalize();
104 }
105 
106 Status Muxer::AddMediaSample(size_t stream_id, const MediaSample& sample) {
107  return Status::OK;
108 }
109 
110 Status Muxer::AddTextSample(size_t stream_id, const TextSample& sample) {
111  return Status::OK;
112 }
113 
114 Status Muxer::ReinitializeMuxer(int64_t timestamp) {
115  if (muxer_listener_ && streams_.back()->is_encrypted()) {
116  const EncryptionConfig& encryption_config =
117  streams_.back()->encryption_config();
118  muxer_listener_->OnEncryptionInfoReady(
119  kInitialEncryptionInfo, encryption_config.protection_scheme,
120  encryption_config.key_id, encryption_config.constant_iv,
121  encryption_config.key_system_info);
122  current_key_id_ = encryption_config.key_id;
123  }
124  if (!output_file_template_.empty()) {
125  // Update |output_file_name| with an actual file name, which will be used by
126  // the subclasses.
127  options_.output_file_name =
128  GetSegmentName(output_file_template_, timestamp, output_file_index_++,
129  options_.bandwidth);
130  }
131  return InitializeMuxer();
132 }
133 
134 } // namespace media
135 } // namespace shaka
shaka::media::Muxer::Process
Status Process(std::unique_ptr< StreamData > stream_data) override
Definition: muxer.cc:44
shaka
All the methods that are virtual are virtual for mocking.
Definition: gflags_hex_bytes.cc:11
shaka::media::Muxer::SetMuxerListener
void SetMuxerListener(std::unique_ptr< MuxerListener > muxer_listener)
Definition: muxer.cc:35
shaka::Status
Definition: status.h:110
shaka::media::Muxer::SetProgressListener
void SetProgressListener(std::unique_ptr< ProgressListener > progress_listener)
Definition: muxer.cc:39
shaka::media::MuxerOptions::output_file_name
std::string output_file_name
Definition: muxer_options.h:34
shaka::media::MediaSample
Class to hold a media sample.
Definition: media_sample.h:22
shaka::media::Muxer::Cancel
void Cancel()
Definition: muxer.cc:31
shaka::media::Muxer::OnFlushRequest
Status OnFlushRequest(size_t input_stream_index) override
Event handler for flush request at the specific input stream index.
Definition: muxer.cc:102
shaka::media::MuxerOptions::bandwidth
uint32_t bandwidth
Definition: muxer_options.h:47
shaka::media::EncryptionConfig
Definition: encryption_config.h:16