Merge branch 'master' into 0.11
authorWim Taymans <wim.taymans@collabora.co.uk>
Wed, 28 Sep 2011 11:29:08 +0000 (13:29 +0200)
committerWim Taymans <wim.taymans@collabora.co.uk>
Wed, 28 Sep 2011 11:29:08 +0000 (13:29 +0200)
Conflicts:
configure.ac
ext/ffmpeg/gstffmpegcodecmap.c
ext/ffmpeg/gstffmpegdeinterlace.c

1  2 
ext/ffmpeg/gstffmpegcodecmap.c
ext/ffmpeg/gstffmpegdec.c
ext/ffmpeg/gstffmpegdeinterlace.c

@@@ -2265,9 -2387,8 +2265,10 @@@ gst_ffmpeg_caps_with_codecid (enum Code
      }
  
      GST_DEBUG ("have codec data of size %d", size);
-   } else if (context->extradata == NULL && codec_id != CODEC_ID_AAC_LATM) {
 +
 +    gst_buffer_unmap (buf, data, size);
+   } else if (context->extradata == NULL && codec_id != CODEC_ID_AAC_LATM &&
+       codec_id != CODEC_ID_FLAC) {
      /* no extradata, alloc dummy with 0 sized, some codecs insist on reading
       * extradata anyway which makes then segfault. */
      context->extradata =
Simple merge
@@@ -85,84 -140,103 +139,125 @@@ G_DEFINE_TYPE (GstFFMpegDeinterlace, gs
  static GstFlowReturn gst_ffmpegdeinterlace_chain (GstPad * pad,
      GstBuffer * inbuf);
  
  static void
 -gst_ffmpegdeinterlace_base_init (gpointer g_class)
 -{
 -  GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
 -
 -  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));
 -  gst_element_class_set_details_simple (element_class,
 -      "FFMPEG Deinterlace element", "Filter/Effect/Video/Deinterlace",
 -      "Deinterlace video", "Luca Ognibene <luogni@tin.it>");
 -}
 -
 -static void
  gst_ffmpegdeinterlace_class_init (GstFFMpegDeinterlaceClass * klass)
  {
+   GObjectClass *gobject_class = (GObjectClass *) klass;
 +  GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
  
+   gobject_class->set_property = gst_ffmpegdeinterlace_set_property;
+   gobject_class->get_property = gst_ffmpegdeinterlace_get_property;
+   /**
+    * GstFFMpegDeinterlace:mode
+    *
+    * This selects whether the deinterlacing methods should
+    * always be applied or if they should only be applied
+    * on content that has the "interlaced" flag on the caps.
+    *
+    * Since: 0.10.13
+    */
+   g_object_class_install_property (gobject_class, PROP_MODE,
+       g_param_spec_enum ("mode", "Mode", "Deinterlace Mode",
+           GST_TYPE_FFMPEGDEINTERLACE_MODES,
+           DEFAULT_MODE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)
+       );
++
 +  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));
 +
 +  gst_element_class_set_details_simple (element_class,
 +      "FFMPEG Deinterlace element", "Filter/Effect/Video/Deinterlace",
 +      "Deinterlace video", "Luca Ognibene <luogni@tin.it>");
  }
  
+ static void
+ gst_ffmpegdeinterlace_update_passthrough (GstFFMpegDeinterlace * deinterlace)
+ {
+   deinterlace->passthrough =
+       (deinterlace->mode == GST_FFMPEGDEINTERLACE_MODE_DISABLED
+       || (!deinterlace->interlaced
+           && deinterlace->mode != GST_FFMPEGDEINTERLACE_MODE_INTERLACED));
+   GST_DEBUG_OBJECT (deinterlace, "Passthrough: %d", deinterlace->passthrough);
+ }
  static gboolean
- gst_ffmpegdeinterlace_sink_event (GstPad * pad, GstEvent * event)
+ gst_ffmpegdeinterlace_sink_setcaps (GstPad * pad, GstCaps * caps)
  {
    GstFFMpegDeinterlace *deinterlace =
        GST_FFMPEGDEINTERLACE (gst_pad_get_parent (pad));
-   gboolean ret = FALSE;
+   GstStructure *structure = gst_caps_get_structure (caps, 0);
+   AVCodecContext *ctx;
+   GstCaps *src_caps;
+   gboolean ret;
+   if (!gst_structure_get_int (structure, "width", &deinterlace->width))
+     return FALSE;
+   if (!gst_structure_get_int (structure, "height", &deinterlace->height))
+     return FALSE;
+   deinterlace->interlaced = FALSE;
+   gst_structure_get_boolean (structure, "interlaced", &deinterlace->interlaced);
+   gst_ffmpegdeinterlace_update_passthrough (deinterlace);
+   ctx = avcodec_alloc_context ();
+   ctx->width = deinterlace->width;
+   ctx->height = deinterlace->height;
+   ctx->pix_fmt = PIX_FMT_NB;
+   gst_ffmpeg_caps_with_codectype (AVMEDIA_TYPE_VIDEO, caps, ctx);
+   if (ctx->pix_fmt == PIX_FMT_NB) {
+     av_free (ctx);
+     return FALSE;
+   }
  
-   switch (GST_EVENT_TYPE (event)) {
-     case GST_EVENT_CAPS:
-     {
-       GstStructure *structure;
-       AVCodecContext *ctx;
-       GstCaps *caps, *src_caps;
+   deinterlace->pixfmt = ctx->pix_fmt;
  
-       gst_event_parse_caps (event, &caps);
-       structure = gst_caps_get_structure (caps, 0);
+   av_free (ctx);
  
-       if (!gst_structure_get_int (structure, "width", &deinterlace->width) ||
-           !gst_structure_get_int (structure, "height", &deinterlace->height)) {
-         goto done;
-       }
+   deinterlace->to_size =
+       avpicture_get_size (deinterlace->pixfmt, deinterlace->width,
+       deinterlace->height);
  
-       ctx = avcodec_alloc_context ();
-       ctx->width = deinterlace->width;
-       ctx->height = deinterlace->height;
-       ctx->pix_fmt = PIX_FMT_NB;
-       gst_ffmpeg_caps_with_codectype (AVMEDIA_TYPE_VIDEO, caps, ctx);
-       if (ctx->pix_fmt == PIX_FMT_NB) {
-         av_free (ctx);
-         goto done;
-       }
+   src_caps = gst_caps_copy (caps);
+   gst_caps_set_simple (src_caps, "interlaced", G_TYPE_BOOLEAN,
+       deinterlace->interlaced, NULL);
+   ret = gst_pad_set_caps (deinterlace->srcpad, src_caps);
+   gst_caps_unref (src_caps);
  
-       deinterlace->pixfmt = ctx->pix_fmt;
+   return ret;
+ }
  
-       av_free (ctx);
++static gboolean
++gst_ffmpegdeinterlace_sink_event (GstPad * pad, GstEvent * event)
++{
++  GstFFMpegDeinterlace *deinterlace =
++      GST_FFMPEGDEINTERLACE (gst_pad_get_parent (pad));
++  gboolean ret = FALSE;
 +
-       deinterlace->to_size =
-           avpicture_get_size (deinterlace->pixfmt, deinterlace->width,
-           deinterlace->height);
++  switch (GST_EVENT_TYPE (event)) {
++    case GST_EVENT_CAPS:
++    {
++      GstCaps *caps;
 +
-       src_caps = gst_caps_copy (caps);
++      gst_event_parse_caps (event, &caps);
++      ret = gst_ffmpegdeinterlace_sink_setcaps (pad, caps);
 +      gst_event_unref (event);
-       gst_caps_set_simple (src_caps, "interlaced", G_TYPE_BOOLEAN, FALSE, NULL);
-       event = gst_event_new_caps (src_caps);
-       gst_caps_unref (src_caps);
-     }
 +      break;
++    }
 +    default:
++      ret = gst_pad_push_event (deinterlace->srcpad, event);
 +      break;
 +  }
 +
-   ret = gst_pad_push_event (deinterlace->srcpad, event);
- done:
 +  gst_object_unref (deinterlace);
 +
 +  return ret;
 +}
 +
  static void
 -gst_ffmpegdeinterlace_init (GstFFMpegDeinterlace * deinterlace,
 -    GstFFMpegDeinterlaceClass * klass)
 +gst_ffmpegdeinterlace_init (GstFFMpegDeinterlace * deinterlace)
  {
    deinterlace->sinkpad =
        gst_pad_new_from_static_template (&sink_factory, "sink");
@@@ -185,27 -265,43 +286,49 @@@ gst_ffmpegdeinterlace_chain (GstPad * p
        GST_FFMPEGDEINTERLACE (gst_pad_get_parent (pad));
    GstBuffer *outbuf = NULL;
    GstFlowReturn result;
 +  guint8 *from_data, *to_data;
 +  gsize from_size, to_size;
  
 -    if (GST_PAD_CAPS (deinterlace->srcpad))
 -      gst_ffmpegdeinterlace_sink_setcaps (deinterlace->sinkpad,
 -          GST_PAD_CAPS (deinterlace->sinkpad));
+   GST_OBJECT_LOCK (deinterlace);
+   if (deinterlace->reconfigure) {
+     if (deinterlace->new_mode != -1)
+       deinterlace->mode = deinterlace->new_mode;
+     deinterlace->new_mode = -1;
+     deinterlace->reconfigure = FALSE;
+     GST_OBJECT_UNLOCK (deinterlace);
 -  result =
 -      gst_pad_alloc_buffer (deinterlace->srcpad, GST_BUFFER_OFFSET_NONE,
 -      deinterlace->to_size, GST_PAD_CAPS (deinterlace->srcpad), &outbuf);
 -  if (result == GST_FLOW_OK) {
 -    gst_ffmpeg_avpicture_fill (&deinterlace->from_frame,
 -        GST_BUFFER_DATA (inbuf), deinterlace->pixfmt, deinterlace->width,
 -        deinterlace->height);
++    if (gst_pad_has_current_caps (deinterlace->srcpad)) {
++      GstCaps *caps;
++
++      caps = gst_pad_get_current_caps (deinterlace->sinkpad);
++      gst_ffmpegdeinterlace_sink_setcaps (deinterlace->sinkpad, caps);
++      gst_caps_unref (caps);
++    }
+   } else {
+     GST_OBJECT_UNLOCK (deinterlace);
+   }
+   if (deinterlace->passthrough)
+     return gst_pad_push (deinterlace->srcpad, inbuf);
 +  outbuf = gst_buffer_new_and_alloc (deinterlace->to_size);
  
 -    gst_ffmpeg_avpicture_fill (&deinterlace->to_frame, GST_BUFFER_DATA (outbuf),
 -        deinterlace->pixfmt, deinterlace->width, deinterlace->height);
 +  from_data = gst_buffer_map (inbuf, &from_size, NULL, GST_MAP_READ);
 +  gst_ffmpeg_avpicture_fill (&deinterlace->from_frame, from_data,
 +      deinterlace->pixfmt, deinterlace->width, deinterlace->height);
  
 -    avpicture_deinterlace (&deinterlace->to_frame, &deinterlace->from_frame,
 -        deinterlace->pixfmt, deinterlace->width, deinterlace->height);
 +  to_data = gst_buffer_map (outbuf, &to_size, NULL, GST_MAP_WRITE);
 +  gst_ffmpeg_avpicture_fill (&deinterlace->to_frame, to_data,
 +      deinterlace->pixfmt, deinterlace->width, deinterlace->height);
  
 -    gst_buffer_copy_metadata (outbuf, inbuf, GST_BUFFER_COPY_TIMESTAMPS);
 +  avpicture_deinterlace (&deinterlace->to_frame, &deinterlace->from_frame,
 +      deinterlace->pixfmt, deinterlace->width, deinterlace->height);
 +  gst_buffer_unmap (outbuf, to_data, to_size);
 +  gst_buffer_unmap (inbuf, from_data, from_size);
  
 -    result = gst_pad_push (deinterlace->srcpad, outbuf);
 -  }
 +  gst_buffer_copy_into (outbuf, inbuf, GST_BUFFER_COPY_TIMESTAMPS, 0, -1);
 +
 +  result = gst_pad_push (deinterlace->srcpad, outbuf);
  
    gst_buffer_unref (inbuf);
  
@@@ -218,3 -314,52 +341,52 @@@ gst_ffmpegdeinterlace_register (GstPlug
    return gst_element_register (plugin, "ffdeinterlace",
        GST_RANK_NONE, GST_TYPE_FFMPEGDEINTERLACE);
  }
 -      if (self->mode != new_mode && GST_PAD_CAPS (self->srcpad)) {
+ static void
+ gst_ffmpegdeinterlace_set_property (GObject * object, guint prop_id,
+     const GValue * value, GParamSpec * pspec)
+ {
+   GstFFMpegDeinterlace *self;
+   g_return_if_fail (GST_IS_FFMPEGDEINTERLACE (object));
+   self = GST_FFMPEGDEINTERLACE (object);
+   switch (prop_id) {
+     case PROP_MODE:{
+       gint new_mode;
+       GST_OBJECT_LOCK (self);
+       new_mode = g_value_get_enum (value);
++      if (self->mode != new_mode && gst_pad_has_current_caps (self->srcpad)) {
+         self->reconfigure = TRUE;
+         self->new_mode = new_mode;
+       } else {
+         self->mode = new_mode;
+         gst_ffmpegdeinterlace_update_passthrough (self);
+       }
+       GST_OBJECT_UNLOCK (self);
+       break;
+     }
+     default:
+       G_OBJECT_WARN_INVALID_PROPERTY_ID (self, prop_id, pspec);
+   }
+ }
+ static void
+ gst_ffmpegdeinterlace_get_property (GObject * object, guint prop_id,
+     GValue * value, GParamSpec * pspec)
+ {
+   GstFFMpegDeinterlace *self;
+   g_return_if_fail (GST_IS_FFMPEGDEINTERLACE (object));
+   self = GST_FFMPEGDEINTERLACE (object);
+   switch (prop_id) {
+     case PROP_MODE:
+       g_value_set_enum (value, self->mode);
+       break;
+     default:
+       G_OBJECT_WARN_INVALID_PROPERTY_ID (self, prop_id, pspec);
+   }
+ }