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 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 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 DVLOG(3) << __func__; | 90 DVLOG(3) << __func__; |
| 91 DCHECK(sequence_checker_.CalledOnValidSequence()); | 91 DCHECK(thread_checker_.CalledOnValidThread()); |
| 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 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 216 } | 216 } |
| 217 | 217 |
| 218 void MediaFoundationVideoEncodeAccelerator::UseOutputBitstreamBuffer( | 218 void MediaFoundationVideoEncodeAccelerator::UseOutputBitstreamBuffer( |
| 219 const BitstreamBuffer& buffer) { | 219 const BitstreamBuffer& buffer) { |
| 220 DVLOG(3) << __func__ << ": buffer size=" << buffer.size(); | 220 DVLOG(3) << __func__ << ": buffer size=" << buffer.size(); |
| 221 DCHECK(sequence_checker_.CalledOnValidSequence()); | 221 DCHECK(sequence_checker_.CalledOnValidSequence()); |
| 222 | 222 |
| 223 if (buffer.size() < bitstream_buffer_size_) { | 223 if (buffer.size() < bitstream_buffer_size_) { |
| 224 DLOG(ERROR) << "Output BitstreamBuffer isn't big enough: " << buffer.size() | 224 DLOG(ERROR) << "Output BitstreamBuffer isn't big enough: " << buffer.size() |
| 225 << " vs. " << bitstream_buffer_size_; | 225 << " vs. " << bitstream_buffer_size_; |
| 226 client_->NotifyError(kInvalidArgumentError); | 226 client_->NotifyError(kInvalidArgumentError); |
|
Pawel Osciak
2016/10/25 01:44:05
client_ is a WeakPtr, so we should always if (clie
emircan
2016/10/25 21:57:51
Done.
| |
| 227 return; | 227 return; |
| 228 } | 228 } |
| 229 | 229 |
| 230 std::unique_ptr<base::SharedMemory> shm( | 230 std::unique_ptr<base::SharedMemory> shm( |
| 231 new base::SharedMemory(buffer.handle(), false)); | 231 new base::SharedMemory(buffer.handle(), false)); |
| 232 if (!shm->Map(buffer.size())) { | 232 if (!shm->Map(buffer.size())) { |
| 233 DLOG(ERROR) << "Failed mapping shared memory."; | 233 DLOG(ERROR) << "Failed mapping shared memory."; |
| 234 client_->NotifyError(kPlatformFailureError); | 234 client_->NotifyError(kPlatformFailureError); |
| 235 return; | 235 return; |
| 236 } | 236 } |
| (...skipping 16 matching lines...) Expand all 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(); |
| 267 client_.reset(); | |
|
Pawel Osciak
2016/10/25 01:44:05
Hm, do we need to InvalidateWeakPtrs() on factory
emircan
2016/10/25 21:57:51
It already gets invalidated from GPUVEA's OnWillDe
Pawel Osciak
2016/10/27 01:45:19
In that case I feel InvalidateWeakPtrs() is more e
| |
| 267 | 268 |
| 268 if (encoder_thread_.IsRunning()) { | 269 if (encoder_thread_.IsRunning()) { |
| 269 encoder_thread_task_runner_->PostTask( | 270 encoder_thread_task_runner_->PostTask( |
| 270 FROM_HERE, | 271 FROM_HERE, |
| 271 base::Bind(&MediaFoundationVideoEncodeAccelerator::DestroyTask, | 272 base::Bind(&MediaFoundationVideoEncodeAccelerator::DestroyTask, |
| 272 encoder_task_weak_factory_.GetWeakPtr())); | 273 encoder_task_weak_factory_.GetWeakPtr())); |
| 273 encoder_thread_.Stop(); | 274 encoder_thread_.Stop(); |
| 274 } | 275 } |
| 275 | 276 |
| 276 delete this; | 277 delete this; |
| 277 } | 278 } |
| 278 | 279 |
| 280 bool MediaFoundationVideoEncodeAccelerator::TryToSetupEncodeOnSeparateThread( | |
| 281 const base::WeakPtr<Client>& encode_client, | |
| 282 const scoped_refptr<base::SingleThreadTaskRunner>& encode_task_runner) { | |
| 283 DVLOG(3) << __func__; | |
| 284 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 285 client_ = encode_client; | |
| 286 client_task_runner_ = encode_task_runner; | |
| 287 sequence_checker_.DetachFromSequence(); | |
| 288 return true; | |
| 289 } | |
| 290 | |
| 279 // static | 291 // static |
| 280 void MediaFoundationVideoEncodeAccelerator::PreSandboxInitialization() { | 292 void MediaFoundationVideoEncodeAccelerator::PreSandboxInitialization() { |
| 281 for (const wchar_t* mfdll : kMediaFoundationVideoEncoderDLLs) | 293 for (const wchar_t* mfdll : kMediaFoundationVideoEncoderDLLs) |
| 282 ::LoadLibrary(mfdll); | 294 ::LoadLibrary(mfdll); |
| 283 } | 295 } |
| 284 | 296 |
| 285 bool MediaFoundationVideoEncodeAccelerator::CreateHardwareEncoderMFT() { | 297 bool MediaFoundationVideoEncodeAccelerator::CreateHardwareEncoderMFT() { |
| 286 DVLOG(3) << __func__; | 298 DVLOG(3) << __func__; |
| 287 DCHECK(sequence_checker_.CalledOnValidSequence()); | 299 DCHECK(thread_checker_.CalledOnValidThread()); |
| 288 | 300 |
| 289 if (base::win::GetVersion() < base::win::VERSION_WIN8) { | 301 if (base::win::GetVersion() < base::win::VERSION_WIN8) { |
| 290 DVLOG(ERROR) << "Windows versions earlier than 8 are not supported."; | 302 DVLOG(ERROR) << "Windows versions earlier than 8 are not supported."; |
| 291 return false; | 303 return false; |
| 292 } | 304 } |
| 293 | 305 |
| 294 for (const wchar_t* mfdll : kMediaFoundationVideoEncoderDLLs) { | 306 for (const wchar_t* mfdll : kMediaFoundationVideoEncoderDLLs) { |
| 295 if (!::GetModuleHandle(mfdll)) { | 307 if (!::GetModuleHandle(mfdll)) { |
| 296 DVLOG(ERROR) << mfdll << " is required for encoding"; | 308 DVLOG(ERROR) << mfdll << " is required for encoding"; |
| 297 return false; | 309 return false; |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 314 &output_info, NULL, &CLSIDs, &count); | 326 &output_info, NULL, &CLSIDs, &count); |
| 315 RETURN_ON_HR_FAILURE(hr, "Couldn't enumerate hardware encoder", false); | 327 RETURN_ON_HR_FAILURE(hr, "Couldn't enumerate hardware encoder", false); |
| 316 RETURN_ON_FAILURE((count > 0), "No HW encoder found", false); | 328 RETURN_ON_FAILURE((count > 0), "No HW encoder found", false); |
| 317 DVLOG(3) << "HW encoder(s) found: " << count; | 329 DVLOG(3) << "HW encoder(s) found: " << count; |
| 318 hr = encoder_.CreateInstance(CLSIDs[0]); | 330 hr = encoder_.CreateInstance(CLSIDs[0]); |
| 319 RETURN_ON_HR_FAILURE(hr, "Couldn't activate hardware encoder", false); | 331 RETURN_ON_HR_FAILURE(hr, "Couldn't activate hardware encoder", false); |
| 320 return true; | 332 return true; |
| 321 } | 333 } |
| 322 | 334 |
| 323 bool MediaFoundationVideoEncodeAccelerator::InitializeInputOutputSamples() { | 335 bool MediaFoundationVideoEncodeAccelerator::InitializeInputOutputSamples() { |
| 324 DCHECK(sequence_checker_.CalledOnValidSequence()); | 336 DCHECK(thread_checker_.CalledOnValidThread()); |
| 325 | 337 |
| 326 // Initialize output parameters. | 338 // Initialize output parameters. |
| 327 HRESULT hr = MFCreateMediaType(imf_output_media_type_.Receive()); | 339 HRESULT hr = MFCreateMediaType(imf_output_media_type_.Receive()); |
| 328 RETURN_ON_HR_FAILURE(hr, "Couldn't create media type", false); | 340 RETURN_ON_HR_FAILURE(hr, "Couldn't create media type", false); |
| 329 hr = imf_output_media_type_->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Video); | 341 hr = imf_output_media_type_->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Video); |
| 330 RETURN_ON_HR_FAILURE(hr, "Couldn't set media type", false); | 342 RETURN_ON_HR_FAILURE(hr, "Couldn't set media type", false); |
| 331 hr = imf_output_media_type_->SetGUID(MF_MT_SUBTYPE, MFVideoFormat_H264); | 343 hr = imf_output_media_type_->SetGUID(MF_MT_SUBTYPE, MFVideoFormat_H264); |
| 332 RETURN_ON_HR_FAILURE(hr, "Couldn't set video format", false); | 344 RETURN_ON_HR_FAILURE(hr, "Couldn't set video format", false); |
| 333 hr = imf_output_media_type_->SetUINT32(MF_MT_AVG_BITRATE, target_bitrate_); | 345 hr = imf_output_media_type_->SetUINT32(MF_MT_AVG_BITRATE, target_bitrate_); |
| 334 RETURN_ON_HR_FAILURE(hr, "Couldn't set bitrate", false); | 346 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, | 377 hr = imf_input_media_type_->SetUINT32(MF_MT_INTERLACE_MODE, |
| 366 MFVideoInterlace_Progressive); | 378 MFVideoInterlace_Progressive); |
| 367 RETURN_ON_HR_FAILURE(hr, "Couldn't set interlace mode", false); | 379 RETURN_ON_HR_FAILURE(hr, "Couldn't set interlace mode", false); |
| 368 hr = encoder_->SetInputType(0, imf_input_media_type_.get(), 0); | 380 hr = encoder_->SetInputType(0, imf_input_media_type_.get(), 0); |
| 369 RETURN_ON_HR_FAILURE(hr, "Couldn't set input media type", false); | 381 RETURN_ON_HR_FAILURE(hr, "Couldn't set input media type", false); |
| 370 | 382 |
| 371 return SUCCEEDED(hr); | 383 return SUCCEEDED(hr); |
| 372 } | 384 } |
| 373 | 385 |
| 374 bool MediaFoundationVideoEncodeAccelerator::SetEncoderModes() { | 386 bool MediaFoundationVideoEncodeAccelerator::SetEncoderModes() { |
| 375 DCHECK(sequence_checker_.CalledOnValidSequence()); | 387 DCHECK(thread_checker_.CalledOnValidThread()); |
| 376 | 388 |
| 377 HRESULT hr = encoder_.QueryInterface(IID_ICodecAPI, codec_api_.ReceiveVoid()); | 389 HRESULT hr = encoder_.QueryInterface(IID_ICodecAPI, codec_api_.ReceiveVoid()); |
| 378 RETURN_ON_HR_FAILURE(hr, "Couldn't get ICodecAPI", false); | 390 RETURN_ON_HR_FAILURE(hr, "Couldn't get ICodecAPI", false); |
| 379 VARIANT var; | 391 VARIANT var; |
| 380 var.vt = VT_UI4; | 392 var.vt = VT_UI4; |
| 381 var.ulVal = eAVEncCommonRateControlMode_CBR; | 393 var.ulVal = eAVEncCommonRateControlMode_CBR; |
| 382 hr = codec_api_->SetValue(&CODECAPI_AVEncCommonRateControlMode, &var); | 394 hr = codec_api_->SetValue(&CODECAPI_AVEncCommonRateControlMode, &var); |
| 383 RETURN_ON_HR_FAILURE(hr, "Couldn't set CommonRateControlMode", false); | 395 RETURN_ON_HR_FAILURE(hr, "Couldn't set CommonRateControlMode", false); |
| 384 var.ulVal = target_bitrate_; | 396 var.ulVal = target_bitrate_; |
| 385 hr = codec_api_->SetValue(&CODECAPI_AVEncCommonMeanBitRate, &var); | 397 hr = codec_api_->SetValue(&CODECAPI_AVEncCommonMeanBitRate, &var); |
| (...skipping 206 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 592 void MediaFoundationVideoEncodeAccelerator::ReleaseEncoderResources() { | 604 void MediaFoundationVideoEncodeAccelerator::ReleaseEncoderResources() { |
| 593 encoder_.Release(); | 605 encoder_.Release(); |
| 594 codec_api_.Release(); | 606 codec_api_.Release(); |
| 595 imf_input_media_type_.Release(); | 607 imf_input_media_type_.Release(); |
| 596 imf_output_media_type_.Release(); | 608 imf_output_media_type_.Release(); |
| 597 input_sample_.Release(); | 609 input_sample_.Release(); |
| 598 output_sample_.Release(); | 610 output_sample_.Release(); |
| 599 } | 611 } |
| 600 | 612 |
| 601 } // namespace content | 613 } // namespace content |
| OLD | NEW |