ext/ogg/gstoggdemux.c: Some cleanups.

Original commit message from CVS:
* ext/ogg/gstoggdemux.c: (gst_ogg_page_copy), (gst_ogg_page_free),
(gst_ogg_pad_init), (gst_ogg_pad_dispose), (gst_ogg_pad_reset),
(gst_ogg_pad_stream_out), (gst_ogg_pad_submit_page),
(gst_ogg_chain_reset), (gst_ogg_demux_perform_seek):
Some cleanups.
Handle continued pages in reverse mode.
This commit is contained in:
Wim Taymans 2006-11-24 15:40:58 +00:00
parent 22411eeb35
commit b8583561da
2 changed files with 157 additions and 28 deletions

View file

@ -1,3 +1,12 @@
2006-11-24 Wim Taymans <wim@fluendo.com>
* ext/ogg/gstoggdemux.c: (gst_ogg_page_copy), (gst_ogg_page_free),
(gst_ogg_pad_init), (gst_ogg_pad_dispose), (gst_ogg_pad_reset),
(gst_ogg_pad_stream_out), (gst_ogg_pad_submit_page),
(gst_ogg_chain_reset), (gst_ogg_demux_perform_seek):
Some cleanups.
Handle continued pages in reverse mode.
2006-11-24 Wim Taymans <wim@fluendo.com>
* ext/vorbis/vorbisdec.c: (vorbis_dec_push_forward),

View file

@ -51,6 +51,28 @@ GST_DEBUG_CATEGORY_STATIC (gst_ogg_demux_debug);
GST_DEBUG_CATEGORY_STATIC (gst_ogg_demux_setup_debug);
#define GST_CAT_DEFAULT gst_ogg_demux_debug
static ogg_page *
gst_ogg_page_copy (ogg_page * page)
{
ogg_page *p = g_new0 (ogg_page, 1);
/* make a copy of the page */
p->header = g_memdup (page->header, page->header_len);
p->header_len = page->header_len;
p->body = g_memdup (page->body, page->body_len);
p->body_len = page->body_len;
return p;
}
static void
gst_ogg_page_free (ogg_page * page)
{
g_free (page->header);
g_free (page->body);
g_free (page);
}
#define GST_TYPE_OGG_PAD (gst_ogg_pad_get_type())
#define GST_OGG_PAD(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_OGG_PAD, GstOggPad))
#define GST_OGG_PAD_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_OGG_PAD, GstOggPad))
@ -138,6 +160,7 @@ struct _GstOggPad
GstClockTime first_time; /* the timestamp of the second page or granuletime of first page */
ogg_stream_state stream;
GList *continued;
gboolean discont;
GstFlowReturn last_ret; /* last return of _pad_push() */
@ -301,6 +324,7 @@ gst_ogg_pad_init (GstOggPad * pad)
pad->first_time = GST_CLOCK_TIME_NONE;
pad->have_type = FALSE;
pad->continued = NULL;
pad->headers = NULL;
}
@ -329,6 +353,11 @@ gst_ogg_pad_dispose (GObject * object)
g_list_free (pad->headers);
pad->headers = NULL;
/* clear continued pages */
g_list_foreach (pad->continued, (GFunc) gst_ogg_page_free, NULL);
g_list_free (pad->continued);
pad->continued = NULL;
ogg_stream_reset (&pad->stream);
G_OBJECT_CLASS (ogg_pad_parent_class)->dispose (object);
@ -535,7 +564,13 @@ static void
gst_ogg_pad_reset (GstOggPad * pad)
{
ogg_stream_reset (&pad->stream);
/* FIXME: need a discont here */
/* clear continued pages */
g_list_foreach (pad->continued, (GFunc) gst_ogg_page_free, NULL);
g_list_free (pad->continued);
pad->continued = NULL;
pad->last_ret = GST_FLOW_OK;
}
/* the filter function for selecting the elements we can use in
@ -1176,27 +1211,22 @@ gst_ogg_pad_submit_packet (GstOggPad * pad, ogg_packet * packet)
return ret;
}
/* submit a page to an oggpad, this function will then submit all
* the packets in the page.
/* flush at most @npackets from the stream layer. All packets if
* @npackets is 0;
*/
static GstFlowReturn
gst_ogg_pad_submit_page (GstOggPad * pad, ogg_page * page)
gst_ogg_pad_stream_out (GstOggPad * pad, gint npackets)
{
ogg_packet packet;
int ret;
gboolean done = FALSE;
GstFlowReturn result = GST_FLOW_OK;
gboolean done = FALSE;
GstOggDemux *ogg;
ogg = GST_OGG_DEMUX (GST_PAD_PARENT (pad));
if (ogg_stream_pagein (&pad->stream, page) != 0)
goto choked;
if (ogg_page_continued (page))
GST_LOG_OBJECT (ogg, "have continued page");
ogg = pad->ogg;
while (!done) {
int ret;
ogg_packet packet;
ret = ogg_stream_packetout (&pad->stream, &packet);
switch (ret) {
case 0:
@ -1220,9 +1250,100 @@ gst_ogg_pad_submit_page (GstOggPad * pad, ogg_page * page)
gst_ogg_pad_reset (pad);
break;
}
if (npackets > 0) {
npackets--;
done = (npackets == 0);
}
}
return result;
/* ERRORS */
could_not_submit:
{
GST_WARNING_OBJECT (ogg,
"could not submit packet for stream %08x, error: %d", pad->serialno,
result);
gst_ogg_pad_reset (pad);
return result;
}
}
/* submit a page to an oggpad, this function will then submit all
* the packets in the page.
*/
static GstFlowReturn
gst_ogg_pad_submit_page (GstOggPad * pad, ogg_page * page)
{
GstFlowReturn result = GST_FLOW_OK;
GstOggDemux *ogg;
gboolean continued = FALSE;
ogg = pad->ogg;
if (ogg->segment.rate < 0.0) {
gint npackets;
continued = ogg_page_continued (page);
/* number of completed packets in the page */
npackets = ogg_page_packets (page);
if (!continued) {
/* page is not continued so it contains at least one packet start */
if (npackets == 0)
npackets = 1;
}
GST_LOG_OBJECT (ogg, "continued: %d, %d packets", continued, npackets);
if (npackets == 0) {
GST_LOG_OBJECT (ogg, "no decodable packets, we need a previous page");
goto done;
}
}
if (ogg_stream_pagein (&pad->stream, page) != 0)
goto choked;
/* flush all packets in the stream layer */
result = gst_ogg_pad_stream_out (pad, 0);
if (pad->continued) {
ogg_packet packet;
/* now send the continued pages to the stream layer */
while (pad->continued) {
ogg_page *p = (ogg_page *) pad->continued->data;
GST_LOG_OBJECT (ogg, "submitting continued page %p", p);
if (ogg_stream_pagein (&pad->stream, p) != 0)
goto choked;
pad->continued = g_list_delete_link (pad->continued, pad->continued);
/* free the page */
gst_ogg_page_free (p);
}
GST_LOG_OBJECT (ogg, "flushing last continued packet");
/* flush 1 continued packet in the stream layer */
result = gst_ogg_pad_stream_out (pad, 1);
/* flush all remaining packets, we pushed them in the previous round.
* We don't use _reset() because we still want to get the discont when
* we submit a next page. */
while (ogg_stream_packetout (&pad->stream, &packet) != 0);
}
done:
/* keep continued pages (only in reverse mode) */
if (continued) {
ogg_page *p = gst_ogg_page_copy (page);
GST_LOG_OBJECT (ogg, "keeping continued page %p", p);
pad->continued = g_list_prepend (pad->continued, p);
}
return result;
choked:
{
GST_WARNING_OBJECT (ogg,
@ -1232,14 +1353,6 @@ choked:
/* we continue to recover */
return GST_FLOW_OK;
}
could_not_submit:
{
GST_WARNING_OBJECT (ogg,
"could not submit packet for stream %08x, error: %d", pad->serialno,
result);
gst_ogg_pad_reset (pad);
return result;
}
}
@ -1288,6 +1401,18 @@ gst_ogg_chain_mark_discont (GstOggChain * chain)
}
}
static void
gst_ogg_chain_reset (GstOggChain * chain)
{
gint i;
for (i = 0; i < chain->streams->len; i++) {
GstOggPad *pad = g_array_index (chain->streams, GstOggPad *, i);
gst_ogg_pad_reset (pad);
}
}
static GstOggPad *
gst_ogg_chain_new_stream (GstOggChain * chain, glong serialno)
{
@ -2072,13 +2197,8 @@ gst_ogg_demux_perform_seek (GstOggDemux * ogg, GstEvent * event)
* make sure the streaming thread is not messing with the stream */
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);
ogg_stream_reset (&pad->stream);
}
gst_ogg_chain_reset (chain);
}
}