Merge branch 'master' into 0.11
[platform/upstream/gst-plugins-base.git] / ext / theora / gsttheoraenc.c
index bff2384..1caa272 100644 (file)
 #define GST_CAT_DEFAULT theoraenc_debug
 GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
 
-#define GST_TYPE_BORDER_MODE (gst_border_mode_get_type())
-static GType
-gst_border_mode_get_type (void)
-{
-  static GType border_mode_type = 0;
-  static const GEnumValue border_mode[] = {
-    {BORDER_NONE, "No Border", "none"},
-    {BORDER_BLACK, "Black Border", "black"},
-    {BORDER_MIRROR, "Mirror image in borders", "mirror"},
-    {0, NULL, NULL},
-  };
-
-  if (!border_mode_type) {
-    border_mode_type =
-        g_enum_register_static ("GstTheoraEncBorderMode", border_mode);
-  }
-  return border_mode_type;
-}
-
 #define GST_TYPE_MULTIPASS_MODE (gst_multipass_mode_get_type())
 static GType
 gst_multipass_mode_get_type (void)
@@ -134,18 +115,11 @@ _ilog (unsigned int v)
 enum
 {
   PROP_0,
-  PROP_CENTER,
-  PROP_BORDER,
   PROP_BITRATE,
   PROP_QUALITY,
-  PROP_QUICK,
   PROP_KEYFRAME_AUTO,
   PROP_KEYFRAME_FREQ,
   PROP_KEYFRAME_FREQ_FORCE,
-  PROP_KEYFRAME_THRESHOLD,
-  PROP_KEYFRAME_MINDISTANCE,
-  PROP_NOISE_SENSITIVITY,
-  PROP_SHARPNESS,
   PROP_SPEEDLEVEL,
   PROP_VP3_COMPATIBLE,
   PROP_DROP_FRAMES,
@@ -232,8 +206,8 @@ static GstStaticPadTemplate theora_enc_sink_factory =
 GST_STATIC_PAD_TEMPLATE ("sink",
     GST_PAD_SINK,
     GST_PAD_ALWAYS,
-    GST_STATIC_CAPS ("video/x-raw-yuv, "
-        "format = (fourcc) { I420, Y42B, Y444 }, "
+    GST_STATIC_CAPS ("video/x-raw, "
+        "format = (string) { I420, Y42B, Y444 }, "
         "framerate = (fraction) [1/MAX, MAX], "
         "width = (int) [ 1, MAX ], " "height = (int) [ 1, MAX ]")
     );
@@ -242,34 +216,28 @@ static GstStaticPadTemplate theora_enc_src_factory =
 GST_STATIC_PAD_TEMPLATE ("src",
     GST_PAD_SRC,
     GST_PAD_ALWAYS,
-    GST_STATIC_CAPS ("video/x-theora")
+    GST_STATIC_CAPS ("video/x-theora, "
+        "framerate = (fraction) [1/MAX, MAX], "
+        "width = (int) [ 1, MAX ], " "height = (int) [ 1, MAX ]")
     );
 
-static GstCaps *theora_enc_src_caps;
+#define gst_theora_enc_parent_class parent_class
+G_DEFINE_TYPE_WITH_CODE (GstTheoraEnc, gst_theora_enc,
+    GST_TYPE_ELEMENT, G_IMPLEMENT_INTERFACE (GST_TYPE_PRESET, NULL));
 
-static void
-_do_init (GType object_type)
-{
-  const GInterfaceInfo preset_interface_info = {
-    NULL,                       /* interface_init */
-    NULL,                       /* interface_finalize */
-    NULL                        /* interface_data */
-  };
-
-  g_type_add_interface_static (object_type, GST_TYPE_PRESET,
-      &preset_interface_info);
-}
-
-GST_BOILERPLATE_FULL (GstTheoraEnc, gst_theora_enc, GstElement,
-    GST_TYPE_ELEMENT, _do_init);
+static GstCaps *theora_enc_src_caps;
 
-static gboolean theora_enc_sink_event (GstPad * pad, GstEvent * event);
-static gboolean theora_enc_src_event (GstPad * pad, GstEvent * event);
-static GstFlowReturn theora_enc_chain (GstPad * pad, GstBuffer * buffer);
+static gboolean theora_enc_sink_event (GstPad * pad, GstObject * parent,
+    GstEvent * event);
+static gboolean theora_enc_src_event (GstPad * pad, GstObject * parent,
+    GstEvent * event);
+static GstFlowReturn theora_enc_chain (GstPad * pad, GstObject * parent,
+    GstBuffer * buffer);
 static GstStateChangeReturn theora_enc_change_state (GstElement * element,
     GstStateChange transition);
-static GstCaps *theora_enc_sink_getcaps (GstPad * pad);
-static gboolean theora_enc_sink_setcaps (GstPad * pad, GstCaps * caps);
+static gboolean theora_enc_sink_query (GstPad * pad, GstObject * parent,
+    GstQuery * query);
+static gboolean theora_enc_sink_setcaps (GstTheoraEnc * enc, GstCaps * caps);
 static void theora_enc_get_property (GObject * object, guint prop_id,
     GValue * value, GParamSpec * pspec);
 static void theora_enc_set_property (GObject * object, guint prop_id,
@@ -287,21 +255,6 @@ theora_enc_encode_and_push (GstTheoraEnc * enc, ogg_packet op,
     GstBuffer * buffer);
 
 static void
-gst_theora_enc_base_init (gpointer g_class)
-{
-  GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
-
-  gst_element_class_add_static_pad_template (element_class,
-      &theora_enc_src_factory);
-  gst_element_class_add_static_pad_template (element_class,
-      &theora_enc_sink_factory);
-  gst_element_class_set_details_simple (element_class,
-      "Theora video encoder", "Codec/Encoder/Video",
-      "encode raw YUV video to a theora stream",
-      "Wim Taymans <wim@fluendo.com>");
-}
-
-static void
 gst_theora_enc_class_init (GstTheoraEncClass * klass)
 {
   GObjectClass *gobject_class = (GObjectClass *) klass;
@@ -327,15 +280,6 @@ gst_theora_enc_class_init (GstTheoraEncClass * klass)
   gobject_class->get_property = theora_enc_get_property;
   gobject_class->finalize = theora_enc_finalize;
 
-  g_object_class_install_property (gobject_class, PROP_CENTER,
-      g_param_spec_boolean ("center", "Center",
-          "ignored and kept for API compat only", TRUE,
-          (GParamFlags) G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
-  g_object_class_install_property (gobject_class, PROP_BORDER,
-      g_param_spec_enum ("border", "Border",
-          "ignored and kept for API compat only",
-          GST_TYPE_BORDER_MODE, BORDER_BLACK,
-          (GParamFlags) G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
   /* general encoding stream options */
   g_object_class_install_property (gobject_class, PROP_BITRATE,
       g_param_spec_int ("bitrate", "Bitrate", "Compressed video bitrate (kbps)",
@@ -347,10 +291,6 @@ gst_theora_enc_class_init (GstTheoraEncClass * klass)
           THEORA_DEF_QUALITY,
           (GParamFlags) G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
           GST_PARAM_MUTABLE_PLAYING));
-  g_object_class_install_property (gobject_class, PROP_QUICK,
-      g_param_spec_boolean ("quick", "Quick",
-          "ignored and kept for API compat only", TRUE,
-          (GParamFlags) G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
   g_object_class_install_property (gobject_class, PROP_KEYFRAME_AUTO,
       g_param_spec_boolean ("keyframe-auto", "Keyframe Auto",
           "Automatic keyframe detection", THEORA_DEF_KEYFRAME_AUTO,
@@ -364,22 +304,6 @@ gst_theora_enc_class_init (GstTheoraEncClass * klass)
           "Force keyframe every N frames", 1, 32768,
           THEORA_DEF_KEYFRAME_FREQ_FORCE,
           (GParamFlags) G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
-  g_object_class_install_property (gobject_class, PROP_KEYFRAME_THRESHOLD,
-      g_param_spec_int ("keyframe-threshold", "Keyframe threshold",
-          "ignored and kept for API compat only", 0, 32768, 80,
-          (GParamFlags) G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
-  g_object_class_install_property (gobject_class, PROP_KEYFRAME_MINDISTANCE,
-      g_param_spec_int ("keyframe-mindistance", "Keyframe mindistance",
-          "ignored and kept for API compat only", 1, 32768, 8,
-          (GParamFlags) G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
-  g_object_class_install_property (gobject_class, PROP_NOISE_SENSITIVITY,
-      g_param_spec_int ("noise-sensitivity", "Noise sensitivity",
-          "ignored and kept for API compat only", 0, 32768, 1,
-          (GParamFlags) G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
-  g_object_class_install_property (gobject_class, PROP_SHARPNESS,
-      g_param_spec_int ("sharpness", "Sharpness",
-          "ignored and kept for API compat only", 0, 2, 0,
-          (GParamFlags) G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
   g_object_class_install_property (gobject_class, PROP_SPEEDLEVEL,
       g_param_spec_int ("speed-level", "Speed level",
           "Controls the amount of analysis performed when encoding."
@@ -436,8 +360,17 @@ gst_theora_enc_class_init (GstTheoraEncClass * klass)
           THEORA_DEF_DUP_ON_GAP,
           (GParamFlags) G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
 
-  caps_string = g_strdup_printf ("video/x-raw-yuv, "
-      "format = (fourcc) { %s }, "
+  gst_element_class_add_pad_template (gstelement_class,
+      gst_static_pad_template_get (&theora_enc_src_factory));
+  gst_element_class_add_pad_template (gstelement_class,
+      gst_static_pad_template_get (&theora_enc_sink_factory));
+  gst_element_class_set_details_simple (gstelement_class,
+      "Theora video encoder", "Codec/Encoder/Video",
+      "encode raw YUV video to a theora stream",
+      "Wim Taymans <wim@fluendo.com>");
+
+  caps_string = g_strdup_printf ("video/x-raw, "
+      "format = (string) { %s }, "
       "framerate = (fraction) [1/MAX, MAX], "
       "width = (int) [ 1, MAX ], " "height = (int) [ 1, MAX ]",
       theora_enc_get_supported_formats ());
@@ -448,14 +381,13 @@ gst_theora_enc_class_init (GstTheoraEncClass * klass)
 }
 
 static void
-gst_theora_enc_init (GstTheoraEnc * enc, GstTheoraEncClass * g_class)
+gst_theora_enc_init (GstTheoraEnc * enc)
 {
   enc->sinkpad =
       gst_pad_new_from_static_template (&theora_enc_sink_factory, "sink");
   gst_pad_set_chain_function (enc->sinkpad, theora_enc_chain);
   gst_pad_set_event_function (enc->sinkpad, theora_enc_sink_event);
-  gst_pad_set_getcaps_function (enc->sinkpad, theora_enc_sink_getcaps);
-  gst_pad_set_setcaps_function (enc->sinkpad, theora_enc_sink_setcaps);
+  gst_pad_set_query_function (enc->sinkpad, theora_enc_sink_query);
   gst_element_add_pad (GST_ELEMENT (enc), enc->sinkpad);
 
   enc->srcpad =
@@ -598,7 +530,7 @@ theora_enc_get_supported_formats (void)
   static const struct
   {
     th_pixel_fmt pixelformat;
-    const char fourcc[5];
+    const char fourcc[];
   } formats[] = {
     {
     TH_PF_420, "I420"}, {
@@ -636,15 +568,15 @@ theora_enc_get_supported_formats (void)
 }
 
 static GstCaps *
-theora_enc_sink_getcaps (GstPad * pad)
+theora_enc_sink_getcaps (GstPad * pad, GstCaps * filter)
 {
   GstTheoraEnc *encoder;
   GstPad *peer;
   GstCaps *caps;
 
   /* If we already have caps return them */
-  if (GST_PAD_CAPS (pad))
-    return gst_caps_ref (GST_PAD_CAPS (pad));
+  if ((caps = gst_pad_get_current_caps (pad)) != NULL)
+    return caps;
 
   encoder = GST_THEORA_ENC (gst_pad_get_parent (pad));
   if (!encoder)
@@ -657,7 +589,7 @@ theora_enc_sink_getcaps (GstPad * pad)
     GstStructure *s;
     guint i, n;
 
-    peer_caps = gst_pad_get_caps (peer);
+    peer_caps = gst_pad_query_caps (peer, NULL);
 
     /* Translate peercaps to YUV */
     peer_caps = gst_caps_make_writable (peer_caps);
@@ -665,7 +597,7 @@ theora_enc_sink_getcaps (GstPad * pad)
     for (i = 0; i < n; i++) {
       s = gst_caps_get_structure (peer_caps, i);
 
-      gst_structure_set_name (s, "video/x-raw-yuv");
+      gst_structure_set_name (s, "video/x-raw");
       gst_structure_remove_field (s, "streamheader");
     }
 
@@ -683,61 +615,90 @@ theora_enc_sink_getcaps (GstPad * pad)
 
   gst_object_unref (encoder);
 
+  if (filter) {
+    GstCaps *intersection;
+
+    intersection =
+        gst_caps_intersect_full (filter, caps, GST_CAPS_INTERSECT_FIRST);
+    gst_caps_unref (caps);
+    caps = intersection;
+  }
+
   return caps;
 }
 
 static gboolean
-theora_enc_sink_setcaps (GstPad * pad, GstCaps * caps)
+theora_enc_sink_query (GstPad * pad, GstObject * parent, GstQuery * query)
+{
+  gboolean res = FALSE;
+
+  switch (GST_QUERY_TYPE (query)) {
+    case GST_QUERY_CAPS:
+    {
+      GstCaps *filter, *caps;
+
+      gst_query_parse_caps (query, &filter);
+      caps = theora_enc_sink_getcaps (pad, filter);
+      gst_query_set_caps_result (query, caps);
+      gst_caps_unref (caps);
+      res = TRUE;
+      break;
+    }
+    default:
+      res = gst_pad_query_default (pad, parent, query);
+      break;
+  }
+
+  return res;
+}
+
+static gboolean
+theora_enc_sink_setcaps (GstTheoraEnc * enc, GstCaps * caps)
 {
-  GstStructure *structure = gst_caps_get_structure (caps, 0);
-  GstTheoraEnc *enc = GST_THEORA_ENC (gst_pad_get_parent (pad));
-  guint32 fourcc;
-  const GValue *par;
-  gint fps_n, fps_d;
-
-  gst_structure_get_fourcc (structure, "format", &fourcc);
-  gst_structure_get_int (structure, "width", &enc->width);
-  gst_structure_get_int (structure, "height", &enc->height);
-  gst_structure_get_fraction (structure, "framerate", &fps_n, &fps_d);
-  par = gst_structure_get_value (structure, "pixel-aspect-ratio");
+  GstVideoInfo info;
 
   th_info_clear (&enc->info);
   th_info_init (&enc->info);
+
+  if (!gst_video_info_from_caps (&info, caps))
+    goto invalid_caps;
+
+  enc->vinfo = info;
+
   /* Theora has a divisible-by-sixteen restriction for the encoded video size but
    * we can define a picture area using pic_width/pic_height */
-  enc->info.frame_width = GST_ROUND_UP_16 (enc->width);
-  enc->info.frame_height = GST_ROUND_UP_16 (enc->height);
-  enc->info.pic_width = enc->width;
-  enc->info.pic_height = enc->height;
-  switch (fourcc) {
-    case GST_MAKE_FOURCC ('I', '4', '2', '0'):
+  enc->info.frame_width = GST_ROUND_UP_16 (info.width);
+  enc->info.frame_height = GST_ROUND_UP_16 (info.height);
+  enc->info.pic_width = info.width;
+  enc->info.pic_height = info.height;
+
+  switch (GST_VIDEO_INFO_FORMAT (&info)) {
+    case GST_VIDEO_FORMAT_I420:
       enc->info.pixel_fmt = TH_PF_420;
       break;
-    case GST_MAKE_FOURCC ('Y', '4', '2', 'B'):
+    case GST_VIDEO_FORMAT_Y42B:
       enc->info.pixel_fmt = TH_PF_422;
       break;
-    case GST_MAKE_FOURCC ('Y', '4', '4', '4'):
+    case GST_VIDEO_FORMAT_Y444:
       enc->info.pixel_fmt = TH_PF_444;
       break;
     default:
       g_assert_not_reached ();
   }
 
-  enc->info.fps_numerator = enc->fps_n = fps_n;
-  enc->info.fps_denominator = enc->fps_d = fps_d;
-  if (par) {
-    enc->info.aspect_numerator = gst_value_get_fraction_numerator (par);
-    enc->par_n = gst_value_get_fraction_numerator (par);
-    enc->info.aspect_denominator = gst_value_get_fraction_denominator (par);
-    enc->par_d = gst_value_get_fraction_denominator (par);
-  } else {
-    /* setting them to 0 indicates that the decoder can chose a good aspect
-     * ratio, defaulting to 1/1 */
-    enc->info.aspect_numerator = 0;
-    enc->par_n = 1;
-    enc->info.aspect_denominator = 0;
-    enc->par_d = 1;
-  }
+  enc->info.fps_numerator = info.fps_n;
+  enc->info.fps_denominator = info.fps_d;
+
+  enc->info.aspect_numerator = info.par_n;
+  enc->info.aspect_denominator = info.par_d;
+#if 0
+  /* setting them to 0 indicates that the decoder can chose a good aspect
+   * ratio, defaulting to 1/1 */
+  enc->info.aspect_numerator = 0;
+  enc->par_n = 1;
+  enc->info.aspect_denominator = 0;
+  enc->par_d = 1;
+#endif
 
   enc->info.colorspace = TH_CS_UNSPECIFIED;
 
@@ -750,9 +711,14 @@ theora_enc_sink_setcaps (GstPad * pad, GstCaps * caps)
   theora_enc_reset (enc);
   enc->initialised = TRUE;
 
-  gst_object_unref (enc);
-
   return TRUE;
+
+  /* ERRORS */
+invalid_caps:
+  {
+    GST_DEBUG_OBJECT (enc, "could not parse caps");
+    return FALSE;
+  }
 }
 
 static guint64
@@ -783,8 +749,7 @@ theora_buffer_from_packet (GstTheoraEnc * enc, ogg_packet * packet,
     goto done;
   }
 
-  memcpy (GST_BUFFER_DATA (buf), packet->packet, packet->bytes);
-  gst_buffer_set_caps (buf, GST_PAD_CAPS (enc->srcpad));
+  gst_buffer_fill (buf, 0, packet->packet, packet->bytes);
   /* see ext/ogg/README; OFFSET_END takes "our" granulepos, OFFSET its
    * time representation */
   GST_BUFFER_OFFSET_END (buf) =
@@ -820,7 +785,7 @@ theora_push_buffer (GstTheoraEnc * enc, GstBuffer * buffer)
 {
   GstFlowReturn ret;
 
-  enc->bytes_out += GST_BUFFER_SIZE (buffer);
+  enc->bytes_out += gst_buffer_get_size (buffer);
 
   ret = gst_pad_push (enc->srcpad, buffer);
 
@@ -862,7 +827,7 @@ theora_set_header_on_caps (GstCaps * caps, GSList * buffers)
     buffer = walk->data;
 
     /* mark buffer */
-    GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_IN_CAPS);
+    GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_HEADER);
 
     /* Copy buffer, because we can't use the original -
      * it creates a circular refcount with the caps<->buffers */
@@ -893,33 +858,34 @@ theora_enc_force_keyframe (GstTheoraEnc * enc)
 
   theora_enc_reset (enc);
   enc->granulepos_offset =
-      gst_util_uint64_scale (next_ts, enc->fps_n, GST_SECOND * enc->fps_d);
+      gst_util_uint64_scale (next_ts, enc->vinfo.fps_n,
+      GST_SECOND * enc->vinfo.fps_d);
   enc->timestamp_offset = next_ts;
   enc->next_ts = 0;
 }
 
 static gboolean
-theora_enc_sink_event (GstPad * pad, GstEvent * event)
+theora_enc_sink_event (GstPad * pad, GstObject * parent, GstEvent * event)
 {
   GstTheoraEnc *enc;
   ogg_packet op;
   gboolean res;
 
-  enc = GST_THEORA_ENC (GST_PAD_PARENT (pad));
+  enc = GST_THEORA_ENC (parent);
 
   switch (GST_EVENT_TYPE (event)) {
-    case GST_EVENT_NEWSEGMENT:
+    case GST_EVENT_CAPS:
     {
-      gboolean update;
-      gdouble rate, applied_rate;
-      GstFormat format;
-      gint64 start, stop, time;
-
-      gst_event_parse_new_segment_full (event, &update, &rate, &applied_rate,
-          &format, &start, &stop, &time);
+      GstCaps *caps;
 
-      gst_segment_set_newsegment_full (&enc->segment, update, rate,
-          applied_rate, format, start, stop, time);
+      gst_event_parse_caps (event, &caps);
+      res = theora_enc_sink_setcaps (enc, caps);
+      gst_event_unref (event);
+      break;
+    }
+    case GST_EVENT_SEGMENT:
+    {
+      gst_event_copy_segment (event, &enc->segment);
 
       res = gst_pad_push_event (enc->srcpad, event);
       break;
@@ -971,12 +937,12 @@ theora_enc_sink_event (GstPad * pad, GstEvent * event)
 }
 
 static gboolean
-theora_enc_src_event (GstPad * pad, GstEvent * event)
+theora_enc_src_event (GstPad * pad, GstObject * parent, GstEvent * event)
 {
   GstTheoraEnc *enc;
   gboolean res = TRUE;
 
-  enc = GST_THEORA_ENC (GST_PAD_PARENT (pad));
+  enc = GST_THEORA_ENC (parent);
 
   switch (GST_EVENT_TYPE (event)) {
     case GST_EVENT_CUSTOM_UPSTREAM:
@@ -1036,25 +1002,11 @@ theora_enc_is_discontinuous (GstTheoraEnc * enc, GstClockTime timestamp,
 }
 
 static void
-theora_enc_init_buffer (th_ycbcr_buffer buf, th_info * info, guint8 * data)
+theora_enc_init_buffer (th_ycbcr_buffer buf, GstVideoFrame * frame)
 {
-  GstVideoFormat format;
+  GstVideoInfo info;
   guint i;
 
-  switch (info->pixel_fmt) {
-    case TH_PF_444:
-      format = GST_VIDEO_FORMAT_Y444;
-      break;
-    case TH_PF_420:
-      format = GST_VIDEO_FORMAT_I420;
-      break;
-    case TH_PF_422:
-      format = GST_VIDEO_FORMAT_Y42B;
-      break;
-    default:
-      g_assert_not_reached ();
-  }
-
   /* According to Theora developer Timothy Terriberry, the Theora 
    * encoder will not use memory outside of pic_width/height, even when
    * the frame size is bigger. The values outside this region will be encoded
@@ -1062,17 +1014,17 @@ theora_enc_init_buffer (th_ycbcr_buffer buf, th_info * info, guint8 * data)
    * Due to this, setting the frame's width/height as the buffer width/height
    * is perfectly ok, even though it does not strictly look ok.
    */
+
+  gst_video_info_init (&info);
+  gst_video_info_set_format (&info, GST_VIDEO_FRAME_FORMAT (frame),
+      GST_ROUND_UP_16 (GST_VIDEO_FRAME_WIDTH (frame)),
+      GST_ROUND_UP_16 (GST_VIDEO_FRAME_HEIGHT (frame)));
+
   for (i = 0; i < 3; i++) {
-    buf[i].width =
-        gst_video_format_get_component_width (format, i, info->frame_width);
-    buf[i].height =
-        gst_video_format_get_component_height (format, i, info->frame_height);
-
-    buf[i].data =
-        data + gst_video_format_get_component_offset (format, i,
-        info->pic_width, info->pic_height);
-    buf[i].stride =
-        gst_video_format_get_row_stride (format, i, info->pic_width);
+    buf[i].width = GST_VIDEO_INFO_COMP_WIDTH (&info, i);
+    buf[i].height = GST_VIDEO_INFO_COMP_HEIGHT (&info, i);
+    buf[i].data = GST_VIDEO_FRAME_COMP_DATA (frame, i);
+    buf[i].stride = GST_VIDEO_FRAME_COMP_STRIDE (frame, i);
   }
 }
 
@@ -1088,17 +1040,21 @@ theora_enc_read_multipass_cache (GstTheoraEnc * enc)
 
   while (!done) {
     if (gst_adapter_available (enc->multipass_cache_adapter) == 0) {
+      GstMapInfo map;
+
       cache_buf = gst_buffer_new_and_alloc (512);
+
+      gst_buffer_map (cache_buf, &map, GST_MAP_READ);
       stat = g_io_channel_read_chars (enc->multipass_cache_fd,
-          (gchar *) GST_BUFFER_DATA (cache_buf), GST_BUFFER_SIZE (cache_buf),
-          &bytes_read, NULL);
+          (gchar *) map.data, map.size, &bytes_read, NULL);
 
       if (bytes_read <= 0) {
+        gst_buffer_unmap (cache_buf, &map);
         gst_buffer_unref (cache_buf);
         break;
       } else {
-        GST_BUFFER_SIZE (cache_buf) = bytes_read;
-
+        gst_buffer_unmap (cache_buf, &map);
+        gst_buffer_resize (cache_buf, 0, bytes_read);
         gst_adapter_push (enc->multipass_cache_adapter, cache_buf);
       }
     }
@@ -1108,11 +1064,13 @@ theora_enc_read_multipass_cache (GstTheoraEnc * enc)
     bytes_read =
         MIN (gst_adapter_available (enc->multipass_cache_adapter), 512);
 
-    cache_data = gst_adapter_peek (enc->multipass_cache_adapter, bytes_read);
+    cache_data = gst_adapter_map (enc->multipass_cache_adapter, bytes_read);
 
     bytes_consumed =
         th_encode_ctl (enc->encoder, TH_ENCCTL_2PASS_IN, (guint8 *) cache_data,
         bytes_read);
+    gst_adapter_unmap (enc->multipass_cache_adapter);
+
     done = bytes_consumed <= 0;
     if (bytes_consumed > 0)
       gst_adapter_flush (enc->multipass_cache_adapter, bytes_consumed);
@@ -1282,6 +1240,7 @@ theora_enc_encode_and_push (GstTheoraEnc * enc, ogg_packet op,
     GstBuffer * buffer)
 {
   GstFlowReturn ret;
+  GstVideoFrame frame;
   th_ycbcr_buffer ycbcr;
   gint res;
 
@@ -1351,9 +1310,12 @@ theora_enc_encode_and_push (GstTheoraEnc * enc, ogg_packet op,
         return GST_FLOW_OK;
       }
     }
-    theora_enc_init_buffer (ycbcr, &enc->info, GST_BUFFER_DATA (enc->prevbuf));
-  } else
-    theora_enc_init_buffer (ycbcr, &enc->info, GST_BUFFER_DATA (buffer));
+    gst_video_frame_map (&frame, &enc->vinfo, enc->prevbuf, GST_MAP_READ);
+    theora_enc_init_buffer (ycbcr, &frame);
+  } else {
+    gst_video_frame_map (&frame, &enc->vinfo, buffer, GST_MAP_READ);
+    theora_enc_init_buffer (ycbcr, &frame);
+  }
 
   /* check for buffer, it can be optional */
   if (enc->current_discont && buffer) {
@@ -1362,8 +1324,8 @@ theora_enc_encode_and_push (GstTheoraEnc * enc, ogg_packet op,
         gst_segment_to_running_time (&enc->segment, GST_FORMAT_TIME, timestamp);
     theora_enc_reset (enc);
     enc->granulepos_offset =
-        gst_util_uint64_scale (running_time, enc->fps_n,
-        GST_SECOND * enc->fps_d);
+        gst_util_uint64_scale (running_time, enc->vinfo.fps_n,
+        GST_SECOND * enc->vinfo.fps_d);
     enc->timestamp_offset = running_time;
     enc->next_ts = 0;
     enc->next_discont = TRUE;
@@ -1419,6 +1381,8 @@ theora_enc_encode_and_push (GstTheoraEnc * enc, ogg_packet op,
   }
 
   theora_timefifo_truncate (enc);
+done:
+  gst_video_frame_unmap (&frame);
   if (buffer)
     gst_buffer_unref (buffer);
   enc->current_discont = FALSE;
@@ -1428,23 +1392,23 @@ theora_enc_encode_and_push (GstTheoraEnc * enc, ogg_packet op,
   /* ERRORS */
 multipass_read_failed:
   {
-    gst_buffer_unref (buffer);
-    return ret;
+    GST_DEBUG_OBJECT (enc, "multipass read failed");
+    goto done;
   }
 multipass_write_failed:
   {
-    gst_buffer_unref (buffer);
-    return ret;
+    GST_DEBUG_OBJECT (enc, "multipass write failed");
+    goto done;
   }
 data_push:
   {
-    gst_buffer_unref (buffer);
-    return ret;
+    GST_DEBUG_OBJECT (enc, "error pushing buffer: %s", gst_flow_get_name (ret));
+    goto done;
   }
 }
 
 static GstFlowReturn
-theora_enc_chain (GstPad * pad, GstBuffer * buffer)
+theora_enc_chain (GstPad * pad, GstObject * parent, GstBuffer * buffer)
 {
   GstTheoraEnc *enc;
   ogg_packet op;
@@ -1452,7 +1416,7 @@ theora_enc_chain (GstPad * pad, GstBuffer * buffer)
   GstFlowReturn ret;
   gboolean force_keyframe;
 
-  enc = GST_THEORA_ENC (GST_PAD_PARENT (pad));
+  enc = GST_THEORA_ENC (parent);
 
   /* we keep track of two timelines.
    * - The timestamps from the incoming buffers, which we copy to the outgoing
@@ -1561,16 +1525,14 @@ theora_enc_chain (GstPad * pad, GstBuffer * buffer)
 
     /* mark buffers and put on caps */
     caps = gst_caps_new_simple ("video/x-theora",
-        "width", G_TYPE_INT, enc->width,
-        "height", G_TYPE_INT, enc->height,
-        "framerate", GST_TYPE_FRACTION, enc->fps_n, enc->fps_d,
-        "pixel-aspect-ratio", GST_TYPE_FRACTION, enc->par_n, enc->par_d, NULL);
+        "width", G_TYPE_INT, enc->vinfo.width,
+        "height", G_TYPE_INT, enc->vinfo.height,
+        "framerate", GST_TYPE_FRACTION, enc->vinfo.fps_n, enc->vinfo.fps_d,
+        "pixel-aspect-ratio", GST_TYPE_FRACTION, enc->vinfo.par_n,
+        enc->vinfo.par_d, NULL);
     caps = theora_set_header_on_caps (caps, buffers);
     GST_DEBUG ("here are the caps: %" GST_PTR_FORMAT, caps);
     gst_pad_set_caps (enc->srcpad, caps);
-
-    g_slist_foreach (buffers, (GFunc) gst_buffer_set_caps, caps);
-
     gst_caps_unref (caps);
 
     /* push out the header buffers */
@@ -1585,8 +1547,8 @@ theora_enc_chain (GstPad * pad, GstBuffer * buffer)
     }
 
     enc->granulepos_offset =
-        gst_util_uint64_scale (running_time, enc->fps_n,
-        GST_SECOND * enc->fps_d);
+        gst_util_uint64_scale (running_time, enc->vinfo.fps_n,
+        GST_SECOND * enc->vinfo.fps_d);
     enc->timestamp_offset = running_time;
     enc->next_ts = 0;
   }
@@ -1681,7 +1643,7 @@ theora_enc_change_state (GstElement * element, GstStateChange transition)
       break;
   }
 
-  ret = parent_class->change_state (element, transition);
+  ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
 
   switch (transition) {
     case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
@@ -1714,17 +1676,6 @@ theora_enc_set_property (GObject * object, guint prop_id,
   GstTheoraEnc *enc = GST_THEORA_ENC (object);
 
   switch (prop_id) {
-    case PROP_CENTER:
-    case PROP_BORDER:
-    case PROP_QUICK:
-    case PROP_KEYFRAME_THRESHOLD:
-    case PROP_KEYFRAME_MINDISTANCE:
-    case PROP_NOISE_SENSITIVITY:
-    case PROP_SHARPNESS:
-      /* kept for API compat, but ignored */
-      GST_WARNING_OBJECT (object, "Obsolete property '%s' ignored",
-          pspec->name);
-      break;
     case PROP_BITRATE:
       GST_OBJECT_LOCK (enc);
       enc->video_bitrate = g_value_get_int (value) * 1000;
@@ -1796,12 +1747,6 @@ theora_enc_get_property (GObject * object, guint prop_id,
   GstTheoraEnc *enc = GST_THEORA_ENC (object);
 
   switch (prop_id) {
-    case PROP_CENTER:
-      g_value_set_boolean (value, TRUE);
-      break;
-    case PROP_BORDER:
-      g_value_set_enum (value, BORDER_BLACK);
-      break;
     case PROP_BITRATE:
       GST_OBJECT_LOCK (enc);
       g_value_set_int (value, enc->video_bitrate / 1000);
@@ -1812,9 +1757,6 @@ theora_enc_get_property (GObject * object, guint prop_id,
       g_value_set_int (value, enc->video_quality);
       GST_OBJECT_UNLOCK (enc);
       break;
-    case PROP_QUICK:
-      g_value_set_boolean (value, TRUE);
-      break;
     case PROP_KEYFRAME_AUTO:
       g_value_set_boolean (value, enc->keyframe_auto);
       break;
@@ -1824,18 +1766,6 @@ theora_enc_get_property (GObject * object, guint prop_id,
     case PROP_KEYFRAME_FREQ_FORCE:
       g_value_set_int (value, enc->keyframe_force);
       break;
-    case PROP_KEYFRAME_THRESHOLD:
-      g_value_set_int (value, 80);
-      break;
-    case PROP_KEYFRAME_MINDISTANCE:
-      g_value_set_int (value, 8);
-      break;
-    case PROP_NOISE_SENSITIVITY:
-      g_value_set_int (value, 1);
-      break;
-    case PROP_SHARPNESS:
-      g_value_set_int (value, 0);
-      break;
     case PROP_SPEEDLEVEL:
       g_value_set_int (value, enc->speed_level);
       break;