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

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

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