dvdepay: don't output frames until we have a header
authorWim Taymans <wim.taymans@collabora.co.uk>
Mon, 22 Feb 2010 17:20:46 +0000 (18:20 +0100)
committerWim Taymans <wim.taymans@collabora.co.uk>
Tue, 23 Feb 2010 11:54:36 +0000 (12:54 +0100)
Wait for the complete first 6 header DIF packets before outputting a frame.
Decoders need this info to correctly decode the data.

Fixes #610556

gst/rtp/gstrtpdvdepay.c
gst/rtp/gstrtpdvdepay.h

index d1c27448404ec075a21ae3099d83629fff9beb9e..50b1a418feefca7ece062c76a189ae438ec390a0 100644 (file)
@@ -264,22 +264,22 @@ calculate_difblock_location (guint8 * block)
   dif_sequence = block[1] >> 4;
   dif_block = block[2];
 
+  location = dif_sequence * 150;
+
   switch (block_type) {
-    case 0:                    /* Header block */
-      location = dif_sequence * 150 * 80;
+    case 0:                    /* Header block, no offset */
       break;
     case 1:                    /* Subcode block */
-      location = dif_sequence * 150 * 80 + (1 + dif_block) * 80;
+      location += (1 + dif_block);
       break;
     case 2:                    /* VAUX block */
-      location = dif_sequence * 150 * 80 + (3 + dif_block) * 80;
+      location += (3 + dif_block);
       break;
     case 3:                    /* Audio block */
-      location = dif_sequence * 150 * 80 + (6 + dif_block * 16) * 80;
+      location += (6 + dif_block * 16);
       break;
     case 4:                    /* Video block */
-      location = dif_sequence * 150 * 80 +
-          (7 + (dif_block / 15) + dif_block) * 80;
+      location += (7 + (dif_block / 15) + dif_block);
       break;
     default:                   /* Something bogus */
       GST_DEBUG ("UNKNOWN BLOCK");
@@ -327,28 +327,43 @@ gst_rtp_dv_depay_process (GstBaseRTPDepayload * base, GstBuffer * in)
 
   /* copy all DIF chunks in their place. */
   while (payload_len >= 80) {
+    guint offset;
+
     /* Calculate where in the frame the payload should go */
     location = calculate_difblock_location (payload);
 
-    /* Check if we received a header. We will not pass on frames until
-     * we've received a header, otherwise the DV decoder goes wacko. */
-    if (location == 0)
-      dvdepay->have_header = TRUE;
+    if (location < 6) {
+      /* part of a header, set the flag to mark that we have the header. */
+      dvdepay->header_mask |= (1 << location);
+      GST_LOG_OBJECT (dvdepay, "got header at location %d, now %02x", location,
+          dvdepay->header_mask);
+    } else {
+      GST_LOG_OBJECT (dvdepay, "got block at location %d", location);
+    }
+
+    /* get the byte offset of the dif block */
+    offset = location * 80;
 
     /* And copy it in, provided the location is sane. */
-    if (location >= 0 && location <= dvdepay->frame_size - 80)
-      memcpy (GST_BUFFER_DATA (dvdepay->acc) + location, payload, 80);
+    if (offset >= 0 && offset <= dvdepay->frame_size - 80)
+      memcpy (GST_BUFFER_DATA (dvdepay->acc) + offset, payload, 80);
 
     payload += 80;
     payload_len -= 80;
   }
 
   if (marker) {
-    /* The marker marks the end of a frame that we need to push. The next frame
-     * will change the timestamp but we won't copy the accumulator again because
-     * we set the prev_ts to -1. */
-    out = gst_buffer_copy (dvdepay->acc);
     GST_DEBUG_OBJECT (dvdepay, "marker bit complete frame %u", rtp_ts);
+    /* only copy the frame when we have a complete header */
+    if (dvdepay->header_mask == 0x3f) {
+      /* The marker marks the end of a frame that we need to push. The next frame
+       * will change the timestamp but we won't copy the accumulator again because
+       * we set the prev_ts to -1. */
+      out = gst_buffer_copy (dvdepay->acc);
+    } else {
+      GST_WARNING_OBJECT (dvdepay, "waiting for frame headers %02x",
+          dvdepay->header_mask);
+    }
     dvdepay->prev_ts = -1;
   } else {
     /* save last timestamp */
@@ -365,8 +380,7 @@ gst_rtp_dv_depay_reset (GstRTPDVDepay * depay)
   depay->acc = NULL;
 
   depay->prev_ts = -1;
-  depay->have_header = FALSE;
-  depay->frame_nr = 0;
+  depay->header_mask = 0;
 }
 
 static GstStateChangeReturn
index c972ec970507b0c7eb58f673ac5d6528f96e8715..08544f581e1c47941c3a371da414f5d009b3d6e7 100644 (file)
@@ -45,9 +45,8 @@ struct _GstRTPDVDepay
 
   GstBuffer *acc;
   guint frame_size;
-  guint frame_nr;
   guint32 prev_ts;
-  gboolean have_header;
+  guint8 header_mask;
 
   gint width, height;
   gint rate_num, rate_denom;