Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(102)

Side by Side Diff: content/common/gpu/media/vt_video_encode_accelerator_mac.cc

Issue 1801343002: Revert of H264 HW encode using VideoToolbox (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « content/common/gpu/media/vt_video_encode_accelerator_mac.h ('k') | content/content_common.gypi » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
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
3 // found in the LICENSE file.
4
5 #include "content/common/gpu/media/vt_video_encode_accelerator_mac.h"
6
7 #include "base/thread_task_runner_handle.h"
8 #include "media/base/mac/coremedia_glue.h"
9 #include "media/base/mac/corevideo_glue.h"
10 #include "media/base/mac/video_frame_mac.h"
11
12 namespace content {
13
14 namespace {
15
16 // TODO(emircan): Check if we can find the actual system capabilities via
17 // creating VTCompressionSessions with varying requirements.
18 // See crbug.com/584784.
19 const size_t kBitsPerByte = 8;
20 const size_t kDefaultResolutionWidth = 640;
21 const size_t kDefaultResolutionHeight = 480;
22 const size_t kMaxFrameRateNumerator = 30;
23 const size_t kMaxFrameRateDenominator = 1;
24 const size_t kMaxResolutionWidth = 4096;
25 const size_t kMaxResolutionHeight = 2160;
26 const size_t kNumInputBuffers = 3;
27
28 } // namespace
29
30 struct VTVideoEncodeAccelerator::InProgressFrameEncode {
31 InProgressFrameEncode(base::TimeDelta rtp_timestamp,
32 base::TimeTicks ref_time)
33 : timestamp(rtp_timestamp), reference_time(ref_time) {}
34 const base::TimeDelta timestamp;
35 const base::TimeTicks reference_time;
36
37 private:
38 DISALLOW_IMPLICIT_CONSTRUCTORS(InProgressFrameEncode);
39 };
40
41 struct VTVideoEncodeAccelerator::EncodeOutput {
42 EncodeOutput(VTEncodeInfoFlags info_flags, CMSampleBufferRef sbuf)
43 : info(info_flags), sample_buffer(sbuf, base::scoped_policy::RETAIN) {}
44 const VTEncodeInfoFlags info;
45 const base::ScopedCFTypeRef<CMSampleBufferRef> sample_buffer;
46
47 private:
48 DISALLOW_IMPLICIT_CONSTRUCTORS(EncodeOutput);
49 };
50
51 struct VTVideoEncodeAccelerator::BitstreamBufferRef {
52 BitstreamBufferRef(int32_t id,
53 scoped_ptr<base::SharedMemory> shm,
54 size_t size)
55 : id(id), shm(std::move(shm)), size(size) {}
56 const int32_t id;
57 const scoped_ptr<base::SharedMemory> shm;
58 const size_t size;
59
60 private:
61 DISALLOW_IMPLICIT_CONSTRUCTORS(BitstreamBufferRef);
62 };
63
64 VTVideoEncodeAccelerator::VTVideoEncodeAccelerator()
65 : client_task_runner_(base::ThreadTaskRunnerHandle::Get()),
66 encoder_thread_("VTEncoderThread"),
67 encoder_task_weak_factory_(this) {
68 encoder_weak_ptr_ = encoder_task_weak_factory_.GetWeakPtr();
69 }
70
71 VTVideoEncodeAccelerator::~VTVideoEncodeAccelerator() {
72 DVLOG(3) << __FUNCTION__;
73 DCHECK(thread_checker_.CalledOnValidThread());
74
75 Destroy();
76 DCHECK(!encoder_thread_.IsRunning());
77 DCHECK(!encoder_task_weak_factory_.HasWeakPtrs());
78 }
79
80 media::VideoEncodeAccelerator::SupportedProfiles
81 VTVideoEncodeAccelerator::GetSupportedProfiles() {
82 DVLOG(3) << __FUNCTION__;
83 DCHECK(thread_checker_.CalledOnValidThread());
84
85 SupportedProfiles profiles;
86 // Check if HW encoder is supported initially.
87 videotoolbox_glue_ = VideoToolboxGlue::Get();
88 if (!videotoolbox_glue_) {
89 DLOG(ERROR) << "Failed creating VideoToolbox glue.";
90 return profiles;
91 }
92 const bool rv = CreateCompressionSession(
93 media::video_toolbox::DictionaryWithKeysAndValues(nullptr, nullptr, 0),
94 gfx::Size(kDefaultResolutionWidth, kDefaultResolutionHeight), true);
95 DestroyCompressionSession();
96 if (!rv) {
97 VLOG(1)
98 << "Hardware encode acceleration is not available on this platform.";
99 return profiles;
100 }
101
102 SupportedProfile profile;
103 profile.profile = media::H264PROFILE_BASELINE;
104 profile.max_framerate_numerator = kMaxFrameRateNumerator;
105 profile.max_framerate_denominator = kMaxFrameRateDenominator;
106 profile.max_resolution = gfx::Size(kMaxResolutionWidth, kMaxResolutionHeight);
107 profiles.push_back(profile);
108 return profiles;
109 }
110
111 bool VTVideoEncodeAccelerator::Initialize(
112 media::VideoPixelFormat format,
113 const gfx::Size& input_visible_size,
114 media::VideoCodecProfile output_profile,
115 uint32_t initial_bitrate,
116 Client* client) {
117 DVLOG(3) << __FUNCTION__
118 << ": input_format=" << media::VideoPixelFormatToString(format)
119 << ", input_visible_size=" << input_visible_size.ToString()
120 << ", output_profile=" << output_profile
121 << ", initial_bitrate=" << initial_bitrate;
122 DCHECK(thread_checker_.CalledOnValidThread());
123 DCHECK(client);
124
125 if (media::PIXEL_FORMAT_I420 != format) {
126 DLOG(ERROR) << "Input format not supported= "
127 << media::VideoPixelFormatToString(format);
128 return false;
129 }
130 if (media::H264PROFILE_BASELINE != output_profile) {
131 DLOG(ERROR) << "Output profile not supported= "
132 << output_profile;
133 return false;
134 }
135
136 videotoolbox_glue_ = VideoToolboxGlue::Get();
137 if (!videotoolbox_glue_) {
138 DLOG(ERROR) << "Failed creating VideoToolbox glue.";
139 return false;
140 }
141
142 client_ptr_factory_.reset(new base::WeakPtrFactory<Client>(client));
143 client_ = client_ptr_factory_->GetWeakPtr();
144 input_visible_size_ = input_visible_size;
145 frame_rate_ = kMaxFrameRateNumerator / kMaxFrameRateDenominator;
146 target_bitrate_ = initial_bitrate;
147 bitstream_buffer_size_ = input_visible_size.GetArea();
148
149 if (!encoder_thread_.Start()) {
150 DLOG(ERROR) << "Failed spawning encoder thread.";
151 return false;
152 }
153 encoder_thread_task_runner_ = encoder_thread_.task_runner();
154
155 if (!ResetCompressionSession()) {
156 DLOG(ERROR) << "Failed creating compression session.";
157 return false;
158 }
159
160 client_task_runner_->PostTask(
161 FROM_HERE,
162 base::Bind(&Client::RequireBitstreamBuffers, client_, kNumInputBuffers,
163 input_visible_size_, bitstream_buffer_size_));
164 return true;
165 }
166
167 void VTVideoEncodeAccelerator::Encode(
168 const scoped_refptr<media::VideoFrame>& frame,
169 bool force_keyframe) {
170 DVLOG(3) << __FUNCTION__;
171 DCHECK(thread_checker_.CalledOnValidThread());
172
173 encoder_thread_task_runner_->PostTask(
174 FROM_HERE, base::Bind(&VTVideoEncodeAccelerator::EncodeTask,
175 base::Unretained(this), frame, force_keyframe));
176 }
177
178 void VTVideoEncodeAccelerator::UseOutputBitstreamBuffer(
179 const media::BitstreamBuffer& buffer) {
180 DVLOG(3) << __FUNCTION__ << ": buffer size=" << buffer.size();
181 DCHECK(thread_checker_.CalledOnValidThread());
182
183 if (buffer.size() < bitstream_buffer_size_) {
184 DLOG(ERROR) << "Output BitstreamBuffer isn't big enough: " << buffer.size()
185 << " vs. " << bitstream_buffer_size_;
186 client_->NotifyError(kInvalidArgumentError);
187 return;
188 }
189
190 scoped_ptr<base::SharedMemory> shm(
191 new base::SharedMemory(buffer.handle(), false));
192 if (!shm->Map(buffer.size())) {
193 DLOG(ERROR) << "Failed mapping shared memory.";
194 client_->NotifyError(kPlatformFailureError);
195 return;
196 }
197
198 scoped_ptr<BitstreamBufferRef> buffer_ref(
199 new BitstreamBufferRef(buffer.id(), std::move(shm), buffer.size()));
200
201 encoder_thread_task_runner_->PostTask(
202 FROM_HERE,
203 base::Bind(&VTVideoEncodeAccelerator::UseOutputBitstreamBufferTask,
204 base::Unretained(this), base::Passed(&buffer_ref)));
205 }
206
207 void VTVideoEncodeAccelerator::RequestEncodingParametersChange(
208 uint32_t bitrate,
209 uint32_t framerate) {
210 DVLOG(3) << __FUNCTION__ << ": bitrate=" << bitrate
211 << ": framerate=" << framerate;
212 DCHECK(thread_checker_.CalledOnValidThread());
213
214 encoder_thread_task_runner_->PostTask(
215 FROM_HERE,
216 base::Bind(&VTVideoEncodeAccelerator::RequestEncodingParametersChangeTask,
217 base::Unretained(this), bitrate, framerate));
218 }
219
220 void VTVideoEncodeAccelerator::Destroy() {
221 DVLOG(3) << __FUNCTION__;
222 DCHECK(thread_checker_.CalledOnValidThread());
223
224 // Cancel all callbacks.
225 client_ptr_factory_.reset();
226
227 if (encoder_thread_.IsRunning()) {
228 encoder_thread_task_runner_->PostTask(
229 FROM_HERE,
230 base::Bind(&VTVideoEncodeAccelerator::DestroyTask,
231 base::Unretained(this)));
232 encoder_thread_.Stop();
233 } else {
234 DestroyTask();
235 }
236 }
237
238 void VTVideoEncodeAccelerator::EncodeTask(
239 const scoped_refptr<media::VideoFrame>& frame,
240 bool force_keyframe) {
241 DCHECK(encoder_thread_task_runner_->BelongsToCurrentThread());
242 DCHECK(compression_session_);
243 DCHECK(frame);
244
245 // TODO(emircan): See if we can eliminate a copy here by using
246 // CVPixelBufferPool for the allocation of incoming VideoFrames.
247 base::ScopedCFTypeRef<CVPixelBufferRef> pixel_buffer =
248 media::WrapVideoFrameInCVPixelBuffer(*frame);
249 base::ScopedCFTypeRef<CFDictionaryRef> frame_props =
250 media::video_toolbox::DictionaryWithKeyValue(
251 videotoolbox_glue_->kVTEncodeFrameOptionKey_ForceKeyFrame(),
252 force_keyframe ? kCFBooleanTrue : kCFBooleanFalse);
253
254 base::TimeTicks ref_time;
255 if (!frame->metadata()->GetTimeTicks(
256 media::VideoFrameMetadata::REFERENCE_TIME, &ref_time)) {
257 ref_time = base::TimeTicks::Now();
258 }
259 auto timestamp_cm = CoreMediaGlue::CMTimeMake(
260 frame->timestamp().InMicroseconds(), USEC_PER_SEC);
261 // Wrap information we'll need after the frame is encoded in a heap object.
262 // We'll get the pointer back from the VideoToolbox completion callback.
263 scoped_ptr<InProgressFrameEncode> request(new InProgressFrameEncode(
264 frame->timestamp(), ref_time));
265
266 // We can pass the ownership of |request| to the encode callback if
267 // successful. Otherwise let it fall out of scope.
268 OSStatus status = videotoolbox_glue_->VTCompressionSessionEncodeFrame(
269 compression_session_, pixel_buffer, timestamp_cm,
270 CoreMediaGlue::CMTime{0, 0, 0, 0}, frame_props,
271 reinterpret_cast<void*>(request.get()), nullptr);
272 if (status != noErr) {
273 DLOG(ERROR) << " VTCompressionSessionEncodeFrame failed: " << status;
274 NotifyError(kPlatformFailureError);
275 } else {
276 CHECK(request.release());
277 }
278 }
279
280 void VTVideoEncodeAccelerator::UseOutputBitstreamBufferTask(
281 scoped_ptr<BitstreamBufferRef> buffer_ref) {
282 DCHECK(encoder_thread_task_runner_->BelongsToCurrentThread());
283
284 // If there is already EncodeOutput waiting, copy its output first.
285 if (!encoder_output_queue_.empty()) {
286 scoped_ptr<VTVideoEncodeAccelerator::EncodeOutput> encode_output =
287 std::move(encoder_output_queue_.front());
288 encoder_output_queue_.pop_front();
289 ReturnBitstreamBuffer(std::move(encode_output), std::move(buffer_ref));
290 return;
291 }
292
293 bitstream_buffer_queue_.push_back(std::move(buffer_ref));
294 }
295
296 void VTVideoEncodeAccelerator::RequestEncodingParametersChangeTask(
297 uint32_t bitrate,
298 uint32_t framerate) {
299 DCHECK(encoder_thread_task_runner_->BelongsToCurrentThread());
300
301 frame_rate_ = framerate > 1 ? framerate : 1;
302 target_bitrate_ = bitrate > 1 ? bitrate : 1;
303
304 if (!compression_session_) {
305 NotifyError(kPlatformFailureError);
306 return;
307 }
308
309 media::video_toolbox::SessionPropertySetter session_property_setter(
310 compression_session_, videotoolbox_glue_);
311 // TODO(emircan): See crbug.com/425352.
312 bool rv = session_property_setter.Set(
313 videotoolbox_glue_->kVTCompressionPropertyKey_AverageBitRate(),
314 target_bitrate_);
315 rv &= session_property_setter.Set(
316 videotoolbox_glue_->kVTCompressionPropertyKey_ExpectedFrameRate(),
317 frame_rate_);
318 rv &= session_property_setter.Set(
319 videotoolbox_glue_->kVTCompressionPropertyKey_DataRateLimits(),
320 media::video_toolbox::ArrayWithIntegerAndFloat(
321 target_bitrate_ / kBitsPerByte, 1.0f));
322 DLOG_IF(ERROR, !rv) << "Couldn't change session encoding parameters.";
323 }
324
325 void VTVideoEncodeAccelerator::DestroyTask() {
326 DCHECK(thread_checker_.CalledOnValidThread() ||
327 (encoder_thread_.IsRunning() &&
328 encoder_thread_task_runner_->BelongsToCurrentThread()));
329
330 // Cancel all encoder thread callbacks.
331 encoder_task_weak_factory_.InvalidateWeakPtrs();
332
333 // This call blocks until all pending frames are flushed out.
334 DestroyCompressionSession();
335 }
336
337 void VTVideoEncodeAccelerator::NotifyError(
338 media::VideoEncodeAccelerator::Error error) {
339 DCHECK(encoder_thread_task_runner_->BelongsToCurrentThread());
340 client_task_runner_->PostTask(
341 FROM_HERE, base::Bind(&Client::NotifyError, client_, error));
342 }
343
344 // static
345 void VTVideoEncodeAccelerator::CompressionCallback(void* encoder_opaque,
346 void* request_opaque,
347 OSStatus status,
348 VTEncodeInfoFlags info,
349 CMSampleBufferRef sbuf) {
350 // This function may be called asynchronously, on a different thread from the
351 // one that calls VTCompressionSessionEncodeFrame.
352 DVLOG(3) << __FUNCTION__;
353
354 auto encoder = reinterpret_cast<VTVideoEncodeAccelerator*>(encoder_opaque);
355 DCHECK(encoder);
356
357 // Release InProgressFrameEncode, since we don't have support to return
358 // timestamps at this point.
359 scoped_ptr<InProgressFrameEncode> request(
360 reinterpret_cast<InProgressFrameEncode*>(request_opaque));
361 request.reset();
362
363 // EncodeOutput holds onto CMSampleBufferRef when posting task between
364 // threads.
365 scoped_ptr<EncodeOutput> encode_output(new EncodeOutput(info, sbuf));
366
367 // This method is NOT called on |encoder_thread_|, so we still need to
368 // post a task back to it to do work.
369 encoder->encoder_thread_task_runner_->PostTask(
370 FROM_HERE, base::Bind(&VTVideoEncodeAccelerator::CompressionCallbackTask,
371 encoder->encoder_weak_ptr_, status,
372 base::Passed(&encode_output)));
373 }
374
375 void VTVideoEncodeAccelerator::CompressionCallbackTask(
376 OSStatus status,
377 scoped_ptr<EncodeOutput> encode_output) {
378 DCHECK(encoder_thread_task_runner_->BelongsToCurrentThread());
379
380 if (status != noErr) {
381 DLOG(ERROR) << " encode failed: " << status;
382 NotifyError(kPlatformFailureError);
383 return;
384 }
385
386 // If there isn't any BitstreamBuffer to copy into, add it to a queue for
387 // later use.
388 if (bitstream_buffer_queue_.empty()) {
389 encoder_output_queue_.push_back(std::move(encode_output));
390 return;
391 }
392
393 scoped_ptr<VTVideoEncodeAccelerator::BitstreamBufferRef> buffer_ref =
394 std::move(bitstream_buffer_queue_.front());
395 bitstream_buffer_queue_.pop_front();
396 ReturnBitstreamBuffer(std::move(encode_output), std::move(buffer_ref));
397 }
398
399 void VTVideoEncodeAccelerator::ReturnBitstreamBuffer(
400 scoped_ptr<EncodeOutput> encode_output,
401 scoped_ptr<VTVideoEncodeAccelerator::BitstreamBufferRef> buffer_ref) {
402 DVLOG(3) << __FUNCTION__;
403 DCHECK(encoder_thread_task_runner_->BelongsToCurrentThread());
404
405 if (encode_output->info & VideoToolboxGlue::kVTEncodeInfo_FrameDropped) {
406 DVLOG(2) << " frame dropped";
407 client_task_runner_->PostTask(
408 FROM_HERE, base::Bind(&Client::BitstreamBufferReady, client_,
409 buffer_ref->id, 0, false));
410 return;
411 }
412
413 auto sample_attachments = static_cast<CFDictionaryRef>(CFArrayGetValueAtIndex(
414 CoreMediaGlue::CMSampleBufferGetSampleAttachmentsArray(
415 encode_output->sample_buffer.get(), true),
416 0));
417 const bool keyframe =
418 !CFDictionaryContainsKey(sample_attachments,
419 CoreMediaGlue::kCMSampleAttachmentKey_NotSync());
420
421 size_t used_buffer_size = 0;
422 const bool copy_rv = media::video_toolbox::CopySampleBufferToAnnexBBuffer(
423 encode_output->sample_buffer.get(), keyframe, buffer_ref->size,
424 reinterpret_cast<char*>(buffer_ref->shm->memory()), &used_buffer_size);
425 if (!copy_rv) {
426 DLOG(ERROR) << "Cannot copy output from SampleBuffer to AnnexBBuffer.";
427 used_buffer_size = 0;
428 }
429
430 client_task_runner_->PostTask(
431 FROM_HERE, base::Bind(&Client::BitstreamBufferReady, client_,
432 buffer_ref->id, used_buffer_size, keyframe));
433 }
434
435 bool VTVideoEncodeAccelerator::ResetCompressionSession() {
436 DCHECK(thread_checker_.CalledOnValidThread());
437
438 DestroyCompressionSession();
439
440 CFTypeRef attributes_keys[] = {
441 kCVPixelBufferOpenGLCompatibilityKey,
442 kCVPixelBufferIOSurfacePropertiesKey,
443 kCVPixelBufferPixelFormatTypeKey
444 };
445 const int format[] = {
446 CoreVideoGlue::kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange};
447 CFTypeRef attributes_values[] = {
448 kCFBooleanTrue,
449 media::video_toolbox::DictionaryWithKeysAndValues(nullptr, nullptr, 0)
450 .release(),
451 media::video_toolbox::ArrayWithIntegers(format, arraysize(format))
452 .release()};
453 const base::ScopedCFTypeRef<CFDictionaryRef> attributes =
454 media::video_toolbox::DictionaryWithKeysAndValues(
455 attributes_keys, attributes_values, arraysize(attributes_keys));
456 for (auto& v : attributes_values)
457 CFRelease(v);
458
459 bool session_rv =
460 CreateCompressionSession(attributes, input_visible_size_, false);
461 if (!session_rv) {
462 DestroyCompressionSession();
463 return false;
464 }
465
466 const bool configure_rv = ConfigureCompressionSession();
467 if (configure_rv)
468 RequestEncodingParametersChange(target_bitrate_, frame_rate_);
469 return configure_rv;
470 }
471
472 bool VTVideoEncodeAccelerator::CreateCompressionSession(
473 base::ScopedCFTypeRef<CFDictionaryRef> attributes,
474 const gfx::Size& input_size,
475 bool require_hw_encoding) {
476 DCHECK(thread_checker_.CalledOnValidThread());
477
478 std::vector<CFTypeRef> encoder_keys;
479 std::vector<CFTypeRef> encoder_values;
480 if (require_hw_encoding) {
481 encoder_keys.push_back(videotoolbox_glue_
482 ->kVTVideoEncoderSpecification_RequireHardwareAcceleratedVideoEncoder());
483 encoder_values.push_back(kCFBooleanTrue);
484 } else {
485 encoder_keys.push_back(videotoolbox_glue_
486 ->kVTVideoEncoderSpecification_EnableHardwareAcceleratedVideoEncoder());
487 encoder_values.push_back(kCFBooleanTrue);
488 }
489 base::ScopedCFTypeRef<CFDictionaryRef> encoder_spec =
490 media::video_toolbox::DictionaryWithKeysAndValues(
491 encoder_keys.data(), encoder_values.data(), encoder_keys.size());
492
493 // Create the compression session.
494 // Note that the encoder object is given to the compression session as the
495 // callback context using a raw pointer. The C API does not allow us to use a
496 // smart pointer, nor is this encoder ref counted. However, this is still
497 // safe, because we 1) we own the compression session and 2) we tear it down
498 // safely. When destructing the encoder, the compression session is flushed
499 // and invalidated. Internally, VideoToolbox will join all of its threads
500 // before returning to the client. Therefore, when control returns to us, we
501 // are guaranteed that the output callback will not execute again.
502 OSStatus status = videotoolbox_glue_->VTCompressionSessionCreate(
503 kCFAllocatorDefault,
504 input_size.width(),
505 input_size.height(),
506 CoreMediaGlue::kCMVideoCodecType_H264,
507 encoder_spec,
508 attributes,
509 nullptr /* compressedDataAllocator */,
510 &VTVideoEncodeAccelerator::CompressionCallback,
511 reinterpret_cast<void*>(this),
512 compression_session_.InitializeInto());
513 if (status != noErr) {
514 DLOG(ERROR) << " VTCompressionSessionCreate failed: " << status;
515 return false;
516 }
517 DVLOG(3) << " VTCompressionSession created with HW encode: "
518 << require_hw_encoding << ", input size=" << input_size.ToString();
519 return true;
520 }
521
522 bool VTVideoEncodeAccelerator::ConfigureCompressionSession() {
523 DCHECK(thread_checker_.CalledOnValidThread());
524 DCHECK(compression_session_);
525
526 media::video_toolbox::SessionPropertySetter session_property_setter(
527 compression_session_, videotoolbox_glue_);
528 bool rv = true;
529 rv &= session_property_setter.Set(
530 videotoolbox_glue_->kVTCompressionPropertyKey_ProfileLevel(),
531 videotoolbox_glue_->kVTProfileLevel_H264_Baseline_AutoLevel());
532 rv &= session_property_setter.Set(
533 videotoolbox_glue_->kVTCompressionPropertyKey_RealTime(), true);
534 rv &= session_property_setter.Set(
535 videotoolbox_glue_->kVTCompressionPropertyKey_AllowFrameReordering(),
536 false);
537 DLOG_IF(ERROR, !rv) << " Setting session property failed.";
538 return rv;
539 }
540
541 void VTVideoEncodeAccelerator::DestroyCompressionSession() {
542 DCHECK(thread_checker_.CalledOnValidThread() ||
543 (encoder_thread_.IsRunning() &&
544 encoder_thread_task_runner_->BelongsToCurrentThread()));
545
546 if (compression_session_) {
547 videotoolbox_glue_->VTCompressionSessionInvalidate(compression_session_);
548 compression_session_.reset();
549 }
550 }
551
552 } // namespace content
OLDNEW
« no previous file with comments | « content/common/gpu/media/vt_video_encode_accelerator_mac.h ('k') | content/content_common.gypi » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698