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 Tue Nov 14 18:02:43 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;
2.1 --- a/gst-plugins-nuvdemux/nuvdemux/gstnuvdemux.h Tue Nov 14 13:34:22 2006 +0000
2.2 +++ b/gst-plugins-nuvdemux/nuvdemux/gstnuvdemux.h Tue Nov 14 18:02:43 2006 +0000
2.3 @@ -71,6 +71,9 @@
2.4
2.5 gdouble d_aspect; /* 1.0 squared pixel */
2.6 gdouble d_fps;
2.7 + //fps num/denom
2.8 + gint i_fpsn;
2.9 + gint i_fpsd;
2.10
2.11 gint i_video_blocks; /* 0 no video, -1 unknown */
2.12 gint i_audio_blocks;
2.13 @@ -164,12 +167,13 @@
2.14
2.15 /* NUV decoding state */
2.16 GstNuvDemuxState state;
2.17 + guint64 duration;
2.18 guint64 offset;
2.19 - guint time_offset;
2.20 + guint64 time_offset;
2.21 + guint64 last_frame_time;
2.22 gboolean new_audio_segment;
2.23 gboolean new_video_segment;
2.24
2.25 -
2.26 /* Mpeg ExtraData */
2.27 guint64 mpeg_data_size;
2.28 GstBuffer *mpeg_buffer;