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 208 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
219 int frames_dropped_media_encoder_; // Number of frames dropped by encoder. | 219 int frames_dropped_media_encoder_; // Number of frames dropped by encoder. |
220 // Number of dropped frames caused by full queue. | 220 // Number of dropped frames caused by full queue. |
221 int consecutive_full_queue_frame_drops_; | 221 int consecutive_full_queue_frame_drops_; |
222 int64_t stat_start_time_ms_; // Start time for statistics. | 222 int64_t stat_start_time_ms_; // Start time for statistics. |
223 int current_frames_; // Number of frames in the current statistics interval. | 223 int current_frames_; // Number of frames in the current statistics interval. |
224 int current_bytes_; // Encoded bytes in the current statistics interval. | 224 int current_bytes_; // Encoded bytes in the current statistics interval. |
225 int current_acc_qp_; // Accumulated QP in the current statistics interval. | 225 int current_acc_qp_; // Accumulated QP in the current statistics interval. |
226 int current_encoding_time_ms_; // Overall encoding time in the current second | 226 int current_encoding_time_ms_; // Overall encoding time in the current second |
227 int64_t last_input_timestamp_ms_; // Timestamp of last received yuv frame. | 227 int64_t last_input_timestamp_ms_; // Timestamp of last received yuv frame. |
228 int64_t last_output_timestamp_ms_; // Timestamp of last encoded frame. | 228 int64_t last_output_timestamp_ms_; // Timestamp of last encoded frame. |
229 bool output_delivery_loop_running_; // Is the onMessage loop running | |
229 | 230 |
230 struct InputFrameInfo { | 231 struct InputFrameInfo { |
231 InputFrameInfo(int64_t encode_start_time, | 232 InputFrameInfo(int64_t encode_start_time, |
232 int32_t frame_timestamp, | 233 int32_t frame_timestamp, |
233 int64_t frame_render_time_ms, | 234 int64_t frame_render_time_ms, |
234 webrtc::VideoRotation rotation) | 235 webrtc::VideoRotation rotation) |
235 : encode_start_time(encode_start_time), | 236 : encode_start_time(encode_start_time), |
236 frame_timestamp(frame_timestamp), | 237 frame_timestamp(frame_timestamp), |
237 frame_render_time_ms(frame_render_time_ms), | 238 frame_render_time_ms(frame_render_time_ms), |
238 rotation(rotation) {} | 239 rotation(rotation) {} |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
299 j_media_codec_video_encoder_( | 300 j_media_codec_video_encoder_( |
300 jni, | 301 jni, |
301 jni->NewObject(*j_media_codec_video_encoder_class_, | 302 jni->NewObject(*j_media_codec_video_encoder_class_, |
302 GetMethodID(jni, | 303 GetMethodID(jni, |
303 *j_media_codec_video_encoder_class_, | 304 *j_media_codec_video_encoder_class_, |
304 "<init>", | 305 "<init>", |
305 "()V"))), | 306 "()V"))), |
306 inited_(false), | 307 inited_(false), |
307 use_surface_(false), | 308 use_surface_(false), |
308 picture_id_(0), | 309 picture_id_(0), |
310 output_delivery_loop_running_(false), | |
309 egl_context_(egl_context) { | 311 egl_context_(egl_context) { |
310 ScopedLocalRefFrame local_ref_frame(jni); | 312 ScopedLocalRefFrame local_ref_frame(jni); |
311 // It would be nice to avoid spinning up a new thread per MediaCodec, and | 313 // It would be nice to avoid spinning up a new thread per MediaCodec, and |
312 // instead re-use e.g. the PeerConnectionFactory's |worker_thread_|, but bug | 314 // instead re-use e.g. the PeerConnectionFactory's |worker_thread_|, but bug |
313 // 2732 means that deadlocks abound. This class synchronously trampolines | 315 // 2732 means that deadlocks abound. This class synchronously trampolines |
314 // to |codec_thread_|, so if anything else can be coming to _us_ from | 316 // to |codec_thread_|, so if anything else can be coming to _us_ from |
315 // |codec_thread_|, or from any thread holding the |_sendCritSect| described | 317 // |codec_thread_|, or from any thread holding the |_sendCritSect| described |
316 // in the bug, we have a problem. For now work around that with a dedicated | 318 // in the bug, we have a problem. For now work around that with a dedicated |
317 // thread. | 319 // thread. |
318 codec_thread_->SetName("MediaCodecVideoEncoder", NULL); | 320 codec_thread_->SetName("MediaCodecVideoEncoder", NULL); |
(...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
466 RTC_CHECK(!msg->message_id) << "Unexpected message!"; | 468 RTC_CHECK(!msg->message_id) << "Unexpected message!"; |
467 RTC_CHECK(!msg->pdata) << "Unexpected message!"; | 469 RTC_CHECK(!msg->pdata) << "Unexpected message!"; |
468 if (!inited_) { | 470 if (!inited_) { |
469 return; | 471 return; |
470 } | 472 } |
471 | 473 |
472 // It would be nice to recover from a failure here if one happened, but it's | 474 // It would be nice to recover from a failure here if one happened, but it's |
473 // unclear how to signal such a failure to the app, so instead we stay silent | 475 // unclear how to signal such a failure to the app, so instead we stay silent |
474 // about it and let the next app-called API method reveal the borkedness. | 476 // about it and let the next app-called API method reveal the borkedness. |
475 DeliverPendingOutputs(jni); | 477 DeliverPendingOutputs(jni); |
476 codec_thread_->PostDelayed(kMediaCodecPollMs, this); | 478 |
479 // If there isn't more frames to deliver, we can stop the loop | |
480 if (last_output_timestamp_ms_ != last_input_timestamp_ms_) { | |
481 codec_thread_->PostDelayed(kMediaCodecPollMs, this); | |
482 } else { | |
483 output_delivery_loop_running_ = false; | |
484 } | |
477 } | 485 } |
478 | 486 |
479 bool MediaCodecVideoEncoder::ResetCodecOnCodecThread() { | 487 bool MediaCodecVideoEncoder::ResetCodecOnCodecThread() { |
480 RTC_DCHECK(codec_thread_checker_.CalledOnValidThread()); | 488 RTC_DCHECK(codec_thread_checker_.CalledOnValidThread()); |
481 ALOGE << "ResetOnCodecThread"; | 489 ALOGE << "ResetOnCodecThread"; |
482 if (ReleaseOnCodecThread() != WEBRTC_VIDEO_CODEC_OK || | 490 if (ReleaseOnCodecThread() != WEBRTC_VIDEO_CODEC_OK || |
483 InitEncodeOnCodecThread(width_, height_, 0, 0, false) != | 491 InitEncodeOnCodecThread(width_, height_, 0, 0, false) != |
484 WEBRTC_VIDEO_CODEC_OK) { | 492 WEBRTC_VIDEO_CODEC_OK) { |
485 // TODO(fischman): wouldn't it be nice if there was a way to gracefully | 493 // TODO(fischman): wouldn't it be nice if there was a way to gracefully |
486 // degrade to a SW encoder at this point? There isn't one AFAICT :( | 494 // degrade to a SW encoder at this point? There isn't one AFAICT :( |
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
580 input_buffers_[i] = | 588 input_buffers_[i] = |
581 jni->NewGlobalRef(jni->GetObjectArrayElement(input_buffers, i)); | 589 jni->NewGlobalRef(jni->GetObjectArrayElement(input_buffers, i)); |
582 int64_t yuv_buffer_capacity = | 590 int64_t yuv_buffer_capacity = |
583 jni->GetDirectBufferCapacity(input_buffers_[i]); | 591 jni->GetDirectBufferCapacity(input_buffers_[i]); |
584 CHECK_EXCEPTION(jni); | 592 CHECK_EXCEPTION(jni); |
585 RTC_CHECK(yuv_buffer_capacity >= yuv_size_) << "Insufficient capacity"; | 593 RTC_CHECK(yuv_buffer_capacity >= yuv_size_) << "Insufficient capacity"; |
586 } | 594 } |
587 } | 595 } |
588 | 596 |
589 inited_ = true; | 597 inited_ = true; |
590 codec_thread_->PostDelayed(kMediaCodecPollMs, this); | |
591 return WEBRTC_VIDEO_CODEC_OK; | 598 return WEBRTC_VIDEO_CODEC_OK; |
592 } | 599 } |
593 | 600 |
594 int32_t MediaCodecVideoEncoder::EncodeOnCodecThread( | 601 int32_t MediaCodecVideoEncoder::EncodeOnCodecThread( |
595 const webrtc::VideoFrame& frame, | 602 const webrtc::VideoFrame& frame, |
596 const std::vector<webrtc::FrameType>* frame_types) { | 603 const std::vector<webrtc::FrameType>* frame_types) { |
597 RTC_DCHECK(codec_thread_checker_.CalledOnValidThread()); | 604 RTC_DCHECK(codec_thread_checker_.CalledOnValidThread()); |
598 JNIEnv* jni = AttachCurrentThreadIfNeeded(); | 605 JNIEnv* jni = AttachCurrentThreadIfNeeded(); |
599 ScopedLocalRefFrame local_ref_frame(jni); | 606 ScopedLocalRefFrame local_ref_frame(jni); |
600 | 607 |
(...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
726 // Save input image timestamps for later output. | 733 // Save input image timestamps for later output. |
727 input_frame_infos_.emplace_back( | 734 input_frame_infos_.emplace_back( |
728 time_before_calling_encode, input_frame.timestamp(), | 735 time_before_calling_encode, input_frame.timestamp(), |
729 input_frame.render_time_ms(), input_frame.rotation()); | 736 input_frame.render_time_ms(), input_frame.rotation()); |
730 | 737 |
731 last_input_timestamp_ms_ = | 738 last_input_timestamp_ms_ = |
732 current_timestamp_us_ / rtc::kNumMicrosecsPerMillisec; | 739 current_timestamp_us_ / rtc::kNumMicrosecsPerMillisec; |
733 | 740 |
734 current_timestamp_us_ += rtc::kNumMicrosecsPerSec / last_set_fps_; | 741 current_timestamp_us_ += rtc::kNumMicrosecsPerSec / last_set_fps_; |
735 | 742 |
743 if (!output_delivery_loop_running_) { | |
perkj_webrtc
2016/05/23 08:00:20
prefer too look at the size of input_frame_infos_.
| |
744 output_delivery_loop_running_ = true; | |
745 codec_thread_->PostDelayed(kMediaCodecPollMs, this); | |
746 } | |
747 | |
736 if (!DeliverPendingOutputs(jni)) { | 748 if (!DeliverPendingOutputs(jni)) { |
737 ALOGE << "Failed deliver pending outputs."; | 749 ALOGE << "Failed deliver pending outputs."; |
738 ResetCodecOnCodecThread(); | 750 ResetCodecOnCodecThread(); |
739 return WEBRTC_VIDEO_CODEC_ERROR; | 751 return WEBRTC_VIDEO_CODEC_ERROR; |
740 } | 752 } |
741 return WEBRTC_VIDEO_CODEC_OK; | 753 return WEBRTC_VIDEO_CODEC_OK; |
742 } | 754 } |
743 | 755 |
744 bool MediaCodecVideoEncoder::MaybeReconfigureEncoderOnCodecThread( | 756 bool MediaCodecVideoEncoder::MaybeReconfigureEncoderOnCodecThread( |
745 const webrtc::VideoFrame& frame) { | 757 const webrtc::VideoFrame& frame) { |
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
845 ". Dropped: " << frames_dropped_media_encoder_; | 857 ". Dropped: " << frames_dropped_media_encoder_; |
846 ScopedLocalRefFrame local_ref_frame(jni); | 858 ScopedLocalRefFrame local_ref_frame(jni); |
847 for (size_t i = 0; i < input_buffers_.size(); ++i) | 859 for (size_t i = 0; i < input_buffers_.size(); ++i) |
848 jni->DeleteGlobalRef(input_buffers_[i]); | 860 jni->DeleteGlobalRef(input_buffers_[i]); |
849 input_buffers_.clear(); | 861 input_buffers_.clear(); |
850 jni->CallVoidMethod(*j_media_codec_video_encoder_, j_release_method_); | 862 jni->CallVoidMethod(*j_media_codec_video_encoder_, j_release_method_); |
851 CHECK_EXCEPTION(jni); | 863 CHECK_EXCEPTION(jni); |
852 rtc::MessageQueueManager::Clear(this); | 864 rtc::MessageQueueManager::Clear(this); |
853 inited_ = false; | 865 inited_ = false; |
854 use_surface_ = false; | 866 use_surface_ = false; |
867 output_delivery_loop_running_ = false; | |
855 ALOGD << "EncoderReleaseOnCodecThread done."; | 868 ALOGD << "EncoderReleaseOnCodecThread done."; |
856 return WEBRTC_VIDEO_CODEC_OK; | 869 return WEBRTC_VIDEO_CODEC_OK; |
857 } | 870 } |
858 | 871 |
859 int32_t MediaCodecVideoEncoder::SetRatesOnCodecThread(uint32_t new_bit_rate, | 872 int32_t MediaCodecVideoEncoder::SetRatesOnCodecThread(uint32_t new_bit_rate, |
860 uint32_t frame_rate) { | 873 uint32_t frame_rate) { |
861 RTC_DCHECK(codec_thread_checker_.CalledOnValidThread()); | 874 RTC_DCHECK(codec_thread_checker_.CalledOnValidThread()); |
862 frame_rate = (frame_rate < MAX_ALLOWED_VIDEO_FPS) ? | 875 frame_rate = (frame_rate < MAX_ALLOWED_VIDEO_FPS) ? |
863 frame_rate : MAX_ALLOWED_VIDEO_FPS; | 876 frame_rate : MAX_ALLOWED_VIDEO_FPS; |
864 if (last_set_bitrate_kbps_ == new_bit_rate && | 877 if (last_set_bitrate_kbps_ == new_bit_rate && |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
932 | 945 |
933 // Get key and config frame flags. | 946 // Get key and config frame flags. |
934 jobject j_output_buffer = | 947 jobject j_output_buffer = |
935 GetOutputBufferInfoBuffer(jni, j_output_buffer_info); | 948 GetOutputBufferInfoBuffer(jni, j_output_buffer_info); |
936 bool key_frame = GetOutputBufferInfoIsKeyFrame(jni, j_output_buffer_info); | 949 bool key_frame = GetOutputBufferInfoIsKeyFrame(jni, j_output_buffer_info); |
937 | 950 |
938 // Get frame timestamps from a queue - for non config frames only. | 951 // Get frame timestamps from a queue - for non config frames only. |
939 int64_t frame_encoding_time_ms = 0; | 952 int64_t frame_encoding_time_ms = 0; |
940 last_output_timestamp_ms_ = | 953 last_output_timestamp_ms_ = |
941 GetOutputBufferInfoPresentationTimestampUs(jni, j_output_buffer_info) / | 954 GetOutputBufferInfoPresentationTimestampUs(jni, j_output_buffer_info) / |
942 1000; | 955 rtc::kNumMicrosecsPerMillisec; |
943 if (!input_frame_infos_.empty()) { | 956 if (!input_frame_infos_.empty()) { |
944 const InputFrameInfo& frame_info = input_frame_infos_.front(); | 957 const InputFrameInfo& frame_info = input_frame_infos_.front(); |
945 output_timestamp_ = frame_info.frame_timestamp; | 958 output_timestamp_ = frame_info.frame_timestamp; |
946 output_render_time_ms_ = frame_info.frame_render_time_ms; | 959 output_render_time_ms_ = frame_info.frame_render_time_ms; |
947 output_rotation_ = frame_info.rotation; | 960 output_rotation_ = frame_info.rotation; |
948 frame_encoding_time_ms = | 961 frame_encoding_time_ms = |
949 rtc::TimeMillis() - frame_info.encode_start_time; | 962 rtc::TimeMillis() - frame_info.encode_start_time; |
950 input_frame_infos_.pop_front(); | 963 input_frame_infos_.pop_front(); |
951 } | 964 } |
952 | 965 |
(...skipping 311 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1264 return supported_codecs_; | 1277 return supported_codecs_; |
1265 } | 1278 } |
1266 | 1279 |
1267 void MediaCodecVideoEncoderFactory::DestroyVideoEncoder( | 1280 void MediaCodecVideoEncoderFactory::DestroyVideoEncoder( |
1268 webrtc::VideoEncoder* encoder) { | 1281 webrtc::VideoEncoder* encoder) { |
1269 ALOGD << "Destroy video encoder."; | 1282 ALOGD << "Destroy video encoder."; |
1270 delete encoder; | 1283 delete encoder; |
1271 } | 1284 } |
1272 | 1285 |
1273 } // namespace webrtc_jni | 1286 } // namespace webrtc_jni |
OLD | NEW |