| 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 |