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> |
| 11 #include <mferror.h> | 11 #include <mferror.h> |
| 12 #include <mftransform.h> | 12 #include <mftransform.h> |
| 13 | 13 |
| 14 #include <iterator> | 14 #include <iterator> |
| 15 #include <utility> | 15 #include <utility> |
| 16 #include <vector> | 16 #include <vector> |
| 17 | 17 |
| 18 #include "base/threading/sequenced_task_runner_handle.h" | 18 #include "base/threading/thread_task_runner_handle.h" |
| 19 #include "base/trace_event/trace_event.h" | 19 #include "base/trace_event/trace_event.h" |
| 20 #include "base/win/scoped_co_mem.h" | 20 #include "base/win/scoped_co_mem.h" |
| 21 #include "base/win/scoped_variant.h" | 21 #include "base/win/scoped_variant.h" |
| 22 #include "base/win/windows_version.h" | 22 #include "base/win/windows_version.h" |
| 23 #include "media/base/win/mf_helpers.h" | 23 #include "media/base/win/mf_helpers.h" |
| 24 #include "media/base/win/mf_initializer.h" | 24 #include "media/base/win/mf_initializer.h" |
| 25 #include "third_party/libyuv/include/libyuv.h" | 25 #include "third_party/libyuv/include/libyuv.h" |
| 26 | 26 |
| 27 using base::win::ScopedComPtr; | 27 using base::win::ScopedComPtr; |
| 28 using media::mf::MediaBufferScopedPointer; | 28 using media::mf::MediaBufferScopedPointer; |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 74 : id(id), shm(std::move(shm)), size(size) {} | 74 : id(id), shm(std::move(shm)), size(size) {} |
| 75 const int32_t id; | 75 const int32_t id; |
| 76 const std::unique_ptr<base::SharedMemory> shm; | 76 const std::unique_ptr<base::SharedMemory> shm; |
| 77 const size_t size; | 77 const size_t size; |
| 78 | 78 |
| 79 private: | 79 private: |
| 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 : main_client_task_runner_(base::ThreadTaskRunnerHandle::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(main_client_task_runner_->BelongsToCurrentThread()); |
| 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(main_client_task_runner_->BelongsToCurrentThread()); |
| 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(main_client_task_runner_->BelongsToCurrentThread()); |
| 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; |
| 150 } | 150 } |
| 151 | 151 |
| 152 encoder_thread_.init_com_with_mta(false); | 152 encoder_thread_.init_com_with_mta(false); |
| 153 if (!encoder_thread_.Start()) { | 153 if (!encoder_thread_.Start()) { |
| 154 DLOG(ERROR) << "Failed spawning encoder thread."; | 154 DLOG(ERROR) << "Failed spawning encoder thread."; |
| 155 return false; | 155 return false; |
| 156 } | 156 } |
| 157 encoder_thread_task_runner_ = encoder_thread_.task_runner(); | 157 encoder_thread_task_runner_ = encoder_thread_.task_runner(); |
| 158 | 158 |
| 159 if (!CreateHardwareEncoderMFT()) { | 159 if (!CreateHardwareEncoderMFT()) { |
| 160 DLOG(ERROR) << "Failed creating a hardware encoder MFT."; | 160 DLOG(ERROR) << "Failed creating a hardware encoder MFT."; |
| 161 return false; | 161 return false; |
| 162 } | 162 } |
| 163 | 163 |
| 164 client_ptr_factory_.reset(new base::WeakPtrFactory<Client>(client)); | 164 main_client_weak_factory_.reset(new base::WeakPtrFactory<Client>(client)); |
| 165 client_ = client_ptr_factory_->GetWeakPtr(); | 165 main_client_ = main_client_weak_factory_->GetWeakPtr(); |
| 166 input_visible_size_ = input_visible_size; | 166 input_visible_size_ = input_visible_size; |
| 167 frame_rate_ = kMaxFrameRateNumerator / kMaxFrameRateDenominator; | 167 frame_rate_ = kMaxFrameRateNumerator / kMaxFrameRateDenominator; |
| 168 target_bitrate_ = initial_bitrate; | 168 target_bitrate_ = initial_bitrate; |
| 169 bitstream_buffer_size_ = input_visible_size.GetArea(); | 169 bitstream_buffer_size_ = input_visible_size.GetArea(); |
| 170 u_plane_offset_ = | 170 u_plane_offset_ = |
| 171 VideoFrame::PlaneSize(PIXEL_FORMAT_I420, VideoFrame::kYPlane, | 171 VideoFrame::PlaneSize(PIXEL_FORMAT_I420, VideoFrame::kYPlane, |
| 172 input_visible_size_) | 172 input_visible_size_) |
| 173 .GetArea(); | 173 .GetArea(); |
| 174 v_plane_offset_ = | 174 v_plane_offset_ = |
| 175 u_plane_offset_ + | 175 u_plane_offset_ + |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 189 } | 189 } |
| 190 input_sample_.Attach(mf::CreateEmptySampleWithBuffer( | 190 input_sample_.Attach(mf::CreateEmptySampleWithBuffer( |
| 191 VideoFrame::AllocationSize(PIXEL_FORMAT_I420, input_visible_size_), 2)); | 191 VideoFrame::AllocationSize(PIXEL_FORMAT_I420, input_visible_size_), 2)); |
| 192 output_sample_.Attach(mf::CreateEmptySampleWithBuffer( | 192 output_sample_.Attach(mf::CreateEmptySampleWithBuffer( |
| 193 bitstream_buffer_size_ * kOutputSampleBufferSizeRatio, 2)); | 193 bitstream_buffer_size_ * kOutputSampleBufferSizeRatio, 2)); |
| 194 | 194 |
| 195 HRESULT hr = | 195 HRESULT hr = |
| 196 encoder_->ProcessMessage(MFT_MESSAGE_NOTIFY_BEGIN_STREAMING, NULL); | 196 encoder_->ProcessMessage(MFT_MESSAGE_NOTIFY_BEGIN_STREAMING, NULL); |
| 197 RETURN_ON_HR_FAILURE(hr, "Couldn't set ProcessMessage", false); | 197 RETURN_ON_HR_FAILURE(hr, "Couldn't set ProcessMessage", false); |
| 198 | 198 |
| 199 client_task_runner_->PostTask( | 199 // Pin all client callbacks to the main task runner initially. It can be |
| 200 FROM_HERE, | 200 // reassigned by TryToSetupEncodeOnSeparateThread(). |
| 201 base::Bind(&Client::RequireBitstreamBuffers, client_, kNumInputBuffers, | 201 encode_client_task_runner_ = main_client_task_runner_; |
|
Pawel Osciak
2016/11/07 02:00:36
Perhaps do this only if (!encoder_client_task_runn
emircan
2016/11/07 19:35:29
Done.
| |
| 202 input_visible_size_, bitstream_buffer_size_)); | 202 encode_client_ = main_client_; |
| 203 | |
| 204 main_client_task_runner_->PostTask( | |
| 205 FROM_HERE, base::Bind(&Client::RequireBitstreamBuffers, main_client_, | |
| 206 kNumInputBuffers, input_visible_size_, | |
| 207 bitstream_buffer_size_)); | |
| 203 return SUCCEEDED(hr); | 208 return SUCCEEDED(hr); |
| 204 } | 209 } |
| 205 | 210 |
| 206 void MediaFoundationVideoEncodeAccelerator::Encode( | 211 void MediaFoundationVideoEncodeAccelerator::Encode( |
| 207 const scoped_refptr<VideoFrame>& frame, | 212 const scoped_refptr<VideoFrame>& frame, |
| 208 bool force_keyframe) { | 213 bool force_keyframe) { |
| 209 DVLOG(3) << __func__; | 214 DVLOG(3) << __func__; |
| 210 DCHECK(sequence_checker_.CalledOnValidSequence()); | 215 DCHECK(encode_client_task_runner_->BelongsToCurrentThread()); |
| 211 | 216 |
| 212 encoder_thread_task_runner_->PostTask( | 217 encoder_thread_task_runner_->PostTask( |
| 213 FROM_HERE, base::Bind(&MediaFoundationVideoEncodeAccelerator::EncodeTask, | 218 FROM_HERE, base::Bind(&MediaFoundationVideoEncodeAccelerator::EncodeTask, |
| 214 encoder_task_weak_factory_.GetWeakPtr(), frame, | 219 encoder_task_weak_factory_.GetWeakPtr(), frame, |
| 215 force_keyframe)); | 220 force_keyframe)); |
| 216 } | 221 } |
| 217 | 222 |
| 218 void MediaFoundationVideoEncodeAccelerator::UseOutputBitstreamBuffer( | 223 void MediaFoundationVideoEncodeAccelerator::UseOutputBitstreamBuffer( |
| 219 const BitstreamBuffer& buffer) { | 224 const BitstreamBuffer& buffer) { |
| 220 DVLOG(3) << __func__ << ": buffer size=" << buffer.size(); | 225 DVLOG(3) << __func__ << ": buffer size=" << buffer.size(); |
| 221 DCHECK(sequence_checker_.CalledOnValidSequence()); | 226 DCHECK(encode_client_task_runner_->BelongsToCurrentThread()); |
| 222 | 227 |
| 223 if (buffer.size() < bitstream_buffer_size_) { | 228 if (buffer.size() < bitstream_buffer_size_) { |
| 224 DLOG(ERROR) << "Output BitstreamBuffer isn't big enough: " << buffer.size() | 229 DLOG(ERROR) << "Output BitstreamBuffer isn't big enough: " << buffer.size() |
| 225 << " vs. " << bitstream_buffer_size_; | 230 << " vs. " << bitstream_buffer_size_; |
| 226 client_->NotifyError(kInvalidArgumentError); | 231 NotifyError(kInvalidArgumentError); |
| 227 return; | 232 return; |
| 228 } | 233 } |
| 229 | 234 |
| 230 std::unique_ptr<base::SharedMemory> shm( | 235 std::unique_ptr<base::SharedMemory> shm( |
| 231 new base::SharedMemory(buffer.handle(), false)); | 236 new base::SharedMemory(buffer.handle(), false)); |
| 232 if (!shm->Map(buffer.size())) { | 237 if (!shm->Map(buffer.size())) { |
| 233 DLOG(ERROR) << "Failed mapping shared memory."; | 238 DLOG(ERROR) << "Failed mapping shared memory."; |
| 234 client_->NotifyError(kPlatformFailureError); | 239 NotifyError(kPlatformFailureError); |
| 235 return; | 240 return; |
| 236 } | 241 } |
| 237 | 242 |
| 238 std::unique_ptr<BitstreamBufferRef> buffer_ref( | 243 std::unique_ptr<BitstreamBufferRef> buffer_ref( |
| 239 new BitstreamBufferRef(buffer.id(), std::move(shm), buffer.size())); | 244 new BitstreamBufferRef(buffer.id(), std::move(shm), buffer.size())); |
| 240 encoder_thread_task_runner_->PostTask( | 245 encoder_thread_task_runner_->PostTask( |
| 241 FROM_HERE, | 246 FROM_HERE, |
| 242 base::Bind( | 247 base::Bind( |
| 243 &MediaFoundationVideoEncodeAccelerator::UseOutputBitstreamBufferTask, | 248 &MediaFoundationVideoEncodeAccelerator::UseOutputBitstreamBufferTask, |
| 244 encoder_task_weak_factory_.GetWeakPtr(), base::Passed(&buffer_ref))); | 249 encoder_task_weak_factory_.GetWeakPtr(), base::Passed(&buffer_ref))); |
| 245 } | 250 } |
| 246 | 251 |
| 247 void MediaFoundationVideoEncodeAccelerator::RequestEncodingParametersChange( | 252 void MediaFoundationVideoEncodeAccelerator::RequestEncodingParametersChange( |
| 248 uint32_t bitrate, | 253 uint32_t bitrate, |
| 249 uint32_t framerate) { | 254 uint32_t framerate) { |
| 250 DVLOG(3) << __func__ << ": bitrate=" << bitrate | 255 DVLOG(3) << __func__ << ": bitrate=" << bitrate |
| 251 << ": framerate=" << framerate; | 256 << ": framerate=" << framerate; |
| 252 DCHECK(sequence_checker_.CalledOnValidSequence()); | 257 DCHECK(encode_client_task_runner_->BelongsToCurrentThread()); |
| 253 | 258 |
| 254 encoder_thread_task_runner_->PostTask( | 259 encoder_thread_task_runner_->PostTask( |
| 255 FROM_HERE, | 260 FROM_HERE, |
| 256 base::Bind(&MediaFoundationVideoEncodeAccelerator:: | 261 base::Bind(&MediaFoundationVideoEncodeAccelerator:: |
| 257 RequestEncodingParametersChangeTask, | 262 RequestEncodingParametersChangeTask, |
| 258 encoder_task_weak_factory_.GetWeakPtr(), bitrate, framerate)); | 263 encoder_task_weak_factory_.GetWeakPtr(), bitrate, framerate)); |
| 259 } | 264 } |
| 260 | 265 |
| 261 void MediaFoundationVideoEncodeAccelerator::Destroy() { | 266 void MediaFoundationVideoEncodeAccelerator::Destroy() { |
| 262 DVLOG(3) << __func__; | 267 DVLOG(3) << __func__; |
| 263 DCHECK(sequence_checker_.CalledOnValidSequence()); | 268 DCHECK(main_client_task_runner_->BelongsToCurrentThread()); |
| 264 | 269 |
| 265 // Cancel all callbacks. | 270 // Cancel all callbacks. |
| 266 client_ptr_factory_.reset(); | 271 main_client_weak_factory_.reset(); |
| 267 | 272 |
| 268 if (encoder_thread_.IsRunning()) { | 273 if (encoder_thread_.IsRunning()) { |
| 269 encoder_thread_task_runner_->PostTask( | 274 encoder_thread_task_runner_->PostTask( |
| 270 FROM_HERE, | 275 FROM_HERE, |
| 271 base::Bind(&MediaFoundationVideoEncodeAccelerator::DestroyTask, | 276 base::Bind(&MediaFoundationVideoEncodeAccelerator::DestroyTask, |
| 272 encoder_task_weak_factory_.GetWeakPtr())); | 277 encoder_task_weak_factory_.GetWeakPtr())); |
| 273 encoder_thread_.Stop(); | 278 encoder_thread_.Stop(); |
| 274 } | 279 } |
| 275 | 280 |
| 276 delete this; | 281 delete this; |
| 277 } | 282 } |
| 278 | 283 |
| 284 bool MediaFoundationVideoEncodeAccelerator::TryToSetupEncodeOnSeparateThread( | |
| 285 const base::WeakPtr<Client>& encode_client, | |
| 286 const scoped_refptr<base::SingleThreadTaskRunner>& encode_task_runner) { | |
| 287 DVLOG(3) << __func__; | |
| 288 DCHECK(main_client_task_runner_->BelongsToCurrentThread()); | |
| 289 encode_client_ = encode_client; | |
| 290 encode_client_task_runner_ = encode_task_runner; | |
| 291 return true; | |
| 292 } | |
| 293 | |
| 279 // static | 294 // static |
| 280 void MediaFoundationVideoEncodeAccelerator::PreSandboxInitialization() { | 295 void MediaFoundationVideoEncodeAccelerator::PreSandboxInitialization() { |
| 281 for (const wchar_t* mfdll : kMediaFoundationVideoEncoderDLLs) | 296 for (const wchar_t* mfdll : kMediaFoundationVideoEncoderDLLs) |
| 282 ::LoadLibrary(mfdll); | 297 ::LoadLibrary(mfdll); |
| 283 } | 298 } |
| 284 | 299 |
| 285 bool MediaFoundationVideoEncodeAccelerator::CreateHardwareEncoderMFT() { | 300 bool MediaFoundationVideoEncodeAccelerator::CreateHardwareEncoderMFT() { |
| 286 DVLOG(3) << __func__; | 301 DVLOG(3) << __func__; |
| 287 DCHECK(sequence_checker_.CalledOnValidSequence()); | 302 DCHECK(main_client_task_runner_->BelongsToCurrentThread()); |
| 288 | 303 |
| 289 if (base::win::GetVersion() < base::win::VERSION_WIN8) { | 304 if (base::win::GetVersion() < base::win::VERSION_WIN8) { |
| 290 DVLOG(ERROR) << "Windows versions earlier than 8 are not supported."; | 305 DVLOG(ERROR) << "Windows versions earlier than 8 are not supported."; |
| 291 return false; | 306 return false; |
| 292 } | 307 } |
| 293 | 308 |
| 294 for (const wchar_t* mfdll : kMediaFoundationVideoEncoderDLLs) { | 309 for (const wchar_t* mfdll : kMediaFoundationVideoEncoderDLLs) { |
| 295 if (!::GetModuleHandle(mfdll)) { | 310 if (!::GetModuleHandle(mfdll)) { |
| 296 DVLOG(ERROR) << mfdll << " is required for encoding"; | 311 DVLOG(ERROR) << mfdll << " is required for encoding"; |
| 297 return false; | 312 return false; |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 314 &output_info, NULL, &CLSIDs, &count); | 329 &output_info, NULL, &CLSIDs, &count); |
| 315 RETURN_ON_HR_FAILURE(hr, "Couldn't enumerate hardware encoder", false); | 330 RETURN_ON_HR_FAILURE(hr, "Couldn't enumerate hardware encoder", false); |
| 316 RETURN_ON_FAILURE((count > 0), "No HW encoder found", false); | 331 RETURN_ON_FAILURE((count > 0), "No HW encoder found", false); |
| 317 DVLOG(3) << "HW encoder(s) found: " << count; | 332 DVLOG(3) << "HW encoder(s) found: " << count; |
| 318 hr = encoder_.CreateInstance(CLSIDs[0]); | 333 hr = encoder_.CreateInstance(CLSIDs[0]); |
| 319 RETURN_ON_HR_FAILURE(hr, "Couldn't activate hardware encoder", false); | 334 RETURN_ON_HR_FAILURE(hr, "Couldn't activate hardware encoder", false); |
| 320 return true; | 335 return true; |
| 321 } | 336 } |
| 322 | 337 |
| 323 bool MediaFoundationVideoEncodeAccelerator::InitializeInputOutputSamples() { | 338 bool MediaFoundationVideoEncodeAccelerator::InitializeInputOutputSamples() { |
| 324 DCHECK(sequence_checker_.CalledOnValidSequence()); | 339 DCHECK(main_client_task_runner_->BelongsToCurrentThread()); |
| 325 | 340 |
| 326 // Initialize output parameters. | 341 // Initialize output parameters. |
| 327 HRESULT hr = MFCreateMediaType(imf_output_media_type_.Receive()); | 342 HRESULT hr = MFCreateMediaType(imf_output_media_type_.Receive()); |
| 328 RETURN_ON_HR_FAILURE(hr, "Couldn't create media type", false); | 343 RETURN_ON_HR_FAILURE(hr, "Couldn't create media type", false); |
| 329 hr = imf_output_media_type_->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Video); | 344 hr = imf_output_media_type_->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Video); |
| 330 RETURN_ON_HR_FAILURE(hr, "Couldn't set media type", false); | 345 RETURN_ON_HR_FAILURE(hr, "Couldn't set media type", false); |
| 331 hr = imf_output_media_type_->SetGUID(MF_MT_SUBTYPE, MFVideoFormat_H264); | 346 hr = imf_output_media_type_->SetGUID(MF_MT_SUBTYPE, MFVideoFormat_H264); |
| 332 RETURN_ON_HR_FAILURE(hr, "Couldn't set video format", false); | 347 RETURN_ON_HR_FAILURE(hr, "Couldn't set video format", false); |
| 333 hr = imf_output_media_type_->SetUINT32(MF_MT_AVG_BITRATE, target_bitrate_); | 348 hr = imf_output_media_type_->SetUINT32(MF_MT_AVG_BITRATE, target_bitrate_); |
| 334 RETURN_ON_HR_FAILURE(hr, "Couldn't set bitrate", false); | 349 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, | 380 hr = imf_input_media_type_->SetUINT32(MF_MT_INTERLACE_MODE, |
| 366 MFVideoInterlace_Progressive); | 381 MFVideoInterlace_Progressive); |
| 367 RETURN_ON_HR_FAILURE(hr, "Couldn't set interlace mode", false); | 382 RETURN_ON_HR_FAILURE(hr, "Couldn't set interlace mode", false); |
| 368 hr = encoder_->SetInputType(0, imf_input_media_type_.get(), 0); | 383 hr = encoder_->SetInputType(0, imf_input_media_type_.get(), 0); |
| 369 RETURN_ON_HR_FAILURE(hr, "Couldn't set input media type", false); | 384 RETURN_ON_HR_FAILURE(hr, "Couldn't set input media type", false); |
| 370 | 385 |
| 371 return SUCCEEDED(hr); | 386 return SUCCEEDED(hr); |
| 372 } | 387 } |
| 373 | 388 |
| 374 bool MediaFoundationVideoEncodeAccelerator::SetEncoderModes() { | 389 bool MediaFoundationVideoEncodeAccelerator::SetEncoderModes() { |
| 375 DCHECK(sequence_checker_.CalledOnValidSequence()); | 390 DCHECK(main_client_task_runner_->BelongsToCurrentThread()); |
| 376 | 391 |
| 377 HRESULT hr = encoder_.QueryInterface(IID_ICodecAPI, codec_api_.ReceiveVoid()); | 392 HRESULT hr = encoder_.QueryInterface(IID_ICodecAPI, codec_api_.ReceiveVoid()); |
| 378 RETURN_ON_HR_FAILURE(hr, "Couldn't get ICodecAPI", false); | 393 RETURN_ON_HR_FAILURE(hr, "Couldn't get ICodecAPI", false); |
| 379 VARIANT var; | 394 VARIANT var; |
| 380 var.vt = VT_UI4; | 395 var.vt = VT_UI4; |
| 381 var.ulVal = eAVEncCommonRateControlMode_CBR; | 396 var.ulVal = eAVEncCommonRateControlMode_CBR; |
| 382 hr = codec_api_->SetValue(&CODECAPI_AVEncCommonRateControlMode, &var); | 397 hr = codec_api_->SetValue(&CODECAPI_AVEncCommonRateControlMode, &var); |
| 383 RETURN_ON_HR_FAILURE(hr, "Couldn't set CommonRateControlMode", false); | 398 RETURN_ON_HR_FAILURE(hr, "Couldn't set CommonRateControlMode", false); |
| 384 var.ulVal = target_bitrate_; | 399 var.ulVal = target_bitrate_; |
| 385 hr = codec_api_->SetValue(&CODECAPI_AVEncCommonMeanBitRate, &var); | 400 hr = codec_api_->SetValue(&CODECAPI_AVEncCommonMeanBitRate, &var); |
| 386 RETURN_ON_HR_FAILURE(hr, "Couldn't set bitrate", false); | 401 RETURN_ON_HR_FAILURE(hr, "Couldn't set bitrate", false); |
| 387 var.ulVal = eAVEncAdaptiveMode_FrameRate; | 402 var.ulVal = eAVEncAdaptiveMode_FrameRate; |
| 388 hr = codec_api_->SetValue(&CODECAPI_AVEncAdaptiveMode, &var); | 403 hr = codec_api_->SetValue(&CODECAPI_AVEncAdaptiveMode, &var); |
| 389 RETURN_ON_HR_FAILURE(hr, "Couldn't set FrameRate", false); | 404 RETURN_ON_HR_FAILURE(hr, "Couldn't set FrameRate", false); |
| 390 var.vt = VT_BOOL; | 405 var.vt = VT_BOOL; |
| 391 var.boolVal = VARIANT_TRUE; | 406 var.boolVal = VARIANT_TRUE; |
| 392 hr = codec_api_->SetValue(&CODECAPI_AVLowLatencyMode, &var); | 407 hr = codec_api_->SetValue(&CODECAPI_AVLowLatencyMode, &var); |
| 393 RETURN_ON_HR_FAILURE(hr, "Couldn't set LowLatencyMode", false); | 408 RETURN_ON_HR_FAILURE(hr, "Couldn't set LowLatencyMode", false); |
| 394 return SUCCEEDED(hr); | 409 return SUCCEEDED(hr); |
| 395 } | 410 } |
| 396 | 411 |
| 397 void MediaFoundationVideoEncodeAccelerator::NotifyError( | 412 void MediaFoundationVideoEncodeAccelerator::NotifyError( |
| 398 VideoEncodeAccelerator::Error error) { | 413 VideoEncodeAccelerator::Error error) { |
| 399 DCHECK(encoder_thread_task_runner_->BelongsToCurrentThread()); | 414 DCHECK(encoder_thread_task_runner_->BelongsToCurrentThread()); |
| 400 client_task_runner_->PostTask( | 415 main_client_task_runner_->PostTask( |
| 401 FROM_HERE, base::Bind(&Client::NotifyError, client_, error)); | 416 FROM_HERE, base::Bind(&Client::NotifyError, main_client_, error)); |
| 402 } | 417 } |
| 403 | 418 |
| 404 void MediaFoundationVideoEncodeAccelerator::EncodeTask( | 419 void MediaFoundationVideoEncodeAccelerator::EncodeTask( |
| 405 scoped_refptr<VideoFrame> frame, | 420 scoped_refptr<VideoFrame> frame, |
| 406 bool force_keyframe) { | 421 bool force_keyframe) { |
| 407 DVLOG(3) << __func__; | 422 DVLOG(3) << __func__; |
| 408 DCHECK(encoder_thread_task_runner_->BelongsToCurrentThread()); | 423 DCHECK(encoder_thread_task_runner_->BelongsToCurrentThread()); |
| 409 | 424 |
| 410 base::win::ScopedComPtr<IMFMediaBuffer> input_buffer; | 425 base::win::ScopedComPtr<IMFMediaBuffer> input_buffer; |
| 411 input_sample_->GetBufferByIndex(0, input_buffer.Receive()); | 426 input_sample_->GetBufferByIndex(0, input_buffer.Receive()); |
| (...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 508 | 523 |
| 509 std::unique_ptr<MediaFoundationVideoEncodeAccelerator::BitstreamBufferRef> | 524 std::unique_ptr<MediaFoundationVideoEncodeAccelerator::BitstreamBufferRef> |
| 510 buffer_ref = std::move(bitstream_buffer_queue_.front()); | 525 buffer_ref = std::move(bitstream_buffer_queue_.front()); |
| 511 bitstream_buffer_queue_.pop_front(); | 526 bitstream_buffer_queue_.pop_front(); |
| 512 | 527 |
| 513 { | 528 { |
| 514 MediaBufferScopedPointer scoped_buffer(output_buffer.get()); | 529 MediaBufferScopedPointer scoped_buffer(output_buffer.get()); |
| 515 memcpy(buffer_ref->shm->memory(), scoped_buffer.get(), size); | 530 memcpy(buffer_ref->shm->memory(), scoped_buffer.get(), size); |
| 516 } | 531 } |
| 517 | 532 |
| 518 client_task_runner_->PostTask( | 533 encode_client_task_runner_->PostTask( |
| 519 FROM_HERE, base::Bind(&Client::BitstreamBufferReady, client_, | 534 FROM_HERE, base::Bind(&Client::BitstreamBufferReady, encode_client_, |
| 520 buffer_ref->id, size, keyframe, timestamp)); | 535 buffer_ref->id, size, keyframe, timestamp)); |
| 521 | 536 |
| 522 // Keep calling ProcessOutput recursively until MF_E_TRANSFORM_NEED_MORE_INPUT | 537 // Keep calling ProcessOutput recursively until MF_E_TRANSFORM_NEED_MORE_INPUT |
| 523 // is returned to flush out all the output. | 538 // is returned to flush out all the output. |
| 524 ProcessOutput(); | 539 ProcessOutput(); |
| 525 } | 540 } |
| 526 | 541 |
| 527 void MediaFoundationVideoEncodeAccelerator::UseOutputBitstreamBufferTask( | 542 void MediaFoundationVideoEncodeAccelerator::UseOutputBitstreamBufferTask( |
| 528 std::unique_ptr<BitstreamBufferRef> buffer_ref) { | 543 std::unique_ptr<BitstreamBufferRef> buffer_ref) { |
| 529 DVLOG(3) << __func__; | 544 DVLOG(3) << __func__; |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 543 | 558 |
| 544 void MediaFoundationVideoEncodeAccelerator::ReturnBitstreamBuffer( | 559 void MediaFoundationVideoEncodeAccelerator::ReturnBitstreamBuffer( |
| 545 std::unique_ptr<EncodeOutput> encode_output, | 560 std::unique_ptr<EncodeOutput> encode_output, |
| 546 std::unique_ptr<MediaFoundationVideoEncodeAccelerator::BitstreamBufferRef> | 561 std::unique_ptr<MediaFoundationVideoEncodeAccelerator::BitstreamBufferRef> |
| 547 buffer_ref) { | 562 buffer_ref) { |
| 548 DVLOG(3) << __func__; | 563 DVLOG(3) << __func__; |
| 549 DCHECK(encoder_thread_task_runner_->BelongsToCurrentThread()); | 564 DCHECK(encoder_thread_task_runner_->BelongsToCurrentThread()); |
| 550 | 565 |
| 551 memcpy(buffer_ref->shm->memory(), encode_output->memory(), | 566 memcpy(buffer_ref->shm->memory(), encode_output->memory(), |
| 552 encode_output->size()); | 567 encode_output->size()); |
| 553 client_task_runner_->PostTask( | 568 encode_client_task_runner_->PostTask( |
| 554 FROM_HERE, | 569 FROM_HERE, |
| 555 base::Bind(&Client::BitstreamBufferReady, client_, buffer_ref->id, | 570 base::Bind(&Client::BitstreamBufferReady, encode_client_, buffer_ref->id, |
| 556 encode_output->size(), encode_output->keyframe, | 571 encode_output->size(), encode_output->keyframe, |
| 557 encode_output->capture_timestamp)); | 572 encode_output->capture_timestamp)); |
| 558 } | 573 } |
| 559 | 574 |
| 560 void MediaFoundationVideoEncodeAccelerator::RequestEncodingParametersChangeTask( | 575 void MediaFoundationVideoEncodeAccelerator::RequestEncodingParametersChangeTask( |
| 561 uint32_t bitrate, | 576 uint32_t bitrate, |
| 562 uint32_t framerate) { | 577 uint32_t framerate) { |
| 563 DVLOG(3) << __func__; | 578 DVLOG(3) << __func__; |
| 564 DCHECK(encoder_thread_task_runner_->BelongsToCurrentThread()); | 579 DCHECK(encoder_thread_task_runner_->BelongsToCurrentThread()); |
| 565 | 580 |
| (...skipping 26 matching lines...) Expand all Loading... | |
| 592 void MediaFoundationVideoEncodeAccelerator::ReleaseEncoderResources() { | 607 void MediaFoundationVideoEncodeAccelerator::ReleaseEncoderResources() { |
| 593 encoder_.Release(); | 608 encoder_.Release(); |
| 594 codec_api_.Release(); | 609 codec_api_.Release(); |
| 595 imf_input_media_type_.Release(); | 610 imf_input_media_type_.Release(); |
| 596 imf_output_media_type_.Release(); | 611 imf_output_media_type_.Release(); |
| 597 input_sample_.Release(); | 612 input_sample_.Release(); |
| 598 output_sample_.Release(); | 613 output_sample_.Release(); |
| 599 } | 614 } |
| 600 | 615 |
| 601 } // namespace content | 616 } // namespace content |
| OLD | NEW |