| 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 |