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 12 matching lines...) Expand all Loading... | |
| 23 #include "webrtc/api/android/jni/classreferenceholder.h" | 23 #include "webrtc/api/android/jni/classreferenceholder.h" |
| 24 #include "webrtc/api/android/jni/native_handle_impl.h" | 24 #include "webrtc/api/android/jni/native_handle_impl.h" |
| 25 #include "webrtc/base/bind.h" | 25 #include "webrtc/base/bind.h" |
| 26 #include "webrtc/base/checks.h" | 26 #include "webrtc/base/checks.h" |
| 27 #include "webrtc/base/logging.h" | 27 #include "webrtc/base/logging.h" |
| 28 #include "webrtc/base/thread.h" | 28 #include "webrtc/base/thread.h" |
| 29 #include "webrtc/base/thread_checker.h" | 29 #include "webrtc/base/thread_checker.h" |
| 30 #include "webrtc/base/timeutils.h" | 30 #include "webrtc/base/timeutils.h" |
| 31 #include "webrtc/common_types.h" | 31 #include "webrtc/common_types.h" |
| 32 #include "webrtc/common_video/h264/h264_bitstream_parser.h" | 32 #include "webrtc/common_video/h264/h264_bitstream_parser.h" |
| 33 #include "webrtc/media/engine/internalencoderfactory.h" | |
| 33 #include "webrtc/modules/video_coding/include/video_codec_interface.h" | 34 #include "webrtc/modules/video_coding/include/video_codec_interface.h" |
| 34 #include "webrtc/modules/video_coding/utility/quality_scaler.h" | 35 #include "webrtc/modules/video_coding/utility/quality_scaler.h" |
| 35 #include "webrtc/modules/video_coding/utility/vp8_header_parser.h" | 36 #include "webrtc/modules/video_coding/utility/vp8_header_parser.h" |
| 36 #include "webrtc/system_wrappers/include/field_trial.h" | 37 #include "webrtc/system_wrappers/include/field_trial.h" |
| 37 #include "webrtc/system_wrappers/include/logcat_trace_context.h" | 38 #include "webrtc/system_wrappers/include/logcat_trace_context.h" |
| 38 | 39 |
| 39 using rtc::Bind; | 40 using rtc::Bind; |
| 40 using rtc::Thread; | 41 using rtc::Thread; |
| 41 using rtc::ThreadManager; | 42 using rtc::ThreadManager; |
| 42 | 43 |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 89 // Android's MediaCodec SDK API behind the scenes to implement (hopefully) | 90 // Android's MediaCodec SDK API behind the scenes to implement (hopefully) |
| 90 // HW-backed video encode. This C++ class is implemented as a very thin shim, | 91 // HW-backed video encode. This C++ class is implemented as a very thin shim, |
| 91 // delegating all of the interesting work to org.webrtc.MediaCodecVideoEncoder. | 92 // delegating all of the interesting work to org.webrtc.MediaCodecVideoEncoder. |
| 92 // MediaCodecVideoEncoder is created, operated, and destroyed on a single | 93 // MediaCodecVideoEncoder is created, operated, and destroyed on a single |
| 93 // thread, currently the libjingle Worker thread. | 94 // thread, currently the libjingle Worker thread. |
| 94 class MediaCodecVideoEncoder : public webrtc::VideoEncoder, | 95 class MediaCodecVideoEncoder : public webrtc::VideoEncoder, |
| 95 public rtc::MessageHandler { | 96 public rtc::MessageHandler { |
| 96 public: | 97 public: |
| 97 virtual ~MediaCodecVideoEncoder(); | 98 virtual ~MediaCodecVideoEncoder(); |
| 98 MediaCodecVideoEncoder(JNIEnv* jni, | 99 MediaCodecVideoEncoder(JNIEnv* jni, |
| 99 VideoCodecType codecType, | 100 const cricket::VideoCodec& codec, |
| 100 jobject egl_context); | 101 jobject egl_context); |
| 101 | 102 |
| 102 // webrtc::VideoEncoder implementation. Everything trampolines to | 103 // webrtc::VideoEncoder implementation. Everything trampolines to |
| 103 // |codec_thread_| for execution. | 104 // |codec_thread_| for execution. |
| 104 int32_t InitEncode(const webrtc::VideoCodec* codec_settings, | 105 int32_t InitEncode(const webrtc::VideoCodec* codec_settings, |
| 105 int32_t /* number_of_cores */, | 106 int32_t /* number_of_cores */, |
| 106 size_t /* max_payload_size */) override; | 107 size_t /* max_payload_size */) override; |
| 107 int32_t Encode(const webrtc::VideoFrame& input_image, | 108 int32_t Encode(const webrtc::VideoFrame& input_image, |
| 108 const webrtc::CodecSpecificInfo* /* codec_specific_info */, | 109 const webrtc::CodecSpecificInfo* /* codec_specific_info */, |
| 109 const std::vector<webrtc::FrameType>* frame_types) override; | 110 const std::vector<webrtc::FrameType>* frame_types) override; |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 178 // true on success. | 179 // true on success. |
| 179 bool DeliverPendingOutputs(JNIEnv* jni); | 180 bool DeliverPendingOutputs(JNIEnv* jni); |
| 180 | 181 |
| 181 // Search for H.264 start codes. | 182 // Search for H.264 start codes. |
| 182 int32_t NextNaluPosition(uint8_t *buffer, size_t buffer_size); | 183 int32_t NextNaluPosition(uint8_t *buffer, size_t buffer_size); |
| 183 | 184 |
| 184 // Displays encoder statistics. | 185 // Displays encoder statistics. |
| 185 void LogStatistics(bool force_log); | 186 void LogStatistics(bool force_log); |
| 186 | 187 |
| 187 // Type of video codec. | 188 // Type of video codec. |
| 188 VideoCodecType codecType_; | 189 const cricket::VideoCodec codec_; |
| 189 | 190 |
| 190 // Valid all the time since RegisterEncodeCompleteCallback() Invoke()s to | 191 // Valid all the time since RegisterEncodeCompleteCallback() Invoke()s to |
| 191 // |codec_thread_| synchronously. | 192 // |codec_thread_| synchronously. |
| 192 webrtc::EncodedImageCallback* callback_; | 193 webrtc::EncodedImageCallback* callback_; |
| 193 | 194 |
| 194 // State that is constant for the lifetime of this object once the ctor | 195 // State that is constant for the lifetime of this object once the ctor |
| 195 // returns. | 196 // returns. |
| 196 std::unique_ptr<Thread> | 197 std::unique_ptr<Thread> |
| 197 codec_thread_; // Thread on which to operate MediaCodec. | 198 codec_thread_; // Thread on which to operate MediaCodec. |
| 198 rtc::ThreadChecker codec_thread_checker_; | 199 rtc::ThreadChecker codec_thread_checker_; |
| (...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 294 | 295 |
| 295 bool sw_fallback_required_; | 296 bool sw_fallback_required_; |
| 296 }; | 297 }; |
| 297 | 298 |
| 298 MediaCodecVideoEncoder::~MediaCodecVideoEncoder() { | 299 MediaCodecVideoEncoder::~MediaCodecVideoEncoder() { |
| 299 // Call Release() to ensure no more callbacks to us after we are deleted. | 300 // Call Release() to ensure no more callbacks to us after we are deleted. |
| 300 Release(); | 301 Release(); |
| 301 } | 302 } |
| 302 | 303 |
| 303 MediaCodecVideoEncoder::MediaCodecVideoEncoder(JNIEnv* jni, | 304 MediaCodecVideoEncoder::MediaCodecVideoEncoder(JNIEnv* jni, |
| 304 VideoCodecType codecType, | 305 const cricket::VideoCodec& codec, |
| 305 jobject egl_context) | 306 jobject egl_context) |
| 306 : codecType_(codecType), | 307 : codec_(codec), |
| 307 callback_(NULL), | 308 callback_(NULL), |
| 308 codec_thread_(new Thread()), | 309 codec_thread_(new Thread()), |
| 309 j_media_codec_video_encoder_class_( | 310 j_media_codec_video_encoder_class_( |
| 310 jni, | 311 jni, |
| 311 FindClass(jni, "org/webrtc/MediaCodecVideoEncoder")), | 312 FindClass(jni, "org/webrtc/MediaCodecVideoEncoder")), |
| 312 j_media_codec_video_encoder_( | 313 j_media_codec_video_encoder_( |
| 313 jni, | 314 jni, |
| 314 jni->NewObject(*j_media_codec_video_encoder_class_, | 315 jni->NewObject(*j_media_codec_video_encoder_class_, |
| 315 GetMethodID(jni, | 316 GetMethodID(jni, |
| 316 *j_media_codec_video_encoder_class_, | 317 *j_media_codec_video_encoder_class_, |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 384 | 385 |
| 385 int32_t MediaCodecVideoEncoder::InitEncode( | 386 int32_t MediaCodecVideoEncoder::InitEncode( |
| 386 const webrtc::VideoCodec* codec_settings, | 387 const webrtc::VideoCodec* codec_settings, |
| 387 int32_t /* number_of_cores */, | 388 int32_t /* number_of_cores */, |
| 388 size_t /* max_payload_size */) { | 389 size_t /* max_payload_size */) { |
| 389 if (codec_settings == NULL) { | 390 if (codec_settings == NULL) { |
| 390 ALOGE << "NULL VideoCodec instance"; | 391 ALOGE << "NULL VideoCodec instance"; |
| 391 return WEBRTC_VIDEO_CODEC_ERR_PARAMETER; | 392 return WEBRTC_VIDEO_CODEC_ERR_PARAMETER; |
| 392 } | 393 } |
| 393 // Factory should guard against other codecs being used with us. | 394 // Factory should guard against other codecs being used with us. |
| 394 RTC_CHECK(codec_settings->codecType == codecType_) | 395 const VideoCodecType codec_type = cricket::CodecTypeFromName(codec_.name); |
| 396 RTC_CHECK(codec_settings->codecType == codec_type) | |
| 395 << "Unsupported codec " << codec_settings->codecType << " for " | 397 << "Unsupported codec " << codec_settings->codecType << " for " |
| 396 << codecType_; | 398 << codec_type; |
| 397 if (sw_fallback_required_) { | 399 if (sw_fallback_required_) { |
| 398 return WEBRTC_VIDEO_CODEC_OK; | 400 return WEBRTC_VIDEO_CODEC_OK; |
| 399 } | 401 } |
| 400 codec_mode_ = codec_settings->mode; | 402 codec_mode_ = codec_settings->mode; |
| 401 int init_width = codec_settings->width; | 403 int init_width = codec_settings->width; |
| 402 int init_height = codec_settings->height; | 404 int init_height = codec_settings->height; |
| 403 // Scaling is disabled for VP9, but optionally enabled for VP8. | 405 // Scaling is disabled for VP9, but optionally enabled for VP8. |
| 404 // TODO(pbos): Extract automaticResizeOn out of VP8 settings. | 406 // TODO(pbos): Extract automaticResizeOn out of VP8 settings. |
| 405 scale_ = false; | 407 scale_ = false; |
| 406 if (codecType_ == kVideoCodecVP8) { | 408 if (codec_type == kVideoCodecVP8) { |
| 407 scale_ = codec_settings->codecSpecific.VP8.automaticResizeOn; | 409 scale_ = codec_settings->codecSpecific.VP8.automaticResizeOn; |
|
hta-webrtc
2016/11/15 20:36:24
Sideswipe: This access to codecSpecific shoudldn't
magjed_webrtc
2016/11/16 13:44:11
Done.
| |
| 408 } else if (codecType_ != kVideoCodecVP9) { | 410 } else if (codec_type != kVideoCodecVP9) { |
| 409 scale_ = true; | 411 scale_ = true; |
| 410 } | 412 } |
| 411 | 413 |
| 412 ALOGD << "InitEncode request: " << init_width << " x " << init_height; | 414 ALOGD << "InitEncode request: " << init_width << " x " << init_height; |
| 413 ALOGD << "Encoder automatic resize " << (scale_ ? "enabled" : "disabled"); | 415 ALOGD << "Encoder automatic resize " << (scale_ ? "enabled" : "disabled"); |
| 414 | 416 |
| 415 if (scale_) { | 417 if (scale_) { |
| 416 if (codecType_ == kVideoCodecVP8 || codecType_ == kVideoCodecH264) { | 418 if (codec_type == kVideoCodecVP8 || codec_type == kVideoCodecH264) { |
| 417 quality_scaler_.Init(codecType_, codec_settings->startBitrate, | 419 quality_scaler_.Init(codec_type, codec_settings->startBitrate, |
| 418 codec_settings->width, codec_settings->height, | 420 codec_settings->width, codec_settings->height, |
| 419 codec_settings->maxFramerate); | 421 codec_settings->maxFramerate); |
| 420 } else { | 422 } else { |
| 421 // When adding codec support to additional hardware codecs, also configure | 423 // When adding codec support to additional hardware codecs, also configure |
| 422 // their QP thresholds for scaling. | 424 // their QP thresholds for scaling. |
| 423 RTC_NOTREACHED() << "Unsupported codec without configured QP thresholds."; | 425 RTC_NOTREACHED() << "Unsupported codec without configured QP thresholds."; |
| 424 scale_ = false; | 426 scale_ = false; |
| 425 } | 427 } |
| 426 QualityScaler::Resolution res = quality_scaler_.GetScaledResolution(); | 428 QualityScaler::Resolution res = quality_scaler_.GetScaledResolution(); |
| 427 init_width = res.width; | 429 init_width = res.width; |
| (...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 513 WEBRTC_VIDEO_CODEC_OK) { | 515 WEBRTC_VIDEO_CODEC_OK) { |
| 514 ALOGE << "Initializing encoder failed during reset."; | 516 ALOGE << "Initializing encoder failed during reset."; |
| 515 return false; | 517 return false; |
| 516 } | 518 } |
| 517 return true; | 519 return true; |
| 518 } | 520 } |
| 519 | 521 |
| 520 bool MediaCodecVideoEncoder::ProcessHWErrorOnCodecThread( | 522 bool MediaCodecVideoEncoder::ProcessHWErrorOnCodecThread( |
| 521 bool reset_if_fallback_unavailable) { | 523 bool reset_if_fallback_unavailable) { |
| 522 ALOGE << "ProcessHWErrorOnCodecThread"; | 524 ALOGE << "ProcessHWErrorOnCodecThread"; |
| 523 if (VideoEncoder::IsSupportedSoftware( | 525 if (FindMatchingCodec( |
| 524 VideoEncoder::CodecToEncoderType(codecType_))) { | 526 cricket::InternalEncoderFactory::GetInstance().supported_codecs(), |
| 527 codec_)) { | |
| 525 ALOGE << "Fallback to SW encoder."; | 528 ALOGE << "Fallback to SW encoder."; |
| 526 sw_fallback_required_ = true; | 529 sw_fallback_required_ = true; |
| 527 return false; | 530 return false; |
| 528 } else if (reset_if_fallback_unavailable) { | 531 } else if (reset_if_fallback_unavailable) { |
| 529 ALOGE << "Reset encoder."; | 532 ALOGE << "Reset encoder."; |
| 530 return ResetCodecOnCodecThread(); | 533 return ResetCodecOnCodecThread(); |
| 531 } | 534 } |
| 532 return false; | 535 return false; |
| 533 } | 536 } |
| 534 | 537 |
| 535 int32_t MediaCodecVideoEncoder::ProcessHWErrorOnEncodeOnCodecThread() { | 538 int32_t MediaCodecVideoEncoder::ProcessHWErrorOnEncodeOnCodecThread() { |
| 536 ProcessHWErrorOnCodecThread(true /* reset_if_fallback_unavailable */); | 539 ProcessHWErrorOnCodecThread(true /* reset_if_fallback_unavailable */); |
| 537 return sw_fallback_required_ ? WEBRTC_VIDEO_CODEC_FALLBACK_SOFTWARE | 540 return sw_fallback_required_ ? WEBRTC_VIDEO_CODEC_FALLBACK_SOFTWARE |
| 538 : WEBRTC_VIDEO_CODEC_ERROR; | 541 : WEBRTC_VIDEO_CODEC_ERROR; |
| 539 } | 542 } |
| 540 | 543 |
| 541 int32_t MediaCodecVideoEncoder::InitEncodeOnCodecThread( | 544 int32_t MediaCodecVideoEncoder::InitEncodeOnCodecThread( |
| 542 int width, int height, int kbps, int fps, bool use_surface) { | 545 int width, int height, int kbps, int fps, bool use_surface) { |
| 543 RTC_DCHECK(codec_thread_checker_.CalledOnValidThread()); | 546 RTC_DCHECK(codec_thread_checker_.CalledOnValidThread()); |
| 544 if (sw_fallback_required_) { | 547 if (sw_fallback_required_) { |
| 545 return WEBRTC_VIDEO_CODEC_OK; | 548 return WEBRTC_VIDEO_CODEC_OK; |
| 546 } | 549 } |
| 547 RTC_CHECK(!use_surface || egl_context_ != nullptr) << "EGL context not set."; | 550 RTC_CHECK(!use_surface || egl_context_ != nullptr) << "EGL context not set."; |
| 548 JNIEnv* jni = AttachCurrentThreadIfNeeded(); | 551 JNIEnv* jni = AttachCurrentThreadIfNeeded(); |
| 549 ScopedLocalRefFrame local_ref_frame(jni); | 552 ScopedLocalRefFrame local_ref_frame(jni); |
| 550 | 553 |
| 551 ALOGD << "InitEncodeOnCodecThread Type: " << (int)codecType_ << ", " << | 554 const VideoCodecType codec_type = cricket::CodecTypeFromName(codec_.name); |
| 552 width << " x " << height << ". Bitrate: " << kbps << | 555 ALOGD << "InitEncodeOnCodecThread Type: " << (int)codec_type << ", " << width |
| 553 " kbps. Fps: " << fps; | 556 << " x " << height << ". Bitrate: " << kbps << " kbps. Fps: " << fps; |
| 554 if (kbps == 0) { | 557 if (kbps == 0) { |
| 555 kbps = last_set_bitrate_kbps_; | 558 kbps = last_set_bitrate_kbps_; |
| 556 } | 559 } |
| 557 if (fps == 0) { | 560 if (fps == 0) { |
| 558 fps = MAX_VIDEO_FPS; | 561 fps = MAX_VIDEO_FPS; |
| 559 } | 562 } |
| 560 | 563 |
| 561 width_ = width; | 564 width_ = width; |
| 562 height_ = height; | 565 height_ = height; |
| 563 last_set_bitrate_kbps_ = kbps; | 566 last_set_bitrate_kbps_ = kbps; |
| (...skipping 18 matching lines...) Expand all Loading... | |
| 582 use_surface_ = use_surface; | 585 use_surface_ = use_surface; |
| 583 picture_id_ = static_cast<uint16_t>(rand()) & 0x7FFF; | 586 picture_id_ = static_cast<uint16_t>(rand()) & 0x7FFF; |
| 584 gof_.SetGofInfoVP9(webrtc::TemporalStructureMode::kTemporalStructureMode1); | 587 gof_.SetGofInfoVP9(webrtc::TemporalStructureMode::kTemporalStructureMode1); |
| 585 tl0_pic_idx_ = static_cast<uint8_t>(rand()); | 588 tl0_pic_idx_ = static_cast<uint8_t>(rand()); |
| 586 gof_idx_ = 0; | 589 gof_idx_ = 0; |
| 587 last_frame_received_ms_ = -1; | 590 last_frame_received_ms_ = -1; |
| 588 frames_received_since_last_key_ = kMinKeyFrameInterval; | 591 frames_received_since_last_key_ = kMinKeyFrameInterval; |
| 589 | 592 |
| 590 // We enforce no extra stride/padding in the format creation step. | 593 // We enforce no extra stride/padding in the format creation step. |
| 591 jobject j_video_codec_enum = JavaEnumFromIndexAndClassName( | 594 jobject j_video_codec_enum = JavaEnumFromIndexAndClassName( |
| 592 jni, "MediaCodecVideoEncoder$VideoCodecType", codecType_); | 595 jni, "MediaCodecVideoEncoder$VideoCodecType", codec_type); |
| 593 const bool encode_status = jni->CallBooleanMethod( | 596 const bool encode_status = jni->CallBooleanMethod( |
| 594 *j_media_codec_video_encoder_, j_init_encode_method_, | 597 *j_media_codec_video_encoder_, j_init_encode_method_, |
| 595 j_video_codec_enum, width, height, kbps, fps, | 598 j_video_codec_enum, width, height, kbps, fps, |
| 596 (use_surface ? egl_context_ : nullptr)); | 599 (use_surface ? egl_context_ : nullptr)); |
| 597 if (!encode_status) { | 600 if (!encode_status) { |
| 598 ALOGE << "Failed to configure encoder."; | 601 ALOGE << "Failed to configure encoder."; |
| 599 ProcessHWErrorOnCodecThread(false /* reset_if_fallback_unavailable */); | 602 ProcessHWErrorOnCodecThread(false /* reset_if_fallback_unavailable */); |
| 600 return WEBRTC_VIDEO_CODEC_ERROR; | 603 return WEBRTC_VIDEO_CODEC_ERROR; |
| 601 } | 604 } |
| 602 if (CheckException(jni)) { | 605 if (CheckException(jni)) { |
| (...skipping 453 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1056 size_t payload_size = jni->GetDirectBufferCapacity(j_output_buffer); | 1059 size_t payload_size = jni->GetDirectBufferCapacity(j_output_buffer); |
| 1057 uint8_t* payload = reinterpret_cast<uint8_t*>( | 1060 uint8_t* payload = reinterpret_cast<uint8_t*>( |
| 1058 jni->GetDirectBufferAddress(j_output_buffer)); | 1061 jni->GetDirectBufferAddress(j_output_buffer)); |
| 1059 if (CheckException(jni)) { | 1062 if (CheckException(jni)) { |
| 1060 ALOGE << "Exception in get direct buffer address."; | 1063 ALOGE << "Exception in get direct buffer address."; |
| 1061 ProcessHWErrorOnCodecThread(true /* reset_if_fallback_unavailable */); | 1064 ProcessHWErrorOnCodecThread(true /* reset_if_fallback_unavailable */); |
| 1062 return WEBRTC_VIDEO_CODEC_ERROR; | 1065 return WEBRTC_VIDEO_CODEC_ERROR; |
| 1063 } | 1066 } |
| 1064 | 1067 |
| 1065 // Callback - return encoded frame. | 1068 // Callback - return encoded frame. |
| 1069 const VideoCodecType codec_type = cricket::CodecTypeFromName(codec_.name); | |
| 1066 webrtc::EncodedImageCallback::Result callback_result( | 1070 webrtc::EncodedImageCallback::Result callback_result( |
| 1067 webrtc::EncodedImageCallback::Result::OK); | 1071 webrtc::EncodedImageCallback::Result::OK); |
| 1068 if (callback_) { | 1072 if (callback_) { |
| 1069 std::unique_ptr<webrtc::EncodedImage> image( | 1073 std::unique_ptr<webrtc::EncodedImage> image( |
| 1070 new webrtc::EncodedImage(payload, payload_size, payload_size)); | 1074 new webrtc::EncodedImage(payload, payload_size, payload_size)); |
| 1071 image->_encodedWidth = width_; | 1075 image->_encodedWidth = width_; |
| 1072 image->_encodedHeight = height_; | 1076 image->_encodedHeight = height_; |
| 1073 image->_timeStamp = output_timestamp_; | 1077 image->_timeStamp = output_timestamp_; |
| 1074 image->capture_time_ms_ = output_render_time_ms_; | 1078 image->capture_time_ms_ = output_render_time_ms_; |
| 1075 image->rotation_ = output_rotation_; | 1079 image->rotation_ = output_rotation_; |
| 1076 image->_frameType = | 1080 image->_frameType = |
| 1077 (key_frame ? webrtc::kVideoFrameKey : webrtc::kVideoFrameDelta); | 1081 (key_frame ? webrtc::kVideoFrameKey : webrtc::kVideoFrameDelta); |
| 1078 image->_completeFrame = true; | 1082 image->_completeFrame = true; |
| 1079 image->adapt_reason_.quality_resolution_downscales = | 1083 image->adapt_reason_.quality_resolution_downscales = |
| 1080 scale_ ? quality_scaler_.downscale_shift() : -1; | 1084 scale_ ? quality_scaler_.downscale_shift() : -1; |
| 1081 | 1085 |
| 1082 webrtc::CodecSpecificInfo info; | 1086 webrtc::CodecSpecificInfo info; |
| 1083 memset(&info, 0, sizeof(info)); | 1087 memset(&info, 0, sizeof(info)); |
| 1084 info.codecType = codecType_; | 1088 info.codecType = codec_type; |
| 1085 if (codecType_ == kVideoCodecVP8) { | 1089 if (codec_type == kVideoCodecVP8) { |
| 1086 info.codecSpecific.VP8.pictureId = picture_id_; | 1090 info.codecSpecific.VP8.pictureId = picture_id_; |
| 1087 info.codecSpecific.VP8.nonReference = false; | 1091 info.codecSpecific.VP8.nonReference = false; |
| 1088 info.codecSpecific.VP8.simulcastIdx = 0; | 1092 info.codecSpecific.VP8.simulcastIdx = 0; |
| 1089 info.codecSpecific.VP8.temporalIdx = webrtc::kNoTemporalIdx; | 1093 info.codecSpecific.VP8.temporalIdx = webrtc::kNoTemporalIdx; |
| 1090 info.codecSpecific.VP8.layerSync = false; | 1094 info.codecSpecific.VP8.layerSync = false; |
| 1091 info.codecSpecific.VP8.tl0PicIdx = webrtc::kNoTl0PicIdx; | 1095 info.codecSpecific.VP8.tl0PicIdx = webrtc::kNoTl0PicIdx; |
| 1092 info.codecSpecific.VP8.keyIdx = webrtc::kNoKeyIdx; | 1096 info.codecSpecific.VP8.keyIdx = webrtc::kNoKeyIdx; |
| 1093 } else if (codecType_ == kVideoCodecVP9) { | 1097 } else if (codec_type == kVideoCodecVP9) { |
| 1094 if (key_frame) { | 1098 if (key_frame) { |
| 1095 gof_idx_ = 0; | 1099 gof_idx_ = 0; |
| 1096 } | 1100 } |
| 1097 info.codecSpecific.VP9.picture_id = picture_id_; | 1101 info.codecSpecific.VP9.picture_id = picture_id_; |
| 1098 info.codecSpecific.VP9.inter_pic_predicted = key_frame ? false : true; | 1102 info.codecSpecific.VP9.inter_pic_predicted = key_frame ? false : true; |
| 1099 info.codecSpecific.VP9.flexible_mode = false; | 1103 info.codecSpecific.VP9.flexible_mode = false; |
| 1100 info.codecSpecific.VP9.ss_data_available = key_frame ? true : false; | 1104 info.codecSpecific.VP9.ss_data_available = key_frame ? true : false; |
| 1101 info.codecSpecific.VP9.tl0_pic_idx = tl0_pic_idx_++; | 1105 info.codecSpecific.VP9.tl0_pic_idx = tl0_pic_idx_++; |
| 1102 info.codecSpecific.VP9.temporal_idx = webrtc::kNoTemporalIdx; | 1106 info.codecSpecific.VP9.temporal_idx = webrtc::kNoTemporalIdx; |
| 1103 info.codecSpecific.VP9.spatial_idx = webrtc::kNoSpatialIdx; | 1107 info.codecSpecific.VP9.spatial_idx = webrtc::kNoSpatialIdx; |
| 1104 info.codecSpecific.VP9.temporal_up_switch = true; | 1108 info.codecSpecific.VP9.temporal_up_switch = true; |
| 1105 info.codecSpecific.VP9.inter_layer_predicted = false; | 1109 info.codecSpecific.VP9.inter_layer_predicted = false; |
| 1106 info.codecSpecific.VP9.gof_idx = | 1110 info.codecSpecific.VP9.gof_idx = |
| 1107 static_cast<uint8_t>(gof_idx_++ % gof_.num_frames_in_gof); | 1111 static_cast<uint8_t>(gof_idx_++ % gof_.num_frames_in_gof); |
| 1108 info.codecSpecific.VP9.num_spatial_layers = 1; | 1112 info.codecSpecific.VP9.num_spatial_layers = 1; |
| 1109 info.codecSpecific.VP9.spatial_layer_resolution_present = false; | 1113 info.codecSpecific.VP9.spatial_layer_resolution_present = false; |
| 1110 if (info.codecSpecific.VP9.ss_data_available) { | 1114 if (info.codecSpecific.VP9.ss_data_available) { |
| 1111 info.codecSpecific.VP9.spatial_layer_resolution_present = true; | 1115 info.codecSpecific.VP9.spatial_layer_resolution_present = true; |
| 1112 info.codecSpecific.VP9.width[0] = width_; | 1116 info.codecSpecific.VP9.width[0] = width_; |
| 1113 info.codecSpecific.VP9.height[0] = height_; | 1117 info.codecSpecific.VP9.height[0] = height_; |
| 1114 info.codecSpecific.VP9.gof.CopyGofInfoVP9(gof_); | 1118 info.codecSpecific.VP9.gof.CopyGofInfoVP9(gof_); |
| 1115 } | 1119 } |
| 1116 } | 1120 } |
| 1117 picture_id_ = (picture_id_ + 1) & 0x7FFF; | 1121 picture_id_ = (picture_id_ + 1) & 0x7FFF; |
| 1118 | 1122 |
| 1119 // Generate a header describing a single fragment. | 1123 // Generate a header describing a single fragment. |
| 1120 webrtc::RTPFragmentationHeader header; | 1124 webrtc::RTPFragmentationHeader header; |
| 1121 memset(&header, 0, sizeof(header)); | 1125 memset(&header, 0, sizeof(header)); |
| 1122 if (codecType_ == kVideoCodecVP8 || codecType_ == kVideoCodecVP9) { | 1126 if (codec_type == kVideoCodecVP8 || codec_type == kVideoCodecVP9) { |
| 1123 header.VerifyAndAllocateFragmentationHeader(1); | 1127 header.VerifyAndAllocateFragmentationHeader(1); |
| 1124 header.fragmentationOffset[0] = 0; | 1128 header.fragmentationOffset[0] = 0; |
| 1125 header.fragmentationLength[0] = image->_length; | 1129 header.fragmentationLength[0] = image->_length; |
| 1126 header.fragmentationPlType[0] = 0; | 1130 header.fragmentationPlType[0] = 0; |
| 1127 header.fragmentationTimeDiff[0] = 0; | 1131 header.fragmentationTimeDiff[0] = 0; |
| 1128 if (codecType_ == kVideoCodecVP8 && scale_) { | 1132 if (codec_type == kVideoCodecVP8 && scale_) { |
| 1129 int qp; | 1133 int qp; |
| 1130 if (webrtc::vp8::GetQp(payload, payload_size, &qp)) { | 1134 if (webrtc::vp8::GetQp(payload, payload_size, &qp)) { |
| 1131 current_acc_qp_ += qp; | 1135 current_acc_qp_ += qp; |
| 1132 quality_scaler_.ReportQP(qp); | 1136 quality_scaler_.ReportQP(qp); |
| 1133 image->qp_ = qp; | 1137 image->qp_ = qp; |
| 1134 } | 1138 } |
| 1135 } | 1139 } |
| 1136 } else if (codecType_ == kVideoCodecH264) { | 1140 } else if (codec_type == kVideoCodecH264) { |
| 1137 if (scale_) { | 1141 if (scale_) { |
| 1138 h264_bitstream_parser_.ParseBitstream(payload, payload_size); | 1142 h264_bitstream_parser_.ParseBitstream(payload, payload_size); |
| 1139 int qp; | 1143 int qp; |
| 1140 if (h264_bitstream_parser_.GetLastSliceQp(&qp)) { | 1144 if (h264_bitstream_parser_.GetLastSliceQp(&qp)) { |
| 1141 current_acc_qp_ += qp; | 1145 current_acc_qp_ += qp; |
| 1142 quality_scaler_.ReportQP(qp); | 1146 quality_scaler_.ReportQP(qp); |
| 1143 } | 1147 } |
| 1144 } | 1148 } |
| 1145 // For H.264 search for start codes. | 1149 // For H.264 search for start codes. |
| 1146 int32_t scPositions[MAX_NALUS_PERFRAME + 1] = {}; | 1150 int32_t scPositions[MAX_NALUS_PERFRAME + 1] = {}; |
| (...skipping 203 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1350 } | 1354 } |
| 1351 | 1355 |
| 1352 webrtc::VideoEncoder* MediaCodecVideoEncoderFactory::CreateVideoEncoder( | 1356 webrtc::VideoEncoder* MediaCodecVideoEncoderFactory::CreateVideoEncoder( |
| 1353 const cricket::VideoCodec& codec) { | 1357 const cricket::VideoCodec& codec) { |
| 1354 if (supported_codecs_.empty()) { | 1358 if (supported_codecs_.empty()) { |
| 1355 ALOGW << "No HW video encoder for codec " << codec.name; | 1359 ALOGW << "No HW video encoder for codec " << codec.name; |
| 1356 return nullptr; | 1360 return nullptr; |
| 1357 } | 1361 } |
| 1358 if (FindMatchingCodec(supported_codecs_, codec)) { | 1362 if (FindMatchingCodec(supported_codecs_, codec)) { |
| 1359 ALOGD << "Create HW video encoder for " << codec.name; | 1363 ALOGD << "Create HW video encoder for " << codec.name; |
| 1360 const VideoCodecType type = cricket::CodecTypeFromName(codec.name); | 1364 return new MediaCodecVideoEncoder(AttachCurrentThreadIfNeeded(), codec, |
| 1361 return new MediaCodecVideoEncoder(AttachCurrentThreadIfNeeded(), type, | |
| 1362 egl_context_); | 1365 egl_context_); |
| 1363 } | 1366 } |
| 1364 ALOGW << "Can not find HW video encoder for type " << codec.name; | 1367 ALOGW << "Can not find HW video encoder for type " << codec.name; |
| 1365 return nullptr; | 1368 return nullptr; |
| 1366 } | 1369 } |
| 1367 | 1370 |
| 1368 const std::vector<cricket::VideoCodec>& | 1371 const std::vector<cricket::VideoCodec>& |
| 1369 MediaCodecVideoEncoderFactory::supported_codecs() const { | 1372 MediaCodecVideoEncoderFactory::supported_codecs() const { |
| 1370 return supported_codecs_; | 1373 return supported_codecs_; |
| 1371 } | 1374 } |
| 1372 | 1375 |
| 1373 void MediaCodecVideoEncoderFactory::DestroyVideoEncoder( | 1376 void MediaCodecVideoEncoderFactory::DestroyVideoEncoder( |
| 1374 webrtc::VideoEncoder* encoder) { | 1377 webrtc::VideoEncoder* encoder) { |
| 1375 ALOGD << "Destroy video encoder."; | 1378 ALOGD << "Destroy video encoder."; |
| 1376 delete encoder; | 1379 delete encoder; |
| 1377 } | 1380 } |
| 1378 | 1381 |
| 1379 } // namespace webrtc_jni | 1382 } // namespace webrtc_jni |
| OLD | NEW |