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

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

Issue 10749019: VideoDecodeAccelerator now SupportsWeakPtr instead of being RefCountedThreadSafe. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: . Created 8 years, 5 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
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/message_loop.h" 9 #include "base/message_loop.h"
10 #include "base/stl_util.h" 10 #include "base/stl_util.h"
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
65 if (!gvd_loop_proxy_->BelongsToCurrentThread() || 65 if (!gvd_loop_proxy_->BelongsToCurrentThread() ||
66 state_ == kDrainingDecoder) { 66 state_ == kDrainingDecoder) {
67 gvd_loop_proxy_->PostTask(FROM_HERE, base::Bind( 67 gvd_loop_proxy_->PostTask(FROM_HERE, base::Bind(
68 &GpuVideoDecoder::Reset, this, closure)); 68 &GpuVideoDecoder::Reset, this, closure));
69 return; 69 return;
70 } 70 }
71 71
72 // Throw away any already-decoded, not-yet-delivered frames. 72 // Throw away any already-decoded, not-yet-delivered frames.
73 ready_video_frames_.clear(); 73 ready_video_frames_.clear();
74 74
75 if (!vda_) { 75 if (!vda_.get()) {
76 closure.Run(); 76 closure.Run();
77 return; 77 return;
78 } 78 }
79 79
80 DCHECK(pending_reset_cb_.is_null()); 80 DCHECK(pending_reset_cb_.is_null());
81 DCHECK(!closure.is_null()); 81 DCHECK(!closure.is_null());
82 82
83 // VideoRendererBase::Flush() can't complete while it has a pending read to 83 // VideoRendererBase::Flush() can't complete while it has a pending read to
84 // us, so we fulfill such a read here. 84 // us, so we fulfill such a read here.
85 if (!pending_read_cb_.is_null()) 85 if (!pending_read_cb_.is_null())
86 EnqueueFrameAndTriggerFrameDelivery(VideoFrame::CreateEmptyFrame()); 86 EnqueueFrameAndTriggerFrameDelivery(VideoFrame::CreateEmptyFrame());
87 87
88 if (shutting_down_) { 88 if (shutting_down_) {
89 // Immediately fire the callback instead of waiting for the reset to 89 // Immediately fire the callback instead of waiting for the reset to
90 // complete (which will happen after PipelineImpl::Stop() completes). 90 // complete (which will happen after PipelineImpl::Stop() completes).
91 gvd_loop_proxy_->PostTask(FROM_HERE, closure); 91 gvd_loop_proxy_->PostTask(FROM_HERE, closure);
92 } else { 92 } else {
93 pending_reset_cb_ = closure; 93 pending_reset_cb_ = closure;
94 } 94 }
95 95
96 vda_loop_proxy_->PostTask(FROM_HERE, base::Bind( 96 vda_loop_proxy_->PostTask(FROM_HERE, base::Bind(
97 &VideoDecodeAccelerator::Reset, vda_)); 97 &VideoDecodeAccelerator::Reset, weak_vda_));
98 } 98 }
99 99
100 void GpuVideoDecoder::Stop(const base::Closure& closure) { 100 void GpuVideoDecoder::Stop(const base::Closure& closure) {
101 if (!gvd_loop_proxy_->BelongsToCurrentThread()) { 101 if (!gvd_loop_proxy_->BelongsToCurrentThread()) {
102 gvd_loop_proxy_->PostTask(FROM_HERE, base::Bind( 102 gvd_loop_proxy_->PostTask(FROM_HERE, base::Bind(
103 &GpuVideoDecoder::Stop, this, closure)); 103 &GpuVideoDecoder::Stop, this, closure));
104 return; 104 return;
105 } 105 }
106 if (!vda_) { 106 if (!vda_.get()) {
107 closure.Run(); 107 closure.Run();
108 return; 108 return;
109 } 109 }
110 VideoDecodeAccelerator* vda ALLOW_UNUSED = vda_.release();
110 vda_loop_proxy_->PostTask(FROM_HERE, base::Bind( 111 vda_loop_proxy_->PostTask(FROM_HERE, base::Bind(
111 &VideoDecodeAccelerator::Destroy, vda_)); 112 &VideoDecodeAccelerator::Destroy, weak_vda_, true));
112 vda_ = NULL;
113 closure.Run(); 113 closure.Run();
114 } 114 }
115 115
116 void GpuVideoDecoder::Initialize(const scoped_refptr<DemuxerStream>& stream, 116 void GpuVideoDecoder::Initialize(const scoped_refptr<DemuxerStream>& stream,
117 const PipelineStatusCB& orig_status_cb, 117 const PipelineStatusCB& orig_status_cb,
118 const StatisticsCB& statistics_cb) { 118 const StatisticsCB& statistics_cb) {
119 if (!gvd_loop_proxy_->BelongsToCurrentThread()) { 119 if (!gvd_loop_proxy_->BelongsToCurrentThread()) {
120 gvd_loop_proxy_->PostTask(FROM_HERE, base::Bind( 120 gvd_loop_proxy_->PostTask(FROM_HERE, base::Bind(
121 &GpuVideoDecoder::Initialize, 121 &GpuVideoDecoder::Initialize,
122 this, stream, orig_status_cb, statistics_cb)); 122 this, stream, orig_status_cb, statistics_cb));
(...skipping 11 matching lines...) Expand all
134 134
135 const VideoDecoderConfig& config = stream->video_decoder_config(); 135 const VideoDecoderConfig& config = stream->video_decoder_config();
136 // TODO(scherkus): this check should go in Pipeline prior to creating 136 // TODO(scherkus): this check should go in Pipeline prior to creating
137 // decoder objects. 137 // decoder objects.
138 if (!config.IsValidConfig()) { 138 if (!config.IsValidConfig()) {
139 DLOG(ERROR) << "Invalid video stream - " << config.AsHumanReadableString(); 139 DLOG(ERROR) << "Invalid video stream - " << config.AsHumanReadableString();
140 status_cb.Run(PIPELINE_ERROR_DECODE); 140 status_cb.Run(PIPELINE_ERROR_DECODE);
141 return; 141 return;
142 } 142 }
143 143
144 vda_ = factories_->CreateVideoDecodeAccelerator(config.profile(), this); 144 VideoDecodeAccelerator* vda =
145 if (!vda_) { 145 factories_->CreateVideoDecodeAccelerator(config.profile(), this);
146 if (!vda) {
146 status_cb.Run(DECODER_ERROR_NOT_SUPPORTED); 147 status_cb.Run(DECODER_ERROR_NOT_SUPPORTED);
147 return; 148 return;
148 } 149 }
149 150
150 demuxer_stream_ = stream; 151 demuxer_stream_ = stream;
151 statistics_cb_ = statistics_cb; 152 statistics_cb_ = statistics_cb;
152 153
153 demuxer_stream_->EnableBitstreamConverter(); 154 demuxer_stream_->EnableBitstreamConverter();
154 155
155 natural_size_ = config.natural_size(); 156 natural_size_ = config.natural_size();
156 config_frame_duration_ = GetFrameDuration(config); 157 config_frame_duration_ = GetFrameDuration(config);
157 158
158 DVLOG(1) << "GpuVideoDecoder::Initialize() succeeded."; 159 DVLOG(1) << "GpuVideoDecoder::Initialize() succeeded.";
159 status_cb.Run(PIPELINE_OK); 160 vda_loop_proxy_->PostTaskAndReply(
161 FROM_HERE,
162 base::Bind(&GpuVideoDecoder::SetVDA, this, vda),
163 base::Bind(status_cb, PIPELINE_OK));
164 }
165
166 void GpuVideoDecoder::SetVDA(VideoDecodeAccelerator* vda) {
167 DCHECK(vda_loop_proxy_->BelongsToCurrentThread());
168 vda_.reset(vda);
169 weak_vda_ = vda->AsWeakPtr();
160 } 170 }
161 171
162 void GpuVideoDecoder::Read(const ReadCB& read_cb) { 172 void GpuVideoDecoder::Read(const ReadCB& read_cb) {
163 if (!gvd_loop_proxy_->BelongsToCurrentThread()) { 173 if (!gvd_loop_proxy_->BelongsToCurrentThread()) {
164 gvd_loop_proxy_->PostTask(FROM_HERE, base::Bind( 174 gvd_loop_proxy_->PostTask(FROM_HERE, base::Bind(
165 &GpuVideoDecoder::Read, this, read_cb)); 175 &GpuVideoDecoder::Read, this, read_cb));
166 return; 176 return;
167 } 177 }
168 178
169 if (error_occured_) { 179 if (error_occured_) {
170 read_cb.Run(kDecodeError, NULL); 180 read_cb.Run(kDecodeError, NULL);
171 return; 181 return;
172 } 182 }
173 183
174 if (!vda_) { 184 if (!vda_.get()) {
175 read_cb.Run(kOk, VideoFrame::CreateEmptyFrame()); 185 read_cb.Run(kOk, VideoFrame::CreateEmptyFrame());
176 return; 186 return;
177 } 187 }
178 188
179 DCHECK(pending_reset_cb_.is_null()); 189 DCHECK(pending_reset_cb_.is_null());
180 DCHECK(pending_read_cb_.is_null()); 190 DCHECK(pending_read_cb_.is_null());
181 pending_read_cb_ = read_cb; 191 pending_read_cb_ = read_cb;
182 192
183 if (!ready_video_frames_.empty()) { 193 if (!ready_video_frames_.empty()) {
184 EnqueueFrameAndTriggerFrameDelivery(NULL); 194 EnqueueFrameAndTriggerFrameDelivery(NULL);
(...skipping 26 matching lines...) Expand all
211 if (!buffer) { 221 if (!buffer) {
212 if (pending_read_cb_.is_null()) 222 if (pending_read_cb_.is_null())
213 return; 223 return;
214 224
215 gvd_loop_proxy_->PostTask(FROM_HERE, base::Bind( 225 gvd_loop_proxy_->PostTask(FROM_HERE, base::Bind(
216 pending_read_cb_, kOk, scoped_refptr<VideoFrame>())); 226 pending_read_cb_, kOk, scoped_refptr<VideoFrame>()));
217 pending_read_cb_.Reset(); 227 pending_read_cb_.Reset();
218 return; 228 return;
219 } 229 }
220 230
221 if (!vda_) { 231 if (!vda_.get()) {
222 EnqueueFrameAndTriggerFrameDelivery(VideoFrame::CreateEmptyFrame()); 232 EnqueueFrameAndTriggerFrameDelivery(VideoFrame::CreateEmptyFrame());
223 return; 233 return;
224 } 234 }
225 235
226 if (buffer->IsEndOfStream()) { 236 if (buffer->IsEndOfStream()) {
227 if (state_ == kNormal) { 237 if (state_ == kNormal) {
228 state_ = kDrainingDecoder; 238 state_ = kDrainingDecoder;
229 vda_loop_proxy_->PostTask(FROM_HERE, base::Bind( 239 vda_loop_proxy_->PostTask(FROM_HERE, base::Bind(
230 &VideoDecodeAccelerator::Flush, vda_)); 240 &VideoDecodeAccelerator::Flush, weak_vda_));
231 } 241 }
232 return; 242 return;
233 } 243 }
234 244
235 size_t size = buffer->GetDataSize(); 245 size_t size = buffer->GetDataSize();
236 SHMBuffer* shm_buffer = GetSHM(size); 246 SHMBuffer* shm_buffer = GetSHM(size);
237 memcpy(shm_buffer->shm->memory(), buffer->GetData(), size); 247 memcpy(shm_buffer->shm->memory(), buffer->GetData(), size);
238 BitstreamBuffer bitstream_buffer( 248 BitstreamBuffer bitstream_buffer(
239 next_bitstream_buffer_id_++, shm_buffer->shm->handle(), size); 249 next_bitstream_buffer_id_++, shm_buffer->shm->handle(), size);
240 bool inserted = bitstream_buffers_in_decoder_.insert(std::make_pair( 250 bool inserted = bitstream_buffers_in_decoder_.insert(std::make_pair(
241 bitstream_buffer.id(), BufferPair(shm_buffer, buffer))).second; 251 bitstream_buffer.id(), BufferPair(shm_buffer, buffer))).second;
242 DCHECK(inserted); 252 DCHECK(inserted);
243 RecordBufferTimeData(bitstream_buffer, *buffer); 253 RecordBufferTimeData(bitstream_buffer, *buffer);
244 254
245 vda_loop_proxy_->PostTask(FROM_HERE, base::Bind( 255 vda_loop_proxy_->PostTask(FROM_HERE, base::Bind(
246 &VideoDecodeAccelerator::Decode, vda_, bitstream_buffer)); 256 &VideoDecodeAccelerator::Decode, weak_vda_, bitstream_buffer));
247 } 257 }
248 258
249 void GpuVideoDecoder::RecordBufferTimeData( 259 void GpuVideoDecoder::RecordBufferTimeData(
250 const BitstreamBuffer& bitstream_buffer, const Buffer& buffer) { 260 const BitstreamBuffer& bitstream_buffer, const Buffer& buffer) {
251 base::TimeDelta duration = buffer.GetDuration(); 261 base::TimeDelta duration = buffer.GetDuration();
252 if (duration == base::TimeDelta()) 262 if (duration == base::TimeDelta())
253 duration = config_frame_duration_; 263 duration = config_frame_duration_;
254 input_buffer_time_data_.push_front(BufferTimeData( 264 input_buffer_time_data_.push_front(BufferTimeData(
255 bitstream_buffer.id(), buffer.GetTimestamp(), duration)); 265 bitstream_buffer.id(), buffer.GetTimestamp(), duration));
256 // Why this value? Because why not. avformat.h:MAX_REORDER_DELAY is 16, but 266 // Why this value? Because why not. avformat.h:MAX_REORDER_DELAY is 16, but
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
312 } 322 }
313 323
314 std::vector<uint32> texture_ids; 324 std::vector<uint32> texture_ids;
315 decoder_texture_target_ = texture_target; 325 decoder_texture_target_ = texture_target;
316 if (!factories_->CreateTextures( 326 if (!factories_->CreateTextures(
317 count, size, &texture_ids, decoder_texture_target_)) { 327 count, size, &texture_ids, decoder_texture_target_)) {
318 NotifyError(VideoDecodeAccelerator::PLATFORM_FAILURE); 328 NotifyError(VideoDecodeAccelerator::PLATFORM_FAILURE);
319 return; 329 return;
320 } 330 }
321 331
322 if (!vda_) 332 if (!vda_.get())
323 return; 333 return;
324 334
325 std::vector<PictureBuffer> picture_buffers; 335 std::vector<PictureBuffer> picture_buffers;
326 for (size_t i = 0; i < texture_ids.size(); ++i) { 336 for (size_t i = 0; i < texture_ids.size(); ++i) {
327 picture_buffers.push_back(PictureBuffer( 337 picture_buffers.push_back(PictureBuffer(
328 next_picture_buffer_id_++, size, texture_ids[i])); 338 next_picture_buffer_id_++, size, texture_ids[i]));
329 bool inserted = picture_buffers_in_decoder_.insert(std::make_pair( 339 bool inserted = picture_buffers_in_decoder_.insert(std::make_pair(
330 picture_buffers.back().id(), picture_buffers.back())).second; 340 picture_buffers.back().id(), picture_buffers.back())).second;
331 DCHECK(inserted); 341 DCHECK(inserted);
332 } 342 }
333 vda_loop_proxy_->PostTask(FROM_HERE, base::Bind( 343 vda_loop_proxy_->PostTask(FROM_HERE, base::Bind(
334 &VideoDecodeAccelerator::AssignPictureBuffers, vda_, picture_buffers)); 344 &VideoDecodeAccelerator::AssignPictureBuffers, weak_vda_,
345 picture_buffers));
335 } 346 }
336 347
337 void GpuVideoDecoder::DismissPictureBuffer(int32 id) { 348 void GpuVideoDecoder::DismissPictureBuffer(int32 id) {
338 if (!gvd_loop_proxy_->BelongsToCurrentThread()) { 349 if (!gvd_loop_proxy_->BelongsToCurrentThread()) {
339 gvd_loop_proxy_->PostTask(FROM_HERE, base::Bind( 350 gvd_loop_proxy_->PostTask(FROM_HERE, base::Bind(
340 &GpuVideoDecoder::DismissPictureBuffer, this, id)); 351 &GpuVideoDecoder::DismissPictureBuffer, this, id));
341 return; 352 return;
342 } 353 }
343 std::map<int32, PictureBuffer>::iterator it = 354 std::map<int32, PictureBuffer>::iterator it =
344 picture_buffers_in_decoder_.find(id); 355 picture_buffers_in_decoder_.find(id);
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
402 pending_read_cb_.Reset(); 413 pending_read_cb_.Reset();
403 ready_video_frames_.pop_front(); 414 ready_video_frames_.pop_front();
404 } 415 }
405 416
406 void GpuVideoDecoder::ReusePictureBuffer(int64 picture_buffer_id) { 417 void GpuVideoDecoder::ReusePictureBuffer(int64 picture_buffer_id) {
407 if (!gvd_loop_proxy_->BelongsToCurrentThread()) { 418 if (!gvd_loop_proxy_->BelongsToCurrentThread()) {
408 gvd_loop_proxy_->PostTask(FROM_HERE, base::Bind( 419 gvd_loop_proxy_->PostTask(FROM_HERE, base::Bind(
409 &GpuVideoDecoder::ReusePictureBuffer, this, picture_buffer_id)); 420 &GpuVideoDecoder::ReusePictureBuffer, this, picture_buffer_id));
410 return; 421 return;
411 } 422 }
412 if (!vda_) 423 if (!vda_.get())
413 return; 424 return;
414 vda_loop_proxy_->PostTask(FROM_HERE, base::Bind( 425 vda_loop_proxy_->PostTask(FROM_HERE, base::Bind(
415 &VideoDecodeAccelerator::ReusePictureBuffer, vda_, picture_buffer_id)); 426 &VideoDecodeAccelerator::ReusePictureBuffer, weak_vda_,
427 picture_buffer_id));
416 } 428 }
417 429
418 GpuVideoDecoder::SHMBuffer* GpuVideoDecoder::GetSHM(size_t min_size) { 430 GpuVideoDecoder::SHMBuffer* GpuVideoDecoder::GetSHM(size_t min_size) {
419 DCHECK(gvd_loop_proxy_->BelongsToCurrentThread()); 431 DCHECK(gvd_loop_proxy_->BelongsToCurrentThread());
420 if (available_shm_segments_.empty() || 432 if (available_shm_segments_.empty() ||
421 available_shm_segments_.back()->size < min_size) { 433 available_shm_segments_.back()->size < min_size) {
422 size_t size_to_allocate = std::max(min_size, kSharedMemorySegmentBytes); 434 size_t size_to_allocate = std::max(min_size, kSharedMemorySegmentBytes);
423 base::SharedMemory* shm = factories_->CreateSharedMemory(size_to_allocate); 435 base::SharedMemory* shm = factories_->CreateSharedMemory(size_to_allocate);
424 DCHECK(shm); 436 DCHECK(shm);
425 return new SHMBuffer(shm, size_to_allocate); 437 return new SHMBuffer(shm, size_to_allocate);
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
460 472
461 if (!pending_read_cb_.is_null() && pending_reset_cb_.is_null() && 473 if (!pending_read_cb_.is_null() && pending_reset_cb_.is_null() &&
462 state_ != kDrainingDecoder && 474 state_ != kDrainingDecoder &&
463 bitstream_buffers_in_decoder_.empty()) { 475 bitstream_buffers_in_decoder_.empty()) {
464 DCHECK(ready_video_frames_.empty()); 476 DCHECK(ready_video_frames_.empty());
465 EnsureDemuxOrDecode(); 477 EnsureDemuxOrDecode();
466 } 478 }
467 } 479 }
468 480
469 GpuVideoDecoder::~GpuVideoDecoder() { 481 GpuVideoDecoder::~GpuVideoDecoder() {
470 DCHECK(!vda_); // Stop should have been already called. 482 DCHECK(!vda_.get()); // Stop should have been already called.
471 DCHECK(pending_read_cb_.is_null()); 483 DCHECK(pending_read_cb_.is_null());
472 for (size_t i = 0; i < available_shm_segments_.size(); ++i) { 484 for (size_t i = 0; i < available_shm_segments_.size(); ++i) {
473 available_shm_segments_[i]->shm->Close(); 485 available_shm_segments_[i]->shm->Close();
474 delete available_shm_segments_[i]; 486 delete available_shm_segments_[i];
475 } 487 }
476 available_shm_segments_.clear(); 488 available_shm_segments_.clear();
477 for (std::map<int32, BufferPair>::iterator it = 489 for (std::map<int32, BufferPair>::iterator it =
478 bitstream_buffers_in_decoder_.begin(); 490 bitstream_buffers_in_decoder_.begin();
479 it != bitstream_buffers_in_decoder_.end(); ++it) { 491 it != bitstream_buffers_in_decoder_.end(); ++it) {
480 it->second.shm_buffer->shm->Close(); 492 it->second.shm_buffer->shm->Close();
(...skipping 22 matching lines...) Expand all
503 EnqueueFrameAndTriggerFrameDelivery(VideoFrame::CreateEmptyFrame()); 515 EnqueueFrameAndTriggerFrameDelivery(VideoFrame::CreateEmptyFrame());
504 } 516 }
505 517
506 void GpuVideoDecoder::NotifyResetDone() { 518 void GpuVideoDecoder::NotifyResetDone() {
507 if (!gvd_loop_proxy_->BelongsToCurrentThread()) { 519 if (!gvd_loop_proxy_->BelongsToCurrentThread()) {
508 gvd_loop_proxy_->PostTask(FROM_HERE, base::Bind( 520 gvd_loop_proxy_->PostTask(FROM_HERE, base::Bind(
509 &GpuVideoDecoder::NotifyResetDone, this)); 521 &GpuVideoDecoder::NotifyResetDone, this));
510 return; 522 return;
511 } 523 }
512 524
513 if (!vda_) 525 if (!vda_.get())
514 return; 526 return;
515 527
516 DCHECK(ready_video_frames_.empty()); 528 DCHECK(ready_video_frames_.empty());
517 529
518 // This needs to happen after the Reset() on vda_ is done to ensure pictures 530 // This needs to happen after the Reset() on vda_ is done to ensure pictures
519 // delivered during the reset can find their time data. 531 // delivered during the reset can find their time data.
520 input_buffer_time_data_.clear(); 532 input_buffer_time_data_.clear();
521 533
522 if (!pending_reset_cb_.is_null()) 534 if (!pending_reset_cb_.is_null())
523 base::ResetAndReturn(&pending_reset_cb_).Run(); 535 base::ResetAndReturn(&pending_reset_cb_).Run();
524 536
525 if (!pending_read_cb_.is_null()) 537 if (!pending_read_cb_.is_null())
526 EnqueueFrameAndTriggerFrameDelivery(VideoFrame::CreateEmptyFrame()); 538 EnqueueFrameAndTriggerFrameDelivery(VideoFrame::CreateEmptyFrame());
527 } 539 }
528 540
529 void GpuVideoDecoder::NotifyError(media::VideoDecodeAccelerator::Error error) { 541 void GpuVideoDecoder::NotifyError(media::VideoDecodeAccelerator::Error error) {
530 if (!gvd_loop_proxy_->BelongsToCurrentThread()) { 542 if (!gvd_loop_proxy_->BelongsToCurrentThread()) {
531 gvd_loop_proxy_->PostTask(FROM_HERE, base::Bind( 543 gvd_loop_proxy_->PostTask(FROM_HERE, base::Bind(
532 &GpuVideoDecoder::NotifyError, this, error)); 544 &GpuVideoDecoder::NotifyError, this, error));
533 return; 545 return;
534 } 546 }
535 if (!vda_) 547 if (!vda_.get())
536 return; 548 return;
537 vda_ = NULL; 549 vda_loop_proxy_->DeleteSoon(FROM_HERE, vda_.release());
538 DLOG(ERROR) << "VDA Error: " << error; 550 DLOG(ERROR) << "VDA Error: " << error;
539 551
540 error_occured_ = true; 552 error_occured_ = true;
541 553
542 if (!pending_read_cb_.is_null()) { 554 if (!pending_read_cb_.is_null()) {
543 base::ResetAndReturn(&pending_read_cb_).Run(kDecodeError, NULL); 555 base::ResetAndReturn(&pending_read_cb_).Run(kDecodeError, NULL);
544 return; 556 return;
545 } 557 }
546 } 558 }
547 559
548 } // namespace media 560 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698