| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright 2015 The WebRTC project authors. All Rights Reserved. | 2 * Copyright 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 27 matching lines...) Expand all Loading... |
| 38 | 38 |
| 39 using webrtc::CodecSpecificInfo; | 39 using webrtc::CodecSpecificInfo; |
| 40 using webrtc::EncodedImage; | 40 using webrtc::EncodedImage; |
| 41 using webrtc::VideoFrame; | 41 using webrtc::VideoFrame; |
| 42 using webrtc::RTPFragmentationHeader; | 42 using webrtc::RTPFragmentationHeader; |
| 43 using webrtc::VideoCodec; | 43 using webrtc::VideoCodec; |
| 44 using webrtc::VideoCodecType; | 44 using webrtc::VideoCodecType; |
| 45 using webrtc::kVideoCodecH264; | 45 using webrtc::kVideoCodecH264; |
| 46 using webrtc::kVideoCodecVP8; | 46 using webrtc::kVideoCodecVP8; |
| 47 using webrtc::kVideoCodecVP9; | 47 using webrtc::kVideoCodecVP9; |
| 48 using webrtc::QualityScaler; |
| 48 | 49 |
| 49 namespace webrtc_jni { | 50 namespace webrtc_jni { |
| 50 | 51 |
| 51 // H.264 start code length. | 52 // H.264 start code length. |
| 52 #define H264_SC_LENGTH 4 | 53 #define H264_SC_LENGTH 4 |
| 53 // Maximum allowed NALUs in one output frame. | 54 // Maximum allowed NALUs in one output frame. |
| 54 #define MAX_NALUS_PERFRAME 32 | 55 #define MAX_NALUS_PERFRAME 32 |
| 55 // Maximum supported HW video encoder resolution. | 56 // Maximum supported HW video encoder resolution. |
| 56 #define MAX_VIDEO_WIDTH 1280 | 57 #define MAX_VIDEO_WIDTH 1280 |
| 57 #define MAX_VIDEO_HEIGHT 1280 | 58 #define MAX_VIDEO_HEIGHT 1280 |
| (...skipping 177 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 235 int32_t output_timestamp_; // Last output frame timestamp from timestamps_ Q. | 236 int32_t output_timestamp_; // Last output frame timestamp from timestamps_ Q. |
| 236 int64_t output_render_time_ms_; // Last output frame render time from | 237 int64_t output_render_time_ms_; // Last output frame render time from |
| 237 // render_times_ms_ queue. | 238 // render_times_ms_ queue. |
| 238 // Frame size in bytes fed to MediaCodec. | 239 // Frame size in bytes fed to MediaCodec. |
| 239 int yuv_size_; | 240 int yuv_size_; |
| 240 // True only when between a callback_->Encoded() call return a positive value | 241 // True only when between a callback_->Encoded() call return a positive value |
| 241 // and the next Encode() call being ignored. | 242 // and the next Encode() call being ignored. |
| 242 bool drop_next_input_frame_; | 243 bool drop_next_input_frame_; |
| 243 // Global references; must be deleted in Release(). | 244 // Global references; must be deleted in Release(). |
| 244 std::vector<jobject> input_buffers_; | 245 std::vector<jobject> input_buffers_; |
| 245 webrtc::QualityScaler quality_scaler_; | 246 QualityScaler quality_scaler_; |
| 246 // Dynamic resolution change, off by default. | 247 // Dynamic resolution change, off by default. |
| 247 bool scale_; | 248 bool scale_; |
| 248 | 249 |
| 249 // H264 bitstream parser, used to extract QP from encoded bitstreams. | 250 // H264 bitstream parser, used to extract QP from encoded bitstreams. |
| 250 webrtc::H264BitstreamParser h264_bitstream_parser_; | 251 webrtc::H264BitstreamParser h264_bitstream_parser_; |
| 251 | 252 |
| 252 // VP9 variables to populate codec specific structure. | 253 // VP9 variables to populate codec specific structure. |
| 253 webrtc::GofInfoVP9 gof_; // Contains each frame's temporal information for | 254 webrtc::GofInfoVP9 gof_; // Contains each frame's temporal information for |
| 254 // non-flexible VP9 mode. | 255 // non-flexible VP9 mode. |
| 255 uint8_t tl0_pic_idx_; | 256 uint8_t tl0_pic_idx_; |
| (...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 348 srand(time(NULL)); | 349 srand(time(NULL)); |
| 349 AllowBlockingCalls(); | 350 AllowBlockingCalls(); |
| 350 } | 351 } |
| 351 | 352 |
| 352 int32_t MediaCodecVideoEncoder::InitEncode( | 353 int32_t MediaCodecVideoEncoder::InitEncode( |
| 353 const webrtc::VideoCodec* codec_settings, | 354 const webrtc::VideoCodec* codec_settings, |
| 354 int32_t /* number_of_cores */, | 355 int32_t /* number_of_cores */, |
| 355 size_t /* max_payload_size */) { | 356 size_t /* max_payload_size */) { |
| 356 const int kMinWidth = 320; | 357 const int kMinWidth = 320; |
| 357 const int kMinHeight = 180; | 358 const int kMinHeight = 180; |
| 358 const int kLowQpThresholdDenominator = 3; | |
| 359 if (codec_settings == NULL) { | 359 if (codec_settings == NULL) { |
| 360 ALOGE << "NULL VideoCodec instance"; | 360 ALOGE << "NULL VideoCodec instance"; |
| 361 return WEBRTC_VIDEO_CODEC_ERR_PARAMETER; | 361 return WEBRTC_VIDEO_CODEC_ERR_PARAMETER; |
| 362 } | 362 } |
| 363 // Factory should guard against other codecs being used with us. | 363 // Factory should guard against other codecs being used with us. |
| 364 RTC_CHECK(codec_settings->codecType == codecType_) | 364 RTC_CHECK(codec_settings->codecType == codecType_) |
| 365 << "Unsupported codec " << codec_settings->codecType << " for " | 365 << "Unsupported codec " << codec_settings->codecType << " for " |
| 366 << codecType_; | 366 << codecType_; |
| 367 | 367 |
| 368 ALOGD << "InitEncode request"; | |
| 369 codec_mode_ = codec_settings->mode; | 368 codec_mode_ = codec_settings->mode; |
| 369 int init_width = codec_settings->width; |
| 370 int init_height = codec_settings->height; |
| 370 scale_ = (codecType_ != kVideoCodecVP9) && (webrtc::field_trial::FindFullName( | 371 scale_ = (codecType_ != kVideoCodecVP9) && (webrtc::field_trial::FindFullName( |
| 371 "WebRTC-MediaCodecVideoEncoder-AutomaticResize") == "Enabled"); | 372 "WebRTC-MediaCodecVideoEncoder-AutomaticResize") == "Enabled"); |
| 373 |
| 374 ALOGD << "InitEncode request: " << init_width << " x " << init_height; |
| 372 ALOGD << "Encoder automatic resize " << (scale_ ? "enabled" : "disabled"); | 375 ALOGD << "Encoder automatic resize " << (scale_ ? "enabled" : "disabled"); |
| 376 |
| 373 if (scale_) { | 377 if (scale_) { |
| 374 if (codecType_ == kVideoCodecVP8) { | 378 if (codecType_ == kVideoCodecVP8) { |
| 375 // QP is obtained from VP8-bitstream for HW, so the QP corresponds to the | 379 // QP is obtained from VP8-bitstream for HW, so the QP corresponds to the |
| 376 // (internal) range: [0, 127]. And we cannot change QP_max in HW, so it is | 380 // (internal) range: [0, 127]. And we cannot change QP_max in HW, so it is |
| 377 // always = 127. Note that in SW, QP is that of the user-level range [0, | 381 // always = 127. Note that in SW, QP is that of the user-level range [0, |
| 378 // 63]. | 382 // 63]. |
| 379 const int kMaxQp = 127; | 383 const int kLowQpThreshold = 32; |
| 380 const int kBadQpThreshold = 95; | 384 const int kBadQpThreshold = 92; |
| 381 quality_scaler_.Init( | 385 quality_scaler_.Init(kLowQpThreshold, kBadQpThreshold, false, |
| 382 kMaxQp / kLowQpThresholdDenominator, kBadQpThreshold, false); | 386 codec_settings->startBitrate, |
| 387 codec_settings->width, codec_settings->height); |
| 383 } else if (codecType_ == kVideoCodecH264) { | 388 } else if (codecType_ == kVideoCodecH264) { |
| 384 // H264 QP is in the range [0, 51]. | 389 // H264 QP is in the range [0, 51]. |
| 385 const int kMaxQp = 51; | 390 const int kLowQpThreshold = 17; |
| 386 const int kBadQpThreshold = 40; | 391 const int kBadQpThreshold = 40; |
| 387 quality_scaler_.Init( | 392 quality_scaler_.Init(kLowQpThreshold, kBadQpThreshold, false, |
| 388 kMaxQp / kLowQpThresholdDenominator, kBadQpThreshold, false); | 393 codec_settings->startBitrate, |
| 394 codec_settings->width, codec_settings->height); |
| 389 } else { | 395 } else { |
| 390 // When adding codec support to additional hardware codecs, also configure | 396 // When adding codec support to additional hardware codecs, also configure |
| 391 // their QP thresholds for scaling. | 397 // their QP thresholds for scaling. |
| 392 RTC_NOTREACHED() << "Unsupported codec without configured QP thresholds."; | 398 RTC_NOTREACHED() << "Unsupported codec without configured QP thresholds."; |
| 399 scale_ = false; |
| 393 } | 400 } |
| 394 quality_scaler_.SetMinResolution(kMinWidth, kMinHeight); | 401 quality_scaler_.SetMinResolution(kMinWidth, kMinHeight); |
| 395 quality_scaler_.ReportFramerate(codec_settings->maxFramerate); | 402 quality_scaler_.ReportFramerate(codec_settings->maxFramerate); |
| 403 QualityScaler::Resolution res = quality_scaler_.GetScaledResolution(); |
| 404 init_width = std::max(res.width, kMinWidth); |
| 405 init_height = std::max(res.height, kMinHeight); |
| 406 ALOGD << "Scaled resolution: " << init_width << " x " << init_height; |
| 396 } | 407 } |
| 408 |
| 397 return codec_thread_->Invoke<int32_t>( | 409 return codec_thread_->Invoke<int32_t>( |
| 398 Bind(&MediaCodecVideoEncoder::InitEncodeOnCodecThread, | 410 Bind(&MediaCodecVideoEncoder::InitEncodeOnCodecThread, |
| 399 this, | 411 this, |
| 400 codec_settings->width, | 412 init_width, |
| 401 codec_settings->height, | 413 init_height, |
| 402 codec_settings->startBitrate, | 414 codec_settings->startBitrate, |
| 403 codec_settings->maxFramerate, | 415 codec_settings->maxFramerate, |
| 404 false /* use_surface */)); | 416 false /* use_surface */)); |
| 405 } | 417 } |
| 406 | 418 |
| 407 int32_t MediaCodecVideoEncoder::Encode( | 419 int32_t MediaCodecVideoEncoder::Encode( |
| 408 const webrtc::VideoFrame& frame, | 420 const webrtc::VideoFrame& frame, |
| 409 const webrtc::CodecSpecificInfo* /* codec_specific_info */, | 421 const webrtc::CodecSpecificInfo* /* codec_specific_info */, |
| 410 const std::vector<webrtc::FrameType>* frame_types) { | 422 const std::vector<webrtc::FrameType>* frame_types) { |
| 411 return codec_thread_->Invoke<int32_t>(Bind( | 423 return codec_thread_->Invoke<int32_t>(Bind( |
| (...skipping 836 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1248 } | 1260 } |
| 1249 | 1261 |
| 1250 void MediaCodecVideoEncoderFactory::DestroyVideoEncoder( | 1262 void MediaCodecVideoEncoderFactory::DestroyVideoEncoder( |
| 1251 webrtc::VideoEncoder* encoder) { | 1263 webrtc::VideoEncoder* encoder) { |
| 1252 ALOGD << "Destroy video encoder."; | 1264 ALOGD << "Destroy video encoder."; |
| 1253 delete encoder; | 1265 delete encoder; |
| 1254 } | 1266 } |
| 1255 | 1267 |
| 1256 } // namespace webrtc_jni | 1268 } // namespace webrtc_jni |
| 1257 | 1269 |
| OLD | NEW |