diff --git a/sys/androidmedia/gstamcvideodec.c b/sys/androidmedia/gstamcvideodec.c index 3e0f5ef428..49808f9bf3 100644 --- a/sys/androidmedia/gstamcvideodec.c +++ b/sys/androidmedia/gstamcvideodec.c @@ -485,6 +485,21 @@ gst_amc_video_dec_close (GstVideoDecoder * decoder) self->surface = NULL; } + if (self->listener) { + JNIEnv *env = gst_amc_jni_get_env (); + GError *err = NULL; + + if (!gst_amc_jni_call_void_method (env, &err, self->listener, + self->set_context_id, GST_AMC_VIDEO_DEC_TO_JLONG (NULL))) { + GST_ERROR_OBJECT (self, "Failed to unset back pointer on the listener. " + "crashes/hangs may ensue: %s", err ? err->message : "Unknown"); + GST_ELEMENT_ERROR_FROM_ERROR (self, err); + } + + gst_amc_jni_object_unref (env, self->listener); + } + self->listener = NULL; + if (self->codec) { GError *err = NULL; @@ -1683,7 +1698,6 @@ gst_amc_video_dec_new_on_frame_available_listener (GstAmcVideoDec * decoder, jobject listener = NULL; jclass listener_cls = NULL; jmethodID constructor_id = 0; - jmethodID set_context_id = 0; JNINativeMethod amcOnFrameAvailableListener = { "native_onFrameAvailable", @@ -1711,9 +1725,9 @@ gst_amc_video_dec_new_on_frame_available_listener (GstAmcVideoDec * decoder, goto done; } - set_context_id = + decoder->set_context_id = gst_amc_jni_get_method_id (env, err, listener_cls, "setContext", "(J)V"); - if (!set_context_id) { + if (!decoder->set_context_id) { goto done; } @@ -1724,7 +1738,7 @@ gst_amc_video_dec_new_on_frame_available_listener (GstAmcVideoDec * decoder, } if (!gst_amc_jni_call_void_method (env, err, listener, - set_context_id, GST_AMC_VIDEO_DEC_TO_JLONG (decoder))) { + decoder->set_context_id, GST_AMC_VIDEO_DEC_TO_JLONG (decoder))) { gst_amc_jni_object_unref (env, listener); listener = NULL; } @@ -1943,7 +1957,6 @@ gst_amc_video_dec_set_format (GstVideoDecoder * decoder, } else if (self->downstream_supports_gl && !self->surface) { int ret = TRUE; JNIEnv *env = NULL; - jobject listener = NULL; GstAmcSurfaceTexture *surface_texture = NULL; env = gst_amc_jni_get_env (); @@ -1953,15 +1966,24 @@ gst_amc_video_dec_set_format (GstVideoDecoder * decoder, return FALSE; } - listener = + if (self->listener) { + if (!gst_amc_jni_call_void_method (env, &err, self->listener, + self->set_context_id, GST_AMC_VIDEO_DEC_TO_JLONG (NULL))) { + ret = FALSE; + goto done; + } + + gst_amc_jni_object_unref (env, self->listener); + } + self->listener = gst_amc_video_dec_new_on_frame_available_listener (self, env, &err); - if (!listener) { + if (!self->listener) { ret = FALSE; goto done; } if (!gst_amc_surface_texture_set_on_frame_available_listener - (surface_texture, listener, &err)) { + (surface_texture, self->listener, &err)) { ret = FALSE; goto done; } @@ -1971,7 +1993,6 @@ gst_amc_video_dec_set_format (GstVideoDecoder * decoder, done: g_object_unref (surface_texture); - gst_amc_jni_object_unref (env, listener); if (!ret) { GST_ELEMENT_ERROR_FROM_ERROR (self, err); return FALSE; @@ -2511,6 +2532,10 @@ gst_amc_video_dec_on_frame_available (JNIEnv * env, jobject thiz, { GstAmcVideoDec *self = JLONG_TO_GST_AMC_VIDEO_DEC (context); + /* apparently we can be called after the decoder has been closed */ + if (!self) + return; + g_mutex_lock (&self->gl_lock); self->gl_ready_frame_count++; GST_LOG_OBJECT (self, "frame %u available", self->gl_ready_frame_count); diff --git a/sys/androidmedia/gstamcvideodec.h b/sys/androidmedia/gstamcvideodec.h index eca39fe0da..039a785e3e 100644 --- a/sys/androidmedia/gstamcvideodec.h +++ b/sys/androidmedia/gstamcvideodec.h @@ -100,6 +100,9 @@ struct _GstAmcVideoDec gboolean downstream_supports_gl; GstFlowReturn downstream_flow_ret; + jobject listener; + jmethodID set_context_id; + gboolean gl_mem_attached; GstGLMemory *oes_mem; GError *gl_error; diff --git a/sys/androidmedia/org/freedesktop/gstreamer/androidmedia/GstAmcOnFrameAvailableListener.java b/sys/androidmedia/org/freedesktop/gstreamer/androidmedia/GstAmcOnFrameAvailableListener.java index 9a4df2396e..f34bcf7ae2 100644 --- a/sys/androidmedia/org/freedesktop/gstreamer/androidmedia/GstAmcOnFrameAvailableListener.java +++ b/sys/androidmedia/org/freedesktop/gstreamer/androidmedia/GstAmcOnFrameAvailableListener.java @@ -31,11 +31,11 @@ public class GstAmcOnFrameAvailableListener implements OnFrameAvailableListener native_onFrameAvailable(context, surfaceTexture); } - public long getContext () { + public synchronized long getContext () { return context; } - public void setContext (long c) { + public synchronized void setContext (long c) { context = c; }