diff options
author | mannol <eniz_vukovic@hotmail.com> | 2014-05-03 01:46:03 +0200 |
---|---|---|
committer | mannol <eniz_vukovic@hotmail.com> | 2014-05-03 01:46:03 +0200 |
commit | 0fa03b924030c5791599451389ba84b81be84da8 (patch) | |
tree | 0d3b93baeb3c18b2f1afce5b9455c9b8bd21ec89 /toxav | |
parent | 42b25a4d3e2fe66f03cbd8c866d8af7bd4f6e5a7 (diff) |
Bunch of random changes
Diffstat (limited to 'toxav')
-rw-r--r-- | toxav/Makefile.inc | 41 | ||||
-rw-r--r-- | toxav/media.c | 95 | ||||
-rw-r--r-- | toxav/media.h | 15 | ||||
-rwxr-xr-x | toxav/msi.c | 34 | ||||
-rwxr-xr-x | toxav/phone.c | 1460 | ||||
-rwxr-xr-x | toxav/rtp.c | 116 | ||||
-rwxr-xr-x | toxav/rtp.h | 20 | ||||
-rwxr-xr-x | toxav/toxav.c | 127 | ||||
-rwxr-xr-x | toxav/toxav.h | 41 |
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 | ||
35 | endif | 35 | endif \ No newline at end of file |
36 | |||
37 | |||
38 | |||
39 | |||
40 | |||
41 | |||
42 | if BUILD_PHONE | ||
43 | |||
44 | |||
45 | noinst_PROGRAMS += phone | ||
46 | |||
47 | phone_SOURCES = ../toxav/phone.c | ||
48 | |||
49 | phone_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 | |||
59 | phone_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 | |||
74 | endif | ||
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 | ||
37 | struct 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 | ||
49 | int empty_queue(struct jitter_buffer *q) | 40 | int 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) |
83 | uint8_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 */ |
92 | RTPMessage *dequeue(struct jitter_buffer *q, int *success) | 76 | RTPMessage *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 | ||
142 | int queue(struct jitter_buffer *q, RTPMessage *pk) | 125 | void 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 | ||
196 | int init_video_decoder(CodecState *cs) | 173 | int 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) | |||
221 | int init_video_encoder(CodecState *cs, uint16_t width, uint16_t height, uint32_t video_bitrate) | 198 | int 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 | ||
244 | int init_audio_encoder(CodecState *cs, uint32_t audio_channels) | 222 | int 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 | |||
72 | struct 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 | |||
71 | struct jitter_buffer *create_queue(int capacity); | 84 | struct jitter_buffer *create_queue(int capacity); |
72 | 85 | ||
73 | int queue(struct jitter_buffer *q, RTPMessage *pk); | 86 | void queue(struct jitter_buffer *q, RTPMessage *pk); |
74 | RTPMessage *dequeue(struct jitter_buffer *q, int *success); | 87 | RTPMessage *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 **********/ |
1018 | int handle_recv_invite ( MSISession *session, MSICall* call, MSIMessage *msg ) | 1019 | int 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 | } |
1072 | int handle_recv_start ( MSISession *session, MSICall* call, MSIMessage *msg ) | 1073 | int 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 | } |
1096 | int handle_recv_reject ( MSISession *session, MSICall* call, MSIMessage *msg ) | 1097 | int 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 | } |
1119 | int handle_recv_cancel ( MSISession *session, MSICall* call, MSIMessage *msg ) | 1120 | int 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 | } |
1138 | int handle_recv_end ( MSISession *session, MSICall* call, MSIMessage *msg ) | 1139 | int 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 **********/ |
1157 | int handle_recv_ringing ( MSISession *session, MSICall* call, MSIMessage *msg ) | 1158 | int 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 | } |
1170 | int handle_recv_starting ( MSISession *session, MSICall* call, MSIMessage *msg ) | 1171 | int 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 | } |
1211 | int handle_recv_ending ( MSISession *session, MSICall* call, MSIMessage *msg ) | 1212 | int 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 | */ |
1508 | int msi_invite ( MSISession* session, uint32_t* call_index, MSICallType call_type, uint32_t rngsec, uint32_t friend_id ) | 1510 | int 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 | */ |
1554 | int msi_hangup ( MSISession* session, uint32_t call_index ) | 1556 | int 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 | */ |
1593 | int msi_answer ( MSISession* session, uint32_t call_index, MSICallType call_type ) | 1595 | int 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 | */ |
1642 | int msi_cancel ( MSISession *session, uint32_t call_index, uint32_t peer, const char *reason ) | 1644 | int 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 | */ |
1671 | int msi_reject ( MSISession *session, uint32_t call_index, const uint8_t *reason ) | 1673 | int 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 | */ |
1700 | int msi_stopcall ( MSISession *session, uint32_t call_index ) | 1702 | int 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 | |||
87 | struct SDL_Surface *screen; | ||
88 | |||
89 | typedef struct { | ||
90 | struct SDL_Overlay *bmp; | ||
91 | int width, height; | ||
92 | } VideoPicture; | ||
93 | |||
94 | |||
95 | typedef struct av_friend_s { | ||
96 | int _id; | ||
97 | int _active; /* 0=false; 1=true; */ | ||
98 | } av_friend_t; | ||
99 | |||
100 | typedef 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; | ||
131 | av_session_t *_phone; | ||
132 | |||
133 | void 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 | } | ||
152 | av_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 | |||
170 | void 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 | |||
181 | unsigned 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 | |||
193 | int 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 | |||
206 | char *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 | |||
232 | static 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 | /* | ||
272 | int 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 *//* | ||
286 | sws_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 | |||
289 | SDL_UnlockYUVOverlay(_phone->video_picture.bmp); | ||
290 | SDL_Rect rect; | ||
291 | rect.x = 0; | ||
292 | rect.y = 0; | ||
293 | rect.w = cs->video_decoder_ctx->width; | ||
294 | rect.h = cs->video_decoder_ctx->height; | ||
295 | SDL_DisplayYUVOverlay(_phone->video_picture.bmp, &rect); | ||
296 | return 1; | ||
297 | } | ||
298 | */ | ||
299 | #ifdef TOX_FFMPEG | ||
300 | void *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 | |||
422 | void *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 | |||
458 | void 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 | |||
539 | void *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 | |||
635 | void *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 | |||
719 | ending: | ||
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 | |||
738 | void *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 | |||
848 | int 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 | |||
917 | void 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 | } | ||
932 | void callback_recv_ringing ( void *_arg ) | ||
933 | { | ||
934 | INFO ( "Ringing!" ); | ||
935 | } | ||
936 | void 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 | } | ||
945 | void 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 | |||
959 | void callback_recv_error ( void *_arg ) | ||
960 | { | ||
961 | /*MSISession* _session = _arg; | ||
962 | |||
963 | INFO( "Error: %s", _session->last_error_str ); */ | ||
964 | } | ||
965 | |||
966 | void 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 | } | ||
975 | void callback_call_canceled ( void *_arg ) | ||
976 | { | ||
977 | INFO ( "Call canceled!" ); | ||
978 | } | ||
979 | void callback_call_rejected ( void *_arg ) | ||
980 | { | ||
981 | INFO ( "Call rejected!" ); | ||
982 | } | ||
983 | void 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 | |||
1005 | void callback_requ_timeout ( void *_arg ) | ||
1006 | { | ||
1007 | INFO( "No answer! " ); | ||
1008 | } | ||
1009 | |||
1010 | av_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 | |||
1116 | failed_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 | |||
1147 | int 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 */ | ||
1173 | void 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 | |||
1185 | void 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 | |||
1200 | int 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 | |||
1218 | int 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 | |||
1233 | void 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 | |||
1348 | void *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 | |||
1360 | int 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 | |||
1389 | int 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 | |||
1400 | int 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[] = { | |||
227 | RTPHeader *extract_header ( const uint8_t *payload, int length ) | 229 | RTPHeader *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 | */ |
585 | RTPMessage *rtp_new_message ( RTPSession *session, const uint8_t *data, uint32_t length ) | 611 | RTPMessage *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 | |||
665 | int rtp_release_session_recv ( RTPSession *session ) | 693 | int 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 | */ | ||
725 | void 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 | */ |
695 | RTPMessage *rtp_recv_msg ( RTPSession *session ) | 750 | RTPMessage *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 | */ |
891 | int rtp_terminate_session ( RTPSession *session, Messenger *messenger ) | 955 | int 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 | */ | ||
156 | void 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 | */ |
197 | RTPSession *rtp_init_session ( int payload_type, | 205 | RTPSession *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 | */ |
289 | int toxav_prepare_transmission ( ToxAv* av, uint32_t call_index, int support_video ) | 289 | int 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 | |||
341 | int toxav_kill_transmission ( ToxAv *av, uint32_t call_index ) | 345 | int 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 | */ |
473 | inline__ int toxav_send_video ( ToxAv *av, uint32_t call_index, vpx_image_t *input) | 479 | inline__ 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 | ||
506 | int 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 | */ |
539 | inline__ int toxav_send_audio ( ToxAv *av, uint32_t call_index, const int16_t *frame, int frame_size) | 581 | inline__ 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 | */ | ||
598 | int 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 | */ | ||
666 | void 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 | */ |
606 | inline__ Tox* toxav_get_tox ( ToxAv* av ) | 679 | void 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 | |||
276 | int toxav_send_video ( ToxAv* av, uint32_t call_index, vpx_image_t* input); | 277 | int 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 | */ |
289 | int toxav_send_audio ( ToxAv* av, uint32_t call_index, const int16_t* frame, int frame_size); | 290 | int toxav_send_audio ( ToxAv* av, uint32_t call_index, const int16_t* frame, int frame_size); |
290 | 291 | ||
292 | int 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 | */ | ||
306 | int 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 ); | |||
320 | int toxav_capability_supported ( ToxAv* av, ToxAvCapabilities capability ); | 337 | int 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 | */ | ||
347 | void 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 | */ |
328 | Tox* toxav_get_tox ( ToxAv* av ); | 357 | void 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 |