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/gpu/dxva_video_decode_accelerator_win.h" | 5 #include "media/gpu/dxva_video_decode_accelerator_win.h" |
6 | 6 |
7 #include <memory> | 7 #include <memory> |
8 | 8 |
9 #if !defined(OS_WIN) | 9 #if !defined(OS_WIN) |
10 #error This file should only be built on Windows. | 10 #error This file should only be built on Windows. |
(...skipping 200 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
211 DWORD max_length_; | 211 DWORD max_length_; |
212 DWORD current_length_; | 212 DWORD current_length_; |
213 | 213 |
214 DISALLOW_COPY_AND_ASSIGN(MediaBufferScopedPointer); | 214 DISALLOW_COPY_AND_ASSIGN(MediaBufferScopedPointer); |
215 }; | 215 }; |
216 | 216 |
217 } // namespace | 217 } // namespace |
218 | 218 |
219 namespace media { | 219 namespace media { |
220 | 220 |
221 static const media::VideoCodecProfile kSupportedProfiles[] = { | 221 static const VideoCodecProfile kSupportedProfiles[] = { |
222 media::H264PROFILE_BASELINE, media::H264PROFILE_MAIN, | 222 H264PROFILE_BASELINE, H264PROFILE_MAIN, H264PROFILE_HIGH, |
223 media::H264PROFILE_HIGH, media::VP8PROFILE_ANY, | 223 VP8PROFILE_ANY, VP9PROFILE_PROFILE0, VP9PROFILE_PROFILE1, |
224 media::VP9PROFILE_PROFILE0, media::VP9PROFILE_PROFILE1, | 224 VP9PROFILE_PROFILE2, VP9PROFILE_PROFILE3}; |
225 media::VP9PROFILE_PROFILE2, media::VP9PROFILE_PROFILE3}; | |
226 | 225 |
227 CreateDXGIDeviceManager | 226 CreateDXGIDeviceManager |
228 DXVAVideoDecodeAccelerator::create_dxgi_device_manager_ = NULL; | 227 DXVAVideoDecodeAccelerator::create_dxgi_device_manager_ = NULL; |
229 | 228 |
230 #define RETURN_ON_FAILURE(result, log, ret) \ | 229 #define RETURN_ON_FAILURE(result, log, ret) \ |
231 do { \ | 230 do { \ |
232 if (!(result)) { \ | 231 if (!(result)) { \ |
233 DLOG(ERROR) << log; \ | 232 DLOG(ERROR) << log; \ |
234 return ret; \ | 233 return ret; \ |
235 } \ | 234 } \ |
(...skipping 217 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
453 last_pps_id_(0), | 452 last_pps_id_(0), |
454 config_changed_(false), | 453 config_changed_(false), |
455 pending_config_changed_(false) {} | 454 pending_config_changed_(false) {} |
456 | 455 |
457 H264ConfigChangeDetector::~H264ConfigChangeDetector() {} | 456 H264ConfigChangeDetector::~H264ConfigChangeDetector() {} |
458 | 457 |
459 bool H264ConfigChangeDetector::DetectConfig(const uint8_t* stream, | 458 bool H264ConfigChangeDetector::DetectConfig(const uint8_t* stream, |
460 unsigned int size) { | 459 unsigned int size) { |
461 std::vector<uint8_t> sps; | 460 std::vector<uint8_t> sps; |
462 std::vector<uint8_t> pps; | 461 std::vector<uint8_t> pps; |
463 media::H264NALU nalu; | 462 H264NALU nalu; |
464 bool idr_seen = false; | 463 bool idr_seen = false; |
465 | 464 |
466 if (!parser_.get()) | 465 if (!parser_.get()) |
467 parser_.reset(new media::H264Parser); | 466 parser_.reset(new H264Parser); |
468 | 467 |
469 parser_->SetStream(stream, size); | 468 parser_->SetStream(stream, size); |
470 config_changed_ = false; | 469 config_changed_ = false; |
471 | 470 |
472 while (true) { | 471 while (true) { |
473 media::H264Parser::Result result = parser_->AdvanceToNextNALU(&nalu); | 472 H264Parser::Result result = parser_->AdvanceToNextNALU(&nalu); |
474 | 473 |
475 if (result == media::H264Parser::kEOStream) | 474 if (result == H264Parser::kEOStream) |
476 break; | 475 break; |
477 | 476 |
478 if (result == media::H264Parser::kUnsupportedStream) { | 477 if (result == H264Parser::kUnsupportedStream) { |
479 DLOG(ERROR) << "Unsupported H.264 stream"; | 478 DLOG(ERROR) << "Unsupported H.264 stream"; |
480 return false; | 479 return false; |
481 } | 480 } |
482 | 481 |
483 if (result != media::H264Parser::kOk) { | 482 if (result != H264Parser::kOk) { |
484 DLOG(ERROR) << "Failed to parse H.264 stream"; | 483 DLOG(ERROR) << "Failed to parse H.264 stream"; |
485 return false; | 484 return false; |
486 } | 485 } |
487 | 486 |
488 switch (nalu.nal_unit_type) { | 487 switch (nalu.nal_unit_type) { |
489 case media::H264NALU::kSPS: | 488 case H264NALU::kSPS: |
490 result = parser_->ParseSPS(&last_sps_id_); | 489 result = parser_->ParseSPS(&last_sps_id_); |
491 if (result == media::H264Parser::kUnsupportedStream) { | 490 if (result == H264Parser::kUnsupportedStream) { |
492 DLOG(ERROR) << "Unsupported SPS"; | 491 DLOG(ERROR) << "Unsupported SPS"; |
493 return false; | 492 return false; |
494 } | 493 } |
495 | 494 |
496 if (result != media::H264Parser::kOk) { | 495 if (result != H264Parser::kOk) { |
497 DLOG(ERROR) << "Could not parse SPS"; | 496 DLOG(ERROR) << "Could not parse SPS"; |
498 return false; | 497 return false; |
499 } | 498 } |
500 | 499 |
501 sps.assign(nalu.data, nalu.data + nalu.size); | 500 sps.assign(nalu.data, nalu.data + nalu.size); |
502 break; | 501 break; |
503 | 502 |
504 case media::H264NALU::kPPS: | 503 case H264NALU::kPPS: |
505 result = parser_->ParsePPS(&last_pps_id_); | 504 result = parser_->ParsePPS(&last_pps_id_); |
506 if (result == media::H264Parser::kUnsupportedStream) { | 505 if (result == H264Parser::kUnsupportedStream) { |
507 DLOG(ERROR) << "Unsupported PPS"; | 506 DLOG(ERROR) << "Unsupported PPS"; |
508 return false; | 507 return false; |
509 } | 508 } |
510 if (result != media::H264Parser::kOk) { | 509 if (result != H264Parser::kOk) { |
511 DLOG(ERROR) << "Could not parse PPS"; | 510 DLOG(ERROR) << "Could not parse PPS"; |
512 return false; | 511 return false; |
513 } | 512 } |
514 pps.assign(nalu.data, nalu.data + nalu.size); | 513 pps.assign(nalu.data, nalu.data + nalu.size); |
515 break; | 514 break; |
516 | 515 |
517 case media::H264NALU::kIDRSlice: | 516 case H264NALU::kIDRSlice: |
518 idr_seen = true; | 517 idr_seen = true; |
519 // If we previously detected a configuration change, and see an IDR | 518 // If we previously detected a configuration change, and see an IDR |
520 // slice next time around, we need to flag a configuration change. | 519 // slice next time around, we need to flag a configuration change. |
521 if (pending_config_changed_) { | 520 if (pending_config_changed_) { |
522 config_changed_ = true; | 521 config_changed_ = true; |
523 pending_config_changed_ = false; | 522 pending_config_changed_ = false; |
524 } | 523 } |
525 break; | 524 break; |
526 | 525 |
527 default: | 526 default: |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
575 : client_(NULL), | 574 : client_(NULL), |
576 dev_manager_reset_token_(0), | 575 dev_manager_reset_token_(0), |
577 dx11_dev_manager_reset_token_(0), | 576 dx11_dev_manager_reset_token_(0), |
578 egl_config_(NULL), | 577 egl_config_(NULL), |
579 state_(kUninitialized), | 578 state_(kUninitialized), |
580 pictures_requested_(false), | 579 pictures_requested_(false), |
581 inputs_before_decode_(0), | 580 inputs_before_decode_(0), |
582 sent_drain_message_(false), | 581 sent_drain_message_(false), |
583 get_gl_context_cb_(get_gl_context_cb), | 582 get_gl_context_cb_(get_gl_context_cb), |
584 make_context_current_cb_(make_context_current_cb), | 583 make_context_current_cb_(make_context_current_cb), |
585 codec_(media::kUnknownVideoCodec), | 584 codec_(kUnknownVideoCodec), |
586 decoder_thread_("DXVAVideoDecoderThread"), | 585 decoder_thread_("DXVAVideoDecoderThread"), |
587 pending_flush_(false), | 586 pending_flush_(false), |
588 share_nv12_textures_(gpu_preferences.enable_zero_copy_dxgi_video), | 587 share_nv12_textures_(gpu_preferences.enable_zero_copy_dxgi_video), |
589 use_dx11_(false), | 588 use_dx11_(false), |
590 use_keyed_mutex_(false), | 589 use_keyed_mutex_(false), |
591 dx11_video_format_converter_media_type_needs_init_(true), | 590 dx11_video_format_converter_media_type_needs_init_(true), |
592 using_angle_device_(false), | 591 using_angle_device_(false), |
593 enable_accelerated_vpx_decode_( | 592 enable_accelerated_vpx_decode_( |
594 gpu_preferences.enable_accelerated_vpx_decode), | 593 gpu_preferences.enable_accelerated_vpx_decode), |
595 weak_this_factory_(this) { | 594 weak_this_factory_(this) { |
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
673 | 672 |
674 RETURN_AND_NOTIFY_ON_FAILURE(gl::GLFence::IsSupported(), | 673 RETURN_AND_NOTIFY_ON_FAILURE(gl::GLFence::IsSupported(), |
675 "GL fences are unsupported", PLATFORM_FAILURE, | 674 "GL fences are unsupported", PLATFORM_FAILURE, |
676 false); | 675 false); |
677 | 676 |
678 State state = GetState(); | 677 State state = GetState(); |
679 RETURN_AND_NOTIFY_ON_FAILURE((state == kUninitialized), | 678 RETURN_AND_NOTIFY_ON_FAILURE((state == kUninitialized), |
680 "Initialize: invalid state: " << state, | 679 "Initialize: invalid state: " << state, |
681 ILLEGAL_STATE, false); | 680 ILLEGAL_STATE, false); |
682 | 681 |
683 media::InitializeMediaFoundation(); | 682 InitializeMediaFoundation(); |
684 | 683 |
685 RETURN_AND_NOTIFY_ON_FAILURE(InitDecoder(config.profile), | 684 RETURN_AND_NOTIFY_ON_FAILURE(InitDecoder(config.profile), |
686 "Failed to initialize decoder", PLATFORM_FAILURE, | 685 "Failed to initialize decoder", PLATFORM_FAILURE, |
687 false); | 686 false); |
688 | 687 |
689 RETURN_AND_NOTIFY_ON_FAILURE(GetStreamsInfoAndBufferReqs(), | 688 RETURN_AND_NOTIFY_ON_FAILURE(GetStreamsInfoAndBufferReqs(), |
690 "Failed to get input/output stream info.", | 689 "Failed to get input/output stream info.", |
691 PLATFORM_FAILURE, false); | 690 PLATFORM_FAILURE, false); |
692 | 691 |
693 RETURN_AND_NOTIFY_ON_FAILURE( | 692 RETURN_AND_NOTIFY_ON_FAILURE( |
(...skipping 154 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
848 RETURN_ON_HR_FAILURE( | 847 RETURN_ON_HR_FAILURE( |
849 hr, "Failed to set MF_XVP_PLAYBACK_MODE attribute on converter", false); | 848 hr, "Failed to set MF_XVP_PLAYBACK_MODE attribute on converter", false); |
850 | 849 |
851 hr = converter_attributes->SetUINT32(MF_LOW_LATENCY, FALSE); | 850 hr = converter_attributes->SetUINT32(MF_LOW_LATENCY, FALSE); |
852 RETURN_ON_HR_FAILURE( | 851 RETURN_ON_HR_FAILURE( |
853 hr, "Failed to set MF_LOW_LATENCY attribute on converter", false); | 852 hr, "Failed to set MF_LOW_LATENCY attribute on converter", false); |
854 return true; | 853 return true; |
855 } | 854 } |
856 | 855 |
857 void DXVAVideoDecodeAccelerator::Decode( | 856 void DXVAVideoDecodeAccelerator::Decode( |
858 const media::BitstreamBuffer& bitstream_buffer) { | 857 const BitstreamBuffer& bitstream_buffer) { |
859 TRACE_EVENT0("media", "DXVAVideoDecodeAccelerator::Decode"); | 858 TRACE_EVENT0("media", "DXVAVideoDecodeAccelerator::Decode"); |
860 DCHECK(main_thread_task_runner_->BelongsToCurrentThread()); | 859 DCHECK(main_thread_task_runner_->BelongsToCurrentThread()); |
861 | 860 |
862 // SharedMemory will take over the ownership of handle. | 861 // SharedMemory will take over the ownership of handle. |
863 base::SharedMemory shm(bitstream_buffer.handle(), true); | 862 base::SharedMemory shm(bitstream_buffer.handle(), true); |
864 | 863 |
865 State state = GetState(); | 864 State state = GetState(); |
866 RETURN_AND_NOTIFY_ON_FAILURE( | 865 RETURN_AND_NOTIFY_ON_FAILURE( |
867 (state == kNormal || state == kStopped || state == kFlushing), | 866 (state == kNormal || state == kStopped || state == kFlushing), |
868 "Invalid state: " << state, ILLEGAL_STATE, ); | 867 "Invalid state: " << state, ILLEGAL_STATE, ); |
(...skipping 18 matching lines...) Expand all Loading... |
887 RETURN_AND_NOTIFY_ON_HR_FAILURE( | 886 RETURN_AND_NOTIFY_ON_HR_FAILURE( |
888 sample->SetSampleTime(bitstream_buffer.id()), | 887 sample->SetSampleTime(bitstream_buffer.id()), |
889 "Failed to associate input buffer id with sample", PLATFORM_FAILURE, ); | 888 "Failed to associate input buffer id with sample", PLATFORM_FAILURE, ); |
890 | 889 |
891 decoder_thread_task_runner_->PostTask( | 890 decoder_thread_task_runner_->PostTask( |
892 FROM_HERE, base::Bind(&DXVAVideoDecodeAccelerator::DecodeInternal, | 891 FROM_HERE, base::Bind(&DXVAVideoDecodeAccelerator::DecodeInternal, |
893 base::Unretained(this), sample)); | 892 base::Unretained(this), sample)); |
894 } | 893 } |
895 | 894 |
896 void DXVAVideoDecodeAccelerator::AssignPictureBuffers( | 895 void DXVAVideoDecodeAccelerator::AssignPictureBuffers( |
897 const std::vector<media::PictureBuffer>& buffers) { | 896 const std::vector<PictureBuffer>& buffers) { |
898 DCHECK(main_thread_task_runner_->BelongsToCurrentThread()); | 897 DCHECK(main_thread_task_runner_->BelongsToCurrentThread()); |
899 | 898 |
900 State state = GetState(); | 899 State state = GetState(); |
901 RETURN_AND_NOTIFY_ON_FAILURE((state != kUninitialized), | 900 RETURN_AND_NOTIFY_ON_FAILURE((state != kUninitialized), |
902 "Invalid state: " << state, ILLEGAL_STATE, ); | 901 "Invalid state: " << state, ILLEGAL_STATE, ); |
903 RETURN_AND_NOTIFY_ON_FAILURE( | 902 RETURN_AND_NOTIFY_ON_FAILURE( |
904 (kNumPictureBuffers >= buffers.size()), | 903 (kNumPictureBuffers >= buffers.size()), |
905 "Failed to provide requested picture buffers. (Got " | 904 "Failed to provide requested picture buffers. (Got " |
906 << buffers.size() << ", requested " << kNumPictureBuffers << ")", | 905 << buffers.size() << ", requested " << kNumPictureBuffers << ")", |
907 INVALID_ARGUMENT, ); | 906 INVALID_ARGUMENT, ); |
(...skipping 193 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1101 const base::WeakPtr<Client>& decode_client, | 1100 const base::WeakPtr<Client>& decode_client, |
1102 const scoped_refptr<base::SingleThreadTaskRunner>& decode_task_runner) { | 1101 const scoped_refptr<base::SingleThreadTaskRunner>& decode_task_runner) { |
1103 return false; | 1102 return false; |
1104 } | 1103 } |
1105 | 1104 |
1106 GLenum DXVAVideoDecodeAccelerator::GetSurfaceInternalFormat() const { | 1105 GLenum DXVAVideoDecodeAccelerator::GetSurfaceInternalFormat() const { |
1107 return GL_BGRA_EXT; | 1106 return GL_BGRA_EXT; |
1108 } | 1107 } |
1109 | 1108 |
1110 // static | 1109 // static |
1111 media::VideoDecodeAccelerator::SupportedProfiles | 1110 VideoDecodeAccelerator::SupportedProfiles |
1112 DXVAVideoDecodeAccelerator::GetSupportedProfiles() { | 1111 DXVAVideoDecodeAccelerator::GetSupportedProfiles() { |
1113 TRACE_EVENT0("gpu,startup", | 1112 TRACE_EVENT0("gpu,startup", |
1114 "DXVAVideoDecodeAccelerator::GetSupportedProfiles"); | 1113 "DXVAVideoDecodeAccelerator::GetSupportedProfiles"); |
1115 | 1114 |
1116 // TODO(henryhsu): Need to ensure the profiles are actually supported. | 1115 // TODO(henryhsu): Need to ensure the profiles are actually supported. |
1117 SupportedProfiles profiles; | 1116 SupportedProfiles profiles; |
1118 for (const auto& supported_profile : kSupportedProfiles) { | 1117 for (const auto& supported_profile : kSupportedProfiles) { |
1119 std::pair<int, int> min_resolution = GetMinResolution(supported_profile); | 1118 std::pair<int, int> min_resolution = GetMinResolution(supported_profile); |
1120 std::pair<int, int> max_resolution = GetMaxResolution(supported_profile); | 1119 std::pair<int, int> max_resolution = GetMaxResolution(supported_profile); |
1121 | 1120 |
(...skipping 17 matching lines...) Expand all Loading... |
1139 LoadLibrary(L"msvproc.dll"); | 1138 LoadLibrary(L"msvproc.dll"); |
1140 } else { | 1139 } else { |
1141 #if defined(ENABLE_DX11_FOR_WIN7) | 1140 #if defined(ENABLE_DX11_FOR_WIN7) |
1142 LoadLibrary(L"mshtmlmedia.dll"); | 1141 LoadLibrary(L"mshtmlmedia.dll"); |
1143 #endif | 1142 #endif |
1144 } | 1143 } |
1145 } | 1144 } |
1146 | 1145 |
1147 // static | 1146 // static |
1148 std::pair<int, int> DXVAVideoDecodeAccelerator::GetMinResolution( | 1147 std::pair<int, int> DXVAVideoDecodeAccelerator::GetMinResolution( |
1149 media::VideoCodecProfile profile) { | 1148 VideoCodecProfile profile) { |
1150 TRACE_EVENT0("gpu,startup", "DXVAVideoDecodeAccelerator::GetMinResolution"); | 1149 TRACE_EVENT0("gpu,startup", "DXVAVideoDecodeAccelerator::GetMinResolution"); |
1151 std::pair<int, int> min_resolution; | 1150 std::pair<int, int> min_resolution; |
1152 if (profile >= media::H264PROFILE_BASELINE && | 1151 if (profile >= H264PROFILE_BASELINE && profile <= H264PROFILE_HIGH) { |
1153 profile <= media::H264PROFILE_HIGH) { | |
1154 // Windows Media Foundation H.264 decoding does not support decoding videos | 1152 // Windows Media Foundation H.264 decoding does not support decoding videos |
1155 // with any dimension smaller than 48 pixels: | 1153 // with any dimension smaller than 48 pixels: |
1156 // http://msdn.microsoft.com/en-us/library/windows/desktop/dd797815 | 1154 // http://msdn.microsoft.com/en-us/library/windows/desktop/dd797815 |
1157 min_resolution = std::make_pair(48, 48); | 1155 min_resolution = std::make_pair(48, 48); |
1158 } else { | 1156 } else { |
1159 // TODO(ananta) | 1157 // TODO(ananta) |
1160 // Detect this properly for VP8/VP9 profiles. | 1158 // Detect this properly for VP8/VP9 profiles. |
1161 min_resolution = std::make_pair(16, 16); | 1159 min_resolution = std::make_pair(16, 16); |
1162 } | 1160 } |
1163 return min_resolution; | 1161 return min_resolution; |
1164 } | 1162 } |
1165 | 1163 |
1166 // static | 1164 // static |
1167 std::pair<int, int> DXVAVideoDecodeAccelerator::GetMaxResolution( | 1165 std::pair<int, int> DXVAVideoDecodeAccelerator::GetMaxResolution( |
1168 const media::VideoCodecProfile profile) { | 1166 const VideoCodecProfile profile) { |
1169 TRACE_EVENT0("gpu,startup", "DXVAVideoDecodeAccelerator::GetMaxResolution"); | 1167 TRACE_EVENT0("gpu,startup", "DXVAVideoDecodeAccelerator::GetMaxResolution"); |
1170 std::pair<int, int> max_resolution; | 1168 std::pair<int, int> max_resolution; |
1171 if (profile >= media::H264PROFILE_BASELINE && | 1169 if (profile >= H264PROFILE_BASELINE && profile <= H264PROFILE_HIGH) { |
1172 profile <= media::H264PROFILE_HIGH) { | |
1173 max_resolution = GetMaxH264Resolution(); | 1170 max_resolution = GetMaxH264Resolution(); |
1174 } else { | 1171 } else { |
1175 // TODO(ananta) | 1172 // TODO(ananta) |
1176 // Detect this properly for VP8/VP9 profiles. | 1173 // Detect this properly for VP8/VP9 profiles. |
1177 max_resolution = std::make_pair(4096, 2160); | 1174 max_resolution = std::make_pair(4096, 2160); |
1178 } | 1175 } |
1179 return max_resolution; | 1176 return max_resolution; |
1180 } | 1177 } |
1181 | 1178 |
1182 std::pair<int, int> DXVAVideoDecodeAccelerator::GetMaxH264Resolution() { | 1179 std::pair<int, int> DXVAVideoDecodeAccelerator::GetMaxH264Resolution() { |
(...skipping 154 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1337 for (size_t i = 0; i < arraysize(g_IntelLegacyGPUList); i++) { | 1334 for (size_t i = 0; i < arraysize(g_IntelLegacyGPUList); i++) { |
1338 if (adapter_desc.DeviceId == g_IntelLegacyGPUList[i]) | 1335 if (adapter_desc.DeviceId == g_IntelLegacyGPUList[i]) |
1339 return legacy_gpu; | 1336 return legacy_gpu; |
1340 } | 1337 } |
1341 } | 1338 } |
1342 } | 1339 } |
1343 legacy_gpu = false; | 1340 legacy_gpu = false; |
1344 return legacy_gpu; | 1341 return legacy_gpu; |
1345 } | 1342 } |
1346 | 1343 |
1347 bool DXVAVideoDecodeAccelerator::InitDecoder(media::VideoCodecProfile profile) { | 1344 bool DXVAVideoDecodeAccelerator::InitDecoder(VideoCodecProfile profile) { |
1348 HMODULE decoder_dll = NULL; | 1345 HMODULE decoder_dll = NULL; |
1349 | 1346 |
1350 CLSID clsid = {}; | 1347 CLSID clsid = {}; |
1351 | 1348 |
1352 // Profile must fall within the valid range for one of the supported codecs. | 1349 // Profile must fall within the valid range for one of the supported codecs. |
1353 if (profile >= media::H264PROFILE_MIN && profile <= media::H264PROFILE_MAX) { | 1350 if (profile >= H264PROFILE_MIN && profile <= H264PROFILE_MAX) { |
1354 // We mimic the steps CoCreateInstance uses to instantiate the object. This | 1351 // We mimic the steps CoCreateInstance uses to instantiate the object. This |
1355 // was previously done because it failed inside the sandbox, and now is done | 1352 // was previously done because it failed inside the sandbox, and now is done |
1356 // as a more minimal approach to avoid other side-effects CCI might have (as | 1353 // as a more minimal approach to avoid other side-effects CCI might have (as |
1357 // we are still in a reduced sandbox). | 1354 // we are still in a reduced sandbox). |
1358 decoder_dll = ::GetModuleHandle(L"msmpeg2vdec.dll"); | 1355 decoder_dll = ::GetModuleHandle(L"msmpeg2vdec.dll"); |
1359 RETURN_ON_FAILURE(decoder_dll, | 1356 RETURN_ON_FAILURE(decoder_dll, |
1360 "msmpeg2vdec.dll required for decoding is not loaded", | 1357 "msmpeg2vdec.dll required for decoding is not loaded", |
1361 false); | 1358 false); |
1362 | 1359 |
1363 // Check version of DLL, version 6.1.7140 is blacklisted due to high crash | 1360 // Check version of DLL, version 6.1.7140 is blacklisted due to high crash |
1364 // rates in browsers loading that DLL. If that is the version installed we | 1361 // rates in browsers loading that DLL. If that is the version installed we |
1365 // fall back to software decoding. See crbug/403440. | 1362 // fall back to software decoding. See crbug/403440. |
1366 std::unique_ptr<FileVersionInfo> version_info( | 1363 std::unique_ptr<FileVersionInfo> version_info( |
1367 FileVersionInfo::CreateFileVersionInfoForModule(decoder_dll)); | 1364 FileVersionInfo::CreateFileVersionInfoForModule(decoder_dll)); |
1368 RETURN_ON_FAILURE(version_info, "unable to get version of msmpeg2vdec.dll", | 1365 RETURN_ON_FAILURE(version_info, "unable to get version of msmpeg2vdec.dll", |
1369 false); | 1366 false); |
1370 base::string16 file_version = version_info->file_version(); | 1367 base::string16 file_version = version_info->file_version(); |
1371 RETURN_ON_FAILURE(file_version.find(L"6.1.7140") == base::string16::npos, | 1368 RETURN_ON_FAILURE(file_version.find(L"6.1.7140") == base::string16::npos, |
1372 "blacklisted version of msmpeg2vdec.dll 6.1.7140", false); | 1369 "blacklisted version of msmpeg2vdec.dll 6.1.7140", false); |
1373 codec_ = media::kCodecH264; | 1370 codec_ = kCodecH264; |
1374 clsid = __uuidof(CMSH264DecoderMFT); | 1371 clsid = __uuidof(CMSH264DecoderMFT); |
1375 } else if (enable_accelerated_vpx_decode_ && | 1372 } else if (enable_accelerated_vpx_decode_ && |
1376 (profile == media::VP8PROFILE_ANY || | 1373 (profile == VP8PROFILE_ANY || profile == VP9PROFILE_PROFILE0 || |
1377 profile == media::VP9PROFILE_PROFILE0 || | 1374 profile == VP9PROFILE_PROFILE1 || |
1378 profile == media::VP9PROFILE_PROFILE1 || | 1375 profile == VP9PROFILE_PROFILE2 || |
1379 profile == media::VP9PROFILE_PROFILE2 || | 1376 profile == VP9PROFILE_PROFILE3)) { |
1380 profile == media::VP9PROFILE_PROFILE3)) { | |
1381 int program_files_key = base::DIR_PROGRAM_FILES; | 1377 int program_files_key = base::DIR_PROGRAM_FILES; |
1382 if (base::win::OSInfo::GetInstance()->wow64_status() == | 1378 if (base::win::OSInfo::GetInstance()->wow64_status() == |
1383 base::win::OSInfo::WOW64_ENABLED) { | 1379 base::win::OSInfo::WOW64_ENABLED) { |
1384 program_files_key = base::DIR_PROGRAM_FILES6432; | 1380 program_files_key = base::DIR_PROGRAM_FILES6432; |
1385 } | 1381 } |
1386 | 1382 |
1387 base::FilePath dll_path; | 1383 base::FilePath dll_path; |
1388 RETURN_ON_FAILURE(PathService::Get(program_files_key, &dll_path), | 1384 RETURN_ON_FAILURE(PathService::Get(program_files_key, &dll_path), |
1389 "failed to get path for Program Files", false); | 1385 "failed to get path for Program Files", false); |
1390 | 1386 |
1391 dll_path = dll_path.Append(kVPXDecoderDLLPath); | 1387 dll_path = dll_path.Append(kVPXDecoderDLLPath); |
1392 if (profile == media::VP8PROFILE_ANY) { | 1388 if (profile == VP8PROFILE_ANY) { |
1393 codec_ = media::kCodecVP8; | 1389 codec_ = kCodecVP8; |
1394 dll_path = dll_path.Append(kVP8DecoderDLLName); | 1390 dll_path = dll_path.Append(kVP8DecoderDLLName); |
1395 clsid = CLSID_WebmMfVp8Dec; | 1391 clsid = CLSID_WebmMfVp8Dec; |
1396 } else { | 1392 } else { |
1397 codec_ = media::kCodecVP9; | 1393 codec_ = kCodecVP9; |
1398 dll_path = dll_path.Append(kVP9DecoderDLLName); | 1394 dll_path = dll_path.Append(kVP9DecoderDLLName); |
1399 clsid = CLSID_WebmMfVp9Dec; | 1395 clsid = CLSID_WebmMfVp9Dec; |
1400 } | 1396 } |
1401 decoder_dll = ::LoadLibraryEx(dll_path.value().data(), NULL, | 1397 decoder_dll = ::LoadLibraryEx(dll_path.value().data(), NULL, |
1402 LOAD_WITH_ALTERED_SEARCH_PATH); | 1398 LOAD_WITH_ALTERED_SEARCH_PATH); |
1403 RETURN_ON_FAILURE(decoder_dll, "vpx decoder dll is not loaded", false); | 1399 RETURN_ON_FAILURE(decoder_dll, "vpx decoder dll is not loaded", false); |
1404 } else { | 1400 } else { |
1405 RETURN_ON_FAILURE(false, "Unsupported codec.", false); | 1401 RETURN_ON_FAILURE(false, "Unsupported codec.", false); |
1406 } | 1402 } |
1407 | 1403 |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1456 | 1452 |
1457 bool DXVAVideoDecodeAccelerator::CheckDecoderDxvaSupport() { | 1453 bool DXVAVideoDecodeAccelerator::CheckDecoderDxvaSupport() { |
1458 base::win::ScopedComPtr<IMFAttributes> attributes; | 1454 base::win::ScopedComPtr<IMFAttributes> attributes; |
1459 HRESULT hr = decoder_->GetAttributes(attributes.Receive()); | 1455 HRESULT hr = decoder_->GetAttributes(attributes.Receive()); |
1460 RETURN_ON_HR_FAILURE(hr, "Failed to get decoder attributes", false); | 1456 RETURN_ON_HR_FAILURE(hr, "Failed to get decoder attributes", false); |
1461 | 1457 |
1462 UINT32 dxva = 0; | 1458 UINT32 dxva = 0; |
1463 hr = attributes->GetUINT32(MF_SA_D3D_AWARE, &dxva); | 1459 hr = attributes->GetUINT32(MF_SA_D3D_AWARE, &dxva); |
1464 RETURN_ON_HR_FAILURE(hr, "Failed to check if decoder supports DXVA", false); | 1460 RETURN_ON_HR_FAILURE(hr, "Failed to check if decoder supports DXVA", false); |
1465 | 1461 |
1466 if (codec_ == media::kCodecH264) { | 1462 if (codec_ == kCodecH264) { |
1467 hr = attributes->SetUINT32(CODECAPI_AVDecVideoAcceleration_H264, TRUE); | 1463 hr = attributes->SetUINT32(CODECAPI_AVDecVideoAcceleration_H264, TRUE); |
1468 RETURN_ON_HR_FAILURE(hr, "Failed to enable DXVA H/W decoding", false); | 1464 RETURN_ON_HR_FAILURE(hr, "Failed to enable DXVA H/W decoding", false); |
1469 } | 1465 } |
1470 | 1466 |
1471 hr = attributes->SetUINT32(CODECAPI_AVLowLatencyMode, TRUE); | 1467 hr = attributes->SetUINT32(CODECAPI_AVLowLatencyMode, TRUE); |
1472 if (SUCCEEDED(hr)) { | 1468 if (SUCCEEDED(hr)) { |
1473 DVLOG(1) << "Successfully set Low latency mode on decoder."; | 1469 DVLOG(1) << "Successfully set Low latency mode on decoder."; |
1474 } else { | 1470 } else { |
1475 DVLOG(1) << "Failed to set Low latency mode on decoder. Error: " << hr; | 1471 DVLOG(1) << "Failed to set Low latency mode on decoder. Error: " << hr; |
1476 } | 1472 } |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1511 } | 1507 } |
1512 | 1508 |
1513 bool DXVAVideoDecodeAccelerator::SetDecoderInputMediaType() { | 1509 bool DXVAVideoDecodeAccelerator::SetDecoderInputMediaType() { |
1514 base::win::ScopedComPtr<IMFMediaType> media_type; | 1510 base::win::ScopedComPtr<IMFMediaType> media_type; |
1515 HRESULT hr = MFCreateMediaType(media_type.Receive()); | 1511 HRESULT hr = MFCreateMediaType(media_type.Receive()); |
1516 RETURN_ON_HR_FAILURE(hr, "MFCreateMediaType failed", false); | 1512 RETURN_ON_HR_FAILURE(hr, "MFCreateMediaType failed", false); |
1517 | 1513 |
1518 hr = media_type->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Video); | 1514 hr = media_type->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Video); |
1519 RETURN_ON_HR_FAILURE(hr, "Failed to set major input type", false); | 1515 RETURN_ON_HR_FAILURE(hr, "Failed to set major input type", false); |
1520 | 1516 |
1521 if (codec_ == media::kCodecH264) { | 1517 if (codec_ == kCodecH264) { |
1522 hr = media_type->SetGUID(MF_MT_SUBTYPE, MFVideoFormat_H264); | 1518 hr = media_type->SetGUID(MF_MT_SUBTYPE, MFVideoFormat_H264); |
1523 } else if (codec_ == media::kCodecVP8) { | 1519 } else if (codec_ == kCodecVP8) { |
1524 hr = media_type->SetGUID(MF_MT_SUBTYPE, MEDIASUBTYPE_VP80); | 1520 hr = media_type->SetGUID(MF_MT_SUBTYPE, MEDIASUBTYPE_VP80); |
1525 } else if (codec_ == media::kCodecVP9) { | 1521 } else if (codec_ == kCodecVP9) { |
1526 hr = media_type->SetGUID(MF_MT_SUBTYPE, MEDIASUBTYPE_VP90); | 1522 hr = media_type->SetGUID(MF_MT_SUBTYPE, MEDIASUBTYPE_VP90); |
1527 } else { | 1523 } else { |
1528 NOTREACHED(); | 1524 NOTREACHED(); |
1529 RETURN_ON_FAILURE(false, "Unsupported codec on input media type.", false); | 1525 RETURN_ON_FAILURE(false, "Unsupported codec on input media type.", false); |
1530 } | 1526 } |
1531 RETURN_ON_HR_FAILURE(hr, "Failed to set subtype", false); | 1527 RETURN_ON_HR_FAILURE(hr, "Failed to set subtype", false); |
1532 | 1528 |
1533 // Not sure about this. msdn recommends setting this value on the input | 1529 // Not sure about this. msdn recommends setting this value on the input |
1534 // media type. | 1530 // media type. |
1535 hr = media_type->SetUINT32(MF_MT_INTERLACE_MODE, | 1531 hr = media_type->SetUINT32(MF_MT_INTERLACE_MODE, |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1568 // sure they're the correct size. We only provide decoding if DXVA is enabled. | 1564 // sure they're the correct size. We only provide decoding if DXVA is enabled. |
1569 bool DXVAVideoDecodeAccelerator::GetStreamsInfoAndBufferReqs() { | 1565 bool DXVAVideoDecodeAccelerator::GetStreamsInfoAndBufferReqs() { |
1570 HRESULT hr = decoder_->GetInputStreamInfo(0, &input_stream_info_); | 1566 HRESULT hr = decoder_->GetInputStreamInfo(0, &input_stream_info_); |
1571 RETURN_ON_HR_FAILURE(hr, "Failed to get input stream info", false); | 1567 RETURN_ON_HR_FAILURE(hr, "Failed to get input stream info", false); |
1572 | 1568 |
1573 hr = decoder_->GetOutputStreamInfo(0, &output_stream_info_); | 1569 hr = decoder_->GetOutputStreamInfo(0, &output_stream_info_); |
1574 RETURN_ON_HR_FAILURE(hr, "Failed to get decoder output stream info", false); | 1570 RETURN_ON_HR_FAILURE(hr, "Failed to get decoder output stream info", false); |
1575 | 1571 |
1576 DVLOG(1) << "Input stream info: "; | 1572 DVLOG(1) << "Input stream info: "; |
1577 DVLOG(1) << "Max latency: " << input_stream_info_.hnsMaxLatency; | 1573 DVLOG(1) << "Max latency: " << input_stream_info_.hnsMaxLatency; |
1578 if (codec_ == media::kCodecH264) { | 1574 if (codec_ == kCodecH264) { |
1579 // There should be three flags, one for requiring a whole frame be in a | 1575 // There should be three flags, one for requiring a whole frame be in a |
1580 // single sample, one for requiring there be one buffer only in a single | 1576 // single sample, one for requiring there be one buffer only in a single |
1581 // sample, and one that specifies a fixed sample size. (as in cbSize) | 1577 // sample, and one that specifies a fixed sample size. (as in cbSize) |
1582 CHECK_EQ(input_stream_info_.dwFlags, 0x7u); | 1578 CHECK_EQ(input_stream_info_.dwFlags, 0x7u); |
1583 } | 1579 } |
1584 | 1580 |
1585 DVLOG(1) << "Min buffer size: " << input_stream_info_.cbSize; | 1581 DVLOG(1) << "Min buffer size: " << input_stream_info_.cbSize; |
1586 DVLOG(1) << "Max lookahead: " << input_stream_info_.cbMaxLookahead; | 1582 DVLOG(1) << "Max lookahead: " << input_stream_info_.cbMaxLookahead; |
1587 DVLOG(1) << "Alignment: " << input_stream_info_.cbAlignment; | 1583 DVLOG(1) << "Alignment: " << input_stream_info_.cbAlignment; |
1588 | 1584 |
1589 DVLOG(1) << "Output stream info: "; | 1585 DVLOG(1) << "Output stream info: "; |
1590 // The flags here should be the same and mean the same thing, except when | 1586 // The flags here should be the same and mean the same thing, except when |
1591 // DXVA is enabled, there is an extra 0x100 flag meaning decoder will | 1587 // DXVA is enabled, there is an extra 0x100 flag meaning decoder will |
1592 // allocate its own sample. | 1588 // allocate its own sample. |
1593 DVLOG(1) << "Flags: " << std::hex << std::showbase | 1589 DVLOG(1) << "Flags: " << std::hex << std::showbase |
1594 << output_stream_info_.dwFlags; | 1590 << output_stream_info_.dwFlags; |
1595 if (codec_ == media::kCodecH264) { | 1591 if (codec_ == kCodecH264) { |
1596 CHECK_EQ(output_stream_info_.dwFlags, 0x107u); | 1592 CHECK_EQ(output_stream_info_.dwFlags, 0x107u); |
1597 } | 1593 } |
1598 DVLOG(1) << "Min buffer size: " << output_stream_info_.cbSize; | 1594 DVLOG(1) << "Min buffer size: " << output_stream_info_.cbSize; |
1599 DVLOG(1) << "Alignment: " << output_stream_info_.cbAlignment; | 1595 DVLOG(1) << "Alignment: " << output_stream_info_.cbAlignment; |
1600 return true; | 1596 return true; |
1601 } | 1597 } |
1602 | 1598 |
1603 void DXVAVideoDecodeAccelerator::DoDecode() { | 1599 void DXVAVideoDecodeAccelerator::DoDecode() { |
1604 TRACE_EVENT0("media", "DXVAVideoDecodeAccelerator::DoDecode"); | 1600 TRACE_EVENT0("media", "DXVAVideoDecodeAccelerator::DoDecode"); |
1605 DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread()); | 1601 DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread()); |
(...skipping 174 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1780 index->second->CopyOutputSampleDataToPictureBuffer( | 1776 index->second->CopyOutputSampleDataToPictureBuffer( |
1781 this, surface.get(), d3d11_texture.get(), | 1777 this, surface.get(), d3d11_texture.get(), |
1782 pending_sample->input_buffer_id), | 1778 pending_sample->input_buffer_id), |
1783 "Failed to copy output sample", PLATFORM_FAILURE, ); | 1779 "Failed to copy output sample", PLATFORM_FAILURE, ); |
1784 | 1780 |
1785 } | 1781 } |
1786 } | 1782 } |
1787 } | 1783 } |
1788 | 1784 |
1789 void DXVAVideoDecodeAccelerator::StopOnError( | 1785 void DXVAVideoDecodeAccelerator::StopOnError( |
1790 media::VideoDecodeAccelerator::Error error) { | 1786 VideoDecodeAccelerator::Error error) { |
1791 if (!main_thread_task_runner_->BelongsToCurrentThread()) { | 1787 if (!main_thread_task_runner_->BelongsToCurrentThread()) { |
1792 main_thread_task_runner_->PostTask( | 1788 main_thread_task_runner_->PostTask( |
1793 FROM_HERE, base::Bind(&DXVAVideoDecodeAccelerator::StopOnError, | 1789 FROM_HERE, base::Bind(&DXVAVideoDecodeAccelerator::StopOnError, |
1794 weak_this_factory_.GetWeakPtr(), error)); | 1790 weak_this_factory_.GetWeakPtr(), error)); |
1795 return; | 1791 return; |
1796 } | 1792 } |
1797 | 1793 |
1798 if (client_) | 1794 if (client_) |
1799 client_->NotifyError(error); | 1795 client_->NotifyError(error); |
1800 client_ = NULL; | 1796 client_ = NULL; |
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1893 } | 1889 } |
1894 } | 1890 } |
1895 | 1891 |
1896 void DXVAVideoDecodeAccelerator::NotifyPictureReady(int picture_buffer_id, | 1892 void DXVAVideoDecodeAccelerator::NotifyPictureReady(int picture_buffer_id, |
1897 int input_buffer_id) { | 1893 int input_buffer_id) { |
1898 DCHECK(main_thread_task_runner_->BelongsToCurrentThread()); | 1894 DCHECK(main_thread_task_runner_->BelongsToCurrentThread()); |
1899 // This task could execute after the decoder has been torn down. | 1895 // This task could execute after the decoder has been torn down. |
1900 if (GetState() != kUninitialized && client_) { | 1896 if (GetState() != kUninitialized && client_) { |
1901 // TODO(henryhsu): Use correct visible size instead of (0, 0). We can't use | 1897 // TODO(henryhsu): Use correct visible size instead of (0, 0). We can't use |
1902 // coded size here so use (0, 0) intentionally to have the client choose. | 1898 // coded size here so use (0, 0) intentionally to have the client choose. |
1903 media::Picture picture(picture_buffer_id, input_buffer_id, gfx::Rect(0, 0), | 1899 Picture picture(picture_buffer_id, input_buffer_id, gfx::Rect(0, 0), false); |
1904 false); | |
1905 client_->PictureReady(picture); | 1900 client_->PictureReady(picture); |
1906 } | 1901 } |
1907 } | 1902 } |
1908 | 1903 |
1909 void DXVAVideoDecodeAccelerator::NotifyInputBuffersDropped() { | 1904 void DXVAVideoDecodeAccelerator::NotifyInputBuffersDropped() { |
1910 DCHECK(main_thread_task_runner_->BelongsToCurrentThread()); | 1905 DCHECK(main_thread_task_runner_->BelongsToCurrentThread()); |
1911 if (!client_) | 1906 if (!client_) |
1912 return; | 1907 return; |
1913 | 1908 |
1914 for (PendingInputs::iterator it = pending_input_buffers_.begin(); | 1909 for (PendingInputs::iterator it = pending_input_buffers_.begin(); |
(...skipping 712 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2627 RETURN_ON_HR_FAILURE(hr, "Failed to set output type", false); | 2622 RETURN_ON_HR_FAILURE(hr, "Failed to set output type", false); |
2628 return true; | 2623 return true; |
2629 } | 2624 } |
2630 media_type.Release(); | 2625 media_type.Release(); |
2631 } | 2626 } |
2632 return false; | 2627 return false; |
2633 } | 2628 } |
2634 | 2629 |
2635 HRESULT DXVAVideoDecodeAccelerator::CheckConfigChanged(IMFSample* sample, | 2630 HRESULT DXVAVideoDecodeAccelerator::CheckConfigChanged(IMFSample* sample, |
2636 bool* config_changed) { | 2631 bool* config_changed) { |
2637 if (codec_ != media::kCodecH264) | 2632 if (codec_ != kCodecH264) |
2638 return S_FALSE; | 2633 return S_FALSE; |
2639 | 2634 |
2640 base::win::ScopedComPtr<IMFMediaBuffer> buffer; | 2635 base::win::ScopedComPtr<IMFMediaBuffer> buffer; |
2641 HRESULT hr = sample->GetBufferByIndex(0, buffer.Receive()); | 2636 HRESULT hr = sample->GetBufferByIndex(0, buffer.Receive()); |
2642 RETURN_ON_HR_FAILURE(hr, "Failed to get buffer from input sample", hr); | 2637 RETURN_ON_HR_FAILURE(hr, "Failed to get buffer from input sample", hr); |
2643 | 2638 |
2644 MediaBufferScopedPointer scoped_media_buffer(buffer.get()); | 2639 MediaBufferScopedPointer scoped_media_buffer(buffer.get()); |
2645 | 2640 |
2646 if (!config_change_detector_->DetectConfig( | 2641 if (!config_change_detector_->DetectConfig( |
2647 scoped_media_buffer.get(), scoped_media_buffer.current_length())) { | 2642 scoped_media_buffer.get(), scoped_media_buffer.current_length())) { |
(...skipping 10 matching lines...) Expand all Loading... |
2658 SetState(kConfigChange); | 2653 SetState(kConfigChange); |
2659 Invalidate(); | 2654 Invalidate(); |
2660 Initialize(config_, client_); | 2655 Initialize(config_, client_); |
2661 decoder_thread_task_runner_->PostTask( | 2656 decoder_thread_task_runner_->PostTask( |
2662 FROM_HERE, | 2657 FROM_HERE, |
2663 base::Bind(&DXVAVideoDecodeAccelerator::DecodePendingInputBuffers, | 2658 base::Bind(&DXVAVideoDecodeAccelerator::DecodePendingInputBuffers, |
2664 base::Unretained(this))); | 2659 base::Unretained(this))); |
2665 } | 2660 } |
2666 | 2661 |
2667 } // namespace media | 2662 } // namespace media |
OLD | NEW |