OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 "media/filters/gpu_video_decoder.h" | 5 #include "media/filters/gpu_video_decoder.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 | 8 |
9 #include "base/bind.h" | 9 #include "base/bind.h" |
10 #include "base/callback_helpers.h" | 10 #include "base/callback_helpers.h" |
11 #include "base/cpu.h" | 11 #include "base/cpu.h" |
12 #include "base/message_loop/message_loop.h" | 12 #include "base/message_loop/message_loop.h" |
13 #include "base/stl_util.h" | 13 #include "base/stl_util.h" |
14 #include "base/task_runner_util.h" | 14 #include "base/task_runner_util.h" |
15 #include "media/base/bind_to_loop.h" | 15 #include "media/base/bind_to_loop.h" |
16 #include "media/base/decoder_buffer.h" | 16 #include "media/base/decoder_buffer.h" |
17 #include "media/base/pipeline.h" | 17 #include "media/base/pipeline.h" |
18 #include "media/base/pipeline_status.h" | 18 #include "media/base/pipeline_status.h" |
19 #include "media/base/video_decoder_config.h" | 19 #include "media/base/video_decoder_config.h" |
| 20 #include "media/filters/gpu_video_decoder_factories.h" |
20 | 21 |
21 namespace media { | 22 namespace media { |
22 | 23 |
23 // Proxies calls to a VideoDecodeAccelerator::Client from the calling thread to | 24 // Proxies calls to a VideoDecodeAccelerator::Client from the calling thread to |
24 // the client's thread. | 25 // the client's thread. |
25 // | 26 // |
26 // TODO(scherkus): VDAClientProxy should hold onto GpuVideoDecoder::Factories | 27 // TODO(scherkus): VDAClientProxy should hold onto GpuVideoDecoderFactories |
27 // and take care of some of the work that GpuVideoDecoder does to minimize | 28 // and take care of some of the work that GpuVideoDecoder does to minimize |
28 // thread hopping. See following for discussion: | 29 // thread hopping. See following for discussion: |
29 // | 30 // |
30 // https://codereview.chromium.org/12989009/diff/27035/media/filters/gpu_video_d
ecoder.cc#newcode23 | 31 // https://codereview.chromium.org/12989009/diff/27035/media/filters/gpu_video_d
ecoder.cc#newcode23 |
31 class VDAClientProxy | 32 class VDAClientProxy |
32 : public base::RefCountedThreadSafe<VDAClientProxy>, | 33 : public base::RefCountedThreadSafe<VDAClientProxy>, |
33 public VideoDecodeAccelerator::Client { | 34 public VideoDecodeAccelerator::Client { |
34 public: | 35 public: |
35 explicit VDAClientProxy(VideoDecodeAccelerator::Client* client); | 36 explicit VDAClientProxy(VideoDecodeAccelerator::Client* client); |
36 | 37 |
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
124 client_loop_->PostTask(FROM_HERE, base::Bind( | 125 client_loop_->PostTask(FROM_HERE, base::Bind( |
125 &VideoDecodeAccelerator::Client::NotifyError, weak_client_, error)); | 126 &VideoDecodeAccelerator::Client::NotifyError, weak_client_, error)); |
126 } | 127 } |
127 | 128 |
128 | 129 |
129 // Maximum number of concurrent VDA::Decode() operations GVD will maintain. | 130 // Maximum number of concurrent VDA::Decode() operations GVD will maintain. |
130 // Higher values allow better pipelining in the GPU, but also require more | 131 // Higher values allow better pipelining in the GPU, but also require more |
131 // resources. | 132 // resources. |
132 enum { kMaxInFlightDecodes = 4 }; | 133 enum { kMaxInFlightDecodes = 4 }; |
133 | 134 |
134 GpuVideoDecoder::Factories::~Factories() {} | |
135 | |
136 // Size of shared-memory segments we allocate. Since we reuse them we let them | 135 // Size of shared-memory segments we allocate. Since we reuse them we let them |
137 // be on the beefy side. | 136 // be on the beefy side. |
138 static const size_t kSharedMemorySegmentBytes = 100 << 10; | 137 static const size_t kSharedMemorySegmentBytes = 100 << 10; |
139 | 138 |
140 GpuVideoDecoder::SHMBuffer::SHMBuffer(base::SharedMemory* m, size_t s) | 139 GpuVideoDecoder::SHMBuffer::SHMBuffer(base::SharedMemory* m, size_t s) |
141 : shm(m), size(s) { | 140 : shm(m), size(s) { |
142 } | 141 } |
143 | 142 |
144 GpuVideoDecoder::SHMBuffer::~SHMBuffer() {} | 143 GpuVideoDecoder::SHMBuffer::~SHMBuffer() {} |
145 | 144 |
146 GpuVideoDecoder::BufferPair::BufferPair( | 145 GpuVideoDecoder::BufferPair::BufferPair( |
147 SHMBuffer* s, const scoped_refptr<DecoderBuffer>& b) | 146 SHMBuffer* s, const scoped_refptr<DecoderBuffer>& b) |
148 : shm_buffer(s), buffer(b) { | 147 : shm_buffer(s), buffer(b) { |
149 } | 148 } |
150 | 149 |
151 GpuVideoDecoder::BufferPair::~BufferPair() {} | 150 GpuVideoDecoder::BufferPair::~BufferPair() {} |
152 | 151 |
153 GpuVideoDecoder::BufferData::BufferData( | 152 GpuVideoDecoder::BufferData::BufferData( |
154 int32 bbid, base::TimeDelta ts, const gfx::Rect& vr, const gfx::Size& ns) | 153 int32 bbid, base::TimeDelta ts, const gfx::Rect& vr, const gfx::Size& ns) |
155 : bitstream_buffer_id(bbid), timestamp(ts), visible_rect(vr), | 154 : bitstream_buffer_id(bbid), timestamp(ts), visible_rect(vr), |
156 natural_size(ns) { | 155 natural_size(ns) { |
157 } | 156 } |
158 | 157 |
159 GpuVideoDecoder::BufferData::~BufferData() {} | 158 GpuVideoDecoder::BufferData::~BufferData() {} |
160 | 159 |
161 GpuVideoDecoder::GpuVideoDecoder( | 160 GpuVideoDecoder::GpuVideoDecoder( |
162 const scoped_refptr<base::MessageLoopProxy>& message_loop, | 161 const scoped_refptr<base::MessageLoopProxy>& message_loop, |
163 const scoped_refptr<Factories>& factories) | 162 const scoped_refptr<GpuVideoDecoderFactories>& factories) |
164 : needs_bitstream_conversion_(false), | 163 : needs_bitstream_conversion_(false), |
165 gvd_loop_proxy_(message_loop), | 164 gvd_loop_proxy_(message_loop), |
166 weak_factory_(this), | 165 weak_factory_(this), |
167 vda_loop_proxy_(factories->GetMessageLoop()), | 166 vda_loop_proxy_(factories->GetMessageLoop()), |
168 factories_(factories), | 167 factories_(factories), |
169 state_(kNormal), | 168 state_(kNormal), |
170 decoder_texture_target_(0), | 169 decoder_texture_target_(0), |
171 next_picture_buffer_id_(0), | 170 next_picture_buffer_id_(0), |
172 next_bitstream_buffer_id_(0), | 171 next_bitstream_buffer_id_(0), |
173 available_pictures_(0) { | 172 available_pictures_(0) { |
(...skipping 366 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
540 const PictureBuffer& pb = it->second; | 539 const PictureBuffer& pb = it->second; |
541 | 540 |
542 // Update frame's timestamp. | 541 // Update frame's timestamp. |
543 base::TimeDelta timestamp; | 542 base::TimeDelta timestamp; |
544 gfx::Rect visible_rect; | 543 gfx::Rect visible_rect; |
545 gfx::Size natural_size; | 544 gfx::Size natural_size; |
546 GetBufferData(picture.bitstream_buffer_id(), ×tamp, &visible_rect, | 545 GetBufferData(picture.bitstream_buffer_id(), ×tamp, &visible_rect, |
547 &natural_size); | 546 &natural_size); |
548 DCHECK(decoder_texture_target_); | 547 DCHECK(decoder_texture_target_); |
549 | 548 |
550 scoped_refptr<VideoFrame> frame( | 549 scoped_refptr<VideoFrame> frame(VideoFrame::WrapNativeTexture( |
551 VideoFrame::WrapNativeTexture( | 550 new VideoFrame::MailboxHolder( |
552 new VideoFrame::MailboxHolder( | 551 pb.texture_mailbox(), |
553 pb.texture_mailbox(), | 552 0, // sync_point |
554 0, // sync_point | 553 BindToCurrentLoop(base::Bind(&GpuVideoDecoder::ReusePictureBuffer, |
555 BindToCurrentLoop(base::Bind( | 554 weak_this_, |
556 &GpuVideoDecoder::ReusePictureBuffer, weak_this_, | 555 picture.picture_buffer_id()))), |
557 picture.picture_buffer_id()))), | 556 decoder_texture_target_, |
558 decoder_texture_target_, | 557 pb.size(), |
559 pb.size(), visible_rect, | 558 visible_rect, |
560 natural_size, timestamp, | 559 natural_size, |
561 base::Bind(&Factories::ReadPixels, factories_, pb.texture_id(), | 560 timestamp, |
562 decoder_texture_target_, | 561 base::Bind(&GpuVideoDecoderFactories::ReadPixels, |
563 gfx::Size(visible_rect.width(), visible_rect.height())), | 562 factories_, |
564 base::Closure())); | 563 pb.texture_id(), |
| 564 decoder_texture_target_, |
| 565 gfx::Size(visible_rect.width(), visible_rect.height())), |
| 566 base::Closure())); |
565 CHECK_GT(available_pictures_, 0); | 567 CHECK_GT(available_pictures_, 0); |
566 --available_pictures_; | 568 --available_pictures_; |
567 bool inserted = | 569 bool inserted = |
568 picture_buffers_at_display_.insert(picture.picture_buffer_id()).second; | 570 picture_buffers_at_display_.insert(picture.picture_buffer_id()).second; |
569 DCHECK(inserted); | 571 DCHECK(inserted); |
570 | 572 |
571 EnqueueFrameAndTriggerFrameDelivery(frame); | 573 EnqueueFrameAndTriggerFrameDelivery(frame); |
572 } | 574 } |
573 | 575 |
574 void GpuVideoDecoder::EnqueueFrameAndTriggerFrameDelivery( | 576 void GpuVideoDecoder::EnqueueFrameAndTriggerFrameDelivery( |
(...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
719 | 721 |
720 state_ = kError; | 722 state_ = kError; |
721 | 723 |
722 if (!pending_read_cb_.is_null()) { | 724 if (!pending_read_cb_.is_null()) { |
723 base::ResetAndReturn(&pending_read_cb_).Run(kDecodeError, NULL); | 725 base::ResetAndReturn(&pending_read_cb_).Run(kDecodeError, NULL); |
724 return; | 726 return; |
725 } | 727 } |
726 } | 728 } |
727 | 729 |
728 } // namespace media | 730 } // namespace media |
OLD | NEW |