OLD | NEW |
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 */ |
11 | 11 |
12 #include "webrtc/modules/video_coding/codecs/h264/h264_video_toolbox_encoder.h" | 12 #include "webrtc/modules/video_coding/codecs/h264/h264_video_toolbox_encoder.h" |
13 | 13 |
14 #if defined(WEBRTC_VIDEO_TOOLBOX_SUPPORTED) | 14 #if defined(WEBRTC_VIDEO_TOOLBOX_SUPPORTED) |
15 | 15 |
16 #include <memory> | 16 #include <memory> |
17 #include <string> | 17 #include <string> |
18 #include <vector> | 18 #include <vector> |
19 | 19 |
20 #if defined(WEBRTC_IOS) | 20 #if defined(WEBRTC_IOS) |
| 21 #import "WebRTC/UIDevice+RTCDevice.h" |
21 #include "RTCUIApplication.h" | 22 #include "RTCUIApplication.h" |
22 #endif | 23 #endif |
23 #include "libyuv/convert_from.h" | 24 #include "libyuv/convert_from.h" |
24 #include "webrtc/base/checks.h" | 25 #include "webrtc/base/checks.h" |
25 #include "webrtc/base/logging.h" | 26 #include "webrtc/base/logging.h" |
26 #include "webrtc/modules/video_coding/codecs/h264/h264_video_toolbox_nalu.h" | 27 #include "webrtc/modules/video_coding/codecs/h264/h264_video_toolbox_nalu.h" |
27 #include "webrtc/system_wrappers/include/clock.h" | 28 #include "webrtc/system_wrappers/include/clock.h" |
28 | 29 |
29 namespace internal { | 30 namespace internal { |
30 | 31 |
(...skipping 179 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
210 // .5 is set as a mininum to prevent overcompensating for large temporary | 211 // .5 is set as a mininum to prevent overcompensating for large temporary |
211 // overshoots. We don't want to degrade video quality too badly. | 212 // overshoots. We don't want to degrade video quality too badly. |
212 // .95 is set to prevent oscillations. When a lower bitrate is set on the | 213 // .95 is set to prevent oscillations. When a lower bitrate is set on the |
213 // encoder than previously set, its output seems to have a brief period of | 214 // encoder than previously set, its output seems to have a brief period of |
214 // drastically reduced bitrate, so we want to avoid that. In steady state | 215 // drastically reduced bitrate, so we want to avoid that. In steady state |
215 // conditions, 0.95 seems to give us better overall bitrate over long periods | 216 // conditions, 0.95 seems to give us better overall bitrate over long periods |
216 // of time. | 217 // of time. |
217 H264VideoToolboxEncoder::H264VideoToolboxEncoder() | 218 H264VideoToolboxEncoder::H264VideoToolboxEncoder() |
218 : callback_(nullptr), | 219 : callback_(nullptr), |
219 compression_session_(nullptr), | 220 compression_session_(nullptr), |
220 bitrate_adjuster_(Clock::GetRealTimeClock(), .5, .95) {} | 221 bitrate_adjuster_(Clock::GetRealTimeClock(), .5, .95), |
| 222 enable_scaling_(true) { |
| 223 #if defined(WEBRTC_IOS) |
| 224 if ([UIDevice deviceType] == RTCDeviceTypeIPhone4S) { |
| 225 enable_scaling_ = false; |
| 226 } |
| 227 #endif |
| 228 } |
221 | 229 |
222 H264VideoToolboxEncoder::~H264VideoToolboxEncoder() { | 230 H264VideoToolboxEncoder::~H264VideoToolboxEncoder() { |
223 DestroyCompressionSession(); | 231 DestroyCompressionSession(); |
224 } | 232 } |
225 | 233 |
226 int H264VideoToolboxEncoder::InitEncode(const VideoCodec* codec_settings, | 234 int H264VideoToolboxEncoder::InitEncode(const VideoCodec* codec_settings, |
227 int number_of_cores, | 235 int number_of_cores, |
228 size_t max_payload_size) { | 236 size_t max_payload_size) { |
229 RTC_DCHECK(codec_settings); | 237 RTC_DCHECK(codec_settings); |
230 RTC_DCHECK_EQ(codec_settings->codecType, kVideoCodecH264); | 238 RTC_DCHECK_EQ(codec_settings->codecType, kVideoCodecH264); |
| 239 width_ = codec_settings->width; |
| 240 height_ = codec_settings->height; |
231 { | 241 { |
232 rtc::CritScope lock(&quality_scaler_crit_); | 242 rtc::CritScope lock(&quality_scaler_crit_); |
233 quality_scaler_.Init(QualityScaler::kLowH264QpThreshold, | 243 quality_scaler_.Init(QualityScaler::kLowH264QpThreshold, |
234 QualityScaler::kBadH264QpThreshold, | 244 QualityScaler::kBadH264QpThreshold, |
235 codec_settings->startBitrate, codec_settings->width, | 245 codec_settings->startBitrate, codec_settings->width, |
236 codec_settings->height, codec_settings->maxFramerate); | 246 codec_settings->height, codec_settings->maxFramerate); |
237 QualityScaler::Resolution res = quality_scaler_.GetScaledResolution(); | 247 QualityScaler::Resolution res = quality_scaler_.GetScaledResolution(); |
238 // TODO(tkchin): We may need to enforce width/height dimension restrictions | 248 // TODO(tkchin): We may need to enforce width/height dimension restrictions |
239 // to match what the encoder supports. | 249 // to match what the encoder supports. |
240 width_ = res.width; | 250 if (enable_scaling_) { |
241 height_ = res.height; | 251 width_ = res.width; |
| 252 height_ = res.height; |
| 253 } |
242 } | 254 } |
243 // We can only set average bitrate on the HW encoder. | 255 // We can only set average bitrate on the HW encoder. |
244 target_bitrate_bps_ = codec_settings->startBitrate; | 256 target_bitrate_bps_ = codec_settings->startBitrate; |
245 bitrate_adjuster_.SetTargetBitrateBps(target_bitrate_bps_); | 257 bitrate_adjuster_.SetTargetBitrateBps(target_bitrate_bps_); |
246 | 258 |
247 // TODO(tkchin): Try setting payload size via | 259 // TODO(tkchin): Try setting payload size via |
248 // kVTCompressionPropertyKey_MaxH264SliceBytes. | 260 // kVTCompressionPropertyKey_MaxH264SliceBytes. |
249 | 261 |
250 return ResetCompressionSession(); | 262 return ResetCompressionSession(); |
251 } | 263 } |
252 | 264 |
253 rtc::scoped_refptr<VideoFrameBuffer> | 265 rtc::scoped_refptr<VideoFrameBuffer> |
254 H264VideoToolboxEncoder::GetScaledBufferOnEncode( | 266 H264VideoToolboxEncoder::GetScaledBufferOnEncode( |
255 const rtc::scoped_refptr<VideoFrameBuffer>& frame) { | 267 const rtc::scoped_refptr<VideoFrameBuffer>& frame) { |
256 rtc::CritScope lock(&quality_scaler_crit_); | 268 rtc::CritScope lock(&quality_scaler_crit_); |
257 quality_scaler_.OnEncodeFrame(frame->width(), frame->height()); | 269 quality_scaler_.OnEncodeFrame(frame->width(), frame->height()); |
258 if (!frame->native_handle()) | 270 if (!frame->native_handle()) |
259 return quality_scaler_.GetScaledBuffer(frame); | 271 return quality_scaler_.GetScaledBuffer(frame); |
260 | 272 |
261 // Handle native (CVImageRef) scaling. | 273 // Handle native (CVImageRef) scaling. |
262 const QualityScaler::Resolution res = quality_scaler_.GetScaledResolution(); | 274 const QualityScaler::Resolution res = quality_scaler_.GetScaledResolution(); |
263 if (res.width == frame->width() && res.height == frame->height()) | 275 if (!enable_scaling_ || |
| 276 (res.width == frame->width() && res.height == frame->height())) |
264 return frame; | 277 return frame; |
265 // TODO(magjed): Implement efficient CVImageRef -> CVImageRef scaling instead | 278 // TODO(magjed): Implement efficient CVImageRef -> CVImageRef scaling instead |
266 // of doing it via I420. | 279 // of doing it via I420. |
267 return quality_scaler_.GetScaledBuffer(frame->NativeToI420Buffer()); | 280 return quality_scaler_.GetScaledBuffer(frame->NativeToI420Buffer()); |
268 } | 281 } |
269 | 282 |
270 int H264VideoToolboxEncoder::Encode( | 283 int H264VideoToolboxEncoder::Encode( |
271 const VideoFrame& frame, | 284 const VideoFrame& frame, |
272 const CodecSpecificInfo* codec_specific_info, | 285 const CodecSpecificInfo* codec_specific_info, |
273 const std::vector<FrameType>* frame_types) { | 286 const std::vector<FrameType>* frame_types) { |
(...skipping 354 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
628 if (result != 0) { | 641 if (result != 0) { |
629 LOG(LS_ERROR) << "Encode callback failed: " << result; | 642 LOG(LS_ERROR) << "Encode callback failed: " << result; |
630 return; | 643 return; |
631 } | 644 } |
632 bitrate_adjuster_.Update(frame._size); | 645 bitrate_adjuster_.Update(frame._size); |
633 } | 646 } |
634 | 647 |
635 } // namespace webrtc | 648 } // namespace webrtc |
636 | 649 |
637 #endif // defined(WEBRTC_VIDEO_TOOLBOX_SUPPORTED) | 650 #endif // defined(WEBRTC_VIDEO_TOOLBOX_SUPPORTED) |
OLD | NEW |