Fix vorbisenc (bug 95097)

Original commit message from CVS:
Fix vorbisenc (bug 95097)
This commit is contained in:
Wim Taymans 2002-10-19 16:57:08 +00:00
parent 9c3f561ddd
commit cc76e0aacd

View file

@ -64,6 +64,8 @@ static void gst_vorbisenc_get_property (GObject * object, guint prop_id, GValu
GParamSpec * pspec); GParamSpec * pspec);
static void gst_vorbisenc_set_property (GObject * object, guint prop_id, const GValue * value, static void gst_vorbisenc_set_property (GObject * object, guint prop_id, const GValue * value,
GParamSpec * pspec); GParamSpec * pspec);
static GstElementStateReturn
gst_vorbisenc_change_state (GstElement *element);
static GstElementClass *parent_class = NULL; static GstElementClass *parent_class = NULL;
/*static guint gst_vorbisenc_signals[LAST_SIGNAL] = { 0 }; */ /*static guint gst_vorbisenc_signals[LAST_SIGNAL] = { 0 }; */
@ -108,6 +110,8 @@ gst_vorbisenc_class_init (VorbisEncClass * klass)
gobject_class->set_property = gst_vorbisenc_set_property; gobject_class->set_property = gst_vorbisenc_set_property;
gobject_class->get_property = gst_vorbisenc_get_property; gobject_class->get_property = gst_vorbisenc_get_property;
gstelement_class->change_state = gst_vorbisenc_change_state;
} }
static GstPadConnectReturn static GstPadConnectReturn
@ -142,10 +146,11 @@ gst_vorbisenc_init (VorbisEnc * vorbisenc)
vorbisenc->srcpad = gst_pad_new_from_template (gst_vorbisenc_src_template, "src"); vorbisenc->srcpad = gst_pad_new_from_template (gst_vorbisenc_src_template, "src");
gst_element_add_pad (GST_ELEMENT (vorbisenc), vorbisenc->srcpad); gst_element_add_pad (GST_ELEMENT (vorbisenc), vorbisenc->srcpad);
vorbisenc->channels = 2; vorbisenc->channels = -1;
vorbisenc->frequency = 44100; vorbisenc->frequency = -1;
vorbisenc->bitrate = 128000; vorbisenc->bitrate = 128000;
vorbisenc->setup = FALSE; vorbisenc->setup = FALSE;
vorbisenc->eos = FALSE;
/* we're chained and we can deal with events */ /* we're chained and we can deal with events */
GST_FLAG_SET (vorbisenc, GST_ELEMENT_EVENT_AWARE); GST_FLAG_SET (vorbisenc, GST_ELEMENT_EVENT_AWARE);
@ -216,27 +221,21 @@ gst_vorbisenc_chain (GstPad * pad, GstBuffer * buf)
vorbisenc = GST_VORBISENC (gst_pad_get_parent (pad)); vorbisenc = GST_VORBISENC (gst_pad_get_parent (pad));
if (!vorbisenc->setup) {
gst_element_error (GST_ELEMENT (vorbisenc), "encoder not initialized (input is not audio?)");
if (GST_IS_BUFFER (buf))
gst_buffer_unref (buf);
else
gst_pad_event_default (pad, GST_EVENT (buf));
return;
}
if (GST_IS_EVENT (buf)) { if (GST_IS_EVENT (buf)) {
switch (GST_EVENT_TYPE (buf)) { GstEvent *event = GST_EVENT (buf);
switch (GST_EVENT_TYPE (event)) {
case GST_EVENT_EOS: case GST_EVENT_EOS:
/* end of file. this can be done implicitly in the mainline, /* end of file. this can be done implicitly in the mainline,
but it's easier to see here in non-clever fashion. but it's easier to see here in non-clever fashion.
Tell the library we're at end of stream so that it can handle Tell the library we're at end of stream so that it can handle
the last frame and mark end of stream in the output properly */ the last frame and mark end of stream in the output properly */
vorbis_analysis_wrote (&vorbisenc->vd, 0); vorbis_analysis_wrote (&vorbisenc->vd, 0);
gst_event_unref (event);
break; break;
default: default:
gst_pad_event_default (pad, GST_EVENT (buf)); gst_pad_event_default (pad, event);
break; return;
} }
} }
else { else {
@ -244,18 +243,25 @@ gst_vorbisenc_chain (GstPad * pad, GstBuffer * buf)
gulong size; gulong size;
gulong i, j; gulong i, j;
float **buffer; float **buffer;
if (!vorbisenc->setup) {
gst_element_error (GST_ELEMENT (vorbisenc), "encoder not initialized (input is not audio?)");
gst_buffer_unref (buf);
return;
}
/* data to encode */ /* data to encode */
data = (gint16 *) GST_BUFFER_DATA (buf); data = (gint16 *) GST_BUFFER_DATA (buf);
size = GST_BUFFER_SIZE (buf) / 2; size = GST_BUFFER_SIZE (buf) >> 1;
/* expose the buffer to submit data */ /* expose the buffer to submit data */
buffer = vorbis_analysis_buffer (&vorbisenc->vd, size / vorbisenc->channels); buffer = vorbis_analysis_buffer (&vorbisenc->vd, size / vorbisenc->channels);
/* uninterleave samples */ /* uninterleave samples */
for (i = 0; i < size / vorbisenc->channels; i++) { for (i = 0; i < size / vorbisenc->channels; i++) {
for (j = 0; j < vorbisenc->channels; j++) for (j = 0; j < vorbisenc->channels; j++) {
buffer[j][i] = data[i * vorbisenc->channels + j] / 32768.f; buffer[j][i] = data[i * vorbisenc->channels + j] / 32768.f;
}
} }
/* tell the library how much we actually submitted */ /* tell the library how much we actually submitted */
@ -273,7 +279,7 @@ gst_vorbisenc_chain (GstPad * pad, GstBuffer * buf)
vorbis_analysis (&vorbisenc->vb, NULL); vorbis_analysis (&vorbisenc->vb, NULL);
vorbis_bitrate_addblock(&vorbisenc->vb); vorbis_bitrate_addblock(&vorbisenc->vb);
while(vorbis_bitrate_flushpacket(&vorbisenc->vd, &vorbisenc->op)) { while (vorbis_bitrate_flushpacket (&vorbisenc->vd, &vorbisenc->op)) {
/* weld the packet into the bitstream */ /* weld the packet into the bitstream */
ogg_stream_packetin (&vorbisenc->os, &vorbisenc->op); ogg_stream_packetin (&vorbisenc->os, &vorbisenc->op);
@ -286,15 +292,17 @@ gst_vorbisenc_chain (GstPad * pad, GstBuffer * buf)
if (result == 0) if (result == 0)
break; break;
outbuf = gst_buffer_new (); outbuf = gst_buffer_new_and_alloc (vorbisenc->og.header_len +
GST_BUFFER_DATA (outbuf) = g_malloc (vorbisenc->og.header_len + vorbisenc->og.body_len); vorbisenc->og.body_len);
GST_BUFFER_SIZE (outbuf) = vorbisenc->og.header_len + vorbisenc->og.body_len;
memcpy (GST_BUFFER_DATA (outbuf), vorbisenc->og.header, vorbisenc->og.header_len); memcpy (GST_BUFFER_DATA (outbuf), vorbisenc->og.header,
memcpy (GST_BUFFER_DATA (outbuf) + vorbisenc->og.header_len, vorbisenc->og.body, vorbisenc->og.header_len);
vorbisenc->og.body_len); memcpy (GST_BUFFER_DATA (outbuf) + vorbisenc->og.header_len,
vorbisenc->og.body,
vorbisenc->og.body_len);
GST_DEBUG (0, "vorbisenc: encoded buffer of %d bytes", GST_BUFFER_SIZE (outbuf)); GST_DEBUG (0, "vorbisenc: encoded buffer of %d bytes",
GST_BUFFER_SIZE (outbuf));
gst_pad_push (vorbisenc->srcpad, outbuf); gst_pad_push (vorbisenc->srcpad, outbuf);
@ -357,3 +365,31 @@ gst_vorbisenc_set_property (GObject * object, guint prop_id, const GValue * valu
break; break;
} }
} }
static GstElementStateReturn
gst_vorbisenc_change_state (GstElement *element)
{
VorbisEnc *vorbisenc = GST_VORBISENC (element);
switch (GST_STATE_TRANSITION (element)) {
case GST_STATE_NULL_TO_READY:
case GST_STATE_READY_TO_PAUSED:
vorbisenc->eos = FALSE;
vorbisenc->setup = FALSE;
break;
case GST_STATE_PAUSED_TO_PLAYING:
case GST_STATE_PLAYING_TO_PAUSED:
break;
case GST_STATE_PAUSED_TO_READY:
break;
case GST_STATE_READY_TO_NULL:
default:
break;
}
if (GST_ELEMENT_CLASS (parent_class)->change_state)
return GST_ELEMENT_CLASS (parent_class)->change_state (element);
return GST_STATE_SUCCESS;
}