This source file includes following definitions.
- HasValidStreamConfig
- IsStreamEncrypted
- weak_ptr_factory_
- SelectDecoder
- Abort
- DecryptingDecoderInitDone
- DecryptingDemuxerStreamInitDone
- InitializeDecoder
- DecoderInitDone
- ReturnNullDecoder
#include "decoder_selector.h"
#include "base/bind.h"
#include "base/callback_helpers.h"
#include "base/logging.h"
#include "base/single_thread_task_runner.h"
#include "media/base/audio_decoder.h"
#include "media/base/bind_to_current_loop.h"
#include "media/base/demuxer_stream.h"
#include "media/base/pipeline.h"
#include "media/base/video_decoder.h"
#include "media/filters/decoder_stream_traits.h"
#include "media/filters/decrypting_audio_decoder.h"
#include "media/filters/decrypting_demuxer_stream.h"
#include "media/filters/decrypting_video_decoder.h"
namespace media {
static bool HasValidStreamConfig(DemuxerStream* stream) {
switch (stream->type()) {
case DemuxerStream::AUDIO:
return stream->audio_decoder_config().IsValidConfig();
case DemuxerStream::VIDEO:
return stream->video_decoder_config().IsValidConfig();
case DemuxerStream::UNKNOWN:
case DemuxerStream::TEXT:
case DemuxerStream::NUM_TYPES:
NOTREACHED();
}
return false;
}
static bool IsStreamEncrypted(DemuxerStream* stream) {
switch (stream->type()) {
case DemuxerStream::AUDIO:
return stream->audio_decoder_config().is_encrypted();
case DemuxerStream::VIDEO:
return stream->video_decoder_config().is_encrypted();
case DemuxerStream::UNKNOWN:
case DemuxerStream::TEXT:
case DemuxerStream::NUM_TYPES:
NOTREACHED();
}
return false;
}
template <DemuxerStream::Type StreamType>
DecoderSelector<StreamType>::DecoderSelector(
const scoped_refptr<base::SingleThreadTaskRunner>& task_runner,
ScopedVector<Decoder> decoders,
const SetDecryptorReadyCB& set_decryptor_ready_cb)
: task_runner_(task_runner),
decoders_(decoders.Pass()),
set_decryptor_ready_cb_(set_decryptor_ready_cb),
input_stream_(NULL),
weak_ptr_factory_(this) {}
template <DemuxerStream::Type StreamType>
DecoderSelector<StreamType>::~DecoderSelector() {
DVLOG(2) << __FUNCTION__;
DCHECK(select_decoder_cb_.is_null());
}
template <DemuxerStream::Type StreamType>
void DecoderSelector<StreamType>::SelectDecoder(
DemuxerStream* stream,
const SelectDecoderCB& select_decoder_cb) {
DVLOG(2) << __FUNCTION__;
DCHECK(task_runner_->BelongsToCurrentThread());
DCHECK(stream);
select_decoder_cb_ = BindToCurrentLoop(select_decoder_cb);
if (!HasValidStreamConfig(stream)) {
DLOG(ERROR) << "Invalid stream config.";
ReturnNullDecoder();
return;
}
input_stream_ = stream;
if (!IsStreamEncrypted(input_stream_)) {
InitializeDecoder();
return;
}
if (set_decryptor_ready_cb_.is_null()) {
ReturnNullDecoder();
return;
}
decoder_.reset(new typename StreamTraits::DecryptingDecoderType(
task_runner_, set_decryptor_ready_cb_));
decoder_->Initialize(
StreamTraits::GetDecoderConfig(*input_stream_),
base::Bind(&DecoderSelector<StreamType>::DecryptingDecoderInitDone,
weak_ptr_factory_.GetWeakPtr()));
}
template <DemuxerStream::Type StreamType>
void DecoderSelector<StreamType>::Abort() {
DVLOG(2) << __FUNCTION__;
DCHECK(task_runner_->BelongsToCurrentThread());
if (select_decoder_cb_.is_null())
return;
weak_ptr_factory_.InvalidateWeakPtrs();
if (decoder_) {
decoder_->Stop();
ReturnNullDecoder();
return;
}
if (decrypted_stream_) {
decrypted_stream_->Stop(
base::Bind(&DecoderSelector<StreamType>::ReturnNullDecoder,
weak_ptr_factory_.GetWeakPtr()));
return;
}
NOTREACHED();
}
template <DemuxerStream::Type StreamType>
void DecoderSelector<StreamType>::DecryptingDecoderInitDone(
PipelineStatus status) {
DVLOG(2) << __FUNCTION__;
DCHECK(task_runner_->BelongsToCurrentThread());
if (status == PIPELINE_OK) {
base::ResetAndReturn(&select_decoder_cb_)
.Run(decoder_.Pass(), scoped_ptr<DecryptingDemuxerStream>());
return;
}
decoder_.reset();
decrypted_stream_.reset(
new DecryptingDemuxerStream(task_runner_, set_decryptor_ready_cb_));
decrypted_stream_->Initialize(
input_stream_,
base::Bind(&DecoderSelector<StreamType>::DecryptingDemuxerStreamInitDone,
weak_ptr_factory_.GetWeakPtr()));
}
template <DemuxerStream::Type StreamType>
void DecoderSelector<StreamType>::DecryptingDemuxerStreamInitDone(
PipelineStatus status) {
DVLOG(2) << __FUNCTION__;
DCHECK(task_runner_->BelongsToCurrentThread());
if (status != PIPELINE_OK) {
ReturnNullDecoder();
return;
}
DCHECK(!IsStreamEncrypted(decrypted_stream_.get()));
input_stream_ = decrypted_stream_.get();
InitializeDecoder();
}
template <DemuxerStream::Type StreamType>
void DecoderSelector<StreamType>::InitializeDecoder() {
DVLOG(2) << __FUNCTION__;
DCHECK(task_runner_->BelongsToCurrentThread());
DCHECK(!decoder_);
if (decoders_.empty()) {
ReturnNullDecoder();
return;
}
decoder_.reset(decoders_.front());
decoders_.weak_erase(decoders_.begin());
decoder_->Initialize(StreamTraits::GetDecoderConfig(*input_stream_),
base::Bind(&DecoderSelector<StreamType>::DecoderInitDone,
weak_ptr_factory_.GetWeakPtr()));
}
template <DemuxerStream::Type StreamType>
void DecoderSelector<StreamType>::DecoderInitDone(PipelineStatus status) {
DVLOG(2) << __FUNCTION__;
DCHECK(task_runner_->BelongsToCurrentThread());
if (status != PIPELINE_OK) {
decoder_.reset();
InitializeDecoder();
return;
}
base::ResetAndReturn(&select_decoder_cb_)
.Run(decoder_.Pass(), decrypted_stream_.Pass());
}
template <DemuxerStream::Type StreamType>
void DecoderSelector<StreamType>::ReturnNullDecoder() {
DVLOG(2) << __FUNCTION__;
DCHECK(task_runner_->BelongsToCurrentThread());
base::ResetAndReturn(&select_decoder_cb_)
.Run(scoped_ptr<Decoder>(),
scoped_ptr<DecryptingDemuxerStream>());
}
template class DecoderSelector<DemuxerStream::AUDIO>;
template class DecoderSelector<DemuxerStream::VIDEO>;
}