Chromium Code Reviews| 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 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 79 #endif | 79 #endif |
| 80 #define ALOGD LOG_TAG(rtc::LS_INFO, TAG_ENCODER) | 80 #define ALOGD LOG_TAG(rtc::LS_INFO, TAG_ENCODER) |
| 81 #define ALOGW LOG_TAG(rtc::LS_WARNING, TAG_ENCODER) | 81 #define ALOGW LOG_TAG(rtc::LS_WARNING, TAG_ENCODER) |
| 82 #define ALOGE LOG_TAG(rtc::LS_ERROR, TAG_ENCODER) | 82 #define ALOGE LOG_TAG(rtc::LS_ERROR, TAG_ENCODER) |
| 83 | 83 |
| 84 namespace { | 84 namespace { |
| 85 // Maximum time limit between incoming frames before requesting a key frame. | 85 // Maximum time limit between incoming frames before requesting a key frame. |
| 86 const size_t kFrameDiffThresholdMs = 350; | 86 const size_t kFrameDiffThresholdMs = 350; |
| 87 const int kMinKeyFrameInterval = 6; | 87 const int kMinKeyFrameInterval = 6; |
| 88 const char kH264HighProfileFieldTrial[] = "WebRTC-H264HighProfile"; | 88 const char kH264HighProfileFieldTrial[] = "WebRTC-H264HighProfile"; |
| 89 const char kCustomQPThresholdsFieldTrial[] = "WebRTC-CustomQPThresholds"; | |
| 89 } // namespace | 90 } // namespace |
| 90 | 91 |
| 91 // MediaCodecVideoEncoder is a webrtc::VideoEncoder implementation that uses | 92 // MediaCodecVideoEncoder is a webrtc::VideoEncoder implementation that uses |
| 92 // Android's MediaCodec SDK API behind the scenes to implement (hopefully) | 93 // Android's MediaCodec SDK API behind the scenes to implement (hopefully) |
| 93 // HW-backed video encode. This C++ class is implemented as a very thin shim, | 94 // HW-backed video encode. This C++ class is implemented as a very thin shim, |
| 94 // delegating all of the interesting work to org.webrtc.MediaCodecVideoEncoder. | 95 // delegating all of the interesting work to org.webrtc.MediaCodecVideoEncoder. |
| 95 // MediaCodecVideoEncoder must be operated on a single task queue, currently | 96 // MediaCodecVideoEncoder must be operated on a single task queue, currently |
| 96 // this is the encoder queue from ViE encoder. | 97 // this is the encoder queue from ViE encoder. |
| 97 class MediaCodecVideoEncoder : public webrtc::VideoEncoder { | 98 class MediaCodecVideoEncoder : public webrtc::VideoEncoder { |
| 98 public: | 99 public: |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 173 | 174 |
| 174 // Deliver any outputs pending in the MediaCodec to our |callback_| and return | 175 // Deliver any outputs pending in the MediaCodec to our |callback_| and return |
| 175 // true on success. | 176 // true on success. |
| 176 bool DeliverPendingOutputs(JNIEnv* jni); | 177 bool DeliverPendingOutputs(JNIEnv* jni); |
| 177 | 178 |
| 178 VideoEncoder::ScalingSettings GetScalingSettings() const override; | 179 VideoEncoder::ScalingSettings GetScalingSettings() const override; |
| 179 | 180 |
| 180 // Displays encoder statistics. | 181 // Displays encoder statistics. |
| 181 void LogStatistics(bool force_log); | 182 void LogStatistics(bool force_log); |
| 182 | 183 |
| 184 VideoCodecType GetCodecType() const; | |
|
kthelgason
2017/03/22 07:38:58
Thanks for cleaning this up!
| |
| 185 | |
| 183 #if RTC_DCHECK_IS_ON | 186 #if RTC_DCHECK_IS_ON |
| 184 // Mutex for protecting inited_. It is only used for correctness checking on | 187 // Mutex for protecting inited_. It is only used for correctness checking on |
| 185 // debug build. It is used for checking that encoder has been released in the | 188 // debug build. It is used for checking that encoder has been released in the |
| 186 // destructor. Because this might happen on a different thread, we need a | 189 // destructor. Because this might happen on a different thread, we need a |
| 187 // mutex. | 190 // mutex. |
| 188 rtc::CriticalSection inited_crit_; | 191 rtc::CriticalSection inited_crit_; |
| 189 #endif | 192 #endif |
| 190 | 193 |
| 191 // Type of video codec. | 194 // Type of video codec. |
| 192 const cricket::VideoCodec codec_; | 195 const cricket::VideoCodec codec_; |
| (...skipping 184 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 377 int32_t MediaCodecVideoEncoder::InitEncode( | 380 int32_t MediaCodecVideoEncoder::InitEncode( |
| 378 const webrtc::VideoCodec* codec_settings, | 381 const webrtc::VideoCodec* codec_settings, |
| 379 int32_t /* number_of_cores */, | 382 int32_t /* number_of_cores */, |
| 380 size_t /* max_payload_size */) { | 383 size_t /* max_payload_size */) { |
| 381 RTC_DCHECK_CALLED_SEQUENTIALLY(&encoder_queue_checker_); | 384 RTC_DCHECK_CALLED_SEQUENTIALLY(&encoder_queue_checker_); |
| 382 if (codec_settings == NULL) { | 385 if (codec_settings == NULL) { |
| 383 ALOGE << "NULL VideoCodec instance"; | 386 ALOGE << "NULL VideoCodec instance"; |
| 384 return WEBRTC_VIDEO_CODEC_ERR_PARAMETER; | 387 return WEBRTC_VIDEO_CODEC_ERR_PARAMETER; |
| 385 } | 388 } |
| 386 // Factory should guard against other codecs being used with us. | 389 // Factory should guard against other codecs being used with us. |
| 387 const VideoCodecType codec_type = webrtc::PayloadNameToCodecType(codec_.name) | 390 const VideoCodecType codec_type = GetCodecType(); |
| 388 .value_or(webrtc::kVideoCodecUnknown); | |
| 389 RTC_CHECK(codec_settings->codecType == codec_type) | 391 RTC_CHECK(codec_settings->codecType == codec_type) |
| 390 << "Unsupported codec " << codec_settings->codecType << " for " | 392 << "Unsupported codec " << codec_settings->codecType << " for " |
| 391 << codec_type; | 393 << codec_type; |
| 392 if (sw_fallback_required_) { | 394 if (sw_fallback_required_) { |
| 393 return WEBRTC_VIDEO_CODEC_OK; | 395 return WEBRTC_VIDEO_CODEC_OK; |
| 394 } | 396 } |
| 395 codec_mode_ = codec_settings->mode; | 397 codec_mode_ = codec_settings->mode; |
| 396 int init_width = codec_settings->width; | 398 int init_width = codec_settings->width; |
| 397 int init_height = codec_settings->height; | 399 int init_height = codec_settings->height; |
| 398 // Scaling is disabled for VP9, but optionally enabled for VP8. | 400 // Scaling is disabled for VP9, but optionally enabled for VP8. |
| (...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 491 } | 493 } |
| 492 return false; | 494 return false; |
| 493 } | 495 } |
| 494 | 496 |
| 495 int32_t MediaCodecVideoEncoder::ProcessHWErrorOnEncode() { | 497 int32_t MediaCodecVideoEncoder::ProcessHWErrorOnEncode() { |
| 496 ProcessHWError(true /* reset_if_fallback_unavailable */); | 498 ProcessHWError(true /* reset_if_fallback_unavailable */); |
| 497 return sw_fallback_required_ ? WEBRTC_VIDEO_CODEC_FALLBACK_SOFTWARE | 499 return sw_fallback_required_ ? WEBRTC_VIDEO_CODEC_FALLBACK_SOFTWARE |
| 498 : WEBRTC_VIDEO_CODEC_ERROR; | 500 : WEBRTC_VIDEO_CODEC_ERROR; |
| 499 } | 501 } |
| 500 | 502 |
| 503 VideoCodecType MediaCodecVideoEncoder::GetCodecType() const { | |
| 504 return webrtc::PayloadNameToCodecType(codec_.name) | |
| 505 .value_or(webrtc::kVideoCodecUnknown); | |
| 506 } | |
| 507 | |
| 501 int32_t MediaCodecVideoEncoder::InitEncodeInternal(int width, | 508 int32_t MediaCodecVideoEncoder::InitEncodeInternal(int width, |
| 502 int height, | 509 int height, |
| 503 int kbps, | 510 int kbps, |
| 504 int fps, | 511 int fps, |
| 505 bool use_surface) { | 512 bool use_surface) { |
| 506 RTC_DCHECK_CALLED_SEQUENTIALLY(&encoder_queue_checker_); | 513 RTC_DCHECK_CALLED_SEQUENTIALLY(&encoder_queue_checker_); |
| 507 if (sw_fallback_required_) { | 514 if (sw_fallback_required_) { |
| 508 return WEBRTC_VIDEO_CODEC_OK; | 515 return WEBRTC_VIDEO_CODEC_OK; |
| 509 } | 516 } |
| 510 RTC_CHECK(!use_surface || egl_context_ != nullptr) << "EGL context not set."; | 517 RTC_CHECK(!use_surface || egl_context_ != nullptr) << "EGL context not set."; |
| 511 JNIEnv* jni = AttachCurrentThreadIfNeeded(); | 518 JNIEnv* jni = AttachCurrentThreadIfNeeded(); |
| 512 ScopedLocalRefFrame local_ref_frame(jni); | 519 ScopedLocalRefFrame local_ref_frame(jni); |
| 513 | 520 |
| 514 const VideoCodecType codec_type = webrtc::PayloadNameToCodecType(codec_.name) | 521 const VideoCodecType codec_type = GetCodecType(); |
| 515 .value_or(webrtc::kVideoCodecUnknown); | |
| 516 ALOGD << "InitEncodeInternal Type: " << (int)codec_type << ", " << width | 522 ALOGD << "InitEncodeInternal Type: " << (int)codec_type << ", " << width |
| 517 << " x " << height << ". Bitrate: " << kbps << " kbps. Fps: " << fps; | 523 << " x " << height << ". Bitrate: " << kbps << " kbps. Fps: " << fps; |
| 518 if (kbps == 0) { | 524 if (kbps == 0) { |
| 519 kbps = last_set_bitrate_kbps_; | 525 kbps = last_set_bitrate_kbps_; |
| 520 } | 526 } |
| 521 if (fps == 0) { | 527 if (fps == 0) { |
| 522 fps = MAX_VIDEO_FPS; | 528 fps = MAX_VIDEO_FPS; |
| 523 } | 529 } |
| 524 | 530 |
| 525 width_ = width; | 531 width_ = width; |
| (...skipping 489 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1015 size_t payload_size = jni->GetDirectBufferCapacity(j_output_buffer); | 1021 size_t payload_size = jni->GetDirectBufferCapacity(j_output_buffer); |
| 1016 uint8_t* payload = reinterpret_cast<uint8_t*>( | 1022 uint8_t* payload = reinterpret_cast<uint8_t*>( |
| 1017 jni->GetDirectBufferAddress(j_output_buffer)); | 1023 jni->GetDirectBufferAddress(j_output_buffer)); |
| 1018 if (CheckException(jni)) { | 1024 if (CheckException(jni)) { |
| 1019 ALOGE << "Exception in get direct buffer address."; | 1025 ALOGE << "Exception in get direct buffer address."; |
| 1020 ProcessHWError(true /* reset_if_fallback_unavailable */); | 1026 ProcessHWError(true /* reset_if_fallback_unavailable */); |
| 1021 return WEBRTC_VIDEO_CODEC_ERROR; | 1027 return WEBRTC_VIDEO_CODEC_ERROR; |
| 1022 } | 1028 } |
| 1023 | 1029 |
| 1024 // Callback - return encoded frame. | 1030 // Callback - return encoded frame. |
| 1025 const VideoCodecType codec_type = | 1031 const VideoCodecType codec_type = GetCodecType(); |
| 1026 webrtc::PayloadNameToCodecType(codec_.name) | |
| 1027 .value_or(webrtc::kVideoCodecUnknown); | |
| 1028 webrtc::EncodedImageCallback::Result callback_result( | 1032 webrtc::EncodedImageCallback::Result callback_result( |
| 1029 webrtc::EncodedImageCallback::Result::OK); | 1033 webrtc::EncodedImageCallback::Result::OK); |
| 1030 if (callback_) { | 1034 if (callback_) { |
| 1031 std::unique_ptr<webrtc::EncodedImage> image( | 1035 std::unique_ptr<webrtc::EncodedImage> image( |
| 1032 new webrtc::EncodedImage(payload, payload_size, payload_size)); | 1036 new webrtc::EncodedImage(payload, payload_size, payload_size)); |
| 1033 image->_encodedWidth = width_; | 1037 image->_encodedWidth = width_; |
| 1034 image->_encodedHeight = height_; | 1038 image->_encodedHeight = height_; |
| 1035 image->_timeStamp = output_timestamp_; | 1039 image->_timeStamp = output_timestamp_; |
| 1036 image->capture_time_ms_ = output_render_time_ms_; | 1040 image->capture_time_ms_ = output_render_time_ms_; |
| 1037 image->rotation_ = output_rotation_; | 1041 image->rotation_ = output_rotation_; |
| (...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1179 stat_start_time_ms_ = rtc::TimeMillis(); | 1183 stat_start_time_ms_ = rtc::TimeMillis(); |
| 1180 current_frames_ = 0; | 1184 current_frames_ = 0; |
| 1181 current_bytes_ = 0; | 1185 current_bytes_ = 0; |
| 1182 current_acc_qp_ = 0; | 1186 current_acc_qp_ = 0; |
| 1183 current_encoding_time_ms_ = 0; | 1187 current_encoding_time_ms_ = 0; |
| 1184 } | 1188 } |
| 1185 } | 1189 } |
| 1186 | 1190 |
| 1187 webrtc::VideoEncoder::ScalingSettings | 1191 webrtc::VideoEncoder::ScalingSettings |
| 1188 MediaCodecVideoEncoder::GetScalingSettings() const { | 1192 MediaCodecVideoEncoder::GetScalingSettings() const { |
| 1193 if (webrtc::field_trial::IsEnabled(kCustomQPThresholdsFieldTrial)) { | |
| 1194 const VideoCodecType codec_type = GetCodecType(); | |
| 1195 std::string experiment_string = | |
| 1196 webrtc::field_trial::FindFullName(kCustomQPThresholdsFieldTrial); | |
| 1197 ALOGD << "QP custom thresholds: " << experiment_string << " for codec " | |
|
stefan-webrtc
2017/03/23 17:58:04
LOG(LS_INFO) or similar?
AlexG
2017/03/23 19:25:08
ALOGD is used now for all logging in this file - t
| |
| 1198 << codec_type; | |
| 1199 int lowVp8QpThreshold; | |
| 1200 int highVp8QpThreshold; | |
| 1201 int lowH264QpThreshold; | |
| 1202 int highH264QpThreshold; | |
|
stefan-webrtc
2017/03/23 17:58:04
No camelCase
AlexG
2017/03/23 19:25:08
Done.
| |
| 1203 int parsed_values = sscanf(experiment_string.c_str(), "Enabled-%u,%u,%u,%u", | |
| 1204 &lowVp8QpThreshold, &highVp8QpThreshold, | |
| 1205 &lowH264QpThreshold, &highH264QpThreshold); | |
| 1206 if (parsed_values == 4) { | |
| 1207 RTC_CHECK_GT(highVp8QpThreshold, lowVp8QpThreshold); | |
| 1208 RTC_CHECK_GT(lowVp8QpThreshold, 0); | |
| 1209 RTC_CHECK_GT(highH264QpThreshold, lowH264QpThreshold); | |
| 1210 RTC_CHECK_GT(lowH264QpThreshold, 0); | |
| 1211 if (codec_type == kVideoCodecVP8) { | |
| 1212 return VideoEncoder::ScalingSettings(scale_, lowVp8QpThreshold, | |
| 1213 highVp8QpThreshold); | |
| 1214 } else if (codec_type == kVideoCodecH264) { | |
| 1215 return VideoEncoder::ScalingSettings(scale_, lowH264QpThreshold, | |
| 1216 highH264QpThreshold); | |
| 1217 } | |
| 1218 } | |
| 1219 } | |
| 1189 return VideoEncoder::ScalingSettings(scale_); | 1220 return VideoEncoder::ScalingSettings(scale_); |
| 1190 } | 1221 } |
| 1191 | 1222 |
| 1192 const char* MediaCodecVideoEncoder::ImplementationName() const { | 1223 const char* MediaCodecVideoEncoder::ImplementationName() const { |
| 1193 return "MediaCodec"; | 1224 return "MediaCodec"; |
| 1194 } | 1225 } |
| 1195 | 1226 |
| 1196 MediaCodecVideoEncoderFactory::MediaCodecVideoEncoderFactory() | 1227 MediaCodecVideoEncoderFactory::MediaCodecVideoEncoderFactory() |
| 1197 : egl_context_(nullptr) { | 1228 : egl_context_(nullptr) { |
| 1198 JNIEnv* jni = AttachCurrentThreadIfNeeded(); | 1229 JNIEnv* jni = AttachCurrentThreadIfNeeded(); |
| (...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1311 } | 1342 } |
| 1312 } | 1343 } |
| 1313 | 1344 |
| 1314 void MediaCodecVideoEncoderFactory::DestroyVideoEncoder( | 1345 void MediaCodecVideoEncoderFactory::DestroyVideoEncoder( |
| 1315 webrtc::VideoEncoder* encoder) { | 1346 webrtc::VideoEncoder* encoder) { |
| 1316 ALOGD << "Destroy video encoder."; | 1347 ALOGD << "Destroy video encoder."; |
| 1317 delete encoder; | 1348 delete encoder; |
| 1318 } | 1349 } |
| 1319 | 1350 |
| 1320 } // namespace webrtc_jni | 1351 } // namespace webrtc_jni |
| OLD | NEW |