[Mesa-dev] [PATCH 6/6] st/omx/tizonia/h264d: Add EGLImage support
Gurkirpal Singh
gurkirpal204 at gmail.com
Sat Jan 20 02:21:06 UTC 2018
Example Gstreamer pipeline :
MESA_ENABLE_OMX_EGLIMAGE=1 GST_GL_API=gles2 GST_GL_PLATFORM=egl gst-launch-1.0 filesrc location=movie.mp4 ! qtdemux ! h264parse ! omxh264dec ! glimagesink
Acked-by: Leo Liu <leo.liu at amd.com>
Reviewed-by: Julien Isorce <julien.isorce at gmail.com>
---
src/gallium/state_trackers/omx/Makefile.am | 1 +
src/gallium/state_trackers/omx/tizonia/Makefile.am | 13 +++
.../state_trackers/omx/tizonia/entrypoint.c | 44 ++++++++
src/gallium/state_trackers/omx/tizonia/h264dprc.c | 116 ++++++++++++++++++++-
src/gallium/state_trackers/omx/vid_dec_common.c | 38 +++++++
src/gallium/state_trackers/omx/vid_dec_common.h | 3 +
6 files changed, 211 insertions(+), 4 deletions(-)
diff --git a/src/gallium/state_trackers/omx/Makefile.am b/src/gallium/state_trackers/omx/Makefile.am
index de6eb64..fbde8e0 100644
--- a/src/gallium/state_trackers/omx/Makefile.am
+++ b/src/gallium/state_trackers/omx/Makefile.am
@@ -37,6 +37,7 @@ SUBDIRS = tizonia
AM_CFLAGS = \
$(GALLIUM_CFLAGS) \
+ $(LIBDRM_CFLAGS) \
$(VISIBILITY_CFLAGS) \
$(VL_CFLAGS) \
$(XCB_DRI3_CFLAGS) \
diff --git a/src/gallium/state_trackers/omx/tizonia/Makefile.am b/src/gallium/state_trackers/omx/tizonia/Makefile.am
index 0f72e39..3149afa 100644
--- a/src/gallium/state_trackers/omx/tizonia/Makefile.am
+++ b/src/gallium/state_trackers/omx/tizonia/Makefile.am
@@ -22,8 +22,21 @@ include Makefile.sources
include $(top_srcdir)/src/gallium/Automake.inc
AM_CFLAGS = \
+ -I$(top_srcdir)/include \
+ -I$(top_srcdir)/src/mapi \
+ -I$(top_srcdir)/src/mesa \
+ -I$(top_builddir)/src/mesa/drivers/dri/common \
+ -I$(top_srcdir)/src/mesa/drivers/dri/common \
+ -I$(top_srcdir)/src/egl/drivers/dri2 \
+ -I$(top_srcdir)/src/egl/wayland/wayland-egl \
+ -I$(top_srcdir)/src/egl/main \
+ -I$(top_srcdir)/src/gbm/main \
+ -I$(top_srcdir)/src/loader \
+ -I$(top_srcdir)/src/gbm/backends/dri \
+ -I$(top_srcdir)/src/gallium/state_trackers/dri \
-I$(top_srcdir)/src/gallium/state_trackers/omx \
$(GALLIUM_CFLAGS) \
+ $(LIBDRM_CFLAGS) \
$(VISIBILITY_CFLAGS) \
$(VL_CFLAGS) \
$(XCB_DRI3_CFLAGS) \
diff --git a/src/gallium/state_trackers/omx/tizonia/entrypoint.c b/src/gallium/state_trackers/omx/tizonia/entrypoint.c
index 72d955b..b896447 100644
--- a/src/gallium/state_trackers/omx/tizonia/entrypoint.c
+++ b/src/gallium/state_trackers/omx/tizonia/entrypoint.c
@@ -44,6 +44,40 @@
#include "h264eoutport.h"
#include "names.h"
+#include "util/u_debug.h"
+
+DEBUG_GET_ONCE_BOOL_OPTION(mesa_enable_omx_eglimage,
+ "MESA_ENABLE_OMX_EGLIMAGE",
+ false)
+
+static OMX_BOOL egl_image_validation_hook(const OMX_HANDLETYPE ap_hdl,
+ OMX_U32 pid, OMX_PTR ap_eglimage,
+ void *ap_args)
+{
+ const void * p_krn = NULL;
+ const tiz_port_t * p_port = NULL;
+
+ assert(ap_hdl);
+ assert(ap_eglimage);
+ assert(!ap_args);
+
+ if (!debug_get_option_mesa_enable_omx_eglimage()) {
+ return OMX_FALSE;
+ }
+
+ p_krn = tiz_get_krn(ap_hdl);
+ p_port = tiz_krn_get_port(p_krn, pid);
+
+ const OMX_VIDEO_PORTDEFINITIONTYPE * p_video_portdef
+ = &(p_port->portdef_.format.video);
+
+ if (!p_video_portdef->pNativeWindow) {
+ return OMX_FALSE;
+ }
+
+ return OMX_TRUE;
+}
+
OMX_ERRORTYPE OMX_ComponentInit (OMX_HANDLETYPE ap_hdl)
{
tiz_role_factory_t h264d_role;
@@ -57,6 +91,11 @@ OMX_ERRORTYPE OMX_ComponentInit (OMX_HANDLETYPE ap_hdl)
const tiz_type_factory_t * tf_list[] = {&h264e_inport_type, &h264e_outport_type,
&h264eprc_type, &h264dprc_type,
&h264d_inport_type};
+ const tiz_eglimage_hook_t egl_validation_hook = {
+ OMX_VID_DEC_AVC_OUTPUT_PORT_INDEX,
+ egl_image_validation_hook,
+ NULL
+ };
/* Settings for roles */
strcpy ((OMX_STRING) h264d_role.role, OMX_VID_DEC_AVC_ROLE);
@@ -108,5 +147,10 @@ OMX_ERRORTYPE OMX_ComponentInit (OMX_HANDLETYPE ap_hdl)
/* Register the component roles */
tiz_comp_register_roles (ap_hdl, rf_list, 2);
+ /* Register egl image validation hook for the decoder */
+ tiz_check_omx (tiz_comp_register_role_eglimage_hook
+ (ap_hdl, (const OMX_U8 *) OMX_VID_DEC_AVC_ROLE,
+ &egl_validation_hook));
+
return OMX_ErrorNone;
}
diff --git a/src/gallium/state_trackers/omx/tizonia/h264dprc.c b/src/gallium/state_trackers/omx/tizonia/h264dprc.c
index f5c5d659..96f95b9 100644
--- a/src/gallium/state_trackers/omx/tizonia/h264dprc.c
+++ b/src/gallium/state_trackers/omx/tizonia/h264dprc.c
@@ -38,10 +38,33 @@
#include "vl/vl_video_buffer.h"
#include "vl/vl_compositor.h"
+#include "util/u_hash_table.h"
#include "util/u_surface.h"
+#include "dri_screen.h"
+#include "egl_dri2.h"
+
unsigned dec_frame_delta;
+#define PTR_TO_UINT(x) ((unsigned)((intptr_t)(x)))
+
+static unsigned handle_hash(void *key)
+{
+ return PTR_TO_UINT(key);
+}
+
+static int handle_compare(void *key1, void *key2)
+{
+ return PTR_TO_UINT(key1) != PTR_TO_UINT(key2);
+}
+
+static enum pipe_error hash_table_clear_item_callback(void *key, void *value, void *data)
+{
+ struct pipe_video_buffer *video_buffer = (struct pipe_video_buffer *)value;
+ video_buffer->destroy(video_buffer);
+ return PIPE_OK;
+}
+
static void release_input_headers(vid_dec_PrivateType* priv) {
int i;
for (i = 0; i < priv->num_in_buffers; i++) {
@@ -157,6 +180,66 @@ static OMX_BUFFERHEADERTYPE * get_input_buffer(vid_dec_PrivateType* priv) {
return priv->p_inhdr_;
}
+static struct pipe_resource * st_omx_pipe_texture_from_eglimage(EGLDisplay egldisplay,
+ EGLImage eglimage)
+{
+ _EGLDisplay *disp = egldisplay;
+ struct dri2_egl_display *dri2_egl_dpy = disp->DriverData;
+ __DRIscreen *_dri_screen = dri2_egl_dpy->dri_screen;
+ struct dri_screen *st_dri_screen = dri_screen(_dri_screen);
+ __DRIimage *_dri_image = st_dri_screen->lookup_egl_image(st_dri_screen, eglimage);
+
+ return _dri_image->texture;
+}
+
+static void get_eglimage(vid_dec_PrivateType* priv) {
+ OMX_PTR p_eglimage = NULL;
+ OMX_NATIVE_WINDOWTYPE * p_egldisplay = NULL;
+ const tiz_port_t * p_port = NULL;
+ struct pipe_video_buffer templat = {};
+ struct pipe_video_buffer *video_buffer = NULL;
+ struct pipe_resource * p_res = NULL;
+ struct pipe_resource *resources[VL_NUM_COMPONENTS];
+
+ if (OMX_ErrorNone ==
+ tiz_krn_claim_eglimage(tiz_get_krn (handleOf (priv)),
+ OMX_VID_DEC_AVC_OUTPUT_PORT_INDEX,
+ priv->p_outhdr_, &p_eglimage)) {
+ priv->use_eglimage = true;
+ p_port = tiz_krn_get_port(tiz_get_krn (handleOf (priv)),
+ OMX_VID_DEC_AVC_OUTPUT_PORT_INDEX);
+ p_egldisplay = p_port->portdef_.format.video.pNativeWindow;
+
+ if (!util_hash_table_get(priv->video_buffer_map, priv->p_outhdr_)) {
+ p_res = st_omx_pipe_texture_from_eglimage(p_egldisplay, p_eglimage);
+
+ assert(p_res);
+
+ memset(&templat, 0, sizeof(templat));
+ templat.buffer_format = p_res->format;
+ templat.chroma_format = PIPE_VIDEO_CHROMA_FORMAT_NONE;
+ templat.width = p_res->width0;
+ templat.height = p_res->height0;
+ templat.interlaced = 0;
+
+ memset(resources, 0, sizeof(resources));
+ pipe_resource_reference(&resources[0], p_res);
+
+ video_buffer = vl_video_buffer_create_ex2(priv->pipe, &templat, resources);
+
+ assert(video_buffer);
+ assert(video_buffer->buffer_format == p_res->format);
+
+ util_hash_table_set(priv->video_buffer_map, priv->p_outhdr_, video_buffer);
+ }
+ } else {
+ (void) tiz_krn_release_buffer(tiz_get_krn (handleOf (priv)),
+ OMX_VID_DEC_AVC_OUTPUT_PORT_INDEX,
+ priv->p_outhdr_);
+ priv->p_outhdr_ = NULL;
+ }
+}
+
static OMX_BUFFERHEADERTYPE * get_output_buffer(vid_dec_PrivateType* priv) {
assert (priv);
@@ -165,9 +248,17 @@ static OMX_BUFFERHEADERTYPE * get_output_buffer(vid_dec_PrivateType* priv) {
}
if (!priv->p_outhdr_) {
- tiz_krn_claim_buffer(tiz_get_krn (handleOf (priv)),
- OMX_VID_DEC_AVC_OUTPUT_PORT_INDEX, 0,
- &priv->p_outhdr_);
+ if (OMX_ErrorNone
+ == tiz_krn_claim_buffer(tiz_get_krn (handleOf (priv)),
+ OMX_VID_DEC_AVC_OUTPUT_PORT_INDEX, 0,
+ &priv->p_outhdr_)) {
+ if (priv->p_outhdr_) {
+ /* Check pBuffer nullity to know if an eglimage has been registered. */
+ if (!priv->p_outhdr_->pBuffer) {
+ get_eglimage(priv);
+ }
+ }
+ }
}
return priv->p_outhdr_;
}
@@ -200,7 +291,7 @@ static void h264d_manage_buffers(vid_dec_PrivateType* priv) {
/* Realase output buffer if filled or eos
Keep if two input buffers are being decoded */
- if ((!next_is_eos) && ((p_prc->p_outhdr_->nFilledLen > 0) || p_prc->eos_)) {
+ if ((!next_is_eos) && ((priv->p_outhdr_->nFilledLen > 0) || priv->use_eglimage || priv->eos_)) {
h264d_buffer_filled(priv, priv->p_outhdr_);
}
@@ -308,6 +399,7 @@ static OMX_ERRORTYPE h264d_prc_allocate_resources(void *ap_obj, OMX_U32 a_pid)
{
vid_dec_PrivateType*priv = ap_obj;
struct pipe_screen *screen;
+ vl_csc_matrix csc;
assert (priv);
@@ -333,8 +425,18 @@ static OMX_ERRORTYPE h264d_prc_allocate_resources(void *ap_obj, OMX_U32 a_pid)
return OMX_ErrorInsufficientResources;
}
+ vl_csc_get_matrix(VL_CSC_COLOR_STANDARD_BT_601, NULL, true, &csc);
+ if (!vl_compositor_set_csc_matrix(&priv->cstate, (const vl_csc_matrix *)&csc, 1.0f, 0.0f)) {
+ vl_compositor_cleanup(&priv->compositor);
+ priv->pipe->destroy(priv->pipe);
+ priv->pipe = NULL;
+ return OMX_ErrorInsufficientResources;
+ }
+
LIST_INITHEAD(&priv->codec_data.h264.dpb_list);
+ priv->video_buffer_map = util_hash_table_create(handle_hash, handle_compare);
+
return OMX_ErrorNone;
}
@@ -343,6 +445,12 @@ static OMX_ERRORTYPE h264d_prc_deallocate_resources(void *ap_obj)
vid_dec_PrivateType*priv = ap_obj;
assert(priv);
+ /* Clear hash table */
+ util_hash_table_foreach(priv->video_buffer_map,
+ &hash_table_clear_item_callback,
+ NULL);
+ util_hash_table_destroy(priv->video_buffer_map);
+
if (priv->pipe) {
vl_compositor_cleanup_state(&priv->cstate);
vl_compositor_cleanup(&priv->compositor);
diff --git a/src/gallium/state_trackers/omx/vid_dec_common.c b/src/gallium/state_trackers/omx/vid_dec_common.c
index 56010ca..2195251 100644
--- a/src/gallium/state_trackers/omx/vid_dec_common.c
+++ b/src/gallium/state_trackers/omx/vid_dec_common.c
@@ -90,6 +90,44 @@ void vid_dec_FillOutput(vid_dec_PrivateType *priv, struct pipe_video_buffer *buf
views = buf->get_sampler_view_planes(buf);
+#if ENABLE_ST_OMX_TIZONIA
+ if (!output->pBuffer) {
+ struct pipe_video_buffer *dst_buf = NULL;
+ struct pipe_surface **dst_surface = NULL;
+ struct u_rect src_rect;
+ struct u_rect dst_rect;
+ struct vl_compositor *compositor = &priv->compositor;
+ struct vl_compositor_state *s = &priv->cstate;
+ enum vl_compositor_deinterlace deinterlace = VL_COMPOSITOR_WEAVE;
+
+ dst_buf = util_hash_table_get(priv->video_buffer_map, output);
+ assert(dst_buf);
+
+ dst_surface = dst_buf->get_surfaces(dst_buf);
+ assert(views);
+
+ src_rect.x0 = 0;
+ src_rect.y0 = 0;
+ src_rect.x1 = def->nFrameWidth;
+ src_rect.y1 = def->nFrameHeight;
+
+ dst_rect.x0 = 0;
+ dst_rect.y0 = 0;
+ dst_rect.x1 = def->nFrameWidth;
+ dst_rect.y1 = def->nFrameHeight;
+
+ vl_compositor_clear_layers(s);
+ vl_compositor_set_buffer_layer(s, compositor, 0, buf,
+ &src_rect, NULL, deinterlace);
+ vl_compositor_set_layer_dst_area(s, 0, &dst_rect);
+ vl_compositor_render(s, compositor, dst_surface[0], NULL, false);
+
+ priv->pipe->flush(priv->pipe, NULL, 0);
+
+ return;
+ }
+#endif
+
for (i = 0; i < 2 /* NV12 */; i++) {
if (!views[i]) continue;
width = def->nFrameWidth;
diff --git a/src/gallium/state_trackers/omx/vid_dec_common.h b/src/gallium/state_trackers/omx/vid_dec_common.h
index dd4d08b..d16bf92 100644
--- a/src/gallium/state_trackers/omx/vid_dec_common.h
+++ b/src/gallium/state_trackers/omx/vid_dec_common.h
@@ -118,6 +118,7 @@ ENDCLASS(vid_dec_PrivateType)
#include <tizport_decls.h>
#include "util/list.h"
+#include "util/u_hash_table.h"
#include "pipe/p_video_state.h"
@@ -157,6 +158,7 @@ struct h264d_prc
struct pipe_video_codec *codec;
struct pipe_video_buffer *target;
enum pipe_video_profile profile;
+ struct util_hash_table *video_buffer_map;
union {
struct {
unsigned nal_ref_idc;
@@ -187,6 +189,7 @@ struct h264d_prc
bool disable_tunnel;
struct vl_compositor compositor;
struct vl_compositor_state cstate;
+ bool use_eglimage;
};
#endif
--
2.7.4
More information about the mesa-dev
mailing list