Chromium Code Reviews| 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 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 80 DISALLOW_IMPLICIT_CONSTRUCTORS(BitstreamBufferRef); | 80 DISALLOW_IMPLICIT_CONSTRUCTORS(BitstreamBufferRef); |
| 81 }; | 81 }; |
| 82 | 82 |
| 83 MediaFoundationVideoEncodeAccelerator::MediaFoundationVideoEncodeAccelerator() | 83 MediaFoundationVideoEncodeAccelerator::MediaFoundationVideoEncodeAccelerator() |
| 84 : client_task_runner_(base::SequencedTaskRunnerHandle::Get()), | 84 : client_task_runner_(base::SequencedTaskRunnerHandle::Get()), |
| 85 encoder_thread_("MFEncoderThread"), | 85 encoder_thread_("MFEncoderThread"), |
| 86 encoder_task_weak_factory_(this) {} | 86 encoder_task_weak_factory_(this) {} |
| 87 | 87 |
| 88 MediaFoundationVideoEncodeAccelerator:: | 88 MediaFoundationVideoEncodeAccelerator:: |
| 89 ~MediaFoundationVideoEncodeAccelerator() { | 89 ~MediaFoundationVideoEncodeAccelerator() { |
| 90 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 90 DVLOG(3) << __func__; | 91 DVLOG(3) << __func__; |
|
sandersd (OOO until July 31)
2016/10/21 01:01:00
Nit: Prefer __func__ logging first.
emircan
2016/10/24 19:44:53
Done.
| |
| 91 DCHECK(sequence_checker_.CalledOnValidSequence()); | |
| 92 | 92 |
| 93 DCHECK(!encoder_thread_.IsRunning()); | 93 DCHECK(!encoder_thread_.IsRunning()); |
| 94 DCHECK(!encoder_task_weak_factory_.HasWeakPtrs()); | 94 DCHECK(!encoder_task_weak_factory_.HasWeakPtrs()); |
| 95 } | 95 } |
| 96 | 96 |
| 97 VideoEncodeAccelerator::SupportedProfiles | 97 VideoEncodeAccelerator::SupportedProfiles |
| 98 MediaFoundationVideoEncodeAccelerator::GetSupportedProfiles() { | 98 MediaFoundationVideoEncodeAccelerator::GetSupportedProfiles() { |
| 99 TRACE_EVENT0("gpu,startup", | 99 TRACE_EVENT0("gpu,startup", |
| 100 "MediaFoundationVideoEncodeAccelerator::GetSupportedProfiles"); | 100 "MediaFoundationVideoEncodeAccelerator::GetSupportedProfiles"); |
| 101 DVLOG(3) << __func__; | 101 DVLOG(3) << __func__; |
| 102 DCHECK(sequence_checker_.CalledOnValidSequence()); | 102 DCHECK(thread_checker_.CalledOnValidThread()); |
| 103 | 103 |
| 104 SupportedProfiles profiles; | 104 SupportedProfiles profiles; |
| 105 | 105 |
| 106 target_bitrate_ = kDefaultTargetBitrate; | 106 target_bitrate_ = kDefaultTargetBitrate; |
| 107 frame_rate_ = kMaxFrameRateNumerator / kMaxFrameRateDenominator; | 107 frame_rate_ = kMaxFrameRateNumerator / kMaxFrameRateDenominator; |
| 108 input_visible_size_ = gfx::Size(kMaxResolutionWidth, kMaxResolutionHeight); | 108 input_visible_size_ = gfx::Size(kMaxResolutionWidth, kMaxResolutionHeight); |
| 109 if (!CreateHardwareEncoderMFT() || !SetEncoderModes() || | 109 if (!CreateHardwareEncoderMFT() || !SetEncoderModes() || |
| 110 !InitializeInputOutputSamples()) { | 110 !InitializeInputOutputSamples()) { |
| 111 ReleaseEncoderResources(); | 111 ReleaseEncoderResources(); |
| 112 DVLOG(1) | 112 DVLOG(1) |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 129 bool MediaFoundationVideoEncodeAccelerator::Initialize( | 129 bool MediaFoundationVideoEncodeAccelerator::Initialize( |
| 130 VideoPixelFormat format, | 130 VideoPixelFormat format, |
| 131 const gfx::Size& input_visible_size, | 131 const gfx::Size& input_visible_size, |
| 132 VideoCodecProfile output_profile, | 132 VideoCodecProfile output_profile, |
| 133 uint32_t initial_bitrate, | 133 uint32_t initial_bitrate, |
| 134 Client* client) { | 134 Client* client) { |
| 135 DVLOG(3) << __func__ << ": input_format=" << VideoPixelFormatToString(format) | 135 DVLOG(3) << __func__ << ": input_format=" << VideoPixelFormatToString(format) |
| 136 << ", input_visible_size=" << input_visible_size.ToString() | 136 << ", input_visible_size=" << input_visible_size.ToString() |
| 137 << ", output_profile=" << output_profile | 137 << ", output_profile=" << output_profile |
| 138 << ", initial_bitrate=" << initial_bitrate; | 138 << ", initial_bitrate=" << initial_bitrate; |
| 139 DCHECK(sequence_checker_.CalledOnValidSequence()); | 139 DCHECK(thread_checker_.CalledOnValidThread()); |
| 140 | 140 |
| 141 if (PIXEL_FORMAT_I420 != format) { | 141 if (PIXEL_FORMAT_I420 != format) { |
| 142 DLOG(ERROR) << "Input format not supported= " | 142 DLOG(ERROR) << "Input format not supported= " |
| 143 << VideoPixelFormatToString(format); | 143 << VideoPixelFormatToString(format); |
| 144 return false; | 144 return false; |
| 145 } | 145 } |
| 146 | 146 |
| 147 if (H264PROFILE_BASELINE != output_profile) { | 147 if (H264PROFILE_BASELINE != output_profile) { |
| 148 DLOG(ERROR) << "Output profile not supported= " << output_profile; | 148 DLOG(ERROR) << "Output profile not supported= " << output_profile; |
| 149 return false; | 149 return false; |
| (...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 253 | 253 |
| 254 encoder_thread_task_runner_->PostTask( | 254 encoder_thread_task_runner_->PostTask( |
| 255 FROM_HERE, | 255 FROM_HERE, |
| 256 base::Bind(&MediaFoundationVideoEncodeAccelerator:: | 256 base::Bind(&MediaFoundationVideoEncodeAccelerator:: |
| 257 RequestEncodingParametersChangeTask, | 257 RequestEncodingParametersChangeTask, |
| 258 encoder_task_weak_factory_.GetWeakPtr(), bitrate, framerate)); | 258 encoder_task_weak_factory_.GetWeakPtr(), bitrate, framerate)); |
| 259 } | 259 } |
| 260 | 260 |
| 261 void MediaFoundationVideoEncodeAccelerator::Destroy() { | 261 void MediaFoundationVideoEncodeAccelerator::Destroy() { |
| 262 DVLOG(3) << __func__; | 262 DVLOG(3) << __func__; |
| 263 DCHECK(sequence_checker_.CalledOnValidSequence()); | 263 DCHECK(thread_checker_.CalledOnValidThread()); |
| 264 | 264 |
| 265 // Cancel all callbacks. | 265 // Cancel all callbacks. |
| 266 client_ptr_factory_.reset(); | 266 client_ptr_factory_.reset(); |
|
sandersd (OOO until July 31)
2016/10/21 18:41:03
Note that this no longer has the stated side effec
emircan
2016/10/24 19:44:53
Thanks for pointing this out. I added a reset to m
| |
| 267 | 267 |
| 268 if (encoder_thread_.IsRunning()) { | 268 if (encoder_thread_.IsRunning()) { |
| 269 encoder_thread_task_runner_->PostTask( | 269 encoder_thread_task_runner_->PostTask( |
| 270 FROM_HERE, | 270 FROM_HERE, |
| 271 base::Bind(&MediaFoundationVideoEncodeAccelerator::DestroyTask, | 271 base::Bind(&MediaFoundationVideoEncodeAccelerator::DestroyTask, |
| 272 encoder_task_weak_factory_.GetWeakPtr())); | 272 encoder_task_weak_factory_.GetWeakPtr())); |
| 273 encoder_thread_.Stop(); | 273 encoder_thread_.Stop(); |
| 274 } | 274 } |
| 275 | 275 |
| 276 delete this; | 276 delete this; |
| 277 } | 277 } |
| 278 | 278 |
| 279 bool MediaFoundationVideoEncodeAccelerator::TryToSetupEncodeOnSeparateThread( | |
| 280 const base::WeakPtr<Client>& encode_client, | |
| 281 const scoped_refptr<base::SingleThreadTaskRunner>& encode_task_runner) { | |
| 282 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 283 client_ = encode_client; | |
| 284 client_task_runner_ = encode_task_runner; | |
| 285 sequence_checker_.DetachFromSequence(); | |
| 286 return true; | |
| 287 } | |
| 288 | |
| 279 // static | 289 // static |
| 280 void MediaFoundationVideoEncodeAccelerator::PreSandboxInitialization() { | 290 void MediaFoundationVideoEncodeAccelerator::PreSandboxInitialization() { |
| 281 for (const wchar_t* mfdll : kMediaFoundationVideoEncoderDLLs) | 291 for (const wchar_t* mfdll : kMediaFoundationVideoEncoderDLLs) |
| 282 ::LoadLibrary(mfdll); | 292 ::LoadLibrary(mfdll); |
| 283 } | 293 } |
| 284 | 294 |
| 285 bool MediaFoundationVideoEncodeAccelerator::CreateHardwareEncoderMFT() { | 295 bool MediaFoundationVideoEncodeAccelerator::CreateHardwareEncoderMFT() { |
| 286 DVLOG(3) << __func__; | 296 DVLOG(3) << __func__; |
| 287 DCHECK(sequence_checker_.CalledOnValidSequence()); | 297 DCHECK(thread_checker_.CalledOnValidThread()); |
| 288 | 298 |
| 289 if (base::win::GetVersion() < base::win::VERSION_WIN8) { | 299 if (base::win::GetVersion() < base::win::VERSION_WIN8) { |
| 290 DVLOG(ERROR) << "Windows versions earlier than 8 are not supported."; | 300 DVLOG(ERROR) << "Windows versions earlier than 8 are not supported."; |
| 291 return false; | 301 return false; |
| 292 } | 302 } |
| 293 | 303 |
| 294 for (const wchar_t* mfdll : kMediaFoundationVideoEncoderDLLs) { | 304 for (const wchar_t* mfdll : kMediaFoundationVideoEncoderDLLs) { |
| 295 if (!::GetModuleHandle(mfdll)) { | 305 if (!::GetModuleHandle(mfdll)) { |
| 296 DVLOG(ERROR) << mfdll << " is required for encoding"; | 306 DVLOG(ERROR) << mfdll << " is required for encoding"; |
| 297 return false; | 307 return false; |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 314 &output_info, NULL, &CLSIDs, &count); | 324 &output_info, NULL, &CLSIDs, &count); |
| 315 RETURN_ON_HR_FAILURE(hr, "Couldn't enumerate hardware encoder", false); | 325 RETURN_ON_HR_FAILURE(hr, "Couldn't enumerate hardware encoder", false); |
| 316 RETURN_ON_FAILURE((count > 0), "No HW encoder found", false); | 326 RETURN_ON_FAILURE((count > 0), "No HW encoder found", false); |
| 317 DVLOG(3) << "HW encoder(s) found: " << count; | 327 DVLOG(3) << "HW encoder(s) found: " << count; |
| 318 hr = encoder_.CreateInstance(CLSIDs[0]); | 328 hr = encoder_.CreateInstance(CLSIDs[0]); |
| 319 RETURN_ON_HR_FAILURE(hr, "Couldn't activate hardware encoder", false); | 329 RETURN_ON_HR_FAILURE(hr, "Couldn't activate hardware encoder", false); |
| 320 return true; | 330 return true; |
| 321 } | 331 } |
| 322 | 332 |
| 323 bool MediaFoundationVideoEncodeAccelerator::InitializeInputOutputSamples() { | 333 bool MediaFoundationVideoEncodeAccelerator::InitializeInputOutputSamples() { |
| 324 DCHECK(sequence_checker_.CalledOnValidSequence()); | 334 DCHECK(thread_checker_.CalledOnValidThread()); |
| 325 | 335 |
| 326 // Initialize output parameters. | 336 // Initialize output parameters. |
| 327 HRESULT hr = MFCreateMediaType(imf_output_media_type_.Receive()); | 337 HRESULT hr = MFCreateMediaType(imf_output_media_type_.Receive()); |
| 328 RETURN_ON_HR_FAILURE(hr, "Couldn't create media type", false); | 338 RETURN_ON_HR_FAILURE(hr, "Couldn't create media type", false); |
| 329 hr = imf_output_media_type_->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Video); | 339 hr = imf_output_media_type_->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Video); |
| 330 RETURN_ON_HR_FAILURE(hr, "Couldn't set media type", false); | 340 RETURN_ON_HR_FAILURE(hr, "Couldn't set media type", false); |
| 331 hr = imf_output_media_type_->SetGUID(MF_MT_SUBTYPE, MFVideoFormat_H264); | 341 hr = imf_output_media_type_->SetGUID(MF_MT_SUBTYPE, MFVideoFormat_H264); |
| 332 RETURN_ON_HR_FAILURE(hr, "Couldn't set video format", false); | 342 RETURN_ON_HR_FAILURE(hr, "Couldn't set video format", false); |
| 333 hr = imf_output_media_type_->SetUINT32(MF_MT_AVG_BITRATE, target_bitrate_); | 343 hr = imf_output_media_type_->SetUINT32(MF_MT_AVG_BITRATE, target_bitrate_); |
| 334 RETURN_ON_HR_FAILURE(hr, "Couldn't set bitrate", false); | 344 RETURN_ON_HR_FAILURE(hr, "Couldn't set bitrate", false); |
| (...skipping 30 matching lines...) Expand all Loading... | |
| 365 hr = imf_input_media_type_->SetUINT32(MF_MT_INTERLACE_MODE, | 375 hr = imf_input_media_type_->SetUINT32(MF_MT_INTERLACE_MODE, |
| 366 MFVideoInterlace_Progressive); | 376 MFVideoInterlace_Progressive); |
| 367 RETURN_ON_HR_FAILURE(hr, "Couldn't set interlace mode", false); | 377 RETURN_ON_HR_FAILURE(hr, "Couldn't set interlace mode", false); |
| 368 hr = encoder_->SetInputType(0, imf_input_media_type_.get(), 0); | 378 hr = encoder_->SetInputType(0, imf_input_media_type_.get(), 0); |
| 369 RETURN_ON_HR_FAILURE(hr, "Couldn't set input media type", false); | 379 RETURN_ON_HR_FAILURE(hr, "Couldn't set input media type", false); |
| 370 | 380 |
| 371 return SUCCEEDED(hr); | 381 return SUCCEEDED(hr); |
| 372 } | 382 } |
| 373 | 383 |
| 374 bool MediaFoundationVideoEncodeAccelerator::SetEncoderModes() { | 384 bool MediaFoundationVideoEncodeAccelerator::SetEncoderModes() { |
| 375 DCHECK(sequence_checker_.CalledOnValidSequence()); | 385 DCHECK(thread_checker_.CalledOnValidThread()); |
| 376 | 386 |
| 377 HRESULT hr = encoder_.QueryInterface(IID_ICodecAPI, codec_api_.ReceiveVoid()); | 387 HRESULT hr = encoder_.QueryInterface(IID_ICodecAPI, codec_api_.ReceiveVoid()); |
| 378 RETURN_ON_HR_FAILURE(hr, "Couldn't get ICodecAPI", false); | 388 RETURN_ON_HR_FAILURE(hr, "Couldn't get ICodecAPI", false); |
| 379 VARIANT var; | 389 VARIANT var; |
| 380 var.vt = VT_UI4; | 390 var.vt = VT_UI4; |
| 381 var.ulVal = eAVEncCommonRateControlMode_CBR; | 391 var.ulVal = eAVEncCommonRateControlMode_CBR; |
| 382 hr = codec_api_->SetValue(&CODECAPI_AVEncCommonRateControlMode, &var); | 392 hr = codec_api_->SetValue(&CODECAPI_AVEncCommonRateControlMode, &var); |
| 383 RETURN_ON_HR_FAILURE(hr, "Couldn't set CommonRateControlMode", false); | 393 RETURN_ON_HR_FAILURE(hr, "Couldn't set CommonRateControlMode", false); |
| 384 var.ulVal = target_bitrate_; | 394 var.ulVal = target_bitrate_; |
| 385 hr = codec_api_->SetValue(&CODECAPI_AVEncCommonMeanBitRate, &var); | 395 hr = codec_api_->SetValue(&CODECAPI_AVEncCommonMeanBitRate, &var); |
| (...skipping 206 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 592 void MediaFoundationVideoEncodeAccelerator::ReleaseEncoderResources() { | 602 void MediaFoundationVideoEncodeAccelerator::ReleaseEncoderResources() { |
| 593 encoder_.Release(); | 603 encoder_.Release(); |
| 594 codec_api_.Release(); | 604 codec_api_.Release(); |
| 595 imf_input_media_type_.Release(); | 605 imf_input_media_type_.Release(); |
| 596 imf_output_media_type_.Release(); | 606 imf_output_media_type_.Release(); |
| 597 input_sample_.Release(); | 607 input_sample_.Release(); |
| 598 output_sample_.Release(); | 608 output_sample_.Release(); |
| 599 } | 609 } |
| 600 | 610 |
| 601 } // namespace content | 611 } // namespace content |
| OLD | NEW |