| 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::TryToSetupDecodeOnSeparateThread( |
| 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 |