| 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> |
| 11 #include <mferror.h> | 11 #include <mferror.h> |
| 12 #include <mftransform.h> | 12 #include <mftransform.h> |
| 13 | 13 |
| 14 #include <iterator> | 14 #include <iterator> |
| 15 #include <utility> | 15 #include <utility> |
| 16 #include <vector> | 16 #include <vector> |
| 17 | 17 |
| 18 #include "base/feature_list.h" |
| 18 #include "base/threading/thread_task_runner_handle.h" | 19 #include "base/threading/thread_task_runner_handle.h" |
| 19 #include "base/trace_event/trace_event.h" | 20 #include "base/trace_event/trace_event.h" |
| 20 #include "base/win/scoped_co_mem.h" | 21 #include "base/win/scoped_co_mem.h" |
| 21 #include "base/win/scoped_variant.h" | 22 #include "base/win/scoped_variant.h" |
| 22 #include "base/win/windows_version.h" | 23 #include "base/win/windows_version.h" |
| 24 #include "media/base/media_switches.h" |
| 23 #include "media/base/win/mf_helpers.h" | 25 #include "media/base/win/mf_helpers.h" |
| 24 #include "media/base/win/mf_initializer.h" | 26 #include "media/base/win/mf_initializer.h" |
| 25 #include "third_party/libyuv/include/libyuv.h" | 27 #include "third_party/libyuv/include/libyuv.h" |
| 26 | 28 |
| 29 #undef DLOG |
| 30 #define DLOG(err) LOG(ERROR) |
| 31 #undef DVLOG |
| 32 #define DVLOG(err) LOG(ERROR) |
| 33 |
| 27 using base::win::ScopedComPtr; | 34 using base::win::ScopedComPtr; |
| 28 using media::mf::MediaBufferScopedPointer; | 35 using media::mf::MediaBufferScopedPointer; |
| 29 | 36 |
| 30 namespace media { | 37 namespace media { |
| 31 | 38 |
| 32 namespace { | 39 namespace { |
| 33 | 40 |
| 34 const int32_t kDefaultTargetBitrate = 5000000; | 41 const int32_t kDefaultTargetBitrate = 5000000; |
| 35 const size_t kMaxFrameRateNumerator = 30; | 42 const size_t kMaxFrameRateNumerator = 30; |
| 36 const size_t kMaxFrameRateDenominator = 1; | 43 const size_t kMaxFrameRateDenominator = 1; |
| 37 const size_t kMaxResolutionWidth = 1920; | 44 const size_t kMaxResolutionWidth = 1920; |
| 38 const size_t kMaxResolutionHeight = 1088; | 45 const size_t kMaxResolutionHeight = 1088; |
| 39 const size_t kNumInputBuffers = 3; | 46 const size_t kNumInputBuffers = 3; |
| 40 // Media Foundation uses 100 nanosecond units for time, see | 47 // 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 | 48 // https://msdn.microsoft.com/en-us/library/windows/desktop/ms697282(v=vs.85).as
px |
| 42 const size_t kOneMicrosecondInMFSampleTimeUnits = 10; | 49 const size_t kOneMicrosecondInMFSampleTimeUnits = 10; |
| 43 const size_t kOutputSampleBufferSizeRatio = 4; | 50 const size_t kOutputSampleBufferSizeRatio = 4; |
| 44 | 51 |
| 45 constexpr const wchar_t* const kMediaFoundationVideoEncoderDLLs[] = { | 52 constexpr const wchar_t* const kMediaFoundationVideoEncoderDLLs[] = { |
| 46 L"mf.dll", L"mfplat.dll", | 53 L"mf.dll", L"mfplat.dll", L"nvEncMFTH264.dll", |
| 47 }; | 54 }; |
| 48 | 55 |
| 49 // Resolutions that some platforms support, should be listed in ascending order. | 56 // Resolutions that some platforms support, should be listed in ascending order. |
| 50 constexpr const gfx::Size kOptionalMaxResolutions[] = {gfx::Size(3840, 2176)}; | 57 constexpr const gfx::Size kOptionalMaxResolutions[] = {gfx::Size(3840, 2176)}; |
| 51 | 58 |
| 59 constexpr const VideoCodecProfile kSupportedH264Profiles[] = { |
| 60 H264PROFILE_BASELINE}; |
| 61 constexpr const VideoCodecProfile kSupportedVPXProfiles[] = {VP8PROFILE_MIN, |
| 62 VP9PROFILE_MIN}; |
| 63 |
| 64 GUID VideoCodecProfileToGUID(VideoCodecProfile profile) { |
| 65 switch (profile) { |
| 66 case VP8PROFILE_MIN: |
| 67 return MFVideoFormat_VP80; |
| 68 case VP9PROFILE_MIN: |
| 69 return MFVideoFormat_VP90; |
| 70 case H264PROFILE_BASELINE: |
| 71 return MFVideoFormat_H264; |
| 72 default: |
| 73 NOTREACHED(); |
| 74 return MFVideoFormat_VP80; |
| 75 } |
| 76 } |
| 77 |
| 52 } // namespace | 78 } // namespace |
| 53 | 79 |
| 54 class MediaFoundationVideoEncodeAccelerator::EncodeOutput { | 80 class MediaFoundationVideoEncodeAccelerator::EncodeOutput { |
| 55 public: | 81 public: |
| 56 EncodeOutput(uint32_t size, bool key_frame, base::TimeDelta timestamp) | 82 EncodeOutput(uint32_t size, bool key_frame, base::TimeDelta timestamp) |
| 57 : keyframe(key_frame), capture_timestamp(timestamp), data_(size) {} | 83 : keyframe(key_frame), capture_timestamp(timestamp), data_(size) {} |
| 58 | 84 |
| 59 uint8_t* memory() { return data_.data(); } | 85 uint8_t* memory() { return data_.data(); } |
| 60 | 86 |
| 61 int size() const { return static_cast<int>(data_.size()); } | 87 int size() const { return static_cast<int>(data_.size()); } |
| (...skipping 14 matching lines...) Expand all Loading... |
| 76 : id(id), shm(std::move(shm)), size(size) {} | 102 : id(id), shm(std::move(shm)), size(size) {} |
| 77 const int32_t id; | 103 const int32_t id; |
| 78 const std::unique_ptr<base::SharedMemory> shm; | 104 const std::unique_ptr<base::SharedMemory> shm; |
| 79 const size_t size; | 105 const size_t size; |
| 80 | 106 |
| 81 private: | 107 private: |
| 82 DISALLOW_IMPLICIT_CONSTRUCTORS(BitstreamBufferRef); | 108 DISALLOW_IMPLICIT_CONSTRUCTORS(BitstreamBufferRef); |
| 83 }; | 109 }; |
| 84 | 110 |
| 85 MediaFoundationVideoEncodeAccelerator::MediaFoundationVideoEncodeAccelerator() | 111 MediaFoundationVideoEncodeAccelerator::MediaFoundationVideoEncodeAccelerator() |
| 86 : main_client_task_runner_(base::ThreadTaskRunnerHandle::Get()), | 112 : h264_enabled_(base::FeatureList::IsEnabled(kMediaFoundationH264Encoding)), |
| 113 vpx_enabled_(base::FeatureList::IsEnabled(kMediaFoundationVPXEncoding)), |
| 114 main_client_task_runner_(base::ThreadTaskRunnerHandle::Get()), |
| 87 encoder_thread_("MFEncoderThread"), | 115 encoder_thread_("MFEncoderThread"), |
| 88 encoder_task_weak_factory_(this) {} | 116 encoder_task_weak_factory_(this) {} |
| 89 | 117 |
| 90 MediaFoundationVideoEncodeAccelerator:: | 118 MediaFoundationVideoEncodeAccelerator:: |
| 91 ~MediaFoundationVideoEncodeAccelerator() { | 119 ~MediaFoundationVideoEncodeAccelerator() { |
| 92 DVLOG(3) << __func__; | 120 DVLOG(3) << __func__; |
| 93 DCHECK(main_client_task_runner_->BelongsToCurrentThread()); | 121 DCHECK(main_client_task_runner_->BelongsToCurrentThread()); |
| 94 | 122 |
| 95 DCHECK(!encoder_thread_.IsRunning()); | 123 DCHECK(!encoder_thread_.IsRunning()); |
| 96 DCHECK(!encoder_task_weak_factory_.HasWeakPtrs()); | 124 DCHECK(!encoder_task_weak_factory_.HasWeakPtrs()); |
| 97 } | 125 } |
| 98 | 126 |
| 99 VideoEncodeAccelerator::SupportedProfiles | 127 VideoEncodeAccelerator::SupportedProfiles |
| 100 MediaFoundationVideoEncodeAccelerator::GetSupportedProfiles() { | 128 MediaFoundationVideoEncodeAccelerator::GetSupportedProfiles() { |
| 101 TRACE_EVENT0("gpu,startup", | 129 TRACE_EVENT0("gpu,startup", |
| 102 "MediaFoundationVideoEncodeAccelerator::GetSupportedProfiles"); | 130 "MediaFoundationVideoEncodeAccelerator::GetSupportedProfiles"); |
| 103 DVLOG(3) << __func__; | 131 DVLOG(3) << __func__; |
| 104 DCHECK(main_client_task_runner_->BelongsToCurrentThread()); | 132 DCHECK(main_client_task_runner_->BelongsToCurrentThread()); |
| 105 | 133 |
| 106 SupportedProfiles profiles; | 134 SupportedProfiles profiles; |
| 107 target_bitrate_ = kDefaultTargetBitrate; | 135 std::vector<VideoCodecProfile> candidate_codecs; |
| 108 frame_rate_ = kMaxFrameRateNumerator / kMaxFrameRateDenominator; | 136 if (h264_enabled_) { |
| 109 input_visible_size_ = gfx::Size(kMaxResolutionWidth, kMaxResolutionHeight); | 137 for (const auto codec : kSupportedH264Profiles) |
| 110 if (!CreateHardwareEncoderMFT() || !SetEncoderModes() || | 138 candidate_codecs.push_back(codec); |
| 111 !InitializeInputOutputSamples()) { | 139 } |
| 112 ReleaseEncoderResources(); | 140 if (vpx_enabled_) { |
| 113 DVLOG(1) | 141 for (const auto codec : kSupportedVPXProfiles) |
| 114 << "Hardware encode acceleration is not available on this platform."; | 142 candidate_codecs.push_back(codec); |
| 115 return profiles; | |
| 116 } | 143 } |
| 117 | 144 |
| 118 gfx::Size highest_supported_resolution = input_visible_size_; | 145 for (const auto codec : candidate_codecs) { |
| 119 for (const auto& resolution : kOptionalMaxResolutions) { | 146 output_profile_ = codec; |
| 120 DCHECK_GT(resolution.GetArea(), highest_supported_resolution.GetArea()); | 147 target_bitrate_ = kDefaultTargetBitrate; |
| 121 if (!IsResolutionSupported(resolution)) | 148 frame_rate_ = kMaxFrameRateNumerator / kMaxFrameRateDenominator; |
| 122 break; | 149 input_visible_size_ = gfx::Size(kMaxResolutionWidth, kMaxResolutionHeight); |
| 123 highest_supported_resolution = resolution; | 150 if (!CreateHardwareEncoderMFT() || !SetEncoderModes() || |
| 151 !InitializeInputOutputSamples()) { |
| 152 ReleaseEncoderResources(); |
| 153 DVLOG(1) << "Hardware encode is not available on this platform for " |
| 154 << GetProfileName(codec); |
| 155 continue; |
| 156 } |
| 157 |
| 158 gfx::Size highest_supported_resolution = input_visible_size_; |
| 159 for (const auto& resolution : kOptionalMaxResolutions) { |
| 160 DCHECK_GT(resolution.GetArea(), highest_supported_resolution.GetArea()); |
| 161 if (!IsResolutionSupported(resolution)) |
| 162 break; |
| 163 highest_supported_resolution = resolution; |
| 164 } |
| 165 ReleaseEncoderResources(); |
| 166 |
| 167 SupportedProfile profile; |
| 168 // More profiles can be supported here, but they should be available in SW |
| 169 // fallback as well. |
| 170 profile.profile = codec; |
| 171 DVLOG(1) << "Hardware encode IS available on this platform for " |
| 172 << GetProfileName(codec); |
| 173 LOG(ERROR) << highest_supported_resolution.ToString(); |
| 174 profile.max_framerate_numerator = kMaxFrameRateNumerator; |
| 175 profile.max_framerate_denominator = kMaxFrameRateDenominator; |
| 176 profile.max_resolution = highest_supported_resolution; |
| 177 profiles.push_back(profile); |
| 124 } | 178 } |
| 125 ReleaseEncoderResources(); | |
| 126 | |
| 127 SupportedProfile profile; | |
| 128 // More profiles can be supported here, but they should be available in SW | |
| 129 // fallback as well. | |
| 130 profile.profile = H264PROFILE_BASELINE; | |
| 131 profile.max_framerate_numerator = kMaxFrameRateNumerator; | |
| 132 profile.max_framerate_denominator = kMaxFrameRateDenominator; | |
| 133 profile.max_resolution = highest_supported_resolution; | |
| 134 profiles.push_back(profile); | |
| 135 return profiles; | 179 return profiles; |
| 136 } | 180 } |
| 137 | 181 |
| 138 bool MediaFoundationVideoEncodeAccelerator::Initialize( | 182 bool MediaFoundationVideoEncodeAccelerator::Initialize( |
| 139 VideoPixelFormat format, | 183 VideoPixelFormat format, |
| 140 const gfx::Size& input_visible_size, | 184 const gfx::Size& input_visible_size, |
| 141 VideoCodecProfile output_profile, | 185 VideoCodecProfile output_profile, |
| 142 uint32_t initial_bitrate, | 186 uint32_t initial_bitrate, |
| 143 Client* client) { | 187 Client* client) { |
| 144 DVLOG(3) << __func__ << ": input_format=" << VideoPixelFormatToString(format) | 188 DVLOG(3) << __func__ << ": input_format=" << VideoPixelFormatToString(format) |
| 145 << ", input_visible_size=" << input_visible_size.ToString() | 189 << ", input_visible_size=" << input_visible_size.ToString() |
| 146 << ", output_profile=" << output_profile | 190 << ", output_profile=" << output_profile |
| 147 << ", initial_bitrate=" << initial_bitrate; | 191 << ", initial_bitrate=" << initial_bitrate; |
| 148 DCHECK(main_client_task_runner_->BelongsToCurrentThread()); | 192 DCHECK(main_client_task_runner_->BelongsToCurrentThread()); |
| 149 | 193 |
| 150 if (PIXEL_FORMAT_I420 != format) { | 194 if (PIXEL_FORMAT_I420 != format) { |
| 151 DLOG(ERROR) << "Input format not supported= " | 195 DLOG(ERROR) << "Input format not supported= " |
| 152 << VideoPixelFormatToString(format); | 196 << VideoPixelFormatToString(format); |
| 153 return false; | 197 return false; |
| 154 } | 198 } |
| 155 | 199 |
| 156 if (H264PROFILE_BASELINE != output_profile) { | 200 if (!((H264PROFILE_BASELINE == output_profile && h264_enabled_) || |
| 201 ((VP8PROFILE_MIN == output_profile || |
| 202 VP9PROFILE_MIN == output_profile) && |
| 203 vpx_enabled_))) { |
| 157 DLOG(ERROR) << "Output profile not supported= " << output_profile; | 204 DLOG(ERROR) << "Output profile not supported= " << output_profile; |
| 158 return false; | 205 return false; |
| 159 } | 206 } |
| 207 output_profile_ = output_profile; |
| 160 | 208 |
| 161 encoder_thread_.init_com_with_mta(false); | 209 encoder_thread_.init_com_with_mta(false); |
| 162 if (!encoder_thread_.Start()) { | 210 if (!encoder_thread_.Start()) { |
| 163 DLOG(ERROR) << "Failed spawning encoder thread."; | 211 DLOG(ERROR) << "Failed spawning encoder thread."; |
| 164 return false; | 212 return false; |
| 165 } | 213 } |
| 166 encoder_thread_task_runner_ = encoder_thread_.task_runner(); | 214 encoder_thread_task_runner_ = encoder_thread_.task_runner(); |
| 167 | 215 |
| 168 if (!CreateHardwareEncoderMFT()) { | 216 if (!CreateHardwareEncoderMFT()) { |
| 169 DLOG(ERROR) << "Failed creating a hardware encoder MFT."; | 217 DLOG(ERROR) << "Failed creating a hardware encoder MFT."; |
| (...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 332 | 380 |
| 333 for (const wchar_t* mfdll : kMediaFoundationVideoEncoderDLLs) { | 381 for (const wchar_t* mfdll : kMediaFoundationVideoEncoderDLLs) { |
| 334 if (!::GetModuleHandle(mfdll)) { | 382 if (!::GetModuleHandle(mfdll)) { |
| 335 DVLOG(ERROR) << mfdll << " is required for encoding"; | 383 DVLOG(ERROR) << mfdll << " is required for encoding"; |
| 336 return false; | 384 return false; |
| 337 } | 385 } |
| 338 } | 386 } |
| 339 | 387 |
| 340 InitializeMediaFoundation(); | 388 InitializeMediaFoundation(); |
| 341 | 389 |
| 342 uint32_t flags = MFT_ENUM_FLAG_HARDWARE | MFT_ENUM_FLAG_SORTANDFILTER; | 390 uint32_t flags = MFT_ENUM_FLAG_SORTANDFILTER | MFT_ENUM_FLAG_SYNCMFT; |
| 391 if (output_profile_ == H264PROFILE_BASELINE) |
| 392 flags |= MFT_ENUM_FLAG_HARDWARE; |
| 343 MFT_REGISTER_TYPE_INFO input_info; | 393 MFT_REGISTER_TYPE_INFO input_info; |
| 344 input_info.guidMajorType = MFMediaType_Video; | 394 input_info.guidMajorType = MFMediaType_Video; |
| 345 input_info.guidSubtype = MFVideoFormat_NV12; | 395 input_info.guidSubtype = MFVideoFormat_NV12; |
| 346 MFT_REGISTER_TYPE_INFO output_info; | 396 MFT_REGISTER_TYPE_INFO output_info; |
| 347 output_info.guidMajorType = MFMediaType_Video; | 397 output_info.guidMajorType = MFMediaType_Video; |
| 348 output_info.guidSubtype = MFVideoFormat_H264; | 398 output_info.guidSubtype = VideoCodecProfileToGUID(output_profile_); |
| 349 | 399 |
| 350 base::win::ScopedCoMem<CLSID> CLSIDs; | 400 base::win::ScopedCoMem<IMFActivate*> devices; |
| 351 uint32_t count = 0; | 401 uint32_t count = 0; |
| 352 HRESULT hr = MFTEnum(MFT_CATEGORY_VIDEO_ENCODER, flags, &input_info, | 402 HRESULT hr = MFTEnumEx(MFT_CATEGORY_VIDEO_ENCODER, flags, &input_info, |
| 353 &output_info, NULL, &CLSIDs, &count); | 403 &output_info, &devices, &count); |
| 354 RETURN_ON_HR_FAILURE(hr, "Couldn't enumerate hardware encoder", false); | 404 RETURN_ON_HR_FAILURE(hr, "Couldn't enumerate hardware encoder", false); |
| 355 RETURN_ON_FAILURE((count > 0), "No HW encoder found", false); | 405 RETURN_ON_FAILURE((count > 0), "No HW encoder found", false); |
| 356 DVLOG(3) << "HW encoder(s) found: " << count; | 406 |
| 357 hr = encoder_.CreateInstance(CLSIDs[0]); | 407 bool succeeded = true; |
| 358 RETURN_ON_HR_FAILURE(hr, "Couldn't activate hardware encoder", false); | 408 if (count < 2) return false; |
| 359 RETURN_ON_FAILURE((encoder_.get() != nullptr), | 409 // hr = devices[0]->ActivateObject(IID_PPV_ARGS(encoder_.Receive())); |
| 360 "No HW encoder instance created", false); | 410 GUID guid = {0}; |
| 361 return true; | 411 hr = devices[1]->GetGUID(MFT_TRANSFORM_CLSID_Attribute, &guid); |
| 412 LPOLESTR name; |
| 413 StringFromCLSID(guid, &name); |
| 414 LOG(ERROR) << __func__ << name; |
| 415 RETURN_ON_HR_FAILURE(hr, "No HW encoder found", false); |
| 416 hr = encoder_.CreateInstance(guid); |
| 417 |
| 418 if (!SUCCEEDED(hr) || encoder_.get() == nullptr) { |
| 419 DLOG(ERROR) << "Couldn't activate hardware encoder, HRESULT: 0x" << std::hex |
| 420 << hr; |
| 421 succeeded = false; |
| 422 } |
| 423 for (uint32_t i = 0; i < count; ++i) |
| 424 devices[i]->Release(); |
| 425 return succeeded; |
| 362 } | 426 } |
| 363 | 427 |
| 364 bool MediaFoundationVideoEncodeAccelerator::InitializeInputOutputSamples() { | 428 bool MediaFoundationVideoEncodeAccelerator::InitializeInputOutputSamples() { |
| 365 DCHECK(main_client_task_runner_->BelongsToCurrentThread()); | 429 DCHECK(main_client_task_runner_->BelongsToCurrentThread()); |
| 366 | 430 |
| 431 base::win::ScopedComPtr<IMFAttributes> attributes; |
| 432 HRESULT hr = encoder_->GetAttributes(attributes.Receive()); |
| 433 RETURN_ON_HR_FAILURE(hr, "Couldn't get attributes", false); |
| 434 hr = attributes->SetUINT32(MF_TRANSFORM_ASYNC_UNLOCK, TRUE); |
| 435 RETURN_ON_HR_FAILURE(hr, "Couldn't unlock", false); |
| 436 |
| 367 DWORD input_count = 0; | 437 DWORD input_count = 0; |
| 368 DWORD output_count = 0; | 438 DWORD output_count = 0; |
| 369 HRESULT hr = encoder_->GetStreamCount(&input_count, &output_count); | 439 hr = encoder_->GetStreamCount(&input_count, &output_count); |
| 370 RETURN_ON_HR_FAILURE(hr, "Couldn't get stream count", false); | 440 RETURN_ON_HR_FAILURE(hr, "Couldn't get stream count", false); |
| 371 if (input_count < 1 || output_count < 1) { | 441 if (input_count < 1 || output_count < 1) { |
| 372 LOG(ERROR) << "Stream count too few: input " << input_count << ", output " | 442 LOG(ERROR) << "Stream count too few: input " << input_count << ", output " |
| 373 << output_count; | 443 << output_count; |
| 374 return false; | 444 return false; |
| 375 } | 445 } |
| 376 | 446 |
| 377 std::vector<DWORD> input_ids(input_count, 0); | 447 std::vector<DWORD> input_ids(input_count, 0); |
| 378 std::vector<DWORD> output_ids(output_count, 0); | 448 std::vector<DWORD> output_ids(output_count, 0); |
| 379 hr = encoder_->GetStreamIDs(input_count, input_ids.data(), output_count, | 449 hr = encoder_->GetStreamIDs(input_count, input_ids.data(), output_count, |
| 380 output_ids.data()); | 450 output_ids.data()); |
| 381 if (hr == S_OK) { | 451 if (hr == S_OK) { |
| 382 input_stream_id_ = input_ids[0]; | 452 input_stream_id_ = input_ids[0]; |
| 383 output_stream_id_ = output_ids[0]; | 453 output_stream_id_ = output_ids[0]; |
| 384 } else if (hr == E_NOTIMPL) { | 454 } else { |
| 385 input_stream_id_ = 0; | 455 input_stream_id_ = 0; |
| 386 output_stream_id_ = 0; | 456 output_stream_id_ = 0; |
| 387 } else { | |
| 388 LOG(ERROR) << "Couldn't find stream ids."; | |
| 389 return false; | |
| 390 } | 457 } |
| 458 // } else if (hr == E_NOTIMPL) { |
| 459 // input_stream_id_ = 0; |
| 460 // output_stream_id_ = 0; |
| 461 // } else { |
| 462 // LOG(ERROR) << "Couldn't find stream ids, HRESULT: 0x" << std::hex << |
| 463 // hr; |
| 464 // return false; |
| 465 // } |
| 391 | 466 |
| 392 // Initialize output parameters. | 467 // Initialize output parameters. |
| 393 hr = MFCreateMediaType(imf_output_media_type_.Receive()); | 468 hr = MFCreateMediaType(imf_output_media_type_.Receive()); |
| 394 RETURN_ON_HR_FAILURE(hr, "Couldn't create media type", false); | 469 RETURN_ON_HR_FAILURE(hr, "Couldn't create media type", false); |
| 395 hr = imf_output_media_type_->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Video); | 470 hr = imf_output_media_type_->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Video); |
| 396 RETURN_ON_HR_FAILURE(hr, "Couldn't set media type", false); | 471 RETURN_ON_HR_FAILURE(hr, "Couldn't set media type", false); |
| 397 hr = imf_output_media_type_->SetGUID(MF_MT_SUBTYPE, MFVideoFormat_H264); | 472 hr = imf_output_media_type_->SetGUID( |
| 473 MF_MT_SUBTYPE, VideoCodecProfileToGUID(output_profile_)); |
| 398 RETURN_ON_HR_FAILURE(hr, "Couldn't set video format", false); | 474 RETURN_ON_HR_FAILURE(hr, "Couldn't set video format", false); |
| 399 hr = imf_output_media_type_->SetUINT32(MF_MT_AVG_BITRATE, target_bitrate_); | 475 hr = imf_output_media_type_->SetUINT32(MF_MT_AVG_BITRATE, target_bitrate_); |
| 400 RETURN_ON_HR_FAILURE(hr, "Couldn't set bitrate", false); | 476 RETURN_ON_HR_FAILURE(hr, "Couldn't set bitrate", false); |
| 401 hr = MFSetAttributeRatio(imf_output_media_type_.get(), MF_MT_FRAME_RATE, | 477 hr = MFSetAttributeRatio(imf_output_media_type_.get(), MF_MT_FRAME_RATE, |
| 402 frame_rate_, 1); | 478 frame_rate_, 1); |
| 403 RETURN_ON_HR_FAILURE(hr, "Couldn't set frame rate", false); | 479 RETURN_ON_HR_FAILURE(hr, "Couldn't set frame rate", false); |
| 404 hr = MFSetAttributeSize(imf_output_media_type_.get(), MF_MT_FRAME_SIZE, | 480 hr = MFSetAttributeSize(imf_output_media_type_.get(), MF_MT_FRAME_SIZE, |
| 405 input_visible_size_.width(), | 481 input_visible_size_.width(), |
| 406 input_visible_size_.height()); | 482 input_visible_size_.height()); |
| 407 RETURN_ON_HR_FAILURE(hr, "Couldn't set frame size", false); | 483 RETURN_ON_HR_FAILURE(hr, "Couldn't set frame size", false); |
| 408 hr = imf_output_media_type_->SetUINT32(MF_MT_INTERLACE_MODE, | 484 hr = imf_output_media_type_->SetUINT32(MF_MT_INTERLACE_MODE, |
| 409 MFVideoInterlace_Progressive); | 485 MFVideoInterlace_Progressive); |
| 410 RETURN_ON_HR_FAILURE(hr, "Couldn't set interlace mode", false); | 486 RETURN_ON_HR_FAILURE(hr, "Couldn't set interlace mode", false); |
| 411 hr = imf_output_media_type_->SetUINT32(MF_MT_MPEG2_PROFILE, | 487 if (output_profile_ == H264PROFILE_BASELINE) { |
| 412 eAVEncH264VProfile_Base); | 488 hr = imf_output_media_type_->SetUINT32(MF_MT_MPEG2_PROFILE, |
| 413 RETURN_ON_HR_FAILURE(hr, "Couldn't set codec profile", false); | 489 eAVEncH264VProfile_Base); |
| 490 RETURN_ON_HR_FAILURE(hr, "Couldn't set codec profile", false); |
| 491 } |
| 414 hr = encoder_->SetOutputType(output_stream_id_, imf_output_media_type_.get(), | 492 hr = encoder_->SetOutputType(output_stream_id_, imf_output_media_type_.get(), |
| 415 0); | 493 0); |
| 416 RETURN_ON_HR_FAILURE(hr, "Couldn't set output media type", false); | 494 RETURN_ON_HR_FAILURE(hr, "Couldn't set output media type", false); |
| 417 | 495 |
| 418 // Initialize input parameters. | 496 // Initialize input parameters. |
| 419 hr = MFCreateMediaType(imf_input_media_type_.Receive()); | 497 hr = MFCreateMediaType(imf_input_media_type_.Receive()); |
| 420 RETURN_ON_HR_FAILURE(hr, "Couldn't create media type", false); | 498 RETURN_ON_HR_FAILURE(hr, "Couldn't create media type", false); |
| 421 hr = imf_input_media_type_->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Video); | 499 hr = imf_input_media_type_->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Video); |
| 422 RETURN_ON_HR_FAILURE(hr, "Couldn't set media type", false); | 500 RETURN_ON_HR_FAILURE(hr, "Couldn't set media type", false); |
| 423 hr = imf_input_media_type_->SetGUID(MF_MT_SUBTYPE, MFVideoFormat_YV12); | 501 hr = imf_input_media_type_->SetGUID(MF_MT_SUBTYPE, MFVideoFormat_NV12); |
| 424 RETURN_ON_HR_FAILURE(hr, "Couldn't set video format", false); | 502 RETURN_ON_HR_FAILURE(hr, "Couldn't set video format", false); |
| 425 hr = MFSetAttributeRatio(imf_input_media_type_.get(), MF_MT_FRAME_RATE, | 503 hr = MFSetAttributeRatio(imf_input_media_type_.get(), MF_MT_FRAME_RATE, |
| 426 frame_rate_, 1); | 504 frame_rate_, 1); |
| 427 RETURN_ON_HR_FAILURE(hr, "Couldn't set frame rate", false); | 505 RETURN_ON_HR_FAILURE(hr, "Couldn't set frame rate", false); |
| 428 hr = MFSetAttributeSize(imf_input_media_type_.get(), MF_MT_FRAME_SIZE, | 506 hr = MFSetAttributeSize(imf_input_media_type_.get(), MF_MT_FRAME_SIZE, |
| 429 input_visible_size_.width(), | 507 input_visible_size_.width(), |
| 430 input_visible_size_.height()); | 508 input_visible_size_.height()); |
| 431 RETURN_ON_HR_FAILURE(hr, "Couldn't set frame size", false); | 509 RETURN_ON_HR_FAILURE(hr, "Couldn't set frame size", false); |
| 432 hr = imf_input_media_type_->SetUINT32(MF_MT_INTERLACE_MODE, | 510 hr = imf_input_media_type_->SetUINT32(MF_MT_INTERLACE_MODE, |
| 433 MFVideoInterlace_Progressive); | 511 MFVideoInterlace_Progressive); |
| (...skipping 12 matching lines...) Expand all Loading... |
| 446 HRESULT hr = encoder_.QueryInterface(codec_api_.Receive()); | 524 HRESULT hr = encoder_.QueryInterface(codec_api_.Receive()); |
| 447 RETURN_ON_HR_FAILURE(hr, "Couldn't get ICodecAPI", false); | 525 RETURN_ON_HR_FAILURE(hr, "Couldn't get ICodecAPI", false); |
| 448 VARIANT var; | 526 VARIANT var; |
| 449 var.vt = VT_UI4; | 527 var.vt = VT_UI4; |
| 450 var.ulVal = eAVEncCommonRateControlMode_CBR; | 528 var.ulVal = eAVEncCommonRateControlMode_CBR; |
| 451 hr = codec_api_->SetValue(&CODECAPI_AVEncCommonRateControlMode, &var); | 529 hr = codec_api_->SetValue(&CODECAPI_AVEncCommonRateControlMode, &var); |
| 452 RETURN_ON_HR_FAILURE(hr, "Couldn't set CommonRateControlMode", false); | 530 RETURN_ON_HR_FAILURE(hr, "Couldn't set CommonRateControlMode", false); |
| 453 var.ulVal = target_bitrate_; | 531 var.ulVal = target_bitrate_; |
| 454 hr = codec_api_->SetValue(&CODECAPI_AVEncCommonMeanBitRate, &var); | 532 hr = codec_api_->SetValue(&CODECAPI_AVEncCommonMeanBitRate, &var); |
| 455 RETURN_ON_HR_FAILURE(hr, "Couldn't set bitrate", false); | 533 RETURN_ON_HR_FAILURE(hr, "Couldn't set bitrate", false); |
| 456 var.ulVal = eAVEncAdaptiveMode_Resolution; | |
| 457 hr = codec_api_->SetValue(&CODECAPI_AVEncAdaptiveMode, &var); | |
| 458 RETURN_ON_HR_FAILURE(hr, "Couldn't set FrameRate", false); | |
| 459 var.vt = VT_BOOL; | 534 var.vt = VT_BOOL; |
| 460 var.boolVal = VARIANT_TRUE; | 535 var.boolVal = VARIANT_TRUE; |
| 461 hr = codec_api_->SetValue(&CODECAPI_AVLowLatencyMode, &var); | 536 hr = codec_api_->SetValue(&CODECAPI_AVLowLatencyMode, &var); |
| 462 RETURN_ON_HR_FAILURE(hr, "Couldn't set LowLatencyMode", false); | 537 RETURN_ON_HR_FAILURE(hr, "Couldn't set LowLatencyMode", false); |
| 538 // if (output_profile_ == H264PROFILE_BASELINE) { |
| 539 // var.ulVal = eAVEncAdaptiveMode_Resolution; |
| 540 // hr = codec_api_->SetValue(&CODECAPI_AVEncAdaptiveMode, &var); |
| 541 // RETURN_ON_HR_FAILURE(hr, "Couldn't set FrameRate", false); |
| 542 // } |
| 463 return SUCCEEDED(hr); | 543 return SUCCEEDED(hr); |
| 464 } | 544 } |
| 465 | 545 |
| 466 bool MediaFoundationVideoEncodeAccelerator::IsResolutionSupported( | 546 bool MediaFoundationVideoEncodeAccelerator::IsResolutionSupported( |
| 467 const gfx::Size& resolution) { | 547 const gfx::Size& resolution) { |
| 468 DCHECK(main_client_task_runner_->BelongsToCurrentThread()); | 548 DCHECK(main_client_task_runner_->BelongsToCurrentThread()); |
| 469 DCHECK(encoder_); | 549 DCHECK(encoder_); |
| 470 | 550 |
| 471 HRESULT hr = | 551 HRESULT hr = |
| 472 MFSetAttributeSize(imf_output_media_type_.get(), MF_MT_FRAME_SIZE, | 552 MFSetAttributeSize(imf_output_media_type_.get(), MF_MT_FRAME_SIZE, |
| (...skipping 222 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 695 void MediaFoundationVideoEncodeAccelerator::ReleaseEncoderResources() { | 775 void MediaFoundationVideoEncodeAccelerator::ReleaseEncoderResources() { |
| 696 encoder_.Release(); | 776 encoder_.Release(); |
| 697 codec_api_.Release(); | 777 codec_api_.Release(); |
| 698 imf_input_media_type_.Release(); | 778 imf_input_media_type_.Release(); |
| 699 imf_output_media_type_.Release(); | 779 imf_output_media_type_.Release(); |
| 700 input_sample_.Release(); | 780 input_sample_.Release(); |
| 701 output_sample_.Release(); | 781 output_sample_.Release(); |
| 702 } | 782 } |
| 703 | 783 |
| 704 } // namespace content | 784 } // namespace content |
| OLD | NEW |