diff -r fc0a5721cd04 -r 0ba50b995f75 gst-plugins-nuvdemux/nuvdemux/gstnuvdemux.c --- a/gst-plugins-nuvdemux/nuvdemux/gstnuvdemux.c Wed Mar 21 14:51:07 2007 +0000 +++ b/gst-plugins-nuvdemux/nuvdemux/gstnuvdemux.c Thu Mar 22 18:13:13 2007 +0000 @@ -257,6 +257,8 @@ gboolean active); static gboolean gst_nuv_demux_sink_activate (GstPad * sinkpad); static gboolean gst_nuv_demux_sink_event (GstPad *pad, GstEvent *event); +static gboolean gst_nuv_demux_srcpad_event (GstPad * pad, GstEvent * event); + static GstFlowReturn gst_nuv_demux_read_bytes (GstNuvDemux * nuv, guint64 size, gboolean move, GstBuffer ** buffer); static void gst_nuv_demux_reset (GstNuvDemux * nuv); @@ -634,6 +636,8 @@ gst_pad_set_active (pad, TRUE); gst_pad_use_fixed_caps (pad); gst_element_add_pad (GST_ELEMENT (nuv), pad); + gst_pad_set_event_function (pad, + GST_DEBUG_FUNCPTR (gst_nuv_demux_srcpad_event)); return pad; } @@ -674,14 +678,79 @@ gst_element_no_more_pads (GST_ELEMENT (nuv)); } +static gboolean +gst_nuv_demux_validate_header (nuv_frame_header *h) +{ + gboolean valid = FALSE; + //g_debug ("Type %d = Compression %d", h->i_type, h->i_compression); + //g_usleep (1 * G_USEC_PER_SEC ); + switch (h->i_type) { +/* + case 'V': + if (h->i_compression == 0 || + h->i_compression == 1 || + h->i_compression == 2 || + h->i_compression == 'N' || + h->i_compression == 'L') { + valid = TRUE; + } + break; + case 'A': + if (h->i_compression == 0 || + h->i_compression == 1 || + h->i_compression == 2 || + h->i_compression == 3 || + h->i_compression == 'F' || + h->i_compression == 'S' || + h->i_compression == 'N' || + h->i_compression == 'L') { + valid = TRUE; + } + break; + case 'S': + if (h->i_compression == 'B' || + h->i_compression == 'A' || + h->i_compression == 'V' || + h->i_compression == 'S') { + valid = TRUE; + } + break; +*/ + case 'A': + case 'V': + case 'S': + case 'R': + case 'D': + valid = TRUE; + break; + default: + valid = FALSE; + } + + return valid; +} + static GstFlowReturn gst_nuv_demux_read_head_frame (GstNuvDemux * nuv) { GstFlowReturn ret = GST_FLOW_OK; + gboolean valid = FALSE; - ret = gst_nuv_demux_frame_header_load (nuv, &nuv->priv->fh); - if (ret != GST_FLOW_OK) - return ret; + do { + ret = gst_nuv_demux_frame_header_load (nuv, &nuv->priv->fh); + if (ret != GST_FLOW_OK) { + g_debug ("FAIL TO READ HEADER"); + return ret; + } + + if (gst_nuv_demux_validate_header (&nuv->priv->fh) == TRUE) + valid = TRUE; + else + g_debug ("Invalid frame header"); + + } while (valid == FALSE); + +// } while (gst_nuv_demux_validate_header (nuv->priv->fh)); nuv->priv->state = GST_NUV_DEMUX_MOVI; return ret; @@ -721,18 +790,18 @@ goto done; if (h.i_length > 0) { - ret = gst_nuv_demux_read_bytes (nuv, h.i_length, TRUE, &buf); - if ((ret != GST_FLOW_OK) || (buf == NULL)) { - goto done; - } + ret = gst_nuv_demux_read_bytes (nuv, h.i_length, TRUE, &buf); + if ((ret != GST_FLOW_OK) || (buf == NULL)) { + goto done; + } - if ((h.i_timecode < 0)) { - h.i_timecode = 0; - //goto done; - } + if ((h.i_timecode < 0)) { + h.i_timecode = 0; + //goto done; + } - timestamp = h.i_timecode * GST_MSECOND; - GST_BUFFER_TIMESTAMP (buf) = timestamp; + timestamp = h.i_timecode * GST_MSECOND; + GST_BUFFER_TIMESTAMP (buf) = timestamp; } else { goto done; @@ -824,10 +893,11 @@ /* verify anothers flow if is necessary stop task */ if (gst_nuv_combine_flow (nuv) != FALSE) { - ret = GST_FLOW_OK; - } + ret = GST_FLOW_OK; + } else { + GST_WARNING_OBJECT (nuv, "error: on push"); + } - //GST_WARNING_OBJECT (nuv, "error: %d pushing on srcpad %s", ret, gst_pad_get_name (pad)); } } @@ -942,6 +1012,7 @@ return res; } + static GstFlowReturn gst_nuv_demux_play (GstPad * pad) { @@ -998,7 +1069,7 @@ } break; - case GST_NUV_DEMUX_MOVI: + case GST_NUV_DEMUX_MOVI: res = gst_nuv_demux_stream_data (nuv); if ((res != GST_FLOW_OK) && (res != GST_FLOW_ERROR_NO_DATA)) { goto pause; @@ -1142,6 +1213,88 @@ return TRUE; } +static gboolean +gst_nuv_demux_do_seek (GstNuvDemux *nuv, GstEvent * event) +{ + gdouble rate; + GstFormat format; + GstSeekFlags flags; + GstSeekType cur_type; + gint64 cur; + GstSeekType stop_type; + gint64 stop; + gboolean flush; + + g_debug ("DEMUX SEEK"); + gst_event_parse_seek (event, &rate, &format, &flags, + &cur_type, &cur, &stop_type, &stop); + + if (format == GST_FORMAT_BYTES && + nuv->priv->state > GST_NUV_DEMUX_EXTEND_HEADER_DATA && + gst_pad_is_linked (nuv->priv->sinkpad)) { + + flush = flags & GST_SEEK_FLAG_FLUSH; + if (flush) { + gst_pad_push_event (nuv->priv->sinkpad, gst_event_new_flush_start ()); + + if (nuv->priv->src_video_pad != NULL) { + gst_pad_push_event (nuv->priv->src_video_pad, gst_event_new_flush_start ()); + } + + if (nuv->priv->src_audio_pad != NULL) { + gst_pad_push_event (nuv->priv->src_audio_pad, gst_event_new_flush_start ()); + } + } + else { + gst_pad_pause_task (nuv->priv->sinkpad); + } + + GST_PAD_STREAM_LOCK (nuv->priv->sinkpad); + + g_debug ("offset %ld, cur %ld", nuv->priv->offset, cur); + + nuv->priv->state = GST_NUV_DEMUX_FRAME_HEADER; + + if (flush) { + gst_pad_push_event (nuv->priv->sinkpad, gst_event_new_flush_stop ()); + + if (nuv->priv->src_video_pad != NULL) { + gst_pad_push_event (nuv->priv->src_video_pad, gst_event_new_flush_stop ()); + } + + if (nuv->priv->src_audio_pad != NULL) { + gst_pad_push_event (nuv->priv->src_audio_pad, gst_event_new_flush_stop ()); + } + } + + g_debug ("STARTING TASK AGAIN"); + gst_pad_start_task (nuv->priv->sinkpad, (GstTaskFunction) gst_nuv_demux_loop, + nuv->priv->sinkpad); + + GST_PAD_STREAM_UNLOCK (nuv->priv->sinkpad); + return TRUE; + } + return FALSE; +} + +static gboolean +gst_nuv_demux_srcpad_event (GstPad * pad, GstEvent * event) +{ + gboolean res = FALSE; + GstNuvDemux *nuv; + + nuv = GST_NUV_DEMUX (gst_pad_get_parent (pad)); + + switch (GST_EVENT_TYPE (event)) { + case GST_EVENT_SEEK: + res = gst_nuv_demux_do_seek (nuv, event); + break; + default: + res = FALSE; + break; + } + return res; +} static gboolean gst_nuv_demux_sink_event (GstPad *pad, GstEvent *event) @@ -1165,6 +1318,7 @@ gst_event_parse_seek (event, &rate, &format, &flags, &cur_type, &cur, &stop_type, &stop); GST_DEBUG_OBJECT (nuv, "got seek, start %" G_GINT64_FORMAT ", stop %" G_GINT64_FORMAT, cur, stop); g_debug ("got seek, start %" G_GINT64_FORMAT ", stop %" G_GINT64_FORMAT, cur, stop); + res = gst_pad_event_default (pad, event); break; } case GST_EVENT_NEWSEGMENT: @@ -1174,32 +1328,13 @@ GstFormat format; gboolean update; - GST_DEBUG_OBJECT (nuv, "got a new segment event"); gst_event_parse_new_segment (event, &update, &rate, &format, &start, &stop, &time); - GST_DEBUG_OBJECT (nuv, "got newsegment, start %" G_GINT64_FORMAT ", stop %" G_GINT64_FORMAT, start, stop); g_debug ("got newsegment, start %" G_GINT64_FORMAT ", stop %" G_GINT64_FORMAT, start, stop); - nuv->priv->duration_bytes = stop - start; - gst_event_unref (event); - res = TRUE; + //nuv->priv->duration_bytes = stop - start; + res = gst_pad_event_default (pad, event); break; } - case GST_EVENT_QOS: - { -/* - gdouble proportion; - GstClockTimeDiff diff; - GstClockTime timestamp; - - gst_event_parse_qos (event, &proportion, &diff, ×tamp); - if (diff > 0) - nuv->time_qos = timecode + diff; - else - nuv->time_qos = -1; -*/ - break; - } - case GST_EVENT_EOS: default: res = gst_pad_event_default (pad, event); @@ -1299,8 +1434,9 @@ } switch (transition) { - case GST_STATE_CHANGE_READY_TO_NULL: - g_debug ("READY_TO_NULL"); + case GST_STATE_CHANGE_PAUSED_TO_READY: + //case GST_STATE_CHANGE_READY_TO_NULL: + g_debug ("PAUSED_TO_READY"); gst_nuv_demux_reset (GST_NUV_DEMUX (element)); gst_nuv_demux_destoy_src_pad (GST_NUV_DEMUX (element)); break;