OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "media/filters/gpu_video_decoder.h" | 5 #include "media/filters/gpu_video_decoder.h" |
6 | 6 |
7 #include "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 Loading... |
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 vda_loop_proxy_->PostTask(FROM_HERE, base::Bind( | 110 vda_loop_proxy_->PostTask(FROM_HERE, base::Bind( |
111 &VideoDecodeAccelerator::Destroy, vda_)); | 111 &VideoDecodeAccelerator::Destroy, weak_vda_, base::Passed(&vda_))); |
112 vda_ = NULL; | |
113 closure.Run(); | 112 closure.Run(); |
114 } | 113 } |
115 | 114 |
116 void GpuVideoDecoder::Initialize(const scoped_refptr<DemuxerStream>& stream, | 115 void GpuVideoDecoder::Initialize(const scoped_refptr<DemuxerStream>& stream, |
117 const PipelineStatusCB& orig_status_cb, | 116 const PipelineStatusCB& orig_status_cb, |
118 const StatisticsCB& statistics_cb) { | 117 const StatisticsCB& statistics_cb) { |
119 if (!gvd_loop_proxy_->BelongsToCurrentThread()) { | 118 if (!gvd_loop_proxy_->BelongsToCurrentThread()) { |
120 gvd_loop_proxy_->PostTask(FROM_HERE, base::Bind( | 119 gvd_loop_proxy_->PostTask(FROM_HERE, base::Bind( |
121 &GpuVideoDecoder::Initialize, | 120 &GpuVideoDecoder::Initialize, |
122 this, stream, orig_status_cb, statistics_cb)); | 121 this, stream, orig_status_cb, statistics_cb)); |
(...skipping 11 matching lines...) Expand all Loading... |
134 | 133 |
135 const VideoDecoderConfig& config = stream->video_decoder_config(); | 134 const VideoDecoderConfig& config = stream->video_decoder_config(); |
136 // TODO(scherkus): this check should go in Pipeline prior to creating | 135 // TODO(scherkus): this check should go in Pipeline prior to creating |
137 // decoder objects. | 136 // decoder objects. |
138 if (!config.IsValidConfig()) { | 137 if (!config.IsValidConfig()) { |
139 DLOG(ERROR) << "Invalid video stream - " << config.AsHumanReadableString(); | 138 DLOG(ERROR) << "Invalid video stream - " << config.AsHumanReadableString(); |
140 status_cb.Run(PIPELINE_ERROR_DECODE); | 139 status_cb.Run(PIPELINE_ERROR_DECODE); |
141 return; | 140 return; |
142 } | 141 } |
143 | 142 |
144 vda_ = factories_->CreateVideoDecodeAccelerator(config.profile(), this); | 143 VideoDecodeAccelerator* vda = |
145 if (!vda_) { | 144 factories_->CreateVideoDecodeAccelerator(config.profile(), this); |
| 145 if (!vda) { |
146 status_cb.Run(DECODER_ERROR_NOT_SUPPORTED); | 146 status_cb.Run(DECODER_ERROR_NOT_SUPPORTED); |
147 return; | 147 return; |
148 } | 148 } |
149 | 149 |
150 demuxer_stream_ = stream; | 150 demuxer_stream_ = stream; |
151 statistics_cb_ = statistics_cb; | 151 statistics_cb_ = statistics_cb; |
152 | 152 |
153 demuxer_stream_->EnableBitstreamConverter(); | 153 demuxer_stream_->EnableBitstreamConverter(); |
154 | 154 |
155 natural_size_ = config.natural_size(); | 155 natural_size_ = config.natural_size(); |
156 config_frame_duration_ = GetFrameDuration(config); | 156 config_frame_duration_ = GetFrameDuration(config); |
157 | 157 |
158 DVLOG(1) << "GpuVideoDecoder::Initialize() succeeded."; | 158 DVLOG(1) << "GpuVideoDecoder::Initialize() succeeded."; |
159 status_cb.Run(PIPELINE_OK); | 159 vda_loop_proxy_->PostTaskAndReply( |
| 160 FROM_HERE, |
| 161 base::Bind(&GpuVideoDecoder::SetVDA, this, vda), |
| 162 base::Bind(status_cb, PIPELINE_OK)); |
| 163 } |
| 164 |
| 165 void GpuVideoDecoder::SetVDA(VideoDecodeAccelerator* vda) { |
| 166 DCHECK(vda_loop_proxy_->BelongsToCurrentThread()); |
| 167 vda_.reset(vda); |
| 168 weak_vda_ = vda->AsWeakPtr(); |
160 } | 169 } |
161 | 170 |
162 void GpuVideoDecoder::Read(const ReadCB& read_cb) { | 171 void GpuVideoDecoder::Read(const ReadCB& read_cb) { |
163 if (!gvd_loop_proxy_->BelongsToCurrentThread()) { | 172 if (!gvd_loop_proxy_->BelongsToCurrentThread()) { |
164 gvd_loop_proxy_->PostTask(FROM_HERE, base::Bind( | 173 gvd_loop_proxy_->PostTask(FROM_HERE, base::Bind( |
165 &GpuVideoDecoder::Read, this, read_cb)); | 174 &GpuVideoDecoder::Read, this, read_cb)); |
166 return; | 175 return; |
167 } | 176 } |
168 | 177 |
169 if (error_occured_) { | 178 if (error_occured_) { |
170 read_cb.Run(kDecodeError, NULL); | 179 read_cb.Run(kDecodeError, NULL); |
171 return; | 180 return; |
172 } | 181 } |
173 | 182 |
174 if (!vda_) { | 183 if (!vda_.get()) { |
175 read_cb.Run(kOk, VideoFrame::CreateEmptyFrame()); | 184 read_cb.Run(kOk, VideoFrame::CreateEmptyFrame()); |
176 return; | 185 return; |
177 } | 186 } |
178 | 187 |
179 DCHECK(pending_reset_cb_.is_null()); | 188 DCHECK(pending_reset_cb_.is_null()); |
180 DCHECK(pending_read_cb_.is_null()); | 189 DCHECK(pending_read_cb_.is_null()); |
181 pending_read_cb_ = read_cb; | 190 pending_read_cb_ = read_cb; |
182 | 191 |
183 if (!ready_video_frames_.empty()) { | 192 if (!ready_video_frames_.empty()) { |
184 EnqueueFrameAndTriggerFrameDelivery(NULL); | 193 EnqueueFrameAndTriggerFrameDelivery(NULL); |
(...skipping 26 matching lines...) Expand all Loading... |
211 if (!buffer) { | 220 if (!buffer) { |
212 if (pending_read_cb_.is_null()) | 221 if (pending_read_cb_.is_null()) |
213 return; | 222 return; |
214 | 223 |
215 gvd_loop_proxy_->PostTask(FROM_HERE, base::Bind( | 224 gvd_loop_proxy_->PostTask(FROM_HERE, base::Bind( |
216 pending_read_cb_, kOk, scoped_refptr<VideoFrame>())); | 225 pending_read_cb_, kOk, scoped_refptr<VideoFrame>())); |
217 pending_read_cb_.Reset(); | 226 pending_read_cb_.Reset(); |
218 return; | 227 return; |
219 } | 228 } |
220 | 229 |
221 if (!vda_) { | 230 if (!vda_.get()) { |
222 EnqueueFrameAndTriggerFrameDelivery(VideoFrame::CreateEmptyFrame()); | 231 EnqueueFrameAndTriggerFrameDelivery(VideoFrame::CreateEmptyFrame()); |
223 return; | 232 return; |
224 } | 233 } |
225 | 234 |
226 if (buffer->IsEndOfStream()) { | 235 if (buffer->IsEndOfStream()) { |
227 if (state_ == kNormal) { | 236 if (state_ == kNormal) { |
228 state_ = kDrainingDecoder; | 237 state_ = kDrainingDecoder; |
229 vda_loop_proxy_->PostTask(FROM_HERE, base::Bind( | 238 vda_loop_proxy_->PostTask(FROM_HERE, base::Bind( |
230 &VideoDecodeAccelerator::Flush, vda_)); | 239 &VideoDecodeAccelerator::Flush, weak_vda_)); |
231 } | 240 } |
232 return; | 241 return; |
233 } | 242 } |
234 | 243 |
235 size_t size = buffer->GetDataSize(); | 244 size_t size = buffer->GetDataSize(); |
236 SHMBuffer* shm_buffer = GetSHM(size); | 245 SHMBuffer* shm_buffer = GetSHM(size); |
237 memcpy(shm_buffer->shm->memory(), buffer->GetData(), size); | 246 memcpy(shm_buffer->shm->memory(), buffer->GetData(), size); |
238 BitstreamBuffer bitstream_buffer( | 247 BitstreamBuffer bitstream_buffer( |
239 next_bitstream_buffer_id_++, shm_buffer->shm->handle(), size); | 248 next_bitstream_buffer_id_++, shm_buffer->shm->handle(), size); |
240 bool inserted = bitstream_buffers_in_decoder_.insert(std::make_pair( | 249 bool inserted = bitstream_buffers_in_decoder_.insert(std::make_pair( |
241 bitstream_buffer.id(), BufferPair(shm_buffer, buffer))).second; | 250 bitstream_buffer.id(), BufferPair(shm_buffer, buffer))).second; |
242 DCHECK(inserted); | 251 DCHECK(inserted); |
243 RecordBufferTimeData(bitstream_buffer, *buffer); | 252 RecordBufferTimeData(bitstream_buffer, *buffer); |
244 | 253 |
245 vda_loop_proxy_->PostTask(FROM_HERE, base::Bind( | 254 vda_loop_proxy_->PostTask(FROM_HERE, base::Bind( |
246 &VideoDecodeAccelerator::Decode, vda_, bitstream_buffer)); | 255 &VideoDecodeAccelerator::Decode, weak_vda_, bitstream_buffer)); |
247 } | 256 } |
248 | 257 |
249 void GpuVideoDecoder::RecordBufferTimeData( | 258 void GpuVideoDecoder::RecordBufferTimeData( |
250 const BitstreamBuffer& bitstream_buffer, const Buffer& buffer) { | 259 const BitstreamBuffer& bitstream_buffer, const Buffer& buffer) { |
251 base::TimeDelta duration = buffer.GetDuration(); | 260 base::TimeDelta duration = buffer.GetDuration(); |
252 if (duration == base::TimeDelta()) | 261 if (duration == base::TimeDelta()) |
253 duration = config_frame_duration_; | 262 duration = config_frame_duration_; |
254 input_buffer_time_data_.push_front(BufferTimeData( | 263 input_buffer_time_data_.push_front(BufferTimeData( |
255 bitstream_buffer.id(), buffer.GetTimestamp(), duration)); | 264 bitstream_buffer.id(), buffer.GetTimestamp(), duration)); |
256 // Why this value? Because why not. avformat.h:MAX_REORDER_DELAY is 16, but | 265 // 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 Loading... |
312 } | 321 } |
313 | 322 |
314 std::vector<uint32> texture_ids; | 323 std::vector<uint32> texture_ids; |
315 decoder_texture_target_ = texture_target; | 324 decoder_texture_target_ = texture_target; |
316 if (!factories_->CreateTextures( | 325 if (!factories_->CreateTextures( |
317 count, size, &texture_ids, decoder_texture_target_)) { | 326 count, size, &texture_ids, decoder_texture_target_)) { |
318 NotifyError(VideoDecodeAccelerator::PLATFORM_FAILURE); | 327 NotifyError(VideoDecodeAccelerator::PLATFORM_FAILURE); |
319 return; | 328 return; |
320 } | 329 } |
321 | 330 |
322 if (!vda_) | 331 if (!vda_.get()) |
323 return; | 332 return; |
324 | 333 |
325 std::vector<PictureBuffer> picture_buffers; | 334 std::vector<PictureBuffer> picture_buffers; |
326 for (size_t i = 0; i < texture_ids.size(); ++i) { | 335 for (size_t i = 0; i < texture_ids.size(); ++i) { |
327 picture_buffers.push_back(PictureBuffer( | 336 picture_buffers.push_back(PictureBuffer( |
328 next_picture_buffer_id_++, size, texture_ids[i])); | 337 next_picture_buffer_id_++, size, texture_ids[i])); |
329 bool inserted = picture_buffers_in_decoder_.insert(std::make_pair( | 338 bool inserted = picture_buffers_in_decoder_.insert(std::make_pair( |
330 picture_buffers.back().id(), picture_buffers.back())).second; | 339 picture_buffers.back().id(), picture_buffers.back())).second; |
331 DCHECK(inserted); | 340 DCHECK(inserted); |
332 } | 341 } |
333 vda_loop_proxy_->PostTask(FROM_HERE, base::Bind( | 342 vda_loop_proxy_->PostTask(FROM_HERE, base::Bind( |
334 &VideoDecodeAccelerator::AssignPictureBuffers, vda_, picture_buffers)); | 343 &VideoDecodeAccelerator::AssignPictureBuffers, weak_vda_, |
| 344 picture_buffers)); |
335 } | 345 } |
336 | 346 |
337 void GpuVideoDecoder::DismissPictureBuffer(int32 id) { | 347 void GpuVideoDecoder::DismissPictureBuffer(int32 id) { |
338 if (!gvd_loop_proxy_->BelongsToCurrentThread()) { | 348 if (!gvd_loop_proxy_->BelongsToCurrentThread()) { |
339 gvd_loop_proxy_->PostTask(FROM_HERE, base::Bind( | 349 gvd_loop_proxy_->PostTask(FROM_HERE, base::Bind( |
340 &GpuVideoDecoder::DismissPictureBuffer, this, id)); | 350 &GpuVideoDecoder::DismissPictureBuffer, this, id)); |
341 return; | 351 return; |
342 } | 352 } |
343 std::map<int32, PictureBuffer>::iterator it = | 353 std::map<int32, PictureBuffer>::iterator it = |
344 picture_buffers_in_decoder_.find(id); | 354 picture_buffers_in_decoder_.find(id); |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
402 pending_read_cb_.Reset(); | 412 pending_read_cb_.Reset(); |
403 ready_video_frames_.pop_front(); | 413 ready_video_frames_.pop_front(); |
404 } | 414 } |
405 | 415 |
406 void GpuVideoDecoder::ReusePictureBuffer(int64 picture_buffer_id) { | 416 void GpuVideoDecoder::ReusePictureBuffer(int64 picture_buffer_id) { |
407 if (!gvd_loop_proxy_->BelongsToCurrentThread()) { | 417 if (!gvd_loop_proxy_->BelongsToCurrentThread()) { |
408 gvd_loop_proxy_->PostTask(FROM_HERE, base::Bind( | 418 gvd_loop_proxy_->PostTask(FROM_HERE, base::Bind( |
409 &GpuVideoDecoder::ReusePictureBuffer, this, picture_buffer_id)); | 419 &GpuVideoDecoder::ReusePictureBuffer, this, picture_buffer_id)); |
410 return; | 420 return; |
411 } | 421 } |
412 if (!vda_) | 422 if (!vda_.get()) |
413 return; | 423 return; |
414 vda_loop_proxy_->PostTask(FROM_HERE, base::Bind( | 424 vda_loop_proxy_->PostTask(FROM_HERE, base::Bind( |
415 &VideoDecodeAccelerator::ReusePictureBuffer, vda_, picture_buffer_id)); | 425 &VideoDecodeAccelerator::ReusePictureBuffer, weak_vda_, |
| 426 picture_buffer_id)); |
416 } | 427 } |
417 | 428 |
418 GpuVideoDecoder::SHMBuffer* GpuVideoDecoder::GetSHM(size_t min_size) { | 429 GpuVideoDecoder::SHMBuffer* GpuVideoDecoder::GetSHM(size_t min_size) { |
419 DCHECK(gvd_loop_proxy_->BelongsToCurrentThread()); | 430 DCHECK(gvd_loop_proxy_->BelongsToCurrentThread()); |
420 if (available_shm_segments_.empty() || | 431 if (available_shm_segments_.empty() || |
421 available_shm_segments_.back()->size < min_size) { | 432 available_shm_segments_.back()->size < min_size) { |
422 size_t size_to_allocate = std::max(min_size, kSharedMemorySegmentBytes); | 433 size_t size_to_allocate = std::max(min_size, kSharedMemorySegmentBytes); |
423 base::SharedMemory* shm = factories_->CreateSharedMemory(size_to_allocate); | 434 base::SharedMemory* shm = factories_->CreateSharedMemory(size_to_allocate); |
424 DCHECK(shm); | 435 DCHECK(shm); |
425 return new SHMBuffer(shm, size_to_allocate); | 436 return new SHMBuffer(shm, size_to_allocate); |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
460 | 471 |
461 if (!pending_read_cb_.is_null() && pending_reset_cb_.is_null() && | 472 if (!pending_read_cb_.is_null() && pending_reset_cb_.is_null() && |
462 state_ != kDrainingDecoder && | 473 state_ != kDrainingDecoder && |
463 bitstream_buffers_in_decoder_.empty()) { | 474 bitstream_buffers_in_decoder_.empty()) { |
464 DCHECK(ready_video_frames_.empty()); | 475 DCHECK(ready_video_frames_.empty()); |
465 EnsureDemuxOrDecode(); | 476 EnsureDemuxOrDecode(); |
466 } | 477 } |
467 } | 478 } |
468 | 479 |
469 GpuVideoDecoder::~GpuVideoDecoder() { | 480 GpuVideoDecoder::~GpuVideoDecoder() { |
470 DCHECK(!vda_); // Stop should have been already called. | 481 DCHECK(!vda_.get()); // Stop should have been already called. |
471 DCHECK(pending_read_cb_.is_null()); | 482 DCHECK(pending_read_cb_.is_null()); |
472 for (size_t i = 0; i < available_shm_segments_.size(); ++i) { | 483 for (size_t i = 0; i < available_shm_segments_.size(); ++i) { |
473 available_shm_segments_[i]->shm->Close(); | 484 available_shm_segments_[i]->shm->Close(); |
474 delete available_shm_segments_[i]; | 485 delete available_shm_segments_[i]; |
475 } | 486 } |
476 available_shm_segments_.clear(); | 487 available_shm_segments_.clear(); |
477 for (std::map<int32, BufferPair>::iterator it = | 488 for (std::map<int32, BufferPair>::iterator it = |
478 bitstream_buffers_in_decoder_.begin(); | 489 bitstream_buffers_in_decoder_.begin(); |
479 it != bitstream_buffers_in_decoder_.end(); ++it) { | 490 it != bitstream_buffers_in_decoder_.end(); ++it) { |
480 it->second.shm_buffer->shm->Close(); | 491 it->second.shm_buffer->shm->Close(); |
(...skipping 22 matching lines...) Expand all Loading... |
503 EnqueueFrameAndTriggerFrameDelivery(VideoFrame::CreateEmptyFrame()); | 514 EnqueueFrameAndTriggerFrameDelivery(VideoFrame::CreateEmptyFrame()); |
504 } | 515 } |
505 | 516 |
506 void GpuVideoDecoder::NotifyResetDone() { | 517 void GpuVideoDecoder::NotifyResetDone() { |
507 if (!gvd_loop_proxy_->BelongsToCurrentThread()) { | 518 if (!gvd_loop_proxy_->BelongsToCurrentThread()) { |
508 gvd_loop_proxy_->PostTask(FROM_HERE, base::Bind( | 519 gvd_loop_proxy_->PostTask(FROM_HERE, base::Bind( |
509 &GpuVideoDecoder::NotifyResetDone, this)); | 520 &GpuVideoDecoder::NotifyResetDone, this)); |
510 return; | 521 return; |
511 } | 522 } |
512 | 523 |
513 if (!vda_) | 524 if (!vda_.get()) |
514 return; | 525 return; |
515 | 526 |
516 DCHECK(ready_video_frames_.empty()); | 527 DCHECK(ready_video_frames_.empty()); |
517 | 528 |
518 // This needs to happen after the Reset() on vda_ is done to ensure pictures | 529 // This needs to happen after the Reset() on vda_ is done to ensure pictures |
519 // delivered during the reset can find their time data. | 530 // delivered during the reset can find their time data. |
520 input_buffer_time_data_.clear(); | 531 input_buffer_time_data_.clear(); |
521 | 532 |
522 if (!pending_reset_cb_.is_null()) | 533 if (!pending_reset_cb_.is_null()) |
523 base::ResetAndReturn(&pending_reset_cb_).Run(); | 534 base::ResetAndReturn(&pending_reset_cb_).Run(); |
524 | 535 |
525 if (!pending_read_cb_.is_null()) | 536 if (!pending_read_cb_.is_null()) |
526 EnqueueFrameAndTriggerFrameDelivery(VideoFrame::CreateEmptyFrame()); | 537 EnqueueFrameAndTriggerFrameDelivery(VideoFrame::CreateEmptyFrame()); |
527 } | 538 } |
528 | 539 |
529 void GpuVideoDecoder::NotifyError(media::VideoDecodeAccelerator::Error error) { | 540 void GpuVideoDecoder::NotifyError(media::VideoDecodeAccelerator::Error error) { |
530 if (!gvd_loop_proxy_->BelongsToCurrentThread()) { | 541 if (!gvd_loop_proxy_->BelongsToCurrentThread()) { |
531 gvd_loop_proxy_->PostTask(FROM_HERE, base::Bind( | 542 gvd_loop_proxy_->PostTask(FROM_HERE, base::Bind( |
532 &GpuVideoDecoder::NotifyError, this, error)); | 543 &GpuVideoDecoder::NotifyError, this, error)); |
533 return; | 544 return; |
534 } | 545 } |
535 if (!vda_) | 546 if (!vda_.get()) |
536 return; | 547 return; |
537 vda_ = NULL; | 548 vda_loop_proxy_->DeleteSoon(FROM_HERE, vda_.release()); |
538 DLOG(ERROR) << "VDA Error: " << error; | 549 DLOG(ERROR) << "VDA Error: " << error; |
539 | 550 |
540 error_occured_ = true; | 551 error_occured_ = true; |
541 | 552 |
542 if (!pending_read_cb_.is_null()) { | 553 if (!pending_read_cb_.is_null()) { |
543 base::ResetAndReturn(&pending_read_cb_).Run(kDecodeError, NULL); | 554 base::ResetAndReturn(&pending_read_cb_).Run(kDecodeError, NULL); |
544 return; | 555 return; |
545 } | 556 } |
546 } | 557 } |
547 | 558 |
548 } // namespace media | 559 } // namespace media |
OLD | NEW |