| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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 <algorithm> | 5 #include <algorithm> |
| 6 | 6 |
| 7 #include <CoreVideo/CoreVideo.h> | 7 #include <CoreVideo/CoreVideo.h> |
| 8 #include <OpenGL/CGLIOSurface.h> | 8 #include <OpenGL/CGLIOSurface.h> |
| 9 #include <OpenGL/gl.h> | 9 #include <OpenGL/gl.h> |
| 10 | 10 |
| (...skipping 614 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 625 } | 625 } |
| 626 } | 626 } |
| 627 | 627 |
| 628 // This method may be called on any VideoToolbox thread. | 628 // This method may be called on any VideoToolbox thread. |
| 629 void VTVideoDecodeAccelerator::Output( | 629 void VTVideoDecodeAccelerator::Output( |
| 630 void* source_frame_refcon, | 630 void* source_frame_refcon, |
| 631 OSStatus status, | 631 OSStatus status, |
| 632 CVImageBufferRef image_buffer) { | 632 CVImageBufferRef image_buffer) { |
| 633 if (status) { | 633 if (status) { |
| 634 NOTIFY_STATUS("Decoding", status); | 634 NOTIFY_STATUS("Decoding", status); |
| 635 } else if (CFGetTypeID(image_buffer) != CVPixelBufferGetTypeID()) { | 635 return; |
| 636 } |
| 637 |
| 638 // The type of |image_buffer| is CVImageBuffer, but we only handle |
| 639 // CVPixelBuffers. This should be guaranteed as we set |
| 640 // kCVPixelBufferOpenGLCompatibilityKey in |image_config|. |
| 641 // |
| 642 // Sometimes, for unknown reasons (http://crbug.com/453050), |image_buffer| is |
| 643 // NULL, which causes CFGetTypeID() to crash. While the rest of the code would |
| 644 // smoothly handle NULL as a dropped frame, we choose to fail permanantly here |
| 645 // until the issue is better understood. |
| 646 if (!image_buffer || CFGetTypeID(image_buffer) != CVPixelBufferGetTypeID()) { |
| 636 DLOG(ERROR) << "Decoded frame is not a CVPixelBuffer"; | 647 DLOG(ERROR) << "Decoded frame is not a CVPixelBuffer"; |
| 637 NotifyError(PLATFORM_FAILURE); | 648 NotifyError(PLATFORM_FAILURE); |
| 638 } else { | 649 return; |
| 639 Frame* frame = reinterpret_cast<Frame*>(source_frame_refcon); | |
| 640 frame->image.reset(image_buffer, base::scoped_policy::RETAIN); | |
| 641 gpu_task_runner_->PostTask(FROM_HERE, base::Bind( | |
| 642 &VTVideoDecodeAccelerator::DecodeDone, weak_this_, frame)); | |
| 643 } | 650 } |
| 651 |
| 652 Frame* frame = reinterpret_cast<Frame*>(source_frame_refcon); |
| 653 frame->image.reset(image_buffer, base::scoped_policy::RETAIN); |
| 654 gpu_task_runner_->PostTask(FROM_HERE, base::Bind( |
| 655 &VTVideoDecodeAccelerator::DecodeDone, weak_this_, frame)); |
| 644 } | 656 } |
| 645 | 657 |
| 646 void VTVideoDecodeAccelerator::DecodeDone(Frame* frame) { | 658 void VTVideoDecodeAccelerator::DecodeDone(Frame* frame) { |
| 647 DCHECK(gpu_thread_checker_.CalledOnValidThread()); | 659 DCHECK(gpu_thread_checker_.CalledOnValidThread()); |
| 648 DCHECK_EQ(1u, pending_frames_.count(frame->bitstream_id)); | 660 DCHECK_EQ(1u, pending_frames_.count(frame->bitstream_id)); |
| 649 Task task(TASK_FRAME); | 661 Task task(TASK_FRAME); |
| 650 task.frame = pending_frames_[frame->bitstream_id]; | 662 task.frame = pending_frames_[frame->bitstream_id]; |
| 651 pending_frames_.erase(frame->bitstream_id); | 663 pending_frames_.erase(frame->bitstream_id); |
| 652 task_queue_.push(task); | 664 task_queue_.push(task); |
| 653 ProcessWorkQueues(); | 665 ProcessWorkQueues(); |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 708 } else { | 720 } else { |
| 709 client_->DismissPictureBuffer(picture_id); | 721 client_->DismissPictureBuffer(picture_id); |
| 710 } | 722 } |
| 711 } | 723 } |
| 712 | 724 |
| 713 void VTVideoDecodeAccelerator::ProcessWorkQueues() { | 725 void VTVideoDecodeAccelerator::ProcessWorkQueues() { |
| 714 DCHECK(gpu_thread_checker_.CalledOnValidThread()); | 726 DCHECK(gpu_thread_checker_.CalledOnValidThread()); |
| 715 switch (state_) { | 727 switch (state_) { |
| 716 case STATE_DECODING: | 728 case STATE_DECODING: |
| 717 // TODO(sandersd): Batch where possible. | 729 // TODO(sandersd): Batch where possible. |
| 718 while (ProcessReorderQueue() || ProcessTaskQueue()); | 730 while (state_ == STATE_DECODING) { |
| 731 if (!ProcessReorderQueue() && !ProcessTaskQueue()) |
| 732 break; |
| 733 } |
| 719 return; | 734 return; |
| 720 | 735 |
| 721 case STATE_ERROR: | 736 case STATE_ERROR: |
| 722 // Do nothing until Destroy() is called. | 737 // Do nothing until Destroy() is called. |
| 723 return; | 738 return; |
| 724 | 739 |
| 725 case STATE_DESTROYING: | 740 case STATE_DESTROYING: |
| 726 // Drop tasks until we are ready to destruct. | 741 // Drop tasks until we are ready to destruct. |
| 727 while (!task_queue_.empty()) { | 742 while (!task_queue_.empty()) { |
| 728 if (task_queue_.front().type == TASK_DESTROY) { | 743 if (task_queue_.front().type == TASK_DESTROY) { |
| (...skipping 212 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 941 assigned_bitstream_ids_.clear(); | 956 assigned_bitstream_ids_.clear(); |
| 942 state_ = STATE_DESTROYING; | 957 state_ = STATE_DESTROYING; |
| 943 QueueFlush(TASK_DESTROY); | 958 QueueFlush(TASK_DESTROY); |
| 944 } | 959 } |
| 945 | 960 |
| 946 bool VTVideoDecodeAccelerator::CanDecodeOnIOThread() { | 961 bool VTVideoDecodeAccelerator::CanDecodeOnIOThread() { |
| 947 return false; | 962 return false; |
| 948 } | 963 } |
| 949 | 964 |
| 950 } // namespace content | 965 } // namespace content |
| OLD | NEW |