OLD | NEW |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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/glue/webmediaplayer_impl.h" | 5 #include "webkit/glue/webmediaplayer_impl.h" |
6 | 6 |
7 #include <limits> | 7 #include <limits> |
8 | 8 |
9 #include "base/callback.h" | 9 #include "base/callback.h" |
10 #include "base/command_line.h" | 10 #include "base/command_line.h" |
(...skipping 15 matching lines...) Expand all Loading... |
26 #include "third_party/WebKit/Source/WebKit/chromium/public/WebVideoFrame.h" | 26 #include "third_party/WebKit/Source/WebKit/chromium/public/WebVideoFrame.h" |
27 #include "webkit/glue/media/buffered_data_source.h" | 27 #include "webkit/glue/media/buffered_data_source.h" |
28 #include "webkit/glue/media/simple_data_source.h" | 28 #include "webkit/glue/media/simple_data_source.h" |
29 #include "webkit/glue/media/video_renderer_impl.h" | 29 #include "webkit/glue/media/video_renderer_impl.h" |
30 #include "webkit/glue/media/web_video_renderer.h" | 30 #include "webkit/glue/media/web_video_renderer.h" |
31 #include "webkit/glue/webvideoframe_impl.h" | 31 #include "webkit/glue/webvideoframe_impl.h" |
32 | 32 |
33 using WebKit::WebCanvas; | 33 using WebKit::WebCanvas; |
34 using WebKit::WebRect; | 34 using WebKit::WebRect; |
35 using WebKit::WebSize; | 35 using WebKit::WebSize; |
| 36 using media::PipelineStatus; |
36 | 37 |
37 namespace { | 38 namespace { |
38 | 39 |
39 // Limits the maximum outstanding repaints posted on render thread. | 40 // Limits the maximum outstanding repaints posted on render thread. |
40 // This number of 50 is a guess, it does not take too much memory on the task | 41 // This number of 50 is a guess, it does not take too much memory on the task |
41 // queue but gives up a pretty good latency on repaint. | 42 // queue but gives up a pretty good latency on repaint. |
42 const int kMaxOutstandingRepaints = 50; | 43 const int kMaxOutstandingRepaints = 50; |
43 | 44 |
44 // Limits the range of playback rate. | 45 // Limits the range of playback rate. |
45 // | 46 // |
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
164 DCHECK(MessageLoop::current() == render_loop_); | 165 DCHECK(MessageLoop::current() == render_loop_); |
165 webmediaplayer_ = NULL; | 166 webmediaplayer_ = NULL; |
166 video_renderer_ = NULL; | 167 video_renderer_ = NULL; |
167 | 168 |
168 { | 169 { |
169 base::AutoLock auto_lock(data_sources_lock_); | 170 base::AutoLock auto_lock(data_sources_lock_); |
170 data_sources_.clear(); | 171 data_sources_.clear(); |
171 } | 172 } |
172 } | 173 } |
173 | 174 |
174 void WebMediaPlayerImpl::Proxy::PipelineInitializationCallback() { | 175 void WebMediaPlayerImpl::Proxy::PipelineInitializationCallback( |
175 render_loop_->PostTask(FROM_HERE, NewRunnableMethod(this, | 176 PipelineStatus status) { |
176 &WebMediaPlayerImpl::Proxy::PipelineInitializationTask)); | 177 render_loop_->PostTask(FROM_HERE, NewRunnableMethod( |
| 178 this, &WebMediaPlayerImpl::Proxy::PipelineInitializationTask, status)); |
177 } | 179 } |
178 | 180 |
179 void WebMediaPlayerImpl::Proxy::PipelineSeekCallback() { | 181 void WebMediaPlayerImpl::Proxy::PipelineSeekCallback(PipelineStatus status) { |
180 render_loop_->PostTask(FROM_HERE, NewRunnableMethod(this, | 182 render_loop_->PostTask(FROM_HERE, NewRunnableMethod( |
181 &WebMediaPlayerImpl::Proxy::PipelineSeekTask)); | 183 this, &WebMediaPlayerImpl::Proxy::PipelineSeekTask, status)); |
182 } | 184 } |
183 | 185 |
184 void WebMediaPlayerImpl::Proxy::PipelineEndedCallback() { | 186 void WebMediaPlayerImpl::Proxy::PipelineEndedCallback(PipelineStatus status) { |
185 render_loop_->PostTask(FROM_HERE, NewRunnableMethod(this, | 187 render_loop_->PostTask(FROM_HERE, NewRunnableMethod( |
186 &WebMediaPlayerImpl::Proxy::PipelineEndedTask)); | 188 this, &WebMediaPlayerImpl::Proxy::PipelineEndedTask, status)); |
187 } | 189 } |
188 | 190 |
189 void WebMediaPlayerImpl::Proxy::PipelineErrorCallback() { | 191 void WebMediaPlayerImpl::Proxy::PipelineStatusCallback(PipelineStatus status) { |
190 render_loop_->PostTask(FROM_HERE, NewRunnableMethod(this, | 192 render_loop_->PostTask(FROM_HERE, NewRunnableMethod( |
191 &WebMediaPlayerImpl::Proxy::PipelineErrorTask)); | 193 this, &WebMediaPlayerImpl::Proxy::PipelineStatusTask, status)); |
192 } | 194 } |
193 | 195 |
194 void WebMediaPlayerImpl::Proxy::NetworkEventCallback() { | 196 void WebMediaPlayerImpl::Proxy::NetworkEventCallback(PipelineStatus status) { |
195 render_loop_->PostTask(FROM_HERE, NewRunnableMethod(this, | 197 render_loop_->PostTask(FROM_HERE, NewRunnableMethod( |
196 &WebMediaPlayerImpl::Proxy::NetworkEventTask)); | 198 this, &WebMediaPlayerImpl::Proxy::NetworkEventTask, status)); |
197 } | 199 } |
198 | 200 |
199 void WebMediaPlayerImpl::Proxy::AddDataSource(WebDataSource* data_source) { | 201 void WebMediaPlayerImpl::Proxy::AddDataSource(WebDataSource* data_source) { |
200 base::AutoLock auto_lock(data_sources_lock_); | 202 base::AutoLock auto_lock(data_sources_lock_); |
201 data_sources_.push_back(make_scoped_refptr(data_source)); | 203 data_sources_.push_back(make_scoped_refptr(data_source)); |
202 } | 204 } |
203 | 205 |
204 void WebMediaPlayerImpl::Proxy::RepaintTask() { | 206 void WebMediaPlayerImpl::Proxy::RepaintTask() { |
205 DCHECK(MessageLoop::current() == render_loop_); | 207 DCHECK(MessageLoop::current() == render_loop_); |
206 { | 208 { |
207 base::AutoLock auto_lock(lock_); | 209 base::AutoLock auto_lock(lock_); |
208 --outstanding_repaints_; | 210 --outstanding_repaints_; |
209 DCHECK_GE(outstanding_repaints_, 0); | 211 DCHECK_GE(outstanding_repaints_, 0); |
210 } | 212 } |
211 if (webmediaplayer_) { | 213 if (webmediaplayer_) { |
212 webmediaplayer_->Repaint(); | 214 webmediaplayer_->Repaint(); |
213 } | 215 } |
214 } | 216 } |
215 | 217 |
216 void WebMediaPlayerImpl::Proxy::PipelineInitializationTask() { | 218 void WebMediaPlayerImpl::Proxy::PipelineInitializationTask( |
| 219 PipelineStatus status) { |
217 DCHECK(MessageLoop::current() == render_loop_); | 220 DCHECK(MessageLoop::current() == render_loop_); |
218 if (webmediaplayer_) { | 221 if (webmediaplayer_) { |
219 webmediaplayer_->OnPipelineInitialize(); | 222 webmediaplayer_->OnPipelineInitialize(status); |
220 } | 223 } |
221 } | 224 } |
222 | 225 |
223 void WebMediaPlayerImpl::Proxy::PipelineSeekTask() { | 226 void WebMediaPlayerImpl::Proxy::PipelineSeekTask(PipelineStatus status) { |
224 DCHECK(MessageLoop::current() == render_loop_); | 227 DCHECK(MessageLoop::current() == render_loop_); |
225 if (webmediaplayer_) { | 228 if (webmediaplayer_) { |
226 webmediaplayer_->OnPipelineSeek(); | 229 webmediaplayer_->OnPipelineSeek(status); |
227 } | 230 } |
228 } | 231 } |
229 | 232 |
230 void WebMediaPlayerImpl::Proxy::PipelineEndedTask() { | 233 void WebMediaPlayerImpl::Proxy::PipelineEndedTask(PipelineStatus status) { |
231 DCHECK(MessageLoop::current() == render_loop_); | 234 DCHECK(MessageLoop::current() == render_loop_); |
232 if (webmediaplayer_) { | 235 if (webmediaplayer_) { |
233 webmediaplayer_->OnPipelineEnded(); | 236 webmediaplayer_->OnPipelineEnded(status); |
234 } | 237 } |
235 } | 238 } |
236 | 239 |
237 void WebMediaPlayerImpl::Proxy::PipelineErrorTask() { | 240 void WebMediaPlayerImpl::Proxy::PipelineStatusTask(PipelineStatus status) { |
238 DCHECK(MessageLoop::current() == render_loop_); | 241 DCHECK(MessageLoop::current() == render_loop_); |
239 if (webmediaplayer_) { | 242 if (webmediaplayer_) { |
240 webmediaplayer_->OnPipelineError(); | 243 webmediaplayer_->OnPipelineStatus(status); |
241 } | 244 } |
242 } | 245 } |
243 | 246 |
244 void WebMediaPlayerImpl::Proxy::NetworkEventTask() { | 247 void WebMediaPlayerImpl::Proxy::NetworkEventTask(PipelineStatus status) { |
245 DCHECK(MessageLoop::current() == render_loop_); | 248 DCHECK(MessageLoop::current() == render_loop_); |
246 if (webmediaplayer_) { | 249 if (webmediaplayer_) { |
247 webmediaplayer_->OnNetworkEvent(); | 250 webmediaplayer_->OnNetworkEvent(status); |
248 } | 251 } |
249 } | 252 } |
250 | 253 |
251 void WebMediaPlayerImpl::Proxy::GetCurrentFrame( | 254 void WebMediaPlayerImpl::Proxy::GetCurrentFrame( |
252 scoped_refptr<media::VideoFrame>* frame_out) { | 255 scoped_refptr<media::VideoFrame>* frame_out) { |
253 if (video_renderer_) | 256 if (video_renderer_) |
254 video_renderer_->GetCurrentFrame(frame_out); | 257 video_renderer_->GetCurrentFrame(frame_out); |
255 } | 258 } |
256 | 259 |
257 void WebMediaPlayerImpl::Proxy::PutCurrentFrame( | 260 void WebMediaPlayerImpl::Proxy::PutCurrentFrame( |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
303 // Creates the proxy. | 306 // Creates the proxy. |
304 proxy_ = new Proxy(main_loop_, this); | 307 proxy_ = new Proxy(main_loop_, this); |
305 web_video_renderer->SetWebMediaPlayerImplProxy(proxy_); | 308 web_video_renderer->SetWebMediaPlayerImplProxy(proxy_); |
306 proxy_->SetVideoRenderer(web_video_renderer); | 309 proxy_->SetVideoRenderer(web_video_renderer); |
307 | 310 |
308 // Set our pipeline callbacks. | 311 // Set our pipeline callbacks. |
309 pipeline_->Init( | 312 pipeline_->Init( |
310 NewCallback(proxy_.get(), | 313 NewCallback(proxy_.get(), |
311 &WebMediaPlayerImpl::Proxy::PipelineEndedCallback), | 314 &WebMediaPlayerImpl::Proxy::PipelineEndedCallback), |
312 NewCallback(proxy_.get(), | 315 NewCallback(proxy_.get(), |
313 &WebMediaPlayerImpl::Proxy::PipelineErrorCallback), | 316 &WebMediaPlayerImpl::Proxy::PipelineStatusCallback), |
314 NewCallback(proxy_.get(), | 317 NewCallback(proxy_.get(), |
315 &WebMediaPlayerImpl::Proxy::NetworkEventCallback)); | 318 &WebMediaPlayerImpl::Proxy::NetworkEventCallback)); |
316 | 319 |
317 // A simple data source that keeps all data in memory. | 320 // A simple data source that keeps all data in memory. |
318 scoped_ptr<media::DataSourceFactory> simple_data_source_factory( | 321 scoped_ptr<media::DataSourceFactory> simple_data_source_factory( |
319 SimpleDataSource::CreateFactory(MessageLoop::current(), frame, | 322 SimpleDataSource::CreateFactory(MessageLoop::current(), frame, |
320 proxy_->GetBuildObserver())); | 323 proxy_->GetBuildObserver())); |
321 | 324 |
322 // A sophisticated data source that does memory caching. | 325 // A sophisticated data source that does memory caching. |
323 scoped_ptr<media::DataSourceFactory> buffered_data_source_factory( | 326 scoped_ptr<media::DataSourceFactory> buffered_data_source_factory( |
(...skipping 413 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
737 void WebMediaPlayerImpl::WillDestroyCurrentMessageLoop() { | 740 void WebMediaPlayerImpl::WillDestroyCurrentMessageLoop() { |
738 Destroy(); | 741 Destroy(); |
739 main_loop_ = NULL; | 742 main_loop_ = NULL; |
740 } | 743 } |
741 | 744 |
742 void WebMediaPlayerImpl::Repaint() { | 745 void WebMediaPlayerImpl::Repaint() { |
743 DCHECK(MessageLoop::current() == main_loop_); | 746 DCHECK(MessageLoop::current() == main_loop_); |
744 GetClient()->repaint(); | 747 GetClient()->repaint(); |
745 } | 748 } |
746 | 749 |
747 void WebMediaPlayerImpl::OnPipelineInitialize() { | 750 void WebMediaPlayerImpl::OnPipelineInitialize(PipelineStatus status) { |
748 DCHECK(MessageLoop::current() == main_loop_); | 751 DCHECK(MessageLoop::current() == main_loop_); |
749 if (pipeline_->GetError() == media::PIPELINE_OK) { | 752 if (status == media::PIPELINE_OK) { |
750 // Only keep one time range starting from 0. | 753 // Only keep one time range starting from 0. |
751 WebKit::WebTimeRanges new_buffered(static_cast<size_t>(1)); | 754 WebKit::WebTimeRanges new_buffered(static_cast<size_t>(1)); |
752 new_buffered[0].start = 0.0f; | 755 new_buffered[0].start = 0.0f; |
753 new_buffered[0].end = | 756 new_buffered[0].end = |
754 static_cast<float>(pipeline_->GetMediaDuration().InSecondsF()); | 757 static_cast<float>(pipeline_->GetMediaDuration().InSecondsF()); |
755 buffered_.swap(new_buffered); | 758 buffered_.swap(new_buffered); |
756 | 759 |
757 // Since we have initialized the pipeline, say we have everything otherwise | 760 // Since we have initialized the pipeline, say we have everything otherwise |
758 // we'll remain either loading/idle. | 761 // we'll remain either loading/idle. |
759 // TODO(hclam): change this to report the correct status. | 762 // TODO(hclam): change this to report the correct status. |
760 SetReadyState(WebKit::WebMediaPlayer::HaveMetadata); | 763 SetReadyState(WebKit::WebMediaPlayer::HaveMetadata); |
761 SetReadyState(WebKit::WebMediaPlayer::HaveEnoughData); | 764 SetReadyState(WebKit::WebMediaPlayer::HaveEnoughData); |
762 if (pipeline_->IsLoaded()) { | 765 if (pipeline_->IsLoaded()) { |
763 SetNetworkState(WebKit::WebMediaPlayer::Loaded); | 766 SetNetworkState(WebKit::WebMediaPlayer::Loaded); |
764 } | 767 } |
765 } else { | 768 } else { |
766 // TODO(hclam): should use pipeline_->GetError() to determine the state | 769 // TODO(hclam): should use |status| to determine the state |
767 // properly and reports error using MediaError. | 770 // properly and reports error using MediaError. |
768 // WebKit uses FormatError to indicate an error for bogus URL or bad file. | 771 // WebKit uses FormatError to indicate an error for bogus URL or bad file. |
769 // Since we are at the initialization stage we can safely treat every error | 772 // Since we are at the initialization stage we can safely treat every error |
770 // as format error. Should post a task to call to |webmediaplayer_|. | 773 // as format error. Should post a task to call to |webmediaplayer_|. |
771 SetNetworkState(WebKit::WebMediaPlayer::FormatError); | 774 SetNetworkState(WebKit::WebMediaPlayer::FormatError); |
772 } | 775 } |
773 | 776 |
774 // Repaint to trigger UI update. | 777 // Repaint to trigger UI update. |
775 Repaint(); | 778 Repaint(); |
776 } | 779 } |
777 | 780 |
778 void WebMediaPlayerImpl::OnPipelineSeek() { | 781 void WebMediaPlayerImpl::OnPipelineSeek(PipelineStatus status) { |
779 DCHECK(MessageLoop::current() == main_loop_); | 782 DCHECK(MessageLoop::current() == main_loop_); |
780 if (pipeline_->GetError() == media::PIPELINE_OK) { | 783 if (status == media::PIPELINE_OK) { |
781 // Update our paused time. | 784 // Update our paused time. |
782 if (paused_) { | 785 if (paused_) { |
783 paused_time_ = pipeline_->GetCurrentTime(); | 786 paused_time_ = pipeline_->GetCurrentTime(); |
784 } | 787 } |
785 | 788 |
786 SetReadyState(WebKit::WebMediaPlayer::HaveEnoughData); | 789 SetReadyState(WebKit::WebMediaPlayer::HaveEnoughData); |
787 seeking_ = false; | 790 seeking_ = false; |
788 GetClient()->timeChanged(); | 791 GetClient()->timeChanged(); |
789 } | 792 } |
790 } | 793 } |
791 | 794 |
792 void WebMediaPlayerImpl::OnPipelineEnded() { | 795 void WebMediaPlayerImpl::OnPipelineEnded(PipelineStatus status) { |
793 DCHECK(MessageLoop::current() == main_loop_); | 796 DCHECK(MessageLoop::current() == main_loop_); |
794 if (pipeline_->GetError() == media::PIPELINE_OK) { | 797 if (status == media::PIPELINE_OK) { |
795 GetClient()->timeChanged(); | 798 GetClient()->timeChanged(); |
796 } | 799 } |
797 } | 800 } |
798 | 801 |
799 void WebMediaPlayerImpl::OnPipelineError() { | 802 void WebMediaPlayerImpl::OnPipelineStatus(PipelineStatus status) { |
800 DCHECK(MessageLoop::current() == main_loop_); | 803 DCHECK(MessageLoop::current() == main_loop_); |
801 switch (pipeline_->GetError()) { | 804 switch (status) { |
802 case media::PIPELINE_OK: | 805 case media::PIPELINE_OK: |
803 case media::PIPELINE_ERROR_INITIALIZATION_FAILED: | 806 case media::PIPELINE_ERROR_INITIALIZATION_FAILED: |
804 case media::PIPELINE_ERROR_REQUIRED_FILTER_MISSING: | 807 case media::PIPELINE_ERROR_REQUIRED_FILTER_MISSING: |
805 case media::PIPELINE_ERROR_COULD_NOT_RENDER: | 808 case media::PIPELINE_ERROR_COULD_NOT_RENDER: |
806 case media::PIPELINE_ERROR_URL_NOT_FOUND: | 809 case media::PIPELINE_ERROR_URL_NOT_FOUND: |
807 case media::PIPELINE_ERROR_NETWORK: | 810 case media::PIPELINE_ERROR_NETWORK: |
808 case media::PIPELINE_ERROR_READ: | 811 case media::PIPELINE_ERROR_READ: |
809 case media::DEMUXER_ERROR_COULD_NOT_OPEN: | 812 case media::DEMUXER_ERROR_COULD_NOT_OPEN: |
810 case media::DEMUXER_ERROR_COULD_NOT_PARSE: | 813 case media::DEMUXER_ERROR_COULD_NOT_PARSE: |
811 case media::DEMUXER_ERROR_NO_SUPPORTED_STREAMS: | 814 case media::DEMUXER_ERROR_NO_SUPPORTED_STREAMS: |
(...skipping 11 matching lines...) Expand all Loading... |
823 case media::PIPELINE_ERROR_INVALID_STATE: | 826 case media::PIPELINE_ERROR_INVALID_STATE: |
824 // Decode error. | 827 // Decode error. |
825 SetNetworkState(WebMediaPlayer::DecodeError); | 828 SetNetworkState(WebMediaPlayer::DecodeError); |
826 break; | 829 break; |
827 } | 830 } |
828 | 831 |
829 // Repaint to trigger UI update. | 832 // Repaint to trigger UI update. |
830 Repaint(); | 833 Repaint(); |
831 } | 834 } |
832 | 835 |
833 void WebMediaPlayerImpl::OnNetworkEvent() { | 836 void WebMediaPlayerImpl::OnNetworkEvent(PipelineStatus status) { |
834 DCHECK(MessageLoop::current() == main_loop_); | 837 DCHECK(MessageLoop::current() == main_loop_); |
835 if (pipeline_->GetError() == media::PIPELINE_OK) { | 838 if (status == media::PIPELINE_OK) { |
836 if (pipeline_->IsNetworkActive()) { | 839 if (pipeline_->IsNetworkActive()) { |
837 SetNetworkState(WebKit::WebMediaPlayer::Loading); | 840 SetNetworkState(WebKit::WebMediaPlayer::Loading); |
838 } else { | 841 } else { |
839 // If we are inactive because we just finished receiving all the data, | 842 // If we are inactive because we just finished receiving all the data, |
840 // do one final repaint to show final progress. | 843 // do one final repaint to show final progress. |
841 if (bytesLoaded() == totalBytes() && | 844 if (bytesLoaded() == totalBytes() && |
842 network_state_ != WebKit::WebMediaPlayer::Idle) { | 845 network_state_ != WebKit::WebMediaPlayer::Idle) { |
843 Repaint(); | 846 Repaint(); |
844 | 847 |
845 SetNetworkState(WebKit::WebMediaPlayer::Loaded); | 848 SetNetworkState(WebKit::WebMediaPlayer::Loaded); |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
885 message_loop_factory_.reset(); | 888 message_loop_factory_.reset(); |
886 | 889 |
887 // And then detach the proxy, it may live on the render thread for a little | 890 // And then detach the proxy, it may live on the render thread for a little |
888 // longer until all the tasks are finished. | 891 // longer until all the tasks are finished. |
889 if (proxy_) { | 892 if (proxy_) { |
890 proxy_->Detach(); | 893 proxy_->Detach(); |
891 proxy_ = NULL; | 894 proxy_ = NULL; |
892 } | 895 } |
893 } | 896 } |
894 | 897 |
895 void WebMediaPlayerImpl::PipelineStoppedCallback() { | 898 void WebMediaPlayerImpl::PipelineStoppedCallback(PipelineStatus status) { |
896 pipeline_stopped_.Signal(); | 899 pipeline_stopped_.Signal(); |
897 } | 900 } |
898 | 901 |
899 WebKit::WebMediaPlayerClient* WebMediaPlayerImpl::GetClient() { | 902 WebKit::WebMediaPlayerClient* WebMediaPlayerImpl::GetClient() { |
900 DCHECK(MessageLoop::current() == main_loop_); | 903 DCHECK(MessageLoop::current() == main_loop_); |
901 DCHECK(client_); | 904 DCHECK(client_); |
902 return client_; | 905 return client_; |
903 } | 906 } |
904 | 907 |
905 } // namespace webkit_glue | 908 } // namespace webkit_glue |
OLD | NEW |