Big mpegparse clean up, second round:

Original commit message from CVS:
2005-12-19  Martin Soto  <martinsoto@users.sourceforge.net>

Big mpegparse clean up, second round:

* gst/mpegstream/gstdvddemux.c (gst_dvd_demux_handle_dvd_event):
Send and EOS event down the audio pipeline when an still frame
event arrives. This prevents the pipeline from locking when a
still menu comes directly after a flush.

* gst/mpegstream/gstmpegparse.c (gst_mpeg_parse_reset):
Don't send a newsegment in reset.
(gst_mpeg_parse_adjust_ts): Check for invalid timestamps.
(gst_mpeg_parse_handle_newsegment, gst_mpeg_parse_process_event):
Move the code of handle_newsegment to process_event. Send a
NEWSEGMENT after FLUSH_STOP.
(gst_mpeg_parse_change_state): Send a NEWSEGMENT right after
moving to PAUSED.

* gst/mpegstream/gstmpegdemux.c (gst_mpeg_demux_send_event)
(gst_mpeg_demux_class_init): Don't override send_event.
* gst/mpegstream/gstmpegdemux.c (gst_mpeg_demux_init)
(gst_mpeg_demux_send_event, gst_mpeg_demux_send_subbuffer)
(gst_mpeg_demux_reset):
* gst/mpegstream/gstmpegdemux.h:  Get rid of just_flushed
attribute.

* gst/mpegstream/gstmpegparse.c (gst_mpeg_parse_process_event):
Reset the mpegparse element after a flush.

* gst/mpegstream/gstmpegparse.c (gst_mpeg_parse_handle_newsegment):
Don't forward events.
* gst/mpegstream/gstmpegparse.c (gst_mpeg_parse_process_event):
* gst/mpegstream/gstmpegparse.h (struct _GstMPEGParseClass):
handle_newsegment is not a virtual method anymore.

* gst/mpegstream/gstmpegparse.c (gst_mpeg_parse_send_newsegment)
(gst_mpeg_parse_reset, gst_mpeg_parse_class_init):
* gst/mpegstream/gstmpegparse.h (struct _GstMPEGParseClass): Get
rid of send_newsegment virtual method.

* gst/mpegstream/gstdvddemux.c (gst_dvd_demux_process_event): Only
handle DVD events and call the superclass method for other event
types.
* gst/mpegstream/gstmpegdemux.c (gst_mpeg_demux_send_event): Don't
override process_event anymore.
* gst/mpegstream/gstmpegparse.c (gst_mpeg_parse_event)
(gst_mpeg_parse_process_event): Move actual event processing to
process event so that subclasses can properly override or extend
it.
* gst/mpegstream/gstmpegparse.h (struct _GstMPEGParseClass):
Eliminate time parameter in process event.

* gst/mpegstream/gstmpegdemux.c (gst_mpeg_demux_init)
(gst_mpeg_demux_parse_packet, gst_mpeg_demux_parse_pes)
(gst_mpeg_demux_send_subbuffer):
* gst/mpegstream/gstmpegparse.c (gst_mpeg_parse_class_init)
(gst_mpeg_parse_parse_packhead, gst_mpeg_parse_event)
(gst_mpeg_parse_chain): Use the new adjust_ts method instead of
adding the value of the adjust attribute.
* gst/mpegstream/gstmpegdemux.h (struct _GstMPEGVideoStream): Get
rid of the adjust attribute. Now all timestamp adjustments are
performed by mpegparse using the current segment.
* gst/mpegstream/gstmpegparse.c (gst_mpeg_parse_adjust_ts)
(gst_mpeg_parse_class_init): Implement the adjust_ts method based
on the adjust attribute for SCR values and the current segment.
* gst/mpegstream/gstmpegparse.h (struct _GstMPEGParseClass): New
adjust_ts virtual method to adjust timestamps for outgoing
buffers.
* gst/mpegstream/gstmpegdemux.c (gst_mpeg_demux_send_newsegment)
(gst_mpeg_demux_parse_packet): Don't override send_newsegment.
* gst/mpegstream/gstdvddemux.c (gst_dvd_demux_class_init)
(gst_dvd_demux_handle_newsegment): Don't override
handle_newsegment.
(gst_dvd_demux_process_event, gst_dvd_demux_handle_dvd_event):
Check for DVD events in process_event instead of
handle_dvd_event.

* gst/mpegstream/gstmpegparse.h (struct _GstMPEGParseClass):
* gst/mpegstream/gstmpegparse.c (gst_mpeg_parse_handle_newsegment)
(gst_mpeg_parse_send_newsegment, gst_mpeg_parse_send_event):
* gst/mpegstream/gstmpegdemux.c (gst_mpeg_demux_process_event)
(gst_mpeg_demux_send_event):
* gst/mpegstream/gstdvddemux.c (gst_dvd_demux_process_event)
(gst_dvd_demux_handle_dvd_event):
Eliminate the time parameter in send_event.
This commit is contained in:
Martin Soto 2005-12-19 17:26:47 +00:00
parent 16d1543b88
commit 4c81add3e6
6 changed files with 238 additions and 282 deletions

View file

@ -1,3 +1,89 @@
2005-12-19 Martin Soto <martinsoto@users.sourceforge.net>
Big mpegparse clean up, second round:
* gst/mpegstream/gstdvddemux.c (gst_dvd_demux_handle_dvd_event):
Send and EOS event down the audio pipeline when an still frame
event arrives. This prevents the pipeline from locking when a
still menu comes directly after a flush.
* gst/mpegstream/gstmpegparse.c (gst_mpeg_parse_reset):
Don't send a newsegment in reset.
(gst_mpeg_parse_adjust_ts): Check for invalid timestamps.
(gst_mpeg_parse_handle_newsegment, gst_mpeg_parse_process_event):
Move the code of handle_newsegment to process_event. Send a
NEWSEGMENT after FLUSH_STOP.
(gst_mpeg_parse_change_state): Send a NEWSEGMENT right after
moving to PAUSED.
* gst/mpegstream/gstmpegdemux.c (gst_mpeg_demux_send_event)
(gst_mpeg_demux_class_init): Don't override send_event.
* gst/mpegstream/gstmpegdemux.c (gst_mpeg_demux_init)
(gst_mpeg_demux_send_event, gst_mpeg_demux_send_subbuffer)
(gst_mpeg_demux_reset):
* gst/mpegstream/gstmpegdemux.h: Get rid of just_flushed
attribute.
* gst/mpegstream/gstmpegparse.c (gst_mpeg_parse_process_event):
Reset the mpegparse element after a flush.
* gst/mpegstream/gstmpegparse.c (gst_mpeg_parse_handle_newsegment):
Don't forward events.
* gst/mpegstream/gstmpegparse.c (gst_mpeg_parse_process_event):
* gst/mpegstream/gstmpegparse.h (struct _GstMPEGParseClass):
handle_newsegment is not a virtual method anymore.
* gst/mpegstream/gstmpegparse.c (gst_mpeg_parse_send_newsegment)
(gst_mpeg_parse_reset, gst_mpeg_parse_class_init):
* gst/mpegstream/gstmpegparse.h (struct _GstMPEGParseClass): Get
rid of send_newsegment virtual method.
* gst/mpegstream/gstdvddemux.c (gst_dvd_demux_process_event): Only
handle DVD events and call the superclass method for other event
types.
* gst/mpegstream/gstmpegdemux.c (gst_mpeg_demux_send_event): Don't
override process_event anymore.
* gst/mpegstream/gstmpegparse.c (gst_mpeg_parse_event)
(gst_mpeg_parse_process_event): Move actual event processing to
process event so that subclasses can properly override or extend
it.
* gst/mpegstream/gstmpegparse.h (struct _GstMPEGParseClass):
Eliminate time parameter in process event.
* gst/mpegstream/gstmpegdemux.c (gst_mpeg_demux_init)
(gst_mpeg_demux_parse_packet, gst_mpeg_demux_parse_pes)
(gst_mpeg_demux_send_subbuffer):
* gst/mpegstream/gstmpegparse.c (gst_mpeg_parse_class_init)
(gst_mpeg_parse_parse_packhead, gst_mpeg_parse_event)
(gst_mpeg_parse_chain): Use the new adjust_ts method instead of
adding the value of the adjust attribute.
* gst/mpegstream/gstmpegdemux.h (struct _GstMPEGVideoStream): Get
rid of the adjust attribute. Now all timestamp adjustments are
performed by mpegparse using the current segment.
* gst/mpegstream/gstmpegparse.c (gst_mpeg_parse_adjust_ts)
(gst_mpeg_parse_class_init): Implement the adjust_ts method based
on the adjust attribute for SCR values and the current segment.
* gst/mpegstream/gstmpegparse.h (struct _GstMPEGParseClass): New
adjust_ts virtual method to adjust timestamps for outgoing
buffers.
* gst/mpegstream/gstmpegdemux.c (gst_mpeg_demux_send_newsegment)
(gst_mpeg_demux_parse_packet): Don't override send_newsegment.
* gst/mpegstream/gstdvddemux.c (gst_dvd_demux_class_init)
(gst_dvd_demux_handle_newsegment): Don't override
handle_newsegment.
(gst_dvd_demux_process_event, gst_dvd_demux_handle_dvd_event):
Check for DVD events in process_event instead of
handle_dvd_event.
* gst/mpegstream/gstmpegparse.h (struct _GstMPEGParseClass):
* gst/mpegstream/gstmpegparse.c (gst_mpeg_parse_handle_newsegment)
(gst_mpeg_parse_send_newsegment, gst_mpeg_parse_send_event):
* gst/mpegstream/gstmpegdemux.c (gst_mpeg_demux_process_event)
(gst_mpeg_demux_send_event):
* gst/mpegstream/gstdvddemux.c (gst_dvd_demux_process_event)
(gst_dvd_demux_handle_dvd_event):
Eliminate the time parameter in send_event.
2005-12-18 Jan Schmidt <thaytan@mad.scientist.com>
* ext/mad/gstid3tag.c: (gst_id3_tag_do_typefind),

View file

@ -142,10 +142,8 @@ static void gst_dvd_demux_init (GstDVDDemux * dvd_demux,
static GstFlowReturn gst_dvd_demux_send_buffer (GstMPEGParse * mpeg_parse,
GstBuffer * buffer, GstClockTime time);
static gboolean gst_dvd_demux_process_event (GstMPEGParse * mpeg_parse,
GstEvent * event, GstClockTime time);
GstEvent * event);
static gboolean gst_dvd_demux_handle_newsegment (GstMPEGParse * mpeg_parse,
GstEvent * event, gboolean forward);
static gboolean gst_dvd_demux_handle_dvd_event
(GstDVDDemux * dvd_demux, GstEvent * event);
@ -244,8 +242,6 @@ gst_dvd_demux_class_init (GstDVDDemuxClass * klass)
gstelement_class->change_state = gst_dvd_demux_change_state;
mpeg_parse_class->handle_newsegment = gst_dvd_demux_handle_newsegment;
mpeg_demux_class->get_audio_stream = gst_dvd_demux_get_audio_stream;
mpeg_demux_class->get_video_stream = gst_dvd_demux_get_video_stream;
mpeg_demux_class->send_subbuffer = gst_dvd_demux_send_subbuffer;
@ -299,51 +295,31 @@ gst_dvd_demux_send_buffer (GstMPEGParse * mpeg_parse, GstBuffer * buffer,
}
static gboolean
gst_dvd_demux_process_event (GstMPEGParse * mpeg_parse, GstEvent * event,
GstClockTime time)
gst_dvd_demux_process_event (GstMPEGParse * mpeg_parse, GstEvent * event)
{
GstDVDDemux *dvd_demux = GST_DVD_DEMUX (mpeg_parse);
gboolean ret = TRUE;
switch (GST_EVENT_TYPE (event)) {
case GST_EVENT_CUSTOM_DOWNSTREAM:
if (!gst_dvd_demux_handle_dvd_event (dvd_demux, event)) {
ret = GST_FLOW_ERROR;
case GST_EVENT_CUSTOM_DOWNSTREAM_OOB:
if (gst_structure_has_name (gst_event_get_structure (event),
"application/x-gst-dvd")) {
ret = gst_dvd_demux_handle_dvd_event (dvd_demux, event);
} else {
ret = GST_MPEG_PARSE_CLASS (parent_class)->process_event (mpeg_parse,
event);
}
break;
/* case GST_EVENT_FILLER: */
case GST_EVENT_NEWSEGMENT:
case GST_EVENT_FLUSH_START:
case GST_EVENT_FLUSH_STOP:
ret = PARSE_CLASS (dvd_demux)->send_event (mpeg_parse, event,
GST_CLOCK_TIME_NONE);
break;
default:
/* Propagate the event normally. */
ret = gst_pad_event_default (mpeg_parse->sinkpad, event);
ret = GST_MPEG_PARSE_CLASS (parent_class)->process_event (mpeg_parse,
event);
break;
}
return ret;
}
static gboolean
gst_dvd_demux_handle_newsegment (GstMPEGParse * mpeg_parse,
GstEvent * event, gboolean forward)
{
gboolean ret;
/* Run the superclass implementation to update the current segment. */
ret = GST_MPEG_PARSE_CLASS (parent_class)->handle_newsegment (mpeg_parse,
event, FALSE);
/* Use the current segment to adjust timestamps. */
GST_MPEG_DEMUX (mpeg_parse)->adjust = mpeg_parse->current_segment.accum -
mpeg_parse->current_segment.start;
return ret;
}
static gboolean
gst_dvd_demux_handle_dvd_event (GstDVDDemux * dvd_demux, GstEvent * event)
{
@ -363,16 +339,6 @@ gst_dvd_demux_handle_dvd_event (GstDVDDemux * dvd_demux, GstEvent * event)
}
#endif
if (strcmp (gst_structure_get_name (structure), "application/x-gst-dvd") != 0) {
/* This isn't a DVD event. */
if (GST_EVENT_TIMESTAMP (event) != GST_CLOCK_TIME_NONE) {
GST_EVENT_TIMESTAMP (event) += mpeg_demux->adjust;
}
gst_pad_event_default (mpeg_parse->sinkpad, event);
return TRUE;
}
if (strcmp (event_type, "dvd-audio-stream-change") == 0) {
gint stream_nr;
@ -395,6 +361,11 @@ gst_dvd_demux_handle_dvd_event (GstDVDDemux * dvd_demux, GstEvent * event)
}
gst_dvd_demux_set_cur_subpicture (dvd_demux, stream_nr);
gst_event_unref (event);
} else if (strcmp (event_type, "dvd-spu-still-frame") == 0) {
/* Send an EOS down the audio path, to allow for preroll in the
absence of audio material. */
gst_event_unref (event);
return gst_pad_push_event (dvd_demux->cur_audio, gst_event_new_eos ());
} else if (!strcmp (event_type, "dvd-lang-codes")) {
gint num_substreams = 0, num_audstreams = 0, n;
gchar *t;
@ -469,8 +440,7 @@ gst_dvd_demux_handle_dvd_event (GstDVDDemux * dvd_demux, GstEvent * event)
GST_DEBUG_OBJECT (dvd_demux, "dvddemux Forwarding DVD event %s to all pads",
event_type);
PARSE_CLASS (dvd_demux)->send_event (mpeg_parse, event,
GST_CLOCK_TIME_NONE);
PARSE_CLASS (dvd_demux)->send_event (mpeg_parse, event);
}
return TRUE;

View file

@ -94,12 +94,6 @@ static void gst_mpeg_demux_class_init (GstMPEGDemuxClass * klass);
static GstFlowReturn gst_mpeg_demux_send_buffer (GstMPEGParse * mpeg_parse,
GstBuffer * buffer, GstClockTime time);
static gboolean gst_mpeg_demux_process_event (GstMPEGParse * mpeg_parse,
GstEvent * event, GstClockTime time);
static gboolean gst_mpeg_demux_send_newsegment (GstMPEGParse * parse,
gdouble rate, GstClockTime start_time, GstClockTime stop_time);
static gboolean gst_mpeg_demux_send_event (GstMPEGParse * mpeg_parse,
GstEvent * event, GstClockTime time);
static GstPad *gst_mpeg_demux_new_output_pad (GstMPEGDemux * mpeg_demux,
const gchar * name, GstPadTemplate * temp);
@ -197,9 +191,6 @@ gst_mpeg_demux_class_init (GstMPEGDemuxClass * klass)
mpeg_parse_class->parse_packet = gst_mpeg_demux_parse_packet;
mpeg_parse_class->parse_pes = gst_mpeg_demux_parse_pes;
mpeg_parse_class->send_buffer = gst_mpeg_demux_send_buffer;
mpeg_parse_class->process_event = gst_mpeg_demux_process_event;
mpeg_parse_class->send_newsegment = gst_mpeg_demux_send_newsegment;
mpeg_parse_class->send_event = gst_mpeg_demux_send_event;
klass->new_output_pad = gst_mpeg_demux_new_output_pad;
klass->init_stream = gst_mpeg_demux_init_stream;
@ -232,10 +223,8 @@ gst_mpeg_demux_init (GstMPEGDemux * mpeg_demux, GstMPEGDemuxClass * klass)
mpeg_demux->private_stream[i] = NULL;
}
mpeg_demux->adjust = 0;
mpeg_demux->max_gap = GST_CLOCK_TIME_NONE;
mpeg_demux->max_gap_tolerance = GST_CLOCK_TIME_NONE;
mpeg_demux->just_flushed = FALSE;
}
static GstFlowReturn
@ -246,80 +235,6 @@ gst_mpeg_demux_send_buffer (GstMPEGParse * mpeg_parse, GstBuffer * buffer,
return GST_FLOW_OK;
}
static gboolean
gst_mpeg_demux_process_event (GstMPEGParse * mpeg_parse, GstEvent * event,
GstClockTime time)
{
gboolean ret = TRUE;
switch (GST_EVENT_TYPE (event)) {
/* case GST_EVENT_FILLER: */
case GST_EVENT_NEWSEGMENT:
case GST_EVENT_FLUSH_START:
case GST_EVENT_FLUSH_STOP:
ret = PARSE_CLASS (mpeg_parse)->send_event (mpeg_parse, event,
GST_CLOCK_TIME_NONE);
break;
default:
/* Propagate the event normally. */
ret = gst_pad_event_default (mpeg_parse->sinkpad, event);
break;
}
return ret;
}
static gboolean
gst_mpeg_demux_send_newsegment (GstMPEGParse * mpeg_parse, gdouble rate,
GstClockTime start_time, GstClockTime stop_time)
{
GstMPEGDemux *mpeg_demux = GST_MPEG_DEMUX (mpeg_parse);
g_return_val_if_fail (GST_CLOCK_TIME_IS_VALID (start_time), FALSE);
start_time += mpeg_demux->adjust;
stop_time += mpeg_demux->adjust;
if (!mpeg_demux->just_flushed) {
GST_DEBUG_OBJECT (mpeg_parse, "NEWSEGMENT without flush, st = %llu",
start_time);
/* Add padding to the end to make sure all streams end at the same timestamp */
CLASS (mpeg_demux)->synchronise_pads (mpeg_demux,
mpeg_parse->current_ts + mpeg_demux->adjust + (GST_SECOND / 20),
mpeg_parse->current_ts + mpeg_demux->adjust + (GST_SECOND / 20));
} else {
GST_DEBUG_OBJECT (mpeg_parse, "NEWSEGMENT after flush, st = %llu",
start_time);
}
mpeg_demux->just_flushed = FALSE;
return parent_class->send_newsegment (mpeg_parse, rate, start_time,
stop_time);
}
static gboolean
gst_mpeg_demux_send_event (GstMPEGParse * mpeg_parse, GstEvent * event,
GstClockTime time)
{
/*
* Distribute the event to all active pads
*/
GstMPEGDemux *mpeg_demux = GST_MPEG_DEMUX (mpeg_parse);
GST_DEBUG_OBJECT (mpeg_demux, "Sending %s event",
GST_EVENT_TYPE_NAME (event));
if (GST_EVENT_TYPE (event) == GST_EVENT_FLUSH_START)
mpeg_demux->just_flushed = TRUE;
if (parent_class->send_event)
return parent_class->send_event (mpeg_parse, event, time);
else
gst_event_unref (event);
return TRUE;
}
static gint
_demux_get_writer_id (GstIndex * index, GstPad * pad)
{
@ -769,8 +684,8 @@ done:
headerlen, datalen);
if (pts != -1) {
pts += mpeg_parse->adjust;
timestamp = MPEGTIME_TO_GSTTIME (pts) + mpeg_demux->adjust;
timestamp = PARSE_CLASS (mpeg_parse)->adjust_ts (mpeg_parse,
MPEGTIME_TO_GSTTIME (pts));
/* this apparently happens for some input were headers are
* rewritten to make time start at zero... */
@ -867,8 +782,8 @@ gst_mpeg_demux_parse_pes (GstMPEGParse * mpeg_parse, GstBuffer * buffer)
pts |= ((guint64) * buf++) << 7;
pts |= ((guint64) (*buf++ & 0xFE)) >> 1;
timestamp =
MPEGTIME_TO_GSTTIME (pts + mpeg_parse->adjust) + mpeg_demux->adjust;
timestamp = PARSE_CLASS (mpeg_parse)->adjust_ts (mpeg_parse,
MPEGTIME_TO_GSTTIME (pts));
GST_DEBUG_OBJECT (mpeg_demux,
"0x%02x (% " G_GINT64_FORMAT ") PTS = %" G_GUINT64_FORMAT, id, pts,
@ -957,12 +872,11 @@ gst_mpeg_demux_send_subbuffer (GstMPEGDemux * mpeg_demux,
GstFlowReturn ret;
GstBuffer *outbuf;
mpeg_demux->just_flushed = FALSE;
if (timestamp != GST_CLOCK_TIME_NONE) {
outstream->cur_ts = timestamp;
outstream->scr_offs =
GST_CLOCK_DIFF (timestamp, mpeg_parse->current_ts + mpeg_demux->adjust);
outstream->scr_offs = GST_CLOCK_DIFF (timestamp,
PARSE_CLASS (mpeg_parse)->adjust_ts (mpeg_parse,
mpeg_parse->current_ts));
if (outstream->scr_offs < 0)
outstream->scr_offs = 0;
@ -974,8 +888,8 @@ gst_mpeg_demux_send_subbuffer (GstMPEGDemux * mpeg_demux,
GST_BUFFER_OFFSET (buffer), GST_FORMAT_TIME, timestamp, 0);
}
} else {
outstream->cur_ts =
mpeg_parse->current_ts + mpeg_demux->adjust + outstream->scr_offs;
outstream->cur_ts = PARSE_CLASS (mpeg_parse)->adjust_ts (mpeg_parse,
mpeg_parse->current_ts + outstream->scr_offs);
}
if (size == 0)
@ -995,14 +909,16 @@ gst_mpeg_demux_send_subbuffer (GstMPEGDemux * mpeg_demux,
if (GST_CLOCK_TIME_IS_VALID (mpeg_demux->max_gap) &&
GST_CLOCK_TIME_IS_VALID (mpeg_parse->current_ts) &&
(mpeg_parse->current_ts + mpeg_demux->adjust > mpeg_demux->max_gap)) {
(PARSE_CLASS (mpeg_parse)->adjust_ts (mpeg_parse,
mpeg_parse->current_ts) > mpeg_demux->max_gap)) {
GstClockTime threshold =
GST_CLOCK_DIFF (mpeg_parse->current_ts + mpeg_demux->adjust,
GST_CLOCK_DIFF (PARSE_CLASS (mpeg_parse)->adjust_ts (mpeg_parse,
mpeg_parse->current_ts),
mpeg_demux->max_gap);
CLASS (mpeg_demux)->synchronise_pads (mpeg_demux, threshold,
mpeg_parse->current_ts + mpeg_demux->adjust -
mpeg_demux->max_gap_tolerance);
PARSE_CLASS (mpeg_parse)->adjust_ts (mpeg_parse,
mpeg_parse->current_ts) - mpeg_demux->max_gap_tolerance);
}
return ret;
@ -1290,7 +1206,6 @@ gst_mpeg_demux_reset (GstMPEGDemux * mpeg_demux)
* mpeg_demux->adjust = 0;
* mpeg_demux->max_gap = GST_CLOCK_TIME_NONE;
* mpeg_demux->max_gap_tolerance = GST_CLOCK_TIME_NONE;
* mpeg_demux->just_flushed = FALSE;
*/
}

View file

@ -129,21 +129,15 @@ struct _GstMPEGDemux {
GstMPEGStream *audio_stream[GST_MPEG_DEMUX_NUM_AUDIO_STREAMS];
GstMPEGStream *private_stream[GST_MPEG_DEMUX_NUM_PRIVATE_STREAMS];
GstClockTimeDiff adjust; /* Added to all PTS timestamps. This element
keeps always this value in 0, but it is
there for the benefit of subclasses. */
GstClockTime max_gap; /* Maximum timestamp difference to
allow between pads before using a
filler to catch up. */
GstClockTime max_gap_tolerance;
/* When catching a pad up, how far
behind to make it. */
GstClockTime max_gap; /* Maximum timestamp difference to allow
* between pads before using a filler to catch up
*/
GstClockTime max_gap_tolerance; /* When catching a pad up, how far behind
to make it
*/
GstClockTime max_ts; /* Highest timestamp of all pads */
GstPad *max_pad; /* Pad with highest timestamp */
gboolean just_flushed;
GstClockTime max_ts; /* Highest timestamp of all pads. */
GstPad *max_pad; /* Pad with highest timestamp. */
};
struct _GstMPEGDemuxClass {

View file

@ -99,18 +99,15 @@ static gboolean gst_mpeg_parse_parse_packhead (GstMPEGParse * mpeg_parse,
static void gst_mpeg_parse_reset (GstMPEGParse * mpeg_parse);
static gboolean
gst_mpeg_parse_handle_newsegment (GstMPEGParse * mpeg_parse,
GstEvent * event, gboolean forward);
static GstClockTime gst_mpeg_parse_adjust_ts (GstMPEGParse * mpeg_parse,
GstClockTime ts);
static GstFlowReturn gst_mpeg_parse_send_buffer (GstMPEGParse * mpeg_parse,
GstBuffer * buffer, GstClockTime time);
static GstFlowReturn gst_mpeg_parse_process_event (GstMPEGParse * mpeg_parse,
GstEvent * event, GstClockTime time);
static GstFlowReturn gst_mpeg_parse_send_newsegment (GstMPEGParse * parse,
gdouble rate, GstClockTime start_time, GstClockTime stop_time);
GstEvent * event);
static gboolean gst_mpeg_parse_send_event (GstMPEGParse * mpeg_parse,
GstEvent * event, GstClockTime time);
GstEvent * event);
static void gst_mpeg_parse_pad_added (GstElement * element, GstPad * pad);
@ -162,10 +159,9 @@ gst_mpeg_parse_class_init (GstMPEGParseClass * klass)
klass->parse_syshead = NULL;
klass->parse_packet = NULL;
klass->parse_pes = NULL;
klass->handle_newsegment = gst_mpeg_parse_handle_newsegment;
klass->adjust_ts = gst_mpeg_parse_adjust_ts;
klass->send_buffer = gst_mpeg_parse_send_buffer;
klass->process_event = gst_mpeg_parse_process_event;
klass->send_newsegment = gst_mpeg_parse_send_newsegment;
klass->send_event = gst_mpeg_parse_send_event;
/* FIXME: this is a hack. We add the pad templates here instead
@ -258,7 +254,7 @@ gst_mpeg_parse_update_streaminfo (GstMPEGParse * mpeg_parse)
static void
gst_mpeg_parse_reset (GstMPEGParse * mpeg_parse)
{
GST_DEBUG ("Resetting mpeg_parse");
GST_DEBUG_OBJECT (mpeg_parse, "Resetting mpeg_parse");
mpeg_parse->first_scr = MP_INVALID_SCR;
mpeg_parse->first_scr_pos = 0;
@ -279,52 +275,27 @@ gst_mpeg_parse_reset (GstMPEGParse * mpeg_parse)
mpeg_parse->do_adjust = TRUE;
mpeg_parse->adjust = 0;
/* Reset the current segment. */
/* Initialize the current segment. */
GST_DEBUG_OBJECT (mpeg_parse, "Resetting current segment");
gst_segment_init (&mpeg_parse->current_segment, GST_FORMAT_TIME);
/* Send a corresponding newsegment. */
if (CLASS (mpeg_parse)->send_newsegment) {
CLASS (mpeg_parse)->send_newsegment (mpeg_parse, 1.0, 0,
GST_CLOCK_TIME_NONE);
}
}
static gboolean
gst_mpeg_parse_handle_newsegment (GstMPEGParse * mpeg_parse,
GstEvent * event, gboolean forward)
static GstClockTime
gst_mpeg_parse_adjust_ts (GstMPEGParse * mpeg_parse, GstClockTime ts)
{
gboolean ret = TRUE;
gboolean update;
gdouble rate;
GstFormat format;
gint64 start, stop, time;
gst_event_parse_new_segment (event, &update, &rate, &format,
&start, &stop, &time);
if (format == GST_FORMAT_TIME && (GST_CLOCK_TIME_IS_VALID (time))) {
/* Update the current segment. */
GST_DEBUG_OBJECT (mpeg_parse, "Updating current segment with newsegment");
gst_segment_set_newsegment (&mpeg_parse->current_segment,
update, rate, format, start, stop, time);
if (forward) {
GST_DEBUG_OBJECT (mpeg_parse, "forwarding time based segment");
if (CLASS (mpeg_parse)->send_event) {
ret = CLASS (mpeg_parse)->send_event (mpeg_parse, event, time);
}
}
/* We are receiving segments from upstream. Don't try to adjust
SCR values. */
mpeg_parse->do_adjust = FALSE;
mpeg_parse->adjust = 0;
if (!GST_CLOCK_TIME_IS_VALID (ts)) {
return GST_CLOCK_TIME_NONE;
}
mpeg_parse->packetize->resync = TRUE;
gst_event_unref (event);
return ret;
if (mpeg_parse->do_adjust) {
/* Close the SCR gaps. */
return ts + MPEGTIME_TO_GSTTIME (mpeg_parse->adjust);
} else {
/* Adjust the timestamp in such a way that all segments appear to
be in a single continuous sequence starting at time 0. */
return ts + mpeg_parse->current_segment.accum -
mpeg_parse->current_segment.start;
}
}
static GstFlowReturn
@ -352,7 +323,8 @@ gst_mpeg_parse_send_buffer (GstMPEGParse * mpeg_parse, GstBuffer * buffer,
}
GST_BUFFER_TIMESTAMP (buffer) = time;
GST_DEBUG ("current buffer time: %" GST_TIME_FORMAT, GST_TIME_ARGS (time));
GST_DEBUG_OBJECT (mpeg_parse, "current buffer time: %" GST_TIME_FORMAT,
GST_TIME_ARGS (time));
result = gst_pad_push (mpeg_parse->srcpad, buffer);
@ -360,37 +332,72 @@ gst_mpeg_parse_send_buffer (GstMPEGParse * mpeg_parse, GstBuffer * buffer,
}
static gboolean
gst_mpeg_parse_process_event (GstMPEGParse * mpeg_parse, GstEvent * event,
GstClockTime time)
gst_mpeg_parse_process_event (GstMPEGParse * mpeg_parse, GstEvent * event)
{
return gst_pad_event_default (mpeg_parse->sinkpad, event);
}
gboolean ret = FALSE;
static gboolean
gst_mpeg_parse_send_newsegment (GstMPEGParse * mpeg_parse, gdouble rate,
GstClockTime start_time, GstClockTime stop_time)
{
GstEvent *event;
switch (GST_EVENT_TYPE (event)) {
case GST_EVENT_NEWSEGMENT:
{
gboolean update;
gdouble rate;
GstFormat format;
gint64 start, stop, time;
event = gst_event_new_new_segment (FALSE, rate, GST_FORMAT_TIME,
start_time, stop_time, 0);
gst_event_parse_new_segment (event, &update, &rate, &format,
&start, &stop, &time);
/* Update the current segment. */
GST_DEBUG_OBJECT (mpeg_parse, "Setting current segment");
gst_segment_set_newsegment (&mpeg_parse->current_segment, FALSE, rate,
GST_FORMAT_TIME, start_time, stop_time, 0);
if (format == GST_FORMAT_TIME && (GST_CLOCK_TIME_IS_VALID (time))) {
/* Update the current segment. */
GST_DEBUG_OBJECT (mpeg_parse,
"Updating current segment with newsegment");
gst_segment_set_newsegment (&mpeg_parse->current_segment,
update, rate, format, start, stop, time);
if (CLASS (mpeg_parse)->send_event) {
return CLASS (mpeg_parse)->send_event (mpeg_parse, event, start_time);
/* We are receiving segments from upstream. Don't try to adjust
SCR values. */
mpeg_parse->do_adjust = FALSE;
mpeg_parse->adjust = 0;
}
mpeg_parse->packetize->resync = TRUE;
gst_event_unref (event);
ret = TRUE;
break;
}
case GST_EVENT_FLUSH_STOP:
/* Forward the event. */
if (CLASS (mpeg_parse)->send_event) {
ret = CLASS (mpeg_parse)->send_event (mpeg_parse, event);
} else {
gst_event_unref (event);
}
/* Send a newsegment event to restart counting from 0. */
if (CLASS (mpeg_parse)->send_event) {
CLASS (mpeg_parse)->send_event (mpeg_parse,
gst_event_new_new_segment (FALSE, 1.0, GST_FORMAT_TIME, 0, -1, 0));
}
/* Reset the internal fields. */
gst_mpeg_parse_reset (mpeg_parse);
break;
default:
if (CLASS (mpeg_parse)->send_event) {
ret = CLASS (mpeg_parse)->send_event (mpeg_parse, event);
} else {
gst_event_unref (event);
}
break;
}
gst_event_unref (event);
return FALSE;
return ret;
}
static gboolean
gst_mpeg_parse_send_event (GstMPEGParse * mpeg_parse, GstEvent * event,
GstClockTime time)
gst_mpeg_parse_send_event (GstMPEGParse * mpeg_parse, GstEvent * event)
{
GstIterator *it;
gpointer pad;
@ -541,19 +548,19 @@ gst_mpeg_parse_parse_packhead (GstMPEGParse * mpeg_parse, GstBuffer * buffer)
if (mpeg_parse->do_adjust && diff > mpeg_parse->max_scr_gap) {
/* SCR gap found, fix the adjust value. */
GST_DEBUG ("SCR gap detected; expected: %" G_GUINT64_FORMAT " got: %"
G_GUINT64_FORMAT " adjusted:%" G_GINT64_FORMAT " adjust:%"
G_GINT64_FORMAT, mpeg_parse->next_scr, mpeg_parse->current_scr,
mpeg_parse->current_scr + mpeg_parse->adjust, mpeg_parse->adjust);
GST_DEBUG_OBJECT (mpeg_parse, "SCR gap detected; expected: %"
G_GUINT64_FORMAT " got: %" G_GUINT64_FORMAT,
mpeg_parse->next_scr, mpeg_parse->current_scr);
mpeg_parse->adjust +=
(gint64) mpeg_parse->next_scr - (gint64) mpeg_parse->current_scr;
GST_DEBUG ("new adjust: %" G_GINT64_FORMAT, mpeg_parse->adjust);
GST_DEBUG_OBJECT (mpeg_parse, "new adjust: %" G_GINT64_FORMAT,
mpeg_parse->adjust);
}
/* Update the current timestamp. */
mpeg_parse->current_ts = MPEGTIME_TO_GSTTIME (mpeg_parse->current_scr +
mpeg_parse->adjust);
mpeg_parse->current_ts = CLASS (mpeg_parse)->adjust_ts (mpeg_parse,
MPEGTIME_TO_GSTTIME (mpeg_parse->current_scr));
/* Check for the reached offset signal. */
offset = gst_mpeg_packetize_tell (mpeg_parse->packetize);
@ -588,13 +595,15 @@ gst_mpeg_parse_parse_packhead (GstMPEGParse * mpeg_parse, GstBuffer * buffer)
mpeg_parse->avg_bitrate_time;
}
//gst_mpeg_parse_update_streaminfo (mpeg_parse);
GST_LOG ("stream current is %1.3fMbs, calculated over %1.3fkB",
GST_LOG_OBJECT (mpeg_parse,
"stream current is %1.3fMbs, calculated over %1.3fkB",
(mpeg_parse->mux_rate * 8) / 1048576.0,
mpeg_parse->bytes_since_scr / 1024.0);
}
if (mpeg_parse->avg_bitrate_bytes) {
GST_LOG ("stream avg is %1.3fMbs, calculated over %1.3fkB",
GST_LOG_OBJECT (mpeg_parse,
"stream avg is %1.3fMbs, calculated over %1.3fkB",
(float) (mpeg_parse->avg_bitrate_bytes) * 8 * GST_SECOND
/ mpeg_parse->avg_bitrate_time / 1048576.0,
mpeg_parse->avg_bitrate_bytes / 1024.0);
@ -613,30 +622,10 @@ gst_mpeg_parse_parse_packhead (GstMPEGParse * mpeg_parse, GstBuffer * buffer)
static gboolean
gst_mpeg_parse_event (GstPad * pad, GstEvent * event)
{
gboolean ret;
GstMPEGParse *mpeg_parse = GST_MPEG_PARSE (gst_pad_get_parent (pad));
GstClockTime time;
gboolean ret = FALSE;
if (mpeg_parse->current_scr != MP_INVALID_SCR) {
time = MPEGTIME_TO_GSTTIME (mpeg_parse->current_scr);
} else {
time = GST_CLOCK_TIME_NONE;
}
switch (GST_EVENT_TYPE (event)) {
case GST_EVENT_NEWSEGMENT:
if (CLASS (mpeg_parse)->handle_newsegment)
ret = CLASS (mpeg_parse)->handle_newsegment (mpeg_parse, event, TRUE);
else
gst_event_unref (event);
break;
default:
if (CLASS (mpeg_parse)->process_event)
ret = CLASS (mpeg_parse)->process_event (mpeg_parse, event, time);
else
gst_event_unref (event);
break;
}
ret = CLASS (mpeg_parse)->process_event (mpeg_parse, event);
gst_object_unref (mpeg_parse);
return ret;
@ -704,7 +693,7 @@ gst_mpeg_parse_chain (GstPad * pad, GstBuffer * buffer)
/* Don't send data as long as no new SCR is found. */
if (mpeg_parse->current_scr == MP_INVALID_SCR) {
GST_DEBUG ("waiting for SCR");
GST_DEBUG_OBJECT (mpeg_parse, "waiting for SCR");
gst_buffer_unref (buffer);
result = GST_FLOW_OK;
goto done;
@ -733,7 +722,8 @@ gst_mpeg_parse_chain (GstPad * pad, GstBuffer * buffer)
/* Send the buffer. */
g_return_val_if_fail (mpeg_parse->current_scr != MP_INVALID_SCR,
GST_FLOW_OK);
time = MPEGTIME_TO_GSTTIME (mpeg_parse->current_scr + mpeg_parse->adjust);
time = CLASS (mpeg_parse)->adjust_ts (mpeg_parse,
MPEGTIME_TO_GSTTIME (mpeg_parse->current_scr));
if (CLASS (mpeg_parse)->send_buffer)
result = CLASS (mpeg_parse)->send_buffer (mpeg_parse, buffer, time);
@ -1089,7 +1079,7 @@ normal_seek (GstMPEGParse * mpeg_parse, GstPad * pad, GstEvent * event)
offset = cur;
if (offset != -1) {
GST_LOG ("starting conversion of cur");
GST_LOG_OBJECT (mpeg_parse, "starting conversion of cur");
/* Bring the format to time on srcpad. */
conv = GST_FORMAT_TIME;
if (!gst_pad_query_convert (pad, format, offset, &conv, &start_position)) {
@ -1101,14 +1091,15 @@ normal_seek (GstMPEGParse * mpeg_parse, GstPad * pad, GstEvent * event)
start_position, &conv, &start_position)) {
goto done;
}
GST_INFO ("Finished conversion of cur, BYTES cur : %lld", start_position);
GST_INFO_OBJECT (mpeg_parse,
"Finished conversion of cur, BYTES cur : %lld", start_position);
} else {
start_position = -1;
}
offset = stop;
if (offset != -1) {
GST_INFO ("starting conversion of stop");
GST_INFO_OBJECT (mpeg_parse, "starting conversion of stop");
/* Bring the format to time on srcpad. */
conv = GST_FORMAT_TIME;
if (!gst_pad_query_convert (pad, format, offset, &conv, &end_position)) {
@ -1120,7 +1111,8 @@ normal_seek (GstMPEGParse * mpeg_parse, GstPad * pad, GstEvent * event)
end_position, &conv, &end_position)) {
goto done;
}
GST_INFO ("Finished conversion of stop, BYTES stop : %lld", end_position);
GST_INFO_OBJECT (mpeg_parse,
"Finished conversion of stop, BYTES stop : %lld", end_position);
} else {
end_position = -1;
}
@ -1196,8 +1188,15 @@ gst_mpeg_parse_change_state (GstElement * element, GstStateChange transition)
gst_mpeg_packetize_new (mpeg_parse->srcpad,
GST_MPEG_PACKETIZE_SYSTEM);
}
/* initialize parser state */
/* Initialize parser state */
gst_mpeg_parse_reset (mpeg_parse);
/* Send a newsegment event to start counting from 0. */
if (CLASS (mpeg_parse)->send_event) {
CLASS (mpeg_parse)->send_event (mpeg_parse,
gst_event_new_new_segment (FALSE, 1.0, GST_FORMAT_TIME, 0, -1, 0));
}
break;
default:
break;

View file

@ -109,21 +109,13 @@ struct _GstMPEGParseClass
/* Process an event */
gboolean (*process_event) (GstMPEGParse * parse,
GstEvent * event, GstClockTime time);
/* Process a newsegment event */
gboolean (*handle_newsegment)
(GstMPEGParse * parse, GstEvent * event,
gboolean forward);
GstEvent * event);
/* Send an event */
gboolean (*send_event) (GstMPEGParse * parse, GstEvent *event,
GstClockTime time);
gboolean (*send_event) (GstMPEGParse * parse, GstEvent *event);
/* Send a newsegment event. */
gboolean (*send_newsegment)(GstMPEGParse * parse, gdouble rate,
GstClockTime start_time,
GstClockTime stop_time);
/* Adjust a timestamp */
GstClockTime (*adjust_ts) (GstMPEGParse * parse, GstClockTime ts);
/* Signals */
void (*reached_offset) (GstMPEGParse *parse,