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 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
150 update_network_state_cb_ = media::BindToCurrentLoop(update_network_state_cb); | 147 update_network_state_cb_ = media::BindToCurrentLoop(update_network_state_cb); |
151 duration_change_cb_ = duration_change_cb; | 148 duration_change_cb_ = duration_change_cb; |
152 access_unit_size_ = kAccessUnitSizeForMediaSource; | 149 access_unit_size_ = kAccessUnitSizeForMediaSource; |
153 | 150 |
154 chunk_demuxer_.reset(new media::ChunkDemuxer( | 151 chunk_demuxer_.reset(new media::ChunkDemuxer( |
155 media::BindToCurrentLoop(base::Bind( | 152 media::BindToCurrentLoop(base::Bind( |
156 &MediaSourceDelegate::OnDemuxerOpened, main_weak_this_)), | 153 &MediaSourceDelegate::OnDemuxerOpened, main_weak_this_)), |
157 media::BindToCurrentLoop(base::Bind( | 154 media::BindToCurrentLoop(base::Bind( |
158 &MediaSourceDelegate::OnNeedKey, main_weak_this_)), | 155 &MediaSourceDelegate::OnNeedKey, main_weak_this_)), |
159 base::Bind(&LogMediaSourceError, media_log_))); | 156 base::Bind(&LogMediaSourceError, media_log_))); |
160 demuxer_ = chunk_demuxer_.get(); | 157 demuxer_ = chunk_demuxer_.get(); |
scherkus (not reviewing)
2014/01/14 19:08:37
I think we can remove the demuxer_ member variable
ycheo (away)
2014/01/14 23:45:38
Done.
| |
161 | 158 |
162 // |this| will be retained until StopDemuxer() is posted, so Unretained() is | 159 // |this| will be retained until StopDemuxer() is posted, so Unretained() is |
163 // safe here. | 160 // safe here. |
164 media_loop_->PostTask(FROM_HERE, | 161 media_loop_->PostTask(FROM_HERE, |
165 base::Bind(&MediaSourceDelegate::InitializeDemuxer, | 162 base::Bind(&MediaSourceDelegate::InitializeDemuxer, |
166 base::Unretained(this))); | 163 base::Unretained(this))); |
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 |