mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-18 14:26:43 +00:00
examples: encoding example
Along with gstcapslist
This commit is contained in:
parent
8a3b45aa1f
commit
a5994446b3
7 changed files with 848 additions and 2 deletions
|
@ -995,6 +995,7 @@ tests/check/Makefile
|
||||||
tests/examples/Makefile
|
tests/examples/Makefile
|
||||||
tests/examples/app/Makefile
|
tests/examples/app/Makefile
|
||||||
tests/examples/dynamic/Makefile
|
tests/examples/dynamic/Makefile
|
||||||
|
tests/examples/encoding/Makefile
|
||||||
tests/examples/gio/Makefile
|
tests/examples/gio/Makefile
|
||||||
tests/examples/overlay/Makefile
|
tests/examples/overlay/Makefile
|
||||||
tests/examples/seek/Makefile
|
tests/examples/seek/Makefile
|
||||||
|
|
|
@ -8,8 +8,8 @@ if USE_GIO
|
||||||
GIO_SUBDIRS = gio
|
GIO_SUBDIRS = gio
|
||||||
endif
|
endif
|
||||||
|
|
||||||
SUBDIRS = app dynamic $(FT2_SUBDIRS) $(GIO_SUBDIRS) overlay playrec volume v4l
|
SUBDIRS = app dynamic $(FT2_SUBDIRS) $(GIO_SUBDIRS) overlay playrec volume v4l encoding
|
||||||
|
|
||||||
DIST_SUBDIRS = app dynamic gio overlay seek snapshot playrec volume v4l
|
DIST_SUBDIRS = app dynamic gio overlay seek snapshot playrec volume v4l encoding
|
||||||
|
|
||||||
include $(top_srcdir)/common/parallel-subdirs.mak
|
include $(top_srcdir)/common/parallel-subdirs.mak
|
||||||
|
|
1
tests/examples/encoding/.gitignore
vendored
Normal file
1
tests/examples/encoding/.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
||||||
|
encoding
|
11
tests/examples/encoding/Makefile.am
Normal file
11
tests/examples/encoding/Makefile.am
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
examples = encoding
|
||||||
|
|
||||||
|
encoding_SOURCES = gstcapslist.c encoding.c
|
||||||
|
EXTRA_DIST = gstcapslist.h
|
||||||
|
|
||||||
|
noinst_PROGRAMS = $(examples)
|
||||||
|
|
||||||
|
LDADD = $(top_builddir)/gst-libs/gst/pbutils/libgstpbutils-@GST_MAJORMINOR@.la\
|
||||||
|
-lgstpbutils-@GST_MAJORMINOR@
|
||||||
|
$(GST_LIBS)
|
||||||
|
AM_CFLAGS = -I$(top_builddir)/gst-libs $(GST_PLUGINS_BASE_CFLAGS) $(GST_BASE_CFLAGS) $(GST_CFLAGS)
|
512
tests/examples/encoding/encoding.c
Normal file
512
tests/examples/encoding/encoding.c
Normal file
|
@ -0,0 +1,512 @@
|
||||||
|
/* Example application for using GstProfile and encodebin
|
||||||
|
* Copyright (C) 2009 Edward Hervey <edward.hervey@collabora.co.uk>
|
||||||
|
*
|
||||||
|
* 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 <stdlib.h>
|
||||||
|
#include <glib.h>
|
||||||
|
#include <glib/gprintf.h>
|
||||||
|
#include <gst/gst.h>
|
||||||
|
#include <gst/pbutils/pbutils.h>
|
||||||
|
#include <gst/pbutils/encoding-profile.h>
|
||||||
|
#include "gstcapslist.h"
|
||||||
|
|
||||||
|
static gboolean silent = FALSE;
|
||||||
|
|
||||||
|
static void
|
||||||
|
list_codecs (void)
|
||||||
|
{
|
||||||
|
GstCaps *l;
|
||||||
|
GstCaps *caps;
|
||||||
|
guint i, len;
|
||||||
|
|
||||||
|
caps = gst_caps_new_empty ();
|
||||||
|
|
||||||
|
g_print ("Available container formats:\n");
|
||||||
|
l = gst_caps_list_container_formats (GST_RANK_NONE);
|
||||||
|
len = gst_caps_get_size (l);
|
||||||
|
for (i = 0; i < len; i++) {
|
||||||
|
GstStructure *st = gst_caps_steal_structure (l, 0);
|
||||||
|
gchar *tmpstr, *desc;
|
||||||
|
|
||||||
|
gst_caps_append_structure (caps, st);
|
||||||
|
|
||||||
|
tmpstr = gst_caps_to_string (caps);
|
||||||
|
desc = gst_pb_utils_get_codec_description (caps);
|
||||||
|
g_print (" %s - %s\n", desc, tmpstr);
|
||||||
|
g_free (tmpstr);
|
||||||
|
if (desc)
|
||||||
|
g_free (desc);
|
||||||
|
gst_caps_remove_structure (caps, 0);
|
||||||
|
}
|
||||||
|
g_print ("\n");
|
||||||
|
gst_caps_unref (l);
|
||||||
|
|
||||||
|
g_print ("Available video codecs:\n");
|
||||||
|
l = gst_caps_list_video_encoding_formats (GST_RANK_NONE);
|
||||||
|
len = gst_caps_get_size (l);
|
||||||
|
for (i = 0; i < len; i++) {
|
||||||
|
GstStructure *st = gst_caps_steal_structure (l, 0);
|
||||||
|
gchar *tmpstr, *desc;
|
||||||
|
|
||||||
|
gst_caps_append_structure (caps, st);
|
||||||
|
|
||||||
|
tmpstr = gst_caps_to_string (caps);
|
||||||
|
desc = gst_pb_utils_get_codec_description (caps);
|
||||||
|
g_print (" %s - %s\n", desc, tmpstr);
|
||||||
|
g_free (tmpstr);
|
||||||
|
if (desc)
|
||||||
|
g_free (desc);
|
||||||
|
gst_caps_remove_structure (caps, 0);
|
||||||
|
}
|
||||||
|
g_print ("\n");
|
||||||
|
gst_caps_unref (l);
|
||||||
|
|
||||||
|
g_print ("Available audio codecs:\n");
|
||||||
|
l = gst_caps_list_audio_encoding_formats (GST_RANK_NONE);
|
||||||
|
len = gst_caps_get_size (l);
|
||||||
|
for (i = 0; i < len; i++) {
|
||||||
|
GstStructure *st = gst_caps_steal_structure (l, 0);
|
||||||
|
gchar *tmpstr, *desc;
|
||||||
|
|
||||||
|
gst_caps_append_structure (caps, st);
|
||||||
|
|
||||||
|
tmpstr = gst_caps_to_string (caps);
|
||||||
|
desc = gst_pb_utils_get_codec_description (caps);
|
||||||
|
g_print (" %s - %s\n", desc, tmpstr);
|
||||||
|
g_free (tmpstr);
|
||||||
|
if (desc)
|
||||||
|
g_free (desc);
|
||||||
|
gst_caps_remove_structure (caps, 0);
|
||||||
|
}
|
||||||
|
g_print ("\n");
|
||||||
|
gst_caps_unref (l);
|
||||||
|
|
||||||
|
gst_caps_unref (caps);
|
||||||
|
}
|
||||||
|
|
||||||
|
static gchar *
|
||||||
|
generate_filename (const GstCaps * container, const GstCaps * vcodec,
|
||||||
|
const GstCaps * acodec)
|
||||||
|
{
|
||||||
|
gchar *a, *b, *c;
|
||||||
|
gchar *res = NULL;
|
||||||
|
guint i;
|
||||||
|
|
||||||
|
a = gst_pb_utils_get_codec_description (container);
|
||||||
|
b = gst_pb_utils_get_codec_description (vcodec);
|
||||||
|
c = gst_pb_utils_get_codec_description (acodec);
|
||||||
|
|
||||||
|
if (!a)
|
||||||
|
a = g_strdup_printf ("%.10s",
|
||||||
|
g_uri_escape_string (gst_caps_to_string (container), NULL, FALSE));
|
||||||
|
if (!b)
|
||||||
|
b = g_strdup_printf ("%.10s",
|
||||||
|
g_uri_escape_string (gst_caps_to_string (vcodec), NULL, FALSE));
|
||||||
|
if (!c)
|
||||||
|
c = g_strdup_printf ("%.10s",
|
||||||
|
g_uri_escape_string (gst_caps_to_string (acodec), NULL, FALSE));
|
||||||
|
|
||||||
|
for (i = 0; i < 256 && res == NULL; i++) {
|
||||||
|
res = g_strdup_printf ("%s-%s-%s-%d.file", a, b, c, i);
|
||||||
|
if (g_file_test (res, G_FILE_TEST_EXISTS)) {
|
||||||
|
g_free (res);
|
||||||
|
res = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* Make sure file doesn't already exist */
|
||||||
|
|
||||||
|
g_free (a);
|
||||||
|
g_free (b);
|
||||||
|
g_free (c);
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
static GstEncodingProfile *
|
||||||
|
create_profile (GstCaps * cf, GstCaps * vf, GstCaps * af)
|
||||||
|
{
|
||||||
|
GstEncodingContainerProfile *cprof = NULL;
|
||||||
|
|
||||||
|
cprof =
|
||||||
|
gst_encoding_container_profile_new ((gchar *) "test-application-profile",
|
||||||
|
NULL, cf, NULL);
|
||||||
|
|
||||||
|
if (vf)
|
||||||
|
gst_encoding_container_profile_add_profile (cprof,
|
||||||
|
(GstEncodingProfile *) gst_encoding_video_profile_new (vf,
|
||||||
|
NULL, NULL, 0));
|
||||||
|
if (af)
|
||||||
|
gst_encoding_container_profile_add_profile (cprof, (GstEncodingProfile *)
|
||||||
|
gst_encoding_audio_profile_new (af, NULL, NULL, 0));
|
||||||
|
|
||||||
|
/* Let's print out some info */
|
||||||
|
if (!silent) {
|
||||||
|
gchar *desc = gst_pb_utils_get_codec_description (cf);
|
||||||
|
gchar *cd = gst_caps_to_string (cf);
|
||||||
|
g_print ("Encoding parameters\n");
|
||||||
|
g_print (" Container format : %s (%s)\n", desc, cd);
|
||||||
|
g_free (desc);
|
||||||
|
g_free (cd);
|
||||||
|
if (vf) {
|
||||||
|
desc = gst_pb_utils_get_codec_description (vf);
|
||||||
|
cd = gst_caps_to_string (vf);
|
||||||
|
g_print (" Video format : %s (%s)\n", desc, cd);
|
||||||
|
g_free (desc);
|
||||||
|
g_free (cd);
|
||||||
|
}
|
||||||
|
if (af) {
|
||||||
|
desc = gst_pb_utils_get_codec_description (af);
|
||||||
|
cd = gst_caps_to_string (af);
|
||||||
|
g_print (" Audio format : %s (%s)\n", desc, cd);
|
||||||
|
g_free (desc);
|
||||||
|
g_free (cd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (GstEncodingProfile *) cprof;
|
||||||
|
}
|
||||||
|
|
||||||
|
static GstEncodingProfile *
|
||||||
|
create_profile_from_string (gchar * format, gchar * vformat, gchar * aformat)
|
||||||
|
{
|
||||||
|
GstEncodingProfile *prof = NULL;
|
||||||
|
GstCaps *cf = NULL, *vf = NULL, *af = NULL;
|
||||||
|
|
||||||
|
if (format)
|
||||||
|
cf = gst_caps_from_string (format);
|
||||||
|
if (vformat)
|
||||||
|
vf = gst_caps_from_string (vformat);
|
||||||
|
if (aformat)
|
||||||
|
af = gst_caps_from_string (aformat);
|
||||||
|
|
||||||
|
if (G_UNLIKELY ((vformat && (vf == NULL)) || (aformat && (af == NULL))))
|
||||||
|
goto beach;
|
||||||
|
|
||||||
|
prof = create_profile (cf, vf, af);
|
||||||
|
|
||||||
|
beach:
|
||||||
|
if (cf)
|
||||||
|
gst_caps_unref (cf);
|
||||||
|
if (vf)
|
||||||
|
gst_caps_unref (vf);
|
||||||
|
if (af)
|
||||||
|
gst_caps_unref (af);
|
||||||
|
|
||||||
|
return prof;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
pad_added_cb (GstElement * uridecodebin, GstPad * pad, GstElement * encodebin)
|
||||||
|
{
|
||||||
|
GstPad *sinkpad;
|
||||||
|
|
||||||
|
sinkpad = gst_element_get_compatible_pad (encodebin, pad, NULL);
|
||||||
|
|
||||||
|
if (sinkpad == NULL) {
|
||||||
|
GstCaps *caps;
|
||||||
|
|
||||||
|
/* Ask encodebin for a compatible pad */
|
||||||
|
caps = gst_pad_get_caps (pad);
|
||||||
|
g_signal_emit_by_name (encodebin, "request-pad", caps, &sinkpad);
|
||||||
|
if (caps)
|
||||||
|
gst_caps_unref (caps);
|
||||||
|
}
|
||||||
|
if (sinkpad == NULL) {
|
||||||
|
g_print ("Couldn't get an encoding channel for pad %s:%s\n",
|
||||||
|
GST_DEBUG_PAD_NAME (pad));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (G_UNLIKELY (gst_pad_link (pad, sinkpad) != GST_PAD_LINK_OK)) {
|
||||||
|
g_print ("Couldn't link pads\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
autoplug_continue_cb (GstElement * uridecodebin, GstPad * somepad,
|
||||||
|
GstCaps * caps, GstElement * encodebin)
|
||||||
|
{
|
||||||
|
GstPad *sinkpad;
|
||||||
|
|
||||||
|
g_signal_emit_by_name (encodebin, "request-pad", caps, &sinkpad);
|
||||||
|
|
||||||
|
if (sinkpad == NULL)
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
bus_message_cb (GstBus * bus, GstMessage * message, GMainLoop * mainloop)
|
||||||
|
{
|
||||||
|
switch (GST_MESSAGE_TYPE (message)) {
|
||||||
|
case GST_MESSAGE_ERROR:
|
||||||
|
g_print ("ERROR\n");
|
||||||
|
gst_bus_set_flushing (bus, TRUE);
|
||||||
|
g_main_loop_quit (mainloop);
|
||||||
|
break;
|
||||||
|
case GST_MESSAGE_EOS:
|
||||||
|
g_print ("Done\n");
|
||||||
|
g_main_loop_quit (mainloop);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
transcode_file (gchar * uri, gchar * outputuri, GstEncodingProfile * prof)
|
||||||
|
{
|
||||||
|
GstElement *pipeline;
|
||||||
|
GstElement *src;
|
||||||
|
GstElement *ebin;
|
||||||
|
GstElement *sink;
|
||||||
|
GstBus *bus;
|
||||||
|
GstCaps *profilecaps, *rescaps;
|
||||||
|
GMainLoop *mainloop;
|
||||||
|
|
||||||
|
g_print (" Input URI : %s\n", uri);
|
||||||
|
g_print (" Output URI : %s\n", outputuri);
|
||||||
|
|
||||||
|
sink = gst_element_make_from_uri (GST_URI_SINK, outputuri, "sink");
|
||||||
|
if (G_UNLIKELY (sink == NULL)) {
|
||||||
|
g_print ("Can't create output sink, most likely invalid output URI !\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
src = gst_element_factory_make ("uridecodebin", NULL);
|
||||||
|
if (G_UNLIKELY (src == NULL)) {
|
||||||
|
g_print ("Can't create uridecodebin for input URI, aborting!\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Figure out the streams that can be passed as-is to encodebin */
|
||||||
|
g_object_get (src, "caps", &rescaps, NULL);
|
||||||
|
rescaps = gst_caps_copy (rescaps);
|
||||||
|
profilecaps = gst_encoding_profile_get_output_caps (prof);
|
||||||
|
gst_caps_append (rescaps, profilecaps);
|
||||||
|
|
||||||
|
/* Set properties */
|
||||||
|
g_object_set (src, "uri", uri, "caps", rescaps, NULL);
|
||||||
|
|
||||||
|
ebin = gst_element_factory_make ("encodebin", NULL);
|
||||||
|
g_object_set (ebin, "profile", prof, NULL);
|
||||||
|
|
||||||
|
g_signal_connect (src, "autoplug-continue", G_CALLBACK (autoplug_continue_cb),
|
||||||
|
ebin);
|
||||||
|
g_signal_connect (src, "pad-added", G_CALLBACK (pad_added_cb), ebin);
|
||||||
|
|
||||||
|
pipeline = gst_pipeline_new ("encoding-pipeline");
|
||||||
|
|
||||||
|
gst_bin_add_many (GST_BIN (pipeline), src, ebin, sink, NULL);
|
||||||
|
|
||||||
|
gst_element_link (ebin, sink);
|
||||||
|
|
||||||
|
mainloop = g_main_loop_new (NULL, FALSE);
|
||||||
|
|
||||||
|
bus = gst_pipeline_get_bus ((GstPipeline *) pipeline);
|
||||||
|
gst_bus_add_signal_watch (bus);
|
||||||
|
g_signal_connect (bus, "message", G_CALLBACK (bus_message_cb), mainloop);
|
||||||
|
|
||||||
|
if (gst_element_set_state (pipeline,
|
||||||
|
GST_STATE_PLAYING) == GST_STATE_CHANGE_FAILURE) {
|
||||||
|
g_print ("Failed to start the encoding\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_main_loop_run (mainloop);
|
||||||
|
|
||||||
|
gst_element_set_state (pipeline, GST_STATE_NULL);
|
||||||
|
gst_object_unref (pipeline);
|
||||||
|
}
|
||||||
|
|
||||||
|
static gchar *
|
||||||
|
ensure_uri (gchar * location)
|
||||||
|
{
|
||||||
|
gchar *res;
|
||||||
|
gchar *path;
|
||||||
|
|
||||||
|
if (gst_uri_is_valid (location))
|
||||||
|
return g_strdup (location);
|
||||||
|
|
||||||
|
if (!g_path_is_absolute (location)) {
|
||||||
|
gchar *cur_dir;
|
||||||
|
cur_dir = g_get_current_dir ();
|
||||||
|
path = g_build_filename (cur_dir, location, NULL);
|
||||||
|
g_free (cur_dir);
|
||||||
|
} else
|
||||||
|
path = g_strdup (location);
|
||||||
|
|
||||||
|
res = g_filename_to_uri (path, NULL, NULL);
|
||||||
|
g_free (path);
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
main (int argc, char **argv)
|
||||||
|
{
|
||||||
|
GError *err = NULL;
|
||||||
|
gchar *outputuri = NULL;
|
||||||
|
gchar *format = NULL;
|
||||||
|
gchar *aformat = NULL;
|
||||||
|
gchar *vformat = NULL;
|
||||||
|
gboolean allmissing = FALSE;
|
||||||
|
gboolean listcodecs = FALSE;
|
||||||
|
GOptionEntry options[] = {
|
||||||
|
{"silent", 's', 0, G_OPTION_ARG_NONE, &silent,
|
||||||
|
"Don't output the information structure", NULL},
|
||||||
|
{"outputuri", 'o', 0, G_OPTION_ARG_STRING, &outputuri,
|
||||||
|
"URI to encode to", "URI (<protocol>://<location>)"},
|
||||||
|
{"format", 'f', 0, G_OPTION_ARG_STRING, &format,
|
||||||
|
"Container format", "<GstCaps>"},
|
||||||
|
{"vformat", 'v', 0, G_OPTION_ARG_STRING, &vformat,
|
||||||
|
"Video format", "<GstCaps>"},
|
||||||
|
{"aformat", 'a', 0, G_OPTION_ARG_STRING, &aformat,
|
||||||
|
"Audio format", "<GstCaps>"},
|
||||||
|
{"allmissing", 'm', 0, G_OPTION_ARG_NONE, &allmissing,
|
||||||
|
"encode to all matching format/codec that aren't specified", NULL},
|
||||||
|
{"list-codecs", 'l', 0, G_OPTION_ARG_NONE, &listcodecs,
|
||||||
|
"list all available codecs and container formats", NULL},
|
||||||
|
{NULL}
|
||||||
|
};
|
||||||
|
GOptionContext *ctx;
|
||||||
|
GstEncodingProfile *prof;
|
||||||
|
gchar *inputuri;
|
||||||
|
|
||||||
|
if (!g_thread_supported ())
|
||||||
|
g_thread_init (NULL);
|
||||||
|
|
||||||
|
ctx = g_option_context_new ("- encode URIs with GstProfile and encodebin");
|
||||||
|
g_option_context_add_main_entries (ctx, options, NULL);
|
||||||
|
g_option_context_add_group (ctx, gst_init_get_option_group ());
|
||||||
|
|
||||||
|
if (!g_option_context_parse (ctx, &argc, &argv, &err)) {
|
||||||
|
g_print ("Error initializing: %s\n", err->message);
|
||||||
|
exit (1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (listcodecs) {
|
||||||
|
list_codecs ();
|
||||||
|
g_option_context_free (ctx);
|
||||||
|
exit (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (outputuri == NULL || argc != 2) {
|
||||||
|
g_print ("%s", g_option_context_get_help (ctx, TRUE, NULL));
|
||||||
|
g_option_context_free (ctx);
|
||||||
|
exit (-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
g_option_context_free (ctx);
|
||||||
|
|
||||||
|
/* Fixup outputuri to be a URI */
|
||||||
|
inputuri = ensure_uri (argv[1]);
|
||||||
|
outputuri = ensure_uri (outputuri);
|
||||||
|
|
||||||
|
if (allmissing) {
|
||||||
|
GList *muxers;
|
||||||
|
GstCaps *formats = NULL;
|
||||||
|
GstCaps *vformats = NULL;
|
||||||
|
GstCaps *aformats = NULL;
|
||||||
|
guint f, v, a, flen, vlen, alen;
|
||||||
|
|
||||||
|
if (!format)
|
||||||
|
formats = gst_caps_list_container_formats (GST_RANK_NONE);
|
||||||
|
else
|
||||||
|
formats = gst_caps_from_string (format);
|
||||||
|
|
||||||
|
if (!vformat)
|
||||||
|
vformats = gst_caps_list_video_encoding_formats (GST_RANK_NONE);
|
||||||
|
else
|
||||||
|
vformats = gst_caps_from_string (vformat);
|
||||||
|
|
||||||
|
if (!aformat)
|
||||||
|
aformats = gst_caps_list_audio_encoding_formats (GST_RANK_NONE);
|
||||||
|
else
|
||||||
|
aformats = gst_caps_from_string (aformat);
|
||||||
|
muxers =
|
||||||
|
gst_element_factory_list_get_elements (GST_ELEMENT_FACTORY_TYPE_MUXER,
|
||||||
|
GST_RANK_NONE);
|
||||||
|
|
||||||
|
flen = gst_caps_get_size (formats);
|
||||||
|
|
||||||
|
for (f = 0; f < flen; f++) {
|
||||||
|
GstCaps *container =
|
||||||
|
gst_caps_new_full (gst_caps_steal_structure (formats, 0), NULL);
|
||||||
|
GstCaps *compatv =
|
||||||
|
gst_caps_list_compatible_codecs (container, vformats, muxers);
|
||||||
|
GstCaps *compata =
|
||||||
|
gst_caps_list_compatible_codecs (container, aformats, muxers);
|
||||||
|
|
||||||
|
vlen = gst_caps_get_size (compatv);
|
||||||
|
alen = gst_caps_get_size (compata);
|
||||||
|
|
||||||
|
|
||||||
|
for (v = 0; v < vlen; v++) {
|
||||||
|
GstCaps *vcodec =
|
||||||
|
gst_caps_new_full (gst_structure_copy (gst_caps_get_structure
|
||||||
|
(compatv, v)), NULL);
|
||||||
|
for (a = 0; a < alen; a++) {
|
||||||
|
GstCaps *acodec =
|
||||||
|
gst_caps_new_full (gst_structure_copy (gst_caps_get_structure
|
||||||
|
(compata, a)), NULL);
|
||||||
|
|
||||||
|
prof =
|
||||||
|
create_profile ((GstCaps *) container, (GstCaps *) vcodec,
|
||||||
|
(GstCaps *) acodec);
|
||||||
|
if (G_UNLIKELY (prof == NULL)) {
|
||||||
|
g_print ("Wrong arguments\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
outputuri =
|
||||||
|
ensure_uri (generate_filename (container, vcodec, acodec));
|
||||||
|
transcode_file (inputuri, outputuri, prof);
|
||||||
|
gst_encoding_profile_unref (prof);
|
||||||
|
|
||||||
|
gst_caps_unref (acodec);
|
||||||
|
}
|
||||||
|
gst_caps_unref (vcodec);
|
||||||
|
}
|
||||||
|
gst_caps_unref (container);
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
/* Create the profile */
|
||||||
|
prof = create_profile_from_string (format, vformat, aformat);
|
||||||
|
if (G_UNLIKELY (prof == NULL)) {
|
||||||
|
g_print ("Encoding arguments are not valid !\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Trancode file */
|
||||||
|
transcode_file (inputuri, outputuri, prof);
|
||||||
|
|
||||||
|
/* cleanup */
|
||||||
|
gst_encoding_profile_unref (prof);
|
||||||
|
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
286
tests/examples/encoding/gstcapslist.c
Normal file
286
tests/examples/encoding/gstcapslist.c
Normal file
|
@ -0,0 +1,286 @@
|
||||||
|
/* GStreamer
|
||||||
|
* Copyright (C) <2010> Edward Hervey <edward.hervey@collabora.co.uk>
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "gstcapslist.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Caps listing convenience functions
|
||||||
|
*/
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
remove_range_foreach (GQuark field_id, const GValue * value, GstStructure * st)
|
||||||
|
{
|
||||||
|
GType ftype = G_VALUE_TYPE (value);
|
||||||
|
const gchar *fname;
|
||||||
|
|
||||||
|
if (ftype == GST_TYPE_INT_RANGE || ftype == GST_TYPE_DOUBLE_RANGE ||
|
||||||
|
ftype == GST_TYPE_FRACTION_RANGE) {
|
||||||
|
gst_structure_remove_field (st, g_quark_to_string (field_id));
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
fname = g_quark_to_string (field_id);
|
||||||
|
|
||||||
|
/* if (strstr (fname, "framerate") || strstr (fname, "pixel-aspect-ratio") || */
|
||||||
|
/* strstr (fname, "rate")) { */
|
||||||
|
/* gst_structure_remove_field (st, g_quark_to_string (field_id)); */
|
||||||
|
/* return FALSE; */
|
||||||
|
/* } */
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
clear_caps (GstCaps * caps, GstCaps * rescaps)
|
||||||
|
{
|
||||||
|
GstCaps *res;
|
||||||
|
GstStructure *st;
|
||||||
|
guint i;
|
||||||
|
|
||||||
|
res = gst_caps_make_writable (caps);
|
||||||
|
|
||||||
|
GST_DEBUG ("incoming caps %" GST_PTR_FORMAT, res);
|
||||||
|
|
||||||
|
/* Remove width/height/framerate/depth/width fields */
|
||||||
|
for (i = gst_caps_get_size (res); i; i--) {
|
||||||
|
st = gst_caps_get_structure (res, i - 1);
|
||||||
|
|
||||||
|
/* Remove range fields */
|
||||||
|
while (!gst_structure_foreach (st,
|
||||||
|
(GstStructureForeachFunc) remove_range_foreach, st));
|
||||||
|
}
|
||||||
|
|
||||||
|
GST_DEBUG ("stripped %" GST_PTR_FORMAT, res);
|
||||||
|
|
||||||
|
/* And append to list without duplicates */
|
||||||
|
while ((st = gst_caps_steal_structure (res, 0))) {
|
||||||
|
/* Skip fake codecs/containers */
|
||||||
|
if (gst_structure_has_name (st, "audio/x-raw-int") ||
|
||||||
|
gst_structure_has_name (st, "audio/x-raw-float") ||
|
||||||
|
gst_structure_has_name (st, "video/x-raw-yuv") ||
|
||||||
|
gst_structure_has_name (st, "video/x-raw-rgb") ||
|
||||||
|
gst_structure_has_name (st, "unknown/unknown")) {
|
||||||
|
gst_structure_free (st);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
gst_caps_append_structure (rescaps, st);
|
||||||
|
}
|
||||||
|
|
||||||
|
gst_caps_unref (res);
|
||||||
|
}
|
||||||
|
|
||||||
|
static GstCaps *
|
||||||
|
get_all_caps (GList * elements, GstPadDirection direction)
|
||||||
|
{
|
||||||
|
GstCaps *res = NULL, *res2;
|
||||||
|
GList *tmp;
|
||||||
|
|
||||||
|
res = gst_caps_new_empty ();
|
||||||
|
|
||||||
|
for (tmp = elements; tmp; tmp = tmp->next) {
|
||||||
|
GstElementFactory *factory = (GstElementFactory *) tmp->data;
|
||||||
|
const GList *templates;
|
||||||
|
GList *walk;
|
||||||
|
|
||||||
|
templates = gst_element_factory_get_static_pad_templates (factory);
|
||||||
|
for (walk = (GList *) templates; walk; walk = g_list_next (walk)) {
|
||||||
|
GstStaticPadTemplate *templ = walk->data;
|
||||||
|
if (templ->direction == direction)
|
||||||
|
clear_caps (gst_static_caps_get (&templ->static_caps), res);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
res2 = gst_caps_normalize (res);
|
||||||
|
gst_caps_unref (res);
|
||||||
|
return res2;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gst_caps_list_container_formats:
|
||||||
|
* @minrank: The minimum #GstRank
|
||||||
|
*
|
||||||
|
* Returns a #GstCaps corresponding to all the container formats
|
||||||
|
* one can mux to on this system.
|
||||||
|
*
|
||||||
|
* Returns: A #GstCaps. Unref with %gst_caps_unref when done with it.
|
||||||
|
*/
|
||||||
|
GstCaps *
|
||||||
|
gst_caps_list_container_formats (GstRank minrank)
|
||||||
|
{
|
||||||
|
GstCaps *res;
|
||||||
|
GList *muxers;
|
||||||
|
|
||||||
|
muxers =
|
||||||
|
gst_element_factory_list_get_elements (GST_ELEMENT_FACTORY_TYPE_MUXER,
|
||||||
|
minrank);
|
||||||
|
res = get_all_caps (muxers, GST_PAD_SRC);
|
||||||
|
gst_plugin_feature_list_free (muxers);
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
static GstCaps *
|
||||||
|
gst_caps_list_encoding_formats (GstRank minrank)
|
||||||
|
{
|
||||||
|
GstCaps *res;
|
||||||
|
GList *encoders;
|
||||||
|
|
||||||
|
encoders =
|
||||||
|
gst_element_factory_list_get_elements (GST_ELEMENT_FACTORY_TYPE_ENCODER,
|
||||||
|
minrank);
|
||||||
|
res = get_all_caps (encoders, GST_PAD_SRC);
|
||||||
|
gst_plugin_feature_list_free (encoders);
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gst_caps_list_video_encoding_formats:
|
||||||
|
* @minrank: The minimum #GstRank
|
||||||
|
*
|
||||||
|
* Returns a #GstCaps corresponding to all the video or image formats one
|
||||||
|
* can encode to on this system.
|
||||||
|
*
|
||||||
|
* Returns: A #GstCaps. Unref with %gst_caps_unref when done with it.
|
||||||
|
*/
|
||||||
|
GstCaps *
|
||||||
|
gst_caps_list_video_encoding_formats (GstRank minrank)
|
||||||
|
{
|
||||||
|
GstCaps *res;
|
||||||
|
GList *encoders;
|
||||||
|
|
||||||
|
encoders =
|
||||||
|
gst_element_factory_list_get_elements
|
||||||
|
(GST_ELEMENT_FACTORY_TYPE_VIDEO_ENCODER, minrank);
|
||||||
|
res = get_all_caps (encoders, GST_PAD_SRC);
|
||||||
|
gst_plugin_feature_list_free (encoders);
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gst_caps_list_audio_encoding_formats:
|
||||||
|
* @minrank: The minimum #GstRank
|
||||||
|
*
|
||||||
|
* Returns a #GstCaps corresponding to all the audio formats one
|
||||||
|
* can encode to on this system.
|
||||||
|
*
|
||||||
|
* Returns: A #GstCaps. Unref with %gst_caps_unref when done with it.
|
||||||
|
*/
|
||||||
|
GstCaps *
|
||||||
|
gst_caps_list_audio_encoding_formats (GstRank minrank)
|
||||||
|
{
|
||||||
|
GstCaps *res;
|
||||||
|
GList *encoders;
|
||||||
|
|
||||||
|
encoders =
|
||||||
|
gst_element_factory_list_get_elements
|
||||||
|
(GST_ELEMENT_FACTORY_TYPE_AUDIO_ENCODER, minrank);
|
||||||
|
res = get_all_caps (encoders, GST_PAD_SRC);
|
||||||
|
gst_plugin_feature_list_free (encoders);
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gst_caps_list_compatible_codecs:
|
||||||
|
* @containerformat: A #GstCaps corresponding to a container format
|
||||||
|
* @codecformats: An optional #GstCaps of codec formats
|
||||||
|
* @muxers: An optional #GList of muxer #GstElementFactory.
|
||||||
|
*
|
||||||
|
* Returns an array of #GstCaps corresponding to the audio/video/text formats
|
||||||
|
* one can encode to and that can be muxed in the provided @containerformat.
|
||||||
|
*
|
||||||
|
* If specified, only the #GstCaps contained in @codecformats will be checked
|
||||||
|
* against, else all compatible audio/video formats will be returned.
|
||||||
|
*
|
||||||
|
* If specified, only the #GstElementFactory contained in @muxers will be checked,
|
||||||
|
* else all available muxers on the system will be checked.
|
||||||
|
*
|
||||||
|
* Returns: A #GstCaps containing all compatible formats. Unref with %gst_caps_unref
|
||||||
|
* when done.
|
||||||
|
*/
|
||||||
|
GstCaps *
|
||||||
|
gst_caps_list_compatible_codecs (const GstCaps * containerformat,
|
||||||
|
GstCaps * codecformats, GList * muxers)
|
||||||
|
{
|
||||||
|
const GList *templates;
|
||||||
|
GstElementFactory *factory;
|
||||||
|
GList *walk;
|
||||||
|
GstCaps *res = NULL;
|
||||||
|
GstCaps *tmpcaps;
|
||||||
|
GList *tmp;
|
||||||
|
gboolean hadmuxers = (muxers != NULL);
|
||||||
|
gboolean hadcodecs = (codecformats != NULL);
|
||||||
|
|
||||||
|
GST_DEBUG ("containerformat: %" GST_PTR_FORMAT, containerformat);
|
||||||
|
GST_DEBUG ("codecformats: %" GST_PTR_FORMAT, codecformats);
|
||||||
|
|
||||||
|
if (!hadmuxers)
|
||||||
|
muxers =
|
||||||
|
gst_element_factory_list_get_elements (GST_ELEMENT_FACTORY_TYPE_MUXER,
|
||||||
|
GST_RANK_NONE);
|
||||||
|
if (!hadcodecs)
|
||||||
|
codecformats = gst_caps_list_encoding_formats (GST_RANK_NONE);
|
||||||
|
|
||||||
|
/* Get the highest rank muxer matching containerformat */
|
||||||
|
tmp =
|
||||||
|
gst_element_factory_list_filter (muxers, containerformat, GST_PAD_SRC,
|
||||||
|
TRUE);
|
||||||
|
if (G_UNLIKELY (tmp == NULL))
|
||||||
|
goto beach;
|
||||||
|
|
||||||
|
factory = (GstElementFactory *) tmp->data;
|
||||||
|
|
||||||
|
GST_DEBUG ("Trying with factory %s",
|
||||||
|
gst_element_factory_get_longname (factory));
|
||||||
|
|
||||||
|
/* Match all muxer sink pad templates against the available codec formats */
|
||||||
|
templates = gst_element_factory_get_static_pad_templates (factory);
|
||||||
|
gst_plugin_feature_list_free (tmp);
|
||||||
|
|
||||||
|
tmpcaps = gst_caps_new_empty ();
|
||||||
|
|
||||||
|
for (walk = (GList *) templates; walk; walk = walk->next) {
|
||||||
|
GstStaticPadTemplate *templ = walk->data;
|
||||||
|
|
||||||
|
if (templ->direction == GST_PAD_SINK) {
|
||||||
|
GstCaps *templ_caps;
|
||||||
|
|
||||||
|
templ_caps = gst_static_caps_get (&templ->static_caps);
|
||||||
|
gst_caps_append (tmpcaps, gst_caps_copy (templ_caps));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
res = gst_caps_intersect (tmpcaps, codecformats);
|
||||||
|
gst_caps_unref (tmpcaps);
|
||||||
|
|
||||||
|
beach:
|
||||||
|
if (!hadmuxers)
|
||||||
|
gst_plugin_feature_list_free (muxers);
|
||||||
|
if (!hadcodecs)
|
||||||
|
gst_caps_unref (codecformats);
|
||||||
|
|
||||||
|
tmpcaps = gst_caps_normalize (res);
|
||||||
|
gst_caps_unref (res);
|
||||||
|
|
||||||
|
return tmpcaps;
|
||||||
|
}
|
35
tests/examples/encoding/gstcapslist.h
Normal file
35
tests/examples/encoding/gstcapslist.h
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
/* GStreamer
|
||||||
|
* Copyright (C) <2010> Edward Hervey <edward.hervey@collabora.co.uk>
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <gst/gst.h>
|
||||||
|
|
||||||
|
GstCaps *gst_caps_list_compatible_codecs (const GstCaps *containerformat,
|
||||||
|
GstCaps *codecformats,
|
||||||
|
GList *muxers);
|
||||||
|
|
||||||
|
GstCaps *gst_caps_list_compatible_containers (GstCaps *mediaformat,
|
||||||
|
GList *containerformats);
|
||||||
|
|
||||||
|
|
||||||
|
GstCaps *gst_caps_list_container_formats (GstRank minrank);
|
||||||
|
|
||||||
|
GstCaps *gst_caps_list_video_encoding_formats (GstRank minrank);
|
||||||
|
|
||||||
|
GstCaps *gst_caps_list_audio_encoding_formats (GstRank minrank);
|
||||||
|
|
Loading…
Reference in a new issue