2003-11-24 04:08:48 +00:00
|
|
|
/* GStreamer
|
2004-07-02 03:41:22 +00:00
|
|
|
* Copyright (C) 2003, 2004 Benjamin Otte <otte@gnome.org>
|
2003-11-24 04:08:48 +00:00
|
|
|
*
|
2004-01-23 13:22:17 +00:00
|
|
|
* gstoggdemux.c: ogg stream demuxer
|
2003-11-24 04:08:48 +00:00
|
|
|
*
|
|
|
|
* This library is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU Library General Public
|
|
|
|
* License as published by the Free Software Foundation; either
|
|
|
|
* version 2 of the License, or (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This library is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
* Library General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU Library General Public
|
|
|
|
* License along with this library; if not, write to the
|
|
|
|
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
|
|
|
* Boston, MA 02111-1307, USA.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
|
|
#include "config.h"
|
|
|
|
#endif
|
|
|
|
#include <gst/gst.h>
|
2004-07-02 03:41:22 +00:00
|
|
|
#include <gst/bytestream/filepad.h>
|
2003-11-24 04:08:48 +00:00
|
|
|
#include <ogg/ogg.h>
|
2004-03-14 22:34:34 +00:00
|
|
|
#include <string.h>
|
2003-11-24 04:08:48 +00:00
|
|
|
|
2004-07-02 03:41:22 +00:00
|
|
|
/* tweak this to improve setup times */
|
|
|
|
/* PLEASE don't just tweak it because one file is faster with tweaked numbers,
|
|
|
|
* but use a good benchmark with both video and audio files */
|
|
|
|
/* number of bytes we seek in front of desired point so we can resync properly */
|
|
|
|
#define SETUP_EXPECTED_PAGE_SIZE (8500) /* this is out of vorbisfile */
|
|
|
|
/* number of bytes where we don't seek to middle anymore but just walk through
|
|
|
|
* all packets */
|
|
|
|
#define SETUP_PASSTHROUGH_SIZE (SETUP_EXPECTED_PAGE_SIZE * 20)
|
|
|
|
/* if we have to repeat a seek backwards because we didn't seek back far enough,
|
|
|
|
* we multiply the amount we seek by this amount */
|
|
|
|
#define SETUP_SEEK_MULTIPLIER (5)
|
|
|
|
|
|
|
|
|
2003-11-24 04:08:48 +00:00
|
|
|
GST_DEBUG_CATEGORY_STATIC (gst_ogg_demux_debug);
|
2004-07-02 03:41:22 +00:00
|
|
|
GST_DEBUG_CATEGORY_STATIC (gst_ogg_demux_setup_debug);
|
2003-11-24 04:08:48 +00:00
|
|
|
#define GST_CAT_DEFAULT gst_ogg_demux_debug
|
|
|
|
|
2004-03-14 22:34:34 +00:00
|
|
|
#define GST_TYPE_OGG_DEMUX (gst_ogg_demux_get_type())
|
2003-11-24 04:08:48 +00:00
|
|
|
#define GST_OGG_DEMUX(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_OGG_DEMUX, GstOggDemux))
|
|
|
|
#define GST_OGG_DEMUX_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_OGG_DEMUX, GstOggDemux))
|
|
|
|
#define GST_IS_OGG_DEMUX(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_OGG_DEMUX))
|
|
|
|
#define GST_IS_OGG_DEMUX_CLASS(obj) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_OGG_DEMUX))
|
|
|
|
|
|
|
|
typedef struct _GstOggDemux GstOggDemux;
|
|
|
|
typedef struct _GstOggDemuxClass GstOggDemuxClass;
|
|
|
|
|
2004-03-14 22:34:34 +00:00
|
|
|
typedef enum
|
|
|
|
{
|
2004-01-29 02:50:20 +00:00
|
|
|
/* just because you shouldn't make a valid enum value 0 */
|
|
|
|
GST_OGG_STATE_INAVLID,
|
|
|
|
/* just started, we need to decide if we should do setup */
|
|
|
|
GST_OGG_STATE_START,
|
|
|
|
/* setup is analyzing the stream, getting lengths and so on */
|
|
|
|
GST_OGG_STATE_SETUP,
|
|
|
|
/* after a seek, during resyncing */
|
|
|
|
GST_OGG_STATE_SEEK,
|
|
|
|
/* normal playback */
|
|
|
|
GST_OGG_STATE_PLAY
|
2004-03-15 19:32:28 +00:00
|
|
|
}
|
|
|
|
GstOggState;
|
2004-01-29 02:50:20 +00:00
|
|
|
|
|
|
|
/* all information needed for one ogg stream */
|
2004-03-14 22:34:34 +00:00
|
|
|
typedef struct
|
|
|
|
{
|
2004-03-15 19:32:28 +00:00
|
|
|
GstPad *pad; /* reference for this pad is held by element we belong to */
|
2004-03-14 22:34:34 +00:00
|
|
|
|
|
|
|
gint serial;
|
|
|
|
ogg_stream_state stream;
|
2004-03-15 19:32:28 +00:00
|
|
|
guint64 offset; /* end offset of last buffer */
|
|
|
|
guint64 known_offset; /* last known offset */
|
|
|
|
gint64 packetno; /* number of next expected packet */
|
2004-03-14 22:34:34 +00:00
|
|
|
|
2004-10-18 15:23:41 +00:00
|
|
|
guint64 start; /* first valid granulepos */
|
2004-03-15 19:32:28 +00:00
|
|
|
guint64 length; /* length of stream or 0 */
|
|
|
|
glong pages; /* number of pages in stream or 0 */
|
2004-03-14 22:34:34 +00:00
|
|
|
|
2004-07-02 03:41:22 +00:00
|
|
|
gint64 start_offset; /* earliest offset in file where this stream has been found */
|
|
|
|
gboolean start_found; /* we have found the bos (first) page */
|
|
|
|
gint64 end_offset; /* last offset in file where this stream has been found */
|
|
|
|
gboolean end_found; /* we have fount the eos (last) page */
|
|
|
|
|
2004-03-14 22:34:34 +00:00
|
|
|
guint flags;
|
2004-03-15 19:32:28 +00:00
|
|
|
}
|
|
|
|
GstOggPad;
|
2003-11-24 04:08:48 +00:00
|
|
|
|
2004-03-14 22:34:34 +00:00
|
|
|
typedef enum
|
|
|
|
{
|
|
|
|
GST_OGG_PAD_NEEDS_DISCONT = (1 << 0),
|
|
|
|
GST_OGG_PAD_NEEDS_FLUSH = (1 << 1)
|
2004-01-31 17:19:21 +00:00
|
|
|
}
|
|
|
|
GstOggPadFlags;
|
|
|
|
|
2004-01-29 02:50:20 +00:00
|
|
|
/* all information needed for one ogg chain (relevant for chained bitstreams) */
|
2004-03-14 22:34:34 +00:00
|
|
|
typedef struct
|
|
|
|
{
|
2004-07-02 03:41:22 +00:00
|
|
|
gint64 starts_at; /* starting offset of chain */
|
|
|
|
gint64 ends_at; /* end offset of stream (only valid when not last chain or not in setup) */
|
|
|
|
|
2004-03-15 19:32:28 +00:00
|
|
|
GSList *pads; /* list of GstOggPad */
|
|
|
|
}
|
|
|
|
GstOggChain;
|
2004-03-14 22:34:34 +00:00
|
|
|
|
2004-01-29 02:50:20 +00:00
|
|
|
#define CURRENT_CHAIN(ogg) (&g_array_index ((ogg)->chains, GstOggChain, (ogg)->current_chain))
|
2004-07-02 03:41:22 +00:00
|
|
|
#define FOR_PAD_IN_CURRENT_CHAIN(ogg, __pad, ...) \
|
|
|
|
FOR_PAD_IN_CHAIN(ogg, __pad, (ogg)->current_chain, __VA_ARGS__)
|
|
|
|
#define FOR_PAD_IN_CHAIN(ogg, _pad, i, ...) G_STMT_START{ \
|
2004-01-31 17:19:21 +00:00
|
|
|
GSList *_walk; \
|
2004-07-02 03:41:22 +00:00
|
|
|
GstOggChain *_chain = &g_array_index ((ogg)->chains, GstOggChain, i); \
|
|
|
|
if (i != -1) { \
|
|
|
|
for (_walk = _chain->pads; _walk; _walk = g_slist_next (_walk)) { \
|
2004-04-01 16:34:14 +00:00
|
|
|
GstOggPad *_pad = (GstOggPad *) _walk->data; \
|
|
|
|
__VA_ARGS__ \
|
|
|
|
} \
|
2004-01-31 17:19:21 +00:00
|
|
|
} \
|
|
|
|
}G_STMT_END
|
2004-01-29 02:50:20 +00:00
|
|
|
|
2004-03-14 22:34:34 +00:00
|
|
|
typedef enum
|
|
|
|
{
|
2004-01-29 02:50:20 +00:00
|
|
|
GST_OGG_FLAG_BOS = GST_ELEMENT_FLAG_LAST,
|
|
|
|
GST_OGG_FLAG_EOS,
|
|
|
|
GST_OGG_FLAG_WAIT_FOR_DISCONT
|
2004-03-15 19:32:28 +00:00
|
|
|
}
|
|
|
|
GstOggFlag;
|
2004-01-29 02:50:20 +00:00
|
|
|
|
2004-03-14 22:34:34 +00:00
|
|
|
struct _GstOggDemux
|
|
|
|
{
|
|
|
|
GstElement element;
|
2003-11-24 04:08:48 +00:00
|
|
|
|
2004-01-29 02:50:20 +00:00
|
|
|
/* pad */
|
2004-07-02 03:41:22 +00:00
|
|
|
GstFilePad *sinkpad;
|
2004-03-14 22:34:34 +00:00
|
|
|
|
2004-01-29 02:50:20 +00:00
|
|
|
/* state */
|
2004-03-14 22:34:34 +00:00
|
|
|
GstOggState state;
|
2004-07-02 03:41:22 +00:00
|
|
|
GArray *chains; /* list of chains we know */
|
|
|
|
gint current_chain; /* id of chain that currently "plays" */
|
|
|
|
gboolean bos; /* no-more-pads signal needs this */
|
|
|
|
/* setup */
|
|
|
|
GSList *unordered; /* streams we haven't found chains for yet */
|
|
|
|
guint setup_state; /* seperate from global state */
|
2004-03-14 22:34:34 +00:00
|
|
|
|
2003-11-24 04:08:48 +00:00
|
|
|
/* ogg stuff */
|
2004-03-14 22:34:34 +00:00
|
|
|
ogg_sync_state sync;
|
|
|
|
|
2004-01-29 02:50:20 +00:00
|
|
|
/* seeking */
|
2004-03-14 22:34:34 +00:00
|
|
|
GstOggPad *seek_pad;
|
2004-07-02 03:41:22 +00:00
|
|
|
gint64 seek_to;
|
|
|
|
gint64 seek_skipped;
|
2004-10-29 15:59:37 +00:00
|
|
|
guint64 seek_offset;
|
ext/: More seeking fixes, oggdemux now supports seeking to time and uses the downstream element to convert granulepos...
Original commit message from CVS:
* ext/ogg/gstoggdemux.c: (gst_ogg_demux_init),
(gst_ogg_demux_get_formats), (gst_ogg_demux_src_query),
(gst_ogg_demux_src_event), (gst_ogg_demux_src_convert),
(gst_ogg_demux_handle_event), (gst_ogg_demux_seek_before),
(_find_chain_get_unknown_part), (_find_streams_check),
(gst_ogg_demux_push), (gst_ogg_pad_push):
* ext/theora/theoradec.c: (theora_get_formats),
(theora_dec_src_convert), (theora_dec_sink_convert),
(theora_dec_src_query), (theora_dec_src_event), (theora_dec_event),
(theora_dec_chain):
* ext/vorbis/vorbisdec.c: (vorbis_dec_get_formats),
(vorbis_dec_convert), (vorbis_dec_src_query),
(vorbis_dec_src_event), (vorbis_dec_event):
More seeking fixes, oggdemux now supports seeking to time and
uses the downstream element to convert granulepos to time.
Seeking in theora-only ogg files now works.
2004-07-21 16:48:20 +00:00
|
|
|
GstFormat seek_format;
|
2004-10-29 15:59:37 +00:00
|
|
|
gint seek_try;
|
2003-11-24 04:08:48 +00:00
|
|
|
};
|
|
|
|
|
2004-03-14 22:34:34 +00:00
|
|
|
struct _GstOggDemuxClass
|
|
|
|
{
|
2003-11-24 04:08:48 +00:00
|
|
|
GstElementClass parent_class;
|
|
|
|
};
|
|
|
|
|
|
|
|
/* signals and args */
|
2004-03-14 22:34:34 +00:00
|
|
|
enum
|
|
|
|
{
|
2003-11-24 04:08:48 +00:00
|
|
|
/* FILL ME */
|
|
|
|
LAST_SIGNAL
|
|
|
|
};
|
|
|
|
|
2004-03-14 22:34:34 +00:00
|
|
|
enum
|
|
|
|
{
|
2004-05-21 23:28:57 +00:00
|
|
|
ARG_0
|
|
|
|
/* FILL ME */
|
2003-11-24 04:08:48 +00:00
|
|
|
};
|
|
|
|
|
2003-12-22 01:47:09 +00:00
|
|
|
static GstStaticPadTemplate ogg_demux_src_template_factory =
|
2004-03-14 22:34:34 +00:00
|
|
|
GST_STATIC_PAD_TEMPLATE ("src",
|
|
|
|
GST_PAD_SRC,
|
|
|
|
GST_PAD_SOMETIMES,
|
|
|
|
GST_STATIC_CAPS_ANY);
|
2003-12-22 01:47:09 +00:00
|
|
|
|
|
|
|
static GstStaticPadTemplate ogg_demux_sink_template_factory =
|
2004-03-14 22:34:34 +00:00
|
|
|
GST_STATIC_PAD_TEMPLATE ("sink",
|
|
|
|
GST_PAD_SINK,
|
|
|
|
GST_PAD_ALWAYS,
|
|
|
|
GST_STATIC_CAPS ("application/ogg")
|
|
|
|
);
|
|
|
|
|
2004-07-02 03:41:22 +00:00
|
|
|
/* different setup phases */
|
|
|
|
typedef enum
|
|
|
|
{
|
|
|
|
SETUP_INVALID,
|
|
|
|
SETUP_READ_FIRST_BOS,
|
|
|
|
SETUP_READ_BOS,
|
|
|
|
SETUP_FIND_LAST_CHAIN,
|
|
|
|
SETUP_FIND_END_OF_CHAIN,
|
|
|
|
SETUP_FIND_END_OF_STREAMS,
|
|
|
|
SETUP_FIND_END_OF_LAST_STREAMS
|
|
|
|
}
|
|
|
|
GstOggSetupState;
|
|
|
|
|
|
|
|
typedef struct
|
|
|
|
{
|
|
|
|
gboolean (*init) (GstOggDemux * ogg);
|
|
|
|
gboolean (*process) (GstOggDemux * ogg, ogg_page * page);
|
|
|
|
}
|
|
|
|
SetupStateFunc;
|
|
|
|
|
|
|
|
static gboolean _read_bos_init (GstOggDemux * ogg);
|
|
|
|
static gboolean _read_bos_process (GstOggDemux * ogg, ogg_page * page);
|
|
|
|
static gboolean _find_chain_init (GstOggDemux * ogg);
|
|
|
|
static gboolean _find_chain_process (GstOggDemux * ogg, ogg_page * page);
|
|
|
|
static gboolean _find_last_chain_init (GstOggDemux * ogg);
|
|
|
|
static gboolean _find_last_chain_process (GstOggDemux * ogg, ogg_page * page);
|
|
|
|
static gboolean _find_streams_init (GstOggDemux * ogg);
|
|
|
|
static gboolean _find_streams_process (GstOggDemux * ogg, ogg_page * page);
|
|
|
|
|
|
|
|
static SetupStateFunc setup_funcs[] = {
|
|
|
|
{NULL, NULL},
|
|
|
|
{_read_bos_init, _read_bos_process},
|
|
|
|
{_read_bos_init, _read_bos_process},
|
|
|
|
{_find_last_chain_init, _find_last_chain_process},
|
|
|
|
{_find_chain_init, _find_chain_process},
|
|
|
|
{_find_streams_init, _find_streams_process},
|
|
|
|
{_find_streams_init, _find_streams_process},
|
|
|
|
{NULL, NULL} /* just because */
|
|
|
|
};
|
|
|
|
|
|
|
|
static gboolean gst_ogg_demux_set_setup_state (GstOggDemux * ogg,
|
|
|
|
GstOggSetupState state);
|
2004-03-14 22:34:34 +00:00
|
|
|
|
|
|
|
static void gst_ogg_demux_finalize (GObject * object);
|
|
|
|
|
|
|
|
static gboolean gst_ogg_demux_src_event (GstPad * pad, GstEvent * event);
|
|
|
|
static const GstEventMask *gst_ogg_demux_get_event_masks (GstPad * pad);
|
|
|
|
static const GstQueryType *gst_ogg_demux_get_query_types (GstPad * pad);
|
ext/: More seeking fixes, oggdemux now supports seeking to time and uses the downstream element to convert granulepos...
Original commit message from CVS:
* ext/ogg/gstoggdemux.c: (gst_ogg_demux_init),
(gst_ogg_demux_get_formats), (gst_ogg_demux_src_query),
(gst_ogg_demux_src_event), (gst_ogg_demux_src_convert),
(gst_ogg_demux_handle_event), (gst_ogg_demux_seek_before),
(_find_chain_get_unknown_part), (_find_streams_check),
(gst_ogg_demux_push), (gst_ogg_pad_push):
* ext/theora/theoradec.c: (theora_get_formats),
(theora_dec_src_convert), (theora_dec_sink_convert),
(theora_dec_src_query), (theora_dec_src_event), (theora_dec_event),
(theora_dec_chain):
* ext/vorbis/vorbisdec.c: (vorbis_dec_get_formats),
(vorbis_dec_convert), (vorbis_dec_src_query),
(vorbis_dec_src_event), (vorbis_dec_event):
More seeking fixes, oggdemux now supports seeking to time and
uses the downstream element to convert granulepos to time.
Seeking in theora-only ogg files now works.
2004-07-21 16:48:20 +00:00
|
|
|
static const GstFormat *gst_ogg_demux_get_formats (GstPad * pad);
|
2004-03-14 22:34:34 +00:00
|
|
|
|
|
|
|
static gboolean gst_ogg_demux_src_query (GstPad * pad,
|
|
|
|
GstQueryType type, GstFormat * format, gint64 * value);
|
|
|
|
|
2004-07-02 03:41:22 +00:00
|
|
|
static void gst_ogg_demux_iterate (GstFilePad * pad);
|
|
|
|
static gboolean gst_ogg_demux_handle_event (GstPad * pad, GstEvent * event);
|
2004-03-14 22:34:34 +00:00
|
|
|
|
|
|
|
static GstElementStateReturn gst_ogg_demux_change_state (GstElement * element);
|
|
|
|
|
|
|
|
static GstOggPad *gst_ogg_pad_new (GstOggDemux * ogg, int serial_no);
|
|
|
|
static void gst_ogg_pad_remove (GstOggDemux * ogg, GstOggPad * ogg_pad);
|
|
|
|
static void gst_ogg_pad_reset (GstOggDemux * ogg, GstOggPad * pad);
|
|
|
|
static void gst_ogg_demux_push (GstOggDemux * ogg, ogg_page * page);
|
|
|
|
static void gst_ogg_pad_push (GstOggDemux * ogg, GstOggPad * ogg_pad);
|
2004-07-02 03:41:22 +00:00
|
|
|
static void gst_ogg_chains_clear (GstOggDemux * ogg);
|
|
|
|
static void gst_ogg_add_chain (GstOggDemux * ogg);
|
2004-03-14 22:34:34 +00:00
|
|
|
|
|
|
|
static GstCaps *gst_ogg_type_find (ogg_packet * packet);
|
|
|
|
|
|
|
|
static void gst_ogg_print (GstOggDemux * demux);
|
2003-11-24 04:08:48 +00:00
|
|
|
|
2004-01-29 02:50:20 +00:00
|
|
|
#define GST_OGG_SET_STATE(ogg, new_state) G_STMT_START{ \
|
|
|
|
GST_DEBUG_OBJECT (ogg, "setting state to %s", G_STRINGIFY (new_state)); \
|
|
|
|
ogg->state = new_state; \
|
2004-07-02 03:41:22 +00:00
|
|
|
ogg->setup_state = (new_state == GST_OGG_STATE_SETUP) ? \
|
|
|
|
SETUP_READ_FIRST_BOS : SETUP_INVALID; \
|
2004-01-29 02:50:20 +00:00
|
|
|
}G_STMT_END
|
2004-03-14 22:34:34 +00:00
|
|
|
|
2004-01-29 02:50:20 +00:00
|
|
|
GST_BOILERPLATE (GstOggDemux, gst_ogg_demux, GstElement, GST_TYPE_ELEMENT)
|
2003-11-24 04:08:48 +00:00
|
|
|
|
2004-03-14 22:34:34 +00:00
|
|
|
static void gst_ogg_demux_base_init (gpointer g_class)
|
2003-11-24 04:08:48 +00:00
|
|
|
{
|
|
|
|
GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
|
2004-07-02 03:41:22 +00:00
|
|
|
static GstElementDetails gst_ogg_demux_details =
|
|
|
|
GST_ELEMENT_DETAILS ("ogg demuxer",
|
|
|
|
"Codec/Demuxer",
|
|
|
|
"demux ogg streams (info about ogg: http://xiph.org)",
|
|
|
|
"Benjamin Otte <otte@gnome.org>");
|
2004-03-14 22:34:34 +00:00
|
|
|
|
2003-11-24 04:08:48 +00:00
|
|
|
gst_element_class_set_details (element_class, &gst_ogg_demux_details);
|
|
|
|
|
|
|
|
gst_element_class_add_pad_template (element_class,
|
2003-12-22 01:47:09 +00:00
|
|
|
gst_static_pad_template_get (&ogg_demux_sink_template_factory));
|
2003-11-24 04:08:48 +00:00
|
|
|
gst_element_class_add_pad_template (element_class,
|
2003-12-22 01:47:09 +00:00
|
|
|
gst_static_pad_template_get (&ogg_demux_src_template_factory));
|
2003-11-24 04:08:48 +00:00
|
|
|
}
|
|
|
|
static void
|
2004-03-14 22:34:34 +00:00
|
|
|
gst_ogg_demux_class_init (GstOggDemuxClass * klass)
|
2003-11-24 04:08:48 +00:00
|
|
|
{
|
2004-01-29 02:50:20 +00:00
|
|
|
GstElementClass *gstelement_class = GST_ELEMENT_CLASS (klass);
|
|
|
|
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
2004-03-14 22:34:34 +00:00
|
|
|
|
2003-11-24 04:08:48 +00:00
|
|
|
gstelement_class->change_state = gst_ogg_demux_change_state;
|
|
|
|
|
2004-01-29 02:50:20 +00:00
|
|
|
gobject_class->finalize = gst_ogg_demux_finalize;
|
2003-11-24 04:08:48 +00:00
|
|
|
}
|
2004-07-02 03:41:22 +00:00
|
|
|
|
2003-11-24 04:08:48 +00:00
|
|
|
static void
|
2004-03-14 22:34:34 +00:00
|
|
|
gst_ogg_demux_init (GstOggDemux * ogg)
|
2003-11-24 04:08:48 +00:00
|
|
|
{
|
2004-07-02 03:41:22 +00:00
|
|
|
GST_FLAG_SET (ogg, GST_ELEMENT_EVENT_AWARE);
|
|
|
|
|
2003-11-24 04:08:48 +00:00
|
|
|
/* create the sink pad */
|
2004-03-14 22:34:34 +00:00
|
|
|
ogg->sinkpad =
|
2004-07-02 03:41:22 +00:00
|
|
|
GST_FILE_PAD (gst_file_pad_new (gst_static_pad_template_get
|
|
|
|
(&ogg_demux_sink_template_factory), "sink"));
|
|
|
|
gst_file_pad_set_iterate_function (ogg->sinkpad, gst_ogg_demux_iterate);
|
|
|
|
gst_file_pad_set_event_function (ogg->sinkpad, gst_ogg_demux_handle_event);
|
ext/: More seeking fixes, oggdemux now supports seeking to time and uses the downstream element to convert granulepos...
Original commit message from CVS:
* ext/ogg/gstoggdemux.c: (gst_ogg_demux_init),
(gst_ogg_demux_get_formats), (gst_ogg_demux_src_query),
(gst_ogg_demux_src_event), (gst_ogg_demux_src_convert),
(gst_ogg_demux_handle_event), (gst_ogg_demux_seek_before),
(_find_chain_get_unknown_part), (_find_streams_check),
(gst_ogg_demux_push), (gst_ogg_pad_push):
* ext/theora/theoradec.c: (theora_get_formats),
(theora_dec_src_convert), (theora_dec_sink_convert),
(theora_dec_src_query), (theora_dec_src_event), (theora_dec_event),
(theora_dec_chain):
* ext/vorbis/vorbisdec.c: (vorbis_dec_get_formats),
(vorbis_dec_convert), (vorbis_dec_src_query),
(vorbis_dec_src_event), (vorbis_dec_event):
More seeking fixes, oggdemux now supports seeking to time and
uses the downstream element to convert granulepos to time.
Seeking in theora-only ogg files now works.
2004-07-21 16:48:20 +00:00
|
|
|
gst_pad_set_formats_function (GST_PAD (ogg->sinkpad),
|
|
|
|
gst_ogg_demux_get_formats);
|
2004-07-02 03:41:22 +00:00
|
|
|
gst_element_add_pad (GST_ELEMENT (ogg), GST_PAD (ogg->sinkpad));
|
2003-11-24 04:08:48 +00:00
|
|
|
|
|
|
|
/* initalize variables */
|
2004-01-29 02:50:20 +00:00
|
|
|
GST_OGG_SET_STATE (ogg, GST_OGG_STATE_START);
|
|
|
|
ogg->chains = g_array_new (TRUE, TRUE, sizeof (GstOggChain));
|
2004-01-30 03:51:04 +00:00
|
|
|
ogg->current_chain = -1;
|
2003-11-24 04:08:48 +00:00
|
|
|
}
|
2004-07-02 03:41:22 +00:00
|
|
|
|
2003-11-24 04:08:48 +00:00
|
|
|
static void
|
2004-03-14 22:34:34 +00:00
|
|
|
gst_ogg_demux_finalize (GObject * object)
|
2003-11-24 04:08:48 +00:00
|
|
|
{
|
|
|
|
GstOggDemux *ogg;
|
|
|
|
|
|
|
|
ogg = GST_OGG_DEMUX (object);
|
|
|
|
|
2004-11-01 17:25:07 +00:00
|
|
|
ogg_sync_clear (&ogg->sync);
|
2004-11-01 10:38:30 +00:00
|
|
|
|
2004-01-29 02:50:20 +00:00
|
|
|
/* chains are removed when going to READY */
|
|
|
|
g_assert (ogg->current_chain == -1);
|
|
|
|
g_assert (ogg->chains->len == 0);
|
|
|
|
g_array_free (ogg->chains, TRUE);
|
2004-11-01 10:38:30 +00:00
|
|
|
|
|
|
|
if (G_OBJECT_CLASS (parent_class)->finalize)
|
|
|
|
G_OBJECT_CLASS (parent_class)->finalize (object);
|
2003-11-24 04:08:48 +00:00
|
|
|
}
|
|
|
|
|
ext/: More seeking fixes, oggdemux now supports seeking to time and uses the downstream element to convert granulepos...
Original commit message from CVS:
* ext/ogg/gstoggdemux.c: (gst_ogg_demux_init),
(gst_ogg_demux_get_formats), (gst_ogg_demux_src_query),
(gst_ogg_demux_src_event), (gst_ogg_demux_src_convert),
(gst_ogg_demux_handle_event), (gst_ogg_demux_seek_before),
(_find_chain_get_unknown_part), (_find_streams_check),
(gst_ogg_demux_push), (gst_ogg_pad_push):
* ext/theora/theoradec.c: (theora_get_formats),
(theora_dec_src_convert), (theora_dec_sink_convert),
(theora_dec_src_query), (theora_dec_src_event), (theora_dec_event),
(theora_dec_chain):
* ext/vorbis/vorbisdec.c: (vorbis_dec_get_formats),
(vorbis_dec_convert), (vorbis_dec_src_query),
(vorbis_dec_src_event), (vorbis_dec_event):
More seeking fixes, oggdemux now supports seeking to time and
uses the downstream element to convert granulepos to time.
Seeking in theora-only ogg files now works.
2004-07-21 16:48:20 +00:00
|
|
|
static const GstFormat *
|
|
|
|
gst_ogg_demux_get_formats (GstPad * pad)
|
|
|
|
{
|
|
|
|
static GstFormat src_formats[] = {
|
|
|
|
GST_FORMAT_BYTES,
|
|
|
|
GST_FORMAT_DEFAULT, /* granulepos */
|
|
|
|
GST_FORMAT_TIME,
|
|
|
|
0
|
|
|
|
};
|
|
|
|
static GstFormat sink_formats[] = {
|
|
|
|
GST_FORMAT_BYTES,
|
|
|
|
GST_FORMAT_DEFAULT, /* bytes */
|
|
|
|
0
|
|
|
|
};
|
|
|
|
|
|
|
|
return (GST_PAD_IS_SRC (pad) ? src_formats : sink_formats);
|
|
|
|
}
|
|
|
|
|
2004-03-14 22:34:34 +00:00
|
|
|
static const GstEventMask *
|
|
|
|
gst_ogg_demux_get_event_masks (GstPad * pad)
|
2003-11-24 04:08:48 +00:00
|
|
|
{
|
|
|
|
static const GstEventMask gst_ogg_demux_src_event_masks[] = {
|
2004-03-14 22:34:34 +00:00
|
|
|
{GST_EVENT_SEEK, GST_SEEK_METHOD_SET | GST_SEEK_FLAG_FLUSH},
|
|
|
|
{0,}
|
2003-11-24 04:08:48 +00:00
|
|
|
};
|
2004-03-15 19:32:28 +00:00
|
|
|
|
2003-11-24 04:08:48 +00:00
|
|
|
return gst_ogg_demux_src_event_masks;
|
|
|
|
}
|
2004-03-14 22:34:34 +00:00
|
|
|
static const GstQueryType *
|
|
|
|
gst_ogg_demux_get_query_types (GstPad * pad)
|
2003-11-24 04:08:48 +00:00
|
|
|
{
|
|
|
|
static const GstQueryType gst_ogg_demux_src_query_types[] = {
|
|
|
|
GST_QUERY_TOTAL,
|
|
|
|
GST_QUERY_POSITION,
|
|
|
|
0
|
|
|
|
};
|
2004-03-15 19:32:28 +00:00
|
|
|
|
2003-11-24 04:08:48 +00:00
|
|
|
return gst_ogg_demux_src_query_types;
|
|
|
|
}
|
|
|
|
|
2004-01-29 02:50:20 +00:00
|
|
|
static GstOggPad *
|
2004-03-14 22:34:34 +00:00
|
|
|
gst_ogg_get_pad_by_pad (GstOggDemux * ogg, GstPad * pad)
|
2004-01-29 02:50:20 +00:00
|
|
|
{
|
|
|
|
GSList *walk;
|
|
|
|
GstOggPad *cur;
|
2004-03-14 22:34:34 +00:00
|
|
|
|
2004-03-06 11:18:28 +00:00
|
|
|
if (ogg->current_chain == -1) {
|
|
|
|
GST_DEBUG_OBJECT (ogg, "no active chain, returning NULL");
|
|
|
|
return NULL;
|
|
|
|
}
|
2004-01-29 02:50:20 +00:00
|
|
|
for (walk = CURRENT_CHAIN (ogg)->pads; walk; walk = g_slist_next (walk)) {
|
|
|
|
cur = (GstOggPad *) walk->data;
|
|
|
|
if (cur->pad == pad)
|
|
|
|
return cur;
|
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2004-11-08 17:02:07 +00:00
|
|
|
/* will subtract the base from a given granulepos in a stream
|
|
|
|
* (lineairly) and return the relative granulepos from the first
|
|
|
|
* packet in the stream, or some approximation thereof. Input is
|
|
|
|
* in granulepos units, output is either granulepos or time.
|
|
|
|
* Uses time internally. Returns -1 on error.
|
|
|
|
*/
|
|
|
|
static gint64
|
|
|
|
get_relative (GstOggDemux * ogg, GstOggPad * cur, gint64 granpos, GstFormat out)
|
|
|
|
{
|
|
|
|
gint64 time, start = -1, tmp;
|
|
|
|
GstFormat fmt;
|
|
|
|
|
|
|
|
/* we're gonna ask our peer */
|
|
|
|
if (!GST_PAD_PEER (cur->pad))
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
/* lineair unit (time) */
|
|
|
|
fmt = GST_FORMAT_TIME;
|
|
|
|
if (!gst_pad_convert (GST_PAD_PEER (cur->pad),
|
|
|
|
GST_FORMAT_DEFAULT, granpos, &fmt, &time))
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
/* get base for this chain */
|
|
|
|
FOR_PAD_IN_CURRENT_CHAIN (ogg, pad,
|
|
|
|
if (pad->start != -1 &&
|
|
|
|
GST_PAD_PEER (pad->pad) &&
|
|
|
|
gst_pad_convert (GST_PAD_PEER (pad->pad),
|
|
|
|
GST_FORMAT_DEFAULT, pad->start,
|
|
|
|
&fmt, &tmp) && (start == -1 || tmp < start))
|
|
|
|
start = tmp;);
|
|
|
|
if (start == -1)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
/* base is *end of first page*, so subtract $random amount to make
|
|
|
|
* us think it's the start of the page (= 1 second) */
|
|
|
|
if (start > GST_SECOND)
|
|
|
|
start -= GST_SECOND;
|
|
|
|
else
|
|
|
|
start = 0;
|
|
|
|
|
|
|
|
/* subtract */
|
|
|
|
if (time > start)
|
|
|
|
time -= start;
|
|
|
|
else
|
|
|
|
time = 0;
|
|
|
|
|
|
|
|
/* convert back to $outputformat */
|
|
|
|
if (!gst_pad_convert (GST_PAD_PEER (cur->pad),
|
|
|
|
GST_FORMAT_TIME, time, &out, &tmp))
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
return tmp;
|
|
|
|
}
|
|
|
|
|
ext/: More seeking fixes, oggdemux now supports seeking to time and uses the downstream element to convert granulepos...
Original commit message from CVS:
* ext/ogg/gstoggdemux.c: (gst_ogg_demux_init),
(gst_ogg_demux_get_formats), (gst_ogg_demux_src_query),
(gst_ogg_demux_src_event), (gst_ogg_demux_src_convert),
(gst_ogg_demux_handle_event), (gst_ogg_demux_seek_before),
(_find_chain_get_unknown_part), (_find_streams_check),
(gst_ogg_demux_push), (gst_ogg_pad_push):
* ext/theora/theoradec.c: (theora_get_formats),
(theora_dec_src_convert), (theora_dec_sink_convert),
(theora_dec_src_query), (theora_dec_src_event), (theora_dec_event),
(theora_dec_chain):
* ext/vorbis/vorbisdec.c: (vorbis_dec_get_formats),
(vorbis_dec_convert), (vorbis_dec_src_query),
(vorbis_dec_src_event), (vorbis_dec_event):
More seeking fixes, oggdemux now supports seeking to time and
uses the downstream element to convert granulepos to time.
Seeking in theora-only ogg files now works.
2004-07-21 16:48:20 +00:00
|
|
|
/* the query function on the src pad only knows about granulepos
|
|
|
|
* values but we can use the peer plugins to convert the granulepos
|
|
|
|
* (which is supposed to be the default format) to any other format
|
|
|
|
*/
|
2003-11-24 04:08:48 +00:00
|
|
|
static gboolean
|
2004-03-14 22:34:34 +00:00
|
|
|
gst_ogg_demux_src_query (GstPad * pad, GstQueryType type,
|
|
|
|
GstFormat * format, gint64 * value)
|
2003-11-24 04:08:48 +00:00
|
|
|
{
|
|
|
|
gboolean res = FALSE;
|
ext/: More seeking fixes, oggdemux now supports seeking to time and uses the downstream element to convert granulepos...
Original commit message from CVS:
* ext/ogg/gstoggdemux.c: (gst_ogg_demux_init),
(gst_ogg_demux_get_formats), (gst_ogg_demux_src_query),
(gst_ogg_demux_src_event), (gst_ogg_demux_src_convert),
(gst_ogg_demux_handle_event), (gst_ogg_demux_seek_before),
(_find_chain_get_unknown_part), (_find_streams_check),
(gst_ogg_demux_push), (gst_ogg_pad_push):
* ext/theora/theoradec.c: (theora_get_formats),
(theora_dec_src_convert), (theora_dec_sink_convert),
(theora_dec_src_query), (theora_dec_src_event), (theora_dec_event),
(theora_dec_chain):
* ext/vorbis/vorbisdec.c: (vorbis_dec_get_formats),
(vorbis_dec_convert), (vorbis_dec_src_query),
(vorbis_dec_src_event), (vorbis_dec_event):
More seeking fixes, oggdemux now supports seeking to time and
uses the downstream element to convert granulepos to time.
Seeking in theora-only ogg files now works.
2004-07-21 16:48:20 +00:00
|
|
|
GstOggDemux *ogg;
|
|
|
|
GstOggPad *cur;
|
ext/alsa/gstalsamixer.c: Update mixer (to sync with other sessions) if we try to obtain a new value. This makes alsam...
Original commit message from CVS:
* ext/alsa/gstalsamixer.c: (gst_alsa_mixer_update),
(gst_alsa_mixer_get_volume), (gst_alsa_mixer_set_volume),
(gst_alsa_mixer_set_mute), (gst_alsa_mixer_set_record),
(gst_alsa_mixer_set_option), (gst_alsa_mixer_get_option):
Update mixer (to sync with other sessions) if we try to obtain
a new value. This makes alsamixer work accross applications.
* ext/alsa/gstalsasink.c: (gst_alsa_sink_get_time):
Only call sync functions if we're running, else alsalib asserts.
* ext/ogg/gstoggdemux.c: (gst_ogg_demux_src_query):
Sometimes fails to compile. Possibly a gcc bug.
* gst/playback/gstplaybin.c: (gen_video_element),
(gen_audio_element):
Add a reference to an application-provided object, because we lose
this same reference if we add it to the bin. If we don't do this,
we can only use this object once and thus crash if we go from
ready to playing, back to ready and back to playing again.
Also add an audioscale element because several cheap soundcards -
like mine - don't support all samplerates.
* sys/ximage/ximagesink.c: (gst_ximagesink_xcontext_get),
(gst_ximagesink_xcontext_clear), (gst_ximagesink_change_state):
Fix wrong order or PAR calls. Makes automatically obtained PAR
from the X server atually being used.
2004-09-13 09:24:00 +00:00
|
|
|
guint64 granulepos = 0;
|
2003-11-24 04:08:48 +00:00
|
|
|
|
ext/: More seeking fixes, oggdemux now supports seeking to time and uses the downstream element to convert granulepos...
Original commit message from CVS:
* ext/ogg/gstoggdemux.c: (gst_ogg_demux_init),
(gst_ogg_demux_get_formats), (gst_ogg_demux_src_query),
(gst_ogg_demux_src_event), (gst_ogg_demux_src_convert),
(gst_ogg_demux_handle_event), (gst_ogg_demux_seek_before),
(_find_chain_get_unknown_part), (_find_streams_check),
(gst_ogg_demux_push), (gst_ogg_pad_push):
* ext/theora/theoradec.c: (theora_get_formats),
(theora_dec_src_convert), (theora_dec_sink_convert),
(theora_dec_src_query), (theora_dec_src_event), (theora_dec_event),
(theora_dec_chain):
* ext/vorbis/vorbisdec.c: (vorbis_dec_get_formats),
(vorbis_dec_convert), (vorbis_dec_src_query),
(vorbis_dec_src_event), (vorbis_dec_event):
More seeking fixes, oggdemux now supports seeking to time and
uses the downstream element to convert granulepos to time.
Seeking in theora-only ogg files now works.
2004-07-21 16:48:20 +00:00
|
|
|
ogg = GST_OGG_DEMUX (gst_pad_get_parent (pad));
|
|
|
|
|
|
|
|
cur = gst_ogg_get_pad_by_pad (ogg, pad);
|
2004-03-06 11:18:28 +00:00
|
|
|
if (!cur)
|
|
|
|
return FALSE;
|
|
|
|
|
2003-11-24 04:08:48 +00:00
|
|
|
switch (type) {
|
2004-03-14 22:34:34 +00:00
|
|
|
case GST_QUERY_TOTAL:{
|
2004-10-20 16:24:18 +00:00
|
|
|
if (cur->length != 0 && cur->length > cur->start) {
|
2004-10-18 19:12:32 +00:00
|
|
|
granulepos = cur->length;
|
2004-07-28 15:40:38 +00:00
|
|
|
res = TRUE;
|
|
|
|
}
|
2003-11-24 04:08:48 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case GST_QUERY_POSITION:
|
2004-10-20 16:24:18 +00:00
|
|
|
if (cur->length != 0 && cur->length > cur->start) {
|
2004-10-18 19:12:32 +00:00
|
|
|
granulepos = cur->known_offset;
|
2004-03-15 19:32:28 +00:00
|
|
|
res = TRUE;
|
2004-01-29 02:50:20 +00:00
|
|
|
}
|
2003-11-24 04:08:48 +00:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
2004-10-20 16:24:18 +00:00
|
|
|
|
ext/: More seeking fixes, oggdemux now supports seeking to time and uses the downstream element to convert granulepos...
Original commit message from CVS:
* ext/ogg/gstoggdemux.c: (gst_ogg_demux_init),
(gst_ogg_demux_get_formats), (gst_ogg_demux_src_query),
(gst_ogg_demux_src_event), (gst_ogg_demux_src_convert),
(gst_ogg_demux_handle_event), (gst_ogg_demux_seek_before),
(_find_chain_get_unknown_part), (_find_streams_check),
(gst_ogg_demux_push), (gst_ogg_pad_push):
* ext/theora/theoradec.c: (theora_get_formats),
(theora_dec_src_convert), (theora_dec_sink_convert),
(theora_dec_src_query), (theora_dec_src_event), (theora_dec_event),
(theora_dec_chain):
* ext/vorbis/vorbisdec.c: (vorbis_dec_get_formats),
(vorbis_dec_convert), (vorbis_dec_src_query),
(vorbis_dec_src_event), (vorbis_dec_event):
More seeking fixes, oggdemux now supports seeking to time and
uses the downstream element to convert granulepos to time.
Seeking in theora-only ogg files now works.
2004-07-21 16:48:20 +00:00
|
|
|
if (res) {
|
2004-11-08 17:02:07 +00:00
|
|
|
gint64 time;
|
2004-10-18 19:12:32 +00:00
|
|
|
|
2004-11-08 17:02:07 +00:00
|
|
|
time = get_relative (ogg, cur, granulepos, GST_FORMAT_TIME);
|
|
|
|
if (time == -1)
|
|
|
|
return FALSE;
|
2004-10-18 19:12:32 +00:00
|
|
|
|
ext/: More seeking fixes, oggdemux now supports seeking to time and uses the downstream element to convert granulepos...
Original commit message from CVS:
* ext/ogg/gstoggdemux.c: (gst_ogg_demux_init),
(gst_ogg_demux_get_formats), (gst_ogg_demux_src_query),
(gst_ogg_demux_src_event), (gst_ogg_demux_src_convert),
(gst_ogg_demux_handle_event), (gst_ogg_demux_seek_before),
(_find_chain_get_unknown_part), (_find_streams_check),
(gst_ogg_demux_push), (gst_ogg_pad_push):
* ext/theora/theoradec.c: (theora_get_formats),
(theora_dec_src_convert), (theora_dec_sink_convert),
(theora_dec_src_query), (theora_dec_src_event), (theora_dec_event),
(theora_dec_chain):
* ext/vorbis/vorbisdec.c: (vorbis_dec_get_formats),
(vorbis_dec_convert), (vorbis_dec_src_query),
(vorbis_dec_src_event), (vorbis_dec_event):
More seeking fixes, oggdemux now supports seeking to time and
uses the downstream element to convert granulepos to time.
Seeking in theora-only ogg files now works.
2004-07-21 16:48:20 +00:00
|
|
|
/* still ok, got a granulepos then */
|
|
|
|
switch (*format) {
|
2004-10-18 19:12:32 +00:00
|
|
|
case GST_FORMAT_TIME:
|
ext/: More seeking fixes, oggdemux now supports seeking to time and uses the downstream element to convert granulepos...
Original commit message from CVS:
* ext/ogg/gstoggdemux.c: (gst_ogg_demux_init),
(gst_ogg_demux_get_formats), (gst_ogg_demux_src_query),
(gst_ogg_demux_src_event), (gst_ogg_demux_src_convert),
(gst_ogg_demux_handle_event), (gst_ogg_demux_seek_before),
(_find_chain_get_unknown_part), (_find_streams_check),
(gst_ogg_demux_push), (gst_ogg_pad_push):
* ext/theora/theoradec.c: (theora_get_formats),
(theora_dec_src_convert), (theora_dec_sink_convert),
(theora_dec_src_query), (theora_dec_src_event), (theora_dec_event),
(theora_dec_chain):
* ext/vorbis/vorbisdec.c: (vorbis_dec_get_formats),
(vorbis_dec_convert), (vorbis_dec_src_query),
(vorbis_dec_src_event), (vorbis_dec_event):
More seeking fixes, oggdemux now supports seeking to time and
uses the downstream element to convert granulepos to time.
Seeking in theora-only ogg files now works.
2004-07-21 16:48:20 +00:00
|
|
|
/* fine, result should be granulepos */
|
2004-10-18 19:12:32 +00:00
|
|
|
*value = time;
|
ext/: More seeking fixes, oggdemux now supports seeking to time and uses the downstream element to convert granulepos...
Original commit message from CVS:
* ext/ogg/gstoggdemux.c: (gst_ogg_demux_init),
(gst_ogg_demux_get_formats), (gst_ogg_demux_src_query),
(gst_ogg_demux_src_event), (gst_ogg_demux_src_convert),
(gst_ogg_demux_handle_event), (gst_ogg_demux_seek_before),
(_find_chain_get_unknown_part), (_find_streams_check),
(gst_ogg_demux_push), (gst_ogg_pad_push):
* ext/theora/theoradec.c: (theora_get_formats),
(theora_dec_src_convert), (theora_dec_sink_convert),
(theora_dec_src_query), (theora_dec_src_event), (theora_dec_event),
(theora_dec_chain):
* ext/vorbis/vorbisdec.c: (vorbis_dec_get_formats),
(vorbis_dec_convert), (vorbis_dec_src_query),
(vorbis_dec_src_event), (vorbis_dec_event):
More seeking fixes, oggdemux now supports seeking to time and
uses the downstream element to convert granulepos to time.
Seeking in theora-only ogg files now works.
2004-07-21 16:48:20 +00:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
/* something we have to ask our peer */
|
2004-07-28 15:40:38 +00:00
|
|
|
if (GST_PAD_PEER (pad)) {
|
|
|
|
res = gst_pad_convert (GST_PAD_PEER (pad),
|
2004-10-18 19:12:32 +00:00
|
|
|
GST_FORMAT_TIME, time, format, value);
|
2004-10-18 15:23:41 +00:00
|
|
|
} else {
|
|
|
|
res = FALSE;
|
2004-07-28 15:40:38 +00:00
|
|
|
}
|
ext/: More seeking fixes, oggdemux now supports seeking to time and uses the downstream element to convert granulepos...
Original commit message from CVS:
* ext/ogg/gstoggdemux.c: (gst_ogg_demux_init),
(gst_ogg_demux_get_formats), (gst_ogg_demux_src_query),
(gst_ogg_demux_src_event), (gst_ogg_demux_src_convert),
(gst_ogg_demux_handle_event), (gst_ogg_demux_seek_before),
(_find_chain_get_unknown_part), (_find_streams_check),
(gst_ogg_demux_push), (gst_ogg_pad_push):
* ext/theora/theoradec.c: (theora_get_formats),
(theora_dec_src_convert), (theora_dec_sink_convert),
(theora_dec_src_query), (theora_dec_src_event), (theora_dec_event),
(theora_dec_chain):
* ext/vorbis/vorbisdec.c: (vorbis_dec_get_formats),
(vorbis_dec_convert), (vorbis_dec_src_query),
(vorbis_dec_src_event), (vorbis_dec_event):
More seeking fixes, oggdemux now supports seeking to time and
uses the downstream element to convert granulepos to time.
Seeking in theora-only ogg files now works.
2004-07-21 16:48:20 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2003-11-24 04:08:48 +00:00
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
2004-01-29 02:50:20 +00:00
|
|
|
/* The current seeking implementation is the most simple I could come up with:
|
|
|
|
* - when seeking forwards, just discard data until desired position is reached
|
|
|
|
* - when seeking backwards, seek to beginning and seek forward from there
|
|
|
|
* Anyone is free to improve this algorithm as it is quite stupid and probably
|
|
|
|
* really slow.
|
ext/: More seeking fixes, oggdemux now supports seeking to time and uses the downstream element to convert granulepos...
Original commit message from CVS:
* ext/ogg/gstoggdemux.c: (gst_ogg_demux_init),
(gst_ogg_demux_get_formats), (gst_ogg_demux_src_query),
(gst_ogg_demux_src_event), (gst_ogg_demux_src_convert),
(gst_ogg_demux_handle_event), (gst_ogg_demux_seek_before),
(_find_chain_get_unknown_part), (_find_streams_check),
(gst_ogg_demux_push), (gst_ogg_pad_push):
* ext/theora/theoradec.c: (theora_get_formats),
(theora_dec_src_convert), (theora_dec_sink_convert),
(theora_dec_src_query), (theora_dec_src_event), (theora_dec_event),
(theora_dec_chain):
* ext/vorbis/vorbisdec.c: (vorbis_dec_get_formats),
(vorbis_dec_convert), (vorbis_dec_src_query),
(vorbis_dec_src_event), (vorbis_dec_event):
More seeking fixes, oggdemux now supports seeking to time and
uses the downstream element to convert granulepos to time.
Seeking in theora-only ogg files now works.
2004-07-21 16:48:20 +00:00
|
|
|
*
|
|
|
|
* The seeking position can be specified as the granulepos in case a decoder
|
|
|
|
* plugin can give us a correct granulepos, or in timestamps.
|
|
|
|
* In the case of a time seek, we repeadedly ask the peer element to
|
|
|
|
* convert the granulepos in the page to a timestamp. We go back to playing
|
|
|
|
* when the timestamp is the requested one (or close enough to it).
|
2004-01-29 02:50:20 +00:00
|
|
|
*/
|
2003-11-24 04:08:48 +00:00
|
|
|
static gboolean
|
2004-03-14 22:34:34 +00:00
|
|
|
gst_ogg_demux_src_event (GstPad * pad, GstEvent * event)
|
2003-11-24 04:08:48 +00:00
|
|
|
{
|
|
|
|
GstOggDemux *ogg;
|
2004-01-29 02:50:20 +00:00
|
|
|
GstOggPad *cur;
|
2003-11-24 04:08:48 +00:00
|
|
|
|
|
|
|
ogg = GST_OGG_DEMUX (gst_pad_get_parent (pad));
|
2004-01-29 02:50:20 +00:00
|
|
|
cur = gst_ogg_get_pad_by_pad (ogg, pad);
|
ext/: More seeking fixes, oggdemux now supports seeking to time and uses the downstream element to convert granulepos...
Original commit message from CVS:
* ext/ogg/gstoggdemux.c: (gst_ogg_demux_init),
(gst_ogg_demux_get_formats), (gst_ogg_demux_src_query),
(gst_ogg_demux_src_event), (gst_ogg_demux_src_convert),
(gst_ogg_demux_handle_event), (gst_ogg_demux_seek_before),
(_find_chain_get_unknown_part), (_find_streams_check),
(gst_ogg_demux_push), (gst_ogg_pad_push):
* ext/theora/theoradec.c: (theora_get_formats),
(theora_dec_src_convert), (theora_dec_sink_convert),
(theora_dec_src_query), (theora_dec_src_event), (theora_dec_event),
(theora_dec_chain):
* ext/vorbis/vorbisdec.c: (vorbis_dec_get_formats),
(vorbis_dec_convert), (vorbis_dec_src_query),
(vorbis_dec_src_event), (vorbis_dec_event):
More seeking fixes, oggdemux now supports seeking to time and
uses the downstream element to convert granulepos to time.
Seeking in theora-only ogg files now works.
2004-07-21 16:48:20 +00:00
|
|
|
|
2004-01-29 02:50:20 +00:00
|
|
|
/* FIXME: optimize this so events from inactive chains work?
|
|
|
|
* in theory there shouldn't be an exisiting pad for inactive chains */
|
2004-03-14 22:34:34 +00:00
|
|
|
if (cur == NULL)
|
|
|
|
goto error;
|
|
|
|
|
2003-11-24 04:08:48 +00:00
|
|
|
switch (GST_EVENT_TYPE (event)) {
|
|
|
|
case GST_EVENT_SEEK:
|
2004-01-29 02:50:20 +00:00
|
|
|
{
|
2004-10-29 15:59:37 +00:00
|
|
|
gint64 offset, position, total, seek_offset;
|
ext/: More seeking fixes, oggdemux now supports seeking to time and uses the downstream element to convert granulepos...
Original commit message from CVS:
* ext/ogg/gstoggdemux.c: (gst_ogg_demux_init),
(gst_ogg_demux_get_formats), (gst_ogg_demux_src_query),
(gst_ogg_demux_src_event), (gst_ogg_demux_src_convert),
(gst_ogg_demux_handle_event), (gst_ogg_demux_seek_before),
(_find_chain_get_unknown_part), (_find_streams_check),
(gst_ogg_demux_push), (gst_ogg_pad_push):
* ext/theora/theoradec.c: (theora_get_formats),
(theora_dec_src_convert), (theora_dec_sink_convert),
(theora_dec_src_query), (theora_dec_src_event), (theora_dec_event),
(theora_dec_chain):
* ext/vorbis/vorbisdec.c: (vorbis_dec_get_formats),
(vorbis_dec_convert), (vorbis_dec_src_query),
(vorbis_dec_src_event), (vorbis_dec_event):
More seeking fixes, oggdemux now supports seeking to time and
uses the downstream element to convert granulepos to time.
Seeking in theora-only ogg files now works.
2004-07-21 16:48:20 +00:00
|
|
|
GstFormat format, my_format;
|
|
|
|
gboolean res;
|
2004-03-14 22:34:34 +00:00
|
|
|
|
ext/: More seeking fixes, oggdemux now supports seeking to time and uses the downstream element to convert granulepos...
Original commit message from CVS:
* ext/ogg/gstoggdemux.c: (gst_ogg_demux_init),
(gst_ogg_demux_get_formats), (gst_ogg_demux_src_query),
(gst_ogg_demux_src_event), (gst_ogg_demux_src_convert),
(gst_ogg_demux_handle_event), (gst_ogg_demux_seek_before),
(_find_chain_get_unknown_part), (_find_streams_check),
(gst_ogg_demux_push), (gst_ogg_pad_push):
* ext/theora/theoradec.c: (theora_get_formats),
(theora_dec_src_convert), (theora_dec_sink_convert),
(theora_dec_src_query), (theora_dec_src_event), (theora_dec_event),
(theora_dec_chain):
* ext/vorbis/vorbisdec.c: (vorbis_dec_get_formats),
(vorbis_dec_convert), (vorbis_dec_src_query),
(vorbis_dec_src_event), (vorbis_dec_event):
More seeking fixes, oggdemux now supports seeking to time and
uses the downstream element to convert granulepos to time.
Seeking in theora-only ogg files now works.
2004-07-21 16:48:20 +00:00
|
|
|
format = GST_EVENT_SEEK_FORMAT (event);
|
2004-01-29 02:50:20 +00:00
|
|
|
offset = GST_EVENT_SEEK_OFFSET (event);
|
ext/: More seeking fixes, oggdemux now supports seeking to time and uses the downstream element to convert granulepos...
Original commit message from CVS:
* ext/ogg/gstoggdemux.c: (gst_ogg_demux_init),
(gst_ogg_demux_get_formats), (gst_ogg_demux_src_query),
(gst_ogg_demux_src_event), (gst_ogg_demux_src_convert),
(gst_ogg_demux_handle_event), (gst_ogg_demux_seek_before),
(_find_chain_get_unknown_part), (_find_streams_check),
(gst_ogg_demux_push), (gst_ogg_pad_push):
* ext/theora/theoradec.c: (theora_get_formats),
(theora_dec_src_convert), (theora_dec_sink_convert),
(theora_dec_src_query), (theora_dec_src_event), (theora_dec_event),
(theora_dec_chain):
* ext/vorbis/vorbisdec.c: (vorbis_dec_get_formats),
(vorbis_dec_convert), (vorbis_dec_src_query),
(vorbis_dec_src_event), (vorbis_dec_event):
More seeking fixes, oggdemux now supports seeking to time and
uses the downstream element to convert granulepos to time.
Seeking in theora-only ogg files now works.
2004-07-21 16:48:20 +00:00
|
|
|
|
|
|
|
my_format = format;
|
|
|
|
|
|
|
|
/* get position, we'll need it later to decide what direction
|
|
|
|
* we need to seek in */
|
|
|
|
res = gst_ogg_demux_src_query (pad,
|
|
|
|
GST_QUERY_POSITION, &my_format, &position);
|
|
|
|
if (!res)
|
|
|
|
goto error;
|
|
|
|
|
2004-01-29 02:50:20 +00:00
|
|
|
switch (GST_EVENT_SEEK_METHOD (event)) {
|
2004-03-15 19:32:28 +00:00
|
|
|
case GST_SEEK_METHOD_END:
|
ext/: More seeking fixes, oggdemux now supports seeking to time and uses the downstream element to convert granulepos...
Original commit message from CVS:
* ext/ogg/gstoggdemux.c: (gst_ogg_demux_init),
(gst_ogg_demux_get_formats), (gst_ogg_demux_src_query),
(gst_ogg_demux_src_event), (gst_ogg_demux_src_convert),
(gst_ogg_demux_handle_event), (gst_ogg_demux_seek_before),
(_find_chain_get_unknown_part), (_find_streams_check),
(gst_ogg_demux_push), (gst_ogg_pad_push):
* ext/theora/theoradec.c: (theora_get_formats),
(theora_dec_src_convert), (theora_dec_sink_convert),
(theora_dec_src_query), (theora_dec_src_event), (theora_dec_event),
(theora_dec_chain):
* ext/vorbis/vorbisdec.c: (vorbis_dec_get_formats),
(vorbis_dec_convert), (vorbis_dec_src_query),
(vorbis_dec_src_event), (vorbis_dec_event):
More seeking fixes, oggdemux now supports seeking to time and
uses the downstream element to convert granulepos to time.
Seeking in theora-only ogg files now works.
2004-07-21 16:48:20 +00:00
|
|
|
{
|
|
|
|
gint64 value;
|
|
|
|
|
|
|
|
/* invalid offset */
|
|
|
|
if (offset > 0)
|
|
|
|
goto error;
|
|
|
|
|
|
|
|
/* calculate total length first */
|
|
|
|
res = gst_ogg_demux_src_query (pad,
|
|
|
|
GST_QUERY_TOTAL, &my_format, &value);
|
|
|
|
if (!res)
|
2004-03-15 19:32:28 +00:00
|
|
|
goto error;
|
ext/: More seeking fixes, oggdemux now supports seeking to time and uses the downstream element to convert granulepos...
Original commit message from CVS:
* ext/ogg/gstoggdemux.c: (gst_ogg_demux_init),
(gst_ogg_demux_get_formats), (gst_ogg_demux_src_query),
(gst_ogg_demux_src_event), (gst_ogg_demux_src_convert),
(gst_ogg_demux_handle_event), (gst_ogg_demux_seek_before),
(_find_chain_get_unknown_part), (_find_streams_check),
(gst_ogg_demux_push), (gst_ogg_pad_push):
* ext/theora/theoradec.c: (theora_get_formats),
(theora_dec_src_convert), (theora_dec_sink_convert),
(theora_dec_src_query), (theora_dec_src_event), (theora_dec_event),
(theora_dec_chain):
* ext/vorbis/vorbisdec.c: (vorbis_dec_get_formats),
(vorbis_dec_convert), (vorbis_dec_src_query),
(vorbis_dec_src_event), (vorbis_dec_event):
More seeking fixes, oggdemux now supports seeking to time and
uses the downstream element to convert granulepos to time.
Seeking in theora-only ogg files now works.
2004-07-21 16:48:20 +00:00
|
|
|
|
|
|
|
/* requested position is end + offset */
|
|
|
|
offset = value + offset;
|
2004-03-15 19:32:28 +00:00
|
|
|
break;
|
ext/: More seeking fixes, oggdemux now supports seeking to time and uses the downstream element to convert granulepos...
Original commit message from CVS:
* ext/ogg/gstoggdemux.c: (gst_ogg_demux_init),
(gst_ogg_demux_get_formats), (gst_ogg_demux_src_query),
(gst_ogg_demux_src_event), (gst_ogg_demux_src_convert),
(gst_ogg_demux_handle_event), (gst_ogg_demux_seek_before),
(_find_chain_get_unknown_part), (_find_streams_check),
(gst_ogg_demux_push), (gst_ogg_pad_push):
* ext/theora/theoradec.c: (theora_get_formats),
(theora_dec_src_convert), (theora_dec_sink_convert),
(theora_dec_src_query), (theora_dec_src_event), (theora_dec_event),
(theora_dec_chain):
* ext/vorbis/vorbisdec.c: (vorbis_dec_get_formats),
(vorbis_dec_convert), (vorbis_dec_src_query),
(vorbis_dec_src_event), (vorbis_dec_event):
More seeking fixes, oggdemux now supports seeking to time and
uses the downstream element to convert granulepos to time.
Seeking in theora-only ogg files now works.
2004-07-21 16:48:20 +00:00
|
|
|
}
|
2004-03-15 19:32:28 +00:00
|
|
|
case GST_SEEK_METHOD_CUR:
|
ext/: More seeking fixes, oggdemux now supports seeking to time and uses the downstream element to convert granulepos...
Original commit message from CVS:
* ext/ogg/gstoggdemux.c: (gst_ogg_demux_init),
(gst_ogg_demux_get_formats), (gst_ogg_demux_src_query),
(gst_ogg_demux_src_event), (gst_ogg_demux_src_convert),
(gst_ogg_demux_handle_event), (gst_ogg_demux_seek_before),
(_find_chain_get_unknown_part), (_find_streams_check),
(gst_ogg_demux_push), (gst_ogg_pad_push):
* ext/theora/theoradec.c: (theora_get_formats),
(theora_dec_src_convert), (theora_dec_sink_convert),
(theora_dec_src_query), (theora_dec_src_event), (theora_dec_event),
(theora_dec_chain):
* ext/vorbis/vorbisdec.c: (vorbis_dec_get_formats),
(vorbis_dec_convert), (vorbis_dec_src_query),
(vorbis_dec_src_event), (vorbis_dec_event):
More seeking fixes, oggdemux now supports seeking to time and
uses the downstream element to convert granulepos to time.
Seeking in theora-only ogg files now works.
2004-07-21 16:48:20 +00:00
|
|
|
{
|
|
|
|
/* add current position to offset */
|
|
|
|
offset = position + offset;
|
2004-03-15 19:32:28 +00:00
|
|
|
break;
|
ext/: More seeking fixes, oggdemux now supports seeking to time and uses the downstream element to convert granulepos...
Original commit message from CVS:
* ext/ogg/gstoggdemux.c: (gst_ogg_demux_init),
(gst_ogg_demux_get_formats), (gst_ogg_demux_src_query),
(gst_ogg_demux_src_event), (gst_ogg_demux_src_convert),
(gst_ogg_demux_handle_event), (gst_ogg_demux_seek_before),
(_find_chain_get_unknown_part), (_find_streams_check),
(gst_ogg_demux_push), (gst_ogg_pad_push):
* ext/theora/theoradec.c: (theora_get_formats),
(theora_dec_src_convert), (theora_dec_sink_convert),
(theora_dec_src_query), (theora_dec_src_event), (theora_dec_event),
(theora_dec_chain):
* ext/vorbis/vorbisdec.c: (vorbis_dec_get_formats),
(vorbis_dec_convert), (vorbis_dec_src_query),
(vorbis_dec_src_event), (vorbis_dec_event):
More seeking fixes, oggdemux now supports seeking to time and
uses the downstream element to convert granulepos to time.
Seeking in theora-only ogg files now works.
2004-07-21 16:48:20 +00:00
|
|
|
}
|
2004-03-15 19:32:28 +00:00
|
|
|
case GST_SEEK_METHOD_SET:
|
ext/: More seeking fixes, oggdemux now supports seeking to time and uses the downstream element to convert granulepos...
Original commit message from CVS:
* ext/ogg/gstoggdemux.c: (gst_ogg_demux_init),
(gst_ogg_demux_get_formats), (gst_ogg_demux_src_query),
(gst_ogg_demux_src_event), (gst_ogg_demux_src_convert),
(gst_ogg_demux_handle_event), (gst_ogg_demux_seek_before),
(_find_chain_get_unknown_part), (_find_streams_check),
(gst_ogg_demux_push), (gst_ogg_pad_push):
* ext/theora/theoradec.c: (theora_get_formats),
(theora_dec_src_convert), (theora_dec_sink_convert),
(theora_dec_src_query), (theora_dec_src_event), (theora_dec_event),
(theora_dec_chain):
* ext/vorbis/vorbisdec.c: (vorbis_dec_get_formats),
(vorbis_dec_convert), (vorbis_dec_src_query),
(vorbis_dec_src_event), (vorbis_dec_event):
More seeking fixes, oggdemux now supports seeking to time and
uses the downstream element to convert granulepos to time.
Seeking in theora-only ogg files now works.
2004-07-21 16:48:20 +00:00
|
|
|
/* offset and format are fine here */
|
2004-03-15 19:32:28 +00:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
g_warning ("invalid seek method in seek event");
|
|
|
|
goto error;
|
2004-01-29 02:50:20 +00:00
|
|
|
}
|
ext/: More seeking fixes, oggdemux now supports seeking to time and uses the downstream element to convert granulepos...
Original commit message from CVS:
* ext/ogg/gstoggdemux.c: (gst_ogg_demux_init),
(gst_ogg_demux_get_formats), (gst_ogg_demux_src_query),
(gst_ogg_demux_src_event), (gst_ogg_demux_src_convert),
(gst_ogg_demux_handle_event), (gst_ogg_demux_seek_before),
(_find_chain_get_unknown_part), (_find_streams_check),
(gst_ogg_demux_push), (gst_ogg_pad_push):
* ext/theora/theoradec.c: (theora_get_formats),
(theora_dec_src_convert), (theora_dec_sink_convert),
(theora_dec_src_query), (theora_dec_src_event), (theora_dec_event),
(theora_dec_chain):
* ext/vorbis/vorbisdec.c: (vorbis_dec_get_formats),
(vorbis_dec_convert), (vorbis_dec_src_query),
(vorbis_dec_src_event), (vorbis_dec_event):
More seeking fixes, oggdemux now supports seeking to time and
uses the downstream element to convert granulepos to time.
Seeking in theora-only ogg files now works.
2004-07-21 16:48:20 +00:00
|
|
|
|
2004-10-18 19:12:32 +00:00
|
|
|
my_format = GST_FORMAT_TIME;
|
|
|
|
if (format != GST_FORMAT_TIME) {
|
2004-10-23 10:06:32 +00:00
|
|
|
if (!GST_PAD_PEER (pad) ||
|
|
|
|
!gst_pad_convert (GST_PAD_PEER (pad), format,
|
2004-10-18 19:12:32 +00:00
|
|
|
offset, &my_format, &position))
|
2004-03-15 19:32:28 +00:00
|
|
|
goto error;
|
2004-10-18 19:12:32 +00:00
|
|
|
} else {
|
|
|
|
position = offset;
|
2004-01-30 20:57:41 +00:00
|
|
|
}
|
2004-10-18 19:12:32 +00:00
|
|
|
if (!gst_ogg_demux_src_query (pad, GST_QUERY_TOTAL, &my_format, &total))
|
|
|
|
goto error;
|
2004-10-18 15:49:00 +00:00
|
|
|
if (position < 0)
|
|
|
|
position = 0;
|
2004-10-18 19:12:32 +00:00
|
|
|
else if (position > total)
|
|
|
|
position = total;
|
2004-10-29 15:59:37 +00:00
|
|
|
seek_offset = gst_file_pad_get_length (ogg->sinkpad) *
|
|
|
|
((gdouble) position) / ((gdouble) total);
|
|
|
|
if (gst_file_pad_seek (ogg->sinkpad, seek_offset,
|
2004-10-18 19:12:32 +00:00
|
|
|
GST_SEEK_METHOD_SET) != 0)
|
2004-10-18 15:23:41 +00:00
|
|
|
goto error;
|
2004-10-29 15:59:37 +00:00
|
|
|
ogg->seek_try = 1;
|
2004-10-18 15:23:41 +00:00
|
|
|
ogg_sync_clear (&ogg->sync);
|
|
|
|
|
2004-10-29 15:59:37 +00:00
|
|
|
GST_OGG_SET_STATE (ogg, GST_OGG_STATE_SEEK);
|
2004-01-31 17:19:21 +00:00
|
|
|
FOR_PAD_IN_CURRENT_CHAIN (ogg, pad,
|
2004-11-25 20:31:22 +00:00
|
|
|
pad->flags |= GST_OGG_PAD_NEEDS_DISCONT;
|
|
|
|
);
|
2004-10-20 16:24:18 +00:00
|
|
|
if (GST_EVENT_SEEK_FLAGS (event) & GST_SEEK_FLAG_FLUSH) {
|
|
|
|
FOR_PAD_IN_CURRENT_CHAIN (ogg, pad,
|
2004-11-25 20:31:22 +00:00
|
|
|
pad->flags |= GST_OGG_PAD_NEEDS_FLUSH;
|
|
|
|
);
|
2004-10-20 16:24:18 +00:00
|
|
|
}
|
ext/: More seeking fixes, oggdemux now supports seeking to time and uses the downstream element to convert granulepos...
Original commit message from CVS:
* ext/ogg/gstoggdemux.c: (gst_ogg_demux_init),
(gst_ogg_demux_get_formats), (gst_ogg_demux_src_query),
(gst_ogg_demux_src_event), (gst_ogg_demux_src_convert),
(gst_ogg_demux_handle_event), (gst_ogg_demux_seek_before),
(_find_chain_get_unknown_part), (_find_streams_check),
(gst_ogg_demux_push), (gst_ogg_pad_push):
* ext/theora/theoradec.c: (theora_get_formats),
(theora_dec_src_convert), (theora_dec_sink_convert),
(theora_dec_src_query), (theora_dec_src_event), (theora_dec_event),
(theora_dec_chain):
* ext/vorbis/vorbisdec.c: (vorbis_dec_get_formats),
(vorbis_dec_convert), (vorbis_dec_src_query),
(vorbis_dec_src_event), (vorbis_dec_event):
More seeking fixes, oggdemux now supports seeking to time and
uses the downstream element to convert granulepos to time.
Seeking in theora-only ogg files now works.
2004-07-21 16:48:20 +00:00
|
|
|
GST_DEBUG_OBJECT (ogg,
|
|
|
|
"initiating seeking to format %d, offset %" G_GUINT64_FORMAT, format,
|
2004-03-15 19:32:28 +00:00
|
|
|
offset);
|
ext/: More seeking fixes, oggdemux now supports seeking to time and uses the downstream element to convert granulepos...
Original commit message from CVS:
* ext/ogg/gstoggdemux.c: (gst_ogg_demux_init),
(gst_ogg_demux_get_formats), (gst_ogg_demux_src_query),
(gst_ogg_demux_src_event), (gst_ogg_demux_src_convert),
(gst_ogg_demux_handle_event), (gst_ogg_demux_seek_before),
(_find_chain_get_unknown_part), (_find_streams_check),
(gst_ogg_demux_push), (gst_ogg_pad_push):
* ext/theora/theoradec.c: (theora_get_formats),
(theora_dec_src_convert), (theora_dec_sink_convert),
(theora_dec_src_query), (theora_dec_src_event), (theora_dec_event),
(theora_dec_chain):
* ext/vorbis/vorbisdec.c: (vorbis_dec_get_formats),
(vorbis_dec_convert), (vorbis_dec_src_query),
(vorbis_dec_src_event), (vorbis_dec_event):
More seeking fixes, oggdemux now supports seeking to time and
uses the downstream element to convert granulepos to time.
Seeking in theora-only ogg files now works.
2004-07-21 16:48:20 +00:00
|
|
|
|
|
|
|
/* store format and position we seek to */
|
2004-03-14 22:34:34 +00:00
|
|
|
ogg->seek_pad = cur;
|
2004-10-29 15:59:37 +00:00
|
|
|
ogg->seek_to = position;
|
|
|
|
ogg->seek_format = GST_FORMAT_TIME;
|
|
|
|
ogg->seek_offset = seek_offset;
|
ext/: More seeking fixes, oggdemux now supports seeking to time and uses the downstream element to convert granulepos...
Original commit message from CVS:
* ext/ogg/gstoggdemux.c: (gst_ogg_demux_init),
(gst_ogg_demux_get_formats), (gst_ogg_demux_src_query),
(gst_ogg_demux_src_event), (gst_ogg_demux_src_convert),
(gst_ogg_demux_handle_event), (gst_ogg_demux_seek_before),
(_find_chain_get_unknown_part), (_find_streams_check),
(gst_ogg_demux_push), (gst_ogg_pad_push):
* ext/theora/theoradec.c: (theora_get_formats),
(theora_dec_src_convert), (theora_dec_sink_convert),
(theora_dec_src_query), (theora_dec_src_event), (theora_dec_event),
(theora_dec_chain):
* ext/vorbis/vorbisdec.c: (vorbis_dec_get_formats),
(vorbis_dec_convert), (vorbis_dec_src_query),
(vorbis_dec_src_event), (vorbis_dec_event):
More seeking fixes, oggdemux now supports seeking to time and
uses the downstream element to convert granulepos to time.
Seeking in theora-only ogg files now works.
2004-07-21 16:48:20 +00:00
|
|
|
|
2004-01-29 02:50:20 +00:00
|
|
|
gst_event_unref (event);
|
|
|
|
return TRUE;
|
|
|
|
}
|
2003-11-24 04:08:48 +00:00
|
|
|
default:
|
2004-01-31 17:19:21 +00:00
|
|
|
return gst_pad_event_default (pad, event);
|
2003-11-24 04:08:48 +00:00
|
|
|
}
|
|
|
|
|
2004-01-31 17:19:21 +00:00
|
|
|
g_assert_not_reached ();
|
2004-03-14 22:34:34 +00:00
|
|
|
|
2004-01-31 17:19:21 +00:00
|
|
|
error:
|
2003-11-24 04:08:48 +00:00
|
|
|
gst_event_unref (event);
|
|
|
|
return FALSE;
|
|
|
|
}
|
2004-01-29 02:50:20 +00:00
|
|
|
|
ext/: More seeking fixes, oggdemux now supports seeking to time and uses the downstream element to convert granulepos...
Original commit message from CVS:
* ext/ogg/gstoggdemux.c: (gst_ogg_demux_init),
(gst_ogg_demux_get_formats), (gst_ogg_demux_src_query),
(gst_ogg_demux_src_event), (gst_ogg_demux_src_convert),
(gst_ogg_demux_handle_event), (gst_ogg_demux_seek_before),
(_find_chain_get_unknown_part), (_find_streams_check),
(gst_ogg_demux_push), (gst_ogg_pad_push):
* ext/theora/theoradec.c: (theora_get_formats),
(theora_dec_src_convert), (theora_dec_sink_convert),
(theora_dec_src_query), (theora_dec_src_event), (theora_dec_event),
(theora_dec_chain):
* ext/vorbis/vorbisdec.c: (vorbis_dec_get_formats),
(vorbis_dec_convert), (vorbis_dec_src_query),
(vorbis_dec_src_event), (vorbis_dec_event):
More seeking fixes, oggdemux now supports seeking to time and
uses the downstream element to convert granulepos to time.
Seeking in theora-only ogg files now works.
2004-07-21 16:48:20 +00:00
|
|
|
static gboolean
|
|
|
|
gst_ogg_demux_src_convert (GstPad * pad,
|
|
|
|
GstFormat src_format, gint64 src_value,
|
|
|
|
GstFormat * dest_format, gint64 * dest_value)
|
|
|
|
{
|
|
|
|
gboolean res = FALSE;
|
|
|
|
GstOggDemux *ogg;
|
|
|
|
GstOggPad *cur;
|
|
|
|
|
|
|
|
ogg = GST_OGG_DEMUX (gst_pad_get_parent (pad));
|
|
|
|
cur = gst_ogg_get_pad_by_pad (ogg, pad);
|
|
|
|
|
|
|
|
/* fill me, not sure with what... */
|
|
|
|
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
2004-01-29 02:50:20 +00:00
|
|
|
static void
|
2004-03-14 22:34:34 +00:00
|
|
|
gst_ogg_start_playing (GstOggDemux * ogg)
|
2004-01-29 02:50:20 +00:00
|
|
|
{
|
2004-07-02 03:41:22 +00:00
|
|
|
GST_DEBUG_OBJECT (ogg, "done with setup, changing to playback now");
|
|
|
|
if (gst_file_pad_seek (ogg->sinkpad, 0, GST_SEEK_METHOD_SET) != 0) {
|
2004-03-14 22:34:34 +00:00
|
|
|
GST_ELEMENT_ERROR (ogg, CORE, SEEK, (NULL),
|
2004-03-15 19:32:28 +00:00
|
|
|
("cannot seek to start after EOS"));
|
2004-01-29 02:50:20 +00:00
|
|
|
}
|
2004-07-02 03:41:22 +00:00
|
|
|
ogg_sync_clear (&ogg->sync);
|
|
|
|
if (ogg->current_chain >= 0) {
|
|
|
|
ogg->current_chain = 0;
|
|
|
|
} else {
|
|
|
|
gst_ogg_add_chain (ogg);
|
|
|
|
}
|
2004-01-29 02:50:20 +00:00
|
|
|
GST_FLAG_UNSET (ogg, GST_OGG_FLAG_EOS);
|
|
|
|
GST_FLAG_SET (ogg, GST_OGG_FLAG_WAIT_FOR_DISCONT);
|
|
|
|
GST_OGG_SET_STATE (ogg, GST_OGG_STATE_PLAY);
|
|
|
|
gst_ogg_print (ogg);
|
|
|
|
}
|
|
|
|
|
2004-07-02 03:41:22 +00:00
|
|
|
static gboolean
|
2004-03-14 22:34:34 +00:00
|
|
|
gst_ogg_demux_handle_event (GstPad * pad, GstEvent * event)
|
2003-11-24 04:08:48 +00:00
|
|
|
{
|
|
|
|
GstOggDemux *ogg = GST_OGG_DEMUX (gst_pad_get_parent (pad));
|
2004-03-14 22:34:34 +00:00
|
|
|
|
2003-11-24 04:08:48 +00:00
|
|
|
switch (GST_EVENT_TYPE (event)) {
|
|
|
|
case GST_EVENT_DISCONTINUOUS:
|
2004-01-29 02:50:20 +00:00
|
|
|
GST_DEBUG_OBJECT (ogg, "got a discont event");
|
|
|
|
ogg_sync_reset (&ogg->sync);
|
|
|
|
gst_event_unref (event);
|
|
|
|
GST_FLAG_UNSET (ogg, GST_OGG_FLAG_WAIT_FOR_DISCONT);
|
2004-01-31 17:19:21 +00:00
|
|
|
FOR_PAD_IN_CURRENT_CHAIN (ogg, pad,
|
2004-11-25 20:31:22 +00:00
|
|
|
pad->flags |= GST_OGG_PAD_NEEDS_DISCONT;
|
|
|
|
);
|
2003-11-24 04:08:48 +00:00
|
|
|
break;
|
2004-07-02 03:41:22 +00:00
|
|
|
default:
|
|
|
|
gst_pad_event_default (pad, event);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return TRUE;
|
|
|
|
}
|
2004-03-15 19:32:28 +00:00
|
|
|
|
2004-07-02 03:41:22 +00:00
|
|
|
static void
|
|
|
|
gst_ogg_demux_eos (GstOggDemux * ogg)
|
|
|
|
{
|
|
|
|
guint i;
|
|
|
|
GSList *walk;
|
|
|
|
GstEvent *event;
|
2004-03-15 19:32:28 +00:00
|
|
|
|
2004-07-02 03:41:22 +00:00
|
|
|
GST_DEBUG_OBJECT (ogg, "got EOS");
|
|
|
|
ogg->current_chain = -1;
|
|
|
|
if (ogg->state == GST_OGG_STATE_SETUP) {
|
|
|
|
gst_ogg_start_playing (ogg);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
event = gst_event_new (GST_EVENT_EOS);
|
|
|
|
for (i = 0; i < ogg->chains->len; i++) {
|
|
|
|
GstOggChain *chain = &g_array_index (ogg->chains, GstOggChain, i);
|
2004-03-15 19:32:28 +00:00
|
|
|
|
2004-07-02 03:41:22 +00:00
|
|
|
for (walk = chain->pads; walk; walk = g_slist_next (walk)) {
|
|
|
|
GstOggPad *pad = (GstOggPad *) walk->data;
|
|
|
|
|
|
|
|
if (pad->pad && GST_PAD_IS_USABLE (pad->pad)) {
|
|
|
|
gst_data_ref (GST_DATA (event));
|
|
|
|
gst_pad_push (pad->pad, GST_DATA (event));
|
2003-11-24 04:08:48 +00:00
|
|
|
}
|
2004-07-02 03:41:22 +00:00
|
|
|
}
|
2003-11-24 04:08:48 +00:00
|
|
|
}
|
2004-07-02 03:41:22 +00:00
|
|
|
gst_element_set_eos (GST_ELEMENT (ogg));
|
|
|
|
gst_event_unref (event);
|
|
|
|
}
|
|
|
|
|
|
|
|
static GstOggPad *
|
|
|
|
gst_ogg_pad_get_in_chain (GstOggDemux * ogg, guint chain, int serial)
|
|
|
|
{
|
|
|
|
FOR_PAD_IN_CHAIN (ogg, pad, chain, if (pad->serial == serial)
|
|
|
|
return pad;);
|
|
|
|
return NULL;
|
2003-11-24 04:08:48 +00:00
|
|
|
}
|
2004-01-29 02:50:20 +00:00
|
|
|
|
|
|
|
/* get the pad with the given serial in the current stream or NULL if none */
|
|
|
|
static GstOggPad *
|
2004-03-14 22:34:34 +00:00
|
|
|
gst_ogg_pad_get_in_current_chain (GstOggDemux * ogg, int serial)
|
2004-01-29 02:50:20 +00:00
|
|
|
{
|
2004-03-14 22:34:34 +00:00
|
|
|
if (ogg->current_chain == -1)
|
|
|
|
return NULL;
|
2004-01-29 02:50:20 +00:00
|
|
|
g_return_val_if_fail (ogg->current_chain < ogg->chains->len, NULL);
|
2004-07-02 03:41:22 +00:00
|
|
|
return gst_ogg_pad_get_in_chain (ogg, ogg->current_chain, serial);
|
|
|
|
}
|
2004-01-29 02:50:20 +00:00
|
|
|
|
2004-07-02 03:41:22 +00:00
|
|
|
/* FIXME: HACK - i dunno if this is supported ogg API */
|
|
|
|
static guint
|
|
|
|
gst_ogg_page_get_length (ogg_page * page)
|
|
|
|
{
|
|
|
|
return page->header_len + page->body_len;
|
|
|
|
}
|
|
|
|
|
|
|
|
static gint64
|
|
|
|
gst_ogg_demux_position (GstOggDemux * ogg)
|
|
|
|
{
|
|
|
|
gint64 pos = gst_file_pad_tell (ogg->sinkpad);
|
|
|
|
|
|
|
|
if (pos < 0)
|
|
|
|
return pos;
|
|
|
|
|
|
|
|
return pos - ogg->sync.fill + ogg->sync.returned;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* END HACK */
|
|
|
|
|
|
|
|
/* fill in values from this page */
|
|
|
|
#include <signal.h>
|
|
|
|
static void
|
|
|
|
gst_ogg_pad_populate (GstOggDemux * ogg, GstOggPad * pad, ogg_page * page)
|
|
|
|
{
|
|
|
|
gint64 start, end;
|
|
|
|
|
2004-10-18 15:23:41 +00:00
|
|
|
if (pad->start > ogg_page_granulepos (page) && ogg_page_granulepos (page) > 0) {
|
|
|
|
pad->start = ogg_page_granulepos (page);
|
|
|
|
}
|
2004-07-02 03:41:22 +00:00
|
|
|
if (pad->length < ogg_page_granulepos (page))
|
|
|
|
pad->length = ogg_page_granulepos (page);
|
|
|
|
if (pad->pages < ogg_page_pageno (page))
|
|
|
|
pad->pages = ogg_page_pageno (page);
|
|
|
|
end = gst_ogg_demux_position (ogg);
|
|
|
|
if (end >= 0) {
|
|
|
|
/* we need to know the offsets into the stream for the current page */
|
|
|
|
start = end - gst_ogg_page_get_length (page);
|
|
|
|
//g_print ("really setting start from %lld to %lld\n", pad->start_offset, start);
|
|
|
|
//g_print ("really setting end from %lld to %lld\n", pad->end_offset, end);
|
|
|
|
if (start < pad->start_offset || pad->start_offset < 0)
|
|
|
|
pad->start_offset = start;
|
|
|
|
if (ogg_page_bos (page))
|
|
|
|
pad->start_found = TRUE;
|
|
|
|
if (end > pad->end_offset)
|
|
|
|
pad->end_offset = end;
|
|
|
|
if (ogg_page_eos (page))
|
|
|
|
pad->end_found = TRUE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* get the ogg pad with the given serial in the unordered list or create and add it */
|
|
|
|
static GstOggPad *
|
|
|
|
gst_ogg_pad_get_unordered (GstOggDemux * ogg, ogg_page * page)
|
|
|
|
{
|
|
|
|
GSList *walk;
|
|
|
|
GstOggPad *pad;
|
|
|
|
int serial = ogg_page_serialno (page);
|
|
|
|
|
|
|
|
for (walk = ogg->unordered; walk; walk = g_slist_next (walk)) {
|
|
|
|
pad = (GstOggPad *) walk->data;
|
2004-03-14 22:34:34 +00:00
|
|
|
|
2004-01-29 02:50:20 +00:00
|
|
|
if (pad->serial == serial)
|
2004-07-02 03:41:22 +00:00
|
|
|
goto out;
|
2004-01-29 02:50:20 +00:00
|
|
|
}
|
2004-07-02 03:41:22 +00:00
|
|
|
pad = gst_ogg_pad_new (ogg, serial);
|
|
|
|
ogg->unordered = g_slist_prepend (ogg->unordered, pad);
|
|
|
|
|
|
|
|
out:
|
|
|
|
/* update start and end pointer if applicable */
|
|
|
|
gst_ogg_pad_populate (ogg, pad, page);
|
|
|
|
|
|
|
|
return pad;
|
|
|
|
}
|
|
|
|
|
|
|
|
static GstOggPad *
|
|
|
|
gst_ogg_pad_get (GstOggDemux * ogg, ogg_page * page)
|
|
|
|
{
|
|
|
|
GstOggPad *pad =
|
|
|
|
gst_ogg_pad_get_in_current_chain (ogg, ogg_page_serialno (page));
|
|
|
|
if (pad) {
|
|
|
|
gst_ogg_pad_populate (ogg, pad, page);
|
|
|
|
} else {
|
|
|
|
pad = gst_ogg_pad_get_unordered (ogg, page);
|
|
|
|
}
|
|
|
|
return pad;
|
2004-01-29 02:50:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2004-03-14 22:34:34 +00:00
|
|
|
gst_ogg_add_chain (GstOggDemux * ogg)
|
2004-01-29 02:50:20 +00:00
|
|
|
{
|
|
|
|
GST_LOG_OBJECT (ogg, "adding chain %u", ogg->chains->len);
|
|
|
|
ogg->current_chain = ogg->chains->len;
|
|
|
|
g_array_set_size (ogg->chains, ogg->chains->len + 1);
|
|
|
|
}
|
|
|
|
|
2004-07-02 03:41:22 +00:00
|
|
|
/* abort setup phase and just start playing */
|
|
|
|
static void
|
|
|
|
abort_setup (GstOggDemux * ogg)
|
|
|
|
{
|
|
|
|
gst_ogg_print (ogg);
|
|
|
|
gst_ogg_chains_clear (ogg);
|
|
|
|
gst_ogg_start_playing (ogg);
|
|
|
|
}
|
|
|
|
|
|
|
|
#undef GST_CAT_DEFAULT
|
|
|
|
#define GST_CAT_DEFAULT gst_ogg_demux_setup_debug
|
|
|
|
static gboolean
|
|
|
|
gst_ogg_demux_set_setup_state (GstOggDemux * ogg, GstOggSetupState state)
|
|
|
|
{
|
|
|
|
g_assert (ogg->state == GST_OGG_STATE_SETUP);
|
|
|
|
g_assert (state > 0);
|
|
|
|
g_assert (state < G_N_ELEMENTS (setup_funcs));
|
|
|
|
g_assert (state != ogg->setup_state);
|
|
|
|
|
|
|
|
GST_DEBUG_OBJECT (ogg, "setting setup state from %d to %d", ogg->setup_state,
|
|
|
|
state);
|
|
|
|
ogg->setup_state = state;
|
|
|
|
if (!setup_funcs[state].init (ogg)) {
|
|
|
|
abort_setup (ogg);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* seeks to the given position if TRUE is returned. Seeks a bit before this
|
|
|
|
* offset for syncing. You can call this function multiple times, if sync
|
|
|
|
* failed, it will then seek further back. It will never seek further back as
|
|
|
|
* min_offset though.
|
|
|
|
*/
|
|
|
|
static gboolean
|
|
|
|
gst_ogg_demux_seek_before (GstOggDemux * ogg, gint64 offset, gint64 min_offset)
|
|
|
|
{
|
|
|
|
gint64 before;
|
2004-07-13 10:38:25 +00:00
|
|
|
GstOggChain *chain;
|
|
|
|
gint streams;
|
2004-07-02 03:41:22 +00:00
|
|
|
|
2004-07-13 10:38:25 +00:00
|
|
|
/* figure out how many streams are in this chain */
|
|
|
|
chain = CURRENT_CHAIN (ogg);
|
|
|
|
if (chain) {
|
|
|
|
streams = g_slist_length (chain->pads);
|
|
|
|
} else {
|
|
|
|
streams = 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* need to multiply the expected page size with the numer of streams we
|
|
|
|
* detected to have a good chance of finding all pages */
|
2004-07-02 03:41:22 +00:00
|
|
|
before = ogg->seek_skipped ? ogg->seek_skipped * SETUP_SEEK_MULTIPLIER :
|
2004-07-13 10:38:25 +00:00
|
|
|
SETUP_EXPECTED_PAGE_SIZE * streams;
|
|
|
|
|
2004-07-02 03:41:22 +00:00
|
|
|
GST_DEBUG_OBJECT (ogg,
|
|
|
|
"seeking to %" G_GINT64_FORMAT " bytes before %" G_GINT64_FORMAT,
|
|
|
|
before, offset);
|
|
|
|
/* tried to seek to start once, don't try again */
|
|
|
|
if (min_offset + ogg->seek_skipped > offset)
|
|
|
|
return FALSE;
|
|
|
|
if (gst_file_pad_seek (ogg->sinkpad, MAX (min_offset, offset - before),
|
|
|
|
GST_SEEK_METHOD_SET) != 0)
|
|
|
|
return FALSE;
|
|
|
|
ogg_sync_clear (&ogg->sync);
|
|
|
|
ogg->seek_skipped = before;
|
|
|
|
ogg->seek_to = offset;
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
_read_bos_init (GstOggDemux * ogg)
|
|
|
|
{
|
|
|
|
gst_ogg_add_chain (ogg);
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
_read_bos_process (GstOggDemux * ogg, ogg_page * page)
|
|
|
|
{
|
|
|
|
/* here we're reading in the bos pages of the current chain */
|
|
|
|
if (ogg_page_bos (page)) {
|
|
|
|
GstOggPad *pad;
|
|
|
|
|
|
|
|
GST_LOG_OBJECT (ogg,
|
|
|
|
"SETUP_READ_BOS: bos found with serial %d, adding to current chain",
|
|
|
|
ogg_page_serialno (page));
|
|
|
|
pad = gst_ogg_pad_get_unordered (ogg, page);
|
|
|
|
ogg->unordered = g_slist_remove (ogg->unordered, pad);
|
|
|
|
g_assert (CURRENT_CHAIN (ogg));
|
|
|
|
CURRENT_CHAIN (ogg)->pads =
|
|
|
|
g_slist_prepend (CURRENT_CHAIN (ogg)->pads, pad);
|
|
|
|
} else {
|
2004-10-18 15:23:41 +00:00
|
|
|
gboolean have_all_first_pages = TRUE;
|
|
|
|
|
2004-07-02 03:41:22 +00:00
|
|
|
if (CURRENT_CHAIN (ogg)->pads == NULL) {
|
|
|
|
GST_ERROR_OBJECT (ogg, "broken ogg stream, chain has no BOS pages");
|
|
|
|
return FALSE;
|
|
|
|
}
|
2004-10-18 15:23:41 +00:00
|
|
|
|
|
|
|
FOR_PAD_IN_CURRENT_CHAIN (ogg, pad, if (pad->start == (guint64) - 1)
|
|
|
|
have_all_first_pages = FALSE;);
|
|
|
|
|
|
|
|
if (have_all_first_pages) {
|
|
|
|
GST_DEBUG_OBJECT (ogg,
|
|
|
|
"SETUP_READ_BOS: no more bos pages, going to find end of stream");
|
|
|
|
if (ogg->setup_state == SETUP_READ_FIRST_BOS) {
|
|
|
|
return gst_ogg_demux_set_setup_state (ogg, SETUP_FIND_LAST_CHAIN);
|
|
|
|
} else if (ogg->unordered) {
|
|
|
|
return gst_ogg_demux_set_setup_state (ogg,
|
|
|
|
SETUP_FIND_END_OF_LAST_STREAMS);
|
|
|
|
} else {
|
|
|
|
return gst_ogg_demux_set_setup_state (ogg, SETUP_FIND_END_OF_STREAMS);
|
|
|
|
}
|
2004-07-02 03:41:22 +00:00
|
|
|
} else {
|
2004-10-18 15:23:41 +00:00
|
|
|
GstOggPad *pad =
|
|
|
|
gst_ogg_pad_get_in_current_chain (ogg, ogg_page_serialno (page));
|
|
|
|
|
|
|
|
gst_ogg_pad_populate (ogg, pad, page);
|
2004-07-02 03:41:22 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
_find_chain_get_unknown_part (GstOggDemux * ogg, gint64 * start, gint64 * end)
|
|
|
|
{
|
|
|
|
*start = 0;
|
|
|
|
*end = G_MAXINT64;
|
|
|
|
|
|
|
|
g_assert (ogg->current_chain >= 0);
|
2004-11-25 20:31:22 +00:00
|
|
|
FOR_PAD_IN_CURRENT_CHAIN (ogg, pad, *start = MAX (*start, pad->end_offset);
|
|
|
|
);
|
2004-07-02 03:41:22 +00:00
|
|
|
|
|
|
|
if (ogg->setup_state == SETUP_FIND_LAST_CHAIN) {
|
|
|
|
*end = gst_file_pad_get_length (ogg->sinkpad);
|
|
|
|
if (*end < 0)
|
|
|
|
return FALSE;
|
|
|
|
} else {
|
|
|
|
GSList *walk;
|
|
|
|
|
|
|
|
g_assert (ogg->unordered != NULL);
|
|
|
|
for (walk = ogg->unordered; walk; walk = g_slist_next (walk)) {
|
|
|
|
GstOggPad *temp = walk->data;
|
|
|
|
|
|
|
|
*end = MIN (*end, temp->start_offset);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
GST_DEBUG_OBJECT (ogg, "we're looking for a new chain in the range [%"
|
|
|
|
G_GINT64_FORMAT ", %" G_GINT64_FORMAT "]", *start, *end);
|
|
|
|
|
|
|
|
/* overlapping chains?! */
|
|
|
|
if (*end < *start) {
|
|
|
|
GST_ERROR_OBJECT (ogg, "chained streams overlap, bailing out");
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
_find_last_chain_init (GstOggDemux * ogg)
|
|
|
|
{
|
|
|
|
gint64 end = gst_file_pad_get_length (ogg->sinkpad);
|
|
|
|
|
|
|
|
ogg->seek_skipped = 0;
|
|
|
|
if (end < 0)
|
|
|
|
return FALSE;
|
|
|
|
if (!gst_ogg_demux_seek_before (ogg, end, 0))
|
|
|
|
return FALSE;
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
_find_last_chain_process (GstOggDemux * ogg, ogg_page * page)
|
|
|
|
{
|
|
|
|
GstOggPad *pad = gst_ogg_pad_get (ogg, page);
|
|
|
|
|
|
|
|
/* optimization: set eos as found - we're investigating last pages here anyway */
|
|
|
|
pad->end_found = TRUE;
|
|
|
|
/* set to 0 to indicate we found a page */
|
|
|
|
ogg->seek_skipped = 0;
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
_find_chain_seek (GstOggDemux * ogg, gint64 start, gint64 end)
|
|
|
|
{
|
|
|
|
if (end - start < SETUP_PASSTHROUGH_SIZE) {
|
|
|
|
GST_LOG_OBJECT (ogg,
|
|
|
|
"iterating through remaining window, because it's smaller than %u bytes",
|
|
|
|
SETUP_PASSTHROUGH_SIZE);
|
|
|
|
if (ogg->seek_to >= start) {
|
|
|
|
ogg->seek_skipped = 0;
|
|
|
|
if (!gst_ogg_demux_seek_before (ogg, start, start))
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (!gst_ogg_demux_seek_before (ogg, (start + end) / 2, start))
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
_find_chain_init (GstOggDemux * ogg)
|
|
|
|
{
|
|
|
|
gint64 start, end;
|
|
|
|
|
|
|
|
ogg->seek_skipped = 0;
|
|
|
|
ogg->seek_to = -1;
|
|
|
|
if (!_find_chain_get_unknown_part (ogg, &start, &end))
|
|
|
|
return FALSE;
|
|
|
|
if (!_find_chain_seek (ogg, start, end))
|
|
|
|
return FALSE;
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
_find_chain_process (GstOggDemux * ogg, ogg_page * page)
|
|
|
|
{
|
|
|
|
gint64 start, end;
|
|
|
|
|
|
|
|
if (!_find_chain_get_unknown_part (ogg, &start, &end))
|
|
|
|
return FALSE;
|
2004-10-23 10:06:32 +00:00
|
|
|
|
2004-07-02 03:41:22 +00:00
|
|
|
if (ogg->seek_to <= start && gst_ogg_demux_position (ogg) > end) {
|
|
|
|
/* we now should have the first bos page, because
|
|
|
|
* - we seeked to a point in the known chain
|
|
|
|
* - we're now in a part that belongs to the unordered streams
|
|
|
|
*/
|
compile fixes for --disable-gst-debug, G_DISABLE_ASSERT and friends
Original commit message from CVS:
* ext/alsa/gstalsamixer.c: (gst_alsa_mixer_get_volume),
(gst_alsa_mixer_set_volume), (gst_alsa_mixer_set_mute),
(gst_alsa_mixer_set_record), (gst_alsa_mixer_set_option),
(gst_alsa_mixer_get_option):
* ext/dvdnav/dvdnavsrc.c: (dvdnav_get_event_name),
(dvdnavsrc_print_event):
* ext/ogg/gstoggdemux.c: (_find_chain_process), (gst_ogg_print):
* ext/ogg/gstoggmux.c: (gst_ogg_mux_pad_link),
(gst_ogg_mux_pad_unlink):
* gst/multipart/multipartmux.c: (gst_multipart_mux_pad_link),
(gst_multipart_mux_pad_unlink):
* gst/videofilter/gstvideobalance.c:
(gst_videobalance_colorbalance_set_value):
* gst/videomixer/videomixer.c: (gst_videomixer_pad_link),
(gst_videomixer_pad_unlink):
* po/uk.po:
* sys/oss/gstossmixer.c:
* sys/v4l/gstv4lcolorbalance.c:
* sys/v4l/gstv4ltuner.c:
* sys/v4l/v4lsrc_calls.c:
* sys/v4l2/gstv4l2colorbalance.c:
* sys/v4l2/gstv4l2tuner.c:
compile fixes for --disable-gst-debug, G_DISABLE_ASSERT and friends
2004-08-03 16:06:08 +00:00
|
|
|
g_assert (g_slist_find (ogg->unordered, gst_ogg_pad_get (ogg, page)));
|
2004-07-02 03:41:22 +00:00
|
|
|
if (!ogg_page_bos (page)) {
|
|
|
|
/* broken stream */
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
if (!gst_ogg_demux_set_setup_state (ogg, SETUP_READ_BOS))
|
|
|
|
return FALSE;
|
|
|
|
return _read_bos_process (ogg, page);
|
|
|
|
} else {
|
|
|
|
if (!_find_chain_seek (ogg, start, end))
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
_find_streams_check (GstOggDemux * ogg)
|
|
|
|
{
|
|
|
|
gint chain_nr = ogg->setup_state == SETUP_FIND_END_OF_LAST_STREAMS ?
|
|
|
|
ogg->chains->len - 1 : ogg->chains->len - 2;
|
|
|
|
gint64 endpos;
|
|
|
|
|
|
|
|
/* figure out positions */
|
|
|
|
if (ogg->setup_state == SETUP_FIND_END_OF_LAST_STREAMS) {
|
|
|
|
if ((endpos = gst_file_pad_get_length (ogg->sinkpad)) < 0)
|
|
|
|
return FALSE;
|
|
|
|
} else {
|
|
|
|
endpos = G_MAXINT64;
|
|
|
|
FOR_PAD_IN_CHAIN (ogg, pad, ogg->chains->len - 1,
|
2004-11-25 20:31:22 +00:00
|
|
|
endpos = MIN (endpos, pad->start_offset);
|
|
|
|
);
|
2004-07-02 03:41:22 +00:00
|
|
|
}
|
|
|
|
if (!ogg->seek_skipped || gst_ogg_demux_position (ogg) >= endpos) {
|
|
|
|
/* have we found the endposition for all streams yet? */
|
|
|
|
FOR_PAD_IN_CHAIN (ogg, pad, chain_nr, if (!pad->end_offset)
|
|
|
|
goto go_on;);
|
|
|
|
/* get out, we're done */
|
|
|
|
ogg->seek_skipped = 0;
|
|
|
|
ogg->seek_to = -1;
|
|
|
|
if (ogg->unordered) {
|
|
|
|
ogg->setup_state = SETUP_FIND_END_OF_CHAIN;
|
|
|
|
} else {
|
|
|
|
gst_ogg_start_playing (ogg);
|
|
|
|
}
|
|
|
|
return TRUE;
|
|
|
|
go_on:
|
|
|
|
if (!gst_ogg_demux_seek_before (ogg, endpos, 0))
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
_find_streams_init (GstOggDemux * ogg)
|
|
|
|
{
|
|
|
|
ogg->seek_skipped = 0;
|
|
|
|
ogg->seek_to = -1;
|
|
|
|
return _find_streams_check (ogg);
|
|
|
|
}
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
_find_streams_process (GstOggDemux * ogg, ogg_page * page)
|
|
|
|
{
|
|
|
|
gint chain_nr = ogg->setup_state == SETUP_FIND_END_OF_LAST_STREAMS ?
|
|
|
|
ogg->chains->len - 1 : ogg->chains->len - 2;
|
|
|
|
|
|
|
|
g_assert (ogg->setup_state == SETUP_FIND_END_OF_LAST_STREAMS ||
|
|
|
|
ogg->setup_state == SETUP_FIND_END_OF_STREAMS);
|
|
|
|
g_assert (chain_nr >= 0);
|
|
|
|
/* mark current pad as having an endframe */
|
|
|
|
if (ogg->seek_skipped) {
|
|
|
|
GstOggPad *pad =
|
|
|
|
gst_ogg_pad_get_in_chain (ogg, chain_nr, ogg_page_serialno (page));
|
|
|
|
if (pad) {
|
|
|
|
pad->end_offset = TRUE;
|
|
|
|
g_print ("marking pad %d as having an end\n", pad->serial);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return _find_streams_check (ogg);
|
|
|
|
}
|
|
|
|
|
|
|
|
#undef GST_CAT_DEFAULT
|
|
|
|
#define GST_CAT_DEFAULT gst_ogg_demux_debug
|
|
|
|
|
2003-11-24 04:08:48 +00:00
|
|
|
static void
|
2004-07-02 03:41:22 +00:00
|
|
|
gst_ogg_demux_iterate (GstFilePad * pad)
|
2003-11-24 04:08:48 +00:00
|
|
|
{
|
|
|
|
GstOggDemux *ogg;
|
|
|
|
guint8 *data;
|
2004-07-02 03:41:22 +00:00
|
|
|
guint available;
|
2003-11-24 04:08:48 +00:00
|
|
|
int pageout_ret = 1;
|
2004-07-02 03:41:22 +00:00
|
|
|
gint64 offset_end;
|
2003-11-24 04:08:48 +00:00
|
|
|
|
2004-07-02 03:41:22 +00:00
|
|
|
ogg = GST_OGG_DEMUX (gst_pad_get_parent (GST_PAD (pad)));
|
2003-11-24 04:08:48 +00:00
|
|
|
|
2004-07-02 03:41:22 +00:00
|
|
|
available = gst_file_pad_available (ogg->sinkpad);
|
|
|
|
if (available == 0) {
|
|
|
|
if (gst_file_pad_eof (ogg->sinkpad)) {
|
|
|
|
gst_ogg_demux_eos (ogg);
|
|
|
|
} else {
|
|
|
|
GST_DEBUG_OBJECT (ogg, "no data available, doing nothing");
|
|
|
|
}
|
2004-10-22 11:11:28 +00:00
|
|
|
if (ogg->state != GST_OGG_STATE_SETUP)
|
|
|
|
return;
|
2004-07-02 03:41:22 +00:00
|
|
|
}
|
|
|
|
GST_LOG_OBJECT (ogg, "queueing next %u bytes of data", available);
|
|
|
|
data = (guint8 *) ogg_sync_buffer (&ogg->sync, available);
|
|
|
|
if ((available = gst_file_pad_read (ogg->sinkpad, data, available)) < 0) {
|
|
|
|
GST_ERROR_OBJECT (ogg, "error %u reading data from pad",
|
|
|
|
gst_file_pad_error (ogg->sinkpad));
|
2004-03-14 22:34:34 +00:00
|
|
|
return;
|
2004-01-29 02:50:20 +00:00
|
|
|
}
|
2004-07-02 03:41:22 +00:00
|
|
|
if (ogg_sync_wrote (&ogg->sync, available) != 0) {
|
2004-03-14 22:34:34 +00:00
|
|
|
GST_ELEMENT_ERROR (ogg, LIBRARY, TOO_LAZY, (NULL),
|
2004-03-15 19:32:28 +00:00
|
|
|
("ogg_sync_wrote failed"));
|
2003-11-24 04:08:48 +00:00
|
|
|
return;
|
|
|
|
}
|
2004-07-02 03:41:22 +00:00
|
|
|
offset_end = gst_file_pad_tell (ogg->sinkpad);
|
|
|
|
g_assert (offset_end >= 0); /* FIXME: do sth reasonable if no length available */
|
2003-11-24 04:08:48 +00:00
|
|
|
while (pageout_ret != 0) {
|
|
|
|
ogg_page page;
|
2004-03-14 22:34:34 +00:00
|
|
|
|
2003-11-24 04:08:48 +00:00
|
|
|
pageout_ret = ogg_sync_pageout (&ogg->sync, &page);
|
|
|
|
switch (pageout_ret) {
|
|
|
|
case -1:
|
2004-03-15 19:32:28 +00:00
|
|
|
/* FIXME: need some kind of discont here, we don't know any values to send though,
|
|
|
|
* we only have the END_OFFSET */
|
|
|
|
break;
|
2003-11-24 04:08:48 +00:00
|
|
|
case 0:
|
2004-03-15 19:32:28 +00:00
|
|
|
if (ogg->state == GST_OGG_STATE_SETUP) {
|
2004-07-02 03:41:22 +00:00
|
|
|
if (gst_file_pad_get_length (ogg->sinkpad) <= offset_end) {
|
|
|
|
if (ogg->seek_skipped) {
|
|
|
|
if (!gst_ogg_demux_seek_before (ogg,
|
|
|
|
gst_file_pad_get_length (ogg->sinkpad), 0))
|
|
|
|
abort_setup (ogg);
|
|
|
|
} else if (ogg->setup_state == SETUP_FIND_LAST_CHAIN) {
|
|
|
|
if (ogg->unordered) {
|
|
|
|
if (!gst_ogg_demux_seek_before (ogg, offset_end / 2, 0))
|
|
|
|
abort_setup (ogg);
|
|
|
|
if (!gst_ogg_demux_set_setup_state (ogg,
|
|
|
|
SETUP_FIND_END_OF_CHAIN))
|
|
|
|
goto out;
|
|
|
|
} else {
|
|
|
|
if (!gst_ogg_demux_set_setup_state (ogg,
|
|
|
|
SETUP_FIND_END_OF_LAST_STREAMS))
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
abort_setup (ogg);
|
|
|
|
}
|
2004-03-15 19:32:28 +00:00
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
2003-11-24 04:08:48 +00:00
|
|
|
case 1:
|
2004-03-15 19:32:28 +00:00
|
|
|
GST_LOG_OBJECT (ogg,
|
2004-10-18 13:52:15 +00:00
|
|
|
"processing ogg page (serial %d, packet %ld, granule pos %llu, state: %d, bos %d)",
|
2004-03-15 19:32:28 +00:00
|
|
|
ogg_page_serialno (&page), ogg_page_pageno (&page),
|
2004-10-18 13:52:15 +00:00
|
|
|
ogg_page_granulepos (&page), ogg->state, ogg_page_bos (&page));
|
2004-03-15 19:32:28 +00:00
|
|
|
switch (ogg->state) {
|
|
|
|
case GST_OGG_STATE_SETUP:
|
2004-07-02 03:41:22 +00:00
|
|
|
if (!setup_funcs[ogg->setup_state].process (ogg, &page)) {
|
|
|
|
abort_setup (ogg);
|
|
|
|
goto out;
|
2004-03-15 19:32:28 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case GST_OGG_STATE_START:
|
2004-07-02 03:41:22 +00:00
|
|
|
if (gst_file_pad_seek (ogg->sinkpad, 0, GST_SEEK_METHOD_END) == 0) {
|
2004-03-15 19:32:28 +00:00
|
|
|
GST_OGG_SET_STATE (ogg, GST_OGG_STATE_SETUP);
|
|
|
|
GST_DEBUG_OBJECT (ogg, "stream can seek, try setup now");
|
2004-07-02 03:41:22 +00:00
|
|
|
if (gst_file_pad_seek (ogg->sinkpad, 0, GST_SEEK_METHOD_SET) != 0) {
|
2004-03-15 19:32:28 +00:00
|
|
|
GST_ELEMENT_ERROR (ogg, CORE, SEEK, (NULL),
|
|
|
|
("stream can seek to end, but not to start. Can't handle that."));
|
|
|
|
}
|
2004-07-02 03:41:22 +00:00
|
|
|
ogg_sync_clear (&ogg->sync);
|
2004-03-15 19:32:28 +00:00
|
|
|
gst_ogg_add_chain (ogg);
|
|
|
|
GST_FLAG_SET (ogg, GST_OGG_FLAG_WAIT_FOR_DISCONT);
|
|
|
|
goto out;
|
2004-10-18 13:52:15 +00:00
|
|
|
} else {
|
|
|
|
GST_DEBUG_OBJECT (ogg, "stream can not seek");
|
|
|
|
gst_ogg_add_chain (ogg);
|
|
|
|
GST_OGG_SET_STATE (ogg, GST_OGG_STATE_PLAY);
|
2004-03-15 19:32:28 +00:00
|
|
|
}
|
|
|
|
/* fall through */
|
|
|
|
case GST_OGG_STATE_SEEK:
|
|
|
|
case GST_OGG_STATE_PLAY:
|
|
|
|
gst_ogg_demux_push (ogg, &page);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
g_assert_not_reached ();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
2003-11-24 04:08:48 +00:00
|
|
|
default:
|
2004-03-15 19:32:28 +00:00
|
|
|
GST_WARNING_OBJECT (ogg,
|
|
|
|
"unknown return value %d from ogg_sync_pageout", pageout_ret);
|
|
|
|
pageout_ret = 0;
|
|
|
|
break;
|
2003-11-24 04:08:48 +00:00
|
|
|
}
|
|
|
|
}
|
2004-01-29 02:50:20 +00:00
|
|
|
out:
|
2003-11-24 04:08:48 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
static GstOggPad *
|
2004-03-14 22:34:34 +00:00
|
|
|
gst_ogg_pad_new (GstOggDemux * ogg, int serial)
|
2003-11-24 04:08:48 +00:00
|
|
|
{
|
2004-01-29 02:50:20 +00:00
|
|
|
GstOggPad *ret = g_new0 (GstOggPad, 1);
|
2004-03-06 17:31:59 +00:00
|
|
|
GstTagList *list = gst_tag_list_new ();
|
2003-11-24 04:08:48 +00:00
|
|
|
|
|
|
|
ret->serial = serial;
|
|
|
|
if (ogg_stream_init (&ret->stream, serial) != 0) {
|
2004-03-14 22:34:34 +00:00
|
|
|
GST_ERROR_OBJECT (ogg,
|
2004-03-15 19:32:28 +00:00
|
|
|
"Could not initialize ogg_stream struct for serial %d.", serial);
|
2003-11-24 04:08:48 +00:00
|
|
|
g_free (ret);
|
|
|
|
return NULL;
|
|
|
|
}
|
2004-03-06 17:31:59 +00:00
|
|
|
gst_tag_list_add (list, GST_TAG_MERGE_REPLACE, GST_TAG_SERIAL, serial, NULL);
|
|
|
|
gst_element_found_tags (GST_ELEMENT (ogg), list);
|
2004-10-26 11:36:53 +00:00
|
|
|
gst_tag_list_free (list);
|
|
|
|
|
2004-03-14 22:34:34 +00:00
|
|
|
GST_LOG_OBJECT (ogg, "created new ogg src %p for stream with serial %d", ret,
|
|
|
|
serial);
|
2004-07-02 03:41:22 +00:00
|
|
|
ret->start_offset = ret->end_offset = -1;
|
2004-10-18 15:23:41 +00:00
|
|
|
ret->start = -1;
|
2004-07-02 03:41:22 +00:00
|
|
|
ret->start_found = ret->end_found = FALSE;
|
2003-11-24 04:08:48 +00:00
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
static void
|
2004-03-14 22:34:34 +00:00
|
|
|
gst_ogg_pad_remove (GstOggDemux * ogg, GstOggPad * pad)
|
2003-11-24 04:08:48 +00:00
|
|
|
{
|
|
|
|
if (pad->pad) {
|
2004-01-29 02:50:20 +00:00
|
|
|
/* FIXME:
|
|
|
|
* we do it in the EOS signal already - EOS handling needs to be better thought out.
|
|
|
|
* Correct way would be pushing EOS on eos page, but scheduler doesn't like that
|
2004-03-14 22:34:34 +00:00
|
|
|
*/
|
2004-10-25 17:46:03 +00:00
|
|
|
if (GST_PAD_IS_USABLE (pad->pad))
|
|
|
|
gst_pad_push (pad->pad, GST_DATA (gst_event_new (GST_EVENT_EOS)));
|
|
|
|
|
2003-11-24 04:08:48 +00:00
|
|
|
gst_element_remove_pad (GST_ELEMENT (ogg), pad->pad);
|
2004-10-25 17:46:03 +00:00
|
|
|
pad->pad = NULL;
|
2003-11-24 04:08:48 +00:00
|
|
|
}
|
|
|
|
if (ogg_stream_clear (&pad->stream) != 0)
|
2004-03-14 22:34:34 +00:00
|
|
|
GST_ERROR_OBJECT (ogg,
|
2004-03-15 19:32:28 +00:00
|
|
|
"ogg_stream_clear (serial %d) did not return 0, ignoring this error",
|
|
|
|
pad->serial);
|
2004-03-14 22:34:34 +00:00
|
|
|
GST_LOG_OBJECT (ogg, "free ogg src %p for stream with serial %d", pad,
|
|
|
|
pad->serial);
|
2003-11-24 04:08:48 +00:00
|
|
|
g_free (pad);
|
|
|
|
}
|
|
|
|
static void
|
2004-03-14 22:34:34 +00:00
|
|
|
gst_ogg_demux_push (GstOggDemux * ogg, ogg_page * page)
|
2003-11-24 04:08:48 +00:00
|
|
|
{
|
2004-07-02 03:41:22 +00:00
|
|
|
GstOggPad *cur =
|
|
|
|
gst_ogg_pad_get_in_current_chain (ogg, ogg_page_serialno (page));
|
2003-11-24 04:08:48 +00:00
|
|
|
|
|
|
|
/* now we either have a stream (cur) or not */
|
|
|
|
if (ogg_page_bos (page)) {
|
|
|
|
if (cur) {
|
2004-03-14 22:34:34 +00:00
|
|
|
GST_DEBUG_OBJECT (ogg,
|
2004-03-15 19:32:28 +00:00
|
|
|
"ogg page declared as BOS while stream %d already existed."
|
|
|
|
"Possibly a seek happened.", cur->serial);
|
2004-01-29 02:50:20 +00:00
|
|
|
} else if (cur) {
|
2004-03-14 22:34:34 +00:00
|
|
|
GST_DEBUG_OBJECT (ogg, "reactivating deactivated stream %d.",
|
2004-03-15 19:32:28 +00:00
|
|
|
cur->serial);
|
2003-11-24 04:08:48 +00:00
|
|
|
} else {
|
|
|
|
/* FIXME: monitor if we are still in creation stage? */
|
|
|
|
cur = gst_ogg_pad_new (ogg, ogg_page_serialno (page));
|
|
|
|
if (!cur) {
|
2004-03-15 19:32:28 +00:00
|
|
|
GST_ELEMENT_ERROR (ogg, LIBRARY, TOO_LAZY, (NULL),
|
|
|
|
("Creating ogg_stream struct failed."));
|
|
|
|
return;
|
2004-01-29 02:50:20 +00:00
|
|
|
}
|
|
|
|
if (ogg->current_chain == -1) {
|
2004-03-15 19:32:28 +00:00
|
|
|
/* add new one at the end */
|
|
|
|
gst_ogg_add_chain (ogg);
|
2003-11-24 04:08:48 +00:00
|
|
|
}
|
2004-03-14 22:34:34 +00:00
|
|
|
CURRENT_CHAIN (ogg)->pads =
|
2004-03-15 19:32:28 +00:00
|
|
|
g_slist_prepend (CURRENT_CHAIN (ogg)->pads, cur);
|
2003-11-24 04:08:48 +00:00
|
|
|
}
|
2004-05-13 16:07:16 +00:00
|
|
|
ogg->bos = TRUE;
|
|
|
|
} else if (ogg->bos) {
|
|
|
|
gst_element_no_more_pads (GST_ELEMENT (ogg));
|
|
|
|
ogg->bos = FALSE;
|
2003-11-24 04:08:48 +00:00
|
|
|
}
|
|
|
|
if (cur == NULL) {
|
2004-03-14 22:34:34 +00:00
|
|
|
GST_ELEMENT_ERROR (ogg, STREAM, DECODE, (NULL),
|
2004-03-15 19:32:28 +00:00
|
|
|
("invalid ogg stream serial no"));
|
2003-11-24 04:08:48 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (ogg_stream_pagein (&cur->stream, page) != 0) {
|
2004-03-14 22:34:34 +00:00
|
|
|
GST_WARNING_OBJECT (ogg,
|
2004-03-15 19:32:28 +00:00
|
|
|
"ogg stream choked on page (serial %d), resetting stream", cur->serial);
|
2003-11-24 04:08:48 +00:00
|
|
|
gst_ogg_pad_reset (ogg, cur);
|
|
|
|
return;
|
|
|
|
}
|
2004-01-29 02:50:20 +00:00
|
|
|
switch (ogg->state) {
|
|
|
|
case GST_OGG_STATE_SEEK:
|
2004-03-14 22:34:34 +00:00
|
|
|
GST_LOG_OBJECT (ogg,
|
2004-03-15 19:32:28 +00:00
|
|
|
"in seek - offset now: %" G_GUINT64_FORMAT
|
|
|
|
" (pad %d) - desired offset %" G_GUINT64_FORMAT " (pad %d)",
|
|
|
|
cur->known_offset, cur->serial, ogg->seek_to, ogg->seek_pad->serial);
|
2004-10-29 15:59:37 +00:00
|
|
|
|
|
|
|
if (cur != ogg->seek_pad) {
|
|
|
|
break;
|
|
|
|
} else {
|
2004-11-08 17:02:07 +00:00
|
|
|
gint64 position, diff;
|
2004-10-29 15:59:37 +00:00
|
|
|
gdouble ratio;
|
|
|
|
|
ext/: More seeking fixes, oggdemux now supports seeking to time and uses the downstream element to convert granulepos...
Original commit message from CVS:
* ext/ogg/gstoggdemux.c: (gst_ogg_demux_init),
(gst_ogg_demux_get_formats), (gst_ogg_demux_src_query),
(gst_ogg_demux_src_event), (gst_ogg_demux_src_convert),
(gst_ogg_demux_handle_event), (gst_ogg_demux_seek_before),
(_find_chain_get_unknown_part), (_find_streams_check),
(gst_ogg_demux_push), (gst_ogg_pad_push):
* ext/theora/theoradec.c: (theora_get_formats),
(theora_dec_src_convert), (theora_dec_sink_convert),
(theora_dec_src_query), (theora_dec_src_event), (theora_dec_event),
(theora_dec_chain):
* ext/vorbis/vorbisdec.c: (vorbis_dec_get_formats),
(vorbis_dec_convert), (vorbis_dec_src_query),
(vorbis_dec_src_event), (vorbis_dec_event):
More seeking fixes, oggdemux now supports seeking to time and
uses the downstream element to convert granulepos to time.
Seeking in theora-only ogg files now works.
2004-07-21 16:48:20 +00:00
|
|
|
/* see if we reached the destination position when seeking */
|
2004-11-08 17:02:07 +00:00
|
|
|
position = get_relative (ogg, cur, ogg_page_granulepos (page),
|
|
|
|
GST_FORMAT_TIME);
|
|
|
|
/* Note: ogg->seek_to is already in GST_FORMAT_TIME... */
|
|
|
|
if (position == -1) {
|
|
|
|
/* let's just stop then */
|
|
|
|
goto play;
|
ext/: More seeking fixes, oggdemux now supports seeking to time and uses the downstream element to convert granulepos...
Original commit message from CVS:
* ext/ogg/gstoggdemux.c: (gst_ogg_demux_init),
(gst_ogg_demux_get_formats), (gst_ogg_demux_src_query),
(gst_ogg_demux_src_event), (gst_ogg_demux_src_convert),
(gst_ogg_demux_handle_event), (gst_ogg_demux_seek_before),
(_find_chain_get_unknown_part), (_find_streams_check),
(gst_ogg_demux_push), (gst_ogg_pad_push):
* ext/theora/theoradec.c: (theora_get_formats),
(theora_dec_src_convert), (theora_dec_sink_convert),
(theora_dec_src_query), (theora_dec_src_event), (theora_dec_event),
(theora_dec_chain):
* ext/vorbis/vorbisdec.c: (vorbis_dec_get_formats),
(vorbis_dec_convert), (vorbis_dec_src_query),
(vorbis_dec_src_event), (vorbis_dec_event):
More seeking fixes, oggdemux now supports seeking to time and
uses the downstream element to convert granulepos to time.
Seeking in theora-only ogg files now works.
2004-07-21 16:48:20 +00:00
|
|
|
}
|
|
|
|
|
2004-10-29 15:59:37 +00:00
|
|
|
/* fairly random treshold. */
|
|
|
|
if (ogg->seek_to > position)
|
|
|
|
diff = ogg->seek_to - position;
|
|
|
|
else
|
|
|
|
diff = position - ogg->seek_to;
|
|
|
|
if (diff < GST_SECOND) {
|
|
|
|
GST_DEBUG ("Close enough (%" GST_TIME_FORMAT " seconds off)",
|
|
|
|
GST_TIME_ARGS (diff));
|
2004-11-25 20:31:22 +00:00
|
|
|
ogg->seek_to = position;
|
2004-10-29 15:59:37 +00:00
|
|
|
goto play;
|
2004-03-15 19:32:28 +00:00
|
|
|
}
|
2004-10-29 15:59:37 +00:00
|
|
|
|
2004-11-23 15:24:28 +00:00
|
|
|
/* not too long */
|
|
|
|
if (ogg->seek_try > 5) {
|
|
|
|
GST_DEBUG ("Seeking took too long, continuing with current page");
|
|
|
|
ogg->seek_to = position;
|
|
|
|
goto play;
|
|
|
|
}
|
|
|
|
|
2004-10-29 15:59:37 +00:00
|
|
|
/* seek again! yay */
|
|
|
|
ratio = (gdouble) ogg->seek_to / position;
|
|
|
|
ogg->seek_offset = ogg->seek_offset * ratio;
|
|
|
|
if (gst_file_pad_seek (ogg->sinkpad, ogg->seek_offset,
|
|
|
|
GST_SEEK_METHOD_SET) != 0) {
|
|
|
|
goto play;
|
|
|
|
}
|
|
|
|
ogg->seek_try++;
|
|
|
|
ogg_sync_clear (&ogg->sync);
|
|
|
|
return;
|
|
|
|
|
|
|
|
play:
|
|
|
|
GST_OGG_SET_STATE (ogg, GST_OGG_STATE_PLAY);
|
|
|
|
GST_DEBUG_OBJECT (ogg,
|
|
|
|
"ended seek at offset %" G_GUINT64_FORMAT " (requested %"
|
|
|
|
G_GUINT64_FORMAT, cur->known_offset, ogg->seek_to);
|
|
|
|
ogg->seek_pad = NULL;
|
2004-10-29 16:18:08 +00:00
|
|
|
ogg->seek_offset = 0;
|
2004-10-29 15:59:37 +00:00
|
|
|
ogg->seek_try = 0;
|
2004-01-29 02:50:20 +00:00
|
|
|
}
|
|
|
|
/* fallthrough */
|
|
|
|
case GST_OGG_STATE_PLAY:
|
|
|
|
cur->known_offset = ogg_page_granulepos (page);
|
|
|
|
gst_ogg_pad_push (ogg, cur);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
g_assert_not_reached ();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (ogg_page_eos (page)) {
|
|
|
|
GST_DEBUG_OBJECT (ogg, "got EOS for stream with serial %d, sending EOS now",
|
2004-03-15 19:32:28 +00:00
|
|
|
cur->serial);
|
2004-10-26 14:41:06 +00:00
|
|
|
|
|
|
|
/* send an EOS before removing this pad */
|
|
|
|
if (GST_PAD_IS_USABLE (cur->pad))
|
|
|
|
gst_pad_push (cur->pad, GST_DATA (gst_event_new (GST_EVENT_EOS)));
|
|
|
|
|
2004-10-25 17:46:03 +00:00
|
|
|
gst_element_remove_pad (GST_ELEMENT (ogg), cur->pad);
|
|
|
|
cur->pad = NULL;
|
2004-01-29 02:50:20 +00:00
|
|
|
}
|
2003-11-24 04:08:48 +00:00
|
|
|
}
|
|
|
|
static void
|
2004-03-14 22:34:34 +00:00
|
|
|
gst_ogg_pad_push (GstOggDemux * ogg, GstOggPad * pad)
|
2003-11-24 04:08:48 +00:00
|
|
|
{
|
|
|
|
ogg_packet packet;
|
|
|
|
int ret;
|
2003-12-07 22:45:23 +00:00
|
|
|
GstBuffer *buf;
|
2003-11-24 04:08:48 +00:00
|
|
|
|
2004-10-31 15:33:43 +00:00
|
|
|
/* Hack. If someone connects to the push (or any related) signal and
|
|
|
|
* goes to READY, the pad will be destroyed and the next line will
|
|
|
|
* segfault. This does not work on PLAY -> READY -> PLAY. */
|
|
|
|
while (GST_STATE (ogg) >= GST_STATE_PAUSED) {
|
2003-11-24 04:08:48 +00:00
|
|
|
ret = ogg_stream_packetout (&pad->stream, &packet);
|
2004-08-17 10:40:50 +00:00
|
|
|
GST_LOG_OBJECT (ogg, "packetout gave %d", ret);
|
2003-11-24 04:08:48 +00:00
|
|
|
switch (ret) {
|
|
|
|
case 0:
|
2004-03-15 19:32:28 +00:00
|
|
|
return;
|
2003-11-24 04:08:48 +00:00
|
|
|
case -1:
|
2004-08-17 10:40:50 +00:00
|
|
|
/* out of sync, could call gst_ogg_pad_reset() here but ogg can decode
|
|
|
|
* the packet just fine. We should probably send a DISCONT though. */
|
2004-03-15 19:32:28 +00:00
|
|
|
break;
|
2004-03-14 22:34:34 +00:00
|
|
|
case 1:{
|
2004-11-08 17:02:07 +00:00
|
|
|
gint64 pos = -1;
|
2004-10-18 19:12:32 +00:00
|
|
|
|
2004-03-15 19:32:28 +00:00
|
|
|
/* only push data when playing, not during seek or similar */
|
|
|
|
if (ogg->state != GST_OGG_STATE_PLAY)
|
|
|
|
continue;
|
|
|
|
if (!pad->pad) {
|
|
|
|
GstCaps *caps = gst_ogg_type_find (&packet);
|
|
|
|
gchar *name = g_strdup_printf ("serial_%d", pad->serial);
|
|
|
|
|
|
|
|
if (caps == NULL) {
|
|
|
|
GST_WARNING_OBJECT (ogg,
|
|
|
|
"couldn't find caps for stream with serial %d", pad->serial);
|
|
|
|
caps = gst_caps_new_simple ("application/octet-stream", NULL);
|
|
|
|
}
|
|
|
|
pad->pad =
|
|
|
|
gst_pad_new_from_template (gst_static_pad_template_get
|
|
|
|
(&ogg_demux_src_template_factory), name);
|
|
|
|
g_free (name);
|
|
|
|
gst_pad_set_event_function (pad->pad,
|
|
|
|
GST_DEBUG_FUNCPTR (gst_ogg_demux_src_event));
|
|
|
|
gst_pad_set_event_mask_function (pad->pad,
|
|
|
|
GST_DEBUG_FUNCPTR (gst_ogg_demux_get_event_masks));
|
|
|
|
gst_pad_set_query_function (pad->pad,
|
|
|
|
GST_DEBUG_FUNCPTR (gst_ogg_demux_src_query));
|
|
|
|
gst_pad_set_query_type_function (pad->pad,
|
|
|
|
GST_DEBUG_FUNCPTR (gst_ogg_demux_get_query_types));
|
ext/: More seeking fixes, oggdemux now supports seeking to time and uses the downstream element to convert granulepos...
Original commit message from CVS:
* ext/ogg/gstoggdemux.c: (gst_ogg_demux_init),
(gst_ogg_demux_get_formats), (gst_ogg_demux_src_query),
(gst_ogg_demux_src_event), (gst_ogg_demux_src_convert),
(gst_ogg_demux_handle_event), (gst_ogg_demux_seek_before),
(_find_chain_get_unknown_part), (_find_streams_check),
(gst_ogg_demux_push), (gst_ogg_pad_push):
* ext/theora/theoradec.c: (theora_get_formats),
(theora_dec_src_convert), (theora_dec_sink_convert),
(theora_dec_src_query), (theora_dec_src_event), (theora_dec_event),
(theora_dec_chain):
* ext/vorbis/vorbisdec.c: (vorbis_dec_get_formats),
(vorbis_dec_convert), (vorbis_dec_src_query),
(vorbis_dec_src_event), (vorbis_dec_event):
More seeking fixes, oggdemux now supports seeking to time and
uses the downstream element to convert granulepos to time.
Seeking in theora-only ogg files now works.
2004-07-21 16:48:20 +00:00
|
|
|
gst_pad_set_formats_function (pad->pad,
|
|
|
|
GST_DEBUG_FUNCPTR (gst_ogg_demux_get_formats));
|
|
|
|
gst_pad_set_convert_function (pad->pad,
|
|
|
|
GST_DEBUG_FUNCPTR (gst_ogg_demux_src_convert));
|
|
|
|
|
2004-03-15 19:32:28 +00:00
|
|
|
gst_pad_use_explicit_caps (pad->pad);
|
|
|
|
gst_pad_set_explicit_caps (pad->pad, caps);
|
2004-10-31 17:16:58 +00:00
|
|
|
gst_caps_free (caps);
|
2004-03-15 19:32:28 +00:00
|
|
|
gst_pad_set_active (pad->pad, TRUE);
|
|
|
|
gst_element_add_pad (GST_ELEMENT (ogg), pad->pad);
|
|
|
|
}
|
|
|
|
/* check for discont */
|
|
|
|
if (packet.packetno != pad->packetno++) {
|
|
|
|
pad->flags |= GST_OGG_PAD_NEEDS_DISCONT;
|
|
|
|
pad->packetno = packet.packetno + 1;
|
|
|
|
}
|
2004-10-18 19:12:32 +00:00
|
|
|
|
2004-11-08 17:02:07 +00:00
|
|
|
if (pad->known_offset != -1) {
|
|
|
|
pos = get_relative (ogg, pad, pad->known_offset, GST_FORMAT_DEFAULT);
|
2004-10-22 13:09:12 +00:00
|
|
|
}
|
2004-10-18 19:12:32 +00:00
|
|
|
|
2004-10-20 16:24:18 +00:00
|
|
|
if ((pad->flags & GST_OGG_PAD_NEEDS_FLUSH)
|
|
|
|
&& GST_PAD_IS_USABLE (pad->pad)) {
|
|
|
|
gst_pad_push (pad->pad, GST_DATA (gst_event_new (GST_EVENT_FLUSH)));
|
|
|
|
pad->flags &= (~GST_OGG_PAD_NEEDS_FLUSH);
|
|
|
|
}
|
|
|
|
|
2004-03-15 19:32:28 +00:00
|
|
|
/* send discont if needed */
|
2004-11-08 14:43:47 +00:00
|
|
|
if ((pad->flags & GST_OGG_PAD_NEEDS_DISCONT)
|
2004-03-15 19:32:28 +00:00
|
|
|
&& GST_PAD_IS_USABLE (pad->pad)) {
|
2004-10-29 16:18:08 +00:00
|
|
|
/* so in order to synchronized the variety of streams, we will
|
|
|
|
* not use the granpos but the last seekpos for the discont. */
|
2004-11-08 17:02:07 +00:00
|
|
|
GstFormat fmt;
|
2004-10-29 16:18:08 +00:00
|
|
|
GstEvent *event;
|
|
|
|
gint64 discont;
|
|
|
|
|
2004-11-08 14:43:47 +00:00
|
|
|
if (pos != -1) {
|
|
|
|
fmt = GST_FORMAT_DEFAULT;
|
|
|
|
if (!GST_PAD_PEER (pad->pad) ||
|
|
|
|
!gst_pad_convert (GST_PAD_PEER (pad->pad),
|
|
|
|
ogg->seek_format, ogg->seek_to, &fmt, &discont)) {
|
|
|
|
event = gst_event_new_discontinuous (FALSE,
|
|
|
|
ogg->seek_format, ogg->seek_to, GST_FORMAT_UNDEFINED);
|
|
|
|
} else {
|
|
|
|
event = gst_event_new_discontinuous (FALSE,
|
|
|
|
GST_FORMAT_DEFAULT, discont, GST_FORMAT_UNDEFINED);
|
|
|
|
}
|
2004-10-29 16:18:08 +00:00
|
|
|
} else {
|
|
|
|
event = gst_event_new_discontinuous (FALSE,
|
2004-11-08 14:43:47 +00:00
|
|
|
GST_FORMAT_DEFAULT, 0, GST_FORMAT_UNDEFINED);
|
2004-10-29 16:18:08 +00:00
|
|
|
}
|
2004-10-18 15:49:00 +00:00
|
|
|
|
|
|
|
/* FIXME: this might be wrong because we can only use the last
|
|
|
|
* known offset */
|
2004-03-15 19:32:28 +00:00
|
|
|
|
|
|
|
gst_pad_push (pad->pad, GST_DATA (event));
|
|
|
|
pad->flags &= (~GST_OGG_PAD_NEEDS_DISCONT);
|
2004-10-20 16:24:18 +00:00
|
|
|
}
|
|
|
|
|
2004-03-15 19:32:28 +00:00
|
|
|
/* optimization: use a bufferpool containing the ogg packet? */
|
|
|
|
buf =
|
|
|
|
gst_pad_alloc_buffer (pad->pad, GST_BUFFER_OFFSET_NONE,
|
|
|
|
packet.bytes);
|
|
|
|
memcpy (buf->data, packet.packet, packet.bytes);
|
|
|
|
if (pad->offset != -1)
|
|
|
|
GST_BUFFER_OFFSET (buf) = pad->offset;
|
2004-10-18 19:12:32 +00:00
|
|
|
if (packet.granulepos != -1 && pos != -1)
|
|
|
|
GST_BUFFER_OFFSET_END (buf) = pos;
|
2004-03-15 19:32:28 +00:00
|
|
|
pad->offset = packet.granulepos;
|
|
|
|
if (GST_PAD_IS_USABLE (pad->pad))
|
|
|
|
gst_pad_push (pad->pad, GST_DATA (buf));
|
|
|
|
break;
|
2003-11-24 04:08:48 +00:00
|
|
|
}
|
|
|
|
default:
|
2004-03-15 19:32:28 +00:00
|
|
|
GST_ERROR_OBJECT (ogg,
|
|
|
|
"invalid return value %d for ogg_stream_packetout, resetting stream",
|
|
|
|
ret);
|
|
|
|
gst_ogg_pad_reset (ogg, pad);
|
|
|
|
break;
|
2003-11-24 04:08:48 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
static void
|
2004-03-14 22:34:34 +00:00
|
|
|
gst_ogg_pad_reset (GstOggDemux * ogg, GstOggPad * pad)
|
2003-11-24 04:08:48 +00:00
|
|
|
{
|
|
|
|
ogg_stream_reset (&pad->stream);
|
|
|
|
pad->offset = GST_BUFFER_OFFSET_NONE;
|
|
|
|
/* FIXME: need a discont here */
|
|
|
|
}
|
2004-01-29 02:50:20 +00:00
|
|
|
|
|
|
|
static void
|
2004-03-14 22:34:34 +00:00
|
|
|
gst_ogg_chains_clear (GstOggDemux * ogg)
|
2004-01-29 02:50:20 +00:00
|
|
|
{
|
|
|
|
gint i;
|
|
|
|
GSList *walk;
|
2004-03-14 22:34:34 +00:00
|
|
|
|
2004-01-29 02:50:20 +00:00
|
|
|
for (i = ogg->chains->len - 1; i >= 0; i--) {
|
|
|
|
GstOggChain *cur = &g_array_index (ogg->chains, GstOggChain, i);
|
2004-03-14 22:34:34 +00:00
|
|
|
|
2004-01-29 02:50:20 +00:00
|
|
|
for (walk = cur->pads; walk; walk = g_slist_next (walk)) {
|
|
|
|
gst_ogg_pad_remove (ogg, (GstOggPad *) walk->data);
|
|
|
|
}
|
|
|
|
g_slist_free (cur->pads);
|
2004-10-25 17:46:03 +00:00
|
|
|
cur->pads = NULL;
|
2004-01-29 02:50:20 +00:00
|
|
|
g_array_remove_index (ogg->chains, i);
|
|
|
|
}
|
|
|
|
ogg->current_chain = -1;
|
|
|
|
}
|
|
|
|
|
2003-11-24 04:08:48 +00:00
|
|
|
static GstElementStateReturn
|
2004-03-14 22:34:34 +00:00
|
|
|
gst_ogg_demux_change_state (GstElement * element)
|
2003-11-24 04:08:48 +00:00
|
|
|
{
|
|
|
|
GstOggDemux *ogg;
|
|
|
|
|
|
|
|
ogg = GST_OGG_DEMUX (element);
|
|
|
|
|
|
|
|
switch (GST_STATE_TRANSITION (element)) {
|
|
|
|
case GST_STATE_NULL_TO_READY:
|
|
|
|
ogg_sync_init (&ogg->sync);
|
|
|
|
break;
|
|
|
|
case GST_STATE_READY_TO_PAUSED:
|
|
|
|
ogg_sync_reset (&ogg->sync);
|
|
|
|
break;
|
|
|
|
case GST_STATE_PAUSED_TO_PLAYING:
|
|
|
|
break;
|
|
|
|
case GST_STATE_PLAYING_TO_PAUSED:
|
|
|
|
break;
|
|
|
|
case GST_STATE_PAUSED_TO_READY:
|
2004-01-29 02:50:20 +00:00
|
|
|
gst_ogg_chains_clear (ogg);
|
|
|
|
GST_OGG_SET_STATE (ogg, GST_OGG_STATE_START);
|
|
|
|
ogg->seek_pad = NULL;
|
|
|
|
ogg->seek_to = 0;
|
2003-11-24 04:08:48 +00:00
|
|
|
break;
|
|
|
|
case GST_STATE_READY_TO_NULL:
|
|
|
|
ogg_sync_clear (&ogg->sync);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return parent_class->change_state (element);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*** typefinding **************************************************************/
|
|
|
|
/* ogg supports its own typefinding because the ogg spec defines that the first
|
|
|
|
* packet of an ogg stream must identify the stream. Therefore ogg can use a
|
|
|
|
* simplified approach at typefinding.
|
|
|
|
*/
|
2004-03-14 22:34:34 +00:00
|
|
|
typedef struct
|
|
|
|
{
|
|
|
|
ogg_packet *packet;
|
|
|
|
guint best_probability;
|
|
|
|
GstCaps *caps;
|
2004-03-15 19:32:28 +00:00
|
|
|
}
|
|
|
|
OggTypeFind;
|
2003-11-24 04:08:48 +00:00
|
|
|
static guint8 *
|
|
|
|
ogg_find_peek (gpointer data, gint64 offset, guint size)
|
|
|
|
{
|
|
|
|
OggTypeFind *find = (OggTypeFind *) data;
|
2004-03-14 22:34:34 +00:00
|
|
|
|
2003-11-24 04:08:48 +00:00
|
|
|
if (offset + size <= find->packet->bytes) {
|
|
|
|
return ((guint8 *) find->packet->packet) + offset;
|
|
|
|
} else {
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
static void
|
2004-03-14 22:34:34 +00:00
|
|
|
ogg_find_suggest (gpointer data, guint probability, const GstCaps * caps)
|
2003-11-24 04:08:48 +00:00
|
|
|
{
|
|
|
|
OggTypeFind *find = (OggTypeFind *) data;
|
2004-03-14 22:34:34 +00:00
|
|
|
|
2003-11-24 04:08:48 +00:00
|
|
|
if (probability > find->best_probability) {
|
2003-12-22 01:47:09 +00:00
|
|
|
gst_caps_replace (&find->caps, gst_caps_copy (caps));
|
2003-11-24 04:08:48 +00:00
|
|
|
find->best_probability = probability;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
static GstCaps *
|
2004-03-14 22:34:34 +00:00
|
|
|
gst_ogg_type_find (ogg_packet * packet)
|
2003-11-24 04:08:48 +00:00
|
|
|
{
|
|
|
|
GstTypeFind gst_find;
|
|
|
|
OggTypeFind find;
|
|
|
|
GList *walk, *type_list = NULL;
|
2004-03-14 22:34:34 +00:00
|
|
|
|
2003-11-24 04:08:48 +00:00
|
|
|
walk = type_list = gst_type_find_factory_get_list ();
|
2004-03-14 22:34:34 +00:00
|
|
|
|
2003-11-24 04:08:48 +00:00
|
|
|
find.packet = packet;
|
|
|
|
find.best_probability = 0;
|
|
|
|
find.caps = NULL;
|
|
|
|
gst_find.data = &find;
|
|
|
|
gst_find.peek = ogg_find_peek;
|
|
|
|
gst_find.suggest = ogg_find_suggest;
|
2004-03-14 22:34:34 +00:00
|
|
|
|
2003-11-24 04:08:48 +00:00
|
|
|
while (walk) {
|
|
|
|
GstTypeFindFactory *factory = GST_TYPE_FIND_FACTORY (walk->data);
|
2004-03-14 22:34:34 +00:00
|
|
|
|
2003-11-24 04:08:48 +00:00
|
|
|
gst_type_find_factory_call_function (factory, &gst_find);
|
|
|
|
if (find.best_probability >= GST_TYPE_FIND_MAXIMUM)
|
|
|
|
break;
|
|
|
|
walk = g_list_next (walk);
|
|
|
|
}
|
2004-03-14 22:34:34 +00:00
|
|
|
|
2003-11-24 04:08:48 +00:00
|
|
|
if (find.best_probability > 0)
|
|
|
|
return find.caps;
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
ext/ogg/: Added an ogg muxer.
Original commit message from CVS:
* ext/ogg/gstogg.c: (plugin_init):
* ext/ogg/gstoggdemux.c: (gst_ogg_demux_plugin_init),
(gst_ogg_print):
* ext/ogg/gstoggmux.c: (gst_ogg_mux_get_type),
(gst_ogg_mux_base_init), (gst_ogg_mux_class_init),
(gst_ogg_mux_get_sink_event_masks), (gst_ogg_mux_init),
(gst_ogg_mux_sinkconnect), (gst_ogg_mux_pad_link),
(gst_ogg_mux_pad_unlink), (gst_ogg_mux_request_new_pad),
(gst_ogg_mux_handle_src_event), (gst_ogg_mux_next_buffer),
(gst_ogg_mux_push_page), (gst_ogg_mux_compare_pads),
(gst_ogg_mux_queue_pads), (gst_ogg_mux_loop),
(gst_ogg_mux_get_property), (gst_ogg_mux_set_property),
(gst_ogg_mux_change_state), (gst_ogg_mux_plugin_init):
Added an ogg muxer.
Small typo fixes in the demuxer.
2004-05-10 13:34:57 +00:00
|
|
|
gboolean
|
|
|
|
gst_ogg_demux_plugin_init (GstPlugin * plugin)
|
2003-11-24 04:08:48 +00:00
|
|
|
{
|
|
|
|
GST_DEBUG_CATEGORY_INIT (gst_ogg_demux_debug, "oggdemux", 0, "ogg demuxer");
|
2004-07-02 03:41:22 +00:00
|
|
|
GST_DEBUG_CATEGORY_INIT (gst_ogg_demux_setup_debug, "oggdemux_setup", 0,
|
|
|
|
"ogg demuxer setup stage when parsing pipeline");
|
2003-11-24 04:08:48 +00:00
|
|
|
|
2004-03-14 22:34:34 +00:00
|
|
|
return gst_element_register (plugin, "oggdemux", GST_RANK_PRIMARY,
|
|
|
|
GST_TYPE_OGG_DEMUX);
|
2003-11-24 04:08:48 +00:00
|
|
|
}
|
2004-03-14 22:34:34 +00:00
|
|
|
|
2004-01-29 02:50:20 +00:00
|
|
|
/* prints all info about the element */
|
2004-07-02 03:41:22 +00:00
|
|
|
#undef GST_CAT_DEFAULT
|
|
|
|
#define GST_CAT_DEFAULT gst_ogg_demux_setup_debug
|
compile fixes for --disable-gst-debug, G_DISABLE_ASSERT and friends
Original commit message from CVS:
* ext/alsa/gstalsamixer.c: (gst_alsa_mixer_get_volume),
(gst_alsa_mixer_set_volume), (gst_alsa_mixer_set_mute),
(gst_alsa_mixer_set_record), (gst_alsa_mixer_set_option),
(gst_alsa_mixer_get_option):
* ext/dvdnav/dvdnavsrc.c: (dvdnav_get_event_name),
(dvdnavsrc_print_event):
* ext/ogg/gstoggdemux.c: (_find_chain_process), (gst_ogg_print):
* ext/ogg/gstoggmux.c: (gst_ogg_mux_pad_link),
(gst_ogg_mux_pad_unlink):
* gst/multipart/multipartmux.c: (gst_multipart_mux_pad_link),
(gst_multipart_mux_pad_unlink):
* gst/videofilter/gstvideobalance.c:
(gst_videobalance_colorbalance_set_value):
* gst/videomixer/videomixer.c: (gst_videomixer_pad_link),
(gst_videomixer_pad_unlink):
* po/uk.po:
* sys/oss/gstossmixer.c:
* sys/v4l/gstv4lcolorbalance.c:
* sys/v4l/gstv4ltuner.c:
* sys/v4l/v4lsrc_calls.c:
* sys/v4l2/gstv4l2colorbalance.c:
* sys/v4l2/gstv4l2tuner.c:
compile fixes for --disable-gst-debug, G_DISABLE_ASSERT and friends
2004-08-03 16:06:08 +00:00
|
|
|
|
|
|
|
#ifdef GST_DISABLE_GST_DEBUG
|
|
|
|
|
ext/ogg/: Added an ogg muxer.
Original commit message from CVS:
* ext/ogg/gstogg.c: (plugin_init):
* ext/ogg/gstoggdemux.c: (gst_ogg_demux_plugin_init),
(gst_ogg_print):
* ext/ogg/gstoggmux.c: (gst_ogg_mux_get_type),
(gst_ogg_mux_base_init), (gst_ogg_mux_class_init),
(gst_ogg_mux_get_sink_event_masks), (gst_ogg_mux_init),
(gst_ogg_mux_sinkconnect), (gst_ogg_mux_pad_link),
(gst_ogg_mux_pad_unlink), (gst_ogg_mux_request_new_pad),
(gst_ogg_mux_handle_src_event), (gst_ogg_mux_next_buffer),
(gst_ogg_mux_push_page), (gst_ogg_mux_compare_pads),
(gst_ogg_mux_queue_pads), (gst_ogg_mux_loop),
(gst_ogg_mux_get_property), (gst_ogg_mux_set_property),
(gst_ogg_mux_change_state), (gst_ogg_mux_plugin_init):
Added an ogg muxer.
Small typo fixes in the demuxer.
2004-05-10 13:34:57 +00:00
|
|
|
static void
|
compile fixes for --disable-gst-debug, G_DISABLE_ASSERT and friends
Original commit message from CVS:
* ext/alsa/gstalsamixer.c: (gst_alsa_mixer_get_volume),
(gst_alsa_mixer_set_volume), (gst_alsa_mixer_set_mute),
(gst_alsa_mixer_set_record), (gst_alsa_mixer_set_option),
(gst_alsa_mixer_get_option):
* ext/dvdnav/dvdnavsrc.c: (dvdnav_get_event_name),
(dvdnavsrc_print_event):
* ext/ogg/gstoggdemux.c: (_find_chain_process), (gst_ogg_print):
* ext/ogg/gstoggmux.c: (gst_ogg_mux_pad_link),
(gst_ogg_mux_pad_unlink):
* gst/multipart/multipartmux.c: (gst_multipart_mux_pad_link),
(gst_multipart_mux_pad_unlink):
* gst/videofilter/gstvideobalance.c:
(gst_videobalance_colorbalance_set_value):
* gst/videomixer/videomixer.c: (gst_videomixer_pad_link),
(gst_videomixer_pad_unlink):
* po/uk.po:
* sys/oss/gstossmixer.c:
* sys/v4l/gstv4lcolorbalance.c:
* sys/v4l/gstv4ltuner.c:
* sys/v4l/v4lsrc_calls.c:
* sys/v4l2/gstv4l2colorbalance.c:
* sys/v4l2/gstv4l2tuner.c:
compile fixes for --disable-gst-debug, G_DISABLE_ASSERT and friends
2004-08-03 16:06:08 +00:00
|
|
|
gst_ogg_print (GstOggDemux * ogg)
|
|
|
|
{
|
|
|
|
/* NOP */
|
|
|
|
}
|
|
|
|
|
|
|
|
#else /* !GST_DISABLE_GST_DEBUG */
|
|
|
|
|
2004-07-02 03:41:22 +00:00
|
|
|
#define gst_ogg_print_pad(ogg, _pad) \
|
|
|
|
G_STMT_START{\
|
|
|
|
GstOggPad *pad = (_pad); \
|
|
|
|
GST_INFO_OBJECT (ogg, " stream %d:", pad->serial); \
|
|
|
|
GST_INFO_OBJECT (ogg, " length %" G_GUINT64_FORMAT, pad->length); \
|
|
|
|
GST_INFO_OBJECT (ogg, " pages %ld", pad->pages); \
|
|
|
|
GST_INFO_OBJECT (ogg, " offset: %"G_GINT64_FORMAT"%s - %"G_GINT64_FORMAT"%s", \
|
|
|
|
pad->start_offset, pad->start_found ? "" : " (?)", \
|
|
|
|
pad->end_offset, pad->end_found ? "" : " (?)"); \
|
|
|
|
}G_STMT_END
|
compile fixes for --disable-gst-debug, G_DISABLE_ASSERT and friends
Original commit message from CVS:
* ext/alsa/gstalsamixer.c: (gst_alsa_mixer_get_volume),
(gst_alsa_mixer_set_volume), (gst_alsa_mixer_set_mute),
(gst_alsa_mixer_set_record), (gst_alsa_mixer_set_option),
(gst_alsa_mixer_get_option):
* ext/dvdnav/dvdnavsrc.c: (dvdnav_get_event_name),
(dvdnavsrc_print_event):
* ext/ogg/gstoggdemux.c: (_find_chain_process), (gst_ogg_print):
* ext/ogg/gstoggmux.c: (gst_ogg_mux_pad_link),
(gst_ogg_mux_pad_unlink):
* gst/multipart/multipartmux.c: (gst_multipart_mux_pad_link),
(gst_multipart_mux_pad_unlink):
* gst/videofilter/gstvideobalance.c:
(gst_videobalance_colorbalance_set_value):
* gst/videomixer/videomixer.c: (gst_videomixer_pad_link),
(gst_videomixer_pad_unlink):
* po/uk.po:
* sys/oss/gstossmixer.c:
* sys/v4l/gstv4lcolorbalance.c:
* sys/v4l/gstv4ltuner.c:
* sys/v4l/v4lsrc_calls.c:
* sys/v4l2/gstv4l2colorbalance.c:
* sys/v4l2/gstv4l2tuner.c:
compile fixes for --disable-gst-debug, G_DISABLE_ASSERT and friends
2004-08-03 16:06:08 +00:00
|
|
|
static void
|
|
|
|
gst_ogg_print (GstOggDemux * ogg)
|
2004-01-29 02:50:20 +00:00
|
|
|
{
|
|
|
|
guint i;
|
|
|
|
GSList *walk;
|
2004-03-14 22:34:34 +00:00
|
|
|
|
2004-01-29 02:50:20 +00:00
|
|
|
for (i = 0; i < ogg->chains->len; i++) {
|
|
|
|
GstOggChain *chain = &g_array_index (ogg->chains, GstOggChain, i);
|
2004-03-14 22:34:34 +00:00
|
|
|
|
|
|
|
GST_INFO_OBJECT (ogg, "chain %d (%u streams):", i,
|
2004-03-15 19:32:28 +00:00
|
|
|
g_slist_length (chain->pads));
|
2004-01-29 02:50:20 +00:00
|
|
|
for (walk = chain->pads; walk; walk = g_slist_next (walk)) {
|
2004-07-02 03:41:22 +00:00
|
|
|
gst_ogg_print_pad (ogg, walk->data);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (ogg->unordered) {
|
|
|
|
GST_INFO_OBJECT (ogg, "unordered (%u streams):", i,
|
|
|
|
g_slist_length (ogg->unordered));
|
|
|
|
for (walk = ogg->unordered; walk; walk = g_slist_next (walk)) {
|
|
|
|
gst_ogg_print_pad (ogg, walk->data);
|
2004-01-29 02:50:20 +00:00
|
|
|
}
|
|
|
|
}
|
compile fixes for --disable-gst-debug, G_DISABLE_ASSERT and friends
Original commit message from CVS:
* ext/alsa/gstalsamixer.c: (gst_alsa_mixer_get_volume),
(gst_alsa_mixer_set_volume), (gst_alsa_mixer_set_mute),
(gst_alsa_mixer_set_record), (gst_alsa_mixer_set_option),
(gst_alsa_mixer_get_option):
* ext/dvdnav/dvdnavsrc.c: (dvdnav_get_event_name),
(dvdnavsrc_print_event):
* ext/ogg/gstoggdemux.c: (_find_chain_process), (gst_ogg_print):
* ext/ogg/gstoggmux.c: (gst_ogg_mux_pad_link),
(gst_ogg_mux_pad_unlink):
* gst/multipart/multipartmux.c: (gst_multipart_mux_pad_link),
(gst_multipart_mux_pad_unlink):
* gst/videofilter/gstvideobalance.c:
(gst_videobalance_colorbalance_set_value):
* gst/videomixer/videomixer.c: (gst_videomixer_pad_link),
(gst_videomixer_pad_unlink):
* po/uk.po:
* sys/oss/gstossmixer.c:
* sys/v4l/gstv4lcolorbalance.c:
* sys/v4l/gstv4ltuner.c:
* sys/v4l/v4lsrc_calls.c:
* sys/v4l2/gstv4l2colorbalance.c:
* sys/v4l2/gstv4l2tuner.c:
compile fixes for --disable-gst-debug, G_DISABLE_ASSERT and friends
2004-08-03 16:06:08 +00:00
|
|
|
|
2004-01-29 02:50:20 +00:00
|
|
|
}
|
compile fixes for --disable-gst-debug, G_DISABLE_ASSERT and friends
Original commit message from CVS:
* ext/alsa/gstalsamixer.c: (gst_alsa_mixer_get_volume),
(gst_alsa_mixer_set_volume), (gst_alsa_mixer_set_mute),
(gst_alsa_mixer_set_record), (gst_alsa_mixer_set_option),
(gst_alsa_mixer_get_option):
* ext/dvdnav/dvdnavsrc.c: (dvdnav_get_event_name),
(dvdnavsrc_print_event):
* ext/ogg/gstoggdemux.c: (_find_chain_process), (gst_ogg_print):
* ext/ogg/gstoggmux.c: (gst_ogg_mux_pad_link),
(gst_ogg_mux_pad_unlink):
* gst/multipart/multipartmux.c: (gst_multipart_mux_pad_link),
(gst_multipart_mux_pad_unlink):
* gst/videofilter/gstvideobalance.c:
(gst_videobalance_colorbalance_set_value):
* gst/videomixer/videomixer.c: (gst_videomixer_pad_link),
(gst_videomixer_pad_unlink):
* po/uk.po:
* sys/oss/gstossmixer.c:
* sys/v4l/gstv4lcolorbalance.c:
* sys/v4l/gstv4ltuner.c:
* sys/v4l/v4lsrc_calls.c:
* sys/v4l2/gstv4l2colorbalance.c:
* sys/v4l2/gstv4l2tuner.c:
compile fixes for --disable-gst-debug, G_DISABLE_ASSERT and friends
2004-08-03 16:06:08 +00:00
|
|
|
#endif /* GST_DISABLE_GST_DEBUG */
|