summaryrefslogtreecommitdiff
path: root/toxav/media.c
diff options
context:
space:
mode:
authorirungentoo <irungentoo@gmail.com>2014-05-25 12:27:48 -0400
committerirungentoo <irungentoo@gmail.com>2014-05-25 12:27:48 -0400
commit82e38883a239f265089982bc255de0f9db618ce7 (patch)
tree1d38b2ff978e86246695cc7e473af309eacdba2a /toxav/media.c
parent9d53bc5d1dabd3142f58cafd9fffa18f783f96df (diff)
parent08ca08dcd952d55a0df75e5efa25a5d8afa70e3f (diff)
Merge branch 'mannol1-Multicalls' into multi-av
Diffstat (limited to 'toxav/media.c')
-rw-r--r--toxav/media.c144
1 files changed, 77 insertions, 67 deletions
diff --git a/toxav/media.c b/toxav/media.c
index a9a4adb8..16156d9d 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,40 +36,31 @@
34#include "rtp.h" 36#include "rtp.h"
35#include "media.h" 37#include "media.h"
36 38
37struct jitter_buffer { 39int empty_queue(JitterBuffer *q)
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
49int empty_queue(struct jitter_buffer *q)
50{ 40{
51 while (q->size > 0) { 41 while (q->size > 0) {
52 rtp_free_msg(NULL, q->queue[q->front]); 42 rtp_free_msg(NULL, q->queue[q->front]);
53 q->front++; 43 q->front++;
54 44
55 if (q->front == q->capacity) 45 if (q->front == q->capacity)
56 q->front = 0; 46 q->front = 0;
57 47
58 q->size--; 48 q->size--;
59 } 49 }
60 50
61 q->id_set = 0; 51 q->id_set = 0;
62 q->queue_ready = 0; 52 q->queue_ready = 0;
63 return 0; 53 return 0;
64} 54}
65 55
66struct jitter_buffer *create_queue(int capacity) 56JitterBuffer *create_queue(int capacity)
67{ 57{
68 struct jitter_buffer *q; 58 JitterBuffer *q;
69 q = calloc(sizeof(struct jitter_buffer), 1); 59
70 q->queue = calloc(sizeof(RTPMessage *), capacity); 60 if ( !(q = calloc(sizeof(JitterBuffer), 1)) ) return NULL;
61
62 if (!(q->queue = calloc(sizeof(RTPMessage *), capacity))) return NULL;
63
71 q->size = 0; 64 q->size = 0;
72 q->capacity = capacity; 65 q->capacity = capacity;
73 q->front = 0; 66 q->front = 0;
@@ -79,17 +72,17 @@ struct jitter_buffer *create_queue(int capacity)
79 return q; 72 return q;
80} 73}
81 74
82/* returns 1 if 'a' has a higher sequence number than 'b' */ 75void terminate_queue(JitterBuffer *q)
83uint8_t sequence_number_older(uint16_t sn_a, uint16_t sn_b, uint32_t ts_a, uint32_t ts_b)
84{ 76{
85 /* TODO: There is already this kind of function in toxrtp.c. 77 empty_queue(q);
86 * Maybe merge? 78 free(q->queue);
87 */ 79 free(q);
88 return (sn_a > sn_b || ts_a > ts_b);
89} 80}
90 81
82#define sequnum_older(sn_a, sn_b, ts_a, ts_b) (sn_a > sn_b || ts_a > ts_b)
83
91/* success is 0 when there is nothing to dequeue, 1 when there's a good packet, 2 when there's a lost packet */ 84/* success is 0 when there is nothing to dequeue, 1 when there's a good packet, 2 when there's a lost packet */
92RTPMessage *dequeue(struct jitter_buffer *q, int *success) 85RTPMessage *dequeue(JitterBuffer *q, int *success)
93{ 86{
94 if (q->size == 0 || q->queue_ready == 0) { /* Empty queue */ 87 if (q->size == 0 || q->queue_ready == 0) { /* Empty queue */
95 q->queue_ready = 0; 88 q->queue_ready = 0;
@@ -112,14 +105,13 @@ RTPMessage *dequeue(struct jitter_buffer *q, int *success)
112 q->current_id = next_id; 105 q->current_id = next_id;
113 q->current_ts = next_ts; 106 q->current_ts = next_ts;
114 } else { 107 } else {
115 if (sequence_number_older(next_id, q->current_id, next_ts, q->current_ts)) { 108 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);*/ 109 LOGGER_DEBUG("nextid: %d current: %d\n", next_id, q->current_id);
117 q->current_id = (q->current_id + 1) % MAX_SEQU_NUM; 110 q->current_id = (q->current_id + 1) % MAX_SEQU_NUM;
118 *success = 2; /* tell the decoder the packet is lost */ 111 *success = 2; /* tell the decoder the packet is lost */
119 return NULL; 112 return NULL;
120 } else { 113 } else {
121 /* packet too old */ 114 LOGGER_DEBUG("Packet too old");
122 /*printf("packet too old\n");*/
123 *success = 0; 115 *success = 0;
124 return NULL; 116 return NULL;
125 } 117 }
@@ -139,12 +131,11 @@ RTPMessage *dequeue(struct jitter_buffer *q, int *success)
139} 131}
140 132
141 133
142int queue(struct jitter_buffer *q, RTPMessage *pk) 134void queue(JitterBuffer *q, RTPMessage *pk)
143{ 135{
144 if (q->size == q->capacity) { /* Full, empty queue */ 136 if (q->size == q->capacity) { /* Full, empty queue */
137 LOGGER_DEBUG("Queue full s(%d) c(%d), emptying...", q->size, q->capacity);
145 empty_queue(q); 138 empty_queue(q);
146 /*rtp_free_msg(NULL, pk);*/
147 return 0;
148 } 139 }
149 140
150 if (q->size > 8) 141 if (q->size > 8)
@@ -169,13 +160,13 @@ int queue(struct jitter_buffer *q, RTPMessage *pk)
169 if (b < 0) 160 if (b < 0)
170 b += q->capacity; 161 b += q->capacity;
171 162
172 if (sequence_number_older(q->queue[b]->header->sequnum, q->queue[a]->header->sequnum, 163 if (sequnum_older(q->queue[b]->header->sequnum, q->queue[a]->header->sequnum,
173 q->queue[b]->header->timestamp, q->queue[a]->header->timestamp)) { 164 q->queue[b]->header->timestamp, q->queue[a]->header->timestamp)) {
174 RTPMessage *temp; 165 RTPMessage *temp;
175 temp = q->queue[a]; 166 temp = q->queue[a];
176 q->queue[a] = q->queue[b]; 167 q->queue[a] = q->queue[b];
177 q->queue[b] = temp; 168 q->queue[b] = temp;
178 /*printf("had to swap\n");*/ 169 LOGGER_DEBUG("Had to swap");
179 } else { 170 } else {
180 break; 171 break;
181 } 172 }
@@ -185,19 +176,15 @@ int queue(struct jitter_buffer *q, RTPMessage *pk)
185 if (a < 0) 176 if (a < 0)
186 a += q->capacity; 177 a += q->capacity;
187 } 178 }
188
189 if (pk)
190 return 1;
191
192 return 0;
193} 179}
194 180
195 181
196int init_video_decoder(CodecState *cs) 182int init_video_decoder(CodecState *cs)
197{ 183{
198 if (vpx_codec_dec_init_ver(&cs->v_decoder, VIDEO_CODEC_DECODER_INTERFACE, NULL, 0, 184 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) { 185
200 /*fprintf(stderr, "Init video_decoder failed!\n");*/ 186 if ( rc != VPX_CODEC_OK) {
187 LOGGER_ERROR("Init video_decoder failed: %s", vpx_codec_err_to_string(rc));
201 return -1; 188 return -1;
202 } 189 }
203 190
@@ -210,7 +197,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 ); 197 cs->audio_decoder = opus_decoder_create(cs->audio_sample_rate, audio_channels, &rc );
211 198
212 if ( rc != OPUS_OK ) { 199 if ( rc != OPUS_OK ) {
213 /*fprintf(stderr, "Error while starting audio decoder!\n");*/ 200 LOGGER_ERROR("Error while starting audio decoder: %s", opus_strerror(rc));
214 return -1; 201 return -1;
215 } 202 }
216 203
@@ -221,10 +208,10 @@ int init_audio_decoder(CodecState *cs, uint32_t audio_channels)
221int init_video_encoder(CodecState *cs, uint16_t width, uint16_t height, uint32_t video_bitrate) 208int init_video_encoder(CodecState *cs, uint16_t width, uint16_t height, uint32_t video_bitrate)
222{ 209{
223 vpx_codec_enc_cfg_t cfg; 210 vpx_codec_enc_cfg_t cfg;
224 int res = vpx_codec_enc_config_default(VIDEO_CODEC_ENCODER_INTERFACE, &cfg, 0); 211 int rc = vpx_codec_enc_config_default(VIDEO_CODEC_ENCODER_INTERFACE, &cfg, 0);
225 212
226 if (res) { 213 if (rc) {
227 /*fprintf(stderr, "Failed to get config: %s\n", vpx_codec_err_to_string(res));*/ 214 LOGGER_ERROR("Failed to get config: %s", vpx_codec_err_to_string(rc));
228 return -1; 215 return -1;
229 } 216 }
230 217
@@ -232,9 +219,10 @@ int init_video_encoder(CodecState *cs, uint16_t width, uint16_t height, uint32_t
232 cfg.g_w = width; 219 cfg.g_w = width;
233 cfg.g_h = height; 220 cfg.g_h = height;
234 221
235 if (vpx_codec_enc_init_ver(&cs->v_encoder, VIDEO_CODEC_ENCODER_INTERFACE, &cfg, 0, 222 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) { 223
237 /*fprintf(stderr, "Failed to initialize encoder\n");*/ 224 if ( rc != VPX_CODEC_OK) {
225 LOGGER_ERROR("Failed to initialize encoder: %s", vpx_codec_err_to_string(rc));
238 return -1; 226 return -1;
239 } 227 }
240 228
@@ -243,13 +231,30 @@ int init_video_encoder(CodecState *cs, uint16_t width, uint16_t height, uint32_t
243 231
244int init_audio_encoder(CodecState *cs, uint32_t audio_channels) 232int init_audio_encoder(CodecState *cs, uint32_t audio_channels)
245{ 233{
246 int err = OPUS_OK; 234 int rc = OPUS_OK;
247 cs->audio_encoder = opus_encoder_create(cs->audio_sample_rate, audio_channels, OPUS_APPLICATION_AUDIO, &err); 235 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)); 236
249 err = opus_encoder_ctl(cs->audio_encoder, OPUS_SET_COMPLEXITY(10)); 237 if ( rc != OPUS_OK ) {
238 LOGGER_ERROR("Error while starting audio encoder: %s", opus_strerror(rc));
239 return -1;
240 }
241
242 rc = opus_encoder_ctl(cs->audio_encoder, OPUS_SET_BITRATE(cs->audio_bitrate));
250 243
244 if ( rc != OPUS_OK ) {
245 LOGGER_ERROR("Error while setting encoder ctl: %s", opus_strerror(rc));
246 return -1;
247 }
248
249 rc = opus_encoder_ctl(cs->audio_encoder, OPUS_SET_COMPLEXITY(10));
250
251 if ( rc != OPUS_OK ) {
252 LOGGER_ERROR("Error while setting encoder ctl: %s", opus_strerror(rc));
253 return -1;
254 }
251 255
252 return err == OPUS_OK ? 0 : -1; 256
257 return 0;
253} 258}
254 259
255 260
@@ -262,7 +267,8 @@ CodecState *codec_init_session ( uint32_t audio_bitrate,
262 uint32_t video_bitrate ) 267 uint32_t video_bitrate )
263{ 268{
264 CodecState *retu = calloc(sizeof(CodecState), 1); 269 CodecState *retu = calloc(sizeof(CodecState), 1);
265 assert(retu); 270
271 if (!retu) return NULL;
266 272
267 retu->audio_bitrate = audio_bitrate; 273 retu->audio_bitrate = audio_bitrate;
268 retu->audio_sample_rate = audio_sample_rate; 274 retu->audio_sample_rate = audio_sample_rate;
@@ -271,8 +277,7 @@ CodecState *codec_init_session ( uint32_t audio_bitrate,
271 if (!video_width || !video_height) { /* Disable video */ 277 if (!video_width || !video_height) { /* Disable video */
272 /*video_width = 320; 278 /*video_width = 320;
273 video_height = 240; */ 279 video_height = 240; */
274 } 280 } else {
275 else {
276 retu->capabilities |= ( 0 == init_video_encoder(retu, video_width, video_height, video_bitrate) ) ? v_encoding : 0; 281 retu->capabilities |= ( 0 == init_video_encoder(retu, video_width, video_height, video_bitrate) ) ? v_encoding : 0;
277 retu->capabilities |= ( 0 == init_video_decoder(retu) ) ? v_decoding : 0; 282 retu->capabilities |= ( 0 == init_video_decoder(retu) ) ? v_decoding : 0;
278 } 283 }
@@ -280,24 +285,29 @@ CodecState *codec_init_session ( uint32_t audio_bitrate,
280 retu->capabilities |= ( 0 == init_audio_encoder(retu, audio_channels) ) ? a_encoding : 0; 285 retu->capabilities |= ( 0 == init_audio_encoder(retu, audio_channels) ) ? a_encoding : 0;
281 retu->capabilities |= ( 0 == init_audio_decoder(retu, audio_channels) ) ? a_decoding : 0; 286 retu->capabilities |= ( 0 == init_audio_decoder(retu, audio_channels) ) ? a_decoding : 0;
282 287
288 if ( retu->capabilities == 0 ) { /* everything failed */
289 free (retu);
290 return NULL;
291 }
292
283 return retu; 293 return retu;
284} 294}
285 295
286void codec_terminate_session ( CodecState *cs ) 296void codec_terminate_session ( CodecState *cs )
287{ 297{
288 if ( cs->audio_encoder ) 298 if ( cs->audio_encoder )
289 opus_encoder_destroy(cs->audio_encoder); 299 opus_encoder_destroy(cs->audio_encoder);
290 300
291 if ( cs->audio_decoder ) 301 if ( cs->audio_decoder )
292 opus_decoder_destroy(cs->audio_decoder); 302 opus_decoder_destroy(cs->audio_decoder);
293
294 303
295 /* TODO: Terminate video 304
296 * Do what??? 305 /* TODO: Terminate video
306 * Do what?
297 */ 307 */
298 if ( cs->capabilities & v_decoding ) 308 if ( cs->capabilities & v_decoding )
299 vpx_codec_destroy(&cs->v_decoder); 309 vpx_codec_destroy(&cs->v_decoder);
300 310
301 if ( cs->capabilities & v_encoding ) 311 if ( cs->capabilities & v_encoding )
302 vpx_codec_destroy(&cs->v_encoder); 312 vpx_codec_destroy(&cs->v_encoder);
303} 313}