diff options
Diffstat (limited to 'toxav/toxav.c')
-rwxr-xr-x | toxav/toxav.c | 245 |
1 files changed, 130 insertions, 115 deletions
diff --git a/toxav/toxav.c b/toxav/toxav.c index 0301c6b2..3a41754a 100755 --- a/toxav/toxav.c +++ b/toxav/toxav.c | |||
@@ -25,17 +25,20 @@ | |||
25 | #include "config.h" | 25 | #include "config.h" |
26 | #endif /* HAVE_CONFIG_H */ | 26 | #endif /* HAVE_CONFIG_H */ |
27 | 27 | ||
28 | |||
29 | #define _GNU_SOURCE /* implicit declaration warning */ | ||
30 | |||
28 | #include "rtp.h" | 31 | #include "rtp.h" |
29 | #include "media.h" | 32 | #include "media.h" |
30 | #include "msi.h" | 33 | #include "msi.h" |
34 | #include "toxav.h" | ||
31 | 35 | ||
32 | #include "../toxcore/logger.h" | 36 | #include "../toxcore/logger.h" |
33 | 37 | ||
38 | |||
39 | #include <assert.h> | ||
34 | #include <stdlib.h> | 40 | #include <stdlib.h> |
35 | #include <string.h> | 41 | #include <string.h> |
36 | #include <assert.h> | ||
37 | |||
38 | #include "toxav.h" | ||
39 | 42 | ||
40 | /* Assume 60 fps*/ | 43 | /* Assume 60 fps*/ |
41 | #define MAX_ENCODE_TIME_US ((1000 / 60) * 1000) | 44 | #define MAX_ENCODE_TIME_US ((1000 / 60) * 1000) |
@@ -45,27 +48,23 @@ | |||
45 | 48 | ||
46 | static const uint8_t audio_index = 0, video_index = 1; | 49 | static const uint8_t audio_index = 0, video_index = 1; |
47 | 50 | ||
48 | typedef struct _CallRTPSessions { | 51 | typedef struct _CallSpecific { |
49 | RTPSession *crtps[2]; /* Audio is first and video is second */ | 52 | RTPSession *crtps[2]; /** Audio is first and video is second */ |
50 | } CallRTPSessions; | 53 | CodecState *cs;/** Each call have its own encoders and decoders. |
54 | * You can, but don't have to, reuse encoders for | ||
55 | * multiple calls. If you choose to reuse encoders, | ||
56 | * make sure to also reuse encoded payload for every call. | ||
57 | * Decoders have to be unique for each call. FIXME: Now add refcounted encoders and | ||
58 | * reuse them really. | ||
59 | */ | ||
60 | JitterBuffer *j_buf; /** Jitter buffer for audio */ | ||
61 | } CallSpecific; | ||
51 | 62 | ||
52 | typedef enum { | ||
53 | ts_closing, | ||
54 | ts_running, | ||
55 | ts_closed | ||
56 | |||
57 | } ThreadState; | ||
58 | 63 | ||
59 | struct _ToxAv { | 64 | struct _ToxAv { |
60 | Messenger *messenger; | 65 | Messenger *messenger; |
61 | |||
62 | MSISession *msi_session; /** Main msi session */ | 66 | MSISession *msi_session; /** Main msi session */ |
63 | 67 | CallSpecific* calls; /** Per-call params */ | |
64 | CallRTPSessions* rtp_sessions; | ||
65 | |||
66 | struct jitter_buffer *j_buf; | ||
67 | CodecState *cs; | ||
68 | |||
69 | uint32_t max_calls; | 68 | uint32_t max_calls; |
70 | }; | 69 | }; |
71 | 70 | ||
@@ -93,7 +92,7 @@ const ToxAvCodecSettings av_DefaultSettings = { | |||
93 | * @return ToxAv* | 92 | * @return ToxAv* |
94 | * @retval NULL On error. | 93 | * @retval NULL On error. |
95 | */ | 94 | */ |
96 | ToxAv *toxav_new( Tox* messenger, ToxAvCodecSettings* codec_settings, uint32_t max_calls) | 95 | ToxAv *toxav_new( Tox* messenger, uint32_t max_calls) |
97 | { | 96 | { |
98 | ToxAv *av = calloc ( sizeof(ToxAv), 1); | 97 | ToxAv *av = calloc ( sizeof(ToxAv), 1); |
99 | 98 | ||
@@ -105,19 +104,9 @@ ToxAv *toxav_new( Tox* messenger, ToxAvCodecSettings* codec_settings, uint32_t m | |||
105 | av->msi_session = msi_init_session(av->messenger, max_calls); | 104 | av->msi_session = msi_init_session(av->messenger, max_calls); |
106 | av->msi_session->agent_handler = av; | 105 | av->msi_session->agent_handler = av; |
107 | 106 | ||
108 | av->rtp_sessions = calloc(sizeof(CallRTPSessions), max_calls); | 107 | av->calls = calloc(sizeof(CallSpecific), max_calls); |
109 | av->max_calls = max_calls; | 108 | av->max_calls = max_calls; |
110 | 109 | ||
111 | av->j_buf = create_queue(codec_settings->jbuf_capacity); | ||
112 | |||
113 | av->cs = codec_init_session(codec_settings->audio_bitrate, | ||
114 | codec_settings->audio_frame_duration, | ||
115 | codec_settings->audio_sample_rate, | ||
116 | codec_settings->audio_channels, | ||
117 | codec_settings->video_width, | ||
118 | codec_settings->video_height, | ||
119 | codec_settings->video_bitrate); | ||
120 | |||
121 | return av; | 110 | return av; |
122 | } | 111 | } |
123 | 112 | ||
@@ -133,19 +122,29 @@ void toxav_kill ( ToxAv *av ) | |||
133 | 122 | ||
134 | int i = 0; | 123 | int i = 0; |
135 | for (; i < av->max_calls; i ++) { | 124 | for (; i < av->max_calls; i ++) { |
136 | if ( av->rtp_sessions[i].crtps[audio_index] ) { | 125 | if ( av->calls[i].crtps[audio_index] ) { |
137 | rtp_terminate_session(av->rtp_sessions[i].crtps[audio_index], av->msi_session->messenger_handle); | 126 | rtp_terminate_session(av->calls[i].crtps[audio_index], av->msi_session->messenger_handle); |
138 | } | 127 | } |
139 | 128 | ||
140 | if ( av->rtp_sessions[i].crtps[video_index] ) { | 129 | if ( av->calls[i].crtps[video_index] ) { |
141 | rtp_terminate_session(av->rtp_sessions[i].crtps[video_index], av->msi_session->messenger_handle); | 130 | rtp_terminate_session(av->calls[i].crtps[video_index], av->msi_session->messenger_handle); |
131 | } | ||
132 | |||
133 | av->calls[i].crtps[audio_index] = NULL; | ||
134 | av->calls[i].crtps[video_index] = NULL; | ||
135 | |||
136 | if ( av->calls[i].j_buf ) { | ||
137 | terminate_queue(av->calls[i].j_buf); | ||
138 | av->calls[i].j_buf = NULL; | ||
139 | } | ||
140 | |||
141 | if ( av->calls[i].cs ) { | ||
142 | codec_terminate_session(av->calls[i].cs); | ||
143 | av->calls[i].cs = NULL; | ||
142 | } | 144 | } |
143 | } | 145 | } |
144 | 146 | ||
145 | free(av->rtp_sessions); | 147 | free(av->calls); |
146 | |||
147 | codec_terminate_session(av->cs); | ||
148 | |||
149 | free(av); | 148 | free(av); |
150 | } | 149 | } |
151 | 150 | ||
@@ -286,14 +285,16 @@ int toxav_stop_call ( ToxAv* av, uint32_t call_index ) | |||
286 | * @retval 0 Success. | 285 | * @retval 0 Success. |
287 | * @retval ToxAvError On error. | 286 | * @retval ToxAvError On error. |
288 | */ | 287 | */ |
289 | int toxav_prepare_transmission ( ToxAv* av, uint32_t call_index, int support_video ) | 288 | int toxav_prepare_transmission ( ToxAv* av, uint32_t call_index, ToxAvCodecSettings* codec_settings, int support_video ) |
290 | { | 289 | { |
291 | if ( !av->msi_session || av->msi_session->max_calls <= call_index || !av->msi_session->calls[call_index] ) { | 290 | if ( !av->msi_session || av->msi_session->max_calls <= call_index || !av->msi_session->calls[call_index] ) { |
292 | /*fprintf(stderr, "Error while starting audio RTP session: invalid call!\n");*/ | 291 | /*fprintf(stderr, "Error while starting audio RTP session: invalid call!\n");*/ |
293 | return ErrorInternal; | 292 | return ErrorInternal; |
294 | } | 293 | } |
295 | 294 | ||
296 | av->rtp_sessions[call_index].crtps[audio_index] = | 295 | CallSpecific* call = &av->calls[call_index]; |
296 | |||
297 | call->crtps[audio_index] = | ||
297 | rtp_init_session( | 298 | rtp_init_session( |
298 | type_audio, | 299 | type_audio, |
299 | av->messenger, | 300 | av->messenger, |
@@ -301,18 +302,17 @@ int toxav_prepare_transmission ( ToxAv* av, uint32_t call_index, int support_vid | |||
301 | av->msi_session->calls[call_index]->key_peer, | 302 | av->msi_session->calls[call_index]->key_peer, |
302 | av->msi_session->calls[call_index]->key_local, | 303 | av->msi_session->calls[call_index]->key_local, |
303 | av->msi_session->calls[call_index]->nonce_peer, | 304 | av->msi_session->calls[call_index]->nonce_peer, |
304 | av->msi_session->calls[call_index]->nonce_local | 305 | av->msi_session->calls[call_index]->nonce_local); |
305 | ); | ||
306 | 306 | ||
307 | 307 | ||
308 | if ( !av->rtp_sessions[call_index].crtps[audio_index] ) { | 308 | if ( !call->crtps[audio_index] ) { |
309 | /*fprintf(stderr, "Error while starting audio RTP session!\n");*/ | 309 | /*fprintf(stderr, "Error while starting audio RTP session!\n");*/ |
310 | return ErrorStartingAudioRtp; | 310 | return ErrorStartingAudioRtp; |
311 | } | 311 | } |
312 | 312 | ||
313 | 313 | ||
314 | if ( support_video ) { | 314 | if ( support_video ) { |
315 | av->rtp_sessions[call_index].crtps[video_index] = | 315 | call->crtps[video_index] = |
316 | rtp_init_session ( | 316 | rtp_init_session ( |
317 | type_video, | 317 | type_video, |
318 | av->messenger, | 318 | av->messenger, |
@@ -320,18 +320,26 @@ int toxav_prepare_transmission ( ToxAv* av, uint32_t call_index, int support_vid | |||
320 | av->msi_session->calls[call_index]->key_peer, | 320 | av->msi_session->calls[call_index]->key_peer, |
321 | av->msi_session->calls[call_index]->key_local, | 321 | av->msi_session->calls[call_index]->key_local, |
322 | av->msi_session->calls[call_index]->nonce_peer, | 322 | av->msi_session->calls[call_index]->nonce_peer, |
323 | av->msi_session->calls[call_index]->nonce_local | 323 | av->msi_session->calls[call_index]->nonce_local); |
324 | ); | ||
325 | 324 | ||
326 | 325 | ||
327 | if ( !av->rtp_sessions[call_index].crtps[video_index] ) { | 326 | if ( !call->crtps[video_index] ) { |
328 | /*fprintf(stderr, "Error while starting video RTP session!\n");*/ | 327 | /*fprintf(stderr, "Error while starting video RTP session!\n");*/ |
329 | return ErrorStartingVideoRtp; | 328 | return ErrorStartingVideoRtp; |
330 | } | 329 | } |
331 | } | 330 | } |
332 | 331 | ||
332 | if ( !(call->j_buf = create_queue(codec_settings->jbuf_capacity)) ) return ErrorInternal; | ||
333 | 333 | ||
334 | return ErrorNone; | 334 | call->cs = codec_init_session(codec_settings->audio_bitrate, |
335 | codec_settings->audio_frame_duration, | ||
336 | codec_settings->audio_sample_rate, | ||
337 | codec_settings->audio_channels, | ||
338 | codec_settings->video_width, | ||
339 | codec_settings->video_height, | ||
340 | codec_settings->video_bitrate); | ||
341 | |||
342 | return call->cs ? ErrorNone : ErrorInternal; | ||
335 | } | 343 | } |
336 | 344 | ||
337 | /** | 345 | /** |
@@ -344,19 +352,30 @@ int toxav_prepare_transmission ( ToxAv* av, uint32_t call_index, int support_vid | |||
344 | */ | 352 | */ |
345 | int toxav_kill_transmission ( ToxAv *av, uint32_t call_index ) | 353 | int toxav_kill_transmission ( ToxAv *av, uint32_t call_index ) |
346 | { | 354 | { |
347 | if ( av->rtp_sessions[call_index].crtps[audio_index] && -1 == rtp_terminate_session(av->rtp_sessions[call_index].crtps[audio_index], av->messenger) ) { | 355 | CallSpecific* call = &av->calls[call_index]; |
356 | |||
357 | if ( call->crtps[audio_index] && -1 == rtp_terminate_session(call->crtps[audio_index], av->messenger) ) { | ||
348 | /*fprintf(stderr, "Error while terminating audio RTP session!\n");*/ | 358 | /*fprintf(stderr, "Error while terminating audio RTP session!\n");*/ |
349 | return ErrorTerminatingAudioRtp; | 359 | return ErrorTerminatingAudioRtp; |
350 | } | 360 | } |
351 | 361 | ||
352 | if ( av->rtp_sessions[call_index].crtps[video_index] && -1 == rtp_terminate_session(av->rtp_sessions[call_index].crtps[video_index], av->messenger) ) { | 362 | if ( call->crtps[video_index] && -1 == rtp_terminate_session(call->crtps[video_index], av->messenger) ) { |
353 | /*fprintf(stderr, "Error while terminating video RTP session!\n");*/ | 363 | /*fprintf(stderr, "Error while terminating video RTP session!\n");*/ |
354 | return ErrorTerminatingVideoRtp; | 364 | return ErrorTerminatingVideoRtp; |
355 | } | 365 | } |
356 | 366 | ||
357 | av->rtp_sessions[call_index].crtps[audio_index] = NULL; | 367 | call->crtps[audio_index] = NULL; |
358 | av->rtp_sessions[call_index].crtps[video_index] = NULL; | 368 | call->crtps[video_index] = NULL; |
359 | 369 | ||
370 | if ( call->j_buf ) { | ||
371 | terminate_queue(call->j_buf); | ||
372 | call->j_buf = NULL; | ||
373 | } | ||
374 | |||
375 | if ( call->cs ) { | ||
376 | codec_terminate_session(call->cs); | ||
377 | call->cs = NULL; | ||
378 | } | ||
360 | 379 | ||
361 | return ErrorNone; | 380 | return ErrorNone; |
362 | } | 381 | } |
@@ -375,8 +394,8 @@ int toxav_kill_transmission ( ToxAv *av, uint32_t call_index ) | |||
375 | */ | 394 | */ |
376 | inline__ int toxav_send_rtp_payload ( ToxAv *av, uint32_t call_index, ToxAvCallType type, const uint8_t *payload, uint16_t length ) | 395 | inline__ int toxav_send_rtp_payload ( ToxAv *av, uint32_t call_index, ToxAvCallType type, const uint8_t *payload, uint16_t length ) |
377 | { | 396 | { |
378 | if ( av->rtp_sessions[call_index].crtps[type - TypeAudio] ) | 397 | if ( av->calls[call_index].crtps[type - TypeAudio] ) |
379 | return rtp_send_msg ( av->rtp_sessions[call_index].crtps[type - TypeAudio], av->msi_session->messenger_handle, payload, length ); | 398 | return rtp_send_msg ( av->calls[call_index].crtps[type - TypeAudio], av->msi_session->messenger_handle, payload, length ); |
380 | else return -1; | 399 | else return -1; |
381 | } | 400 | } |
382 | 401 | ||
@@ -394,27 +413,29 @@ inline__ int toxav_recv_rtp_payload ( ToxAv *av, uint32_t call_index, ToxAvCallT | |||
394 | { | 413 | { |
395 | if ( !dest ) return ErrorInternal; | 414 | if ( !dest ) return ErrorInternal; |
396 | 415 | ||
397 | if ( !av->rtp_sessions[call_index].crtps[type - TypeAudio] ) return ErrorNoRtpSession; | 416 | CallSpecific* call = &av->calls[call_index]; |
417 | |||
418 | if ( !call->crtps[type - TypeAudio] ) return ErrorNoRtpSession; | ||
398 | 419 | ||
399 | RTPMessage *message; | 420 | RTPMessage *message; |
400 | 421 | ||
401 | if ( type == TypeAudio ) { | 422 | if ( type == TypeAudio ) { |
402 | 423 | ||
403 | do { | 424 | do { |
404 | message = rtp_recv_msg(av->rtp_sessions[call_index].crtps[audio_index]); | 425 | message = rtp_recv_msg(call->crtps[audio_index]); |
405 | 426 | ||
406 | if (message) { | 427 | if (message) { |
407 | /* push the packet into the queue */ | 428 | /* push the packet into the queue */ |
408 | queue(av->j_buf, message); | 429 | queue(call->j_buf, message); |
409 | } | 430 | } |
410 | } while (message); | 431 | } while (message); |
411 | 432 | ||
412 | int success = 0; | 433 | int success = 0; |
413 | message = dequeue(av->j_buf, &success); | 434 | message = dequeue(call->j_buf, &success); |
414 | 435 | ||
415 | if ( success == 2) return ErrorAudioPacketLost; | 436 | if ( success == 2) return ErrorAudioPacketLost; |
416 | } else { | 437 | } else { |
417 | message = rtp_recv_msg(av->rtp_sessions[call_index].crtps[video_index]); | 438 | message = rtp_recv_msg(call->crtps[video_index]); |
418 | } | 439 | } |
419 | 440 | ||
420 | if ( message ) { | 441 | if ( message ) { |
@@ -446,11 +467,12 @@ inline__ int toxav_recv_video ( ToxAv *av, uint32_t call_index, vpx_image_t **ou | |||
446 | uint8_t packet [RTP_PAYLOAD_SIZE]; | 467 | uint8_t packet [RTP_PAYLOAD_SIZE]; |
447 | int recved_size = 0; | 468 | int recved_size = 0; |
448 | int rc; | 469 | int rc; |
470 | CallSpecific* call = &av->calls[call_index]; | ||
449 | 471 | ||
450 | do { | 472 | do { |
451 | recved_size = toxav_recv_rtp_payload(av, call_index, TypeVideo, packet); | 473 | recved_size = toxav_recv_rtp_payload(av, call_index, TypeVideo, packet); |
452 | 474 | ||
453 | if (recved_size > 0 && ( rc = vpx_codec_decode(&av->cs->v_decoder, packet, recved_size, NULL, 0) ) != VPX_CODEC_OK) { | 475 | if (recved_size > 0 && ( rc = vpx_codec_decode(&call->cs->v_decoder, packet, recved_size, NULL, 0) ) != VPX_CODEC_OK) { |
454 | /*fprintf(stderr, "Error decoding video: %s\n", vpx_codec_err_to_string(rc));*/ | 476 | /*fprintf(stderr, "Error decoding video: %s\n", vpx_codec_err_to_string(rc));*/ |
455 | return ErrorInternal; | 477 | return ErrorInternal; |
456 | } | 478 | } |
@@ -459,12 +481,10 @@ inline__ int toxav_recv_video ( ToxAv *av, uint32_t call_index, vpx_image_t **ou | |||
459 | 481 | ||
460 | vpx_codec_iter_t iter = NULL; | 482 | vpx_codec_iter_t iter = NULL; |
461 | vpx_image_t *img; | 483 | vpx_image_t *img; |
462 | img = vpx_codec_get_frame(&av->cs->v_decoder, &iter); | 484 | img = vpx_codec_get_frame(&call->cs->v_decoder, &iter); |
463 | 485 | ||
464 | *output = img; | 486 | *output = img; |
465 | return 0; | 487 | return 0; |
466 | /* Yeah, i set output to be NULL if nothing received | ||
467 | */ | ||
468 | } | 488 | } |
469 | 489 | ||
470 | /** | 490 | /** |
@@ -476,60 +496,47 @@ inline__ int toxav_recv_video ( ToxAv *av, uint32_t call_index, vpx_image_t **ou | |||
476 | * @retval 0 Success. | 496 | * @retval 0 Success. |
477 | * @retval ToxAvError On error. | 497 | * @retval ToxAvError On error. |
478 | */ | 498 | */ |
479 | inline__ int toxav_send_video ( ToxAv *av, uint32_t call_index, vpx_image_t *input) | 499 | inline__ int toxav_send_video ( ToxAv *av, uint32_t call_index, const uint8_t* frame, int frame_size) |
480 | { | 500 | { |
481 | int rc = vpx_codec_encode(&av->cs->v_encoder, input, av->cs->frame_counter, 1, 0, MAX_ENCODE_TIME_US); | 501 | return toxav_send_rtp_payload(av, call_index, TypeVideo, frame, frame_size); |
482 | if ( rc != VPX_CODEC_OK) { | ||
483 | /*fprintf(stderr, "Could not encode video frame: %s\n", vpx_codec_err_to_string(rc));*/ | ||
484 | return ErrorInternal; | ||
485 | } | ||
486 | |||
487 | ++av->cs->frame_counter; | ||
488 | |||
489 | vpx_codec_iter_t iter = NULL; | ||
490 | const vpx_codec_cx_pkt_t *pkt; | ||
491 | int sent = 0; | ||
492 | |||
493 | while ( (pkt = vpx_codec_get_cx_data(&av->cs->v_encoder, &iter)) ) { | ||
494 | if (pkt->kind == VPX_CODEC_CX_FRAME_PKT) { | ||
495 | if (toxav_send_rtp_payload(av, call_index, TypeVideo, pkt->data.frame.buf, pkt->data.frame.sz) != -1) | ||
496 | ++sent; | ||
497 | } | ||
498 | } | ||
499 | |||
500 | if (sent > 0) | ||
501 | return ErrorNone; | ||
502 | |||
503 | return ErrorInternal; | ||
504 | } | 502 | } |
505 | 503 | ||
506 | int toxav_prepare_video_frame(ToxAv* av, uint8_t* dest, int dest_max, vpx_image_t* input) | 504 | /** |
505 | * @brief Encode video frame | ||
506 | * | ||
507 | * @param av Handler | ||
508 | * @param dest Where to | ||
509 | * @param dest_max Max size | ||
510 | * @param input What to encode | ||
511 | * @return int | ||
512 | * @retval ToxAvError On error. | ||
513 | * @retval >0 On success | ||
514 | */ | ||
515 | inline__ int toxav_prepare_video_frame(ToxAv* av, uint32_t call_index, uint8_t* dest, int dest_max, vpx_image_t* input) | ||
507 | { | 516 | { |
508 | int rc = vpx_codec_encode(&av->cs->v_encoder, input, av->cs->frame_counter, 1, 0, MAX_ENCODE_TIME_US); | 517 | CallSpecific* call = &av->calls[call_index]; |
518 | |||
519 | int rc = vpx_codec_encode(&call->cs->v_encoder, input, call->cs->frame_counter, 1, 0, MAX_ENCODE_TIME_US); | ||
509 | if ( rc != VPX_CODEC_OK) { | 520 | if ( rc != VPX_CODEC_OK) { |
510 | /*fprintf(stderr, "Could not encode video frame: %s\n", vpx_codec_err_to_string(rc));*/ | 521 | fprintf(stderr, "Could not encode video frame: %s\n", vpx_codec_err_to_string(rc)); |
511 | return ErrorInternal; | 522 | return ErrorInternal; |
512 | } | 523 | } |
513 | ++av->cs->frame_counter; | 524 | ++call->cs->frame_counter; |
514 | 525 | ||
515 | vpx_codec_iter_t iter = NULL; | 526 | vpx_codec_iter_t iter = NULL; |
516 | const vpx_codec_cx_pkt_t *pkt; | 527 | const vpx_codec_cx_pkt_t *pkt; |
517 | int counted = 0, copied = 0; | 528 | int copied = 0; |
518 | 529 | ||
519 | while ( (pkt = vpx_codec_get_cx_data(&av->cs->v_encoder, &iter)) ) { | 530 | while ( (pkt = vpx_codec_get_cx_data(&call->cs->v_encoder, &iter)) ) { |
520 | if (pkt->kind == VPX_CODEC_CX_FRAME_PKT) { | 531 | if (pkt->kind == VPX_CODEC_CX_FRAME_PKT) { |
521 | |||
522 | if ( copied + pkt->data.frame.sz > dest_max ) return ErrorPacketTooLarge; | 532 | if ( copied + pkt->data.frame.sz > dest_max ) return ErrorPacketTooLarge; |
523 | 533 | ||
524 | mempcpy(dest + copied, pkt->data.frame.buf, pkt->data.frame.sz); | 534 | mempcpy(dest + copied, pkt->data.frame.buf, pkt->data.frame.sz); |
525 | 535 | copied += pkt->data.frame.sz; | |
526 | if (toxav_send_rtp_payload(av, call_index, TypeVideo, pkt->data.frame.buf, pkt->data.frame.sz) != -1) | ||
527 | ++counted; | ||
528 | } | 536 | } |
529 | } | 537 | } |
530 | 538 | ||
531 | if (counted > 0) | 539 | return copied; |
532 | return ErrorNone; | ||
533 | } | 540 | } |
534 | 541 | ||
535 | /** | 542 | /** |
@@ -547,21 +554,28 @@ int toxav_prepare_video_frame(ToxAv* av, uint8_t* dest, int dest_max, vpx_image_ | |||
547 | inline__ int toxav_recv_audio ( ToxAv *av, uint32_t call_index, int frame_size, int16_t *dest ) | 554 | inline__ int toxav_recv_audio ( ToxAv *av, uint32_t call_index, int frame_size, int16_t *dest ) |
548 | { | 555 | { |
549 | if ( !dest ) return ErrorInternal; | 556 | if ( !dest ) return ErrorInternal; |
557 | |||
558 | CallSpecific* call = &av->calls[call_index]; | ||
550 | 559 | ||
551 | uint8_t packet [RTP_PAYLOAD_SIZE]; | 560 | uint8_t packet [RTP_PAYLOAD_SIZE]; |
552 | 561 | ||
553 | int recved_size = toxav_recv_rtp_payload(av, call_index, TypeAudio, packet); | 562 | int recved_size = toxav_recv_rtp_payload(av, call_index, TypeAudio, packet); |
554 | 563 | ||
555 | if ( recved_size == ErrorAudioPacketLost ) { | 564 | if ( recved_size == ErrorAudioPacketLost ) { |
556 | int dec_size = opus_decode(av->cs->audio_decoder, NULL, 0, dest, frame_size, 1); | 565 | int dec_size = opus_decode(call->cs->audio_decoder, NULL, 0, dest, frame_size, 1); |
557 | 566 | ||
558 | if ( dec_size != OPUS_OK ) return ErrorInternal; | 567 | if ( dec_size != OPUS_OK ) |
568 | return ErrorInternal; | ||
569 | else | ||
570 | return dec_size; | ||
559 | 571 | ||
560 | } else if ( recved_size ) { | 572 | } else if ( recved_size ) { |
561 | int dec_size = opus_decode(av->cs->audio_decoder, packet, recved_size, dest, frame_size, 0); | 573 | int dec_size = opus_decode(call->cs->audio_decoder, packet, recved_size, dest, frame_size, 0); |
562 | |||
563 | if ( dec_size != OPUS_OK ) return ErrorInternal; | ||
564 | 574 | ||
575 | if ( dec_size != OPUS_OK ) | ||
576 | return ErrorInternal; | ||
577 | else | ||
578 | return dec_size; | ||
565 | } else { | 579 | } else { |
566 | return 0; /* Nothing received */ | 580 | return 0; /* Nothing received */ |
567 | } | 581 | } |
@@ -578,7 +592,7 @@ inline__ int toxav_recv_audio ( ToxAv *av, uint32_t call_index, int frame_size, | |||
578 | * @retval 0 Success. | 592 | * @retval 0 Success. |
579 | * @retval ToxAvError On error. | 593 | * @retval ToxAvError On error. |
580 | */ | 594 | */ |
581 | inline__ int toxav_send_audio ( ToxAv *av, uint32_t call_index, const int16_t *frame, int frame_size) | 595 | inline__ int toxav_send_audio ( ToxAv *av, uint32_t call_index, const uint8_t *frame, int frame_size) |
582 | { | 596 | { |
583 | return toxav_send_rtp_payload(av, call_index, TypeAudio, frame, frame_size); | 597 | return toxav_send_rtp_payload(av, call_index, TypeAudio, frame, frame_size); |
584 | } | 598 | } |
@@ -595,13 +609,14 @@ inline__ int toxav_send_audio ( ToxAv *av, uint32_t call_index, const int16_t *f | |||
595 | * @retval ToxAvError On error. | 609 | * @retval ToxAvError On error. |
596 | * @retval >0 On success | 610 | * @retval >0 On success |
597 | */ | 611 | */ |
598 | int toxav_prepare_audio_frame ( ToxAv* av, int16_t* dest, int dest_max, const int16_t* frame, int frame_size) | 612 | inline__ int toxav_prepare_audio_frame ( ToxAv* av, uint32_t call_index, uint8_t* dest, int dest_max, const int16_t* frame, int frame_size) |
599 | { | 613 | { |
600 | int32_t rc = opus_encode(av->cs->audio_encoder, frame, frame_size, dest, dest_max); | 614 | int32_t rc = opus_encode(av->calls[call_index].cs->audio_encoder, frame, frame_size, dest, dest_max); |
601 | 615 | ||
602 | if (rc <= 0) | 616 | if (rc < 0) { |
617 | fprintf(stderr, "Failed to encode payload: %s\n", opus_strerror(rc)); | ||
603 | return ErrorInternal; | 618 | return ErrorInternal; |
604 | 619 | } | |
605 | return rc; | 620 | return rc; |
606 | } | 621 | } |
607 | 622 | ||
@@ -650,9 +665,9 @@ int toxav_get_peer_id ( ToxAv* av, uint32_t call_index, int peer ) | |||
650 | * @retval 1 Yes. | 665 | * @retval 1 Yes. |
651 | * @retval 0 No. | 666 | * @retval 0 No. |
652 | */ | 667 | */ |
653 | inline__ int toxav_capability_supported ( ToxAv* av, ToxAvCapabilities capability ) | 668 | inline__ int toxav_capability_supported ( ToxAv* av, uint32_t call_index, ToxAvCapabilities capability ) |
654 | { | 669 | { |
655 | return av->cs->capabilities & (Capabilities) capability; | 670 | return av->calls[call_index].cs->capabilities & (Capabilities) capability; |
656 | } | 671 | } |
657 | 672 | ||
658 | /** | 673 | /** |
@@ -665,7 +680,7 @@ inline__ int toxav_capability_supported ( ToxAv* av, ToxAvCapabilities capabilit | |||
665 | */ | 680 | */ |
666 | void toxav_set_audio_queue_limit(ToxAv* av, uint32_t call_index, uint64_t limit) | 681 | void toxav_set_audio_queue_limit(ToxAv* av, uint32_t call_index, uint64_t limit) |
667 | { | 682 | { |
668 | rtp_queue_adjust_limit(av->rtp_sessions[call_index].crtps[audio_index], limit); | 683 | rtp_queue_adjust_limit(av->calls[call_index].crtps[audio_index], limit); |
669 | } | 684 | } |
670 | 685 | ||
671 | /** | 686 | /** |
@@ -678,5 +693,5 @@ void toxav_set_audio_queue_limit(ToxAv* av, uint32_t call_index, uint64_t limit) | |||
678 | */ | 693 | */ |
679 | void toxav_set_video_queue_limit(ToxAv* av, uint32_t call_index, uint64_t limit) | 694 | void toxav_set_video_queue_limit(ToxAv* av, uint32_t call_index, uint64_t limit) |
680 | { | 695 | { |
681 | rtp_queue_adjust_limit(av->rtp_sessions[call_index].crtps[video_index], limit); | 696 | rtp_queue_adjust_limit(av->calls[call_index].crtps[video_index], limit); |
682 | } | 697 | } |