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