OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2017 The WebRTC project authors. All Rights Reserved. | 2 * Copyright 2017 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 #include "webrtc/sdk/android/src/jni/videodecoderwrapper.h" | 11 #include "webrtc/sdk/android/src/jni/videodecoderwrapper.h" |
12 | 12 |
13 #include "webrtc/api/video/video_frame.h" | 13 #include "webrtc/api/video/video_frame.h" |
14 #include "webrtc/modules/video_coding/include/video_codec_interface.h" | 14 #include "webrtc/modules/video_coding/include/video_codec_interface.h" |
15 #include "webrtc/modules/video_coding/utility/vp8_header_parser.h" | 15 #include "webrtc/modules/video_coding/utility/vp8_header_parser.h" |
16 #include "webrtc/modules/video_coding/utility/vp9_uncompressed_header_parser.h" | 16 #include "webrtc/modules/video_coding/utility/vp9_uncompressed_header_parser.h" |
17 #include "webrtc/rtc_base/logging.h" | 17 #include "webrtc/rtc_base/logging.h" |
| 18 #include "webrtc/rtc_base/timeutils.h" |
18 #include "webrtc/sdk/android/src/jni/classreferenceholder.h" | 19 #include "webrtc/sdk/android/src/jni/classreferenceholder.h" |
19 | 20 |
20 namespace webrtc { | 21 namespace webrtc { |
21 namespace jni { | 22 namespace jni { |
22 | 23 |
23 VideoDecoderWrapper::VideoDecoderWrapper(JNIEnv* jni, jobject decoder) | 24 VideoDecoderWrapper::VideoDecoderWrapper(JNIEnv* jni, jobject decoder) |
24 : android_video_buffer_factory_(jni), | 25 : android_video_buffer_factory_(jni), |
25 decoder_(jni, decoder), | 26 decoder_(jni, decoder), |
26 encoded_image_class_(jni, FindClass(jni, "org/webrtc/EncodedImage")), | 27 encoded_image_class_(jni, FindClass(jni, "org/webrtc/EncodedImage")), |
27 frame_type_class_(jni, | 28 frame_type_class_(jni, |
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
120 int64_t render_time_ms) { | 121 int64_t render_time_ms) { |
121 if (!initialized_) { | 122 if (!initialized_) { |
122 // Most likely initializing the codec failed. | 123 // Most likely initializing the codec failed. |
123 return WEBRTC_VIDEO_CODEC_FALLBACK_SOFTWARE; | 124 return WEBRTC_VIDEO_CODEC_FALLBACK_SOFTWARE; |
124 } | 125 } |
125 | 126 |
126 JNIEnv* jni = AttachCurrentThreadIfNeeded(); | 127 JNIEnv* jni = AttachCurrentThreadIfNeeded(); |
127 ScopedLocalRefFrame local_ref_frame(jni); | 128 ScopedLocalRefFrame local_ref_frame(jni); |
128 | 129 |
129 FrameExtraInfo frame_extra_info; | 130 FrameExtraInfo frame_extra_info; |
130 frame_extra_info.capture_time_ms = input_image.capture_time_ms_; | 131 frame_extra_info.capture_time_ns = |
| 132 input_image.capture_time_ms_ * rtc::kNumNanosecsPerMillisec; |
131 frame_extra_info.timestamp_rtp = input_image._timeStamp; | 133 frame_extra_info.timestamp_rtp = input_image._timeStamp; |
132 frame_extra_info.qp = | 134 frame_extra_info.qp = |
133 qp_parsing_enabled_ ? ParseQP(input_image) : rtc::Optional<uint8_t>(); | 135 qp_parsing_enabled_ ? ParseQP(input_image) : rtc::Optional<uint8_t>(); |
134 frame_extra_infos_.push_back(frame_extra_info); | 136 frame_extra_infos_.push_back(frame_extra_info); |
135 | 137 |
136 jobject jinput_image = | 138 jobject jinput_image = |
137 ConvertEncodedImageToJavaEncodedImage(jni, input_image); | 139 ConvertEncodedImageToJavaEncodedImage(jni, input_image); |
138 jobject ret = | 140 jobject ret = |
139 jni->CallObjectMethod(*decoder_, decode_method_, jinput_image, nullptr); | 141 jni->CallObjectMethod(*decoder_, decode_method_, jinput_image, nullptr); |
140 return HandleReturnCode(jni, ret); | 142 return HandleReturnCode(jni, ret); |
(...skipping 26 matching lines...) Expand all Loading... |
167 jni->CallObjectMethod(*decoder_, get_implementation_name_method_)); | 169 jni->CallObjectMethod(*decoder_, get_implementation_name_method_)); |
168 return JavaToStdString(jni, jname).c_str(); | 170 return JavaToStdString(jni, jname).c_str(); |
169 } | 171 } |
170 | 172 |
171 void VideoDecoderWrapper::OnDecodedFrame(JNIEnv* jni, | 173 void VideoDecoderWrapper::OnDecodedFrame(JNIEnv* jni, |
172 jobject jframe, | 174 jobject jframe, |
173 jobject jdecode_time_ms, | 175 jobject jdecode_time_ms, |
174 jobject jqp) { | 176 jobject jqp) { |
175 const jlong capture_time_ns = | 177 const jlong capture_time_ns = |
176 jni->CallLongMethod(jframe, video_frame_get_timestamp_ns_method_); | 178 jni->CallLongMethod(jframe, video_frame_get_timestamp_ns_method_); |
177 const uint32_t capture_time_ms = capture_time_ns / 1000 / 1000; | |
178 FrameExtraInfo frame_extra_info; | 179 FrameExtraInfo frame_extra_info; |
179 do { | 180 do { |
180 if (frame_extra_infos_.empty()) { | 181 if (frame_extra_infos_.empty()) { |
181 LOG(LS_WARNING) << "Java decoder produced an unexpected frame."; | 182 LOG(LS_WARNING) << "Java decoder produced an unexpected frame."; |
182 return; | 183 return; |
183 } | 184 } |
184 | 185 |
185 frame_extra_info = frame_extra_infos_.front(); | 186 frame_extra_info = frame_extra_infos_.front(); |
186 frame_extra_infos_.pop_front(); | 187 frame_extra_infos_.pop_front(); |
187 // If the decoder might drop frames so iterate through the queue until we | 188 // If the decoder might drop frames so iterate through the queue until we |
188 // find a matching timestamp. | 189 // find a matching timestamp. |
189 } while (frame_extra_info.capture_time_ms != capture_time_ms); | 190 } while (frame_extra_info.capture_time_ns != capture_time_ns); |
190 | 191 |
191 VideoFrame frame = android_video_buffer_factory_.CreateFrame( | 192 VideoFrame frame = android_video_buffer_factory_.CreateFrame( |
192 jni, jframe, frame_extra_info.timestamp_rtp); | 193 jni, jframe, frame_extra_info.timestamp_rtp); |
193 | 194 |
194 rtc::Optional<int32_t> decoding_time_ms; | 195 rtc::Optional<int32_t> decoding_time_ms; |
195 if (jdecode_time_ms != nullptr) { | 196 if (jdecode_time_ms != nullptr) { |
196 decoding_time_ms = rtc::Optional<int32_t>( | 197 decoding_time_ms = rtc::Optional<int32_t>( |
197 jni->CallIntMethod(jdecode_time_ms, int_value_method_)); | 198 jni->CallIntMethod(jdecode_time_ms, int_value_method_)); |
198 } | 199 } |
199 | 200 |
(...skipping 30 matching lines...) Expand all Loading... |
230 default: | 231 default: |
231 RTC_NOTREACHED(); | 232 RTC_NOTREACHED(); |
232 return nullptr; | 233 return nullptr; |
233 } | 234 } |
234 jobject frame_type = | 235 jobject frame_type = |
235 jni->GetStaticObjectField(*frame_type_class_, frame_type_field); | 236 jni->GetStaticObjectField(*frame_type_class_, frame_type_field); |
236 jobject qp = nullptr; | 237 jobject qp = nullptr; |
237 if (image.qp_ != -1) { | 238 if (image.qp_ != -1) { |
238 qp = jni->NewObject(*integer_class_, integer_constructor_, image.qp_); | 239 qp = jni->NewObject(*integer_class_, integer_constructor_, image.qp_); |
239 } | 240 } |
240 return jni->NewObject(*encoded_image_class_, encoded_image_constructor_, | 241 return jni->NewObject( |
241 buffer, static_cast<jint>(image._encodedWidth), | 242 *encoded_image_class_, encoded_image_constructor_, buffer, |
242 static_cast<jint>(image._encodedHeight), | 243 static_cast<jint>(image._encodedWidth), |
243 static_cast<jlong>(image.capture_time_ms_), frame_type, | 244 static_cast<jint>(image._encodedHeight), |
244 static_cast<jint>(image.rotation_), | 245 static_cast<jlong>(image.capture_time_ms_ * rtc::kNumNanosecsPerMillisec), |
245 image._completeFrame, qp); | 246 frame_type, static_cast<jint>(image.rotation_), image._completeFrame, qp); |
246 } | 247 } |
247 | 248 |
248 int32_t VideoDecoderWrapper::HandleReturnCode(JNIEnv* jni, jobject code) { | 249 int32_t VideoDecoderWrapper::HandleReturnCode(JNIEnv* jni, jobject code) { |
249 int32_t value = jni->CallIntMethod(code, get_number_method_); | 250 int32_t value = jni->CallIntMethod(code, get_number_method_); |
250 if (value < 0) { // Any errors are represented by negative values. | 251 if (value < 0) { // Any errors are represented by negative values. |
251 // Reset the codec. | 252 // Reset the codec. |
252 if (Release() == WEBRTC_VIDEO_CODEC_OK) { | 253 if (Release() == WEBRTC_VIDEO_CODEC_OK) { |
253 InitDecodeInternal(jni); | 254 InitDecodeInternal(jni); |
254 } | 255 } |
255 | 256 |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
305 jobject jframe, | 306 jobject jframe, |
306 jobject jdecode_time_ms, | 307 jobject jdecode_time_ms, |
307 jobject jqp) { | 308 jobject jqp) { |
308 VideoDecoderWrapper* native_decoder = | 309 VideoDecoderWrapper* native_decoder = |
309 reinterpret_cast<VideoDecoderWrapper*>(jnative_decoder); | 310 reinterpret_cast<VideoDecoderWrapper*>(jnative_decoder); |
310 native_decoder->OnDecodedFrame(jni, jframe, jdecode_time_ms, jqp); | 311 native_decoder->OnDecodedFrame(jni, jframe, jdecode_time_ms, jqp); |
311 } | 312 } |
312 | 313 |
313 } // namespace jni | 314 } // namespace jni |
314 } // namespace webrtc | 315 } // namespace webrtc |
OLD | NEW |