Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1838)

Unified Diff: content/renderer/media/android/media_source_delegate.cc

Issue 2283493003: Delete browser MSE implementation. (Closed)
Patch Set: Actually delete MSP. Cleanse references. Remove AudioTrack usage. Created 4 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: content/renderer/media/android/media_source_delegate.cc
diff --git a/content/renderer/media/android/media_source_delegate.cc b/content/renderer/media/android/media_source_delegate.cc
deleted file mode 100644
index 24a65a04804b439549d34fa1ebcf93ac4f84b416..0000000000000000000000000000000000000000
--- a/content/renderer/media/android/media_source_delegate.cc
+++ /dev/null
@@ -1,811 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/renderer/media/android/media_source_delegate.h"
-
-#include <limits>
-#include <string>
-#include <utility>
-#include <vector>
-
-#include "base/callback_helpers.h"
-#include "base/strings/string_number_conversions.h"
-#include "base/threading/thread_task_runner_handle.h"
-#include "content/renderer/media/android/renderer_demuxer_android.h"
-#include "media/base/android/demuxer_stream_player_params.h"
-#include "media/base/bind_to_current_loop.h"
-#include "media/base/demuxer_stream.h"
-#include "media/base/media_log.h"
-#include "media/base/timestamp_constants.h"
-#include "media/blink/webmediaplayer_util.h"
-#include "media/blink/webmediasource_impl.h"
-#include "media/filters/chunk_demuxer.h"
-#include "media/filters/decrypting_demuxer_stream.h"
-#include "third_party/WebKit/public/platform/WebString.h"
-#include "third_party/WebKit/public/web/WebRuntimeFeatures.h"
-
-using media::DemuxerStream;
-using media::DemuxerConfigs;
-using media::DemuxerData;
-using blink::WebMediaPlayer;
-using blink::WebString;
-
-namespace {
-
-// The size of the access unit to transfer in an IPC in case of MediaSource.
-// 4: approximately 64ms of content in 60 fps movies.
-const size_t kAccessUnitSizeForMediaSource = 4;
-
-const uint8_t kVorbisPadding[] = {0xff, 0xff, 0xff, 0xff};
-
-} // namespace
-
-namespace content {
-
-MediaSourceDelegate::MediaSourceDelegate(
- RendererDemuxerAndroid* demuxer_client,
- int demuxer_client_id,
- const scoped_refptr<base::SingleThreadTaskRunner>& media_task_runner,
- const scoped_refptr<media::MediaLog> media_log)
- : demuxer_client_(demuxer_client),
- demuxer_client_id_(demuxer_client_id),
- media_log_(media_log),
- is_demuxer_ready_(false),
- audio_stream_(NULL),
- video_stream_(NULL),
- seeking_(false),
- is_video_encrypted_(false),
- doing_browser_seek_(false),
- browser_seek_time_(media::kNoTimestamp),
- expecting_regular_seek_(false),
- access_unit_size_(0),
- main_task_runner_(base::ThreadTaskRunnerHandle::Get()),
- media_task_runner_(media_task_runner),
- main_weak_factory_(this),
- media_weak_factory_(this) {
- main_weak_this_ = main_weak_factory_.GetWeakPtr();
- DCHECK(main_task_runner_->BelongsToCurrentThread());
-}
-
-MediaSourceDelegate::~MediaSourceDelegate() {
- DCHECK(main_task_runner_->BelongsToCurrentThread());
- DVLOG(1) << __FUNCTION__ << " : " << demuxer_client_id_;
- DCHECK(!chunk_demuxer_);
- DCHECK(!demuxer_client_);
- DCHECK(!audio_decrypting_demuxer_stream_);
- DCHECK(!video_decrypting_demuxer_stream_);
- DCHECK(!audio_stream_);
- DCHECK(!video_stream_);
-}
-
-void MediaSourceDelegate::Stop(const base::Closure& stop_cb) {
- DCHECK(main_task_runner_->BelongsToCurrentThread());
- DVLOG(1) << __FUNCTION__ << " : " << demuxer_client_id_;
-
- if (!chunk_demuxer_) {
- DCHECK(!demuxer_client_);
- return;
- }
-
- duration_change_cb_.Reset();
- update_network_state_cb_.Reset();
- media_source_opened_cb_.Reset();
-
- main_weak_factory_.InvalidateWeakPtrs();
- DCHECK(!main_weak_factory_.HasWeakPtrs());
-
- chunk_demuxer_->Shutdown();
-
- // Continue to stop objects on the media thread.
- media_task_runner_->PostTask(
- FROM_HERE,
- base::Bind(
- &MediaSourceDelegate::StopDemuxer, base::Unretained(this), stop_cb));
-}
-
-bool MediaSourceDelegate::IsVideoEncrypted() {
- DCHECK(main_task_runner_->BelongsToCurrentThread());
- base::AutoLock auto_lock(is_video_encrypted_lock_);
- return is_video_encrypted_;
-}
-
-base::Time MediaSourceDelegate::GetTimelineOffset() const {
- DCHECK(main_task_runner_->BelongsToCurrentThread());
- if (!chunk_demuxer_)
- return base::Time();
-
- return chunk_demuxer_->GetTimelineOffset();
-}
-
-void MediaSourceDelegate::StopDemuxer(const base::Closure& stop_cb) {
- DVLOG(2) << __FUNCTION__;
- DCHECK(media_task_runner_->BelongsToCurrentThread());
- DCHECK(chunk_demuxer_);
-
- demuxer_client_->RemoveDelegate(demuxer_client_id_);
- demuxer_client_ = NULL;
-
- audio_stream_ = NULL;
- video_stream_ = NULL;
- // TODO(xhwang): Figure out if we need to Reset the DDSs after Seeking or
- // before destroying them.
- audio_decrypting_demuxer_stream_.reset();
- video_decrypting_demuxer_stream_.reset();
-
- media_weak_factory_.InvalidateWeakPtrs();
- DCHECK(!media_weak_factory_.HasWeakPtrs());
-
- chunk_demuxer_->Stop();
- chunk_demuxer_.reset();
-
- // |this| may be destroyed at this point in time as a result of running
- // |stop_cb|.
- stop_cb.Run();
-}
-
-void MediaSourceDelegate::InitializeMediaSource(
- const MediaSourceOpenedCB& media_source_opened_cb,
- const media::Demuxer::EncryptedMediaInitDataCB&
- encrypted_media_init_data_cb,
- const SetCdmReadyCB& set_cdm_ready_cb,
- const UpdateNetworkStateCB& update_network_state_cb,
- const DurationChangeCB& duration_change_cb,
- const base::Closure& waiting_for_decryption_key_cb) {
- DCHECK(main_task_runner_->BelongsToCurrentThread());
- DCHECK(!media_source_opened_cb.is_null());
- DCHECK(!encrypted_media_init_data_cb.is_null());
- DCHECK(!set_cdm_ready_cb.is_null());
- DCHECK(!update_network_state_cb.is_null());
- DCHECK(!duration_change_cb.is_null());
- DCHECK(!waiting_for_decryption_key_cb.is_null());
-
- media_source_opened_cb_ = media_source_opened_cb;
- encrypted_media_init_data_cb_ = encrypted_media_init_data_cb;
- set_cdm_ready_cb_ = media::BindToCurrentLoop(set_cdm_ready_cb);
- update_network_state_cb_ = media::BindToCurrentLoop(update_network_state_cb);
- duration_change_cb_ = duration_change_cb;
- waiting_for_decryption_key_cb_ =
- media::BindToCurrentLoop(waiting_for_decryption_key_cb);
- access_unit_size_ = kAccessUnitSizeForMediaSource;
-
- chunk_demuxer_.reset(new media::ChunkDemuxer(
- media::BindToCurrentLoop(
- base::Bind(&MediaSourceDelegate::OnDemuxerOpened, main_weak_this_)),
- media::BindToCurrentLoop(base::Bind(
- &MediaSourceDelegate::OnEncryptedMediaInitData, main_weak_this_)),
- media_log_, false));
-
- // |this| will be retained until StopDemuxer() is posted, so Unretained() is
- // safe here.
- media_task_runner_->PostTask(FROM_HERE,
- base::Bind(&MediaSourceDelegate::InitializeDemuxer,
- base::Unretained(this)));
-}
-
-void MediaSourceDelegate::InitializeDemuxer() {
- DCHECK(media_task_runner_->BelongsToCurrentThread());
- demuxer_client_->AddDelegate(demuxer_client_id_, this);
- chunk_demuxer_->Initialize(this,
- base::Bind(&MediaSourceDelegate::OnDemuxerInitDone,
- media_weak_factory_.GetWeakPtr()),
- false);
-}
-
-blink::WebTimeRanges MediaSourceDelegate::Buffered() const {
- return media::ConvertToWebTimeRanges(buffered_time_ranges_);
-}
-
-size_t MediaSourceDelegate::DecodedFrameCount() const {
- return statistics_.video_frames_decoded;
-}
-
-size_t MediaSourceDelegate::DroppedFrameCount() const {
- return statistics_.video_frames_dropped;
-}
-
-size_t MediaSourceDelegate::AudioDecodedByteCount() const {
- return statistics_.audio_bytes_decoded;
-}
-
-size_t MediaSourceDelegate::VideoDecodedByteCount() const {
- return statistics_.video_bytes_decoded;
-}
-
-void MediaSourceDelegate::CancelPendingSeek(const base::TimeDelta& seek_time) {
- DCHECK(main_task_runner_->BelongsToCurrentThread());
- DVLOG(1) << __FUNCTION__ << "(" << seek_time.InSecondsF() << ") : "
- << demuxer_client_id_;
-
- if (!chunk_demuxer_)
- return;
-
- {
- // Remember to trivially finish any newly arriving browser seek requests
- // that may arrive prior to the next regular seek request.
- base::AutoLock auto_lock(seeking_lock_);
- expecting_regular_seek_ = true;
- }
-
- // Cancel any previously expected or in-progress regular or browser seek.
- // It is possible that we have just finished the seek, but caller does
- // not know this yet. It is still safe to cancel in this case because the
- // caller will always call StartWaitingForSeek() when it is notified of
- // the finished seek.
- chunk_demuxer_->CancelPendingSeek(seek_time);
-}
-
-void MediaSourceDelegate::StartWaitingForSeek(
- const base::TimeDelta& seek_time) {
- DCHECK(main_task_runner_->BelongsToCurrentThread());
- DVLOG(1) << __FUNCTION__ << "(" << seek_time.InSecondsF() << ") : "
- << demuxer_client_id_;
-
- if (!chunk_demuxer_)
- return;
-
- bool cancel_browser_seek = false;
- {
- // Remember to trivially finish any newly arriving browser seek requests
- // that may arrive prior to the next regular seek request.
- base::AutoLock auto_lock(seeking_lock_);
- expecting_regular_seek_ = true;
-
- // Remember to cancel any in-progress browser seek.
- if (seeking_) {
- DCHECK(doing_browser_seek_);
- cancel_browser_seek = true;
- }
- }
-
- if (cancel_browser_seek)
- chunk_demuxer_->CancelPendingSeek(seek_time);
- chunk_demuxer_->StartWaitingForSeek(seek_time);
-}
-
-void MediaSourceDelegate::Seek(
- const base::TimeDelta& seek_time, bool is_browser_seek) {
- DCHECK(media_task_runner_->BelongsToCurrentThread());
- DVLOG(1) << __FUNCTION__ << "(" << seek_time.InSecondsF() << ", "
- << (is_browser_seek ? "browser seek" : "regular seek") << ") : "
- << demuxer_client_id_;
-
- base::TimeDelta internal_seek_time = seek_time;
- {
- base::AutoLock auto_lock(seeking_lock_);
- DCHECK(!seeking_);
- seeking_ = true;
- doing_browser_seek_ = is_browser_seek;
-
- if (doing_browser_seek_ && (!chunk_demuxer_ || expecting_regular_seek_)) {
- // Trivially finish the browser seek without actually doing it. Reads will
- // continue to be |kAborted| until the next regular seek is done. Browser
- // seeking is not supported unless using a ChunkDemuxer; browser seeks are
- // trivially finished if |chunk_demuxer_| is NULL.
- seeking_ = false;
- doing_browser_seek_ = false;
- demuxer_client_->DemuxerSeekDone(demuxer_client_id_, seek_time);
- return;
- }
-
- if (doing_browser_seek_) {
- internal_seek_time = FindBufferedBrowserSeekTime_Locked(seek_time);
- browser_seek_time_ = internal_seek_time;
- } else {
- expecting_regular_seek_ = false;
- browser_seek_time_ = media::kNoTimestamp;
- }
- }
-
- // Prepare |chunk_demuxer_| for browser seek.
- if (is_browser_seek) {
- chunk_demuxer_->CancelPendingSeek(internal_seek_time);
- chunk_demuxer_->StartWaitingForSeek(internal_seek_time);
- }
-
- SeekInternal(internal_seek_time);
-}
-
-void MediaSourceDelegate::SeekInternal(const base::TimeDelta& seek_time) {
- DCHECK(media_task_runner_->BelongsToCurrentThread());
- DCHECK(IsSeeking());
- chunk_demuxer_->Seek(seek_time, base::Bind(
- &MediaSourceDelegate::OnDemuxerSeekDone,
- media_weak_factory_.GetWeakPtr()));
-}
-
-void MediaSourceDelegate::OnBufferedTimeRangesChanged(
- const media::Ranges<base::TimeDelta>& ranges) {
- buffered_time_ranges_ = ranges;
-}
-
-void MediaSourceDelegate::SetDuration(base::TimeDelta duration) {
- DCHECK(main_task_runner_->BelongsToCurrentThread());
- DVLOG(1) << __FUNCTION__ << "(" << duration.InSecondsF() << ") : "
- << demuxer_client_id_;
-
- // Force duration change notification to be async to avoid reentrancy into
- // ChunkDemxuer.
- main_task_runner_->PostTask(FROM_HERE, base::Bind(
- &MediaSourceDelegate::OnDurationChanged, main_weak_this_, duration));
-}
-
-void MediaSourceDelegate::OnDurationChanged(const base::TimeDelta& duration) {
- DCHECK(main_task_runner_->BelongsToCurrentThread());
- if (demuxer_client_)
- demuxer_client_->DurationChanged(demuxer_client_id_, duration);
- if (!duration_change_cb_.is_null())
- duration_change_cb_.Run(duration);
-}
-
-void MediaSourceDelegate::OnReadFromDemuxer(media::DemuxerStream::Type type) {
- DCHECK(media_task_runner_->BelongsToCurrentThread());
- DVLOG(1) << __FUNCTION__ << "(" << type << ") : " << demuxer_client_id_;
- if (IsSeeking())
- return; // Drop the request during seeking.
-
- DCHECK(type == DemuxerStream::AUDIO || type == DemuxerStream::VIDEO);
- // The access unit size should have been initialized properly at this stage.
- DCHECK_GT(access_unit_size_, 0u);
- std::unique_ptr<DemuxerData> data(new DemuxerData());
- data->type = type;
- data->access_units.resize(access_unit_size_);
- ReadFromDemuxerStream(type, std::move(data), 0);
-}
-
-void MediaSourceDelegate::ReadFromDemuxerStream(
- media::DemuxerStream::Type type,
- std::unique_ptr<DemuxerData> data,
- size_t index) {
- DCHECK(media_task_runner_->BelongsToCurrentThread());
- // DemuxerStream::Read() always returns the read callback asynchronously.
- DemuxerStream* stream =
- (type == DemuxerStream::AUDIO) ? audio_stream_ : video_stream_;
- stream->Read(base::Bind(
- &MediaSourceDelegate::OnBufferReady,
- media_weak_factory_.GetWeakPtr(), type, base::Passed(&data), index));
-}
-
-void MediaSourceDelegate::OnBufferReady(
- media::DemuxerStream::Type type,
- std::unique_ptr<DemuxerData> data,
- size_t index,
- DemuxerStream::Status status,
- const scoped_refptr<media::DecoderBuffer>& buffer) {
- DCHECK(media_task_runner_->BelongsToCurrentThread());
- DVLOG(1) << __FUNCTION__ << "(" << index << ", " << status << ", "
- << ((!buffer.get() || buffer->end_of_stream())
- ? -1
- : buffer->timestamp().InMilliseconds())
- << ") : " << demuxer_client_id_;
- DCHECK(chunk_demuxer_);
-
- // No new OnReadFromDemuxer() will be called during seeking. So this callback
- // must be from previous OnReadFromDemuxer() call and should be ignored.
- if (IsSeeking()) {
- DVLOG(1) << __FUNCTION__ << ": Ignore previous read during seeking.";
- return;
- }
-
- bool is_audio = (type == DemuxerStream::AUDIO);
- if (status != DemuxerStream::kAborted &&
- index >= data->access_units.size()) {
- LOG(ERROR) << "The internal state inconsistency onBufferReady: "
- << (is_audio ? "Audio" : "Video") << ", index " << index
- << ", size " << data->access_units.size()
- << ", status " << static_cast<int>(status);
- NOTREACHED();
- return;
- }
-
- switch (status) {
- case DemuxerStream::kAborted:
- DVLOG(1) << __FUNCTION__ << " : Aborted";
- data->access_units[index].status = status;
- data->access_units.resize(index + 1);
- break;
-
- case DemuxerStream::kConfigChanged:
- CHECK((is_audio && audio_stream_) || (!is_audio && video_stream_));
- data->demuxer_configs.resize(1);
- CHECK(GetDemuxerConfigFromStream(&data->demuxer_configs[0], is_audio));
- if (!is_audio) {
- gfx::Size size = data->demuxer_configs[0].video_size;
- DVLOG(1) << "Video config is changed: " << size.width() << "x"
- << size.height();
- }
- data->access_units[index].status = status;
- data->access_units.resize(index + 1);
- break;
-
- case DemuxerStream::kOk:
- data->access_units[index].status = status;
- if (buffer->end_of_stream()) {
- data->access_units[index].is_end_of_stream = true;
- data->access_units.resize(index + 1);
- break;
- }
- data->access_units[index].is_key_frame = buffer->is_key_frame();
- // TODO(ycheo): We assume that the inputed stream will be decoded
- // right away.
- // Need to implement this properly using MediaPlayer.OnInfoListener.
- if (is_audio) {
- statistics_.audio_bytes_decoded += buffer->data_size();
- } else {
- statistics_.video_bytes_decoded += buffer->data_size();
- statistics_.video_frames_decoded++;
- }
- data->access_units[index].timestamp = buffer->timestamp();
-
- data->access_units[index].data.assign(
- buffer->data(), buffer->data() + buffer->data_size());
- // Vorbis needs 4 extra bytes padding on Android. Check
- // NuMediaExtractor.cpp in Android source code.
- if (is_audio && media::kCodecVorbis ==
- audio_stream_->audio_decoder_config().codec()) {
- data->access_units[index].data.insert(
- data->access_units[index].data.end(), kVorbisPadding,
- kVorbisPadding + 4);
- }
- if (buffer->decrypt_config()) {
- data->access_units[index].key_id = std::vector<char>(
- buffer->decrypt_config()->key_id().begin(),
- buffer->decrypt_config()->key_id().end());
- data->access_units[index].iv = std::vector<char>(
- buffer->decrypt_config()->iv().begin(),
- buffer->decrypt_config()->iv().end());
- data->access_units[index].subsamples =
- buffer->decrypt_config()->subsamples();
- }
- if (++index < data->access_units.size()) {
- ReadFromDemuxerStream(type, std::move(data), index);
- return;
- }
- break;
-
- default:
- NOTREACHED();
- }
-
- if (!IsSeeking() && demuxer_client_)
- demuxer_client_->ReadFromDemuxerAck(demuxer_client_id_, *data);
-}
-
-void MediaSourceDelegate::OnDemuxerError(media::PipelineStatus status) {
- DVLOG(1) << __FUNCTION__ << "(" << status << ") : " << demuxer_client_id_;
- // |update_network_state_cb_| is bound to the main thread.
- if (status != media::PIPELINE_OK && !update_network_state_cb_.is_null())
- update_network_state_cb_.Run(PipelineErrorToNetworkState(status));
-}
-
-void MediaSourceDelegate::AddTextStream(
- media::DemuxerStream* /* text_stream */ ,
- const media::TextTrackConfig& /* config */ ) {
- // TODO(matthewjheaney): add text stream (http://crbug/322115).
- NOTIMPLEMENTED();
-}
-
-void MediaSourceDelegate::RemoveTextStream(
- media::DemuxerStream* /* text_stream */ ) {
- // TODO(matthewjheaney): remove text stream (http://crbug/322115).
- NOTIMPLEMENTED();
-}
-
-void MediaSourceDelegate::OnDemuxerInitDone(media::PipelineStatus status) {
- DCHECK(media_task_runner_->BelongsToCurrentThread());
- DVLOG(1) << __FUNCTION__ << "(" << status << ") : " << demuxer_client_id_;
- DCHECK(chunk_demuxer_);
-
- if (status != media::PIPELINE_OK) {
- OnDemuxerError(status);
- return;
- }
-
- audio_stream_ = chunk_demuxer_->GetStream(DemuxerStream::AUDIO);
- video_stream_ = chunk_demuxer_->GetStream(DemuxerStream::VIDEO);
- DCHECK(audio_stream_ || video_stream_);
-
- if (HasEncryptedStream()) {
- set_cdm_ready_cb_.Run(BindToCurrentLoop(base::Bind(
- &MediaSourceDelegate::SetCdm, media_weak_factory_.GetWeakPtr())));
- return;
- }
-
- // Notify demuxer ready when both streams are not encrypted.
- NotifyDemuxerReady(false);
-}
-
-bool MediaSourceDelegate::HasEncryptedStream() {
- DCHECK(media_task_runner_->BelongsToCurrentThread());
- DCHECK(audio_stream_ || video_stream_);
-
- return (audio_stream_ &&
- audio_stream_->audio_decoder_config().is_encrypted()) ||
- (video_stream_ &&
- video_stream_->video_decoder_config().is_encrypted());
-}
-
-void MediaSourceDelegate::SetCdm(media::CdmContext* cdm_context,
- const media::CdmAttachedCB& cdm_attached_cb) {
- DCHECK(media_task_runner_->BelongsToCurrentThread());
- DCHECK(cdm_context);
- DCHECK(!cdm_attached_cb.is_null());
- DCHECK(!is_demuxer_ready_);
- DCHECK(HasEncryptedStream());
-
- cdm_context_ = cdm_context;
- pending_cdm_attached_cb_ = cdm_attached_cb;
-
- if (audio_stream_ && audio_stream_->audio_decoder_config().is_encrypted()) {
- InitAudioDecryptingDemuxerStream();
- // InitVideoDecryptingDemuxerStream() will be called in
- // OnAudioDecryptingDemuxerStreamInitDone().
- return;
- }
-
- if (video_stream_ && video_stream_->video_decoder_config().is_encrypted()) {
- InitVideoDecryptingDemuxerStream();
- return;
- }
-
- NOTREACHED() << "No encrytped stream.";
-}
-
-void MediaSourceDelegate::InitAudioDecryptingDemuxerStream() {
- DCHECK(media_task_runner_->BelongsToCurrentThread());
- DVLOG(1) << __FUNCTION__ << " : " << demuxer_client_id_;
- DCHECK(cdm_context_);
- audio_decrypting_demuxer_stream_.reset(new media::DecryptingDemuxerStream(
- media_task_runner_, media_log_, waiting_for_decryption_key_cb_));
- audio_decrypting_demuxer_stream_->Initialize(
- audio_stream_, cdm_context_,
- base::Bind(&MediaSourceDelegate::OnAudioDecryptingDemuxerStreamInitDone,
- media_weak_factory_.GetWeakPtr()));
-}
-
-void MediaSourceDelegate::InitVideoDecryptingDemuxerStream() {
- DCHECK(media_task_runner_->BelongsToCurrentThread());
- DVLOG(1) << __FUNCTION__ << " : " << demuxer_client_id_;
- DCHECK(cdm_context_);
-
- video_decrypting_demuxer_stream_.reset(new media::DecryptingDemuxerStream(
- media_task_runner_, media_log_, waiting_for_decryption_key_cb_));
- video_decrypting_demuxer_stream_->Initialize(
- video_stream_, cdm_context_,
- base::Bind(&MediaSourceDelegate::OnVideoDecryptingDemuxerStreamInitDone,
- media_weak_factory_.GetWeakPtr()));
-}
-
-void MediaSourceDelegate::OnAudioDecryptingDemuxerStreamInitDone(
- media::PipelineStatus status) {
- DCHECK(media_task_runner_->BelongsToCurrentThread());
- DVLOG(1) << __FUNCTION__ << "(" << status << ") : " << demuxer_client_id_;
- DCHECK(chunk_demuxer_);
-
- if (status != media::PIPELINE_OK) {
- audio_decrypting_demuxer_stream_.reset();
- // Different CDMs are supported differently. For CDMs that support a
- // Decryptor, we'll try to use DecryptingDemuxerStream in the render side.
- // Otherwise, we'll try to use the CDMs in the browser side. Therefore, if
- // DecryptingDemuxerStream initialization failed, it's still possible that
- // we can handle the audio with a CDM in the browser. Declare demuxer ready
- // now to try that path. Note there's no need to try DecryptingDemuxerStream
- // for video here since it is impossible to handle audio in the browser and
- // handle video in the render process.
- NotifyDemuxerReady(false);
- return;
- }
-
- audio_stream_ = audio_decrypting_demuxer_stream_.get();
-
- if (video_stream_ && video_stream_->video_decoder_config().is_encrypted()) {
- InitVideoDecryptingDemuxerStream();
- return;
- }
-
- // Try to notify demuxer ready when audio DDS initialization finished and
- // video is not encrypted.
- NotifyDemuxerReady(true);
-}
-
-void MediaSourceDelegate::OnVideoDecryptingDemuxerStreamInitDone(
- media::PipelineStatus status) {
- DCHECK(media_task_runner_->BelongsToCurrentThread());
- DVLOG(1) << __FUNCTION__ << "(" << status << ") : " << demuxer_client_id_;
- DCHECK(chunk_demuxer_);
-
- bool success = status == media::PIPELINE_OK;
-
- if (!success)
- video_decrypting_demuxer_stream_.reset();
- else
- video_stream_ = video_decrypting_demuxer_stream_.get();
-
- // Try to notify demuxer ready when video DDS initialization finished.
- NotifyDemuxerReady(success);
-}
-
-void MediaSourceDelegate::OnDemuxerSeekDone(media::PipelineStatus status) {
- DCHECK(media_task_runner_->BelongsToCurrentThread());
- DVLOG(1) << __FUNCTION__ << "(" << status << ") : " << demuxer_client_id_;
- DCHECK(IsSeeking());
-
- if (status != media::PIPELINE_OK) {
- OnDemuxerError(status);
- return;
- }
-
- ResetAudioDecryptingDemuxerStream();
-}
-
-void MediaSourceDelegate::ResetAudioDecryptingDemuxerStream() {
- DCHECK(media_task_runner_->BelongsToCurrentThread());
- DVLOG(1) << __FUNCTION__ << " : " << demuxer_client_id_;
- if (audio_decrypting_demuxer_stream_) {
- audio_decrypting_demuxer_stream_->Reset(
- base::Bind(&MediaSourceDelegate::ResetVideoDecryptingDemuxerStream,
- media_weak_factory_.GetWeakPtr()));
- return;
- }
-
- ResetVideoDecryptingDemuxerStream();
-}
-
-void MediaSourceDelegate::ResetVideoDecryptingDemuxerStream() {
- DCHECK(media_task_runner_->BelongsToCurrentThread());
- DVLOG(1) << __FUNCTION__ << " : " << demuxer_client_id_;
- if (video_decrypting_demuxer_stream_) {
- video_decrypting_demuxer_stream_->Reset(base::Bind(
- &MediaSourceDelegate::FinishResettingDecryptingDemuxerStreams,
- media_weak_factory_.GetWeakPtr()));
- return;
- }
-
- FinishResettingDecryptingDemuxerStreams();
-}
-
-void MediaSourceDelegate::FinishResettingDecryptingDemuxerStreams() {
- DCHECK(media_task_runner_->BelongsToCurrentThread());
- DVLOG(1) << __FUNCTION__ << " : " << demuxer_client_id_;
-
- base::AutoLock auto_lock(seeking_lock_);
- DCHECK(seeking_);
- seeking_ = false;
- doing_browser_seek_ = false;
- demuxer_client_->DemuxerSeekDone(demuxer_client_id_, browser_seek_time_);
-}
-
-void MediaSourceDelegate::NotifyDemuxerReady(bool is_cdm_attached) {
- DCHECK(media_task_runner_->BelongsToCurrentThread());
- DVLOG(1) << __FUNCTION__ << " : " << demuxer_client_id_
- << ", is_cdm_attached: " << is_cdm_attached;
- DCHECK(!is_demuxer_ready_);
-
- is_demuxer_ready_ = true;
-
- if (!pending_cdm_attached_cb_.is_null())
- base::ResetAndReturn(&pending_cdm_attached_cb_).Run(is_cdm_attached);
-
- std::unique_ptr<DemuxerConfigs> configs(new DemuxerConfigs());
- GetDemuxerConfigFromStream(configs.get(), true);
- GetDemuxerConfigFromStream(configs.get(), false);
- configs->duration = GetDuration();
-
- if (demuxer_client_)
- demuxer_client_->DemuxerReady(demuxer_client_id_, *configs);
-
- base::AutoLock auto_lock(is_video_encrypted_lock_);
- is_video_encrypted_ = configs->is_video_encrypted;
-}
-
-base::TimeDelta MediaSourceDelegate::GetDuration() const {
- DCHECK(media_task_runner_->BelongsToCurrentThread());
- if (!chunk_demuxer_)
- return media::kNoTimestamp;
-
- double duration = chunk_demuxer_->GetDuration();
- if (duration == std::numeric_limits<double>::infinity())
- return media::kInfiniteDuration;
-
- return base::TimeDelta::FromSecondsD(duration);
-}
-
-void MediaSourceDelegate::OnDemuxerOpened() {
- DCHECK(main_task_runner_->BelongsToCurrentThread());
- if (media_source_opened_cb_.is_null())
- return;
-
- media_source_opened_cb_.Run(
- new media::WebMediaSourceImpl(chunk_demuxer_.get(), media_log_));
-}
-
-void MediaSourceDelegate::OnEncryptedMediaInitData(
- media::EmeInitDataType init_data_type,
- const std::vector<uint8_t>& init_data) {
- DCHECK(main_task_runner_->BelongsToCurrentThread());
- if (encrypted_media_init_data_cb_.is_null())
- return;
-
- encrypted_media_init_data_cb_.Run(init_data_type, init_data);
-}
-
-bool MediaSourceDelegate::IsSeeking() const {
- base::AutoLock auto_lock(seeking_lock_);
- return seeking_;
-}
-
-base::TimeDelta MediaSourceDelegate::FindBufferedBrowserSeekTime_Locked(
- const base::TimeDelta& seek_time) const {
- seeking_lock_.AssertAcquired();
- DCHECK(seeking_);
- DCHECK(doing_browser_seek_);
- DCHECK(chunk_demuxer_) << "Browser seek requested, but no chunk demuxer";
-
- media::Ranges<base::TimeDelta> buffered =
- chunk_demuxer_->GetBufferedRanges();
-
- for (size_t i = 0; i < buffered.size(); ++i) {
- base::TimeDelta range_start = buffered.start(i);
- base::TimeDelta range_end = buffered.end(i);
- if (range_start <= seek_time) {
- if (range_end >= seek_time)
- return seek_time;
- continue;
- }
-
- // If the start of the next buffered range after |seek_time| is too far
- // into the future, do not jump forward.
- if ((range_start - seek_time) > base::TimeDelta::FromMilliseconds(100))
- break;
-
- // TODO(wolenetz): Remove possibility that this browser seek jumps
- // into future when the requested range is unbuffered but there is some
- // other buffered range after it. See http://crbug.com/304234.
- return range_start;
- }
-
- // We found no range containing |seek_time| or beginning shortly after
- // |seek_time|. While possible that such data at and beyond the player's
- // current time have been garbage collected or removed by the web app, this is
- // unlikely. This may cause unexpected playback stall due to seek pending an
- // append for a GOP prior to the last GOP demuxed.
- // TODO(wolenetz): Remove the possibility for this seek to cause unexpected
- // player stall by replaying cached data since last keyframe in browser player
- // rather than issuing browser seek. See http://crbug.com/304234.
- return seek_time;
-}
-
-bool MediaSourceDelegate::GetDemuxerConfigFromStream(
- media::DemuxerConfigs* configs, bool is_audio) {
- DCHECK(media_task_runner_->BelongsToCurrentThread());
- if (!is_demuxer_ready_)
- return false;
- if (is_audio && audio_stream_) {
- media::AudioDecoderConfig config = audio_stream_->audio_decoder_config();
- configs->audio_codec = config.codec();
- configs->audio_channels =
- media::ChannelLayoutToChannelCount(config.channel_layout());
- configs->audio_sampling_rate = config.samples_per_second();
- configs->is_audio_encrypted = config.is_encrypted();
- configs->audio_extra_data = config.extra_data();
- configs->audio_codec_delay_ns = static_cast<int64_t>(
- config.codec_delay() *
- (static_cast<double>(base::Time::kNanosecondsPerSecond) /
- config.samples_per_second()));
- configs->audio_seek_preroll_ns =
- config.seek_preroll().InMicroseconds() *
- base::Time::kNanosecondsPerMicrosecond;
- return true;
- }
- if (!is_audio && video_stream_) {
- media::VideoDecoderConfig config = video_stream_->video_decoder_config();
- configs->video_codec = config.codec();
- configs->video_size = config.natural_size();
- configs->is_video_encrypted = config.is_encrypted();
- configs->video_extra_data = config.extra_data();
- return true;
- }
- return false;
-}
-
-} // namespace content

Powered by Google App Engine
This is Rietveld 408576698