Revert "C++ wrapper for VideoDecoder and VideoDecoderFactory interfaces."
This reverts commit ef4342f21ba9448138fc7d22482f3210cb20fd7e. Reason for revert: Breaks chromium.webrtc.fyi Original change's description: > C++ wrapper for VideoDecoder and VideoDecoderFactory interfaces. > > Bug: webrtc:7760 > Change-Id: I136aff9bcfb9244bb45ec552b5443f4a06b87c27 > Reviewed-on: https://chromium-review.googlesource.com/535475 > Commit-Queue: Sami Kalliomäki <sakal@webrtc.org> > Reviewed-by: Magnus Jedvert <magjed@webrtc.org> > Cr-Commit-Position: refs/heads/master@{#18773} TBR=magjed@webrtc.org,sakal@webrtc.org Change-Id: I45810b9f3573074bb52539aa63843d59865c02f2 No-Presubmit: true No-Tree-Checks: true No-Try: true Bug: webrtc:7760 Reviewed-on: https://chromium-review.googlesource.com/549337 Reviewed-by: Sami Kalliomäki <sakal@webrtc.org> Commit-Queue: Sami Kalliomäki <sakal@webrtc.org> Cr-Commit-Position: refs/heads/master@{#18776}
This commit is contained in:
committed by
Commit Bot
parent
afd52d3777
commit
37a2350498
@ -92,10 +92,6 @@ rtc_static_library("video_jni") {
|
|||||||
"src/jni/surfacetexturehelper_jni.h",
|
"src/jni/surfacetexturehelper_jni.h",
|
||||||
"src/jni/video_jni.cc",
|
"src/jni/video_jni.cc",
|
||||||
"src/jni/video_renderer_jni.cc",
|
"src/jni/video_renderer_jni.cc",
|
||||||
"src/jni/videodecoderfactorywrapper.cc",
|
|
||||||
"src/jni/videodecoderfactorywrapper.h",
|
|
||||||
"src/jni/videodecoderwrapper.cc",
|
|
||||||
"src/jni/videodecoderwrapper.h",
|
|
||||||
"src/jni/videofilerenderer_jni.cc",
|
"src/jni/videofilerenderer_jni.cc",
|
||||||
"src/jni/videotrack_jni.cc",
|
"src/jni/videotrack_jni.cc",
|
||||||
"src/jni/wrapped_native_i420_buffer.cc",
|
"src/jni/wrapped_native_i420_buffer.cc",
|
||||||
@ -399,7 +395,6 @@ android_library("libjingle_peerconnection_java") {
|
|||||||
"src/java/org/webrtc/HardwareVideoEncoder.java",
|
"src/java/org/webrtc/HardwareVideoEncoder.java",
|
||||||
"src/java/org/webrtc/Histogram.java",
|
"src/java/org/webrtc/Histogram.java",
|
||||||
"src/java/org/webrtc/I420BufferImpl.java",
|
"src/java/org/webrtc/I420BufferImpl.java",
|
||||||
"src/java/org/webrtc/VideoDecoderWrapperCallback.java",
|
|
||||||
"src/java/org/webrtc/MediaCodecUtils.java",
|
"src/java/org/webrtc/MediaCodecUtils.java",
|
||||||
"src/java/org/webrtc/VideoCodecType.java",
|
"src/java/org/webrtc/VideoCodecType.java",
|
||||||
"src/java/org/webrtc/WrappedNativeI420Buffer.java",
|
"src/java/org/webrtc/WrappedNativeI420Buffer.java",
|
||||||
|
|||||||
@ -269,9 +269,7 @@ class HardwareVideoDecoder implements VideoDecoder {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public VideoCodecStatus release() {
|
public VideoCodecStatus release() {
|
||||||
// TODO(sakal): This is not called on the correct thread but is still called synchronously.
|
decoderThreadChecker.checkIsOnValidThread();
|
||||||
// Re-enable the check once this is called on the correct thread.
|
|
||||||
// decoderThreadChecker.checkIsOnValidThread();
|
|
||||||
try {
|
try {
|
||||||
// The outputThread actually stops and releases the codec once running is false.
|
// The outputThread actually stops and releases the codec once running is false.
|
||||||
running = false;
|
running = false;
|
||||||
|
|||||||
@ -1,30 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2017 The WebRTC project authors. All Rights Reserved.
|
|
||||||
*
|
|
||||||
* Use of this source code is governed by a BSD-style license
|
|
||||||
* that can be found in the LICENSE file in the root of the source
|
|
||||||
* tree. An additional intellectual property rights grant can be found
|
|
||||||
* in the file PATENTS. All contributing project authors may
|
|
||||||
* be found in the AUTHORS file in the root of the source tree.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.webrtc;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* VideoDecoder callback that calls VideoDecoderWrapper.OnDecodedFrame for the decoded frames.
|
|
||||||
*/
|
|
||||||
class VideoDecoderWrapperCallback implements VideoDecoder.Callback {
|
|
||||||
private final long nativeDecoder;
|
|
||||||
|
|
||||||
public VideoDecoderWrapperCallback(long nativeDecoder) {
|
|
||||||
this.nativeDecoder = nativeDecoder;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onDecodedFrame(VideoFrame frame, Integer decodeTimeMs, Integer qp) {
|
|
||||||
nativeOnDecodedFrame(nativeDecoder, frame, decodeTimeMs, qp);
|
|
||||||
}
|
|
||||||
|
|
||||||
private native static void nativeOnDecodedFrame(
|
|
||||||
long nativeDecoder, VideoFrame frame, Integer decodeTimeMs, Integer qp);
|
|
||||||
}
|
|
||||||
@ -8,7 +8,6 @@ include_rules = [
|
|||||||
"+webrtc/media/base",
|
"+webrtc/media/base",
|
||||||
"+webrtc/media/engine",
|
"+webrtc/media/engine",
|
||||||
"+webrtc/modules/utility/include/jvm_android.h",
|
"+webrtc/modules/utility/include/jvm_android.h",
|
||||||
"+webrtc/modules/video_coding/include/video_codec_interface.h",
|
|
||||||
"+webrtc/modules/video_coding/utility/vp8_header_parser.h",
|
"+webrtc/modules/video_coding/utility/vp8_header_parser.h",
|
||||||
"+webrtc/modules/video_coding/utility/vp9_uncompressed_header_parser.h",
|
"+webrtc/modules/video_coding/utility/vp9_uncompressed_header_parser.h",
|
||||||
"+webrtc/pc",
|
"+webrtc/pc",
|
||||||
|
|||||||
@ -65,8 +65,6 @@ ClassReferenceHolder::ClassReferenceHolder(JNIEnv* jni) {
|
|||||||
LoadClass(jni, "org/webrtc/EglBase");
|
LoadClass(jni, "org/webrtc/EglBase");
|
||||||
LoadClass(jni, "org/webrtc/EglBase$Context");
|
LoadClass(jni, "org/webrtc/EglBase$Context");
|
||||||
LoadClass(jni, "org/webrtc/EglBase14$Context");
|
LoadClass(jni, "org/webrtc/EglBase14$Context");
|
||||||
LoadClass(jni, "org/webrtc/EncodedImage");
|
|
||||||
LoadClass(jni, "org/webrtc/EncodedImage$FrameType");
|
|
||||||
LoadClass(jni, "org/webrtc/IceCandidate");
|
LoadClass(jni, "org/webrtc/IceCandidate");
|
||||||
LoadClass(jni, "org/webrtc/MediaCodecVideoDecoder");
|
LoadClass(jni, "org/webrtc/MediaCodecVideoDecoder");
|
||||||
LoadClass(jni, "org/webrtc/MediaCodecVideoDecoder$DecodedOutputBuffer");
|
LoadClass(jni, "org/webrtc/MediaCodecVideoDecoder$DecodedOutputBuffer");
|
||||||
@ -105,9 +103,6 @@ ClassReferenceHolder::ClassReferenceHolder(JNIEnv* jni) {
|
|||||||
LoadClass(jni, "org/webrtc/StatsReport$Value");
|
LoadClass(jni, "org/webrtc/StatsReport$Value");
|
||||||
LoadClass(jni, "org/webrtc/SurfaceTextureHelper");
|
LoadClass(jni, "org/webrtc/SurfaceTextureHelper");
|
||||||
LoadClass(jni, "org/webrtc/VideoCapturer");
|
LoadClass(jni, "org/webrtc/VideoCapturer");
|
||||||
LoadClass(jni, "org/webrtc/VideoCodecStatus");
|
|
||||||
LoadClass(jni, "org/webrtc/VideoDecoder$Settings");
|
|
||||||
LoadClass(jni, "org/webrtc/VideoDecoderWrapperCallback");
|
|
||||||
LoadClass(jni, "org/webrtc/VideoFrame");
|
LoadClass(jni, "org/webrtc/VideoFrame");
|
||||||
LoadClass(jni, "org/webrtc/VideoFrame$Buffer");
|
LoadClass(jni, "org/webrtc/VideoFrame$Buffer");
|
||||||
LoadClass(jni, "org/webrtc/VideoFrame$I420Buffer");
|
LoadClass(jni, "org/webrtc/VideoFrame$I420Buffer");
|
||||||
|
|||||||
@ -1,47 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2017 The WebRTC project authors. All Rights Reserved.
|
|
||||||
*
|
|
||||||
* Use of this source code is governed by a BSD-style license
|
|
||||||
* that can be found in the LICENSE file in the root of the source
|
|
||||||
* tree. An additional intellectual property rights grant can be found
|
|
||||||
* in the file PATENTS. All contributing project authors may
|
|
||||||
* be found in the AUTHORS file in the root of the source tree.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "webrtc/sdk/android/src/jni/videodecoderfactorywrapper.h"
|
|
||||||
|
|
||||||
#include "webrtc/api/video_codecs/video_decoder.h"
|
|
||||||
#include "webrtc/base/logging.h"
|
|
||||||
#include "webrtc/common_types.h"
|
|
||||||
#include "webrtc/sdk/android/src/jni/videodecoderwrapper.h"
|
|
||||||
|
|
||||||
namespace webrtc_jni {
|
|
||||||
|
|
||||||
VideoDecoderFactoryWrapper::VideoDecoderFactoryWrapper(JNIEnv* jni,
|
|
||||||
jobject decoder_factory)
|
|
||||||
: decoder_factory_(jni, decoder_factory) {
|
|
||||||
jclass decoder_factory_class = jni->GetObjectClass(*decoder_factory_);
|
|
||||||
create_decoder_method_ =
|
|
||||||
jni->GetMethodID(decoder_factory_class, "createDecoder",
|
|
||||||
"(Ljava/lang/String;)Lorg/webrtc/VideoDecoder;");
|
|
||||||
}
|
|
||||||
|
|
||||||
webrtc::VideoDecoder* VideoDecoderFactoryWrapper::CreateVideoDecoder(
|
|
||||||
webrtc::VideoCodecType type) {
|
|
||||||
JNIEnv* jni = AttachCurrentThreadIfNeeded();
|
|
||||||
ScopedLocalRefFrame local_ref_frame(jni);
|
|
||||||
rtc::Optional<const char*> type_payload =
|
|
||||||
webrtc::CodecTypeToPayloadName(type);
|
|
||||||
RTC_DCHECK(type_payload);
|
|
||||||
jstring name = jni->NewStringUTF(*type_payload);
|
|
||||||
jobject decoder =
|
|
||||||
jni->CallObjectMethod(*decoder_factory_, create_decoder_method_, name);
|
|
||||||
return decoder != nullptr ? new VideoDecoderWrapper(jni, decoder) : nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
void VideoDecoderFactoryWrapper::DestroyVideoDecoder(
|
|
||||||
webrtc::VideoDecoder* decoder) {
|
|
||||||
delete decoder;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace webrtc_jni
|
|
||||||
@ -1,40 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2017 The WebRTC project authors. All Rights Reserved.
|
|
||||||
*
|
|
||||||
* Use of this source code is governed by a BSD-style license
|
|
||||||
* that can be found in the LICENSE file in the root of the source
|
|
||||||
* tree. An additional intellectual property rights grant can be found
|
|
||||||
* in the file PATENTS. All contributing project authors may
|
|
||||||
* be found in the AUTHORS file in the root of the source tree.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef WEBRTC_SDK_ANDROID_SRC_JNI_VIDEODECODERFACTORYWRAPPER_H_
|
|
||||||
#define WEBRTC_SDK_ANDROID_SRC_JNI_VIDEODECODERFACTORYWRAPPER_H_
|
|
||||||
|
|
||||||
#include <jni.h>
|
|
||||||
|
|
||||||
#include "webrtc/media/engine/webrtcvideodecoderfactory.h"
|
|
||||||
#include "webrtc/sdk/android/src/jni/jni_helpers.h"
|
|
||||||
|
|
||||||
namespace webrtc_jni {
|
|
||||||
|
|
||||||
// Wrapper for Java VideoDecoderFactory class. Delegates method calls through
|
|
||||||
// JNI and wraps the decoder inside VideoDecoderWrapper.
|
|
||||||
class VideoDecoderFactoryWrapper : public cricket::WebRtcVideoDecoderFactory {
|
|
||||||
public:
|
|
||||||
VideoDecoderFactoryWrapper(JNIEnv* jni, jobject decoder_factory);
|
|
||||||
|
|
||||||
// Caller takes the ownership of the returned object and it should be released
|
|
||||||
// by calling DestroyVideoDecoder().
|
|
||||||
webrtc::VideoDecoder* CreateVideoDecoder(
|
|
||||||
webrtc::VideoCodecType type) override;
|
|
||||||
void DestroyVideoDecoder(webrtc::VideoDecoder* decoder) override;
|
|
||||||
|
|
||||||
private:
|
|
||||||
const ScopedGlobalRef<jobject> decoder_factory_;
|
|
||||||
jmethodID create_decoder_method_;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace webrtc_jni
|
|
||||||
|
|
||||||
#endif // WEBRTC_SDK_ANDROID_SRC_JNI_VIDEODECODERFACTORYWRAPPER_H_
|
|
||||||
@ -1,256 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2017 The WebRTC project authors. All Rights Reserved.
|
|
||||||
*
|
|
||||||
* Use of this source code is governed by a BSD-style license
|
|
||||||
* that can be found in the LICENSE file in the root of the source
|
|
||||||
* tree. An additional intellectual property rights grant can be found
|
|
||||||
* in the file PATENTS. All contributing project authors may
|
|
||||||
* be found in the AUTHORS file in the root of the source tree.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "webrtc/sdk/android/src/jni/videodecoderwrapper.h"
|
|
||||||
|
|
||||||
#include "webrtc/api/video/video_frame.h"
|
|
||||||
#include "webrtc/base/logging.h"
|
|
||||||
#include "webrtc/modules/video_coding/include/video_codec_interface.h"
|
|
||||||
#include "webrtc/sdk/android/src/jni/classreferenceholder.h"
|
|
||||||
|
|
||||||
namespace webrtc_jni {
|
|
||||||
|
|
||||||
VideoDecoderWrapper::VideoDecoderWrapper(JNIEnv* jni, jobject decoder)
|
|
||||||
: android_video_buffer_factory_(jni),
|
|
||||||
decoder_(jni, decoder),
|
|
||||||
encoded_image_class_(jni, FindClass(jni, "org/webrtc/EncodedImage")),
|
|
||||||
frame_type_class_(jni,
|
|
||||||
FindClass(jni, "org/webrtc/EncodedImage$FrameType")),
|
|
||||||
settings_class_(jni, FindClass(jni, "org/webrtc/VideoDecoder$Settings")),
|
|
||||||
video_frame_class_(jni, FindClass(jni, "org/webrtc/VideoFrame")),
|
|
||||||
video_codec_status_class_(jni,
|
|
||||||
FindClass(jni, "org/webrtc/VideoCodecStatus")),
|
|
||||||
integer_class_(jni, jni->FindClass("java/lang/Integer")) {
|
|
||||||
encoded_image_constructor_ =
|
|
||||||
jni->GetMethodID(*encoded_image_class_, "<init>",
|
|
||||||
"(Ljava/nio/ByteBuffer;IIJLorg/webrtc/"
|
|
||||||
"EncodedImage$FrameType;IZLjava/lang/Integer;)V");
|
|
||||||
settings_constructor_ =
|
|
||||||
jni->GetMethodID(*settings_class_, "<init>", "(III)V");
|
|
||||||
|
|
||||||
empty_frame_field_ = jni->GetStaticFieldID(
|
|
||||||
*frame_type_class_, "EmptyFrame", "Lorg/webrtc/EncodedImage$FrameType;");
|
|
||||||
video_frame_key_field_ =
|
|
||||||
jni->GetStaticFieldID(*frame_type_class_, "VideoFrameKey",
|
|
||||||
"Lorg/webrtc/EncodedImage$FrameType;");
|
|
||||||
video_frame_delta_field_ =
|
|
||||||
jni->GetStaticFieldID(*frame_type_class_, "VideoFrameDelta",
|
|
||||||
"Lorg/webrtc/EncodedImage$FrameType;");
|
|
||||||
|
|
||||||
video_frame_get_timestamp_ns_method_ =
|
|
||||||
jni->GetMethodID(*video_frame_class_, "getTimestampNs", "()J");
|
|
||||||
|
|
||||||
jclass decoder_class = jni->GetObjectClass(decoder);
|
|
||||||
init_decode_method_ =
|
|
||||||
jni->GetMethodID(decoder_class, "initDecode",
|
|
||||||
"(Lorg/webrtc/VideoDecoder$Settings;Lorg/webrtc/"
|
|
||||||
"VideoDecoder$Callback;)Lorg/webrtc/VideoCodecStatus;");
|
|
||||||
release_method_ = jni->GetMethodID(decoder_class, "release",
|
|
||||||
"()Lorg/webrtc/VideoCodecStatus;");
|
|
||||||
decode_method_ = jni->GetMethodID(decoder_class, "decode",
|
|
||||||
"(Lorg/webrtc/EncodedImage;Lorg/webrtc/"
|
|
||||||
"VideoDecoder$DecodeInfo;)Lorg/webrtc/"
|
|
||||||
"VideoCodecStatus;");
|
|
||||||
get_prefers_late_decoding_method_ =
|
|
||||||
jni->GetMethodID(decoder_class, "getPrefersLateDecoding", "()Z");
|
|
||||||
get_implementation_name_method_ = jni->GetMethodID(
|
|
||||||
decoder_class, "getImplementationName", "()Ljava/lang/String;");
|
|
||||||
|
|
||||||
get_number_method_ =
|
|
||||||
jni->GetMethodID(*video_codec_status_class_, "getNumber", "()I");
|
|
||||||
|
|
||||||
integer_constructor_ = jni->GetMethodID(*integer_class_, "<init>", "(I)V");
|
|
||||||
int_value_method_ = jni->GetMethodID(*integer_class_, "intValue", "()I");
|
|
||||||
|
|
||||||
initialized_ = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
int32_t VideoDecoderWrapper::InitDecode(
|
|
||||||
const webrtc::VideoCodec* codec_settings,
|
|
||||||
int32_t number_of_cores) {
|
|
||||||
JNIEnv* jni = AttachCurrentThreadIfNeeded();
|
|
||||||
ScopedLocalRefFrame local_ref_frame(jni);
|
|
||||||
|
|
||||||
codec_settings_ = *codec_settings;
|
|
||||||
number_of_cores_ = number_of_cores;
|
|
||||||
return InitDecodeInternal(jni);
|
|
||||||
}
|
|
||||||
|
|
||||||
int32_t VideoDecoderWrapper::InitDecodeInternal(JNIEnv* jni) {
|
|
||||||
jobject settings =
|
|
||||||
jni->NewObject(*settings_class_, settings_constructor_, number_of_cores_,
|
|
||||||
codec_settings_.width, codec_settings_.height);
|
|
||||||
|
|
||||||
jclass callback_class =
|
|
||||||
FindClass(jni, "org/webrtc/VideoDecoderWrapperCallback");
|
|
||||||
jmethodID callback_constructor =
|
|
||||||
jni->GetMethodID(callback_class, "<init>", "(J)V");
|
|
||||||
jobject callback = jni->NewObject(callback_class, callback_constructor,
|
|
||||||
jlongFromPointer(this));
|
|
||||||
|
|
||||||
jobject ret =
|
|
||||||
jni->CallObjectMethod(*decoder_, init_decode_method_, settings, callback);
|
|
||||||
if (jni->CallIntMethod(ret, get_number_method_) == WEBRTC_VIDEO_CODEC_OK) {
|
|
||||||
initialized_ = true;
|
|
||||||
}
|
|
||||||
return HandleReturnCode(jni, ret);
|
|
||||||
}
|
|
||||||
|
|
||||||
int32_t VideoDecoderWrapper::Decode(
|
|
||||||
const webrtc::EncodedImage& input_image,
|
|
||||||
bool missing_frames,
|
|
||||||
const webrtc::RTPFragmentationHeader* fragmentation,
|
|
||||||
const webrtc::CodecSpecificInfo* codec_specific_info,
|
|
||||||
int64_t render_time_ms) {
|
|
||||||
if (!initialized_) {
|
|
||||||
// Most likely initializing the codec failed.
|
|
||||||
return WEBRTC_VIDEO_CODEC_FALLBACK_SOFTWARE;
|
|
||||||
}
|
|
||||||
|
|
||||||
JNIEnv* jni = AttachCurrentThreadIfNeeded();
|
|
||||||
ScopedLocalRefFrame local_ref_frame(jni);
|
|
||||||
|
|
||||||
FrameExtraInfo frame_extra_info;
|
|
||||||
frame_extra_info.capture_time_ms = input_image.capture_time_ms_;
|
|
||||||
frame_extra_info.timestamp_rtp = input_image._timeStamp;
|
|
||||||
frame_extra_infos_.push_back(frame_extra_info);
|
|
||||||
|
|
||||||
jobject jinput_image =
|
|
||||||
ConvertEncodedImageToJavaEncodedImage(jni, input_image);
|
|
||||||
jobject ret =
|
|
||||||
jni->CallObjectMethod(*decoder_, decode_method_, jinput_image, nullptr);
|
|
||||||
return HandleReturnCode(jni, ret);
|
|
||||||
}
|
|
||||||
|
|
||||||
int32_t VideoDecoderWrapper::RegisterDecodeCompleteCallback(
|
|
||||||
webrtc::DecodedImageCallback* callback) {
|
|
||||||
callback_ = callback;
|
|
||||||
return WEBRTC_VIDEO_CODEC_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
int32_t VideoDecoderWrapper::Release() {
|
|
||||||
JNIEnv* jni = AttachCurrentThreadIfNeeded();
|
|
||||||
ScopedLocalRefFrame local_ref_frame(jni);
|
|
||||||
jobject ret = jni->CallObjectMethod(*decoder_, release_method_);
|
|
||||||
frame_extra_infos_.clear();
|
|
||||||
initialized_ = false;
|
|
||||||
return HandleReturnCode(jni, ret);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool VideoDecoderWrapper::PrefersLateDecoding() const {
|
|
||||||
JNIEnv* jni = AttachCurrentThreadIfNeeded();
|
|
||||||
return jni->CallBooleanMethod(*decoder_, get_prefers_late_decoding_method_);
|
|
||||||
}
|
|
||||||
|
|
||||||
const char* VideoDecoderWrapper::ImplementationName() const {
|
|
||||||
JNIEnv* jni = AttachCurrentThreadIfNeeded();
|
|
||||||
ScopedLocalRefFrame local_ref_frame(jni);
|
|
||||||
jstring jname = reinterpret_cast<jstring>(
|
|
||||||
jni->CallObjectMethod(*decoder_, get_implementation_name_method_));
|
|
||||||
return JavaToStdString(jni, jname).c_str();
|
|
||||||
}
|
|
||||||
|
|
||||||
void VideoDecoderWrapper::OnDecodedFrame(JNIEnv* jni,
|
|
||||||
jobject jframe,
|
|
||||||
jobject jdecode_time_ms,
|
|
||||||
jobject jqp) {
|
|
||||||
const jlong capture_time_ns =
|
|
||||||
jni->CallLongMethod(jframe, video_frame_get_timestamp_ns_method_);
|
|
||||||
const uint32_t capture_time_ms = capture_time_ns / 1000 / 1000;
|
|
||||||
FrameExtraInfo frame_extra_info;
|
|
||||||
do {
|
|
||||||
if (frame_extra_infos_.empty()) {
|
|
||||||
LOG(LS_WARNING) << "Java decoder produced an unexpected frame.";
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
frame_extra_info = frame_extra_infos_.front();
|
|
||||||
frame_extra_infos_.pop_front();
|
|
||||||
// If the decoder might drop frames so iterate through the queue until we
|
|
||||||
// find a matching timestamp.
|
|
||||||
} while (frame_extra_info.capture_time_ms != capture_time_ms);
|
|
||||||
|
|
||||||
webrtc::VideoFrame frame = android_video_buffer_factory_.CreateFrame(
|
|
||||||
jni, jframe, frame_extra_info.timestamp_rtp);
|
|
||||||
|
|
||||||
rtc::Optional<int32_t> decoding_time_ms;
|
|
||||||
if (jdecode_time_ms != nullptr) {
|
|
||||||
decoding_time_ms = rtc::Optional<int32_t>(
|
|
||||||
jni->CallIntMethod(jdecode_time_ms, int_value_method_));
|
|
||||||
}
|
|
||||||
|
|
||||||
rtc::Optional<uint8_t> qp;
|
|
||||||
if (jqp != nullptr) {
|
|
||||||
qp = rtc::Optional<uint8_t>(jni->CallIntMethod(jqp, int_value_method_));
|
|
||||||
}
|
|
||||||
|
|
||||||
callback_->Decoded(frame, decoding_time_ms, rtc::Optional<uint8_t>());
|
|
||||||
}
|
|
||||||
|
|
||||||
jobject VideoDecoderWrapper::ConvertEncodedImageToJavaEncodedImage(
|
|
||||||
JNIEnv* jni,
|
|
||||||
const webrtc::EncodedImage& image) {
|
|
||||||
jobject buffer = jni->NewDirectByteBuffer(image._buffer, image._length);
|
|
||||||
jfieldID frame_type_field;
|
|
||||||
switch (image._frameType) {
|
|
||||||
case webrtc::kEmptyFrame:
|
|
||||||
frame_type_field = empty_frame_field_;
|
|
||||||
break;
|
|
||||||
case webrtc::kVideoFrameKey:
|
|
||||||
frame_type_field = video_frame_key_field_;
|
|
||||||
break;
|
|
||||||
case webrtc::kVideoFrameDelta:
|
|
||||||
frame_type_field = video_frame_delta_field_;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
RTC_NOTREACHED();
|
|
||||||
}
|
|
||||||
jobject frame_type =
|
|
||||||
jni->GetStaticObjectField(*frame_type_class_, frame_type_field);
|
|
||||||
jobject qp = nullptr;
|
|
||||||
if (image.qp_ != -1) {
|
|
||||||
qp = jni->NewObject(*integer_class_, integer_constructor_, image.qp_);
|
|
||||||
}
|
|
||||||
return jni->NewObject(*encoded_image_class_, encoded_image_constructor_,
|
|
||||||
buffer, static_cast<jint>(image._encodedWidth),
|
|
||||||
static_cast<jint>(image._encodedHeight),
|
|
||||||
static_cast<jlong>(image.capture_time_ms_), frame_type,
|
|
||||||
static_cast<jint>(image.rotation_),
|
|
||||||
image._completeFrame, qp);
|
|
||||||
}
|
|
||||||
|
|
||||||
int32_t VideoDecoderWrapper::HandleReturnCode(JNIEnv* jni, jobject code) {
|
|
||||||
int32_t value = jni->CallIntMethod(code, get_number_method_);
|
|
||||||
if (value < 0) { // Any errors are represented by negative values.
|
|
||||||
// Reset the codec.
|
|
||||||
if (Release() == WEBRTC_VIDEO_CODEC_OK) {
|
|
||||||
InitDecodeInternal(jni);
|
|
||||||
}
|
|
||||||
|
|
||||||
LOG(LS_WARNING) << "Falling back to software decoder.";
|
|
||||||
return WEBRTC_VIDEO_CODEC_FALLBACK_SOFTWARE;
|
|
||||||
} else {
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
JOW(void, VideoDecoderWrapperCallback_nativeOnDecodedFrame)
|
|
||||||
(JNIEnv* jni,
|
|
||||||
jclass,
|
|
||||||
jlong jnative_decoder,
|
|
||||||
jobject jframe,
|
|
||||||
jobject jdecode_time_ms,
|
|
||||||
jobject jqp) {
|
|
||||||
VideoDecoderWrapper* native_decoder =
|
|
||||||
reinterpret_cast<VideoDecoderWrapper*>(jnative_decoder);
|
|
||||||
native_decoder->OnDecodedFrame(jni, jframe, jdecode_time_ms, jqp);
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace webrtc_jni
|
|
||||||
@ -1,115 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2017 The WebRTC project authors. All Rights Reserved.
|
|
||||||
*
|
|
||||||
* Use of this source code is governed by a BSD-style license
|
|
||||||
* that can be found in the LICENSE file in the root of the source
|
|
||||||
* tree. An additional intellectual property rights grant can be found
|
|
||||||
* in the file PATENTS. All contributing project authors may
|
|
||||||
* be found in the AUTHORS file in the root of the source tree.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef WEBRTC_SDK_ANDROID_SRC_JNI_VIDEODECODERWRAPPER_H_
|
|
||||||
#define WEBRTC_SDK_ANDROID_SRC_JNI_VIDEODECODERWRAPPER_H_
|
|
||||||
|
|
||||||
#include <jni.h>
|
|
||||||
|
|
||||||
#include <deque>
|
|
||||||
|
|
||||||
#include "webrtc/api/video_codecs/video_decoder.h"
|
|
||||||
#include "webrtc/sdk/android/src/jni/jni_helpers.h"
|
|
||||||
#include "webrtc/sdk/android/src/jni/native_handle_impl.h"
|
|
||||||
|
|
||||||
namespace webrtc_jni {
|
|
||||||
|
|
||||||
// Wraps a Java decoder and delegates all calls to it. Passes
|
|
||||||
// VideoDecoderWrapperCallback to the decoder on InitDecode. Wraps the received
|
|
||||||
// frames to AndroidVideoBuffer.
|
|
||||||
class VideoDecoderWrapper : public webrtc::VideoDecoder {
|
|
||||||
public:
|
|
||||||
VideoDecoderWrapper(JNIEnv* jni, jobject decoder);
|
|
||||||
|
|
||||||
int32_t InitDecode(const webrtc::VideoCodec* codec_settings,
|
|
||||||
int32_t number_of_cores) override;
|
|
||||||
|
|
||||||
int32_t Decode(const webrtc::EncodedImage& input_image,
|
|
||||||
bool missing_frames,
|
|
||||||
const webrtc::RTPFragmentationHeader* fragmentation,
|
|
||||||
const webrtc::CodecSpecificInfo* codec_specific_info,
|
|
||||||
int64_t render_time_ms) override;
|
|
||||||
|
|
||||||
int32_t RegisterDecodeCompleteCallback(
|
|
||||||
webrtc::DecodedImageCallback* callback) override;
|
|
||||||
|
|
||||||
int32_t Release() override;
|
|
||||||
|
|
||||||
// Returns true if the decoder prefer to decode frames late.
|
|
||||||
// That is, it can not decode infinite number of frames before the decoded
|
|
||||||
// frame is consumed.
|
|
||||||
bool PrefersLateDecoding() const override;
|
|
||||||
|
|
||||||
const char* ImplementationName() const override;
|
|
||||||
|
|
||||||
// Wraps the frame to a AndroidVideoBuffer and passes it to the callback.
|
|
||||||
void OnDecodedFrame(JNIEnv* jni,
|
|
||||||
jobject jframe,
|
|
||||||
jobject jdecode_time_ms,
|
|
||||||
jobject jqp);
|
|
||||||
|
|
||||||
private:
|
|
||||||
struct FrameExtraInfo {
|
|
||||||
uint32_t capture_time_ms; // Used as an identifier of the frame.
|
|
||||||
|
|
||||||
uint32_t timestamp_rtp;
|
|
||||||
};
|
|
||||||
|
|
||||||
int32_t InitDecodeInternal(JNIEnv* jni);
|
|
||||||
|
|
||||||
// Takes Java VideoCodecStatus, handles it and returns WEBRTC_VIDEO_CODEC_*
|
|
||||||
// status code.
|
|
||||||
int32_t HandleReturnCode(JNIEnv* jni, jobject code);
|
|
||||||
|
|
||||||
webrtc::VideoCodec codec_settings_;
|
|
||||||
int32_t number_of_cores_;
|
|
||||||
|
|
||||||
bool initialized_;
|
|
||||||
AndroidVideoBufferFactory android_video_buffer_factory_;
|
|
||||||
std::deque<FrameExtraInfo> frame_extra_infos_;
|
|
||||||
|
|
||||||
webrtc::DecodedImageCallback* callback_;
|
|
||||||
|
|
||||||
const ScopedGlobalRef<jobject> decoder_;
|
|
||||||
const ScopedGlobalRef<jclass> encoded_image_class_;
|
|
||||||
const ScopedGlobalRef<jclass> frame_type_class_;
|
|
||||||
const ScopedGlobalRef<jclass> settings_class_;
|
|
||||||
const ScopedGlobalRef<jclass> video_frame_class_;
|
|
||||||
const ScopedGlobalRef<jclass> video_codec_status_class_;
|
|
||||||
const ScopedGlobalRef<jclass> integer_class_;
|
|
||||||
|
|
||||||
jmethodID encoded_image_constructor_;
|
|
||||||
jmethodID settings_constructor_;
|
|
||||||
|
|
||||||
jfieldID empty_frame_field_;
|
|
||||||
jfieldID video_frame_key_field_;
|
|
||||||
jfieldID video_frame_delta_field_;
|
|
||||||
|
|
||||||
jmethodID video_frame_get_timestamp_ns_method_;
|
|
||||||
|
|
||||||
jmethodID init_decode_method_;
|
|
||||||
jmethodID release_method_;
|
|
||||||
jmethodID decode_method_;
|
|
||||||
jmethodID get_prefers_late_decoding_method_;
|
|
||||||
jmethodID get_implementation_name_method_;
|
|
||||||
|
|
||||||
jmethodID get_number_method_;
|
|
||||||
|
|
||||||
jmethodID integer_constructor_;
|
|
||||||
jmethodID int_value_method_;
|
|
||||||
|
|
||||||
jobject ConvertEncodedImageToJavaEncodedImage(
|
|
||||||
JNIEnv* jni,
|
|
||||||
const webrtc::EncodedImage& image);
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace webrtc_jni
|
|
||||||
|
|
||||||
#endif // WEBRTC_SDK_ANDROID_SRC_JNI_VIDEODECODERWRAPPER_H_
|
|
||||||
Reference in New Issue
Block a user