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

Side by Side Diff: media/cast/sender/h264_vt_encoder.cc

Issue 2529493002: mac: Remove more media/base/mac glue unneeded now that we target 10.9 (Closed)
Patch Set: . Created 4 years 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 | « media/cast/sender/h264_vt_encoder.h ('k') | media/cast/sender/h264_vt_encoder_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 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/cast/sender/h264_vt_encoder.h" 5 #include "media/cast/sender/h264_vt_encoder.h"
6 6
7 #include <stddef.h> 7 #include <stddef.h>
8 8
9 #include <string> 9 #include <string>
10 #include <vector> 10 #include <vector>
11 11
12 #include "base/big_endian.h" 12 #include "base/big_endian.h"
13 #include "base/bind.h" 13 #include "base/bind.h"
14 #include "base/bind_helpers.h" 14 #include "base/bind_helpers.h"
15 #include "base/location.h" 15 #include "base/location.h"
16 #include "base/logging.h" 16 #include "base/logging.h"
17 #include "base/macros.h" 17 #include "base/macros.h"
18 #include "base/power_monitor/power_monitor.h" 18 #include "base/power_monitor/power_monitor.h"
19 #include "base/synchronization/lock.h" 19 #include "base/synchronization/lock.h"
20 #include "build/build_config.h" 20 #include "build/build_config.h"
21 #include "media/base/mac/corevideo_glue.h"
22 #include "media/base/mac/video_frame_mac.h" 21 #include "media/base/mac/video_frame_mac.h"
23 #include "media/cast/common/rtp_time.h" 22 #include "media/cast/common/rtp_time.h"
24 #include "media/cast/constants.h" 23 #include "media/cast/constants.h"
25 #include "media/cast/sender/video_frame_factory.h" 24 #include "media/cast/sender/video_frame_factory.h"
26 25
27 namespace media { 26 namespace media {
28 namespace cast { 27 namespace cast {
29 28
30 namespace { 29 namespace {
31 30
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after
141 ~Proxy() final {} 140 ~Proxy() final {}
142 141
143 const scoped_refptr<VideoFrameFactoryImpl> video_frame_factory_; 142 const scoped_refptr<VideoFrameFactoryImpl> video_frame_factory_;
144 143
145 DISALLOW_COPY_AND_ASSIGN(Proxy); 144 DISALLOW_COPY_AND_ASSIGN(Proxy);
146 }; 145 };
147 146
148 // static 147 // static
149 bool H264VideoToolboxEncoder::IsSupported( 148 bool H264VideoToolboxEncoder::IsSupported(
150 const FrameSenderConfig& video_config) { 149 const FrameSenderConfig& video_config) {
151 return video_config.codec == CODEC_VIDEO_H264 && VideoToolboxGlue::Get(); 150 return video_config.codec == CODEC_VIDEO_H264;
152 } 151 }
153 152
154 H264VideoToolboxEncoder::H264VideoToolboxEncoder( 153 H264VideoToolboxEncoder::H264VideoToolboxEncoder(
155 const scoped_refptr<CastEnvironment>& cast_environment, 154 const scoped_refptr<CastEnvironment>& cast_environment,
156 const FrameSenderConfig& video_config, 155 const FrameSenderConfig& video_config,
157 const StatusChangeCallback& status_change_cb) 156 const StatusChangeCallback& status_change_cb)
158 : cast_environment_(cast_environment), 157 : cast_environment_(cast_environment),
159 videotoolbox_glue_(VideoToolboxGlue::Get()),
160 video_config_(video_config), 158 video_config_(video_config),
161 status_change_cb_(status_change_cb), 159 status_change_cb_(status_change_cb),
162 next_frame_id_(FrameId::first()), 160 next_frame_id_(FrameId::first()),
163 encode_next_frame_as_keyframe_(false), 161 encode_next_frame_as_keyframe_(false),
164 power_suspended_(false), 162 power_suspended_(false),
165 weak_factory_(this) { 163 weak_factory_(this) {
166 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); 164 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN));
167 DCHECK(!status_change_cb_.is_null()); 165 DCHECK(!status_change_cb_.is_null());
168 166
169 OperationalStatus operational_status = 167 OperationalStatus operational_status =
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
219 base::Bind(status_change_cb_, STATUS_CODEC_REINIT_PENDING)); 217 base::Bind(status_change_cb_, STATUS_CODEC_REINIT_PENDING));
220 218
221 // Destroy the current session, if any. 219 // Destroy the current session, if any.
222 DestroyCompressionSession(); 220 DestroyCompressionSession();
223 221
224 // On OS X, allow the hardware encoder. Don't require it, it does not support 222 // On OS X, allow the hardware encoder. Don't require it, it does not support
225 // all configurations (some of which are used for testing). 223 // all configurations (some of which are used for testing).
226 base::ScopedCFTypeRef<CFDictionaryRef> encoder_spec; 224 base::ScopedCFTypeRef<CFDictionaryRef> encoder_spec;
227 #if !defined(OS_IOS) 225 #if !defined(OS_IOS)
228 encoder_spec = video_toolbox::DictionaryWithKeyValue( 226 encoder_spec = video_toolbox::DictionaryWithKeyValue(
229 videotoolbox_glue_ 227 kVTVideoEncoderSpecification_EnableHardwareAcceleratedVideoEncoder,
230 ->kVTVideoEncoderSpecification_EnableHardwareAcceleratedVideoEncoder() ,
231 kCFBooleanTrue); 228 kCFBooleanTrue);
232 #endif 229 #endif
233 230
234 // Force 420v so that clients can easily use these buffers as GPU textures. 231 // Force 420v so that clients can easily use these buffers as GPU textures.
235 const int format[] = { 232 const int format[] = {kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange};
236 CoreVideoGlue::kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange};
237 233
238 // Keep these attachment settings in-sync with those in ConfigureSession(). 234 // Keep these attachment settings in-sync with those in ConfigureSession().
239 CFTypeRef attachments_keys[] = {kCVImageBufferColorPrimariesKey, 235 CFTypeRef attachments_keys[] = {kCVImageBufferColorPrimariesKey,
240 kCVImageBufferTransferFunctionKey, 236 kCVImageBufferTransferFunctionKey,
241 kCVImageBufferYCbCrMatrixKey}; 237 kCVImageBufferYCbCrMatrixKey};
242 CFTypeRef attachments_values[] = {kCVImageBufferColorPrimaries_ITU_R_709_2, 238 CFTypeRef attachments_values[] = {kCVImageBufferColorPrimaries_ITU_R_709_2,
243 kCVImageBufferTransferFunction_ITU_R_709_2, 239 kCVImageBufferTransferFunction_ITU_R_709_2,
244 kCVImageBufferYCbCrMatrix_ITU_R_709_2}; 240 kCVImageBufferYCbCrMatrix_ITU_R_709_2};
245 CFTypeRef buffer_attributes_keys[] = {kCVPixelBufferPixelFormatTypeKey, 241 CFTypeRef buffer_attributes_keys[] = {kCVPixelBufferPixelFormatTypeKey,
246 kCVBufferPropagatedAttachmentsKey}; 242 kCVBufferPropagatedAttachmentsKey};
(...skipping 12 matching lines...) Expand all
259 // Create the compression session. 255 // Create the compression session.
260 256
261 // Note that the encoder object is given to the compression session as the 257 // Note that the encoder object is given to the compression session as the
262 // callback context using a raw pointer. The C API does not allow us to use a 258 // callback context using a raw pointer. The C API does not allow us to use a
263 // smart pointer, nor is this encoder ref counted. However, this is still 259 // smart pointer, nor is this encoder ref counted. However, this is still
264 // safe, because we 1) we own the compression session and 2) we tear it down 260 // safe, because we 1) we own the compression session and 2) we tear it down
265 // safely. When destructing the encoder, the compression session is flushed 261 // safely. When destructing the encoder, the compression session is flushed
266 // and invalidated. Internally, VideoToolbox will join all of its threads 262 // and invalidated. Internally, VideoToolbox will join all of its threads
267 // before returning to the client. Therefore, when control returns to us, we 263 // before returning to the client. Therefore, when control returns to us, we
268 // are guaranteed that the output callback will not execute again. 264 // are guaranteed that the output callback will not execute again.
269 OSStatus status = videotoolbox_glue_->VTCompressionSessionCreate( 265 OSStatus status = VTCompressionSessionCreate(
270 kCFAllocatorDefault, frame_size_.width(), frame_size_.height(), 266 kCFAllocatorDefault, frame_size_.width(), frame_size_.height(),
271 CoreMediaGlue::kCMVideoCodecType_H264, encoder_spec, buffer_attributes, 267 kCMVideoCodecType_H264, encoder_spec, buffer_attributes,
272 nullptr /* compressedDataAllocator */, 268 nullptr /* compressedDataAllocator */,
273 &H264VideoToolboxEncoder::CompressionCallback, 269 &H264VideoToolboxEncoder::CompressionCallback,
274 reinterpret_cast<void*>(this), compression_session_.InitializeInto()); 270 reinterpret_cast<void*>(this), compression_session_.InitializeInto());
275 if (status != noErr) { 271 if (status != noErr) {
276 DLOG(ERROR) << " VTCompressionSessionCreate failed: " << status; 272 DLOG(ERROR) << " VTCompressionSessionCreate failed: " << status;
277 // Notify that reinitialization has failed. 273 // Notify that reinitialization has failed.
278 cast_environment_->PostTask( 274 cast_environment_->PostTask(
279 CastEnvironment::MAIN, FROM_HERE, 275 CastEnvironment::MAIN, FROM_HERE,
280 base::Bind(status_change_cb_, STATUS_CODEC_INIT_FAILED)); 276 base::Bind(status_change_cb_, STATUS_CODEC_INIT_FAILED));
281 return; 277 return;
282 } 278 }
283 279
284 // Configure the session (apply session properties based on the current state 280 // Configure the session (apply session properties based on the current state
285 // of the encoder, experimental tuning and requirements). 281 // of the encoder, experimental tuning and requirements).
286 ConfigureCompressionSession(); 282 ConfigureCompressionSession();
287 283
288 // Update the video frame factory. 284 // Update the video frame factory.
289 base::ScopedCFTypeRef<CVPixelBufferPoolRef> pool( 285 base::ScopedCFTypeRef<CVPixelBufferPoolRef> pool(
290 videotoolbox_glue_->VTCompressionSessionGetPixelBufferPool( 286 VTCompressionSessionGetPixelBufferPool(compression_session_),
291 compression_session_),
292 base::scoped_policy::RETAIN); 287 base::scoped_policy::RETAIN);
293 video_frame_factory_->Update(pool, frame_size_); 288 video_frame_factory_->Update(pool, frame_size_);
294 289
295 // Notify that reinitialization is done. 290 // Notify that reinitialization is done.
296 cast_environment_->PostTask( 291 cast_environment_->PostTask(
297 CastEnvironment::MAIN, FROM_HERE, 292 CastEnvironment::MAIN, FROM_HERE,
298 base::Bind(status_change_cb_, STATUS_INITIALIZED)); 293 base::Bind(status_change_cb_, STATUS_INITIALIZED));
299 } 294 }
300 295
301 void H264VideoToolboxEncoder::ConfigureCompressionSession() { 296 void H264VideoToolboxEncoder::ConfigureCompressionSession() {
302 video_toolbox::SessionPropertySetter session_property_setter( 297 video_toolbox::SessionPropertySetter session_property_setter(
303 compression_session_, videotoolbox_glue_); 298 compression_session_);
299 session_property_setter.Set(kVTCompressionPropertyKey_ProfileLevel,
300 kVTProfileLevel_H264_Main_AutoLevel);
301 session_property_setter.Set(kVTCompressionPropertyKey_RealTime, true);
302 session_property_setter.Set(kVTCompressionPropertyKey_AllowFrameReordering,
303 false);
304 session_property_setter.Set(kVTCompressionPropertyKey_MaxKeyFrameInterval,
305 240);
304 session_property_setter.Set( 306 session_property_setter.Set(
305 videotoolbox_glue_->kVTCompressionPropertyKey_ProfileLevel(), 307 kVTCompressionPropertyKey_MaxKeyFrameIntervalDuration, 240);
306 videotoolbox_glue_->kVTProfileLevel_H264_Main_AutoLevel());
307 session_property_setter.Set(
308 videotoolbox_glue_->kVTCompressionPropertyKey_RealTime(), true);
309 session_property_setter.Set(
310 videotoolbox_glue_->kVTCompressionPropertyKey_AllowFrameReordering(),
311 false);
312 session_property_setter.Set(
313 videotoolbox_glue_->kVTCompressionPropertyKey_MaxKeyFrameInterval(), 240);
314 session_property_setter.Set(
315 videotoolbox_glue_
316 ->kVTCompressionPropertyKey_MaxKeyFrameIntervalDuration(),
317 240);
318 // TODO(jfroy): implement better bitrate control 308 // TODO(jfroy): implement better bitrate control
319 // https://crbug.com/425352 309 // https://crbug.com/425352
320 session_property_setter.Set( 310 session_property_setter.Set(
321 videotoolbox_glue_->kVTCompressionPropertyKey_AverageBitRate(), 311 kVTCompressionPropertyKey_AverageBitRate,
322 (video_config_.min_bitrate + video_config_.max_bitrate) / 2); 312 (video_config_.min_bitrate + video_config_.max_bitrate) / 2);
323 session_property_setter.Set( 313 session_property_setter.Set(
324 videotoolbox_glue_->kVTCompressionPropertyKey_ExpectedFrameRate(), 314 kVTCompressionPropertyKey_ExpectedFrameRate,
325 static_cast<int>(video_config_.max_frame_rate + 0.5)); 315 static_cast<int>(video_config_.max_frame_rate + 0.5));
326 // Keep these attachment settings in-sync with those in Initialize(). 316 // Keep these attachment settings in-sync with those in Initialize().
327 session_property_setter.Set( 317 session_property_setter.Set(kVTCompressionPropertyKey_ColorPrimaries,
328 videotoolbox_glue_->kVTCompressionPropertyKey_ColorPrimaries(), 318 kCVImageBufferColorPrimaries_ITU_R_709_2);
329 kCVImageBufferColorPrimaries_ITU_R_709_2); 319 session_property_setter.Set(kVTCompressionPropertyKey_TransferFunction,
330 session_property_setter.Set( 320 kCVImageBufferTransferFunction_ITU_R_709_2);
331 videotoolbox_glue_->kVTCompressionPropertyKey_TransferFunction(), 321 session_property_setter.Set(kVTCompressionPropertyKey_YCbCrMatrix,
332 kCVImageBufferTransferFunction_ITU_R_709_2); 322 kCVImageBufferYCbCrMatrix_ITU_R_709_2);
333 session_property_setter.Set(
334 videotoolbox_glue_->kVTCompressionPropertyKey_YCbCrMatrix(),
335 kCVImageBufferYCbCrMatrix_ITU_R_709_2);
336 if (video_config_.video_codec_params.max_number_of_video_buffers_used > 0) { 323 if (video_config_.video_codec_params.max_number_of_video_buffers_used > 0) {
337 session_property_setter.Set( 324 session_property_setter.Set(
338 videotoolbox_glue_->kVTCompressionPropertyKey_MaxFrameDelayCount(), 325 kVTCompressionPropertyKey_MaxFrameDelayCount,
339 video_config_.video_codec_params.max_number_of_video_buffers_used); 326 video_config_.video_codec_params.max_number_of_video_buffers_used);
340 } 327 }
341 } 328 }
342 329
343 void H264VideoToolboxEncoder::DestroyCompressionSession() { 330 void H264VideoToolboxEncoder::DestroyCompressionSession() {
344 DCHECK(thread_checker_.CalledOnValidThread()); 331 DCHECK(thread_checker_.CalledOnValidThread());
345 332
346 // If the compression session exists, invalidate it. This blocks until all 333 // If the compression session exists, invalidate it. This blocks until all
347 // pending output callbacks have returned and any internal threads have 334 // pending output callbacks have returned and any internal threads have
348 // joined, ensuring no output callback ever sees a dangling encoder pointer. 335 // joined, ensuring no output callback ever sees a dangling encoder pointer.
349 // 336 //
350 // Before destroying the compression session, the video frame factory's pool 337 // Before destroying the compression session, the video frame factory's pool
351 // is updated to null so that no thread will produce new video frames via the 338 // is updated to null so that no thread will produce new video frames via the
352 // factory until a new compression session is created. The current frame size 339 // factory until a new compression session is created. The current frame size
353 // is passed to prevent the video frame factory from posting |UpdateFrameSize| 340 // is passed to prevent the video frame factory from posting |UpdateFrameSize|
354 // tasks. Indeed, |DestroyCompressionSession| is either called from 341 // tasks. Indeed, |DestroyCompressionSession| is either called from
355 // |ResetCompressionSession|, in which case a new pool and frame size will be 342 // |ResetCompressionSession|, in which case a new pool and frame size will be
356 // set, or from callsites that require that there be no compression session 343 // set, or from callsites that require that there be no compression session
357 // (ex: the dtor). 344 // (ex: the dtor).
358 if (compression_session_) { 345 if (compression_session_) {
359 video_frame_factory_->Update( 346 video_frame_factory_->Update(
360 base::ScopedCFTypeRef<CVPixelBufferPoolRef>(nullptr), frame_size_); 347 base::ScopedCFTypeRef<CVPixelBufferPoolRef>(nullptr), frame_size_);
361 videotoolbox_glue_->VTCompressionSessionInvalidate(compression_session_); 348 VTCompressionSessionInvalidate(compression_session_);
362 compression_session_.reset(); 349 compression_session_.reset();
363 } 350 }
364 } 351 }
365 352
366 bool H264VideoToolboxEncoder::EncodeVideoFrame( 353 bool H264VideoToolboxEncoder::EncodeVideoFrame(
367 const scoped_refptr<media::VideoFrame>& video_frame, 354 const scoped_refptr<media::VideoFrame>& video_frame,
368 const base::TimeTicks& reference_time, 355 const base::TimeTicks& reference_time,
369 const FrameEncodedCallback& frame_encoded_callback) { 356 const FrameEncodedCallback& frame_encoded_callback) {
370 DCHECK(thread_checker_.CalledOnValidThread()); 357 DCHECK(thread_checker_.CalledOnValidThread());
371 DCHECK(!frame_encoded_callback.is_null()); 358 DCHECK(!frame_encoded_callback.is_null());
(...skipping 23 matching lines...) Expand all
395 // compression session's pixel buffer pool. This will eliminate a copy of the 382 // compression session's pixel buffer pool. This will eliminate a copy of the
396 // frame into memory visible by the hardware encoder. The VideoFrame's 383 // frame into memory visible by the hardware encoder. The VideoFrame's
397 // lifetime is extended for the lifetime of the returned CVPixelBuffer. 384 // lifetime is extended for the lifetime of the returned CVPixelBuffer.
398 auto pixel_buffer = media::WrapVideoFrameInCVPixelBuffer(*video_frame); 385 auto pixel_buffer = media::WrapVideoFrameInCVPixelBuffer(*video_frame);
399 if (!pixel_buffer) { 386 if (!pixel_buffer) {
400 DLOG(ERROR) << "WrapVideoFrameInCVPixelBuffer failed."; 387 DLOG(ERROR) << "WrapVideoFrameInCVPixelBuffer failed.";
401 return false; 388 return false;
402 } 389 }
403 390
404 // Convert the frame timestamp to CMTime. 391 // Convert the frame timestamp to CMTime.
405 auto timestamp_cm = CoreMediaGlue::CMTimeMake( 392 auto timestamp_cm =
406 video_frame->timestamp().InMicroseconds(), USEC_PER_SEC); 393 CMTimeMake(video_frame->timestamp().InMicroseconds(), USEC_PER_SEC);
407 394
408 // Wrap information we'll need after the frame is encoded in a heap object. 395 // Wrap information we'll need after the frame is encoded in a heap object.
409 // We'll get the pointer back from the VideoToolbox completion callback. 396 // We'll get the pointer back from the VideoToolbox completion callback.
410 std::unique_ptr<InProgressFrameEncode> request(new InProgressFrameEncode( 397 std::unique_ptr<InProgressFrameEncode> request(new InProgressFrameEncode(
411 RtpTimeTicks::FromTimeDelta(video_frame->timestamp(), kVideoFrequency), 398 RtpTimeTicks::FromTimeDelta(video_frame->timestamp(), kVideoFrequency),
412 reference_time, frame_encoded_callback)); 399 reference_time, frame_encoded_callback));
413 400
414 // Build a suitable frame properties dictionary for keyframes. 401 // Build a suitable frame properties dictionary for keyframes.
415 base::ScopedCFTypeRef<CFDictionaryRef> frame_props; 402 base::ScopedCFTypeRef<CFDictionaryRef> frame_props;
416 if (encode_next_frame_as_keyframe_) { 403 if (encode_next_frame_as_keyframe_) {
417 frame_props = video_toolbox::DictionaryWithKeyValue( 404 frame_props = video_toolbox::DictionaryWithKeyValue(
418 videotoolbox_glue_->kVTEncodeFrameOptionKey_ForceKeyFrame(), 405 kVTEncodeFrameOptionKey_ForceKeyFrame, kCFBooleanTrue);
419 kCFBooleanTrue);
420 encode_next_frame_as_keyframe_ = false; 406 encode_next_frame_as_keyframe_ = false;
421 } 407 }
422 408
423 // Submit the frame to the compression session. The function returns as soon 409 // Submit the frame to the compression session. The function returns as soon
424 // as the frame has been enqueued. 410 // as the frame has been enqueued.
425 OSStatus status = videotoolbox_glue_->VTCompressionSessionEncodeFrame( 411 OSStatus status = VTCompressionSessionEncodeFrame(
426 compression_session_, pixel_buffer, timestamp_cm, 412 compression_session_, pixel_buffer, timestamp_cm, CMTime{0, 0, 0, 0},
427 CoreMediaGlue::CMTime{0, 0, 0, 0}, frame_props, 413 frame_props, reinterpret_cast<void*>(request.release()), nullptr);
428 reinterpret_cast<void*>(request.release()), nullptr);
429 if (status != noErr) { 414 if (status != noErr) {
430 DLOG(ERROR) << " VTCompressionSessionEncodeFrame failed: " << status; 415 DLOG(ERROR) << " VTCompressionSessionEncodeFrame failed: " << status;
431 return false; 416 return false;
432 } 417 }
433 418
434 return true; 419 return true;
435 } 420 }
436 421
437 void H264VideoToolboxEncoder::UpdateFrameSize(const gfx::Size& size_needed) { 422 void H264VideoToolboxEncoder::UpdateFrameSize(const gfx::Size& size_needed) {
438 DCHECK(thread_checker_.CalledOnValidThread()); 423 DCHECK(thread_checker_.CalledOnValidThread());
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
475 DCHECK(thread_checker_.CalledOnValidThread()); 460 DCHECK(thread_checker_.CalledOnValidThread());
476 return std::unique_ptr<VideoFrameFactory>( 461 return std::unique_ptr<VideoFrameFactory>(
477 new VideoFrameFactoryImpl::Proxy(video_frame_factory_)); 462 new VideoFrameFactoryImpl::Proxy(video_frame_factory_));
478 } 463 }
479 464
480 void H264VideoToolboxEncoder::EmitFrames() { 465 void H264VideoToolboxEncoder::EmitFrames() {
481 DCHECK(thread_checker_.CalledOnValidThread()); 466 DCHECK(thread_checker_.CalledOnValidThread());
482 if (!compression_session_) 467 if (!compression_session_)
483 return; 468 return;
484 469
485 OSStatus status = videotoolbox_glue_->VTCompressionSessionCompleteFrames( 470 OSStatus status = VTCompressionSessionCompleteFrames(compression_session_,
486 compression_session_, CoreMediaGlue::CMTime{0, 0, 0, 0}); 471 CMTime{0, 0, 0, 0});
487 if (status != noErr) { 472 if (status != noErr) {
488 DLOG(ERROR) << " VTCompressionSessionCompleteFrames failed: " << status; 473 DLOG(ERROR) << " VTCompressionSessionCompleteFrames failed: " << status;
489 } 474 }
490 } 475 }
491 476
492 void H264VideoToolboxEncoder::OnSuspend() { 477 void H264VideoToolboxEncoder::OnSuspend() {
493 VLOG(1) 478 VLOG(1)
494 << "OnSuspend: Emitting all frames and destroying compression session."; 479 << "OnSuspend: Emitting all frames and destroying compression session.";
495 EmitFrames(); 480 EmitFrames();
496 DestroyCompressionSession(); 481 DestroyCompressionSession();
(...skipping 22 matching lines...) Expand all
519 const std::unique_ptr<InProgressFrameEncode> request( 504 const std::unique_ptr<InProgressFrameEncode> request(
520 reinterpret_cast<InProgressFrameEncode*>(request_opaque)); 505 reinterpret_cast<InProgressFrameEncode*>(request_opaque));
521 bool keyframe = false; 506 bool keyframe = false;
522 bool has_frame_data = false; 507 bool has_frame_data = false;
523 508
524 if (status != noErr) { 509 if (status != noErr) {
525 DLOG(ERROR) << " encoding failed: " << status; 510 DLOG(ERROR) << " encoding failed: " << status;
526 encoder->cast_environment_->PostTask( 511 encoder->cast_environment_->PostTask(
527 CastEnvironment::MAIN, FROM_HERE, 512 CastEnvironment::MAIN, FROM_HERE,
528 base::Bind(encoder->status_change_cb_, STATUS_CODEC_RUNTIME_ERROR)); 513 base::Bind(encoder->status_change_cb_, STATUS_CODEC_RUNTIME_ERROR));
529 } else if ((info & VideoToolboxGlue::kVTEncodeInfo_FrameDropped)) { 514 } else if ((info & kVTEncodeInfo_FrameDropped)) {
530 DVLOG(2) << " frame dropped"; 515 DVLOG(2) << " frame dropped";
531 } else { 516 } else {
532 auto* sample_attachments = 517 auto* sample_attachments =
533 static_cast<CFDictionaryRef>(CFArrayGetValueAtIndex( 518 static_cast<CFDictionaryRef>(CFArrayGetValueAtIndex(
534 CoreMediaGlue::CMSampleBufferGetSampleAttachmentsArray(sbuf, true), 519 CMSampleBufferGetSampleAttachmentsArray(sbuf, true), 0));
535 0));
536 520
537 // If the NotSync key is not present, it implies Sync, which indicates a 521 // If the NotSync key is not present, it implies Sync, which indicates a
538 // keyframe (at least I think, VT documentation is, erm, sparse). Could 522 // keyframe (at least I think, VT documentation is, erm, sparse). Could
539 // alternatively use kCMSampleAttachmentKey_DependsOnOthers == false. 523 // alternatively use kCMSampleAttachmentKey_DependsOnOthers == false.
540 keyframe = !CFDictionaryContainsKey( 524 keyframe = !CFDictionaryContainsKey(sample_attachments,
541 sample_attachments, 525 kCMSampleAttachmentKey_NotSync);
542 CoreMediaGlue::kCMSampleAttachmentKey_NotSync());
543 has_frame_data = true; 526 has_frame_data = true;
544 } 527 }
545 528
546 // Grab the next frame ID and increment |next_frame_id_| for next time. 529 // Grab the next frame ID and increment |next_frame_id_| for next time.
547 // VideoToolbox calls the output callback serially, so this is safe. 530 // VideoToolbox calls the output callback serially, so this is safe.
548 const FrameId frame_id = encoder->next_frame_id_++; 531 const FrameId frame_id = encoder->next_frame_id_++;
549 532
550 std::unique_ptr<SenderEncodedFrame> encoded_frame(new SenderEncodedFrame()); 533 std::unique_ptr<SenderEncodedFrame> encoded_frame(new SenderEncodedFrame());
551 encoded_frame->frame_id = frame_id; 534 encoded_frame->frame_id = frame_id;
552 encoded_frame->reference_time = request->reference_time; 535 encoded_frame->reference_time = request->reference_time;
(...skipping 26 matching lines...) Expand all
579 encoded_frame->encode_completion_time = 562 encoded_frame->encode_completion_time =
580 encoder->cast_environment_->Clock()->NowTicks(); 563 encoder->cast_environment_->Clock()->NowTicks();
581 encoder->cast_environment_->PostTask( 564 encoder->cast_environment_->PostTask(
582 CastEnvironment::MAIN, FROM_HERE, 565 CastEnvironment::MAIN, FROM_HERE,
583 base::Bind(request->frame_encoded_callback, 566 base::Bind(request->frame_encoded_callback,
584 base::Passed(&encoded_frame))); 567 base::Passed(&encoded_frame)));
585 } 568 }
586 569
587 } // namespace cast 570 } // namespace cast
588 } // namespace media 571 } // namespace media
OLDNEW
« no previous file with comments | « media/cast/sender/h264_vt_encoder.h ('k') | media/cast/sender/h264_vt_encoder_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698