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 "content/renderer/media/android/media_source_delegate.h" | 5 #include "content/renderer/media/android/media_source_delegate.h" |
6 | 6 |
7 #include <limits> | 7 #include <limits> |
8 #include <string> | 8 #include <string> |
9 #include <vector> | 9 #include <vector> |
10 | 10 |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
51 const scoped_refptr<base::MessageLoopProxy>& media_loop, | 51 const scoped_refptr<base::MessageLoopProxy>& media_loop, |
52 media::MediaLog* media_log) | 52 media::MediaLog* media_log) |
53 : main_loop_(base::MessageLoopProxy::current()), | 53 : main_loop_(base::MessageLoopProxy::current()), |
54 main_weak_factory_(this), | 54 main_weak_factory_(this), |
55 main_weak_this_(main_weak_factory_.GetWeakPtr()), | 55 main_weak_this_(main_weak_factory_.GetWeakPtr()), |
56 media_loop_(media_loop), | 56 media_loop_(media_loop), |
57 media_weak_factory_(this), | 57 media_weak_factory_(this), |
58 demuxer_client_(demuxer_client), | 58 demuxer_client_(demuxer_client), |
59 demuxer_client_id_(demuxer_client_id), | 59 demuxer_client_id_(demuxer_client_id), |
60 media_log_(media_log), | 60 media_log_(media_log), |
61 demuxer_(NULL), | |
62 is_demuxer_ready_(false), | 61 is_demuxer_ready_(false), |
63 audio_stream_(NULL), | 62 audio_stream_(NULL), |
64 video_stream_(NULL), | 63 video_stream_(NULL), |
65 seeking_(false), | 64 seeking_(false), |
66 doing_browser_seek_(false), | 65 doing_browser_seek_(false), |
67 browser_seek_time_(media::kNoTimestamp()), | 66 browser_seek_time_(media::kNoTimestamp()), |
68 expecting_regular_seek_(false), | 67 expecting_regular_seek_(false), |
69 #if defined(GOOGLE_TV) | |
70 key_added_(false), | |
71 #endif | |
72 access_unit_size_(0) { | 68 access_unit_size_(0) { |
73 DCHECK(main_loop_->BelongsToCurrentThread()); | 69 DCHECK(main_loop_->BelongsToCurrentThread()); |
74 } | 70 } |
75 | 71 |
76 MediaSourceDelegate::~MediaSourceDelegate() { | 72 MediaSourceDelegate::~MediaSourceDelegate() { |
77 DCHECK(main_loop_->BelongsToCurrentThread()); | 73 DCHECK(main_loop_->BelongsToCurrentThread()); |
78 DVLOG(1) << __FUNCTION__ << " : " << demuxer_client_id_; | 74 DVLOG(1) << __FUNCTION__ << " : " << demuxer_client_id_; |
79 DCHECK(!chunk_demuxer_); | 75 DCHECK(!chunk_demuxer_); |
80 DCHECK(!demuxer_); | |
81 DCHECK(!demuxer_client_); | 76 DCHECK(!demuxer_client_); |
82 DCHECK(!audio_decrypting_demuxer_stream_); | 77 DCHECK(!audio_decrypting_demuxer_stream_); |
83 DCHECK(!video_decrypting_demuxer_stream_); | 78 DCHECK(!video_decrypting_demuxer_stream_); |
84 DCHECK(!audio_stream_); | 79 DCHECK(!audio_stream_); |
85 DCHECK(!video_stream_); | 80 DCHECK(!video_stream_); |
86 } | 81 } |
87 | 82 |
88 void MediaSourceDelegate::Destroy() { | 83 void MediaSourceDelegate::Destroy() { |
89 DCHECK(main_loop_->BelongsToCurrentThread()); | 84 DCHECK(main_loop_->BelongsToCurrentThread()); |
90 DVLOG(1) << __FUNCTION__ << " : " << demuxer_client_id_; | 85 DVLOG(1) << __FUNCTION__ << " : " << demuxer_client_id_; |
91 | 86 |
92 if (!demuxer_) { | 87 if (!chunk_demuxer_) { |
93 DCHECK(!demuxer_client_); | 88 DCHECK(!demuxer_client_); |
94 delete this; | 89 delete this; |
95 return; | 90 return; |
96 } | 91 } |
97 | 92 |
98 duration_change_cb_.Reset(); | 93 duration_change_cb_.Reset(); |
99 update_network_state_cb_.Reset(); | 94 update_network_state_cb_.Reset(); |
100 media_source_opened_cb_.Reset(); | 95 media_source_opened_cb_.Reset(); |
101 | 96 |
102 main_weak_factory_.InvalidateWeakPtrs(); | 97 main_weak_factory_.InvalidateWeakPtrs(); |
103 DCHECK(!main_weak_factory_.HasWeakPtrs()); | 98 DCHECK(!main_weak_factory_.HasWeakPtrs()); |
104 | 99 |
105 if (chunk_demuxer_) | 100 chunk_demuxer_->Shutdown(); |
106 chunk_demuxer_->Shutdown(); | |
107 | 101 |
108 // |this| will be transferred to the callback StopDemuxer() and | 102 // |this| will be transferred to the callback StopDemuxer() and |
109 // OnDemuxerStopDone(). They own |this| and OnDemuxerStopDone() will delete | 103 // OnDemuxerStopDone(). They own |this| and OnDemuxerStopDone() will delete |
110 // it when called, hence using base::Unretained(this) is safe here. | 104 // it when called, hence using base::Unretained(this) is safe here. |
111 media_loop_->PostTask(FROM_HERE, | 105 media_loop_->PostTask(FROM_HERE, |
112 base::Bind(&MediaSourceDelegate::StopDemuxer, | 106 base::Bind(&MediaSourceDelegate::StopDemuxer, |
113 base::Unretained(this))); | 107 base::Unretained(this))); |
114 } | 108 } |
115 | 109 |
116 void MediaSourceDelegate::StopDemuxer() { | 110 void MediaSourceDelegate::StopDemuxer() { |
117 DCHECK(media_loop_->BelongsToCurrentThread()); | 111 DCHECK(media_loop_->BelongsToCurrentThread()); |
118 DCHECK(demuxer_); | 112 DCHECK(chunk_demuxer_); |
119 | 113 |
120 demuxer_client_->RemoveDelegate(demuxer_client_id_); | 114 demuxer_client_->RemoveDelegate(demuxer_client_id_); |
121 demuxer_client_ = NULL; | 115 demuxer_client_ = NULL; |
122 | 116 |
123 audio_stream_ = NULL; | 117 audio_stream_ = NULL; |
124 video_stream_ = NULL; | 118 video_stream_ = NULL; |
125 // TODO(xhwang): Figure out if we need to Reset the DDSs after Seeking or | 119 // TODO(xhwang): Figure out if we need to Reset the DDSs after Seeking or |
126 // before destroying them. | 120 // before destroying them. |
127 audio_decrypting_demuxer_stream_.reset(); | 121 audio_decrypting_demuxer_stream_.reset(); |
128 video_decrypting_demuxer_stream_.reset(); | 122 video_decrypting_demuxer_stream_.reset(); |
129 | 123 |
130 media_weak_factory_.InvalidateWeakPtrs(); | 124 media_weak_factory_.InvalidateWeakPtrs(); |
131 DCHECK(!media_weak_factory_.HasWeakPtrs()); | 125 DCHECK(!media_weak_factory_.HasWeakPtrs()); |
132 | 126 |
133 // The callback OnDemuxerStopDone() owns |this| and will delete it when | 127 // The callback OnDemuxerStopDone() owns |this| and will delete it when |
134 // called. Hence using base::Unretained(this) is safe here. | 128 // called. Hence using base::Unretained(this) is safe here. |
135 demuxer_->Stop(base::Bind(&MediaSourceDelegate::OnDemuxerStopDone, | 129 chunk_demuxer_->Stop(base::Bind(&MediaSourceDelegate::OnDemuxerStopDone, |
136 base::Unretained(this))); | 130 base::Unretained(this))); |
137 } | 131 } |
138 | 132 |
139 void MediaSourceDelegate::InitializeMediaSource( | 133 void MediaSourceDelegate::InitializeMediaSource( |
140 const MediaSourceOpenedCB& media_source_opened_cb, | 134 const MediaSourceOpenedCB& media_source_opened_cb, |
141 const media::Demuxer::NeedKeyCB& need_key_cb, | 135 const media::Demuxer::NeedKeyCB& need_key_cb, |
142 const media::SetDecryptorReadyCB& set_decryptor_ready_cb, | 136 const media::SetDecryptorReadyCB& set_decryptor_ready_cb, |
143 const UpdateNetworkStateCB& update_network_state_cb, | 137 const UpdateNetworkStateCB& update_network_state_cb, |
144 const DurationChangeCB& duration_change_cb) { | 138 const DurationChangeCB& duration_change_cb) { |
145 DCHECK(main_loop_->BelongsToCurrentThread()); | 139 DCHECK(main_loop_->BelongsToCurrentThread()); |
146 DCHECK(!media_source_opened_cb.is_null()); | 140 DCHECK(!media_source_opened_cb.is_null()); |
147 media_source_opened_cb_ = media_source_opened_cb; | 141 media_source_opened_cb_ = media_source_opened_cb; |
148 need_key_cb_ = need_key_cb; | 142 need_key_cb_ = need_key_cb; |
149 set_decryptor_ready_cb_ = set_decryptor_ready_cb; | 143 set_decryptor_ready_cb_ = set_decryptor_ready_cb; |
150 update_network_state_cb_ = media::BindToCurrentLoop(update_network_state_cb); | 144 update_network_state_cb_ = media::BindToCurrentLoop(update_network_state_cb); |
151 duration_change_cb_ = duration_change_cb; | 145 duration_change_cb_ = duration_change_cb; |
152 access_unit_size_ = kAccessUnitSizeForMediaSource; | 146 access_unit_size_ = kAccessUnitSizeForMediaSource; |
153 | 147 |
154 chunk_demuxer_.reset(new media::ChunkDemuxer( | 148 chunk_demuxer_.reset(new media::ChunkDemuxer( |
155 media::BindToCurrentLoop(base::Bind( | 149 media::BindToCurrentLoop(base::Bind( |
156 &MediaSourceDelegate::OnDemuxerOpened, main_weak_this_)), | 150 &MediaSourceDelegate::OnDemuxerOpened, main_weak_this_)), |
157 media::BindToCurrentLoop(base::Bind( | 151 media::BindToCurrentLoop(base::Bind( |
158 &MediaSourceDelegate::OnNeedKey, main_weak_this_)), | 152 &MediaSourceDelegate::OnNeedKey, main_weak_this_)), |
159 base::Bind(&LogMediaSourceError, media_log_))); | 153 base::Bind(&LogMediaSourceError, media_log_))); |
160 demuxer_ = chunk_demuxer_.get(); | |
161 | 154 |
162 // |this| will be retained until StopDemuxer() is posted, so Unretained() is | 155 // |this| will be retained until StopDemuxer() is posted, so Unretained() is |
163 // safe here. | 156 // safe here. |
164 media_loop_->PostTask(FROM_HERE, | 157 media_loop_->PostTask(FROM_HERE, |
165 base::Bind(&MediaSourceDelegate::InitializeDemuxer, | 158 base::Bind(&MediaSourceDelegate::InitializeDemuxer, |
166 base::Unretained(this))); | 159 base::Unretained(this))); |
167 } | 160 } |
168 | 161 |
169 void MediaSourceDelegate::InitializeDemuxer() { | 162 void MediaSourceDelegate::InitializeDemuxer() { |
170 DCHECK(media_loop_->BelongsToCurrentThread()); | 163 DCHECK(media_loop_->BelongsToCurrentThread()); |
171 demuxer_client_->AddDelegate(demuxer_client_id_, this); | 164 demuxer_client_->AddDelegate(demuxer_client_id_, this); |
172 demuxer_->Initialize(this, base::Bind(&MediaSourceDelegate::OnDemuxerInitDone, | 165 chunk_demuxer_->Initialize(this, |
| 166 base::Bind(&MediaSourceDelegate::OnDemuxerInitDone, |
173 media_weak_factory_.GetWeakPtr()), | 167 media_weak_factory_.GetWeakPtr()), |
174 false); | 168 false); |
175 } | 169 } |
176 | 170 |
177 #if defined(GOOGLE_TV) | |
178 void MediaSourceDelegate::InitializeMediaStream( | |
179 media::Demuxer* demuxer, | |
180 const UpdateNetworkStateCB& update_network_state_cb) { | |
181 DCHECK(main_loop_->BelongsToCurrentThread()); | |
182 DCHECK(demuxer); | |
183 demuxer_ = demuxer; | |
184 update_network_state_cb_ = media::BindToCurrentLoop(update_network_state_cb); | |
185 // When playing Media Stream, don't wait to accumulate multiple packets per | |
186 // IPC communication. | |
187 access_unit_size_ = 1; | |
188 | |
189 // |this| will be retained until StopDemuxer() is posted, so Unretained() is | |
190 // safe here. | |
191 media_loop_->PostTask(FROM_HERE, | |
192 base::Bind(&MediaSourceDelegate::InitializeDemuxer, | |
193 base::Unretained(this))); | |
194 } | |
195 #endif | |
196 | |
197 const blink::WebTimeRanges& MediaSourceDelegate::Buffered() { | 171 const blink::WebTimeRanges& MediaSourceDelegate::Buffered() { |
198 buffered_web_time_ranges_ = | 172 buffered_web_time_ranges_ = |
199 ConvertToWebTimeRanges(buffered_time_ranges_); | 173 ConvertToWebTimeRanges(buffered_time_ranges_); |
200 return buffered_web_time_ranges_; | 174 return buffered_web_time_ranges_; |
201 } | 175 } |
202 | 176 |
203 size_t MediaSourceDelegate::DecodedFrameCount() const { | 177 size_t MediaSourceDelegate::DecodedFrameCount() const { |
204 return statistics_.video_frames_decoded; | 178 return statistics_.video_frames_decoded; |
205 } | 179 } |
206 | 180 |
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
306 chunk_demuxer_->CancelPendingSeek(internal_seek_time); | 280 chunk_demuxer_->CancelPendingSeek(internal_seek_time); |
307 chunk_demuxer_->StartWaitingForSeek(internal_seek_time); | 281 chunk_demuxer_->StartWaitingForSeek(internal_seek_time); |
308 } | 282 } |
309 | 283 |
310 SeekInternal(internal_seek_time); | 284 SeekInternal(internal_seek_time); |
311 } | 285 } |
312 | 286 |
313 void MediaSourceDelegate::SeekInternal(const base::TimeDelta& seek_time) { | 287 void MediaSourceDelegate::SeekInternal(const base::TimeDelta& seek_time) { |
314 DCHECK(media_loop_->BelongsToCurrentThread()); | 288 DCHECK(media_loop_->BelongsToCurrentThread()); |
315 DCHECK(IsSeeking()); | 289 DCHECK(IsSeeking()); |
316 demuxer_->Seek(seek_time, base::Bind( | 290 chunk_demuxer_->Seek(seek_time, base::Bind( |
317 &MediaSourceDelegate::OnDemuxerSeekDone, | 291 &MediaSourceDelegate::OnDemuxerSeekDone, |
318 media_weak_factory_.GetWeakPtr())); | 292 media_weak_factory_.GetWeakPtr())); |
319 } | 293 } |
320 | 294 |
321 void MediaSourceDelegate::SetTotalBytes(int64 total_bytes) { | 295 void MediaSourceDelegate::SetTotalBytes(int64 total_bytes) { |
322 NOTIMPLEMENTED(); | 296 NOTIMPLEMENTED(); |
323 } | 297 } |
324 | 298 |
325 void MediaSourceDelegate::AddBufferedByteRange(int64 start, int64 end) { | 299 void MediaSourceDelegate::AddBufferedByteRange(int64 start, int64 end) { |
326 NOTIMPLEMENTED(); | 300 NOTIMPLEMENTED(); |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
381 media::DemuxerStream::Type type, | 355 media::DemuxerStream::Type type, |
382 scoped_ptr<DemuxerData> data, | 356 scoped_ptr<DemuxerData> data, |
383 size_t index, | 357 size_t index, |
384 DemuxerStream::Status status, | 358 DemuxerStream::Status status, |
385 const scoped_refptr<media::DecoderBuffer>& buffer) { | 359 const scoped_refptr<media::DecoderBuffer>& buffer) { |
386 DCHECK(media_loop_->BelongsToCurrentThread()); | 360 DCHECK(media_loop_->BelongsToCurrentThread()); |
387 DVLOG(1) << __FUNCTION__ << "(" << index << ", " << status << ", " | 361 DVLOG(1) << __FUNCTION__ << "(" << index << ", " << status << ", " |
388 << ((!buffer || buffer->end_of_stream()) ? | 362 << ((!buffer || buffer->end_of_stream()) ? |
389 -1 : buffer->timestamp().InMilliseconds()) | 363 -1 : buffer->timestamp().InMilliseconds()) |
390 << ") : " << demuxer_client_id_; | 364 << ") : " << demuxer_client_id_; |
391 DCHECK(demuxer_); | 365 DCHECK(chunk_demuxer_); |
392 | 366 |
393 // No new OnReadFromDemuxer() will be called during seeking. So this callback | 367 // No new OnReadFromDemuxer() will be called during seeking. So this callback |
394 // must be from previous OnReadFromDemuxer() call and should be ignored. | 368 // must be from previous OnReadFromDemuxer() call and should be ignored. |
395 if (IsSeeking()) { | 369 if (IsSeeking()) { |
396 DVLOG(1) << __FUNCTION__ << ": Ignore previous read during seeking."; | 370 DVLOG(1) << __FUNCTION__ << ": Ignore previous read during seeking."; |
397 return; | 371 return; |
398 } | 372 } |
399 | 373 |
400 bool is_audio = (type == DemuxerStream::AUDIO); | 374 bool is_audio = (type == DemuxerStream::AUDIO); |
401 if (status != DemuxerStream::kAborted && | 375 if (status != DemuxerStream::kAborted && |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
444 if (is_audio) { | 418 if (is_audio) { |
445 statistics_.audio_bytes_decoded += buffer->data_size(); | 419 statistics_.audio_bytes_decoded += buffer->data_size(); |
446 } else { | 420 } else { |
447 statistics_.video_bytes_decoded += buffer->data_size(); | 421 statistics_.video_bytes_decoded += buffer->data_size(); |
448 statistics_.video_frames_decoded++; | 422 statistics_.video_frames_decoded++; |
449 } | 423 } |
450 data->access_units[index].timestamp = buffer->timestamp(); | 424 data->access_units[index].timestamp = buffer->timestamp(); |
451 | 425 |
452 data->access_units[index].data.assign( | 426 data->access_units[index].data.assign( |
453 buffer->data(), buffer->data() + buffer->data_size()); | 427 buffer->data(), buffer->data() + buffer->data_size()); |
454 #if !defined(GOOGLE_TV) | |
455 // Vorbis needs 4 extra bytes padding on Android. Check | 428 // Vorbis needs 4 extra bytes padding on Android. Check |
456 // NuMediaExtractor.cpp in Android source code. | 429 // NuMediaExtractor.cpp in Android source code. |
457 if (is_audio && media::kCodecVorbis == | 430 if (is_audio && media::kCodecVorbis == |
458 audio_stream_->audio_decoder_config().codec()) { | 431 audio_stream_->audio_decoder_config().codec()) { |
459 data->access_units[index].data.insert( | 432 data->access_units[index].data.insert( |
460 data->access_units[index].data.end(), kVorbisPadding, | 433 data->access_units[index].data.end(), kVorbisPadding, |
461 kVorbisPadding + 4); | 434 kVorbisPadding + 4); |
462 } | 435 } |
463 #endif | |
464 if (buffer->decrypt_config()) { | 436 if (buffer->decrypt_config()) { |
465 data->access_units[index].key_id = std::vector<char>( | 437 data->access_units[index].key_id = std::vector<char>( |
466 buffer->decrypt_config()->key_id().begin(), | 438 buffer->decrypt_config()->key_id().begin(), |
467 buffer->decrypt_config()->key_id().end()); | 439 buffer->decrypt_config()->key_id().end()); |
468 data->access_units[index].iv = std::vector<char>( | 440 data->access_units[index].iv = std::vector<char>( |
469 buffer->decrypt_config()->iv().begin(), | 441 buffer->decrypt_config()->iv().begin(), |
470 buffer->decrypt_config()->iv().end()); | 442 buffer->decrypt_config()->iv().end()); |
471 data->access_units[index].subsamples = | 443 data->access_units[index].subsamples = |
472 buffer->decrypt_config()->subsamples(); | 444 buffer->decrypt_config()->subsamples(); |
473 } | 445 } |
(...skipping 27 matching lines...) Expand all Loading... |
501 | 473 |
502 void MediaSourceDelegate::RemoveTextStream( | 474 void MediaSourceDelegate::RemoveTextStream( |
503 media::DemuxerStream* /* text_stream */ ) { | 475 media::DemuxerStream* /* text_stream */ ) { |
504 // TODO(matthewjheaney): remove text stream (http://crbug/322115). | 476 // TODO(matthewjheaney): remove text stream (http://crbug/322115). |
505 NOTIMPLEMENTED(); | 477 NOTIMPLEMENTED(); |
506 } | 478 } |
507 | 479 |
508 void MediaSourceDelegate::OnDemuxerInitDone(media::PipelineStatus status) { | 480 void MediaSourceDelegate::OnDemuxerInitDone(media::PipelineStatus status) { |
509 DCHECK(media_loop_->BelongsToCurrentThread()); | 481 DCHECK(media_loop_->BelongsToCurrentThread()); |
510 DVLOG(1) << __FUNCTION__ << "(" << status << ") : " << demuxer_client_id_; | 482 DVLOG(1) << __FUNCTION__ << "(" << status << ") : " << demuxer_client_id_; |
511 DCHECK(demuxer_); | 483 DCHECK(chunk_demuxer_); |
512 | 484 |
513 if (status != media::PIPELINE_OK) { | 485 if (status != media::PIPELINE_OK) { |
514 OnDemuxerError(status); | 486 OnDemuxerError(status); |
515 return; | 487 return; |
516 } | 488 } |
517 | 489 |
518 audio_stream_ = demuxer_->GetStream(DemuxerStream::AUDIO); | 490 audio_stream_ = chunk_demuxer_->GetStream(DemuxerStream::AUDIO); |
519 video_stream_ = demuxer_->GetStream(DemuxerStream::VIDEO); | 491 video_stream_ = chunk_demuxer_->GetStream(DemuxerStream::VIDEO); |
520 | 492 |
521 if (audio_stream_ && audio_stream_->audio_decoder_config().is_encrypted() && | 493 if (audio_stream_ && audio_stream_->audio_decoder_config().is_encrypted() && |
522 !set_decryptor_ready_cb_.is_null()) { | 494 !set_decryptor_ready_cb_.is_null()) { |
523 InitAudioDecryptingDemuxerStream(); | 495 InitAudioDecryptingDemuxerStream(); |
524 // InitVideoDecryptingDemuxerStream() will be called in | 496 // InitVideoDecryptingDemuxerStream() will be called in |
525 // OnAudioDecryptingDemuxerStreamInitDone(). | 497 // OnAudioDecryptingDemuxerStreamInitDone(). |
526 return; | 498 return; |
527 } | 499 } |
528 | 500 |
529 if (video_stream_ && video_stream_->video_decoder_config().is_encrypted() && | 501 if (video_stream_ && video_stream_->video_decoder_config().is_encrypted() && |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
561 video_decrypting_demuxer_stream_->Initialize( | 533 video_decrypting_demuxer_stream_->Initialize( |
562 video_stream_, | 534 video_stream_, |
563 base::Bind(&MediaSourceDelegate::OnVideoDecryptingDemuxerStreamInitDone, | 535 base::Bind(&MediaSourceDelegate::OnVideoDecryptingDemuxerStreamInitDone, |
564 media_weak_factory_.GetWeakPtr())); | 536 media_weak_factory_.GetWeakPtr())); |
565 } | 537 } |
566 | 538 |
567 void MediaSourceDelegate::OnAudioDecryptingDemuxerStreamInitDone( | 539 void MediaSourceDelegate::OnAudioDecryptingDemuxerStreamInitDone( |
568 media::PipelineStatus status) { | 540 media::PipelineStatus status) { |
569 DCHECK(media_loop_->BelongsToCurrentThread()); | 541 DCHECK(media_loop_->BelongsToCurrentThread()); |
570 DVLOG(1) << __FUNCTION__ << "(" << status << ") : " << demuxer_client_id_; | 542 DVLOG(1) << __FUNCTION__ << "(" << status << ") : " << demuxer_client_id_; |
571 DCHECK(demuxer_); | 543 DCHECK(chunk_demuxer_); |
572 | 544 |
573 if (status != media::PIPELINE_OK) | 545 if (status != media::PIPELINE_OK) |
574 audio_decrypting_demuxer_stream_.reset(); | 546 audio_decrypting_demuxer_stream_.reset(); |
575 else | 547 else |
576 audio_stream_ = audio_decrypting_demuxer_stream_.get(); | 548 audio_stream_ = audio_decrypting_demuxer_stream_.get(); |
577 | 549 |
578 if (video_stream_ && video_stream_->video_decoder_config().is_encrypted()) { | 550 if (video_stream_ && video_stream_->video_decoder_config().is_encrypted()) { |
579 InitVideoDecryptingDemuxerStream(); | 551 InitVideoDecryptingDemuxerStream(); |
580 return; | 552 return; |
581 } | 553 } |
582 | 554 |
583 // Try to notify demuxer ready when audio DDS initialization finished and | 555 // Try to notify demuxer ready when audio DDS initialization finished and |
584 // video is not encrypted. | 556 // video is not encrypted. |
585 is_demuxer_ready_ = true; | 557 is_demuxer_ready_ = true; |
586 if (CanNotifyDemuxerReady()) | 558 if (CanNotifyDemuxerReady()) |
587 NotifyDemuxerReady(); | 559 NotifyDemuxerReady(); |
588 } | 560 } |
589 | 561 |
590 void MediaSourceDelegate::OnVideoDecryptingDemuxerStreamInitDone( | 562 void MediaSourceDelegate::OnVideoDecryptingDemuxerStreamInitDone( |
591 media::PipelineStatus status) { | 563 media::PipelineStatus status) { |
592 DCHECK(media_loop_->BelongsToCurrentThread()); | 564 DCHECK(media_loop_->BelongsToCurrentThread()); |
593 DVLOG(1) << __FUNCTION__ << "(" << status << ") : " << demuxer_client_id_; | 565 DVLOG(1) << __FUNCTION__ << "(" << status << ") : " << demuxer_client_id_; |
594 DCHECK(demuxer_); | 566 DCHECK(chunk_demuxer_); |
595 | 567 |
596 if (status != media::PIPELINE_OK) | 568 if (status != media::PIPELINE_OK) |
597 video_decrypting_demuxer_stream_.reset(); | 569 video_decrypting_demuxer_stream_.reset(); |
598 else | 570 else |
599 video_stream_ = video_decrypting_demuxer_stream_.get(); | 571 video_stream_ = video_decrypting_demuxer_stream_.get(); |
600 | 572 |
601 // Try to notify demuxer ready when video DDS initialization finished. | 573 // Try to notify demuxer ready when video DDS initialization finished. |
602 is_demuxer_ready_ = true; | 574 is_demuxer_ready_ = true; |
603 if (CanNotifyDemuxerReady()) | 575 if (CanNotifyDemuxerReady()) |
604 NotifyDemuxerReady(); | 576 NotifyDemuxerReady(); |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
659 DVLOG(1) << __FUNCTION__ << " : " << demuxer_client_id_; | 631 DVLOG(1) << __FUNCTION__ << " : " << demuxer_client_id_; |
660 main_loop_->PostTask( | 632 main_loop_->PostTask( |
661 FROM_HERE, | 633 FROM_HERE, |
662 base::Bind(&MediaSourceDelegate::DeleteSelf, base::Unretained(this))); | 634 base::Bind(&MediaSourceDelegate::DeleteSelf, base::Unretained(this))); |
663 } | 635 } |
664 | 636 |
665 void MediaSourceDelegate::DeleteSelf() { | 637 void MediaSourceDelegate::DeleteSelf() { |
666 DCHECK(main_loop_->BelongsToCurrentThread()); | 638 DCHECK(main_loop_->BelongsToCurrentThread()); |
667 DVLOG(1) << __FUNCTION__ << " : " << demuxer_client_id_; | 639 DVLOG(1) << __FUNCTION__ << " : " << demuxer_client_id_; |
668 chunk_demuxer_.reset(); | 640 chunk_demuxer_.reset(); |
669 demuxer_ = NULL; | |
670 delete this; | 641 delete this; |
671 } | 642 } |
672 | 643 |
673 void MediaSourceDelegate::OnMediaConfigRequest() { | 644 void MediaSourceDelegate::OnMediaConfigRequest() { |
674 DCHECK(media_loop_->BelongsToCurrentThread()); | 645 DCHECK(media_loop_->BelongsToCurrentThread()); |
675 DVLOG(1) << __FUNCTION__ << " : " << demuxer_client_id_; | 646 DVLOG(1) << __FUNCTION__ << " : " << demuxer_client_id_; |
676 if (CanNotifyDemuxerReady()) | 647 if (CanNotifyDemuxerReady()) |
677 NotifyDemuxerReady(); | 648 NotifyDemuxerReady(); |
678 } | 649 } |
679 | 650 |
680 #if defined(GOOGLE_TV) | |
681 // TODO(kjyoun): Enhance logic to detect when to call NotifyDemuxerReady() | |
682 // For now, we call it when the first key is added. See http://crbug.com/255781 | |
683 void MediaSourceDelegate::NotifyKeyAdded(const std::string& key_system) { | |
684 if (!media_loop_->BelongsToCurrentThread()) { | |
685 media_loop_->PostTask(FROM_HERE, | |
686 base::Bind(&MediaSourceDelegate::NotifyKeyAdded, | |
687 base::Unretained(this), key_system)); | |
688 return; | |
689 } | |
690 DVLOG(1) << __FUNCTION__ << " : " << demuxer_client_id_; | |
691 if (key_added_) | |
692 return; | |
693 key_added_ = true; | |
694 key_system_ = key_system; | |
695 if (!CanNotifyDemuxerReady()) | |
696 return; | |
697 if (HasEncryptedStream()) | |
698 NotifyDemuxerReady(); | |
699 } | |
700 #endif // defined(GOOGLE_TV) | |
701 | |
702 bool MediaSourceDelegate::CanNotifyDemuxerReady() { | 651 bool MediaSourceDelegate::CanNotifyDemuxerReady() { |
703 DCHECK(media_loop_->BelongsToCurrentThread()); | 652 DCHECK(media_loop_->BelongsToCurrentThread()); |
704 // This can happen when a key is added before the demuxer is initialized. | 653 return is_demuxer_ready_; |
705 // See NotifyKeyAdded(). | |
706 // TODO(kjyoun): Remove NotifyDemxuerReady() call from NotifyKeyAdded() so | |
707 // that we can remove all is_demuxer_ready_/key_added_/key_system_ madness. | |
708 // See http://crbug.com/255781 | |
709 if (!is_demuxer_ready_) | |
710 return false; | |
711 #if defined(GOOGLE_TV) | |
712 if (HasEncryptedStream() && !key_added_) | |
713 return false; | |
714 #endif // defined(GOOGLE_TV) | |
715 return true; | |
716 } | 654 } |
717 | 655 |
718 void MediaSourceDelegate::NotifyDemuxerReady() { | 656 void MediaSourceDelegate::NotifyDemuxerReady() { |
719 DCHECK(media_loop_->BelongsToCurrentThread()); | 657 DCHECK(media_loop_->BelongsToCurrentThread()); |
720 DVLOG(1) << __FUNCTION__ << " : " << demuxer_client_id_; | 658 DVLOG(1) << __FUNCTION__ << " : " << demuxer_client_id_; |
721 DCHECK(CanNotifyDemuxerReady()); | 659 DCHECK(CanNotifyDemuxerReady()); |
722 | 660 |
723 scoped_ptr<DemuxerConfigs> configs(new DemuxerConfigs()); | 661 scoped_ptr<DemuxerConfigs> configs(new DemuxerConfigs()); |
724 if (audio_stream_) { | 662 if (audio_stream_) { |
725 media::AudioDecoderConfig config = audio_stream_->audio_decoder_config(); | 663 media::AudioDecoderConfig config = audio_stream_->audio_decoder_config(); |
726 configs->audio_codec = config.codec(); | 664 configs->audio_codec = config.codec(); |
727 configs->audio_channels = | 665 configs->audio_channels = |
728 media::ChannelLayoutToChannelCount(config.channel_layout()); | 666 media::ChannelLayoutToChannelCount(config.channel_layout()); |
729 configs->audio_sampling_rate = config.samples_per_second(); | 667 configs->audio_sampling_rate = config.samples_per_second(); |
730 configs->is_audio_encrypted = config.is_encrypted(); | 668 configs->is_audio_encrypted = config.is_encrypted(); |
731 configs->audio_extra_data = std::vector<uint8>( | 669 configs->audio_extra_data = std::vector<uint8>( |
732 config.extra_data(), config.extra_data() + config.extra_data_size()); | 670 config.extra_data(), config.extra_data() + config.extra_data_size()); |
733 } | 671 } |
734 if (video_stream_) { | 672 if (video_stream_) { |
735 media::VideoDecoderConfig config = video_stream_->video_decoder_config(); | 673 media::VideoDecoderConfig config = video_stream_->video_decoder_config(); |
736 configs->video_codec = config.codec(); | 674 configs->video_codec = config.codec(); |
737 configs->video_size = config.natural_size(); | 675 configs->video_size = config.natural_size(); |
738 configs->is_video_encrypted = config.is_encrypted(); | 676 configs->is_video_encrypted = config.is_encrypted(); |
739 configs->video_extra_data = std::vector<uint8>( | 677 configs->video_extra_data = std::vector<uint8>( |
740 config.extra_data(), config.extra_data() + config.extra_data_size()); | 678 config.extra_data(), config.extra_data() + config.extra_data_size()); |
741 } | 679 } |
742 configs->duration_ms = GetDurationMs(); | 680 configs->duration_ms = GetDurationMs(); |
743 | 681 |
744 #if defined(GOOGLE_TV) | |
745 configs->key_system = HasEncryptedStream() ? key_system_ : ""; | |
746 #endif | |
747 | |
748 if (demuxer_client_) | 682 if (demuxer_client_) |
749 demuxer_client_->DemuxerReady(demuxer_client_id_, *configs); | 683 demuxer_client_->DemuxerReady(demuxer_client_id_, *configs); |
750 } | 684 } |
751 | 685 |
752 int MediaSourceDelegate::GetDurationMs() { | 686 int MediaSourceDelegate::GetDurationMs() { |
753 DCHECK(media_loop_->BelongsToCurrentThread()); | 687 DCHECK(media_loop_->BelongsToCurrentThread()); |
754 if (!chunk_demuxer_) | 688 if (!chunk_demuxer_) |
755 return -1; | 689 return -1; |
756 | 690 |
757 double duration_ms = chunk_demuxer_->GetDuration() * 1000; | 691 double duration_ms = chunk_demuxer_->GetDuration() * 1000; |
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
829 // current time have been garbage collected or removed by the web app, this is | 763 // current time have been garbage collected or removed by the web app, this is |
830 // unlikely. This may cause unexpected playback stall due to seek pending an | 764 // unlikely. This may cause unexpected playback stall due to seek pending an |
831 // append for a GOP prior to the last GOP demuxed. | 765 // append for a GOP prior to the last GOP demuxed. |
832 // TODO(wolenetz): Remove the possibility for this seek to cause unexpected | 766 // TODO(wolenetz): Remove the possibility for this seek to cause unexpected |
833 // player stall by replaying cached data since last keyframe in browser player | 767 // player stall by replaying cached data since last keyframe in browser player |
834 // rather than issuing browser seek. See http://crbug.com/304234. | 768 // rather than issuing browser seek. See http://crbug.com/304234. |
835 return seek_time; | 769 return seek_time; |
836 } | 770 } |
837 | 771 |
838 } // namespace content | 772 } // namespace content |
OLD | NEW |