mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-02-22 22:16:22 +00:00
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:
parent
e3f171704d
commit
2e082a9640
3 changed files with 123 additions and 117 deletions
12
ChangeLog
12
ChangeLog
|
@ -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),
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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 {
|
||||
|
|
Loading…
Reference in a new issue