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

Side by Side Diff: media/filters/gpu_video_decoder.cc

Issue 12989009: Remove reference counting from media::VideoDecoder and friends. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: rebase Created 7 years, 8 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
« no previous file with comments | « media/filters/gpu_video_decoder.h ('k') | media/filters/pipeline_integration_test_base.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 "base/bind.h" 7 #include "base/bind.h"
8 #include "base/callback_helpers.h" 8 #include "base/callback_helpers.h"
9 #include "base/cpu.h" 9 #include "base/cpu.h"
10 #include "base/message_loop.h" 10 #include "base/message_loop.h"
11 #include "base/stl_util.h" 11 #include "base/stl_util.h"
12 #include "base/task_runner_util.h"
12 #include "media/base/bind_to_loop.h" 13 #include "media/base/bind_to_loop.h"
13 #include "media/base/decoder_buffer.h" 14 #include "media/base/decoder_buffer.h"
14 #include "media/base/demuxer_stream.h" 15 #include "media/base/demuxer_stream.h"
15 #include "media/base/pipeline.h" 16 #include "media/base/pipeline.h"
16 #include "media/base/pipeline_status.h" 17 #include "media/base/pipeline_status.h"
17 #include "media/base/video_decoder_config.h" 18 #include "media/base/video_decoder_config.h"
18 19
19 namespace media { 20 namespace media {
20 21
22 // Proxies calls to a VideoDecodeAccelerator::Client from the calling thread to
23 // the client's thread.
24 //
25 // TODO(scherkus): VDAClientProxy should hold onto GpuVideoDecoder::Factories
26 // and take care of some of the work that GpuVideoDecoder does to minimize
27 // thread hopping. See following for discussion:
28 //
29 // https://codereview.chromium.org/12989009/diff/27035/media/filters/gpu_video_d ecoder.cc#newcode23
30 class VDAClientProxy
31 : public base::RefCountedThreadSafe<VDAClientProxy>,
32 public VideoDecodeAccelerator::Client {
33 public:
34 explicit VDAClientProxy(VideoDecodeAccelerator::Client* client);
35
36 // Detaches the proxy. |weak_client_| will no longer be called and can be
37 // safely deleted. Any pending/future calls will be discarded.
38 //
39 // Must be called on |client_loop_|.
40 void Detach();
41
42 // VideoDecodeAccelerator::Client implementation.
43 virtual void NotifyInitializeDone() OVERRIDE;
44 virtual void ProvidePictureBuffers(uint32 count,
45 const gfx::Size& size,
46 uint32 texture_target) OVERRIDE;
47 virtual void DismissPictureBuffer(int32 id) OVERRIDE;
48 virtual void PictureReady(const media::Picture& picture) OVERRIDE;
49 virtual void NotifyEndOfBitstreamBuffer(int32 id) OVERRIDE;
50 virtual void NotifyFlushDone() OVERRIDE;
51 virtual void NotifyResetDone() OVERRIDE;
52 virtual void NotifyError(media::VideoDecodeAccelerator::Error error) OVERRIDE;
53
54 private:
55 friend class base::RefCountedThreadSafe<VDAClientProxy>;
56 virtual ~VDAClientProxy();
57
58 scoped_refptr<base::MessageLoopProxy> client_loop_;
59
60 // Weak pointers are used to invalidate tasks posted to |client_loop_| after
61 // Detach() has been called.
62 base::WeakPtrFactory<VideoDecodeAccelerator::Client> weak_client_factory_;
63 base::WeakPtr<VideoDecodeAccelerator::Client> weak_client_;
64
65 DISALLOW_COPY_AND_ASSIGN(VDAClientProxy);
66 };
67
68 VDAClientProxy::VDAClientProxy(VideoDecodeAccelerator::Client* client)
69 : client_loop_(base::MessageLoopProxy::current()),
70 weak_client_factory_(client),
71 weak_client_(weak_client_factory_.GetWeakPtr()) {
72 DCHECK(weak_client_);
73 }
74
75 VDAClientProxy::~VDAClientProxy() {
76 DCHECK(!weak_client_) << "Detach() was not called";
77 }
78
79 void VDAClientProxy::Detach() {
80 DCHECK(client_loop_->BelongsToCurrentThread());
81 DCHECK(weak_client_) << "Detach() already called";
82 weak_client_factory_.InvalidateWeakPtrs();
83 }
84
85 void VDAClientProxy::NotifyInitializeDone() {
86 client_loop_->PostTask(FROM_HERE, base::Bind(
87 &VideoDecodeAccelerator::Client::NotifyInitializeDone, weak_client_));
88 }
89
90 void VDAClientProxy::ProvidePictureBuffers(uint32 count,
91 const gfx::Size& size,
92 uint32 texture_target) {
93 client_loop_->PostTask(FROM_HERE, base::Bind(
94 &VideoDecodeAccelerator::Client::ProvidePictureBuffers, weak_client_,
95 count, size, texture_target));
96 }
97
98 void VDAClientProxy::DismissPictureBuffer(int32 id) {
99 client_loop_->PostTask(FROM_HERE, base::Bind(
100 &VideoDecodeAccelerator::Client::DismissPictureBuffer, weak_client_, id));
101 }
102
103 void VDAClientProxy::PictureReady(const media::Picture& picture) {
104 client_loop_->PostTask(FROM_HERE, base::Bind(
105 &VideoDecodeAccelerator::Client::PictureReady, weak_client_, picture));
106 }
107
108 void VDAClientProxy::NotifyEndOfBitstreamBuffer(int32 id) {
109 client_loop_->PostTask(FROM_HERE, base::Bind(
110 &VideoDecodeAccelerator::Client::NotifyEndOfBitstreamBuffer, weak_client_,
111 id));
112 }
113
114 void VDAClientProxy::NotifyFlushDone() {
115 client_loop_->PostTask(FROM_HERE, base::Bind(
116 &VideoDecodeAccelerator::Client::NotifyFlushDone, weak_client_));
117 }
118
119 void VDAClientProxy::NotifyResetDone() {
120 client_loop_->PostTask(FROM_HERE, base::Bind(
121 &VideoDecodeAccelerator::Client::NotifyResetDone, weak_client_));
122 }
123
124 void VDAClientProxy::NotifyError(media::VideoDecodeAccelerator::Error error) {
125 client_loop_->PostTask(FROM_HERE, base::Bind(
126 &VideoDecodeAccelerator::Client::NotifyError, weak_client_, error));
127 }
128
129
21 // Maximum number of concurrent VDA::Decode() operations GVD will maintain. 130 // Maximum number of concurrent VDA::Decode() operations GVD will maintain.
22 // 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
23 // resources. 132 // resources.
24 enum { kMaxInFlightDecodes = 4 }; 133 enum { kMaxInFlightDecodes = 4 };
25 134
26 GpuVideoDecoder::Factories::~Factories() {} 135 GpuVideoDecoder::Factories::~Factories() {}
27 136
28 // Size of shared-memory segments we allocate. Since we reuse them we let them 137 // Size of shared-memory segments we allocate. Since we reuse them we let them
29 // be on the beefy side. 138 // be on the beefy side.
30 static const size_t kSharedMemorySegmentBytes = 100 << 10; 139 static const size_t kSharedMemorySegmentBytes = 100 << 10;
(...skipping 16 matching lines...) Expand all
47 : bitstream_buffer_id(bbid), timestamp(ts), visible_rect(vr), 156 : bitstream_buffer_id(bbid), timestamp(ts), visible_rect(vr),
48 natural_size(ns) { 157 natural_size(ns) {
49 } 158 }
50 159
51 GpuVideoDecoder::BufferData::~BufferData() {} 160 GpuVideoDecoder::BufferData::~BufferData() {}
52 161
53 GpuVideoDecoder::GpuVideoDecoder( 162 GpuVideoDecoder::GpuVideoDecoder(
54 const scoped_refptr<base::MessageLoopProxy>& message_loop, 163 const scoped_refptr<base::MessageLoopProxy>& message_loop,
55 const scoped_refptr<Factories>& factories) 164 const scoped_refptr<Factories>& factories)
56 : gvd_loop_proxy_(message_loop), 165 : gvd_loop_proxy_(message_loop),
166 weak_factory_(this),
57 vda_loop_proxy_(factories->GetMessageLoop()), 167 vda_loop_proxy_(factories->GetMessageLoop()),
58 factories_(factories), 168 factories_(factories),
59 state_(kNormal), 169 state_(kNormal),
60 demuxer_read_in_progress_(false), 170 demuxer_read_in_progress_(false),
61 decoder_texture_target_(0), 171 decoder_texture_target_(0),
62 next_picture_buffer_id_(0), 172 next_picture_buffer_id_(0),
63 next_bitstream_buffer_id_(0), 173 next_bitstream_buffer_id_(0),
64 error_occured_(false), 174 error_occured_(false),
65 available_pictures_(-1) { 175 available_pictures_(-1) {
66 DCHECK(factories_); 176 DCHECK(factories_);
67 } 177 }
68 178
69 void GpuVideoDecoder::Reset(const base::Closure& closure) { 179 void GpuVideoDecoder::Reset(const base::Closure& closure) {
70 DCHECK(gvd_loop_proxy_->BelongsToCurrentThread()); 180 DCHECK(gvd_loop_proxy_->BelongsToCurrentThread());
71 181
72 if (state_ == kDrainingDecoder && !factories_->IsAborted()) { 182 if (state_ == kDrainingDecoder && !factories_->IsAborted()) {
73 gvd_loop_proxy_->PostTask(FROM_HERE, base::Bind( 183 gvd_loop_proxy_->PostTask(FROM_HERE, base::Bind(
74 &GpuVideoDecoder::Reset, this, closure)); 184 &GpuVideoDecoder::Reset, weak_this_, closure));
75 // NOTE: if we're deferring Reset() until a Flush() completes, return 185 // NOTE: if we're deferring Reset() until a Flush() completes, return
76 // queued pictures to the VDA so they can be used to finish that Flush(). 186 // queued pictures to the VDA so they can be used to finish that Flush().
77 if (pending_read_cb_.is_null()) 187 if (pending_read_cb_.is_null())
78 ready_video_frames_.clear(); 188 ready_video_frames_.clear();
79 return; 189 return;
80 } 190 }
81 191
82 // Throw away any already-decoded, not-yet-delivered frames. 192 // Throw away any already-decoded, not-yet-delivered frames.
83 ready_video_frames_.clear(); 193 ready_video_frames_.clear();
84 194
(...skipping 23 matching lines...) Expand all
108 if (!pending_reset_cb_.is_null()) 218 if (!pending_reset_cb_.is_null())
109 base::ResetAndReturn(&pending_reset_cb_).Run(); 219 base::ResetAndReturn(&pending_reset_cb_).Run();
110 demuxer_stream_ = NULL; 220 demuxer_stream_ = NULL;
111 BindToCurrentLoop(closure).Run(); 221 BindToCurrentLoop(closure).Run();
112 } 222 }
113 223
114 void GpuVideoDecoder::Initialize(const scoped_refptr<DemuxerStream>& stream, 224 void GpuVideoDecoder::Initialize(const scoped_refptr<DemuxerStream>& stream,
115 const PipelineStatusCB& orig_status_cb, 225 const PipelineStatusCB& orig_status_cb,
116 const StatisticsCB& statistics_cb) { 226 const StatisticsCB& statistics_cb) {
117 DCHECK(gvd_loop_proxy_->BelongsToCurrentThread()); 227 DCHECK(gvd_loop_proxy_->BelongsToCurrentThread());
228 weak_this_ = weak_factory_.GetWeakPtr();
229
118 PipelineStatusCB status_cb = CreateUMAReportingPipelineCB( 230 PipelineStatusCB status_cb = CreateUMAReportingPipelineCB(
119 "Media.GpuVideoDecoderInitializeStatus", 231 "Media.GpuVideoDecoderInitializeStatus",
120 BindToCurrentLoop(orig_status_cb)); 232 BindToCurrentLoop(orig_status_cb));
121 DCHECK(!demuxer_stream_); 233 DCHECK(!demuxer_stream_);
122 234
123 if (!stream) { 235 if (!stream) {
124 status_cb.Run(PIPELINE_ERROR_DECODE); 236 status_cb.Run(PIPELINE_ERROR_DECODE);
125 return; 237 return;
126 } 238 }
127 239
(...skipping 17 matching lines...) Expand all
145 bool os_large_video_support = true; 257 bool os_large_video_support = true;
146 #if defined(OS_WIN) 258 #if defined(OS_WIN)
147 os_large_video_support = false; 259 os_large_video_support = false;
148 #endif 260 #endif
149 if (!(os_large_video_support && hw_large_video_support)) { 261 if (!(os_large_video_support && hw_large_video_support)) {
150 status_cb.Run(DECODER_ERROR_NOT_SUPPORTED); 262 status_cb.Run(DECODER_ERROR_NOT_SUPPORTED);
151 return; 263 return;
152 } 264 }
153 } 265 }
154 266
267 client_proxy_ = new VDAClientProxy(this);
155 VideoDecodeAccelerator* vda = 268 VideoDecodeAccelerator* vda =
156 factories_->CreateVideoDecodeAccelerator(config.profile(), this); 269 factories_->CreateVideoDecodeAccelerator(config.profile(), client_proxy_);
157 if (!vda) { 270 if (!vda) {
158 status_cb.Run(DECODER_ERROR_NOT_SUPPORTED); 271 status_cb.Run(DECODER_ERROR_NOT_SUPPORTED);
159 return; 272 return;
160 } 273 }
161 274
162 if (config.codec() == kCodecH264) 275 if (config.codec() == kCodecH264)
163 stream->EnableBitstreamConverter(); 276 stream->EnableBitstreamConverter();
164 277
165 demuxer_stream_ = stream; 278 demuxer_stream_ = stream;
166 statistics_cb_ = statistics_cb; 279 statistics_cb_ = statistics_cb;
167 280
168 DVLOG(1) << "GpuVideoDecoder::Initialize() succeeded."; 281 DVLOG(1) << "GpuVideoDecoder::Initialize() succeeded.";
169 vda_loop_proxy_->PostTaskAndReply( 282 PostTaskAndReplyWithResult(
170 FROM_HERE, 283 vda_loop_proxy_, FROM_HERE,
171 base::Bind(&GpuVideoDecoder::SetVDA, this, vda), 284 base::Bind(&VideoDecodeAccelerator::AsWeakPtr, base::Unretained(vda)),
172 base::Bind(status_cb, PIPELINE_OK)); 285 base::Bind(&GpuVideoDecoder::SetVDA, weak_this_, status_cb, vda));
173 } 286 }
174 287
175 void GpuVideoDecoder::SetVDA(VideoDecodeAccelerator* vda) { 288 void GpuVideoDecoder::SetVDA(
176 DCHECK(vda_loop_proxy_->BelongsToCurrentThread()); 289 const PipelineStatusCB& status_cb,
290 VideoDecodeAccelerator* vda,
291 base::WeakPtr<VideoDecodeAccelerator> weak_vda) {
292 DCHECK(gvd_loop_proxy_->BelongsToCurrentThread());
177 DCHECK(!vda_.get()); 293 DCHECK(!vda_.get());
178 vda_.reset(vda); 294 vda_.reset(vda);
179 weak_vda_ = vda->AsWeakPtr(); 295 weak_vda_ = weak_vda;
296 status_cb.Run(PIPELINE_OK);
180 } 297 }
181 298
182 void GpuVideoDecoder::DestroyTextures() { 299 void GpuVideoDecoder::DestroyTextures() {
183 for (std::map<int32, PictureBuffer>::iterator it = 300 for (std::map<int32, PictureBuffer>::iterator it =
184 picture_buffers_in_decoder_.begin(); 301 picture_buffers_in_decoder_.begin();
185 it != picture_buffers_in_decoder_.end(); ++it) { 302 it != picture_buffers_in_decoder_.end(); ++it) {
186 factories_->DeleteTexture(it->second.texture_id()); 303 factories_->DeleteTexture(it->second.texture_id());
187 } 304 }
188 picture_buffers_in_decoder_.clear(); 305 picture_buffers_in_decoder_.clear();
189 } 306 }
190 307
308 static void DestroyVDAWithClientProxy(
309 const scoped_refptr<VDAClientProxy>& client_proxy,
310 base::WeakPtr<VideoDecodeAccelerator> weak_vda) {
311 if (weak_vda)
312 weak_vda->Destroy();
313 }
314
191 void GpuVideoDecoder::DestroyVDA() { 315 void GpuVideoDecoder::DestroyVDA() {
192 DCHECK(gvd_loop_proxy_->BelongsToCurrentThread()); 316 DCHECK(gvd_loop_proxy_->BelongsToCurrentThread());
317
318 // |client_proxy| must stay alive until |weak_vda_| has been destroyed.
319 vda_loop_proxy_->PostTask(FROM_HERE, base::Bind(
320 &DestroyVDAWithClientProxy, client_proxy_, weak_vda_));
321
193 VideoDecodeAccelerator* vda ALLOW_UNUSED = vda_.release(); 322 VideoDecodeAccelerator* vda ALLOW_UNUSED = vda_.release();
194 // Tricky: |this| needs to stay alive until after VDA::Destroy is actually 323 client_proxy_->Detach();
195 // called, not just posted, so we take an artificial ref to |this| and release 324 client_proxy_ = NULL;
196 // it as |reply| after VDA::Destroy() returns.
197 AddRef();
198 vda_loop_proxy_->PostTaskAndReply(
199 FROM_HERE,
200 base::Bind(&VideoDecodeAccelerator::Destroy, weak_vda_),
201 base::Bind(&GpuVideoDecoder::Release, this));
202 325
203 DestroyTextures(); 326 DestroyTextures();
204 } 327 }
205 328
206 void GpuVideoDecoder::Read(const ReadCB& read_cb) { 329 void GpuVideoDecoder::Read(const ReadCB& read_cb) {
207 DCHECK(gvd_loop_proxy_->BelongsToCurrentThread()); 330 DCHECK(gvd_loop_proxy_->BelongsToCurrentThread());
208 DCHECK(pending_reset_cb_.is_null()); 331 DCHECK(pending_reset_cb_.is_null());
209 DCHECK(pending_read_cb_.is_null()); 332 DCHECK(pending_read_cb_.is_null());
210 pending_read_cb_ = BindToCurrentLoop(read_cb); 333 pending_read_cb_ = BindToCurrentLoop(read_cb);
211 334
(...skipping 27 matching lines...) Expand all
239 } 362 }
240 } 363 }
241 364
242 bool GpuVideoDecoder::CanMoreDecodeWorkBeDone() { 365 bool GpuVideoDecoder::CanMoreDecodeWorkBeDone() {
243 return bitstream_buffers_in_decoder_.size() < kMaxInFlightDecodes; 366 return bitstream_buffers_in_decoder_.size() < kMaxInFlightDecodes;
244 } 367 }
245 368
246 void GpuVideoDecoder::RequestBufferDecode( 369 void GpuVideoDecoder::RequestBufferDecode(
247 DemuxerStream::Status status, 370 DemuxerStream::Status status,
248 const scoped_refptr<DecoderBuffer>& buffer) { 371 const scoped_refptr<DecoderBuffer>& buffer) {
372 DCHECK(gvd_loop_proxy_->BelongsToCurrentThread());
249 DCHECK_EQ(status != DemuxerStream::kOk, !buffer) << status; 373 DCHECK_EQ(status != DemuxerStream::kOk, !buffer) << status;
250 374
251 if (!gvd_loop_proxy_->BelongsToCurrentThread()) {
252 gvd_loop_proxy_->PostTask(FROM_HERE, base::Bind(
253 &GpuVideoDecoder::RequestBufferDecode, this, status, buffer));
254 return;
255 }
256 demuxer_read_in_progress_ = false; 375 demuxer_read_in_progress_ = false;
257 376
258 if (status != DemuxerStream::kOk) { 377 if (status != DemuxerStream::kOk) {
259 if (pending_read_cb_.is_null()) 378 if (pending_read_cb_.is_null())
260 return; 379 return;
261 380
262 // TODO(acolwell): Add support for reinitializing the decoder when 381 // TODO(acolwell): Add support for reinitializing the decoder when
263 // |status| == kConfigChanged. For now we just trigger a decode error. 382 // |status| == kConfigChanged. For now we just trigger a decode error.
264 Status decoder_status = 383 Status decoder_status =
265 (status == DemuxerStream::kAborted) ? kOk : kDecodeError; 384 (status == DemuxerStream::kAborted) ? kOk : kDecodeError;
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
300 bitstream_buffer.id(), BufferPair(shm_buffer, buffer))).second; 419 bitstream_buffer.id(), BufferPair(shm_buffer, buffer))).second;
301 DCHECK(inserted); 420 DCHECK(inserted);
302 RecordBufferData(bitstream_buffer, *buffer); 421 RecordBufferData(bitstream_buffer, *buffer);
303 422
304 vda_loop_proxy_->PostTask(FROM_HERE, base::Bind( 423 vda_loop_proxy_->PostTask(FROM_HERE, base::Bind(
305 &VideoDecodeAccelerator::Decode, weak_vda_, bitstream_buffer)); 424 &VideoDecodeAccelerator::Decode, weak_vda_, bitstream_buffer));
306 425
307 if (CanMoreDecodeWorkBeDone()) { 426 if (CanMoreDecodeWorkBeDone()) {
308 // Force post here to prevent reentrancy into DemuxerStream. 427 // Force post here to prevent reentrancy into DemuxerStream.
309 gvd_loop_proxy_->PostTask(FROM_HERE, base::Bind( 428 gvd_loop_proxy_->PostTask(FROM_HERE, base::Bind(
310 &GpuVideoDecoder::EnsureDemuxOrDecode, this)); 429 &GpuVideoDecoder::EnsureDemuxOrDecode, weak_this_));
311 } 430 }
312 } 431 }
313 432
314 void GpuVideoDecoder::RecordBufferData( 433 void GpuVideoDecoder::RecordBufferData(
315 const BitstreamBuffer& bitstream_buffer, const DecoderBuffer& buffer) { 434 const BitstreamBuffer& bitstream_buffer, const DecoderBuffer& buffer) {
316 input_buffer_data_.push_front(BufferData( 435 input_buffer_data_.push_front(BufferData(
317 bitstream_buffer.id(), buffer.GetTimestamp(), 436 bitstream_buffer.id(), buffer.GetTimestamp(),
318 demuxer_stream_->video_decoder_config().visible_rect(), 437 demuxer_stream_->video_decoder_config().visible_rect(),
319 demuxer_stream_->video_decoder_config().natural_size())); 438 demuxer_stream_->video_decoder_config().natural_size()));
320 // Why this value? Because why not. avformat.h:MAX_REORDER_DELAY is 16, but 439 // Why this value? Because why not. avformat.h:MAX_REORDER_DELAY is 16, but
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
353 return available_pictures_ > 0; 472 return available_pictures_ > 0;
354 } 473 }
355 474
356 void GpuVideoDecoder::NotifyInitializeDone() { 475 void GpuVideoDecoder::NotifyInitializeDone() {
357 NOTREACHED() << "GpuVideoDecodeAcceleratorHost::Initialize is synchronous!"; 476 NOTREACHED() << "GpuVideoDecodeAcceleratorHost::Initialize is synchronous!";
358 } 477 }
359 478
360 void GpuVideoDecoder::ProvidePictureBuffers(uint32 count, 479 void GpuVideoDecoder::ProvidePictureBuffers(uint32 count,
361 const gfx::Size& size, 480 const gfx::Size& size,
362 uint32 texture_target) { 481 uint32 texture_target) {
363 if (!gvd_loop_proxy_->BelongsToCurrentThread()) { 482 DCHECK(gvd_loop_proxy_->BelongsToCurrentThread());
364 gvd_loop_proxy_->PostTask(FROM_HERE, base::Bind(
365 &GpuVideoDecoder::ProvidePictureBuffers, this, count, size,
366 texture_target));
367 return;
368 }
369 483
370 std::vector<uint32> texture_ids; 484 std::vector<uint32> texture_ids;
371 decoder_texture_target_ = texture_target; 485 decoder_texture_target_ = texture_target;
372 if (!factories_->CreateTextures( 486 if (!factories_->CreateTextures(
373 count, size, &texture_ids, decoder_texture_target_)) { 487 count, size, &texture_ids, decoder_texture_target_)) {
374 NotifyError(VideoDecodeAccelerator::PLATFORM_FAILURE); 488 NotifyError(VideoDecodeAccelerator::PLATFORM_FAILURE);
375 return; 489 return;
376 } 490 }
377 491
378 if (!vda_.get()) 492 if (!vda_.get())
379 return; 493 return;
380 494
381 CHECK_EQ(available_pictures_, -1); 495 CHECK_EQ(available_pictures_, -1);
382 available_pictures_ = count; 496 available_pictures_ = count;
383 497
384 std::vector<PictureBuffer> picture_buffers; 498 std::vector<PictureBuffer> picture_buffers;
385 for (size_t i = 0; i < texture_ids.size(); ++i) { 499 for (size_t i = 0; i < texture_ids.size(); ++i) {
386 picture_buffers.push_back(PictureBuffer( 500 picture_buffers.push_back(PictureBuffer(
387 next_picture_buffer_id_++, size, texture_ids[i])); 501 next_picture_buffer_id_++, size, texture_ids[i]));
388 bool inserted = picture_buffers_in_decoder_.insert(std::make_pair( 502 bool inserted = picture_buffers_in_decoder_.insert(std::make_pair(
389 picture_buffers.back().id(), picture_buffers.back())).second; 503 picture_buffers.back().id(), picture_buffers.back())).second;
390 DCHECK(inserted); 504 DCHECK(inserted);
391 } 505 }
392 vda_loop_proxy_->PostTask(FROM_HERE, base::Bind( 506 vda_loop_proxy_->PostTask(FROM_HERE, base::Bind(
393 &VideoDecodeAccelerator::AssignPictureBuffers, weak_vda_, 507 &VideoDecodeAccelerator::AssignPictureBuffers, weak_vda_,
394 picture_buffers)); 508 picture_buffers));
395 } 509 }
396 510
397 void GpuVideoDecoder::DismissPictureBuffer(int32 id) { 511 void GpuVideoDecoder::DismissPictureBuffer(int32 id) {
398 if (!gvd_loop_proxy_->BelongsToCurrentThread()) { 512 DCHECK(gvd_loop_proxy_->BelongsToCurrentThread());
399 gvd_loop_proxy_->PostTask(FROM_HERE, base::Bind( 513
400 &GpuVideoDecoder::DismissPictureBuffer, this, id));
401 return;
402 }
403 std::map<int32, PictureBuffer>::iterator it = 514 std::map<int32, PictureBuffer>::iterator it =
404 picture_buffers_in_decoder_.find(id); 515 picture_buffers_in_decoder_.find(id);
405 if (it == picture_buffers_in_decoder_.end()) { 516 if (it == picture_buffers_in_decoder_.end()) {
406 NOTREACHED() << "Missing picture buffer: " << id; 517 NOTREACHED() << "Missing picture buffer: " << id;
407 return; 518 return;
408 } 519 }
409 factories_->DeleteTexture(it->second.texture_id()); 520 factories_->DeleteTexture(it->second.texture_id());
410 picture_buffers_in_decoder_.erase(it); 521 picture_buffers_in_decoder_.erase(it);
411 } 522 }
412 523
413 void GpuVideoDecoder::PictureReady(const media::Picture& picture) { 524 void GpuVideoDecoder::PictureReady(const media::Picture& picture) {
414 if (!gvd_loop_proxy_->BelongsToCurrentThread()) { 525 DCHECK(gvd_loop_proxy_->BelongsToCurrentThread());
415 gvd_loop_proxy_->PostTask(FROM_HERE, base::Bind( 526
416 &GpuVideoDecoder::PictureReady, this, picture));
417 return;
418 }
419 std::map<int32, PictureBuffer>::iterator it = 527 std::map<int32, PictureBuffer>::iterator it =
420 picture_buffers_in_decoder_.find(picture.picture_buffer_id()); 528 picture_buffers_in_decoder_.find(picture.picture_buffer_id());
421 if (it == picture_buffers_in_decoder_.end()) { 529 if (it == picture_buffers_in_decoder_.end()) {
422 NOTREACHED() << "Missing picture buffer: " << picture.picture_buffer_id(); 530 NOTREACHED() << "Missing picture buffer: " << picture.picture_buffer_id();
423 NotifyError(VideoDecodeAccelerator::PLATFORM_FAILURE); 531 NotifyError(VideoDecodeAccelerator::PLATFORM_FAILURE);
424 return; 532 return;
425 } 533 }
426 const PictureBuffer& pb = it->second; 534 const PictureBuffer& pb = it->second;
427 535
428 // Update frame's timestamp. 536 // Update frame's timestamp.
429 base::TimeDelta timestamp; 537 base::TimeDelta timestamp;
430 gfx::Rect visible_rect; 538 gfx::Rect visible_rect;
431 gfx::Size natural_size; 539 gfx::Size natural_size;
432 GetBufferData(picture.bitstream_buffer_id(), &timestamp, &visible_rect, 540 GetBufferData(picture.bitstream_buffer_id(), &timestamp, &visible_rect,
433 &natural_size); 541 &natural_size);
434 DCHECK(decoder_texture_target_); 542 DCHECK(decoder_texture_target_);
435 scoped_refptr<VideoFrame> frame( 543 scoped_refptr<VideoFrame> frame(
436 VideoFrame::WrapNativeTexture( 544 VideoFrame::WrapNativeTexture(
437 pb.texture_id(), decoder_texture_target_, pb.size(), visible_rect, 545 pb.texture_id(), decoder_texture_target_, pb.size(), visible_rect,
438 natural_size, timestamp, 546 natural_size, timestamp,
439 base::Bind(&Factories::ReadPixels, factories_, pb.texture_id(), 547 base::Bind(&Factories::ReadPixels, factories_, pb.texture_id(),
440 decoder_texture_target_, 548 decoder_texture_target_,
441 gfx::Size(visible_rect.width(), visible_rect.height())), 549 gfx::Size(visible_rect.width(), visible_rect.height())),
442 base::Bind(&GpuVideoDecoder::ReusePictureBuffer, this, 550 BindToCurrentLoop(base::Bind(
443 picture.picture_buffer_id()))); 551 &GpuVideoDecoder::ReusePictureBuffer, weak_this_,
552 picture.picture_buffer_id()))));
444 CHECK_GT(available_pictures_, 0); 553 CHECK_GT(available_pictures_, 0);
445 available_pictures_--; 554 available_pictures_--;
446 555
447 EnqueueFrameAndTriggerFrameDelivery(frame); 556 EnqueueFrameAndTriggerFrameDelivery(frame);
448 } 557 }
449 558
450 void GpuVideoDecoder::EnqueueFrameAndTriggerFrameDelivery( 559 void GpuVideoDecoder::EnqueueFrameAndTriggerFrameDelivery(
451 const scoped_refptr<VideoFrame>& frame) { 560 const scoped_refptr<VideoFrame>& frame) {
452 DCHECK(gvd_loop_proxy_->BelongsToCurrentThread()); 561 DCHECK(gvd_loop_proxy_->BelongsToCurrentThread());
453 562
454 // During a pending vda->Reset(), we don't accumulate frames. Drop it on the 563 // During a pending vda->Reset(), we don't accumulate frames. Drop it on the
455 // floor and return. 564 // floor and return.
456 if (!pending_reset_cb_.is_null()) 565 if (!pending_reset_cb_.is_null())
457 return; 566 return;
458 567
459 if (frame) 568 if (frame)
460 ready_video_frames_.push_back(frame); 569 ready_video_frames_.push_back(frame);
461 else 570 else
462 DCHECK(!ready_video_frames_.empty()); 571 DCHECK(!ready_video_frames_.empty());
463 572
464 if (pending_read_cb_.is_null()) 573 if (pending_read_cb_.is_null())
465 return; 574 return;
466 575
467 base::ResetAndReturn(&pending_read_cb_).Run(kOk, ready_video_frames_.front()); 576 base::ResetAndReturn(&pending_read_cb_).Run(kOk, ready_video_frames_.front());
468 ready_video_frames_.pop_front(); 577 ready_video_frames_.pop_front();
469 } 578 }
470 579
471 void GpuVideoDecoder::ReusePictureBuffer(int64 picture_buffer_id) { 580 void GpuVideoDecoder::ReusePictureBuffer(int64 picture_buffer_id) {
472 if (!gvd_loop_proxy_->BelongsToCurrentThread()) { 581 DCHECK(gvd_loop_proxy_->BelongsToCurrentThread());
473 gvd_loop_proxy_->PostTask(FROM_HERE, base::Bind(
474 &GpuVideoDecoder::ReusePictureBuffer, this, picture_buffer_id));
475 return;
476 }
477 CHECK_GE(available_pictures_, 0); 582 CHECK_GE(available_pictures_, 0);
478 available_pictures_++; 583 available_pictures_++;
479 584
480 if (!vda_.get()) 585 if (!vda_.get())
481 return; 586 return;
482 vda_loop_proxy_->PostTask(FROM_HERE, base::Bind( 587 vda_loop_proxy_->PostTask(FROM_HERE, base::Bind(
483 &VideoDecodeAccelerator::ReusePictureBuffer, weak_vda_, 588 &VideoDecodeAccelerator::ReusePictureBuffer, weak_vda_,
484 picture_buffer_id)); 589 picture_buffer_id));
485 } 590 }
486 591
(...skipping 12 matching lines...) Expand all
499 available_shm_segments_.pop_back(); 604 available_shm_segments_.pop_back();
500 return ret; 605 return ret;
501 } 606 }
502 607
503 void GpuVideoDecoder::PutSHM(SHMBuffer* shm_buffer) { 608 void GpuVideoDecoder::PutSHM(SHMBuffer* shm_buffer) {
504 DCHECK(gvd_loop_proxy_->BelongsToCurrentThread()); 609 DCHECK(gvd_loop_proxy_->BelongsToCurrentThread());
505 available_shm_segments_.push_back(shm_buffer); 610 available_shm_segments_.push_back(shm_buffer);
506 } 611 }
507 612
508 void GpuVideoDecoder::NotifyEndOfBitstreamBuffer(int32 id) { 613 void GpuVideoDecoder::NotifyEndOfBitstreamBuffer(int32 id) {
509 if (!gvd_loop_proxy_->BelongsToCurrentThread()) { 614 DCHECK(gvd_loop_proxy_->BelongsToCurrentThread());
510 gvd_loop_proxy_->PostTask(FROM_HERE, base::Bind(
511 &GpuVideoDecoder::NotifyEndOfBitstreamBuffer, this, id));
512 return;
513 }
514 615
515 std::map<int32, BufferPair>::iterator it = 616 std::map<int32, BufferPair>::iterator it =
516 bitstream_buffers_in_decoder_.find(id); 617 bitstream_buffers_in_decoder_.find(id);
517 if (it == bitstream_buffers_in_decoder_.end()) { 618 if (it == bitstream_buffers_in_decoder_.end()) {
518 NotifyError(VideoDecodeAccelerator::PLATFORM_FAILURE); 619 NotifyError(VideoDecodeAccelerator::PLATFORM_FAILURE);
519 NOTREACHED() << "Missing bitstream buffer: " << id; 620 NOTREACHED() << "Missing bitstream buffer: " << id;
520 return; 621 return;
521 } 622 }
522 623
523 PutSHM(it->second.shm_buffer); 624 PutSHM(it->second.shm_buffer);
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
558 659
559 // The second condition can happen during the tear-down process. 660 // The second condition can happen during the tear-down process.
560 // GpuVideoDecoder::Stop() returns the |pending_read_cb_| immediately without 661 // GpuVideoDecoder::Stop() returns the |pending_read_cb_| immediately without
561 // waiting for the demuxer read to be returned. Therefore, this function could 662 // waiting for the demuxer read to be returned. Therefore, this function could
562 // be called even after the decoder has been stopped. 663 // be called even after the decoder has been stopped.
563 if (demuxer_read_in_progress_ || !demuxer_stream_) 664 if (demuxer_read_in_progress_ || !demuxer_stream_)
564 return; 665 return;
565 666
566 demuxer_read_in_progress_ = true; 667 demuxer_read_in_progress_ = true;
567 demuxer_stream_->Read(base::Bind( 668 demuxer_stream_->Read(base::Bind(
568 &GpuVideoDecoder::RequestBufferDecode, this)); 669 &GpuVideoDecoder::RequestBufferDecode, weak_this_));
569 } 670 }
570 671
571 void GpuVideoDecoder::NotifyFlushDone() { 672 void GpuVideoDecoder::NotifyFlushDone() {
572 if (!gvd_loop_proxy_->BelongsToCurrentThread()) { 673 DCHECK(gvd_loop_proxy_->BelongsToCurrentThread());
573 gvd_loop_proxy_->PostTask(FROM_HERE, base::Bind(
574 &GpuVideoDecoder::NotifyFlushDone, this));
575 return;
576 }
577 DCHECK_EQ(state_, kDrainingDecoder); 674 DCHECK_EQ(state_, kDrainingDecoder);
578 state_ = kDecoderDrained; 675 state_ = kDecoderDrained;
579 EnqueueFrameAndTriggerFrameDelivery(VideoFrame::CreateEmptyFrame()); 676 EnqueueFrameAndTriggerFrameDelivery(VideoFrame::CreateEmptyFrame());
580 } 677 }
581 678
582 void GpuVideoDecoder::NotifyResetDone() { 679 void GpuVideoDecoder::NotifyResetDone() {
583 if (!gvd_loop_proxy_->BelongsToCurrentThread()) { 680 DCHECK(gvd_loop_proxy_->BelongsToCurrentThread());
584 gvd_loop_proxy_->PostTask(FROM_HERE, base::Bind(
585 &GpuVideoDecoder::NotifyResetDone, this));
586 return;
587 }
588
589 DCHECK(ready_video_frames_.empty()); 681 DCHECK(ready_video_frames_.empty());
590 682
591 // This needs to happen after the Reset() on vda_ is done to ensure pictures 683 // This needs to happen after the Reset() on vda_ is done to ensure pictures
592 // delivered during the reset can find their time data. 684 // delivered during the reset can find their time data.
593 input_buffer_data_.clear(); 685 input_buffer_data_.clear();
594 686
595 if (!pending_reset_cb_.is_null()) 687 if (!pending_reset_cb_.is_null())
596 base::ResetAndReturn(&pending_reset_cb_).Run(); 688 base::ResetAndReturn(&pending_reset_cb_).Run();
597 689
598 if (!pending_read_cb_.is_null()) 690 if (!pending_read_cb_.is_null())
599 EnqueueFrameAndTriggerFrameDelivery(VideoFrame::CreateEmptyFrame()); 691 EnqueueFrameAndTriggerFrameDelivery(VideoFrame::CreateEmptyFrame());
600 } 692 }
601 693
602 void GpuVideoDecoder::NotifyError(media::VideoDecodeAccelerator::Error error) { 694 void GpuVideoDecoder::NotifyError(media::VideoDecodeAccelerator::Error error) {
603 if (!gvd_loop_proxy_->BelongsToCurrentThread()) { 695 DCHECK(gvd_loop_proxy_->BelongsToCurrentThread());
604 gvd_loop_proxy_->PostTask(FROM_HERE, base::Bind(
605 &GpuVideoDecoder::NotifyError, this, error));
606 return;
607 }
608 if (!vda_.get()) 696 if (!vda_.get())
609 return; 697 return;
610 698
611 DLOG(ERROR) << "VDA Error: " << error; 699 DLOG(ERROR) << "VDA Error: " << error;
612 DestroyVDA(); 700 DestroyVDA();
613 701
614 error_occured_ = true; 702 error_occured_ = true;
615 703
616 if (!pending_read_cb_.is_null()) { 704 if (!pending_read_cb_.is_null()) {
617 base::ResetAndReturn(&pending_read_cb_).Run(kDecodeError, NULL); 705 base::ResetAndReturn(&pending_read_cb_).Run(kDecodeError, NULL);
618 return; 706 return;
619 } 707 }
620 } 708 }
621 709
622 } // namespace media 710 } // namespace media
OLDNEW
« no previous file with comments | « media/filters/gpu_video_decoder.h ('k') | media/filters/pipeline_integration_test_base.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698