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

Side by Side Diff: webrtc/sdk/objc/Framework/Classes/h264_video_toolbox_encoder.mm

Issue 2398963003: Move usage of QualityScaler to ViEEncoder. (Closed)
Patch Set: Fix flaky test Created 4 years, 1 month 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
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 232 matching lines...) Expand 10 before | Expand all | Expand 10 after
243 243
244 H264VideoToolboxEncoder::~H264VideoToolboxEncoder() { 244 H264VideoToolboxEncoder::~H264VideoToolboxEncoder() {
245 DestroyCompressionSession(); 245 DestroyCompressionSession();
246 } 246 }
247 247
248 int H264VideoToolboxEncoder::InitEncode(const VideoCodec* codec_settings, 248 int H264VideoToolboxEncoder::InitEncode(const VideoCodec* codec_settings,
249 int number_of_cores, 249 int number_of_cores,
250 size_t max_payload_size) { 250 size_t max_payload_size) {
251 RTC_DCHECK(codec_settings); 251 RTC_DCHECK(codec_settings);
252 RTC_DCHECK_EQ(codec_settings->codecType, kVideoCodecH264); 252 RTC_DCHECK_EQ(codec_settings->codecType, kVideoCodecH264);
253 { 253
254 rtc::CritScope lock(&quality_scaler_crit_); 254 width_ = codec_settings->width;
255 quality_scaler_.Init(internal::kLowH264QpThreshold, 255 height_ = codec_settings->height;
256 internal::kHighH264QpThreshold,
257 codec_settings->startBitrate, codec_settings->width,
258 codec_settings->height, codec_settings->maxFramerate);
259 QualityScaler::Resolution res = quality_scaler_.GetScaledResolution();
260 // TODO(tkchin): We may need to enforce width/height dimension restrictions
261 // to match what the encoder supports.
262 width_ = res.width;
263 height_ = res.height;
264 }
265 // We can only set average bitrate on the HW encoder. 256 // We can only set average bitrate on the HW encoder.
266 target_bitrate_bps_ = codec_settings->startBitrate; 257 target_bitrate_bps_ = codec_settings->startBitrate;
267 bitrate_adjuster_.SetTargetBitrateBps(target_bitrate_bps_); 258 bitrate_adjuster_.SetTargetBitrateBps(target_bitrate_bps_);
268 259
269 // TODO(tkchin): Try setting payload size via 260 // TODO(tkchin): Try setting payload size via
270 // kVTCompressionPropertyKey_MaxH264SliceBytes. 261 // kVTCompressionPropertyKey_MaxH264SliceBytes.
271 262
272 return ResetCompressionSession(); 263 return ResetCompressionSession();
273 } 264 }
274 265
275 int H264VideoToolboxEncoder::Encode( 266 int H264VideoToolboxEncoder::Encode(
276 const VideoFrame& frame, 267 const VideoFrame& frame,
277 const CodecSpecificInfo* codec_specific_info, 268 const CodecSpecificInfo* codec_specific_info,
278 const std::vector<FrameType>* frame_types) { 269 const std::vector<FrameType>* frame_types) {
270 // |input_frame| size should always match codec settings.
271 RTC_DCHECK_EQ(frame.width(), width_);
272 RTC_DCHECK_EQ(frame.height(), height_);
279 RTC_DCHECK(!frame.IsZeroSize()); 273 RTC_DCHECK(!frame.IsZeroSize());
280 if (!callback_ || !compression_session_) { 274 if (!callback_ || !compression_session_) {
281 return WEBRTC_VIDEO_CODEC_UNINITIALIZED; 275 return WEBRTC_VIDEO_CODEC_UNINITIALIZED;
282 } 276 }
283 #if defined(WEBRTC_IOS) 277 #if defined(WEBRTC_IOS)
284 if (!RTCIsUIApplicationActive()) { 278 if (!RTCIsUIApplicationActive()) {
285 // Ignore all encode requests when app isn't active. In this state, the 279 // Ignore all encode requests when app isn't active. In this state, the
286 // hardware encoder has been invalidated by the OS. 280 // hardware encoder has been invalidated by the OS.
287 return WEBRTC_VIDEO_CODEC_OK; 281 return WEBRTC_VIDEO_CODEC_OK;
288 } 282 }
289 #endif 283 #endif
290 bool is_keyframe_required = false; 284 bool is_keyframe_required = false;
291 285
292 quality_scaler_.OnEncodeFrame(frame.width(), frame.height());
293 const QualityScaler::Resolution scaled_res =
294 quality_scaler_.GetScaledResolution();
295
296 if (scaled_res.width != width_ || scaled_res.height != height_) {
297 width_ = scaled_res.width;
298 height_ = scaled_res.height;
299 int ret = ResetCompressionSession();
300 if (ret < 0)
301 return ret;
302 }
303
304 // Get a pixel buffer from the pool and copy frame data over. 286 // Get a pixel buffer from the pool and copy frame data over.
305 CVPixelBufferPoolRef pixel_buffer_pool = 287 CVPixelBufferPoolRef pixel_buffer_pool =
306 VTCompressionSessionGetPixelBufferPool(compression_session_); 288 VTCompressionSessionGetPixelBufferPool(compression_session_);
307 #if defined(WEBRTC_IOS) 289 #if defined(WEBRTC_IOS)
308 if (!pixel_buffer_pool) { 290 if (!pixel_buffer_pool) {
309 // Kind of a hack. On backgrounding, the compression session seems to get 291 // Kind of a hack. On backgrounding, the compression session seems to get
310 // invalidated, which causes this pool call to fail when the application 292 // invalidated, which causes this pool call to fail when the application
311 // is foregrounded and frames are being sent for encoding again. 293 // is foregrounded and frames are being sent for encoding again.
312 // Resetting the session when this happens fixes the issue. 294 // Resetting the session when this happens fixes the issue.
313 // In addition we request a keyframe so video can recover quickly. 295 // In addition we request a keyframe so video can recover quickly.
(...skipping 26 matching lines...) Expand all
340 if (!core_video_frame_buffer->CropAndScaleTo(&nv12_scale_buffer_, 322 if (!core_video_frame_buffer->CropAndScaleTo(&nv12_scale_buffer_,
341 pixel_buffer)) { 323 pixel_buffer)) {
342 return WEBRTC_VIDEO_CODEC_ERROR; 324 return WEBRTC_VIDEO_CODEC_ERROR;
343 } 325 }
344 } 326 }
345 } else { 327 } else {
346 pixel_buffer = internal::CreatePixelBuffer(pixel_buffer_pool); 328 pixel_buffer = internal::CreatePixelBuffer(pixel_buffer_pool);
347 if (!pixel_buffer) { 329 if (!pixel_buffer) {
348 return WEBRTC_VIDEO_CODEC_ERROR; 330 return WEBRTC_VIDEO_CODEC_ERROR;
349 } 331 }
350 // TODO(magjed): Optimize by merging scaling and NV12 pixel buffer 332 RTC_DCHECK(pixel_buffer);
351 // conversion once libyuv::MergeUVPlanes is available. 333 if (!internal::CopyVideoFrameToPixelBuffer(frame.video_frame_buffer(),
352 rtc::scoped_refptr<VideoFrameBuffer> scaled_i420_buffer =
353 quality_scaler_.GetScaledBuffer(frame.video_frame_buffer());
354 if (!internal::CopyVideoFrameToPixelBuffer(scaled_i420_buffer,
355 pixel_buffer)) { 334 pixel_buffer)) {
356 LOG(LS_ERROR) << "Failed to copy frame data."; 335 LOG(LS_ERROR) << "Failed to copy frame data.";
357 CVBufferRelease(pixel_buffer); 336 CVBufferRelease(pixel_buffer);
358 return WEBRTC_VIDEO_CODEC_ERROR; 337 return WEBRTC_VIDEO_CODEC_ERROR;
359 } 338 }
360 } 339 }
361 340
362 // Check if we need a keyframe. 341 // Check if we need a keyframe.
363 if (!is_keyframe_required && frame_types) { 342 if (!is_keyframe_required && frame_types) {
364 for (auto frame_type : *frame_types) { 343 for (auto frame_type : *frame_types) {
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
400 } 379 }
401 return WEBRTC_VIDEO_CODEC_OK; 380 return WEBRTC_VIDEO_CODEC_OK;
402 } 381 }
403 382
404 int H264VideoToolboxEncoder::RegisterEncodeCompleteCallback( 383 int H264VideoToolboxEncoder::RegisterEncodeCompleteCallback(
405 EncodedImageCallback* callback) { 384 EncodedImageCallback* callback) {
406 callback_ = callback; 385 callback_ = callback;
407 return WEBRTC_VIDEO_CODEC_OK; 386 return WEBRTC_VIDEO_CODEC_OK;
408 } 387 }
409 388
410 void H264VideoToolboxEncoder::OnDroppedFrame() {
411 rtc::CritScope lock(&quality_scaler_crit_);
412 quality_scaler_.ReportDroppedFrame();
413 }
414
415 int H264VideoToolboxEncoder::SetChannelParameters(uint32_t packet_loss, 389 int H264VideoToolboxEncoder::SetChannelParameters(uint32_t packet_loss,
416 int64_t rtt) { 390 int64_t rtt) {
417 // Encoder doesn't know anything about packet loss or rtt so just return. 391 // Encoder doesn't know anything about packet loss or rtt so just return.
418 return WEBRTC_VIDEO_CODEC_OK; 392 return WEBRTC_VIDEO_CODEC_OK;
419 } 393 }
420 394
421 int H264VideoToolboxEncoder::SetRates(uint32_t new_bitrate_kbit, 395 int H264VideoToolboxEncoder::SetRates(uint32_t new_bitrate_kbit,
422 uint32_t frame_rate) { 396 uint32_t frame_rate) {
423 target_bitrate_bps_ = 1000 * new_bitrate_kbit; 397 target_bitrate_bps_ = 1000 * new_bitrate_kbit;
424 bitrate_adjuster_.SetTargetBitrateBps(target_bitrate_bps_); 398 bitrate_adjuster_.SetTargetBitrateBps(target_bitrate_bps_);
425 SetBitrateBps(bitrate_adjuster_.GetAdjustedBitrateBps()); 399 SetBitrateBps(bitrate_adjuster_.GetAdjustedBitrateBps());
426
427 rtc::CritScope lock(&quality_scaler_crit_);
428 quality_scaler_.ReportFramerate(frame_rate);
429
430 return WEBRTC_VIDEO_CODEC_OK; 400 return WEBRTC_VIDEO_CODEC_OK;
431 } 401 }
432 402
433 int H264VideoToolboxEncoder::Release() { 403 int H264VideoToolboxEncoder::Release() {
434 // Need to reset so that the session is invalidated and won't use the 404 // Need to reset so that the session is invalidated and won't use the
435 // callback anymore. Do not remove callback until the session is invalidated 405 // callback anymore. Do not remove callback until the session is invalidated
436 // since async encoder callbacks can occur until invalidation. 406 // since async encoder callbacks can occur until invalidation.
437 int ret = ResetCompressionSession(); 407 int ret = ResetCompressionSession();
438 callback_ = nullptr; 408 callback_ = nullptr;
439 return ret; 409 return ret;
(...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after
592 int32_t height, 562 int32_t height,
593 int64_t render_time_ms, 563 int64_t render_time_ms,
594 uint32_t timestamp, 564 uint32_t timestamp,
595 VideoRotation rotation) { 565 VideoRotation rotation) {
596 if (status != noErr) { 566 if (status != noErr) {
597 LOG(LS_ERROR) << "H264 encode failed."; 567 LOG(LS_ERROR) << "H264 encode failed.";
598 return; 568 return;
599 } 569 }
600 if (info_flags & kVTEncodeInfo_FrameDropped) { 570 if (info_flags & kVTEncodeInfo_FrameDropped) {
601 LOG(LS_INFO) << "H264 encode dropped frame."; 571 LOG(LS_INFO) << "H264 encode dropped frame.";
602 rtc::CritScope lock(&quality_scaler_crit_);
603 quality_scaler_.ReportDroppedFrame();
604 return; 572 return;
605 } 573 }
606 574
607 bool is_keyframe = false; 575 bool is_keyframe = false;
608 CFArrayRef attachments = 576 CFArrayRef attachments =
609 CMSampleBufferGetSampleAttachmentsArray(sample_buffer, 0); 577 CMSampleBufferGetSampleAttachmentsArray(sample_buffer, 0);
610 if (attachments != nullptr && CFArrayGetCount(attachments)) { 578 if (attachments != nullptr && CFArrayGetCount(attachments)) {
611 CFDictionaryRef attachment = 579 CFDictionaryRef attachment =
612 static_cast<CFDictionaryRef>(CFArrayGetValueAtIndex(attachments, 0)); 580 static_cast<CFDictionaryRef>(CFArrayGetValueAtIndex(attachments, 0));
613 is_keyframe = 581 is_keyframe =
(...skipping 21 matching lines...) Expand all
635 frame._encodedWidth = width; 603 frame._encodedWidth = width;
636 frame._encodedHeight = height; 604 frame._encodedHeight = height;
637 frame._completeFrame = true; 605 frame._completeFrame = true;
638 frame._frameType = 606 frame._frameType =
639 is_keyframe ? webrtc::kVideoFrameKey : webrtc::kVideoFrameDelta; 607 is_keyframe ? webrtc::kVideoFrameKey : webrtc::kVideoFrameDelta;
640 frame.capture_time_ms_ = render_time_ms; 608 frame.capture_time_ms_ = render_time_ms;
641 frame._timeStamp = timestamp; 609 frame._timeStamp = timestamp;
642 frame.rotation_ = rotation; 610 frame.rotation_ = rotation;
643 611
644 h264_bitstream_parser_.ParseBitstream(buffer->data(), buffer->size()); 612 h264_bitstream_parser_.ParseBitstream(buffer->data(), buffer->size());
645 int qp; 613 h264_bitstream_parser_.GetLastSliceQp(&frame.qp_);
646 if (h264_bitstream_parser_.GetLastSliceQp(&qp)) {
647 rtc::CritScope lock(&quality_scaler_crit_);
648 quality_scaler_.ReportQP(qp);
649 }
650 614
651 EncodedImageCallback::Result result = 615 EncodedImageCallback::Result res =
652 callback_->OnEncodedImage(frame, &codec_specific_info, header.get()); 616 callback_->OnEncodedImage(frame, &codec_specific_info, header.get());
653 if (result.error != EncodedImageCallback::Result::OK) { 617 if (res.error != EncodedImageCallback::Result::OK) {
654 LOG(LS_ERROR) << "Encode callback failed: " << result.error; 618 LOG(LS_ERROR) << "Encode callback failed: " << res.error;
655 return; 619 return;
656 } 620 }
657 bitrate_adjuster_.Update(frame._size); 621 bitrate_adjuster_.Update(frame._size);
658 } 622 }
659 623
624 QualityScaler::Settings H264VideoToolboxEncoder::GetQPThresholds() const {
625 return QualityScaler::Settings(true, internal::kLowH264QpThreshold,
626 internal::kHighH264QpThreshold);
627 }
660 } // namespace webrtc 628 } // namespace webrtc
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698