mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-10-19 00:43:44 +00:00
parent
6a7b02e480
commit
f81b1e7a4a
2 changed files with 149 additions and 173 deletions
|
@ -1,5 +1,6 @@
|
||||||
/* GStreamer FAAC (Free AAC Encoder) plugin
|
/* GStreamer FAAC (Free AAC Encoder) plugin
|
||||||
* Copyright (C) 2003 Ronald Bultje <rbultje@ronald.bitfreak.net>
|
* Copyright (C) 2003 Ronald Bultje <rbultje@ronald.bitfreak.net>
|
||||||
|
* Copyright (C) 2009 Mark Nauwelaerts <mnauw@users.sourceforge.net>
|
||||||
*
|
*
|
||||||
* This library is free software; you can redistribute it and/or
|
* This library is free software; you can redistribute it and/or
|
||||||
* modify it under the terms of the GNU Library General Public
|
* modify it under the terms of the GNU Library General Public
|
||||||
|
@ -82,6 +83,7 @@ enum
|
||||||
static void gst_faac_base_init (GstFaacClass * klass);
|
static void gst_faac_base_init (GstFaacClass * klass);
|
||||||
static void gst_faac_class_init (GstFaacClass * klass);
|
static void gst_faac_class_init (GstFaacClass * klass);
|
||||||
static void gst_faac_init (GstFaac * faac);
|
static void gst_faac_init (GstFaac * faac);
|
||||||
|
static void gst_faac_finalize (GObject * object);
|
||||||
|
|
||||||
static void gst_faac_set_property (GObject * object,
|
static void gst_faac_set_property (GObject * object,
|
||||||
guint prop_id, const GValue * value, GParamSpec * pspec);
|
guint prop_id, const GValue * value, GParamSpec * pspec);
|
||||||
|
@ -222,6 +224,7 @@ gst_faac_class_init (GstFaacClass * klass)
|
||||||
|
|
||||||
gobject_class->set_property = gst_faac_set_property;
|
gobject_class->set_property = gst_faac_set_property;
|
||||||
gobject_class->get_property = gst_faac_get_property;
|
gobject_class->get_property = gst_faac_get_property;
|
||||||
|
gobject_class->finalize = GST_DEBUG_FUNCPTR (gst_faac_finalize);
|
||||||
|
|
||||||
/* properties */
|
/* properties */
|
||||||
g_object_class_install_property (gobject_class, ARG_BITRATE,
|
g_object_class_install_property (gobject_class, ARG_BITRATE,
|
||||||
|
@ -255,10 +258,7 @@ gst_faac_init (GstFaac * faac)
|
||||||
faac->handle = NULL;
|
faac->handle = NULL;
|
||||||
faac->samplerate = -1;
|
faac->samplerate = -1;
|
||||||
faac->channels = -1;
|
faac->channels = -1;
|
||||||
faac->cache = NULL;
|
faac->offset = 0;
|
||||||
faac->cache_time = GST_CLOCK_TIME_NONE;
|
|
||||||
faac->cache_duration = 0;
|
|
||||||
faac->next_ts = GST_CLOCK_TIME_NONE;
|
|
||||||
|
|
||||||
faac->sinkpad = gst_pad_new_from_static_template (&sink_template, "sink");
|
faac->sinkpad = gst_pad_new_from_static_template (&sink_template, "sink");
|
||||||
gst_pad_set_chain_function (faac->sinkpad,
|
gst_pad_set_chain_function (faac->sinkpad,
|
||||||
|
@ -273,6 +273,8 @@ gst_faac_init (GstFaac * faac)
|
||||||
gst_pad_use_fixed_caps (faac->srcpad);
|
gst_pad_use_fixed_caps (faac->srcpad);
|
||||||
gst_element_add_pad (GST_ELEMENT (faac), faac->srcpad);
|
gst_element_add_pad (GST_ELEMENT (faac), faac->srcpad);
|
||||||
|
|
||||||
|
faac->adapter = gst_adapter_new ();
|
||||||
|
|
||||||
/* default properties */
|
/* default properties */
|
||||||
faac->bitrate = 1000 * 128;
|
faac->bitrate = 1000 * 128;
|
||||||
faac->profile = MAIN;
|
faac->profile = MAIN;
|
||||||
|
@ -282,6 +284,16 @@ gst_faac_init (GstFaac * faac)
|
||||||
faac->midside = TRUE;
|
faac->midside = TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_faac_finalize (GObject * object)
|
||||||
|
{
|
||||||
|
GstFaac *faac = (GstFaac *) object;
|
||||||
|
|
||||||
|
g_object_unref (faac->adapter);
|
||||||
|
|
||||||
|
G_OBJECT_CLASS (parent_class)->finalize (object);
|
||||||
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
gst_faac_sink_setcaps (GstPad * pad, GstCaps * caps)
|
gst_faac_sink_setcaps (GstPad * pad, GstCaps * caps)
|
||||||
{
|
{
|
||||||
|
@ -300,10 +312,8 @@ gst_faac_sink_setcaps (GstPad * pad, GstCaps * caps)
|
||||||
faacEncClose (faac->handle);
|
faacEncClose (faac->handle);
|
||||||
faac->handle = NULL;
|
faac->handle = NULL;
|
||||||
}
|
}
|
||||||
if (faac->cache) {
|
gst_adapter_clear (faac->adapter);
|
||||||
gst_buffer_unref (faac->cache);
|
faac->offset = 0;
|
||||||
faac->cache = NULL;
|
|
||||||
}
|
|
||||||
GST_OBJECT_UNLOCK (faac);
|
GST_OBJECT_UNLOCK (faac);
|
||||||
|
|
||||||
if (!gst_structure_get_int (structure, "channels", &channels) ||
|
if (!gst_structure_get_int (structure, "channels", &channels) ||
|
||||||
|
@ -464,6 +474,119 @@ set_failed:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static GstFlowReturn
|
||||||
|
gst_faac_push_buffers (GstFaac * faac, gboolean force)
|
||||||
|
{
|
||||||
|
GstFlowReturn ret = GST_FLOW_OK;
|
||||||
|
gint av, frame_size, size, ret_size;
|
||||||
|
GstBuffer *outbuf;
|
||||||
|
guint64 timestamp, distance;
|
||||||
|
const guint8 *data;
|
||||||
|
|
||||||
|
/* samples already considers channel count */
|
||||||
|
frame_size = faac->samples * faac->bps;
|
||||||
|
|
||||||
|
while (ret == GST_FLOW_OK) {
|
||||||
|
|
||||||
|
av = gst_adapter_available (faac->adapter);
|
||||||
|
|
||||||
|
GST_LOG_OBJECT (faac, "pushing: force: %d, frame_size: %d, av: %d, "
|
||||||
|
"offset: %d", force, frame_size, av, faac->offset);
|
||||||
|
|
||||||
|
/* idea:
|
||||||
|
* - start of adapter corresponds with what has already been encoded
|
||||||
|
* (i.e. really returned by faac)
|
||||||
|
* - start + offset is what needs to be fed to faac next
|
||||||
|
* That way we can timestamp the output based
|
||||||
|
* on adapter provided timestamp (and duration is a fixed frame duration) */
|
||||||
|
|
||||||
|
/* not enough data for one frame and no flush forcing */
|
||||||
|
if (!force && (av < frame_size + faac->offset))
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (G_LIKELY (av - faac->offset >= frame_size)) {
|
||||||
|
GST_LOG_OBJECT (faac, "encoding a frame");
|
||||||
|
data = gst_adapter_peek (faac->adapter, faac->offset + frame_size);
|
||||||
|
data += faac->offset;
|
||||||
|
size = frame_size;
|
||||||
|
} else if (av - faac->offset > 0) {
|
||||||
|
GST_LOG_OBJECT (faac, "encoding leftover");
|
||||||
|
data = gst_adapter_peek (faac->adapter, av);
|
||||||
|
data += faac->offset;
|
||||||
|
size = av - faac->offset;
|
||||||
|
} else {
|
||||||
|
GST_LOG_OBJECT (faac, "emptying encoder");
|
||||||
|
data = NULL;
|
||||||
|
size = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
outbuf = gst_buffer_new_and_alloc (faac->bytes);
|
||||||
|
|
||||||
|
if ((ret_size = faacEncEncode (faac->handle, (gint32 *) data,
|
||||||
|
size / faac->bps, GST_BUFFER_DATA (outbuf), faac->bytes)) < 0) {
|
||||||
|
gst_buffer_unref (outbuf);
|
||||||
|
goto encode_failed;
|
||||||
|
}
|
||||||
|
|
||||||
|
GST_LOG_OBJECT (faac, "encoder return: %d", ret_size);
|
||||||
|
|
||||||
|
/* consumed, advanced view */
|
||||||
|
faac->offset += size;
|
||||||
|
g_assert (faac->offset <= av);
|
||||||
|
|
||||||
|
if (!ret_size) {
|
||||||
|
gst_buffer_unref (outbuf);
|
||||||
|
if (size)
|
||||||
|
continue;
|
||||||
|
else
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* after some caching, finally some data */
|
||||||
|
/* adapter gives time */
|
||||||
|
timestamp = gst_adapter_prev_timestamp (faac->adapter, &distance);
|
||||||
|
if ((av = gst_adapter_available (faac->adapter)) >= frame_size) {
|
||||||
|
/* must have then come from a complete frame */
|
||||||
|
gst_adapter_flush (faac->adapter, frame_size);
|
||||||
|
faac->offset -= frame_size;
|
||||||
|
size = frame_size;
|
||||||
|
} else {
|
||||||
|
/* otherwise leftover */
|
||||||
|
gst_adapter_clear (faac->adapter);
|
||||||
|
faac->offset = 0;
|
||||||
|
size = av;
|
||||||
|
}
|
||||||
|
|
||||||
|
GST_BUFFER_SIZE (outbuf) = ret_size;
|
||||||
|
if (GST_CLOCK_TIME_IS_VALID (timestamp))
|
||||||
|
GST_BUFFER_TIMESTAMP (outbuf) = timestamp +
|
||||||
|
GST_FRAMES_TO_CLOCK_TIME (distance / faac->channels / faac->bps,
|
||||||
|
faac->samplerate);
|
||||||
|
GST_BUFFER_DURATION (outbuf) =
|
||||||
|
GST_FRAMES_TO_CLOCK_TIME (size / faac->channels / faac->bps,
|
||||||
|
faac->samplerate);
|
||||||
|
/* perhaps check/set DISCONT based on timestamps ? */
|
||||||
|
|
||||||
|
GST_LOG_OBJECT (faac, "Pushing out buffer time: %" GST_TIME_FORMAT
|
||||||
|
" duration: %" GST_TIME_FORMAT,
|
||||||
|
GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (outbuf)),
|
||||||
|
GST_TIME_ARGS (GST_BUFFER_DURATION (outbuf)));
|
||||||
|
|
||||||
|
gst_buffer_set_caps (outbuf, GST_PAD_CAPS (faac->srcpad));
|
||||||
|
ret = gst_pad_push (faac->srcpad, outbuf);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
/* ERRORS */
|
||||||
|
encode_failed:
|
||||||
|
{
|
||||||
|
GST_ELEMENT_ERROR (faac, LIBRARY, ENCODE, (NULL), (NULL));
|
||||||
|
gst_buffer_unref (outbuf);
|
||||||
|
return GST_FLOW_ERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
gst_faac_sink_event (GstPad * pad, GstEvent * event)
|
gst_faac_sink_event (GstPad * pad, GstEvent * event)
|
||||||
{
|
{
|
||||||
|
@ -472,46 +595,17 @@ gst_faac_sink_event (GstPad * pad, GstEvent * event)
|
||||||
|
|
||||||
faac = GST_FAAC (gst_pad_get_parent (pad));
|
faac = GST_FAAC (gst_pad_get_parent (pad));
|
||||||
|
|
||||||
|
GST_LOG_OBJECT (faac, "received %s", GST_EVENT_TYPE_NAME (event));
|
||||||
|
|
||||||
switch (GST_EVENT_TYPE (event)) {
|
switch (GST_EVENT_TYPE (event)) {
|
||||||
case GST_EVENT_EOS:
|
case GST_EVENT_EOS:
|
||||||
{
|
{
|
||||||
GstBuffer *outbuf;
|
if (faac->handle) {
|
||||||
|
/* flush first */
|
||||||
if (!faac->handle)
|
GST_DEBUG_OBJECT (faac, "Pushing out remaining buffers because of EOS");
|
||||||
ret = FALSE;
|
gst_faac_push_buffers (faac, TRUE);
|
||||||
else
|
|
||||||
ret = TRUE;
|
|
||||||
|
|
||||||
/* flush first */
|
|
||||||
GST_DEBUG ("Pushing out remaining buffers because of EOS");
|
|
||||||
while (ret) {
|
|
||||||
if (gst_pad_alloc_buffer_and_set_caps (faac->srcpad,
|
|
||||||
GST_BUFFER_OFFSET_NONE, faac->bytes,
|
|
||||||
GST_PAD_CAPS (faac->srcpad), &outbuf) == GST_FLOW_OK) {
|
|
||||||
gint ret_size;
|
|
||||||
|
|
||||||
GST_DEBUG ("next_ts %" GST_TIME_FORMAT,
|
|
||||||
GST_TIME_ARGS (faac->next_ts));
|
|
||||||
|
|
||||||
if ((ret_size = faacEncEncode (faac->handle, NULL, 0,
|
|
||||||
GST_BUFFER_DATA (outbuf), faac->bytes)) > 0) {
|
|
||||||
GST_BUFFER_SIZE (outbuf) = ret_size;
|
|
||||||
GST_BUFFER_TIMESTAMP (outbuf) = faac->next_ts;
|
|
||||||
/* faac seems to always consume a fixed number of input samples,
|
|
||||||
* therefore extrapolate the duration from that value and the incoming
|
|
||||||
* bitrate */
|
|
||||||
GST_BUFFER_DURATION (outbuf) = gst_util_uint64_scale (faac->samples,
|
|
||||||
GST_SECOND, faac->channels * faac->samplerate);
|
|
||||||
if (GST_CLOCK_TIME_IS_VALID (faac->next_ts))
|
|
||||||
faac->next_ts += GST_BUFFER_DURATION (outbuf);
|
|
||||||
gst_pad_push (faac->srcpad, outbuf);
|
|
||||||
} else {
|
|
||||||
gst_buffer_unref (outbuf);
|
|
||||||
ret = FALSE;
|
|
||||||
}
|
|
||||||
} else
|
|
||||||
ret = FALSE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = gst_pad_event_default (pad, event);
|
ret = gst_pad_event_default (pad, event);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -534,9 +628,7 @@ static GstFlowReturn
|
||||||
gst_faac_chain (GstPad * pad, GstBuffer * inbuf)
|
gst_faac_chain (GstPad * pad, GstBuffer * inbuf)
|
||||||
{
|
{
|
||||||
GstFlowReturn result = GST_FLOW_OK;
|
GstFlowReturn result = GST_FLOW_OK;
|
||||||
GstBuffer *outbuf, *subbuf;
|
|
||||||
GstFaac *faac;
|
GstFaac *faac;
|
||||||
guint size, ret_size, in_size, frame_size;
|
|
||||||
|
|
||||||
faac = GST_FAAC (gst_pad_get_parent (pad));
|
faac = GST_FAAC (gst_pad_get_parent (pad));
|
||||||
|
|
||||||
|
@ -548,124 +640,13 @@ gst_faac_chain (GstPad * pad, GstBuffer * inbuf)
|
||||||
goto nego_failed;
|
goto nego_failed;
|
||||||
}
|
}
|
||||||
|
|
||||||
GST_DEBUG ("Got buffer time:%" GST_TIME_FORMAT " duration:%" GST_TIME_FORMAT,
|
GST_LOG_OBJECT (faac, "Got buffer time: %" GST_TIME_FORMAT " duration: %"
|
||||||
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)));
|
||||||
|
|
||||||
size = GST_BUFFER_SIZE (inbuf);
|
gst_adapter_push (faac->adapter, inbuf);
|
||||||
in_size = size;
|
|
||||||
if (faac->cache)
|
|
||||||
in_size += GST_BUFFER_SIZE (faac->cache);
|
|
||||||
frame_size = faac->samples * faac->bps;
|
|
||||||
|
|
||||||
while (1) {
|
result = gst_faac_push_buffers (faac, FALSE);
|
||||||
/* do we have enough data for one frame? */
|
|
||||||
if (in_size / faac->bps < faac->samples) {
|
|
||||||
if (in_size > size) {
|
|
||||||
GstBuffer *merge;
|
|
||||||
|
|
||||||
/* this is panic! we got a buffer, but still don't have enough
|
|
||||||
* data. Merge them and retry in the next cycle... */
|
|
||||||
merge = gst_buffer_merge (faac->cache, inbuf);
|
|
||||||
gst_buffer_unref (faac->cache);
|
|
||||||
gst_buffer_unref (inbuf);
|
|
||||||
faac->cache = merge;
|
|
||||||
} else if (in_size == size) {
|
|
||||||
/* this shouldn't happen, but still... */
|
|
||||||
faac->cache = inbuf;
|
|
||||||
} else if (in_size > 0) {
|
|
||||||
faac->cache = gst_buffer_create_sub (inbuf, size - in_size, in_size);
|
|
||||||
GST_BUFFER_DURATION (faac->cache) =
|
|
||||||
GST_BUFFER_DURATION (inbuf) * GST_BUFFER_SIZE (faac->cache) / size;
|
|
||||||
GST_BUFFER_TIMESTAMP (faac->cache) =
|
|
||||||
GST_BUFFER_TIMESTAMP (inbuf) + (GST_BUFFER_DURATION (inbuf) *
|
|
||||||
(size - in_size) / size);
|
|
||||||
gst_buffer_unref (inbuf);
|
|
||||||
} else {
|
|
||||||
gst_buffer_unref (inbuf);
|
|
||||||
}
|
|
||||||
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* create the frame */
|
|
||||||
if (in_size > size) {
|
|
||||||
GstBuffer *merge;
|
|
||||||
|
|
||||||
/* merge */
|
|
||||||
subbuf = gst_buffer_create_sub (inbuf, 0, frame_size - (in_size - size));
|
|
||||||
GST_BUFFER_DURATION (subbuf) =
|
|
||||||
GST_BUFFER_DURATION (inbuf) * GST_BUFFER_SIZE (subbuf) / size;
|
|
||||||
merge = gst_buffer_merge (faac->cache, subbuf);
|
|
||||||
gst_buffer_unref (faac->cache);
|
|
||||||
gst_buffer_unref (subbuf);
|
|
||||||
subbuf = merge;
|
|
||||||
faac->cache = NULL;
|
|
||||||
} else {
|
|
||||||
subbuf = gst_buffer_create_sub (inbuf, size - in_size, frame_size);
|
|
||||||
GST_BUFFER_DURATION (subbuf) =
|
|
||||||
GST_BUFFER_DURATION (inbuf) * GST_BUFFER_SIZE (subbuf) / size;
|
|
||||||
GST_BUFFER_TIMESTAMP (subbuf) =
|
|
||||||
GST_BUFFER_TIMESTAMP (inbuf) + (GST_BUFFER_DURATION (inbuf) *
|
|
||||||
(size - in_size) / size);
|
|
||||||
}
|
|
||||||
|
|
||||||
result =
|
|
||||||
gst_pad_alloc_buffer_and_set_caps (faac->srcpad, GST_BUFFER_OFFSET_NONE,
|
|
||||||
faac->bytes, GST_PAD_CAPS (faac->srcpad), &outbuf);
|
|
||||||
if (result != GST_FLOW_OK)
|
|
||||||
goto done;
|
|
||||||
|
|
||||||
if ((ret_size = faacEncEncode (faac->handle,
|
|
||||||
(gint32 *) GST_BUFFER_DATA (subbuf),
|
|
||||||
GST_BUFFER_SIZE (subbuf) / faac->bps,
|
|
||||||
GST_BUFFER_DATA (outbuf), faac->bytes)) < 0) {
|
|
||||||
GST_ELEMENT_ERROR (faac, LIBRARY, ENCODE, (NULL), (NULL));
|
|
||||||
gst_buffer_unref (inbuf);
|
|
||||||
gst_buffer_unref (subbuf);
|
|
||||||
result = GST_FLOW_ERROR;
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ret_size > 0) {
|
|
||||||
GST_BUFFER_SIZE (outbuf) = ret_size;
|
|
||||||
if (faac->cache_time != GST_CLOCK_TIME_NONE) {
|
|
||||||
GST_BUFFER_TIMESTAMP (outbuf) = faac->cache_time;
|
|
||||||
faac->cache_time = GST_CLOCK_TIME_NONE;
|
|
||||||
} else
|
|
||||||
GST_BUFFER_TIMESTAMP (outbuf) = GST_BUFFER_TIMESTAMP (subbuf);
|
|
||||||
GST_BUFFER_DURATION (outbuf) = GST_BUFFER_DURATION (subbuf);
|
|
||||||
if (faac->cache_duration) {
|
|
||||||
GST_BUFFER_DURATION (outbuf) += faac->cache_duration;
|
|
||||||
faac->cache_duration = 0;
|
|
||||||
}
|
|
||||||
/* Store the value of the next expected timestamp to output
|
|
||||||
* This is required in order to output the trailing encoded packets
|
|
||||||
* at EOS with proper timestamps and duration. */
|
|
||||||
faac->next_ts =
|
|
||||||
GST_BUFFER_TIMESTAMP (outbuf) + GST_BUFFER_DURATION (outbuf);
|
|
||||||
GST_DEBUG ("Pushing out buffer time:%" GST_TIME_FORMAT " duration:%"
|
|
||||||
GST_TIME_FORMAT, GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (outbuf)),
|
|
||||||
GST_TIME_ARGS (GST_BUFFER_DURATION (outbuf)));
|
|
||||||
result = gst_pad_push (faac->srcpad, outbuf);
|
|
||||||
} else {
|
|
||||||
/* FIXME: what I'm doing here isn't fully correct, but there
|
|
||||||
* really isn't a better way yet.
|
|
||||||
* Problem is that libfaac caches buffers (for encoding
|
|
||||||
* purposes), so the timestamp of the outgoing buffer isn't
|
|
||||||
* the same as the timestamp of the data that I pushed in.
|
|
||||||
* However, I don't know the delay between those two so I
|
|
||||||
* cannot really say aything about it. This is a bad guess. */
|
|
||||||
|
|
||||||
gst_buffer_unref (outbuf);
|
|
||||||
if (faac->cache_time != GST_CLOCK_TIME_NONE)
|
|
||||||
faac->cache_time = GST_BUFFER_TIMESTAMP (subbuf);
|
|
||||||
faac->cache_duration += GST_BUFFER_DURATION (subbuf);
|
|
||||||
}
|
|
||||||
|
|
||||||
in_size -= frame_size;
|
|
||||||
gst_buffer_unref (subbuf);
|
|
||||||
}
|
|
||||||
|
|
||||||
done:
|
done:
|
||||||
gst_object_unref (faac);
|
gst_object_unref (faac);
|
||||||
|
@ -784,15 +765,10 @@ gst_faac_change_state (GstElement * element, GstStateChange transition)
|
||||||
faacEncClose (faac->handle);
|
faacEncClose (faac->handle);
|
||||||
faac->handle = NULL;
|
faac->handle = NULL;
|
||||||
}
|
}
|
||||||
if (faac->cache) {
|
gst_adapter_clear (faac->adapter);
|
||||||
gst_buffer_unref (faac->cache);
|
faac->offset = 0;
|
||||||
faac->cache = NULL;
|
|
||||||
}
|
|
||||||
faac->cache_time = GST_CLOCK_TIME_NONE;
|
|
||||||
faac->cache_duration = 0;
|
|
||||||
faac->samplerate = -1;
|
faac->samplerate = -1;
|
||||||
faac->channels = -1;
|
faac->channels = -1;
|
||||||
faac->next_ts = GST_CLOCK_TIME_NONE;
|
|
||||||
GST_OBJECT_UNLOCK (faac);
|
GST_OBJECT_UNLOCK (faac);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,6 +21,8 @@
|
||||||
#define __GST_FAAC_H__
|
#define __GST_FAAC_H__
|
||||||
|
|
||||||
#include <gst/gst.h>
|
#include <gst/gst.h>
|
||||||
|
#include <gst/base/gstadapter.h>
|
||||||
|
#include <gst/audio/audio.h>
|
||||||
#include <faac.h>
|
#include <faac.h>
|
||||||
|
|
||||||
G_BEGIN_DECLS
|
G_BEGIN_DECLS
|
||||||
|
@ -60,11 +62,9 @@ typedef struct _GstFaac {
|
||||||
faacEncHandle handle;
|
faacEncHandle handle;
|
||||||
|
|
||||||
/* cache of the input */
|
/* cache of the input */
|
||||||
GstBuffer *cache;
|
GstAdapter *adapter;
|
||||||
guint64 cache_time, cache_duration;
|
/* offset of data to be encoded next */
|
||||||
|
guint offset;
|
||||||
/* Expected timestamp of the next buffer to output */
|
|
||||||
GstClockTime next_ts;
|
|
||||||
} GstFaac;
|
} GstFaac;
|
||||||
|
|
||||||
typedef struct _GstFaacClass {
|
typedef struct _GstFaacClass {
|
||||||
|
|
Loading…
Reference in a new issue