diff options
Diffstat (limited to 'libjuicer/rb-gst-media-types.c')
-rw-r--r-- | libjuicer/rb-gst-media-types.c | 336 |
1 files changed, 336 insertions, 0 deletions
diff --git a/libjuicer/rb-gst-media-types.c b/libjuicer/rb-gst-media-types.c new file mode 100644 index 0000000..e87b013 --- /dev/null +++ b/libjuicer/rb-gst-media-types.c @@ -0,0 +1,336 @@ +/* + * Copyright (C) 2010 Jonathan Matthew <jonathan@d14n.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * The Rhythmbox authors hereby grant permission for non-GPL compatible + * GStreamer plugins to be used and distributed together with GStreamer + * and Rhythmbox. This permission is above and beyond the permissions granted + * by the GPL license by which Rhythmbox is covered. If you modify this code + * you may extend this exception to your version of the code, but you are not + * obligated to do so. If you do not wish to do so, delete this exception + * statement from your version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + */ + +#include "config.h" + +#include <memory.h> + +#include <gst/pbutils/encoding-target.h> +#include <gst/pbutils/missing-plugins.h> + +#include "rb-gst-media-types.h" + +#define SOURCE_ENCODING_TARGET_FILE "../data/rhythmbox.gep" +#define INSTALLED_ENCODING_TARGET_FILE DATADIR"/sound-juicer/rhythmbox.gep" +static GstEncodingTarget *default_target = NULL; + +char * +rb_gst_caps_to_media_type (const GstCaps *caps) +{ + GstStructure *s; + const char *media_type; + + /* the aim here is to reduce the caps to a single mimetype-like + * string, describing the audio encoding (for audio files) or the + * file type (for everything else). raw media types are ignored. + * + * there are only a couple of special cases. + */ + + if (gst_caps_get_size (caps) == 0) + return NULL; + + s = gst_caps_get_structure (caps, 0); + media_type = gst_structure_get_name (s); + if (media_type == NULL) { + return NULL; + } else if (g_str_has_prefix (media_type, "audio/x-raw-") || + g_str_has_prefix (media_type, "video/x-raw-")) { + /* ignore raw types */ + return NULL; + } else if (g_str_equal (media_type, "audio/mpeg")) { + /* need to distinguish between mpeg 1 layer 3 and + * mpeg 2 or 4 here. + */ + int mpegversion = 0; + gst_structure_get_int (s, "mpegversion", &mpegversion); + switch (mpegversion) { + case 2: + case 4: + return g_strdup ("audio/x-aac"); /* hmm. */ + + case 1: + default: + return g_strdup ("audio/mpeg"); + } + } else { + /* everything else is fine as-is */ + return g_strdup (media_type); + } +} + +GstCaps * +rb_gst_media_type_to_caps (const char *media_type) +{ + /* special cases: */ + if (strcmp (media_type, "audio/mpeg") == 0) { + return gst_caps_from_string ("audio/mpeg, mpegversion=(int)1"); + } else if (strcmp (media_type, "audio/x-aac") == 0) { + return gst_caps_from_string ("audio/mpeg, mpegversion=(int){ 2, 4 }"); + } else { + /* otherwise, the media type is enough */ + return gst_caps_from_string (media_type); + } +} + +const char * +rb_gst_media_type_to_extension (const char *media_type) +{ + if (media_type == NULL) { + return NULL; + } else if (!strcmp (media_type, "audio/mpeg")) { + return "mp3"; + } else if (!strcmp (media_type, "audio/x-vorbis") || !strcmp (media_type, "application/ogg")) { + return "ogg"; + } else if (!strcmp (media_type, "audio/x-flac") || !strcmp (media_type, "audio/flac")) { + return "flac"; + } else if (!strcmp (media_type, "audio/x-aac") || !strcmp (media_type, "audio/aac") || !strcmp (media_type, "audio/x-alac")) { + return "m4a"; + } else if (!strcmp (media_type, "audio/x-wavpack")) { + return "wv"; + } else { + return NULL; + } +} + +const char * +rb_gst_mime_type_to_media_type (const char *mime_type) +{ + if (!strcmp (mime_type, "application/x-id3") || !strcmp (mime_type, "audio/mpeg")) { + return "audio/mpeg"; + } else if (!strcmp (mime_type, "application/ogg") || !strcmp (mime_type, "audio/x-vorbis")) { + return "audio/x-vorbis"; + } else if (!strcmp (mime_type, "audio/flac")) { + return "audio/x-flac"; + } else if (!strcmp (mime_type, "audio/aac") || !strcmp (mime_type, "audio/mp4") || !strcmp (mime_type, "audio/m4a")) { + return "audio/x-aac"; + } + return mime_type; +} + +const char * +rb_gst_media_type_to_mime_type (const char *media_type) +{ + if (!strcmp (media_type, "audio/x-vorbis")) { + return "application/ogg"; + } else if (!strcmp (media_type, "audio/x-flac")) { + return "audio/flac"; + } else if (!strcmp (media_type, "audio/x-aac")) { + return "audio/mp4"; /* probably */ + } else { + return media_type; + } +} + +gboolean +rb_gst_media_type_matches_profile (GstEncodingProfile *profile, const char *media_type) +{ + const GstCaps *pcaps; + const GList *cl; + GstCaps *caps; + gboolean matches = FALSE; + + caps = rb_gst_media_type_to_caps (media_type); + if (caps == NULL) { + return FALSE; + } + + pcaps = gst_encoding_profile_get_format (profile); + if (gst_caps_can_intersect (caps, pcaps)) { + matches = TRUE; + } + + if (matches == FALSE && GST_IS_ENCODING_CONTAINER_PROFILE (profile)) { + for (cl = gst_encoding_container_profile_get_profiles (GST_ENCODING_CONTAINER_PROFILE (profile)); cl != NULL; cl = cl->next) { + GstEncodingProfile *cp = cl->data; + pcaps = gst_encoding_profile_get_format (cp); + if (gst_caps_can_intersect (caps, pcaps)) { + matches = TRUE; + break; + } + } + } + return matches; +} + +char * +rb_gst_encoding_profile_get_media_type (GstEncodingProfile *profile) +{ + if (GST_IS_ENCODING_CONTAINER_PROFILE (profile)) { + const GList *cl = gst_encoding_container_profile_get_profiles (GST_ENCODING_CONTAINER_PROFILE (profile)); + for (; cl != NULL; cl = cl->next) { + GstEncodingProfile *p = cl->data; + if (GST_IS_ENCODING_AUDIO_PROFILE (p)) { + return rb_gst_caps_to_media_type (gst_encoding_profile_get_format (p)); + } + + } + + /* now what? */ + return NULL; + } else { + return rb_gst_caps_to_media_type (gst_encoding_profile_get_format (profile)); + } +} + +GstEncodingTarget * +rb_gst_get_default_encoding_target () +{ + if (default_target == NULL) { + char *target_file; + GError *error = NULL; + + if (g_file_test (SOURCE_ENCODING_TARGET_FILE, + G_FILE_TEST_EXISTS) != FALSE) { + target_file = SOURCE_ENCODING_TARGET_FILE; + } else { + target_file = INSTALLED_ENCODING_TARGET_FILE; + } + + default_target = gst_encoding_target_load_from_file (target_file, &error); + if (default_target == NULL) { + g_warning ("Unable to load encoding profiles from %s: %s", target_file, error ? error->message : "no error"); + g_clear_error (&error); + return NULL; + } + } + + return default_target; +} + +GstEncodingProfile * +rb_gst_get_encoding_profile (const char *media_type) +{ + const GList *l; + GstEncodingTarget *target; + target = rb_gst_get_default_encoding_target (); + + for (l = gst_encoding_target_get_profiles (target); l != NULL; l = l->next) { + GstEncodingProfile *profile = l->data; + if (rb_gst_media_type_matches_profile (profile, media_type)) { + gst_encoding_profile_ref (profile); + return profile; + } + } + + return NULL; +} + +gboolean +rb_gst_media_type_is_lossless (const char *media_type) +{ + int i; + const char *lossless_types[] = { + "audio/x-flac", + "audio/x-alac", + "audio/x-shorten", + "audio/x-wavpack" /* not completely sure */ + }; + + for (i = 0; i < G_N_ELEMENTS (lossless_types); i++) { + if (strcmp (media_type, lossless_types[i]) == 0) { + return TRUE; + } + } + return FALSE; +} + +gboolean +rb_gst_check_missing_plugins (GstEncodingProfile *profile, + char ***details, + char ***descriptions) +{ + GstElement *encodebin; + GstBus *bus; + GstPad *pad; + gboolean ret; + + ret = FALSE; + + encodebin = gst_element_factory_make ("encodebin", NULL); + if (encodebin == NULL) { + g_warning ("Unable to create encodebin"); + return TRUE; + } + + bus = gst_bus_new (); + gst_element_set_bus (encodebin, bus); + gst_bus_set_flushing (bus, FALSE); /* necessary? */ + + g_object_set (encodebin, "profile", profile, NULL); + pad = gst_element_get_static_pad (encodebin, "audio_0"); + if (pad == NULL) { + GstMessage *message; + GList *messages = NULL; + GList *m; + int i; + + message = gst_bus_pop (bus); + while (message != NULL) { + if (gst_is_missing_plugin_message (message)) { + messages = g_list_append (messages, message); + } else { + gst_message_unref (message); + } + message = gst_bus_pop (bus); + } + + if (messages != NULL) { + if (details != NULL) { + *details = g_new0(char *, g_list_length (messages)+1); + } + if (descriptions != NULL) { + *descriptions = g_new0(char *, g_list_length (messages)+1); + } + i = 0; + for (m = messages; m != NULL; m = m->next) { + char *str; + if (details != NULL) { + str = gst_missing_plugin_message_get_installer_detail (m->data); + (*details)[i] = str; + } + if (descriptions != NULL) { + str = gst_missing_plugin_message_get_description (m->data); + (*descriptions)[i] = str; + } + i++; + } + + ret = TRUE; + g_list_foreach (messages, (GFunc)gst_message_unref, NULL); + g_list_free (messages); + } + + } else { + gst_element_release_request_pad (encodebin, pad); + gst_object_unref (pad); + } + + gst_object_unref (encodebin); + gst_object_unref (bus); + return ret; +} |