diff --git a/sys/v4l2/gstv4l2bufferpool.c b/sys/v4l2/gstv4l2bufferpool.c
index 498ed83..5104a50 100644
--- a/sys/v4l2/gstv4l2bufferpool.c
+++ b/sys/v4l2/gstv4l2bufferpool.c
@@ -1671,10 +1671,11 @@ gst_v4l2_buffer_pool_process (GstV4l2BufferPool * pool, GstBuffer ** buf)
           if ((ret = gst_v4l2_buffer_pool_dqbuf (pool, &tmp)) != GST_FLOW_OK)
             goto done;
 
-          /* An empty buffer on capture indicates the end of stream */
+          /* An empty buffer on capture indicates need check event */
           if (gst_buffer_get_size (tmp) == 0) {
             gst_v4l2_buffer_pool_release_buffer (bpool, tmp);
 
             if (GST_BUFFER_FLAG_IS_SET (*buf, GST_BUFFER_FLAG_CORRUPTED))
               goto buffer_corrupted;
             else
diff --git a/sys/v4l2/gstv4l2bufferpool.h b/sys/v4l2/gstv4l2bufferpool.h
index 76013ce..5cada83 100644
--- a/sys/v4l2/gstv4l2bufferpool.h
+++ b/sys/v4l2/gstv4l2bufferpool.h
@@ -45,8 +45,8 @@ G_BEGIN_DECLS
 #define GST_V4L2_BUFFER_POOL_CAST(obj) ((GstV4l2BufferPool*)(obj))
 
 /* This flow return is used to indicated that the last buffer of a
- * drain or a resoltuion change has been found. This should normally
- * only occure for mem-2-mem devices. */
+ * drain has been found. This should normally only occure for 
+ * mem-2-mem devices. */
 #define GST_V4L2_FLOW_LAST_BUFFER GST_FLOW_CUSTOM_SUCCESS
 
 /* This flow return is used to indicated that the returned buffer was marked
@@ -54,6 +54,11 @@ G_BEGIN_DECLS
  * simply waiting for next buffer. */
 #define GST_V4L2_FLOW_CORRUPTED_BUFFER GST_FLOW_CUSTOM_SUCCESS_1
 
+/* This flow return is used to indicated that the last buffer of a 
+ * resoltuion change has been found. This should normally only 
+ * occure for mem-2-mem devices. */
+#define GST_V4L2_FLOW_SOURCE_CHANGE GST_FLOW_CUSTOM_SUCCESS_2
+
 struct _GstV4l2BufferPool
 {
   GstBufferPool parent;
diff --git a/sys/v4l2/gstv4l2object.c b/sys/v4l2/gstv4l2object.c
index aa4071d..9631d6e 100644
--- a/sys/v4l2/gstv4l2object.c
+++ b/sys/v4l2/gstv4l2object.c
@@ -446,6 +446,10 @@ gst_v4l2_object_new (GstElement * element,
 
   v4l2object->no_initial_format = FALSE;
 
+  v4l2object->poll = gst_poll_new (TRUE);
+  v4l2object->can_wait_event = FALSE;
+  v4l2object->can_poll_device = TRUE;
+
   return v4l2object;
 }
 
@@ -793,6 +797,14 @@ gst_v4l2_object_open_shared (GstV4l2Object * v4l2object, GstV4l2Object * other)
 
   ret = gst_v4l2_dup (v4l2object, other);
 
+  if (ret && !V4L2_TYPE_IS_OUTPUT (v4l2object->type)) {
+    gst_poll_fd_init (&v4l2object->pollfd);
+    v4l2object->pollfd.fd = v4l2object->video_fd;
+    gst_poll_add_fd (v4l2object->poll, &v4l2object->pollfd);
+    /* used for dequeue event */
+    gst_poll_fd_ctl_read (v4l2object->poll, &v4l2object->pollfd, TRUE);
+  }
+
   return ret;
 }
 
@@ -2898,6 +2910,100 @@ pool_failed:
   }
 }
 
+GstFlowReturn
+gst_v4l2_object_poll (GstV4l2Object * v4l2object)
+{
+  gint ret;
+
+  if (!v4l2object->can_poll_device)
+    goto done;
+
+  GST_LOG_OBJECT (v4l2object, "polling device");
+
+again:
+  ret = gst_poll_wait (v4l2object->poll, GST_CLOCK_TIME_NONE);
+  if (G_UNLIKELY (ret < 0)) {
+    switch (errno) {
+      case EBUSY:
+        goto stopped;
+      case EAGAIN:
+      case EINTR:
+        goto again;
+      case ENXIO:
+        GST_WARNING_OBJECT (v4l2object,
+            "v4l2 device doesn't support polling. Disabling"
+            " using libv4l2 in this case may cause deadlocks");
+        v4l2object->can_poll_device = FALSE;
+        goto done;
+      default:
+        goto select_error;
+    }
+  }
+
+  if (gst_poll_fd_has_error (v4l2object->poll, &v4l2object->pollfd))
+    goto select_error;
+
+done:
+  return GST_FLOW_OK;
+
+  /* ERRORS */
+stopped:
+  {
+    GST_DEBUG_OBJECT (v4l2object, "stop called");
+    return GST_FLOW_FLUSHING;
+  }
+select_error:
+  {
+    GST_ELEMENT_ERROR (v4l2object->element, RESOURCE, READ, (NULL),
+        ("poll error %d: %s (%d)", ret, g_strerror (errno), errno));
+    return GST_FLOW_ERROR;
+  }
+}
+
+GstFlowReturn
+gst_v4l2_object_dqevent (GstV4l2Object * v4l2object)
+{
+  GstFlowReturn res;
+  struct v4l2_event evt;
+
+  if ((res = gst_v4l2_object_poll (v4l2object)) != GST_FLOW_OK)
+    goto poll_failed;
+
+  memset (&evt, 0x00, sizeof (struct v4l2_event));
+  evt.type = v4l2object->type;
+  if (v4l2_ioctl (v4l2object->video_fd, VIDIOC_DQEVENT, &evt) < 0)
+    goto dqevent_failed;
+
+  switch (evt.type)
+  {
+    case V4L2_EVENT_SOURCE_CHANGE:
+      return GST_V4L2_FLOW_SOURCE_CHANGE;
+      break;
+    case V4L2_EVENT_EOS:
+      return GST_V4L2_FLOW_LAST_BUFFER;
+      break;
+    default:
+      break;
+  }
+
+  return GST_FLOW_OK;
+
+  /* ERRORS */
+poll_failed:
+  {
+    GST_DEBUG_OBJECT (v4l2object, "poll error %s", gst_flow_get_name (res));
+    return res;
+  }
+dqevent_failed:
+  {
+    return GST_FLOW_ERROR;
+  }
+}
+
 /**
  * gst_v4l2_object_acquire_format:
  * @v4l2object the object
@@ -3068,6 +3174,8 @@ gst_v4l2_object_unlock (GstV4l2Object * v4l2object)
 
   GST_LOG_OBJECT (v4l2object->element, "start flushing");
 
+  gst_poll_set_flushing (v4l2object->poll, TRUE);
+
   if (v4l2object->pool && gst_buffer_pool_is_active (v4l2object->pool))
     gst_buffer_pool_set_flushing (v4l2object->pool, TRUE);
 
@@ -3084,6 +3192,8 @@ gst_v4l2_object_unlock_stop (GstV4l2Object * v4l2object)
   if (v4l2object->pool && gst_buffer_pool_is_active (v4l2object->pool))
     gst_buffer_pool_set_flushing (v4l2object->pool, FALSE);
 
+  gst_poll_set_flushing (v4l2object->poll, FALSE);
+
   return ret;
 }
 
@@ -3104,6 +3214,8 @@ gst_v4l2_object_stop (GstV4l2Object * v4l2object)
     v4l2object->pool = NULL;
   }
 
+  gst_poll_free (v4l2object->poll);
+
   GST_V4L2_SET_INACTIVE (v4l2object);
 
 done:
diff --git a/sys/v4l2/gstv4l2object.h b/sys/v4l2/gstv4l2object.h
index c13cd64..263b245 100644
--- a/sys/v4l2/gstv4l2object.h
+++ b/sys/v4l2/gstv4l2object.h
@@ -88,6 +88,9 @@ struct _GstV4l2Object {
   /* the video-device's file descriptor */
   gint video_fd;
   GstV4l2IOMode mode;
+  GstPoll *poll;             /* a poll for video_fd */
+  GstPollFD pollfd;
+  gboolean can_poll_device;
 
   gboolean active;
   gboolean streaming;
@@ -168,6 +171,8 @@ struct _GstV4l2Object {
   /* Allow to skip reading initial format through G_FMT. Some devices
    * just fails if you don't call S_FMT first. (ex: M2M decoders) */
   gboolean no_initial_format;
+  gboolean can_wait_event;
+  gboolean need_wait_event;
 };
 
 struct _GstV4l2ObjectClassHelper {
@@ -256,6 +261,8 @@ gboolean      gst_v4l2_object_stop        (GstV4l2Object * v4l2object);
 GstCaps *     gst_v4l2_object_get_caps    (GstV4l2Object * v4l2object,
                                            GstCaps * filter);
 
+GstFlowReturn gst_v4l2_object_dqevent     (GstV4l2Object * v4l2object);
+
 gboolean      gst_v4l2_object_acquire_format (GstV4l2Object * v4l2object,
                                               GstVideoInfo * info);
 
diff --git a/sys/v4l2/gstv4l2videodec.c b/sys/v4l2/gstv4l2videodec.c
index c81f0aa..bddde09 100644
--- a/sys/v4l2/gstv4l2videodec.c
+++ b/sys/v4l2/gstv4l2videodec.c
@@ -358,14 +360,60 @@ static void
 gst_v4l2_video_dec_loop (GstVideoDecoder * decoder)
 {
   GstV4l2VideoDec *self = GST_V4L2_VIDEO_DEC (decoder);
-  GstV4l2BufferPool *v4l2_pool = GST_V4L2_BUFFER_POOL (self->v4l2capture->pool);
+  GstV4l2BufferPool *v4l2_pool;
   GstBufferPool *pool;
   GstVideoCodecFrame *frame;
   GstBuffer *buffer = NULL;
   GstFlowReturn ret;
 
+  if (G_UNLIKELY (!GST_V4L2_IS_ACTIVE (self->v4l2capture))) {
+    GstVideoInfo info;
+    GstVideoCodecState *output_state;
+
+    /* Wait until received SOURCE_CHANGE event to get right video format */
+    while (self->v4l2capture->can_wait_event
+        && self->v4l2capture->need_wait_event) {
+      ret = gst_v4l2_object_dqevent (self->v4l2capture);
+      if (ret == GST_V4L2_FLOW_SOURCE_CHANGE) {
+        GST_DEBUG_OBJECT (self, "Received source change event");
+        break;
+      } else if (ret == GST_V4L2_FLOW_LAST_BUFFER) {
+        GST_DEBUG_OBJECT (self, "Received eos event");
+        goto beach;
+      } else if (ret != GST_FLOW_OK) {
+        GST_ERROR_OBJECT (self, "dqevent error");
+        goto beach;
+      }
+    }
+    self->v4l2capture->need_wait_event = FALSE;
+
+    if (!gst_v4l2_object_acquire_format (self->v4l2capture, &info))
+      goto not_negotiated;
+
+    output_state = gst_video_decoder_set_output_state (decoder,
+        info.finfo->format, info.width, info.height, self->input_state);
+
+    /* Copy the rest of the information, there might be more in the future */
+    output_state->info.interlace_mode = info.interlace_mode;
+    gst_video_codec_state_unref (output_state);
+
+    if (!gst_video_decoder_negotiate (decoder)) {
+      if (GST_PAD_IS_FLUSHING (decoder->srcpad))
+        goto flushing;
+      else
+        goto not_negotiated;
+    }
+
+    /* Ensure our internal pool is activated */
+    if (!gst_buffer_pool_set_active (GST_BUFFER_POOL (self->v4l2capture->pool),
+            TRUE))
+      goto activate_failed;
+  }
+
   GST_LOG_OBJECT (decoder, "Allocate output buffer");
 
+  v4l2_pool = GST_V4L2_BUFFER_POOL (self->v4l2capture->pool);
+
   do {
     /* We cannot use the base class allotate helper since it taking the internal
      * stream lock. we know that the acquire may need to poll until more frames
@@ -387,7 +435,12 @@ gst_v4l2_video_dec_loop (GstVideoDecoder * decoder)
 
     GST_LOG_OBJECT (decoder, "Process output buffer");
     ret = gst_v4l2_buffer_pool_process (v4l2_pool, &buffer);
-
+    if (ret == GST_V4L2_FLOW_LAST_BUFFER && self->v4l2capture->can_wait_event) {
+      if (GST_V4L2_FLOW_SOURCE_CHANGE == gst_v4l2_object_dqevent (self->v4l2capture)) {
+        gst_v4l2_object_stop (self->v4l2capture);
+        return;
+      }
+    }
   } while (ret == GST_V4L2_FLOW_CORRUPTED_BUFFER);
 
   if (ret != GST_FLOW_OK)
@@ -409,6 +464,27 @@ gst_v4l2_video_dec_loop (GstVideoDecoder * decoder)
 
   return;
 
+/* ERRORS */
+not_negotiated:
+  {
+    GST_ERROR_OBJECT (self, "not negotiated");
+    ret = GST_FLOW_NOT_NEGOTIATED;
+    goto beach;
+  }
+activate_failed:
+  {
+    GST_ERROR_OBJECT (self, "Buffer pool activation failed");
+    GST_ELEMENT_ERROR (self, RESOURCE, SETTINGS,
+        (_("Failed to allocate required memory.")),
+        ("Buffer pool activation failed"));
+    ret = GST_FLOW_ERROR;
+    goto beach;
+  }
+flushing:
+  {
+    ret = GST_FLOW_FLUSHING;
+    goto beach;
+  }
 beach:
   GST_DEBUG_OBJECT (decoder, "Leaving output thread: %s",
       gst_flow_get_name (ret));
@@ -439,10 +515,12 @@ gst_v4l2_video_dec_handle_frame (GstVideoDecoder * decoder,
     GstVideoCodecFrame * frame)
 {
   GstV4l2VideoDec *self = GST_V4L2_VIDEO_DEC (decoder);
+  GstBufferPool *pool = GST_BUFFER_POOL (self->v4l2output->pool);
   GstFlowReturn ret = GST_FLOW_OK;
 
   GST_DEBUG_OBJECT (self, "Handling frame %d", frame->system_frame_number);
 
   if (G_UNLIKELY (!g_atomic_int_get (&self->active)))
     goto flushing;
 
@@ -453,10 +531,7 @@ gst_v4l2_video_dec_handle_frame (GstVideoDecoder * decoder,
       goto not_negotiated;
   }
 
-  if (G_UNLIKELY (!GST_V4L2_IS_ACTIVE (self->v4l2capture))) {
-    GstBufferPool *pool = GST_BUFFER_POOL (self->v4l2output->pool);
-    GstVideoInfo info;
-    GstVideoCodecState *output_state;
+  if (G_UNLIKELY (!gst_buffer_pool_is_active (pool))) {
     GstBuffer *codec_data;
 
     GST_DEBUG_OBJECT (self, "Sending header");
@@ -495,28 +570,6 @@ gst_v4l2_video_dec_handle_frame (GstVideoDecoder * decoder,
     GST_VIDEO_DECODER_STREAM_LOCK (decoder);
 
     gst_buffer_unref (codec_data);
-
-    if (!gst_v4l2_object_acquire_format (self->v4l2capture, &info))
-      goto not_negotiated;
-
-    output_state = gst_video_decoder_set_output_state (decoder,
-        info.finfo->format, info.width, info.height, self->input_state);
-
-    /* Copy the rest of the information, there might be more in the future */
-    output_state->info.interlace_mode = info.interlace_mode;
-    gst_video_codec_state_unref (output_state);
-
-    if (!gst_video_decoder_negotiate (decoder)) {
-      if (GST_PAD_IS_FLUSHING (decoder->srcpad))
-        goto flushing;
-      else
-        goto not_negotiated;
-    }
-
-    /* Ensure our internal pool is activated */
-    if (!gst_buffer_pool_set_active (GST_BUFFER_POOL (self->v4l2capture->pool),
-            TRUE))
-      goto activate_failed;
   }
 
   if (g_atomic_int_get (&self->processing) == FALSE) {
@@ -798,6 +852,7 @@ gst_v4l2_video_dec_subinstance_init (GTypeInstance * instance, gpointer g_class)
       V4L2_BUF_TYPE_VIDEO_CAPTURE, klass->default_device,
       gst_v4l2_get_input, gst_v4l2_set_input, NULL);
   self->v4l2capture->no_initial_format = TRUE;
+  self->v4l2capture->need_wait_event = TRUE;
   self->v4l2output->keep_aspect = FALSE;
 }
 
diff --git a/sys/v4l2/v4l2_calls.c b/sys/v4l2/v4l2_calls.c
index d1cc284..c2c898a 100644
--- a/sys/v4l2/v4l2_calls.c
+++ b/sys/v4l2/v4l2_calls.c
@@ -504,6 +504,42 @@ gst_v4l2_adjust_buf_type (GstV4l2Object * v4l2object)
 #undef CHECK_CAPS
 }
 
+gboolean
+gst_v4l2_subscribe_event (GstV4l2Object * v4l2object)
+{
+  GstElement *e;
+  struct v4l2_event_subscription  sub;
+
+  e = v4l2object->element;
+
+  GST_DEBUG_OBJECT (e, "subscribe event");
+
+  if (!GST_V4L2_IS_OPEN (v4l2object))
+    return FALSE;
+
+  memset(&sub, 0, sizeof(struct v4l2_event_subscription));
+  sub.type = V4L2_EVENT_SOURCE_CHANGE;
+  if (v4l2_ioctl (v4l2object->video_fd, VIDIOC_SUBSCRIBE_EVENT, &sub) < 0)
+    goto failed;
+
+  sub.type = V4L2_EVENT_EOS;
+  if (v4l2_ioctl (v4l2object->video_fd, VIDIOC_SUBSCRIBE_EVENT, &sub) < 0)
+    goto failed;
+
+  v4l2object->can_wait_event = TRUE;
+
+  return TRUE;
+
+  /* ERRORS */
+failed:
+  {
+    GST_WARNING_OBJECT (e, "Cannot subscribe V4L2_EVENT_SOURCE_CHANGE or "
+        "V4L2_EVENT_EOS event for device '%s'.",
+        v4l2object->videodev);
+    return TRUE;
+  }
+}
+
 /******************************************************
  * gst_v4l2_open():
  *   open the video device (v4l2object->videodev)
@@ -589,6 +625,10 @@ gst_v4l2_open (GstV4l2Object * v4l2object)
   if (v4l2object->extra_controls)
     gst_v4l2_set_controls (v4l2object, v4l2object->extra_controls);
 
+  if (GST_IS_V4L2_VIDEO_DEC (v4l2object->element)) {
+    gst_v4l2_subscribe_event (v4l2object);
+  }
+
   /* UVC devices are never interlaced, and doing VIDIOC_TRY_FMT on them
    * causes expensive and slow USB IO, so don't probe them for interlaced
    */
@@ -684,6 +724,7 @@ gst_v4l2_dup (GstV4l2Object * v4l2object, GstV4l2Object * other)
       v4l2object->vcap.card, v4l2object->videodev);
 
   v4l2object->never_interlaced = other->never_interlaced;
+  v4l2object->can_wait_event = other->can_wait_event;
 
   return TRUE;
 
