[vlc-commits] mediacodec: Fix freeze when seeking on pause
Thomas Guillem
git at videolan.org
Tue Mar 24 10:36:11 CET 2015
vlc | branch: master | Thomas Guillem <thomas at gllm.fr> | Tue Mar 24 10:34:57 2015 +0100| [d38e44dd960e58e50f79cf1b6793d699789391f6] | committer: Jean-Baptiste Kempf
mediacodec: Fix freeze when seeking on pause
See FIXME comment.
Fixes #12397
Signed-off-by: Jean-Baptiste Kempf <jb at videolan.org>
> http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=d38e44dd960e58e50f79cf1b6793d699789391f6
---
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 93481cd..282b7bb 100644
--- a/modules/codec/omxil/android_mediacodec.c
+++ b/modules/codec/omxil/android_mediacodec.c
@@ -796,10 +796,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;
@@ -843,14 +842,12 @@ 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 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)
@@ -1061,46 +1053,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:
More information about the vlc-commits
mailing list