OLD | NEW |
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 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/renderer/media/android/media_source_delegate.h" | 5 #include "webkit/renderer/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/public/platform/WebString.h" | 14 #include "third_party/WebKit/public/platform/WebString.h" |
15 #include "third_party/WebKit/Source/WebKit/chromium/public/WebMediaSource.h" | 15 #include "third_party/WebKit/Source/WebKit/chromium/public/WebMediaSource.h" |
16 #include "third_party/WebKit/Source/WebKit/chromium/public/WebRuntimeFeatures.h" | 16 #include "third_party/WebKit/Source/WebKit/chromium/public/WebRuntimeFeatures.h" |
17 #include "webkit/renderer/media/android/webmediaplayer_proxy_android.h" | 17 #include "webkit/renderer/media/android/webmediaplayer_proxy_android.h" |
18 #include "webkit/renderer/media/crypto/key_systems.h" | 18 #include "webkit/renderer/media/crypto/key_systems.h" |
19 #include "webkit/renderer/media/webmediaplayer_util.h" | 19 #include "webkit/renderer/media/webmediaplayer_util.h" |
20 #include "webkit/renderer/media/webmediasourceclient_impl.h" | 20 #include "webkit/renderer/media/webmediasourceclient_impl.h" |
21 | 21 |
22 using media::DemuxerStream; | 22 using media::DemuxerStream; |
23 using media::MediaPlayerHostMsg_DemuxerReady_Params; | 23 using media::MediaPlayerHostMsg_DemuxerReady_Params; |
24 using media::MediaPlayerHostMsg_ReadFromDemuxerAck_Params; | 24 using media::MediaPlayerHostMsg_ReadFromDemuxerAck_Params; |
25 using WebKit::WebMediaPlayer; | 25 using WebKit::WebMediaPlayer; |
26 using WebKit::WebString; | 26 using WebKit::WebString; |
27 | 27 |
28 namespace { | 28 namespace { |
29 | 29 |
30 // The size of the access unit to transfer in an IPC. | 30 // The size of the access unit to transfer in an IPC in case of MediaSource. |
31 // 16: approximately 250ms of content in 60 fps movies. | 31 // 16: approximately 250ms of content in 60 fps movies. |
32 const size_t kAccessUnitSize = 16; | 32 const size_t kAccessUnitSizeForMediaSource = 16; |
33 | 33 |
34 const uint8 kVorbisPadding[] = { 0xff, 0xff, 0xff, 0xff }; | 34 const uint8 kVorbisPadding[] = { 0xff, 0xff, 0xff, 0xff }; |
35 | 35 |
36 } // namespace | 36 } // namespace |
37 | 37 |
38 namespace webkit_media { | 38 namespace webkit_media { |
39 | 39 |
40 #define BIND_TO_RENDER_LOOP(function) \ | 40 #define BIND_TO_RENDER_LOOP(function) \ |
41 media::BindToLoop(base::MessageLoopProxy::current(), \ | 41 media::BindToLoop(base::MessageLoopProxy::current(), \ |
42 base::Bind(function, weak_this_.GetWeakPtr())) | 42 base::Bind(function, weak_this_.GetWeakPtr())) |
(...skipping 16 matching lines...) Expand all Loading... |
59 media_log->AddEvent(media_log->CreateMediaSourceErrorEvent(error)); | 59 media_log->AddEvent(media_log->CreateMediaSourceErrorEvent(error)); |
60 } | 60 } |
61 | 61 |
62 MediaSourceDelegate::MediaSourceDelegate(WebMediaPlayerProxyAndroid* proxy, | 62 MediaSourceDelegate::MediaSourceDelegate(WebMediaPlayerProxyAndroid* proxy, |
63 int player_id, | 63 int player_id, |
64 media::MediaLog* media_log) | 64 media::MediaLog* media_log) |
65 : weak_this_(this), | 65 : weak_this_(this), |
66 proxy_(proxy), | 66 proxy_(proxy), |
67 player_id_(player_id), | 67 player_id_(player_id), |
68 media_log_(media_log), | 68 media_log_(media_log), |
| 69 demuxer_(NULL), |
69 audio_params_(new MediaPlayerHostMsg_ReadFromDemuxerAck_Params), | 70 audio_params_(new MediaPlayerHostMsg_ReadFromDemuxerAck_Params), |
70 video_params_(new MediaPlayerHostMsg_ReadFromDemuxerAck_Params), | 71 video_params_(new MediaPlayerHostMsg_ReadFromDemuxerAck_Params), |
71 seeking_(false) { | 72 seeking_(false), |
| 73 access_unit_size_(0) { |
72 } | 74 } |
73 | 75 |
74 MediaSourceDelegate::~MediaSourceDelegate() { | 76 MediaSourceDelegate::~MediaSourceDelegate() { |
75 DVLOG(1) << "MediaSourceDelegate::~MediaSourceDelegate() : " << player_id_; | 77 DVLOG(1) << "MediaSourceDelegate::~MediaSourceDelegate() : " << player_id_; |
76 DCHECK(!chunk_demuxer_); | 78 DCHECK(!chunk_demuxer_); |
| 79 DCHECK(!demuxer_); |
77 } | 80 } |
78 | 81 |
79 void MediaSourceDelegate::Destroy() { | 82 void MediaSourceDelegate::Destroy() { |
80 DVLOG(1) << "MediaSourceDelegate::Destroy() : " << player_id_; | 83 DVLOG(1) << "MediaSourceDelegate::Destroy() : " << player_id_; |
81 if (!chunk_demuxer_) { | 84 if (!demuxer_) { |
82 delete this; | 85 delete this; |
83 return; | 86 return; |
84 } | 87 } |
85 | 88 |
86 update_network_state_cb_.Reset(); | 89 update_network_state_cb_.Reset(); |
87 media_source_.reset(); | 90 media_source_.reset(); |
88 proxy_ = NULL; | 91 proxy_ = NULL; |
89 | 92 |
90 chunk_demuxer_->Stop( | 93 demuxer_ = NULL; |
91 BIND_TO_RENDER_LOOP(&MediaSourceDelegate::OnDemuxerStopDone)); | 94 if (chunk_demuxer_) |
| 95 chunk_demuxer_->Stop( |
| 96 BIND_TO_RENDER_LOOP(&MediaSourceDelegate::OnDemuxerStopDone)); |
92 } | 97 } |
93 | 98 |
94 void MediaSourceDelegate::Initialize( | 99 void MediaSourceDelegate::InitializeMediaSource( |
95 WebKit::WebMediaSource* media_source, | 100 WebKit::WebMediaSource* media_source, |
96 const media::NeedKeyCB& need_key_cb, | 101 const media::NeedKeyCB& need_key_cb, |
97 const UpdateNetworkStateCB& update_network_state_cb) { | 102 const UpdateNetworkStateCB& update_network_state_cb) { |
98 DCHECK(media_source); | 103 DCHECK(media_source); |
99 media_source_.reset(media_source); | 104 media_source_.reset(media_source); |
100 need_key_cb_ = need_key_cb; | 105 need_key_cb_ = need_key_cb; |
101 update_network_state_cb_ = update_network_state_cb; | 106 update_network_state_cb_ = update_network_state_cb; |
102 | 107 |
103 chunk_demuxer_.reset(new media::ChunkDemuxer( | 108 chunk_demuxer_.reset(new media::ChunkDemuxer( |
104 BIND_TO_RENDER_LOOP(&MediaSourceDelegate::OnDemuxerOpened), | 109 BIND_TO_RENDER_LOOP(&MediaSourceDelegate::OnDemuxerOpened), |
105 BIND_TO_RENDER_LOOP_2(&MediaSourceDelegate::OnNeedKey, "", ""), | 110 BIND_TO_RENDER_LOOP_2(&MediaSourceDelegate::OnNeedKey, "", ""), |
106 base::Bind(&MediaSourceDelegate::OnAddTextTrack, | 111 base::Bind(&MediaSourceDelegate::OnAddTextTrack, |
107 base::Unretained(this)), | 112 base::Unretained(this)), |
108 base::Bind(&LogMediaSourceError, media_log_))); | 113 base::Bind(&LogMediaSourceError, media_log_))); |
109 chunk_demuxer_->Initialize(this, | 114 chunk_demuxer_->Initialize(this, |
110 BIND_TO_RENDER_LOOP(&MediaSourceDelegate::OnDemuxerInitDone)); | 115 BIND_TO_RENDER_LOOP(&MediaSourceDelegate::OnDemuxerInitDone)); |
| 116 demuxer_ = chunk_demuxer_.get(); |
| 117 access_unit_size_ = kAccessUnitSizeForMediaSource; |
111 } | 118 } |
112 | 119 |
| 120 #if defined(GOOGLE_TV) |
| 121 void MediaSourceDelegate::InitializeMediaStream( |
| 122 media::Demuxer* demuxer, |
| 123 const UpdateNetworkStateCB& update_network_state_cb) { |
| 124 DCHECK(demuxer); |
| 125 demuxer_ = demuxer; |
| 126 update_network_state_cb_ = update_network_state_cb; |
| 127 |
| 128 demuxer_->Initialize(this, |
| 129 BIND_TO_RENDER_LOOP(&MediaSourceDelegate::OnDemuxerInitDone)); |
| 130 // When playing Media Stream, don't wait to accumulate multiple packets per |
| 131 // IPC communication. |
| 132 access_unit_size_ = 1; |
| 133 } |
| 134 #endif |
| 135 |
113 const WebKit::WebTimeRanges& MediaSourceDelegate::Buffered() { | 136 const WebKit::WebTimeRanges& MediaSourceDelegate::Buffered() { |
114 buffered_web_time_ranges_ = | 137 buffered_web_time_ranges_ = |
115 ConvertToWebTimeRanges(buffered_time_ranges_); | 138 ConvertToWebTimeRanges(buffered_time_ranges_); |
116 return buffered_web_time_ranges_; | 139 return buffered_web_time_ranges_; |
117 } | 140 } |
118 | 141 |
119 size_t MediaSourceDelegate::DecodedFrameCount() const { | 142 size_t MediaSourceDelegate::DecodedFrameCount() const { |
120 return statistics_.video_frames_decoded; | 143 return statistics_.video_frames_decoded; |
121 } | 144 } |
122 | 145 |
123 size_t MediaSourceDelegate::DroppedFrameCount() const { | 146 size_t MediaSourceDelegate::DroppedFrameCount() const { |
124 return statistics_.video_frames_dropped; | 147 return statistics_.video_frames_dropped; |
125 } | 148 } |
126 | 149 |
127 size_t MediaSourceDelegate::AudioDecodedByteCount() const { | 150 size_t MediaSourceDelegate::AudioDecodedByteCount() const { |
128 return statistics_.audio_bytes_decoded; | 151 return statistics_.audio_bytes_decoded; |
129 } | 152 } |
130 | 153 |
131 size_t MediaSourceDelegate::VideoDecodedByteCount() const { | 154 size_t MediaSourceDelegate::VideoDecodedByteCount() const { |
132 return statistics_.video_bytes_decoded; | 155 return statistics_.video_bytes_decoded; |
133 } | 156 } |
134 | 157 |
135 void MediaSourceDelegate::Seek(base::TimeDelta time) { | 158 void MediaSourceDelegate::Seek(base::TimeDelta time) { |
136 DVLOG(1) << "MediaSourceDelegate::Seek(" << time.InSecondsF() << ") : " | 159 DVLOG(1) << "MediaSourceDelegate::Seek(" << time.InSecondsF() << ") : " |
137 << player_id_; | 160 << player_id_; |
138 seeking_ = true; | 161 seeking_ = true; |
139 DCHECK(chunk_demuxer_); | 162 DCHECK(demuxer_); |
140 if (!chunk_demuxer_) | 163 if (chunk_demuxer_) |
141 return; | 164 chunk_demuxer_->StartWaitingForSeek(); |
142 chunk_demuxer_->StartWaitingForSeek(); | 165 demuxer_->Seek(time, |
143 chunk_demuxer_->Seek(time, | |
144 BIND_TO_RENDER_LOOP(&MediaSourceDelegate::OnDemuxerError)); | 166 BIND_TO_RENDER_LOOP(&MediaSourceDelegate::OnDemuxerError)); |
145 } | 167 } |
146 | 168 |
147 void MediaSourceDelegate::CancelPendingSeek() { | 169 void MediaSourceDelegate::CancelPendingSeek() { |
148 if (chunk_demuxer_) | 170 if (chunk_demuxer_) |
149 chunk_demuxer_->CancelPendingSeek(); | 171 chunk_demuxer_->CancelPendingSeek(); |
150 } | 172 } |
151 | 173 |
152 void MediaSourceDelegate::SetTotalBytes(int64 total_bytes) { | 174 void MediaSourceDelegate::SetTotalBytes(int64 total_bytes) { |
153 NOTIMPLEMENTED(); | 175 NOTIMPLEMENTED(); |
(...skipping 14 matching lines...) Expand all Loading... |
168 | 190 |
169 void MediaSourceDelegate::OnReadFromDemuxer(media::DemuxerStream::Type type, | 191 void MediaSourceDelegate::OnReadFromDemuxer(media::DemuxerStream::Type type, |
170 bool seek_done) { | 192 bool seek_done) { |
171 DVLOG(1) << "MediaSourceDelegate::OnReadFromDemuxer(" << type | 193 DVLOG(1) << "MediaSourceDelegate::OnReadFromDemuxer(" << type |
172 << ", " << seek_done << ") : " << player_id_; | 194 << ", " << seek_done << ") : " << player_id_; |
173 if (seeking_ && !seek_done) | 195 if (seeking_ && !seek_done) |
174 return; // Drop the request during seeking. | 196 return; // Drop the request during seeking. |
175 seeking_ = false; | 197 seeking_ = false; |
176 | 198 |
177 DCHECK(type == DemuxerStream::AUDIO || type == DemuxerStream::VIDEO); | 199 DCHECK(type == DemuxerStream::AUDIO || type == DemuxerStream::VIDEO); |
| 200 // The access unit size should have been initialized properly at this stage. |
| 201 DCHECK_GT(access_unit_size_, 0u); |
178 MediaPlayerHostMsg_ReadFromDemuxerAck_Params* params = | 202 MediaPlayerHostMsg_ReadFromDemuxerAck_Params* params = |
179 type == DemuxerStream::AUDIO ? audio_params_.get() : video_params_.get(); | 203 type == DemuxerStream::AUDIO ? audio_params_.get() : video_params_.get(); |
180 params->type = type; | 204 params->type = type; |
181 params->access_units.resize(kAccessUnitSize); | 205 params->access_units.resize(access_unit_size_); |
182 DemuxerStream* stream = chunk_demuxer_->GetStream(type); | 206 DemuxerStream* stream = demuxer_->GetStream(type); |
183 DCHECK(stream != NULL); | 207 DCHECK(stream != NULL); |
184 ReadFromDemuxerStream(stream, params, 0); | 208 ReadFromDemuxerStream(stream, params, 0); |
185 } | 209 } |
186 | 210 |
187 void MediaSourceDelegate::ReadFromDemuxerStream( | 211 void MediaSourceDelegate::ReadFromDemuxerStream( |
188 DemuxerStream* stream, | 212 DemuxerStream* stream, |
189 MediaPlayerHostMsg_ReadFromDemuxerAck_Params* params, | 213 MediaPlayerHostMsg_ReadFromDemuxerAck_Params* params, |
190 size_t index) { | 214 size_t index) { |
191 stream->Read(BIND_TO_RENDER_LOOP_3(&MediaSourceDelegate::OnBufferReady, | 215 stream->Read(BIND_TO_RENDER_LOOP_3(&MediaSourceDelegate::OnBufferReady, |
192 stream, params, index)); | 216 stream, params, index)); |
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
304 } | 328 } |
305 | 329 |
306 void MediaSourceDelegate::OnDemuxerStopDone() { | 330 void MediaSourceDelegate::OnDemuxerStopDone() { |
307 DVLOG(1) << "MediaSourceDelegate::OnDemuxerStopDone() : " << player_id_; | 331 DVLOG(1) << "MediaSourceDelegate::OnDemuxerStopDone() : " << player_id_; |
308 chunk_demuxer_.reset(); | 332 chunk_demuxer_.reset(); |
309 delete this; | 333 delete this; |
310 } | 334 } |
311 | 335 |
312 void MediaSourceDelegate::NotifyDemuxerReady(const std::string& key_system) { | 336 void MediaSourceDelegate::NotifyDemuxerReady(const std::string& key_system) { |
313 MediaPlayerHostMsg_DemuxerReady_Params params; | 337 MediaPlayerHostMsg_DemuxerReady_Params params; |
314 DemuxerStream* audio_stream = chunk_demuxer_->GetStream(DemuxerStream::AUDIO); | 338 DemuxerStream* audio_stream = demuxer_->GetStream(DemuxerStream::AUDIO); |
315 if (audio_stream) { | 339 if (audio_stream) { |
316 const media::AudioDecoderConfig& config = | 340 const media::AudioDecoderConfig& config = |
317 audio_stream->audio_decoder_config(); | 341 audio_stream->audio_decoder_config(); |
318 params.audio_codec = config.codec(); | 342 params.audio_codec = config.codec(); |
319 params.audio_channels = | 343 params.audio_channels = |
320 media::ChannelLayoutToChannelCount(config.channel_layout()); | 344 media::ChannelLayoutToChannelCount(config.channel_layout()); |
321 params.audio_sampling_rate = config.samples_per_second(); | 345 params.audio_sampling_rate = config.samples_per_second(); |
322 params.is_audio_encrypted = config.is_encrypted(); | 346 params.is_audio_encrypted = config.is_encrypted(); |
323 params.audio_extra_data = std::vector<uint8>( | 347 params.audio_extra_data = std::vector<uint8>( |
324 config.extra_data(), config.extra_data() + config.extra_data_size()); | 348 config.extra_data(), config.extra_data() + config.extra_data_size()); |
325 } | 349 } |
326 DemuxerStream* video_stream = chunk_demuxer_->GetStream(DemuxerStream::VIDEO); | 350 DemuxerStream* video_stream = demuxer_->GetStream(DemuxerStream::VIDEO); |
327 if (video_stream) { | 351 if (video_stream) { |
328 const media::VideoDecoderConfig& config = | 352 const media::VideoDecoderConfig& config = |
329 video_stream->video_decoder_config(); | 353 video_stream->video_decoder_config(); |
330 params.video_codec = config.codec(); | 354 params.video_codec = config.codec(); |
331 params.video_size = config.natural_size(); | 355 params.video_size = config.natural_size(); |
332 params.is_video_encrypted = config.is_encrypted(); | 356 params.is_video_encrypted = config.is_encrypted(); |
333 params.video_extra_data = std::vector<uint8>( | 357 params.video_extra_data = std::vector<uint8>( |
334 config.extra_data(), config.extra_data() + config.extra_data_size()); | 358 config.extra_data(), config.extra_data() + config.extra_data_size()); |
335 } | 359 } |
336 double duration_ms = chunk_demuxer_->GetDuration() * 1000; | 360 params.duration_ms = GetDurationMs(); |
337 DCHECK(duration_ms >= 0); | |
338 if (duration_ms > std::numeric_limits<int>::max()) | |
339 duration_ms = std::numeric_limits<int>::max(); | |
340 params.duration_ms = duration_ms; | |
341 params.key_system = key_system; | 361 params.key_system = key_system; |
342 | 362 |
343 bool ready_to_send = (!params.is_audio_encrypted && | 363 bool ready_to_send = (!params.is_audio_encrypted && |
344 !params.is_video_encrypted) || !key_system.empty(); | 364 !params.is_video_encrypted) || !key_system.empty(); |
345 if (proxy_ && ready_to_send) | 365 if (proxy_ && ready_to_send) |
346 proxy_->DemuxerReady(player_id_, params); | 366 proxy_->DemuxerReady(player_id_, params); |
347 } | 367 } |
348 | 368 |
| 369 int MediaSourceDelegate::GetDurationMs() { |
| 370 if (!chunk_demuxer_) |
| 371 return -1; |
| 372 |
| 373 double duration_ms = chunk_demuxer_->GetDuration() * 1000; |
| 374 if (duration_ms > std::numeric_limits<int>::max()) { |
| 375 LOG(WARNING) << "Duration from ChunkDemuxer is too large; probably " |
| 376 "something has gone wrong."; |
| 377 return std::numeric_limits<int>::max(); |
| 378 } |
| 379 return duration_ms; |
| 380 } |
| 381 |
349 void MediaSourceDelegate::OnDemuxerOpened() { | 382 void MediaSourceDelegate::OnDemuxerOpened() { |
350 if (!media_source_) | 383 if (!media_source_) |
351 return; | 384 return; |
352 | 385 |
353 media_source_->open(new WebMediaSourceClientImpl( | 386 media_source_->open(new WebMediaSourceClientImpl( |
354 chunk_demuxer_.get(), base::Bind(&LogMediaSourceError, media_log_))); | 387 chunk_demuxer_.get(), base::Bind(&LogMediaSourceError, media_log_))); |
355 } | 388 } |
356 | 389 |
357 void MediaSourceDelegate::OnNeedKey(const std::string& key_system, | 390 void MediaSourceDelegate::OnNeedKey(const std::string& key_system, |
358 const std::string& session_id, | 391 const std::string& session_id, |
359 const std::string& type, | 392 const std::string& type, |
360 scoped_ptr<uint8[]> init_data, | 393 scoped_ptr<uint8[]> init_data, |
361 int init_data_size) { | 394 int init_data_size) { |
362 if (need_key_cb_.is_null()) | 395 if (need_key_cb_.is_null()) |
363 return; | 396 return; |
364 | 397 |
365 need_key_cb_.Run( | 398 need_key_cb_.Run( |
366 key_system, session_id, type, init_data.Pass(), init_data_size); | 399 key_system, session_id, type, init_data.Pass(), init_data_size); |
367 } | 400 } |
368 | 401 |
369 scoped_ptr<media::TextTrack> MediaSourceDelegate::OnAddTextTrack( | 402 scoped_ptr<media::TextTrack> MediaSourceDelegate::OnAddTextTrack( |
370 media::TextKind kind, | 403 media::TextKind kind, |
371 const std::string& label, | 404 const std::string& label, |
372 const std::string& language) { | 405 const std::string& language) { |
373 return scoped_ptr<media::TextTrack>(); | 406 return scoped_ptr<media::TextTrack>(); |
374 } | 407 } |
375 | 408 |
376 } // namespace webkit_media | 409 } // namespace webkit_media |
OLD | NEW |