mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-27 20:21:24 +00:00
ext/ogg/gstoggdemux.c: Generate correct disconts for live chained oggs.
Original commit message from CVS: * ext/ogg/gstoggdemux.c: (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_activate_chain), (gst_ogg_demux_perform_seek), (gst_ogg_demux_collect_chain_info), (gst_ogg_demux_collect_info), (gst_ogg_demux_chain), (gst_ogg_demux_send_event), (gst_ogg_demux_loop): Generate correct disconts for live chained oggs. * gst-libs/gst/audio/gstbaseaudiosink.c: (gst_base_audio_sink_render), (gst_base_audio_sink_create_ringbuffer), (gst_base_audio_sink_change_state): Handle discont math correctly. * gst/playback/gstplaybin.c: (add_sink): Some small debug cleanup.
This commit is contained in:
parent
f314343058
commit
e2da9961d9
4 changed files with 140 additions and 57 deletions
22
ChangeLog
22
ChangeLog
|
@ -1,3 +1,25 @@
|
|||
2005-07-21 Wim Taymans <wim@fluendo.com>
|
||||
|
||||
* ext/ogg/gstoggdemux.c: (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_activate_chain),
|
||||
(gst_ogg_demux_perform_seek), (gst_ogg_demux_collect_chain_info),
|
||||
(gst_ogg_demux_collect_info), (gst_ogg_demux_chain),
|
||||
(gst_ogg_demux_send_event), (gst_ogg_demux_loop):
|
||||
Generate correct disconts for live chained oggs.
|
||||
|
||||
* gst-libs/gst/audio/gstbaseaudiosink.c:
|
||||
(gst_base_audio_sink_render),
|
||||
(gst_base_audio_sink_create_ringbuffer),
|
||||
(gst_base_audio_sink_change_state):
|
||||
Handle discont math correctly.
|
||||
|
||||
* gst/playback/gstplaybin.c: (add_sink):
|
||||
Some small debug cleanup.
|
||||
|
||||
2005-07-21 Wim Taymans <wim@fluendo.com>
|
||||
|
||||
* ext/ogg/gstoggdemux.c: (gst_ogg_pad_init), (gst_ogg_pad_event),
|
||||
|
|
|
@ -131,12 +131,6 @@ struct _GstOggPadClass
|
|||
PARENTCLASS parent_class;
|
||||
};
|
||||
|
||||
typedef enum
|
||||
{
|
||||
OGG_STATE_NEW_CHAIN,
|
||||
OGG_STATE_STREAMING,
|
||||
} OggState;
|
||||
|
||||
#define GST_CHAIN_LOCK(ogg) g_mutex_lock((ogg)->chain_lock)
|
||||
#define GST_CHAIN_UNLOCK(ogg) g_mutex_unlock((ogg)->chain_lock)
|
||||
|
||||
|
@ -149,7 +143,6 @@ struct _GstOggDemux
|
|||
gint64 length;
|
||||
gint64 offset;
|
||||
|
||||
OggState state;
|
||||
gboolean seekable;
|
||||
gboolean running;
|
||||
|
||||
|
@ -169,6 +162,9 @@ struct _GstOggDemux
|
|||
GstClockTime segment_stop;
|
||||
gboolean segment_play;
|
||||
|
||||
gint64 current_granule;
|
||||
GstClockTime current_time;
|
||||
|
||||
/* ogg stuff */
|
||||
ogg_sync_state sync;
|
||||
};
|
||||
|
@ -529,16 +525,20 @@ static GstFlowReturn
|
|||
gst_ogg_pad_internal_chain (GstPad * pad, GstBuffer * buffer)
|
||||
{
|
||||
GstOggPad *oggpad;
|
||||
GstOggDemux *ogg;
|
||||
GstClockTime timestamp;
|
||||
|
||||
oggpad = gst_pad_get_element_private (pad);
|
||||
ogg = GST_OGG_DEMUX (oggpad->ogg);
|
||||
|
||||
timestamp = GST_BUFFER_TIMESTAMP (buffer);
|
||||
GST_DEBUG_OBJECT (oggpad, "received buffer from iternal pad, TS=%lld",
|
||||
timestamp);
|
||||
|
||||
if (oggpad->start_time == GST_CLOCK_TIME_NONE)
|
||||
if (oggpad->start_time == GST_CLOCK_TIME_NONE) {
|
||||
oggpad->start_time = timestamp;
|
||||
ogg->current_time = timestamp;
|
||||
}
|
||||
|
||||
gst_buffer_unref (buffer);
|
||||
|
||||
|
@ -701,6 +701,21 @@ gst_ogg_demux_chain_peer (GstOggPad * pad, ogg_packet * packet)
|
|||
GST_BUFFER_OFFSET_END (buf) = packet->granulepos;
|
||||
|
||||
ret = gst_pad_push (GST_PAD (pad), buf);
|
||||
|
||||
if (packet->granulepos != -1) {
|
||||
GstFormat format;
|
||||
|
||||
ogg->current_granule = packet->granulepos;
|
||||
format = GST_FORMAT_TIME;
|
||||
if (!gst_pad_query_convert (pad->elem_pad,
|
||||
GST_FORMAT_DEFAULT, packet->granulepos, &format,
|
||||
(gint64 *) & ogg->current_time)) {
|
||||
g_warning ("could not convert granulepos to time");
|
||||
} else {
|
||||
GST_DEBUG ("ogg current time %" GST_TIME_FORMAT,
|
||||
GST_TIME_ARGS (ogg->current_time));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
GST_DEBUG_OBJECT (ogg,
|
||||
"%p could not get buffer from peer %08lx", pad, pad->serialno);
|
||||
|
@ -725,19 +740,21 @@ gst_ogg_pad_submit_packet (GstOggPad * pad, ogg_packet * packet)
|
|||
|
||||
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;
|
||||
}
|
||||
|
||||
granule = packet->granulepos;
|
||||
if (granule != -1) {
|
||||
ogg->current_granule = granule;
|
||||
pad->current_granule = granule;
|
||||
if (pad->first_granule == -1 && granule != 0) {
|
||||
pad->first_granule = granule;
|
||||
}
|
||||
}
|
||||
|
||||
/* no start time known, stream to internal plugin to
|
||||
* get time */
|
||||
if (pad->start_time == GST_CLOCK_TIME_NONE) {
|
||||
|
@ -747,17 +764,21 @@ gst_ogg_pad_submit_packet (GstOggPad * pad, ogg_packet * packet)
|
|||
* can activate the complete chain if this is a dynamic
|
||||
* chain. */
|
||||
if (pad->start_time != GST_CLOCK_TIME_NONE) {
|
||||
GstOggChain *chain = pad->chain;
|
||||
|
||||
/* check if complete chain has start time */
|
||||
if (pad->chain == ogg->building_chain) {
|
||||
if (gst_ogg_demux_collect_chain_info (ogg, pad->chain)) {
|
||||
if (chain == ogg->building_chain) {
|
||||
|
||||
/* see if we have enough info to activate the chain */
|
||||
if (gst_ogg_demux_collect_chain_info (ogg, 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_FORMAT_TIME, (gint64) chain->start_time - chain->begin_time,
|
||||
(gint64) chain->last_time - chain->begin_time, NULL);
|
||||
|
||||
gst_ogg_demux_activate_chain (ogg, pad->chain, event);
|
||||
gst_ogg_demux_activate_chain (ogg, chain, event);
|
||||
|
||||
ogg->building_chain = NULL;
|
||||
}
|
||||
|
@ -848,6 +869,7 @@ gst_ogg_chain_new (GstOggDemux * ogg)
|
|||
chain->bytes = -1;
|
||||
chain->have_bos = FALSE;
|
||||
chain->streams = g_array_new (FALSE, TRUE, sizeof (GstOggPad *));
|
||||
chain->begin_time = GST_CLOCK_TIME_NONE;
|
||||
chain->start_time = GST_CLOCK_TIME_NONE;
|
||||
chain->total_time = GST_CLOCK_TIME_NONE;
|
||||
|
||||
|
@ -1029,7 +1051,9 @@ gst_ogg_demux_init (GstOggDemux * ogg)
|
|||
|
||||
ogg->chain_lock = g_mutex_new ();
|
||||
ogg->chains = g_array_new (FALSE, TRUE, sizeof (GstOggChain *));
|
||||
ogg->state = OGG_STATE_NEW_CHAIN;
|
||||
|
||||
ogg->current_granule = -1;
|
||||
ogg->current_time = 0;
|
||||
|
||||
ogg->segment_start = GST_CLOCK_TIME_NONE;
|
||||
ogg->segment_stop = GST_CLOCK_TIME_NONE;
|
||||
|
@ -1287,9 +1311,6 @@ gst_ogg_demux_activate_chain (GstOggDemux * ogg, GstOggChain * chain,
|
|||
|
||||
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++) {
|
||||
GList *headers;
|
||||
|
@ -1512,36 +1533,30 @@ gst_ogg_demux_perform_seek (GstOggDemux * ogg, gboolean flush)
|
|||
|
||||
ogg->offset = best;
|
||||
|
||||
/* switch to different chain */
|
||||
if (chain != ogg->current_chain) {
|
||||
gst_ogg_demux_activate_chain (ogg, chain, NULL);
|
||||
}
|
||||
/* current time starts from 0 again after a flush */
|
||||
if (flush)
|
||||
ogg->current_time = 0;
|
||||
|
||||
/* now we have a new position, prepare for streaming again */
|
||||
{
|
||||
gint i;
|
||||
GstEvent *event;
|
||||
|
||||
/* we have to send the flush to the old chain, not the new one */
|
||||
if (flush)
|
||||
gst_ogg_demux_send_event (ogg, gst_event_new_flush (TRUE));
|
||||
|
||||
/* create the discont event we are going to send out */
|
||||
event = gst_event_new_discontinuous (1.0,
|
||||
GST_FORMAT_TIME, (gint64) ogg->segment_start,
|
||||
(gint64) ogg->segment_stop, NULL);
|
||||
|
||||
for (i = 0; i < ogg->chains->len; i++) {
|
||||
GstOggChain *chain = g_array_index (ogg->chains, GstOggChain *, i);
|
||||
gint j;
|
||||
|
||||
for (j = 0; j < chain->streams->len; j++) {
|
||||
GstOggPad *pad = g_array_index (chain->streams, GstOggPad *, j);
|
||||
|
||||
if (flush)
|
||||
gst_pad_push_event (GST_PAD (pad), gst_event_new_flush (TRUE));
|
||||
|
||||
/* and the discont */
|
||||
gst_event_ref (event);
|
||||
gst_pad_push_event (GST_PAD (pad), event);
|
||||
}
|
||||
if (chain != ogg->current_chain) {
|
||||
/* switch to different chain, send discont on new chain */
|
||||
gst_ogg_demux_activate_chain (ogg, chain, event);
|
||||
} else {
|
||||
/* send discont on old chain */
|
||||
gst_ogg_demux_send_event (ogg, event);
|
||||
}
|
||||
gst_event_unref (event);
|
||||
|
||||
/* notify start of new segment */
|
||||
if (ogg->segment_play) {
|
||||
|
@ -1987,6 +2002,7 @@ gst_ogg_demux_chain (GstPad * pad, GstBuffer * buffer)
|
|||
GstOggDemux *ogg;
|
||||
gint ret = -1;
|
||||
GstFlowReturn result = GST_FLOW_OK;
|
||||
guint serialno;
|
||||
|
||||
ogg = GST_OGG_DEMUX (GST_OBJECT_PARENT (pad));
|
||||
|
||||
|
@ -2004,14 +2020,14 @@ gst_ogg_demux_chain (GstPad * pad, GstBuffer * buffer)
|
|||
/* discontinuity in the pages */
|
||||
} else {
|
||||
GstOggPad *pad;
|
||||
guint serialno;
|
||||
gint64 granule;
|
||||
|
||||
serialno = ogg_page_serialno (&page);
|
||||
granule = ogg_page_granulepos (&page);
|
||||
|
||||
GST_LOG_OBJECT (ogg,
|
||||
"processing ogg page (serial %08lx, pageno %ld, granule pos %llu, bos %d)",
|
||||
serialno, ogg_page_pageno (&page),
|
||||
ogg_page_granulepos (&page), ogg_page_bos (&page));
|
||||
serialno, ogg_page_pageno (&page), granule, ogg_page_bos (&page));
|
||||
|
||||
if (ogg_page_bos (&page)) {
|
||||
GstOggChain *chain;
|
||||
|
@ -2024,16 +2040,40 @@ gst_ogg_demux_chain (GstPad * pad, GstBuffer * buffer)
|
|||
gst_ogg_demux_activate_chain (ogg, chain, NULL);
|
||||
pad = gst_ogg_demux_find_pad (ogg, serialno);
|
||||
} else {
|
||||
/* chain is unknown */
|
||||
if (ogg->state == OGG_STATE_STREAMING) {
|
||||
GstClockTime chain_time;
|
||||
GstOggChain *current_chain;
|
||||
|
||||
/* this can only happen in non-seekabe mode */
|
||||
if (ogg->seekable)
|
||||
goto unknown_chain;
|
||||
|
||||
current_chain = ogg->current_chain;
|
||||
if (current_chain) {
|
||||
GstClockTime duration;
|
||||
|
||||
/* this was the duration of the previous chain */
|
||||
duration = ogg->current_time - current_chain->start_time;
|
||||
/* the new chain time starts at duration + begin_time */
|
||||
chain_time = duration + current_chain->begin_time;
|
||||
|
||||
/* remove existing pads */
|
||||
gst_ogg_demux_deactivate_current_chain (ogg);
|
||||
/* switch to new-chain mode */
|
||||
ogg->state = OGG_STATE_NEW_CHAIN;
|
||||
} else {
|
||||
/* non previous chain, start at configured current time */
|
||||
chain_time = ogg->current_time;
|
||||
}
|
||||
if (ogg->building_chain == NULL) {
|
||||
ogg->building_chain = gst_ogg_chain_new (ogg);
|
||||
ogg->building_chain->offset = 0;
|
||||
GstOggChain *newchain;
|
||||
|
||||
newchain = gst_ogg_chain_new (ogg);
|
||||
newchain->offset = 0;
|
||||
/* set new chain begin time aligned with end time of old chain */
|
||||
newchain->begin_time = chain_time;
|
||||
GST_DEBUG ("new chain, begin time %" GST_TIME_FORMAT,
|
||||
GST_TIME_ARGS (chain_time));
|
||||
|
||||
/* and this is the one we are building now */
|
||||
ogg->building_chain = newchain;
|
||||
}
|
||||
pad = gst_ogg_chain_new_stream (ogg->building_chain, serialno);
|
||||
}
|
||||
|
@ -2043,12 +2083,31 @@ gst_ogg_demux_chain (GstPad * pad, GstBuffer * buffer)
|
|||
if (pad) {
|
||||
result = gst_ogg_pad_submit_page (pad, &page);
|
||||
} else {
|
||||
GST_LOG_OBJECT (ogg, "cannot find pad for serial %08lx", serialno);
|
||||
/* no pad, this is pretty fatal. This means an ogg page without bos
|
||||
* has been seen for this serialno. could just ignore it too... */
|
||||
goto unknown_pad;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
|
||||
unknown_chain:
|
||||
{
|
||||
GST_ELEMENT_ERROR (ogg, STREAM, DECODE,
|
||||
("unknown ogg chain for serial %08x detected", serialno),
|
||||
("unknown ogg chain for serial %08x detected", serialno));
|
||||
gst_ogg_demux_send_event (ogg, gst_event_new_eos ());
|
||||
return GST_FLOW_ERROR;
|
||||
}
|
||||
unknown_pad:
|
||||
{
|
||||
GST_ELEMENT_ERROR (ogg, STREAM, DECODE,
|
||||
("unknown ogg pad for serial %08d detected", serialno),
|
||||
("unknown ogg pad for serial %08d detected", serialno));
|
||||
gst_ogg_demux_send_event (ogg, gst_event_new_eos ());
|
||||
return GST_FLOW_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
|
@ -331,6 +331,7 @@ gst_base_audio_sink_render (GstBaseSink * bsink, GstBuffer * buf)
|
|||
{
|
||||
guint64 render_offset, in_offset;
|
||||
GstClockTime time, render_time;
|
||||
GstClockTimeDiff render_diff;
|
||||
GstBaseAudioSink *sink = GST_BASE_AUDIO_SINK (bsink);
|
||||
gint64 diff;
|
||||
|
||||
|
@ -344,15 +345,16 @@ gst_base_audio_sink_render (GstBaseSink * bsink, GstBuffer * buf)
|
|||
GST_DEBUG ("time %" GST_TIME_FORMAT ", offset %llu, start %" GST_TIME_FORMAT,
|
||||
GST_TIME_ARGS (time), in_offset, GST_TIME_ARGS (bsink->discont_start));
|
||||
|
||||
render_diff = time - bsink->discont_start;
|
||||
/* samples should be rendered based on their timestamp. All samples
|
||||
* arriving before the discont_start are to be thrown away */
|
||||
/* FIXME, for now we drop the sample completely, we should
|
||||
* in fact clip the sample. Same for the segment_stop, actually. */
|
||||
if (time < bsink->discont_start)
|
||||
if (render_diff < 0)
|
||||
return GST_FLOW_OK;
|
||||
|
||||
/* bring buffer timestamp to stream time */
|
||||
render_time = time - bsink->discont_start;
|
||||
render_time = render_diff;
|
||||
/* add base time to get absolute clock time */
|
||||
render_time += gst_element_get_base_time (GST_ELEMENT (bsink));
|
||||
/* and bring the time to the offset in the buffer */
|
||||
|
|
|
@ -729,7 +729,7 @@ add_sink (GstPlayBin * play_bin, GstElement * sink, GstPad * srcpad)
|
|||
/* this is only for debugging */
|
||||
parent = gst_pad_get_parent_element (srcpad);
|
||||
if (parent) {
|
||||
GST_DEBUG ("Adding sink with state %d (parent: %d, peer: %d)\n",
|
||||
GST_DEBUG ("Adding sink with state %d (parent: %d, peer: %d)",
|
||||
GST_STATE (sink), GST_STATE (play_bin), GST_STATE (parent));
|
||||
gst_object_unref (parent);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue