diff --git a/ext/theora/gsttheoraenc.c b/ext/theora/gsttheoraenc.c
index c580675..487fd00 100644
--- a/ext/theora/gsttheoraenc.c
+++ b/ext/theora/gsttheoraenc.c
@@ -130,6 +130,7 @@ _ilog (unsigned int v)
 #define THEORA_DEF_RATE_BUFFER          0
 #define THEORA_DEF_MULTIPASS_CACHE_FILE NULL
 #define THEORA_DEF_MULTIPASS_MODE       MULTIPASS_MODE_SINGLE_PASS
+#define THEORA_DEF_DUP_ON_GAP           FALSE
 enum
 {
   PROP_0,
@@ -152,7 +153,8 @@ enum
   PROP_CAP_UNDERFLOW,
   PROP_RATE_BUFFER,
   PROP_MULTIPASS_CACHE_FILE,
-  PROP_MULTIPASS_MODE
+  PROP_MULTIPASS_MODE,
+  PROP_DUP_ON_GAP
       /* FILL ME */
 };
 
@@ -413,6 +415,14 @@ gst_theora_enc_class_init (GstTheoraEncClass * klass)
           "Single pass or first/second pass", GST_TYPE_MULTIPASS_MODE,
           THEORA_DEF_MULTIPASS_MODE,
           (GParamFlags) G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+  g_object_class_install_property (gobject_class, PROP_DUP_ON_GAP,
+      g_param_spec_boolean ("dup-on-gap", "Create DUP frame on GAP flag",
+          "Allow codec to handle frames with GAP flag as duplicats of next frame. "
+          "This is goot to work with variable frame rate stabelized "
+          "by videorate element, but may be not good for other things "
+          "like rtp stream.",
+          THEORA_DEF_DUP_ON_GAP,
+          (GParamFlags) G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
 
   gstelement_class->change_state = theora_enc_change_state;
 }
@@ -449,6 +459,7 @@ gst_theora_enc_init (GstTheoraEnc * enc, GstTheoraEncClass * g_class)
   enc->cap_overflow = THEORA_DEF_CAP_OVERFLOW;
   enc->cap_underflow = THEORA_DEF_CAP_UNDERFLOW;
   enc->rate_buffer = THEORA_DEF_RATE_BUFFER;
+  enc->dup_on_gap = THEORA_DEF_DUP_ON_GAP;
 
   enc->multipass_mode = THEORA_DEF_MULTIPASS_MODE;
   enc->multipass_cache_file = THEORA_DEF_MULTIPASS_CACHE_FILE;
@@ -544,6 +555,7 @@ theora_enc_clear (GstTheoraEnc * enc)
   enc->bytes_out = 0;
   enc->granulepos_offset = 0;
   enc->timestamp_offset = 0;
+  enc->dups = 0;
 
   enc->next_ts = GST_CLOCK_TIME_NONE;
   enc->next_discont = FALSE;
@@ -717,6 +729,7 @@ theora_buffer_from_packet (GstTheoraEnc * enc, ogg_packet * packet,
   gst_buffer_set_caps (buf, GST_PAD_CAPS (enc->srcpad));
   /* see ext/ogg/README; OFFSET_END takes "our" granulepos, OFFSET its
    * time representation */
+
   GST_BUFFER_OFFSET_END (buf) =
       granulepos_add (packet->granulepos, enc->granulepos_offset,
       enc->info.keyframe_granule_shift);
@@ -932,36 +945,6 @@ theora_enc_src_event (GstPad * pad, GstEvent * event)
   return res;
 }
 
-static gboolean
-theora_enc_is_discontinuous (GstTheoraEnc * enc, GstClockTime timestamp,
-    GstClockTime duration)
-{
-  GstClockTimeDiff max_diff;
-  gboolean ret = FALSE;
-
-  /* Allow 3/4 a frame off */
-  max_diff = (enc->info.fps_denominator * GST_SECOND * 3) /
-      (enc->info.fps_numerator * 4);
-
-  if (timestamp != GST_CLOCK_TIME_NONE
-      && enc->expected_ts != GST_CLOCK_TIME_NONE) {
-    if ((GstClockTimeDiff) (timestamp - enc->expected_ts) > max_diff) {
-      GST_DEBUG_OBJECT (enc, "Incoming TS %" GST_TIME_FORMAT
-          " exceeds expected value %" GST_TIME_FORMAT
-          " by too much, marking discontinuity",
-          GST_TIME_ARGS (timestamp), GST_TIME_ARGS (enc->expected_ts));
-      ret = TRUE;
-    }
-  }
-
-  if (GST_CLOCK_TIME_IS_VALID (duration))
-    enc->expected_ts = timestamp + duration;
-  else
-    enc->expected_ts = GST_CLOCK_TIME_NONE;
-
-  return ret;
-}
-
 static void
 theora_enc_init_buffer (th_ycbcr_buffer buf, th_info * info, guint8 * data)
 {
@@ -1129,6 +1112,7 @@ theora_enc_chain (GstPad * pad, GstBuffer * buffer)
     return GST_FLOW_OK;
   }
 
+ 
   GST_OBJECT_LOCK (enc);
   if (enc->bitrate_changed) {
     long int bitrate = enc->video_bitrate;
@@ -1249,16 +1233,6 @@ theora_enc_chain (GstPad * pad, GstBuffer * buffer)
 
     theora_enc_init_buffer (ycbcr, &enc->info, GST_BUFFER_DATA (buffer));
 
-    if (theora_enc_is_discontinuous (enc, running_time, duration)) {
-      theora_enc_reset (enc);
-      enc->granulepos_offset =
-          gst_util_uint64_scale (running_time, enc->fps_n,
-          GST_SECOND * enc->fps_d);
-      enc->timestamp_offset = running_time;
-      enc->next_ts = 0;
-      enc->next_discont = TRUE;
-    }
-
     if (enc->multipass_cache_fd
         && enc->multipass_mode == MULTIPASS_MODE_SECOND_PASS) {
       if (!theora_enc_read_multipass_cache (enc)) {
@@ -1267,6 +1241,35 @@ theora_enc_chain (GstPad * pad, GstBuffer * buffer)
       }
     }
 
+    if (enc->dup_on_gap &&
+        GST_BUFFER_FLAG_IS_SET (buffer, GST_BUFFER_FLAG_GAP)) {
+      GST_DEBUG_OBJECT (enc, "Got GAP frame, queue as duplicat.");
+
+      /* remember the timestamp of first dup frame */
+      if (!enc->dups)
+        enc->first_dup_time = timestamp;
+
+      enc->dups++;
+
+      /* videorate can easy create 200 dup frames in one shot.
+       * To make us more bullet proof, make sure we have no
+       * more dup frames than keyframe interval. */
+      if (enc->keyframe_force > enc->dups) {
+        gst_buffer_unref (buffer);
+        return GST_FLOW_OK;
+      }
+    }
+
+    if (enc->dups) {
+      res = th_encode_ctl (enc->encoder, TH_ENCCTL_SET_DUP_COUNT,
+                           &enc->dups, sizeof(enc->dups));
+      enc->dups++;
+      if (res < 0) {
+        GST_WARNING_OBJECT (enc, "Failed marking dups for last frame");
+        /* we can continue anyway, it'll just be slower */
+      }
+    }
+
     res = th_encode_ycbcr_in (enc->encoder, ycbcr);
     /* none of the failure cases can happen here */
     g_assert (res == 0);
@@ -1281,18 +1284,31 @@ theora_enc_chain (GstPad * pad, GstBuffer * buffer)
 
     ret = GST_FLOW_OK;
     while (th_encode_packetout (enc->encoder, 0, &op)) {
-      GstClockTime next_time;
+      GstClockTime next_time, duration;
+      GST_DEBUG_OBJECT (enc, "encoded. granule:%x, packet:%p, bytes:%u",
+                        op.granulepos, op.packet, op.bytes);
 
       next_time = th_granule_time (enc->encoder, op.granulepos) * GST_SECOND;
+      duration = next_time - enc->next_ts;
+
+      if (enc->dups) {
+        timestamp = enc->first_dup_time;
+        enc->first_dup_time += duration;
+        enc->dups--;
+      }
 
       ret =
-          theora_push_packet (enc, &op, timestamp, enc->next_ts,
-          next_time - enc->next_ts);
+          theora_push_packet (enc, &op, timestamp, enc->next_ts, duration);
 
       enc->next_ts = next_time;
-      if (ret != GST_FLOW_OK)
+      if (ret != GST_FLOW_OK) {
+        /* if we are here, reference frame is lost, so dups too */
+        enc->dups = 0;
         goto data_push;
+      }
     }
+    /* if th_encode_packetout filed on some frame, we lost all dups too */
+    enc->dups = 0;
     gst_buffer_unref (buffer);
   }
 
@@ -1481,6 +1497,9 @@ theora_enc_set_property (GObject * object, guint prop_id,
     case PROP_MULTIPASS_MODE:
       enc->multipass_mode = g_value_get_enum (value);
       break;
+    case PROP_DUP_ON_GAP:
+      enc->dup_on_gap = g_value_get_boolean (value);
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
@@ -1558,6 +1577,10 @@ theora_enc_get_property (GObject * object, guint prop_id,
     case PROP_MULTIPASS_MODE:
       g_value_set_enum (value, enc->multipass_mode);
       break;
+    case PROP_DUP_ON_GAP:
+      g_value_set_boolean (value, enc->dup_on_gap);
+      break;
+
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
diff --git a/ext/theora/gsttheoraenc.h b/ext/theora/gsttheoraenc.h
index 08707d8..947e6e1 100644
--- a/ext/theora/gsttheoraenc.h
+++ b/ext/theora/gsttheoraenc.h
@@ -121,6 +121,10 @@ struct _GstTheoraEnc
   gboolean cap_underflow;
   int rate_buffer;
 
+  gboolean dup_on_gap;
+  gint dups;
+  GstClockTime first_dup_time;
+
   GstTheoraEncMultipassMode multipass_mode;
   GIOChannel *multipass_cache_fd;
   GstAdapter *multipass_cache_adapter;
