[vlc-devel] [PATCH 1/4] mediacodec: process input buffers in only one place
Thomas Guillem
thomas at gllm.fr
Wed Oct 29 17:46:59 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 6d204d7..2f9f384 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)
decoder_DeletePicture(p_dec, 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.0
More information about the vlc-devel
mailing list