gstreamer/examples/seeking/vorbisfile.c

265 lines
6.3 KiB
C
Raw Normal View History

#include <stdlib.h>
#include <gst/gst.h>
#include <string.h>
static gboolean ready = FALSE;
struct probe_context
{
GstElement *pipeline;
GstElement *element;
GstPad *pad;
GstFormat ls_format;
gint total_ls;
GstCaps *metadata;
GstCaps *streaminfo;
GstCaps *caps;
};
static void
print_caps (GstCaps * caps)
{
char *s;
s = gst_caps_to_string (caps);
g_print (" %s\n", s);
g_free (s);
}
static void
print_format (GstCaps * caps)
{
char *s;
s = gst_caps_to_string (caps);
g_print (" format: %s\n", s);
g_free (s);
}
static void
print_lbs_info (struct probe_context *context, gint stream)
{
const GstFormat *formats;
/* FIXME: need a better name here */
g_print (" stream info:\n");
/* report info in all supported formats */
formats = gst_pad_get_formats (context->pad);
while (*formats) {
const GstFormatDefinition *definition;
gint64 value_start, value_end;
gboolean res;
GstFormat format;
format = *formats;
formats++;
if (format == context->ls_format) {
continue;
}
definition = gst_format_get_details (format);
/* get start and end position of this stream */
res = gst_pad_convert (context->pad,
context->ls_format, stream, &format, &value_start);
res &= gst_pad_convert (context->pad,
context->ls_format, stream + 1, &format, &value_end);
if (res) {
/* substract to get the length */
value_end -= value_start;
if (format == GST_FORMAT_TIME) {
value_end /= (GST_SECOND / 100);
g_print (" %s: %lld:%02lld.%02lld\n", definition->nick,
value_end / 6000, (value_end / 100) % 60, (value_end % 100));
} else {
g_print (" %s: %lld\n", definition->nick, value_end);
}
} else
g_print (" could not get logical stream %s\n", definition->nick);
}
}
static void
deep_notify (GObject * object, GstObject * origin,
GParamSpec * pspec, gpointer data)
{
struct probe_context *context = (struct probe_context *) data;
GValue value = { 0, };
if (!strcmp (pspec->name, "metadata")) {
g_value_init (&value, pspec->value_type);
g_object_get_property (G_OBJECT (origin), pspec->name, &value);
context->metadata = g_value_peek_pointer (&value);
} else if (!strcmp (pspec->name, "streaminfo")) {
g_value_init (&value, pspec->value_type);
g_object_get_property (G_OBJECT (origin), pspec->name, &value);
context->streaminfo = g_value_peek_pointer (&value);
} else if (!strcmp (pspec->name, "caps")) {
if (GST_IS_PAD (origin) && GST_PAD (origin) == context->pad) {
g_value_init (&value, pspec->value_type);
g_object_get_property (G_OBJECT (origin), pspec->name, &value);
context->caps = g_value_peek_pointer (&value);
ready = TRUE;
}
}
}
static gboolean
collect_logical_stream_properties (struct probe_context *context, gint stream)
{
GstEvent *event;
gboolean res;
gint count;
g_print ("info for logical stream %d:\n", stream);
/* seek to stream */
event = gst_event_new_seek (context->ls_format |
GST_SEEK_METHOD_SET | GST_SEEK_FLAG_FLUSH, stream);
res = gst_pad_send_event (context->pad, event);
if (!res) {
g_warning ("seek to logical track failed");
return FALSE;
}
/* run the pipeline to get the info */
count = 0;
ready = FALSE;
while (gst_bin_iterate (GST_BIN (context->pipeline)) && !ready) {
count++;
if (count > 10)
break;
}
print_caps (context->metadata);
print_caps (context->streaminfo);
print_format (context->caps);
print_lbs_info (context, stream);
g_print ("\n");
return TRUE;
}
static void
collect_stream_properties (struct probe_context *context)
{
const GstFormat *formats;
ready = FALSE;
while (gst_bin_iterate (GST_BIN (context->pipeline)) && !ready);
g_print ("stream info:\n");
context->total_ls = -1;
/* report info in all supported formats */
formats = gst_pad_get_formats (context->pad);
while (*formats) {
const GstFormatDefinition *definition;
gint64 value;
gboolean res;
GstFormat format;
format = *formats;
formats++;
res = gst_pad_query (context->pad, GST_QUERY_TOTAL, &format, &value);
definition = gst_format_get_details (format);
if (res) {
if (format == GST_FORMAT_TIME) {
value /= (GST_SECOND / 100);
g_print (" total %s: %lld:%02lld.%02lld\n", definition->nick,
value / 6000, (value / 100) % 60, (value % 100));
} else {
if (format == context->ls_format)
context->total_ls = value;
g_print (" total %s: %lld\n", definition->nick, value);
}
}
}
if (context->total_ls == -1) {
g_warning (" could not get number of logical streams");
}
g_print ("\n");
}
int
main (int argc, char **argv)
{
GstElement *pipeline;
GstElement *filesrc;
GstElement *vorbisfile;
GstPad *pad;
GstFormat logical_stream_format;
struct probe_context *context;
gint stream;
gst_init (&argc, &argv);
if (argc < 2) {
g_print ("usage: %s <oggfile>\n", argv[0]);
return (-1);
}
pipeline = gst_pipeline_new ("pipeline");
filesrc = gst_element_factory_make ("filesrc", "filesrc");
g_assert (filesrc);
g_object_set (G_OBJECT (filesrc), "location", argv[1], NULL);
vorbisfile = gst_element_factory_make ("vorbisfile", "vorbisfile");
//vorbisfile = gst_element_factory_make ("mad", "vorbisfile");
g_assert (vorbisfile);
gst_bin_add (GST_BIN (pipeline), filesrc);
gst_bin_add (GST_BIN (pipeline), vorbisfile);
gst_element_link_pads (filesrc, "src", vorbisfile, "sink");
pad = gst_element_get_pad (vorbisfile, "src");
g_assert (pad);
logical_stream_format = gst_format_get_by_nick ("logical_stream");
g_assert (logical_stream_format != 0);
context = g_new0 (struct probe_context, 1);
context->pipeline = pipeline;
context->element = vorbisfile;
context->pad = pad;
context->ls_format = logical_stream_format;
g_signal_connect (G_OBJECT (pipeline), "deep_notify",
G_CALLBACK (deep_notify), context);
gst_element_set_state (pipeline, GST_STATE_PLAYING);
/* at this point we can inspect the stream */
collect_stream_properties (context);
/* loop over all logical streams to get info */
stream = 0;
while (stream < context->total_ls) {
collect_logical_stream_properties (context, stream);
stream++;
}
/* stop probe */
gst_element_set_state (pipeline, GST_STATE_NULL);
return 0;
}