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-04-08 18:41:17 +00:00
|
|
|
#include "packager/media/base/fourccs.h"
|
2014-10-01 22:10:21 +00:00
|
|
|
#include "packager/media/base/media_sample.h"
|
|
|
|
#include "packager/media/base/media_stream.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 {
|
|
|
|
|
2014-01-14 01:38:34 +00:00
|
|
|
Muxer::Muxer(const MuxerOptions& options)
|
2013-12-12 23:49:31 +00:00
|
|
|
: options_(options),
|
2014-04-09 17:34:55 +00:00
|
|
|
initialized_(false),
|
2014-04-18 18:49:49 +00:00
|
|
|
encryption_key_source_(NULL),
|
2014-04-24 21:32:18 +00:00
|
|
|
max_sd_pixels_(0),
|
2013-12-12 23:49:31 +00:00
|
|
|
clear_lead_in_seconds_(0),
|
2014-04-18 18:49:49 +00:00
|
|
|
crypto_period_duration_in_seconds_(0),
|
2016-04-08 18:41:17 +00:00
|
|
|
protection_scheme_(FOURCC_NULL),
|
2015-02-09 18:22:28 +00:00
|
|
|
cancelled_(false),
|
2014-02-28 02:39:52 +00:00
|
|
|
clock_(NULL) {}
|
2013-10-11 21:44:55 +00:00
|
|
|
|
|
|
|
Muxer::~Muxer() {}
|
|
|
|
|
2014-08-20 23:51:15 +00:00
|
|
|
void Muxer::SetKeySource(KeySource* encryption_key_source,
|
2014-09-30 21:52:21 +00:00
|
|
|
uint32_t max_sd_pixels,
|
2014-08-20 23:51:15 +00:00
|
|
|
double clear_lead_in_seconds,
|
2016-03-17 17:03:19 +00:00
|
|
|
double crypto_period_duration_in_seconds,
|
2016-04-08 18:41:17 +00:00
|
|
|
FourCC protection_scheme) {
|
2014-04-18 18:49:49 +00:00
|
|
|
DCHECK(encryption_key_source);
|
2014-04-16 01:09:32 +00:00
|
|
|
encryption_key_source_ = encryption_key_source;
|
2014-04-24 21:32:18 +00:00
|
|
|
max_sd_pixels_ = max_sd_pixels;
|
2014-01-14 01:38:34 +00:00
|
|
|
clear_lead_in_seconds_ = clear_lead_in_seconds;
|
2014-04-18 18:49:49 +00:00
|
|
|
crypto_period_duration_in_seconds_ = crypto_period_duration_in_seconds;
|
2016-04-08 18:41:17 +00:00
|
|
|
protection_scheme_ = protection_scheme;
|
2014-01-14 01:38:34 +00:00
|
|
|
}
|
|
|
|
|
2014-04-09 17:34:55 +00:00
|
|
|
void Muxer::AddStream(MediaStream* stream) {
|
|
|
|
DCHECK(stream);
|
2013-10-11 21:44:55 +00:00
|
|
|
stream->Connect(this);
|
|
|
|
streams_.push_back(stream);
|
|
|
|
}
|
|
|
|
|
|
|
|
Status Muxer::Run() {
|
|
|
|
DCHECK(!streams_.empty());
|
|
|
|
|
|
|
|
Status status;
|
|
|
|
// Start the streams.
|
|
|
|
for (std::vector<MediaStream*>::iterator it = streams_.begin();
|
|
|
|
it != streams_.end();
|
|
|
|
++it) {
|
|
|
|
status = (*it)->Start(MediaStream::kPull);
|
|
|
|
if (!status.ok())
|
|
|
|
return status;
|
|
|
|
}
|
|
|
|
|
2014-09-30 21:52:21 +00:00
|
|
|
uint32_t current_stream_id = 0;
|
2013-10-11 21:44:55 +00:00
|
|
|
while (status.ok()) {
|
2015-02-09 18:22:28 +00:00
|
|
|
if (cancelled_)
|
|
|
|
return Status(error::CANCELLED, "muxer run cancelled");
|
|
|
|
|
2013-10-11 21:44:55 +00:00
|
|
|
scoped_refptr<MediaSample> sample;
|
2013-11-12 20:37:58 +00:00
|
|
|
status = streams_[current_stream_id]->PullSample(&sample);
|
2013-10-11 21:44:55 +00:00
|
|
|
if (!status.ok())
|
|
|
|
break;
|
2013-11-12 20:37:58 +00:00
|
|
|
status = AddSample(streams_[current_stream_id], sample);
|
|
|
|
|
|
|
|
// Switch to next stream if the current stream is ready for fragmentation.
|
2014-04-09 17:34:55 +00:00
|
|
|
if (status.error_code() == error::FRAGMENT_FINALIZED) {
|
2013-11-12 20:37:58 +00:00
|
|
|
current_stream_id = (current_stream_id + 1) % streams_.size();
|
|
|
|
status.Clear();
|
|
|
|
}
|
2013-10-11 21:44:55 +00:00
|
|
|
}
|
2014-04-09 17:34:55 +00:00
|
|
|
// Finalize the muxer after reaching end of stream.
|
|
|
|
return status.error_code() == error::END_OF_STREAM ? Finalize() : status;
|
2013-10-11 21:44:55 +00:00
|
|
|
}
|
|
|
|
|
2015-02-09 18:22:28 +00:00
|
|
|
void Muxer::Cancel() {
|
|
|
|
cancelled_ = true;
|
|
|
|
}
|
|
|
|
|
2015-05-07 21:06:16 +00:00
|
|
|
void Muxer::SetMuxerListener(scoped_ptr<MuxerListener> muxer_listener) {
|
2015-05-05 23:30:14 +00:00
|
|
|
muxer_listener_ = muxer_listener.Pass();
|
2013-12-12 23:49:31 +00:00
|
|
|
}
|
|
|
|
|
2015-05-11 21:07:10 +00:00
|
|
|
void Muxer::SetProgressListener(
|
|
|
|
scoped_ptr<ProgressListener> progress_listener) {
|
|
|
|
progress_listener_ = progress_listener.Pass();
|
|
|
|
}
|
|
|
|
|
2014-04-09 17:34:55 +00:00
|
|
|
Status Muxer::AddSample(const MediaStream* stream,
|
|
|
|
scoped_refptr<MediaSample> sample) {
|
|
|
|
DCHECK(std::find(streams_.begin(), streams_.end(), stream) != streams_.end());
|
|
|
|
|
|
|
|
if (!initialized_) {
|
|
|
|
Status status = Initialize();
|
|
|
|
if (!status.ok())
|
|
|
|
return status;
|
|
|
|
initialized_ = true;
|
|
|
|
}
|
|
|
|
if (sample->end_of_stream()) {
|
|
|
|
// EOS sample should be sent only when the sample was pushed from Demuxer
|
|
|
|
// to Muxer. In this case, there should be only one stream in Muxer.
|
|
|
|
DCHECK_EQ(1u, streams_.size());
|
|
|
|
return Finalize();
|
2015-01-12 21:17:10 +00:00
|
|
|
} else if (sample->is_encrypted()) {
|
|
|
|
LOG(ERROR) << "Unable to multiplex encrypted media sample";
|
|
|
|
return Status(error::INTERNAL_ERROR, "Encrypted media sample.");
|
2014-04-09 17:34:55 +00:00
|
|
|
}
|
|
|
|
return DoAddSample(stream, sample);
|
|
|
|
}
|
|
|
|
|
2013-10-11 21:44:55 +00:00
|
|
|
} // namespace media
|
2016-05-20 21:19:33 +00:00
|
|
|
} // namespace shaka
|