| OLD | NEW |
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 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/media_foundation_video_encode_accelerator_win.h" | 5 #include "media/gpu/media_foundation_video_encode_accelerator_win.h" |
| 6 | 6 |
| 7 #pragma warning(push) | 7 #pragma warning(push) |
| 8 #pragma warning(disable : 4800) // Disable warning for added padding. | 8 #pragma warning(disable : 4800) // Disable warning for added padding. |
| 9 | 9 |
| 10 #include <codecapi.h> | 10 #include <codecapi.h> |
| (...skipping 16 matching lines...) Expand all Loading... |
| 27 using base::win::ScopedComPtr; | 27 using base::win::ScopedComPtr; |
| 28 using media::mf::MediaBufferScopedPointer; | 28 using media::mf::MediaBufferScopedPointer; |
| 29 | 29 |
| 30 namespace media { | 30 namespace media { |
| 31 | 31 |
| 32 namespace { | 32 namespace { |
| 33 | 33 |
| 34 const int32_t kDefaultTargetBitrate = 5000000; | 34 const int32_t kDefaultTargetBitrate = 5000000; |
| 35 const size_t kMaxFrameRateNumerator = 30; | 35 const size_t kMaxFrameRateNumerator = 30; |
| 36 const size_t kMaxFrameRateDenominator = 1; | 36 const size_t kMaxFrameRateDenominator = 1; |
| 37 const size_t kMaxResolutionWidth = 3840; | 37 const size_t kMaxResolutionWidth = 1920; |
| 38 const size_t kMaxResolutionHeight = 2176; | 38 const size_t kMaxResolutionHeight = 1088; |
| 39 const size_t kNumInputBuffers = 3; | 39 const size_t kNumInputBuffers = 3; |
| 40 // Media Foundation uses 100 nanosecond units for time, see | 40 // Media Foundation uses 100 nanosecond units for time, see |
| 41 // https://msdn.microsoft.com/en-us/library/windows/desktop/ms697282(v=vs.85).as
px | 41 // https://msdn.microsoft.com/en-us/library/windows/desktop/ms697282(v=vs.85).as
px |
| 42 const size_t kOneMicrosecondInMFSampleTimeUnits = 10; | 42 const size_t kOneMicrosecondInMFSampleTimeUnits = 10; |
| 43 const size_t kOutputSampleBufferSizeRatio = 4; | 43 const size_t kOutputSampleBufferSizeRatio = 4; |
| 44 | 44 |
| 45 constexpr const wchar_t* const kMediaFoundationVideoEncoderDLLs[] = { | 45 constexpr const wchar_t* const kMediaFoundationVideoEncoderDLLs[] = { |
| 46 L"mf.dll", L"mfplat.dll", | 46 L"mf.dll", L"mfplat.dll", |
| 47 }; | 47 }; |
| 48 | 48 |
| 49 // Resolutions that some platforms support, should be listed in ascending order. |
| 50 constexpr const gfx::Size kOptionalMaxResolutions[] = {gfx::Size(3840, 2176)}; |
| 51 |
| 49 } // namespace | 52 } // namespace |
| 50 | 53 |
| 51 class MediaFoundationVideoEncodeAccelerator::EncodeOutput { | 54 class MediaFoundationVideoEncodeAccelerator::EncodeOutput { |
| 52 public: | 55 public: |
| 53 EncodeOutput(uint32_t size, bool key_frame, base::TimeDelta timestamp) | 56 EncodeOutput(uint32_t size, bool key_frame, base::TimeDelta timestamp) |
| 54 : keyframe(key_frame), capture_timestamp(timestamp), data_(size) {} | 57 : keyframe(key_frame), capture_timestamp(timestamp), data_(size) {} |
| 55 | 58 |
| 56 uint8_t* memory() { return data_.data(); } | 59 uint8_t* memory() { return data_.data(); } |
| 57 | 60 |
| 58 int size() const { return static_cast<int>(data_.size()); } | 61 int size() const { return static_cast<int>(data_.size()); } |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 94 } | 97 } |
| 95 | 98 |
| 96 VideoEncodeAccelerator::SupportedProfiles | 99 VideoEncodeAccelerator::SupportedProfiles |
| 97 MediaFoundationVideoEncodeAccelerator::GetSupportedProfiles() { | 100 MediaFoundationVideoEncodeAccelerator::GetSupportedProfiles() { |
| 98 TRACE_EVENT0("gpu,startup", | 101 TRACE_EVENT0("gpu,startup", |
| 99 "MediaFoundationVideoEncodeAccelerator::GetSupportedProfiles"); | 102 "MediaFoundationVideoEncodeAccelerator::GetSupportedProfiles"); |
| 100 DVLOG(3) << __func__; | 103 DVLOG(3) << __func__; |
| 101 DCHECK(main_client_task_runner_->BelongsToCurrentThread()); | 104 DCHECK(main_client_task_runner_->BelongsToCurrentThread()); |
| 102 | 105 |
| 103 SupportedProfiles profiles; | 106 SupportedProfiles profiles; |
| 104 | |
| 105 target_bitrate_ = kDefaultTargetBitrate; | 107 target_bitrate_ = kDefaultTargetBitrate; |
| 106 frame_rate_ = kMaxFrameRateNumerator / kMaxFrameRateDenominator; | 108 frame_rate_ = kMaxFrameRateNumerator / kMaxFrameRateDenominator; |
| 107 input_visible_size_ = gfx::Size(kMaxResolutionWidth, kMaxResolutionHeight); | 109 input_visible_size_ = gfx::Size(kMaxResolutionWidth, kMaxResolutionHeight); |
| 108 if (!CreateHardwareEncoderMFT() || !SetEncoderModes() || | 110 if (!CreateHardwareEncoderMFT() || !SetEncoderModes() || |
| 109 !InitializeInputOutputSamples()) { | 111 !InitializeInputOutputSamples()) { |
| 110 ReleaseEncoderResources(); | 112 ReleaseEncoderResources(); |
| 111 DVLOG(1) | 113 DVLOG(1) |
| 112 << "Hardware encode acceleration is not available on this platform."; | 114 << "Hardware encode acceleration is not available on this platform."; |
| 113 return profiles; | 115 return profiles; |
| 114 } | 116 } |
| 117 |
| 118 gfx::Size highest_supported_resolution = input_visible_size_; |
| 119 for (const auto& resolution : kOptionalMaxResolutions) { |
| 120 DCHECK_GT(resolution.GetArea(), highest_supported_resolution.GetArea()); |
| 121 if (!IsResolutionSupported(resolution)) |
| 122 break; |
| 123 highest_supported_resolution = resolution; |
| 124 } |
| 115 ReleaseEncoderResources(); | 125 ReleaseEncoderResources(); |
| 116 | 126 |
| 117 SupportedProfile profile; | 127 SupportedProfile profile; |
| 118 // More profiles can be supported here, but they should be available in SW | 128 // More profiles can be supported here, but they should be available in SW |
| 119 // fallback as well. | 129 // fallback as well. |
| 120 profile.profile = H264PROFILE_BASELINE; | 130 profile.profile = H264PROFILE_BASELINE; |
| 121 profile.max_framerate_numerator = kMaxFrameRateNumerator; | 131 profile.max_framerate_numerator = kMaxFrameRateNumerator; |
| 122 profile.max_framerate_denominator = kMaxFrameRateDenominator; | 132 profile.max_framerate_denominator = kMaxFrameRateDenominator; |
| 123 profile.max_resolution = gfx::Size(kMaxResolutionWidth, kMaxResolutionHeight); | 133 profile.max_resolution = highest_supported_resolution; |
| 124 profiles.push_back(profile); | 134 profiles.push_back(profile); |
| 125 return profiles; | 135 return profiles; |
| 126 } | 136 } |
| 127 | 137 |
| 128 bool MediaFoundationVideoEncodeAccelerator::Initialize( | 138 bool MediaFoundationVideoEncodeAccelerator::Initialize( |
| 129 VideoPixelFormat format, | 139 VideoPixelFormat format, |
| 130 const gfx::Size& input_visible_size, | 140 const gfx::Size& input_visible_size, |
| 131 VideoCodecProfile output_profile, | 141 VideoCodecProfile output_profile, |
| 132 uint32_t initial_bitrate, | 142 uint32_t initial_bitrate, |
| 133 Client* client) { | 143 Client* client) { |
| (...skipping 308 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 442 var.ulVal = eAVEncAdaptiveMode_Resolution; | 452 var.ulVal = eAVEncAdaptiveMode_Resolution; |
| 443 hr = codec_api_->SetValue(&CODECAPI_AVEncAdaptiveMode, &var); | 453 hr = codec_api_->SetValue(&CODECAPI_AVEncAdaptiveMode, &var); |
| 444 RETURN_ON_HR_FAILURE(hr, "Couldn't set FrameRate", false); | 454 RETURN_ON_HR_FAILURE(hr, "Couldn't set FrameRate", false); |
| 445 var.vt = VT_BOOL; | 455 var.vt = VT_BOOL; |
| 446 var.boolVal = VARIANT_TRUE; | 456 var.boolVal = VARIANT_TRUE; |
| 447 hr = codec_api_->SetValue(&CODECAPI_AVLowLatencyMode, &var); | 457 hr = codec_api_->SetValue(&CODECAPI_AVLowLatencyMode, &var); |
| 448 RETURN_ON_HR_FAILURE(hr, "Couldn't set LowLatencyMode", false); | 458 RETURN_ON_HR_FAILURE(hr, "Couldn't set LowLatencyMode", false); |
| 449 return SUCCEEDED(hr); | 459 return SUCCEEDED(hr); |
| 450 } | 460 } |
| 451 | 461 |
| 462 bool MediaFoundationVideoEncodeAccelerator::IsResolutionSupported( |
| 463 const gfx::Size& resolution) { |
| 464 DCHECK(main_client_task_runner_->BelongsToCurrentThread()); |
| 465 DCHECK(encoder_); |
| 466 |
| 467 HRESULT hr = |
| 468 MFSetAttributeSize(imf_output_media_type_.get(), MF_MT_FRAME_SIZE, |
| 469 resolution.width(), resolution.height()); |
| 470 RETURN_ON_HR_FAILURE(hr, "Couldn't set frame size", false); |
| 471 hr = encoder_->SetOutputType(output_stream_id_, imf_output_media_type_.get(), |
| 472 0); |
| 473 RETURN_ON_HR_FAILURE(hr, "Couldn't set output media type", false); |
| 474 |
| 475 hr = MFSetAttributeSize(imf_input_media_type_.get(), MF_MT_FRAME_SIZE, |
| 476 resolution.width(), resolution.height()); |
| 477 RETURN_ON_HR_FAILURE(hr, "Couldn't set frame size", false); |
| 478 hr = encoder_->SetInputType(input_stream_id_, imf_input_media_type_.get(), 0); |
| 479 RETURN_ON_HR_FAILURE(hr, "Couldn't set input media type", false); |
| 480 |
| 481 return true; |
| 482 } |
| 483 |
| 452 void MediaFoundationVideoEncodeAccelerator::NotifyError( | 484 void MediaFoundationVideoEncodeAccelerator::NotifyError( |
| 453 VideoEncodeAccelerator::Error error) { | 485 VideoEncodeAccelerator::Error error) { |
| 454 DCHECK(encoder_thread_task_runner_->BelongsToCurrentThread()); | 486 DCHECK(encoder_thread_task_runner_->BelongsToCurrentThread()); |
| 455 main_client_task_runner_->PostTask( | 487 main_client_task_runner_->PostTask( |
| 456 FROM_HERE, base::Bind(&Client::NotifyError, main_client_, error)); | 488 FROM_HERE, base::Bind(&Client::NotifyError, main_client_, error)); |
| 457 } | 489 } |
| 458 | 490 |
| 459 void MediaFoundationVideoEncodeAccelerator::EncodeTask( | 491 void MediaFoundationVideoEncodeAccelerator::EncodeTask( |
| 460 scoped_refptr<VideoFrame> frame, | 492 scoped_refptr<VideoFrame> frame, |
| 461 bool force_keyframe) { | 493 bool force_keyframe) { |
| (...skipping 197 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 659 void MediaFoundationVideoEncodeAccelerator::ReleaseEncoderResources() { | 691 void MediaFoundationVideoEncodeAccelerator::ReleaseEncoderResources() { |
| 660 encoder_.Release(); | 692 encoder_.Release(); |
| 661 codec_api_.Release(); | 693 codec_api_.Release(); |
| 662 imf_input_media_type_.Release(); | 694 imf_input_media_type_.Release(); |
| 663 imf_output_media_type_.Release(); | 695 imf_output_media_type_.Release(); |
| 664 input_sample_.Release(); | 696 input_sample_.Release(); |
| 665 output_sample_.Release(); | 697 output_sample_.Release(); |
| 666 } | 698 } |
| 667 | 699 |
| 668 } // namespace content | 700 } // namespace content |
| OLD | NEW |