Openembedded Core Discussions
 help / color / mirror / Atom feed
* [poky][PATCH 00/13] Add patches for gstreamer 1.6
@ 2016-01-18  9:32 Yuqing Zhu
  2016-01-18  9:32 ` [poky][PATCH 01/13] gstreamer1.0: [baseparse] unset FLAG_DISCONT when push to adapter Yuqing Zhu
                   ` (13 more replies)
  0 siblings, 14 replies; 19+ messages in thread
From: Yuqing Zhu @ 2016-01-18  9:32 UTC (permalink / raw)
  To: openembedded-core

---gstreamer1.0
   Correct the setting for FLAG_DISCONT when push to adapter.

---gstreamer1.0-plugins-base
   Fix taglist not being sent to down stream issue.
   Fix audio/video decoder error.
   Make gstaudiobasesink print warning instead of returning ERROR.
   Disable orc optimization for lib video.
   Add video crop supporting when convert frame.

---gstreamer1.0-plugins-bad
   Fix mpegtsmux get wrong pid.
   Add code type checking in mpeg4videoparse when draining.
   Detect picture coding type when draining.
   Fix frame rate info lost when fixating caps.
   Add video stitching support based on Open CV.
   Fix memory leak of navigation thread in glwindow.
   Fix loop test hang in glimagesink.


Yuqing Zhu (13):
  gstreamer1.0: [baseparse] unset FLAG_DISCONT when push to adapter
  gstreamer1.0-plugins-base: Fix taglist not being sent to down stream
    if     all the frame corrupted
  gstreamer1.0-plugins-base: Fix audio/video decoder error
  gstreamer1.0-plugins-base: Make gstaudiobasesink print warning instead
    of returning ERROR
  gstreamer1.0-plugins-base: Disable orc optimization for lib video
  gstreamer1.0-plugins-base: Add video crop supporting when convert
    frame
  gstreamer1.0-plugins-bad: Fix mpegtsmux get wrong pid
  gstreamer1.0-plugins-bad: Add check coding type when drain in
    mpeg4videoparse
  gstreamer1.0-plugins-bad: Adding picture coding type when drain
  gstreamer1.0-plugins-bad: Fix frame rate info lost when fixate caps
  gstreamer1.0-plugins-bad: Add video stitching support based on Open CV
  gstreamer1.0-plugins-bad: Fix memory leak of navigation thread in
    glwindow
  gstreamer1.0-plugins-bad: Fix loop test hang in glimagesink

 ...pegtsmux-Need-get-pid-when-create-streams.patch |   45 +
 ...arse-Need-detect-picture-coding-type-when.patch |   47 +
 ...rse-Need-detect-picture-coding-type-when-.patch |   47 +
 ...ter-Lost-frame-rate-info-when-fixate-caps.patch |   51 +
 ...-video-stitching-support-based-on-Open-CV.patch | 1915 ++++++++++++++++++++
 ...window-fix-memory-leak-of-navigation-thre.patch |   35 +
 ...-wayland-fix-loop-test-hang-in-glimagesin.patch |  142 ++
 .../gstreamer/gstreamer1.0-plugins-bad_1.6.2.bb    |   10 +-
 ...-send-to-down-stream-if-all-the-frame-cor.patch |   58 +
 .../0006-handle-audio-video-decoder-error.patch    |   66 +
 ...esink-print-warning-istead-of-return-ERRO.patch |   47 +
 ...-optimization-for-lib-video-in-plugins-ba.patch |   34 +
 ...ame-Support-video-crop-when-convert-frame.patch |  143 ++
 .../gstreamer/gstreamer1.0-plugins-base_1.6.2.bb   |    5 +
 ...e-unset-FLAG_DISCONT-when-push-to-adapter.patch |   34 +
 .../gstreamer/gstreamer1.0_1.6.2.bb                |    1 +
 16 files changed, 2679 insertions(+), 1 deletion(-)
 create mode 100755 meta/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad/0002-mpegtsmux-Need-get-pid-when-create-streams.patch
 create mode 100755 meta/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad/0003-mpeg4videoparse-Need-detect-picture-coding-type-when.patch
 create mode 100755 meta/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad/0004-mpegvideoparse-Need-detect-picture-coding-type-when-.patch
 create mode 100755 meta/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad/0005-glfilter-Lost-frame-rate-info-when-fixate-caps.patch
 create mode 100755 meta/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad/0006-opencv-Add-video-stitching-support-based-on-Open-CV.patch
 create mode 100755 meta/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad/0007-glplugin-glwindow-fix-memory-leak-of-navigation-thre.patch
 create mode 100755 meta/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad/0008-glplugin-gl-wayland-fix-loop-test-hang-in-glimagesin.patch
 create mode 100755 meta/recipes-multimedia/gstreamer/gstreamer1.0-plugins-base/0005-taglist-not-send-to-down-stream-if-all-the-frame-cor.patch
 create mode 100755 meta/recipes-multimedia/gstreamer/gstreamer1.0-plugins-base/0006-handle-audio-video-decoder-error.patch
 create mode 100755 meta/recipes-multimedia/gstreamer/gstreamer1.0-plugins-base/0007-gstaudiobasesink-print-warning-istead-of-return-ERRO.patch
 create mode 100755 meta/recipes-multimedia/gstreamer/gstreamer1.0-plugins-base/0008-Disable-orc-optimization-for-lib-video-in-plugins-ba.patch
 create mode 100755 meta/recipes-multimedia/gstreamer/gstreamer1.0-plugins-base/0009-convertframe-Support-video-crop-when-convert-frame.patch
 create mode 100755 meta/recipes-multimedia/gstreamer/gstreamer1.0/0002-baseparse-unset-FLAG_DISCONT-when-push-to-adapter.patch

-- 
1.9.1



^ permalink raw reply	[flat|nested] 19+ messages in thread

* [poky][PATCH 01/13] gstreamer1.0: [baseparse] unset FLAG_DISCONT when push to adapter
  2016-01-18  9:32 [poky][PATCH 00/13] Add patches for gstreamer 1.6 Yuqing Zhu
@ 2016-01-18  9:32 ` Yuqing Zhu
  2016-01-18  9:32 ` [poky][PATCH 02/13] gstreamer1.0-plugins-base: Fix taglist not being sent to down stream if all the frame corrupted Yuqing Zhu
                   ` (12 subsequent siblings)
  13 siblings, 0 replies; 19+ messages in thread
From: Yuqing Zhu @ 2016-01-18  9:32 UTC (permalink / raw)
  To: openembedded-core

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 always be set on each frame
for the first chain in buffer.

Signed-off-by: Yuqing Zhu <b54851@freescale.com>
---
 ...e-unset-FLAG_DISCONT-when-push-to-adapter.patch | 34 ++++++++++++++++++++++
 .../gstreamer/gstreamer1.0_1.6.2.bb                |  1 +
 2 files changed, 35 insertions(+)
 create mode 100755 meta/recipes-multimedia/gstreamer/gstreamer1.0/0002-baseparse-unset-FLAG_DISCONT-when-push-to-adapter.patch

diff --git a/meta/recipes-multimedia/gstreamer/gstreamer1.0/0002-baseparse-unset-FLAG_DISCONT-when-push-to-adapter.patch b/meta/recipes-multimedia/gstreamer/gstreamer1.0/0002-baseparse-unset-FLAG_DISCONT-when-push-to-adapter.patch
new file mode 100755
index 0000000..a4e9909
--- /dev/null
+++ b/meta/recipes-multimedia/gstreamer/gstreamer1.0/0002-baseparse-unset-FLAG_DISCONT-when-push-to-adapter.patch
@@ -0,0 +1,34 @@
+From 90254a34f57278930bbcb3bd80cfef607157b03f Mon Sep 17 00:00:00 2001
+From: Lyon Wang <lyon.wang@freescale.com>
+Date: Wed, 4 Nov 2015 18:16:52 +0800
+Subject: [PATCH] [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.
+
+https://bugzilla.gnome.org/show_bug.cgi?id=757575
+
+Upstream-Status: Pending
+
+Signed-off-by: Lyon Wang <lyon.wang@freescale.com>
+---
+ 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 51d159d..184fafe 100644
+--- a/libs/gst/base/gstbaseparse.c
++++ b/libs/gst/base/gstbaseparse.c
+@@ -3026,6 +3026,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/meta/recipes-multimedia/gstreamer/gstreamer1.0_1.6.2.bb b/meta/recipes-multimedia/gstreamer/gstreamer1.0_1.6.2.bb
index ba46c77..ef1e88c 100644
--- a/meta/recipes-multimedia/gstreamer/gstreamer1.0_1.6.2.bb
+++ b/meta/recipes-multimedia/gstreamer/gstreamer1.0_1.6.2.bb
@@ -6,6 +6,7 @@ LIC_FILES_CHKSUM = "file://COPYING;md5=6762ed442b3822387a51c92d928ead0d \
 SRC_URI = " \
     http://gstreamer.freedesktop.org/src/gstreamer/gstreamer-${PV}.tar.xz \
     file://0001-Fix-crash-with-gst-inspect.patch \
+    file://0002-baseparse-unset-FLAG_DISCONT-when-push-to-adapter.patch \
 "
 SRC_URI[md5sum] = "5e610b5a94c209487310739b39b6c464"
 SRC_URI[sha256sum] = "5896716bd8e089dba452932a2eff2bb6f6c9d58ff64a96635d157f1ffaf8feb2"
-- 
1.9.1



^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [poky][PATCH 02/13] gstreamer1.0-plugins-base: Fix taglist not being sent to down stream if all the frame corrupted
  2016-01-18  9:32 [poky][PATCH 00/13] Add patches for gstreamer 1.6 Yuqing Zhu
  2016-01-18  9:32 ` [poky][PATCH 01/13] gstreamer1.0: [baseparse] unset FLAG_DISCONT when push to adapter Yuqing Zhu
@ 2016-01-18  9:32 ` Yuqing Zhu
  2016-01-18  9:32 ` [poky][PATCH 03/13] gstreamer1.0-plugins-base: Fix audio/video decoder error Yuqing Zhu
                   ` (11 subsequent siblings)
  13 siblings, 0 replies; 19+ messages in thread
From: Yuqing Zhu @ 2016-01-18  9:32 UTC (permalink / raw)
  To: openembedded-core

Signed-off-by: Yuqing Zhu <b54851@freescale.com>
---
 ...-send-to-down-stream-if-all-the-frame-cor.patch | 58 ++++++++++++++++++++++
 .../gstreamer/gstreamer1.0-plugins-base_1.6.2.bb   |  1 +
 2 files changed, 59 insertions(+)
 create mode 100755 meta/recipes-multimedia/gstreamer/gstreamer1.0-plugins-base/0005-taglist-not-send-to-down-stream-if-all-the-frame-cor.patch

diff --git a/meta/recipes-multimedia/gstreamer/gstreamer1.0-plugins-base/0005-taglist-not-send-to-down-stream-if-all-the-frame-cor.patch b/meta/recipes-multimedia/gstreamer/gstreamer1.0-plugins-base/0005-taglist-not-send-to-down-stream-if-all-the-frame-cor.patch
new file mode 100755
index 0000000..1e5ef5d
--- /dev/null
+++ b/meta/recipes-multimedia/gstreamer/gstreamer1.0-plugins-base/0005-taglist-not-send-to-down-stream-if-all-the-frame-cor.patch
@@ -0,0 +1,58 @@
+From 2f2fc40a88061995053c60d700efe20cb17358c9 Mon Sep 17 00:00:00 2001
+From: Lyon Wang <lyon.wang@freescale.com>
+Date: Wed, 21 Oct 2015 16:35:43 +0800
+Subject: [PATCH 8/9] 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 <lj.qfy.sh@gmail.com>
+---
+ 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 f4c663a..b68f9eb 100644
+--- a/gst-libs/gst/audio/gstaudiodecoder.c
++++ b/gst-libs/gst/audio/gstaudiodecoder.c
+@@ -2309,6 +2309,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 f8a5869..514c06f 100644
+--- a/gst-libs/gst/video/gstvideodecoder.c
++++ b/gst-libs/gst/video/gstvideodecoder.c
+@@ -1265,6 +1265,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/meta/recipes-multimedia/gstreamer/gstreamer1.0-plugins-base_1.6.2.bb b/meta/recipes-multimedia/gstreamer/gstreamer1.0-plugins-base_1.6.2.bb
index 473dbcd..3139148 100644
--- a/meta/recipes-multimedia/gstreamer/gstreamer1.0-plugins-base_1.6.2.bb
+++ b/meta/recipes-multimedia/gstreamer/gstreamer1.0-plugins-base_1.6.2.bb
@@ -9,6 +9,7 @@ SRC_URI += "file://get-caps-from-src-pad-when-query-caps.patch \
             file://0003-ssaparse-enhance-SSA-text-lines-parsing.patch \
             file://0004-subparse-set-need_segment-after-sink-pad-received-GS.patch \
             file://encodebin-Need-more-buffers-in-output-queue-for-bett.patch \
+            file://0005-taglist-not-send-to-down-stream-if-all-the-frame-cor.patch \
 "
 
 SRC_URI[md5sum] = "f530fbbe287edce79c55a37bd1a39fe2"
-- 
1.9.1



^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [poky][PATCH 03/13] gstreamer1.0-plugins-base: Fix audio/video decoder error
  2016-01-18  9:32 [poky][PATCH 00/13] Add patches for gstreamer 1.6 Yuqing Zhu
  2016-01-18  9:32 ` [poky][PATCH 01/13] gstreamer1.0: [baseparse] unset FLAG_DISCONT when push to adapter Yuqing Zhu
  2016-01-18  9:32 ` [poky][PATCH 02/13] gstreamer1.0-plugins-base: Fix taglist not being sent to down stream if all the frame corrupted Yuqing Zhu
@ 2016-01-18  9:32 ` Yuqing Zhu
  2016-01-18  9:32 ` [poky][PATCH 04/13] gstreamer1.0-plugins-base: Make gstaudiobasesink print warning instead of returning ERROR Yuqing Zhu
                   ` (10 subsequent siblings)
  13 siblings, 0 replies; 19+ messages in thread
From: Yuqing Zhu @ 2016-01-18  9:32 UTC (permalink / raw)
  To: openembedded-core

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.

Signed-off-by: Yuqing Zhu <b54851@freescale.com>
---
 .../0006-handle-audio-video-decoder-error.patch    | 66 ++++++++++++++++++++++
 .../gstreamer/gstreamer1.0-plugins-base_1.6.2.bb   |  1 +
 2 files changed, 67 insertions(+)
 create mode 100755 meta/recipes-multimedia/gstreamer/gstreamer1.0-plugins-base/0006-handle-audio-video-decoder-error.patch

diff --git a/meta/recipes-multimedia/gstreamer/gstreamer1.0-plugins-base/0006-handle-audio-video-decoder-error.patch b/meta/recipes-multimedia/gstreamer/gstreamer1.0-plugins-base/0006-handle-audio-video-decoder-error.patch
new file mode 100755
index 0000000..2b714e4
--- /dev/null
+++ b/meta/recipes-multimedia/gstreamer/gstreamer1.0-plugins-base/0006-handle-audio-video-decoder-error.patch
@@ -0,0 +1,66 @@
+From 9e2b1ea55e1676649f4130bd15c2cfcceb7bfed0 Mon Sep 17 00:00:00 2001
+From: Lyon Wang <lyon.wang@freescale.com>
+Date: Mon, 15 Dec 2014 16:52:07 +0800
+Subject: [PATCH 9/9] 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 <lyon.wang@freescale.com>
+---
+ 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 b68f9eb..506c13d
+--- a/gst-libs/gst/audio/gstaudiodecoder.c
++++ b/gst-libs/gst/audio/gstaudiodecoder.c
+@@ -2304,9 +2304,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 514c06f..fa29083
+--- a/gst-libs/gst/video/gstvideodecoder.c
++++ b/gst-libs/gst/video/gstvideodecoder.c
+@@ -1251,9 +1251,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/meta/recipes-multimedia/gstreamer/gstreamer1.0-plugins-base_1.6.2.bb b/meta/recipes-multimedia/gstreamer/gstreamer1.0-plugins-base_1.6.2.bb
index 3139148..014f081 100644
--- a/meta/recipes-multimedia/gstreamer/gstreamer1.0-plugins-base_1.6.2.bb
+++ b/meta/recipes-multimedia/gstreamer/gstreamer1.0-plugins-base_1.6.2.bb
@@ -10,6 +10,7 @@ SRC_URI += "file://get-caps-from-src-pad-when-query-caps.patch \
             file://0004-subparse-set-need_segment-after-sink-pad-received-GS.patch \
             file://encodebin-Need-more-buffers-in-output-queue-for-bett.patch \
             file://0005-taglist-not-send-to-down-stream-if-all-the-frame-cor.patch \
+            file://0006-handle-audio-video-decoder-error.patch \
 "
 
 SRC_URI[md5sum] = "f530fbbe287edce79c55a37bd1a39fe2"
-- 
1.9.1



^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [poky][PATCH 04/13] gstreamer1.0-plugins-base: Make gstaudiobasesink print warning instead of returning ERROR
  2016-01-18  9:32 [poky][PATCH 00/13] Add patches for gstreamer 1.6 Yuqing Zhu
                   ` (2 preceding siblings ...)
  2016-01-18  9:32 ` [poky][PATCH 03/13] gstreamer1.0-plugins-base: Fix audio/video decoder error Yuqing Zhu
@ 2016-01-18  9:32 ` Yuqing Zhu
  2016-01-18  9:32 ` [poky][PATCH 05/13] gstreamer1.0-plugins-base: Disable orc optimization for lib video Yuqing Zhu
                   ` (9 subsequent siblings)
  13 siblings, 0 replies; 19+ messages in thread
From: Yuqing Zhu @ 2016-01-18  9:32 UTC (permalink / raw)
  To: openembedded-core

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.

Signed-off-by: Yuqing Zhu <b54851@freescale.com>
---
 ...esink-print-warning-istead-of-return-ERRO.patch | 47 ++++++++++++++++++++++
 .../gstreamer/gstreamer1.0-plugins-base_1.6.2.bb   |  1 +
 2 files changed, 48 insertions(+)
 create mode 100755 meta/recipes-multimedia/gstreamer/gstreamer1.0-plugins-base/0007-gstaudiobasesink-print-warning-istead-of-return-ERRO.patch

diff --git a/meta/recipes-multimedia/gstreamer/gstreamer1.0-plugins-base/0007-gstaudiobasesink-print-warning-istead-of-return-ERRO.patch b/meta/recipes-multimedia/gstreamer/gstreamer1.0-plugins-base/0007-gstaudiobasesink-print-warning-istead-of-return-ERRO.patch
new file mode 100755
index 0000000..cf56afc
--- /dev/null
+++ b/meta/recipes-multimedia/gstreamer/gstreamer1.0-plugins-base/0007-gstaudiobasesink-print-warning-istead-of-return-ERRO.patch
@@ -0,0 +1,47 @@
+From 5d83c4db60646ce077dfb2460b59c9d30ce06b04 Mon Sep 17 00:00:00 2001
+From: Lyon Wang <lyon.wang@freescale.com>
+Date: Tue, 17 Nov 2015 14:56:47 +0800
+Subject: [PATCH] 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 <lyon.wang@freescale.com>
+---
+ 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 704801e..a4a716b
+--- a/gst-libs/gst/audio/gstaudiobasesink.c
++++ b/gst-libs/gst/audio/gstaudiobasesink.c
+@@ -1133,10 +1133,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/meta/recipes-multimedia/gstreamer/gstreamer1.0-plugins-base_1.6.2.bb b/meta/recipes-multimedia/gstreamer/gstreamer1.0-plugins-base_1.6.2.bb
index 014f081..2e7952b 100644
--- a/meta/recipes-multimedia/gstreamer/gstreamer1.0-plugins-base_1.6.2.bb
+++ b/meta/recipes-multimedia/gstreamer/gstreamer1.0-plugins-base_1.6.2.bb
@@ -11,6 +11,7 @@ SRC_URI += "file://get-caps-from-src-pad-when-query-caps.patch \
             file://encodebin-Need-more-buffers-in-output-queue-for-bett.patch \
             file://0005-taglist-not-send-to-down-stream-if-all-the-frame-cor.patch \
             file://0006-handle-audio-video-decoder-error.patch \
+            file://0007-gstaudiobasesink-print-warning-istead-of-return-ERRO.patch \
 "
 
 SRC_URI[md5sum] = "f530fbbe287edce79c55a37bd1a39fe2"
-- 
1.9.1



^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [poky][PATCH 05/13] gstreamer1.0-plugins-base: Disable orc optimization for lib video
  2016-01-18  9:32 [poky][PATCH 00/13] Add patches for gstreamer 1.6 Yuqing Zhu
                   ` (3 preceding siblings ...)
  2016-01-18  9:32 ` [poky][PATCH 04/13] gstreamer1.0-plugins-base: Make gstaudiobasesink print warning instead of returning ERROR Yuqing Zhu
@ 2016-01-18  9:32 ` Yuqing Zhu
  2016-01-18  9:32 ` [poky][PATCH 06/13] gstreamer1.0-plugins-base: Add video crop supporting when convert frame Yuqing Zhu
                   ` (8 subsequent siblings)
  13 siblings, 0 replies; 19+ messages in thread
From: Yuqing Zhu @ 2016-01-18  9:32 UTC (permalink / raw)
  To: openembedded-core

- 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.

Signed-off-by: Yuqing Zhu <b54851@freescale.com>
---
 ...-optimization-for-lib-video-in-plugins-ba.patch | 34 ++++++++++++++++++++++
 .../gstreamer/gstreamer1.0-plugins-base_1.6.2.bb   |  1 +
 2 files changed, 35 insertions(+)
 create mode 100755 meta/recipes-multimedia/gstreamer/gstreamer1.0-plugins-base/0008-Disable-orc-optimization-for-lib-video-in-plugins-ba.patch

diff --git a/meta/recipes-multimedia/gstreamer/gstreamer1.0-plugins-base/0008-Disable-orc-optimization-for-lib-video-in-plugins-ba.patch b/meta/recipes-multimedia/gstreamer/gstreamer1.0-plugins-base/0008-Disable-orc-optimization-for-lib-video-in-plugins-ba.patch
new file mode 100755
index 0000000..9e80d96
--- /dev/null
+++ b/meta/recipes-multimedia/gstreamer/gstreamer1.0-plugins-base/0008-Disable-orc-optimization-for-lib-video-in-plugins-ba.patch
@@ -0,0 +1,34 @@
+From 51554875c2ee2714a4f80456f805cc2dfd612f78 Mon Sep 17 00:00:00 2001
+From: Lyon Wang <lyon.wang@freescale.com>
+Date: Thu, 10 Dec 2015 14:32:43 +0800
+Subject: [PATCH] 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
+Community ticket: https://bugzilla.gnome.org/show_bug.cgi?id=759286
+Upstream-Status: pending
+
+Signed-off-by: Lyon Wang <lyon.wang@freescale.com>
+---
+ 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 5d31fa1..f91fca6 100644
+--- a/gst-libs/gst/video/Makefile.am
++++ b/gst-libs/gst/video/Makefile.am
+@@ -84,7 +84,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/meta/recipes-multimedia/gstreamer/gstreamer1.0-plugins-base_1.6.2.bb b/meta/recipes-multimedia/gstreamer/gstreamer1.0-plugins-base_1.6.2.bb
index 2e7952b..c6f5d77 100644
--- a/meta/recipes-multimedia/gstreamer/gstreamer1.0-plugins-base_1.6.2.bb
+++ b/meta/recipes-multimedia/gstreamer/gstreamer1.0-plugins-base_1.6.2.bb
@@ -12,6 +12,7 @@ SRC_URI += "file://get-caps-from-src-pad-when-query-caps.patch \
             file://0005-taglist-not-send-to-down-stream-if-all-the-frame-cor.patch \
             file://0006-handle-audio-video-decoder-error.patch \
             file://0007-gstaudiobasesink-print-warning-istead-of-return-ERRO.patch \
+            file://0008-Disable-orc-optimization-for-lib-video-in-plugins-ba.patch \
 "
 
 SRC_URI[md5sum] = "f530fbbe287edce79c55a37bd1a39fe2"
-- 
1.9.1



^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [poky][PATCH 06/13] gstreamer1.0-plugins-base: Add video crop supporting when convert frame
  2016-01-18  9:32 [poky][PATCH 00/13] Add patches for gstreamer 1.6 Yuqing Zhu
                   ` (4 preceding siblings ...)
  2016-01-18  9:32 ` [poky][PATCH 05/13] gstreamer1.0-plugins-base: Disable orc optimization for lib video Yuqing Zhu
@ 2016-01-18  9:32 ` Yuqing Zhu
  2016-01-18  9:32 ` [poky][PATCH 07/13] gstreamer1.0-plugins-bad: Fix mpegtsmux get wrong pid Yuqing Zhu
                   ` (7 subsequent siblings)
  13 siblings, 0 replies; 19+ messages in thread
From: Yuqing Zhu @ 2016-01-18  9:32 UTC (permalink / raw)
  To: openembedded-core

Getting thumbnail will use convertframe to convert video frame to
desired video format and size. But haven't process crop meta on
the video buffer. Need to add video crop support.

Signed-off-by: Yuqing Zhu <b54851@freescale.com>
---
 ...ame-Support-video-crop-when-convert-frame.patch | 143 +++++++++++++++++++++
 .../gstreamer/gstreamer1.0-plugins-base_1.6.2.bb   |   1 +
 2 files changed, 144 insertions(+)
 create mode 100755 meta/recipes-multimedia/gstreamer/gstreamer1.0-plugins-base/0009-convertframe-Support-video-crop-when-convert-frame.patch

diff --git a/meta/recipes-multimedia/gstreamer/gstreamer1.0-plugins-base/0009-convertframe-Support-video-crop-when-convert-frame.patch b/meta/recipes-multimedia/gstreamer/gstreamer1.0-plugins-base/0009-convertframe-Support-video-crop-when-convert-frame.patch
new file mode 100755
index 0000000..096a6f4
--- /dev/null
+++ b/meta/recipes-multimedia/gstreamer/gstreamer1.0-plugins-base/0009-convertframe-Support-video-crop-when-convert-frame.patch
@@ -0,0 +1,143 @@
+From 5be6ed00aad028d9cbb4e0c63af0be69d335c71e Mon Sep 17 00:00:00 2001
+From: Song Bing <b06498@freescale.com>
+Date: Fri, 11 Dec 2015 21:42:00 +0800
+Subject: [PATCH] convertframe: Support video crop when convert frame
+
+Get thumbnail will user convertframe to convert video frame to
+desired video format and size. But haven't process crop meta on
+the video buffer. Add support video crop.
+
+https://bugzilla.gnome.org/show_bug.cgi?id=759329
+
+Upstream-Status: Backport [1.7.1]
+
+---
+ gst-libs/gst/video/convertframe.c | 65 +++++++++++++++++++++++++++++++++------
+ 1 file changed, 56 insertions(+), 9 deletions(-)
+
+diff --git a/gst-libs/gst/video/convertframe.c b/gst-libs/gst/video/convertframe.c
+index aa9c3d3..942a51e 100644
+--- a/gst-libs/gst/video/convertframe.c
++++ b/gst-libs/gst/video/convertframe.c
+@@ -110,12 +110,23 @@ fail:
+ static GstElement *
+ build_convert_frame_pipeline (GstElement ** src_element,
+     GstElement ** sink_element, const GstCaps * from_caps,
+-    const GstCaps * to_caps, GError ** err)
++    GstVideoCropMeta * cmeta, const GstCaps * to_caps, GError ** err)
+ {
+-  GstElement *src = NULL, *csp = NULL, *vscale = NULL;
+-  GstElement *sink = NULL, *encoder = NULL, *pipeline;
++  GstElement *vcrop = NULL, *csp = NULL, *csp2 = NULL, *vscale = NULL;
++  GstElement *src = NULL, *sink = NULL, *encoder = NULL, *pipeline;
++  GstVideoInfo info;
+   GError *error = NULL;
+ 
++  if (cmeta) {
++    if (!create_element ("videocrop", &vcrop, &error)) {
++      g_warning
++          ("build_convert_frame_pipeline: Buffer has crop metadata but videocrop element is not found. Cropping will be disabled");
++    } else {
++      if (!create_element ("videoconvert", &csp2, &error))
++        goto no_elements;
++    }
++  }
++
+   /* videoscale is here to correct for the pixel-aspect-ratio for us */
+   GST_DEBUG ("creating elements");
+   if (!create_element ("appsrc", &src, &error) ||
+@@ -133,15 +144,42 @@ build_convert_frame_pipeline (GstElement ** src_element,
+ 
+   GST_DEBUG ("adding elements");
+   gst_bin_add_many (GST_BIN (pipeline), src, csp, vscale, sink, NULL);
++  if (vcrop)
++    gst_bin_add_many (GST_BIN (pipeline), vcrop, csp2, NULL);
+ 
+   /* set caps */
+   g_object_set (src, "caps", from_caps, NULL);
++  if (vcrop) {
++    gst_video_info_from_caps (&info, from_caps);
++    g_object_set (vcrop, "left", cmeta->x, NULL);
++    g_object_set (vcrop, "top", cmeta->y, NULL);
++    g_object_set (vcrop, "right", GST_VIDEO_INFO_WIDTH (&info) - cmeta->width,
++        NULL);
++    g_object_set (vcrop, "bottom",
++        GST_VIDEO_INFO_HEIGHT (&info) - cmeta->height, NULL);
++    GST_DEBUG ("crop meta [x,y,width,height]: %d %d %d %d", cmeta->x, cmeta->y,
++        cmeta->width, cmeta->height);
++  }
+   g_object_set (sink, "caps", to_caps, NULL);
+ 
+   /* FIXME: linking is still way too expensive, profile this properly */
+-  GST_DEBUG ("linking src->csp");
+-  if (!gst_element_link_pads (src, "src", csp, "sink"))
+-    goto link_failed;
++  if (vcrop) {
++    GST_DEBUG ("linking src->csp2");
++    if (!gst_element_link_pads (src, "src", csp2, "sink"))
++      goto link_failed;
++
++    GST_DEBUG ("linking csp2->vcrop");
++    if (!gst_element_link_pads (csp2, "src", vcrop, "sink"))
++      goto link_failed;
++
++    GST_DEBUG ("linking vcrop->csp");
++    if (!gst_element_link_pads (vcrop, "src", csp, "sink"))
++      goto link_failed;
++  } else {
++    GST_DEBUG ("linking src->csp");
++    if (!gst_element_link_pads (src, "src", csp, "sink"))
++      goto link_failed;
++  }
+ 
+   GST_DEBUG ("linking csp->vscale");
+   if (!gst_element_link_pads_full (csp, "src", vscale, "sink",
+@@ -193,8 +231,12 @@ no_elements:
+   {
+     if (src)
+       gst_object_unref (src);
++    if (vcrop)
++      gst_object_unref (vcrop);
+     if (csp)
+       gst_object_unref (csp);
++    if (csp2)
++      gst_object_unref (csp2);
+     if (vscale)
+       gst_object_unref (vscale);
+     if (sink)
+@@ -209,7 +251,11 @@ no_elements:
+ no_pipeline:
+   {
+     gst_object_unref (src);
++    if (vcrop)
++      gst_object_unref (vcrop);
+     gst_object_unref (csp);
++    if (csp2)
++      gst_object_unref (csp2);
+     gst_object_unref (vscale);
+     gst_object_unref (sink);
+ 
+@@ -282,7 +328,8 @@ gst_video_convert_sample (GstSample * sample, const GstCaps * to_caps,
+   }
+ 
+   pipeline =
+-      build_convert_frame_pipeline (&src, &sink, from_caps, to_caps_copy, &err);
++      build_convert_frame_pipeline (&src, &sink, from_caps,
++      gst_buffer_get_video_crop_meta (buf), to_caps_copy, &err);
+   if (!pipeline)
+     goto no_pipeline;
+ 
+@@ -646,8 +693,8 @@ gst_video_convert_sample_async (GstSample * sample,
+   }
+ 
+   pipeline =
+-      build_convert_frame_pipeline (&src, &sink, from_caps, to_caps_copy,
+-      &error);
++      build_convert_frame_pipeline (&src, &sink, from_caps,
++      gst_buffer_get_video_crop_meta (buf), to_caps_copy, &error);
+   if (!pipeline)
+     goto no_pipeline;
+ 
+-- 
+2.5.0
+
diff --git a/meta/recipes-multimedia/gstreamer/gstreamer1.0-plugins-base_1.6.2.bb b/meta/recipes-multimedia/gstreamer/gstreamer1.0-plugins-base_1.6.2.bb
index c6f5d77..97b1a87 100644
--- a/meta/recipes-multimedia/gstreamer/gstreamer1.0-plugins-base_1.6.2.bb
+++ b/meta/recipes-multimedia/gstreamer/gstreamer1.0-plugins-base_1.6.2.bb
@@ -13,6 +13,7 @@ SRC_URI += "file://get-caps-from-src-pad-when-query-caps.patch \
             file://0006-handle-audio-video-decoder-error.patch \
             file://0007-gstaudiobasesink-print-warning-istead-of-return-ERRO.patch \
             file://0008-Disable-orc-optimization-for-lib-video-in-plugins-ba.patch \
+            file://0009-convertframe-Support-video-crop-when-convert-frame.patch \
 "
 
 SRC_URI[md5sum] = "f530fbbe287edce79c55a37bd1a39fe2"
-- 
1.9.1



^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [poky][PATCH 07/13] gstreamer1.0-plugins-bad: Fix mpegtsmux get wrong pid
  2016-01-18  9:32 [poky][PATCH 00/13] Add patches for gstreamer 1.6 Yuqing Zhu
                   ` (5 preceding siblings ...)
  2016-01-18  9:32 ` [poky][PATCH 06/13] gstreamer1.0-plugins-base: Add video crop supporting when convert frame Yuqing Zhu
@ 2016-01-18  9:32 ` Yuqing Zhu
  2016-01-18  9:32 ` [poky][PATCH 08/13] gstreamer1.0-plugins-bad: Add check coding type when drain in mpeg4videoparse Yuqing Zhu
                   ` (6 subsequent siblings)
  13 siblings, 0 replies; 19+ messages in thread
From: Yuqing Zhu @ 2016-01-18  9:32 UTC (permalink / raw)
  To: openembedded-core

When camerabin use mpegtsmux as muxer to start video recording and then
stop video recording and then start video recording again, mpegtsmux will
get wrong pid.
Need to get pid when create streams.

Signed-off-by: Yuqing Zhu <b54851@freescale.com>
---
 ...pegtsmux-Need-get-pid-when-create-streams.patch | 45 ++++++++++++++++++++++
 .../gstreamer/gstreamer1.0-plugins-bad_1.6.2.bb    |  4 +-
 2 files changed, 48 insertions(+), 1 deletion(-)
 create mode 100755 meta/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad/0002-mpegtsmux-Need-get-pid-when-create-streams.patch

diff --git a/meta/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad/0002-mpegtsmux-Need-get-pid-when-create-streams.patch b/meta/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad/0002-mpegtsmux-Need-get-pid-when-create-streams.patch
new file mode 100755
index 0000000..f2c063f
--- /dev/null
+++ b/meta/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad/0002-mpegtsmux-Need-get-pid-when-create-streams.patch
@@ -0,0 +1,45 @@
+From 3e0bc017ca9b4e093484ee6b3b73917918364e92 Mon Sep 17 00:00:00 2001
+From: Song Bing <b06498@freescale.com>
+Date: Wed, 22 Apr 2015 18:06:35 +0800
+Subject: [PATCH 02/10] 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.
+
+https://bugzilla.gnome.org/show_bug.cgi?id=748288
+
+Upstream-Status: Pending
+---
+ gst/mpegtsmux/mpegtsmux.c | 15 +++++++++++++++
+ 1 file changed, 15 insertions(+)
+
+diff --git a/gst/mpegtsmux/mpegtsmux.c b/gst/mpegtsmux/mpegtsmux.c
+index c3a0dbb..5a6d9e1 100644
+--- a/gst/mpegtsmux/mpegtsmux.c
++++ b/gst/mpegtsmux/mpegtsmux.c
+@@ -761,6 +761,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/meta/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad_1.6.2.bb b/meta/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad_1.6.2.bb
index 284e1f2..3f30f86 100644
--- a/meta/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad_1.6.2.bb
+++ b/meta/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad_1.6.2.bb
@@ -5,7 +5,9 @@ LIC_FILES_CHKSUM = "file://COPYING;md5=73a5855a8119deb017f5f13cf327095d \
                     file://COPYING.LIB;md5=21682e4e8fea52413fd26c60acb907e5 \
                     file://gst/tta/crc32.h;beginline=12;endline=29;md5=27db269c575d1e5317fffca2d33b3b50"
 
-SRC_URI += "file://0001-glimagesink-Downrank-to-marginal.patch"
+SRC_URI += "file://0001-glimagesink-Downrank-to-marginal.patch \
+            file://0002-mpegtsmux-Need-get-pid-when-create-streams.patch \
+"
 
 SRC_URI[md5sum] = "7c73bec1d389f0e184ebbbbb9e9f883d"
 SRC_URI[sha256sum] = "650855e39ff56a8bb6cb0c192109c5926ce12f536d06e19ebf829de71ef396fe"
-- 
1.9.1



^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [poky][PATCH 08/13] gstreamer1.0-plugins-bad: Add check coding type when drain in mpeg4videoparse
  2016-01-18  9:32 [poky][PATCH 00/13] Add patches for gstreamer 1.6 Yuqing Zhu
                   ` (6 preceding siblings ...)
  2016-01-18  9:32 ` [poky][PATCH 07/13] gstreamer1.0-plugins-bad: Fix mpegtsmux get wrong pid Yuqing Zhu
@ 2016-01-18  9:32 ` Yuqing Zhu
  2016-01-18  9:32 ` [poky][PATCH 09/13] gstreamer1.0-plugins-bad: Detect picture coding type when drain Yuqing Zhu
                   ` (5 subsequent siblings)
  13 siblings, 0 replies; 19+ messages in thread
From: Yuqing Zhu @ 2016-01-18  9:32 UTC (permalink / raw)
  To: openembedded-core

Our use case is demuxer only output key frame when backward playback.
Every frame is DISCONT and KEY frame. mpeg4videoparse will detect coding
type when detect start code after VOP. our use case will drain after VOP
and can't detect start code after VOP. Add check coding type code when
drain.

Signed-off-by: Yuqing Zhu <b54851@freescale.com>
---
 ...arse-Need-detect-picture-coding-type-when.patch | 47 ++++++++++++++++++++++
 .../gstreamer/gstreamer1.0-plugins-bad_1.6.2.bb    |  1 +
 2 files changed, 48 insertions(+)
 create mode 100755 meta/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad/0003-mpeg4videoparse-Need-detect-picture-coding-type-when.patch

diff --git a/meta/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad/0003-mpeg4videoparse-Need-detect-picture-coding-type-when.patch b/meta/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad/0003-mpeg4videoparse-Need-detect-picture-coding-type-when.patch
new file mode 100755
index 0000000..3f09d4d
--- /dev/null
+++ b/meta/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad/0003-mpeg4videoparse-Need-detect-picture-coding-type-when.patch
@@ -0,0 +1,47 @@
+From f712092e768347b59719f5016714c91d4d82483b Mon Sep 17 00:00:00 2001
+From: Song Bing <b06498@freescale.com>
+Date: Wed, 20 May 2015 15:13:20 +0800
+Subject: [PATCH 03/10] mpeg4videoparse: Need detect picture coding type when
+ drain
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+our use case is demuxer only output key frame when backward playback.
+every frame is DISCONT and KEY frame. mpeg4videoparse will detect coding
+type when detect start code after VOP. our use case will drain after VOP
+and can't detect start code after VOP. Add check coding type code when
+drain.
+
+Upstream-Status: Submitted [https://bugzilla.gnome.org/show_bug.cgi?id=749617]
+
+---
+ gst/videoparsers/gstmpeg4videoparse.c | 12 ++++++++++++
+ 1 file changed, 12 insertions(+)
+
+diff --git a/gst/videoparsers/gstmpeg4videoparse.c b/gst/videoparsers/gstmpeg4videoparse.c
+index 53db2d5..dbbd6d2 100644
+--- a/gst/videoparsers/gstmpeg4videoparse.c
++++ b/gst/videoparsers/gstmpeg4videoparse.c
+@@ -502,6 +502,18 @@ next:
+     case (GST_MPEG4_PARSER_ERROR):
+       /* if draining, take all */
+       if (GST_BASE_PARSE_DRAINING (parse)) {
++        /* need decide intra_frame */
++        if (mp4vparse->vop_offset >= 0) {
++          if (G_LIKELY (size > mp4vparse->vop_offset + 1)) {
++            mp4vparse->intra_frame =
++              ((data[mp4vparse->vop_offset + 1] >> 6 & 0x3) == 0);
++          } else {
++            GST_WARNING_OBJECT (mp4vparse, "no data following VOP startcode");
++            mp4vparse->intra_frame = FALSE;
++          }
++          GST_LOG_OBJECT (mp4vparse, "is intra %d %d",
++              mp4vparse->intra_frame, mp4vparse->vop_offset);
++        }
+         framesize = size;
+         ret = TRUE;
+       } else {
+-- 
+1.9.1
+
diff --git a/meta/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad_1.6.2.bb b/meta/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad_1.6.2.bb
index 3f30f86..507d048 100644
--- a/meta/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad_1.6.2.bb
+++ b/meta/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad_1.6.2.bb
@@ -7,6 +7,7 @@ LIC_FILES_CHKSUM = "file://COPYING;md5=73a5855a8119deb017f5f13cf327095d \
 
 SRC_URI += "file://0001-glimagesink-Downrank-to-marginal.patch \
             file://0002-mpegtsmux-Need-get-pid-when-create-streams.patch \
+            file://0003-mpeg4videoparse-Need-detect-picture-coding-type-when.patch \
 "
 
 SRC_URI[md5sum] = "7c73bec1d389f0e184ebbbbb9e9f883d"
-- 
1.9.1



^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [poky][PATCH 09/13] gstreamer1.0-plugins-bad: Detect picture coding type when drain
  2016-01-18  9:32 [poky][PATCH 00/13] Add patches for gstreamer 1.6 Yuqing Zhu
                   ` (7 preceding siblings ...)
  2016-01-18  9:32 ` [poky][PATCH 08/13] gstreamer1.0-plugins-bad: Add check coding type when drain in mpeg4videoparse Yuqing Zhu
@ 2016-01-18  9:32 ` Yuqing Zhu
  2016-01-18  9:32 ` [poky][PATCH 10/13] gstreamer1.0-plugins-bad: Fix frame rate info lost when fixate caps Yuqing Zhu
                   ` (4 subsequent siblings)
  13 siblings, 0 replies; 19+ messages in thread
From: Yuqing Zhu @ 2016-01-18  9:32 UTC (permalink / raw)
  To: openembedded-core

Signed-off-by: Yuqing Zhu <b54851@freescale.com>
---
 ...rse-Need-detect-picture-coding-type-when-.patch | 47 ++++++++++++++++++++++
 .../gstreamer/gstreamer1.0-plugins-bad_1.6.2.bb    |  1 +
 2 files changed, 48 insertions(+)
 create mode 100755 meta/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad/0004-mpegvideoparse-Need-detect-picture-coding-type-when-.patch

diff --git a/meta/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad/0004-mpegvideoparse-Need-detect-picture-coding-type-when-.patch b/meta/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad/0004-mpegvideoparse-Need-detect-picture-coding-type-when-.patch
new file mode 100755
index 0000000..81e5f28
--- /dev/null
+++ b/meta/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad/0004-mpegvideoparse-Need-detect-picture-coding-type-when-.patch
@@ -0,0 +1,47 @@
+From 71c688f09c86b2428f58757f42d9ae1ad26227a4 Mon Sep 17 00:00:00 2001
+From: Song Bing <b06498@freescale.com>
+Date: Wed, 20 May 2015 15:15:08 +0800
+Subject: [PATCH 04/10] 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 54ee13b..c70fa6d 100644
+--- a/gst/videoparsers/gstmpegvideoparse.c
++++ b/gst/videoparsers/gstmpegvideoparse.c
+@@ -717,6 +717,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/meta/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad_1.6.2.bb b/meta/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad_1.6.2.bb
index 507d048..4628018 100644
--- a/meta/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad_1.6.2.bb
+++ b/meta/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad_1.6.2.bb
@@ -8,6 +8,7 @@ LIC_FILES_CHKSUM = "file://COPYING;md5=73a5855a8119deb017f5f13cf327095d \
 SRC_URI += "file://0001-glimagesink-Downrank-to-marginal.patch \
             file://0002-mpegtsmux-Need-get-pid-when-create-streams.patch \
             file://0003-mpeg4videoparse-Need-detect-picture-coding-type-when.patch \
+            file://0004-mpegvideoparse-Need-detect-picture-coding-type-when-.patch \
 "
 
 SRC_URI[md5sum] = "7c73bec1d389f0e184ebbbbb9e9f883d"
-- 
1.9.1



^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [poky][PATCH 10/13] gstreamer1.0-plugins-bad: Fix frame rate info lost when fixate caps
  2016-01-18  9:32 [poky][PATCH 00/13] Add patches for gstreamer 1.6 Yuqing Zhu
                   ` (8 preceding siblings ...)
  2016-01-18  9:32 ` [poky][PATCH 09/13] gstreamer1.0-plugins-bad: Detect picture coding type when drain Yuqing Zhu
@ 2016-01-18  9:32 ` Yuqing Zhu
  2016-01-18 15:04   ` Burton, Ross
  2016-01-18  9:33 ` [poky][PATCH 11/13] gstreamer1.0-plugins-bad: Add video stitching support based on Open CV Yuqing Zhu
                   ` (3 subsequent siblings)
  13 siblings, 1 reply; 19+ messages in thread
From: Yuqing Zhu @ 2016-01-18  9:32 UTC (permalink / raw)
  To: openembedded-core

Frame rate info will be lost when fixate caps. It will
cause down stream element fail, such as avimux.

Signed-off-by: Yuqing Zhu <b54851@freescale.com>
---
 ...ter-Lost-frame-rate-info-when-fixate-caps.patch | 51 ++++++++++++++++++++++
 .../gstreamer/gstreamer1.0-plugins-bad_1.6.2.bb    |  1 +
 2 files changed, 52 insertions(+)
 create mode 100755 meta/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad/0005-glfilter-Lost-frame-rate-info-when-fixate-caps.patch

diff --git a/meta/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad/0005-glfilter-Lost-frame-rate-info-when-fixate-caps.patch b/meta/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad/0005-glfilter-Lost-frame-rate-info-when-fixate-caps.patch
new file mode 100755
index 0000000..7313415
--- /dev/null
+++ b/meta/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad/0005-glfilter-Lost-frame-rate-info-when-fixate-caps.patch
@@ -0,0 +1,51 @@
+From 15fcb87bc9abd69377b38ef0f8b48b84a56909f4 Mon Sep 17 00:00:00 2001
+From: Song Bing <b06498@freescale.com>
+Date: Mon, 8 Jun 2015 17:06:22 +0800
+Subject: [PATCH 06/10] 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 78bcbc9..65eba1e 100644
+--- a/gst-libs/gst/gl/gstglfilter.c
++++ b/gst-libs/gst/gl/gstglfilter.c
+@@ -258,7 +258,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,};
+ 
+@@ -271,6 +272,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/meta/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad_1.6.2.bb b/meta/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad_1.6.2.bb
index 4628018..c434a08 100644
--- a/meta/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad_1.6.2.bb
+++ b/meta/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad_1.6.2.bb
@@ -9,6 +9,7 @@ SRC_URI += "file://0001-glimagesink-Downrank-to-marginal.patch \
             file://0002-mpegtsmux-Need-get-pid-when-create-streams.patch \
             file://0003-mpeg4videoparse-Need-detect-picture-coding-type-when.patch \
             file://0004-mpegvideoparse-Need-detect-picture-coding-type-when-.patch \
+            file://0005-glfilter-Lost-frame-rate-info-when-fixate-caps.patch \
 "
 
 SRC_URI[md5sum] = "7c73bec1d389f0e184ebbbbb9e9f883d"
-- 
1.9.1



^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [poky][PATCH 11/13] gstreamer1.0-plugins-bad: Add video stitching support based on Open CV
  2016-01-18  9:32 [poky][PATCH 00/13] Add patches for gstreamer 1.6 Yuqing Zhu
                   ` (9 preceding siblings ...)
  2016-01-18  9:32 ` [poky][PATCH 10/13] gstreamer1.0-plugins-bad: Fix frame rate info lost when fixate caps Yuqing Zhu
@ 2016-01-18  9:33 ` Yuqing Zhu
  2016-01-18 15:10   ` Burton, Ross
  2016-01-18  9:33 ` [poky][PATCH 12/13] gstreamer1.0-plugins-bad: Fix memory leak of navigation thread in glwindow Yuqing Zhu
                   ` (2 subsequent siblings)
  13 siblings, 1 reply; 19+ messages in thread
From: Yuqing Zhu @ 2016-01-18  9:33 UTC (permalink / raw)
  To: openembedded-core

Signed-off-by: Yuqing Zhu <b54851@freescale.com>
---
 ...-video-stitching-support-based-on-Open-CV.patch | 1915 ++++++++++++++++++++
 .../gstreamer/gstreamer1.0-plugins-bad_1.6.2.bb    |    1 +
 2 files changed, 1916 insertions(+)
 create mode 100755 meta/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad/0006-opencv-Add-video-stitching-support-based-on-Open-CV.patch

diff --git a/meta/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad/0006-opencv-Add-video-stitching-support-based-on-Open-CV.patch b/meta/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad/0006-opencv-Add-video-stitching-support-based-on-Open-CV.patch
new file mode 100755
index 0000000..e19e222
--- /dev/null
+++ b/meta/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad/0006-opencv-Add-video-stitching-support-based-on-Open-CV.patch
@@ -0,0 +1,1915 @@
+From a2a7f25eba91b429a26fd5347007420e258676de Mon Sep 17 00:00:00 2001
+From: Song Bing <b06498@freescale.com>
+Date: Mon, 1 Jun 2015 13:30:11 +0800
+Subject: [PATCH 07/10] opencv: Add video stitching support based on Open CV
+
+Add video stitching element based on Open CV.
+
+Upstream-Status: Submitted [https://bugzilla.gnome.org/show_bug.cgi?id=751203]
+---
+ docs/plugins/Makefile.am         |   1 +
+ ext/opencv/Makefile.am           |  12 +-
+ ext/opencv/gstcvstitching.cpp    | 834 +++++++++++++++++++++++++++++++++++++++
+ ext/opencv/gstcvstitching.h      | 130 ++++++
+ ext/opencv/gstopencv.cpp         |   4 +
+ ext/opencv/gstopencvaggregator.c | 705 +++++++++++++++++++++++++++++++++
+ ext/opencv/gstopencvaggregator.h | 118 ++++++
+ 7 files changed, 1803 insertions(+), 1 deletion(-)
+ create mode 100644 ext/opencv/gstcvstitching.cpp
+ create mode 100644 ext/opencv/gstcvstitching.h
+ create mode 100644 ext/opencv/gstopencvaggregator.c
+ create mode 100644 ext/opencv/gstopencvaggregator.h
+
+diff --git a/docs/plugins/Makefile.am b/docs/plugins/Makefile.am
+index c431f78..d96ace8 100644
+--- a/docs/plugins/Makefile.am
++++ b/docs/plugins/Makefile.am
+@@ -97,6 +97,7 @@ EXTRA_HFILES = \
+ 	$(top_srcdir)/ext/opencv/gstpyramidsegment.h \
+ 	$(top_srcdir)/ext/opencv/gsttemplatematch.h \
+ 	$(top_srcdir)/ext/opencv/gsttextoverlay.h \
++	$(top_srcdir)/ext/opencv/gstcvstitching.h \
+ 	$(top_srcdir)/ext/openni2/gstopenni2src.h \
+ 	$(top_srcdir)/ext/rsvg/gstrsvgdec.h \
+ 	$(top_srcdir)/ext/rsvg/gstrsvgoverlay.h \
+diff --git a/ext/opencv/Makefile.am b/ext/opencv/Makefile.am
+index 72472fb..66c5786 100644
+--- a/ext/opencv/Makefile.am
++++ b/ext/opencv/Makefile.am
+@@ -24,10 +24,15 @@ libgstopencv_la_SOURCES = gstopencv.cpp \
+ 			gstsegmentation.cpp \
+ 			gstgrabcut.cpp \
+ 			gstdisparity.cpp \
++			gstopencvaggregator.c \
++			gstcvstitching.cpp \
+ 			motioncells_wrapper.cpp \
+ 			MotionCells.cpp
+ 
+-libgstopencv_la_CXXFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_BASE_CFLAGS) $(GST_CXXFLAGS) $(OPENCV_CFLAGS)
++libgstopencv_la_CXXFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_BASE_CFLAGS) \
++	$(GST_CXXFLAGS) $(OPENCV_CFLAGS) \
++	-I$(top_srcdir)/gst-libs \
++	-I$(top_builddir)/gst-libs
+ 
+ # flags used to compile this facedetect
+ # add other _CFLAGS and _LIBS as needed
+@@ -36,11 +41,14 @@ libgstopencv_la_CXXFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_BASE_CFLAGS) $(GST_C
+ # OpenCV's define isn't good enough to avoid 'unused' gcc warnings (at v2.1.0)
+ libgstopencv_la_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_BASE_CFLAGS) \
+ 	$(GST_CFLAGS) $(OPENCV_CFLAGS) \
++	-I$(top_srcdir)/gst-libs \
++	-I$(top_builddir)/gst-libs \
+ 	-DGST_HAAR_CASCADES_DIR=\"$(pkgdatadir)/@GST_API_VERSION@/opencv_haarcascades\" \
+ 	-DCV_INLINE="static inline" \
+ 	-DCV_NO_BACKWARD_COMPATIBILITY
+ 
+ libgstopencv_la_LIBADD = $(GST_LIBS) $(GST_BASE_LIBS) $(OPENCV_LIBS) \
++			$(top_builddir)/gst-libs/gst/video/libgstbadvideo-$(GST_API_VERSION).la \
+ 			$(GSTPB_BASE_LIBS) -lgstvideo-$(GST_API_VERSION)
+ 
+ libgstopencv_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)
+@@ -67,6 +75,8 @@ noinst_HEADERS = gstopencvvideofilter.h gstopencvutils.h \
+ 		gstsegmentation.h \
+ 		gstgrabcut.h \
+ 		gstdisparity.h \
++		gstopencvaggregator.h \
++		gstcvstitching.h \
+ 		gstmotioncells.h \
+ 		motioncells_wrapper.h \
+ 		MotionCells.h
+diff --git a/ext/opencv/gstcvstitching.cpp b/ext/opencv/gstcvstitching.cpp
+new file mode 100644
+index 0000000..47105f7
+--- /dev/null
++++ b/ext/opencv/gstcvstitching.cpp
+@@ -0,0 +1,834 @@
++/*
++ * GStreamer
++ * Copyright (C) 2015 Song Bing <b06498@freescale.com>
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining a
++ * copy of this software and associated documentation files (the "Software"),
++ * to deal in the Software without restriction, including without limitation
++ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
++ * and/or sell copies of the Software, and to permit persons to whom the
++ * Software is furnished to do so, subject to the following conditions:
++ *
++ * The above copyright notice and this permission notice shall be included in
++ * all copies or substantial portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
++ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
++ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
++ * DEALINGS IN THE SOFTWARE.
++ *
++ * Alternatively, the contents of this file may be used under the
++ * GNU Lesser General Public License Version 2.1 (the "LGPL"), in
++ * which case the following provisions apply instead of the ones
++ * mentioned above:
++ *
++ * 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.
++ */
++
++/**
++ * SECTION:element-cvstitching
++ *
++ * video or image stitching.
++ *
++ * video or image stitching.
++ *
++ * <refsect2>
++ * <title>Example launch line</title>
++ * |[
++ * gst-launch-1.0 filesrc  location=IMG_20150529_152901.jpg ! jpegdec ! videoconvert ! imagefreeze ! stitcher. filesrc location=IMG_20150529_152907.jpg ! jpegdec ! videoconvert ! imagefreeze ! stitcher. cvstitching name=stitcher stitcher.src ! videoconvert ! ximagesink sync=false
++ * ]| image stitching.
++ * |[
++ * gst-launch-1.0 filesrc location=IMG_20150529_152901.jpg ! jpegdec ! videoconvert ! imagefreeze ! stitcher. filesrc location=IMG_20150529_152907.jpg ! jpegdec ! videoconvert ! imagefreeze ! stitcher. filesrc location=IMG_20150529_152913.jpg ! jpegdec ! videoconvert ! imagefreeze ! stitcher. filesrc location=IMG_20150529_152918.jpg ! jpegdec ! videoconvert ! imagefreeze ! stitcher. filesrc location=IMG_20150529_152924.jpg ! jpegdec ! videoconvert ! imagefreeze ! stitcher. filesrc location=IMG_20150529_152929.jpg ! jpegdec ! videoconvert ! imagefreeze ! stitcher. filesrc location=IMG_20150529_152933.jpg ! jpegdec ! videoconvert ! 
++ *imagefreeze ! stitcher. filesrc location=IMG_20150529_152938.jpg ! jpegdec ! videoconvert ! imagefreeze ! stitcher. filesrc location=IMG_20150529_152942.jpg ! jpegdec ! videoconvert ! imagefreeze ! stitcher. filesrc location=IMG_20150529_152947.jpg ! jpegdec ! videoconvert ! imagefreeze ! stitcher. filesrc location=IMG_20150529_152951.jpg ! jpegdec ! videoconvert ! imagefreeze ! stitcher. cvstitching name=stitcher stitcher.src ! videoconvert ! ximagesink sync=false
++ * ]| images stitching.
++ *
++ * </refsect2>
++ */
++
++#ifdef HAVE_CONFIG_H
++#  include <config.h>
++#endif
++
++#include "gstopencvutils.h"
++#include "gstcvstitching.h"
++
++// default settings.
++bool preview = false;
++bool try_gpu = false;
++double work_megapix = 0.6;
++double seam_megapix = 0.1;
++double compose_megapix = -1;
++float conf_thresh = 1.f;
++string ba_refine_mask = "xxxxx";
++bool do_wave_correct = true;
++WaveCorrectKind wave_correct = detail::WAVE_CORRECT_HORIZ;
++int expos_comp_type = ExposureCompensator::GAIN_BLOCKS;
++float match_conf = 0.3f;
++int blend_type = Blender::MULTI_BAND;
++float blend_strength = 5;
++
++#define gst_cv_stitching_parent_class parent_class
++
++#define GST_CAT_DEFAULT gst_cv_stitching_debug
++GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
++
++#define DEFAULT_FEATURE_TYPE 0
++#define DEFAULT_WARP_TYPE 0
++#define DEFAULT_SEAM_FIND 0
++#define DEFAULT_BA_COST_FUNC 0
++enum
++{
++  PROP_0,
++  PROP_FEATURE_TYPE,
++  PROP_WARP_TYPE,
++  PROP_SEAM_FIND_TYPE,
++  PROP_BA_COST_FUNC
++};
++
++static GstStaticPadTemplate sink_factory = GST_STATIC_PAD_TEMPLATE ("sink_%u",
++    GST_PAD_SINK,
++    GST_PAD_REQUEST,
++    GST_STATIC_CAPS (GST_VIDEO_CAPS_MAKE ("RGB"))
++    );
++
++static GstStaticPadTemplate src_factory = GST_STATIC_PAD_TEMPLATE ("src",
++    GST_PAD_SRC,
++    GST_PAD_ALWAYS,
++    GST_STATIC_CAPS (GST_VIDEO_CAPS_MAKE ("RGB"))
++    );
++
++G_DEFINE_TYPE (GstCvStitching, gst_cv_stitching, GST_TYPE_OPENCV_AGGREGATOR);
++
++G_DEFINE_TYPE (GstCvStitchingPad, gst_cv_stitching_pad,
++    GST_TYPE_OPENCV_AGGREGATOR_PAD);
++
++static void gst_cv_stitching_pad_set_property (GObject * object,
++    guint prop_id, const GValue * value, GParamSpec * pspec);
++static void gst_cv_stitching_pad_get_property (GObject * object,
++    guint prop_id, GValue * value, GParamSpec * pspec);
++
++enum
++{
++  PROP_PAD_0,
++};
++
++static void
++gst_cv_stitching_pad_class_init (GstCvStitchingPadClass * klass)
++{
++  GObjectClass *gobject_class = (GObjectClass *) klass;
++
++  gobject_class->set_property = gst_cv_stitching_pad_set_property;
++  gobject_class->get_property = gst_cv_stitching_pad_get_property;
++}
++
++static void
++gst_cv_stitching_pad_init (GstCvStitchingPad * pad)
++{
++}
++
++static void
++gst_cv_stitching_pad_get_property (GObject * object, guint prop_id,
++    GValue * value, GParamSpec * pspec)
++{
++  switch (prop_id) {
++    default:
++      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
++      break;
++  }
++}
++
++static void
++gst_cv_stitching_pad_set_property (GObject * object, guint prop_id,
++    const GValue * value, GParamSpec * pspec)
++{
++  switch (prop_id) {
++    default:
++      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
++      break;
++  }
++}
++
++static void gst_cv_stitching_set_property (GObject * object, guint prop_id,
++    const GValue * value, GParamSpec * pspec);
++static void gst_cv_stitching_get_property (GObject * object, guint prop_id,
++    GValue * value, GParamSpec * pspec);
++static gboolean gst_cv_stitching_start (GstAggregator * agg);
++static gboolean gst_cv_stitching_stop (GstAggregator * agg);
++static gboolean
++gst_cv_stitching_process (GstOpencvAggregator * agg, GPtrArray *imgs,
++        IplImage *outimg);
++
++enum _GstCvStitchingFeatureTypes {
++  GST_CV_STITCHING_FEATURE_TYPES_SURF = 0,
++  GST_CV_STITCHING_FEATURE_TYPES_ORB = 1
++};
++
++#define GST_TYPE_CV_STITCHING_FEATURE_TYPES (cv_stitching_feature_type_get_type ())
++
++static GType
++cv_stitching_feature_type_get_type (void)
++{
++  static GType cv_stitching_feature_type_type = 0;
++  static const GEnumValue cv_stitching_feature_type[] = {
++    {GST_CV_STITCHING_FEATURE_TYPES_SURF, "feature type surf", "surf"},
++    {GST_CV_STITCHING_FEATURE_TYPES_ORB, "feature type surf", "orb"},
++    {0, NULL, NULL},
++  };
++
++  if (!cv_stitching_feature_type_type) {
++    cv_stitching_feature_type_type =
++      g_enum_register_static ("GstCvStitchingFeatureTypes", cv_stitching_feature_type);
++  }
++  return cv_stitching_feature_type_type;
++}
++
++enum _GstCvStitchingWarpTypes {
++  GST_CV_STITCHING_WARP_TYPES_PLANE = 0,
++  GST_CV_STITCHING_WARP_TYPES_CYLINDRICAL = 1,
++  GST_CV_STITCHING_WARP_TYPES_SPHERICAL = 2,
++  GST_CV_STITCHING_WARP_TYPES_FISHEYE = 3,
++  GST_CV_STITCHING_WARP_TYPES_STEREOGRAPHIC = 4,
++  GST_CV_STITCHING_WARP_TYPES_COMPRESSEDPLANEA2B1 = 5,
++  GST_CV_STITCHING_WARP_TYPES_COMPRESSEDPLANEA1_5B1 = 6,
++  GST_CV_STITCHING_WARP_TYPES_COMPRESSEDPLANEPORTRAITA2B1 = 7,
++  GST_CV_STITCHING_WARP_TYPES_COMPRESSEDPLANEPORTRAITA1_5B1 = 8,
++  GST_CV_STITCHING_WARP_TYPES_PANINIA2B1 = 9,
++  GST_CV_STITCHING_WARP_TYPES_PANINIA1_5B1 = 10,
++  GST_CV_STITCHING_WARP_TYPES_PANINIPORTRAITA2B1 = 11,
++  GST_CV_STITCHING_WARP_TYPES_PANINIPORTRAITA1_5B1 = 12,
++  GST_CV_STITCHING_WARP_TYPES_MERCATOR = 13,
++  GST_CV_STITCHING_WARP_TYPES_TRANSVERSEMERCATOR = 14
++};
++
++#define GST_TYPE_CV_STITCHING_WARP_TYPES (cv_stitching_warp_type_get_type ())
++
++static GType
++cv_stitching_warp_type_get_type (void)
++{
++  static GType cv_stitching_warp_type_type = 0;
++  static const GEnumValue cv_stitching_warp_type[] = {
++    {GST_CV_STITCHING_WARP_TYPES_PLANE, "warp type plane", "plane"},
++    {GST_CV_STITCHING_WARP_TYPES_CYLINDRICAL, "warp type cylindrical", "cylindrical"},
++    {GST_CV_STITCHING_WARP_TYPES_SPHERICAL, "warp type spherical", "spherical"},
++    {GST_CV_STITCHING_WARP_TYPES_FISHEYE, "warp type fisheye", "fisheye"},
++    {GST_CV_STITCHING_WARP_TYPES_STEREOGRAPHIC, "warp type stereographic", "stereographic"},
++    {GST_CV_STITCHING_WARP_TYPES_COMPRESSEDPLANEA2B1, "warp type compressedPlaneA2B1", "compressedPlaneA2B1"},
++    {GST_CV_STITCHING_WARP_TYPES_COMPRESSEDPLANEA1_5B1, "warp type compressedPlaneA1.5B1", "compressedPlaneA1.5B1"},
++    {GST_CV_STITCHING_WARP_TYPES_COMPRESSEDPLANEPORTRAITA2B1, "warp type compressedPlanePortraitA2B1", "compressedPlanePortraitA2B1"},
++    {GST_CV_STITCHING_WARP_TYPES_COMPRESSEDPLANEPORTRAITA1_5B1, "warp type compressedPlanePortraitA1.5B1", "compressedPlanePortraitA1.5B1"},
++    {GST_CV_STITCHING_WARP_TYPES_PANINIA2B1, "warp type paniniA2B1", "paniniA2B1"},
++    {GST_CV_STITCHING_WARP_TYPES_PANINIA1_5B1, "warp type paniniA1.5B1", "paniniA1.5B1"},
++    {GST_CV_STITCHING_WARP_TYPES_PANINIPORTRAITA2B1, "warp type paniniPortraitA2B1", "paniniPortraitA2B1"},
++    {GST_CV_STITCHING_WARP_TYPES_PANINIPORTRAITA1_5B1, "warp type paniniPortraitA1.5B1", "paniniPortraitA1.5B1"},
++    {GST_CV_STITCHING_WARP_TYPES_MERCATOR, "warp type mercator", "mercator"},
++    {GST_CV_STITCHING_WARP_TYPES_TRANSVERSEMERCATOR, "warp type transverseMercator", "transverseMercator"},
++    {0, NULL, NULL},
++  };
++
++  if (!cv_stitching_warp_type_type) {
++    cv_stitching_warp_type_type =
++      g_enum_register_static ("GstCvStitchingWarpTypes", cv_stitching_warp_type);
++  }
++  return cv_stitching_warp_type_type;
++}
++
++enum _GstCvStitchingSeamFindTypes {
++  GST_CV_STITCHING_SEAM_FIND_TYPES_NO = 0,
++  GST_CV_STITCHING_SEAM_FIND_TYPES_VORONOI = 1,
++  GST_CV_STITCHING_SEAM_FIND_TYPES_GC_COLOR = 2,
++  GST_CV_STITCHING_SEAM_FIND_TYPES_GC_COLORGRAD = 3,
++  GST_CV_STITCHING_SEAM_FIND_TYPES_DP_COLOR = 4,
++  GST_CV_STITCHING_SEAM_FIND_TYPES_DP_COLORGRAD = 5
++};
++
++#define GST_TYPE_CV_STITCHING_SEAM_FIND_TYPES (cv_stitching_seam_find_type_get_type ())
++
++static GType
++cv_stitching_seam_find_type_get_type (void)
++{
++  static GType cv_stitching_seam_find_type_type = 0;
++  static const GEnumValue cv_stitching_seam_find_type[] = {
++    {GST_CV_STITCHING_SEAM_FIND_TYPES_NO, "seam_find type no", "no"},
++    {GST_CV_STITCHING_SEAM_FIND_TYPES_VORONOI, "seam_find type voronoi", "voronoi"},
++    {GST_CV_STITCHING_SEAM_FIND_TYPES_GC_COLOR, "seam_find type gc_color", "gc_color"},
++    {GST_CV_STITCHING_SEAM_FIND_TYPES_GC_COLORGRAD, "seam_find type gc_colorgrad", "gc_colorgrad"},
++    {GST_CV_STITCHING_SEAM_FIND_TYPES_DP_COLOR, "seam_find type dp_color", "dp_color"},
++    {GST_CV_STITCHING_SEAM_FIND_TYPES_DP_COLORGRAD, "seam_find type dp_colorgrad", "dp_colorgrad"},
++    {0, NULL, NULL},
++  };
++
++  if (!cv_stitching_seam_find_type_type) {
++    cv_stitching_seam_find_type_type =
++      g_enum_register_static ("GstCvStitchingSeamFindTypes", cv_stitching_seam_find_type);
++  }
++  return cv_stitching_seam_find_type_type;
++}
++
++enum _GstCvStitchingBACostFuncs {
++  GST_CV_STITCHING_BA_COST_FUNCS_REPROJ = 0,
++  GST_CV_STITCHING_BA_COST_FUNCS_RAY = 1
++};
++
++#define GST_TYPE_CV_STITCHING_BA_COST_FUNCS (cv_stitching_ba_cost_func_get_type ())
++
++static GType
++cv_stitching_ba_cost_func_get_type (void)
++{
++  static GType cv_stitching_ba_cost_func_type = 0;
++  static const GEnumValue cv_stitching_ba_cost_func[] = {
++    {GST_CV_STITCHING_BA_COST_FUNCS_REPROJ, "ba cost func reproj", "reproj"},
++    {GST_CV_STITCHING_BA_COST_FUNCS_RAY, "ba cost func ray", "ray"},
++    {0, NULL, NULL},
++  };
++
++  if (!cv_stitching_ba_cost_func_type) {
++    cv_stitching_ba_cost_func_type =
++      g_enum_register_static ("GstCvStitchingBACostFuncs", cv_stitching_ba_cost_func);
++  }
++  return cv_stitching_ba_cost_func_type;
++}
++
++static void
++gst_cv_stitching_class_init (GstCvStitchingClass * klass)
++{
++  GObjectClass *gobject_class;
++  GstElementClass *element_class;
++  GstAggregatorClass *agg_class = (GstAggregatorClass *) klass;
++  GstOpencvAggregatorClass *cvagg_class = (GstOpencvAggregatorClass *) klass;
++
++  gobject_class = (GObjectClass *) klass;
++  element_class = GST_ELEMENT_CLASS (klass);
++
++  gobject_class->set_property = gst_cv_stitching_set_property;
++  gobject_class->get_property = gst_cv_stitching_get_property;
++
++  gst_element_class_add_pad_template (element_class,
++      gst_static_pad_template_get (&src_factory));
++  gst_element_class_add_pad_template (element_class,
++      gst_static_pad_template_get (&sink_factory));
++
++  g_object_class_install_property (gobject_class, PROP_FEATURE_TYPE,
++      g_param_spec_enum ("feturetypes", "Featuretypes", "match feature type",
++        GST_TYPE_CV_STITCHING_FEATURE_TYPES, DEFAULT_FEATURE_TYPE,
++        G_PARAM_READWRITE));
++  g_object_class_install_property (gobject_class, PROP_WARP_TYPE,
++      g_param_spec_enum ("warptypes", "Warptypes", "Warp type",
++        GST_TYPE_CV_STITCHING_WARP_TYPES, DEFAULT_WARP_TYPE,
++        G_PARAM_READWRITE));
++  g_object_class_install_property (gobject_class, PROP_SEAM_FIND_TYPE,
++      g_param_spec_enum ("seamfindtypes", "Seamfindtypes", "Seam find type",
++        GST_TYPE_CV_STITCHING_SEAM_FIND_TYPES, DEFAULT_SEAM_FIND,
++        G_PARAM_READWRITE));
++  g_object_class_install_property (gobject_class, PROP_BA_COST_FUNC,
++      g_param_spec_enum ("bacostfuncs", "Bacostfuncs", "Ba cost func",
++        GST_TYPE_CV_STITCHING_BA_COST_FUNCS, DEFAULT_BA_COST_FUNC,
++        G_PARAM_READWRITE));
++
++  gst_element_class_set_metadata (element_class, "OpenCV video_stitcher",
++      "Aggregator/VideoAggregator/CvStitching", "OpenCV video_stitcher",
++      "Song Bing <b06498@freescale.com>");
++
++  agg_class->start = gst_cv_stitching_start;
++  agg_class->stop = gst_cv_stitching_stop;
++
++  cvagg_class->GstOpencvAggregatorProcess = gst_cv_stitching_process;
++
++  agg_class->sinkpads_type = GST_TYPE_CV_STITCHING_PAD;
++}
++
++static void
++gst_cv_stitching_init (GstCvStitching * stitcher)
++{
++  stitcher->features_type = DEFAULT_FEATURE_TYPE;
++  stitcher->warp_type = DEFAULT_WARP_TYPE;
++  stitcher->seam_find_type = DEFAULT_SEAM_FIND;
++  stitcher->ba_cost_func = DEFAULT_BA_COST_FUNC;
++}
++
++static void
++gst_cv_stitching_set_property (GObject * object, guint prop_id,
++    const GValue * value, GParamSpec * pspec)
++{
++  GstCvStitching *stitcher = GST_CV_STITCHING (object);
++
++  switch (prop_id) {
++    case PROP_FEATURE_TYPE:
++      stitcher->features_type = g_value_get_enum (value);
++      break;
++    case PROP_WARP_TYPE:
++      stitcher->warp_type = g_value_get_enum (value);
++      break;
++     case PROP_SEAM_FIND_TYPE:
++      stitcher->seam_find_type = g_value_get_enum (value);
++      break;
++     case PROP_BA_COST_FUNC:
++      stitcher->ba_cost_func = g_value_get_enum (value);
++      break;
++    default:
++      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
++      break;
++  }
++}
++
++static void
++gst_cv_stitching_get_property (GObject * object, guint prop_id,
++    GValue * value, GParamSpec * pspec)
++{
++  GstCvStitching *stitcher = GST_CV_STITCHING (object);
++
++  switch (prop_id) {
++    case PROP_FEATURE_TYPE:
++      g_value_set_enum (value, stitcher->features_type);
++      break;
++    case PROP_WARP_TYPE:
++      g_value_set_enum (value, stitcher->warp_type);
++      break;
++     case PROP_SEAM_FIND_TYPE:
++      g_value_set_enum (value, stitcher->seam_find_type);
++      break;
++     case PROP_BA_COST_FUNC:
++      g_value_set_enum (value, stitcher->ba_cost_func);
++      break;
++    default:
++      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
++      break;
++  }
++}
++
++static gboolean
++gst_cv_stitching_start (GstAggregator * agg)
++{
++  GstCvStitching *stitcher = GST_CV_STITCHING (agg);
++
++  if (!GST_AGGREGATOR_CLASS (parent_class)->start (agg))
++    return FALSE;
++
++  if (stitcher->features_type == GST_CV_STITCHING_FEATURE_TYPES_SURF) {
++      stitcher->finder = new SurfFeaturesFinder();
++  } else if (stitcher->features_type == GST_CV_STITCHING_FEATURE_TYPES_ORB) {
++    stitcher->finder = new OrbFeaturesFinder();
++  } else {
++    GST_ERROR_OBJECT (stitcher, "Unknown 2D features type: %d", stitcher->features_type);
++    return FALSE;
++  }
++
++  if (stitcher->warp_type == GST_CV_STITCHING_WARP_TYPES_PLANE)
++    stitcher->warper_creator = new cv::PlaneWarper();
++  else if (stitcher->warp_type == GST_CV_STITCHING_WARP_TYPES_CYLINDRICAL)
++    stitcher->warper_creator = new cv::CylindricalWarper();
++  else if (stitcher->warp_type == GST_CV_STITCHING_WARP_TYPES_SPHERICAL)
++    stitcher->warper_creator = new cv::SphericalWarper();
++  else if (stitcher->warp_type == GST_CV_STITCHING_WARP_TYPES_FISHEYE)
++    stitcher->warper_creator = new cv::FisheyeWarper();
++  else if (stitcher->warp_type == GST_CV_STITCHING_WARP_TYPES_STEREOGRAPHIC)
++    stitcher->warper_creator = new cv::StereographicWarper();
++  else if (stitcher->warp_type == GST_CV_STITCHING_WARP_TYPES_COMPRESSEDPLANEA2B1)
++    stitcher->warper_creator = new cv::CompressedRectilinearWarper(2, 1);
++  else if (stitcher->warp_type == GST_CV_STITCHING_WARP_TYPES_COMPRESSEDPLANEA1_5B1)
++    stitcher->warper_creator = new cv::CompressedRectilinearWarper(1.5, 1);
++  else if (stitcher->warp_type == GST_CV_STITCHING_WARP_TYPES_COMPRESSEDPLANEPORTRAITA2B1)
++    stitcher->warper_creator = new cv::CompressedRectilinearPortraitWarper(2, 1);
++  else if (stitcher->warp_type == GST_CV_STITCHING_WARP_TYPES_COMPRESSEDPLANEPORTRAITA1_5B1)
++    stitcher->warper_creator = new cv::CompressedRectilinearPortraitWarper(1.5, 1);
++  else if (stitcher->warp_type == GST_CV_STITCHING_WARP_TYPES_PANINIA2B1)
++    stitcher->warper_creator = new cv::PaniniWarper(2, 1);
++  else if (stitcher->warp_type == GST_CV_STITCHING_WARP_TYPES_PANINIA1_5B1)
++    stitcher->warper_creator = new cv::PaniniWarper(1.5, 1);
++  else if (stitcher->warp_type == GST_CV_STITCHING_WARP_TYPES_PANINIPORTRAITA2B1)
++    stitcher->warper_creator = new cv::PaniniPortraitWarper(2, 1);
++  else if (stitcher->warp_type == GST_CV_STITCHING_WARP_TYPES_PANINIPORTRAITA1_5B1)
++    stitcher->warper_creator = new cv::PaniniPortraitWarper(1.5, 1);
++  else if (stitcher->warp_type == GST_CV_STITCHING_WARP_TYPES_MERCATOR)
++    stitcher->warper_creator = new cv::MercatorWarper();
++  else if (stitcher->warp_type == GST_CV_STITCHING_WARP_TYPES_TRANSVERSEMERCATOR)
++    stitcher->warper_creator = new cv::TransverseMercatorWarper();
++  if (stitcher->warper_creator.empty()) {
++    GST_ERROR_OBJECT (stitcher, "Can't create the following warper: %d",
++        stitcher->warp_type);
++    return FALSE;
++  }
++
++  if (stitcher->seam_find_type == GST_CV_STITCHING_SEAM_FIND_TYPES_NO)
++    stitcher->seam_finder = new detail::NoSeamFinder();
++  else if (stitcher->seam_find_type == GST_CV_STITCHING_SEAM_FIND_TYPES_VORONOI)
++    stitcher->seam_finder = new detail::VoronoiSeamFinder();
++  else if (stitcher->seam_find_type == GST_CV_STITCHING_SEAM_FIND_TYPES_GC_COLOR) {
++    stitcher->seam_finder = new detail::GraphCutSeamFinder(GraphCutSeamFinderBase::COST_COLOR);
++  } else if (stitcher->seam_find_type == GST_CV_STITCHING_SEAM_FIND_TYPES_GC_COLORGRAD) {
++    stitcher->seam_finder = new detail::GraphCutSeamFinder(GraphCutSeamFinderBase::COST_COLOR_GRAD);
++  } else if (stitcher->seam_find_type == GST_CV_STITCHING_SEAM_FIND_TYPES_DP_COLOR)
++    stitcher->seam_finder = new detail::DpSeamFinder(DpSeamFinder::COLOR);
++  else if (stitcher->seam_find_type == GST_CV_STITCHING_SEAM_FIND_TYPES_DP_COLORGRAD)
++    stitcher->seam_finder = new detail::DpSeamFinder(DpSeamFinder::COLOR_GRAD);
++  if (stitcher->seam_finder.empty()) {
++    GST_ERROR_OBJECT (stitcher, "Can't create the following seam finder: %d",
++        stitcher->seam_find_type);
++    return FALSE;
++  }
++
++  if (stitcher->ba_cost_func == GST_CV_STITCHING_BA_COST_FUNCS_REPROJ)
++    stitcher->adjuster = new detail::BundleAdjusterReproj();
++  else if (stitcher->ba_cost_func == GST_CV_STITCHING_BA_COST_FUNCS_RAY)
++    stitcher->adjuster = new detail::BundleAdjusterRay();
++  else {
++    GST_ERROR_OBJECT (stitcher, "Unknown bundle adjustment cost function: %d",
++        stitcher->ba_cost_func);
++    return FALSE;
++  }
++
++  return TRUE;
++}
++
++static gboolean
++gst_cv_stitching_stop (GstAggregator * agg)
++{
++  GstCvStitching *stitcher = GST_CV_STITCHING (agg);
++
++  stitcher->finder.release();
++  stitcher->warper_creator.release();
++  stitcher->seam_finder.release();
++  stitcher->adjuster.release();
++
++  return GST_AGGREGATOR_CLASS (parent_class)->stop (agg);
++}
++
++static gboolean
++gst_cv_stitching_process (GstOpencvAggregator * agg, GPtrArray *imgs,
++        IplImage *outimg)
++{
++  GstCvStitching *stitcher = GST_CV_STITCHING (agg);
++  int64 app_start_time = getTickCount();
++
++  GST_LOG_OBJECT (stitcher, "video stitching process");
++  int num_images = imgs->len;
++  if (num_images < 2) {
++    GST_ERROR_OBJECT (stitcher, "Need more images");
++    return FALSE;
++  }
++
++  double work_scale = 1, seam_scale = 1, compose_scale = 1;
++  bool is_work_scale_set = false, is_seam_scale_set = false, is_compose_scale_set = false;
++
++  GST_LOG_OBJECT (stitcher, "Finding features...");
++  int64 t = getTickCount();
++
++  Mat full_img, img;
++  vector<ImageFeatures> features(num_images);
++  vector<Mat> images(num_images);
++  vector<Size> full_img_sizes(num_images);
++  double seam_work_aspect = 1;
++
++  for (int i = 0; i < num_images; ++i) {
++    IplImage *cvImage = (IplImage *) g_ptr_array_index (imgs, i);
++    Mat in_mat(cvImage, false);
++
++    full_img = in_mat;
++    full_img_sizes[i] = full_img.size();
++
++    if (full_img.empty()) {
++      GST_ERROR_OBJECT (stitcher, "No input data");
++      return FALSE;
++    }
++    if (work_megapix < 0) {
++      img = full_img;
++      work_scale = 1;
++      is_work_scale_set = true;
++    } else {
++      if (!is_work_scale_set) {
++        work_scale = min(1.0, sqrt(work_megapix * 1e6 / full_img.size().area()));
++        is_work_scale_set = true;
++      }
++      resize(full_img, img, Size(), work_scale, work_scale);
++    }
++    if (!is_seam_scale_set) {
++      seam_scale = min(1.0, sqrt(seam_megapix * 1e6 / full_img.size().area()));
++      seam_work_aspect = seam_scale / work_scale;
++      is_seam_scale_set = true;
++    }
++
++    (*stitcher->finder)(img, features[i]);
++    features[i].img_idx = i;
++    //LOGLN("Features in image #" << i+1 << ": " << features[i].keypoints.size());
++
++    resize(full_img, img, Size(), seam_scale, seam_scale);
++    images[i] = img.clone();
++  }
++
++  stitcher->finder->collectGarbage();
++  full_img.release();
++  img.release();
++
++  GST_LOG_OBJECT (stitcher, "Finding features, time: %f sec",
++      ((getTickCount() - t) / getTickFrequency()));
++
++  GST_LOG_OBJECT (stitcher, "Pairwise matching");
++  t = getTickCount();
++  BestOf2NearestMatcher matcher(try_gpu, match_conf);
++  vector<MatchesInfo> pairwise_matches;
++
++  matcher(features, pairwise_matches);
++  matcher.collectGarbage();
++  GST_LOG_OBJECT (stitcher, "Pairwise matching, time: %f sec",
++      ((getTickCount() - t) / getTickFrequency()));
++
++  // Leave only images we are sure are from the same panorama
++  vector<int> indices = leaveBiggestComponent(features, pairwise_matches, conf_thresh);
++  vector<Mat> img_subset;
++  vector<Size> full_img_sizes_subset;
++  for (size_t i = 0; i < indices.size(); ++i) {
++    img_subset.push_back(images[indices[i]]);
++    full_img_sizes_subset.push_back(full_img_sizes[indices[i]]);
++  }
++
++  images = img_subset;
++  full_img_sizes = full_img_sizes_subset;
++
++  // Check if we still have enough images
++  num_images = static_cast<int>(images.size());
++  if (num_images < 2) {
++    GST_WARNING_OBJECT (stitcher, "Can't find overlap images");
++    return FALSE;
++  }
++  HomographyBasedEstimator estimator;
++  vector<CameraParams> cameras;
++  estimator(features, pairwise_matches, cameras);
++
++  for (size_t i = 0; i < cameras.size(); ++i) {
++    Mat R;
++    cameras[i].R.convertTo(R, CV_32F);
++    cameras[i].R = R;
++    //LOGLN("Initial intrinsics #" << indices[i]+1 << ":\n" << cameras[i].K());
++  }
++
++  stitcher->adjuster->setConfThresh(conf_thresh);
++  Mat_<uchar> refine_mask = Mat::zeros(3, 3, CV_8U);
++  if (ba_refine_mask[0] == 'x') refine_mask(0,0) = 1;
++  if (ba_refine_mask[1] == 'x') refine_mask(0,1) = 1;
++  if (ba_refine_mask[2] == 'x') refine_mask(0,2) = 1;
++  if (ba_refine_mask[3] == 'x') refine_mask(1,1) = 1;
++  if (ba_refine_mask[4] == 'x') refine_mask(1,2) = 1;
++  stitcher->adjuster->setRefinementMask(refine_mask);
++  (*stitcher->adjuster)(features, pairwise_matches, cameras);
++
++  // Find median focal length
++  vector<double> focals;
++  for (size_t i = 0; i < cameras.size(); ++i) {
++    //LOGLN("Camera #" << indices[i]+1 << ":\n" << cameras[i].K());
++    focals.push_back(cameras[i].focal);
++  }
++
++  sort(focals.begin(), focals.end());
++  float warped_image_scale;
++  if (focals.size() % 2 == 1)
++    warped_image_scale = static_cast<float>(focals[focals.size() / 2]);
++  else
++    warped_image_scale = static_cast<float>(focals[focals.size() / 2 - 1]
++        + focals[focals.size() / 2]) * 0.5f;
++
++  if (do_wave_correct) {
++    vector<Mat> rmats;
++    for (size_t i = 0; i < cameras.size(); ++i)
++      rmats.push_back(cameras[i].R);
++    waveCorrect(rmats, wave_correct);
++    for (size_t i = 0; i < cameras.size(); ++i)
++      cameras[i].R = rmats[i];
++  }
++
++  GST_LOG_OBJECT (stitcher, "Warping images (auxiliary)... ");
++  t = getTickCount();
++
++  vector<Point> corners(num_images);
++  vector<Mat> masks_warped(num_images);
++  vector<Mat> images_warped(num_images);
++  vector<Size> sizes(num_images);
++  vector<Mat> masks(num_images);
++
++  // Preapre images masks
++  for (int i = 0; i < num_images; ++i) {
++    masks[i].create(images[i].size(), CV_8U);
++    masks[i].setTo(Scalar::all(255));
++  }
++
++  Ptr<RotationWarper> warper = stitcher->warper_creator->create(
++      static_cast<float>(warped_image_scale * seam_work_aspect));
++
++  for (int i = 0; i < num_images; ++i) {
++    Mat_<float> K;
++    cameras[i].K().convertTo(K, CV_32F);
++    float swa = (float)seam_work_aspect;
++    K(0,0) *= swa; K(0,2) *= swa;
++    K(1,1) *= swa; K(1,2) *= swa;
++
++    corners[i] = warper->warp(images[i], K, cameras[i].R,
++        INTER_LINEAR, BORDER_REFLECT, images_warped[i]);
++    sizes[i] = images_warped[i].size();
++
++    warper->warp(masks[i], K, cameras[i].R, INTER_NEAREST,
++        BORDER_CONSTANT, masks_warped[i]);
++  }
++
++  vector<Mat> images_warped_f(num_images);
++  for (int i = 0; i < num_images; ++i)
++    images_warped[i].convertTo(images_warped_f[i], CV_32F);
++
++  GST_LOG_OBJECT (stitcher, "Warping images, time: %f sec",
++      ((getTickCount() - t) / getTickFrequency()));
++
++  GST_LOG_OBJECT (stitcher, "seam finder...");
++  t = getTickCount();
++
++  Ptr<ExposureCompensator> compensator = ExposureCompensator::createDefault(expos_comp_type);
++  compensator->feed(corners, images_warped, masks_warped);
++
++  stitcher->seam_finder->find(images_warped_f, corners, masks_warped);
++
++  // Release unused memory
++  images.clear();
++  images_warped.clear();
++  images_warped_f.clear();
++  masks.clear();
++  GST_LOG_OBJECT (stitcher, "seam finder, time: %f sec",
++      ((getTickCount() - t) / getTickFrequency()));
++
++  GST_LOG_OBJECT (stitcher, "Compositing...");
++  t = getTickCount();
++
++  Mat img_warped, img_warped_s;
++  Mat dilated_mask, seam_mask, mask, mask_warped;
++  //double compose_seam_aspect = 1;
++  double compose_work_aspect = 1;
++  Ptr<Blender> blender;
++
++  for (int img_idx = 0; img_idx < num_images; ++img_idx) {
++    //LOGLN("Compositing image #" << indices[img_idx]+1);
++    // Read image and resize it if necessary
++    IplImage *cvImage = (IplImage *) g_ptr_array_index (imgs, img_idx);
++    Mat in_mat(cvImage, false);
++
++    full_img = in_mat;
++    if (!is_compose_scale_set) {
++      if (compose_megapix > 0)
++        compose_scale = min(1.0, sqrt(compose_megapix * 1e6 / full_img.size().area()));
++      is_compose_scale_set = true;
++
++      // Compute relative scales
++      //compose_seam_aspect = compose_scale / seam_scale;
++      compose_work_aspect = compose_scale / work_scale;
++
++      // Update warped image scale
++      warped_image_scale *= static_cast<float>(compose_work_aspect);
++      warper = stitcher->warper_creator->create(warped_image_scale);
++
++      // Update corners and sizes
++      for (int i = 0; i < num_images; ++i) {
++        // Update intrinsics
++        cameras[i].focal *= compose_work_aspect;
++        cameras[i].ppx *= compose_work_aspect;
++        cameras[i].ppy *= compose_work_aspect;
++
++        // Update corner and size
++        Size sz = full_img_sizes[i];
++        if (std::abs(compose_scale - 1) > 1e-1) {
++          sz.width = cvRound(full_img_sizes[i].width * compose_scale);
++          sz.height = cvRound(full_img_sizes[i].height * compose_scale);
++        }
++
++        Mat K;
++        cameras[i].K().convertTo(K, CV_32F);
++        Rect roi = warper->warpRoi(sz, K, cameras[i].R);
++        corners[i] = roi.tl();
++        sizes[i] = roi.size();
++      }
++    }
++    if (abs(compose_scale - 1) > 1e-1)
++      resize(full_img, img, Size(), compose_scale, compose_scale);
++    else
++      img = full_img;
++    full_img.release();
++    Size img_size = img.size();
++
++    Mat K;
++    cameras[img_idx].K().convertTo(K, CV_32F);
++
++    // Warp the current image
++    warper->warp(img, K, cameras[img_idx].R, INTER_LINEAR, BORDER_REFLECT, img_warped);
++
++    // Warp the current image mask
++    mask.create(img_size, CV_8U);
++    mask.setTo(Scalar::all(255));
++    warper->warp(mask, K, cameras[img_idx].R, INTER_NEAREST, BORDER_CONSTANT, mask_warped);
++
++    // Compensate exposure
++    compensator->apply(img_idx, corners[img_idx], img_warped, mask_warped);
++
++    img_warped.convertTo(img_warped_s, CV_16S);
++    img_warped.release();
++    img.release();
++    mask.release();
++
++    dilate(masks_warped[img_idx], dilated_mask, Mat());
++    resize(dilated_mask, seam_mask, mask_warped.size());
++    mask_warped = seam_mask & mask_warped;
++
++    if (blender.empty()) {
++      blender = Blender::createDefault(blend_type, try_gpu);
++      Size dst_sz = resultRoi(corners, sizes).size();
++      float blend_width = sqrt(static_cast<float>(dst_sz.area())) * blend_strength / 100.f;
++      if (blend_width < 1.f)
++        blender = Blender::createDefault(Blender::NO, try_gpu);
++      else if (blend_type == Blender::MULTI_BAND) {
++        MultiBandBlender* mb = dynamic_cast<MultiBandBlender*>(static_cast<Blender*>(blender));
++        mb->setNumBands(static_cast<int>(ceil(log(blend_width)/log(2.)) - 1.));
++        //LOGLN("Multi-band blender, number of bands: " << mb->numBands());
++      } else if (blend_type == Blender::FEATHER) {
++        FeatherBlender* fb = dynamic_cast<FeatherBlender*>(static_cast<Blender*>(blender));
++        fb->setSharpness(1.f/blend_width);
++        //LOGLN("Feather blender, sharpness: " << fb->sharpness());
++      }
++      blender->prepare(corners, sizes);
++    }
++
++    // Blend the current image
++    blender->feed(img_warped_s, mask_warped, corners[img_idx]);
++  }
++
++  Mat result, result_mask;
++  blender->blend(result, result_mask);
++
++  GST_LOG_OBJECT (stitcher, "Compositing, time: %f sec", ((getTickCount() - t) / getTickFrequency()));
++
++  Mat m1(outimg->height, outimg->width, CV_8UC3), m2;
++  resize(result, m1, m1.size());
++  m1.convertTo(m2, CV_8UC3);
++  memcpy(outimg->imageData, m2.data, outimg->imageSize);
++
++  GST_LOG_OBJECT (stitcher, "Finished, total time: %f sec", (
++        (getTickCount() - app_start_time) / getTickFrequency()));
++
++  return TRUE;
++}
++
++gboolean
++gst_cv_stitching_plugin_init (GstPlugin * plugin)
++{
++  GST_DEBUG_CATEGORY_INIT (gst_cv_stitching_debug, "cvstitching",
++      0, "Video or image stitching");
++
++  return gst_element_register (plugin, "cvstitching", GST_RANK_NONE,
++      GST_TYPE_CV_STITCHING);
++}
+diff --git a/ext/opencv/gstcvstitching.h b/ext/opencv/gstcvstitching.h
+new file mode 100644
+index 0000000..ec955d0
+--- /dev/null
++++ b/ext/opencv/gstcvstitching.h
+@@ -0,0 +1,130 @@
++/*
++ * GStreamer
++ * Copyright (C) 2015 Song Bing <b06498@freescale.com>
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining a
++ * copy of this software and associated documentation files (the "Software"),
++ * to deal in the Software without restriction, including without limitation
++ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
++ * and/or sell copies of the Software, and to permit persons to whom the
++ * Software is furnished to do so, subject to the following conditions:
++ *
++ * The above copyright notice and this permission notice shall be included in
++ * all copies or substantial portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
++ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
++ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
++ * DEALINGS IN THE SOFTWARE.
++ *
++ * Alternatively, the contents of this file may be used under the
++ * GNU Lesser General Public License Version 2.1 (the "LGPL"), in
++ * which case the following provisions apply instead of the ones
++ * mentioned above:
++ *
++ * 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_CV_STITCHING_H__
++#define __GST_CV_STITCHING_H__
++
++#include <gst/gst.h>
++#include "opencv2/opencv_modules.hpp"
++#include "opencv2/highgui/highgui.hpp"
++#include "opencv2/stitching/detail/autocalib.hpp"
++#include "opencv2/stitching/detail/blenders.hpp"
++#include "opencv2/stitching/detail/camera.hpp"
++#include "opencv2/stitching/detail/exposure_compensate.hpp"
++#include "opencv2/stitching/detail/matchers.hpp"
++#include "opencv2/stitching/detail/motion_estimators.hpp"
++#include "opencv2/stitching/detail/seam_finders.hpp"
++#include "opencv2/stitching/detail/util.hpp"
++#include "opencv2/stitching/detail/warpers.hpp"
++#include "opencv2/stitching/warpers.hpp"
++#include "gstopencvaggregator.h"
++
++using namespace std;
++using namespace cv;
++using namespace cv::detail;
++
++G_BEGIN_DECLS
++#define GST_TYPE_CV_STITCHING_PAD (gst_cv_stitching_pad_get_type())
++#define GST_CV_STITCHING_PAD(obj) \
++        (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_CV_STITCHING_PAD, GstCvStitchingPad))
++#define GST_CV_STITCHING_PAD_CLASS(klass) \
++        (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_CV_STITCHING_PAD, GstCvStitchingPadClass))
++#define GST_IS_CV_STITCHING_PAD(obj) \
++        (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_CV_STITCHING_PAD))
++#define GST_IS_CV_STITCHING_PAD_CLASS(klass) \
++        (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_CV_STITCHING_PAD))
++
++typedef struct _GstCvStitchingPad GstCvStitchingPad;
++typedef struct _GstCvStitchingPadClass GstCvStitchingPadClass;
++
++struct _GstCvStitchingPad
++{
++  GstOpencvAggregatorPad parent;
++};
++
++struct _GstCvStitchingPadClass
++{
++  GstOpencvAggregatorPadClass parent_class;
++};
++
++GType gst_cv_stitching_pad_get_type (void);
++
++#define GST_TYPE_CV_STITCHING \
++  (gst_cv_stitching_get_type())
++#define GST_CV_STITCHING(obj) \
++  (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_CV_STITCHING,GstCvStitching))
++#define GST_CV_STITCHING_CLASS(klass) \
++  (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_CV_STITCHING,GstCvStitchingClass))
++#define GST_IS_CV_STITCHING(obj) \
++  (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_CV_STITCHING))
++#define GST_IS_CV_STITCHING_CLASS(klass) \
++  (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_CV_STITCHING))
++
++typedef struct _GstCvStitching GstCvStitching;
++typedef struct _GstCvStitchingClass GstCvStitchingClass;
++
++struct _GstCvStitching
++{
++  GstOpencvAggregator parent;
++
++  Ptr<FeaturesFinder> finder;
++  Ptr<WarperCreator> warper_creator;
++  Ptr<SeamFinder> seam_finder;
++  Ptr<detail::BundleAdjusterBase> adjuster;
++  gint features_type;
++  gint warp_type;
++  gint seam_find_type;
++  gint ba_cost_func;
++};
++
++struct _GstCvStitchingClass
++{
++  GstOpencvAggregatorClass parent_class;
++};
++
++GType gst_cv_stitching_get_type (void);
++
++gboolean gst_cv_stitching_plugin_init (GstPlugin * plugin);
++
++G_END_DECLS
++#endif /* __GST_CV_STITCHING_H__ */
+diff --git a/ext/opencv/gstopencv.cpp b/ext/opencv/gstopencv.cpp
+index 4077ba6..6ae73c4 100644
+--- a/ext/opencv/gstopencv.cpp
++++ b/ext/opencv/gstopencv.cpp
+@@ -42,6 +42,7 @@
+ #include "gstsegmentation.h"
+ #include "gstgrabcut.h"
+ #include "gstdisparity.h"
++#include "gstcvstitching.h"
+ 
+ static gboolean
+ plugin_init (GstPlugin * plugin)
+@@ -103,6 +104,9 @@ plugin_init (GstPlugin * plugin)
+   if (!gst_disparity_plugin_init (plugin))
+     return FALSE;
+ 
++  if (!gst_cv_stitching_plugin_init (plugin))
++    return FALSE;
++
+   return TRUE;
+ }
+ 
+diff --git a/ext/opencv/gstopencvaggregator.c b/ext/opencv/gstopencvaggregator.c
+new file mode 100644
+index 0000000..8a813fc
+--- /dev/null
++++ b/ext/opencv/gstopencvaggregator.c
+@@ -0,0 +1,705 @@
++/*
++ * GStreamer
++ * Copyright (C) 2015 Song Bing <b06498@freescale.com>
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining a
++ * copy of this software and associated documentation files (the "Software"),
++ * to deal in the Software without restriction, including without limitation
++ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
++ * and/or sell copies of the Software, and to permit persons to whom the
++ * Software is furnished to do so, subject to the following conditions:
++ *
++ * The above copyright notice and this permission notice shall be included in
++ * all copies or substantial portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
++ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
++ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
++ * DEALINGS IN THE SOFTWARE.
++ *
++ * Alternatively, the contents of this file may be used under the
++ * GNU Lesser General Public License Version 2.1 (the "LGPL"), in
++ * which case the following provisions apply instead of the ones
++ * mentioned above:
++ *
++ * 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 <gst/gst.h>
++#include "gstopencvaggregator.h"
++#include "gstopencvutils.h"
++
++#define gst_opencv_aggregator_parent_class parent_class
++G_DEFINE_ABSTRACT_TYPE (GstOpencvAggregator, gst_opencv_aggregator,
++    GST_TYPE_VIDEO_AGGREGATOR);
++
++G_DEFINE_TYPE (GstOpencvAggregatorPad, gst_opencv_aggregator_pad,
++    GST_TYPE_VIDEO_AGGREGATOR_PAD);
++
++#define GST_CAT_DEFAULT gst_opencv_aggregator_debug
++GST_DEBUG_CATEGORY (gst_opencv_aggregator_debug);
++
++static void gst_opencv_aggregator_pad_get_property (GObject * object,
++    guint prop_id, GValue * value, GParamSpec * pspec);
++static void gst_opencv_aggregator_pad_set_property (GObject * object,
++    guint prop_id, const GValue * value, GParamSpec * pspec);
++
++enum
++{
++  PROP_PAD_0
++};
++
++#define GST_OPENCV_AGGREGATOR_GET_PRIVATE(obj)  \
++    (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GST_TYPE_OPENCV_AGGREGATOR, \
++    GstOpencvAggregatorPrivate))
++
++struct _GstOpencvAggregatorPrivate
++{
++  gboolean set_caps;
++  GstBufferPool *pool;
++  gboolean pool_active;
++  GstAllocator *allocator;
++  GstAllocationParams params;
++  GstQuery *query;
++
++  GPtrArray *imgs;
++  GPtrArray *in_infos;
++  IplImage *out_cvImage;
++};
++
++static void
++gst_opencv_aggregator_pad_class_init (GstOpencvAggregatorPadClass * klass)
++{
++  GObjectClass *gobject_class = (GObjectClass *) klass;
++
++  gobject_class->set_property = gst_opencv_aggregator_pad_set_property;
++  gobject_class->get_property = gst_opencv_aggregator_pad_get_property;
++}
++
++static void
++gst_opencv_aggregator_pad_init (GstOpencvAggregatorPad * aggregatorerpad)
++{
++}
++
++static void
++gst_opencv_aggregator_pad_get_property (GObject * object, guint prop_id,
++    GValue * value, GParamSpec * pspec)
++{
++  switch (prop_id) {
++    default:
++      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
++      break;
++  }
++}
++
++static void
++gst_opencv_aggregator_pad_set_property (GObject * object, guint prop_id,
++    const GValue * value, GParamSpec * pspec)
++{
++  switch (prop_id) {
++    default:
++      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
++      break;
++  }
++}
++
++enum
++{
++  PROP_0
++};
++
++static void gst_opencv_aggregator_set_property (GObject * object, guint prop_id,
++    const GValue * value, GParamSpec * pspec);
++static void gst_opencv_aggregator_get_property (GObject * object, guint prop_id,
++    GValue * value, GParamSpec * pspec);
++static gboolean gst_opencv_aggregator_start (GstAggregator * agg);
++static gboolean gst_opencv_aggregator_stop (GstAggregator * agg);
++static GstFlowReturn
++gst_opencv_aggregator_get_output_buffer (GstVideoAggregator * videoaggregator,
++    GstBuffer ** outbuf);
++static GstFlowReturn
++gst_opencv_aggregator_aggregate_frames (GstVideoAggregator * vagg,
++    GstBuffer * outbuffer);
++static gboolean
++gst_opencv_aggregator_sink_query (GstAggregator * agg, GstAggregatorPad * bpad,
++    GstQuery * query);
++static gboolean
++gst_opencv_aggregator_negotiated_caps (GstVideoAggregator * vagg,
++    GstCaps * caps);
++static gboolean
++gst_opencv_aggregator_decide_allocation_default (GstOpencvAggregator *
++    aggregator, GstQuery * query);
++static gboolean
++gst_opencv_aggregator_propose_allocation_default (GstOpencvAggregator *
++    aggregator, GstQuery * query);
++
++static void
++gst_opencv_aggregator_class_init (GstOpencvAggregatorClass * klass)
++{
++  GObjectClass *gobject_class;
++
++  GstVideoAggregatorClass *videoaggregator_class =
++      (GstVideoAggregatorClass *) klass;
++  GstAggregatorClass *agg_class = (GstAggregatorClass *) klass;
++
++  GST_DEBUG_CATEGORY_INIT (GST_CAT_DEFAULT, "opencvaggregator", 0,
++      "opencv aggregator");
++
++  gobject_class = (GObjectClass *) klass;
++
++  g_type_class_add_private (klass, sizeof (GstOpencvAggregatorPrivate));
++
++  gobject_class->get_property = gst_opencv_aggregator_get_property;
++  gobject_class->set_property = gst_opencv_aggregator_set_property;
++
++  agg_class->sinkpads_type = GST_TYPE_OPENCV_AGGREGATOR_PAD;
++  agg_class->sink_query = gst_opencv_aggregator_sink_query;
++  agg_class->stop = gst_opencv_aggregator_stop;
++  agg_class->start = gst_opencv_aggregator_start;
++
++  videoaggregator_class->aggregate_frames =
++      gst_opencv_aggregator_aggregate_frames;
++  videoaggregator_class->get_output_buffer =
++      gst_opencv_aggregator_get_output_buffer;
++  videoaggregator_class->negotiated_caps =
++      gst_opencv_aggregator_negotiated_caps;
++
++  klass->decide_allocation = gst_opencv_aggregator_decide_allocation_default;
++  klass->propose_allocation = gst_opencv_aggregator_propose_allocation_default;
++}
++
++static void
++gst_opencv_aggregator_reset (GstOpencvAggregator * aggregator)
++{
++  aggregator->priv->set_caps = FALSE;
++}
++
++static void
++gst_opencv_aggregator_init (GstOpencvAggregator * aggregator)
++{
++  aggregator->priv = GST_OPENCV_AGGREGATOR_GET_PRIVATE (aggregator);
++
++  gst_opencv_aggregator_reset (aggregator);
++}
++
++static void
++gst_opencv_aggregator_get_property (GObject * object,
++    guint prop_id, GValue * value, GParamSpec * pspec)
++{
++  switch (prop_id) {
++    default:
++      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
++      break;
++  }
++}
++
++static void
++gst_opencv_aggregator_set_property (GObject * object,
++    guint prop_id, const GValue * value, GParamSpec * pspec)
++{
++  switch (prop_id) {
++    default:
++      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
++      break;
++  }
++}
++
++static void
++_free_opencv_aggregator_img (IplImage * img)
++{
++  cvReleaseImage (&img);
++}
++
++static void
++_free_opencv_aggregator_in_info (GstMapInfo * info)
++{
++  g_slice_free1 (sizeof (GstMapInfo), info);
++}
++
++static gboolean
++gst_opencv_aggregator_start (GstAggregator * agg)
++{
++  GstOpencvAggregator *aggregator = GST_OPENCV_AGGREGATOR (agg);
++  GstElement *element = GST_ELEMENT (agg);
++
++  if (!GST_AGGREGATOR_CLASS (parent_class)->start (agg))
++    return FALSE;
++
++  GST_OBJECT_LOCK (aggregator);
++  aggregator->priv->imgs = g_ptr_array_new_full (element->numsinkpads,
++      (GDestroyNotify) _free_opencv_aggregator_img);
++  g_ptr_array_set_size (aggregator->priv->imgs, element->numsinkpads);
++
++  aggregator->priv->in_infos = g_ptr_array_new_full (element->numsinkpads,
++      (GDestroyNotify) _free_opencv_aggregator_in_info);
++  g_ptr_array_set_size (aggregator->priv->in_infos, element->numsinkpads);
++  GST_OBJECT_UNLOCK (aggregator);
++
++  return TRUE;
++}
++
++static gboolean
++gst_opencv_aggregator_stop (GstAggregator * agg)
++{
++  GstOpencvAggregator *aggregator = GST_OPENCV_AGGREGATOR (agg);
++
++  GST_OBJECT_LOCK (agg);
++  g_ptr_array_free (aggregator->priv->imgs, TRUE);
++  aggregator->priv->imgs = NULL;
++  g_ptr_array_free (aggregator->priv->in_infos, TRUE);
++  aggregator->priv->in_infos = NULL;
++  GST_OBJECT_UNLOCK (agg);
++
++  if (aggregator->priv->pool) {
++    gst_object_unref (aggregator->priv->pool);
++    aggregator->priv->pool = NULL;
++  }
++
++  if (aggregator->priv->out_cvImage)
++    cvReleaseImage (&aggregator->priv->out_cvImage);
++
++  gst_opencv_aggregator_reset (aggregator);
++
++  return GST_AGGREGATOR_CLASS (parent_class)->stop (agg);
++}
++
++static gboolean
++gst_opencv_aggregator_sink_query (GstAggregator * agg, GstAggregatorPad * bpad,
++    GstQuery * query)
++{
++  gboolean ret = FALSE;
++  GstOpencvAggregator *aggregator = GST_OPENCV_AGGREGATOR (agg);
++  GstOpencvAggregatorClass *klass = GST_OPENCV_AGGREGATOR_GET_CLASS (agg);
++
++  GST_TRACE ("QUERY %" GST_PTR_FORMAT, query);
++
++  switch (GST_QUERY_TYPE (query)) {
++    case GST_QUERY_ALLOCATION:{
++      if (klass->propose_allocation)
++        ret = klass->propose_allocation (aggregator, query);
++      break;
++    }
++    default:
++      ret = GST_AGGREGATOR_CLASS (parent_class)->sink_query (agg, bpad, query);
++      break;
++  }
++
++  return ret;
++}
++
++static gboolean
++gst_opencv_aggregator_decide_allocation_default (GstOpencvAggregator *
++    aggregator, GstQuery * query)
++{
++  GstCaps *outcaps = NULL;
++  GstBufferPool *pool = NULL;
++  guint size, min, max;
++  GstAllocator *allocator = NULL;
++  GstAllocationParams params;
++  GstStructure *config;
++  gboolean update_pool, update_allocator;
++  GstVideoInfo vinfo;
++
++  gst_query_parse_allocation (query, &outcaps, NULL);
++  gst_video_info_init (&vinfo);
++  if (outcaps)
++    gst_video_info_from_caps (&vinfo, outcaps);
++
++  /* we got configuration from our peer or the decide_allocation method,
++   * parse them */
++  if (gst_query_get_n_allocation_params (query) > 0) {
++    /* try the allocator */
++    gst_query_parse_nth_allocation_param (query, 0, &allocator, &params);
++    update_allocator = TRUE;
++  } else {
++    allocator = NULL;
++    gst_allocation_params_init (&params);
++    update_allocator = FALSE;
++  }
++
++  if (gst_query_get_n_allocation_pools (query) > 0) {
++    gst_query_parse_nth_allocation_pool (query, 0, &pool, &size, &min, &max);
++    size = MAX (size, vinfo.size);
++    update_pool = TRUE;
++  } else {
++    pool = NULL;
++    size = vinfo.size;
++    min = max = 0;
++
++    update_pool = FALSE;
++  }
++
++  if (pool == NULL) {
++    /* no pool, we can make our own */
++    GST_DEBUG_OBJECT (aggregator, "no pool, making new pool");
++    pool = gst_video_buffer_pool_new ();
++  }
++
++  /* now configure */
++  config = gst_buffer_pool_get_config (pool);
++  gst_buffer_pool_config_set_params (config, outcaps, size, min, max);
++  gst_buffer_pool_config_set_allocator (config, allocator, &params);
++
++  if (!gst_buffer_pool_set_config (pool, config)) {
++    config = gst_buffer_pool_get_config (pool);
++
++    /* If change are not acceptable, fallback to generic pool */
++    if (!gst_buffer_pool_config_validate_params (config, outcaps, size, min,
++            max)) {
++      GST_DEBUG_OBJECT (aggregator, "unsuported pool, making new pool");
++
++      gst_object_unref (pool);
++      pool = gst_video_buffer_pool_new ();
++      gst_buffer_pool_config_set_params (config, outcaps, size, min, max);
++      gst_buffer_pool_config_set_allocator (config, allocator, &params);
++    }
++
++    if (!gst_buffer_pool_set_config (pool, config))
++      goto config_failed;
++  }
++
++  if (update_allocator)
++    gst_query_set_nth_allocation_param (query, 0, allocator, &params);
++  else
++    gst_query_add_allocation_param (query, allocator, &params);
++  if (allocator)
++    gst_object_unref (allocator);
++
++  if (update_pool)
++    gst_query_set_nth_allocation_pool (query, 0, pool, size, min, max);
++  else
++    gst_query_add_allocation_pool (query, pool, size, min, max);
++
++  if (pool)
++    gst_object_unref (pool);
++
++  return TRUE;
++
++config_failed:
++  if (allocator)
++    gst_object_unref (allocator);
++  if (pool)
++    gst_object_unref (pool);
++  GST_ELEMENT_ERROR (aggregator, RESOURCE, SETTINGS,
++      ("Failed to configure the buffer pool"),
++      ("Configuration is most likely invalid, please report this issue."));
++  return FALSE;
++}
++
++static gboolean
++gst_opencv_aggregator_propose_allocation_default (GstOpencvAggregator *
++    aggregator, GstQuery * query)
++{
++  GstCaps *caps;
++  GstVideoInfo info;
++  GstBufferPool *pool;
++  guint size;
++
++  gst_query_parse_allocation (query, &caps, NULL);
++
++  if (caps == NULL)
++    return FALSE;
++
++  if (!gst_video_info_from_caps (&info, caps))
++    return FALSE;
++
++  size = GST_VIDEO_INFO_SIZE (&info);
++
++  if (gst_query_get_n_allocation_pools (query) == 0) {
++    GstStructure *structure;
++    GstAllocator *allocator = NULL;
++    GstAllocationParams params = { 0, 15, 0, 0 };
++
++    if (gst_query_get_n_allocation_params (query) > 0)
++      gst_query_parse_nth_allocation_param (query, 0, &allocator, &params);
++    else
++      gst_query_add_allocation_param (query, allocator, &params);
++
++    pool = gst_video_buffer_pool_new ();
++
++    structure = gst_buffer_pool_get_config (pool);
++    gst_buffer_pool_config_set_params (structure, caps, size, 0, 0);
++    gst_buffer_pool_config_set_allocator (structure, allocator, &params);
++
++    if (allocator)
++      gst_object_unref (allocator);
++
++    if (!gst_buffer_pool_set_config (pool, structure))
++      goto config_failed;
++
++    gst_query_add_allocation_pool (query, pool, size, 0, 0);
++    gst_object_unref (pool);
++    gst_query_add_allocation_meta (query, GST_VIDEO_META_API_TYPE, NULL);
++  }
++
++  return TRUE;
++
++  /* ERRORS */
++config_failed:
++  {
++    GST_ERROR_OBJECT (aggregator, "failed to set config");
++    gst_object_unref (pool);
++    return FALSE;
++  }
++}
++
++static gboolean
++gst_opencv_aggregator_negotiate_pool (GstOpencvAggregator * aggregator,
++    GstCaps * caps)
++{
++  GstAggregator *agg = GST_AGGREGATOR (aggregator);
++  GstOpencvAggregatorClass *klass;
++  GstQuery *query = NULL;
++  GstBufferPool *pool = NULL;
++  GstAllocator *allocator;
++  GstAllocationParams params;
++  gboolean ret = TRUE;
++
++  klass = GST_OPENCV_AGGREGATOR_GET_CLASS (aggregator);
++
++  query = gst_query_new_allocation (caps, TRUE);
++
++  if (!gst_pad_peer_query (agg->srcpad, query)) {
++    GST_DEBUG_OBJECT (aggregator, "didn't get downstream ALLOCATION hints");
++  }
++
++  g_assert (klass->decide_allocation != NULL);
++  ret = klass->decide_allocation (aggregator, query);
++
++  GST_DEBUG_OBJECT (aggregator, "ALLOCATION (%d) params: %" GST_PTR_FORMAT, ret,
++      query);
++
++  if (!ret)
++    goto no_decide_allocation;
++
++  /* we got configuration from our peer or the decide_allocation method,
++   * parse them */
++  if (gst_query_get_n_allocation_params (query) > 0) {
++    gst_query_parse_nth_allocation_param (query, 0, &allocator, &params);
++  } else {
++    allocator = NULL;
++    gst_allocation_params_init (&params);
++  }
++
++  if (gst_query_get_n_allocation_pools (query) > 0)
++    gst_query_parse_nth_allocation_pool (query, 0, &pool, NULL, NULL, NULL);
++  if (!pool) {
++    if (allocator)
++      gst_object_unref (allocator);
++    ret = FALSE;
++    goto no_decide_allocation;
++  }
++
++  if (aggregator->priv->allocator)
++    gst_object_unref (aggregator->priv->allocator);
++  aggregator->priv->allocator = allocator;
++  aggregator->priv->params = params;
++
++  if (aggregator->priv->pool) {
++    /* do not set the bufferpool to inactive here, it will be done
++     * on its finalize function. As videoaggregator do late renegotiation
++     * it might happen that some element downstream is already using this
++     * same bufferpool and deactivating it will make it fail.
++     * Happens when a downstream element changes from passthrough to
++     * non-passthrough and gets this same bufferpool to use */
++    gst_object_unref (aggregator->priv->pool);
++  }
++  aggregator->priv->pool = pool;
++
++  /* and activate */
++  gst_buffer_pool_set_active (pool, TRUE);
++
++done:
++  if (query)
++    gst_query_unref (query);
++
++  return ret;
++
++  /* Errors */
++no_decide_allocation:
++  {
++    GST_WARNING_OBJECT (aggregator, "Subclass failed to decide allocation");
++    goto done;
++  }
++}
++
++static gboolean
++gst_opencv_aggregator_negotiated_caps (GstVideoAggregator * vagg,
++    GstCaps * caps)
++{
++  GstOpencvAggregator *aggregator = GST_OPENCV_AGGREGATOR (vagg);
++  gint out_width, out_height;
++  gint out_depth, out_channels;
++  GError *out_err = NULL;
++
++  if (!gst_opencv_parse_iplimage_params_from_caps (caps, &out_width,
++          &out_height, &out_depth, &out_channels, &out_err)) {
++    GST_WARNING_OBJECT (aggregator, "Failed to parse output caps: %s",
++        out_err->message);
++    g_error_free (out_err);
++    return FALSE;
++  }
++
++  if (aggregator->priv->out_cvImage)
++    cvReleaseImage (&aggregator->priv->out_cvImage);
++
++  aggregator->priv->out_cvImage =
++      cvCreateImageHeader (cvSize (out_width, out_height), out_depth,
++      out_channels);
++
++  return gst_opencv_aggregator_negotiate_pool (aggregator, caps);
++}
++
++static GstFlowReturn
++gst_opencv_aggregator_get_output_buffer (GstVideoAggregator * videoaggregator,
++    GstBuffer ** outbuf)
++{
++  GstOpencvAggregator *aggregator = GST_OPENCV_AGGREGATOR (videoaggregator);
++
++  return gst_buffer_pool_acquire_buffer (aggregator->priv->pool, outbuf, NULL);
++}
++
++static GstFlowReturn
++gst_opencv_aggregator_aggregate_frames (GstVideoAggregator * vagg,
++    GstBuffer * outbuf)
++{
++  GstOpencvAggregator *aggregator = GST_OPENCV_AGGREGATOR (vagg);
++  GstOpencvAggregatorClass *aggregator_class =
++      GST_OPENCV_AGGREGATOR_GET_CLASS (vagg);
++  GstElement *element = GST_ELEMENT (aggregator);
++  GstMapInfo out_info;
++  guint array_index = 0;
++  gboolean res = FALSE;
++  GList *walk;
++  guint i;
++
++  if (!aggregator->priv->set_caps) {
++    gint in_width, in_height;
++    gint in_depth, in_channels;
++    GError *in_err = NULL;
++
++    GST_OBJECT_LOCK (aggregator);
++    walk = element->sinkpads;
++    while (walk) {
++      GstVideoAggregatorPad *vaggpad = walk->data;
++      GstCaps *caps = gst_video_info_to_caps (&vaggpad->info);
++
++      walk = g_list_next (walk);
++
++      GST_WARNING_OBJECT (aggregator, "sink pad caps:  %" GST_PTR_FORMAT, caps);
++      if (!gst_opencv_parse_iplimage_params_from_caps (caps, &in_width,
++              &in_height, &in_depth, &in_channels, &in_err)) {
++        GST_WARNING_OBJECT (aggregator, "Failed to parse input caps: %s",
++            in_err->message);
++        g_error_free (in_err);
++        gst_caps_unref (caps);
++        return FALSE;
++      }
++      gst_caps_unref (caps);
++
++      aggregator->priv->imgs->pdata[array_index] =
++          cvCreateImageHeader (cvSize (in_width, in_height), in_depth,
++          in_channels);
++      aggregator->priv->in_infos->pdata[array_index] =
++          g_slice_new0 (GstMapInfo);
++      array_index++;
++    }
++    GST_OBJECT_UNLOCK (aggregator);
++    aggregator->priv->set_caps = TRUE;
++  }
++
++  array_index = 0;
++  GST_OBJECT_LOCK (aggregator);
++  walk = GST_ELEMENT (aggregator)->sinkpads;
++  while (walk) {
++    GstVideoAggregatorPad *vaggpad = walk->data;
++    IplImage *cvImage;
++    GstMapInfo *in_info = aggregator->priv->in_infos->pdata[array_index];
++
++    walk = g_list_next (walk);
++
++    if (!gst_buffer_map (vaggpad->buffer, in_info, GST_MAP_READ))
++      goto inbuf_map_failed;
++
++    cvImage = aggregator->priv->imgs->pdata[array_index];
++    cvImage->imageData = (char *) in_info->data;
++    ++array_index;
++  }
++  GST_OBJECT_UNLOCK (aggregator);
++
++  if (!gst_buffer_map (outbuf, &out_info, GST_MAP_WRITE))
++    goto outbuf_map_failed;
++
++  aggregator->priv->out_cvImage->imageData = (char *) out_info.data;
++
++  res =
++      aggregator_class->GstOpencvAggregatorProcess (aggregator,
++      aggregator->priv->imgs, aggregator->priv->out_cvImage);
++
++  GST_OBJECT_LOCK (aggregator);
++  walk = GST_ELEMENT (aggregator)->sinkpads;
++  array_index = 0;
++  while (walk) {
++    GstVideoAggregatorPad *vaggpad = walk->data;
++    GstMapInfo *in_info = aggregator->priv->in_infos->pdata[array_index];
++    walk = g_list_next (walk);
++    gst_buffer_unmap (vaggpad->buffer, in_info);
++    ++array_index;
++  }
++  GST_OBJECT_UNLOCK (aggregator);
++
++  gst_buffer_unmap (outbuf, &out_info);
++
++  return res ? GST_FLOW_OK : GST_FLOW_ERROR;
++
++inbuf_map_failed:
++  GST_ELEMENT_ERROR (aggregator, RESOURCE, READ,
++      ("Failed to map buffer for reading"), (NULL));
++  walk = GST_ELEMENT (aggregator)->sinkpads;
++  for (i = 0; i < array_index; i++) {
++    GstVideoAggregatorPad *vaggpad = walk->data;
++    GstMapInfo *in_info = aggregator->priv->in_infos->pdata[array_index];
++    walk = g_list_next (walk);
++    gst_buffer_unmap (vaggpad->buffer, in_info);
++    ++array_index;
++  }
++  GST_OBJECT_UNLOCK (aggregator);
++  return GST_FLOW_ERROR;
++
++outbuf_map_failed:
++  GST_ELEMENT_ERROR (aggregator, RESOURCE, WRITE,
++      ("Failed to map buffer for writing"), (NULL));
++  GST_OBJECT_LOCK (aggregator);
++  walk = GST_ELEMENT (aggregator)->sinkpads;
++  array_index = 0;
++  while (walk) {
++    GstVideoAggregatorPad *vaggpad = walk->data;
++    GstMapInfo *in_info = aggregator->priv->in_infos->pdata[array_index];
++    walk = g_list_next (walk);
++    gst_buffer_unmap (vaggpad->buffer, in_info);
++    ++array_index;
++  }
++  GST_OBJECT_UNLOCK (aggregator);
++
++  return GST_FLOW_ERROR;
++}
+diff --git a/ext/opencv/gstopencvaggregator.h b/ext/opencv/gstopencvaggregator.h
+new file mode 100644
+index 0000000..1fc65a5
+--- /dev/null
++++ b/ext/opencv/gstopencvaggregator.h
+@@ -0,0 +1,118 @@
++/*
++ * GStreamer
++ * Copyright (C) 2015 Song Bing <b06498@freescale.com>
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining a
++ * copy of this software and associated documentation files (the "Software"),
++ * to deal in the Software without restriction, including without limitation
++ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
++ * and/or sell copies of the Software, and to permit persons to whom the
++ * Software is furnished to do so, subject to the following conditions:
++ *
++ * The above copyright notice and this permission notice shall be included in
++ * all copies or substantial portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
++ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
++ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
++ * DEALINGS IN THE SOFTWARE.
++ *
++ * Alternatively, the contents of this file may be used under the
++ * GNU Lesser General Public License Version 2.1 (the "LGPL"), in
++ * which case the following provisions apply instead of the ones
++ * mentioned above:
++ *
++ * 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_OPENCV_AGGREGATOR_H__
++#define __GST_OPENCV_AGGREGATOR_H__
++
++#include <gst/gst.h>
++#include <gst/video/gstvideoaggregator.h>
++#include <opencv2/core/core_c.h>
++
++G_BEGIN_DECLS
++#define GST_TYPE_OPENCV_AGGREGATOR_PAD (gst_opencv_aggregator_pad_get_type())
++#define GST_OPENCV_AGGREGATOR_PAD(obj) \
++        (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_OPENCV_AGGREGATOR_PAD, GstOpencvAggregatorPad))
++#define GST_OPENCV_AGGREGATOR_PAD_CLASS(klass) \
++        (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_OPENCV_AGGREGATOR_PAD, GstOpencvAggregatorPadClass))
++#define GST_IS_OPENCV_AGGREGATOR_PAD(obj) \
++        (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_OPENCV_AGGREGATOR_PAD))
++#define GST_IS_OPENCV_AGGREGATOR_PAD_CLASS(klass) \
++        (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_OPENCV_AGGREGATOR_PAD))
++#define GST_OPENCV_AGGREGATOR_PAD_GET_CLASS(obj) \
++        (G_TYPE_INSTANCE_GET_CLASS((obj),GST_TYPE_OPENCV_AGGREGATOR_PAD,GstOpencvAggregatorPadClass))
++typedef struct _GstOpencvAggregatorPad GstOpencvAggregatorPad;
++typedef struct _GstOpencvAggregatorPadClass GstOpencvAggregatorPadClass;
++
++struct _GstOpencvAggregatorPad
++{
++  GstVideoAggregatorPad parent;
++};
++
++struct _GstOpencvAggregatorPadClass
++{
++  GstVideoAggregatorPadClass parent_class;
++};
++
++GType gst_opencv_aggregator_pad_get_type (void);
++
++#define GST_TYPE_OPENCV_AGGREGATOR \
++  (gst_opencv_aggregator_get_type())
++#define GST_OPENCV_AGGREGATOR(obj) \
++  (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_OPENCV_AGGREGATOR,GstOpencvAggregator))
++#define GST_OPENCV_AGGREGATOR_CLASS(klass) \
++  (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_OPENCV_AGGREGATOR,GstOpencvAggregatorClass))
++#define GST_IS_OPENCV_AGGREGATOR(obj) \
++  (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_OPENCV_AGGREGATOR))
++#define GST_IS_OPENCV_AGGREGATOR_CLASS(klass) \
++  (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_OPENCV_AGGREGATOR))
++#define GST_OPENCV_AGGREGATOR_GET_CLASS(obj)  \
++    (G_TYPE_INSTANCE_GET_CLASS((obj),GST_TYPE_OPENCV_AGGREGATOR,GstOpencvAggregatorClass))
++#define GST_OPENCV_AGGREGATOR_CAST(obj) ((GstOpencvAggregator *) (obj))
++
++typedef struct _GstOpencvAggregator GstOpencvAggregator;
++typedef struct _GstOpencvAggregatorClass GstOpencvAggregatorClass;
++typedef struct _GstOpencvAggregatorPrivate GstOpencvAggregatorPrivate;
++
++struct _GstOpencvAggregator
++{
++  GstVideoAggregator parent;
++
++  GstOpencvAggregatorPrivate *priv;
++};
++
++struct _GstOpencvAggregatorClass
++{
++  GstVideoAggregatorClass parent_class;
++
++    gboolean (*GstOpencvAggregatorProcess) (GstOpencvAggregator * aggregrator,
++      GPtrArray * imgs, IplImage * outimg);
++    gboolean (*decide_allocation) (GstOpencvAggregator * aggretator,
++      GstQuery * query);
++    gboolean (*propose_allocation) (GstOpencvAggregator * aggretator,
++      GstQuery * query);
++};
++
++GType gst_opencv_aggregator_get_type (void);
++
++G_END_DECLS
++#endif /* __GST_OPENCV_AGGREGATOR_H__ */
+-- 
+1.9.1
+
diff --git a/meta/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad_1.6.2.bb b/meta/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad_1.6.2.bb
index c434a08..a75d1e9 100644
--- a/meta/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad_1.6.2.bb
+++ b/meta/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad_1.6.2.bb
@@ -10,6 +10,7 @@ SRC_URI += "file://0001-glimagesink-Downrank-to-marginal.patch \
             file://0003-mpeg4videoparse-Need-detect-picture-coding-type-when.patch \
             file://0004-mpegvideoparse-Need-detect-picture-coding-type-when-.patch \
             file://0005-glfilter-Lost-frame-rate-info-when-fixate-caps.patch \
+            file://0006-opencv-Add-video-stitching-support-based-on-Open-CV.patch \
 "
 
 SRC_URI[md5sum] = "7c73bec1d389f0e184ebbbbb9e9f883d"
-- 
1.9.1



^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [poky][PATCH 12/13] gstreamer1.0-plugins-bad: Fix memory leak of navigation thread in glwindow
  2016-01-18  9:32 [poky][PATCH 00/13] Add patches for gstreamer 1.6 Yuqing Zhu
                   ` (10 preceding siblings ...)
  2016-01-18  9:33 ` [poky][PATCH 11/13] gstreamer1.0-plugins-bad: Add video stitching support based on Open CV Yuqing Zhu
@ 2016-01-18  9:33 ` Yuqing Zhu
  2016-01-18 15:05   ` Burton, Ross
  2016-01-18  9:33 ` [poky][PATCH 13/13] gstreamer1.0-plugins-bad: Fix loop test hang in glimagesink Yuqing Zhu
  2016-01-18 17:16 ` [poky][PATCH 00/13] Add patches for gstreamer 1.6 alexander.kanavin
  13 siblings, 1 reply; 19+ messages in thread
From: Yuqing Zhu @ 2016-01-18  9:33 UTC (permalink / raw)
  To: openembedded-core

When exit navigation thread, call g_thread_join() to release
the resource which is hold by it.

Signed-off-by: Yuqing Zhu <b54851@freescale.com>
---
 ...window-fix-memory-leak-of-navigation-thre.patch | 35 ++++++++++++++++++++++
 .../gstreamer/gstreamer1.0-plugins-bad_1.6.2.bb    |  1 +
 2 files changed, 36 insertions(+)
 create mode 100755 meta/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad/0007-glplugin-glwindow-fix-memory-leak-of-navigation-thre.patch

diff --git a/meta/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad/0007-glplugin-glwindow-fix-memory-leak-of-navigation-thre.patch b/meta/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad/0007-glplugin-glwindow-fix-memory-leak-of-navigation-thre.patch
new file mode 100755
index 0000000..60866bf
--- /dev/null
+++ b/meta/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad/0007-glplugin-glwindow-fix-memory-leak-of-navigation-thre.patch
@@ -0,0 +1,35 @@
+From 95cda7fbcf1a81289d9315c801c8e2b3d896f4cb Mon Sep 17 00:00:00 2001
+From: Haihua Hu <b55597@freescale.com>
+Date: Mon, 30 Nov 2015 09:36:09 +0800
+Subject: [PATCH 2/5] [glplugin] glwindow: fix memory leak of navigation
+ thread
+
+When exit navigation thread, call g_thread_join() to release
+the resource hold by it.
+
+Upstream-Status: Pending
+
+bugzilla URL: https://bugzilla.gnome.org/show_bug.cgi?id=758820
+
+Signed-off-by: Haihua Hu <b55597@freescale.com>
+---
+ gst-libs/gst/gl/gstglwindow.c |    3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/gst-libs/gst/gl/gstglwindow.c b/gst-libs/gst/gl/gstglwindow.c
+index 44b74ca..42ef296 100644
+--- a/gst-libs/gst/gl/gstglwindow.c
++++ b/gst-libs/gst/gl/gstglwindow.c
+@@ -343,6 +343,9 @@ gst_gl_window_finalize (GObject * object)
+     while (window->nav_alive) {
+       g_cond_wait (&window->nav_destroy_cond, &window->nav_lock);
+     }
++    /* release resource hold by navigation thread */
++    g_thread_join(window->priv->navigation_thread);
++    window->priv->navigation_thread = NULL;
+     g_mutex_unlock (&window->nav_lock);
+   }
+ 
+-- 
+1.7.9.5
+
diff --git a/meta/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad_1.6.2.bb b/meta/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad_1.6.2.bb
index a75d1e9..280ec26 100644
--- a/meta/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad_1.6.2.bb
+++ b/meta/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad_1.6.2.bb
@@ -11,6 +11,7 @@ SRC_URI += "file://0001-glimagesink-Downrank-to-marginal.patch \
             file://0004-mpegvideoparse-Need-detect-picture-coding-type-when-.patch \
             file://0005-glfilter-Lost-frame-rate-info-when-fixate-caps.patch \
             file://0006-opencv-Add-video-stitching-support-based-on-Open-CV.patch \
+            file://0007-glplugin-glwindow-fix-memory-leak-of-navigation-thre.patch \
 "
 
 SRC_URI[md5sum] = "7c73bec1d389f0e184ebbbbb9e9f883d"
-- 
1.9.1



^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [poky][PATCH 13/13] gstreamer1.0-plugins-bad: Fix loop test hang in glimagesink
  2016-01-18  9:32 [poky][PATCH 00/13] Add patches for gstreamer 1.6 Yuqing Zhu
                   ` (11 preceding siblings ...)
  2016-01-18  9:33 ` [poky][PATCH 12/13] gstreamer1.0-plugins-bad: Fix memory leak of navigation thread in glwindow Yuqing Zhu
@ 2016-01-18  9:33 ` Yuqing Zhu
  2016-01-18 15:08   ` Burton, Ross
  2016-01-18 17:16 ` [poky][PATCH 00/13] Add patches for gstreamer 1.6 alexander.kanavin
  13 siblings, 1 reply; 19+ messages in thread
From: Yuqing Zhu @ 2016-01-18  9:33 UTC (permalink / raw)
  To: openembedded-core

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.

Signed-off-by: Yuqing Zhu <b54851@freescale.com>
---
 ...-wayland-fix-loop-test-hang-in-glimagesin.patch | 142 +++++++++++++++++++++
 .../gstreamer/gstreamer1.0-plugins-bad_1.6.2.bb    |   1 +
 2 files changed, 143 insertions(+)
 create mode 100755 meta/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad/0008-glplugin-gl-wayland-fix-loop-test-hang-in-glimagesin.patch

diff --git a/meta/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad/0008-glplugin-gl-wayland-fix-loop-test-hang-in-glimagesin.patch b/meta/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad/0008-glplugin-gl-wayland-fix-loop-test-hang-in-glimagesin.patch
new file mode 100755
index 0000000..59f47de
--- /dev/null
+++ b/meta/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad/0008-glplugin-gl-wayland-fix-loop-test-hang-in-glimagesin.patch
@@ -0,0 +1,142 @@
+From 196799920b36b47e2f99fa55732abda6574e247c Mon Sep 17 00:00:00 2001
+From: Haihua Hu <b55597@freescale.com>
+Date: Sun, 6 Dec 2015 14:25:44 +0800
+Subject: [PATCH 3/5] [glplugin] gl/wayland: fix loop test hang in glimagesink
+
+Root cause: In glimagesink, gl thread will dispatch event queue and window_show()
+is called from streaming thread. Gl thread will empty event queue and
+potentially cause gst_gl_wl_display_roundtrip_queue() blocking the
+streaming thread to wait for an event occur. Actually, no event can occur
+becaue the swap_buffer event is queued by streaming thread but it is blocked.
+
+Solution: Use two event queue, One for surface and another for gl thread
+
+Upstream-Status: Pending
+
+bugzilla URL: https://bugzilla.gnome.org/show_bug.cgi?id=758984
+
+Signed-off-by: Haihua Hu <b55597@freescale.com>
+---
+ gst-libs/gst/gl/wayland/gstglwindow_wayland_egl.c |   33 ++++++++++++++-------
+ gst-libs/gst/gl/wayland/gstglwindow_wayland_egl.h |    2 +-
+ 2 files changed, 23 insertions(+), 12 deletions(-)
+
+diff --git a/gst-libs/gst/gl/wayland/gstglwindow_wayland_egl.c b/gst-libs/gst/gl/wayland/gstglwindow_wayland_egl.c
+index b557daa..8ec9e7a 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);
+   }
+ }
+ 
+@@ -374,6 +380,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;
+@@ -402,10 +413,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;
+@@ -454,7 +465,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 f76b5b0..2e9bfad 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.7.9.5
+
diff --git a/meta/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad_1.6.2.bb b/meta/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad_1.6.2.bb
index 280ec26..33cf1e5 100644
--- a/meta/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad_1.6.2.bb
+++ b/meta/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad_1.6.2.bb
@@ -12,6 +12,7 @@ SRC_URI += "file://0001-glimagesink-Downrank-to-marginal.patch \
             file://0005-glfilter-Lost-frame-rate-info-when-fixate-caps.patch \
             file://0006-opencv-Add-video-stitching-support-based-on-Open-CV.patch \
             file://0007-glplugin-glwindow-fix-memory-leak-of-navigation-thre.patch \
+            file://0008-glplugin-gl-wayland-fix-loop-test-hang-in-glimagesin.patch \
 "
 
 SRC_URI[md5sum] = "7c73bec1d389f0e184ebbbbb9e9f883d"
-- 
1.9.1



^ permalink raw reply related	[flat|nested] 19+ messages in thread

* Re: [poky][PATCH 10/13] gstreamer1.0-plugins-bad: Fix frame rate info lost when fixate caps
  2016-01-18  9:32 ` [poky][PATCH 10/13] gstreamer1.0-plugins-bad: Fix frame rate info lost when fixate caps Yuqing Zhu
@ 2016-01-18 15:04   ` Burton, Ross
  0 siblings, 0 replies; 19+ messages in thread
From: Burton, Ross @ 2016-01-18 15:04 UTC (permalink / raw)
  To: Yuqing Zhu; +Cc: OE-core

[-- Attachment #1: Type: text/plain, Size: 294 bytes --]

On 18 January 2016 at 09:32, Yuqing Zhu <b54851@freescale.com> wrote:

> Frame rate info will be lost when fixate caps. It will
> cause down stream element fail, such as avimux.
>

The upstream bug here rejects the patch, do you plan on improving it as per
Sebastian's comment?

Ross

[-- Attachment #2: Type: text/html, Size: 706 bytes --]

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [poky][PATCH 12/13] gstreamer1.0-plugins-bad: Fix memory leak of navigation thread in glwindow
  2016-01-18  9:33 ` [poky][PATCH 12/13] gstreamer1.0-plugins-bad: Fix memory leak of navigation thread in glwindow Yuqing Zhu
@ 2016-01-18 15:05   ` Burton, Ross
  0 siblings, 0 replies; 19+ messages in thread
From: Burton, Ross @ 2016-01-18 15:05 UTC (permalink / raw)
  To: Yuqing Zhu; +Cc: OE-core

[-- Attachment #1: Type: text/plain, Size: 389 bytes --]

On 18 January 2016 at 09:33, Yuqing Zhu <b54851@freescale.com> wrote:

> +Upstream-Status: Pending
> +
> +bugzilla URL: https://bugzilla.gnome.org/show_bug.cgi?id=758820
>

Shouldn't this be a backport of the commits that were actually merged, and
then Upstream-Status: Backport?  I don't want the next person who updates
this recipe to have to figure out any conflicts.

Ross

[-- Attachment #2: Type: text/html, Size: 900 bytes --]

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [poky][PATCH 13/13] gstreamer1.0-plugins-bad: Fix loop test hang in glimagesink
  2016-01-18  9:33 ` [poky][PATCH 13/13] gstreamer1.0-plugins-bad: Fix loop test hang in glimagesink Yuqing Zhu
@ 2016-01-18 15:08   ` Burton, Ross
  0 siblings, 0 replies; 19+ messages in thread
From: Burton, Ross @ 2016-01-18 15:08 UTC (permalink / raw)
  To: Yuqing Zhu; +Cc: OE-core

[-- Attachment #1: Type: text/plain, Size: 337 bytes --]

On 18 January 2016 at 09:33, Yuqing Zhu <b54851@freescale.com> wrote:

> +Upstream-Status: Pending
> +
> +bugzilla URL: https://bugzilla.gnome.org/show_bug.cgi?id=758984
>

So this would be Upstream-Status: Submitted.

Most of the patches are actually submitted upstream but in Pending state,
can you fix them please.

Ross

[-- Attachment #2: Type: text/html, Size: 880 bytes --]

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [poky][PATCH 11/13] gstreamer1.0-plugins-bad: Add video stitching support based on Open CV
  2016-01-18  9:33 ` [poky][PATCH 11/13] gstreamer1.0-plugins-bad: Add video stitching support based on Open CV Yuqing Zhu
@ 2016-01-18 15:10   ` Burton, Ross
  0 siblings, 0 replies; 19+ messages in thread
From: Burton, Ross @ 2016-01-18 15:10 UTC (permalink / raw)
  To: Yuqing Zhu; +Cc: OE-core

[-- Attachment #1: Type: text/plain, Size: 305 bytes --]

On 18 January 2016 at 09:33, Yuqing Zhu <b54851@freescale.com> wrote:

> +Add video stitching element based on Open CV.
>

I'm not entirely convinced that we should be carrying patches to add
entirely new elements to GStreamer.  Why can't this be in your layer until
it's merged upstream?

Ross

[-- Attachment #2: Type: text/html, Size: 723 bytes --]

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [poky][PATCH 00/13] Add patches for gstreamer 1.6
  2016-01-18  9:32 [poky][PATCH 00/13] Add patches for gstreamer 1.6 Yuqing Zhu
                   ` (12 preceding siblings ...)
  2016-01-18  9:33 ` [poky][PATCH 13/13] gstreamer1.0-plugins-bad: Fix loop test hang in glimagesink Yuqing Zhu
@ 2016-01-18 17:16 ` alexander.kanavin
  13 siblings, 0 replies; 19+ messages in thread
From: alexander.kanavin @ 2016-01-18 17:16 UTC (permalink / raw)
  To: Yuqing Zhu; +Cc: openembedded-core

> ---gstreamer1.0
>    Correct the setting for FLAG_DISCONT when push to adapter.
>
> ---gstreamer1.0-plugins-base
>    Fix taglist not being sent to down stream issue.
>    Fix audio/video decoder error.
>    Make gstaudiobasesink print warning instead of returning ERROR.
>    Disable orc optimization for lib video.
>    Add video crop supporting when convert frame.
>
> ---gstreamer1.0-plugins-bad
>    Fix mpegtsmux get wrong pid.
>    Add code type checking in mpeg4videoparse when draining.
>    Detect picture coding type when draining.
>    Fix frame rate info lost when fixating caps.
>    Add video stitching support based on Open CV.
>    Fix memory leak of navigation thread in glwindow.
>    Fix loop test hang in glimagesink.

Please explain what is the benefit of having these patches in oe-core
right now, instead of just getting the fixes automatically from future
upstream releases. Why are you submitting these patches in particular, are
they something that a lot of people will benefit from?

These patches add significantly to the maintenance burden of oe-core
recipes, and if they're difficult to forward port, they will simply be
dropped from the recipes when new versions of gstreamer are out.

Generally, we prefer to take patches that:
a) fix build issues, particularly those exposed by cross-compilation or
less common architectures.
b) fix issues that are embedded-specific.


Alex


^ permalink raw reply	[flat|nested] 19+ messages in thread

end of thread, other threads:[~2016-01-18 16:28 UTC | newest]

Thread overview: 19+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2016-01-18  9:32 [poky][PATCH 00/13] Add patches for gstreamer 1.6 Yuqing Zhu
2016-01-18  9:32 ` [poky][PATCH 01/13] gstreamer1.0: [baseparse] unset FLAG_DISCONT when push to adapter Yuqing Zhu
2016-01-18  9:32 ` [poky][PATCH 02/13] gstreamer1.0-plugins-base: Fix taglist not being sent to down stream if all the frame corrupted Yuqing Zhu
2016-01-18  9:32 ` [poky][PATCH 03/13] gstreamer1.0-plugins-base: Fix audio/video decoder error Yuqing Zhu
2016-01-18  9:32 ` [poky][PATCH 04/13] gstreamer1.0-plugins-base: Make gstaudiobasesink print warning instead of returning ERROR Yuqing Zhu
2016-01-18  9:32 ` [poky][PATCH 05/13] gstreamer1.0-plugins-base: Disable orc optimization for lib video Yuqing Zhu
2016-01-18  9:32 ` [poky][PATCH 06/13] gstreamer1.0-plugins-base: Add video crop supporting when convert frame Yuqing Zhu
2016-01-18  9:32 ` [poky][PATCH 07/13] gstreamer1.0-plugins-bad: Fix mpegtsmux get wrong pid Yuqing Zhu
2016-01-18  9:32 ` [poky][PATCH 08/13] gstreamer1.0-plugins-bad: Add check coding type when drain in mpeg4videoparse Yuqing Zhu
2016-01-18  9:32 ` [poky][PATCH 09/13] gstreamer1.0-plugins-bad: Detect picture coding type when drain Yuqing Zhu
2016-01-18  9:32 ` [poky][PATCH 10/13] gstreamer1.0-plugins-bad: Fix frame rate info lost when fixate caps Yuqing Zhu
2016-01-18 15:04   ` Burton, Ross
2016-01-18  9:33 ` [poky][PATCH 11/13] gstreamer1.0-plugins-bad: Add video stitching support based on Open CV Yuqing Zhu
2016-01-18 15:10   ` Burton, Ross
2016-01-18  9:33 ` [poky][PATCH 12/13] gstreamer1.0-plugins-bad: Fix memory leak of navigation thread in glwindow Yuqing Zhu
2016-01-18 15:05   ` Burton, Ross
2016-01-18  9:33 ` [poky][PATCH 13/13] gstreamer1.0-plugins-bad: Fix loop test hang in glimagesink Yuqing Zhu
2016-01-18 15:08   ` Burton, Ross
2016-01-18 17:16 ` [poky][PATCH 00/13] Add patches for gstreamer 1.6 alexander.kanavin

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox