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

Side by Side Diff: webrtc/modules/video_coding/codecs/h264/h264_video_toolbox_encoder.cc

Issue 2001153003: Integrate QualityScaler into VideoToolboxEncoder. (Closed) Base URL: https://chromium.googlesource.com/external/webrtc.git@master
Patch Set: Created 4 years, 7 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 | « webrtc/modules/video_coding/codecs/h264/h264_video_toolbox_encoder.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved. 2 * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved.
3 * 3 *
4 * Use of this source code is governed by a BSD-style license 4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source 5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found 6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may 7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree. 8 * be found in the AUTHORS file in the root of the source tree.
9 * 9 *
10 */ 10 */
(...skipping 207 matching lines...) Expand 10 before | Expand all | Expand 10 after
218 218
219 H264VideoToolboxEncoder::~H264VideoToolboxEncoder() { 219 H264VideoToolboxEncoder::~H264VideoToolboxEncoder() {
220 DestroyCompressionSession(); 220 DestroyCompressionSession();
221 } 221 }
222 222
223 int H264VideoToolboxEncoder::InitEncode(const VideoCodec* codec_settings, 223 int H264VideoToolboxEncoder::InitEncode(const VideoCodec* codec_settings,
224 int number_of_cores, 224 int number_of_cores,
225 size_t max_payload_size) { 225 size_t max_payload_size) {
226 RTC_DCHECK(codec_settings); 226 RTC_DCHECK(codec_settings);
227 RTC_DCHECK_EQ(codec_settings->codecType, kVideoCodecH264); 227 RTC_DCHECK_EQ(codec_settings->codecType, kVideoCodecH264);
228 // TODO(tkchin): We may need to enforce width/height dimension restrictions 228 {
229 // to match what the encoder supports. 229 rtc::CritScope lock(&quality_scaler_crit_);
230 width_ = codec_settings->width; 230 quality_scaler_.Init(QualityScaler::kLowH264QpThreshold,
231 height_ = codec_settings->height; 231 QualityScaler::kBadH264QpThreshold,
232 codec_settings->startBitrate, codec_settings->width,
233 codec_settings->height, codec_settings->maxFramerate);
234 QualityScaler::Resolution res = quality_scaler_.GetScaledResolution();
235 // TODO(tkchin): We may need to enforce width/height dimension restrictions
236 // to match what the encoder supports.
237 width_ = res.width;
238 height_ = res.height;
239 }
232 // We can only set average bitrate on the HW encoder. 240 // We can only set average bitrate on the HW encoder.
233 target_bitrate_bps_ = codec_settings->startBitrate; 241 target_bitrate_bps_ = codec_settings->startBitrate;
234 bitrate_adjuster_.SetTargetBitrateBps(target_bitrate_bps_); 242 bitrate_adjuster_.SetTargetBitrateBps(target_bitrate_bps_);
235 243
236 // TODO(tkchin): Try setting payload size via 244 // TODO(tkchin): Try setting payload size via
237 // kVTCompressionPropertyKey_MaxH264SliceBytes. 245 // kVTCompressionPropertyKey_MaxH264SliceBytes.
238 246
239 return ResetCompressionSession(); 247 return ResetCompressionSession();
240 } 248 }
241 249
250 const VideoFrame& H264VideoToolboxEncoder::GetScaledFrameOnEncode(
251 const VideoFrame& frame) {
252 rtc::CritScope lock(&quality_scaler_crit_);
253 quality_scaler_.OnEncodeFrame(frame);
254 return quality_scaler_.GetScaledFrame(frame);
255 }
256
242 int H264VideoToolboxEncoder::Encode( 257 int H264VideoToolboxEncoder::Encode(
243 const VideoFrame& input_image, 258 const VideoFrame& frame,
244 const CodecSpecificInfo* codec_specific_info, 259 const CodecSpecificInfo* codec_specific_info,
245 const std::vector<FrameType>* frame_types) { 260 const std::vector<FrameType>* frame_types) {
246 if (input_image.IsZeroSize()) { 261 RTC_DCHECK(frame.IsZeroSize());
tkchin_webrtc 2016/05/23 21:26:56 why are frames expected to be zero size?
pbos-webrtc 2016/05/23 21:36:25 Why indeed? :| Inverted it.
247 // It's possible to get zero sizes as a signal to produce keyframes (this
248 // happens for internal sources). But this shouldn't happen in
249 // webrtcvideoengine2.
250 RTC_NOTREACHED();
251 return WEBRTC_VIDEO_CODEC_OK;
252 }
253 if (!callback_ || !compression_session_) { 262 if (!callback_ || !compression_session_) {
254 return WEBRTC_VIDEO_CODEC_UNINITIALIZED; 263 return WEBRTC_VIDEO_CODEC_UNINITIALIZED;
255 } 264 }
256 #if defined(WEBRTC_IOS) 265 #if defined(WEBRTC_IOS)
257 if (!RTCIsUIApplicationActive()) { 266 if (!RTCIsUIApplicationActive()) {
258 // Ignore all encode requests when app isn't active. In this state, the 267 // Ignore all encode requests when app isn't active. In this state, the
259 // hardware encoder has been invalidated by the OS. 268 // hardware encoder has been invalidated by the OS.
260 return WEBRTC_VIDEO_CODEC_OK; 269 return WEBRTC_VIDEO_CODEC_OK;
261 } 270 }
262 #endif 271 #endif
263 bool is_keyframe_required = false; 272 bool is_keyframe_required = false;
273 const VideoFrame& input_image = GetScaledFrameOnEncode(frame);
274
275 if (input_image.width() != width_ || input_image.height() != height_) {
276 width_ = input_image.width();
277 height_ = input_image.height();
278 int ret = ResetCompressionSession();
279 if (ret < 0)
280 return ret;
281 }
282
264 // Get a pixel buffer from the pool and copy frame data over. 283 // Get a pixel buffer from the pool and copy frame data over.
265 CVPixelBufferPoolRef pixel_buffer_pool = 284 CVPixelBufferPoolRef pixel_buffer_pool =
266 VTCompressionSessionGetPixelBufferPool(compression_session_); 285 VTCompressionSessionGetPixelBufferPool(compression_session_);
267 #if defined(WEBRTC_IOS) 286 #if defined(WEBRTC_IOS)
268 if (!pixel_buffer_pool) { 287 if (!pixel_buffer_pool) {
269 // Kind of a hack. On backgrounding, the compression session seems to get 288 // Kind of a hack. On backgrounding, the compression session seems to get
270 // invalidated, which causes this pool call to fail when the application 289 // invalidated, which causes this pool call to fail when the application
271 // is foregrounded and frames are being sent for encoding again. 290 // is foregrounded and frames are being sent for encoding again.
272 // Resetting the session when this happens fixes the issue. 291 // Resetting the session when this happens fixes the issue.
273 // In addition we request a keyframe so video can recover quickly. 292 // In addition we request a keyframe so video can recover quickly.
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
338 } 357 }
339 return WEBRTC_VIDEO_CODEC_OK; 358 return WEBRTC_VIDEO_CODEC_OK;
340 } 359 }
341 360
342 int H264VideoToolboxEncoder::RegisterEncodeCompleteCallback( 361 int H264VideoToolboxEncoder::RegisterEncodeCompleteCallback(
343 EncodedImageCallback* callback) { 362 EncodedImageCallback* callback) {
344 callback_ = callback; 363 callback_ = callback;
345 return WEBRTC_VIDEO_CODEC_OK; 364 return WEBRTC_VIDEO_CODEC_OK;
346 } 365 }
347 366
367 void H264VideoToolboxEncoder::OnDroppedFrame() {
368 rtc::CritScope lock(&quality_scaler_crit_);
369 quality_scaler_.ReportDroppedFrame();
370 }
371
348 int H264VideoToolboxEncoder::SetChannelParameters(uint32_t packet_loss, 372 int H264VideoToolboxEncoder::SetChannelParameters(uint32_t packet_loss,
349 int64_t rtt) { 373 int64_t rtt) {
350 // Encoder doesn't know anything about packet loss or rtt so just return. 374 // Encoder doesn't know anything about packet loss or rtt so just return.
351 return WEBRTC_VIDEO_CODEC_OK; 375 return WEBRTC_VIDEO_CODEC_OK;
352 } 376 }
353 377
354 int H264VideoToolboxEncoder::SetRates(uint32_t new_bitrate_kbit, 378 int H264VideoToolboxEncoder::SetRates(uint32_t new_bitrate_kbit,
355 uint32_t frame_rate) { 379 uint32_t frame_rate) {
356 target_bitrate_bps_ = 1000 * new_bitrate_kbit; 380 target_bitrate_bps_ = 1000 * new_bitrate_kbit;
357 bitrate_adjuster_.SetTargetBitrateBps(target_bitrate_bps_); 381 bitrate_adjuster_.SetTargetBitrateBps(target_bitrate_bps_);
358 SetBitrateBps(bitrate_adjuster_.GetAdjustedBitrateBps()); 382 SetBitrateBps(bitrate_adjuster_.GetAdjustedBitrateBps());
359 383
384 rtc::CritScope lock(&quality_scaler_crit_);
385 quality_scaler_.ReportFramerate(frame_rate);
386
360 return WEBRTC_VIDEO_CODEC_OK; 387 return WEBRTC_VIDEO_CODEC_OK;
361 } 388 }
362 389
363 int H264VideoToolboxEncoder::Release() { 390 int H264VideoToolboxEncoder::Release() {
364 // Need to reset so that the session is invalidated and won't use the 391 // Need to reset so that the session is invalidated and won't use the
365 // callback anymore. Do not remove callback until the session is invalidated 392 // callback anymore. Do not remove callback until the session is invalidated
366 // since async encoder callbacks can occur until invalidation. 393 // since async encoder callbacks can occur until invalidation.
367 int ret = ResetCompressionSession(); 394 int ret = ResetCompressionSession();
368 callback_ = nullptr; 395 callback_ = nullptr;
369 return ret; 396 return ret;
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after
484 int32_t height, 511 int32_t height,
485 int64_t render_time_ms, 512 int64_t render_time_ms,
486 uint32_t timestamp, 513 uint32_t timestamp,
487 VideoRotation rotation) { 514 VideoRotation rotation) {
488 if (status != noErr) { 515 if (status != noErr) {
489 LOG(LS_ERROR) << "H264 encode failed."; 516 LOG(LS_ERROR) << "H264 encode failed.";
490 return; 517 return;
491 } 518 }
492 if (info_flags & kVTEncodeInfo_FrameDropped) { 519 if (info_flags & kVTEncodeInfo_FrameDropped) {
493 LOG(LS_INFO) << "H264 encode dropped frame."; 520 LOG(LS_INFO) << "H264 encode dropped frame.";
521 rtc::CritScope lock(&quality_scaler_crit_);
522 quality_scaler_.ReportDroppedFrame();
523 return;
494 } 524 }
495 525
496 bool is_keyframe = false; 526 bool is_keyframe = false;
497 CFArrayRef attachments = 527 CFArrayRef attachments =
498 CMSampleBufferGetSampleAttachmentsArray(sample_buffer, 0); 528 CMSampleBufferGetSampleAttachmentsArray(sample_buffer, 0);
499 if (attachments != nullptr && CFArrayGetCount(attachments)) { 529 if (attachments != nullptr && CFArrayGetCount(attachments)) {
500 CFDictionaryRef attachment = 530 CFDictionaryRef attachment =
501 static_cast<CFDictionaryRef>(CFArrayGetValueAtIndex(attachments, 0)); 531 static_cast<CFDictionaryRef>(CFArrayGetValueAtIndex(attachments, 0));
502 is_keyframe = 532 is_keyframe =
503 !CFDictionaryContainsKey(attachment, kCMSampleAttachmentKey_NotSync); 533 !CFDictionaryContainsKey(attachment, kCMSampleAttachmentKey_NotSync);
(...skipping 15 matching lines...) Expand all
519 webrtc::EncodedImage frame(buffer->data(), buffer->size(), buffer->size()); 549 webrtc::EncodedImage frame(buffer->data(), buffer->size(), buffer->size());
520 frame._encodedWidth = width; 550 frame._encodedWidth = width;
521 frame._encodedHeight = height; 551 frame._encodedHeight = height;
522 frame._completeFrame = true; 552 frame._completeFrame = true;
523 frame._frameType = 553 frame._frameType =
524 is_keyframe ? webrtc::kVideoFrameKey : webrtc::kVideoFrameDelta; 554 is_keyframe ? webrtc::kVideoFrameKey : webrtc::kVideoFrameDelta;
525 frame.capture_time_ms_ = render_time_ms; 555 frame.capture_time_ms_ = render_time_ms;
526 frame._timeStamp = timestamp; 556 frame._timeStamp = timestamp;
527 frame.rotation_ = rotation; 557 frame.rotation_ = rotation;
528 558
559 h264_bitstream_parser_.ParseBitstream(buffer->data(), buffer->size());
560 int qp;
561 if (h264_bitstream_parser_.GetLastSliceQp(&qp)) {
562 rtc::CritScope lock(&quality_scaler_crit_);
563 quality_scaler_.ReportQP(qp);
564 }
565
529 int result = callback_->Encoded(frame, &codec_specific_info, header.get()); 566 int result = callback_->Encoded(frame, &codec_specific_info, header.get());
530 if (result != 0) { 567 if (result != 0) {
531 LOG(LS_ERROR) << "Encode callback failed: " << result; 568 LOG(LS_ERROR) << "Encode callback failed: " << result;
532 return; 569 return;
533 } 570 }
534 bitrate_adjuster_.Update(frame._size); 571 bitrate_adjuster_.Update(frame._size);
535 } 572 }
536 573
537 } // namespace webrtc 574 } // namespace webrtc
538 575
539 #endif // defined(WEBRTC_VIDEO_TOOLBOX_SUPPORTED) 576 #endif // defined(WEBRTC_VIDEO_TOOLBOX_SUPPORTED)
OLDNEW
« no previous file with comments | « webrtc/modules/video_coding/codecs/h264/h264_video_toolbox_encoder.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698