From 389480c0a11c134b963fe4d249d49549db519dec Mon Sep 17 00:00:00 2001
From: Kazunori Kobayashi <kkobayas@igel.co.jp>
Date: Tue, 18 Jun 2013 12:28:32 +0900
Subject: [PATCH 2/2] asfdemux/asfpacket: set frame start code to VC-1 advanced
 profile stream

VC-1 advanced profile constrains the bitstream format to pair
the frame data with the frame start code.
---
 gst/asfdemux/asfpacket.c | 73 ++++++++++++++++++++++++++++++++++++++++++++----
 1 file changed, 67 insertions(+), 6 deletions(-)

diff --git a/gst/asfdemux/asfpacket.c b/gst/asfdemux/asfpacket.c
index 12eede8..7b72aa0 100644
--- a/gst/asfdemux/asfpacket.c
+++ b/gst/asfdemux/asfpacket.c
@@ -72,7 +72,7 @@ asf_packet_read_varlen_int (guint lentype_flags, guint lentype_bit_offset,
 
 static GstBuffer *
 asf_packet_create_payload_buffer (AsfPacket * packet, const guint8 ** p_data,
-    guint * p_size, guint payload_len)
+    guint * p_size, guint payload_len, gboolean need_st_code)
 {
   guint off;
 
@@ -84,6 +84,39 @@ asf_packet_create_payload_buffer (AsfPacket * packet, const guint8 ** p_data,
   *p_data += payload_len;
   *p_size -= payload_len;
 
+  /* set start code for VC-1 advanced profile */
+  if (need_st_code && off >= 4) {
+    const guint8 *pos;
+
+    pos = packet->bdata + off;
+    /* check if this packet has a start code */
+    if (pos[0] != 0x00 || pos[1] != 0x00 || pos[2] != 0x01 || pos[3] != 0x0d) {
+      GstBuffer *subbuf;
+      GstMapInfo map;
+
+      subbuf = gst_buffer_copy_region (packet->buf, GST_BUFFER_COPY_ALL,
+          off - 4, payload_len + 4);
+      if (subbuf == NULL) {
+        GST_ERROR ("Failed to create a sub-buffer");
+        return NULL;
+      }
+
+      if (!gst_buffer_map (subbuf, &map, GST_MAP_WRITE)) {
+        GST_ERROR ("Failed to create a gstbuffer mapping");
+        return NULL;
+      }
+
+      map.data[0] = 0x00;
+      map.data[1] = 0x00;
+      map.data[2] = 0x01;
+      map.data[3] = 0x0d;
+
+      gst_buffer_unmap (subbuf, &map);
+
+      return subbuf;
+    }
+  }
+
   return gst_buffer_copy_region (packet->buf, GST_BUFFER_COPY_ALL, off,
       payload_len);
 }
@@ -284,6 +317,9 @@ gst_asf_demux_parse_payload (GstASFDemux * demux, AsfPacket * packet,
   gboolean is_compressed;
   guint payload_len;
   guint stream_num;
+  GstStructure *structure;
+  const gchar *fourcc;
+  gboolean need_st_code = FALSE;
 
   if (G_UNLIKELY (*p_size < 1)) {
     GST_WARNING_OBJECT (demux, "Short packet!");
@@ -363,6 +399,18 @@ gst_asf_demux_parse_payload (GstASFDemux * demux, AsfPacket * packet,
     return TRUE;
   }
 
+  structure = gst_caps_get_structure (stream->caps, 0);
+  fourcc = gst_structure_get_string (structure, "format");
+  if (fourcc) {
+    /*
+     * set start code for VC-1 advanced profile if fourcc is 'WVC1' and this
+     * packet is at the head of a payload.
+     */
+    if (strncmp (fourcc, "WVC1", strlen ("WVC1")) == 0
+        && payload.mo_offset == 0)
+      need_st_code = TRUE;
+  }
+
   if (G_UNLIKELY (!is_compressed)) {
     GST_LOG_OBJECT (demux, "replicated data length: %u", payload.rep_data_len);
 
@@ -397,7 +445,7 @@ gst_asf_demux_parse_payload (GstASFDemux * demux, AsfPacket * packet,
       /* if the media object is not fragmented, just create a sub-buffer */
       GST_LOG_OBJECT (demux, "unfragmented media object size %u", payload_len);
       payload.buf = asf_packet_create_payload_buffer (packet, p_data, p_size,
-          payload_len);
+          payload_len, need_st_code);
       payload.buf_filled = payload_len;
       gst_asf_payload_queue_for_stream (demux, &payload, stream);
     } else {
@@ -437,11 +485,24 @@ gst_asf_demux_parse_payload (GstASFDemux * demux, AsfPacket * packet,
               "any previous fragment, ignoring payload");
         }
       } else {
+        const guint8 st_code[] = { 0x00, 0x00, 0x01, 0x0d };
+
         GST_LOG_OBJECT (demux, "allocating buffer of size %u for fragmented "
             "media object", payload.mo_size);
-        payload.buf = gst_buffer_new_allocate (NULL, payload.mo_size, NULL);
-        gst_buffer_fill (payload.buf, 0, payload_data, payload_len);
-        payload.buf_filled = payload_len;
+        if ((payload_data[0] != 0x00 || payload_data[1] != 0x00 ||
+                payload_data[2] != 0x01 || payload_data[3] != 0x0d) &&
+            need_st_code) {
+          /* set start code for VC-1 advanced profile */
+          payload.buf =
+              gst_buffer_new_allocate (NULL, payload.mo_size + 4, NULL);
+          gst_buffer_fill (payload.buf, 0, st_code, sizeof (st_code));
+          gst_buffer_fill (payload.buf, 4, payload_data, payload_len);
+          payload.buf_filled = payload_len + sizeof (st_code);
+        } else {
+          payload.buf = gst_buffer_new_allocate (NULL, payload.mo_size, NULL);
+          gst_buffer_fill (payload.buf, 0, payload_data, payload_len);
+          payload.buf_filled = payload_len;
+        }
 
         gst_asf_payload_queue_for_stream (demux, &payload, stream);
       }
@@ -483,7 +544,7 @@ gst_asf_demux_parse_payload (GstASFDemux * demux, AsfPacket * packet,
 
       if (G_LIKELY (sub_payload_len > 0)) {
         payload.buf = asf_packet_create_payload_buffer (packet,
-            &payload_data, &payload_len, sub_payload_len);
+            &payload_data, &payload_len, sub_payload_len, need_st_code);
         payload.buf_filled = sub_payload_len;
 
         payload.ts = ts;
-- 
1.8.1.2