[vlc-devel] [PATCH 4/6] mediacodec: GetOutput: separate JNI part from Decoder part

Thomas Guillem thomas at gllm.fr
Tue May 19 18:58:43 CEST 2015


---
 modules/codec/omxil/mediacodec.c | 208 +++++++++++++++++++++++++--------------
 1 file changed, 133 insertions(+), 75 deletions(-)

diff --git a/modules/codec/omxil/mediacodec.c b/modules/codec/omxil/mediacodec.c
index 8145946..d84fcc9 100644
--- a/modules/codec/omxil/mediacodec.c
+++ b/modules/codec/omxil/mediacodec.c
@@ -141,6 +141,35 @@ struct csd
     size_t i_size;
 };
 
+struct mc_out
+{
+    enum {
+        MC_OUT_TYPE_BUF,
+        MC_OUT_TYPE_CONF,
+    } type;
+    union
+    {
+        struct
+        {
+            int i_index;
+            mtime_t i_ts;
+            const void *p_ptr;
+            int i_size;
+        } buf;
+        struct
+        {
+            int width, height;
+            int stride;
+            int slice_height;
+            int pixel_format;
+            int crop_left;
+            int crop_top;
+            int crop_right;
+            int crop_bottom;
+        } conf;
+    } u;
+};
+
 struct decoder_sys_t
 {
     uint32_t nal_size;
@@ -1238,7 +1267,8 @@ static int PutInput(decoder_t *p_dec, JNIEnv *env, block_t *p_block,
     }
 }
 
-static int GetOutput(decoder_t *p_dec, JNIEnv *env, picture_t *p_pic, jlong timeout)
+static int JniGetOutput(decoder_t *p_dec, JNIEnv *env,
+                        struct mc_out *p_out, mtime_t timeout)
 {
     decoder_sys_t *p_sys = p_dec->p_sys;
     int index = (*env)->CallIntMethod(env, p_sys->codec, jfields.dequeue_output_buffer,
@@ -1249,39 +1279,13 @@ static int GetOutput(decoder_t *p_dec, JNIEnv *env, picture_t *p_pic, jlong time
     }
 
     if (index >= 0) {
-        int64_t i_buffer_pts;
-
-        /* If the oldest input block had no PTS, the timestamp of the frame
-         * returned by MediaCodec might be wrong so we overwrite it with the
-         * corresponding dts. Call FifoGet first in order to avoid a gap if
-         * buffers are released due to an invalid format or a preroll */
-        int64_t forced_ts = timestamp_FifoGet(p_sys->timestamp_fifo);
-
-        if (!p_sys->pixel_format || !p_pic) {
-            msg_Warn(p_dec, "Buffers returned before output format is set, dropping frame");
-            return ReleaseOutputBuffer(p_dec, env, index, false);
-        }
-
-        i_buffer_pts = (*env)->GetLongField(env, p_sys->buffer_info, jfields.pts_field);
-        if (i_buffer_pts <= p_sys->i_preroll_end)
-            return ReleaseOutputBuffer(p_dec, env, index, false);
-
-        if (forced_ts == VLC_TS_INVALID)
-            p_pic->date = i_buffer_pts;
-        else
-            p_pic->date = forced_ts;
+        p_out->type = MC_OUT_TYPE_BUF;
+        p_out->u.buf.i_index = index;
+        p_out->u.buf.i_ts = (*env)->GetLongField(env, p_sys->buffer_info, jfields.pts_field);
 
         if (p_sys->direct_rendering) {
-            picture_sys_t *p_picsys = p_pic->p_sys;
-            p_picsys->pf_lock_pic = NULL;
-            p_picsys->pf_unlock_pic = UnlockPicture;
-            p_picsys->priv.hw.p_dec = p_dec;
-            p_picsys->priv.hw.i_index = index;
-            p_picsys->priv.hw.b_valid = true;
-
-            vlc_mutex_lock(get_android_opaque_mutex());
-            InsertInflightPicture(p_dec, p_pic, index);
-            vlc_mutex_unlock(get_android_opaque_mutex());
+            p_out->u.buf.p_ptr = NULL;
+            p_out->u.buf.i_size = 0;
         } else {
             jobject buf;
             if (jfields.get_output_buffers)
@@ -1292,28 +1296,10 @@ static int GetOutput(decoder_t *p_dec, JNIEnv *env, picture_t *p_pic, jlong time
             //jsize buf_size = (*env)->GetDirectBufferCapacity(env, buf);
             uint8_t *ptr = (*env)->GetDirectBufferAddress(env, buf);
 
-            //int size = (*env)->GetIntField(env, p_sys->buffer_info, jfields.size_field);
             int offset = (*env)->GetIntField(env, p_sys->buffer_info, jfields.offset_field);
-            ptr += offset; // Check the size parameter as well
-
-            unsigned int chroma_div;
-            GetVlcChromaSizes(p_dec->fmt_out.i_codec, p_dec->fmt_out.video.i_width,
-                              p_dec->fmt_out.video.i_height, NULL, NULL, &chroma_div);
-            CopyOmxPicture(p_sys->pixel_format, p_pic, p_sys->slice_height, p_sys->stride,
-                           ptr, chroma_div, &p_sys->architecture_specific_data);
-            (*env)->CallVoidMethod(env, p_sys->codec, jfields.release_output_buffer, index, false);
-
-            jthrowable exception = (*env)->ExceptionOccurred(env);
-            if (exception != NULL) {
-                jclass illegalStateException = (*env)->FindClass(env, "java/lang/IllegalStateException");
-                if((*env)->IsInstanceOf(env, exception, illegalStateException)) {
-                    msg_Err(p_dec, "Codec error (IllegalStateException) in MediaCodec.releaseOutputBuffer");
-                    (*env)->ExceptionClear(env);
-                    (*env)->DeleteLocalRef(env, illegalStateException);
-                    (*env)->DeleteLocalRef(env, buf);
-                    return -1;
-                }
-            }
+            p_out->u.buf.p_ptr = ptr + offset;
+            p_out->u.buf.i_size = (*env)->GetIntField(env, p_sys->buffer_info,
+                                                       jfields.size_field);
             (*env)->DeleteLocalRef(env, buf);
         }
         return 1;
@@ -1354,18 +1340,85 @@ static int GetOutput(decoder_t *p_dec, JNIEnv *env, picture_t *p_pic, jlong time
         msg_Dbg(p_dec, "output format changed: %.*s", format_len, format_ptr);
         (*env)->ReleaseStringUTFChars(env, format_string, format_ptr);
 
-        ArchitectureSpecificCopyHooksDestroy(p_sys->pixel_format, &p_sys->architecture_specific_data);
-
-        int width           = GET_INTEGER(format, "width");
-        int height          = GET_INTEGER(format, "height");
-        p_sys->stride       = GET_INTEGER(format, "stride");
-        p_sys->slice_height = GET_INTEGER(format, "slice-height");
-        p_sys->pixel_format = GET_INTEGER(format, "color-format");
-        int crop_left       = GET_INTEGER(format, "crop-left");
-        int crop_top        = GET_INTEGER(format, "crop-top");
-        int crop_right      = GET_INTEGER(format, "crop-right");
-        int crop_bottom     = GET_INTEGER(format, "crop-bottom");
+        p_out->type = MC_OUT_TYPE_CONF;
+        p_out->u.conf.width = GET_INTEGER(format, "width");
+        p_out->u.conf.height = GET_INTEGER(format, "height");
+        p_out->u.conf.stride = GET_INTEGER(format, "stride");
+        p_out->u.conf.slice_height = GET_INTEGER(format, "slice-height");
+        p_out->u.conf.pixel_format = GET_INTEGER(format, "color-format");
+        p_out->u.conf.crop_left = GET_INTEGER(format, "crop-left");
+        p_out->u.conf.crop_top = GET_INTEGER(format, "crop-top");
+        p_out->u.conf.crop_right = GET_INTEGER(format, "crop-right");
+        p_out->u.conf.crop_bottom = GET_INTEGER(format, "crop-bottom");
+
         (*env)->DeleteLocalRef(env, format);
+        return 1;
+    }
+    return 0;
+}
+
+static int GetOutput(decoder_t *p_dec, JNIEnv *env, picture_t *p_pic,
+                     mtime_t i_timeout)
+{
+    decoder_sys_t *p_sys = p_dec->p_sys;
+    struct mc_out out;
+    int i_ret = JniGetOutput(p_dec, env, &out, i_timeout);
+
+    if (i_ret != 1)
+        return i_ret;
+    if (out.type == MC_OUT_TYPE_BUF)
+    {
+        /* If the oldest input block had no PTS, the timestamp of
+         * the frame returned by MediaCodec might be wrong so we
+         * overwrite it with the corresponding dts. Call FifoGet
+         * first in order to avoid a gap if buffers are released
+         * due to an invalid format or a preroll */
+        int64_t forced_ts = timestamp_FifoGet(p_sys->timestamp_fifo);
+
+        if (!p_sys->pixel_format || !p_pic) {
+            msg_Warn(p_dec, "Buffers returned before output format is set, dropping frame");
+            return ReleaseOutputBuffer(p_dec, env, out.u.buf.i_index, false);
+        }
+
+        if (out.u.buf.i_ts <= p_sys->i_preroll_end)
+            return ReleaseOutputBuffer(p_dec, env, out.u.buf.i_index, false);
+
+        if (forced_ts == VLC_TS_INVALID)
+            p_pic->date = out.u.buf.i_ts;
+        else
+            p_pic->date = forced_ts;
+
+        if (p_sys->direct_rendering)
+        {
+            picture_sys_t *p_picsys = p_pic->p_sys;
+            p_picsys->pf_lock_pic = NULL;
+            p_picsys->pf_unlock_pic = UnlockPicture;
+            p_picsys->priv.hw.p_dec = p_dec;
+            p_picsys->priv.hw.i_index = out.u.buf.i_index;
+            p_picsys->priv.hw.b_valid = true;
+
+            vlc_mutex_lock(get_android_opaque_mutex());
+            InsertInflightPicture(p_dec, p_pic, out.u.buf.i_index);
+            vlc_mutex_unlock(get_android_opaque_mutex());
+        } else {
+            unsigned int chroma_div;
+            GetVlcChromaSizes(p_dec->fmt_out.i_codec,
+                              p_dec->fmt_out.video.i_width,
+                              p_dec->fmt_out.video.i_height,
+                              NULL, NULL, &chroma_div);
+            CopyOmxPicture(p_sys->pixel_format, p_pic,
+                           p_sys->slice_height, p_sys->stride,
+                           (uint8_t *)out.u.buf.p_ptr, chroma_div,
+                           &p_sys->architecture_specific_data);
+            if (ReleaseOutputBuffer(p_dec, env, out.u.buf.i_index, false) != 0)
+                return -1;
+        }
+        return 1;
+    } else {
+        assert(out.type == MC_OUT_TYPE_CONF);
+        p_sys->pixel_format = out.u.conf.pixel_format;
+        ArchitectureSpecificCopyHooksDestroy(p_sys->pixel_format,
+                                             &p_sys->architecture_specific_data);
 
         const char *name = "unknown";
         if (!p_sys->direct_rendering) {
@@ -1377,35 +1430,40 @@ static int GetOutput(decoder_t *p_dec, JNIEnv *env, picture_t *p_pic, jlong time
         }
 
         msg_Err(p_dec, "output: %d %s, %dx%d stride %d %d, crop %d %d %d %d",
-                p_sys->pixel_format, name, width, height, p_sys->stride, p_sys->slice_height,
-                crop_left, crop_top, crop_right, crop_bottom);
+                p_sys->pixel_format, name, out.u.conf.width, out.u.conf.height,
+                out.u.conf.stride, out.u.conf.slice_height,
+                out.u.conf.crop_left, out.u.conf.crop_top,
+                out.u.conf.crop_right, out.u.conf.crop_bottom);
 
-        p_dec->fmt_out.video.i_width = crop_right + 1 - crop_left;
-        p_dec->fmt_out.video.i_height = crop_bottom + 1 - crop_top;
+        p_dec->fmt_out.video.i_width = out.u.conf.crop_right + 1 - out.u.conf.crop_left;
+        p_dec->fmt_out.video.i_height = out.u.conf.crop_bottom + 1 - out.u.conf.crop_top;
         if (p_dec->fmt_out.video.i_width <= 1
             || p_dec->fmt_out.video.i_height <= 1) {
-            p_dec->fmt_out.video.i_width = width;
-            p_dec->fmt_out.video.i_height = height;
+            p_dec->fmt_out.video.i_width = out.u.conf.width;
+            p_dec->fmt_out.video.i_height = out.u.conf.height;
         }
         p_dec->fmt_out.video.i_visible_width = p_dec->fmt_out.video.i_width;
         p_dec->fmt_out.video.i_visible_height = p_dec->fmt_out.video.i_height;
 
+        p_sys->stride = out.u.conf.stride;
+        p_sys->slice_height = out.u.conf.slice_height;
         if (p_sys->stride <= 0)
-            p_sys->stride = width;
+            p_sys->stride = out.u.conf.width;
         if (p_sys->slice_height <= 0)
-            p_sys->slice_height = height;
+            p_sys->slice_height = out.u.conf.height;
 
-        ArchitectureSpecificCopyHooks(p_dec, p_sys->pixel_format, p_sys->slice_height,
+        ArchitectureSpecificCopyHooks(p_dec, out.u.conf.pixel_format,
+                                      out.u.conf.slice_height,
                                       p_sys->stride, &p_sys->architecture_specific_data);
         if (p_sys->pixel_format == OMX_TI_COLOR_FormatYUV420PackedSemiPlanar)
-            p_sys->slice_height -= crop_top/2;
+            p_sys->slice_height -= out.u.conf.crop_top/2;
         if (IgnoreOmxDecoderPadding(p_sys->name)) {
             p_sys->slice_height = 0;
             p_sys->stride = p_dec->fmt_out.video.i_width;
         }
         p_sys->b_update_format = true;
+        return 0;
     }
-    return 0;
 }
 
 static void H264ProcessBlock(decoder_t *p_dec, block_t *p_block,
-- 
2.1.4




More information about the vlc-devel mailing list