# HG changeset patch
# User rosfran
# Date 1163085629 0
# Node ID 959df0ca7621db30ce70978715479668ad5df048
# Parent  04a6aeac87b05555526c6ac6e59c3278d3c5624f
[svn r74] Changed the set_active on PADs, fixed some offset on video and audio.

diff -r 04a6aeac87b0 -r 959df0ca7621 gst-plugins-nuvdemux/src/gstnuvdemux.c
--- a/gst-plugins-nuvdemux/src/gstnuvdemux.c	Tue Nov 07 23:11:23 2006 +0000
+++ b/gst-plugins-nuvdemux/src/gstnuvdemux.c	Thu Nov 09 15:20:29 2006 +0000
@@ -52,15 +52,13 @@
 #include <gst/gstplugin.h>
 #include <string.h>
 
-#define GETTEXT_PACKAGE "gst-plugins-nuvdemux-0.10.3"
-#include <glib/gi18n.h>
+#include "gst/gst-i18n-plugin.h"
 #include "gstnuvdemux.h"
 
 GST_DEBUG_CATEGORY_STATIC (nuvdemux_debug);
 #define GST_CAT_DEFAULT nuvdemux_debug
 
 
-#define DEMUX_INDEX_SIZE_MAX (100000)
 #define GST_FLOW_ERROR_NO_DATA  -101
 
 GST_DEBUG_CATEGORY_EXTERN (GST_CAT_EVENT);
@@ -90,11 +88,11 @@
     GST_STATIC_CAPS_ANY);
 
 /* NUV Demux indexes init/dispose callers */
-static nuv_demux_index* gst_nuv_demux_index_new (void);
-static void gst_nuv_demux_index_destroy (nuv_demux_index *p_idx);
+static void gst_nuv_demux_index_init( nuv_demux_index **p_idx );
+static void gst_nuv_demux_index_clean( nuv_demux_index **p_idx );
 
 /* NUV Demux indexes manipulation functions */
-static gint64 gst_nuv_demux_index_find_offset( GstNuvDemux *nuv, gint64 i_offset );
+//static gint64 gst_nuv_demux_index_find_offset( GstNuvDemux *nuv, gint64 i_offset );
 static void gst_nuv_demux_index_append( GstNuvDemux *nuv, gint64 i_time, gint64 i_offset );
 static gint64 gst_nuv_demux_index_convert_time( GstNuvDemux *nuv, gint64 i_time );
 
@@ -107,12 +105,16 @@
 static GstFlowReturn gst_nuv_demux_play (GstPad * pad);
 static gboolean gst_nuv_demux_sink_activate_pull (GstPad * sinkpad,
     gboolean active);
-static gboolean gst_nuv_demux_sink_activate_push (GstPad * pad, 
-    gboolean active);
 static gboolean gst_nuv_demux_sink_activate (GstPad * sinkpad);
 static GstFlowReturn gst_nuv_demux_read_bytes (GstNuvDemux * nuv, guint64 size,
     gboolean move, GstBuffer ** buffer);
 static void gst_nuv_demux_reset (GstNuvDemux * nuv);
+static gboolean gst_nuv_demux_handle_sink_event (GstPad * sinkpad,
+    GstEvent * event);
+static gboolean gst_nuv_demux_handle_audio_src_event (GstPad * sinkpad,
+    GstEvent * event);
+static gboolean gst_nuv_demux_handle_video_src_event (GstPad * sinkpad,
+    GstEvent * event);
 static void gst_nuv_demux_destoy_src_pad (GstNuvDemux * nuv);
 static void gst_nuv_demux_send_eos (GstNuvDemux * nuv);
 
@@ -180,15 +182,14 @@
   gst_pad_set_activatepull_function (nuv->sinkpad,
       gst_nuv_demux_sink_activate_pull);
 
-  gst_pad_set_activatepush_function (nuv->sinkpad, 
-      gst_nuv_demux_sink_activate_push);
-
   gst_pad_set_chain_function (nuv->sinkpad,
       GST_DEBUG_FUNCPTR (gst_nuv_demux_chain));
 
+  gst_pad_set_event_function (nuv->sinkpad, gst_nuv_demux_handle_sink_event);
+
   gst_element_add_pad (GST_ELEMENT (nuv), nuv->sinkpad);
   
-  nuv->index_entries = gst_nuv_demux_index_new ();
+  gst_nuv_demux_index_init( &nuv->index_entries );
 
   nuv->adapter = NULL;
   nuv->mpeg_buffer = NULL;
@@ -208,7 +209,7 @@
   }
   
   if ( nuv->index_entries != NULL ) {
-  	gst_nuv_demux_index_destroy (nuv->index_entries);
+  	gst_nuv_demux_index_clean( &nuv->index_entries );
   	nuv->index_entries = NULL;
   }
 
@@ -225,20 +226,22 @@
  * Indexes (timecode offset conversion) functions
  *****************************************************************************/
 
-static nuv_demux_index*
-gst_nuv_demux_index_new (void)
+static void 
+gst_nuv_demux_index_init( nuv_demux_index **p_idx )
 {
-	return g_new0 (nuv_demux_index, 1);
+	*p_idx = g_new0( nuv_demux_index, 1 );
+	(*p_idx)->i_idx = 0;
+	(*p_idx)->i_idx_max = 0;
 }
 
 static void 
-gst_nuv_demux_index_destroy (nuv_demux_index *p_idx)
+gst_nuv_demux_index_clean( nuv_demux_index **p_idx )
 {
-	if (p_idx != NULL) {
-        g_free (p_idx->idx);        
-        p_idx->idx = NULL;
-		g_free (p_idx);
+	if ( *p_idx != NULL ) {
+		g_free( *p_idx );
+		*p_idx = NULL;
 	}
+
 }
 
 static void 
@@ -250,13 +253,13 @@
 	//	return;
 
 	/* Be sure to append new entry (we don't insert point) */
-	if (p_idx != NULL && p_idx->i_idx > 0 && p_idx->idx[p_idx->i_idx-1].i_time >= i_time)
+	if( p_idx != NULL && p_idx->i_idx > 0 && p_idx->idx[p_idx->i_idx-1].i_time >= i_time )
 		return;
 
 	/* */
-	if (p_idx->i_idx >= p_idx->i_idx_max)
+	if( p_idx->i_idx >= p_idx->i_idx_max )
 	{
-		if (p_idx->i_idx >= DEMUX_INDEX_SIZE_MAX)
+		if( p_idx->i_idx >= DEMUX_INDEX_SIZE_MAX )
 		{
 			/* Avoid too big index */
 			const gint64 i_length = p_idx->idx[p_idx->i_idx-1].i_time -
@@ -265,20 +268,20 @@
 			gint i, j;
 
 			/* We try to reduce the resolution of the index by a factor 2 */
-			for (i = 1, j = 1; i < p_idx->i_idx; i++)
+			for( i = 1, j = 1; i < p_idx->i_idx; i++ )
 			{
-				if (p_idx->idx[i].i_time < j * i_length / i_count)
+				if( p_idx->idx[i].i_time < j * i_length / i_count )
 					continue;
 
 				p_idx->idx[j++] = p_idx->idx[i];
 			}
 			p_idx->i_idx = j;
 
-			if (p_idx->i_idx > 3 * DEMUX_INDEX_SIZE_MAX / 4)
+			if( p_idx->i_idx > 3 * DEMUX_INDEX_SIZE_MAX / 4 )
 			{
 				/* We haven't created enough space
 				 * (This method won't create a good index but work for sure) */
-				for (i = 0; i < p_idx->i_idx/2; i++)
+				for( i = 0; i < p_idx->i_idx/2; i++ )
 					p_idx->idx[i] = p_idx->idx[2*i];
 				p_idx->i_idx /= 2;
 			}
@@ -286,8 +289,6 @@
 		else
 		{
 			p_idx->i_idx_max += 1000;
-			p_idx->idx = g_realloc (p_idx->idx, 
-                    p_idx->i_idx_max*sizeof(nuv_demux_index_entry));
 		}
 	}
 
@@ -342,50 +343,26 @@
 		return p_idx->idx[i_max].i_offset;
 }
 
-static gint64
-gst_nuv_demux_index_find_offset( GstNuvDemux *nuv, gint64 i_offset )
+/*****************************************************************************
+ * Utils functions
+ *****************************************************************************/
+
+static gboolean
+gst_nuv_demux_handle_sink_event (GstPad * sinkpad, GstEvent * event)
 {
-	nuv_demux_index *p_idx = nuv->index_entries;
+  gboolean res = FALSE;
 
-	g_return_val_if_fail( p_idx != NULL && p_idx->idx != NULL, i_offset );
+  switch (GST_EVENT_TYPE (event)) {
+    case GST_EVENT_NEWSEGMENT:
+      res = TRUE;
+      break;
+    default:
+      return gst_pad_event_default (sinkpad, event);
+      break;
+  }
 
-	gint i_min = 0;
-	gint i_max = p_idx->i_idx-1;
-
-	/* Empty index */
-	if( p_idx->i_idx <= 0 )
-		return -1;
-
-	/* Special border case */
-	if( i_offset <= p_idx->idx[0].i_offset )
-		return p_idx->idx[0].i_offset;
-	if( i_offset == p_idx->idx[i_max].i_offset )
-		return p_idx->idx[i_max].i_offset;
-	if( i_offset > p_idx->idx[i_max].i_offset )
-		return -1;
-
-	/* Dicho */
-	for( ;; )
-	{
-		gint i_med;
-
-		if ( i_max - i_min <= 1 )
-			break;
-
-		i_med = (i_min+i_max)/2;
-		if( p_idx->idx[i_med].i_offset < i_offset )
-			i_min = i_med;
-		else if( p_idx->idx[i_med].i_offset > i_offset )
-			i_max = i_med;
-		else
-			return p_idx->idx[i_med].i_offset;
-	}
-
-	/* return nearest */
-	if( i_offset - p_idx->idx[i_min].i_offset < p_idx->idx[i_max].i_offset - i_offset )
-		return p_idx->idx[i_min].i_offset;
-	else
-		return p_idx->idx[i_max].i_offset;
+  gst_event_unref (event);
+  return res;
 }
 
 /* HeaderLoad:
@@ -559,12 +536,18 @@
 }
 
 static gboolean
-gst_nuv_demux_handle_src_event (GstPad * pad, GstEvent * event)
+gst_nuv_demux_handle_audio_src_event (GstPad * pad, GstEvent * event)
 {
   gst_event_unref (event);
   return FALSE;
 }
 
+static gboolean
+gst_nuv_demux_handle_video_src_event (GstPad * pad, GstEvent * event)
+{
+  gst_event_unref (event);
+  return FALSE;
+}
 
 static void
 gst_nuv_demux_create_pads (GstNuvDemux * nuv)
@@ -584,15 +567,13 @@
         (gint) (nuv->h->d_aspect * 1000.0f), 1000, NULL);
 
     gst_pad_use_fixed_caps (nuv->src_video_pad);
-    gst_pad_set_active (nuv->src_video_pad, TRUE);
     gst_pad_set_caps (nuv->src_video_pad, video_caps);
 
+    gst_pad_set_event_function (nuv->src_video_pad,
+	    	gst_nuv_demux_handle_video_src_event);
     gst_pad_set_active (nuv->src_video_pad, TRUE);
     gst_element_add_pad (GST_ELEMENT (nuv), nuv->src_video_pad);
 
-    gst_pad_set_event_function (nuv->src_video_pad,
-        gst_nuv_demux_handle_src_event);
-
     gst_caps_unref (video_caps);
   }
 
@@ -609,14 +590,13 @@
         "mpegversion", G_TYPE_INT, nuv->eh->i_version, NULL);
 
     gst_pad_use_fixed_caps (nuv->src_audio_pad);
-    gst_pad_set_active (nuv->src_audio_pad, TRUE);
     gst_pad_set_caps (nuv->src_audio_pad, audio_caps);
+    
+    gst_pad_set_event_function (nuv->src_audio_pad,
+  		  gst_nuv_demux_handle_audio_src_event);
     gst_pad_set_active (nuv->src_audio_pad, TRUE);
     gst_element_add_pad (GST_ELEMENT (nuv), nuv->src_audio_pad);
 
-    gst_pad_set_event_function (nuv->src_audio_pad,
-        gst_nuv_demux_handle_src_event);
-
     gst_caps_unref (audio_caps);
   }
 
@@ -642,14 +622,19 @@
   GstFlowReturn ret = GST_FLOW_OK;
   GstBuffer *buf = NULL;
   nuv_frame_header *h = nuv->fh;
+  
+  gint64 table_timecode = 0;
 
   if (h->i_type == 'R')
     goto done;
     
+  table_timecode = h->i_timecode;
 
- GST_DEBUG_OBJECT (nuv, "starting append index");
-   /* append the frame's header timecode field, and the actual offset */
-  gst_nuv_demux_index_append( nuv, h->i_timecode, nuv->offset );
+  /* append the frame's header timecode field, and the actual offset */
+  if ( h->i_type == 'V' ) 
+  	gst_nuv_demux_index_append( nuv, h->i_timecode, nuv->video_offset );
+  else if ( h->i_type == 'A' ) 
+  	gst_nuv_demux_index_append( nuv, h->i_timecode, nuv->audio_offset );  	
  
   if (h->i_length > 0) {
 	  ret = gst_nuv_demux_read_bytes (nuv, h->i_length, TRUE, &buf);
@@ -659,71 +644,80 @@
 	  /* search for a valid timecode in the indexes list (find the nearest valid timecode) */
 	  if ( h->i_timecode < 0 ) {
 		  /* convert this actual timecode to a valid index in the timecode's table */
-		  gint64 pos = gst_nuv_demux_index_convert_time (nuv, h->i_timecode);
-
-		  /* find the nearest empty frame slot */		  
-		  gint64 near_off = gst_nuv_demux_index_find_offset  (nuv, pos);
+		  gint64 pos = gst_nuv_demux_index_convert_time( nuv, h->i_timecode );
 
 		  /* just get the timecode from the timecode's table */		  
-		  GST_BUFFER_TIMESTAMP (buf) = nuv->index_entries->idx[near_off].i_time * GST_MSECOND;
+		  table_timecode = nuv->index_entries->idx[pos].i_time * GST_MSECOND;
 	  } else {  
-		  GST_BUFFER_TIMESTAMP (buf) = h->i_timecode * GST_MSECOND;
+			table_timecode = h->i_timecode * GST_MSECOND;
 	  }
-  }
-
- GST_DEBUG_OBJECT (nuv, "index appended");
+	  
+	  GST_BUFFER_TIMESTAMP (buf) = table_timecode;
+  }  
 
   switch (h->i_type) {
     case 'V':
     {
       if (h->i_length == 0)
         break;
-
-      GST_BUFFER_OFFSET (buf) = nuv->video_offset;
+        
+      if ( !gst_pad_is_linked( nuv->src_video_pad ) )
+      	break;
+      
+      //GST_PAD_STREAM_LOCK(nuv->src_video_pad);
+      
+      GST_BUFFER_SIZE (buf) = h->i_length;
       gst_buffer_set_caps (buf, GST_PAD_CAPS (nuv->src_video_pad));
       ret = gst_pad_push (nuv->src_video_pad, buf);
-      if (ret != GST_FLOW_OK) {
-        GST_WARNING_OBJECT (nuv, "error pushing on srcpad %s, is linked? = %d",
-            gst_pad_get_name (nuv->src_video_pad), gst_pad_is_linked (nuv->src_video_pad));
-      }
-      nuv->video_offset++;
+      nuv->video_offset += h->i_length;
+      
+      //GST_PAD_STREAM_UNLOCK(nuv->src_video_pad);
       break;
     }
     case 'A':
     {
       if (h->i_length == 0)
         break;
-
-      GST_BUFFER_OFFSET (buf) = nuv->audio_offset;
+        
+      if ( !gst_pad_is_linked( nuv->src_audio_pad ) )
+      	break;
+        
+      //GST_PAD_STREAM_LOCK(nuv->src_audio_pad);
+      
+      GST_BUFFER_SIZE (buf) = h->i_length;
       gst_buffer_set_caps (buf, GST_PAD_CAPS (nuv->src_audio_pad));
       ret = gst_pad_push (nuv->src_audio_pad, buf);
-      if (ret != GST_FLOW_OK) {
-        GST_WARNING_OBJECT (nuv, "Error pushing on srcpad %s, is linked? = %d",
-            gst_pad_get_name (nuv->src_audio_pad), gst_pad_is_linked (nuv->src_audio_pad));
-      }
-      nuv->audio_offset++;
+      nuv->audio_offset += h->i_length;
+      
+      //GST_PAD_STREAM_UNLOCK(nuv->src_audio_pad);
       break;
     }
     case 'S':
     {
-        /*
       switch (h->i_compression) {
         case 'V':
-          GST_DEBUG_OBJECT (nuv, "Video New Segment");
-          nuv->video_offset = 0;
+		      if ( !gst_pad_is_linked( nuv->src_video_pad ) )
+		      	break;
+
+        	//GST_PAD_STREAM_LOCK(nuv->src_video_pad);
           gst_pad_push_event (nuv->src_video_pad,
-              gst_event_new_new_segment (TRUE, 1.0, GST_FORMAT_TIME, 0, -1,
-                  0));
+              gst_event_new_new_segment (TRUE, 1.0, GST_FORMAT_TIME, table_timecode, 
+              		GST_CLOCK_TIME_NONE, 0));
+          //GST_PAD_STREAM_UNLOCK(nuv->src_video_pad);
           break;
-        case 'A':
-          GST_DEBUG_OBJECT (nuv, "Audio New Segment");
+        case 'A':        
+		      if ( !gst_pad_is_linked( nuv->src_audio_pad ) )
+		      	break;
+
+        	//GST_PAD_STREAM_LOCK(nuv->src_audio_pad);
           gst_pad_push_event (nuv->src_audio_pad,
-              gst_event_new_new_segment (TRUE, 1.0, GST_FORMAT_TIME, 0, -1, 0));
+              gst_event_new_new_segment (TRUE, 1.0, GST_FORMAT_TIME, table_timecode, 
+              		GST_CLOCK_TIME_NONE, 0));
+          //GST_PAD_STREAM_UNLOCK(nuv->src_audio_pad);
           break;
         default:
           break;
       }
-      */
     }
     default:
       if (buf != NULL)
@@ -732,8 +726,6 @@
       break;
   }
 
- GST_DEBUG_OBJECT (nuv, "data sent");
-
 done:
   nuv->state = GST_NUV_DEMUX_FRAME_HEADER;
   g_free (nuv->fh);
@@ -751,7 +743,7 @@
       gst_nuv_demux_read_bytes (nuv, nuv->mpeg_data_size, TRUE,
       &nuv->mpeg_buffer);
   if (ret != GST_FLOW_OK) {
-    return GST_FLOW_ERROR;
+    return ret; //GST_FLOW_ERROR;
   }
   GST_BUFFER_SIZE (nuv->mpeg_buffer) = nuv->mpeg_data_size;
   nuv->state = GST_NUV_DEMUX_EXTEND_HEADER;
@@ -912,7 +904,7 @@
 
     case GST_NUV_DEMUX_MOVI:
       res = gst_nuv_demux_stream_data (nuv);
-      if ((res != GST_FLOW_OK) && (res != GST_FLOW_ERROR_NO_DATA)) {
+      if ((res != GST_FLOW_OK) && (res != GST_FLOW_ERROR_NO_DATA) && (res != GST_FLOW_CUSTOM_ERROR)) {
         goto pause;
       }
       break;
@@ -929,8 +921,6 @@
   return GST_FLOW_OK;
 
 pause:
-  g_debug ("PAUSE");
-
   GST_LOG_OBJECT (nuv, "pausing task, reason %s", gst_flow_get_name (res));
   gst_pad_pause_task (nuv->sinkpad);
   if (GST_FLOW_IS_FATAL (res)) {
@@ -965,13 +955,13 @@
     *buffer = gst_buffer_new ();
     return ret;
   }
-
+  
   if (nuv->mode == 0) {
     ret = gst_pad_pull_range (nuv->sinkpad, nuv->offset, size, buffer);
     if (ret == GST_FLOW_OK) {
-      if (move) {
-        nuv->offset += size;
-      }
+    		if (move) {
+					nuv->offset += size;
+				}    	
       /* got eos */
     } else if (ret == GST_FLOW_UNEXPECTED) {
       gst_nuv_demux_send_eos (nuv);
@@ -982,11 +972,7 @@
       return GST_FLOW_ERROR_NO_DATA;
 
     if (move) {
-      guint8 *data = NULL;
-
-      data = (guint8 *) gst_adapter_take (nuv->adapter, size);
-      *buffer = gst_buffer_new ();
-      gst_buffer_set_data (*buffer, data, size);
+      *buffer = gst_adapter_take_buffer (nuv->adapter, size);
     } else {
       guint8 *data = NULL;
 
@@ -995,6 +981,8 @@
       gst_buffer_set_data (*buffer, data, size);
     }
   }
+  
+	
   return ret;
 }
 
@@ -1006,14 +994,20 @@
 
   if (gst_pad_check_pull_range (sinkpad)) {
     nuv->mode = 0;
-    nuv->adapter = NULL;
+    if (nuv->adapter) {
+      gst_adapter_clear (nuv->adapter);
+      g_object_unref (nuv->adapter);
+      nuv->adapter = NULL;
+    }
     res = gst_pad_activate_pull (sinkpad, TRUE);
-    GST_DEBUG_OBJECT (nuv, "starting PULL mode");
   } else {
     nuv->mode = 1;
-    nuv->adapter = gst_adapter_new ();
+    if (nuv->adapter) {
+      gst_adapter_clear (nuv->adapter);
+    } else {
+      nuv->adapter = gst_adapter_new ();
+    }
     res = gst_pad_activate_push (sinkpad, TRUE);
-    GST_DEBUG_OBJECT (nuv, "starting PUSH mode");
   }
 
   g_object_unref (nuv);
@@ -1035,22 +1029,6 @@
   return TRUE;
 }
 
-static gboolean
-gst_nuv_demux_sink_activate_push (GstPad * pad, gboolean active)
-{
-  GstNuvDemux *nuv = GST_NUV_DEMUX (gst_pad_get_parent (pad));
-
-  if (active) {
-    GST_DEBUG_OBJECT (nuv, "activating push/chain function");
-  } else {
-    GST_DEBUG_OBJECT (nuv, "deactivating push/chain function");
-  }
-
-  gst_object_unref (nuv);
-
-  return TRUE;
-}
-
 static GstFlowReturn
 gst_nuv_demux_chain (GstPad * pad, GstBuffer * buf)
 {
@@ -1058,10 +1036,6 @@
 
   gst_adapter_push (nuv->adapter, buf);
 
-  GST_DEBUG_OBJECT (nuv, "PUSH adapter %d", gst_adapter_available (nuv->adapter));
-
-  gst_object_unref (nuv);
-
   return gst_nuv_demux_play (pad);
 }
 
@@ -1116,7 +1090,7 @@
 gst_nuv_demux_change_state (GstElement * element, GstStateChange transition)
 {
   GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;
-  
+
   switch (transition) {
     case GST_STATE_CHANGE_READY_TO_PAUSED:
       break;
@@ -1146,6 +1120,7 @@
 {
 #ifdef ENABLE_NLS
   setlocale (LC_ALL, "");
+  bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR);
 #endif /* ENABLE_NLS */
 
   if (!gst_element_register (plugin, "nuvdemux", GST_RANK_SECONDARY,
diff -r 04a6aeac87b0 -r 959df0ca7621 gst-plugins-nuvdemux/src/gstnuvdemux.h
--- a/gst-plugins-nuvdemux/src/gstnuvdemux.h	Tue Nov 07 23:11:23 2006 +0000
+++ b/gst-plugins-nuvdemux/src/gstnuvdemux.h	Thu Nov 09 15:20:29 2006 +0000
@@ -38,6 +38,8 @@
 #define GST_IS_NUV_DEMUX_CLASS(klass) \
   (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_NUV_DEMUX))
 
+#define DEMUX_INDEX_SIZE_MAX (100000)
+
 /* Indexes (timecodes/offsets) conversion structures */
 typedef struct
 {
@@ -51,7 +53,7 @@
     gint i_idx;
     gint i_idx_max;
 
-    nuv_demux_index_entry *idx;
+    nuv_demux_index_entry idx[DEMUX_INDEX_SIZE_MAX];
 } nuv_demux_index;
 
 /* */
@@ -107,7 +109,7 @@
                            0x02: gauss 5 pixel (8,1,1,1,1)/12
                            0x04: cartoon filter */
 
-    gint i_timecode;     /* ms */
+    gint32 i_timecode;     /* ms */
 
     gint i_length;       /* V,A,T: length of following data
                            S: length of packet correl */