diff --git a/gst/asfdemux/gstasfdemux.c b/gst/asfdemux/gstasfdemux.c
index 020d749..b056c36 100644
--- a/gst/asfdemux/gstasfdemux.c
+++ b/gst/asfdemux/gstasfdemux.c
@@ -49,7 +49,7 @@ static GstStaticPadTemplate gst_asf_demux_sink_template =
 GST_STATIC_PAD_TEMPLATE ("sink",
     GST_PAD_SINK,
     GST_PAD_ALWAYS,
-    GST_STATIC_CAPS ("video/x-ms-asf")
+    GST_STATIC_CAPS ("application/x-mms-framed; " "video/x-ms-asf")
     );
 
 static GstStaticPadTemplate audio_src_template =
@@ -238,6 +238,9 @@ gst_asf_demux_reset (GstASFDemux * demux, gboolean chain_reset)
   demux->state = GST_ASF_DEMUX_STATE_HEADER;
   demux->seekable = FALSE;
   demux->broadcast = FALSE;
+
+  /* do not reset the framed flag */
+
   demux->sidx_interval = 0;
   demux->sidx_num_entries = 0;
   g_free (demux->sidx_entries);
@@ -261,11 +264,31 @@ gst_asf_demux_reset (GstASFDemux * demux, gboolean chain_reset)
   }
 }
 
+static gboolean
+gst_asf_demux_setcaps (GstPad * pad, GstCaps * caps)
+{
+  GstStructure *structure;
+  GstASFDemux *demux;
+
+  g_return_val_if_fail (caps != NULL, FALSE);
+  g_return_val_if_fail (pad != NULL, FALSE);
+
+  demux = GST_ASF_DEMUX (gst_pad_get_parent (pad));
+
+  structure = gst_caps_get_structure (caps, 0);
+
+  demux->framed = gst_structure_has_name (structure, "application/x-mms-framed");
+
+  return TRUE;
+}
+
 static void
 gst_asf_demux_init (GstASFDemux * demux, GstASFDemuxClass * klass)
 {
   demux->sinkpad =
       gst_pad_new_from_static_template (&gst_asf_demux_sink_template, "sink");
+  gst_pad_set_setcaps_function (demux->sinkpad,
+      GST_DEBUG_FUNCPTR (gst_asf_demux_setcaps));
   gst_pad_set_chain_function (demux->sinkpad,
       GST_DEBUG_FUNCPTR (gst_asf_demux_chain));
   gst_pad_set_event_function (demux->sinkpad,
@@ -814,6 +837,65 @@ gst_asf_demux_release_old_pads (GstASFDemux * demux)
   demux->old_num_streams = 0;
 }
 
+#define GST_ASF_DEMUX_FRAME_OFFSET 12
+
+typedef enum {
+  GST_ASF_DEMUX_FRAME_OK,
+  GST_ASF_DEMUX_FRAME_ERROR,
+  GST_ASF_DEMUX_FRAME_NEED_MORE_DATA
+} GstAsfDemuxFrameStatus;
+
+
+
+static GstAsfDemuxFrameStatus
+gst_asf_demux_frame_available (GstASFDemux * demux)
+{
+	const guint8 *cdata = NULL;
+	guint16 frame_size, check_size;
+
+try_again:
+	if (!(cdata = (guint8 *) gst_adapter_peek (demux->adapter, 4)))
+		return GST_ASF_DEMUX_FRAME_NEED_MORE_DATA;
+
+	/* discard NUL padding */
+	if (G_UNLIKELY(cdata[0] == 0)) {
+		gst_adapter_flush(demux->adapter, 1);
+		goto try_again;
+	}
+
+	if (G_UNLIKELY((cdata[0] & 0x7f) != '$')) {
+	    GST_WARNING_OBJECT (demux, "bad frame boundary: %#2x", cdata[0]);
+		return GST_ASF_DEMUX_FRAME_ERROR;
+	}
+
+	frame_size = GST_READ_UINT16_LE (cdata+2);
+
+	if (gst_adapter_available(demux->adapter) < frame_size + 4)
+		return GST_ASF_DEMUX_FRAME_NEED_MORE_DATA;
+
+	if (cdata[1] != 'D' && cdata[1] != 'H') {
+		/* Discard all frames except header and data */
+	    GST_DEBUG_OBJECT (demux, "Discard frame of type %c", cdata[1]);
+		gst_adapter_flush(demux->adapter, frame_size + 4);
+		goto try_again;
+	}
+
+	cdata = (guint8 *) gst_adapter_peek (demux->adapter, GST_ASF_DEMUX_FRAME_OFFSET);
+	check_size = GST_READ_UINT16_LE (cdata+10);
+
+	if (G_UNLIKELY(frame_size != check_size)) {
+	    GST_WARNING_OBJECT (demux, "frame of type %c: size %u != check_size %u",
+	    		cdata[1], (unsigned)frame_size, (unsigned)check_size);
+		return GST_ASF_DEMUX_FRAME_ERROR;
+	}
+
+	if (cdata[1] == 'D')
+		/* maybe want to check for frame-to-frame consistency here */
+		demux->packet_size = frame_size - 8;
+
+	return GST_ASF_DEMUX_FRAME_OK;
+}
+
 static GstFlowReturn
 gst_asf_demux_chain_headers (GstASFDemux * demux)
 {
@@ -822,34 +904,50 @@ gst_asf_demux_chain_headers (GstASFDemux * demux)
   guint8 *header_data, *data = NULL;
   const guint8 *cdata = NULL;
   guint64 header_size;
+  guint frame_offset = 0;
+
+  if (demux->framed) {
+	  switch (gst_asf_demux_frame_available(demux)) {
+	  case GST_ASF_DEMUX_FRAME_OK:
+		  frame_offset = GST_ASF_DEMUX_FRAME_OFFSET;
+		  break;
+	  case GST_ASF_DEMUX_FRAME_NEED_MORE_DATA:
+		  goto need_more_data;
+	  case GST_ASF_DEMUX_FRAME_ERROR:
+		  goto wrong_type;
+	  default:
+	      g_assert_not_reached ();
+	  }
+  }
+
+  cdata = (guint8 *) gst_adapter_peek (demux->adapter, ASF_OBJECT_HEADER_SIZE + frame_offset);
 
-  cdata = (guint8 *) gst_adapter_peek (demux->adapter, ASF_OBJECT_HEADER_SIZE);
   if (cdata == NULL)
     goto need_more_data;
 
-  asf_demux_peek_object (demux, cdata, ASF_OBJECT_HEADER_SIZE, &obj, TRUE);
+  asf_demux_peek_object (demux, cdata + frame_offset, ASF_OBJECT_HEADER_SIZE, &obj, TRUE);
   if (obj.id != ASF_OBJ_HEADER)
     goto wrong_type;
 
   GST_LOG_OBJECT (demux, "header size = %u", (guint) obj.size);
 
   /* + 50 for non-packet data at beginning of ASF_OBJ_DATA */
-  if (gst_adapter_available (demux->adapter) < obj.size + 50)
+  if (gst_adapter_available (demux->adapter) < obj.size + 50 + frame_offset)
     goto need_more_data;
 
-  data = gst_adapter_take (demux->adapter, obj.size + 50);
+  data = gst_adapter_take (demux->adapter, obj.size + 50 + frame_offset);
 
-  header_data = data;
+  header_data = data + frame_offset;
   header_size = obj.size;
   flow = gst_asf_demux_process_object (demux, &header_data, &header_size);
   if (flow != GST_FLOW_OK)
     goto parse_failed;
 
   /* calculate where the packet data starts */
-  demux->data_offset = obj.size + 50;
+  demux->data_offset = obj.size + 50 + frame_offset;
 
   /* now parse the beginning of the ASF_OBJ_DATA object */
-  if (!gst_asf_demux_parse_data_object_start (demux, data + obj.size))
+  if (!gst_asf_demux_parse_data_object_start (demux, data + obj.size + frame_offset))
     goto wrong_type;
 
   if (demux->num_streams == 0)
@@ -1690,12 +1788,16 @@ static gint
 gst_asf_demux_check_header (GstASFDemux * demux)
 {
   AsfObject obj;
+  guint frame_offset = demux->framed ? GST_ASF_DEMUX_FRAME_OFFSET : 0;
+
+  /* it is guaranteed that gst_asf_demux_frame_available() will have already been called */
+
   guint8 *cdata = (guint8 *) gst_adapter_peek (demux->adapter,
-      ASF_OBJECT_HEADER_SIZE);
+      ASF_OBJECT_HEADER_SIZE + frame_offset);
   if (cdata == NULL)            /* need more data */
     return GST_ASF_DEMUX_CHECK_HEADER_NEED_DATA;
 
-  asf_demux_peek_object (demux, cdata, ASF_OBJECT_HEADER_SIZE, &obj, FALSE);
+  asf_demux_peek_object (demux, cdata + frame_offset, ASF_OBJECT_HEADER_SIZE, &obj, FALSE);
   if (obj.id != ASF_OBJ_HEADER) {
     return GST_ASF_DEMUX_CHECK_HEADER_NO;
   } else {
@@ -1732,7 +1834,20 @@ gst_asf_demux_chain (GstPad * pad, GstBuffer * buf)
 
   switch (demux->state) {
     case GST_ASF_DEMUX_STATE_INDEX:{
-      gint result = gst_asf_demux_check_header (demux);
+      gint result;
+      if(demux->framed) {
+     	switch (gst_asf_demux_frame_available(demux)) {
+    	case GST_ASF_DEMUX_FRAME_OK:
+    	  break;
+    	case GST_ASF_DEMUX_FRAME_NEED_MORE_DATA:
+    	  return GST_FLOW_OK;
+    	case GST_ASF_DEMUX_FRAME_ERROR:
+    	  return GST_FLOW_ERROR;
+    	default:
+	      g_assert_not_reached ();
+    	}
+      }
+      result = gst_asf_demux_check_header (demux);
       if (result == GST_ASF_DEMUX_CHECK_HEADER_NEED_DATA)       /* need more data */
         break;
 
@@ -1757,11 +1872,10 @@ gst_asf_demux_chain (GstPad * pad, GstBuffer * buf)
     }
     case GST_ASF_DEMUX_STATE_DATA:
     {
-      guint64 data_size;
-
-      data_size = demux->packet_size;
-
-      while (gst_adapter_available (demux->adapter) >= data_size) {
+      GstAsfDemuxFrameStatus frame_status = GST_ASF_DEMUX_FRAME_OK;
+      while (demux->framed
+    		? ((frame_status = gst_asf_demux_frame_available(demux)) == GST_ASF_DEMUX_FRAME_OK)
+    		: (gst_adapter_available (demux->adapter) >= demux->packet_size)) {
         GstBuffer *buf;
 
         /* we don't know the length of the stream
@@ -1781,7 +1895,9 @@ gst_asf_demux_chain (GstPad * pad, GstBuffer * buf)
           break;
         }
 
-        buf = gst_adapter_take_buffer (demux->adapter, data_size);
+        if (demux->framed)
+          gst_adapter_flush(demux->adapter, GST_ASF_DEMUX_FRAME_OFFSET);
+        buf = gst_adapter_take_buffer (demux->adapter, demux->packet_size);
 
         /* FIXME: maybe we should just skip broken packets and error out only
          * after a few broken packets in a row? */
@@ -1796,6 +1912,8 @@ gst_asf_demux_chain (GstPad * pad, GstBuffer * buf)
         if (demux->packet >= 0)
           ++demux->packet;
       }
+      if (G_UNLIKELY(frame_status == GST_ASF_DEMUX_FRAME_ERROR && ret == GST_FLOW_OK))
+    	  ret = GST_FLOW_ERROR;
       if (G_UNLIKELY (demux->num_packets != 0 && demux->packet >= 0
               && demux->packet >= demux->num_packets)) {
         demux->state = GST_ASF_DEMUX_STATE_INDEX;
diff --git a/gst/asfdemux/gstasfdemux.h b/gst/asfdemux/gstasfdemux.h
index 797c40f..939be46 100644
--- a/gst/asfdemux/gstasfdemux.h
+++ b/gst/asfdemux/gstasfdemux.h
@@ -174,6 +174,7 @@ struct _GstASFDemux {
 
   gboolean             seekable;
   gboolean             broadcast;
+  gboolean             framed;           /* application/x-mms-framed */
 
   GstSegment           segment;          /* configured play segment                 */
   gboolean             accurate;
