mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-04-26 06:54:49 +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);
|
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_start (GstAudioDecoder * dec);
|
||||||
static gboolean gst_opus_dec_stop (GstAudioDecoder * dec);
|
static gboolean gst_opus_dec_stop (GstAudioDecoder * dec);
|
||||||
static GstFlowReturn gst_opus_dec_handle_frame (GstAudioDecoder * dec,
|
static GstFlowReturn gst_opus_dec_handle_frame (GstAudioDecoder * dec,
|
||||||
GstBuffer * buffer);
|
GstBuffer * buffer);
|
||||||
static gboolean gst_opus_dec_set_format (GstAudioDecoder * bdec,
|
static gboolean gst_opus_dec_set_format (GstAudioDecoder * bdec,
|
||||||
GstCaps * caps);
|
GstCaps * caps);
|
||||||
static GstFlowReturn opus_dec_chain_parse_data (GstOpusDec * dec,
|
|
||||||
GstBuffer * buf, GstClockTime timestamp, GstClockTime duration);
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gst_opus_dec_class_init (GstOpusDecClass * klass)
|
gst_opus_dec_class_init (GstOpusDecClass * klass)
|
||||||
|
@ -112,8 +112,6 @@ gst_opus_dec_reset (GstOpusDec * dec)
|
||||||
dec->state = NULL;
|
dec->state = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
dec->next_ts = 0;
|
|
||||||
|
|
||||||
gst_buffer_replace (&dec->streamheader, NULL);
|
gst_buffer_replace (&dec->streamheader, NULL);
|
||||||
gst_buffer_replace (&dec->vorbiscomment, NULL);
|
gst_buffer_replace (&dec->vorbiscomment, NULL);
|
||||||
}
|
}
|
||||||
|
@ -167,17 +165,19 @@ gst_opus_dec_setup_from_peer_caps (GstOpusDec * dec)
|
||||||
{
|
{
|
||||||
GstPad *srcpad, *peer;
|
GstPad *srcpad, *peer;
|
||||||
GstStructure *s;
|
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);
|
srcpad = GST_AUDIO_DECODER_SRC_PAD (dec);
|
||||||
peer = gst_pad_get_peer (srcpad);
|
peer = gst_pad_get_peer (srcpad);
|
||||||
|
|
||||||
if (peer) {
|
if (peer) {
|
||||||
template_caps = gst_pad_get_pad_template_caps (srcpad);
|
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);
|
GST_DEBUG_OBJECT (dec, "Peer caps: %" GST_PTR_FORMAT, peer_caps);
|
||||||
caps = gst_caps_intersect (template_caps, 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);
|
GST_DEBUG_OBJECT (dec, "Fixated caps: %" GST_PTR_FORMAT, caps);
|
||||||
|
|
||||||
s = gst_caps_get_structure (caps, 0);
|
s = gst_caps_get_structure (caps, 0);
|
||||||
|
@ -203,8 +203,7 @@ gst_opus_dec_setup_from_peer_caps (GstOpusDec * dec)
|
||||||
}
|
}
|
||||||
|
|
||||||
static GstFlowReturn
|
static GstFlowReturn
|
||||||
opus_dec_chain_parse_data (GstOpusDec * dec, GstBuffer * buf,
|
opus_dec_chain_parse_data (GstOpusDec * dec, GstBuffer * buf)
|
||||||
GstClockTime timestamp, GstClockTime duration)
|
|
||||||
{
|
{
|
||||||
GstFlowReturn res = GST_FLOW_OK;
|
GstFlowReturn res = GST_FLOW_OK;
|
||||||
gsize size, out_size;
|
gsize size, out_size;
|
||||||
|
@ -218,6 +217,8 @@ opus_dec_chain_parse_data (GstOpusDec * dec, GstBuffer * buf,
|
||||||
if (dec->state == NULL) {
|
if (dec->state == NULL) {
|
||||||
gst_opus_dec_setup_from_peer_caps (dec);
|
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);
|
dec->state = opus_decoder_create (dec->sample_rate, dec->n_channels, &err);
|
||||||
if (!dec->state || err != OPUS_OK)
|
if (!dec->state || err != OPUS_OK)
|
||||||
goto creation_failed;
|
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);
|
data = gst_buffer_map (buf, &size, NULL, GST_MAP_READ);
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (dec, "received buffer of size %u", size);
|
GST_DEBUG_OBJECT (dec, "received buffer of size %u", size);
|
||||||
|
|
||||||
/* copy timestamp */
|
|
||||||
} else {
|
} else {
|
||||||
/* concealment data, pass NULL as the bits parameters */
|
/* concealment data, pass NULL as the bits parameters */
|
||||||
GST_DEBUG_OBJECT (dec, "creating concealment data");
|
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);
|
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);
|
res = gst_audio_decoder_finish_frame (GST_AUDIO_DECODER (dec), outbuf, 1);
|
||||||
|
|
||||||
if (res != GST_FLOW_OK)
|
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);
|
gst_audio_decoder_finish_frame (adec, NULL, 1);
|
||||||
res = GST_FLOW_OK;
|
res = GST_FLOW_OK;
|
||||||
} else {
|
} else {
|
||||||
res = opus_dec_chain_parse_data (dec, buf, GST_BUFFER_TIMESTAMP (buf),
|
res = opus_dec_chain_parse_data (dec, buf);
|
||||||
GST_BUFFER_DURATION (buf));
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
/* Otherwise fall back to packet counting and assume that the
|
/* 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);
|
res = gst_opus_dec_parse_header (dec, buf);
|
||||||
gst_audio_decoder_finish_frame (adec, NULL, 1);
|
gst_audio_decoder_finish_frame (adec, NULL, 1);
|
||||||
} else {
|
} else {
|
||||||
res = opus_dec_chain_parse_data (dec, buf, GST_BUFFER_TIMESTAMP (buf),
|
res = opus_dec_chain_parse_data (dec, buf);
|
||||||
GST_BUFFER_DURATION (buf));
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
|
@ -418,14 +401,12 @@ gst_opus_dec_handle_frame (GstAudioDecoder * adec, GstBuffer * buf)
|
||||||
res = gst_opus_dec_parse_comments (dec, buf);
|
res = gst_opus_dec_parse_comments (dec, buf);
|
||||||
gst_audio_decoder_finish_frame (adec, NULL, 1);
|
gst_audio_decoder_finish_frame (adec, NULL, 1);
|
||||||
} else {
|
} else {
|
||||||
res = opus_dec_chain_parse_data (dec, buf, GST_BUFFER_TIMESTAMP (buf),
|
res = opus_dec_chain_parse_data (dec, buf);
|
||||||
GST_BUFFER_DURATION (buf));
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
res = opus_dec_chain_parse_data (dec, buf, GST_BUFFER_TIMESTAMP (buf),
|
res = opus_dec_chain_parse_data (dec, buf);
|
||||||
GST_BUFFER_DURATION (buf));
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -47,7 +47,6 @@ struct _GstOpusDec {
|
||||||
OpusDecoder *state;
|
OpusDecoder *state;
|
||||||
|
|
||||||
guint64 packetno;
|
guint64 packetno;
|
||||||
GstClockTime next_ts;
|
|
||||||
|
|
||||||
GstBuffer *streamheader;
|
GstBuffer *streamheader;
|
||||||
GstBuffer *vorbiscomment;
|
GstBuffer *vorbiscomment;
|
||||||
|
|
|
@ -94,9 +94,7 @@ static GstStaticPadTemplate sink_factory = GST_STATIC_PAD_TEMPLATE ("sink",
|
||||||
static GstStaticPadTemplate src_factory = GST_STATIC_PAD_TEMPLATE ("src",
|
static GstStaticPadTemplate src_factory = GST_STATIC_PAD_TEMPLATE ("src",
|
||||||
GST_PAD_SRC,
|
GST_PAD_SRC,
|
||||||
GST_PAD_ALWAYS,
|
GST_PAD_ALWAYS,
|
||||||
GST_STATIC_CAPS ("audio/x-opus, "
|
GST_STATIC_CAPS ("audio/x-opus")
|
||||||
"rate = (int) { 8000, 12000, 16000, 24000, 48000 }, "
|
|
||||||
"channels = (int) [ 1, 2 ], " "frame-size = (int) [ 2, 60 ]")
|
|
||||||
);
|
);
|
||||||
|
|
||||||
#define DEFAULT_AUDIO TRUE
|
#define DEFAULT_AUDIO TRUE
|
||||||
|
@ -144,6 +142,9 @@ static GstFlowReturn gst_opus_enc_handle_frame (GstAudioEncoder * benc,
|
||||||
GstBuffer * buf);
|
GstBuffer * buf);
|
||||||
static GstFlowReturn gst_opus_enc_pre_push (GstAudioEncoder * benc,
|
static GstFlowReturn gst_opus_enc_pre_push (GstAudioEncoder * benc,
|
||||||
GstBuffer ** buffer);
|
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 GstFlowReturn gst_opus_enc_encode (GstOpusEnc * enc, GstBuffer * buf);
|
||||||
static gint64 gst_opus_enc_get_latency (GstOpusEnc * enc);
|
static gint64 gst_opus_enc_get_latency (GstOpusEnc * enc);
|
||||||
|
@ -157,13 +158,16 @@ static void
|
||||||
gst_opus_enc_class_init (GstOpusEncClass * klass)
|
gst_opus_enc_class_init (GstOpusEncClass * klass)
|
||||||
{
|
{
|
||||||
GObjectClass *gobject_class;
|
GObjectClass *gobject_class;
|
||||||
GstElementClass *element_class;
|
GstElementClass *gstelement_class;
|
||||||
GstAudioEncoderClass *base_class;
|
GstAudioEncoderClass *base_class;
|
||||||
|
|
||||||
gobject_class = (GObjectClass *) klass;
|
gobject_class = (GObjectClass *) klass;
|
||||||
element_class = (GstElementClass *) klass;
|
gstelement_class = (GstElementClass *) klass;
|
||||||
base_class = (GstAudioEncoderClass *) 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_element_class_add_pad_template (element_class,
|
||||||
gst_static_pad_template_get (&src_factory));
|
gst_static_pad_template_get (&src_factory));
|
||||||
gst_element_class_add_pad_template (element_class,
|
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->pre_push = GST_DEBUG_FUNCPTR (gst_opus_enc_pre_push);
|
||||||
base_class->event = GST_DEBUG_FUNCPTR (gst_opus_enc_sink_event);
|
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_object_class_install_property (gobject_class, PROP_AUDIO,
|
||||||
g_param_spec_boolean ("audio", "Audio or voice",
|
g_param_spec_boolean ("audio", "Audio or voice",
|
||||||
"Audio or voice", DEFAULT_AUDIO,
|
"Audio or voice", DEFAULT_AUDIO,
|
||||||
|
@ -205,7 +206,7 @@ gst_opus_enc_class_init (GstOpusEncClass * klass)
|
||||||
"Constant bit rate", DEFAULT_CBR,
|
"Constant bit rate", DEFAULT_CBR,
|
||||||
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
||||||
g_object_class_install_property (gobject_class, PROP_CONSTRAINED_VBR,
|
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,
|
"Constrained VBR", DEFAULT_CONSTRAINED_VBR,
|
||||||
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
||||||
g_object_class_install_property (gobject_class, PROP_COMPLEXITY,
|
g_object_class_install_property (gobject_class, PROP_COMPLEXITY,
|
||||||
|
@ -237,12 +238,11 @@ gst_opus_enc_finalize (GObject * object)
|
||||||
|
|
||||||
enc = GST_OPUS_ENC (object);
|
enc = GST_OPUS_ENC (object);
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (enc, "finalize");
|
|
||||||
G_OBJECT_CLASS (parent_class)->finalize (object);
|
G_OBJECT_CLASS (parent_class)->finalize (object);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gst_opus_enc_init (GstOpusEnc * enc)
|
gst_opus_enc_init (GstOpusEnc * enc, GstOpusEncClass * klass)
|
||||||
{
|
{
|
||||||
GstAudioEncoder *benc = GST_AUDIO_ENCODER (enc);
|
GstAudioEncoder *benc = GST_AUDIO_ENCODER (enc);
|
||||||
|
|
||||||
|
@ -273,7 +273,7 @@ gst_opus_enc_start (GstAudioEncoder * benc)
|
||||||
GstOpusEnc *enc = GST_OPUS_ENC (benc);
|
GstOpusEnc *enc = GST_OPUS_ENC (benc);
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (enc, "start");
|
GST_DEBUG_OBJECT (enc, "start");
|
||||||
enc->tags = gst_tag_list_new_empty ();
|
enc->tags = gst_tag_list_new ();
|
||||||
enc->header_sent = FALSE;
|
enc->header_sent = FALSE;
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
@ -297,6 +297,15 @@ gst_opus_enc_stop (GstAudioEncoder * benc)
|
||||||
return TRUE;
|
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
|
static gint
|
||||||
gst_opus_enc_get_frame_samples (GstOpusEnc * enc)
|
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);
|
opus_encoder_destroy (enc->state);
|
||||||
enc->state = NULL;
|
enc->state = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!gst_opus_enc_setup (enc))
|
if (!gst_opus_enc_setup (enc))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
|
@ -354,7 +362,6 @@ gst_opus_enc_set_format (GstAudioEncoder * benc, GstAudioInfo * info)
|
||||||
/* feedback to base class */
|
/* feedback to base class */
|
||||||
gst_audio_encoder_set_latency (benc,
|
gst_audio_encoder_set_latency (benc,
|
||||||
gst_opus_enc_get_latency (enc), gst_opus_enc_get_latency (enc));
|
gst_opus_enc_get_latency (enc), gst_opus_enc_get_latency (enc));
|
||||||
|
|
||||||
gst_audio_encoder_set_frame_samples_min (benc,
|
gst_audio_encoder_set_frame_samples_min (benc,
|
||||||
enc->frame_samples * enc->n_channels * 2);
|
enc->frame_samples * enc->n_channels * 2);
|
||||||
gst_audio_encoder_set_frame_samples_max (benc,
|
gst_audio_encoder_set_frame_samples_max (benc,
|
||||||
|
@ -364,15 +371,6 @@ gst_opus_enc_set_format (GstAudioEncoder * benc, GstAudioInfo * info)
|
||||||
return TRUE;
|
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 *
|
static GstBuffer *
|
||||||
gst_opus_enc_create_id_buffer (GstOpusEnc * enc)
|
gst_opus_enc_create_id_buffer (GstOpusEnc * enc)
|
||||||
{
|
{
|
||||||
|
@ -495,8 +493,8 @@ gst_opus_enc_sink_event (GstAudioEncoder * benc, GstEvent * event)
|
||||||
static GstFlowReturn
|
static GstFlowReturn
|
||||||
gst_opus_enc_pre_push (GstAudioEncoder * benc, GstBuffer ** buffer)
|
gst_opus_enc_pre_push (GstAudioEncoder * benc, GstBuffer ** buffer)
|
||||||
{
|
{
|
||||||
GstOpusEnc *enc;
|
|
||||||
GstFlowReturn ret = GST_FLOW_OK;
|
GstFlowReturn ret = GST_FLOW_OK;
|
||||||
|
GstOpusEnc *enc;
|
||||||
|
|
||||||
enc = GST_OPUS_ENC (benc);
|
enc = GST_OPUS_ENC (benc);
|
||||||
|
|
||||||
|
@ -522,6 +520,39 @@ gst_opus_enc_pre_push (GstAudioEncoder * benc, GstBuffer ** buffer)
|
||||||
return ret;
|
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
|
static GstFlowReturn
|
||||||
gst_opus_enc_encode (GstOpusEnc * enc, GstBuffer * buf)
|
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;
|
GstFlowReturn ret = GST_FLOW_OK;
|
||||||
|
|
||||||
enc = GST_OPUS_ENC (benc);
|
enc = GST_OPUS_ENC (benc);
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (enc, "handle_frame");
|
GST_DEBUG_OBJECT (enc, "handle_frame");
|
||||||
|
|
||||||
if (!enc->header_sent) {
|
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);
|
buf2 = gst_opus_enc_create_metadata_buffer (enc);
|
||||||
|
|
||||||
/* mark and put on caps */
|
/* mark and put on caps */
|
||||||
caps =
|
caps = gst_caps_from_string ("audio/x-opus");
|
||||||
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_set_buffer_array (caps, "streamheader", buf1, buf2, NULL);
|
caps = _gst_caps_set_buffer_array (caps, "streamheader", buf1, buf2, NULL);
|
||||||
|
|
||||||
/* negotiate with these caps */
|
/* negotiate with these caps */
|
||||||
GST_DEBUG_OBJECT (enc, "here are the caps: %" GST_PTR_FORMAT, 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_pad_set_caps (GST_AUDIO_ENCODER_SRC_PAD (enc), caps);
|
||||||
gst_caps_unref (caps);
|
|
||||||
|
|
||||||
/* push out buffers */
|
/* push out buffers */
|
||||||
/* store buffers for later pre_push sending */
|
/* 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");
|
GST_DEBUG_OBJECT (enc, "storing header buffers");
|
||||||
enc->headers = g_slist_prepend (enc->headers, buf2);
|
enc->headers = g_slist_prepend (enc->headers, buf2);
|
||||||
enc->headers = g_slist_prepend (enc->headers, buf1);
|
enc->headers = g_slist_prepend (enc->headers, buf1);
|
||||||
|
|
||||||
enc->header_sent = TRUE;
|
enc->header_sent = TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (enc, "received buffer %p of %u bytes", buf,
|
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);
|
ret = gst_opus_enc_encode (enc, buf);
|
||||||
|
|
||||||
|
|
|
@ -48,11 +48,7 @@ typedef struct _GstOpusEnc GstOpusEnc;
|
||||||
typedef struct _GstOpusEncClass GstOpusEncClass;
|
typedef struct _GstOpusEncClass GstOpusEncClass;
|
||||||
|
|
||||||
struct _GstOpusEnc {
|
struct _GstOpusEnc {
|
||||||
GstAudioEncoder element;
|
GstAudioEncoder element;
|
||||||
|
|
||||||
/* pads */
|
|
||||||
GstPad *sinkpad;
|
|
||||||
GstPad *srcpad;
|
|
||||||
|
|
||||||
OpusEncoder *state;
|
OpusEncoder *state;
|
||||||
|
|
||||||
|
@ -74,7 +70,8 @@ struct _GstOpusEnc {
|
||||||
|
|
||||||
gboolean setup;
|
gboolean setup;
|
||||||
gboolean header_sent;
|
gboolean header_sent;
|
||||||
GSList *headers;
|
|
||||||
|
GSList *headers;
|
||||||
|
|
||||||
GstTagList *tags;
|
GstTagList *tags;
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in a new issue