| 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 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 43 #include "webrtc/sdk/android/src/jni/androidmediacodeccommon.h" | 43 #include "webrtc/sdk/android/src/jni/androidmediacodeccommon.h" |
| 44 #include "webrtc/sdk/android/src/jni/classreferenceholder.h" | 44 #include "webrtc/sdk/android/src/jni/classreferenceholder.h" |
| 45 #include "webrtc/sdk/android/src/jni/jni_helpers.h" | 45 #include "webrtc/sdk/android/src/jni/jni_helpers.h" |
| 46 #include "webrtc/sdk/android/src/jni/native_handle_impl.h" | 46 #include "webrtc/sdk/android/src/jni/native_handle_impl.h" |
| 47 #include "webrtc/system_wrappers/include/field_trial.h" | 47 #include "webrtc/system_wrappers/include/field_trial.h" |
| 48 | 48 |
| 49 using rtc::Bind; | 49 using rtc::Bind; |
| 50 using rtc::Thread; | 50 using rtc::Thread; |
| 51 using rtc::ThreadManager; | 51 using rtc::ThreadManager; |
| 52 | 52 |
| 53 using webrtc::CodecSpecificInfo; | 53 namespace webrtc { |
| 54 using webrtc::EncodedImage; | 54 namespace jni { |
| 55 using webrtc::VideoFrame; | |
| 56 using webrtc::RTPFragmentationHeader; | |
| 57 using webrtc::VideoCodec; | |
| 58 using webrtc::VideoCodecType; | |
| 59 using webrtc::kVideoCodecH264; | |
| 60 using webrtc::kVideoCodecVP8; | |
| 61 using webrtc::kVideoCodecVP9; | |
| 62 using webrtc::QualityScaler; | |
| 63 | |
| 64 namespace webrtc_jni { | |
| 65 | 55 |
| 66 // Maximum supported HW video encoder fps. | 56 // Maximum supported HW video encoder fps. |
| 67 #define MAX_VIDEO_FPS 30 | 57 #define MAX_VIDEO_FPS 30 |
| 68 // Maximum allowed fps value in SetRates() call. | 58 // Maximum allowed fps value in SetRates() call. |
| 69 #define MAX_ALLOWED_VIDEO_FPS 60 | 59 #define MAX_ALLOWED_VIDEO_FPS 60 |
| 70 // Maximum allowed frames in encoder input queue. | 60 // Maximum allowed frames in encoder input queue. |
| 71 #define MAX_ENCODER_Q_SIZE 2 | 61 #define MAX_ENCODER_Q_SIZE 2 |
| 72 // Maximum amount of dropped frames caused by full encoder queue - exceeding | 62 // Maximum amount of dropped frames caused by full encoder queue - exceeding |
| 73 // this threshold means that encoder probably got stuck and need to be reset. | 63 // this threshold means that encoder probably got stuck and need to be reset. |
| 74 #define ENCODER_STALL_FRAMEDROP_THRESHOLD 60 | 64 #define ENCODER_STALL_FRAMEDROP_THRESHOLD 60 |
| (...skipping 11 matching lines...) Expand all Loading... |
| 86 #define ALOGE LOG_TAG(rtc::LS_ERROR, TAG_ENCODER) | 76 #define ALOGE LOG_TAG(rtc::LS_ERROR, TAG_ENCODER) |
| 87 | 77 |
| 88 namespace { | 78 namespace { |
| 89 // Maximum time limit between incoming frames before requesting a key frame. | 79 // Maximum time limit between incoming frames before requesting a key frame. |
| 90 const size_t kFrameDiffThresholdMs = 350; | 80 const size_t kFrameDiffThresholdMs = 350; |
| 91 const int kMinKeyFrameInterval = 6; | 81 const int kMinKeyFrameInterval = 6; |
| 92 const char kH264HighProfileFieldTrial[] = "WebRTC-H264HighProfile"; | 82 const char kH264HighProfileFieldTrial[] = "WebRTC-H264HighProfile"; |
| 93 const char kCustomQPThresholdsFieldTrial[] = "WebRTC-CustomQPThresholds"; | 83 const char kCustomQPThresholdsFieldTrial[] = "WebRTC-CustomQPThresholds"; |
| 94 } // namespace | 84 } // namespace |
| 95 | 85 |
| 96 // MediaCodecVideoEncoder is a webrtc::VideoEncoder implementation that uses | 86 // MediaCodecVideoEncoder is a VideoEncoder implementation that uses |
| 97 // Android's MediaCodec SDK API behind the scenes to implement (hopefully) | 87 // Android's MediaCodec SDK API behind the scenes to implement (hopefully) |
| 98 // HW-backed video encode. This C++ class is implemented as a very thin shim, | 88 // HW-backed video encode. This C++ class is implemented as a very thin shim, |
| 99 // delegating all of the interesting work to org.webrtc.MediaCodecVideoEncoder. | 89 // delegating all of the interesting work to org.webrtc.MediaCodecVideoEncoder. |
| 100 // MediaCodecVideoEncoder must be operated on a single task queue, currently | 90 // MediaCodecVideoEncoder must be operated on a single task queue, currently |
| 101 // this is the encoder queue from ViE encoder. | 91 // this is the encoder queue from ViE encoder. |
| 102 class MediaCodecVideoEncoder : public webrtc::VideoEncoder { | 92 class MediaCodecVideoEncoder : public VideoEncoder { |
| 103 public: | 93 public: |
| 104 virtual ~MediaCodecVideoEncoder(); | 94 virtual ~MediaCodecVideoEncoder(); |
| 105 MediaCodecVideoEncoder(JNIEnv* jni, | 95 MediaCodecVideoEncoder(JNIEnv* jni, |
| 106 const cricket::VideoCodec& codec, | 96 const cricket::VideoCodec& codec, |
| 107 jobject egl_context); | 97 jobject egl_context); |
| 108 | 98 |
| 109 // webrtc::VideoEncoder implementation. | 99 // VideoEncoder implementation. |
| 110 int32_t InitEncode(const webrtc::VideoCodec* codec_settings, | 100 int32_t InitEncode(const VideoCodec* codec_settings, |
| 111 int32_t /* number_of_cores */, | 101 int32_t /* number_of_cores */, |
| 112 size_t /* max_payload_size */) override; | 102 size_t /* max_payload_size */) override; |
| 113 int32_t Encode(const webrtc::VideoFrame& input_image, | 103 int32_t Encode(const VideoFrame& input_image, |
| 114 const webrtc::CodecSpecificInfo* /* codec_specific_info */, | 104 const CodecSpecificInfo* /* codec_specific_info */, |
| 115 const std::vector<webrtc::FrameType>* frame_types) override; | 105 const std::vector<FrameType>* frame_types) override; |
| 116 int32_t RegisterEncodeCompleteCallback( | 106 int32_t RegisterEncodeCompleteCallback( |
| 117 webrtc::EncodedImageCallback* callback) override; | 107 EncodedImageCallback* callback) override; |
| 118 int32_t Release() override; | 108 int32_t Release() override; |
| 119 int32_t SetChannelParameters(uint32_t /* packet_loss */, | 109 int32_t SetChannelParameters(uint32_t /* packet_loss */, |
| 120 int64_t /* rtt */) override; | 110 int64_t /* rtt */) override; |
| 121 int32_t SetRateAllocation(const webrtc::BitrateAllocation& rate_allocation, | 111 int32_t SetRateAllocation(const BitrateAllocation& rate_allocation, |
| 122 uint32_t frame_rate) override; | 112 uint32_t frame_rate) override; |
| 123 | 113 |
| 124 bool SupportsNativeHandle() const override { return egl_context_ != nullptr; } | 114 bool SupportsNativeHandle() const override { return egl_context_ != nullptr; } |
| 125 const char* ImplementationName() const override; | 115 const char* ImplementationName() const override; |
| 126 | 116 |
| 127 // Fills the input buffer with data from the buffers passed as parameters. | 117 // Fills the input buffer with data from the buffers passed as parameters. |
| 128 bool FillInputBuffer(JNIEnv* jni, | 118 bool FillInputBuffer(JNIEnv* jni, |
| 129 int input_buffer_index, | 119 int input_buffer_index, |
| 130 uint8_t const* buffer_y, | 120 uint8_t const* buffer_y, |
| 131 int stride_y, | 121 int stride_y, |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 163 // previously-current values are reused instead of the passed parameters | 153 // previously-current values are reused instead of the passed parameters |
| 164 // (makes it easier to reason about thread-safety). | 154 // (makes it easier to reason about thread-safety). |
| 165 int32_t InitEncodeInternal(int width, | 155 int32_t InitEncodeInternal(int width, |
| 166 int height, | 156 int height, |
| 167 int kbps, | 157 int kbps, |
| 168 int fps, | 158 int fps, |
| 169 bool use_surface); | 159 bool use_surface); |
| 170 // Reconfigure to match |frame| in width, height. Also reconfigures the | 160 // Reconfigure to match |frame| in width, height. Also reconfigures the |
| 171 // encoder if |frame| is a texture/byte buffer and the encoder is initialized | 161 // encoder if |frame| is a texture/byte buffer and the encoder is initialized |
| 172 // for byte buffer/texture. Returns false if reconfiguring fails. | 162 // for byte buffer/texture. Returns false if reconfiguring fails. |
| 173 bool MaybeReconfigureEncoder(JNIEnv* jni, const webrtc::VideoFrame& frame); | 163 bool MaybeReconfigureEncoder(JNIEnv* jni, const VideoFrame& frame); |
| 174 | 164 |
| 175 // Returns true if the frame is a texture frame and we should use surface | 165 // Returns true if the frame is a texture frame and we should use surface |
| 176 // based encoding. | 166 // based encoding. |
| 177 bool IsTextureFrame(JNIEnv* jni, const webrtc::VideoFrame& frame); | 167 bool IsTextureFrame(JNIEnv* jni, const VideoFrame& frame); |
| 178 | 168 |
| 179 bool EncodeByteBuffer(JNIEnv* jni, | 169 bool EncodeByteBuffer(JNIEnv* jni, |
| 180 bool key_frame, | 170 bool key_frame, |
| 181 const webrtc::VideoFrame& frame, | 171 const VideoFrame& frame, |
| 182 int input_buffer_index); | 172 int input_buffer_index); |
| 183 bool EncodeTexture(JNIEnv* jni, | 173 bool EncodeTexture(JNIEnv* jni, bool key_frame, const VideoFrame& frame); |
| 184 bool key_frame, | |
| 185 const webrtc::VideoFrame& frame); | |
| 186 // Encodes a new style org.webrtc.VideoFrame. Might be a I420 or a texture | 174 // Encodes a new style org.webrtc.VideoFrame. Might be a I420 or a texture |
| 187 // frame. | 175 // frame. |
| 188 bool EncodeJavaFrame(JNIEnv* jni, | 176 bool EncodeJavaFrame(JNIEnv* jni, |
| 189 bool key_frame, | 177 bool key_frame, |
| 190 jobject frame, | 178 jobject frame, |
| 191 int input_buffer_index); | 179 int input_buffer_index); |
| 192 | 180 |
| 193 // Helper accessors for MediaCodecVideoEncoder$OutputBufferInfo members. | 181 // Helper accessors for MediaCodecVideoEncoder$OutputBufferInfo members. |
| 194 int GetOutputBufferInfoIndex(JNIEnv* jni, jobject j_output_buffer_info); | 182 int GetOutputBufferInfoIndex(JNIEnv* jni, jobject j_output_buffer_info); |
| 195 jobject GetOutputBufferInfoBuffer(JNIEnv* jni, jobject j_output_buffer_info); | 183 jobject GetOutputBufferInfoBuffer(JNIEnv* jni, jobject j_output_buffer_info); |
| (...skipping 16 matching lines...) Expand all Loading... |
| 212 // Mutex for protecting inited_. It is only used for correctness checking on | 200 // Mutex for protecting inited_. It is only used for correctness checking on |
| 213 // debug build. It is used for checking that encoder has been released in the | 201 // debug build. It is used for checking that encoder has been released in the |
| 214 // destructor. Because this might happen on a different thread, we need a | 202 // destructor. Because this might happen on a different thread, we need a |
| 215 // mutex. | 203 // mutex. |
| 216 rtc::CriticalSection inited_crit_; | 204 rtc::CriticalSection inited_crit_; |
| 217 #endif | 205 #endif |
| 218 | 206 |
| 219 // Type of video codec. | 207 // Type of video codec. |
| 220 const cricket::VideoCodec codec_; | 208 const cricket::VideoCodec codec_; |
| 221 | 209 |
| 222 webrtc::EncodedImageCallback* callback_; | 210 EncodedImageCallback* callback_; |
| 223 | 211 |
| 224 // State that is constant for the lifetime of this object once the ctor | 212 // State that is constant for the lifetime of this object once the ctor |
| 225 // returns. | 213 // returns. |
| 226 rtc::SequencedTaskChecker encoder_queue_checker_; | 214 rtc::SequencedTaskChecker encoder_queue_checker_; |
| 227 ScopedGlobalRef<jclass> j_media_codec_video_encoder_class_; | 215 ScopedGlobalRef<jclass> j_media_codec_video_encoder_class_; |
| 228 ScopedGlobalRef<jobject> j_media_codec_video_encoder_; | 216 ScopedGlobalRef<jobject> j_media_codec_video_encoder_; |
| 229 jmethodID j_init_encode_method_; | 217 jmethodID j_init_encode_method_; |
| 230 jmethodID j_get_input_buffers_method_; | 218 jmethodID j_get_input_buffers_method_; |
| 231 jmethodID j_dequeue_input_buffer_method_; | 219 jmethodID j_dequeue_input_buffer_method_; |
| 232 jmethodID j_encode_buffer_method_; | 220 jmethodID j_encode_buffer_method_; |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 266 int current_encoding_time_ms_; // Overall encoding time in the current second | 254 int current_encoding_time_ms_; // Overall encoding time in the current second |
| 267 int64_t last_input_timestamp_ms_; // Timestamp of last received yuv frame. | 255 int64_t last_input_timestamp_ms_; // Timestamp of last received yuv frame. |
| 268 int64_t last_output_timestamp_ms_; // Timestamp of last encoded frame. | 256 int64_t last_output_timestamp_ms_; // Timestamp of last encoded frame. |
| 269 // Holds the task while the polling loop is paused. | 257 // Holds the task while the polling loop is paused. |
| 270 std::unique_ptr<rtc::QueuedTask> encode_task_; | 258 std::unique_ptr<rtc::QueuedTask> encode_task_; |
| 271 | 259 |
| 272 struct InputFrameInfo { | 260 struct InputFrameInfo { |
| 273 InputFrameInfo(int64_t encode_start_time, | 261 InputFrameInfo(int64_t encode_start_time, |
| 274 int32_t frame_timestamp, | 262 int32_t frame_timestamp, |
| 275 int64_t frame_render_time_ms, | 263 int64_t frame_render_time_ms, |
| 276 webrtc::VideoRotation rotation) | 264 VideoRotation rotation) |
| 277 : encode_start_time(encode_start_time), | 265 : encode_start_time(encode_start_time), |
| 278 frame_timestamp(frame_timestamp), | 266 frame_timestamp(frame_timestamp), |
| 279 frame_render_time_ms(frame_render_time_ms), | 267 frame_render_time_ms(frame_render_time_ms), |
| 280 rotation(rotation) {} | 268 rotation(rotation) {} |
| 281 // Time when video frame is sent to encoder input. | 269 // Time when video frame is sent to encoder input. |
| 282 const int64_t encode_start_time; | 270 const int64_t encode_start_time; |
| 283 | 271 |
| 284 // Input frame information. | 272 // Input frame information. |
| 285 const int32_t frame_timestamp; | 273 const int32_t frame_timestamp; |
| 286 const int64_t frame_render_time_ms; | 274 const int64_t frame_render_time_ms; |
| 287 const webrtc::VideoRotation rotation; | 275 const VideoRotation rotation; |
| 288 }; | 276 }; |
| 289 std::list<InputFrameInfo> input_frame_infos_; | 277 std::list<InputFrameInfo> input_frame_infos_; |
| 290 int32_t output_timestamp_; // Last output frame timestamp from | 278 int32_t output_timestamp_; // Last output frame timestamp from |
| 291 // |input_frame_infos_|. | 279 // |input_frame_infos_|. |
| 292 int64_t output_render_time_ms_; // Last output frame render time from | 280 int64_t output_render_time_ms_; // Last output frame render time from |
| 293 // |input_frame_infos_|. | 281 // |input_frame_infos_|. |
| 294 webrtc::VideoRotation output_rotation_; // Last output frame rotation from | 282 VideoRotation output_rotation_; // Last output frame rotation from |
| 295 // |input_frame_infos_|. | 283 // |input_frame_infos_|. |
| 296 | 284 |
| 297 // Frame size in bytes fed to MediaCodec. | 285 // Frame size in bytes fed to MediaCodec. |
| 298 int yuv_size_; | 286 int yuv_size_; |
| 299 // True only when between a callback_->OnEncodedImage() call return a positive | 287 // True only when between a callback_->OnEncodedImage() call return a positive |
| 300 // value and the next Encode() call being ignored. | 288 // value and the next Encode() call being ignored. |
| 301 bool drop_next_input_frame_; | 289 bool drop_next_input_frame_; |
| 302 bool scale_; | 290 bool scale_; |
| 303 webrtc::H264::Profile profile_; | 291 H264::Profile profile_; |
| 304 // Global references; must be deleted in Release(). | 292 // Global references; must be deleted in Release(). |
| 305 std::vector<jobject> input_buffers_; | 293 std::vector<jobject> input_buffers_; |
| 306 webrtc::H264BitstreamParser h264_bitstream_parser_; | 294 H264BitstreamParser h264_bitstream_parser_; |
| 307 | 295 |
| 308 // VP9 variables to populate codec specific structure. | 296 // VP9 variables to populate codec specific structure. |
| 309 webrtc::GofInfoVP9 gof_; // Contains each frame's temporal information for | 297 GofInfoVP9 gof_; // Contains each frame's temporal information for |
| 310 // non-flexible VP9 mode. | 298 // non-flexible VP9 mode. |
| 311 size_t gof_idx_; | 299 size_t gof_idx_; |
| 312 | 300 |
| 313 // EGL context - owned by factory, should not be allocated/destroyed | 301 // EGL context - owned by factory, should not be allocated/destroyed |
| 314 // by MediaCodecVideoEncoder. | 302 // by MediaCodecVideoEncoder. |
| 315 jobject egl_context_; | 303 jobject egl_context_; |
| 316 | 304 |
| 317 // Temporary fix for VP8. | 305 // Temporary fix for VP8. |
| 318 // Sends a key frame if frames are largely spaced apart (possibly | 306 // Sends a key frame if frames are largely spaced apart (possibly |
| 319 // corresponding to a large image change). | 307 // corresponding to a large image change). |
| 320 int64_t last_frame_received_ms_; | 308 int64_t last_frame_received_ms_; |
| 321 int frames_received_since_last_key_; | 309 int frames_received_since_last_key_; |
| 322 webrtc::VideoCodecMode codec_mode_; | 310 VideoCodecMode codec_mode_; |
| 323 | 311 |
| 324 // RTP state. | 312 // RTP state. |
| 325 uint16_t picture_id_; | 313 uint16_t picture_id_; |
| 326 uint8_t tl0_pic_idx_; | 314 uint8_t tl0_pic_idx_; |
| 327 | 315 |
| 328 bool sw_fallback_required_; | 316 bool sw_fallback_required_; |
| 329 | 317 |
| 330 // All other member variables should be before WeakPtrFactory. Valid only from | 318 // All other member variables should be before WeakPtrFactory. Valid only from |
| 331 // InitEncode to Release. | 319 // InitEncode to Release. |
| 332 std::unique_ptr<rtc::WeakPtrFactory<MediaCodecVideoEncoder>> weak_factory_; | 320 std::unique_ptr<rtc::WeakPtrFactory<MediaCodecVideoEncoder>> weak_factory_; |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 405 jni, j_output_buffer_info_class, "buffer", "Ljava/nio/ByteBuffer;"); | 393 jni, j_output_buffer_info_class, "buffer", "Ljava/nio/ByteBuffer;"); |
| 406 j_info_is_key_frame_field_ = | 394 j_info_is_key_frame_field_ = |
| 407 GetFieldID(jni, j_output_buffer_info_class, "isKeyFrame", "Z"); | 395 GetFieldID(jni, j_output_buffer_info_class, "isKeyFrame", "Z"); |
| 408 j_info_presentation_timestamp_us_field_ = GetFieldID( | 396 j_info_presentation_timestamp_us_field_ = GetFieldID( |
| 409 jni, j_output_buffer_info_class, "presentationTimestampUs", "J"); | 397 jni, j_output_buffer_info_class, "presentationTimestampUs", "J"); |
| 410 if (CheckException(jni)) { | 398 if (CheckException(jni)) { |
| 411 ALOGW << "MediaCodecVideoEncoder ctor failed."; | 399 ALOGW << "MediaCodecVideoEncoder ctor failed."; |
| 412 ProcessHWError(true /* reset_if_fallback_unavailable */); | 400 ProcessHWError(true /* reset_if_fallback_unavailable */); |
| 413 } | 401 } |
| 414 | 402 |
| 415 webrtc::Random random(rtc::TimeMicros()); | 403 Random random(rtc::TimeMicros()); |
| 416 picture_id_ = random.Rand<uint16_t>() & 0x7FFF; | 404 picture_id_ = random.Rand<uint16_t>() & 0x7FFF; |
| 417 tl0_pic_idx_ = random.Rand<uint8_t>(); | 405 tl0_pic_idx_ = random.Rand<uint8_t>(); |
| 418 } | 406 } |
| 419 | 407 |
| 420 int32_t MediaCodecVideoEncoder::InitEncode( | 408 int32_t MediaCodecVideoEncoder::InitEncode(const VideoCodec* codec_settings, |
| 421 const webrtc::VideoCodec* codec_settings, | 409 int32_t /* number_of_cores */, |
| 422 int32_t /* number_of_cores */, | 410 size_t /* max_payload_size */) { |
| 423 size_t /* max_payload_size */) { | |
| 424 RTC_DCHECK_CALLED_SEQUENTIALLY(&encoder_queue_checker_); | 411 RTC_DCHECK_CALLED_SEQUENTIALLY(&encoder_queue_checker_); |
| 425 if (codec_settings == NULL) { | 412 if (codec_settings == NULL) { |
| 426 ALOGE << "NULL VideoCodec instance"; | 413 ALOGE << "NULL VideoCodec instance"; |
| 427 return WEBRTC_VIDEO_CODEC_ERR_PARAMETER; | 414 return WEBRTC_VIDEO_CODEC_ERR_PARAMETER; |
| 428 } | 415 } |
| 429 // Factory should guard against other codecs being used with us. | 416 // Factory should guard against other codecs being used with us. |
| 430 const VideoCodecType codec_type = GetCodecType(); | 417 const VideoCodecType codec_type = GetCodecType(); |
| 431 RTC_CHECK(codec_settings->codecType == codec_type) | 418 RTC_CHECK(codec_settings->codecType == codec_type) |
| 432 << "Unsupported codec " << codec_settings->codecType << " for " | 419 << "Unsupported codec " << codec_settings->codecType << " for " |
| 433 << codec_type; | 420 << codec_type; |
| (...skipping 11 matching lines...) Expand all Loading... |
| 445 } else if (codec_type == kVideoCodecVP9) { | 432 } else if (codec_type == kVideoCodecVP9) { |
| 446 scale_ = codec_settings->VP9().automaticResizeOn; | 433 scale_ = codec_settings->VP9().automaticResizeOn; |
| 447 } else { | 434 } else { |
| 448 scale_ = true; | 435 scale_ = true; |
| 449 } | 436 } |
| 450 | 437 |
| 451 ALOGD << "InitEncode request: " << init_width << " x " << init_height; | 438 ALOGD << "InitEncode request: " << init_width << " x " << init_height; |
| 452 ALOGD << "Encoder automatic resize " << (scale_ ? "enabled" : "disabled"); | 439 ALOGD << "Encoder automatic resize " << (scale_ ? "enabled" : "disabled"); |
| 453 | 440 |
| 454 // Check allowed H.264 profile | 441 // Check allowed H.264 profile |
| 455 profile_ = webrtc::H264::Profile::kProfileBaseline; | 442 profile_ = H264::Profile::kProfileBaseline; |
| 456 if (codec_type == kVideoCodecH264) { | 443 if (codec_type == kVideoCodecH264) { |
| 457 const rtc::Optional<webrtc::H264::ProfileLevelId> profile_level_id = | 444 const rtc::Optional<H264::ProfileLevelId> profile_level_id = |
| 458 webrtc::H264::ParseSdpProfileLevelId(codec_.params); | 445 H264::ParseSdpProfileLevelId(codec_.params); |
| 459 RTC_DCHECK(profile_level_id); | 446 RTC_DCHECK(profile_level_id); |
| 460 profile_ = profile_level_id->profile; | 447 profile_ = profile_level_id->profile; |
| 461 ALOGD << "H.264 profile: " << profile_; | 448 ALOGD << "H.264 profile: " << profile_; |
| 462 } | 449 } |
| 463 | 450 |
| 464 return InitEncodeInternal( | 451 return InitEncodeInternal( |
| 465 init_width, init_height, codec_settings->startBitrate, | 452 init_width, init_height, codec_settings->startBitrate, |
| 466 codec_settings->maxFramerate, codec_settings->expect_encode_from_texture); | 453 codec_settings->maxFramerate, codec_settings->expect_encode_from_texture); |
| 467 } | 454 } |
| 468 | 455 |
| (...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 546 return false; | 533 return false; |
| 547 } | 534 } |
| 548 | 535 |
| 549 int32_t MediaCodecVideoEncoder::ProcessHWErrorOnEncode() { | 536 int32_t MediaCodecVideoEncoder::ProcessHWErrorOnEncode() { |
| 550 ProcessHWError(true /* reset_if_fallback_unavailable */); | 537 ProcessHWError(true /* reset_if_fallback_unavailable */); |
| 551 return sw_fallback_required_ ? WEBRTC_VIDEO_CODEC_FALLBACK_SOFTWARE | 538 return sw_fallback_required_ ? WEBRTC_VIDEO_CODEC_FALLBACK_SOFTWARE |
| 552 : WEBRTC_VIDEO_CODEC_ERROR; | 539 : WEBRTC_VIDEO_CODEC_ERROR; |
| 553 } | 540 } |
| 554 | 541 |
| 555 VideoCodecType MediaCodecVideoEncoder::GetCodecType() const { | 542 VideoCodecType MediaCodecVideoEncoder::GetCodecType() const { |
| 556 return webrtc::PayloadStringToCodecType(codec_.name); | 543 return PayloadStringToCodecType(codec_.name); |
| 557 } | 544 } |
| 558 | 545 |
| 559 int32_t MediaCodecVideoEncoder::InitEncodeInternal(int width, | 546 int32_t MediaCodecVideoEncoder::InitEncodeInternal(int width, |
| 560 int height, | 547 int height, |
| 561 int kbps, | 548 int kbps, |
| 562 int fps, | 549 int fps, |
| 563 bool use_surface) { | 550 bool use_surface) { |
| 564 RTC_DCHECK_CALLED_SEQUENTIALLY(&encoder_queue_checker_); | 551 RTC_DCHECK_CALLED_SEQUENTIALLY(&encoder_queue_checker_); |
| 565 if (sw_fallback_required_) { | 552 if (sw_fallback_required_) { |
| 566 return WEBRTC_VIDEO_CODEC_OK; | 553 return WEBRTC_VIDEO_CODEC_OK; |
| (...skipping 28 matching lines...) Expand all Loading... |
| 595 current_bytes_ = 0; | 582 current_bytes_ = 0; |
| 596 current_acc_qp_ = 0; | 583 current_acc_qp_ = 0; |
| 597 current_encoding_time_ms_ = 0; | 584 current_encoding_time_ms_ = 0; |
| 598 last_input_timestamp_ms_ = -1; | 585 last_input_timestamp_ms_ = -1; |
| 599 last_output_timestamp_ms_ = -1; | 586 last_output_timestamp_ms_ = -1; |
| 600 output_timestamp_ = 0; | 587 output_timestamp_ = 0; |
| 601 output_render_time_ms_ = 0; | 588 output_render_time_ms_ = 0; |
| 602 input_frame_infos_.clear(); | 589 input_frame_infos_.clear(); |
| 603 drop_next_input_frame_ = false; | 590 drop_next_input_frame_ = false; |
| 604 use_surface_ = use_surface; | 591 use_surface_ = use_surface; |
| 605 gof_.SetGofInfoVP9(webrtc::TemporalStructureMode::kTemporalStructureMode1); | 592 gof_.SetGofInfoVP9(TemporalStructureMode::kTemporalStructureMode1); |
| 606 gof_idx_ = 0; | 593 gof_idx_ = 0; |
| 607 last_frame_received_ms_ = -1; | 594 last_frame_received_ms_ = -1; |
| 608 frames_received_since_last_key_ = kMinKeyFrameInterval; | 595 frames_received_since_last_key_ = kMinKeyFrameInterval; |
| 609 | 596 |
| 610 // We enforce no extra stride/padding in the format creation step. | 597 // We enforce no extra stride/padding in the format creation step. |
| 611 jobject j_video_codec_enum = JavaEnumFromIndexAndClassName( | 598 jobject j_video_codec_enum = JavaEnumFromIndexAndClassName( |
| 612 jni, "MediaCodecVideoEncoder$VideoCodecType", codec_type); | 599 jni, "MediaCodecVideoEncoder$VideoCodecType", codec_type); |
| 613 const bool encode_status = jni->CallBooleanMethod( | 600 const bool encode_status = jni->CallBooleanMethod( |
| 614 *j_media_codec_video_encoder_, j_init_encode_method_, j_video_codec_enum, | 601 *j_media_codec_video_encoder_, j_init_encode_method_, j_video_codec_enum, |
| 615 profile_, width, height, kbps, fps, | 602 profile_, width, height, kbps, fps, |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 679 #endif | 666 #endif |
| 680 inited_ = true; | 667 inited_ = true; |
| 681 } | 668 } |
| 682 weak_factory_.reset(new rtc::WeakPtrFactory<MediaCodecVideoEncoder>(this)); | 669 weak_factory_.reset(new rtc::WeakPtrFactory<MediaCodecVideoEncoder>(this)); |
| 683 encode_task_.reset(new EncodeTask(weak_factory_->GetWeakPtr())); | 670 encode_task_.reset(new EncodeTask(weak_factory_->GetWeakPtr())); |
| 684 | 671 |
| 685 return WEBRTC_VIDEO_CODEC_OK; | 672 return WEBRTC_VIDEO_CODEC_OK; |
| 686 } | 673 } |
| 687 | 674 |
| 688 int32_t MediaCodecVideoEncoder::Encode( | 675 int32_t MediaCodecVideoEncoder::Encode( |
| 689 const webrtc::VideoFrame& frame, | 676 const VideoFrame& frame, |
| 690 const webrtc::CodecSpecificInfo* /* codec_specific_info */, | 677 const CodecSpecificInfo* /* codec_specific_info */, |
| 691 const std::vector<webrtc::FrameType>* frame_types) { | 678 const std::vector<FrameType>* frame_types) { |
| 692 RTC_DCHECK_CALLED_SEQUENTIALLY(&encoder_queue_checker_); | 679 RTC_DCHECK_CALLED_SEQUENTIALLY(&encoder_queue_checker_); |
| 693 if (sw_fallback_required_) | 680 if (sw_fallback_required_) |
| 694 return WEBRTC_VIDEO_CODEC_FALLBACK_SOFTWARE; | 681 return WEBRTC_VIDEO_CODEC_FALLBACK_SOFTWARE; |
| 695 JNIEnv* jni = AttachCurrentThreadIfNeeded(); | 682 JNIEnv* jni = AttachCurrentThreadIfNeeded(); |
| 696 ScopedLocalRefFrame local_ref_frame(jni); | 683 ScopedLocalRefFrame local_ref_frame(jni); |
| 697 const int64_t frame_input_time_ms = rtc::TimeMillis(); | 684 const int64_t frame_input_time_ms = rtc::TimeMillis(); |
| 698 | 685 |
| 699 if (!inited_) { | 686 if (!inited_) { |
| 700 return WEBRTC_VIDEO_CODEC_UNINITIALIZED; | 687 return WEBRTC_VIDEO_CODEC_UNINITIALIZED; |
| 701 } | 688 } |
| 702 | 689 |
| 703 bool send_key_frame = false; | 690 bool send_key_frame = false; |
| 704 if (codec_mode_ == webrtc::kRealtimeVideo) { | 691 if (codec_mode_ == kRealtimeVideo) { |
| 705 ++frames_received_since_last_key_; | 692 ++frames_received_since_last_key_; |
| 706 int64_t now_ms = rtc::TimeMillis(); | 693 int64_t now_ms = rtc::TimeMillis(); |
| 707 if (last_frame_received_ms_ != -1 && | 694 if (last_frame_received_ms_ != -1 && |
| 708 (now_ms - last_frame_received_ms_) > kFrameDiffThresholdMs) { | 695 (now_ms - last_frame_received_ms_) > kFrameDiffThresholdMs) { |
| 709 // Add limit to prevent triggering a key for every frame for very low | 696 // Add limit to prevent triggering a key for every frame for very low |
| 710 // framerates (e.g. if frame diff > kFrameDiffThresholdMs). | 697 // framerates (e.g. if frame diff > kFrameDiffThresholdMs). |
| 711 if (frames_received_since_last_key_ > kMinKeyFrameInterval) { | 698 if (frames_received_since_last_key_ > kMinKeyFrameInterval) { |
| 712 ALOGD << "Send key, frame diff: " << (now_ms - last_frame_received_ms_); | 699 ALOGD << "Send key, frame diff: " << (now_ms - last_frame_received_ms_); |
| 713 send_key_frame = true; | 700 send_key_frame = true; |
| 714 } | 701 } |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 754 if (consecutive_full_queue_frame_drops_ >= | 741 if (consecutive_full_queue_frame_drops_ >= |
| 755 ENCODER_STALL_FRAMEDROP_THRESHOLD) { | 742 ENCODER_STALL_FRAMEDROP_THRESHOLD) { |
| 756 ALOGE << "Encoder got stuck."; | 743 ALOGE << "Encoder got stuck."; |
| 757 return ProcessHWErrorOnEncode(); | 744 return ProcessHWErrorOnEncode(); |
| 758 } | 745 } |
| 759 frames_dropped_media_encoder_++; | 746 frames_dropped_media_encoder_++; |
| 760 return WEBRTC_VIDEO_CODEC_OK; | 747 return WEBRTC_VIDEO_CODEC_OK; |
| 761 } | 748 } |
| 762 consecutive_full_queue_frame_drops_ = 0; | 749 consecutive_full_queue_frame_drops_ = 0; |
| 763 | 750 |
| 764 rtc::scoped_refptr<webrtc::VideoFrameBuffer> input_buffer( | 751 rtc::scoped_refptr<VideoFrameBuffer> input_buffer(frame.video_frame_buffer()); |
| 765 frame.video_frame_buffer()); | |
| 766 | 752 |
| 767 VideoFrame input_frame(input_buffer, frame.timestamp(), | 753 VideoFrame input_frame(input_buffer, frame.timestamp(), |
| 768 frame.render_time_ms(), frame.rotation()); | 754 frame.render_time_ms(), frame.rotation()); |
| 769 | 755 |
| 770 if (!MaybeReconfigureEncoder(jni, input_frame)) { | 756 if (!MaybeReconfigureEncoder(jni, input_frame)) { |
| 771 ALOGE << "Failed to reconfigure encoder."; | 757 ALOGE << "Failed to reconfigure encoder."; |
| 772 return WEBRTC_VIDEO_CODEC_ERROR; | 758 return WEBRTC_VIDEO_CODEC_ERROR; |
| 773 } | 759 } |
| 774 | 760 |
| 775 const bool key_frame = | 761 const bool key_frame = |
| 776 frame_types->front() != webrtc::kVideoFrameDelta || send_key_frame; | 762 frame_types->front() != kVideoFrameDelta || send_key_frame; |
| 777 bool encode_status = true; | 763 bool encode_status = true; |
| 778 | 764 |
| 779 int j_input_buffer_index = -1; | 765 int j_input_buffer_index = -1; |
| 780 if (!use_surface_) { | 766 if (!use_surface_) { |
| 781 j_input_buffer_index = jni->CallIntMethod(*j_media_codec_video_encoder_, | 767 j_input_buffer_index = jni->CallIntMethod(*j_media_codec_video_encoder_, |
| 782 j_dequeue_input_buffer_method_); | 768 j_dequeue_input_buffer_method_); |
| 783 if (CheckException(jni)) { | 769 if (CheckException(jni)) { |
| 784 ALOGE << "Exception in dequeu input buffer."; | 770 ALOGE << "Exception in dequeu input buffer."; |
| 785 return ProcessHWErrorOnEncode(); | 771 return ProcessHWErrorOnEncode(); |
| 786 } | 772 } |
| 787 if (j_input_buffer_index == -1) { | 773 if (j_input_buffer_index == -1) { |
| 788 // Video codec falls behind - no input buffer available. | 774 // Video codec falls behind - no input buffer available. |
| 789 ALOGW << "Encoder drop frame - no input buffers available"; | 775 ALOGW << "Encoder drop frame - no input buffers available"; |
| 790 if (frames_received_ > 1) { | 776 if (frames_received_ > 1) { |
| 791 current_timestamp_us_ += rtc::kNumMicrosecsPerSec / last_set_fps_; | 777 current_timestamp_us_ += rtc::kNumMicrosecsPerSec / last_set_fps_; |
| 792 frames_dropped_media_encoder_++; | 778 frames_dropped_media_encoder_++; |
| 793 } else { | 779 } else { |
| 794 // Input buffers are not ready after codec initialization, HW is still | 780 // Input buffers are not ready after codec initialization, HW is still |
| 795 // allocating thme - this is expected and should not result in drop | 781 // allocating thme - this is expected and should not result in drop |
| 796 // frame report. | 782 // frame report. |
| 797 frames_received_ = 0; | 783 frames_received_ = 0; |
| 798 } | 784 } |
| 799 return WEBRTC_VIDEO_CODEC_OK; // TODO(fischman): see webrtc bug 2887. | 785 return WEBRTC_VIDEO_CODEC_OK; // TODO(fischman): see webrtc bug 2887. |
| 800 } else if (j_input_buffer_index == -2) { | 786 } else if (j_input_buffer_index == -2) { |
| 801 return ProcessHWErrorOnEncode(); | 787 return ProcessHWErrorOnEncode(); |
| 802 } | 788 } |
| 803 } | 789 } |
| 804 | 790 |
| 805 if (input_frame.video_frame_buffer()->type() != | 791 if (input_frame.video_frame_buffer()->type() != |
| 806 webrtc::VideoFrameBuffer::Type::kNative) { | 792 VideoFrameBuffer::Type::kNative) { |
| 807 encode_status = | 793 encode_status = |
| 808 EncodeByteBuffer(jni, key_frame, input_frame, j_input_buffer_index); | 794 EncodeByteBuffer(jni, key_frame, input_frame, j_input_buffer_index); |
| 809 } else { | 795 } else { |
| 810 AndroidVideoFrameBuffer* android_buffer = | 796 AndroidVideoFrameBuffer* android_buffer = |
| 811 static_cast<AndroidVideoFrameBuffer*>( | 797 static_cast<AndroidVideoFrameBuffer*>( |
| 812 input_frame.video_frame_buffer().get()); | 798 input_frame.video_frame_buffer().get()); |
| 813 switch (android_buffer->android_type()) { | 799 switch (android_buffer->android_type()) { |
| 814 case AndroidVideoFrameBuffer::AndroidType::kTextureBuffer: | 800 case AndroidVideoFrameBuffer::AndroidType::kTextureBuffer: |
| 815 encode_status = EncodeTexture(jni, key_frame, input_frame); | 801 encode_status = EncodeTexture(jni, key_frame, input_frame); |
| 816 break; | 802 break; |
| (...skipping 28 matching lines...) Expand all Loading... |
| 845 rtc::TaskQueue::Current()->PostDelayedTask(std::move(encode_task_), | 831 rtc::TaskQueue::Current()->PostDelayedTask(std::move(encode_task_), |
| 846 kMediaCodecPollMs); | 832 kMediaCodecPollMs); |
| 847 } | 833 } |
| 848 | 834 |
| 849 if (!DeliverPendingOutputs(jni)) { | 835 if (!DeliverPendingOutputs(jni)) { |
| 850 return ProcessHWErrorOnEncode(); | 836 return ProcessHWErrorOnEncode(); |
| 851 } | 837 } |
| 852 return WEBRTC_VIDEO_CODEC_OK; | 838 return WEBRTC_VIDEO_CODEC_OK; |
| 853 } | 839 } |
| 854 | 840 |
| 855 bool MediaCodecVideoEncoder::MaybeReconfigureEncoder( | 841 bool MediaCodecVideoEncoder::MaybeReconfigureEncoder(JNIEnv* jni, |
| 856 JNIEnv* jni, | 842 const VideoFrame& frame) { |
| 857 const webrtc::VideoFrame& frame) { | |
| 858 RTC_DCHECK_CALLED_SEQUENTIALLY(&encoder_queue_checker_); | 843 RTC_DCHECK_CALLED_SEQUENTIALLY(&encoder_queue_checker_); |
| 859 | 844 |
| 860 bool is_texture = IsTextureFrame(jni, frame); | 845 bool is_texture = IsTextureFrame(jni, frame); |
| 861 const bool reconfigure_due_to_format = is_texture != use_surface_; | 846 const bool reconfigure_due_to_format = is_texture != use_surface_; |
| 862 const bool reconfigure_due_to_size = | 847 const bool reconfigure_due_to_size = |
| 863 frame.width() != width_ || frame.height() != height_; | 848 frame.width() != width_ || frame.height() != height_; |
| 864 | 849 |
| 865 if (reconfigure_due_to_format) { | 850 if (reconfigure_due_to_format) { |
| 866 ALOGD << "Reconfigure encoder due to format change. " | 851 ALOGD << "Reconfigure encoder due to format change. " |
| 867 << (use_surface_ ? | 852 << (use_surface_ ? |
| (...skipping 13 matching lines...) Expand all Loading... |
| 881 if (!reconfigure_due_to_format && !reconfigure_due_to_size) | 866 if (!reconfigure_due_to_format && !reconfigure_due_to_size) |
| 882 return true; | 867 return true; |
| 883 | 868 |
| 884 Release(); | 869 Release(); |
| 885 | 870 |
| 886 return InitEncodeInternal(width_, height_, 0, 0, is_texture) == | 871 return InitEncodeInternal(width_, height_, 0, 0, is_texture) == |
| 887 WEBRTC_VIDEO_CODEC_OK; | 872 WEBRTC_VIDEO_CODEC_OK; |
| 888 } | 873 } |
| 889 | 874 |
| 890 bool MediaCodecVideoEncoder::IsTextureFrame(JNIEnv* jni, | 875 bool MediaCodecVideoEncoder::IsTextureFrame(JNIEnv* jni, |
| 891 const webrtc::VideoFrame& frame) { | 876 const VideoFrame& frame) { |
| 892 if (frame.video_frame_buffer()->type() != | 877 if (frame.video_frame_buffer()->type() != VideoFrameBuffer::Type::kNative) { |
| 893 webrtc::VideoFrameBuffer::Type::kNative) { | |
| 894 return false; | 878 return false; |
| 895 } | 879 } |
| 896 | 880 |
| 897 AndroidVideoFrameBuffer* android_buffer = | 881 AndroidVideoFrameBuffer* android_buffer = |
| 898 static_cast<AndroidVideoFrameBuffer*>(frame.video_frame_buffer().get()); | 882 static_cast<AndroidVideoFrameBuffer*>(frame.video_frame_buffer().get()); |
| 899 switch (android_buffer->android_type()) { | 883 switch (android_buffer->android_type()) { |
| 900 case AndroidVideoFrameBuffer::AndroidType::kTextureBuffer: | 884 case AndroidVideoFrameBuffer::AndroidType::kTextureBuffer: |
| 901 return true; | 885 return true; |
| 902 case AndroidVideoFrameBuffer::AndroidType::kJavaBuffer: | 886 case AndroidVideoFrameBuffer::AndroidType::kJavaBuffer: |
| 903 return jni->IsInstanceOf(static_cast<AndroidVideoBuffer*>(android_buffer) | 887 return jni->IsInstanceOf(static_cast<AndroidVideoBuffer*>(android_buffer) |
| 904 ->video_frame_buffer(), | 888 ->video_frame_buffer(), |
| 905 *j_video_frame_texture_buffer_class_); | 889 *j_video_frame_texture_buffer_class_); |
| 906 default: | 890 default: |
| 907 RTC_NOTREACHED(); | 891 RTC_NOTREACHED(); |
| 908 return false; | 892 return false; |
| 909 } | 893 } |
| 910 } | 894 } |
| 911 | 895 |
| 912 bool MediaCodecVideoEncoder::EncodeByteBuffer(JNIEnv* jni, | 896 bool MediaCodecVideoEncoder::EncodeByteBuffer(JNIEnv* jni, |
| 913 bool key_frame, | 897 bool key_frame, |
| 914 const webrtc::VideoFrame& frame, | 898 const VideoFrame& frame, |
| 915 int input_buffer_index) { | 899 int input_buffer_index) { |
| 916 RTC_DCHECK_CALLED_SEQUENTIALLY(&encoder_queue_checker_); | 900 RTC_DCHECK_CALLED_SEQUENTIALLY(&encoder_queue_checker_); |
| 917 RTC_CHECK(!use_surface_); | 901 RTC_CHECK(!use_surface_); |
| 918 | 902 |
| 919 rtc::scoped_refptr<webrtc::I420BufferInterface> i420_buffer = | 903 rtc::scoped_refptr<I420BufferInterface> i420_buffer = |
| 920 frame.video_frame_buffer()->ToI420(); | 904 frame.video_frame_buffer()->ToI420(); |
| 921 if (!FillInputBuffer(jni, input_buffer_index, i420_buffer->DataY(), | 905 if (!FillInputBuffer(jni, input_buffer_index, i420_buffer->DataY(), |
| 922 i420_buffer->StrideY(), i420_buffer->DataU(), | 906 i420_buffer->StrideY(), i420_buffer->DataU(), |
| 923 i420_buffer->StrideU(), i420_buffer->DataV(), | 907 i420_buffer->StrideU(), i420_buffer->DataV(), |
| 924 i420_buffer->StrideV())) { | 908 i420_buffer->StrideV())) { |
| 925 return false; | 909 return false; |
| 926 } | 910 } |
| 927 bool encode_status = jni->CallBooleanMethod( | 911 bool encode_status = jni->CallBooleanMethod( |
| 928 *j_media_codec_video_encoder_, j_encode_buffer_method_, key_frame, | 912 *j_media_codec_video_encoder_, j_encode_buffer_method_, key_frame, |
| 929 input_buffer_index, yuv_size_, current_timestamp_us_); | 913 input_buffer_index, yuv_size_, current_timestamp_us_); |
| (...skipping 25 matching lines...) Expand all Loading... |
| 955 | 939 |
| 956 RTC_CHECK(!libyuv::ConvertFromI420(buffer_y, stride_y, buffer_u, stride_u, | 940 RTC_CHECK(!libyuv::ConvertFromI420(buffer_y, stride_y, buffer_u, stride_u, |
| 957 buffer_v, stride_v, yuv_buffer, width_, | 941 buffer_v, stride_v, yuv_buffer, width_, |
| 958 width_, height_, encoder_fourcc_)) | 942 width_, height_, encoder_fourcc_)) |
| 959 << "ConvertFromI420 failed"; | 943 << "ConvertFromI420 failed"; |
| 960 return true; | 944 return true; |
| 961 } | 945 } |
| 962 | 946 |
| 963 bool MediaCodecVideoEncoder::EncodeTexture(JNIEnv* jni, | 947 bool MediaCodecVideoEncoder::EncodeTexture(JNIEnv* jni, |
| 964 bool key_frame, | 948 bool key_frame, |
| 965 const webrtc::VideoFrame& frame) { | 949 const VideoFrame& frame) { |
| 966 RTC_DCHECK_CALLED_SEQUENTIALLY(&encoder_queue_checker_); | 950 RTC_DCHECK_CALLED_SEQUENTIALLY(&encoder_queue_checker_); |
| 967 RTC_CHECK(use_surface_); | 951 RTC_CHECK(use_surface_); |
| 968 NativeHandleImpl handle = | 952 NativeHandleImpl handle = |
| 969 static_cast<AndroidTextureBuffer*>(frame.video_frame_buffer().get()) | 953 static_cast<AndroidTextureBuffer*>(frame.video_frame_buffer().get()) |
| 970 ->native_handle_impl(); | 954 ->native_handle_impl(); |
| 971 | 955 |
| 972 jfloatArray sampling_matrix = handle.sampling_matrix.ToJava(jni); | 956 jfloatArray sampling_matrix = handle.sampling_matrix.ToJava(jni); |
| 973 bool encode_status = jni->CallBooleanMethod( | 957 bool encode_status = jni->CallBooleanMethod( |
| 974 *j_media_codec_video_encoder_, j_encode_texture_method_, key_frame, | 958 *j_media_codec_video_encoder_, j_encode_texture_method_, key_frame, |
| 975 handle.oes_texture_id, sampling_matrix, current_timestamp_us_); | 959 handle.oes_texture_id, sampling_matrix, current_timestamp_us_); |
| (...skipping 14 matching lines...) Expand all Loading... |
| 990 jlongFromPointer(this), key_frame, frame, input_buffer_index); | 974 jlongFromPointer(this), key_frame, frame, input_buffer_index); |
| 991 if (CheckException(jni)) { | 975 if (CheckException(jni)) { |
| 992 ALOGE << "Exception in encode frame."; | 976 ALOGE << "Exception in encode frame."; |
| 993 ProcessHWError(true /* reset_if_fallback_unavailable */); | 977 ProcessHWError(true /* reset_if_fallback_unavailable */); |
| 994 return false; | 978 return false; |
| 995 } | 979 } |
| 996 return encode_status; | 980 return encode_status; |
| 997 } | 981 } |
| 998 | 982 |
| 999 int32_t MediaCodecVideoEncoder::RegisterEncodeCompleteCallback( | 983 int32_t MediaCodecVideoEncoder::RegisterEncodeCompleteCallback( |
| 1000 webrtc::EncodedImageCallback* callback) { | 984 EncodedImageCallback* callback) { |
| 1001 RTC_DCHECK_CALLED_SEQUENTIALLY(&encoder_queue_checker_); | 985 RTC_DCHECK_CALLED_SEQUENTIALLY(&encoder_queue_checker_); |
| 1002 JNIEnv* jni = AttachCurrentThreadIfNeeded(); | 986 JNIEnv* jni = AttachCurrentThreadIfNeeded(); |
| 1003 ScopedLocalRefFrame local_ref_frame(jni); | 987 ScopedLocalRefFrame local_ref_frame(jni); |
| 1004 callback_ = callback; | 988 callback_ = callback; |
| 1005 return WEBRTC_VIDEO_CODEC_OK; | 989 return WEBRTC_VIDEO_CODEC_OK; |
| 1006 } | 990 } |
| 1007 | 991 |
| 1008 int32_t MediaCodecVideoEncoder::Release() { | 992 int32_t MediaCodecVideoEncoder::Release() { |
| 1009 RTC_DCHECK_CALLED_SEQUENTIALLY(&encoder_queue_checker_); | 993 RTC_DCHECK_CALLED_SEQUENTIALLY(&encoder_queue_checker_); |
| 1010 if (!inited_) { | 994 if (!inited_) { |
| (...skipping 20 matching lines...) Expand all Loading... |
| 1031 rtc::CritScope lock(&inited_crit_); | 1015 rtc::CritScope lock(&inited_crit_); |
| 1032 #endif | 1016 #endif |
| 1033 inited_ = false; | 1017 inited_ = false; |
| 1034 } | 1018 } |
| 1035 use_surface_ = false; | 1019 use_surface_ = false; |
| 1036 ALOGD << "EncoderRelease done."; | 1020 ALOGD << "EncoderRelease done."; |
| 1037 return WEBRTC_VIDEO_CODEC_OK; | 1021 return WEBRTC_VIDEO_CODEC_OK; |
| 1038 } | 1022 } |
| 1039 | 1023 |
| 1040 int32_t MediaCodecVideoEncoder::SetRateAllocation( | 1024 int32_t MediaCodecVideoEncoder::SetRateAllocation( |
| 1041 const webrtc::BitrateAllocation& rate_allocation, | 1025 const BitrateAllocation& rate_allocation, |
| 1042 uint32_t frame_rate) { | 1026 uint32_t frame_rate) { |
| 1043 RTC_DCHECK_CALLED_SEQUENTIALLY(&encoder_queue_checker_); | 1027 RTC_DCHECK_CALLED_SEQUENTIALLY(&encoder_queue_checker_); |
| 1044 const uint32_t new_bit_rate = rate_allocation.get_sum_kbps(); | 1028 const uint32_t new_bit_rate = rate_allocation.get_sum_kbps(); |
| 1045 if (sw_fallback_required_) | 1029 if (sw_fallback_required_) |
| 1046 return WEBRTC_VIDEO_CODEC_OK; | 1030 return WEBRTC_VIDEO_CODEC_OK; |
| 1047 frame_rate = | 1031 frame_rate = |
| 1048 (frame_rate < MAX_ALLOWED_VIDEO_FPS) ? frame_rate : MAX_ALLOWED_VIDEO_FPS; | 1032 (frame_rate < MAX_ALLOWED_VIDEO_FPS) ? frame_rate : MAX_ALLOWED_VIDEO_FPS; |
| 1049 if (last_set_bitrate_kbps_ == new_bit_rate && last_set_fps_ == frame_rate) { | 1033 if (last_set_bitrate_kbps_ == new_bit_rate && last_set_fps_ == frame_rate) { |
| 1050 return WEBRTC_VIDEO_CODEC_OK; | 1034 return WEBRTC_VIDEO_CODEC_OK; |
| 1051 } | 1035 } |
| (...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1140 uint8_t* payload = reinterpret_cast<uint8_t*>( | 1124 uint8_t* payload = reinterpret_cast<uint8_t*>( |
| 1141 jni->GetDirectBufferAddress(j_output_buffer)); | 1125 jni->GetDirectBufferAddress(j_output_buffer)); |
| 1142 if (CheckException(jni)) { | 1126 if (CheckException(jni)) { |
| 1143 ALOGE << "Exception in get direct buffer address."; | 1127 ALOGE << "Exception in get direct buffer address."; |
| 1144 ProcessHWError(true /* reset_if_fallback_unavailable */); | 1128 ProcessHWError(true /* reset_if_fallback_unavailable */); |
| 1145 return WEBRTC_VIDEO_CODEC_ERROR; | 1129 return WEBRTC_VIDEO_CODEC_ERROR; |
| 1146 } | 1130 } |
| 1147 | 1131 |
| 1148 // Callback - return encoded frame. | 1132 // Callback - return encoded frame. |
| 1149 const VideoCodecType codec_type = GetCodecType(); | 1133 const VideoCodecType codec_type = GetCodecType(); |
| 1150 webrtc::EncodedImageCallback::Result callback_result( | 1134 EncodedImageCallback::Result callback_result( |
| 1151 webrtc::EncodedImageCallback::Result::OK); | 1135 EncodedImageCallback::Result::OK); |
| 1152 if (callback_) { | 1136 if (callback_) { |
| 1153 std::unique_ptr<webrtc::EncodedImage> image( | 1137 std::unique_ptr<EncodedImage> image( |
| 1154 new webrtc::EncodedImage(payload, payload_size, payload_size)); | 1138 new EncodedImage(payload, payload_size, payload_size)); |
| 1155 image->_encodedWidth = width_; | 1139 image->_encodedWidth = width_; |
| 1156 image->_encodedHeight = height_; | 1140 image->_encodedHeight = height_; |
| 1157 image->_timeStamp = output_timestamp_; | 1141 image->_timeStamp = output_timestamp_; |
| 1158 image->capture_time_ms_ = output_render_time_ms_; | 1142 image->capture_time_ms_ = output_render_time_ms_; |
| 1159 image->rotation_ = output_rotation_; | 1143 image->rotation_ = output_rotation_; |
| 1160 image->content_type_ = | 1144 image->content_type_ = (codec_mode_ == VideoCodecMode::kScreensharing) |
| 1161 (codec_mode_ == webrtc::VideoCodecMode::kScreensharing) | 1145 ? VideoContentType::SCREENSHARE |
| 1162 ? webrtc::VideoContentType::SCREENSHARE | 1146 : VideoContentType::UNSPECIFIED; |
| 1163 : webrtc::VideoContentType::UNSPECIFIED; | 1147 image->timing_.flags = TimingFrameFlags::kInvalid; |
| 1164 image->timing_.flags = webrtc::TimingFrameFlags::kInvalid; | 1148 image->_frameType = (key_frame ? kVideoFrameKey : kVideoFrameDelta); |
| 1165 image->_frameType = | |
| 1166 (key_frame ? webrtc::kVideoFrameKey : webrtc::kVideoFrameDelta); | |
| 1167 image->_completeFrame = true; | 1149 image->_completeFrame = true; |
| 1168 webrtc::CodecSpecificInfo info; | 1150 CodecSpecificInfo info; |
| 1169 memset(&info, 0, sizeof(info)); | 1151 memset(&info, 0, sizeof(info)); |
| 1170 info.codecType = codec_type; | 1152 info.codecType = codec_type; |
| 1171 if (codec_type == kVideoCodecVP8) { | 1153 if (codec_type == kVideoCodecVP8) { |
| 1172 info.codecSpecific.VP8.pictureId = picture_id_; | 1154 info.codecSpecific.VP8.pictureId = picture_id_; |
| 1173 info.codecSpecific.VP8.nonReference = false; | 1155 info.codecSpecific.VP8.nonReference = false; |
| 1174 info.codecSpecific.VP8.simulcastIdx = 0; | 1156 info.codecSpecific.VP8.simulcastIdx = 0; |
| 1175 info.codecSpecific.VP8.temporalIdx = webrtc::kNoTemporalIdx; | 1157 info.codecSpecific.VP8.temporalIdx = kNoTemporalIdx; |
| 1176 info.codecSpecific.VP8.layerSync = false; | 1158 info.codecSpecific.VP8.layerSync = false; |
| 1177 info.codecSpecific.VP8.tl0PicIdx = webrtc::kNoTl0PicIdx; | 1159 info.codecSpecific.VP8.tl0PicIdx = kNoTl0PicIdx; |
| 1178 info.codecSpecific.VP8.keyIdx = webrtc::kNoKeyIdx; | 1160 info.codecSpecific.VP8.keyIdx = kNoKeyIdx; |
| 1179 } else if (codec_type == kVideoCodecVP9) { | 1161 } else if (codec_type == kVideoCodecVP9) { |
| 1180 if (key_frame) { | 1162 if (key_frame) { |
| 1181 gof_idx_ = 0; | 1163 gof_idx_ = 0; |
| 1182 } | 1164 } |
| 1183 info.codecSpecific.VP9.picture_id = picture_id_; | 1165 info.codecSpecific.VP9.picture_id = picture_id_; |
| 1184 info.codecSpecific.VP9.inter_pic_predicted = key_frame ? false : true; | 1166 info.codecSpecific.VP9.inter_pic_predicted = key_frame ? false : true; |
| 1185 info.codecSpecific.VP9.flexible_mode = false; | 1167 info.codecSpecific.VP9.flexible_mode = false; |
| 1186 info.codecSpecific.VP9.ss_data_available = key_frame ? true : false; | 1168 info.codecSpecific.VP9.ss_data_available = key_frame ? true : false; |
| 1187 info.codecSpecific.VP9.tl0_pic_idx = tl0_pic_idx_++; | 1169 info.codecSpecific.VP9.tl0_pic_idx = tl0_pic_idx_++; |
| 1188 info.codecSpecific.VP9.temporal_idx = webrtc::kNoTemporalIdx; | 1170 info.codecSpecific.VP9.temporal_idx = kNoTemporalIdx; |
| 1189 info.codecSpecific.VP9.spatial_idx = webrtc::kNoSpatialIdx; | 1171 info.codecSpecific.VP9.spatial_idx = kNoSpatialIdx; |
| 1190 info.codecSpecific.VP9.temporal_up_switch = true; | 1172 info.codecSpecific.VP9.temporal_up_switch = true; |
| 1191 info.codecSpecific.VP9.inter_layer_predicted = false; | 1173 info.codecSpecific.VP9.inter_layer_predicted = false; |
| 1192 info.codecSpecific.VP9.gof_idx = | 1174 info.codecSpecific.VP9.gof_idx = |
| 1193 static_cast<uint8_t>(gof_idx_++ % gof_.num_frames_in_gof); | 1175 static_cast<uint8_t>(gof_idx_++ % gof_.num_frames_in_gof); |
| 1194 info.codecSpecific.VP9.num_spatial_layers = 1; | 1176 info.codecSpecific.VP9.num_spatial_layers = 1; |
| 1195 info.codecSpecific.VP9.spatial_layer_resolution_present = false; | 1177 info.codecSpecific.VP9.spatial_layer_resolution_present = false; |
| 1196 if (info.codecSpecific.VP9.ss_data_available) { | 1178 if (info.codecSpecific.VP9.ss_data_available) { |
| 1197 info.codecSpecific.VP9.spatial_layer_resolution_present = true; | 1179 info.codecSpecific.VP9.spatial_layer_resolution_present = true; |
| 1198 info.codecSpecific.VP9.width[0] = width_; | 1180 info.codecSpecific.VP9.width[0] = width_; |
| 1199 info.codecSpecific.VP9.height[0] = height_; | 1181 info.codecSpecific.VP9.height[0] = height_; |
| 1200 info.codecSpecific.VP9.gof.CopyGofInfoVP9(gof_); | 1182 info.codecSpecific.VP9.gof.CopyGofInfoVP9(gof_); |
| 1201 } | 1183 } |
| 1202 } | 1184 } |
| 1203 picture_id_ = (picture_id_ + 1) & 0x7FFF; | 1185 picture_id_ = (picture_id_ + 1) & 0x7FFF; |
| 1204 | 1186 |
| 1205 // Generate a header describing a single fragment. | 1187 // Generate a header describing a single fragment. |
| 1206 webrtc::RTPFragmentationHeader header; | 1188 RTPFragmentationHeader header; |
| 1207 memset(&header, 0, sizeof(header)); | 1189 memset(&header, 0, sizeof(header)); |
| 1208 if (codec_type == kVideoCodecVP8 || codec_type == kVideoCodecVP9) { | 1190 if (codec_type == kVideoCodecVP8 || codec_type == kVideoCodecVP9) { |
| 1209 header.VerifyAndAllocateFragmentationHeader(1); | 1191 header.VerifyAndAllocateFragmentationHeader(1); |
| 1210 header.fragmentationOffset[0] = 0; | 1192 header.fragmentationOffset[0] = 0; |
| 1211 header.fragmentationLength[0] = image->_length; | 1193 header.fragmentationLength[0] = image->_length; |
| 1212 header.fragmentationPlType[0] = 0; | 1194 header.fragmentationPlType[0] = 0; |
| 1213 header.fragmentationTimeDiff[0] = 0; | 1195 header.fragmentationTimeDiff[0] = 0; |
| 1214 if (codec_type == kVideoCodecVP8) { | 1196 if (codec_type == kVideoCodecVP8) { |
| 1215 int qp; | 1197 int qp; |
| 1216 if (webrtc::vp8::GetQp(payload, payload_size, &qp)) { | 1198 if (vp8::GetQp(payload, payload_size, &qp)) { |
| 1217 current_acc_qp_ += qp; | 1199 current_acc_qp_ += qp; |
| 1218 image->qp_ = qp; | 1200 image->qp_ = qp; |
| 1219 } | 1201 } |
| 1220 } else if (codec_type == kVideoCodecVP9) { | 1202 } else if (codec_type == kVideoCodecVP9) { |
| 1221 int qp; | 1203 int qp; |
| 1222 if (webrtc::vp9::GetQp(payload, payload_size, &qp)) { | 1204 if (vp9::GetQp(payload, payload_size, &qp)) { |
| 1223 current_acc_qp_ += qp; | 1205 current_acc_qp_ += qp; |
| 1224 image->qp_ = qp; | 1206 image->qp_ = qp; |
| 1225 } | 1207 } |
| 1226 } | 1208 } |
| 1227 } else if (codec_type == kVideoCodecH264) { | 1209 } else if (codec_type == kVideoCodecH264) { |
| 1228 h264_bitstream_parser_.ParseBitstream(payload, payload_size); | 1210 h264_bitstream_parser_.ParseBitstream(payload, payload_size); |
| 1229 int qp; | 1211 int qp; |
| 1230 if (h264_bitstream_parser_.GetLastSliceQp(&qp)) { | 1212 if (h264_bitstream_parser_.GetLastSliceQp(&qp)) { |
| 1231 current_acc_qp_ += qp; | 1213 current_acc_qp_ += qp; |
| 1232 image->qp_ = qp; | 1214 image->qp_ = qp; |
| 1233 } | 1215 } |
| 1234 // For H.264 search for start codes. | 1216 // For H.264 search for start codes. |
| 1235 const std::vector<webrtc::H264::NaluIndex> nalu_idxs = | 1217 const std::vector<H264::NaluIndex> nalu_idxs = |
| 1236 webrtc::H264::FindNaluIndices(payload, payload_size); | 1218 H264::FindNaluIndices(payload, payload_size); |
| 1237 if (nalu_idxs.empty()) { | 1219 if (nalu_idxs.empty()) { |
| 1238 ALOGE << "Start code is not found!"; | 1220 ALOGE << "Start code is not found!"; |
| 1239 ALOGE << "Data:" << image->_buffer[0] << " " << image->_buffer[1] | 1221 ALOGE << "Data:" << image->_buffer[0] << " " << image->_buffer[1] |
| 1240 << " " << image->_buffer[2] << " " << image->_buffer[3] | 1222 << " " << image->_buffer[2] << " " << image->_buffer[3] |
| 1241 << " " << image->_buffer[4] << " " << image->_buffer[5]; | 1223 << " " << image->_buffer[4] << " " << image->_buffer[5]; |
| 1242 ProcessHWError(true /* reset_if_fallback_unavailable */); | 1224 ProcessHWError(true /* reset_if_fallback_unavailable */); |
| 1243 return false; | 1225 return false; |
| 1244 } | 1226 } |
| 1245 header.VerifyAndAllocateFragmentationHeader(nalu_idxs.size()); | 1227 header.VerifyAndAllocateFragmentationHeader(nalu_idxs.size()); |
| 1246 for (size_t i = 0; i < nalu_idxs.size(); i++) { | 1228 for (size_t i = 0; i < nalu_idxs.size(); i++) { |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1309 ". QP: " << (current_acc_qp_ / current_frames_divider) << | 1291 ". QP: " << (current_acc_qp_ / current_frames_divider) << |
| 1310 " for last " << statistic_time_ms << " ms."; | 1292 " for last " << statistic_time_ms << " ms."; |
| 1311 stat_start_time_ms_ = rtc::TimeMillis(); | 1293 stat_start_time_ms_ = rtc::TimeMillis(); |
| 1312 current_frames_ = 0; | 1294 current_frames_ = 0; |
| 1313 current_bytes_ = 0; | 1295 current_bytes_ = 0; |
| 1314 current_acc_qp_ = 0; | 1296 current_acc_qp_ = 0; |
| 1315 current_encoding_time_ms_ = 0; | 1297 current_encoding_time_ms_ = 0; |
| 1316 } | 1298 } |
| 1317 } | 1299 } |
| 1318 | 1300 |
| 1319 webrtc::VideoEncoder::ScalingSettings | 1301 VideoEncoder::ScalingSettings MediaCodecVideoEncoder::GetScalingSettings() |
| 1320 MediaCodecVideoEncoder::GetScalingSettings() const { | 1302 const { |
| 1321 if (webrtc::field_trial::IsEnabled(kCustomQPThresholdsFieldTrial)) { | 1303 if (field_trial::IsEnabled(kCustomQPThresholdsFieldTrial)) { |
| 1322 const VideoCodecType codec_type = GetCodecType(); | 1304 const VideoCodecType codec_type = GetCodecType(); |
| 1323 std::string experiment_string = | 1305 std::string experiment_string = |
| 1324 webrtc::field_trial::FindFullName(kCustomQPThresholdsFieldTrial); | 1306 field_trial::FindFullName(kCustomQPThresholdsFieldTrial); |
| 1325 ALOGD << "QP custom thresholds: " << experiment_string << " for codec " | 1307 ALOGD << "QP custom thresholds: " << experiment_string << " for codec " |
| 1326 << codec_type; | 1308 << codec_type; |
| 1327 int low_vp8_qp_threshold; | 1309 int low_vp8_qp_threshold; |
| 1328 int high_vp8_qp_threshold; | 1310 int high_vp8_qp_threshold; |
| 1329 int low_h264_qp_threshold; | 1311 int low_h264_qp_threshold; |
| 1330 int high_h264_qp_threshold; | 1312 int high_h264_qp_threshold; |
| 1331 int parsed_values = sscanf(experiment_string.c_str(), "Enabled-%u,%u,%u,%u", | 1313 int parsed_values = sscanf(experiment_string.c_str(), "Enabled-%u,%u,%u,%u", |
| 1332 &low_vp8_qp_threshold, &high_vp8_qp_threshold, | 1314 &low_vp8_qp_threshold, &high_vp8_qp_threshold, |
| 1333 &low_h264_qp_threshold, &high_h264_qp_threshold); | 1315 &low_h264_qp_threshold, &high_h264_qp_threshold); |
| 1334 if (parsed_values == 4) { | 1316 if (parsed_values == 4) { |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1384 bool is_h264_high_profile_hw_supported = jni->CallStaticBooleanMethod( | 1366 bool is_h264_high_profile_hw_supported = jni->CallStaticBooleanMethod( |
| 1385 j_decoder_class, | 1367 j_decoder_class, |
| 1386 GetStaticMethodID(jni, j_decoder_class, "isH264HighProfileHwSupported", | 1368 GetStaticMethodID(jni, j_decoder_class, "isH264HighProfileHwSupported", |
| 1387 "()Z")); | 1369 "()Z")); |
| 1388 CHECK_EXCEPTION(jni); | 1370 CHECK_EXCEPTION(jni); |
| 1389 if (is_h264_high_profile_hw_supported) { | 1371 if (is_h264_high_profile_hw_supported) { |
| 1390 ALOGD << "H.264 High Profile HW Encoder supported."; | 1372 ALOGD << "H.264 High Profile HW Encoder supported."; |
| 1391 // TODO(magjed): Enumerate actual level instead of using hardcoded level | 1373 // TODO(magjed): Enumerate actual level instead of using hardcoded level |
| 1392 // 3.1. Level 3.1 is 1280x720@30fps which is enough for now. | 1374 // 3.1. Level 3.1 is 1280x720@30fps which is enough for now. |
| 1393 cricket::VideoCodec constrained_high(cricket::kH264CodecName); | 1375 cricket::VideoCodec constrained_high(cricket::kH264CodecName); |
| 1394 const webrtc::H264::ProfileLevelId constrained_high_profile( | 1376 const H264::ProfileLevelId constrained_high_profile( |
| 1395 webrtc::H264::kProfileConstrainedHigh, webrtc::H264::kLevel3_1); | 1377 H264::kProfileConstrainedHigh, H264::kLevel3_1); |
| 1396 constrained_high.SetParam( | 1378 constrained_high.SetParam( |
| 1397 cricket::kH264FmtpProfileLevelId, | 1379 cricket::kH264FmtpProfileLevelId, |
| 1398 *webrtc::H264::ProfileLevelIdToString(constrained_high_profile)); | 1380 *H264::ProfileLevelIdToString(constrained_high_profile)); |
| 1399 constrained_high.SetParam(cricket::kH264FmtpLevelAsymmetryAllowed, "1"); | 1381 constrained_high.SetParam(cricket::kH264FmtpLevelAsymmetryAllowed, "1"); |
| 1400 constrained_high.SetParam(cricket::kH264FmtpPacketizationMode, "1"); | 1382 constrained_high.SetParam(cricket::kH264FmtpPacketizationMode, "1"); |
| 1401 supported_codecs_with_h264_hp_.push_back(constrained_high); | 1383 supported_codecs_with_h264_hp_.push_back(constrained_high); |
| 1402 } | 1384 } |
| 1403 | 1385 |
| 1404 bool is_h264_hw_supported = jni->CallStaticBooleanMethod( | 1386 bool is_h264_hw_supported = jni->CallStaticBooleanMethod( |
| 1405 j_encoder_class, | 1387 j_encoder_class, |
| 1406 GetStaticMethodID(jni, j_encoder_class, "isH264HwSupported", "()Z")); | 1388 GetStaticMethodID(jni, j_encoder_class, "isH264HwSupported", "()Z")); |
| 1407 CHECK_EXCEPTION(jni); | 1389 CHECK_EXCEPTION(jni); |
| 1408 if (is_h264_hw_supported) { | 1390 if (is_h264_hw_supported) { |
| 1409 ALOGD << "H.264 HW Encoder supported."; | 1391 ALOGD << "H.264 HW Encoder supported."; |
| 1410 // TODO(magjed): Push Constrained High profile as well when negotiation is | 1392 // TODO(magjed): Push Constrained High profile as well when negotiation is |
| 1411 // ready, http://crbug/webrtc/6337. We can negotiate Constrained High | 1393 // ready, http://crbug/webrtc/6337. We can negotiate Constrained High |
| 1412 // profile as long as we have decode support for it and still send Baseline | 1394 // profile as long as we have decode support for it and still send Baseline |
| 1413 // since Baseline is a subset of the High profile. | 1395 // since Baseline is a subset of the High profile. |
| 1414 cricket::VideoCodec constrained_baseline(cricket::kH264CodecName); | 1396 cricket::VideoCodec constrained_baseline(cricket::kH264CodecName); |
| 1415 const webrtc::H264::ProfileLevelId constrained_baseline_profile( | 1397 const H264::ProfileLevelId constrained_baseline_profile( |
| 1416 webrtc::H264::kProfileConstrainedBaseline, webrtc::H264::kLevel3_1); | 1398 H264::kProfileConstrainedBaseline, H264::kLevel3_1); |
| 1417 constrained_baseline.SetParam( | 1399 constrained_baseline.SetParam( |
| 1418 cricket::kH264FmtpProfileLevelId, | 1400 cricket::kH264FmtpProfileLevelId, |
| 1419 *webrtc::H264::ProfileLevelIdToString(constrained_baseline_profile)); | 1401 *H264::ProfileLevelIdToString(constrained_baseline_profile)); |
| 1420 constrained_baseline.SetParam(cricket::kH264FmtpLevelAsymmetryAllowed, "1"); | 1402 constrained_baseline.SetParam(cricket::kH264FmtpLevelAsymmetryAllowed, "1"); |
| 1421 constrained_baseline.SetParam(cricket::kH264FmtpPacketizationMode, "1"); | 1403 constrained_baseline.SetParam(cricket::kH264FmtpPacketizationMode, "1"); |
| 1422 supported_codecs_.push_back(constrained_baseline); | 1404 supported_codecs_.push_back(constrained_baseline); |
| 1423 supported_codecs_with_h264_hp_.push_back(constrained_baseline); | 1405 supported_codecs_with_h264_hp_.push_back(constrained_baseline); |
| 1424 } | 1406 } |
| 1425 } | 1407 } |
| 1426 | 1408 |
| 1427 MediaCodecVideoEncoderFactory::~MediaCodecVideoEncoderFactory() { | 1409 MediaCodecVideoEncoderFactory::~MediaCodecVideoEncoderFactory() { |
| 1428 ALOGD << "MediaCodecVideoEncoderFactory dtor"; | 1410 ALOGD << "MediaCodecVideoEncoderFactory dtor"; |
| 1429 if (egl_context_) { | 1411 if (egl_context_) { |
| 1430 JNIEnv* jni = AttachCurrentThreadIfNeeded(); | 1412 JNIEnv* jni = AttachCurrentThreadIfNeeded(); |
| 1431 jni->DeleteGlobalRef(egl_context_); | 1413 jni->DeleteGlobalRef(egl_context_); |
| 1432 } | 1414 } |
| 1433 } | 1415 } |
| 1434 | 1416 |
| 1435 void MediaCodecVideoEncoderFactory::SetEGLContext( | 1417 void MediaCodecVideoEncoderFactory::SetEGLContext( |
| 1436 JNIEnv* jni, jobject egl_context) { | 1418 JNIEnv* jni, jobject egl_context) { |
| 1437 ALOGD << "MediaCodecVideoEncoderFactory::SetEGLContext"; | 1419 ALOGD << "MediaCodecVideoEncoderFactory::SetEGLContext"; |
| 1438 if (egl_context_) { | 1420 if (egl_context_) { |
| 1439 jni->DeleteGlobalRef(egl_context_); | 1421 jni->DeleteGlobalRef(egl_context_); |
| 1440 egl_context_ = nullptr; | 1422 egl_context_ = nullptr; |
| 1441 } | 1423 } |
| 1442 egl_context_ = jni->NewGlobalRef(egl_context); | 1424 egl_context_ = jni->NewGlobalRef(egl_context); |
| 1443 if (CheckException(jni)) { | 1425 if (CheckException(jni)) { |
| 1444 ALOGE << "error calling NewGlobalRef for EGL Context."; | 1426 ALOGE << "error calling NewGlobalRef for EGL Context."; |
| 1445 } | 1427 } |
| 1446 } | 1428 } |
| 1447 | 1429 |
| 1448 webrtc::VideoEncoder* MediaCodecVideoEncoderFactory::CreateVideoEncoder( | 1430 VideoEncoder* MediaCodecVideoEncoderFactory::CreateVideoEncoder( |
| 1449 const cricket::VideoCodec& codec) { | 1431 const cricket::VideoCodec& codec) { |
| 1450 if (supported_codecs().empty()) { | 1432 if (supported_codecs().empty()) { |
| 1451 ALOGW << "No HW video encoder for codec " << codec.name; | 1433 ALOGW << "No HW video encoder for codec " << codec.name; |
| 1452 return nullptr; | 1434 return nullptr; |
| 1453 } | 1435 } |
| 1454 if (FindMatchingCodec(supported_codecs(), codec)) { | 1436 if (FindMatchingCodec(supported_codecs(), codec)) { |
| 1455 ALOGD << "Create HW video encoder for " << codec.name; | 1437 ALOGD << "Create HW video encoder for " << codec.name; |
| 1456 JNIEnv* jni = AttachCurrentThreadIfNeeded(); | 1438 JNIEnv* jni = AttachCurrentThreadIfNeeded(); |
| 1457 ScopedLocalRefFrame local_ref_frame(jni); | 1439 ScopedLocalRefFrame local_ref_frame(jni); |
| 1458 return new MediaCodecVideoEncoder(jni, codec, egl_context_); | 1440 return new MediaCodecVideoEncoder(jni, codec, egl_context_); |
| 1459 } | 1441 } |
| 1460 ALOGW << "Can not find HW video encoder for type " << codec.name; | 1442 ALOGW << "Can not find HW video encoder for type " << codec.name; |
| 1461 return nullptr; | 1443 return nullptr; |
| 1462 } | 1444 } |
| 1463 | 1445 |
| 1464 const std::vector<cricket::VideoCodec>& | 1446 const std::vector<cricket::VideoCodec>& |
| 1465 MediaCodecVideoEncoderFactory::supported_codecs() const { | 1447 MediaCodecVideoEncoderFactory::supported_codecs() const { |
| 1466 if (webrtc::field_trial::IsEnabled(kH264HighProfileFieldTrial)) { | 1448 if (field_trial::IsEnabled(kH264HighProfileFieldTrial)) { |
| 1467 return supported_codecs_with_h264_hp_; | 1449 return supported_codecs_with_h264_hp_; |
| 1468 } else { | 1450 } else { |
| 1469 return supported_codecs_; | 1451 return supported_codecs_; |
| 1470 } | 1452 } |
| 1471 } | 1453 } |
| 1472 | 1454 |
| 1473 void MediaCodecVideoEncoderFactory::DestroyVideoEncoder( | 1455 void MediaCodecVideoEncoderFactory::DestroyVideoEncoder(VideoEncoder* encoder) { |
| 1474 webrtc::VideoEncoder* encoder) { | |
| 1475 ALOGD << "Destroy video encoder."; | 1456 ALOGD << "Destroy video encoder."; |
| 1476 delete encoder; | 1457 delete encoder; |
| 1477 } | 1458 } |
| 1478 | 1459 |
| 1479 JNI_FUNCTION_DECLARATION(void, | 1460 JNI_FUNCTION_DECLARATION(void, |
| 1480 MediaCodecVideoEncoder_nativeFillBuffer, | 1461 MediaCodecVideoEncoder_nativeFillBuffer, |
| 1481 JNIEnv* jni, | 1462 JNIEnv* jni, |
| 1482 jclass, | 1463 jclass, |
| 1483 jlong native_encoder, | 1464 jlong native_encoder, |
| 1484 jint input_buffer, | 1465 jint input_buffer, |
| 1485 jobject j_buffer_y, | 1466 jobject j_buffer_y, |
| 1486 jint stride_y, | 1467 jint stride_y, |
| 1487 jobject j_buffer_u, | 1468 jobject j_buffer_u, |
| 1488 jint stride_u, | 1469 jint stride_u, |
| 1489 jobject j_buffer_v, | 1470 jobject j_buffer_v, |
| 1490 jint stride_v) { | 1471 jint stride_v) { |
| 1491 uint8_t* buffer_y = | 1472 uint8_t* buffer_y = |
| 1492 static_cast<uint8_t*>(jni->GetDirectBufferAddress(j_buffer_y)); | 1473 static_cast<uint8_t*>(jni->GetDirectBufferAddress(j_buffer_y)); |
| 1493 uint8_t* buffer_u = | 1474 uint8_t* buffer_u = |
| 1494 static_cast<uint8_t*>(jni->GetDirectBufferAddress(j_buffer_u)); | 1475 static_cast<uint8_t*>(jni->GetDirectBufferAddress(j_buffer_u)); |
| 1495 uint8_t* buffer_v = | 1476 uint8_t* buffer_v = |
| 1496 static_cast<uint8_t*>(jni->GetDirectBufferAddress(j_buffer_v)); | 1477 static_cast<uint8_t*>(jni->GetDirectBufferAddress(j_buffer_v)); |
| 1497 | 1478 |
| 1498 reinterpret_cast<MediaCodecVideoEncoder*>(native_encoder) | 1479 reinterpret_cast<MediaCodecVideoEncoder*>(native_encoder) |
| 1499 ->FillInputBuffer(jni, input_buffer, buffer_y, stride_y, buffer_u, | 1480 ->FillInputBuffer(jni, input_buffer, buffer_y, stride_y, buffer_u, |
| 1500 stride_u, buffer_v, stride_v); | 1481 stride_u, buffer_v, stride_v); |
| 1501 } | 1482 } |
| 1502 | 1483 |
| 1503 } // namespace webrtc_jni | 1484 } // namespace jni |
| 1485 } // namespace webrtc |
| OLD | NEW |