gst/dvdlpcmdec/gstdvdlpcmdec.*: Implement all sample rates.

Original commit message from CVS:
* gst/dvdlpcmdec/gstdvdlpcmdec.c: (gst_dvdlpcm_reset),
(update_timestamps), (parse_header), (gst_dvdlpcmdec_chain_dvd),
(gst_dvdlpcmdec_chain_raw), (dvdlpcmdec_sink_event):
* gst/dvdlpcmdec/gstdvdlpcmdec.h:
Implement all sample rates.
Implement sample permutation a little smarter avoiding a memcpy.
Fix timestamps, use segments, fix seeking.
This commit is contained in:
Wim Taymans 2007-02-28 15:52:23 +00:00
parent 549ec77758
commit d8659dad60
3 changed files with 69 additions and 40 deletions

View File

@ -1,3 +1,13 @@
2007-02-28 Wim Taymans <wim@fluendo.com>
* gst/dvdlpcmdec/gstdvdlpcmdec.c: (gst_dvdlpcm_reset),
(update_timestamps), (parse_header), (gst_dvdlpcmdec_chain_dvd),
(gst_dvdlpcmdec_chain_raw), (dvdlpcmdec_sink_event):
* gst/dvdlpcmdec/gstdvdlpcmdec.h:
Implement all sample rates.
Implement sample permutation a little smarter avoiding a memcpy.
Fix timestamps, use segments, fix seeking.
2007-02-28 Wim Taymans <wim@fluendo.com> 2007-02-28 Wim Taymans <wim@fluendo.com>
* docs/plugins/Makefile.am: * docs/plugins/Makefile.am:

View File

@ -155,8 +155,7 @@ gst_dvdlpcm_reset (GstDvdLpcmDec * dvdlpcmdec)
dvdlpcmdec->header = 0; dvdlpcmdec->header = 0;
GST_LOG_OBJECT (dvdlpcmdec, "Setting NULL caps on src pad"); gst_segment_init (&dvdlpcmdec->segment, GST_FORMAT_UNDEFINED);
gst_pad_set_caps (dvdlpcmdec->srcpad, NULL);
} }
static void static void
@ -276,7 +275,7 @@ update_timestamps (GstDvdLpcmDec * dvdlpcmdec, GstBuffer * buf, int samples)
take_buf_ts = TRUE; take_buf_ts = TRUE;
} }
} else if (!GST_CLOCK_TIME_IS_VALID (dvdlpcmdec->timestamp)) { } else if (!GST_CLOCK_TIME_IS_VALID (dvdlpcmdec->timestamp)) {
dvdlpcmdec->timestamp = dvdlpcmdec->segment_start; dvdlpcmdec->timestamp = 0;
} }
if (take_buf_ts) { if (take_buf_ts) {
@ -318,11 +317,21 @@ parse_header (GstDvdLpcmDec * dec, guint32 header)
break; break;
} }
/* Only two sample rates supported */ /* Only four sample rates supported */
if (header & 0x1000) switch (header & 0x3000) {
dec->rate = 96000; case 0x0000:
else
dec->rate = 48000; dec->rate = 48000;
break;
case 0x1000:
dec->rate = 96000;
break;
case 0x2000:
dec->rate = 44100;
break;
case 0x3000:
dec->rate = 32000;
break;
}
/* And, of course, the number of channels (up to 8) */ /* And, of course, the number of channels (up to 8) */
dec->channels = ((header >> 8) & 0x7) + 1; dec->channels = ((header >> 8) & 0x7) + 1;
@ -426,7 +435,7 @@ gst_dvdlpcmdec_chain_dvd (GstPad * pad, GstBuffer * buf)
GST_WARNING_OBJECT (pad, "Bad first_access parameter in buffer"); GST_WARNING_OBJECT (pad, "Bad first_access parameter in buffer");
GST_ELEMENT_ERROR (dvdlpcmdec, STREAM, DECODE, GST_ELEMENT_ERROR (dvdlpcmdec, STREAM, DECODE,
(NULL), (NULL),
("first_access parameter out of range: bad buffer from " "demuxer")); ("first_access parameter out of range: bad buffer from demuxer"));
ret = GST_FLOW_ERROR; ret = GST_FLOW_ERROR;
goto done; goto done;
} }
@ -496,8 +505,7 @@ done:
negotiation_failed: negotiation_failed:
{ {
GST_DEBUG_OBJECT (dvdlpcmdec, "Failed to set caps!"); GST_DEBUG_OBJECT (dvdlpcmdec, "Failed to set caps!");
GST_DEBUG_OBJECT (dvdlpcmdec, "Couldn't negotiate caps on src pad"); ret = GST_FLOW_NOT_NEGOTIATED;
ret = GST_FLOW_ERROR;
goto done; goto done;
} }
} }
@ -506,7 +514,7 @@ static GstFlowReturn
gst_dvdlpcmdec_chain_raw (GstPad * pad, GstBuffer * buf) gst_dvdlpcmdec_chain_raw (GstPad * pad, GstBuffer * buf)
{ {
GstDvdLpcmDec *dvdlpcmdec; GstDvdLpcmDec *dvdlpcmdec;
guchar *data; guint8 *data;
guint size; guint size;
GstFlowReturn ret; GstFlowReturn ret;
guint samples = 0; guint samples = 0;
@ -523,6 +531,9 @@ gst_dvdlpcmdec_chain_raw (GstPad * pad, GstBuffer * buf)
if (dvdlpcmdec->rate == 0) if (dvdlpcmdec->rate == 0)
goto not_negotiated; goto not_negotiated;
if (GST_BUFFER_TIMESTAMP_IS_VALID (buf))
dvdlpcmdec->timestamp = GST_BUFFER_TIMESTAMP (buf);
/* We don't currently do anything at all regarding emphasis, mute or /* We don't currently do anything at all regarding emphasis, mute or
* dynamic_range - I'm not sure what they're for */ * dynamic_range - I'm not sure what they're for */
switch (dvdlpcmdec->width) { switch (dvdlpcmdec->width) {
@ -540,8 +551,8 @@ gst_dvdlpcmdec_chain_raw (GstPad * pad, GstBuffer * buf)
gint64 samples = size * 8 / 20; gint64 samples = size * 8 / 20;
gint64 count = size / 10; gint64 count = size / 10;
gint64 i; gint64 i;
guchar *src; guint8 *src;
guchar *dest; guint8 *dest;
GstBuffer *outbuf; GstBuffer *outbuf;
GstCaps *bufcaps = GST_PAD_CAPS (dvdlpcmdec->srcpad); GstCaps *bufcaps = GST_PAD_CAPS (dvdlpcmdec->srcpad);
@ -598,19 +609,19 @@ gst_dvdlpcmdec_chain_raw (GstPad * pad, GstBuffer * buf)
src = GST_BUFFER_DATA (buf); src = GST_BUFFER_DATA (buf);
for (i = 0; i < count; i++) { for (i = 0; i < count; i++) {
guchar temp[9]; guint8 tmp;
temp[0] = src[8]; tmp = src[10];
temp[1] = src[2]; src[10] = src[7];
temp[2] = src[3]; src[7] = src[5];
temp[3] = src[9]; src[5] = src[9];
temp[4] = src[4]; src[9] = src[6];
temp[5] = src[5]; src[6] = src[4];
temp[6] = src[10]; src[4] = src[3];
temp[7] = src[6]; src[3] = src[2];
temp[8] = src[7]; src[2] = src[8];
src[8] = tmp;
memcpy (src + 2, temp, 9);
src += 12; src += 12;
} }
break; break;
@ -659,7 +670,10 @@ invalid_width:
static gboolean static gboolean
dvdlpcmdec_sink_event (GstPad * pad, GstEvent * event) dvdlpcmdec_sink_event (GstPad * pad, GstEvent * event)
{ {
GstDvdLpcmDec *dvdlpcmdec = GST_DVDLPCMDEC (GST_PAD_PARENT (pad)); GstDvdLpcmDec *dvdlpcmdec;
gboolean res;
dvdlpcmdec = GST_DVDLPCMDEC (GST_PAD_PARENT (pad));
switch (GST_EVENT_TYPE (event)) { switch (GST_EVENT_TYPE (event)) {
case GST_EVENT_NEWSEGMENT: case GST_EVENT_NEWSEGMENT:
@ -667,32 +681,37 @@ dvdlpcmdec_sink_event (GstPad * pad, GstEvent * event)
gdouble rate, arate; gdouble rate, arate;
GstFormat format; GstFormat format;
gboolean update; gboolean update;
gint64 start, end, base; gint64 start, stop, pos;
gst_event_parse_new_segment_full (event, &update, &rate, &arate, gst_event_parse_new_segment_full (event, &update, &rate, &arate,
&format, &start, &end, &base); &format, &start, &stop, &pos);
GST_DEBUG_OBJECT (dvdlpcmdec, GST_DEBUG_OBJECT (dvdlpcmdec,
"new segment, format=%d, start = %" G_GINT64_FORMAT "new segment, format=%d, start = %" G_GINT64_FORMAT
", end = %" G_GINT64_FORMAT ", position %" G_GINT64_FORMAT, ", stop = %" G_GINT64_FORMAT ", position %" G_GINT64_FORMAT,
format, start, end, base); format, start, stop, pos);
gst_segment_set_newsegment_full (&dvdlpcmdec->segment, update,
rate, arate, format, start, stop, pos);
if (format == GST_FORMAT_TIME) {
dvdlpcmdec->timestamp = GST_CLOCK_TIME_NONE; dvdlpcmdec->timestamp = GST_CLOCK_TIME_NONE;
if (format == GST_FORMAT_TIME) } else {
dvdlpcmdec->segment_start = start; dvdlpcmdec->timestamp = 0;
else }
dvdlpcmdec->segment_start = 0; res = gst_pad_push_event (dvdlpcmdec->srcpad, event);
GST_DEBUG_OBJECT (dvdlpcmdec,
"Have new segment. Resetting timestamp. segment_start = % "
G_GINT64_FORMAT, dvdlpcmdec->segment_start);
break; break;
} }
case GST_EVENT_FLUSH_STOP:
gst_segment_init (&dvdlpcmdec->segment, GST_FORMAT_UNDEFINED);
res = gst_pad_push_event (dvdlpcmdec->srcpad, event);
break;
default: default:
res = gst_pad_push_event (dvdlpcmdec->srcpad, event);
break; break;
} }
return gst_pad_event_default (pad, event); return res;
} }
static GstStateChangeReturn static GstStateChangeReturn

View File

@ -55,7 +55,7 @@ struct _GstDvdLpcmDec {
gint mute; gint mute;
GstClockTime timestamp; GstClockTime timestamp;
GstClockTime segment_start; GstSegment segment;
}; };
struct _GstDvdLpcmDecClass { struct _GstDvdLpcmDecClass {