media_source_delegate.cc revision f8ee788a64d60abd8f2d742a5fdedde054ecd910
1868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved.
2c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
3c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// found in the LICENSE file.
4c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
5eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "content/renderer/media/android/media_source_delegate.h"
6c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include <limits>
858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include <string>
958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include <vector>
1058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
11868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/message_loop/message_loop_proxy.h"
12c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/strings/string_number_conversions.h"
13d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "content/renderer/media/android/renderer_demuxer_android.h"
147dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "content/renderer/media/webmediaplayer_util.h"
153551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "content/renderer/media/webmediasource_impl.h"
16c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "media/base/android/demuxer_stream_player_params.h"
175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "media/base/bind_to_current_loop.h"
18c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "media/base/demuxer_stream.h"
19c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "media/base/media_log.h"
20c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "media/filters/chunk_demuxer.h"
21eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "media/filters/decrypting_demuxer_stream.h"
22868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "third_party/WebKit/public/platform/WebString.h"
237d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "third_party/WebKit/public/web/WebRuntimeFeatures.h"
24c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
25c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)using media::DemuxerStream;
26424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)using media::DemuxerConfigs;
27424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)using media::DemuxerData;
28f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)using blink::WebMediaPlayer;
29f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)using blink::WebString;
30c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
31c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)namespace {
32c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
33868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// The size of the access unit to transfer in an IPC in case of MediaSource.
3423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)// 4: approximately 64ms of content in 60 fps movies.
3523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)const size_t kAccessUnitSizeForMediaSource = 4;
36c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)const uint8 kVorbisPadding[] = { 0xff, 0xff, 0xff, 0xff };
3890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
39c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}  // namespace
40c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
41eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochnamespace content {
42eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
43c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)static void LogMediaSourceError(const scoped_refptr<media::MediaLog>& media_log,
44c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                const std::string& error) {
45c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  media_log->AddEvent(media_log->CreateMediaSourceErrorEvent(error));
46c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
47c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
483551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)MediaSourceDelegate::MediaSourceDelegate(
49d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    RendererDemuxerAndroid* demuxer_client,
50d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    int demuxer_client_id,
513551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    const scoped_refptr<base::MessageLoopProxy>& media_loop,
523551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    media::MediaLog* media_log)
5323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    : demuxer_client_(demuxer_client),
54d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      demuxer_client_id_(demuxer_client_id),
55c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      media_log_(media_log),
56eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      is_demuxer_ready_(false),
57eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      audio_stream_(NULL),
58eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      video_stream_(NULL),
59868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      seeking_(false),
605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      is_video_encrypted_(false),
611e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      doing_browser_seek_(false),
621e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      browser_seek_time_(media::kNoTimestamp()),
631e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      expecting_regular_seek_(false),
6423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      access_unit_size_(0),
6523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      main_loop_(base::MessageLoopProxy::current()),
6623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      media_loop_(media_loop),
6723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      main_weak_factory_(this),
6823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      media_weak_factory_(this),
6923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      main_weak_this_(main_weak_factory_.GetWeakPtr()) {
7058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  DCHECK(main_loop_->BelongsToCurrentThread());
71c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
72c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
7390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)MediaSourceDelegate::~MediaSourceDelegate() {
743551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  DCHECK(main_loop_->BelongsToCurrentThread());
75d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  DVLOG(1) << __FUNCTION__ << " : " << demuxer_client_id_;
7690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  DCHECK(!chunk_demuxer_);
77d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  DCHECK(!demuxer_client_);
78eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  DCHECK(!audio_decrypting_demuxer_stream_);
79eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  DCHECK(!video_decrypting_demuxer_stream_);
80eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  DCHECK(!audio_stream_);
81eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  DCHECK(!video_stream_);
8290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
8390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
8490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void MediaSourceDelegate::Destroy() {
853551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  DCHECK(main_loop_->BelongsToCurrentThread());
86d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  DVLOG(1) << __FUNCTION__ << " : " << demuxer_client_id_;
87d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!chunk_demuxer_) {
8968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    DCHECK(!demuxer_client_);
9090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    delete this;
9190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return;
9290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
9390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
947d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  duration_change_cb_.Reset();
9590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  update_network_state_cb_.Reset();
963551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  media_source_opened_cb_.Reset();
9790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
9858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  main_weak_factory_.InvalidateWeakPtrs();
9958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  DCHECK(!main_weak_factory_.HasWeakPtrs());
1003551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
1015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  chunk_demuxer_->Shutdown();
10258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
10358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // |this| will be transferred to the callback StopDemuxer() and
10458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // OnDemuxerStopDone(). They own |this| and OnDemuxerStopDone() will delete
10558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // it when called, hence using base::Unretained(this) is safe here.
1063551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  media_loop_->PostTask(FROM_HERE,
1073551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                        base::Bind(&MediaSourceDelegate::StopDemuxer,
1083551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                        base::Unretained(this)));
1093551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
1103551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
1115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool MediaSourceDelegate::IsVideoEncrypted() {
1125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCHECK(main_loop_->BelongsToCurrentThread());
1135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::AutoLock auto_lock(is_video_encrypted_lock_);
1145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return is_video_encrypted_;
1155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
117010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)base::Time MediaSourceDelegate::GetTimelineOffset() const {
118010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  DCHECK(main_loop_->BelongsToCurrentThread());
119010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (!chunk_demuxer_)
120010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    return base::Time();
121010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
122010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  return chunk_demuxer_->GetTimelineOffset();
123010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
124010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
1253551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void MediaSourceDelegate::StopDemuxer() {
12658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  DCHECK(media_loop_->BelongsToCurrentThread());
1275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCHECK(chunk_demuxer_);
1283551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
12968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  demuxer_client_->RemoveDelegate(demuxer_client_id_);
13068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  demuxer_client_ = NULL;
13168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
132eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  audio_stream_ = NULL;
133eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  video_stream_ = NULL;
134eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // TODO(xhwang): Figure out if we need to Reset the DDSs after Seeking or
135eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // before destroying them.
136eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  audio_decrypting_demuxer_stream_.reset();
137eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  video_decrypting_demuxer_stream_.reset();
138eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
13958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  media_weak_factory_.InvalidateWeakPtrs();
14058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  DCHECK(!media_weak_factory_.HasWeakPtrs());
1417dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
1423551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // The callback OnDemuxerStopDone() owns |this| and will delete it when
1433551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // called. Hence using base::Unretained(this) is safe here.
1445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  chunk_demuxer_->Stop(base::Bind(&MediaSourceDelegate::OnDemuxerStopDone,
1455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                  base::Unretained(this)));
14690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
147c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
148868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void MediaSourceDelegate::InitializeMediaSource(
1493551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    const MediaSourceOpenedCB& media_source_opened_cb,
1504e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    const media::Demuxer::NeedKeyCB& need_key_cb,
151eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    const media::SetDecryptorReadyCB& set_decryptor_ready_cb,
1527d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    const UpdateNetworkStateCB& update_network_state_cb,
15368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    const DurationChangeCB& duration_change_cb) {
1543551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  DCHECK(main_loop_->BelongsToCurrentThread());
1553551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  DCHECK(!media_source_opened_cb.is_null());
1563551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  media_source_opened_cb_ = media_source_opened_cb;
157868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  need_key_cb_ = need_key_cb;
158eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  set_decryptor_ready_cb_ = set_decryptor_ready_cb;
1593551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  update_network_state_cb_ = media::BindToCurrentLoop(update_network_state_cb);
160d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  duration_change_cb_ = duration_change_cb;
161eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  access_unit_size_ = kAccessUnitSizeForMediaSource;
162c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
163c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  chunk_demuxer_.reset(new media::ChunkDemuxer(
164effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      media::BindToCurrentLoop(
165effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch          base::Bind(&MediaSourceDelegate::OnDemuxerOpened, main_weak_this_)),
166effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      media::BindToCurrentLoop(
167effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch          base::Bind(&MediaSourceDelegate::OnNeedKey, main_weak_this_)),
168effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      base::Bind(&LogMediaSourceError, media_log_),
169effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      false));
170eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
1713551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // |this| will be retained until StopDemuxer() is posted, so Unretained() is
1723551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // safe here.
1733551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  media_loop_->PostTask(FROM_HERE,
1743551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                        base::Bind(&MediaSourceDelegate::InitializeDemuxer,
1753551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                        base::Unretained(this)));
1763551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
1773551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
1783551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void MediaSourceDelegate::InitializeDemuxer() {
17958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  DCHECK(media_loop_->BelongsToCurrentThread());
18068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  demuxer_client_->AddDelegate(demuxer_client_id_, this);
1815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  chunk_demuxer_->Initialize(this,
1825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                             base::Bind(&MediaSourceDelegate::OnDemuxerInitDone,
183f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                        media_weak_factory_.GetWeakPtr()),
1845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                             false);
185868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
186868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
187cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)blink::WebTimeRanges MediaSourceDelegate::Buffered() const {
188cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return ConvertToWebTimeRanges(buffered_time_ranges_);
189c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
190c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
191c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)size_t MediaSourceDelegate::DecodedFrameCount() const {
192c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return statistics_.video_frames_decoded;
193c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
194c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
195c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)size_t MediaSourceDelegate::DroppedFrameCount() const {
196c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return statistics_.video_frames_dropped;
197c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
198c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
199c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)size_t MediaSourceDelegate::AudioDecodedByteCount() const {
200c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return statistics_.audio_bytes_decoded;
201c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
202c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
203c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)size_t MediaSourceDelegate::VideoDecodedByteCount() const {
204c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return statistics_.video_bytes_decoded;
205c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
206c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
20768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)void MediaSourceDelegate::CancelPendingSeek(const base::TimeDelta& seek_time) {
2083551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  DCHECK(main_loop_->BelongsToCurrentThread());
20968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  DVLOG(1) << __FUNCTION__ << "(" << seek_time.InSecondsF() << ") : "
210d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)           << demuxer_client_id_;
211eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2121e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  if (!chunk_demuxer_)
2131e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    return;
2141e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
2151e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  {
2161e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    // Remember to trivially finish any newly arriving browser seek requests
2171e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    // that may arrive prior to the next regular seek request.
2181e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    base::AutoLock auto_lock(seeking_lock_);
2191e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    expecting_regular_seek_ = true;
220eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
2211e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
2221e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // Cancel any previously expected or in-progress regular or browser seek.
2231e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // It is possible that we have just finished the seek, but caller does
2241e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // not know this yet. It is still safe to cancel in this case because the
2251e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // caller will always call StartWaitingForSeek() when it is notified of
2261e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // the finished seek.
2271e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  chunk_demuxer_->CancelPendingSeek(seek_time);
22868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
229eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
23068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)void MediaSourceDelegate::StartWaitingForSeek(
23168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    const base::TimeDelta& seek_time) {
23268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  DCHECK(main_loop_->BelongsToCurrentThread());
23368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  DVLOG(1) << __FUNCTION__ << "(" << seek_time.InSecondsF() << ") : "
23468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)           << demuxer_client_id_;
23568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
2361e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  if (!chunk_demuxer_)
2371e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    return;
2381e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
2391e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  bool cancel_browser_seek = false;
2401e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  {
2411e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    // Remember to trivially finish any newly arriving browser seek requests
2421e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    // that may arrive prior to the next regular seek request.
2431e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    base::AutoLock auto_lock(seeking_lock_);
2441e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    expecting_regular_seek_ = true;
2451e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
2461e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    // Remember to cancel any in-progress browser seek.
2471e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    if (seeking_) {
2481e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      DCHECK(doing_browser_seek_);
2491e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      cancel_browser_seek = true;
2501e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    }
2511e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  }
2521e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
2531e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  if (cancel_browser_seek)
2541e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    chunk_demuxer_->CancelPendingSeek(seek_time);
2551e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  chunk_demuxer_->StartWaitingForSeek(seek_time);
25668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
25768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
2581e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)void MediaSourceDelegate::Seek(
2591e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    const base::TimeDelta& seek_time, bool is_browser_seek) {
26068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  DCHECK(media_loop_->BelongsToCurrentThread());
2611e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  DVLOG(1) << __FUNCTION__ << "(" << seek_time.InSecondsF() << ", "
2621e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)           << (is_browser_seek ? "browser seek" : "regular seek") << ") : "
26368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)           << demuxer_client_id_;
26468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
2651e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  base::TimeDelta internal_seek_time = seek_time;
2661e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  {
2671e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    base::AutoLock auto_lock(seeking_lock_);
2681e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    DCHECK(!seeking_);
2691e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    seeking_ = true;
2701e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    doing_browser_seek_ = is_browser_seek;
2711e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
2721e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    if (doing_browser_seek_ && (!chunk_demuxer_ || expecting_regular_seek_)) {
2731e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      // Trivially finish the browser seek without actually doing it. Reads will
2741e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      // continue to be |kAborted| until the next regular seek is done. Browser
2751e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      // seeking is not supported unless using a ChunkDemuxer; browser seeks are
2761e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      // trivially finished if |chunk_demuxer_| is NULL.
2771e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      seeking_ = false;
2781e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      doing_browser_seek_ = false;
2791e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      demuxer_client_->DemuxerSeekDone(demuxer_client_id_, seek_time);
2801e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      return;
2811e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    }
2821e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
2831e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    if (doing_browser_seek_) {
2841e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      internal_seek_time = FindBufferedBrowserSeekTime_Locked(seek_time);
2851e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      browser_seek_time_ = internal_seek_time;
2861e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    } else {
2871e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      expecting_regular_seek_ = false;
2881e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      browser_seek_time_ = media::kNoTimestamp();
2891e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    }
2901e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  }
2911e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
2921e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // Prepare |chunk_demuxer_| for browser seek.
2931e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  if (is_browser_seek) {
2941e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    chunk_demuxer_->CancelPendingSeek(internal_seek_time);
2951e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    chunk_demuxer_->StartWaitingForSeek(internal_seek_time);
2961e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  }
2971e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
2981e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  SeekInternal(internal_seek_time);
29968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
30058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
30168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)void MediaSourceDelegate::SeekInternal(const base::TimeDelta& seek_time) {
30258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  DCHECK(media_loop_->BelongsToCurrentThread());
30368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  DCHECK(IsSeeking());
3045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  chunk_demuxer_->Seek(seek_time, base::Bind(
30568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      &MediaSourceDelegate::OnDemuxerSeekDone,
30668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      media_weak_factory_.GetWeakPtr()));
30790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
30890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
309c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void MediaSourceDelegate::AddBufferedTimeRange(base::TimeDelta start,
310c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                               base::TimeDelta end) {
311c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  buffered_time_ranges_.Add(start, end);
312c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
313c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
314c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void MediaSourceDelegate::SetDuration(base::TimeDelta duration) {
315d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  DCHECK(main_loop_->BelongsToCurrentThread());
316d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  DVLOG(1) << __FUNCTION__ << "(" << duration.InSecondsF() << ") : "
317d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)           << demuxer_client_id_;
318d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
319d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  // Force duration change notification to be async to avoid reentrancy into
320d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  // ChunkDemxuer.
321d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  main_loop_->PostTask(FROM_HERE, base::Bind(
322d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      &MediaSourceDelegate::OnDurationChanged, main_weak_this_, duration));
323d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)}
324d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
325d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)void MediaSourceDelegate::OnDurationChanged(const base::TimeDelta& duration) {
326d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  DCHECK(main_loop_->BelongsToCurrentThread());
327d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  if (demuxer_client_)
328d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    demuxer_client_->DurationChanged(demuxer_client_id_, duration);
3297d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  if (!duration_change_cb_.is_null())
3307d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    duration_change_cb_.Run(duration);
331c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
332c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
333eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid MediaSourceDelegate::OnReadFromDemuxer(media::DemuxerStream::Type type) {
33458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  DCHECK(media_loop_->BelongsToCurrentThread());
335d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  DVLOG(1) << __FUNCTION__ << "(" << type << ") : " << demuxer_client_id_;
3363551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (IsSeeking())
337eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return;  // Drop the request during seeking.
338c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
339c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(type == DemuxerStream::AUDIO || type == DemuxerStream::VIDEO);
340868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // The access unit size should have been initialized properly at this stage.
341868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK_GT(access_unit_size_, 0u);
342424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  scoped_ptr<DemuxerData> data(new DemuxerData());
343424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  data->type = type;
344424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  data->access_units.resize(access_unit_size_);
345424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  ReadFromDemuxerStream(type, data.Pass(), 0);
346c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
347c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
348424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)void MediaSourceDelegate::ReadFromDemuxerStream(media::DemuxerStream::Type type,
349424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)                                                scoped_ptr<DemuxerData> data,
350424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)                                                size_t index) {
35158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  DCHECK(media_loop_->BelongsToCurrentThread());
352eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // DemuxerStream::Read() always returns the read callback asynchronously.
353eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  DemuxerStream* stream =
354eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      (type == DemuxerStream::AUDIO) ? audio_stream_ : video_stream_;
3553551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  stream->Read(base::Bind(
3563551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      &MediaSourceDelegate::OnBufferReady,
35758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      media_weak_factory_.GetWeakPtr(), type, base::Passed(&data), index));
358c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
359c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
360c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void MediaSourceDelegate::OnBufferReady(
361eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    media::DemuxerStream::Type type,
362424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    scoped_ptr<DemuxerData> data,
363c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    size_t index,
364c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    DemuxerStream::Status status,
365c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const scoped_refptr<media::DecoderBuffer>& buffer) {
36658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  DCHECK(media_loop_->BelongsToCurrentThread());
367d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  DVLOG(1) << __FUNCTION__ << "(" << index << ", " << status << ", "
368a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)           << ((!buffer || buffer->end_of_stream()) ?
369a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)               -1 : buffer->timestamp().InMilliseconds())
370d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)           << ") : " << demuxer_client_id_;
3715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCHECK(chunk_demuxer_);
372eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
373eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // No new OnReadFromDemuxer() will be called during seeking. So this callback
374eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // must be from previous OnReadFromDemuxer() call and should be ignored.
3753551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (IsSeeking()) {
376d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    DVLOG(1) << __FUNCTION__ << ": Ignore previous read during seeking.";
377eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return;
378eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
379eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
380eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  bool is_audio = (type == DemuxerStream::AUDIO);
381c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (status != DemuxerStream::kAborted &&
382424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      index >= data->access_units.size()) {
383c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    LOG(ERROR) << "The internal state inconsistency onBufferReady: "
384c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)               << (is_audio ? "Audio" : "Video") << ", index " << index
385424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)               << ", size " << data->access_units.size()
386c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)               << ", status " << static_cast<int>(status);
387eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    NOTREACHED();
388c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return;
389c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
390eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
391c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  switch (status) {
392c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    case DemuxerStream::kAborted:
393d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      DVLOG(1) << __FUNCTION__ << " : Aborted";
394424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      data->access_units[index].status = status;
395424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      data->access_units.resize(index + 1);
396424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      break;
397c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
398c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    case DemuxerStream::kConfigChanged:
399cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      CHECK((is_audio && audio_stream_) || (!is_audio && video_stream_));
400cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      data->demuxer_configs.resize(1);
401cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      CHECK(GetDemuxerConfigFromStream(&data->demuxer_configs[0], is_audio));
402cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      if (!is_audio) {
403cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        gfx::Size size = data->demuxer_configs[0].video_size;
404eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        DVLOG(1) << "Video config is changed: " << size.width() << "x"
405eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                 << size.height();
406c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      }
407424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      data->access_units[index].status = status;
408424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      data->access_units.resize(index + 1);
409c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      break;
410c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
411c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    case DemuxerStream::kOk:
412424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      data->access_units[index].status = status;
413ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      if (buffer->end_of_stream()) {
414424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)        data->access_units[index].end_of_stream = true;
415424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)        data->access_units.resize(index + 1);
416c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        break;
417c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      }
418c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      // TODO(ycheo): We assume that the inputed stream will be decoded
419c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      // right away.
420c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      // Need to implement this properly using MediaPlayer.OnInfoListener.
421c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      if (is_audio) {
422ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch        statistics_.audio_bytes_decoded += buffer->data_size();
423c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      } else {
424ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch        statistics_.video_bytes_decoded += buffer->data_size();
425c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        statistics_.video_frames_decoded++;
426c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      }
427424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      data->access_units[index].timestamp = buffer->timestamp();
4284e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
4295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      data->access_units[index].data.assign(
4305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          buffer->data(), buffer->data() + buffer->data_size());
43190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      // Vorbis needs 4 extra bytes padding on Android. Check
43290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      // NuMediaExtractor.cpp in Android source code.
43390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      if (is_audio && media::kCodecVorbis ==
434eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch          audio_stream_->audio_decoder_config().codec()) {
435424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)        data->access_units[index].data.insert(
436424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)            data->access_units[index].data.end(), kVorbisPadding,
43790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)            kVorbisPadding + 4);
43890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      }
439ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      if (buffer->decrypt_config()) {
440424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)        data->access_units[index].key_id = std::vector<char>(
441ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch            buffer->decrypt_config()->key_id().begin(),
442ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch            buffer->decrypt_config()->key_id().end());
443424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)        data->access_units[index].iv = std::vector<char>(
444ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch            buffer->decrypt_config()->iv().begin(),
445ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch            buffer->decrypt_config()->iv().end());
446424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)        data->access_units[index].subsamples =
447ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch            buffer->decrypt_config()->subsamples();
448c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      }
449424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      if (++index < data->access_units.size()) {
450424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)        ReadFromDemuxerStream(type, data.Pass(), index);
451c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        return;
452c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      }
453c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      break;
454c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
455c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    default:
456c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      NOTREACHED();
457c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
458c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
459d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  if (!IsSeeking() && demuxer_client_)
460d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    demuxer_client_->ReadFromDemuxerAck(demuxer_client_id_, *data);
461c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
462c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
463eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid MediaSourceDelegate::OnDemuxerError(media::PipelineStatus status) {
464d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  DVLOG(1) << __FUNCTION__ << "(" << status << ") : " << demuxer_client_id_;
4653551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // |update_network_state_cb_| is bound to the main thread.
46690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (status != media::PIPELINE_OK && !update_network_state_cb_.is_null())
46790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    update_network_state_cb_.Run(PipelineErrorToNetworkState(status));
468c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
469c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
470f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void MediaSourceDelegate::AddTextStream(
471f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    media::DemuxerStream* /* text_stream */ ,
472f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    const media::TextTrackConfig& /* config */ ) {
473f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // TODO(matthewjheaney): add text stream (http://crbug/322115).
474f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  NOTIMPLEMENTED();
475f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
476f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
477f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void MediaSourceDelegate::RemoveTextStream(
478f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    media::DemuxerStream* /* text_stream */ ) {
479f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // TODO(matthewjheaney): remove text stream (http://crbug/322115).
480f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  NOTIMPLEMENTED();
481f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
482f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
483eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid MediaSourceDelegate::OnDemuxerInitDone(media::PipelineStatus status) {
48458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  DCHECK(media_loop_->BelongsToCurrentThread());
485d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  DVLOG(1) << __FUNCTION__ << "(" << status << ") : " << demuxer_client_id_;
4865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCHECK(chunk_demuxer_);
487eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
488eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (status != media::PIPELINE_OK) {
489eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    OnDemuxerError(status);
490eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return;
491eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
492eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
4935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  audio_stream_ = chunk_demuxer_->GetStream(DemuxerStream::AUDIO);
4945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  video_stream_ = chunk_demuxer_->GetStream(DemuxerStream::VIDEO);
495eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
4967dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (audio_stream_ && audio_stream_->audio_decoder_config().is_encrypted() &&
4977dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      !set_decryptor_ready_cb_.is_null()) {
498eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    InitAudioDecryptingDemuxerStream();
499eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    // InitVideoDecryptingDemuxerStream() will be called in
500eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    // OnAudioDecryptingDemuxerStreamInitDone().
501eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return;
502eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
503eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
5047dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (video_stream_ && video_stream_->video_decoder_config().is_encrypted() &&
5057dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      !set_decryptor_ready_cb_.is_null()) {
506eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    InitVideoDecryptingDemuxerStream();
507eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return;
508eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
509eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
510eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Notify demuxer ready when both streams are not encrypted.
511eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  is_demuxer_ready_ = true;
512f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  NotifyDemuxerReady();
513eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
514eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
515eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid MediaSourceDelegate::InitAudioDecryptingDemuxerStream() {
51658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  DCHECK(media_loop_->BelongsToCurrentThread());
517d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  DVLOG(1) << __FUNCTION__ << " : " << demuxer_client_id_;
5187dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  DCHECK(!set_decryptor_ready_cb_.is_null());
5197dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
520eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  audio_decrypting_demuxer_stream_.reset(new media::DecryptingDemuxerStream(
521d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      media_loop_, set_decryptor_ready_cb_));
522eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  audio_decrypting_demuxer_stream_->Initialize(
523eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      audio_stream_,
5243551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      base::Bind(&MediaSourceDelegate::OnAudioDecryptingDemuxerStreamInitDone,
52558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                 media_weak_factory_.GetWeakPtr()));
526eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
527eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
528eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid MediaSourceDelegate::InitVideoDecryptingDemuxerStream() {
52958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  DCHECK(media_loop_->BelongsToCurrentThread());
530d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  DVLOG(1) << __FUNCTION__ << " : " << demuxer_client_id_;
5317dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  DCHECK(!set_decryptor_ready_cb_.is_null());
5327dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
533eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  video_decrypting_demuxer_stream_.reset(new media::DecryptingDemuxerStream(
534d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      media_loop_, set_decryptor_ready_cb_));
535eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  video_decrypting_demuxer_stream_->Initialize(
536eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      video_stream_,
5373551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      base::Bind(&MediaSourceDelegate::OnVideoDecryptingDemuxerStreamInitDone,
53858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                 media_weak_factory_.GetWeakPtr()));
539eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
540eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
541eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid MediaSourceDelegate::OnAudioDecryptingDemuxerStreamInitDone(
542eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    media::PipelineStatus status) {
54358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  DCHECK(media_loop_->BelongsToCurrentThread());
544d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  DVLOG(1) << __FUNCTION__ << "(" << status << ") : " << demuxer_client_id_;
5455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCHECK(chunk_demuxer_);
546eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
547eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (status != media::PIPELINE_OK)
548eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    audio_decrypting_demuxer_stream_.reset();
549eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  else
550eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    audio_stream_ = audio_decrypting_demuxer_stream_.get();
551eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
552eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (video_stream_ && video_stream_->video_decoder_config().is_encrypted()) {
553eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    InitVideoDecryptingDemuxerStream();
554eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return;
555eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
556eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
557eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Try to notify demuxer ready when audio DDS initialization finished and
558eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // video is not encrypted.
559eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  is_demuxer_ready_ = true;
560f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  NotifyDemuxerReady();
561eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
562eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
563eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid MediaSourceDelegate::OnVideoDecryptingDemuxerStreamInitDone(
564c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    media::PipelineStatus status) {
56558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  DCHECK(media_loop_->BelongsToCurrentThread());
566d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  DVLOG(1) << __FUNCTION__ << "(" << status << ") : " << demuxer_client_id_;
5675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCHECK(chunk_demuxer_);
568eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
569eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (status != media::PIPELINE_OK)
570eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    video_decrypting_demuxer_stream_.reset();
571eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  else
572eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    video_stream_ = video_decrypting_demuxer_stream_.get();
573eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
574eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Try to notify demuxer ready when video DDS initialization finished.
575eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  is_demuxer_ready_ = true;
576f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  NotifyDemuxerReady();
577eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
578eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
57968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)void MediaSourceDelegate::OnDemuxerSeekDone(media::PipelineStatus status) {
58058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  DCHECK(media_loop_->BelongsToCurrentThread());
581d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  DVLOG(1) << __FUNCTION__ << "(" << status << ") : " << demuxer_client_id_;
5823551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  DCHECK(IsSeeking());
583eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
584c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (status != media::PIPELINE_OK) {
585c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    OnDemuxerError(status);
586c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return;
587c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
588eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
589eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ResetAudioDecryptingDemuxerStream();
590eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
591eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
592eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid MediaSourceDelegate::ResetAudioDecryptingDemuxerStream() {
59358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  DCHECK(media_loop_->BelongsToCurrentThread());
594d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  DVLOG(1) << __FUNCTION__ << " : " << demuxer_client_id_;
595eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (audio_decrypting_demuxer_stream_) {
596eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    audio_decrypting_demuxer_stream_->Reset(
597eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        base::Bind(&MediaSourceDelegate::ResetVideoDecryptingDemuxerStream,
59858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                   media_weak_factory_.GetWeakPtr()));
59958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    return;
600eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
60158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
60258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  ResetVideoDecryptingDemuxerStream();
603eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
604eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
605eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid MediaSourceDelegate::ResetVideoDecryptingDemuxerStream() {
60658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  DCHECK(media_loop_->BelongsToCurrentThread());
607d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  DVLOG(1) << __FUNCTION__ << " : " << demuxer_client_id_;
608eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (video_decrypting_demuxer_stream_) {
60958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    video_decrypting_demuxer_stream_->Reset(base::Bind(
61058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        &MediaSourceDelegate::FinishResettingDecryptingDemuxerStreams,
61158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        media_weak_factory_.GetWeakPtr()));
61258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    return;
613eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
61458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
61558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  FinishResettingDecryptingDemuxerStreams();
61658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)}
61758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
61858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)void MediaSourceDelegate::FinishResettingDecryptingDemuxerStreams() {
61958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  DCHECK(media_loop_->BelongsToCurrentThread());
620d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  DVLOG(1) << __FUNCTION__ << " : " << demuxer_client_id_;
6211e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
6221e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  base::AutoLock auto_lock(seeking_lock_);
6231e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  DCHECK(seeking_);
6241e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  seeking_ = false;
6251e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  doing_browser_seek_ = false;
6261e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  demuxer_client_->DemuxerSeekDone(demuxer_client_id_, browser_seek_time_);
627c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
628c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
62990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void MediaSourceDelegate::OnDemuxerStopDone() {
6305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCHECK(media_loop_->BelongsToCurrentThread());
6315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DVLOG(1) << __FUNCTION__ << " : " << demuxer_client_id_;
6325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  main_loop_->PostTask(
6335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      FROM_HERE,
6345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      base::Bind(&MediaSourceDelegate::DeleteSelf, base::Unretained(this)));
6355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
6365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
6375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void MediaSourceDelegate::DeleteSelf() {
6383551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  DCHECK(main_loop_->BelongsToCurrentThread());
639d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  DVLOG(1) << __FUNCTION__ << " : " << demuxer_client_id_;
64090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  chunk_demuxer_.reset();
64190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  delete this;
64290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
64390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
644eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid MediaSourceDelegate::NotifyDemuxerReady() {
64558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  DCHECK(media_loop_->BelongsToCurrentThread());
646d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  DVLOG(1) << __FUNCTION__ << " : " << demuxer_client_id_;
647f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  DCHECK(is_demuxer_ready_);
648eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
649424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  scoped_ptr<DemuxerConfigs> configs(new DemuxerConfigs());
650cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  GetDemuxerConfigFromStream(configs.get(), true);
651cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  GetDemuxerConfigFromStream(configs.get(), false);
6520529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  configs->duration = GetDuration();
653c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
654d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  if (demuxer_client_)
655d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    demuxer_client_->DemuxerReady(demuxer_client_id_, *configs);
6565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
6575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::AutoLock auto_lock(is_video_encrypted_lock_);
6585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  is_video_encrypted_ = configs->is_video_encrypted;
659c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
660c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
6610529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochbase::TimeDelta MediaSourceDelegate::GetDuration() const {
66258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  DCHECK(media_loop_->BelongsToCurrentThread());
663868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!chunk_demuxer_)
6640529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    return media::kNoTimestamp();
665868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
6660529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  double duration = chunk_demuxer_->GetDuration();
6670529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  if (duration == std::numeric_limits<double>::infinity())
6680529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    return media::kInfiniteDuration();
6690529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
6700529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  return ConvertSecondsToTimestamp(duration);
671868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
672868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
673c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void MediaSourceDelegate::OnDemuxerOpened() {
6743551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  DCHECK(main_loop_->BelongsToCurrentThread());
6753551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (media_source_opened_cb_.is_null())
67690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return;
67790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
6783551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  media_source_opened_cb_.Run(new WebMediaSourceImpl(
679c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      chunk_demuxer_.get(), base::Bind(&LogMediaSourceError, media_log_)));
680c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
681c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
68258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)void MediaSourceDelegate::OnNeedKey(const std::string& type,
683424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)                                    const std::vector<uint8>& init_data) {
6843551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  DCHECK(main_loop_->BelongsToCurrentThread());
685868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (need_key_cb_.is_null())
686c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return;
687c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
6884e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  need_key_cb_.Run(type, init_data);
68990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
69090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
6913551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)bool MediaSourceDelegate::IsSeeking() const {
6923551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  base::AutoLock auto_lock(seeking_lock_);
6933551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  return seeking_;
6943551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
6953551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
6961e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)base::TimeDelta MediaSourceDelegate::FindBufferedBrowserSeekTime_Locked(
6971e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    const base::TimeDelta& seek_time) const {
6981e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  seeking_lock_.AssertAcquired();
6991e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  DCHECK(seeking_);
7001e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  DCHECK(doing_browser_seek_);
7011e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  DCHECK(chunk_demuxer_) << "Browser seek requested, but no chunk demuxer";
7021e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
7031e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  media::Ranges<base::TimeDelta> buffered =
7041e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      chunk_demuxer_->GetBufferedRanges();
7051e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
7061e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  for (size_t i = 0; i < buffered.size(); ++i) {
7071e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    base::TimeDelta range_start = buffered.start(i);
7081e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    base::TimeDelta range_end = buffered.end(i);
7091e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    if (range_start <= seek_time) {
7101e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      if (range_end >= seek_time)
7111e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)        return seek_time;
7121e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      continue;
7131e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    }
7141e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
7151e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    // If the start of the next buffered range after |seek_time| is too far
7161e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    // into the future, do not jump forward.
7171e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    if ((range_start - seek_time) > base::TimeDelta::FromMilliseconds(100))
7181e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      break;
7191e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
7201e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    // TODO(wolenetz): Remove possibility that this browser seek jumps
7211e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    // into future when the requested range is unbuffered but there is some
7221e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    // other buffered range after it. See http://crbug.com/304234.
7231e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    return range_start;
7241e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  }
7251e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
7261e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // We found no range containing |seek_time| or beginning shortly after
7271e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // |seek_time|. While possible that such data at and beyond the player's
7281e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // current time have been garbage collected or removed by the web app, this is
7291e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // unlikely. This may cause unexpected playback stall due to seek pending an
7301e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // append for a GOP prior to the last GOP demuxed.
7311e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // TODO(wolenetz): Remove the possibility for this seek to cause unexpected
7321e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // player stall by replaying cached data since last keyframe in browser player
7331e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // rather than issuing browser seek. See http://crbug.com/304234.
7341e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  return seek_time;
7351e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
7361e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
737cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)bool MediaSourceDelegate::GetDemuxerConfigFromStream(
738cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    media::DemuxerConfigs* configs, bool is_audio) {
739cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  DCHECK(media_loop_->BelongsToCurrentThread());
740f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (!is_demuxer_ready_)
741cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return false;
742cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (is_audio && audio_stream_) {
743cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    media::AudioDecoderConfig config = audio_stream_->audio_decoder_config();
744cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    configs->audio_codec = config.codec();
745cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    configs->audio_channels =
746cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        media::ChannelLayoutToChannelCount(config.channel_layout());
747cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    configs->audio_sampling_rate = config.samples_per_second();
748cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    configs->is_audio_encrypted = config.is_encrypted();
749cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    configs->audio_extra_data = std::vector<uint8>(
750cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        config.extra_data(), config.extra_data() + config.extra_data_size());
751cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return true;
752cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
753cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (!is_audio && video_stream_) {
754cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    media::VideoDecoderConfig config = video_stream_->video_decoder_config();
755cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    configs->video_codec = config.codec();
756cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    configs->video_size = config.natural_size();
757cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    configs->is_video_encrypted = config.is_encrypted();
758cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    configs->video_extra_data = std::vector<uint8>(
759cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        config.extra_data(), config.extra_data() + config.extra_data_size());
760cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return true;
761cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
762cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return false;
763cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
764cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
765eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}  // namespace content
766