st/omx/tizonia/h264d: Add EGLImage support
authorGurkirpal Singh <gurkirpal204@gmail.com>
Sat, 20 Jan 2018 01:57:07 +0000 (07:27 +0530)
committerJulien Isorce <jisorce@oblong.com>
Tue, 6 Mar 2018 17:21:11 +0000 (17:21 +0000)
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@amd.com>
Reviewed-by: Julien Isorce <julien.isorce@gmail.com>
src/gallium/state_trackers/omx/Makefile.am
src/gallium/state_trackers/omx/meson.build
src/gallium/state_trackers/omx/tizonia/Makefile.am
src/gallium/state_trackers/omx/tizonia/entrypoint.c
src/gallium/state_trackers/omx/tizonia/h264dprc.c
src/gallium/state_trackers/omx/vid_dec_common.c
src/gallium/state_trackers/omx/vid_dec_common.h

index b25ad5d275574e44544cebfb641cc60aef274566..734ca0908e4e2cd914fd1de76af733f1705df2aa 100644 (file)
@@ -37,6 +37,7 @@ SUBDIRS = tizonia
 
 AM_CFLAGS = \
        $(GALLIUM_CFLAGS) \
+       $(LIBDRM_CFLAGS) \
        $(VISIBILITY_CFLAGS) \
        $(VL_CFLAGS) \
        $(XCB_DRI3_CFLAGS) \
index f2daf44117532d55459b1edc8765c9cd6f015ae0..84e5631d2573a281d485ebf7f4c195199027e623 100644 (file)
@@ -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,
 )
index 0f72e393699c59e2c8955f71396920eb839b59dc..3149afa7bbb58b287382605be829ed4411401d2d 100644 (file)
@@ -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) \
index dc81d5500ae3ddc7ca988e90ef84f8c52e48735c..a6c2c45b39e3253e412c09642b79a6b2a558bad7 100644 (file)
 #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;
 }
index a55e3e9782b7eb3946f7de9feb8dc8806e5a06bb..09248e64a9231634529ff2544870eb27748651b8 100644 (file)
 
 #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);
index 56010ca0aeaa5926b6fa816ca128584c4232e422..21952513de1addfaa77291209993f6581eef4b08 100644 (file)
@@ -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;
index dea7149da86aa700f3de5ca46bf606f59a7bce2d..bb104d05aefced62e15b56a45d370ed41bfe0178 100644 (file)
@@ -115,6 +115,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"
 
@@ -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