diff options
author | Regis Merlino <regis.merlino@intel.com> | 2013-03-07 10:58:13 +0100 |
---|---|---|
committer | Regis Merlino <regis.merlino@intel.com> | 2013-03-18 16:12:22 +0100 |
commit | 84c824f8f5bd5852ba52686e4ad81351d2c52bc0 (patch) | |
tree | 4a43d8df34039a7d1572fa46c85fc8be5683eb6b /libgupnp-dlna/gupnp-dlna-profiles.c | |
parent | e7ff72861ea768fe40f0ed522b15e68e79bbb1e3 (diff) | |
download | GUPnP-DLNA-84c824f8f5bd5852ba52686e4ad81351d2c52bc0.tar.gz GUPnP-DLNA-84c824f8f5bd5852ba52686e4ad81351d2c52bc0.tar.bz2 GUPnP-DLNA-84c824f8f5bd5852ba52686e4ad81351d2c52bc0.zip |
Updated GUPnP-DLNA version to 0.10.0 (a245d94)
Diffstat (limited to 'libgupnp-dlna/gupnp-dlna-profiles.c')
-rw-r--r-- | libgupnp-dlna/gupnp-dlna-profiles.c | 545 |
1 files changed, 0 insertions, 545 deletions
diff --git a/libgupnp-dlna/gupnp-dlna-profiles.c b/libgupnp-dlna/gupnp-dlna-profiles.c deleted file mode 100644 index 4207b58..0000000 --- a/libgupnp-dlna/gupnp-dlna-profiles.c +++ /dev/null @@ -1,545 +0,0 @@ -/* - * Copyright (C) 2010 Nokia Corporation. - * - * Authors: Arun Raghavan <arun.raghavan@collabora.co.uk> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser 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 <glib.h> -#include <gst/pbutils/pbutils.h> -#include "gupnp-dlna-discoverer.h" -#include "gupnp-dlna-profile.h" - -/* - * This file provides the infrastructure to load DLNA profiles and the - * corresponding restrictions from an on-disk representation, and use them to - * map a given stream to its DLNA profile, if possible. - * - * Each DLNA profile is represented as a GstEncodingProfile (there might be - * exceptions where a single DLNA profile is represented by multiple - * GstEncodingProfiles - right now that's only LPCM). - * - * For a GstEncodingProfile "profile", the following fields will be populated: - * - * profile.name = "<DLNA Profile Name>" - * profile.format = Muxing format caps (with restrictions) if specified, - * else GST_CAPS_NONE - * profile.encodingprofiles = GList of GstStreamEncodingProfiles - * - * For each stream of the given profile, "profile.encodingprofiles" will have - * a GstEncodingProfile representing the restrictions for that stream (for a - * video format there will be one audio and one video stream, for example). - * - * enc_profile.type = GST_ENCODING_PROFILE_{AUDIO,VIDEO,...} (UNKNOWN for - * container restrictions) - * enc_profile.format = GstCaps with all the restrictions for this format - * enc_profile.restriction = GST_CAPS_ANY - * - * We assume that all DLNA profiles have exactly one audio stream, or one audio - * stream and one video stream. - * - * Things yet to account for: - * - * 1. Multiple audio/video streams (we need to pick the "main" one - how? - * Possibly get information from the demuxer.) - * - * 2. How do we handle discovered metadata which is in tags, but not in caps? - * Could potentially move it to caps in a post-discovery, pre-guessing - * phase - */ - -/* New profile guessing API */ - -#define GUPNP_DLNA_DEBUG_ENV "GUPNP_DLNA_DEBUG" - -#define gupnp_dlna_debug(args...) \ -do { \ - const gchar *_e = g_getenv (GUPNP_DLNA_DEBUG_ENV); \ - if (_e && !g_str_equal (_e, "0")) \ - g_debug (args); \ -} while (0) - -static gboolean -is_video_profile (const GstEncodingProfile *profile) -{ - const GList *i, *profiles_list; - - if (GST_IS_ENCODING_CONTAINER_PROFILE (profile)) { - profiles_list = gst_encoding_container_profile_get_profiles - (GST_ENCODING_CONTAINER_PROFILE (profile)); - - for (i = profiles_list ; i; i = i->next) - if (GST_IS_ENCODING_VIDEO_PROFILE (i->data)) - return TRUE; - } - - return FALSE; -} - -static gboolean -structure_can_intersect (const GstStructure *st1, const GstStructure *st2) -{ - /* Since there is no API to intersect GstStructures, we cheat (thanks - * for the idea, tpm!) and make caps from the structuresa */ - - GstCaps *caps1, *caps2; - gboolean ret; - - caps1 = gst_caps_new_full (gst_structure_copy (st1), NULL); - caps2 = gst_caps_new_full (gst_structure_copy (st2), NULL); - - ret = gst_caps_can_intersect (caps1, caps2); - - gst_caps_unref (caps1); - gst_caps_unref (caps2); - - return ret; -} - -static gboolean -structure_is_subset (const GstStructure *st1, const GstStructure *st2) -{ - int i; - - for (i = 0; i < gst_structure_n_fields (st2); i++) { - const gchar *name = gst_structure_nth_field_name (st2, i); - - if (!gst_structure_has_field(st1, name)) { - gupnp_dlna_debug (" missing field %s", name); - return FALSE; - } - } - - return TRUE; -} - -/* - * Returns TRUE if stream_caps and profile_caps can intersect, and the - * intersecting structure from profile_caps is a subset of stream_caps. Put - * simply, the condition being met is that stream_caps intersects with - * profile_caps, and that intersection includes *all* fields specified by - * profile_caps (viz. all the fields specified by the DLNA profile's - * restrictions) - */ -static gboolean -caps_can_intersect_and_is_subset (GstCaps *stream_caps, - const GstCaps *profile_caps) -{ - int i; - GstStructure *stream_st, *profile_st; - - stream_st = gst_caps_get_structure (stream_caps, 0); - - for (i = 0; i < gst_caps_get_size (profile_caps); i++) { - profile_st = gst_caps_get_structure (profile_caps, i); - - if (structure_can_intersect (stream_st, profile_st) && - structure_is_subset (stream_st, profile_st)) - return TRUE; - } - - return FALSE; -} - -static gboolean -match_profile (GstEncodingProfile *profile, - GstCaps *caps, - GType type) -{ - const GList *i, *profiles_list; - const gchar *name; - - /* Profiles with an empty name are used only for inheritance and should - * not be matched against. */ - name = gst_encoding_profile_get_name (profile); - if (name[0] == '\0') - return FALSE; - - profiles_list = gst_encoding_container_profile_get_profiles - (GST_ENCODING_CONTAINER_PROFILE (profile)); - - for (i = profiles_list; i; i = i->next){ - GstEncodingProfile *enc_profile = GST_ENCODING_PROFILE - (i->data); - const GstCaps *format = gst_encoding_profile_get_format - (enc_profile); - - if (type == G_TYPE_FROM_INSTANCE (enc_profile) && - caps_can_intersect_and_is_subset (caps, format)) - return TRUE; - } - - return FALSE; -} - -static gboolean -check_container (GstDiscovererInfo *info, - GstEncodingProfile *profile) -{ - GstDiscovererStreamInfo *stream_info; - GType stream_type; - GstCaps *stream_caps; - gboolean ret = FALSE; - - const GstCaps *profile_caps = gst_encoding_profile_get_format (profile); - - /* Top-level GstStreamInformation in the topology will be - * the container */ - stream_info = gst_discoverer_info_get_stream_info (info); - stream_caps = gst_discoverer_stream_info_get_caps (stream_info); - stream_type = G_TYPE_FROM_INSTANCE (stream_info); - - if (stream_type == GST_TYPE_DISCOVERER_CONTAINER_INFO && - gst_caps_can_intersect (stream_caps, profile_caps)) - ret = TRUE; - else if (stream_type != GST_TYPE_DISCOVERER_CONTAINER_INFO && - gst_caps_is_empty (profile_caps)) - ret = TRUE; - - gst_discoverer_stream_info_unref (stream_info); - gst_caps_unref (stream_caps); - - return ret; -} - -static GstCaps * -caps_from_audio_stream_info (GstDiscovererStreamInfo *info) -{ - GstCaps *temp = gst_discoverer_stream_info_get_caps (info); - GstCaps *caps = gst_caps_copy (temp); - const GstDiscovererAudioInfo *audio_info = - GST_DISCOVERER_AUDIO_INFO(info); - guint data; - - gst_caps_unref (temp); - - data = gst_discoverer_audio_info_get_sample_rate (audio_info); - if (data) - gst_caps_set_simple (caps, "rate", G_TYPE_INT, data, NULL); - - data = gst_discoverer_audio_info_get_channels (audio_info); - if (data) - gst_caps_set_simple (caps, "channels", G_TYPE_INT, data, NULL); - - data = gst_discoverer_audio_info_get_bitrate (audio_info); - if (data) - gst_caps_set_simple (caps, "bitrate", G_TYPE_INT, data, NULL); - - data = gst_discoverer_audio_info_get_max_bitrate (audio_info); - if (data) - gst_caps_set_simple - (caps, "maximum-bitrate", G_TYPE_INT, data, NULL); - - data = gst_discoverer_audio_info_get_depth (audio_info); - if (data) - gst_caps_set_simple (caps, "depth", G_TYPE_INT, data, NULL); - - return caps; -} - -static gboolean -check_audio_profile (GstDiscovererInfo *info, - GstEncodingProfile *profile) -{ - GstCaps *caps; - GList *i, *stream_list; - gboolean found = FALSE; - - /* Optimisation TODO: this can be pre-computed */ - if (is_video_profile (profile)) - return FALSE; - - stream_list = gst_discoverer_info_get_stream_list (info); - - for (i = stream_list; !found && i; i = i->next) { - GstDiscovererStreamInfo *stream = - GST_DISCOVERER_STREAM_INFO(i->data); - GType stream_type = G_TYPE_FROM_INSTANCE (stream); - - if (stream_type != GST_TYPE_DISCOVERER_AUDIO_INFO) - continue; - - caps = caps_from_audio_stream_info (stream); - - if (match_profile (profile, - caps, - GST_TYPE_ENCODING_AUDIO_PROFILE)) { - found = TRUE; - break; - } - - gst_caps_unref (caps); - } - - gst_discoverer_stream_info_list_free (stream_list); - - return found; -} - -static void -guess_audio_profile (GstDiscovererInfo *info, - gchar **name, - gchar **mime, - GList *profiles) -{ - GList *i; - GUPnPDLNAProfile *profile; - GstEncodingProfile *enc_profile; - - for (i = profiles; i; i = i->next) { - profile = (GUPnPDLNAProfile *)(i->data); - enc_profile = gupnp_dlna_profile_get_encoding_profile (profile); - - gupnp_dlna_debug ("Checking DLNA profile %s", - gupnp_dlna_profile_get_name (profile)); - - if (!check_audio_profile (info, enc_profile)) - gupnp_dlna_debug (" Audio did not match"); - else if (!check_container (info, enc_profile)) - gupnp_dlna_debug (" Container did not match"); - else { - *name = g_strdup - (gupnp_dlna_profile_get_name (profile)); - *mime = g_strdup - (gupnp_dlna_profile_get_mime (profile)); - break; - } - } -} - -static GstCaps * -caps_from_video_stream_info (GstDiscovererStreamInfo *info) -{ - GstCaps *temp = gst_discoverer_stream_info_get_caps (info); - GstCaps *caps = gst_caps_copy (temp); - const GstDiscovererVideoInfo *video_info = - GST_DISCOVERER_VIDEO_INFO (info); - const GstTagList *stream_tag_list; - guint n, d, data; - gboolean value; - - gst_caps_unref (temp); - - data = gst_discoverer_video_info_get_height (video_info); - if (data) - gst_caps_set_simple (caps, "height", G_TYPE_INT, data, NULL); - - data = gst_discoverer_video_info_get_width (video_info); - if (data) - gst_caps_set_simple (caps, "width", G_TYPE_INT, data, NULL); - - data = gst_discoverer_video_info_get_depth (video_info); - if (data) - gst_caps_set_simple (caps, "depth", G_TYPE_INT, data, NULL); - - n = gst_discoverer_video_info_get_framerate_num (video_info); - d = gst_discoverer_video_info_get_framerate_denom (video_info); - if (n && d) - gst_caps_set_simple (caps, - "framerate", - GST_TYPE_FRACTION, n, d, - NULL); - - n = gst_discoverer_video_info_get_par_num (video_info); - d = gst_discoverer_video_info_get_par_denom (video_info); - if (n && d) - gst_caps_set_simple (caps, - "pixel-aspect-ratio", - GST_TYPE_FRACTION, n, d, - NULL); - - value = gst_discoverer_video_info_is_interlaced (video_info); - if (value) - gst_caps_set_simple - (caps, "interlaced", G_TYPE_BOOLEAN, value, NULL); - - stream_tag_list = gst_discoverer_stream_info_get_tags (info); - if (stream_tag_list) { - guint bitrate; - if (gst_tag_list_get_uint (stream_tag_list, "bitrate", &bitrate)) - gst_caps_set_simple - (caps, "bitrate", G_TYPE_INT, (int) bitrate, NULL); - - if (gst_tag_list_get_uint (stream_tag_list, - "maximum-bitrate", - &bitrate)) - gst_caps_set_simple (caps, - "maximum-bitrate", - G_TYPE_INT, - (int) bitrate, - NULL); - } - - return caps; -} - -static gboolean -check_video_profile (GstDiscovererInfo *info, - GstEncodingProfile *profile) -{ - GList *i, *stream_list; - gboolean found_video = FALSE, found_audio = FALSE;; - - stream_list = gst_discoverer_info_get_stream_list (info); - - /* Check video and audio restrictions */ - for (i = stream_list; - i && !(found_video && found_audio); - i = i->next) { - GstDiscovererStreamInfo *stream; - GType stream_type; - GstCaps *caps = NULL; - - stream = GST_DISCOVERER_STREAM_INFO(i->data); - stream_type = G_TYPE_FROM_INSTANCE (stream); - - if (!found_video && - stream_type == GST_TYPE_DISCOVERER_VIDEO_INFO) { - caps = caps_from_video_stream_info (stream); - if (match_profile (profile, - caps, - GST_TYPE_ENCODING_VIDEO_PROFILE)) - found_video = TRUE; - else - gupnp_dlna_debug (" Video did not match"); - } else if (!found_audio && - stream_type == GST_TYPE_DISCOVERER_AUDIO_INFO) { - caps = caps_from_audio_stream_info (stream); - if (match_profile (profile, - caps, - GST_TYPE_ENCODING_AUDIO_PROFILE)) - found_audio = TRUE; - else - gupnp_dlna_debug (" Audio did not match"); - } - - if (caps) - gst_caps_unref (caps); - } - - gst_discoverer_stream_info_list_free (stream_list); - - if (!found_video || !found_audio) - return FALSE; - - /* Check container restrictions */ - if (!check_container (info, profile)) { - gupnp_dlna_debug (" Container did not match"); - return FALSE; - } - - return TRUE; -} - -static void -guess_video_profile (GstDiscovererInfo *info, - gchar **name, - gchar **mime, - GList *profiles) -{ - GUPnPDLNAProfile *profile = NULL; - GstEncodingProfile *enc_profile; - GList *i; - - for (i = profiles; i; i = i->next) { - profile = (GUPnPDLNAProfile *)(i->data); - enc_profile = gupnp_dlna_profile_get_encoding_profile (profile); - - gupnp_dlna_debug ("Checking DLNA profile %s", - gupnp_dlna_profile_get_name (profile)); - if (check_video_profile (info, enc_profile)) { - *name = g_strdup (gupnp_dlna_profile_get_name (profile)); - *mime = g_strdup (gupnp_dlna_profile_get_mime (profile)); - break; - } - } -} - -static void -guess_image_profile (GstDiscovererStreamInfo *info, - gchar **name, - gchar **mime, - GList *profiles) -{ - GstCaps *caps; - GList *i; - gboolean found = FALSE; - GUPnPDLNAProfile *profile; - GstEncodingProfile *enc_profile; - const GstDiscovererVideoInfo *video_info = - GST_DISCOVERER_VIDEO_INFO (info); - - if (!info || !gst_discoverer_video_info_is_image (video_info)) - return; - - caps = caps_from_video_stream_info (info); - - for (i = profiles; !found && i; i = i->next) { - profile = (GUPnPDLNAProfile *)(i->data); - enc_profile = gupnp_dlna_profile_get_encoding_profile (profile); - - /* Optimisation TODO: this can be pre-computed */ - if (!is_video_profile (enc_profile)) - continue; - - if (match_profile (enc_profile, - caps, - GST_TYPE_ENCODING_VIDEO_PROFILE)) { - /* Found a match */ - *name = g_strdup (gupnp_dlna_profile_get_name (profile)); - *mime = g_strdup (gupnp_dlna_profile_get_mime (profile)); - break; - } - } - - gst_caps_unref (caps); -} - -GUPnPDLNAInformation * -gupnp_dlna_information_new_from_discoverer_info (GstDiscovererInfo *info, - GList *profiles) -{ - GUPnPDLNAInformation *dlna; - GList *video_list, *audio_list; - gchar *name = NULL, *mime = NULL; - - video_list = gst_discoverer_info_get_video_streams (info); - audio_list = gst_discoverer_info_get_audio_streams (info); - if (video_list) { - if ((g_list_length (video_list) ==1 ) && - gst_discoverer_video_info_is_image - (GST_DISCOVERER_VIDEO_INFO - (video_list->data))) { - GstDiscovererStreamInfo *stream; - stream = (GstDiscovererStreamInfo *) video_list->data; - guess_image_profile (stream, &name, &mime, profiles); - } else - guess_video_profile (info, &name, &mime, profiles); - } else if (audio_list) - guess_audio_profile (info, &name, &mime, profiles); - - gst_discoverer_stream_info_list_free (audio_list); - gst_discoverer_stream_info_list_free (video_list); - - dlna = gupnp_dlna_information_new (name, mime, info); - - - g_free (name); - g_free (mime); - - return dlna; -} |