jpegformat: port to 0.11
authorWim Taymans <wim.taymans@collabora.co.uk>
Wed, 5 Oct 2011 18:06:20 +0000 (20:06 +0200)
committerWim Taymans <wim.taymans@collabora.co.uk>
Wed, 5 Oct 2011 18:06:20 +0000 (20:06 +0200)
gst/jpegformat/gstjifmux.c
gst/jpegformat/gstjpegparse.c

index 9bfcfc8..b9552b1 100644 (file)
@@ -114,58 +114,43 @@ static GstFlowReturn gst_jif_mux_chain (GstPad * pad, GstBuffer * buffer);
 static GstStateChangeReturn gst_jif_mux_change_state (GstElement * element,
     GstStateChange transition);
 
+#define gst_jif_mux_parent_class parent_class
+G_DEFINE_TYPE_WITH_CODE (GstJifMux, gst_jif_mux, GST_TYPE_ELEMENT,
+    G_IMPLEMENT_INTERFACE (GST_TYPE_TAG_SETTER, NULL);
+    G_IMPLEMENT_INTERFACE (GST_TYPE_TAG_XMP_WRITER, NULL));
 
 static void
-gst_jif_type_init (GType type)
+gst_jif_mux_class_init (GstJifMuxClass * klass)
 {
-  static const GInterfaceInfo tag_setter_info = { NULL, NULL, NULL };
-  static const GInterfaceInfo tag_xmp_writer_info = { NULL, NULL, NULL };
+  GObjectClass *gobject_class;
+  GstElementClass *gstelement_class;
 
-  g_type_add_interface_static (type, GST_TYPE_TAG_SETTER, &tag_setter_info);
-  g_type_add_interface_static (type, GST_TYPE_TAG_XMP_WRITER,
-      &tag_xmp_writer_info);
+  gobject_class = (GObjectClass *) klass;
+  gstelement_class = (GstElementClass *) klass;
 
-  GST_DEBUG_CATEGORY_INIT (jif_mux_debug, "jifmux", 0,
-      "JPEG interchange format muxer");
-}
+  g_type_class_add_private (gobject_class, sizeof (GstJifMuxPrivate));
 
-GST_BOILERPLATE_FULL (GstJifMux, gst_jif_mux, GstElement, GST_TYPE_ELEMENT,
-    gst_jif_type_init);
+  gobject_class->finalize = gst_jif_mux_finalize;
 
-static void
-gst_jif_mux_base_init (gpointer g_class)
-{
-  GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
+  gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_jif_mux_change_state);
 
-  gst_element_class_add_pad_template (element_class,
+  gst_element_class_add_pad_template (gstelement_class,
       gst_static_pad_template_get (&gst_jif_mux_src_pad_template));
-  gst_element_class_add_pad_template (element_class,
+  gst_element_class_add_pad_template (gstelement_class,
       gst_static_pad_template_get (&gst_jif_mux_sink_pad_template));
-  gst_element_class_set_details_simple (element_class,
+
+  gst_element_class_set_details_simple (gstelement_class,
       "JPEG stream muxer",
       "Video/Formatter",
       "Remuxes JPEG images with markers and tags",
       "Arnout Vandecappelle (Essensium/Mind) <arnout@mind.be>");
-}
-
-static void
-gst_jif_mux_class_init (GstJifMuxClass * klass)
-{
-  GObjectClass *gobject_class;
-  GstElementClass *gstelement_class;
-
-  gobject_class = (GObjectClass *) klass;
-  gstelement_class = (GstElementClass *) klass;
 
-  g_type_class_add_private (gobject_class, sizeof (GstJifMuxPrivate));
-
-  gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_jif_mux_change_state);
-
-  gobject_class->finalize = gst_jif_mux_finalize;
+  GST_DEBUG_CATEGORY_INIT (jif_mux_debug, "jifmux", 0,
+      "JPEG interchange format muxer");
 }
 
 static void
-gst_jif_mux_init (GstJifMux * self, GstJifMuxClass * g_class)
+gst_jif_mux_init (GstJifMux * self)
 {
   GstPad *sinkpad;
 
@@ -176,8 +161,6 @@ gst_jif_mux_init (GstJifMux * self, GstJifMuxClass * g_class)
   sinkpad = gst_pad_new_from_static_template (&gst_jif_mux_sink_pad_template,
       "sink");
   gst_pad_set_chain_function (sinkpad, GST_DEBUG_FUNCPTR (gst_jif_mux_chain));
-  gst_pad_set_setcaps_function (sinkpad,
-      GST_DEBUG_FUNCPTR (gst_jif_mux_sink_setcaps));
   gst_pad_set_event_function (sinkpad,
       GST_DEBUG_FUNCPTR (gst_jif_mux_sink_event));
   gst_element_add_pad (GST_ELEMENT (self), sinkpad);
@@ -219,6 +202,15 @@ gst_jif_mux_sink_event (GstPad * pad, GstEvent * event)
   gboolean ret;
 
   switch (GST_EVENT_TYPE (event)) {
+    case GST_EVENT_CAPS:
+    {
+      GstCaps *caps;
+
+      gst_event_parse_caps (event, &caps);
+      ret = gst_jif_mux_sink_setcaps (pad, caps);
+      gst_event_unref (event);
+      break;
+    }
     case GST_EVENT_TAG:{
       GstTagList *list;
       GstTagSetter *setter = GST_TAG_SETTER (self);
@@ -227,12 +219,14 @@ gst_jif_mux_sink_event (GstPad * pad, GstEvent * event)
       gst_event_parse_tag (event, &list);
 
       gst_tag_setter_merge_tags (setter, list, mode);
+
+      ret = gst_pad_event_default (pad, event);
       break;
     }
     default:
+      ret = gst_pad_event_default (pad, event);
       break;
   }
-  ret = gst_pad_event_default (pad, event);
   return ret;
 }
 
@@ -276,13 +270,18 @@ gst_jif_mux_new_marker (guint8 marker, guint16 size, const guint8 * data,
 static gboolean
 gst_jif_mux_parse_image (GstJifMux * self, GstBuffer * buf)
 {
-  GstByteReader reader = GST_BYTE_READER_INIT_FROM_BUFFER (buf);
+  GstByteReader reader;
   GstJifMuxMarker *m;
   guint8 marker = 0;
   guint16 size = 0;
   const guint8 *data = NULL;
+  guint8 *bdata;
+  gsize bsize;
+
+  bdata = gst_buffer_map (buf, &bsize, NULL, GST_MAP_READ);
+  gst_byte_reader_init (&reader, bdata, bsize);
 
-  GST_LOG_OBJECT (self, "Received buffer of size: %u", GST_BUFFER_SIZE (buf));
+  GST_LOG_OBJECT (self, "Received buffer of size: %u", bsize);
 
   if (!gst_byte_reader_peek_uint8 (&reader, &marker))
     goto error;
@@ -330,21 +329,23 @@ gst_jif_mux_parse_image (GstJifMux * self, GstBuffer * buf)
     if (marker == SOS) {
       gint eoi_pos = -1;
       gint i;
+      guint8 *mdata;
+      gsize msize;
 
       /* search the last 5 bytes for the EOI marker */
-      g_assert (GST_BUFFER_SIZE (buf) >= 5);
+      mdata = gst_buffer_map (buf, &msize, NULL, GST_MAP_READ);
+      g_assert (msize >= 5);
       for (i = 5; i >= 2; i--) {
-        if (GST_BUFFER_DATA (buf)[GST_BUFFER_SIZE (buf) - i] == 0xFF &&
-            GST_BUFFER_DATA (buf)[GST_BUFFER_SIZE (buf) - i + 1] == EOI) {
-          eoi_pos = GST_BUFFER_SIZE (buf) - i;
+        if (mdata[msize - i] == 0xFF && mdata[msize - i + 1] == EOI) {
+          eoi_pos = msize - i;
           break;
         }
       }
-
       if (eoi_pos == -1) {
         GST_WARNING_OBJECT (self, "Couldn't find an EOI marker");
-        eoi_pos = GST_BUFFER_SIZE (buf);
+        eoi_pos = msize;
       }
+      gst_buffer_unmap (buf, mdata, msize);
 
       /* remaining size except EOI is scan data */
       self->priv->scan_size = eoi_pos - gst_byte_reader_get_pos (&reader);
@@ -359,17 +360,23 @@ gst_jif_mux_parse_image (GstJifMux * self, GstBuffer * buf)
       goto error;
   }
   GST_INFO_OBJECT (self, "done parsing at 0x%x / 0x%x",
-      gst_byte_reader_get_pos (&reader), GST_BUFFER_SIZE (buf));
+      gst_byte_reader_get_pos (&reader), bsize);
 
 done:
   self->priv->markers = g_list_reverse (self->priv->markers);
+  gst_buffer_unmap (buf, bdata, bsize);
+
   return TRUE;
 
+  /* ERRORS */
 error:
-  GST_WARNING_OBJECT (self,
-      "Error parsing image header (need more that %u bytes available)",
-      gst_byte_reader_get_remaining (&reader));
-  return FALSE;
+  {
+    GST_WARNING_OBJECT (self,
+        "Error parsing image header (need more that %u bytes available)",
+        gst_byte_reader_get_remaining (&reader));
+    gst_buffer_unmap (buf, bdata, bsize);
+    return FALSE;
+  }
 }
 
 static gboolean
@@ -531,25 +538,25 @@ gst_jif_mux_mangle_markers (GstJifMux * self)
   /* Add EXIF */
   {
     GstBuffer *exif_data;
+    gsize exif_size;
     guint8 *data;
     GstJifMuxMarker *m;
     GList *pos;
 
     /* insert into self->markers list */
     exif_data = gst_tag_list_to_exif_buffer_with_tiff_header (tags);
-    if (exif_data &&
-        GST_BUFFER_SIZE (exif_data) + 8 >= G_GUINT64_CONSTANT (65536)) {
+    exif_size = exif_data ? gst_buffer_get_size (exif_data) : 0;
+
+    if (exif_data && exif_size + 8 >= G_GUINT64_CONSTANT (65536)) {
       GST_WARNING_OBJECT (self, "Exif tags data size exceed maximum size");
       gst_buffer_unref (exif_data);
       exif_data = NULL;
     }
     if (exif_data) {
-      data = g_malloc0 (GST_BUFFER_SIZE (exif_data) + 6);
+      data = g_malloc0 (exif_size + 6);
       memcpy (data, "Exif", 4);
-      memcpy (data + 6, GST_BUFFER_DATA (exif_data),
-          GST_BUFFER_SIZE (exif_data));
-      m = gst_jif_mux_new_marker (APP1, GST_BUFFER_SIZE (exif_data) + 6, data,
-          TRUE);
+      gst_buffer_extract (exif_data, 0, data + 6, exif_size);
+      m = gst_jif_mux_new_marker (APP1, exif_size + 6, data, TRUE);
       gst_buffer_unref (exif_data);
 
       if (app1_exif) {
@@ -578,13 +585,14 @@ gst_jif_mux_mangle_markers (GstJifMux * self)
       gst_tag_xmp_writer_tag_list_to_xmp_buffer (GST_TAG_XMP_WRITER (self),
       tags, FALSE);
   if (xmp_data) {
-    guint8 *data, *xmp = GST_BUFFER_DATA (xmp_data);
-    guint size = GST_BUFFER_SIZE (xmp_data);
+    guint8 *data;
+    gsize size;
     GList *pos;
 
+    size = gst_buffer_get_size (xmp_data);
     data = g_malloc (size + 29);
     memcpy (data, "http://ns.adobe.com/xap/1.0/\0", 29);
-    memcpy (&data[29], xmp, size);
+    gst_buffer_extract (xmp_data, 0, &data[29], size);
     m = gst_jif_mux_new_marker (APP1, size + 29, data, TRUE);
 
     /*
@@ -640,11 +648,12 @@ gst_jif_mux_recombine_image (GstJifMux * self, GstBuffer ** new_buf,
 {
   GstBuffer *buf;
   GstByteWriter *writer;
-  GstFlowReturn fret;
   GstJifMuxMarker *m;
   GList *node;
   guint size = self->priv->scan_size;
   gboolean writer_status = TRUE;
+  guint8 *bdata;
+  gsize bsize;
 
   /* iterate list and collect size */
   for (node = self->priv->markers; node; node = g_list_next (node)) {
@@ -658,21 +667,19 @@ gst_jif_mux_recombine_image (GstJifMux * self, GstBuffer ** new_buf,
     size += 2;
   }
   GST_INFO_OBJECT (self, "old size: %u, new size: %u",
-      GST_BUFFER_SIZE (old_buf), size);
+      gst_buffer_get_size (old_buf), size);
 
   /* allocate new buffer */
-  fret = gst_pad_alloc_buffer_and_set_caps (self->priv->srcpad,
-      GST_BUFFER_OFFSET (old_buf), size, GST_PAD_CAPS (self->priv->srcpad),
-      &buf);
-  if (fret != GST_FLOW_OK)
-    goto no_buffer;
+  buf = gst_buffer_new_allocate (NULL, size, 0);
 
   /* copy buffer metadata */
-  gst_buffer_copy_metadata (buf, old_buf,
-      GST_BUFFER_COPY_FLAGS | GST_BUFFER_COPY_TIMESTAMPS);
+  gst_buffer_copy_into (buf, old_buf,
+      GST_BUFFER_COPY_FLAGS | GST_BUFFER_COPY_TIMESTAMPS, 0, -1);
 
   /* memcopy markers */
-  writer = gst_byte_writer_new_with_buffer (buf, TRUE);
+  bdata = gst_buffer_map (buf, &bsize, NULL, GST_MAP_WRITE);
+  writer = gst_byte_writer_new_with_data (bdata, bsize, TRUE);
+
   for (node = self->priv->markers; node && writer_status;
       node = g_list_next (node)) {
     m = (GstJifMuxMarker *) node->data;
@@ -694,6 +701,7 @@ gst_jif_mux_recombine_image (GstJifMux * self, GstBuffer ** new_buf,
           self->priv->scan_size);
     }
   }
+  gst_buffer_unmap (buf, bdata, bsize);
   gst_byte_writer_free (writer);
 
   if (!writer_status) {
@@ -704,11 +712,6 @@ gst_jif_mux_recombine_image (GstJifMux * self, GstBuffer ** new_buf,
 
   *new_buf = buf;
   return GST_FLOW_OK;
-
-no_buffer:
-  GST_WARNING_OBJECT (self, "failed to allocate output buffer, flow_ret = %s",
-      gst_flow_get_name (fret));
-  return fret;
 }
 
 static GstFlowReturn
@@ -717,15 +720,11 @@ gst_jif_mux_chain (GstPad * pad, GstBuffer * buf)
   GstJifMux *self = GST_JIF_MUX (GST_PAD_PARENT (pad));
   GstFlowReturn fret = GST_FLOW_OK;
 
-  if (GST_BUFFER_CAPS (buf) == NULL) {
-    GST_WARNING_OBJECT (self, "Rejecting buffer without caps");
-    gst_buffer_unref (buf);
-    return GST_FLOW_NOT_NEGOTIATED;
-  }
-
+#if 0
   GST_MEMDUMP ("jpeg beg", GST_BUFFER_DATA (buf), 64);
   GST_MEMDUMP ("jpeg end", GST_BUFFER_DATA (buf) + GST_BUFFER_SIZE (buf) - 64,
       64);
+#endif
 
   /* we should have received a whole picture from SOI to EOI
    * build a list of markers */
index 64b16ae..fd977dc 100644 (file)
@@ -59,7 +59,7 @@ GST_STATIC_PAD_TEMPLATE ("src",
     GST_PAD_SRC,
     GST_PAD_ALWAYS,
     GST_STATIC_CAPS ("image/jpeg, "
-        "format = (fourcc) { I420, Y41B, UYVY, YV12 }, "
+        "format = (string) { I420, Y41B, UYVY, YV12 }, "
         "width = (int) [ 0, MAX ],"
         "height = (int) [ 0, MAX ], "
         "interlaced = (boolean) { true, false }, "
@@ -99,8 +99,8 @@ struct _GstJpegParsePrivate
   /* TRUE if the image is interlaced */
   gboolean interlaced;
 
-  /* fourcc color space */
-  guint32 fourcc;
+  /* format color space */
+  const gchar *format;
 
   /* TRUE if the src caps sets a specific framerate */
   gboolean has_fps;
@@ -124,31 +124,12 @@ static void gst_jpeg_parse_dispose (GObject * object);
 static GstFlowReturn gst_jpeg_parse_chain (GstPad * pad, GstBuffer * buffer);
 static gboolean gst_jpeg_parse_sink_setcaps (GstPad * pad, GstCaps * caps);
 static gboolean gst_jpeg_parse_sink_event (GstPad * pad, GstEvent * event);
-static GstCaps *gst_jpeg_parse_src_getcaps (GstPad * pad);
+static GstCaps *gst_jpeg_parse_src_getcaps (GstPad * pad, GstCaps * filter);
 static GstStateChangeReturn gst_jpeg_parse_change_state (GstElement * element,
     GstStateChange transition);
 
-#define _do_init(bla) \
-  GST_DEBUG_CATEGORY_INIT (jpeg_parse_debug, "jpegparse", 0, "JPEG parser");
-
-GST_BOILERPLATE_FULL (GstJpegParse, gst_jpeg_parse, GstElement,
-    GST_TYPE_ELEMENT, _do_init);
-
-static void
-gst_jpeg_parse_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 (&gst_jpeg_parse_src_pad_template));
-  gst_element_class_add_pad_template (element_class,
-      gst_static_pad_template_get (&gst_jpeg_parse_sink_pad_template));
-  gst_element_class_set_details_simple (element_class,
-      "JPEG stream parser",
-      "Video/Parser",
-      "Parse JPEG images into single-frame buffers",
-      "Arnout Vandecappelle (Essensium/Mind) <arnout@mind.be>");
-}
+#define gst_jpeg_parse_parent_class parent_class
+G_DEFINE_TYPE (GstJpegParse, gst_jpeg_parse, GST_TYPE_ELEMENT);
 
 static void
 gst_jpeg_parse_class_init (GstJpegParseClass * klass)
@@ -164,10 +145,23 @@ gst_jpeg_parse_class_init (GstJpegParseClass * klass)
 
   gstelement_class->change_state =
       GST_DEBUG_FUNCPTR (gst_jpeg_parse_change_state);
+
+  gst_element_class_add_pad_template (gstelement_class,
+      gst_static_pad_template_get (&gst_jpeg_parse_src_pad_template));
+  gst_element_class_add_pad_template (gstelement_class,
+      gst_static_pad_template_get (&gst_jpeg_parse_sink_pad_template));
+
+  gst_element_class_set_details_simple (gstelement_class,
+      "JPEG stream parser",
+      "Video/Parser",
+      "Parse JPEG images into single-frame buffers",
+      "Arnout Vandecappelle (Essensium/Mind) <arnout@mind.be>");
+
+  GST_DEBUG_CATEGORY_INIT (jpeg_parse_debug, "jpegparse", 0, "JPEG parser");
 }
 
 static void
-gst_jpeg_parse_init (GstJpegParse * parse, GstJpegParseClass * g_class)
+gst_jpeg_parse_init (GstJpegParse * parse)
 {
   GstPad *sinkpad;
 
@@ -181,8 +175,6 @@ gst_jpeg_parse_init (GstJpegParse * parse, GstJpegParseClass * g_class)
       GST_DEBUG_FUNCPTR (gst_jpeg_parse_chain));
   gst_pad_set_event_function (sinkpad,
       GST_DEBUG_FUNCPTR (gst_jpeg_parse_sink_event));
-  gst_pad_set_setcaps_function (sinkpad,
-      GST_DEBUG_FUNCPTR (gst_jpeg_parse_sink_setcaps));
   gst_element_add_pad (GST_ELEMENT (parse), sinkpad);
 
   parse->priv->srcpad =
@@ -234,12 +226,11 @@ gst_jpeg_parse_sink_setcaps (GstPad * pad, GstCaps * caps)
 }
 
 static GstCaps *
-gst_jpeg_parse_src_getcaps (GstPad * pad)
+gst_jpeg_parse_src_getcaps (GstPad * pad, GstCaps * filter)
 {
   GstCaps *result;
 
-  if ((result = GST_PAD_CAPS (pad))) {
-    result = gst_caps_ref (result);
+  if ((result = gst_pad_get_current_caps (pad))) {
     GST_DEBUG_OBJECT (pad, "using pad caps %" GST_PTR_FORMAT, result);
   } else {
     result = gst_caps_ref (GST_PAD_TEMPLATE_CAPS (GST_PAD_PAD_TEMPLATE (pad)));
@@ -487,21 +478,21 @@ gst_jpeg_parse_sof (GstJpegParse * parse, GstByteReader * reader)
   }
 
   if (numcomps == 1) {
-    /* gray image - no fourcc */
-    parse->priv->fourcc = 0;
+    /* gray image - no format */
+    parse->priv->format = "";
   } else if (numcomps == 3) {
     temp = (blockWidth[0] * blockHeight[0]) / (blockWidth[1] * blockHeight[1]);
 
     if (temp == 4 && blockHeight[0] == 2)
-      parse->priv->fourcc = GST_MAKE_FOURCC ('I', '4', '2', '0');
+      parse->priv->format = "I420";
     else if (temp == 4 && blockHeight[0] == 4)
-      parse->priv->fourcc = GST_MAKE_FOURCC ('Y', '4', '1', 'B');
+      parse->priv->format = "Y41B";
     else if (temp == 2)
-      parse->priv->fourcc = GST_MAKE_FOURCC ('U', 'Y', 'V', 'Y');
+      parse->priv->format = "UYVY";
     else if (temp == 1)
-      parse->priv->fourcc = GST_MAKE_FOURCC ('Y', 'V', '1', '2');
+      parse->priv->format = "YV12";
     else
-      parse->priv->fourcc = 0;
+      parse->priv->format = "";
   } else {
     return FALSE;
   }
@@ -517,7 +508,8 @@ gst_jpeg_parse_remove_marker (GstJpegParse * parse,
 {
   guint16 size = 0;
   guint pos = gst_byte_reader_get_pos (reader);
-  guint8 *data = GST_BUFFER_DATA (buffer);
+  guint8 *data;
+  gsize bsize;
 
   if (!gst_byte_reader_peek_uint16_be (reader, &size))
     return FALSE;
@@ -526,9 +518,9 @@ gst_jpeg_parse_remove_marker (GstJpegParse * parse,
 
   GST_LOG_OBJECT (parse, "unhandled marker %x removing %u bytes", marker, size);
 
-  memmove (&data[pos], &data[pos + size],
-      GST_BUFFER_SIZE (buffer) - (pos + size));
-  GST_BUFFER_SIZE (buffer) -= size;
+  data = gst_buffer_map (buffer, &bsize, NULL, GST_MAP_READWRITE);
+  memmove (&data[pos], &data[pos + size], bsize - (pos + size));
+  gst_buffer_unmap (buffer, data, bsize - size);
 
   if (!gst_byte_reader_set_pos (reader, pos - size))
     return FALSE;
@@ -579,14 +571,12 @@ get_tag_list (GstJpegParse * parse)
 
 static inline void
 extract_and_queue_tags (GstJpegParse * parse, guint size, guint8 * data,
-    GstTagList * (*tag_func) (const GstBuffer * buff))
+    GstTagList * (*tag_func) (GstBuffer * buff))
 {
   GstTagList *tags;
   GstBuffer *buf;
 
-  buf = gst_buffer_new ();
-  GST_BUFFER_DATA (buf) = data;
-  GST_BUFFER_SIZE (buf) = size;
+  buf = gst_buffer_new_wrapped_full (data, NULL, 0, size);
 
   tags = tag_func (buf);
   gst_buffer_unref (buf);
@@ -702,9 +692,14 @@ gst_jpeg_parse_com (GstJpegParse * parse, GstByteReader * reader)
 static gboolean
 gst_jpeg_parse_read_header (GstJpegParse * parse, GstBuffer * buffer)
 {
-  GstByteReader reader = GST_BYTE_READER_INIT_FROM_BUFFER (buffer);
+  GstByteReader reader;
   guint8 marker = 0;
   gboolean foundSOF = FALSE;
+  guint8 *data;
+  gsize size;
+
+  data = gst_buffer_map (buffer, &size, NULL, GST_MAP_READ);
+  gst_byte_reader_init (&reader, data, size);
 
   if (!gst_byte_reader_peek_uint8 (&reader, &marker))
     goto error;
@@ -720,7 +715,7 @@ gst_jpeg_parse_read_header (GstJpegParse * parse, GstBuffer * buffer)
 
     switch (marker) {
       case SOS:                /* start of scan (begins compressed data) */
-        return foundSOF;
+        goto done;
 
       case SOI:
         break;
@@ -751,12 +746,12 @@ gst_jpeg_parse_read_header (GstJpegParse * parse, GstBuffer * buffer)
         parse->priv->interlaced = TRUE;
         /* fall through */
       case SOF0:
-        foundSOF = TRUE;
         /* parse Start Of Frame */
         if (!gst_jpeg_parse_sof (parse, &reader))
           goto error;
 
-        return TRUE;
+        foundSOF = TRUE;
+        goto done;
 
       default:
         if (marker == JPG || (marker >= JPG0 && marker <= JPG13)) {
@@ -766,25 +761,35 @@ gst_jpeg_parse_read_header (GstJpegParse * parse, GstBuffer * buffer)
         } else if (marker >= APP0 && marker <= APP15) {
           if (!gst_jpeg_parse_skip_marker (parse, &reader, marker))
             goto error;
-        } else {
-          GST_WARNING_OBJECT (parse, "unhandled marker %x, leaving", marker);
-          /* Not SOF or SOI.  Must not be a JPEG file (or file pointer
-           * is placed wrong).  In either case, it's an error. */
-          return FALSE;
-        }
+        } else
+          goto unhandled;
     }
 
     if (!gst_byte_reader_peek_uint8 (&reader, &marker))
       goto error;
   }
+done:
+  gst_buffer_unmap (buffer, data, size);
 
   return foundSOF;
 
+  /* ERRORS */
 error:
-  GST_WARNING_OBJECT (parse,
-      "Error parsing image header (need more than %u bytes available)",
-      gst_byte_reader_get_remaining (&reader));
-  return FALSE;
+  {
+    GST_WARNING_OBJECT (parse,
+        "Error parsing image header (need more than %u bytes available)",
+        gst_byte_reader_get_remaining (&reader));
+    gst_buffer_unmap (buffer, data, size);
+    return FALSE;
+  }
+unhandled:
+  {
+    GST_WARNING_OBJECT (parse, "unhandled marker %x, leaving", marker);
+    /* Not SOF or SOI.  Must not be a JPEG file (or file pointer
+     * is placed wrong).  In either case, it's an error. */
+    gst_buffer_unmap (buffer, data, size);
+    return FALSE;
+  }
 }
 
 static gboolean
@@ -801,7 +806,7 @@ gst_jpeg_parse_set_new_caps (GstJpegParse * parse, gboolean header_ok)
 
   if (header_ok == TRUE) {
     gst_caps_set_simple (caps,
-        "format", GST_TYPE_FOURCC, parse->priv->fourcc,
+        "format", G_TYPE_STRING, parse->priv->format,
         "interlaced", G_TYPE_BOOLEAN, parse->priv->interlaced,
         "width", G_TYPE_INT, parse->priv->width,
         "height", G_TYPE_INT, parse->priv->height, NULL);
@@ -896,8 +901,6 @@ gst_jpeg_parse_push_buffer (GstJpegParse * parse, guint len)
 
   GST_BUFFER_DURATION (outbuf) = parse->priv->duration;
 
-  gst_buffer_set_caps (outbuf, GST_PAD_CAPS (parse->priv->srcpad));
-
   GST_LOG_OBJECT (parse, "pushing buffer (ts=%" GST_TIME_FORMAT ", len=%u)",
       GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (outbuf)), len);
 
@@ -957,6 +960,15 @@ gst_jpeg_parse_sink_event (GstPad * pad, GstEvent * event)
   GST_DEBUG_OBJECT (parse, "event : %s", GST_EVENT_TYPE_NAME (event));
 
   switch (GST_EVENT_TYPE (event)) {
+    case GST_EVENT_CAPS:
+    {
+      GstCaps *caps;
+
+      gst_event_parse_caps (event, &caps);
+      res = gst_jpeg_parse_sink_setcaps (pad, caps);
+      gst_event_unref (event);
+      break;
+    }
     case GST_EVENT_FLUSH_STOP:
       parse->priv->next_ts = GST_CLOCK_TIME_NONE;
       parse->priv->last_offset = 0;
@@ -972,7 +984,7 @@ gst_jpeg_parse_sink_event (GstPad * pad, GstEvent * event)
       res = gst_pad_push_event (parse->priv->srcpad, event);
       break;
     }
-    case GST_EVENT_NEWSEGMENT:
+    case GST_EVENT_SEGMENT:
       /* Discard any data in the adapter.  There should have been an EOS before
        * to flush it. */
       gst_adapter_clear (parse->priv->adapter);