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 |