PeerConnection(java): replace ScopedLocalRef with ScopedLocalRefFrame and fix a local reference leak in OnMessage.
Hopefully the approach of pushing/popping frames will be easier to avoid messing up than remembering to annotate every single local reference with a ScopedLocalRef. BUG=2761 R=wu@webrtc.org Review URL: https://webrtc-codereview.appspot.com/6729004 git-svn-id: http://webrtc.googlecode.com/svn/trunk@5355 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
parent
1794693ec8
commit
4177615e87
@ -376,22 +376,20 @@ class WeakRef {
|
||||
jobject const obj_;
|
||||
};
|
||||
|
||||
// Given a local ref, take ownership of it and delete the ref when this goes out
|
||||
// of scope.
|
||||
template<class T> // T is jclass, jobject, jintArray, etc.
|
||||
class ScopedLocalRef {
|
||||
// Scope Java local references to the lifetime of this object. Use in all C++
|
||||
// callbacks (i.e. entry points that don't originate in a Java callstack
|
||||
// through a "native" method call).
|
||||
class ScopedLocalRefFrame {
|
||||
public:
|
||||
ScopedLocalRef(JNIEnv* jni, T obj)
|
||||
: jni_(jni), obj_(obj) {}
|
||||
~ScopedLocalRef() {
|
||||
jni_->DeleteLocalRef(obj_);
|
||||
explicit ScopedLocalRefFrame(JNIEnv* jni) : jni_(jni) {
|
||||
CHECK(!jni_->PushLocalFrame(0), "Failed to PushLocalFrame");
|
||||
}
|
||||
T operator*() const {
|
||||
return obj_;
|
||||
~ScopedLocalRefFrame() {
|
||||
jni_->PopLocalFrame(NULL);
|
||||
}
|
||||
|
||||
private:
|
||||
JNIEnv* jni_;
|
||||
T obj_;
|
||||
};
|
||||
|
||||
// Scoped holder for global Java refs.
|
||||
@ -418,11 +416,10 @@ jobject JavaEnumFromIndex(
|
||||
jclass state_class = FindClass(jni, state_class_name.c_str());
|
||||
jmethodID state_values_id = GetStaticMethodID(
|
||||
jni, state_class, "values", ("()[L" + state_class_name + ";").c_str());
|
||||
ScopedLocalRef<jobjectArray> state_values(
|
||||
jni,
|
||||
(jobjectArray)jni->CallStaticObjectMethod(state_class, state_values_id));
|
||||
jobjectArray state_values = static_cast<jobjectArray>(
|
||||
jni->CallStaticObjectMethod(state_class, state_values_id));
|
||||
CHECK_EXCEPTION(jni, "error during CallStaticObjectMethod");
|
||||
jobject ret = jni->GetObjectArrayElement(*state_values, index);
|
||||
jobject ret = jni->GetObjectArrayElement(state_values, index);
|
||||
CHECK_EXCEPTION(jni, "error during GetObjectArrayElement");
|
||||
return ret;
|
||||
}
|
||||
@ -500,20 +497,20 @@ class PCOJava : public PeerConnectionObserver {
|
||||
virtual ~PCOJava() {}
|
||||
|
||||
virtual void OnIceCandidate(const IceCandidateInterface* candidate) OVERRIDE {
|
||||
ScopedLocalRefFrame local_ref_frame(jni());
|
||||
std::string sdp;
|
||||
CHECK(candidate->ToString(&sdp), "got so far: " << sdp);
|
||||
jclass candidate_class = FindClass(jni(), "org/webrtc/IceCandidate");
|
||||
jmethodID ctor = GetMethodID(jni(), candidate_class,
|
||||
"<init>", "(Ljava/lang/String;ILjava/lang/String;)V");
|
||||
ScopedLocalRef<jstring> j_mid(
|
||||
jni(), JavaStringFromStdString(jni(), candidate->sdp_mid()));
|
||||
ScopedLocalRef<jstring> j_sdp(jni(), JavaStringFromStdString(jni(), sdp));
|
||||
ScopedLocalRef<jobject> j_candidate(jni(), jni()->NewObject(
|
||||
candidate_class, ctor, *j_mid, candidate->sdp_mline_index(), *j_sdp));
|
||||
jstring j_mid = JavaStringFromStdString(jni(), candidate->sdp_mid());
|
||||
jstring j_sdp = JavaStringFromStdString(jni(), sdp);
|
||||
jobject j_candidate = jni()->NewObject(
|
||||
candidate_class, ctor, j_mid, candidate->sdp_mline_index(), j_sdp);
|
||||
CHECK_EXCEPTION(jni(), "error during NewObject");
|
||||
jmethodID m = GetMethodID(jni(), *j_observer_class_,
|
||||
"onIceCandidate", "(Lorg/webrtc/IceCandidate;)V");
|
||||
jni()->CallVoidMethod(*j_observer_global_, m, *j_candidate);
|
||||
jni()->CallVoidMethod(*j_observer_global_, m, j_candidate);
|
||||
CHECK_EXCEPTION(jni(), "error during CallVoidMethod");
|
||||
}
|
||||
|
||||
@ -525,59 +522,63 @@ class PCOJava : public PeerConnectionObserver {
|
||||
|
||||
virtual void OnSignalingChange(
|
||||
PeerConnectionInterface::SignalingState new_state) OVERRIDE {
|
||||
ScopedLocalRefFrame local_ref_frame(jni());
|
||||
jmethodID m = GetMethodID(
|
||||
jni(), *j_observer_class_, "onSignalingChange",
|
||||
"(Lorg/webrtc/PeerConnection$SignalingState;)V");
|
||||
ScopedLocalRef<jobject> new_state_enum(jni(), JavaEnumFromIndex(
|
||||
jni(), "PeerConnection$SignalingState", new_state));
|
||||
jni()->CallVoidMethod(*j_observer_global_, m, *new_state_enum);
|
||||
jobject new_state_enum =
|
||||
JavaEnumFromIndex(jni(), "PeerConnection$SignalingState", new_state);
|
||||
jni()->CallVoidMethod(*j_observer_global_, m, new_state_enum);
|
||||
CHECK_EXCEPTION(jni(), "error during CallVoidMethod");
|
||||
}
|
||||
|
||||
virtual void OnIceConnectionChange(
|
||||
PeerConnectionInterface::IceConnectionState new_state) OVERRIDE {
|
||||
ScopedLocalRefFrame local_ref_frame(jni());
|
||||
jmethodID m = GetMethodID(
|
||||
jni(), *j_observer_class_, "onIceConnectionChange",
|
||||
"(Lorg/webrtc/PeerConnection$IceConnectionState;)V");
|
||||
ScopedLocalRef<jobject> new_state_enum(jni(), JavaEnumFromIndex(
|
||||
jni(), "PeerConnection$IceConnectionState", new_state));
|
||||
jni()->CallVoidMethod(*j_observer_global_, m, *new_state_enum);
|
||||
jobject new_state_enum = JavaEnumFromIndex(
|
||||
jni(), "PeerConnection$IceConnectionState", new_state);
|
||||
jni()->CallVoidMethod(*j_observer_global_, m, new_state_enum);
|
||||
CHECK_EXCEPTION(jni(), "error during CallVoidMethod");
|
||||
}
|
||||
|
||||
virtual void OnIceGatheringChange(
|
||||
PeerConnectionInterface::IceGatheringState new_state) OVERRIDE {
|
||||
ScopedLocalRefFrame local_ref_frame(jni());
|
||||
jmethodID m = GetMethodID(
|
||||
jni(), *j_observer_class_, "onIceGatheringChange",
|
||||
"(Lorg/webrtc/PeerConnection$IceGatheringState;)V");
|
||||
ScopedLocalRef<jobject> new_state_enum(jni(), JavaEnumFromIndex(
|
||||
jni(), "PeerConnection$IceGatheringState", new_state));
|
||||
jni()->CallVoidMethod(*j_observer_global_, m, *new_state_enum);
|
||||
jobject new_state_enum = JavaEnumFromIndex(
|
||||
jni(), "PeerConnection$IceGatheringState", new_state);
|
||||
jni()->CallVoidMethod(*j_observer_global_, m, new_state_enum);
|
||||
CHECK_EXCEPTION(jni(), "error during CallVoidMethod");
|
||||
}
|
||||
|
||||
virtual void OnAddStream(MediaStreamInterface* stream) OVERRIDE {
|
||||
ScopedLocalRef<jobject> j_stream(jni(), jni()->NewObject(
|
||||
*j_media_stream_class_, j_media_stream_ctor_, (jlong)stream));
|
||||
ScopedLocalRefFrame local_ref_frame(jni());
|
||||
jobject j_stream = jni()->NewObject(
|
||||
*j_media_stream_class_, j_media_stream_ctor_, (jlong)stream);
|
||||
CHECK_EXCEPTION(jni(), "error during NewObject");
|
||||
|
||||
AudioTrackVector audio_tracks = stream->GetAudioTracks();
|
||||
for (size_t i = 0; i < audio_tracks.size(); ++i) {
|
||||
AudioTrackInterface* track = audio_tracks[i];
|
||||
ScopedLocalRef<jstring> id(
|
||||
jni(), JavaStringFromStdString(jni(), track->id()));
|
||||
ScopedLocalRef<jobject> j_track(jni(), jni()->NewObject(
|
||||
*j_audio_track_class_, j_audio_track_ctor_, (jlong)track, *id));
|
||||
jstring id = JavaStringFromStdString(jni(), track->id());
|
||||
jobject j_track = jni()->NewObject(
|
||||
*j_audio_track_class_, j_audio_track_ctor_, (jlong)track, id);
|
||||
CHECK_EXCEPTION(jni(), "error during NewObject");
|
||||
jfieldID audio_tracks_id = GetFieldID(jni(),
|
||||
*j_media_stream_class_,
|
||||
"audioTracks",
|
||||
"Ljava/util/LinkedList;");
|
||||
ScopedLocalRef<jobject> audio_tracks(jni(), GetObjectField(
|
||||
jni(), *j_stream, audio_tracks_id));
|
||||
jobject audio_tracks = GetObjectField(jni(), j_stream, audio_tracks_id);
|
||||
jmethodID add = GetMethodID(jni(),
|
||||
GetObjectClass(jni(), *audio_tracks), "add", "(Ljava/lang/Object;)Z");
|
||||
jboolean added = jni()->CallBooleanMethod(*audio_tracks, add, *j_track);
|
||||
GetObjectClass(jni(), audio_tracks),
|
||||
"add",
|
||||
"(Ljava/lang/Object;)Z");
|
||||
jboolean added = jni()->CallBooleanMethod(audio_tracks, add, j_track);
|
||||
CHECK_EXCEPTION(jni(), "error during CallBooleanMethod");
|
||||
CHECK(added, "");
|
||||
}
|
||||
@ -585,33 +586,34 @@ class PCOJava : public PeerConnectionObserver {
|
||||
VideoTrackVector video_tracks = stream->GetVideoTracks();
|
||||
for (size_t i = 0; i < video_tracks.size(); ++i) {
|
||||
VideoTrackInterface* track = video_tracks[i];
|
||||
ScopedLocalRef<jstring> id(
|
||||
jni(), JavaStringFromStdString(jni(), track->id()));
|
||||
ScopedLocalRef<jobject> j_track(jni(), jni()->NewObject(
|
||||
*j_video_track_class_, j_video_track_ctor_, (jlong)track, *id));
|
||||
jstring id = JavaStringFromStdString(jni(), track->id());
|
||||
jobject j_track = jni()->NewObject(
|
||||
*j_video_track_class_, j_video_track_ctor_, (jlong)track, id);
|
||||
CHECK_EXCEPTION(jni(), "error during NewObject");
|
||||
jfieldID video_tracks_id = GetFieldID(jni(),
|
||||
*j_media_stream_class_,
|
||||
"videoTracks",
|
||||
"Ljava/util/LinkedList;");
|
||||
ScopedLocalRef<jobject> video_tracks(jni(), GetObjectField(
|
||||
jni(), *j_stream, video_tracks_id));
|
||||
jobject video_tracks = GetObjectField(jni(), j_stream, video_tracks_id);
|
||||
jmethodID add = GetMethodID(jni(),
|
||||
GetObjectClass(jni(), *video_tracks), "add", "(Ljava/lang/Object;)Z");
|
||||
jboolean added = jni()->CallBooleanMethod(*video_tracks, add, *j_track);
|
||||
GetObjectClass(jni(), video_tracks),
|
||||
"add",
|
||||
"(Ljava/lang/Object;)Z");
|
||||
jboolean added = jni()->CallBooleanMethod(video_tracks, add, j_track);
|
||||
CHECK_EXCEPTION(jni(), "error during CallBooleanMethod");
|
||||
CHECK(added, "");
|
||||
}
|
||||
streams_[stream] = jni()->NewWeakGlobalRef(*j_stream);
|
||||
streams_[stream] = jni()->NewWeakGlobalRef(j_stream);
|
||||
CHECK_EXCEPTION(jni(), "error during NewWeakGlobalRef");
|
||||
|
||||
jmethodID m = GetMethodID(jni(), *j_observer_class_, "onAddStream",
|
||||
"(Lorg/webrtc/MediaStream;)V");
|
||||
jni()->CallVoidMethod(*j_observer_global_, m, *j_stream);
|
||||
jni()->CallVoidMethod(*j_observer_global_, m, j_stream);
|
||||
CHECK_EXCEPTION(jni(), "error during CallVoidMethod");
|
||||
}
|
||||
|
||||
virtual void OnRemoveStream(MediaStreamInterface* stream) OVERRIDE {
|
||||
ScopedLocalRefFrame local_ref_frame(jni());
|
||||
NativeToJavaStreamsMap::iterator it = streams_.find(stream);
|
||||
CHECK(it != streams_.end(), "unexpected stream: " << std::hex << stream);
|
||||
|
||||
@ -627,13 +629,14 @@ class PCOJava : public PeerConnectionObserver {
|
||||
}
|
||||
|
||||
virtual void OnDataChannel(DataChannelInterface* channel) OVERRIDE {
|
||||
ScopedLocalRef<jobject> j_channel(jni(), jni()->NewObject(
|
||||
*j_data_channel_class_, j_data_channel_ctor_, (jlong)channel));
|
||||
ScopedLocalRefFrame local_ref_frame(jni());
|
||||
jobject j_channel = jni()->NewObject(
|
||||
*j_data_channel_class_, j_data_channel_ctor_, (jlong)channel);
|
||||
CHECK_EXCEPTION(jni(), "error during NewObject");
|
||||
|
||||
jmethodID m = GetMethodID(jni(), *j_observer_class_, "onDataChannel",
|
||||
"(Lorg/webrtc/DataChannel;)V");
|
||||
jni()->CallVoidMethod(*j_observer_global_, m, *j_channel);
|
||||
jni()->CallVoidMethod(*j_observer_global_, m, j_channel);
|
||||
|
||||
// Channel is now owned by Java object, and will be freed from
|
||||
// DataChannel.dispose(). Important that this be done _after_ the
|
||||
@ -738,17 +741,16 @@ static jobject JavaSdpFromNativeSdp(
|
||||
JNIEnv* jni, const SessionDescriptionInterface* desc) {
|
||||
std::string sdp;
|
||||
CHECK(desc->ToString(&sdp), "got so far: " << sdp);
|
||||
ScopedLocalRef<jstring> j_description(jni, JavaStringFromStdString(jni, sdp));
|
||||
jstring j_description = JavaStringFromStdString(jni, sdp);
|
||||
|
||||
jclass j_type_class = FindClass(
|
||||
jni, "org/webrtc/SessionDescription$Type");
|
||||
jmethodID j_type_from_canonical = GetStaticMethodID(
|
||||
jni, j_type_class, "fromCanonicalForm",
|
||||
"(Ljava/lang/String;)Lorg/webrtc/SessionDescription$Type;");
|
||||
ScopedLocalRef<jstring> j_type_string(
|
||||
jni, JavaStringFromStdString(jni, desc->type()));
|
||||
jstring j_type_string = JavaStringFromStdString(jni, desc->type());
|
||||
jobject j_type = jni->CallStaticObjectMethod(
|
||||
j_type_class, j_type_from_canonical, *j_type_string);
|
||||
j_type_class, j_type_from_canonical, j_type_string);
|
||||
CHECK_EXCEPTION(jni, "error during CallObjectMethod");
|
||||
|
||||
jclass j_sdp_class = FindClass(jni, "org/webrtc/SessionDescription");
|
||||
@ -756,7 +758,7 @@ static jobject JavaSdpFromNativeSdp(
|
||||
jni, j_sdp_class, "<init>",
|
||||
"(Lorg/webrtc/SessionDescription$Type;Ljava/lang/String;)V");
|
||||
jobject j_sdp = jni->NewObject(
|
||||
j_sdp_class, j_sdp_ctor, j_type, *j_description);
|
||||
j_sdp_class, j_sdp_ctor, j_type, j_description);
|
||||
CHECK_EXCEPTION(jni, "error during NewObject");
|
||||
return j_sdp;
|
||||
}
|
||||
@ -775,6 +777,7 @@ class SdpObserverWrapper : public T {
|
||||
|
||||
// Can't mark OVERRIDE because of templating.
|
||||
virtual void OnSuccess() {
|
||||
ScopedLocalRefFrame local_ref_frame(jni());
|
||||
jmethodID m = GetMethodID(jni(), *j_observer_class_, "onSetSuccess", "()V");
|
||||
jni()->CallVoidMethod(*j_observer_global_, m);
|
||||
CHECK_EXCEPTION(jni(), "error during CallVoidMethod");
|
||||
@ -782,11 +785,12 @@ class SdpObserverWrapper : public T {
|
||||
|
||||
// Can't mark OVERRIDE because of templating.
|
||||
virtual void OnSuccess(SessionDescriptionInterface* desc) {
|
||||
ScopedLocalRefFrame local_ref_frame(jni());
|
||||
jmethodID m = GetMethodID(
|
||||
jni(), *j_observer_class_, "onCreateSuccess",
|
||||
"(Lorg/webrtc/SessionDescription;)V");
|
||||
ScopedLocalRef<jobject> j_sdp(jni(), JavaSdpFromNativeSdp(jni(), desc));
|
||||
jni()->CallVoidMethod(*j_observer_global_, m, *j_sdp);
|
||||
jobject j_sdp = JavaSdpFromNativeSdp(jni(), desc);
|
||||
jni()->CallVoidMethod(*j_observer_global_, m, j_sdp);
|
||||
CHECK_EXCEPTION(jni(), "error during CallVoidMethod");
|
||||
}
|
||||
|
||||
@ -796,17 +800,16 @@ class SdpObserverWrapper : public T {
|
||||
void OnFailure(const std::string& op, const std::string& error) {
|
||||
jmethodID m = GetMethodID(jni(), *j_observer_class_, "on" + op + "Failure",
|
||||
"(Ljava/lang/String;)V");
|
||||
ScopedLocalRef<jstring> j_error_string(
|
||||
jni(), JavaStringFromStdString(jni(), error));
|
||||
jni()->CallVoidMethod(*j_observer_global_, m, *j_error_string);
|
||||
jstring j_error_string = JavaStringFromStdString(jni(), error);
|
||||
jni()->CallVoidMethod(*j_observer_global_, m, j_error_string);
|
||||
CHECK_EXCEPTION(jni(), "error during CallVoidMethod");
|
||||
}
|
||||
|
||||
private:
|
||||
JNIEnv* jni() {
|
||||
return AttachCurrentThreadIfNeeded();
|
||||
}
|
||||
|
||||
private:
|
||||
talk_base::scoped_ptr<ConstraintsWrapper> constraints_;
|
||||
const ScopedGlobalRef<jobject> j_observer_global_;
|
||||
const ScopedGlobalRef<jclass> j_observer_class_;
|
||||
@ -820,6 +823,7 @@ class CreateSdpObserverWrapper
|
||||
: SdpObserverWrapper(jni, j_observer, constraints) {}
|
||||
|
||||
virtual void OnFailure(const std::string& error) OVERRIDE {
|
||||
ScopedLocalRefFrame local_ref_frame(jni());
|
||||
SdpObserverWrapper::OnFailure(std::string("Create"), error);
|
||||
}
|
||||
};
|
||||
@ -832,6 +836,7 @@ class SetSdpObserverWrapper
|
||||
: SdpObserverWrapper(jni, j_observer, constraints) {}
|
||||
|
||||
virtual void OnFailure(const std::string& error) OVERRIDE {
|
||||
ScopedLocalRefFrame local_ref_frame(jni());
|
||||
SdpObserverWrapper::OnFailure(std::string("Set"), error);
|
||||
}
|
||||
};
|
||||
@ -855,11 +860,13 @@ class DataChannelObserverWrapper : public DataChannelObserver {
|
||||
virtual ~DataChannelObserverWrapper() {}
|
||||
|
||||
virtual void OnStateChange() OVERRIDE {
|
||||
ScopedLocalRefFrame local_ref_frame(jni());
|
||||
jni()->CallVoidMethod(*j_observer_global_, j_on_state_change_mid_);
|
||||
CHECK_EXCEPTION(jni(), "error during CallVoidMethod");
|
||||
}
|
||||
|
||||
virtual void OnMessage(const DataBuffer& buffer) OVERRIDE {
|
||||
ScopedLocalRefFrame local_ref_frame(jni());
|
||||
jobject byte_buffer =
|
||||
jni()->NewDirectByteBuffer(const_cast<char*>(buffer.data.data()),
|
||||
buffer.data.length());
|
||||
@ -904,11 +911,11 @@ class StatsObserverWrapper : public StatsObserver {
|
||||
virtual ~StatsObserverWrapper() {}
|
||||
|
||||
virtual void OnComplete(const std::vector<StatsReport>& reports) OVERRIDE {
|
||||
ScopedLocalRef<jobjectArray> j_reports(jni(),
|
||||
ReportsToJava(jni(), reports));
|
||||
ScopedLocalRefFrame local_ref_frame(jni());
|
||||
jobjectArray j_reports = ReportsToJava(jni(), reports);
|
||||
jmethodID m = GetMethodID(jni(), *j_observer_class_, "onComplete",
|
||||
"([Lorg/webrtc/StatsReport;)V");
|
||||
jni()->CallVoidMethod(*j_observer_global_, m, *j_reports);
|
||||
jni()->CallVoidMethod(*j_observer_global_, m, j_reports);
|
||||
CHECK_EXCEPTION(jni(), "error during CallVoidMethod");
|
||||
}
|
||||
|
||||
@ -918,17 +925,18 @@ class StatsObserverWrapper : public StatsObserver {
|
||||
jobjectArray reports_array = jni->NewObjectArray(
|
||||
reports.size(), *j_stats_report_class_, NULL);
|
||||
for (int i = 0; i < reports.size(); ++i) {
|
||||
ScopedLocalRefFrame local_ref_frame(jni);
|
||||
const StatsReport& report = reports[i];
|
||||
ScopedLocalRef<jstring> j_id(
|
||||
jni, JavaStringFromStdString(jni, report.id));
|
||||
ScopedLocalRef<jstring> j_type(
|
||||
jni, JavaStringFromStdString(jni, report.type));
|
||||
ScopedLocalRef<jobjectArray> j_values(
|
||||
jni, ValuesToJava(jni, report.values));
|
||||
ScopedLocalRef<jobject> j_report(jni, jni->NewObject(
|
||||
*j_stats_report_class_, j_stats_report_ctor_, *j_id, *j_type,
|
||||
report.timestamp, *j_values));
|
||||
jni->SetObjectArrayElement(reports_array, i, *j_report);
|
||||
jstring j_id = JavaStringFromStdString(jni, report.id);
|
||||
jstring j_type = JavaStringFromStdString(jni, report.type);
|
||||
jobjectArray j_values = ValuesToJava(jni, report.values);
|
||||
jobject j_report = jni->NewObject(*j_stats_report_class_,
|
||||
j_stats_report_ctor_,
|
||||
j_id,
|
||||
j_type,
|
||||
report.timestamp,
|
||||
j_values);
|
||||
jni->SetObjectArrayElement(reports_array, i, j_report);
|
||||
}
|
||||
return reports_array;
|
||||
}
|
||||
@ -937,14 +945,13 @@ class StatsObserverWrapper : public StatsObserver {
|
||||
jobjectArray j_values = jni->NewObjectArray(
|
||||
values.size(), *j_value_class_, NULL);
|
||||
for (int i = 0; i < values.size(); ++i) {
|
||||
ScopedLocalRefFrame local_ref_frame(jni);
|
||||
const StatsReport::Value& value = values[i];
|
||||
ScopedLocalRef<jstring> j_name(
|
||||
jni, JavaStringFromStdString(jni, value.name));
|
||||
ScopedLocalRef<jstring> j_value(
|
||||
jni, JavaStringFromStdString(jni, value.value));
|
||||
ScopedLocalRef<jobject> j_element_value(jni, jni->NewObject(
|
||||
*j_value_class_, j_value_ctor_, *j_name, *j_value));
|
||||
jni->SetObjectArrayElement(j_values, i, *j_element_value);
|
||||
jstring j_name = JavaStringFromStdString(jni, value.name);
|
||||
jstring j_value = JavaStringFromStdString(jni, value.value);
|
||||
jobject j_element_value =
|
||||
jni->NewObject(*j_value_class_, j_value_ctor_, j_name, j_value);
|
||||
jni->SetObjectArrayElement(j_values, i, j_element_value);
|
||||
}
|
||||
return j_values;
|
||||
}
|
||||
@ -974,11 +981,13 @@ class VideoRendererWrapper : public VideoRendererInterface {
|
||||
virtual ~VideoRendererWrapper() {}
|
||||
|
||||
virtual void SetSize(int width, int height) OVERRIDE {
|
||||
ScopedLocalRefFrame local_ref_frame(AttachCurrentThreadIfNeeded());
|
||||
const bool kNotReserved = false; // What does this param mean??
|
||||
renderer_->SetSize(width, height, kNotReserved);
|
||||
}
|
||||
|
||||
virtual void RenderFrame(const cricket::VideoFrame* frame) OVERRIDE {
|
||||
ScopedLocalRefFrame local_ref_frame(AttachCurrentThreadIfNeeded());
|
||||
renderer_->RenderFrame(frame);
|
||||
}
|
||||
|
||||
@ -1011,40 +1020,41 @@ class JavaVideoRendererWrapper : public VideoRendererInterface {
|
||||
virtual ~JavaVideoRendererWrapper() {}
|
||||
|
||||
virtual void SetSize(int width, int height) OVERRIDE {
|
||||
ScopedLocalRefFrame local_ref_frame(jni());
|
||||
jni()->CallVoidMethod(*j_callbacks_, j_set_size_id_, width, height);
|
||||
CHECK_EXCEPTION(jni(), "");
|
||||
}
|
||||
|
||||
virtual void RenderFrame(const cricket::VideoFrame* frame) OVERRIDE {
|
||||
ScopedLocalRef<jobject> j_frame(jni(), CricketToJavaFrame(frame));
|
||||
jni()->CallVoidMethod(*j_callbacks_, j_render_frame_id_, *j_frame);
|
||||
ScopedLocalRefFrame local_ref_frame(jni());
|
||||
jobject j_frame = CricketToJavaFrame(frame);
|
||||
jni()->CallVoidMethod(*j_callbacks_, j_render_frame_id_, j_frame);
|
||||
CHECK_EXCEPTION(jni(), "");
|
||||
}
|
||||
|
||||
private:
|
||||
// Return a VideoRenderer.I420Frame referring to the data in |frame|.
|
||||
jobject CricketToJavaFrame(const cricket::VideoFrame* frame) {
|
||||
ScopedLocalRef<jintArray> strides(jni(), jni()->NewIntArray(3));
|
||||
jint* strides_array = jni()->GetIntArrayElements(*strides, NULL);
|
||||
jintArray strides = jni()->NewIntArray(3);
|
||||
jint* strides_array = jni()->GetIntArrayElements(strides, NULL);
|
||||
strides_array[0] = frame->GetYPitch();
|
||||
strides_array[1] = frame->GetUPitch();
|
||||
strides_array[2] = frame->GetVPitch();
|
||||
jni()->ReleaseIntArrayElements(*strides, strides_array, 0);
|
||||
ScopedLocalRef<jobjectArray> planes(
|
||||
jni(), jni()->NewObjectArray(3, *j_byte_buffer_class_, NULL));
|
||||
ScopedLocalRef<jobject> y_buffer(jni(), jni()->NewDirectByteBuffer(
|
||||
jni()->ReleaseIntArrayElements(strides, strides_array, 0);
|
||||
jobjectArray planes = jni()->NewObjectArray(3, *j_byte_buffer_class_, NULL);
|
||||
jobject y_buffer = jni()->NewDirectByteBuffer(
|
||||
const_cast<uint8*>(frame->GetYPlane()),
|
||||
frame->GetYPitch() * frame->GetHeight()));
|
||||
ScopedLocalRef<jobject> u_buffer(jni(), jni()->NewDirectByteBuffer(
|
||||
const_cast<uint8*>(frame->GetUPlane()), frame->GetChromaSize()));
|
||||
ScopedLocalRef<jobject> v_buffer(jni(), jni()->NewDirectByteBuffer(
|
||||
const_cast<uint8*>(frame->GetVPlane()), frame->GetChromaSize()));
|
||||
jni()->SetObjectArrayElement(*planes, 0, *y_buffer);
|
||||
jni()->SetObjectArrayElement(*planes, 1, *u_buffer);
|
||||
jni()->SetObjectArrayElement(*planes, 2, *v_buffer);
|
||||
frame->GetYPitch() * frame->GetHeight());
|
||||
jobject u_buffer = jni()->NewDirectByteBuffer(
|
||||
const_cast<uint8*>(frame->GetUPlane()), frame->GetChromaSize());
|
||||
jobject v_buffer = jni()->NewDirectByteBuffer(
|
||||
const_cast<uint8*>(frame->GetVPlane()), frame->GetChromaSize());
|
||||
jni()->SetObjectArrayElement(planes, 0, y_buffer);
|
||||
jni()->SetObjectArrayElement(planes, 1, u_buffer);
|
||||
jni()->SetObjectArrayElement(planes, 2, v_buffer);
|
||||
return jni()->NewObject(
|
||||
*j_frame_class_, j_frame_ctor_id_,
|
||||
frame->GetWidth(), frame->GetHeight(), *strides, *planes);
|
||||
frame->GetWidth(), frame->GetHeight(), strides, planes);
|
||||
}
|
||||
|
||||
JNIEnv* jni() {
|
||||
|
Loading…
x
Reference in New Issue
Block a user