diff --git a/sdk/android/src/jni/video_encoder_wrapper.cc b/sdk/android/src/jni/video_encoder_wrapper.cc index c12f5cff52..dde82a53a9 100644 --- a/sdk/android/src/jni/video_encoder_wrapper.cc +++ b/sdk/android/src/jni/video_encoder_wrapper.cc @@ -113,7 +113,10 @@ int32_t VideoEncoderWrapper::Release() { int32_t status = JavaToNativeVideoCodecStatus( jni, Java_VideoEncoder_release(jni, encoder_)); RTC_LOG(LS_INFO) << "release: " << status; - frame_extra_infos_.clear(); + { + MutexLock lock(&frame_extra_infos_lock_); + frame_extra_infos_.clear(); + } initialized_ = false; return status; @@ -138,7 +141,10 @@ int32_t VideoEncoderWrapper::Encode( FrameExtraInfo info; info.capture_time_ns = frame.timestamp_us() * rtc::kNumNanosecsPerMicrosec; info.timestamp_rtp = frame.timestamp(); - frame_extra_infos_.push_back(info); + { + MutexLock lock(&frame_extra_infos_lock_); + frame_extra_infos_.push_back(info); + } ScopedJavaLocalRef j_frame = NativeToJavaVideoFrame(jni, frame); ScopedJavaLocalRef ret = @@ -229,19 +235,23 @@ void VideoEncoderWrapper::OnEncodedFrame( // entries that don't belong to us, and we need to be careful not to // remove them. Removing only those entries older than the current frame // provides this guarantee. - while (!frame_extra_infos_.empty() && - frame_extra_infos_.front().capture_time_ns < capture_time_ns) { + FrameExtraInfo frame_extra_info; + { + MutexLock lock(&frame_extra_infos_lock_); + while (!frame_extra_infos_.empty() && + frame_extra_infos_.front().capture_time_ns < capture_time_ns) { + frame_extra_infos_.pop_front(); + } + if (frame_extra_infos_.empty() || + frame_extra_infos_.front().capture_time_ns != capture_time_ns) { + RTC_LOG(LS_WARNING) + << "Java encoder produced an unexpected frame with timestamp: " + << capture_time_ns; + return; + } + frame_extra_info = frame_extra_infos_.front(); frame_extra_infos_.pop_front(); } - if (frame_extra_infos_.empty() || - frame_extra_infos_.front().capture_time_ns != capture_time_ns) { - RTC_LOG(LS_WARNING) - << "Java encoder produced an unexpected frame with timestamp: " - << capture_time_ns; - return; - } - FrameExtraInfo frame_extra_info = std::move(frame_extra_infos_.front()); - frame_extra_infos_.pop_front(); // This is a bit subtle. The |frame| variable from the lambda capture is // const. Which implies that (i) we need to make a copy to be able to diff --git a/sdk/android/src/jni/video_encoder_wrapper.h b/sdk/android/src/jni/video_encoder_wrapper.h index cee3a609a3..bb098bb7c7 100644 --- a/sdk/android/src/jni/video_encoder_wrapper.h +++ b/sdk/android/src/jni/video_encoder_wrapper.h @@ -21,6 +21,7 @@ #include "api/video_codecs/video_encoder.h" #include "common_video/h264/h264_bitstream_parser.h" #include "modules/video_coding/codecs/vp9/include/vp9_globals.h" +#include "rtc_base/synchronization/mutex.h" #include "sdk/android/src/jni/jni_helpers.h" #include "sdk/android/src/jni/video_frame.h" @@ -82,7 +83,10 @@ class VideoEncoderWrapper : public VideoEncoder { const ScopedJavaGlobalRef encoder_; const ScopedJavaGlobalRef int_array_class_; - std::deque frame_extra_infos_; + // Modified both on the encoder thread and the callback thread. + Mutex frame_extra_infos_lock_; + std::deque frame_extra_infos_ + RTC_GUARDED_BY(frame_extra_infos_lock_); EncodedImageCallback* callback_; bool initialized_; int num_resets_;