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 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
75 }; | 75 }; |
76 | 76 |
77 MediaFoundationVideoEncodeAccelerator::MediaFoundationVideoEncodeAccelerator() | 77 MediaFoundationVideoEncodeAccelerator::MediaFoundationVideoEncodeAccelerator() |
78 : client_task_runner_(base::SequencedTaskRunnerHandle::Get()), | 78 : client_task_runner_(base::SequencedTaskRunnerHandle::Get()), |
79 encoder_thread_("MFEncoderThread"), | 79 encoder_thread_("MFEncoderThread"), |
80 encoder_task_weak_factory_(this) {} | 80 encoder_task_weak_factory_(this) {} |
81 | 81 |
82 MediaFoundationVideoEncodeAccelerator:: | 82 MediaFoundationVideoEncodeAccelerator:: |
83 ~MediaFoundationVideoEncodeAccelerator() { | 83 ~MediaFoundationVideoEncodeAccelerator() { |
84 DVLOG(3) << __FUNCTION__; | 84 DVLOG(3) << __FUNCTION__; |
85 DCHECK(sequence_checker_.CalledOnValidSequencedThread()); | 85 DCHECK(sequence_checker_.CalledOnValidSequence()); |
86 | 86 |
87 DCHECK(!encoder_thread_.IsRunning()); | 87 DCHECK(!encoder_thread_.IsRunning()); |
88 DCHECK(!encoder_task_weak_factory_.HasWeakPtrs()); | 88 DCHECK(!encoder_task_weak_factory_.HasWeakPtrs()); |
89 } | 89 } |
90 | 90 |
91 VideoEncodeAccelerator::SupportedProfiles | 91 VideoEncodeAccelerator::SupportedProfiles |
92 MediaFoundationVideoEncodeAccelerator::GetSupportedProfiles() { | 92 MediaFoundationVideoEncodeAccelerator::GetSupportedProfiles() { |
93 DVLOG(3) << __FUNCTION__; | 93 DVLOG(3) << __FUNCTION__; |
94 DCHECK(sequence_checker_.CalledOnValidSequencedThread()); | 94 DCHECK(sequence_checker_.CalledOnValidSequence()); |
95 | 95 |
96 SupportedProfiles profiles; | 96 SupportedProfiles profiles; |
97 if (base::win::GetVersion() < base::win::VERSION_WIN8) { | 97 if (base::win::GetVersion() < base::win::VERSION_WIN8) { |
98 DLOG(ERROR) << "Windows versions earlier than 8 are not supported."; | 98 DLOG(ERROR) << "Windows versions earlier than 8 are not supported."; |
99 return profiles; | 99 return profiles; |
100 } | 100 } |
101 | 101 |
102 SupportedProfile profile; | 102 SupportedProfile profile; |
103 // More profiles can be supported here, but they should be available in SW | 103 // More profiles can be supported here, but they should be available in SW |
104 // fallback as well. | 104 // fallback as well. |
105 profile.profile = H264PROFILE_BASELINE; | 105 profile.profile = H264PROFILE_BASELINE; |
106 profile.max_framerate_numerator = kMaxFrameRateNumerator; | 106 profile.max_framerate_numerator = kMaxFrameRateNumerator; |
107 profile.max_framerate_denominator = kMaxFrameRateDenominator; | 107 profile.max_framerate_denominator = kMaxFrameRateDenominator; |
108 profile.max_resolution = gfx::Size(kMaxResolutionWidth, kMaxResolutionHeight); | 108 profile.max_resolution = gfx::Size(kMaxResolutionWidth, kMaxResolutionHeight); |
109 profiles.push_back(profile); | 109 profiles.push_back(profile); |
110 return profiles; | 110 return profiles; |
111 } | 111 } |
112 | 112 |
113 bool MediaFoundationVideoEncodeAccelerator::Initialize( | 113 bool MediaFoundationVideoEncodeAccelerator::Initialize( |
114 VideoPixelFormat format, | 114 VideoPixelFormat format, |
115 const gfx::Size& input_visible_size, | 115 const gfx::Size& input_visible_size, |
116 VideoCodecProfile output_profile, | 116 VideoCodecProfile output_profile, |
117 uint32_t initial_bitrate, | 117 uint32_t initial_bitrate, |
118 Client* client) { | 118 Client* client) { |
119 DVLOG(3) << __FUNCTION__ | 119 DVLOG(3) << __FUNCTION__ |
120 << ": input_format=" << VideoPixelFormatToString(format) | 120 << ": input_format=" << VideoPixelFormatToString(format) |
121 << ", input_visible_size=" << input_visible_size.ToString() | 121 << ", input_visible_size=" << input_visible_size.ToString() |
122 << ", output_profile=" << output_profile | 122 << ", output_profile=" << output_profile |
123 << ", initial_bitrate=" << initial_bitrate; | 123 << ", initial_bitrate=" << initial_bitrate; |
124 DCHECK(sequence_checker_.CalledOnValidSequencedThread()); | 124 DCHECK(sequence_checker_.CalledOnValidSequence()); |
125 | 125 |
126 if (PIXEL_FORMAT_I420 != format) { | 126 if (PIXEL_FORMAT_I420 != format) { |
127 DLOG(ERROR) << "Input format not supported= " | 127 DLOG(ERROR) << "Input format not supported= " |
128 << VideoPixelFormatToString(format); | 128 << VideoPixelFormatToString(format); |
129 return false; | 129 return false; |
130 } | 130 } |
131 | 131 |
132 if (H264PROFILE_BASELINE != output_profile) { | 132 if (H264PROFILE_BASELINE != output_profile) { |
133 DLOG(ERROR) << "Output profile not supported= " << output_profile; | 133 DLOG(ERROR) << "Output profile not supported= " << output_profile; |
134 return false; | 134 return false; |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
202 FROM_HERE, | 202 FROM_HERE, |
203 base::Bind(&Client::RequireBitstreamBuffers, client_, kNumInputBuffers, | 203 base::Bind(&Client::RequireBitstreamBuffers, client_, kNumInputBuffers, |
204 input_visible_size_, bitstream_buffer_size_)); | 204 input_visible_size_, bitstream_buffer_size_)); |
205 return SUCCEEDED(hr); | 205 return SUCCEEDED(hr); |
206 } | 206 } |
207 | 207 |
208 void MediaFoundationVideoEncodeAccelerator::Encode( | 208 void MediaFoundationVideoEncodeAccelerator::Encode( |
209 const scoped_refptr<VideoFrame>& frame, | 209 const scoped_refptr<VideoFrame>& frame, |
210 bool force_keyframe) { | 210 bool force_keyframe) { |
211 DVLOG(3) << __FUNCTION__; | 211 DVLOG(3) << __FUNCTION__; |
212 DCHECK(sequence_checker_.CalledOnValidSequencedThread()); | 212 DCHECK(sequence_checker_.CalledOnValidSequence()); |
213 | 213 |
214 encoder_thread_task_runner_->PostTask( | 214 encoder_thread_task_runner_->PostTask( |
215 FROM_HERE, base::Bind(&MediaFoundationVideoEncodeAccelerator::EncodeTask, | 215 FROM_HERE, base::Bind(&MediaFoundationVideoEncodeAccelerator::EncodeTask, |
216 encoder_task_weak_factory_.GetWeakPtr(), frame, | 216 encoder_task_weak_factory_.GetWeakPtr(), frame, |
217 force_keyframe)); | 217 force_keyframe)); |
218 } | 218 } |
219 | 219 |
220 void MediaFoundationVideoEncodeAccelerator::UseOutputBitstreamBuffer( | 220 void MediaFoundationVideoEncodeAccelerator::UseOutputBitstreamBuffer( |
221 const BitstreamBuffer& buffer) { | 221 const BitstreamBuffer& buffer) { |
222 DVLOG(3) << __FUNCTION__ << ": buffer size=" << buffer.size(); | 222 DVLOG(3) << __FUNCTION__ << ": buffer size=" << buffer.size(); |
223 DCHECK(sequence_checker_.CalledOnValidSequencedThread()); | 223 DCHECK(sequence_checker_.CalledOnValidSequence()); |
224 | 224 |
225 if (buffer.size() < bitstream_buffer_size_) { | 225 if (buffer.size() < bitstream_buffer_size_) { |
226 DLOG(ERROR) << "Output BitstreamBuffer isn't big enough: " << buffer.size() | 226 DLOG(ERROR) << "Output BitstreamBuffer isn't big enough: " << buffer.size() |
227 << " vs. " << bitstream_buffer_size_; | 227 << " vs. " << bitstream_buffer_size_; |
228 client_->NotifyError(kInvalidArgumentError); | 228 client_->NotifyError(kInvalidArgumentError); |
229 return; | 229 return; |
230 } | 230 } |
231 | 231 |
232 std::unique_ptr<base::SharedMemory> shm( | 232 std::unique_ptr<base::SharedMemory> shm( |
233 new base::SharedMemory(buffer.handle(), false)); | 233 new base::SharedMemory(buffer.handle(), false)); |
(...skipping 10 matching lines...) Expand all Loading... |
244 base::Bind( | 244 base::Bind( |
245 &MediaFoundationVideoEncodeAccelerator::UseOutputBitstreamBufferTask, | 245 &MediaFoundationVideoEncodeAccelerator::UseOutputBitstreamBufferTask, |
246 encoder_task_weak_factory_.GetWeakPtr(), base::Passed(&buffer_ref))); | 246 encoder_task_weak_factory_.GetWeakPtr(), base::Passed(&buffer_ref))); |
247 } | 247 } |
248 | 248 |
249 void MediaFoundationVideoEncodeAccelerator::RequestEncodingParametersChange( | 249 void MediaFoundationVideoEncodeAccelerator::RequestEncodingParametersChange( |
250 uint32_t bitrate, | 250 uint32_t bitrate, |
251 uint32_t framerate) { | 251 uint32_t framerate) { |
252 DVLOG(3) << __FUNCTION__ << ": bitrate=" << bitrate | 252 DVLOG(3) << __FUNCTION__ << ": bitrate=" << bitrate |
253 << ": framerate=" << framerate; | 253 << ": framerate=" << framerate; |
254 DCHECK(sequence_checker_.CalledOnValidSequencedThread()); | 254 DCHECK(sequence_checker_.CalledOnValidSequence()); |
255 | 255 |
256 encoder_thread_task_runner_->PostTask( | 256 encoder_thread_task_runner_->PostTask( |
257 FROM_HERE, | 257 FROM_HERE, |
258 base::Bind(&MediaFoundationVideoEncodeAccelerator:: | 258 base::Bind(&MediaFoundationVideoEncodeAccelerator:: |
259 RequestEncodingParametersChangeTask, | 259 RequestEncodingParametersChangeTask, |
260 encoder_task_weak_factory_.GetWeakPtr(), bitrate, framerate)); | 260 encoder_task_weak_factory_.GetWeakPtr(), bitrate, framerate)); |
261 } | 261 } |
262 | 262 |
263 void MediaFoundationVideoEncodeAccelerator::Destroy() { | 263 void MediaFoundationVideoEncodeAccelerator::Destroy() { |
264 DVLOG(3) << __FUNCTION__; | 264 DVLOG(3) << __FUNCTION__; |
265 DCHECK(sequence_checker_.CalledOnValidSequencedThread()); | 265 DCHECK(sequence_checker_.CalledOnValidSequence()); |
266 | 266 |
267 // Cancel all callbacks. | 267 // Cancel all callbacks. |
268 client_ptr_factory_.reset(); | 268 client_ptr_factory_.reset(); |
269 | 269 |
270 if (encoder_thread_.IsRunning()) { | 270 if (encoder_thread_.IsRunning()) { |
271 encoder_thread_task_runner_->PostTask( | 271 encoder_thread_task_runner_->PostTask( |
272 FROM_HERE, | 272 FROM_HERE, |
273 base::Bind(&MediaFoundationVideoEncodeAccelerator::DestroyTask, | 273 base::Bind(&MediaFoundationVideoEncodeAccelerator::DestroyTask, |
274 encoder_task_weak_factory_.GetWeakPtr())); | 274 encoder_task_weak_factory_.GetWeakPtr())); |
275 encoder_thread_.Stop(); | 275 encoder_thread_.Stop(); |
276 } | 276 } |
277 | 277 |
278 delete this; | 278 delete this; |
279 } | 279 } |
280 | 280 |
281 // static | 281 // static |
282 void MediaFoundationVideoEncodeAccelerator::PreSandboxInitialization() { | 282 void MediaFoundationVideoEncodeAccelerator::PreSandboxInitialization() { |
283 for (const wchar_t* mfdll : kMediaFoundationVideoEncoderDLLs) | 283 for (const wchar_t* mfdll : kMediaFoundationVideoEncoderDLLs) |
284 ::LoadLibrary(mfdll); | 284 ::LoadLibrary(mfdll); |
285 } | 285 } |
286 | 286 |
287 bool MediaFoundationVideoEncodeAccelerator::InitializeInputOutputSamples() { | 287 bool MediaFoundationVideoEncodeAccelerator::InitializeInputOutputSamples() { |
288 DCHECK(sequence_checker_.CalledOnValidSequencedThread()); | 288 DCHECK(sequence_checker_.CalledOnValidSequence()); |
289 | 289 |
290 HRESULT hr = encoder_->GetStreamLimits( | 290 HRESULT hr = encoder_->GetStreamLimits( |
291 &input_stream_count_min_, &input_stream_count_max_, | 291 &input_stream_count_min_, &input_stream_count_max_, |
292 &output_stream_count_min_, &output_stream_count_max_); | 292 &output_stream_count_min_, &output_stream_count_max_); |
293 RETURN_ON_HR_FAILURE(hr, "Couldn't query stream limits", false); | 293 RETURN_ON_HR_FAILURE(hr, "Couldn't query stream limits", false); |
294 DVLOG(3) << "Stream limits: " << input_stream_count_min_ << "," | 294 DVLOG(3) << "Stream limits: " << input_stream_count_min_ << "," |
295 << input_stream_count_max_ << "," << output_stream_count_min_ << "," | 295 << input_stream_count_max_ << "," << output_stream_count_min_ << "," |
296 << output_stream_count_max_; | 296 << output_stream_count_max_; |
297 | 297 |
298 // Initialize output parameters. | 298 // Initialize output parameters. |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
344 | 344 |
345 input_sample_.Attach(mf::CreateEmptySampleWithBuffer( | 345 input_sample_.Attach(mf::CreateEmptySampleWithBuffer( |
346 VideoFrame::AllocationSize(PIXEL_FORMAT_I420, input_visible_size_), 2)); | 346 VideoFrame::AllocationSize(PIXEL_FORMAT_I420, input_visible_size_), 2)); |
347 output_sample_.Attach(mf::CreateEmptySampleWithBuffer( | 347 output_sample_.Attach(mf::CreateEmptySampleWithBuffer( |
348 bitstream_buffer_size_ * kOutputSampleBufferSizeRatio, 2)); | 348 bitstream_buffer_size_ * kOutputSampleBufferSizeRatio, 2)); |
349 | 349 |
350 return SUCCEEDED(hr); | 350 return SUCCEEDED(hr); |
351 } | 351 } |
352 | 352 |
353 bool MediaFoundationVideoEncodeAccelerator::SetEncoderModes() { | 353 bool MediaFoundationVideoEncodeAccelerator::SetEncoderModes() { |
354 DCHECK(sequence_checker_.CalledOnValidSequencedThread()); | 354 DCHECK(sequence_checker_.CalledOnValidSequence()); |
355 | 355 |
356 HRESULT hr = encoder_.QueryInterface(IID_ICodecAPI, codec_api_.ReceiveVoid()); | 356 HRESULT hr = encoder_.QueryInterface(IID_ICodecAPI, codec_api_.ReceiveVoid()); |
357 RETURN_ON_HR_FAILURE(hr, "Couldn't get ICodecAPI", false); | 357 RETURN_ON_HR_FAILURE(hr, "Couldn't get ICodecAPI", false); |
358 VARIANT var; | 358 VARIANT var; |
359 var.vt = VT_UI4; | 359 var.vt = VT_UI4; |
360 var.ulVal = eAVEncCommonRateControlMode_CBR; | 360 var.ulVal = eAVEncCommonRateControlMode_CBR; |
361 hr = codec_api_->SetValue(&CODECAPI_AVEncCommonRateControlMode, &var); | 361 hr = codec_api_->SetValue(&CODECAPI_AVEncCommonRateControlMode, &var); |
362 RETURN_ON_HR_FAILURE(hr, "Couldn't set CommonRateControlMode", false); | 362 RETURN_ON_HR_FAILURE(hr, "Couldn't set CommonRateControlMode", false); |
363 var.ulVal = target_bitrate_; | 363 var.ulVal = target_bitrate_; |
364 hr = codec_api_->SetValue(&CODECAPI_AVEncCommonMeanBitRate, &var); | 364 hr = codec_api_->SetValue(&CODECAPI_AVEncCommonMeanBitRate, &var); |
(...skipping 188 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
553 DVLOG(3) << __FUNCTION__; | 553 DVLOG(3) << __FUNCTION__; |
554 DCHECK(encoder_thread_task_runner_->BelongsToCurrentThread()); | 554 DCHECK(encoder_thread_task_runner_->BelongsToCurrentThread()); |
555 | 555 |
556 // Cancel all encoder thread callbacks. | 556 // Cancel all encoder thread callbacks. |
557 encoder_task_weak_factory_.InvalidateWeakPtrs(); | 557 encoder_task_weak_factory_.InvalidateWeakPtrs(); |
558 | 558 |
559 encoder_.Release(); | 559 encoder_.Release(); |
560 } | 560 } |
561 | 561 |
562 } // namespace content | 562 } // namespace content |
OLD | NEW |