OLD | NEW |
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "webkit/media/android/media_source_delegate.h" | 5 #include "webkit/media/android/media_source_delegate.h" |
6 | 6 |
7 #include "base/message_loop_proxy.h" | 7 #include "base/message_loop_proxy.h" |
8 #include "base/strings/string_number_conversions.h" | 8 #include "base/strings/string_number_conversions.h" |
9 #include "media/base/android/demuxer_stream_player_params.h" | 9 #include "media/base/android/demuxer_stream_player_params.h" |
10 #include "media/base/bind_to_loop.h" | 10 #include "media/base/bind_to_loop.h" |
11 #include "media/base/demuxer_stream.h" | 11 #include "media/base/demuxer_stream.h" |
12 #include "media/base/media_log.h" | 12 #include "media/base/media_log.h" |
13 #include "media/filters/chunk_demuxer.h" | 13 #include "media/filters/chunk_demuxer.h" |
14 #include "third_party/WebKit/Source/Platform/chromium/public/WebString.h" | 14 #include "third_party/WebKit/Source/Platform/chromium/public/WebString.h" |
15 #include "third_party/WebKit/Source/WebKit/chromium/public/WebMediaPlayerClient.
h" | 15 #include "third_party/WebKit/Source/WebKit/chromium/public/WebMediaPlayerClient.
h" |
16 #include "third_party/WebKit/Source/WebKit/chromium/public/WebMediaSource.h" | 16 #include "third_party/WebKit/Source/WebKit/chromium/public/WebMediaSource.h" |
17 #include "third_party/WebKit/Source/WebKit/chromium/public/WebRuntimeFeatures.h" | 17 #include "third_party/WebKit/Source/WebKit/chromium/public/WebRuntimeFeatures.h" |
18 #include "webkit/media/android/webmediaplayer_proxy_android.h" | 18 #include "webkit/media/android/webmediaplayer_proxy_android.h" |
19 #include "webkit/media/crypto/key_systems.h" | 19 #include "webkit/media/crypto/key_systems.h" |
20 #include "webkit/media/crypto/proxy_decryptor.h" | 20 #include "webkit/media/crypto/proxy_decryptor.h" |
21 #include "webkit/media/webmediaplayer_util.h" | 21 #include "webkit/media/webmediaplayer_util.h" |
22 #include "webkit/media/webmediasourceclient_impl.h" | 22 #include "webkit/media/webmediasourceclient_impl.h" |
23 | 23 |
| 24 using media::DemuxerHost; |
24 using media::DemuxerStream; | 25 using media::DemuxerStream; |
25 using media::MediaPlayerHostMsg_DemuxerReady_Params; | 26 using media::MediaPlayerHostMsg_DemuxerReady_Params; |
26 using media::MediaPlayerHostMsg_ReadFromDemuxerAck_Params; | 27 using media::MediaPlayerHostMsg_ReadFromDemuxerAck_Params; |
| 28 using media::PipelineStatusCB; |
27 using WebKit::WebMediaPlayer; | 29 using WebKit::WebMediaPlayer; |
28 using WebKit::WebString; | 30 using WebKit::WebString; |
29 | 31 |
30 namespace { | 32 namespace { |
31 | 33 |
32 // The size of the access unit to transfer in an IPC. | 34 // The size of the access unit to transfer in an IPC in case of MediaSource. |
33 // 16: approximately 250ms of content in 60 fps movies. | 35 // 16: approximately 250ms of content in 60 fps movies. |
34 const size_t kAccessUnitSize = 16; | 36 const size_t kAccessUnitSizeForMediaSource = 16; |
35 | 37 |
36 } // namespace | 38 } // namespace |
37 | 39 |
38 namespace webkit_media { | 40 namespace webkit_media { |
39 | 41 |
40 #define BIND_TO_RENDER_LOOP(function) \ | 42 #define BIND_TO_RENDER_LOOP(function) \ |
41 media::BindToLoop(base::MessageLoopProxy::current(), \ | 43 media::BindToLoop(base::MessageLoopProxy::current(), \ |
42 base::Bind(function, weak_this_.GetWeakPtr())) | 44 base::Bind(function, weak_this_.GetWeakPtr())) |
43 | 45 |
44 #define BIND_TO_RENDER_LOOP_1(function, arg1) \ | 46 #define BIND_TO_RENDER_LOOP_1(function, arg1) \ |
45 media::BindToLoop(base::MessageLoopProxy::current(), \ | 47 media::BindToLoop(base::MessageLoopProxy::current(), \ |
46 base::Bind(function, weak_this_.GetWeakPtr(), arg1)) | 48 base::Bind(function, weak_this_.GetWeakPtr(), arg1)) |
47 | 49 |
48 #define BIND_TO_RENDER_LOOP_2(function, arg1, arg2) \ | 50 #define BIND_TO_RENDER_LOOP_2(function, arg1, arg2) \ |
49 media::BindToLoop(base::MessageLoopProxy::current(), \ | 51 media::BindToLoop(base::MessageLoopProxy::current(), \ |
50 base::Bind(function, weak_this_.GetWeakPtr(), arg1, arg2)) | 52 base::Bind(function, weak_this_.GetWeakPtr(), arg1, arg2)) |
51 | 53 |
52 #define BIND_TO_RENDER_LOOP_3(function, arg1, arg2, arg3) \ | 54 #define BIND_TO_RENDER_LOOP_3(function, arg1, arg2, arg3) \ |
53 media::BindToLoop(base::MessageLoopProxy::current(), \ | 55 media::BindToLoop(base::MessageLoopProxy::current(), \ |
54 base::Bind(function, \ | 56 base::Bind(function, \ |
55 weak_this_.GetWeakPtr(), arg1, arg2, arg3)) | 57 weak_this_.GetWeakPtr(), arg1, arg2, arg3)) |
56 | 58 |
57 static void LogMediaSourceError(const scoped_refptr<media::MediaLog>& media_log, | 59 static void LogMediaSourceError(const scoped_refptr<media::MediaLog>& media_log, |
58 const std::string& error) { | 60 const std::string& error) { |
59 media_log->AddEvent(media_log->CreateMediaSourceErrorEvent(error)); | 61 media_log->AddEvent(media_log->CreateMediaSourceErrorEvent(error)); |
60 } | 62 } |
61 | 63 |
62 MediaSourceDelegate::MediaSourceDelegate( | 64 // KeyHandlingDemuxer ---------------------------------------------------------- |
| 65 |
| 66 class KeyHandlingDemuxer : public media::Demuxer { |
| 67 public: |
| 68 typedef base::Callback<void(const std::string& key_system)> NotifyDemuxerCB; |
| 69 |
| 70 KeyHandlingDemuxer(); |
| 71 virtual ~KeyHandlingDemuxer(); |
| 72 |
| 73 void InitializeDemuxer(media::Demuxer* demuxer); |
| 74 void InitializeChunkDemuxer(WebKit::WebFrame* frame, |
| 75 WebKit::WebMediaPlayerClient* client, |
| 76 WebKit::WebMediaSource* media_source, |
| 77 scoped_refptr<media::MediaLog> media_log, |
| 78 const NotifyDemuxerCB& notify_demuxer_cb); |
| 79 WebKit::WebMediaPlayer::MediaKeyException GenerateKeyRequest( |
| 80 const WebKit::WebString& key_system, |
| 81 const unsigned char* init_data, |
| 82 unsigned init_data_length); |
| 83 WebKit::WebMediaPlayer::MediaKeyException AddKey( |
| 84 const WebKit::WebString& key_system, |
| 85 const unsigned char* key, |
| 86 unsigned key_length, |
| 87 const unsigned char* init_data, |
| 88 unsigned init_data_length, |
| 89 const WebKit::WebString& session_id); |
| 90 WebKit::WebMediaPlayer::MediaKeyException CancelKeyRequest( |
| 91 const WebKit::WebString& key_system, |
| 92 const WebKit::WebString& session_id); |
| 93 int GetDurationMs(); |
| 94 media::Demuxer* demuxer() { return demuxer_; } |
| 95 |
| 96 // media::Demuxer implementation |
| 97 virtual void Initialize(DemuxerHost* host, const PipelineStatusCB& status_cb) |
| 98 OVERRIDE; |
| 99 virtual void SetPlaybackRate(float playback_rate) OVERRIDE; |
| 100 virtual void Seek(base::TimeDelta time, const PipelineStatusCB& status_cb) |
| 101 OVERRIDE; |
| 102 virtual void Stop(const base::Closure& callback) OVERRIDE; |
| 103 virtual void OnAudioRendererDisabled() OVERRIDE; |
| 104 virtual DemuxerStream* GetStream(DemuxerStream::Type type) OVERRIDE; |
| 105 virtual base::TimeDelta GetStartTime() const OVERRIDE; |
| 106 |
| 107 private: |
| 108 // Callbacks for ChunkDemuxer & Decryptor. |
| 109 void OnDemuxerOpened(); |
| 110 void OnKeyAdded(const std::string& key_system, const std::string& session_id); |
| 111 void OnKeyError(const std::string& key_system, |
| 112 const std::string& session_id, |
| 113 media::Decryptor::KeyError error_code, |
| 114 int system_code); |
| 115 void OnKeyMessage(const std::string& key_system, |
| 116 const std::string& session_id, |
| 117 const std::string& message, |
| 118 const std::string& default_url); |
| 119 void OnNeedKey(const std::string& key_system, |
| 120 const std::string& type, |
| 121 const std::string& session_id, |
| 122 scoped_ptr<uint8[]> init_data, |
| 123 int init_data_size); |
| 124 void OnDecryptorReady(media::Decryptor*); |
| 125 |
| 126 media::Demuxer* demuxer_; |
| 127 |
| 128 base::WeakPtrFactory<KeyHandlingDemuxer> weak_this_; |
| 129 scoped_ptr<media::ChunkDemuxer> chunk_demuxer_; |
| 130 WebKit::WebMediaPlayerClient* client_; |
| 131 scoped_refptr<media::MediaLog> media_log_; |
| 132 |
| 133 // The decryptor that manages decryption keys and decrypts encrypted frames. |
| 134 scoped_ptr<ProxyDecryptor> decryptor_; |
| 135 |
| 136 // The currently selected key system. Empty string means that no key system |
| 137 // has been selected. |
| 138 WebKit::WebString current_key_system_; |
| 139 |
| 140 // Temporary for EME v0.1. In the future the init data type should be passed |
| 141 // through GenerateKeyRequest() directly from WebKit. |
| 142 std::string init_data_type_; |
| 143 |
| 144 NotifyDemuxerCB notify_demuxer_cb_; |
| 145 |
| 146 scoped_ptr<WebKit::WebMediaSource> media_source_; |
| 147 }; |
| 148 |
| 149 KeyHandlingDemuxer::KeyHandlingDemuxer() |
| 150 : demuxer_(NULL), weak_this_(this), client_(NULL) {} |
| 151 |
| 152 KeyHandlingDemuxer::~KeyHandlingDemuxer() {} |
| 153 |
| 154 void KeyHandlingDemuxer::InitializeDemuxer(media::Demuxer* demuxer) { |
| 155 DCHECK(!demuxer_); |
| 156 demuxer_ = demuxer; |
| 157 } |
| 158 |
| 159 void KeyHandlingDemuxer::InitializeChunkDemuxer( |
63 WebKit::WebFrame* frame, | 160 WebKit::WebFrame* frame, |
64 WebKit::WebMediaPlayerClient* client, | 161 WebKit::WebMediaPlayerClient* client, |
65 WebMediaPlayerProxyAndroid* proxy, | 162 WebKit::WebMediaSource* media_source, |
66 int player_id, | 163 scoped_refptr<media::MediaLog> media_log, |
67 media::MediaLog* media_log) | 164 const NotifyDemuxerCB& notify_demuxer_cb) { |
68 : weak_this_(this), | 165 DCHECK(!demuxer_); |
69 client_(client), | 166 client_ = client; |
70 proxy_(proxy), | 167 media_log_ = media_log; |
71 player_id_(player_id), | 168 notify_demuxer_cb_ = notify_demuxer_cb; |
72 media_log_(media_log), | 169 chunk_demuxer_.reset(new media::ChunkDemuxer( |
73 audio_params_(new MediaPlayerHostMsg_ReadFromDemuxerAck_Params), | 170 BIND_TO_RENDER_LOOP(&KeyHandlingDemuxer::OnDemuxerOpened), |
74 video_params_(new MediaPlayerHostMsg_ReadFromDemuxerAck_Params), | 171 BIND_TO_RENDER_LOOP_2(&KeyHandlingDemuxer::OnNeedKey, "", ""), |
75 seeking_(false) { | 172 base::Bind(&LogMediaSourceError, media_log))); |
| 173 demuxer_ = chunk_demuxer_.get(); |
| 174 media_source_.reset(media_source); |
76 if (WebKit::WebRuntimeFeatures::isEncryptedMediaEnabled()) { | 175 if (WebKit::WebRuntimeFeatures::isEncryptedMediaEnabled()) { |
77 decryptor_.reset(new ProxyDecryptor( | 176 decryptor_.reset(new ProxyDecryptor( |
78 client, | 177 client, |
79 frame, | 178 frame, |
80 BIND_TO_RENDER_LOOP(&MediaSourceDelegate::OnKeyAdded), | 179 BIND_TO_RENDER_LOOP(&KeyHandlingDemuxer::OnKeyAdded), |
81 BIND_TO_RENDER_LOOP(&MediaSourceDelegate::OnKeyError), | 180 BIND_TO_RENDER_LOOP(&KeyHandlingDemuxer::OnKeyError), |
82 BIND_TO_RENDER_LOOP(&MediaSourceDelegate::OnKeyMessage), | 181 BIND_TO_RENDER_LOOP(&KeyHandlingDemuxer::OnKeyMessage), |
83 BIND_TO_RENDER_LOOP(&MediaSourceDelegate::OnNeedKey))); | 182 BIND_TO_RENDER_LOOP(&KeyHandlingDemuxer::OnNeedKey))); |
84 decryptor_->SetDecryptorReadyCB( | 183 decryptor_->SetDecryptorReadyCB( |
85 BIND_TO_RENDER_LOOP(&MediaSourceDelegate::OnDecryptorReady)); | 184 BIND_TO_RENDER_LOOP(&KeyHandlingDemuxer::OnDecryptorReady)); |
86 } | 185 } |
87 } | 186 } |
88 | 187 |
89 MediaSourceDelegate::~MediaSourceDelegate() {} | 188 void KeyHandlingDemuxer::Initialize(DemuxerHost* host, |
90 | 189 const PipelineStatusCB& status_cb) { |
91 void MediaSourceDelegate::Initialize( | 190 demuxer_->Initialize(host, status_cb); |
92 scoped_ptr<WebKit::WebMediaSource> media_source, | |
93 const UpdateNetworkStateCB& update_network_state_cb) { | |
94 DCHECK(media_source); | |
95 media_source_ = media_source.Pass(); | |
96 update_network_state_cb_ = update_network_state_cb; | |
97 | |
98 chunk_demuxer_.reset(new media::ChunkDemuxer( | |
99 BIND_TO_RENDER_LOOP(&MediaSourceDelegate::OnDemuxerOpened), | |
100 BIND_TO_RENDER_LOOP_2(&MediaSourceDelegate::OnNeedKey, "", ""), | |
101 base::Bind(&LogMediaSourceError, media_log_))); | |
102 chunk_demuxer_->Initialize(this, | |
103 BIND_TO_RENDER_LOOP(&MediaSourceDelegate::OnDemuxerInitDone)); | |
104 } | 191 } |
105 | 192 |
106 const WebKit::WebTimeRanges& MediaSourceDelegate::Buffered() { | 193 void KeyHandlingDemuxer::SetPlaybackRate(float playback_rate) { |
107 buffered_web_time_ranges_ = | 194 demuxer_->SetPlaybackRate(playback_rate); |
108 ConvertToWebTimeRanges(buffered_time_ranges_); | |
109 return buffered_web_time_ranges_; | |
110 } | 195 } |
111 | 196 |
112 size_t MediaSourceDelegate::DecodedFrameCount() const { | 197 void KeyHandlingDemuxer::Seek(base::TimeDelta time, |
113 return statistics_.video_frames_decoded; | 198 const PipelineStatusCB& status_cb) { |
| 199 if (!chunk_demuxer_) |
| 200 chunk_demuxer_->StartWaitingForSeek(); |
| 201 demuxer_->Seek(time, status_cb); |
114 } | 202 } |
115 | 203 |
116 size_t MediaSourceDelegate::DroppedFrameCount() const { | 204 void KeyHandlingDemuxer::Stop(const base::Closure& callback) { |
117 return statistics_.video_frames_dropped; | 205 demuxer_->Stop(callback); |
118 } | 206 } |
119 | 207 |
120 size_t MediaSourceDelegate::AudioDecodedByteCount() const { | 208 void KeyHandlingDemuxer::OnAudioRendererDisabled() { |
121 return statistics_.audio_bytes_decoded; | 209 demuxer_->OnAudioRendererDisabled(); |
122 } | 210 } |
123 | 211 |
124 size_t MediaSourceDelegate::VideoDecodedByteCount() const { | 212 DemuxerStream* KeyHandlingDemuxer::GetStream(DemuxerStream::Type type) { |
125 return statistics_.video_bytes_decoded; | 213 return demuxer_->GetStream(type); |
126 } | 214 } |
127 | 215 |
128 WebMediaPlayer::MediaKeyException MediaSourceDelegate::GenerateKeyRequest( | 216 base::TimeDelta KeyHandlingDemuxer::GetStartTime() const { |
| 217 return demuxer_->GetStartTime(); |
| 218 } |
| 219 |
| 220 WebMediaPlayer::MediaKeyException KeyHandlingDemuxer::GenerateKeyRequest( |
129 const WebString& key_system, | 221 const WebString& key_system, |
130 const unsigned char* init_data, | 222 const unsigned char* init_data, |
131 size_t init_data_length) { | 223 size_t init_data_length) { |
| 224 if (!decryptor_) |
| 225 return WebKit::WebMediaPlayer::MediaKeyExceptionKeySystemNotSupported; |
132 if (!IsSupportedKeySystem(key_system)) | 226 if (!IsSupportedKeySystem(key_system)) |
133 return WebMediaPlayer::MediaKeyExceptionKeySystemNotSupported; | 227 return WebMediaPlayer::MediaKeyExceptionKeySystemNotSupported; |
134 | 228 |
135 // We do not support run-time switching between key systems for now. | 229 // We do not support run-time switching between key systems for now. |
136 if (current_key_system_.isEmpty()) | 230 if (current_key_system_.isEmpty()) |
137 current_key_system_ = key_system; | 231 current_key_system_ = key_system; |
138 else if (key_system != current_key_system_) | 232 else if (key_system != current_key_system_) |
139 return WebMediaPlayer::MediaKeyExceptionInvalidPlayerState; | 233 return WebMediaPlayer::MediaKeyExceptionInvalidPlayerState; |
140 | 234 |
141 DVLOG(1) << "generateKeyRequest: " << key_system.utf8().data() << ": " | 235 DVLOG(1) << "generateKeyRequest: " << key_system.utf8().data() << ": " |
142 << std::string(reinterpret_cast<const char*>(init_data), | 236 << std::string(reinterpret_cast<const char*>(init_data), |
143 init_data_length); | 237 init_data_length); |
144 | 238 |
145 // TODO(xhwang): We assume all streams are from the same container (thus have | 239 // TODO(xhwang): We assume all streams are from the same container (thus have |
146 // the same "type") for now. In the future, the "type" should be passed down | 240 // the same "type") for now. In the future, the "type" should be passed down |
147 // from the application. | 241 // from the application. |
148 if (!decryptor_->GenerateKeyRequest(key_system.utf8(), | 242 if (!decryptor_->GenerateKeyRequest(key_system.utf8(), |
149 init_data_type_, | 243 init_data_type_, |
150 init_data, init_data_length)) { | 244 init_data, init_data_length)) { |
151 current_key_system_.reset(); | 245 current_key_system_.reset(); |
152 return WebMediaPlayer::MediaKeyExceptionKeySystemNotSupported; | 246 return WebMediaPlayer::MediaKeyExceptionKeySystemNotSupported; |
153 } | 247 } |
154 | 248 |
155 return WebMediaPlayer::MediaKeyExceptionNoError; | 249 return WebMediaPlayer::MediaKeyExceptionNoError; |
156 } | 250 } |
157 | 251 |
158 WebMediaPlayer::MediaKeyException MediaSourceDelegate::AddKey( | 252 WebMediaPlayer::MediaKeyException KeyHandlingDemuxer::AddKey( |
159 const WebString& key_system, | 253 const WebString& key_system, |
160 const unsigned char* key, | 254 const unsigned char* key, |
161 size_t key_length, | 255 size_t key_length, |
162 const unsigned char* init_data, | 256 const unsigned char* init_data, |
163 size_t init_data_length, | 257 size_t init_data_length, |
164 const WebString& session_id) { | 258 const WebString& session_id) { |
| 259 if (!decryptor_) |
| 260 return WebKit::WebMediaPlayer::MediaKeyExceptionKeySystemNotSupported; |
165 DCHECK(key); | 261 DCHECK(key); |
166 DCHECK_EQ(key_length, 16u); | 262 DCHECK_EQ(key_length, 16u); |
167 | 263 |
168 if (!IsSupportedKeySystem(key_system)) | 264 if (!IsSupportedKeySystem(key_system)) |
169 return WebMediaPlayer::MediaKeyExceptionKeySystemNotSupported; | 265 return WebMediaPlayer::MediaKeyExceptionKeySystemNotSupported; |
170 | 266 |
171 if (current_key_system_.isEmpty() || key_system != current_key_system_) | 267 if (current_key_system_.isEmpty() || key_system != current_key_system_) |
172 return WebMediaPlayer::MediaKeyExceptionInvalidPlayerState; | 268 return WebMediaPlayer::MediaKeyExceptionInvalidPlayerState; |
173 | 269 |
174 DVLOG(1) << "addKey: " << key_system.utf8().data() << ": " | 270 DVLOG(1) << "addKey: " << key_system.utf8().data() << ": " |
175 << base::HexEncode(key, key_length) << ", " | 271 << base::HexEncode(key, key_length) << ", " |
176 << base::HexEncode(init_data, std::max(init_data_length, 256u)) | 272 << base::HexEncode(init_data, std::max(init_data_length, 256u)) |
177 << " [" << session_id.utf8().data() << "]"; | 273 << " [" << session_id.utf8().data() << "]"; |
178 | 274 |
179 decryptor_->AddKey(key_system.utf8(), key, key_length, | 275 decryptor_->AddKey(key_system.utf8(), key, key_length, |
180 init_data, init_data_length, session_id.utf8()); | 276 init_data, init_data_length, session_id.utf8()); |
181 return WebMediaPlayer::MediaKeyExceptionNoError; | 277 return WebMediaPlayer::MediaKeyExceptionNoError; |
182 } | 278 } |
183 | 279 |
184 WebMediaPlayer::MediaKeyException MediaSourceDelegate::CancelKeyRequest( | 280 WebMediaPlayer::MediaKeyException KeyHandlingDemuxer::CancelKeyRequest( |
185 const WebString& key_system, | 281 const WebString& key_system, |
186 const WebString& session_id) { | 282 const WebString& session_id) { |
| 283 if (!decryptor_) |
| 284 return WebKit::WebMediaPlayer::MediaKeyExceptionKeySystemNotSupported; |
187 if (!IsSupportedKeySystem(key_system)) | 285 if (!IsSupportedKeySystem(key_system)) |
188 return WebMediaPlayer::MediaKeyExceptionKeySystemNotSupported; | 286 return WebMediaPlayer::MediaKeyExceptionKeySystemNotSupported; |
189 | 287 |
190 if (current_key_system_.isEmpty() || key_system != current_key_system_) | 288 if (current_key_system_.isEmpty() || key_system != current_key_system_) |
191 return WebMediaPlayer::MediaKeyExceptionInvalidPlayerState; | 289 return WebMediaPlayer::MediaKeyExceptionInvalidPlayerState; |
192 | 290 |
193 decryptor_->CancelKeyRequest(key_system.utf8(), session_id.utf8()); | 291 decryptor_->CancelKeyRequest(key_system.utf8(), session_id.utf8()); |
194 return WebMediaPlayer::MediaKeyExceptionNoError; | 292 return WebMediaPlayer::MediaKeyExceptionNoError; |
195 } | 293 } |
196 | 294 |
| 295 int KeyHandlingDemuxer::GetDurationMs() { |
| 296 if (!chunk_demuxer_) |
| 297 return -1; |
| 298 |
| 299 double duration_ms = chunk_demuxer_->GetDuration() * 1000; |
| 300 if (duration_ms > std::numeric_limits<int>::max()) { |
| 301 LOG(WARNING) << "Duration from ChunkDemuxer is too large; probably " |
| 302 "something have gone wrong."; |
| 303 return std::numeric_limits<int>::max(); |
| 304 } |
| 305 return duration_ms; |
| 306 } |
| 307 |
| 308 void KeyHandlingDemuxer::OnKeyError(const std::string& key_system, |
| 309 const std::string& session_id, |
| 310 media::Decryptor::KeyError error_code, |
| 311 int system_code) { |
| 312 if (!client_) |
| 313 return; |
| 314 client_->keyError( |
| 315 WebString::fromUTF8(key_system), |
| 316 WebString::fromUTF8(session_id), |
| 317 static_cast<WebKit::WebMediaPlayerClient::MediaKeyErrorCode>(error_code), |
| 318 system_code); |
| 319 } |
| 320 |
| 321 void KeyHandlingDemuxer::OnKeyMessage(const std::string& key_system, |
| 322 const std::string& session_id, |
| 323 const std::string& message, |
| 324 const std::string& default_url) { |
| 325 if (!client_) |
| 326 return; |
| 327 const GURL default_url_gurl(default_url); |
| 328 DLOG_IF(WARNING, !default_url.empty() && !default_url_gurl.is_valid()) |
| 329 << "Invalid URL in default_url: " << default_url; |
| 330 |
| 331 client_->keyMessage(WebString::fromUTF8(key_system), |
| 332 WebString::fromUTF8(session_id), |
| 333 reinterpret_cast<const uint8*>(message.data()), |
| 334 message.size(), |
| 335 default_url_gurl); |
| 336 } |
| 337 |
| 338 void KeyHandlingDemuxer::OnKeyAdded(const std::string& key_system, |
| 339 const std::string& session_id) { |
| 340 if (!client_ || notify_demuxer_cb_.is_null()) |
| 341 return; |
| 342 notify_demuxer_cb_.Run(key_system); |
| 343 client_->keyAdded(WebString::fromUTF8(key_system), |
| 344 WebString::fromUTF8(session_id)); |
| 345 } |
| 346 |
| 347 void KeyHandlingDemuxer::OnNeedKey(const std::string& key_system, |
| 348 const std::string& session_id, |
| 349 const std::string& type, |
| 350 scoped_ptr<uint8[]> init_data, |
| 351 int init_data_size) { |
| 352 // Do not fire NeedKey event if encrypted media is not enabled. |
| 353 if (!decryptor_) |
| 354 return; |
| 355 |
| 356 CHECK(init_data_size >= 0); |
| 357 DCHECK(init_data_type_.empty() || type.empty() || type == init_data_type_); |
| 358 if (init_data_type_.empty()) |
| 359 init_data_type_ = type; |
| 360 |
| 361 client_->keyNeeded(WebString::fromUTF8(key_system), |
| 362 WebString::fromUTF8(session_id), |
| 363 init_data.get(), |
| 364 init_data_size); |
| 365 } |
| 366 |
| 367 void KeyHandlingDemuxer::OnDecryptorReady(media::Decryptor*) {} |
| 368 |
| 369 void KeyHandlingDemuxer::OnDemuxerOpened() { |
| 370 DCHECK(media_source_); |
| 371 media_source_->open(new WebMediaSourceClientImpl( |
| 372 chunk_demuxer_.get(), base::Bind(&LogMediaSourceError, media_log_))); |
| 373 } |
| 374 |
| 375 // MediaSourceDelegate --------------------------------------------------------- |
| 376 |
| 377 MediaSourceDelegate::MediaSourceDelegate( |
| 378 WebMediaPlayerProxyAndroid* proxy, |
| 379 int player_id, |
| 380 const UpdateNetworkStateCB& update_network_state_cb) |
| 381 : weak_this_(this), |
| 382 proxy_(proxy), |
| 383 player_id_(player_id), |
| 384 update_network_state_cb_(update_network_state_cb), |
| 385 demuxer_(new KeyHandlingDemuxer), |
| 386 audio_params_(new MediaPlayerHostMsg_ReadFromDemuxerAck_Params), |
| 387 video_params_(new MediaPlayerHostMsg_ReadFromDemuxerAck_Params), |
| 388 seeking_(false), |
| 389 access_unit_size_(0) { |
| 390 } |
| 391 |
| 392 MediaSourceDelegate::~MediaSourceDelegate() { |
| 393 if (!destroy_demuxer_cb_.is_null()) |
| 394 destroy_demuxer_cb_.Run(demuxer_->demuxer()); |
| 395 } |
| 396 |
| 397 void MediaSourceDelegate::InitializeMediaSource( |
| 398 WebKit::WebFrame* frame, |
| 399 WebKit::WebMediaPlayerClient* client, |
| 400 WebKit::WebMediaSource* media_source, |
| 401 media::MediaLog* media_log) { |
| 402 DCHECK(media_source); |
| 403 demuxer_->InitializeChunkDemuxer( |
| 404 frame, |
| 405 client, |
| 406 media_source, |
| 407 scoped_refptr<media::MediaLog>(media_log), |
| 408 BIND_TO_RENDER_LOOP(&MediaSourceDelegate::NotifyDemuxerReady)); |
| 409 demuxer_->Initialize(this, |
| 410 BIND_TO_RENDER_LOOP(&MediaSourceDelegate::OnDemuxerInitDone)); |
| 411 access_unit_size_ = kAccessUnitSizeForMediaSource; |
| 412 } |
| 413 |
| 414 void MediaSourceDelegate::InitializeMediaStream(media::Demuxer* demuxer) { |
| 415 DCHECK(demuxer); |
| 416 demuxer_->InitializeDemuxer(demuxer); |
| 417 demuxer_->Initialize(this, |
| 418 BIND_TO_RENDER_LOOP(&MediaSourceDelegate::OnDemuxerInitDone)); |
| 419 // When playing Media Stream, don't wait to accumulate multiple packets per |
| 420 // IPC communication. |
| 421 access_unit_size_ = 1; |
| 422 } |
| 423 |
| 424 const WebKit::WebTimeRanges& MediaSourceDelegate::Buffered() { |
| 425 buffered_web_time_ranges_ = |
| 426 ConvertToWebTimeRanges(buffered_time_ranges_); |
| 427 return buffered_web_time_ranges_; |
| 428 } |
| 429 |
| 430 unsigned MediaSourceDelegate::DecodedFrameCount() const { |
| 431 return statistics_.video_frames_decoded; |
| 432 } |
| 433 |
| 434 unsigned MediaSourceDelegate::DroppedFrameCount() const { |
| 435 return statistics_.video_frames_dropped; |
| 436 } |
| 437 |
| 438 unsigned MediaSourceDelegate::AudioDecodedByteCount() const { |
| 439 return statistics_.audio_bytes_decoded;; |
| 440 } |
| 441 |
| 442 unsigned MediaSourceDelegate::VideoDecodedByteCount() const { |
| 443 return statistics_.video_bytes_decoded; |
| 444 } |
| 445 |
| 446 WebMediaPlayer::MediaKeyException MediaSourceDelegate::GenerateKeyRequest( |
| 447 const WebString& key_system, |
| 448 const unsigned char* init_data, |
| 449 unsigned init_data_length) { |
| 450 return demuxer_->GenerateKeyRequest(key_system, init_data, init_data_length); |
| 451 } |
| 452 |
| 453 WebMediaPlayer::MediaKeyException MediaSourceDelegate::AddKey( |
| 454 const WebString& key_system, |
| 455 const unsigned char* key, |
| 456 unsigned key_length, |
| 457 const unsigned char* init_data, |
| 458 unsigned init_data_length, |
| 459 const WebString& session_id) { |
| 460 return demuxer_->AddKey( |
| 461 key_system, key, key_length, init_data, init_data_length, session_id); |
| 462 } |
| 463 |
| 464 WebMediaPlayer::MediaKeyException MediaSourceDelegate::CancelKeyRequest( |
| 465 const WebString& key_system, |
| 466 const WebString& session_id) { |
| 467 return demuxer_->CancelKeyRequest(key_system, session_id); |
| 468 } |
| 469 |
197 void MediaSourceDelegate::Seek(base::TimeDelta time) { | 470 void MediaSourceDelegate::Seek(base::TimeDelta time) { |
198 seeking_ = true; | 471 seeking_ = true; |
199 DCHECK(chunk_demuxer_); | 472 DCHECK(demuxer_); |
200 if (!chunk_demuxer_) | 473 if (!demuxer_) |
201 return; | 474 return; |
202 chunk_demuxer_->StartWaitingForSeek(); | 475 demuxer_->Seek(time, |
203 chunk_demuxer_->Seek(time, | |
204 BIND_TO_RENDER_LOOP(&MediaSourceDelegate::OnDemuxerError)); | 476 BIND_TO_RENDER_LOOP(&MediaSourceDelegate::OnDemuxerError)); |
205 } | 477 } |
206 | 478 |
207 void MediaSourceDelegate::SetTotalBytes(int64 total_bytes) { | 479 void MediaSourceDelegate::SetTotalBytes(int64 total_bytes) { |
208 NOTIMPLEMENTED(); | 480 NOTIMPLEMENTED(); |
209 } | 481 } |
210 | 482 |
211 void MediaSourceDelegate::AddBufferedByteRange(int64 start, int64 end) { | 483 void MediaSourceDelegate::AddBufferedByteRange(int64 start, int64 end) { |
212 NOTIMPLEMENTED(); | 484 NOTIMPLEMENTED(); |
213 } | 485 } |
214 | 486 |
215 void MediaSourceDelegate::AddBufferedTimeRange(base::TimeDelta start, | 487 void MediaSourceDelegate::AddBufferedTimeRange(base::TimeDelta start, |
216 base::TimeDelta end) { | 488 base::TimeDelta end) { |
217 buffered_time_ranges_.Add(start, end); | 489 buffered_time_ranges_.Add(start, end); |
218 } | 490 } |
219 | 491 |
220 void MediaSourceDelegate::SetDuration(base::TimeDelta duration) { | 492 void MediaSourceDelegate::SetDuration(base::TimeDelta duration) { |
221 // Do nothing | 493 // Do nothing |
222 } | 494 } |
223 | 495 |
224 void MediaSourceDelegate::OnReadFromDemuxer(media::DemuxerStream::Type type, | 496 void MediaSourceDelegate::OnReadFromDemuxer(media::DemuxerStream::Type type, |
225 bool seek_done) { | 497 bool seek_done) { |
226 if (seeking_ && !seek_done) | 498 if (seeking_ && !seek_done) |
227 return; // Drop the request during seeking. | 499 return; // Drop the request during seeking. |
228 seeking_ = false; | 500 seeking_ = false; |
229 | 501 |
230 DCHECK(type == DemuxerStream::AUDIO || type == DemuxerStream::VIDEO); | 502 DCHECK(type == DemuxerStream::AUDIO || type == DemuxerStream::VIDEO); |
| 503 // The access unit size should have been initialized properly at this stage. |
| 504 DCHECK(access_unit_size_ > 0); |
| 505 |
231 MediaPlayerHostMsg_ReadFromDemuxerAck_Params* params = | 506 MediaPlayerHostMsg_ReadFromDemuxerAck_Params* params = |
232 type == DemuxerStream::AUDIO ? audio_params_.get() : video_params_.get(); | 507 type == DemuxerStream::AUDIO ? audio_params_.get() : video_params_.get(); |
233 params->type = type; | 508 params->type = type; |
234 params->access_units.resize(kAccessUnitSize); | 509 params->access_units.resize(access_unit_size_); |
235 DemuxerStream* stream = chunk_demuxer_->GetStream(type); | 510 DemuxerStream* stream = demuxer_->GetStream(type); |
236 DCHECK(stream != NULL); | 511 DCHECK(stream != NULL); |
237 ReadFromDemuxerStream(stream, params, 0); | 512 ReadFromDemuxerStream(stream, params, 0); |
238 } | 513 } |
239 | 514 |
240 void MediaSourceDelegate::ReadFromDemuxerStream( | 515 void MediaSourceDelegate::ReadFromDemuxerStream( |
241 DemuxerStream* stream, | 516 DemuxerStream* stream, |
242 MediaPlayerHostMsg_ReadFromDemuxerAck_Params* params, | 517 MediaPlayerHostMsg_ReadFromDemuxerAck_Params* params, |
243 size_t index) { | 518 size_t index) { |
244 stream->Read(BIND_TO_RENDER_LOOP_3(&MediaSourceDelegate::OnBufferReady, | 519 stream->Read(BIND_TO_RENDER_LOOP_3(&MediaSourceDelegate::OnBufferReady, |
245 stream, params, index)); | 520 stream, params, index)); |
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
343 if (status != media::PIPELINE_OK) { | 618 if (status != media::PIPELINE_OK) { |
344 OnDemuxerError(status); | 619 OnDemuxerError(status); |
345 return; | 620 return; |
346 } | 621 } |
347 NotifyDemuxerReady(""); | 622 NotifyDemuxerReady(""); |
348 } | 623 } |
349 | 624 |
350 void MediaSourceDelegate::NotifyDemuxerReady( | 625 void MediaSourceDelegate::NotifyDemuxerReady( |
351 const std::string& key_system) { | 626 const std::string& key_system) { |
352 MediaPlayerHostMsg_DemuxerReady_Params params; | 627 MediaPlayerHostMsg_DemuxerReady_Params params; |
353 DemuxerStream* audio_stream = chunk_demuxer_->GetStream(DemuxerStream::AUDIO); | 628 DemuxerStream* audio_stream = demuxer_->GetStream(DemuxerStream::AUDIO); |
354 if (audio_stream) { | 629 if (audio_stream) { |
355 const media::AudioDecoderConfig& config = | 630 const media::AudioDecoderConfig& config = |
356 audio_stream->audio_decoder_config(); | 631 audio_stream->audio_decoder_config(); |
357 params.audio_codec = config.codec(); | 632 params.audio_codec = config.codec(); |
358 params.audio_channels = | 633 params.audio_channels = |
359 media::ChannelLayoutToChannelCount(config.channel_layout()); | 634 media::ChannelLayoutToChannelCount(config.channel_layout()); |
360 params.audio_sampling_rate = config.samples_per_second(); | 635 params.audio_sampling_rate = config.samples_per_second(); |
361 params.is_audio_encrypted = config.is_encrypted(); | 636 params.is_audio_encrypted = config.is_encrypted(); |
362 params.audio_extra_data = std::vector<uint8>( | 637 params.audio_extra_data = std::vector<uint8>( |
363 config.extra_data(), config.extra_data() + config.extra_data_size()); | 638 config.extra_data(), config.extra_data() + config.extra_data_size()); |
364 } | 639 } |
365 DemuxerStream* video_stream = chunk_demuxer_->GetStream(DemuxerStream::VIDEO); | 640 DemuxerStream* video_stream = demuxer_->GetStream(DemuxerStream::VIDEO); |
366 if (video_stream) { | 641 if (video_stream) { |
367 const media::VideoDecoderConfig& config = | 642 const media::VideoDecoderConfig& config = |
368 video_stream->video_decoder_config(); | 643 video_stream->video_decoder_config(); |
369 params.video_codec = config.codec(); | 644 params.video_codec = config.codec(); |
370 params.video_size = config.natural_size(); | 645 params.video_size = config.natural_size(); |
371 params.is_video_encrypted = config.is_encrypted(); | 646 params.is_video_encrypted = config.is_encrypted(); |
372 params.video_extra_data = std::vector<uint8>( | 647 params.video_extra_data = std::vector<uint8>( |
373 config.extra_data(), config.extra_data() + config.extra_data_size()); | 648 config.extra_data(), config.extra_data() + config.extra_data_size()); |
374 } | 649 } |
375 double duration_ms = chunk_demuxer_->GetDuration() * 1000; | 650 params.duration_ms = demuxer_->GetDurationMs(); |
376 DCHECK(duration_ms >= 0); | |
377 if (duration_ms > std::numeric_limits<int>::max()) | |
378 duration_ms = std::numeric_limits<int>::max(); | |
379 params.duration_ms = duration_ms; | |
380 params.key_system = key_system; | 651 params.key_system = key_system; |
381 | 652 |
382 bool ready_to_send = (!params.is_audio_encrypted && | 653 bool ready_to_send = (!params.is_audio_encrypted && |
383 !params.is_video_encrypted) || !key_system.empty(); | 654 !params.is_video_encrypted) || !key_system.empty(); |
384 if (proxy_ && ready_to_send) | 655 if (proxy_ && ready_to_send) |
385 proxy_->DemuxerReady(player_id_, params); | 656 proxy_->DemuxerReady(player_id_, params); |
386 } | 657 } |
387 | 658 |
388 void MediaSourceDelegate::OnDemuxerOpened() { | |
389 media_source_->open(new WebMediaSourceClientImpl( | |
390 chunk_demuxer_.get(), base::Bind(&LogMediaSourceError, media_log_))); | |
391 } | |
392 | |
393 void MediaSourceDelegate::OnKeyError(const std::string& key_system, | |
394 const std::string& session_id, | |
395 media::Decryptor::KeyError error_code, | |
396 int system_code) { | |
397 client_->keyError( | |
398 WebString::fromUTF8(key_system), | |
399 WebString::fromUTF8(session_id), | |
400 static_cast<WebKit::WebMediaPlayerClient::MediaKeyErrorCode>(error_code), | |
401 system_code); | |
402 } | |
403 | |
404 void MediaSourceDelegate::OnKeyMessage(const std::string& key_system, | |
405 const std::string& session_id, | |
406 const std::string& message, | |
407 const std::string& default_url) { | |
408 const GURL default_url_gurl(default_url); | |
409 DLOG_IF(WARNING, !default_url.empty() && !default_url_gurl.is_valid()) | |
410 << "Invalid URL in default_url: " << default_url; | |
411 | |
412 client_->keyMessage(WebString::fromUTF8(key_system), | |
413 WebString::fromUTF8(session_id), | |
414 reinterpret_cast<const uint8*>(message.data()), | |
415 message.size(), | |
416 default_url_gurl); | |
417 } | |
418 | |
419 void MediaSourceDelegate::OnKeyAdded(const std::string& key_system, | |
420 const std::string& session_id) { | |
421 NotifyDemuxerReady(key_system); | |
422 client_->keyAdded(WebString::fromUTF8(key_system), | |
423 WebString::fromUTF8(session_id)); | |
424 } | |
425 | |
426 void MediaSourceDelegate::OnNeedKey(const std::string& key_system, | |
427 const std::string& session_id, | |
428 const std::string& type, | |
429 scoped_ptr<uint8[]> init_data, | |
430 int init_data_size) { | |
431 // Do not fire NeedKey event if encrypted media is not enabled. | |
432 if (!decryptor_) | |
433 return; | |
434 | |
435 CHECK(init_data_size >= 0); | |
436 DCHECK(init_data_type_.empty() || type.empty() || type == init_data_type_); | |
437 if (init_data_type_.empty()) | |
438 init_data_type_ = type; | |
439 | |
440 client_->keyNeeded(WebString::fromUTF8(key_system), | |
441 WebString::fromUTF8(session_id), | |
442 init_data.get(), | |
443 init_data_size); | |
444 } | |
445 | |
446 void MediaSourceDelegate::OnDecryptorReady(media::Decryptor* decryptor) {} | |
447 | |
448 } // namespace webkit_media | 659 } // namespace webkit_media |
OLD | NEW |