[Mesa-dev] [PATCH] st/omx/enc: replace omx buffer with texture buffer

Christian König deathsimple at vodafone.de
Tue Apr 22 07:44:42 PDT 2014


Am 17.04.2014 18:19, schrieb Leo Liu:
> From: Leo Liu<leo.liu at amd.com>
>
> Signed-off-by: Leo Liu<leo.liu at amd.com>

Reviewed & pushed.

Thanks,
Christian.

> ---
>   src/gallium/state_trackers/omx/vid_enc.c | 214 ++++++++++++++++++++++++++-----
>   1 file changed, 185 insertions(+), 29 deletions(-)
>
> diff --git a/src/gallium/state_trackers/omx/vid_enc.c b/src/gallium/state_trackers/omx/vid_enc.c
> index 88d15a9..8a95999 100644
> --- a/src/gallium/state_trackers/omx/vid_enc.c
> +++ b/src/gallium/state_trackers/omx/vid_enc.c
> @@ -50,6 +50,7 @@
>   #include "pipe/p_video_codec.h"
>   #include "state_tracker/drm_driver.h"
>   #include "util/u_memory.h"
> +#include "vl/vl_video_buffer.h"
>   
>   #include "entrypoint.h"
>   #include "vid_enc.h"
> @@ -64,6 +65,9 @@ struct encode_task {
>   
>   struct input_buf_private {
>      struct list_head tasks;
> +
> +   struct pipe_resource *resource;
> +   struct pipe_transfer *transfer;
>   };
>   
>   struct output_buf_private {
> @@ -78,6 +82,10 @@ static OMX_ERRORTYPE vid_enc_GetParameter(OMX_HANDLETYPE handle, OMX_INDEXTYPE i
>   static OMX_ERRORTYPE vid_enc_SetConfig(OMX_HANDLETYPE handle, OMX_INDEXTYPE idx, OMX_PTR config);
>   static OMX_ERRORTYPE vid_enc_GetConfig(OMX_HANDLETYPE handle, OMX_INDEXTYPE idx, OMX_PTR config);
>   static OMX_ERRORTYPE vid_enc_MessageHandler(OMX_COMPONENTTYPE *comp, internalRequestMessageType *msg);
> +static OMX_ERRORTYPE vid_enc_AllocateInBuffer(omx_base_PortType *port, OMX_INOUT OMX_BUFFERHEADERTYPE **buf,
> +                                              OMX_IN OMX_U32 idx, OMX_IN OMX_PTR private, OMX_IN OMX_U32 size);
> +static OMX_ERRORTYPE vid_enc_UseInBuffer(omx_base_PortType *port, OMX_BUFFERHEADERTYPE **buf, OMX_U32 idx,
> +                                         OMX_PTR private, OMX_U32 size, OMX_U8 *mem);
>   static OMX_ERRORTYPE vid_enc_FreeInBuffer(omx_base_PortType *port, OMX_U32 idx, OMX_BUFFERHEADERTYPE *buf);
>   static OMX_ERRORTYPE vid_enc_EncodeFrame(omx_base_PortType *port, OMX_BUFFERHEADERTYPE *buf);
>   static OMX_ERRORTYPE vid_enc_AllocateOutBuffer(omx_base_PortType *comp, OMX_INOUT OMX_BUFFERHEADERTYPE **buf,
> @@ -226,6 +234,8 @@ static OMX_ERRORTYPE vid_enc_Constructor(OMX_COMPONENTTYPE *comp, OMX_STRING nam
>      port->sPortParam.nBufferCountMin = 4;
>   
>      port->Port_SendBufferFunction = vid_enc_EncodeFrame;
> +   port->Port_AllocateBuffer = vid_enc_AllocateInBuffer;
> +   port->Port_UseBuffer = vid_enc_UseInBuffer;
>      port->Port_FreeBuffer = vid_enc_FreeInBuffer;
>   
>      port = (omx_base_video_PortType *)priv->ports[OMX_BASE_FILTER_OUTPUTPORT_INDEX];
> @@ -293,6 +303,42 @@ static OMX_ERRORTYPE vid_enc_Destructor(OMX_COMPONENTTYPE *comp)
>      return omx_workaround_Destructor(comp);
>   }
>   
> +static OMX_ERRORTYPE enc_AllocateBackTexture(omx_base_PortType *port,
> +                                             struct pipe_resource **resource,
> +                                             struct pipe_transfer **transfer,
> +                                             OMX_U8 **map)
> +{
> +   OMX_COMPONENTTYPE* comp = port->standCompContainer;
> +   vid_enc_PrivateType *priv = comp->pComponentPrivate;
> +   struct pipe_resource buf_templ;
> +   struct pipe_box box = {};
> +   OMX_U8 *ptr;
> +
> +   memset(&buf_templ, 0, sizeof buf_templ);
> +   buf_templ.target = PIPE_TEXTURE_2D;
> +   buf_templ.format = PIPE_FORMAT_I8_UNORM;
> +   buf_templ.bind = PIPE_BIND_LINEAR;
> +   buf_templ.usage = PIPE_USAGE_STAGING;
> +   buf_templ.flags = 0;
> +   buf_templ.width0 = port->sPortParam.format.video.nFrameWidth;
> +   buf_templ.height0 = port->sPortParam.format.video.nFrameHeight * 3 / 2;
> +   buf_templ.depth0 = 1;
> +   buf_templ.array_size = 1;
> +
> +   *resource = priv->s_pipe->screen->resource_create(priv->s_pipe->screen, &buf_templ);
> +   if (!*resource)
> +      return OMX_ErrorInsufficientResources;
> +
> +   box.width = (*resource)->width0;
> +   box.height = (*resource)->height0;
> +   box.depth = (*resource)->depth0;
> +   ptr = priv->s_pipe->transfer_map(priv->s_pipe, *resource, 0, PIPE_TRANSFER_WRITE, &box, transfer);
> +   if (map)
> +      *map = ptr;
> +
> +   return OMX_ErrorNone;
> +}
> +
>   static OMX_ERRORTYPE vid_enc_SetParameter(OMX_HANDLETYPE handle, OMX_INDEXTYPE idx, OMX_PTR param)
>   {
>      OMX_COMPONENTTYPE *comp = handle;
> @@ -313,12 +359,20 @@ static OMX_ERRORTYPE vid_enc_SetParameter(OMX_HANDLETYPE handle, OMX_INDEXTYPE i
>         if (def->nPortIndex == OMX_BASE_FILTER_INPUTPORT_INDEX) {
>            omx_base_video_PortType *port;
>            unsigned framesize;
> +         struct pipe_resource *resource;
> +         struct pipe_transfer *transfer;
>   
>            port = (omx_base_video_PortType *)priv->ports[OMX_BASE_FILTER_INPUTPORT_INDEX];
> -         framesize = port->sPortParam.format.video.nFrameWidth*
> +         enc_AllocateBackTexture(priv->ports[OMX_BASE_FILTER_INPUTPORT_INDEX],
> +                                 &resource, &transfer, NULL);
> +         port->sPortParam.format.video.nStride = transfer->stride;
> +         pipe_transfer_unmap(priv->s_pipe, transfer);
> +         pipe_resource_reference(&resource, NULL);
> +
> +         framesize = port->sPortParam.format.video.nStride *
>                        port->sPortParam.format.video.nFrameHeight;
>            port->sPortParam.format.video.nSliceHeight = port->sPortParam.format.video.nFrameHeight;
> -         port->sPortParam.nBufferSize = framesize*3/2;
> +         port->sPortParam.nBufferSize = framesize * 3 / 2;
>   
>            port = (omx_base_video_PortType *)priv->ports[OMX_BASE_FILTER_OUTPUTPORT_INDEX];
>            port->sPortParam.nBufferSize = framesize * 512 / (16*16);
> @@ -574,13 +628,71 @@ static OMX_ERRORTYPE vid_enc_MessageHandler(OMX_COMPONENTTYPE* comp, internalReq
>      return omx_base_component_MessageHandler(comp, msg);
>   }
>   
> +static OMX_ERRORTYPE vid_enc_AllocateInBuffer(omx_base_PortType *port, OMX_INOUT OMX_BUFFERHEADERTYPE **buf,
> +                                              OMX_IN OMX_U32 idx, OMX_IN OMX_PTR private, OMX_IN OMX_U32 size)
> +{
> +   struct input_buf_private *inp;
> +   OMX_ERRORTYPE r;
> +
> +   r = base_port_AllocateBuffer(port, buf, idx, private, size);
> +   if (r)
> +      return r;
> +
> +   inp = (*buf)->pInputPortPrivate = CALLOC_STRUCT(input_buf_private);
> +   if (!inp) {
> +      base_port_FreeBuffer(port, idx, *buf);
> +      return OMX_ErrorInsufficientResources;
> +   }
> +
> +   LIST_INITHEAD(&inp->tasks);
> +
> +   FREE((*buf)->pBuffer);
> +   r = enc_AllocateBackTexture(port, &inp->resource, &inp->transfer, &(*buf)->pBuffer);
> +   if (r) {
> +      FREE(inp);
> +      base_port_FreeBuffer(port, idx, *buf);
> +      return r;
> +   }
> +
> +   return OMX_ErrorNone;
> +}
> +
> +static OMX_ERRORTYPE vid_enc_UseInBuffer(omx_base_PortType *port, OMX_BUFFERHEADERTYPE **buf, OMX_U32 idx,
> +                                         OMX_PTR private, OMX_U32 size, OMX_U8 *mem)
> +{
> +   struct input_buf_private *inp;
> +   OMX_ERRORTYPE r;
> +
> +   r = base_port_UseBuffer(port, buf, idx, private, size, mem);
> +   if (r)
> +      return r;
> +
> +   inp = (*buf)->pInputPortPrivate = CALLOC_STRUCT(input_buf_private);
> +   if (!inp) {
> +      base_port_FreeBuffer(port, idx, *buf);
> +      return OMX_ErrorInsufficientResources;
> +   }
> +
> +   LIST_INITHEAD(&inp->tasks);
> +
> +   return OMX_ErrorNone;
> +}
> +
>   static OMX_ERRORTYPE vid_enc_FreeInBuffer(omx_base_PortType *port, OMX_U32 idx, OMX_BUFFERHEADERTYPE *buf)
>   {
> +   OMX_COMPONENTTYPE* comp = port->standCompContainer;
> +   vid_enc_PrivateType *priv = comp->pComponentPrivate;
>      struct input_buf_private *inp = buf->pInputPortPrivate;
> +
>      if (inp) {
>         enc_ReleaseTasks(&inp->tasks);
> +      if (inp->transfer)
> +         pipe_transfer_unmap(priv->s_pipe, inp->transfer);
> +      pipe_resource_reference(&inp->resource, NULL);
>         FREE(inp);
>      }
> +   buf->pBuffer = NULL;
> +
>      return base_port_FreeBuffer(port, idx, buf);
>   }
>   
> @@ -683,28 +795,79 @@ static OMX_ERRORTYPE enc_LoadImage(omx_base_PortType *port, OMX_BUFFERHEADERTYPE
>      OMX_COMPONENTTYPE* comp = port->standCompContainer;
>      vid_enc_PrivateType *priv = comp->pComponentPrivate;
>      OMX_VIDEO_PORTDEFINITIONTYPE *def = &port->sPortParam.format.video;
> -   struct pipe_sampler_view **views;
>      struct pipe_box box = {};
> -   void *ptr;
> +   struct input_buf_private *inp = buf->pInputPortPrivate;
>   
> -   views = vbuf->get_sampler_view_planes(vbuf);
> -   if (!views)
> -      return OMX_ErrorInsufficientResources;
> +   if (!inp->resource) {
> +      struct pipe_sampler_view **views;
> +      void *ptr;
> +
> +      views = vbuf->get_sampler_view_planes(vbuf);
> +      if (!views)
> +         return OMX_ErrorInsufficientResources;
> +
> +      ptr = buf->pBuffer;
> +      box.width = def->nFrameWidth;
> +      box.height = def->nFrameHeight;
> +      box.depth = 1;
> +      priv->s_pipe->transfer_inline_write(priv->s_pipe, views[0]->texture, 0,
> +                                          PIPE_TRANSFER_WRITE, &box,
> +                                          ptr, def->nStride, 0);
> +      ptr = ((uint8_t*)buf->pBuffer) + (def->nStride * box.height);
> +      box.width = def->nFrameWidth / 2;
> +      box.height = def->nFrameHeight / 2;
> +      box.depth = 1;
> +      priv->s_pipe->transfer_inline_write(priv->s_pipe, views[1]->texture, 0,
> +                                          PIPE_TRANSFER_WRITE, &box,
> +                                          ptr, def->nStride, 0);
> +   } else {
> +      struct pipe_blit_info blit;
> +      struct vl_video_buffer *dst_buf = (struct vl_video_buffer *)vbuf;
> +
> +      pipe_transfer_unmap(priv->s_pipe, inp->transfer);
> +
> +      box.width = def->nFrameWidth;
> +      box.height = def->nFrameHeight;
> +      box.depth = 1;
> +
> +      priv->s_pipe->resource_copy_region(priv->s_pipe,
> +                                         dst_buf->resources[0],
> +                                         0, 0, 0, 0, inp->resource, 0, &box);
> +
> +      memset(&blit, 0, sizeof(blit));
> +      blit.src.resource = inp->resource;
> +      blit.src.format = inp->resource->format;
> +
> +      blit.src.box.x = 0;
> +      blit.src.box.y = def->nFrameHeight;
> +      blit.src.box.width = def->nFrameWidth;
> +      blit.src.box.height = def->nFrameHeight / 2 ;
> +      blit.src.box.depth = 1;
> +
> +      blit.dst.resource = dst_buf->resources[1];
> +      blit.dst.format = blit.dst.resource->format;
> +
> +      blit.dst.box.width = def->nFrameWidth / 2;
> +      blit.dst.box.height = def->nFrameHeight / 2;
> +      blit.dst.box.depth = 1;
> +      blit.filter = PIPE_TEX_FILTER_NEAREST;
> +
> +      blit.mask = PIPE_MASK_G;
> +      priv->s_pipe->blit(priv->s_pipe, &blit);
> +
> +      blit.src.box.x = 1;
> +      blit.mask = PIPE_MASK_R;
> +      priv->s_pipe->blit(priv->s_pipe, &blit);
> +      priv->s_pipe->flush(priv->s_pipe, NULL, 0);
> +
> +      box.width = inp->resource->width0;
> +      box.height = inp->resource->height0;
> +      box.depth = inp->resource->depth0;
> +      buf->pBuffer = priv->s_pipe->transfer_map(priv->s_pipe, inp->resource, 0,
> +                                                PIPE_TRANSFER_WRITE, &box,
> +                                                &inp->transfer);
> +   }
>   
> -   ptr = buf->pBuffer;
> -   box.width = def->nFrameWidth;
> -   box.height = def->nFrameHeight;
> -   box.depth = 1;
> -   priv->s_pipe->transfer_inline_write(priv->s_pipe, views[0]->texture, 0,
> -                                       PIPE_TRANSFER_WRITE, &box,
> -                                       ptr, def->nStride, 0);
> -   ptr = ((uint8_t*)buf->pBuffer) + (def->nStride * box.height);
> -   box.width = def->nFrameWidth / 2;
> -   box.height = def->nFrameHeight / 2;
> -   box.depth = 1;
> -   priv->s_pipe->transfer_inline_write(priv->s_pipe, views[1]->texture, 0,
> -                                       PIPE_TRANSFER_WRITE, &box,
> -                                       ptr, def->nStride, 0);
>      return OMX_ErrorNone;
>   }
>   
> @@ -850,14 +1013,7 @@ static OMX_ERRORTYPE vid_enc_EncodeFrame(omx_base_PortType *port, OMX_BUFFERHEAD
>      struct encode_task *task;
>      OMX_ERRORTYPE err;
>   
> -   if (!inp) {
> -      inp = buf->pInputPortPrivate = CALLOC_STRUCT(input_buf_private);
> -      if (!inp)
> -         return OMX_ErrorInsufficientResources;
> -      LIST_INITHEAD(&inp->tasks);
> -   } else
> -      enc_MoveTasks(&inp->tasks, &priv->free_tasks);
> -
> +   enc_MoveTasks(&inp->tasks, &priv->free_tasks);
>      task = enc_NeedTask(port);
>      if (!task)
>         return OMX_ErrorInsufficientResources;



More information about the mesa-dev mailing list