[vlc-devel] [RFC PATCH 07/11] omxil: factorize FreeBuffers and AllocateBuffers
Martin Storsjö
martin at martin.st
Tue Jun 24 18:31:45 CEST 2014
On Tue, 24 Jun 2014, Thomas Guillem wrote:
> ---
> modules/codec/omxil/omxil.c | 236 ++++++++++++++++++++++---------------------
> 1 file changed, 123 insertions(+), 113 deletions(-)
>
> diff --git a/modules/codec/omxil/omxil.c b/modules/codec/omxil/omxil.c
> index df75c93..c1ed20d 100644
> --- a/modules/codec/omxil/omxil.c
> +++ b/modules/codec/omxil/omxil.c
> @@ -355,6 +355,113 @@ static OMX_ERRORTYPE UpdatePixelAspect(decoder_t *p_dec)
> return omx_err;
> }
>
> +static OMX_ERRORTYPE AllocateBuffers(decoder_t *p_dec, OmxPort *p_port)
> +{
> + decoder_sys_t *p_sys = p_dec->p_sys;
> + OMX_ERRORTYPE omx_error = OMX_ErrorUndefined;
> + OMX_PARAM_PORTDEFINITIONTYPE *def = &p_port->definition;
> + unsigned int i;
> +
> +#ifdef OMXIL_EXTRA_DEBUG
> + msg_Dbg( p_dec, "AllocateBuffers(%d)", def->eDir );
> +#endif
> +
> + p_port->i_buffers = p_port->definition.nBufferCountActual;
> +
> + p_port->pp_buffers = calloc(p_port->i_buffers, sizeof(OMX_BUFFERHEADERTYPE*));
> + if( !p_port->pp_buffers )
> + {
> + return OMX_ErrorInsufficientResources;
> + }
> +
> + for(i = 0; i < p_port->i_buffers; i++)
> + {
> +#if 0
> +#define ALIGN(x,BLOCKLIGN) (((x) + BLOCKLIGN - 1) & ~(BLOCKLIGN - 1))
> + char *p_buf = malloc(p_port->definition.nBufferSize +
> + p_port->definition.nBufferAlignment);
> + p_port->pp_buffers[i] = (void *)ALIGN((uintptr_t)p_buf, p_port->definition.nBufferAlignment);
> +#endif
> +
> + if(p_port->b_direct)
> + omx_error =
> + OMX_UseBuffer( p_sys->omx_handle, &p_port->pp_buffers[i],
> + p_port->i_port_index, 0,
> + p_port->definition.nBufferSize, (void*)1);
> + else
> + omx_error =
> + OMX_AllocateBuffer( p_sys->omx_handle, &p_port->pp_buffers[i],
> + p_port->i_port_index, 0,
> + p_port->definition.nBufferSize);
> +
> + if(omx_error != OMX_ErrorNone) break;
> + OMX_FIFO_PUT(&p_port->fifo, p_port->pp_buffers[i]);
> + }
> + CHECK_ERROR(omx_error, "AllocateBuffers failed (%x, %i)",
> + omx_error, (int)p_port->i_port_index );
> +
> +
> +#ifdef OMXIL_EXTRA_DEBUG
> + msg_Dbg( p_dec, "AllocateBuffers(%d)::done", def->eDir );
> +#endif
> +error:
> + return omx_error;
> +}
> +
> +static OMX_ERRORTYPE FreeBuffers(decoder_t *p_dec, OmxPort *p_port)
> +{
> + decoder_sys_t *p_sys = p_dec->p_sys;
> + OMX_PARAM_PORTDEFINITIONTYPE *def = &p_port->definition;
> + OMX_ERRORTYPE omx_error = OMX_ErrorNone;
> + OMX_BUFFERHEADERTYPE *p_buffer;
> + unsigned int i;
> +
> +#ifdef OMXIL_EXTRA_DEBUG
> + msg_Dbg( p_dec, "FreeBuffers(%d)", def->eDir );
> +#endif
> +
> + /* wait for omx to release all buffers */
> + while (1) {
> + OMX_FIFO_PEEK(&p_port->fifo, p_buffer);
> + if (!p_buffer) break;
> +
> + OMX_FIFO_GET(&p_port->fifo, p_buffer);
> + if (p_buffer->nFlags & SENTINEL_FLAG) {
> + free(p_buffer);
> + continue;
> + }
> + msg_Dbg( p_dec, "Stray buffer left in fifo, %p", p_buffer );
> + }
> +
> + for(i = 0; i < p_port->i_buffers; i++)
> + {
> + p_buffer = p_port->pp_buffers[i];
> +
> + if( p_buffer )
> + {
> + if( p_buffer->pAppPrivate != NULL )
> + decoder_DeletePicture( p_dec, p_buffer->pAppPrivate );
> + omx_error = OMX_FreeBuffer( p_sys->omx_handle,
> + p_port->i_port_index, p_buffer );
> + if(omx_error != OMX_ErrorNone) break;
> + }
> + }
Why did you change the order of this code compared to how it was before?
This will not work as intended. Previously this was structured like this:
for (0..i_buffers) {
OMX_FIFO_GET
}
while (1)
// Get any remaining buffer (sentinels?)
Now you just remove any buffers currently in the FIFO, and then assume you
have got them all.
At this point, we've signalled the codec to return them to us (by setting
the state to loaded, or by disabling the port), but the codec might not
have returned all of them yet - and while the codec still owns one of the
buffers, we cannot free it. (I've spent a lot of time debugging quite
non-obvious bugs relating exactly to this piece of code.)
Thus, we need to make sure that we actually remove exactly 'i_buffers'
buffers from the fifo. (And if there are sentinel buffers in the fifo
those should not be counted.) By looping 'i_buffers' times and doing
OMX_FIFO_GET each time, we make sure the code blocks until there is one
buffer that we can free.
Thus, please keep the original structure of the code that frees the
buffers - but factorizing it definitely is a good step.
// Martin
More information about the vlc-devel
mailing list