I'm adding imagereader support in VLC-Android decoder pipeline. VLC has OutThread
for dequeuing output and another thread for queuing input. When buffers are used dequeue_out
(wrapper for AMediaCodec_dequeueOutputBuffer
) returns valid values but when using imagereader dequeue_out
returns undefined negative value.
Why is it not working with imagereader? If there is a problem with input thread then it should also not work with buffers. But when I use imagereader it fails at dequeue_out
(returns invalid index due to which OutThread
aborts).
static void *OutThread(void *data)
{
decoder_t *p_dec = data;
decoder_sys_t *p_sys = p_dec->p_sys;
vlc_thread_set_name("vlc-mediacodec");
vlc_mutex_lock(&p_sys->lock);
while (!p_sys->b_aborted)
{
int i_index;
/* Wait for output ready */
if (!p_sys->b_flush_out && !p_sys->b_output_ready) {
vlc_cond_wait(&p_sys->cond, &p_sys->lock);
continue;
}
if (p_sys->b_flush_out)
{
/* Acknowledge flushed state */
p_sys->b_flush_out = false;
vlc_cond_broadcast(&p_sys->dec_cond);
continue;
}
vlc_mutex_unlock(&p_sys->lock);
/* Wait for an output buffer. This function returns when a new output
* is available or if output is flushed. */
i_index = p_sys->api.dequeue_out(&p_sys->api, -1);
vlc_mutex_lock(&p_sys->lock);
/* Ignore dequeue_out errors caused by flush, or late picture being
* dequeued after close. */
if (p_sys->b_flush_out || p_sys->b_decoder_dead)
{
/* If i_index >= 0, Release it. There is no way to know if i_index
* is owned by us, so don't check the error. */
if (i_index >= 0)
p_sys->api.release_out(&p_sys->api, i_index, false);
/* Parse output format/buffers even when we are flushing */
if (i_index != MC_API_INFO_OUTPUT_FORMAT_CHANGED
&& i_index != MC_API_INFO_OUTPUT_BUFFERS_CHANGED)
continue;
}
if (i_index == MC_API_ERROR)
{
msg_Warn(p_dec, "Failure in MediaCodec.dequeueOutputBuffer");
break;
}
/* Process output returned by dequeue_out */
if (i_index >= 0 || i_index == MC_API_INFO_OUTPUT_FORMAT_CHANGED
|| i_index == MC_API_INFO_OUTPUT_BUFFERS_CHANGED)
{
struct mc_api_out out;
int i_ret = -1;
if (p_sys->api.b_support_imagereader)
{
if (i_index > 0)
{
p_sys->api.release_out(&p_sys->api, i_index, true);
if (p_sys->api.b_support_imagereader && !p_sys->b_img_ready)
{
vlc_cond_wait(&p_sys->img_cond, &p_sys->lock);
}
p_sys->b_img_ready = false;
i_ret = p_sys->api.acquire_latest_image(&p_sys->api, i_index, &out);
}
else if (i_index == MC_API_INFO_OUTPUT_FORMAT_CHANGED)
{
p_sys->api.update_format(&p_sys->api, i_index, &out);
}
}
else
{
i_ret = p_sys->api.get_out(&p_sys->api, i_index, &out);
}
if (i_ret == 1)
{
picture_t *p_pic = NULL;
block_t *p_block = NULL;
if (p_sys->pf_process_output(p_dec, &out, &p_pic,
&p_block) == -1 && !out.b_eos)
{
msg_Err(p_dec, "pf_process_output failed");
break;
}
if (p_pic)
decoder_QueueVideo(p_dec, p_pic);
else if (p_block)
decoder_QueueAudio(p_dec, p_block);
if (out.b_eos)
{
msg_Warn(p_dec, "EOS received");
p_sys->b_drained = true;
vlc_cond_signal(&p_sys->dec_cond);
}
} else if (i_ret != 0)
{
msg_Err(p_dec, "get_out failed");
break;
}
}
else
break;
}
if (!p_sys->b_decoder_dead)
msg_Warn(p_dec, "OutThread stopped");
/* Signal DecoderFlush that the output thread aborted */
p_sys->b_aborted = true;
vlc_cond_signal(&p_sys->dec_cond);
vlc_mutex_unlock(&p_sys->lock);
return NULL;
}