mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-01-08 15:00:11 +01:00
st/omx/enc: replace omx buffer with texture buffer
Signed-off-by: Leo Liu <leo.liu@amd.com> Reviewed-by: Christian König <christian.koenig@amd.com>
This commit is contained in:
parent
360038fa50
commit
b03be6908e
1 changed files with 185 additions and 29 deletions
|
|
@ -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;
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue