diff options
Diffstat (limited to 'toxav')
-rw-r--r-- | toxav/rtp.c | 132 | ||||
-rw-r--r-- | toxav/rtp.h | 10 | ||||
-rw-r--r-- | toxav/toxav.c | 349 | ||||
-rw-r--r-- | toxav/toxav.h | 43 |
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> |
31 | void 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 | */ | ||
479 | int 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 | */ | ||
511 | void 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 | */ | ||
537 | RTPMessage *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 | */ |
173 | void rtp_free_msg ( RTPSession *session, RTPMessage *msg ); | 168 | void 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 | */ | ||
181 | void 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 | */ | ||
192 | void 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 | */ | ||
487 | inline__ 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 | */ | ||
538 | inline__ 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 | */ | ||
718 | inline__ 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 | */ | ||
916 | inline__ 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 | */ | ||
934 | inline__ 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 | |||
944 | inline__ Tox *toxav_get_tox(ToxAv *av) | 743 | inline__ 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 | |||
755 | void 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 | |||
827 | end: | ||
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); | |||
165 | void toxav_register_callstate_callback (ToxAVCallback callback, ToxAvCallbackID id, void *userdata); | 165 | void 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 | */ | ||
173 | void 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 | */ | ||
181 | void 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 | |||
253 | int toxav_kill_transmission(ToxAv *av, int32_t call_index); | 269 | int 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 | */ | ||
264 | int 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 | */ | ||
278 | int 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 */ |