| 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 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 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), | 61 demuxer_(NULL), |
| 62 is_demuxer_ready_(false), | 62 is_demuxer_ready_(false), |
| 63 audio_stream_(NULL), | 63 audio_stream_(NULL), |
| 64 video_stream_(NULL), | 64 video_stream_(NULL), |
| 65 seeking_(false), | 65 seeking_(false), |
| 66 doing_browser_seek_(false), | 66 doing_browser_seek_(false), |
| 67 browser_seek_time_(media::kNoTimestamp()), | 67 browser_seek_time_(media::kNoTimestamp()), |
| 68 expecting_regular_seek_(false), | 68 expecting_regular_seek_(false), |
| 69 #if defined(GOOGLE_TV) | |
| 70 key_added_(false), | |
| 71 #endif | |
| 72 access_unit_size_(0) { | 69 access_unit_size_(0) { |
| 73 DCHECK(main_loop_->BelongsToCurrentThread()); | 70 DCHECK(main_loop_->BelongsToCurrentThread()); |
| 74 } | 71 } |
| 75 | 72 |
| 76 MediaSourceDelegate::~MediaSourceDelegate() { | 73 MediaSourceDelegate::~MediaSourceDelegate() { |
| 77 DCHECK(main_loop_->BelongsToCurrentThread()); | 74 DCHECK(main_loop_->BelongsToCurrentThread()); |
| 78 DVLOG(1) << __FUNCTION__ << " : " << demuxer_client_id_; | 75 DVLOG(1) << __FUNCTION__ << " : " << demuxer_client_id_; |
| 79 DCHECK(!chunk_demuxer_); | 76 DCHECK(!chunk_demuxer_); |
| 80 DCHECK(!demuxer_); | 77 DCHECK(!demuxer_); |
| 81 DCHECK(!demuxer_client_); | 78 DCHECK(!demuxer_client_); |
| (...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 167 } | 164 } |
| 168 | 165 |
| 169 void MediaSourceDelegate::InitializeDemuxer() { | 166 void MediaSourceDelegate::InitializeDemuxer() { |
| 170 DCHECK(media_loop_->BelongsToCurrentThread()); | 167 DCHECK(media_loop_->BelongsToCurrentThread()); |
| 171 demuxer_client_->AddDelegate(demuxer_client_id_, this); | 168 demuxer_client_->AddDelegate(demuxer_client_id_, this); |
| 172 demuxer_->Initialize(this, base::Bind(&MediaSourceDelegate::OnDemuxerInitDone, | 169 demuxer_->Initialize(this, base::Bind(&MediaSourceDelegate::OnDemuxerInitDone, |
| 173 media_weak_factory_.GetWeakPtr()), | 170 media_weak_factory_.GetWeakPtr()), |
| 174 false); | 171 false); |
| 175 } | 172 } |
| 176 | 173 |
| 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() { | 174 const blink::WebTimeRanges& MediaSourceDelegate::Buffered() { |
| 198 buffered_web_time_ranges_ = | 175 buffered_web_time_ranges_ = |
| 199 ConvertToWebTimeRanges(buffered_time_ranges_); | 176 ConvertToWebTimeRanges(buffered_time_ranges_); |
| 200 return buffered_web_time_ranges_; | 177 return buffered_web_time_ranges_; |
| 201 } | 178 } |
| 202 | 179 |
| 203 size_t MediaSourceDelegate::DecodedFrameCount() const { | 180 size_t MediaSourceDelegate::DecodedFrameCount() const { |
| 204 return statistics_.video_frames_decoded; | 181 return statistics_.video_frames_decoded; |
| 205 } | 182 } |
| 206 | 183 |
| (...skipping 237 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 444 if (is_audio) { | 421 if (is_audio) { |
| 445 statistics_.audio_bytes_decoded += buffer->data_size(); | 422 statistics_.audio_bytes_decoded += buffer->data_size(); |
| 446 } else { | 423 } else { |
| 447 statistics_.video_bytes_decoded += buffer->data_size(); | 424 statistics_.video_bytes_decoded += buffer->data_size(); |
| 448 statistics_.video_frames_decoded++; | 425 statistics_.video_frames_decoded++; |
| 449 } | 426 } |
| 450 data->access_units[index].timestamp = buffer->timestamp(); | 427 data->access_units[index].timestamp = buffer->timestamp(); |
| 451 | 428 |
| 452 data->access_units[index].data.assign( | 429 data->access_units[index].data.assign( |
| 453 buffer->data(), buffer->data() + buffer->data_size()); | 430 buffer->data(), buffer->data() + buffer->data_size()); |
| 454 #if !defined(GOOGLE_TV) | |
| 455 // Vorbis needs 4 extra bytes padding on Android. Check | 431 // Vorbis needs 4 extra bytes padding on Android. Check |
| 456 // NuMediaExtractor.cpp in Android source code. | 432 // NuMediaExtractor.cpp in Android source code. |
| 457 if (is_audio && media::kCodecVorbis == | 433 if (is_audio && media::kCodecVorbis == |
| 458 audio_stream_->audio_decoder_config().codec()) { | 434 audio_stream_->audio_decoder_config().codec()) { |
| 459 data->access_units[index].data.insert( | 435 data->access_units[index].data.insert( |
| 460 data->access_units[index].data.end(), kVorbisPadding, | 436 data->access_units[index].data.end(), kVorbisPadding, |
| 461 kVorbisPadding + 4); | 437 kVorbisPadding + 4); |
| 462 } | 438 } |
| 463 #endif | |
| 464 if (buffer->decrypt_config()) { | 439 if (buffer->decrypt_config()) { |
| 465 data->access_units[index].key_id = std::vector<char>( | 440 data->access_units[index].key_id = std::vector<char>( |
| 466 buffer->decrypt_config()->key_id().begin(), | 441 buffer->decrypt_config()->key_id().begin(), |
| 467 buffer->decrypt_config()->key_id().end()); | 442 buffer->decrypt_config()->key_id().end()); |
| 468 data->access_units[index].iv = std::vector<char>( | 443 data->access_units[index].iv = std::vector<char>( |
| 469 buffer->decrypt_config()->iv().begin(), | 444 buffer->decrypt_config()->iv().begin(), |
| 470 buffer->decrypt_config()->iv().end()); | 445 buffer->decrypt_config()->iv().end()); |
| 471 data->access_units[index].subsamples = | 446 data->access_units[index].subsamples = |
| 472 buffer->decrypt_config()->subsamples(); | 447 buffer->decrypt_config()->subsamples(); |
| 473 } | 448 } |
| (...skipping 196 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 670 delete this; | 645 delete this; |
| 671 } | 646 } |
| 672 | 647 |
| 673 void MediaSourceDelegate::OnMediaConfigRequest() { | 648 void MediaSourceDelegate::OnMediaConfigRequest() { |
| 674 DCHECK(media_loop_->BelongsToCurrentThread()); | 649 DCHECK(media_loop_->BelongsToCurrentThread()); |
| 675 DVLOG(1) << __FUNCTION__ << " : " << demuxer_client_id_; | 650 DVLOG(1) << __FUNCTION__ << " : " << demuxer_client_id_; |
| 676 if (CanNotifyDemuxerReady()) | 651 if (CanNotifyDemuxerReady()) |
| 677 NotifyDemuxerReady(); | 652 NotifyDemuxerReady(); |
| 678 } | 653 } |
| 679 | 654 |
| 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() { | 655 bool MediaSourceDelegate::CanNotifyDemuxerReady() { |
| 703 DCHECK(media_loop_->BelongsToCurrentThread()); | 656 DCHECK(media_loop_->BelongsToCurrentThread()); |
| 704 // This can happen when a key is added before the demuxer is initialized. | 657 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 } | 658 } |
| 717 | 659 |
| 718 void MediaSourceDelegate::NotifyDemuxerReady() { | 660 void MediaSourceDelegate::NotifyDemuxerReady() { |
| 719 DCHECK(media_loop_->BelongsToCurrentThread()); | 661 DCHECK(media_loop_->BelongsToCurrentThread()); |
| 720 DVLOG(1) << __FUNCTION__ << " : " << demuxer_client_id_; | 662 DVLOG(1) << __FUNCTION__ << " : " << demuxer_client_id_; |
| 721 DCHECK(CanNotifyDemuxerReady()); | 663 DCHECK(CanNotifyDemuxerReady()); |
| 722 | 664 |
| 723 scoped_ptr<DemuxerConfigs> configs(new DemuxerConfigs()); | 665 scoped_ptr<DemuxerConfigs> configs(new DemuxerConfigs()); |
| 724 if (audio_stream_) { | 666 if (audio_stream_) { |
| 725 media::AudioDecoderConfig config = audio_stream_->audio_decoder_config(); | 667 media::AudioDecoderConfig config = audio_stream_->audio_decoder_config(); |
| 726 configs->audio_codec = config.codec(); | 668 configs->audio_codec = config.codec(); |
| 727 configs->audio_channels = | 669 configs->audio_channels = |
| 728 media::ChannelLayoutToChannelCount(config.channel_layout()); | 670 media::ChannelLayoutToChannelCount(config.channel_layout()); |
| 729 configs->audio_sampling_rate = config.samples_per_second(); | 671 configs->audio_sampling_rate = config.samples_per_second(); |
| 730 configs->is_audio_encrypted = config.is_encrypted(); | 672 configs->is_audio_encrypted = config.is_encrypted(); |
| 731 configs->audio_extra_data = std::vector<uint8>( | 673 configs->audio_extra_data = std::vector<uint8>( |
| 732 config.extra_data(), config.extra_data() + config.extra_data_size()); | 674 config.extra_data(), config.extra_data() + config.extra_data_size()); |
| 733 } | 675 } |
| 734 if (video_stream_) { | 676 if (video_stream_) { |
| 735 media::VideoDecoderConfig config = video_stream_->video_decoder_config(); | 677 media::VideoDecoderConfig config = video_stream_->video_decoder_config(); |
| 736 configs->video_codec = config.codec(); | 678 configs->video_codec = config.codec(); |
| 737 configs->video_size = config.natural_size(); | 679 configs->video_size = config.natural_size(); |
| 738 configs->is_video_encrypted = config.is_encrypted(); | 680 configs->is_video_encrypted = config.is_encrypted(); |
| 739 configs->video_extra_data = std::vector<uint8>( | 681 configs->video_extra_data = std::vector<uint8>( |
| 740 config.extra_data(), config.extra_data() + config.extra_data_size()); | 682 config.extra_data(), config.extra_data() + config.extra_data_size()); |
| 741 } | 683 } |
| 742 configs->duration_ms = GetDurationMs(); | 684 configs->duration_ms = GetDurationMs(); |
| 743 | 685 |
| 744 #if defined(GOOGLE_TV) | |
| 745 configs->key_system = HasEncryptedStream() ? key_system_ : ""; | |
| 746 #endif | |
| 747 | |
| 748 if (demuxer_client_) | 686 if (demuxer_client_) |
| 749 demuxer_client_->DemuxerReady(demuxer_client_id_, *configs); | 687 demuxer_client_->DemuxerReady(demuxer_client_id_, *configs); |
| 750 } | 688 } |
| 751 | 689 |
| 752 int MediaSourceDelegate::GetDurationMs() { | 690 int MediaSourceDelegate::GetDurationMs() { |
| 753 DCHECK(media_loop_->BelongsToCurrentThread()); | 691 DCHECK(media_loop_->BelongsToCurrentThread()); |
| 754 if (!chunk_demuxer_) | 692 if (!chunk_demuxer_) |
| 755 return -1; | 693 return -1; |
| 756 | 694 |
| 757 double duration_ms = chunk_demuxer_->GetDuration() * 1000; | 695 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 | 767 // 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 | 768 // unlikely. This may cause unexpected playback stall due to seek pending an |
| 831 // append for a GOP prior to the last GOP demuxed. | 769 // append for a GOP prior to the last GOP demuxed. |
| 832 // TODO(wolenetz): Remove the possibility for this seek to cause unexpected | 770 // TODO(wolenetz): Remove the possibility for this seek to cause unexpected |
| 833 // player stall by replaying cached data since last keyframe in browser player | 771 // player stall by replaying cached data since last keyframe in browser player |
| 834 // rather than issuing browser seek. See http://crbug.com/304234. | 772 // rather than issuing browser seek. See http://crbug.com/304234. |
| 835 return seek_time; | 773 return seek_time; |
| 836 } | 774 } |
| 837 | 775 |
| 838 } // namespace content | 776 } // namespace content |
| OLD | NEW |