[vlc-devel] [PATCH 6/7] mediacodec: Fix freeze when seeking on pause
Thomas Guillem
thomas at gllm.fr
Mon Mar 23 18:40:03 CET 2015
See FIXME comment.
Fixes #12397
---
modules/codec/omxil/android_mediacodec.c | 86 +++++++++++++++-----------------
1 file changed, 40 insertions(+), 46 deletions(-)
diff --git a/modules/codec/omxil/android_mediacodec.c b/modules/codec/omxil/android_mediacodec.c
index 03c33d1..f765fbf 100644
--- a/modules/codec/omxil/android_mediacodec.c
+++ b/modules/codec/omxil/android_mediacodec.c
@@ -782,10 +782,9 @@ static int InsertInflightPicture(decoder_t *p_dec, picture_t *p_pic,
return 0;
}
-static int PutInput(decoder_t *p_dec, JNIEnv *env, block_t **pp_block, jlong timeout)
+static int PutInput(decoder_t *p_dec, JNIEnv *env, block_t *p_block, jlong timeout)
{
decoder_sys_t *p_sys = p_dec->p_sys;
- block_t *p_block = *pp_block;
int index;
jobject buf;
jsize size;
@@ -829,11 +828,9 @@ static int PutInput(decoder_t *p_dec, JNIEnv *env, block_t **pp_block, jlong tim
msg_Err(p_dec, "Exception in MediaCodec.queueInputBuffer");
return -1;
}
- block_Release(p_block);
- *pp_block = NULL;
p_sys->decoded = true;
- return 0;
+ return 1;
}
static int ReleaseOutputBuffer(decoder_t *p_dec, JNIEnv *env, int i_index,
@@ -850,7 +847,7 @@ static int ReleaseOutputBuffer(decoder_t *p_dec, JNIEnv *env, int i_index,
return 0;
}
-static int GetOutput(decoder_t *p_dec, JNIEnv *env, picture_t **pp_pic, jlong timeout)
+static int GetOutput(decoder_t *p_dec, JNIEnv *env, picture_t *p_pic, jlong timeout)
{
decoder_sys_t *p_sys = p_dec->p_sys;
int index = (*env)->CallIntMethod(env, p_sys->codec, p_sys->dequeue_output_buffer,
@@ -863,7 +860,7 @@ static int GetOutput(decoder_t *p_dec, JNIEnv *env, picture_t **pp_pic, jlong ti
if (index >= 0) {
int64_t i_buffer_pts;
- if (!p_sys->pixel_format) {
+ 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);
}
@@ -872,12 +869,6 @@ static int GetOutput(decoder_t *p_dec, JNIEnv *env, picture_t **pp_pic, jlong ti
if (i_buffer_pts <= p_sys->i_preroll_end)
return ReleaseOutputBuffer(p_dec, env, index, false);
- *pp_pic = decoder_NewPicture(p_dec);
- if (!*pp_pic) {
- msg_Warn(p_dec, "NewPicture failed");
- return ReleaseOutputBuffer(p_dec, env, index, false);
- }
- picture_t *p_pic = *pp_pic;
/* 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. */
@@ -932,6 +923,7 @@ static int GetOutput(decoder_t *p_dec, JNIEnv *env, picture_t **pp_pic, jlong ti
}
(*env)->DeleteLocalRef(env, buf);
}
+ return 1;
} else if (index == INFO_OUTPUT_BUFFERS_CHANGED) {
msg_Dbg(p_dec, "output buffers changed");
if (!p_sys->get_output_buffers)
@@ -1062,46 +1054,48 @@ static picture_t *DecodeVideo(decoder_t *p_dec, block_t **pp_block)
}
jlong timeout = 0;
- const int max_polling_attempts = 50;
- int attempts = 0;
- /* return when pp_block is processed */
- while (*pp_block != NULL) {
- if (*pp_block != NULL && PutInput(p_dec, env, pp_block, (jlong) 0) != 0) {
- p_sys->error_state = true;
- break;
+ int i_output_ret = 0;
+ int i_input_ret = 0;
+ /* return when pp_block is processed or when we got an output pic */
+ while (i_input_ret != 1 && i_output_ret != 1) {
+ if (i_input_ret == 0) {
+ i_input_ret = PutInput(p_dec, env, *pp_block, timeout);
+ if (i_input_ret == 1) {
+ block_Release(*pp_block);
+ *pp_block = NULL;
+ } else if (i_input_ret == -1) {
+ p_sys->error_state = true;
+ break;
+ }
}
- if (p_pic == NULL && GetOutput(p_dec, env, &p_pic, timeout) != 0) {
- p_sys->error_state = true;
- break;
- }
+ if (i_output_ret == 0) {
+ /* FIXME: A new picture shouldn't be created each time.
+ * If decoder_NewPicture fails because the decoder is
+ * flushing/exiting, GetOutput will either fail (or crash in
+ * function of devices), or never return an output buffer. Indeed,
+ * if the Decoder is flushing, MediaCodec can be stalled since the
+ * input is waiting for the output or vice-versa. Therefore, call
+ * decoder_NewPicture before GetOutput as a safeguard. */
- 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) {
+ if (p_sys->pixel_format) {
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_lock_pic = NULL;
- p_picsys->pf_unlock_pic = NULL;
- p_picsys->priv.hw.p_dec = NULL;
- p_picsys->priv.hw.i_index = -1;
- p_picsys->priv.hw.b_valid = false;
- }
- else {
- /* If we cannot return a picture we must free the
- block since the decoder will proceed with the
- next block. */
- block_Release(*pp_block);
- *pp_block = NULL;
+ if (!p_pic) {
+ msg_Warn(p_dec, "NewPicture failed");
+ goto endclean;
}
}
+ i_output_ret = GetOutput(p_dec, env, p_pic, timeout);
+ msg_Err(p_dec, "i_output_ret: %d", i_output_ret);
+ if (i_output_ret == -1) {
+ p_sys->error_state = true;
+ break;
+ } else if (i_output_ret == 0 && p_pic) {
+ picture_Release(p_pic);
+ p_pic = NULL;
+ }
}
+ timeout = 10 * 1000;
}
endclean:
--
2.1.3
More information about the vlc-devel
mailing list