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

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