From c62cf1f165919bc74296952452906b517d49b64a Mon Sep 17 00:00:00 2001 From: Gurkirpal Singh Date: Sat, 20 Jan 2018 07:27:07 +0530 Subject: st/omx/tizonia/h264d: Add EGLImage support 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 Reviewed-by: Julien Isorce --- src/gallium/state_trackers/omx/Makefile.am | 1 + src/gallium/state_trackers/omx/meson.build | 18 +++- 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 + 7 files changed, 227 insertions(+), 6 deletions(-) (limited to 'src/gallium/state_trackers') diff --git a/src/gallium/state_trackers/omx/Makefile.am b/src/gallium/state_trackers/omx/Makefile.am index b25ad5d275..734ca0908e 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/meson.build b/src/gallium/state_trackers/omx/meson.build index f2daf44117..84e5631d25 100644 --- a/src/gallium/state_trackers/omx/meson.build +++ b/src/gallium/state_trackers/omx/meson.build @@ -18,6 +18,9 @@ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. +inc_st_omx = [inc_common] +dep_st_omx = [dep_omx, dep_x11_xcb, dep_xcb, dep_xcb_dri2, dep_xcb_dri3] + files_omx = files( 'vid_dec_common.c', 'vid_dec_h264_common.c', @@ -45,12 +48,23 @@ files_omx += files( 'tizonia/h264einport.c', 'tizonia/h264eoutport.c' ) +inc_st_omx = [ + inc_st_omx, + inc_dri_common, + include_directories('../../state_trackers/dri'), + include_directories('../../../egl/drivers/dri2'), + include_directories('../../../egl/main'), + include_directories('../../../gbm/backends/dri'), + include_directories('../../../gbm/main'), + include_directories('../../../loader') +] +dep_st_omx = [dep_st_omx, dep_omx_other, dep_libdrm] endif libomx_st = static_library( 'omx_st', files_omx, c_args : [c_vis_args], - include_directories : [inc_common], - dependencies : [dep_omx, dep_omx_other, dep_x11_xcb, dep_xcb, dep_xcb_dri2, dep_xcb_dri3], + include_directories : inc_st_omx, + dependencies : dep_st_omx, ) diff --git a/src/gallium/state_trackers/omx/tizonia/Makefile.am b/src/gallium/state_trackers/omx/tizonia/Makefile.am index 0f72e39369..3149afa7bb 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 dc81d5500a..a6c2c45b39 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; @@ -59,6 +93,11 @@ OMX_ERRORTYPE OMX_ComponentInit (OMX_HANDLETYPE ap_hdl) &h264eprc_type, &h264e_inport_type, &h264e_outport_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); @@ -110,5 +149,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 a55e3e9782..09248e64a9 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++) { @@ -156,6 +179,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); @@ -164,9 +247,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_; } @@ -199,7 +290,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) && ((priv->p_outhdr_->nFilledLen > 0) || priv->eos_)) { + if ((!next_is_eos) && ((priv->p_outhdr_->nFilledLen > 0) || priv->use_eglimage || priv->eos_)) { h264d_buffer_filled(priv, priv->p_outhdr_); } @@ -307,6 +398,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); @@ -332,8 +424,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; } @@ -342,6 +444,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 56010ca0ae..21952513de 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 dea7149da8..bb104d05ae 100644 --- a/src/gallium/state_trackers/omx/vid_dec_common.h +++ b/src/gallium/state_trackers/omx/vid_dec_common.h @@ -115,6 +115,7 @@ ENDCLASS(vid_dec_PrivateType) #include #include "util/list.h" +#include "util/u_hash_table.h" #include "pipe/p_video_state.h" @@ -154,6 +155,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; @@ -184,6 +186,7 @@ struct h264d_prc bool disable_tunnel; struct vl_compositor compositor; struct vl_compositor_state cstate; + bool use_eglimage; }; #endif -- cgit v1.2.3