summaryrefslogtreecommitdiff
path: root/toxav
diff options
context:
space:
mode:
authormannol <eniz_vukovic@hotmail.com>2014-05-03 01:46:03 +0200
committermannol <eniz_vukovic@hotmail.com>2014-05-03 01:46:03 +0200
commit0fa03b924030c5791599451389ba84b81be84da8 (patch)
tree0d3b93baeb3c18b2f1afce5b9455c9b8bd21ec89 /toxav
parent42b25a4d3e2fe66f03cbd8c866d8af7bd4f6e5a7 (diff)
Bunch of random changes
Diffstat (limited to 'toxav')
-rw-r--r--toxav/Makefile.inc41
-rw-r--r--toxav/media.c95
-rw-r--r--toxav/media.h15
-rwxr-xr-xtoxav/msi.c34
-rwxr-xr-xtoxav/phone.c1460
-rwxr-xr-xtoxav/rtp.c116
-rwxr-xr-xtoxav/rtp.h20
-rwxr-xr-xtoxav/toxav.c127
-rwxr-xr-xtoxav/toxav.h41
9 files changed, 318 insertions, 1631 deletions
diff --git a/toxav/Makefile.inc b/toxav/Makefile.inc
index 0cad1840..060a760c 100644
--- a/toxav/Makefile.inc
+++ b/toxav/Makefile.inc
@@ -32,43 +32,4 @@ libtoxav_la_LIBADD = libtoxcore.la \
32 $(AV_LIBS) 32 $(AV_LIBS)
33 33
34 34
35endif 35endif \ No newline at end of file
36
37
38
39
40
41
42if BUILD_PHONE
43
44
45noinst_PROGRAMS += phone
46
47phone_SOURCES = ../toxav/phone.c
48
49phone_CFLAGS = -I../toxcore \
50 -I../toxav \
51 $(AVFORMAT_CFLAGS) \
52 $(AVCODEC_CFLAGS) \
53 $(AVUTIL_CFLAGS) \
54 $(AVDEVICE_CFLAGS) \
55 $(SWSCALE_CFLAGS) \
56 $(SDL_CFLAGS) \
57 $(OPENAL_CFLAGS)
58
59phone_LDADD = libtoxav.la \
60 libtoxcore.la \
61 $(AVFORMAT_LIBS) \
62 $(AVCODEC_LIBS) \
63 $(AVUTIL_LIBS) \
64 $(AVDEVICE_LIBS) \
65 $(SWSCALE_LIBS) \
66 $(SDL_LIBS) \
67 $(OPENAL_LIBS) \
68 $(OPUS_LIBS) \
69 $(VPX_LIBS)\
70 $(PTHREAD_LIBS)\
71 $(NACL_LIBS)
72
73
74endif
diff --git a/toxav/media.c b/toxav/media.c
index a9a4adb8..33d5d6b6 100644
--- a/toxav/media.c
+++ b/toxav/media.c
@@ -26,6 +26,8 @@
26#include "config.h" 26#include "config.h"
27#endif /* HAVE_CONFIG_H */ 27#endif /* HAVE_CONFIG_H */
28 28
29#include "../toxcore/logger.h"
30
29#include <stdio.h> 31#include <stdio.h>
30#include <stdlib.h> 32#include <stdlib.h>
31#include <math.h> 33#include <math.h>
@@ -34,17 +36,6 @@
34#include "rtp.h" 36#include "rtp.h"
35#include "media.h" 37#include "media.h"
36 38
37struct jitter_buffer {
38 RTPMessage **queue;
39 uint16_t capacity;
40 uint16_t size;
41 uint16_t front;
42 uint16_t rear;
43 uint8_t queue_ready;
44 uint16_t current_id;
45 uint32_t current_ts;
46 uint8_t id_set;
47};
48 39
49int empty_queue(struct jitter_buffer *q) 40int empty_queue(struct jitter_buffer *q)
50{ 41{
@@ -79,14 +70,7 @@ struct jitter_buffer *create_queue(int capacity)
79 return q; 70 return q;
80} 71}
81 72
82/* returns 1 if 'a' has a higher sequence number than 'b' */ 73#define sequnum_older(sn_a, sn_b, ts_a, ts_b) (sn_a > sn_b || ts_a > ts_b)
83uint8_t sequence_number_older(uint16_t sn_a, uint16_t sn_b, uint32_t ts_a, uint32_t ts_b)
84{
85 /* TODO: There is already this kind of function in toxrtp.c.
86 * Maybe merge?
87 */
88 return (sn_a > sn_b || ts_a > ts_b);
89}
90 74
91/* success is 0 when there is nothing to dequeue, 1 when there's a good packet, 2 when there's a lost packet */ 75/* success is 0 when there is nothing to dequeue, 1 when there's a good packet, 2 when there's a lost packet */
92RTPMessage *dequeue(struct jitter_buffer *q, int *success) 76RTPMessage *dequeue(struct jitter_buffer *q, int *success)
@@ -112,14 +96,13 @@ RTPMessage *dequeue(struct jitter_buffer *q, int *success)
112 q->current_id = next_id; 96 q->current_id = next_id;
113 q->current_ts = next_ts; 97 q->current_ts = next_ts;
114 } else { 98 } else {
115 if (sequence_number_older(next_id, q->current_id, next_ts, q->current_ts)) { 99 if (sequnum_older(next_id, q->current_id, next_ts, q->current_ts)) {
116 /*printf("nextid: %d current: %d\n", next_id, q->current_id);*/ 100 LOGGER_DEBUG("nextid: %d current: %d\n", next_id, q->current_id);
117 q->current_id = (q->current_id + 1) % MAX_SEQU_NUM; 101 q->current_id = (q->current_id + 1) % MAX_SEQU_NUM;
118 *success = 2; /* tell the decoder the packet is lost */ 102 *success = 2; /* tell the decoder the packet is lost */
119 return NULL; 103 return NULL;
120 } else { 104 } else {
121 /* packet too old */ 105 LOGGER_DEBUG("Packet too old");
122 /*printf("packet too old\n");*/
123 *success = 0; 106 *success = 0;
124 return NULL; 107 return NULL;
125 } 108 }
@@ -139,12 +122,11 @@ RTPMessage *dequeue(struct jitter_buffer *q, int *success)
139} 122}
140 123
141 124
142int queue(struct jitter_buffer *q, RTPMessage *pk) 125void queue(struct jitter_buffer* q, RTPMessage* pk)
143{ 126{
144 if (q->size == q->capacity) { /* Full, empty queue */ 127 if (q->size == q->capacity) { /* Full, empty queue */
128 LOGGER_DEBUG("Queue full, emptying...");
145 empty_queue(q); 129 empty_queue(q);
146 /*rtp_free_msg(NULL, pk);*/
147 return 0;
148 } 130 }
149 131
150 if (q->size > 8) 132 if (q->size > 8)
@@ -169,13 +151,13 @@ int queue(struct jitter_buffer *q, RTPMessage *pk)
169 if (b < 0) 151 if (b < 0)
170 b += q->capacity; 152 b += q->capacity;
171 153
172 if (sequence_number_older(q->queue[b]->header->sequnum, q->queue[a]->header->sequnum, 154 if (sequnum_older(q->queue[b]->header->sequnum, q->queue[a]->header->sequnum,
173 q->queue[b]->header->timestamp, q->queue[a]->header->timestamp)) { 155 q->queue[b]->header->timestamp, q->queue[a]->header->timestamp)) {
174 RTPMessage *temp; 156 RTPMessage *temp;
175 temp = q->queue[a]; 157 temp = q->queue[a];
176 q->queue[a] = q->queue[b]; 158 q->queue[a] = q->queue[b];
177 q->queue[b] = temp; 159 q->queue[b] = temp;
178 /*printf("had to swap\n");*/ 160 LOGGER_DEBUG("Had to swap");
179 } else { 161 } else {
180 break; 162 break;
181 } 163 }
@@ -185,19 +167,14 @@ int queue(struct jitter_buffer *q, RTPMessage *pk)
185 if (a < 0) 167 if (a < 0)
186 a += q->capacity; 168 a += q->capacity;
187 } 169 }
188
189 if (pk)
190 return 1;
191
192 return 0;
193} 170}
194 171
195 172
196int init_video_decoder(CodecState *cs) 173int init_video_decoder(CodecState *cs)
197{ 174{
198 if (vpx_codec_dec_init_ver(&cs->v_decoder, VIDEO_CODEC_DECODER_INTERFACE, NULL, 0, 175 int rc = vpx_codec_dec_init_ver(&cs->v_decoder, VIDEO_CODEC_DECODER_INTERFACE, NULL, 0, VPX_DECODER_ABI_VERSION);
199 VPX_DECODER_ABI_VERSION) != VPX_CODEC_OK) { 176 if ( rc != VPX_CODEC_OK) {
200 /*fprintf(stderr, "Init video_decoder failed!\n");*/ 177 LOGGER_ERROR("Init video_decoder failed: %s", vpx_codec_err_to_string(rc));
201 return -1; 178 return -1;
202 } 179 }
203 180
@@ -210,7 +187,7 @@ int init_audio_decoder(CodecState *cs, uint32_t audio_channels)
210 cs->audio_decoder = opus_decoder_create(cs->audio_sample_rate, audio_channels, &rc ); 187 cs->audio_decoder = opus_decoder_create(cs->audio_sample_rate, audio_channels, &rc );
211 188
212 if ( rc != OPUS_OK ) { 189 if ( rc != OPUS_OK ) {
213 /*fprintf(stderr, "Error while starting audio decoder!\n");*/ 190 LOGGER_ERROR("Error while starting audio decoder: %s", opus_strerror(rc));
214 return -1; 191 return -1;
215 } 192 }
216 193
@@ -221,10 +198,10 @@ int init_audio_decoder(CodecState *cs, uint32_t audio_channels)
221int init_video_encoder(CodecState *cs, uint16_t width, uint16_t height, uint32_t video_bitrate) 198int init_video_encoder(CodecState *cs, uint16_t width, uint16_t height, uint32_t video_bitrate)
222{ 199{
223 vpx_codec_enc_cfg_t cfg; 200 vpx_codec_enc_cfg_t cfg;
224 int res = vpx_codec_enc_config_default(VIDEO_CODEC_ENCODER_INTERFACE, &cfg, 0); 201 int rc = vpx_codec_enc_config_default(VIDEO_CODEC_ENCODER_INTERFACE, &cfg, 0);
225 202
226 if (res) { 203 if (rc) {
227 /*fprintf(stderr, "Failed to get config: %s\n", vpx_codec_err_to_string(res));*/ 204 LOGGER_ERROR("Failed to get config: %s", vpx_codec_err_to_string(rc));
228 return -1; 205 return -1;
229 } 206 }
230 207
@@ -232,9 +209,10 @@ int init_video_encoder(CodecState *cs, uint16_t width, uint16_t height, uint32_t
232 cfg.g_w = width; 209 cfg.g_w = width;
233 cfg.g_h = height; 210 cfg.g_h = height;
234 211
235 if (vpx_codec_enc_init_ver(&cs->v_encoder, VIDEO_CODEC_ENCODER_INTERFACE, &cfg, 0, 212 rc = vpx_codec_enc_init_ver(&cs->v_encoder, VIDEO_CODEC_ENCODER_INTERFACE, &cfg, 0, VPX_ENCODER_ABI_VERSION);
236 VPX_ENCODER_ABI_VERSION) != VPX_CODEC_OK) { 213
237 /*fprintf(stderr, "Failed to initialize encoder\n");*/ 214 if ( rc != VPX_CODEC_OK) {
215 LOGGER_ERROR("Failed to initialize encoder: %s", vpx_codec_err_to_string(rc));
238 return -1; 216 return -1;
239 } 217 }
240 218
@@ -243,13 +221,30 @@ int init_video_encoder(CodecState *cs, uint16_t width, uint16_t height, uint32_t
243 221
244int init_audio_encoder(CodecState *cs, uint32_t audio_channels) 222int init_audio_encoder(CodecState *cs, uint32_t audio_channels)
245{ 223{
246 int err = OPUS_OK; 224 int rc = OPUS_OK;
247 cs->audio_encoder = opus_encoder_create(cs->audio_sample_rate, audio_channels, OPUS_APPLICATION_AUDIO, &err); 225 cs->audio_encoder = opus_encoder_create(cs->audio_sample_rate, audio_channels, OPUS_APPLICATION_AUDIO, &rc);
248 err = opus_encoder_ctl(cs->audio_encoder, OPUS_SET_BITRATE(cs->audio_bitrate)); 226
249 err = opus_encoder_ctl(cs->audio_encoder, OPUS_SET_COMPLEXITY(10)); 227 if ( rc != OPUS_OK ) {
228 LOGGER_ERROR("Error while starting audio encoder: %s", opus_strerror(rc));
229 return -1;
230 }
231
232 rc = opus_encoder_ctl(cs->audio_encoder, OPUS_SET_BITRATE(cs->audio_bitrate));
233
234 if ( rc != OPUS_OK ) {
235 LOGGER_ERROR("Error while setting encoder ctl: %s", opus_strerror(rc));
236 return -1;
237 }
238
239 rc = opus_encoder_ctl(cs->audio_encoder, OPUS_SET_COMPLEXITY(10));
240
241 if ( rc != OPUS_OK ) {
242 LOGGER_ERROR("Error while setting encoder ctl: %s", opus_strerror(rc));
243 return -1;
244 }
250 245
251 246
252 return err == OPUS_OK ? 0 : -1; 247 return 0;
253} 248}
254 249
255 250
@@ -293,7 +288,7 @@ void codec_terminate_session ( CodecState *cs )
293 288
294 289
295 /* TODO: Terminate video 290 /* TODO: Terminate video
296 * Do what??? 291 * Do what?
297 */ 292 */
298 if ( cs->capabilities & v_decoding ) 293 if ( cs->capabilities & v_decoding )
299 vpx_codec_destroy(&cs->v_decoder); 294 vpx_codec_destroy(&cs->v_decoder);
diff --git a/toxav/media.h b/toxav/media.h
index f5c5fbe4..68694664 100644
--- a/toxav/media.h
+++ b/toxav/media.h
@@ -68,9 +68,22 @@ typedef struct _CodecState {
68 68
69} CodecState; 69} CodecState;
70 70
71
72struct jitter_buffer {
73 RTPMessage **queue;
74 uint16_t capacity;
75 uint16_t size;
76 uint16_t front;
77 uint16_t rear;
78 uint8_t queue_ready;
79 uint16_t current_id;
80 uint32_t current_ts;
81 uint8_t id_set;
82};
83
71struct jitter_buffer *create_queue(int capacity); 84struct jitter_buffer *create_queue(int capacity);
72 85
73int queue(struct jitter_buffer *q, RTPMessage *pk); 86void queue(struct jitter_buffer *q, RTPMessage *pk);
74RTPMessage *dequeue(struct jitter_buffer *q, int *success); 87RTPMessage *dequeue(struct jitter_buffer *q, int *success);
75 88
76 89
diff --git a/toxav/msi.c b/toxav/msi.c
index ae6fcf84..8d4e6964 100755
--- a/toxav/msi.c
+++ b/toxav/msi.c
@@ -932,6 +932,7 @@ MSICall *init_call ( MSISession *session, int peers, int ringing_timeout )
932 932
933 if ( _call_idx == session->max_calls ) { 933 if ( _call_idx == session->max_calls ) {
934 LOGGER_WARNING("Reached maximum amount of calls!"); 934 LOGGER_WARNING("Reached maximum amount of calls!");
935 return NULL;
935 } 936 }
936 937
937 938
@@ -1017,7 +1018,7 @@ int terminate_call ( MSISession *session, MSICall *call )
1017/********** Request handlers **********/ 1018/********** Request handlers **********/
1018int handle_recv_invite ( MSISession *session, MSICall* call, MSIMessage *msg ) 1019int handle_recv_invite ( MSISession *session, MSICall* call, MSIMessage *msg )
1019{ 1020{
1020 LOGGER_DEBUG("Handling 'invite' on call: %s", call? (char*)call->id : "making new"); 1021 LOGGER_DEBUG("Session: %p Handling 'invite' on call: %s", session, call? (char*)call->id : "making new");
1021 1022
1022 if ( call ) { 1023 if ( call ) {
1023 if ( call->peers[0] == msg->friend_id ) { 1024 if ( call->peers[0] == msg->friend_id ) {
@@ -1071,7 +1072,7 @@ int handle_recv_invite ( MSISession *session, MSICall* call, MSIMessage *msg )
1071} 1072}
1072int handle_recv_start ( MSISession *session, MSICall* call, MSIMessage *msg ) 1073int handle_recv_start ( MSISession *session, MSICall* call, MSIMessage *msg )
1073{ 1074{
1074 LOGGER_DEBUG("Handling 'start' on call: %s", call->id ); 1075 LOGGER_DEBUG("Session: %p Handling 'start' on call: %s", session, call->id );
1075 1076
1076 if ( has_call_error ( session, call, msg ) == 0 ) 1077 if ( has_call_error ( session, call, msg ) == 0 )
1077 return -1; 1078 return -1;
@@ -1095,7 +1096,7 @@ int handle_recv_start ( MSISession *session, MSICall* call, MSIMessage *msg )
1095} 1096}
1096int handle_recv_reject ( MSISession *session, MSICall* call, MSIMessage *msg ) 1097int handle_recv_reject ( MSISession *session, MSICall* call, MSIMessage *msg )
1097{ 1098{
1098 LOGGER_DEBUG("Handling 'reject' on call: %s", call->id ); 1099 LOGGER_DEBUG("Session: %p Handling 'reject' on call: %s", session, call->id);
1099 1100
1100 if ( has_call_error ( session, call, msg ) == 0 ) 1101 if ( has_call_error ( session, call, msg ) == 0 )
1101 return 0; 1102 return 0;
@@ -1118,7 +1119,7 @@ int handle_recv_reject ( MSISession *session, MSICall* call, MSIMessage *msg )
1118} 1119}
1119int handle_recv_cancel ( MSISession *session, MSICall* call, MSIMessage *msg ) 1120int handle_recv_cancel ( MSISession *session, MSICall* call, MSIMessage *msg )
1120{ 1121{
1121 LOGGER_DEBUG("Handling 'cancel' on call: %s", call->id ); 1122 LOGGER_DEBUG("Session: %p Handling 'cancel' on call: %s", session, call->id );
1122 1123
1123 if ( has_call_error ( session, call, msg ) == 0 ) 1124 if ( has_call_error ( session, call, msg ) == 0 )
1124 return 0; 1125 return 0;
@@ -1137,7 +1138,7 @@ int handle_recv_cancel ( MSISession *session, MSICall* call, MSIMessage *msg )
1137} 1138}
1138int handle_recv_end ( MSISession *session, MSICall* call, MSIMessage *msg ) 1139int handle_recv_end ( MSISession *session, MSICall* call, MSIMessage *msg )
1139{ 1140{
1140 LOGGER_DEBUG("Handling 'end' on call: %s", call->id ); 1141 LOGGER_DEBUG("Session: %p Handling 'end' on call: %s", session, call->id );
1141 1142
1142 if ( has_call_error ( session, call, msg ) == 0 ) 1143 if ( has_call_error ( session, call, msg ) == 0 )
1143 return 0; 1144 return 0;
@@ -1156,7 +1157,7 @@ int handle_recv_end ( MSISession *session, MSICall* call, MSIMessage *msg )
1156/********** Response handlers **********/ 1157/********** Response handlers **********/
1157int handle_recv_ringing ( MSISession *session, MSICall* call, MSIMessage *msg ) 1158int handle_recv_ringing ( MSISession *session, MSICall* call, MSIMessage *msg )
1158{ 1159{
1159 LOGGER_DEBUG("Handling 'ringing' on call: %s", call->id ); 1160 LOGGER_DEBUG("Session: %p Handling 'ringing' on call: %s", session, call->id );
1160 1161
1161 if ( has_call_error ( session, call, msg ) == 0 ) 1162 if ( has_call_error ( session, call, msg ) == 0 )
1162 return 0; 1163 return 0;
@@ -1169,7 +1170,7 @@ int handle_recv_ringing ( MSISession *session, MSICall* call, MSIMessage *msg )
1169} 1170}
1170int handle_recv_starting ( MSISession *session, MSICall* call, MSIMessage *msg ) 1171int handle_recv_starting ( MSISession *session, MSICall* call, MSIMessage *msg )
1171{ 1172{
1172 LOGGER_DEBUG("Handling 'starting' on call: %s", call->id ); 1173 LOGGER_DEBUG("Session: %p Handling 'starting' on call: %s", session, call->id );
1173 1174
1174 if ( has_call_error ( session, call, msg ) == 0 ) 1175 if ( has_call_error ( session, call, msg ) == 0 )
1175 return 0; 1176 return 0;
@@ -1210,7 +1211,7 @@ int handle_recv_starting ( MSISession *session, MSICall* call, MSIMessage *msg )
1210} 1211}
1211int handle_recv_ending ( MSISession *session, MSICall* call, MSIMessage *msg ) 1212int handle_recv_ending ( MSISession *session, MSICall* call, MSIMessage *msg )
1212{ 1213{
1213 LOGGER_DEBUG("Handling 'ending' on call: %s", call->id ); 1214 LOGGER_DEBUG("Session: %p Handling 'ending' on call: %s", session, call->id );
1214 1215
1215 if ( has_call_error ( session, call, msg ) == 0 ) 1216 if ( has_call_error ( session, call, msg ) == 0 )
1216 return 0; 1217 return 0;
@@ -1232,7 +1233,7 @@ int handle_recv_error ( MSISession *session, MSICall* call, MSIMessage *msg )
1232 return -1; 1233 return -1;
1233 } 1234 }
1234 1235
1235 LOGGER_DEBUG("Handling 'error' on call: %s", call->id ); 1236 LOGGER_DEBUG("Session: %p Handling 'error' on call: %s", session, call->id );
1236 1237
1237 /* Handle error accordingly */ 1238 /* Handle error accordingly */
1238 if ( msg->reason.header_value ) { 1239 if ( msg->reason.header_value ) {
@@ -1490,7 +1491,8 @@ int msi_terminate_session ( MSISession *session )
1490 } 1491 }
1491 1492
1492 m_callback_msi_packet((struct Messenger *) session->messenger_handle, NULL, NULL); 1493 m_callback_msi_packet((struct Messenger *) session->messenger_handle, NULL, NULL);
1493 1494
1495 LOGGER_DEBUG("Terminated session: %p", session);
1494 free ( session ); 1496 free ( session );
1495 return _status; 1497 return _status;
1496} 1498}
@@ -1507,7 +1509,7 @@ int msi_terminate_session ( MSISession *session )
1507 */ 1509 */
1508int msi_invite ( MSISession* session, uint32_t* call_index, MSICallType call_type, uint32_t rngsec, uint32_t friend_id ) 1510int msi_invite ( MSISession* session, uint32_t* call_index, MSICallType call_type, uint32_t rngsec, uint32_t friend_id )
1509{ 1511{
1510 LOGGER_DEBUG("Inviting friend: %u", friend_id); 1512 LOGGER_DEBUG("Session: %p Inviting friend: %u", session, friend_id);
1511 1513
1512 MSIMessage *_msg_invite = msi_new_message ( TYPE_REQUEST, stringify_request ( invite ) ); 1514 MSIMessage *_msg_invite = msi_new_message ( TYPE_REQUEST, stringify_request ( invite ) );
1513 1515
@@ -1553,7 +1555,7 @@ int msi_invite ( MSISession* session, uint32_t* call_index, MSICallType call_typ
1553 */ 1555 */
1554int msi_hangup ( MSISession* session, uint32_t call_index ) 1556int msi_hangup ( MSISession* session, uint32_t call_index )
1555{ 1557{
1556 LOGGER_DEBUG("Hanging up call: %u", call_index); 1558 LOGGER_DEBUG("Session: %p Hanging up call: %u", session, call_index);
1557 1559
1558 if ( call_index >= session->max_calls || !session->calls[call_index] ) { 1560 if ( call_index >= session->max_calls || !session->calls[call_index] ) {
1559 LOGGER_ERROR("Invalid call index!"); 1561 LOGGER_ERROR("Invalid call index!");
@@ -1592,7 +1594,7 @@ int msi_hangup ( MSISession* session, uint32_t call_index )
1592 */ 1594 */
1593int msi_answer ( MSISession* session, uint32_t call_index, MSICallType call_type ) 1595int msi_answer ( MSISession* session, uint32_t call_index, MSICallType call_type )
1594{ 1596{
1595 LOGGER_DEBUG("Answering call: %u", call_index); 1597 LOGGER_DEBUG("Session: %p Answering call: %u", session, call_index);
1596 1598
1597 if ( call_index >= session->max_calls || !session->calls[call_index] ){ 1599 if ( call_index >= session->max_calls || !session->calls[call_index] ){
1598 LOGGER_ERROR("Invalid call index!"); 1600 LOGGER_ERROR("Invalid call index!");
@@ -1641,7 +1643,7 @@ int msi_answer ( MSISession* session, uint32_t call_index, MSICallType call_type
1641 */ 1643 */
1642int msi_cancel ( MSISession *session, uint32_t call_index, uint32_t peer, const char *reason ) 1644int msi_cancel ( MSISession *session, uint32_t call_index, uint32_t peer, const char *reason )
1643{ 1645{
1644 LOGGER_DEBUG("Canceling call: %u; reason:", call_index, reason? reason : "Unknown"); 1646 LOGGER_DEBUG("Session: %p Canceling call: %u; reason:", session, call_index, reason? reason : "Unknown");
1645 1647
1646 if ( call_index >= session->max_calls || !session->calls[call_index] ){ 1648 if ( call_index >= session->max_calls || !session->calls[call_index] ){
1647 LOGGER_ERROR("Invalid call index!"); 1649 LOGGER_ERROR("Invalid call index!");
@@ -1670,7 +1672,7 @@ int msi_cancel ( MSISession *session, uint32_t call_index, uint32_t peer, const
1670 */ 1672 */
1671int msi_reject ( MSISession *session, uint32_t call_index, const uint8_t *reason ) 1673int msi_reject ( MSISession *session, uint32_t call_index, const uint8_t *reason )
1672{ 1674{
1673 LOGGER_DEBUG("Rejecting call: %u; reason:", call_index, reason? (char*)reason : "Unknown"); 1675 LOGGER_DEBUG("Session: %p Rejecting call: %u; reason:", session, call_index, reason? (char*)reason : "Unknown");
1674 1676
1675 if ( call_index >= session->max_calls || !session->calls[call_index] ){ 1677 if ( call_index >= session->max_calls || !session->calls[call_index] ){
1676 LOGGER_ERROR("Invalid call index!"); 1678 LOGGER_ERROR("Invalid call index!");
@@ -1699,7 +1701,7 @@ int msi_reject ( MSISession *session, uint32_t call_index, const uint8_t *reason
1699 */ 1701 */
1700int msi_stopcall ( MSISession *session, uint32_t call_index ) 1702int msi_stopcall ( MSISession *session, uint32_t call_index )
1701{ 1703{
1702 LOGGER_DEBUG("Stopping call index: %u", call_index); 1704 LOGGER_DEBUG("Session: %p Stopping call index: %u", session, call_index);
1703 1705
1704 if ( call_index >= session->max_calls || !session->calls[call_index] ) 1706 if ( call_index >= session->max_calls || !session->calls[call_index] )
1705 return -1; 1707 return -1;
diff --git a/toxav/phone.c b/toxav/phone.c
deleted file mode 100755
index 2b33f7e9..00000000
--- a/toxav/phone.c
+++ /dev/null
@@ -1,1460 +0,0 @@
1/** phone.c
2 *
3 * NOTE NOTE NOTE NOTE NOTE NOTE
4 *
5 * This file is for testing/reference purposes only, hence
6 * it is _poorly_ designed and it does not fully reflect the
7 * quaility of msi nor rtp. Although toxmsi* and toxrtp* are tested
8 * there is always possiblity of crashes. If crash occures,
9 * contact me ( mannol ) on either irc channel #tox-dev @ freenode.net:6667
10 * or eniz_vukovic@hotmail.com
11 *
12 * NOTE NOTE NOTE NOTE NOTE NOTE
13 *
14 * Copyright (C) 2013 Tox project All Rights Reserved.
15 *
16 * This file is part of Tox.
17 *
18 * Tox is free software: you can redistribute it and/or modify
19 * it under the terms of the GNU General Public License as published by
20 * the Free Software Foundation, either version 3 of the License, or
21 * (at your option) any later version.
22 *
23 * Tox is distributed in the hope that it will be useful,
24 * but WITHOUT ANY WARRANTY; without even the implied warranty of
25 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
26 * GNU General Public License for more details.
27 *
28 * You should have received a copy of the GNU General Public License
29 * along with Tox. If not, see <http://www.gnu.org/licenses/>.
30 *
31 */
32
33#ifdef HAVE_CONFIG_H
34#include "config.h"
35#endif /* HAVE_CONFIG_H */
36
37#define _BSD_SOURCE
38
39#include <stdio.h>
40#include <string.h>
41#include <stdlib.h>
42#include <stdarg.h>
43#include <unistd.h>
44#include <assert.h>
45#include <math.h>
46#include <pthread.h>
47
48//#include "media.h"
49#include "toxav.h"
50#include "event.h"
51#include "../toxcore/tox.h"
52
53#define AUDIO_FRAME_SIZE (av_DefaultSettings.audio_sample_rate * av_DefaultSettings.audio_frame_duration / 1000)
54
55#ifdef TOX_FFMPEG
56/* Video encoding/decoding */
57#include <libavcodec/avcodec.h>
58#include <libavformat/avformat.h>
59#include <libswscale/swscale.h>
60#include <libavdevice/avdevice.h>
61#include <libavutil/opt.h>
62#endif
63
64#include <AL/al.h>
65#include <AL/alc.h>
66#include <SDL/SDL.h>
67#include <SDL/SDL_thread.h>
68
69/* the quit event for SDL */
70#define FF_QUIT_EVENT (SDL_USEREVENT + 2)
71
72#ifdef __linux__
73#define VIDEO_DRIVER "video4linux2"
74#define DEFAULT_WEBCAM "/dev/video0"
75#endif
76
77#if defined(_WIN32) || defined(__WIN32__) || defined (WIN32)
78#define VIDEO_DRIVER "vfwcap"
79#define DEFAULT_WEBCAM "0"
80#endif
81
82
83/* Define client version */
84#define _USERAGENT "v.0.3.0"
85
86
87struct SDL_Surface *screen;
88
89typedef struct {
90 struct SDL_Overlay *bmp;
91 int width, height;
92} VideoPicture;
93
94
95typedef struct av_friend_s {
96 int _id;
97 int _active; /* 0=false; 1=true; */
98} av_friend_t;
99
100typedef struct av_session_s {
101 /* Encoding/decoding/capturing/playing */
102 ToxAv *av;
103
104 VideoPicture video_picture;
105 struct ALCdevice *audio_capture_device;
106
107 /* context for converting image format to something SDL can use*/
108 struct SwsContext *sws_SDL_r_ctx;
109
110 /* context for converting webcam image format to something the video encoder can use */
111 struct SwsContext *sws_ctx;
112
113 /* Thread running control */
114 int running_decaud, running_encaud,
115 running_decvid, running_encvid;
116
117 pthread_mutex_t _mutex;
118
119 Tox *_messenger;
120 av_friend_t *_friends;
121 int _friend_cout;
122 char _my_public_id[200];
123#ifdef TOX_FFMPEG
124 AVInputFormat *video_input_format;
125 AVFormatContext *video_format_ctx;
126 uint8_t video_stream;
127 AVCodecContext *webcam_decoder_ctx;
128 AVCodec *webcam_decoder;
129#endif
130} av_session_t;
131av_session_t *_phone;
132
133void av_allocate_friend(av_session_t *_phone, int _id, int _active)
134{
135 static int _new_id = 0;
136
137 if ( !_phone->_friends ) {
138 _phone->_friends = calloc(sizeof(av_friend_t), 1);
139 _phone->_friend_cout = 1;
140 } else {
141 _phone->_friend_cout ++;
142 _phone->_friends = realloc(_phone->_friends, sizeof(av_friend_t) * _phone->_friend_cout);
143 }
144
145 if ( _id == -1 ) {
146 _phone->_friends->_id = _new_id;
147 _new_id ++;
148 } else _phone->_friends->_id = _id;
149
150 _phone->_friends->_active = _active;
151}
152av_friend_t *av_get_friend(av_session_t *_phone, int _id)
153{
154 av_friend_t *_friends = _phone->_friends;
155
156 if ( !_friends ) return NULL;
157
158 int _it = 0;
159
160 for (; _it < _phone->_friend_cout; _it ++)
161 if ( _friends[_it]._id == _id )
162 return _friends + _it;
163
164 return NULL;
165}
166
167
168/***************** MISC *****************/
169
170void INFO (const char *_format, ...)
171{
172 printf("\r[!] ");
173 va_list _arg;
174 va_start (_arg, _format);
175 vfprintf (stdout, _format, _arg);
176 va_end (_arg);
177 printf("\n\r >> ");
178 fflush(stdout);
179}
180
181unsigned char *hex_string_to_bin(char hex_string[])
182{
183 size_t i, len = strlen(hex_string);
184 unsigned char *val = calloc(sizeof(unsigned char), len);
185 char *pos = hex_string;
186
187 for (i = 0; i < len; ++i, pos += 2)
188 sscanf(pos, "%2hhx", &val[i]);
189
190 return val;
191}
192
193int getinput( char *_buff, size_t _limit, int *_len )
194{
195 if ( fgets(_buff, _limit, stdin) == NULL )
196 return -1;
197
198 *_len = strlen(_buff) - 1;
199
200 /* Get rid of newline */
201 _buff[*_len] = '\0';
202
203 return 0;
204}
205
206char *trim_spaces ( char *buff )
207{
208
209 int _i = 0, _len = strlen(buff);
210
211 char *container = calloc(sizeof(char), _len);
212 int _ci = 0;
213
214 for ( ; _i < _len; _i++ ) {
215 while ( _i < _len && buff[_i] == ' ' )
216 _i++;
217
218 if ( _i < _len ) {
219 container[_ci] = buff[_i];
220 _ci ++;
221 }
222 }
223
224 memcpy( buff, container, _ci );
225 buff[_ci] = '\0';
226 free(container);
227 return buff;
228}
229
230#define FRADDR_TOSTR_CHUNK_LEN 8
231
232static void fraddr_to_str(uint8_t *id_bin, char *id_str)
233{
234 uint i, delta = 0, pos_extra = 0, sum_extra = 0;
235
236 for (i = 0; i < TOX_FRIEND_ADDRESS_SIZE; i++) {
237 sprintf(&id_str[2 * i + delta], "%02hhX", id_bin[i]);
238
239 if ((i + 1) == TOX_CLIENT_ID_SIZE)
240 pos_extra = 2 * (i + 1) + delta;
241
242 if (i >= TOX_CLIENT_ID_SIZE)
243 sum_extra |= id_bin[i];
244
245 if (!((i + 1) % FRADDR_TOSTR_CHUNK_LEN)) {
246 id_str[2 * (i + 1) + delta] = ' ';
247 delta++;
248 }
249 }
250
251 id_str[2 * i + delta] = 0;
252
253 if (!sum_extra)
254 id_str[pos_extra] = 0;
255}
256
257/*********************************************
258 *********************************************
259 *********************************************
260 *********************************************
261 *********************************************
262 *********************************************
263 *********************************************
264 *********************************************
265 */
266
267
268/*
269 * How av stuff _should_ look like
270 */
271/*
272int display_received_frame(av_session_t* _phone, vpx_image_t *image)
273{
274 CodecState* cs = get_cs_temp(_phone->av);
275 AVPicture pict;
276 SDL_LockYUVOverlay(_phone->video_picture.bmp);
277
278 pict.data[0] = _phone->video_picture.bmp->pixels[0];
279 pict.data[1] = _phone->video_picture.bmp->pixels[2];
280 pict.data[2] = _phone->video_picture.bmp->pixels[1];
281 pict.linesize[0] = _phone->video_picture.bmp->pitches[0];
282 pict.linesize[1] = _phone->video_picture.bmp->pitches[2];
283 pict.linesize[2] = _phone->video_picture.bmp->pitches[1];
284 */
285/* Convert the image into YUV format that SDL uses *//*
286sws_scale(_phone->sws_SDL_r_ctx, (uint8_t const * const *)r_video_frame->data, r_video_frame->linesize, 0,
287 cs->video_decoder_ctx->height, pict.data, pict.linesize );
288
289SDL_UnlockYUVOverlay(_phone->video_picture.bmp);
290SDL_Rect rect;
291rect.x = 0;
292rect.y = 0;
293rect.w = cs->video_decoder_ctx->width;
294rect.h = cs->video_decoder_ctx->height;
295SDL_DisplayYUVOverlay(_phone->video_picture.bmp, &rect);
296return 1;
297}
298*/
299#ifdef TOX_FFMPEG
300void *encode_video_thread(void *arg)
301{
302 INFO("Started encode video thread!");
303
304 av_session_t *_phone = arg;
305
306 _phone->running_encvid = 1;
307 //CodecState *cs = get_cs_temp(_phone->av);
308 AVPacket pkt1, *packet = &pkt1;
309 //int p = 0;
310 //int got_packet;
311 int video_frame_finished;
312 AVFrame *s_video_frame;
313 AVFrame *webcam_frame;
314 s_video_frame = avcodec_alloc_frame();
315 webcam_frame = avcodec_alloc_frame();
316 //AVPacket enc_video_packet;
317
318 uint8_t *buffer;
319 int numBytes;
320 /* Determine required buffer size and allocate buffer */
321 numBytes = avpicture_get_size(PIX_FMT_YUV420P, _phone->webcam_decoder_ctx->width, _phone->webcam_decoder_ctx->height);
322 buffer = (uint8_t *)av_calloc(numBytes * sizeof(uint8_t), 1);
323 avpicture_fill((AVPicture *)s_video_frame, buffer, PIX_FMT_YUV420P, _phone->webcam_decoder_ctx->width,
324 _phone->webcam_decoder_ctx->height);
325 _phone->sws_ctx = sws_getContext(_phone->webcam_decoder_ctx->width, _phone->webcam_decoder_ctx->height,
326 _phone->webcam_decoder_ctx->pix_fmt, _phone->webcam_decoder_ctx->width, _phone->webcam_decoder_ctx->height,
327 PIX_FMT_YUV420P,
328 SWS_BILINEAR, NULL, NULL, NULL);
329
330
331 vpx_image_t *image =
332 vpx_img_alloc(NULL, VPX_IMG_FMT_I420, _phone->webcam_decoder_ctx->width, _phone->webcam_decoder_ctx->height, 1);
333
334 //uint32_t frame_counter = 0;
335 while (_phone->running_encvid) {
336
337 if (av_read_frame(_phone->video_format_ctx, packet) < 0) {
338 printf("error reading frame\n");
339
340 if (_phone->video_format_ctx->pb->error != 0)
341 break;
342
343 continue;
344 }
345
346 if (packet->stream_index == _phone->video_stream) {
347 if (avcodec_decode_video2(_phone->webcam_decoder_ctx, webcam_frame, &video_frame_finished, packet) < 0) {
348 printf("couldn't decode\n");
349 continue;
350 }
351
352 av_free_packet(packet);
353 sws_scale(_phone->sws_ctx, (uint8_t const * const *)webcam_frame->data, webcam_frame->linesize, 0,
354 _phone->webcam_decoder_ctx->height, s_video_frame->data, s_video_frame->linesize);
355 /* create a new I-frame every 60 frames */
356 //++p;
357 /*
358 if (p == 60) {
359
360 s_video_frame->pict_type = AV_PICTURE_TYPE_BI ;
361 } else if (p == 61) {
362 s_video_frame->pict_type = AV_PICTURE_TYPE_I ;
363 p = 0;
364 } else {
365 s_video_frame->pict_type = AV_PICTURE_TYPE_P ;
366 }*/
367
368 if (video_frame_finished) {
369 memcpy(image->planes[VPX_PLANE_Y], s_video_frame->data[0],
370 s_video_frame->linesize[0] * _phone->webcam_decoder_ctx->height);
371 memcpy(image->planes[VPX_PLANE_U], s_video_frame->data[1],
372 s_video_frame->linesize[1] * _phone->webcam_decoder_ctx->height / 2);
373 memcpy(image->planes[VPX_PLANE_V], s_video_frame->data[2],
374 s_video_frame->linesize[2] * _phone->webcam_decoder_ctx->height / 2);
375 toxav_send_video (_phone->av, image);
376 //if (avcodec_encode_video2(cs->video_encoder_ctx, &enc_video_packet, s_video_frame, &got_packet) < 0) {
377 /*if (vpx_codec_encode(&cs->v_encoder, image, frame_counter, 1, 0, 0) != VPX_CODEC_OK) {
378 printf("could not encode video frame\n");
379 continue;
380 }
381 ++frame_counter;
382
383 vpx_codec_iter_t iter = NULL;
384 vpx_codec_cx_pkt_t *pkt;
385 while( (pkt = vpx_codec_get_cx_data(&cs->v_encoder, &iter)) ) {
386 if (pkt->kind == VPX_CODEC_CX_FRAME_PKT)
387 toxav_send_rtp_payload(_phone->av, TypeVideo, pkt->data.frame.buf, pkt->data.frame.sz);
388 }*/
389 //if (!got_packet) {
390 // continue;
391 //}
392
393 //if (!enc_video_packet.data) fprintf(stderr, "video packet data is NULL\n");
394
395 //toxav_send_rtp_payload(_phone->av, TypeVideo, enc_video_packet.data, enc_video_packet.size);
396
397 //av_free_packet(&enc_video_packet);
398 }
399 } else {
400 av_free_packet(packet);
401 }
402 }
403
404 vpx_img_free(image);
405
406 /* clean up codecs */
407 //pthread_mutex_lock(&cs->ctrl_mutex);
408 av_free(buffer);
409 av_free(webcam_frame);
410 av_free(s_video_frame);
411 sws_freeContext(_phone->sws_ctx);
412 //avcodec_close(webcam_decoder_ctx);
413 //avcodec_close(cs->video_encoder_ctx);
414 //pthread_mutex_unlock(&cs->ctrl_mutex);
415
416 _phone->running_encvid = -1;
417
418 pthread_exit ( NULL );
419}
420#endif
421
422void *encode_audio_thread(void *arg)
423{
424 INFO("Started encode audio thread!");
425 av_session_t *_phone = arg;
426 _phone->running_encaud = 1;
427
428 int ret = 0;
429 int16_t frame[4096];
430 int frame_size = AUDIO_FRAME_SIZE;
431 ALint sample = 0;
432 alcCaptureStart((ALCdevice *)_phone->audio_capture_device);
433 while (_phone->running_encaud) {
434
435 alcGetIntegerv((ALCdevice *)_phone->audio_capture_device, ALC_CAPTURE_SAMPLES, (ALCsizei)sizeof(ALint), &sample);
436
437 if (sample >= frame_size) {
438 alcCaptureSamples((ALCdevice *)_phone->audio_capture_device, frame, frame_size);
439
440 ret = toxav_send_audio(_phone->av, frame, frame_size);
441
442 if (ret < 0) printf("Could not encode or send audio packet\n");
443
444 } else {
445 usleep(1000);
446 }
447 }
448
449 /* clean up codecs *
450 pthread_mutex_lock(&cs->ctrl_mutex);* /
451 alcCaptureStop((ALCdevice*)_phone->audio_capture_device);
452 alcCaptureCloseDevice((ALCdevice*)_phone->audio_capture_device);
453 / *pthread_mutex_unlock(&cs->ctrl_mutex);*/
454 _phone->running_encaud = -1;
455 pthread_exit ( NULL );
456}
457
458void convert_to_rgb(vpx_image_t *img, unsigned char *out)
459{
460 const int w = img->d_w;
461 const int w2 = w / 2;
462 const int pstride = w * 3;
463 const int h = img->d_h;
464 const int h2 = h / 2;
465
466 const int strideY = img->stride[0];
467 const int strideU = img->stride[1];
468 const int strideV = img->stride[2];
469 int posy, posx;
470
471 for (posy = 0; posy < h2; posy++) {
472 unsigned char *dst = out + pstride * (posy * 2);
473 unsigned char *dst2 = out + pstride * (posy * 2 + 1);
474 const unsigned char *srcY = img->planes[0] + strideY * posy * 2;
475 const unsigned char *srcY2 = img->planes[0] + strideY * (posy * 2 + 1);
476 const unsigned char *srcU = img->planes[1] + strideU * posy;
477 const unsigned char *srcV = img->planes[2] + strideV * posy;
478
479 for (posx = 0; posx < w2; posx++) {
480 unsigned char Y, U, V;
481 short R, G, B;
482 short iR, iG, iB;
483
484 U = *(srcU++);
485 V = *(srcV++);
486 iR = (351 * (V - 128)) / 256;
487 iG = - (179 * (V - 128)) / 256 - (86 * (U - 128)) / 256;
488 iB = (444 * (U - 128)) / 256;
489
490 Y = *(srcY++);
491 R = Y + iR ;
492 G = Y + iG ;
493 B = Y + iB ;
494 R = (R < 0 ? 0 : (R > 255 ? 255 : R));
495 G = (G < 0 ? 0 : (G > 255 ? 255 : G));
496 B = (B < 0 ? 0 : (B > 255 ? 255 : B));
497 *(dst++) = R;
498 *(dst++) = G;
499 *(dst++) = B;
500
501 Y = *(srcY2++);
502 R = Y + iR ;
503 G = Y + iG ;
504 B = Y + iB ;
505 R = (R < 0 ? 0 : (R > 255 ? 255 : R));
506 G = (G < 0 ? 0 : (G > 255 ? 255 : G));
507 B = (B < 0 ? 0 : (B > 255 ? 255 : B));
508 *(dst2++) = R;
509 *(dst2++) = G;
510 *(dst2++) = B;
511
512 Y = *(srcY++) ;
513 R = Y + iR ;
514 G = Y + iG ;
515 B = Y + iB ;
516 R = (R < 0 ? 0 : (R > 255 ? 255 : R));
517 G = (G < 0 ? 0 : (G > 255 ? 255 : G));
518 B = (B < 0 ? 0 : (B > 255 ? 255 : B));
519 *(dst++) = R;
520 *(dst++) = G;
521 *(dst++) = B;
522
523 Y = *(srcY2++);
524 R = Y + iR ;
525 G = Y + iG ;
526 B = Y + iB ;
527 R = (R < 0 ? 0 : (R > 255 ? 255 : R));
528 G = (G < 0 ? 0 : (G > 255 ? 255 : G));
529 B = (B < 0 ? 0 : (B > 255 ? 255 : B));
530 *(dst2++) = R;
531 *(dst2++) = G;
532 *(dst2++) = B;
533 }
534 }
535}
536
537#define mask32(BYTE) (*(uint32_t *)(uint8_t [4]){ [BYTE] = 0xff })
538
539void *decode_video_thread(void *arg)
540{
541 INFO("Started decode video thread!");
542 av_session_t *_phone = arg;
543 _phone->running_decvid = 1;
544
545 //CodecState *cs = get_cs_temp(_phone->av);
546 //cs->video_stream = 0;
547
548 //int recved_size;
549 //uint8_t dest[RTP_PAYLOAD_SIZE];
550
551 //int dec_frame_finished;
552 //AVFrame *r_video_frame;
553 //r_video_frame = avcodec_alloc_frame();
554 //AVPacket dec_video_packet;
555 //av_new_packet (&dec_video_packet, 65536);
556 int width = 0;
557 int height = 0;
558
559 while (_phone->running_decvid) {
560 //recved_size = toxav_recv_rtp_payload(_phone->av, TypeVideo, dest);
561 //if (recved_size) {
562 vpx_image_t *image = NULL;
563
564 if (toxav_recv_video(_phone->av, &image) == 0 && image) {
565 //memcpy(dec_video_packet.data, dest, recved_size);
566 //dec_video_packet.size = recved_size;
567
568 //avcodec_decode_video2(cs->video_decoder_ctx, r_video_frame, &dec_frame_finished, &dec_video_packet);
569
570 //if (dec_frame_finished) {
571
572 /* Check if size has changed */
573 if (image->d_w != width || image->d_h != height) {
574
575 width = image->d_w;
576 height = image->d_h;
577
578 printf("w: %d h: %d \n", width, height);
579
580 screen = SDL_SetVideoMode(width, height, 0, 0);
581
582 //if (_phone->video_picture.bmp)
583 // SDL_FreeYUVOverlay(_phone->video_picture.bmp);
584
585 //_phone->video_picture.bmp = SDL_CreateYUVOverlay(width, height, SDL_YV12_OVERLAY, screen);
586 // _phone->sws_SDL_r_ctx = sws_getContext(width, height, cs->video_decoder_ctx->pix_fmt, width, height, PIX_FMT_YUV420P,
587 // SWS_BILINEAR, NULL, NULL, NULL);
588 }
589
590 uint8_t *rgb_image = malloc(width * height * 3);
591 convert_to_rgb(image, rgb_image);
592 SDL_Surface *img_surface = SDL_CreateRGBSurfaceFrom(rgb_image, width, height, 24, width * 3, mask32(0), mask32(1),
593 mask32(2), 0);
594
595 if (SDL_BlitSurface(img_surface, NULL, screen, NULL) == 0)
596 SDL_UpdateRect(screen, 0, 0, 0, 0);
597
598 /*
599 SDL_LockYUVOverlay(_phone->video_picture.bmp);
600 memcpy(_phone->video_picture.bmp->pixels[0], image->planes[VPX_PLANE_Y], _phone->video_picture.bmp->pitches[0] * height);
601 memcpy(_phone->video_picture.bmp->pixels[1], image->planes[VPX_PLANE_V], _phone->video_picture.bmp->pitches[1] * height / 2);
602 memcpy(_phone->video_picture.bmp->pixels[2], image->planes[VPX_PLANE_U], _phone->video_picture.bmp->pitches[2] * height / 2);
603
604 SDL_Rect rect;
605 rect.x = 0;
606 rect.y = 0;
607 rect.w = width;
608 rect.h = height;
609 SDL_DisplayYUVOverlay(_phone->video_picture.bmp, &rect);*/
610 free(rgb_image);
611 //display_received_frame(_phone, image);
612
613 } //else {
614
615 /* TODO: request the sender to create a new i-frame immediatly */
616 //printf("Bad video packet\n");
617 //}
618 //}
619
620 usleep(1000);
621 }
622
623 /* clean up codecs */
624 //av_free(r_video_frame);
625
626 //pthread_mutex_lock(&cs->ctrl_mutex);
627 //avcodec_close(cs->video_decoder_ctx);
628 //pthread_mutex_unlock(&cs->ctrl_mutex);
629
630 _phone->running_decvid = -1;
631
632 pthread_exit ( NULL );
633}
634
635void *decode_audio_thread(void *arg)
636{
637 INFO("Started decode audio thread!");
638 av_session_t *_phone = arg;
639 _phone->running_decaud = 1;
640
641 //int recved_size;
642 //uint8_t dest [RTP_PAYLOAD_SIZE];
643
644 int frame_size = AUDIO_FRAME_SIZE;
645 //int data_size;
646
647 ALCdevice *dev;
648 ALCcontext *ctx;
649 ALuint source, *buffers;
650 dev = alcOpenDevice(NULL);
651 ctx = alcCreateContext(dev, NULL);
652 alcMakeContextCurrent(ctx);
653 int openal_buffers = 5;
654
655 buffers = calloc(sizeof(ALuint) * openal_buffers, 1);
656 alGenBuffers(openal_buffers, buffers);
657 alGenSources((ALuint)1, &source);
658 alSourcei(source, AL_LOOPING, AL_FALSE);
659
660 ALuint buffer;
661 ALint ready;
662
663 uint16_t zeros[frame_size];
664 memset(zeros, 0, frame_size);
665 int16_t PCM[frame_size];
666
667 int i;
668
669 for (i = 0; i < openal_buffers; ++i) {
670 alBufferData(buffers[i], AL_FORMAT_MONO16, zeros, frame_size, 48000);
671 }
672
673 alSourceQueueBuffers(source, openal_buffers, buffers);
674 alSourcePlay(source);
675
676 if (alGetError() != AL_NO_ERROR) {
677 fprintf(stderr, "Error starting audio\n");
678 goto ending;
679 }
680
681 int dec_frame_len = 0;
682
683 while (_phone->running_decaud) {
684
685 alGetSourcei(source, AL_BUFFERS_PROCESSED, &ready);
686
687 if (ready <= 0)
688 continue;
689
690 dec_frame_len = toxav_recv_audio(_phone->av, frame_size, PCM);
691
692 /* Play the packet */
693 if (dec_frame_len > 0) {
694 alSourceUnqueueBuffers(source, 1, &buffer);
695 alBufferData(buffer, AL_FORMAT_MONO16, PCM, dec_frame_len * 2 * 1, 48000);
696 int error = alGetError();
697
698 if (error != AL_NO_ERROR) {
699 fprintf(stderr, "Error setting buffer %d\n", error);
700 break;
701 }
702
703 alSourceQueueBuffers(source, 1, &buffer);
704
705 if (alGetError() != AL_NO_ERROR) {
706 fprintf(stderr, "Error: could not buffer audio\n");
707 break;
708 }
709
710 alGetSourcei(source, AL_SOURCE_STATE, &ready);
711
712 if (ready != AL_PLAYING) alSourcePlay(source);
713 }
714
715 usleep(1000);
716 }
717
718
719ending:
720 /* clean up codecs */
721 //pthread_mutex_lock(&cs->ctrl_mutex);
722 /*
723 alDeleteSources(1, &source);
724 alDeleteBuffers(openal_buffers, buffers);
725 alcMakeContextCurrent(NULL);
726 alcDestroyContext(ctx);
727 alcCloseDevice(dev);
728 */
729 //pthread_mutex_unlock(&cs->ctrl_mutex);
730
731 _phone->running_decaud = -1;
732
733 pthread_exit ( NULL );
734}
735
736
737
738void *one_threaded_audio(void *arg)
739{
740 INFO("Started audio thread!");
741 av_session_t *_phone = arg;
742 _phone->running_decaud = 1;
743
744 //int recved_size;
745 //uint8_t dest [RTP_PAYLOAD_SIZE];
746
747 int frame_size = AUDIO_FRAME_SIZE;
748
749 int16_t frame[4096];
750 ALint sample = 0;
751 alcCaptureStart((ALCdevice *)_phone->audio_capture_device);
752
753 ALCdevice *dev;
754 ALCcontext *ctx;
755 ALuint source, *buffers;
756 dev = alcOpenDevice(NULL);
757 ctx = alcCreateContext(dev, NULL);
758 alcMakeContextCurrent(ctx);
759 int openal_buffers = 5;
760
761 buffers = calloc(sizeof(ALuint) * openal_buffers, 1);
762 alGenBuffers(openal_buffers, buffers);
763 alGenSources((ALuint)1, &source);
764 alSourcei(source, AL_LOOPING, AL_FALSE);
765
766 ALuint buffer;
767 ALint ready;
768
769 uint16_t zeros[frame_size];
770 memset(zeros, 0, frame_size);
771 int16_t PCM[frame_size];
772
773 int i;
774
775 for (i = 0; i < openal_buffers; ++i) {
776 alBufferData(buffers[i], AL_FORMAT_MONO16, zeros, frame_size, 48000);
777 }
778
779 alSourceQueueBuffers(source, openal_buffers, buffers);
780 alSourcePlay(source);
781
782 if (alGetError() != AL_NO_ERROR) {
783 fprintf(stderr, "Error starting audio\n");
784 goto ending;
785 }
786
787 int dec_frame_len;
788
789 while (_phone->running_decaud) {
790
791 // combo
792 alcGetIntegerv((ALCdevice *)_phone->audio_capture_device, ALC_CAPTURE_SAMPLES, (ALCsizei)sizeof(ALint), &sample);
793
794 // record and send
795 if (sample >= frame_size) {
796 alcCaptureSamples((ALCdevice *)_phone->audio_capture_device, frame, frame_size);
797
798 if (toxav_send_audio(_phone->av, frame, frame_size) < 0)
799 printf("Could not encode or send audio packet\n");
800
801 } else {
802 usleep(5000);
803 }
804
805 // play received
806
807 alGetSourcei(source, AL_BUFFERS_PROCESSED, &ready);
808
809 if (ready <= 0)
810 continue;
811
812 dec_frame_len = toxav_recv_audio(_phone->av, frame_size, PCM);
813
814 /* Play the packet */
815 if (dec_frame_len > 0) {
816 alSourceUnqueueBuffers(source, 1, &buffer);
817 alBufferData(buffer, AL_FORMAT_MONO16, PCM, dec_frame_len * 2 * 1, 48000);
818 int error = alGetError();
819
820 if (error != AL_NO_ERROR) {
821 fprintf(stderr, "Error setting buffer %d\n", error);
822 break;
823 }
824
825 alSourceQueueBuffers(source, 1, &buffer);
826
827 if (alGetError() != AL_NO_ERROR) {
828 fprintf(stderr, "Error: could not buffer audio\n");
829 break;
830 }
831
832 alGetSourcei(source, AL_SOURCE_STATE, &ready);
833
834 if (ready != AL_PLAYING) alSourcePlay(source);
835 }
836
837 usleep(1000);
838 }
839
840
841 ending:
842 _phone->running_decaud = -1;
843
844 pthread_exit ( NULL );
845}
846
847
848int phone_startmedia_loop ( ToxAv *arg )
849{
850 if ( !arg ) {
851 return -1;
852 }
853
854 toxav_prepare_transmission(arg, 1);
855
856 /*
857 * Rise all threads
858 */
859#ifdef TOX_FFMPEG
860
861 /* Only checks for last peer */
862 if ( toxav_get_peer_transmission_type(arg, 0) == TypeVideo &&
863 0 > event.rise(encode_video_thread, _phone) ) {
864 INFO("Error while starting encode_video_thread()");
865 return -1;
866 }
867
868#endif
869
870 /* Always send audio */
871 /*if ( 0 > event.rise(encode_audio_thread, toxav_get_agent_handler(arg)) ) {
872 INFO("Error while starting encode_audio_thread()");
873 return -1;
874 } */
875
876 /* Only checks for last peer */
877 if ( toxav_get_peer_transmission_type(arg, 0) == TypeVideo &&
878 0 > event.rise(decode_video_thread, _phone) ) {
879 INFO("Error while starting decode_video_thread()");
880 return -1;
881 }
882
883 /*if ( 0 > event.rise(decode_audio_thread, toxav_get_agent_handler(arg)) ) {
884 INFO("Error while starting decode_audio_thread()");
885 return -1;
886 } */
887
888
889 /* One threaded audio */
890
891 if ( 0 > event.rise(one_threaded_audio, _phone) ) {
892 INFO ("Shit-head");
893 return -1;
894 }
895
896 return 0;
897}
898
899
900
901
902
903
904/*********************************************
905 *********************************************
906 *********************************************
907 *********************************************
908 *********************************************
909 *********************************************
910 *********************************************
911 *********************************************
912 */
913
914
915/* Some example callbacks */
916
917void callback_recv_invite ( void *_arg )
918{
919 assert(_arg);
920
921 switch ( toxav_get_peer_transmission_type(_arg, 0) ) {
922 case TypeAudio:
923 INFO( "Incoming audio call!");
924 break;
925
926 case TypeVideo:
927 INFO( "Incoming video call!");
928 break;
929 }
930
931}
932void callback_recv_ringing ( void *_arg )
933{
934 INFO ( "Ringing!" );
935}
936void callback_recv_starting ( void *_arg )
937{
938 if ( 0 != phone_startmedia_loop(_arg) ) {
939 INFO("Starting call failed!");
940 } else {
941 INFO ("Call started! ( press h to hangup )");
942 }
943
944}
945void callback_recv_ending ( void *_arg )
946{
947 INFO ( "Call ended!" );
948 _phone->running_encaud = 0;
949 _phone->running_decaud = 0;
950 _phone->running_encvid = 0;
951 _phone->running_decvid = 0;
952
953 /* Wait until all threads are done */
954 usleep(100000);
955
956 INFO ( "Call ended!" );
957}
958
959void callback_recv_error ( void *_arg )
960{
961 /*MSISession* _session = _arg;
962
963 INFO( "Error: %s", _session->last_error_str ); */
964}
965
966void callback_call_started ( void *_arg )
967{
968 if ( 0 != phone_startmedia_loop(_arg) ) {
969 INFO("Starting call failed!");
970 } else {
971 INFO ("Call started! ( press h to hangup )");
972 }
973
974}
975void callback_call_canceled ( void *_arg )
976{
977 INFO ( "Call canceled!" );
978}
979void callback_call_rejected ( void *_arg )
980{
981 INFO ( "Call rejected!" );
982}
983void callback_call_ended ( void *_arg )
984{
985 _phone->running_encaud = 0;
986 _phone->running_decaud = 0;
987 _phone->running_encvid = 0;
988 _phone->running_decvid = 0;
989
990 /* Wait until all threads are done
991
992 while ( _phone->running_encaud != -1 ||
993 _phone->running_decaud != -1 ||
994 _phone->running_encvid != -1 ||
995 _phone->running_decvid != -1 )
996
997 usleep(1000000);*/
998
999 while (_phone->running_decaud != -1) usleep(1000000);
1000
1001 toxav_kill_transmission(_phone->av);
1002 INFO ( "Call ended!" );
1003}
1004
1005void callback_requ_timeout ( void *_arg )
1006{
1007 INFO( "No answer! " );
1008}
1009
1010av_session_t *av_init_session()
1011{
1012 av_session_t *_retu = malloc(sizeof(av_session_t));
1013
1014 /* Initialize our mutex */
1015 pthread_mutex_init ( &_retu->_mutex, NULL );
1016
1017 _retu->_messenger = tox_new(1);
1018
1019 if ( !_retu->_messenger ) {
1020 fprintf ( stderr, "tox_new() failed!\n" );
1021 return NULL;
1022 }
1023
1024 _retu->_friends = NULL;
1025
1026
1027 const ALchar *_device_list = alcGetString(NULL, ALC_CAPTURE_DEVICE_SPECIFIER);
1028 int i = 0;
1029 const ALchar *device_names[20];
1030
1031 if ( _device_list ) {
1032 INFO("\nAvailable Capture Devices are:");
1033
1034 while (*_device_list ) {
1035 device_names[i] = _device_list;
1036 INFO("%d) %s", i, device_names[i]);
1037 _device_list += strlen( _device_list ) + 1;
1038 ++i;
1039 }
1040 }
1041
1042 INFO("Enter capture device number");
1043
1044 char dev[2];
1045 char *left;
1046 char *warned_ = fgets(dev, 2, stdin);
1047 (void)warned_;
1048 long selection = strtol(dev, &left, 10);
1049
1050 if ( *left ) {
1051 printf("'%s' is not a number!", dev);
1052 fflush(stdout);
1053 exit(EXIT_FAILURE);
1054 } else {
1055 INFO("Selected: %d ( %s )", selection, device_names[selection]);
1056 }
1057
1058 _retu->audio_capture_device =
1059 (struct ALCdevice *)alcCaptureOpenDevice(
1060 device_names[selection], av_DefaultSettings.audio_sample_rate, AL_FORMAT_MONO16, AUDIO_FRAME_SIZE * 4);
1061
1062
1063 if (alcGetError((ALCdevice *)_retu->audio_capture_device) != AL_NO_ERROR) {
1064 printf("Could not start capture device! %d\n", alcGetError((ALCdevice *)_retu->audio_capture_device));
1065 return 0;
1066 }
1067
1068 uint16_t height = 0, width = 0;
1069#ifdef TOX_FFMPEG
1070 avdevice_register_all();
1071 avcodec_register_all();
1072 av_register_all();
1073
1074 _retu->video_input_format = av_find_input_format(VIDEO_DRIVER);
1075
1076 if (avformat_open_input(&_retu->video_format_ctx, DEFAULT_WEBCAM, _retu->video_input_format, NULL) != 0) {
1077 fprintf(stderr, "Opening video_input_format failed!\n");
1078 //return -1;
1079 goto failed_init_ffmpeg;
1080 }
1081
1082 avformat_find_stream_info(_retu->video_format_ctx, NULL);
1083 av_dump_format(_retu->video_format_ctx, 0, DEFAULT_WEBCAM, 0);
1084
1085 for (i = 0; i < _retu->video_format_ctx->nb_streams; ++i) {
1086 if (_retu->video_format_ctx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
1087 _retu->video_stream = i;
1088 break;
1089 }
1090 }
1091
1092 _retu->webcam_decoder_ctx = _retu->video_format_ctx->streams[_retu->video_stream]->codec;
1093 _retu->webcam_decoder = avcodec_find_decoder(_retu->webcam_decoder_ctx->codec_id);
1094
1095 if (_retu->webcam_decoder == NULL) {
1096 fprintf(stderr, "Unsupported codec!\n");
1097 //return -1;
1098 goto failed_init_ffmpeg;
1099 }
1100
1101 if (_retu->webcam_decoder_ctx == NULL) {
1102 fprintf(stderr, "Init webcam_decoder_ctx failed!\n");
1103 //return -1;
1104 goto failed_init_ffmpeg;
1105 }
1106
1107 if (avcodec_open2(_retu->webcam_decoder_ctx, _retu->webcam_decoder, NULL) < 0) {
1108 fprintf(stderr, "Opening webcam decoder failed!\n");
1109 //return -1;
1110 goto failed_init_ffmpeg;
1111 }
1112
1113 width = _retu->webcam_decoder_ctx->width;
1114 height = _retu->webcam_decoder_ctx->height;
1115
1116failed_init_ffmpeg: ;
1117#endif
1118 uint8_t _byte_address[TOX_FRIEND_ADDRESS_SIZE];
1119 tox_get_address(_retu->_messenger, _byte_address );
1120 fraddr_to_str( _byte_address, _retu->_my_public_id );
1121
1122 ToxAvCodecSettings cs = av_DefaultSettings;
1123 cs.video_height = height;
1124 cs.video_width = width;
1125 _retu->av = toxav_new(_retu->_messenger, &cs);
1126
1127 /* ------------------ */
1128
1129 toxav_register_callstate_callback(callback_call_started, av_OnStart, _retu->av);
1130 toxav_register_callstate_callback(callback_call_canceled, av_OnCancel, _retu->av);
1131 toxav_register_callstate_callback(callback_call_rejected, av_OnReject, _retu->av);
1132 toxav_register_callstate_callback(callback_call_ended, av_OnEnd, _retu->av);
1133 toxav_register_callstate_callback(callback_recv_invite, av_OnInvite, _retu->av);
1134
1135 toxav_register_callstate_callback(callback_recv_ringing, av_OnRinging, _retu->av);
1136 toxav_register_callstate_callback(callback_recv_starting, av_OnStarting, _retu->av);
1137 toxav_register_callstate_callback(callback_recv_ending, av_OnEnding, _retu->av);
1138
1139 toxav_register_callstate_callback(callback_recv_error, av_OnError, _retu->av);
1140 toxav_register_callstate_callback(callback_requ_timeout, av_OnRequestTimeout, _retu->av);
1141
1142 /* ------------------ */
1143
1144 return _retu;
1145}
1146
1147int av_terminate_session(av_session_t *_phone)
1148{
1149 _phone->running_decaud = 0;
1150 usleep(100000); /* Wait for tox_poll to end */
1151
1152 toxav_kill(_phone->av);
1153 printf("\r[i] KILLED AV ARGH!\n");
1154
1155 usleep(1000000); /* Wait for cancel request to be sent */
1156 Tox *_p = _phone->_messenger;
1157 _phone->_messenger = NULL;
1158 tox_kill(_p);
1159
1160
1161 free(_phone->_friends);
1162 pthread_mutex_destroy ( &_phone->_mutex );
1163
1164 free(_phone);
1165
1166 printf("\r[i] Quit!\n");
1167 return 0;
1168}
1169
1170/****** AV HELPER FUNCTIONS ******/
1171
1172/* Auto accept friend request */
1173void av_friend_requ(Tox *_messenger, uint8_t *_public_key, uint8_t *_data, uint16_t _length, void *_userdata)
1174{
1175 av_session_t *_phone = _userdata;
1176 av_allocate_friend (_phone, -1, 0);
1177
1178 INFO("Got friend request with message: %s", _data);
1179
1180 tox_add_friend_norequest(_phone->_messenger, _public_key);
1181
1182 INFO("Auto-accepted! Friend id: %d", _phone->_friends->_id );
1183}
1184
1185void av_friend_active(Tox *_messenger, int _friendnumber, uint8_t *_string, uint16_t _length, void *_userdata)
1186{
1187 av_session_t *_phone = _userdata;
1188 INFO("Friend no. %d is online", _friendnumber);
1189
1190 av_friend_t *_this_friend = av_get_friend(_phone, _friendnumber);
1191
1192 if ( !_this_friend ) {
1193 INFO("But it's not registered!");
1194 return;
1195 }
1196
1197 (*_this_friend)._active = 1;
1198}
1199
1200int av_add_friend(av_session_t *_phone, char *_friend_hash)
1201{
1202 trim_spaces(_friend_hash);
1203
1204 unsigned char *_bin_string = hex_string_to_bin(_friend_hash);
1205 int _number = tox_add_friend(_phone->_messenger, _bin_string, (uint8_t *)"Tox phone "_USERAGENT,
1206 sizeof("Tox phone "_USERAGENT));
1207 free(_bin_string);
1208
1209 if ( _number >= 0) {
1210 INFO("Added friend as %d", _number );
1211 av_allocate_friend(_phone, _number, 0);
1212 } else
1213 INFO("Unknown error %i", _number );
1214
1215 return _number;
1216}
1217
1218int av_connect_to_dht(av_session_t *_phone, char *_dht_key, const char *_dht_addr, unsigned short _dht_port)
1219{
1220 unsigned char *_binary_string = hex_string_to_bin(_dht_key);
1221
1222 uint16_t _port = htons(_dht_port);
1223
1224 int _if = tox_bootstrap_from_address(_phone->_messenger, _dht_addr, 1, _port, _binary_string );
1225
1226 free(_binary_string);
1227
1228 return _if ? 0 : -1;
1229}
1230
1231/*********************************/
1232
1233void do_phone ( av_session_t *_phone )
1234{
1235 INFO("Welcome to tox_phone version: " _USERAGENT "\n"
1236 "Usage: \n"
1237 "f [pubkey] (add friend)\n"
1238 "c [a/v] (type) [friend] (friend id) (calls friend if online)\n"
1239 "h (if call is active hang up)\n"
1240 "a [a/v] (answer incoming call: a - audio / v - audio + video (audio is default))\n"
1241 "r (reject incoming call)\n"
1242 "q (quit)\n"
1243 "================================================================================"
1244 );
1245
1246 while ( 1 ) {
1247 char _line [ 1500 ];
1248 int _len;
1249
1250 if ( -1 == getinput(_line, 1500, &_len) ) {
1251 printf(" >> ");
1252 fflush(stdout);
1253 continue;
1254 }
1255
1256 if ( _len > 1 && _line[1] != ' ' && _line[1] != '\n' ) {
1257 INFO("Invalid input!");
1258 continue;
1259 }
1260
1261 switch (_line[0]) {
1262
1263 case 'f': {
1264 char _id [128];
1265 strncpy(_id, _line + 2, 128);
1266
1267 av_add_friend(_phone, _id);
1268
1269 }
1270 break;
1271
1272 case 'c': {
1273 ToxAvCallType _ctype;
1274
1275 if ( _len < 5 ) {
1276 INFO("Invalid input; usage: c a/v [friend]");
1277 break;
1278 } else if ( _line[2] == 'a' || _line[2] != 'v' ) { /* default and audio */
1279 _ctype = TypeAudio;
1280 } else { /* video */
1281 _ctype = TypeVideo;
1282 }
1283
1284 char *_end;
1285 int _friend = strtol(_line + 4, &_end, 10);
1286
1287 if ( *_end ) {
1288 INFO("Friend num has to be numerical value");
1289 break;
1290 }
1291
1292 if ( toxav_call(_phone->av, _friend, _ctype, 30) == ErrorAlreadyInCall ) {
1293 INFO("Already in a call");
1294 break;
1295 } else INFO("Calling friend: %d!", _friend);
1296
1297 }
1298 break;
1299
1300 case 'h': {
1301 if ( toxav_hangup(_phone->av) == ErrorNoCall ) {
1302 INFO("No call!");
1303 break;
1304 } else INFO("Hung up...");
1305
1306 }
1307 break;
1308
1309 case 'a': {
1310 ToxAvError rc;
1311
1312 if ( _len > 1 && _line[2] == 'v' ) {
1313 rc = toxav_answer(_phone->av, TypeVideo);
1314 } else
1315 rc = toxav_answer(_phone->av, TypeAudio);
1316
1317 if ( rc == ErrorInvalidState ) {
1318 INFO("No call to answer!");
1319 }
1320
1321 }
1322 break;
1323
1324 case 'r': {
1325 if ( toxav_reject(_phone->av, "User action") == ErrorInvalidState )
1326 INFO("No state to cancel!");
1327 else INFO("Call Rejected...");
1328
1329 }
1330 break;
1331
1332 case 'q': {
1333 INFO("Quitting!");
1334 return;
1335 }
1336
1337 case '\n': {
1338 }
1339
1340 default: {
1341 } break;
1342
1343 }
1344
1345 }
1346}
1347
1348void *tox_poll (void *_messenger_p)
1349{
1350 Tox **_messenger = _messenger_p;
1351
1352 while ( *_messenger ) {
1353 tox_do(*_messenger);
1354 usleep(10000);
1355 }
1356
1357 pthread_exit(NULL);
1358}
1359
1360int av_wait_dht(av_session_t *_phone, int _wait_seconds, const char *_ip, char *_key, unsigned short _port)
1361{
1362 if ( !_wait_seconds )
1363 return -1;
1364
1365 int _waited = 0;
1366
1367 while ( !tox_isconnected(_phone->_messenger) ) {
1368
1369 if ( -1 == av_connect_to_dht(_phone, _key, _ip, _port) ) {
1370 INFO("Could not connect to: %s", _ip);
1371 av_terminate_session(_phone);
1372 return -1;
1373 }
1374
1375 if ( _waited >= _wait_seconds ) return 0;
1376
1377 printf(".");
1378 fflush(stdout);
1379
1380 _waited ++;
1381 usleep(1000000);
1382 }
1383
1384 int _r = _wait_seconds - _waited;
1385 return _r ? _r : 1;
1386}
1387/* ---------------------- */
1388
1389int print_help ( const char *_name )
1390{
1391 printf ( "Usage: %s [IP] [PORT] [KEY]\n"
1392 "\t[IP] (DHT ip)\n"
1393 "\t[PORT] (DHT port)\n"
1394 "\t[KEY] (DHT public key)\n"
1395 "P.S. Friends and key are stored in ./tox_phone.conf\n"
1396 , _name );
1397 return 1;
1398}
1399
1400int main ( int argc, char *argv [] )
1401{
1402 if ( argc < 1 || argc < 4 )
1403 return print_help(argv[0]);
1404
1405 char *_convertable;
1406
1407
1408 const char *_ip = argv[1];
1409 char *_key = argv[3];
1410 unsigned short _port = strtol(argv[2], &_convertable, 10);
1411
1412 if ( *_convertable ) {
1413 printf("Invalid port: cannot convert string to long: %s", _convertable);
1414 return 1;
1415 }
1416
1417 _phone = av_init_session();
1418
1419 assert ( _phone );
1420
1421 tox_callback_friend_request(_phone->_messenger, av_friend_requ, _phone);
1422 tox_callback_status_message(_phone->_messenger, av_friend_active, _phone);
1423
1424
1425 INFO("\r================================================================================\n"
1426 "[!] Trying dht@%s:%d"
1427 , _ip, _port);
1428
1429 /* Start tox protocol */
1430 event.rise( tox_poll, &_phone->_messenger );
1431
1432 /* Just clean one line */
1433 printf("\r \r");
1434 fflush(stdout);
1435
1436 int _r;
1437 int _wait_seconds = 5;
1438
1439 for ( _r = 0; _r == 0; _r = av_wait_dht(_phone, _wait_seconds, _ip, _key, _port) ) _wait_seconds --;
1440
1441
1442 if ( -1 == _r ) {
1443 INFO("Error while connecting to dht: %s:%d", _ip, _port);
1444 av_terminate_session(_phone);
1445 return 1;
1446 }
1447
1448 INFO("CONNECTED!\n"
1449 "================================================================================\n"
1450 "%s\n"
1451 "================================================================================"
1452 , trim_spaces(_phone->_my_public_id) );
1453
1454
1455 do_phone (_phone);
1456
1457 av_terminate_session(_phone);
1458
1459 return 0;
1460}
diff --git a/toxav/rtp.c b/toxav/rtp.c
index b52840c1..a404202b 100755
--- a/toxav/rtp.c
+++ b/toxav/rtp.c
@@ -25,6 +25,8 @@
25#include "config.h" 25#include "config.h"
26#endif /* HAVE_CONFIG_H */ 26#endif /* HAVE_CONFIG_H */
27 27
28#include "../toxcore/logger.h"
29
28#include "rtp.h" 30#include "rtp.h"
29#include <assert.h> 31#include <assert.h>
30#include <stdlib.h> 32#include <stdlib.h>
@@ -227,6 +229,7 @@ static const uint32_t payload_table[] = {
227RTPHeader *extract_header ( const uint8_t *payload, int length ) 229RTPHeader *extract_header ( const uint8_t *payload, int length )
228{ 230{
229 if ( !payload || !length ) { 231 if ( !payload || !length ) {
232 LOGGER_WARNING("No payload to extract!");
230 return NULL; 233 return NULL;
231 } 234 }
232 235
@@ -245,6 +248,7 @@ RTPHeader *extract_header ( const uint8_t *payload, int length )
245 248
246 if ( GET_FLAG_VERSION(_retu) != RTP_VERSION ) { 249 if ( GET_FLAG_VERSION(_retu) != RTP_VERSION ) {
247 /* Deallocate */ 250 /* Deallocate */
251 LOGGER_WARNING("Invalid version!");
248 free(_retu); 252 free(_retu);
249 return NULL; 253 return NULL;
250 } 254 }
@@ -258,6 +262,7 @@ RTPHeader *extract_header ( const uint8_t *payload, int length )
258 262
259 if ( length < _length ) { 263 if ( length < _length ) {
260 /* Deallocate */ 264 /* Deallocate */
265 LOGGER_WARNING("Length invalid!");
261 free(_retu); 266 free(_retu);
262 return NULL; 267 return NULL;
263 } 268 }
@@ -304,6 +309,7 @@ RTPExtHeader *extract_ext_header ( const uint8_t *payload, uint16_t length )
304 309
305 310
306 if ( length < ( _ext_length * sizeof(uint32_t) ) ) { 311 if ( length < ( _ext_length * sizeof(uint32_t) ) ) {
312 LOGGER_WARNING("Length invalid!");
307 free(_retu); 313 free(_retu);
308 return NULL; 314 return NULL;
309 } 315 }
@@ -443,6 +449,7 @@ RTPMessage *msg_parse ( uint16_t sequnum, const uint8_t *data, int length )
443 _retu->header = extract_header ( data, length ); /* It allocates memory and all */ 449 _retu->header = extract_header ( data, length ); /* It allocates memory and all */
444 450
445 if ( !_retu->header ) { 451 if ( !_retu->header ) {
452 LOGGER_WARNING("Header failed to extract!");
446 free(_retu); 453 free(_retu);
447 return NULL; 454 return NULL;
448 } 455 }
@@ -461,6 +468,7 @@ RTPMessage *msg_parse ( uint16_t sequnum, const uint8_t *data, int length )
461 _retu->length -= ( 4 /* Minimum ext header len */ + _retu->ext_header->length * size_32 ); 468 _retu->length -= ( 4 /* Minimum ext header len */ + _retu->ext_header->length * size_32 );
462 _from_pos += ( 4 /* Minimum ext header len */ + _retu->ext_header->length * size_32 ); 469 _from_pos += ( 4 /* Minimum ext header len */ + _retu->ext_header->length * size_32 );
463 } else { /* Error */ 470 } else { /* Error */
471 LOGGER_WARNING("Ext Header failed to extract!");
464 rtp_free_msg(NULL, _retu); 472 rtp_free_msg(NULL, _retu);
465 return NULL; 473 return NULL;
466 } 474 }
@@ -471,6 +479,7 @@ RTPMessage *msg_parse ( uint16_t sequnum, const uint8_t *data, int length )
471 if ( length - _from_pos <= MAX_RTP_SIZE ) 479 if ( length - _from_pos <= MAX_RTP_SIZE )
472 memcpy ( _retu->data, data + _from_pos, length - _from_pos ); 480 memcpy ( _retu->data, data + _from_pos, length - _from_pos );
473 else { 481 else {
482 LOGGER_WARNING("Invalid length!");
474 rtp_free_msg(NULL, _retu); 483 rtp_free_msg(NULL, _retu);
475 return NULL; 484 return NULL;
476 } 485 }
@@ -495,9 +504,16 @@ int rtp_handle_packet ( void *object, IP_Port ip_port, uint8_t *data, uint32_t l
495{ 504{
496 RTPSession *_session = object; 505 RTPSession *_session = object;
497 RTPMessage *_msg; 506 RTPMessage *_msg;
498 507
499 if ( !_session || length < 13 + crypto_secretbox_MACBYTES) /* 12 is the minimum length for rtp + desc. byte */ 508 if ( !_session || length < 13 + crypto_secretbox_MACBYTES) { /* 12 is the minimum length for rtp + desc. byte */
509 LOGGER_WARNING("No session or invalid length of received buffer!");
510 return -1;
511 }
512
513 if ( _session->queue_limit <= _session->queue_size ) {
514 LOGGER_WARNING("Queue limit reached!");
500 return -1; 515 return -1;
516 }
501 517
502 uint8_t _plain[MAX_UDP_PACKET_SIZE]; 518 uint8_t _plain[MAX_UDP_PACKET_SIZE];
503 519
@@ -510,8 +526,7 @@ int rtp_handle_packet ( void *object, IP_Port ip_port, uint8_t *data, uint32_t l
510 increase_nonce ( _calculated, _sequnum ); 526 increase_nonce ( _calculated, _sequnum );
511 527
512 /* Decrypt message */ 528 /* Decrypt message */
513 int _decrypted_length = decrypt_data_symmetric( 529 int _decrypted_length = decrypt_data_symmetric((uint8_t *)_session->decrypt_key, _calculated, data + 3, length - 3, _plain );
514 (uint8_t *)_session->decrypt_key, _calculated, data + 3, length - 3, _plain );
515 530
516 /* This packet is either not encrypted properly or late 531 /* This packet is either not encrypted properly or late
517 */ 532 */
@@ -524,7 +539,10 @@ int rtp_handle_packet ( void *object, IP_Port ip_port, uint8_t *data, uint32_t l
524 _decrypted_length = decrypt_data_symmetric( 539 _decrypted_length = decrypt_data_symmetric(
525 (uint8_t *)_session->decrypt_key, _session->nonce_cycle, data + 3, length - 3, _plain ); 540 (uint8_t *)_session->decrypt_key, _session->nonce_cycle, data + 3, length - 3, _plain );
526 541
527 if ( _decrypted_length == -1 ) return -1; /* This packet is not encrypted properly */ 542 if ( _decrypted_length == -1 ) {
543 LOGGER_WARNING("Packet not ecrypted properly!");
544 return -1; /* This packet is not encrypted properly */
545 }
528 546
529 /* Otherwise, if decryption is ok with new cycle, set new cycle 547 /* Otherwise, if decryption is ok with new cycle, set new cycle
530 */ 548 */
@@ -533,7 +551,10 @@ int rtp_handle_packet ( void *object, IP_Port ip_port, uint8_t *data, uint32_t l
533 _decrypted_length = decrypt_data_symmetric( 551 _decrypted_length = decrypt_data_symmetric(
534 (uint8_t *)_session->decrypt_key, _calculated, data + 3, length - 3, _plain ); 552 (uint8_t *)_session->decrypt_key, _calculated, data + 3, length - 3, _plain );
535 553
536 if ( _decrypted_length == -1 ) return -1; /* This is just an error */ 554 if ( _decrypted_length == -1 ) {
555 LOGGER_WARNING("Error decrypting!");
556 return -1; /* This is just an error */
557 }
537 558
538 /* A new cycle setting. */ 559 /* A new cycle setting. */
539 memcpy(_session->nonce_cycle, _session->decrypt_nonce, crypto_secretbox_NONCEBYTES); 560 memcpy(_session->nonce_cycle, _session->decrypt_nonce, crypto_secretbox_NONCEBYTES);
@@ -543,7 +564,10 @@ int rtp_handle_packet ( void *object, IP_Port ip_port, uint8_t *data, uint32_t l
543 564
544 _msg = msg_parse ( _sequnum, _plain, _decrypted_length ); 565 _msg = msg_parse ( _sequnum, _plain, _decrypted_length );
545 566
546 if ( !_msg ) return -1; 567 if ( !_msg ) {
568 LOGGER_WARNING("Could not parse message!");
569 return -1;
570 }
547 571
548 /* Hopefully this goes well 572 /* Hopefully this goes well
549 * NOTE: Is this even used? 573 * NOTE: Is this even used?
@@ -565,6 +589,8 @@ int rtp_handle_packet ( void *object, IP_Port ip_port, uint8_t *data, uint32_t l
565 _session->last_msg = _session->oldest_msg = _msg; 589 _session->last_msg = _session->oldest_msg = _msg;
566 } 590 }
567 591
592 _session->queue_size++;
593
568 pthread_mutex_unlock(&_session->mutex); 594 pthread_mutex_unlock(&_session->mutex);
569 595
570 return 0; 596 return 0;
@@ -584,8 +610,10 @@ int rtp_handle_packet ( void *object, IP_Port ip_port, uint8_t *data, uint32_t l
584 */ 610 */
585RTPMessage *rtp_new_message ( RTPSession *session, const uint8_t *data, uint32_t length ) 611RTPMessage *rtp_new_message ( RTPSession *session, const uint8_t *data, uint32_t length )
586{ 612{
587 if ( !session ) 613 if ( !session ) {
614 LOGGER_WARNING("No session!");
588 return NULL; 615 return NULL;
616 }
589 617
590 uint8_t *_from_pos; 618 uint8_t *_from_pos;
591 RTPMessage *_retu = calloc(1, sizeof (RTPMessage)); 619 RTPMessage *_retu = calloc(1, sizeof (RTPMessage));
@@ -665,6 +693,7 @@ RTPMessage *rtp_new_message ( RTPSession *session, const uint8_t *data, uint32_t
665int rtp_release_session_recv ( RTPSession *session ) 693int rtp_release_session_recv ( RTPSession *session )
666{ 694{
667 if ( !session ) { 695 if ( !session ) {
696 LOGGER_WARNING("No session!");
668 return -1; 697 return -1;
669 } 698 }
670 699
@@ -678,7 +707,8 @@ int rtp_release_session_recv ( RTPSession *session )
678 } 707 }
679 708
680 session->last_msg = session->oldest_msg = NULL; 709 session->last_msg = session->oldest_msg = NULL;
681 710 session->queue_size = 0;
711
682 pthread_mutex_unlock(&session->mutex); 712 pthread_mutex_unlock(&session->mutex);
683 713
684 return 0; 714 return 0;
@@ -686,6 +716,31 @@ int rtp_release_session_recv ( RTPSession *session )
686 716
687 717
688/** 718/**
719 * @brief Call this to change queue limit
720 *
721 * @param session The session
722 * @param limit new limit
723 * @return void
724 */
725void rtp_queue_adjust_limit(RTPSession* session, uint64_t limit)
726{
727 RTPMessage *_tmp, * _it;
728 pthread_mutex_lock(&session->mutex);
729
730 for ( _it = session->oldest_msg; session->queue_size > limit; _it = _tmp ) {
731 _tmp = _it->next;
732 rtp_free_msg( session, _it);
733 session->queue_size --;
734 }
735
736 session->oldest_msg = _it;
737 session->queue_limit = limit;
738
739 pthread_mutex_unlock(&session->mutex);
740}
741
742
743/**
689 * @brief Gets oldest message in the list. 744 * @brief Gets oldest message in the list.
690 * 745 *
691 * @param session Where the list is. 746 * @param session Where the list is.
@@ -694,15 +749,21 @@ int rtp_release_session_recv ( RTPSession *session )
694 */ 749 */
695RTPMessage *rtp_recv_msg ( RTPSession *session ) 750RTPMessage *rtp_recv_msg ( RTPSession *session )
696{ 751{
697 if ( !session ) 752 if ( !session ) {
753 LOGGER_WARNING("No session!");
698 return NULL; 754 return NULL;
699 755 }
700 RTPMessage *_retu = session->oldest_msg; 756
701 757 if ( session->queue_size == 0 ) {
758 return NULL;
759 }
760
702 pthread_mutex_lock(&session->mutex); 761 pthread_mutex_lock(&session->mutex);
762
763 RTPMessage *_retu = session->oldest_msg;
703 764
704 if ( _retu ) 765 /*if (_retu)*/
705 session->oldest_msg = _retu->next; 766 session->oldest_msg = _retu->next;
706 767
707 if ( !session->oldest_msg ) 768 if ( !session->oldest_msg )
708 session->last_msg = NULL; 769 session->last_msg = NULL;
@@ -728,7 +789,10 @@ int rtp_send_msg ( RTPSession *session, Messenger *messenger, const uint8_t *dat
728{ 789{
729 RTPMessage *msg = rtp_new_message (session, data, length); 790 RTPMessage *msg = rtp_new_message (session, data, length);
730 791
731 if ( !msg ) return -1; 792 if ( !msg ) {
793 LOGGER_WARNING("No session!");
794 return -1;
795 }
732 796
733 uint8_t _send_data [ MAX_UDP_PACKET_SIZE ]; 797 uint8_t _send_data [ MAX_UDP_PACKET_SIZE ];
734 798
@@ -749,9 +813,8 @@ int rtp_send_msg ( RTPSession *session, Messenger *messenger, const uint8_t *dat
749 _send_data[2] = msg->data[1]; 813 _send_data[2] = msg->data[1];
750 814
751 815
752 /*if ( full_length != sendpacket ( messenger->net, *((IP_Port*) &session->dest), _send_data, full_length) ) {*/
753 if ( full_length != send_custom_user_packet(messenger, session->dest, _send_data, full_length) ) { 816 if ( full_length != send_custom_user_packet(messenger, session->dest, _send_data, full_length) ) {
754 /*fprintf(stderr, "Rtp error: %s\n", strerror(errno));*/ 817 LOGGER_WARNING("Failed to send full packet! std error: %s", strerror(errno));
755 rtp_free_msg ( session, msg ); 818 rtp_free_msg ( session, msg );
756 return -1; 819 return -1;
757 } 820 }
@@ -822,9 +885,10 @@ RTPSession *rtp_init_session ( int payload_type,
822 RTPSession *_retu = calloc(1, sizeof(RTPSession)); 885 RTPSession *_retu = calloc(1, sizeof(RTPSession));
823 assert(_retu); 886 assert(_retu);
824 887
825 /*networking_registerhandler(messenger->net, payload_type, rtp_handle_packet, _retu);*/ 888 if ( -1 == custom_user_packet_registerhandler(messenger, friend_num, payload_type, rtp_handle_packet, _retu) ||
826 if ( -1 == custom_user_packet_registerhandler(messenger, friend_num, payload_type, rtp_handle_packet, _retu) ) { 889 !encrypt_key, !decrypt_key, !encrypt_nonce, !decrypt_nonce
827 /*fprintf(stderr, "Error setting custom register handler for rtp session\n");*/ 890 ) {
891 LOGGER_ERROR("Error setting custom register handler for rtp session");
828 free(_retu); 892 free(_retu);
829 return NULL; 893 return NULL;
830 } 894 }
@@ -843,9 +907,7 @@ RTPSession *rtp_init_session ( int payload_type,
843 _retu->rsequnum = _retu->sequnum = 1; 907 _retu->rsequnum = _retu->sequnum = 1;
844 908
845 _retu->ext_header = NULL; /* When needed allocate */ 909 _retu->ext_header = NULL; /* When needed allocate */
846 _retu->framerate = -1; 910
847 _retu->resolution = -1;
848
849 _retu->encrypt_key = encrypt_key; 911 _retu->encrypt_key = encrypt_key;
850 _retu->decrypt_key = decrypt_key; 912 _retu->decrypt_key = decrypt_key;
851 913
@@ -870,6 +932,8 @@ RTPSession *rtp_init_session ( int payload_type,
870 _retu->prefix = payload_type; 932 _retu->prefix = payload_type;
871 933
872 _retu->oldest_msg = _retu->last_msg = NULL; 934 _retu->oldest_msg = _retu->last_msg = NULL;
935 _retu->queue_limit = 100; /* Default */
936 _retu->queue_size = 0;
873 937
874 pthread_mutex_init(&_retu->mutex, NULL); 938 pthread_mutex_init(&_retu->mutex, NULL);
875 /* 939 /*
@@ -890,8 +954,10 @@ RTPSession *rtp_init_session ( int payload_type,
890 */ 954 */
891int rtp_terminate_session ( RTPSession *session, Messenger *messenger ) 955int rtp_terminate_session ( RTPSession *session, Messenger *messenger )
892{ 956{
893 if ( !session ) 957 if ( !session ) {
958 LOGGER_WARNING("No session!");
894 return -1; 959 return -1;
960 }
895 961
896 custom_user_packet_registerhandler(messenger, session->dest, session->prefix, NULL, NULL); 962 custom_user_packet_registerhandler(messenger, session->dest, session->prefix, NULL, NULL);
897 963
diff --git a/toxav/rtp.h b/toxav/rtp.h
index 58b16ab1..4d66e791 100755
--- a/toxav/rtp.h
+++ b/toxav/rtp.h
@@ -108,11 +108,7 @@ typedef struct _RTPSession {
108 */ 108 */
109 RTPExtHeader *ext_header; 109 RTPExtHeader *ext_header;
110 110
111 /* External header identifiers */ 111
112 int resolution;
113 int framerate;
114
115
116 /* Since these are only references of the 112 /* Since these are only references of the
117 * call structure don't allocate or free 113 * call structure don't allocate or free
118 */ 114 */
@@ -126,6 +122,9 @@ typedef struct _RTPSession {
126 122
127 RTPMessage *oldest_msg; 123 RTPMessage *oldest_msg;
128 RTPMessage *last_msg; /* tail */ 124 RTPMessage *last_msg; /* tail */
125
126 uint64_t queue_limit;/* Default 100; modify per thy liking */
127 uint64_t queue_size; /* currently holding << messages */
129 128
130 /* Msg prefix for core to know when recving */ 129 /* Msg prefix for core to know when recving */
131 uint8_t prefix; 130 uint8_t prefix;
@@ -148,6 +147,15 @@ int rtp_release_session_recv ( RTPSession *session );
148 147
149 148
150/** 149/**
150 * @brief Call this to change queue limit
151 *
152 * @param session The session
153 * @param limit new limit
154 * @return void
155 */
156void rtp_queue_adjust_limit ( RTPSession *session, uint64_t limit );
157
158/**
151 * @brief Get's oldest message in the list. 159 * @brief Get's oldest message in the list.
152 * 160 *
153 * @param session Where the list is. 161 * @param session Where the list is.
@@ -195,7 +203,7 @@ void rtp_free_msg ( RTPSession *session, RTPMessage *msg );
195 * @retval NULL Error occurred. 203 * @retval NULL Error occurred.
196 */ 204 */
197RTPSession *rtp_init_session ( int payload_type, 205RTPSession *rtp_init_session ( int payload_type,
198 Messenger *messenger, 206 Messenger *messenger,
199 int friend_num, 207 int friend_num,
200 const uint8_t *encrypt_key, 208 const uint8_t *encrypt_key,
201 const uint8_t *decrypt_key, 209 const uint8_t *decrypt_key,
diff --git a/toxav/toxav.c b/toxav/toxav.c
index f1ff2312..0301c6b2 100755
--- a/toxav/toxav.c
+++ b/toxav/toxav.c
@@ -105,7 +105,7 @@ ToxAv *toxav_new( Tox* messenger, ToxAvCodecSettings* codec_settings, uint32_t m
105 av->msi_session = msi_init_session(av->messenger, max_calls); 105 av->msi_session = msi_init_session(av->messenger, max_calls);
106 av->msi_session->agent_handler = av; 106 av->msi_session->agent_handler = av;
107 107
108 av->rtp_sessions = calloc(sizeof(RTPSession), max_calls); 108 av->rtp_sessions = calloc(sizeof(CallRTPSessions), max_calls);
109 av->max_calls = max_calls; 109 av->max_calls = max_calls;
110 110
111 av->j_buf = create_queue(codec_settings->jbuf_capacity); 111 av->j_buf = create_queue(codec_settings->jbuf_capacity);
@@ -288,8 +288,9 @@ int toxav_stop_call ( ToxAv* av, uint32_t call_index )
288 */ 288 */
289int toxav_prepare_transmission ( ToxAv* av, uint32_t call_index, int support_video ) 289int toxav_prepare_transmission ( ToxAv* av, uint32_t call_index, int support_video )
290{ 290{
291 if ( !av->msi_session || !av->msi_session->calls[call_index] ) { 291 if ( !av->msi_session || av->msi_session->max_calls <= call_index || !av->msi_session->calls[call_index] ) {
292 return ErrorNoCall; 292 /*fprintf(stderr, "Error while starting audio RTP session: invalid call!\n");*/
293 return ErrorInternal;
293 } 294 }
294 295
295 av->rtp_sessions[call_index].crtps[audio_index] = 296 av->rtp_sessions[call_index].crtps[audio_index] =
@@ -305,10 +306,11 @@ int toxav_prepare_transmission ( ToxAv* av, uint32_t call_index, int support_vid
305 306
306 307
307 if ( !av->rtp_sessions[call_index].crtps[audio_index] ) { 308 if ( !av->rtp_sessions[call_index].crtps[audio_index] ) {
308 fprintf(stderr, "Error while starting audio RTP session!\n"); 309 /*fprintf(stderr, "Error while starting audio RTP session!\n");*/
309 return ErrorStartingAudioRtp; 310 return ErrorStartingAudioRtp;
310 } 311 }
311 312
313
312 if ( support_video ) { 314 if ( support_video ) {
313 av->rtp_sessions[call_index].crtps[video_index] = 315 av->rtp_sessions[call_index].crtps[video_index] =
314 rtp_init_session ( 316 rtp_init_session (
@@ -323,10 +325,12 @@ int toxav_prepare_transmission ( ToxAv* av, uint32_t call_index, int support_vid
323 325
324 326
325 if ( !av->rtp_sessions[call_index].crtps[video_index] ) { 327 if ( !av->rtp_sessions[call_index].crtps[video_index] ) {
326 fprintf(stderr, "Error while starting video RTP session!\n"); 328 /*fprintf(stderr, "Error while starting video RTP session!\n");*/
327 return ErrorStartingVideoRtp; 329 return ErrorStartingVideoRtp;
328 } 330 }
329 } 331 }
332
333
330 return ErrorNone; 334 return ErrorNone;
331} 335}
332 336
@@ -341,12 +345,12 @@ int toxav_prepare_transmission ( ToxAv* av, uint32_t call_index, int support_vid
341int toxav_kill_transmission ( ToxAv *av, uint32_t call_index ) 345int toxav_kill_transmission ( ToxAv *av, uint32_t call_index )
342{ 346{
343 if ( av->rtp_sessions[call_index].crtps[audio_index] && -1 == rtp_terminate_session(av->rtp_sessions[call_index].crtps[audio_index], av->messenger) ) { 347 if ( av->rtp_sessions[call_index].crtps[audio_index] && -1 == rtp_terminate_session(av->rtp_sessions[call_index].crtps[audio_index], av->messenger) ) {
344 fprintf(stderr, "Error while terminating audio RTP session!\n"); 348 /*fprintf(stderr, "Error while terminating audio RTP session!\n");*/
345 return ErrorTerminatingAudioRtp; 349 return ErrorTerminatingAudioRtp;
346 } 350 }
347 351
348 if ( av->rtp_sessions[call_index].crtps[video_index] && -1 == rtp_terminate_session(av->rtp_sessions[call_index].crtps[video_index], av->messenger) ) { 352 if ( av->rtp_sessions[call_index].crtps[video_index] && -1 == rtp_terminate_session(av->rtp_sessions[call_index].crtps[video_index], av->messenger) ) {
349 fprintf(stderr, "Error while terminating video RTP session!\n"); 353 /*fprintf(stderr, "Error while terminating video RTP session!\n");*/
350 return ErrorTerminatingVideoRtp; 354 return ErrorTerminatingVideoRtp;
351 } 355 }
352 356
@@ -441,13 +445,15 @@ inline__ int toxav_recv_video ( ToxAv *av, uint32_t call_index, vpx_image_t **ou
441 445
442 uint8_t packet [RTP_PAYLOAD_SIZE]; 446 uint8_t packet [RTP_PAYLOAD_SIZE];
443 int recved_size = 0; 447 int recved_size = 0;
444 int error; 448 int rc;
445 449
446 do { 450 do {
447 recved_size = toxav_recv_rtp_payload(av, call_index, TypeVideo, packet); 451 recved_size = toxav_recv_rtp_payload(av, call_index, TypeVideo, packet);
448 452
449 if (recved_size > 0 && ( error = vpx_codec_decode(&av->cs->v_decoder, packet, recved_size, NULL, 0) ) != VPX_CODEC_OK) 453 if (recved_size > 0 && ( rc = vpx_codec_decode(&av->cs->v_decoder, packet, recved_size, NULL, 0) ) != VPX_CODEC_OK) {
450 fprintf(stderr, "Error decoding: %s\n", vpx_codec_err_to_string(error)); 454 /*fprintf(stderr, "Error decoding video: %s\n", vpx_codec_err_to_string(rc));*/
455 return ErrorInternal;
456 }
451 457
452 } while (recved_size > 0); 458 } while (recved_size > 0);
453 459
@@ -472,8 +478,9 @@ inline__ int toxav_recv_video ( ToxAv *av, uint32_t call_index, vpx_image_t **ou
472 */ 478 */
473inline__ int toxav_send_video ( ToxAv *av, uint32_t call_index, vpx_image_t *input) 479inline__ int toxav_send_video ( ToxAv *av, uint32_t call_index, vpx_image_t *input)
474{ 480{
475 if (vpx_codec_encode(&av->cs->v_encoder, input, av->cs->frame_counter, 1, 0, MAX_ENCODE_TIME_US) != VPX_CODEC_OK) { 481 int rc = vpx_codec_encode(&av->cs->v_encoder, input, av->cs->frame_counter, 1, 0, MAX_ENCODE_TIME_US);
476 fprintf(stderr, "Could not encode video frame\n"); 482 if ( rc != VPX_CODEC_OK) {
483 /*fprintf(stderr, "Could not encode video frame: %s\n", vpx_codec_err_to_string(rc));*/
477 return ErrorInternal; 484 return ErrorInternal;
478 } 485 }
479 486
@@ -491,11 +498,40 @@ inline__ int toxav_send_video ( ToxAv *av, uint32_t call_index, vpx_image_t *inp
491 } 498 }
492 499
493 if (sent > 0) 500 if (sent > 0)
494 return 0; 501 return ErrorNone;
495 502
496 return ErrorInternal; 503 return ErrorInternal;
497} 504}
498 505
506int toxav_prepare_video_frame(ToxAv* av, uint8_t* dest, int dest_max, vpx_image_t* input)
507{
508 int rc = vpx_codec_encode(&av->cs->v_encoder, input, av->cs->frame_counter, 1, 0, MAX_ENCODE_TIME_US);
509 if ( rc != VPX_CODEC_OK) {
510 /*fprintf(stderr, "Could not encode video frame: %s\n", vpx_codec_err_to_string(rc));*/
511 return ErrorInternal;
512 }
513 ++av->cs->frame_counter;
514
515 vpx_codec_iter_t iter = NULL;
516 const vpx_codec_cx_pkt_t *pkt;
517 int counted = 0, copied = 0;
518
519 while ( (pkt = vpx_codec_get_cx_data(&av->cs->v_encoder, &iter)) ) {
520 if (pkt->kind == VPX_CODEC_CX_FRAME_PKT) {
521
522 if ( copied + pkt->data.frame.sz > dest_max ) return ErrorPacketTooLarge;
523
524 mempcpy(dest + copied, pkt->data.frame.buf, pkt->data.frame.sz);
525
526 if (toxav_send_rtp_payload(av, call_index, TypeVideo, pkt->data.frame.buf, pkt->data.frame.sz) != -1)
527 ++counted;
528 }
529 }
530
531 if (counted > 0)
532 return ErrorNone;
533}
534
499/** 535/**
500 * @brief Receive decoded audio frame. 536 * @brief Receive decoded audio frame.
501 * 537 *
@@ -517,16 +553,22 @@ inline__ int toxav_recv_audio ( ToxAv *av, uint32_t call_index, int frame_size,
517 int recved_size = toxav_recv_rtp_payload(av, call_index, TypeAudio, packet); 553 int recved_size = toxav_recv_rtp_payload(av, call_index, TypeAudio, packet);
518 554
519 if ( recved_size == ErrorAudioPacketLost ) { 555 if ( recved_size == ErrorAudioPacketLost ) {
520 return opus_decode(av->cs->audio_decoder, NULL, 0, dest, frame_size, 1); 556 int dec_size = opus_decode(av->cs->audio_decoder, NULL, 0, dest, frame_size, 1);
557
558 if ( dec_size != OPUS_OK ) return ErrorInternal;
559
521 } else if ( recved_size ) { 560 } else if ( recved_size ) {
522 return opus_decode(av->cs->audio_decoder, packet, recved_size, dest, frame_size, 0); 561 int dec_size = opus_decode(av->cs->audio_decoder, packet, recved_size, dest, frame_size, 0);
562
563 if ( dec_size != OPUS_OK ) return ErrorInternal;
564
523 } else { 565 } else {
524 return 0; /* Nothing received */ 566 return 0; /* Nothing received */
525 } 567 }
526} 568}
527 569
528/** 570/**
529 * @brief Encode and send audio frame. 571 * @brief Send audio frame.
530 * 572 *
531 * @param av Handler. 573 * @param av Handler.
532 * @param frame The frame (raw 16 bit signed pcm with AUDIO_CHANNELS channels audio.) 574 * @param frame The frame (raw 16 bit signed pcm with AUDIO_CHANNELS channels audio.)
@@ -538,13 +580,29 @@ inline__ int toxav_recv_audio ( ToxAv *av, uint32_t call_index, int frame_size,
538 */ 580 */
539inline__ int toxav_send_audio ( ToxAv *av, uint32_t call_index, const int16_t *frame, int frame_size) 581inline__ int toxav_send_audio ( ToxAv *av, uint32_t call_index, const int16_t *frame, int frame_size)
540{ 582{
541 uint8_t temp_data[RTP_PAYLOAD_SIZE]; 583 return toxav_send_rtp_payload(av, call_index, TypeAudio, frame, frame_size);
542 int32_t ret = opus_encode(av->cs->audio_encoder, frame, frame_size, temp_data, sizeof(temp_data)); 584}
543 585
544 if (ret <= 0) 586/**
587 * @brief Encode audio frame
588 *
589 * @param av Handler
590 * @param dest dest
591 * @param dest_max Max dest size
592 * @param frame The frame
593 * @param frame_size The frame size
594 * @return int
595 * @retval ToxAvError On error.
596 * @retval >0 On success
597 */
598int toxav_prepare_audio_frame ( ToxAv* av, int16_t* dest, int dest_max, const int16_t* frame, int frame_size)
599{
600 int32_t rc = opus_encode(av->cs->audio_encoder, frame, frame_size, dest, dest_max);
601
602 if (rc <= 0)
545 return ErrorInternal; 603 return ErrorInternal;
546 604
547 return toxav_send_rtp_payload(av, call_index, TypeAudio, temp_data, ret); 605 return rc;
548} 606}
549 607
550/** 608/**
@@ -598,12 +656,27 @@ inline__ int toxav_capability_supported ( ToxAv* av, ToxAvCapabilities capabilit
598} 656}
599 657
600/** 658/**
601 * @brief Get messenger handle 659 * @brief Set queue limit
602 * 660 *
603 * @param av Handler. 661 * @param av Handler
604 * @return Tox* 662 * @param call_index index
663 * @param limit the limit
664 * @return void
665 */
666void toxav_set_audio_queue_limit(ToxAv* av, uint32_t call_index, uint64_t limit)
667{
668 rtp_queue_adjust_limit(av->rtp_sessions[call_index].crtps[audio_index], limit);
669}
670
671/**
672 * @brief Set queue limit
673 *
674 * @param av Handler
675 * @param call_index index
676 * @param limit the limit
677 * @return void
605 */ 678 */
606inline__ Tox* toxav_get_tox ( ToxAv* av ) 679void toxav_set_video_queue_limit(ToxAv* av, uint32_t call_index, uint64_t limit)
607{ 680{
608 return (Tox*)av->messenger; 681 rtp_queue_adjust_limit(av->rtp_sessions[call_index].crtps[video_index], limit);
609} 682}
diff --git a/toxav/toxav.h b/toxav/toxav.h
index 89addb2b..5a8e8f56 100755
--- a/toxav/toxav.h
+++ b/toxav/toxav.h
@@ -87,7 +87,8 @@ typedef enum {
87 ErrorStartingVideoRtp = -8 , /* Error in toxav_prepare_transmission() */ 87 ErrorStartingVideoRtp = -8 , /* Error in toxav_prepare_transmission() */
88 ErrorTerminatingAudioRtp = -9, /* Returned in toxav_kill_transmission() */ 88 ErrorTerminatingAudioRtp = -9, /* Returned in toxav_kill_transmission() */
89 ErrorTerminatingVideoRtp = -10, /* Returned in toxav_kill_transmission() */ 89 ErrorTerminatingVideoRtp = -10, /* Returned in toxav_kill_transmission() */
90 90 ErrorPacketTooLarge = -11, /* Buffer exceeds size while encoding */
91
91} ToxAvError; 92} ToxAvError;
92 93
93 94
@@ -276,7 +277,7 @@ int toxav_recv_audio( ToxAv* av, uint32_t call_index, int frame_size, int16_t* d
276int toxav_send_video ( ToxAv* av, uint32_t call_index, vpx_image_t* input); 277int toxav_send_video ( ToxAv* av, uint32_t call_index, vpx_image_t* input);
277 278
278/** 279/**
279 * @brief Encode and send audio frame. 280 * @brief Send audio frame.
280 * 281 *
281 * @param av Handler. 282 * @param av Handler.
282 * @param frame The frame (raw 16 bit signed pcm with AUDIO_CHANNELS channels audio.) 283 * @param frame The frame (raw 16 bit signed pcm with AUDIO_CHANNELS channels audio.)
@@ -288,6 +289,22 @@ int toxav_send_video ( ToxAv* av, uint32_t call_index, vpx_image_t* input);
288 */ 289 */
289int toxav_send_audio ( ToxAv* av, uint32_t call_index, const int16_t* frame, int frame_size); 290int toxav_send_audio ( ToxAv* av, uint32_t call_index, const int16_t* frame, int frame_size);
290 291
292int toxav_prepare_video_frame ( ToxAv* av, uint8_t* dest, int dest_max, vpx_image_t* input );
293
294/**
295 * @brief Encode audio frame
296 *
297 * @param av Handler
298 * @param dest dest
299 * @param dest_max Max dest size
300 * @param frame The frame
301 * @param frame_size The frame size
302 * @return int
303 * @retval ToxAvError On error.
304 * @retval >0 On success
305 */
306int toxav_prepare_audio_frame ( ToxAv* av, int16_t* dest, int dest_max, const int16_t* frame, int frame_size);
307
291/** 308/**
292 * @brief Get peer transmission type. It can either be audio or video. 309 * @brief Get peer transmission type. It can either be audio or video.
293 * 310 *
@@ -320,11 +337,23 @@ int toxav_get_peer_id ( ToxAv* av, uint32_t call_index, int peer );
320int toxav_capability_supported ( ToxAv* av, ToxAvCapabilities capability ); 337int toxav_capability_supported ( ToxAv* av, ToxAvCapabilities capability );
321 338
322/** 339/**
323 * @brief Get messenger handle 340 * @brief Set queue limit
324 * 341 *
325 * @param av Handler. 342 * @param av Handler
326 * @return Tox* 343 * @param call_index index
344 * @param limit the limit
345 * @return void
346 */
347void toxav_set_audio_queue_limit ( ToxAv* av, uint32_t call_index, uint64_t limit );
348
349/**
350 * @brief Set queue limit
351 *
352 * @param av Handler
353 * @param call_index index
354 * @param limit the limit
355 * @return void
327 */ 356 */
328Tox* toxav_get_tox ( ToxAv* av ); 357void toxav_set_video_queue_limit ( ToxAv* av, uint32_t call_index, uint64_t limit );
329 358
330#endif /* __TOXAV */ \ No newline at end of file 359#endif /* __TOXAV */ \ No newline at end of file