diff --git a/ext/opus/gstopusdec.c b/ext/opus/gstopusdec.c index 47c06cec0a..35f501a8ab 100644 --- a/ext/opus/gstopusdec.c +++ b/ext/opus/gstopusdec.c @@ -55,7 +55,7 @@ GST_STATIC_PAD_TEMPLATE ("src", GST_PAD_SRC, GST_PAD_ALWAYS, GST_STATIC_CAPS ("audio/x-raw-int, " - "rate = (int) [ 32000, 64000 ], " + "rate = (int) { 8000, 12000, 16000, 24000, 48000 }, " "channels = (int) [ 1, 2 ], " "endianness = (int) BYTE_ORDER, " "signed = (boolean) true, " "width = (int) 16, " "depth = (int) 16") @@ -193,6 +193,8 @@ opus_dec_sink_setcaps (GstPad * pad, GstCaps * caps) GstStructure *s; const GValue *streamheader; + GST_DEBUG_OBJECT (pad, "Setting sink caps to %" GST_PTR_FORMAT, caps); + s = gst_caps_get_structure (caps, 0); if ((streamheader = gst_structure_get_value (s, "streamheader")) && G_VALUE_HOLDS (streamheader, GST_TYPE_ARRAY) && @@ -237,6 +239,47 @@ opus_dec_sink_setcaps (GstPad * pad, GstCaps * caps) } } + if (!gst_structure_get_int (s, "frame-size", &dec->frame_size)) { + GST_WARNING_OBJECT (dec, "Frame size not included in caps"); + } + if (!gst_structure_get_int (s, "channels", &dec->n_channels)) { + GST_WARNING_OBJECT (dec, "Number of channels not included in caps"); + } + if (!gst_structure_get_int (s, "rate", &dec->sample_rate)) { + GST_WARNING_OBJECT (dec, "Sample rate not included in caps"); + } + switch (dec->frame_size) { + case 2: + dec->frame_samples = dec->sample_rate / 400; + break; + case 5: + dec->frame_samples = dec->sample_rate / 200; + break; + case 10: + dec->frame_samples = dec->sample_rate / 100; + break; + case 20: + dec->frame_samples = dec->sample_rate / 50; + break; + case 40: + dec->frame_samples = dec->sample_rate / 25; + break; + case 60: + dec->frame_samples = 3 * dec->sample_rate / 50; + break; + default: + GST_WARNING_OBJECT (dec, "Unsupported frame size: %d", dec->frame_size); + break; + } + + dec->frame_duration = gst_util_uint64_scale_int (dec->frame_samples, + GST_SECOND, dec->sample_rate); + + GST_INFO_OBJECT (dec, + "Got frame size %d, %d channels, %d Hz, giving %d samples per frame, frame duration %" + GST_TIME_FORMAT, dec->frame_size, dec->n_channels, dec->sample_rate, + dec->frame_samples, GST_TIME_ARGS (dec->frame_duration)); + done: gst_object_unref (dec); return ret; @@ -566,7 +609,7 @@ static GstFlowReturn opus_dec_chain_parse_header (GstOpusDec * dec, GstBuffer * buf) { GstCaps *caps; - //gint error = OPUS_OK; + int err; #if 0 dec->samples_per_frame = opus_packet_get_samples_per_frame ( @@ -578,42 +621,10 @@ opus_dec_chain_parse_header (GstOpusDec * dec, GstBuffer * buf) goto invalid_header; #endif -#if 0 -#ifdef HAVE_OPUS_0_7 - dec->mode = - opus_mode_create (dec->sample_rate, dec->header.frame_size, &error); -#else - dec->mode = - opus_mode_create (dec->sample_rate, dec->header.nb_channels, - dec->header.frame_size, &error); -#endif - if (!dec->mode) - goto mode_init_failed; - - /* initialize the decoder */ -#ifdef HAVE_OPUS_0_11 - dec->state = - opus_decoder_create_custom (dec->mode, dec->header.nb_channels, &error); -#else -#ifdef HAVE_OPUS_0_7 - dec->state = opus_decoder_create (dec->mode, dec->header.nb_channels, &error); -#else - dec->state = opus_decoder_create (dec->mode); -#endif -#endif -#endif - dec->state = opus_decoder_create (dec->sample_rate, dec->n_channels); - if (!dec->state) + dec->state = opus_decoder_create (dec->sample_rate, dec->n_channels, &err); + if (!dec->state || err != OPUS_OK) goto init_failed; -#if 0 -#ifdef HAVE_OPUS_0_8 - dec->frame_size = dec->header.frame_size; -#else - opus_mode_info (dec->mode, OPUS_GET_FRAME_SIZE, &dec->frame_size); -#endif -#endif - dec->frame_duration = gst_util_uint64_scale_int (dec->frame_size, GST_SECOND, dec->sample_rate); @@ -711,7 +722,7 @@ opus_dec_chain_parse_data (GstOpusDec * dec, GstBuffer * buf, guint8 *data; GstBuffer *outbuf; gint16 *out_data; - int n; + int n, err; if (timestamp != -1) { dec->segment.last_stop = timestamp; @@ -721,7 +732,9 @@ opus_dec_chain_parse_data (GstOpusDec * dec, GstBuffer * buf, if (dec->state == NULL) { GstCaps *caps; - dec->state = opus_decoder_create (dec->sample_rate, dec->n_channels); + dec->state = opus_decoder_create (dec->sample_rate, dec->n_channels, &err); + if (!dec->state || err != OPUS_OK) + goto creation_failed; /* set caps */ caps = gst_caps_new_simple ("audio/x-raw-int", @@ -772,7 +785,7 @@ opus_dec_chain_parse_data (GstOpusDec * dec, GstBuffer * buf, GST_LOG_OBJECT (dec, "decoding frame"); - n = opus_decode (dec->state, data, size, out_data, dec->frame_samples, TRUE); + n = opus_decode (dec->state, data, size, out_data, dec->frame_samples, 0); if (n < 0) { GST_ELEMENT_ERROR (dec, STREAM, DECODE, ("Decoding error: %d", n), (NULL)); return GST_FLOW_ERROR; @@ -805,6 +818,10 @@ opus_dec_chain_parse_data (GstOpusDec * dec, GstBuffer * buf, GST_DEBUG_OBJECT (dec, "flow: %s", gst_flow_get_name (res)); return res; + +creation_failed: + GST_ERROR_OBJECT (dec, "Failed to create Opus decoder: %d", err); + return GST_FLOW_ERROR; } static GstFlowReturn @@ -814,6 +831,10 @@ opus_dec_chain (GstPad * pad, GstBuffer * buf) GstOpusDec *dec; dec = GST_OPUS_DEC (gst_pad_get_parent (pad)); + GST_LOG_OBJECT (pad, + "Got buffer ts %" GST_TIME_FORMAT ", duration %" GST_TIME_FORMAT, + GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)), + GST_TIME_ARGS (GST_BUFFER_DURATION (buf))); if (GST_BUFFER_IS_DISCONT (buf)) { dec->discont = TRUE; diff --git a/ext/opus/gstopusenc.c b/ext/opus/gstopusenc.c index db57ff75d1..75ccaaa573 100644 --- a/ext/opus/gstopusenc.c +++ b/ext/opus/gstopusenc.c @@ -63,7 +63,7 @@ gst_opus_enc_bandwidth_get_type (void) {OPUS_BANDWIDTH_WIDEBAND, "Wide band", "wideband"}, {OPUS_BANDWIDTH_SUPERWIDEBAND, "Super wide band", "superwideband"}, {OPUS_BANDWIDTH_FULLBAND, "Full band", "fullband"}, - {OPUS_BANDWIDTH_AUTO, "Auto", "auto"}, + {OPUS_AUTO, "Auto", "auto"}, {0, NULL, NULL} }; static volatile GType id = 0; @@ -286,12 +286,13 @@ gst_opus_enc_sink_setcaps (GstPad * pad, GstCaps * caps) enc->frame_samples = enc->sample_rate / 50; break; case 40: - enc->frame_samples = enc->sample_rate / 20; + enc->frame_samples = enc->sample_rate / 25; break; case 60: enc->frame_samples = 3 * enc->sample_rate / 50; break; default: + GST_WARNING_OBJECT (enc, "Unsupported frame size: %d", enc->frame_size); return FALSE; break; } @@ -664,62 +665,24 @@ gst_opus_enc_create_metadata_buffer (GstOpusEnc * enc) static gboolean gst_opus_enc_setup (GstOpusEnc * enc) { - //gint error = OPUS_OK; + int error = OPUS_OK; enc->setup = FALSE; -#if 0 -#ifdef HAVE_OPUS_0_7 - enc->mode = opus_mode_create (enc->rate, enc->frame_size, &error); -#else - enc->mode = - opus_mode_create (enc->rate, enc->n_channels, enc->frame_size, &error); -#endif - if (!enc->mode) - goto mode_initialization_failed; - -#ifdef HAVE_OPUS_0_11 - opus_header_init (&enc->header, enc->mode, enc->frame_size, enc->n_channels); -#else -#ifdef HAVE_OPUS_0_7 - opus_header_init (&enc->header, enc->mode, enc->n_channels); -#else - opus_header_init (&enc->header, enc->mode); -#endif -#endif - enc->header.nb_channels = enc->n_channels; - -#ifdef HAVE_OPUS_0_8 - enc->frame_size = enc->header.frame_size; -#else - opus_mode_info (enc->mode, OPUS_GET_FRAME_SIZE, &enc->frame_size); -#endif -#endif - -#if 0 -#ifdef HAVE_OPUS_0_11 - enc->state = opus_encoder_create_custom (enc->mode, enc->n_channels, &error); -#else -#ifdef HAVE_OPUS_0_7 - enc->state = opus_encoder_create (enc->mode, enc->n_channels, &error); -#else - enc->state = opus_encoder_create (enc->mode); -#endif -#endif -#endif enc->state = opus_encoder_create (enc->sample_rate, enc->n_channels, - enc->audio_or_voip ? OPUS_APPLICATION_AUDIO : OPUS_APPLICATION_VOIP); - if (!enc->state) + enc->audio_or_voip ? OPUS_APPLICATION_AUDIO : OPUS_APPLICATION_VOIP, + &error); + if (!enc->state || error != OPUS_OK) goto encoder_creation_failed; opus_encoder_ctl (enc->state, OPUS_SET_BITRATE (enc->bitrate), 0); opus_encoder_ctl (enc->state, OPUS_SET_BANDWIDTH (enc->bandwidth), 0); - opus_encoder_ctl (enc->state, OPUS_SET_VBR_FLAG (!enc->cbr), 0); + opus_encoder_ctl (enc->state, OPUS_SET_VBR (!enc->cbr), 0); opus_encoder_ctl (enc->state, OPUS_SET_VBR_CONSTRAINT (enc->constrained_vbr), 0); opus_encoder_ctl (enc->state, OPUS_SET_COMPLEXITY (enc->complexity), 0); - opus_encoder_ctl (enc->state, OPUS_SET_INBAND_FEC_FLAG (enc->inband_fec), 0); - opus_encoder_ctl (enc->state, OPUS_SET_DTX_FLAG (enc->dtx), 0); + opus_encoder_ctl (enc->state, OPUS_SET_INBAND_FEC (enc->inband_fec), 0); + opus_encoder_ctl (enc->state, OPUS_SET_DTX (enc->dtx), 0); opus_encoder_ctl (enc->state, OPUS_SET_PACKET_LOSS_PERC (enc->packet_loss_percentage), 0); @@ -879,6 +842,12 @@ gst_opus_enc_encode (GstOpusEnc * enc, gboolean flush) GST_ERROR_OBJECT (enc, "Encoding failed: %d", outsize); ret = GST_FLOW_ERROR; goto done; + } else if (outsize != bytes_per_packet) { + GST_WARNING_OBJECT (enc, + "Encoded size %d is different from %d bytes per packet", outsize, + bytes_per_packet); + ret = GST_FLOW_ERROR; + goto done; } GST_BUFFER_TIMESTAMP (outbuf) = enc->start_ts + @@ -916,29 +885,10 @@ gst_opus_enc_chain (GstPad * pad, GstBuffer * buf) if (!enc->setup) goto not_setup; -#if 0 if (!enc->header_sent) { - /* Opus streams begin with two headers; the initial header (with - most of the codec setup parameters) which is mandated by the Ogg - bitstream spec. The second header holds any comment fields. - We merely need to make the headers, then pass them to libopus - one at a time; libopus handles the additional Ogg bitstream - constraints */ - GstBuffer *buf1, *buf2; GstCaps *caps; - guchar data[100]; - /* create header buffer */ - opus_header_to_packet (&enc->header, data, 100); - buf1 = gst_opus_enc_buffer_from_data (enc, data, 100, 0); - - /* create comment buffer */ - buf2 = gst_opus_enc_create_metadata_buffer (enc); - - /* mark and put on caps */ caps = gst_pad_get_caps (enc->srcpad); - caps = gst_opus_enc_set_header_on_caps (caps, buf1, buf2); - gst_caps_set_simple (caps, "rate", G_TYPE_INT, enc->sample_rate, "channels", G_TYPE_INT, enc->n_channels, @@ -950,26 +900,8 @@ gst_opus_enc_chain (GstPad * pad, GstBuffer * buf) enc->sample_rate, enc->n_channels, enc->frame_size); gst_pad_set_caps (enc->srcpad, caps); - gst_buffer_set_caps (buf1, caps); - gst_buffer_set_caps (buf2, caps); - gst_caps_unref (caps); - - /* push out buffers */ - ret = gst_opus_enc_push_buffer (enc, buf1); - - if (ret != GST_FLOW_OK) { - gst_buffer_unref (buf2); - goto done; - } - - ret = gst_opus_enc_push_buffer (enc, buf2); - - if (ret != GST_FLOW_OK) - goto done; - enc->header_sent = TRUE; } -#endif GST_DEBUG_OBJECT (enc, "received buffer of %u bytes", GST_BUFFER_SIZE (buf));