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