1.1 --- a/gst-plugins-nuvdemux/nuvdemux/gstnuvdemux.c Fri Nov 17 13:09:12 2006 +0000
1.2 +++ b/gst-plugins-nuvdemux/nuvdemux/gstnuvdemux.c Fri Nov 17 13:18:48 2006 +0000
1.3 @@ -56,11 +56,12 @@
1.4 #include "glib/gi18n.h"
1.5 #include "gstnuvdemux.h"
1.6
1.7 +#define GST_NUV_DEMUX_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GST_TYPE_NUV_DEMUX, GstNuvDemuxPrivate))
1.8 +
1.9 GST_DEBUG_CATEGORY_STATIC (nuvdemux_debug);
1.10 #define GST_CAT_DEFAULT nuvdemux_debug
1.11 +#define GST_FLOW_ERROR_NO_DATA -101
1.12
1.13 -
1.14 -#define GST_FLOW_ERROR_NO_DATA -101
1.15 enum
1.16 {
1.17 NUV_PUSH_MODE = 0,
1.18 @@ -76,6 +77,155 @@
1.19 "Renato Araujo Oliveira Filho <renato.filho@indt.org.br>,"
1.20 "Rosfran Borges <rosfran.borges@indt.org.br>");
1.21
1.22 +
1.23 +/* file header */
1.24 +typedef struct
1.25 +{
1.26 + gchar id[12]; /* "NuppelVideo\0" or "MythTVVideo\0" */
1.27 + gchar version[5]; /* "x.xx\0" */
1.28 +
1.29 + gint i_width;
1.30 + gint i_height;
1.31 + gint i_width_desired;
1.32 + gint i_height_desired;
1.33 +
1.34 + gchar i_mode; /* P progressive, I interlaced */
1.35 +
1.36 + gdouble d_aspect; /* 1.0 squared pixel */
1.37 + gdouble d_fps;
1.38 + //fps num/denom
1.39 + gint i_fpsn;
1.40 + gint i_fpsd;
1.41 +
1.42 + gint i_video_blocks; /* 0 no video, -1 unknown */
1.43 + gint i_audio_blocks;
1.44 + gint i_text_blocks;
1.45 +
1.46 + gint i_keyframe_distance;
1.47 +
1.48 +} nuv_header;
1.49 +
1.50 +/* frame header */
1.51 +typedef struct
1.52 +{
1.53 + gchar i_type; /* A: audio, V: video, S: sync; T: test
1.54 + R: Seekpoint (string:RTjjjjjjjj)
1.55 + D: Extra data for codec */
1.56 + gchar i_compression; /* V: 0 uncompressed
1.57 + 1 RTJpeg
1.58 + 2 RTJpeg+lzo
1.59 + N black frame
1.60 + L copy last
1.61 + A: 0 uncompressed (44100 1-bits, 2ch)
1.62 + 1 lzo
1.63 + 2 layer 2
1.64 + 3 layer 3
1.65 + F flac
1.66 + S shorten
1.67 + N null frame loudless
1.68 + L copy last
1.69 + S: B audio and vdeo sync point
1.70 + A audio sync info (timecode == effective
1.71 + dsp frequency*100)
1.72 + V next video sync (timecode == next video
1.73 + frame num)
1.74 + S audio,video,text correlation */
1.75 + gchar i_keyframe; /* 0 keyframe, else no no key frame */
1.76 + guint8 i_filters; /* 0x01: gauss 5 pixel (8,2,2,2,2)/16
1.77 + 0x02: gauss 5 pixel (8,1,1,1,1)/12
1.78 + 0x04: cartoon filter */
1.79 +
1.80 + gint32 i_timecode; /* ms */
1.81 +
1.82 + gint i_length; /* V,A,T: length of following data
1.83 + S: length of packet correl */
1.84 +} nuv_frame_header;
1.85 +
1.86 +/* FIXME Not sure of this one */
1.87 +typedef struct
1.88 +{
1.89 + gint i_version;
1.90 + guint32 i_video_fcc;
1.91 +
1.92 + guint32 i_audio_fcc;
1.93 + gint i_audio_sample_rate;
1.94 + gint i_audio_bits_per_sample;
1.95 + gint i_audio_channels;
1.96 + gint i_audio_compression_ratio;
1.97 + gint i_audio_quality;
1.98 + gint i_rtjpeg_quality;
1.99 + gint i_rtjpeg_luma_filter;
1.100 + gint i_rtjpeg_chroma_filter;
1.101 + gint i_lavc_bitrate;
1.102 + gint i_lavc_qmin;
1.103 + gint i_lavc_qmax;
1.104 + gint i_lavc_maxqdiff;
1.105 + gint64 i_seekable_offset;
1.106 + gint64 i_keyframe_adjust_offset;
1.107 +
1.108 +} nuv_extended_header;
1.109 +
1.110 +typedef enum {
1.111 + GST_NUV_DEMUX_START,
1.112 + GST_NUV_DEMUX_HEADER_DATA,
1.113 + GST_NUV_DEMUX_EXTRA_DATA,
1.114 + GST_NUV_DEMUX_MPEG_DATA,
1.115 + GST_NUV_DEMUX_EXTEND_HEADER,
1.116 + GST_NUV_DEMUX_EXTEND_HEADER_DATA,
1.117 + GST_NUV_DEMUX_FRAME_HEADER,
1.118 + GST_NUV_DEMUX_MOVI,
1.119 + GST_NUV_DEMUX_INVALID_DATA
1.120 +} GstNuvDemuxState;
1.121 +
1.122 +struct _GstNuvDemuxPrivate {
1.123 + /* used for indicate the mode */
1.124 + guint mode;
1.125 +
1.126 + /* used on push mode */
1.127 + GstAdapter *adapter;
1.128 +
1.129 + /* pads */
1.130 + GstPad *sinkpad;
1.131 + GstPad *src_video_pad;
1.132 + GstPad *src_audio_pad;
1.133 +
1.134 + /* Flow control */
1.135 + GstFlowReturn last_video_return;
1.136 + GstFlowReturn last_audio_return;
1.137 +
1.138 + /* NUV decoding state */
1.139 + GstNuvDemuxState state;
1.140 + GstSegment segment;
1.141 + guint64 last_update;
1.142 + guint64 offset;
1.143 + guint64 streamer_offset;
1.144 +
1.145 + /* duration information */
1.146 + gint64 duration_bytes;
1.147 + gint64 duration_time;
1.148 + gint64 duration_average;
1.149 +
1.150 + /* segment control info */
1.151 + gboolean new_audio_segment;
1.152 + gboolean new_video_segment;
1.153 +
1.154 + /* Mpeg ExtraData */
1.155 + guint64 mpeg_data_size;
1.156 + GstBuffer *mpeg_buffer;
1.157 +
1.158 + /* Headers */
1.159 + nuv_header *h;
1.160 + nuv_extended_header *eh;
1.161 + nuv_frame_header *fh;
1.162 +
1.163 + /* anothers info */
1.164 + gint64 time_start;
1.165 + gint64 time_diff;
1.166 + gint64 time_qos;
1.167 + guint64 last_frame_time;
1.168 +};
1.169 +
1.170 +
1.171 static GstStaticPadTemplate sink_template = GST_STATIC_PAD_TEMPLATE ("sink",
1.172 GST_PAD_SINK,
1.173 GST_PAD_ALWAYS,
1.174 @@ -93,6 +243,7 @@
1.175 GST_PAD_SOMETIMES,
1.176 GST_STATIC_CAPS_ANY);
1.177
1.178 +static void gst_nuv_demux_dispose (GObject * object);
1.179 static void gst_nuv_demux_finalize (GObject * object);
1.180 static GstStateChangeReturn gst_nuv_demux_change_state (GstElement * element,
1.181 GstStateChange transition);
1.182 @@ -101,18 +252,25 @@
1.183 static GstFlowReturn gst_nuv_demux_play (GstPad * pad);
1.184 static gboolean gst_nuv_demux_sink_activate_pull (GstPad * sinkpad,
1.185 gboolean active);
1.186 -static gboolean gst_nuv_demux_sink_activate_push (GstPad * pad,
1.187 +static gboolean gst_nuv_demux_sink_activate_push (GstPad * pad,
1.188 gboolean active);
1.189 static gboolean gst_nuv_demux_sink_activate (GstPad * sinkpad);
1.190 +static gboolean gst_nuv_demux_sink_event (GstPad *pad, GstEvent *event);
1.191 static GstFlowReturn gst_nuv_demux_read_bytes (GstNuvDemux * nuv, guint64 size,
1.192 gboolean move, GstBuffer ** buffer);
1.193 static void gst_nuv_demux_reset (GstNuvDemux * nuv);
1.194 static void gst_nuv_demux_destoy_src_pad (GstNuvDemux * nuv);
1.195 static void gst_nuv_demux_send_eos (GstNuvDemux * nuv);
1.196 +static void gst_nuv_demux_update_duration (GstNuvDemux *nuv, guint64 current_timestamp);
1.197 +static gint64 gst_nuv_demux_get_bytes_duration (GstNuvDemux *nuv);
1.198 +static gint64 gst_nuv_demux_get_time_duration (GstNuvDemux *nuv);
1.199
1.200 -/* GObject methods */
1.201 +
1.202 GST_BOILERPLATE (GstNuvDemux, gst_nuv_demux, GstElement, GST_TYPE_ELEMENT);
1.203
1.204 +/******************************************************************************
1.205 + * Utils function
1.206 + ******************************************************************************/
1.207 #if G_BYTE_ORDER == G_BIG_ENDIAN
1.208 static inline gdouble
1.209 _gdouble_swap_le_be (gdouble * d)
1.210 @@ -133,7 +291,7 @@
1.211 #define READ_DOUBLE_FROM_LE(d) *((gdouble* ) (d))
1.212 #endif /* G_BYTE_ORDER != G_BIG_ENDIAN */
1.213
1.214 -static void
1.215 +static void
1.216 double2fraction (double in, int *num, int *denom)
1.217 {
1.218 if (in == 29.97) {
1.219 @@ -152,6 +310,8 @@
1.220 }
1.221 }
1.222
1.223 +/* GObject Functions */
1.224 +
1.225 static void
1.226 gst_nuv_demux_base_init (gpointer klass)
1.227 {
1.228 @@ -179,54 +339,55 @@
1.229
1.230 parent_class = g_type_class_peek_parent (klass);
1.231
1.232 + gobject_class->dispose = gst_nuv_demux_dispose;
1.233 gobject_class->finalize = gst_nuv_demux_finalize;
1.234 gstelement_class->change_state = gst_nuv_demux_change_state;
1.235 +
1.236 + g_type_class_add_private (gobject_class, sizeof (GstNuvDemuxPrivate));
1.237 }
1.238
1.239 static void
1.240 gst_nuv_demux_init (GstNuvDemux * nuv, GstNuvDemuxClass * nuv_class)
1.241 {
1.242 - nuv->sinkpad = gst_pad_new_from_static_template (&sink_template, "sink");
1.243 + nuv->priv = GST_NUV_DEMUX_GET_PRIVATE (nuv);
1.244 + nuv->priv->sinkpad = gst_pad_new_from_static_template (&sink_template, "sink");
1.245 + gst_pad_set_activate_function (nuv->priv->sinkpad, gst_nuv_demux_sink_activate);
1.246 + gst_pad_set_activatepull_function (nuv->priv->sinkpad,
1.247 + gst_nuv_demux_sink_activate_pull);
1.248 + gst_pad_set_activatepush_function (nuv->priv->sinkpad,
1.249 + gst_nuv_demux_sink_activate_push);
1.250 + gst_pad_set_chain_function (nuv->priv->sinkpad,
1.251 + GST_DEBUG_FUNCPTR (gst_nuv_demux_chain));
1.252 + gst_pad_set_event_function (nuv->priv->sinkpad,
1.253 + gst_nuv_demux_sink_event);
1.254 + gst_element_add_pad (GST_ELEMENT (nuv), nuv->priv->sinkpad);
1.255
1.256 - gst_pad_set_activate_function (nuv->sinkpad, gst_nuv_demux_sink_activate);
1.257 + nuv->priv->new_audio_segment = TRUE;
1.258 + nuv->priv->new_video_segment = TRUE;
1.259
1.260 - gst_pad_set_activatepull_function (nuv->sinkpad,
1.261 - gst_nuv_demux_sink_activate_pull);
1.262 + gst_nuv_demux_reset (nuv);
1.263 +}
1.264
1.265 - gst_pad_set_activatepush_function (nuv->sinkpad,
1.266 - gst_nuv_demux_sink_activate_push);
1.267 +static void
1.268 +gst_nuv_demux_dispose (GObject * object)
1.269 +{
1.270 + GstNuvDemux *nuv = GST_NUV_DEMUX (object);
1.271
1.272 - gst_pad_set_chain_function (nuv->sinkpad,
1.273 - GST_DEBUG_FUNCPTR (gst_nuv_demux_chain));
1.274 + if (nuv->priv->mpeg_buffer != NULL) {
1.275 + gst_buffer_unref (nuv->priv->mpeg_buffer);
1.276 + }
1.277
1.278 - gst_element_add_pad (GST_ELEMENT (nuv), nuv->sinkpad);
1.279 -
1.280 - nuv->adapter = NULL;
1.281 - nuv->mpeg_buffer = NULL;
1.282 - nuv->h = NULL;
1.283 - nuv->eh = NULL;
1.284 - nuv->fh = NULL;
1.285 + gst_nuv_demux_reset (GST_NUV_DEMUX (object));
1.286 + gst_nuv_demux_destoy_src_pad (GST_NUV_DEMUX (object));
1.287
1.288 - nuv->new_audio_segment = TRUE;
1.289 - nuv->new_video_segment = TRUE;
1.290 -
1.291 - gst_nuv_demux_reset (nuv);
1.292 + if (nuv->priv->adapter != NULL) {
1.293 + gst_object_unref (nuv->priv->adapter);
1.294 + }
1.295 }
1.296
1.297 static void
1.298 gst_nuv_demux_finalize (GObject * object)
1.299 {
1.300 - GstNuvDemux *nuv = GST_NUV_DEMUX (object);
1.301 -
1.302 - if (nuv->mpeg_buffer != NULL) {
1.303 - gst_buffer_unref (nuv->mpeg_buffer);
1.304 - }
1.305 -
1.306 - gst_nuv_demux_destoy_src_pad (nuv);
1.307 - gst_nuv_demux_reset (nuv);
1.308 - if (nuv->adapter != NULL) {
1.309 - gst_object_unref (nuv->adapter);
1.310 - }
1.311 G_OBJECT_CLASS (parent_class)->finalize (object);
1.312 }
1.313
1.314 @@ -274,10 +435,11 @@
1.315 static GstFlowReturn
1.316 gst_nuv_demux_stream_header_data (GstNuvDemux * nuv)
1.317 {
1.318 - GstFlowReturn res = gst_nuv_demux_header_load (nuv, &nuv->h);
1.319 + GstFlowReturn res;
1.320
1.321 + res = gst_nuv_demux_header_load (nuv, &nuv->priv->h);
1.322 if (res == GST_FLOW_OK)
1.323 - nuv->state = GST_NUV_DEMUX_EXTRA_DATA;
1.324 + nuv->priv->state = GST_NUV_DEMUX_EXTRA_DATA;
1.325 return res;
1.326 }
1.327
1.328 @@ -296,10 +458,10 @@
1.329 } else {
1.330 if (strncmp ((gchar *) file_header->data, "MythTVVideo", 11) ||
1.331 strncmp ((gchar *) file_header->data, "NuppelVideo", 11)) {
1.332 - nuv->state = GST_NUV_DEMUX_HEADER_DATA;
1.333 + nuv->priv->state = GST_NUV_DEMUX_HEADER_DATA;
1.334 } else {
1.335 GST_DEBUG_OBJECT (nuv, "error parsing file header");
1.336 - nuv->state = GST_NUV_DEMUX_INVALID_DATA;
1.337 + nuv->priv->state = GST_NUV_DEMUX_INVALID_DATA;
1.338 res = GST_FLOW_ERROR;
1.339 }
1.340 }
1.341 @@ -336,7 +498,7 @@
1.342 h->i_filters = GPOINTER_TO_INT (data[3]);
1.343 h->i_timecode = GST_READ_UINT32_LE (&data[4]);
1.344 h->i_length = GST_READ_UINT32_LE (&data[8]);
1.345 -
1.346 +
1.347 GST_DEBUG_OBJECT (nuv, "frame hdr: t=%c c=%c k=%d f=0x%x timecode=%d l=%d",
1.348 h->i_type,
1.349 h->i_compression ? h->i_compression : ' ',
1.350 @@ -400,11 +562,15 @@
1.351 gst_buffer_unref (buff);
1.352 return res;
1.353 }
1.354 +
1.355 +
1.356 +/* Query Functions */
1.357 static const GstQueryType *
1.358 gst_nuv_demux_get_src_query_types (GstPad * pad)
1.359 {
1.360 static const GstQueryType src_types[] = {
1.361 GST_QUERY_POSITION,
1.362 + GST_QUERY_DURATION,
1.363 0
1.364 };
1.365
1.366 @@ -419,11 +585,23 @@
1.367
1.368 switch (GST_QUERY_TYPE (query)) {
1.369 case GST_QUERY_POSITION:
1.370 - if (GST_CLOCK_TIME_IS_VALID (nuv->last_frame_time)) {
1.371 - gst_query_set_position (query, GST_FORMAT_TIME,
1.372 - nuv->last_frame_time);
1.373 + if (GST_CLOCK_TIME_IS_VALID (nuv->priv->last_frame_time)) {
1.374 +
1.375 + gst_query_set_position (query, GST_FORMAT_TIME, nuv->priv->last_frame_time);
1.376 res = TRUE;
1.377 - GST_DEBUG_OBJECT (nuv, "POS %d", nuv->last_frame_time);
1.378 + }
1.379 + break;
1.380 + case GST_QUERY_DURATION:
1.381 + {
1.382 + gint64 duration = 0;
1.383 + duration = gst_nuv_demux_get_time_duration (nuv);
1.384 + if (duration == GST_CLOCK_TIME_NONE) {
1.385 + duration = nuv->priv->duration_average;
1.386 + }
1.387 + if (duration != GST_CLOCK_TIME_NONE) {
1.388 + gst_query_set_duration (query, GST_FORMAT_TIME, duration);
1.389 + res = TRUE;
1.390 + }
1.391 }
1.392 break;
1.393 default:
1.394 @@ -436,52 +614,48 @@
1.395 return res;
1.396 }
1.397
1.398 -//TODO: create a function to control events and send to src pads
1.399 +static GstPad*
1.400 +gst_nuv_demux_create_pad (GstNuvDemux *nuv, GstCaps *caps, GstStaticPadTemplate *template, const gchar* name)
1.401 +{
1.402 + GstPad *pad = NULL;
1.403 + pad = gst_pad_new_from_static_template (template, name);
1.404 + gst_pad_use_fixed_caps (pad);
1.405 + gst_pad_set_caps (pad, caps);
1.406 + gst_pad_set_active (pad, TRUE);
1.407 + gst_element_add_pad (GST_ELEMENT (nuv), pad);
1.408 +
1.409 + return pad;
1.410 +}
1.411 +
1.412 static void
1.413 gst_nuv_demux_create_pads (GstNuvDemux * nuv)
1.414 {
1.415 - if (nuv->h->i_video_blocks != 0) {
1.416 + if (nuv->priv->h->i_video_blocks != 0) {
1.417 GstCaps *video_caps = NULL;
1.418
1.419 - nuv->src_video_pad =
1.420 - gst_pad_new_from_static_template (&video_src_template, "video_src");
1.421 -
1.422 video_caps = gst_caps_new_simple ("video/x-divx",
1.423 "divxversion", G_TYPE_INT, 4,
1.424 - "width", G_TYPE_INT, nuv->h->i_width,
1.425 - "height", G_TYPE_INT, nuv->h->i_height,
1.426 - "framerate", GST_TYPE_FRACTION, nuv->h->i_fpsn, nuv->h->i_fpsd,
1.427 - "format", GST_TYPE_FOURCC, nuv->eh->i_video_fcc,
1.428 + "width", G_TYPE_INT, nuv->priv->h->i_width,
1.429 + "height", G_TYPE_INT, nuv->priv->h->i_height,
1.430 + "framerate", GST_TYPE_FRACTION, nuv->priv->h->i_fpsn, nuv->priv->h->i_fpsd,
1.431 + "format", GST_TYPE_FOURCC, nuv->priv->eh->i_video_fcc,
1.432 "pixel-aspect-ratio", GST_TYPE_FRACTION,
1.433 - (gint) (nuv->h->d_aspect * 1000.0f), 1000, NULL);
1.434 + (gint) (nuv->priv->h->d_aspect * 1000.0f), 1000, NULL);
1.435
1.436 - gst_pad_use_fixed_caps (nuv->src_video_pad);
1.437 - gst_pad_set_caps (nuv->src_video_pad, video_caps);
1.438 - gst_pad_set_active (nuv->src_video_pad, TRUE);
1.439 - gst_pad_set_query_type_function (nuv->src_video_pad, gst_nuv_demux_get_src_query_types);
1.440 - gst_pad_set_query_function (nuv->src_video_pad, gst_nuv_demux_handle_src_query);
1.441 - gst_element_add_pad (GST_ELEMENT (nuv), nuv->src_video_pad);
1.442 + nuv->priv->src_video_pad = gst_nuv_demux_create_pad (nuv, video_caps, &video_src_template, "video_src");
1.443 gst_caps_unref (video_caps);
1.444 }
1.445
1.446 - if (nuv->h->i_audio_blocks != 0) {
1.447 + if (nuv->priv->h->i_audio_blocks != 0) {
1.448 GstCaps *audio_caps = NULL;
1.449
1.450 - nuv->src_audio_pad =
1.451 - gst_pad_new_from_static_template (&audio_src_template, "audio_src");
1.452 + audio_caps = gst_caps_new_simple ("audio/mpeg",
1.453 + "rate", G_TYPE_INT, nuv->priv->eh->i_audio_sample_rate,
1.454 + "format", GST_TYPE_FOURCC, nuv->priv->eh->i_audio_fcc,
1.455 + "channels", G_TYPE_INT, nuv->priv->eh->i_audio_channels,
1.456 + "mpegversion", G_TYPE_INT, nuv->priv->eh->i_version, NULL);
1.457
1.458 - audio_caps = gst_caps_new_simple ("audio/mpeg",
1.459 - "rate", G_TYPE_INT, nuv->eh->i_audio_sample_rate,
1.460 - "format", GST_TYPE_FOURCC, nuv->eh->i_audio_fcc,
1.461 - "channels", G_TYPE_INT, nuv->eh->i_audio_channels,
1.462 - "mpegversion", G_TYPE_INT, nuv->eh->i_version, NULL);
1.463 -
1.464 - gst_pad_use_fixed_caps (nuv->src_audio_pad);
1.465 - gst_pad_set_caps (nuv->src_audio_pad, audio_caps);
1.466 - gst_pad_set_active (nuv->src_audio_pad, TRUE);
1.467 - gst_pad_set_query_type_function (nuv->src_video_pad, gst_nuv_demux_get_src_query_types);
1.468 - gst_pad_set_query_function (nuv->src_video_pad, gst_nuv_demux_handle_src_query);
1.469 - gst_element_add_pad (GST_ELEMENT (nuv), nuv->src_audio_pad);
1.470 + nuv->priv->src_audio_pad = gst_nuv_demux_create_pad (nuv, audio_caps, &audio_src_template, "audio_src");
1.471 gst_caps_unref (audio_caps);
1.472 }
1.473
1.474 @@ -493,49 +667,53 @@
1.475 {
1.476 GstFlowReturn ret = GST_FLOW_OK;
1.477
1.478 - if (nuv->fh != NULL)
1.479 + if (nuv->priv->fh != NULL)
1.480 {
1.481 - g_free (nuv->fh);
1.482 - nuv->fh = NULL;
1.483 + g_free (nuv->priv->fh);
1.484 + nuv->priv->fh = NULL;
1.485 }
1.486 -
1.487 - ret = gst_nuv_demux_frame_header_load (nuv, &nuv->fh);
1.488 +
1.489 + ret = gst_nuv_demux_frame_header_load (nuv, &nuv->priv->fh);
1.490 if (ret != GST_FLOW_OK)
1.491 return ret;
1.492
1.493 - nuv->state = GST_NUV_DEMUX_MOVI;
1.494 + nuv->priv->state = GST_NUV_DEMUX_MOVI;
1.495 return ret;
1.496 }
1.497
1.498 static gboolean
1.499 gst_nuv_combine_flow (GstNuvDemux *nuv)
1.500 {
1.501 - GstFlowReturn ret_video = nuv->last_video_return;
1.502 - GstFlowReturn ret_audio = nuv->last_audio_return;
1.503 + GstFlowReturn ret_video = nuv->priv->last_video_return;
1.504 + GstFlowReturn ret_audio = nuv->priv->last_audio_return;
1.505
1.506 if ((ret_video != GST_FLOW_OK) &&
1.507 (ret_audio != GST_FLOW_OK))
1.508 return FALSE;
1.509
1.510 - if (GST_FLOW_IS_FATAL (nuv->last_video_return))
1.511 + if (GST_FLOW_IS_FATAL (ret_video))
1.512 return FALSE;
1.513
1.514 - if (GST_FLOW_IS_FATAL (nuv->last_audio_return))
1.515 + if (GST_FLOW_IS_FATAL (ret_audio))
1.516 return FALSE;
1.517
1.518 - return TRUE;
1.519 + return TRUE;
1.520 }
1.521
1.522 static GstFlowReturn
1.523 gst_nuv_demux_stream_data (GstNuvDemux * nuv)
1.524 {
1.525 GstFlowReturn ret = GST_FLOW_OK;
1.526 + GstPad *pad = NULL;
1.527 + guint64 timestamp;
1.528 GstBuffer *buf = NULL;
1.529 - nuv_frame_header *h = nuv->fh;
1.530 + nuv_frame_header *h = NULL;
1.531 +
1.532 + h = nuv->priv->fh;
1.533
1.534 if (h->i_type == 'R')
1.535 goto done;
1.536 -
1.537 +
1.538 if (h->i_length > 0) {
1.539 ret = gst_nuv_demux_read_bytes (nuv, h->i_length, TRUE, &buf);
1.540 if ((ret != GST_FLOW_OK) || (buf == NULL))
1.541 @@ -543,81 +721,74 @@
1.542
1.543 if (h->i_timecode < 0) {
1.544 h->i_timecode = h->i_timecode * -1;
1.545 - nuv->time_offset = h->i_timecode;
1.546 + nuv->priv->time_diff = h->i_timecode;
1.547 }
1.548 else
1.549 - h->i_timecode += nuv->time_offset;
1.550 -
1.551 - GST_BUFFER_TIMESTAMP (buf) = h->i_timecode * GST_MSECOND;
1.552 - nuv->last_frame_time = h->i_timecode * GST_MSECOND;
1.553 + h->i_timecode += nuv->priv->time_diff;
1.554 +
1.555 + timestamp = h->i_timecode * GST_MSECOND;
1.556 +
1.557 + GST_BUFFER_SIZE (buf) = h->i_length;
1.558 + GST_BUFFER_TIMESTAMP (buf) = timestamp;
1.559 +
1.560 + if ((h->i_type == 'V') || (h->i_type == 'A')) {
1.561 + }
1.562 }
1.563 + else {
1.564 + goto done;
1.565 + }
1.566 +
1.567
1.568 switch (h->i_type) {
1.569 case 'V':
1.570 {
1.571 - if (h->i_length == 0)
1.572 - break;
1.573 -
1.574 - if (nuv->new_video_segment) {
1.575 + pad = nuv->priv->src_video_pad;
1.576 +
1.577 + if (nuv->priv->new_video_segment) {
1.578 /* send new segment event*/
1.579 - gst_pad_push_event (nuv->src_video_pad,
1.580 - gst_event_new_new_segment (TRUE, 1.0, GST_FORMAT_TIME, 0,
1.581 + gst_pad_push_event (nuv->priv->src_video_pad,
1.582 + gst_event_new_new_segment (TRUE, 1.0, GST_FORMAT_TIME, 0,
1.583 GST_CLOCK_TIME_NONE, 0));
1.584 - nuv->new_video_segment = FALSE;
1.585 +
1.586 + if (nuv->priv->time_start == GST_CLOCK_TIME_NONE) {
1.587 + nuv->priv->time_start = timestamp;
1.588 + }
1.589 + nuv->priv->new_video_segment = FALSE;
1.590 }
1.591 -
1.592 - GST_BUFFER_SIZE (buf) = h->i_length;
1.593 - gst_buffer_set_caps (buf, GST_PAD_CAPS (nuv->src_video_pad));
1.594 - nuv->last_video_return = gst_pad_push (nuv->src_video_pad, buf);
1.595 - if (!gst_nuv_combine_flow (nuv)) {
1.596 - ret = nuv->last_video_return;
1.597 - GST_WARNING_OBJECT (nuv, "error: %d pushing on srcpad %s, is linked? = %d",
1.598 - nuv->last_video_return, gst_pad_get_name (nuv->src_video_pad), gst_pad_is_linked (nuv->src_video_pad));
1.599 - }
1.600 +
1.601 break;
1.602 }
1.603 case 'A':
1.604 {
1.605 - if (h->i_length == 0)
1.606 - break;
1.607 -
1.608 - if (nuv->new_audio_segment) {
1.609 + pad = nuv->priv->src_audio_pad;
1.610 +
1.611 + if (nuv->priv->new_audio_segment) {
1.612 /* send new segment event*/
1.613 - gst_pad_push_event (nuv->src_audio_pad,
1.614 - gst_event_new_new_segment (TRUE, 1.0, GST_FORMAT_TIME, 0,
1.615 + gst_pad_push_event (nuv->priv->src_audio_pad,
1.616 + gst_event_new_new_segment (TRUE, 1.0, GST_FORMAT_TIME, 0,
1.617 GST_CLOCK_TIME_NONE, 0));
1.618 - nuv->new_audio_segment = FALSE;
1.619 +
1.620 + if (nuv->priv->time_start == GST_CLOCK_TIME_NONE) {
1.621 + nuv->priv->time_start = timestamp;
1.622 + }
1.623 + nuv->priv->new_audio_segment = FALSE;
1.624 }
1.625 -
1.626 - GST_BUFFER_SIZE (buf) = h->i_length;
1.627 - gst_buffer_set_caps (buf, GST_PAD_CAPS (nuv->src_audio_pad));
1.628 - nuv->last_audio_return = gst_pad_push (nuv->src_audio_pad, buf);
1.629 - if (!gst_nuv_combine_flow (nuv)) {
1.630 - ret = nuv->last_audio_return;
1.631 - GST_WARNING_OBJECT (nuv, "Error %d pushing on srcpad %s, is linked? = %d",
1.632 - nuv->last_audio_return, gst_pad_get_name (nuv->src_audio_pad), gst_pad_is_linked (nuv->src_audio_pad));
1.633 - }
1.634 +
1.635 break;
1.636 }
1.637 case 'S':
1.638 {
1.639 switch (h->i_compression) {
1.640 case 'V':
1.641 - if ( !gst_pad_is_linked( nuv->src_video_pad ) )
1.642 - break;
1.643 -
1.644 GST_DEBUG_OBJECT (nuv, "sending new video segment: %d", h->i_timecode);
1.645 - gst_pad_push_event (nuv->src_video_pad,
1.646 - gst_event_new_new_segment (TRUE, 1.0, GST_FORMAT_TIME, h->i_timecode * GST_MSECOND,
1.647 + gst_pad_push_event (nuv->priv->src_video_pad,
1.648 + gst_event_new_new_segment (TRUE, 1.0, GST_FORMAT_TIME, h->i_timecode * GST_MSECOND,
1.649 GST_CLOCK_TIME_NONE, 0));
1.650 break;
1.651 - case 'A':
1.652 - if ( !gst_pad_is_linked( nuv->src_audio_pad ) )
1.653 - break;
1.654 -
1.655 + case 'A':
1.656 GST_DEBUG_OBJECT (nuv, "sending new audio segment: %d", h->i_timecode);
1.657 - gst_pad_push_event (nuv->src_audio_pad,
1.658 - gst_event_new_new_segment (TRUE, 1.0, GST_FORMAT_TIME, 0,
1.659 + gst_pad_push_event (nuv->priv->src_audio_pad,
1.660 + gst_event_new_new_segment (TRUE, 1.0, GST_FORMAT_TIME, 0,
1.661 GST_CLOCK_TIME_NONE, 0));
1.662 break;
1.663 default:
1.664 @@ -625,6 +796,8 @@
1.665 }
1.666 if (buf != NULL)
1.667 gst_buffer_unref (buf);
1.668 +
1.669 + goto done;
1.670 }
1.671 default:
1.672 if (buf != NULL)
1.673 @@ -633,10 +806,37 @@
1.674 break;
1.675 }
1.676
1.677 + if ((buf != NULL) && (pad != NULL)) {
1.678 + /* update average time */
1.679 + nuv->priv->streamer_offset += h->i_length;
1.680 + gst_segment_set_last_stop (&nuv->priv->segment, GST_FORMAT_TIME, timestamp);
1.681 + gst_nuv_demux_update_duration (nuv, timestamp);
1.682 +
1.683 + /* pushing the buffer */
1.684 + gst_buffer_set_caps (buf, GST_PAD_CAPS (pad));
1.685 + ret = gst_pad_push (pad, buf);
1.686 +
1.687 + if (ret != GST_FLOW_OK) {
1.688 + if (pad == nuv->priv->src_video_pad) {
1.689 + nuv->priv->last_video_return = ret;
1.690 + }
1.691 + else if (pad == nuv->priv->src_audio_pad) {
1.692 + nuv->priv->last_audio_return = ret;
1.693 + }
1.694 +
1.695 + /* verify anothers flow if is necessary stop task */
1.696 + if (gst_nuv_combine_flow (nuv) != FALSE) {
1.697 + ret = GST_FLOW_OK;
1.698 + }
1.699 +
1.700 + GST_WARNING_OBJECT (nuv, "error: %d pushing on srcpad %s", ret, gst_pad_get_name (pad));
1.701 + }
1.702 + }
1.703 +
1.704 done:
1.705 - nuv->state = GST_NUV_DEMUX_FRAME_HEADER;
1.706 - g_free (nuv->fh);
1.707 - nuv->fh = NULL;
1.708 + nuv->priv->state = GST_NUV_DEMUX_FRAME_HEADER;
1.709 + g_free (nuv->priv->fh);
1.710 + nuv->priv->fh = NULL;
1.711 return ret;
1.712 }
1.713
1.714 @@ -646,14 +846,14 @@
1.715 GstFlowReturn ret = GST_FLOW_OK;
1.716
1.717 /* ffmpeg extra data */
1.718 - ret =
1.719 - gst_nuv_demux_read_bytes (nuv, nuv->mpeg_data_size, TRUE,
1.720 - &nuv->mpeg_buffer);
1.721 - if ((ret != GST_FLOW_OK) || (nuv->mpeg_buffer == NULL)) {
1.722 - return ret;
1.723 + ret = gst_nuv_demux_read_bytes (nuv, nuv->priv->mpeg_data_size, TRUE,
1.724 + &nuv->priv->mpeg_buffer);
1.725 + if ((ret != GST_FLOW_OK) || (nuv->priv->mpeg_buffer == NULL)) {
1.726 + return ret;
1.727 }
1.728 - GST_BUFFER_SIZE (nuv->mpeg_buffer) = nuv->mpeg_data_size;
1.729 - nuv->state = GST_NUV_DEMUX_EXTEND_HEADER;
1.730 +
1.731 + GST_BUFFER_SIZE (nuv->priv->mpeg_buffer) = nuv->priv->mpeg_data_size;
1.732 + nuv->priv->state = GST_NUV_DEMUX_EXTEND_HEADER;
1.733 return ret;
1.734 }
1.735
1.736 @@ -676,13 +876,13 @@
1.737
1.738 if (h->i_length > 0) {
1.739 if (h->i_compression == 'F') {
1.740 - nuv->state = GST_NUV_DEMUX_MPEG_DATA;
1.741 + nuv->priv->state = GST_NUV_DEMUX_MPEG_DATA;
1.742 } else {
1.743 g_free (h);
1.744 return GST_FLOW_ERROR;
1.745 }
1.746 } else {
1.747 - nuv->state = GST_NUV_DEMUX_EXTEND_HEADER;
1.748 + nuv->priv->state = GST_NUV_DEMUX_EXTEND_HEADER;
1.749 }
1.750
1.751 g_free (h);
1.752 @@ -695,12 +895,12 @@
1.753 {
1.754 GstFlowReturn ret = GST_FLOW_OK;
1.755
1.756 - ret = gst_nuv_demux_extended_header_load (nuv, &nuv->eh);
1.757 + ret = gst_nuv_demux_extended_header_load (nuv, &nuv->priv->eh);
1.758 if (ret != GST_FLOW_OK)
1.759 return ret;
1.760
1.761 gst_nuv_demux_create_pads (nuv);
1.762 - nuv->state = GST_NUV_DEMUX_FRAME_HEADER;
1.763 + nuv->priv->state = GST_NUV_DEMUX_FRAME_HEADER;
1.764 return ret;
1.765 }
1.766
1.767 @@ -733,9 +933,9 @@
1.768 }
1.769 g_free (h);
1.770 h = NULL;
1.771 - nuv->state = GST_NUV_DEMUX_EXTEND_HEADER_DATA;
1.772 + nuv->priv->state = GST_NUV_DEMUX_EXTEND_HEADER_DATA;
1.773 } else {
1.774 - nuv->state = GST_NUV_DEMUX_INVALID_DATA;
1.775 + nuv->priv->state = GST_NUV_DEMUX_INVALID_DATA;
1.776 g_object_unref (buf);
1.777 GST_ELEMENT_WARNING (nuv, STREAM, FAILED,
1.778 (_("incomplete NUV support")), ("incomplete NUV support"));
1.779 @@ -750,13 +950,13 @@
1.780 GstFlowReturn res = GST_FLOW_OK;
1.781 GstNuvDemux *nuv = GST_NUV_DEMUX (GST_PAD_PARENT (pad));
1.782
1.783 - switch (nuv->state) {
1.784 + switch (nuv->priv->state) {
1.785 case GST_NUV_DEMUX_START:
1.786 res = gst_nuv_demux_stream_file_header (nuv);
1.787 if ((res != GST_FLOW_OK) && (res != GST_FLOW_ERROR_NO_DATA)) {
1.788 goto pause;
1.789 }
1.790 - if (nuv->state != GST_NUV_DEMUX_HEADER_DATA)
1.791 + if (nuv->priv->state != GST_NUV_DEMUX_HEADER_DATA)
1.792 break;
1.793
1.794 case GST_NUV_DEMUX_HEADER_DATA:
1.795 @@ -764,7 +964,7 @@
1.796 if ((res != GST_FLOW_OK) && (res != GST_FLOW_ERROR_NO_DATA)) {
1.797 goto pause;
1.798 }
1.799 - if (nuv->state != GST_NUV_DEMUX_EXTRA_DATA)
1.800 + if (nuv->priv->state != GST_NUV_DEMUX_EXTRA_DATA)
1.801 break;
1.802
1.803 case GST_NUV_DEMUX_EXTRA_DATA:
1.804 @@ -772,7 +972,7 @@
1.805 if ((res != GST_FLOW_OK) && (res != GST_FLOW_ERROR_NO_DATA)) {
1.806 goto pause;
1.807 }
1.808 - if (nuv->state != GST_NUV_DEMUX_MPEG_DATA)
1.809 + if (nuv->priv->state != GST_NUV_DEMUX_MPEG_DATA)
1.810 break;
1.811
1.812 case GST_NUV_DEMUX_MPEG_DATA:
1.813 @@ -781,7 +981,7 @@
1.814 goto pause;
1.815 }
1.816
1.817 - if (nuv->state != GST_NUV_DEMUX_EXTEND_HEADER)
1.818 + if (nuv->priv->state != GST_NUV_DEMUX_EXTEND_HEADER)
1.819 break;
1.820
1.821 case GST_NUV_DEMUX_EXTEND_HEADER:
1.822 @@ -789,7 +989,7 @@
1.823 if ((res != GST_FLOW_OK) && (res != GST_FLOW_ERROR_NO_DATA)) {
1.824 goto pause;
1.825 }
1.826 - if (nuv->state != GST_NUV_DEMUX_EXTEND_HEADER_DATA)
1.827 + if (nuv->priv->state != GST_NUV_DEMUX_EXTEND_HEADER_DATA)
1.828 break;
1.829
1.830 case GST_NUV_DEMUX_EXTEND_HEADER_DATA:
1.831 @@ -798,7 +998,7 @@
1.832 goto pause;
1.833 }
1.834
1.835 - if (nuv->state != GST_NUV_DEMUX_FRAME_HEADER)
1.836 + if (nuv->priv->state != GST_NUV_DEMUX_FRAME_HEADER)
1.837 break;
1.838
1.839 case GST_NUV_DEMUX_FRAME_HEADER:
1.840 @@ -806,7 +1006,7 @@
1.841 if ((res != GST_FLOW_OK) && (res != GST_FLOW_ERROR_NO_DATA)) {
1.842 goto pause;
1.843 }
1.844 - if (nuv->state != GST_NUV_DEMUX_MOVI)
1.845 + if (nuv->priv->state != GST_NUV_DEMUX_MOVI)
1.846 break;
1.847
1.848 case GST_NUV_DEMUX_MOVI:
1.849 @@ -822,14 +1022,13 @@
1.850 g_assert_not_reached ();
1.851 }
1.852
1.853 - GST_DEBUG_OBJECT (nuv, "state: %d res:%s", nuv->state,
1.854 - gst_flow_get_name (res));
1.855 + GST_DEBUG_OBJECT (nuv, "state: %d res:%s", nuv->priv->state, gst_flow_get_name (res));
1.856
1.857 return GST_FLOW_OK;
1.858
1.859 pause:
1.860 GST_LOG_OBJECT (nuv, "pausing task, reason %s", gst_flow_get_name (res));
1.861 - gst_pad_pause_task (nuv->sinkpad);
1.862 + gst_pad_pause_task (nuv->priv->sinkpad);
1.863 if (GST_FLOW_IS_FATAL (res)) {
1.864 GST_ELEMENT_ERROR (nuv, STREAM, FAILED,
1.865 (_("Internal data stream error.")),
1.866 @@ -846,12 +1045,12 @@
1.867 gst_element_post_message (GST_ELEMENT (nuv),
1.868 gst_message_new_segment_done (GST_OBJECT (nuv), GST_FORMAT_TIME, -1));
1.869
1.870 - if (nuv->src_video_pad)
1.871 - gst_pad_push_event (nuv->src_video_pad, gst_event_new_eos ());
1.872 - if (nuv->src_audio_pad)
1.873 - gst_pad_push_event (nuv->src_audio_pad, gst_event_new_eos ());
1.874 + if (nuv->priv->src_video_pad)
1.875 + gst_pad_push_event (nuv->priv->src_video_pad, gst_event_new_eos ());
1.876 + if (nuv->priv->src_audio_pad)
1.877 + gst_pad_push_event (nuv->priv->src_audio_pad, gst_event_new_eos ());
1.878 }
1.879 -
1.880 +
1.881 static GstFlowReturn
1.882 gst_nuv_demux_read_bytes (GstNuvDemux * nuv, guint64 size, gboolean move,
1.883 GstBuffer ** buffer)
1.884 @@ -861,33 +1060,33 @@
1.885 if (size == 0) {
1.886 return ret;
1.887 }
1.888 -
1.889 - if (nuv->mode == NUV_PULL_MODE) {
1.890 - ret = gst_pad_pull_range (nuv->sinkpad, nuv->offset, size, buffer);
1.891 +
1.892 + if (nuv->priv->mode == NUV_PULL_MODE) {
1.893 + ret = gst_pad_pull_range (nuv->priv->sinkpad, nuv->priv->offset, size, buffer);
1.894 if (ret == GST_FLOW_OK) {
1.895 if (move) {
1.896 - nuv->offset += size;
1.897 + nuv->priv->offset += size;
1.898 }
1.899 /* got eos */
1.900 } else if (ret == GST_FLOW_UNEXPECTED) {
1.901 if (buffer != NULL)
1.902 gst_buffer_unref (buffer);
1.903 -
1.904 +
1.905 gst_nuv_demux_send_eos (nuv);
1.906 return GST_FLOW_WRONG_STATE;
1.907 }
1.908 } else {
1.909 - if (gst_adapter_available (nuv->adapter) < size)
1.910 + if (gst_adapter_available (nuv->priv->adapter) < size)
1.911 return GST_FLOW_ERROR_NO_DATA;
1.912
1.913 if (move) {
1.914 guint8 *data = NULL;
1.915 - data = (guint8 *) gst_adapter_take (nuv->adapter, size);
1.916 + data = (guint8 *) gst_adapter_take (nuv->priv->adapter, size);
1.917 *buffer = gst_buffer_new ();
1.918 gst_buffer_set_data (*buffer, data, size);
1.919 } else {
1.920 guint8 *data = NULL;
1.921 - data = (guint8 *) gst_adapter_peek (nuv->adapter, size);
1.922 + data = (guint8 *) gst_adapter_peek (nuv->priv->adapter, size);
1.923 *buffer = gst_buffer_new ();
1.924 gst_buffer_set_data (*buffer, data, size);
1.925 }
1.926 @@ -917,11 +1116,11 @@
1.927
1.928 if (active) {
1.929 GST_DEBUG_OBJECT (nuv, "activating pull function");
1.930 - nuv->mode = NUV_PULL_MODE;
1.931 - if (nuv->adapter) {
1.932 - gst_adapter_clear (nuv->adapter);
1.933 - g_object_unref (nuv->adapter);
1.934 - nuv->adapter = NULL;
1.935 + nuv->priv->mode = NUV_PULL_MODE;
1.936 + if (nuv->priv->adapter) {
1.937 + gst_adapter_clear (nuv->priv->adapter);
1.938 + g_object_unref (nuv->priv->adapter);
1.939 + nuv->priv->adapter = NULL;
1.940 }
1.941 gst_pad_start_task (sinkpad, (GstTaskFunction) gst_nuv_demux_loop, sinkpad);
1.942 } else {
1.943 @@ -939,11 +1138,11 @@
1.944 GstNuvDemux *nuv = GST_NUV_DEMUX (gst_pad_get_parent (pad));
1.945
1.946 if (active) {
1.947 - nuv->mode = NUV_PUSH_MODE;
1.948 - if (nuv->adapter) {
1.949 - gst_adapter_clear (nuv->adapter);
1.950 + nuv->priv->mode = NUV_PUSH_MODE;
1.951 + if (nuv->priv->adapter) {
1.952 + gst_adapter_clear (nuv->priv->adapter);
1.953 } else {
1.954 - nuv->adapter = gst_adapter_new ();
1.955 + nuv->priv->adapter = gst_adapter_new ();
1.956 }
1.957 GST_DEBUG_OBJECT (nuv, "activating push/chain function");
1.958 } else {
1.959 @@ -955,13 +1154,84 @@
1.960 return TRUE;
1.961 }
1.962
1.963 +
1.964 +static gboolean
1.965 +gst_nuv_demux_sink_event (GstPad *pad, GstEvent *event)
1.966 +{
1.967 + gboolean res;
1.968 + GstNuvDemux *nuv;
1.969 +
1.970 + nuv = GST_NUV_DEMUX (gst_pad_get_parent (pad));
1.971 +
1.972 + switch (GST_EVENT_TYPE (event)) {
1.973 + case GST_EVENT_SEEK:
1.974 + {
1.975 + gdouble rate;
1.976 + GstFormat format;
1.977 + GstSeekFlags flags;
1.978 + GstSeekType cur_type;
1.979 + gint64 cur;
1.980 + GstSeekType stop_type;
1.981 + gint64 stop;
1.982 +
1.983 + gst_event_parse_seek (event, &rate, &format, &flags, &cur_type, &cur, &stop_type, &stop);
1.984 +
1.985 + GST_DEBUG_OBJECT (nuv, "got seek, start %" G_GINT64_FORMAT ", stop %" G_GINT64_FORMAT, cur, stop);
1.986 +
1.987 + break;
1.988 + }
1.989 + case GST_EVENT_NEWSEGMENT:
1.990 + {
1.991 + gint64 start, stop, time;
1.992 + gdouble rate, arate;
1.993 + GstFormat format;
1.994 + gboolean update;
1.995 +
1.996 + GST_DEBUG_OBJECT (nuv, "got a new segment event");
1.997 + gst_event_parse_new_segment_full (event, &update, &rate, &arate, &format,
1.998 + &start, &stop, &time);
1.999 +
1.1000 + GST_DEBUG_OBJECT (nuv, "got newsegment, start %" G_GINT64_FORMAT ", stop %" G_GINT64_FORMAT, start, stop);
1.1001 + g_debug ("got newsegment, start %" G_GINT64_FORMAT ", stop %" G_GINT64_FORMAT, start, stop);
1.1002 + nuv->priv->duration_bytes = stop - start;
1.1003 + gst_event_unref (event);
1.1004 + res = TRUE;
1.1005 + break;
1.1006 + }
1.1007 + case GST_EVENT_QOS:
1.1008 + {
1.1009 +/*
1.1010 + gdouble proportion;
1.1011 + GstClockTimeDiff diff;
1.1012 + GstClockTime timestamp;
1.1013 +
1.1014 + gst_event_parse_qos (event, &proportion, &diff, ×tamp);
1.1015 + if (diff > 0)
1.1016 + nuv->time_qos = timecode + diff;
1.1017 + else
1.1018 + nuv->time_qos = -1;
1.1019 +*/
1.1020 +
1.1021 + break;
1.1022 + }
1.1023 +
1.1024 + case GST_EVENT_EOS:
1.1025 + default:
1.1026 + res = gst_pad_event_default (pad, event);
1.1027 + break;
1.1028 + }
1.1029 +
1.1030 + gst_object_unref (nuv);
1.1031 + return res;
1.1032 +}
1.1033 +
1.1034 static GstFlowReturn
1.1035 gst_nuv_demux_chain (GstPad * pad, GstBuffer * buf)
1.1036 {
1.1037 GstNuvDemux *nuv = GST_NUV_DEMUX (gst_pad_get_parent (pad));
1.1038
1.1039 GST_DEBUG_OBJECT (nuv, " gst_nuv_demux_chain function");
1.1040 - gst_adapter_push (nuv->adapter, buf);
1.1041 + gst_adapter_push (nuv->priv->adapter, buf);
1.1042
1.1043 gst_object_unref (nuv);
1.1044
1.1045 @@ -977,40 +1247,46 @@
1.1046 static void
1.1047 gst_nuv_demux_reset (GstNuvDemux * nuv)
1.1048 {
1.1049 - nuv->state = GST_NUV_DEMUX_START;
1.1050 - nuv->mode = 0;
1.1051 - nuv->offset = 0;
1.1052 - nuv->time_offset = 0;
1.1053 + nuv->priv->state = GST_NUV_DEMUX_START;
1.1054 + nuv->priv->mode = 0;
1.1055 + nuv->priv->offset = 0;
1.1056 + nuv->priv->streamer_offset = 0;
1.1057 + nuv->priv->time_start = 0;
1.1058 + nuv->priv->time_qos = GST_CLOCK_TIME_NONE;
1.1059 + nuv->priv->duration_bytes = GST_CLOCK_TIME_NONE;
1.1060 + nuv->priv->duration_time = GST_CLOCK_TIME_NONE;
1.1061 + nuv->priv->duration_average = GST_CLOCK_TIME_NONE;
1.1062 + gst_segment_init (&nuv->priv->segment, GST_FORMAT_TIME);
1.1063
1.1064 - if (nuv->adapter != NULL)
1.1065 - gst_adapter_clear (nuv->adapter);
1.1066 + if (nuv->priv->adapter != NULL)
1.1067 + gst_adapter_clear (nuv->priv->adapter);
1.1068
1.1069 - if (nuv->mpeg_buffer != NULL) {
1.1070 - gst_buffer_unref (nuv->mpeg_buffer);
1.1071 - nuv->mpeg_buffer = NULL;
1.1072 + if (nuv->priv->mpeg_buffer != NULL) {
1.1073 + gst_buffer_unref (nuv->priv->mpeg_buffer);
1.1074 + nuv->priv->mpeg_buffer = NULL;
1.1075 }
1.1076
1.1077 - g_free (nuv->h);
1.1078 - nuv->h = NULL;
1.1079 + g_free (nuv->priv->h);
1.1080 + nuv->priv->h = NULL;
1.1081
1.1082 - g_free (nuv->eh);
1.1083 - nuv->eh = NULL;
1.1084 + g_free (nuv->priv->eh);
1.1085 + nuv->priv->eh = NULL;
1.1086
1.1087 - g_free (nuv->fh);
1.1088 - nuv->fh = NULL;
1.1089 + g_free (nuv->priv->fh);
1.1090 + nuv->priv->fh = NULL;
1.1091 }
1.1092
1.1093 static void
1.1094 gst_nuv_demux_destoy_src_pad (GstNuvDemux * nuv)
1.1095 {
1.1096 - if (nuv->src_video_pad) {
1.1097 - gst_element_remove_pad (GST_ELEMENT (nuv), nuv->src_video_pad);
1.1098 - nuv->src_video_pad = NULL;
1.1099 + if (nuv->priv->src_video_pad) {
1.1100 + gst_element_remove_pad (GST_ELEMENT (nuv), nuv->priv->src_video_pad);
1.1101 + nuv->priv->src_video_pad = NULL;
1.1102 }
1.1103
1.1104 - if (nuv->src_audio_pad) {
1.1105 - gst_element_remove_pad (GST_ELEMENT (nuv), nuv->src_audio_pad);
1.1106 - nuv->src_audio_pad = NULL;
1.1107 + if (nuv->priv->src_audio_pad) {
1.1108 + gst_element_remove_pad (GST_ELEMENT (nuv), nuv->priv->src_audio_pad);
1.1109 + nuv->priv->src_audio_pad = NULL;
1.1110 }
1.1111 }
1.1112
1.1113 @@ -1021,6 +1297,7 @@
1.1114
1.1115 switch (transition) {
1.1116 case GST_STATE_CHANGE_READY_TO_PAUSED:
1.1117 + gst_nuv_demux_reset (GST_NUV_DEMUX (element));
1.1118 break;
1.1119 default:
1.1120 break;
1.1121 @@ -1031,10 +1308,9 @@
1.1122 goto done;
1.1123
1.1124 switch (transition) {
1.1125 - case GST_STATE_CHANGE_PAUSED_TO_READY:
1.1126 - GST_DEBUG_OBJECT (element, "GST_STATE_CHANGE_PAUSED_TO_READY");
1.1127 + case GST_STATE_CHANGE_READY_TO_NULL:
1.1128 + gst_nuv_demux_reset (GST_NUV_DEMUX (element));
1.1129 gst_nuv_demux_destoy_src_pad (GST_NUV_DEMUX (element));
1.1130 - gst_nuv_demux_reset (GST_NUV_DEMUX (element));
1.1131 break;
1.1132 default:
1.1133 break;
1.1134 @@ -1044,6 +1320,70 @@
1.1135 return ret;
1.1136 }
1.1137
1.1138 +static void
1.1139 +gst_nuv_demux_update_duration (GstNuvDemux *nuv, guint64 current_timestamp)
1.1140 +{
1.1141 + guint64 interval = 0;
1.1142 +
1.1143 + if (gst_nuv_demux_get_time_duration (nuv) != GST_CLOCK_TIME_NONE)
1.1144 + return;
1.1145 +
1.1146 + interval = current_timestamp - nuv->priv->last_update;
1.1147 +
1.1148 + if (interval > (10 * GST_SECOND)) {
1.1149 + GstMessage* msg = NULL;
1.1150 + gint64 average = 0;
1.1151 + gint64 duration_bytes = gst_nuv_demux_get_bytes_duration (nuv);
1.1152 +
1.1153 + if (duration_bytes == GST_CLOCK_TIME_NONE)
1.1154 + return;
1.1155 +
1.1156 + interval = gst_util_uint64_scale (1, current_timestamp - nuv->priv->time_start, GST_SECOND);
1.1157 + average = gst_util_uint64_scale (1 , nuv->priv->streamer_offset, interval);
1.1158 + nuv->priv->duration_average = gst_util_uint64_scale (GST_SECOND, duration_bytes, average);
1.1159 + nuv->priv->last_update = current_timestamp;
1.1160 + msg = gst_message_new_duration (GST_OBJECT (nuv), GST_FORMAT_TIME, nuv->priv->duration_average);
1.1161 + gst_element_post_message (GST_ELEMENT (nuv), msg);
1.1162 + GST_DEBUG_OBJECT (nuv, "New Duration Average %"G_GUINT64_FORMAT, nuv->priv->duration_average);
1.1163 + }
1.1164 +}
1.1165 +
1.1166 +static gint64
1.1167 +gst_nuv_demux_get_bytes_duration (GstNuvDemux *nuv)
1.1168 +{
1.1169 + if (nuv->priv->duration_bytes == GST_CLOCK_TIME_NONE) {
1.1170 + GstPad *peer = gst_pad_get_peer (nuv->priv->sinkpad);
1.1171 + GstQuery *query = gst_query_new_duration (GST_FORMAT_BYTES);
1.1172 + if (gst_pad_query (peer, query)) {
1.1173 + gint64 duration;
1.1174 +
1.1175 + gst_query_parse_duration (query, NULL, &duration);
1.1176 + nuv->priv->duration_bytes = duration;
1.1177 + }
1.1178 + gst_object_unref (peer);
1.1179 + gst_query_unref (query);
1.1180 + }
1.1181 + return nuv->priv->duration_bytes;
1.1182 +}
1.1183 +
1.1184 +static gint64
1.1185 +gst_nuv_demux_get_time_duration (GstNuvDemux *nuv)
1.1186 +{
1.1187 + if (nuv->priv->duration_time == GST_CLOCK_TIME_NONE) {
1.1188 + GstPad *peer = gst_pad_get_peer (nuv->priv->sinkpad);
1.1189 + GstQuery *query = gst_query_new_duration (GST_FORMAT_TIME);
1.1190 + if (gst_pad_query (peer, query)) {
1.1191 + gint64 duration;
1.1192 + gst_query_parse_duration (query, NULL, &duration);
1.1193 + nuv->priv->duration_time = duration;
1.1194 + }
1.1195 + gst_object_unref (peer);
1.1196 + gst_query_unref (query);
1.1197 + }
1.1198 + return nuv->priv->duration_time;
1.1199 +}
1.1200 +
1.1201 +
1.1202 static gboolean
1.1203 plugin_init (GstPlugin * plugin)
1.1204 {
2.1 --- a/gst-plugins-nuvdemux/nuvdemux/gstnuvdemux.h Fri Nov 17 13:09:12 2006 +0000
2.2 +++ b/gst-plugins-nuvdemux/nuvdemux/gstnuvdemux.h Fri Nov 17 13:18:48 2006 +0000
2.3 @@ -38,155 +38,10 @@
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[DEMUX_INDEX_SIZE_MAX];
2.23 -} nuv_demux_index;
2.24 -
2.25 -/* */
2.26 -typedef struct
2.27 -{
2.28 - gchar id[12]; /* "NuppelVideo\0" or "MythTVVideo\0" */
2.29 - gchar version[5]; /* "x.xx\0" */
2.30 -
2.31 - gint i_width;
2.32 - gint i_height;
2.33 - gint i_width_desired;
2.34 - gint i_height_desired;
2.35 -
2.36 - gchar i_mode; /* P progressive, I interlaced */
2.37 -
2.38 - gdouble d_aspect; /* 1.0 squared pixel */
2.39 - gdouble d_fps;
2.40 - //fps num/denom
2.41 - gint i_fpsn;
2.42 - gint i_fpsd;
2.43 -
2.44 - gint i_video_blocks; /* 0 no video, -1 unknown */
2.45 - gint i_audio_blocks;
2.46 - gint i_text_blocks;
2.47 -
2.48 - gint i_keyframe_distance;
2.49 -
2.50 -} nuv_header;
2.51 -
2.52 -typedef struct
2.53 -{
2.54 - gchar i_type; /* A: audio, V: video, S: sync; T: test
2.55 - R: Seekpoint (string:RTjjjjjjjj)
2.56 - D: Extra data for codec */
2.57 - gchar i_compression; /* V: 0 uncompressed
2.58 - 1 RTJpeg
2.59 - 2 RTJpeg+lzo
2.60 - N black frame
2.61 - L copy last
2.62 - A: 0 uncompressed (44100 1-bits, 2ch)
2.63 - 1 lzo
2.64 - 2 layer 2
2.65 - 3 layer 3
2.66 - F flac
2.67 - S shorten
2.68 - N null frame loudless
2.69 - L copy last
2.70 - S: B audio and vdeo sync point
2.71 - A audio sync info (timecode == effective
2.72 - dsp frequency*100)
2.73 - V next video sync (timecode == next video
2.74 - frame num)
2.75 - S audio,video,text correlation */
2.76 - gchar i_keyframe; /* 0 keyframe, else no no key frame */
2.77 - guint8 i_filters; /* 0x01: gauss 5 pixel (8,2,2,2,2)/16
2.78 - 0x02: gauss 5 pixel (8,1,1,1,1)/12
2.79 - 0x04: cartoon filter */
2.80 -
2.81 - gint32 i_timecode; /* ms */
2.82 -
2.83 - gint i_length; /* V,A,T: length of following data
2.84 - S: length of packet correl */
2.85 -} nuv_frame_header;
2.86 -
2.87 -/* FIXME Not sure of this one */
2.88 -typedef struct
2.89 -{
2.90 - gint i_version;
2.91 - guint32 i_video_fcc;
2.92 -
2.93 - guint32 i_audio_fcc;
2.94 - gint i_audio_sample_rate;
2.95 - gint i_audio_bits_per_sample;
2.96 - gint i_audio_channels;
2.97 - gint i_audio_compression_ratio;
2.98 - gint i_audio_quality;
2.99 - gint i_rtjpeg_quality;
2.100 - gint i_rtjpeg_luma_filter;
2.101 - gint i_rtjpeg_chroma_filter;
2.102 - gint i_lavc_bitrate;
2.103 - gint i_lavc_qmin;
2.104 - gint i_lavc_qmax;
2.105 - gint i_lavc_maxqdiff;
2.106 - gint64 i_seekable_offset;
2.107 - gint64 i_keyframe_adjust_offset;
2.108 -
2.109 -} nuv_extended_header;
2.110 -
2.111 -typedef enum {
2.112 - GST_NUV_DEMUX_START,
2.113 - GST_NUV_DEMUX_HEADER_DATA,
2.114 - GST_NUV_DEMUX_EXTRA_DATA,
2.115 - GST_NUV_DEMUX_MPEG_DATA,
2.116 - GST_NUV_DEMUX_EXTEND_HEADER,
2.117 - GST_NUV_DEMUX_EXTEND_HEADER_DATA,
2.118 - GST_NUV_DEMUX_FRAME_HEADER,
2.119 - GST_NUV_DEMUX_MOVI,
2.120 - GST_NUV_DEMUX_INVALID_DATA
2.121 -} GstNuvDemuxState;
2.122 -
2.123 +typedef struct _GstNuvDemuxPrivate GstNuvDemuxPrivate;
2.124 typedef struct _GstNuvDemux {
2.125 - GstElement parent;
2.126 -
2.127 - guint mode;
2.128 - GstAdapter *adapter;
2.129 -
2.130 - /* pads */
2.131 - GstPad *sinkpad;
2.132 - GstPad *src_video_pad;
2.133 - GstPad *src_audio_pad;
2.134 -
2.135 - GstFlowReturn last_video_return;
2.136 - GstFlowReturn last_audio_return;
2.137 -
2.138 - /* NUV decoding state */
2.139 - GstNuvDemuxState state;
2.140 - guint64 duration;
2.141 - guint64 offset;
2.142 - guint64 time_offset;
2.143 - guint64 last_frame_time;
2.144 - gboolean new_audio_segment;
2.145 - gboolean new_video_segment;
2.146 -
2.147 - /* Mpeg ExtraData */
2.148 - guint64 mpeg_data_size;
2.149 - GstBuffer *mpeg_buffer;
2.150 -
2.151 - nuv_header *h;
2.152 - nuv_extended_header *eh;
2.153 - nuv_frame_header *fh;
2.154 -
2.155 - /* FIXME: change these fields to private struct */
2.156 - /* first data buffer received, should sent new_segment */
2.157 + GstElement parent;
2.158 + GstNuvDemuxPrivate *priv;
2.159 } GstNuvDemux;
2.160
2.161 typedef struct _GstNuvDemuxClass {