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 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_)); |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 |
OLD | NEW |