faac: freshen up caps negotiation

Perform sink and src caps negotiation during caps negotation,
and also cater for re-negotiation.
This commit is contained in:
Mark Nauwelaerts 2009-08-30 23:06:24 +02:00
parent f81b1e7a4a
commit 9a8d62a775

View file

@ -91,7 +91,9 @@ static void gst_faac_get_property (GObject * object,
guint prop_id, GValue * value, GParamSpec * pspec); guint prop_id, GValue * value, GParamSpec * pspec);
static gboolean gst_faac_sink_event (GstPad * pad, GstEvent * event); static gboolean gst_faac_sink_event (GstPad * pad, GstEvent * event);
static gboolean gst_faac_configure_source_pad (GstFaac * faac);
static gboolean gst_faac_sink_setcaps (GstPad * pad, GstCaps * caps); static gboolean gst_faac_sink_setcaps (GstPad * pad, GstCaps * caps);
static GstFlowReturn gst_faac_push_buffers (GstFaac * faac, gboolean force);
static GstFlowReturn gst_faac_chain (GstPad * pad, GstBuffer * data); static GstFlowReturn gst_faac_chain (GstPad * pad, GstBuffer * data);
static GstStateChangeReturn gst_faac_change_state (GstElement * element, static GstStateChangeReturn gst_faac_change_state (GstElement * element,
GstStateChange transition); GstStateChange transition);
@ -294,6 +296,16 @@ gst_faac_finalize (GObject * object)
G_OBJECT_CLASS (parent_class)->finalize (object); G_OBJECT_CLASS (parent_class)->finalize (object);
} }
static void
gst_faac_close_encoder (GstFaac * faac)
{
if (faac->handle)
faacEncClose (faac->handle);
faac->handle = NULL;
gst_adapter_clear (faac->adapter);
faac->offset = 0;
}
static gboolean static gboolean
gst_faac_sink_setcaps (GstPad * pad, GstCaps * caps) gst_faac_sink_setcaps (GstPad * pad, GstCaps * caps)
{ {
@ -305,25 +317,13 @@ gst_faac_sink_setcaps (GstPad * pad, GstCaps * caps)
gboolean result = FALSE; gboolean result = FALSE;
if (!gst_caps_is_fixed (caps)) if (!gst_caps_is_fixed (caps))
goto done; goto refuse_caps;
GST_OBJECT_LOCK (faac);
if (faac->handle) {
faacEncClose (faac->handle);
faac->handle = NULL;
}
gst_adapter_clear (faac->adapter);
faac->offset = 0;
GST_OBJECT_UNLOCK (faac);
if (!gst_structure_get_int (structure, "channels", &channels) || if (!gst_structure_get_int (structure, "channels", &channels) ||
!gst_structure_get_int (structure, "rate", &samplerate)) { !gst_structure_get_int (structure, "rate", &samplerate)) {
goto done; goto refuse_caps;
} }
if (!(handle = faacEncOpen (samplerate, channels, &samples, &bytes)))
goto done;
if (gst_structure_has_name (structure, "audio/x-raw-int")) { if (gst_structure_has_name (structure, "audio/x-raw-int")) {
gst_structure_get_int (structure, "width", &width); gst_structure_get_int (structure, "width", &width);
switch (width) { switch (width) {
@ -344,12 +344,26 @@ gst_faac_sink_setcaps (GstPad * pad, GstCaps * caps)
bps = 4; bps = 4;
} }
if (!fmt) { if (!fmt)
faacEncClose (handle); goto refuse_caps;
goto done;
/* If the encoder is initialized, do not
reinitialize it again if not necessary */
if (faac->handle) {
if (samplerate == faac->samplerate && channels == faac->channels &&
fmt == faac->format)
return TRUE;
/* clear out pending frames */
gst_faac_push_buffers (faac, TRUE);
gst_faac_close_encoder (faac);
} }
GST_OBJECT_LOCK (faac); if (!(handle = faacEncOpen (samplerate, channels, &samples, &bytes)))
goto setup_failed;
/* ok, record and set up */
faac->format = fmt; faac->format = fmt;
faac->bps = bps; faac->bps = bps;
faac->handle = handle; faac->handle = handle;
@ -357,13 +371,25 @@ gst_faac_sink_setcaps (GstPad * pad, GstCaps * caps)
faac->samples = samples; faac->samples = samples;
faac->channels = channels; faac->channels = channels;
faac->samplerate = samplerate; faac->samplerate = samplerate;
GST_OBJECT_UNLOCK (faac);
result = TRUE; /* finish up */
result = gst_faac_configure_source_pad (faac);
done: done:
gst_object_unref (faac); gst_object_unref (faac);
return result; return result;
/* ERRORS */
setup_failed:
{
GST_ELEMENT_ERROR (faac, LIBRARY, SETTINGS, (NULL), (NULL));
goto done;
}
refuse_caps:
{
GST_WARNING_OBJECT (faac, "refused caps %" GST_PTR_FORMAT, caps);
goto done;
}
} }
static gboolean static gboolean
@ -372,7 +398,7 @@ gst_faac_configure_source_pad (GstFaac * faac)
GstCaps *allowed_caps; GstCaps *allowed_caps;
GstCaps *srccaps; GstCaps *srccaps;
gboolean ret = FALSE; gboolean ret = FALSE;
gint n, ver, mpegversion; gint n, ver, mpegversion = 2;
faacEncConfiguration *conf; faacEncConfiguration *conf;
guint maxbitrate; guint maxbitrate;
@ -381,9 +407,7 @@ gst_faac_configure_source_pad (GstFaac * faac)
allowed_caps = gst_pad_get_allowed_caps (faac->srcpad); allowed_caps = gst_pad_get_allowed_caps (faac->srcpad);
GST_DEBUG_OBJECT (faac, "allowed caps: %" GST_PTR_FORMAT, allowed_caps); GST_DEBUG_OBJECT (faac, "allowed caps: %" GST_PTR_FORMAT, allowed_caps);
if (allowed_caps == NULL) if (allowed_caps) {
return FALSE;
if (gst_caps_is_empty (allowed_caps)) if (gst_caps_is_empty (allowed_caps))
goto empty_caps; goto empty_caps;
@ -399,6 +423,7 @@ gst_faac_configure_source_pad (GstFaac * faac)
} }
} }
gst_caps_unref (allowed_caps); gst_caps_unref (allowed_caps);
}
/* we negotiated caps update current configuration */ /* we negotiated caps update current configuration */
conf = faacEncGetCurrentConfiguration (faac->handle); conf = faacEncGetCurrentConfiguration (faac->handle);
@ -635,11 +660,6 @@ gst_faac_chain (GstPad * pad, GstBuffer * inbuf)
if (!faac->handle) if (!faac->handle)
goto no_handle; goto no_handle;
if (!GST_PAD_CAPS (faac->srcpad)) {
if (!gst_faac_configure_source_pad (faac))
goto nego_failed;
}
GST_LOG_OBJECT (faac, "Got buffer time: %" GST_TIME_FORMAT " duration: %" GST_LOG_OBJECT (faac, "Got buffer time: %" GST_TIME_FORMAT " duration: %"
GST_TIME_FORMAT, GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (inbuf)), GST_TIME_FORMAT, GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (inbuf)),
GST_TIME_ARGS (GST_BUFFER_DURATION (inbuf))); GST_TIME_ARGS (GST_BUFFER_DURATION (inbuf)));
@ -662,14 +682,6 @@ no_handle:
result = GST_FLOW_ERROR; result = GST_FLOW_ERROR;
goto done; goto done;
} }
nego_failed:
{
GST_ELEMENT_ERROR (faac, CORE, NEGOTIATION, (NULL),
("failed to negotiate MPEG/AAC format with next element"));
gst_buffer_unref (inbuf);
result = GST_FLOW_ERROR;
goto done;
}
} }
static void static void