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 |