gst/wavenc/gstwavenc.*: Properly write wav files with width!=depth by having the depth most significant bytes set and...

Original commit message from CVS:
* gst/wavenc/gstwavenc.c: (gst_wavenc_create_header_buf),
(gst_wavenc_sink_setcaps), (gst_wavenc_format_samples),
(gst_wavenc_chain), (gst_wavenc_change_state):
* gst/wavenc/gstwavenc.h:
Properly write wav files with width!=depth by having the depth most
significant bytes set and all others zero. Fixes #442535.
This commit is contained in:
Sebastian Dröge 2007-06-03 11:21:44 +00:00
parent 6ce8b13eb4
commit 10da08ace4
3 changed files with 67 additions and 4 deletions

View file

@ -1,3 +1,12 @@
2007-06-03 Sebastian Dröge <slomo@circular-chaos.org>
* gst/wavenc/gstwavenc.c: (gst_wavenc_create_header_buf),
(gst_wavenc_sink_setcaps), (gst_wavenc_format_samples),
(gst_wavenc_chain), (gst_wavenc_change_state):
* gst/wavenc/gstwavenc.h:
Properly write wav files with width!=depth by having the depth most
significant bytes set and all others zero. Fixes #442535.
2007-06-01 Wim Taymans <wim@fluendo.com> 2007-06-01 Wim Taymans <wim@fluendo.com>
* gst/rtsp/rtspconnection.c: * gst/rtsp/rtspconnection.c:

View file

@ -195,8 +195,7 @@ gst_wavenc_create_header_buf (GstWavEnc * wavenc, guint audio_data_size)
wave.format.len = 16; wave.format.len = 16;
wave.common.wFormatTag = WAVE_FORMAT_PCM; wave.common.wFormatTag = WAVE_FORMAT_PCM;
wave.common.wBlockAlign = wave.common.wBlockAlign = (wavenc->width / 8) * wave.common.wChannels;
(GST_ROUND_UP_8 (wavenc->depth) / 8) * wave.common.wChannels;
wave.common.dwAvgBytesPerSec = wave.common.dwAvgBytesPerSec =
wave.common.wBlockAlign * wave.common.dwSamplesPerSec; wave.common.wBlockAlign * wave.common.dwSamplesPerSec;
@ -275,10 +274,11 @@ gst_wavenc_sink_setcaps (GstPad * pad, GstCaps * caps)
wavenc->channels = chans; wavenc->channels = chans;
wavenc->depth = depth; wavenc->depth = depth;
wavenc->width = width;
wavenc->rate = rate; wavenc->rate = rate;
GST_LOG_OBJECT (wavenc, "accepted caps: chans=%u width=%u depth=%u rate=%u", GST_LOG_OBJECT (wavenc, "accepted caps: chans=%u width=%u depth=%u rate=%u",
wavenc->channels, width, wavenc->depth, wavenc->rate); wavenc->channels, wavenc->width, wavenc->depth, wavenc->rate);
gst_object_unref (wavenc); gst_object_unref (wavenc);
return TRUE; return TRUE;
@ -608,6 +608,52 @@ gst_wavenc_event (GstPad * pad, GstEvent * event)
return res; return res;
} }
/* Copied from gst-plugins-base/gst/audioconvert/audioconvert.c */
#define READ24_FROM_LE(p) (p[0] | (p[1] << 8) | (p[2] << 16))
#define WRITE24_TO_LE(p,v) p[0] = v & 0xff; p[1] = (v >> 8) & 0xff; p[2] = (v >> 16) & 0xff
/* Correctly format samples with width!=depth for the wav format, i.e.
* have the data in the highest depth bits and all others zero */
static void
gst_wavenc_format_samples (GstBuffer * buf, guint width, guint depth)
{
guint8 *data = GST_BUFFER_DATA (buf);
guint nsamples = (GST_BUFFER_SIZE (buf) * 8) / width;
guint32 tmp;
for (; nsamples; nsamples--) {
switch (width) {
case 8:
tmp = *data;
*data = *data << (width - depth);
data += 1;
break;
case 16:
tmp = GST_READ_UINT16_LE (data);
tmp = tmp << (width - depth);
GST_WRITE_UINT16_LE (data, tmp);
data += 2;
break;
case 24:
tmp = READ24_FROM_LE (data);
tmp = tmp << (width - depth);
WRITE24_TO_LE (data, tmp);
data += 3;
break;
case 32:
tmp = GST_READ_UINT32_LE (data);
tmp = tmp << (width - depth);
GST_WRITE_UINT32_LE (data, tmp);
data += 4;
break;
}
}
}
#undef READ24_FROM_LE
#undef WRITE24_TO_LE
static GstFlowReturn static GstFlowReturn
gst_wavenc_chain (GstPad * pad, GstBuffer * buf) gst_wavenc_chain (GstPad * pad, GstBuffer * buf)
{ {
@ -633,7 +679,13 @@ gst_wavenc_chain (GstPad * pad, GstBuffer * buf)
GST_LOG_OBJECT (wavenc, "pushing %u bytes raw audio, ts=%" GST_TIME_FORMAT, GST_LOG_OBJECT (wavenc, "pushing %u bytes raw audio, ts=%" GST_TIME_FORMAT,
GST_BUFFER_SIZE (buf), GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf))); GST_BUFFER_SIZE (buf), GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)));
if (wavenc->width != wavenc->depth) {
buf = gst_buffer_make_writable (buf);
gst_wavenc_format_samples (buf, wavenc->width, wavenc->depth);
} else {
buf = gst_buffer_make_metadata_writable (buf); buf = gst_buffer_make_metadata_writable (buf);
}
gst_buffer_set_caps (buf, GST_PAD_CAPS (wavenc->srcpad)); gst_buffer_set_caps (buf, GST_PAD_CAPS (wavenc->srcpad));
GST_BUFFER_OFFSET (buf) = WAV_HEADER_LEN + wavenc->length; GST_BUFFER_OFFSET (buf) = WAV_HEADER_LEN + wavenc->length;
GST_BUFFER_OFFSET_END (buf) = GST_BUFFER_OFFSET_NONE; GST_BUFFER_OFFSET_END (buf) = GST_BUFFER_OFFSET_NONE;
@ -653,6 +705,7 @@ gst_wavenc_change_state (GstElement * element, GstStateChange transition)
case GST_STATE_CHANGE_NULL_TO_READY: case GST_STATE_CHANGE_NULL_TO_READY:
wavenc->channels = 0; wavenc->channels = 0;
wavenc->depth = 0; wavenc->depth = 0;
wavenc->width = 0;
wavenc->rate = 0; wavenc->rate = 0;
wavenc->length = 0; wavenc->length = 0;
wavenc->sent_header = FALSE; wavenc->sent_header = FALSE;

View file

@ -47,6 +47,7 @@ struct _GstWavEnc {
GstPad *srcpad; GstPad *srcpad;
/* useful audio data */ /* useful audio data */
guint width;
guint depth; guint depth;
guint rate; guint rate;
guint channels; guint channels;