Commit 82dc411e authored by Wim Taymans's avatar Wim Taymans
Browse files

Updated seek example.

Original commit message from CVS:
* docs/libs/tmpl/gstringbuffer.sgml:
* examples/seeking/seek.c: (make_vorbis_theora_pipeline),
(query_rates), (query_positions_elems), (query_positions_pads),
(update_scale), (do_seek):
Updated seek example.

* ext/ogg/gstoggdemux.c: (gst_ogg_pad_submit_packet),
(gst_ogg_pad_submit_page), (gst_ogg_demux_activate_chain),
(gst_ogg_demux_find_chains), (gst_ogg_demux_send_event),
(gst_ogg_demux_loop):
Push out correct discont values.

* ext/theora/theoradec.c: (theora_dec_src_convert),
(theora_dec_sink_convert), (theora_dec_src_getcaps),
(theora_dec_sink_event), (theora_handle_type_packet),
(theora_handle_header_packet), (theora_dec_push),
(theora_handle_data_packet), (theora_dec_chain),
(theora_dec_change_state):
Better timestamping.

* ext/vorbis/vorbisdec.c: (gst_vorbis_dec_init),
(vorbis_dec_sink_event), (vorbis_dec_push),
(vorbis_handle_data_packet), (vorbis_dec_chain):
* ext/vorbis/vorbisdec.h:
Better timestamping.

* gst-libs/gst/audio/gstbaseaudiosink.c:
(gst_base_audio_sink_get_time), (gst_base_audio_sink_get_times),
(gst_base_audio_sink_event), (gst_base_audio_sink_render):
Handle syncing on timestamps instead of sample offsets. Make
use of DISCONT values as described in design docs.

* gst-libs/gst/audio/gstbaseaudiosrc.c:
(gst_base_audio_src_get_time):
* gst-libs/gst/audio/gstringbuffer.c: (gst_ring_buffer_acquire),
(gst_ring_buffer_set_sample), (gst_ring_buffer_commit),
(gst_ring_buffer_read):
* gst-libs/gst/audio/gstringbuffer.h:
* sys/ximage/ximagesink.c: (gst_ximagesink_get_times),
(gst_ximagesink_show_frame):
* sys/xvimage/xvimagesink.c: (gst_xvimagesink_get_times):
Correcly convert buffer timestamp to stream time.
parent 567802ca
2005-07-16 Wim Taymans <wim@fluendo.com>
* docs/libs/tmpl/gstringbuffer.sgml:
* examples/seeking/seek.c: (make_vorbis_theora_pipeline),
(query_rates), (query_positions_elems), (query_positions_pads),
(update_scale), (do_seek):
Updated seek example.
* ext/ogg/gstoggdemux.c: (gst_ogg_pad_submit_packet),
(gst_ogg_pad_submit_page), (gst_ogg_demux_activate_chain),
(gst_ogg_demux_find_chains), (gst_ogg_demux_send_event),
(gst_ogg_demux_loop):
Push out correct discont values.
* ext/theora/theoradec.c: (theora_dec_src_convert),
(theora_dec_sink_convert), (theora_dec_src_getcaps),
(theora_dec_sink_event), (theora_handle_type_packet),
(theora_handle_header_packet), (theora_dec_push),
(theora_handle_data_packet), (theora_dec_chain),
(theora_dec_change_state):
Better timestamping.
* ext/vorbis/vorbisdec.c: (gst_vorbis_dec_init),
(vorbis_dec_sink_event), (vorbis_dec_push),
(vorbis_handle_data_packet), (vorbis_dec_chain):
* ext/vorbis/vorbisdec.h:
Better timestamping.
* gst-libs/gst/audio/gstbaseaudiosink.c:
(gst_base_audio_sink_get_time), (gst_base_audio_sink_get_times),
(gst_base_audio_sink_event), (gst_base_audio_sink_render):
Handle syncing on timestamps instead of sample offsets. Make
use of DISCONT values as described in design docs.
* gst-libs/gst/audio/gstbaseaudiosrc.c:
(gst_base_audio_src_get_time):
* gst-libs/gst/audio/gstringbuffer.c: (gst_ring_buffer_acquire),
(gst_ring_buffer_set_sample), (gst_ring_buffer_commit),
(gst_ring_buffer_read):
* gst-libs/gst/audio/gstringbuffer.h:
* sys/ximage/ximagesink.c: (gst_ximagesink_get_times),
(gst_ximagesink_show_frame):
* sys/xvimage/xvimagesink.c: (gst_xvimagesink_get_times):
Correcly convert buffer timestamp to stream time.
2005-07-16 Wim Taymans <wim@fluendo.com>
* gst/audioconvert/gstaudioconvert.c:
......
......@@ -28,6 +28,7 @@ an implementation of an audio ringbuffer
@empty_seg:
@state:
@segdone:
@segbase:
@waiting:
<!-- ##### STRUCT GstRingBufferClass ##### -->
......
......@@ -21,7 +21,7 @@ static guint update_id;
static guint seek_timeout_id = 0;
static gulong changed_id;
//#define SOURCE "gnomevfssrc"
//#define SOURCE "filesrc"
#define SOURCE "gnomevfssrc"
#define ASINK "alsasink"
//#define ASINK "osssink"
......@@ -33,8 +33,8 @@ static gulong changed_id;
#define UPDATE_INTERVAL 500
/* number of milliseconds to play for after a seek */
#define SCRUB_TIME 250
#define SCRUB
//#define SCRUB_TIME 250
//#define SCRUB
#define THREAD
#define PAD_SEEK
......@@ -376,6 +376,7 @@ make_vorbis_theora_pipeline (const gchar * location)
GstElement *audiosink, *videosink;
GstElement *a_queue, *v_queue;
GstPad *seekable;
GstPad *pad;
pipeline = gst_pipeline_new ("app");
......@@ -405,8 +406,9 @@ make_vorbis_theora_pipeline (const gchar * location)
gst_element_link (a_decoder, a_convert);
gst_element_link (a_convert, audiosink);
gst_element_add_ghost_pad (audio_bin, gst_element_get_pad (a_queue, "sink"),
"sink");
pad = gst_element_get_pad (a_queue, "sink");
gst_element_add_pad (audio_bin, gst_ghost_pad_new ("sink", pad));
gst_object_unref (GST_OBJECT_CAST (pad));
setup_dynamic_link (demux, NULL, gst_element_get_pad (audio_bin, "sink"),
NULL);
......@@ -427,8 +429,9 @@ make_vorbis_theora_pipeline (const gchar * location)
gst_element_link_many (v_queue, v_decoder, v_convert, videosink, NULL);
gst_element_add_ghost_pad (video_bin, gst_element_get_pad (v_queue, "sink"),
"sink");
pad = gst_element_get_pad (v_queue, "sink");
gst_element_add_pad (video_bin, gst_ghost_pad_new ("sink", pad));
gst_object_unref (GST_OBJECT_CAST (pad));
setup_dynamic_link (demux, NULL, gst_element_get_pad (video_bin, "sink"),
NULL);
......@@ -933,6 +936,8 @@ update_scale (gpointer data)
gtk_widget_queue_draw (hscale);
}
gst_object_unref (clock);
return TRUE;
}
......@@ -992,7 +997,7 @@ do_seek (GtkWidget * widget)
}
if (res)
GST_PIPELINE (pipeline)->stream_time = real;
gst_pipeline_set_new_stream_time (GST_PIPELINE (pipeline), 0);
else
g_print ("seek failed\n");
}
......
......@@ -898,6 +898,7 @@ static gboolean gst_ogg_demux_sink_activate_pull (GstPad * sinkpad,
static gboolean gst_ogg_demux_sink_activate_push (GstPad * sinkpad,
gboolean active);
static GstElementStateReturn gst_ogg_demux_change_state (GstElement * element);
static void gst_ogg_demux_send_event (GstOggDemux * ogg, GstEvent * event);
static void gst_ogg_print (GstOggDemux * demux);
......@@ -1173,6 +1174,7 @@ gst_ogg_demux_activate_chain (GstOggDemux * ogg, GstOggChain * chain)
gint i;
GList *headers;
GstOggPad *pad;
GstEvent *event;
if (chain == ogg->current_chain)
return TRUE;
......@@ -1188,6 +1190,13 @@ gst_ogg_demux_activate_chain (GstOggDemux * ogg, GstOggChain * chain)
gst_element_no_more_pads (GST_ELEMENT (ogg));
ogg->current_chain = chain;
/* send the base time */
event = gst_event_new_discontinuous (1.0,
GST_FORMAT_TIME, (gint64) chain->start_time, (gint64) chain->total_time,
NULL);
gst_ogg_demux_send_event (ogg, event);
/* then send out the buffers */
for (i = 0; i < chain->streams->len; i++) {
pad = g_array_index (chain->streams, GstOggPad *, i);
......@@ -1775,7 +1784,7 @@ gst_ogg_demux_find_chains (GstOggDemux * ogg)
GstOggChain *chain = g_array_index (ogg->chains, GstOggChain *, i);
chain->total_time = 0;
chain->start_time = 0;
chain->start_time = G_MAXINT64;
chain->last_time = 0;
chain->begin_time = ogg->total_time;
......@@ -1904,7 +1913,7 @@ gst_ogg_demux_chain (GstPad * pad, GstBuffer * buffer)
}
static void
gst_ogg_demux_send_eos (GstOggDemux * ogg)
gst_ogg_demux_send_event (GstOggDemux * ogg, GstEvent * event)
{
GstOggChain *chain = ogg->current_chain;
......@@ -1914,9 +1923,11 @@ gst_ogg_demux_send_eos (GstOggDemux * ogg)
for (i = 0; i < chain->streams->len; i++) {
GstOggPad *pad = g_array_index (chain->streams, GstOggPad *, i);
gst_pad_push_event (GST_PAD (pad), gst_event_new (GST_EVENT_EOS));
gst_event_ref (event);
gst_pad_push_event (GST_PAD (pad), event);
}
}
gst_event_unref (event);
}
/* random access code
......@@ -1946,6 +1957,7 @@ gst_ogg_demux_loop (GstOggPad * pad)
GST_CHAIN_UNLOCK (ogg);
if (!got_chains)
goto chain_read_failed;
ogg->need_chains = FALSE;
ogg->offset = 0;
}
......@@ -1953,7 +1965,7 @@ gst_ogg_demux_loop (GstOggPad * pad)
GST_LOG_OBJECT (ogg, "pull data %lld", ogg->offset);
if (ogg->offset == ogg->length) {
ret = GST_FLOW_OK;
gst_ogg_demux_send_eos (ogg);
gst_ogg_demux_send_event (ogg, gst_event_new (GST_EVENT_EOS));
goto pause;
}
......@@ -1982,7 +1994,7 @@ pause:
GST_LOG_OBJECT (ogg, "pausing task, reason %d", ret);
gst_pad_pause_task (ogg->sinkpad);
if (GST_FLOW_IS_FATAL (ret)) {
gst_ogg_demux_send_eos (ogg);
gst_ogg_demux_send_event (ogg, gst_event_new (GST_EVENT_EOS));
GST_ELEMENT_ERROR (ogg, STREAM, STOPPED,
("stream stopped, reason %d", ret),
("stream stopped, reason %d", ret));
......
......@@ -54,10 +54,11 @@ struct _GstTheoraDec
theora_info info;
theora_comment comment;
guint packetno;
gboolean have_header;
guint64 granulepos;
gboolean initialized;
GstClockTime last_timestamp;
guint64 frame_nr;
gboolean need_keyframe;
gint width, height;
gint offset_x, offset_y;
......@@ -281,7 +282,7 @@ theora_dec_src_convert (GstPad * pad,
dec = GST_THEORA_DEC (GST_PAD_PARENT (pad));
/* we need the info part before we can done something */
if (dec->packetno < 1)
if (!dec->have_header)
return FALSE;
if (src_format == *dest_format) {
......@@ -347,7 +348,7 @@ theora_dec_sink_convert (GstPad * pad,
dec = GST_THEORA_DEC (GST_PAD_PARENT (pad));
/* we need the info part before we can done something */
if (dec->packetno < 1)
if (!dec->have_header)
return FALSE;
if (src_format == *dest_format) {
......@@ -581,69 +582,32 @@ theora_dec_src_getcaps (GstPad * pad)
static gboolean
theora_dec_sink_event (GstPad * pad, GstEvent * event)
{
gint64 start_value, end_value, time, bytes;
gboolean ret = TRUE;
GstTheoraDec *dec;
dec = GST_THEORA_DEC (GST_PAD_PARENT (pad));
dec = GST_THEORA_DEC (gst_pad_get_parent (pad));
GST_LOG_OBJECT (dec, "handling event");
switch (GST_EVENT_TYPE (event)) {
case GST_EVENT_EOS:
GST_STREAM_LOCK (pad);
ret = gst_pad_push_event (dec->srcpad, event);
GST_STREAM_UNLOCK (pad);
break;
case GST_EVENT_DISCONTINUOUS:
GST_STREAM_LOCK (pad);
if (gst_event_discont_get_value (event, GST_FORMAT_DEFAULT,
&start_value, &end_value)) {
dec->granulepos = start_value;
GST_DEBUG_OBJECT (dec,
"setting granuleposition to %" G_GUINT64_FORMAT " after discont",
start_value);
} else {
GST_WARNING_OBJECT (dec,
"discont event didn't include offset, we might set it wrong now");
dec->granulepos = -1;
}
if (dec->packetno < 3) {
if (dec->granulepos != 0)
GST_ELEMENT_ERROR (dec, STREAM, DECODE, (NULL),
("can't handle discont before parsing first 3 packets"));
dec->packetno = 0;
gst_pad_push_event (dec->srcpad, gst_event_new_discontinuous (FALSE,
GST_FORMAT_TIME, (guint64) 0, GST_FORMAT_DEFAULT,
(guint64) 0, GST_FORMAT_BYTES, (guint64) 0, 0));
} else {
GstFormat time_format, default_format, bytes_format;
time_format = GST_FORMAT_TIME;
default_format = GST_FORMAT_DEFAULT;
bytes_format = GST_FORMAT_BYTES;
/* if one of them works, all of them work */
if (theora_dec_sink_convert (dec->sinkpad, GST_FORMAT_DEFAULT,
dec->granulepos, &time_format, &time)
&& theora_dec_src_convert (dec->srcpad, GST_FORMAT_TIME, time,
&default_format, &start_value)
&& theora_dec_src_convert (dec->srcpad, GST_FORMAT_TIME, time,
&bytes_format, &bytes)) {
gst_pad_push_event (dec->srcpad,
gst_event_new_discontinuous (FALSE, GST_FORMAT_TIME,
time, GST_FORMAT_DEFAULT, start_value, GST_FORMAT_BYTES,
bytes, 0));
/* store new framenumber */
dec->packetno = start_value + 3;
} else {
GST_ERROR_OBJECT (dec,
"failed to parse data for DISCONT event, not sending any");
}
/* sync to keyframe */
dec->need_keyframe = TRUE;
}
dec->need_keyframe = TRUE;
dec->granulepos = -1;
dec->last_timestamp = -1;
ret = gst_pad_push_event (dec->srcpad, event);
GST_STREAM_UNLOCK (pad);
gst_event_unref (event);
break;
default:
ret = gst_pad_event_default (dec->sinkpad, event);
ret = gst_pad_push_event (dec->srcpad, event);
break;
}
gst_object_unref (dec);
return ret;
}
......@@ -750,7 +714,7 @@ theora_handle_type_packet (GstTheoraDec * dec, ogg_packet * packet)
gst_pad_set_caps (dec->srcpad, caps);
gst_caps_unref (caps);
dec->initialized = TRUE;
dec->have_header = TRUE;
return GST_FLOW_OK;
}
......@@ -765,15 +729,18 @@ theora_handle_header_packet (GstTheoraDec * dec, ogg_packet * packet)
if (theora_decode_header (&dec->info, &dec->comment, packet))
goto header_read_error;
switch (packet->packetno) {
case 1:
switch (packet->packet[0]) {
case 0x81:
res = theora_handle_comment_packet (dec, packet);
break;
case 2:
case 0x82:
res = theora_handle_type_packet (dec, packet);
break;
default:
/* ignore */
g_warning ("unknown theora header packet found");
case 0x80:
/* nothing special, this is the identification header */
res = GST_FLOW_OK;
break;
}
......@@ -792,8 +759,39 @@ static GstFlowReturn
theora_dec_push (GstTheoraDec * dec, GstBuffer * buf)
{
GstFlowReturn result;
GstClockTime outtime = GST_BUFFER_TIMESTAMP (buf);
result = gst_pad_push (dec->srcpad, buf);
if (outtime == GST_CLOCK_TIME_NONE) {
dec->queued = g_list_append (dec->queued, buf);
GST_DEBUG_OBJECT (dec, "queued buffer");
result = GST_FLOW_OK;
} else {
if (dec->queued) {
gint64 size;
GList *walk;
GST_DEBUG_OBJECT (dec, "first buffer with time %" GST_TIME_FORMAT,
GST_TIME_ARGS (outtime));
size = g_list_length (dec->queued);
for (walk = dec->queued; walk; walk = g_list_next (walk)) {
GstBuffer *buffer = GST_BUFFER (walk->data);
GstClockTime time;
time = outtime - ((size * GST_SECOND * dec->info.fps_denominator)
/ dec->info.fps_numerator);
GST_DEBUG_OBJECT (dec, "patch buffer %lld %lld", size, time);
GST_BUFFER_TIMESTAMP (buffer) = time;
/* ignore the result */
gst_pad_push (dec->srcpad, buffer);
size--;
}
g_list_free (dec->queued);
dec->queued = NULL;
}
result = gst_pad_push (dec->srcpad, buf);
}
return result;
}
......@@ -813,7 +811,7 @@ theora_handle_data_packet (GstTheoraDec * dec, ogg_packet * packet,
gint cwidth, cheight;
GstFlowReturn result;
if (!dec->initialized)
if (!dec->have_header)
goto not_initialized;
/* the second most significant bit of the first data byte is cleared
......@@ -894,8 +892,9 @@ theora_handle_data_packet (GstTheoraDec * dec, ogg_packet * packet,
}
}
GST_BUFFER_OFFSET (out) = dec->packetno - 4;
GST_BUFFER_OFFSET_END (out) = dec->packetno - 3;
GST_BUFFER_OFFSET (out) = dec->frame_nr;
dec->frame_nr++;
GST_BUFFER_OFFSET_END (out) = dec->frame_nr;
GST_BUFFER_DURATION (out) =
GST_SECOND * ((gdouble) dec->info.fps_denominator) /
dec->info.fps_numerator;
......@@ -909,7 +908,7 @@ theora_handle_data_packet (GstTheoraDec * dec, ogg_packet * packet,
not_initialized:
{
GST_ELEMENT_ERROR (GST_ELEMENT (dec), STREAM, DECODE,
(NULL), ("no header sent yet (packet no is %d)", packet->packetno));
(NULL), ("no header sent yet"));
return GST_FLOW_ERROR;
}
dropping:
......@@ -946,110 +945,50 @@ theora_dec_chain (GstPad * pad, GstBuffer * buf)
{
GstTheoraDec *dec;
ogg_packet packet;
guint64 offset_end;
GstClockTime outtime;
GstFlowReturn result = GST_FLOW_OK;
dec = GST_THEORA_DEC (GST_PAD_PARENT (pad));
if (dec->packetno >= 3) {
/* try timestamp first */
outtime = GST_BUFFER_TIMESTAMP (buf);
if (outtime == -1) {
gboolean need_flush = FALSE;
/* the offset end field in theora is actually the time of
* this frame, not the end time */
offset_end = GST_BUFFER_OFFSET_END (buf);
GST_DEBUG_OBJECT (dec, "got buffer with granule %lld", offset_end);
if (offset_end != -1) {
if (dec->granulepos == -1) {
GST_DEBUG_OBJECT (dec, "first buffer with granule");
need_flush = TRUE;
}
dec->granulepos = offset_end;
}
if (dec->granulepos == -1) {
/* we need to wait for a buffer with at least a timestamp or an
* offset before we can generate valid timestamps */
dec->queued = g_list_append (dec->queued, buf);
GST_DEBUG_OBJECT (dec, "queued buffer");
return GST_FLOW_OK;
} else {
/* granulepos to time */
outtime =
GST_SECOND * theora_granule_time (&dec->state, dec->granulepos);
GST_DEBUG_OBJECT (dec, "granulepos=%lld outtime=%" GST_TIME_FORMAT,
dec->granulepos, GST_TIME_ARGS (outtime));
if (need_flush) {
GList *walk;
GstClockTime patch;
gint64 len;
gint64 old_granule = dec->granulepos;
dec->granulepos = -1;
len = g_list_length (dec->queued);
GST_DEBUG_OBJECT (dec, "first buffer with granule, flushing");
/* now resubmit all queued buffers with corrected timestamps */
for (walk = dec->queued; walk; walk = g_list_next (walk)) {
GstBuffer *qbuffer = GST_BUFFER (walk->data);
patch = outtime - (GST_SECOND * len * dec->info.fps_denominator) /
dec->info.fps_numerator,
GST_DEBUG_OBJECT (dec, "patch buffer %lld %lld", len, patch);
GST_BUFFER_TIMESTAMP (qbuffer) = patch;
/* buffers are unreffed in chain function */
theora_dec_chain (pad, qbuffer);
len--;
}
g_list_free (dec->queued);
dec->queued = NULL;
dec->granulepos = old_granule;
}
}
} else {
GST_DEBUG_OBJECT (dec, "got buffer with timestamp %lld", outtime);
}
} else {
/* we don't know yet */
outtime = -1;
}
dec = GST_THEORA_DEC (gst_pad_get_parent (pad));
/* make ogg_packet out of the buffer */
packet.packet = GST_BUFFER_DATA (buf);
packet.bytes = GST_BUFFER_SIZE (buf);
packet.granulepos = dec->granulepos;
packet.packetno = dec->packetno;
packet.b_o_s = (packet.packetno == 0) ? 1 : 0;
packet.granulepos = GST_BUFFER_OFFSET_END (buf);
packet.packetno = 0; /* we don't really care */
packet.b_o_s = dec->have_header ? 0 : 1;
packet.e_o_s = 0;
if (dec->have_header) {
if (packet.granulepos != -1) {
dec->granulepos = packet.granulepos;
dec->last_timestamp =
GST_SECOND * theora_granule_time (&dec->state, packet.granulepos);
} else if (dec->last_timestamp != -1) {
dec->last_timestamp +=
(GST_SECOND * dec->info.fps_denominator) / dec->info.fps_numerator;
}
} else {
dec->last_timestamp = -1;
}
GST_DEBUG_OBJECT (dec, "header=%d packetno=%lld, outtime=%" GST_TIME_FORMAT,
packet.packet[0], packet.packetno, GST_TIME_ARGS (outtime));
packet.packet[0], packet.packetno, GST_TIME_ARGS (dec->last_timestamp));
/* switch depending on packet type */
if (packet.packet[0] & 0x80) {
if (packet.packetno > 3) {
if (dec->have_header) {
GST_WARNING_OBJECT (GST_OBJECT (dec), "Ignoring header");
goto done;
}
result = theora_handle_header_packet (dec, &packet);
} else {
result = theora_handle_data_packet (dec, &packet, outtime);
result = theora_handle_data_packet (dec, &packet, dec->last_timestamp);
}
done:
dec->packetno++;
_inc_granulepos (dec);
gst_object_unref (dec);
gst_buffer_unref (buf);
return result;
......@@ -1070,8 +1009,9 @@ theora_dec_change_state (GstElement * element)
case GST_STATE_READY_TO_PAUSED:
theora_info_init (&dec->info);
theora_comment_init (&dec->comment);
dec->have_header = FALSE;
dec->need_keyframe = TRUE;
dec->initialized = FALSE;
dec->last_timestamp = -1;
dec->granulepos = -1;
break;
case GST_STATE_PAUSED_TO_PLAYING:
......@@ -1089,7 +1029,7 @@ theora_dec_change_state (GstElement * element)
theora_clear (&dec->state);
theora_comment_clear (&dec->comment);
theora_info_clear (&dec->info);
dec->packetno = 0;
dec->have_header = FALSE;
dec->granulepos = -1;
break;
case GST_STATE_READY_TO_NULL:
......
......@@ -171,6 +171,8 @@ gst_vorbis_dec_init (GstVorbisDec * dec)
gst_pad_set_query_type_function (dec->srcpad, vorbis_get_query_types);
gst_pad_set_query_function (dec->srcpad, vorbis_dec_src_query);
gst_element_add_pad (GST_ELEMENT (dec), dec->srcpad);
dec->queued = NULL;
}
static gboolean
......@@ -366,90 +368,33 @@ vorbis_dec_src_event (GstPad * pad, GstEvent * event)
static gboolean
vorbis_dec_sink_event (GstPad * pad, GstEvent * event)
{
gint64 start_value, end_value, time, bytes;
gboolean ret = TRUE;
GstVorbisDec *dec;
dec = GST_VORBIS_DEC (GST_PAD_PARENT (pad));
dec = GST_VORBIS_DEC (gst_pad_get_parent (pad));
GST_LOG_OBJECT (dec, "handling event");
switch (GST_EVENT_TYPE (event)) {
case GST_EVENT_EOS:
GST_STREAM_LOCK (pad);
ret = gst_pad_push_event (dec->srcpad, event);
GST_STREAM_UNLOCK (pad);
break;
case GST_EVENT_DISCONTINUOUS:
GST_STREAM_LOCK (pad);
if (gst_event_discont_get_value (event, GST_FORMAT_DEFAULT,
(gint64 *) & start_value, &end_value)) {
dec->granulepos = start_value;
GST_DEBUG_OBJECT (dec,
"setting granuleposition to %" G_GUINT64_FORMAT " after discont",
start_value);
} else {
if (gst_event_discont_get_value (event, GST_FORMAT_TIME,
(gint64 *) & start_value, &end_value)) {
dec->granulepos = start_value * dec->vi.rate / GST_SECOND;
GST_DEBUG_OBJECT (dec,
"setting granuleposition to %" G_GUINT64_FORMAT " after discont",
dec->granulepos);
} else {
GST_WARNING_OBJECT (dec,
"discont event didn't include offset, we might set it wrong now");
dec->granulepos = -1;