mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-03-28 03:45:39 +00:00
Merge branch 'master' into 0.11
Conflicts: ext/celt/gstceltdec.c ext/opus/gstopusdec.c ext/opus/gstopusdec.h ext/opus/gstopusenc.c ext/opus/gstopusenc.h ext/opus/gstopusparse.c
This commit is contained in:
commit
f566dae7dc
4 changed files with 74 additions and 72 deletions
|
@ -67,14 +67,14 @@ GST_STATIC_PAD_TEMPLATE ("sink",
|
|||
|
||||
G_DEFINE_TYPE (GstOpusDec, gst_opus_dec, GST_TYPE_AUDIO_DECODER);
|
||||
|
||||
static GstFlowReturn gst_opus_dec_parse_header (GstOpusDec * dec,
|
||||
GstBuffer * buf);
|
||||
static gboolean gst_opus_dec_start (GstAudioDecoder * dec);
|
||||
static gboolean gst_opus_dec_stop (GstAudioDecoder * dec);
|
||||
static GstFlowReturn gst_opus_dec_handle_frame (GstAudioDecoder * dec,
|
||||
GstBuffer * buffer);
|
||||
static gboolean gst_opus_dec_set_format (GstAudioDecoder * bdec,
|
||||
GstCaps * caps);
|
||||
static GstFlowReturn opus_dec_chain_parse_data (GstOpusDec * dec,
|
||||
GstBuffer * buf, GstClockTime timestamp, GstClockTime duration);
|
||||
|
||||
static void
|
||||
gst_opus_dec_class_init (GstOpusDecClass * klass)
|
||||
|
@ -112,8 +112,6 @@ gst_opus_dec_reset (GstOpusDec * dec)
|
|||
dec->state = NULL;
|
||||
}
|
||||
|
||||
dec->next_ts = 0;
|
||||
|
||||
gst_buffer_replace (&dec->streamheader, NULL);
|
||||
gst_buffer_replace (&dec->vorbiscomment, NULL);
|
||||
}
|
||||
|
@ -167,17 +165,19 @@ gst_opus_dec_setup_from_peer_caps (GstOpusDec * dec)
|
|||
{
|
||||
GstPad *srcpad, *peer;
|
||||
GstStructure *s;
|
||||
GstCaps *caps, *template_caps, *peer_caps;
|
||||
GstCaps *caps;
|
||||
const GstCaps *template_caps;
|
||||
const GstCaps *peer_caps;
|
||||
|
||||
srcpad = GST_AUDIO_DECODER_SRC_PAD (dec);
|
||||
peer = gst_pad_get_peer (srcpad);
|
||||
|
||||
if (peer) {
|
||||
template_caps = gst_pad_get_pad_template_caps (srcpad);
|
||||
peer_caps = gst_pad_get_caps (peer, NULL);
|
||||
peer_caps = gst_pad_get_caps (peer);
|
||||
GST_DEBUG_OBJECT (dec, "Peer caps: %" GST_PTR_FORMAT, peer_caps);
|
||||
caps = gst_caps_intersect (template_caps, peer_caps);
|
||||
gst_caps_fixate (caps);
|
||||
gst_pad_fixate_caps (peer, caps);
|
||||
GST_DEBUG_OBJECT (dec, "Fixated caps: %" GST_PTR_FORMAT, caps);
|
||||
|
||||
s = gst_caps_get_structure (caps, 0);
|
||||
|
@ -203,8 +203,7 @@ gst_opus_dec_setup_from_peer_caps (GstOpusDec * dec)
|
|||
}
|
||||
|
||||
static GstFlowReturn
|
||||
opus_dec_chain_parse_data (GstOpusDec * dec, GstBuffer * buf,
|
||||
GstClockTime timestamp, GstClockTime duration)
|
||||
opus_dec_chain_parse_data (GstOpusDec * dec, GstBuffer * buf)
|
||||
{
|
||||
GstFlowReturn res = GST_FLOW_OK;
|
||||
gsize size, out_size;
|
||||
|
@ -218,6 +217,8 @@ opus_dec_chain_parse_data (GstOpusDec * dec, GstBuffer * buf,
|
|||
if (dec->state == NULL) {
|
||||
gst_opus_dec_setup_from_peer_caps (dec);
|
||||
|
||||
GST_DEBUG_OBJECT (dec, "Creating decoder with %d channels, %d Hz",
|
||||
dec->n_channels, dec->sample_rate);
|
||||
dec->state = opus_decoder_create (dec->sample_rate, dec->n_channels, &err);
|
||||
if (!dec->state || err != OPUS_OK)
|
||||
goto creation_failed;
|
||||
|
@ -227,8 +228,6 @@ opus_dec_chain_parse_data (GstOpusDec * dec, GstBuffer * buf,
|
|||
data = gst_buffer_map (buf, &size, NULL, GST_MAP_READ);
|
||||
|
||||
GST_DEBUG_OBJECT (dec, "received buffer of size %u", size);
|
||||
|
||||
/* copy timestamp */
|
||||
} else {
|
||||
/* concealment data, pass NULL as the bits parameters */
|
||||
GST_DEBUG_OBJECT (dec, "creating concealment data");
|
||||
|
@ -261,20 +260,6 @@ opus_dec_chain_parse_data (GstOpusDec * dec, GstBuffer * buf,
|
|||
}
|
||||
GST_DEBUG_OBJECT (dec, "decoded %d samples", n);
|
||||
|
||||
if (GST_CLOCK_TIME_IS_VALID (timestamp)) {
|
||||
GST_BUFFER_TIMESTAMP (outbuf) = timestamp;
|
||||
} else {
|
||||
GST_BUFFER_TIMESTAMP (outbuf) = dec->next_ts;
|
||||
}
|
||||
|
||||
GST_BUFFER_DURATION (outbuf) =
|
||||
gst_util_uint64_scale (n, GST_SECOND, dec->sample_rate);
|
||||
dec->next_ts = GST_BUFFER_TIMESTAMP (outbuf) + GST_BUFFER_DURATION (outbuf);
|
||||
|
||||
GST_LOG_OBJECT (dec, "pushing buffer with ts=%" GST_TIME_FORMAT ", dur=%"
|
||||
GST_TIME_FORMAT, GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (outbuf)),
|
||||
GST_TIME_ARGS (GST_BUFFER_DURATION (outbuf)));
|
||||
|
||||
res = gst_audio_decoder_finish_frame (GST_AUDIO_DECODER (dec), outbuf, 1);
|
||||
|
||||
if (res != GST_FLOW_OK)
|
||||
|
@ -395,8 +380,7 @@ gst_opus_dec_handle_frame (GstAudioDecoder * adec, GstBuffer * buf)
|
|||
gst_audio_decoder_finish_frame (adec, NULL, 1);
|
||||
res = GST_FLOW_OK;
|
||||
} else {
|
||||
res = opus_dec_chain_parse_data (dec, buf, GST_BUFFER_TIMESTAMP (buf),
|
||||
GST_BUFFER_DURATION (buf));
|
||||
res = opus_dec_chain_parse_data (dec, buf);
|
||||
}
|
||||
} else {
|
||||
/* Otherwise fall back to packet counting and assume that the
|
||||
|
@ -408,8 +392,7 @@ gst_opus_dec_handle_frame (GstAudioDecoder * adec, GstBuffer * buf)
|
|||
res = gst_opus_dec_parse_header (dec, buf);
|
||||
gst_audio_decoder_finish_frame (adec, NULL, 1);
|
||||
} else {
|
||||
res = opus_dec_chain_parse_data (dec, buf, GST_BUFFER_TIMESTAMP (buf),
|
||||
GST_BUFFER_DURATION (buf));
|
||||
res = opus_dec_chain_parse_data (dec, buf);
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
|
@ -418,14 +401,12 @@ gst_opus_dec_handle_frame (GstAudioDecoder * adec, GstBuffer * buf)
|
|||
res = gst_opus_dec_parse_comments (dec, buf);
|
||||
gst_audio_decoder_finish_frame (adec, NULL, 1);
|
||||
} else {
|
||||
res = opus_dec_chain_parse_data (dec, buf, GST_BUFFER_TIMESTAMP (buf),
|
||||
GST_BUFFER_DURATION (buf));
|
||||
res = opus_dec_chain_parse_data (dec, buf);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
{
|
||||
res = opus_dec_chain_parse_data (dec, buf, GST_BUFFER_TIMESTAMP (buf),
|
||||
GST_BUFFER_DURATION (buf));
|
||||
res = opus_dec_chain_parse_data (dec, buf);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -47,7 +47,6 @@ struct _GstOpusDec {
|
|||
OpusDecoder *state;
|
||||
|
||||
guint64 packetno;
|
||||
GstClockTime next_ts;
|
||||
|
||||
GstBuffer *streamheader;
|
||||
GstBuffer *vorbiscomment;
|
||||
|
|
|
@ -94,9 +94,7 @@ static GstStaticPadTemplate sink_factory = GST_STATIC_PAD_TEMPLATE ("sink",
|
|||
static GstStaticPadTemplate src_factory = GST_STATIC_PAD_TEMPLATE ("src",
|
||||
GST_PAD_SRC,
|
||||
GST_PAD_ALWAYS,
|
||||
GST_STATIC_CAPS ("audio/x-opus, "
|
||||
"rate = (int) { 8000, 12000, 16000, 24000, 48000 }, "
|
||||
"channels = (int) [ 1, 2 ], " "frame-size = (int) [ 2, 60 ]")
|
||||
GST_STATIC_CAPS ("audio/x-opus")
|
||||
);
|
||||
|
||||
#define DEFAULT_AUDIO TRUE
|
||||
|
@ -144,6 +142,9 @@ static GstFlowReturn gst_opus_enc_handle_frame (GstAudioEncoder * benc,
|
|||
GstBuffer * buf);
|
||||
static GstFlowReturn gst_opus_enc_pre_push (GstAudioEncoder * benc,
|
||||
GstBuffer ** buffer);
|
||||
static gint64 gst_opus_enc_get_latency (GstOpusEnc * enc);
|
||||
|
||||
static GstFlowReturn gst_opus_enc_encode (GstOpusEnc * enc, GstBuffer * buffer);
|
||||
|
||||
static GstFlowReturn gst_opus_enc_encode (GstOpusEnc * enc, GstBuffer * buf);
|
||||
static gint64 gst_opus_enc_get_latency (GstOpusEnc * enc);
|
||||
|
@ -157,13 +158,16 @@ static void
|
|||
gst_opus_enc_class_init (GstOpusEncClass * klass)
|
||||
{
|
||||
GObjectClass *gobject_class;
|
||||
GstElementClass *element_class;
|
||||
GstElementClass *gstelement_class;
|
||||
GstAudioEncoderClass *base_class;
|
||||
|
||||
gobject_class = (GObjectClass *) klass;
|
||||
element_class = (GstElementClass *) klass;
|
||||
gstelement_class = (GstElementClass *) klass;
|
||||
base_class = (GstAudioEncoderClass *) klass;
|
||||
|
||||
gobject_class->set_property = gst_opus_enc_set_property;
|
||||
gobject_class->get_property = gst_opus_enc_get_property;
|
||||
|
||||
gst_element_class_add_pad_template (element_class,
|
||||
gst_static_pad_template_get (&src_factory));
|
||||
gst_element_class_add_pad_template (element_class,
|
||||
|
@ -180,9 +184,6 @@ gst_opus_enc_class_init (GstOpusEncClass * klass)
|
|||
base_class->pre_push = GST_DEBUG_FUNCPTR (gst_opus_enc_pre_push);
|
||||
base_class->event = GST_DEBUG_FUNCPTR (gst_opus_enc_sink_event);
|
||||
|
||||
gobject_class->set_property = gst_opus_enc_set_property;
|
||||
gobject_class->get_property = gst_opus_enc_get_property;
|
||||
|
||||
g_object_class_install_property (gobject_class, PROP_AUDIO,
|
||||
g_param_spec_boolean ("audio", "Audio or voice",
|
||||
"Audio or voice", DEFAULT_AUDIO,
|
||||
|
@ -205,7 +206,7 @@ gst_opus_enc_class_init (GstOpusEncClass * klass)
|
|||
"Constant bit rate", DEFAULT_CBR,
|
||||
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
||||
g_object_class_install_property (gobject_class, PROP_CONSTRAINED_VBR,
|
||||
g_param_spec_boolean ("constrained-cbr", "Constrained VBR",
|
||||
g_param_spec_boolean ("constrained-vbr", "Constrained VBR",
|
||||
"Constrained VBR", DEFAULT_CONSTRAINED_VBR,
|
||||
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
||||
g_object_class_install_property (gobject_class, PROP_COMPLEXITY,
|
||||
|
@ -237,12 +238,11 @@ gst_opus_enc_finalize (GObject * object)
|
|||
|
||||
enc = GST_OPUS_ENC (object);
|
||||
|
||||
GST_DEBUG_OBJECT (enc, "finalize");
|
||||
G_OBJECT_CLASS (parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
gst_opus_enc_init (GstOpusEnc * enc)
|
||||
gst_opus_enc_init (GstOpusEnc * enc, GstOpusEncClass * klass)
|
||||
{
|
||||
GstAudioEncoder *benc = GST_AUDIO_ENCODER (enc);
|
||||
|
||||
|
@ -273,7 +273,7 @@ gst_opus_enc_start (GstAudioEncoder * benc)
|
|||
GstOpusEnc *enc = GST_OPUS_ENC (benc);
|
||||
|
||||
GST_DEBUG_OBJECT (enc, "start");
|
||||
enc->tags = gst_tag_list_new_empty ();
|
||||
enc->tags = gst_tag_list_new ();
|
||||
enc->header_sent = FALSE;
|
||||
return TRUE;
|
||||
}
|
||||
|
@ -297,6 +297,15 @@ gst_opus_enc_stop (GstAudioEncoder * benc)
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
static gint64
|
||||
gst_opus_enc_get_latency (GstOpusEnc * enc)
|
||||
{
|
||||
gint64 latency = gst_util_uint64_scale (enc->frame_samples, GST_SECOND,
|
||||
enc->sample_rate);
|
||||
GST_DEBUG_OBJECT (enc, "Latency: %" GST_TIME_FORMAT, GST_TIME_ARGS (latency));
|
||||
return latency;
|
||||
}
|
||||
|
||||
static gint
|
||||
gst_opus_enc_get_frame_samples (GstOpusEnc * enc)
|
||||
{
|
||||
|
@ -345,7 +354,6 @@ gst_opus_enc_set_format (GstAudioEncoder * benc, GstAudioInfo * info)
|
|||
opus_encoder_destroy (enc->state);
|
||||
enc->state = NULL;
|
||||
}
|
||||
|
||||
if (!gst_opus_enc_setup (enc))
|
||||
return FALSE;
|
||||
|
||||
|
@ -354,7 +362,6 @@ gst_opus_enc_set_format (GstAudioEncoder * benc, GstAudioInfo * info)
|
|||
/* feedback to base class */
|
||||
gst_audio_encoder_set_latency (benc,
|
||||
gst_opus_enc_get_latency (enc), gst_opus_enc_get_latency (enc));
|
||||
|
||||
gst_audio_encoder_set_frame_samples_min (benc,
|
||||
enc->frame_samples * enc->n_channels * 2);
|
||||
gst_audio_encoder_set_frame_samples_max (benc,
|
||||
|
@ -364,15 +371,6 @@ gst_opus_enc_set_format (GstAudioEncoder * benc, GstAudioInfo * info)
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
static gint64
|
||||
gst_opus_enc_get_latency (GstOpusEnc * enc)
|
||||
{
|
||||
gint64 latency = gst_util_uint64_scale (enc->frame_samples, GST_SECOND,
|
||||
enc->sample_rate);
|
||||
GST_DEBUG_OBJECT (enc, "Latency: %" GST_TIME_FORMAT, GST_TIME_ARGS (latency));
|
||||
return latency;
|
||||
}
|
||||
|
||||
static GstBuffer *
|
||||
gst_opus_enc_create_id_buffer (GstOpusEnc * enc)
|
||||
{
|
||||
|
@ -495,8 +493,8 @@ gst_opus_enc_sink_event (GstAudioEncoder * benc, GstEvent * event)
|
|||
static GstFlowReturn
|
||||
gst_opus_enc_pre_push (GstAudioEncoder * benc, GstBuffer ** buffer)
|
||||
{
|
||||
GstOpusEnc *enc;
|
||||
GstFlowReturn ret = GST_FLOW_OK;
|
||||
GstOpusEnc *enc;
|
||||
|
||||
enc = GST_OPUS_ENC (benc);
|
||||
|
||||
|
@ -522,6 +520,39 @@ gst_opus_enc_pre_push (GstAudioEncoder * benc, GstBuffer ** buffer)
|
|||
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;
|
||||
|
||||
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)
|
||||
{
|
||||
|
@ -669,7 +700,6 @@ gst_opus_enc_handle_frame (GstAudioEncoder * benc, GstBuffer * buf)
|
|||
GstFlowReturn ret = GST_FLOW_OK;
|
||||
|
||||
enc = GST_OPUS_ENC (benc);
|
||||
|
||||
GST_DEBUG_OBJECT (enc, "handle_frame");
|
||||
|
||||
if (!enc->header_sent) {
|
||||
|
@ -684,17 +714,13 @@ gst_opus_enc_handle_frame (GstAudioEncoder * benc, GstBuffer * buf)
|
|||
buf2 = gst_opus_enc_create_metadata_buffer (enc);
|
||||
|
||||
/* mark and put on caps */
|
||||
caps =
|
||||
gst_caps_new_simple ("audio/x-opus", "rate", G_TYPE_INT,
|
||||
enc->sample_rate, "channels", G_TYPE_INT, enc->n_channels, "frame-size",
|
||||
G_TYPE_INT, enc->frame_size, NULL);
|
||||
caps = gst_caps_from_string ("audio/x-opus");
|
||||
caps = _gst_caps_set_buffer_array (caps, "streamheader", buf1, buf2, NULL);
|
||||
|
||||
/* negotiate with these caps */
|
||||
GST_DEBUG_OBJECT (enc, "here are the caps: %" GST_PTR_FORMAT, caps);
|
||||
|
||||
gst_pad_set_caps (GST_AUDIO_ENCODER_SRC_PAD (enc), caps);
|
||||
gst_caps_unref (caps);
|
||||
|
||||
/* push out buffers */
|
||||
/* store buffers for later pre_push sending */
|
||||
|
@ -703,12 +729,11 @@ gst_opus_enc_handle_frame (GstAudioEncoder * benc, GstBuffer * buf)
|
|||
GST_DEBUG_OBJECT (enc, "storing header buffers");
|
||||
enc->headers = g_slist_prepend (enc->headers, buf2);
|
||||
enc->headers = g_slist_prepend (enc->headers, buf1);
|
||||
|
||||
enc->header_sent = TRUE;
|
||||
}
|
||||
|
||||
GST_DEBUG_OBJECT (enc, "received buffer %p of %u bytes", buf,
|
||||
buf ? gst_buffer_get_size (buf) : 0);
|
||||
buf ? GST_BUFFER_SIZE (buf) : 0);
|
||||
|
||||
ret = gst_opus_enc_encode (enc, buf);
|
||||
|
||||
|
|
|
@ -48,11 +48,7 @@ typedef struct _GstOpusEnc GstOpusEnc;
|
|||
typedef struct _GstOpusEncClass GstOpusEncClass;
|
||||
|
||||
struct _GstOpusEnc {
|
||||
GstAudioEncoder element;
|
||||
|
||||
/* pads */
|
||||
GstPad *sinkpad;
|
||||
GstPad *srcpad;
|
||||
GstAudioEncoder element;
|
||||
|
||||
OpusEncoder *state;
|
||||
|
||||
|
@ -74,7 +70,8 @@ struct _GstOpusEnc {
|
|||
|
||||
gboolean setup;
|
||||
gboolean header_sent;
|
||||
GSList *headers;
|
||||
|
||||
GSList *headers;
|
||||
|
||||
GstTagList *tags;
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue