size = 0;
}
- samples =
- opus_packet_get_samples_per_frame (data,
- dec->sample_rate) * opus_packet_get_nb_frames (data, size);
- GST_DEBUG ("bandwidth %d", opus_packet_get_bandwidth (data));
- GST_DEBUG ("samples %d", samples);
+ if (data) {
+ samples =
+ opus_packet_get_samples_per_frame (data,
+ dec->sample_rate) * opus_packet_get_nb_frames (data, size);
+ packet_size = samples * dec->n_channels * 2;
+ GST_DEBUG_OBJECT (dec, "bandwidth %d", opus_packet_get_bandwidth (data));
+ GST_DEBUG_OBJECT (dec, "samples %d", samples);
+ } else {
+ /* use maximum size (120 ms) as we do now know in advance how many samples
+ will be returned */
+ samples = 120 * dec->sample_rate / 1000;
+ }
- packet_size = samples * dec->n_channels * 2;
-
- res = gst_pad_alloc_buffer_and_set_caps (GST_AUDIO_DECODER_SRC_PAD (dec),
- GST_BUFFER_OFFSET_NONE, packet_size,
- 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;
+ packet_size = samples * dec->n_channels * 2;
+ outbuf = gst_buffer_new_and_alloc (packet_size);
+ if (!outbuf) {
+ goto buffer_failed;
}
- out_data = (gint16 *) GST_BUFFER_DATA (outbuf);
+ out_data = (gint16 *) gst_buffer_map (outbuf, &out_size, NULL, GST_MAP_WRITE);
- GST_LOG_OBJECT (dec, "decoding %d samples, in size %u", samples, size);
-
n = opus_decode (dec->state, data, size, out_data, samples, 0);
+ gst_buffer_unmap (buf, data, size);
+ gst_buffer_unmap (outbuf, out_data, out_size);
if (n < 0) {
GST_ELEMENT_ERROR (dec, STREAM, DECODE, ("Decoding error: %d", n), (NULL));
return GST_FLOW_ERROR;
if (size1 != size2)
return FALSE;
- return !memcmp (GST_BUFFER_DATA (buf1), GST_BUFFER_DATA (buf2), size1);
+ data1 = gst_buffer_map (buf1, NULL, NULL, GST_MAP_READ);
+ res = gst_buffer_memcmp (buf2, 0, data1, size1) == 0;
+ gst_buffer_unmap (buf1, data1, size1);
+
+ return res;
}
- static gboolean
- gst_opus_dec_is_header (GstBuffer * buf, const char *magic, guint magic_size)
- {
- guint8 *data;
- gsize size;
- gboolean ret;
-
- data = gst_buffer_map (buf, &size, NULL, GST_MAP_READ);
- if (!data)
- return FALSE;
- ret = (size >= magic_size && !memcmp (magic, data, magic_size));
- gst_buffer_unmap (buf, data, size);
- return ret;
- }
-
static GstFlowReturn
gst_opus_dec_handle_frame (GstAudioDecoder * adec, GstBuffer * buf)
{
return id;
}
- #define FORMAT_STR GST_AUDIO_NE(S16)
+ #define GST_OPUS_ENC_TYPE_FRAME_SIZE (gst_opus_enc_frame_size_get_type())
+ static GType
+ gst_opus_enc_frame_size_get_type (void)
+ {
+ static const GEnumValue values[] = {
+ {2, "2.5", "2.5"},
+ {5, "5", "5"},
+ {10, "10", "10"},
+ {20, "20", "20"},
+ {40, "40", "40"},
+ {60, "60", "60"},
+ {0, NULL, NULL}
+ };
+ static volatile GType id = 0;
+ if (g_once_init_enter ((gsize *) & id)) {
+ GType _id;
+
+ _id = g_enum_register_static ("GstOpusEncFrameSize", values);
+
+ g_once_init_leave ((gsize *) & id, _id);
+ }
+
+ return id;
+ }
+
++#define FORMAT_STR GST_AUDIO_NE(S16)
static GstStaticPadTemplate sink_factory = GST_STATIC_PAD_TEMPLATE ("sink",
GST_PAD_SINK,
GST_PAD_ALWAYS,
PROP_PACKET_LOSS_PERCENT, g_param_spec_int ("packet-loss-percentage",
"Loss percentage", "Packet loss percentage", 0, 100,
DEFAULT_PACKET_LOSS_PERCENT,
- G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
+ GST_PARAM_MUTABLE_PLAYING));
+ g_object_class_install_property (G_OBJECT_CLASS (klass),
+ PROP_MAX_PAYLOAD_SIZE, g_param_spec_uint ("max-payload-size",
+ "Max payload size", "Maximum payload size in bytes", 2, 1275,
+ DEFAULT_MAX_PAYLOAD_SIZE,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
+ GST_PARAM_MUTABLE_PLAYING));
gobject_class->finalize = GST_DEBUG_FUNCPTR (gst_opus_enc_finalize);
+
+ GST_DEBUG_CATEGORY_INIT (opusenc_debug, "opusenc", 0, "Opus encoder");
}
static void
{
guint8 *bdata, *data, *mdata = NULL;
gsize bsize, size;
- gsize bytes;
+ gsize bytes = enc->frame_samples * enc->n_channels * 2;
- gsize bytes_per_packet =
- (enc->bitrate * enc->frame_samples / enc->sample_rate + 4) / 8;
gint ret = GST_FLOW_OK;
- if (G_LIKELY (buf)) {
- bdata = GST_BUFFER_DATA (buf);
- bsize = GST_BUFFER_SIZE (buf);
- if (G_UNLIKELY (bsize % bytes)) {
- GST_DEBUG_OBJECT (enc, "draining; adding silence samples");
-
- size = ((bsize / bytes) + 1) * bytes;
- mdata = g_malloc0 (size);
- memcpy (mdata, bdata, bsize);
- bdata = NULL;
- data = mdata;
- } else {
- data = bdata;
- size = bsize;
- }
- } else {
- GST_DEBUG_OBJECT (enc, "nothing to drain");
- goto done;
- }
-
- return ret;
- }
-
- static GstFlowReturn
- gst_opus_enc_encode (GstOpusEnc * enc, GstBuffer * buf)
- {
- guint8 *bdata, *data, *mdata = NULL;
- gsize bsize, size;
- gsize bytes = enc->frame_samples * enc->n_channels * 2;
- gsize bytes_per_packet =
- (enc->bitrate * enc->frame_samples / enc->sample_rate + 4) / 8;
- gint ret = GST_FLOW_OK;
+ g_mutex_lock (enc->property_lock);
- bytes = enc->frame_samples * enc->n_channels * 2;
if (G_LIKELY (buf)) {
- bdata = GST_BUFFER_DATA (buf);
- bsize = GST_BUFFER_SIZE (buf);
+ bdata = gst_buffer_map (buf, &bsize, NULL, GST_MAP_READ);
+
if (G_UNLIKELY (bsize % bytes)) {
GST_DEBUG_OBJECT (enc, "draining; adding silence samples");
goto done;
}
-
while (size) {
- gint outsize;
+ gint encoded_size;
+ unsigned char *out_data;
+ gsize out_size;
GstBuffer *outbuf;
- outbuf = gst_buffer_new_and_alloc (bytes_per_packet);
- ret = gst_pad_alloc_buffer_and_set_caps (GST_AUDIO_ENCODER_SRC_PAD (enc),
- GST_BUFFER_OFFSET_NONE, enc->max_payload_size,
- GST_PAD_CAPS (GST_AUDIO_ENCODER_SRC_PAD (enc)), &outbuf);
-
- if (GST_FLOW_OK != ret)
++ outbuf = gst_buffer_new_and_alloc (enc->max_payload_size);
+ if (!outbuf)
goto done;
- GST_DEBUG_OBJECT (enc, "encoding %d samples (%d bytes) to %d bytes",
- enc->frame_samples, bytes, bytes_per_packet);
+ GST_DEBUG_OBJECT (enc, "encoding %d samples (%d bytes)",
+ enc->frame_samples);
- outsize =
+ out_data = gst_buffer_map (outbuf, &out_size, NULL, GST_MAP_WRITE);
+ encoded_size =
opus_encode (enc->state, (const gint16 *) data, enc->frame_samples,
- out_data, bytes_per_packet);
- GST_BUFFER_DATA (outbuf), enc->max_payload_size);
++ out_data, enc->max_payload_size);
+ gst_buffer_unmap (outbuf, out_data, out_size);
- if (outsize < 0) {
- GST_ERROR_OBJECT (enc, "Encoding failed: %d", outsize);
+ if (encoded_size < 0) {
+ GST_ERROR_OBJECT (enc, "Encoding failed: %d", encoded_size);
ret = GST_FLOW_ERROR;
goto done;
- } else if (encoded_size != bytes_per_packet) {
- } else if (outsize > enc->max_payload_size) {
++ } else if (encoded_size > enc->max_payload_size) {
GST_WARNING_OBJECT (enc,
- "Encoded size %d is different from %d bytes per packet", encoded_size,
- bytes_per_packet);
+ "Encoded size %d is higher than max payload size (%d bytes)",
+ outsize, enc->max_payload_size);
ret = GST_FLOW_ERROR;
goto done;
}
done:
+ if (bdata)
+ gst_buffer_unmap (buf, bdata, bsize);
+ g_mutex_unlock (enc->property_lock);
+
if (mdata)
g_free (mdata);