celt: port to 0.11

This commit is contained in:
Mark Nauwelaerts 2012-03-07 10:18:31 +01:00
parent dbf0b994f2
commit 99a4e43c76
3 changed files with 97 additions and 111 deletions

View file

@ -310,7 +310,7 @@ GST_PLUGINS_NONPORTED=" aiff asfmux \
sdi segmentclip siren speed subenc stereo tta videofilters \
videomeasure videosignal vmnc \
decklink fbdev linsys shm vcd \
apexsink bz2 cdaudio celt cog curl dc1394 dirac directfb resindvd \
apexsink bz2 cdaudio cog curl dc1394 dirac directfb resindvd \
gsettings jp2k ladspa mimic \
musepack musicbrainz nas neon ofa openal opencv rsvg sdl smooth sndfile soundtouch spandsp timidity \
wildmidi xvid lv2 teletextdec opus dvb"

View file

@ -57,6 +57,7 @@ GST_STATIC_PAD_TEMPLATE ("src",
GST_PAD_ALWAYS,
GST_STATIC_CAPS ("audio/x-raw, "
"format = (string) " GST_AUDIO_NE (S16) ", "
"layout = (string) interleaved, "
"rate = (int) [ 32000, 64000 ], " "channels = (int) [ 1, 2 ]")
);
@ -80,8 +81,10 @@ static GstFlowReturn gst_celt_dec_handle_frame (GstAudioDecoder * dec,
static void
gst_celt_dec_class_init (GstCeltDecClass * klass)
{
GstElementClass *gstelement_class;
GstAudioDecoderClass *gstbase_class;
gstelement_class = (GstElementClass *) klass;
gstbase_class = (GstAudioDecoderClass *) klass;
gstbase_class->start = GST_DEBUG_FUNCPTR (gst_celt_dec_start);
@ -161,13 +164,16 @@ gst_celt_dec_stop (GstAudioDecoder * dec)
static GstFlowReturn
gst_celt_dec_parse_header (GstCeltDec * dec, GstBuffer * buf)
{
GstCaps *caps;
gint error = CELT_OK;
GstMapInfo map;
GstAudioInfo info;
/* get the header */
gst_buffer_map (buf, &map, GST_MAP_READ);
error =
celt_header_from_packet ((const unsigned char *) GST_BUFFER_DATA (buf),
GST_BUFFER_SIZE (buf), &dec->header);
celt_header_from_packet ((const unsigned char *) map.data,
map.size, &dec->header);
gst_buffer_unmap (buf, &map);
if (error < 0)
goto invalid_header;
@ -206,21 +212,15 @@ gst_celt_dec_parse_header (GstCeltDec * dec, GstBuffer * buf)
celt_mode_info (dec->mode, CELT_GET_FRAME_SIZE, &dec->frame_size);
#endif
/* set caps */
caps = gst_caps_new_simple ("audio/x-raw-int",
"rate", G_TYPE_INT, dec->header.sample_rate,
"channels", G_TYPE_INT, dec->header.nb_channels,
"signed", G_TYPE_BOOLEAN, TRUE,
"endianness", G_TYPE_INT, G_BYTE_ORDER,
"width", G_TYPE_INT, 16, "depth", G_TYPE_INT, 16, NULL);
GST_DEBUG_OBJECT (dec, "rate=%d channels=%d frame-size=%d",
dec->header.sample_rate, dec->header.nb_channels, dec->frame_size);
if (!gst_pad_set_caps (GST_AUDIO_DECODER_SRC_PAD (dec), caps))
gst_audio_info_init (&info);
gst_audio_info_set_format (&info, GST_AUDIO_FORMAT_S16,
dec->header.sample_rate, dec->header.nb_channels, NULL);
if (!gst_audio_decoder_set_output_format (GST_AUDIO_DECODER (dec), &info))
goto nego_failed;
gst_caps_unref (caps);
return GST_FLOW_OK;
/* ERRORS */
@ -251,7 +251,6 @@ nego_failed:
{
GST_ELEMENT_ERROR (GST_ELEMENT (dec), STREAM, DECODE,
(NULL), ("couldn't negotiate format"));
gst_caps_unref (caps);
return GST_FLOW_NOT_NEGOTIATED;
}
}
@ -266,7 +265,7 @@ gst_celt_dec_parse_comments (GstCeltDec * dec, GstBuffer * buf)
if (!list) {
GST_WARNING_OBJECT (dec, "couldn't decode comments");
list = gst_tag_list_new ();
list = gst_tag_list_new_empty ();
}
if (encoder) {
@ -292,8 +291,8 @@ gst_celt_dec_parse_comments (GstCeltDec * dec, GstBuffer * buf)
GST_INFO_OBJECT (dec, "tags: %" GST_PTR_FORMAT, list);
gst_element_found_tags_for_pad (GST_ELEMENT (dec),
GST_AUDIO_DECODER_SRC_PAD (dec), list);
gst_pad_push_event (GST_AUDIO_DECODER_SRC_PAD (dec),
gst_event_new_tag (list));
g_free (encoder);
g_free (ver);
@ -311,13 +310,15 @@ gst_celt_dec_parse_data (GstCeltDec * dec, GstBuffer * buf)
gint16 *out_data;
gint error = CELT_OK;
int skip = 0;
GstMapInfo map, omap;
if (!dec->frame_size)
goto not_negotiated;
if (G_LIKELY (GST_BUFFER_SIZE (buf))) {
data = GST_BUFFER_DATA (buf);
size = GST_BUFFER_SIZE (buf);
if (G_LIKELY (buf && gst_buffer_get_size (buf))) {
gst_buffer_map (buf, &map, GST_MAP_READ);
data = map.data;
size = map.size;
} else {
/* FIXME ? actually consider how much concealment is needed */
/* concealment data, pass NULL as the bits parameters */
@ -337,16 +338,10 @@ gst_celt_dec_parse_data (GstCeltDec * dec, GstBuffer * buf)
#endif
}
res = gst_pad_alloc_buffer_and_set_caps (GST_AUDIO_DECODER_SRC_PAD (dec),
GST_BUFFER_OFFSET_NONE, dec->frame_size * dec->header.nb_channels * 2,
GST_PAD_CAPS (GST_AUDIO_DECODER_SRC_PAD (dec)), &outbuf);
if (res != GST_FLOW_OK) {
GST_DEBUG_OBJECT (dec, "buf alloc flow: %s", gst_flow_get_name (res));
return res;
}
out_data = (gint16 *) GST_BUFFER_DATA (outbuf);
outbuf =
gst_buffer_new_and_alloc (dec->frame_size * dec->header.nb_channels * 2);
gst_buffer_map (outbuf, &omap, GST_MAP_WRITE);
out_data = (gint16 *) omap.data;
GST_LOG_OBJECT (dec, "decoding frame");
@ -355,6 +350,11 @@ gst_celt_dec_parse_data (GstCeltDec * dec, GstBuffer * buf)
#else
error = celt_decode (dec->state, data, size, out_data);
#endif
gst_buffer_unmap (outbuf, &omap);
if (buf)
gst_buffer_unmap (buf, &map);
#ifdef HAVE_CELT_0_11
if (error < 0) {
#else
@ -366,10 +366,7 @@ gst_celt_dec_parse_data (GstCeltDec * dec, GstBuffer * buf)
if (skip > 0) {
GST_ERROR_OBJECT (dec, "skipping %d samples", skip);
GST_BUFFER_DATA (outbuf) = GST_BUFFER_DATA (outbuf) +
skip * dec->header.nb_channels * 2;
GST_BUFFER_SIZE (outbuf) = GST_BUFFER_SIZE (outbuf) -
skip * dec->header.nb_channels * 2;
gst_buffer_resize (outbuf, skip * dec->header.nb_channels * 2, -1);
}
res = gst_audio_decoder_finish_frame (GST_AUDIO_DECODER (dec), outbuf, 1);
@ -443,6 +440,22 @@ done:
return ret;
}
static gint
_gst_buffer_memcmp (GstBuffer * buf1, GstBuffer * buf2)
{
GstMapInfo map;
gint ret;
if (gst_buffer_get_size (buf1) == gst_buffer_get_size (buf2))
return 1;
gst_buffer_map (buf1, &map, GST_MAP_READ);
ret = gst_buffer_memcmp (buf2, 0, map.data, map.size);
gst_buffer_unmap (buf1, &map);
return ret;
}
static GstFlowReturn
gst_celt_dec_handle_frame (GstAudioDecoder * bdec, GstBuffer * buf)
{
@ -458,15 +471,11 @@ gst_celt_dec_handle_frame (GstAudioDecoder * bdec, GstBuffer * buf)
/* If we have the streamheader and vorbiscomment from the caps already
* ignore them here */
if (dec->streamheader && dec->vorbiscomment) {
if (GST_BUFFER_SIZE (dec->streamheader) == GST_BUFFER_SIZE (buf)
&& memcmp (GST_BUFFER_DATA (dec->streamheader), GST_BUFFER_DATA (buf),
GST_BUFFER_SIZE (buf)) == 0) {
if (_gst_buffer_memcmp (dec->streamheader, buf) == 0) {
GST_DEBUG_OBJECT (dec, "found streamheader");
gst_audio_decoder_finish_frame (bdec, NULL, 1);
res = GST_FLOW_OK;
} else if (GST_BUFFER_SIZE (dec->vorbiscomment) == GST_BUFFER_SIZE (buf)
&& memcmp (GST_BUFFER_DATA (dec->vorbiscomment), GST_BUFFER_DATA (buf),
GST_BUFFER_SIZE (buf)) == 0) {
} else if (_gst_buffer_memcmp (dec->vorbiscomment, buf) == 0) {
GST_DEBUG_OBJECT (dec, "found vorbiscomments");
gst_audio_decoder_finish_frame (bdec, NULL, 1);
res = GST_FLOW_OK;
@ -475,9 +484,7 @@ gst_celt_dec_handle_frame (GstAudioDecoder * bdec, GstBuffer * buf)
for (l = dec->extra_headers; l; l = l->next) {
GstBuffer *header = l->data;
if (GST_BUFFER_SIZE (header) == GST_BUFFER_SIZE (buf) &&
memcmp (GST_BUFFER_DATA (header), GST_BUFFER_DATA (buf),
GST_BUFFER_SIZE (buf)) == 0) {
if (_gst_buffer_memcmp (header, buf) == 0) {
GST_DEBUG_OBJECT (dec, "found extra header buffer");
gst_audio_decoder_finish_frame (bdec, NULL, 1);
res = GST_FLOW_OK;

View file

@ -80,11 +80,10 @@ gst_celt_enc_prediction_get_type (void)
static GstStaticPadTemplate sink_factory = GST_STATIC_PAD_TEMPLATE ("sink",
GST_PAD_SINK,
GST_PAD_ALWAYS,
GST_STATIC_CAPS ("audio/x-raw-int, "
"rate = (int) [ 32000, 64000 ], "
"channels = (int) [ 1, 2 ], "
"endianness = (int) BYTE_ORDER, "
"signed = (boolean) TRUE, " "width = (int) 16, " "depth = (int) 16")
GST_STATIC_CAPS ("audio/x-raw, "
"format = (string) " GST_AUDIO_NE (S16) ", "
"layout = (string) interleaved, "
"rate = (int) [ 32000, 64000 ], " "channels = (int) [ 1, 2 ]")
);
static GstStaticPadTemplate src_factory = GST_STATIC_PAD_TEMPLATE ("src",
@ -131,42 +130,19 @@ static gboolean gst_celt_enc_sink_event (GstAudioEncoder * enc,
static GstFlowReturn gst_celt_enc_pre_push (GstAudioEncoder * benc,
GstBuffer ** buffer);
static void
gst_celt_enc_setup_interfaces (GType celtenc_type)
{
static const GInterfaceInfo tag_setter_info = { NULL, NULL, NULL };
g_type_add_interface_static (celtenc_type, GST_TYPE_TAG_SETTER,
&tag_setter_info);
GST_DEBUG_CATEGORY_INIT (celtenc_debug, "celtenc", 0, "Celt encoder");
}
GST_BOILERPLATE_FULL (GstCeltEnc, gst_celt_enc, GstAudioEncoder,
GST_TYPE_AUDIO_ENCODER, gst_celt_enc_setup_interfaces);
static void
gst_celt_enc_base_init (gpointer g_class)
{
GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
gst_element_class_add_pad_template (element_class,
gst_static_pad_template_get (&src_factory));
gst_element_class_add_pad_template (element_class,
gst_static_pad_template_get (&sink_factory));
gst_element_class_set_details_simple (element_class, "Celt audio encoder",
"Codec/Encoder/Audio",
"Encodes audio in Celt format",
"Sebastian Dröge <sebastian.droege@collabora.co.uk>");
}
#define gst_celt_enc_parent_class parent_class
G_DEFINE_TYPE_WITH_CODE (GstCeltEnc, gst_celt_enc, GST_TYPE_AUDIO_ENCODER,
G_IMPLEMENT_INTERFACE (GST_TYPE_TAG_SETTER, NULL));
static void
gst_celt_enc_class_init (GstCeltEncClass * klass)
{
GObjectClass *gobject_class;
GstElementClass *gstelement_class;
GstAudioEncoderClass *gstbase_class;
gobject_class = (GObjectClass *) klass;
gstelement_class = (GstElementClass *) klass;
gstbase_class = (GstAudioEncoderClass *) klass;
gobject_class->set_property = gst_celt_enc_set_property;
@ -211,10 +187,21 @@ gst_celt_enc_class_init (GstCeltEncClass * klass)
"Controls the start band that should be used",
0, G_MAXINT, DEFAULT_START_BAND,
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
gst_element_class_add_pad_template (gstelement_class,
gst_static_pad_template_get (&src_factory));
gst_element_class_add_pad_template (gstelement_class,
gst_static_pad_template_get (&sink_factory));
gst_element_class_set_details_simple (gstelement_class, "Celt audio encoder",
"Codec/Encoder/Audio",
"Encodes audio in Celt format",
"Sebastian Dröge <sebastian.droege@collabora.co.uk>");
GST_DEBUG_CATEGORY_INIT (celtenc_debug, "celtenc", 0, "Celt encoder");
}
static void
gst_celt_enc_init (GstCeltEnc * enc, GstCeltEncClass * klass)
gst_celt_enc_init (GstCeltEnc * enc)
{
enc->bitrate = DEFAULT_BITRATE;
enc->frame_size = DEFAULT_FRAMESIZE;
@ -433,7 +420,7 @@ gst_celt_enc_create_metadata_buffer (GstCeltEnc * enc)
if (tags == NULL) {
/* FIXME: better fix chain of callers to not write metadata at all,
* if there is none */
empty_tags = gst_tag_list_new ();
empty_tags = gst_tag_list_new_empty ();
tags = empty_tags;
}
comments = gst_tag_list_to_vorbiscomment_buffer (tags, NULL,
@ -458,16 +445,19 @@ gst_celt_enc_encode (GstCeltEnc * enc, GstBuffer * buf)
gint16 *data, *data0 = NULL;
gint outsize, size;
GstBuffer *outbuf;
GstMapInfo map, omap;
if (G_LIKELY (buf)) {
data = (gint16 *) GST_BUFFER_DATA (buf);
size = GST_BUFFER_SIZE (buf);
gst_buffer_map (buf, &map, GST_MAP_READ);
data = (gint16 *) map.data;
size = map.size;
if (G_UNLIKELY (size % bytes)) {
if (G_UNLIKELY (map.size % bytes)) {
GST_DEBUG_OBJECT (enc, "draining; adding silence samples");
size = ((size / bytes) + 1) * bytes;
data0 = data = g_malloc0 (size);
memcpy (data, GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf));
data0 = g_malloc0 (size);
memcpy (data0, data, size);
data = data0;
}
} else {
GST_DEBUG_OBJECT (enc, "nothing to drain");
@ -481,25 +471,21 @@ gst_celt_enc_encode (GstCeltEnc * enc, GstBuffer * buf)
bytes_per_packet = (enc->max_bitrate * frame_size / enc->rate + 4) / 8;
}
ret = gst_pad_alloc_buffer_and_set_caps (GST_AUDIO_ENCODER_SRC_PAD (enc),
GST_BUFFER_OFFSET_NONE, bytes_per_packet,
GST_PAD_CAPS (GST_AUDIO_ENCODER_SRC_PAD (enc)), &outbuf);
if (GST_FLOW_OK != ret)
goto done;
outbuf = gst_buffer_new_and_alloc (bytes_per_packet);
GST_DEBUG_OBJECT (enc, "encoding %d samples (%d bytes)", frame_size, bytes);
gst_buffer_map (outbuf, &omap, GST_MAP_WRITE);
#ifdef HAVE_CELT_0_8
outsize =
celt_encode (enc->state, data, frame_size,
GST_BUFFER_DATA (outbuf), bytes_per_packet);
celt_encode (enc->state, data, frame_size, omap.data, bytes_per_packet);
#else
outsize =
celt_encode (enc->state, data, NULL,
GST_BUFFER_DATA (outbuf), bytes_per_packet);
outsize = celt_encode (enc->state, data, NULL, omap.data, bytes_per_packet);
#endif
gst_buffer_unmap (outbuf, &omap);
gst_buffer_unmap (buf, &map);
if (outsize < 0) {
GST_ELEMENT_ERROR (enc, STREAM, ENCODE, (NULL),
("encoding failed: %d", outsize));
@ -552,14 +538,14 @@ _gst_caps_set_buffer_array (GstCaps * caps, const gchar * field,
va_start (va, buf);
/* put buffers in a fixed list */
while (buf) {
g_assert (gst_buffer_is_metadata_writable (buf));
g_assert (gst_buffer_is_writable (buf));
/* mark buffer */
GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_IN_CAPS);
GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_HEADER);
g_value_init (&value, GST_TYPE_BUFFER);
buf = gst_buffer_copy (buf);
GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_IN_CAPS);
GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_HEADER);
gst_value_set_buffer (&value, buf);
gst_buffer_unref (buf);
gst_value_array_append_value (&array, &value);
@ -601,9 +587,7 @@ gst_celt_enc_handle_frame (GstAudioEncoder * benc, GstBuffer * buf)
g_free (data);
goto no_header;
}
buf1 = gst_buffer_new ();
GST_BUFFER_DATA (buf1) = GST_BUFFER_MALLOCDATA (buf1) = data;
GST_BUFFER_SIZE (buf1) = header_size;
buf1 = gst_buffer_new_wrapped (data, header_size);
GST_BUFFER_OFFSET_END (buf1) = 0;
GST_BUFFER_OFFSET (buf1) = 0;
@ -611,8 +595,7 @@ gst_celt_enc_handle_frame (GstAudioEncoder * benc, GstBuffer * buf)
buf2 = gst_celt_enc_create_metadata_buffer (enc);
/* mark and put on caps */
caps = gst_pad_get_caps (GST_AUDIO_ENCODER_SRC_PAD (enc));
gst_caps_set_simple (caps,
caps = gst_caps_new_simple ("audio/x-celt",
"rate", G_TYPE_INT, enc->rate,
"channels", G_TYPE_INT, enc->channels,
"frame-size", G_TYPE_INT, enc->frame_size, NULL);
@ -622,10 +605,7 @@ gst_celt_enc_handle_frame (GstAudioEncoder * benc, GstBuffer * buf)
GST_DEBUG_OBJECT (enc, "here are the caps: %" GST_PTR_FORMAT, caps);
GST_LOG_OBJECT (enc, "rate=%d channels=%d frame-size=%d",
enc->rate, enc->channels, enc->frame_size);
gst_pad_set_caps (GST_AUDIO_ENCODER_SRC_PAD (enc), caps);
gst_buffer_set_caps (buf1, caps);
gst_buffer_set_caps (buf2, caps);
gst_audio_encoder_set_output_format (GST_AUDIO_ENCODER (enc), caps);
gst_caps_unref (caps);
/* push out buffers */
@ -640,7 +620,7 @@ gst_celt_enc_handle_frame (GstAudioEncoder * benc, GstBuffer * buf)
}
GST_DEBUG_OBJECT (enc, "received buffer %p of %u bytes", buf,
buf ? GST_BUFFER_SIZE (buf) : 0);
buf ? gst_buffer_get_size (buf) : 0);
ret = gst_celt_enc_encode (enc, buf);
@ -663,10 +643,9 @@ gst_celt_enc_push_buffer (GstCeltEnc * enc, GstBuffer * buffer)
{
guint size;
size = GST_BUFFER_SIZE (buffer);
size = gst_buffer_get_size (buffer);
GST_DEBUG_OBJECT (enc, "pushing output buffer of size %u", size);
gst_buffer_set_caps (buffer, GST_PAD_CAPS (GST_AUDIO_ENCODER_SRC_PAD (enc)));
return gst_pad_push (GST_AUDIO_ENCODER_SRC_PAD (enc), buffer);
}