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/vt_video_encode_accelerator_mac.h" | 5 #include "media/gpu/vt_video_encode_accelerator_mac.h" |
6 | 6 |
7 #include <memory> | 7 #include <memory> |
8 | 8 |
9 #include "base/mac/mac_util.h" | 9 #include "base/mac/mac_util.h" |
10 #include "base/threading/thread_task_runner_handle.h" | 10 #include "base/threading/thread_task_runner_handle.h" |
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
87 | 87 |
88 VTVideoEncodeAccelerator::~VTVideoEncodeAccelerator() { | 88 VTVideoEncodeAccelerator::~VTVideoEncodeAccelerator() { |
89 DVLOG(3) << __FUNCTION__; | 89 DVLOG(3) << __FUNCTION__; |
90 DCHECK(thread_checker_.CalledOnValidThread()); | 90 DCHECK(thread_checker_.CalledOnValidThread()); |
91 | 91 |
92 Destroy(); | 92 Destroy(); |
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 media::VideoEncodeAccelerator::SupportedProfiles | 97 VideoEncodeAccelerator::SupportedProfiles |
98 VTVideoEncodeAccelerator::GetSupportedProfiles() { | 98 VTVideoEncodeAccelerator::GetSupportedProfiles() { |
99 DVLOG(3) << __FUNCTION__; | 99 DVLOG(3) << __FUNCTION__; |
100 DCHECK(thread_checker_.CalledOnValidThread()); | 100 DCHECK(thread_checker_.CalledOnValidThread()); |
101 | 101 |
102 SupportedProfiles profiles; | 102 SupportedProfiles profiles; |
103 // Check if HW encoder is supported initially. | 103 // Check if HW encoder is supported initially. |
104 videotoolbox_glue_ = VideoToolboxGlue::Get(); | 104 videotoolbox_glue_ = VideoToolboxGlue::Get(); |
105 if (!videotoolbox_glue_) { | 105 if (!videotoolbox_glue_) { |
106 DLOG(ERROR) << "Failed creating VideoToolbox glue."; | 106 DLOG(ERROR) << "Failed creating VideoToolbox glue."; |
107 return profiles; | 107 return profiles; |
108 } | 108 } |
109 if (!base::mac::IsOSMavericksOrLater()) { | 109 if (!base::mac::IsOSMavericksOrLater()) { |
110 DLOG(ERROR) << "VideoToolbox hardware encoder is supported on Mac OS 10.9 " | 110 DLOG(ERROR) << "VideoToolbox hardware encoder is supported on Mac OS 10.9 " |
111 "and later."; | 111 "and later."; |
112 return profiles; | 112 return profiles; |
113 } | 113 } |
114 const bool rv = CreateCompressionSession( | 114 const bool rv = CreateCompressionSession( |
115 media::video_toolbox::DictionaryWithKeysAndValues(nullptr, nullptr, 0), | 115 video_toolbox::DictionaryWithKeysAndValues(nullptr, nullptr, 0), |
116 gfx::Size(kDefaultResolutionWidth, kDefaultResolutionHeight), true); | 116 gfx::Size(kDefaultResolutionWidth, kDefaultResolutionHeight), true); |
117 DestroyCompressionSession(); | 117 DestroyCompressionSession(); |
118 if (!rv) { | 118 if (!rv) { |
119 VLOG(1) | 119 VLOG(1) |
120 << "Hardware encode acceleration is not available on this platform."; | 120 << "Hardware encode acceleration is not available on this platform."; |
121 return profiles; | 121 return profiles; |
122 } | 122 } |
123 | 123 |
124 SupportedProfile profile; | 124 SupportedProfile profile; |
125 profile.profile = media::H264PROFILE_BASELINE; | 125 profile.profile = H264PROFILE_BASELINE; |
126 profile.max_framerate_numerator = kMaxFrameRateNumerator; | 126 profile.max_framerate_numerator = kMaxFrameRateNumerator; |
127 profile.max_framerate_denominator = kMaxFrameRateDenominator; | 127 profile.max_framerate_denominator = kMaxFrameRateDenominator; |
128 profile.max_resolution = gfx::Size(kMaxResolutionWidth, kMaxResolutionHeight); | 128 profile.max_resolution = gfx::Size(kMaxResolutionWidth, kMaxResolutionHeight); |
129 profiles.push_back(profile); | 129 profiles.push_back(profile); |
130 return profiles; | 130 return profiles; |
131 } | 131 } |
132 | 132 |
133 bool VTVideoEncodeAccelerator::Initialize( | 133 bool VTVideoEncodeAccelerator::Initialize(VideoPixelFormat format, |
134 media::VideoPixelFormat format, | 134 const gfx::Size& input_visible_size, |
135 const gfx::Size& input_visible_size, | 135 VideoCodecProfile output_profile, |
136 media::VideoCodecProfile output_profile, | 136 uint32_t initial_bitrate, |
137 uint32_t initial_bitrate, | 137 Client* client) { |
138 Client* client) { | |
139 DVLOG(3) << __FUNCTION__ | 138 DVLOG(3) << __FUNCTION__ |
140 << ": input_format=" << media::VideoPixelFormatToString(format) | 139 << ": input_format=" << VideoPixelFormatToString(format) |
141 << ", input_visible_size=" << input_visible_size.ToString() | 140 << ", input_visible_size=" << input_visible_size.ToString() |
142 << ", output_profile=" << output_profile | 141 << ", output_profile=" << output_profile |
143 << ", initial_bitrate=" << initial_bitrate; | 142 << ", initial_bitrate=" << initial_bitrate; |
144 DCHECK(thread_checker_.CalledOnValidThread()); | 143 DCHECK(thread_checker_.CalledOnValidThread()); |
145 DCHECK(client); | 144 DCHECK(client); |
146 | 145 |
147 if (media::PIXEL_FORMAT_I420 != format) { | 146 if (PIXEL_FORMAT_I420 != format) { |
148 DLOG(ERROR) << "Input format not supported= " | 147 DLOG(ERROR) << "Input format not supported= " |
149 << media::VideoPixelFormatToString(format); | 148 << VideoPixelFormatToString(format); |
150 return false; | 149 return false; |
151 } | 150 } |
152 if (media::H264PROFILE_BASELINE != output_profile) { | 151 if (H264PROFILE_BASELINE != output_profile) { |
153 DLOG(ERROR) << "Output profile not supported= " << output_profile; | 152 DLOG(ERROR) << "Output profile not supported= " << output_profile; |
154 return false; | 153 return false; |
155 } | 154 } |
156 | 155 |
157 videotoolbox_glue_ = VideoToolboxGlue::Get(); | 156 videotoolbox_glue_ = VideoToolboxGlue::Get(); |
158 if (!videotoolbox_glue_) { | 157 if (!videotoolbox_glue_) { |
159 DLOG(ERROR) << "Failed creating VideoToolbox glue."; | 158 DLOG(ERROR) << "Failed creating VideoToolbox glue."; |
160 return false; | 159 return false; |
161 } | 160 } |
162 if (!base::mac::IsOSMavericksOrLater()) { | 161 if (!base::mac::IsOSMavericksOrLater()) { |
(...skipping 20 matching lines...) Expand all Loading... |
183 return false; | 182 return false; |
184 } | 183 } |
185 | 184 |
186 client_task_runner_->PostTask( | 185 client_task_runner_->PostTask( |
187 FROM_HERE, | 186 FROM_HERE, |
188 base::Bind(&Client::RequireBitstreamBuffers, client_, kNumInputBuffers, | 187 base::Bind(&Client::RequireBitstreamBuffers, client_, kNumInputBuffers, |
189 input_visible_size_, bitstream_buffer_size_)); | 188 input_visible_size_, bitstream_buffer_size_)); |
190 return true; | 189 return true; |
191 } | 190 } |
192 | 191 |
193 void VTVideoEncodeAccelerator::Encode( | 192 void VTVideoEncodeAccelerator::Encode(const scoped_refptr<VideoFrame>& frame, |
194 const scoped_refptr<media::VideoFrame>& frame, | 193 bool force_keyframe) { |
195 bool force_keyframe) { | |
196 DVLOG(3) << __FUNCTION__; | 194 DVLOG(3) << __FUNCTION__; |
197 DCHECK(thread_checker_.CalledOnValidThread()); | 195 DCHECK(thread_checker_.CalledOnValidThread()); |
198 | 196 |
199 encoder_thread_task_runner_->PostTask( | 197 encoder_thread_task_runner_->PostTask( |
200 FROM_HERE, base::Bind(&VTVideoEncodeAccelerator::EncodeTask, | 198 FROM_HERE, base::Bind(&VTVideoEncodeAccelerator::EncodeTask, |
201 base::Unretained(this), frame, force_keyframe)); | 199 base::Unretained(this), frame, force_keyframe)); |
202 } | 200 } |
203 | 201 |
204 void VTVideoEncodeAccelerator::UseOutputBitstreamBuffer( | 202 void VTVideoEncodeAccelerator::UseOutputBitstreamBuffer( |
205 const media::BitstreamBuffer& buffer) { | 203 const BitstreamBuffer& buffer) { |
206 DVLOG(3) << __FUNCTION__ << ": buffer size=" << buffer.size(); | 204 DVLOG(3) << __FUNCTION__ << ": buffer size=" << buffer.size(); |
207 DCHECK(thread_checker_.CalledOnValidThread()); | 205 DCHECK(thread_checker_.CalledOnValidThread()); |
208 | 206 |
209 if (buffer.size() < bitstream_buffer_size_) { | 207 if (buffer.size() < bitstream_buffer_size_) { |
210 DLOG(ERROR) << "Output BitstreamBuffer isn't big enough: " << buffer.size() | 208 DLOG(ERROR) << "Output BitstreamBuffer isn't big enough: " << buffer.size() |
211 << " vs. " << bitstream_buffer_size_; | 209 << " vs. " << bitstream_buffer_size_; |
212 client_->NotifyError(kInvalidArgumentError); | 210 client_->NotifyError(kInvalidArgumentError); |
213 return; | 211 return; |
214 } | 212 } |
215 | 213 |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
254 encoder_thread_task_runner_->PostTask( | 252 encoder_thread_task_runner_->PostTask( |
255 FROM_HERE, base::Bind(&VTVideoEncodeAccelerator::DestroyTask, | 253 FROM_HERE, base::Bind(&VTVideoEncodeAccelerator::DestroyTask, |
256 base::Unretained(this))); | 254 base::Unretained(this))); |
257 encoder_thread_.Stop(); | 255 encoder_thread_.Stop(); |
258 } else { | 256 } else { |
259 DestroyTask(); | 257 DestroyTask(); |
260 } | 258 } |
261 } | 259 } |
262 | 260 |
263 void VTVideoEncodeAccelerator::EncodeTask( | 261 void VTVideoEncodeAccelerator::EncodeTask( |
264 const scoped_refptr<media::VideoFrame>& frame, | 262 const scoped_refptr<VideoFrame>& frame, |
265 bool force_keyframe) { | 263 bool force_keyframe) { |
266 DCHECK(encoder_thread_task_runner_->BelongsToCurrentThread()); | 264 DCHECK(encoder_thread_task_runner_->BelongsToCurrentThread()); |
267 DCHECK(compression_session_); | 265 DCHECK(compression_session_); |
268 DCHECK(frame); | 266 DCHECK(frame); |
269 | 267 |
270 // TODO(emircan): See if we can eliminate a copy here by using | 268 // TODO(emircan): See if we can eliminate a copy here by using |
271 // CVPixelBufferPool for the allocation of incoming VideoFrames. | 269 // CVPixelBufferPool for the allocation of incoming VideoFrames. |
272 base::ScopedCFTypeRef<CVPixelBufferRef> pixel_buffer = | 270 base::ScopedCFTypeRef<CVPixelBufferRef> pixel_buffer = |
273 media::WrapVideoFrameInCVPixelBuffer(*frame); | 271 WrapVideoFrameInCVPixelBuffer(*frame); |
274 base::ScopedCFTypeRef<CFDictionaryRef> frame_props = | 272 base::ScopedCFTypeRef<CFDictionaryRef> frame_props = |
275 media::video_toolbox::DictionaryWithKeyValue( | 273 video_toolbox::DictionaryWithKeyValue( |
276 videotoolbox_glue_->kVTEncodeFrameOptionKey_ForceKeyFrame(), | 274 videotoolbox_glue_->kVTEncodeFrameOptionKey_ForceKeyFrame(), |
277 force_keyframe ? kCFBooleanTrue : kCFBooleanFalse); | 275 force_keyframe ? kCFBooleanTrue : kCFBooleanFalse); |
278 | 276 |
279 base::TimeTicks ref_time; | 277 base::TimeTicks ref_time; |
280 if (!frame->metadata()->GetTimeTicks( | 278 if (!frame->metadata()->GetTimeTicks(VideoFrameMetadata::REFERENCE_TIME, |
281 media::VideoFrameMetadata::REFERENCE_TIME, &ref_time)) { | 279 &ref_time)) { |
282 ref_time = base::TimeTicks::Now(); | 280 ref_time = base::TimeTicks::Now(); |
283 } | 281 } |
284 auto timestamp_cm = CoreMediaGlue::CMTimeMake( | 282 auto timestamp_cm = CoreMediaGlue::CMTimeMake( |
285 frame->timestamp().InMicroseconds(), USEC_PER_SEC); | 283 frame->timestamp().InMicroseconds(), USEC_PER_SEC); |
286 // Wrap information we'll need after the frame is encoded in a heap object. | 284 // Wrap information we'll need after the frame is encoded in a heap object. |
287 // We'll get the pointer back from the VideoToolbox completion callback. | 285 // We'll get the pointer back from the VideoToolbox completion callback. |
288 std::unique_ptr<InProgressFrameEncode> request( | 286 std::unique_ptr<InProgressFrameEncode> request( |
289 new InProgressFrameEncode(frame->timestamp(), ref_time)); | 287 new InProgressFrameEncode(frame->timestamp(), ref_time)); |
290 | 288 |
291 // Update the bitrate if needed. | 289 // Update the bitrate if needed. |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
325 uint32_t bitrate, | 323 uint32_t bitrate, |
326 uint32_t framerate) { | 324 uint32_t framerate) { |
327 DCHECK(encoder_thread_task_runner_->BelongsToCurrentThread()); | 325 DCHECK(encoder_thread_task_runner_->BelongsToCurrentThread()); |
328 | 326 |
329 if (!compression_session_) { | 327 if (!compression_session_) { |
330 NotifyError(kPlatformFailureError); | 328 NotifyError(kPlatformFailureError); |
331 return; | 329 return; |
332 } | 330 } |
333 | 331 |
334 if (framerate != static_cast<uint32_t>(frame_rate_)) { | 332 if (framerate != static_cast<uint32_t>(frame_rate_)) { |
335 media::video_toolbox::SessionPropertySetter session_property_setter( | 333 video_toolbox::SessionPropertySetter session_property_setter( |
336 compression_session_, videotoolbox_glue_); | 334 compression_session_, videotoolbox_glue_); |
337 session_property_setter.Set( | 335 session_property_setter.Set( |
338 videotoolbox_glue_->kVTCompressionPropertyKey_ExpectedFrameRate(), | 336 videotoolbox_glue_->kVTCompressionPropertyKey_ExpectedFrameRate(), |
339 frame_rate_); | 337 frame_rate_); |
340 } | 338 } |
341 | 339 |
342 if (bitrate != static_cast<uint32_t>(target_bitrate_) && bitrate > 0) { | 340 if (bitrate != static_cast<uint32_t>(target_bitrate_) && bitrate > 0) { |
343 target_bitrate_ = bitrate; | 341 target_bitrate_ = bitrate; |
344 bitrate_adjuster_.SetTargetBitrateBps(target_bitrate_); | 342 bitrate_adjuster_.SetTargetBitrateBps(target_bitrate_); |
345 SetAdjustedBitrate(bitrate_adjuster_.GetAdjustedBitrateBps()); | 343 SetAdjustedBitrate(bitrate_adjuster_.GetAdjustedBitrateBps()); |
346 } | 344 } |
347 } | 345 } |
348 | 346 |
349 void VTVideoEncodeAccelerator::SetAdjustedBitrate(int32_t bitrate) { | 347 void VTVideoEncodeAccelerator::SetAdjustedBitrate(int32_t bitrate) { |
350 DCHECK(encoder_thread_task_runner_->BelongsToCurrentThread()); | 348 DCHECK(encoder_thread_task_runner_->BelongsToCurrentThread()); |
351 | 349 |
352 if (bitrate == encoder_set_bitrate_) | 350 if (bitrate == encoder_set_bitrate_) |
353 return; | 351 return; |
354 | 352 |
355 encoder_set_bitrate_ = bitrate; | 353 encoder_set_bitrate_ = bitrate; |
356 media::video_toolbox::SessionPropertySetter session_property_setter( | 354 video_toolbox::SessionPropertySetter session_property_setter( |
357 compression_session_, videotoolbox_glue_); | 355 compression_session_, videotoolbox_glue_); |
358 bool rv = session_property_setter.Set( | 356 bool rv = session_property_setter.Set( |
359 videotoolbox_glue_->kVTCompressionPropertyKey_AverageBitRate(), | 357 videotoolbox_glue_->kVTCompressionPropertyKey_AverageBitRate(), |
360 encoder_set_bitrate_); | 358 encoder_set_bitrate_); |
361 rv &= session_property_setter.Set( | 359 rv &= session_property_setter.Set( |
362 videotoolbox_glue_->kVTCompressionPropertyKey_DataRateLimits(), | 360 videotoolbox_glue_->kVTCompressionPropertyKey_DataRateLimits(), |
363 media::video_toolbox::ArrayWithIntegerAndFloat( | 361 video_toolbox::ArrayWithIntegerAndFloat( |
364 encoder_set_bitrate_ / kBitsPerByte, 1.0f)); | 362 encoder_set_bitrate_ / kBitsPerByte, 1.0f)); |
365 DLOG_IF(ERROR, !rv) | 363 DLOG_IF(ERROR, !rv) |
366 << "Couldn't change bitrate parameters of encode session."; | 364 << "Couldn't change bitrate parameters of encode session."; |
367 } | 365 } |
368 | 366 |
369 void VTVideoEncodeAccelerator::DestroyTask() { | 367 void VTVideoEncodeAccelerator::DestroyTask() { |
370 DCHECK(thread_checker_.CalledOnValidThread() || | 368 DCHECK(thread_checker_.CalledOnValidThread() || |
371 (encoder_thread_.IsRunning() && | 369 (encoder_thread_.IsRunning() && |
372 encoder_thread_task_runner_->BelongsToCurrentThread())); | 370 encoder_thread_task_runner_->BelongsToCurrentThread())); |
373 | 371 |
374 // Cancel all encoder thread callbacks. | 372 // Cancel all encoder thread callbacks. |
375 encoder_task_weak_factory_.InvalidateWeakPtrs(); | 373 encoder_task_weak_factory_.InvalidateWeakPtrs(); |
376 | 374 |
377 // This call blocks until all pending frames are flushed out. | 375 // This call blocks until all pending frames are flushed out. |
378 DestroyCompressionSession(); | 376 DestroyCompressionSession(); |
379 } | 377 } |
380 | 378 |
381 void VTVideoEncodeAccelerator::NotifyError( | 379 void VTVideoEncodeAccelerator::NotifyError( |
382 media::VideoEncodeAccelerator::Error error) { | 380 VideoEncodeAccelerator::Error error) { |
383 DCHECK(encoder_thread_task_runner_->BelongsToCurrentThread()); | 381 DCHECK(encoder_thread_task_runner_->BelongsToCurrentThread()); |
384 client_task_runner_->PostTask( | 382 client_task_runner_->PostTask( |
385 FROM_HERE, base::Bind(&Client::NotifyError, client_, error)); | 383 FROM_HERE, base::Bind(&Client::NotifyError, client_, error)); |
386 } | 384 } |
387 | 385 |
388 // static | 386 // static |
389 void VTVideoEncodeAccelerator::CompressionCallback(void* encoder_opaque, | 387 void VTVideoEncodeAccelerator::CompressionCallback(void* encoder_opaque, |
390 void* request_opaque, | 388 void* request_opaque, |
391 OSStatus status, | 389 OSStatus status, |
392 VTEncodeInfoFlags info, | 390 VTEncodeInfoFlags info, |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
455 } | 453 } |
456 | 454 |
457 auto sample_attachments = static_cast<CFDictionaryRef>(CFArrayGetValueAtIndex( | 455 auto sample_attachments = static_cast<CFDictionaryRef>(CFArrayGetValueAtIndex( |
458 CoreMediaGlue::CMSampleBufferGetSampleAttachmentsArray( | 456 CoreMediaGlue::CMSampleBufferGetSampleAttachmentsArray( |
459 encode_output->sample_buffer.get(), true), | 457 encode_output->sample_buffer.get(), true), |
460 0)); | 458 0)); |
461 const bool keyframe = !CFDictionaryContainsKey( | 459 const bool keyframe = !CFDictionaryContainsKey( |
462 sample_attachments, CoreMediaGlue::kCMSampleAttachmentKey_NotSync()); | 460 sample_attachments, CoreMediaGlue::kCMSampleAttachmentKey_NotSync()); |
463 | 461 |
464 size_t used_buffer_size = 0; | 462 size_t used_buffer_size = 0; |
465 const bool copy_rv = media::video_toolbox::CopySampleBufferToAnnexBBuffer( | 463 const bool copy_rv = video_toolbox::CopySampleBufferToAnnexBBuffer( |
466 encode_output->sample_buffer.get(), keyframe, buffer_ref->size, | 464 encode_output->sample_buffer.get(), keyframe, buffer_ref->size, |
467 reinterpret_cast<char*>(buffer_ref->shm->memory()), &used_buffer_size); | 465 reinterpret_cast<char*>(buffer_ref->shm->memory()), &used_buffer_size); |
468 if (!copy_rv) { | 466 if (!copy_rv) { |
469 DLOG(ERROR) << "Cannot copy output from SampleBuffer to AnnexBBuffer."; | 467 DLOG(ERROR) << "Cannot copy output from SampleBuffer to AnnexBBuffer."; |
470 used_buffer_size = 0; | 468 used_buffer_size = 0; |
471 } | 469 } |
472 bitrate_adjuster_.Update(used_buffer_size); | 470 bitrate_adjuster_.Update(used_buffer_size); |
473 | 471 |
474 client_task_runner_->PostTask( | 472 client_task_runner_->PostTask( |
475 FROM_HERE, | 473 FROM_HERE, |
476 base::Bind(&Client::BitstreamBufferReady, client_, buffer_ref->id, | 474 base::Bind(&Client::BitstreamBufferReady, client_, buffer_ref->id, |
477 used_buffer_size, keyframe, encode_output->capture_timestamp)); | 475 used_buffer_size, keyframe, encode_output->capture_timestamp)); |
478 } | 476 } |
479 | 477 |
480 bool VTVideoEncodeAccelerator::ResetCompressionSession() { | 478 bool VTVideoEncodeAccelerator::ResetCompressionSession() { |
481 DCHECK(thread_checker_.CalledOnValidThread()); | 479 DCHECK(thread_checker_.CalledOnValidThread()); |
482 | 480 |
483 DestroyCompressionSession(); | 481 DestroyCompressionSession(); |
484 | 482 |
485 CFTypeRef attributes_keys[] = {kCVPixelBufferOpenGLCompatibilityKey, | 483 CFTypeRef attributes_keys[] = {kCVPixelBufferOpenGLCompatibilityKey, |
486 kCVPixelBufferIOSurfacePropertiesKey, | 484 kCVPixelBufferIOSurfacePropertiesKey, |
487 kCVPixelBufferPixelFormatTypeKey}; | 485 kCVPixelBufferPixelFormatTypeKey}; |
488 const int format[] = { | 486 const int format[] = { |
489 CoreVideoGlue::kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange}; | 487 CoreVideoGlue::kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange}; |
490 CFTypeRef attributes_values[] = { | 488 CFTypeRef attributes_values[] = { |
491 kCFBooleanTrue, | 489 kCFBooleanTrue, |
492 media::video_toolbox::DictionaryWithKeysAndValues(nullptr, nullptr, 0) | 490 video_toolbox::DictionaryWithKeysAndValues(nullptr, nullptr, 0).release(), |
493 .release(), | 491 video_toolbox::ArrayWithIntegers(format, arraysize(format)).release()}; |
494 media::video_toolbox::ArrayWithIntegers(format, arraysize(format)) | |
495 .release()}; | |
496 const base::ScopedCFTypeRef<CFDictionaryRef> attributes = | 492 const base::ScopedCFTypeRef<CFDictionaryRef> attributes = |
497 media::video_toolbox::DictionaryWithKeysAndValues( | 493 video_toolbox::DictionaryWithKeysAndValues( |
498 attributes_keys, attributes_values, arraysize(attributes_keys)); | 494 attributes_keys, attributes_values, arraysize(attributes_keys)); |
499 for (auto& v : attributes_values) | 495 for (auto& v : attributes_values) |
500 CFRelease(v); | 496 CFRelease(v); |
501 | 497 |
502 bool session_rv = | 498 bool session_rv = |
503 CreateCompressionSession(attributes, input_visible_size_, false); | 499 CreateCompressionSession(attributes, input_visible_size_, false); |
504 if (!session_rv) { | 500 if (!session_rv) { |
505 DestroyCompressionSession(); | 501 DestroyCompressionSession(); |
506 return false; | 502 return false; |
507 } | 503 } |
(...skipping 17 matching lines...) Expand all Loading... |
525 videotoolbox_glue_ | 521 videotoolbox_glue_ |
526 ->kVTVideoEncoderSpecification_RequireHardwareAcceleratedVideoEncode
r()); | 522 ->kVTVideoEncoderSpecification_RequireHardwareAcceleratedVideoEncode
r()); |
527 encoder_values.push_back(kCFBooleanTrue); | 523 encoder_values.push_back(kCFBooleanTrue); |
528 } else { | 524 } else { |
529 encoder_keys.push_back( | 525 encoder_keys.push_back( |
530 videotoolbox_glue_ | 526 videotoolbox_glue_ |
531 ->kVTVideoEncoderSpecification_EnableHardwareAcceleratedVideoEncoder
()); | 527 ->kVTVideoEncoderSpecification_EnableHardwareAcceleratedVideoEncoder
()); |
532 encoder_values.push_back(kCFBooleanTrue); | 528 encoder_values.push_back(kCFBooleanTrue); |
533 } | 529 } |
534 base::ScopedCFTypeRef<CFDictionaryRef> encoder_spec = | 530 base::ScopedCFTypeRef<CFDictionaryRef> encoder_spec = |
535 media::video_toolbox::DictionaryWithKeysAndValues( | 531 video_toolbox::DictionaryWithKeysAndValues( |
536 encoder_keys.data(), encoder_values.data(), encoder_keys.size()); | 532 encoder_keys.data(), encoder_values.data(), encoder_keys.size()); |
537 | 533 |
538 // Create the compression session. | 534 // Create the compression session. |
539 // Note that the encoder object is given to the compression session as the | 535 // Note that the encoder object is given to the compression session as the |
540 // callback context using a raw pointer. The C API does not allow us to use a | 536 // callback context using a raw pointer. The C API does not allow us to use a |
541 // smart pointer, nor is this encoder ref counted. However, this is still | 537 // smart pointer, nor is this encoder ref counted. However, this is still |
542 // safe, because we 1) we own the compression session and 2) we tear it down | 538 // safe, because we 1) we own the compression session and 2) we tear it down |
543 // safely. When destructing the encoder, the compression session is flushed | 539 // safely. When destructing the encoder, the compression session is flushed |
544 // and invalidated. Internally, VideoToolbox will join all of its threads | 540 // and invalidated. Internally, VideoToolbox will join all of its threads |
545 // before returning to the client. Therefore, when control returns to us, we | 541 // before returning to the client. Therefore, when control returns to us, we |
(...skipping 10 matching lines...) Expand all Loading... |
556 } | 552 } |
557 DVLOG(3) << " VTCompressionSession created with HW encode: " | 553 DVLOG(3) << " VTCompressionSession created with HW encode: " |
558 << require_hw_encoding << ", input size=" << input_size.ToString(); | 554 << require_hw_encoding << ", input size=" << input_size.ToString(); |
559 return true; | 555 return true; |
560 } | 556 } |
561 | 557 |
562 bool VTVideoEncodeAccelerator::ConfigureCompressionSession() { | 558 bool VTVideoEncodeAccelerator::ConfigureCompressionSession() { |
563 DCHECK(thread_checker_.CalledOnValidThread()); | 559 DCHECK(thread_checker_.CalledOnValidThread()); |
564 DCHECK(compression_session_); | 560 DCHECK(compression_session_); |
565 | 561 |
566 media::video_toolbox::SessionPropertySetter session_property_setter( | 562 video_toolbox::SessionPropertySetter session_property_setter( |
567 compression_session_, videotoolbox_glue_); | 563 compression_session_, videotoolbox_glue_); |
568 bool rv = true; | 564 bool rv = true; |
569 rv &= session_property_setter.Set( | 565 rv &= session_property_setter.Set( |
570 videotoolbox_glue_->kVTCompressionPropertyKey_ProfileLevel(), | 566 videotoolbox_glue_->kVTCompressionPropertyKey_ProfileLevel(), |
571 videotoolbox_glue_->kVTProfileLevel_H264_Baseline_AutoLevel()); | 567 videotoolbox_glue_->kVTProfileLevel_H264_Baseline_AutoLevel()); |
572 rv &= session_property_setter.Set( | 568 rv &= session_property_setter.Set( |
573 videotoolbox_glue_->kVTCompressionPropertyKey_RealTime(), true); | 569 videotoolbox_glue_->kVTCompressionPropertyKey_RealTime(), true); |
574 rv &= session_property_setter.Set( | 570 rv &= session_property_setter.Set( |
575 videotoolbox_glue_->kVTCompressionPropertyKey_AllowFrameReordering(), | 571 videotoolbox_glue_->kVTCompressionPropertyKey_AllowFrameReordering(), |
576 false); | 572 false); |
577 DLOG_IF(ERROR, !rv) << " Setting session property failed."; | 573 DLOG_IF(ERROR, !rv) << " Setting session property failed."; |
578 return rv; | 574 return rv; |
579 } | 575 } |
580 | 576 |
581 void VTVideoEncodeAccelerator::DestroyCompressionSession() { | 577 void VTVideoEncodeAccelerator::DestroyCompressionSession() { |
582 DCHECK(thread_checker_.CalledOnValidThread() || | 578 DCHECK(thread_checker_.CalledOnValidThread() || |
583 (encoder_thread_.IsRunning() && | 579 (encoder_thread_.IsRunning() && |
584 encoder_thread_task_runner_->BelongsToCurrentThread())); | 580 encoder_thread_task_runner_->BelongsToCurrentThread())); |
585 | 581 |
586 if (compression_session_) { | 582 if (compression_session_) { |
587 videotoolbox_glue_->VTCompressionSessionInvalidate(compression_session_); | 583 videotoolbox_glue_->VTCompressionSessionInvalidate(compression_session_); |
588 compression_session_.reset(); | 584 compression_session_.reset(); |
589 } | 585 } |
590 } | 586 } |
591 | 587 |
592 } // namespace media | 588 } // namespace media |
OLD | NEW |