summaryrefslogtreecommitdiff
path: root/toxav
diff options
context:
space:
mode:
Diffstat (limited to 'toxav')
-rw-r--r--toxav/rtp.c132
-rw-r--r--toxav/rtp.h10
-rw-r--r--toxav/toxav.c349
-rw-r--r--toxav/toxav.h43
4 files changed, 138 insertions, 396 deletions
diff --git a/toxav/rtp.c b/toxav/rtp.c
index 653a22df..a6bcaf18 100644
--- a/toxav/rtp.c
+++ b/toxav/rtp.c
@@ -28,6 +28,7 @@
28 28
29#include "rtp.h" 29#include "rtp.h"
30#include <stdlib.h> 30#include <stdlib.h>
31void toxav_handle_packet(RTPSession *_session, RTPMessage *_msg);
31 32
32#define size_32 4 33#define size_32 4
33 34
@@ -372,11 +373,6 @@ int rtp_handle_packet ( void *object, const uint8_t *data, uint32_t length )
372 return -1; 373 return -1;
373 } 374 }
374 375
375 if ( _session->queue_limit <= _session->queue_size ) {
376 LOGGER_WARNING("Queue limit reached!");
377 return -1;
378 }
379
380 _msg = msg_parse ( data + 1, length - 1 ); 376 _msg = msg_parse ( data + 1, length - 1 );
381 377
382 if ( !_msg ) { 378 if ( !_msg ) {
@@ -390,18 +386,7 @@ int rtp_handle_packet ( void *object, const uint8_t *data, uint32_t length )
390 _session->timestamp = _msg->header->timestamp; 386 _session->timestamp = _msg->header->timestamp;
391 } 387 }
392 388
393 pthread_mutex_lock(&_session->mutex); 389 toxav_handle_packet(_session, _msg);
394
395 if ( _session->last_msg ) {
396 _session->last_msg->next = _msg;
397 _session->last_msg = _msg;
398 } else {
399 _session->last_msg = _session->oldest_msg = _msg;
400 }
401
402 _session->queue_size++;
403
404 pthread_mutex_unlock(&_session->mutex);
405 390
406 return 0; 391 return 0;
407} 392}
@@ -467,105 +452,6 @@ RTPMessage *rtp_new_message ( RTPSession *session, const uint8_t *data, uint32_t
467} 452}
468 453
469 454
470
471/**
472 * @brief Release all messages held by session.
473 *
474 * @param session The session.
475 * @return int
476 * @retval -1 Error occurred.
477 * @retval 0 Success.
478 */
479int rtp_release_session_recv ( RTPSession *session )
480{
481 if ( !session ) {
482 LOGGER_WARNING("No session!");
483 return -1;
484 }
485
486 RTPMessage *_tmp, * _it;
487
488 pthread_mutex_lock(&session->mutex);
489
490 for ( _it = session->oldest_msg; _it; _it = _tmp ) {
491 _tmp = _it->next;
492 rtp_free_msg( session, _it);
493 }
494
495 session->last_msg = session->oldest_msg = NULL;
496 session->queue_size = 0;
497
498 pthread_mutex_unlock(&session->mutex);
499
500 return 0;
501}
502
503
504/**
505 * @brief Call this to change queue limit
506 *
507 * @param session The session
508 * @param limit new limit
509 * @return void
510 */
511void rtp_queue_adjust_limit(RTPSession *session, uint64_t limit)
512{
513 pthread_mutex_lock(&session->mutex);
514
515 RTPMessage *_tmp, * _it = session->oldest_msg;
516
517 for ( ; session->queue_size > limit; _it = _tmp ) {
518 _tmp = _it->next;
519 rtp_free_msg( session, _it);
520 session->queue_size --;
521 }
522
523 session->oldest_msg = _it;
524 session->queue_limit = limit;
525
526 pthread_mutex_unlock(&session->mutex);
527}
528
529
530/**
531 * @brief Gets oldest message in the list.
532 *
533 * @param session Where the list is.
534 * @return RTPMessage* The message. You _must_ call rtp_msg_free() to free it.
535 * @retval NULL No messages in the list, or no list.
536 */
537RTPMessage *rtp_recv_msg ( RTPSession *session )
538{
539 if ( !session ) {
540 LOGGER_WARNING("No session!");
541 return NULL;
542 }
543
544 pthread_mutex_lock(&session->mutex);
545
546 if ( session->queue_size == 0 ) {
547 pthread_mutex_unlock(&session->mutex);
548 return NULL;
549 }
550
551
552 RTPMessage *_retu = session->oldest_msg;
553
554 /*if (_retu)*/
555 session->oldest_msg = _retu->next;
556
557 if ( !session->oldest_msg )
558 session->last_msg = NULL;
559
560 session->queue_size --;
561
562 pthread_mutex_unlock(&session->mutex);
563
564
565 return _retu;
566}
567
568
569/** 455/**
570 * @brief Sends data to _RTPSession::dest 456 * @brief Sends data to _RTPSession::dest
571 * 457 *
@@ -627,7 +513,6 @@ void rtp_free_msg ( RTPSession *session, RTPMessage *msg )
627 free ( msg ); 513 free ( msg );
628} 514}
629 515
630
631/** 516/**
632 * @brief Must be called before calling any other rtp function. It's used 517 * @brief Must be called before calling any other rtp function. It's used
633 * to initialize RTP control session. 518 * to initialize RTP control session.
@@ -682,11 +567,6 @@ RTPSession *rtp_init_session ( int payload_type, Messenger *messenger, int frien
682 /* Also set payload type as prefix */ 567 /* Also set payload type as prefix */
683 _retu->prefix = payload_type; 568 _retu->prefix = payload_type;
684 569
685 _retu->oldest_msg = _retu->last_msg = NULL;
686 _retu->queue_limit = 100; /* Default */
687 _retu->queue_size = 0;
688
689 pthread_mutex_init(&_retu->mutex, NULL);
690 /* 570 /*
691 * 571 *
692 */ 572 */
@@ -709,17 +589,9 @@ void rtp_terminate_session ( RTPSession *session, Messenger *messenger )
709 589
710 custom_lossy_packet_registerhandler(messenger, session->dest, session->prefix, NULL, NULL); 590 custom_lossy_packet_registerhandler(messenger, session->dest, session->prefix, NULL, NULL);
711 591
712 rtp_release_session_recv(session);
713
714 pthread_mutex_lock(&session->mutex);
715
716 free ( session->ext_header ); 592 free ( session->ext_header );
717 free ( session->csrc ); 593 free ( session->csrc );
718 594
719 pthread_mutex_unlock(&session->mutex);
720
721 pthread_mutex_destroy(&session->mutex);
722
723 LOGGER_DEBUG("Terminated RTP session: %p", session); 595 LOGGER_DEBUG("Terminated RTP session: %p", session);
724 596
725 /* And finally free session */ 597 /* And finally free session */
diff --git a/toxav/rtp.h b/toxav/rtp.h
index 727839c6..45128285 100644
--- a/toxav/rtp.h
+++ b/toxav/rtp.h
@@ -105,17 +105,12 @@ typedef struct _RTPSession {
105 */ 105 */
106 RTPExtHeader *ext_header; 106 RTPExtHeader *ext_header;
107 107
108 RTPMessage *oldest_msg;
109 RTPMessage *last_msg; /* tail */
110
111 uint64_t queue_limit;/* Default 100; modify per thy liking */
112 uint64_t queue_size; /* currently holding << messages */
113
114 /* Msg prefix for core to know when recving */ 108 /* Msg prefix for core to know when recving */
115 uint8_t prefix; 109 uint8_t prefix;
116 110
117 pthread_mutex_t mutex;
118 int dest; 111 int dest;
112 int32_t call_index;
113 struct _ToxAv *av;
119 114
120} RTPSession; 115} RTPSession;
121 116
@@ -172,7 +167,6 @@ int rtp_send_msg ( RTPSession *session, Messenger *messenger, const uint8_t *dat
172 */ 167 */
173void rtp_free_msg ( RTPSession *session, RTPMessage *msg ); 168void rtp_free_msg ( RTPSession *session, RTPMessage *msg );
174 169
175
176/** 170/**
177 * @brief Must be called before calling any other rtp function. It's used 171 * @brief Must be called before calling any other rtp function. It's used
178 * to initialize RTP control session. 172 * to initialize RTP control session.
diff --git a/toxav/toxav.c b/toxav/toxav.c
index 151a1e64..a301e007 100644
--- a/toxav/toxav.c
+++ b/toxav/toxav.c
@@ -76,6 +76,10 @@ struct _ToxAv {
76 Messenger *messenger; 76 Messenger *messenger;
77 MSISession *msi_session; /** Main msi session */ 77 MSISession *msi_session; /** Main msi session */
78 CallSpecific *calls; /** Per-call params */ 78 CallSpecific *calls; /** Per-call params */
79
80 void (*audio_callback)(ToxAv *, int32_t, int16_t *, int);
81 void (*video_callback)(ToxAv *, int32_t, vpx_image_t *);
82
79 uint32_t max_calls; 83 uint32_t max_calls;
80}; 84};
81 85
@@ -169,6 +173,28 @@ void toxav_register_callstate_callback ( ToxAVCallback callback, ToxAvCallbackID
169} 173}
170 174
171/** 175/**
176 * @brief Register callback for recieving audio data
177 *
178 * @param callback The callback
179 * @return void
180 */
181void toxav_register_audio_recv_callback (ToxAv *av, void (*callback)(ToxAv *, int32_t, int16_t *, int))
182{
183 av->audio_callback = callback;
184}
185
186/**
187 * @brief Register callback for recieving video data
188 *
189 * @param callback The callback
190 * @return void
191 */
192void toxav_register_video_recv_callback (ToxAv *av, void (*callback)(ToxAv *, int32_t, vpx_image_t *))
193{
194 av->video_callback = callback;
195}
196
197/**
172 * @brief Call user. Use its friend_id. 198 * @brief Call user. Use its friend_id.
173 * 199 *
174 * @param av Handler. 200 * @param av Handler.
@@ -316,17 +342,21 @@ int toxav_prepare_transmission ( ToxAv *av, int32_t call_index, ToxAvCodecSettin
316 return ErrorInternal; 342 return ErrorInternal;
317 } 343 }
318 344
345 call->crtps[audio_index]->call_index = call_index;
346 call->crtps[audio_index]->av = av;
319 347
320 if ( support_video ) { 348 if ( support_video ) {
321 call->crtps[video_index] = 349 call->crtps[video_index] =
322 rtp_init_session(type_video, av->messenger, av->msi_session->calls[call_index]->peers[0]); 350 rtp_init_session(type_video, av->messenger, av->msi_session->calls[call_index]->peers[0]);
323 351
324
325 if ( !call->crtps[video_index] ) { 352 if ( !call->crtps[video_index] ) {
326 LOGGER_ERROR("Error while starting video RTP session!\n"); 353 LOGGER_ERROR("Error while starting video RTP session!\n");
327 goto error; 354 goto error;
328 } 355 }
329 356
357 call->crtps[video_index]->call_index = call_index;
358 call->crtps[video_index]->av = av;
359
330 call->frame_limit = 0; 360 call->frame_limit = 0;
331 call->frame_id = 0; 361 call->frame_id = 0;
332 call->frame_outid = 0; 362 call->frame_outid = 0;
@@ -475,140 +505,6 @@ inline__ int toxav_send_rtp_payload ( ToxAv *av, int32_t call_index, ToxAvCallTy
475} 505}
476 506
477/** 507/**
478 * @brief Receive RTP payload.
479 *
480 * @param av Handler.
481 * @param type Type of the payload.
482 * @param dest Storage.
483 * @return int
484 * @retval ToxAvError On Error.
485 * @retval >=0 Size of received payload.
486 */
487inline__ int toxav_recv_rtp_payload ( ToxAv *av, int32_t call_index, ToxAvCallType type, uint8_t *dest )
488{
489 if ( !dest ) return ErrorInternal;
490
491 CallSpecific *call = &av->calls[call_index];
492
493 if ( !call->crtps[type - TypeAudio] ) return ErrorNoRtpSession;
494
495 RTPMessage *message;
496
497 if ( type == TypeAudio ) {
498
499 do {
500 message = rtp_recv_msg(call->crtps[audio_index]);
501
502 if (message) {
503 /* push the packet into the queue */
504 queue(call->j_buf, message);
505 }
506 } while (message);
507
508 int success = 0;
509 message = dequeue(call->j_buf, &success);
510
511 if ( success == 2) return ErrorAudioPacketLost;
512 } else {
513 message = rtp_recv_msg(call->crtps[video_index]);
514 }
515
516 if ( message ) {
517 memcpy(dest, message->data, message->length);
518
519 int length = message->length;
520
521 rtp_free_msg(NULL, message);
522
523 return length;
524 }
525
526 return 0;
527}
528
529/**
530 * @brief Receive decoded video packet.
531 *
532 * @param av Handler.
533 * @param output Storage.
534 * @return int
535 * @retval 0 Success.
536 * @retval ToxAvError On Error.
537 */
538inline__ int toxav_recv_video ( ToxAv *av, int32_t call_index, vpx_image_t **output)
539{
540 if ( !output ) return ErrorInternal;
541
542 if (cii(call_index, av->msi_session)) {
543 LOGGER_WARNING("Invalid call index: %d", call_index);
544 return ErrorNoCall;
545 }
546
547 CallSpecific *call = &av->calls[call_index];
548 pthread_mutex_lock(&call->mutex);
549
550 if (!call->call_active) {
551 pthread_mutex_unlock(&call->mutex);
552 LOGGER_WARNING("Action on inactive call: %d", call_index);
553 return ErrorNoCall;
554 }
555
556 uint8_t packet [RTP_PAYLOAD_SIZE];
557 int recved_size;
558
559 while ((recved_size = toxav_recv_rtp_payload(av, call_index, TypeVideo, packet)) > 0) {
560 if (recved_size < VIDEOFRAME_HEADER_SIZE) {
561 continue;
562 }
563
564 uint8_t i = packet[0] - call->frame_id;
565
566 if (i == 0) {
567 /* piece of current frame */
568 } else if (i > 0 && i < 128) {
569 /* recieved a piece of a frame ahead, flush current frame and start reading this new frame */
570 int rc = vpx_codec_decode(&call->cs->v_decoder, call->frame_buf, call->frame_limit, NULL, 0);
571 call->frame_id = packet[0];
572 memset(call->frame_buf, 0, call->frame_limit);
573 call->frame_limit = 0;
574
575 if (rc != VPX_CODEC_OK) {
576 LOGGER_ERROR("Error decoding video: %u %s\n", i, vpx_codec_err_to_string(rc));
577 }
578 } else {
579 /* old packet, dont read */
580 LOGGER_DEBUG("Old packet: %u\n", i);
581 continue;
582 }
583
584 if (packet[1] > (MAX_VIDEOFRAME_SIZE - VIDEOFRAME_PIECE_SIZE + 1) /
585 VIDEOFRAME_PIECE_SIZE) { //TODO, fix this check? not sure
586 /* packet out of buffer range */
587 continue;
588 }
589
590 LOGGER_DEBUG("Video Packet: %u %u\n", packet[0], packet[1]);
591 memcpy(call->frame_buf + packet[1] * VIDEOFRAME_PIECE_SIZE, packet + VIDEOFRAME_HEADER_SIZE,
592 recved_size - VIDEOFRAME_HEADER_SIZE);
593 uint32_t limit = packet[1] * VIDEOFRAME_PIECE_SIZE + recved_size - VIDEOFRAME_HEADER_SIZE;
594
595 if (limit > call->frame_limit) {
596 call->frame_limit = limit;
597 LOGGER_DEBUG("Limit: %u\n", call->frame_limit);
598 }
599 }
600
601 vpx_codec_iter_t iter = NULL;
602 vpx_image_t *img;
603 img = vpx_codec_get_frame(&call->cs->v_decoder, &iter);
604
605 *output = img;
606
607 pthread_mutex_unlock(&call->mutex);
608 return ErrorNone;
609}
610
611/**
612 * @brief Encode and send video packet. 508 * @brief Encode and send video packet.
613 * 509 *
614 * @param av Handler. 510 * @param av Handler.
@@ -704,67 +600,6 @@ inline__ int toxav_prepare_video_frame(ToxAv *av, int32_t call_index, uint8_t *d
704} 600}
705 601
706/** 602/**
707 * @brief Receive decoded audio frame.
708 *
709 * @param av Handler.
710 * @param frame_size The size of dest in frames/samples (one frame/sample is 16 bits or 2 bytes
711 * and corresponds to one sample of audio.)
712 * @param dest Destination of the raw audio (16 bit signed pcm with AUDIO_CHANNELS channels).
713 * Make sure it has enough space for frame_size frames/samples.
714 * @return int
715 * @retval >=0 Size of received data in frames/samples.
716 * @retval ToxAvError On error.
717 */
718inline__ int toxav_recv_audio ( ToxAv *av, int32_t call_index, int frame_size, int16_t *dest )
719{
720 if ( !dest ) return ErrorInternal;
721
722 if (cii(call_index, av->msi_session)) {
723 LOGGER_WARNING("Invalid call index: %d", call_index);
724 return ErrorNoCall;
725 }
726
727
728 CallSpecific *call = &av->calls[call_index];
729 pthread_mutex_lock(&call->mutex);
730
731
732 if (!call->call_active) {
733 pthread_mutex_unlock(&call->mutex);
734 LOGGER_WARNING("Action on inactive call: %d", call_index);
735 return ErrorNoCall;
736 }
737
738 uint8_t packet [RTP_PAYLOAD_SIZE];
739
740 int recved_size = toxav_recv_rtp_payload(av, call_index, TypeAudio, packet);
741
742 if ( recved_size == ErrorAudioPacketLost ) {
743 int dec_size = opus_decode(call->cs->audio_decoder, NULL, 0, dest, frame_size, 1);
744
745 pthread_mutex_unlock(&call->mutex);
746
747 if ( dec_size < 0 ) {
748 LOGGER_WARNING("Decoding error: %s", opus_strerror(dec_size));
749 return ErrorInternal;
750 } else return dec_size;
751
752 } else if ( recved_size ) {
753 int dec_size = opus_decode(call->cs->audio_decoder, packet, recved_size, dest, frame_size, 0);
754
755 pthread_mutex_unlock(&call->mutex);
756
757 if ( dec_size < 0 ) {
758 LOGGER_WARNING("Decoding error: %s", opus_strerror(dec_size));
759 return ErrorInternal;
760 } else return dec_size;
761 } else {
762 pthread_mutex_unlock(&call->mutex);
763 return 0; /* Nothing received */
764 }
765}
766
767/**
768 * @brief Send audio frame. 603 * @brief Send audio frame.
769 * 604 *
770 * @param av Handler. 605 * @param av Handler.
@@ -905,42 +740,6 @@ inline__ int toxav_capability_supported ( ToxAv *av, int32_t call_index, ToxAvCa
905 /* 0 is error here */ 740 /* 0 is error here */
906} 741}
907 742
908/**
909 * @brief Set queue limit
910 *
911 * @param av Handler
912 * @param call_index index
913 * @param limit the limit
914 * @return void
915 */
916inline__ int toxav_set_audio_queue_limit(ToxAv *av, int32_t call_index, uint64_t limit)
917{
918 if ( av->calls[call_index].crtps[audio_index] )
919 rtp_queue_adjust_limit(av->calls[call_index].crtps[audio_index], limit);
920 else
921 return ErrorNoRtpSession;
922
923 return ErrorNone;
924}
925
926/**
927 * @brief Set queue limit
928 *
929 * @param av Handler
930 * @param call_index index
931 * @param limit the limit
932 * @return void
933 */
934inline__ int toxav_set_video_queue_limit(ToxAv *av, int32_t call_index, uint64_t limit)
935{
936 if ( av->calls[call_index].crtps[video_index] )
937 rtp_queue_adjust_limit(av->calls[call_index].crtps[video_index], limit);
938 else
939 return ErrorNoRtpSession;
940
941 return ErrorNone;
942}
943
944inline__ Tox *toxav_get_tox(ToxAv *av) 743inline__ Tox *toxav_get_tox(ToxAv *av)
945{ 744{
946 return (Tox *)av->messenger; 745 return (Tox *)av->messenger;
@@ -952,3 +751,89 @@ int toxav_has_activity(ToxAv *av, int32_t call_index, int16_t *PCM, uint16_t fra
952 751
953 return energy_VAD(av->calls[call_index].cs, PCM, frame_size, ref_energy); 752 return energy_VAD(av->calls[call_index].cs, PCM, frame_size, ref_energy);
954} 753}
754
755void toxav_handle_packet(RTPSession *_session, RTPMessage *_msg)
756{
757 ToxAv *av = _session->av;
758 int32_t call_index = _session->call_index;
759 CallSpecific *call = &av->calls[call_index];
760
761 if (_session->payload_type == type_audio % 128) {
762 queue(call->j_buf, _msg);
763
764 int success = 0, dec_size;
765 int frame_size = 960;
766 int16_t dest[frame_size];
767
768 while ((_msg = dequeue(call->j_buf, &success)) || success == 2) {
769 if (success == 2) {
770 dec_size = opus_decode(call->cs->audio_decoder, NULL, 0, dest, frame_size, 1);
771 } else {
772 dec_size = opus_decode(call->cs->audio_decoder, _msg->data, _msg->length, dest, frame_size, 0);
773 rtp_free_msg(NULL, _msg);
774 }
775
776 if (dec_size < 0) {
777 LOGGER_WARNING("Decoding error: %s", opus_strerror(dec_size));
778 continue;
779 }
780
781 av->audio_callback(av, call_index, dest, frame_size);
782 }
783 } else {
784 uint8_t *packet = _msg->data;
785 int recved_size = _msg->length;
786
787 if (recved_size < VIDEOFRAME_HEADER_SIZE) {
788 goto end;
789 }
790
791 uint8_t i = packet[0] - call->frame_id;
792
793 if (i == 0) {
794 /* piece of current frame */
795 } else if (i > 0 && i < 128) {
796 /* recieved a piece of a frame ahead, flush current frame and start reading this new frame */
797 int rc = vpx_codec_decode(&call->cs->v_decoder, call->frame_buf, call->frame_limit, NULL, 0);
798 call->frame_id = packet[0];
799 memset(call->frame_buf, 0, call->frame_limit);
800 call->frame_limit = 0;
801
802 if (rc != VPX_CODEC_OK) {
803 LOGGER_ERROR("Error decoding video: %u %s\n", i, vpx_codec_err_to_string(rc));
804 }
805 } else {
806 /* old packet, dont read */
807 LOGGER_DEBUG("Old packet: %u\n", i);
808 goto end;
809 }
810
811 if (packet[1] > (MAX_VIDEOFRAME_SIZE - VIDEOFRAME_PIECE_SIZE + 1) /
812 VIDEOFRAME_PIECE_SIZE) { //TODO, fix this check? not sure
813 /* packet out of buffer range */
814 goto end;
815 }
816
817 LOGGER_DEBUG("Video Packet: %u %u\n", packet[0], packet[1]);
818 memcpy(call->frame_buf + packet[1] * VIDEOFRAME_PIECE_SIZE, packet + VIDEOFRAME_HEADER_SIZE,
819 recved_size - VIDEOFRAME_HEADER_SIZE);
820 uint32_t limit = packet[1] * VIDEOFRAME_PIECE_SIZE + recved_size - VIDEOFRAME_HEADER_SIZE;
821
822 if (limit > call->frame_limit) {
823 call->frame_limit = limit;
824 LOGGER_DEBUG("Limit: %u\n", call->frame_limit);
825 }
826
827end:
828 ;
829 vpx_codec_iter_t iter = NULL;
830 vpx_image_t *img;
831 img = vpx_codec_get_frame(&call->cs->v_decoder, &iter);
832
833 if (img) {
834 av->video_callback(av, call_index, img);
835 }
836
837 rtp_free_msg(NULL, _msg);
838 }
839}
diff --git a/toxav/toxav.h b/toxav/toxav.h
index b7659441..0ded42bd 100644
--- a/toxav/toxav.h
+++ b/toxav/toxav.h
@@ -165,6 +165,22 @@ void toxav_kill(ToxAv *av);
165void toxav_register_callstate_callback (ToxAVCallback callback, ToxAvCallbackID id, void *userdata); 165void toxav_register_callstate_callback (ToxAVCallback callback, ToxAvCallbackID id, void *userdata);
166 166
167/** 167/**
168 * @brief Register callback for recieving audio data
169 *
170 * @param callback The callback
171 * @return void
172 */
173void toxav_register_audio_recv_callback (ToxAv *av, void (*callback)(ToxAv *, int32_t, int16_t *, int));
174
175/**
176 * @brief Register callback for recieving video data
177 *
178 * @param callback The callback
179 * @return void
180 */
181void toxav_register_video_recv_callback (ToxAv *av, void (*callback)(ToxAv *, int32_t, vpx_image_t *));
182
183/**
168 * @brief Call user. Use its friend_id. 184 * @brief Call user. Use its friend_id.
169 * 185 *
170 * @param av Handler. 186 * @param av Handler.
@@ -253,31 +269,6 @@ int toxav_prepare_transmission(ToxAv *av, int32_t call_index, ToxAvCodecSettings
253int toxav_kill_transmission(ToxAv *av, int32_t call_index); 269int toxav_kill_transmission(ToxAv *av, int32_t call_index);
254 270
255/** 271/**
256 * @brief Receive decoded video packet.
257 *
258 * @param av Handler.
259 * @param output Storage.
260 * @return int
261 * @retval 0 Success.
262 * @retval ToxAvError On Error.
263 */
264int toxav_recv_video ( ToxAv *av, int32_t call_index, vpx_image_t **output);
265
266/**
267 * @brief Receive decoded audio frame.
268 *
269 * @param av Handler.
270 * @param frame_size The size of dest in frames/samples (one frame/sample is 16 bits or 2 bytes
271 * and corresponds to one sample of audio.)
272 * @param dest Destination of the raw audio (16 bit signed pcm with AUDIO_CHANNELS channels).
273 * Make sure it has enough space for frame_size frames/samples.
274 * @return int
275 * @retval >=0 Size of received data in frames/samples.
276 * @retval ToxAvError On error.
277 */
278int toxav_recv_audio( ToxAv *av, int32_t call_index, int frame_size, int16_t *dest );
279
280/**
281 * @brief Encode and send video packet. 272 * @brief Encode and send video packet.
282 * 273 *
283 * @param av Handler. 274 * @param av Handler.
@@ -399,4 +390,4 @@ int toxav_has_activity ( ToxAv *av, int32_t call_index, int16_t *PCM, uint16_t f
399} 390}
400#endif 391#endif
401 392
402#endif /* __TOXAV */ \ No newline at end of file 393#endif /* __TOXAV */