[vlc-commits] mediacodec: seperate MediaCodec Open/Close from Decoder Open/Close

Thomas Guillem git at videolan.org
Thu Apr 23 15:41:09 CEST 2015


vlc | branch: master | Thomas Guillem <thomas at gllm.fr> | Thu Apr 23 15:36:21 2015 +0200| [08f6114d37faef0d4d2ae7dcde69112e6017d657] | committer: Thomas Guillem

mediacodec: seperate MediaCodec Open/Close from Decoder Open/Close

It's now safe to close and open MediaCodec during playback.

> http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=08f6114d37faef0d4d2ae7dcde69112e6017d657
---

 modules/codec/omxil/android_mediacodec.c |  150 +++++++++++++++++++++---------
 1 file changed, 104 insertions(+), 46 deletions(-)

diff --git a/modules/codec/omxil/android_mediacodec.c b/modules/codec/omxil/android_mediacodec.c
index af6cb6e..6adbd89 100644
--- a/modules/codec/omxil/android_mediacodec.c
+++ b/modules/codec/omxil/android_mediacodec.c
@@ -29,6 +29,7 @@
 
 #include <jni.h>
 #include <stdint.h>
+#include <assert.h>
 
 #include <vlc_common.h>
 #include <vlc_plugin.h>
@@ -260,6 +261,7 @@ static const struct member members[] = {
  *****************************************************************************/
 static int  OpenDecoder(vlc_object_t *);
 static void CloseDecoder(vlc_object_t *);
+static void CloseMediaCodec(decoder_t *p_dec, JNIEnv *env);
 
 static picture_t *DecodeVideo(decoder_t *, block_t **);
 
@@ -386,17 +388,14 @@ end:
 }
 
 /*****************************************************************************
- * OpenDecoder: Create the decoder instance
+ * OpenMediaCodec: Create the mediacodec instance
  *****************************************************************************/
-static int OpenDecoder(vlc_object_t *p_this)
+static int OpenMediaCodec(decoder_t *p_dec, JNIEnv *env)
 {
-    decoder_t *p_dec = (decoder_t*)p_this;
-    decoder_sys_t *p_sys;
-
-    if (p_dec->fmt_in.i_cat != VIDEO_ES && !p_dec->b_force)
-        return VLC_EGENERIC;
-
+    decoder_sys_t *p_sys = p_dec->p_sys;
     const char *mime = NULL;
+    size_t fmt_profile = 0;
+
     switch (p_dec->fmt_in.i_codec) {
     case VLC_CODEC_HEVC: mime = "video/hevc"; break;
     case VLC_CODEC_H264: mime = "video/avc"; break;
@@ -407,32 +406,12 @@ static int OpenDecoder(vlc_object_t *p_this)
     case VLC_CODEC_VP8:  mime = "video/x-vnd.on2.vp8"; break;
     case VLC_CODEC_VP9:  mime = "video/x-vnd.on2.vp9"; break;
     default:
-        msg_Dbg(p_dec, "codec %4.4s not supported", (char *)&p_dec->fmt_in.i_codec);
-        return VLC_EGENERIC;
+        vlc_assert_unreachable();
     }
 
-    size_t fmt_profile = 0;
     if (p_dec->fmt_in.i_codec == VLC_CODEC_H264)
         h264_get_profile_level(&p_dec->fmt_in, &fmt_profile, NULL, NULL);
 
-    /* Allocate the memory needed to store the decoder's structure */
-    if ((p_dec->p_sys = p_sys = calloc(1, sizeof(*p_sys))) == NULL)
-        return VLC_ENOMEM;
-
-    p_dec->pf_decode_video = DecodeVideo;
-
-    p_dec->fmt_out.i_cat = p_dec->fmt_in.i_cat;
-    p_dec->fmt_out.video = p_dec->fmt_in.video;
-    p_dec->fmt_out.audio = p_dec->fmt_in.audio;
-    p_dec->b_need_packetized = true;
-
-    JNIEnv* env = NULL;
-    if (!(env = jni_get_env(THREAD_NAME)))
-        goto error;
-
-    if (!InitJNIFields(p_dec, env))
-        goto error;
-
     int num_codecs = (*env)->CallStaticIntMethod(env, jfields.media_codec_list_class,
                                                  jfields.get_codec_count);
     jobject codec_name = NULL;
@@ -674,58 +653,137 @@ loopclean:
     p_sys->buffer_info = (*env)->NewGlobalRef(env, p_sys->buffer_info);
     (*env)->DeleteLocalRef(env, format);
 
-    const int timestamp_fifo_size = 32;
-    p_sys->timestamp_fifo = timestamp_FifoNew(timestamp_fifo_size);
-    if (!p_sys->timestamp_fifo)
-        goto error;
-
     return VLC_SUCCESS;
 
  error:
-    CloseDecoder(p_this);
+    CloseMediaCodec(p_dec, env);
     return VLC_EGENERIC;
 }
 
-static void CloseDecoder(vlc_object_t *p_this)
+/*****************************************************************************
+ * CloseMediaCodec: Close the mediacodec instance
+ *****************************************************************************/
+static void CloseMediaCodec(decoder_t *p_dec, JNIEnv *env)
 {
-    decoder_t *p_dec = (decoder_t *)p_this;
     decoder_sys_t *p_sys = p_dec->p_sys;
-    JNIEnv *env = NULL;
 
     if (!p_sys)
         return;
 
+    free(p_sys->name);
+    p_sys->name = NULL;
+
     /* Invalidate all pictures that are currently in flight in order
      * to prevent the vout from using destroyed output buffers. */
-    if (p_sys->direct_rendering)
+    if (p_sys->direct_rendering) {
         InvalidateAllPictures(p_dec);
+        p_sys->direct_rendering = false;
+    }
 
-    if (!(env = jni_get_env(THREAD_NAME)))
-        goto cleanup;
-
-    if (p_sys->input_buffers)
+    if (p_sys->input_buffers) {
         (*env)->DeleteGlobalRef(env, p_sys->input_buffers);
-    if (p_sys->output_buffers)
+        p_sys->input_buffers = NULL;
+    }
+    if (p_sys->output_buffers) {
         (*env)->DeleteGlobalRef(env, p_sys->output_buffers);
+        p_sys->output_buffers = NULL;
+    }
     if (p_sys->codec) {
         if (p_sys->started)
         {
             (*env)->CallVoidMethod(env, p_sys->codec, jfields.stop);
             if (CHECK_EXCEPTION())
                 msg_Err(p_dec, "Exception in MediaCodec.stop");
+            p_sys->started = false;
         }
         if (p_sys->allocated)
         {
             (*env)->CallVoidMethod(env, p_sys->codec, jfields.release);
             if (CHECK_EXCEPTION())
                 msg_Err(p_dec, "Exception in MediaCodec.release");
+            p_sys->allocated = false;
         }
         (*env)->DeleteGlobalRef(env, p_sys->codec);
+        p_sys->codec = NULL;
     }
-    if (p_sys->buffer_info)
+    if (p_sys->buffer_info) {
         (*env)->DeleteGlobalRef(env, p_sys->buffer_info);
+        p_sys->buffer_info = NULL;
+    }
+}
+
+/*****************************************************************************
+ * OpenDecoder: Create the decoder instance
+ *****************************************************************************/
+static int OpenDecoder(vlc_object_t *p_this)
+{
+    decoder_t *p_dec = (decoder_t*)p_this;
+    JNIEnv* env = NULL;
+
+    if (p_dec->fmt_in.i_cat != VIDEO_ES && !p_dec->b_force)
+        return VLC_EGENERIC;
+
+    switch (p_dec->fmt_in.i_codec) {
+    case VLC_CODEC_H264:
+    case VLC_CODEC_HEVC:
+    case VLC_CODEC_H263:
+    case VLC_CODEC_MP4V:
+    case VLC_CODEC_WMV3:
+    case VLC_CODEC_VC1:
+    case VLC_CODEC_VP8:
+    case VLC_CODEC_VP9:
+        break;
+    default:
+        msg_Dbg(p_dec, "codec %4.4s not supported",
+                (char *)&p_dec->fmt_in.i_codec);
+        return VLC_EGENERIC;
+    }
+
+    if (!(env = jni_get_env(THREAD_NAME)))
+        goto error;
+
+    if (!InitJNIFields(p_dec, env))
+        goto error;
+
+    /* Allocate the memory needed to store the decoder's structure */
+    if ((p_dec->p_sys = calloc(1, sizeof(*p_dec->p_sys))) == NULL)
+        return VLC_ENOMEM;
+
+    p_dec->pf_decode_video = DecodeVideo;
+
+    p_dec->fmt_out.i_cat = p_dec->fmt_in.i_cat;
+    p_dec->fmt_out.video = p_dec->fmt_in.video;
+    p_dec->fmt_out.audio = p_dec->fmt_in.audio;
+    p_dec->b_need_packetized = true;
+
+    p_dec->p_sys->timestamp_fifo = timestamp_FifoNew(32);
+    if (!p_dec->p_sys->timestamp_fifo)
+        goto error;
+
+    return OpenMediaCodec(p_dec, env);
+
+ error:
+    CloseDecoder(p_this);
+    return VLC_EGENERIC;
+}
+
+/*****************************************************************************
+ * CloseDecoder: Close the decoder instance
+ *****************************************************************************/
+static void CloseDecoder(vlc_object_t *p_this)
+{
+    decoder_t *p_dec = (decoder_t *)p_this;
+    decoder_sys_t *p_sys = p_dec->p_sys;
+    JNIEnv *env = NULL;
+
+    if (!p_sys)
+        return;
+
+    if ((env = jni_get_env(THREAD_NAME)))
+        CloseMediaCodec(p_dec, env);
+    else
+        msg_Warn(p_dec, "Can't get a JNIEnv, can't close mediacodec !");
 
-cleanup:
     free(p_sys->p_extra_buffer);
     free(p_sys->name);
     ArchitectureSpecificCopyHooksDestroy(p_sys->pixel_format, &p_sys->architecture_specific_data);



More information about the vlc-commits mailing list