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 233 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
244 // Repeating timer responsible for draining pending IO to the codecs. | 244 // Repeating timer responsible for draining pending IO to the codecs. |
245 base::RepeatingTimer io_timer_; | 245 base::RepeatingTimer io_timer_; |
246 | 246 |
247 DISALLOW_COPY_AND_ASSIGN(AVDATimerManager); | 247 DISALLOW_COPY_AND_ASSIGN(AVDATimerManager); |
248 }; | 248 }; |
249 | 249 |
250 static base::LazyInstance<AVDATimerManager>::Leaky g_avda_timer = | 250 static base::LazyInstance<AVDATimerManager>::Leaky g_avda_timer = |
251 LAZY_INSTANCE_INITIALIZER; | 251 LAZY_INSTANCE_INITIALIZER; |
252 | 252 |
253 AndroidVideoDecodeAccelerator::AndroidVideoDecodeAccelerator( | 253 AndroidVideoDecodeAccelerator::AndroidVideoDecodeAccelerator( |
254 const base::WeakPtr<gpu::gles2::GLES2Decoder> decoder, | 254 const MakeGLContextCurrentCallback& make_context_current_cb, |
255 const base::Callback<bool(void)>& make_context_current) | 255 const GetGLES2DecoderCallback& get_gles2_decoder_cb) |
256 : client_(NULL), | 256 : client_(NULL), |
257 make_context_current_(make_context_current), | 257 make_context_current_cb_(make_context_current_cb), |
| 258 get_gles2_decoder_cb_(get_gles2_decoder_cb), |
258 codec_(media::kCodecH264), | 259 codec_(media::kCodecH264), |
259 is_encrypted_(false), | 260 is_encrypted_(false), |
260 needs_protected_surface_(false), | 261 needs_protected_surface_(false), |
261 state_(NO_ERROR), | 262 state_(NO_ERROR), |
262 picturebuffers_requested_(false), | 263 picturebuffers_requested_(false), |
263 gl_decoder_(decoder), | |
264 media_drm_bridge_cdm_context_(nullptr), | 264 media_drm_bridge_cdm_context_(nullptr), |
265 cdm_registration_id_(0), | 265 cdm_registration_id_(0), |
266 pending_input_buf_index_(-1), | 266 pending_input_buf_index_(-1), |
267 error_sequence_token_(0), | 267 error_sequence_token_(0), |
268 defer_errors_(false), | 268 defer_errors_(false), |
269 weak_this_factory_(this) { | 269 weak_this_factory_(this) {} |
270 const gpu::GpuPreferences& gpu_preferences = | |
271 gl_decoder_->GetContextGroup()->gpu_preferences(); | |
272 if (UseDeferredRenderingStrategy(gpu_preferences)) { | |
273 // TODO(liberato, watk): Figure out what we want to do about zero copy for | |
274 // fullscreen external SurfaceView in WebView. http://crbug.com/582170. | |
275 DCHECK(!gl_decoder_->GetContextGroup()->mailbox_manager()->UsesSync()); | |
276 DVLOG(1) << __FUNCTION__ << ", using deferred rendering strategy."; | |
277 strategy_.reset(new AndroidDeferredRenderingBackingStrategy(this)); | |
278 } else { | |
279 DVLOG(1) << __FUNCTION__ << ", using copy back strategy."; | |
280 strategy_.reset(new AndroidCopyingBackingStrategy(this)); | |
281 } | |
282 } | |
283 | 270 |
284 AndroidVideoDecodeAccelerator::~AndroidVideoDecodeAccelerator() { | 271 AndroidVideoDecodeAccelerator::~AndroidVideoDecodeAccelerator() { |
285 DCHECK(thread_checker_.CalledOnValidThread()); | 272 DCHECK(thread_checker_.CalledOnValidThread()); |
286 g_avda_timer.Pointer()->StopTimer(this); | 273 g_avda_timer.Pointer()->StopTimer(this); |
287 | 274 |
288 #if defined(ENABLE_MOJO_MEDIA_IN_GPU_PROCESS) | 275 #if defined(ENABLE_MOJO_MEDIA_IN_GPU_PROCESS) |
289 if (!media_drm_bridge_cdm_context_) | 276 if (!media_drm_bridge_cdm_context_) |
290 return; | 277 return; |
291 | 278 |
292 DCHECK(cdm_registration_id_); | 279 DCHECK(cdm_registration_id_); |
293 media_drm_bridge_cdm_context_->UnregisterPlayer(cdm_registration_id_); | 280 media_drm_bridge_cdm_context_->UnregisterPlayer(cdm_registration_id_); |
294 #endif // defined(ENABLE_MOJO_MEDIA_IN_GPU_PROCESS) | 281 #endif // defined(ENABLE_MOJO_MEDIA_IN_GPU_PROCESS) |
295 } | 282 } |
296 | 283 |
297 bool AndroidVideoDecodeAccelerator::Initialize(const Config& config, | 284 bool AndroidVideoDecodeAccelerator::Initialize(const Config& config, |
298 Client* client) { | 285 Client* client) { |
299 DCHECK(!media_codec_); | 286 DCHECK(!media_codec_); |
300 DCHECK(thread_checker_.CalledOnValidThread()); | 287 DCHECK(thread_checker_.CalledOnValidThread()); |
301 TRACE_EVENT0("media", "AVDA::Initialize"); | 288 TRACE_EVENT0("media", "AVDA::Initialize"); |
302 | 289 |
303 DVLOG(1) << __FUNCTION__ << ": " << config.AsHumanReadableString(); | 290 DVLOG(1) << __FUNCTION__ << ": " << config.AsHumanReadableString(); |
304 | 291 |
| 292 if (make_context_current_cb_.is_null() || get_gles2_decoder_cb_.is_null()) { |
| 293 NOTREACHED() << "GL callbacks are required for this VDA"; |
| 294 return false; |
| 295 } |
| 296 |
305 DCHECK(client); | 297 DCHECK(client); |
306 client_ = client; | 298 client_ = client; |
307 codec_ = VideoCodecProfileToVideoCodec(config.profile); | 299 codec_ = VideoCodecProfileToVideoCodec(config.profile); |
308 is_encrypted_ = config.is_encrypted; | 300 is_encrypted_ = config.is_encrypted; |
309 | 301 |
310 bool profile_supported = codec_ == media::kCodecVP8 || | 302 bool profile_supported = codec_ == media::kCodecVP8 || |
311 codec_ == media::kCodecVP9 || | 303 codec_ == media::kCodecVP9 || |
312 codec_ == media::kCodecH264; | 304 codec_ == media::kCodecH264; |
313 | 305 |
314 if (!profile_supported) { | 306 if (!profile_supported) { |
315 LOG(ERROR) << "Unsupported profile: " << config.profile; | 307 LOG(ERROR) << "Unsupported profile: " << config.profile; |
316 return false; | 308 return false; |
317 } | 309 } |
318 | 310 |
319 // Only use MediaCodec for VP8/9 if it's likely backed by hardware | 311 // Only use MediaCodec for VP8/9 if it's likely backed by hardware |
320 // or if the stream is encrypted. | 312 // or if the stream is encrypted. |
321 if (codec_ == media::kCodecVP8 || codec_ == media::kCodecVP9) { | 313 if (codec_ == media::kCodecVP8 || codec_ == media::kCodecVP9) { |
322 DCHECK(is_encrypted_ || | 314 DCHECK(is_encrypted_ || |
323 !media::VideoCodecBridge::IsKnownUnaccelerated( | 315 !media::VideoCodecBridge::IsKnownUnaccelerated( |
324 codec_, media::MEDIA_CODEC_DECODER)); | 316 codec_, media::MEDIA_CODEC_DECODER)); |
325 } | 317 } |
326 | 318 |
327 if (!make_context_current_.Run()) { | 319 auto gles_decoder = get_gles2_decoder_cb_.Run(); |
| 320 if (!gles_decoder) { |
| 321 LOG(ERROR) << "Failed to get gles2 decoder instance."; |
| 322 return false; |
| 323 } |
| 324 |
| 325 const gpu::GpuPreferences& gpu_preferences = |
| 326 gles_decoder->GetContextGroup()->gpu_preferences(); |
| 327 |
| 328 if (UseDeferredRenderingStrategy(gpu_preferences)) { |
| 329 // TODO(liberato, watk): Figure out what we want to do about zero copy for |
| 330 // fullscreen external SurfaceView in WebView. http://crbug.com/582170. |
| 331 DCHECK(!gles_decoder->GetContextGroup()->mailbox_manager()->UsesSync()); |
| 332 DVLOG(1) << __FUNCTION__ << ", using deferred rendering strategy."; |
| 333 strategy_.reset(new AndroidDeferredRenderingBackingStrategy(this)); |
| 334 } else { |
| 335 DVLOG(1) << __FUNCTION__ << ", using copy back strategy."; |
| 336 strategy_.reset(new AndroidCopyingBackingStrategy(this)); |
| 337 } |
| 338 |
| 339 if (!make_context_current_cb_.Run()) { |
328 LOG(ERROR) << "Failed to make this decoder's GL context current."; | 340 LOG(ERROR) << "Failed to make this decoder's GL context current."; |
329 return false; | 341 return false; |
330 } | 342 } |
331 | 343 |
332 if (!gl_decoder_) { | |
333 LOG(ERROR) << "Failed to get gles2 decoder instance."; | |
334 return false; | |
335 } | |
336 | |
337 surface_ = strategy_->Initialize(config.surface_id); | 344 surface_ = strategy_->Initialize(config.surface_id); |
338 if (surface_.IsEmpty()) { | 345 if (surface_.IsEmpty()) { |
339 LOG(ERROR) << "Failed to initialize the backing strategy. The returned " | 346 LOG(ERROR) << "Failed to initialize the backing strategy. The returned " |
340 "Java surface is empty."; | 347 "Java surface is empty."; |
341 return false; | 348 return false; |
342 } | 349 } |
343 | 350 |
344 // TODO(watk,liberato): move this into the strategy. | 351 // TODO(watk,liberato): move this into the strategy. |
345 scoped_refptr<gfx::SurfaceTexture> surface_texture = | 352 scoped_refptr<gfx::SurfaceTexture> surface_texture = |
346 strategy_->GetSurfaceTexture(); | 353 strategy_->GetSurfaceTexture(); |
(...skipping 355 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
702 } | 709 } |
703 | 710 |
704 void AndroidVideoDecodeAccelerator::SendDecodedFrameToClient( | 711 void AndroidVideoDecodeAccelerator::SendDecodedFrameToClient( |
705 int32_t codec_buffer_index, | 712 int32_t codec_buffer_index, |
706 int32_t bitstream_id) { | 713 int32_t bitstream_id) { |
707 DCHECK(thread_checker_.CalledOnValidThread()); | 714 DCHECK(thread_checker_.CalledOnValidThread()); |
708 DCHECK_NE(bitstream_id, -1); | 715 DCHECK_NE(bitstream_id, -1); |
709 DCHECK(!free_picture_ids_.empty()); | 716 DCHECK(!free_picture_ids_.empty()); |
710 TRACE_EVENT0("media", "AVDA::SendDecodedFrameToClient"); | 717 TRACE_EVENT0("media", "AVDA::SendDecodedFrameToClient"); |
711 | 718 |
712 if (!make_context_current_.Run()) { | 719 if (!make_context_current_cb_.Run()) { |
713 POST_ERROR(PLATFORM_FAILURE, "Failed to make the GL context current."); | 720 POST_ERROR(PLATFORM_FAILURE, "Failed to make the GL context current."); |
714 return; | 721 return; |
715 } | 722 } |
716 | 723 |
717 int32_t picture_buffer_id = free_picture_ids_.front(); | 724 int32_t picture_buffer_id = free_picture_ids_.front(); |
718 free_picture_ids_.pop(); | 725 free_picture_ids_.pop(); |
719 TRACE_COUNTER1("media", "AVDA::FreePictureIds", free_picture_ids_.size()); | 726 TRACE_COUNTER1("media", "AVDA::FreePictureIds", free_picture_ids_.size()); |
720 | 727 |
721 const auto& i = output_picture_buffers_.find(picture_buffer_id); | 728 const auto& i = output_picture_buffers_.find(picture_buffer_id); |
722 if (i == output_picture_buffers_.end()) { | 729 if (i == output_picture_buffers_.end()) { |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
790 const std::vector<media::PictureBuffer>& buffers) { | 797 const std::vector<media::PictureBuffer>& buffers) { |
791 DCHECK(thread_checker_.CalledOnValidThread()); | 798 DCHECK(thread_checker_.CalledOnValidThread()); |
792 DCHECK(output_picture_buffers_.empty()); | 799 DCHECK(output_picture_buffers_.empty()); |
793 DCHECK(free_picture_ids_.empty()); | 800 DCHECK(free_picture_ids_.empty()); |
794 | 801 |
795 if (buffers.size() < kNumPictureBuffers) { | 802 if (buffers.size() < kNumPictureBuffers) { |
796 POST_ERROR(INVALID_ARGUMENT, "Not enough picture buffers assigned."); | 803 POST_ERROR(INVALID_ARGUMENT, "Not enough picture buffers assigned."); |
797 return; | 804 return; |
798 } | 805 } |
799 | 806 |
800 const bool have_context = make_context_current_.Run(); | 807 const bool have_context = make_context_current_cb_.Run(); |
801 LOG_IF(WARNING, !have_context) | 808 LOG_IF(WARNING, !have_context) |
802 << "Failed to make GL context current for Assign, continuing."; | 809 << "Failed to make GL context current for Assign, continuing."; |
803 | 810 |
804 for (size_t i = 0; i < buffers.size(); ++i) { | 811 for (size_t i = 0; i < buffers.size(); ++i) { |
805 if (buffers[i].size() != strategy_->GetPictureBufferSize()) { | 812 if (buffers[i].size() != strategy_->GetPictureBufferSize()) { |
806 POST_ERROR(INVALID_ARGUMENT, | 813 POST_ERROR(INVALID_ARGUMENT, |
807 "Invalid picture buffer size assigned. Wanted " | 814 "Invalid picture buffer size assigned. Wanted " |
808 << size_.ToString() << ", but got " | 815 << size_.ToString() << ", but got " |
809 << buffers[i].size().ToString()); | 816 << buffers[i].size().ToString()); |
810 return; | 817 return; |
(...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
945 ResetCodecState(); | 952 ResetCodecState(); |
946 | 953 |
947 base::MessageLoop::current()->PostTask( | 954 base::MessageLoop::current()->PostTask( |
948 FROM_HERE, base::Bind(&AndroidVideoDecodeAccelerator::NotifyResetDone, | 955 FROM_HERE, base::Bind(&AndroidVideoDecodeAccelerator::NotifyResetDone, |
949 weak_this_factory_.GetWeakPtr())); | 956 weak_this_factory_.GetWeakPtr())); |
950 } | 957 } |
951 | 958 |
952 void AndroidVideoDecodeAccelerator::Destroy() { | 959 void AndroidVideoDecodeAccelerator::Destroy() { |
953 DCHECK(thread_checker_.CalledOnValidThread()); | 960 DCHECK(thread_checker_.CalledOnValidThread()); |
954 | 961 |
955 bool have_context = make_context_current_.Run(); | 962 bool have_context = make_context_current_cb_.Run(); |
956 if (!have_context) | 963 if (!have_context) |
957 LOG(WARNING) << "Failed make GL context current for Destroy, continuing."; | 964 LOG(WARNING) << "Failed make GL context current for Destroy, continuing."; |
958 | 965 |
959 strategy_->Cleanup(have_context, output_picture_buffers_); | 966 if (strategy_) |
| 967 strategy_->Cleanup(have_context, output_picture_buffers_); |
960 | 968 |
961 // If we have an OnFrameAvailable handler, tell it that we're going away. | 969 // If we have an OnFrameAvailable handler, tell it that we're going away. |
962 if (on_frame_available_handler_) { | 970 if (on_frame_available_handler_) { |
963 on_frame_available_handler_->ClearOwner(); | 971 on_frame_available_handler_->ClearOwner(); |
964 on_frame_available_handler_ = nullptr; | 972 on_frame_available_handler_ = nullptr; |
965 } | 973 } |
966 | 974 |
967 weak_this_factory_.InvalidateWeakPtrs(); | 975 weak_this_factory_.InvalidateWeakPtrs(); |
968 if (media_codec_) { | 976 if (media_codec_) { |
969 g_avda_timer.Pointer()->StopTimer(this); | 977 g_avda_timer.Pointer()->StopTimer(this); |
970 media_codec_.reset(); | 978 media_codec_.reset(); |
971 } | 979 } |
972 delete this; | 980 delete this; |
973 } | 981 } |
974 | 982 |
975 bool AndroidVideoDecodeAccelerator::CanDecodeOnIOThread() { | 983 bool AndroidVideoDecodeAccelerator::TryToSetupDecodeOnSeparateThread( |
| 984 const base::WeakPtr<Client>& decode_client, |
| 985 const scoped_refptr<base::SingleThreadTaskRunner>& decode_task_runner) { |
976 return false; | 986 return false; |
977 } | 987 } |
978 | 988 |
979 const gfx::Size& AndroidVideoDecodeAccelerator::GetSize() const { | 989 const gfx::Size& AndroidVideoDecodeAccelerator::GetSize() const { |
980 return size_; | 990 return size_; |
981 } | 991 } |
982 | 992 |
983 const base::ThreadChecker& AndroidVideoDecodeAccelerator::ThreadChecker() | 993 const base::ThreadChecker& AndroidVideoDecodeAccelerator::ThreadChecker() |
984 const { | 994 const { |
985 return thread_checker_; | 995 return thread_checker_; |
986 } | 996 } |
987 | 997 |
988 base::WeakPtr<gpu::gles2::GLES2Decoder> | 998 base::WeakPtr<gpu::gles2::GLES2Decoder> |
989 AndroidVideoDecodeAccelerator::GetGlDecoder() const { | 999 AndroidVideoDecodeAccelerator::GetGlDecoder() const { |
990 return gl_decoder_; | 1000 return get_gles2_decoder_cb_.Run(); |
991 } | 1001 } |
992 | 1002 |
993 gpu::gles2::TextureRef* AndroidVideoDecodeAccelerator::GetTextureForPicture( | 1003 gpu::gles2::TextureRef* AndroidVideoDecodeAccelerator::GetTextureForPicture( |
994 const media::PictureBuffer& picture_buffer) { | 1004 const media::PictureBuffer& picture_buffer) { |
995 RETURN_ON_FAILURE(this, gl_decoder_, "Null gl_decoder_", ILLEGAL_STATE, | 1005 auto gles_decoder = GetGlDecoder(); |
996 nullptr); | 1006 RETURN_ON_FAILURE(this, gles_decoder, "Failed to get GL decoder", |
997 RETURN_ON_FAILURE(this, gl_decoder_->GetContextGroup(), | 1007 ILLEGAL_STATE, nullptr); |
998 "Null gl_decoder_->GetContextGroup()", ILLEGAL_STATE, | 1008 RETURN_ON_FAILURE(this, gles_decoder->GetContextGroup(), |
| 1009 "Null gles_decoder->GetContextGroup()", ILLEGAL_STATE, |
999 nullptr); | 1010 nullptr); |
1000 gpu::gles2::TextureManager* texture_manager = | 1011 gpu::gles2::TextureManager* texture_manager = |
1001 gl_decoder_->GetContextGroup()->texture_manager(); | 1012 gles_decoder->GetContextGroup()->texture_manager(); |
1002 RETURN_ON_FAILURE(this, texture_manager, "Null texture_manager", | 1013 RETURN_ON_FAILURE(this, texture_manager, "Null texture_manager", |
1003 ILLEGAL_STATE, nullptr); | 1014 ILLEGAL_STATE, nullptr); |
1004 | 1015 |
1005 DCHECK_LE(1u, picture_buffer.internal_texture_ids().size()); | 1016 DCHECK_LE(1u, picture_buffer.internal_texture_ids().size()); |
1006 gpu::gles2::TextureRef* texture_ref = | 1017 gpu::gles2::TextureRef* texture_ref = |
1007 texture_manager->GetTexture(picture_buffer.internal_texture_ids()[0]); | 1018 texture_manager->GetTexture(picture_buffer.internal_texture_ids()[0]); |
1008 RETURN_ON_FAILURE(this, texture_manager, "Null texture_ref", ILLEGAL_STATE, | 1019 RETURN_ON_FAILURE(this, texture_manager, "Null texture_ref", ILLEGAL_STATE, |
1009 nullptr); | 1020 nullptr); |
1010 | 1021 |
1011 return texture_ref; | 1022 return texture_ref; |
(...skipping 171 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1183 capabilities.flags = media::VideoDecodeAccelerator::Capabilities:: | 1194 capabilities.flags = media::VideoDecodeAccelerator::Capabilities:: |
1184 NEEDS_ALL_PICTURE_BUFFERS_TO_DECODE | | 1195 NEEDS_ALL_PICTURE_BUFFERS_TO_DECODE | |
1185 media::VideoDecodeAccelerator::Capabilities:: | 1196 media::VideoDecodeAccelerator::Capabilities:: |
1186 SUPPORTS_EXTERNAL_OUTPUT_SURFACE; | 1197 SUPPORTS_EXTERNAL_OUTPUT_SURFACE; |
1187 } | 1198 } |
1188 | 1199 |
1189 return capabilities; | 1200 return capabilities; |
1190 } | 1201 } |
1191 | 1202 |
1192 } // namespace content | 1203 } // namespace content |
OLD | NEW |