+2005-01-26 Jan Schmidt <thaytan@mad.scientist.com>
+ * ext/a52dec/gsta52dec.c: (gst_a52dec_push),
+ (gst_a52dec_handle_event), (gst_a52dec_chain):
+ Add some debug output. Check that a discont has a valid
+ time associated.
+ * ext/alsa/gstalsasink.c: (gst_alsa_sink_check_event),
+ (gst_alsa_sink_loop):
+ Ignore TAG events. A little extra debug for broken timestamps.
+ * ext/dvdnav/dvdnavsrc.c: (dvdnavsrc_init), (dvdnavsrc_loop),
+ (dvdnavsrc_change_state):
+ Ensure we send a discont to engage the link before we send any
+ other events.
+ * ext/dvdread/dvdreadsrc.c: (dvdreadsrc_init),
+ (dvdreadsrc_finalize), (_close), (_open), (_seek_title),
+ (_seek_chapter), (seek_sector), (dvdreadsrc_get),
+ (dvdreadsrc_uri_get_uri), (dvdreadsrc_uri_set_uri):
+ Handle URI of the form dvd://title[,chapter[,angle]]. Currently only
+ dvd://title works in totem because typefinding sends a seek that ends
+ up going back to chapter 1 regardless.
+ * ext/mpeg2dec/gstmpeg2dec.c:
+ * ext/mpeg2dec/gstmpeg2dec.h:
+ Output correct timestamps and handle disconts.
+ * ext/ogg/gstoggdemux.c: (get_relative):
+ Small guard against a null dereference.
+ * ext/pango/gsttextoverlay.c: (gst_textoverlay_finalize),
+ (gst_textoverlay_set_property):
+ Free memory when done. Don't call gst_event_filler_get_duration on
+ EOS events. Use GST_LOG and GST_WARNING instead of g_message and
+ g_warning.
+ * ext/smoothwave/gstsmoothwave.c: (gst_smoothwave_init),
+ (draw_line), (gst_smoothwave_dispose), (gst_sw_sinklink),
+ (gst_sw_srclink), (gst_smoothwave_chain):
+ Draw solid lines, prettier colours.
+ * gst/mpeg2sub/gstmpeg2subt.c: (gst_mpeg2subt_init):
+ Add a default palette that'll work for some movies.
+ * gst/mpegstream/gstdvddemux.c: (gst_dvd_demux_init),
+ (gst_dvd_demux_handle_dvd_event), (gst_dvd_demux_send_discont),
+ (gst_dvd_demux_send_subbuffer), (gst_dvd_demux_reset):
+ * gst/mpegstream/gstdvddemux.h:
+ * gst/mpegstream/gstmpegdemux.c: (gst_mpeg_demux_send_discont),
+ (gst_mpeg_demux_parse_syshead), (gst_mpeg_demux_parse_pes):
+ * gst/mpegstream/gstmpegparse.c: (gst_mpeg_parse_init),
+ (gst_mpeg_parse_handle_discont), (gst_mpeg_parse_parse_packhead):
+ * gst/mpegstream/gstmpegparse.h:
+ Use PTM/NAV events when for timestamp adjustment when connected to
+ dvdnavsrc. Don't use many discont events where one suffices.
+ * gst/playback/gstplaybasebin.c: (group_destroy),
+ (gen_preroll_element), (gst_play_base_bin_add_element):
+ * gst/playback/gstplaybasebin.h:
+ Make sure we remove subtitles from the same bin we put them in.
+ * gst/subparse/gstsubparse.c: (convert_encoding), (parse_subrip),
+ (gst_subparse_buffer_format_autodetect),
+ (gst_subparse_change_state):
+ Fix some memleaks and invalid accesses.
+ * gst/typefind/gsttypefindfunctions.c: (ogganx_type_find),
+ (oggskel_type_find), (cmml_type_find), (plugin_init):
+ Some typefind functions for Annodex v3.0 files
+ * gst/wavparse/gstwavparse.h:
+ GstRiffReadClass is the correct parent class.
+
2005-01-25 Ronald S. Bultje <rbultje@ronald.bitfreak.net>
* gst-libs/gst/riff/riff-media.c:
GST_BUFFER_TIMESTAMP (buf) = timestamp;
GST_BUFFER_DURATION (buf) = 256 * GST_SECOND / a52dec->sample_rate;
+ GST_DEBUG_OBJECT (a52dec,
+ "Pushing buffer with ts %" GST_TIME_FORMAT " duration %" GST_TIME_FORMAT,
+ GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)),
+ GST_TIME_ARGS (GST_BUFFER_DURATION (buf)));
+
gst_pad_push (srcpad, GST_DATA (buf));
return 0;
case GST_EVENT_DISCONTINUOUS:{
gint64 val;
- if (!gst_event_discont_get_value (event, GST_FORMAT_TIME, &val)) {
+ if (!gst_event_discont_get_value (event, GST_FORMAT_TIME, &val)
+ || !GST_CLOCK_TIME_IS_VALID (val)) {
GST_WARNING ("No time discont value in event %p", event);
} else {
a52dec->time = val;
buf = GST_BUFFER (_data);
if (GST_BUFFER_TIMESTAMP_IS_VALID (buf)) {
a52dec->time = GST_BUFFER_TIMESTAMP (buf);
+ GST_DEBUG_OBJECT (a52dec,
+ "Received buffer with ts %" GST_TIME_FORMAT " duration %"
+ GST_TIME_FORMAT, GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)),
+ GST_TIME_ARGS (GST_BUFFER_DURATION (buf)));
}
+
if (a52dec->cache) {
buf = gst_buffer_join (a52dec->cache, buf);
a52dec->cache = NULL;
gboolean did_seek;
gboolean need_flush;
- gboolean need_discont;
+ gboolean need_newmedia;
/* Timing */
GstClock *clock; /* The clock for this element. */
src->did_seek = FALSE;
src->need_flush = FALSE;
+ src->need_newmedia = TRUE;
/* Pause mode is initially inactive. */
src->pause_mode = DVDNAVSRC_PAUSE_OFF;
g_return_if_fail (dvdnavsrc_is_open (src));
- if (src->did_seek) {
+ if (src->did_seek || src->need_newmedia) {
GstEvent *event;
src->did_seek = FALSE;
GST_INFO_OBJECT (src, "sending discont");
- event = gst_event_new_discontinuous (FALSE, 0);
+
+ event = gst_event_new_discontinuous (src->need_newmedia, 0);
+
src->need_flush = FALSE;
+ src->need_newmedia = FALSE;
gst_pad_push (src->srcpad, GST_DATA (event));
return;
}
}
}
src->streaminfo = NULL;
+ src->need_newmedia = TRUE;
break;
case GST_STATE_PAUSED_TO_PLAYING:
break;
/* location */
gchar *location;
+ gchar *last_uri;
gboolean new_seek;
dvdreadsrc_get_formats);
gst_element_add_pad (GST_ELEMENT (dvdreadsrc), dvdreadsrc->priv->srcpad);
+ dvdreadsrc->priv->dvd = NULL;
+ dvdreadsrc->priv->vts_file = NULL;
+ dvdreadsrc->priv->vmg_file = NULL;
+ dvdreadsrc->priv->dvd_title = NULL;
+
dvdreadsrc->priv->location = g_strdup ("/dev/dvd");
+ dvdreadsrc->priv->last_uri = NULL;
dvdreadsrc->priv->new_seek = TRUE;
dvdreadsrc->priv->new_cell = TRUE;
dvdreadsrc->priv->title = 0;
if (dvdreadsrc->priv) {
g_free (dvdreadsrc->priv->location);
+ g_free (dvdreadsrc->priv->last_uri);
g_free (dvdreadsrc->priv);
dvdreadsrc->priv = NULL;
}
}
static int
+_close (DVDReadSrcPrivate * priv)
+{
+ ifoClose (priv->vts_file);
+ priv->vts_file = NULL;
+
+ ifoClose (priv->vmg_file);
+ priv->vmg_file = NULL;
+
+ DVDCloseFile (priv->dvd_title);
+ priv->dvd_title = NULL;
+
+ DVDClose (priv->dvd);
+ priv->dvd = NULL;
+
+ return 0;
+}
+
+static int
_open (DVDReadSrcPrivate * priv, const gchar * location)
{
g_return_val_if_fail (priv != NULL, -1);
priv->vmg_file = ifoOpen (priv->dvd, 0);
if (!priv->vmg_file) {
GST_ERROR ("Can't open VMG info");
- DVDClose (priv->dvd);
return -1;
}
priv->tt_srpt = priv->vmg_file->tt_srpt;
}
static int
-_close (DVDReadSrcPrivate * priv)
-{
- ifoClose (priv->vts_file);
- ifoClose (priv->vmg_file);
- DVDCloseFile (priv->dvd_title);
- DVDClose (priv->dvd);
- return 0;
-}
-
-static int
_seek_title (DVDReadSrcPrivate * priv, int title, int angle)
{
GHashTable *languagelist = NULL;
*/
GST_LOG ("There are %d titles on this DVD", priv->tt_srpt->nr_of_srpts);
if (title < 0 || title >= priv->tt_srpt->nr_of_srpts) {
- GST_ERROR ("Invalid title %d (only %d available)",
+ GST_WARNING ("Invalid title %d (only %d available)",
title, priv->tt_srpt->nr_of_srpts);
- ifoClose (priv->vmg_file);
- DVDClose (priv->dvd);
- return -1;
+
+ if (title < 0)
+ title = 0;
+ else
+ title = priv->tt_srpt->nr_of_srpts - 1;
}
GST_LOG ("There are %d chapters in this title",
priv->tt_srpt->title[title].nr_of_angles);
if (angle < 0 || angle >= priv->tt_srpt->title[title].nr_of_angles) {
- GST_ERROR ("Invalid angle %d (only %d available)",
+ GST_WARNING ("Invalid angle %d (only %d available)",
angle, priv->tt_srpt->title[title].nr_of_angles);
- ifoClose (priv->vmg_file);
- DVDClose (priv->dvd);
- return -1;
+ if (angle < 0)
+ angle = 0;
+ else
+ angle = priv->tt_srpt->title[title].nr_of_angles - 1;
}
-
/**
* Load the VTS information for the title set our title is in.
*/
if (!priv->vts_file) {
GST_ERROR ("Can't open the info file of title %d",
priv->tt_srpt->title[title].title_set_nr);
- ifoClose (priv->vmg_file);
- DVDClose (priv->dvd);
+ _close (priv);
return -1;
}
if (!priv->dvd_title) {
GST_ERROR ("Can't open title VOBS (VTS_%02d_1.VOB)",
priv->tt_srpt->title[title].title_set_nr);
- ifoClose (priv->vts_file);
- ifoClose (priv->vmg_file);
- DVDClose (priv->dvd);
+ _close (priv);
return -1;
}
g_hash_table_destroy (languagelist);
GST_LOG ("Opened title %d, angle %d", title, angle);
+ priv->title = title;
+ priv->angle = angle;
return 0;
}
* Make sure the chapter number is valid for this title.
*/
if (chapter < 0 || chapter >= priv->tt_srpt->title[priv->title].nr_of_ptts) {
- GST_ERROR ("Invalid chapter %d (only %d available)",
+ GST_WARNING ("Invalid chapter %d (only %d available)",
chapter, priv->tt_srpt->title[priv->title].nr_of_ptts);
- ifoClose (priv->vmg_file);
- DVDClose (priv->dvd);
- return -1;
+ if (chapter < 0)
+ chapter = 0;
+ chapter = priv->tt_srpt->title[priv->title].nr_of_ptts - 1;
}
/**
priv->new_cell = TRUE;
priv->next_cell = priv->start_cell;
+ priv->chapter = chapter;
return 0;
}
static gboolean
seek_sector (DVDReadSrcPrivate * priv, int angle)
{
- gint seek_to = priv->cur_pack, chapter, sectors, next, cur, i;
+ gint seek_to = priv->cur_pack;
+ gint chapter, sectors, next, cur, i;
/* retrieve position */
priv->cur_pack = 0;
priv->seek_pend_fmt = GST_FORMAT_UNDEFINED;
} else {
if (!seek_sector (priv, priv->angle)) {
+ gst_element_set_eos (GST_ELEMENT (dvdreadsrc));
return GST_DATA (gst_event_new (GST_EVENT_EOS));
}
}
static const gchar *
dvdreadsrc_uri_get_uri (GstURIHandler * handler)
{
- return "dvd://";
+ DVDReadSrc *dvdreadsrc = DVDREADSRC (handler);
+
+ g_free (dvdreadsrc->priv->last_uri);
+ dvdreadsrc->priv->last_uri =
+ g_strdup_printf ("dvd://%d,%d,%d", dvdreadsrc->priv->title,
+ dvdreadsrc->priv->chapter, dvdreadsrc->priv->angle);
+
+ return dvdreadsrc->priv->last_uri;
}
static gboolean
dvdreadsrc_uri_set_uri (GstURIHandler * handler, const gchar * uri)
{
+ DVDReadSrc *dvdreadsrc = DVDREADSRC (handler);
gboolean ret;
gchar *protocol = gst_uri_get_protocol (uri);
ret = (protocol && !strcmp (protocol, "dvd")) ? TRUE : FALSE;
g_free (protocol);
+ protocol = NULL;
+
+ if (!ret)
+ return ret;
+
+ /*
+ * Parse out the new t/c/a and seek to them
+ */
+ {
+ gchar *location = NULL;
+ gchar **strs;
+ gchar **strcur;
+ gint pos = 0;
+
+ location = gst_uri_get_location (uri);
+
+ if (!location)
+ return ret;
+
+ strcur = strs = g_strsplit (location, ",", 0);
+ while (strcur && *strcur) {
+ gint val;
+
+ if (!sscanf (*strcur, "%d", &val))
+ break;
+
+ switch (pos) {
+ case 0:
+ if (val != dvdreadsrc->priv->title) {
+ dvdreadsrc->priv->title = val;
+ dvdreadsrc->priv->new_seek = TRUE;
+ }
+ break;
+ case 1:
+ if (val != dvdreadsrc->priv->chapter) {
+ dvdreadsrc->priv->chapter = val;
+ dvdreadsrc->priv->new_seek = TRUE;
+ }
+ break;
+ case 2:
+ dvdreadsrc->priv->angle = val;
+ break;
+ }
+
+ strcur++;
+ pos++;
+ }
+
+ g_strfreev (strs);
+ g_free (location);
+ }
return ret;
}
GstMpeg2dec *mpeg2dec = GST_MPEG2DEC (gst_pad_get_parent (pad));
guint32 size;
guint8 *data, *end;
- gint64 pts;
+ GstClockTime pts;
const mpeg2_info_t *info;
mpeg2_state_t state;
gboolean done = FALSE;
switch (GST_EVENT_TYPE (event)) {
case GST_EVENT_DISCONTINUOUS:
{
- GST_DEBUG_OBJECT (mpeg2dec, "discont, resetting next_time to 0");
- mpeg2dec->next_time = 0;
+ GstClockTime time;
+
+ if (!gst_event_discont_get_value (event, GST_FORMAT_TIME, &time)
+ || !GST_CLOCK_TIME_IS_VALID (time)) {
+ GST_WARNING_OBJECT (mpeg2dec,
+ "No new time offset in discont event %p", event);
+ } else {
+ mpeg2dec->next_time = time;
+ GST_DEBUG_OBJECT (mpeg2dec,
+ "discont, reset next_time to %" G_GUINT64_FORMAT " (%"
+ GST_TIME_FORMAT ")", mpeg2dec->next_time,
+ GST_TIME_ARGS (mpeg2dec->next_time));
+ }
+
mpeg2dec->discont_state = MPEG2DEC_DISC_NEW_PICTURE;
gst_mpeg2dec_flush_decoder (mpeg2dec);
gst_pad_event_default (pad, event);
info = mpeg2_info (mpeg2dec->decoder);
end = data + size;
- if (pts != -1) {
+ if (pts != GST_CLOCK_TIME_NONE) {
gint64 mpeg_pts = GST_TIME_TO_MPEG_TIME (pts);
GST_DEBUG_OBJECT (mpeg2dec,
GST_LOG ("no pts");
}
- GST_LOG ("calling mpeg2_buffer");
+ GST_LOG_OBJECT (mpeg2dec, "calling mpeg2_buffer");
mpeg2_buffer (mpeg2dec->decoder, data, end);
- GST_LOG ("calling mpeg2_buffer done");
+ GST_LOG_OBJECT (mpeg2dec, "calling mpeg2_buffer done");
while (!done) {
gboolean slice = FALSE;
- GST_LOG ("calling parse");
+ GST_LOG_OBJECT (mpeg2dec, "calling parse");
state = mpeg2_parse (mpeg2dec->decoder);
GST_DEBUG_OBJECT (mpeg2dec, "parse state %d", state);
switch (state) {
info->sequence->frame_period * GST_USECOND / 27;
GST_DEBUG_OBJECT (mpeg2dec,
- "sequence flags: %d, frame period: %d, frame rate: %d",
+ "sequence flags: %d, frame period: %d (%g), frame rate: %g",
info->sequence->flags, info->sequence->frame_period,
+ (double) (mpeg2dec->frame_period) / GST_SECOND,
mpeg2dec->frame_rate);
GST_DEBUG_OBJECT (mpeg2dec, "profile: %02x, colour_primaries: %d",
info->sequence->profile_level_id, info->sequence->colour_primaries);
break;
}
case STATE_SLICE_1ST:
- GST_DEBUG_OBJECT (mpeg2dec, "slice 1st");
+ GST_LOG_OBJECT (mpeg2dec, "1st slice of frame encountered");
break;
case STATE_PICTURE_2ND:
- GST_DEBUG_OBJECT (mpeg2dec, "picture second");
+ GST_LOG_OBJECT (mpeg2dec,
+ "Second picture header encountered. Decoding 2nd field");
break;
case STATE_SLICE:
slice = TRUE;
#else
if (picture->flags & PIC_FLAG_TAGS) {
GstClockTime time =
- MPEG_TIME_TO_GST_TIME ((guint64) picture->tag2 << 32 | picture->
- tag);
+ MPEG_TIME_TO_GST_TIME ((GstClockTime) (picture->
+ tag2) << 32 | picture->tag);
#endif
-
- GST_DEBUG_OBJECT (mpeg2dec, "picture had pts %" GST_TIME_FORMAT,
- GST_TIME_ARGS (time));
+ GST_DEBUG_OBJECT (mpeg2dec,
+ "picture had pts %" GST_TIME_FORMAT ", we had %"
+ GST_TIME_FORMAT, GST_TIME_ARGS (time),
+ GST_TIME_ARGS (mpeg2dec->next_time));
GST_BUFFER_TIMESTAMP (outbuf) = mpeg2dec->next_time = time;
} else {
GST_DEBUG_OBJECT (mpeg2dec,
- "picture didn't have pts using %" GST_TIME_FORMAT,
+ "picture didn't have pts. Using %" GST_TIME_FORMAT,
GST_TIME_ARGS (mpeg2dec->next_time));
GST_BUFFER_TIMESTAMP (outbuf) = mpeg2dec->next_time;
}
- mpeg2dec->next_time +=
- (mpeg2dec->frame_period * picture->nb_fields) >> 1;
+ /* TODO set correct offset here based on frame number */
+ if (info->display_picture_2nd) {
+ GST_BUFFER_DURATION (outbuf) = (picture->nb_fields +
+ info->display_picture_2nd->nb_fields) * mpeg2dec->frame_period /
+ 2;
+ } else {
+ GST_BUFFER_DURATION (outbuf) =
+ picture->nb_fields * mpeg2dec->frame_period / 2;
+ }
+ mpeg2dec->next_time += GST_BUFFER_DURATION (outbuf);
GST_DEBUG_OBJECT (mpeg2dec,
"picture: %s %s fields:%d off:%" G_GINT64_FORMAT " ts:%"
GST_DEBUG_OBJECT (mpeg2dec, "dropping buffer, asked to skip");
gst_buffer_unref (outbuf);
} else {
- /* TODO set correct offset here based on frame number */
- GST_BUFFER_DURATION (outbuf) = mpeg2dec->frame_period;
GST_LOG_OBJECT (mpeg2dec, "pushing buffer, timestamp %"
GST_TIME_FORMAT ", duration %" GST_TIME_FORMAT,
GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (outbuf)),
break;
/* error */
case STATE_INVALID:
- g_warning ("mpeg2dec: decoding error");
+ GST_WARNING_OBJECT (mpeg2dec, "Decoding error");
/* it looks like setting a new frame in libmpeg2 avoids a crash */
/* FIXME figure out how this screws up sync and buffer leakage */
gst_mpeg2dec_alloc_buffer (mpeg2dec, info, GST_BUFFER_OFFSET (buf));
break;
default:
- g_warning ("%s: unhandled state %d, FIXME",
- gst_element_get_name (GST_ELEMENT (mpeg2dec)), state);
+ GST_ERROR_OBJECT (mpeg2dec, "Unknown libmpeg2 state %d, FIXME", state);
break;
}
case GST_STATE_PLAYING_TO_PAUSED:
break;
case GST_STATE_PAUSED_TO_READY:
+ gst_mpeg2dec_flush_decoder (mpeg2dec);
gst_mpeg2dec_close_decoder (mpeg2dec);
break;
case GST_STATE_READY_TO_NULL:
gboolean closed;
gboolean have_fbuf;
- /* the timestamp of the next frame */
DiscontState discont_state;
- gint64 next_time;
+
+ /* the timestamp of the next frame */
+ GstClockTime next_time;
gint64 segment_start;
gint64 segment_end;
#include "gstdvddemux.h"
+/*
+ * Start the timestamp sequence at 2 seconds to allow for strange audio
+ * timestamps when audio crosses a VOBU
+ */
+#define INITIAL_END_PTM (2 * GST_SECOND)
GST_DEBUG_CATEGORY_STATIC (gstdvddemux_debug);
#define GST_CAT_DEFAULT (gstdvddemux_debug)
dvd_demux->cur_audio_nr = 0;
dvd_demux->cur_subpicture_nr = 0;
- /* Start the timestamp sequence in 0. */
- dvd_demux->last_end_ptm = 0;
-
- /* (Ronald) so, this was disabled. I'm enabling (default) it again.
- * Timestamp adjustment is fairly evil, we would ideally use discont
- * events instead. However, our current clocking has a pretty serious
- * race condition: imagine that $pipeline is at time 30sec and $audio
- * receives a discont to 0sec. Video processes its last buffer and
- * calls _wait() on $timestamp, which is 30s - so we wait (hang) 30sec.
- * This is unacceptable, obviously, and timestamp adjustment, no matter
- * how evil, solves this.
- * Before disabling this again, tripple check that al .vob files on our
- * websites /media/ directory work fine, especially bullet.vob and
- * barrage.vob.
- */
-#if 0
- /* Try to prevent the mpegparse infrastructure from doing timestamp
- adjustment. */
- mpeg_parse->do_adjust = FALSE;
- mpeg_parse->adjust = 0;
-#endif
-
+ dvd_demux->last_end_ptm = INITIAL_END_PTM;
dvd_demux->just_flushed = FALSE;
dvd_demux->discont_time = GST_CLOCK_TIME_NONE;
(double) dvd_demux->last_end_ptm / GST_SECOND,
(double) start_ptm / GST_SECOND,
(double) mpeg_demux->adjust / GST_SECOND);
+
+ /* Disable mpeg_parse's timestamp adjustment in favour of the info
+ * from DVD nav packets.
+ * Timestamp adjustment is fairly evil, we would ideally use discont
+ * events instead. However, our current clocking has a pretty serious
+ * race condition: imagine that $pipeline is at time 30sec and $audio
+ * receives a discont to 0sec. Video processes its last buffer and
+ * calls _wait() on $timestamp, which is 30s - so we wait (hang) 30sec.
+ * This is unacceptable, obviously, and timestamp adjustment, no matter
+ * how evil, solves this.
+ * Before disabling this again, tripple check that al .vob files on our
+ * websites /media/ directory work fine, especially bullet.vob and
+ * barrage.vob.
+ */
+#if 1
+ /* Try to prevent the mpegparse infrastructure from doing timestamp
+ adjustment. */
+ mpeg_parse->use_adjust = FALSE;
+ mpeg_parse->adjust = 0;
+#endif
}
dvd_demux->last_end_ptm = end_ptm;
time gap between the discontinuity and the subsequent data
blocks. */
dvd_demux->discont_time = start_ptm + mpeg_demux->adjust;
+ GST_DEBUG_OBJECT (dvd_demux, "Set discont time to %" G_GINT64_FORMAT,
+ start_ptm + mpeg_demux->adjust);
+
dvd_demux->just_flushed = FALSE;
}
GST_MPEG_PARSE_CLASS (parent_class)->send_discont (mpeg_parse, time);
+ discont = gst_event_new_discontinuous (FALSE, GST_FORMAT_TIME, time, NULL);
+ if (!discont) {
+ GST_ELEMENT_ERROR (GST_ELEMENT (dvd_demux),
+ RESOURCE, FAILED, (NULL), ("Allocation failed"));
+ return;
+ }
+
for (i = 0; i < GST_DVD_DEMUX_NUM_SUBPICTURE_STREAMS; i++) {
if (dvd_demux->subpicture_stream[i] &&
GST_PAD_IS_USABLE (dvd_demux->subpicture_stream[i]->pad)) {
- discont = gst_event_new_discontinuous (FALSE, GST_FORMAT_TIME,
- time, NULL);
+ gst_event_ref (discont);
gst_pad_push (dvd_demux->subpicture_stream[i]->pad, GST_DATA (discont));
}
}
/* Distribute the event to the "current" pads. */
if (GST_PAD_IS_USABLE (dvd_demux->cur_video)) {
- discont = gst_event_new_discontinuous (FALSE, GST_FORMAT_TIME, time, NULL);
-
+ gst_event_ref (discont);
gst_pad_push (dvd_demux->cur_video, GST_DATA (discont));
}
if (GST_PAD_IS_USABLE (dvd_demux->cur_audio)) {
- discont = gst_event_new_discontinuous (FALSE, GST_FORMAT_TIME, time, NULL);
-
+ gst_event_ref (discont);
gst_pad_push (dvd_demux->cur_audio, GST_DATA (discont));
}
if (GST_PAD_IS_USABLE (dvd_demux->cur_subpicture)) {
- discont = gst_event_new_discontinuous (FALSE, GST_FORMAT_TIME, time, NULL);
-
+ gst_event_ref (discont);
gst_pad_push (dvd_demux->cur_subpicture, GST_DATA (discont));
}
+
+ gst_event_unref (discont);
}
static void
minimize the time interval between the discontinuity and the data
buffers following it. */
if (dvd_demux->discont_time != GST_CLOCK_TIME_NONE) {
+ if ((gint64) (dvd_demux->discont_time) < 0) {
+ GST_ERROR ("DVD Discont < 0! % " G_GINT64_FORMAT,
+ (gint64) dvd_demux->discont_time);
+ }
PARSE_CLASS (mpeg_demux)->send_discont (mpeg_parse,
- dvd_demux->discont_time - 200 * GST_MSECOND);
+ dvd_demux->discont_time);
dvd_demux->discont_time = GST_CLOCK_TIME_NONE;
}
dvd_demux->cur_audio_nr = 0;
dvd_demux->cur_subpicture_nr = 0;
dvd_demux->mpeg_version = 0;
- dvd_demux->last_end_ptm = 0;
+ dvd_demux->last_end_ptm = INITIAL_END_PTM;
dvd_demux->just_flushed = FALSE;
dvd_demux->discont_time = GST_CLOCK_TIME_NONE;
gboolean just_flushed; /* The element just received a flush event. */
GstClockTime discont_time; /* If different from GST_CLOCK_TIME_NONE, a
discontinuous event should be sent with the
- given time, before sending the next dara
+ given time, before sending the next data
block.. */
gint mpeg_version; /* Version of the MPEG video stream */
gint i;
GST_DEBUG_OBJECT (mpeg_demux, "discont %" G_GUINT64_FORMAT, time);
+ discont = gst_event_new_discontinuous (FALSE, GST_FORMAT_TIME, time, NULL);
+
+ if (!discont) {
+ GST_ELEMENT_ERROR (GST_ELEMENT (mpeg_demux),
+ RESOURCE, FAILED, (NULL), ("Allocation failed"));
+ return;
+ }
for (i = 0; i < GST_MPEG_DEMUX_NUM_VIDEO_STREAMS; i++) {
if (mpeg_demux->video_stream[i] &&
GST_PAD_IS_USABLE (mpeg_demux->video_stream[i]->pad)) {
- discont = gst_event_new_discontinuous (FALSE, GST_FORMAT_TIME,
- time, NULL);
-
+ gst_event_ref (discont);
gst_pad_push (mpeg_demux->video_stream[i]->pad, GST_DATA (discont));
}
}
for (i = 0; i < GST_MPEG_DEMUX_NUM_AUDIO_STREAMS; i++) {
if (mpeg_demux->audio_stream[i] &&
GST_PAD_IS_USABLE (mpeg_demux->audio_stream[i]->pad)) {
- discont = gst_event_new_discontinuous (FALSE, GST_FORMAT_TIME,
- time, NULL);
-
+ gst_event_ref (discont);
gst_pad_push (mpeg_demux->audio_stream[i]->pad, GST_DATA (discont));
}
}
for (i = 0; i < GST_MPEG_DEMUX_NUM_PRIVATE_STREAMS; i++) {
if (mpeg_demux->private_stream[i] &&
GST_PAD_IS_USABLE (mpeg_demux->private_stream[i]->pad)) {
- discont = gst_event_new_discontinuous (FALSE, GST_FORMAT_TIME,
- time, NULL);
-
+ gst_event_ref (discont);
gst_pad_push (mpeg_demux->private_stream[i]->pad, GST_DATA (discont));
}
}
+
+ gst_event_unref (discont);
}
static void
if (GST_PAD_IS_USABLE (outstream->pad)) {
GstEvent *event;
- gint64 time;
+ GstClockTime time;
time = MPEGTIME_TO_GSTTIME (mpeg_parse->current_scr
+ mpeg_parse->adjust) + mpeg_demux->adjust;
event = gst_event_new_discontinuous (FALSE, GST_FORMAT_TIME,
- MPEGTIME_TO_GSTTIME (time), NULL);
+ time, NULL);
gst_pad_push (outstream->pad, GST_DATA (event));
}
pts |= ((guint64) * buf++) << 7;
pts |= ((guint64) (*buf++ & 0xFE)) >> 1;
- GST_DEBUG_OBJECT (mpeg_demux, "0x%02x (%lld) PTS = %" G_GUINT64_FORMAT,
- id, pts, MPEGTIME_TO_GSTTIME (pts));
+ timestamp =
+ MPEGTIME_TO_GSTTIME (pts + mpeg_parse->adjust) + mpeg_demux->adjust;
- pts += mpeg_parse->adjust;
- timestamp = MPEGTIME_TO_GSTTIME (pts) + mpeg_demux->adjust;
+ GST_DEBUG_OBJECT (mpeg_demux,
+ "0x%02x (% " G_GINT64_FORMAT ") PTS = %" G_GUINT64_FORMAT
+ " (adjusted = %" G_GINT64_FORMAT ")", id, pts,
+ MPEGTIME_TO_GSTTIME (pts),
+ MPEGTIME_TO_GSTTIME (pts + mpeg_parse->adjust) + mpeg_demux->adjust);
} else {
timestamp = GST_CLOCK_TIME_NONE;
}
mpeg_parse->max_discont = DEFAULT_MAX_DISCONT;
mpeg_parse->do_adjust = TRUE;
+ mpeg_parse->use_adjust = TRUE;
GST_FLAG_SET (mpeg_parse, GST_ELEMENT_EVENT_AWARE);
}
g_return_if_fail (GST_EVENT_TYPE (event) == GST_EVENT_DISCONTINUOUS);
- if (gst_event_discont_get_value (event, GST_FORMAT_TIME, &time)) {
- GST_DEBUG_OBJECT (mpeg_parse,
- "forwarding discontinuity, time: %0.3fs", (double) time / GST_SECOND);
+ if (gst_event_discont_get_value (event, GST_FORMAT_TIME, &time)
+ && (GST_CLOCK_TIME_IS_VALID (time))) {
+ GST_DEBUG_OBJECT (mpeg_parse, "forwarding discontinuity, time: %0.3fs",
+ (double) time / GST_SECOND);
if (CLASS (mpeg_parse)->send_discont)
CLASS (mpeg_parse)->send_discont (mpeg_parse, time);
mpeg_parse->current_scr, mpeg_parse->adjust);
if (mpeg_parse->do_adjust) {
- mpeg_parse->adjust +=
- (gint64) mpeg_parse->next_scr - (gint64) mpeg_parse->current_scr;
-
- GST_DEBUG ("new adjust: %" G_GINT64_FORMAT, mpeg_parse->adjust);
+ if (mpeg_parse->use_adjust) {
+ mpeg_parse->adjust +=
+ (gint64) mpeg_parse->next_scr - (gint64) mpeg_parse->current_scr;
+ GST_DEBUG ("new adjust: %" G_GINT64_FORMAT, mpeg_parse->adjust);
+ }
} else {
mpeg_parse->discont_pending = TRUE;
}
guint64 next_scr; /* Expected next SCR. */
guint64 bytes_since_scr;
- gboolean do_adjust; /* Adjust timestamps to smooth
- discontinuities. */
+ gboolean do_adjust; /* If false, send discont events on SCR
+ * jumps
+ */
+ gboolean use_adjust; /* Collect SCR jumps into 'adjust' in
+ * order to adjust timestamps to smooth
+ * discontinuities. */
gint64 adjust; /* Current timestamp adjust value. */
gboolean discont_pending;