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 "content/common/gpu/media/dxva_video_decode_accelerator.h" | 5 #include "content/common/gpu/media/dxva_video_decode_accelerator.h" |
6 | 6 |
7 #if !defined(OS_WIN) | 7 #if !defined(OS_WIN) |
8 #error This file should only be built on Windows. | 8 #error This file should only be built on Windows. |
9 #endif // !defined(OS_WIN) | 9 #endif // !defined(OS_WIN) |
10 | 10 |
(...skipping 530 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
541 SendMFTMessage(MFT_MESSAGE_NOTIFY_BEGIN_STREAMING, 0), | 541 SendMFTMessage(MFT_MESSAGE_NOTIFY_BEGIN_STREAMING, 0), |
542 "Send MFT_MESSAGE_NOTIFY_BEGIN_STREAMING notification failed", | 542 "Send MFT_MESSAGE_NOTIFY_BEGIN_STREAMING notification failed", |
543 PLATFORM_FAILURE, false); | 543 PLATFORM_FAILURE, false); |
544 | 544 |
545 RETURN_AND_NOTIFY_ON_FAILURE( | 545 RETURN_AND_NOTIFY_ON_FAILURE( |
546 SendMFTMessage(MFT_MESSAGE_NOTIFY_START_OF_STREAM, 0), | 546 SendMFTMessage(MFT_MESSAGE_NOTIFY_START_OF_STREAM, 0), |
547 "Send MFT_MESSAGE_NOTIFY_START_OF_STREAM notification failed", | 547 "Send MFT_MESSAGE_NOTIFY_START_OF_STREAM notification failed", |
548 PLATFORM_FAILURE, false); | 548 PLATFORM_FAILURE, false); |
549 | 549 |
550 state_ = kNormal; | 550 state_ = kNormal; |
551 MessageLoop::current()->PostTask(FROM_HERE, | 551 MessageLoop::current()->PostTask(FROM_HERE, base::Bind( |
552 base::Bind(&DXVAVideoDecodeAccelerator::NotifyInitializeDone, this)); | 552 &DXVAVideoDecodeAccelerator::NotifyInitializeDone, |
| 553 base::AsWeakPtr(this))); |
553 return true; | 554 return true; |
554 } | 555 } |
555 | 556 |
556 void DXVAVideoDecodeAccelerator::Decode( | 557 void DXVAVideoDecodeAccelerator::Decode( |
557 const media::BitstreamBuffer& bitstream_buffer) { | 558 const media::BitstreamBuffer& bitstream_buffer) { |
558 DCHECK(CalledOnValidThread()); | 559 DCHECK(CalledOnValidThread()); |
559 | 560 |
560 RETURN_AND_NOTIFY_ON_FAILURE((state_ == kNormal || state_ == kStopped), | 561 RETURN_AND_NOTIFY_ON_FAILURE((state_ == kNormal || state_ == kStopped), |
561 "Invalid state: " << state_, ILLEGAL_STATE,); | 562 "Invalid state: " << state_, ILLEGAL_STATE,); |
562 | 563 |
(...skipping 27 matching lines...) Expand all Loading... |
590 // The Microsoft Media foundation decoder internally buffers up to 30 frames | 591 // The Microsoft Media foundation decoder internally buffers up to 30 frames |
591 // before returning a decoded frame. We need to inform the client that this | 592 // before returning a decoded frame. We need to inform the client that this |
592 // input buffer is processed as it may stop sending us further input. | 593 // input buffer is processed as it may stop sending us further input. |
593 // Note: This may break clients which expect every input buffer to be | 594 // Note: This may break clients which expect every input buffer to be |
594 // associated with a decoded output buffer. | 595 // associated with a decoded output buffer. |
595 // TODO(ananta) | 596 // TODO(ananta) |
596 // Do some more investigation into whether it is possible to get the MFT | 597 // Do some more investigation into whether it is possible to get the MFT |
597 // decoder to emit an output packet for every input packet. | 598 // decoder to emit an output packet for every input packet. |
598 // http://code.google.com/p/chromium/issues/detail?id=108121 | 599 // http://code.google.com/p/chromium/issues/detail?id=108121 |
599 MessageLoop::current()->PostTask(FROM_HERE, base::Bind( | 600 MessageLoop::current()->PostTask(FROM_HERE, base::Bind( |
600 &DXVAVideoDecodeAccelerator::NotifyInputBufferRead, this, | 601 &DXVAVideoDecodeAccelerator::NotifyInputBufferRead, base::AsWeakPtr(this), |
601 bitstream_buffer.id())); | 602 bitstream_buffer.id())); |
602 } | 603 } |
603 | 604 |
604 void DXVAVideoDecodeAccelerator::AssignPictureBuffers( | 605 void DXVAVideoDecodeAccelerator::AssignPictureBuffers( |
605 const std::vector<media::PictureBuffer>& buffers) { | 606 const std::vector<media::PictureBuffer>& buffers) { |
606 DCHECK(CalledOnValidThread()); | 607 DCHECK(CalledOnValidThread()); |
607 // Copy the picture buffers provided by the client to the available list, | 608 // Copy the picture buffers provided by the client to the available list, |
608 // and mark these buffers as available for use. | 609 // and mark these buffers as available for use. |
609 for (size_t buffer_index = 0; buffer_index < buffers.size(); | 610 for (size_t buffer_index = 0; buffer_index < buffers.size(); |
610 ++buffer_index) { | 611 ++buffer_index) { |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
651 // the state to kStopped when the decoder returns | 652 // the state to kStopped when the decoder returns |
652 // MF_E_TRANSFORM_NEED_MORE_INPUT. | 653 // MF_E_TRANSFORM_NEED_MORE_INPUT. |
653 // The MFT decoder can buffer upto 30 frames worth of input before returning | 654 // The MFT decoder can buffer upto 30 frames worth of input before returning |
654 // an output frame. This loop here attempts to retrieve as many output frames | 655 // an output frame. This loop here attempts to retrieve as many output frames |
655 // as possible from the buffered set. | 656 // as possible from the buffered set. |
656 while (state_ != kStopped) { | 657 while (state_ != kStopped) { |
657 DoDecode(); | 658 DoDecode(); |
658 } | 659 } |
659 | 660 |
660 MessageLoop::current()->PostTask(FROM_HERE, base::Bind( | 661 MessageLoop::current()->PostTask(FROM_HERE, base::Bind( |
661 &DXVAVideoDecodeAccelerator::NotifyFlushDone, this)); | 662 &DXVAVideoDecodeAccelerator::NotifyFlushDone, base::AsWeakPtr(this))); |
662 | 663 |
663 state_ = kNormal; | 664 state_ = kNormal; |
664 } | 665 } |
665 | 666 |
666 void DXVAVideoDecodeAccelerator::Reset() { | 667 void DXVAVideoDecodeAccelerator::Reset() { |
667 DCHECK(CalledOnValidThread()); | 668 DCHECK(CalledOnValidThread()); |
668 | 669 |
669 DVLOG(1) << "DXVAVideoDecodeAccelerator::Reset"; | 670 DVLOG(1) << "DXVAVideoDecodeAccelerator::Reset"; |
670 | 671 |
671 RETURN_AND_NOTIFY_ON_FAILURE((state_ == kNormal || state_ == kStopped), | 672 RETURN_AND_NOTIFY_ON_FAILURE((state_ == kNormal || state_ == kStopped), |
672 "Reset: invalid state: " << state_, ILLEGAL_STATE,); | 673 "Reset: invalid state: " << state_, ILLEGAL_STATE,); |
673 | 674 |
674 state_ = kResetting; | 675 state_ = kResetting; |
675 | 676 |
676 RETURN_AND_NOTIFY_ON_FAILURE(SendMFTMessage(MFT_MESSAGE_COMMAND_FLUSH, 0), | 677 RETURN_AND_NOTIFY_ON_FAILURE(SendMFTMessage(MFT_MESSAGE_COMMAND_FLUSH, 0), |
677 "Reset: Failed to send message.", PLATFORM_FAILURE,); | 678 "Reset: Failed to send message.", PLATFORM_FAILURE,); |
678 | 679 |
679 MessageLoop::current()->PostTask(FROM_HERE, base::Bind( | 680 MessageLoop::current()->PostTask(FROM_HERE, base::Bind( |
680 &DXVAVideoDecodeAccelerator::NotifyResetDone, this)); | 681 &DXVAVideoDecodeAccelerator::NotifyResetDone, base::AsWeakPtr(this))); |
681 | 682 |
682 state_ = DXVAVideoDecodeAccelerator::kNormal; | 683 state_ = DXVAVideoDecodeAccelerator::kNormal; |
683 } | 684 } |
684 | 685 |
685 void DXVAVideoDecodeAccelerator::Destroy() { | 686 void DXVAVideoDecodeAccelerator::Destroy() { |
686 DCHECK(CalledOnValidThread()); | 687 DCHECK(CalledOnValidThread()); |
687 Invalidate(); | 688 Invalidate(); |
| 689 delete this; |
688 } | 690 } |
689 | 691 |
690 bool DXVAVideoDecodeAccelerator::InitDecoder() { | 692 bool DXVAVideoDecodeAccelerator::InitDecoder() { |
691 // We cannot use CoCreateInstance to instantiate the decoder object as that | 693 // We cannot use CoCreateInstance to instantiate the decoder object as that |
692 // fails in the sandbox. We mimic the steps CoCreateInstance uses to | 694 // fails in the sandbox. We mimic the steps CoCreateInstance uses to |
693 // instantiate the object. | 695 // instantiate the object. |
694 HMODULE decoder_dll = ::GetModuleHandle(L"msmpeg2vdec.dll"); | 696 HMODULE decoder_dll = ::GetModuleHandle(L"msmpeg2vdec.dll"); |
695 RETURN_ON_FAILURE(decoder_dll, | 697 RETURN_ON_FAILURE(decoder_dll, |
696 "msmpeg2vdec.dll required for decoding is not loaded", | 698 "msmpeg2vdec.dll required for decoding is not loaded", |
697 false); | 699 false); |
(...skipping 241 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
939 ProcessPendingSamples(); | 941 ProcessPendingSamples(); |
940 return true; | 942 return true; |
941 } | 943 } |
942 if (pictures_requested_) { | 944 if (pictures_requested_) { |
943 DVLOG(1) << "Waiting for picture slots from the client."; | 945 DVLOG(1) << "Waiting for picture slots from the client."; |
944 return true; | 946 return true; |
945 } | 947 } |
946 // Go ahead and request picture buffers. | 948 // Go ahead and request picture buffers. |
947 MessageLoop::current()->PostTask(FROM_HERE, base::Bind( | 949 MessageLoop::current()->PostTask(FROM_HERE, base::Bind( |
948 &DXVAVideoDecodeAccelerator::RequestPictureBuffers, | 950 &DXVAVideoDecodeAccelerator::RequestPictureBuffers, |
949 this, surface_desc.Width, surface_desc.Height)); | 951 base::AsWeakPtr(this), surface_desc.Width, surface_desc.Height)); |
950 | 952 |
951 pictures_requested_ = true; | 953 pictures_requested_ = true; |
952 return true; | 954 return true; |
953 } | 955 } |
954 | 956 |
955 void DXVAVideoDecodeAccelerator::ProcessPendingSamples() { | 957 void DXVAVideoDecodeAccelerator::ProcessPendingSamples() { |
956 if (pending_output_samples_.empty()) | 958 if (pending_output_samples_.empty()) |
957 return; | 959 return; |
958 | 960 |
959 OutputBuffers::iterator index; | 961 OutputBuffers::iterator index; |
960 | 962 |
961 for (index = output_picture_buffers_.begin(); | 963 for (index = output_picture_buffers_.begin(); |
962 index != output_picture_buffers_.end() && | 964 index != output_picture_buffers_.end() && |
963 !pending_output_samples_.empty(); | 965 !pending_output_samples_.empty(); |
964 ++index) { | 966 ++index) { |
965 if (index->second->available()) { | 967 if (index->second->available()) { |
966 PendingSampleInfo sample_info = pending_output_samples_.front(); | 968 PendingSampleInfo sample_info = pending_output_samples_.front(); |
967 | 969 |
968 RETURN_AND_NOTIFY_ON_FAILURE( | 970 RETURN_AND_NOTIFY_ON_FAILURE( |
969 index->second->CopyOutputSampleDataToPictureBuffer( | 971 index->second->CopyOutputSampleDataToPictureBuffer( |
970 sample_info.dest_surface), | 972 sample_info.dest_surface), |
971 "Failed to copy output sample", PLATFORM_FAILURE,); | 973 "Failed to copy output sample", PLATFORM_FAILURE,); |
972 | 974 |
973 media::Picture output_picture(index->second->id(), | 975 media::Picture output_picture(index->second->id(), |
974 sample_info.input_buffer_id); | 976 sample_info.input_buffer_id); |
975 MessageLoop::current()->PostTask(FROM_HERE, base::Bind( | 977 MessageLoop::current()->PostTask(FROM_HERE, base::Bind( |
976 &DXVAVideoDecodeAccelerator::NotifyPictureReady, this, | 978 &DXVAVideoDecodeAccelerator::NotifyPictureReady, |
977 output_picture)); | 979 base::AsWeakPtr(this), output_picture)); |
978 | 980 |
979 index->second->set_available(false); | 981 index->second->set_available(false); |
980 pending_output_samples_.pop_front(); | 982 pending_output_samples_.pop_front(); |
981 } | 983 } |
982 } | 984 } |
983 } | 985 } |
984 | 986 |
985 void DXVAVideoDecodeAccelerator::ClearState() { | 987 void DXVAVideoDecodeAccelerator::ClearState() { |
986 output_picture_buffers_.clear(); | 988 output_picture_buffers_.clear(); |
987 pending_output_samples_.clear(); | 989 pending_output_samples_.clear(); |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1040 GL_TEXTURE_2D); | 1042 GL_TEXTURE_2D); |
1041 } | 1043 } |
1042 } | 1044 } |
1043 | 1045 |
1044 void DXVAVideoDecodeAccelerator::NotifyPictureReady( | 1046 void DXVAVideoDecodeAccelerator::NotifyPictureReady( |
1045 const media::Picture& picture) { | 1047 const media::Picture& picture) { |
1046 // This task could execute after the decoder has been torn down. | 1048 // This task could execute after the decoder has been torn down. |
1047 if (state_ != kUninitialized && client_) | 1049 if (state_ != kUninitialized && client_) |
1048 client_->PictureReady(picture); | 1050 client_->PictureReady(picture); |
1049 } | 1051 } |
OLD | NEW |