ext/a52dec/gsta52dec.*: Do something useful with timestamps. Make chain-based (since there's really no reason to be l...

Original commit message from CVS:
* ext/a52dec/gsta52dec.c: (gst_a52dec_init),
(gst_a52dec_handle_event), (gst_a52dec_update_streaminfo),
(gst_a52dec_handle_frame), (gst_a52dec_chain),
(gst_a52dec_change_state), (plugin_init):
* ext/a52dec/gsta52dec.h:
Do something useful with timestamps. Make chain-based (since
there's really no reason to be loopbased).
* gst/avi/gstavidemux.c: (gst_avi_demux_process_next_entry):
Update current_byte/frame correctly.
This commit is contained in:
Ronald S. Bultje 2004-12-06 10:28:13 +00:00
parent e3f171704d
commit 2e082a9640
3 changed files with 123 additions and 117 deletions

View file

@ -1,3 +1,15 @@
2004-12-06 Ronald S. Bultje <rbultje@ronald.bitfreak.net>
* ext/a52dec/gsta52dec.c: (gst_a52dec_init),
(gst_a52dec_handle_event), (gst_a52dec_update_streaminfo),
(gst_a52dec_handle_frame), (gst_a52dec_chain),
(gst_a52dec_change_state), (plugin_init):
* ext/a52dec/gsta52dec.h:
Do something useful with timestamps. Make chain-based (since
there's really no reason to be loopbased).
* gst/avi/gstavidemux.c: (gst_avi_demux_process_next_entry):
Update current_byte/frame correctly.
2004-12-04 Ronald S. Bultje <rbultje@ronald.bitfreak.net>
* gst/apetag/apedemux.c: (gst_ape_demux_parse_tags),

View file

@ -63,10 +63,6 @@ enum
ARG_DRC
};
/*
* "audio/a52", "audio/x-a52" and "audio/ac3" should not be used (deprecated names)
* Only use "audio/x-ac3" in new code.
*/
static GstStaticPadTemplate sink_factory = GST_STATIC_PAD_TEMPLATE ("sink",
GST_PAD_SINK,
GST_PAD_ALWAYS,
@ -87,7 +83,7 @@ static void gst_a52dec_base_init (gpointer g_class);
static void gst_a52dec_class_init (GstA52DecClass * klass);
static void gst_a52dec_init (GstA52Dec * a52dec);
static void gst_a52dec_loop (GstElement * element);
static void gst_a52dec_chain (GstPad * pad, GstData * data);
static GstElementStateReturn gst_a52dec_change_state (GstElement * element);
static void gst_a52dec_set_property (GObject * object, guint prop_id,
@ -160,12 +156,14 @@ gst_a52dec_class_init (GstA52DecClass * klass)
static void
gst_a52dec_init (GstA52Dec * a52dec)
{
GST_FLAG_SET (GST_ELEMENT (a52dec), GST_ELEMENT_EVENT_AWARE);
/* create the sink and src pads */
a52dec->sinkpad =
gst_pad_new_from_template (gst_element_get_pad_template (GST_ELEMENT
(a52dec), "sink"), "sink");
gst_pad_set_chain_function (a52dec->sinkpad, gst_a52dec_chain);
gst_element_add_pad (GST_ELEMENT (a52dec), a52dec->sinkpad);
gst_element_set_loop_function ((GstElement *) a52dec, gst_a52dec_loop);
a52dec->srcpad =
gst_pad_new_from_template (gst_element_get_pad_template (GST_ELEMENT
@ -173,8 +171,8 @@ gst_a52dec_init (GstA52Dec * a52dec)
gst_pad_use_explicit_caps (a52dec->srcpad);
gst_element_add_pad (GST_ELEMENT (a52dec), a52dec->srcpad);
GST_FLAG_SET (GST_ELEMENT (a52dec), GST_ELEMENT_EVENT_AWARE);
a52dec->dynamic_range_compression = FALSE;
a52dec->cache = NULL;
}
static int
@ -289,8 +287,6 @@ gst_a52dec_push (GstPad * srcpad, int flags, sample_t * samples,
return 0;
}
/* END modified a52dec conversion code */
static gboolean
gst_a52dec_reneg (GstPad * pad)
{
@ -318,28 +314,32 @@ gst_a52dec_reneg (GstPad * pad)
}
static void
gst_a52dec_handle_event (GstA52Dec * a52dec)
gst_a52dec_handle_event (GstA52Dec * a52dec, GstEvent * event)
{
guint32 remaining;
GstEvent *event;
gst_bytestream_get_status (a52dec->bs, &remaining, &event);
if (!event) {
g_warning ("a52dec: no bytestream event");
return;
}
GST_LOG ("Handling event of type %d timestamp %llu", GST_EVENT_TYPE (event),
GST_EVENT_TIMESTAMP (event));
switch (GST_EVENT_TYPE (event)) {
case GST_EVENT_DISCONTINUOUS:
case GST_EVENT_DISCONTINUOUS:{
gint64 val;
if (!gst_event_discont_get_value (event, GST_FORMAT_TIME, &val)) {
GST_WARNING ("No time discont value in event %p", event);
} else {
a52dec->time = val;
}
}
/* fall-through */
case GST_EVENT_FLUSH:
gst_bytestream_flush_fast (a52dec->bs, remaining);
if (a52dec->cache) {
gst_buffer_unref (a52dec->cache);
a52dec->cache = NULL;
}
break;
default:
break;
}
gst_pad_event_default (a52dec->sinkpad, event);
}
@ -354,56 +354,18 @@ gst_a52dec_update_streaminfo (GstA52Dec * a52dec)
GST_TAG_BITRATE, (guint) a52dec->bit_rate, NULL);
gst_element_found_tags_for_pad (GST_ELEMENT (a52dec),
GST_PAD (a52dec->srcpad), a52dec->current_ts, taglist);
GST_PAD (a52dec->srcpad), a52dec->time, taglist);
}
static void
gst_a52dec_loop (GstElement * element)
static gboolean
gst_a52dec_handle_frame (GstA52Dec * a52dec, guint8 * data,
guint length, gint flags, gint sample_rate, gint bit_rate)
{
GstA52Dec *a52dec;
guint8 *data;
int i, length, flags, sample_rate, bit_rate;
int channels;
GstBuffer *buf = NULL;
guint32 got_bytes;
gboolean need_reneg;
GstClockTime timestamp = 0;
a52dec = GST_A52DEC (element);
/* find and read header */
bit_rate = a52dec->bit_rate;
sample_rate = a52dec->sample_rate;
flags = 0;
do {
gint skipped_bytes = 0;
while (skipped_bytes < 3840) {
got_bytes = gst_bytestream_peek_bytes (a52dec->bs, &data, 7);
if (got_bytes < 7) {
gst_a52dec_handle_event (a52dec);
return;
}
length = a52_syncinfo (data, &flags, &sample_rate, &bit_rate);
if (length == 0) {
/* slide window to next 7 bytesa */
gst_bytestream_flush_fast (a52dec->bs, 1);
skipped_bytes++;
GST_DEBUG ("Skipped");
} else {
GST_DEBUG ("Sync: %d", length);
break;
}
}
if (skipped_bytes >= 3840) {
GST_LOG ("Sync failed");
return;
}
}
while (0);
gint channels, i;
gboolean need_reneg = FALSE;
/* update stream information, renegotiate or re-streaminfo if needed */
need_reneg = FALSE;
if (a52dec->sample_rate != sample_rate) {
need_reneg = TRUE;
a52dec->sample_rate = sample_rate;
@ -418,69 +380,109 @@ gst_a52dec_loop (GstElement * element)
gst_a52dec_update_streaminfo (a52dec);
}
/* read the header + rest of frame */
got_bytes = gst_bytestream_read (a52dec->bs, &buf, length);
if (got_bytes < length) {
gst_a52dec_handle_event (a52dec);
return;
}
data = GST_BUFFER_DATA (buf);
timestamp = gst_bytestream_get_timestamp (a52dec->bs);
if (GST_CLOCK_TIME_IS_VALID (timestamp)) {
if (timestamp == a52dec->last_ts) {
timestamp = a52dec->current_ts;
} else {
a52dec->last_ts = timestamp;
}
}
/* process */
flags = a52dec->request_channels; /* | A52_ADJUST_LEVEL; */
a52dec->level = 1;
if (a52_frame (a52dec->state, data, &flags, &a52dec->level, a52dec->bias)) {
GST_WARNING ("a52_frame error");
goto end;
return TRUE;
}
channels = flags & (A52_CHANNEL_MASK | A52_LFE);
if (a52dec->using_channels != channels) {
need_reneg = TRUE;
a52dec->using_channels = channels;
}
/* negotiate if required */
if (need_reneg == TRUE) {
GST_DEBUG ("a52dec reneg: sample_rate:%d stream_chans:%d using_chans:%d\n",
a52dec->sample_rate, a52dec->stream_channels, a52dec->using_channels);
if (!gst_a52dec_reneg (a52dec->srcpad))
goto end;
if (!gst_a52dec_reneg (a52dec->srcpad)) {
GST_ELEMENT_ERROR (a52dec, CORE, NEGOTIATION, (NULL), (NULL));
return FALSE;
}
}
if (a52dec->dynamic_range_compression == FALSE) {
a52_dynrng (a52dec->state, NULL, NULL);
}
/* each frame consists of 6 blocks */
for (i = 0; i < 6; i++) {
if (a52_block (a52dec->state)) {
GST_WARNING ("a52_block error %d", i);
continue;
}
/* push on */
if (gst_a52dec_push (a52dec->srcpad, a52dec->using_channels,
a52dec->samples, timestamp)) {
GST_WARNING ("a52dec push error");
} else {
/* push on */
gst_a52dec_push (a52dec->srcpad, a52dec->using_channels,
a52dec->samples, a52dec->time);
}
a52dec->time += 256 * GST_SECOND / a52dec->sample_rate;
}
if (i % 2)
timestamp += 256 * GST_SECOND / a52dec->sample_rate;
return TRUE;
}
static void
gst_a52dec_chain (GstPad * pad, GstData * _data)
{
GstA52Dec *a52dec = GST_A52DEC (gst_pad_get_parent (pad));
GstBuffer *buf;
guint8 *data;
guint size;
gint length = 0, flags, sample_rate, bit_rate;
/* event handling */
if (GST_IS_EVENT (_data)) {
gst_a52dec_handle_event (a52dec, GST_EVENT (_data));
return;
}
/* merge with cache, if any. Also make sure timestamps match */
buf = GST_BUFFER (_data);
if (GST_BUFFER_TIMESTAMP_IS_VALID (buf)) {
a52dec->time = GST_BUFFER_TIMESTAMP (buf);
}
if (a52dec->cache) {
buf = gst_buffer_join (a52dec->cache, buf);
a52dec->cache = NULL;
}
data = GST_BUFFER_DATA (buf);
size = GST_BUFFER_SIZE (buf);
/* find and read header */
bit_rate = a52dec->bit_rate;
sample_rate = a52dec->sample_rate;
flags = 0;
while (size >= 7) {
length = a52_syncinfo (data, &flags, &sample_rate, &bit_rate);
if (length == 0) {
/* no sync */
data++;
size--;
} else if (length <= size) {
GST_DEBUG ("Sync: %d", length);
if (!gst_a52dec_handle_frame (a52dec, data,
length, flags, sample_rate, bit_rate)) {
size = 0;
break;
}
size -= length;
data += length;
} else {
/* not enough data */
GST_LOG ("Not enough data available");
break;
}
}
a52dec->current_ts = timestamp;
end:
/* keep cache */
if (length == 0) {
GST_LOG ("No sync found");
}
if (size > 0) {
a52dec->cache = gst_buffer_create_sub (buf,
GST_BUFFER_SIZE (buf) - size, size);
}
gst_buffer_unref (buf);
}
@ -493,7 +495,6 @@ gst_a52dec_change_state (GstElement * element)
switch (GST_STATE_TRANSITION (element)) {
case GST_STATE_NULL_TO_READY:
a52dec->bs = gst_bytestream_new (a52dec->sinkpad);
cpuflags = gst_cpu_get_flags ();
if (cpuflags & GST_CPU_FLAG_MMX)
a52_cpuflags |= MM_ACCEL_X86_MMX;
@ -513,20 +514,18 @@ gst_a52dec_change_state (GstElement * element)
a52dec->using_channels = A52_CHANNEL;
a52dec->level = 1;
a52dec->bias = 0;
a52dec->last_ts = 0;
a52dec->current_ts = 0;
a52dec->last_timestamp = 0;
a52dec->last_diff = 0;
a52dec->time = 0;
break;
case GST_STATE_PAUSED_TO_PLAYING:
break;
case GST_STATE_PLAYING_TO_PAUSED:
break;
case GST_STATE_PAUSED_TO_READY:
gst_bytestream_destroy (a52dec->bs);
a52dec->bs = NULL;
a52dec->samples = NULL;
if (a52dec->cache) {
gst_buffer_unref (a52dec->cache);
a52dec->cache = NULL;
}
break;
case GST_STATE_READY_TO_NULL:
a52_free (a52dec->state);
@ -586,7 +585,7 @@ static gboolean
plugin_init (GstPlugin * plugin)
{
if (!gst_library_load ("gstbytestream") || !gst_library_load ("gstaudio"))
if (!gst_library_load ("gstaudio"))
return FALSE;
if (!gst_element_register (plugin, "a52dec", GST_RANK_PRIMARY,

View file

@ -58,13 +58,8 @@ struct _GstA52Dec {
sample_t *samples;
a52_state_t *state;
GstByteStream *bs;
GstClockTime last_ts;
GstClockTime current_ts;
GstClockTime last_timestamp;
GstClockTimeDiff last_diff;
GstBuffer *cache;
GstClockTime time;
};
struct _GstA52DecClass {