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 if (!encode_client_task_runner_) { |
202 input_visible_size_, bitstream_buffer_size_)); | 202 encode_client_task_runner_ = main_client_task_runner_; |
| 203 encode_client_ = main_client_; |
| 204 } |
| 205 |
| 206 main_client_task_runner_->PostTask( |
| 207 FROM_HERE, base::Bind(&Client::RequireBitstreamBuffers, main_client_, |
| 208 kNumInputBuffers, input_visible_size_, |
| 209 bitstream_buffer_size_)); |
203 return SUCCEEDED(hr); | 210 return SUCCEEDED(hr); |
204 } | 211 } |
205 | 212 |
206 void MediaFoundationVideoEncodeAccelerator::Encode( | 213 void MediaFoundationVideoEncodeAccelerator::Encode( |
207 const scoped_refptr<VideoFrame>& frame, | 214 const scoped_refptr<VideoFrame>& frame, |
208 bool force_keyframe) { | 215 bool force_keyframe) { |
209 DVLOG(3) << __func__; | 216 DVLOG(3) << __func__; |
210 DCHECK(sequence_checker_.CalledOnValidSequence()); | 217 DCHECK(encode_client_task_runner_->BelongsToCurrentThread()); |
211 | 218 |
212 encoder_thread_task_runner_->PostTask( | 219 encoder_thread_task_runner_->PostTask( |
213 FROM_HERE, base::Bind(&MediaFoundationVideoEncodeAccelerator::EncodeTask, | 220 FROM_HERE, base::Bind(&MediaFoundationVideoEncodeAccelerator::EncodeTask, |
214 encoder_task_weak_factory_.GetWeakPtr(), frame, | 221 encoder_task_weak_factory_.GetWeakPtr(), frame, |
215 force_keyframe)); | 222 force_keyframe)); |
216 } | 223 } |
217 | 224 |
218 void MediaFoundationVideoEncodeAccelerator::UseOutputBitstreamBuffer( | 225 void MediaFoundationVideoEncodeAccelerator::UseOutputBitstreamBuffer( |
219 const BitstreamBuffer& buffer) { | 226 const BitstreamBuffer& buffer) { |
220 DVLOG(3) << __func__ << ": buffer size=" << buffer.size(); | 227 DVLOG(3) << __func__ << ": buffer size=" << buffer.size(); |
221 DCHECK(sequence_checker_.CalledOnValidSequence()); | 228 DCHECK(encode_client_task_runner_->BelongsToCurrentThread()); |
222 | 229 |
223 if (buffer.size() < bitstream_buffer_size_) { | 230 if (buffer.size() < bitstream_buffer_size_) { |
224 DLOG(ERROR) << "Output BitstreamBuffer isn't big enough: " << buffer.size() | 231 DLOG(ERROR) << "Output BitstreamBuffer isn't big enough: " << buffer.size() |
225 << " vs. " << bitstream_buffer_size_; | 232 << " vs. " << bitstream_buffer_size_; |
226 client_->NotifyError(kInvalidArgumentError); | 233 NotifyError(kInvalidArgumentError); |
227 return; | 234 return; |
228 } | 235 } |
229 | 236 |
230 std::unique_ptr<base::SharedMemory> shm( | 237 std::unique_ptr<base::SharedMemory> shm( |
231 new base::SharedMemory(buffer.handle(), false)); | 238 new base::SharedMemory(buffer.handle(), false)); |
232 if (!shm->Map(buffer.size())) { | 239 if (!shm->Map(buffer.size())) { |
233 DLOG(ERROR) << "Failed mapping shared memory."; | 240 DLOG(ERROR) << "Failed mapping shared memory."; |
234 client_->NotifyError(kPlatformFailureError); | 241 NotifyError(kPlatformFailureError); |
235 return; | 242 return; |
236 } | 243 } |
237 | 244 |
238 std::unique_ptr<BitstreamBufferRef> buffer_ref( | 245 std::unique_ptr<BitstreamBufferRef> buffer_ref( |
239 new BitstreamBufferRef(buffer.id(), std::move(shm), buffer.size())); | 246 new BitstreamBufferRef(buffer.id(), std::move(shm), buffer.size())); |
240 encoder_thread_task_runner_->PostTask( | 247 encoder_thread_task_runner_->PostTask( |
241 FROM_HERE, | 248 FROM_HERE, |
242 base::Bind( | 249 base::Bind( |
243 &MediaFoundationVideoEncodeAccelerator::UseOutputBitstreamBufferTask, | 250 &MediaFoundationVideoEncodeAccelerator::UseOutputBitstreamBufferTask, |
244 encoder_task_weak_factory_.GetWeakPtr(), base::Passed(&buffer_ref))); | 251 encoder_task_weak_factory_.GetWeakPtr(), base::Passed(&buffer_ref))); |
245 } | 252 } |
246 | 253 |
247 void MediaFoundationVideoEncodeAccelerator::RequestEncodingParametersChange( | 254 void MediaFoundationVideoEncodeAccelerator::RequestEncodingParametersChange( |
248 uint32_t bitrate, | 255 uint32_t bitrate, |
249 uint32_t framerate) { | 256 uint32_t framerate) { |
250 DVLOG(3) << __func__ << ": bitrate=" << bitrate | 257 DVLOG(3) << __func__ << ": bitrate=" << bitrate |
251 << ": framerate=" << framerate; | 258 << ": framerate=" << framerate; |
252 DCHECK(sequence_checker_.CalledOnValidSequence()); | 259 DCHECK(encode_client_task_runner_->BelongsToCurrentThread()); |
253 | 260 |
254 encoder_thread_task_runner_->PostTask( | 261 encoder_thread_task_runner_->PostTask( |
255 FROM_HERE, | 262 FROM_HERE, |
256 base::Bind(&MediaFoundationVideoEncodeAccelerator:: | 263 base::Bind(&MediaFoundationVideoEncodeAccelerator:: |
257 RequestEncodingParametersChangeTask, | 264 RequestEncodingParametersChangeTask, |
258 encoder_task_weak_factory_.GetWeakPtr(), bitrate, framerate)); | 265 encoder_task_weak_factory_.GetWeakPtr(), bitrate, framerate)); |
259 } | 266 } |
260 | 267 |
261 void MediaFoundationVideoEncodeAccelerator::Destroy() { | 268 void MediaFoundationVideoEncodeAccelerator::Destroy() { |
262 DVLOG(3) << __func__; | 269 DVLOG(3) << __func__; |
263 DCHECK(sequence_checker_.CalledOnValidSequence()); | 270 DCHECK(main_client_task_runner_->BelongsToCurrentThread()); |
264 | 271 |
265 // Cancel all callbacks. | 272 // Cancel all callbacks. |
266 client_ptr_factory_.reset(); | 273 main_client_weak_factory_.reset(); |
267 | 274 |
268 if (encoder_thread_.IsRunning()) { | 275 if (encoder_thread_.IsRunning()) { |
269 encoder_thread_task_runner_->PostTask( | 276 encoder_thread_task_runner_->PostTask( |
270 FROM_HERE, | 277 FROM_HERE, |
271 base::Bind(&MediaFoundationVideoEncodeAccelerator::DestroyTask, | 278 base::Bind(&MediaFoundationVideoEncodeAccelerator::DestroyTask, |
272 encoder_task_weak_factory_.GetWeakPtr())); | 279 encoder_task_weak_factory_.GetWeakPtr())); |
273 encoder_thread_.Stop(); | 280 encoder_thread_.Stop(); |
274 } | 281 } |
275 | 282 |
276 delete this; | 283 delete this; |
277 } | 284 } |
278 | 285 |
| 286 bool MediaFoundationVideoEncodeAccelerator::TryToSetupEncodeOnSeparateThread( |
| 287 const base::WeakPtr<Client>& encode_client, |
| 288 const scoped_refptr<base::SingleThreadTaskRunner>& encode_task_runner) { |
| 289 DVLOG(3) << __func__; |
| 290 DCHECK(main_client_task_runner_->BelongsToCurrentThread()); |
| 291 encode_client_ = encode_client; |
| 292 encode_client_task_runner_ = encode_task_runner; |
| 293 return true; |
| 294 } |
| 295 |
279 // static | 296 // static |
280 void MediaFoundationVideoEncodeAccelerator::PreSandboxInitialization() { | 297 void MediaFoundationVideoEncodeAccelerator::PreSandboxInitialization() { |
281 for (const wchar_t* mfdll : kMediaFoundationVideoEncoderDLLs) | 298 for (const wchar_t* mfdll : kMediaFoundationVideoEncoderDLLs) |
282 ::LoadLibrary(mfdll); | 299 ::LoadLibrary(mfdll); |
283 } | 300 } |
284 | 301 |
285 bool MediaFoundationVideoEncodeAccelerator::CreateHardwareEncoderMFT() { | 302 bool MediaFoundationVideoEncodeAccelerator::CreateHardwareEncoderMFT() { |
286 DVLOG(3) << __func__; | 303 DVLOG(3) << __func__; |
287 DCHECK(sequence_checker_.CalledOnValidSequence()); | 304 DCHECK(main_client_task_runner_->BelongsToCurrentThread()); |
288 | 305 |
289 if (base::win::GetVersion() < base::win::VERSION_WIN8) { | 306 if (base::win::GetVersion() < base::win::VERSION_WIN8) { |
290 DVLOG(ERROR) << "Windows versions earlier than 8 are not supported."; | 307 DVLOG(ERROR) << "Windows versions earlier than 8 are not supported."; |
291 return false; | 308 return false; |
292 } | 309 } |
293 | 310 |
294 for (const wchar_t* mfdll : kMediaFoundationVideoEncoderDLLs) { | 311 for (const wchar_t* mfdll : kMediaFoundationVideoEncoderDLLs) { |
295 if (!::GetModuleHandle(mfdll)) { | 312 if (!::GetModuleHandle(mfdll)) { |
296 DVLOG(ERROR) << mfdll << " is required for encoding"; | 313 DVLOG(ERROR) << mfdll << " is required for encoding"; |
297 return false; | 314 return false; |
(...skipping 16 matching lines...) Expand all Loading... |
314 &output_info, NULL, &CLSIDs, &count); | 331 &output_info, NULL, &CLSIDs, &count); |
315 RETURN_ON_HR_FAILURE(hr, "Couldn't enumerate hardware encoder", false); | 332 RETURN_ON_HR_FAILURE(hr, "Couldn't enumerate hardware encoder", false); |
316 RETURN_ON_FAILURE((count > 0), "No HW encoder found", false); | 333 RETURN_ON_FAILURE((count > 0), "No HW encoder found", false); |
317 DVLOG(3) << "HW encoder(s) found: " << count; | 334 DVLOG(3) << "HW encoder(s) found: " << count; |
318 hr = encoder_.CreateInstance(CLSIDs[0]); | 335 hr = encoder_.CreateInstance(CLSIDs[0]); |
319 RETURN_ON_HR_FAILURE(hr, "Couldn't activate hardware encoder", false); | 336 RETURN_ON_HR_FAILURE(hr, "Couldn't activate hardware encoder", false); |
320 return true; | 337 return true; |
321 } | 338 } |
322 | 339 |
323 bool MediaFoundationVideoEncodeAccelerator::InitializeInputOutputSamples() { | 340 bool MediaFoundationVideoEncodeAccelerator::InitializeInputOutputSamples() { |
324 DCHECK(sequence_checker_.CalledOnValidSequence()); | 341 DCHECK(main_client_task_runner_->BelongsToCurrentThread()); |
325 | 342 |
326 // Initialize output parameters. | 343 // Initialize output parameters. |
327 HRESULT hr = MFCreateMediaType(imf_output_media_type_.Receive()); | 344 HRESULT hr = MFCreateMediaType(imf_output_media_type_.Receive()); |
328 RETURN_ON_HR_FAILURE(hr, "Couldn't create media type", false); | 345 RETURN_ON_HR_FAILURE(hr, "Couldn't create media type", false); |
329 hr = imf_output_media_type_->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Video); | 346 hr = imf_output_media_type_->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Video); |
330 RETURN_ON_HR_FAILURE(hr, "Couldn't set media type", false); | 347 RETURN_ON_HR_FAILURE(hr, "Couldn't set media type", false); |
331 hr = imf_output_media_type_->SetGUID(MF_MT_SUBTYPE, MFVideoFormat_H264); | 348 hr = imf_output_media_type_->SetGUID(MF_MT_SUBTYPE, MFVideoFormat_H264); |
332 RETURN_ON_HR_FAILURE(hr, "Couldn't set video format", false); | 349 RETURN_ON_HR_FAILURE(hr, "Couldn't set video format", false); |
333 hr = imf_output_media_type_->SetUINT32(MF_MT_AVG_BITRATE, target_bitrate_); | 350 hr = imf_output_media_type_->SetUINT32(MF_MT_AVG_BITRATE, target_bitrate_); |
334 RETURN_ON_HR_FAILURE(hr, "Couldn't set bitrate", false); | 351 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, | 382 hr = imf_input_media_type_->SetUINT32(MF_MT_INTERLACE_MODE, |
366 MFVideoInterlace_Progressive); | 383 MFVideoInterlace_Progressive); |
367 RETURN_ON_HR_FAILURE(hr, "Couldn't set interlace mode", false); | 384 RETURN_ON_HR_FAILURE(hr, "Couldn't set interlace mode", false); |
368 hr = encoder_->SetInputType(0, imf_input_media_type_.get(), 0); | 385 hr = encoder_->SetInputType(0, imf_input_media_type_.get(), 0); |
369 RETURN_ON_HR_FAILURE(hr, "Couldn't set input media type", false); | 386 RETURN_ON_HR_FAILURE(hr, "Couldn't set input media type", false); |
370 | 387 |
371 return SUCCEEDED(hr); | 388 return SUCCEEDED(hr); |
372 } | 389 } |
373 | 390 |
374 bool MediaFoundationVideoEncodeAccelerator::SetEncoderModes() { | 391 bool MediaFoundationVideoEncodeAccelerator::SetEncoderModes() { |
375 DCHECK(sequence_checker_.CalledOnValidSequence()); | 392 DCHECK(main_client_task_runner_->BelongsToCurrentThread()); |
376 | 393 |
377 HRESULT hr = encoder_.QueryInterface(IID_ICodecAPI, codec_api_.ReceiveVoid()); | 394 HRESULT hr = encoder_.QueryInterface(IID_ICodecAPI, codec_api_.ReceiveVoid()); |
378 RETURN_ON_HR_FAILURE(hr, "Couldn't get ICodecAPI", false); | 395 RETURN_ON_HR_FAILURE(hr, "Couldn't get ICodecAPI", false); |
379 VARIANT var; | 396 VARIANT var; |
380 var.vt = VT_UI4; | 397 var.vt = VT_UI4; |
381 var.ulVal = eAVEncCommonRateControlMode_CBR; | 398 var.ulVal = eAVEncCommonRateControlMode_CBR; |
382 hr = codec_api_->SetValue(&CODECAPI_AVEncCommonRateControlMode, &var); | 399 hr = codec_api_->SetValue(&CODECAPI_AVEncCommonRateControlMode, &var); |
383 RETURN_ON_HR_FAILURE(hr, "Couldn't set CommonRateControlMode", false); | 400 RETURN_ON_HR_FAILURE(hr, "Couldn't set CommonRateControlMode", false); |
384 var.ulVal = target_bitrate_; | 401 var.ulVal = target_bitrate_; |
385 hr = codec_api_->SetValue(&CODECAPI_AVEncCommonMeanBitRate, &var); | 402 hr = codec_api_->SetValue(&CODECAPI_AVEncCommonMeanBitRate, &var); |
386 RETURN_ON_HR_FAILURE(hr, "Couldn't set bitrate", false); | 403 RETURN_ON_HR_FAILURE(hr, "Couldn't set bitrate", false); |
387 var.ulVal = eAVEncAdaptiveMode_FrameRate; | 404 var.ulVal = eAVEncAdaptiveMode_FrameRate; |
388 hr = codec_api_->SetValue(&CODECAPI_AVEncAdaptiveMode, &var); | 405 hr = codec_api_->SetValue(&CODECAPI_AVEncAdaptiveMode, &var); |
389 RETURN_ON_HR_FAILURE(hr, "Couldn't set FrameRate", false); | 406 RETURN_ON_HR_FAILURE(hr, "Couldn't set FrameRate", false); |
390 var.vt = VT_BOOL; | 407 var.vt = VT_BOOL; |
391 var.boolVal = VARIANT_TRUE; | 408 var.boolVal = VARIANT_TRUE; |
392 hr = codec_api_->SetValue(&CODECAPI_AVLowLatencyMode, &var); | 409 hr = codec_api_->SetValue(&CODECAPI_AVLowLatencyMode, &var); |
393 RETURN_ON_HR_FAILURE(hr, "Couldn't set LowLatencyMode", false); | 410 RETURN_ON_HR_FAILURE(hr, "Couldn't set LowLatencyMode", false); |
394 return SUCCEEDED(hr); | 411 return SUCCEEDED(hr); |
395 } | 412 } |
396 | 413 |
397 void MediaFoundationVideoEncodeAccelerator::NotifyError( | 414 void MediaFoundationVideoEncodeAccelerator::NotifyError( |
398 VideoEncodeAccelerator::Error error) { | 415 VideoEncodeAccelerator::Error error) { |
399 DCHECK(encoder_thread_task_runner_->BelongsToCurrentThread()); | 416 DCHECK(encoder_thread_task_runner_->BelongsToCurrentThread()); |
400 client_task_runner_->PostTask( | 417 main_client_task_runner_->PostTask( |
401 FROM_HERE, base::Bind(&Client::NotifyError, client_, error)); | 418 FROM_HERE, base::Bind(&Client::NotifyError, main_client_, error)); |
402 } | 419 } |
403 | 420 |
404 void MediaFoundationVideoEncodeAccelerator::EncodeTask( | 421 void MediaFoundationVideoEncodeAccelerator::EncodeTask( |
405 scoped_refptr<VideoFrame> frame, | 422 scoped_refptr<VideoFrame> frame, |
406 bool force_keyframe) { | 423 bool force_keyframe) { |
407 DVLOG(3) << __func__; | 424 DVLOG(3) << __func__; |
408 DCHECK(encoder_thread_task_runner_->BelongsToCurrentThread()); | 425 DCHECK(encoder_thread_task_runner_->BelongsToCurrentThread()); |
409 | 426 |
410 base::win::ScopedComPtr<IMFMediaBuffer> input_buffer; | 427 base::win::ScopedComPtr<IMFMediaBuffer> input_buffer; |
411 input_sample_->GetBufferByIndex(0, input_buffer.Receive()); | 428 input_sample_->GetBufferByIndex(0, input_buffer.Receive()); |
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
508 | 525 |
509 std::unique_ptr<MediaFoundationVideoEncodeAccelerator::BitstreamBufferRef> | 526 std::unique_ptr<MediaFoundationVideoEncodeAccelerator::BitstreamBufferRef> |
510 buffer_ref = std::move(bitstream_buffer_queue_.front()); | 527 buffer_ref = std::move(bitstream_buffer_queue_.front()); |
511 bitstream_buffer_queue_.pop_front(); | 528 bitstream_buffer_queue_.pop_front(); |
512 | 529 |
513 { | 530 { |
514 MediaBufferScopedPointer scoped_buffer(output_buffer.get()); | 531 MediaBufferScopedPointer scoped_buffer(output_buffer.get()); |
515 memcpy(buffer_ref->shm->memory(), scoped_buffer.get(), size); | 532 memcpy(buffer_ref->shm->memory(), scoped_buffer.get(), size); |
516 } | 533 } |
517 | 534 |
518 client_task_runner_->PostTask( | 535 encode_client_task_runner_->PostTask( |
519 FROM_HERE, base::Bind(&Client::BitstreamBufferReady, client_, | 536 FROM_HERE, base::Bind(&Client::BitstreamBufferReady, encode_client_, |
520 buffer_ref->id, size, keyframe, timestamp)); | 537 buffer_ref->id, size, keyframe, timestamp)); |
521 | 538 |
522 // Keep calling ProcessOutput recursively until MF_E_TRANSFORM_NEED_MORE_INPUT | 539 // Keep calling ProcessOutput recursively until MF_E_TRANSFORM_NEED_MORE_INPUT |
523 // is returned to flush out all the output. | 540 // is returned to flush out all the output. |
524 ProcessOutput(); | 541 ProcessOutput(); |
525 } | 542 } |
526 | 543 |
527 void MediaFoundationVideoEncodeAccelerator::UseOutputBitstreamBufferTask( | 544 void MediaFoundationVideoEncodeAccelerator::UseOutputBitstreamBufferTask( |
528 std::unique_ptr<BitstreamBufferRef> buffer_ref) { | 545 std::unique_ptr<BitstreamBufferRef> buffer_ref) { |
529 DVLOG(3) << __func__; | 546 DVLOG(3) << __func__; |
(...skipping 13 matching lines...) Expand all Loading... |
543 | 560 |
544 void MediaFoundationVideoEncodeAccelerator::ReturnBitstreamBuffer( | 561 void MediaFoundationVideoEncodeAccelerator::ReturnBitstreamBuffer( |
545 std::unique_ptr<EncodeOutput> encode_output, | 562 std::unique_ptr<EncodeOutput> encode_output, |
546 std::unique_ptr<MediaFoundationVideoEncodeAccelerator::BitstreamBufferRef> | 563 std::unique_ptr<MediaFoundationVideoEncodeAccelerator::BitstreamBufferRef> |
547 buffer_ref) { | 564 buffer_ref) { |
548 DVLOG(3) << __func__; | 565 DVLOG(3) << __func__; |
549 DCHECK(encoder_thread_task_runner_->BelongsToCurrentThread()); | 566 DCHECK(encoder_thread_task_runner_->BelongsToCurrentThread()); |
550 | 567 |
551 memcpy(buffer_ref->shm->memory(), encode_output->memory(), | 568 memcpy(buffer_ref->shm->memory(), encode_output->memory(), |
552 encode_output->size()); | 569 encode_output->size()); |
553 client_task_runner_->PostTask( | 570 encode_client_task_runner_->PostTask( |
554 FROM_HERE, | 571 FROM_HERE, |
555 base::Bind(&Client::BitstreamBufferReady, client_, buffer_ref->id, | 572 base::Bind(&Client::BitstreamBufferReady, encode_client_, buffer_ref->id, |
556 encode_output->size(), encode_output->keyframe, | 573 encode_output->size(), encode_output->keyframe, |
557 encode_output->capture_timestamp)); | 574 encode_output->capture_timestamp)); |
558 } | 575 } |
559 | 576 |
560 void MediaFoundationVideoEncodeAccelerator::RequestEncodingParametersChangeTask( | 577 void MediaFoundationVideoEncodeAccelerator::RequestEncodingParametersChangeTask( |
561 uint32_t bitrate, | 578 uint32_t bitrate, |
562 uint32_t framerate) { | 579 uint32_t framerate) { |
563 DVLOG(3) << __func__; | 580 DVLOG(3) << __func__; |
564 DCHECK(encoder_thread_task_runner_->BelongsToCurrentThread()); | 581 DCHECK(encoder_thread_task_runner_->BelongsToCurrentThread()); |
565 | 582 |
(...skipping 26 matching lines...) Expand all Loading... |
592 void MediaFoundationVideoEncodeAccelerator::ReleaseEncoderResources() { | 609 void MediaFoundationVideoEncodeAccelerator::ReleaseEncoderResources() { |
593 encoder_.Release(); | 610 encoder_.Release(); |
594 codec_api_.Release(); | 611 codec_api_.Release(); |
595 imf_input_media_type_.Release(); | 612 imf_input_media_type_.Release(); |
596 imf_output_media_type_.Release(); | 613 imf_output_media_type_.Release(); |
597 input_sample_.Release(); | 614 input_sample_.Release(); |
598 output_sample_.Release(); | 615 output_sample_.Release(); |
599 } | 616 } |
600 | 617 |
601 } // namespace content | 618 } // namespace content |
OLD | NEW |