[svn r57] Fixed problem with the audio frame timestamps. trunk
authorrosfran
Thu Oct 26 18:55:14 2006 +0100 (2006-10-26)
branchtrunk
changeset 5624be83eaef89
parent 55 e5dd2fbecd64
child 57 c83c59b22fe1
[svn r57] Fixed problem with the audio frame timestamps.
gst-plugins-nuvdemux/src/gstnuvdemux.c
gst-plugins-nuvdemux/src/gstnuvdemux.h
     1.1 --- a/gst-plugins-nuvdemux/src/gstnuvdemux.c	Thu Oct 26 15:28:10 2006 +0100
     1.2 +++ b/gst-plugins-nuvdemux/src/gstnuvdemux.c	Thu Oct 26 18:55:14 2006 +0100
     1.3 @@ -52,8 +52,7 @@
     1.4  #include <gst/gstplugin.h>
     1.5  #include <string.h>
     1.6  
     1.7 -//#include "gst/gst-i18n-plugin.h"
     1.8 -#include <glib/gi18n.h>
     1.9 +#include "gst/gst-i18n-plugin.h"
    1.10  #include "gstnuvdemux.h"
    1.11  
    1.12  GST_DEBUG_CATEGORY_STATIC (nuvdemux_debug);
    1.13 @@ -89,6 +88,15 @@
    1.14      GST_STATIC_CAPS_ANY);
    1.15  
    1.16  /* NUV Demux indexes init/dispose callers */
    1.17 +static void gst_nuv_demux_index_init( nuv_demux_index *p_idx );
    1.18 +static void gst_nuv_demux_index_clean( nuv_demux_index *p_idx );
    1.19 +
    1.20 +/* NUV Demux indexes manipulation functions */
    1.21 +static gint64 gst_nuv_demux_index_find_offset( GstNuvDemux *nuv, gint64 i_offset );
    1.22 +static void gst_nuv_demux_index_append( GstNuvDemux *nuv, gint64 i_time, gint64 i_offset );
    1.23 +static gint64 gst_nuv_demux_index_convert_time( GstNuvDemux *nuv, gint64 i_time );
    1.24 +
    1.25 +/* NUV Demux plug-in time-line functions */
    1.26  static void gst_nuv_demux_finalize (GObject * object);
    1.27  static GstStateChangeReturn gst_nuv_demux_change_state (GstElement * element,
    1.28      GstStateChange transition);
    1.29 @@ -129,6 +137,17 @@
    1.30  #define READ_DOUBLE_FROM_LE(d) *((gdouble* ) (d))
    1.31  #endif /* G_BYTE_ORDER != G_BIG_ENDIAN */
    1.32  
    1.33 +static gint32 
    1.34 +gst_nuv_demux_getdwle (void const * _p)
    1.35 +{
    1.36 +    guint8 * p = (guint8 *)_p;
    1.37 +	g_print( "[%s] shifting bits: {%d, %d, %d, %d}\n", __FUNCTION__, 
    1.38 +			  ((guint32)p[3] << 24), ((guint32)p[2] << 16),
    1.39 +              ((guint32)p[1] << 8), p[0] );
    1.40 +    return ( ((guint32)p[3] << 24) | ((guint32)p[2] << 16)
    1.41 +              | ((guint32)p[1] << 8) | p[0] );
    1.42 +    //return ( (gint)p[3] | (gint)p[2] | (gint)p[1] | p[0] );
    1.43 +}
    1.44  
    1.45  static void
    1.46  gst_nuv_demux_base_init (gpointer klass)
    1.47 @@ -177,6 +196,8 @@
    1.48    gst_pad_set_event_function (nuv->sinkpad, gst_nuv_demux_handle_sink_event);
    1.49  
    1.50    gst_element_add_pad (GST_ELEMENT (nuv), nuv->sinkpad);
    1.51 +  
    1.52 +  gst_nuv_demux_index_init( nuv->index_entries );
    1.53  
    1.54    nuv->adapter = NULL;
    1.55    nuv->mpeg_buffer = NULL;
    1.56 @@ -194,6 +215,11 @@
    1.57    if (nuv->mpeg_buffer != NULL) {
    1.58      gst_buffer_unref (nuv->mpeg_buffer);
    1.59    }
    1.60 +  
    1.61 +  if ( nuv->index_entries != NULL ) {
    1.62 +  	gst_nuv_demux_index_clean( nuv->index_entries );
    1.63 +  	nuv->index_entries = NULL;
    1.64 +  }
    1.65  
    1.66    gst_nuv_demux_destoy_src_pad (nuv);
    1.67    gst_nuv_demux_reset (nuv);
    1.68 @@ -203,8 +229,178 @@
    1.69    G_OBJECT_CLASS (parent_class)->finalize (object);
    1.70  }
    1.71  
    1.72 +
    1.73  /*****************************************************************************
    1.74 - * Utils fucntions
    1.75 + * Indexes (timecode offset conversion) functions
    1.76 + *****************************************************************************/
    1.77 +
    1.78 +static void 
    1.79 +gst_nuv_demux_index_init( nuv_demux_index *p_idx )
    1.80 +{
    1.81 +		p_idx = g_new0( nuv_demux_index, 1 );
    1.82 +    p_idx->i_idx = 0;
    1.83 +    p_idx->i_idx_max = 0;
    1.84 +    p_idx->idx = g_new0( nuv_demux_index_entry, DEMUX_INDEX_SIZE_MAX );
    1.85 +}
    1.86 +
    1.87 +static void 
    1.88 +gst_nuv_demux_index_clean( nuv_demux_index *p_idx )
    1.89 +{
    1.90 +    if( p_idx->idx )
    1.91 +    {
    1.92 +        g_free( p_idx->idx );
    1.93 +    }
    1.94 +}
    1.95 +
    1.96 +static void 
    1.97 +gst_nuv_demux_index_append( GstNuvDemux *nuv, gint64 i_time, gint64 i_offset )
    1.98 +{
    1.99 +	nuv_demux_index *p_idx = nuv->index_entries;
   1.100 +	
   1.101 +	if ( p_idx == NULL || p_idx->idx == NULL )
   1.102 +		return;
   1.103 +
   1.104 +    /* Be sure to append new entry (we don't insert point) */
   1.105 +    if(  p_idx != NULL && p_idx->i_idx > 0 && p_idx->idx[p_idx->i_idx-1].i_time >= i_time )
   1.106 +        return;
   1.107 +
   1.108 +    /* */
   1.109 +    if( p_idx->i_idx >= p_idx->i_idx_max )
   1.110 +    {
   1.111 +        if( p_idx->i_idx >= DEMUX_INDEX_SIZE_MAX )
   1.112 +        {
   1.113 +            /* Avoid too big index */
   1.114 +            const gint64 i_length = p_idx->idx[p_idx->i_idx-1].i_time -
   1.115 +                                                        p_idx->idx[0].i_time;
   1.116 +            const gint i_count = DEMUX_INDEX_SIZE_MAX/2;
   1.117 +            gint i, j;
   1.118 +
   1.119 +            /* We try to reduce the resolution of the index by a factor 2 */
   1.120 +            for( i = 1, j = 1; i < p_idx->i_idx; i++ )
   1.121 +            {
   1.122 +                if( p_idx->idx[i].i_time < j * i_length / i_count )
   1.123 +                    continue;
   1.124 +
   1.125 +                p_idx->idx[j++] = p_idx->idx[i];
   1.126 +            }
   1.127 +            p_idx->i_idx = j;
   1.128 +
   1.129 +            if( p_idx->i_idx > 3 * DEMUX_INDEX_SIZE_MAX / 4 )
   1.130 +            {
   1.131 +                /* We haven't created enough space
   1.132 +                 * (This method won't create a good index but work for sure) */
   1.133 +                for( i = 0; i < p_idx->i_idx/2; i++ )
   1.134 +                    p_idx->idx[i] = p_idx->idx[2*i];
   1.135 +                p_idx->i_idx /= 2;
   1.136 +            }
   1.137 +        }
   1.138 +        else
   1.139 +        {
   1.140 +            p_idx->i_idx_max += 1000;
   1.141 +            p_idx->idx = g_realloc( p_idx->idx,
   1.142 +                                  p_idx->i_idx_max*sizeof(nuv_demux_index_entry));
   1.143 +        }
   1.144 +    }
   1.145 +
   1.146 +    /* */
   1.147 +    p_idx->idx[p_idx->i_idx].i_time = i_time;
   1.148 +    p_idx->idx[p_idx->i_idx].i_offset = i_offset;
   1.149 +
   1.150 +    p_idx->i_idx++;
   1.151 +}
   1.152 +
   1.153 +static gint64 
   1.154 +gst_nuv_demux_index_convert_time( GstNuvDemux *nuv, gint64 i_time )
   1.155 +{
   1.156 +	nuv_demux_index *p_idx = nuv->index_entries;
   1.157 +	
   1.158 +	g_return_val_if_fail( p_idx != NULL, i_time );
   1.159 +	
   1.160 +    gint i_min = 0;
   1.161 +    gint i_max = p_idx->i_idx-1;
   1.162 +
   1.163 +    /* Empty index */
   1.164 +    if( p_idx->i_idx <= 0 )
   1.165 +        return -1;
   1.166 +
   1.167 +    /* Special border case */
   1.168 +    if( i_time <= p_idx->idx[0].i_time )
   1.169 +        return p_idx->idx[0].i_offset;
   1.170 +    if( i_time >= p_idx->idx[i_max].i_time )
   1.171 +        return p_idx->idx[i_max].i_offset;
   1.172 +
   1.173 +    /* Dicho */
   1.174 +    for( ;; )
   1.175 +    {
   1.176 +        gint i_med;
   1.177 +
   1.178 +        if( i_max - i_min <= 1 )
   1.179 +            break;
   1.180 +
   1.181 +        i_med = (i_min+i_max)/2;
   1.182 +        if( p_idx->idx[i_med].i_time < i_time )
   1.183 +            i_min = i_med;
   1.184 +        else if( p_idx->idx[i_med].i_time > i_time )
   1.185 +            i_max = i_med;
   1.186 +        else
   1.187 +            return p_idx->idx[i_med].i_offset;
   1.188 +    }
   1.189 +
   1.190 +    /* return nearest in time */
   1.191 +    if( i_time - p_idx->idx[i_min].i_time < p_idx->idx[i_max].i_time - i_time )
   1.192 +        return p_idx->idx[i_min].i_offset;
   1.193 +    else
   1.194 +        return p_idx->idx[i_max].i_offset;
   1.195 +}
   1.196 +
   1.197 +static gint64
   1.198 +gst_nuv_demux_index_find_offset( GstNuvDemux *nuv, gint64 i_offset )
   1.199 +{
   1.200 +	nuv_demux_index *p_idx = nuv->index_entries;
   1.201 +	
   1.202 +	g_return_val_if_fail( p_idx != NULL, i_offset );
   1.203 +	
   1.204 +    gint i_min = 0;
   1.205 +    gint i_max = p_idx->i_idx-1;
   1.206 +
   1.207 +    /* Empty index */
   1.208 +    if( p_idx->i_idx <= 0 )
   1.209 +        return -1;
   1.210 +
   1.211 +    /* Special border case */
   1.212 +    if( i_offset <= p_idx->idx[0].i_offset )
   1.213 +        return p_idx->idx[0].i_offset;
   1.214 +    if( i_offset == p_idx->idx[i_max].i_offset )
   1.215 +        return p_idx->idx[i_max].i_offset;
   1.216 +    if( i_offset > p_idx->idx[i_max].i_offset )
   1.217 +        return -1;
   1.218 +
   1.219 +    /* Dicho */
   1.220 +    for( ;; )
   1.221 +    {
   1.222 +        gint i_med;
   1.223 +
   1.224 +        if ( i_max - i_min <= 1 )
   1.225 +            break;
   1.226 +
   1.227 +        i_med = (i_min+i_max)/2;
   1.228 +        if( p_idx->idx[i_med].i_offset < i_offset )
   1.229 +            i_min = i_med;
   1.230 +        else if( p_idx->idx[i_med].i_offset > i_offset )
   1.231 +            i_max = i_med;
   1.232 +        else
   1.233 +            return p_idx->idx[i_med].i_offset;
   1.234 +    }
   1.235 +
   1.236 +    /* return nearest */
   1.237 +    if( i_offset - p_idx->idx[i_min].i_offset < p_idx->idx[i_max].i_offset - i_offset )
   1.238 +        return p_idx->idx[i_min].i_offset;
   1.239 +    else
   1.240 +        return p_idx->idx[i_max].i_offset;
   1.241 +}
   1.242 +
   1.243 +/*****************************************************************************
   1.244 + * Utils functions
   1.245   *****************************************************************************/
   1.246  
   1.247  static gboolean
   1.248 @@ -328,9 +524,9 @@
   1.249    h->i_keyframe = data[2];
   1.250    h->i_filters = data[3];
   1.251  
   1.252 -  h->i_timecode = GST_READ_UINT32_LE (&data[4]);
   1.253 +  h->i_timecode = gst_nuv_demux_getdwle( &data[4] ); //GST_READ_UINT32_LE (&data[4]);
   1.254    h->i_length = GST_READ_UINT32_LE (&data[8]);
   1.255 -  GST_DEBUG_OBJECT (nuv, "frame hdr: t=%c c=%c k=%d f=0x%x timecode=%u l=%u",
   1.256 +  GST_DEBUG_OBJECT (nuv, "frame hdr: t=%c c=%c k=%d f=0x%x timecode=%d l=%d",
   1.257        h->i_type,
   1.258        h->i_compression ? h->i_compression : ' ',
   1.259        h->i_keyframe ? h->i_keyframe : ' ',
   1.260 @@ -427,6 +623,7 @@
   1.261          gst_nuv_demux_handle_src_event);
   1.262      gst_pad_set_active (nuv->src_video_pad, TRUE);
   1.263      gst_element_add_pad (GST_ELEMENT (nuv), nuv->src_video_pad);
   1.264 +
   1.265      gst_caps_unref (video_caps);
   1.266    }
   1.267  
   1.268 @@ -450,6 +647,7 @@
   1.269  
   1.270      gst_pad_set_event_function (nuv->src_audio_pad,
   1.271          gst_nuv_demux_handle_src_event);
   1.272 +
   1.273      gst_caps_unref (audio_caps);
   1.274    }
   1.275  
   1.276 @@ -478,17 +676,36 @@
   1.277  
   1.278    if (h->i_type == 'R')
   1.279      goto done;
   1.280 -
   1.281 -  ret = gst_nuv_demux_read_bytes (nuv, h->i_length, TRUE, &buf);
   1.282 -  if (ret != GST_FLOW_OK) {
   1.283 -    return ret;
   1.284 +    
   1.285 +	/* append the frame's header timecode field, and the actual offset */
   1.286 +  gst_nuv_demux_index_append( nuv, h->i_timecode, nuv->offset );
   1.287 +  
   1.288 +  if (h->i_length > 0) {
   1.289 +    ret = gst_nuv_demux_read_bytes (nuv, h->i_length, TRUE, &buf);
   1.290 +    if (ret != GST_FLOW_OK)
   1.291 +      return ret;
   1.292 +      
   1.293 +    /* search for a valid timecode in the indexes list (find the nearest valid timecode) */
   1.294 +	  if ( h->i_timecode < 0 ) {
   1.295 +	  	/* convert this actual timecode to a valid index in the timecode's table */
   1.296 +		  gint64 pos = gst_nuv_demux_index_convert_time( nuv, h->i_timecode );
   1.297 +		  
   1.298 +		  /* find the nearest empty frame slot */		  
   1.299 +		  gint64 near_off = gst_nuv_demux_index_find_offset( nuv, pos );
   1.300 +		  
   1.301 +		  /* just get the timecode from the timecode's table */		  
   1.302 +		  GST_BUFFER_TIMESTAMP (buf) = nuv->index_entries->idx[near_off].i_time * GST_MSECOND;
   1.303 +	  } else {  
   1.304 +	  	GST_BUFFER_TIMESTAMP (buf) = h->i_timecode * GST_MSECOND;
   1.305 +	  }
   1.306    }
   1.307  
   1.308 -  GST_BUFFER_TIMESTAMP (buf) = h->i_timecode * GST_MSECOND;
   1.309 -
   1.310    switch (h->i_type) {
   1.311      case 'V':
   1.312      {
   1.313 +      if (h->i_length == 0)
   1.314 +        break;
   1.315 +
   1.316        GST_BUFFER_OFFSET (buf) = nuv->video_offset;
   1.317        gst_buffer_set_caps (buf, GST_PAD_CAPS (nuv->src_video_pad));
   1.318        ret = gst_pad_push (nuv->src_video_pad, buf);
   1.319 @@ -497,6 +714,9 @@
   1.320      }
   1.321      case 'A':
   1.322      {
   1.323 +      if (h->i_length == 0)
   1.324 +        break;
   1.325 +
   1.326        GST_BUFFER_OFFSET (buf) = nuv->audio_offset;
   1.327        gst_buffer_set_caps (buf, GST_PAD_CAPS (nuv->src_audio_pad));
   1.328        ret = gst_pad_push (nuv->src_audio_pad, buf);
   1.329 @@ -508,18 +728,22 @@
   1.330        switch (h->i_compression) {
   1.331          case 'V':
   1.332            gst_pad_push_event (nuv->src_video_pad,
   1.333 -              gst_event_new_new_segment (TRUE, 1.0, GST_FORMAT_TIME, 0, -1, 0));
   1.334 +              gst_event_new_new_segment (TRUE, 1.0, GST_FORMAT_TIME, 0, -1,
   1.335 +                  h->i_timecode));
   1.336            break;
   1.337          case 'A':
   1.338            gst_pad_push_event (nuv->src_audio_pad,
   1.339                gst_event_new_new_segment (TRUE, 1.0, GST_FORMAT_TIME, 0, -1, 0));
   1.340 -
   1.341            break;
   1.342          default:
   1.343            break;
   1.344        }
   1.345 +    }
   1.346 +    default:
   1.347 +      if (buf != NULL)
   1.348 +        gst_buffer_unref (buf);
   1.349 +
   1.350        break;
   1.351 -    }
   1.352    }
   1.353  
   1.354  done:
   1.355 @@ -700,7 +924,7 @@
   1.356  
   1.357      case GST_NUV_DEMUX_MOVI:
   1.358        res = gst_nuv_demux_stream_data (nuv);
   1.359 -      if ((res != GST_FLOW_OK) && (res != GST_FLOW_ERROR_NO_DATA)) {
   1.360 +      if ((res != GST_FLOW_OK) && (res != GST_FLOW_CUSTOM_ERROR)) {
   1.361          goto pause;
   1.362        }
   1.363        break;
   1.364 @@ -768,10 +992,7 @@
   1.365        return GST_FLOW_ERROR_NO_DATA;
   1.366  
   1.367      if (move) {
   1.368 -      guint8 *data = NULL;
   1.369 -      data = (guint8 *) gst_adapter_take (nuv->adapter, size);
   1.370 -      *buffer = gst_buffer_new ();
   1.371 -      gst_buffer_set_data (*buffer, data, size);
   1.372 +      *buffer = gst_adapter_take_buffer (nuv->adapter, size);
   1.373      } else {
   1.374        guint8 *data = NULL;
   1.375  
     2.1 --- a/gst-plugins-nuvdemux/src/gstnuvdemux.h	Thu Oct 26 15:28:10 2006 +0100
     2.2 +++ b/gst-plugins-nuvdemux/src/gstnuvdemux.h	Thu Oct 26 18:55:14 2006 +0100
     2.3 @@ -38,6 +38,23 @@
     2.4  #define GST_IS_NUV_DEMUX_CLASS(klass) \
     2.5    (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_NUV_DEMUX))
     2.6  
     2.7 +#define DEMUX_INDEX_SIZE_MAX (100000)
     2.8 +
     2.9 +/* Indexes (timecodes/offsets) conversion structures */
    2.10 +typedef struct
    2.11 +{
    2.12 +    gint64 i_time;
    2.13 +    gint64 i_offset;
    2.14 +
    2.15 +} nuv_demux_index_entry;
    2.16 +
    2.17 +typedef struct
    2.18 +{
    2.19 +    gint i_idx;
    2.20 +    gint i_idx_max;
    2.21 +
    2.22 +    nuv_demux_index_entry *idx;
    2.23 +} nuv_demux_index;
    2.24  
    2.25  /* */
    2.26  typedef struct
    2.27 @@ -92,9 +109,9 @@
    2.28                             0x02: gauss 5 pixel (8,1,1,1,1)/12
    2.29                             0x04: cartoon filter */
    2.30  
    2.31 -    guint32 i_timecode;     /* ms */
    2.32 +    gint32 i_timecode;     /* ms */
    2.33  
    2.34 -    guint32 i_length;       /* V,A,T: length of following data
    2.35 +    gint i_length;       /* V,A,T: length of following data
    2.36                             S: length of packet correl */
    2.37  } nuv_frame_header;
    2.38  
    2.39 @@ -160,6 +177,13 @@
    2.40    nuv_header *h;
    2.41    nuv_extended_header *eh;
    2.42    nuv_frame_header *fh;
    2.43 +  
    2.44 +  /* index */
    2.45 +  nuv_demux_index *index_entries;
    2.46 +  guint          index_size;
    2.47 +  guint64        index_offset;
    2.48 +  guint          current_entry;
    2.49 +
    2.50  } GstNuvDemux;
    2.51  
    2.52  typedef struct _GstNuvDemuxClass {