ext/a52dec/gsta52dec.c: Add some debug output. Check that a discont has a valid time associated.

Original commit message from CVS:
* 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.
This commit is contained in:
Jan Schmidt 2005-01-25 15:34:08 +00:00
parent 06862c4645
commit f8d863517a
11 changed files with 322 additions and 117 deletions

View file

@ -1,3 +1,63 @@
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:

View file

@ -283,6 +283,11 @@ gst_a52dec_push (GstA52Dec * a52dec,
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;
@ -324,7 +329,8 @@ gst_a52dec_handle_event (GstA52Dec * a52dec, GstEvent * event)
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;
@ -442,7 +448,12 @@ gst_a52dec_chain (GstPad * pad, GstData * _data)
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;

View file

@ -124,7 +124,7 @@ struct _DVDNavSrc
gboolean did_seek;
gboolean need_flush;
gboolean need_discont;
gboolean need_newmedia;
/* Timing */
GstClock *clock; /* The clock for this element. */
@ -395,6 +395,7 @@ dvdnavsrc_init (DVDNavSrc * src)
src->did_seek = FALSE;
src->need_flush = FALSE;
src->need_newmedia = TRUE;
/* Pause mode is initially inactive. */
src->pause_mode = DVDNAVSRC_PAUSE_OFF;
@ -1278,13 +1279,16 @@ dvdnavsrc_loop (GstElement * element)
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;
}
@ -1595,6 +1599,7 @@ dvdnavsrc_change_state (GstElement * element)
}
}
src->streaminfo = NULL;
src->need_newmedia = TRUE;
break;
case GST_STATE_PAUSED_TO_PLAYING:
break;

View file

@ -53,6 +53,7 @@ struct _DVDReadSrcPrivate
/* location */
gchar *location;
gchar *last_uri;
gboolean new_seek;
@ -235,7 +236,13 @@ dvdreadsrc_init (DVDReadSrc * dvdreadsrc)
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;
@ -254,6 +261,7 @@ dvdreadsrc_finalize (GObject * object)
if (dvdreadsrc->priv) {
g_free (dvdreadsrc->priv->location);
g_free (dvdreadsrc->priv->last_uri);
g_free (dvdreadsrc->priv);
dvdreadsrc->priv = NULL;
}
@ -549,6 +557,24 @@ is_nav_pack (unsigned char *buffer)
return (buffer[41] == 0xbf && buffer[1027] == 0xbf);
}
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)
{
@ -572,7 +598,6 @@ _open (DVDReadSrcPrivate * priv, const gchar * location)
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;
@ -580,16 +605,6 @@ _open (DVDReadSrcPrivate * priv, const gchar * location)
return 0;
}
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)
{
@ -600,11 +615,13 @@ _seek_title (DVDReadSrcPrivate * priv, int title, int angle)
*/
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",
@ -617,14 +634,14 @@ _seek_title (DVDReadSrcPrivate * priv, int title, int angle)
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.
*/
@ -633,8 +650,7 @@ _seek_title (DVDReadSrcPrivate * priv, int title, int angle)
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;
}
@ -650,9 +666,7 @@ _seek_title (DVDReadSrcPrivate * priv, int title, int angle)
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;
}
@ -665,6 +679,8 @@ _seek_title (DVDReadSrcPrivate * priv, int title, int angle)
g_hash_table_destroy (languagelist);
GST_LOG ("Opened title %d, angle %d", title, angle);
priv->title = title;
priv->angle = angle;
return 0;
}
@ -678,11 +694,11 @@ _seek_chapter (DVDReadSrcPrivate * priv, int chapter)
* 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;
}
/**
@ -730,6 +746,7 @@ _seek_chapter (DVDReadSrcPrivate * priv, int chapter)
priv->new_cell = TRUE;
priv->next_cell = priv->start_cell;
priv->chapter = chapter;
return 0;
}
@ -907,7 +924,8 @@ again:
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;
@ -992,6 +1010,7 @@ dvdreadsrc_get (GstPad * pad)
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));
}
}
@ -1122,17 +1141,76 @@ dvdreadsrc_uri_get_protocols (void)
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;
}

View file

@ -585,7 +585,7 @@ gst_mpeg2dec_chain (GstPad * pad, GstData * _data)
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;
@ -596,8 +596,20 @@ gst_mpeg2dec_chain (GstPad * pad, GstData * _data)
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);
@ -626,7 +638,7 @@ gst_mpeg2dec_chain (GstPad * pad, GstData * _data)
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,
@ -643,14 +655,14 @@ gst_mpeg2dec_chain (GstPad * pad, GstData * _data)
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) {
@ -676,8 +688,9 @@ gst_mpeg2dec_chain (GstPad * pad, GstData * _data)
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);
@ -741,10 +754,11 @@ gst_mpeg2dec_chain (GstPad * pad, GstData * _data)
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;
@ -788,22 +802,31 @@ gst_mpeg2dec_chain (GstPad * pad, GstData * _data)
#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:%"
@ -840,8 +863,6 @@ gst_mpeg2dec_chain (GstPad * pad, GstData * _data)
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)),
@ -869,14 +890,13 @@ gst_mpeg2dec_chain (GstPad * pad, GstData * _data)
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;
}
@ -1306,6 +1326,7 @@ gst_mpeg2dec_change_state (GstElement * element)
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:

View file

@ -71,9 +71,10 @@ struct _GstMpeg2dec {
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;

View file

@ -26,6 +26,11 @@
#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)
@ -290,28 +295,7 @@ gst_dvd_demux_init (GstDVDDemux * dvd_demux)
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;
@ -416,6 +400,26 @@ gst_dvd_demux_handle_dvd_event (GstDVDDemux * dvd_demux, GstEvent * event)
(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;
@ -425,6 +429,9 @@ gst_dvd_demux_handle_dvd_event (GstDVDDemux * dvd_demux, GstEvent * event)
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;
}
@ -454,34 +461,39 @@ gst_dvd_demux_send_discont (GstMPEGParse * mpeg_parse, GstClockTime time)
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
@ -857,8 +869,12 @@ gst_dvd_demux_send_subbuffer (GstMPEGDemux * mpeg_demux,
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;
}
@ -991,7 +1007,7 @@ gst_dvd_demux_reset (GstDVDDemux * dvd_demux)
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;

View file

@ -107,7 +107,7 @@ struct _GstDVDDemux {
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 */

View file

@ -275,13 +275,18 @@ gst_mpeg_demux_send_discont (GstMPEGParse * mpeg_parse, GstClockTime time)
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));
}
}
@ -289,9 +294,7 @@ gst_mpeg_demux_send_discont (GstMPEGParse * mpeg_parse, GstClockTime time)
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));
}
}
@ -299,12 +302,12 @@ gst_mpeg_demux_send_discont (GstMPEGParse * mpeg_parse, GstClockTime time)
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
@ -618,13 +621,13 @@ gst_mpeg_demux_parse_syshead (GstMPEGParse * mpeg_parse, GstBuffer * buffer)
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));
}
@ -839,11 +842,14 @@ gst_mpeg_demux_parse_pes (GstMPEGParse * mpeg_parse, GstBuffer * buffer)
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;
}

View file

@ -238,6 +238,7 @@ gst_mpeg_parse_init (GstMPEGParse * mpeg_parse)
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);
}
@ -283,9 +284,10 @@ gst_mpeg_parse_handle_discont (GstMPEGParse * mpeg_parse, GstEvent * event)
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);
@ -452,10 +454,11 @@ gst_mpeg_parse_parse_packhead (GstMPEGParse * mpeg_parse, GstBuffer * buffer)
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;
}

View file

@ -65,8 +65,12 @@ struct _GstMPEGParse {
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;