gst-plugins-nuvdemux/nuvdemux/gstnuvdemux.c
branchtrunk
changeset 86 ac9a990a5733
parent 84 8b867c828e89
child 88 2a70ed80ed1a
     1.1 --- a/gst-plugins-nuvdemux/nuvdemux/gstnuvdemux.c	Tue Nov 14 13:34:22 2006 +0000
     1.2 +++ b/gst-plugins-nuvdemux/nuvdemux/gstnuvdemux.c	Wed Nov 15 14:37:59 2006 +0000
     1.3 @@ -51,6 +51,7 @@
     1.4  #include <gst/gsterror.h>
     1.5  #include <gst/gstplugin.h>
     1.6  #include <string.h>
     1.7 +#include <math.h>
     1.8  
     1.9  #include "glib/gi18n.h"
    1.10  #include "gstnuvdemux.h"
    1.11 @@ -132,6 +133,25 @@
    1.12  #define READ_DOUBLE_FROM_LE(d) *((gdouble* ) (d))
    1.13  #endif /* G_BYTE_ORDER != G_BIG_ENDIAN */
    1.14  
    1.15 +static void 
    1.16 +double2fraction (double in, int *num, int *denom)
    1.17 +{
    1.18 +    if (in == 29.97) {
    1.19 +        *num = 30000;
    1.20 +        *denom = 1001;
    1.21 +    } else if (in == 23.976) {
    1.22 +        *num = 24000;
    1.23 +        *denom = 1001;
    1.24 +    } else {
    1.25 +        *denom = 1;
    1.26 +        while (in - floor(in) >= 0.1) {
    1.27 +            *denom *= 10;
    1.28 +            in *= 10.0;
    1.29 +        }
    1.30 +        *num = (int)floor(in);
    1.31 +    }
    1.32 +}
    1.33 +
    1.34  static void
    1.35  gst_nuv_demux_base_init (gpointer klass)
    1.36  {
    1.37 @@ -233,6 +253,8 @@
    1.38    h->i_mode = GPOINTER_TO_INT (buffer->data[36]);
    1.39    h->d_aspect = READ_DOUBLE_FROM_LE (&buffer->data[40]);
    1.40    h->d_fps = READ_DOUBLE_FROM_LE (&buffer->data[48]);
    1.41 +  /* get the num and denom values from fps */
    1.42 +  double2fraction (h->d_fps, &h->i_fpsn, &h->i_fpsd);
    1.43    h->i_video_blocks = GST_READ_UINT32_LE (&buffer->data[56]);
    1.44    h->i_audio_blocks = GST_READ_UINT32_LE (&buffer->data[60]);
    1.45    h->i_text_blocks = GST_READ_UINT32_LE (&buffer->data[64]);
    1.46 @@ -378,6 +400,54 @@
    1.47    gst_buffer_unref (buff);
    1.48    return res;
    1.49  }
    1.50 +static const GstQueryType *
    1.51 +gst_nuv_demux_get_src_query_types (GstPad * pad)
    1.52 +{
    1.53 +  static const GstQueryType src_types[] = {
    1.54 +    GST_QUERY_POSITION,
    1.55 +    GST_QUERY_DURATION,
    1.56 +    0
    1.57 +  };
    1.58 +
    1.59 +  return src_types;
    1.60 +}
    1.61 +
    1.62 +static gboolean
    1.63 +gst_nuv_demux_handle_src_query (GstPad * pad, GstQuery * query)
    1.64 +{
    1.65 +  gboolean res = FALSE;
    1.66 +  GstNuvDemux *nuv = GST_NUV_DEMUX (gst_pad_get_parent (pad));
    1.67 +
    1.68 +  switch (GST_QUERY_TYPE (query)) {
    1.69 +    case GST_QUERY_POSITION:
    1.70 +      if (GST_CLOCK_TIME_IS_VALID (nuv->last_frame_time)) {
    1.71 +        gst_query_set_position (query, GST_FORMAT_TIME,
    1.72 +            nuv->last_frame_time);
    1.73 +        res = TRUE;
    1.74 +        GST_DEBUG_OBJECT (nuv, "POS %d", nuv->last_frame_time);
    1.75 +      }
    1.76 +      break;
    1.77 +    case GST_QUERY_DURATION:
    1.78 +      if (nuv->duration != 0) {
    1.79 +        gint64 total;
    1.80 +        gint64 fps;
    1.81 +        
    1.82 +        fps = nuv->h->i_fpsn / nuv->h->i_fpsd;
    1.83 +        total = gst_util_uint64_scale_int (GST_SECOND, nuv->h->i_video_blocks, fps);
    1.84 +        gst_query_set_duration (query, GST_FORMAT_TIME, total);
    1.85 +        GST_DEBUG_OBJECT (nuv, "DURATION %d", total);
    1.86 +        res = TRUE;
    1.87 +      }
    1.88 +      break;
    1.89 +    default:
    1.90 +      res = FALSE;
    1.91 +      break;
    1.92 +  }
    1.93 +
    1.94 +  gst_object_unref (nuv);
    1.95 +
    1.96 +  return res;
    1.97 +}
    1.98  
    1.99  //TODO: create a function to control events and send to src pads
   1.100  static void
   1.101 @@ -393,7 +463,7 @@
   1.102          "divxversion", G_TYPE_INT, 4,
   1.103          "width", G_TYPE_INT, nuv->h->i_width,
   1.104          "height", G_TYPE_INT, nuv->h->i_height,
   1.105 -        "framerate", GST_TYPE_FRACTION, (gint) (nuv->h->d_fps * 1000.0f), 1000,
   1.106 +        "framerate", GST_TYPE_FRACTION, nuv->h->i_fpsn, nuv->h->i_fpsd,
   1.107          "format", GST_TYPE_FOURCC, nuv->eh->i_video_fcc,
   1.108          "pixel-aspect-ratio", GST_TYPE_FRACTION,
   1.109          (gint) (nuv->h->d_aspect * 1000.0f), 1000, NULL);
   1.110 @@ -401,8 +471,9 @@
   1.111      gst_pad_use_fixed_caps (nuv->src_video_pad);
   1.112      gst_pad_set_caps (nuv->src_video_pad, video_caps);
   1.113      gst_pad_set_active (nuv->src_video_pad, TRUE);
   1.114 +    gst_pad_set_query_type_function (nuv->src_video_pad, gst_nuv_demux_get_src_query_types);
   1.115 +    gst_pad_set_query_function (nuv->src_video_pad, gst_nuv_demux_handle_src_query);
   1.116      gst_element_add_pad (GST_ELEMENT (nuv), nuv->src_video_pad);
   1.117 -
   1.118      gst_caps_unref (video_caps);
   1.119    }
   1.120  
   1.121 @@ -421,6 +492,8 @@
   1.122      gst_pad_use_fixed_caps (nuv->src_audio_pad);
   1.123      gst_pad_set_caps (nuv->src_audio_pad, audio_caps);
   1.124      gst_pad_set_active (nuv->src_audio_pad, TRUE);
   1.125 +    gst_pad_set_query_type_function (nuv->src_video_pad, gst_nuv_demux_get_src_query_types);
   1.126 +    gst_pad_set_query_function (nuv->src_video_pad, gst_nuv_demux_handle_src_query);
   1.127      gst_element_add_pad (GST_ELEMENT (nuv), nuv->src_audio_pad);
   1.128      gst_caps_unref (audio_caps);
   1.129    }
   1.130 @@ -470,6 +543,7 @@
   1.131            h->i_timecode += nuv->time_offset;
   1.132        
   1.133        GST_BUFFER_TIMESTAMP (buf) = h->i_timecode * GST_MSECOND;
   1.134 +      nuv->last_frame_time = h->i_timecode * GST_MSECOND;
   1.135    }
   1.136  
   1.137    switch (h->i_type) {
   1.138 @@ -490,7 +564,7 @@
   1.139                                       GST_CLOCK_TIME_NONE, 0));
   1.140          nuv->new_video_segment = FALSE;
   1.141        }
   1.142 -      GST_BUFFER_OFFSET (buf) = GST_CLOCK_TIME_NONE;
   1.143 +      
   1.144        GST_BUFFER_SIZE (buf) = h->i_length;
   1.145        gst_buffer_set_caps (buf, GST_PAD_CAPS (nuv->src_video_pad));
   1.146        ret = gst_pad_push (nuv->src_video_pad, buf);
   1.147 @@ -518,7 +592,6 @@
   1.148          nuv->new_audio_segment = FALSE;
   1.149        }
   1.150         
   1.151 -      GST_BUFFER_OFFSET (buf) = GST_CLOCK_TIME_NONE;
   1.152        GST_BUFFER_SIZE (buf) = h->i_length;
   1.153        gst_buffer_set_caps (buf, GST_PAD_CAPS (nuv->src_audio_pad));
   1.154        ret = gst_pad_push (nuv->src_audio_pad, buf);
   1.155 @@ -833,12 +906,6 @@
   1.156    if (gst_pad_check_pull_range (sinkpad)) {
   1.157      res = gst_pad_activate_pull (sinkpad, TRUE);
   1.158    } else {
   1.159 -    nuv->mode = NUV_PUSH_MODE;
   1.160 -    if (nuv->adapter) {
   1.161 -      gst_adapter_clear (nuv->adapter);
   1.162 -    } else {
   1.163 -      nuv->adapter = gst_adapter_new ();
   1.164 -    }
   1.165      res = gst_pad_activate_push (sinkpad, TRUE);
   1.166    }
   1.167    g_object_unref (nuv);
   1.168 @@ -851,6 +918,7 @@
   1.169    GstNuvDemux *nuv = GST_NUV_DEMUX (gst_pad_get_parent (sinkpad));
   1.170  
   1.171    if (active) {
   1.172 +    GST_DEBUG_OBJECT (nuv, "activating pull function");
   1.173      nuv->mode = NUV_PULL_MODE;
   1.174      if (nuv->adapter) {
   1.175        gst_adapter_clear (nuv->adapter);
   1.176 @@ -859,6 +927,7 @@
   1.177      }
   1.178      gst_pad_start_task (sinkpad, (GstTaskFunction) gst_nuv_demux_loop, sinkpad);
   1.179    } else {
   1.180 +    GST_DEBUG_OBJECT (nuv, "deactivating pull function");
   1.181      gst_pad_stop_task (sinkpad);
   1.182    }
   1.183    gst_object_unref (nuv);
   1.184 @@ -872,6 +941,12 @@
   1.185    GstNuvDemux *nuv = GST_NUV_DEMUX (gst_pad_get_parent (pad));
   1.186  
   1.187    if (active) {
   1.188 +    nuv->mode = NUV_PUSH_MODE;
   1.189 +    if (nuv->adapter) {
   1.190 +      gst_adapter_clear (nuv->adapter);
   1.191 +    } else {
   1.192 +      nuv->adapter = gst_adapter_new ();
   1.193 +    }
   1.194      GST_DEBUG_OBJECT (nuv, "activating push/chain function");
   1.195    } else {
   1.196      GST_DEBUG_OBJECT (nuv, "deactivating push/chain function");
   1.197 @@ -887,6 +962,7 @@
   1.198  {
   1.199    GstNuvDemux *nuv = GST_NUV_DEMUX (gst_pad_get_parent (pad));
   1.200  
   1.201 +  GST_DEBUG_OBJECT (nuv, " gst_nuv_demux_chain function");
   1.202    gst_adapter_push (nuv->adapter, buf);
   1.203  
   1.204    gst_object_unref (nuv);
   1.205 @@ -958,6 +1034,7 @@
   1.206  
   1.207    switch (transition) {
   1.208      case GST_STATE_CHANGE_PAUSED_TO_READY:
   1.209 +      GST_DEBUG_OBJECT (element, "GST_STATE_CHANGE_PAUSED_TO_READY");
   1.210        gst_nuv_demux_destoy_src_pad (GST_NUV_DEMUX (element));
   1.211        gst_nuv_demux_reset (GST_NUV_DEMUX (element));
   1.212        break;