Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / content / renderer / media / android / media_source_delegate.cc
index bd32e70..504a08f 100644 (file)
 #include "base/message_loop/message_loop_proxy.h"
 #include "base/strings/string_number_conversions.h"
 #include "content/renderer/media/android/renderer_demuxer_android.h"
-#include "content/renderer/media/webmediaplayer_util.h"
-#include "content/renderer/media/webmediasource_impl.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/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"
@@ -48,8 +48,8 @@ static void LogMediaSourceError(const scoped_refptr<media::MediaLog>& media_log,
 MediaSourceDelegate::MediaSourceDelegate(
     RendererDemuxerAndroid* demuxer_client,
     int demuxer_client_id,
-    const scoped_refptr<base::MessageLoopProxy>& media_loop,
-    media::MediaLog* media_log)
+    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),
@@ -62,16 +62,16 @@ MediaSourceDelegate::MediaSourceDelegate(
       browser_seek_time_(media::kNoTimestamp()),
       expecting_regular_seek_(false),
       access_unit_size_(0),
-      main_loop_(base::MessageLoopProxy::current()),
-      media_loop_(media_loop),
+      main_task_runner_(base::MessageLoopProxy::current()),
+      media_task_runner_(media_task_runner),
       main_weak_factory_(this),
       media_weak_factory_(this),
       main_weak_this_(main_weak_factory_.GetWeakPtr()) {
-  DCHECK(main_loop_->BelongsToCurrentThread());
+  DCHECK(main_task_runner_->BelongsToCurrentThread());
 }
 
 MediaSourceDelegate::~MediaSourceDelegate() {
-  DCHECK(main_loop_->BelongsToCurrentThread());
+  DCHECK(main_task_runner_->BelongsToCurrentThread());
   DVLOG(1) << __FUNCTION__ << " : " << demuxer_client_id_;
   DCHECK(!chunk_demuxer_);
   DCHECK(!demuxer_client_);
@@ -81,13 +81,12 @@ MediaSourceDelegate::~MediaSourceDelegate() {
   DCHECK(!video_stream_);
 }
 
-void MediaSourceDelegate::Destroy() {
-  DCHECK(main_loop_->BelongsToCurrentThread());
+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_);
-    delete this;
     return;
   }
 
@@ -100,22 +99,30 @@ void MediaSourceDelegate::Destroy() {
 
   chunk_demuxer_->Shutdown();
 
-  // |this| will be transferred to the callback StopDemuxer() and
-  // OnDemuxerStopDone(). They own |this| and OnDemuxerStopDone() will delete
-  // it when called, hence using base::Unretained(this) is safe here.
-  media_loop_->PostTask(FROM_HERE,
-                        base::Bind(&MediaSourceDelegate::StopDemuxer,
-                        base::Unretained(this)));
+  // 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_loop_->BelongsToCurrentThread());
+  DCHECK(main_task_runner_->BelongsToCurrentThread());
   base::AutoLock auto_lock(is_video_encrypted_lock_);
   return is_video_encrypted_;
 }
 
-void MediaSourceDelegate::StopDemuxer() {
-  DCHECK(media_loop_->BelongsToCurrentThread());
+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_);
@@ -131,10 +138,12 @@ void MediaSourceDelegate::StopDemuxer() {
   media_weak_factory_.InvalidateWeakPtrs();
   DCHECK(!media_weak_factory_.HasWeakPtrs());
 
-  // The callback OnDemuxerStopDone() owns |this| and will delete it when
-  // called. Hence using base::Unretained(this) is safe here.
-  chunk_demuxer_->Stop(base::Bind(&MediaSourceDelegate::OnDemuxerStopDone,
-                                  base::Unretained(this)));
+  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(
@@ -143,7 +152,7 @@ void MediaSourceDelegate::InitializeMediaSource(
     const media::SetDecryptorReadyCB& set_decryptor_ready_cb,
     const UpdateNetworkStateCB& update_network_state_cb,
     const DurationChangeCB& duration_change_cb) {
-  DCHECK(main_loop_->BelongsToCurrentThread());
+  DCHECK(main_task_runner_->BelongsToCurrentThread());
   DCHECK(!media_source_opened_cb.is_null());
   media_source_opened_cb_ = media_source_opened_cb;
   need_key_cb_ = need_key_cb;
@@ -162,13 +171,13 @@ void MediaSourceDelegate::InitializeMediaSource(
 
   // |this| will be retained until StopDemuxer() is posted, so Unretained() is
   // safe here.
-  media_loop_->PostTask(FROM_HERE,
+  media_task_runner_->PostTask(FROM_HERE,
                         base::Bind(&MediaSourceDelegate::InitializeDemuxer,
                         base::Unretained(this)));
 }
 
 void MediaSourceDelegate::InitializeDemuxer() {
-  DCHECK(media_loop_->BelongsToCurrentThread());
+  DCHECK(media_task_runner_->BelongsToCurrentThread());
   demuxer_client_->AddDelegate(demuxer_client_id_, this);
   chunk_demuxer_->Initialize(this,
                              base::Bind(&MediaSourceDelegate::OnDemuxerInitDone,
@@ -176,10 +185,8 @@ void MediaSourceDelegate::InitializeDemuxer() {
                              false);
 }
 
-const blink::WebTimeRanges& MediaSourceDelegate::Buffered() {
-  buffered_web_time_ranges_ =
-      ConvertToWebTimeRanges(buffered_time_ranges_);
-  return buffered_web_time_ranges_;
+blink::WebTimeRanges MediaSourceDelegate::Buffered() const {
+  return media::ConvertToWebTimeRanges(buffered_time_ranges_);
 }
 
 size_t MediaSourceDelegate::DecodedFrameCount() const {
@@ -199,7 +206,7 @@ size_t MediaSourceDelegate::VideoDecodedByteCount() const {
 }
 
 void MediaSourceDelegate::CancelPendingSeek(const base::TimeDelta& seek_time) {
-  DCHECK(main_loop_->BelongsToCurrentThread());
+  DCHECK(main_task_runner_->BelongsToCurrentThread());
   DVLOG(1) << __FUNCTION__ << "(" << seek_time.InSecondsF() << ") : "
            << demuxer_client_id_;
 
@@ -223,7 +230,7 @@ void MediaSourceDelegate::CancelPendingSeek(const base::TimeDelta& seek_time) {
 
 void MediaSourceDelegate::StartWaitingForSeek(
     const base::TimeDelta& seek_time) {
-  DCHECK(main_loop_->BelongsToCurrentThread());
+  DCHECK(main_task_runner_->BelongsToCurrentThread());
   DVLOG(1) << __FUNCTION__ << "(" << seek_time.InSecondsF() << ") : "
            << demuxer_client_id_;
 
@@ -251,7 +258,7 @@ void MediaSourceDelegate::StartWaitingForSeek(
 
 void MediaSourceDelegate::Seek(
     const base::TimeDelta& seek_time, bool is_browser_seek) {
-  DCHECK(media_loop_->BelongsToCurrentThread());
+  DCHECK(media_task_runner_->BelongsToCurrentThread());
   DVLOG(1) << __FUNCTION__ << "(" << seek_time.InSecondsF() << ", "
            << (is_browser_seek ? "browser seek" : "regular seek") << ") : "
            << demuxer_client_id_;
@@ -293,39 +300,31 @@ void MediaSourceDelegate::Seek(
 }
 
 void MediaSourceDelegate::SeekInternal(const base::TimeDelta& seek_time) {
-  DCHECK(media_loop_->BelongsToCurrentThread());
+  DCHECK(media_task_runner_->BelongsToCurrentThread());
   DCHECK(IsSeeking());
   chunk_demuxer_->Seek(seek_time, base::Bind(
       &MediaSourceDelegate::OnDemuxerSeekDone,
       media_weak_factory_.GetWeakPtr()));
 }
 
-void MediaSourceDelegate::SetTotalBytes(int64 total_bytes) {
-  NOTIMPLEMENTED();
-}
-
-void MediaSourceDelegate::AddBufferedByteRange(int64 start, int64 end) {
-  NOTIMPLEMENTED();
-}
-
 void MediaSourceDelegate::AddBufferedTimeRange(base::TimeDelta start,
                                                base::TimeDelta end) {
   buffered_time_ranges_.Add(start, end);
 }
 
 void MediaSourceDelegate::SetDuration(base::TimeDelta duration) {
-  DCHECK(main_loop_->BelongsToCurrentThread());
+  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_loop_->PostTask(FROM_HERE, base::Bind(
+  main_task_runner_->PostTask(FROM_HERE, base::Bind(
       &MediaSourceDelegate::OnDurationChanged, main_weak_this_, duration));
 }
 
 void MediaSourceDelegate::OnDurationChanged(const base::TimeDelta& duration) {
-  DCHECK(main_loop_->BelongsToCurrentThread());
+  DCHECK(main_task_runner_->BelongsToCurrentThread());
   if (demuxer_client_)
     demuxer_client_->DurationChanged(demuxer_client_id_, duration);
   if (!duration_change_cb_.is_null())
@@ -333,7 +332,7 @@ void MediaSourceDelegate::OnDurationChanged(const base::TimeDelta& duration) {
 }
 
 void MediaSourceDelegate::OnReadFromDemuxer(media::DemuxerStream::Type type) {
-  DCHECK(media_loop_->BelongsToCurrentThread());
+  DCHECK(media_task_runner_->BelongsToCurrentThread());
   DVLOG(1) << __FUNCTION__ << "(" << type << ") : " << demuxer_client_id_;
   if (IsSeeking())
     return;  // Drop the request during seeking.
@@ -350,7 +349,7 @@ void MediaSourceDelegate::OnReadFromDemuxer(media::DemuxerStream::Type type) {
 void MediaSourceDelegate::ReadFromDemuxerStream(media::DemuxerStream::Type type,
                                                 scoped_ptr<DemuxerData> data,
                                                 size_t index) {
-  DCHECK(media_loop_->BelongsToCurrentThread());
+  DCHECK(media_task_runner_->BelongsToCurrentThread());
   // DemuxerStream::Read() always returns the read callback asynchronously.
   DemuxerStream* stream =
       (type == DemuxerStream::AUDIO) ? audio_stream_ : video_stream_;
@@ -365,10 +364,11 @@ void MediaSourceDelegate::OnBufferReady(
     size_t index,
     DemuxerStream::Status status,
     const scoped_refptr<media::DecoderBuffer>& buffer) {
-  DCHECK(media_loop_->BelongsToCurrentThread());
+  DCHECK(media_task_runner_->BelongsToCurrentThread());
   DVLOG(1) << __FUNCTION__ << "(" << index << ", " << status << ", "
-           << ((!buffer || buffer->end_of_stream()) ?
-               -1 : buffer->timestamp().InMilliseconds())
+           << ((!buffer.get() || buffer->end_of_stream())
+                   ? -1
+                   : buffer->timestamp().InMilliseconds())
            << ") : " << demuxer_client_id_;
   DCHECK(chunk_demuxer_);
 
@@ -398,14 +398,11 @@ void MediaSourceDelegate::OnBufferReady(
       break;
 
     case DemuxerStream::kConfigChanged:
-      // In case of kConfigChanged, need to read decoder_config once
-      // for the next reads.
-      // TODO(kjyoun): Investigate if we need to use this new config. See
-      // http://crbug.com/255783
-      if (is_audio) {
-        audio_stream_->audio_decoder_config();
-      } else {
-        gfx::Size size = video_stream_->video_decoder_config().coded_size();
+      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();
       }
@@ -486,7 +483,7 @@ void MediaSourceDelegate::RemoveTextStream(
 }
 
 void MediaSourceDelegate::OnDemuxerInitDone(media::PipelineStatus status) {
-  DCHECK(media_loop_->BelongsToCurrentThread());
+  DCHECK(media_task_runner_->BelongsToCurrentThread());
   DVLOG(1) << __FUNCTION__ << "(" << status << ") : " << demuxer_client_id_;
   DCHECK(chunk_demuxer_);
 
@@ -514,17 +511,16 @@ void MediaSourceDelegate::OnDemuxerInitDone(media::PipelineStatus status) {
 
   // Notify demuxer ready when both streams are not encrypted.
   is_demuxer_ready_ = true;
-  if (CanNotifyDemuxerReady())
-    NotifyDemuxerReady();
+  NotifyDemuxerReady();
 }
 
 void MediaSourceDelegate::InitAudioDecryptingDemuxerStream() {
-  DCHECK(media_loop_->BelongsToCurrentThread());
+  DCHECK(media_task_runner_->BelongsToCurrentThread());
   DVLOG(1) << __FUNCTION__ << " : " << demuxer_client_id_;
   DCHECK(!set_decryptor_ready_cb_.is_null());
 
   audio_decrypting_demuxer_stream_.reset(new media::DecryptingDemuxerStream(
-      media_loop_, set_decryptor_ready_cb_));
+      media_task_runner_, set_decryptor_ready_cb_));
   audio_decrypting_demuxer_stream_->Initialize(
       audio_stream_,
       base::Bind(&MediaSourceDelegate::OnAudioDecryptingDemuxerStreamInitDone,
@@ -532,12 +528,12 @@ void MediaSourceDelegate::InitAudioDecryptingDemuxerStream() {
 }
 
 void MediaSourceDelegate::InitVideoDecryptingDemuxerStream() {
-  DCHECK(media_loop_->BelongsToCurrentThread());
+  DCHECK(media_task_runner_->BelongsToCurrentThread());
   DVLOG(1) << __FUNCTION__ << " : " << demuxer_client_id_;
   DCHECK(!set_decryptor_ready_cb_.is_null());
 
   video_decrypting_demuxer_stream_.reset(new media::DecryptingDemuxerStream(
-      media_loop_, set_decryptor_ready_cb_));
+      media_task_runner_, set_decryptor_ready_cb_));
   video_decrypting_demuxer_stream_->Initialize(
       video_stream_,
       base::Bind(&MediaSourceDelegate::OnVideoDecryptingDemuxerStreamInitDone,
@@ -546,7 +542,7 @@ void MediaSourceDelegate::InitVideoDecryptingDemuxerStream() {
 
 void MediaSourceDelegate::OnAudioDecryptingDemuxerStreamInitDone(
     media::PipelineStatus status) {
-  DCHECK(media_loop_->BelongsToCurrentThread());
+  DCHECK(media_task_runner_->BelongsToCurrentThread());
   DVLOG(1) << __FUNCTION__ << "(" << status << ") : " << demuxer_client_id_;
   DCHECK(chunk_demuxer_);
 
@@ -563,13 +559,12 @@ void MediaSourceDelegate::OnAudioDecryptingDemuxerStreamInitDone(
   // Try to notify demuxer ready when audio DDS initialization finished and
   // video is not encrypted.
   is_demuxer_ready_ = true;
-  if (CanNotifyDemuxerReady())
-    NotifyDemuxerReady();
+  NotifyDemuxerReady();
 }
 
 void MediaSourceDelegate::OnVideoDecryptingDemuxerStreamInitDone(
     media::PipelineStatus status) {
-  DCHECK(media_loop_->BelongsToCurrentThread());
+  DCHECK(media_task_runner_->BelongsToCurrentThread());
   DVLOG(1) << __FUNCTION__ << "(" << status << ") : " << demuxer_client_id_;
   DCHECK(chunk_demuxer_);
 
@@ -580,12 +575,11 @@ void MediaSourceDelegate::OnVideoDecryptingDemuxerStreamInitDone(
 
   // Try to notify demuxer ready when video DDS initialization finished.
   is_demuxer_ready_ = true;
-  if (CanNotifyDemuxerReady())
-    NotifyDemuxerReady();
+  NotifyDemuxerReady();
 }
 
 void MediaSourceDelegate::OnDemuxerSeekDone(media::PipelineStatus status) {
-  DCHECK(media_loop_->BelongsToCurrentThread());
+  DCHECK(media_task_runner_->BelongsToCurrentThread());
   DVLOG(1) << __FUNCTION__ << "(" << status << ") : " << demuxer_client_id_;
   DCHECK(IsSeeking());
 
@@ -598,7 +592,7 @@ void MediaSourceDelegate::OnDemuxerSeekDone(media::PipelineStatus status) {
 }
 
 void MediaSourceDelegate::ResetAudioDecryptingDemuxerStream() {
-  DCHECK(media_loop_->BelongsToCurrentThread());
+  DCHECK(media_task_runner_->BelongsToCurrentThread());
   DVLOG(1) << __FUNCTION__ << " : " << demuxer_client_id_;
   if (audio_decrypting_demuxer_stream_) {
     audio_decrypting_demuxer_stream_->Reset(
@@ -611,7 +605,7 @@ void MediaSourceDelegate::ResetAudioDecryptingDemuxerStream() {
 }
 
 void MediaSourceDelegate::ResetVideoDecryptingDemuxerStream() {
-  DCHECK(media_loop_->BelongsToCurrentThread());
+  DCHECK(media_task_runner_->BelongsToCurrentThread());
   DVLOG(1) << __FUNCTION__ << " : " << demuxer_client_id_;
   if (video_decrypting_demuxer_stream_) {
     video_decrypting_demuxer_stream_->Reset(base::Bind(
@@ -624,7 +618,7 @@ void MediaSourceDelegate::ResetVideoDecryptingDemuxerStream() {
 }
 
 void MediaSourceDelegate::FinishResettingDecryptingDemuxerStreams() {
-  DCHECK(media_loop_->BelongsToCurrentThread());
+  DCHECK(media_task_runner_->BelongsToCurrentThread());
   DVLOG(1) << __FUNCTION__ << " : " << demuxer_client_id_;
 
   base::AutoLock auto_lock(seeking_lock_);
@@ -634,58 +628,15 @@ void MediaSourceDelegate::FinishResettingDecryptingDemuxerStreams() {
   demuxer_client_->DemuxerSeekDone(demuxer_client_id_, browser_seek_time_);
 }
 
-void MediaSourceDelegate::OnDemuxerStopDone() {
-  DCHECK(media_loop_->BelongsToCurrentThread());
-  DVLOG(1) << __FUNCTION__ << " : " << demuxer_client_id_;
-  main_loop_->PostTask(
-      FROM_HERE,
-      base::Bind(&MediaSourceDelegate::DeleteSelf, base::Unretained(this)));
-}
-
-void MediaSourceDelegate::DeleteSelf() {
-  DCHECK(main_loop_->BelongsToCurrentThread());
-  DVLOG(1) << __FUNCTION__ << " : " << demuxer_client_id_;
-  chunk_demuxer_.reset();
-  delete this;
-}
-
-void MediaSourceDelegate::OnMediaConfigRequest() {
-  DCHECK(media_loop_->BelongsToCurrentThread());
-  DVLOG(1) << __FUNCTION__ << " : " << demuxer_client_id_;
-  if (CanNotifyDemuxerReady())
-    NotifyDemuxerReady();
-}
-
-bool MediaSourceDelegate::CanNotifyDemuxerReady() {
-  DCHECK(media_loop_->BelongsToCurrentThread());
-  return is_demuxer_ready_;
-}
-
 void MediaSourceDelegate::NotifyDemuxerReady() {
-  DCHECK(media_loop_->BelongsToCurrentThread());
+  DCHECK(media_task_runner_->BelongsToCurrentThread());
   DVLOG(1) << __FUNCTION__ << " : " << demuxer_client_id_;
-  DCHECK(CanNotifyDemuxerReady());
+  DCHECK(is_demuxer_ready_);
 
   scoped_ptr<DemuxerConfigs> configs(new DemuxerConfigs());
-  if (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 = std::vector<uint8>(
-        config.extra_data(), config.extra_data() + config.extra_data_size());
-  }
-  if (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 = std::vector<uint8>(
-        config.extra_data(), config.extra_data() + config.extra_data_size());
-  }
-  configs->duration_ms = GetDurationMs();
+  GetDemuxerConfigFromStream(configs.get(), true);
+  GetDemuxerConfigFromStream(configs.get(), false);
+  configs->duration = GetDuration();
 
   if (demuxer_client_)
     demuxer_client_->DemuxerReady(demuxer_client_id_, *configs);
@@ -694,32 +645,30 @@ void MediaSourceDelegate::NotifyDemuxerReady() {
   is_video_encrypted_ = configs->is_video_encrypted;
 }
 
-int MediaSourceDelegate::GetDurationMs() {
-  DCHECK(media_loop_->BelongsToCurrentThread());
+base::TimeDelta MediaSourceDelegate::GetDuration() const {
+  DCHECK(media_task_runner_->BelongsToCurrentThread());
   if (!chunk_demuxer_)
-    return -1;
+    return media::kNoTimestamp();
 
-  double duration_ms = chunk_demuxer_->GetDuration() * 1000;
-  if (duration_ms > std::numeric_limits<int32>::max()) {
-    LOG(WARNING) << "Duration from ChunkDemuxer is too large; probably "
-                    "something has gone wrong.";
-    return std::numeric_limits<int32>::max();
-  }
-  return duration_ms;
+  double duration = chunk_demuxer_->GetDuration();
+  if (duration == std::numeric_limits<double>::infinity())
+    return media::kInfiniteDuration();
+
+  return media::ConvertSecondsToTimestamp(duration);
 }
 
 void MediaSourceDelegate::OnDemuxerOpened() {
-  DCHECK(main_loop_->BelongsToCurrentThread());
+  DCHECK(main_task_runner_->BelongsToCurrentThread());
   if (media_source_opened_cb_.is_null())
     return;
 
-  media_source_opened_cb_.Run(new WebMediaSourceImpl(
+  media_source_opened_cb_.Run(new media::WebMediaSourceImpl(
       chunk_demuxer_.get(), base::Bind(&LogMediaSourceError, media_log_)));
 }
 
 void MediaSourceDelegate::OnNeedKey(const std::string& type,
                                     const std::vector<uint8>& init_data) {
-  DCHECK(main_loop_->BelongsToCurrentThread());
+  DCHECK(main_task_runner_->BelongsToCurrentThread());
   if (need_key_cb_.is_null())
     return;
 
@@ -772,4 +721,32 @@ base::TimeDelta MediaSourceDelegate::FindBufferedBrowserSeekTime_Locked(
   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 = std::vector<uint8>(
+        config.extra_data(), config.extra_data() + config.extra_data_size());
+    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 = std::vector<uint8>(
+        config.extra_data(), config.extra_data() + config.extra_data_size());
+    return true;
+  }
+  return false;
+}
+
 }  // namespace content