Android: Use RTP timestamp instead of capture_time_ms_ in VideoDecoderWrapper.
capture_time_ms_ is always 0 for frames received from the network. This caused a bug because it was used as an unique identified. Bug: b/68271454 Change-Id: Ic4417a52e61cf2b0cd796a89207a90b603a16590 Reviewed-on: https://webrtc-review.googlesource.com/24940 Reviewed-by: Magnus Jedvert <magjed@webrtc.org> Commit-Queue: Sami Kalliomäki <sakal@webrtc.org> Cr-Commit-Position: refs/heads/master@{#20837}
This commit is contained in:
committed by
Commit Bot
parent
1882d8509a
commit
ce86e2965c
@ -26,6 +26,9 @@ namespace webrtc {
|
|||||||
namespace jni {
|
namespace jni {
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
// RTP timestamps are 90 kHz.
|
||||||
|
const int64_t kNumRtpTicksPerMillisec = 90000 / rtc::kNumMillisecsPerSec;
|
||||||
|
|
||||||
template <typename Dst, typename Src>
|
template <typename Dst, typename Src>
|
||||||
inline rtc::Optional<Dst> cast_optional(const rtc::Optional<Src>& value) {
|
inline rtc::Optional<Dst> cast_optional(const rtc::Optional<Src>& value) {
|
||||||
return value ? rtc::Optional<Dst>(rtc::dchecked_cast<Dst, Src>(*value))
|
return value ? rtc::Optional<Dst>(rtc::dchecked_cast<Dst, Src>(*value))
|
||||||
@ -74,7 +77,7 @@ int32_t VideoDecoderWrapper::InitDecodeInternal(JNIEnv* jni) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int32_t VideoDecoderWrapper::Decode(
|
int32_t VideoDecoderWrapper::Decode(
|
||||||
const EncodedImage& input_image,
|
const EncodedImage& image_param,
|
||||||
bool missing_frames,
|
bool missing_frames,
|
||||||
const RTPFragmentationHeader* fragmentation,
|
const RTPFragmentationHeader* fragmentation,
|
||||||
const CodecSpecificInfo* codec_specific_info,
|
const CodecSpecificInfo* codec_specific_info,
|
||||||
@ -87,10 +90,17 @@ int32_t VideoDecoderWrapper::Decode(
|
|||||||
JNIEnv* jni = AttachCurrentThreadIfNeeded();
|
JNIEnv* jni = AttachCurrentThreadIfNeeded();
|
||||||
ScopedLocalRefFrame local_ref_frame(jni);
|
ScopedLocalRefFrame local_ref_frame(jni);
|
||||||
|
|
||||||
|
// Make a mutable copy so we can modify the timestamp.
|
||||||
|
EncodedImage input_image(image_param);
|
||||||
|
// We use RTP timestamp for capture time because capture_time_ms_ is always 0.
|
||||||
|
input_image.capture_time_ms_ =
|
||||||
|
input_image._timeStamp / kNumRtpTicksPerMillisec;
|
||||||
|
|
||||||
FrameExtraInfo frame_extra_info;
|
FrameExtraInfo frame_extra_info;
|
||||||
frame_extra_info.capture_time_ns =
|
frame_extra_info.timestamp_ns =
|
||||||
input_image.capture_time_ms_ * rtc::kNumNanosecsPerMillisec;
|
input_image.capture_time_ms_ * rtc::kNumNanosecsPerMillisec;
|
||||||
frame_extra_info.timestamp_rtp = input_image._timeStamp;
|
frame_extra_info.timestamp_rtp = input_image._timeStamp;
|
||||||
|
frame_extra_info.timestamp_ntp = input_image.ntp_time_ms_;
|
||||||
frame_extra_info.qp =
|
frame_extra_info.qp =
|
||||||
qp_parsing_enabled_ ? ParseQP(input_image) : rtc::nullopt;
|
qp_parsing_enabled_ ? ParseQP(input_image) : rtc::nullopt;
|
||||||
frame_extra_infos_.push_back(frame_extra_info);
|
frame_extra_infos_.push_back(frame_extra_info);
|
||||||
@ -129,12 +139,13 @@ void VideoDecoderWrapper::OnDecodedFrame(JNIEnv* env,
|
|||||||
jobject j_frame,
|
jobject j_frame,
|
||||||
jobject j_decode_time_ms,
|
jobject j_decode_time_ms,
|
||||||
jobject j_qp) {
|
jobject j_qp) {
|
||||||
const uint64_t capture_time_ns = GetJavaVideoFrameTimestampNs(env, j_frame);
|
const uint64_t timestamp_ns = GetJavaVideoFrameTimestampNs(env, j_frame);
|
||||||
|
|
||||||
FrameExtraInfo frame_extra_info;
|
FrameExtraInfo frame_extra_info;
|
||||||
do {
|
do {
|
||||||
if (frame_extra_infos_.empty()) {
|
if (frame_extra_infos_.empty()) {
|
||||||
RTC_LOG(LS_WARNING) << "Java decoder produced an unexpected frame.";
|
RTC_LOG(LS_WARNING) << "Java decoder produced an unexpected frame: "
|
||||||
|
<< timestamp_ns;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -142,10 +153,11 @@ void VideoDecoderWrapper::OnDecodedFrame(JNIEnv* env,
|
|||||||
frame_extra_infos_.pop_front();
|
frame_extra_infos_.pop_front();
|
||||||
// If the decoder might drop frames so iterate through the queue until we
|
// If the decoder might drop frames so iterate through the queue until we
|
||||||
// find a matching timestamp.
|
// find a matching timestamp.
|
||||||
} while (frame_extra_info.capture_time_ns != capture_time_ns);
|
} while (frame_extra_info.timestamp_ns != timestamp_ns);
|
||||||
|
|
||||||
VideoFrame frame =
|
VideoFrame frame =
|
||||||
JavaToNativeFrame(env, j_frame, frame_extra_info.timestamp_rtp);
|
JavaToNativeFrame(env, j_frame, frame_extra_info.timestamp_rtp);
|
||||||
|
frame.set_ntp_time_ms(frame_extra_info.timestamp_ntp);
|
||||||
|
|
||||||
rtc::Optional<int32_t> decoding_time_ms =
|
rtc::Optional<int32_t> decoding_time_ms =
|
||||||
JavaIntegerToOptionalInt(env, j_decode_time_ms);
|
JavaIntegerToOptionalInt(env, j_decode_time_ms);
|
||||||
|
|||||||
@ -56,9 +56,10 @@ class VideoDecoderWrapper : public VideoDecoder {
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
struct FrameExtraInfo {
|
struct FrameExtraInfo {
|
||||||
uint64_t capture_time_ns; // Used as an identifier of the frame.
|
int64_t timestamp_ns; // Used as an identifier of the frame.
|
||||||
|
|
||||||
uint32_t timestamp_rtp;
|
uint32_t timestamp_rtp;
|
||||||
|
int64_t timestamp_ntp;
|
||||||
rtc::Optional<uint8_t> qp;
|
rtc::Optional<uint8_t> qp;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user