encoding-profile: add gst_encoding_profile_get_file_extension()

API: gst_encoding_profile_get_file_extension()

https://bugzilla.gnome.org/show_bug.cgi?id=636753
This commit is contained in:
Tim-Philipp Müller 2012-12-23 15:26:59 +00:00
parent 76c0cca765
commit 42f971c5eb
5 changed files with 252 additions and 1 deletions

View file

@ -300,7 +300,7 @@ static const FormatInfo formats[] = {
{"video/x-dv", "Digital Video (DV) System Stream",
FLAG_CONTAINER | FLAG_SYSTEMSTREAM, "dv"},
{"video/x-dv", "Digital Video (DV)", FLAG_VIDEO, ""},
{"video/x-h263", NULL, FLAG_VIDEO, ""},
{"video/x-h263", NULL, FLAG_VIDEO, "h263"},
{"video/x-h264", NULL, FLAG_VIDEO, "h264"},
{"video/x-indeo", NULL, FLAG_VIDEO, ""},
{"video/x-msmpeg", NULL, FLAG_VIDEO, ""},
@ -1028,6 +1028,79 @@ gst_pb_utils_get_codec_description (const GstCaps * caps)
return str;
}
/* internal helper functions for gst_encoding_profile_get_file_extension() */
const gchar *pb_utils_get_file_extension_from_caps (const GstCaps * caps);
gboolean pb_utils_is_tag (const GstCaps * caps);
const gchar *
pb_utils_get_file_extension_from_caps (const GstCaps * caps)
{
const FormatInfo *info;
const gchar *ext = NULL;
GstCaps *stripped_caps;
g_assert (GST_IS_CAPS (caps));
stripped_caps = copy_and_clean_caps (caps);
g_assert (gst_caps_is_fixed (stripped_caps));
info = find_format_info (stripped_caps);
if (info && info->ext[0] != '\0') {
ext = info->ext;
} else if (info && info->desc == NULL) {
const GstStructure *s;
s = gst_caps_get_structure (stripped_caps, 0);
/* cases where we have to evaluate the caps more closely */
if (strcmp (info->type, "audio/mpeg") == 0) {
int version = 0, layer = 3;
if (gst_structure_get_int (s, "mpegversion", &version)) {
if (version == 2 || version == 4) {
ext = "aac";
} else if (version == 1) {
gst_structure_get_int (s, "layer", &layer);
if (layer == 1)
ext = "mp1";
else if (layer == 2)
ext = "mp2";
else
ext = "mp3";
}
}
}
}
gst_caps_unref (stripped_caps);
return ext;
}
gboolean
pb_utils_is_tag (const GstCaps * caps)
{
const FormatInfo *info;
GstCaps *stripped_caps;
gboolean is_tag = FALSE;
g_assert (GST_IS_CAPS (caps));
stripped_caps = copy_and_clean_caps (caps);
g_assert (gst_caps_is_fixed (stripped_caps));
info = find_format_info (stripped_caps);
if (info) {
is_tag = (info->flags & FLAG_TAG) != 0;
}
gst_caps_unref (stripped_caps);
return is_tag;
}
#if 0
void
gst_pb_utils_list_all (void)

View file

@ -127,6 +127,8 @@
#include "encoding-profile.h"
#include "encoding-target.h"
#include <string.h>
/* GstEncodingProfile API */
struct _GstEncodingProfile
@ -902,6 +904,114 @@ gst_encoding_profile_get_type_nick (GstEncodingProfile * profile)
return NULL;
}
extern const gchar *pb_utils_get_file_extension_from_caps (const GstCaps *
caps);
gboolean pb_utils_is_tag (const GstCaps * caps);
static gboolean
gst_encoding_profile_has_format (GstEncodingProfile * profile,
const gchar * media_type)
{
GstCaps *caps;
gboolean ret;
caps = gst_encoding_profile_get_format (profile);
ret = gst_structure_has_name (gst_caps_get_structure (caps, 0), media_type);
gst_caps_unref (caps);
return ret;
}
static gboolean
gst_encoding_container_profile_has_video (GstEncodingContainerProfile * profile)
{
const GList *l;
for (l = profile->encodingprofiles; l != NULL; l = l->next) {
if (GST_IS_ENCODING_VIDEO_PROFILE (l->data))
return TRUE;
if (GST_IS_ENCODING_CONTAINER_PROFILE (l->data) &&
gst_encoding_container_profile_has_video (l->data))
return TRUE;
}
return FALSE;
}
/**
* gst_encoding_profile_get_file_extension:
* @profile: a #GstEncodingProfile
*
* Returns: a suitable file extension for @profile, or NULL.
*/
const gchar *
gst_encoding_profile_get_file_extension (GstEncodingProfile * profile)
{
GstEncodingContainerProfile *cprofile;
const gchar *ext = NULL;
gboolean has_video;
GstCaps *caps;
guint num_children;
g_return_val_if_fail (GST_IS_ENCODING_PROFILE (profile), NULL);
caps = gst_encoding_profile_get_format (profile);
ext = pb_utils_get_file_extension_from_caps (caps);
if (!GST_IS_ENCODING_CONTAINER_PROFILE (profile))
goto done;
cprofile = GST_ENCODING_CONTAINER_PROFILE (profile);
num_children = g_list_length (cprofile->encodingprofiles);
/* if it's a tag container profile (e.g. id3mux/apemux), we need
* to look at what's inside it */
if (pb_utils_is_tag (caps)) {
GST_DEBUG ("tag container profile");
if (num_children == 1) {
GstEncodingProfile *child_profile = cprofile->encodingprofiles->data;
ext = gst_encoding_profile_get_file_extension (child_profile);
} else {
GST_WARNING ("expected exactly one child profile with tag profile");
}
goto done;
}
/* special cases */
has_video = gst_encoding_container_profile_has_video (cprofile);
if (strcmp (ext, "ogg") == 0) {
/* ogg with video => .ogv */
if (has_video) {
ext = "ogv";
goto done;
}
/* ogg with just speex audio => .spx */
if (num_children == 1) {
GstEncodingProfile *child_profile = cprofile->encodingprofiles->data;
if (GST_IS_ENCODING_AUDIO_PROFILE (child_profile) &&
gst_encoding_profile_has_format (child_profile, "audio/x-speex")) {
ext = "spx";
goto done;
}
}
/* does anyone actually use .oga for ogg audio files? */
goto done;
}
if (has_video && strcmp (ext, "mka") == 0)
ext = "mkv";
done:
GST_INFO ("caps %" GST_PTR_FORMAT ", ext: %s", caps, GST_STR_NULL (ext));
gst_caps_unref (caps);
return ext;
}
/**
* gst_encoding_profile_find:
* @targetname: (transfer none): The name of the target

View file

@ -143,6 +143,8 @@ gboolean gst_encoding_profile_is_equal (GstEncodingProfile *a,
GstCaps * gst_encoding_profile_get_input_caps (GstEncodingProfile *profile);
const gchar * gst_encoding_profile_get_type_nick (GstEncodingProfile *profile);
const gchar * gst_encoding_profile_get_file_extension (GstEncodingProfile * profile);
GstEncodingProfile * gst_encoding_profile_find (const gchar *targetname,
const gchar *profilename,
const gchar *category);

View file

@ -605,6 +605,70 @@ test_teardown (void)
remove_profile_file ();
}
GST_START_TEST (test_file_extension)
{
GstEncodingContainerProfile *cprof;
GstCaps *ogg, *speex, *vorbis, *theora, *id3, *mp3;
/* 1 - ogg variants */
ogg = gst_caps_new_empty_simple ("application/ogg");
cprof = gst_encoding_container_profile_new ("myprofile", NULL, ogg, NULL);
gst_caps_unref (ogg);
fail_unless_equals_string (gst_encoding_profile_get_file_extension
(GST_ENCODING_PROFILE (cprof)), "ogg");
speex = gst_caps_new_empty_simple ("audio/x-speex");
gst_encoding_container_profile_add_profile (cprof,
(GstEncodingProfile *) gst_encoding_audio_profile_new (speex, NULL,
NULL, 1));
gst_caps_unref (speex);
fail_unless_equals_string (gst_encoding_profile_get_file_extension
(GST_ENCODING_PROFILE (cprof)), "spx");
vorbis = gst_caps_new_empty_simple ("audio/x-vorbis");
gst_encoding_container_profile_add_profile (cprof,
(GstEncodingProfile *) gst_encoding_audio_profile_new (vorbis, NULL,
NULL, 1));
gst_caps_unref (vorbis);
fail_unless_equals_string (gst_encoding_profile_get_file_extension
(GST_ENCODING_PROFILE (cprof)), "ogg");
theora = gst_caps_new_empty_simple ("video/x-theora");
gst_encoding_container_profile_add_profile (cprof,
(GstEncodingProfile *) gst_encoding_video_profile_new (theora, NULL,
NULL, 1));
gst_caps_unref (theora);
fail_unless_equals_string (gst_encoding_profile_get_file_extension
(GST_ENCODING_PROFILE (cprof)), "ogv");
gst_encoding_profile_unref (cprof);
/* 2 - tag container */
id3 = gst_caps_new_empty_simple ("application/x-id3");
cprof = gst_encoding_container_profile_new ("myprofile", NULL, id3, NULL);
gst_caps_unref (id3);
fail_unless (gst_encoding_profile_get_file_extension (GST_ENCODING_PROFILE
(cprof)) == NULL);
mp3 = gst_caps_new_simple ("audio/mpeg", "mpegversion", G_TYPE_INT, 1,
"layer", G_TYPE_INT, 3, NULL);
gst_encoding_container_profile_add_profile (cprof,
(GstEncodingProfile *) gst_encoding_audio_profile_new (mp3, NULL,
NULL, 1));
gst_caps_unref (mp3);
fail_unless_equals_string (gst_encoding_profile_get_file_extension
(GST_ENCODING_PROFILE (cprof)), "mp3");
gst_encoding_profile_unref (cprof);
}
GST_END_TEST;
static Suite *
profile_suite (void)
@ -625,6 +689,7 @@ profile_suite (void)
tcase_add_test (tc_chain, test_profile_input_caps);
tcase_add_test (tc_chain, test_target_naming);
tcase_add_test (tc_chain, test_target_profile);
tcase_add_test (tc_chain, test_file_extension);
if (can_write) {
tcase_add_test (tc_chain, test_loading_profile);
tcase_add_test (tc_chain, test_saving_profile);

View file

@ -78,6 +78,7 @@ EXPORTS
gst_encoding_profile_find
gst_encoding_profile_from_discoverer
gst_encoding_profile_get_description
gst_encoding_profile_get_file_extension
gst_encoding_profile_get_format
gst_encoding_profile_get_input_caps
gst_encoding_profile_get_name