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 |
11 // NOTICE: androidmediaencoder_jni.h must be included before | 11 // NOTICE: androidmediaencoder_jni.h must be included before |
12 // androidmediacodeccommon.h to avoid build errors. | 12 // androidmediacodeccommon.h to avoid build errors. |
13 #include "webrtc/sdk/android/src/jni/androidmediaencoder_jni.h" | 13 #include "webrtc/sdk/android/src/jni/androidmediaencoder_jni.h" |
14 | 14 |
15 #include <algorithm> | 15 #include <algorithm> |
16 #include <list> | 16 #include <list> |
17 #include <memory> | 17 #include <memory> |
18 #include <string> | 18 #include <string> |
19 #include <utility> | 19 #include <utility> |
20 | 20 |
21 #include "third_party/libyuv/include/libyuv/convert.h" | 21 #include "third_party/libyuv/include/libyuv/convert.h" |
22 #include "third_party/libyuv/include/libyuv/convert_from.h" | 22 #include "third_party/libyuv/include/libyuv/convert_from.h" |
23 #include "third_party/libyuv/include/libyuv/video_common.h" | 23 #include "third_party/libyuv/include/libyuv/video_common.h" |
24 #include "webrtc/api/video_codecs/video_encoder.h" | 24 #include "webrtc/api/video_codecs/video_encoder.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/random.h" | |
28 #include "webrtc/base/sequenced_task_checker.h" | 29 #include "webrtc/base/sequenced_task_checker.h" |
29 #include "webrtc/base/task_queue.h" | 30 #include "webrtc/base/task_queue.h" |
30 #include "webrtc/base/thread.h" | 31 #include "webrtc/base/thread.h" |
31 #include "webrtc/base/timeutils.h" | 32 #include "webrtc/base/timeutils.h" |
32 #include "webrtc/base/weak_ptr.h" | 33 #include "webrtc/base/weak_ptr.h" |
33 #include "webrtc/common_types.h" | 34 #include "webrtc/common_types.h" |
34 #include "webrtc/common_video/h264/h264_bitstream_parser.h" | 35 #include "webrtc/common_video/h264/h264_bitstream_parser.h" |
35 #include "webrtc/common_video/h264/h264_common.h" | 36 #include "webrtc/common_video/h264/h264_common.h" |
36 #include "webrtc/common_video/h264/profile_level_id.h" | 37 #include "webrtc/common_video/h264/profile_level_id.h" |
37 #include "webrtc/media/engine/internalencoderfactory.h" | 38 #include "webrtc/media/engine/internalencoderfactory.h" |
(...skipping 177 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
215 jfieldID j_info_index_field_; | 216 jfieldID j_info_index_field_; |
216 jfieldID j_info_buffer_field_; | 217 jfieldID j_info_buffer_field_; |
217 jfieldID j_info_is_key_frame_field_; | 218 jfieldID j_info_is_key_frame_field_; |
218 jfieldID j_info_presentation_timestamp_us_field_; | 219 jfieldID j_info_presentation_timestamp_us_field_; |
219 | 220 |
220 // State that is valid only between InitEncode() and the next Release(). | 221 // State that is valid only between InitEncode() and the next Release(). |
221 int width_; // Frame width in pixels. | 222 int width_; // Frame width in pixels. |
222 int height_; // Frame height in pixels. | 223 int height_; // Frame height in pixels. |
223 bool inited_; | 224 bool inited_; |
224 bool use_surface_; | 225 bool use_surface_; |
225 uint16_t picture_id_; | |
226 enum libyuv::FourCC encoder_fourcc_; // Encoder color space format. | 226 enum libyuv::FourCC encoder_fourcc_; // Encoder color space format. |
227 int last_set_bitrate_kbps_; // Last-requested bitrate in kbps. | 227 int last_set_bitrate_kbps_; // Last-requested bitrate in kbps. |
228 int last_set_fps_; // Last-requested frame rate. | 228 int last_set_fps_; // Last-requested frame rate. |
229 int64_t current_timestamp_us_; // Current frame timestamps in us. | 229 int64_t current_timestamp_us_; // Current frame timestamps in us. |
230 int frames_received_; // Number of frames received by encoder. | 230 int frames_received_; // Number of frames received by encoder. |
231 int frames_encoded_; // Number of frames encoded by encoder. | 231 int frames_encoded_; // Number of frames encoded by encoder. |
232 int frames_dropped_media_encoder_; // Number of frames dropped by encoder. | 232 int frames_dropped_media_encoder_; // Number of frames dropped by encoder. |
233 // Number of dropped frames caused by full queue. | 233 // Number of dropped frames caused by full queue. |
234 int consecutive_full_queue_frame_drops_; | 234 int consecutive_full_queue_frame_drops_; |
235 int64_t stat_start_time_ms_; // Start time for statistics. | 235 int64_t stat_start_time_ms_; // Start time for statistics. |
(...skipping 23 matching lines...) Expand all Loading... | |
259 const int64_t frame_render_time_ms; | 259 const int64_t frame_render_time_ms; |
260 const webrtc::VideoRotation rotation; | 260 const webrtc::VideoRotation rotation; |
261 }; | 261 }; |
262 std::list<InputFrameInfo> input_frame_infos_; | 262 std::list<InputFrameInfo> input_frame_infos_; |
263 int32_t output_timestamp_; // Last output frame timestamp from | 263 int32_t output_timestamp_; // Last output frame timestamp from |
264 // |input_frame_infos_|. | 264 // |input_frame_infos_|. |
265 int64_t output_render_time_ms_; // Last output frame render time from | 265 int64_t output_render_time_ms_; // Last output frame render time from |
266 // |input_frame_infos_|. | 266 // |input_frame_infos_|. |
267 webrtc::VideoRotation output_rotation_; // Last output frame rotation from | 267 webrtc::VideoRotation output_rotation_; // Last output frame rotation from |
268 // |input_frame_infos_|. | 268 // |input_frame_infos_|. |
269 | |
269 // Frame size in bytes fed to MediaCodec. | 270 // Frame size in bytes fed to MediaCodec. |
270 int yuv_size_; | 271 int yuv_size_; |
271 // True only when between a callback_->OnEncodedImage() call return a positive | 272 // True only when between a callback_->OnEncodedImage() call return a positive |
272 // value and the next Encode() call being ignored. | 273 // value and the next Encode() call being ignored. |
273 bool drop_next_input_frame_; | 274 bool drop_next_input_frame_; |
274 bool scale_; | 275 bool scale_; |
275 // Global references; must be deleted in Release(). | 276 // Global references; must be deleted in Release(). |
276 std::vector<jobject> input_buffers_; | 277 std::vector<jobject> input_buffers_; |
277 webrtc::H264BitstreamParser h264_bitstream_parser_; | 278 webrtc::H264BitstreamParser h264_bitstream_parser_; |
278 | 279 |
279 // VP9 variables to populate codec specific structure. | 280 // VP9 variables to populate codec specific structure. |
280 webrtc::GofInfoVP9 gof_; // Contains each frame's temporal information for | 281 webrtc::GofInfoVP9 gof_; // Contains each frame's temporal information for |
281 // non-flexible VP9 mode. | 282 // non-flexible VP9 mode. |
282 uint8_t tl0_pic_idx_; | |
283 size_t gof_idx_; | 283 size_t gof_idx_; |
284 | 284 |
285 // EGL context - owned by factory, should not be allocated/destroyed | 285 // EGL context - owned by factory, should not be allocated/destroyed |
286 // by MediaCodecVideoEncoder. | 286 // by MediaCodecVideoEncoder. |
287 jobject egl_context_; | 287 jobject egl_context_; |
288 | 288 |
289 // Temporary fix for VP8. | 289 // Temporary fix for VP8. |
290 // Sends a key frame if frames are largely spaced apart (possibly | 290 // Sends a key frame if frames are largely spaced apart (possibly |
291 // corresponding to a large image change). | 291 // corresponding to a large image change). |
292 int64_t last_frame_received_ms_; | 292 int64_t last_frame_received_ms_; |
293 int frames_received_since_last_key_; | 293 int frames_received_since_last_key_; |
294 webrtc::VideoCodecMode codec_mode_; | 294 webrtc::VideoCodecMode codec_mode_; |
295 | 295 |
296 // Used to randomize the initial |picture_id_| and |tl0_pic_idx_|. | |
297 webrtc::Random random_; | |
magjed_webrtc
2017/04/21 15:11:18
I would like to not keep this as a member variable
brandtr
2017/04/24 07:53:47
Good idea. Done.
| |
298 | |
299 // RTP state. | |
300 uint16_t picture_id_; | |
301 uint8_t tl0_pic_idx_; | |
302 | |
296 bool sw_fallback_required_; | 303 bool sw_fallback_required_; |
297 | 304 |
298 // All other member variables should be before WeakPtrFactory. Valid only from | 305 // All other member variables should be before WeakPtrFactory. Valid only from |
299 // InitEncode to Release. | 306 // InitEncode to Release. |
300 std::unique_ptr<rtc::WeakPtrFactory<MediaCodecVideoEncoder>> weak_factory_; | 307 std::unique_ptr<rtc::WeakPtrFactory<MediaCodecVideoEncoder>> weak_factory_; |
301 }; | 308 }; |
302 | 309 |
303 MediaCodecVideoEncoder::~MediaCodecVideoEncoder() { | 310 MediaCodecVideoEncoder::~MediaCodecVideoEncoder() { |
304 #if RTC_DCHECK_IS_ON | 311 #if RTC_DCHECK_IS_ON |
305 rtc::CritScope lock(&inited_crit_); | 312 rtc::CritScope lock(&inited_crit_); |
(...skipping 11 matching lines...) Expand all Loading... | |
317 FindClass(jni, "org/webrtc/MediaCodecVideoEncoder")), | 324 FindClass(jni, "org/webrtc/MediaCodecVideoEncoder")), |
318 j_media_codec_video_encoder_( | 325 j_media_codec_video_encoder_( |
319 jni, | 326 jni, |
320 jni->NewObject(*j_media_codec_video_encoder_class_, | 327 jni->NewObject(*j_media_codec_video_encoder_class_, |
321 GetMethodID(jni, | 328 GetMethodID(jni, |
322 *j_media_codec_video_encoder_class_, | 329 *j_media_codec_video_encoder_class_, |
323 "<init>", | 330 "<init>", |
324 "()V"))), | 331 "()V"))), |
325 inited_(false), | 332 inited_(false), |
326 use_surface_(false), | 333 use_surface_(false), |
327 picture_id_(0), | |
328 egl_context_(egl_context), | 334 egl_context_(egl_context), |
335 random_(rtc::TimeMicros()), | |
336 picture_id_(random_.Rand<uint16_t>() & 0x7FFF), | |
magjed_webrtc
2017/04/20 12:39:12
Is it possible to pass in the start |picture_id_|
brandtr
2017/04/21 08:29:31
That is something that we maybe want to do long-te
magjed_webrtc
2017/04/21 15:11:18
Acknowledged.
| |
337 tl0_pic_idx_(random_.Rand<uint8_t>()), | |
329 sw_fallback_required_(false) { | 338 sw_fallback_required_(false) { |
330 encoder_queue_checker_.Detach(); | 339 encoder_queue_checker_.Detach(); |
331 | 340 |
332 jclass j_output_buffer_info_class = | 341 jclass j_output_buffer_info_class = |
333 FindClass(jni, "org/webrtc/MediaCodecVideoEncoder$OutputBufferInfo"); | 342 FindClass(jni, "org/webrtc/MediaCodecVideoEncoder$OutputBufferInfo"); |
334 j_init_encode_method_ = GetMethodID( | 343 j_init_encode_method_ = GetMethodID( |
335 jni, | 344 jni, |
336 *j_media_codec_video_encoder_class_, | 345 *j_media_codec_video_encoder_class_, |
337 "initEncode", | 346 "initEncode", |
338 "(Lorg/webrtc/MediaCodecVideoEncoder$VideoCodecType;" | 347 "(Lorg/webrtc/MediaCodecVideoEncoder$VideoCodecType;" |
(...skipping 29 matching lines...) Expand all Loading... | |
368 j_info_buffer_field_ = GetFieldID( | 377 j_info_buffer_field_ = GetFieldID( |
369 jni, j_output_buffer_info_class, "buffer", "Ljava/nio/ByteBuffer;"); | 378 jni, j_output_buffer_info_class, "buffer", "Ljava/nio/ByteBuffer;"); |
370 j_info_is_key_frame_field_ = | 379 j_info_is_key_frame_field_ = |
371 GetFieldID(jni, j_output_buffer_info_class, "isKeyFrame", "Z"); | 380 GetFieldID(jni, j_output_buffer_info_class, "isKeyFrame", "Z"); |
372 j_info_presentation_timestamp_us_field_ = GetFieldID( | 381 j_info_presentation_timestamp_us_field_ = GetFieldID( |
373 jni, j_output_buffer_info_class, "presentationTimestampUs", "J"); | 382 jni, j_output_buffer_info_class, "presentationTimestampUs", "J"); |
374 if (CheckException(jni)) { | 383 if (CheckException(jni)) { |
375 ALOGW << "MediaCodecVideoEncoder ctor failed."; | 384 ALOGW << "MediaCodecVideoEncoder ctor failed."; |
376 ProcessHWError(true /* reset_if_fallback_unavailable */); | 385 ProcessHWError(true /* reset_if_fallback_unavailable */); |
377 } | 386 } |
378 srand(rtc::Time32()); | |
379 } | 387 } |
380 | 388 |
381 int32_t MediaCodecVideoEncoder::InitEncode( | 389 int32_t MediaCodecVideoEncoder::InitEncode( |
382 const webrtc::VideoCodec* codec_settings, | 390 const webrtc::VideoCodec* codec_settings, |
383 int32_t /* number_of_cores */, | 391 int32_t /* number_of_cores */, |
384 size_t /* max_payload_size */) { | 392 size_t /* max_payload_size */) { |
385 RTC_DCHECK_CALLED_SEQUENTIALLY(&encoder_queue_checker_); | 393 RTC_DCHECK_CALLED_SEQUENTIALLY(&encoder_queue_checker_); |
386 if (codec_settings == NULL) { | 394 if (codec_settings == NULL) { |
387 ALOGE << "NULL VideoCodec instance"; | 395 ALOGE << "NULL VideoCodec instance"; |
388 return WEBRTC_VIDEO_CODEC_ERR_PARAMETER; | 396 return WEBRTC_VIDEO_CODEC_ERR_PARAMETER; |
(...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
545 current_bytes_ = 0; | 553 current_bytes_ = 0; |
546 current_acc_qp_ = 0; | 554 current_acc_qp_ = 0; |
547 current_encoding_time_ms_ = 0; | 555 current_encoding_time_ms_ = 0; |
548 last_input_timestamp_ms_ = -1; | 556 last_input_timestamp_ms_ = -1; |
549 last_output_timestamp_ms_ = -1; | 557 last_output_timestamp_ms_ = -1; |
550 output_timestamp_ = 0; | 558 output_timestamp_ = 0; |
551 output_render_time_ms_ = 0; | 559 output_render_time_ms_ = 0; |
552 input_frame_infos_.clear(); | 560 input_frame_infos_.clear(); |
553 drop_next_input_frame_ = false; | 561 drop_next_input_frame_ = false; |
554 use_surface_ = use_surface; | 562 use_surface_ = use_surface; |
555 // TODO(ilnik): Use rand_r() instead to avoid LINT warnings below. | |
556 picture_id_ = static_cast<uint16_t>(rand()) & 0x7FFF; // NOLINT | |
557 gof_.SetGofInfoVP9(webrtc::TemporalStructureMode::kTemporalStructureMode1); | 563 gof_.SetGofInfoVP9(webrtc::TemporalStructureMode::kTemporalStructureMode1); |
558 tl0_pic_idx_ = static_cast<uint8_t>(rand()); // NOLINT | |
559 gof_idx_ = 0; | 564 gof_idx_ = 0; |
560 last_frame_received_ms_ = -1; | 565 last_frame_received_ms_ = -1; |
561 frames_received_since_last_key_ = kMinKeyFrameInterval; | 566 frames_received_since_last_key_ = kMinKeyFrameInterval; |
562 | 567 |
563 // We enforce no extra stride/padding in the format creation step. | 568 // We enforce no extra stride/padding in the format creation step. |
564 jobject j_video_codec_enum = JavaEnumFromIndexAndClassName( | 569 jobject j_video_codec_enum = JavaEnumFromIndexAndClassName( |
565 jni, "MediaCodecVideoEncoder$VideoCodecType", codec_type); | 570 jni, "MediaCodecVideoEncoder$VideoCodecType", codec_type); |
566 const bool encode_status = jni->CallBooleanMethod( | 571 const bool encode_status = jni->CallBooleanMethod( |
567 *j_media_codec_video_encoder_, j_init_encode_method_, | 572 *j_media_codec_video_encoder_, j_init_encode_method_, |
568 j_video_codec_enum, width, height, kbps, fps, | 573 j_video_codec_enum, width, height, kbps, fps, |
(...skipping 779 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1348 } | 1353 } |
1349 } | 1354 } |
1350 | 1355 |
1351 void MediaCodecVideoEncoderFactory::DestroyVideoEncoder( | 1356 void MediaCodecVideoEncoderFactory::DestroyVideoEncoder( |
1352 webrtc::VideoEncoder* encoder) { | 1357 webrtc::VideoEncoder* encoder) { |
1353 ALOGD << "Destroy video encoder."; | 1358 ALOGD << "Destroy video encoder."; |
1354 delete encoder; | 1359 delete encoder; |
1355 } | 1360 } |
1356 | 1361 |
1357 } // namespace webrtc_jni | 1362 } // namespace webrtc_jni |
OLD | NEW |