Chromium Code Reviews| 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. |
| 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 kAccessUnitSize = 16; |
| 35 | 37 |
| 36 } // namespace | 38 } // namespace |
| (...skipping 15 matching lines...) Expand all Loading... | |
| 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 explicit KeyHandlingDemuxer(media::Demuxer* demuxer); | |
| 69 virtual ~KeyHandlingDemuxer(); | |
| 70 | |
| 71 virtual WebKit::WebMediaPlayer::MediaKeyException GenerateKeyRequest( | |
| 72 const WebKit::WebString& key_system, | |
| 73 const unsigned char* init_data, | |
| 74 unsigned init_data_length) { | |
| 75 return WebKit::WebMediaPlayer::MediaKeyExceptionKeySystemNotSupported; | |
| 76 } | |
| 77 virtual WebKit::WebMediaPlayer::MediaKeyException AddKey( | |
| 78 const WebKit::WebString& key_system, | |
| 79 const unsigned char* key, | |
| 80 unsigned key_length, | |
| 81 const unsigned char* init_data, | |
| 82 unsigned init_data_length, | |
| 83 const WebKit::WebString& session_id) { | |
| 84 return WebKit::WebMediaPlayer::MediaKeyExceptionKeySystemNotSupported; | |
| 85 } | |
| 86 virtual WebKit::WebMediaPlayer::MediaKeyException CancelKeyRequest( | |
| 87 const WebKit::WebString& key_system, | |
| 88 const WebKit::WebString& session_id) { | |
| 89 return WebKit::WebMediaPlayer::MediaKeyExceptionKeySystemNotSupported; | |
| 90 } | |
| 91 virtual int GetDurationMs() { return -1; } | |
| 92 | |
| 93 // media::Demuxer implementation | |
| 94 virtual void Initialize(DemuxerHost* host, const PipelineStatusCB& status_cb) | |
| 95 OVERRIDE; | |
| 96 virtual void SetPlaybackRate(float playback_rate) OVERRIDE; | |
| 97 virtual void Seek(base::TimeDelta time, const PipelineStatusCB& status_cb) | |
| 98 OVERRIDE; | |
| 99 virtual void Stop(const base::Closure& callback) OVERRIDE; | |
| 100 virtual void OnAudioRendererDisabled() OVERRIDE; | |
| 101 virtual DemuxerStream* GetStream(DemuxerStream::Type type) OVERRIDE; | |
| 102 virtual base::TimeDelta GetStartTime() const OVERRIDE; | |
| 103 | |
| 104 protected: | |
| 105 scoped_ptr<media::Demuxer> demuxer_; | |
| 106 }; | |
| 107 | |
| 108 KeyHandlingDemuxer::KeyHandlingDemuxer(media::Demuxer* demuxer) | |
| 109 : demuxer_(demuxer) {} | |
| 110 | |
| 111 KeyHandlingDemuxer::~KeyHandlingDemuxer() {} | |
| 112 | |
| 113 void KeyHandlingDemuxer::Initialize(DemuxerHost* host, | |
| 114 const PipelineStatusCB& status_cb) { | |
| 115 demuxer_->Initialize(host, status_cb); | |
| 116 } | |
| 117 | |
| 118 void KeyHandlingDemuxer::SetPlaybackRate(float playback_rate) { | |
| 119 demuxer_->SetPlaybackRate(playback_rate); | |
| 120 } | |
| 121 | |
| 122 void KeyHandlingDemuxer::Seek(base::TimeDelta time, | |
| 123 const PipelineStatusCB& status_cb) { | |
| 124 demuxer_->Seek(time, status_cb); | |
| 125 } | |
| 126 | |
| 127 void KeyHandlingDemuxer::Stop(const base::Closure& callback) { | |
| 128 demuxer_->Stop(callback); | |
| 129 } | |
| 130 | |
| 131 void KeyHandlingDemuxer::OnAudioRendererDisabled() { | |
| 132 demuxer_->OnAudioRendererDisabled(); | |
| 133 } | |
| 134 | |
| 135 DemuxerStream* KeyHandlingDemuxer::GetStream( | |
| 136 DemuxerStream::Type type) { | |
| 137 return demuxer_->GetStream(type); | |
| 138 } | |
| 139 | |
| 140 base::TimeDelta KeyHandlingDemuxer::GetStartTime() const { | |
| 141 return demuxer_->GetStartTime(); | |
| 142 } | |
| 143 | |
| 144 // KeyHandlingChunkDemuxer ----------------------------------------------------- | |
| 145 | |
| 146 namespace { | |
| 147 | |
| 148 class KeyHandlingChunkDemuxer : public KeyHandlingDemuxer { | |
| 149 public: | |
| 150 typedef base::Callback<void(const std::string& key_system)> NotifyDemuxerCB; | |
| 151 | |
| 152 KeyHandlingChunkDemuxer(WebKit::WebFrame* frame, | |
| 153 WebKit::WebMediaPlayerClient* client, | |
| 154 WebKit::WebMediaSource* media_source, | |
| 155 scoped_refptr<media::MediaLog> media_log, | |
| 156 NotifyDemuxerCB notify_demuxer_cb); | |
| 157 virtual ~KeyHandlingChunkDemuxer(); | |
| 158 | |
| 159 // KeyHandlingDemuxer | |
| 160 virtual WebKit::WebMediaPlayer::MediaKeyException GenerateKeyRequest( | |
| 161 const WebKit::WebString& key_system, | |
| 162 const unsigned char* init_data, | |
| 163 unsigned init_data_length) OVERRIDE; | |
| 164 virtual WebKit::WebMediaPlayer::MediaKeyException AddKey( | |
| 165 const WebKit::WebString& key_system, | |
| 166 const unsigned char* key, | |
| 167 unsigned key_length, | |
| 168 const unsigned char* init_data, | |
| 169 unsigned init_data_length, | |
| 170 const WebKit::WebString& session_id) OVERRIDE; | |
| 171 virtual WebKit::WebMediaPlayer::MediaKeyException CancelKeyRequest( | |
| 172 const WebKit::WebString& key_system, | |
| 173 const WebKit::WebString& session_id) OVERRIDE; | |
| 174 virtual int GetDurationMs() OVERRIDE; | |
| 175 | |
| 176 // media::Demuxer | |
| 177 virtual void Seek(base::TimeDelta time, const PipelineStatusCB& status_cb) | |
| 178 OVERRIDE; | |
| 179 | |
| 180 private: | |
| 181 // Callbacks for ChunkDemuxer & Decryptor. | |
| 182 void OnDemuxerOpened(); | |
| 183 void OnKeyAdded(const std::string& key_system, const std::string& session_id); | |
| 184 void OnKeyError(const std::string& key_system, | |
| 185 const std::string& session_id, | |
| 186 media::Decryptor::KeyError error_code, | |
| 187 int system_code); | |
| 188 void OnKeyMessage(const std::string& key_system, | |
| 189 const std::string& session_id, | |
| 190 const std::string& message, | |
| 191 const std::string& default_url); | |
| 192 void OnNeedKey(const std::string& key_system, | |
| 193 const std::string& type, | |
| 194 const std::string& session_id, | |
| 195 scoped_ptr<uint8[]> init_data, | |
| 196 int init_data_size); | |
| 197 void OnDecryptorReady(media::Decryptor*); | |
| 198 | |
| 199 base::WeakPtrFactory<KeyHandlingChunkDemuxer> weak_this_; | |
| 200 media::ChunkDemuxer* chunk_demuxer_; | |
| 201 WebKit::WebMediaPlayerClient* client_; | |
| 202 scoped_refptr<media::MediaLog> media_log_; | |
| 203 | |
| 204 // The decryptor that manages decryption keys and decrypts encrypted frames. | |
| 205 scoped_ptr<ProxyDecryptor> decryptor_; | |
| 206 | |
| 207 // The currently selected key system. Empty string means that no key system | |
| 208 // has been selected. | |
| 209 WebKit::WebString current_key_system_; | |
| 210 | |
| 211 // Temporary for EME v0.1. In the future the init data type should be passed | |
| 212 // through GenerateKeyRequest() directly from WebKit. | |
| 213 std::string init_data_type_; | |
| 214 | |
| 215 NotifyDemuxerCB notify_demuxer_cb_; | |
| 216 | |
| 217 scoped_ptr<WebKit::WebMediaSource> media_source_; | |
| 218 }; | |
| 219 | |
| 220 KeyHandlingChunkDemuxer::KeyHandlingChunkDemuxer( | |
| 63 WebKit::WebFrame* frame, | 221 WebKit::WebFrame* frame, |
| 64 WebKit::WebMediaPlayerClient* client, | 222 WebKit::WebMediaPlayerClient* client, |
| 65 WebMediaPlayerProxyAndroid* proxy, | 223 WebKit::WebMediaSource* media_source, |
| 66 int player_id, | 224 scoped_refptr<media::MediaLog> media_log, |
| 67 media::MediaLog* media_log) | 225 NotifyDemuxerCB notify_demuxer_cb) |
| 68 : weak_this_(this), | 226 : KeyHandlingDemuxer(NULL), |
| 227 weak_this_(this), | |
| 69 client_(client), | 228 client_(client), |
| 70 proxy_(proxy), | |
| 71 player_id_(player_id), | |
| 72 media_log_(media_log), | 229 media_log_(media_log), |
| 73 audio_params_(new MediaPlayerHostMsg_ReadFromDemuxerAck_Params), | 230 notify_demuxer_cb_(notify_demuxer_cb) { |
| 74 video_params_(new MediaPlayerHostMsg_ReadFromDemuxerAck_Params), | 231 chunk_demuxer_ = new media::ChunkDemuxer( |
| 75 seeking_(false) { | 232 BIND_TO_RENDER_LOOP(&KeyHandlingChunkDemuxer::OnDemuxerOpened), |
| 233 BIND_TO_RENDER_LOOP_2(&KeyHandlingChunkDemuxer::OnNeedKey, "", ""), | |
| 234 base::Bind(&LogMediaSourceError, media_log)); | |
| 235 demuxer_.reset(chunk_demuxer_); | |
| 236 media_source_.reset(media_source); | |
| 76 if (WebKit::WebRuntimeFeatures::isEncryptedMediaEnabled()) { | 237 if (WebKit::WebRuntimeFeatures::isEncryptedMediaEnabled()) { |
| 77 decryptor_.reset(new ProxyDecryptor( | 238 decryptor_.reset(new ProxyDecryptor( |
| 78 client, | 239 client, |
| 79 frame, | 240 frame, |
| 80 BIND_TO_RENDER_LOOP(&MediaSourceDelegate::OnKeyAdded), | 241 BIND_TO_RENDER_LOOP(&KeyHandlingChunkDemuxer::OnKeyAdded), |
| 81 BIND_TO_RENDER_LOOP(&MediaSourceDelegate::OnKeyError), | 242 BIND_TO_RENDER_LOOP(&KeyHandlingChunkDemuxer::OnKeyError), |
| 82 BIND_TO_RENDER_LOOP(&MediaSourceDelegate::OnKeyMessage), | 243 BIND_TO_RENDER_LOOP(&KeyHandlingChunkDemuxer::OnKeyMessage), |
| 83 BIND_TO_RENDER_LOOP(&MediaSourceDelegate::OnNeedKey))); | 244 BIND_TO_RENDER_LOOP(&KeyHandlingChunkDemuxer::OnNeedKey))); |
| 84 decryptor_->SetDecryptorReadyCB( | 245 decryptor_->SetDecryptorReadyCB( |
| 85 BIND_TO_RENDER_LOOP(&MediaSourceDelegate::OnDecryptorReady)); | 246 BIND_TO_RENDER_LOOP(&KeyHandlingChunkDemuxer::OnDecryptorReady)); |
| 86 } | 247 } |
| 87 } | 248 } |
| 88 | 249 |
| 89 MediaSourceDelegate::~MediaSourceDelegate() {} | 250 KeyHandlingChunkDemuxer::~KeyHandlingChunkDemuxer() {} |
| 90 | 251 |
| 91 void MediaSourceDelegate::Initialize( | 252 WebMediaPlayer::MediaKeyException KeyHandlingChunkDemuxer::GenerateKeyRequest( |
| 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 } | |
| 105 | |
| 106 const WebKit::WebTimeRanges& MediaSourceDelegate::Buffered() { | |
| 107 buffered_web_time_ranges_ = | |
| 108 ConvertToWebTimeRanges(buffered_time_ranges_); | |
| 109 return buffered_web_time_ranges_; | |
| 110 } | |
| 111 | |
| 112 size_t MediaSourceDelegate::DecodedFrameCount() const { | |
| 113 return statistics_.video_frames_decoded; | |
| 114 } | |
| 115 | |
| 116 size_t MediaSourceDelegate::DroppedFrameCount() const { | |
| 117 return statistics_.video_frames_dropped; | |
| 118 } | |
| 119 | |
| 120 size_t MediaSourceDelegate::AudioDecodedByteCount() const { | |
| 121 return statistics_.audio_bytes_decoded; | |
| 122 } | |
| 123 | |
| 124 size_t MediaSourceDelegate::VideoDecodedByteCount() const { | |
| 125 return statistics_.video_bytes_decoded; | |
| 126 } | |
| 127 | |
| 128 WebMediaPlayer::MediaKeyException MediaSourceDelegate::GenerateKeyRequest( | |
| 129 const WebString& key_system, | 253 const WebString& key_system, |
| 130 const unsigned char* init_data, | 254 const unsigned char* init_data, |
| 131 size_t init_data_length) { | 255 size_t init_data_length) { |
| 132 if (!IsSupportedKeySystem(key_system)) | 256 if (!IsSupportedKeySystem(key_system)) |
| 133 return WebMediaPlayer::MediaKeyExceptionKeySystemNotSupported; | 257 return WebMediaPlayer::MediaKeyExceptionKeySystemNotSupported; |
| 134 | 258 |
| 135 // We do not support run-time switching between key systems for now. | 259 // We do not support run-time switching between key systems for now. |
| 136 if (current_key_system_.isEmpty()) | 260 if (current_key_system_.isEmpty()) |
| 137 current_key_system_ = key_system; | 261 current_key_system_ = key_system; |
| 138 else if (key_system != current_key_system_) | 262 else if (key_system != current_key_system_) |
| 139 return WebMediaPlayer::MediaKeyExceptionInvalidPlayerState; | 263 return WebMediaPlayer::MediaKeyExceptionInvalidPlayerState; |
| 140 | 264 |
| 141 DVLOG(1) << "generateKeyRequest: " << key_system.utf8().data() << ": " | 265 DVLOG(1) << "generateKeyRequest: " << key_system.utf8().data() << ": " |
| 142 << std::string(reinterpret_cast<const char*>(init_data), | 266 << std::string(reinterpret_cast<const char*>(init_data), |
| 143 init_data_length); | 267 init_data_length); |
| 144 | 268 |
| 145 // TODO(xhwang): We assume all streams are from the same container (thus have | 269 // 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 | 270 // the same "type") for now. In the future, the "type" should be passed down |
| 147 // from the application. | 271 // from the application. |
| 148 if (!decryptor_->GenerateKeyRequest(key_system.utf8(), | 272 if (!decryptor_->GenerateKeyRequest(key_system.utf8(), |
| 149 init_data_type_, | 273 init_data_type_, |
| 150 init_data, init_data_length)) { | 274 init_data, init_data_length)) { |
| 151 current_key_system_.reset(); | 275 current_key_system_.reset(); |
| 152 return WebMediaPlayer::MediaKeyExceptionKeySystemNotSupported; | 276 return WebMediaPlayer::MediaKeyExceptionKeySystemNotSupported; |
| 153 } | 277 } |
| 154 | 278 |
| 155 return WebMediaPlayer::MediaKeyExceptionNoError; | 279 return WebMediaPlayer::MediaKeyExceptionNoError; |
| 156 } | 280 } |
| 157 | 281 |
| 158 WebMediaPlayer::MediaKeyException MediaSourceDelegate::AddKey( | 282 WebMediaPlayer::MediaKeyException KeyHandlingChunkDemuxer::AddKey( |
| 159 const WebString& key_system, | 283 const WebString& key_system, |
| 160 const unsigned char* key, | 284 const unsigned char* key, |
| 161 size_t key_length, | 285 size_t key_length, |
| 162 const unsigned char* init_data, | 286 const unsigned char* init_data, |
| 163 size_t init_data_length, | 287 size_t init_data_length, |
| 164 const WebString& session_id) { | 288 const WebString& session_id) { |
| 165 DCHECK(key); | 289 DCHECK(key); |
| 166 DCHECK_EQ(key_length, 16u); | 290 DCHECK_EQ(key_length, 16u); |
| 167 | 291 |
| 168 if (!IsSupportedKeySystem(key_system)) | 292 if (!IsSupportedKeySystem(key_system)) |
| 169 return WebMediaPlayer::MediaKeyExceptionKeySystemNotSupported; | 293 return WebMediaPlayer::MediaKeyExceptionKeySystemNotSupported; |
| 170 | 294 |
| 171 if (current_key_system_.isEmpty() || key_system != current_key_system_) | 295 if (current_key_system_.isEmpty() || key_system != current_key_system_) |
| 172 return WebMediaPlayer::MediaKeyExceptionInvalidPlayerState; | 296 return WebMediaPlayer::MediaKeyExceptionInvalidPlayerState; |
| 173 | 297 |
| 174 DVLOG(1) << "addKey: " << key_system.utf8().data() << ": " | 298 DVLOG(1) << "addKey: " << key_system.utf8().data() << ": " |
| 175 << base::HexEncode(key, key_length) << ", " | 299 << base::HexEncode(key, key_length) << ", " |
| 176 << base::HexEncode(init_data, std::max(init_data_length, 256u)) | 300 << base::HexEncode(init_data, std::max(init_data_length, 256u)) |
| 177 << " [" << session_id.utf8().data() << "]"; | 301 << " [" << session_id.utf8().data() << "]"; |
| 178 | 302 |
| 179 decryptor_->AddKey(key_system.utf8(), key, key_length, | 303 decryptor_->AddKey(key_system.utf8(), key, key_length, |
| 180 init_data, init_data_length, session_id.utf8()); | 304 init_data, init_data_length, session_id.utf8()); |
| 181 return WebMediaPlayer::MediaKeyExceptionNoError; | 305 return WebMediaPlayer::MediaKeyExceptionNoError; |
| 182 } | 306 } |
| 183 | 307 |
| 184 WebMediaPlayer::MediaKeyException MediaSourceDelegate::CancelKeyRequest( | 308 WebMediaPlayer::MediaKeyException KeyHandlingChunkDemuxer::CancelKeyRequest( |
| 185 const WebString& key_system, | 309 const WebString& key_system, |
| 186 const WebString& session_id) { | 310 const WebString& session_id) { |
| 187 if (!IsSupportedKeySystem(key_system)) | 311 if (!IsSupportedKeySystem(key_system)) |
| 188 return WebMediaPlayer::MediaKeyExceptionKeySystemNotSupported; | 312 return WebMediaPlayer::MediaKeyExceptionKeySystemNotSupported; |
| 189 | 313 |
| 190 if (current_key_system_.isEmpty() || key_system != current_key_system_) | 314 if (current_key_system_.isEmpty() || key_system != current_key_system_) |
| 191 return WebMediaPlayer::MediaKeyExceptionInvalidPlayerState; | 315 return WebMediaPlayer::MediaKeyExceptionInvalidPlayerState; |
| 192 | 316 |
| 193 decryptor_->CancelKeyRequest(key_system.utf8(), session_id.utf8()); | 317 decryptor_->CancelKeyRequest(key_system.utf8(), session_id.utf8()); |
| 194 return WebMediaPlayer::MediaKeyExceptionNoError; | 318 return WebMediaPlayer::MediaKeyExceptionNoError; |
| 195 } | 319 } |
| 196 | 320 |
| 321 int KeyHandlingChunkDemuxer::GetDurationMs() { | |
| 322 double duration_ms = chunk_demuxer_->GetDuration() * 1000; | |
| 323 if (duration_ms > std::numeric_limits<int>::max()) | |
|
Ami GONE FROM CHROMIUM
2013/05/01 22:01:37
this is still pretty fishy...
wonsik
2013/05/02 15:22:00
Logged warning.
| |
| 324 duration_ms = std::numeric_limits<int>::max(); | |
| 325 return duration_ms; | |
| 326 } | |
| 327 | |
| 328 void KeyHandlingChunkDemuxer::Seek(base::TimeDelta time, | |
| 329 const PipelineStatusCB& status_cb) { | |
| 330 chunk_demuxer_->StartWaitingForSeek(); | |
| 331 chunk_demuxer_->Seek(time, status_cb); | |
| 332 } | |
| 333 | |
| 334 void KeyHandlingChunkDemuxer::OnKeyError(const std::string& key_system, | |
| 335 const std::string& session_id, | |
| 336 media::Decryptor::KeyError error_code, | |
| 337 int system_code) { | |
| 338 client_->keyError( | |
| 339 WebString::fromUTF8(key_system), | |
| 340 WebString::fromUTF8(session_id), | |
| 341 static_cast<WebKit::WebMediaPlayerClient::MediaKeyErrorCode>(error_code), | |
| 342 system_code); | |
| 343 } | |
| 344 | |
| 345 void KeyHandlingChunkDemuxer::OnKeyMessage(const std::string& key_system, | |
| 346 const std::string& session_id, | |
| 347 const std::string& message, | |
| 348 const std::string& default_url) { | |
| 349 const GURL default_url_gurl(default_url); | |
| 350 DLOG_IF(WARNING, !default_url.empty() && !default_url_gurl.is_valid()) | |
| 351 << "Invalid URL in default_url: " << default_url; | |
| 352 | |
| 353 client_->keyMessage(WebString::fromUTF8(key_system), | |
| 354 WebString::fromUTF8(session_id), | |
| 355 reinterpret_cast<const uint8*>(message.data()), | |
| 356 message.size(), | |
| 357 default_url_gurl); | |
| 358 } | |
| 359 | |
| 360 void KeyHandlingChunkDemuxer::OnKeyAdded(const std::string& key_system, | |
| 361 const std::string& session_id) { | |
| 362 notify_demuxer_cb_.Run(key_system); | |
| 363 client_->keyAdded(WebString::fromUTF8(key_system), | |
| 364 WebString::fromUTF8(session_id)); | |
| 365 } | |
| 366 | |
| 367 void KeyHandlingChunkDemuxer::OnNeedKey(const std::string& key_system, | |
| 368 const std::string& session_id, | |
| 369 const std::string& type, | |
| 370 scoped_ptr<uint8[]> init_data, | |
| 371 int init_data_size) { | |
| 372 // Do not fire NeedKey event if encrypted media is not enabled. | |
| 373 if (!decryptor_) | |
| 374 return; | |
| 375 | |
| 376 CHECK(init_data_size >= 0); | |
| 377 DCHECK(init_data_type_.empty() || type.empty() || type == init_data_type_); | |
| 378 if (init_data_type_.empty()) | |
| 379 init_data_type_ = type; | |
| 380 | |
| 381 client_->keyNeeded(WebString::fromUTF8(key_system), | |
| 382 WebString::fromUTF8(session_id), | |
| 383 init_data.get(), | |
| 384 init_data_size); | |
| 385 } | |
| 386 | |
| 387 void KeyHandlingChunkDemuxer::OnDecryptorReady(media::Decryptor* decryptor) {} | |
| 388 | |
| 389 void KeyHandlingChunkDemuxer::OnDemuxerOpened() { | |
| 390 media_source_->open(new WebMediaSourceClientImpl( | |
| 391 chunk_demuxer_, base::Bind(&LogMediaSourceError, media_log_))); | |
| 392 } | |
| 393 | |
| 394 } // anonymous namespace | |
| 395 | |
| 396 // MediaSourceDelegate --------------------------------------------------------- | |
| 397 | |
| 398 MediaSourceDelegate::MediaSourceDelegate( | |
| 399 WebMediaPlayerProxyAndroid* proxy, | |
| 400 int player_id, | |
| 401 const UpdateNetworkStateCB& update_network_state_cb) | |
| 402 : weak_this_(this), | |
| 403 proxy_(proxy), | |
| 404 player_id_(player_id), | |
| 405 update_network_state_cb_(update_network_state_cb), | |
| 406 audio_params_(new MediaPlayerHostMsg_ReadFromDemuxerAck_Params), | |
| 407 video_params_(new MediaPlayerHostMsg_ReadFromDemuxerAck_Params), | |
| 408 seeking_(false), | |
| 409 low_latency_mode_(false) { | |
| 410 } | |
| 411 | |
| 412 MediaSourceDelegate::~MediaSourceDelegate() {} | |
| 413 | |
| 414 void MediaSourceDelegate::InitializeMediaSource( | |
| 415 WebKit::WebFrame * frame, | |
| 416 WebKit::WebMediaPlayerClient * client, | |
| 417 WebKit::WebMediaSource* media_source, | |
| 418 media::MediaLog * media_log) { | |
| 419 DCHECK(media_source); | |
| 420 demuxer_.reset(new KeyHandlingChunkDemuxer( | |
| 421 frame, | |
| 422 client, | |
| 423 media_source, | |
| 424 scoped_refptr<media::MediaLog>(media_log), | |
| 425 BIND_TO_RENDER_LOOP(&MediaSourceDelegate::NotifyDemuxerReady))); | |
| 426 demuxer_->Initialize(this, | |
| 427 BIND_TO_RENDER_LOOP(&MediaSourceDelegate::OnDemuxerInitDone)); | |
| 428 } | |
| 429 | |
| 430 void MediaSourceDelegate::InitializeMediaStream(media::Demuxer* demuxer) { | |
| 431 DCHECK(demuxer); | |
| 432 low_latency_mode_ = true; | |
| 433 demuxer_.reset(new KeyHandlingDemuxer(demuxer)); | |
| 434 demuxer_->Initialize(this, | |
| 435 BIND_TO_RENDER_LOOP(&MediaSourceDelegate::OnDemuxerInitDone)); | |
| 436 } | |
| 437 | |
| 438 const WebKit::WebTimeRanges& MediaSourceDelegate::Buffered() { | |
| 439 buffered_web_time_ranges_ = | |
| 440 ConvertToWebTimeRanges(buffered_time_ranges_); | |
| 441 return buffered_web_time_ranges_; | |
| 442 } | |
| 443 | |
| 444 unsigned MediaSourceDelegate::DecodedFrameCount() const { | |
| 445 return statistics_.video_frames_decoded; | |
| 446 } | |
| 447 | |
| 448 unsigned MediaSourceDelegate::DroppedFrameCount() const { | |
| 449 return statistics_.video_frames_dropped; | |
| 450 } | |
| 451 | |
| 452 unsigned MediaSourceDelegate::AudioDecodedByteCount() const { | |
| 453 return statistics_.audio_bytes_decoded;; | |
| 454 } | |
| 455 | |
| 456 unsigned MediaSourceDelegate::VideoDecodedByteCount() const { | |
| 457 return statistics_.video_bytes_decoded; | |
| 458 } | |
| 459 | |
| 460 WebMediaPlayer::MediaKeyException MediaSourceDelegate::GenerateKeyRequest( | |
| 461 const WebString& key_system, | |
| 462 const unsigned char* init_data, | |
| 463 unsigned init_data_length) { | |
| 464 return demuxer_->GenerateKeyRequest(key_system, init_data, init_data_length); | |
| 465 } | |
| 466 | |
| 467 WebMediaPlayer::MediaKeyException MediaSourceDelegate::AddKey( | |
| 468 const WebString& key_system, | |
| 469 const unsigned char* key, | |
| 470 unsigned key_length, | |
| 471 const unsigned char* init_data, | |
| 472 unsigned init_data_length, | |
| 473 const WebString& session_id) { | |
| 474 return demuxer_->AddKey( | |
| 475 key_system, key, key_length, init_data, init_data_length, session_id); | |
| 476 } | |
| 477 | |
| 478 WebMediaPlayer::MediaKeyException MediaSourceDelegate::CancelKeyRequest( | |
| 479 const WebString& key_system, | |
| 480 const WebString& session_id) { | |
| 481 return demuxer_->CancelKeyRequest(key_system, session_id); | |
| 482 } | |
| 483 | |
| 197 void MediaSourceDelegate::Seek(base::TimeDelta time) { | 484 void MediaSourceDelegate::Seek(base::TimeDelta time) { |
| 198 seeking_ = true; | 485 seeking_ = true; |
| 199 DCHECK(chunk_demuxer_); | 486 DCHECK(demuxer_); |
| 200 if (!chunk_demuxer_) | 487 if (!demuxer_) |
| 201 return; | 488 return; |
| 202 chunk_demuxer_->StartWaitingForSeek(); | 489 demuxer_->Seek(time, |
| 203 chunk_demuxer_->Seek(time, | |
| 204 BIND_TO_RENDER_LOOP(&MediaSourceDelegate::OnDemuxerError)); | 490 BIND_TO_RENDER_LOOP(&MediaSourceDelegate::OnDemuxerError)); |
| 205 } | 491 } |
| 206 | 492 |
| 207 void MediaSourceDelegate::SetTotalBytes(int64 total_bytes) { | 493 void MediaSourceDelegate::SetTotalBytes(int64 total_bytes) { |
| 208 NOTIMPLEMENTED(); | 494 NOTIMPLEMENTED(); |
| 209 } | 495 } |
| 210 | 496 |
| 211 void MediaSourceDelegate::AddBufferedByteRange(int64 start, int64 end) { | 497 void MediaSourceDelegate::AddBufferedByteRange(int64 start, int64 end) { |
| 212 NOTIMPLEMENTED(); | 498 NOTIMPLEMENTED(); |
| 213 } | 499 } |
| 214 | 500 |
| 215 void MediaSourceDelegate::AddBufferedTimeRange(base::TimeDelta start, | 501 void MediaSourceDelegate::AddBufferedTimeRange(base::TimeDelta start, |
| 216 base::TimeDelta end) { | 502 base::TimeDelta end) { |
| 217 buffered_time_ranges_.Add(start, end); | 503 buffered_time_ranges_.Add(start, end); |
| 218 } | 504 } |
| 219 | 505 |
| 220 void MediaSourceDelegate::SetDuration(base::TimeDelta duration) { | 506 void MediaSourceDelegate::SetDuration(base::TimeDelta duration) { |
| 221 // Do nothing | 507 // Do nothing |
| 222 } | 508 } |
| 223 | 509 |
| 224 void MediaSourceDelegate::OnReadFromDemuxer(media::DemuxerStream::Type type, | 510 void MediaSourceDelegate::OnReadFromDemuxer(media::DemuxerStream::Type type, |
| 225 bool seek_done) { | 511 bool seek_done) { |
| 226 if (seeking_ && !seek_done) | 512 if (seeking_ && !seek_done) |
| 227 return; // Drop the request during seeking. | 513 return; // Drop the request during seeking. |
| 228 seeking_ = false; | 514 seeking_ = false; |
| 229 | 515 |
| 230 DCHECK(type == DemuxerStream::AUDIO || type == DemuxerStream::VIDEO); | 516 DCHECK(type == DemuxerStream::AUDIO || type == DemuxerStream::VIDEO); |
| 517 | |
| 518 // When in low latency mode, don't wait to accumulate multiple packets per IPC | |
| 519 // communication. | |
| 520 size_t access_unit_size = low_latency_mode_ ? 1 : kAccessUnitSize; | |
| 521 | |
| 231 MediaPlayerHostMsg_ReadFromDemuxerAck_Params* params = | 522 MediaPlayerHostMsg_ReadFromDemuxerAck_Params* params = |
| 232 type == DemuxerStream::AUDIO ? audio_params_.get() : video_params_.get(); | 523 type == DemuxerStream::AUDIO ? audio_params_.get() : video_params_.get(); |
| 233 params->type = type; | 524 params->type = type; |
| 234 params->access_units.resize(kAccessUnitSize); | 525 params->access_units.resize(access_unit_size); |
| 235 DemuxerStream* stream = chunk_demuxer_->GetStream(type); | 526 DemuxerStream* stream = demuxer_->GetStream(type); |
| 236 DCHECK(stream != NULL); | 527 DCHECK(stream != NULL); |
| 237 ReadFromDemuxerStream(stream, params, 0); | 528 ReadFromDemuxerStream(stream, params, 0); |
| 238 } | 529 } |
| 239 | 530 |
| 240 void MediaSourceDelegate::ReadFromDemuxerStream( | 531 void MediaSourceDelegate::ReadFromDemuxerStream( |
| 241 DemuxerStream* stream, | 532 DemuxerStream* stream, |
| 242 MediaPlayerHostMsg_ReadFromDemuxerAck_Params* params, | 533 MediaPlayerHostMsg_ReadFromDemuxerAck_Params* params, |
| 243 size_t index) { | 534 size_t index) { |
| 244 stream->Read(BIND_TO_RENDER_LOOP_3(&MediaSourceDelegate::OnBufferReady, | 535 stream->Read(BIND_TO_RENDER_LOOP_3(&MediaSourceDelegate::OnBufferReady, |
| 245 stream, params, index)); | 536 stream, params, index)); |
| (...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 343 if (status != media::PIPELINE_OK) { | 634 if (status != media::PIPELINE_OK) { |
| 344 OnDemuxerError(status); | 635 OnDemuxerError(status); |
| 345 return; | 636 return; |
| 346 } | 637 } |
| 347 NotifyDemuxerReady(""); | 638 NotifyDemuxerReady(""); |
| 348 } | 639 } |
| 349 | 640 |
| 350 void MediaSourceDelegate::NotifyDemuxerReady( | 641 void MediaSourceDelegate::NotifyDemuxerReady( |
| 351 const std::string& key_system) { | 642 const std::string& key_system) { |
| 352 MediaPlayerHostMsg_DemuxerReady_Params params; | 643 MediaPlayerHostMsg_DemuxerReady_Params params; |
| 353 DemuxerStream* audio_stream = chunk_demuxer_->GetStream(DemuxerStream::AUDIO); | 644 DemuxerStream* audio_stream = demuxer_->GetStream(DemuxerStream::AUDIO); |
| 354 if (audio_stream) { | 645 if (audio_stream) { |
| 355 const media::AudioDecoderConfig& config = | 646 const media::AudioDecoderConfig& config = |
| 356 audio_stream->audio_decoder_config(); | 647 audio_stream->audio_decoder_config(); |
| 357 params.audio_codec = config.codec(); | 648 params.audio_codec = config.codec(); |
| 358 params.audio_channels = | 649 params.audio_channels = |
| 359 media::ChannelLayoutToChannelCount(config.channel_layout()); | 650 media::ChannelLayoutToChannelCount(config.channel_layout()); |
| 360 params.audio_sampling_rate = config.samples_per_second(); | 651 params.audio_sampling_rate = config.samples_per_second(); |
| 361 params.is_audio_encrypted = config.is_encrypted(); | 652 params.is_audio_encrypted = config.is_encrypted(); |
| 362 } | 653 } |
| 363 DemuxerStream* video_stream = chunk_demuxer_->GetStream(DemuxerStream::VIDEO); | 654 DemuxerStream* video_stream = demuxer_->GetStream(DemuxerStream::VIDEO); |
| 364 if (video_stream) { | 655 if (video_stream) { |
| 365 const media::VideoDecoderConfig& config = | 656 const media::VideoDecoderConfig& config = |
| 366 video_stream->video_decoder_config(); | 657 video_stream->video_decoder_config(); |
| 367 params.video_codec = config.codec(); | 658 params.video_codec = config.codec(); |
| 368 params.video_size = config.natural_size(); | 659 params.video_size = config.natural_size(); |
| 369 params.is_video_encrypted = config.is_encrypted(); | 660 params.is_video_encrypted = config.is_encrypted(); |
| 370 } | 661 } |
| 371 double duration_ms = chunk_demuxer_->GetDuration() * 1000; | 662 params.duration_ms = demuxer_->GetDurationMs(); |
| 372 DCHECK(duration_ms >= 0); | |
| 373 if (duration_ms > std::numeric_limits<int>::max()) | |
| 374 duration_ms = std::numeric_limits<int>::max(); | |
| 375 params.duration_ms = duration_ms; | |
| 376 params.key_system = key_system; | 663 params.key_system = key_system; |
| 377 | 664 |
| 378 bool ready_to_send = (!params.is_audio_encrypted && | 665 bool ready_to_send = (!params.is_audio_encrypted && |
| 379 !params.is_video_encrypted) || !key_system.empty(); | 666 !params.is_video_encrypted) || !key_system.empty(); |
| 380 if (proxy_ && ready_to_send) | 667 if (proxy_ && ready_to_send) |
| 381 proxy_->DemuxerReady(player_id_, params); | 668 proxy_->DemuxerReady(player_id_, params); |
| 382 } | 669 } |
| 383 | 670 |
| 384 void MediaSourceDelegate::OnDemuxerOpened() { | |
| 385 media_source_->open(new WebMediaSourceClientImpl( | |
| 386 chunk_demuxer_.get(), base::Bind(&LogMediaSourceError, media_log_))); | |
| 387 } | |
| 388 | |
| 389 void MediaSourceDelegate::OnKeyError(const std::string& key_system, | |
| 390 const std::string& session_id, | |
| 391 media::Decryptor::KeyError error_code, | |
| 392 int system_code) { | |
| 393 client_->keyError( | |
| 394 WebString::fromUTF8(key_system), | |
| 395 WebString::fromUTF8(session_id), | |
| 396 static_cast<WebKit::WebMediaPlayerClient::MediaKeyErrorCode>(error_code), | |
| 397 system_code); | |
| 398 } | |
| 399 | |
| 400 void MediaSourceDelegate::OnKeyMessage(const std::string& key_system, | |
| 401 const std::string& session_id, | |
| 402 const std::string& message, | |
| 403 const std::string& default_url) { | |
| 404 const GURL default_url_gurl(default_url); | |
| 405 DLOG_IF(WARNING, !default_url.empty() && !default_url_gurl.is_valid()) | |
| 406 << "Invalid URL in default_url: " << default_url; | |
| 407 | |
| 408 client_->keyMessage(WebString::fromUTF8(key_system), | |
| 409 WebString::fromUTF8(session_id), | |
| 410 reinterpret_cast<const uint8*>(message.data()), | |
| 411 message.size(), | |
| 412 default_url_gurl); | |
| 413 } | |
| 414 | |
| 415 void MediaSourceDelegate::OnKeyAdded(const std::string& key_system, | |
| 416 const std::string& session_id) { | |
| 417 NotifyDemuxerReady(key_system); | |
| 418 client_->keyAdded(WebString::fromUTF8(key_system), | |
| 419 WebString::fromUTF8(session_id)); | |
| 420 } | |
| 421 | |
| 422 void MediaSourceDelegate::OnNeedKey(const std::string& key_system, | |
| 423 const std::string& session_id, | |
| 424 const std::string& type, | |
| 425 scoped_ptr<uint8[]> init_data, | |
| 426 int init_data_size) { | |
| 427 // Do not fire NeedKey event if encrypted media is not enabled. | |
| 428 if (!decryptor_) | |
| 429 return; | |
| 430 | |
| 431 CHECK(init_data_size >= 0); | |
| 432 DCHECK(init_data_type_.empty() || type.empty() || type == init_data_type_); | |
| 433 if (init_data_type_.empty()) | |
| 434 init_data_type_ = type; | |
| 435 | |
| 436 client_->keyNeeded(WebString::fromUTF8(key_system), | |
| 437 WebString::fromUTF8(session_id), | |
| 438 init_data.get(), | |
| 439 init_data_size); | |
| 440 } | |
| 441 | |
| 442 void MediaSourceDelegate::OnDecryptorReady(media::Decryptor* decryptor) {} | |
| 443 | |
| 444 } // namespace webkit_media | 671 } // namespace webkit_media |
| OLD | NEW |