2014-02-14 23:21:05 +00:00
|
|
|
// Copyright 2014 Google Inc. All rights reserved.
|
|
|
|
//
|
|
|
|
// Use of this source code is governed by a BSD-style
|
|
|
|
// license that can be found in the LICENSE file or at
|
|
|
|
// https://developers.google.com/open-source/licenses/bsd
|
2013-10-11 21:44:55 +00:00
|
|
|
|
2014-10-01 22:10:21 +00:00
|
|
|
#include "packager/media/base/muxer.h"
|
2013-10-11 21:44:55 +00:00
|
|
|
|
2016-08-17 17:41:40 +00:00
|
|
|
#include <algorithm>
|
|
|
|
|
2014-10-01 22:10:21 +00:00
|
|
|
#include "packager/media/base/media_sample.h"
|
2013-10-11 21:44:55 +00:00
|
|
|
|
2016-05-20 21:19:33 +00:00
|
|
|
namespace shaka {
|
2013-10-11 21:44:55 +00:00
|
|
|
namespace media {
|
2017-03-11 02:49:55 +00:00
|
|
|
namespace {
|
|
|
|
const bool kInitialEncryptionInfo = true;
|
|
|
|
} // namespace
|
2013-10-11 21:44:55 +00:00
|
|
|
|
2014-01-14 01:38:34 +00:00
|
|
|
Muxer::Muxer(const MuxerOptions& options)
|
2017-03-11 02:49:55 +00:00
|
|
|
: options_(options), cancelled_(false), clock_(NULL) {}
|
2013-10-11 21:44:55 +00:00
|
|
|
|
|
|
|
Muxer::~Muxer() {}
|
|
|
|
|
2015-02-09 18:22:28 +00:00
|
|
|
void Muxer::Cancel() {
|
|
|
|
cancelled_ = true;
|
|
|
|
}
|
|
|
|
|
2016-08-17 17:41:40 +00:00
|
|
|
void Muxer::SetMuxerListener(std::unique_ptr<MuxerListener> muxer_listener) {
|
|
|
|
muxer_listener_ = std::move(muxer_listener);
|
2013-12-12 23:49:31 +00:00
|
|
|
}
|
|
|
|
|
2015-05-11 21:07:10 +00:00
|
|
|
void Muxer::SetProgressListener(
|
2016-08-17 17:41:40 +00:00
|
|
|
std::unique_ptr<ProgressListener> progress_listener) {
|
|
|
|
progress_listener_ = std::move(progress_listener);
|
2015-05-11 21:07:10 +00:00
|
|
|
}
|
|
|
|
|
2017-02-21 18:36:50 +00:00
|
|
|
Status Muxer::Process(std::unique_ptr<StreamData> stream_data) {
|
|
|
|
Status status;
|
|
|
|
switch (stream_data->stream_data_type) {
|
|
|
|
case StreamDataType::kStreamInfo:
|
|
|
|
streams_.push_back(std::move(stream_data->stream_info));
|
2017-03-11 02:49:55 +00:00
|
|
|
if (muxer_listener_ && streams_.back()->is_encrypted()) {
|
|
|
|
const EncryptionConfig& encryption_config =
|
|
|
|
streams_.back()->encryption_config();
|
|
|
|
muxer_listener_->OnEncryptionInfoReady(
|
|
|
|
kInitialEncryptionInfo, encryption_config.protection_scheme,
|
|
|
|
encryption_config.key_id, encryption_config.constant_iv,
|
|
|
|
encryption_config.key_system_info);
|
2017-06-20 23:30:03 +00:00
|
|
|
current_key_id_ = encryption_config.key_id;
|
2017-03-11 02:49:55 +00:00
|
|
|
}
|
2017-02-21 18:36:50 +00:00
|
|
|
return InitializeMuxer();
|
2017-03-11 02:49:55 +00:00
|
|
|
case StreamDataType::kSegmentInfo: {
|
2017-09-12 17:24:24 +00:00
|
|
|
const auto& segment_info = *stream_data->segment_info;
|
|
|
|
if (muxer_listener_ && segment_info.is_encrypted) {
|
2017-03-11 02:49:55 +00:00
|
|
|
const EncryptionConfig* encryption_config =
|
2017-09-12 17:24:24 +00:00
|
|
|
segment_info.key_rotation_encryption_config.get();
|
2017-06-20 23:30:03 +00:00
|
|
|
// Only call OnEncryptionInfoReady again when key updates.
|
|
|
|
if (encryption_config && encryption_config->key_id != current_key_id_) {
|
2017-03-11 02:49:55 +00:00
|
|
|
muxer_listener_->OnEncryptionInfoReady(
|
|
|
|
!kInitialEncryptionInfo, encryption_config->protection_scheme,
|
|
|
|
encryption_config->key_id, encryption_config->constant_iv,
|
|
|
|
encryption_config->key_system_info);
|
2017-06-20 23:30:03 +00:00
|
|
|
current_key_id_ = encryption_config->key_id;
|
2017-03-11 02:49:55 +00:00
|
|
|
}
|
2017-06-20 23:30:03 +00:00
|
|
|
if (!encryption_started_) {
|
2017-03-11 02:49:55 +00:00
|
|
|
encryption_started_ = true;
|
|
|
|
muxer_listener_->OnEncryptionStart();
|
|
|
|
}
|
|
|
|
}
|
2017-09-12 17:24:24 +00:00
|
|
|
return FinalizeSegment(stream_data->stream_index, segment_info);
|
2017-03-11 02:49:55 +00:00
|
|
|
}
|
2017-02-21 18:36:50 +00:00
|
|
|
case StreamDataType::kMediaSample:
|
2018-03-15 23:01:47 +00:00
|
|
|
return AddSample(stream_data->stream_index, *stream_data->media_sample);
|
2018-01-03 00:10:33 +00:00
|
|
|
case StreamDataType::kCueEvent:
|
|
|
|
if (muxer_listener_) {
|
2018-03-15 23:01:47 +00:00
|
|
|
const int64_t time_scale =
|
|
|
|
streams_[stream_data->stream_index]->time_scale();
|
|
|
|
const double time_in_seconds = stream_data->cue_event->time_in_seconds;
|
|
|
|
const int64_t scaled_time =
|
|
|
|
static_cast<int64_t>(time_in_seconds * time_scale);
|
|
|
|
muxer_listener_->OnCueEvent(scaled_time,
|
2018-01-03 00:10:33 +00:00
|
|
|
stream_data->cue_event->cue_data);
|
|
|
|
}
|
|
|
|
break;
|
2017-02-21 18:36:50 +00:00
|
|
|
default:
|
|
|
|
VLOG(3) << "Stream data type "
|
|
|
|
<< static_cast<int>(stream_data->stream_data_type) << " ignored.";
|
|
|
|
break;
|
2014-04-09 17:34:55 +00:00
|
|
|
}
|
2017-02-21 18:36:50 +00:00
|
|
|
// No dispatch for muxer.
|
|
|
|
return Status::OK;
|
2014-04-09 17:34:55 +00:00
|
|
|
}
|
|
|
|
|
2013-10-11 21:44:55 +00:00
|
|
|
} // namespace media
|
2016-05-20 21:19:33 +00:00
|
|
|
} // namespace shaka
|