mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-10-04 09:42:19 +00:00
this patch implements metadata the wtay way.
Original commit message from CVS: this patch implements metadata the wtay way. some other stuff I still need to clean up to make it work well. test it with gst-launch filesrc location=... ! vorbisfile
This commit is contained in:
parent
9a41ec69ff
commit
a88782e66b
1 changed files with 306 additions and 69 deletions
|
@ -48,6 +48,9 @@ struct _VorbisFile {
|
|||
|
||||
gboolean restart;
|
||||
gboolean need_discont;
|
||||
gboolean get_metadata; /* TRUE if we request metadata */
|
||||
gboolean have_metadata; /* TRUE if we already have this */
|
||||
gboolean have_metadata_technical; /* TRUE if we already have this */
|
||||
gboolean eos;
|
||||
gboolean seek_pending;
|
||||
gint64 seek_value;
|
||||
|
@ -59,13 +62,30 @@ struct _VorbisFile {
|
|||
guint64 total_out;
|
||||
guint64 total_bytes;
|
||||
guint64 offset;
|
||||
|
||||
int link; /* stream id of logical bitstream */
|
||||
int streams; /* number of streams in physical bitstream */
|
||||
int version;
|
||||
int channels;
|
||||
long samplerate;
|
||||
long bitrate;
|
||||
|
||||
long bitrate_upper;
|
||||
long bitrate_nominal;
|
||||
long bitrate_lower;
|
||||
/* long bitrate_window; not set in 1.0 */
|
||||
|
||||
GstCaps *metadata;
|
||||
};
|
||||
|
||||
struct _VorbisFileClass {
|
||||
GstElementClass parent_class;
|
||||
|
||||
/* signals */
|
||||
void (*have_metadata) (GstElement *element);
|
||||
};
|
||||
|
||||
GType vorbisfile_get_type(void);
|
||||
GType vorbisfile_get_type (void);
|
||||
|
||||
extern GstPadTemplate *gst_vorbisdec_src_template, *gst_vorbisdec_sink_template;
|
||||
|
||||
|
@ -85,48 +105,70 @@ GstElementDetails vorbisfile_details =
|
|||
enum
|
||||
{
|
||||
/* FILL ME */
|
||||
SIGNAL_HAVE_METADATA, /* FIXME: maybe separate out in
|
||||
- descriptive
|
||||
- technical
|
||||
- easy
|
||||
- hard (expensive)
|
||||
*/
|
||||
LAST_SIGNAL
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
ARG_0,
|
||||
ARG_COMMENT,
|
||||
ARG_METADATA,
|
||||
ARG_VENDOR,
|
||||
ARG_VERSION,
|
||||
ARG_CHANNELS,
|
||||
ARG_RATE,
|
||||
ARG_STREAMS,
|
||||
ARG_LINK,
|
||||
ARG_BITRATE,
|
||||
ARG_BITRATE_UPPER,
|
||||
ARG_BITRATE_NOMINAL,
|
||||
ARG_BITRATE_LOWER,
|
||||
ARG_BITRATE_WINDOW,
|
||||
};
|
||||
|
||||
static void gst_vorbisfile_class_init (VorbisFileClass *klass);
|
||||
static void gst_vorbisfile_init (VorbisFile *vorbisfile);
|
||||
static void
|
||||
gst_vorbisfile_class_init (VorbisFileClass *klass);
|
||||
static void gst_vorbisfile_init (VorbisFile *vorbisfile);
|
||||
|
||||
static GstElementStateReturn
|
||||
gst_vorbisfile_change_state (GstElement *element);
|
||||
gst_vorbisfile_change_state (GstElement *element);
|
||||
|
||||
static const GstFormat* gst_vorbisfile_get_formats (GstPad *pad);
|
||||
static gboolean gst_vorbisfile_src_convert (GstPad *pad, GstFormat src_format, gint64 src_value,
|
||||
GstFormat *dest_format, gint64 *dest_value);
|
||||
static const
|
||||
GstFormat* gst_vorbisfile_get_formats (GstPad *pad);
|
||||
static gboolean gst_vorbisfile_src_convert (GstPad *pad,
|
||||
GstFormat src_format,
|
||||
gint64 src_value,
|
||||
GstFormat *dest_format,
|
||||
gint64 *dest_value);
|
||||
static const GstPadQueryType*
|
||||
gst_vorbisfile_get_query_types (GstPad *pad);
|
||||
gst_vorbisfile_get_query_types (GstPad *pad);
|
||||
|
||||
static gboolean gst_vorbisfile_src_query (GstPad *pad, GstPadQueryType type,
|
||||
GstFormat *format, gint64 *value);
|
||||
static const GstEventMask*
|
||||
gst_vorbisfile_get_event_masks (GstPad *pad);
|
||||
static gboolean gst_vorbisfile_src_event (GstPad *pad, GstEvent *event);
|
||||
static gboolean gst_vorbisfile_src_query (GstPad *pad,
|
||||
GstPadQueryType type,
|
||||
GstFormat *format,
|
||||
gint64 *value);
|
||||
static const
|
||||
GstEventMask* gst_vorbisfile_get_event_masks (GstPad *pad);
|
||||
static gboolean gst_vorbisfile_src_event (GstPad *pad, GstEvent *event);
|
||||
|
||||
static void gst_vorbisfile_get_property (GObject *object, guint prop_id,
|
||||
GValue *value, GParamSpec *pspec);
|
||||
static void gst_vorbisfile_get_property (GObject *object,
|
||||
guint prop_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec);
|
||||
static void gst_vorbisfile_set_property (GObject *object,
|
||||
guint prop_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec);
|
||||
|
||||
static void gst_vorbisfile_loop (GstElement *element);
|
||||
static void gst_vorbisfile_loop (GstElement *element);
|
||||
|
||||
static GstElementClass *parent_class = NULL;
|
||||
/*static guint gst_vorbisfile_signals[LAST_SIGNAL] = { 0 }; */
|
||||
static guint gst_vorbisfile_signals[LAST_SIGNAL] = { 0 };
|
||||
|
||||
GType
|
||||
vorbisfile_get_type (void)
|
||||
|
@ -135,18 +177,14 @@ vorbisfile_get_type (void)
|
|||
|
||||
if (!vorbisfile_type) {
|
||||
static const GTypeInfo vorbisfile_info = {
|
||||
sizeof (VorbisFileClass),
|
||||
NULL,
|
||||
NULL,
|
||||
(GClassInitFunc) gst_vorbisfile_class_init,
|
||||
NULL,
|
||||
NULL,
|
||||
sizeof (VorbisFile),
|
||||
0,
|
||||
sizeof (VorbisFileClass), NULL, NULL,
|
||||
(GClassInitFunc) gst_vorbisfile_class_init, NULL, NULL,
|
||||
sizeof (VorbisFile), 0,
|
||||
(GInstanceInitFunc) gst_vorbisfile_init,
|
||||
};
|
||||
|
||||
vorbisfile_type = g_type_register_static (GST_TYPE_ELEMENT, "VorbisFile", &vorbisfile_info, 0);
|
||||
vorbisfile_type = g_type_register_static (GST_TYPE_ELEMENT, "VorbisFile",
|
||||
&vorbisfile_info, 0);
|
||||
}
|
||||
return vorbisfile_type;
|
||||
}
|
||||
|
@ -162,11 +200,12 @@ gst_vorbisfile_class_init (VorbisFileClass * klass)
|
|||
|
||||
parent_class = g_type_class_ref (GST_TYPE_ELEMENT);
|
||||
|
||||
g_object_class_install_property (gobject_class, ARG_COMMENT,
|
||||
g_param_spec_string ("comment", "Comment", "The comment tags for this vorbis stream",
|
||||
"", G_PARAM_READABLE));
|
||||
g_object_class_install_property (gobject_class, ARG_METADATA,
|
||||
g_param_spec_boxed ("metadata", "Metadata", "Metadata",
|
||||
GST_TYPE_CAPS, G_PARAM_READABLE));
|
||||
g_object_class_install_property (gobject_class, ARG_VENDOR,
|
||||
g_param_spec_string ("vendor", "Vendor", "The vendor for this vorbis stream",
|
||||
g_param_spec_string ("vendor", "Vendor",
|
||||
"The vendor for this vorbis stream",
|
||||
"", G_PARAM_READABLE));
|
||||
g_object_class_install_property (gobject_class, ARG_VERSION,
|
||||
g_param_spec_int ("version", "Version", "The version",
|
||||
|
@ -174,10 +213,22 @@ gst_vorbisfile_class_init (VorbisFileClass * klass)
|
|||
g_object_class_install_property (gobject_class, ARG_CHANNELS,
|
||||
g_param_spec_int ("channels", "Channels", "The number of channels",
|
||||
0, G_MAXINT, 0, G_PARAM_READABLE));
|
||||
g_object_class_install_property (gobject_class, ARG_RATE,
|
||||
g_object_class_install_property (gobject_class, ARG_STREAMS,
|
||||
g_param_spec_int ("streams", "Streams",
|
||||
"Number of logical bitstreams in the physical bitstream",
|
||||
0, G_MAXINT, 0, G_PARAM_READABLE));
|
||||
g_object_class_install_property (gobject_class, ARG_LINK,
|
||||
g_param_spec_int ("link", "Link",
|
||||
"The link id of the current logical bitstream",
|
||||
-1, G_MAXINT, 0, G_PARAM_READWRITE));
|
||||
g_object_class_install_property (gobject_class, ARG_RATE,
|
||||
g_param_spec_int ("rate", "Rate", "The samplerate",
|
||||
0, G_MAXINT, 0, G_PARAM_READABLE));
|
||||
g_object_class_install_property (gobject_class, ARG_BITRATE_UPPER,
|
||||
g_object_class_install_property (gobject_class, ARG_BITRATE,
|
||||
g_param_spec_int ("bitrate", "Bitrate",
|
||||
"(average) bitrate in bits per second",
|
||||
0, G_MAXINT, 0, G_PARAM_READABLE));
|
||||
g_object_class_install_property (gobject_class, ARG_BITRATE_UPPER,
|
||||
g_param_spec_int ("bitrate_upper", "bitrate_upper", "bitrate_upper",
|
||||
0, G_MAXINT, 0, G_PARAM_READABLE));
|
||||
g_object_class_install_property (gobject_class, ARG_BITRATE_NOMINAL,
|
||||
|
@ -191,6 +242,13 @@ gst_vorbisfile_class_init (VorbisFileClass * klass)
|
|||
0, G_MAXINT, 0, G_PARAM_READABLE));
|
||||
|
||||
gobject_class->get_property = gst_vorbisfile_get_property;
|
||||
gobject_class->set_property = gst_vorbisfile_set_property;
|
||||
|
||||
gst_vorbisfile_signals[SIGNAL_HAVE_METADATA] =
|
||||
g_signal_new ("have_metadata", G_TYPE_FROM_CLASS(klass), G_SIGNAL_RUN_LAST,
|
||||
G_STRUCT_OFFSET (VorbisFileClass, have_metadata),
|
||||
NULL, NULL,
|
||||
g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
|
||||
|
||||
gstelement_class->change_state = gst_vorbisfile_change_state;
|
||||
}
|
||||
|
@ -198,17 +256,21 @@ gst_vorbisfile_class_init (VorbisFileClass * klass)
|
|||
static void
|
||||
gst_vorbisfile_init (VorbisFile * vorbisfile)
|
||||
{
|
||||
vorbisfile->sinkpad = gst_pad_new_from_template (gst_vorbisdec_sink_template, "sink");
|
||||
vorbisfile->sinkpad = gst_pad_new_from_template (gst_vorbisdec_sink_template,
|
||||
"sink");
|
||||
gst_element_add_pad (GST_ELEMENT (vorbisfile), vorbisfile->sinkpad);
|
||||
gst_pad_set_convert_function (vorbisfile->sinkpad, NULL);
|
||||
|
||||
gst_element_set_loop_function (GST_ELEMENT (vorbisfile), gst_vorbisfile_loop);
|
||||
vorbisfile->srcpad = gst_pad_new_from_template (gst_vorbisdec_src_template, "src");
|
||||
vorbisfile->srcpad = gst_pad_new_from_template (gst_vorbisdec_src_template,
|
||||
"src");
|
||||
gst_element_add_pad (GST_ELEMENT (vorbisfile), vorbisfile->srcpad);
|
||||
gst_pad_set_formats_function (vorbisfile->srcpad, gst_vorbisfile_get_formats);
|
||||
gst_pad_set_query_type_function (vorbisfile->srcpad, gst_vorbisfile_get_query_types);
|
||||
gst_pad_set_query_type_function (vorbisfile->srcpad,
|
||||
gst_vorbisfile_get_query_types);
|
||||
gst_pad_set_query_function (vorbisfile->srcpad, gst_vorbisfile_src_query);
|
||||
gst_pad_set_event_mask_function (vorbisfile->srcpad, gst_vorbisfile_get_event_masks);
|
||||
gst_pad_set_event_mask_function (vorbisfile->srcpad,
|
||||
gst_vorbisfile_get_event_masks);
|
||||
gst_pad_set_event_function (vorbisfile->srcpad, gst_vorbisfile_src_event);
|
||||
gst_pad_set_convert_function (vorbisfile->srcpad, gst_vorbisfile_src_convert);
|
||||
|
||||
|
@ -218,8 +280,14 @@ gst_vorbisfile_init (VorbisFile * vorbisfile)
|
|||
vorbisfile->offset = 0;
|
||||
vorbisfile->seek_pending = 0;
|
||||
vorbisfile->need_discont = FALSE;
|
||||
vorbisfile->get_metadata = TRUE;
|
||||
vorbisfile->link = -1; /* by default, ask for entire bitstream */
|
||||
vorbisfile->metadata = NULL;
|
||||
}
|
||||
|
||||
/* the next four functions are the ov callbacks we provide to vorbisfile
|
||||
* which interface between GStreamer's handling of the data flow and
|
||||
* vorbis's needs */
|
||||
static size_t
|
||||
gst_vorbisfile_read (void *ptr, size_t size, size_t nmemb, void *datasource)
|
||||
{
|
||||
|
@ -349,23 +417,95 @@ ov_callbacks vorbisfile_ov_callbacks =
|
|||
gst_vorbisfile_tell,
|
||||
};
|
||||
|
||||
/* retrieve the comment field and put tags in metadata GstCaps
|
||||
* returns TRUE if caps were still valid or could be set,
|
||||
* FALSE if they couldn't be read somehow */
|
||||
static gboolean
|
||||
gst_vorbisfile_get_metadata (VorbisFile *vorbisfile)
|
||||
{
|
||||
OggVorbis_File *vf = &vorbisfile->vf;
|
||||
char **ptr;
|
||||
int link = vorbisfile->link;
|
||||
GstProps *props = NULL;
|
||||
GstPropsEntry *entry;
|
||||
gchar *name, *value;
|
||||
|
||||
/* check if we need to update or not */
|
||||
if (vorbisfile->have_metadata)
|
||||
return TRUE;
|
||||
|
||||
/* clear old one */
|
||||
if (vorbisfile->metadata) {
|
||||
gst_caps_unref (vorbisfile->metadata);
|
||||
vorbisfile->metadata = NULL;
|
||||
}
|
||||
|
||||
ptr = ov_comment (vf, link)->user_comments;
|
||||
if (! (*ptr)) return FALSE;
|
||||
props = gst_props_empty_new ();
|
||||
|
||||
while (*ptr) {
|
||||
value = strstr (*ptr, "=");
|
||||
if (value) {
|
||||
*value = 0;
|
||||
++value;
|
||||
name = *ptr;
|
||||
entry = gst_props_entry_new (name, GST_PROPS_STRING_TYPE, value);
|
||||
gst_props_add_entry (props, (GstPropsEntry *) entry);
|
||||
}
|
||||
++ptr;
|
||||
}
|
||||
|
||||
vorbisfile->have_metadata = TRUE;
|
||||
vorbisfile->metadata = gst_caps_new ("vorbisfile_metadata",
|
||||
"application/x-gst-metadata",
|
||||
props);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* retrieve techical metadata and update vorbisfile with it */
|
||||
/* FIXME: write me */
|
||||
/* FIXME: make this less more expensive; only update it if the
|
||||
* link id has changed */
|
||||
static void
|
||||
gst_vorbisfile_metadata_get_technical (VorbisFile *vorbisfile)
|
||||
{
|
||||
OggVorbis_File *vf = &vorbisfile->vf;
|
||||
//vorbis_info *vi;
|
||||
//int link = vorbisfile->link;
|
||||
|
||||
/* check if we need to update or not */
|
||||
if (vorbisfile->have_metadata_technical)
|
||||
return;
|
||||
|
||||
/* FIXME: clear old one */
|
||||
|
||||
/* get number of streams */
|
||||
vorbisfile->streams = ov_streams (vf);
|
||||
}
|
||||
static void
|
||||
gst_vorbisfile_loop (GstElement *element)
|
||||
{
|
||||
VorbisFile *vorbisfile = GST_VORBISFILE (element);
|
||||
OggVorbis_File *vf = &vorbisfile->vf;
|
||||
GstBuffer *outbuf;
|
||||
long ret;
|
||||
GstClockTime time;
|
||||
gint64 samples;
|
||||
|
||||
/* this function needs to go first since you don't want to be messing
|
||||
* with an unset vf ;) */
|
||||
if (vorbisfile->restart) {
|
||||
vorbisfile->current_section = 0;
|
||||
vorbisfile->offset = 0;
|
||||
vorbisfile->total_bytes = 0;
|
||||
vorbisfile->may_eos = FALSE;
|
||||
vorbisfile->vf.seekable = gst_bytestream_seek (vorbisfile->bs, 0, GST_SEEK_METHOD_SET);
|
||||
vorbisfile->vf.seekable = gst_bytestream_seek (vorbisfile->bs, 0,
|
||||
GST_SEEK_METHOD_SET);
|
||||
|
||||
if (ov_open_callbacks (vorbisfile, &vorbisfile->vf, NULL, 0, vorbisfile_ov_callbacks) < 0) {
|
||||
/* open our custom vorbisfile data object with the callbacks we provide */
|
||||
if (ov_open_callbacks (vorbisfile, &vorbisfile->vf, NULL, 0,
|
||||
vorbisfile_ov_callbacks) < 0) {
|
||||
gst_element_error (element, "this is not a vorbis file");
|
||||
return;
|
||||
}
|
||||
|
@ -373,33 +513,80 @@ gst_vorbisfile_loop (GstElement *element)
|
|||
vorbisfile->restart = FALSE;
|
||||
}
|
||||
|
||||
/* get relevant data if asked for */
|
||||
if (vorbisfile->get_metadata) {
|
||||
vorbis_info *vi;
|
||||
double time_total;
|
||||
ogg_int64_t raw_total;
|
||||
int link = vorbisfile->link;
|
||||
|
||||
if (gst_vorbisfile_get_metadata (vorbisfile))
|
||||
g_object_notify (G_OBJECT (vorbisfile), "metadata");
|
||||
|
||||
|
||||
/* get stream metadata */
|
||||
/* FIXME: due to a compiler bug, the actual vorbis bitrate function
|
||||
* doesn't return a good number ... */
|
||||
vorbisfile->bitrate = ov_bitrate (vf, link);
|
||||
if (vorbisfile->bitrate == OV_EINVAL)
|
||||
g_warning ("OV_EINVAL: vf not open\n");
|
||||
if (vorbisfile->bitrate == OV_FALSE)
|
||||
g_warning ("OV_FALSE: non-seekable and no bitrate values set\n");
|
||||
|
||||
/* ... so we calculate it by hand, which should be done better
|
||||
* by avoiding headers and stuff */
|
||||
time_total = ov_time_total (vf, link);
|
||||
raw_total = ov_raw_total (vf, link);
|
||||
g_print ("total time: %f\n", time_total);
|
||||
g_print ("abr: %d\n",
|
||||
(gint) ((guint64) raw_total / (guint64) time_total) * 8);
|
||||
vi = ov_info (vf, link);
|
||||
vorbisfile->version = vi->version;
|
||||
vorbisfile->samplerate = vi->rate;
|
||||
vorbisfile->channels = vi->channels;
|
||||
vorbisfile->bitrate_upper = vi->bitrate_upper;
|
||||
vorbisfile->bitrate_nominal = vi->bitrate_nominal;
|
||||
vorbisfile->bitrate_lower = vi->bitrate_lower;
|
||||
g_print ("Bitstream is %d channel, %ld Hz, %d version, %ld bitrate\n",
|
||||
vi->channels, vi->rate, vi->version, vorbisfile->bitrate);
|
||||
g_print ("bitrate: %f\n", (double) vorbisfile->bitrate);
|
||||
/* fire the signal saying we have metadata */
|
||||
g_signal_emit (G_OBJECT(vorbisfile),
|
||||
gst_vorbisfile_signals[SIGNAL_HAVE_METADATA], 0);
|
||||
vorbisfile->get_metadata = FALSE;
|
||||
}
|
||||
|
||||
if (vorbisfile->seek_pending) {
|
||||
/* get time to seek to in seconds */
|
||||
gdouble seek_to = (gdouble) vorbisfile->seek_value / GST_SECOND;
|
||||
|
||||
switch (vorbisfile->seek_format) {
|
||||
case GST_FORMAT_TIME:
|
||||
if (vorbisfile->seek_accurate) {
|
||||
if (ov_time_seek (&vorbisfile->vf, (gdouble) vorbisfile->seek_value / GST_SECOND) == 0) {
|
||||
if (ov_time_seek (&vorbisfile->vf, seek_to) == 0) {
|
||||
vorbisfile->need_discont = TRUE;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (ov_time_seek_page (&vorbisfile->vf, (gdouble) vorbisfile->seek_value / GST_SECOND) == 0) {
|
||||
if (ov_time_seek_page (&vorbisfile->vf, seek_to) == 0) {
|
||||
vorbisfile->need_discont = TRUE;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case GST_FORMAT_UNITS:
|
||||
if (vorbisfile->seek_accurate) {
|
||||
if (ov_pcm_seek (&vorbisfile->vf, (gdouble) vorbisfile->seek_value / GST_SECOND) == 0) {
|
||||
if (ov_pcm_seek (&vorbisfile->vf, seek_to) == 0) {
|
||||
vorbisfile->need_discont = TRUE;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (ov_pcm_seek_page (&vorbisfile->vf, (gdouble) vorbisfile->seek_value / GST_SECOND) == 0) {
|
||||
if (ov_pcm_seek_page (&vorbisfile->vf, seek_to) == 0) {
|
||||
vorbisfile->need_discont = TRUE;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
g_warning ("unknown seek method, implement me !");
|
||||
break;
|
||||
}
|
||||
vorbisfile->seek_pending = FALSE;
|
||||
|
@ -412,20 +599,23 @@ gst_vorbisfile_loop (GstElement *element)
|
|||
/* get current time for discont and buffer timestamp */
|
||||
time = (GstClockTime) (ov_time_tell (&vorbisfile->vf) * GST_SECOND);
|
||||
|
||||
ret = ov_read (&vorbisfile->vf, GST_BUFFER_DATA (outbuf), GST_BUFFER_SIZE (outbuf),
|
||||
(G_BYTE_ORDER == G_LITTLE_ENDIAN ? 0 : 1), sizeof (gint16), 1, &vorbisfile->current_section);
|
||||
ret = ov_read (&vorbisfile->vf,
|
||||
GST_BUFFER_DATA (outbuf), GST_BUFFER_SIZE (outbuf),
|
||||
(G_BYTE_ORDER == G_LITTLE_ENDIAN ? 0 : 1),
|
||||
sizeof (gint16), 1, &vorbisfile->current_section);
|
||||
|
||||
if (vorbisfile->need_discont) {
|
||||
GstEvent *discont;
|
||||
|
||||
vorbisfile->need_discont = FALSE;
|
||||
|
||||
/* if the pad is not usable, don't push it out */
|
||||
if (GST_PAD_IS_USABLE (vorbisfile->srcpad)) {
|
||||
/* get stream stats */
|
||||
samples = (gint64) (ov_pcm_tell (&vorbisfile->vf));
|
||||
|
||||
discont = gst_event_new_discontinuous (FALSE, GST_FORMAT_TIME, time,
|
||||
GST_FORMAT_UNITS, samples, NULL);
|
||||
GST_FORMAT_UNITS, samples, NULL);
|
||||
|
||||
gst_pad_push (vorbisfile->srcpad, GST_BUFFER (discont));
|
||||
}
|
||||
|
@ -433,11 +623,15 @@ gst_vorbisfile_loop (GstElement *element)
|
|||
|
||||
if (ret == 0) {
|
||||
GST_DEBUG (0, "eos");
|
||||
//ov_clear (&vorbisfile->vf);
|
||||
/* send EOS event */
|
||||
/*FIXME: should we do this or not ?
|
||||
ov_clear (&vorbisfile->vf);*/
|
||||
vorbisfile->restart = TRUE;
|
||||
gst_buffer_unref (outbuf);
|
||||
/* if the pad is not usable, don't push it out */
|
||||
if (GST_PAD_IS_USABLE (vorbisfile->srcpad))
|
||||
gst_pad_push (vorbisfile->srcpad, GST_BUFFER (gst_event_new (GST_EVENT_EOS)));
|
||||
gst_pad_push (vorbisfile->srcpad,
|
||||
GST_BUFFER (gst_event_new (GST_EVENT_EOS)));
|
||||
gst_element_set_eos (element);
|
||||
return;
|
||||
}
|
||||
|
@ -453,19 +647,20 @@ gst_vorbisfile_loop (GstElement *element)
|
|||
|
||||
if (gst_pad_try_set_caps (vorbisfile->srcpad,
|
||||
GST_CAPS_NEW ("vorbisdec_src",
|
||||
"audio/raw",
|
||||
"format", GST_PROPS_STRING ("int"),
|
||||
"law", GST_PROPS_INT (0),
|
||||
"endianness", GST_PROPS_INT (G_BYTE_ORDER),
|
||||
"signed", GST_PROPS_BOOLEAN (TRUE),
|
||||
"width", GST_PROPS_INT (16),
|
||||
"depth", GST_PROPS_INT (16),
|
||||
"rate", GST_PROPS_INT (vi->rate),
|
||||
"channels", GST_PROPS_INT (vi->channels)
|
||||
)) <= 0)
|
||||
"audio/raw",
|
||||
"format", GST_PROPS_STRING ("int"),
|
||||
"law", GST_PROPS_INT (0),
|
||||
"endianness", GST_PROPS_INT (G_BYTE_ORDER),
|
||||
"signed", GST_PROPS_BOOLEAN (TRUE),
|
||||
"width", GST_PROPS_INT (16),
|
||||
"depth", GST_PROPS_INT (16),
|
||||
"rate", GST_PROPS_INT (vi->rate),
|
||||
"channels", GST_PROPS_INT (vi->channels)
|
||||
)) <= 0)
|
||||
{
|
||||
gst_buffer_unref (outbuf);
|
||||
gst_element_error (GST_ELEMENT (vorbisfile), "could not negotiate format");
|
||||
gst_element_error (GST_ELEMENT (vorbisfile),
|
||||
"could not negotiate format");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -497,8 +692,11 @@ gst_vorbisfile_get_formats (GstPad *pad)
|
|||
return formats;
|
||||
}
|
||||
|
||||
/* handles conversion of location offsets between two formats based on
|
||||
* src caps */
|
||||
static gboolean
|
||||
gst_vorbisfile_src_convert (GstPad *pad, GstFormat src_format, gint64 src_value,
|
||||
gst_vorbisfile_src_convert (GstPad *pad,
|
||||
GstFormat src_format, gint64 src_value,
|
||||
GstFormat *dest_format, gint64 *dest_value)
|
||||
{
|
||||
gboolean res = TRUE;
|
||||
|
@ -579,7 +777,8 @@ gst_vorbisfile_get_query_types (GstPad *pad)
|
|||
};
|
||||
return types;
|
||||
}
|
||||
|
||||
|
||||
/* handles queries for location in the stream in the requested format */
|
||||
static gboolean
|
||||
gst_vorbisfile_src_query (GstPad *pad, GstPadQueryType type,
|
||||
GstFormat *format, gint64 *value)
|
||||
|
@ -632,7 +831,8 @@ gst_vorbisfile_src_query (GstPad *pad, GstPadQueryType type,
|
|||
if (vorbisfile->vf.seekable)
|
||||
*value = (gint64) (ov_time_tell (&vorbisfile->vf) * GST_SECOND);
|
||||
else
|
||||
*value = vorbisfile->total_bytes * GST_SECOND / (vi->rate * vi->channels * 2);
|
||||
*value = vorbisfile->total_bytes * GST_SECOND
|
||||
/ (vi->rate * vi->channels * 2);
|
||||
break;
|
||||
case GST_FORMAT_BYTES:
|
||||
if (vorbisfile->vf.seekable)
|
||||
|
@ -668,7 +868,8 @@ gst_vorbisfile_get_event_masks (GstPad *pad)
|
|||
};
|
||||
return masks;
|
||||
}
|
||||
|
||||
|
||||
/* handle events on src pad */
|
||||
static gboolean
|
||||
gst_vorbisfile_src_event (GstPad *pad, GstEvent *event)
|
||||
{
|
||||
|
@ -695,7 +896,8 @@ gst_vorbisfile_src_event (GstPad *pad, GstEvent *event)
|
|||
vorbisfile->seek_pending = TRUE;
|
||||
vorbisfile->seek_value = offset;
|
||||
vorbisfile->seek_format = GST_FORMAT_TIME;
|
||||
vorbisfile->seek_accurate = GST_EVENT_SEEK_FLAGS (event) & GST_SEEK_FLAG_ACCURATE;
|
||||
vorbisfile->seek_accurate = GST_EVENT_SEEK_FLAGS (event)
|
||||
& GST_SEEK_FLAG_ACCURATE;
|
||||
break;
|
||||
case GST_FORMAT_BYTES:
|
||||
vi = ov_info (&vorbisfile->vf, -1);
|
||||
|
@ -709,7 +911,8 @@ gst_vorbisfile_src_event (GstPad *pad, GstEvent *event)
|
|||
vorbisfile->seek_pending = TRUE;
|
||||
vorbisfile->seek_value = offset;
|
||||
vorbisfile->seek_format = GST_FORMAT_UNITS;
|
||||
vorbisfile->seek_accurate = GST_EVENT_SEEK_FLAGS (event) & GST_SEEK_FLAG_ACCURATE;
|
||||
vorbisfile->seek_accurate = GST_EVENT_SEEK_FLAGS (event)
|
||||
& GST_SEEK_FLAG_ACCURATE;
|
||||
break;
|
||||
default:
|
||||
res = FALSE;
|
||||
|
@ -757,8 +960,9 @@ gst_vorbisfile_change_state (GstElement *element)
|
|||
return GST_STATE_SUCCESS;
|
||||
}
|
||||
|
||||
static void
|
||||
gst_vorbisfile_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
|
||||
static void
|
||||
gst_vorbisfile_set_property (GObject *object, guint prop_id,
|
||||
const GValue *value, GParamSpec *pspec)
|
||||
{
|
||||
VorbisFile *vorbisfile;
|
||||
|
||||
|
@ -767,8 +971,31 @@ gst_vorbisfile_get_property (GObject *object, guint prop_id, GValue *value, GPar
|
|||
vorbisfile = GST_VORBISFILE (object);
|
||||
|
||||
switch (prop_id) {
|
||||
case ARG_COMMENT:
|
||||
g_value_set_string (value, "comment");
|
||||
case ARG_METADATA:
|
||||
break;
|
||||
case ARG_LINK:
|
||||
vorbisfile->link = g_value_get_int (value);
|
||||
break;
|
||||
default:
|
||||
g_warning ("Unknown property id\n");
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gst_vorbisfile_get_property (GObject *object, guint prop_id,
|
||||
GValue *value, GParamSpec *pspec)
|
||||
{
|
||||
VorbisFile *vorbisfile;
|
||||
|
||||
g_return_if_fail (GST_IS_VORBISFILE (object));
|
||||
|
||||
vorbisfile = GST_VORBISFILE (object);
|
||||
|
||||
/* FIXME: the reupdate could be expensive */
|
||||
switch (prop_id) {
|
||||
case ARG_METADATA:
|
||||
gst_vorbisfile_get_metadata (vorbisfile);
|
||||
g_value_set_boxed (value, vorbisfile->metadata);
|
||||
break;
|
||||
case ARG_VENDOR:
|
||||
break;
|
||||
|
@ -778,6 +1005,14 @@ gst_vorbisfile_get_property (GObject *object, guint prop_id, GValue *value, GPar
|
|||
break;
|
||||
case ARG_RATE:
|
||||
break;
|
||||
case ARG_STREAMS:
|
||||
gst_vorbisfile_metadata_get_technical (vorbisfile);
|
||||
g_value_set_int (value, vorbisfile->streams);
|
||||
break;
|
||||
case ARG_LINK:
|
||||
break;
|
||||
case ARG_BITRATE:
|
||||
break;
|
||||
case ARG_BITRATE_UPPER:
|
||||
break;
|
||||
case ARG_BITRATE_NOMINAL:
|
||||
|
@ -786,5 +1021,7 @@ gst_vorbisfile_get_property (GObject *object, guint prop_id, GValue *value, GPar
|
|||
break;
|
||||
case ARG_BITRATE_WINDOW:
|
||||
break;
|
||||
default:
|
||||
g_warning ("Unknown property id\n");
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue