From 5faa79028eead21680d490a1b589a3875f966e0e Mon Sep 17 00:00:00 2001 From: Stefan Agner Date: Tue, 19 Dec 2017 22:57:48 +0100 Subject: imx-gst1.0-plugin: Add v4.3.1 and NXP specific gstreamer1.0 patches 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 Acked-by: Marcel Ziswiler --- ...tavcodecmap-Do-not-require-a-channel-mask.patch | 46 ++ .../gstreamer/gstreamer1.0-libav_1.12.%.bbappend | 5 + ...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 | 63 ++ ...rlay-make-memory-copy-when-video-buffer-s.patch | 78 +++ ...-don-t-set-async-of-custom-text-sink-to-f.patch | 35 ++ ...stplaybin-remove-default-deinterlace-flag.patch | 31 + ...-send-to-down-stream-if-all-the-frame-cor.patch | 58 ++ .../0007-handle-audio-video-decoder-error.patch | 66 ++ ...esink-print-warning-istead-of-return-ERRO.patch | 47 ++ ...-Linux_MX6QP_ARD-IMXCameraApp-When-Enable.patch | 58 ++ ...-7259-Remove-dependence-on-imx-plugin-git.patch | 433 +++++++++++++ ...-optimization-for-lib-video-in-plugins-ba.patch | 34 + ...-Remove-phymem-allocator-from-base-to-bad.patch | 37 ++ .../0013-dmabuf-set-fd-memory-to-keep-mapped.patch | 30 + ...ed-unmap-if-mapping-flags-are-not-subset-.patch | 36 ++ ...-basetextoverlay-need-avoid-idx-exceed-me.patch | 34 + .../gstreamer1.0-plugins-base_1.12.%.bbappend | 25 + ...Need-to-check-if-pa-stream-is-still-valid.patch | 39 ++ .../0002-Fix-aacpase-error-tolerance-issue.patch | 34 + ...-MMFMWK-7274-mx8dv-Enable-camera-on-mx8dv.patch | 37 ++ ...-Fix-adif-aac-file-read-channel-progile-i.patch | 267 ++++++++ .../gstreamer1.0-plugins-good_1.12.%.bbappend | 8 + .../gstreamer/gstreamer1.0-plugins-imx_0.13.0.bb | 69 ++ .../0001-handle-base-parse-error.patch | 35 ++ ...ith-gst-inspect-Chris-Lord-chris-openedha.patch | 32 + ...e-unset-FLAG_DISCONT-when-push-to-adapter.patch | 33 + ...e-Need-push-adapter-remainning-data-in-pa.patch | 51 ++ ...or-should-proceed-non-active-pad-buffer-e.patch | 51 ++ ...0006-poll-Add-check-if-can-read-event-API.patch | 95 +++ ...or-Need-flush-when-set-active-pad-and-the.patch | 68 ++ .../gstreamer/gstreamer1.0_1.12.%.bbappend | 16 + .../gstreamer/imx-gst1.0-plugin_4.3.1.bb | 86 +++ 69 files changed, 7622 insertions(+) create mode 100644 recipes-multimedia/gstreamer/gstreamer1.0-libav/0002-gstavcodecmap-Do-not-require-a-channel-mask.patch create mode 100644 recipes-multimedia/gstreamer/gstreamer1.0-libav_1.12.%.bbappend 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 create mode 100644 recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad_1.12.%.bbappend create mode 100644 recipes-multimedia/gstreamer/gstreamer1.0-plugins-base/0001-basetextoverlay-make-memory-copy-when-video-buffer-s.patch create mode 100644 recipes-multimedia/gstreamer/gstreamer1.0-plugins-base/0002-gstplaysink-don-t-set-async-of-custom-text-sink-to-f.patch create mode 100644 recipes-multimedia/gstreamer/gstreamer1.0-plugins-base/0005-gstplaybin-remove-default-deinterlace-flag.patch create mode 100644 recipes-multimedia/gstreamer/gstreamer1.0-plugins-base/0006-taglist-not-send-to-down-stream-if-all-the-frame-cor.patch create mode 100644 recipes-multimedia/gstreamer/gstreamer1.0-plugins-base/0007-handle-audio-video-decoder-error.patch create mode 100644 recipes-multimedia/gstreamer/gstreamer1.0-plugins-base/0008-gstaudiobasesink-print-warning-istead-of-return-ERRO.patch create mode 100644 recipes-multimedia/gstreamer/gstreamer1.0-plugins-base/0009-MMFMWK-7030-Linux_MX6QP_ARD-IMXCameraApp-When-Enable.patch create mode 100644 recipes-multimedia/gstreamer/gstreamer1.0-plugins-base/0010-MMFMWK-7259-Remove-dependence-on-imx-plugin-git.patch create mode 100644 recipes-multimedia/gstreamer/gstreamer1.0-plugins-base/0011-Disable-orc-optimization-for-lib-video-in-plugins-ba.patch create mode 100644 recipes-multimedia/gstreamer/gstreamer1.0-plugins-base/0012-Remove-phymem-allocator-from-base-to-bad.patch create mode 100644 recipes-multimedia/gstreamer/gstreamer1.0-plugins-base/0013-dmabuf-set-fd-memory-to-keep-mapped.patch create mode 100644 recipes-multimedia/gstreamer/gstreamer1.0-plugins-base/0014-fdmemory-need-unmap-if-mapping-flags-are-not-subset-.patch create mode 100644 recipes-multimedia/gstreamer/gstreamer1.0-plugins-base/0015-basetextoverlay-need-avoid-idx-exceed-me.patch create mode 100644 recipes-multimedia/gstreamer/gstreamer1.0-plugins-base_1.12.%.bbappend create mode 100644 recipes-multimedia/gstreamer/gstreamer1.0-plugins-good/0001-Need-to-check-if-pa-stream-is-still-valid.patch create mode 100644 recipes-multimedia/gstreamer/gstreamer1.0-plugins-good/0002-Fix-aacpase-error-tolerance-issue.patch create mode 100644 recipes-multimedia/gstreamer/gstreamer1.0-plugins-good/0003-MMFMWK-7274-mx8dv-Enable-camera-on-mx8dv.patch create mode 100644 recipes-multimedia/gstreamer/gstreamer1.0-plugins-good/0004-gstaacparse-Fix-adif-aac-file-read-channel-progile-i.patch create mode 100644 recipes-multimedia/gstreamer/gstreamer1.0-plugins-good_1.12.%.bbappend create mode 100644 recipes-multimedia/gstreamer/gstreamer1.0-plugins-imx_0.13.0.bb create mode 100644 recipes-multimedia/gstreamer/gstreamer1.0/0001-handle-base-parse-error.patch create mode 100644 recipes-multimedia/gstreamer/gstreamer1.0/0002-Fix-crash-with-gst-inspect-Chris-Lord-chris-openedha.patch create mode 100644 recipes-multimedia/gstreamer/gstreamer1.0/0003-baseparse-unset-FLAG_DISCONT-when-push-to-adapter.patch create mode 100644 recipes-multimedia/gstreamer/gstreamer1.0/0004-gstbaseparse-Need-push-adapter-remainning-data-in-pa.patch create mode 100644 recipes-multimedia/gstreamer/gstreamer1.0/0005-inputselector-should-proceed-non-active-pad-buffer-e.patch create mode 100644 recipes-multimedia/gstreamer/gstreamer1.0/0006-poll-Add-check-if-can-read-event-API.patch create mode 100644 recipes-multimedia/gstreamer/gstreamer1.0/0007-inputselector-Need-flush-when-set-active-pad-and-the.patch create mode 100644 recipes-multimedia/gstreamer/gstreamer1.0_1.12.%.bbappend create mode 100644 recipes-multimedia/gstreamer/imx-gst1.0-plugin_4.3.1.bb (limited to 'recipes-multimedia') diff --git a/recipes-multimedia/gstreamer/gstreamer1.0-libav/0002-gstavcodecmap-Do-not-require-a-channel-mask.patch b/recipes-multimedia/gstreamer/gstreamer1.0-libav/0002-gstavcodecmap-Do-not-require-a-channel-mask.patch new file mode 100644 index 0000000..b499d21 --- /dev/null +++ b/recipes-multimedia/gstreamer/gstreamer1.0-libav/0002-gstavcodecmap-Do-not-require-a-channel-mask.patch @@ -0,0 +1,46 @@ +From 1553cc0f1843213801767dedb973e30db2d23855 Mon Sep 17 00:00:00 2001 +From: Mathieu Duponchelle +Date: Thu, 17 Aug 2017 14:28:22 +0200 +Subject: [PATCH] gstavcodecmap: Do not require a channel-mask + +.. for mono or stereo input. + +Upstream-Status: Backport [1.13.1] + +https://bugzilla.gnome.org/show_bug.cgi?id=786401 +--- + ext/libav/gstavcodecmap.c | 17 ++++++++++++----- + 1 file changed, 12 insertions(+), 5 deletions(-) + +diff --git a/ext/libav/gstavcodecmap.c b/ext/libav/gstavcodecmap.c +index 35a2ca0..7033f54 100644 +--- a/ext/libav/gstavcodecmap.c ++++ b/ext/libav/gstavcodecmap.c +@@ -651,12 +651,19 @@ gst_ff_aud_caps_new (AVCodecContext * context, AVCodec * codec, + + if (gst_audio_channel_positions_to_mask (pos, nbits_set, FALSE, + &mask)) { +- GstCaps *tmp = +- gst_caps_new_simple (mimetype, "channel-mask", GST_TYPE_BITMASK, +- mask, +- "channels", G_TYPE_INT, nbits_set, NULL); ++ GstStructure *s = ++ gst_structure_new (mimetype, "channels", G_TYPE_INT, nbits_set, ++ NULL); ++ ++ /* No need to require a channel mask for mono or stereo */ ++ if (!(nbits_set == 1 && pos[0] == GST_AUDIO_CHANNEL_POSITION_MONO) ++ && !(nbits_set == 2 ++ && pos[0] == GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT ++ && pos[1] == GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT)) ++ gst_structure_set (s, "channel-mask", GST_TYPE_BITMASK, mask, ++ NULL); + +- gst_caps_append (caps, tmp); ++ gst_caps_append_structure (caps, s); + } + } + layouts++; +-- +1.9.1 + diff --git a/recipes-multimedia/gstreamer/gstreamer1.0-libav_1.12.%.bbappend b/recipes-multimedia/gstreamer/gstreamer1.0-libav_1.12.%.bbappend new file mode 100644 index 0000000..e783e5f --- /dev/null +++ b/recipes-multimedia/gstreamer/gstreamer1.0-libav_1.12.%.bbappend @@ -0,0 +1,5 @@ +FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:" + +SRC_URI_append_imx = " \ + file://0002-gstavcodecmap-Do-not-require-a-channel-mask.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 0000000..4e5a455 --- /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 +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 0000000..2babed7 --- /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 +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 0000000..3816745 --- /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 +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 + +[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 +--- + 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 0000000..ea278f2 --- /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 +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 0000000..14291e9 --- /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 +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 0000000..a1eb706 --- /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 +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 + +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 0000000..cd0b23a --- /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 +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 +--- + 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 0000000..25bd452 --- /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 +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 +--- + 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 0000000..ba85cc9 --- /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 +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 +--- + 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 0000000..cf2a085 --- /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 +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 +--- + 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 0000000..ba9b6b8 --- /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 +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 + +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 0000000..a030657 --- /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 +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 + +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 0000000..eb7e132 --- /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 +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 0000000..61cafda --- /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 +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 + +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 0000000..da6f878 --- /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 +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 + +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 0000000..a4ccc18 --- /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 +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 + +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 0000000..22b6266 --- /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 +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 +--- + 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_@GST_API_VERSION@_includedir = $(includedir)/gstreamer-@GST_ + + libgstbadallocators_@GST_API_VERSION@_include_HEADERS = \ + badallocators.h \ +- gstphysmemory.h ++ gstphysmemory.h \ ++ gstallocatorphymem.h + + noinst_HEADERS = + + libgstbadallocators_@GST_API_VERSION@_la_SOURCES = \ +- gstphysmemory.c ++ gstphysmemory.c \ ++ gstallocatorphymem.c + + libgstbadallocators_@GST_API_VERSION@_la_LIBADD = $(GST_LIBS) $(LIBM) + libgstbadallocators_@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 ++#include + + #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 ++#include ++#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 ++#include ++ ++#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 0000000..2aead8d --- /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 +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 + #include + #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 0000000..b242ec3 --- /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 +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 +--- + 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 + #include "gstgldownloadelement.h" + ++#if GST_GL_HAVE_PHYMEM ++#include ++#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 (¶ms); ++ ++#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, ¶ms); ++ 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_@GST_API_VERSION@_la_LIBADD += egl/libgstgl-egl.la + libgstgl_@GST_API_VERSION@_la_LIBADD += -lgstallocators-$(GST_API_VERSION) + endif + ++if HAVE_GL_PHYMEM ++libgstgl_@GST_API_VERSION@_la_SOURCES += gstglphymemory.c ++libgstgl_@GST_API_VERSION@include_HEADERS += gstglphymemory.h ++libgstgl_@GST_API_VERSION@_la_LIBADD += -lg2d ++endif ++ + configexecincludedir = $(libdir)/gstreamer-@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 ++#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 ++ ++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 ++#include ++#include ++#include ++ ++#include ++ ++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 0000000..c344b2f --- /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 +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_@GST_API_VERSION@_include_HEADERS = \ + gstphysmemory.h \ + gstallocatorphymem.h + ++if USE_ION ++libgstbadallocators_@GST_API_VERSION@_include_HEADERS += \ ++ gstionmemory.h ++endif ++ + noinst_HEADERS = + + libgstbadallocators_@GST_API_VERSION@_la_SOURCES = \ + gstphysmemory.c \ + gstallocatorphymem.c + ++if USE_ION ++libgstbadallocators_@GST_API_VERSION@_la_SOURCES += \ ++ gstionmemory.c ++endif ++ + libgstbadallocators_@GST_API_VERSION@_la_LIBADD = $(GST_LIBS) $(LIBM) + libgstbadallocators_@GST_API_VERSION@_la_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_CFLAGS) + libgstbadallocators_@GST_API_VERSION@_la_LDFLAGS = $(GST_LIB_LDFLAGS) $(GST_ALL_LDFLAGS) $(GST_LT_LDFLAGS) + ++if USE_ION ++libgstbadallocators_@GST_API_VERSION@_la_LIBADD += -lgstallocators-$(GST_API_VERSION) ++endif ++ + if HAVE_INTROSPECTION + BUILT_GIRSOURCES = GstBadAllocators-@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 ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#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 ++#include ++ ++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 0000000..5ab4183 --- /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 +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 + + #include ++#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 0000000..67c6db6 --- /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 +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 0000000..c2b55f6 --- /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 +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 +--- + 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-@GST_API_VERSION@.gir: $(INTROSPECTION_SCANNER) libgstgl-@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-@GST_API_VERSION@` \ +- --add-include-path=`PKG_CONFIG_PATH="$(GST_PKG_CONFIG_PATH)" $(PKG_CONFIG) --variable=girdir gstreamer-base-@GST_API_VERSION@` \ +- --add-include-path=`PKG_CONFIG_PATH="$(GST_PKG_CONFIG_PATH)" $(PKG_CONFIG) --variable=girdir gstreamer-video-@GST_API_VERSION@` \ ++ --add-include-path=$(PKG_CONFIG_SYSROOT_DIR)`PKG_CONFIG_PATH="$(GST_PKG_CONFIG_PATH)" $(PKG_CONFIG) --variable=girdir gstreamer-@GST_API_VERSION@` \ ++ --add-include-path=$(PKG_CONFIG_SYSROOT_DIR)`PKG_CONFIG_PATH="$(GST_PKG_CONFIG_PATH)" $(PKG_CONFIG) --variable=girdir gstreamer-base-@GST_API_VERSION@` \ ++ --add-include-path=$(PKG_CONFIG_SYSROOT_DIR)`PKG_CONFIG_PATH="$(GST_PKG_CONFIG_PATH)" $(PKG_CONFIG) --variable=girdir gstreamer-video-@GST_API_VERSION@` \ + --library=libgstgl-@GST_API_VERSION@.la \ + --include=Gst-@GST_API_VERSION@ \ + --include=GstBase-@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 + #endif + ++#if GST_GL_HAVE_IONDMA ++#include ++#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 (¶ms); ++ ++ /* 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, ¶ms); ++ ++ 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 0000000..66f78d9 --- /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 +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 +--- + 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 + #endif + ++#if GST_GL_HAVE_IONDMA ++#include ++#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 (¶ms); + ++ 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_@GST_API_VERSION@include_HEADERS += gstglphymemory.h + libgstgl_@GST_API_VERSION@_la_LIBADD += -lg2d + endif + ++if HAVE_IONDMA ++libgstgl_@GST_API_VERSION@_la_SOURCES += gstglmemorydma.c ++libgstgl_@GST_API_VERSION@include_HEADERS += gstglmemorydma.h ++endif ++ ++ + configexecincludedir = $(libdir)/gstreamer-@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 ++ ++#include ++#include ++ ++#if GST_GL_HAVE_IONDMA ++#include ++#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 ++#include ++#include ++#include ++ ++#include ++#include ++#include ++ ++#include ++ ++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; ++ ++ /* */ ++ 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 0000000..9d3f569 --- /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 +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 0000000..6adb5c9 --- /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 +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 + +-#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 + #include ++#if GST_GL_HAVE_PLATFORM_GLX + #include ++#elif GST_GL_HAVE_PLATFORM_EGL ++#include ++#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 0000000..2edd593 --- /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 +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 +--- + 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 + + #include ++#include ++#include + + #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 0000000..7bf995f --- /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 +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 ++#include + #include + + #include +@@ -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 0000000..691ac84 --- /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 +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 0000000..cbec6d1 --- /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 +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 0000000..9eef87e --- /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 +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 0000000..3fd9f14 --- /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 +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 0000000..9226727 --- /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 +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 0000000..3084ba5 --- /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 +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 0000000..fe10d74 --- /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 +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 0000000..3c2159c --- /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 +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 +--- + 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 0000000..c0751d8 --- /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 +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 new file mode 100644 index 0000000..3beab8c --- /dev/null +++ b/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad_1.12.%.bbappend @@ -0,0 +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_imx = " \ + 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" +} diff --git a/recipes-multimedia/gstreamer/gstreamer1.0-plugins-base/0001-basetextoverlay-make-memory-copy-when-video-buffer-s.patch b/recipes-multimedia/gstreamer/gstreamer1.0-plugins-base/0001-basetextoverlay-make-memory-copy-when-video-buffer-s.patch new file mode 100644 index 0000000..28347c6 --- /dev/null +++ b/recipes-multimedia/gstreamer/gstreamer1.0-plugins-base/0001-basetextoverlay-make-memory-copy-when-video-buffer-s.patch @@ -0,0 +1,78 @@ +From f54f1c28272913a216e91868ce0270e6c0d99b2e Mon Sep 17 00:00:00 2001 +From: Mingke Wang +Date: Fri, 16 Oct 2015 19:31:32 +0800 +Subject: [PATCH 01/16] basetextoverlay: make memory copy when video buffer's + memory is ready only + +1. since gst_buffer_make_writable just lookup the refcount to determine if + a buffer is writable, and it will use _gst_buffer_copy() which don't + perform a deep memory copy even if the flag of a memory is set to + GST_MEMORY_FLAG_READONLY. So, we detect the memory flag and use + gst_buffer_copy_region with GST_BUFFER_COPY_DEEP parameter to perform + deep memory copy. if the allocator of a memory don't support mem_copy + interface, the it will return NULL, if this case, we can use + gst_buffer_make_writable() to get a shared memory buffer or the orignal + buffer if the buffer's refcount is 1. + +Signed-off-by: Mingke Wang +--- + ext/pango/gstbasetextoverlay.c | 32 ++++++++++++++++++++++++++++++-- + 1 file changed, 30 insertions(+), 2 deletions(-) + mode change 100644 => 100755 ext/pango/gstbasetextoverlay.c + +diff --git a/ext/pango/gstbasetextoverlay.c b/ext/pango/gstbasetextoverlay.c +old mode 100644 +new mode 100755 +index 44f5f52..c08e3b0 +--- a/ext/pango/gstbasetextoverlay.c ++++ b/ext/pango/gstbasetextoverlay.c +@@ -2227,16 +2227,44 @@ gst_base_text_overlay_push_frame (GstBaseTextOverlay * overlay, + } + } + +- video_frame = gst_buffer_make_writable (video_frame); +- + if (overlay->attach_compo_to_buffer) { + GST_DEBUG_OBJECT (overlay, "Attaching text overlay image to video buffer"); ++ video_frame = gst_buffer_make_writable (video_frame); + gst_buffer_add_video_overlay_composition_meta (video_frame, + overlay->composition); + /* FIXME: emulate shaded background box if want_shading=true */ + goto done; + } + ++ gint idx = 0; ++ gboolean mem_rdonly = FALSE; ++ GstMemory *mem; ++ ++ while (mem = gst_buffer_get_memory(video_frame, idx++)) { ++ if (GST_MEMORY_IS_READONLY(mem)) { ++ gst_memory_unref (mem); ++ mem_rdonly = TRUE; ++ break; ++ } ++ gst_memory_unref (mem); ++ } ++ ++ if (mem_rdonly) { ++ GstBuffer *new_buf = gst_buffer_copy_region (video_frame, ++ GST_BUFFER_COPY_ALL | GST_BUFFER_COPY_DEEP, 0, -1); ++ ++ if (!new_buf) { ++ GST_WARNING_OBJECT(overlay, ++ "buffer memory read only, but copy memory failed"); ++ goto done; ++ } else { ++ gst_buffer_unref (video_frame); ++ video_frame = new_buf; ++ } ++ } else { ++ video_frame = gst_buffer_make_writable (video_frame); ++ } ++ + if (!gst_video_frame_map (&frame, &overlay->info, video_frame, + GST_MAP_READWRITE)) + goto invalid_frame; +-- +1.9.1 + diff --git a/recipes-multimedia/gstreamer/gstreamer1.0-plugins-base/0002-gstplaysink-don-t-set-async-of-custom-text-sink-to-f.patch b/recipes-multimedia/gstreamer/gstreamer1.0-plugins-base/0002-gstplaysink-don-t-set-async-of-custom-text-sink-to-f.patch new file mode 100644 index 0000000..e628bf9 --- /dev/null +++ b/recipes-multimedia/gstreamer/gstreamer1.0-plugins-base/0002-gstplaysink-don-t-set-async-of-custom-text-sink-to-f.patch @@ -0,0 +1,35 @@ +From 9444e647142d69b5381bb1225700e335312b1144 Mon Sep 17 00:00:00 2001 +From: Mingke Wang +Date: Thu, 19 Mar 2015 14:15:25 +0800 +Subject: [PATCH 02/16] gstplaysink: don't set async of custom text-sink to + false + +set async to false lead to A/V sync problem when seeking. +the preroll need use GAP event instead of set async to false. + +Upstream-Status: Inappropriate [i.MX specific] + +Signed-off-by: Mingke Wang +--- + gst/playback/gstplaysink.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + mode change 100644 => 100755 gst/playback/gstplaysink.c + +diff --git a/gst/playback/gstplaysink.c b/gst/playback/gstplaysink.c +old mode 100644 +new mode 100755 +index ead2e68..3f62769 +--- a/gst/playback/gstplaysink.c ++++ b/gst/playback/gstplaysink.c +@@ -2456,7 +2456,7 @@ gen_text_chain (GstPlaySink * playsink) + G_TYPE_BOOLEAN); + if (elem) { + /* make sure the sparse subtitles don't participate in the preroll */ +- g_object_set (elem, "async", FALSE, NULL); ++ //g_object_set (elem, "async", FALSE, NULL); + GST_DEBUG_OBJECT (playsink, "adding custom text sink"); + gst_bin_add (bin, chain->sink); + /* NOTE streamsynchronizer needs streams decoupled */ +-- +1.9.1 + diff --git a/recipes-multimedia/gstreamer/gstreamer1.0-plugins-base/0005-gstplaybin-remove-default-deinterlace-flag.patch b/recipes-multimedia/gstreamer/gstreamer1.0-plugins-base/0005-gstplaybin-remove-default-deinterlace-flag.patch new file mode 100644 index 0000000..64b45fd --- /dev/null +++ b/recipes-multimedia/gstreamer/gstreamer1.0-plugins-base/0005-gstplaybin-remove-default-deinterlace-flag.patch @@ -0,0 +1,31 @@ +From 14dc47b7e6e118d06ad4e7ed29284984b3fae248 Mon Sep 17 00:00:00 2001 +From: Jian Li +Date: Mon, 23 Jun 2014 14:14:07 +0800 +Subject: [PATCH 06/16] gstplaybin remove default deinterlace flag + +- remove default deinterlace flag in playbin for i.MX SoCs + +Upstream-Status: Inappropriate [i.MX specific] + +Signed-off-by: Jian Li +--- + gst/playback/gstplaybin2.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +diff --git a/gst/playback/gstplaybin2.c b/gst/playback/gstplaybin2.c +index 04eeb2b..09b7ad2 100644 +--- a/gst/playback/gstplaybin2.c ++++ b/gst/playback/gstplaybin2.c +@@ -500,8 +500,7 @@ struct _GstPlayBinClass + #define DEFAULT_SUBURI NULL + #define DEFAULT_SOURCE NULL + #define DEFAULT_FLAGS GST_PLAY_FLAG_AUDIO | GST_PLAY_FLAG_VIDEO | GST_PLAY_FLAG_TEXT | \ +- GST_PLAY_FLAG_SOFT_VOLUME | GST_PLAY_FLAG_DEINTERLACE | \ +- GST_PLAY_FLAG_SOFT_COLORBALANCE ++ GST_PLAY_FLAG_SOFT_VOLUME + #define DEFAULT_N_VIDEO 0 + #define DEFAULT_CURRENT_VIDEO -1 + #define DEFAULT_N_AUDIO 0 +-- +1.9.1 + diff --git a/recipes-multimedia/gstreamer/gstreamer1.0-plugins-base/0006-taglist-not-send-to-down-stream-if-all-the-frame-cor.patch b/recipes-multimedia/gstreamer/gstreamer1.0-plugins-base/0006-taglist-not-send-to-down-stream-if-all-the-frame-cor.patch new file mode 100644 index 0000000..c8fd2eb --- /dev/null +++ b/recipes-multimedia/gstreamer/gstreamer1.0-plugins-base/0006-taglist-not-send-to-down-stream-if-all-the-frame-cor.patch @@ -0,0 +1,58 @@ +From 1dfe4f567771217bb33c57e8480b99969f119ded Mon Sep 17 00:00:00 2001 +From: Lyon Wang +Date: Wed, 21 Oct 2015 16:35:43 +0800 +Subject: [PATCH 07/16] taglist not send to down stream if all the frame + corrupted + +https://bugzilla.gnome.org/show_bug.cgi?id=737246 + +Upstream-Status: Pending + +Signed-off-by: Jian Li +--- + gst-libs/gst/audio/gstaudiodecoder.c | 9 +++++++++ + gst-libs/gst/video/gstvideodecoder.c | 8 ++++++++ + 2 files changed, 17 insertions(+) + +diff --git a/gst-libs/gst/audio/gstaudiodecoder.c b/gst-libs/gst/audio/gstaudiodecoder.c +index 333dbf9..d082380 100644 +--- a/gst-libs/gst/audio/gstaudiodecoder.c ++++ b/gst-libs/gst/audio/gstaudiodecoder.c +@@ -2261,6 +2261,15 @@ gst_audio_decoder_sink_eventfunc (GstAudioDecoder * dec, GstEvent * event) + ("no valid frames found")); + } + ++ /* send taglist if no valid frame is decoded util EOS */ ++ if (dec->priv->taglist && dec->priv->taglist_changed) { ++ GST_DEBUG_OBJECT (dec, "codec tag %" GST_PTR_FORMAT, dec->priv->taglist); ++ if (!gst_tag_list_is_empty (dec->priv->taglist)) ++ gst_audio_decoder_push_event (dec, ++ gst_event_new_tag (gst_tag_list_ref (dec->priv->taglist))); ++ dec->priv->taglist_changed = FALSE; ++ } ++ + /* Forward EOS because no buffer or serialized event will come after + * EOS and nothing could trigger another _finish_frame() call. */ + if (dec->priv->pending_events) +diff --git a/gst-libs/gst/video/gstvideodecoder.c b/gst-libs/gst/video/gstvideodecoder.c +index b91a32e..1f89e10 100644 +--- a/gst-libs/gst/video/gstvideodecoder.c ++++ b/gst-libs/gst/video/gstvideodecoder.c +@@ -1165,6 +1165,14 @@ gst_video_decoder_sink_event_default (GstVideoDecoder * decoder, + * parent class' ::sink_event() until a later time. + */ + forward_immediate = TRUE; ++ ++ /* send taglist if no valid frame is decoded util EOS */ ++ if (decoder->priv->tags && decoder->priv->tags_changed) { ++ gst_video_decoder_push_event (decoder, ++ gst_event_new_tag (gst_tag_list_ref (decoder->priv->tags))); ++ decoder->priv->tags_changed = FALSE; ++ } ++ + break; + } + case GST_EVENT_GAP: +-- +1.9.1 + diff --git a/recipes-multimedia/gstreamer/gstreamer1.0-plugins-base/0007-handle-audio-video-decoder-error.patch b/recipes-multimedia/gstreamer/gstreamer1.0-plugins-base/0007-handle-audio-video-decoder-error.patch new file mode 100644 index 0000000..ed39e85 --- /dev/null +++ b/recipes-multimedia/gstreamer/gstreamer1.0-plugins-base/0007-handle-audio-video-decoder-error.patch @@ -0,0 +1,66 @@ +From 40ef196e9291e71b852b32979daa0256cb805d14 Mon Sep 17 00:00:00 2001 +From: Lyon Wang +Date: Mon, 15 Dec 2014 16:52:07 +0800 +Subject: [PATCH 08/16] handle audio/video decoder error + +When there is input data and no output data to the end of the stream, it will +send GST_ELEMENT_ERROR, So the clips playing will quit. +However, if only one of the tracks is corrupt, there is no need to quit other +tracks playing. + +The patch comments the GST_ELEMENT_ERROR() and just add GST_ERROR_OBJECT() +information instead. + +https://bugzilla.gnome.org/show_bug.cgi?id=741542 + +Upstream-Status: Pending + +Signed-off-by: Lyon Wang +--- + gst-libs/gst/audio/gstaudiodecoder.c | 5 +++-- + gst-libs/gst/video/gstvideodecoder.c | 5 +++-- + 2 files changed, 6 insertions(+), 4 deletions(-) + mode change 100644 => 100755 gst-libs/gst/audio/gstaudiodecoder.c + mode change 100644 => 100755 gst-libs/gst/video/gstvideodecoder.c + +diff --git a/gst-libs/gst/audio/gstaudiodecoder.c b/gst-libs/gst/audio/gstaudiodecoder.c +old mode 100644 +new mode 100755 +index d082380..669b02a +--- a/gst-libs/gst/audio/gstaudiodecoder.c ++++ b/gst-libs/gst/audio/gstaudiodecoder.c +@@ -2256,9 +2256,10 @@ gst_audio_decoder_sink_eventfunc (GstAudioDecoder * dec, GstEvent * event) + GST_AUDIO_DECODER_STREAM_UNLOCK (dec); + + if (dec->priv->ctx.had_input_data && !dec->priv->ctx.had_output_data) { +- GST_ELEMENT_ERROR (dec, STREAM, DECODE, ++ /* GST_ELEMENT_ERROR (dec, STREAM, DECODE, + ("No valid frames decoded before end of stream"), +- ("no valid frames found")); ++ ("no valid frames found")); */ ++ GST_ERROR_OBJECT(dec, "No valid frames decoded before end of stream"); + } + + /* send taglist if no valid frame is decoded util EOS */ +diff --git a/gst-libs/gst/video/gstvideodecoder.c b/gst-libs/gst/video/gstvideodecoder.c +old mode 100644 +new mode 100755 +index 1f89e10..802d94a +--- a/gst-libs/gst/video/gstvideodecoder.c ++++ b/gst-libs/gst/video/gstvideodecoder.c +@@ -1151,9 +1151,10 @@ gst_video_decoder_sink_event_default (GstVideoDecoder * decoder, + + /* Error out even if EOS was ok when we had input, but no output */ + if (ret && priv->had_input_data && !priv->had_output_data) { +- GST_ELEMENT_ERROR (decoder, STREAM, DECODE, ++ /* GST_ELEMENT_ERROR (decoder, STREAM, DECODE, + ("No valid frames decoded before end of stream"), +- ("no valid frames found")); ++ ("no valid frames found")); */ ++ GST_ERROR_OBJECT(decoder, "No valid frames decoded before end of stream"); + } + + /* Forward EOS immediately. This is required because no +-- +1.9.1 + diff --git a/recipes-multimedia/gstreamer/gstreamer1.0-plugins-base/0008-gstaudiobasesink-print-warning-istead-of-return-ERRO.patch b/recipes-multimedia/gstreamer/gstreamer1.0-plugins-base/0008-gstaudiobasesink-print-warning-istead-of-return-ERRO.patch new file mode 100644 index 0000000..acfb748 --- /dev/null +++ b/recipes-multimedia/gstreamer/gstreamer1.0-plugins-base/0008-gstaudiobasesink-print-warning-istead-of-return-ERRO.patch @@ -0,0 +1,47 @@ +From 0b04eab955d557b84cfecea4bbe8cec6f04da0d8 Mon Sep 17 00:00:00 2001 +From: Lyon Wang +Date: Tue, 17 Nov 2015 14:56:47 +0800 +Subject: [PATCH 09/16] gstaudiobasesink print warning istead of return ERROR. + +For those clips with corrupt audio track, +there might be no output from audio decoder +and thus the audio track have no chance to negotiate. +We can just print error warning instead of return ERROR, +so that other track can be played normally + +https://bugzilla.gnome.org/show_bug.cgi?id=758215 + +Upstream-Status: Pending + +Signed-off-by: Lyon Wang +--- + gst-libs/gst/audio/gstaudiobasesink.c | 7 ++++++- + 1 file changed, 6 insertions(+), 1 deletion(-) + mode change 100644 => 100755 gst-libs/gst/audio/gstaudiobasesink.c + +diff --git a/gst-libs/gst/audio/gstaudiobasesink.c b/gst-libs/gst/audio/gstaudiobasesink.c +old mode 100644 +new mode 100755 +index 6c0e7c9..91f0a48 +--- a/gst-libs/gst/audio/gstaudiobasesink.c ++++ b/gst-libs/gst/audio/gstaudiobasesink.c +@@ -1114,10 +1114,15 @@ gst_audio_base_sink_wait_event (GstBaseSink * bsink, GstEvent * event) + case GST_EVENT_GAP: + /* We must have a negotiated format before starting the ringbuffer */ + if (G_UNLIKELY (!gst_audio_ring_buffer_is_acquired (sink->ringbuffer))) { +- GST_ELEMENT_ERROR (sink, STREAM, FORMAT, (NULL), ++ /* GST_ELEMENT_ERROR (sink, STREAM, FORMAT, (NULL), + ("Sink not negotiated before %s event.", + GST_EVENT_TYPE_NAME (event))); ++ + return GST_FLOW_ERROR; ++ */ ++ /* consider there might be chance that corrupt audio track without output buffer and not negotiated. ++ We'd better not return error and quit play, video track can keep playing.*/ ++ GST_ERROR_OBJECT(sink, "Sink not negotiated before %s event.",GST_EVENT_TYPE_NAME (event)); + } + + gst_audio_base_sink_force_start (sink); +-- +1.9.1 + diff --git a/recipes-multimedia/gstreamer/gstreamer1.0-plugins-base/0009-MMFMWK-7030-Linux_MX6QP_ARD-IMXCameraApp-When-Enable.patch b/recipes-multimedia/gstreamer/gstreamer1.0-plugins-base/0009-MMFMWK-7030-Linux_MX6QP_ARD-IMXCameraApp-When-Enable.patch new file mode 100644 index 0000000..8055e84 --- /dev/null +++ b/recipes-multimedia/gstreamer/gstreamer1.0-plugins-base/0009-MMFMWK-7030-Linux_MX6QP_ARD-IMXCameraApp-When-Enable.patch @@ -0,0 +1,58 @@ +From c2790999940b0d96a663114c7f7a5af3b6069fef Mon Sep 17 00:00:00 2001 +From: Song Bing +Date: Mon, 11 Jan 2016 14:51:17 +0800 +Subject: [PATCH 10/16] MMFMWK-7030 [Linux_MX6QP_ARD]IMXCameraApp:When Enabled + "save time to image" item, preview, find the time can not display completely. + 100% + +As IPU need 8 pixels alignment, add one workaround in base text overlay +to generate 8 pixels alignment text video buffer. The side effect should +cause all text a little smaller. + +Upstream-Status: Inappropriate [i.MX specific] + +Signed-off-by: Song Bing b06498@freescale.com +--- + ext/pango/gstbasetextoverlay.c | 12 ++++++++++-- + 1 file changed, 10 insertions(+), 2 deletions(-) + +diff --git a/ext/pango/gstbasetextoverlay.c b/ext/pango/gstbasetextoverlay.c +index c08e3b0..421340a 100755 +--- a/ext/pango/gstbasetextoverlay.c ++++ b/ext/pango/gstbasetextoverlay.c +@@ -1677,7 +1677,7 @@ gst_base_text_overlay_render_pangocairo (GstBaseTextOverlay * overlay, + gint unscaled_width, unscaled_height; + gint width, height; + gboolean full_width = FALSE; +- double scalef = 1.0; ++ double scalef = 1.0, scalefx, scalefy; + double a, r, g, b; + gdouble shadow_offset = 0.0; + gdouble outline_offset = 0.0; +@@ -1805,6 +1805,14 @@ gst_base_text_overlay_render_pangocairo (GstBaseTextOverlay * overlay, + height = ceil (height * overlay->render_scale); + scalef *= overlay->render_scale; + ++ /* i.MX special, will cause text a little small */ ++ scalefx = scalef * ((gdouble)GST_ROUND_DOWN_8 (width)) / width; ++ scalefy = scalef * ((gdouble)GST_ROUND_DOWN_8 (height)) / height; ++ width = GST_ROUND_DOWN_8 (width); ++ height = GST_ROUND_DOWN_8 (height); ++ GST_DEBUG_OBJECT (overlay, "Rendering with width %d and height %d " ++ , width, height); ++ + if (width <= 0 || height <= 0) { + g_mutex_unlock (GST_BASE_TEXT_OVERLAY_GET_CLASS (overlay)->pango_lock); + GST_DEBUG_OBJECT (overlay, +@@ -1821,7 +1829,7 @@ gst_base_text_overlay_render_pangocairo (GstBaseTextOverlay * overlay, + /* Prepare the transformation matrix. Note that the transformation happens + * in reverse order. So for horizontal text, we will translate and then + * scale. This is important to understand which scale shall be used. */ +- cairo_matrix_init_scale (&cairo_matrix, scalef, scalef); ++ cairo_matrix_init_scale (&cairo_matrix, scalefx, scalefy); + + if (overlay->use_vertical_render) { + gint tmp; +-- +1.9.1 + diff --git a/recipes-multimedia/gstreamer/gstreamer1.0-plugins-base/0010-MMFMWK-7259-Remove-dependence-on-imx-plugin-git.patch b/recipes-multimedia/gstreamer/gstreamer1.0-plugins-base/0010-MMFMWK-7259-Remove-dependence-on-imx-plugin-git.patch new file mode 100644 index 0000000..bd6b1df --- /dev/null +++ b/recipes-multimedia/gstreamer/gstreamer1.0-plugins-base/0010-MMFMWK-7259-Remove-dependence-on-imx-plugin-git.patch @@ -0,0 +1,433 @@ +From d58bab2ab3df3b40d6f65d88d0c827a303e0a651 Mon Sep 17 00:00:00 2001 +From: Haihua Hu +Date: Fri, 5 Aug 2016 17:08:40 +0800 +Subject: [PATCH 11/16] [MMFMWK-7259] Remove dependence on imx plugin git. + +Add physical memory allocator + +Upstream-Status: Inappropriate [i.MX specific] + +Signed-off-by: Haihua Hu +--- + gst-libs/gst/allocators/Makefile.am | 6 +- + gst-libs/gst/allocators/gstallocatorphymem.c | 314 +++++++++++++++++++++++++++ + gst-libs/gst/allocators/gstallocatorphymem.h | 64 ++++++ + 3 files changed, 382 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 bccfdb3..a19c249 100644 +--- a/gst-libs/gst/allocators/Makefile.am ++++ b/gst-libs/gst/allocators/Makefile.am +@@ -5,13 +5,15 @@ libgstallocators_@GST_API_VERSION@_includedir = $(includedir)/gstreamer-@GST_API + libgstallocators_@GST_API_VERSION@_include_HEADERS = \ + allocators.h \ + gstfdmemory.h \ +- gstdmabuf.h ++ gstdmabuf.h \ ++ gstallocatorphymem.h + + noinst_HEADERS = + + libgstallocators_@GST_API_VERSION@_la_SOURCES = \ + gstfdmemory.c \ +- gstdmabuf.c ++ gstdmabuf.c \ ++ gstallocatorphymem.c + + libgstallocators_@GST_API_VERSION@_la_LIBADD = $(GST_LIBS) $(LIBM) + libgstallocators_@GST_API_VERSION@_la_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_CFLAGS) +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 ++#include ++#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 ++#include ++ ++#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-base/0011-Disable-orc-optimization-for-lib-video-in-plugins-ba.patch b/recipes-multimedia/gstreamer/gstreamer1.0-plugins-base/0011-Disable-orc-optimization-for-lib-video-in-plugins-ba.patch new file mode 100644 index 0000000..69e1c9a --- /dev/null +++ b/recipes-multimedia/gstreamer/gstreamer1.0-plugins-base/0011-Disable-orc-optimization-for-lib-video-in-plugins-ba.patch @@ -0,0 +1,34 @@ +From 0100444aa707053fb65bea26feffb5de90909b60 Mon Sep 17 00:00:00 2001 +From: Lyon Wang +Date: Thu, 10 Dec 2015 14:32:43 +0800 +Subject: [PATCH 12/16] Disable orc optimization for lib video in plugins-base + +- the orc optimization for lib video in plugins base may +cause segmentation fault +- disalbe orc optimization for lib video and just use the c source + +package: gstreamer1.0-plugins-base + +Upstream-Status: Pending [https://bugzilla.gnome.org/show_bug.cgi?id=759286] + +Signed-off-by: Lyon Wang +--- + gst-libs/gst/video/Makefile.am | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/gst-libs/gst/video/Makefile.am b/gst-libs/gst/video/Makefile.am +index 64f4978..a197a2f 100644 +--- a/gst-libs/gst/video/Makefile.am ++++ b/gst-libs/gst/video/Makefile.am +@@ -90,7 +90,7 @@ nodist_libgstvideo_@GST_API_VERSION@include_HEADERS = $(built_headers) + noinst_HEADERS = gstvideoutilsprivate.h + + libgstvideo_@GST_API_VERSION@_la_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_BASE_CFLAGS) $(GST_CFLAGS) \ +- $(ORC_CFLAGS) ++ $(ORC_CFLAGS) -DDISABLE_ORC + libgstvideo_@GST_API_VERSION@_la_LIBADD = $(GST_BASE_LIBS) $(GST_LIBS) $(ORC_LIBS) $(LIBM) + libgstvideo_@GST_API_VERSION@_la_LDFLAGS = $(GST_LIB_LDFLAGS) $(GST_ALL_LDFLAGS) $(GST_LT_LDFLAGS) + +-- +1.9.1 + diff --git a/recipes-multimedia/gstreamer/gstreamer1.0-plugins-base/0012-Remove-phymem-allocator-from-base-to-bad.patch b/recipes-multimedia/gstreamer/gstreamer1.0-plugins-base/0012-Remove-phymem-allocator-from-base-to-bad.patch new file mode 100644 index 0000000..5d3aaf9 --- /dev/null +++ b/recipes-multimedia/gstreamer/gstreamer1.0-plugins-base/0012-Remove-phymem-allocator-from-base-to-bad.patch @@ -0,0 +1,37 @@ +From 2ad9aa1c62ff7b7772862ace35dd03bfae3f0fce Mon Sep 17 00:00:00 2001 +From: Haihua Hu +Date: Thu, 25 May 2017 11:31:46 +0800 +Subject: [PATCH 16/16] Remove phymem allocator from base to bad + +Upstream-Status: Inappropriate [i.MX specific] +--- + gst-libs/gst/allocators/Makefile.am | 6 ++---- + 1 file changed, 2 insertions(+), 4 deletions(-) + +diff --git a/gst-libs/gst/allocators/Makefile.am b/gst-libs/gst/allocators/Makefile.am +index 1955436..1c5680b 100644 +--- a/gst-libs/gst/allocators/Makefile.am ++++ b/gst-libs/gst/allocators/Makefile.am +@@ -5,8 +5,7 @@ libgstallocators_@GST_API_VERSION@_includedir = $(includedir)/gstreamer-@GST_API + libgstallocators_@GST_API_VERSION@_include_HEADERS = \ + allocators.h \ + gstfdmemory.h \ +- gstdmabuf.h \ +- gstallocatorphymem.h ++ gstdmabuf.h + + if USE_ION + libgstallocators_@GST_API_VERSION@_include_HEADERS += \ +@@ -17,8 +16,7 @@ noinst_HEADERS = + + libgstallocators_@GST_API_VERSION@_la_SOURCES = \ + gstfdmemory.c \ +- gstdmabuf.c \ +- gstallocatorphymem.c ++ gstdmabuf.c + + if USE_ION + libgstallocators_@GST_API_VERSION@_la_SOURCES += \ +-- +1.9.1 + diff --git a/recipes-multimedia/gstreamer/gstreamer1.0-plugins-base/0013-dmabuf-set-fd-memory-to-keep-mapped.patch b/recipes-multimedia/gstreamer/gstreamer1.0-plugins-base/0013-dmabuf-set-fd-memory-to-keep-mapped.patch new file mode 100644 index 0000000..da3df63 --- /dev/null +++ b/recipes-multimedia/gstreamer/gstreamer1.0-plugins-base/0013-dmabuf-set-fd-memory-to-keep-mapped.patch @@ -0,0 +1,30 @@ +From 59a4c4584f732eea055267971013909816287311 Mon Sep 17 00:00:00 2001 +From: Song Bing +Date: Wed, 13 Sep 2017 13:37:17 -0800 +Subject: [PATCH 4/4] dmabuf: set fd memory to keep mapped + +set fd memory to keep mapped. + +Upstream-Status: Pending + +https://bugzilla.gnome.org/show_bug.cgi?id=768794 +--- + gst-libs/gst/allocators/gstdmabuf.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/gst-libs/gst/allocators/gstdmabuf.c b/gst-libs/gst/allocators/gstdmabuf.c +index 7d6bcab..89bb447 100644 +--- a/gst-libs/gst/allocators/gstdmabuf.c ++++ b/gst-libs/gst/allocators/gstdmabuf.c +@@ -95,7 +95,7 @@ gst_dmabuf_allocator_alloc (GstAllocator * allocator, gint fd, gsize size) + { + g_return_val_if_fail (GST_IS_DMABUF_ALLOCATOR (allocator), NULL); + +- return gst_fd_allocator_alloc (allocator, fd, size, GST_FD_MEMORY_FLAG_NONE); ++ return gst_fd_allocator_alloc (allocator, fd, size, GST_FD_MEMORY_FLAG_KEEP_MAPPED); + } + + /** +-- +2.7.4 + diff --git a/recipes-multimedia/gstreamer/gstreamer1.0-plugins-base/0014-fdmemory-need-unmap-if-mapping-flags-are-not-subset-.patch b/recipes-multimedia/gstreamer/gstreamer1.0-plugins-base/0014-fdmemory-need-unmap-if-mapping-flags-are-not-subset-.patch new file mode 100644 index 0000000..a986d22 --- /dev/null +++ b/recipes-multimedia/gstreamer/gstreamer1.0-plugins-base/0014-fdmemory-need-unmap-if-mapping-flags-are-not-subset-.patch @@ -0,0 +1,36 @@ +From bbce23ade0d17c7ef4dbd6042009e0f2419f9668 Mon Sep 17 00:00:00 2001 +From: Haihua Hu +Date: Mon, 6 Nov 2017 15:05:47 +0800 +Subject: [PATCH] fdmemory: need unmap if mapping flags are not subset of + previous + +Upstream-Status: Pending +https://bugzilla.gnome.org/show_bug.cgi?id=789952 + +--- + gst-libs/gst/allocators/gstfdmemory.c | 8 ++++++-- + 1 file changed, 6 insertions(+), 2 deletions(-) + +diff --git a/gst-libs/gst/allocators/gstfdmemory.c b/gst-libs/gst/allocators/gstfdmemory.c +index ad428a7..1e6125a 100644 +--- a/gst-libs/gst/allocators/gstfdmemory.c ++++ b/gst-libs/gst/allocators/gstfdmemory.c +@@ -97,9 +97,13 @@ gst_fd_mem_map (GstMemory * gmem, gsize maxsize, GstMapFlags flags) + if ((mem->mmapping_flags & prot) == prot) { + ret = mem->data; + mem->mmap_count++; ++ goto out; ++ } else { ++ /* if mapping flags is not a subset, need unmap first */ ++ munmap ((void *) mem->data, gmem->maxsize); ++ mem->data = NULL; ++ mem->mmap_count = 0;; + } +- +- goto out; + } + + if (mem->fd != -1) { +-- +1.9.1 + diff --git a/recipes-multimedia/gstreamer/gstreamer1.0-plugins-base/0015-basetextoverlay-need-avoid-idx-exceed-me.patch b/recipes-multimedia/gstreamer/gstreamer1.0-plugins-base/0015-basetextoverlay-need-avoid-idx-exceed-me.patch new file mode 100644 index 0000000..5fdc93c --- /dev/null +++ b/recipes-multimedia/gstreamer/gstreamer1.0-plugins-base/0015-basetextoverlay-need-avoid-idx-exceed-me.patch @@ -0,0 +1,34 @@ +From f11ab0f14638d21b6e48bff3fd63aaaa0689f21d Mon Sep 17 00:00:00 2001 +From: Haihua Hu +Date: Thu, 30 Nov 2017 17:43:20 +0800 +Subject: [PATCH] [MMFMWK-7786] basetextoverlay: need avoid idx exceed memory + block number + +when check whether video buffer is read only, the gst_buffer_get_memory call +should make sure idx don't exceed the total memory block number + +Upstream-Status: Inappropriate [i.MX specific] + +Signed-off-by: Haihua Hu +--- + ext/pango/gstbasetextoverlay.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/ext/pango/gstbasetextoverlay.c b/ext/pango/gstbasetextoverlay.c +index 7e32904..d2bbbee 100755 +--- a/ext/pango/gstbasetextoverlay.c ++++ b/ext/pango/gstbasetextoverlay.c +@@ -2248,7 +2248,9 @@ gst_base_text_overlay_push_frame (GstBaseTextOverlay * overlay, + gboolean mem_rdonly = FALSE; + GstMemory *mem; + +- while (mem = gst_buffer_get_memory(video_frame, idx++)) { ++ gint n_mem = gst_buffer_n_memory (video_frame); ++ ++ while (idx < n_mem && (mem = gst_buffer_get_memory(video_frame, idx++))) { + if (GST_MEMORY_IS_READONLY(mem)) { + gst_memory_unref (mem); + mem_rdonly = TRUE; +-- +1.9.1 + diff --git a/recipes-multimedia/gstreamer/gstreamer1.0-plugins-base_1.12.%.bbappend b/recipes-multimedia/gstreamer/gstreamer1.0-plugins-base_1.12.%.bbappend new file mode 100644 index 0000000..48c0bb3 --- /dev/null +++ b/recipes-multimedia/gstreamer/gstreamer1.0-plugins-base_1.12.%.bbappend @@ -0,0 +1,25 @@ +FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:" + +# Enable pango lib +PACKAGECONFIG_append = " pango " + +# ion allocator will be enabled only when detecting the ion.h exists, which is built out from kernel. +# For now, ion allocatior is supported on mx7ulp & mx8 +DEPENDS_append_mx7ulp = " virtual/kernel" +DEPENDS_append_mx8 = " virtual/kernel" + +SRC_URI_append_imx = " \ + file://0001-basetextoverlay-make-memory-copy-when-video-buffer-s.patch \ + file://0002-gstplaysink-don-t-set-async-of-custom-text-sink-to-f.patch \ + file://0005-gstplaybin-remove-default-deinterlace-flag.patch \ + file://0006-taglist-not-send-to-down-stream-if-all-the-frame-cor.patch \ + file://0007-handle-audio-video-decoder-error.patch \ + file://0008-gstaudiobasesink-print-warning-istead-of-return-ERRO.patch \ + file://0009-MMFMWK-7030-Linux_MX6QP_ARD-IMXCameraApp-When-Enable.patch \ + file://0010-MMFMWK-7259-Remove-dependence-on-imx-plugin-git.patch \ + file://0011-Disable-orc-optimization-for-lib-video-in-plugins-ba.patch \ + file://0012-Remove-phymem-allocator-from-base-to-bad.patch \ + file://0013-dmabuf-set-fd-memory-to-keep-mapped.patch \ + file://0014-fdmemory-need-unmap-if-mapping-flags-are-not-subset-.patch \ + file://0015-basetextoverlay-need-avoid-idx-exceed-me.patch \ +" diff --git a/recipes-multimedia/gstreamer/gstreamer1.0-plugins-good/0001-Need-to-check-if-pa-stream-is-still-valid.patch b/recipes-multimedia/gstreamer/gstreamer1.0-plugins-good/0001-Need-to-check-if-pa-stream-is-still-valid.patch new file mode 100644 index 0000000..f2ee02e --- /dev/null +++ b/recipes-multimedia/gstreamer/gstreamer1.0-plugins-good/0001-Need-to-check-if-pa-stream-is-still-valid.patch @@ -0,0 +1,39 @@ +From a4af947cb793cd3b9550c76d1ea8db7d3a94612a Mon Sep 17 00:00:00 2001 +From: Jian +Date: Tue, 3 Feb 2015 17:08:40 +0800 +Subject: [PATCH 2/4] Need to check if pa stream is still valid + +Fixed the issue that will report pulse server is dead +when doing audio track switching. +Need to check if pa stream is valid as it may be released +by caps change. + +Upstream-Status: Submitted +https://bugzilla.gnome.org/show_bug.cgi?id=743912 + +Signed-off-by: Jian +--- + ext/pulse/pulsesink.c | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git a/ext/pulse/pulsesink.c b/ext/pulse/pulsesink.c +index 521c4a6..931f1c8 100644 +--- a/ext/pulse/pulsesink.c ++++ b/ext/pulse/pulsesink.c +@@ -2022,6 +2022,13 @@ gst_pulsesink_get_time (GstClock * clock, GstAudioBaseSink * sink) + } + + pa_threaded_mainloop_lock (mainloop); ++ ++ /* Need to check if pa stream is valid as it may be released by caps change*/ ++ if (!pbuf->stream) { ++ pa_threaded_mainloop_unlock (mainloop); ++ return GST_CLOCK_TIME_NONE; ++ } ++ + if (gst_pulsering_is_dead (psink, pbuf, TRUE)) + goto server_dead; + +-- +1.9.1 + diff --git a/recipes-multimedia/gstreamer/gstreamer1.0-plugins-good/0002-Fix-aacpase-error-tolerance-issue.patch b/recipes-multimedia/gstreamer/gstreamer1.0-plugins-good/0002-Fix-aacpase-error-tolerance-issue.patch new file mode 100644 index 0000000..5430df9 --- /dev/null +++ b/recipes-multimedia/gstreamer/gstreamer1.0-plugins-good/0002-Fix-aacpase-error-tolerance-issue.patch @@ -0,0 +1,34 @@ +From db527a6db0c55322174ff6baa389ac8b110ec662 Mon Sep 17 00:00:00 2001 +From: Lyon Wang +Date: Fri, 6 Feb 2015 11:27:47 +0800 +Subject: [PATCH 3/4] Fix aacpase error tolerance issue + +There is no need to check channel configure in adts header. +The channel could be output of decoder. +No need to return fatal error here. + +https://bugzilla.gnome.org/show_bug.cgi?id=743332 + +Upstream-Status: Pending + +Signed-off-by: Lyon Wang +--- + gst/audioparsers/gstaacparse.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/gst/audioparsers/gstaacparse.c b/gst/audioparsers/gstaacparse.c +index cabd961..09a53cc 100644 +--- a/gst/audioparsers/gstaacparse.c ++++ b/gst/audioparsers/gstaacparse.c +@@ -915,7 +915,7 @@ gst_aac_parse_detect_stream (GstAacParse * aacparse, + gst_aac_parse_parse_adts_header (aacparse, data, &rate, &channels, + &aacparse->object_type, &aacparse->mpegversion); + +- if (!channels || !framesize) { ++ if (!framesize) { + GST_DEBUG_OBJECT (aacparse, "impossible ADTS configuration"); + return FALSE; + } +-- +1.9.1 + diff --git a/recipes-multimedia/gstreamer/gstreamer1.0-plugins-good/0003-MMFMWK-7274-mx8dv-Enable-camera-on-mx8dv.patch b/recipes-multimedia/gstreamer/gstreamer1.0-plugins-good/0003-MMFMWK-7274-mx8dv-Enable-camera-on-mx8dv.patch new file mode 100644 index 0000000..66d8ec6 --- /dev/null +++ b/recipes-multimedia/gstreamer/gstreamer1.0-plugins-good/0003-MMFMWK-7274-mx8dv-Enable-camera-on-mx8dv.patch @@ -0,0 +1,37 @@ +From 4a37ac1ffc2952fb6dedec914dcd336dbaf5dff5 Mon Sep 17 00:00:00 2001 +From: Song Bing +Date: Fri, 21 Oct 2016 11:24:05 +0800 +Subject: [PATCH 4/4] MMFMWK-7274 [mx8dv] Enable camera on mx8dv + +Set memory allocate by camera as physical continuoues. + +Signed-off-by: Song Bing bing.song@nxp.com +--- + sys/v4l2/gstv4l2allocator.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/sys/v4l2/gstv4l2allocator.c b/sys/v4l2/gstv4l2allocator.c +index 2047383..ecab01e 100644 +--- a/sys/v4l2/gstv4l2allocator.c ++++ b/sys/v4l2/gstv4l2allocator.c +@@ -818,7 +818,7 @@ gst_v4l2_allocator_alloc_mmap (GstV4l2Allocator * allocator) + "mmap buffer length %d, data offset %d, plane %d", + group->planes[i].length, group->planes[i].data_offset, i); + +- group->mem[i] = (GstMemory *) _v4l2mem_new (0, GST_ALLOCATOR (allocator), ++ group->mem[i] = (GstMemory *) _v4l2mem_new (GST_MEMORY_FLAG_PHYSICALLY_CONTIGUOUS, GST_ALLOCATOR (allocator), + NULL, group->planes[i].length, 0, 0, group->planes[i].length, i, + data, -1, group); + } else { +@@ -879,7 +879,7 @@ gst_v4l2_allocator_alloc_dmabuf (GstV4l2Allocator * allocator, + GST_LOG_OBJECT (allocator, "exported DMABUF as fd %i plane %d", + expbuf.fd, i); + +- group->mem[i] = (GstMemory *) _v4l2mem_new (0, GST_ALLOCATOR (allocator), ++ group->mem[i] = (GstMemory *) _v4l2mem_new (GST_MEMORY_FLAG_PHYSICALLY_CONTIGUOUS, GST_ALLOCATOR (allocator), + NULL, group->planes[i].length, 0, 0, group->planes[i].length, i, + NULL, expbuf.fd, group); + } else { +-- +1.9.1 + diff --git a/recipes-multimedia/gstreamer/gstreamer1.0-plugins-good/0004-gstaacparse-Fix-adif-aac-file-read-channel-progile-i.patch b/recipes-multimedia/gstreamer/gstreamer1.0-plugins-good/0004-gstaacparse-Fix-adif-aac-file-read-channel-progile-i.patch new file mode 100644 index 0000000..a77917c --- /dev/null +++ b/recipes-multimedia/gstreamer/gstreamer1.0-plugins-good/0004-gstaacparse-Fix-adif-aac-file-read-channel-progile-i.patch @@ -0,0 +1,267 @@ +From b2c850f295a0fe49310fb60784ac6af4a29bceae Mon Sep 17 00:00:00 2001 +From: Lyon Wang +Date: Fri, 9 Jun 2017 16:53:11 +0800 +Subject: [PATCH] gstaacparse: Fix adif aac file read channel/progile issue + +- parser adif program_config_element() to get correct channel +- Fix aacparse src pad caps wrong profile for ADIF file + +Upstream status: submitted. +Combined 2 bugzilla ticket: +https://bugzilla.gnome.org/show_bug.cgi?id=783583 +https://bugzilla.gnome.org/show_bug.cgi?id=785476 + +Signed-off-by: Lyon Wang +--- + gst/audioparsers/gstaacparse.c | 203 ++++++++++++++++++++++++++++++----------- + 1 file changed, 152 insertions(+), 51 deletions(-) + +diff --git a/gst/audioparsers/gstaacparse.c b/gst/audioparsers/gstaacparse.c +index 16d66e2..e2c2bc9 100644 +--- a/gst/audioparsers/gstaacparse.c ++++ b/gst/audioparsers/gstaacparse.c +@@ -85,6 +85,35 @@ static const gint loas_channels_table[16] = { + 0, 0, 0, 7, 8, 0, 8, 0 + }; + ++typedef struct ++{ ++ guint32 num_ele; ++ guint32 ele_is_cpe[16]; ++ guint32 ele_tag[16]; ++} GstAacEleList; ++ ++typedef struct ++{ ++ guint32 present; ++ guint32 ele_tag; ++ guint32 pseudo_enab; ++} GstAacMIXdown; ++ ++typedef struct ++{ ++ guint32 profile; ++ guint32 sr_idx; ++ GstAacEleList front; ++ GstAacEleList side; ++ GstAacEleList back; ++ GstAacEleList data; ++ GstAacEleList lfe; ++ GstAacEleList coupling; ++ GstAacMIXdown mono_mix; ++ GstAacMIXdown stereo_mix; ++ GstAacMIXdown matrix_mix; ++} GstAacProgConfig; ++ + static gboolean gst_aac_parse_start (GstBaseParse * parse); + static gboolean gst_aac_parse_stop (GstBaseParse * parse); + +@@ -104,6 +133,9 @@ static gboolean gst_aac_parse_read_audio_specific_config (GstAacParse * + aacparse, GstBitReader * br, gint * object_type, gint * sample_rate, + gint * channels, gint * frame_samples); + ++static gboolean gst_aac_parse_read_program_config_element (GstAacProgConfig * ++ progConfig, GstBitReader * br); ++ + + #define gst_aac_parse_parent_class parent_class + G_DEFINE_TYPE (GstAacParse, gst_aac_parse, GST_TYPE_BASE_PARSE); +@@ -844,6 +876,87 @@ gst_aac_parse_parse_adts_header (GstAacParse * aacparse, const guint8 * data, + *object = ((data[2] & 0xc0) >> 6) + 1; + } + ++static void ++gst_aac_parse_get_ele_list (GstAacEleList * pList, gint32 cpe, ++ GstBitReader * br) ++{ ++ guint32 count, num_elem; ++ num_elem = pList->num_ele; ++ for (count = 0; count < num_elem; count++) { ++ if (cpe) { ++ gst_bit_reader_get_bits_uint32 (br, &(pList->ele_is_cpe[count]), 1); ++ } else { ++ pList->ele_is_cpe[count] = 0; ++ } ++ gst_bit_reader_get_bits_uint32 (br, &(pList->ele_tag[count]), 4); ++ } ++} ++ ++static gint32 ++gst_aac_parse_get_config_channels (GstAacEleList * pList) ++{ ++ guint32 count, num_elem, channels = 0; ++ num_elem = pList->num_ele; ++ for (count = 0; count < num_elem; count++) { ++ channels++; ++ if (pList->ele_is_cpe[count] == 1) { ++ /* CPE element channels++ */ ++ channels++; ++ } ++ } ++ return channels; ++} ++ ++/* Read program config element ++ISO/IEC 14496-3, 4.4.1.1 read program config element */ ++static gboolean ++gst_aac_parse_read_program_config_element (GstAacProgConfig * ++ progConfig, GstBitReader * br) ++{ ++ guint32 count = 0; ++ guint32 bytes = 0; ++ ++ gst_bit_reader_skip (br, 4); //element_instance_tag ++ ++ gst_bit_reader_get_bits_uint32 (br, &progConfig->profile, 2); ++ gst_bit_reader_get_bits_uint32 (br, &progConfig->sr_idx, 4); ++ gst_bit_reader_get_bits_uint32 (br, &(progConfig->front.num_ele), 4); ++ gst_bit_reader_get_bits_uint32 (br, &(progConfig->side.num_ele), 4); ++ gst_bit_reader_get_bits_uint32 (br, &(progConfig->back.num_ele), 4); ++ gst_bit_reader_get_bits_uint32 (br, &(progConfig->lfe.num_ele), 2); ++ gst_bit_reader_get_bits_uint32 (br, &(progConfig->data.num_ele), 3); ++ gst_bit_reader_get_bits_uint32 (br, &(progConfig->coupling.num_ele), 4); ++ ++ gst_bit_reader_get_bits_uint32 (br, &(progConfig->mono_mix.present), 1); ++ if (progConfig->mono_mix.present) { ++ gst_bit_reader_get_bits_uint32 (br, &(progConfig->mono_mix.ele_tag), 4); ++ } ++ gst_bit_reader_get_bits_uint32 (br, &(progConfig->stereo_mix.present), 1); ++ if (progConfig->mono_mix.present) { ++ gst_bit_reader_get_bits_uint32 (br, &(progConfig->stereo_mix.ele_tag), 4); ++ } ++ gst_bit_reader_get_bits_uint32 (br, &(progConfig->matrix_mix.present), 1); ++ if (progConfig->mono_mix.present) { ++ gst_bit_reader_get_bits_uint32 (br, &(progConfig->matrix_mix.ele_tag), 2); ++ gst_bit_reader_get_bits_uint32 (br, &(progConfig->matrix_mix.pseudo_enab), 1); ++ } ++ ++ gst_aac_parse_get_ele_list (&progConfig->front, 1, br); ++ gst_aac_parse_get_ele_list (&progConfig->side, 1, br); ++ gst_aac_parse_get_ele_list (&progConfig->back, 1, br); ++ gst_aac_parse_get_ele_list (&progConfig->data, 0, br); ++ gst_aac_parse_get_ele_list (&progConfig->lfe, 0, br); ++ gst_aac_parse_get_ele_list (&progConfig->coupling, 1, br); ++ ++ gst_bit_reader_skip_to_byte (br); // byte_alignment ++ ++ gst_bit_reader_get_bits_uint32 (br, &bytes, 8); //comment_field_bytes ++ for (count = 0; count < bytes; count++) { ++ gst_bit_reader_skip (br, 8); //skip comment data ++ } ++ return TRUE; ++} ++ + /** + * gst_aac_parse_detect_stream: + * @aacparse: #GstAacParse. +@@ -973,68 +1086,56 @@ gst_aac_parse_detect_stream (GstAacParse * aacparse, + return FALSE; + + if (memcmp (data + i, "ADIF", 4) == 0) { +- const guint8 *adif; +- int skip_size = 0; +- int bitstream_type; ++ GstBitReader br; ++ guint8 u8 = 0; ++ guint8 bitstream_type = 0; ++ guint num_elems = 0; ++ guint bitrate = 0; ++ guint count; + int sr_idx; + GstCaps *sinkcaps; +- ++ GstAacProgConfig *progConfig; + aacparse->header_type = DSPAAC_HEADER_ADIF; + aacparse->mpegversion = 4; +- +- /* Skip the "ADIF" bytes */ +- adif = data + i + 4; +- +- /* copyright string */ +- if (adif[0] & 0x80) +- skip_size += 9; /* skip 9 bytes */ +- +- bitstream_type = adif[0 + skip_size] & 0x10; +- aacparse->bitrate = +- ((unsigned int) (adif[0 + skip_size] & 0x0f) << 19) | +- ((unsigned int) adif[1 + skip_size] << 11) | +- ((unsigned int) adif[2 + skip_size] << 3) | +- ((unsigned int) adif[3 + skip_size] & 0xe0); +- +- /* CBR */ ++ gst_bit_reader_init (&br, data + i, avail - i); ++ /* skip sync word (adif 4 byte ) */ ++ gst_bit_reader_skip (&br, 32); ++ gst_bit_reader_get_bits_uint8 (&br, &u8, 1); ++ if (u8) { ++ gst_bit_reader_skip (&br, 72); //copyright_id ++ } ++ gst_bit_reader_skip (&br, 2); // original_copy and home ++ gst_bit_reader_get_bits_uint8 (&br, &bitstream_type, 1); ++ gst_bit_reader_get_bits_uint32 (&br, &bitrate, 23); ++ gst_bit_reader_get_bits_uint32 (&br, &num_elems, 4); + if (bitstream_type == 0) { +-#if 0 +- /* Buffer fullness parsing. Currently not needed... */ +- guint num_elems = 0; +- guint fullness = 0; +- +- num_elems = (adif[3 + skip_size] & 0x1e); +- GST_INFO ("ADIF num_config_elems: %d", num_elems); +- +- fullness = ((unsigned int) (adif[3 + skip_size] & 0x01) << 19) | +- ((unsigned int) adif[4 + skip_size] << 11) | +- ((unsigned int) adif[5 + skip_size] << 3) | +- ((unsigned int) (adif[6 + skip_size] & 0xe0) >> 5); +- +- GST_INFO ("ADIF buffer fullness: %d", fullness); +-#endif +- aacparse->object_type = ((adif[6 + skip_size] & 0x01) << 1) | +- ((adif[7 + skip_size] & 0x80) >> 7); +- sr_idx = (adif[7 + skip_size] & 0x78) >> 3; ++ gst_bit_reader_skip (&br, 20); //adif_buffer_fullness + } +- /* VBR */ +- else { +- aacparse->object_type = (adif[4 + skip_size] & 0x18) >> 3; +- sr_idx = ((adif[4 + skip_size] & 0x07) << 1) | +- ((adif[5 + skip_size] & 0x80) >> 7); ++ ++ progConfig = ++ (GstAacProgConfig *) g_malloc0 ((num_elems+1) * sizeof (GstAacProgConfig)); ++ for ( count = 0; count < num_elems + 1; count++) { ++ gst_aac_parse_read_program_config_element (&progConfig[count], &br); ++ aacparse->channels += ++ gst_aac_parse_get_config_channels (&(progConfig[count].front)); ++ aacparse->channels += ++ gst_aac_parse_get_config_channels (&(progConfig[count].side)); ++ aacparse->channels += ++ gst_aac_parse_get_config_channels (&(progConfig[count].back)); ++ aacparse->channels += ++ gst_aac_parse_get_config_channels (&(progConfig[count].lfe)); ++ aacparse->channels += ++ gst_aac_parse_get_config_channels (&(progConfig[count].coupling)); + } + +- /* FIXME: This gives totally wrong results. Duration calculation cannot +- be based on this */ ++ aacparse->bitrate = (gint)bitrate; ++ aacparse->object_type = progConfig[0].profile + 1; ++ sr_idx = progConfig[0].sr_idx; ++ g_free(progConfig); ++ + aacparse->sample_rate = + gst_codec_utils_aac_get_sample_rate_from_index (sr_idx); + +- /* baseparse is not given any fps, +- * so it will give up on timestamps, seeking, etc */ +- +- /* FIXME: Can we assume this? */ +- aacparse->channels = 2; +- + GST_INFO ("ADIF: br=%d, samplerate=%d, objtype=%d", + aacparse->bitrate, aacparse->sample_rate, aacparse->object_type); + +-- +1.9.1 + diff --git a/recipes-multimedia/gstreamer/gstreamer1.0-plugins-good_1.12.%.bbappend b/recipes-multimedia/gstreamer/gstreamer1.0-plugins-good_1.12.%.bbappend new file mode 100644 index 0000000..9ba5fc5 --- /dev/null +++ b/recipes-multimedia/gstreamer/gstreamer1.0-plugins-good_1.12.%.bbappend @@ -0,0 +1,8 @@ +FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:" + +SRC_URI_append_imx = " \ + file://0001-Need-to-check-if-pa-stream-is-still-valid.patch \ + file://0002-Fix-aacpase-error-tolerance-issue.patch \ + file://0003-MMFMWK-7274-mx8dv-Enable-camera-on-mx8dv.patch \ + file://0004-gstaacparse-Fix-adif-aac-file-read-channel-progile-i.patch \ +" diff --git a/recipes-multimedia/gstreamer/gstreamer1.0-plugins-imx_0.13.0.bb b/recipes-multimedia/gstreamer/gstreamer1.0-plugins-imx_0.13.0.bb new file mode 100644 index 0000000..d996bb3 --- /dev/null +++ b/recipes-multimedia/gstreamer/gstreamer1.0-plugins-imx_0.13.0.bb @@ -0,0 +1,69 @@ +DESCRIPTION = "GStreamer 1.0 plugins for i.MX platforms" +LICENSE = "LGPLv2+" +LIC_FILES_CHKSUM = "file://LICENSE;md5=55ca817ccb7d5b5b66355690e9abc605" +SECTION = "multimedia" +# gstreamer1.0-plugins-bad is in DEPENDS because the build script scans for the +# GstPhotography headers and libraries +DEPENDS = "gstreamer1.0 gstreamer1.0-plugins-base gstreamer1.0-plugins-bad virtual/kernel" +# add the audioparsers and the videoparsersbad plugins as RDEPENDS ; audioparsers +# for the uniaudio decoder, videoparsersbad for the VPU video decoder +# the gstreamer1.0-plugins-imx RDEPENDS is necessary to ensure the -good recipe is +# build (it is not a compile-time dependency however, hence RDEPENDS and not DEPENDS) +RDEPENDS_gstreamer1.0-plugins-imx = "gstreamer1.0-plugins-good" +RDEPENDS_gstreamer1.0-plugins-imx-imxaudio = "gstreamer1.0-plugins-good-audioparsers" +RDEPENDS_gstreamer1.0-plugins-imx-imxvpu = "gstreamer1.0-plugins-bad-videoparsersbad" + +SRCBRANCH ?= "master" +SRCREV = "048d596dfc657f16d235029c39221b0a118e5c87" +SRC_URI = "git://github.com/Freescale/gstreamer-imx.git;branch=${SRCBRANCH}" + +S = "${WORKDIR}/git" + +inherit pkgconfig waf + +do_compile[depends] += "virtual/kernel:do_shared_workdir" + +# configure the eglvivsink element to use the appropriate EGL platform code +# Wayland if 'wayland' is present in DISTRO_FEATURES, if not, +# X11 if x11 is present in DISTRO_FEATURES, +# Framebuffer otherwise +EGLVIVSINK_PLATFORM = "${@bb.utils.contains('DISTRO_FEATURES', 'wayland', 'wayland', \ + bb.utils.contains('DISTRO_FEATURES', 'x11', 'x11', \ + 'fb', d),d)}" + +EGL_PLATFORM_CONF = "--egl-platform=${EGLVIVSINK_PLATFORM}" +EXTRA_OECONF = "--libdir=${libdir} --kernel-headers=${STAGING_KERNEL_DIR}/include ${PACKAGECONFIG_CONFARGS}" + +EGLVIVSINK_DEPENDS = " \ + virtual/egl virtual/libgles2 \ + ${@bb.utils.contains('DISTRO_FEATURES', 'wayland', 'wayland', \ + bb.utils.contains('DISTRO_FEATURES', 'x11', 'virtual/libx11', \ + '', d), d)} \ +" + +PACKAGECONFIG ?= "uniaudiodec mp3encoder v4l2src v4l2sink" +PACKAGECONFIG_append_imxgpu3d = " eglvivsink" +PACKAGECONFIG_append_imxgpu2d = " g2d g2dpango" +PACKAGECONFIG_append_imxipu = " ipu" +PACKAGECONFIG_append_imxvpu = " vpu" +PACKAGECONFIG_append_imxpxp = " pxp" + +PACKAGECONFIG[g2d] = ",--disable-g2d,imx-gpu-viv" +PACKAGECONFIG[g2dpango] = ",--disable-g2dpango,imx-gpu-viv pango" +PACKAGECONFIG[pxp] = ",--disable-pxp," +PACKAGECONFIG[ipu] = ",--disable-ipu," +PACKAGECONFIG[vpu] = ",--disable-vpu,libimxvpuapi" +PACKAGECONFIG[eglvivsink] = "${EGL_PLATFORM_CONF},--disable-eglvivsink,${EGLVIVSINK_DEPENDS}" +PACKAGECONFIG[v4l2src] = ",--disable-imxv4l2videosrc," +PACKAGECONFIG[v4l2sink] = ",--disable-imxv4l2videosink," +PACKAGECONFIG[uniaudiodec] = ",--disable-uniaudiodec,imx-codec" +PACKAGECONFIG[mp3encoder] = ",--disable-mp3encoder,imx-codec" + +# LIBV is used by gst-plugins-package.inc to specify the GStreamer version (0.10 vs 1.0) +LIBV = "1.0" +require recipes-multimedia/gstreamer/gst-plugins-package.inc + +# the following line is required to produce one package for each plugin +PACKAGES_DYNAMIC = "^${PN}-.*" + +COMPATIBLE_MACHINE = "(mx6dl|mx6q|mx6sl|mx6sx|mx6ul|mx6ull|mx7d)" diff --git a/recipes-multimedia/gstreamer/gstreamer1.0/0001-handle-base-parse-error.patch b/recipes-multimedia/gstreamer/gstreamer1.0/0001-handle-base-parse-error.patch new file mode 100644 index 0000000..3aaa636 --- /dev/null +++ b/recipes-multimedia/gstreamer/gstreamer1.0/0001-handle-base-parse-error.patch @@ -0,0 +1,35 @@ +From 01b047cbb5e326fb3980bb6fc5206a82ea401170 Mon Sep 17 00:00:00 2001 +From: Lyon Wang +Date: Wed, 14 Oct 2015 14:15:11 +0800 +Subject: [PATCH 1/7] handle base parse error + +There is no need to send GST_ELEMENT_ERROR +becuase ohter tracks may still good to play. +no need to end the element, just print error message is enough + +Upstream-Status: Submitted [https://bugzilla.gnome.org/show_bug.cgi?id=741542] + +Signed-off-by: Lyon Wang +--- + libs/gst/base/gstbaseparse.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/libs/gst/base/gstbaseparse.c b/libs/gst/base/gstbaseparse.c +index df67dd0..2f45d23 100644 +--- a/libs/gst/base/gstbaseparse.c ++++ b/libs/gst/base/gstbaseparse.c +@@ -1324,8 +1324,9 @@ gst_base_parse_sink_event_default (GstBaseParse * parse, GstEvent * event) + /* If we STILL have zero frames processed, fire an error */ + if (parse->priv->framecount == 0 && !parse->priv->saw_gaps && + !parse->priv->first_buffer) { +- GST_ELEMENT_ERROR (parse, STREAM, WRONG_TYPE, +- ("No valid frames found before end of stream"), (NULL)); ++ /* GST_ELEMENT_ERROR (parse, STREAM, WRONG_TYPE, ++ ("No valid frames found before end of stream"), (NULL));*/ ++ GST_ERROR_OBJECT(parse, "No valid frames decoded before end of stream"); + } + + if (!parse->priv->saw_gaps +-- +1.9.1 + diff --git a/recipes-multimedia/gstreamer/gstreamer1.0/0002-Fix-crash-with-gst-inspect-Chris-Lord-chris-openedha.patch b/recipes-multimedia/gstreamer/gstreamer1.0/0002-Fix-crash-with-gst-inspect-Chris-Lord-chris-openedha.patch new file mode 100644 index 0000000..1bd381b --- /dev/null +++ b/recipes-multimedia/gstreamer/gstreamer1.0/0002-Fix-crash-with-gst-inspect-Chris-Lord-chris-openedha.patch @@ -0,0 +1,32 @@ +From 1bd9b30040ad23d86faa577baeb1c6734f39150f Mon Sep 17 00:00:00 2001 +From: Carlos Rafael Giani +Date: Sat, 6 Apr 2013 23:52:11 +0200 +Subject: [PATCH 2/7] Fix crash with gst-inspect Chris Lord + + +Upstream-Status: Pending + +Signed-off-by: Carlos Rafael Giani + +Conflicts: + tools/gst-inspect.c +--- + tools/gst-inspect.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/tools/gst-inspect.c b/tools/gst-inspect.c +index e420e4c..95983bc 100644 +--- a/tools/gst-inspect.c ++++ b/tools/gst-inspect.c +@@ -1548,7 +1548,7 @@ main (int argc, char *argv[]) + g_option_context_add_main_entries (ctx, options, GETTEXT_PACKAGE); + g_option_context_add_group (ctx, gst_init_get_option_group ()); + if (!g_option_context_parse (ctx, &argc, &argv, &err)) { +- g_printerr ("Error initializing: %s\n", err->message); ++ g_printerr ("Error initializing: %s\n", err ? err->message : "(null)"); + g_clear_error (&err); + g_option_context_free (ctx); + return -1; +-- +1.9.1 + diff --git a/recipes-multimedia/gstreamer/gstreamer1.0/0003-baseparse-unset-FLAG_DISCONT-when-push-to-adapter.patch b/recipes-multimedia/gstreamer/gstreamer1.0/0003-baseparse-unset-FLAG_DISCONT-when-push-to-adapter.patch new file mode 100644 index 0000000..9758d9c --- /dev/null +++ b/recipes-multimedia/gstreamer/gstreamer1.0/0003-baseparse-unset-FLAG_DISCONT-when-push-to-adapter.patch @@ -0,0 +1,33 @@ +From 95d80584413c60cfe302cb2b55f59ffdca2a67b9 Mon Sep 17 00:00:00 2001 +From: Lyon Wang +Date: Wed, 4 Nov 2015 18:16:52 +0800 +Subject: [PATCH 3/7] [baseparse] unset FLAG_DISCONT when push to adapter + +Since DISCONT flag will be handled by priv->discont flag. +There is no need to copy DISCONT flag to adapter. +Otherwise, the DISCONT flag will alwasys been set on each frame, +for the first chain in buffer. + + +Upstream-Status: Pending [https://bugzilla.gnome.org/show_bug.cgi?id=757575] + +Signed-off-by: Lyon Wang +--- + libs/gst/base/gstbaseparse.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/libs/gst/base/gstbaseparse.c b/libs/gst/base/gstbaseparse.c +index 2f45d23..3c52887 100644 +--- a/libs/gst/base/gstbaseparse.c ++++ b/libs/gst/base/gstbaseparse.c +@@ -3157,6 +3157,7 @@ gst_base_parse_chain (GstPad * pad, GstObject * parent, GstBuffer * buffer) + parse->priv->discont = TRUE; + } + } ++ GST_BUFFER_FLAG_UNSET(buffer, GST_BUFFER_FLAG_DISCONT); + gst_adapter_push (parse->priv->adapter, buffer); + } + +-- +1.9.1 + diff --git a/recipes-multimedia/gstreamer/gstreamer1.0/0004-gstbaseparse-Need-push-adapter-remainning-data-in-pa.patch b/recipes-multimedia/gstreamer/gstreamer1.0/0004-gstbaseparse-Need-push-adapter-remainning-data-in-pa.patch new file mode 100644 index 0000000..303e108 --- /dev/null +++ b/recipes-multimedia/gstreamer/gstreamer1.0/0004-gstbaseparse-Need-push-adapter-remainning-data-in-pa.patch @@ -0,0 +1,51 @@ +From b7f3a53b5d43c40fc1432c12f2ca314c5dbf403b Mon Sep 17 00:00:00 2001 +From: Lyon Wang +Date: Fri, 15 Jan 2016 17:30:14 +0800 +Subject: [PATCH 4/7] [gstbaseparse] Need push adapter remainning data in pass + through mode + +When switching to pass through mode, there might be remainning +data in the adpater, and it will be no chance to push to downstream when +in pass through mode. +So need check adapter available data and push downstream to avoid missing data + +package: gstreamer1.0 +Upstream-Status: Pending [https://bugzilla.gnome.org/show_bug.cgi?id=760513] + +Signed-off-by: Lyon Wang +--- + libs/gst/base/gstbaseparse.c | 15 +++++++++++++++ + 1 file changed, 15 insertions(+) + mode change 100644 => 100755 libs/gst/base/gstbaseparse.c + +diff --git a/libs/gst/base/gstbaseparse.c b/libs/gst/base/gstbaseparse.c +old mode 100644 +new mode 100755 +index 3c52887..6d3eacf +--- a/libs/gst/base/gstbaseparse.c ++++ b/libs/gst/base/gstbaseparse.c +@@ -3138,6 +3138,21 @@ gst_base_parse_chain (GstPad * pad, GstObject * parent, GstBuffer * buffer) + && parse->priv->passthrough)) { + GstBaseParseFrame frame; + ++ av = gst_adapter_available (parse->priv->adapter); ++ if (av) { ++ tmpbuf = gst_adapter_take_buffer (parse->priv->adapter, av); ++ ++ if (parse->priv->upstream_format == GST_FORMAT_TIME) { ++ tmpbuf = gst_buffer_make_writable (tmpbuf); ++ GST_BUFFER_PTS (tmpbuf) = parse->priv->next_pts; ++ GST_BUFFER_DTS (tmpbuf) = parse->priv->next_dts; ++ GST_BUFFER_DURATION (tmpbuf) = GST_CLOCK_TIME_NONE; ++ } ++ ++ ret = gst_pad_push (parse->srcpad, tmpbuf); ++ ++ } ++ + gst_base_parse_frame_init (&frame); + frame.buffer = gst_buffer_make_writable (buffer); + ret = gst_base_parse_push_frame (parse, &frame); +-- +1.9.1 + diff --git a/recipes-multimedia/gstreamer/gstreamer1.0/0005-inputselector-should-proceed-non-active-pad-buffer-e.patch b/recipes-multimedia/gstreamer/gstreamer1.0/0005-inputselector-should-proceed-non-active-pad-buffer-e.patch new file mode 100644 index 0000000..f35ca04 --- /dev/null +++ b/recipes-multimedia/gstreamer/gstreamer1.0/0005-inputselector-should-proceed-non-active-pad-buffer-e.patch @@ -0,0 +1,51 @@ +From 7f7398acb5dc5fdc904f6684eab2bb072be25de7 Mon Sep 17 00:00:00 2001 +From: Song Bing +Date: Wed, 11 May 2016 16:57:23 +0800 +Subject: [PATCH 5/7] inputselector: should proceed non-active pad buffer even + if active pad reach eos + +non-active pad will be blocked if active pad reach eos in inputselector. +Which will cause all pipeline be blocked. +Inputselector should proceed non-active pad buffer based on clock even +if active pad reach eos +Change to sync with clock for better user experience. + + +Upstream-Status: Pending [https://bugzilla.gnome.org/show_bug.cgi?id=766261] + +Signed-off-by: Song Bing bing.song@nxp.com +--- + plugins/elements/gstinputselector.c | 10 ++++++++-- + 1 file changed, 8 insertions(+), 2 deletions(-) + +diff --git a/plugins/elements/gstinputselector.c b/plugins/elements/gstinputselector.c +index f3f95e6..f6e1993 100644 +--- a/plugins/elements/gstinputselector.c ++++ b/plugins/elements/gstinputselector.c +@@ -772,7 +772,7 @@ gst_input_selector_wait_running_time (GstInputSelector * sel, + } + + cur_running_time = GST_CLOCK_TIME_NONE; +- if (sel->sync_mode == GST_INPUT_SELECTOR_SYNC_MODE_CLOCK) { ++ if (sel->sync_mode == GST_INPUT_SELECTOR_SYNC_MODE_CLOCK || active_selpad->eos) { + clock = gst_element_get_clock (GST_ELEMENT_CAST (sel)); + if (clock) { + GstClockTime base_time; +@@ -823,7 +823,13 @@ gst_input_selector_wait_running_time (GstInputSelector * sel, + "Waiting for active streams to advance. %" GST_TIME_FORMAT " >= %" + GST_TIME_FORMAT, GST_TIME_ARGS (running_time), + GST_TIME_ARGS (cur_running_time)); +- GST_INPUT_SELECTOR_WAIT (sel); ++ if (active_selpad->eos) { ++ GST_INPUT_SELECTOR_UNLOCK (sel); ++ g_usleep (5000); ++ GST_INPUT_SELECTOR_LOCK (sel); ++ } else { ++ GST_INPUT_SELECTOR_WAIT (sel); ++ } + } else { + GST_INPUT_SELECTOR_UNLOCK (sel); + break; +-- +1.9.1 + diff --git a/recipes-multimedia/gstreamer/gstreamer1.0/0006-poll-Add-check-if-can-read-event-API.patch b/recipes-multimedia/gstreamer/gstreamer1.0/0006-poll-Add-check-if-can-read-event-API.patch new file mode 100644 index 0000000..9a6cf47 --- /dev/null +++ b/recipes-multimedia/gstreamer/gstreamer1.0/0006-poll-Add-check-if-can-read-event-API.patch @@ -0,0 +1,95 @@ +From 6daed66db8a147783acc117b76afa2e779c8c12c Mon Sep 17 00:00:00 2001 +From: Song Bing +Date: Thu, 20 Aug 2015 14:57:46 +0800 +Subject: [PATCH 6/7] poll: Add check if can read event API + +Need check if can read event of buffer for video decoder based on +V4L2 driver. Add the API for it. + + +Upstream-Status: Pending [https://bugzilla.gnome.org/show_bug.cgi?id=752962] + +Signed-off-by: Song Bing bing.song@nxp.com +--- + gst/gstpoll.c | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++++ + gst/gstpoll.h | 1 + + 2 files changed, 53 insertions(+) + +diff --git a/gst/gstpoll.c b/gst/gstpoll.c +index fd672ed..084f6f7 100644 +--- a/gst/gstpoll.c ++++ b/gst/gstpoll.c +@@ -1242,6 +1242,58 @@ gst_poll_fd_can_read (const GstPoll * set, GstPollFD * fd) + return res; + } + ++static gboolean ++gst_poll_fd_can_read_pri_unlocked (const GstPoll * set, GstPollFD * fd) ++{ ++ gboolean res = FALSE; ++ gint idx; ++ ++ idx = find_index (set->active_fds, fd); ++ if (idx >= 0) { ++#ifndef G_OS_WIN32 ++ struct pollfd *pfd = &g_array_index (set->active_fds, struct pollfd, idx); ++ ++ res = (pfd->revents & POLLPRI) != 0; ++#else ++ WinsockFd *wfd = &g_array_index (set->active_fds, WinsockFd, idx); ++ ++ res = (wfd->events.lNetworkEvents & FD_ACCEPT) != 0; ++#endif ++ } else { ++ GST_WARNING ("%p: couldn't find fd !", set); ++ } ++ GST_DEBUG ("%p: fd (fd:%d, idx:%d) %d", set, fd->fd, fd->idx, res); ++ ++ return res; ++} ++ ++/** ++ * gst_poll_fd_can_read_pri: ++ * @set: a file descriptor set. ++ * @fd: a file descriptor. ++ * ++ * Check if @fd in @set has data to be read. ++ * ++ * Returns: %TRUE if the descriptor has data to be read. ++ */ ++gboolean ++gst_poll_fd_can_read_pri (const GstPoll * set, GstPollFD * fd) ++{ ++ gboolean res = FALSE; ++ ++ g_return_val_if_fail (set != NULL, FALSE); ++ g_return_val_if_fail (fd != NULL, FALSE); ++ g_return_val_if_fail (fd->fd >= 0, FALSE); ++ ++ g_mutex_lock (&((GstPoll *) set)->lock); ++ ++ res = gst_poll_fd_can_read_pri_unlocked (set, fd); ++ ++ g_mutex_unlock (&((GstPoll *) set)->lock); ++ ++ return res; ++} ++ + /** + * gst_poll_fd_can_write: + * @set: a file descriptor set. +diff --git a/gst/gstpoll.h b/gst/gstpoll.h +index ef6dcea..0513648 100644 +--- a/gst/gstpoll.h ++++ b/gst/gstpoll.h +@@ -79,6 +79,7 @@ void gst_poll_fd_ignored (GstPoll *set, GstPollFD *fd); + gboolean gst_poll_fd_has_closed (const GstPoll *set, GstPollFD *fd); + gboolean gst_poll_fd_has_error (const GstPoll *set, GstPollFD *fd); + gboolean gst_poll_fd_can_read (const GstPoll *set, GstPollFD *fd); ++gboolean gst_poll_fd_can_read_pri (const GstPoll *set, GstPollFD *fd); + gboolean gst_poll_fd_can_write (const GstPoll *set, GstPollFD *fd); + + gint gst_poll_wait (GstPoll *set, GstClockTime timeout); +-- +1.9.1 + diff --git a/recipes-multimedia/gstreamer/gstreamer1.0/0007-inputselector-Need-flush-when-set-active-pad-and-the.patch b/recipes-multimedia/gstreamer/gstreamer1.0/0007-inputselector-Need-flush-when-set-active-pad-and-the.patch new file mode 100644 index 0000000..c5d329b --- /dev/null +++ b/recipes-multimedia/gstreamer/gstreamer1.0/0007-inputselector-Need-flush-when-set-active-pad-and-the.patch @@ -0,0 +1,68 @@ +From 9860e95c4c6bcec422b6c83a2650ef76dd6a5488 Mon Sep 17 00:00:00 2001 +From: Song Bing +Date: Wed, 10 May 2017 11:24:46 +0800 +Subject: [PATCH 7/7] inputselector: Need flush when set active pad and then + seek in PAUSE state + + +Upstream-Status: Pending [https://bugzilla.gnome.org/show_bug.cgi?id=782417] + +Signed-off-by: Song Bing bing.song@nxp.com +--- + plugins/elements/gstinputselector.c | 11 ++++++++++- + 1 file changed, 10 insertions(+), 1 deletion(-) + +diff --git a/plugins/elements/gstinputselector.c b/plugins/elements/gstinputselector.c +index f6e1993..54400dd 100644 +--- a/plugins/elements/gstinputselector.c ++++ b/plugins/elements/gstinputselector.c +@@ -161,6 +161,7 @@ struct _GstSelectorPad + guint32 segment_seqnum; /* sequence number of the current segment */ + + gboolean events_pending; /* TRUE if sticky events need to be updated */ ++ gboolean flush_events_pending;/* unblock old active track */ + + gboolean sending_cached_buffers; + GQueue *cached_buffers; +@@ -339,6 +340,7 @@ gst_selector_pad_reset (GstSelectorPad * pad) + pad->eos = FALSE; + pad->eos_sent = FALSE; + pad->events_pending = FALSE; ++ pad->flush_events_pending = FALSE; + pad->discont = FALSE; + pad->flushing = FALSE; + gst_segment_init (&pad->segment, GST_FORMAT_UNDEFINED); +@@ -557,6 +559,8 @@ gst_selector_pad_event (GstPad * pad, GstObject * parent, GstEvent * event) + selpad->flushing = TRUE; + sel->eos = FALSE; + selpad->group_done = FALSE; ++ if (selpad->flush_events_pending) ++ forward = TRUE; + GST_INPUT_SELECTOR_BROADCAST (sel); + break; + case GST_EVENT_FLUSH_STOP: +@@ -1136,6 +1140,7 @@ gst_selector_pad_chain (GstPad * pad, GstObject * parent, GstBuffer * buf) + buf = gst_buffer_ref (buf); + res = gst_pad_push (sel->srcpad, buf); + GST_LOG_OBJECT (pad, "Buffer %p forwarded result=%d", buf, res); ++ selpad->flush_events_pending = FALSE; + + GST_INPUT_SELECTOR_LOCK (sel); + +@@ -1389,8 +1394,12 @@ gst_input_selector_set_active_pad (GstInputSelector * self, GstPad * pad) + active_pad_p = &self->active_sinkpad; + gst_object_replace ((GstObject **) active_pad_p, GST_OBJECT_CAST (pad)); + +- if (old && old != new) ++ if (old && old != new) { + gst_pad_push_event (GST_PAD_CAST (old), gst_event_new_reconfigure ()); ++ /* Old will be blocked on gst_pad_push() when set active pad in PAUSE ++ * state. Need flush when set active pad and then seek in PAUSE state */ ++ old->flush_events_pending = TRUE; ++ } + if (new) + gst_pad_push_event (GST_PAD_CAST (new), gst_event_new_reconfigure ()); + +-- +1.9.1 + diff --git a/recipes-multimedia/gstreamer/gstreamer1.0_1.12.%.bbappend b/recipes-multimedia/gstreamer/gstreamer1.0_1.12.%.bbappend new file mode 100644 index 0000000..358fbaf --- /dev/null +++ b/recipes-multimedia/gstreamer/gstreamer1.0_1.12.%.bbappend @@ -0,0 +1,16 @@ +FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:" + +DEPENDS += " elfutils" + +# Unrecognised options, need to remove them +EXTRA_OECONF_remove = " --disable-docbook --disable-trace" + +SRC_URI_append_imx = " \ + file://0001-handle-base-parse-error.patch \ + file://0002-Fix-crash-with-gst-inspect-Chris-Lord-chris-openedha.patch \ + file://0003-baseparse-unset-FLAG_DISCONT-when-push-to-adapter.patch \ + file://0004-gstbaseparse-Need-push-adapter-remainning-data-in-pa.patch \ + file://0005-inputselector-should-proceed-non-active-pad-buffer-e.patch \ + file://0006-poll-Add-check-if-can-read-event-API.patch \ + file://0007-inputselector-Need-flush-when-set-active-pad-and-the.patch \ +" diff --git a/recipes-multimedia/gstreamer/imx-gst1.0-plugin_4.3.1.bb b/recipes-multimedia/gstreamer/imx-gst1.0-plugin_4.3.1.bb new file mode 100644 index 0000000..3375d97 --- /dev/null +++ b/recipes-multimedia/gstreamer/imx-gst1.0-plugin_4.3.1.bb @@ -0,0 +1,86 @@ +# Copyright (C) 2014,2016 Freescale Semiconductor +# Copyright 2017 NXP +# Copyright (C) 2012-2015 O.S. Systems Software LTDA. +# Released under the MIT license (see COPYING.MIT for the terms) + +DESCRIPTION = "Gstreamer freescale plugins" +LICENSE = "GPLv2 & LGPLv2 & LGPLv2.1" +SECTION = "multimedia" + +DEPENDS = "imx-codec imx-parser virtual/kernel gstreamer1.0 gstreamer1.0-plugins-base gstreamer1.0-plugins-bad" +DEPENDS_append_mx6 = " imx-lib" +DEPENDS_append_mx7 = " imx-lib" +DEPENDS_append_imxvpu = " imx-vpuwrap" + +# For backwards compatibility +RREPLACES_${PN} = "gst1.0-fsl-plugin" +RPROVIDES_${PN} = "gst1.0-fsl-plugin" +RCONFLICTS_${PN} = "gst1.0-fsl-plugin" + +LIC_FILES_CHKSUM = "file://COPYING-LGPL-2;md5=5f30f0716dfdd0d91eb439ebec522ec2 \ + file://COPYING-LGPL-2.1;md5=fbc093901857fcd118f065f900982c24" + +IMXGST_SRC ?= "git://source.codeaurora.org/external/imx/imx-gst1.0-plugin.git;protocol=https" +SRCBRANCH = "MM_04.03.01_1710_L4.9.51_MX8_BETA1" + +SRC_URI = "${IMXGST_SRC};branch=${SRCBRANCH}" +SRCREV = "cfa6157b4c7d07890ba41131809333bfa1f757de" + +S = "${WORKDIR}/git" + +inherit autotools pkgconfig + +# Make sure kernel sources are available +do_configure[depends] += "virtual/kernel:do_shared_workdir" + +PLATFORM_mx6 = "MX6" +PLATFORM_mx6sl = "MX6SL" +PLATFORM_mx6sx = "MX6SX" +PLATFORM_mx6ul = "MX6UL" +PLATFORM_mx6sll = "MX6SLL" +PLATFORM_mx7= "MX7D" +PLATFORM_mx7ulp= "MX7ULP" +PLATFORM_mx8 = "MX8" + +# Todo add a mechanism to map possible build targets +EXTRA_OECONF = "PLATFORM=${PLATFORM} \ + CPPFLAGS="-I${STAGING_KERNEL_BUILDDIR}/include/generated/uapi -I${STAGING_KERNEL_DIR}/include/uapi -I${STAGING_KERNEL_DIR}/include" \ + CROSS_ROOT=${PKG_CONFIG_SYSROOT_DIR} \ + ${@bb.utils.contains('DISTRO_FEATURES', 'wayland', bb.utils.contains('DISTRO_FEATURES', 'x11', '--disable-x11', '', d), '', d)}" + +PACKAGES =+ "${PN}-gplay ${PN}-libgplaycore ${PN}-libgstfsl ${PN}-grecorder ${PN}-librecorder-engine ${PN}-libplayengine" + +# Add codec list that the beep plugin run-time depended +BEEP_RDEPENDS = "imx-codec-aac imx-codec-mp3 imx-codec-oggvorbis" +RDEPENDS_${PN} += "imx-parser ${BEEP_RDEPENDS} gstreamer1.0-plugins-good-id3demux " + +# overlaysink rely on G2D, +# cannot be supported on i.MX6SLL & i.MX6UL & i.MX6ULL & i.MX7D +PACKAGECONFIG ?= "" +PACKAGECONFIG_imxgpu2d = "overlaysink" + + +# FIXME: Add all features +# feature from excluded mm packages +PACKAGECONFIG[ac3] += ",,imx-ac3codec,imx-ac3codec" +# feature from special mm packages +PACKAGECONFIG[aacp] += ",,imx-aacpcodec,imx-aacpcodec" +MSDEPENDS = "imx-msparser imx-mscodec" +PACKAGECONFIG[wma10dec] += ",,${MSDEPENDS},${MSDEPENDS}" +PACKAGECONFIG[wma8enc] += "--enable-wma8enc,--disable-wma8enc,${MSDEPENDS},${MSDEPENDS}" +OVDEPENDS = "virtual/libg2d" +PACKAGECONFIG[overlaysink] += "--enable-overlaysink,--disable-overlaysink, ${OVDEPENDS}" + +FILES_${PN} = "${libdir}/gstreamer-1.0/*.so ${datadir}" + +FILES_${PN}-dbg += "${libdir}/gstreamer-1.0/.debug" +FILES_${PN}-dev += "${libdir}/gstreamer-1.0/*.la ${libdir}/pkgconfig/*.pc" +FILES_${PN}-staticdev += "${libdir}/gstreamer-1.0/*.a" +FILES_${PN}-gplay = "${bindir}/gplay-1.0" +FILES_${PN}-libgplaycore = "${libdir}/libgplaycore-1.0${SOLIBS}" +FILES_${PN}-libgstfsl = "${libdir}/libgstfsl-1.0${SOLIBS}" +FILES_${PN}-grecorder = "${bindir}/grecorder-1.0" +FILES_${PN}-librecorder-engine = "${libdir}/librecorder_engine-1.0${SOLIBS}" +FILES_${PN}-libplayengine = "${libdir}/libplayengine-1.0${SOLIBS}" + +COMPATIBLE_MACHINE = "(mx6|mx7|mx8)" -- cgit v1.2.3