diff --git a/ext/faac/Makefile.am b/ext/faac/Makefile.am index b4ec10a3fe..3cdf9ca241 100644 --- a/ext/faac/Makefile.am +++ b/ext/faac/Makefile.am @@ -4,7 +4,7 @@ libgstfaac_la_SOURCES = gstfaac.c libgstfaac_la_CFLAGS = $(FAAC_CFLAGS) $(GST_CFLAGS) $(GST_BASE_CFLAGS) \ $(GST_PLUGINS_BASE_CFLAGS) libgstfaac_la_LIBADD = $(FAAC_LIBS) $(GST_BASE_LIBS) $(GST_PLUGINS_BASE_LIBS) \ - -lgstaudio-@GST_MAJORMINOR@ + -lgstaudio-@GST_MAJORMINOR@ -lgstpbutils-@GST_MAJORMINOR@ libgstfaac_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) libgstfaac_la_LIBTOOLFLAGS = --tag=disable-static diff --git a/ext/faac/gstfaac.c b/ext/faac/gstfaac.c index 5bc44f9e41..2ed0f6fde8 100644 --- a/ext/faac/gstfaac.c +++ b/ext/faac/gstfaac.c @@ -24,11 +24,6 @@ * * faac encodes raw audio to AAC (MPEG-4 part 3) streams. * - * - * The #GstFaac:profile property determines the AAC profile, where the default - * LC (Low Complexity) profile is most widely used, supported and suitable for - * general use. The other profiles are very rarely used and often not supported. - * * * Example launch line * |[ @@ -44,6 +39,7 @@ #include #include +#include #include "gstfaac.h" @@ -72,10 +68,17 @@ #endif #define SRC_CAPS \ "audio/mpeg, " \ - "mpegversion = (int) { 4, 2 }, " \ + "mpegversion = (int) 4, " \ "channels = (int) [ 1, 6 ], " \ "rate = (int) [ 8000, 96000 ], " \ - "stream-format = (string) { adts, raw } " + "stream-format = (string) { adts, raw }, " \ + "base-profile = (string) { main, lc, ssr, ltp }; " \ + "audio/mpeg, " \ + "mpegversion = (int) 2, " \ + "channels = (int) [ 1, 6 ], " \ + "rate = (int) [ 8000, 96000 ], " \ + "stream-format = (string) { adts, raw }, " \ + "profile = (string) { main, lc }" static GstStaticPadTemplate src_template = GST_STATIC_PAD_TEMPLATE ("src", GST_PAD_SRC, GST_PAD_ALWAYS, @@ -121,10 +124,8 @@ static GstElementClass *parent_class = NULL; GST_DEBUG_CATEGORY_STATIC (faac_debug); #define GST_CAT_DEFAULT faac_debug -#define FAAC_DEFAULT_MPEGVERSION 4 #define FAAC_DEFAULT_OUTPUTFORMAT 0 /* RAW */ #define FAAC_DEFAULT_BITRATE 128 * 1000 -#define FAAC_DEFAULT_PROFILE LOW #define FAAC_DEFAULT_TNS FALSE #define FAAC_DEFAULT_MIDSIDE TRUE #define FAAC_DEFAULT_SHORTCTL SHORTCTL_NORMAL @@ -180,28 +181,6 @@ gst_faac_base_init (GstFaacClass * klass) GST_DEBUG_CATEGORY_INIT (faac_debug, "faac", 0, "AAC encoding"); } -#define GST_TYPE_FAAC_PROFILE (gst_faac_profile_get_type ()) -static GType -gst_faac_profile_get_type (void) -{ - static GType gst_faac_profile_type = 0; - - if (!gst_faac_profile_type) { - static GEnumValue gst_faac_profile[] = { - {MAIN, "MAIN", "Main profile"}, - {LOW, "LC", "Low complexity profile"}, - {SSR, "SSR", "Scalable sampling rate profile"}, - {LTP, "LTP", "Long term prediction profile"}, - {0, NULL, NULL}, - }; - - gst_faac_profile_type = g_enum_register_static ("GstFaacProfile", - gst_faac_profile); - } - - return gst_faac_profile_type; -} - #define GST_TYPE_FAAC_SHORTCTL (gst_faac_shortctl_get_type ()) static GType gst_faac_shortctl_get_type (void) @@ -240,10 +219,6 @@ gst_faac_class_init (GstFaacClass * klass) g_param_spec_int ("bitrate", "Bitrate (bps)", "Bitrate in bits/sec", 8 * 1000, 320 * 1000, FAAC_DEFAULT_BITRATE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); - g_object_class_install_property (gobject_class, PROP_PROFILE, - g_param_spec_enum ("profile", "Profile", "MPEG/AAC encoding profile", - GST_TYPE_FAAC_PROFILE, FAAC_DEFAULT_PROFILE, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); g_object_class_install_property (gobject_class, PROP_TNS, g_param_spec_boolean ("tns", "TNS", "Use temporal noise shaping", FAAC_DEFAULT_TNS, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); @@ -280,9 +255,11 @@ gst_faac_init (GstFaac * faac) faac->adapter = gst_adapter_new (); + faac->profile = LOW; + faac->mpegversion = 4; + /* default properties */ faac->bitrate = FAAC_DEFAULT_BITRATE; - faac->profile = FAAC_DEFAULT_PROFILE; faac->shortctl = FAAC_DEFAULT_SHORTCTL; faac->outputformat = FAAC_DEFAULT_OUTPUTFORMAT; faac->tns = FAAC_DEFAULT_TNS; @@ -410,6 +387,7 @@ gst_faac_negotiate (GstFaac * faac) if (caps && gst_caps_get_size (caps) > 0) { GstStructure *s = gst_caps_get_structure (caps, 0); const gchar *str = NULL; + gint i = 4; if ((str = gst_structure_get_string (s, "stream-format"))) { if (strcmp (str, "adts") == 0) { @@ -423,11 +401,30 @@ gst_faac_negotiate (GstFaac * faac) faac->outputformat = 0; } } + + if ((str = gst_structure_get_string (s, "profile"))) { + if (strcmp (str, "main") == 0) { + faac->profile = MAIN; + } else if (strcmp (str, "lc") == 0) { + faac->profile = LOW; + } else if (strcmp (str, "ssr") == 0) { + faac->profile = SSR; + } else if (strcmp (str, "ltp") == 0) { + faac->profile = LTP; + } else { + faac->profile = LOW; + } + } + + if (!gst_structure_get_int (s, "mpegversion", &i) || i == 4) { + faac->mpegversion = 4; + } else { + faac->mpegversion = 2; + } } if (caps) gst_caps_unref (caps); - } static gboolean @@ -521,39 +518,14 @@ refuse_caps: static gboolean gst_faac_configure_source_pad (GstFaac * faac) { - GstCaps *allowed_caps; GstCaps *srccaps; gboolean ret = FALSE; - gint n, ver, mpegversion = 2; faacEncConfiguration *conf; guint maxbitrate; - mpegversion = FAAC_DEFAULT_MPEGVERSION; - - allowed_caps = gst_pad_get_allowed_caps (faac->srcpad); - GST_DEBUG_OBJECT (faac, "allowed caps: %" GST_PTR_FORMAT, allowed_caps); - - if (allowed_caps) { - if (gst_caps_is_empty (allowed_caps)) - goto empty_caps; - - if (!gst_caps_is_any (allowed_caps)) { - for (n = 0; n < gst_caps_get_size (allowed_caps); n++) { - GstStructure *s = gst_caps_get_structure (allowed_caps, n); - - if (gst_structure_get_int (s, "mpegversion", &ver) && - (ver == 4 || ver == 2)) { - mpegversion = ver; - break; - } - } - } - gst_caps_unref (allowed_caps); - } - /* we negotiated caps update current configuration */ conf = faacEncGetCurrentConfiguration (faac->handle); - conf->mpegVersion = (mpegversion == 4) ? MPEG4 : MPEG2; + conf->mpegVersion = (faac->mpegversion == 4) ? MPEG4 : MPEG2; conf->aacObjectType = faac->profile; conf->allowMidside = faac->midside; conf->useLfe = 0; @@ -591,14 +563,14 @@ gst_faac_configure_source_pad (GstFaac * faac) /* now create a caps for it all */ srccaps = gst_caps_new_simple ("audio/mpeg", - "mpegversion", G_TYPE_INT, mpegversion, + "mpegversion", G_TYPE_INT, faac->mpegversion, "channels", G_TYPE_INT, faac->channels, "rate", G_TYPE_INT, faac->samplerate, "stream-format", G_TYPE_STRING, (faac->outputformat ? "adts" : "raw"), NULL); - if (!faac->outputformat) { - GstBuffer *codec_data; + /* DecoderSpecificInfo is only available for mpegversion=4 */ + if (faac->mpegversion == 4) { guint8 *config = NULL; gulong config_len = 0; @@ -606,16 +578,49 @@ gst_faac_configure_source_pad (GstFaac * faac) GST_DEBUG_OBJECT (faac, "retrieving decoder info"); faacEncGetDecoderSpecificInfo (faac->handle, &config, &config_len); - /* copy it into a buffer */ - codec_data = gst_buffer_new_and_alloc (config_len); - memcpy (GST_BUFFER_DATA (codec_data), config, config_len); + if (!gst_codec_utils_aac_caps_set_level_and_profile (srccaps, config, + config_len)) { + free (config); + gst_caps_unref (srccaps); + goto invalid_codec_data; + } + + if (!faac->outputformat) { + GstBuffer *codec_data; + + /* copy it into a buffer */ + codec_data = gst_buffer_new_and_alloc (config_len); + memcpy (GST_BUFFER_DATA (codec_data), config, config_len); + + /* add to caps */ + gst_caps_set_simple (srccaps, + "codec_data", GST_TYPE_BUFFER, codec_data, NULL); + + gst_buffer_unref (codec_data); + } + free (config); + } else { + const gchar *profile; - /* add to caps */ - gst_caps_set_simple (srccaps, - "codec_data", GST_TYPE_BUFFER, codec_data, NULL); - - gst_buffer_unref (codec_data); + /* Add least add the profile to the caps */ + switch (faac->profile) { + case MAIN: + profile = "main"; + break; + case LTP: + profile = "ltp"; + break; + case SSR: + profile = "ssr"; + break; + case LOW: + default: + profile = "lc"; + break; + } + gst_caps_set_simple (srccaps, "profile", G_TYPE_STRING, profile, NULL); + /* FIXME: How to get the profile for mpegversion==2? */ } GST_DEBUG_OBJECT (faac, "src pad caps: %" GST_PTR_FORMAT, srccaps); @@ -626,16 +631,16 @@ gst_faac_configure_source_pad (GstFaac * faac) return ret; /* ERROR */ -empty_caps: - { - gst_caps_unref (allowed_caps); - return FALSE; - } set_failed: { GST_WARNING_OBJECT (faac, "Faac doesn't support the current configuration"); return FALSE; } +invalid_codec_data: + { + GST_ERROR_OBJECT (faac, "Invalid codec data"); + return FALSE; + } } static GstFlowReturn @@ -850,9 +855,6 @@ gst_faac_set_property (GObject * object, case PROP_BITRATE: faac->bitrate = g_value_get_int (value); break; - case PROP_PROFILE: - faac->profile = g_value_get_enum (value); - break; case PROP_TNS: faac->tns = g_value_get_boolean (value); break; @@ -882,9 +884,6 @@ gst_faac_get_property (GObject * object, case PROP_BITRATE: g_value_set_int (value, faac->bitrate); break; - case PROP_PROFILE: - g_value_set_enum (value, faac->profile); - break; case PROP_TNS: g_value_set_boolean (value, faac->tns); break; diff --git a/ext/faac/gstfaac.h b/ext/faac/gstfaac.h index 7a282ec508..49e2b85e86 100644 --- a/ext/faac/gstfaac.h +++ b/ext/faac/gstfaac.h @@ -54,6 +54,7 @@ struct _GstFaac { bps, bitrate, profile, + mpegversion, shortctl, outputformat; gboolean tns,