mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-04-26 06:54:49 +00:00
ext/ogg/: Ported ogg muxer.
Original commit message from CVS: * ext/ogg/Makefile.am: * ext/ogg/README: * ext/ogg/gstoggdemux.c: (gst_ogg_pad_typefind), (gst_ogg_pad_submit_packet), (gst_ogg_demux_sink_activate), (gst_ogg_print): * ext/ogg/gstoggmux.c: (gst_ogg_mux_init), (gst_ogg_mux_request_new_pad), (gst_ogg_mux_next_buffer), (gst_ogg_mux_push_page), (gst_ogg_mux_queue_pads), (gst_ogg_mux_get_headers), (gst_ogg_mux_set_header_on_caps), (gst_ogg_mux_send_headers), (gst_ogg_mux_collected), (gst_ogg_mux_change_state): Ported ogg muxer.
This commit is contained in:
parent
658bd2cac6
commit
59241d5e74
5 changed files with 235 additions and 156 deletions
15
ChangeLog
15
ChangeLog
|
@ -1,3 +1,18 @@
|
||||||
|
2005-05-05 Wim Taymans <wim@fluendo.com>
|
||||||
|
|
||||||
|
* ext/ogg/Makefile.am:
|
||||||
|
* ext/ogg/README:
|
||||||
|
* ext/ogg/gstoggdemux.c: (gst_ogg_pad_typefind),
|
||||||
|
(gst_ogg_pad_submit_packet), (gst_ogg_demux_sink_activate),
|
||||||
|
(gst_ogg_print):
|
||||||
|
* ext/ogg/gstoggmux.c: (gst_ogg_mux_init),
|
||||||
|
(gst_ogg_mux_request_new_pad), (gst_ogg_mux_next_buffer),
|
||||||
|
(gst_ogg_mux_push_page), (gst_ogg_mux_queue_pads),
|
||||||
|
(gst_ogg_mux_get_headers), (gst_ogg_mux_set_header_on_caps),
|
||||||
|
(gst_ogg_mux_send_headers), (gst_ogg_mux_collected),
|
||||||
|
(gst_ogg_mux_change_state):
|
||||||
|
Ported ogg muxer.
|
||||||
|
|
||||||
2005-05-05 Wim Taymans <wim@fluendo.com>
|
2005-05-05 Wim Taymans <wim@fluendo.com>
|
||||||
|
|
||||||
* docs/design-audiosinks.txt:
|
* docs/design-audiosinks.txt:
|
||||||
|
|
|
@ -10,6 +10,6 @@ libgstogg_la_SOURCES = \
|
||||||
|
|
||||||
libgstogg_la_CFLAGS = $(GST_CFLAGS) $(OGG_CFLAGS)
|
libgstogg_la_CFLAGS = $(GST_CFLAGS) $(OGG_CFLAGS)
|
||||||
libgstogg_la_LIBADD = $(OGG_LIBS) \
|
libgstogg_la_LIBADD = $(OGG_LIBS) \
|
||||||
$(top_builddir)/gst-libs/gst/riff/libgstriff-@GST_MAJORMINOR@.la
|
$(top_builddir)/gst-libs/gst/riff/libgstriff-@GST_MAJORMINOR@.la $(GST_BASE_LIBS)
|
||||||
libgstogg_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)
|
libgstogg_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)
|
||||||
|
|
||||||
|
|
|
@ -125,6 +125,8 @@ unique correct timestamp and a framenumber.
|
||||||
|
|
||||||
in a raw theroa stream we use the granulepos as the offset field.
|
in a raw theroa stream we use the granulepos as the offset field.
|
||||||
|
|
||||||
|
The granulepos of an ogg page is the framenumber of the last frame in the page.
|
||||||
|
|
||||||
|
|
||||||
vorbis and granulepos
|
vorbis and granulepos
|
||||||
---------------------
|
---------------------
|
||||||
|
@ -134,6 +136,8 @@ from granulepos is therefore easy.
|
||||||
|
|
||||||
in a raw vorbis stream we use the granulepos as the offset field.
|
in a raw vorbis stream we use the granulepos as the offset field.
|
||||||
|
|
||||||
|
The granulepos of an ogg page is the sample number of the next page in the ogg stream.
|
||||||
|
|
||||||
|
|
||||||
What can ogg do?
|
What can ogg do?
|
||||||
----------------
|
----------------
|
||||||
|
@ -183,4 +187,3 @@ TODO
|
||||||
|
|
||||||
- use the OFFSET field in the GstBuffer to store/read the granulepos as
|
- use the OFFSET field in the GstBuffer to store/read the granulepos as
|
||||||
opposed to the OFFSET_END field.
|
opposed to the OFFSET_END field.
|
||||||
- Seeking should be implemented with a binary search.
|
|
||||||
|
|
|
@ -703,6 +703,9 @@ gst_ogg_pad_submit_packet (GstOggPad * pad, ogg_packet * packet)
|
||||||
ret = GST_RPAD_CHAINFUNC (pad->elem_pad) (pad->elem_pad, buf);
|
ret = GST_RPAD_CHAINFUNC (pad->elem_pad) (pad->elem_pad, buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
done:
|
||||||
|
#endif
|
||||||
pad->packetno++;
|
pad->packetno++;
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -1975,7 +1978,7 @@ gst_ogg_demux_sink_activate (GstPad * sinkpad, GstActivateMode mode)
|
||||||
ogg->seekable = FALSE;
|
ogg->seekable = FALSE;
|
||||||
result = TRUE;
|
result = TRUE;
|
||||||
break;
|
break;
|
||||||
case GST_ACTIVATE_PULL:
|
case GST_ACTIVATE_PULL_RANGE:
|
||||||
/* if we have a scheduler we can start the task */
|
/* if we have a scheduler we can start the task */
|
||||||
if (GST_ELEMENT_SCHEDULER (ogg)) {
|
if (GST_ELEMENT_SCHEDULER (ogg)) {
|
||||||
gst_pad_peer_set_active (sinkpad, mode);
|
gst_pad_peer_set_active (sinkpad, mode);
|
||||||
|
@ -2007,6 +2010,9 @@ gst_ogg_demux_sink_activate (GstPad * sinkpad, GstActivateMode mode)
|
||||||
|
|
||||||
result = TRUE;
|
result = TRUE;
|
||||||
break;
|
break;
|
||||||
|
case GST_ACTIVATE_PULL:
|
||||||
|
result = FALSE;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -2142,7 +2148,7 @@ 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, 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++) {
|
||||||
|
@ -2158,17 +2164,17 @@ gst_ogg_print (GstOggDemux * ogg)
|
||||||
GstOggPad *stream = g_array_index (chain->streams, GstOggPad *, j);
|
GstOggPad *stream = g_array_index (chain->streams, GstOggPad *, j);
|
||||||
|
|
||||||
GST_INFO_OBJECT (ogg, " stream %08lx:", stream->serialno);
|
GST_INFO_OBJECT (ogg, " stream %08lx:", stream->serialno);
|
||||||
GST_INFO_OBJECT (ogg, " start time %" GST_TIME_FORMAT ":",
|
GST_INFO_OBJECT (ogg, " start time: %" GST_TIME_FORMAT,
|
||||||
GST_TIME_ARGS (stream->start_time));
|
GST_TIME_ARGS (stream->start_time));
|
||||||
GST_INFO_OBJECT (ogg, " first granulepos %" G_GINT64_FORMAT ":",
|
GST_INFO_OBJECT (ogg, " first granulepos: %" G_GINT64_FORMAT,
|
||||||
stream->first_granule);
|
stream->first_granule);
|
||||||
GST_INFO_OBJECT (ogg, " first time %" GST_TIME_FORMAT ":",
|
GST_INFO_OBJECT (ogg, " first time: %" GST_TIME_FORMAT,
|
||||||
GST_TIME_ARGS (stream->first_time));
|
GST_TIME_ARGS (stream->first_time));
|
||||||
GST_INFO_OBJECT (ogg, " last granulepos %" G_GINT64_FORMAT ":",
|
GST_INFO_OBJECT (ogg, " last granulepos: %" G_GINT64_FORMAT,
|
||||||
stream->last_granule);
|
stream->last_granule);
|
||||||
GST_INFO_OBJECT (ogg, " last time %" GST_TIME_FORMAT ":",
|
GST_INFO_OBJECT (ogg, " last time: %" GST_TIME_FORMAT,
|
||||||
GST_TIME_ARGS (stream->last_time));
|
GST_TIME_ARGS (stream->last_time));
|
||||||
GST_INFO_OBJECT (ogg, " total time %" GST_TIME_FORMAT ":",
|
GST_INFO_OBJECT (ogg, " total time: %" GST_TIME_FORMAT,
|
||||||
GST_TIME_ARGS (stream->total_time));
|
GST_TIME_ARGS (stream->total_time));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,6 +22,8 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <gst/gst.h>
|
#include <gst/gst.h>
|
||||||
|
#include <gst/base/gstcollectpads.h>
|
||||||
|
|
||||||
#include <ogg/ogg.h>
|
#include <ogg/ogg.h>
|
||||||
/* memcpy - if someone knows a way to get rid of it, please speak up
|
/* memcpy - if someone knows a way to get rid of it, please speak up
|
||||||
* note: the ogg docs even say you need this... */
|
* note: the ogg docs even say you need this... */
|
||||||
|
@ -40,10 +42,17 @@ GST_DEBUG_CATEGORY_STATIC (gst_ogg_mux_debug);
|
||||||
typedef struct _GstOggMux GstOggMux;
|
typedef struct _GstOggMux GstOggMux;
|
||||||
typedef struct _GstOggMuxClass GstOggMuxClass;
|
typedef struct _GstOggMuxClass GstOggMuxClass;
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
GST_OGG_PAD_STATE_CONTROL = 0,
|
||||||
|
GST_OGG_PAD_STATE_DATA = 1
|
||||||
|
}
|
||||||
|
GstOggPadState;
|
||||||
|
|
||||||
/* all information needed for one ogg stream */
|
/* all information needed for one ogg stream */
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
GstPad *pad; /* reference for this pad is held by element we belong to */
|
GstCollectData collect; /* we extend the CollectData */
|
||||||
|
|
||||||
GstBuffer *buffer; /* the queued buffer for this pad */
|
GstBuffer *buffer; /* the queued buffer for this pad */
|
||||||
|
|
||||||
|
@ -55,7 +64,7 @@ typedef struct
|
||||||
gboolean eos;
|
gboolean eos;
|
||||||
gint64 offset;
|
gint64 offset;
|
||||||
|
|
||||||
guint state; /* state of the pad */
|
GstOggPadState state; /* state of the pad */
|
||||||
|
|
||||||
GList *headers;
|
GList *headers;
|
||||||
|
|
||||||
|
@ -65,24 +74,17 @@ typedef struct
|
||||||
}
|
}
|
||||||
GstOggPad;
|
GstOggPad;
|
||||||
|
|
||||||
typedef enum
|
|
||||||
{
|
|
||||||
GST_OGG_PAD_STATE_CONTROL = 0,
|
|
||||||
GST_OGG_PAD_STATE_DATA = 1
|
|
||||||
}
|
|
||||||
GstOggPadState;
|
|
||||||
|
|
||||||
struct _GstOggMux
|
struct _GstOggMux
|
||||||
{
|
{
|
||||||
GstElement element;
|
GstElement element;
|
||||||
|
|
||||||
/* pad */
|
/* source pad */
|
||||||
GstPad *srcpad;
|
GstPad *srcpad;
|
||||||
|
|
||||||
/* sinkpads, a GSList of GstOggPads */
|
/* sinkpads */
|
||||||
GSList *sinkpads;
|
GstCollectPads *collect;
|
||||||
|
|
||||||
/* the pad we are currently pulling from to fill a page */
|
/* the pad we are currently using to fill a page */
|
||||||
GstOggPad *pulling;
|
GstOggPad *pulling;
|
||||||
|
|
||||||
/* next timestamp for the page */
|
/* next timestamp for the page */
|
||||||
|
@ -128,9 +130,9 @@ enum
|
||||||
LAST_SIGNAL
|
LAST_SIGNAL
|
||||||
};
|
};
|
||||||
|
|
||||||
/* set to 5 seconds by default */
|
/* set to 0.5 seconds by default */
|
||||||
#define DEFAULT_MAX_DELAY 5000000000LL
|
#define DEFAULT_MAX_DELAY 500000000LL
|
||||||
#define DEFAULT_MAX_PAGE_DELAY 5000000000LL
|
#define DEFAULT_MAX_PAGE_DELAY 500000000LL
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
ARG_0,
|
ARG_0,
|
||||||
|
@ -156,7 +158,8 @@ static void gst_ogg_mux_base_init (gpointer g_class);
|
||||||
static void gst_ogg_mux_class_init (GstOggMuxClass * klass);
|
static void gst_ogg_mux_class_init (GstOggMuxClass * klass);
|
||||||
static void gst_ogg_mux_init (GstOggMux * ogg_mux);
|
static void gst_ogg_mux_init (GstOggMux * ogg_mux);
|
||||||
|
|
||||||
static void gst_ogg_mux_loop (GstElement * element);
|
static GstFlowReturn
|
||||||
|
gst_ogg_mux_collected (GstCollectPads * pads, GstOggMux * ogg_mux);
|
||||||
static gboolean gst_ogg_mux_handle_src_event (GstPad * pad, GstEvent * event);
|
static gboolean gst_ogg_mux_handle_src_event (GstPad * pad, GstEvent * event);
|
||||||
static GstPad *gst_ogg_mux_request_new_pad (GstElement * element,
|
static GstPad *gst_ogg_mux_request_new_pad (GstElement * element,
|
||||||
GstPadTemplate * templ, const gchar * name);
|
GstPadTemplate * templ, const gchar * name);
|
||||||
|
@ -265,16 +268,15 @@ gst_ogg_mux_init (GstOggMux * ogg_mux)
|
||||||
/* seed random number generator for creation of serial numbers */
|
/* seed random number generator for creation of serial numbers */
|
||||||
srand (time (NULL));
|
srand (time (NULL));
|
||||||
|
|
||||||
ogg_mux->sinkpads = NULL;
|
ogg_mux->collect = gst_collectpads_new ();
|
||||||
|
gst_collectpads_set_function (ogg_mux->collect,
|
||||||
|
(GstCollectPadsFunction) gst_ogg_mux_collected, ogg_mux);
|
||||||
ogg_mux->pulling = NULL;
|
ogg_mux->pulling = NULL;
|
||||||
ogg_mux->need_headers = TRUE;
|
ogg_mux->need_headers = TRUE;
|
||||||
ogg_mux->max_delay = DEFAULT_MAX_DELAY;
|
ogg_mux->max_delay = DEFAULT_MAX_DELAY;
|
||||||
ogg_mux->max_page_delay = DEFAULT_MAX_PAGE_DELAY;
|
ogg_mux->max_page_delay = DEFAULT_MAX_PAGE_DELAY;
|
||||||
|
|
||||||
ogg_mux->delta_pad = NULL;
|
ogg_mux->delta_pad = NULL;
|
||||||
|
|
||||||
//gst_element_set_loop_function (GST_ELEMENT (ogg_mux), gst_ogg_mux_loop);
|
|
||||||
gst_ogg_mux_loop (GST_ELEMENT (ogg_mux));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static GstPadLinkReturn
|
static GstPadLinkReturn
|
||||||
|
@ -290,42 +292,28 @@ gst_ogg_mux_sinkconnect (GstPad * pad, GstPad * peer)
|
||||||
return GST_PAD_LINK_OK;
|
return GST_PAD_LINK_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
gst_ogg_mux_pad_link (GstPad * pad, GstPad * peer, gpointer data)
|
|
||||||
{
|
|
||||||
GstOggMux *ogg_mux = ogg_mux = GST_OGG_MUX (gst_pad_get_parent (pad));
|
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (ogg_mux, "pad '%s' connected", gst_pad_get_name (pad));
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
gst_ogg_mux_pad_unlink (GstPad * pad, GstPad * peer, gpointer data)
|
|
||||||
{
|
|
||||||
GstOggMux *ogg_mux = ogg_mux = GST_OGG_MUX (gst_pad_get_parent (pad));
|
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (ogg_mux, "pad '%s' unlinked", gst_pad_get_name (pad));
|
|
||||||
}
|
|
||||||
|
|
||||||
static GstPad *
|
static GstPad *
|
||||||
gst_ogg_mux_request_new_pad (GstElement * element,
|
gst_ogg_mux_request_new_pad (GstElement * element,
|
||||||
GstPadTemplate * templ, const gchar * req_name)
|
GstPadTemplate * templ, const gchar * req_name)
|
||||||
{
|
{
|
||||||
GstOggMux *ogg_mux;
|
GstOggMux *ogg_mux;
|
||||||
GstPad *newpad;
|
GstPad *newpad;
|
||||||
GstElementClass *klass = GST_ELEMENT_GET_CLASS (element);
|
GstElementClass *klass;
|
||||||
|
|
||||||
g_return_val_if_fail (templ != NULL, NULL);
|
g_return_val_if_fail (templ != NULL, NULL);
|
||||||
|
|
||||||
if (templ->direction != GST_PAD_SINK) {
|
if (templ->direction != GST_PAD_SINK)
|
||||||
g_warning ("ogg_mux: request pad that is not a SINK pad\n");
|
goto wrong_direction;
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
g_return_val_if_fail (GST_IS_OGG_MUX (element), NULL);
|
g_return_val_if_fail (GST_IS_OGG_MUX (element), NULL);
|
||||||
|
|
||||||
ogg_mux = GST_OGG_MUX (element);
|
ogg_mux = GST_OGG_MUX (element);
|
||||||
|
|
||||||
if (templ == gst_element_class_get_pad_template (klass, "sink_%d")) {
|
klass = GST_ELEMENT_GET_CLASS (element);
|
||||||
|
|
||||||
|
if (templ != gst_element_class_get_pad_template (klass, "sink_%d"))
|
||||||
|
goto wrong_template;
|
||||||
|
|
||||||
|
{
|
||||||
gint serial;
|
gint serial;
|
||||||
gchar *name;
|
gchar *name;
|
||||||
|
|
||||||
|
@ -344,9 +332,12 @@ gst_ogg_mux_request_new_pad (GstElement * element,
|
||||||
/* construct our own wrapper data structure for the pad to
|
/* construct our own wrapper data structure for the pad to
|
||||||
* keep track of its status */
|
* keep track of its status */
|
||||||
{
|
{
|
||||||
GstOggPad *oggpad = g_new0 (GstOggPad, 1);
|
GstOggPad *oggpad;
|
||||||
|
|
||||||
|
oggpad = (GstOggPad *)
|
||||||
|
gst_collectpads_add_pad (ogg_mux->collect, newpad,
|
||||||
|
sizeof (GstOggPad));
|
||||||
|
|
||||||
oggpad->pad = newpad;
|
|
||||||
oggpad->serial = serial;
|
oggpad->serial = serial;
|
||||||
ogg_stream_init (&oggpad->stream, serial);
|
ogg_stream_init (&oggpad->stream, serial);
|
||||||
oggpad->packetno = 0;
|
oggpad->packetno = 0;
|
||||||
|
@ -357,22 +348,9 @@ gst_ogg_mux_request_new_pad (GstElement * element,
|
||||||
oggpad->new_page = TRUE;
|
oggpad->new_page = TRUE;
|
||||||
oggpad->first_delta = FALSE;
|
oggpad->first_delta = FALSE;
|
||||||
oggpad->prev_delta = FALSE;
|
oggpad->prev_delta = FALSE;
|
||||||
|
|
||||||
/* save a pointer to our data in the pad */
|
|
||||||
gst_pad_set_element_private (newpad, oggpad);
|
|
||||||
/* store our data for the pad */
|
|
||||||
ogg_mux->sinkpads = g_slist_prepend (ogg_mux->sinkpads, oggpad);
|
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
g_warning ("ogg_mux: this is not our template!\n");
|
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
g_signal_connect (newpad, "linked",
|
|
||||||
G_CALLBACK (gst_ogg_mux_pad_link), (gpointer) ogg_mux);
|
|
||||||
g_signal_connect (newpad, "unlinked",
|
|
||||||
G_CALLBACK (gst_ogg_mux_pad_unlink), (gpointer) ogg_mux);
|
|
||||||
|
|
||||||
/* setup some pad functions */
|
/* setup some pad functions */
|
||||||
gst_pad_set_link_function (newpad, gst_ogg_mux_sinkconnect);
|
gst_pad_set_link_function (newpad, gst_ogg_mux_sinkconnect);
|
||||||
gst_pad_set_event_mask_function (newpad, gst_ogg_mux_get_sink_event_masks);
|
gst_pad_set_event_mask_function (newpad, gst_ogg_mux_get_sink_event_masks);
|
||||||
|
@ -380,6 +358,18 @@ gst_ogg_mux_request_new_pad (GstElement * element,
|
||||||
gst_element_add_pad (element, newpad);
|
gst_element_add_pad (element, newpad);
|
||||||
|
|
||||||
return newpad;
|
return newpad;
|
||||||
|
|
||||||
|
/* ERRORS */
|
||||||
|
wrong_direction:
|
||||||
|
{
|
||||||
|
g_warning ("ogg_mux: request pad that is not a SINK pad\n");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
wrong_template:
|
||||||
|
{
|
||||||
|
g_warning ("ogg_mux: this is not our template!\n");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* handle events */
|
/* handle events */
|
||||||
|
@ -404,6 +394,7 @@ gst_ogg_mux_handle_src_event (GstPad * pad, GstEvent * event)
|
||||||
return gst_pad_event_default (pad, event);
|
return gst_pad_event_default (pad, event);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
static GstBuffer *
|
static GstBuffer *
|
||||||
gst_ogg_mux_next_buffer (GstOggPad * pad, gboolean * interrupt)
|
gst_ogg_mux_next_buffer (GstOggPad * pad, gboolean * interrupt)
|
||||||
{
|
{
|
||||||
|
@ -473,6 +464,7 @@ gst_ogg_mux_next_buffer (GstOggPad * pad, gboolean * interrupt)
|
||||||
}
|
}
|
||||||
return GST_BUFFER (data);
|
return GST_BUFFER (data);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static GstBuffer *
|
static GstBuffer *
|
||||||
gst_ogg_mux_buffer_from_page (GstOggMux * mux, ogg_page * page, gboolean delta)
|
gst_ogg_mux_buffer_from_page (GstOggMux * mux, ogg_page * page, gboolean delta)
|
||||||
|
@ -497,14 +489,17 @@ gst_ogg_mux_buffer_from_page (GstOggMux * mux, ogg_page * page, gboolean delta)
|
||||||
return buffer;
|
return buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static GstFlowReturn
|
||||||
gst_ogg_mux_push_page (GstOggMux * mux, ogg_page * page, gboolean delta)
|
gst_ogg_mux_push_page (GstOggMux * mux, ogg_page * page, gboolean delta)
|
||||||
{
|
{
|
||||||
if (GST_PAD_IS_USABLE (mux->srcpad)) {
|
GstBuffer *buffer;
|
||||||
GstBuffer *buffer = gst_ogg_mux_buffer_from_page (mux, page, delta);
|
GstFlowReturn ret;
|
||||||
|
|
||||||
gst_pad_push (mux->srcpad, buffer);
|
buffer = gst_ogg_mux_buffer_from_page (mux, page, delta);
|
||||||
}
|
|
||||||
|
ret = gst_pad_push (mux->srcpad, buffer);
|
||||||
|
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -555,34 +550,50 @@ gst_ogg_mux_compare_pads (GstOggMux * ogg_mux, GstOggPad * old, GstOggPad * new)
|
||||||
/* make sure a buffer is queued on all pads, returns a pointer to an oggpad
|
/* make sure a buffer is queued on all pads, returns a pointer to an oggpad
|
||||||
* that holds the best buffer or NULL when no pad was usable */
|
* that holds the best buffer or NULL when no pad was usable */
|
||||||
static GstOggPad *
|
static GstOggPad *
|
||||||
gst_ogg_mux_queue_pads (GstOggMux * ogg_mux, gboolean * interrupt)
|
gst_ogg_mux_queue_pads (GstOggMux * ogg_mux)
|
||||||
{
|
{
|
||||||
GstOggPad *bestpad = NULL;
|
GstOggPad *bestpad = NULL;
|
||||||
GSList *walk;
|
GSList *walk;
|
||||||
|
|
||||||
/* try to make sure we have a buffer from each usable pad first */
|
/* try to make sure we have a buffer from each usable pad first */
|
||||||
walk = ogg_mux->sinkpads;
|
walk = ogg_mux->collect->data;
|
||||||
while (walk) {
|
while (walk) {
|
||||||
GstOggPad *pad = (GstOggPad *) walk->data;
|
GstOggPad *pad;
|
||||||
|
GstCollectData *data;
|
||||||
|
|
||||||
walk = walk->next;
|
data = (GstCollectData *) walk->data;
|
||||||
|
pad = (GstOggPad *) data;
|
||||||
|
|
||||||
if (pad->eos)
|
walk = g_slist_next (walk);
|
||||||
|
|
||||||
|
if (data->eos)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
/* try to get a new buffer for this pad if needed and possible */
|
/* try to get a new buffer for this pad if needed and possible */
|
||||||
if (pad->buffer == NULL && GST_PAD_IS_USABLE (pad->pad)) {
|
if (pad->buffer == NULL) {
|
||||||
pad->buffer = gst_ogg_mux_next_buffer (pad, interrupt);
|
GstBuffer *buf;
|
||||||
if (*interrupt)
|
gboolean incaps;
|
||||||
return NULL;
|
|
||||||
/* no next buffer, try another pad */
|
|
||||||
if (pad->buffer == NULL)
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* skip unusable pads */
|
buf = gst_collectpads_pop (ogg_mux->collect, data);
|
||||||
if (!GST_PAD_IS_USABLE (pad->pad))
|
|
||||||
continue;
|
incaps = GST_BUFFER_FLAG_IS_SET (buf, GST_BUFFER_IN_CAPS);
|
||||||
|
/* if we need headers */
|
||||||
|
if (pad->state == GST_OGG_PAD_STATE_CONTROL) {
|
||||||
|
/* and we have one */
|
||||||
|
if (incaps) {
|
||||||
|
GST_DEBUG ("muxer: got incaps buffer in control state, ignoring");
|
||||||
|
/* just ignore */
|
||||||
|
gst_buffer_unref (buf);
|
||||||
|
buf = NULL;
|
||||||
|
} else {
|
||||||
|
GST_DEBUG
|
||||||
|
("muxer: got data buffer in control state, switching to data mode");
|
||||||
|
/* this is a data buffer so switch to data state */
|
||||||
|
pad->state = GST_OGG_PAD_STATE_DATA;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pad->buffer = buf;
|
||||||
|
}
|
||||||
|
|
||||||
/* we should have a buffer now, see if it is the best pad to
|
/* we should have a buffer now, see if it is the best pad to
|
||||||
* pull on */
|
* pull on */
|
||||||
|
@ -602,45 +613,64 @@ gst_ogg_mux_get_headers (GstOggPad * pad)
|
||||||
GstOggMux *ogg_mux;
|
GstOggMux *ogg_mux;
|
||||||
GstStructure *structure;
|
GstStructure *structure;
|
||||||
const GstCaps *caps;
|
const GstCaps *caps;
|
||||||
|
GstPad *thepad;
|
||||||
|
|
||||||
ogg_mux = GST_OGG_MUX (gst_pad_get_parent (pad->pad));
|
thepad = pad->collect.pad;
|
||||||
|
|
||||||
GST_LOG ("getting headers from pad %s:%s", GST_DEBUG_PAD_NAME (pad->pad));
|
ogg_mux = GST_OGG_MUX (GST_PAD_PARENT (thepad));
|
||||||
|
|
||||||
caps = gst_pad_get_negotiated_caps (pad->pad);
|
GST_LOG ("getting headers from pad %s:%s", GST_DEBUG_PAD_NAME (thepad));
|
||||||
|
|
||||||
|
caps = gst_pad_get_negotiated_caps (thepad);
|
||||||
if (caps != NULL) {
|
if (caps != NULL) {
|
||||||
const GValue *streamheader;
|
const GValue *streamheader;
|
||||||
|
|
||||||
structure = gst_caps_get_structure (caps, 0);
|
structure = gst_caps_get_structure (caps, 0);
|
||||||
streamheader = gst_structure_get_value (structure, "streamheader");
|
streamheader = gst_structure_get_value (structure, "streamheader");
|
||||||
if (streamheader != NULL) {
|
if (streamheader != NULL) {
|
||||||
|
GST_LOG ("got header");
|
||||||
if (G_VALUE_TYPE (streamheader) == GST_TYPE_FIXED_LIST) {
|
if (G_VALUE_TYPE (streamheader) == GST_TYPE_FIXED_LIST) {
|
||||||
GArray *bufarr = g_value_peek_pointer (streamheader);
|
GArray *bufarr = g_value_peek_pointer (streamheader);
|
||||||
gint i;
|
gint i;
|
||||||
|
|
||||||
|
GST_LOG ("got fixed list");
|
||||||
|
|
||||||
for (i = 0; i < bufarr->len; i++) {
|
for (i = 0; i < bufarr->len; i++) {
|
||||||
GValue *bufval = &g_array_index (bufarr, GValue, i);
|
GValue *bufval = &g_array_index (bufarr, GValue, i);
|
||||||
|
|
||||||
|
GST_LOG ("item %d", i);
|
||||||
if (G_VALUE_TYPE (bufval) == GST_TYPE_BUFFER) {
|
if (G_VALUE_TYPE (bufval) == GST_TYPE_BUFFER) {
|
||||||
GstBuffer *buf = g_value_peek_pointer (bufval);
|
GstBuffer *buf = g_value_peek_pointer (bufval);
|
||||||
|
|
||||||
|
GST_LOG ("adding item %d to header list", i);
|
||||||
|
|
||||||
gst_buffer_ref (buf);
|
gst_buffer_ref (buf);
|
||||||
res = g_list_append (res, buf);
|
res = g_list_append (res, buf);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
GST_LOG ("streamheader is not fixed list");
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
GST_LOG ("caps done have streamheader");
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
GST_LOG ("got empty caps as negotiated format");
|
||||||
}
|
}
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static GstCaps *
|
||||||
gst_ogg_mux_set_header_on_caps (GstCaps * caps, GList * buffers)
|
gst_ogg_mux_set_header_on_caps (GstCaps * caps, GList * buffers)
|
||||||
{
|
{
|
||||||
GstStructure *structure = gst_caps_get_structure (caps, 0);
|
GstStructure *structure;
|
||||||
GValue list = { 0 };
|
GValue list = { 0 };
|
||||||
GList *walk = buffers;
|
GList *walk = buffers;
|
||||||
|
|
||||||
|
caps = gst_caps_make_writable (caps);
|
||||||
|
|
||||||
|
structure = gst_caps_get_structure (caps, 0);
|
||||||
|
|
||||||
/* put buffers in a fixed list */
|
/* put buffers in a fixed list */
|
||||||
g_value_init (&list, GST_TYPE_FIXED_LIST);
|
g_value_init (&list, GST_TYPE_FIXED_LIST);
|
||||||
|
|
||||||
|
@ -660,6 +690,8 @@ gst_ogg_mux_set_header_on_caps (GstCaps * caps, GList * buffers)
|
||||||
}
|
}
|
||||||
gst_structure_set_value (structure, "streamheader", &list);
|
gst_structure_set_value (structure, "streamheader", &list);
|
||||||
g_value_unset (&list);
|
g_value_unset (&list);
|
||||||
|
|
||||||
|
return caps;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -670,24 +702,30 @@ gst_ogg_mux_set_header_on_caps (GstCaps * caps, GList * buffers)
|
||||||
* find that info in the streamcaps.
|
* find that info in the streamcaps.
|
||||||
* After writing the headers we must start a new page for the data.
|
* After writing the headers we must start a new page for the data.
|
||||||
*/
|
*/
|
||||||
static void
|
static GstFlowReturn
|
||||||
gst_ogg_mux_send_headers (GstOggMux * mux)
|
gst_ogg_mux_send_headers (GstOggMux * mux)
|
||||||
{
|
{
|
||||||
GSList *walk;
|
GSList *walk;
|
||||||
GList *hbufs, *hwalk;
|
GList *hbufs, *hwalk;
|
||||||
GstCaps *caps;
|
GstCaps *caps;
|
||||||
|
GstFlowReturn ret;
|
||||||
|
|
||||||
hbufs = NULL;
|
hbufs = NULL;
|
||||||
|
ret = GST_FLOW_OK;
|
||||||
|
|
||||||
GST_LOG ("collecting headers");
|
GST_LOG ("collecting headers");
|
||||||
|
|
||||||
walk = mux->sinkpads;
|
walk = mux->collect->data;
|
||||||
while (walk) {
|
while (walk) {
|
||||||
GstOggPad *pad = (GstOggPad *) walk->data;
|
GstOggPad *pad;
|
||||||
|
GstPad *thepad;
|
||||||
|
|
||||||
walk = walk->next;
|
pad = (GstOggPad *) walk->data;
|
||||||
|
thepad = pad->collect.pad;
|
||||||
|
|
||||||
GST_LOG ("looking at pad %s:%s", GST_DEBUG_PAD_NAME (pad->pad));
|
walk = g_slist_next (walk);
|
||||||
|
|
||||||
|
GST_LOG ("looking at pad %s:%s", GST_DEBUG_PAD_NAME (thepad));
|
||||||
|
|
||||||
/* if the pad has no buffer, we don't care */
|
/* if the pad has no buffer, we don't care */
|
||||||
if (pad->buffer == NULL)
|
if (pad->buffer == NULL)
|
||||||
|
@ -698,19 +736,22 @@ gst_ogg_mux_send_headers (GstOggMux * mux)
|
||||||
}
|
}
|
||||||
|
|
||||||
GST_LOG ("creating first headers");
|
GST_LOG ("creating first headers");
|
||||||
walk = mux->sinkpads;
|
walk = mux->collect->data;
|
||||||
while (walk) {
|
while (walk) {
|
||||||
GstOggPad *pad = (GstOggPad *) walk->data;
|
GstOggPad *pad;
|
||||||
GstBuffer *buf;
|
GstBuffer *buf;
|
||||||
ogg_packet packet;
|
ogg_packet packet;
|
||||||
ogg_page page;
|
ogg_page page;
|
||||||
|
GstPad *thepad;
|
||||||
|
|
||||||
|
pad = (GstOggPad *) walk->data;
|
||||||
|
thepad = pad->collect.pad;
|
||||||
|
|
||||||
walk = walk->next;
|
walk = walk->next;
|
||||||
|
|
||||||
pad->packetno = 0;
|
pad->packetno = 0;
|
||||||
|
|
||||||
GST_LOG ("looping over headers for pad %s:%s",
|
GST_LOG ("looping over headers for pad %s:%s", GST_DEBUG_PAD_NAME (thepad));
|
||||||
GST_DEBUG_PAD_NAME (pad->pad));
|
|
||||||
|
|
||||||
if (pad->headers) {
|
if (pad->headers) {
|
||||||
buf = GST_BUFFER (pad->headers->data);
|
buf = GST_BUFFER (pad->headers->data);
|
||||||
|
@ -746,14 +787,17 @@ gst_ogg_mux_send_headers (GstOggMux * mux)
|
||||||
}
|
}
|
||||||
|
|
||||||
GST_LOG ("creating next headers");
|
GST_LOG ("creating next headers");
|
||||||
walk = mux->sinkpads;
|
walk = mux->collect->data;
|
||||||
while (walk) {
|
while (walk) {
|
||||||
GstOggPad *pad = (GstOggPad *) walk->data;
|
GstOggPad *pad;
|
||||||
|
GstPad *thepad;
|
||||||
|
|
||||||
|
pad = (GstOggPad *) walk->data;
|
||||||
|
thepad = pad->collect.pad;
|
||||||
|
|
||||||
walk = walk->next;
|
walk = walk->next;
|
||||||
|
|
||||||
GST_LOG ("looping over headers for pad %s:%s",
|
GST_LOG ("looping over headers for pad %s:%s", GST_DEBUG_PAD_NAME (thepad));
|
||||||
GST_DEBUG_PAD_NAME (pad->pad));
|
|
||||||
|
|
||||||
hwalk = pad->headers;
|
hwalk = pad->headers;
|
||||||
while (hwalk) {
|
while (hwalk) {
|
||||||
|
@ -808,8 +852,8 @@ gst_ogg_mux_send_headers (GstOggMux * mux)
|
||||||
/* create caps with the buffers */
|
/* create caps with the buffers */
|
||||||
caps = gst_pad_get_caps (mux->srcpad);
|
caps = gst_pad_get_caps (mux->srcpad);
|
||||||
if (caps) {
|
if (caps) {
|
||||||
gst_ogg_mux_set_header_on_caps (caps, hbufs);
|
caps = gst_ogg_mux_set_header_on_caps (caps, hbufs);
|
||||||
//gst_pad_try_set_caps (mux->srcpad, caps);
|
gst_pad_set_caps (mux->srcpad, caps);
|
||||||
}
|
}
|
||||||
/* and send the buffers */
|
/* and send the buffers */
|
||||||
hwalk = hbufs;
|
hwalk = hbufs;
|
||||||
|
@ -818,19 +862,20 @@ gst_ogg_mux_send_headers (GstOggMux * mux)
|
||||||
|
|
||||||
hwalk = hwalk->next;
|
hwalk = hwalk->next;
|
||||||
|
|
||||||
if (GST_PAD_IS_USABLE (mux->srcpad)) {
|
if ((ret = gst_pad_push (mux->srcpad, buf)) != GST_FLOW_OK)
|
||||||
gst_pad_push (mux->srcpad, buf);
|
break;
|
||||||
} else {
|
|
||||||
gst_buffer_unref (buf);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
g_list_free (hbufs);
|
g_list_free (hbufs);
|
||||||
|
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* basic idea:
|
/* this function is called when there is data on all pads.
|
||||||
*
|
*
|
||||||
* 1) find a pad to pull on, this is done by pulling on all pads and
|
* basic idea:
|
||||||
* looking at the buffers to decide which one should be muxed first.
|
*
|
||||||
|
* 1) find a pad to pull on, this is done by looking at the buffers
|
||||||
|
* to decide which one should be muxed first.
|
||||||
* 2) store the selected pad and keep on pulling until we fill a
|
* 2) store the selected pad and keep on pulling until we fill a
|
||||||
* complete ogg page or the ogg page is filled above the max-delay
|
* complete ogg page or the ogg page is filled above the max-delay
|
||||||
* threshold. This is needed because the ogg spec says that
|
* threshold. This is needed because the ogg spec says that
|
||||||
|
@ -841,19 +886,20 @@ gst_ogg_mux_send_headers (GstOggMux * mux)
|
||||||
* spec mandates that the last packet should have the EOS flag set before
|
* spec mandates that the last packet should have the EOS flag set before
|
||||||
* sending it to ogg.
|
* sending it to ogg.
|
||||||
*/
|
*/
|
||||||
static void
|
static GstFlowReturn
|
||||||
gst_ogg_mux_loop (GstElement * element)
|
gst_ogg_mux_collected (GstCollectPads * pads, GstOggMux * ogg_mux)
|
||||||
{
|
{
|
||||||
GstOggMux *ogg_mux;
|
|
||||||
GstOggPad *best;
|
GstOggPad *best;
|
||||||
gboolean delta_unit;
|
gboolean delta_unit;
|
||||||
gboolean interrupt = FALSE;
|
GstFlowReturn ret;
|
||||||
|
|
||||||
ogg_mux = GST_OGG_MUX (element);
|
GST_DEBUG ("collected");
|
||||||
|
|
||||||
best = gst_ogg_mux_queue_pads (ogg_mux, &interrupt);
|
best = gst_ogg_mux_queue_pads (ogg_mux);
|
||||||
if (interrupt)
|
if (best == NULL)
|
||||||
return;
|
return GST_FLOW_OK;
|
||||||
|
|
||||||
|
GST_DEBUG ("best pad %p", best);
|
||||||
|
|
||||||
/* we're pulling a pad and there is a better one, see if we need
|
/* we're pulling a pad and there is a better one, see if we need
|
||||||
* to flush the current page */
|
* to flush the current page */
|
||||||
|
@ -863,13 +909,14 @@ gst_ogg_mux_loop (GstElement * element)
|
||||||
|
|
||||||
GstClockTime last_ts =
|
GstClockTime last_ts =
|
||||||
GST_BUFFER_TIMESTAMP (pad->buffer) + GST_BUFFER_DURATION (pad->buffer);
|
GST_BUFFER_TIMESTAMP (pad->buffer) + GST_BUFFER_DURATION (pad->buffer);
|
||||||
|
|
||||||
/* if the next packet in the current page is going to make the page
|
/* if the next packet in the current page is going to make the page
|
||||||
* too long, we need to flush */
|
* too long, we need to flush */
|
||||||
if (last_ts > ogg_mux->next_ts + ogg_mux->max_delay) {
|
if (last_ts > ogg_mux->next_ts + ogg_mux->max_delay) {
|
||||||
ogg_page page;
|
ogg_page page;
|
||||||
|
|
||||||
while (ogg_stream_flush (&pad->stream, &page)) {
|
while (ogg_stream_flush (&pad->stream, &page)) {
|
||||||
gst_ogg_mux_push_page (ogg_mux, &page, pad->first_delta);
|
ret = gst_ogg_mux_push_page (ogg_mux, &page, pad->first_delta);
|
||||||
/* increment the page number counter */
|
/* increment the page number counter */
|
||||||
pad->pageno++;
|
pad->pageno++;
|
||||||
/* mark other pages as delta */
|
/* mark other pages as delta */
|
||||||
|
@ -888,15 +935,13 @@ gst_ogg_mux_loop (GstElement * element)
|
||||||
ogg_mux->next_ts = GST_BUFFER_TIMESTAMP (ogg_mux->pulling->buffer);
|
ogg_mux->next_ts = GST_BUFFER_TIMESTAMP (ogg_mux->pulling->buffer);
|
||||||
} else {
|
} else {
|
||||||
/* no pad to pull on, send EOS */
|
/* no pad to pull on, send EOS */
|
||||||
if (GST_PAD_IS_USABLE (ogg_mux->srcpad))
|
gst_pad_push_event (ogg_mux->srcpad, gst_event_new (GST_EVENT_EOS));
|
||||||
gst_pad_push_event (ogg_mux->srcpad, gst_event_new (GST_EVENT_EOS));
|
return GST_FLOW_WRONG_STATE;
|
||||||
//gst_element_set_eos (element);
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ogg_mux->need_headers) {
|
if (ogg_mux->need_headers) {
|
||||||
gst_ogg_mux_send_headers (ogg_mux);
|
ret = gst_ogg_mux_send_headers (ogg_mux);
|
||||||
ogg_mux->need_headers = FALSE;
|
ogg_mux->need_headers = FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -912,18 +957,6 @@ gst_ogg_mux_loop (GstElement * element)
|
||||||
|
|
||||||
/* now see if we have a buffer */
|
/* now see if we have a buffer */
|
||||||
buf = pad->buffer;
|
buf = pad->buffer;
|
||||||
if (buf == NULL) {
|
|
||||||
/* no buffer, get one, and store in the pad so we free it later on */
|
|
||||||
buf = pad->buffer = gst_ogg_mux_next_buffer (pad, &interrupt);
|
|
||||||
if (interrupt)
|
|
||||||
return;
|
|
||||||
/* data exhausted on this pad (EOS) */
|
|
||||||
if (buf == NULL) {
|
|
||||||
/* stop pulling from the pad */
|
|
||||||
ogg_mux->pulling = NULL;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
delta_unit = GST_BUFFER_FLAG_IS_SET (buf, GST_BUFFER_DELTA_UNIT);
|
delta_unit = GST_BUFFER_FLAG_IS_SET (buf, GST_BUFFER_DELTA_UNIT);
|
||||||
duration = GST_BUFFER_DURATION (buf);
|
duration = GST_BUFFER_DURATION (buf);
|
||||||
|
@ -938,6 +971,7 @@ gst_ogg_mux_loop (GstElement * element)
|
||||||
packet.b_o_s = (pad->packetno == 0);
|
packet.b_o_s = (pad->packetno == 0);
|
||||||
packet.packetno = pad->packetno++;
|
packet.packetno = pad->packetno++;
|
||||||
|
|
||||||
|
#if 0
|
||||||
/* read ahead one more buffer to find EOS */
|
/* read ahead one more buffer to find EOS */
|
||||||
tmpbuf = gst_ogg_mux_next_buffer (pad, &interrupt);
|
tmpbuf = gst_ogg_mux_next_buffer (pad, &interrupt);
|
||||||
if (interrupt)
|
if (interrupt)
|
||||||
|
@ -949,6 +983,10 @@ gst_ogg_mux_loop (GstElement * element)
|
||||||
}
|
}
|
||||||
/* mark EOS */
|
/* mark EOS */
|
||||||
packet.e_o_s = (tmpbuf == NULL ? 1 : 0);
|
packet.e_o_s = (tmpbuf == NULL ? 1 : 0);
|
||||||
|
#else
|
||||||
|
packet.e_o_s = 0;
|
||||||
|
tmpbuf = NULL;
|
||||||
|
#endif
|
||||||
|
|
||||||
/* we flush when we see a new keyframe */
|
/* we flush when we see a new keyframe */
|
||||||
force_flush = (pad->prev_delta && !delta_unit);
|
force_flush = (pad->prev_delta && !delta_unit);
|
||||||
|
@ -964,7 +1002,7 @@ gst_ogg_mux_loop (GstElement * element)
|
||||||
/* force flush */
|
/* force flush */
|
||||||
if (force_flush) {
|
if (force_flush) {
|
||||||
while (ogg_stream_flush (&pad->stream, &page)) {
|
while (ogg_stream_flush (&pad->stream, &page)) {
|
||||||
gst_ogg_mux_push_page (ogg_mux, &page, pad->first_delta);
|
ret = gst_ogg_mux_push_page (ogg_mux, &page, pad->first_delta);
|
||||||
/* increment the page number counter */
|
/* increment the page number counter */
|
||||||
pad->pageno++;
|
pad->pageno++;
|
||||||
/* mark other pages as delta */
|
/* mark other pages as delta */
|
||||||
|
@ -1004,6 +1042,11 @@ gst_ogg_mux_loop (GstElement * element)
|
||||||
pad->prev_delta = delta_unit;
|
pad->prev_delta = delta_unit;
|
||||||
|
|
||||||
/* swap the packet in */
|
/* swap the packet in */
|
||||||
|
if (packet.e_o_s == 1)
|
||||||
|
GST_DEBUG_OBJECT (pad, "swapping in EOS packet");
|
||||||
|
if (packet.b_o_s == 1)
|
||||||
|
GST_DEBUG_OBJECT (pad, "swapping in BOS packet");
|
||||||
|
|
||||||
ogg_stream_packetin (&pad->stream, &packet);
|
ogg_stream_packetin (&pad->stream, &packet);
|
||||||
|
|
||||||
/* don't need the old buffer anymore */
|
/* don't need the old buffer anymore */
|
||||||
|
@ -1015,7 +1058,7 @@ gst_ogg_mux_loop (GstElement * element)
|
||||||
* up in more than one page so we need to write them all */
|
* up in more than one page so we need to write them all */
|
||||||
if (ogg_stream_pageout (&pad->stream, &page) > 0) {
|
if (ogg_stream_pageout (&pad->stream, &page) > 0) {
|
||||||
/* push the page */
|
/* push the page */
|
||||||
gst_ogg_mux_push_page (ogg_mux, &page, pad->first_delta);
|
ret = gst_ogg_mux_push_page (ogg_mux, &page, pad->first_delta);
|
||||||
pad->pageno++;
|
pad->pageno++;
|
||||||
/* mark next pages as delta */
|
/* mark next pages as delta */
|
||||||
pad->first_delta = TRUE;
|
pad->first_delta = TRUE;
|
||||||
|
@ -1025,7 +1068,7 @@ gst_ogg_mux_loop (GstElement * element)
|
||||||
while (ogg_stream_pageout (&pad->stream, &page) > 0) {
|
while (ogg_stream_pageout (&pad->stream, &page) > 0) {
|
||||||
/* we have a complete page now, we can push the page
|
/* we have a complete page now, we can push the page
|
||||||
* and make sure to pull on a new pad the next time around */
|
* and make sure to pull on a new pad the next time around */
|
||||||
gst_ogg_mux_push_page (ogg_mux, &page, pad->first_delta);
|
ret = gst_ogg_mux_push_page (ogg_mux, &page, pad->first_delta);
|
||||||
/* increment the page number counter */
|
/* increment the page number counter */
|
||||||
pad->pageno++;
|
pad->pageno++;
|
||||||
}
|
}
|
||||||
|
@ -1037,6 +1080,8 @@ gst_ogg_mux_loop (GstElement * element)
|
||||||
ogg_mux->pulling = NULL;
|
ogg_mux->pulling = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return GST_FLOW_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -1085,10 +1130,10 @@ static GstElementStateReturn
|
||||||
gst_ogg_mux_change_state (GstElement * element)
|
gst_ogg_mux_change_state (GstElement * element)
|
||||||
{
|
{
|
||||||
GstOggMux *ogg_mux;
|
GstOggMux *ogg_mux;
|
||||||
gint transition = GST_STATE_TRANSITION (element);
|
gint transition;
|
||||||
|
GstElementStateReturn ret;
|
||||||
g_return_val_if_fail (GST_IS_OGG_MUX (element), GST_STATE_FAILURE);
|
|
||||||
|
|
||||||
|
transition = GST_STATE_TRANSITION (element);
|
||||||
ogg_mux = GST_OGG_MUX (element);
|
ogg_mux = GST_OGG_MUX (element);
|
||||||
|
|
||||||
switch (transition) {
|
switch (transition) {
|
||||||
|
@ -1097,18 +1142,28 @@ gst_ogg_mux_change_state (GstElement * element)
|
||||||
ogg_mux->next_ts = 0;
|
ogg_mux->next_ts = 0;
|
||||||
ogg_mux->offset = 0;
|
ogg_mux->offset = 0;
|
||||||
ogg_mux->pulling = NULL;
|
ogg_mux->pulling = NULL;
|
||||||
|
gst_collectpads_start (ogg_mux->collect);
|
||||||
break;
|
break;
|
||||||
case GST_STATE_PAUSED_TO_PLAYING:
|
case GST_STATE_PAUSED_TO_PLAYING:
|
||||||
case GST_STATE_PLAYING_TO_PAUSED:
|
break;
|
||||||
case GST_STATE_PAUSED_TO_READY:
|
default:
|
||||||
case GST_STATE_READY_TO_NULL:
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (GST_ELEMENT_CLASS (parent_class)->change_state)
|
ret = GST_ELEMENT_CLASS (parent_class)->change_state (element);
|
||||||
return GST_ELEMENT_CLASS (parent_class)->change_state (element);
|
|
||||||
|
|
||||||
return GST_STATE_SUCCESS;
|
switch (transition) {
|
||||||
|
case GST_STATE_PLAYING_TO_PAUSED:
|
||||||
|
break;
|
||||||
|
case GST_STATE_PAUSED_TO_READY:
|
||||||
|
gst_collectpads_stop (ogg_mux->collect);
|
||||||
|
break;
|
||||||
|
case GST_STATE_READY_TO_NULL:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
gboolean
|
gboolean
|
||||||
|
|
Loading…
Reference in a new issue