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 237 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
248 // Repeating timer responsible for draining pending IO to the codecs. | 248 // Repeating timer responsible for draining pending IO to the codecs. |
249 base::RepeatingTimer io_timer_; | 249 base::RepeatingTimer io_timer_; |
250 | 250 |
251 DISALLOW_COPY_AND_ASSIGN(AVDATimerManager); | 251 DISALLOW_COPY_AND_ASSIGN(AVDATimerManager); |
252 }; | 252 }; |
253 | 253 |
254 static base::LazyInstance<AVDATimerManager>::Leaky g_avda_timer = | 254 static base::LazyInstance<AVDATimerManager>::Leaky g_avda_timer = |
255 LAZY_INSTANCE_INITIALIZER; | 255 LAZY_INSTANCE_INITIALIZER; |
256 | 256 |
257 AndroidVideoDecodeAccelerator::AndroidVideoDecodeAccelerator( | 257 AndroidVideoDecodeAccelerator::AndroidVideoDecodeAccelerator( |
258 const base::WeakPtr<gpu::gles2::GLES2Decoder> decoder, | 258 const gpu_vda::MakeGLContextCurrentCallback& make_context_current_cb, |
259 const base::Callback<bool(void)>& make_context_current) | 259 const gpu_vda::GetGLES2DecoderCallback& get_gles2_decoder_cb) |
260 : client_(NULL), | 260 : client_(NULL), |
261 make_context_current_(make_context_current), | 261 make_context_current_cb_(make_context_current_cb), |
| 262 get_gles2_decoder_cb_(get_gles2_decoder_cb), |
262 codec_(media::kCodecH264), | 263 codec_(media::kCodecH264), |
263 is_encrypted_(false), | 264 is_encrypted_(false), |
264 needs_protected_surface_(false), | 265 needs_protected_surface_(false), |
265 state_(NO_ERROR), | 266 state_(NO_ERROR), |
266 picturebuffers_requested_(false), | 267 picturebuffers_requested_(false), |
267 gl_decoder_(decoder), | |
268 cdm_registration_id_(0), | 268 cdm_registration_id_(0), |
269 pending_input_buf_index_(-1), | 269 pending_input_buf_index_(-1), |
270 error_sequence_token_(0), | 270 error_sequence_token_(0), |
271 defer_errors_(false), | 271 defer_errors_(false), |
272 weak_this_factory_(this) { | 272 weak_this_factory_(this) {} |
273 if (UseDeferredRenderingStrategy()) { | |
274 // TODO(liberato, watk): Figure out what we want to do about zero copy for | |
275 // fullscreen external SurfaceView in WebView. http://crbug.com/582170. | |
276 DCHECK(!gl_decoder_->GetContextGroup()->mailbox_manager()->UsesSync()); | |
277 DVLOG(1) << __FUNCTION__ << ", using deferred rendering strategy."; | |
278 strategy_.reset(new AndroidDeferredRenderingBackingStrategy(this)); | |
279 } else { | |
280 DVLOG(1) << __FUNCTION__ << ", using copy back strategy."; | |
281 strategy_.reset(new AndroidCopyingBackingStrategy(this)); | |
282 } | |
283 } | |
284 | 273 |
285 AndroidVideoDecodeAccelerator::~AndroidVideoDecodeAccelerator() { | 274 AndroidVideoDecodeAccelerator::~AndroidVideoDecodeAccelerator() { |
286 DCHECK(thread_checker_.CalledOnValidThread()); | 275 DCHECK(thread_checker_.CalledOnValidThread()); |
287 g_avda_timer.Pointer()->StopTimer(this); | 276 g_avda_timer.Pointer()->StopTimer(this); |
288 | 277 |
289 #if defined(ENABLE_MOJO_MEDIA_IN_GPU_PROCESS) | 278 #if defined(ENABLE_MOJO_MEDIA_IN_GPU_PROCESS) |
290 if (cdm_) { | 279 if (cdm_) { |
291 DCHECK(cdm_registration_id_); | 280 DCHECK(cdm_registration_id_); |
292 static_cast<media::MediaDrmBridge*>(cdm_.get()) | 281 static_cast<media::MediaDrmBridge*>(cdm_.get()) |
293 ->UnregisterPlayer(cdm_registration_id_); | 282 ->UnregisterPlayer(cdm_registration_id_); |
294 } | 283 } |
295 #endif // defined(ENABLE_MOJO_MEDIA_IN_GPU_PROCESS) | 284 #endif // defined(ENABLE_MOJO_MEDIA_IN_GPU_PROCESS) |
296 } | 285 } |
297 | 286 |
298 bool AndroidVideoDecodeAccelerator::Initialize(const Config& config, | 287 bool AndroidVideoDecodeAccelerator::Initialize(const Config& config, |
299 Client* client) { | 288 Client* client) { |
300 DCHECK(!media_codec_); | 289 DCHECK(!media_codec_); |
301 DCHECK(thread_checker_.CalledOnValidThread()); | 290 DCHECK(thread_checker_.CalledOnValidThread()); |
302 TRACE_EVENT0("media", "AVDA::Initialize"); | 291 TRACE_EVENT0("media", "AVDA::Initialize"); |
303 | 292 |
304 DVLOG(1) << __FUNCTION__ << ": " << config.AsHumanReadableString(); | 293 DVLOG(1) << __FUNCTION__ << ": " << config.AsHumanReadableString(); |
305 | 294 |
| 295 if (make_context_current_cb_.is_null() || get_gles2_decoder_cb_.is_null()) { |
| 296 NOTREACHED() << "GL callbacks are required for this VDA"; |
| 297 return false; |
| 298 } |
| 299 |
306 DCHECK(client); | 300 DCHECK(client); |
307 client_ = client; | 301 client_ = client; |
308 codec_ = VideoCodecProfileToVideoCodec(config.profile); | 302 codec_ = VideoCodecProfileToVideoCodec(config.profile); |
309 is_encrypted_ = config.is_encrypted; | 303 is_encrypted_ = config.is_encrypted; |
310 | 304 |
311 bool profile_supported = codec_ == media::kCodecVP8 || | 305 bool profile_supported = codec_ == media::kCodecVP8 || |
312 codec_ == media::kCodecVP9 || | 306 codec_ == media::kCodecVP9 || |
313 codec_ == media::kCodecH264; | 307 codec_ == media::kCodecH264; |
314 | 308 |
315 if (!profile_supported) { | 309 if (!profile_supported) { |
316 LOG(ERROR) << "Unsupported profile: " << config.profile; | 310 LOG(ERROR) << "Unsupported profile: " << config.profile; |
317 return false; | 311 return false; |
318 } | 312 } |
319 | 313 |
320 // Only use MediaCodec for VP8/9 if it's likely backed by hardware | 314 // Only use MediaCodec for VP8/9 if it's likely backed by hardware |
321 // or if the stream is encrypted. | 315 // or if the stream is encrypted. |
322 if ((codec_ == media::kCodecVP8 || codec_ == media::kCodecVP9) && | 316 if ((codec_ == media::kCodecVP8 || codec_ == media::kCodecVP9) && |
323 !is_encrypted_) { | 317 !is_encrypted_) { |
324 if (media::VideoCodecBridge::IsKnownUnaccelerated( | 318 if (media::VideoCodecBridge::IsKnownUnaccelerated( |
325 codec_, media::MEDIA_CODEC_DECODER)) { | 319 codec_, media::MEDIA_CODEC_DECODER)) { |
326 DVLOG(1) << "Initialization failed: " | 320 DVLOG(1) << "Initialization failed: " |
327 << (codec_ == media::kCodecVP8 ? "vp8" : "vp9") | 321 << (codec_ == media::kCodecVP8 ? "vp8" : "vp9") |
328 << " is not hardware accelerated"; | 322 << " is not hardware accelerated"; |
329 return false; | 323 return false; |
330 } | 324 } |
331 } | 325 } |
332 | 326 |
333 if (!make_context_current_.Run()) { | 327 if (UseDeferredRenderingStrategy()) { |
| 328 // TODO(liberato, watk): Figure out what we want to do about zero copy for |
| 329 // fullscreen external SurfaceView in WebView. http://crbug.com/582170. |
| 330 auto gles_decoder = get_gles2_decoder_cb_.Run(); |
| 331 if (!gles_decoder) { |
| 332 LOG(ERROR) << "Failed to get gles2 decoder instance."; |
| 333 return false; |
| 334 } |
| 335 DCHECK(!gles_decoder->GetContextGroup()->mailbox_manager()->UsesSync()); |
| 336 DVLOG(1) << __FUNCTION__ << ", using deferred rendering strategy."; |
| 337 strategy_.reset(new AndroidDeferredRenderingBackingStrategy(this)); |
| 338 } else { |
| 339 DVLOG(1) << __FUNCTION__ << ", using copy back strategy."; |
| 340 strategy_.reset(new AndroidCopyingBackingStrategy(this)); |
| 341 } |
| 342 |
| 343 if (!make_context_current_cb_.Run()) { |
334 LOG(ERROR) << "Failed to make this decoder's GL context current."; | 344 LOG(ERROR) << "Failed to make this decoder's GL context current."; |
335 return false; | 345 return false; |
336 } | 346 } |
337 | 347 |
338 if (!gl_decoder_) { | |
339 LOG(ERROR) << "Failed to get gles2 decoder instance."; | |
340 return false; | |
341 } | |
342 | |
343 surface_ = strategy_->Initialize(config.surface_id); | 348 surface_ = strategy_->Initialize(config.surface_id); |
344 if (surface_.IsEmpty()) { | 349 if (surface_.IsEmpty()) { |
345 LOG(ERROR) << "Failed to initialize the backing strategy. The returned " | 350 LOG(ERROR) << "Failed to initialize the backing strategy. The returned " |
346 "Java surface is empty."; | 351 "Java surface is empty."; |
347 return false; | 352 return false; |
348 } | 353 } |
349 | 354 |
350 // TODO(watk,liberato): move this into the strategy. | 355 // TODO(watk,liberato): move this into the strategy. |
351 scoped_refptr<gfx::SurfaceTexture> surface_texture = | 356 scoped_refptr<gfx::SurfaceTexture> surface_texture = |
352 strategy_->GetSurfaceTexture(); | 357 strategy_->GetSurfaceTexture(); |
(...skipping 360 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
713 } | 718 } |
714 | 719 |
715 void AndroidVideoDecodeAccelerator::SendDecodedFrameToClient( | 720 void AndroidVideoDecodeAccelerator::SendDecodedFrameToClient( |
716 int32_t codec_buffer_index, | 721 int32_t codec_buffer_index, |
717 int32_t bitstream_id) { | 722 int32_t bitstream_id) { |
718 DCHECK(thread_checker_.CalledOnValidThread()); | 723 DCHECK(thread_checker_.CalledOnValidThread()); |
719 DCHECK_NE(bitstream_id, -1); | 724 DCHECK_NE(bitstream_id, -1); |
720 DCHECK(!free_picture_ids_.empty()); | 725 DCHECK(!free_picture_ids_.empty()); |
721 TRACE_EVENT0("media", "AVDA::SendDecodedFrameToClient"); | 726 TRACE_EVENT0("media", "AVDA::SendDecodedFrameToClient"); |
722 | 727 |
723 if (!make_context_current_.Run()) { | 728 if (!make_context_current_cb_.Run()) { |
724 POST_ERROR(PLATFORM_FAILURE, "Failed to make the GL context current."); | 729 POST_ERROR(PLATFORM_FAILURE, "Failed to make the GL context current."); |
725 return; | 730 return; |
726 } | 731 } |
727 | 732 |
728 int32_t picture_buffer_id = free_picture_ids_.front(); | 733 int32_t picture_buffer_id = free_picture_ids_.front(); |
729 free_picture_ids_.pop(); | 734 free_picture_ids_.pop(); |
730 TRACE_COUNTER1("media", "AVDA::FreePictureIds", free_picture_ids_.size()); | 735 TRACE_COUNTER1("media", "AVDA::FreePictureIds", free_picture_ids_.size()); |
731 | 736 |
732 const auto& i = output_picture_buffers_.find(picture_buffer_id); | 737 const auto& i = output_picture_buffers_.find(picture_buffer_id); |
733 if (i == output_picture_buffers_.end()) { | 738 if (i == output_picture_buffers_.end()) { |
(...skipping 257 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
991 ResetCodecState(); | 996 ResetCodecState(); |
992 | 997 |
993 base::MessageLoop::current()->PostTask( | 998 base::MessageLoop::current()->PostTask( |
994 FROM_HERE, base::Bind(&AndroidVideoDecodeAccelerator::NotifyResetDone, | 999 FROM_HERE, base::Bind(&AndroidVideoDecodeAccelerator::NotifyResetDone, |
995 weak_this_factory_.GetWeakPtr())); | 1000 weak_this_factory_.GetWeakPtr())); |
996 } | 1001 } |
997 | 1002 |
998 void AndroidVideoDecodeAccelerator::Destroy() { | 1003 void AndroidVideoDecodeAccelerator::Destroy() { |
999 DCHECK(thread_checker_.CalledOnValidThread()); | 1004 DCHECK(thread_checker_.CalledOnValidThread()); |
1000 | 1005 |
1001 bool have_context = make_context_current_.Run(); | 1006 bool have_context = make_context_current_cb_.Run(); |
1002 if (!have_context) | 1007 if (!have_context) |
1003 LOG(WARNING) << "Failed make GL context current for Destroy, continuing."; | 1008 LOG(WARNING) << "Failed make GL context current for Destroy, continuing."; |
1004 | 1009 |
1005 strategy_->Cleanup(have_context, output_picture_buffers_); | 1010 strategy_->Cleanup(have_context, output_picture_buffers_); |
1006 | 1011 |
1007 // If we have an OnFrameAvailable handler, tell it that we're going away. | 1012 // If we have an OnFrameAvailable handler, tell it that we're going away. |
1008 if (on_frame_available_handler_) { | 1013 if (on_frame_available_handler_) { |
1009 on_frame_available_handler_->ClearOwner(); | 1014 on_frame_available_handler_->ClearOwner(); |
1010 on_frame_available_handler_ = nullptr; | 1015 on_frame_available_handler_ = nullptr; |
1011 } | 1016 } |
1012 | 1017 |
1013 weak_this_factory_.InvalidateWeakPtrs(); | 1018 weak_this_factory_.InvalidateWeakPtrs(); |
1014 if (media_codec_) { | 1019 if (media_codec_) { |
1015 g_avda_timer.Pointer()->StopTimer(this); | 1020 g_avda_timer.Pointer()->StopTimer(this); |
1016 media_codec_.reset(); | 1021 media_codec_.reset(); |
1017 } | 1022 } |
1018 delete this; | 1023 delete this; |
1019 } | 1024 } |
1020 | 1025 |
1021 bool AndroidVideoDecodeAccelerator::CanDecodeOnIOThread() { | 1026 bool AndroidVideoDecodeAccelerator::TryToSetupDecodeOnSeparateThread( |
| 1027 const base::WeakPtr<Client>& decode_client, |
| 1028 const scoped_refptr<base::SingleThreadTaskRunner>& decode_task_runner) { |
1022 return false; | 1029 return false; |
1023 } | 1030 } |
1024 | 1031 |
1025 const gfx::Size& AndroidVideoDecodeAccelerator::GetSize() const { | 1032 const gfx::Size& AndroidVideoDecodeAccelerator::GetSize() const { |
1026 return size_; | 1033 return size_; |
1027 } | 1034 } |
1028 | 1035 |
1029 const base::ThreadChecker& AndroidVideoDecodeAccelerator::ThreadChecker() | 1036 const base::ThreadChecker& AndroidVideoDecodeAccelerator::ThreadChecker() |
1030 const { | 1037 const { |
1031 return thread_checker_; | 1038 return thread_checker_; |
1032 } | 1039 } |
1033 | 1040 |
1034 base::WeakPtr<gpu::gles2::GLES2Decoder> | 1041 base::WeakPtr<gpu::gles2::GLES2Decoder> |
1035 AndroidVideoDecodeAccelerator::GetGlDecoder() const { | 1042 AndroidVideoDecodeAccelerator::GetGlDecoder() const { |
1036 return gl_decoder_; | 1043 return get_gles2_decoder_cb_.Run(); |
1037 } | 1044 } |
1038 | 1045 |
1039 gpu::gles2::TextureRef* AndroidVideoDecodeAccelerator::GetTextureForPicture( | 1046 gpu::gles2::TextureRef* AndroidVideoDecodeAccelerator::GetTextureForPicture( |
1040 const media::PictureBuffer& picture_buffer) { | 1047 const media::PictureBuffer& picture_buffer) { |
1041 RETURN_ON_FAILURE(this, gl_decoder_, "Null gl_decoder_", ILLEGAL_STATE, | 1048 auto gles_decoder = GetGlDecoder(); |
1042 nullptr); | 1049 RETURN_ON_FAILURE(this, gles_decoder, "Failed to get GL decoder", |
1043 RETURN_ON_FAILURE(this, gl_decoder_->GetContextGroup(), | 1050 ILLEGAL_STATE, nullptr); |
1044 "Null gl_decoder_->GetContextGroup()", ILLEGAL_STATE, | 1051 RETURN_ON_FAILURE(this, gles_decoder->GetContextGroup(), |
| 1052 "Null gles_decoder->GetContextGroup()", ILLEGAL_STATE, |
1045 nullptr); | 1053 nullptr); |
1046 gpu::gles2::TextureManager* texture_manager = | 1054 gpu::gles2::TextureManager* texture_manager = |
1047 gl_decoder_->GetContextGroup()->texture_manager(); | 1055 gles_decoder->GetContextGroup()->texture_manager(); |
1048 RETURN_ON_FAILURE(this, texture_manager, "Null texture_manager", | 1056 RETURN_ON_FAILURE(this, texture_manager, "Null texture_manager", |
1049 ILLEGAL_STATE, nullptr); | 1057 ILLEGAL_STATE, nullptr); |
1050 gpu::gles2::TextureRef* texture_ref = | 1058 gpu::gles2::TextureRef* texture_ref = |
1051 texture_manager->GetTexture(picture_buffer.internal_texture_id()); | 1059 texture_manager->GetTexture(picture_buffer.internal_texture_id()); |
1052 RETURN_ON_FAILURE(this, texture_manager, "Null texture_ref", ILLEGAL_STATE, | 1060 RETURN_ON_FAILURE(this, texture_manager, "Null texture_ref", ILLEGAL_STATE, |
1053 nullptr); | 1061 nullptr); |
1054 | 1062 |
1055 return texture_ref; | 1063 return texture_ref; |
1056 } | 1064 } |
1057 | 1065 |
(...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1202 capabilities.flags = media::VideoDecodeAccelerator::Capabilities:: | 1210 capabilities.flags = media::VideoDecodeAccelerator::Capabilities:: |
1203 NEEDS_ALL_PICTURE_BUFFERS_TO_DECODE | | 1211 NEEDS_ALL_PICTURE_BUFFERS_TO_DECODE | |
1204 media::VideoDecodeAccelerator::Capabilities:: | 1212 media::VideoDecodeAccelerator::Capabilities:: |
1205 SUPPORTS_EXTERNAL_OUTPUT_SURFACE; | 1213 SUPPORTS_EXTERNAL_OUTPUT_SURFACE; |
1206 } | 1214 } |
1207 | 1215 |
1208 return capabilities; | 1216 return capabilities; |
1209 } | 1217 } |
1210 | 1218 |
1211 } // namespace content | 1219 } // namespace content |
OLD | NEW |