faac: Add the profile and level to the caps

Also negotiate the profile from the downstream peer caps
instead of using a property.

Fixes bug #650594.
This commit is contained in:
Sebastian Dröge 2011-05-27 10:11:32 +02:00
parent 7f0aa4061e
commit 6702de4237
3 changed files with 86 additions and 86 deletions

View file

@ -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

View file

@ -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.
*
* <refsect2>
* <title>Example launch line</title>
* |[
@ -44,6 +39,7 @@
#include <string.h>
#include <gst/audio/multichannel.h>
#include <gst/pbutils/codec-utils.h>
#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;

View file

@ -54,6 +54,7 @@ struct _GstFaac {
bps,
bitrate,
profile,
mpegversion,
shortctl,
outputformat;
gboolean tns,