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 |