diff options
Diffstat (limited to 'toxav/codec.c')
-rw-r--r-- | toxav/codec.c | 187 |
1 files changed, 46 insertions, 141 deletions
diff --git a/toxav/codec.c b/toxav/codec.c index a72b2764..b9cbbc06 100644 --- a/toxav/codec.c +++ b/toxav/codec.c | |||
@@ -38,7 +38,7 @@ | |||
38 | #include "rtp.h" | 38 | #include "rtp.h" |
39 | #include "codec.h" | 39 | #include "codec.h" |
40 | 40 | ||
41 | #define DEFAULT_JBUF 6 | 41 | #define DEFAULT_JBUF 3 |
42 | 42 | ||
43 | /* Good quality encode. */ | 43 | /* Good quality encode. */ |
44 | #define MAX_DECODE_TIME_US 0 | 44 | #define MAX_DECODE_TIME_US 0 |
@@ -175,6 +175,8 @@ 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); | ||
179 | |||
178 | jbuf_clear(q); | 180 | jbuf_clear(q); |
179 | q->bottom = sequnum - q->capacity; | 181 | q->bottom = sequnum - q->capacity; |
180 | q->queue[num] = m; | 182 | q->queue[num] = m; |
@@ -193,7 +195,7 @@ static int jbuf_write(JitterBuffer *q, RTPMessage *m) | |||
193 | return 0; | 195 | return 0; |
194 | } | 196 | } |
195 | 197 | ||
196 | /* Success is 0 when there is nothing to dequeue, | 198 | /* success is set to 0 when there is nothing to dequeue, |
197 | * 1 when there's a good packet, | 199 | * 1 when there's a good packet, |
198 | * 2 when there's a lost packet */ | 200 | * 2 when there's a lost packet */ |
199 | static RTPMessage *jbuf_read(JitterBuffer *q, int32_t *success) | 201 | static RTPMessage *jbuf_read(JitterBuffer *q, int32_t *success) |
@@ -237,62 +239,6 @@ static int convert_bw_to_sampling_rate(int bw) | |||
237 | } | 239 | } |
238 | 240 | ||
239 | 241 | ||
240 | int cs_set_receiving_audio_bitrate(CSSession *cs, int32_t rate) | ||
241 | { | ||
242 | if (cs->audio_decoder == NULL) | ||
243 | return -1; | ||
244 | |||
245 | int rc = opus_decoder_ctl(cs->audio_decoder, OPUS_SET_BITRATE(rate)); | ||
246 | |||
247 | if ( rc != OPUS_OK ) { | ||
248 | LOGGER_ERROR("Error while setting decoder ctl: %s", opus_strerror(rc)); | ||
249 | return -1; | ||
250 | } | ||
251 | |||
252 | LOGGER_DEBUG("Set new decoder bitrate to: %d", rate); | ||
253 | return 0; | ||
254 | } | ||
255 | |||
256 | int cs_set_receiving_audio_sampling_rate(CSSession* cs, int32_t rate) | ||
257 | { | ||
258 | /* TODO Find a better way? */ | ||
259 | if (cs->audio_decoder == NULL) | ||
260 | return -1; | ||
261 | |||
262 | if (cs->decoder_sample_rate == rate) | ||
263 | return 0; | ||
264 | |||
265 | int channels = cs->decoder_channels; | ||
266 | |||
267 | cs_disable_audio_receiving(cs); | ||
268 | |||
269 | cs->decoder_sample_rate = rate; | ||
270 | cs->decoder_channels = channels; | ||
271 | |||
272 | LOGGER_DEBUG("Set new encoder sampling rate: %d", rate); | ||
273 | return cs_enable_audio_receiving(cs); | ||
274 | } | ||
275 | |||
276 | int cs_set_receiving_audio_channels(CSSession* cs, int32_t count) | ||
277 | { | ||
278 | /* TODO Find a better way? */ | ||
279 | if (cs->audio_decoder == NULL) | ||
280 | return -1; | ||
281 | |||
282 | if (cs->decoder_channels == count) | ||
283 | return 0; | ||
284 | |||
285 | int srate = cs->decoder_sample_rate; | ||
286 | cs_disable_audio_receiving(cs); | ||
287 | |||
288 | cs->decoder_channels = count; | ||
289 | cs->decoder_sample_rate = srate; | ||
290 | |||
291 | LOGGER_DEBUG("Set new encoder channel count: %d", count); | ||
292 | return cs_enable_audio_receiving(cs); | ||
293 | } | ||
294 | |||
295 | |||
296 | /* PUBLIC */ | 242 | /* PUBLIC */ |
297 | 243 | ||
298 | void cs_do(CSSession *cs) | 244 | void cs_do(CSSession *cs) |
@@ -310,17 +256,19 @@ void cs_do(CSSession *cs) | |||
310 | 256 | ||
311 | pthread_mutex_lock(cs->queue_mutex); | 257 | pthread_mutex_lock(cs->queue_mutex); |
312 | 258 | ||
259 | /********************* AUDIO *********************/ | ||
313 | if (cs->audio_decoder) { /* If receiving enabled */ | 260 | if (cs->audio_decoder) { /* If receiving enabled */ |
314 | RTPMessage *msg; | 261 | RTPMessage *msg; |
315 | 262 | ||
316 | uint16_t fsize = 10000; /* Should be enough for all normal frequences */ | 263 | /* The maximum for 120 ms 48 KHz audio */ |
317 | int16_t tmp[fsize * 2]; | 264 | int16_t tmp[20000]; |
318 | 265 | ||
319 | while ((msg = jbuf_read(cs->j_buf, &success)) || success == 2) { | 266 | while ((msg = jbuf_read(cs->j_buf, &success)) || success == 2) { |
320 | pthread_mutex_unlock(cs->queue_mutex); | 267 | pthread_mutex_unlock(cs->queue_mutex); |
321 | 268 | ||
322 | if (success == 2) { | 269 | if (success == 2) { |
323 | rc = opus_decode(cs->audio_decoder, 0, 0, tmp, fsize, 1); | 270 | rc = opus_decode(cs->audio_decoder, NULL, 0, tmp, |
271 | cs->last_packet_sampling_rate * cs->last_packet_frame_duration / 1000, 1); | ||
324 | } else { | 272 | } else { |
325 | /* Get values from packet and decode. | 273 | /* Get values from packet and decode. |
326 | * It also checks for validity of an opus packet | 274 | * It also checks for validity of an opus packet |
@@ -328,7 +276,7 @@ void cs_do(CSSession *cs) | |||
328 | rc = convert_bw_to_sampling_rate(opus_packet_get_bandwidth(msg->data)); | 276 | rc = convert_bw_to_sampling_rate(opus_packet_get_bandwidth(msg->data)); |
329 | if (rc != -1) { | 277 | if (rc != -1) { |
330 | cs->last_packet_sampling_rate = rc; | 278 | cs->last_packet_sampling_rate = rc; |
331 | cs->last_pack_channels = opus_packet_get_nb_channels(msg->data); | 279 | cs->last_packet_channels = opus_packet_get_nb_channels(msg->data); |
332 | 280 | ||
333 | cs->last_packet_frame_duration = | 281 | cs->last_packet_frame_duration = |
334 | ( opus_packet_get_samples_per_frame(msg->data, cs->last_packet_sampling_rate) * 1000 ) | 282 | ( opus_packet_get_samples_per_frame(msg->data, cs->last_packet_sampling_rate) * 1000 ) |
@@ -339,11 +287,7 @@ void cs_do(CSSession *cs) | |||
339 | continue; | 287 | continue; |
340 | } | 288 | } |
341 | 289 | ||
342 | cs_set_receiving_audio_sampling_rate(cs, cs->last_packet_sampling_rate); | 290 | rc = opus_decode(cs->audio_decoder, msg->data, msg->length, tmp, sizeof(tmp), 0); |
343 | cs_set_receiving_audio_channels(cs, cs->last_pack_channels); | ||
344 | |||
345 | LOGGER_DEBUG("Decoding packet of length: %d", msg->length); | ||
346 | rc = opus_decode(cs->audio_decoder, msg->data, msg->length, tmp, fsize, 0); | ||
347 | rtp_free_msg(NULL, msg); | 291 | rtp_free_msg(NULL, msg); |
348 | } | 292 | } |
349 | 293 | ||
@@ -351,15 +295,28 @@ void cs_do(CSSession *cs) | |||
351 | LOGGER_WARNING("Decoding error: %s", opus_strerror(rc)); | 295 | LOGGER_WARNING("Decoding error: %s", opus_strerror(rc)); |
352 | } else if (cs->acb.first) { | 296 | } else if (cs->acb.first) { |
353 | /* Play */ | 297 | /* Play */ |
354 | LOGGER_DEBUG("Playing audio frame size: %d chans: %d srate: %d", rc, cs->last_pack_channels, cs->last_packet_sampling_rate); | 298 | |
299 | LOGGER_DEBUG("Playing audio frame size: %d; channels: %d; srate: %d; duration %d", rc, | ||
300 | cs->last_packet_channels, cs->last_packet_sampling_rate, cs->last_packet_frame_duration); | ||
301 | |||
302 | /* According to https://tools.ietf.org/html/rfc6716#section-2.1.2 | ||
303 | * Every encoder can encode both mono and stereo data so we must | ||
304 | * determine which format is selected. | ||
305 | */ | ||
306 | |||
307 | if (cs->last_packet_channels == 2) { | ||
308 | /* The packet is encoded with stereo encoder */ | ||
309 | } | ||
310 | |||
355 | cs->acb.first(cs->agent, cs->friend_id, tmp, rc, | 311 | cs->acb.first(cs->agent, cs->friend_id, tmp, rc, |
356 | cs->last_pack_channels, cs->last_packet_sampling_rate, cs->acb.second); | 312 | cs->last_packet_channels, cs->last_packet_sampling_rate, cs->acb.second); |
357 | } | 313 | } |
358 | 314 | ||
359 | pthread_mutex_lock(cs->queue_mutex); | 315 | pthread_mutex_lock(cs->queue_mutex); |
360 | } | 316 | } |
361 | } | 317 | } |
362 | 318 | ||
319 | /********************* VIDEO *********************/ | ||
363 | if (cs->vbuf_raw && !buffer_empty(cs->vbuf_raw)) { | 320 | if (cs->vbuf_raw && !buffer_empty(cs->vbuf_raw)) { |
364 | /* Decode video */ | 321 | /* Decode video */ |
365 | buffer_read(cs->vbuf_raw, &p); | 322 | buffer_read(cs->vbuf_raw, &p); |
@@ -411,8 +368,6 @@ CSSession *cs_new(uint32_t peer_video_frame_piece_size) | |||
411 | 368 | ||
412 | cs->peer_video_frame_piece_size = peer_video_frame_piece_size; | 369 | cs->peer_video_frame_piece_size = peer_video_frame_piece_size; |
413 | 370 | ||
414 | cs->decoder_sample_rate = 48000; | ||
415 | cs->decoder_channels = 2; | ||
416 | return cs; | 371 | return cs; |
417 | } | 372 | } |
418 | 373 | ||
@@ -538,6 +493,8 @@ int cs_set_sending_video_bitrate(CSSession *cs, uint32_t bitrate) | |||
538 | return 0; | 493 | return 0; |
539 | } | 494 | } |
540 | 495 | ||
496 | |||
497 | |||
541 | int cs_enable_video_sending(CSSession* cs, uint32_t bitrate) | 498 | int cs_enable_video_sending(CSSession* cs, uint32_t bitrate) |
542 | { | 499 | { |
543 | if (cs->v_encoding) | 500 | if (cs->v_encoding) |
@@ -619,6 +576,8 @@ FAILURE: | |||
619 | return -1; | 576 | return -1; |
620 | } | 577 | } |
621 | 578 | ||
579 | |||
580 | |||
622 | void cs_disable_video_sending(CSSession* cs) | 581 | void cs_disable_video_sending(CSSession* cs) |
623 | { | 582 | { |
624 | if (cs->v_encoding) { | 583 | if (cs->v_encoding) { |
@@ -663,64 +622,13 @@ int cs_set_sending_audio_bitrate(CSSession *cs, int32_t rate) | |||
663 | return 0; | 622 | return 0; |
664 | } | 623 | } |
665 | 624 | ||
666 | int cs_set_sending_audio_sampling_rate(CSSession* cs, int32_t rate) | ||
667 | { | ||
668 | /* TODO Find a better way? */ | ||
669 | if (cs->audio_encoder == NULL) | ||
670 | return -1; | ||
671 | |||
672 | if (cs->encoder_sample_rate == rate) | ||
673 | return 0; | ||
674 | |||
675 | int rc = OPUS_OK; | ||
676 | int bitrate = 0; | ||
677 | int channels = cs->encoder_channels; | ||
678 | |||
679 | rc = opus_encoder_ctl(cs->audio_encoder, OPUS_GET_BITRATE(&bitrate)); | ||
680 | |||
681 | if ( rc != OPUS_OK ) { | ||
682 | LOGGER_ERROR("Error while getting encoder ctl: %s", opus_strerror(rc)); | ||
683 | return -1; | ||
684 | } | ||
685 | |||
686 | cs_disable_audio_sending(cs); | ||
687 | cs->encoder_sample_rate = rate; | ||
688 | |||
689 | LOGGER_DEBUG("Set new encoder sampling rate: %d", rate); | ||
690 | return cs_enable_audio_sending(cs, bitrate, channels); | ||
691 | } | ||
692 | 625 | ||
693 | int cs_set_sending_audio_channels(CSSession* cs, int32_t count) | ||
694 | { | ||
695 | /* TODO Find a better way? */ | ||
696 | if (cs->audio_encoder == NULL) | ||
697 | return -1; | ||
698 | |||
699 | if (cs->encoder_channels == count) | ||
700 | return 0; | ||
701 | |||
702 | int rc = OPUS_OK; | ||
703 | int bitrate = 0; | ||
704 | |||
705 | rc = opus_encoder_ctl(cs->audio_encoder, OPUS_GET_BITRATE(&bitrate)); | ||
706 | |||
707 | if ( rc != OPUS_OK ) { | ||
708 | LOGGER_ERROR("Error while getting encoder ctl: %s", opus_strerror(rc)); | ||
709 | return -1; | ||
710 | } | ||
711 | |||
712 | cs_disable_audio_sending(cs); | ||
713 | |||
714 | LOGGER_DEBUG("Set new encoder channel count: %d", count); | ||
715 | return cs_enable_audio_sending(cs, bitrate, count); | ||
716 | } | ||
717 | 626 | ||
718 | void cs_disable_audio_sending(CSSession* cs) | 627 | void cs_disable_audio_sending(CSSession* cs) |
719 | { | 628 | { |
720 | if ( cs->audio_encoder ) { | 629 | if ( cs->audio_encoder ) { |
721 | opus_encoder_destroy(cs->audio_encoder); | 630 | opus_encoder_destroy(cs->audio_encoder); |
722 | cs->audio_encoder = NULL; | 631 | cs->audio_encoder = NULL; |
723 | cs->encoder_channels = 0; | ||
724 | } | 632 | } |
725 | } | 633 | } |
726 | 634 | ||
@@ -732,26 +640,22 @@ void cs_disable_audio_receiving(CSSession* cs) | |||
732 | jbuf_free(cs->j_buf); | 640 | jbuf_free(cs->j_buf); |
733 | cs->j_buf = NULL; | 641 | cs->j_buf = NULL; |
734 | 642 | ||
735 | /* It's used for measuring iteration interval so this has to be some value. | 643 | /* These need to be set in order to properly |
736 | * To avoid unecessary checking we set this to 500 | 644 | * do error correction with opus */ |
737 | */ | 645 | cs->last_packet_frame_duration = 120; |
738 | cs->last_packet_frame_duration = 500; | 646 | cs->last_packet_sampling_rate = 48000; |
739 | cs->decoder_sample_rate = 48000; | ||
740 | cs->decoder_channels = 2; | ||
741 | } | 647 | } |
742 | } | 648 | } |
743 | 649 | ||
744 | int cs_enable_audio_sending(CSSession* cs, uint32_t bitrate, int channels) | 650 | |
651 | |||
652 | int cs_enable_audio_sending(CSSession* cs, uint32_t bitrate) | ||
745 | { | 653 | { |
746 | if (cs->audio_encoder) | 654 | if (cs->audio_encoder) |
747 | return 0; | 655 | return 0; |
748 | 656 | ||
749 | if (!cs->encoder_sample_rate) | ||
750 | cs->encoder_sample_rate = 48000; | ||
751 | cs->encoder_channels = channels; | ||
752 | |||
753 | int rc = OPUS_OK; | 657 | int rc = OPUS_OK; |
754 | cs->audio_encoder = opus_encoder_create(cs->encoder_sample_rate, channels, OPUS_APPLICATION_AUDIO, &rc); | 658 | cs->audio_encoder = opus_encoder_create(48000, 2, OPUS_APPLICATION_AUDIO, &rc); |
755 | 659 | ||
756 | if ( rc != OPUS_OK ) { | 660 | if ( rc != OPUS_OK ) { |
757 | LOGGER_ERROR("Error while starting audio encoder: %s", opus_strerror(rc)); | 661 | LOGGER_ERROR("Error while starting audio encoder: %s", opus_strerror(rc)); |
@@ -785,7 +689,7 @@ int cs_enable_audio_receiving(CSSession* cs) | |||
785 | return 0; | 689 | return 0; |
786 | 690 | ||
787 | int rc; | 691 | int rc; |
788 | cs->audio_decoder = opus_decoder_create(cs->decoder_sample_rate, cs->decoder_channels, &rc ); | 692 | cs->audio_decoder = opus_decoder_create(48000, 2, &rc ); |
789 | 693 | ||
790 | if ( rc != OPUS_OK ) { | 694 | if ( rc != OPUS_OK ) { |
791 | LOGGER_ERROR("Error while starting audio decoder: %s", opus_strerror(rc)); | 695 | LOGGER_ERROR("Error while starting audio decoder: %s", opus_strerror(rc)); |
@@ -800,10 +704,11 @@ int cs_enable_audio_receiving(CSSession* cs) | |||
800 | return -1; | 704 | return -1; |
801 | } | 705 | } |
802 | 706 | ||
803 | /* It's used for measuring iteration interval so this has to be some value. | 707 | |
804 | * To avoid unecessary checking we set this to 500 | 708 | /* These need to be set in order to properly |
805 | */ | 709 | * do error correction with opus */ |
806 | cs->last_packet_frame_duration = 500; | 710 | cs->last_packet_frame_duration = 120; |
711 | cs->last_packet_sampling_rate = 48000; | ||
807 | 712 | ||
808 | return 0; | 713 | return 0; |
809 | } | 714 | } |
@@ -813,8 +718,8 @@ int cs_enable_audio_receiving(CSSession* cs) | |||
813 | /* Called from RTP */ | 718 | /* Called from RTP */ |
814 | void queue_message(RTPSession *session, RTPMessage *msg) | 719 | void queue_message(RTPSession *session, RTPMessage *msg) |
815 | { | 720 | { |
816 | /* This function is unregistered during call termination befor destroing | 721 | /* This function is unregistered during call termination befor destroying |
817 | * Codec session so no need to check for validity of cs | 722 | * Codec session so no need to check for validity of cs TODO properly check video cycle |
818 | */ | 723 | */ |
819 | CSSession *cs = session->cs; | 724 | CSSession *cs = session->cs; |
820 | 725 | ||