ext/ogg/gstoggdemux.c: Reorganize code to send the right disconts when in streaming mode.
Original commit message from CVS: * ext/ogg/gstoggdemux.c: (gst_ogg_pad_init), (gst_ogg_pad_event), (gst_ogg_pad_internal_chain), (gst_ogg_pad_typefind), (gst_ogg_demux_chain_elem_pad), (gst_ogg_demux_queue_data), (gst_ogg_demux_chain_peer), (gst_ogg_pad_submit_packet), (gst_ogg_pad_submit_page), (gst_ogg_chain_new), (gst_ogg_demux_init), (gst_ogg_demux_deactivate_current_chain), (gst_ogg_demux_activate_chain), (gst_ogg_demux_perform_seek), (gst_ogg_demux_read_chain), (gst_ogg_demux_find_pad), (gst_ogg_demux_collect_chain_info), (gst_ogg_demux_collect_info), (gst_ogg_demux_find_chains), (gst_ogg_demux_chain), (gst_ogg_demux_send_event), (gst_ogg_demux_loop), (gst_ogg_demux_change_state), (gst_ogg_print): Reorganize code to send the right disconts when in streaming mode.
This commit is contained in:
parent
ce8045a421
commit
f314343058
17
ChangeLog
17
ChangeLog
@ -1,3 +1,20 @@
|
|||||||
|
2005-07-21 Wim Taymans <wim@fluendo.com>
|
||||||
|
|
||||||
|
* ext/ogg/gstoggdemux.c: (gst_ogg_pad_init), (gst_ogg_pad_event),
|
||||||
|
(gst_ogg_pad_internal_chain), (gst_ogg_pad_typefind),
|
||||||
|
(gst_ogg_demux_chain_elem_pad), (gst_ogg_demux_queue_data),
|
||||||
|
(gst_ogg_demux_chain_peer), (gst_ogg_pad_submit_packet),
|
||||||
|
(gst_ogg_pad_submit_page), (gst_ogg_chain_new),
|
||||||
|
(gst_ogg_demux_init), (gst_ogg_demux_deactivate_current_chain),
|
||||||
|
(gst_ogg_demux_activate_chain), (gst_ogg_demux_perform_seek),
|
||||||
|
(gst_ogg_demux_read_chain), (gst_ogg_demux_find_pad),
|
||||||
|
(gst_ogg_demux_collect_chain_info), (gst_ogg_demux_collect_info),
|
||||||
|
(gst_ogg_demux_find_chains), (gst_ogg_demux_chain),
|
||||||
|
(gst_ogg_demux_send_event), (gst_ogg_demux_loop),
|
||||||
|
(gst_ogg_demux_change_state), (gst_ogg_print):
|
||||||
|
Reorganize code to send the right disconts when in streaming
|
||||||
|
mode.
|
||||||
|
|
||||||
2005-07-20 Andy Wingo <wingo@pobox.com>
|
2005-07-20 Andy Wingo <wingo@pobox.com>
|
||||||
|
|
||||||
* gst/videoscale/vs_image.c (vs_image_scale_nearest_YUYV): Typo
|
* gst/videoscale/vs_image.c (vs_image_scale_nearest_YUYV): Typo
|
||||||
|
@ -75,11 +75,11 @@ typedef struct _GstOggChain
|
|||||||
|
|
||||||
GstClockTime total_time; /* the total time of this chain, this is the MAX of
|
GstClockTime total_time; /* the total time of this chain, this is the MAX of
|
||||||
the totals of all streams */
|
the totals of all streams */
|
||||||
GstClockTime start_time; /* the timestamp of the first sample */
|
GstClockTime start_time; /* the timestamp of the first sample, this is the MIN of
|
||||||
GstClockTime last_time; /* the timestamp of the last page == last sample */
|
the start times of all streams. */
|
||||||
|
GstClockTime last_time; /* the timestamp of the last page, this is the MAX of the
|
||||||
|
streams. */
|
||||||
GstClockTime begin_time; /* when this chain starts in the stream */
|
GstClockTime begin_time; /* when this chain starts in the stream */
|
||||||
|
|
||||||
} GstOggChain;
|
} GstOggChain;
|
||||||
|
|
||||||
/* different modes for the pad */
|
/* different modes for the pad */
|
||||||
@ -97,6 +97,7 @@ struct _GstOggPad
|
|||||||
{
|
{
|
||||||
PARENT pad; /* subclass GstPad */
|
PARENT pad; /* subclass GstPad */
|
||||||
|
|
||||||
|
gboolean have_type;
|
||||||
GstOggPadMode mode;
|
GstOggPadMode mode;
|
||||||
|
|
||||||
GstPad *elem_pad; /* sinkpad of internal element */
|
GstPad *elem_pad; /* sinkpad of internal element */
|
||||||
@ -110,11 +111,6 @@ struct _GstOggPad
|
|||||||
|
|
||||||
gint serialno;
|
gint serialno;
|
||||||
gint64 packetno;
|
gint64 packetno;
|
||||||
gint64 offset;
|
|
||||||
|
|
||||||
gint64 start;
|
|
||||||
gint64 stop;
|
|
||||||
|
|
||||||
gint64 current_granule;
|
gint64 current_granule;
|
||||||
|
|
||||||
GstClockTime start_time; /* the timestamp of the first sample */
|
GstClockTime start_time; /* the timestamp of the first sample */
|
||||||
@ -155,18 +151,24 @@ struct _GstOggDemux
|
|||||||
|
|
||||||
OggState state;
|
OggState state;
|
||||||
gboolean seekable;
|
gboolean seekable;
|
||||||
|
gboolean running;
|
||||||
|
|
||||||
gboolean need_chains;
|
gboolean need_chains;
|
||||||
|
|
||||||
/* state */
|
/* state */
|
||||||
GMutex *chain_lock; /* we need the lock to protect the chains */
|
GMutex *chain_lock; /* we need the lock to protect the chains */
|
||||||
GArray *chains; /* list of chains we know */
|
GArray *chains; /* list of chains we know */
|
||||||
|
GstClockTime start_time; /* the start time of the first chain */
|
||||||
GstClockTime total_time; /* the total time of this ogg, this is the sum of
|
GstClockTime total_time; /* the total time of this ogg, this is the sum of
|
||||||
the totals of all chains */
|
the totals of all chains */
|
||||||
GstOggChain *current_chain;
|
GstOggChain *current_chain;
|
||||||
GstOggChain *building_chain;
|
GstOggChain *building_chain;
|
||||||
|
|
||||||
|
/* playback start/stop positions */
|
||||||
|
GstClockTime segment_start;
|
||||||
|
GstClockTime segment_stop;
|
||||||
|
gboolean segment_play;
|
||||||
|
|
||||||
/* ogg stuff */
|
/* ogg stuff */
|
||||||
ogg_sync_state sync;
|
ogg_sync_state sync;
|
||||||
};
|
};
|
||||||
@ -182,7 +184,12 @@ GST_STATIC_PAD_TEMPLATE ("internal",
|
|||||||
GST_PAD_ALWAYS,
|
GST_PAD_ALWAYS,
|
||||||
GST_STATIC_CAPS_ANY);
|
GST_STATIC_CAPS_ANY);
|
||||||
|
|
||||||
static gboolean gst_ogg_demux_perform_seek (GstOggDemux * ogg, gint64 pos);
|
static gboolean gst_ogg_demux_collect_chain_info (GstOggDemux * ogg,
|
||||||
|
GstOggChain * chain);
|
||||||
|
static gboolean gst_ogg_demux_activate_chain (GstOggDemux * ogg,
|
||||||
|
GstOggChain * chain, GstEvent * event);
|
||||||
|
|
||||||
|
static gboolean gst_ogg_demux_perform_seek (GstOggDemux * ogg, gboolean flush);
|
||||||
|
|
||||||
static void gst_ogg_pad_class_init (GstOggPadClass * klass);
|
static void gst_ogg_pad_class_init (GstOggPadClass * klass);
|
||||||
static void gst_ogg_pad_init (GstOggPad * pad);
|
static void gst_ogg_pad_init (GstOggPad * pad);
|
||||||
@ -256,10 +263,12 @@ gst_ogg_pad_init (GstOggPad * pad)
|
|||||||
pad->last_granule = -1;
|
pad->last_granule = -1;
|
||||||
pad->current_granule = -1;
|
pad->current_granule = -1;
|
||||||
|
|
||||||
pad->start_time = -1;
|
pad->start_time = GST_CLOCK_TIME_NONE;
|
||||||
pad->first_time = -1;
|
pad->first_time = GST_CLOCK_TIME_NONE;
|
||||||
pad->last_time = -1;
|
pad->last_time = GST_CLOCK_TIME_NONE;
|
||||||
|
pad->total_time = GST_CLOCK_TIME_NONE;
|
||||||
|
|
||||||
|
pad->have_type = FALSE;
|
||||||
pad->headers = NULL;
|
pad->headers = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -382,23 +391,44 @@ gst_ogg_pad_event (GstPad * pad, GstEvent * event)
|
|||||||
switch (GST_EVENT_TYPE (event)) {
|
switch (GST_EVENT_TYPE (event)) {
|
||||||
case GST_EVENT_SEEK:
|
case GST_EVENT_SEEK:
|
||||||
{
|
{
|
||||||
gint64 offset;
|
gboolean running;
|
||||||
|
gboolean flush;
|
||||||
|
|
||||||
/* can't seek if we are not seekable */
|
/* can't seek if we are not seekable, FIXME could pass the
|
||||||
|
* seek query upstream after converting it to bytes using
|
||||||
|
* the average bitrate of the stream. */
|
||||||
if (!ogg->seekable) {
|
if (!ogg->seekable) {
|
||||||
res = FALSE;
|
res = FALSE;
|
||||||
|
GST_DEBUG ("seek on non seekable stream");
|
||||||
goto done_unref;
|
goto done_unref;
|
||||||
}
|
}
|
||||||
/* we can only seek on time */
|
/* we can only seek on time */
|
||||||
if (GST_EVENT_SEEK_FORMAT (event) != GST_FORMAT_TIME) {
|
if (GST_EVENT_SEEK_FORMAT (event) != GST_FORMAT_TIME) {
|
||||||
res = FALSE;
|
res = FALSE;
|
||||||
|
GST_DEBUG ("can only seek on TIME");
|
||||||
goto done_unref;
|
goto done_unref;
|
||||||
}
|
}
|
||||||
offset = GST_EVENT_SEEK_OFFSET (event);
|
ogg->segment_start = GST_EVENT_SEEK_OFFSET (event);
|
||||||
|
ogg->segment_stop = GST_EVENT_SEEK_ENDOFFSET (event);
|
||||||
|
ogg->segment_play =
|
||||||
|
!!(GST_EVENT_SEEK_TYPE (event) & GST_SEEK_FLAG_SEGMENT_LOOP);
|
||||||
|
flush = !!(GST_EVENT_SEEK_TYPE (event) & GST_SEEK_FLAG_FLUSH);
|
||||||
gst_event_unref (event);
|
gst_event_unref (event);
|
||||||
|
|
||||||
|
GST_DEBUG ("segment positions set to %" GST_TIME_FORMAT "-%"
|
||||||
|
GST_TIME_FORMAT, GST_TIME_ARGS (ogg->segment_start),
|
||||||
|
GST_TIME_ARGS (ogg->segment_stop));
|
||||||
|
|
||||||
|
/* check if we can do the seek now */
|
||||||
|
GST_LOCK (ogg);
|
||||||
|
running = ogg->running;
|
||||||
|
GST_UNLOCK (ogg);
|
||||||
|
|
||||||
/* now do the seek */
|
/* now do the seek */
|
||||||
res = gst_ogg_demux_perform_seek (ogg, offset);
|
if (running) {
|
||||||
|
res = gst_ogg_demux_perform_seek (ogg, flush);
|
||||||
|
} else
|
||||||
|
res = TRUE;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
@ -409,6 +439,7 @@ gst_ogg_pad_event (GstPad * pad, GstEvent * event)
|
|||||||
return res;
|
return res;
|
||||||
|
|
||||||
done_unref:
|
done_unref:
|
||||||
|
GST_DEBUG ("error handling event");
|
||||||
gst_event_unref (event);
|
gst_event_unref (event);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
@ -506,7 +537,7 @@ gst_ogg_pad_internal_chain (GstPad * pad, GstBuffer * buffer)
|
|||||||
GST_DEBUG_OBJECT (oggpad, "received buffer from iternal pad, TS=%lld",
|
GST_DEBUG_OBJECT (oggpad, "received buffer from iternal pad, TS=%lld",
|
||||||
timestamp);
|
timestamp);
|
||||||
|
|
||||||
if (oggpad->start_time == -1)
|
if (oggpad->start_time == GST_CLOCK_TIME_NONE)
|
||||||
oggpad->start_time = timestamp;
|
oggpad->start_time = timestamp;
|
||||||
|
|
||||||
gst_buffer_unref (buffer);
|
gst_buffer_unref (buffer);
|
||||||
@ -539,9 +570,8 @@ gst_ogg_pad_typefind (GstOggPad * pad, ogg_packet * packet)
|
|||||||
caps = gst_caps_new_simple ("application/octet-stream", NULL);
|
caps = gst_caps_new_simple ("application/octet-stream", NULL);
|
||||||
} else {
|
} else {
|
||||||
/* ogg requires you to use a decoder element to define the
|
/* ogg requires you to use a decoder element to define the
|
||||||
* meaning of granulepos etc so we make one. We only do this if
|
* meaning of granulepos etc so we make one. We also do this if
|
||||||
* we are in the seeking mode. */
|
* we are in the streaming mode to calculate the first timestamp. */
|
||||||
if (ogg->seekable) {
|
|
||||||
GList *factories;
|
GList *factories;
|
||||||
|
|
||||||
/* first filter out the interesting element factories */
|
/* first filter out the interesting element factories */
|
||||||
@ -567,8 +597,7 @@ gst_ogg_pad_typefind (GstOggPad * pad, ogg_packet * packet)
|
|||||||
pad->elem_out =
|
pad->elem_out =
|
||||||
gst_pad_new_from_template (gst_static_pad_template_get
|
gst_pad_new_from_template (gst_static_pad_template_get
|
||||||
(&internaltemplate), "internal");
|
(&internaltemplate), "internal");
|
||||||
gst_pad_set_chain_function (pad->elem_out,
|
gst_pad_set_chain_function (pad->elem_out, gst_ogg_pad_internal_chain);
|
||||||
gst_ogg_pad_internal_chain);
|
|
||||||
gst_pad_set_element_private (pad->elem_out, pad);
|
gst_pad_set_element_private (pad->elem_out, pad);
|
||||||
gst_pad_set_active (pad->elem_out, TRUE);
|
gst_pad_set_active (pad->elem_out, TRUE);
|
||||||
|
|
||||||
@ -583,9 +612,6 @@ gst_ogg_pad_typefind (GstOggPad * pad, ogg_packet * packet)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
g_list_free (factories);
|
g_list_free (factories);
|
||||||
} else {
|
|
||||||
pad->mode = GST_OGG_PAD_MODE_STREAMING;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
pad->element = element;
|
pad->element = element;
|
||||||
|
|
||||||
@ -595,82 +621,19 @@ gst_ogg_pad_typefind (GstOggPad * pad, ogg_packet * packet)
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* submit a packet to the oggpad, this function will run the
|
/* send packet to internal element */
|
||||||
* typefind code for the pad if this is the first packet for this
|
|
||||||
* stream
|
|
||||||
*/
|
|
||||||
static GstFlowReturn
|
static GstFlowReturn
|
||||||
gst_ogg_pad_submit_packet (GstOggPad * pad, ogg_packet * packet)
|
gst_ogg_demux_chain_elem_pad (GstOggPad * pad, ogg_packet * packet)
|
||||||
{
|
{
|
||||||
GstBuffer *buf;
|
GstBuffer *buf;
|
||||||
gint64 granule;
|
GstFlowReturn ret;
|
||||||
GstFlowReturn ret = GST_FLOW_OK;
|
|
||||||
|
|
||||||
GstOggDemux *ogg = pad->ogg;
|
GstOggDemux *ogg = pad->ogg;
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (ogg,
|
|
||||||
"%p submit packet serial %08lx, packetno %lld", pad, pad->serialno,
|
|
||||||
pad->packetno);
|
|
||||||
|
|
||||||
granule = packet->granulepos;
|
|
||||||
if (granule != -1) {
|
|
||||||
pad->current_granule = granule;
|
|
||||||
if (pad->first_granule == -1 && granule != 0) {
|
|
||||||
pad->first_granule = granule;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* first packet, FIXME, do this in chain activation */
|
|
||||||
if (pad->packetno == 0) {
|
|
||||||
gst_ogg_pad_typefind (pad, packet);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* stream packet to peer plugin */
|
|
||||||
if (pad->mode == GST_OGG_PAD_MODE_STREAMING) {
|
|
||||||
ret =
|
|
||||||
gst_pad_alloc_buffer (GST_PAD (pad), GST_BUFFER_OFFSET_NONE,
|
|
||||||
packet->bytes, GST_PAD_CAPS (pad), &buf);
|
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (ogg,
|
|
||||||
"%p streaming to peer serial %08lx, packetno %lld", pad, pad->serialno,
|
|
||||||
pad->packetno);
|
|
||||||
|
|
||||||
if (ret == GST_FLOW_OK) {
|
|
||||||
memcpy (buf->data, packet->packet, packet->bytes);
|
|
||||||
|
|
||||||
pad->offset = packet->granulepos;
|
|
||||||
GST_BUFFER_OFFSET (buf) = -1;
|
|
||||||
GST_BUFFER_OFFSET_END (buf) = packet->granulepos;
|
|
||||||
|
|
||||||
ret = gst_pad_push (GST_PAD (pad), buf);
|
|
||||||
} else {
|
|
||||||
GST_DEBUG_OBJECT (ogg,
|
|
||||||
"%p could not get buffer from peer %08lx, packetno %lld", pad,
|
|
||||||
pad->serialno, pad->packetno);
|
|
||||||
|
|
||||||
/* if we are still building a chain, we have to queue this buffer and
|
|
||||||
* push it when we activate the chain */
|
|
||||||
if (ogg->building_chain) {
|
|
||||||
buf = gst_buffer_new_and_alloc (packet->bytes);
|
|
||||||
memcpy (buf->data, packet->packet, packet->bytes);
|
|
||||||
pad->offset = packet->granulepos;
|
|
||||||
GST_BUFFER_OFFSET (buf) = -1;
|
|
||||||
GST_BUFFER_OFFSET_END (buf) = packet->granulepos;
|
|
||||||
pad->headers = g_list_append (pad->headers, buf);
|
|
||||||
/* we are ok now */
|
|
||||||
ret = GST_FLOW_OK;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* we just ignore unlinked pads */
|
|
||||||
if (ret == GST_FLOW_NOT_LINKED)
|
|
||||||
ret = GST_FLOW_OK;
|
|
||||||
} else {
|
|
||||||
/* initialize our internal decoder with packets */
|
/* initialize our internal decoder with packets */
|
||||||
if (!pad->elem_pad)
|
if (!pad->elem_pad)
|
||||||
goto no_decoder;
|
goto no_decoder;
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (ogg,
|
GST_DEBUG_OBJECT (ogg, "%p init decoder serial %08lx", pad, pad->serialno);
|
||||||
"%p init decoder serial %08lx, packetno %lld", pad, pad->serialno,
|
|
||||||
pad->packetno);
|
|
||||||
|
|
||||||
buf = gst_buffer_new_and_alloc (packet->bytes);
|
buf = gst_buffer_new_and_alloc (packet->bytes);
|
||||||
memcpy (GST_BUFFER_DATA (buf), packet->packet, packet->bytes);
|
memcpy (GST_BUFFER_DATA (buf), packet->packet, packet->bytes);
|
||||||
@ -681,8 +644,6 @@ gst_ogg_pad_submit_packet (GstOggPad * pad, ogg_packet * packet)
|
|||||||
ret = gst_pad_chain (pad->elem_pad, buf);
|
ret = gst_pad_chain (pad->elem_pad, buf);
|
||||||
if (GST_FLOW_IS_FATAL (ret))
|
if (GST_FLOW_IS_FATAL (ret))
|
||||||
goto decoder_error;
|
goto decoder_error;
|
||||||
}
|
|
||||||
pad->packetno++;
|
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
@ -699,6 +660,122 @@ decoder_error:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* queue data */
|
||||||
|
static GstFlowReturn
|
||||||
|
gst_ogg_demux_queue_data (GstOggPad * pad, ogg_packet * packet)
|
||||||
|
{
|
||||||
|
GstBuffer *buf;
|
||||||
|
GstOggDemux *ogg = pad->ogg;
|
||||||
|
|
||||||
|
GST_DEBUG_OBJECT (ogg, "%p queueing data serial %08lx", pad, pad->serialno);
|
||||||
|
|
||||||
|
buf = gst_buffer_new_and_alloc (packet->bytes);
|
||||||
|
memcpy (buf->data, packet->packet, packet->bytes);
|
||||||
|
GST_BUFFER_OFFSET (buf) = -1;
|
||||||
|
GST_BUFFER_OFFSET_END (buf) = packet->granulepos;
|
||||||
|
pad->headers = g_list_append (pad->headers, buf);
|
||||||
|
|
||||||
|
/* we are ok now */
|
||||||
|
return GST_FLOW_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* send packet to internal element */
|
||||||
|
static GstFlowReturn
|
||||||
|
gst_ogg_demux_chain_peer (GstOggPad * pad, ogg_packet * packet)
|
||||||
|
{
|
||||||
|
GstBuffer *buf;
|
||||||
|
GstFlowReturn ret;
|
||||||
|
GstOggDemux *ogg = pad->ogg;
|
||||||
|
|
||||||
|
|
||||||
|
ret = gst_pad_alloc_buffer (GST_PAD (pad), GST_BUFFER_OFFSET_NONE,
|
||||||
|
packet->bytes, GST_PAD_CAPS (pad), &buf);
|
||||||
|
|
||||||
|
GST_DEBUG_OBJECT (ogg,
|
||||||
|
"%p streaming to peer serial %08lx", pad, pad->serialno);
|
||||||
|
|
||||||
|
if (ret == GST_FLOW_OK) {
|
||||||
|
memcpy (buf->data, packet->packet, packet->bytes);
|
||||||
|
|
||||||
|
GST_BUFFER_OFFSET (buf) = -1;
|
||||||
|
GST_BUFFER_OFFSET_END (buf) = packet->granulepos;
|
||||||
|
|
||||||
|
ret = gst_pad_push (GST_PAD (pad), buf);
|
||||||
|
} else {
|
||||||
|
GST_DEBUG_OBJECT (ogg,
|
||||||
|
"%p could not get buffer from peer %08lx", pad, pad->serialno);
|
||||||
|
|
||||||
|
if (ret == GST_FLOW_NOT_LINKED)
|
||||||
|
ret = GST_FLOW_OK;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* submit a packet to the oggpad, this function will run the
|
||||||
|
* typefind code for the pad if this is the first packet for this
|
||||||
|
* stream
|
||||||
|
*/
|
||||||
|
static GstFlowReturn
|
||||||
|
gst_ogg_pad_submit_packet (GstOggPad * pad, ogg_packet * packet)
|
||||||
|
{
|
||||||
|
gint64 granule;
|
||||||
|
GstFlowReturn ret;
|
||||||
|
|
||||||
|
GstOggDemux *ogg = pad->ogg;
|
||||||
|
|
||||||
|
GST_DEBUG_OBJECT (ogg, "%p submit packet serial %08lx", pad, pad->serialno);
|
||||||
|
|
||||||
|
granule = packet->granulepos;
|
||||||
|
if (granule != -1) {
|
||||||
|
pad->current_granule = granule;
|
||||||
|
if (pad->first_granule == -1 && granule != 0) {
|
||||||
|
pad->first_granule = granule;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* first packet */
|
||||||
|
if (!pad->have_type) {
|
||||||
|
gst_ogg_pad_typefind (pad, packet);
|
||||||
|
pad->have_type = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* no start time known, stream to internal plugin to
|
||||||
|
* get time */
|
||||||
|
if (pad->start_time == GST_CLOCK_TIME_NONE) {
|
||||||
|
ret = gst_ogg_demux_chain_elem_pad (pad, packet);
|
||||||
|
}
|
||||||
|
/* we know the start_time of the pad data, see if we
|
||||||
|
* can activate the complete chain if this is a dynamic
|
||||||
|
* chain. */
|
||||||
|
if (pad->start_time != GST_CLOCK_TIME_NONE) {
|
||||||
|
/* check if complete chain has start time */
|
||||||
|
if (pad->chain == ogg->building_chain) {
|
||||||
|
if (gst_ogg_demux_collect_chain_info (ogg, pad->chain)) {
|
||||||
|
GstEvent *event;
|
||||||
|
|
||||||
|
/* create the discont event we are going to send out */
|
||||||
|
event = gst_event_new_discontinuous (1.0,
|
||||||
|
GST_FORMAT_TIME, (gint64) pad->chain->start_time,
|
||||||
|
(gint64) pad->chain->last_time, NULL);
|
||||||
|
|
||||||
|
gst_ogg_demux_activate_chain (ogg, pad->chain, event);
|
||||||
|
|
||||||
|
ogg->building_chain = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* if we are building a chain, store buffer for when we activate
|
||||||
|
* it. This path is taken if we operate in streaming mode. */
|
||||||
|
if (ogg->building_chain) {
|
||||||
|
ret = gst_ogg_demux_queue_data (pad, packet);
|
||||||
|
}
|
||||||
|
/* else we are completely streaming to the peer */
|
||||||
|
else {
|
||||||
|
ret = gst_ogg_demux_chain_peer (pad, packet);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
/* submit a page to an oggpad, this function will then submit all
|
/* submit a page to an oggpad, this function will then submit all
|
||||||
* the packets in the page.
|
* the packets in the page.
|
||||||
*/
|
*/
|
||||||
@ -771,6 +848,8 @@ gst_ogg_chain_new (GstOggDemux * ogg)
|
|||||||
chain->bytes = -1;
|
chain->bytes = -1;
|
||||||
chain->have_bos = FALSE;
|
chain->have_bos = FALSE;
|
||||||
chain->streams = g_array_new (FALSE, TRUE, sizeof (GstOggPad *));
|
chain->streams = g_array_new (FALSE, TRUE, sizeof (GstOggPad *));
|
||||||
|
chain->start_time = GST_CLOCK_TIME_NONE;
|
||||||
|
chain->total_time = GST_CLOCK_TIME_NONE;
|
||||||
|
|
||||||
return chain;
|
return chain;
|
||||||
}
|
}
|
||||||
@ -951,6 +1030,12 @@ gst_ogg_demux_init (GstOggDemux * ogg)
|
|||||||
ogg->chain_lock = g_mutex_new ();
|
ogg->chain_lock = g_mutex_new ();
|
||||||
ogg->chains = g_array_new (FALSE, TRUE, sizeof (GstOggChain *));
|
ogg->chains = g_array_new (FALSE, TRUE, sizeof (GstOggChain *));
|
||||||
ogg->state = OGG_STATE_NEW_CHAIN;
|
ogg->state = OGG_STATE_NEW_CHAIN;
|
||||||
|
|
||||||
|
ogg->segment_start = GST_CLOCK_TIME_NONE;
|
||||||
|
ogg->segment_stop = GST_CLOCK_TIME_NONE;
|
||||||
|
ogg->segment_play = FALSE;
|
||||||
|
|
||||||
|
ogg->running = FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -1153,13 +1238,15 @@ gst_ogg_demux_deactivate_current_chain (GstOggDemux * ogg)
|
|||||||
if (chain == NULL)
|
if (chain == NULL)
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
||||||
|
/* send EOS on all the pads */
|
||||||
for (i = 0; i < chain->streams->len; i++) {
|
for (i = 0; i < chain->streams->len; i++) {
|
||||||
GstOggPad *pad = g_array_index (chain->streams, GstOggPad *, i);
|
GstOggPad *pad = g_array_index (chain->streams, GstOggPad *, i);
|
||||||
|
|
||||||
gst_pad_push_event (GST_PAD (pad), gst_event_new (GST_EVENT_EOS));
|
gst_pad_push_event (GST_PAD (pad), gst_event_new (GST_EVENT_EOS));
|
||||||
gst_element_remove_pad (GST_ELEMENT (ogg), GST_PAD (pad));
|
gst_element_remove_pad (GST_ELEMENT (ogg), GST_PAD (pad));
|
||||||
}
|
}
|
||||||
/* if we cannot seek, we can destroy the chain completely */
|
/* if we cannot seek back to the chain, we can destroy the chain
|
||||||
|
* completely */
|
||||||
if (!ogg->seekable) {
|
if (!ogg->seekable) {
|
||||||
gst_ogg_chain_free (chain);
|
gst_ogg_chain_free (chain);
|
||||||
}
|
}
|
||||||
@ -1169,20 +1256,25 @@ gst_ogg_demux_deactivate_current_chain (GstOggDemux * ogg)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
gst_ogg_demux_activate_chain (GstOggDemux * ogg, GstOggChain * chain)
|
gst_ogg_demux_activate_chain (GstOggDemux * ogg, GstOggChain * chain,
|
||||||
|
GstEvent * event)
|
||||||
{
|
{
|
||||||
gint i;
|
gint i;
|
||||||
GList *headers;
|
|
||||||
GstOggPad *pad;
|
|
||||||
GstEvent *event;
|
|
||||||
|
|
||||||
if (chain == ogg->current_chain)
|
if (chain == ogg->current_chain) {
|
||||||
|
if (event)
|
||||||
|
gst_event_unref (event);
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
gst_ogg_demux_deactivate_current_chain (ogg);
|
gst_ogg_demux_deactivate_current_chain (ogg);
|
||||||
|
|
||||||
|
GST_DEBUG ("activating chain");
|
||||||
|
|
||||||
/* first add the pads */
|
/* first add the pads */
|
||||||
for (i = 0; i < chain->streams->len; i++) {
|
for (i = 0; i < chain->streams->len; i++) {
|
||||||
|
GstOggPad *pad;
|
||||||
|
|
||||||
pad = g_array_index (chain->streams, GstOggPad *, i);
|
pad = g_array_index (chain->streams, GstOggPad *, i);
|
||||||
gst_element_add_pad (GST_ELEMENT (ogg), GST_PAD (pad));
|
gst_element_add_pad (GST_ELEMENT (ogg), GST_PAD (pad));
|
||||||
}
|
}
|
||||||
@ -1190,15 +1282,19 @@ gst_ogg_demux_activate_chain (GstOggDemux * ogg, GstOggChain * chain)
|
|||||||
gst_element_no_more_pads (GST_ELEMENT (ogg));
|
gst_element_no_more_pads (GST_ELEMENT (ogg));
|
||||||
ogg->current_chain = chain;
|
ogg->current_chain = chain;
|
||||||
|
|
||||||
/* send the base time */
|
if (event)
|
||||||
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);
|
gst_ogg_demux_send_event (ogg, event);
|
||||||
|
|
||||||
/* then send out the buffers */
|
GST_DEBUG ("starting chain");
|
||||||
|
|
||||||
|
/* we are streaming now */
|
||||||
|
ogg->state = OGG_STATE_STREAMING;
|
||||||
|
|
||||||
|
/* then send out any queued buffers */
|
||||||
for (i = 0; i < chain->streams->len; i++) {
|
for (i = 0; i < chain->streams->len; i++) {
|
||||||
|
GList *headers;
|
||||||
|
GstOggPad *pad;
|
||||||
|
|
||||||
pad = g_array_index (chain->streams, GstOggPad *, i);
|
pad = g_array_index (chain->streams, GstOggPad *, i);
|
||||||
|
|
||||||
for (headers = pad->headers; headers; headers = g_list_next (headers)) {
|
for (headers = pad->headers; headers; headers = g_list_next (headers)) {
|
||||||
@ -1215,7 +1311,7 @@ gst_ogg_demux_activate_chain (GstOggDemux * ogg, GstOggChain * chain)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
gst_ogg_demux_perform_seek (GstOggDemux * ogg, gint64 pos)
|
gst_ogg_demux_perform_seek (GstOggDemux * ogg, gboolean flush)
|
||||||
{
|
{
|
||||||
GstOggChain *chain = NULL;
|
GstOggChain *chain = NULL;
|
||||||
gint64 begin, end;
|
gint64 begin, end;
|
||||||
@ -1226,18 +1322,22 @@ gst_ogg_demux_perform_seek (GstOggDemux * ogg, gint64 pos)
|
|||||||
gint64 result = 0;
|
gint64 result = 0;
|
||||||
gint i;
|
gint i;
|
||||||
|
|
||||||
total = ogg->total_time;
|
/* nothing configured, play complete file */
|
||||||
|
if (ogg->segment_start == GST_CLOCK_TIME_NONE)
|
||||||
|
ogg->segment_start = ogg->start_time;
|
||||||
|
if (ogg->segment_stop == GST_CLOCK_TIME_NONE)
|
||||||
|
ogg->segment_stop = ogg->total_time;
|
||||||
|
|
||||||
/* can't seek past start or end */
|
ogg->segment_start =
|
||||||
if (pos < 0 || pos > total) {
|
CLAMP (ogg->segment_start, ogg->start_time, ogg->total_time);
|
||||||
return FALSE;
|
ogg->segment_stop =
|
||||||
}
|
CLAMP (ogg->segment_stop, ogg->start_time, ogg->total_time);
|
||||||
|
|
||||||
/* first step is to unlock the streaming thread if it is
|
/* first step is to unlock the streaming thread if it is
|
||||||
* blocked in a chain call, we do this by starting the flush. because
|
* blocked in a chain call, we do this by starting the flush. because
|
||||||
* we cannot yet hold any streaming lock, we have to protect the chains
|
* we cannot yet hold any streaming lock, we have to protect the chains
|
||||||
* with their own lock. */
|
* with their own lock. */
|
||||||
{
|
if (flush) {
|
||||||
gint i;
|
gint i;
|
||||||
|
|
||||||
gst_pad_push_event (ogg->sinkpad, gst_event_new_flush (FALSE));
|
gst_pad_push_event (ogg->sinkpad, gst_event_new_flush (FALSE));
|
||||||
@ -1247,7 +1347,6 @@ gst_ogg_demux_perform_seek (GstOggDemux * ogg, gint64 pos)
|
|||||||
GstOggChain *chain = g_array_index (ogg->chains, GstOggChain *, i);
|
GstOggChain *chain = g_array_index (ogg->chains, GstOggChain *, i);
|
||||||
gint j;
|
gint j;
|
||||||
|
|
||||||
|
|
||||||
for (j = 0; j < chain->streams->len; j++) {
|
for (j = 0; j < chain->streams->len; j++) {
|
||||||
GstOggPad *pad = g_array_index (chain->streams, GstOggPad *, j);
|
GstOggPad *pad = g_array_index (chain->streams, GstOggPad *, j);
|
||||||
|
|
||||||
@ -1255,16 +1354,19 @@ gst_ogg_demux_perform_seek (GstOggDemux * ogg, gint64 pos)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
GST_CHAIN_UNLOCK (ogg);
|
GST_CHAIN_UNLOCK (ogg);
|
||||||
|
} else {
|
||||||
|
gst_pad_pause_task (ogg->sinkpad);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* now grab the stream lock so that streaming cannot continue */
|
/* now grab the stream lock so that streaming cannot continue, for
|
||||||
|
* non flushing seeks when the element is in PAUSED this could block
|
||||||
|
* forever. */
|
||||||
GST_STREAM_LOCK (ogg->sinkpad);
|
GST_STREAM_LOCK (ogg->sinkpad);
|
||||||
|
|
||||||
/* we need to stop flushing on the srcpad as w're going to use it
|
/* 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. */
|
* next. We can do this as we have the STREAM lock now. */
|
||||||
gst_pad_push_event (ogg->sinkpad, gst_event_new_flush (TRUE));
|
gst_pad_push_event (ogg->sinkpad, gst_event_new_flush (TRUE));
|
||||||
|
|
||||||
|
|
||||||
{
|
{
|
||||||
gint i;
|
gint i;
|
||||||
|
|
||||||
@ -1283,10 +1385,11 @@ gst_ogg_demux_perform_seek (GstOggDemux * ogg, gint64 pos)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* first find the chain to search in */
|
/* first find the chain to search in */
|
||||||
|
total = ogg->total_time;
|
||||||
for (i = ogg->chains->len - 1; i >= 0; i--) {
|
for (i = ogg->chains->len - 1; i >= 0; i--) {
|
||||||
chain = g_array_index (ogg->chains, GstOggChain *, i);
|
chain = g_array_index (ogg->chains, GstOggChain *, i);
|
||||||
total -= chain->total_time;
|
total -= chain->total_time;
|
||||||
if (pos >= total)
|
if (ogg->segment_start >= total)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1294,11 +1397,13 @@ gst_ogg_demux_perform_seek (GstOggDemux * ogg, gint64 pos)
|
|||||||
end = chain->end_offset;
|
end = chain->end_offset;
|
||||||
begintime = chain->begin_time;
|
begintime = chain->begin_time;
|
||||||
endtime = chain->begin_time + chain->total_time;
|
endtime = chain->begin_time + chain->total_time;
|
||||||
target = pos - total + begintime;
|
target = ogg->segment_start - total + begintime;
|
||||||
best = begin;
|
best = begin;
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (ogg, "seeking to %" GST_TIME_FORMAT " in chain %p",
|
GST_DEBUG_OBJECT (ogg,
|
||||||
GST_TIME_ARGS (pos), chain);
|
"seeking to %" GST_TIME_FORMAT "-%" GST_TIME_FORMAT " in chain %p",
|
||||||
|
GST_TIME_ARGS (ogg->segment_start), GST_TIME_ARGS (ogg->segment_stop),
|
||||||
|
chain);
|
||||||
GST_DEBUG_OBJECT (ogg,
|
GST_DEBUG_OBJECT (ogg,
|
||||||
"chain offset %" G_GINT64_FORMAT ", end offset %" G_GINT64_FORMAT, begin,
|
"chain offset %" G_GINT64_FORMAT ", end offset %" G_GINT64_FORMAT, begin,
|
||||||
end);
|
end);
|
||||||
@ -1407,6 +1512,10 @@ gst_ogg_demux_perform_seek (GstOggDemux * ogg, gint64 pos)
|
|||||||
|
|
||||||
ogg->offset = best;
|
ogg->offset = best;
|
||||||
|
|
||||||
|
/* switch to different chain */
|
||||||
|
if (chain != ogg->current_chain) {
|
||||||
|
gst_ogg_demux_activate_chain (ogg, chain, NULL);
|
||||||
|
}
|
||||||
/* now we have a new position, prepare for streaming again */
|
/* now we have a new position, prepare for streaming again */
|
||||||
{
|
{
|
||||||
gint i;
|
gint i;
|
||||||
@ -1414,7 +1523,8 @@ gst_ogg_demux_perform_seek (GstOggDemux * ogg, gint64 pos)
|
|||||||
|
|
||||||
/* create the discont event we are going to send out */
|
/* create the discont event we are going to send out */
|
||||||
event = gst_event_new_discontinuous (1.0,
|
event = gst_event_new_discontinuous (1.0,
|
||||||
GST_FORMAT_TIME, (gint64) pos, (gint64) ogg->total_time, NULL);
|
GST_FORMAT_TIME, (gint64) ogg->segment_start,
|
||||||
|
(gint64) ogg->segment_stop, NULL);
|
||||||
|
|
||||||
for (i = 0; i < ogg->chains->len; i++) {
|
for (i = 0; i < ogg->chains->len; i++) {
|
||||||
GstOggChain *chain = g_array_index (ogg->chains, GstOggChain *, i);
|
GstOggChain *chain = g_array_index (ogg->chains, GstOggChain *, i);
|
||||||
@ -1423,6 +1533,7 @@ gst_ogg_demux_perform_seek (GstOggDemux * ogg, gint64 pos)
|
|||||||
for (j = 0; j < chain->streams->len; j++) {
|
for (j = 0; j < chain->streams->len; j++) {
|
||||||
GstOggPad *pad = g_array_index (chain->streams, GstOggPad *, j);
|
GstOggPad *pad = g_array_index (chain->streams, GstOggPad *, j);
|
||||||
|
|
||||||
|
if (flush)
|
||||||
gst_pad_push_event (GST_PAD (pad), gst_event_new_flush (TRUE));
|
gst_pad_push_event (GST_PAD (pad), gst_event_new_flush (TRUE));
|
||||||
|
|
||||||
/* and the discont */
|
/* and the discont */
|
||||||
@ -1431,17 +1542,18 @@ gst_ogg_demux_perform_seek (GstOggDemux * ogg, gint64 pos)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
gst_event_unref (event);
|
gst_event_unref (event);
|
||||||
|
|
||||||
|
/* notify start of new segment */
|
||||||
|
if (ogg->segment_play) {
|
||||||
|
gst_element_post_message (GST_ELEMENT (ogg),
|
||||||
|
gst_message_new_segment_start (GST_OBJECT (ogg), ogg->segment_start));
|
||||||
|
}
|
||||||
/* restart our task since it might have been stopped when we did the
|
/* restart our task since it might have been stopped when we did the
|
||||||
* flush. */
|
* flush. */
|
||||||
gst_pad_start_task (ogg->sinkpad, (GstTaskFunction) gst_ogg_demux_loop,
|
gst_pad_start_task (ogg->sinkpad, (GstTaskFunction) gst_ogg_demux_loop,
|
||||||
ogg->sinkpad);
|
ogg->sinkpad);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* switch to different chain */
|
|
||||||
if (chain != ogg->current_chain) {
|
|
||||||
gst_ogg_demux_activate_chain (ogg, chain);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* streaming can continue now */
|
/* streaming can continue now */
|
||||||
GST_STREAM_UNLOCK (ogg->sinkpad);
|
GST_STREAM_UNLOCK (ogg->sinkpad);
|
||||||
|
|
||||||
@ -1593,7 +1705,7 @@ gst_ogg_demux_read_chain (GstOggDemux * ogg)
|
|||||||
gst_ogg_pad_submit_page (pad, &op);
|
gst_ogg_pad_submit_page (pad, &op);
|
||||||
}
|
}
|
||||||
/* the timestamp will be filled in when we submit the pages */
|
/* the timestamp will be filled in when we submit the pages */
|
||||||
done &= (pad->start_time != -1);
|
done &= (pad->start_time != GST_CLOCK_TIME_NONE);
|
||||||
GST_LOG_OBJECT (ogg, "done %08lx now %d", serial, done);
|
GST_LOG_OBJECT (ogg, "done %08lx now %d", serial, done);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1617,7 +1729,6 @@ gst_ogg_demux_read_chain (GstOggDemux * ogg)
|
|||||||
}
|
}
|
||||||
|
|
||||||
pad->mode = GST_OGG_PAD_MODE_STREAMING;
|
pad->mode = GST_OGG_PAD_MODE_STREAMING;
|
||||||
pad->packetno = 0;
|
|
||||||
}
|
}
|
||||||
return chain;
|
return chain;
|
||||||
}
|
}
|
||||||
@ -1692,7 +1803,14 @@ gst_ogg_demux_find_pad (GstOggDemux * ogg, int serialno)
|
|||||||
GstOggPad *pad;
|
GstOggPad *pad;
|
||||||
gint i;
|
gint i;
|
||||||
|
|
||||||
/* first look in current chain if any */
|
/* first look in building chain if any */
|
||||||
|
if (ogg->building_chain) {
|
||||||
|
pad = gst_ogg_chain_get_stream (ogg->building_chain, serialno);
|
||||||
|
if (pad)
|
||||||
|
return pad;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* then look in current chain if any */
|
||||||
if (ogg->current_chain) {
|
if (ogg->current_chain) {
|
||||||
pad = gst_ogg_chain_get_stream (ogg->current_chain, serialno);
|
pad = gst_ogg_chain_get_stream (ogg->current_chain, serialno);
|
||||||
if (pad)
|
if (pad)
|
||||||
@ -1723,6 +1841,67 @@ gst_ogg_demux_find_chain (GstOggDemux * ogg, int serialno)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
gst_ogg_demux_collect_chain_info (GstOggDemux * ogg, GstOggChain * chain)
|
||||||
|
{
|
||||||
|
gint i;
|
||||||
|
|
||||||
|
chain->total_time = 0;
|
||||||
|
chain->start_time = G_MAXINT64;
|
||||||
|
chain->last_time = 0;
|
||||||
|
|
||||||
|
for (i = 0; i < chain->streams->len; i++) {
|
||||||
|
GstOggPad *pad = g_array_index (chain->streams, GstOggPad *, i);
|
||||||
|
|
||||||
|
/* can do this if the pad start time is not defined */
|
||||||
|
if (pad->start_time == GST_CLOCK_TIME_NONE)
|
||||||
|
goto no_start_time;
|
||||||
|
|
||||||
|
if (pad->last_time != GST_CLOCK_TIME_NONE) {
|
||||||
|
pad->total_time = pad->last_time - pad->start_time;
|
||||||
|
chain->total_time = MAX (chain->total_time, pad->total_time);
|
||||||
|
chain->last_time = MAX (chain->last_time, pad->last_time);
|
||||||
|
} else {
|
||||||
|
pad->total_time = GST_CLOCK_TIME_NONE;
|
||||||
|
chain->total_time = GST_CLOCK_TIME_NONE;
|
||||||
|
chain->last_time = GST_CLOCK_TIME_NONE;
|
||||||
|
}
|
||||||
|
chain->start_time = MIN (chain->start_time, pad->start_time);
|
||||||
|
}
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
/* ERROR */
|
||||||
|
no_start_time:
|
||||||
|
{
|
||||||
|
chain->total_time = GST_CLOCK_TIME_NONE;
|
||||||
|
chain->start_time = GST_CLOCK_TIME_NONE;
|
||||||
|
chain->last_time = GST_CLOCK_TIME_NONE;
|
||||||
|
chain->begin_time = GST_CLOCK_TIME_NONE;
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_ogg_demux_collect_info (GstOggDemux * ogg)
|
||||||
|
{
|
||||||
|
gint i;
|
||||||
|
|
||||||
|
/* collect all info */
|
||||||
|
ogg->start_time = G_MAXINT64;
|
||||||
|
ogg->total_time = 0;
|
||||||
|
|
||||||
|
for (i = 0; i < ogg->chains->len; i++) {
|
||||||
|
GstOggChain *chain = g_array_index (ogg->chains, GstOggChain *, i);
|
||||||
|
|
||||||
|
chain->begin_time = ogg->total_time;
|
||||||
|
|
||||||
|
gst_ogg_demux_collect_chain_info (ogg, chain);
|
||||||
|
|
||||||
|
ogg->start_time = MIN (ogg->start_time, chain->start_time);
|
||||||
|
ogg->total_time += chain->total_time;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* find all the chains in the ogg file, this reads the first and
|
/* find all the chains in the ogg file, this reads the first and
|
||||||
* last page of the ogg stream, if they match then the ogg file has
|
* last page of the ogg stream, if they match then the ogg file has
|
||||||
* just one chain, else we do a binary search for all chains.
|
* just one chain, else we do a binary search for all chains.
|
||||||
@ -1774,44 +1953,11 @@ gst_ogg_demux_find_chains (GstOggDemux * ogg)
|
|||||||
gst_ogg_demux_bisect_forward_serialno (ogg, 0, ogg->length, ogg->length,
|
gst_ogg_demux_bisect_forward_serialno (ogg, 0, ogg->length, ogg->length,
|
||||||
chain, 0);
|
chain, 0);
|
||||||
}
|
}
|
||||||
/* collect all info */
|
gst_ogg_demux_collect_info (ogg);
|
||||||
{
|
|
||||||
gint i, j;
|
|
||||||
|
|
||||||
ogg->total_time = 0;
|
|
||||||
|
|
||||||
for (i = 0; i < ogg->chains->len; i++) {
|
|
||||||
GstOggChain *chain = g_array_index (ogg->chains, GstOggChain *, i);
|
|
||||||
|
|
||||||
chain->total_time = 0;
|
|
||||||
chain->start_time = G_MAXINT64;
|
|
||||||
chain->last_time = 0;
|
|
||||||
chain->begin_time = ogg->total_time;
|
|
||||||
|
|
||||||
for (j = 0; j < chain->streams->len; j++) {
|
|
||||||
GstOggPad *pad = g_array_index (chain->streams, GstOggPad *, j);
|
|
||||||
|
|
||||||
pad->total_time = pad->last_time - pad->start_time;
|
|
||||||
chain->total_time = MAX (chain->total_time, pad->total_time);
|
|
||||||
chain->start_time = MIN (chain->start_time, pad->start_time);
|
|
||||||
chain->last_time = MAX (chain->last_time, pad->last_time);
|
|
||||||
}
|
|
||||||
ogg->total_time += chain->total_time;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* dump our chains and streams */
|
/* dump our chains and streams */
|
||||||
gst_ogg_print (ogg);
|
gst_ogg_print (ogg);
|
||||||
|
|
||||||
/* activate first chain */
|
|
||||||
if (ogg->chains->len > 0) {
|
|
||||||
GstOggChain *chain = g_array_index (ogg->chains, GstOggChain *, 0);
|
|
||||||
|
|
||||||
gst_ogg_demux_activate_chain (ogg, chain);
|
|
||||||
/* and we are streaming now */
|
|
||||||
ogg->state = OGG_STATE_STREAMING;
|
|
||||||
}
|
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
||||||
/*** error cases ***/
|
/*** error cases ***/
|
||||||
@ -1875,7 +2021,7 @@ gst_ogg_demux_chain (GstPad * pad, GstBuffer * buffer)
|
|||||||
chain = gst_ogg_demux_find_chain (ogg, serialno);
|
chain = gst_ogg_demux_find_chain (ogg, serialno);
|
||||||
if (chain) {
|
if (chain) {
|
||||||
/* we do, activate it as it means we have a non-header */
|
/* we do, activate it as it means we have a non-header */
|
||||||
gst_ogg_demux_activate_chain (ogg, chain);
|
gst_ogg_demux_activate_chain (ogg, chain, NULL);
|
||||||
pad = gst_ogg_demux_find_pad (ogg, serialno);
|
pad = gst_ogg_demux_find_pad (ogg, serialno);
|
||||||
} else {
|
} else {
|
||||||
/* chain is unknown */
|
/* chain is unknown */
|
||||||
@ -1892,13 +2038,6 @@ gst_ogg_demux_chain (GstPad * pad, GstBuffer * buffer)
|
|||||||
pad = gst_ogg_chain_new_stream (ogg->building_chain, serialno);
|
pad = gst_ogg_chain_new_stream (ogg->building_chain, serialno);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
/* no more bos pages, see if we need to activate the chain we were
|
|
||||||
* building */
|
|
||||||
if (ogg->building_chain) {
|
|
||||||
gst_ogg_demux_activate_chain (ogg, ogg->building_chain);
|
|
||||||
ogg->building_chain = NULL;
|
|
||||||
ogg->state = OGG_STATE_STREAMING;
|
|
||||||
}
|
|
||||||
pad = gst_ogg_demux_find_pad (ogg, serialno);
|
pad = gst_ogg_demux_find_pad (ogg, serialno);
|
||||||
}
|
}
|
||||||
if (pad) {
|
if (pad) {
|
||||||
@ -1959,13 +2098,28 @@ gst_ogg_demux_loop (GstOggPad * pad)
|
|||||||
goto chain_read_failed;
|
goto chain_read_failed;
|
||||||
|
|
||||||
ogg->need_chains = FALSE;
|
ogg->need_chains = FALSE;
|
||||||
ogg->offset = 0;
|
|
||||||
|
GST_LOCK (ogg);
|
||||||
|
ogg->running = TRUE;
|
||||||
|
GST_UNLOCK (ogg);
|
||||||
|
|
||||||
|
/* and seek to configured positions without FLUSH */
|
||||||
|
gst_ogg_demux_perform_seek (ogg, FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
GST_LOG_OBJECT (ogg, "pull data %lld", ogg->offset);
|
GST_LOG_OBJECT (ogg, "pull data %lld", ogg->offset);
|
||||||
if (ogg->offset == ogg->length) {
|
if (ogg->offset == ogg->length) {
|
||||||
ret = GST_FLOW_OK;
|
ret = GST_FLOW_OK;
|
||||||
|
/* segment playback just posts a segment end message instead of
|
||||||
|
* pushing out EOS. */
|
||||||
|
/* FIXME, need to be done somewhere else where we
|
||||||
|
* can check against segment_stop time. */
|
||||||
|
if (ogg->segment_play) {
|
||||||
|
gst_element_post_message (GST_ELEMENT (ogg),
|
||||||
|
gst_message_new_segment_done (GST_OBJECT (ogg), ogg->total_time));
|
||||||
|
} else {
|
||||||
gst_ogg_demux_send_event (ogg, gst_event_new (GST_EVENT_EOS));
|
gst_ogg_demux_send_event (ogg, gst_event_new (GST_EVENT_EOS));
|
||||||
|
}
|
||||||
goto pause;
|
goto pause;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2020,6 +2174,12 @@ gst_ogg_demux_clear_chains (GstOggDemux * ogg)
|
|||||||
GST_CHAIN_UNLOCK (ogg);
|
GST_CHAIN_UNLOCK (ogg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* this function is called when the pad is activated and should start
|
||||||
|
* processing data.
|
||||||
|
*
|
||||||
|
* We check if we can do random access to decide if we work push or
|
||||||
|
* pull based.
|
||||||
|
*/
|
||||||
static gboolean
|
static gboolean
|
||||||
gst_ogg_demux_sink_activate (GstPad * sinkpad)
|
gst_ogg_demux_sink_activate (GstPad * sinkpad)
|
||||||
{
|
{
|
||||||
@ -2030,6 +2190,8 @@ gst_ogg_demux_sink_activate (GstPad * sinkpad)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* this function gets called when we activate ourselves in push mode.
|
||||||
|
* We cannot seek (ourselves) in the stream */
|
||||||
static gboolean
|
static gboolean
|
||||||
gst_ogg_demux_sink_activate_push (GstPad * sinkpad, gboolean active)
|
gst_ogg_demux_sink_activate_push (GstPad * sinkpad, gboolean active)
|
||||||
{
|
{
|
||||||
@ -2042,6 +2204,9 @@ gst_ogg_demux_sink_activate_push (GstPad * sinkpad, gboolean active)
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* this function gets called when we activate ourselves in pull mode.
|
||||||
|
* We can perform random access to the resource and we start a task
|
||||||
|
* to start reading */
|
||||||
static gboolean
|
static gboolean
|
||||||
gst_ogg_demux_sink_activate_pull (GstPad * sinkpad, gboolean active)
|
gst_ogg_demux_sink_activate_pull (GstPad * sinkpad, gboolean active)
|
||||||
{
|
{
|
||||||
@ -2086,6 +2251,9 @@ gst_ogg_demux_change_state (GstElement * element)
|
|||||||
break;
|
break;
|
||||||
case GST_STATE_PAUSED_TO_READY:
|
case GST_STATE_PAUSED_TO_READY:
|
||||||
gst_ogg_demux_clear_chains (ogg);
|
gst_ogg_demux_clear_chains (ogg);
|
||||||
|
GST_LOCK (ogg);
|
||||||
|
ogg->running = FALSE;
|
||||||
|
GST_UNLOCK (ogg);
|
||||||
break;
|
break;
|
||||||
case GST_STATE_READY_TO_NULL:
|
case GST_STATE_READY_TO_NULL:
|
||||||
ogg_sync_clear (&ogg->sync);
|
ogg_sync_clear (&ogg->sync);
|
||||||
@ -2192,7 +2360,9 @@ gst_ogg_print (GstOggDemux * ogg)
|
|||||||
{
|
{
|
||||||
guint j, i;
|
guint j, i;
|
||||||
|
|
||||||
GST_INFO_OBJECT (ogg, "%u chains, total time: %" GST_TIME_FORMAT,
|
GST_INFO_OBJECT (ogg, "%u chains, start time: %" GST_TIME_FORMAT,
|
||||||
|
ogg->chains->len, GST_TIME_ARGS (ogg->start_time));
|
||||||
|
GST_INFO_OBJECT (ogg, " total time: %" GST_TIME_FORMAT,
|
||||||
ogg->chains->len, GST_TIME_ARGS (ogg->total_time));
|
ogg->chains->len, GST_TIME_ARGS (ogg->total_time));
|
||||||
|
|
||||||
for (i = 0; i < ogg->chains->len; i++) {
|
for (i = 0; i < ogg->chains->len; i++) {
|
||||||
@ -2201,8 +2371,12 @@ gst_ogg_print (GstOggDemux * ogg)
|
|||||||
GST_INFO_OBJECT (ogg, " chain %d (%u streams):", i, chain->streams->len);
|
GST_INFO_OBJECT (ogg, " chain %d (%u streams):", i, chain->streams->len);
|
||||||
GST_INFO_OBJECT (ogg, " offset: %" G_GINT64_FORMAT " - %" G_GINT64_FORMAT,
|
GST_INFO_OBJECT (ogg, " offset: %" G_GINT64_FORMAT " - %" G_GINT64_FORMAT,
|
||||||
chain->offset, chain->end_offset);
|
chain->offset, chain->end_offset);
|
||||||
|
GST_INFO_OBJECT (ogg, " start time: %" GST_TIME_FORMAT,
|
||||||
|
GST_TIME_ARGS (chain->start_time));
|
||||||
GST_INFO_OBJECT (ogg, " total time: %" GST_TIME_FORMAT,
|
GST_INFO_OBJECT (ogg, " total time: %" GST_TIME_FORMAT,
|
||||||
GST_TIME_ARGS (chain->total_time));
|
GST_TIME_ARGS (chain->total_time));
|
||||||
|
GST_INFO_OBJECT (ogg, " begin time: %" GST_TIME_FORMAT,
|
||||||
|
GST_TIME_ARGS (chain->begin_time));
|
||||||
|
|
||||||
for (j = 0; j < chain->streams->len; j++) {
|
for (j = 0; j < chain->streams->len; j++) {
|
||||||
GstOggPad *stream = g_array_index (chain->streams, GstOggPad *, j);
|
GstOggPad *stream = g_array_index (chain->streams, GstOggPad *, j);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user