diff -r 8b867c828e89 -r ac9a990a5733 gst-plugins-nuvdemux/nuvdemux/gstnuvdemux.c --- a/gst-plugins-nuvdemux/nuvdemux/gstnuvdemux.c Tue Nov 14 13:34:22 2006 +0000 +++ b/gst-plugins-nuvdemux/nuvdemux/gstnuvdemux.c Wed Nov 15 14:37:59 2006 +0000 @@ -51,6 +51,7 @@ #include #include #include +#include #include "glib/gi18n.h" #include "gstnuvdemux.h" @@ -132,6 +133,25 @@ #define READ_DOUBLE_FROM_LE(d) *((gdouble* ) (d)) #endif /* G_BYTE_ORDER != G_BIG_ENDIAN */ +static void +double2fraction (double in, int *num, int *denom) +{ + if (in == 29.97) { + *num = 30000; + *denom = 1001; + } else if (in == 23.976) { + *num = 24000; + *denom = 1001; + } else { + *denom = 1; + while (in - floor(in) >= 0.1) { + *denom *= 10; + in *= 10.0; + } + *num = (int)floor(in); + } +} + static void gst_nuv_demux_base_init (gpointer klass) { @@ -233,6 +253,8 @@ h->i_mode = GPOINTER_TO_INT (buffer->data[36]); h->d_aspect = READ_DOUBLE_FROM_LE (&buffer->data[40]); h->d_fps = READ_DOUBLE_FROM_LE (&buffer->data[48]); + /* get the num and denom values from fps */ + double2fraction (h->d_fps, &h->i_fpsn, &h->i_fpsd); h->i_video_blocks = GST_READ_UINT32_LE (&buffer->data[56]); h->i_audio_blocks = GST_READ_UINT32_LE (&buffer->data[60]); h->i_text_blocks = GST_READ_UINT32_LE (&buffer->data[64]); @@ -378,6 +400,54 @@ gst_buffer_unref (buff); return res; } +static const GstQueryType * +gst_nuv_demux_get_src_query_types (GstPad * pad) +{ + static const GstQueryType src_types[] = { + GST_QUERY_POSITION, + GST_QUERY_DURATION, + 0 + }; + + return src_types; +} + +static gboolean +gst_nuv_demux_handle_src_query (GstPad * pad, GstQuery * query) +{ + gboolean res = FALSE; + GstNuvDemux *nuv = GST_NUV_DEMUX (gst_pad_get_parent (pad)); + + switch (GST_QUERY_TYPE (query)) { + case GST_QUERY_POSITION: + if (GST_CLOCK_TIME_IS_VALID (nuv->last_frame_time)) { + gst_query_set_position (query, GST_FORMAT_TIME, + nuv->last_frame_time); + res = TRUE; + GST_DEBUG_OBJECT (nuv, "POS %d", nuv->last_frame_time); + } + break; + case GST_QUERY_DURATION: + if (nuv->duration != 0) { + gint64 total; + gint64 fps; + + fps = nuv->h->i_fpsn / nuv->h->i_fpsd; + total = gst_util_uint64_scale_int (GST_SECOND, nuv->h->i_video_blocks, fps); + gst_query_set_duration (query, GST_FORMAT_TIME, total); + GST_DEBUG_OBJECT (nuv, "DURATION %d", total); + res = TRUE; + } + break; + default: + res = FALSE; + break; + } + + gst_object_unref (nuv); + + return res; +} //TODO: create a function to control events and send to src pads static void @@ -393,7 +463,7 @@ "divxversion", G_TYPE_INT, 4, "width", G_TYPE_INT, nuv->h->i_width, "height", G_TYPE_INT, nuv->h->i_height, - "framerate", GST_TYPE_FRACTION, (gint) (nuv->h->d_fps * 1000.0f), 1000, + "framerate", GST_TYPE_FRACTION, nuv->h->i_fpsn, nuv->h->i_fpsd, "format", GST_TYPE_FOURCC, nuv->eh->i_video_fcc, "pixel-aspect-ratio", GST_TYPE_FRACTION, (gint) (nuv->h->d_aspect * 1000.0f), 1000, NULL); @@ -401,8 +471,9 @@ gst_pad_use_fixed_caps (nuv->src_video_pad); gst_pad_set_caps (nuv->src_video_pad, video_caps); gst_pad_set_active (nuv->src_video_pad, TRUE); + gst_pad_set_query_type_function (nuv->src_video_pad, gst_nuv_demux_get_src_query_types); + gst_pad_set_query_function (nuv->src_video_pad, gst_nuv_demux_handle_src_query); gst_element_add_pad (GST_ELEMENT (nuv), nuv->src_video_pad); - gst_caps_unref (video_caps); } @@ -421,6 +492,8 @@ gst_pad_use_fixed_caps (nuv->src_audio_pad); gst_pad_set_caps (nuv->src_audio_pad, audio_caps); gst_pad_set_active (nuv->src_audio_pad, TRUE); + gst_pad_set_query_type_function (nuv->src_video_pad, gst_nuv_demux_get_src_query_types); + gst_pad_set_query_function (nuv->src_video_pad, gst_nuv_demux_handle_src_query); gst_element_add_pad (GST_ELEMENT (nuv), nuv->src_audio_pad); gst_caps_unref (audio_caps); } @@ -470,6 +543,7 @@ h->i_timecode += nuv->time_offset; GST_BUFFER_TIMESTAMP (buf) = h->i_timecode * GST_MSECOND; + nuv->last_frame_time = h->i_timecode * GST_MSECOND; } switch (h->i_type) { @@ -490,7 +564,7 @@ GST_CLOCK_TIME_NONE, 0)); nuv->new_video_segment = FALSE; } - GST_BUFFER_OFFSET (buf) = GST_CLOCK_TIME_NONE; + 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); @@ -518,7 +592,6 @@ nuv->new_audio_segment = FALSE; } - GST_BUFFER_OFFSET (buf) = GST_CLOCK_TIME_NONE; 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); @@ -833,12 +906,6 @@ if (gst_pad_check_pull_range (sinkpad)) { res = gst_pad_activate_pull (sinkpad, TRUE); } else { - nuv->mode = NUV_PUSH_MODE; - if (nuv->adapter) { - gst_adapter_clear (nuv->adapter); - } else { - nuv->adapter = gst_adapter_new (); - } res = gst_pad_activate_push (sinkpad, TRUE); } g_object_unref (nuv); @@ -851,6 +918,7 @@ GstNuvDemux *nuv = GST_NUV_DEMUX (gst_pad_get_parent (sinkpad)); if (active) { + GST_DEBUG_OBJECT (nuv, "activating pull function"); nuv->mode = NUV_PULL_MODE; if (nuv->adapter) { gst_adapter_clear (nuv->adapter); @@ -859,6 +927,7 @@ } gst_pad_start_task (sinkpad, (GstTaskFunction) gst_nuv_demux_loop, sinkpad); } else { + GST_DEBUG_OBJECT (nuv, "deactivating pull function"); gst_pad_stop_task (sinkpad); } gst_object_unref (nuv); @@ -872,6 +941,12 @@ GstNuvDemux *nuv = GST_NUV_DEMUX (gst_pad_get_parent (pad)); if (active) { + nuv->mode = NUV_PUSH_MODE; + if (nuv->adapter) { + gst_adapter_clear (nuv->adapter); + } else { + nuv->adapter = gst_adapter_new (); + } GST_DEBUG_OBJECT (nuv, "activating push/chain function"); } else { GST_DEBUG_OBJECT (nuv, "deactivating push/chain function"); @@ -887,6 +962,7 @@ { GstNuvDemux *nuv = GST_NUV_DEMUX (gst_pad_get_parent (pad)); + GST_DEBUG_OBJECT (nuv, " gst_nuv_demux_chain function"); gst_adapter_push (nuv->adapter, buf); gst_object_unref (nuv); @@ -958,6 +1034,7 @@ switch (transition) { case GST_STATE_CHANGE_PAUSED_TO_READY: + GST_DEBUG_OBJECT (element, "GST_STATE_CHANGE_PAUSED_TO_READY"); gst_nuv_demux_destoy_src_pad (GST_NUV_DEMUX (element)); gst_nuv_demux_reset (GST_NUV_DEMUX (element)); break;