diff options
Diffstat (limited to 'toxav/codec.c')
-rw-r--r-- | toxav/codec.c | 78 |
1 files changed, 48 insertions, 30 deletions
diff --git a/toxav/codec.c b/toxav/codec.c index be69ee70..d55cc345 100644 --- a/toxav/codec.c +++ b/toxav/codec.c | |||
@@ -175,7 +175,7 @@ static int jbuf_write(JitterBuffer *q, RTPMessage *m) | |||
175 | unsigned int num = sequnum % q->size; | 175 | unsigned int num = sequnum % q->size; |
176 | 176 | ||
177 | if ((uint32_t)(sequnum - q->bottom) > q->size) { | 177 | if ((uint32_t)(sequnum - q->bottom) > q->size) { |
178 | LOGGER_DEBUG("Clearing jitter: %p", q); | 178 | LOGGER_DEBUG("Clearing filled jitter buffer: %p", q); |
179 | 179 | ||
180 | jbuf_clear(q); | 180 | jbuf_clear(q); |
181 | q->bottom = sequnum - q->capacity; | 181 | q->bottom = sequnum - q->capacity; |
@@ -309,6 +309,32 @@ bool create_video_encoder (vpx_codec_ctx_t* dest, int32_t bitrate) | |||
309 | return true; | 309 | return true; |
310 | } | 310 | } |
311 | 311 | ||
312 | bool reconfigure_audio_decoder(CSession* cs, int32_t sampling_rate, int8_t channels) | ||
313 | { | ||
314 | if (sampling_rate != cs->last_decoding_sampling_rate || channels != cs->last_decoding_channel_count) { | ||
315 | if (current_time_monotonic() - cs->last_decoder_reconfiguration < 500) | ||
316 | return false; | ||
317 | |||
318 | int status; | ||
319 | OpusDecoder* new_dec = opus_decoder_create(sampling_rate, channels, &status ); | ||
320 | if ( status != OPUS_OK ) { | ||
321 | LOGGER_ERROR("Error while starting audio decoder: %s", opus_strerror(status)); | ||
322 | return false; | ||
323 | } | ||
324 | |||
325 | cs->last_decoding_sampling_rate = sampling_rate; | ||
326 | cs->last_decoding_channel_count = channels; | ||
327 | cs->last_decoder_reconfiguration = current_time_monotonic(); | ||
328 | |||
329 | opus_decoder_destroy(cs->audio_decoder); | ||
330 | cs->audio_decoder = new_dec; | ||
331 | |||
332 | LOGGER_DEBUG("Reconfigured audio decoder sr: %d cc: %d", sampling_rate, channels); | ||
333 | } | ||
334 | |||
335 | return true; | ||
336 | } | ||
337 | |||
312 | /* PUBLIC */ | 338 | /* PUBLIC */ |
313 | 339 | ||
314 | void cs_do(CSession *cs) | 340 | void cs_do(CSession *cs) |
@@ -339,7 +365,7 @@ void cs_do(CSession *cs) | |||
339 | if (success == 2) { | 365 | if (success == 2) { |
340 | LOGGER_DEBUG("OPUS correction"); | 366 | LOGGER_DEBUG("OPUS correction"); |
341 | rc = opus_decode(cs->audio_decoder, NULL, 0, tmp, | 367 | rc = opus_decode(cs->audio_decoder, NULL, 0, tmp, |
342 | (cs->last_packet_sampling_rate * cs->last_packet_frame_duration / 1000) * | 368 | (cs->last_packet_sampling_rate * cs->last_packet_frame_duration / 1000) / |
343 | cs->last_packet_channel_count, 1); | 369 | cs->last_packet_channel_count, 1); |
344 | } else { | 370 | } else { |
345 | /* Get values from packet and decode. */ | 371 | /* Get values from packet and decode. */ |
@@ -359,6 +385,17 @@ void cs_do(CSession *cs) | |||
359 | cs->last_packet_sampling_rate = ntohl(cs->last_packet_sampling_rate); | 385 | cs->last_packet_sampling_rate = ntohl(cs->last_packet_sampling_rate); |
360 | 386 | ||
361 | cs->last_packet_channel_count = opus_packet_get_nb_channels(msg->data + 4); | 387 | cs->last_packet_channel_count = opus_packet_get_nb_channels(msg->data + 4); |
388 | |||
389 | /* | ||
390 | * NOTE: even though OPUS supports decoding mono frames with stereo decoder and vice versa, | ||
391 | * it didn't work quite well. | ||
392 | */ | ||
393 | if (!reconfigure_audio_decoder(cs, cs->last_packet_sampling_rate, cs->last_packet_channel_count)) { | ||
394 | LOGGER_WARNING("Failed to reconfigure decoder!"); | ||
395 | rtp_free_msg(NULL, msg); | ||
396 | continue; | ||
397 | } | ||
398 | |||
362 | rc = opus_decode(cs->audio_decoder, msg->data + 4, msg->length - 4, tmp, 5760, 0); | 399 | rc = opus_decode(cs->audio_decoder, msg->data + 4, msg->length - 4, tmp, 5760, 0); |
363 | rtp_free_msg(NULL, msg); | 400 | rtp_free_msg(NULL, msg); |
364 | } | 401 | } |
@@ -366,35 +403,12 @@ void cs_do(CSession *cs) | |||
366 | if (rc < 0) { | 403 | if (rc < 0) { |
367 | LOGGER_WARNING("Decoding error: %s", opus_strerror(rc)); | 404 | LOGGER_WARNING("Decoding error: %s", opus_strerror(rc)); |
368 | } else if (cs->acb.first) { | 405 | } else if (cs->acb.first) { |
406 | cs->last_packet_channel_count = 2; | ||
407 | cs->last_packet_frame_duration = (rc * 1000) / cs->last_packet_sampling_rate * cs->last_packet_channel_count; | ||
369 | 408 | ||
370 | /* Extract channels */ | 409 | cs->acb.first(cs->av, cs->friend_id, tmp, rc * cs->last_packet_channel_count, |
371 | int16_t left[rc/2]; | 410 | cs->last_packet_channel_count, cs->last_packet_sampling_rate, cs->acb.second); |
372 | int16_t right[rc/2]; | ||
373 | int i = 0; | ||
374 | for (; i < rc/2; i ++) { | ||
375 | left[i] = tmp[i * 2]; | ||
376 | right[i] = tmp[(i * 2) + 1]; | ||
377 | } | ||
378 | 411 | ||
379 | if (memcmp(left, right, sizeof(int16_t)) == 0) { | ||
380 | cs->last_packet_channel_count = 1; | ||
381 | cs->last_packet_frame_duration = (rc * 1000) / cs->last_packet_sampling_rate * cs->last_packet_channel_count; | ||
382 | |||
383 | LOGGER_DEBUG("Playing mono audio frame size: %d; srate: %d; duration %d", rc, | ||
384 | cs->last_packet_sampling_rate, cs->last_packet_frame_duration); | ||
385 | |||
386 | cs->acb.first(cs->av, cs->friend_id, right, rc / 2, | ||
387 | cs->last_packet_channel_count, cs->last_packet_sampling_rate, cs->acb.second); | ||
388 | } else { | ||
389 | cs->last_packet_channel_count = 2; | ||
390 | cs->last_packet_frame_duration = (rc * 1000) / cs->last_packet_sampling_rate * cs->last_packet_channel_count; | ||
391 | |||
392 | LOGGER_DEBUG("Playing stereo audio frame size: %d; channels: %d; srate: %d; duration %d", rc, | ||
393 | cs->last_packet_channel_count, cs->last_packet_sampling_rate, cs->last_packet_frame_duration); | ||
394 | |||
395 | cs->acb.first(cs->av, cs->friend_id, tmp, rc, | ||
396 | cs->last_packet_channel_count, cs->last_packet_sampling_rate, cs->acb.second); | ||
397 | } | ||
398 | } | 412 | } |
399 | 413 | ||
400 | LOGGED_LOCK(cs->queue_mutex); | 414 | LOGGED_LOCK(cs->queue_mutex); |
@@ -458,13 +472,17 @@ CSession *cs_new(uint32_t peer_video_frame_piece_size) | |||
458 | */ | 472 | */ |
459 | 473 | ||
460 | int status; | 474 | int status; |
461 | cs->audio_decoder = opus_decoder_create(48000, 2, &status ); /* NOTE: Must be stereo */ | 475 | cs->audio_decoder = opus_decoder_create(48000, 2, &status ); |
462 | 476 | ||
463 | if ( status != OPUS_OK ) { | 477 | if ( status != OPUS_OK ) { |
464 | LOGGER_ERROR("Error while starting audio decoder: %s", opus_strerror(status)); | 478 | LOGGER_ERROR("Error while starting audio decoder: %s", opus_strerror(status)); |
465 | goto FAILURE; | 479 | goto FAILURE; |
466 | } | 480 | } |
467 | 481 | ||
482 | cs->last_decoding_channel_count = 2; | ||
483 | cs->last_decoding_sampling_rate = 48000; | ||
484 | cs->last_decoder_reconfiguration = 0; /* Make it possible to reconfigure straight away */ | ||
485 | |||
468 | /* These need to be set in order to properly | 486 | /* These need to be set in order to properly |
469 | * do error correction with opus */ | 487 | * do error correction with opus */ |
470 | cs->last_packet_frame_duration = 120; | 488 | cs->last_packet_frame_duration = 120; |