| 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 <algorithm> | 7 #include <algorithm> |
| 8 | 8 |
| 9 #include "base/bind.h" | 9 #include "base/bind.h" |
| 10 #include "base/callback_helpers.h" | 10 #include "base/callback_helpers.h" |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 73 | 73 |
| 74 void GpuVideoDecoder::Reset(const base::Closure& closure) { | 74 void GpuVideoDecoder::Reset(const base::Closure& closure) { |
| 75 DVLOG(3) << "Reset()"; | 75 DVLOG(3) << "Reset()"; |
| 76 DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent(); | 76 DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent(); |
| 77 | 77 |
| 78 if (state_ == kDrainingDecoder) { | 78 if (state_ == kDrainingDecoder) { |
| 79 base::MessageLoop::current()->PostTask( | 79 base::MessageLoop::current()->PostTask( |
| 80 FROM_HERE, | 80 FROM_HERE, |
| 81 base::Bind( | 81 base::Bind( |
| 82 &GpuVideoDecoder::Reset, weak_factory_.GetWeakPtr(), closure)); | 82 &GpuVideoDecoder::Reset, weak_factory_.GetWeakPtr(), closure)); |
| 83 // NOTE: if we're deferring Reset() until a Flush() completes, return | |
| 84 // queued pictures to the VDA so they can be used to finish that Flush(). | |
| 85 if (pending_decode_cb_.is_null()) | |
| 86 ready_video_frames_.clear(); | |
| 87 return; | 83 return; |
| 88 } | 84 } |
| 89 | 85 |
| 90 // Throw away any already-decoded, not-yet-delivered frames. | |
| 91 ready_video_frames_.clear(); | |
| 92 | |
| 93 if (!vda_) { | 86 if (!vda_) { |
| 94 base::MessageLoop::current()->PostTask(FROM_HERE, closure); | 87 base::MessageLoop::current()->PostTask(FROM_HERE, closure); |
| 95 return; | 88 return; |
| 96 } | 89 } |
| 97 | 90 |
| 98 if (!pending_decode_cb_.is_null()) | 91 while (!pending_decode_callbacks_.empty()) { |
| 99 EnqueueFrameAndTriggerFrameDelivery(VideoFrame::CreateEOSFrame()); | 92 DeliverFrame(VideoFrame::CreateEOSFrame()); |
| 93 } |
| 100 | 94 |
| 101 DCHECK(pending_reset_cb_.is_null()); | 95 DCHECK(pending_reset_cb_.is_null()); |
| 102 pending_reset_cb_ = BindToCurrentLoop(closure); | 96 pending_reset_cb_ = BindToCurrentLoop(closure); |
| 103 | 97 |
| 104 vda_->Reset(); | 98 vda_->Reset(); |
| 105 } | 99 } |
| 106 | 100 |
| 107 void GpuVideoDecoder::Stop() { | 101 void GpuVideoDecoder::Stop() { |
| 108 DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent(); | 102 DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent(); |
| 109 if (vda_) | 103 if (vda_) |
| 110 DestroyVDA(); | 104 DestroyVDA(); |
| 111 if (!pending_decode_cb_.is_null()) | 105 while (!pending_decode_callbacks_.empty()) { |
| 112 EnqueueFrameAndTriggerFrameDelivery(VideoFrame::CreateEOSFrame()); | 106 DeliverFrame(VideoFrame::CreateEOSFrame()); |
| 107 } |
| 113 if (!pending_reset_cb_.is_null()) | 108 if (!pending_reset_cb_.is_null()) |
| 114 base::ResetAndReturn(&pending_reset_cb_).Run(); | 109 base::ResetAndReturn(&pending_reset_cb_).Run(); |
| 115 } | 110 } |
| 116 | 111 |
| 117 static bool IsCodedSizeSupported(const gfx::Size& coded_size) { | 112 static bool IsCodedSizeSupported(const gfx::Size& coded_size) { |
| 118 // Only non-Windows, Ivy Bridge+ platforms can support more than 1920x1080. | 113 // Only non-Windows, Ivy Bridge+ platforms can support more than 1920x1080. |
| 119 // We test against 1088 to account for 16x16 macroblocks. | 114 // We test against 1088 to account for 16x16 macroblocks. |
| 120 if (coded_size.width() <= 1920 && coded_size.height() <= 1088) | 115 if (coded_size.width() <= 1920 && coded_size.height() <= 1088) |
| 121 return true; | 116 return true; |
| 122 | 117 |
| (...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 215 ++it) { | 210 ++it) { |
| 216 assigned_picture_buffers_.erase(it->first); | 211 assigned_picture_buffers_.erase(it->first); |
| 217 } | 212 } |
| 218 DestroyPictureBuffers(&assigned_picture_buffers_); | 213 DestroyPictureBuffers(&assigned_picture_buffers_); |
| 219 } | 214 } |
| 220 | 215 |
| 221 void GpuVideoDecoder::Decode(const scoped_refptr<DecoderBuffer>& buffer, | 216 void GpuVideoDecoder::Decode(const scoped_refptr<DecoderBuffer>& buffer, |
| 222 const DecodeCB& decode_cb) { | 217 const DecodeCB& decode_cb) { |
| 223 DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent(); | 218 DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent(); |
| 224 DCHECK(pending_reset_cb_.is_null()); | 219 DCHECK(pending_reset_cb_.is_null()); |
| 225 DCHECK(pending_decode_cb_.is_null()); | |
| 226 | |
| 227 pending_decode_cb_ = BindToCurrentLoop(decode_cb); | |
| 228 | 220 |
| 229 if (state_ == kError || !vda_) { | 221 if (state_ == kError || !vda_) { |
| 230 base::ResetAndReturn(&pending_decode_cb_).Run(kDecodeError, NULL); | 222 decode_cb.Run(kDecodeError, NULL); |
| 231 return; | 223 return; |
| 232 } | 224 } |
| 233 | 225 |
| 234 switch (state_) { | 226 switch (state_) { |
| 235 case kDecoderDrained: | 227 case kDecoderDrained: |
| 236 if (!ready_video_frames_.empty()) { | |
| 237 EnqueueFrameAndTriggerFrameDelivery(NULL); | |
| 238 return; | |
| 239 } | |
| 240 state_ = kNormal; | 228 state_ = kNormal; |
| 241 // Fall-through. | 229 // Fall-through. |
| 242 case kNormal: | 230 case kNormal: |
| 243 break; | 231 break; |
| 244 case kDrainingDecoder: | 232 case kDrainingDecoder: |
| 245 DCHECK(buffer->end_of_stream()); | 233 DCHECK(buffer->end_of_stream()); |
| 246 // Do nothing. Will be satisfied either by a PictureReady or | 234 // Do nothing. Will be satisfied either by a PictureReady or |
| 247 // NotifyFlushDone below. | 235 // NotifyFlushDone below. |
| 248 return; | 236 return; |
| 249 case kError: | 237 case kError: |
| 250 NOTREACHED(); | 238 NOTREACHED(); |
| 251 return; | 239 return; |
| 252 } | 240 } |
| 253 | 241 |
| 254 if (buffer->end_of_stream()) { | 242 if (buffer->end_of_stream()) { |
| 255 if (state_ == kNormal) { | 243 if (state_ == kNormal) { |
| 256 state_ = kDrainingDecoder; | 244 state_ = kDrainingDecoder; |
| 245 pending_decode_callbacks_.push_back(BindToCurrentLoop(decode_cb)); |
| 246 DCHECK_LE(static_cast<int>(pending_decode_callbacks_.size()), |
| 247 kMaxInFlightDecodes); |
| 257 vda_->Flush(); | 248 vda_->Flush(); |
| 258 // If we have ready frames, go ahead and process them to ensure that the | |
| 259 // Flush operation does not block in the VDA due to lack of picture | |
| 260 // buffers. | |
| 261 if (!ready_video_frames_.empty()) | |
| 262 EnqueueFrameAndTriggerFrameDelivery(NULL); | |
| 263 } | 249 } |
| 264 return; | 250 return; |
| 265 } | 251 } |
| 266 | 252 |
| 267 size_t size = buffer->data_size(); | 253 size_t size = buffer->data_size(); |
| 268 SHMBuffer* shm_buffer = GetSHM(size); | 254 SHMBuffer* shm_buffer = GetSHM(size); |
| 269 if (!shm_buffer) { | 255 if (!shm_buffer) { |
| 270 base::ResetAndReturn(&pending_decode_cb_).Run(kDecodeError, NULL); | 256 decode_cb.Run(kDecodeError, NULL); |
| 271 return; | 257 return; |
| 272 } | 258 } |
| 273 | 259 |
| 260 pending_decode_callbacks_.push_back(BindToCurrentLoop(decode_cb)); |
| 261 DCHECK_LE(static_cast<int>(pending_decode_callbacks_.size()), |
| 262 kMaxInFlightDecodes); |
| 263 |
| 274 memcpy(shm_buffer->shm->memory(), buffer->data(), size); | 264 memcpy(shm_buffer->shm->memory(), buffer->data(), size); |
| 275 BitstreamBuffer bitstream_buffer( | 265 BitstreamBuffer bitstream_buffer( |
| 276 next_bitstream_buffer_id_, shm_buffer->shm->handle(), size); | 266 next_bitstream_buffer_id_, shm_buffer->shm->handle(), size); |
| 277 // Mask against 30 bits, to avoid (undefined) wraparound on signed integer. | 267 // Mask against 30 bits, to avoid (undefined) wraparound on signed integer. |
| 278 next_bitstream_buffer_id_ = (next_bitstream_buffer_id_ + 1) & 0x3FFFFFFF; | 268 next_bitstream_buffer_id_ = (next_bitstream_buffer_id_ + 1) & 0x3FFFFFFF; |
| 279 bool inserted = bitstream_buffers_in_decoder_.insert(std::make_pair( | 269 bool inserted = bitstream_buffers_in_decoder_.insert(std::make_pair( |
| 280 bitstream_buffer.id(), BufferPair(shm_buffer, buffer))).second; | 270 bitstream_buffer.id(), BufferPair(shm_buffer, buffer))).second; |
| 281 DCHECK(inserted); | 271 DCHECK(inserted); |
| 282 RecordBufferData(bitstream_buffer, *buffer.get()); | 272 RecordBufferData(bitstream_buffer, *buffer.get()); |
| 283 | 273 |
| 284 vda_->Decode(bitstream_buffer); | 274 vda_->Decode(bitstream_buffer); |
| 285 | |
| 286 if (!ready_video_frames_.empty()) { | |
| 287 EnqueueFrameAndTriggerFrameDelivery(NULL); | |
| 288 return; | |
| 289 } | |
| 290 | |
| 291 if (CanMoreDecodeWorkBeDone()) | |
| 292 base::ResetAndReturn(&pending_decode_cb_).Run(kNotEnoughData, NULL); | |
| 293 } | |
| 294 | |
| 295 bool GpuVideoDecoder::CanMoreDecodeWorkBeDone() { | |
| 296 return bitstream_buffers_in_decoder_.size() < kMaxInFlightDecodes; | |
| 297 } | 275 } |
| 298 | 276 |
| 299 void GpuVideoDecoder::RecordBufferData(const BitstreamBuffer& bitstream_buffer, | 277 void GpuVideoDecoder::RecordBufferData(const BitstreamBuffer& bitstream_buffer, |
| 300 const DecoderBuffer& buffer) { | 278 const DecoderBuffer& buffer) { |
| 301 input_buffer_data_.push_front(BufferData(bitstream_buffer.id(), | 279 input_buffer_data_.push_front(BufferData(bitstream_buffer.id(), |
| 302 buffer.timestamp(), | 280 buffer.timestamp(), |
| 303 config_.visible_rect(), | 281 config_.visible_rect(), |
| 304 config_.natural_size())); | 282 config_.natural_size())); |
| 305 // Why this value? Because why not. avformat.h:MAX_REORDER_DELAY is 16, but | 283 // Why this value? Because why not. avformat.h:MAX_REORDER_DELAY is 16, but |
| 306 // that's too small for some pathological B-frame test videos. The cost of | 284 // that's too small for some pathological B-frame test videos. The cost of |
| (...skipping 23 matching lines...) Expand all Loading... |
| 330 | 308 |
| 331 bool GpuVideoDecoder::NeedsBitstreamConversion() const { | 309 bool GpuVideoDecoder::NeedsBitstreamConversion() const { |
| 332 DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent(); | 310 DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent(); |
| 333 return needs_bitstream_conversion_; | 311 return needs_bitstream_conversion_; |
| 334 } | 312 } |
| 335 | 313 |
| 336 bool GpuVideoDecoder::CanReadWithoutStalling() const { | 314 bool GpuVideoDecoder::CanReadWithoutStalling() const { |
| 337 DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent(); | 315 DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent(); |
| 338 return | 316 return |
| 339 next_picture_buffer_id_ == 0 || // Decode() will ProvidePictureBuffers(). | 317 next_picture_buffer_id_ == 0 || // Decode() will ProvidePictureBuffers(). |
| 340 available_pictures_ > 0 || !ready_video_frames_.empty(); | 318 available_pictures_ > 0; |
| 319 } |
| 320 |
| 321 int GpuVideoDecoder::GetMaxDecodeRequests() const { |
| 322 return kMaxInFlightDecodes; |
| 341 } | 323 } |
| 342 | 324 |
| 343 void GpuVideoDecoder::ProvidePictureBuffers(uint32 count, | 325 void GpuVideoDecoder::ProvidePictureBuffers(uint32 count, |
| 344 const gfx::Size& size, | 326 const gfx::Size& size, |
| 345 uint32 texture_target) { | 327 uint32 texture_target) { |
| 346 DVLOG(3) << "ProvidePictureBuffers(" << count << ", " | 328 DVLOG(3) << "ProvidePictureBuffers(" << count << ", " |
| 347 << size.width() << "x" << size.height() << ")"; | 329 << size.width() << "x" << size.height() << ")"; |
| 348 DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent(); | 330 DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent(); |
| 349 | 331 |
| 350 std::vector<uint32> texture_ids; | 332 std::vector<uint32> texture_ids; |
| (...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 463 timestamp, | 445 timestamp, |
| 464 base::Bind(&ReadPixelsSync, factories_, pb.texture_id(), visible_rect))); | 446 base::Bind(&ReadPixelsSync, factories_, pb.texture_id(), visible_rect))); |
| 465 CHECK_GT(available_pictures_, 0); | 447 CHECK_GT(available_pictures_, 0); |
| 466 --available_pictures_; | 448 --available_pictures_; |
| 467 bool inserted = | 449 bool inserted = |
| 468 picture_buffers_at_display_.insert(std::make_pair( | 450 picture_buffers_at_display_.insert(std::make_pair( |
| 469 picture.picture_buffer_id(), | 451 picture.picture_buffer_id(), |
| 470 pb.texture_id())).second; | 452 pb.texture_id())).second; |
| 471 DCHECK(inserted); | 453 DCHECK(inserted); |
| 472 | 454 |
| 473 EnqueueFrameAndTriggerFrameDelivery(frame); | 455 DeliverFrame(frame); |
| 474 } | 456 } |
| 475 | 457 |
| 476 void GpuVideoDecoder::EnqueueFrameAndTriggerFrameDelivery( | 458 void GpuVideoDecoder::DeliverFrame( |
| 477 const scoped_refptr<VideoFrame>& frame) { | 459 const scoped_refptr<VideoFrame>& frame) { |
| 478 DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent(); | 460 DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent(); |
| 479 | 461 |
| 480 // During a pending vda->Reset(), we don't accumulate frames. Drop it on the | 462 // During a pending vda->Reset(), we don't accumulate frames. Drop it on the |
| 481 // floor and return. | 463 // floor and return. |
| 482 if (!pending_reset_cb_.is_null()) | 464 if (!pending_reset_cb_.is_null()) |
| 483 return; | 465 return; |
| 484 | 466 |
| 485 if (frame.get()) | 467 DCHECK(!pending_decode_callbacks_.empty()); |
| 486 ready_video_frames_.push_back(frame); | |
| 487 else | |
| 488 DCHECK(!ready_video_frames_.empty()); | |
| 489 | 468 |
| 490 if (pending_decode_cb_.is_null()) | 469 DecodeCB decode_cb = pending_decode_callbacks_.front(); |
| 491 return; | 470 pending_decode_callbacks_.pop_front(); |
| 492 | 471 |
| 493 base::ResetAndReturn(&pending_decode_cb_) | 472 decode_cb.Run(kOk, frame); |
| 494 .Run(kOk, ready_video_frames_.front()); | |
| 495 ready_video_frames_.pop_front(); | |
| 496 } | 473 } |
| 497 | 474 |
| 498 // static | 475 // static |
| 499 void GpuVideoDecoder::ReleaseMailbox( | 476 void GpuVideoDecoder::ReleaseMailbox( |
| 500 base::WeakPtr<GpuVideoDecoder> decoder, | 477 base::WeakPtr<GpuVideoDecoder> decoder, |
| 501 const scoped_refptr<media::GpuVideoAcceleratorFactories>& factories, | 478 const scoped_refptr<media::GpuVideoAcceleratorFactories>& factories, |
| 502 int64 picture_buffer_id, | 479 int64 picture_buffer_id, |
| 503 uint32 texture_id, | 480 uint32 texture_id, |
| 504 scoped_ptr<gpu::MailboxHolder> mailbox_holder) { | 481 scoped_ptr<gpu::MailboxHolder> mailbox_holder) { |
| 505 DCHECK(factories->GetTaskRunner()->BelongsToCurrentThread()); | 482 DCHECK(factories->GetTaskRunner()->BelongsToCurrentThread()); |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 566 std::map<int32, BufferPair>::iterator it = | 543 std::map<int32, BufferPair>::iterator it = |
| 567 bitstream_buffers_in_decoder_.find(id); | 544 bitstream_buffers_in_decoder_.find(id); |
| 568 if (it == bitstream_buffers_in_decoder_.end()) { | 545 if (it == bitstream_buffers_in_decoder_.end()) { |
| 569 NotifyError(VideoDecodeAccelerator::PLATFORM_FAILURE); | 546 NotifyError(VideoDecodeAccelerator::PLATFORM_FAILURE); |
| 570 NOTREACHED() << "Missing bitstream buffer: " << id; | 547 NOTREACHED() << "Missing bitstream buffer: " << id; |
| 571 return; | 548 return; |
| 572 } | 549 } |
| 573 | 550 |
| 574 PutSHM(it->second.shm_buffer); | 551 PutSHM(it->second.shm_buffer); |
| 575 bitstream_buffers_in_decoder_.erase(it); | 552 bitstream_buffers_in_decoder_.erase(it); |
| 576 | |
| 577 if (pending_reset_cb_.is_null() && state_ != kDrainingDecoder && | |
| 578 CanMoreDecodeWorkBeDone() && !pending_decode_cb_.is_null()) { | |
| 579 base::ResetAndReturn(&pending_decode_cb_).Run(kNotEnoughData, NULL); | |
| 580 } | |
| 581 } | 553 } |
| 582 | 554 |
| 583 GpuVideoDecoder::~GpuVideoDecoder() { | 555 GpuVideoDecoder::~GpuVideoDecoder() { |
| 584 DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent(); | 556 DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent(); |
| 585 // Stop should have been already called. | 557 // Stop should have been already called. |
| 586 DCHECK(!vda_.get() && assigned_picture_buffers_.empty()); | 558 DCHECK(!vda_.get() && assigned_picture_buffers_.empty()); |
| 587 DCHECK(pending_decode_cb_.is_null()); | 559 DCHECK(pending_decode_callbacks_.empty()); |
| 588 for (size_t i = 0; i < available_shm_segments_.size(); ++i) { | 560 for (size_t i = 0; i < available_shm_segments_.size(); ++i) { |
| 589 available_shm_segments_[i]->shm->Close(); | 561 available_shm_segments_[i]->shm->Close(); |
| 590 delete available_shm_segments_[i]; | 562 delete available_shm_segments_[i]; |
| 591 } | 563 } |
| 592 available_shm_segments_.clear(); | 564 available_shm_segments_.clear(); |
| 593 for (std::map<int32, BufferPair>::iterator it = | 565 for (std::map<int32, BufferPair>::iterator it = |
| 594 bitstream_buffers_in_decoder_.begin(); | 566 bitstream_buffers_in_decoder_.begin(); |
| 595 it != bitstream_buffers_in_decoder_.end(); ++it) { | 567 it != bitstream_buffers_in_decoder_.end(); ++it) { |
| 596 it->second.shm_buffer->shm->Close(); | 568 it->second.shm_buffer->shm->Close(); |
| 597 } | 569 } |
| 598 bitstream_buffers_in_decoder_.clear(); | 570 bitstream_buffers_in_decoder_.clear(); |
| 599 } | 571 } |
| 600 | 572 |
| 601 void GpuVideoDecoder::NotifyFlushDone() { | 573 void GpuVideoDecoder::NotifyFlushDone() { |
| 602 DVLOG(3) << "NotifyFlushDone()"; | 574 DVLOG(3) << "NotifyFlushDone()"; |
| 603 DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent(); | 575 DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent(); |
| 604 DCHECK_EQ(state_, kDrainingDecoder); | 576 DCHECK_EQ(state_, kDrainingDecoder); |
| 577 DCHECK_EQ(pending_decode_callbacks_.size(), 1U); |
| 605 state_ = kDecoderDrained; | 578 state_ = kDecoderDrained; |
| 606 EnqueueFrameAndTriggerFrameDelivery(VideoFrame::CreateEOSFrame()); | 579 DeliverFrame(VideoFrame::CreateEOSFrame()); |
| 607 } | 580 } |
| 608 | 581 |
| 609 void GpuVideoDecoder::NotifyResetDone() { | 582 void GpuVideoDecoder::NotifyResetDone() { |
| 610 DVLOG(3) << "NotifyResetDone()"; | 583 DVLOG(3) << "NotifyResetDone()"; |
| 611 DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent(); | 584 DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent(); |
| 612 DCHECK(ready_video_frames_.empty()); | 585 DCHECK(pending_decode_callbacks_.empty()); |
| 613 | 586 |
| 614 // This needs to happen after the Reset() on vda_ is done to ensure pictures | 587 // This needs to happen after the Reset() on vda_ is done to ensure pictures |
| 615 // delivered during the reset can find their time data. | 588 // delivered during the reset can find their time data. |
| 616 input_buffer_data_.clear(); | 589 input_buffer_data_.clear(); |
| 617 | 590 |
| 618 if (!pending_reset_cb_.is_null()) | 591 if (!pending_reset_cb_.is_null()) |
| 619 base::ResetAndReturn(&pending_reset_cb_).Run(); | 592 base::ResetAndReturn(&pending_reset_cb_).Run(); |
| 620 | |
| 621 if (!pending_decode_cb_.is_null()) | |
| 622 EnqueueFrameAndTriggerFrameDelivery(VideoFrame::CreateEOSFrame()); | |
| 623 } | 593 } |
| 624 | 594 |
| 625 void GpuVideoDecoder::NotifyError(media::VideoDecodeAccelerator::Error error) { | 595 void GpuVideoDecoder::NotifyError(media::VideoDecodeAccelerator::Error error) { |
| 626 DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent(); | 596 DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent(); |
| 627 if (!vda_) | 597 if (!vda_) |
| 628 return; | 598 return; |
| 629 | 599 |
| 630 DLOG(ERROR) << "VDA Error: " << error; | 600 DLOG(ERROR) << "VDA Error: " << error; |
| 631 DestroyVDA(); | 601 DestroyVDA(); |
| 632 | 602 |
| 633 state_ = kError; | 603 state_ = kError; |
| 634 | 604 |
| 635 if (!pending_decode_cb_.is_null()) { | 605 while (!pending_decode_callbacks_.empty()) { |
| 636 base::ResetAndReturn(&pending_decode_cb_).Run(kDecodeError, NULL); | 606 pending_decode_callbacks_.front().Run(kDecodeError, NULL); |
| 637 return; | 607 pending_decode_callbacks_.pop_front(); |
| 638 } | 608 } |
| 639 } | 609 } |
| 640 | 610 |
| 641 void GpuVideoDecoder::DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent() | 611 void GpuVideoDecoder::DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent() |
| 642 const { | 612 const { |
| 643 DCHECK(factories_->GetTaskRunner()->BelongsToCurrentThread()); | 613 DCHECK(factories_->GetTaskRunner()->BelongsToCurrentThread()); |
| 644 } | 614 } |
| 645 | 615 |
| 646 } // namespace media | 616 } // namespace media |
| OLD | NEW |