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

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

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