static const GstQueryType *gst_ogg_pad_query_types (GstPad * pad);
static gboolean gst_ogg_pad_src_query (GstPad * pad, GstQuery * query);
static gboolean gst_ogg_pad_event (GstPad * pad, GstEvent * event);
-static GstCaps *gst_ogg_pad_getcaps (GstPad * pad);
static GstOggPad *gst_ogg_chain_get_stream (GstOggChain * chain,
guint32 serialno);
{
gst_pad_set_event_function (GST_PAD (pad),
GST_DEBUG_FUNCPTR (gst_ogg_pad_event));
- gst_pad_set_getcaps_function (GST_PAD (pad),
- GST_DEBUG_FUNCPTR (gst_ogg_pad_getcaps));
gst_pad_set_query_type_function (GST_PAD (pad),
GST_DEBUG_FUNCPTR (gst_ogg_pad_query_types));
gst_pad_set_query_function (GST_PAD (pad),
GST_DEBUG_FUNCPTR (gst_ogg_pad_src_query));
+ gst_pad_use_fixed_caps (GST_PAD (pad));
pad->mode = GST_OGG_PAD_MODE_INIT;
pad->start_time = GST_CLOCK_TIME_NONE;
- pad->last_stop = GST_CLOCK_TIME_NONE;
+ pad->position = GST_CLOCK_TIME_NONE;
pad->have_type = FALSE;
pad->continued = NULL;
return query_types;
}
-static GstCaps *
-gst_ogg_pad_getcaps (GstPad * pad)
-{
- return gst_caps_ref (GST_PAD_CAPS (pad));
-}
-
static gboolean
gst_ogg_pad_src_query (GstPad * pad, GstQuery * query)
{
pad->continued = NULL;
pad->last_ret = GST_FLOW_OK;
- pad->last_stop = GST_CLOCK_TIME_NONE;
+ pad->position = GST_CLOCK_TIME_NONE;
pad->current_granule = -1;
pad->keyframe_granule = -1;
pad->is_eos = FALSE;
goto not_added;
buf = gst_buffer_new_and_alloc (packet->bytes - offset - trim);
- gst_buffer_set_caps (buf, GST_PAD_CAPS (pad));
/* set delta flag for OGM content */
if (delta_unit)
GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DELTA_UNIT);
/* copy packet in buffer */
- memcpy (buf->data, packet->packet + offset, packet->bytes - offset - trim);
+ gst_buffer_fill (buf, 0, packet->packet + offset,
+ packet->bytes - offset - trim);
GST_BUFFER_TIMESTAMP (buf) = out_timestamp;
GST_BUFFER_DURATION (buf) = out_duration;
pad->discont = FALSE;
}
- pad->last_stop = ogg->segment.last_stop;
+ pad->position = ogg->segment.position;
/* don't push the header packets when we are asked to skip them */
if (!packet->b_o_s || push_headers) {
/* check if valid granulepos, then we can calculate the current
* position. We know the granule for each packet but we only want to update
- * the last_stop when we have a valid granulepos on the packet because else
+ * the position when we have a valid granulepos on the packet because else
* our time jumps around for the different streams. */
if (packet->granulepos < 0)
goto done;
}
/* and store as the current position */
- gst_segment_set_last_stop (&ogg->segment, GST_FORMAT_TIME, current_time);
+ ogg->segment.position = current_time;
GST_DEBUG_OBJECT (ogg, "ogg current time %" GST_TIME_FORMAT,
GST_TIME_ARGS (current_time));
if (start_time != G_MAXUINT64) {
gint64 segment_time;
+ GstSegment segment;
GST_DEBUG_OBJECT (ogg, "start_time: %" GST_TIME_FORMAT,
GST_TIME_ARGS (start_time));
segment_time = chain->begin_time;
/* create the newsegment event we are going to send out */
+ gst_segment_init (&segment, GST_FORMAT_TIME);
+
GST_PUSH_LOCK (ogg);
if (!ogg->pullmode && ogg->push_state == PUSH_LINEAR2) {
/* if we are fast forwarding to the actual seek target,
", start_time %" GST_TIME_FORMAT,
GST_TIME_ARGS (ogg->push_seek_time_original_target),
GST_TIME_ARGS (start_time));
- event =
- gst_event_new_new_segment (FALSE, ogg->push_seek_rate,
- GST_FORMAT_TIME, ogg->push_seek_time_original_target, -1,
- ogg->push_seek_time_original_target);
+ segment.rate = ogg->push_seek_rate;
+ segment.start = ogg->push_seek_time_original_target;
+ segment.stop = -1;
+ segment.time = ogg->push_seek_time_original_target;
+ event = gst_event_new_segment (&segment);
ogg->push_state = PUSH_PLAYING;
} else {
- event = gst_event_new_new_segment (FALSE, ogg->segment.rate,
- GST_FORMAT_TIME, start_time, chain->segment_stop, segment_time);
+ segment.rate = ogg->segment.rate;
+ segment.applied_rate = ogg->segment.applied_rate;
+ segment.start = start_time;
+ segment.stop = chain->segment_stop;
+ segment.time = segment_time;
+ event = gst_event_new_segment (&segment);
}
GST_PUSH_UNLOCK (ogg);
/* see if we have enough info to activate the chain, we have enough info
* when all streams have a valid start time. */
if (gst_ogg_demux_collect_chain_info (ogg, chain)) {
+ GstSegment segment;
GST_DEBUG_OBJECT (ogg, "segment_start: %" GST_TIME_FORMAT,
GST_TIME_ARGS (chain->segment_start));
GST_TIME_ARGS (chain->begin_time));
/* create the newsegment event we are going to send out */
- event = gst_event_new_new_segment (FALSE, ogg->segment.rate,
- GST_FORMAT_TIME, chain->segment_start, chain->segment_stop,
- chain->begin_time);
+ gst_segment_init (&segment, GST_FORMAT_TIME);
+ segment.rate = ogg->segment.rate;
+ segment.applied_rate = ogg->segment.applied_rate;
+ segment.start = chain->segment_start;
+ segment.stop = chain->segment_stop;
+ segment.time = chain->begin_time;
+ event = gst_event_new_segment (&segment);
}
}
ret = g_object_new (GST_TYPE_OGG_PAD, NULL);
/* we own this one */
- gst_object_ref (ret);
- gst_object_sink (ret);
+ gst_object_ref_sink (ret);
GST_PAD_DIRECTION (ret) = GST_PAD_SRC;
gst_ogg_pad_mark_discont (ret);
"created new ogg src %p for stream with serial %08x", ret, serialno);
g_array_append_val (chain->streams, ret);
+ gst_pad_set_active (GST_PAD_CAST (ret), TRUE);
return ret;
static void gst_ogg_print (GstOggDemux * demux);
-GST_BOILERPLATE (GstOggDemux, gst_ogg_demux, GstElement, GST_TYPE_ELEMENT);
+#define gst_ogg_demux_parent_class parent_class
+G_DEFINE_TYPE (GstOggDemux, gst_ogg_demux, GST_TYPE_ELEMENT);
static void
-gst_ogg_demux_base_init (gpointer g_class)
+gst_ogg_demux_class_init (GstOggDemuxClass * klass)
{
- GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
+ GstElementClass *gstelement_class = GST_ELEMENT_CLASS (klass);
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
- gst_element_class_set_details_simple (element_class,
+ gst_element_class_set_details_simple (gstelement_class,
"Ogg demuxer", "Codec/Demuxer",
"demux ogg streams (info about ogg: http://xiph.org)",
"Wim Taymans <wim@fluendo.com>");
- gst_element_class_add_pad_template (element_class,
+ gst_element_class_add_pad_template (gstelement_class,
gst_static_pad_template_get (&ogg_demux_sink_template_factory));
- gst_element_class_add_pad_template (element_class,
+ gst_element_class_add_pad_template (gstelement_class,
gst_static_pad_template_get (&ogg_demux_src_template_factory));
-}
-
-static void
-gst_ogg_demux_class_init (GstOggDemuxClass * klass)
-{
- GstElementClass *gstelement_class = GST_ELEMENT_CLASS (klass);
- GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
gstelement_class->change_state = gst_ogg_demux_change_state;
gstelement_class->send_event = gst_ogg_demux_receive_event;
}
static void
-gst_ogg_demux_init (GstOggDemux * ogg, GstOggDemuxClass * g_class)
+gst_ogg_demux_init (GstOggDemux * ogg)
{
/* create the sink pad */
ogg->sinkpad =
gst_ogg_demux_reset_streams (ogg);
}
break;
- case GST_EVENT_NEWSEGMENT:
+ case GST_EVENT_SEGMENT:
GST_DEBUG_OBJECT (ogg, "got a new segment event");
{
- gboolean update;
- GstFormat format;
- gdouble rate, arate;
- gint64 start, stop, time;
-
- gst_event_parse_new_segment_full (event, &update, &rate, &arate,
- &format, &start, &stop, &time);
- if (format == GST_FORMAT_BYTES) {
+ GstSegment segment;
+
+ gst_event_copy_segment (event, &segment);
+
+ if (segment.format == GST_FORMAT_BYTES) {
GST_PUSH_LOCK (ogg);
- ogg->push_byte_offset = start;
- ogg->push_last_seek_offset = start;
+ ogg->push_byte_offset = segment.start;
+ ogg->push_last_seek_offset = segment.start;
GST_PUSH_UNLOCK (ogg);
} else {
GST_WARNING_OBJECT (ogg, "unexpected segment format: %s",
- gst_format_get_name (format));
+ gst_format_get_name (segment.format));
}
}
gst_event_unref (event);
static GstFlowReturn
gst_ogg_demux_submit_buffer (GstOggDemux * ogg, GstBuffer * buffer)
{
- gint size;
- guint8 *data;
+ gsize size;
gchar *oggbuffer;
GstFlowReturn ret = GST_FLOW_OK;
- size = GST_BUFFER_SIZE (buffer);
- data = GST_BUFFER_DATA (buffer);
-
- GST_DEBUG_OBJECT (ogg, "submitting %u bytes", size);
+ size = gst_buffer_get_size (buffer);
+ GST_DEBUG_OBJECT (ogg, "submitting %" G_GSIZE_FORMAT " bytes", size);
if (G_UNLIKELY (size == 0))
goto done;
if (G_UNLIKELY (oggbuffer == NULL))
goto no_buffer;
- memcpy (oggbuffer, data, size);
+ gst_buffer_extract (buffer, 0, oggbuffer, size);
+
if (G_UNLIKELY (ogg_sync_wrote (&ogg->sync, size) < 0))
goto write_failed;
}
write_failed:
{
- GST_ELEMENT_ERROR (ogg, STREAM, DECODE,
- (NULL), ("failed to write %d bytes to the sync buffer", size));
+ GST_ELEMENT_ERROR (ogg, STREAM, DECODE, (NULL),
+ ("failed to write %" G_GSIZE_FORMAT " bytes to the sync buffer", size));
ret = GST_FLOW_ERROR;
goto done;
}
if (ret != GST_FLOW_OK)
goto error;
- ogg->read_offset += GST_BUFFER_SIZE (buffer);
+ ogg->read_offset += gst_buffer_get_size (buffer);
ret = gst_ogg_demux_submit_buffer (ogg, buffer);
ogg_packet *op = headers->data;
g_assert (op);
buffer = gst_buffer_new_and_alloc (op->bytes);
- memcpy (GST_BUFFER_DATA (buffer), op->packet, op->bytes);
+ gst_buffer_fill (buffer, 0, op->packet, op->bytes);
GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_IN_CAPS);
g_value_init (&value, GST_TYPE_BUFFER);
gst_value_take_buffer (&value, buffer);
gst_ogg_pad_mark_discont (pad);
pad->last_ret = GST_FLOW_OK;
- if (pad->map.is_skeleton || pad->added || GST_PAD_CAPS (pad) == NULL)
+ if (pad->map.is_skeleton || pad->added
+ || !gst_pad_has_current_caps (GST_PAD_CAST (pad)))
continue;
GST_DEBUG_OBJECT (ogg, "adding pad %" GST_PTR_FORMAT, pad);
gint i, pending, len;
gboolean first_parsed_page = TRUE;
- position = segment->last_stop;
+ position = segment->position;
/* first find the chain to search in */
total = ogg->total_time;
if (keyframe) {
if (segment->rate > 0.0)
segment->time = keytarget;
- segment->last_stop = keytarget - begintime;
+ segment->position = keytarget - begintime;
}
*rchain = chain;
* forever. */
GST_PAD_STREAM_LOCK (ogg->sinkpad);
- if (ogg->segment_running && !flush) {
- /* create the segment event to close the current segment */
- if ((chain = ogg->current_chain)) {
- GstEvent *newseg;
- gint64 chain_start = 0;
-
- if (chain->segment_start != GST_CLOCK_TIME_NONE)
- chain_start = chain->segment_start;
-
- newseg = gst_event_new_new_segment (TRUE, ogg->segment.rate,
- GST_FORMAT_TIME, ogg->segment.start + chain_start,
- ogg->segment.last_stop + chain_start, ogg->segment.time);
- /* set the seqnum of the running segment */
- gst_event_set_seqnum (newseg, ogg->seqnum);
-
- /* send segment on old chain, FIXME, must be sent from streaming thread. */
- gst_ogg_demux_send_event (ogg, newseg);
- }
- }
-
if (event) {
- gst_segment_set_seek (&ogg->segment, rate, format, flags,
+ gst_segment_do_seek (&ogg->segment, rate, format, flags,
cur_type, cur, stop_type, stop, &update);
}
/* we need to stop flushing on the srcpad as we're going to use it
* next. We can do this as we have the STREAM lock now. */
if (flush) {
- tevent = gst_event_new_flush_stop ();
+ tevent = gst_event_new_flush_stop (TRUE);
gst_event_set_seqnum (tevent, seqnum);
gst_pad_push_event (ogg->sinkpad, tevent);
}
GstEvent *event;
gint64 stop;
gint64 start;
- gint64 last_stop, begin_time;
+ gint64 position, begin_time;
+ GstSegment segment;
/* we have to send the flush to the old chain, not the new one */
if (flush) {
- tevent = gst_event_new_flush_stop ();
+ tevent = gst_event_new_flush_stop (TRUE);
gst_event_set_seqnum (tevent, seqnum);
gst_ogg_demux_send_event (ogg, tevent);
}
stop = MIN (stop, chain->segment_stop);
}
- last_stop = ogg->segment.last_stop;
+ position = ogg->segment.position;
if (chain->segment_start != GST_CLOCK_TIME_NONE)
- last_stop += chain->segment_start;
+ position += chain->segment_start;
- /* create the segment event we are going to send out */
- if (ogg->segment.rate >= 0.0)
- event = gst_event_new_new_segment (FALSE, ogg->segment.rate,
- ogg->segment.format, last_stop, stop, ogg->segment.time);
- else
- event = gst_event_new_new_segment (FALSE, ogg->segment.rate,
- ogg->segment.format, start, last_stop, ogg->segment.time);
+ gst_segment_copy_into (&ogg->segment, &segment);
+ /* create the segment event we are going to send out */
+ if (ogg->segment.rate >= 0.0) {
+ segment.start = position;
+ segment.stop = stop;
+ } else {
+ segment.start = start;
+ segment.stop = position;
+ }
+ event = gst_event_new_segment (&segment);
gst_event_set_seqnum (event, seqnum);
if (chain != ogg->current_chain) {
GstMessage *message;
message = gst_message_new_segment_start (GST_OBJECT (ogg),
- GST_FORMAT_TIME, ogg->segment.last_stop);
+ GST_FORMAT_TIME, ogg->segment.position);
gst_message_set_seqnum (message, seqnum);
gst_element_post_message (GST_ELEMENT (ogg), message);
}
- ogg->segment_running = TRUE;
ogg->seqnum = seqnum;
/* restart our task since it might have been stopped when we did the
* flush. */
GST_DEBUG_OBJECT (ogg, "Trying to find byte/time length");
if ((peer = gst_pad_get_peer (ogg->sinkpad)) != NULL) {
- GstFormat format = GST_FORMAT_BYTES;
gint64 length;
int res;
- res = gst_pad_query_duration (peer, &format, &length);
+ res = gst_pad_query_duration (peer, GST_FORMAT_BYTES, &length);
if (res && length > 0) {
ogg->push_byte_length = length;
GST_DEBUG_OBJECT (ogg,
"File byte length %" G_GINT64_FORMAT, ogg->push_byte_length);
}
- format = GST_FORMAT_TIME;
- res = gst_pad_query_duration (peer, &format, &length);
+ res = gst_pad_query_duration (peer, GST_FORMAT_TIME, &length);
gst_object_unref (peer);
if (res && length >= 0) {
ogg->push_time_length = length;
ogg->total_time += chain->total_time;
}
- gst_segment_set_duration (&ogg->segment, GST_FORMAT_TIME, ogg->total_time);
+ ogg->segment.duration = ogg->total_time;
}
/* find all the chains in the ogg file, this reads the first and
{
ogg_page og;
GstPad *peer;
- GstFormat format;
gboolean res;
guint32 serialno;
GstOggChain *chain;
goto no_peer;
/* find length to read last page, we store this for later use. */
- format = GST_FORMAT_BYTES;
- res = gst_pad_query_duration (peer, &format, &ogg->length);
+ res = gst_pad_query_duration (peer, GST_FORMAT_BYTES, &ogg->length);
gst_object_unref (peer);
if (!res || ogg->length <= 0)
goto no_length;
if (chain) {
GstEvent *event;
gint64 start = 0;
+ GstSegment segment;
if (chain->segment_start != GST_CLOCK_TIME_NONE)
start = chain->segment_start;
/* create the newsegment event we are going to send out */
- event = gst_event_new_new_segment (FALSE, ogg->segment.rate,
- GST_FORMAT_TIME, start, chain->segment_stop, chain->begin_time);
+ gst_segment_copy_into (&ogg->segment, &segment);
+ segment.start = start;
+ segment.stop = chain->segment_stop;
+ segment.time = chain->begin_time;
+ event = gst_event_new_segment (&segment);
gst_event_set_seqnum (event, ogg->seqnum);
GST_DEBUG_OBJECT (ogg,
if (ogg->pullmode)
goto unknown_chain;
- current_time = ogg->segment.last_stop;
+ current_time = ogg->segment.position;
/* time of new chain is current time */
chain_time = current_time;
goto done;
}
- ogg->offset += GST_BUFFER_SIZE (buffer);
+ ogg->offset += gst_buffer_get_size (buffer);
if (G_UNLIKELY (ogg->newsegment)) {
gst_ogg_demux_send_event (ogg, ogg->newsegment);
guint i;
chain = ogg->current_chain;
- cur = ogg->segment.last_stop;
+ cur = ogg->segment.position;
if (chain == NULL || cur == -1)
return;
/* Theoretically, we should be doing this for all streams, but we're only
* doing it for known-to-be-sparse streams at the moment in order not to
* break things for wrongly-muxed streams (like we used to produce once) */
- if (stream->map.is_sparse && stream->last_stop != GST_CLOCK_TIME_NONE) {
+ if (stream->map.is_sparse && stream->position != GST_CLOCK_TIME_NONE) {
/* Does this stream lag? Random threshold of 2 seconds */
- if (GST_CLOCK_DIFF (stream->last_stop, cur) > (2 * GST_SECOND)) {
+ if (GST_CLOCK_DIFF (stream->position, cur) > (2 * GST_SECOND)) {
GST_DEBUG_OBJECT (stream, "synchronizing stream with others by "
"advancing time from %" GST_TIME_FORMAT " to %" GST_TIME_FORMAT,
- GST_TIME_ARGS (stream->last_stop), GST_TIME_ARGS (cur));
- stream->last_stop = cur;
+ GST_TIME_ARGS (stream->position), GST_TIME_ARGS (cur));
+
+ stream->position = cur;
+
+#if 0
+ ogg->segment.base += cur - stream->position;
/* advance stream time (FIXME: is this right, esp. time_pos?) */
gst_pad_push_event (GST_PAD_CAST (stream),
gst_event_new_new_segment (TRUE, ogg->segment.rate,
- GST_FORMAT_TIME, stream->last_stop, -1, stream->last_stop));
+ ogg->segment.applied_rate,
+ GST_FORMAT_TIME, stream->position, -1, stream->position));
+#endif
}
}
}
GstEvent *event = NULL;
GST_LOG_OBJECT (ogg, "pausing task, reason %s", reason);
- ogg->segment_running = FALSE;
gst_pad_pause_task (ogg->sinkpad);
if (ret == GST_FLOW_UNEXPECTED) {
static gboolean
gst_ogg_demux_sink_activate (GstPad * sinkpad)
{
- if (gst_pad_check_pull_range (sinkpad)) {
- GST_DEBUG_OBJECT (sinkpad, "activating pull");
- return gst_pad_activate_pull (sinkpad, TRUE);
- } else {
+ GstQuery *query;
+ gboolean pull_mode;
+
+ query = gst_query_new_scheduling ();
+
+ if (!gst_pad_peer_query (sinkpad, query)) {
+ gst_query_unref (query);
+ goto activate_push;
+ }
+
+ gst_query_parse_scheduling (query, &pull_mode, NULL, NULL, NULL, NULL, NULL);
+
+ if (!pull_mode)
+ goto activate_push;
+
+ GST_DEBUG_OBJECT (sinkpad, "activating pull");
+ return gst_pad_activate_pull (sinkpad, TRUE);
+
+activate_push:
+ {
GST_DEBUG_OBJECT (sinkpad, "activating push");
return gst_pad_activate_push (sinkpad, TRUE);
}
ogg_sync_reset (&ogg->sync);
ogg->running = FALSE;
ogg->bitrate = 0;
- ogg->segment_running = FALSE;
ogg->total_time = -1;
GST_PUSH_LOCK (ogg);
ogg->push_byte_offset = 0;
break;
}
- result = parent_class->change_state (element, transition);
+ result = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
switch (transition) {
case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
gst_ogg_demux_clear_chains (ogg);
GST_OBJECT_LOCK (ogg);
ogg->running = FALSE;
- ogg->segment_running = FALSE;
GST_OBJECT_UNLOCK (ogg);
break;
case GST_STATE_CHANGE_READY_TO_NULL: