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 |