ext/mad/gstmad.*: Implement buffer clipping and use GST_BOILERPLATE instead of manual
Original commit message from CVS: * ext/mad/gstmad.c: (_do_init), (gst_mad_init), (index_seek), (normal_seek), (gst_mad_sink_event), (clip_outgoing_buffer), (gst_mad_chain), (gst_mad_change_state): * ext/mad/gstmad.h: Implement buffer clipping and use GST_BOILERPLATE instead of manual GType magic. Part one of bug #308312.
This commit is contained in:
parent
c8f8ef9390
commit
68bbfd4fd3
@ -1,3 +1,12 @@
|
|||||||
|
2007-07-13 Sebastian Dröge <slomo@circular-chaos.org>
|
||||||
|
|
||||||
|
* ext/mad/gstmad.c: (_do_init), (gst_mad_init), (index_seek),
|
||||||
|
(normal_seek), (gst_mad_sink_event), (clip_outgoing_buffer),
|
||||||
|
(gst_mad_chain), (gst_mad_change_state):
|
||||||
|
* ext/mad/gstmad.h:
|
||||||
|
Implement buffer clipping and use GST_BOILERPLATE instead of manual
|
||||||
|
GType magic. Part one of bug #308312.
|
||||||
|
|
||||||
2007-07-12 Stefan Kost <ensonic@users.sf.net>
|
2007-07-12 Stefan Kost <ensonic@users.sf.net>
|
||||||
|
|
||||||
* configure.ac:
|
* configure.ac:
|
||||||
|
116
ext/mad/gstmad.c
116
ext/mad/gstmad.c
@ -23,6 +23,7 @@
|
|||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include "gstmad.h"
|
#include "gstmad.h"
|
||||||
|
#include <gst/audio/audio.h>
|
||||||
|
|
||||||
|
|
||||||
/* elementfactory information */
|
/* elementfactory information */
|
||||||
@ -70,7 +71,7 @@ GST_STATIC_PAD_TEMPLATE ("sink",
|
|||||||
|
|
||||||
static void gst_mad_base_init (gpointer g_class);
|
static void gst_mad_base_init (gpointer g_class);
|
||||||
static void gst_mad_class_init (GstMadClass * klass);
|
static void gst_mad_class_init (GstMadClass * klass);
|
||||||
static void gst_mad_init (GstMad * mad);
|
static void gst_mad_init (GstMad * mad, GstMadClass * klass);
|
||||||
static void gst_mad_dispose (GObject * object);
|
static void gst_mad_dispose (GObject * object);
|
||||||
|
|
||||||
static void gst_mad_set_property (GObject * object, guint prop_id,
|
static void gst_mad_set_property (GObject * object, guint prop_id,
|
||||||
@ -97,34 +98,14 @@ static GstStateChangeReturn gst_mad_change_state (GstElement * element,
|
|||||||
static void gst_mad_set_index (GstElement * element, GstIndex * index);
|
static void gst_mad_set_index (GstElement * element, GstIndex * index);
|
||||||
static GstIndex *gst_mad_get_index (GstElement * element);
|
static GstIndex *gst_mad_get_index (GstElement * element);
|
||||||
|
|
||||||
|
static void
|
||||||
static GstElementClass *parent_class = NULL;
|
_do_init (GType type)
|
||||||
|
|
||||||
GType
|
|
||||||
gst_mad_get_type (void)
|
|
||||||
{
|
{
|
||||||
static GType mad_type = 0;
|
|
||||||
|
|
||||||
if (!mad_type) {
|
|
||||||
static const GTypeInfo mad_info = {
|
|
||||||
sizeof (GstMadClass),
|
|
||||||
gst_mad_base_init,
|
|
||||||
NULL,
|
|
||||||
(GClassInitFunc) gst_mad_class_init,
|
|
||||||
NULL,
|
|
||||||
NULL,
|
|
||||||
sizeof (GstMad),
|
|
||||||
0,
|
|
||||||
(GInstanceInitFunc) gst_mad_init,
|
|
||||||
};
|
|
||||||
|
|
||||||
mad_type =
|
|
||||||
g_type_register_static (GST_TYPE_ELEMENT, "GstMad", &mad_info, 0);
|
|
||||||
}
|
|
||||||
GST_DEBUG_CATEGORY_INIT (mad_debug, "mad", 0, "mad mp3 decoding");
|
GST_DEBUG_CATEGORY_INIT (mad_debug, "mad", 0, "mad mp3 decoding");
|
||||||
return mad_type;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GST_BOILERPLATE_FULL (GstMad, gst_mad, GstElement, GST_TYPE_ELEMENT, _do_init);
|
||||||
|
|
||||||
#define GST_TYPE_MAD_LAYER (gst_mad_layer_get_type())
|
#define GST_TYPE_MAD_LAYER (gst_mad_layer_get_type())
|
||||||
G_GNUC_UNUSED static GType
|
G_GNUC_UNUSED static GType
|
||||||
gst_mad_layer_get_type (void)
|
gst_mad_layer_get_type (void)
|
||||||
@ -239,7 +220,7 @@ gst_mad_class_init (GstMadClass * klass)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gst_mad_init (GstMad * mad)
|
gst_mad_init (GstMad * mad, GstMadClass * klass)
|
||||||
{
|
{
|
||||||
GstPadTemplate *template;
|
GstPadTemplate *template;
|
||||||
|
|
||||||
@ -273,6 +254,7 @@ gst_mad_init (GstMad * mad)
|
|||||||
mad->vbr_rate = 0;
|
mad->vbr_rate = 0;
|
||||||
mad->restart = TRUE;
|
mad->restart = TRUE;
|
||||||
mad->segment_start = 0;
|
mad->segment_start = 0;
|
||||||
|
gst_segment_init (&mad->segment, GST_FORMAT_TIME);
|
||||||
mad->header.mode = -1;
|
mad->header.mode = -1;
|
||||||
mad->header.emphasis = -1;
|
mad->header.emphasis = -1;
|
||||||
mad->tags = NULL;
|
mad->tags = NULL;
|
||||||
@ -621,6 +603,13 @@ index_seek (GstMad * mad, GstPad * pad, GstEvent * event)
|
|||||||
gst_event_parse_seek (event, &rate, &format, &flags,
|
gst_event_parse_seek (event, &rate, &format, &flags,
|
||||||
&cur_type, &cur, &stop_type, &stop);
|
&cur_type, &cur, &stop_type, &stop);
|
||||||
|
|
||||||
|
if (format == GST_FORMAT_TIME) {
|
||||||
|
gst_segment_set_seek (&mad->segment, rate, format, flags, cur_type,
|
||||||
|
cur, stop_type, stop, NULL);
|
||||||
|
} else {
|
||||||
|
gst_segment_init (&mad->segment, GST_FORMAT_UNDEFINED);
|
||||||
|
}
|
||||||
|
|
||||||
entry = gst_index_get_assoc_entry (mad->index, mad->index_id,
|
entry = gst_index_get_assoc_entry (mad->index, mad->index_id,
|
||||||
GST_INDEX_LOOKUP_BEFORE, 0, format, cur);
|
GST_INDEX_LOOKUP_BEFORE, 0, format, cur);
|
||||||
|
|
||||||
@ -695,6 +684,9 @@ normal_seek (GstMad * mad, GstPad * pad, GstEvent * event)
|
|||||||
time_stop = stop;
|
time_stop = stop;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gst_segment_set_seek (&mad->segment, rate, GST_FORMAT_TIME, flags, cur_type,
|
||||||
|
time_cur, stop_type, time_stop, NULL);
|
||||||
|
|
||||||
GST_DEBUG ("seek to time %" GST_TIME_FORMAT "-%" GST_TIME_FORMAT,
|
GST_DEBUG ("seek to time %" GST_TIME_FORMAT "-%" GST_TIME_FORMAT,
|
||||||
GST_TIME_ARGS (time_cur), GST_TIME_ARGS (time_stop));
|
GST_TIME_ARGS (time_cur), GST_TIME_ARGS (time_stop));
|
||||||
|
|
||||||
@ -944,9 +936,12 @@ gst_mad_sink_event (GstPad * pad, GstEvent * event)
|
|||||||
switch (GST_EVENT_TYPE (event)) {
|
switch (GST_EVENT_TYPE (event)) {
|
||||||
case GST_EVENT_NEWSEGMENT:{
|
case GST_EVENT_NEWSEGMENT:{
|
||||||
GstFormat format;
|
GstFormat format;
|
||||||
|
gboolean update;
|
||||||
|
gdouble rate, applied_rate;
|
||||||
|
gint64 start, stop, pos;
|
||||||
|
|
||||||
gst_event_parse_new_segment (event, NULL, NULL, &format, NULL, NULL,
|
gst_event_parse_new_segment_full (event, &update, &rate, &applied_rate,
|
||||||
NULL);
|
&format, &start, &stop, &pos);
|
||||||
|
|
||||||
if (format == GST_FORMAT_TIME) {
|
if (format == GST_FORMAT_TIME) {
|
||||||
/* FIXME: is this really correct? */
|
/* FIXME: is this really correct? */
|
||||||
@ -955,6 +950,8 @@ gst_mad_sink_event (GstPad * pad, GstEvent * event)
|
|||||||
/* we don't need to restart when we get here */
|
/* we don't need to restart when we get here */
|
||||||
mad->restart = FALSE;
|
mad->restart = FALSE;
|
||||||
mad->framed = TRUE;
|
mad->framed = TRUE;
|
||||||
|
gst_segment_set_newsegment_full (&mad->segment, update, rate,
|
||||||
|
applied_rate, GST_FORMAT_TIME, start, stop, pos);
|
||||||
} else {
|
} else {
|
||||||
GST_DEBUG ("dropping newsegment event in format %s",
|
GST_DEBUG ("dropping newsegment event in format %s",
|
||||||
gst_format_get_name (format));
|
gst_format_get_name (format));
|
||||||
@ -1226,6 +1223,51 @@ gst_mad_check_caps_reset (GstMad * mad)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
clips buffer to currently configured segment. Returns FALSE if the buffer
|
||||||
|
has to be dropped.
|
||||||
|
*/
|
||||||
|
static gboolean
|
||||||
|
clip_outgoing_buffer (GstMad * mad, GstBuffer * buffer)
|
||||||
|
{
|
||||||
|
gint64 start, stop, cstart, cstop, diff;
|
||||||
|
gboolean res = TRUE;
|
||||||
|
|
||||||
|
if (mad->segment.format != GST_FORMAT_TIME)
|
||||||
|
goto beach;
|
||||||
|
|
||||||
|
start = GST_BUFFER_TIMESTAMP (buffer);
|
||||||
|
stop = start + GST_BUFFER_DURATION (buffer);
|
||||||
|
|
||||||
|
if (gst_segment_clip (&mad->segment, GST_FORMAT_TIME,
|
||||||
|
start, stop, &cstart, &cstop)) {
|
||||||
|
diff = cstart - start;
|
||||||
|
if (diff > 0) {
|
||||||
|
GST_BUFFER_TIMESTAMP (buffer) = cstart;
|
||||||
|
GST_BUFFER_DURATION (buffer) -= diff;
|
||||||
|
|
||||||
|
/* time->frames->bytes */
|
||||||
|
diff = 4 * mad->channels * GST_CLOCK_TIME_TO_FRAMES (diff, mad->rate);
|
||||||
|
GST_BUFFER_DATA (buffer) += diff;
|
||||||
|
GST_BUFFER_SIZE (buffer) -= diff;
|
||||||
|
}
|
||||||
|
diff = cstop - stop;
|
||||||
|
if (diff > 0) {
|
||||||
|
GST_BUFFER_DURATION (buffer) -= diff;
|
||||||
|
/* time->frames->bytes */
|
||||||
|
diff = 4 * mad->channels * GST_CLOCK_TIME_TO_FRAMES (diff, mad->rate);
|
||||||
|
/* update size */
|
||||||
|
GST_BUFFER_SIZE (buffer) -= diff;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
GST_DEBUG_OBJECT (mad, "buffer is outside configured segment");
|
||||||
|
res = FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
beach:
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
static GstFlowReturn
|
static GstFlowReturn
|
||||||
gst_mad_chain (GstPad * pad, GstBuffer * buffer)
|
gst_mad_chain (GstPad * pad, GstBuffer * buffer)
|
||||||
{
|
{
|
||||||
@ -1516,6 +1558,9 @@ gst_mad_chain (GstPad * pad, GstBuffer * buffer)
|
|||||||
GST_DEBUG ("Sending NEWSEGMENT event, start=%" GST_TIME_FORMAT,
|
GST_DEBUG ("Sending NEWSEGMENT event, start=%" GST_TIME_FORMAT,
|
||||||
GST_TIME_ARGS (start));
|
GST_TIME_ARGS (start));
|
||||||
|
|
||||||
|
gst_segment_set_newsegment (&mad->segment, FALSE, 1.0,
|
||||||
|
GST_FORMAT_TIME, start, GST_CLOCK_TIME_NONE, start);
|
||||||
|
|
||||||
gst_pad_push_event (mad->srcpad,
|
gst_pad_push_event (mad->srcpad,
|
||||||
gst_event_new_new_segment (FALSE, 1.0, GST_FORMAT_TIME,
|
gst_event_new_new_segment (FALSE, 1.0, GST_FORMAT_TIME,
|
||||||
start, GST_CLOCK_TIME_NONE, start));
|
start, GST_CLOCK_TIME_NONE, start));
|
||||||
@ -1563,11 +1608,24 @@ gst_mad_chain (GstPad * pad, GstBuffer * buffer)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (clip_outgoing_buffer (mad, outbuffer)) {
|
||||||
|
GST_LOG_OBJECT (mad,
|
||||||
|
"pushing buffer, off=%" G_GUINT64_FORMAT ", ts=%" GST_TIME_FORMAT,
|
||||||
|
GST_BUFFER_OFFSET (outbuffer),
|
||||||
|
GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (outbuffer)));
|
||||||
|
mad->segment.last_stop = GST_BUFFER_TIMESTAMP (outbuffer);
|
||||||
result = gst_pad_push (mad->srcpad, outbuffer);
|
result = gst_pad_push (mad->srcpad, outbuffer);
|
||||||
if (result != GST_FLOW_OK) {
|
if (result != GST_FLOW_OK) {
|
||||||
/* Head for the exit, dropping samples as we go */
|
/* Head for the exit, dropping samples as we go */
|
||||||
goto_exit = TRUE;
|
goto_exit = TRUE;
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
GST_LOG_OBJECT (mad, "Dropping buffer"
|
||||||
|
", off=%" G_GUINT64_FORMAT ", ts=%" GST_TIME_FORMAT,
|
||||||
|
GST_BUFFER_OFFSET (outbuffer),
|
||||||
|
GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (outbuffer)));
|
||||||
|
gst_buffer_unref (outbuffer);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
skip_frame:
|
skip_frame:
|
||||||
@ -1639,7 +1697,7 @@ gst_mad_change_state (GstElement * element, GstStateChange transition)
|
|||||||
mad->caps_set = FALSE;
|
mad->caps_set = FALSE;
|
||||||
mad->times_pending = mad->pending_rate = mad->pending_channels = 0;
|
mad->times_pending = mad->pending_rate = mad->pending_channels = 0;
|
||||||
mad->vbr_average = 0;
|
mad->vbr_average = 0;
|
||||||
mad->segment_start = 0;
|
gst_segment_init (&mad->segment, GST_FORMAT_TIME);
|
||||||
mad->new_header = TRUE;
|
mad->new_header = TRUE;
|
||||||
mad->framed = FALSE;
|
mad->framed = FALSE;
|
||||||
mad->framecount = 0;
|
mad->framecount = 0;
|
||||||
|
@ -64,6 +64,7 @@ struct _GstMad
|
|||||||
gboolean in_error; /* set when mad's in an error state */
|
gboolean in_error; /* set when mad's in an error state */
|
||||||
gboolean restart;
|
gboolean restart;
|
||||||
guint64 segment_start;
|
guint64 segment_start;
|
||||||
|
GstSegment segment;
|
||||||
gboolean need_newsegment;
|
gboolean need_newsegment;
|
||||||
|
|
||||||
/* info */
|
/* info */
|
||||||
|
Loading…
x
Reference in New Issue
Block a user