[vlc-devel] [RFC PATCH 1/6] mediacodec: process input buffers in only one place

Thomas Guillem thomas at gllm.fr
Mon Nov 3 19:41:17 CET 2014


(behavior not changed)
---
 modules/codec/omxil/android_mediacodec.c | 162 ++++++++++++++++---------------
 1 file changed, 83 insertions(+), 79 deletions(-)

diff --git a/modules/codec/omxil/android_mediacodec.c b/modules/codec/omxil/android_mediacodec.c
index 1eeee69..e303f2b 100644
--- a/modules/codec/omxil/android_mediacodec.c
+++ b/modules/codec/omxil/android_mediacodec.c
@@ -676,6 +676,58 @@ static void InvalidateAllPictures(decoder_t *p_dec)
     vlc_mutex_unlock(get_android_opaque_mutex());
 }
 
+static void PutInput(decoder_t *p_dec, JNIEnv *env, block_t **pp_block, jlong timeout)
+{
+    decoder_sys_t *p_sys = p_dec->p_sys;
+    block_t *p_block = *pp_block;
+    int index;
+    jobject buf;
+    jsize size;
+    uint8_t *bufptr;
+    struct H264ConvertState convert_state = { 0, 0 };
+
+    index = (*env)->CallIntMethod(env, p_sys->codec,
+                                  p_sys->dequeue_input_buffer, timeout);
+    if ((*env)->ExceptionOccurred(env)) {
+        msg_Err(p_dec, "Exception occurred in MediaCodec.dequeueInputBuffer");
+        (*env)->ExceptionClear(env);
+        p_sys->error_state = true;
+        return;
+    }
+    if (index < 0)
+        return;
+
+    buf = (*env)->GetObjectArrayElement(env, p_sys->input_buffers, index);
+    size = (*env)->GetDirectBufferCapacity(env, buf);
+    bufptr = (*env)->GetDirectBufferAddress(env, buf);
+    if (size < 0) {
+        msg_Err(p_dec, "Java buffer has invalid size");
+        p_sys->error_state = true;
+        return;
+    }
+    if ((size_t) size > p_block->i_buffer)
+        size = p_block->i_buffer;
+    memcpy(bufptr, p_block->p_buffer, size);
+
+    convert_h264_to_annexb(bufptr, size, p_sys->nal_size, &convert_state);
+
+    int64_t ts = p_block->i_pts;
+    if (!ts && p_block->i_dts)
+        ts = p_block->i_dts;
+    timestamp_FifoPut(p_sys->timestamp_fifo, p_block->i_pts ? VLC_TS_INVALID : p_block->i_dts);
+    (*env)->CallVoidMethod(env, p_sys->codec, p_sys->queue_input_buffer, index, 0, size, ts, 0);
+    (*env)->DeleteLocalRef(env, buf);
+    if ((*env)->ExceptionOccurred(env)) {
+        msg_Err(p_dec, "Exception in MediaCodec.queueInputBuffer");
+        (*env)->ExceptionClear(env);
+        p_sys->error_state = true;
+        return;
+    }
+    block_Release(p_block);
+    *pp_block = NULL;
+    p_sys->decoded = true;
+}
+
 static void GetOutput(decoder_t *p_dec, JNIEnv *env, picture_t **pp_pic, jlong timeout)
 {
     decoder_sys_t *p_sys = p_dec->p_sys;
@@ -890,27 +942,21 @@ static picture_t *DecodeVideo(decoder_t *p_dec, block_t **pp_block)
     decoder_sys_t *p_sys = p_dec->p_sys;
     picture_t *p_pic = NULL;
     JNIEnv *env = NULL;
-    struct H264ConvertState convert_state = { 0, 0 };
 
     if (!pp_block || !*pp_block)
         return NULL;
 
-    block_t *p_block = *pp_block;
-
     if (p_sys->error_state) {
-        block_Release(p_block);
-        if (!p_sys->error_event_sent) {
-            /* Signal the error to the Java. */
-            jni_EventHardwareAccelerationError();
-            p_sys->error_event_sent = true;
-        }
-        return NULL;
+        block_Release(*pp_block);
+        *pp_block = NULL;
+        goto endclean;
     }
 
     jni_attach_thread(&env, THREAD_NAME);
 
-    if (p_block->i_flags & (BLOCK_FLAG_DISCONTINUITY|BLOCK_FLAG_CORRUPTED)) {
-        block_Release(p_block);
+    if ((*pp_block)->i_flags & (BLOCK_FLAG_DISCONTINUITY|BLOCK_FLAG_CORRUPTED)) {
+        block_Release(*pp_block);
+        *pp_block = NULL;
         timestamp_FifoEmpty(p_sys->timestamp_fifo);
         if (p_sys->decoded) {
             /* Invalidate all pictures that are currently in flight
@@ -927,8 +973,7 @@ static picture_t *DecodeVideo(decoder_t *p_dec, block_t **pp_block)
             }
         }
         p_sys->decoded = false;
-        jni_detach_thread();
-        return NULL;
+        goto endclean;
     }
 
     /* Use the aspect ratio provided by the input (ie read from packetizer).
@@ -942,38 +987,26 @@ static picture_t *DecodeVideo(decoder_t *p_dec, block_t **pp_block)
     jlong timeout = 0;
     const int max_polling_attempts = 50;
     int attempts = 0;
-    while (true) {
-        int index = (*env)->CallIntMethod(env, p_sys->codec, p_sys->dequeue_input_buffer, (jlong) 0);
-        if ((*env)->ExceptionOccurred(env)) {
-            msg_Err(p_dec, "Exception occurred in MediaCodec.dequeueInputBuffer");
-            (*env)->ExceptionClear(env);
-            p_sys->error_state = true;
+    while (*pp_block != NULL && p_pic == NULL) {
+        PutInput(p_dec, env, pp_block, (jlong) 0);
+        if (p_sys->error_state)
             break;
-        }
 
-        if (index < 0) {
-            GetOutput(p_dec, env, &p_pic, timeout);
-            if (p_sys->error_state)
-                break;
-            if (p_pic) {
-                /* If we couldn't get an available input buffer but a
-                 * decoded frame is available, we return the frame
-                 * without assigning NULL to *pp_block. The next call
-                 * to DecodeVideo will try to send the input packet again.
-                 */
-                jni_detach_thread();
-                return p_pic;
-            }
+        GetOutput(p_dec, env, &p_pic, timeout);
+        if (p_sys->error_state)
+            break;
+
+        if (p_pic == NULL && *pp_block != NULL) {
             timeout = 30 * 1000;
             ++attempts;
             /* With opaque DR the output buffers are released by the
                vout therefore we implement a timeout for polling in
                order to avoid being indefinitely stalled in this loop. */
             if (p_sys->direct_rendering && attempts == max_polling_attempts) {
-                picture_t *invalid_picture = decoder_NewPicture(p_dec);
-                if (invalid_picture) {
-                    invalid_picture->date = VLC_TS_INVALID;
-                    picture_sys_t *p_picsys = invalid_picture->p_sys;
+                p_pic = decoder_NewPicture(p_dec);
+                if (p_pic) {
+                    p_pic->date = VLC_TS_INVALID;
+                    picture_sys_t *p_picsys = p_pic->p_sys;
                     p_picsys->pf_display_callback = NULL;
                     p_picsys->pf_unlock_callback = NULL;
                     p_picsys->p_dec = NULL;
@@ -984,56 +1017,27 @@ static picture_t *DecodeVideo(decoder_t *p_dec, block_t **pp_block)
                     /* If we cannot return a picture we must free the
                        block since the decoder will proceed with the
                        next block. */
-                    block_Release(p_block);
+                    block_Release(*pp_block);
                     *pp_block = NULL;
                 }
-                jni_detach_thread();
-                return invalid_picture;
             }
-            continue;
-        }
-
-        jobject buf = (*env)->GetObjectArrayElement(env, p_sys->input_buffers, index);
-        jsize size = (*env)->GetDirectBufferCapacity(env, buf);
-        uint8_t *bufptr = (*env)->GetDirectBufferAddress(env, buf);
-        if (size < 0) {
-            msg_Err(p_dec, "Java buffer has invalid size");
-            p_sys->error_state = true;
-            break;
-        }
-        if ((size_t) size > p_block->i_buffer)
-            size = p_block->i_buffer;
-        memcpy(bufptr, p_block->p_buffer, size);
-
-        convert_h264_to_annexb(bufptr, size, p_sys->nal_size, &convert_state);
-
-        int64_t ts = p_block->i_pts;
-        if (!ts && p_block->i_dts)
-            ts = p_block->i_dts;
-        timestamp_FifoPut(p_sys->timestamp_fifo, p_block->i_pts ? VLC_TS_INVALID : p_block->i_dts);
-        (*env)->CallVoidMethod(env, p_sys->codec, p_sys->queue_input_buffer, index, 0, size, ts, 0);
-        (*env)->DeleteLocalRef(env, buf);
-        if ((*env)->ExceptionOccurred(env)) {
-            msg_Err(p_dec, "Exception in MediaCodec.queueInputBuffer");
-            (*env)->ExceptionClear(env);
-            p_sys->error_state = true;
-            break;
         }
-        p_sys->decoded = true;
-        break;
     }
+
+endclean:
     if (p_sys->error_state) {
         if (p_pic)
             picture_Release(p_pic);
-        jni_detach_thread();
-        return NULL;
-    }
-    if (!p_pic)
-        GetOutput(p_dec, env, &p_pic, 0);
-    jni_detach_thread();
+        p_pic = NULL;
 
-    block_Release(p_block);
-    *pp_block = NULL;
+        if (!p_sys->error_event_sent) {
+            /* Signal the error to the Java. */
+            jni_EventHardwareAccelerationError();
+            p_sys->error_event_sent = true;
+        }
+    }
+    if (env != NULL)
+        jni_detach_thread();
 
     return p_pic;
 }
-- 
2.1.1




More information about the vlc-devel mailing list