Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(25)

Side by Side Diff: webrtc/api/java/jni/androidmediaencoder_jni.cc

Issue 2000103002: Make Android MediaEncoder loop not run when there aren't any frames left. (Closed) Base URL: https://chromium.googlesource.com/external/webrtc.git@master
Patch Set: Created 4 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698