static int decode_audio_packet(Group_AV *group_av, Group_Peer_AV *peer_av, int groupnumber, int friendgroupnumber) { if (!group_av || !peer_av) return -1; int success; Group_Audio_Packet *pk = dequeue(peer_av->buffer, &success); if (success == 0) return -1; int16_t *out_audio = NULL; int out_audio_samples = 0; unsigned int sample_rate = 48000; if (success == 1) { int channels = opus_packet_get_nb_channels(pk->data); if (channels == OPUS_INVALID_PACKET) { free(pk); return -1; } if (channels != 1 && channels != 2) { free(pk); return -1; } if (channels != peer_av->decoder_channels) { if (peer_av->audio_decoder) { opus_decoder_destroy(peer_av->audio_decoder); peer_av->audio_decoder = NULL; } int rc; peer_av->audio_decoder = opus_decoder_create(sample_rate, channels, &rc); if (rc != OPUS_OK) { LOGGER_ERROR("Error while starting audio decoder: %s", opus_strerror(rc)); free(pk); return -1; } peer_av->decoder_channels = channels; } int num_samples = opus_decoder_get_nb_samples(peer_av->audio_decoder, pk->data, pk->length); out_audio = malloc(num_samples * peer_av->decoder_channels * sizeof(int16_t)); if (!out_audio) { free(pk); return -1; } out_audio_samples = opus_decode(peer_av->audio_decoder, pk->data, pk->length, out_audio, num_samples, 0); free(pk); if (out_audio_samples <= 0) return -1; peer_av->last_packet_samples = out_audio_samples; } else { if (!peer_av->audio_decoder) return -1; if (!peer_av->last_packet_samples) return -1; out_audio = malloc(peer_av->last_packet_samples * peer_av->decoder_channels * sizeof(int16_t)); if (!out_audio) { free(pk); return -1; } out_audio_samples = opus_decode(peer_av->audio_decoder, NULL, 0, out_audio, peer_av->last_packet_samples, 1); if (out_audio_samples <= 0) return -1; } if (out_audio) { if (group_av->audio_data) group_av->audio_data(group_av->g_c->m, groupnumber, friendgroupnumber, out_audio, out_audio_samples, peer_av->decoder_channels, sample_rate, group_av->userdata); free(out_audio); return 0; } return -1; }
static GstFlowReturn opus_dec_chain_parse_data (GstOpusDec * dec, GstBuffer * buf, GstClockTime timestamp, GstClockTime duration) { GstFlowReturn res = GST_FLOW_OK; gint size; guint8 *data; GstBuffer *outbuf; gint16 *out_data; int n; if (timestamp != -1) { dec->segment.last_stop = timestamp; dec->granulepos = -1; } if (dec->state == NULL) { GstCaps *caps; dec->state = opus_decoder_create (dec->sample_rate, dec->n_channels); /* set caps */ caps = gst_caps_new_simple ("audio/x-raw-int", "rate", G_TYPE_INT, dec->sample_rate, "channels", G_TYPE_INT, dec->n_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->sample_rate, dec->n_channels, dec->frame_size); if (!gst_pad_set_caps (dec->srcpad, caps)) GST_ERROR ("nego failure"); gst_caps_unref (caps); } if (buf) { data = GST_BUFFER_DATA (buf); size = GST_BUFFER_SIZE (buf); 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"); data = NULL; size = 0; } GST_DEBUG ("bandwidth %d", opus_packet_get_bandwidth (data)); GST_DEBUG ("samples_per_frame %d", opus_packet_get_samples_per_frame (data, 48000)); GST_DEBUG ("channels %d", opus_packet_get_nb_channels (data)); res = gst_pad_alloc_buffer_and_set_caps (dec->srcpad, GST_BUFFER_OFFSET_NONE, dec->frame_samples * dec->n_channels * 2, GST_PAD_CAPS (dec->srcpad), &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); GST_LOG_OBJECT (dec, "decoding frame"); n = opus_decode (dec->state, data, size, out_data, dec->frame_samples, TRUE); if (n < 0) { GST_ELEMENT_ERROR (dec, STREAM, DECODE, ("Decoding error: %d", n), (NULL)); return GST_FLOW_ERROR; } if (!GST_CLOCK_TIME_IS_VALID (timestamp)) { timestamp = gst_util_uint64_scale_int (dec->granulepos - dec->frame_size, GST_SECOND, dec->sample_rate); } GST_DEBUG_OBJECT (dec, "timestamp=%" GST_TIME_FORMAT, GST_TIME_ARGS (timestamp)); GST_BUFFER_TIMESTAMP (outbuf) = GST_BUFFER_TIMESTAMP (buf); GST_BUFFER_DURATION (outbuf) = GST_BUFFER_DURATION (buf); if (dec->discont) { GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_FLAG_DISCONT); dec->discont = 0; } dec->segment.last_stop += dec->frame_duration; 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 (dec->frame_duration)); res = gst_pad_push (dec->srcpad, outbuf); if (res != GST_FLOW_OK) GST_DEBUG_OBJECT (dec, "flow: %s", gst_flow_get_name (res)); return res; }
void ac_iterate(ACSession *ac) { if (!ac) { return; } /* TODO(mannol): fix this and jitter buffering */ /* Enough space for the maximum frame size (120 ms 48 KHz stereo audio) */ int16_t tmp[5760 * 2]; struct RTPMessage *msg; int rc = 0; pthread_mutex_lock(ac->queue_mutex); while ((msg = jbuf_read((struct JitterBuffer *)ac->j_buf, &rc)) || rc == 2) { pthread_mutex_unlock(ac->queue_mutex); if (rc == 2) { LOGGER_DEBUG(ac->log, "OPUS correction"); int fs = (ac->lp_sampling_rate * ac->lp_frame_duration) / 1000; rc = opus_decode(ac->decoder, NULL, 0, tmp, fs, 1); } else { /* Get values from packet and decode. */ /* NOTE: This didn't work very well */ #if 0 rc = convert_bw_to_sampling_rate(opus_packet_get_bandwidth(msg->data)); if (rc != -1) { cs->last_packet_sampling_rate = rc; } else { LOGGER_WARNING(ac->log, "Failed to load packet values!"); rtp_free_msg(msg); continue; } #endif /* Pick up sampling rate from packet */ memcpy(&ac->lp_sampling_rate, msg->data, 4); ac->lp_sampling_rate = ntohl(ac->lp_sampling_rate); ac->lp_channel_count = opus_packet_get_nb_channels(msg->data + 4); /** NOTE: even though OPUS supports decoding mono frames with stereo decoder and vice versa, * it didn't work quite well. */ if (!reconfigure_audio_decoder(ac, ac->lp_sampling_rate, ac->lp_channel_count)) { LOGGER_WARNING(ac->log, "Failed to reconfigure decoder!"); free(msg); continue; } rc = opus_decode(ac->decoder, msg->data + 4, msg->len - 4, tmp, 5760, 0); free(msg); } if (rc < 0) { LOGGER_WARNING(ac->log, "Decoding error: %s", opus_strerror(rc)); } else if (ac->acb.first) { ac->lp_frame_duration = (rc * 1000) / ac->lp_sampling_rate; ac->acb.first(ac->av, ac->friend_number, tmp, rc, ac->lp_channel_count, ac->lp_sampling_rate, ac->acb.second); } return; } pthread_mutex_unlock(ac->queue_mutex); }
int opus_decode_native(OpusDecoder *st, const unsigned char *data, opus_int32 len, opus_val16 *pcm, int frame_size, int decode_fec, int self_delimited, opus_int32 *packet_offset, int soft_clip) { int i, nb_samples; int count, offset; unsigned char toc; int packet_frame_size, packet_bandwidth, packet_mode, packet_stream_channels; /* 48 x 2.5 ms = 120 ms */ opus_int16 size[48]; if (decode_fec<0 || decode_fec>1) return OPUS_BAD_ARG; /* For FEC/PLC, frame_size has to be to have a multiple of 2.5 ms */ if ((decode_fec || len==0 || data==NULL) && frame_size%(st->Fs/400)!=0) return OPUS_BAD_ARG; if (len==0 || data==NULL) { int pcm_count=0; do { int ret; ret = opus_decode_frame(st, NULL, 0, pcm+pcm_count*st->channels, frame_size-pcm_count, 0); if (ret<0) return ret; pcm_count += ret; } while (pcm_count < frame_size); celt_assert(pcm_count == frame_size); if (OPUS_CHECK_ARRAY(pcm, pcm_count*st->channels)) OPUS_PRINT_INT(pcm_count); st->last_packet_duration = pcm_count; return pcm_count; } else if (len<0) return OPUS_BAD_ARG; packet_mode = opus_packet_get_mode(data); packet_bandwidth = opus_packet_get_bandwidth(data); packet_frame_size = opus_packet_get_samples_per_frame(data, st->Fs); packet_stream_channels = opus_packet_get_nb_channels(data); count = opus_packet_parse_impl(data, len, self_delimited, &toc, NULL, size, &offset, packet_offset); if (count<0) return count; data += offset; if (decode_fec) { int duration_copy; int ret; /* If no FEC can be present, run the PLC (recursive call) */ if (frame_size < packet_frame_size || packet_mode == MODE_CELT_ONLY || st->mode == MODE_CELT_ONLY) return opus_decode_native(st, NULL, 0, pcm, frame_size, 0, 0, NULL, soft_clip); /* Otherwise, run the PLC on everything except the size for which we might have FEC */ duration_copy = st->last_packet_duration; if (frame_size-packet_frame_size!=0) { ret = opus_decode_native(st, NULL, 0, pcm, frame_size-packet_frame_size, 0, 0, NULL, soft_clip); if (ret<0) { st->last_packet_duration = duration_copy; return ret; } celt_assert(ret==frame_size-packet_frame_size); } /* Complete with FEC */ st->mode = packet_mode; st->bandwidth = packet_bandwidth; st->frame_size = packet_frame_size; st->stream_channels = packet_stream_channels; ret = opus_decode_frame(st, data, size[0], pcm+st->channels*(frame_size-packet_frame_size), packet_frame_size, 1); if (ret<0) return ret; else { if (OPUS_CHECK_ARRAY(pcm, frame_size*st->channels)) OPUS_PRINT_INT(frame_size); st->last_packet_duration = frame_size; return frame_size; } } if (count*packet_frame_size > frame_size) return OPUS_BUFFER_TOO_SMALL; /* Update the state as the last step to avoid updating it on an invalid packet */ st->mode = packet_mode; st->bandwidth = packet_bandwidth; st->frame_size = packet_frame_size; st->stream_channels = packet_stream_channels; nb_samples=0; for (i=0;i<count;i++) { int ret; ret = opus_decode_frame(st, data, size[i], pcm+nb_samples*st->channels, frame_size-nb_samples, 0); if (ret<0) return ret; celt_assert(ret==packet_frame_size); data += size[i]; nb_samples += ret; } st->last_packet_duration = nb_samples; if (OPUS_CHECK_ARRAY(pcm, nb_samples*st->channels)) OPUS_PRINT_INT(nb_samples); #ifndef FIXED_POINT if (soft_clip) opus_pcm_soft_clip(pcm, nb_samples, st->channels, st->softclip_mem); else st->softclip_mem[0]=st->softclip_mem[1]=0; #endif return nb_samples; }
int opus_decode_native(OpusDecoder *st, const unsigned char *data, opus_int32 len, opus_val16 *pcm, int frame_size, int decode_fec, int self_delimited, int *packet_offset) { int i, nb_samples; int count, offset; unsigned char toc; int tot_offset; int packet_frame_size, packet_bandwidth, packet_mode, packet_stream_channels; /* 48 x 2.5 ms = 120 ms */ short size[48]; if (decode_fec<0 || decode_fec>1) return OPUS_BAD_ARG; /* For FEC/PLC, frame_size has to be to have a multiple of 2.5 ms */ if ((decode_fec || len==0 || data==NULL) && frame_size%(st->Fs/400)!=0) return OPUS_BAD_ARG; if (len==0 || data==NULL) { int pcm_count=0; do { int ret; ret = opus_decode_frame(st, NULL, 0, pcm, frame_size-pcm_count, 0); if (ret<0) return ret; pcm += st->channels*ret; pcm_count += ret; } while (pcm_count < frame_size); st->last_packet_duration = pcm_count; return pcm_count; } else if (len<0) return OPUS_BAD_ARG; packet_mode = opus_packet_get_mode(data); packet_bandwidth = opus_packet_get_bandwidth(data); packet_frame_size = opus_packet_get_samples_per_frame(data, st->Fs); packet_stream_channels = opus_packet_get_nb_channels(data); count = opus_packet_parse_impl(data, len, self_delimited, &toc, NULL, size, &offset); data += offset; if (decode_fec) { int duration_copy; int ret; /* If no FEC can be present, run the PLC (recursive call) */ if (frame_size <= packet_frame_size || packet_mode == MODE_CELT_ONLY || st->mode == MODE_CELT_ONLY) return opus_decode_native(st, NULL, 0, pcm, frame_size, 0, 0, NULL); /* Otherwise, run the PLC on everything except the size for which we might have FEC */ duration_copy = st->last_packet_duration; ret = opus_decode_native(st, NULL, 0, pcm, frame_size-packet_frame_size, 0, 0, NULL); if (ret<0) { st->last_packet_duration = duration_copy; return ret; } /* Complete with FEC */ st->mode = packet_mode; st->bandwidth = packet_bandwidth; st->frame_size = packet_frame_size; st->stream_channels = packet_stream_channels; ret = opus_decode_frame(st, data, size[0], pcm+st->channels*(frame_size-packet_frame_size), packet_frame_size, 1); if (ret<0) return ret; st->last_packet_duration = frame_size; return frame_size; } tot_offset = 0; if (count < 0) return count; tot_offset += offset; if (count*packet_frame_size > frame_size) return OPUS_BUFFER_TOO_SMALL; /* Update the state as the last step to avoid updating it on an invalid packet */ st->mode = packet_mode; st->bandwidth = packet_bandwidth; st->frame_size = packet_frame_size; st->stream_channels = packet_stream_channels; nb_samples=0; for (i=0;i<count;i++) { int ret; ret = opus_decode_frame(st, data, size[i], pcm, frame_size-nb_samples, decode_fec); if (ret<0) return ret; data += size[i]; tot_offset += size[i]; pcm += ret*st->channels; nb_samples += ret; } if (packet_offset != NULL) *packet_offset = tot_offset; st->last_packet_duration = nb_samples; return nb_samples; }