Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(224)

Side by Side Diff: content/renderer/media/rtc_video_decoder.cc

Issue 159263004: Remove threading from GpuVideoAcceleratorFactories (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: 0f7ba9fd NULL pointer fix. Created 6 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright 2013 The Chromium Authors. All rights reserved. 1 // Copyright 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/renderer/media/rtc_video_decoder.h" 5 #include "content/renderer/media/rtc_video_decoder.h"
6 6
7 #include "base/bind.h" 7 #include "base/bind.h"
8 #include "base/logging.h" 8 #include "base/logging.h"
9 #include "base/memory/ref_counted.h" 9 #include "base/memory/ref_counted.h"
10 #include "base/message_loop/message_loop_proxy.h" 10 #include "base/message_loop/message_loop_proxy.h"
11 #include "base/metrics/histogram.h" 11 #include "base/metrics/histogram.h"
12 #include "base/numerics/safe_conversions.h" 12 #include "base/numerics/safe_conversions.h"
13 #include "base/stl_util.h" 13 #include "base/stl_util.h"
14 #include "base/synchronization/waitable_event.h"
14 #include "base/task_runner_util.h" 15 #include "base/task_runner_util.h"
15 #include "content/child/child_thread.h" 16 #include "content/child/child_thread.h"
16 #include "content/renderer/media/native_handle_impl.h" 17 #include "content/renderer/media/native_handle_impl.h"
17 #include "gpu/command_buffer/common/mailbox_holder.h" 18 #include "gpu/command_buffer/common/mailbox_holder.h"
18 #include "media/base/bind_to_current_loop.h" 19 #include "media/base/bind_to_current_loop.h"
19 #include "media/filters/gpu_video_accelerator_factories.h" 20 #include "media/filters/gpu_video_accelerator_factories.h"
21 #include "third_party/skia/include/core/SkBitmap.h"
20 #include "third_party/webrtc/common_video/interface/texture_video_frame.h" 22 #include "third_party/webrtc/common_video/interface/texture_video_frame.h"
21 #include "third_party/webrtc/system_wrappers/interface/ref_count.h" 23 #include "third_party/webrtc/system_wrappers/interface/ref_count.h"
22 24
23 namespace content { 25 namespace content {
24 26
25 const int32 RTCVideoDecoder::ID_LAST = 0x3FFFFFFF; 27 const int32 RTCVideoDecoder::ID_LAST = 0x3FFFFFFF;
26 const int32 RTCVideoDecoder::ID_HALF = 0x20000000; 28 const int32 RTCVideoDecoder::ID_HALF = 0x20000000;
27 const int32 RTCVideoDecoder::ID_INVALID = -1; 29 const int32 RTCVideoDecoder::ID_INVALID = -1;
28 30
29 // Maximum number of concurrent VDA::Decode() operations RVD will maintain. 31 // Maximum number of concurrent VDA::Decode() operations RVD will maintain.
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
79 decoder_texture_target_(0), 81 decoder_texture_target_(0),
80 next_picture_buffer_id_(0), 82 next_picture_buffer_id_(0),
81 state_(UNINITIALIZED), 83 state_(UNINITIALIZED),
82 decode_complete_callback_(NULL), 84 decode_complete_callback_(NULL),
83 num_shm_buffers_(0), 85 num_shm_buffers_(0),
84 next_bitstream_buffer_id_(0), 86 next_bitstream_buffer_id_(0),
85 reset_bitstream_buffer_id_(ID_INVALID), 87 reset_bitstream_buffer_id_(ID_INVALID),
86 weak_factory_(this) { 88 weak_factory_(this) {
87 DCHECK(!vda_task_runner_->BelongsToCurrentThread()); 89 DCHECK(!vda_task_runner_->BelongsToCurrentThread());
88 weak_this_ = weak_factory_.GetWeakPtr(); 90 weak_this_ = weak_factory_.GetWeakPtr();
89
90 base::WaitableEvent message_loop_async_waiter(false, false);
91 // Waiting here is safe. The media thread is stopped in the child thread and
92 // the child thread is blocked when VideoDecoderFactory::CreateVideoDecoder
93 // runs.
94 vda_task_runner_->PostTask(FROM_HERE,
95 base::Bind(&RTCVideoDecoder::Initialize,
96 base::Unretained(this),
97 &message_loop_async_waiter));
98 message_loop_async_waiter.Wait();
99 } 91 }
100 92
101 RTCVideoDecoder::~RTCVideoDecoder() { 93 RTCVideoDecoder::~RTCVideoDecoder() {
102 DVLOG(2) << "~RTCVideoDecoder"; 94 DVLOG(2) << "~RTCVideoDecoder";
103 // Destroy VDA and remove |this| from the observer if this is vda thread. 95 DCHECK(vda_task_runner_->BelongsToCurrentThread());
104 if (vda_task_runner_->BelongsToCurrentThread()) { 96 DestroyVDA();
105 base::MessageLoop::current()->RemoveDestructionObserver(this);
106 DestroyVDA();
107 } else {
108 // VDA should have been destroyed in WillDestroyCurrentMessageLoop.
109 DCHECK(!vda_);
110 }
111 97
112 // Delete all shared memories. 98 // Delete all shared memories.
113 STLDeleteElements(&available_shm_segments_); 99 STLDeleteElements(&available_shm_segments_);
114 STLDeleteValues(&bitstream_buffers_in_decoder_); 100 STLDeleteValues(&bitstream_buffers_in_decoder_);
115 STLDeleteContainerPairFirstPointers(decode_buffers_.begin(), 101 STLDeleteContainerPairFirstPointers(decode_buffers_.begin(),
116 decode_buffers_.end()); 102 decode_buffers_.end());
117 decode_buffers_.clear(); 103 decode_buffers_.clear();
118 104
119 // Delete WebRTC input buffers. 105 // Delete WebRTC input buffers.
120 for (std::deque<std::pair<webrtc::EncodedImage, BufferData> >::iterator it = 106 for (std::deque<std::pair<webrtc::EncodedImage, BufferData> >::iterator it =
121 pending_buffers_.begin(); 107 pending_buffers_.begin();
122 it != pending_buffers_.end(); 108 it != pending_buffers_.end();
123 ++it) { 109 ++it) {
124 delete[] it->first._buffer; 110 delete[] it->first._buffer;
125 } 111 }
126 } 112 }
127 113
114 // static
128 scoped_ptr<RTCVideoDecoder> RTCVideoDecoder::Create( 115 scoped_ptr<RTCVideoDecoder> RTCVideoDecoder::Create(
129 webrtc::VideoCodecType type, 116 webrtc::VideoCodecType type,
130 const scoped_refptr<media::GpuVideoAcceleratorFactories>& factories) { 117 const scoped_refptr<media::GpuVideoAcceleratorFactories>& factories) {
131 scoped_ptr<RTCVideoDecoder> decoder; 118 scoped_ptr<RTCVideoDecoder> decoder;
132 // Convert WebRTC codec type to media codec profile. 119 // Convert WebRTC codec type to media codec profile.
133 media::VideoCodecProfile profile; 120 media::VideoCodecProfile profile;
134 switch (type) { 121 switch (type) {
135 case webrtc::kVideoCodecVP8: 122 case webrtc::kVideoCodecVP8:
136 profile = media::VP8PROFILE_MAIN; 123 profile = media::VP8PROFILE_MAIN;
137 break; 124 break;
138 default: 125 default:
139 DVLOG(2) << "Video codec not supported:" << type; 126 DVLOG(2) << "Video codec not supported:" << type;
140 return decoder.Pass(); 127 return decoder.Pass();
141 } 128 }
142 129
130 base::WaitableEvent waiter(true, false);
143 decoder.reset(new RTCVideoDecoder(factories)); 131 decoder.reset(new RTCVideoDecoder(factories));
144 decoder->vda_ = 132 decoder->vda_task_runner_->PostTask(
145 factories->CreateVideoDecodeAccelerator(profile, decoder.get()).Pass(); 133 FROM_HERE,
134 base::Bind(&RTCVideoDecoder::CreateVDA,
135 base::Unretained(decoder.get()),
136 profile,
137 &waiter));
138 waiter.Wait();
146 // vda can be NULL if VP8 is not supported. 139 // vda can be NULL if VP8 is not supported.
147 if (decoder->vda_ != NULL) { 140 if (decoder->vda_ != NULL) {
148 decoder->state_ = INITIALIZED; 141 decoder->state_ = INITIALIZED;
149 } else { 142 } else {
150 factories->GetTaskRunner()->DeleteSoon(FROM_HERE, decoder.release()); 143 factories->GetTaskRunner()->DeleteSoon(FROM_HERE, decoder.release());
151 } 144 }
152 return decoder.Pass(); 145 return decoder.Pass();
153 } 146 }
154 147
155 int32_t RTCVideoDecoder::InitDecode(const webrtc::VideoCodec* codecSettings, 148 int32_t RTCVideoDecoder::InitDecode(const webrtc::VideoCodec* codecSettings,
(...skipping 244 matching lines...) Expand 10 before | Expand all | Expand 10 after
400 { 393 {
401 base::AutoLock auto_lock(lock_); 394 base::AutoLock auto_lock(lock_);
402 DCHECK(decode_complete_callback_ != NULL); 395 DCHECK(decode_complete_callback_ != NULL);
403 if (IsBufferAfterReset(picture.bitstream_buffer_id(), 396 if (IsBufferAfterReset(picture.bitstream_buffer_id(),
404 reset_bitstream_buffer_id_)) { 397 reset_bitstream_buffer_id_)) {
405 decode_complete_callback_->Decoded(decoded_image); 398 decode_complete_callback_->Decoded(decoded_image);
406 } 399 }
407 } 400 }
408 } 401 }
409 402
403 static void ReadPixelsSyncInner(
404 const scoped_refptr<media::GpuVideoAcceleratorFactories>& factories,
405 uint32 texture_id,
406 const gfx::Rect& visible_rect,
407 const SkBitmap& pixels,
408 base::WaitableEvent* event) {
409 factories->ReadPixels(texture_id, visible_rect, pixels);
410 event->Signal();
411 }
412
413 static void ReadPixelsSync(
414 const scoped_refptr<media::GpuVideoAcceleratorFactories>& factories,
415 uint32 texture_id,
416 const gfx::Rect& visible_rect,
417 const SkBitmap& pixels) {
418 base::WaitableEvent event(true, false);
419 if (!factories->GetTaskRunner()->PostTask(FROM_HERE,
420 base::Bind(&ReadPixelsSyncInner,
421 factories,
422 texture_id,
423 visible_rect,
424 pixels,
425 &event)))
426 return;
427 event.Wait();
428 }
429
410 scoped_refptr<media::VideoFrame> RTCVideoDecoder::CreateVideoFrame( 430 scoped_refptr<media::VideoFrame> RTCVideoDecoder::CreateVideoFrame(
411 const media::Picture& picture, 431 const media::Picture& picture,
412 const media::PictureBuffer& pb, 432 const media::PictureBuffer& pb,
413 uint32_t timestamp, 433 uint32_t timestamp,
414 uint32_t width, 434 uint32_t width,
415 uint32_t height, 435 uint32_t height,
416 size_t size) { 436 size_t size) {
417 gfx::Rect visible_rect(width, height); 437 gfx::Rect visible_rect(width, height);
418 gfx::Size natural_size(width, height);
419 DCHECK(decoder_texture_target_); 438 DCHECK(decoder_texture_target_);
420 // Convert timestamp from 90KHz to ms. 439 // Convert timestamp from 90KHz to ms.
421 base::TimeDelta timestamp_ms = base::TimeDelta::FromInternalValue( 440 base::TimeDelta timestamp_ms = base::TimeDelta::FromInternalValue(
422 base::checked_cast<uint64_t>(timestamp) * 1000 / 90); 441 base::checked_cast<uint64_t>(timestamp) * 1000 / 90);
423 return media::VideoFrame::WrapNativeTexture( 442 return media::VideoFrame::WrapNativeTexture(
424 make_scoped_ptr(new gpu::MailboxHolder( 443 make_scoped_ptr(new gpu::MailboxHolder(
425 pb.texture_mailbox(), decoder_texture_target_, 0)), 444 pb.texture_mailbox(), decoder_texture_target_, 0)),
426 media::BindToCurrentLoop(base::Bind(&RTCVideoDecoder::ReusePictureBuffer, 445 media::BindToCurrentLoop(base::Bind(&RTCVideoDecoder::ReusePictureBuffer,
427 weak_this_, 446 weak_this_,
428 picture.picture_buffer_id())), 447 picture.picture_buffer_id())),
429 pb.size(), 448 pb.size(),
430 visible_rect, 449 visible_rect,
431 natural_size, 450 visible_rect.size(),
432 timestamp_ms, 451 timestamp_ms,
433 base::Bind(&media::GpuVideoAcceleratorFactories::ReadPixels, 452 base::Bind(&ReadPixelsSync, factories_, pb.texture_id(), visible_rect));
434 factories_,
435 pb.texture_id(),
436 natural_size));
437 } 453 }
438 454
439 void RTCVideoDecoder::NotifyEndOfBitstreamBuffer(int32 id) { 455 void RTCVideoDecoder::NotifyEndOfBitstreamBuffer(int32 id) {
440 DVLOG(3) << "NotifyEndOfBitstreamBuffer. id=" << id; 456 DVLOG(3) << "NotifyEndOfBitstreamBuffer. id=" << id;
441 DCHECK(vda_task_runner_->BelongsToCurrentThread()); 457 DCHECK(vda_task_runner_->BelongsToCurrentThread());
442 458
443 std::map<int32, SHMBuffer*>::iterator it = 459 std::map<int32, SHMBuffer*>::iterator it =
444 bitstream_buffers_in_decoder_.find(id); 460 bitstream_buffers_in_decoder_.find(id);
445 if (it == bitstream_buffers_in_decoder_.end()) { 461 if (it == bitstream_buffers_in_decoder_.end()) {
446 NotifyError(media::VideoDecodeAccelerator::PLATFORM_FAILURE); 462 NotifyError(media::VideoDecodeAccelerator::PLATFORM_FAILURE);
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
486 LOG(ERROR) << "VDA Error:" << error; 502 LOG(ERROR) << "VDA Error:" << error;
487 UMA_HISTOGRAM_ENUMERATION("Media.RTCVideoDecoderError", 503 UMA_HISTOGRAM_ENUMERATION("Media.RTCVideoDecoderError",
488 error, 504 error,
489 media::VideoDecodeAccelerator::LARGEST_ERROR_ENUM); 505 media::VideoDecodeAccelerator::LARGEST_ERROR_ENUM);
490 DestroyVDA(); 506 DestroyVDA();
491 507
492 base::AutoLock auto_lock(lock_); 508 base::AutoLock auto_lock(lock_);
493 state_ = DECODE_ERROR; 509 state_ = DECODE_ERROR;
494 } 510 }
495 511
496 void RTCVideoDecoder::WillDestroyCurrentMessageLoop() {
497 DVLOG(2) << "WillDestroyCurrentMessageLoop";
498 DCHECK(vda_task_runner_->BelongsToCurrentThread());
499 factories_->Abort();
500 weak_factory_.InvalidateWeakPtrs();
501 DestroyVDA();
502 }
503
504 void RTCVideoDecoder::Initialize(base::WaitableEvent* waiter) {
505 DVLOG(2) << "Initialize";
506 DCHECK(vda_task_runner_->BelongsToCurrentThread());
507 base::MessageLoop::current()->AddDestructionObserver(this);
508 waiter->Signal();
509 }
510
511 void RTCVideoDecoder::RequestBufferDecode() { 512 void RTCVideoDecoder::RequestBufferDecode() {
512 DCHECK(vda_task_runner_->BelongsToCurrentThread()); 513 DCHECK(vda_task_runner_->BelongsToCurrentThread());
513 if (!vda_) 514 if (!vda_)
514 return; 515 return;
515 516
516 MovePendingBuffersToDecodeBuffers(); 517 MovePendingBuffersToDecodeBuffers();
517 518
518 while (CanMoreDecodeWorkBeDone()) { 519 while (CanMoreDecodeWorkBeDone()) {
519 // Get a buffer and data from the queue. 520 // Get a buffer and data from the queue.
520 SHMBuffer* shm_buffer = NULL; 521 SHMBuffer* shm_buffer = NULL;
(...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after
661 factories_->DeleteTexture(it->second.texture_id()); 662 factories_->DeleteTexture(it->second.texture_id());
662 dismissed_picture_buffers_.erase(it); 663 dismissed_picture_buffers_.erase(it);
663 return; 664 return;
664 } 665 }
665 666
666 factories_->WaitSyncPoint(mailbox_holder->sync_point); 667 factories_->WaitSyncPoint(mailbox_holder->sync_point);
667 668
668 vda_->ReusePictureBuffer(picture_buffer_id); 669 vda_->ReusePictureBuffer(picture_buffer_id);
669 } 670 }
670 671
672 void RTCVideoDecoder::CreateVDA(media::VideoCodecProfile profile,
673 base::WaitableEvent* waiter) {
674 DCHECK(vda_task_runner_->BelongsToCurrentThread());
675 vda_ = factories_->CreateVideoDecodeAccelerator(profile, this);
676 waiter->Signal();
677 }
678
671 void RTCVideoDecoder::DestroyTextures() { 679 void RTCVideoDecoder::DestroyTextures() {
672 DCHECK(vda_task_runner_->BelongsToCurrentThread()); 680 DCHECK(vda_task_runner_->BelongsToCurrentThread());
673 std::map<int32, media::PictureBuffer>::iterator it; 681 std::map<int32, media::PictureBuffer>::iterator it;
674 682
675 for (it = assigned_picture_buffers_.begin(); 683 for (it = assigned_picture_buffers_.begin();
676 it != assigned_picture_buffers_.end(); 684 it != assigned_picture_buffers_.end();
677 ++it) { 685 ++it) {
678 factories_->DeleteTexture(it->second.texture_id()); 686 factories_->DeleteTexture(it->second.texture_id());
679 } 687 }
680 assigned_picture_buffers_.clear(); 688 assigned_picture_buffers_.clear();
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after
776 784
777 int32_t RTCVideoDecoder::RecordInitDecodeUMA(int32_t status) { 785 int32_t RTCVideoDecoder::RecordInitDecodeUMA(int32_t status) {
778 // Logging boolean is enough to know if HW decoding has been used. Also, 786 // Logging boolean is enough to know if HW decoding has been used. Also,
779 // InitDecode is less likely to return an error so enum is not used here. 787 // InitDecode is less likely to return an error so enum is not used here.
780 bool sample = (status == WEBRTC_VIDEO_CODEC_OK) ? true : false; 788 bool sample = (status == WEBRTC_VIDEO_CODEC_OK) ? true : false;
781 UMA_HISTOGRAM_BOOLEAN("Media.RTCVideoDecoderInitDecodeSuccess", sample); 789 UMA_HISTOGRAM_BOOLEAN("Media.RTCVideoDecoderInitDecodeSuccess", sample);
782 return status; 790 return status;
783 } 791 }
784 792
785 } // namespace content 793 } // namespace content
OLDNEW
« no previous file with comments | « content/renderer/media/rtc_video_decoder.h ('k') | content/renderer/media/rtc_video_decoder_factory.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698