OLD | NEW |
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 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/common/gpu/media/android_video_decode_accelerator.h" | 5 #include "content/common/gpu/media/android_video_decode_accelerator.h" |
6 | 6 |
7 #include <stddef.h> | 7 #include <stddef.h> |
8 | 8 |
9 #include "base/android/build_info.h" | 9 #include "base/android/build_info.h" |
10 #include "base/auto_reset.h" | 10 #include "base/auto_reset.h" |
(...skipping 221 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
232 // Repeating timer responsible for draining pending IO to the codecs. | 232 // Repeating timer responsible for draining pending IO to the codecs. |
233 base::RepeatingTimer io_timer_; | 233 base::RepeatingTimer io_timer_; |
234 | 234 |
235 DISALLOW_COPY_AND_ASSIGN(AVDATimerManager); | 235 DISALLOW_COPY_AND_ASSIGN(AVDATimerManager); |
236 }; | 236 }; |
237 | 237 |
238 static base::LazyInstance<AVDATimerManager>::Leaky g_avda_timer = | 238 static base::LazyInstance<AVDATimerManager>::Leaky g_avda_timer = |
239 LAZY_INSTANCE_INITIALIZER; | 239 LAZY_INSTANCE_INITIALIZER; |
240 | 240 |
241 AndroidVideoDecodeAccelerator::AndroidVideoDecodeAccelerator( | 241 AndroidVideoDecodeAccelerator::AndroidVideoDecodeAccelerator( |
242 const base::WeakPtr<gpu::gles2::GLES2Decoder> decoder, | 242 const gpu_vda_helpers::MakeGLContextCurrentCb& make_context_current_cb, |
243 const base::Callback<bool(void)>& make_context_current) | 243 const gpu_vda_helpers::GetGLES2DecoderCb& get_gles2_decoder_cb) |
244 : client_(NULL), | 244 : client_(NULL), |
245 make_context_current_(make_context_current), | 245 make_context_current_cb_(make_context_current_cb), |
| 246 get_gles2_decoder_cb_(get_gles2_decoder_cb), |
246 codec_(media::kCodecH264), | 247 codec_(media::kCodecH264), |
247 is_encrypted_(false), | 248 is_encrypted_(false), |
248 needs_protected_surface_(false), | 249 needs_protected_surface_(false), |
249 state_(NO_ERROR), | 250 state_(NO_ERROR), |
250 picturebuffers_requested_(false), | 251 picturebuffers_requested_(false), |
251 gl_decoder_(decoder), | |
252 cdm_registration_id_(0), | 252 cdm_registration_id_(0), |
253 pending_input_buf_index_(-1), | 253 pending_input_buf_index_(-1), |
254 error_sequence_token_(0), | 254 error_sequence_token_(0), |
255 defer_errors_(false), | 255 defer_errors_(false), |
256 weak_this_factory_(this) { | 256 weak_this_factory_(this) {} |
257 if (UseDeferredRenderingStrategy()) { | |
258 // TODO(liberato, watk): Figure out what we want to do about zero copy for | |
259 // fullscreen external SurfaceView in WebView. http://crbug.com/582170. | |
260 DCHECK(!gl_decoder_->GetContextGroup()->mailbox_manager()->UsesSync()); | |
261 DVLOG(1) << __FUNCTION__ << ", using deferred rendering strategy."; | |
262 strategy_.reset(new AndroidDeferredRenderingBackingStrategy(this)); | |
263 } else { | |
264 DVLOG(1) << __FUNCTION__ << ", using copy back strategy."; | |
265 strategy_.reset(new AndroidCopyingBackingStrategy(this)); | |
266 } | |
267 } | |
268 | 257 |
269 AndroidVideoDecodeAccelerator::~AndroidVideoDecodeAccelerator() { | 258 AndroidVideoDecodeAccelerator::~AndroidVideoDecodeAccelerator() { |
270 DCHECK(thread_checker_.CalledOnValidThread()); | 259 DCHECK(thread_checker_.CalledOnValidThread()); |
271 g_avda_timer.Pointer()->StopTimer(this); | 260 g_avda_timer.Pointer()->StopTimer(this); |
272 | 261 |
273 #if defined(ENABLE_MOJO_MEDIA_IN_GPU_PROCESS) | 262 #if defined(ENABLE_MOJO_MEDIA_IN_GPU_PROCESS) |
274 if (cdm_) { | 263 if (cdm_) { |
275 DCHECK(cdm_registration_id_); | 264 DCHECK(cdm_registration_id_); |
276 static_cast<media::MediaDrmBridge*>(cdm_.get()) | 265 static_cast<media::MediaDrmBridge*>(cdm_.get()) |
277 ->UnregisterPlayer(cdm_registration_id_); | 266 ->UnregisterPlayer(cdm_registration_id_); |
278 } | 267 } |
279 #endif // defined(ENABLE_MOJO_MEDIA_IN_GPU_PROCESS) | 268 #endif // defined(ENABLE_MOJO_MEDIA_IN_GPU_PROCESS) |
280 } | 269 } |
281 | 270 |
282 bool AndroidVideoDecodeAccelerator::Initialize(const Config& config, | 271 bool AndroidVideoDecodeAccelerator::Initialize(const Config& config, |
283 Client* client) { | 272 Client* client) { |
284 DCHECK(!media_codec_); | 273 DCHECK(!media_codec_); |
285 DCHECK(thread_checker_.CalledOnValidThread()); | 274 DCHECK(thread_checker_.CalledOnValidThread()); |
286 TRACE_EVENT0("media", "AVDA::Initialize"); | 275 TRACE_EVENT0("media", "AVDA::Initialize"); |
287 | 276 |
288 DVLOG(1) << __FUNCTION__ << ": " << config.AsHumanReadableString(); | 277 DVLOG(1) << __FUNCTION__ << ": " << config.AsHumanReadableString(); |
289 | 278 |
| 279 if (make_context_current_cb_.is_null() || get_gles2_decoder_cb_.is_null()) { |
| 280 NOTREACHED() << "GL callbacks are required for this VDA"; |
| 281 return false; |
| 282 } |
| 283 |
290 DCHECK(client); | 284 DCHECK(client); |
291 client_ = client; | 285 client_ = client; |
292 codec_ = VideoCodecProfileToVideoCodec(config.profile); | 286 codec_ = VideoCodecProfileToVideoCodec(config.profile); |
293 is_encrypted_ = config.is_encrypted; | 287 is_encrypted_ = config.is_encrypted; |
294 | 288 |
295 bool profile_supported = codec_ == media::kCodecVP8 || | 289 bool profile_supported = codec_ == media::kCodecVP8 || |
296 codec_ == media::kCodecVP9 || | 290 codec_ == media::kCodecVP9 || |
297 codec_ == media::kCodecH264; | 291 codec_ == media::kCodecH264; |
298 | 292 |
299 if (!profile_supported) { | 293 if (!profile_supported) { |
300 LOG(ERROR) << "Unsupported profile: " << config.profile; | 294 LOG(ERROR) << "Unsupported profile: " << config.profile; |
301 return false; | 295 return false; |
302 } | 296 } |
303 | 297 |
304 // Only use MediaCodec for VP8/9 if it's likely backed by hardware | 298 // Only use MediaCodec for VP8/9 if it's likely backed by hardware |
305 // or if the stream is encrypted. | 299 // or if the stream is encrypted. |
306 if ((codec_ == media::kCodecVP8 || codec_ == media::kCodecVP9) && | 300 if ((codec_ == media::kCodecVP8 || codec_ == media::kCodecVP9) && |
307 !is_encrypted_) { | 301 !is_encrypted_) { |
308 if (media::VideoCodecBridge::IsKnownUnaccelerated( | 302 if (media::VideoCodecBridge::IsKnownUnaccelerated( |
309 codec_, media::MEDIA_CODEC_DECODER)) { | 303 codec_, media::MEDIA_CODEC_DECODER)) { |
310 DVLOG(1) << "Initialization failed: " | 304 DVLOG(1) << "Initialization failed: " |
311 << (codec_ == media::kCodecVP8 ? "vp8" : "vp9") | 305 << (codec_ == media::kCodecVP8 ? "vp8" : "vp9") |
312 << " is not hardware accelerated"; | 306 << " is not hardware accelerated"; |
313 return false; | 307 return false; |
314 } | 308 } |
315 } | 309 } |
316 | 310 |
317 if (!make_context_current_.Run()) { | 311 if (UseDeferredRenderingStrategy()) { |
| 312 // TODO(liberato, watk): Figure out what we want to do about zero copy for |
| 313 // fullscreen external SurfaceView in WebView. http://crbug.com/582170. |
| 314 auto gles_decoder = get_gles2_decoder_cb_.Run(); |
| 315 if (!gles_decoder) { |
| 316 LOG(ERROR) << "Failed to get gles2 decoder instance."; |
| 317 return false; |
| 318 } |
| 319 DCHECK(!gles_decoder->GetContextGroup()->mailbox_manager()->UsesSync()); |
| 320 DVLOG(1) << __FUNCTION__ << ", using deferred rendering strategy."; |
| 321 strategy_.reset(new AndroidDeferredRenderingBackingStrategy(this)); |
| 322 } else { |
| 323 DVLOG(1) << __FUNCTION__ << ", using copy back strategy."; |
| 324 strategy_.reset(new AndroidCopyingBackingStrategy(this)); |
| 325 } |
| 326 |
| 327 if (!make_context_current_cb_.Run()) { |
318 LOG(ERROR) << "Failed to make this decoder's GL context current."; | 328 LOG(ERROR) << "Failed to make this decoder's GL context current."; |
319 return false; | 329 return false; |
320 } | 330 } |
321 | 331 |
322 if (!gl_decoder_) { | |
323 LOG(ERROR) << "Failed to get gles2 decoder instance."; | |
324 return false; | |
325 } | |
326 | |
327 surface_ = strategy_->Initialize(config.surface_id); | 332 surface_ = strategy_->Initialize(config.surface_id); |
328 if (surface_.IsEmpty()) { | 333 if (surface_.IsEmpty()) { |
329 LOG(ERROR) << "Failed to initialize the backing strategy. The returned " | 334 LOG(ERROR) << "Failed to initialize the backing strategy. The returned " |
330 "Java surface is empty."; | 335 "Java surface is empty."; |
331 return false; | 336 return false; |
332 } | 337 } |
333 | 338 |
334 // TODO(watk,liberato): move this into the strategy. | 339 // TODO(watk,liberato): move this into the strategy. |
335 scoped_refptr<gfx::SurfaceTexture> surface_texture = | 340 scoped_refptr<gfx::SurfaceTexture> surface_texture = |
336 strategy_->GetSurfaceTexture(); | 341 strategy_->GetSurfaceTexture(); |
(...skipping 353 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
690 } | 695 } |
691 | 696 |
692 void AndroidVideoDecodeAccelerator::SendDecodedFrameToClient( | 697 void AndroidVideoDecodeAccelerator::SendDecodedFrameToClient( |
693 int32_t codec_buffer_index, | 698 int32_t codec_buffer_index, |
694 int32_t bitstream_id) { | 699 int32_t bitstream_id) { |
695 DCHECK(thread_checker_.CalledOnValidThread()); | 700 DCHECK(thread_checker_.CalledOnValidThread()); |
696 DCHECK_NE(bitstream_id, -1); | 701 DCHECK_NE(bitstream_id, -1); |
697 DCHECK(!free_picture_ids_.empty()); | 702 DCHECK(!free_picture_ids_.empty()); |
698 TRACE_EVENT0("media", "AVDA::SendDecodedFrameToClient"); | 703 TRACE_EVENT0("media", "AVDA::SendDecodedFrameToClient"); |
699 | 704 |
700 if (!make_context_current_.Run()) { | 705 if (!make_context_current_cb_.Run()) { |
701 POST_ERROR(PLATFORM_FAILURE, "Failed to make the GL context current."); | 706 POST_ERROR(PLATFORM_FAILURE, "Failed to make the GL context current."); |
702 return; | 707 return; |
703 } | 708 } |
704 | 709 |
705 int32_t picture_buffer_id = free_picture_ids_.front(); | 710 int32_t picture_buffer_id = free_picture_ids_.front(); |
706 free_picture_ids_.pop(); | 711 free_picture_ids_.pop(); |
707 TRACE_COUNTER1("media", "AVDA::FreePictureIds", free_picture_ids_.size()); | 712 TRACE_COUNTER1("media", "AVDA::FreePictureIds", free_picture_ids_.size()); |
708 | 713 |
709 OutputBufferMap::const_iterator i = | 714 OutputBufferMap::const_iterator i = |
710 output_picture_buffers_.find(picture_buffer_id); | 715 output_picture_buffers_.find(picture_buffer_id); |
(...skipping 242 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
953 ResetCodecState(); | 958 ResetCodecState(); |
954 | 959 |
955 base::MessageLoop::current()->PostTask( | 960 base::MessageLoop::current()->PostTask( |
956 FROM_HERE, base::Bind(&AndroidVideoDecodeAccelerator::NotifyResetDone, | 961 FROM_HERE, base::Bind(&AndroidVideoDecodeAccelerator::NotifyResetDone, |
957 weak_this_factory_.GetWeakPtr())); | 962 weak_this_factory_.GetWeakPtr())); |
958 } | 963 } |
959 | 964 |
960 void AndroidVideoDecodeAccelerator::Destroy() { | 965 void AndroidVideoDecodeAccelerator::Destroy() { |
961 DCHECK(thread_checker_.CalledOnValidThread()); | 966 DCHECK(thread_checker_.CalledOnValidThread()); |
962 | 967 |
963 bool have_context = make_context_current_.Run(); | 968 bool have_context = make_context_current_cb_.Run(); |
964 if (!have_context) | 969 if (!have_context) |
965 LOG(WARNING) << "Failed make GL context current for Destroy, continuing."; | 970 LOG(WARNING) << "Failed make GL context current for Destroy, continuing."; |
966 | 971 |
967 strategy_->Cleanup(have_context, output_picture_buffers_); | 972 strategy_->Cleanup(have_context, output_picture_buffers_); |
968 | 973 |
969 // If we have an OnFrameAvailable handler, tell it that we're going away. | 974 // If we have an OnFrameAvailable handler, tell it that we're going away. |
970 if (on_frame_available_handler_) { | 975 if (on_frame_available_handler_) { |
971 on_frame_available_handler_->ClearOwner(); | 976 on_frame_available_handler_->ClearOwner(); |
972 on_frame_available_handler_ = nullptr; | 977 on_frame_available_handler_ = nullptr; |
973 } | 978 } |
974 | 979 |
975 weak_this_factory_.InvalidateWeakPtrs(); | 980 weak_this_factory_.InvalidateWeakPtrs(); |
976 if (media_codec_) { | 981 if (media_codec_) { |
977 g_avda_timer.Pointer()->StopTimer(this); | 982 g_avda_timer.Pointer()->StopTimer(this); |
978 media_codec_.reset(); | 983 media_codec_.reset(); |
979 } | 984 } |
980 delete this; | 985 delete this; |
981 } | 986 } |
982 | 987 |
983 bool AndroidVideoDecodeAccelerator::CanDecodeOnIOThread() { | 988 bool AndroidVideoDecodeAccelerator::TryInitializeDecodeOnSeparateThread( |
| 989 const base::WeakPtr<Client>& decode_client, |
| 990 const scoped_refptr<base::SingleThreadTaskRunner>& decode_task_runner) { |
984 return false; | 991 return false; |
985 } | 992 } |
986 | 993 |
987 const gfx::Size& AndroidVideoDecodeAccelerator::GetSize() const { | 994 const gfx::Size& AndroidVideoDecodeAccelerator::GetSize() const { |
988 return size_; | 995 return size_; |
989 } | 996 } |
990 | 997 |
991 const base::ThreadChecker& AndroidVideoDecodeAccelerator::ThreadChecker() | 998 const base::ThreadChecker& AndroidVideoDecodeAccelerator::ThreadChecker() |
992 const { | 999 const { |
993 return thread_checker_; | 1000 return thread_checker_; |
994 } | 1001 } |
995 | 1002 |
996 base::WeakPtr<gpu::gles2::GLES2Decoder> | 1003 base::WeakPtr<gpu::gles2::GLES2Decoder> |
997 AndroidVideoDecodeAccelerator::GetGlDecoder() const { | 1004 AndroidVideoDecodeAccelerator::GetGlDecoder() const { |
998 return gl_decoder_; | 1005 return get_gles2_decoder_cb_.Run(); |
999 } | 1006 } |
1000 | 1007 |
1001 void AndroidVideoDecodeAccelerator::OnFrameAvailable() { | 1008 void AndroidVideoDecodeAccelerator::OnFrameAvailable() { |
1002 // Remember: this may be on any thread. | 1009 // Remember: this may be on any thread. |
1003 DCHECK(strategy_); | 1010 DCHECK(strategy_); |
1004 strategy_->OnFrameAvailable(); | 1011 strategy_->OnFrameAvailable(); |
1005 } | 1012 } |
1006 | 1013 |
1007 void AndroidVideoDecodeAccelerator::PostError( | 1014 void AndroidVideoDecodeAccelerator::PostError( |
1008 const ::tracked_objects::Location& from_here, | 1015 const ::tracked_objects::Location& from_here, |
(...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1145 capabilities.flags = media::VideoDecodeAccelerator::Capabilities:: | 1152 capabilities.flags = media::VideoDecodeAccelerator::Capabilities:: |
1146 NEEDS_ALL_PICTURE_BUFFERS_TO_DECODE | | 1153 NEEDS_ALL_PICTURE_BUFFERS_TO_DECODE | |
1147 media::VideoDecodeAccelerator::Capabilities:: | 1154 media::VideoDecodeAccelerator::Capabilities:: |
1148 SUPPORTS_EXTERNAL_OUTPUT_SURFACE; | 1155 SUPPORTS_EXTERNAL_OUTPUT_SURFACE; |
1149 } | 1156 } |
1150 | 1157 |
1151 return capabilities; | 1158 return capabilities; |
1152 } | 1159 } |
1153 | 1160 |
1154 } // namespace content | 1161 } // namespace content |
OLD | NEW |