[meta-freescale] [PATCH 5/6] gstreamer1.0-plugins-bad: Add NXP specific patches

Otavio Salvador otavio.salvador at ossystems.com.br
Tue Dec 19 08:38:05 PST 2017


same.

On Mon, Dec 18, 2017 at 3:20 PM, Stefan Agner <stefan at agner.ch> wrote:
> From: Stefan Agner <stefan.agner at toradex.com>
>
> Add NXP specific patches from morty-4.9.51-mx8_beta branch. This
> allows to use imx-gst1.0-plugin 4.3.1 with gstreamer 1.12.2.
>
> Signed-off-by: Stefan Agner <stefan.agner at toradex.com>
> ---
>  ...pegtsmux-Need-get-pid-when-create-streams.patch |  44 ++
>  ...rse-Need-detect-picture-coding-type-when-.patch |  47 ++
>  .../0003-modifiy-the-videoparse-rank.patch         |  77 +++
>  ...ter-Lost-frame-rate-info-when-fixate-caps.patch |  51 ++
>  ...dd-one-property-to-set-sink-element-for-v.patch | 181 ++++++
>  ...or-gl-plugin-not-built-in-wayland-backend.patch |  34 +
>  ...07-Change-wayland-default-res-to-1024x768.patch |  41 ++
>  ...wayland-fix-loop-test-hang-in-glimagesink.patch | 142 +++++
>  ...sink-wayland-resize-showed-blurred-screen.patch |  32 +
>  .../0010-support-video-crop-for-glimagesink.patch  | 151 +++++
>  .../0011-Add-fps-print-in-glimagesink.patch        |  86 +++
>  ...rconvert-convert-YUV-to-RGB-use-directviv.patch | 168 +++++
>  ...mpositor-Remove-output-format-alpha-check.patch |  35 ++
>  .../0014-Specific-patches-for-gstplayer-API.patch  | 367 +++++++++++
>  ...15-gstplayer-Add-gst_player_get_state-API.patch |  63 ++
>  .../0016-gstplayer-Add-play-stop-sync-API.patch    | 182 ++++++
>  .../0018-Add-imx-physical-memory-allocator.patch   | 443 +++++++++++++
>  ...nt-of-interface-get_phys_addr-to-support-.patch |  48 ++
>  ...0020-Accelerate-gldownload-with-directviv.patch | 698 +++++++++++++++++++++
>  ...mabuf-memory-allocator-based-on-ion-drive.patch | 390 ++++++++++++
>  .../0022-ionmemory-support-get-phys-memory.patch   |  94 +++
>  ...d-add-crop-meta-support-in-dmafd-uploader.patch |  52 ++
>  ...upload-add-ion-dmabuf-support-in-glupload.patch | 477 ++++++++++++++
>  ...0025-Add-ion-dmabuf-support-in-gldownload.patch | 473 ++++++++++++++
>  ...er-check-frame-buffer-status-need-use-spe.patch | 132 ++++
>  ...-add-EGL-platform-support-for-x11-backend.patch |  63 ++
>  ...-kmssink-use-control-node-to-setplane-to-.patch | 108 ++++
>  ...29-kmssink-support-videooverlay-interface.patch | 343 ++++++++++
>  ...030-kmssink-check-scaleable-when-set_caps.patch |  74 +++
>  ...-glimagesink-fix-segmentation-fault-when-.patch |  35 ++
>  ...-gl-viv-fb-fix-wrong-pos-x-y-calculate-in.patch |  52 ++
>  ...-gl-viv-fb-transform-screen-coordinate-to.patch |  52 ++
>  ...-glimagesink-expose-should-do-redisplay-a.patch |  37 ++
>  ...-videoaggregator-passthrough-interlace-mo.patch |  99 +++
>  ...-glvideomixer-need-update-output-geometry.patch |  83 +++
>  ...-gleglimage-fix-YUY2-import-error-when-up.patch |  30 +
>  ...-glupload-need-upload-each-plane-to-singl.patch | 101 +++
>  .../gstreamer1.0-plugins-bad_1.12.%.bbappend       |  61 ++
>  38 files changed, 5646 insertions(+)
>  create mode 100644 recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad/0001-mpegtsmux-Need-get-pid-when-create-streams.patch
>  create mode 100644 recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad/0002-mpegvideoparse-Need-detect-picture-coding-type-when-.patch
>  create mode 100644 recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad/0003-modifiy-the-videoparse-rank.patch
>  create mode 100644 recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad/0004-glfilter-Lost-frame-rate-info-when-fixate-caps.patch
>  create mode 100644 recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad/0005-camerabin-Add-one-property-to-set-sink-element-for-v.patch
>  create mode 100644 recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad/0006-Fix-for-gl-plugin-not-built-in-wayland-backend.patch
>  create mode 100644 recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad/0007-Change-wayland-default-res-to-1024x768.patch
>  create mode 100644 recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad/0008-gl-wayland-fix-loop-test-hang-in-glimagesink.patch
>  create mode 100644 recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad/0009-Fix-glimagesink-wayland-resize-showed-blurred-screen.patch
>  create mode 100644 recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad/0010-support-video-crop-for-glimagesink.patch
>  create mode 100644 recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad/0011-Add-fps-print-in-glimagesink.patch
>  create mode 100644 recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad/0012-glcolorconvert-convert-YUV-to-RGB-use-directviv.patch
>  create mode 100644 recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad/0013-videocompositor-Remove-output-format-alpha-check.patch
>  create mode 100644 recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad/0014-Specific-patches-for-gstplayer-API.patch
>  create mode 100644 recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad/0015-gstplayer-Add-gst_player_get_state-API.patch
>  create mode 100644 recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad/0016-gstplayer-Add-play-stop-sync-API.patch
>  create mode 100644 recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad/0018-Add-imx-physical-memory-allocator.patch
>  create mode 100644 recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad/0019-Add-implement-of-interface-get_phys_addr-to-support-.patch
>  create mode 100644 recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad/0020-Accelerate-gldownload-with-directviv.patch
>  create mode 100644 recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad/0021-ionmemory-dmabuf-memory-allocator-based-on-ion-drive.patch
>  create mode 100644 recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad/0022-ionmemory-support-get-phys-memory.patch
>  create mode 100644 recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad/0023-glupload-add-crop-meta-support-in-dmafd-uploader.patch
>  create mode 100644 recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad/0024-glupload-add-ion-dmabuf-support-in-glupload.patch
>  create mode 100644 recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad/0025-Add-ion-dmabuf-support-in-gldownload.patch
>  create mode 100644 recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad/0026-glframebuffer-check-frame-buffer-status-need-use-spe.patch
>  create mode 100644 recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad/0027-qml-add-EGL-platform-support-for-x11-backend.patch
>  create mode 100644 recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad/0028-kmssink-use-control-node-to-setplane-to-.patch
>  create mode 100644 recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad/0029-kmssink-support-videooverlay-interface.patch
>  create mode 100644 recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad/0030-kmssink-check-scaleable-when-set_caps.patch
>  create mode 100644 recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad/0031-glimagesink-fix-segmentation-fault-when-.patch
>  create mode 100644 recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad/0032-gl-viv-fb-fix-wrong-pos-x-y-calculate-in.patch
>  create mode 100644 recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad/0033-gl-viv-fb-transform-screen-coordinate-to.patch
>  create mode 100644 recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad/0034-glimagesink-expose-should-do-redisplay-a.patch
>  create mode 100644 recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad/0035-videoaggregator-passthrough-interlace-mo.patch
>  create mode 100644 recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad/0036-glvideomixer-need-update-output-geometry.patch
>  create mode 100644 recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad/0037-gleglimage-fix-YUY2-import-error-when-up.patch
>  create mode 100644 recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad/0038-glupload-need-upload-each-plane-to-singl.patch
>
> diff --git a/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad/0001-mpegtsmux-Need-get-pid-when-create-streams.patch b/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad/0001-mpegtsmux-Need-get-pid-when-create-streams.patch
> new file mode 100644
> index 00000000..4e5a455d
> --- /dev/null
> +++ b/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad/0001-mpegtsmux-Need-get-pid-when-create-streams.patch
> @@ -0,0 +1,44 @@
> +From 0d97f9e8693a498d10ea9ad68caa4f6305c1114e Mon Sep 17 00:00:00 2001
> +From: Song Bing <b06498 at freescale.com>
> +Date: Wed, 22 Apr 2015 18:06:35 +0800
> +Subject: [PATCH 01/26] mpegtsmux: Need get pid when create streams.
> +
> +when camerabin use mpegtsmux as muxer, start video recording and then
> +stop video recording and then start video recording, mpegtsmux get wrong
> +pid.
> +
> +Upstream-Status: Pending [https://bugzilla.gnome.org/show_bug.cgi?id=748288]
> +
> +---
> + gst/mpegtsmux/mpegtsmux.c | 15 +++++++++++++++
> + 1 file changed, 15 insertions(+)
> +
> +diff --git a/gst/mpegtsmux/mpegtsmux.c b/gst/mpegtsmux/mpegtsmux.c
> +index 67c2b72..cfd7c2a 100644
> +--- a/gst/mpegtsmux/mpegtsmux.c
> ++++ b/gst/mpegtsmux/mpegtsmux.c
> +@@ -833,6 +833,21 @@ mpegtsmux_create_streams (MpegTsMux * mux)
> +       } else {
> +         ts_data->prog_id = DEFAULT_PROG_ID;
> +       }
> ++
> ++      if (!ts_data->pid) {
> ++        gint pid = -1;
> ++
> ++        name = GST_PAD_NAME (c_data->pad);
> ++        if (name != NULL && sscanf (name, "sink_%d", &pid) == 1) {
> ++          if (tsmux_find_stream (mux->tsmux, pid)) {
> ++            GST_WARNING_OBJECT (mux, "Duplicate PID");
> ++          }
> ++        } else {
> ++          pid = tsmux_get_new_pid (mux->tsmux);
> ++        }
> ++
> ++        ts_data->pid = pid;
> ++      }
> +     }
> +
> +     ts_data->prog =
> +--
> +1.9.1
> +
> diff --git a/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad/0002-mpegvideoparse-Need-detect-picture-coding-type-when-.patch b/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad/0002-mpegvideoparse-Need-detect-picture-coding-type-when-.patch
> new file mode 100644
> index 00000000..2babed71
> --- /dev/null
> +++ b/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad/0002-mpegvideoparse-Need-detect-picture-coding-type-when-.patch
> @@ -0,0 +1,47 @@
> +From b50e0af12b3c045e7587c86829e1a42ba421c3bc Mon Sep 17 00:00:00 2001
> +From: Song Bing <b06498 at freescale.com>
> +Date: Wed, 20 May 2015 15:15:08 +0800
> +Subject: [PATCH 02/26] mpegvideoparse: Need detect picture coding type when
> + drain
> +MIME-Version: 1.0
> +Content-Type: text/plain; charset=UTF-8
> +Content-Transfer-Encoding: 8bit
> +
> +Need detect picture coding type when drain
> +
> +Upstream-Status: Submitted [https://bugzilla.gnome.org/show_bug.cgi?id=749617]
> +
> +---
> + gst/videoparsers/gstmpegvideoparse.c | 16 ++++++++++++++++
> + 1 file changed, 16 insertions(+)
> +
> +diff --git a/gst/videoparsers/gstmpegvideoparse.c b/gst/videoparsers/gstmpegvideoparse.c
> +index 6896339..769e0fd 100644
> +--- a/gst/videoparsers/gstmpegvideoparse.c
> ++++ b/gst/videoparsers/gstmpegvideoparse.c
> +@@ -715,6 +715,22 @@ need_more:
> +   if (GST_BASE_PARSE_DRAINING (parse)) {
> +     GST_LOG_OBJECT (mpvparse, "draining, accepting all data");
> +     off = size;
> ++    /* decide picture codding type */
> ++    if (mpvparse->pic_offset >= 0 && mpvparse->pic_offset < off) {
> ++      GstMpegVideoPacket header;
> ++
> ++      header.data = map.data;
> ++      header.type = GST_MPEG_VIDEO_PACKET_PICTURE;
> ++      header.offset = mpvparse->pic_offset;
> ++      header.size = map.size - mpvparse->pic_offset;
> ++      if (gst_mpeg_video_packet_parse_picture_header (&header, &mpvparse->pichdr))
> ++        GST_LOG_OBJECT (mpvparse, "picture_coding_type %d (%s), ending"
> ++            "frame of size %d", mpvparse->pichdr.pic_type,
> ++            picture_type_name (mpvparse->pichdr.pic_type), off - 4);
> ++      else
> ++        GST_LOG_OBJECT (mpvparse, "Couldn't parse picture at offset %d",
> ++            mpvparse->pic_offset);
> ++    }
> +     ret = TRUE;
> +   } else {
> +     GST_LOG_OBJECT (mpvparse, "need more data");
> +--
> +1.9.1
> +
> diff --git a/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad/0003-modifiy-the-videoparse-rank.patch b/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad/0003-modifiy-the-videoparse-rank.patch
> new file mode 100644
> index 00000000..38167456
> --- /dev/null
> +++ b/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad/0003-modifiy-the-videoparse-rank.patch
> @@ -0,0 +1,77 @@
> +From 2c3b12f0bddf4d92cf9fc982197f8e92479f3271 Mon Sep 17 00:00:00 2001
> +From: Lyon Wang <lyon.wang at freescale.com>
> +Date: Fri, 29 May 2015 09:54:56 +0800
> +Subject: [PATCH 03/26] modifiy the videoparse rank
> +
> +- Modify the videparsers rank down to avoid link them in
> +. h263parse rank down to 63
> +. mpegvideoparse rank down to 63
> +. mpeg4videpparse rank down to 63
> +. pngparse, rank down to 63
> +. h265parse rank down to 63
> +
> +Upstream-Status: Inappropriate [i.MX specific]
> +
> +Signed-off-by: Lyon Wang <lyon.wang at freescale.com>
> +
> +[vidoeparse] Roll-back h264parse rank
> +
> +Roll back the h264parse rank.
> +MMFMWK-7012
> +For SW video decoder, it only support aligment au,
> +But in GST1.6, rtph264depay output aligment nal format video.
> +Need link h264parse to convert it to au alginment,
> +make the sw decodear work
> +
> +Set h265parse to GST_RANK_PRIMARY + 1,(similar reason as 264parse)
> +
> +http://sw-jira.freescale.net/browse/MMFMWK-7012
> +Upstream Status:  [i.MX specific]
> +
> +Signed-off-by: Lyon Wang <lyon.wang at freescale.com>
> +---
> + gst/videoparsers/plugin.c | 21 +++++++++++++++++++--
> + 1 file changed, 19 insertions(+), 2 deletions(-)
> +
> +diff --git a/gst/videoparsers/plugin.c b/gst/videoparsers/plugin.c
> +index 2deddf4..97be33b 100644
> +--- a/gst/videoparsers/plugin.c
> ++++ b/gst/videoparsers/plugin.c
> +@@ -36,7 +36,7 @@ static gboolean
> + plugin_init (GstPlugin * plugin)
> + {
> +   gboolean ret = FALSE;
> +-
> ++#if 0
> +   ret |= gst_element_register (plugin, "h263parse",
> +       GST_RANK_PRIMARY + 1, GST_TYPE_H263_PARSE);
> +   ret |= gst_element_register (plugin, "h264parse",
> +@@ -55,7 +55,24 @@ plugin_init (GstPlugin * plugin)
> +       GST_RANK_SECONDARY, GST_TYPE_H265_PARSE);
> +   ret |= gst_element_register (plugin, "vc1parse",
> +       GST_RANK_NONE, GST_TYPE_VC1_PARSE);
> +-
> ++#else
> ++  ret |= gst_element_register (plugin, "h263parse",
> ++      GST_RANK_MARGINAL - 1, GST_TYPE_H263_PARSE);
> ++  ret |= gst_element_register (plugin, "h264parse",
> ++      GST_RANK_PRIMARY + 1, GST_TYPE_H264_PARSE);
> ++  ret |= gst_element_register (plugin, "diracparse",
> ++      GST_RANK_NONE, GST_TYPE_DIRAC_PARSE);
> ++  ret |= gst_element_register (plugin, "mpegvideoparse",
> ++      GST_RANK_MARGINAL - 1, GST_TYPE_MPEGVIDEO_PARSE);
> ++  ret |= gst_element_register (plugin, "mpeg4videoparse",
> ++      GST_RANK_MARGINAL -1, GST_TYPE_MPEG4VIDEO_PARSE);
> ++  ret |= gst_element_register (plugin, "pngparse",
> ++      GST_RANK_MARGINAL-1, GST_TYPE_PNG_PARSE);
> ++  ret |= gst_element_register (plugin, "h265parse",
> ++      GST_RANK_PRIMARY + 1, GST_TYPE_H265_PARSE);
> ++  ret |= gst_element_register (plugin, "vc1parse",
> ++      GST_RANK_NONE, GST_TYPE_VC1_PARSE);
> ++#endif
> +   return ret;
> + }
> +
> +--
> +1.9.1
> +
> diff --git a/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad/0004-glfilter-Lost-frame-rate-info-when-fixate-caps.patch b/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad/0004-glfilter-Lost-frame-rate-info-when-fixate-caps.patch
> new file mode 100644
> index 00000000..ea278f22
> --- /dev/null
> +++ b/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad/0004-glfilter-Lost-frame-rate-info-when-fixate-caps.patch
> @@ -0,0 +1,51 @@
> +From 18e6e4edece67383b8424fb4f4dff9d381dbe41f Mon Sep 17 00:00:00 2001
> +From: Song Bing <b06498 at freescale.com>
> +Date: Mon, 8 Jun 2015 17:06:22 +0800
> +Subject: [PATCH 04/26] glfilter: Lost frame rate info when fixate caps
> +MIME-Version: 1.0
> +Content-Type: text/plain; charset=UTF-8
> +Content-Transfer-Encoding: 8bit
> +
> +Lost frame rate info when fixate caps. It will cause
> +down stream element fail, such avimux.
> +
> +Upstream-Status: Submitted [https://bugzilla.gnome.org/show_bug.cgi?id=750545]
> +
> +---
> + gst-libs/gst/gl/gstglfilter.c | 13 ++++++++++++-
> + 1 file changed, 12 insertions(+), 1 deletion(-)
> +
> +diff --git a/gst-libs/gst/gl/gstglfilter.c b/gst-libs/gst/gl/gstglfilter.c
> +index e702a1e..2be7eb3 100644
> +--- a/gst-libs/gst/gl/gstglfilter.c
> ++++ b/gst-libs/gst/gl/gstglfilter.c
> +@@ -237,7 +237,8 @@ gst_gl_filter_fixate_caps (GstBaseTransform * bt,
> +     GstPadDirection direction, GstCaps * caps, GstCaps * othercaps)
> + {
> +   GstStructure *ins, *outs;
> +-  const GValue *from_par, *to_par;
> ++  const GValue *from_par, *to_par, *from_fps;
> ++  gint framerate_num, framerate_den;
> +   GValue fpar = { 0, }, tpar = {
> +   0,};
> +
> +@@ -250,6 +251,16 @@ gst_gl_filter_fixate_caps (GstBaseTransform * bt,
> +   ins = gst_caps_get_structure (caps, 0);
> +   outs = gst_caps_get_structure (othercaps, 0);
> +
> ++  /* replace frame rate */
> ++  from_fps = gst_structure_get_value (ins, "framerate");
> ++  if (from_fps) {
> ++      gst_structure_set_value (outs, "framerate", from_fps);
> ++  } else {
> ++    if (gst_structure_get_fraction (ins, "framerate", &framerate_num, &framerate_den))
> ++      gst_structure_set (outs, "framerate", GST_TYPE_FRACTION, framerate_num, framerate_den,
> ++          NULL);
> ++  }
> ++
> +   from_par = gst_structure_get_value (ins, "pixel-aspect-ratio");
> +   to_par = gst_structure_get_value (outs, "pixel-aspect-ratio");
> +
> +--
> +1.9.1
> +
> diff --git a/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad/0005-camerabin-Add-one-property-to-set-sink-element-for-v.patch b/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad/0005-camerabin-Add-one-property-to-set-sink-element-for-v.patch
> new file mode 100644
> index 00000000..14291e9b
> --- /dev/null
> +++ b/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad/0005-camerabin-Add-one-property-to-set-sink-element-for-v.patch
> @@ -0,0 +1,181 @@
> +From 74ba87e4a54c7f39e8ee58bff16c47f1f0baad14 Mon Sep 17 00:00:00 2001
> +From: Song Bing <b06498 at freescale.com>
> +Date: Fri, 13 Mar 2015 17:31:29 +0800
> +Subject: [PATCH 05/26] camerabin: Add one property to set sink element for
> + video recording pipeline
> +
> +Add one property to set sink element for video recording. Default is
> +filesink.
> +
> +https://bugzilla.gnome.org/show_bug.cgi?id=744508
> +
> +Upstream-Status: Inappropriate [i.MX specific]
> +---
> + gst/camerabin2/gstcamerabin2.c | 73 +++++++++++++++++++++++++++++++++++-------
> + gst/camerabin2/gstcamerabin2.h |  1 +
> + 2 files changed, 63 insertions(+), 11 deletions(-)
> +
> +diff --git a/gst/camerabin2/gstcamerabin2.c b/gst/camerabin2/gstcamerabin2.c
> +index 0e4a3c7..6549bcb 100644
> +--- a/gst/camerabin2/gstcamerabin2.c
> ++++ b/gst/camerabin2/gstcamerabin2.c
> +@@ -203,6 +203,7 @@ enum
> +   PROP_MUTE_AUDIO,
> +   PROP_AUDIO_CAPTURE_SUPPORTED_CAPS,
> +   PROP_AUDIO_CAPTURE_CAPS,
> ++  PROP_VIDEO_SINK,
> +   PROP_ZOOM,
> +   PROP_MAX_ZOOM,
> +   PROP_IMAGE_ENCODING_PROFILE,
> +@@ -342,7 +343,7 @@ gst_camera_bin_start_capture (GstCameraBin2 * camerabin)
> +
> +   /* check that we have a valid location */
> +   if (camerabin->mode == MODE_VIDEO) {
> +-    if (camerabin->location == NULL) {
> ++    if (camerabin->location == NULL && !camerabin->user_video_sink) {
> +       GST_ELEMENT_ERROR (camerabin, RESOURCE, OPEN_WRITE,
> +           (_("File location is set to NULL, please set it to a valid filename")), (NULL));
> +       return;
> +@@ -477,10 +478,13 @@ gst_camera_bin_src_notify_readyforcapture (GObject * obj, GParamSpec * pspec,
> +     if (camera->mode == MODE_VIDEO) {
> +       /* a video recording is about to start, change the filesink location */
> +       gst_element_set_state (camera->videosink, GST_STATE_NULL);
> +-      location = g_strdup_printf (camera->location, camera->capture_index);
> +-      GST_DEBUG_OBJECT (camera, "Switching videobin location to %s", location);
> +-      g_object_set (camera->videosink, "location", location, NULL);
> +-      g_free (location);
> ++      /* shouldn't set location for user_video_sink */
> ++      if (!camera->user_video_sink) {
> ++        location = g_strdup_printf (camera->location, camera->capture_index);
> ++        GST_DEBUG_OBJECT (camera, "Switching videobin location to %s", location);
> ++        g_object_set (camera->videosink, "location", location, NULL);
> ++        g_free (location);
> ++      }
> +       if (gst_element_set_state (camera->videosink, GST_STATE_PLAYING) ==
> +           GST_STATE_CHANGE_FAILURE) {
> +         /* Resets the latest state change return, that would be a failure
> +@@ -535,6 +539,8 @@ gst_camera_bin_dispose (GObject * object)
> +
> +   if (camerabin->videosink)
> +     gst_object_unref (camerabin->videosink);
> ++  if (camerabin->user_video_sink)
> ++    gst_object_unref (camerabin->user_video_sink);
> +   if (camerabin->video_encodebin)
> +     gst_object_unref (camerabin->video_encodebin);
> +   if (camerabin->videobin_capsfilter)
> +@@ -655,6 +661,12 @@ gst_camera_bin_class_init (GstCameraBin2Class * klass)
> +           " taken into use on the next null to ready transition",
> +           GST_TYPE_ELEMENT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
> +
> ++  g_object_class_install_property (object_class, PROP_VIDEO_SINK,
> ++      g_param_spec_object ("video-sink", "Video sink",
> ++          "The video sink element to be used on video recordings. It is only"
> ++          " taken into use on the next null to ready transition",
> ++          GST_TYPE_ELEMENT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
> ++
> +   g_object_class_install_property (object_class, PROP_MUTE_AUDIO,
> +       g_param_spec_boolean ("mute", "Mute",
> +           "If the audio recording should be muted. Note that this still "
> +@@ -1519,13 +1531,30 @@ gst_camera_bin_create_elements (GstCameraBin2 * camera)
> +         g_signal_connect (camera->video_encodebin, "element-added",
> +         (GCallback) encodebin_element_added, camera);
> +
> +-    camera->videosink =
> +-        gst_element_factory_make ("filesink", "videobin-filesink");
> ++    /* check if we need to replace the videosink */
> ++    if (camera->videosink) {
> ++      if (camera->user_video_sink && camera->user_video_sink != camera->videosink) {
> ++        gst_bin_remove (GST_BIN_CAST (camera), camera->videosink);
> ++        gst_object_unref (camera->videosink);
> ++        camera->videosink = NULL;
> ++      }
> ++    }
> ++
> +     if (!camera->videosink) {
> +-      missing_element_name = "filesink";
> +-      goto missing_element;
> ++      if (camera->user_video_sink) {
> ++        camera->videosink = gst_object_ref (camera->user_video_sink);
> ++      } else {
> ++        camera->videosink =
> ++          gst_element_factory_make ("filesink", "videobin-filesink");
> ++        if (!camera->videosink) {
> ++          missing_element_name = "filesink";
> ++          goto missing_element;
> ++        }
> ++        g_object_set (camera->videosink, "async", FALSE, NULL);
> ++      }
> +     }
> +-    g_object_set (camera->videosink, "async", FALSE, NULL);
> ++
> ++    g_assert (camera->videosink != NULL);
> +
> +     /* audio elements */
> +     if (!camera->audio_volume) {
> +@@ -1648,7 +1677,9 @@ gst_camera_bin_create_elements (GstCameraBin2 * camera)
> +     gst_element_set_locked_state (camera->videosink, TRUE);
> +     gst_element_set_locked_state (camera->imagesink, TRUE);
> +
> +-    g_object_set (camera->videosink, "location", camera->location, NULL);
> ++    if (!camera->user_video_sink) {
> ++      g_object_set (camera->videosink, "location", camera->location, NULL);
> ++    }
> +     g_object_set (camera->imagesink, "location", camera->location, NULL);
> +   }
> +
> +@@ -2014,6 +2045,20 @@ gst_camera_bin_set_audio_src (GstCameraBin2 * camera, GstElement * src)
> + }
> +
> + static void
> ++gst_camera_bin_set_video_sink (GstCameraBin2 * camera, GstElement * sink)
> ++{
> ++  GST_DEBUG_OBJECT (GST_OBJECT (camera),
> ++      "Setting video sink %" GST_PTR_FORMAT, sink);
> ++
> ++  if (camera->user_video_sink)
> ++    g_object_unref (camera->user_video_sink);
> ++
> ++  if (sink)
> ++    g_object_ref (sink);
> ++  camera->user_video_sink = sink;
> ++}
> ++
> ++static void
> + gst_camera_bin_set_camera_src (GstCameraBin2 * camera, GstElement * src)
> + {
> +   GST_DEBUG_OBJECT (GST_OBJECT (camera),
> +@@ -2046,6 +2091,9 @@ gst_camera_bin_set_property (GObject * object, guint prop_id,
> +     case PROP_AUDIO_SRC:
> +       gst_camera_bin_set_audio_src (camera, g_value_get_object (value));
> +       break;
> ++    case PROP_VIDEO_SINK:
> ++      gst_camera_bin_set_video_sink (camera, g_value_get_object (value));
> ++      break;
> +     case PROP_MUTE_AUDIO:
> +       g_object_set (camera->audio_volume, "mute", g_value_get_boolean (value),
> +           NULL);
> +@@ -2229,6 +2277,9 @@ gst_camera_bin_get_property (GObject * object, guint prop_id,
> +     case PROP_AUDIO_SRC:
> +       g_value_set_object (value, camera->user_audio_src);
> +       break;
> ++    case PROP_VIDEO_SINK:
> ++      g_value_set_object (value, camera->user_video_sink);
> ++      break;
> +     case PROP_MUTE_AUDIO:{
> +       gboolean mute;
> +
> +diff --git a/gst/camerabin2/gstcamerabin2.h b/gst/camerabin2/gstcamerabin2.h
> +index ba55a7e..9e090b6 100644
> +--- a/gst/camerabin2/gstcamerabin2.h
> ++++ b/gst/camerabin2/gstcamerabin2.h
> +@@ -71,6 +71,7 @@ struct _GstCameraBin2
> +   GstElement *video_encodebin;
> +   gulong video_encodebin_signal_id;
> +   GstElement *videosink;
> ++  GstElement *user_video_sink;
> +   GstElement *videobin_capsfilter;
> +
> +   GstElement *viewfinderbin;
> +--
> +1.9.1
> +
> diff --git a/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad/0006-Fix-for-gl-plugin-not-built-in-wayland-backend.patch b/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad/0006-Fix-for-gl-plugin-not-built-in-wayland-backend.patch
> new file mode 100644
> index 00000000..a1eb7060
> --- /dev/null
> +++ b/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad/0006-Fix-for-gl-plugin-not-built-in-wayland-backend.patch
> @@ -0,0 +1,34 @@
> +From 3015f801add8e0d004954d5e76ee9d8dcb6b88f6 Mon Sep 17 00:00:00 2001
> +From: Jian <Jian.Li at freescale.com>
> +Date: Fri, 24 Apr 2015 17:12:02 +0800
> +Subject: [PATCH 06/26] Fix for gl plugin not built in wayland backend
> +MIME-Version: 1.0
> +Content-Type: text/plain; charset=UTF-8
> +Content-Transfer-Encoding: 8bit
> +
> +Upstream-Status: Inappropriate [i.MX specific]
> +
> +Signed-off-by: Jian <Jian.Li at freescale.com>
> +
> +Conflicts:
> +       configure.ac
> +---
> + configure.ac | 2 +-
> + 1 file changed, 1 insertion(+), 1 deletion(-)
> +
> +diff --git a/configure.ac b/configure.ac
> +index b0a5b2a..8a05495 100644
> +--- a/configure.ac
> ++++ b/configure.ac
> +@@ -776,7 +776,7 @@ case $host in
> +     LIBS=$old_LIBS
> +     CFLAGS=$old_CFLAGS
> +
> +-    PKG_CHECK_MODULES(WAYLAND_EGL, wayland-client >= 1.0 wayland-cursor >= 1.0 wayland-egl >= 9.0, HAVE_WAYLAND_EGL=yes, HAVE_WAYLAND_EGL=no)
> ++    PKG_CHECK_MODULES(WAYLAND_EGL, wayland-client >= 1.0 wayland-cursor >= 1.0 wayland-egl >= 1.0, HAVE_WAYLAND_EGL=yes, HAVE_WAYLAND_EGL=no)
> +
> +     # OS X and iOS always have GL available
> +     case $host in
> +--
> +1.9.1
> +
> diff --git a/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad/0007-Change-wayland-default-res-to-1024x768.patch b/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad/0007-Change-wayland-default-res-to-1024x768.patch
> new file mode 100644
> index 00000000..cd0b23a2
> --- /dev/null
> +++ b/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad/0007-Change-wayland-default-res-to-1024x768.patch
> @@ -0,0 +1,41 @@
> +From 019b7942e2ba756ef65fa7ec3b5bd9ffa310af1e Mon Sep 17 00:00:00 2001
> +From: Jian <Jian.Li at freescale.com>
> +Date: Tue, 17 Nov 2015 14:39:07 +0800
> +Subject: [PATCH 07/26] Change wayland default res to 1024x768
> +MIME-Version: 1.0
> +Content-Type: text/plain; charset=UTF-8
> +Content-Transfer-Encoding: 8bit
> +
> +Change wayland backend default window resolution
> +from 320x240 to 1024x768
> +
> +Upstream-Status: Inappropriate [i.MX specific]
> +
> +Signed-off-by: Jian <Jian.Li at freescale.com>
> +---
> + gst-libs/gst/gl/wayland/gstglwindow_wayland_egl.c | 4 ++--
> + 1 file changed, 2 insertions(+), 2 deletions(-)
> +
> +diff --git a/gst-libs/gst/gl/wayland/gstglwindow_wayland_egl.c b/gst-libs/gst/gl/wayland/gstglwindow_wayland_egl.c
> +index 933ddfe..1930585 100644
> +--- a/gst-libs/gst/gl/wayland/gstglwindow_wayland_egl.c
> ++++ b/gst-libs/gst/gl/wayland/gstglwindow_wayland_egl.c
> +@@ -305,13 +305,13 @@ create_surfaces (GstGLWindowWaylandEGL * window_egl)
> +   if (window_egl->window.window_width > 0)
> +     width = window_egl->window.window_width;
> +   else
> +-    width = 320;
> ++    width = 1024;
> +   window_egl->window.window_width = width;
> +
> +   if (window_egl->window.window_height > 0)
> +     height = window_egl->window.window_height;
> +   else
> +-    height = 240;
> ++    height = 768;
> +   window_egl->window.window_height = height;
> +
> +   if (!window_egl->window.native) {
> +--
> +1.9.1
> +
> diff --git a/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad/0008-gl-wayland-fix-loop-test-hang-in-glimagesink.patch b/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad/0008-gl-wayland-fix-loop-test-hang-in-glimagesink.patch
> new file mode 100644
> index 00000000..25bd452a
> --- /dev/null
> +++ b/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad/0008-gl-wayland-fix-loop-test-hang-in-glimagesink.patch
> @@ -0,0 +1,142 @@
> +From 810fb3179c01747534af7f5b566f5e792be50b2b Mon Sep 17 00:00:00 2001
> +From: Haihua Hu <b55597 at freescale.com>
> +Date: Sun, 6 Dec 2015 14:25:44 +0800
> +Subject: [PATCH 08/26] gl/wayland: fix loop test hang in glimagesink
> +
> +Root cause: In glimagesink, gl thread will dispatch event queue and window_show()
> +is called from streaming thread. Gl thread will empty event queue and
> +potentially cause gst_gl_wl_display_roundtrip_queue() blocking the
> +streaming thread to wait for an event occur. Actually, no event can occur
> +becaue the swap_buffer event is queued by streaming thread but it is blocked.
> +
> +Solution: Use two event queue, One for surface and another for gl thread
> +
> +Upstream-Status: Pending
> +
> +bugzilla URL: https://bugzilla.gnome.org/show_bug.cgi?id=758984
> +
> +Signed-off-by: Haihua Hu <b55597 at freescale.com>
> +---
> + gst-libs/gst/gl/wayland/gstglwindow_wayland_egl.c | 33 +++++++++++++++--------
> + gst-libs/gst/gl/wayland/gstglwindow_wayland_egl.h |  2 +-
> + 2 files changed, 23 insertions(+), 12 deletions(-)
> +
> +diff --git a/gst-libs/gst/gl/wayland/gstglwindow_wayland_egl.c b/gst-libs/gst/gl/wayland/gstglwindow_wayland_egl.c
> +index 1930585..326e051 100644
> +--- a/gst-libs/gst/gl/wayland/gstglwindow_wayland_egl.c
> ++++ b/gst-libs/gst/gl/wayland/gstglwindow_wayland_egl.c
> +@@ -245,6 +245,10 @@ destroy_surfaces (GstGLWindowWaylandEGL * window_egl)
> +     wl_egl_window_destroy (window_egl->window.native);
> +     window_egl->window.native = NULL;
> +   }
> ++  if(window_egl->window.surface_queue) {
> ++    wl_event_queue_destroy (window_egl->window.surface_queue);
> ++    window_egl->window.surface_queue = NULL;
> ++  }
> + }
> +
> + static void
> +@@ -253,13 +257,15 @@ create_surfaces (GstGLWindowWaylandEGL * window_egl)
> +   GstGLDisplayWayland *display =
> +       GST_GL_DISPLAY_WAYLAND (GST_GL_WINDOW (window_egl)->display);
> +   gint width, height;
> ++  if (!window_egl->window.surface_queue)
> ++    window_egl->window.surface_queue = wl_display_create_queue (display->display);
> +
> +   if (!window_egl->window.surface) {
> +     window_egl->window.surface =
> +         wl_compositor_create_surface (display->compositor);
> +-    if (window_egl->window.queue)
> ++    if (window_egl->window.surface_queue)
> +       wl_proxy_set_queue ((struct wl_proxy *) window_egl->window.surface,
> +-          window_egl->window.queue);
> ++          window_egl->window.surface_queue);
> +   }
> +
> +   if (window_egl->window.foreign_surface) {
> +@@ -275,9 +281,9 @@ create_surfaces (GstGLWindowWaylandEGL * window_egl)
> +       window_egl->window.subsurface =
> +           wl_subcompositor_get_subsurface (display->subcompositor,
> +           window_egl->window.surface, window_egl->window.foreign_surface);
> +-      if (window_egl->window.queue)
> ++      if (window_egl->window.surface_queue)
> +         wl_proxy_set_queue ((struct wl_proxy *) window_egl->window.subsurface,
> +-            window_egl->window.queue);
> ++            window_egl->window.surface_queue);
> +
> +       wl_subsurface_set_position (window_egl->window.subsurface,
> +           window_egl->window.window_x, window_egl->window.window_y);
> +@@ -289,9 +295,9 @@ create_surfaces (GstGLWindowWaylandEGL * window_egl)
> +       window_egl->window.shell_surface =
> +           wl_shell_get_shell_surface (display->shell,
> +           window_egl->window.surface);
> +-      if (window_egl->window.queue)
> ++      if (window_egl->window.surface_queue)
> +         wl_proxy_set_queue ((struct wl_proxy *) window_egl->window.
> +-            shell_surface, window_egl->window.queue);
> ++            shell_surface, window_egl->window.surface_queue);
> +
> +       wl_shell_surface_add_listener (window_egl->window.shell_surface,
> +           &shell_surface_listener, window_egl);
> +@@ -319,9 +325,9 @@ create_surfaces (GstGLWindowWaylandEGL * window_egl)
> +
> +     window_egl->window.native =
> +         wl_egl_window_create (window_egl->window.surface, width, height);
> +-    if (window_egl->window.queue)
> ++    if (window_egl->window.surface_queue)
> +       wl_proxy_set_queue ((struct wl_proxy *) window_egl->window.native,
> +-          window_egl->window.queue);
> ++          window_egl->window.surface_queue);
> +   }
> + }
> +
> +@@ -372,6 +378,11 @@ gst_gl_window_wayland_egl_close (GstGLWindow * window)
> +
> +   destroy_surfaces (window_egl);
> +
> ++  if(window_egl->window.wl_queue) {
> ++    wl_event_queue_destroy (window_egl->window.wl_queue);
> ++    window_egl->window.wl_queue = NULL;
> ++  }
> ++
> +   g_source_destroy (window_egl->wl_source);
> +   g_source_unref (window_egl->wl_source);
> +   window_egl->wl_source = NULL;
> +@@ -400,10 +411,10 @@ gst_gl_window_wayland_egl_open (GstGLWindow * window, GError ** error)
> +     return FALSE;
> +   }
> +
> +-  window_egl->window.queue = wl_display_create_queue (display->display);
> ++  window_egl->window.wl_queue = wl_display_create_queue (display->display);
> +
> +   window_egl->wl_source = wayland_event_source_new (display->display,
> +-      window_egl->window.queue);
> ++      window_egl->window.wl_queue);
> +
> +   if (!GST_GL_WINDOW_CLASS (parent_class)->open (window, error))
> +     return FALSE;
> +@@ -452,7 +463,7 @@ gst_gl_window_wayland_egl_show (GstGLWindow * window)
> +   create_surfaces (window_egl);
> +
> +   if (gst_gl_wl_display_roundtrip_queue (display_wayland->display,
> +-          window_egl->window.queue) < 0)
> ++          window_egl->window.surface_queue) < 0)
> +     GST_WARNING_OBJECT (window, "failed a roundtrip");
> + }
> +
> +diff --git a/gst-libs/gst/gl/wayland/gstglwindow_wayland_egl.h b/gst-libs/gst/gl/wayland/gstglwindow_wayland_egl.h
> +index 16a0543..5256728 100644
> +--- a/gst-libs/gst/gl/wayland/gstglwindow_wayland_egl.h
> ++++ b/gst-libs/gst/gl/wayland/gstglwindow_wayland_egl.h
> +@@ -63,7 +63,7 @@ struct display {
> + struct window {
> +   struct display *display;
> +
> +-  struct wl_event_queue     *queue;
> ++  struct wl_event_queue     *wl_queue, *surface_queue;
> +   struct wl_surface         *surface;
> +   struct wl_shell_surface   *shell_surface;
> +   struct wl_egl_window      *native;
> +--
> +1.9.1
> +
> diff --git a/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad/0009-Fix-glimagesink-wayland-resize-showed-blurred-screen.patch b/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad/0009-Fix-glimagesink-wayland-resize-showed-blurred-screen.patch
> new file mode 100644
> index 00000000..ba85cc92
> --- /dev/null
> +++ b/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad/0009-Fix-glimagesink-wayland-resize-showed-blurred-screen.patch
> @@ -0,0 +1,32 @@
> +From 60647b7ab90b2efdbfb9c342be8acfde94d12fad Mon Sep 17 00:00:00 2001
> +From: Haihua Hu <b55597 at freescale.com>
> +Date: Tue, 8 Dec 2015 16:06:34 +0800
> +Subject: [PATCH 09/26] Fix glimagesink wayland resize showed blurred screen
> +
> +For imx, wl_egl_window type is not a wl_proxy object. Can not set
> +queue to wl_egl_window object.
> +
> +Upstream-Status: Inappropriate [i.MX specific]
> +
> +Signed-off-by: Haihua Hu <b55597 at freescale.com>
> +---
> + gst-libs/gst/gl/wayland/gstglwindow_wayland_egl.c | 3 ---
> + 1 file changed, 3 deletions(-)
> +
> +diff --git a/gst-libs/gst/gl/wayland/gstglwindow_wayland_egl.c b/gst-libs/gst/gl/wayland/gstglwindow_wayland_egl.c
> +index 326e051..c6a4d19 100644
> +--- a/gst-libs/gst/gl/wayland/gstglwindow_wayland_egl.c
> ++++ b/gst-libs/gst/gl/wayland/gstglwindow_wayland_egl.c
> +@@ -325,9 +325,6 @@ create_surfaces (GstGLWindowWaylandEGL * window_egl)
> +
> +     window_egl->window.native =
> +         wl_egl_window_create (window_egl->window.surface, width, height);
> +-    if (window_egl->window.surface_queue)
> +-      wl_proxy_set_queue ((struct wl_proxy *) window_egl->window.native,
> +-          window_egl->window.surface_queue);
> +   }
> + }
> +
> +--
> +1.9.1
> +
> diff --git a/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad/0010-support-video-crop-for-glimagesink.patch b/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad/0010-support-video-crop-for-glimagesink.patch
> new file mode 100644
> index 00000000..cf2a0856
> --- /dev/null
> +++ b/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad/0010-support-video-crop-for-glimagesink.patch
> @@ -0,0 +1,151 @@
> +From a90946b5890892f105bc89161f7c3b7b8f0b7f52 Mon Sep 17 00:00:00 2001
> +From: Haihua Hu <b55597 at freescale.com>
> +Date: Fri, 13 Nov 2015 10:51:25 +0800
> +Subject: [PATCH 10/26] support video crop for glimagesink
> +
> +1.Add video crop meta copy in glupload
> +2.Calculate the new texture coordinate in vertices array and bind to buffer object
> +3.Make glimagesink only updating vertices array when video crop meta changed
> +
> +Upstream-Status: Inappropriate [i.MX specific]
> +
> +Signed-off-by: Haihua Hu <b55597 at freescale.com>
> +---
> + ext/gl/gstglimagesink.c     | 58 +++++++++++++++++++++++++++++++++++++++++++++
> + ext/gl/gstglimagesink.h     |  3 +++
> + ext/gl/gstgluploadelement.c | 14 +++++++++--
> + 3 files changed, 73 insertions(+), 2 deletions(-)
> +
> +diff --git a/ext/gl/gstglimagesink.c b/ext/gl/gstglimagesink.c
> +index f6a61ac..75d3214 100644
> +--- a/ext/gl/gstglimagesink.c
> ++++ b/ext/gl/gstglimagesink.c
> +@@ -764,6 +764,8 @@ gst_glimage_sink_init (GstGLImageSink * glimage_sink)
> +   glimage_sink->handle_events = TRUE;
> +   glimage_sink->ignore_alpha = TRUE;
> +   glimage_sink->overlay_compositor = NULL;
> ++  glimage_sink->cropmeta = NULL;
> ++  glimage_sink->prev_cropmeta = NULL;
> +
> +   glimage_sink->mview_output_mode = DEFAULT_MULTIVIEW_MODE;
> +   glimage_sink->mview_output_flags = DEFAULT_MULTIVIEW_FLAGS;
> +@@ -1253,6 +1255,12 @@ gst_glimage_sink_change_state (GstElement * element, GstStateChange transition)
> +         gst_object_unref (glimage_sink->display);
> +         glimage_sink->display = NULL;
> +       }
> ++
> ++      glimage_sink->cropmeta = NULL;
> ++      if (glimage_sink->prev_cropmeta)
> ++        g_slice_free(GstVideoCropMeta, glimage_sink->prev_cropmeta);
> ++      glimage_sink->prev_cropmeta = NULL;
> ++
> +       break;
> +     default:
> +       break;
> +@@ -1737,6 +1745,8 @@ gst_glimage_sink_show_frame (GstVideoSink * vsink, GstBuffer * buf)
> +       GST_VIDEO_SINK_WIDTH (glimage_sink),
> +       GST_VIDEO_SINK_HEIGHT (glimage_sink));
> +
> ++  glimage_sink->cropmeta = gst_buffer_get_video_crop_meta (buf);
> ++
> +   /* Ask the underlying window to redraw its content */
> +   if (!gst_glimage_sink_redisplay (glimage_sink))
> +     goto redisplay_failed;
> +@@ -2222,6 +2232,54 @@ gst_glimage_sink_on_draw (GstGLImageSink * gl_sink)
> +
> +     gst_gl_shader_use (gl_sink->redisplay_shader);
> +
> ++    if (gl_sink->cropmeta) {
> ++      gint width = GST_VIDEO_SINK_WIDTH (gl_sink);
> ++      gint height = GST_VIDEO_SINK_HEIGHT (gl_sink);
> ++
> ++      if (!gl_sink->prev_cropmeta){
> ++        /* Initialize the previous crop meta and set all memroy to zero */
> ++        gl_sink->prev_cropmeta = (GstVideoCropMeta *) g_slice_new0(GstVideoCropMeta);
> ++      }
> ++
> ++      /* If crop meta not equal to the previous, recalculate the vertices */
> ++      if (gl_sink->prev_cropmeta->x != gl_sink->cropmeta->x
> ++        || gl_sink->prev_cropmeta->y != gl_sink->cropmeta->y
> ++        || gl_sink->prev_cropmeta->width != gl_sink->cropmeta->width
> ++        || gl_sink->prev_cropmeta->height != gl_sink->cropmeta->height){
> ++
> ++      GLfloat crop_vertices[] = {
> ++           1.0f,  1.0f, 0.0f, 1.0f, 0.0f,
> ++          -1.0f,  1.0f, 0.0f, 0.0f, 0.0f,
> ++          -1.0f, -1.0f, 0.0f, 0.0f, 1.0f,
> ++           1.0f, -1.0f, 0.0f, 1.0f, 1.0f
> ++      };
> ++
> ++        crop_vertices[8] = (float)(gl_sink->cropmeta->x) / width;
> ++        crop_vertices[9] = (float)(gl_sink->cropmeta->y) / height;
> ++
> ++        crop_vertices[3] = (float)(gl_sink->cropmeta->width + gl_sink->cropmeta->x) / width;
> ++        crop_vertices[4] = crop_vertices[9];
> ++
> ++        crop_vertices[13] = crop_vertices[8];
> ++        crop_vertices[14] = (float)(gl_sink->cropmeta->height + gl_sink->cropmeta->y) / height;
> ++
> ++        crop_vertices[18] = crop_vertices[3];
> ++        crop_vertices[19] = crop_vertices[14];
> ++
> ++        gl->BindBuffer (GL_ARRAY_BUFFER, gl_sink->vertex_buffer);
> ++        gl->BufferData (GL_ARRAY_BUFFER, 4 * 5 * sizeof (GLfloat), crop_vertices,
> ++            GL_STATIC_DRAW);
> ++
> ++        gl->BindBuffer (GL_ARRAY_BUFFER, 0);
> ++
> ++        /* Store the previous crop meta */
> ++        gl_sink->prev_cropmeta->x = gl_sink->cropmeta->x;
> ++        gl_sink->prev_cropmeta->y = gl_sink->cropmeta->y;
> ++        gl_sink->prev_cropmeta->width = gl_sink->cropmeta->width;
> ++        gl_sink->prev_cropmeta->height = gl_sink->cropmeta->height;
> ++      }
> ++    }
> ++
> +     if (gl->GenVertexArrays)
> +       gl->BindVertexArray (gl_sink->vao);
> +     _bind_buffer (gl_sink);
> +diff --git a/ext/gl/gstglimagesink.h b/ext/gl/gstglimagesink.h
> +index 8833103..0723e08 100644
> +--- a/ext/gl/gstglimagesink.h
> ++++ b/ext/gl/gstglimagesink.h
> +@@ -120,6 +120,9 @@ struct _GstGLImageSink
> +     guint window_width;
> +     guint window_height;
> +
> ++    GstVideoCropMeta *cropmeta;
> ++    GstVideoCropMeta *prev_cropmeta;
> ++
> +     GstVideoRectangle display_rect;
> +
> +     GstGLShader *redisplay_shader;
> +diff --git a/ext/gl/gstgluploadelement.c b/ext/gl/gstgluploadelement.c
> +index f9e52f6..52bd76a 100644
> +--- a/ext/gl/gstgluploadelement.c
> ++++ b/ext/gl/gstgluploadelement.c
> +@@ -256,9 +256,19 @@ gst_gl_upload_element_prepare_output_buffer (GstBaseTransform * bt,
> +   /* basetransform doesn't unref if they're the same */
> +   if (buffer == *outbuf)
> +     gst_buffer_unref (*outbuf);
> +-  else
> ++  else {
> ++    GstVideoCropMeta *incropmeta, *outcropmeta;
> ++    /* add video crop meta to out buffer if need */
> ++    incropmeta = gst_buffer_get_video_crop_meta (buffer);
> ++    if (incropmeta) {
> ++      outcropmeta = gst_buffer_add_video_crop_meta (*outbuf);
> ++      outcropmeta->x = incropmeta->x;
> ++      outcropmeta->y = incropmeta->y;
> ++      outcropmeta->width = incropmeta->width;
> ++      outcropmeta->height = incropmeta->height;
> ++    }
> +     bclass->copy_metadata (bt, buffer, *outbuf);
> +-
> ++  }
> +   return GST_FLOW_OK;
> + }
> +
> +--
> +1.9.1
> +
> diff --git a/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad/0011-Add-fps-print-in-glimagesink.patch b/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad/0011-Add-fps-print-in-glimagesink.patch
> new file mode 100644
> index 00000000..ba9b6b8b
> --- /dev/null
> +++ b/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad/0011-Add-fps-print-in-glimagesink.patch
> @@ -0,0 +1,86 @@
> +From cbe0f26aef2ab0e8004bdc75fe1e0a053e649642 Mon Sep 17 00:00:00 2001
> +From: Haihua Hu <b55597 at freescale.com>
> +Date: Wed, 18 Nov 2015 15:10:22 +0800
> +Subject: [PATCH 11/26] Add fps print in glimagesink
> +
> +In GST-1.6, Pipeline will set start time to 0 when state
> +change form PAUSE to READY, so get start time in state change
> +PLAYING_PAUSE.
> +
> +Upstream-Status: Inappropriate [i.MX specific]
> +
> +Signed-off-by: Haihua Hu <b55597 at freescale.com>
> +
> +Conflicts:
> +       ext/gl/gstglimagesink.h
> +---
> + ext/gl/gstglimagesink.c | 15 +++++++++++++++
> + ext/gl/gstglimagesink.h |  4 ++++
> + 2 files changed, 19 insertions(+)
> +
> +diff --git a/ext/gl/gstglimagesink.c b/ext/gl/gstglimagesink.c
> +index 75d3214..e697bd0 100644
> +--- a/ext/gl/gstglimagesink.c
> ++++ b/ext/gl/gstglimagesink.c
> +@@ -766,6 +766,8 @@ gst_glimage_sink_init (GstGLImageSink * glimage_sink)
> +   glimage_sink->overlay_compositor = NULL;
> +   glimage_sink->cropmeta = NULL;
> +   glimage_sink->prev_cropmeta = NULL;
> ++  glimage_sink->frame_showed = 0;
> ++  glimage_sink->run_time = 0;
> +
> +   glimage_sink->mview_output_mode = DEFAULT_MULTIVIEW_MODE;
> +   glimage_sink->mview_output_flags = DEFAULT_MULTIVIEW_FLAGS;
> +@@ -1169,7 +1171,10 @@ gst_glimage_sink_change_state (GstElement * element, GstStateChange transition)
> +
> +   switch (transition) {
> +     case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
> ++    {
> ++      glimage_sink->run_time = gst_element_get_start_time (GST_ELEMENT (glimage_sink));
> +       break;
> ++    }
> +     case GST_STATE_CHANGE_PAUSED_TO_READY:
> +     {
> +       GstBuffer *buf[2];
> +@@ -1261,6 +1266,14 @@ gst_glimage_sink_change_state (GstElement * element, GstStateChange transition)
> +         g_slice_free(GstVideoCropMeta, glimage_sink->prev_cropmeta);
> +       glimage_sink->prev_cropmeta = NULL;
> +
> ++      if (glimage_sink->run_time > 0) {
> ++        g_print ("Total showed frames (%lld), playing for (%"GST_TIME_FORMAT"), fps (%.3f).\n",
> ++                glimage_sink->frame_showed, GST_TIME_ARGS (glimage_sink->run_time),
> ++                (gfloat)GST_SECOND * glimage_sink->frame_showed / glimage_sink->run_time);
> ++      }
> ++
> ++      glimage_sink->frame_showed = 0;
> ++      glimage_sink->run_time = 0;
> +       break;
> +     default:
> +       break;
> +@@ -1759,6 +1772,8 @@ gst_glimage_sink_show_frame (GstVideoSink * vsink, GstBuffer * buf)
> +     return GST_FLOW_ERROR;
> +   }
> +
> ++  glimage_sink->frame_showed++;
> ++
> +   return GST_FLOW_OK;
> +
> + /* ERRORS */
> +diff --git a/ext/gl/gstglimagesink.h b/ext/gl/gstglimagesink.h
> +index 0723e08..405db44 100644
> +--- a/ext/gl/gstglimagesink.h
> ++++ b/ext/gl/gstglimagesink.h
> +@@ -143,6 +143,10 @@ struct _GstGLImageSink
> +     GstGLRotateMethod current_rotate_method;
> +     GstGLRotateMethod rotate_method;
> +     const gfloat *transform_matrix;
> ++
> ++    /* fps print support */
> ++    guint64 frame_showed;
> ++    GstClockTime run_time;
> + };
> +
> + struct _GstGLImageSinkClass
> +--
> +1.9.1
> +
> diff --git a/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad/0012-glcolorconvert-convert-YUV-to-RGB-use-directviv.patch b/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad/0012-glcolorconvert-convert-YUV-to-RGB-use-directviv.patch
> new file mode 100644
> index 00000000..a030657f
> --- /dev/null
> +++ b/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad/0012-glcolorconvert-convert-YUV-to-RGB-use-directviv.patch
> @@ -0,0 +1,168 @@
> +From 1808102fb3fce09f8f905364ec62595a48fb0753 Mon Sep 17 00:00:00 2001
> +From: Haihua Hu <b55597 at freescale.com>
> +Date: Thu, 25 Feb 2016 13:53:20 +0800
> +Subject: [PATCH 12/26] glcolorconvert: convert YUV to RGB use directviv
> +
> +Add a property "disable_passthrough" in glcolorconvert for enable/disable passthrough.
> +When need convert YUV to RGB with directviv, set it to be TRUE.
> +
> +Upstream-Status: Inappropriate [i.MX specific]
> +
> +Signed-off-by: Haihua Hu <b55597 at freescale.com>
> +
> +Conflicts:
> +       gst-libs/gst/gl/gstglcolorconvert.c
> +---
> + ext/gl/gstglcolorconvertelement.c   | 70 +++++++++++++++++++++++++++++++++++++
> + ext/gl/gstglcolorconvertelement.h   |  1 +
> + gst-libs/gst/gl/gstglcolorconvert.c |  6 +++-
> + 3 files changed, 76 insertions(+), 1 deletion(-)
> +
> +diff --git a/ext/gl/gstglcolorconvertelement.c b/ext/gl/gstglcolorconvertelement.c
> +index 642b494..5e26f84 100644
> +--- a/ext/gl/gstglcolorconvertelement.c
> ++++ b/ext/gl/gstglcolorconvertelement.c
> +@@ -35,6 +35,14 @@ G_DEFINE_TYPE_WITH_CODE (GstGLColorConvertElement, gst_gl_color_convert_element,
> +         "glconvertelement", 0, "convert");
> +     );
> +
> ++enum
> ++{
> ++  GL_COLOR_CONVERT_PROP_0,
> ++  GL_COLOR_CONVERT_PROP_DISABLE_PASSTHROUGH
> ++};
> ++
> ++#define DISABLE_PASSTHROUGH_DAFAULT FALSE
> ++
> + static gboolean gst_gl_color_convert_element_set_caps (GstBaseTransform * bt,
> +     GstCaps * in_caps, GstCaps * out_caps);
> + static GstCaps *gst_gl_color_convert_element_transform_caps (GstBaseTransform *
> +@@ -54,6 +62,15 @@ static GstFlowReturn gst_gl_color_convert_element_transform (GstBaseTransform *
> + static GstCaps *gst_gl_color_convert_element_fixate_caps (GstBaseTransform *
> +     bt, GstPadDirection direction, GstCaps * caps, GstCaps * othercaps);
> +
> ++static void gst_gl_color_convert_set_property (GObject *object,
> ++    guint prop_id,
> ++    const GValue *value,
> ++    GParamSpec *pspec);
> ++static void gst_gl_color_convert_get_property (GObject *object,
> ++    guint prop_id,
> ++    GValue *value,
> ++    GParamSpec *pspec);
> ++
> + static GstStaticPadTemplate gst_gl_color_convert_element_src_pad_template =
> + GST_STATIC_PAD_TEMPLATE ("src",
> +     GST_PAD_SRC,
> +@@ -89,6 +106,10 @@ gst_gl_color_convert_element_class_init (GstGLColorConvertElementClass * klass)
> + {
> +   GstBaseTransformClass *bt_class = GST_BASE_TRANSFORM_CLASS (klass);
> +   GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
> ++  GObjectClass *object_class = G_OBJECT_CLASS (klass);
> ++
> ++  object_class->set_property = gst_gl_color_convert_set_property;
> ++  object_class->get_property = gst_gl_color_convert_get_property;
> +
> +   bt_class->transform_caps = gst_gl_color_convert_element_transform_caps;
> +   bt_class->set_caps = gst_gl_color_convert_element_set_caps;
> +@@ -108,6 +129,13 @@ gst_gl_color_convert_element_class_init (GstGLColorConvertElementClass * klass)
> +   gst_element_class_add_static_pad_template (element_class,
> +       &gst_gl_color_convert_element_sink_pad_template);
> +
> ++  g_object_class_install_property (object_class, GL_COLOR_CONVERT_PROP_DISABLE_PASSTHROUGH,
> ++      g_param_spec_boolean ("disable_passthrough",
> ++          "Disable passthrough",
> ++          "Disable passthrough mode",
> ++          DISABLE_PASSTHROUGH_DAFAULT,
> ++          G_PARAM_READWRITE));
> ++
> +   gst_element_class_set_metadata (element_class,
> +       "OpenGL color converter", "Filter/Converter/Video",
> +       "Converts between color spaces using OpenGL shaders",
> +@@ -119,6 +147,41 @@ gst_gl_color_convert_element_init (GstGLColorConvertElement * convert)
> + {
> +   gst_base_transform_set_prefer_passthrough (GST_BASE_TRANSFORM (convert),
> +       TRUE);
> ++  convert->disable_passthrough = FALSE;
> ++}
> ++
> ++static void
> ++gst_gl_color_convert_set_property (GObject *object,
> ++    guint prop_id,
> ++    const GValue *value,
> ++    GParamSpec *pspec)
> ++{
> ++  GstGLColorConvertElement *convert = GST_GL_COLOR_CONVERT_ELEMENT (object);
> ++  switch (prop_id) {
> ++    case GL_COLOR_CONVERT_PROP_DISABLE_PASSTHROUGH:
> ++      convert->disable_passthrough = g_value_get_boolean (value);
> ++      break;
> ++    default:
> ++      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
> ++      break;
> ++  }
> ++}
> ++
> ++static void
> ++gst_gl_color_convert_get_property (GObject *object,
> ++    guint prop_id,
> ++    GValue *value,
> ++    GParamSpec *pspec)
> ++{
> ++  GstGLColorConvertElement *convert = GST_GL_COLOR_CONVERT_ELEMENT (object);
> ++  switch (prop_id) {
> ++    case GL_COLOR_CONVERT_PROP_DISABLE_PASSTHROUGH:
> ++      g_value_set_boolean (value, convert->disable_passthrough);
> ++      break;
> ++    default:
> ++      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
> ++      break;
> ++  }
> + }
> +
> + static gboolean
> +@@ -133,6 +196,13 @@ gst_gl_color_convert_element_set_caps (GstBaseTransform * bt,
> +   if (convert->convert)
> +     gst_gl_color_convert_set_caps (convert->convert, in_caps, out_caps);
> +
> ++  if(gst_base_transform_is_passthrough (bt) && convert->disable_passthrough){
> ++    /* if in passthrough mode and disable_passthrough is set to true,
> ++     * set passthrough to FALSE*/
> ++    GST_DEBUG_OBJECT(convert, "Disable passthrough mode");
> ++    gst_base_transform_set_passthrough(bt, FALSE);
> ++  }
> ++
> +   return TRUE;
> + }
> +
> +diff --git a/ext/gl/gstglcolorconvertelement.h b/ext/gl/gstglcolorconvertelement.h
> +index 2a0dd1d..5cdbd3a 100644
> +--- a/ext/gl/gstglcolorconvertelement.h
> ++++ b/ext/gl/gstglcolorconvertelement.h
> +@@ -47,6 +47,7 @@ struct _GstGLColorConvertElement
> +   GstGLColorConvert *convert;
> +   GstCaps *in_caps;
> +   GstCaps *out_caps;
> ++  gboolean disable_passthrough;
> + };
> +
> + struct _GstGLColorConvertElementClass
> +diff --git a/gst-libs/gst/gl/gstglcolorconvert.c b/gst-libs/gst/gl/gstglcolorconvert.c
> +index 89edb16..adf5a6e 100644
> +--- a/gst-libs/gst/gl/gstglcolorconvert.c
> ++++ b/gst-libs/gst/gl/gstglcolorconvert.c
> +@@ -718,7 +718,11 @@ _gst_gl_color_convert_set_caps_unlocked (GstGLColorConvert * convert,
> +   convert->priv->to_texture_target = to_target;
> +   convert->initted = FALSE;
> +
> +-  convert->passthrough = passthrough;
> ++  /* We may disable passthrough via an external property
> ++   * By the way, when glconvertelement is in passthrough mode,
> ++   * the plugin will not call gst_gl_color_convert_perform().*/
> ++
> ++  //convert->passthrough = passthrough;
> + #ifndef GST_DISABLE_GST_DEBUG
> +   if (G_UNLIKELY (convert->passthrough))
> +     GST_DEBUG_OBJECT (convert,
> +--
> +1.9.1
> +
> diff --git a/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad/0013-videocompositor-Remove-output-format-alpha-check.patch b/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad/0013-videocompositor-Remove-output-format-alpha-check.patch
> new file mode 100644
> index 00000000..eb7e132f
> --- /dev/null
> +++ b/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad/0013-videocompositor-Remove-output-format-alpha-check.patch
> @@ -0,0 +1,35 @@
> +From cd2d0769aaf242ecb24e18b7acc027bfb846b7c8 Mon Sep 17 00:00:00 2001
> +From: Song Bing <bing.song at nxp.com>
> +Date: Tue, 16 Aug 2016 13:11:57 +0800
> +Subject: [PATCH 13/26] videocompositor: Remove output format alpha check
> +
> +Remove output format alpha check, or output without alpha will
> +fail if input has alpha.
> +
> +Upstream-Status: Pending
> +
> +https://bugzilla.gnome.org/show_bug.cgi?id=769962
> +---
> + gst-libs/gst/video/gstvideoaggregator.c | 4 +---
> + 1 file changed, 1 insertion(+), 3 deletions(-)
> +
> +diff --git a/gst-libs/gst/video/gstvideoaggregator.c b/gst-libs/gst/video/gstvideoaggregator.c
> +index 1616b27..a987c15 100644
> +--- a/gst-libs/gst/video/gstvideoaggregator.c
> ++++ b/gst-libs/gst/video/gstvideoaggregator.c
> +@@ -781,11 +781,9 @@ gst_video_aggregator_update_src_caps (GstVideoAggregator * vagg)
> +       g_return_val_if_fail (finfo != NULL, FALSE);
> +
> +       if (at_least_one_alpha && !(finfo->flags & GST_VIDEO_FORMAT_FLAG_ALPHA)) {
> +-        GST_ELEMENT_ERROR (vagg, CORE, NEGOTIATION,
> ++        GST_WARNING_OBJECT (vagg,
> +             ("At least one of the input pads contains alpha, but configured caps don't support alpha."),
> +             ("Either convert your inputs to not contain alpha or add a videoconvert after the aggregator"));
> +-        ret = FALSE;
> +-        goto done;
> +       }
> +     }
> +
> +--
> +1.9.1
> +
> diff --git a/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad/0014-Specific-patches-for-gstplayer-API.patch b/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad/0014-Specific-patches-for-gstplayer-API.patch
> new file mode 100644
> index 00000000..61cafda6
> --- /dev/null
> +++ b/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad/0014-Specific-patches-for-gstplayer-API.patch
> @@ -0,0 +1,367 @@
> +From e277ba3892378d6562913e2a803f3a126d46c720 Mon Sep 17 00:00:00 2001
> +From: Lyon Wang <lyon.wang at nxp.com>
> +Date: Fri, 30 Dec 2016 15:53:21 +0800
> +Subject: [PATCH 14/26] Specific patches for gstplayer API
> +
> +player: Add get_rotate, set_rotate API
> +
> +- Add gstplayer get_rotate() and set_rotate() API
> +
> +player: Add force-aspect-ratio config
> +
> +- Add get/set force-aspect-ratio config API
> +
> +player: Add set audio / text sink API
> +
> +- Add get/set audio / text sink API
> +
> +Upstream-Status: Inappropriate [i.MX specific]
> +
> +Signed-off-by: Lyon Wang <lyon.wang at nxp.com>
> +
> +Conflicts:
> +       gst-libs/gst/player/gstplayer.c
> +       gst-libs/gst/player/gstplayer.h
> +---
> + gst-libs/gst/player/gstplayer.c | 284 ++++++++++++++++++++++++++++++++++++++++
> + gst-libs/gst/player/gstplayer.h |  11 ++
> + 2 files changed, 295 insertions(+)
> +
> +diff --git a/gst-libs/gst/player/gstplayer.c b/gst-libs/gst/player/gstplayer.c
> +index 273a480..92ad919 100644
> +--- a/gst-libs/gst/player/gstplayer.c
> ++++ b/gst-libs/gst/player/gstplayer.c
> +@@ -82,6 +82,7 @@ typedef enum
> +   CONFIG_QUARK_USER_AGENT = 0,
> +   CONFIG_QUARK_POSITION_INTERVAL_UPDATE,
> +   CONFIG_QUARK_ACCURATE_SEEK,
> ++  CONFIG_QUARK_FORCE_ASPECT_RATIO,
> +
> +   CONFIG_QUARK_MAX
> + } ConfigQuarkId;
> +@@ -90,6 +91,7 @@ static const gchar *_config_quark_strings[] = {
> +   "user-agent",
> +   "position-interval-update",
> +   "accurate-seek",
> ++  "force-aspect-ratio",
> + };
> +
> + GQuark _config_quark_table[CONFIG_QUARK_MAX];
> +@@ -286,6 +288,7 @@ gst_player_init (GstPlayer * self)
> +   self->config = gst_structure_new_id (QUARK_CONFIG,
> +       CONFIG_QUARK (POSITION_INTERVAL_UPDATE), G_TYPE_UINT, DEFAULT_POSITION_UPDATE_INTERVAL_MS,
> +       CONFIG_QUARK (ACCURATE_SEEK), G_TYPE_BOOLEAN, FALSE,
> ++      CONFIG_QUARK (FORCE_ASPECT_RATIO), G_TYPE_BOOLEAN, TRUE,
> +       NULL);
> +   /* *INDENT-ON* */
> +
> +@@ -4758,3 +4761,284 @@ gst_player_get_video_snapshot (GstPlayer * self,
> +
> +   return sample;
> + }
> ++
> ++/**
> ++ * gst_player_get_video_sink:
> ++ * @player: #GstPlayer instance
> ++ *
> ++ * Returns: actual video sink element
> ++ */
> ++GstElement *
> ++gst_player_get_video_sink (GstPlayer * self)
> ++{
> ++  GstElement *sink = NULL;
> ++  GstElement *actual_sink = NULL;
> ++  GstIteratorResult rc;
> ++  GstIterator *it;
> ++  GValue item = { 0, };
> ++  g_return_val_if_fail (GST_IS_PLAYER (self), NULL);
> ++
> ++  g_object_get (G_OBJECT (self->playbin), "video-sink", &sink, NULL);
> ++  if (NULL == sink) {
> ++    GST_WARNING_OBJECT (self, "No video-sink found");
> ++    return NULL;
> ++  }
> ++  it = gst_bin_iterate_sinks ((GstBin *) sink);
> ++  do {
> ++    rc = gst_iterator_next (it, &item);
> ++    if (rc == GST_ITERATOR_OK) {
> ++      break;
> ++    }
> ++  } while (rc != GST_ITERATOR_DONE);
> ++
> ++  g_object_unref (sink);
> ++  actual_sink = g_value_get_object (&item);
> ++  g_value_unset (&item);
> ++  gst_iterator_free (it);
> ++
> ++  if (NULL == actual_sink) {
> ++    GST_WARNING_OBJECT (self, "No video-sink found");
> ++    return NULL;
> ++  }
> ++
> ++  return actual_sink;
> ++}
> ++
> ++/**
> ++ * gst_palyer_set_rotate:
> ++ * @player: #GstPlayer instance
> ++ * @rotation: rotation degree value
> ++ *
> ++ * Returns: %TRUE or %FALSE
> ++ *
> ++ * Set the rotation vaule
> ++ */
> ++gboolean
> ++gst_player_set_rotate (GstPlayer * self, gint rotation)
> ++{
> ++  GstElement *video_sink = NULL;
> ++  GObjectClass *gobjclass = NULL;
> ++  g_return_val_if_fail (GST_IS_PLAYER (self), FALSE);
> ++
> ++  video_sink = gst_player_get_video_sink (self);
> ++  if (NULL == video_sink) {
> ++    GST_WARNING_OBJECT (self, " cannot get  video sink ");
> ++    return FALSE;
> ++  }
> ++  GST_DEBUG_OBJECT (self, "set rotation degree '%d'", rotation);
> ++
> ++  gobjclass = G_OBJECT_GET_CLASS (G_OBJECT (video_sink));
> ++  if (g_object_class_find_property (gobjclass, "rotate")
> ++      && g_object_class_find_property (gobjclass, "reconfig")) {
> ++    g_object_set (G_OBJECT (video_sink), "rotate", rotation / 90, NULL);
> ++    g_object_set (G_OBJECT (video_sink), "reconfig", 1, NULL);
> ++  } else if (g_object_class_find_property (gobjclass, "rotate-method")) {
> ++    g_object_set (G_OBJECT (video_sink), "rotate-method", rotation / 90, NULL);
> ++  } else {
> ++    GST_INFO_OBJECT (self, "can't set rotation for current video sink %s'",
> ++        gst_element_get_name (video_sink));
> ++    return FALSE;
> ++  }
> ++
> ++  return TRUE;
> ++}
> ++
> ++/**
> ++ * gst_player_get_rotate:
> ++ * @player: #GstPlayer instance
> ++ *
> ++ * Returns: the rotation degree value
> ++ */
> ++gint
> ++gst_player_get_rotate (GstPlayer * self)
> ++{
> ++  GstElement *video_sink = NULL;
> ++  GObjectClass *gobjclass = NULL;
> ++  gint rotation = 0;
> ++  g_return_val_if_fail (GST_IS_PLAYER (self), 0);
> ++
> ++  video_sink = gst_player_get_video_sink (self);
> ++  if (NULL == video_sink) {
> ++    GST_WARNING_OBJECT (self, " cannot get  video sink ");
> ++    return 0;
> ++  }
> ++
> ++  /* check if the element has "rotate" property */
> ++  gobjclass = G_OBJECT_GET_CLASS (video_sink);
> ++  if (g_object_class_find_property (gobjclass, "rotate")) {
> ++    g_object_get (G_OBJECT (video_sink), "rotate", &rotation, NULL);
> ++    rotation = rotation * 90;
> ++  } else if (g_object_class_find_property (gobjclass, "rotate-method")) {
> ++    g_object_get (G_OBJECT (video_sink), "rotate-method", &rotation, NULL);
> ++    rotation = rotation * 90;
> ++  }
> ++
> ++  GST_DEBUG_OBJECT (self, "get rotation degree '%d'", rotation);
> ++
> ++  return rotation;
> ++}
> ++
> ++/**
> ++ * gst_player_config_set_force_aspect_ratio:
> ++ * @player: #GstPlayer instance
> ++ * @force_aspect_ratio: keey original aspect ratio or not
> ++ *
> ++ * Enable or disable force aspect ratio
> ++ * force_aspect_ratio seeking is TRUE by default.
> ++ *
> ++ * Since: 1.12
> ++ */
> ++void
> ++gst_player_config_set_force_aspect_ratio (GstPlayer * self, gboolean force_aspect_ratio)
> ++{
> ++  GstStructure *config = self->config;
> ++  g_return_if_fail (config != NULL);
> ++
> ++  gst_structure_id_set (config,
> ++      CONFIG_QUARK (FORCE_ASPECT_RATIO), G_TYPE_BOOLEAN, force_aspect_ratio, NULL);
> ++
> ++  g_object_set(self->playbin, "force-aspect-ratio", force_aspect_ratio, NULL);
> ++}
> ++
> ++/**
> ++ * gst_player_config_get_force_aspect_ratio:
> ++ * @config: a #GstPlayer configuration
> ++ *
> ++ * Returns: %TRUE if force-aspect-ratio is enabled
> ++ *
> ++ * Since 1.12
> ++ */
> ++gboolean
> ++gst_player_config_get_force_aspect_ratio (const GstStructure * config)
> ++{
> ++  gboolean force_aspect_ratio = TRUE;
> ++
> ++  g_return_val_if_fail (config != NULL, FALSE);
> ++
> ++  gst_structure_id_get (config,
> ++      CONFIG_QUARK (FORCE_ASPECT_RATIO), G_TYPE_BOOLEAN, &force_aspect_ratio, NULL);
> ++
> ++  return force_aspect_ratio;
> ++}
> ++
> ++/**
> ++ * gst_player_set_audio_sink:
> ++ * @player: #GstPlayer instance
> ++ * @audio_sink: the custom audio sink to set
> ++ *
> ++ * Returns: %TRUE or %FALSE
> ++ *
> ++ * Set the customize audio sink
> ++ */
> ++gboolean
> ++gst_player_set_audio_sink (GstPlayer * self,  GstElement * audio_sink)
> ++{
> ++  g_return_val_if_fail (GST_IS_PLAYER (self), FALSE);
> ++  g_return_val_if_fail (audio_sink != NULL, FALSE);
> ++
> ++  g_object_set (G_OBJECT (self->playbin), "audio-sink", audio_sink, NULL);
> ++  return TRUE;
> ++}
> ++
> ++/**
> ++ * gst_player_set_text_sink:
> ++ * @player: #GstPlayer instance
> ++ * @text_sink: the custom text sink  to set
> ++ *
> ++ * Returns: %TRUE or %FALSE
> ++ *
> ++ * Set the customize text sink
> ++ */
> ++gboolean
> ++gst_player_set_text_sink (GstPlayer * self,  GstElement * text_sink)
> ++{
> ++  g_return_val_if_fail (GST_IS_PLAYER (self), FALSE);
> ++  g_return_val_if_fail (text_sink != NULL, FALSE);
> ++
> ++  g_object_set (G_OBJECT (self->playbin), "text-sink", text_sink, NULL);
> ++  return TRUE;
> ++}
> ++
> ++/**
> ++ * gst_player_get_audio_sink:
> ++ * @player: #GstPlayer instance
> ++ *
> ++ * Returns: actual audio sink element
> ++ */
> ++GstElement *
> ++gst_player_get_audio_sink (GstPlayer * self)
> ++{
> ++  GstElement *sink = NULL;
> ++  GstElement *actual_sink = NULL;
> ++  GstIteratorResult rc;
> ++  GstIterator *it;
> ++  GValue item = { 0, };
> ++  g_return_val_if_fail (GST_IS_PLAYER (self), NULL);
> ++
> ++  g_object_get (G_OBJECT (self->playbin), "audio-sink", &sink, NULL);
> ++  if (NULL == sink) {
> ++    GST_WARNING_OBJECT (self, "No audio-sink found");
> ++    return NULL;
> ++  }
> ++  it = gst_bin_iterate_sinks ((GstBin *) sink);
> ++  do {
> ++    rc = gst_iterator_next (it, &item);
> ++    if (rc == GST_ITERATOR_OK) {
> ++      break;
> ++    }
> ++  } while (rc != GST_ITERATOR_DONE);
> ++
> ++  g_object_unref (sink);
> ++  actual_sink = g_value_get_object (&item);
> ++  g_value_unset (&item);
> ++  gst_iterator_free (it);
> ++
> ++  if (NULL == actual_sink) {
> ++    GST_WARNING_OBJECT (self, "No auido-sink found");
> ++    return NULL;
> ++  }
> ++
> ++  return actual_sink;
> ++}
> ++
> ++/**
> ++ * gst_player_get_text_sink:
> ++ * @player: #GstPlayer instance
> ++ *
> ++ * Returns: actual text sink element
> ++ */
> ++GstElement *
> ++gst_player_get_text_sink (GstPlayer * self)
> ++{
> ++  GstElement *sink = NULL;
> ++  GstElement *actual_sink = NULL;
> ++  GstIteratorResult rc;
> ++  GstIterator *it;
> ++  GValue item = { 0, };
> ++  g_return_val_if_fail (GST_IS_PLAYER (self), NULL);
> ++
> ++  g_object_get (G_OBJECT (self->playbin), "text-sink", &sink, NULL);
> ++  if (NULL == sink) {
> ++    GST_WARNING_OBJECT (self, "No text-sink found");
> ++    return NULL;
> ++  }
> ++  it = gst_bin_iterate_sinks ((GstBin *) sink);
> ++  do {
> ++    rc = gst_iterator_next (it, &item);
> ++    if (rc == GST_ITERATOR_OK) {
> ++      break;
> ++    }
> ++  } while (rc != GST_ITERATOR_DONE);
> ++
> ++  g_object_unref (sink);
> ++  actual_sink = g_value_get_object (&item);
> ++  g_value_unset (&item);
> ++  gst_iterator_free (it);
> ++
> ++  if (NULL == actual_sink) {
> ++    GST_WARNING_OBJECT (self, "No text-sink found");
> ++    return NULL;
> ++  }
> ++
> ++  return actual_sink;
> ++}
> +diff --git a/gst-libs/gst/player/gstplayer.h b/gst-libs/gst/player/gstplayer.h
> +index 0338d1a..f444918 100644
> +--- a/gst-libs/gst/player/gstplayer.h
> ++++ b/gst-libs/gst/player/gstplayer.h
> +@@ -216,6 +216,17 @@ typedef enum
> +
> + GstSample * gst_player_get_video_snapshot (GstPlayer * player,
> +     GstPlayerSnapshotFormat format, GstStructure * config);
> ++/* Custom gstplayer API */
> ++gboolean    gst_player_set_rotate (GstPlayer * player, gint rotation);
> ++gint        gst_player_get_rotate (GstPlayer * player);
> ++
> ++void        gst_player_config_set_force_aspect_ratio (GstPlayer * self, gboolean force_aspect_ratio);
> ++gboolean    gst_player_config_get_force_aspect_ratio (const GstStructure * config);
> ++
> ++gboolean    gst_player_set_audio_sink (GstPlayer * player, GstElement * audio_sink);
> ++gboolean    gst_player_set_text_sink (GstPlayer * player, GstElement * text_sink);
> ++GstElement * gst_player_get_audio_sink (GstPlayer * player);
> ++GstElement * gst_player_get_text_sink (GstPlayer * player);
> +
> + G_END_DECLS
> +
> +--
> +1.9.1
> +
> diff --git a/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad/0015-gstplayer-Add-gst_player_get_state-API.patch b/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad/0015-gstplayer-Add-gst_player_get_state-API.patch
> new file mode 100644
> index 00000000..da6f8783
> --- /dev/null
> +++ b/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad/0015-gstplayer-Add-gst_player_get_state-API.patch
> @@ -0,0 +1,63 @@
> +From 6e74c8bb4c93f07a83b6e79acfcef467e735abc5 Mon Sep 17 00:00:00 2001
> +From: Lyon Wang <lyon.wang at nxp.com>
> +Date: Fri, 17 Feb 2017 17:22:31 +0800
> +Subject: [PATCH 15/26] gstplayer: Add gst_player_get_state() API
> +
> +- Add gst_player_get_state() API
> +
> +https://bugzilla.gnome.org/show_bug.cgi?id=778379
> +Upstream-Status: Submitted
> +
> +Signed-off-by: Lyon Wang <lyon.wang at nxp.com>
> +
> +Conflicts:
> +       gst-libs/gst/player/gstplayer.c
> +---
> + gst-libs/gst/player/gstplayer.c | 20 ++++++++++++++++++++
> + gst-libs/gst/player/gstplayer.h |  2 ++
> + 2 files changed, 22 insertions(+)
> +
> +diff --git a/gst-libs/gst/player/gstplayer.c b/gst-libs/gst/player/gstplayer.c
> +index 92ad919..ebad94e 100644
> +--- a/gst-libs/gst/player/gstplayer.c
> ++++ b/gst-libs/gst/player/gstplayer.c
> +@@ -5042,3 +5042,23 @@ gst_player_get_text_sink (GstPlayer * self)
> +
> +   return actual_sink;
> + }
> ++
> ++/**
> ++ * gst_player_get_state:
> ++ * @player: #GstPlayer instance
> ++ *
> ++ * Gets internal GstPlayer state.
> ++ * It's not guaranteed that the state returned is the current state,
> ++ * it might've changed in the meantime.
> ++ *
> ++ * Returns: (transfer none): internal GstPlayerState
> ++ *
> ++ * Since 1.12
> ++ */
> ++GstPlayerState
> ++gst_player_get_state (GstPlayer * self)
> ++{
> ++  g_return_val_if_fail (GST_IS_PLAYER (self), GST_PLAYER_STATE_STOPPED);
> ++
> ++  return self->app_state;
> ++}
> +diff --git a/gst-libs/gst/player/gstplayer.h b/gst-libs/gst/player/gstplayer.h
> +index f444918..5ee3592 100644
> +--- a/gst-libs/gst/player/gstplayer.h
> ++++ b/gst-libs/gst/player/gstplayer.h
> +@@ -228,6 +228,8 @@ gboolean    gst_player_set_text_sink (GstPlayer * player, GstElement * text_sink
> + GstElement * gst_player_get_audio_sink (GstPlayer * player);
> + GstElement * gst_player_get_text_sink (GstPlayer * player);
> +
> ++GstPlayerState  gst_player_get_state (GstPlayer * player);
> ++
> + G_END_DECLS
> +
> + #endif /* __GST_PLAYER_H__ */
> +--
> +1.9.1
> +
> diff --git a/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad/0016-gstplayer-Add-play-stop-sync-API.patch b/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad/0016-gstplayer-Add-play-stop-sync-API.patch
> new file mode 100644
> index 00000000..a4ccc18b
> --- /dev/null
> +++ b/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad/0016-gstplayer-Add-play-stop-sync-API.patch
> @@ -0,0 +1,182 @@
> +From cbbb524a5e634463965935cf9b6d03ec91804e2d Mon Sep 17 00:00:00 2001
> +From: Lyon Wang <lyon.wang at nxp.com>
> +Date: Thu, 16 Feb 2017 18:50:28 +0800
> +Subject: [PATCH 16/26] gstplayer: Add play/stop sync API
> +
> +- Add play/stop/pause sync API
> +      gst_player_play_sync()
> +      gst_player_stop_sync()
> +      gst_player_pause_sync()
> +
> +https://bugzilla.gnome.org/show_bug.cgi?id=778390
> +
> +Upstream-Status: Inappropriate [i.MX specific]
> +
> +Signed-off-by: Lyon Wang <lyon.wang at nxp.com>
> +
> +Conflicts:
> +       gst-libs/gst/player/gstplayer.c
> +---
> + gst-libs/gst/player/gstplayer.c | 112 ++++++++++++++++++++++++++++++++++++++++
> + gst-libs/gst/player/gstplayer.h |   4 ++
> + 2 files changed, 116 insertions(+)
> +
> +diff --git a/gst-libs/gst/player/gstplayer.c b/gst-libs/gst/player/gstplayer.c
> +index ebad94e..8c94a98 100644
> +--- a/gst-libs/gst/player/gstplayer.c
> ++++ b/gst-libs/gst/player/gstplayer.c
> +@@ -200,6 +200,10 @@ struct _GstPlayer
> +   gchar *audio_sid;
> +   gchar *subtitle_sid;
> +   gulong stream_notify_id;
> ++
> ++  /* When error occur, will set this flag to TRUE,
> ++   * so that it could quit for sync play/stop loop */
> ++  gboolean got_error;
> + };
> +
> + struct _GstPlayerClass
> +@@ -296,6 +300,7 @@ gst_player_init (GstPlayer * self)
> +   self->seek_position = GST_CLOCK_TIME_NONE;
> +   self->last_seek_time = GST_CLOCK_TIME_NONE;
> +   self->inhibit_sigs = FALSE;
> ++  self->got_error = FALSE;
> +
> +   GST_TRACE_OBJECT (self, "Initialized");
> + }
> +@@ -1055,6 +1060,8 @@ emit_error (GstPlayer * self, GError * err)
> +   GST_ERROR_OBJECT (self, "Error: %s (%s, %d)", err->message,
> +       g_quark_to_string (err->domain), err->code);
> +
> ++  self->got_error = TRUE;
> ++
> +   if (g_signal_handler_find (self, G_SIGNAL_MATCH_ID,
> +           signals[SIGNAL_ERROR], 0, NULL, NULL, NULL) != 0) {
> +     ErrorSignalData *data = g_new (ErrorSignalData, 1);
> +@@ -5062,3 +5069,108 @@ gst_player_get_state (GstPlayer * self)
> +
> +   return self->app_state;
> + }
> ++
> ++/**
> ++ * gst_player_wait_state
> ++ * @player: #GstPlayer instance
> ++ * @target_state: target state
> ++ * @time_out:  time out value
> ++ *  negtive (< 0): infinitely waiting for state change.
> ++ *  positive (>0): wait until time out.
> ++ *  zero (0), do not wait for the state change.
> ++ *
> ++ * Wait for target state, quit loop when time out
> ++ */
> ++static void
> ++gst_player_wait_state (GstPlayer * self, GstPlayerState target_state,
> ++    gint time_out)
> ++{
> ++  gint wait_cnt = 0;
> ++
> ++  while (time_out < 0 || wait_cnt < time_out * 20) {
> ++    if (self->app_state == target_state) {
> ++      break;
> ++    } else if (self->got_error == TRUE) {
> ++      self->got_error = FALSE;
> ++      return;
> ++    } else if (self->is_eos == TRUE) {
> ++      return;
> ++    } else {
> ++      wait_cnt++;
> ++      usleep (50000);
> ++    }
> ++  }
> ++  if (time_out > 0 && wait_cnt >= time_out * 20) {
> ++    emit_error (self, g_error_new (GST_PLAYER_ERROR,
> ++            GST_PLAYER_ERROR_FAILED,
> ++            "try to play /stop /pause failed, time out"));
> ++  }
> ++
> ++  return;
> ++}
> ++
> ++/**
> ++ * gst_player_play_sync:
> ++ * @player: #GstPlayer instance
> ++ * @time_out:  time out value
> ++ *  negtive (< 0): infinitely waiting for state change.
> ++ *  positive (>0): wait until time out.
> ++ *  zero (0), do not wait for the state change.
> ++ *
> ++ * Request to play the loaded stream in sync mode.
> ++ */
> ++void
> ++gst_player_play_sync (GstPlayer * self, gint time_out)
> ++{
> ++  g_return_if_fail (GST_IS_PLAYER (self));
> ++
> ++  gst_player_play (self);
> ++
> ++  gst_player_wait_state (self, GST_PLAYER_STATE_PLAYING, time_out);
> ++
> ++  return;
> ++}
> ++
> ++/**
> ++ * gst_player_stop_sync:
> ++ * @player: #GstPlayer instance
> ++ * @time_out:  time out value
> ++ *  negtive (< 0): infinitely waiting for state change.
> ++ *  positive (>0): wait until time out.
> ++ *  zero (0), do not wait for the state change.
> ++ *
> ++ *  Stops playing the current stream in sync mode.
> ++ */
> ++void
> ++gst_player_stop_sync (GstPlayer * self, gint time_out)
> ++{
> ++  g_return_if_fail (GST_IS_PLAYER (self));
> ++
> ++  gst_player_stop (self);
> ++
> ++  gst_player_wait_state (self, GST_PLAYER_STATE_STOPPED, time_out);
> ++
> ++  return;
> ++}
> ++
> ++/**
> ++ * gst_player_pause_sync:
> ++ * @player: #GstPlayer instance
> ++ * @time_out:  time out value
> ++ *  negtive (< 0): infinitely waiting for state change.
> ++ *  positive (>0): wait until time out.
> ++ *  zero (0), do not wait for the state change.
> ++ *
> ++ *  Pause current stream in sync mode.
> ++ */
> ++void
> ++gst_player_pause_sync (GstPlayer * self, gint time_out)
> ++{
> ++  g_return_if_fail (GST_IS_PLAYER (self));
> ++
> ++  gst_player_pause (self);
> ++
> ++  gst_player_wait_state (self, GST_PLAYER_STATE_PAUSED, time_out);
> ++
> ++  return;
> ++}
> +diff --git a/gst-libs/gst/player/gstplayer.h b/gst-libs/gst/player/gstplayer.h
> +index 5ee3592..ee1a8da 100644
> +--- a/gst-libs/gst/player/gstplayer.h
> ++++ b/gst-libs/gst/player/gstplayer.h
> +@@ -230,6 +230,10 @@ GstElement * gst_player_get_text_sink (GstPlayer * player);
> +
> + GstPlayerState  gst_player_get_state (GstPlayer * player);
> +
> ++void         gst_player_play_sync (GstPlayer * player, gint time_out);
> ++void         gst_player_stop_sync (GstPlayer * player, gint time_out);
> ++void         gst_player_pause_sync (GstPlayer * player, gint time_out);
> ++
> + G_END_DECLS
> +
> + #endif /* __GST_PLAYER_H__ */
> +--
> +1.9.1
> +
> diff --git a/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad/0018-Add-imx-physical-memory-allocator.patch b/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad/0018-Add-imx-physical-memory-allocator.patch
> new file mode 100644
> index 00000000..22b62661
> --- /dev/null
> +++ b/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad/0018-Add-imx-physical-memory-allocator.patch
> @@ -0,0 +1,443 @@
> +From 09c72d6fcdee9b1d529db187047085653d264da4 Mon Sep 17 00:00:00 2001
> +From: Haihua Hu <jared.hu at nxp.com>
> +Date: Thu, 18 May 2017 16:43:40 +0800
> +Subject: [PATCH 18/26] Add imx physical memory allocator
> +
> +Upstream-Status: Inappropriate [i.MX specific]
> +
> +Signed-off-by: Haihua Hu <jared.hu at nxp.com>
> +---
> + gst-libs/gst/allocators/Makefile.am          |   6 +-
> + gst-libs/gst/allocators/badallocators.h      |   1 +
> + gst-libs/gst/allocators/gstallocatorphymem.c | 314 +++++++++++++++++++++++++++
> + gst-libs/gst/allocators/gstallocatorphymem.h |  64 ++++++
> + 4 files changed, 383 insertions(+), 2 deletions(-)
> + create mode 100755 gst-libs/gst/allocators/gstallocatorphymem.c
> + create mode 100755 gst-libs/gst/allocators/gstallocatorphymem.h
> +
> +diff --git a/gst-libs/gst/allocators/Makefile.am b/gst-libs/gst/allocators/Makefile.am
> +index e50d077..46c75c0 100644
> +--- a/gst-libs/gst/allocators/Makefile.am
> ++++ b/gst-libs/gst/allocators/Makefile.am
> +@@ -4,12 +4,14 @@ libgstbadallocators_ at GST_API_VERSION@_includedir = $(includedir)/gstreamer- at GST_
> +
> + libgstbadallocators_ at GST_API_VERSION@_include_HEADERS = \
> +       badallocators.h \
> +-      gstphysmemory.h
> ++      gstphysmemory.h \
> ++      gstallocatorphymem.h
> +
> + noinst_HEADERS =
> +
> + libgstbadallocators_ at GST_API_VERSION@_la_SOURCES = \
> +-      gstphysmemory.c
> ++      gstphysmemory.c \
> ++      gstallocatorphymem.c
> +
> + libgstbadallocators_ at GST_API_VERSION@_la_LIBADD = $(GST_LIBS) $(LIBM)
> + libgstbadallocators_ at GST_API_VERSION@_la_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_CFLAGS)
> +diff --git a/gst-libs/gst/allocators/badallocators.h b/gst-libs/gst/allocators/badallocators.h
> +index 4e18215..2c143f4 100644
> +--- a/gst-libs/gst/allocators/badallocators.h
> ++++ b/gst-libs/gst/allocators/badallocators.h
> +@@ -23,6 +23,7 @@
> + #define __GST_ALLOCATORS_BAD_H__
> +
> + #include <gst/allocators/gstphysmemory.h>
> ++#include <gst/allocators/gstallocatorphymem.h>
> +
> + #endif /* __GST_ALLOCATORS_BAD_H__ */
> +
> +diff --git a/gst-libs/gst/allocators/gstallocatorphymem.c b/gst-libs/gst/allocators/gstallocatorphymem.c
> +new file mode 100755
> +index 0000000..cf5995e
> +--- /dev/null
> ++++ b/gst-libs/gst/allocators/gstallocatorphymem.c
> +@@ -0,0 +1,314 @@
> ++/*
> ++ * Copyright (c) 2013-2015, Freescale Semiconductor, Inc. All rights reserved.
> ++ *
> ++ * This library is free software; you can redistribute it and/or
> ++ * modify it under the terms of the GNU Library General Public
> ++ * License as published by the Free Software Foundation; either
> ++ * version 2 of the License, or (at your option) any later version.
> ++ *
> ++ * This library is distributed in the hope that it will be useful,
> ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
> ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> ++ * Library General Public License for more details.
> ++ *
> ++ * You should have received a copy of the GNU Library General Public
> ++ * License along with this library; if not, write to the
> ++ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
> ++ * Boston, MA 02111-1307, USA.
> ++ */
> ++
> ++#include <stdio.h>
> ++#include <string.h>
> ++#include "gstallocatorphymem.h"
> ++
> ++typedef struct {
> ++  GstMemory mem;
> ++  guint8 *vaddr;
> ++  guint8 *paddr;
> ++  PhyMemBlock block;
> ++} GstMemoryPhy;
> ++
> ++static int
> ++default_copy (GstAllocatorPhyMem *allocator, PhyMemBlock *dst_mem,
> ++              PhyMemBlock *src_mem, guint offset, guint size)
> ++{
> ++  GST_WARNING ("No default copy implementation for physical memory allocator.\n");
> ++  return -1;
> ++}
> ++
> ++static gpointer
> ++gst_phymem_map (GstMemory * mem, gsize maxsize, GstMapFlags flags)
> ++{
> ++  GstMemoryPhy *phymem = (GstMemoryPhy*) mem;
> ++
> ++  if (GST_MEMORY_IS_READONLY(mem) && (flags & GST_MAP_WRITE)) {
> ++    GST_ERROR("memory is read only");
> ++    return NULL;
> ++  }
> ++
> ++  return phymem->vaddr;
> ++}
> ++
> ++static void
> ++gst_phymem_unmap (GstMemory * mem)
> ++{
> ++  return;
> ++}
> ++
> ++static GstMemory *
> ++gst_phymem_copy (GstMemory * mem, gssize offset, gssize size)
> ++{
> ++  GstAllocatorPhyMemClass *klass;
> ++  GstMemoryPhy *src_mem = (GstMemoryPhy *)mem;
> ++
> ++  GstMemoryPhy *dst_mem = g_slice_alloc(sizeof(GstMemoryPhy));
> ++  if(dst_mem == NULL) {
> ++    GST_ERROR("Can't allocate for GstMemoryPhy structure.\n");
> ++    return NULL;
> ++  }
> ++
> ++  klass = GST_ALLOCATOR_PHYMEM_CLASS(G_OBJECT_GET_CLASS(mem->allocator));
> ++  if(klass == NULL) {
> ++    GST_ERROR("Can't get class from allocator object.\n");
> ++    return NULL;
> ++  }
> ++
> ++  if(klass->copy_phymem((GstAllocatorPhyMem*)mem->allocator,
> ++                         &dst_mem->block, &src_mem->block, offset, size) < 0) {
> ++    GST_WARNING ("Copy phymem %d failed.\n", size);
> ++    return NULL;
> ++  }
> ++
> ++  GST_DEBUG ("copied phymem, vaddr(%p), paddr(%p), size(%d).\n",
> ++      dst_mem->block.vaddr, dst_mem->block.paddr, dst_mem->block.size);
> ++
> ++  dst_mem->vaddr = dst_mem->block.vaddr;
> ++  dst_mem->paddr = dst_mem->block.paddr;
> ++
> ++  gst_memory_init (GST_MEMORY_CAST (dst_mem),
> ++                   mem->mini_object.flags&(~GST_MEMORY_FLAG_READONLY),
> ++                   mem->allocator, NULL, mem->maxsize, mem->align,
> ++                   mem->offset, mem->size);
> ++
> ++  return (GstMemory*)dst_mem;
> ++}
> ++
> ++static GstMemory *
> ++gst_phymem_share (GstMemory * mem, gssize offset, gssize size)
> ++{
> ++  GST_ERROR("Not implemented mem_share in gstallocatorphymem.\n");
> ++  return NULL;
> ++}
> ++
> ++static gboolean
> ++gst_phymem_is_span (GstMemory * mem1, GstMemory * mem2, gsize * offset)
> ++{
> ++  return FALSE;
> ++}
> ++
> ++static gpointer
> ++gst_phymem_get_phy (GstMemory * mem)
> ++{
> ++  GstMemoryPhy *phymem = (GstMemoryPhy*) mem;
> ++
> ++  return phymem->paddr;
> ++}
> ++
> ++static GstMemory *
> ++base_alloc (GstAllocator * allocator, gsize size,
> ++    GstAllocationParams * params)
> ++{
> ++  GstAllocatorPhyMemClass *klass;
> ++  GstMemoryPhy *mem;
> ++  gsize maxsize, aoffset, offset, align, padding;
> ++  guint8 *data;
> ++
> ++  mem = g_slice_alloc(sizeof(GstMemoryPhy));
> ++  if(mem == NULL) {
> ++    GST_ERROR("Can allocate for GstMemoryPhy structure.\n");
> ++    return NULL;
> ++  }
> ++
> ++  klass = GST_ALLOCATOR_PHYMEM_CLASS(G_OBJECT_GET_CLASS(allocator));
> ++  if(klass == NULL) {
> ++    GST_ERROR("Can't get class from allocator object.\n");
> ++    return NULL;
> ++  }
> ++
> ++  GST_DEBUG ("allocate params, prefix (%d), padding (%d), align (%d), flags (%x).\n",
> ++      params->prefix, params->padding, params->align, params->flags);
> ++
> ++  maxsize = size + params->prefix + params->padding;
> ++  mem->block.size = maxsize;
> ++  if(klass->alloc_phymem((GstAllocatorPhyMem*)allocator, &mem->block) < 0) {
> ++    GST_ERROR("Allocate phymem %d failed.\n", maxsize);
> ++    return NULL;
> ++  }
> ++
> ++  GST_DEBUG ("allocated phymem, vaddr(%p), paddr(%p), size(%d).\n",
> ++      mem->block.vaddr, mem->block.paddr, mem->block.size);
> ++
> ++  data = mem->block.vaddr;
> ++  offset = params->prefix;
> ++  align = params->align;
> ++  /* do alignment */
> ++  if ((aoffset = ((guintptr)data & align))) {
> ++    aoffset = (align + 1) - aoffset;
> ++    data += aoffset;
> ++    maxsize -= aoffset;
> ++  }
> ++  mem->vaddr = mem->block.vaddr + aoffset;
> ++  mem->paddr = mem->block.paddr + aoffset;
> ++
> ++  GST_DEBUG ("aligned vaddr(%p), paddr(%p), size(%d).\n",
> ++      mem->block.vaddr, mem->block.paddr, mem->block.size);
> ++
> ++  if (offset && (params->flags & GST_MEMORY_FLAG_ZERO_PREFIXED))
> ++    memset (data, 0, offset);
> ++
> ++  padding = maxsize - (offset + size);
> ++  if (padding && (params->flags & GST_MEMORY_FLAG_ZERO_PADDED))
> ++    memset (data + offset + size, 0, padding);
> ++
> ++  gst_memory_init (GST_MEMORY_CAST (mem), params->flags, allocator, NULL, maxsize, align, offset, size);
> ++
> ++  return (GstMemory*)mem;
> ++}
> ++
> ++static void
> ++base_free (GstAllocator * allocator, GstMemory * mem)
> ++{
> ++  GstAllocatorPhyMemClass *klass;
> ++  GstMemoryPhy *phymem;
> ++
> ++  klass = GST_ALLOCATOR_PHYMEM_CLASS(G_OBJECT_GET_CLASS(allocator));
> ++  if(klass == NULL) {
> ++    GST_ERROR("Can't get class from allocator object, can't free %p\n", mem);
> ++    return;
> ++  }
> ++
> ++  phymem = (GstMemoryPhy*)mem;
> ++
> ++  GST_DEBUG ("free phymem, vaddr(%p), paddr(%p), size(%d).\n",
> ++      phymem->block.vaddr, phymem->block.paddr, phymem->block.size);
> ++
> ++  klass->free_phymem((GstAllocatorPhyMem*)allocator, &phymem->block);
> ++  g_slice_free1(sizeof(GstMemoryPhy), mem);
> ++
> ++  return;
> ++}
> ++
> ++static int
> ++default_alloc (GstAllocatorPhyMem *allocator, PhyMemBlock *phy_mem)
> ++{
> ++  GST_ERROR ("No default allocating implementation for physical memory allocation.\n");
> ++  return -1;
> ++}
> ++
> ++static int
> ++default_free (GstAllocatorPhyMem *allocator, PhyMemBlock *phy_mem)
> ++{
> ++  GST_ERROR ("No default free implementation for physical memory allocation.\n");
> ++  return -1;
> ++}
> ++
> ++G_DEFINE_TYPE (GstAllocatorPhyMem, gst_allocator_phymem, GST_TYPE_ALLOCATOR);
> ++
> ++static void
> ++gst_allocator_phymem_class_init (GstAllocatorPhyMemClass * klass)
> ++{
> ++  GstAllocatorClass *allocator_class;
> ++
> ++  allocator_class = (GstAllocatorClass *) klass;
> ++
> ++  allocator_class->alloc = base_alloc;
> ++  allocator_class->free = base_free;
> ++  klass->alloc_phymem = default_alloc;
> ++  klass->free_phymem = default_free;
> ++  klass->copy_phymem = default_copy;
> ++}
> ++
> ++static void
> ++gst_allocator_phymem_init (GstAllocatorPhyMem * allocator)
> ++{
> ++  GstAllocator *alloc = GST_ALLOCATOR_CAST (allocator);
> ++
> ++  alloc->mem_map =  gst_phymem_map;
> ++  alloc->mem_unmap =  gst_phymem_unmap;
> ++  alloc->mem_copy =  gst_phymem_copy;
> ++  alloc->mem_share =  gst_phymem_share;
> ++  alloc->mem_is_span =  gst_phymem_is_span;
> ++}
> ++
> ++
> ++//global functions
> ++
> ++gboolean
> ++gst_buffer_is_phymem (GstBuffer *buffer)
> ++{
> ++  gboolean ret = FALSE;
> ++  PhyMemBlock * memblk;
> ++  GstMemory *mem = gst_buffer_get_memory (buffer, 0);
> ++  if(mem == NULL) {
> ++    GST_ERROR ("Not get memory from buffer.\n");
> ++    return FALSE;
> ++  }
> ++
> ++  if(GST_IS_ALLOCATOR_PHYMEM(mem->allocator)) {
> ++    if (NULL == ((GstMemoryPhy*)mem)->block.paddr) {
> ++      GST_WARNING("physical address in memory block is invalid");
> ++      ret = FALSE;
> ++    } else {
> ++      ret = TRUE;
> ++    }
> ++  }
> ++
> ++  gst_memory_unref (mem);
> ++
> ++  return ret;
> ++}
> ++
> ++PhyMemBlock *
> ++gst_buffer_query_phymem_block (GstBuffer *buffer)
> ++{
> ++  GstMemory *mem;
> ++  GstMemoryPhy *memphy;
> ++  PhyMemBlock *memblk;
> ++
> ++  mem = gst_buffer_get_memory (buffer, 0);
> ++  if(mem == NULL) {
> ++    GST_ERROR ("Not get memory from buffer.\n");
> ++    return NULL;
> ++  }
> ++
> ++  if(!GST_IS_ALLOCATOR_PHYMEM(mem->allocator)) {
> ++    gst_memory_unref (mem);
> ++    return NULL;
> ++  }
> ++
> ++  memphy = (GstMemoryPhy*) mem;
> ++  memblk = &memphy->block;
> ++
> ++  gst_memory_unref (mem);
> ++
> ++  return memblk;
> ++}
> ++
> ++PhyMemBlock *
> ++gst_memory_query_phymem_block (GstMemory *mem)
> ++{
> ++  GstMemoryPhy *memphy;
> ++  PhyMemBlock *memblk;
> ++
> ++  if (!mem)
> ++    return NULL;
> ++
> ++  if (!GST_IS_ALLOCATOR_PHYMEM(mem->allocator))
> ++    return NULL;
> ++
> ++  memphy = (GstMemoryPhy*) mem;
> ++  memblk = &memphy->block;
> ++
> ++  return memblk;
> ++}
> ++
> +diff --git a/gst-libs/gst/allocators/gstallocatorphymem.h b/gst-libs/gst/allocators/gstallocatorphymem.h
> +new file mode 100755
> +index 0000000..f0833ae
> +--- /dev/null
> ++++ b/gst-libs/gst/allocators/gstallocatorphymem.h
> +@@ -0,0 +1,64 @@
> ++/*
> ++ * Copyright (c) 2013-2015, Freescale Semiconductor, Inc. All rights reserved.
> ++ *
> ++ * This library is free software; you can redistribute it and/or
> ++ * modify it under the terms of the GNU Library General Public
> ++ * License as published by the Free Software Foundation; either
> ++ * version 2 of the License, or (at your option) any later version.
> ++ *
> ++ * This library is distributed in the hope that it will be useful,
> ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
> ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> ++ * Library General Public License for more details.
> ++ *
> ++ * You should have received a copy of the GNU Library General Public
> ++ * License along with this library; if not, write to the
> ++ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
> ++ * Boston, MA 02111-1307, USA.
> ++ */
> ++
> ++#ifndef __ALLOCATOR_PHYMEM_H__
> ++#define __ALLOCATOR_PHYMEM_H__
> ++
> ++#include <gst/gst.h>
> ++#include <gst/gstallocator.h>
> ++
> ++#define PAGE_ALIGN(x) (((x) + 4095) & ~4095)
> ++
> ++#define GST_TYPE_ALLOCATOR_PHYMEM             (gst_allocator_phymem_get_type())
> ++#define GST_ALLOCATOR_PHYMEM(obj)             (G_TYPE_CHECK_INSTANCE_CAST((obj), GST_TYPE_ALLOCATOR_PHYMEM, GstAllocatorPhyMem))
> ++#define GST_ALLOCATOR_PHYMEM_CLASS(klass)     (G_TYPE_CHECK_CLASS_CAST((klass), GST_TYPE_ALLOCATOR_PHYMEM, GstAllocatorPhyMemClass))
> ++#define GST_IS_ALLOCATOR_PHYMEM(obj)          (G_TYPE_CHECK_INSTANCE_TYPE((obj), GST_TYPE_ALLOCATOR_PHYMEM))
> ++#define GST_IS_ALLOCATOR_PHYMEM_CLASS(klass)  (G_TYPE_CHECK_CLASS_TYPE((klass), GST_TYPE_ALLOCATOR_PHYMEM))
> ++
> ++typedef struct _GstAllocatorPhyMem GstAllocatorPhyMem;
> ++typedef struct _GstAllocatorPhyMemClass GstAllocatorPhyMemClass;
> ++
> ++/* also change gst-libs/gst/gl/gstglvivdirecttexture.c in gst-plugins-bad git
> ++ * if changed below structure */
> ++typedef struct {
> ++  guint8 *vaddr;
> ++  guint8 *paddr;
> ++  guint8 *caddr;
> ++  gsize size;
> ++  gpointer *user_data;
> ++} PhyMemBlock;
> ++
> ++struct _GstAllocatorPhyMem {
> ++  GstAllocator parent;
> ++};
> ++
> ++struct _GstAllocatorPhyMemClass {
> ++  GstAllocatorClass parent_class;
> ++  int (*alloc_phymem) (GstAllocatorPhyMem *allocator, PhyMemBlock *phy_mem);
> ++  int (*free_phymem) (GstAllocatorPhyMem *allocator, PhyMemBlock *phy_mem);
> ++  int (*copy_phymem) (GstAllocatorPhyMem *allocator, PhyMemBlock *det_mem,
> ++                      PhyMemBlock *src_mem, guint offset, guint size);
> ++};
> ++
> ++GType gst_allocator_phymem_get_type (void);
> ++gboolean gst_buffer_is_phymem (GstBuffer *buffer);
> ++PhyMemBlock *gst_buffer_query_phymem_block (GstBuffer *buffer);
> ++PhyMemBlock *gst_memory_query_phymem_block (GstMemory *mem);
> ++
> ++#endif
> +--
> +1.9.1
> +
> diff --git a/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad/0019-Add-implement-of-interface-get_phys_addr-to-support-.patch b/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad/0019-Add-implement-of-interface-get_phys_addr-to-support-.patch
> new file mode 100644
> index 00000000..2aead8d3
> --- /dev/null
> +++ b/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad/0019-Add-implement-of-interface-get_phys_addr-to-support-.patch
> @@ -0,0 +1,48 @@
> +From ccbb5a40d9260e63fbf87c737adb05102c82fbb3 Mon Sep 17 00:00:00 2001
> +From: Haihua Hu <jared.hu at nxp.com>
> +Date: Mon, 22 May 2017 13:38:05 +0800
> +Subject: [PATCH 19/26] Add implement of interface "get_phys_addr" to support
> + directviv upload
> +
> +Upstream-Status: Inappropriate [i.MX specific]
> +---
> + gst-libs/gst/allocators/gstallocatorphymem.c | 16 +++++++++++++++-
> + 1 file changed, 15 insertions(+), 1 deletion(-)
> +
> +diff --git a/gst-libs/gst/allocators/gstallocatorphymem.c b/gst-libs/gst/allocators/gstallocatorphymem.c
> +index cf5995e..d128b83 100755
> +--- a/gst-libs/gst/allocators/gstallocatorphymem.c
> ++++ b/gst-libs/gst/allocators/gstallocatorphymem.c
> +@@ -20,6 +20,7 @@
> + #include <stdio.h>
> + #include <string.h>
> + #include "gstallocatorphymem.h"
> ++#include "gstphysmemory.h"
> +
> + typedef struct {
> +   GstMemory mem;
> +@@ -212,7 +213,20 @@ default_free (GstAllocatorPhyMem *allocator, PhyMemBlock *phy_mem)
> +   return -1;
> + }
> +
> +-G_DEFINE_TYPE (GstAllocatorPhyMem, gst_allocator_phymem, GST_TYPE_ALLOCATOR);
> ++static guintptr
> ++gst_allocator_phymem_get_phys_addr (GstPhysMemoryAllocator *allocator, GstMemory *mem)
> ++{
> ++  return gst_phymem_get_phy (mem);
> ++}
> ++
> ++static void gst_allocator_phymem_iface_init(gpointer g_iface)
> ++{
> ++  GstPhysMemoryAllocatorInterface *iface = g_iface;
> ++  iface->get_phys_addr = gst_allocator_phymem_get_phys_addr;
> ++}
> ++
> ++G_DEFINE_TYPE_WITH_CODE (GstAllocatorPhyMem, gst_allocator_phymem, GST_TYPE_ALLOCATOR,
> ++    G_IMPLEMENT_INTERFACE(GST_TYPE_PHYS_MEMORY_ALLOCATOR, gst_allocator_phymem_iface_init));
> +
> + static void
> + gst_allocator_phymem_class_init (GstAllocatorPhyMemClass * klass)
> +--
> +1.9.1
> +
> diff --git a/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad/0020-Accelerate-gldownload-with-directviv.patch b/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad/0020-Accelerate-gldownload-with-directviv.patch
> new file mode 100644
> index 00000000..b242ec34
> --- /dev/null
> +++ b/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad/0020-Accelerate-gldownload-with-directviv.patch
> @@ -0,0 +1,698 @@
> +From 80d15dc6e8484bb65cbcc994ab5cae8f4860094d Mon Sep 17 00:00:00 2001
> +From: Haihua Hu <jared.hu at nxp.com>
> +Date: Tue, 16 May 2017 14:20:42 +0800
> +Subject: [PATCH] Accelerate gldownload with directviv
> +
> +1.Propose a physical buffer pool to upstream in gldownload
> +2.Bind the physical buffer with texture via dirctviv
> +3.In gldownload, wrap the physical buffer to gstbuffer, pass to
> +  downstream plugins.
> +4.Add some configure check for g2d and phymem
> +
> +Upstream-Status: Inappropriate [i.MX specific]
> +
> +Signed-off-by: Haihua Hu <jared.hu at nxp.com>
> +---
> + configure.ac                      |  14 ++
> + ext/gl/gstgldownloadelement.c     |  99 +++++++++++
> + gst-libs/gst/gl/Makefile.am       |   6 +
> + gst-libs/gst/gl/gstglbufferpool.c |  21 ++-
> + gst-libs/gst/gl/gstglphymemory.c  | 363 ++++++++++++++++++++++++++++++++++++++
> + gst-libs/gst/gl/gstglphymemory.h  |  44 +++++
> + 6 files changed, 546 insertions(+), 1 deletion(-)
> + create mode 100644 gst-libs/gst/gl/gstglphymemory.c
> + create mode 100644 gst-libs/gst/gl/gstglphymemory.h
> +
> +diff --git a/configure.ac b/configure.ac
> +index 8a05495..d7a2a46 100644
> +--- a/configure.ac
> ++++ b/configure.ac
> +@@ -871,6 +871,17 @@ if test "x$HAVE_VIV_DIRECTVIV" = "xyes"; then
> +           GST_GL_HAVE_VIV_DIRECTVIV=1
> + fi
> +
> ++dnl check imx6 g2d support
> ++HAVE_G2D=no
> ++AC_CHECK_HEADER(g2d.h, HAVE_G2D=yes, HAVE_G2D=no)
> ++
> ++GST_GL_HAVE_PHYMEM=0
> ++if test "x$HAVE_G2D" = "xyes" -a "x$HAVE_VIV_DIRECTVIV" = "xyes"; then
> ++  GST_GL_HAVE_PHYMEM=1
> ++else
> ++  AC_MSG_WARN([Physical memory do not support])
> ++fi
> ++
> + dnl check if we can include both GL and GLES2 at the same time
> + if test "x$HAVE_GL" = "xyes" -a "x$HAVE_GLES2" = "xyes"; then
> +   GLES3_H_DEFINE=0
> +@@ -1291,6 +1302,7 @@ GL_CONFIG_DEFINES="$GL_CONFIG_DEFINES
> + GL_CONFIG_DEFINES="$GL_CONFIG_DEFINES
> + #define GST_GL_HAVE_DMABUF $GST_GL_HAVE_DMABUF
> + #define GST_GL_HAVE_VIV_DIRECTVIV $GST_GL_HAVE_VIV_DIRECTVIV
> ++#define GST_GL_HAVE_PHYMEM $GST_GL_HAVE_PHYMEM
> + "
> +
> + dnl Check for no platforms/window systems
> +@@ -1326,6 +1338,7 @@ if test "x$GL_APIS" = "x" -o "x$GL_PLATFORMS" = "x" -o "x$GL_WINDOWS" = "x"; the
> +   HAVE_WINDOW_COCOA=no
> +   HAVE_WINDOW_EAGL=no
> +   HAVE_WINDOW_VIV_FB=no
> ++  HAVE_G2D=no
> + fi
> +
> + AC_SUBST(GL_APIS)
> +@@ -1345,6 +1358,7 @@ AM_CONDITIONAL(HAVE_WINDOW_WAYLAND, test "x$HAVE_WINDOW_WAYLAND" = "xyes")
> + AM_CONDITIONAL(HAVE_WINDOW_ANDROID, test "x$HAVE_WINDOW_ANDROID" = "xyes")
> + AM_CONDITIONAL(HAVE_WINDOW_EAGL, test "x$HAVE_WINDOW_EAGL" = "xyes")
> + AM_CONDITIONAL(HAVE_WINDOW_VIV_FB, test "x$HAVE_WINDOW_VIV_FB" = "xyes")
> ++AM_CONDITIONAL(HAVE_GL_PHYMEM, test "x$HAVE_G2D" = "xyes" -a "x$HAVE_VIV_DIRECTVIV" = "xyes")
> +
> + AM_CONDITIONAL(USE_OPENGL, test "x$USE_OPENGL" = "xyes")
> + AM_CONDITIONAL(USE_GLES2, test "x$USE_GLES2" = "xyes")
> +diff --git a/ext/gl/gstgldownloadelement.c b/ext/gl/gstgldownloadelement.c
> +index 36821df..03f4479 100644
> +--- a/ext/gl/gstgldownloadelement.c
> ++++ b/ext/gl/gstgldownloadelement.c
> +@@ -25,6 +25,10 @@
> + #include <gst/gl/gl.h>
> + #include "gstgldownloadelement.h"
> +
> ++#if GST_GL_HAVE_PHYMEM
> ++#include <gst/gl/gstglphymemory.h>
> ++#endif
> ++
> + GST_DEBUG_CATEGORY_STATIC (gst_gl_download_element_debug);
> + #define GST_CAT_DEFAULT gst_gl_download_element_debug
> +
> +@@ -45,6 +49,8 @@ gst_gl_download_element_prepare_output_buffer (GstBaseTransform * bt,
> +     GstBuffer * buffer, GstBuffer ** outbuf);
> + static GstFlowReturn gst_gl_download_element_transform (GstBaseTransform * bt,
> +     GstBuffer * buffer, GstBuffer * outbuf);
> ++static gboolean gst_gl_download_element_propose_allocation (GstBaseTransform *
> ++    bt, GstQuery * decide_query, GstQuery * query);
> +
> + static GstStaticPadTemplate gst_gl_download_element_src_pad_template =
> +     GST_STATIC_PAD_TEMPLATE ("src",
> +@@ -70,6 +76,7 @@ gst_gl_download_element_class_init (GstGLDownloadElementClass * klass)
> +   bt_class->prepare_output_buffer =
> +       gst_gl_download_element_prepare_output_buffer;
> +   bt_class->transform = gst_gl_download_element_transform;
> ++  bt_class->propose_allocation = gst_gl_download_element_propose_allocation;
> +
> +   bt_class->passthrough_on_same_caps = TRUE;
> +
> +@@ -160,9 +167,26 @@ static GstFlowReturn
> + gst_gl_download_element_prepare_output_buffer (GstBaseTransform * bt,
> +     GstBuffer * inbuf, GstBuffer ** outbuf)
> + {
> ++  GstGLDownloadElement *download = GST_GL_DOWNLOAD_ELEMENT (bt);
> +   GstCaps *src_caps = gst_pad_get_current_caps (bt->srcpad);
> +   GstCapsFeatures *features = NULL;
> +   gint i, n;
> ++  GstGLMemory *glmem;
> ++
> ++#if GST_GL_HAVE_PHYMEM
> ++  glmem = gst_buffer_peek_memory (inbuf, 0);
> ++  if (gst_is_gl_physical_memory (glmem)) {
> ++    GstGLContext *context = GST_GL_BASE_FILTER (bt)->context;
> ++    GstVideoInfo info;
> ++
> ++    gst_video_info_from_caps (&info, src_caps);
> ++    *outbuf = gst_gl_phymem_buffer_to_gstbuffer (context, &info, inbuf);
> ++
> ++    GST_DEBUG_OBJECT (download, "gl download with direct viv.");
> ++
> ++    return GST_FLOW_OK;
> ++  }
> ++#endif /* GST_GL_HAVE_PHYMEM */
> +
> +   *outbuf = inbuf;
> +
> +@@ -194,3 +218,78 @@ gst_gl_download_element_transform (GstBaseTransform * bt,
> + {
> +   return GST_FLOW_OK;
> + }
> ++
> ++static gboolean
> ++gst_gl_download_element_propose_allocation (GstBaseTransform * bt,
> ++    GstQuery * decide_query, GstQuery * query)
> ++{
> ++  GstGLContext *context = GST_GL_BASE_FILTER (bt)->context;
> ++  GstGLDownloadElement *download = GST_GL_DOWNLOAD_ELEMENT (bt);
> ++  GstAllocationParams params;
> ++  GstAllocator *allocator = NULL;
> ++  GstBufferPool *pool = NULL;
> ++  guint n_pools, i;
> ++  GstVideoInfo info;
> ++  GstCaps *caps;
> ++  GstStructure *config;
> ++  gsize size;
> ++
> ++  gst_query_parse_allocation (query, &caps, NULL);
> ++  if (!gst_video_info_from_caps (&info, caps)) {
> ++    GST_WARNING_OBJECT (bt, "invalid caps specified");
> ++    return FALSE;
> ++  }
> ++
> ++  GST_DEBUG_OBJECT (bt, "video format is %s", gst_video_format_to_string (GST_VIDEO_INFO_FORMAT (&info)));
> ++
> ++  gst_allocation_params_init (&params);
> ++
> ++#if GST_GL_HAVE_PHYMEM
> ++  if (gst_is_gl_physical_memory_supported_fmt (&info)) {
> ++    allocator = gst_phy_mem_allocator_obtain ();
> ++    GST_DEBUG_OBJECT (bt, "obtain physical memory allocator %p.", allocator);
> ++  }
> ++#endif /* GST_GL_HAVE_PHYMEM */
> ++
> ++  if (!allocator)
> ++    allocator = gst_allocator_find (GST_GL_MEMORY_ALLOCATOR_NAME);
> ++
> ++  if (!allocator) {
> ++    GST_ERROR_OBJECT (bt, "Can't obtain gl memory allocator.");
> ++    return FALSE;
> ++  }
> ++
> ++  gst_query_add_allocation_param (query, allocator, &params);
> ++  gst_object_unref (allocator);
> ++
> ++  n_pools = gst_query_get_n_allocation_pools (query);
> ++  for (i = 0; i < n_pools; i++) {
> ++    gst_query_parse_nth_allocation_pool (query, i, &pool, NULL, NULL, NULL);
> ++    gst_object_unref (pool);
> ++    pool = NULL;
> ++  }
> ++
> ++  //new buffer pool
> ++  pool = gst_gl_buffer_pool_new (context);
> ++  config = gst_buffer_pool_get_config (pool);
> ++
> ++  /* the normal size of a frame */
> ++  size = info.size;
> ++  gst_buffer_pool_config_set_params (config, caps, size, 0, 0);
> ++  gst_buffer_pool_config_add_option (config, GST_BUFFER_POOL_OPTION_GL_SYNC_META);
> ++
> ++  if (!gst_buffer_pool_set_config (pool, config)) {
> ++    gst_object_unref (pool);
> ++    GST_WARNING_OBJECT (bt, "failed setting config");
> ++    return FALSE;
> ++  }
> ++
> ++  GST_DEBUG_OBJECT (download, "create pool %p", pool);
> ++
> ++  //propose 3 buffers for better performance
> ++  gst_query_add_allocation_pool (query, pool, size, 3, 0);
> ++
> ++  gst_object_unref (pool);
> ++
> ++  return TRUE;
> ++}
> +diff --git a/gst-libs/gst/gl/Makefile.am b/gst-libs/gst/gl/Makefile.am
> +index 2ae4773..e97a386 100644
> +--- a/gst-libs/gst/gl/Makefile.am
> ++++ b/gst-libs/gst/gl/Makefile.am
> +@@ -131,6 +131,12 @@ libgstgl_ at GST_API_VERSION@_la_LIBADD += egl/libgstgl-egl.la
> + libgstgl_ at GST_API_VERSION@_la_LIBADD += -lgstallocators-$(GST_API_VERSION)
> + endif
> +
> ++if HAVE_GL_PHYMEM
> ++libgstgl_ at GST_API_VERSION@_la_SOURCES += gstglphymemory.c
> ++libgstgl_ at GST_API_VERSION@include_HEADERS += gstglphymemory.h
> ++libgstgl_ at GST_API_VERSION@_la_LIBADD += -lg2d
> ++endif
> ++
> + configexecincludedir = $(libdir)/gstreamer- at GST_API_VERSION@/include/gst/gl
> + nodist_configexecinclude_HEADERS = $(built_sys_header_configure)
> +
> +diff --git a/gst-libs/gst/gl/gstglbufferpool.c b/gst-libs/gst/gl/gstglbufferpool.c
> +index e886557..e8bde19 100644
> +--- a/gst-libs/gst/gl/gstglbufferpool.c
> ++++ b/gst-libs/gst/gl/gstglbufferpool.c
> +@@ -26,6 +26,10 @@
> + #include "gstglbufferpool.h"
> + #include "gstglutils.h"
> +
> ++#if GST_GL_HAVE_PHYMEM
> ++#include <gst/gl/gstglphymemory.h>
> ++#endif
> ++
> + /**
> +  * SECTION:gstglbufferpool
> +  * @title: GstGlBufferPool
> +@@ -117,7 +121,11 @@ gst_gl_buffer_pool_set_config (GstBufferPool * pool, GstStructure * config)
> +     gst_object_unref (priv->allocator);
> +
> +   if (allocator) {
> +-    if (!GST_IS_GL_MEMORY_ALLOCATOR (allocator)) {
> ++    if (!GST_IS_GL_MEMORY_ALLOCATOR (allocator)
> ++#if GST_GL_HAVE_PHYMEM
> ++        && (g_strcmp0 (allocator->mem_type, GST_GL_PHY_MEM_ALLOCATOR) != 0)
> ++#endif
> ++        ) {
> +       gst_object_unref (allocator);
> +       goto wrong_allocator;
> +     } else {
> +@@ -274,10 +282,21 @@ gst_gl_buffer_pool_alloc (GstBufferPool * pool, GstBuffer ** buffer,
> +     goto no_buffer;
> +   }
> +
> ++#if GST_GL_HAVE_PHYMEM
> ++  if ((g_strcmp0 (priv->allocator->mem_type, GST_GL_PHY_MEM_ALLOCATOR) == 0)) {
> ++    if (!gst_gl_physical_memory_setup_buffer (priv->allocator, buf, priv->gl_params)) {
> ++      GST_ERROR_OBJECT (pool, "Can't create physcial buffer.");
> ++      return GST_FLOW_ERROR;
> ++    }
> ++    goto done;
> ++  }
> ++#endif
> ++
> +   alloc = GST_GL_MEMORY_ALLOCATOR (priv->allocator);
> +   if (!gst_gl_memory_setup_buffer (alloc, buf, priv->gl_params, NULL, NULL, 0))
> +     goto mem_create_failed;
> +
> ++done:
> +   if (priv->add_glsyncmeta)
> +     gst_buffer_add_gl_sync_meta (glpool->context, buf);
> +
> +diff --git a/gst-libs/gst/gl/gstglphymemory.c b/gst-libs/gst/gl/gstglphymemory.c
> +new file mode 100644
> +index 0000000..11e6c8e
> +--- /dev/null
> ++++ b/gst-libs/gst/gl/gstglphymemory.c
> +@@ -0,0 +1,363 @@
> ++/*
> ++ * GStreamer
> ++ * Copyright (c) 2015, Freescale Semiconductor, Inc.
> ++ * Copyright 2017 NXP
> ++ *
> ++ * This library is free software; you can redistribute it and/or
> ++ * modify it under the terms of the GNU Library General Public
> ++ * License as published by the Free Software Foundation; either
> ++ * version 2 of the License, or (at your option) any later version.
> ++ *
> ++ * This library is distributed in the hope that it will be useful,
> ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
> ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> ++ * Library General Public License for more details.
> ++ *
> ++ * You should have received a copy of the GNU Library General Public
> ++ * License along with this library; if not, write to the
> ++ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
> ++ * Boston, MA 02110-1301, USA.
> ++ */
> ++
> ++#ifdef HAVE_CONFIG_H
> ++#include "config.h"
> ++#endif
> ++
> ++#include "gstglphymemory.h"
> ++#include <g2d.h>
> ++
> ++GST_DEBUG_CATEGORY_STATIC (GST_CAT_GL_PHY_MEMORY);
> ++#define GST_CAT_DEFAULT GST_CAT_GL_PHY_MEMORY
> ++
> ++#ifndef GL_BGRA_EXT
> ++#define GL_BGRA_EXT                                             0x80E1
> ++#endif
> ++#ifndef GL_VIV_YV12
> ++#define GL_VIV_YV12                                             0x8FC0
> ++#endif
> ++#ifndef GL_VIV_NV12
> ++#define GL_VIV_NV12                                             0x8FC1
> ++#endif
> ++#ifndef GL_VIV_YUY2
> ++#define GL_VIV_YUY2                                             0x8FC2
> ++#endif
> ++#ifndef GL_VIV_UYVY
> ++#define GL_VIV_UYVY                                             0x8FC3
> ++#endif
> ++#ifndef GL_VIV_NV21
> ++#define GL_VIV_NV21                                             0x8FC4
> ++#endif
> ++#ifndef GL_VIV_I420
> ++#define GL_VIV_I420                                             0x8FC5
> ++#endif
> ++
> ++typedef void (*TexDirectVIVMap) (GLenum Target, GLsizei Width, GLsizei Height,
> ++    GLenum Format, GLvoid ** Logical, const GLuint * Physical);
> ++typedef void (*TexDirectInvalidateVIV) (GLenum Target);
> ++static TexDirectVIVMap pTexDirectVIVMap = NULL;
> ++static TexDirectInvalidateVIV pTexDirectInvalidateVIV = NULL;
> ++
> ++typedef struct {
> ++  guint tex_id;
> ++  guint w;
> ++  guint h;
> ++  guint fmt;
> ++  void *vaddr;
> ++  guint paddr;
> ++  gboolean ret;
> ++}DirectVIVData;
> ++
> ++typedef struct _GstPhyMemAllocator GstPhyMemAllocator;
> ++typedef struct _GstPhyMemAllocatorClass GstPhyMemAllocatorClass;
> ++
> ++struct _GstPhyMemAllocator
> ++{
> ++  GstAllocatorPhyMem parent;
> ++};
> ++
> ++struct _GstPhyMemAllocatorClass
> ++{
> ++  GstAllocatorPhyMemClass parent_class;
> ++};
> ++
> ++GType gst_phy_mem_allocator_get_type (void);
> ++G_DEFINE_TYPE (GstPhyMemAllocator, gst_phy_mem_allocator, GST_TYPE_ALLOCATOR_PHYMEM);
> ++
> ++static int
> ++alloc_phymem (GstAllocatorPhyMem *allocator, PhyMemBlock *memblk)
> ++{
> ++  struct g2d_buf *pbuf = NULL;
> ++
> ++  memblk->size = PAGE_ALIGN(memblk->size);
> ++
> ++  pbuf = g2d_alloc (memblk->size, 0);
> ++  if (!pbuf) {
> ++    GST_ERROR("G2D allocate %u bytes memory failed: %s",
> ++        memblk->size, strerror(errno));
> ++    return -1;
> ++  }
> ++
> ++  memblk->vaddr = (guchar*) pbuf->buf_vaddr;
> ++  memblk->paddr = (guchar*) pbuf->buf_paddr;
> ++  memblk->user_data = (gpointer) pbuf;
> ++  GST_DEBUG("G2D allocated memory (%p)", memblk->paddr);
> ++
> ++  return 1;
> ++}
> ++
> ++static int
> ++free_phymem (GstAllocatorPhyMem *allocator, PhyMemBlock *memblk)
> ++{
> ++  GST_DEBUG("G2D free memory (%p)", memblk->paddr);
> ++  gint ret = g2d_free ((struct g2d_buf*)(memblk->user_data));
> ++  memblk->user_data = NULL;
> ++  memblk->vaddr = NULL;
> ++  memblk->paddr = NULL;
> ++  memblk->size = 0;
> ++
> ++  return ret;
> ++}
> ++
> ++static void
> ++gst_phy_mem_allocator_class_init (GstPhyMemAllocatorClass * klass)
> ++{
> ++  GstAllocatorPhyMemClass *phy_allocator_klass = (GstAllocatorPhyMemClass *) klass;
> ++
> ++  phy_allocator_klass->alloc_phymem = alloc_phymem;
> ++  phy_allocator_klass->free_phymem = free_phymem;
> ++}
> ++
> ++static void
> ++gst_phy_mem_allocator_init (GstPhyMemAllocator * allocator)
> ++{
> ++  GstAllocator *alloc = GST_ALLOCATOR_CAST (allocator);
> ++
> ++  alloc->mem_type = GST_GL_PHY_MEM_ALLOCATOR;
> ++}
> ++
> ++
> ++static gpointer
> ++gst_phy_mem_allocator_init_instance (gpointer data)
> ++{
> ++  GstAllocator *allocator =
> ++      g_object_new (gst_phy_mem_allocator_get_type (), NULL);
> ++
> ++  GST_DEBUG_CATEGORY_INIT (GST_CAT_GL_PHY_MEMORY, "glphymemory", 0,
> ++      "GLPhysical Memory");
> ++
> ++  gst_allocator_register (GST_GL_PHY_MEM_ALLOCATOR, gst_object_ref (allocator));
> ++
> ++  return allocator;
> ++}
> ++
> ++static void
> ++_finish_texture (GstGLContext * ctx, gpointer *data)
> ++{
> ++  GstGLFuncs *gl = ctx->gl_vtable;
> ++
> ++  gl->Finish ();
> ++}
> ++
> ++static void
> ++_do_viv_direct_tex_bind_mem(GstGLContext * ctx, DirectVIVData *data)
> ++{
> ++  GstGLFuncs *gl = ctx->gl_vtable;
> ++
> ++  GST_DEBUG ("viv direct bind, tex_id %d, fmt: %d, res: (%dx%d)", data->tex_id, data->fmt, data->w, data->h);
> ++  GST_DEBUG ("Physical memory buffer, vaddr: %p, paddr: %p", data->vaddr, data->paddr);
> ++
> ++  gl->BindTexture (GL_TEXTURE_2D, data->tex_id);
> ++  pTexDirectVIVMap (GL_TEXTURE_2D, data->w, data->h, data->fmt, &data->vaddr, &data->paddr);
> ++  pTexDirectInvalidateVIV (GL_TEXTURE_2D);
> ++  data->ret = TRUE;
> ++}
> ++
> ++static GLenum
> ++_directviv_video_format_to_gl_format (GstVideoFormat format)
> ++{
> ++  switch (format) {
> ++    case GST_VIDEO_FORMAT_I420:
> ++      return GL_VIV_I420;
> ++    case GST_VIDEO_FORMAT_YV12:
> ++      return GL_VIV_YV12;
> ++    case GST_VIDEO_FORMAT_NV12:
> ++      return GL_VIV_NV12;
> ++    case GST_VIDEO_FORMAT_NV21:
> ++      return GL_VIV_NV21;
> ++    case GST_VIDEO_FORMAT_YUY2:
> ++      return GL_VIV_YUY2;
> ++    case GST_VIDEO_FORMAT_UYVY:
> ++      return GL_VIV_UYVY;
> ++    case GST_VIDEO_FORMAT_RGB16:
> ++      return GL_RGB565;
> ++    case GST_VIDEO_FORMAT_RGBA:
> ++      return GL_RGBA;
> ++    case GST_VIDEO_FORMAT_BGRA:
> ++      return GL_BGRA_EXT;
> ++    case GST_VIDEO_FORMAT_RGBx:
> ++      return GL_RGBA;
> ++    case GST_VIDEO_FORMAT_BGRx:
> ++      return GL_BGRA_EXT;
> ++    default:
> ++      return 0;
> ++  }
> ++}
> ++
> ++static void
> ++gst_gl_phy_mem_destroy (GstMemory *mem)
> ++{
> ++  gst_memory_unref (mem);
> ++}
> ++
> ++
> ++GstAllocator *
> ++gst_phy_mem_allocator_obtain (void)
> ++{
> ++  static GOnce once = G_ONCE_INIT;
> ++
> ++  g_once (&once, gst_phy_mem_allocator_init_instance, NULL);
> ++
> ++  g_return_val_if_fail (once.retval != NULL, NULL);
> ++
> ++  return (GstAllocator *) (g_object_ref (once.retval));
> ++}
> ++
> ++gboolean
> ++gst_is_gl_physical_memory (GstMemory * mem)
> ++{
> ++  GstGLBaseMemory *glmem;
> ++  g_return_val_if_fail (gst_is_gl_memory (mem), FALSE);
> ++
> ++  glmem = (GstGLBaseMemory*) mem;
> ++
> ++  if (glmem->user_data
> ++      && GST_IS_MINI_OBJECT_TYPE(glmem->user_data, GST_TYPE_MEMORY))
> ++    return gst_memory_is_type ((GstMemory*)glmem->user_data, GST_GL_PHY_MEM_ALLOCATOR);
> ++  else
> ++    return FALSE;
> ++}
> ++
> ++gboolean
> ++gst_is_gl_physical_memory_supported_fmt (GstVideoInfo * info)
> ++{
> ++  if (GST_VIDEO_INFO_IS_RGB(info)
> ++      && _directviv_video_format_to_gl_format (GST_VIDEO_INFO_FORMAT (info))) {
> ++    return TRUE;
> ++  }
> ++  else
> ++    return FALSE;
> ++}
> ++
> ++gboolean
> ++gst_gl_physical_memory_setup_buffer (GstAllocator * allocator, GstBuffer *buffer,
> ++    GstGLVideoAllocationParams * params)
> ++{
> ++  GstGLBaseMemoryAllocator *gl_alloc;
> ++  GstMemory *mem = NULL;
> ++  PhyMemBlock *memblk = NULL;
> ++  GstGLMemory *glmem = NULL;
> ++  gsize size;
> ++
> ++  GstVideoInfo * info = params->v_info;
> ++  GstVideoAlignment * valign = params->valign;
> ++
> ++  GST_DEBUG ("glphymemory setup buffer format %s", gst_video_format_to_string (GST_VIDEO_INFO_FORMAT (info)));
> ++
> ++  if (!gst_is_gl_physical_memory_supported_fmt (info)) {
> ++    GST_DEBUG ("Not support format.");
> ++    return FALSE;
> ++  }
> ++
> ++  if(!pTexDirectVIVMap || !pTexDirectInvalidateVIV) {
> ++    pTexDirectVIVMap =
> ++      gst_gl_context_get_proc_address (params->parent.context, "glTexDirectVIVMap");
> ++    pTexDirectInvalidateVIV =
> ++      gst_gl_context_get_proc_address (params->parent.context, "glTexDirectInvalidateVIV");
> ++  }
> ++
> ++  if(!pTexDirectVIVMap || !pTexDirectInvalidateVIV) {
> ++    GST_DEBUG ("Load directviv functions failed.");
> ++    return FALSE;
> ++  }
> ++
> ++  size = gst_gl_get_plane_data_size (info, valign, 0);
> ++  mem = gst_allocator_alloc (allocator, size, params->parent.alloc_params);
> ++  if (!mem) {
> ++    GST_DEBUG ("Can't allocate physical memory size %d", size);
> ++    return FALSE;
> ++  }
> ++
> ++  memblk = gst_memory_query_phymem_block (mem);
> ++  if (!memblk) {
> ++    GST_ERROR("Can't find physic memory block.");
> ++    return FALSE;
> ++  }
> ++
> ++  gl_alloc =
> ++      GST_GL_BASE_MEMORY_ALLOCATOR (gst_gl_memory_allocator_get_default
> ++      (params->parent.context));
> ++
> ++  params->plane = 0;
> ++  params->parent.user_data = mem;
> ++  params->parent.notify = gst_gl_phy_mem_destroy;
> ++  params->tex_format =
> ++    gst_gl_format_from_video_info(params->parent.context, info, 0);
> ++
> ++  glmem = (GstGLMemory *)gst_gl_base_memory_alloc (gl_alloc, (GstGLAllocationParams *) params);
> ++  gst_object_unref (gl_alloc);
> ++  if (!glmem) {
> ++    GST_ERROR("Can't get gl memory.");
> ++    return FALSE;
> ++  }
> ++
> ++  gst_buffer_append_memory (buffer, (GstMemory *) glmem);
> ++
> ++  gst_buffer_add_video_meta_full (buffer, 0,
> ++      GST_VIDEO_INFO_FORMAT (info), GST_VIDEO_INFO_WIDTH (info),
> ++      GST_VIDEO_INFO_HEIGHT (info), 1, info->offset, info->stride);
> ++
> ++  guint viv_fmt = _directviv_video_format_to_gl_format (GST_VIDEO_INFO_FORMAT (info));
> ++
> ++  DirectVIVData directvivdata =
> ++  {
> ++    glmem->tex_id,
> ++    GST_VIDEO_INFO_WIDTH (info),
> ++    GST_VIDEO_INFO_HEIGHT (info),
> ++    viv_fmt,
> ++    memblk->vaddr,
> ++    memblk->paddr,
> ++    FALSE
> ++  };
> ++
> ++  gst_gl_context_thread_add (params->parent.context,
> ++      _do_viv_direct_tex_bind_mem, &directvivdata);
> ++
> ++  return directvivdata.ret;
> ++}
> ++
> ++GstBuffer *
> ++gst_gl_phymem_buffer_to_gstbuffer (GstGLContext * ctx,
> ++    GstVideoInfo * info, GstBuffer *glbuf)
> ++{
> ++  GstBuffer *buf;
> ++  GstGLBaseMemory *glmem;
> ++
> ++  gst_gl_context_thread_add (ctx, (GstGLContextThreadFunc) _finish_texture, NULL);
> ++
> ++  glmem = gst_buffer_peek_memory (glbuf, 0);
> ++
> ++  buf = gst_buffer_new ();
> ++  gst_buffer_append_memory (buf, (GstMemory *) glmem->user_data);
> ++  gst_memory_ref ((GstMemory *)glmem->user_data);
> ++
> ++  gst_buffer_add_video_meta_full (buf, 0,
> ++      GST_VIDEO_INFO_FORMAT (info), GST_VIDEO_INFO_WIDTH (info),
> ++      GST_VIDEO_INFO_HEIGHT (info), 1, info->offset, info->stride);
> ++  GST_BUFFER_FLAGS (buf) = GST_BUFFER_FLAGS (glbuf);
> ++  GST_BUFFER_PTS (buf) = GST_BUFFER_PTS (glbuf);
> ++  GST_BUFFER_DTS (buf) = GST_BUFFER_DTS (glbuf);
> ++  GST_BUFFER_DURATION (buf) = GST_BUFFER_DURATION (glbuf);
> ++
> ++  return buf;
> ++}
> ++
> +diff --git a/gst-libs/gst/gl/gstglphymemory.h b/gst-libs/gst/gl/gstglphymemory.h
> +new file mode 100644
> +index 0000000..9ebb3ea
> +--- /dev/null
> ++++ b/gst-libs/gst/gl/gstglphymemory.h
> +@@ -0,0 +1,44 @@
> ++/*
> ++ * GStreamer
> ++ * Copyright (c) 2015, Freescale Semiconductor, Inc.
> ++ * Copyright 2017 NXP
> ++ *
> ++ * This library is free software; you can redistribute it and/or
> ++ * modify it under the terms of the GNU Library General Public
> ++ * License as published by the Free Software Foundation; either
> ++ * version 2 of the License, or (at your option) any later version.
> ++ *
> ++ * This library is distributed in the hope that it will be useful,
> ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
> ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> ++ * Library General Public License for more details.
> ++ *
> ++ * You should have received a copy of the GNU Library General Public
> ++ * License along with this library; if not, write to the
> ++ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
> ++ * Boston, MA 02110-1301, USA.
> ++ */
> ++
> ++#ifndef _GST_GL_PHY_MEMORY_H_
> ++#define _GST_GL_PHY_MEMORY_H_
> ++
> ++#include <gst/gst.h>
> ++#include <gst/gstmemory.h>
> ++#include <gst/video/video.h>
> ++#include <gst/allocators/gstallocatorphymem.h>
> ++
> ++#include <gst/gl/gl.h>
> ++
> ++G_BEGIN_DECLS
> ++
> ++#define GST_GL_PHY_MEM_ALLOCATOR "GLPhyMemory"
> ++
> ++GstAllocator *gst_phy_mem_allocator_obtain (void);
> ++gboolean gst_is_gl_physical_memory (GstMemory * mem);
> ++gboolean gst_is_gl_physical_memory_supported_fmt (GstVideoInfo * info);
> ++gboolean gst_gl_physical_memory_setup_buffer (GstAllocator * allocator, GstBuffer *buffer, GstGLVideoAllocationParams * params);
> ++GstBuffer * gst_gl_phymem_buffer_to_gstbuffer (GstGLContext * ctx, GstVideoInfo * info, GstBuffer *glbuf);
> ++
> ++G_END_DECLS
> ++
> ++#endif /* _GST_GL_PHY_MEMORY_H_ */
> +--
> +1.9.1
> +
> diff --git a/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad/0021-ionmemory-dmabuf-memory-allocator-based-on-ion-drive.patch b/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad/0021-ionmemory-dmabuf-memory-allocator-based-on-ion-drive.patch
> new file mode 100644
> index 00000000..c344b2f5
> --- /dev/null
> +++ b/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad/0021-ionmemory-dmabuf-memory-allocator-based-on-ion-drive.patch
> @@ -0,0 +1,390 @@
> +From b245b00342439a0fc2b3e7892dceb1f595fbf67e Mon Sep 17 00:00:00 2001
> +From: Song Bing <bing.song at nxp.com>
> +Date: Tue, 12 Sep 2017 13:42:01 +0800
> +Subject: [PATCH 2/3] ionmemory: dmabuf memory allocator based on ion driver.
> +
> +Upstream Status: Pending
> +
> +https://bugzilla.gnome.org/show_bug.cgi?id=768794
> +---
> + configure.ac                           |   6 +
> + gst-libs/gst/allocators/Makefile.am    |  14 ++
> + gst-libs/gst/allocators/gstionmemory.c | 241 +++++++++++++++++++++++++++++++++
> + gst-libs/gst/allocators/gstionmemory.h |  65 +++++++++
> + 4 files changed, 326 insertions(+)
> + create mode 100755 gst-libs/gst/allocators/gstionmemory.c
> + create mode 100755 gst-libs/gst/allocators/gstionmemory.h
> +
> +diff --git a/configure.ac b/configure.ac
> +index d17bb64..30acf1c 100644
> +--- a/configure.ac
> ++++ b/configure.ac
> +@@ -565,6 +565,12 @@ if test "x$HAVE_WINSOCK2_H" = "xyes"; then
> +   AC_SUBST(WINSOCK2_LIBS)
> + fi
> +
> ++dnl check for ion
> ++translit(dnm, m, l) AM_CONDITIONAL(USE_ION, true)
> ++AG_GST_CHECK_FEATURE(ION, [ion], ion, [
> ++  AC_CHECK_HEADER(linux/ion.h, HAVE_ION="yes", HAVE_ION="no")
> ++])
> ++
> + dnl *** opengl ***
> + AC_ARG_ENABLE([opengl],
> +      [  --enable-opengl         Enable Desktop OpenGL support @<:@default=auto@:>@],
> +diff --git a/gst-libs/gst/allocators/Makefile.am b/gst-libs/gst/allocators/Makefile.am
> +index 46c75c0..07d86f9 100644
> +--- a/gst-libs/gst/allocators/Makefile.am
> ++++ b/gst-libs/gst/allocators/Makefile.am
> +@@ -7,16 +7,30 @@ libgstbadallocators_ at GST_API_VERSION@_include_HEADERS = \
> +       gstphysmemory.h \
> +       gstallocatorphymem.h
> +
> ++if USE_ION
> ++libgstbadallocators_ at GST_API_VERSION@_include_HEADERS += \
> ++      gstionmemory.h
> ++endif
> ++
> + noinst_HEADERS =
> +
> + libgstbadallocators_ at GST_API_VERSION@_la_SOURCES = \
> +       gstphysmemory.c \
> +       gstallocatorphymem.c
> +
> ++if USE_ION
> ++libgstbadallocators_ at GST_API_VERSION@_la_SOURCES += \
> ++      gstionmemory.c
> ++endif
> ++
> + libgstbadallocators_ at GST_API_VERSION@_la_LIBADD = $(GST_LIBS) $(LIBM)
> + libgstbadallocators_ at GST_API_VERSION@_la_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_CFLAGS)
> + libgstbadallocators_ at GST_API_VERSION@_la_LDFLAGS = $(GST_LIB_LDFLAGS) $(GST_ALL_LDFLAGS) $(GST_LT_LDFLAGS)
> +
> ++if USE_ION
> ++libgstbadallocators_ at GST_API_VERSION@_la_LIBADD += -lgstallocators-$(GST_API_VERSION)
> ++endif
> ++
> + if HAVE_INTROSPECTION
> + BUILT_GIRSOURCES = GstBadAllocators- at GST_API_VERSION@.gir
> +
> +diff --git a/gst-libs/gst/allocators/gstionmemory.c b/gst-libs/gst/allocators/gstionmemory.c
> +new file mode 100755
> +index 0000000..bfe13ad
> +--- /dev/null
> ++++ b/gst-libs/gst/allocators/gstionmemory.c
> +@@ -0,0 +1,241 @@
> ++/*
> ++ * Copyright (c) 2016, Freescale Semiconductor, Inc. All rights reserved.
> ++ * Copyright 2017 NXP
> ++ *
> ++ * This library is free software; you can redistribute it and/or
> ++ * modify it under the terms of the GNU Library General Public
> ++ * License as published by the Free Software Foundation; either
> ++ * version 2 of the License, or (at your option) any later version.
> ++ *
> ++ * This library is distributed in the hope that it will be useful,
> ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
> ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> ++ * Library General Public License for more details.
> ++ *
> ++ * You should have received a copy of the GNU Library General Public
> ++ * License along with this library; if not, write to the
> ++ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
> ++ * Boston, MA 02111-1307, USA.
> ++ */
> ++
> ++#include <errno.h>
> ++#include <fcntl.h>
> ++#include <stdio.h>
> ++#include <string.h>
> ++#include <unistd.h>
> ++#include <sys/ioctl.h>
> ++#include <sys/mman.h>
> ++#include <sys/types.h>
> ++#include <linux/ion.h>
> ++
> ++#include <gst/allocators/gstdmabuf.h>
> ++#include "gstionmemory.h"
> ++
> ++GST_DEBUG_CATEGORY_STATIC (ion_allocator_debug);
> ++#define GST_CAT_DEFAULT ion_allocator_debug
> ++
> ++#define gst_ion_allocator_parent_class parent_class
> ++
> ++G_DEFINE_TYPE (GstIONAllocator, gst_ion_allocator, GST_TYPE_DMABUF_ALLOCATOR)
> ++
> ++#define DEFAULT_HEAP_ID  0
> ++#define DEFAULT_FLAG     0
> ++
> ++enum
> ++{
> ++  PROP_0,
> ++  PROP_HEAP_ID,
> ++  PROP_FLAG,
> ++  PROP_LAST
> ++};
> ++
> ++static gint
> ++gst_ion_ioctl (gint fd, gint req, void *arg)
> ++{
> ++  gint ret = ioctl (fd, req, arg);
> ++  if (ret < 0) {
> ++    GST_ERROR ("ioctl %x failed with code %d: %s\n", req, ret,
> ++        strerror (errno));
> ++  }
> ++  return ret;
> ++}
> ++
> ++static void
> ++gst_ion_mem_init (void)
> ++{
> ++  GstAllocator *allocator = g_object_new (gst_ion_allocator_get_type (), NULL);
> ++  GstIONAllocator *self = GST_ION_ALLOCATOR (allocator);
> ++  gint fd;
> ++
> ++  fd = open ("/dev/ion", O_RDWR);
> ++  if (fd < 0) {
> ++    GST_WARNING ("Could not open ion driver");
> ++    g_object_unref (self);
> ++    return;
> ++  }
> ++
> ++  self->fd = fd;
> ++
> ++  gst_allocator_register (GST_ALLOCATOR_ION, allocator);
> ++}
> ++
> ++GstAllocator *
> ++gst_ion_allocator_obtain (void)
> ++{
> ++  static GOnce ion_allocator_once = G_ONCE_INIT;
> ++  GstAllocator *allocator;
> ++
> ++  g_once (&ion_allocator_once, (GThreadFunc) gst_ion_mem_init, NULL);
> ++
> ++  allocator = gst_allocator_find (GST_ALLOCATOR_ION);
> ++  if (allocator == NULL)
> ++    GST_WARNING ("No allocator named %s found", GST_ALLOCATOR_ION);
> ++
> ++  return allocator;
> ++}
> ++
> ++static GstMemory *
> ++gst_ion_alloc_alloc (GstAllocator * allocator, gsize size,
> ++    GstAllocationParams * params)
> ++{
> ++  GstIONAllocator *self = GST_ION_ALLOCATOR (allocator);
> ++  struct ion_allocation_data allocation_data = { 0 };
> ++  struct ion_fd_data fd_data = { 0 };
> ++  struct ion_handle_data handle_data = { 0 };
> ++  ion_user_handle_t ion_handle;
> ++  GstMemory *mem;
> ++  gsize ion_size;
> ++  gint dma_fd = -1;
> ++  gint ret;
> ++
> ++  if (self->fd < 0) {
> ++    GST_ERROR ("ion allocate param wrong");
> ++    return NULL;
> ++  }
> ++
> ++  ion_size = size + params->prefix + params->padding;
> ++  allocation_data.len = ion_size;
> ++  allocation_data.align = params->align;
> ++  allocation_data.heap_id_mask = 1 << self->heap_id;
> ++  allocation_data.flags = self->flags;
> ++  if (gst_ion_ioctl (self->fd, ION_IOC_ALLOC, &allocation_data) < 0) {
> ++    GST_ERROR ("ion allocate failed.");
> ++    return NULL;
> ++  }
> ++  ion_handle = allocation_data.handle;
> ++
> ++  fd_data.handle = ion_handle;
> ++  ret = gst_ion_ioctl (self->fd, ION_IOC_MAP, &fd_data);
> ++  if (ret < 0 || fd_data.fd < 0) {
> ++    GST_ERROR ("map ioctl failed or returned negative fd");
> ++    goto bail;
> ++  }
> ++  dma_fd = fd_data.fd;
> ++
> ++  handle_data.handle = ion_handle;
> ++  gst_ion_ioctl (self->fd, ION_IOC_FREE, &handle_data);
> ++
> ++  mem = gst_dmabuf_allocator_alloc (allocator, dma_fd, size);
> ++
> ++  GST_DEBUG ("ion allocated size: %" G_GSIZE_FORMAT "DMA FD: %d", ion_size,
> ++      dma_fd);
> ++
> ++  return mem;
> ++
> ++bail:
> ++  if (dma_fd >= 0) {
> ++    close (dma_fd);
> ++  }
> ++  handle_data.handle = ion_handle;
> ++  gst_ion_ioctl (self->fd, ION_IOC_FREE, &handle_data);
> ++
> ++  return NULL;
> ++}
> ++
> ++static void
> ++gst_ion_allocator_dispose (GObject * object)
> ++{
> ++  GstIONAllocator *self = GST_ION_ALLOCATOR (object);
> ++
> ++  if (self->fd > 0) {
> ++    close (self->fd);
> ++    self->fd = -1;
> ++  }
> ++
> ++  G_OBJECT_CLASS (parent_class)->dispose (object);
> ++}
> ++
> ++static void
> ++gst_ion_allocator_set_property (GObject * object, guint prop_id,
> ++    const GValue * value, GParamSpec * pspec)
> ++{
> ++  GstIONAllocator *self = GST_ION_ALLOCATOR (object);
> ++
> ++  switch (prop_id) {
> ++    case PROP_HEAP_ID:
> ++      self->heap_id = g_value_get_uint (value);
> ++      break;
> ++    case PROP_FLAG:
> ++      self->flags = g_value_get_uint (value);
> ++      break;
> ++    default:
> ++      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
> ++      break;
> ++  }
> ++}
> ++
> ++static void
> ++gst_ion_allocator_get_property (GObject * object, guint prop_id, GValue * value,
> ++    GParamSpec * pspec)
> ++{
> ++  GstIONAllocator *self = GST_ION_ALLOCATOR (object);
> ++
> ++  switch (prop_id) {
> ++    case PROP_HEAP_ID:
> ++      g_value_set_uint (value, self->heap_id);
> ++      break;
> ++    case PROP_FLAG:
> ++      g_value_set_uint (value, self->flags);
> ++      break;
> ++    default:
> ++      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
> ++      break;
> ++  }
> ++}
> ++
> ++static void
> ++gst_ion_allocator_class_init (GstIONAllocatorClass * klass)
> ++{
> ++  GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
> ++  GstAllocatorClass *allocator_class = GST_ALLOCATOR_CLASS (klass);
> ++
> ++  gobject_class->dispose = GST_DEBUG_FUNCPTR (gst_ion_allocator_dispose);
> ++  gobject_class->set_property = gst_ion_allocator_set_property;
> ++  gobject_class->get_property = gst_ion_allocator_get_property;
> ++
> ++  g_object_class_install_property (gobject_class, PROP_HEAP_ID,
> ++      g_param_spec_uint ("heap-id", "Heap ID",
> ++        "ION heap id", 0, G_MAXUINT32, DEFAULT_HEAP_ID,
> ++        G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
> ++
> ++  g_object_class_install_property (gobject_class, PROP_FLAG,
> ++      g_param_spec_uint ("flags", "Flags",
> ++        "ION memory flags", 0, G_MAXUINT32, DEFAULT_FLAG,
> ++        G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
> ++
> ++  allocator_class->alloc = GST_DEBUG_FUNCPTR (gst_ion_alloc_alloc);
> ++
> ++  GST_DEBUG_CATEGORY_INIT (ion_allocator_debug, "ionmemory", 0,
> ++      "DMA FD memory allocator based on ion");
> ++}
> ++
> ++static void
> ++gst_ion_allocator_init (GstIONAllocator * self)
> ++{
> ++  GstAllocator *allocator = GST_ALLOCATOR (self);
> ++
> ++  allocator->mem_type = GST_ALLOCATOR_ION;
> ++
> ++  self->heap_id = DEFAULT_HEAP_ID;
> ++  self->flags = DEFAULT_FLAG;
> ++}
> +diff --git a/gst-libs/gst/allocators/gstionmemory.h b/gst-libs/gst/allocators/gstionmemory.h
> +new file mode 100755
> +index 0000000..be45722
> +--- /dev/null
> ++++ b/gst-libs/gst/allocators/gstionmemory.h
> +@@ -0,0 +1,65 @@
> ++/*
> ++ * Copyright (c) 2016, Freescale Semiconductor, Inc. All rights reserved.
> ++ * Copyright 2017 NXP
> ++ *
> ++ * This library is free software; you can redistribute it and/or
> ++ * modify it under the terms of the GNU Library General Public
> ++ * License as published by the Free Software Foundation; either
> ++ * version 2 of the License, or (at your option) any later version.
> ++ *
> ++ * This library is distributed in the hope that it will be useful,
> ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
> ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> ++ * Library General Public License for more details.
> ++ *
> ++ * You should have received a copy of the GNU Library General Public
> ++ * License along with this library; if not, write to the
> ++ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
> ++ * Boston, MA 02111-1307, USA.
> ++ */
> ++
> ++#ifndef __GST_IONMEMORY_H__
> ++#define __GST_IONMEMORY_H__
> ++
> ++#include <gst/gst.h>
> ++#include <gst/allocators/gstdmabuf.h>
> ++
> ++G_BEGIN_DECLS
> ++
> ++typedef struct _GstIONAllocator GstIONAllocator;
> ++typedef struct _GstIONAllocatorClass GstIONAllocatorClass;
> ++typedef struct _GstIONMemory GstIONMemory;
> ++
> ++#define GST_ALLOCATOR_ION "ionmem"
> ++
> ++#define GST_TYPE_ION_ALLOCATOR gst_ion_allocator_get_type ()
> ++#define GST_IS_ION_ALLOCATOR(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \
> ++    GST_TYPE_ION_ALLOCATOR))
> ++#define GST_ION_ALLOCATOR(obj) \
> ++  (G_TYPE_CHECK_INSTANCE_CAST((obj), GST_TYPE_ION_ALLOCATOR, GstIONAllocator))
> ++#define GST_ION_ALLOCATOR_CLASS(klass) \
> ++  (G_TYPE_CHECK_CLASS_CAST((klass), GST_TYPE_ION_ALLOCATOR, GstIONAllocatorClass))
> ++#define GST_ION_ALLOCATOR_CAST(obj) ((GstIONAllocator *)(obj))
> ++
> ++#define GST_ION_MEMORY_QUARK gst_ion_memory_quark ()
> ++
> ++struct _GstIONAllocator
> ++{
> ++  GstDmaBufAllocator parent;
> ++
> ++  gint fd;
> ++  guint heap_id;
> ++  guint flags;
> ++};
> ++
> ++struct _GstIONAllocatorClass
> ++{
> ++  GstDmaBufAllocatorClass parent;
> ++};
> ++
> ++GType gst_ion_allocator_get_type (void);
> ++GstAllocator* gst_ion_allocator_obtain (void);
> ++
> ++G_END_DECLS
> ++
> ++#endif /* __GST_IONMEMORY_H__ */
> +--
> +2.7.4
> +
> diff --git a/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad/0022-ionmemory-support-get-phys-memory.patch b/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad/0022-ionmemory-support-get-phys-memory.patch
> new file mode 100644
> index 00000000..5ab41833
> --- /dev/null
> +++ b/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad/0022-ionmemory-support-get-phys-memory.patch
> @@ -0,0 +1,94 @@
> +From 2f82ec644f10e2aefa9f80ee3909ba06466752e6 Mon Sep 17 00:00:00 2001
> +From: Song Bing <bing.song at nxp.com>
> +Date: Wed, 13 Sep 2017 13:39:53 +0800
> +Subject: [PATCH 3/3] ionmemory: support get phys memory
> +
> +Upstream Status: Pending
> +
> +https://bugzilla.gnome.org/show_bug.cgi?id=768794
> +---
> + gst-libs/gst/allocators/gstionmemory.c | 54 ++++++++++++++++++++++++++++++++--
> + 1 file changed, 52 insertions(+), 2 deletions(-)
> +
> +diff --git a/gst-libs/gst/allocators/gstionmemory.c b/gst-libs/gst/allocators/gstionmemory.c
> +index bfe13ad..fad53db 100755
> +--- a/gst-libs/gst/allocators/gstionmemory.c
> ++++ b/gst-libs/gst/allocators/gstionmemory.c
> +@@ -29,6 +29,7 @@
> + #include <linux/ion.h>
> +
> + #include <gst/allocators/gstdmabuf.h>
> ++#include "gstphysmemory.h"
> + #include "gstionmemory.h"
> +
> + GST_DEBUG_CATEGORY_STATIC (ion_allocator_debug);
> +@@ -36,8 +37,6 @@ GST_DEBUG_CATEGORY_STATIC (ion_allocator_debug);
> +
> + #define gst_ion_allocator_parent_class parent_class
> +
> +-G_DEFINE_TYPE (GstIONAllocator, gst_ion_allocator, GST_TYPE_DMABUF_ALLOCATOR)
> +-
> + #define DEFAULT_HEAP_ID  0
> + #define DEFAULT_FLAG     0
> +
> +@@ -49,6 +48,57 @@ enum
> +   PROP_LAST
> + };
> +
> ++static guintptr
> ++gst_ion_allocator_get_phys_addr (GstPhysMemoryAllocator *allocator, GstMemory *mem)
> ++{
> ++  GstIONAllocator *self = GST_ION_ALLOCATOR (allocator);
> ++  gint ret, fd;
> ++
> ++  if (self->fd < 0 || !mem) {
> ++    GST_ERROR ("ion get phys param wrong");
> ++    return 0;
> ++  }
> ++
> ++  if (!gst_is_dmabuf_memory (mem)) {
> ++    GST_ERROR ("isn't dmabuf memory");
> ++    return 0;
> ++  }
> ++
> ++  fd = gst_dmabuf_memory_get_fd (mem);
> ++  if (fd < 0) {
> ++    GST_ERROR ("dmabuf memory get fd failed");
> ++    return 0;
> ++  }
> ++
> ++  GST_DEBUG ("ion DMA FD: %d", fd);
> ++
> ++  struct ion_phys_dma_data data = {
> ++    .phys = 0,
> ++    .size = 0,
> ++    .dmafd = fd,
> ++  };
> ++
> ++  struct ion_custom_data custom = {
> ++    .cmd = ION_IOC_PHYS_DMA,
> ++    .arg = (unsigned long)&data,
> ++  };
> ++
> ++  ret = ioctl(self->fd, ION_IOC_CUSTOM, &custom);
> ++  if (ret < 0)
> ++    return 0;
> ++
> ++  return data.phys;
> ++}
> ++
> ++static void gst_ion_allocator_iface_init(gpointer g_iface)
> ++{
> ++  GstPhysMemoryAllocatorInterface *iface = g_iface;
> ++  iface->get_phys_addr = gst_ion_allocator_get_phys_addr;
> ++}
> ++
> ++G_DEFINE_TYPE_WITH_CODE (GstIONAllocator, gst_ion_allocator, GST_TYPE_DMABUF_ALLOCATOR,
> ++    G_IMPLEMENT_INTERFACE(GST_TYPE_PHYS_MEMORY_ALLOCATOR, gst_ion_allocator_iface_init));
> ++
> + static gint
> + gst_ion_ioctl (gint fd, gint req, void *arg)
> + {
> +--
> +2.7.4
> +
> diff --git a/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad/0023-glupload-add-crop-meta-support-in-dmafd-uploader.patch b/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad/0023-glupload-add-crop-meta-support-in-dmafd-uploader.patch
> new file mode 100644
> index 00000000..67c6db6c
> --- /dev/null
> +++ b/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad/0023-glupload-add-crop-meta-support-in-dmafd-uploader.patch
> @@ -0,0 +1,52 @@
> +From efa0059db11f091ceeef768a6ed115045399eeac Mon Sep 17 00:00:00 2001
> +From: Haihua Hu <jared.hu at nxp.com>
> +Date: Wed, 13 Sep 2017 16:42:21 +0800
> +Subject: [PATCH 2/2] glupload: add crop meta support in dmafd uploader
> +
> +get video crop meta from input buffer and update video info
> +
> +Upstream-Status: Pending
> +https://bugzilla.gnome.org/show_bug.cgi?id=787616
> +---
> + gst-libs/gst/gl/gstglupload.c | 11 +++++++++++
> + 1 file changed, 11 insertions(+)
> +
> +diff --git a/gst-libs/gst/gl/gstglupload.c b/gst-libs/gst/gl/gstglupload.c
> +index 6011695..5c7eca0 100644
> +--- a/gst-libs/gst/gl/gstglupload.c
> ++++ b/gst-libs/gst/gl/gstglupload.c
> +@@ -651,6 +651,7 @@ _dma_buf_upload_accept (gpointer impl, GstBuffer * buffer, GstCaps * in_caps,
> +   GstVideoInfo *in_info = &dmabuf->upload->priv->in_info;
> +   guint n_planes = GST_VIDEO_INFO_N_PLANES (in_info);
> +   GstVideoMeta *meta;
> ++  GstVideoCropMeta *crop;
> +   guint n_mem;
> +   guint mems_idx[GST_VIDEO_MAX_PLANES];
> +   gsize mems_skip[GST_VIDEO_MAX_PLANES];
> +@@ -659,6 +660,7 @@ _dma_buf_upload_accept (gpointer impl, GstBuffer * buffer, GstCaps * in_caps,
> +
> +   n_mem = gst_buffer_n_memory (buffer);
> +   meta = gst_buffer_get_video_meta (buffer);
> ++  crop = gst_buffer_get_video_crop_meta(buffer);
> +
> +   /* dmabuf upload is only supported with EGL contexts. */
> +   if (gst_gl_context_get_gl_platform (dmabuf->upload->context) !=
> +@@ -732,6 +734,15 @@ _dma_buf_upload_accept (gpointer impl, GstBuffer * buffer, GstCaps * in_caps,
> +     }
> +   }
> +
> ++  if (crop) {
> ++    in_info->width = MIN (crop->width, in_info->width);
> ++    in_info->height = MIN (crop->height, in_info->height);
> ++
> ++    GST_DEBUG_OBJECT (dmabuf->upload, "got crop meta (%d)x(%d)",
> ++        in_info->width, in_info->height);
> ++    gst_buffer_remove_meta (buffer, (GstMeta *)crop);
> ++  }
> ++
> +   if (dmabuf->params)
> +     gst_gl_allocation_params_free ((GstGLAllocationParams *) dmabuf->params);
> +   if (!(dmabuf->params =
> +--
> +1.9.1
> +
> diff --git a/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad/0024-glupload-add-ion-dmabuf-support-in-glupload.patch b/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad/0024-glupload-add-ion-dmabuf-support-in-glupload.patch
> new file mode 100644
> index 00000000..c2b55f6f
> --- /dev/null
> +++ b/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad/0024-glupload-add-ion-dmabuf-support-in-glupload.patch
> @@ -0,0 +1,477 @@
> +From 21b21597d3e2bccd2bf04ec6dd7c89bfe1a88ec5 Mon Sep 17 00:00:00 2001
> +From: Haihua Hu <jared.hu at nxp.com>
> +Date: Wed, 17 May 2017 14:55:33 +0800
> +Subject: [PATCH] glupload: add ion dmabuf support in glupload
> +
> +1. Support one texture for YUV format in dmabuf uploader
> +2. Propose ion dma-fd buffer pool to upstream to avoid memory copy
> +3. If upstream don't chose the proposed buffer pool, then create
> +   our own and do copy to avoid memory copy from CPU to GPU side
> +4. Add buffer alignmentw
> +
> +Upstream-Status: Inappropriate [i.MX specific]
> +
> +Signed-off-by: Haihua Hu <jared.hu at nxp.com>
> +---
> + configure.ac                      |   9 ++
> + gst-libs/gst/gl/Makefile.am       |   6 +-
> + gst-libs/gst/gl/egl/gsteglimage.c |  77 +++++++++++++++
> + gst-libs/gst/gl/egl/gsteglimage.h |   5 +
> + gst-libs/gst/gl/gstglupload.c     | 194 +++++++++++++++++++++++++++++++++++++-
> + 5 files changed, 285 insertions(+), 6 deletions(-)
> +
> +diff --git a/configure.ac b/configure.ac
> +index 3f6f100..d17bb64 100644
> +--- a/configure.ac
> ++++ b/configure.ac
> +@@ -857,10 +857,16 @@ PKG_CHECK_MODULES(GST_ALLOCATORS, gstreamer-allocators-1.0,
> +   HAVE_GST_ALLOCATORS=yes, )
> +
> + GST_GL_HAVE_DMABUF=0
> ++GST_GL_HAVE_IONDMA=0
> ++HAVE_IONDMA=no
> + if test "x$HAVE_DRM_FOURCC_HEADER" = "xyes" -a \
> +         "x$HAVE_GST_ALLOCATORS" = "xyes" -a \
> +         "x$HAVE_EGL" = "xyes"; then
> +           GST_GL_HAVE_DMABUF=1
> ++  if test "x$HAVE_ION" = "xyes"; then
> ++    HAVE_IONDMA=yes
> ++    GST_GL_HAVE_IONDMA=1
> ++  fi
> + fi
> +
> + dnl check for Vivante DirectVIV support
> +@@ -1301,6 +1307,7 @@ GL_CONFIG_DEFINES="$GL_CONFIG_DEFINES
> +
> + GL_CONFIG_DEFINES="$GL_CONFIG_DEFINES
> + #define GST_GL_HAVE_DMABUF $GST_GL_HAVE_DMABUF
> ++#define GST_GL_HAVE_IONDMA $GST_GL_HAVE_IONDMA
> + #define GST_GL_HAVE_VIV_DIRECTVIV $GST_GL_HAVE_VIV_DIRECTVIV
> + #define GST_GL_HAVE_PHYMEM $GST_GL_HAVE_PHYMEM
> + "
> +@@ -1339,6 +1346,7 @@ if test "x$GL_APIS" = "x" -o "x$GL_PLATFORMS" = "x" -o "x$GL_WINDOWS" = "x"; the
> +   HAVE_WINDOW_EAGL=no
> +   HAVE_WINDOW_VIV_FB=no
> +   HAVE_G2D=no
> ++  HAVE_IONDMA=no
> + fi
> +
> + AC_SUBST(GL_APIS)
> +@@ -1359,6 +1367,7 @@ AM_CONDITIONAL(HAVE_WINDOW_ANDROID, test "x$HAVE_WINDOW_ANDROID" = "xyes")
> + AM_CONDITIONAL(HAVE_WINDOW_EAGL, test "x$HAVE_WINDOW_EAGL" = "xyes")
> + AM_CONDITIONAL(HAVE_WINDOW_VIV_FB, test "x$HAVE_WINDOW_VIV_FB" = "xyes")
> + AM_CONDITIONAL(HAVE_GL_PHYMEM, test "x$HAVE_G2D" = "xyes" -a "x$HAVE_VIV_DIRECTVIV" = "xyes")
> ++AM_CONDITIONAL(HAVE_IONDMA, test "x$HAVE_IONDMA" = "xyes")
> +
> + AM_CONDITIONAL(USE_OPENGL, test "x$USE_OPENGL" = "xyes")
> + AM_CONDITIONAL(USE_GLES2, test "x$USE_GLES2" = "xyes")
> +diff --git a/gst-libs/gst/gl/Makefile.am b/gst-libs/gst/gl/Makefile.am
> +index e97a386..03ce1b0 100644
> +--- a/gst-libs/gst/gl/Makefile.am
> ++++ b/gst-libs/gst/gl/Makefile.am
> +@@ -177,9 +177,9 @@ GstGL- at GST_API_VERSION@.gir: $(INTROSPECTION_SCANNER) libgstgl- at GST_API_VERSION@
> +               -I$(top_builddir)/gst-libs \
> +               $(GST_PLUGINS_BASE_CFLAGS) \
> +               $(GL_CFLAGS) \
> +-              --add-include-path=`PKG_CONFIG_PATH="$(GST_PKG_CONFIG_PATH)" $(PKG_CONFIG) --variable=girdir gstreamer- at GST_API_VERSION@` \
> +-              --add-include-path=`PKG_CONFIG_PATH="$(GST_PKG_CONFIG_PATH)" $(PKG_CONFIG) --variable=girdir gstreamer-base- at GST_API_VERSION@` \
> +-              --add-include-path=`PKG_CONFIG_PATH="$(GST_PKG_CONFIG_PATH)" $(PKG_CONFIG) --variable=girdir gstreamer-video- at GST_API_VERSION@` \
> ++              --add-include-path=$(PKG_CONFIG_SYSROOT_DIR)`PKG_CONFIG_PATH="$(GST_PKG_CONFIG_PATH)" $(PKG_CONFIG) --variable=girdir gstreamer- at GST_API_VERSION@` \
> ++              --add-include-path=$(PKG_CONFIG_SYSROOT_DIR)`PKG_CONFIG_PATH="$(GST_PKG_CONFIG_PATH)" $(PKG_CONFIG) --variable=girdir gstreamer-base- at GST_API_VERSION@` \
> ++              --add-include-path=$(PKG_CONFIG_SYSROOT_DIR)`PKG_CONFIG_PATH="$(GST_PKG_CONFIG_PATH)" $(PKG_CONFIG) --variable=girdir gstreamer-video- at GST_API_VERSION@` \
> +               --library=libgstgl- at GST_API_VERSION@.la \
> +               --include=Gst- at GST_API_VERSION@ \
> +               --include=GstBase- at GST_API_VERSION@ \
> +diff --git a/gst-libs/gst/gl/egl/gsteglimage.c b/gst-libs/gst/gl/egl/gsteglimage.c
> +index f570718..75ed5cf 100644
> +--- a/gst-libs/gst/gl/egl/gsteglimage.c
> ++++ b/gst-libs/gst/gl/egl/gsteglimage.c
> +@@ -462,4 +462,81 @@ gst_egl_image_from_dmabuf (GstGLContext * context,
> +   return gst_egl_image_new_wrapped (context, img, format, NULL,
> +       (GstEGLImageDestroyNotify) _destroy_egl_image);
> + }
> ++
> ++GstEGLImage *
> ++gst_egl_image_from_dmabuf_singleplaner (GstGLContext * context,
> ++    GstMemory ** mems, GstVideoInfo * in_info, gint n_planes, gsize * offset)
> ++{
> ++  gint fourcc;
> ++  gint atti = 0;
> ++  guint i;
> ++  guintptr attribs[25];
> ++  guintptr dmafd_flags[] = {
> ++    EGL_DMA_BUF_PLANE0_FD_EXT,
> ++    EGL_DMA_BUF_PLANE1_FD_EXT,
> ++    EGL_DMA_BUF_PLANE2_FD_EXT
> ++  };
> ++  guintptr offset_flags[] = {
> ++    EGL_DMA_BUF_PLANE0_OFFSET_EXT,
> ++    EGL_DMA_BUF_PLANE1_OFFSET_EXT,
> ++    EGL_DMA_BUF_PLANE2_OFFSET_EXT
> ++  };
> ++  guintptr pitch_flags[] = {
> ++    EGL_DMA_BUF_PLANE0_PITCH_EXT,
> ++    EGL_DMA_BUF_PLANE1_PITCH_EXT,
> ++    EGL_DMA_BUF_PLANE2_PITCH_EXT
> ++  };
> ++  EGLImageKHR img = EGL_NO_IMAGE_KHR;
> ++
> ++  fourcc = _drm_fourcc_from_info (in_info, 0);
> ++
> ++  if(GST_VIDEO_INFO_IS_YUV(in_info)) {
> ++    fourcc = gst_video_format_to_fourcc (GST_VIDEO_INFO_FORMAT(in_info));
> ++
> ++    /* gstreamer fourcc is not compatible with DRM FOURCC*/
> ++    if(GST_VIDEO_INFO_FORMAT(in_info) == GST_VIDEO_FORMAT_I420)
> ++      fourcc = DRM_FORMAT_YUV420;
> ++  }
> ++
> ++  GST_DEBUG ("fourcc %.4s (%d) n_planes %d (%dx%d)",
> ++      (char *) &fourcc, fourcc, n_planes,
> ++      GST_VIDEO_INFO_COMP_WIDTH (in_info, 0),
> ++      GST_VIDEO_INFO_COMP_HEIGHT (in_info, 0));
> ++
> ++  attribs[atti++] = EGL_WIDTH;
> ++  attribs[atti++] = GST_VIDEO_INFO_WIDTH (in_info);
> ++  attribs[atti++] = EGL_HEIGHT;
> ++  attribs[atti++] = GST_VIDEO_INFO_HEIGHT (in_info);
> ++
> ++  attribs[atti++] = EGL_LINUX_DRM_FOURCC_EXT;
> ++  attribs[atti++] = fourcc;
> ++
> ++  for (i = 0; i < n_planes; i++) {
> ++    attribs[atti++] = dmafd_flags[i];
> ++    attribs[atti++] = gst_dmabuf_memory_get_fd (mems[i]);
> ++    attribs[atti++] = offset_flags[i];
> ++    attribs[atti++] = offset[i];
> ++    attribs[atti++] = pitch_flags[i];
> ++    attribs[atti++] = GST_VIDEO_INFO_PLANE_STRIDE (in_info, i);
> ++  }
> ++
> ++  attribs[atti] = EGL_NONE;
> ++
> ++  for (int i = 0; i < atti; i++)
> ++    GST_LOG ("attr %i: %" G_GINTPTR_FORMAT, i, attribs[i]);
> ++
> ++  g_assert (atti <= 25);
> ++
> ++  img = _gst_egl_image_create (context, EGL_LINUX_DMA_BUF_EXT, NULL, attribs);
> ++
> ++  if (!img) {
> ++    GST_WARNING ("eglCreateImage failed: %s",
> ++        gst_egl_get_error_string (eglGetError ()));
> ++    return NULL;
> ++  }
> ++
> ++  /* one texture for YUV format is treat as RGBA texture in imx GPU */
> ++  return gst_egl_image_new_wrapped (context, img, GST_GL_RGBA,
> ++      NULL, (GstEGLImageDestroyNotify) _destroy_egl_image);
> ++}
> + #endif /* GST_GL_HAVE_DMABUF */
> +diff --git a/gst-libs/gst/gl/egl/gsteglimage.h b/gst-libs/gst/gl/egl/gsteglimage.h
> +index 56ec7e1..5595ba8 100644
> +--- a/gst-libs/gst/gl/egl/gsteglimage.h
> ++++ b/gst-libs/gst/gl/egl/gsteglimage.h
> +@@ -78,6 +78,11 @@ GstEGLImage *           gst_egl_image_from_dmabuf               (GstGLContext *
> +                                                                  GstVideoInfo * in_info,
> +                                                                  gint plane,
> +                                                                  gsize offset);
> ++GstEGLImage *           gst_egl_image_from_dmabuf_singleplaner  (GstGLContext * context,
> ++                                                                 GstMemory ** mems,
> ++                                                                 GstVideoInfo * in_info,
> ++                                                                 gint n_planes,
> ++                                                                 gsize * offset);
> + #endif
> +
> + /**
> +diff --git a/gst-libs/gst/gl/gstglupload.c b/gst-libs/gst/gl/gstglupload.c
> +index 496ca86..6011695 100644
> +--- a/gst-libs/gst/gl/gstglupload.c
> ++++ b/gst-libs/gst/gl/gstglupload.c
> +@@ -41,6 +41,10 @@
> + #include <gst/allocators/gstphysmemory.h>
> + #endif
> +
> ++#if GST_GL_HAVE_IONDMA
> ++#include <gst/allocators/gstionmemory.h>
> ++#endif
> ++
> + /**
> +  * SECTION:gstglupload
> +  * @title: GstGLUpload
> +@@ -58,6 +62,8 @@
> + #define USING_GLES2(context) (gst_gl_context_check_gl_version (context, GST_GL_API_GLES2, 2, 0))
> + #define USING_GLES3(context) (gst_gl_context_check_gl_version (context, GST_GL_API_GLES2, 3, 0))
> +
> ++#define DEFAULT_ALIGN 16
> ++
> + GST_DEBUG_CATEGORY_STATIC (gst_gl_upload_debug);
> + #define GST_CAT_DEFAULT gst_gl_upload_debug
> +
> +@@ -483,7 +489,9 @@ struct DmabufUpload
> +   GstGLUpload *upload;
> +
> +   GstEGLImage *eglimage[GST_VIDEO_MAX_PLANES];
> ++  GstBuffer *inbuf;
> +   GstBuffer *outbuf;
> ++  GstBufferPool *pool;
> +   GstGLVideoAllocationParams *params;
> + };
> +
> +@@ -514,6 +522,7 @@ _dma_buf_upload_transform_caps (gpointer impl, GstGLContext * context,
> +         _set_caps_features_with_passthrough (caps,
> +         GST_CAPS_FEATURE_MEMORY_GL_MEMORY, passthrough);
> +
> ++    gst_caps_set_simple (ret, "format", G_TYPE_STRING, "RGBA", NULL);
> +     tmp = _caps_intersect_texture_target (ret, 1 << GST_GL_TEXTURE_TARGET_2D);
> +     gst_caps_unref (ret);
> +     ret = tmp;
> +@@ -569,6 +578,72 @@ _set_cached_eglimage (GstMemory * mem, GstEGLImage * eglimage, gint plane)
> + }
> +
> + static gboolean
> ++_dma_buf_upload_setup_buffer_pool (GstBufferPool **pool, GstAllocator *allocator,
> ++    GstCaps *caps, GstVideoInfo *info)
> ++{
> ++  GstAllocationParams params;
> ++  GstStructure *config;
> ++  gsize size;
> ++  guint width, height;
> ++  GstVideoAlignment alignment;
> ++
> ++  g_return_val_if_fail (caps != NULL && info != NULL, FALSE);
> ++
> ++  width = GST_VIDEO_INFO_WIDTH (info);
> ++  height = GST_VIDEO_INFO_HEIGHT (info);
> ++
> ++  gst_allocation_params_init (&params);
> ++
> ++  /* if user not provide an allocator, then use default ion allocator*/
> ++  if (!allocator) {
> ++#if GST_GL_HAVE_IONDMA
> ++    allocator = gst_ion_allocator_obtain ();
> ++#endif
> ++  }
> ++
> ++  if (!allocator) {
> ++    GST_WARNING ("Cannot get available allocator");
> ++    return FALSE;
> ++  }
> ++  GST_DEBUG ("got allocator(%p).", allocator);
> ++
> ++  if (*pool)
> ++    gst_object_unref(*pool);
> ++
> ++  *pool = gst_video_buffer_pool_new ();
> ++  if (!*pool) {
> ++    GST_WARNING ("New video buffer pool failed.");
> ++    return FALSE;
> ++  }
> ++  GST_DEBUG ("create buffer pool(%p).", *pool);
> ++
> ++  config = gst_buffer_pool_get_config (*pool);
> ++
> ++  /* configure alignment for eglimage to import this dma-fd buffer */
> ++  memset (&alignment, 0, sizeof (GstVideoAlignment));
> ++  alignment.padding_right = GST_ROUND_UP_N(width, DEFAULT_ALIGN) - width;
> ++  alignment.padding_bottom = GST_ROUND_UP_N(height, DEFAULT_ALIGN) - height;
> ++  GST_DEBUG ("align buffer pool, w(%d) h(%d), padding_right (%d), padding_bottom (%d)",
> ++      width, height, alignment.padding_right, alignment.padding_bottom);
> ++
> ++  /* the normal size of a frame */
> ++  size = info->size;
> ++  gst_buffer_pool_config_set_params (config, caps, size, 0, 30);
> ++  gst_buffer_pool_config_add_option (config, GST_BUFFER_POOL_OPTION_VIDEO_META);
> ++  gst_buffer_pool_config_add_option (config, GST_BUFFER_POOL_OPTION_VIDEO_ALIGNMENT);
> ++  gst_buffer_pool_config_set_video_alignment (config, &alignment);
> ++  gst_buffer_pool_config_set_allocator (config, allocator, &params);
> ++
> ++  if (!gst_buffer_pool_set_config (*pool, config)) {
> ++    GST_WARNING ("buffer pool config failed.");
> ++    gst_object_unref (*pool);
> ++    return FALSE;
> ++  }
> ++
> ++  return TRUE;
> ++}
> ++
> ++static gboolean
> + _dma_buf_upload_accept (gpointer impl, GstBuffer * buffer, GstCaps * in_caps,
> +     GstCaps * out_caps)
> + {
> +@@ -595,8 +670,52 @@ _dma_buf_upload_accept (gpointer impl, GstBuffer * buffer, GstCaps * in_caps,
> +     return FALSE;
> +
> +   /* This will eliminate most non-dmabuf out there */
> +-  if (!gst_is_dmabuf_memory (gst_buffer_peek_memory (buffer, 0)))
> +-    return FALSE;
> ++  if (!gst_is_dmabuf_memory (gst_buffer_peek_memory (buffer, 0))) {
> ++    GstVideoFrame frame1, frame2;
> ++
> ++    gst_video_frame_map (&frame1, in_info, buffer, GST_MAP_READ);
> ++
> ++    if (!dmabuf->pool) {
> ++      gboolean ret;
> ++      GstCaps *new_caps = gst_video_info_to_caps(&frame1.info);
> ++      gst_video_info_from_caps(in_info, new_caps);
> ++
> ++      ret = _dma_buf_upload_setup_buffer_pool (&dmabuf->pool, NULL, new_caps, in_info);
> ++      if (!ret) {
> ++        gst_video_frame_unmap (&frame1);
> ++        gst_caps_unref (new_caps);
> ++        GST_WARNING_OBJECT (dmabuf->upload, "no available buffer pool");
> ++        return FALSE;
> ++      }
> ++    }
> ++
> ++    if (!gst_buffer_pool_is_active (dmabuf->pool)
> ++        && gst_buffer_pool_set_active (dmabuf->pool, TRUE) != TRUE) {
> ++      gst_video_frame_unmap (&frame1);
> ++      GST_WARNING_OBJECT (dmabuf->upload, "buffer pool is not ok");
> ++      return FALSE;
> ++    }
> ++
> ++    if (dmabuf->inbuf)
> ++      gst_buffer_unref(dmabuf->inbuf);
> ++    dmabuf->inbuf = NULL;
> ++
> ++    gst_buffer_pool_acquire_buffer (dmabuf->pool, &dmabuf->inbuf, NULL);
> ++    if (!dmabuf->inbuf) {
> ++      gst_video_frame_unmap (&frame1);
> ++      GST_WARNING_OBJECT (dmabuf->upload, "acquire_buffer failed");
> ++      return FALSE;
> ++    }
> ++
> ++    GST_DEBUG_OBJECT (dmabuf->upload, "copy plane resolution (%d)x(%d)\n", in_info->width, in_info->height);
> ++    gst_video_frame_map (&frame2, in_info, dmabuf->inbuf, GST_MAP_WRITE);
> ++    gst_video_frame_copy (&frame2, &frame1);
> ++    gst_video_frame_unmap (&frame1);
> ++    gst_video_frame_unmap (&frame2);
> ++
> ++    buffer = dmabuf->inbuf;
> ++    meta = gst_buffer_get_video_meta (buffer);
> ++  }
> +
> +   /* We cannot have multiple dmabuf per plane */
> +   if (n_mem > n_planes)
> +@@ -617,7 +736,7 @@ _dma_buf_upload_accept (gpointer impl, GstBuffer * buffer, GstCaps * in_caps,
> +     gst_gl_allocation_params_free ((GstGLAllocationParams *) dmabuf->params);
> +   if (!(dmabuf->params =
> +           gst_gl_video_allocation_params_new_wrapped_gl_handle (dmabuf->
> +-              upload->context, NULL, &dmabuf->upload->priv->in_info, -1, NULL,
> ++              upload->context, NULL, &dmabuf->upload->priv->out_info, -1, NULL,
> +               GST_GL_TEXTURE_TARGET_2D, 0, NULL, NULL, NULL)))
> +     return FALSE;
> +
> +@@ -643,6 +762,21 @@ _dma_buf_upload_accept (gpointer impl, GstBuffer * buffer, GstCaps * in_caps,
> +       return FALSE;
> +   }
> +
> ++#ifdef EGL_DMA_BUF_PLANE1_FD_EXT
> ++  /* Now create one single EGLImage */
> ++  /* check if one is cached */
> ++  dmabuf->eglimage[0] = _get_cached_eglimage (mems[0], 0);
> ++  if (dmabuf->eglimage[0])
> ++    return TRUE;
> ++
> ++  dmabuf->eglimage[0] =
> ++      gst_egl_image_from_dmabuf_singleplaner (dmabuf->upload->context,
> ++      mems, in_info, n_planes, mems_skip);
> ++  if (!dmabuf->eglimage[0])
> ++    return FALSE;
> ++
> ++  _set_cached_eglimage (mems[0], dmabuf->eglimage[0], 0);
> ++#else
> +   /* Now create an EGLImage for each dmabufs */
> +   for (i = 0; i < n_planes; i++) {
> +     /* check if one is cached */
> +@@ -661,6 +795,7 @@ _dma_buf_upload_accept (gpointer impl, GstBuffer * buffer, GstCaps * in_caps,
> +
> +     _set_cached_eglimage (mems[i], dmabuf->eglimage[i], i);
> +   }
> ++#endif
> +
> +   return TRUE;
> + }
> +@@ -670,6 +805,47 @@ _dma_buf_upload_propose_allocation (gpointer impl, GstQuery * decide_query,
> +     GstQuery * query)
> + {
> +   /* nothing to do for now. */
> ++  struct DmabufUpload *upload = impl;
> ++  GstBufferPool *pool = NULL;
> ++  GstAllocator *allocator = NULL;
> ++  GstCaps *caps;
> ++  GstVideoInfo info;
> ++
> ++  gst_query_parse_allocation (query, &caps, NULL);
> ++
> ++  if (!gst_video_info_from_caps (&info, caps))
> ++    goto invalid_caps;
> ++
> ++#if GST_GL_HAVE_IONDMA
> ++  allocator = gst_ion_allocator_obtain ();
> ++#endif
> ++  if (!allocator) {
> ++    GST_WARNING ("New ion allocator failed.");
> ++    return;
> ++  }
> ++  GST_DEBUG ("create ion allocator(%p).", allocator);
> ++
> ++  gst_query_add_allocation_param (query, allocator, NULL);
> ++
> ++  if (!_dma_buf_upload_setup_buffer_pool (&pool, allocator, caps, &info))
> ++    goto setup_failed;
> ++
> ++  gst_query_set_nth_allocation_pool (query, 0, pool, info.size, 1, 30);
> ++
> ++  if (pool)
> ++    gst_object_unref (pool);
> ++
> ++  return;
> ++invalid_caps:
> ++  {
> ++    GST_WARNING_OBJECT (upload->upload, "invalid caps specified");
> ++    return;
> ++  }
> ++setup_failed:
> ++  {
> ++    GST_WARNING_OBJECT (upload->upload, "failed to setup buffer pool");
> ++    return;
> ++  }
> + }
> +
> + static void
> +@@ -677,11 +853,17 @@ _dma_buf_upload_perform_gl_thread (GstGLContext * context,
> +     struct DmabufUpload *dmabuf)
> + {
> +   GstGLMemoryAllocator *allocator;
> ++  guint n_mem, i;
> +
> +   allocator =
> +       GST_GL_MEMORY_ALLOCATOR (gst_allocator_find
> +       (GST_GL_MEMORY_EGL_ALLOCATOR_NAME));
> +
> ++  n_mem = GST_VIDEO_INFO_N_PLANES (dmabuf->params->v_info);
> ++  for (i = 0; i < n_mem; i++) {
> ++    if(!dmabuf->eglimage[i])
> ++      return;
> ++  }
> +   /* FIXME: buffer pool */
> +   dmabuf->outbuf = gst_buffer_new ();
> +   gst_gl_memory_setup_buffer (allocator, dmabuf->outbuf, dmabuf->params, NULL,
> +@@ -716,6 +898,12 @@ _dma_buf_upload_free (gpointer impl)
> +   if (dmabuf->params)
> +     gst_gl_allocation_params_free ((GstGLAllocationParams *) dmabuf->params);
> +
> ++  if (dmabuf->inbuf)
> ++    gst_buffer_unref (dmabuf->inbuf);
> ++
> ++  if (dmabuf->pool)
> ++    gst_object_unref(dmabuf->pool);
> ++
> +   g_free (impl);
> + }
> +
> +--
> +2.7.4
> +
> diff --git a/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad/0025-Add-ion-dmabuf-support-in-gldownload.patch b/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad/0025-Add-ion-dmabuf-support-in-gldownload.patch
> new file mode 100644
> index 00000000..66f78d96
> --- /dev/null
> +++ b/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad/0025-Add-ion-dmabuf-support-in-gldownload.patch
> @@ -0,0 +1,473 @@
> +From 7964e5dabf3f89b02a89ac775466de5b3dfab8a9 Mon Sep 17 00:00:00 2001
> +From: Haihua Hu <jared.hu at nxp.com>
> +Date: Fri, 25 Nov 2016 14:48:44 +0800
> +Subject: [PATCH 23/26] Add ion dmabuf support in gldownload
> +
> +Support copy into dma-fb buffer if support the buffer format
> +
> +Upstream-Status: Inappropriate [i.MX specific]
> +
> +Signed-off-by: Haihua Hu <jared.hu at nxp.com>
> +---
> + ext/gl/gstgldownloadelement.c    |  36 +++++-
> + gst-libs/gst/gl/Makefile.am      |   6 +
> + gst-libs/gst/gl/gstgl_fwd.h      |   4 +
> + gst-libs/gst/gl/gstglmemorydma.c | 258 +++++++++++++++++++++++++++++++++++++++
> + gst-libs/gst/gl/gstglmemorydma.h |  76 ++++++++++++
> + 5 files changed, 376 insertions(+), 4 deletions(-)
> + create mode 100644 gst-libs/gst/gl/gstglmemorydma.c
> + create mode 100644 gst-libs/gst/gl/gstglmemorydma.h
> +
> +diff --git a/ext/gl/gstgldownloadelement.c b/ext/gl/gstgldownloadelement.c
> +index 03f4479..1e6e728 100644
> +--- a/ext/gl/gstgldownloadelement.c
> ++++ b/ext/gl/gstgldownloadelement.c
> +@@ -29,6 +29,10 @@
> + #include <gst/gl/gstglphymemory.h>
> + #endif
> +
> ++#if GST_GL_HAVE_IONDMA
> ++#include <gst/gl/gstglmemorydma.h>
> ++#endif
> ++
> + GST_DEBUG_CATEGORY_STATIC (gst_gl_download_element_debug);
> + #define GST_CAT_DEFAULT gst_gl_download_element_debug
> +
> +@@ -173,8 +177,22 @@ gst_gl_download_element_prepare_output_buffer (GstBaseTransform * bt,
> +   gint i, n;
> +   GstGLMemory *glmem;
> +
> +-#if GST_GL_HAVE_PHYMEM
> +   glmem = gst_buffer_peek_memory (inbuf, 0);
> ++#if GST_GL_HAVE_IONDMA
> ++  if (gst_is_gl_memory_dma (glmem)) {
> ++    GstGLContext *context = GST_GL_BASE_FILTER (bt)->context;
> ++    GstVideoInfo info;
> ++
> ++    gst_video_info_from_caps (&info, src_caps);
> ++    *outbuf = gst_gl_memory_dma_buffer_to_gstbuffer (context, &info, inbuf);
> ++
> ++    GST_DEBUG_OBJECT (download, "gl download with dma buf.");
> ++
> ++    return GST_FLOW_OK;
> ++  }
> ++#endif
> ++
> ++#if GST_GL_HAVE_PHYMEM
> +   if (gst_is_gl_physical_memory (glmem)) {
> +     GstGLContext *context = GST_GL_BASE_FILTER (bt)->context;
> +     GstVideoInfo info;
> +@@ -233,6 +251,7 @@ gst_gl_download_element_propose_allocation (GstBaseTransform * bt,
> +   GstCaps *caps;
> +   GstStructure *config;
> +   gsize size;
> ++  GstVideoFormat fmt;
> +
> +   gst_query_parse_allocation (query, &caps, NULL);
> +   if (!gst_video_info_from_caps (&info, caps)) {
> +@@ -240,12 +259,21 @@ gst_gl_download_element_propose_allocation (GstBaseTransform * bt,
> +     return FALSE;
> +   }
> +
> +-  GST_DEBUG_OBJECT (bt, "video format is %s", gst_video_format_to_string (GST_VIDEO_INFO_FORMAT (&info)));
> +-
> +   gst_allocation_params_init (&params);
> +
> ++  fmt = GST_VIDEO_INFO_FORMAT (&info);
> ++
> ++  GST_DEBUG_OBJECT (bt, "video format is %s", gst_video_format_to_string (fmt));
> ++
> ++#if GST_GL_HAVE_IONDMA
> ++  if (fmt == GST_VIDEO_FORMAT_RGBA || fmt == GST_VIDEO_FORMAT_RGB16) {
> ++    allocator = gst_gl_memory_dma_allocator_obtain ();
> ++    GST_DEBUG_OBJECT (bt, "obtain dma memory allocator %p.", allocator);
> ++  }
> ++#endif
> ++
> + #if GST_GL_HAVE_PHYMEM
> +-  if (gst_is_gl_physical_memory_supported_fmt (&info)) {
> ++  if (!allocator && gst_is_gl_physical_memory_supported_fmt (&info)) {
> +     allocator = gst_phy_mem_allocator_obtain ();
> +     GST_DEBUG_OBJECT (bt, "obtain physical memory allocator %p.", allocator);
> +   }
> +diff --git a/gst-libs/gst/gl/Makefile.am b/gst-libs/gst/gl/Makefile.am
> +index 03ce1b0..b0b6655 100644
> +--- a/gst-libs/gst/gl/Makefile.am
> ++++ b/gst-libs/gst/gl/Makefile.am
> +@@ -137,6 +137,12 @@ libgstgl_ at GST_API_VERSION@include_HEADERS += gstglphymemory.h
> + libgstgl_ at GST_API_VERSION@_la_LIBADD += -lg2d
> + endif
> +
> ++if HAVE_IONDMA
> ++libgstgl_ at GST_API_VERSION@_la_SOURCES += gstglmemorydma.c
> ++libgstgl_ at GST_API_VERSION@include_HEADERS += gstglmemorydma.h
> ++endif
> ++
> ++
> + configexecincludedir = $(libdir)/gstreamer- at GST_API_VERSION@/include/gst/gl
> + nodist_configexecinclude_HEADERS = $(built_sys_header_configure)
> +
> +diff --git a/gst-libs/gst/gl/gstgl_fwd.h b/gst-libs/gst/gl/gstgl_fwd.h
> +index 8f42e8d..0f5957d 100644
> +--- a/gst-libs/gst/gl/gstgl_fwd.h
> ++++ b/gst-libs/gst/gl/gstgl_fwd.h
> +@@ -51,6 +51,10 @@ typedef struct _GstGLMemory GstGLMemory;
> + typedef struct _GstGLMemoryAllocator GstGLMemoryAllocator;
> + typedef struct _GstGLMemoryAllocatorClass GstGLMemoryAllocatorClass;
> +
> ++typedef struct _GstGLMemoryDMA GstGLMemoryDMA;
> ++typedef struct _GstGLMemoryDMAAllocator GstGLMemoryDMAAllocator;
> ++typedef struct _GstGLMemoryDMAAllocatorClass GstGLMemoryDMAAllocatorClass;
> ++
> + typedef struct _GstGLMemoryPBO GstGLMemoryPBO;
> + typedef struct _GstGLMemoryPBOAllocator GstGLMemoryPBOAllocator;
> + typedef struct _GstGLMemoryPBOAllocatorClass GstGLMemoryPBOAllocatorClass;
> +diff --git a/gst-libs/gst/gl/gstglmemorydma.c b/gst-libs/gst/gl/gstglmemorydma.c
> +new file mode 100644
> +index 0000000..8774e6a
> +--- /dev/null
> ++++ b/gst-libs/gst/gl/gstglmemorydma.c
> +@@ -0,0 +1,258 @@
> ++/*
> ++ * GStreamer
> ++ * Copyright (c) 2016, Freescale Semiconductor, Inc.
> ++ *
> ++ * This library is free software; you can redistribute it and/or
> ++ * modify it under the terms of the GNU Library General Public
> ++ * License as published by the Free Software Foundatdma; either
> ++ * versdma 2 of the License, or (at your option) any later version.
> ++ *
> ++ * This library is distributed in the hope that it will be useful,
> ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
> ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> ++ * Library General Public License for more details.
> ++ *
> ++ * You should have received a copy of the GNU Library General Public
> ++ * License along with this library; if not, write to the
> ++ * Free Software Foundatdma, Inc., 51 Franklin St, Fifth Floor,
> ++ * Boston, MA 02110-1301, USA.
> ++ */
> ++
> ++#ifdef HAVE_CONFIG_H
> ++#include "config.h"
> ++#endif
> ++
> ++#include <string.h>
> ++
> ++#include <gst/allocators/gstdmabuf.h>
> ++#include <gst/gl/gstglmemorydma.h>
> ++
> ++#if GST_GL_HAVE_IONDMA
> ++#include <gst/allocators/gstionmemory.h>
> ++#endif
> ++
> ++GST_DEBUG_CATEGORY_STATIC (GST_CAT_GL_DMA_MEMORY);
> ++#define GST_CAT_DEFAULT GST_CAT_GL_DMA_MEMORY
> ++
> ++#define parent_class gst_gl_memory_dma_allocator_parent_class
> ++G_DEFINE_TYPE (GstGLMemoryDMAAllocator, gst_gl_memory_dma_allocator,
> ++    GST_TYPE_GL_MEMORY_ALLOCATOR);
> ++
> ++static void
> ++gst_gl_memory_dma_init_instance (void)
> ++{
> ++  GstAllocator *ion_allocator = NULL;
> ++  GstGLMemoryDMAAllocator *_gl_allocator;
> ++
> ++  GST_DEBUG_CATEGORY_INIT (GST_CAT_GL_DMA_MEMORY, "glmemorydma", 0, "OpenGL dma memory");
> ++
> ++#if GST_GL_HAVE_IONDMA
> ++  ion_allocator = gst_ion_allocator_obtain();
> ++#endif
> ++
> ++  if (!ion_allocator)
> ++    return;
> ++
> ++  gst_gl_memory_init_once ();
> ++
> ++  _gl_allocator = (GstGLMemoryDMAAllocator *) g_object_new (GST_TYPE_GL_MEMORY_DMA_ALLOCATOR, NULL);
> ++  _gl_allocator->ion_allocator = ion_allocator;
> ++
> ++  gst_allocator_register (GST_GL_MEMORY_DMA_ALLOCATOR_NAME,
> ++      gst_object_ref (_gl_allocator));
> ++}
> ++
> ++GstAllocator *
> ++gst_gl_memory_dma_allocator_obtain (void)
> ++{
> ++
> ++  static GOnce once = G_ONCE_INIT;
> ++  GstAllocator *allocator;
> ++
> ++  g_once (&once, (GThreadFunc) gst_gl_memory_dma_init_instance, NULL);
> ++
> ++  allocator = gst_allocator_find (GST_GL_MEMORY_DMA_ALLOCATOR_NAME);
> ++  if (allocator == NULL)
> ++    GST_WARNING ("No allocator named %s found", GST_GL_MEMORY_DMA_ALLOCATOR_NAME);
> ++
> ++  return allocator;
> ++}
> ++
> ++static void
> ++gst_gl_memory_dma_allocator_dispose (GObject * object)
> ++{
> ++  GstGLMemoryDMAAllocator *gl_dma_alloc= GST_GL_MEMORY_DMA_ALLOCATOR (object);
> ++
> ++  if (gl_dma_alloc->ion_allocator) {
> ++    GST_DEBUG ("free ion allocator");
> ++    gst_object_unref (gl_dma_alloc->ion_allocator);
> ++    gl_dma_alloc->ion_allocator = NULL;
> ++  }
> ++
> ++  G_OBJECT_CLASS (parent_class)->dispose (object);
> ++}
> ++
> ++static gboolean
> ++_gl_mem_create (GstGLMemoryDMA * gl_mem, GError ** error)
> ++{
> ++  GstGLContext *context = gl_mem->mem.mem.context;
> ++  GstGLBaseMemoryAllocatorClass *alloc_class;
> ++  guint dma_fd;
> ++
> ++  alloc_class = GST_GL_BASE_MEMORY_ALLOCATOR_CLASS (parent_class);
> ++  if (!alloc_class->create ((GstGLBaseMemory *) gl_mem, error))
> ++    return FALSE;
> ++
> ++  dma_fd = gst_dmabuf_memory_get_fd ((GstMemory*) gl_mem->dma);
> ++
> ++  gl_mem->eglimage =
> ++    gst_egl_image_from_dmabuf (context, dma_fd, &gl_mem->mem.info, 0,0);
> ++
> ++  if (!gl_mem->eglimage) {
> ++    GST_CAT_ERROR (GST_CAT_GL_DMA_MEMORY, "Can't allocate eglimage memory");
> ++    return FALSE;
> ++  }
> ++
> ++  const GstGLFuncs *gl = context->gl_vtable;
> ++
> ++  gl->ActiveTexture (GL_TEXTURE0);
> ++  gl->BindTexture (GL_TEXTURE_2D, gl_mem->mem.tex_id);
> ++  gl->EGLImageTargetTexture2D (GL_TEXTURE_2D,
> ++      gst_egl_image_get_image (gl_mem->eglimage));
> ++
> ++  GST_CAT_DEBUG (GST_CAT_GL_DMA_MEMORY, "generated dma buffer %p fd %u texid %u",
> ++      gl_mem, dma_fd, gl_mem->mem.tex_id);
> ++
> ++  return TRUE;
> ++}
> ++
> ++static GstMemory *
> ++_gl_mem_alloc (GstAllocator * allocator, gsize size,
> ++    GstAllocationParams * params)
> ++{
> ++  g_warning ("Use gst_gl_base_memory_alloc () to allocate from this "
> ++      "GstGLMemoryDMA allocator");
> ++
> ++  return NULL;
> ++}
> ++
> ++static void
> ++_gl_mem_destroy (GstGLMemoryDMA * gl_mem)
> ++{
> ++  GST_CAT_DEBUG (GST_CAT_GL_DMA_MEMORY, "destroy gl dma buffer %p", gl_mem);
> ++
> ++  if (gl_mem->eglimage)
> ++    gst_egl_image_unref (gl_mem->eglimage);
> ++  gl_mem->eglimage = NULL;
> ++  if (gl_mem->dma)
> ++    gst_memory_unref (GST_MEMORY_CAST (gl_mem->dma));
> ++  gl_mem->dma = NULL;
> ++
> ++  GST_GL_BASE_MEMORY_ALLOCATOR_CLASS (parent_class)->destroy ((GstGLBaseMemory
> ++          *) gl_mem);
> ++}
> ++
> ++static GstGLMemoryDMA *
> ++_gl_mem_dma_alloc (GstGLBaseMemoryAllocator * allocator,
> ++    GstGLVideoAllocationParams * params)
> ++{
> ++  GstGLMemoryDMA *mem;
> ++  guint alloc_flags;
> ++  gsize size;
> ++  GstGLMemoryDMAAllocator *gl_dma_alloc = GST_GL_MEMORY_DMA_ALLOCATOR (allocator);
> ++
> ++  alloc_flags = params->parent.alloc_flags;
> ++
> ++  g_return_val_if_fail (alloc_flags & GST_GL_ALLOCATION_PARAMS_ALLOC_FLAG_VIDEO,
> ++      NULL);
> ++
> ++  mem = g_new0 (GstGLMemoryDMA, 1);
> ++
> ++  mem->params = params->parent.alloc_params;
> ++
> ++  size = gst_gl_get_plane_data_size (params->v_info, params->valign, params->plane);
> ++  mem->dma = gst_allocator_alloc (gl_dma_alloc->ion_allocator, size, mem->params);
> ++
> ++  if (!mem->dma) {
> ++    GST_CAT_ERROR (GST_CAT_GL_DMA_MEMORY, "Can't allocate dma memory size %d", size);
> ++    g_free(mem);
> ++    return NULL;
> ++  }
> ++
> ++  gst_gl_memory_init (GST_GL_MEMORY_CAST (mem), GST_ALLOCATOR_CAST (allocator),
> ++      NULL, params->parent.context, params->target, params->tex_format,
> ++      params->parent.alloc_params, params->v_info, params->plane,
> ++      params->valign, params->parent.user_data, params->parent.notify);
> ++
> ++  return mem;
> ++}
> ++
> ++static void
> ++gst_gl_memory_dma_allocator_class_init (GstGLMemoryDMAAllocatorClass * klass)
> ++{
> ++  GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
> ++  GstGLBaseMemoryAllocatorClass *gl_base;
> ++  GstAllocatorClass *allocator_class;
> ++
> ++  gl_base = (GstGLBaseMemoryAllocatorClass *) klass;
> ++  allocator_class = (GstAllocatorClass *) klass;
> ++
> ++  gl_base->alloc = (GstGLBaseMemoryAllocatorAllocFunction) _gl_mem_dma_alloc;
> ++  gl_base->create = (GstGLBaseMemoryAllocatorCreateFunction) _gl_mem_create;
> ++  gl_base->destroy = (GstGLBaseMemoryAllocatorDestroyFunction) _gl_mem_destroy;
> ++  gobject_class->dispose = GST_DEBUG_FUNCPTR (gst_gl_memory_dma_allocator_dispose);
> ++
> ++  allocator_class->alloc = _gl_mem_alloc;
> ++}
> ++
> ++static void
> ++gst_gl_memory_dma_allocator_init (GstGLMemoryDMAAllocator * allocator)
> ++{
> ++  GstAllocator *alloc = GST_ALLOCATOR_CAST (allocator);
> ++
> ++  alloc->mem_type = GST_GL_MEMORY_DMA_ALLOCATOR_NAME;
> ++
> ++  GST_OBJECT_FLAG_SET (allocator, GST_ALLOCATOR_FLAG_CUSTOM_ALLOC);
> ++}
> ++
> ++gboolean
> ++gst_is_gl_memory_dma (GstMemory * mem)
> ++{
> ++  return mem != NULL && mem->allocator != NULL
> ++      && g_type_is_a (G_OBJECT_TYPE (mem->allocator),
> ++      GST_TYPE_GL_MEMORY_DMA_ALLOCATOR);
> ++}
> ++
> ++static void
> ++_finish_texture (GstGLContext * ctx, gpointer *data)
> ++{
> ++  GstGLFuncs *gl = ctx->gl_vtable;
> ++
> ++  gl->Finish ();
> ++}
> ++
> ++GstBuffer *
> ++gst_gl_memory_dma_buffer_to_gstbuffer (GstGLContext *ctx, GstVideoInfo * info,
> ++    GstBuffer * glbuf)
> ++{
> ++  GstBuffer *buf;
> ++  GstGLMemoryDMA *glmem;
> ++
> ++  gst_gl_context_thread_add (ctx, (GstGLContextThreadFunc) _finish_texture, NULL);
> ++
> ++  glmem = gst_buffer_peek_memory (glbuf, 0);
> ++
> ++  buf = gst_buffer_new ();
> ++  gst_buffer_append_memory (buf, (GstMemory *) glmem->dma);
> ++  gst_memory_ref ((GstMemory *)glmem->dma);
> ++
> ++  gst_buffer_add_video_meta_full (buf, 0,
> ++      GST_VIDEO_INFO_FORMAT (info), GST_VIDEO_INFO_WIDTH (info),
> ++      GST_VIDEO_INFO_HEIGHT (info), 1, info->offset, info->stride);
> ++  GST_BUFFER_FLAGS (buf) = GST_BUFFER_FLAGS (glbuf);
> ++  GST_BUFFER_PTS (buf) = GST_BUFFER_PTS (glbuf);
> ++  GST_BUFFER_DTS (buf) = GST_BUFFER_DTS (glbuf);
> ++  GST_BUFFER_DURATION (buf) = GST_BUFFER_DURATION (glbuf);
> ++
> ++  return buf;
> ++}
> +diff --git a/gst-libs/gst/gl/gstglmemorydma.h b/gst-libs/gst/gl/gstglmemorydma.h
> +new file mode 100644
> +index 0000000..f63442a
> +--- /dev/null
> ++++ b/gst-libs/gst/gl/gstglmemorydma.h
> +@@ -0,0 +1,76 @@
> ++/*
> ++ * GStreamer
> ++ * Copyright (c) 2016, Freescale Semiconductor, Inc.
> ++ *
> ++ * This library is free software; you can redistribute it and/or
> ++ * modify it under the terms of the GNU Library General Public
> ++ * License as published by the Free Software Foundatdma; either
> ++ * versdma 2 of the License, or (at your optdma) any later versdma.
> ++ *
> ++ * This library is distributed in the hope that it will be useful,
> ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
> ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> ++ * Library General Public License for more details.
> ++ *
> ++ * You should have received a copy of the GNU Library General Public
> ++ * License along with this library; if not, write to the
> ++ * Free Software Foundatdma, Inc., 51 Franklin St, Fifth Floor,
> ++ * Boston, MA 02110-1301, USA.
> ++ */
> ++
> ++#ifndef _GST_GL_MEMORY_DMA_H_
> ++#define _GST_GL_MEMORY_DMA_H_
> ++
> ++#include <gst/gst.h>
> ++#include <gst/gstallocator.h>
> ++#include <gst/gstmemory.h>
> ++#include <gst/video/video.h>
> ++
> ++#include <gst/gl/gl.h>
> ++#include <gst/gl/egl/gstglcontext_egl.h>
> ++#include <gst/gl/egl/gsteglimage.h>
> ++
> ++#include <gst/gl/gstglmemory.h>
> ++
> ++G_BEGIN_DECLS
> ++
> ++#define GST_TYPE_GL_MEMORY_DMA_ALLOCATOR (gst_gl_memory_dma_allocator_get_type())
> ++GType gst_gl_memory_dma_allocator_get_type(void);
> ++
> ++#define GST_IS_GL_MEMORY_DMA_ALLOCATOR(obj)              (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_GL_MEMORY_DMA_ALLOCATOR))
> ++#define GST_IS_GL_MEMORY_DMA_ALLOCATOR_CLASS(klass)      (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_GL_MEMORY_DMA_ALLOCATOR))
> ++#define GST_GL_MEMORY_DMA_ALLOCATOR_GET_CLASS(obj)       (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_GL_MEMORY_DMA_ALLOCATOR, GstGLMemoryDMAAllocatorClass))
> ++#define GST_GL_MEMORY_DMA_ALLOCATOR(obj)                 (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_GL_MEMORY_DMA_ALLOCATOR, GstGLMemoryDMAAllocator))
> ++#define GST_GL_MEMORY_DMA_ALLOCATOR_CLASS(klass)         (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_GL_MEMORY_DMA_ALLOCATOR, GstGLAllocatorClass))
> ++#define GST_GL_MEMORY_DMA_ALLOCATOR_CAST(obj)            ((GstGLMemoryDMAAllocator *)(obj))
> ++
> ++struct _GstGLMemoryDMA
> ++{
> ++  GstGLMemory   mem;
> ++
> ++  /* <private> */
> ++  GstEGLImage *eglimage;
> ++  GstMemory     *dma;
> ++  GstAllocationParams *params;
> ++};
> ++
> ++#define GST_GL_MEMORY_DMA_ALLOCATOR_NAME   "GLMemoryDMA"
> ++
> ++struct _GstGLMemoryDMAAllocator
> ++{
> ++  GstGLMemoryAllocator parent;
> ++  GstAllocator  *ion_allocator;
> ++};
> ++
> ++struct _GstGLMemoryDMAAllocatorClass
> ++{
> ++  GstGLMemoryAllocatorClass parent_class;
> ++};
> ++
> ++GstAllocator *gst_gl_memory_dma_allocator_obtain (void);
> ++gboolean      gst_is_gl_memory_dma                      (GstMemory * mem);
> ++GstBuffer *   gst_gl_memory_dma_buffer_to_gstbuffer     (GstGLContext * ctx, GstVideoInfo * info, GstBuffer * glbuf);
> ++
> ++G_END_DECLS
> ++
> ++#endif /* _GST_GL_MEMORY_DMA_H_ */
> +--
> +1.9.1
> +
> diff --git a/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad/0026-glframebuffer-check-frame-buffer-status-need-use-spe.patch b/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad/0026-glframebuffer-check-frame-buffer-status-need-use-spe.patch
> new file mode 100644
> index 00000000..9d3f5690
> --- /dev/null
> +++ b/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad/0026-glframebuffer-check-frame-buffer-status-need-use-spe.patch
> @@ -0,0 +1,132 @@
> +From bf7eb6a0725daf770dc68503216d7cd8e1e314c4 Mon Sep 17 00:00:00 2001
> +From: Haihua Hu <jared.hu at nxp.com>
> +Date: Thu, 25 May 2017 10:09:04 +0800
> +Subject: [PATCH 25/26] glframebuffer: check frame buffer status need use
> + specific fbo target
> +
> +Upstream-Status: Pending
> +https://bugzilla.gnome.org/show_bug.cgi?id=783065
> +---
> + ext/qt/qtwindow.cc                  |  4 ++--
> + gst-libs/gst/gl/gstglcolorconvert.c |  2 +-
> + gst-libs/gst/gl/gstglframebuffer.c  | 10 ++++++++--
> + gst-libs/gst/gl/gstglframebuffer.h  |  3 ++-
> + gst-libs/gst/gl/gstglmemory.c       |  8 ++++----
> + 5 files changed, 17 insertions(+), 10 deletions(-)
> +
> +diff --git a/ext/qt/qtwindow.cc b/ext/qt/qtwindow.cc
> +index 92c5834..6f1df7e 100644
> +--- a/ext/qt/qtwindow.cc
> ++++ b/ext/qt/qtwindow.cc
> +@@ -217,7 +217,7 @@ QtGLWindow::afterRendering()
> +
> +   gl->BindFramebuffer (GL_READ_FRAMEBUFFER, this->source->renderTargetId());
> +
> +-  ret = gst_gl_context_check_framebuffer_status (context);
> ++  ret = gst_gl_context_check_framebuffer_status (context, GL_READ_FRAMEBUFFER);
> +   if (!ret) {
> +     GST_ERROR ("FBO errors");
> +     goto errors;
> +@@ -233,7 +233,7 @@ QtGLWindow::afterRendering()
> +     gl->FramebufferTexture2D (GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
> +               GL_TEXTURE_2D, dst_tex, 0);
> +
> +-    ret = gst_gl_context_check_framebuffer_status (context);
> ++    ret = gst_gl_context_check_framebuffer_status (context, GL_DRAW_FRAMEBUFFER);
> +     if (!ret) {
> +       GST_ERROR ("FBO errors");
> +       goto errors;
> +diff --git a/gst-libs/gst/gl/gstglcolorconvert.c b/gst-libs/gst/gl/gstglcolorconvert.c
> +index adf5a6e..45d2d32 100644
> +--- a/gst-libs/gst/gl/gstglcolorconvert.c
> ++++ b/gst-libs/gst/gl/gstglcolorconvert.c
> +@@ -2516,7 +2516,7 @@ _do_convert_draw (GstGLContext * context, GstGLColorConvert * convert)
> +   gl->Viewport (viewport_dim[0], viewport_dim[1], viewport_dim[2],
> +       viewport_dim[3]);
> +
> +-  if (!gst_gl_context_check_framebuffer_status (context))
> ++  if (!gst_gl_context_check_framebuffer_status (context, GL_FRAMEBUFFER))
> +     ret = FALSE;
> +
> +   gst_gl_context_clear_framebuffer (context);
> +diff --git a/gst-libs/gst/gl/gstglframebuffer.c b/gst-libs/gst/gl/gstglframebuffer.c
> +index f628997..7dc9727 100644
> +--- a/gst-libs/gst/gl/gstglframebuffer.c
> ++++ b/gst-libs/gst/gl/gstglframebuffer.c
> +@@ -507,11 +507,17 @@ gst_gl_framebuffer_get_effective_dimensions (GstGLFramebuffer * fb,
> +  * Since: 1.10
> +  */
> + gboolean
> +-gst_gl_context_check_framebuffer_status (GstGLContext * context)
> ++gst_gl_context_check_framebuffer_status (GstGLContext * context, GLenum fbo_target)
> + {
> +   g_return_val_if_fail (GST_IS_GL_CONTEXT (context), FALSE);
> +
> +-  switch (context->gl_vtable->CheckFramebufferStatus (GL_FRAMEBUFFER)) {
> ++  if (fbo_target != GL_FRAMEBUFFER && fbo_target != GL_READ_FRAMEBUFFER
> ++      && fbo_target != GL_DRAW_FRAMEBUFFER) {
> ++    GST_ERROR_OBJECT (context, "fbo target is invalid");
> ++    return FALSE;
> ++  }
> ++
> ++  switch (context->gl_vtable->CheckFramebufferStatus (fbo_target)) {
> +     case GL_FRAMEBUFFER_COMPLETE:
> +       return TRUE;
> +       break;
> +diff --git a/gst-libs/gst/gl/gstglframebuffer.h b/gst-libs/gst/gl/gstglframebuffer.h
> +index 297a71e..172f999 100644
> +--- a/gst-libs/gst/gl/gstglframebuffer.h
> ++++ b/gst-libs/gst/gl/gstglframebuffer.h
> +@@ -103,7 +103,8 @@ void                    gst_gl_framebuffer_get_effective_dimensions (GstGLFrameb
> +                                                                      guint * height);
> +
> + GST_EXPORT
> +-gboolean                gst_gl_context_check_framebuffer_status     (GstGLContext * context);
> ++gboolean                gst_gl_context_check_framebuffer_status     (GstGLContext * context,
> ++                                                                     GLenum fbo_target);
> +
> + GST_EXPORT
> + gboolean                gst_gl_framebuffer_draw_to_texture          (GstGLFramebuffer * fb,
> +diff --git a/gst-libs/gst/gl/gstglmemory.c b/gst-libs/gst/gl/gstglmemory.c
> +index 343a859..0cda68b 100644
> +--- a/gst-libs/gst/gl/gstglmemory.c
> ++++ b/gst-libs/gst/gl/gstglmemory.c
> +@@ -373,7 +373,7 @@ gst_gl_memory_read_pixels (GstGLMemory * gl_mem, gpointer read_pointer)
> +   gl->FramebufferTexture2D (GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
> +       gst_gl_texture_target_to_gl (gl_mem->tex_target), gl_mem->tex_id, 0);
> +
> +-  if (!gst_gl_context_check_framebuffer_status (context)) {
> ++  if (!gst_gl_context_check_framebuffer_status (context, GL_FRAMEBUFFER)) {
> +     GST_CAT_WARNING (GST_CAT_GL_MEMORY,
> +         "Could not create framebuffer to read pixels for memory %p", gl_mem);
> +     gl->DeleteFramebuffers (1, &fbo);
> +@@ -682,7 +682,7 @@ gst_gl_memory_copy_teximage (GstGLMemory * src, guint tex_id,
> +     gl->FramebufferTexture2D (GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
> +         gst_gl_texture_target_to_gl (src->tex_target), src_tex_id, 0);
> +
> +-    if (!gst_gl_context_check_framebuffer_status (src->mem.context))
> ++    if (!gst_gl_context_check_framebuffer_status (src->mem.context, GL_FRAMEBUFFER))
> +       goto fbo_error;
> +
> +     gl->BindTexture (out_tex_target, tex_id);
> +@@ -711,7 +711,7 @@ gst_gl_memory_copy_teximage (GstGLMemory * src, guint tex_id,
> +     gl->FramebufferTexture2D (GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
> +         gst_gl_texture_target_to_gl (src->tex_target), src_tex_id, 0);
> +
> +-    if (!gst_gl_context_check_framebuffer_status (src->mem.context))
> ++    if (!gst_gl_context_check_framebuffer_status (src->mem.context, GL_READ_FRAMEBUFFER))
> +       goto fbo_error;
> +
> +     gl->BindFramebuffer (GL_DRAW_FRAMEBUFFER, fbo[1]);
> +@@ -719,7 +719,7 @@ gst_gl_memory_copy_teximage (GstGLMemory * src, guint tex_id,
> +     gl->FramebufferTexture2D (GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
> +         gst_gl_texture_target_to_gl (src->tex_target), tex_id, 0);
> +
> +-    if (!gst_gl_context_check_framebuffer_status (src->mem.context))
> ++    if (!gst_gl_context_check_framebuffer_status (src->mem.context, GL_DRAW_FRAMEBUFFER))
> +       goto fbo_error;
> +
> +     gl->BindTexture (out_tex_target, tex_id);
> +--
> +1.9.1
> +
> diff --git a/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad/0027-qml-add-EGL-platform-support-for-x11-backend.patch b/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad/0027-qml-add-EGL-platform-support-for-x11-backend.patch
> new file mode 100644
> index 00000000..6adb5c91
> --- /dev/null
> +++ b/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad/0027-qml-add-EGL-platform-support-for-x11-backend.patch
> @@ -0,0 +1,63 @@
> +From bb75828b2d92a871b4b3da75cd5143f1a66fe229 Mon Sep 17 00:00:00 2001
> +From: Haihua Hu <jared.hu at nxp.com>
> +Date: Wed, 17 May 2017 10:58:05 +0800
> +Subject: [PATCH 20/24] qml:add EGL platform support for x11 backend
> +
> +Add support for EGL platform when x11 is available. This can work
> +eg. on imx6 platform.
> +
> +Upstream status: Backport[1.13.1]
> +https://bugzilla.gnome.org/show_bug.cgi?id=782718
> +---
> + configure.ac             |  2 +-
> + ext/qt/gstqtglutility.cc | 10 +++++++++-
> + 2 files changed, 10 insertions(+), 2 deletions(-)
> +
> +diff --git a/configure.ac b/configure.ac
> +index 2b71529..3f6f100 100644
> +--- a/configure.ac
> ++++ b/configure.ac
> +@@ -2948,7 +2948,7 @@ AG_GST_CHECK_FEATURE(QT, [Qt elements], qt, [
> +           QT_CFLAGS="$QT_CFLAGS -I$PKG_CONFIG_SYSROOT_DIR/$QPA_INCLUDE_PATH"
> +           HAVE_QT_QPA_HEADER="yes"
> +         ], [AC_MSG_NOTICE([Cannot find QPA])])
> +-        if test "x$GST_GL_HAVE_WINDOW_X11" = "x1" -a "x$GST_GL_HAVE_PLATFORM_GLX" = "x1"; then
> ++        if test "x$GST_GL_HAVE_WINDOW_X11" = "x1" -a "x$GST_GL_HAVE_PLATFORM_GLX" = "x1" || test "x$GST_GL_HAVE_WINDOW_X11" = "x1" -a "x$GST_GL_HAVE_PLATFORM_EGL" = "x1"; then
> +           PKG_CHECK_MODULES(QT_X11, Qt5X11Extras, [
> +             AC_DEFINE([HAVE_QT_X11], [], [Define if Qt X11 integration is installed])
> +             QT_CFLAGS="$QT_CFLAGS $QT_X11_CFLAGS"
> +diff --git a/ext/qt/gstqtglutility.cc b/ext/qt/gstqtglutility.cc
> +index a4b22aa..d0f7668 100644
> +--- a/ext/qt/gstqtglutility.cc
> ++++ b/ext/qt/gstqtglutility.cc
> +@@ -25,10 +25,14 @@
> + #include "gstqtglutility.h"
> + #include <QtGui/QGuiApplication>
> +
> +-#if GST_GL_HAVE_WINDOW_X11 && GST_GL_HAVE_PLATFORM_GLX && defined (HAVE_QT_X11)
> ++#if GST_GL_HAVE_WINDOW_X11 && defined (HAVE_QT_X11)
> + #include <QX11Info>
> + #include <gst/gl/x11/gstgldisplay_x11.h>
> ++#if GST_GL_HAVE_PLATFORM_GLX
> + #include <gst/gl/x11/gstglcontext_glx.h>
> ++#elif GST_GL_HAVE_PLATFORM_EGL
> ++#include <gst/gl/egl/gstglcontext_egl.h>
> ++#endif
> + #endif
> +
> + #if GST_GL_HAVE_WINDOW_WAYLAND && GST_GL_HAVE_PLATFORM_EGL && defined (HAVE_QT_WAYLAND)
> +@@ -151,7 +155,11 @@ gst_qt_get_gl_wrapcontext (GstGLDisplay * display,
> +
> + #if GST_GL_HAVE_WINDOW_X11 && defined (HAVE_QT_X11)
> +   if (GST_IS_GL_DISPLAY_X11 (display)) {
> ++#if GST_GL_HAVE_PLATFORM_GLX
> +     platform = GST_GL_PLATFORM_GLX;
> ++#elif GST_GL_HAVE_PLATFORM_EGL
> ++    platform = GST_GL_PLATFORM_EGL;
> ++#endif
> +   }
> + #endif
> + #if GST_GL_HAVE_WINDOW_WAYLAND && defined (HAVE_QT_WAYLAND)
> +--
> +1.9.1
> +
> diff --git a/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad/0028-kmssink-use-control-node-to-setplane-to-.patch b/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad/0028-kmssink-use-control-node-to-setplane-to-.patch
> new file mode 100644
> index 00000000..2edd5934
> --- /dev/null
> +++ b/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad/0028-kmssink-use-control-node-to-setplane-to-.patch
> @@ -0,0 +1,108 @@
> +From c2dd58fac7dc43280fab80d2234193993076665c Mon Sep 17 00:00:00 2001
> +From: Haihua Hu <jared.hu at nxp.com>
> +Date: Tue, 8 Aug 2017 12:55:42 +0800
> +Subject: [PATCH 1/3] [MMFMWK-7567] kmssink: use control node to setplane to
> + avoid getting DRM-Master
> +
> +a workaround on Linux 4.9 for kmssink multi-user
> +
> +Upstream-Status: Inappropriate [i.MX specific]
> +
> +Signed-off-by: Haihua Hu <jared.hu at nxp.com>
> +---
> + sys/kms/gstkmssink.c | 31 +++++++++++++++++++++++++++++--
> + sys/kms/gstkmssink.h |  1 +
> + 2 files changed, 30 insertions(+), 2 deletions(-)
> +
> +diff --git a/sys/kms/gstkmssink.c b/sys/kms/gstkmssink.c
> +index d19e19e..e91c211 100644
> +--- a/sys/kms/gstkmssink.c
> ++++ b/sys/kms/gstkmssink.c
> +@@ -51,6 +51,8 @@
> + #include <drm_fourcc.h>
> +
> + #include <string.h>
> ++#include <fcntl.h>
> ++#include <unistd.h>
> +
> + #include "gstkmssink.h"
> + #include "gstkmsutils.h"
> +@@ -485,6 +487,21 @@ ensure_allowed_caps (GstKMSSink * self, drmModeConnector * conn,
> +   return (self->allowed_caps && !gst_caps_is_empty (self->allowed_caps));
> + }
> +
> ++static gint
> ++get_drm_minor_base (gint type)
> ++{
> ++  switch (type) {
> ++    case DRM_NODE_PRIMARY:
> ++      return 0;
> ++    case DRM_NODE_CONTROL:
> ++      return 64;
> ++    case DRM_NODE_RENDER:
> ++      return 128;
> ++    default:
> ++      return -1;
> ++  }
> ++}
> ++
> + static gboolean
> + gst_kms_sink_start (GstBaseSink * bsink)
> + {
> +@@ -496,6 +513,7 @@ gst_kms_sink_start (GstBaseSink * bsink)
> +   drmModePlane *plane;
> +   gboolean universal_planes;
> +   gboolean ret;
> ++  gint minor;
> +
> +   self = GST_KMS_SINK (bsink);
> +   universal_planes = FALSE;
> +@@ -510,7 +528,11 @@ gst_kms_sink_start (GstBaseSink * bsink)
> +     self->fd = drmOpen (self->devname, NULL);
> +   else
> +     self->fd = kms_open (&self->devname);
> +-  if (self->fd < 0)
> ++
> ++  minor = get_drm_minor_base (DRM_NODE_CONTROL);
> ++  self->ctrl_fd = drmOpenControl(minor);
> ++
> ++  if (self->fd < 0 || self->ctrl_fd < 0)
> +     goto open_failed;
> +
> +   log_drm_version (self);
> +@@ -689,6 +711,11 @@ gst_kms_sink_stop (GstBaseSink * bsink)
> +     self->fd = -1;
> +   }
> +
> ++  if (self->ctrl_fd >= 0) {
> ++    drmClose (self->ctrl_fd);
> ++    self->ctrl_fd = -1;
> ++  }
> ++
> +   return TRUE;
> + }
> +
> +@@ -1278,7 +1305,7 @@ retry_set_plane:
> +       "drmModeSetPlane at (%i,%i) %ix%i sourcing at (%i,%i) %ix%i",
> +       result.x, result.y, result.w, result.h, src.x, src.y, src.w, src.h);
> +
> +-  ret = drmModeSetPlane (self->fd, self->plane_id, self->crtc_id, fb_id, 0,
> ++  ret = drmModeSetPlane (self->ctrl_fd, self->plane_id, self->crtc_id, fb_id, 0,
> +       result.x, result.y, result.w, result.h,
> +       /* source/cropping coordinates are given in Q16 */
> +       src.x << 16, src.y << 16, src.w << 16, src.h << 16);
> +diff --git a/sys/kms/gstkmssink.h b/sys/kms/gstkmssink.h
> +index 214f3ad..f2ab4d4 100644
> +--- a/sys/kms/gstkmssink.h
> ++++ b/sys/kms/gstkmssink.h
> +@@ -49,6 +49,7 @@ struct _GstKMSSink {
> +
> +   /*< private >*/
> +   gint fd;
> ++  gint ctrl_fd;
> +   gint conn_id;
> +   gint crtc_id;
> +   gint plane_id;
> +--
> +1.9.1
> +
> diff --git a/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad/0029-kmssink-support-videooverlay-interface.patch b/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad/0029-kmssink-support-videooverlay-interface.patch
> new file mode 100644
> index 00000000..7bf995f9
> --- /dev/null
> +++ b/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad/0029-kmssink-support-videooverlay-interface.patch
> @@ -0,0 +1,343 @@
> +From a1affa1293e31870d6fb9dda85e4c648cc4dd247 Mon Sep 17 00:00:00 2001
> +From: Haihua Hu <jared.hu at nxp.com>
> +Date: Tue, 20 Jun 2017 13:11:27 +0800
> +Subject: [PATCH 2/3] [MMFMWK-7567] kmssink: support videooverlay interface
> +
> +Implement videooverlay interface in kmssink, divided into two cases:
> +when driver supports scale, then we do refresh in show_frame(); if
> +not, send a reconfigure event to upstream and re-negotiate, using the
> +new size.
> +
> +Upstream-Status: Backport [1.13.1]
> +https://bugzilla.gnome.org/show_bug.cgi?id=784599
> +---
> + sys/kms/gstkmssink.c | 164 ++++++++++++++++++++++++++++++++++++++++++++++++---
> + sys/kms/gstkmssink.h |  12 ++++
> + 2 files changed, 167 insertions(+), 9 deletions(-)
> +
> +diff --git a/sys/kms/gstkmssink.c b/sys/kms/gstkmssink.c
> +index e91c211..6d9b765 100644
> +--- a/sys/kms/gstkmssink.c
> ++++ b/sys/kms/gstkmssink.c
> +@@ -43,6 +43,7 @@
> + #endif
> +
> + #include <gst/video/video.h>
> ++#include <gst/video/videooverlay.h>
> + #include <gst/allocators/gstdmabuf.h>
> +
> + #include <drm.h>
> +@@ -66,11 +67,17 @@ GST_DEBUG_CATEGORY_STATIC (gst_kms_sink_debug);
> + GST_DEBUG_CATEGORY_STATIC (CAT_PERFORMANCE);
> + #define GST_CAT_DEFAULT gst_kms_sink_debug
> +
> ++static GstFlowReturn gst_kms_sink_show_frame (GstVideoSink * vsink,
> ++    GstBuffer * buf);
> ++static void gst_kms_sink_video_overlay_init (GstVideoOverlayInterface * iface);
> ++
> + #define parent_class gst_kms_sink_parent_class
> + G_DEFINE_TYPE_WITH_CODE (GstKMSSink, gst_kms_sink, GST_TYPE_VIDEO_SINK,
> +     GST_DEBUG_CATEGORY_INIT (GST_CAT_DEFAULT, GST_PLUGIN_NAME, 0,
> +         GST_PLUGIN_DESC);
> +-    GST_DEBUG_CATEGORY_GET (CAT_PERFORMANCE, "GST_PERFORMANCE"));
> ++    GST_DEBUG_CATEGORY_GET (CAT_PERFORMANCE, "GST_PERFORMANCE");
> ++    G_IMPLEMENT_INTERFACE (GST_TYPE_VIDEO_OVERLAY,
> ++        gst_kms_sink_video_overlay_init));
> +
> + enum
> + {
> +@@ -83,6 +90,79 @@ enum
> +
> + static GParamSpec *g_properties[PROP_N] = { NULL, };
> +
> ++static void
> ++gst_kms_sink_set_render_rectangle (GstVideoOverlay * overlay,
> ++    gint x, gint y, gint width, gint height)
> ++{
> ++  GstKMSSink *self = GST_KMS_SINK (overlay);
> ++
> ++  if (width <= 0 || height <= 0) {
> ++    if (width == -1 && height == -1) {
> ++      x = 0;
> ++      y = 0;
> ++      width = self->hdisplay;
> ++      height = self->vdisplay;
> ++      goto commit;
> ++    }
> ++    return;
> ++  }
> ++
> ++commit:
> ++  GST_OBJECT_LOCK (self);
> ++  if (self->can_scale) {
> ++    self->preferred_rect.x = x;
> ++    self->preferred_rect.y = y;
> ++    self->preferred_rect.w = width;
> ++    self->preferred_rect.h = height;
> ++  } else {
> ++    GstVideoRectangle src = { 0, };
> ++    GstVideoRectangle dst = { 0, };
> ++    GstVideoRectangle result;
> ++
> ++    src.w = self->original_width;
> ++    src.h = self->original_heigth;
> ++
> ++    dst.w = width;
> ++    dst.h = height;
> ++
> ++    gst_video_sink_center_rect (src, dst, &result, TRUE);
> ++
> ++    self->pending_rect.x = x + result.x;
> ++    self->pending_rect.y = y + result.y;
> ++    self->pending_rect.w = result.w;
> ++    self->pending_rect.h = result.h;
> ++
> ++    GST_DEBUG_OBJECT (self, "pending resize to (%d,%d)-(%dx%d)",
> ++        self->pending_rect.x, self->pending_rect.y,
> ++        self->pending_rect.w, self->pending_rect.h);
> ++  }
> ++  GST_OBJECT_UNLOCK (self);
> ++}
> ++
> ++static void
> ++gst_kms_sink_expose (GstVideoOverlay * overlay)
> ++{
> ++  GstKMSSink *self = GST_KMS_SINK (overlay);
> ++
> ++  if (self->can_scale) {
> ++    gst_kms_sink_show_frame (GST_VIDEO_SINK (self), NULL);
> ++  } else {
> ++    GST_OBJECT_LOCK (self);
> ++    self->reconfigure = TRUE;
> ++    GST_OBJECT_UNLOCK (self);
> ++
> ++    gst_pad_push_event (GST_BASE_SINK (self)->sinkpad,
> ++        gst_event_new_reconfigure ());
> ++  }
> ++}
> ++
> ++static void
> ++gst_kms_sink_video_overlay_init (GstVideoOverlayInterface * iface)
> ++{
> ++  iface->expose = gst_kms_sink_expose;
> ++  iface->set_render_rectangle = gst_kms_sink_set_render_rectangle;
> ++}
> ++
> + static int
> + kms_open (gchar ** driver)
> + {
> +@@ -539,7 +619,7 @@ gst_kms_sink_start (GstBaseSink * bsink)
> +   if (!get_drm_caps (self))
> +     goto bail;
> +
> +-  self->can_scale = TRUE;
> ++  //self->can_scale = TRUE;
> +
> +   res = drmModeGetResources (self->fd);
> +   if (!res)
> +@@ -588,8 +668,10 @@ retry_find_plane:
> +   GST_INFO_OBJECT (self, "connector id = %d / crtc id = %d / plane id = %d",
> +       self->conn_id, self->crtc_id, self->plane_id);
> +
> +-  self->hdisplay = crtc->mode.hdisplay;
> +-  self->vdisplay = crtc->mode.vdisplay;
> ++  self->preferred_rect.x = 0;
> ++  self->preferred_rect.y = 0;
> ++  self->hdisplay = self->preferred_rect.w = crtc->mode.hdisplay;
> ++  self->vdisplay = self->preferred_rect.h = crtc->mode.vdisplay;
> +   self->buffer_id = crtc->buffer_id;
> +
> +   self->mm_width = conn->mmWidth;
> +@@ -602,6 +684,9 @@ retry_find_plane:
> +   gst_poll_add_fd (self->poll, &self->pollfd);
> +   gst_poll_fd_ctl_read (self->poll, &self->pollfd, TRUE);
> +
> ++  self->original_width = -1;
> ++  self->original_heigth = -1;
> ++
> +   ret = TRUE;
> +
> + bail:
> +@@ -731,17 +816,29 @@ static GstCaps *
> + gst_kms_sink_get_caps (GstBaseSink * bsink, GstCaps * filter)
> + {
> +   GstKMSSink *self;
> +-  GstCaps *caps, *out_caps;
> ++  GstCaps *caps, *out_caps, *tmp;
> +
> +   self = GST_KMS_SINK (bsink);
> +
> +   caps = gst_kms_sink_get_allowed_caps (self);
> ++
> ++  GST_OBJECT_LOCK (self);
> ++  if (caps && self->reconfigure) {
> ++    tmp = gst_caps_copy (caps);
> ++    gst_caps_set_simple (tmp, "width", G_TYPE_INT, self->pending_rect.w,
> ++        "height", G_TYPE_INT, self->pending_rect.h, NULL);
> ++    gst_caps_append (tmp, caps);
> ++    caps = tmp;
> ++  }
> ++  GST_OBJECT_UNLOCK (self);
> ++
> +   if (caps && filter) {
> +     out_caps = gst_caps_intersect_full (caps, filter, GST_CAPS_INTERSECT_FIRST);
> +     gst_caps_unref (caps);
> +   } else {
> +     out_caps = caps;
> +   }
> ++  GST_DEBUG_OBJECT (self, "out caps %" GST_PTR_FORMAT, out_caps);
> +
> +   return out_caps;
> + }
> +@@ -880,6 +977,19 @@ gst_kms_sink_set_caps (GstBaseSink * bsink, GstCaps * caps)
> +
> +   self->vinfo = vinfo;
> +
> ++  GST_OBJECT_LOCK (self);
> ++  if (self->reconfigure) {
> ++    self->reconfigure = FALSE;
> ++    self->preferred_rect = self->pending_rect;
> ++  }
> ++  GST_OBJECT_UNLOCK (self);
> ++
> ++  /* initialize original video size */
> ++  if (self->original_width < 0) {
> ++    self->original_width = GST_VIDEO_INFO_WIDTH (&self->vinfo);
> ++    self->original_heigth = GST_VIDEO_INFO_HEIGHT (&self->vinfo);
> ++  }
> ++
> +   GST_DEBUG_OBJECT (self, "negotiated caps = %" GST_PTR_FORMAT, caps);
> +
> +   return TRUE;
> +@@ -1258,7 +1368,13 @@ gst_kms_sink_show_frame (GstVideoSink * vsink, GstBuffer * buf)
> +
> +   res = GST_FLOW_ERROR;
> +
> +-  buffer = gst_kms_sink_get_input_buffer (self, buf);
> ++  buffer = NULL;
> ++
> ++  if (buf)
> ++    buffer = gst_kms_sink_get_input_buffer (self, buf);
> ++  else if (self->last_buffer)
> ++    buffer = gst_buffer_ref (self->last_buffer);
> ++
> +   if (!buffer)
> +     return GST_FLOW_ERROR;
> +   fb_id = gst_kms_memory_get_fb_id (gst_buffer_peek_memory (buffer, 0));
> +@@ -1267,6 +1383,7 @@ gst_kms_sink_show_frame (GstVideoSink * vsink, GstBuffer * buf)
> +
> +   GST_TRACE_OBJECT (self, "displaying fb %d", fb_id);
> +
> ++  GST_OBJECT_LOCK (self);
> +   if (self->modesetting_enabled) {
> +     self->buffer_id = fb_id;
> +     goto sync_frame;
> +@@ -1287,12 +1404,15 @@ gst_kms_sink_show_frame (GstVideoSink * vsink, GstBuffer * buf)
> +   src.w = GST_VIDEO_SINK_WIDTH (self);
> +   src.h = GST_VIDEO_SINK_HEIGHT (self);
> +
> +-  dst.w = self->hdisplay;
> +-  dst.h = self->vdisplay;
> ++  dst.w = self->preferred_rect.w;
> ++  dst.h = self->preferred_rect.h;
> +
> + retry_set_plane:
> +   gst_video_sink_center_rect (src, dst, &result, self->can_scale);
> +
> ++  result.x += self->preferred_rect.x;
> ++  result.y += self->preferred_rect.y;
> ++
> +   if (crop) {
> +     src.w = crop->width;
> +     src.h = crop->height;
> +@@ -1301,6 +1421,27 @@ retry_set_plane:
> +     src.h = GST_VIDEO_INFO_HEIGHT (&self->vinfo);
> +   }
> +
> ++  /* handle out of screen case */
> ++  if ((result.x + result.w) > self->hdisplay)
> ++    src.w = self->hdisplay - result.x;
> ++
> ++  if ((result.y + result.h) > self->vdisplay)
> ++    src.h = self->vdisplay - result.y;
> ++
> ++  if (src.w <= 0 || src.h <= 0) {
> ++    GST_WARNING_OBJECT (self, "video is out of display range");
> ++    goto sync_frame;
> ++  }
> ++  GST_TRACE_OBJECT (self,
> ++      "before drmModeSetPlane at (%i,%i) %ix%i sourcing at (%i,%i) %ix%i",
> ++      result.x, result.y, result.w, result.h, src.x, src.y, src.w, src.h);
> ++
> ++  /* to make sure it can be show when driver don't support scale */
> ++  if (!self->can_scale) {
> ++    result.w = src.w;
> ++    result.h = src.h;
> ++  }
> ++
> +   GST_TRACE_OBJECT (self,
> +       "drmModeSetPlane at (%i,%i) %ix%i sourcing at (%i,%i) %ix%i",
> +       result.x, result.y, result.w, result.h, src.x, src.y, src.w, src.h);
> +@@ -1322,9 +1463,11 @@ sync_frame:
> +   if (!gst_kms_sink_sync (self))
> +     goto bail;
> +
> +-  gst_buffer_replace (&self->last_buffer, buffer);
> ++  if (buffer != self->last_buffer)
> ++    gst_buffer_replace (&self->last_buffer, buffer);
> +   g_clear_pointer (&self->tmp_kmsmem, gst_memory_unref);
> +
> ++  GST_OBJECT_UNLOCK (self);
> +   res = GST_FLOW_OK;
> +
> + bail:
> +@@ -1339,6 +1482,7 @@ buffer_invalid:
> +   }
> + set_plane_failed:
> +   {
> ++    GST_OBJECT_UNLOCK (self);
> +     GST_DEBUG_OBJECT (self, "result = { %d, %d, %d, %d} / "
> +         "src = { %d, %d, %d %d } / dst = { %d, %d, %d %d }", result.x, result.y,
> +         result.w, result.h, src.x, src.y, src.w, src.h, dst.x, dst.y, dst.w,
> +@@ -1349,6 +1493,7 @@ set_plane_failed:
> +   }
> + no_disp_ratio:
> +   {
> ++    GST_OBJECT_UNLOCK (self);
> +     GST_ELEMENT_ERROR (self, CORE, NEGOTIATION, (NULL),
> +         ("Error calculating the output display ratio of the video."));
> +     goto bail;
> +@@ -1427,6 +1572,7 @@ gst_kms_sink_init (GstKMSSink * sink)
> +   sink->fd = -1;
> +   sink->conn_id = -1;
> +   sink->plane_id = -1;
> ++  sink->can_scale = TRUE;
> +   gst_poll_fd_init (&sink->pollfd);
> +   sink->poll = gst_poll_new (TRUE);
> +   gst_video_info_init (&sink->vinfo);
> +diff --git a/sys/kms/gstkmssink.h b/sys/kms/gstkmssink.h
> +index f2ab4d4..44476e1 100644
> +--- a/sys/kms/gstkmssink.h
> ++++ b/sys/kms/gstkmssink.h
> +@@ -79,6 +79,18 @@ struct _GstKMSSink {
> +
> +   GstPoll *poll;
> +   GstPollFD pollfd;
> ++
> ++  /* preferred video rectangle */
> ++  GstVideoRectangle preferred_rect;
> ++
> ++  /* reconfigure info if driver doesn't scale */
> ++  GstVideoRectangle pending_rect;
> ++  gboolean reconfigure;
> ++
> ++  /* kept original video size */
> ++  gint original_width;
> ++  gint original_heigth;
> ++
> + };
> +
> + struct _GstKMSSinkClass {
> +--
> +1.9.1
> +
> diff --git a/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad/0030-kmssink-check-scaleable-when-set_caps.patch b/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad/0030-kmssink-check-scaleable-when-set_caps.patch
> new file mode 100644
> index 00000000..691ac849
> --- /dev/null
> +++ b/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad/0030-kmssink-check-scaleable-when-set_caps.patch
> @@ -0,0 +1,74 @@
> +From b1886be721be792c98f17af31dd8c144754e05be Mon Sep 17 00:00:00 2001
> +From: Haihua Hu <jared.hu at nxp.com>
> +Date: Wed, 12 Jul 2017 10:17:18 +0800
> +Subject: [PATCH 3/3] [MMFMWK-7567] kmssink: check scaleable when set_caps
> +
> +when video size is same as display resolution, show frame will not do
> +retry because the setplane will never fail. But the scale result is not
> +correct. We can do this check by set a fake plane.
> +
> +Upstream-Status: Inappropriate [i.MX specific]
> +
> +---
> + sys/kms/gstkmssink.c | 38 ++++++++++++++++++++++++++++++++++++++
> + 1 file changed, 38 insertions(+)
> +
> +diff --git a/sys/kms/gstkmssink.c b/sys/kms/gstkmssink.c
> +index 6d9b765..65fdc4f 100644
> +--- a/sys/kms/gstkmssink.c
> ++++ b/sys/kms/gstkmssink.c
> +@@ -402,6 +402,42 @@ get_drm_caps (GstKMSSink * self)
> +   return TRUE;
> + }
> +
> ++static void
> ++check_scaleable (GstKMSSink * self)
> ++{
> ++  gint result;
> ++  guint32 fb_id;
> ++  guint32 width, height;
> ++  GstKMSMemory *kmsmem = NULL;
> ++
> ++  if (!self->can_scale)
> ++    return;
> ++
> ++  if (self->conn_id < 0)
> ++    return;
> ++
> ++  kmsmem = (GstKMSMemory *) gst_kms_allocator_bo_alloc (self->allocator, &self->vinfo);
> ++  if (!kmsmem)
> ++    return;
> ++
> ++  fb_id = kmsmem->fb_id;
> ++
> ++  GST_INFO_OBJECT (self, "checking scaleable");
> ++
> ++  width = GST_VIDEO_INFO_WIDTH (&self->vinfo);
> ++  height = GST_VIDEO_INFO_HEIGHT (&self->vinfo);
> ++
> ++  result = drmModeSetPlane (self->fd, self->plane_id, self->crtc_id, fb_id, 0,
> ++      0, 0, width/2, height/2,
> ++      0, 0, width << 16, height << 16);
> ++  if (result) {
> ++    self->can_scale = FALSE;
> ++    GST_INFO_OBJECT (self, "scale is not support");
> ++  }
> ++
> ++  g_clear_pointer (&kmsmem, gst_memory_unref);
> ++}
> ++
> + static gboolean
> + configure_mode_setting (GstKMSSink * self, GstVideoInfo * vinfo)
> + {
> +@@ -977,6 +1013,8 @@ gst_kms_sink_set_caps (GstBaseSink * bsink, GstCaps * caps)
> +
> +   self->vinfo = vinfo;
> +
> ++  check_scaleable (self);
> ++
> +   GST_OBJECT_LOCK (self);
> +   if (self->reconfigure) {
> +     self->reconfigure = FALSE;
> +--
> +1.9.1
> +
> diff --git a/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad/0031-glimagesink-fix-segmentation-fault-when-.patch b/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad/0031-glimagesink-fix-segmentation-fault-when-.patch
> new file mode 100644
> index 00000000..cbec6d13
> --- /dev/null
> +++ b/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad/0031-glimagesink-fix-segmentation-fault-when-.patch
> @@ -0,0 +1,35 @@
> +From dcaf27575e66a34a60255ddd59ddfc75f1c196c7 Mon Sep 17 00:00:00 2001
> +From: Haihua Hu <jared.hu at nxp.com>
> +Date: Tue, 5 Sep 2017 12:48:56 +0800
> +Subject: [PATCH] [MMFMWK-7700] glimagesink: fix segmentation fault when stop
> + glimagesink wayland
> +
> +eglTerminate call is integrated into GstGLDisplyEGL, GstGLDisplayWayland
> +will hold an instance of GstGLDisplyEGL when egl context call to
> +gst_gl_display_egl_from_gl_display. When we unref GstGLDisplayWayland,
> +first clean the hold instance GstGLDisplyEGL and then do disconnect
> +
> +Upstream-Status: Backport [1.13.1]
> +https://bugzilla.gnome.org/show_bug.cgi?id=787293
> +---
> + gst-libs/gst/gl/wayland/gstgldisplay_wayland.c | 4 ++++
> + 1 file changed, 4 insertions(+)
> +
> +diff --git a/gst-libs/gst/gl/wayland/gstgldisplay_wayland.c b/gst-libs/gst/gl/wayland/gstgldisplay_wayland.c
> +index e466fb4..c3e902d 100644
> +--- a/gst-libs/gst/gl/wayland/gstgldisplay_wayland.c
> ++++ b/gst-libs/gst/gl/wayland/gstgldisplay_wayland.c
> +@@ -91,6 +91,10 @@ gst_gl_display_wayland_finalize (GObject * object)
> + {
> +   GstGLDisplayWayland *display_wayland = GST_GL_DISPLAY_WAYLAND (object);
> +
> ++  /* Cause eglTerminate() to occur before wl_display_disconnect()
> ++   * https://bugzilla.gnome.org/show_bug.cgi?id=787293 */
> ++  g_object_set_data (object, "gst.gl.display.egl", NULL);
> ++
> +   if (!display_wayland->foreign_display && display_wayland->display) {
> +     wl_display_flush (display_wayland->display);
> +     wl_display_disconnect (display_wayland->display);
> +--
> +1.9.1
> +
> diff --git a/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad/0032-gl-viv-fb-fix-wrong-pos-x-y-calculate-in.patch b/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad/0032-gl-viv-fb-fix-wrong-pos-x-y-calculate-in.patch
> new file mode 100644
> index 00000000..9eef87e9
> --- /dev/null
> +++ b/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad/0032-gl-viv-fb-fix-wrong-pos-x-y-calculate-in.patch
> @@ -0,0 +1,52 @@
> +From b2f9859ec9170ed8aba88df4bf29c0b235b6aa07 Mon Sep 17 00:00:00 2001
> +From: Haihua Hu <jared.hu at nxp.com>
> +Date: Mon, 11 Sep 2017 15:12:53 +0800
> +Subject: [PATCH 1/3] [MMFMWK-7707] gl/viv-fb: fix wrong pos (x,y) calculate in
> + queue_resize
> +
> +queue_resize viewport coordinate calculate is wrong and
> +force queue_resize when do _set_render_rectangle in case
> +user input pos changed
> +
> +Upstream-Status: Backport [1.13.1]
> +https://bugzilla.gnome.org/show_bug.cgi?id=787394
> +---
> + gst-libs/gst/gl/viv-fb/gstglwindow_viv_fb_egl.c | 10 +++++-----
> + 1 file changed, 5 insertions(+), 5 deletions(-)
> +
> +diff --git a/gst-libs/gst/gl/viv-fb/gstglwindow_viv_fb_egl.c b/gst-libs/gst/gl/viv-fb/gstglwindow_viv_fb_egl.c
> +index f8fb638..14d9997 100644
> +--- a/gst-libs/gst/gl/viv-fb/gstglwindow_viv_fb_egl.c
> ++++ b/gst-libs/gst/gl/viv-fb/gstglwindow_viv_fb_egl.c
> +@@ -174,9 +174,7 @@ draw_cb (gpointer data)
> +
> +     gl->GetIntegerv (GL_VIEWPORT, viewport_dim);
> +     viewport_dim[0] += window_egl->render_rectangle.x;
> +-    viewport_dim[1] -= window_egl->render_rectangle.y;
> +-    viewport_dim[2] -= window_egl->render_rectangle.x;
> +-    viewport_dim[3] -= window_egl->render_rectangle.y;
> ++    viewport_dim[1] += window_egl->render_rectangle.y;
> +     gl->Viewport (viewport_dim[0],
> +         viewport_dim[1], viewport_dim[2], viewport_dim[3]);
> +   }
> +@@ -215,13 +213,15 @@ static void
> + _set_render_rectangle (gpointer data)
> + {
> +   SetRenderRectangleData *render = data;
> ++  GstGLWindow *window = GST_GL_WINDOW (render->window_egl);
> +
> +   GST_LOG_OBJECT (render->window_egl, "setting render rectangle %i,%i+%ix%i",
> +       render->rect.x, render->rect.y, render->rect.w, render->rect.h);
> +
> +   render->window_egl->render_rectangle = render->rect;
> +-  gst_gl_window_resize (GST_GL_WINDOW (render->window_egl), render->rect.w,
> +-      render->rect.h);
> ++  gst_gl_window_resize (window, render->rect.w, render->rect.h);
> ++
> ++  window->queue_resize = TRUE;
> + }
> +
> + static gboolean
> +--
> +1.9.1
> +
> diff --git a/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad/0033-gl-viv-fb-transform-screen-coordinate-to.patch b/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad/0033-gl-viv-fb-transform-screen-coordinate-to.patch
> new file mode 100644
> index 00000000..3fd9f142
> --- /dev/null
> +++ b/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad/0033-gl-viv-fb-transform-screen-coordinate-to.patch
> @@ -0,0 +1,52 @@
> +From eb552ac9f5cb457de11d4da8214982de4ad35283 Mon Sep 17 00:00:00 2001
> +From: Haihua Hu <jared.hu at nxp.com>
> +Date: Mon, 11 Sep 2017 16:00:24 +0800
> +Subject: [PATCH 2/3] [MMFMWK-7707]gl/viv-fb: transform screen coordinate to
> + viewport coordinate
> +
> +In y direction, screen coordinate are opposite to viewport coordinate.
> +
> +Upstream-Status: Backport [1.13.1]
> +https://bugzilla.gnome.org/show_bug.cgi?id=787394
> +---
> + gst-libs/gst/gl/viv-fb/gstglwindow_viv_fb_egl.c | 17 +++++++++++++++--
> + 1 file changed, 15 insertions(+), 2 deletions(-)
> +
> +diff --git a/gst-libs/gst/gl/viv-fb/gstglwindow_viv_fb_egl.c b/gst-libs/gst/gl/viv-fb/gstglwindow_viv_fb_egl.c
> +index 14d9997..e1a3fd3 100644
> +--- a/gst-libs/gst/gl/viv-fb/gstglwindow_viv_fb_egl.c
> ++++ b/gst-libs/gst/gl/viv-fb/gstglwindow_viv_fb_egl.c
> +@@ -210,15 +210,28 @@ _free_set_render_rectangle (SetRenderRectangleData * render)
> + }
> +
> + static void
> ++_calculate_viewport_coordinates(GstGLWindowVivFBEGL * window_egl,
> ++    GstVideoRectangle * req, GstVideoRectangle * result)
> ++{
> ++  result->x = req->x;
> ++  result->y = window_egl->window_height - (req->y + req->h);
> ++  result->w = req->w;
> ++  result->h = req->h;
> ++}
> ++
> ++static void
> + _set_render_rectangle (gpointer data)
> + {
> +   SetRenderRectangleData *render = data;
> +-  GstGLWindow *window = GST_GL_WINDOW (render->window_egl);
> ++  GstGLWindowVivFBEGL *window_egl = render->window_egl;
> ++  GstGLWindow *window = GST_GL_WINDOW (window_egl);
> +
> +   GST_LOG_OBJECT (render->window_egl, "setting render rectangle %i,%i+%ix%i",
> +       render->rect.x, render->rect.y, render->rect.w, render->rect.h);
> +
> +-  render->window_egl->render_rectangle = render->rect;
> ++  _calculate_viewport_coordinates (window_egl, &render->rect,
> ++      &window_egl->render_rectangle);
> ++
> +   gst_gl_window_resize (window, render->rect.w, render->rect.h);
> +
> +   window->queue_resize = TRUE;
> +--
> +1.9.1
> +
> diff --git a/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad/0034-glimagesink-expose-should-do-redisplay-a.patch b/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad/0034-glimagesink-expose-should-do-redisplay-a.patch
> new file mode 100644
> index 00000000..9226727b
> --- /dev/null
> +++ b/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad/0034-glimagesink-expose-should-do-redisplay-a.patch
> @@ -0,0 +1,37 @@
> +From 5f355f75a93bce1fc445bd6cce8b6f608c19902c Mon Sep 17 00:00:00 2001
> +From: Haihua Hu <jared.hu at nxp.com>
> +Date: Mon, 11 Sep 2017 16:11:19 +0800
> +Subject: [PATCH 3/3] [MMFMWK-7707] glimagesink: expose should do redisplay all
> + the time
> +
> +when using internal window, window resize should work
> +when pause state, but expose only do redisplay when
> +window_id is valid. So expose should do redisplay all
> +the time.
> +
> +Upstream-Status: Backport [1.13.1]
> +https://bugzilla.gnome.org/show_bug.cgi?id=787394
> +---
> + ext/gl/gstglimagesink.c | 6 +++---
> + 1 file changed, 3 insertions(+), 3 deletions(-)
> +
> +diff --git a/ext/gl/gstglimagesink.c b/ext/gl/gstglimagesink.c
> +index e697bd0..b8a9971 100644
> +--- a/ext/gl/gstglimagesink.c
> ++++ b/ext/gl/gstglimagesink.c
> +@@ -1814,9 +1814,9 @@ gst_glimage_sink_expose (GstVideoOverlay * overlay)
> +   GstGLImageSink *glimage_sink = GST_GLIMAGE_SINK (overlay);
> +
> +   /* redisplay opengl scene */
> +-  if (glimage_sink->display && glimage_sink->window_id) {
> +-
> +-    if (glimage_sink->window_id != glimage_sink->new_window_id) {
> ++  if (glimage_sink->display) {
> ++    if (glimage_sink->window_id
> ++        && glimage_sink->window_id != glimage_sink->new_window_id) {
> +       GstGLWindow *window = gst_gl_context_get_window (glimage_sink->context);
> +
> +       glimage_sink->window_id = glimage_sink->new_window_id;
> +--
> +1.9.1
> +
> diff --git a/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad/0035-videoaggregator-passthrough-interlace-mo.patch b/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad/0035-videoaggregator-passthrough-interlace-mo.patch
> new file mode 100644
> index 00000000..3084ba57
> --- /dev/null
> +++ b/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad/0035-videoaggregator-passthrough-interlace-mo.patch
> @@ -0,0 +1,99 @@
> +From ed7ce121daa3c5fdfa8d32eeff30c4fb7332017b Mon Sep 17 00:00:00 2001
> +From: Haihua Hu <jared.hu at nxp.com>
> +Date: Mon, 18 Sep 2017 15:11:41 +0800
> +Subject: [PATCH 1/2] [MMFMWK-7736] videoaggregator: passthrough interlace mode
> + when update src caps
> +
> +Upstream-Status: Pending
> +https://bugzilla.gnome.org/show_bug.cgi?id=787819
> +---
> + gst-libs/gst/video/gstvideoaggregator.c | 59 ++++++++++++++++++++++-----------
> + 1 file changed, 39 insertions(+), 20 deletions(-)
> +
> +diff --git a/gst-libs/gst/video/gstvideoaggregator.c b/gst-libs/gst/video/gstvideoaggregator.c
> +index a987c15..246ff8b 100644
> +--- a/gst-libs/gst/video/gstvideoaggregator.c
> ++++ b/gst-libs/gst/video/gstvideoaggregator.c
> +@@ -691,6 +691,26 @@ gst_video_aggregator_default_update_caps (GstVideoAggregator * vagg,
> +   return ret;
> + }
> +
> ++static gboolean
> ++gst_video_aggregator_get_sinkpads_interlace_mode (GstVideoAggregator * vagg,
> ++    GstVideoAggregatorPad * skip_pad, GstVideoInterlaceMode * mode)
> ++{
> ++  GList *walk;
> ++
> ++  for (walk = GST_ELEMENT (vagg)->sinkpads; walk; walk = g_list_next (walk)) {
> ++    GstVideoAggregatorPad *vaggpad = walk->data;
> ++
> ++    if (skip_pad && vaggpad == skip_pad)
> ++      continue;
> ++    if (vaggpad->info.finfo
> ++        && GST_VIDEO_INFO_FORMAT (&vaggpad->info) != GST_VIDEO_FORMAT_UNKNOWN) {
> ++      *mode = GST_VIDEO_INFO_INTERLACE_MODE (&vaggpad->info);
> ++      return TRUE;
> ++    }
> ++  }
> ++  return FALSE;
> ++}
> ++
> + /* WITH GST_VIDEO_AGGREGATOR_LOCK TAKEN */
> + static gboolean
> + gst_video_aggregator_update_src_caps (GstVideoAggregator * vagg)
> +@@ -787,6 +807,25 @@ gst_video_aggregator_update_src_caps (GstVideoAggregator * vagg)
> +       }
> +     }
> +
> ++    /* configure for interlace mode, we can only pass through interlace mode */
> ++    {
> ++      GstVideoInterlaceMode interlace_mode = GST_VIDEO_INTERLACE_MODE_PROGRESSIVE;
> ++      gboolean has_mode = FALSE;
> ++      GstStructure *s;
> ++      guint i, n;
> ++      has_mode =
> ++          gst_video_aggregator_get_sinkpads_interlace_mode (vagg, NULL,
> ++          &interlace_mode);
> ++
> ++      n = gst_caps_get_size (caps);
> ++      for (i = 0; i < n; i++) {
> ++        s = gst_caps_get_structure (caps, i);
> ++        if (has_mode)
> ++          gst_structure_set (s, "interlace-mode", G_TYPE_STRING,
> ++              gst_video_interlace_mode_to_string (interlace_mode), NULL);
> ++      }
> ++    }
> ++
> +     gst_video_info_from_caps (&vagg->info, caps);
> +
> +     if (vaggpad_klass->set_info) {
> +@@ -820,26 +859,6 @@ done:
> + }
> +
> + static gboolean
> +-gst_video_aggregator_get_sinkpads_interlace_mode (GstVideoAggregator * vagg,
> +-    GstVideoAggregatorPad * skip_pad, GstVideoInterlaceMode * mode)
> +-{
> +-  GList *walk;
> +-
> +-  for (walk = GST_ELEMENT (vagg)->sinkpads; walk; walk = g_list_next (walk)) {
> +-    GstVideoAggregatorPad *vaggpad = walk->data;
> +-
> +-    if (skip_pad && vaggpad == skip_pad)
> +-      continue;
> +-    if (vaggpad->info.finfo
> +-        && GST_VIDEO_INFO_FORMAT (&vaggpad->info) != GST_VIDEO_FORMAT_UNKNOWN) {
> +-      *mode = GST_VIDEO_INFO_INTERLACE_MODE (&vaggpad->info);
> +-      return TRUE;
> +-    }
> +-  }
> +-  return FALSE;
> +-}
> +-
> +-static gboolean
> + gst_video_aggregator_pad_sink_setcaps (GstPad * pad, GstObject * parent,
> +     GstCaps * caps)
> + {
> +--
> +1.9.1
> +
> diff --git a/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad/0036-glvideomixer-need-update-output-geometry.patch b/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad/0036-glvideomixer-need-update-output-geometry.patch
> new file mode 100644
> index 00000000..fe10d749
> --- /dev/null
> +++ b/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad/0036-glvideomixer-need-update-output-geometry.patch
> @@ -0,0 +1,83 @@
> +From fb4d28d491a8949cd78329ec30a0bffea6d2bb91 Mon Sep 17 00:00:00 2001
> +From: Haihua Hu <jared.hu at nxp.com>
> +Date: Mon, 18 Sep 2017 15:42:00 +0800
> +Subject: [PATCH 2/2] [MMFMWK-7736] glvideomixer: need update output geometry
> + after src caps reconfigure
> +
> +Need update output geometry when sink caps changed and use
> +gst_structure_set to update caps if structure is fixed
> +
> +Upstream-Status: Pending
> +https://bugzilla.gnome.org/show_bug.cgi?id=787820
> +---
> + ext/gl/gstglvideomixer.c | 19 ++++++++++++++-----
> + ext/gl/gstglvideomixer.h |  2 ++
> + 2 files changed, 16 insertions(+), 5 deletions(-)
> +
> +diff --git a/ext/gl/gstglvideomixer.c b/ext/gl/gstglvideomixer.c
> +index 5df126d..d918ac7 100644
> +--- a/ext/gl/gstglvideomixer.c
> ++++ b/ext/gl/gstglvideomixer.c
> +@@ -1089,10 +1089,14 @@ _fixate_caps (GstVideoAggregator * vagg, GstCaps * caps)
> +   }
> +
> +   s = gst_caps_get_structure (ret, 0);
> +-  gst_structure_fixate_field_nearest_int (s, "width", best_width);
> +-  gst_structure_fixate_field_nearest_int (s, "height", best_height);
> +-  gst_structure_fixate_field_nearest_fraction (s, "framerate", best_fps_n,
> +-      best_fps_d);
> ++  if (!gst_structure_fixate_field_nearest_int (s, "width", best_width))
> ++    gst_structure_set (s, "width", G_TYPE_INT, best_width, NULL);
> ++  if (!gst_structure_fixate_field_nearest_int (s, "height", best_height))
> ++    gst_structure_set (s, "height", G_TYPE_INT, best_height, NULL);
> ++  if (!gst_structure_fixate_field_nearest_fraction (s, "framerate", best_fps_n,
> ++          best_fps_d))
> ++    gst_structure_set (s, "framerate", GST_TYPE_FRACTION, best_fps_n,
> ++        best_fps_d, NULL);
> +   ret = gst_caps_fixate (ret);
> +
> +   return ret;
> +@@ -1165,6 +1169,9 @@ gst_gl_video_mixer_init_shader (GstGLMixer * mixer, GstCaps * outcaps)
> +   if (video_mixer->shader)
> +     gst_object_unref (video_mixer->shader);
> +
> ++  /* need reconfigure output geometry */
> ++  video_mixer->output_geo_changed = TRUE;
> ++
> +   return gst_gl_context_gen_shader (GST_GL_BASE_MIXER (mixer)->context,
> +       gst_gl_shader_string_vertex_mat4_vertex_transform,
> +       video_mixer_f_src, &video_mixer->shader);
> +@@ -1487,7 +1494,8 @@ gst_gl_video_mixer_callback (gpointer stuff)
> +
> +     _init_vbo_indices (video_mixer);
> +
> +-    if (pad->geometry_change || !pad->vertex_buffer) {
> ++    if (video_mixer->output_geo_changed || pad->geometry_change
> ++        || !pad->vertex_buffer) {
> +       gint pad_width, pad_height;
> +       gfloat w, h;
> +
> +@@ -1555,6 +1563,7 @@ gst_gl_video_mixer_callback (gpointer stuff)
> +
> +     walk = g_list_next (walk);
> +   }
> ++  video_mixer->output_geo_changed = FALSE;
> +   GST_OBJECT_UNLOCK (video_mixer);
> +
> +   gl->DisableVertexAttribArray (attr_position_loc);
> +diff --git a/ext/gl/gstglvideomixer.h b/ext/gl/gstglvideomixer.h
> +index f352646..c734efb 100644
> +--- a/ext/gl/gstglvideomixer.h
> ++++ b/ext/gl/gstglvideomixer.h
> +@@ -126,6 +126,8 @@ struct _GstGLVideoMixer
> +     GLuint vbo_indices;
> +     GLuint checker_vbo;
> +     GstGLMemory *out_tex;
> ++
> ++    gboolean output_geo_changed;
> + };
> +
> + struct _GstGLVideoMixerClass
> +--
> +1.9.1
> +
> diff --git a/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad/0037-gleglimage-fix-YUY2-import-error-when-up.patch b/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad/0037-gleglimage-fix-YUY2-import-error-when-up.patch
> new file mode 100644
> index 00000000..3c2159cd
> --- /dev/null
> +++ b/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad/0037-gleglimage-fix-YUY2-import-error-when-up.patch
> @@ -0,0 +1,30 @@
> +From 0479a8e34369080c9beb5b36cd77d93b83a7b663 Mon Sep 17 00:00:00 2001
> +From: Haihua Hu <jared.hu at nxp.com>
> +Date: Wed, 27 Sep 2017 12:22:51 +0800
> +Subject: [PATCH] [MMFMWK-7741] gleglimage: fix YUY2 import error when upload
> + with dmafd
> +
> +gstreamer YUY2 fourcc is not match with that one in drm fourcc
> +
> +Upstream Status:  [i.MX specific]
> +Signed-off-by: Haihua Hu <jared.hu at nxp.com>
> +---
> + gst-libs/gst/gl/egl/gsteglimage.c | 2 ++
> + 1 file changed, 2 insertions(+)
> +
> +diff --git a/gst-libs/gst/gl/egl/gsteglimage.c b/gst-libs/gst/gl/egl/gsteglimage.c
> +index 75ed5cf..f0ab74b 100644
> +--- a/gst-libs/gst/gl/egl/gsteglimage.c
> ++++ b/gst-libs/gst/gl/egl/gsteglimage.c
> +@@ -496,6 +496,8 @@ gst_egl_image_from_dmabuf_singleplaner (GstGLContext * context,
> +     /* gstreamer fourcc is not compatible with DRM FOURCC*/
> +     if(GST_VIDEO_INFO_FORMAT(in_info) == GST_VIDEO_FORMAT_I420)
> +       fourcc = DRM_FORMAT_YUV420;
> ++    if(GST_VIDEO_INFO_FORMAT(in_info) == GST_VIDEO_FORMAT_YUY2)
> ++      fourcc = DRM_FORMAT_YUYV;
> +   }
> +
> +   GST_DEBUG ("fourcc %.4s (%d) n_planes %d (%dx%d)",
> +--
> +1.9.1
> +
> diff --git a/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad/0038-glupload-need-upload-each-plane-to-singl.patch b/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad/0038-glupload-need-upload-each-plane-to-singl.patch
> new file mode 100644
> index 00000000..c0751d8c
> --- /dev/null
> +++ b/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad/0038-glupload-need-upload-each-plane-to-singl.patch
> @@ -0,0 +1,101 @@
> +From 2f11f9247972d09ba461de10be2398e513764045 Mon Sep 17 00:00:00 2001
> +From: Haihua Hu <jared.hu at nxp.com>
> +Date: Fri, 17 Nov 2017 13:06:56 +0800
> +Subject: [PATCH] [MMFMWK-7782] glupload: need upload each plane to single
> + eglimage when output format is not RGBA
> +
> +when glupload out format is not RGBA, need to use single eglimage
> +upload each plane.
> +
> +Upstream-Status: Inappropriate [i.MX specific]
> +---
> + gst-libs/gst/gl/gstglupload.c | 62 ++++++++++++++++++++++---------------------
> + 1 file changed, 32 insertions(+), 30 deletions(-)
> +
> +diff --git a/gst-libs/gst/gl/gstglupload.c b/gst-libs/gst/gl/gstglupload.c
> +index 5c7eca0..ed5e54b 100644
> +--- a/gst-libs/gst/gl/gstglupload.c
> ++++ b/gst-libs/gst/gl/gstglupload.c
> +@@ -657,6 +657,7 @@ _dma_buf_upload_accept (gpointer impl, GstBuffer * buffer, GstCaps * in_caps,
> +   gsize mems_skip[GST_VIDEO_MAX_PLANES];
> +   GstMemory *mems[GST_VIDEO_MAX_PLANES];
> +   guint i;
> ++  GstVideoFormat out_fmt;
> +
> +   n_mem = gst_buffer_n_memory (buffer);
> +   meta = gst_buffer_get_video_meta (buffer);
> +@@ -773,40 +774,41 @@ _dma_buf_upload_accept (gpointer impl, GstBuffer * buffer, GstCaps * in_caps,
> +       return FALSE;
> +   }
> +
> +-#ifdef EGL_DMA_BUF_PLANE1_FD_EXT
> +-  /* Now create one single EGLImage */
> +-  /* check if one is cached */
> +-  dmabuf->eglimage[0] = _get_cached_eglimage (mems[0], 0);
> +-  if (dmabuf->eglimage[0])
> +-    return TRUE;
> +-
> +-  dmabuf->eglimage[0] =
> +-      gst_egl_image_from_dmabuf_singleplaner (dmabuf->upload->context,
> +-      mems, in_info, n_planes, mems_skip);
> +-  if (!dmabuf->eglimage[0])
> +-    return FALSE;
> +-
> +-  _set_cached_eglimage (mems[0], dmabuf->eglimage[0], 0);
> +-#else
> +-  /* Now create an EGLImage for each dmabufs */
> +-  for (i = 0; i < n_planes; i++) {
> ++  out_fmt = GST_VIDEO_INFO_FORMAT (&dmabuf->upload->priv->out_info);
> ++  if (out_fmt == GST_VIDEO_FORMAT_RGBA) {
> ++    /* Now create one single EGLImage */
> +     /* check if one is cached */
> +-    dmabuf->eglimage[i] = _get_cached_eglimage (mems[i], i);
> +-    if (dmabuf->eglimage[i])
> +-      continue;
> +-
> +-    /* otherwise create one and cache it */
> +-    dmabuf->eglimage[i] =
> +-        gst_egl_image_from_dmabuf (dmabuf->upload->context,
> +-        gst_dmabuf_memory_get_fd (mems[i]), in_info, i,
> +-        mems[i]->offset + mems_skip[i]);
> +-
> +-    if (!dmabuf->eglimage[i])
> ++    dmabuf->eglimage[0] = _get_cached_eglimage (mems[0], 0);
> ++    if (dmabuf->eglimage[0])
> ++      return TRUE;
> ++
> ++    dmabuf->eglimage[0] =
> ++        gst_egl_image_from_dmabuf_singleplaner (dmabuf->upload->context,
> ++        mems, in_info, n_planes, mems_skip);
> ++    if (!dmabuf->eglimage[0])
> +       return FALSE;
> +
> +-    _set_cached_eglimage (mems[i], dmabuf->eglimage[i], i);
> ++    _set_cached_eglimage (mems[0], dmabuf->eglimage[0], 0);
> ++  } else {
> ++    /* Now create an EGLImage for each dmabufs */
> ++    for (i = 0; i < n_planes; i++) {
> ++      /* check if one is cached */
> ++      dmabuf->eglimage[i] = _get_cached_eglimage (mems[i], i);
> ++      if (dmabuf->eglimage[i])
> ++        continue;
> ++
> ++      /* otherwise create one and cache it */
> ++      dmabuf->eglimage[i] =
> ++          gst_egl_image_from_dmabuf (dmabuf->upload->context,
> ++          gst_dmabuf_memory_get_fd (mems[i]), in_info, i,
> ++          mems[i]->offset + mems_skip[i]);
> ++
> ++      if (!dmabuf->eglimage[i])
> ++        return FALSE;
> ++
> ++      _set_cached_eglimage (mems[i], dmabuf->eglimage[i], i);
> ++    }
> +   }
> +-#endif
> +
> +   return TRUE;
> + }
> +--
> +1.9.1
> +
> diff --git a/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad_1.12.%.bbappend b/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad_1.12.%.bbappend
> index 15a735d4..d89c7cd8 100644
> --- a/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad_1.12.%.bbappend
> +++ b/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad_1.12.%.bbappend
> @@ -1,2 +1,63 @@
> +FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:"
> +
> +DEPENDS_append_imxgpu2d = " virtual/libg2d"
> +DEPENDS_append_mx7ulp = " libdrm"
> +
>  PACKAGECONFIG_GL_imxgpu2d = "${@bb.utils.contains('DISTRO_FEATURES', 'opengl x11', 'opengl', '', d)}"
>  PACKAGECONFIG_GL_imxgpu3d = "${@bb.utils.contains('DISTRO_FEATURES', 'opengl', 'gles2', '', d)}"
> +
> +PACKAGECONFIG_append_mx6q = " opencv"
> +PACKAGECONFIG_append_mx6qp = " opencv"
> +PACKAGECONFIG_append_mx8 = " opencv"
> +PACKAGECONFIG_remove_mx6sl = " gles2"
> +
> +SRC_URI_append = " \
> +    file://0001-mpegtsmux-Need-get-pid-when-create-streams.patch \
> +    file://0002-mpegvideoparse-Need-detect-picture-coding-type-when-.patch \
> +    file://0003-modifiy-the-videoparse-rank.patch \
> +    file://0004-glfilter-Lost-frame-rate-info-when-fixate-caps.patch \
> +    file://0005-camerabin-Add-one-property-to-set-sink-element-for-v.patch \
> +    file://0006-Fix-for-gl-plugin-not-built-in-wayland-backend.patch \
> +    file://0007-Change-wayland-default-res-to-1024x768.patch \
> +    file://0008-gl-wayland-fix-loop-test-hang-in-glimagesink.patch \
> +    file://0009-Fix-glimagesink-wayland-resize-showed-blurred-screen.patch \
> +    file://0010-support-video-crop-for-glimagesink.patch \
> +    file://0011-Add-fps-print-in-glimagesink.patch \
> +    file://0012-glcolorconvert-convert-YUV-to-RGB-use-directviv.patch \
> +    file://0013-videocompositor-Remove-output-format-alpha-check.patch \
> +    file://0014-Specific-patches-for-gstplayer-API.patch \
> +    file://0015-gstplayer-Add-gst_player_get_state-API.patch \
> +    file://0016-gstplayer-Add-play-stop-sync-API.patch \
> +    file://0018-Add-imx-physical-memory-allocator.patch \
> +    file://0019-Add-implement-of-interface-get_phys_addr-to-support-.patch \
> +    file://0020-Accelerate-gldownload-with-directviv.patch \
> +    file://0021-ionmemory-dmabuf-memory-allocator-based-on-ion-drive.patch \
> +    file://0022-ionmemory-support-get-phys-memory.patch \
> +    file://0023-glupload-add-crop-meta-support-in-dmafd-uploader.patch \
> +    file://0024-glupload-add-ion-dmabuf-support-in-glupload.patch \
> +    file://0025-Add-ion-dmabuf-support-in-gldownload.patch \
> +    file://0026-glframebuffer-check-frame-buffer-status-need-use-spe.patch \
> +    file://0027-qml-add-EGL-platform-support-for-x11-backend.patch \
> +    file://0028-kmssink-use-control-node-to-setplane-to-.patch \
> +    file://0029-kmssink-support-videooverlay-interface.patch \
> +    file://0030-kmssink-check-scaleable-when-set_caps.patch \
> +    file://0031-glimagesink-fix-segmentation-fault-when-.patch \
> +    file://0032-gl-viv-fb-fix-wrong-pos-x-y-calculate-in.patch \
> +    file://0033-gl-viv-fb-transform-screen-coordinate-to.patch \
> +    file://0034-glimagesink-expose-should-do-redisplay-a.patch \
> +    file://0035-videoaggregator-passthrough-interlace-mo.patch \
> +    file://0036-glvideomixer-need-update-output-geometry.patch \
> +    file://0037-gleglimage-fix-YUY2-import-error-when-up.patch \
> +    file://0038-glupload-need-upload-each-plane-to-singl.patch \
> +"
> +
> +# include fragment shaders
> +FILES_${PN}-opengl += "/usr/share/*.fs"
> +
> +PACKAGE_ARCH_imxpxp = "${MACHINE_SOCARCH}"
> +PACKAGE_ARCH_mx8 = "${MACHINE_SOCARCH}"
> +
> +# Fix libgstbadion-1.0.so.0 which is under built directory cannot be found
> +do_compile_prepend () {
> +    export GIR_EXTRA_LIBS_PATH="${B}/gst-libs/gst/ion/.libs"
> +}
> --
> 2.13.6
>
> --
> _______________________________________________
> meta-freescale mailing list
> meta-freescale at yoctoproject.org
> https://lists.yoctoproject.org/listinfo/meta-freescale



-- 
Otavio Salvador                             O.S. Systems
http://www.ossystems.com.br        http://code.ossystems.com.br
Mobile: +55 (53) 9981-7854            Mobile: +1 (347) 903-9750


More information about the meta-freescale mailing list