Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 /* | 1 /* |
| 2 * libjingle | 2 * libjingle |
| 3 * Copyright 2015 Google Inc. | 3 * Copyright 2015 Google Inc. |
| 4 * | 4 * |
| 5 * Redistribution and use in source and binary forms, with or without | 5 * Redistribution and use in source and binary forms, with or without |
| 6 * modification, are permitted provided that the following conditions are met: | 6 * modification, are permitted provided that the following conditions are met: |
| 7 * | 7 * |
| 8 * 1. Redistributions of source code must retain the above copyright notice, | 8 * 1. Redistributions of source code must retain the above copyright notice, |
| 9 * this list of conditions and the following disclaimer. | 9 * this list of conditions and the following disclaimer. |
| 10 * 2. Redistributions in binary form must reproduce the above copyright notice, | 10 * 2. Redistributions in binary form must reproduce the above copyright notice, |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 27 */ | 27 */ |
| 28 | 28 |
| 29 #include "talk/app/webrtc/java/jni/androidmediaencoder_jni.h" | 29 #include "talk/app/webrtc/java/jni/androidmediaencoder_jni.h" |
| 30 #include "talk/app/webrtc/java/jni/classreferenceholder.h" | 30 #include "talk/app/webrtc/java/jni/classreferenceholder.h" |
| 31 #include "talk/app/webrtc/java/jni/androidmediacodeccommon.h" | 31 #include "talk/app/webrtc/java/jni/androidmediacodeccommon.h" |
| 32 #include "webrtc/base/bind.h" | 32 #include "webrtc/base/bind.h" |
| 33 #include "webrtc/base/checks.h" | 33 #include "webrtc/base/checks.h" |
| 34 #include "webrtc/base/logging.h" | 34 #include "webrtc/base/logging.h" |
| 35 #include "webrtc/base/thread.h" | 35 #include "webrtc/base/thread.h" |
| 36 #include "webrtc/base/thread_checker.h" | 36 #include "webrtc/base/thread_checker.h" |
| 37 #include "webrtc/common_types.h" | |
| 37 #include "webrtc/modules/rtp_rtcp/source/h264_bitstream_parser.h" | 38 #include "webrtc/modules/rtp_rtcp/source/h264_bitstream_parser.h" |
| 38 #include "webrtc/modules/video_coding/codecs/interface/video_codec_interface.h" | 39 #include "webrtc/modules/video_coding/codecs/interface/video_codec_interface.h" |
| 39 #include "webrtc/modules/video_coding/utility/include/quality_scaler.h" | 40 #include "webrtc/modules/video_coding/utility/include/quality_scaler.h" |
| 40 #include "webrtc/modules/video_coding/utility/include/vp8_header_parser.h" | 41 #include "webrtc/modules/video_coding/utility/include/vp8_header_parser.h" |
| 41 #include "webrtc/system_wrappers/include/field_trial.h" | 42 #include "webrtc/system_wrappers/include/field_trial.h" |
| 42 #include "webrtc/system_wrappers/include/logcat_trace_context.h" | 43 #include "webrtc/system_wrappers/include/logcat_trace_context.h" |
| 43 #include "third_party/libyuv/include/libyuv/convert.h" | 44 #include "third_party/libyuv/include/libyuv/convert.h" |
| 44 #include "third_party/libyuv/include/libyuv/convert_from.h" | 45 #include "third_party/libyuv/include/libyuv/convert_from.h" |
| 45 #include "third_party/libyuv/include/libyuv/video_common.h" | 46 #include "third_party/libyuv/include/libyuv/video_common.h" |
| 46 | 47 |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 63 // H.264 start code length. | 64 // H.264 start code length. |
| 64 #define H264_SC_LENGTH 4 | 65 #define H264_SC_LENGTH 4 |
| 65 // Maximum allowed NALUs in one output frame. | 66 // Maximum allowed NALUs in one output frame. |
| 66 #define MAX_NALUS_PERFRAME 32 | 67 #define MAX_NALUS_PERFRAME 32 |
| 67 // Maximum supported HW video encoder resolution. | 68 // Maximum supported HW video encoder resolution. |
| 68 #define MAX_VIDEO_WIDTH 1280 | 69 #define MAX_VIDEO_WIDTH 1280 |
| 69 #define MAX_VIDEO_HEIGHT 1280 | 70 #define MAX_VIDEO_HEIGHT 1280 |
| 70 // Maximum supported HW video encoder fps. | 71 // Maximum supported HW video encoder fps. |
| 71 #define MAX_VIDEO_FPS 30 | 72 #define MAX_VIDEO_FPS 30 |
| 72 | 73 |
| 74 namespace { | |
| 75 // Maximum time limit between incoming frames before requesting a key frame. | |
| 76 const size_t kFrameDiffThresholdMs = 1100; | |
| 77 const int kMinKeyFrameInterval = 2; | |
| 78 } // namespace | |
| 79 | |
| 73 // MediaCodecVideoEncoder is a webrtc::VideoEncoder implementation that uses | 80 // MediaCodecVideoEncoder is a webrtc::VideoEncoder implementation that uses |
| 74 // Android's MediaCodec SDK API behind the scenes to implement (hopefully) | 81 // Android's MediaCodec SDK API behind the scenes to implement (hopefully) |
| 75 // HW-backed video encode. This C++ class is implemented as a very thin shim, | 82 // HW-backed video encode. This C++ class is implemented as a very thin shim, |
| 76 // delegating all of the interesting work to org.webrtc.MediaCodecVideoEncoder. | 83 // delegating all of the interesting work to org.webrtc.MediaCodecVideoEncoder. |
| 77 // MediaCodecVideoEncoder is created, operated, and destroyed on a single | 84 // MediaCodecVideoEncoder is created, operated, and destroyed on a single |
| 78 // thread, currently the libjingle Worker thread. | 85 // thread, currently the libjingle Worker thread. |
| 79 class MediaCodecVideoEncoder : public webrtc::VideoEncoder, | 86 class MediaCodecVideoEncoder : public webrtc::VideoEncoder, |
| 80 public rtc::MessageHandler { | 87 public rtc::MessageHandler { |
| 81 public: | 88 public: |
| 82 virtual ~MediaCodecVideoEncoder(); | 89 virtual ~MediaCodecVideoEncoder(); |
| (...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 206 // and the next Encode() call being ignored. | 213 // and the next Encode() call being ignored. |
| 207 bool drop_next_input_frame_; | 214 bool drop_next_input_frame_; |
| 208 // Global references; must be deleted in Release(). | 215 // Global references; must be deleted in Release(). |
| 209 std::vector<jobject> input_buffers_; | 216 std::vector<jobject> input_buffers_; |
| 210 webrtc::QualityScaler quality_scaler_; | 217 webrtc::QualityScaler quality_scaler_; |
| 211 // Dynamic resolution change, off by default. | 218 // Dynamic resolution change, off by default. |
| 212 bool scale_; | 219 bool scale_; |
| 213 | 220 |
| 214 // H264 bitstream parser, used to extract QP from encoded bitstreams. | 221 // H264 bitstream parser, used to extract QP from encoded bitstreams. |
| 215 webrtc::H264BitstreamParser h264_bitstream_parser_; | 222 webrtc::H264BitstreamParser h264_bitstream_parser_; |
| 223 | |
| 224 // Temporary fix for VP8. | |
| 225 // Sends a key frame if frames are largely spaced apart (possibly | |
| 226 // corresponding to a large image change). | |
| 227 int64_t last_frame_received_ms_; | |
| 228 int frames_received_since_last_key_; | |
| 229 webrtc::VideoCodecMode codec_mode_; | |
| 216 }; | 230 }; |
| 217 | 231 |
| 218 MediaCodecVideoEncoder::~MediaCodecVideoEncoder() { | 232 MediaCodecVideoEncoder::~MediaCodecVideoEncoder() { |
| 219 // Call Release() to ensure no more callbacks to us after we are deleted. | 233 // Call Release() to ensure no more callbacks to us after we are deleted. |
| 220 Release(); | 234 Release(); |
| 221 } | 235 } |
| 222 | 236 |
| 223 MediaCodecVideoEncoder::MediaCodecVideoEncoder( | 237 MediaCodecVideoEncoder::MediaCodecVideoEncoder( |
| 224 JNIEnv* jni, VideoCodecType codecType) : | 238 JNIEnv* jni, VideoCodecType codecType) : |
| 225 codecType_(codecType), | 239 codecType_(codecType), |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 300 if (codec_settings == NULL) { | 314 if (codec_settings == NULL) { |
| 301 ALOGE << "NULL VideoCodec instance"; | 315 ALOGE << "NULL VideoCodec instance"; |
| 302 return WEBRTC_VIDEO_CODEC_ERR_PARAMETER; | 316 return WEBRTC_VIDEO_CODEC_ERR_PARAMETER; |
| 303 } | 317 } |
| 304 // Factory should guard against other codecs being used with us. | 318 // Factory should guard against other codecs being used with us. |
| 305 RTC_CHECK(codec_settings->codecType == codecType_) | 319 RTC_CHECK(codec_settings->codecType == codecType_) |
| 306 << "Unsupported codec " << codec_settings->codecType << " for " | 320 << "Unsupported codec " << codec_settings->codecType << " for " |
| 307 << codecType_; | 321 << codecType_; |
| 308 | 322 |
| 309 ALOGD << "InitEncode request"; | 323 ALOGD << "InitEncode request"; |
| 324 codec_mode_ = codec_settings->mode; | |
| 310 scale_ = webrtc::field_trial::FindFullName( | 325 scale_ = webrtc::field_trial::FindFullName( |
| 311 "WebRTC-MediaCodecVideoEncoder-AutomaticResize") == "Enabled"; | 326 "WebRTC-MediaCodecVideoEncoder-AutomaticResize") == "Enabled"; |
| 312 ALOGD << "Encoder automatic resize " << (scale_ ? "enabled" : "disabled"); | 327 ALOGD << "Encoder automatic resize " << (scale_ ? "enabled" : "disabled"); |
| 313 if (scale_) { | 328 if (scale_) { |
| 314 if (codecType_ == kVideoCodecVP8) { | 329 if (codecType_ == kVideoCodecVP8) { |
| 315 // QP is obtained from VP8-bitstream for HW, so the QP corresponds to the | 330 // QP is obtained from VP8-bitstream for HW, so the QP corresponds to the |
| 316 // (internal) range: [0, 127]. And we cannot change QP_max in HW, so it is | 331 // (internal) range: [0, 127]. And we cannot change QP_max in HW, so it is |
| 317 // always = 127. Note that in SW, QP is that of the user-level range [0, | 332 // always = 127. Note that in SW, QP is that of the user-level range [0, |
| 318 // 63]. | 333 // 63]. |
| 319 const int kMaxQp = 127; | 334 const int kMaxQp = 127; |
| (...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 451 current_encoding_time_ms_ = 0; | 466 current_encoding_time_ms_ = 0; |
| 452 last_input_timestamp_ms_ = -1; | 467 last_input_timestamp_ms_ = -1; |
| 453 last_output_timestamp_ms_ = -1; | 468 last_output_timestamp_ms_ = -1; |
| 454 output_timestamp_ = 0; | 469 output_timestamp_ = 0; |
| 455 output_render_time_ms_ = 0; | 470 output_render_time_ms_ = 0; |
| 456 timestamps_.clear(); | 471 timestamps_.clear(); |
| 457 render_times_ms_.clear(); | 472 render_times_ms_.clear(); |
| 458 frame_rtc_times_ms_.clear(); | 473 frame_rtc_times_ms_.clear(); |
| 459 drop_next_input_frame_ = false; | 474 drop_next_input_frame_ = false; |
| 460 picture_id_ = static_cast<uint16_t>(rand()) & 0x7FFF; | 475 picture_id_ = static_cast<uint16_t>(rand()) & 0x7FFF; |
| 476 last_frame_received_ms_ = -1; | |
| 477 frames_received_since_last_key_ = kMinKeyFrameInterval; | |
| 461 | 478 |
| 462 // We enforce no extra stride/padding in the format creation step. | 479 // We enforce no extra stride/padding in the format creation step. |
| 463 jobject j_video_codec_enum = JavaEnumFromIndex( | 480 jobject j_video_codec_enum = JavaEnumFromIndex( |
| 464 jni, "MediaCodecVideoEncoder$VideoCodecType", codecType_); | 481 jni, "MediaCodecVideoEncoder$VideoCodecType", codecType_); |
| 465 const bool encode_status = jni->CallBooleanMethod( | 482 const bool encode_status = jni->CallBooleanMethod( |
| 466 *j_media_codec_video_encoder_, j_init_encode_method_, | 483 *j_media_codec_video_encoder_, j_init_encode_method_, |
| 467 j_video_codec_enum, width, height, kbps, fps); | 484 j_video_codec_enum, width, height, kbps, fps); |
| 468 if (!encode_status) { | 485 if (!encode_status) { |
| 469 ALOGE << "Failed to configure encoder."; | 486 ALOGE << "Failed to configure encoder."; |
| 470 return WEBRTC_VIDEO_CODEC_ERROR; | 487 return WEBRTC_VIDEO_CODEC_ERROR; |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 517 const webrtc::VideoFrame& frame, | 534 const webrtc::VideoFrame& frame, |
| 518 const std::vector<webrtc::FrameType>* frame_types) { | 535 const std::vector<webrtc::FrameType>* frame_types) { |
| 519 RTC_DCHECK(codec_thread_checker_.CalledOnValidThread()); | 536 RTC_DCHECK(codec_thread_checker_.CalledOnValidThread()); |
| 520 JNIEnv* jni = AttachCurrentThreadIfNeeded(); | 537 JNIEnv* jni = AttachCurrentThreadIfNeeded(); |
| 521 ScopedLocalRefFrame local_ref_frame(jni); | 538 ScopedLocalRefFrame local_ref_frame(jni); |
| 522 | 539 |
| 523 if (!inited_) { | 540 if (!inited_) { |
| 524 return WEBRTC_VIDEO_CODEC_UNINITIALIZED; | 541 return WEBRTC_VIDEO_CODEC_UNINITIALIZED; |
| 525 } | 542 } |
| 526 | 543 |
| 544 bool send_key_frame = false; | |
| 545 if (codecType_ == kVideoCodecVP8 && codec_mode_ == webrtc::kRealtimeVideo) { | |
| 546 ++frames_received_since_last_key_; | |
| 547 int64_t now_ms = GetCurrentTimeMs(); | |
| 548 if (last_frame_received_ms_ != -1 && | |
| 549 (now_ms - last_frame_received_ms_) > kFrameDiffThresholdMs) { | |
| 550 if (frames_received_since_last_key_ > kMinKeyFrameInterval) { | |
|
stefan-webrtc
2016/01/18 20:02:36
What if there are two camera switches close to eac
åsapersson
2016/01/19 12:22:17
Yes will not work if there are two camera switches
| |
| 551 ALOGD << "Send key, frame diff: " << (now_ms - last_frame_received_ms_); | |
| 552 send_key_frame = true; | |
| 553 } | |
| 554 frames_received_since_last_key_ = 0; | |
| 555 } | |
| 556 last_frame_received_ms_ = now_ms; | |
| 557 } | |
| 558 | |
| 527 frames_received_++; | 559 frames_received_++; |
| 528 if (!DeliverPendingOutputs(jni)) { | 560 if (!DeliverPendingOutputs(jni)) { |
| 529 if (!ResetCodecOnCodecThread()) | 561 if (!ResetCodecOnCodecThread()) |
| 530 return WEBRTC_VIDEO_CODEC_ERROR; | 562 return WEBRTC_VIDEO_CODEC_ERROR; |
| 531 } | 563 } |
| 532 | 564 |
| 533 if (drop_next_input_frame_) { | 565 if (drop_next_input_frame_) { |
| 534 ALOGW << "Encoder drop frame - failed callback."; | 566 ALOGW << "Encoder drop frame - failed callback."; |
| 535 drop_next_input_frame_ = false; | 567 drop_next_input_frame_ = false; |
| 536 return WEBRTC_VIDEO_CODEC_OK; | 568 return WEBRTC_VIDEO_CODEC_OK; |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 582 | 614 |
| 583 last_input_timestamp_ms_ = | 615 last_input_timestamp_ms_ = |
| 584 current_timestamp_us_ / rtc::kNumMicrosecsPerMillisec; | 616 current_timestamp_us_ / rtc::kNumMicrosecsPerMillisec; |
| 585 frames_in_queue_++; | 617 frames_in_queue_++; |
| 586 | 618 |
| 587 // Save input image timestamps for later output | 619 // Save input image timestamps for later output |
| 588 timestamps_.push_back(input_frame.timestamp()); | 620 timestamps_.push_back(input_frame.timestamp()); |
| 589 render_times_ms_.push_back(input_frame.render_time_ms()); | 621 render_times_ms_.push_back(input_frame.render_time_ms()); |
| 590 frame_rtc_times_ms_.push_back(GetCurrentTimeMs()); | 622 frame_rtc_times_ms_.push_back(GetCurrentTimeMs()); |
| 591 | 623 |
| 592 const bool key_frame = frame_types->front() != webrtc::kVideoFrameDelta; | 624 const bool key_frame = |
| 625 frame_types->front() != webrtc::kVideoFrameDelta || send_key_frame; | |
|
stefan-webrtc
2016/01/18 20:02:36
Why isn't this == kVideoFrameKey? Now we will gene
åsapersson
2016/01/19 12:22:17
Right seems a bit wrong, not sure about the reason
| |
| 593 const bool encode_status = | 626 const bool encode_status = |
| 594 EncodeByteBufferOnCodecThread(jni, key_frame, input_frame, | 627 EncodeByteBufferOnCodecThread(jni, key_frame, input_frame, |
| 595 j_input_buffer_index); | 628 j_input_buffer_index); |
| 596 | 629 |
| 597 current_timestamp_us_ += rtc::kNumMicrosecsPerSec / last_set_fps_; | 630 current_timestamp_us_ += rtc::kNumMicrosecsPerSec / last_set_fps_; |
| 598 | 631 |
| 599 if (!encode_status || !DeliverPendingOutputs(jni)) { | 632 if (!encode_status || !DeliverPendingOutputs(jni)) { |
| 600 ALOGE << "Failed deliver pending outputs."; | 633 ALOGE << "Failed deliver pending outputs."; |
| 601 ResetCodecOnCodecThread(); | 634 ResetCodecOnCodecThread(); |
| 602 return WEBRTC_VIDEO_CODEC_ERROR; | 635 return WEBRTC_VIDEO_CODEC_ERROR; |
| (...skipping 405 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1008 } | 1041 } |
| 1009 | 1042 |
| 1010 void MediaCodecVideoEncoderFactory::DestroyVideoEncoder( | 1043 void MediaCodecVideoEncoderFactory::DestroyVideoEncoder( |
| 1011 webrtc::VideoEncoder* encoder) { | 1044 webrtc::VideoEncoder* encoder) { |
| 1012 ALOGD << "Destroy video encoder."; | 1045 ALOGD << "Destroy video encoder."; |
| 1013 delete encoder; | 1046 delete encoder; |
| 1014 } | 1047 } |
| 1015 | 1048 |
| 1016 } // namespace webrtc_jni | 1049 } // namespace webrtc_jni |
| 1017 | 1050 |
| OLD | NEW |