summaryrefslogtreecommitdiff
path: root/toxav/codec.c
diff options
context:
space:
mode:
Diffstat (limited to 'toxav/codec.c')
-rw-r--r--toxav/codec.c680
1 files changed, 408 insertions, 272 deletions
diff --git a/toxav/codec.c b/toxav/codec.c
index de802526..bf94115e 100644
--- a/toxav/codec.c
+++ b/toxav/codec.c
@@ -1,8 +1,6 @@
1/** codec.c 1/** codec.c
2 * 2 *
3 * Audio and video codec intitialization, encoding/decoding and playback 3 * Copyright (C) 2013-2015 Tox project All Rights Reserved.
4 *
5 * Copyright (C) 2013 Tox project All Rights Reserved.
6 * 4 *
7 * This file is part of Tox. 5 * This file is part of Tox.
8 * 6 *
@@ -31,6 +29,7 @@
31 29
32#include <stdio.h> 30#include <stdio.h>
33#include <stdlib.h> 31#include <stdlib.h>
32#include <stdbool.h>
34#include <math.h> 33#include <math.h>
35#include <assert.h> 34#include <assert.h>
36#include <time.h> 35#include <time.h>
@@ -39,12 +38,12 @@
39#include "rtp.h" 38#include "rtp.h"
40#include "codec.h" 39#include "codec.h"
41 40
41#define DEFAULT_JBUF 6
42
42/* Good quality encode. */ 43/* Good quality encode. */
43#define MAX_DECODE_TIME_US 0 44#define MAX_DECODE_TIME_US 0
44 45
45// TODO this has to be exchanged in msi
46#define MAX_VIDEOFRAME_SIZE 0x40000 /* 256KiB */ 46#define MAX_VIDEOFRAME_SIZE 0x40000 /* 256KiB */
47#define VIDEOFRAME_PIECE_SIZE 0x500 /* 1.25 KiB*/
48#define VIDEOFRAME_HEADER_SIZE 0x2 47#define VIDEOFRAME_HEADER_SIZE 0x2
49 48
50/* FIXME: Might not be enough */ 49/* FIXME: Might not be enough */
@@ -61,12 +60,12 @@ typedef struct {
61 Payload **packets; 60 Payload **packets;
62} PayloadBuffer; 61} PayloadBuffer;
63 62
64static _Bool buffer_full(const PayloadBuffer *b) 63static bool buffer_full(const PayloadBuffer *b)
65{ 64{
66 return (b->end + 1) % b->size == b->start; 65 return (b->end + 1) % b->size == b->start;
67} 66}
68 67
69static _Bool buffer_empty(const PayloadBuffer *b) 68static bool buffer_empty(const PayloadBuffer *b)
70{ 69{
71 return b->end == b->start; 70 return b->end == b->start;
72} 71}
@@ -120,7 +119,7 @@ static void buffer_free(PayloadBuffer *b)
120} 119}
121 120
122/* JITTER BUFFER WORK */ 121/* JITTER BUFFER WORK */
123typedef struct _JitterBuffer { 122typedef struct JitterBuffer_s {
124 RTPMessage **queue; 123 RTPMessage **queue;
125 uint32_t size; 124 uint32_t size;
126 uint32_t capacity; 125 uint32_t capacity;
@@ -224,129 +223,186 @@ static RTPMessage *jbuf_read(JitterBuffer *q, int32_t *success)
224 return NULL; 223 return NULL;
225} 224}
226 225
227static int init_video_decoder(CSSession *cs) 226static int convert_bw_to_sampling_rate(int bw)
228{ 227{
229 int rc = vpx_codec_dec_init_ver(&cs->v_decoder, VIDEO_CODEC_DECODER_INTERFACE, NULL, 0, VPX_DECODER_ABI_VERSION); 228 switch(bw)
230 229 {
231 if ( rc != VPX_CODEC_OK) { 230 case OPUS_BANDWIDTH_NARROWBAND: return 8000;
232 LOGGER_ERROR("Init video_decoder failed: %s", vpx_codec_err_to_string(rc)); 231 case OPUS_BANDWIDTH_MEDIUMBAND: return 12000;
233 return -1; 232 case OPUS_BANDWIDTH_WIDEBAND: return 16000;
233 case OPUS_BANDWIDTH_SUPERWIDEBAND: return 24000;
234 case OPUS_BANDWIDTH_FULLBAND: return 48000;
235 default: return -1;
234 } 236 }
235
236 return 0;
237} 237}
238 238
239static int init_audio_decoder(CSSession *cs)
240{
241 int rc;
242 cs->audio_decoder = opus_decoder_create(cs->audio_decoder_sample_rate, cs->audio_decoder_channels, &rc );
243 239
244 if ( rc != OPUS_OK ) {
245 LOGGER_ERROR("Error while starting audio decoder: %s", opus_strerror(rc));
246 return -1;
247 }
248 240
249 return 0; 241/* PUBLIC */
250}
251 242
252static int init_video_encoder(CSSession *cs, uint16_t max_width, uint16_t max_height, uint32_t video_bitrate) 243void cs_do(CSSession *cs)
253{ 244{
254 vpx_codec_enc_cfg_t cfg; 245 /* Codec session should always be protected by call mutex so no need to check for cs validity
255 int rc = vpx_codec_enc_config_default(VIDEO_CODEC_ENCODER_INTERFACE, &cfg, 0); 246 */
256 247
257 if (rc != VPX_CODEC_OK) { 248 if (!cs)
258 LOGGER_ERROR("Failed to get config: %s", vpx_codec_err_to_string(rc)); 249 return;
259 return -1; 250
260 } 251 Payload *p;
261 252 int rc;
262 cfg.rc_target_bitrate = video_bitrate; 253
263 cfg.g_w = max_width; 254 int success = 0;
264 cfg.g_h = max_height; 255
265 cfg.g_pass = VPX_RC_ONE_PASS; 256 pthread_mutex_lock(cs->queue_mutex);
266 cfg.g_error_resilient = VPX_ERROR_RESILIENT_DEFAULT | VPX_ERROR_RESILIENT_PARTITIONS; 257
267 cfg.g_lag_in_frames = 0; 258 if (cs->audio_decoder) { /* If receiving enabled */
268 cfg.kf_min_dist = 0; 259 RTPMessage *msg;
269 cfg.kf_max_dist = 48; 260
270 cfg.kf_mode = VPX_KF_AUTO; 261 uint16_t fsize = 5760; /* Max frame size for 48 kHz */
271 262 int16_t tmp[fsize * 2];
272 rc = vpx_codec_enc_init_ver(&cs->v_encoder, VIDEO_CODEC_ENCODER_INTERFACE, &cfg, 0, VPX_ENCODER_ABI_VERSION); 263
273 264 while ((msg = jbuf_read(cs->j_buf, &success)) || success == 2) {
274 if ( rc != VPX_CODEC_OK) { 265 pthread_mutex_unlock(cs->queue_mutex);
275 LOGGER_ERROR("Failed to initialize encoder: %s", vpx_codec_err_to_string(rc)); 266
276 return -1; 267 if (success == 2) {
268 rc = opus_decode(cs->audio_decoder, 0, 0, tmp, fsize, 1);
269 } else {
270 /* Get values from packet and decode.
271 * It also checks for validity of an opus packet
272 */
273 rc = convert_bw_to_sampling_rate(opus_packet_get_bandwidth(msg->data));
274 if (rc != -1) {
275 cs->last_packet_sampling_rate = rc;
276 cs->last_pack_channels = opus_packet_get_nb_channels(msg->data);
277
278 cs->last_packet_frame_duration =
279 ( opus_packet_get_samples_per_frame(msg->data, cs->last_packet_sampling_rate) * 1000 )
280 / cs->last_packet_sampling_rate;
281 } else {
282 LOGGER_WARNING("Failed to load packet values!");
283 rtp_free_msg(NULL, msg);
284 continue;
285 }
286
287 rc = opus_decode(cs->audio_decoder, msg->data, msg->length, tmp, fsize, 0);
288 rtp_free_msg(NULL, msg);
289 }
290
291 if (rc < 0) {
292 LOGGER_WARNING("Decoding error: %s", opus_strerror(rc));
293 } else if (cs->acb.first) {
294 /* Play */
295 cs->acb.first(cs->agent, cs->friend_id, tmp, rc,
296 cs->last_pack_channels, cs->last_packet_sampling_rate, cs->acb.second);
297 }
298
299 pthread_mutex_lock(cs->queue_mutex);
300 }
277 } 301 }
278 302
279 rc = vpx_codec_control(&cs->v_encoder, VP8E_SET_CPUUSED, 8); 303 if (cs->vbuf_raw && !buffer_empty(cs->vbuf_raw)) {
280 304 /* Decode video */
281 if ( rc != VPX_CODEC_OK) { 305 buffer_read(cs->vbuf_raw, &p);
282 LOGGER_ERROR("Failed to set encoder control setting: %s", vpx_codec_err_to_string(rc)); 306
283 return -1; 307 /* Leave space for (possibly) other thread to queue more data after we read it here */
308 pthread_mutex_unlock(cs->queue_mutex);
309
310 rc = vpx_codec_decode(cs->v_decoder, p->data, p->size, NULL, MAX_DECODE_TIME_US);
311 free(p);
312
313 if (rc != VPX_CODEC_OK) {
314 LOGGER_ERROR("Error decoding video: %s", vpx_codec_err_to_string(rc));
315 } else {
316 vpx_codec_iter_t iter = NULL;
317 vpx_image_t *dest = vpx_codec_get_frame(cs->v_decoder, &iter);
318
319 /* Play decoded images */
320 for (; dest; dest = vpx_codec_get_frame(cs->v_decoder, &iter)) {
321 if (cs->vcb.first)
322 cs->vcb.first(cs->agent, cs->friend_id, dest->d_w, dest->d_h,
323 (const uint8_t**)dest->planes, dest->stride, cs->vcb.second);
324
325 vpx_img_free(dest);
326 }
327 }
328
329 return;
284 } 330 }
285 331
286 cs->max_width = max_width; 332 pthread_mutex_unlock(cs->queue_mutex);
287 cs->max_height = max_height;
288 cs->video_bitrate = video_bitrate;
289
290 return 0;
291} 333}
292 334
293static int init_audio_encoder(CSSession *cs) 335CSSession *cs_new(uint32_t peer_video_frame_piece_size)
294{ 336{
295 int rc = OPUS_OK; 337 CSSession *cs = calloc(sizeof(CSSession), 1);
296 cs->audio_encoder = opus_encoder_create(cs->audio_encoder_sample_rate, 338
297 cs->audio_encoder_channels, OPUS_APPLICATION_AUDIO, &rc); 339 if (!cs) {
298 340 LOGGER_WARNING("Allocation failed! Application might misbehave!");
299 if ( rc != OPUS_OK ) { 341 return NULL;
300 LOGGER_ERROR("Error while starting audio encoder: %s", opus_strerror(rc));
301 return -1;
302 } 342 }
303 343
304 rc = opus_encoder_ctl(cs->audio_encoder, OPUS_SET_BITRATE(cs->audio_encoder_bitrate)); 344
305 345 if (create_recursive_mutex(cs->queue_mutex) != 0) {
306 if ( rc != OPUS_OK ) { 346 LOGGER_WARNING("Failed to create recursive mutex!");
307 LOGGER_ERROR("Error while setting encoder ctl: %s", opus_strerror(rc)); 347 free(cs);
308 return -1; 348 return NULL;
309 } 349 }
350
351
352 cs->peer_video_frame_piece_size = peer_video_frame_piece_size;
353
354 return cs;
355}
310 356
311 rc = opus_encoder_ctl(cs->audio_encoder, OPUS_SET_COMPLEXITY(10)); 357void cs_kill(CSSession *cs)
358{
359 if (!cs)
360 return;
361
362 /* NOTE: queue_message() will not be called since
363 * the callback is unregistered before cs_kill is called.
364 */
365
366 cs_disable_audio_sending(cs);
367 cs_disable_audio_receiving(cs);
368 cs_disable_video_sending(cs);
369 cs_disable_video_receiving(cs);
370
371 pthread_mutex_destroy(cs->queue_mutex);
372
373 LOGGER_DEBUG("Terminated codec state: %p", cs);
374 free(cs);
375}
312 376
313 if ( rc != OPUS_OK ) {
314 LOGGER_ERROR("Error while setting encoder ctl: %s", opus_strerror(rc));
315 return -1;
316 }
317 377
318 return 0;
319}
320 378
321/* PUBLIC */ 379void cs_init_video_splitter_cycle(CSSession* cs)
322int cs_split_video_payload(CSSession *cs, const uint8_t *payload, uint16_t length)
323{ 380{
324 if (!cs || !length || length > cs->max_video_frame_size) {
325 LOGGER_ERROR("Invalid CodecState or video frame size: %u", length);
326 return cs_ErrorSplittingVideoPayload;
327 }
328
329 cs->split_video_frame[0] = cs->frameid_out++; 381 cs->split_video_frame[0] = cs->frameid_out++;
330 cs->split_video_frame[1] = 0; 382 cs->split_video_frame[1] = 0;
383}
384
385int cs_update_video_splitter_cycle(CSSession *cs, const uint8_t *payload, uint16_t length)
386{
331 cs->processing_video_frame = payload; 387 cs->processing_video_frame = payload;
332 cs->processing_video_frame_size = length; 388 cs->processing_video_frame_size = length;
333 389
334 return ((length - 1) / cs->video_frame_piece_size) + 1; 390 return ((length - 1) / VIDEOFRAME_PIECE_SIZE) + 1;
335} 391}
336 392
337const uint8_t *cs_get_split_video_frame(CSSession *cs, uint16_t *size) 393const uint8_t *cs_iterate_split_video_frame(CSSession *cs, uint16_t *size)
338{ 394{
339 if (!cs || !size) return NULL; 395 if (!cs || !size) return NULL;
340 396
341 if (cs->processing_video_frame_size > cs->video_frame_piece_size) { 397 if (cs->processing_video_frame_size > VIDEOFRAME_PIECE_SIZE) {
342 memcpy(cs->split_video_frame + VIDEOFRAME_HEADER_SIZE, 398 memcpy(cs->split_video_frame + VIDEOFRAME_HEADER_SIZE,
343 cs->processing_video_frame, 399 cs->processing_video_frame,
344 cs->video_frame_piece_size); 400 VIDEOFRAME_PIECE_SIZE);
345 401
346 cs->processing_video_frame += cs->video_frame_piece_size; 402 cs->processing_video_frame += VIDEOFRAME_PIECE_SIZE;
347 cs->processing_video_frame_size -= cs->video_frame_piece_size; 403 cs->processing_video_frame_size -= VIDEOFRAME_PIECE_SIZE;
348 404
349 *size = cs->video_frame_piece_size + VIDEOFRAME_HEADER_SIZE; 405 *size = VIDEOFRAME_PIECE_SIZE + VIDEOFRAME_HEADER_SIZE;
350 } else { 406 } else {
351 memcpy(cs->split_video_frame + VIDEOFRAME_HEADER_SIZE, 407 memcpy(cs->split_video_frame + VIDEOFRAME_HEADER_SIZE,
352 cs->processing_video_frame, 408 cs->processing_video_frame,
@@ -360,82 +416,19 @@ const uint8_t *cs_get_split_video_frame(CSSession *cs, uint16_t *size)
360 return cs->split_video_frame; 416 return cs->split_video_frame;
361} 417}
362 418
363void cs_do(CSSession *cs)
364{
365 /* Codec session should always be protected by call mutex so no need to check for cs validity
366 */
367
368 if (!cs) return;
369
370 Payload *p;
371 int rc;
372
373 int success = 0;
374
375 pthread_mutex_lock(cs->queue_mutex);
376 RTPMessage *msg;
377
378 while ((msg = jbuf_read(cs->j_buf, &success)) || success == 2) {
379 pthread_mutex_unlock(cs->queue_mutex);
380
381 uint16_t fsize = ((cs->audio_decoder_sample_rate * cs->audio_decoder_frame_duration) / 1000);
382 int16_t tmp[fsize * cs->audio_decoder_channels];
383
384 if (success == 2) {
385 rc = opus_decode(cs->audio_decoder, 0, 0, tmp, fsize, 1);
386 } else {
387 rc = opus_decode(cs->audio_decoder, msg->data, msg->length, tmp, fsize, 0);
388 rtp_free_msg(NULL, msg);
389 }
390
391 if (rc < 0) {
392 LOGGER_WARNING("Decoding error: %s", opus_strerror(rc));
393 } else if (cs->acb.first) {
394 /* Play */
395 cs->acb.first(cs->agent, cs->call_idx, tmp, rc, cs->acb.second);
396 }
397
398 pthread_mutex_lock(cs->queue_mutex);
399 }
400
401 if (cs->vbuf_raw && !buffer_empty(cs->vbuf_raw)) {
402 /* Decode video */
403 buffer_read(cs->vbuf_raw, &p);
404 419
405 /* Leave space for (possibly) other thread to queue more data after we read it here */
406 pthread_mutex_unlock(cs->queue_mutex);
407
408 rc = vpx_codec_decode(&cs->v_decoder, p->data, p->size, NULL, MAX_DECODE_TIME_US);
409 free(p);
410
411 if (rc != VPX_CODEC_OK) {
412 LOGGER_ERROR("Error decoding video: %s", vpx_codec_err_to_string(rc));
413 } else {
414 vpx_codec_iter_t iter = NULL;
415 vpx_image_t *dest = vpx_codec_get_frame(&cs->v_decoder, &iter);
416 420
417 /* Play decoded images */ 421int cs_set_sending_video_resolution(CSSession *cs, uint16_t width, uint16_t height)
418 for (; dest; dest = vpx_codec_get_frame(&cs->v_decoder, &iter)) {
419 if (cs->vcb.first)
420 cs->vcb.first(cs->agent, cs->call_idx, dest, cs->vcb.second);
421
422 vpx_img_free(dest);
423 }
424 }
425
426 return;
427 }
428
429 pthread_mutex_unlock(cs->queue_mutex);
430}
431
432int cs_set_video_encoder_resolution(CSSession *cs, uint16_t width, uint16_t height)
433{ 422{
434 vpx_codec_enc_cfg_t cfg = *cs->v_encoder.config.enc; 423 if (!cs->v_encoding)
435 424 return -1;
425
426 /* TODO FIXME reference is safe? */
427 vpx_codec_enc_cfg_t cfg = *cs->v_encoder[0].config.enc;
428
436 if (cfg.g_w == width && cfg.g_h == height) 429 if (cfg.g_w == width && cfg.g_h == height)
437 return 0; 430 return 0;
438 431/*
439 if (width * height > cs->max_width * cs->max_height) { 432 if (width * height > cs->max_width * cs->max_height) {
440 vpx_codec_ctx_t v_encoder = cs->v_encoder; 433 vpx_codec_ctx_t v_encoder = cs->v_encoder;
441 434
@@ -446,12 +439,12 @@ int cs_set_video_encoder_resolution(CSSession *cs, uint16_t width, uint16_t heig
446 439
447 vpx_codec_destroy(&v_encoder); 440 vpx_codec_destroy(&v_encoder);
448 return 0; 441 return 0;
449 } 442 }*/
450 443
451 LOGGER_DEBUG("New video resolution: %u %u", width, height); 444 LOGGER_DEBUG("New video resolution: %u %u", width, height);
452 cfg.g_w = width; 445 cfg.g_w = width;
453 cfg.g_h = height; 446 cfg.g_h = height;
454 int rc = vpx_codec_enc_config_set(&cs->v_encoder, &cfg); 447 int rc = vpx_codec_enc_config_set(cs->v_encoder, &cfg);
455 448
456 if ( rc != VPX_CODEC_OK) { 449 if ( rc != VPX_CODEC_OK) {
457 LOGGER_ERROR("Failed to set encoder control setting: %s", vpx_codec_err_to_string(rc)); 450 LOGGER_ERROR("Failed to set encoder control setting: %s", vpx_codec_err_to_string(rc));
@@ -461,138 +454,282 @@ int cs_set_video_encoder_resolution(CSSession *cs, uint16_t width, uint16_t heig
461 return 0; 454 return 0;
462} 455}
463 456
464int cs_set_video_encoder_bitrate(CSSession *cs, uint32_t video_bitrate) 457int cs_set_sending_video_bitrate(CSSession *cs, uint32_t bitrate)
465{ 458{
466 vpx_codec_enc_cfg_t cfg = *cs->v_encoder.config.enc; 459 if (!cs->v_encoding)
467 460 return -1;
468 if (cfg.rc_target_bitrate == video_bitrate) 461
462 /* TODO FIXME reference is safe? */
463 vpx_codec_enc_cfg_t cfg = *cs->v_encoder[0].config.enc;
464 if (cfg.rc_target_bitrate == bitrate)
469 return 0; 465 return 0;
470 466
471 LOGGER_DEBUG("New video bitrate: %u", video_bitrate); 467 LOGGER_DEBUG("New video bitrate: %u", bitrate);
472 cfg.rc_target_bitrate = video_bitrate; 468 cfg.rc_target_bitrate = bitrate;
473 int rc = vpx_codec_enc_config_set(&cs->v_encoder, &cfg); 469
474 470 int rc = vpx_codec_enc_config_set(cs->v_encoder, &cfg);
475 if ( rc != VPX_CODEC_OK) { 471 if ( rc != VPX_CODEC_OK) {
476 LOGGER_ERROR("Failed to set encoder control setting: %s", vpx_codec_err_to_string(rc)); 472 LOGGER_ERROR("Failed to set encoder control setting: %s", vpx_codec_err_to_string(rc));
477 return cs_ErrorSettingVideoBitrate; 473 return cs_ErrorSettingVideoBitrate;
478 } 474 }
479 475
480 cs->video_bitrate = video_bitrate;
481 return 0; 476 return 0;
482} 477}
483 478
484CSSession *cs_new(const ToxAvCSettings *cs_self, const ToxAvCSettings *cs_peer, uint32_t jbuf_size, int has_video) 479int cs_enable_video_sending(CSSession* cs, uint32_t bitrate)
485{ 480{
486 CSSession *cs = calloc(sizeof(CSSession), 1); 481 if (cs->v_encoding)
487 482 return 0;
488 if (!cs) { 483
489 LOGGER_WARNING("Allocation failed! Application might misbehave!"); 484 vpx_codec_enc_cfg_t cfg;
490 return NULL; 485 int rc = vpx_codec_enc_config_default(VIDEO_CODEC_ENCODER_INTERFACE, &cfg, 0);
486
487 if (rc != VPX_CODEC_OK) {
488 LOGGER_ERROR("Failed to get config: %s", vpx_codec_err_to_string(rc));
489 return -1;
491 } 490 }
492 491
493 if (create_recursive_mutex(cs->queue_mutex) != 0) { 492 rc = vpx_codec_enc_init_ver(cs->v_encoder, VIDEO_CODEC_ENCODER_INTERFACE, &cfg, 0,
494 LOGGER_WARNING("Failed to create recursive mutex!"); 493 VPX_ENCODER_ABI_VERSION);
495 free(cs); 494
496 return NULL; 495 if ( rc != VPX_CODEC_OK) {
496 LOGGER_ERROR("Failed to initialize encoder: %s", vpx_codec_err_to_string(rc));
497 return -1;
497 } 498 }
498 499
499 if ( !(cs->j_buf = jbuf_new(jbuf_size)) ) { 500 /* So that we can use cs_disable_video_sending to clean up */
500 LOGGER_WARNING("Jitter buffer creaton failed!"); 501 cs->v_encoding = true;
501 goto error; 502
503 if ( !(cs->split_video_frame = calloc(VIDEOFRAME_PIECE_SIZE + VIDEOFRAME_HEADER_SIZE, 1)) )
504 goto FAILURE;
505
506 cfg.rc_target_bitrate = bitrate;
507 cfg.g_w = 800;
508 cfg.g_h = 600;
509 cfg.g_pass = VPX_RC_ONE_PASS;
510 cfg.g_error_resilient = VPX_ERROR_RESILIENT_DEFAULT | VPX_ERROR_RESILIENT_PARTITIONS;
511 cfg.g_lag_in_frames = 0;
512 cfg.kf_min_dist = 0;
513 cfg.kf_max_dist = 48;
514 cfg.kf_mode = VPX_KF_AUTO;
515
516
517 rc = vpx_codec_control(cs->v_encoder, VP8E_SET_CPUUSED, 8);
518
519 if ( rc != VPX_CODEC_OK) {
520 LOGGER_ERROR("Failed to set encoder control setting: %s", vpx_codec_err_to_string(rc));
521 goto FAILURE;
502 } 522 }
523
524 return 0;
525
526FAILURE:
527 cs_disable_video_sending(cs);
528 return -1;
529}
503 530
504 cs->audio_encoder_bitrate = cs_self->audio_bitrate; 531int cs_enable_video_receiving(CSSession* cs)
505 cs->audio_encoder_sample_rate = cs_self->audio_sample_rate; 532{
506 cs->audio_encoder_channels = cs_self->audio_channels; 533 if (cs->v_decoding)
507 cs->audio_encoder_frame_duration = cs_self->audio_frame_duration; 534 return 0;
508
509 cs->audio_decoder_bitrate = cs_peer->audio_bitrate;
510 cs->audio_decoder_sample_rate = cs_peer->audio_sample_rate;
511 cs->audio_decoder_channels = cs_peer->audio_channels;
512 cs->audio_decoder_frame_duration = cs_peer->audio_frame_duration;
513
514
515 cs->capabilities |= ( 0 == init_audio_encoder(cs) ) ? cs_AudioEncoding : 0;
516 cs->capabilities |= ( 0 == init_audio_decoder(cs) ) ? cs_AudioDecoding : 0;
517
518 if ( !(cs->capabilities & cs_AudioEncoding) || !(cs->capabilities & cs_AudioDecoding) ) goto error;
519
520 if ((cs->support_video = has_video)) {
521 cs->max_video_frame_size = MAX_VIDEOFRAME_SIZE;
522 cs->video_frame_piece_size = VIDEOFRAME_PIECE_SIZE;
523
524 cs->capabilities |= ( 0 == init_video_encoder(cs, cs_self->max_video_width,
525 cs_self->max_video_height, cs_self->video_bitrate) ) ? cs_VideoEncoding : 0;
526 cs->capabilities |= ( 0 == init_video_decoder(cs) ) ? cs_VideoDecoding : 0;
527
528 if ( !(cs->capabilities & cs_VideoEncoding) || !(cs->capabilities & cs_VideoDecoding) ) goto error;
529
530 if ( !(cs->frame_buf = calloc(cs->max_video_frame_size, 1)) ) goto error;
531
532 if ( !(cs->split_video_frame = calloc(cs->video_frame_piece_size + VIDEOFRAME_HEADER_SIZE, 1)) )
533 goto error;
534 535
535 if ( !(cs->vbuf_raw = buffer_new(VIDEO_DECODE_BUFFER_SIZE)) ) goto error; 536 int rc = vpx_codec_dec_init_ver(cs->v_decoder, VIDEO_CODEC_DECODER_INTERFACE,
537 NULL, 0, VPX_DECODER_ABI_VERSION);
538
539 if ( rc != VPX_CODEC_OK) {
540 LOGGER_ERROR("Init video_decoder failed: %s", vpx_codec_err_to_string(rc));
541 return -1;
536 } 542 }
543
544 /* So that we can use cs_disable_video_sending to clean up */
545 cs->v_decoding = true;
546
547 if ( !(cs->frame_buf = calloc(MAX_VIDEOFRAME_SIZE, 1)) )
548 goto FAILURE;
549
550 if ( !(cs->vbuf_raw = buffer_new(VIDEO_DECODE_BUFFER_SIZE)) )
551 goto FAILURE;
552
553 return 0;
554
555FAILURE:
556 cs_disable_video_receiving(cs);
557 return -1;
558}
537 559
538 return cs; 560void cs_disable_video_sending(CSSession* cs)
539 561{
540error: 562 if (cs->v_encoding) {
541 LOGGER_WARNING("Error initializing codec session! Application might misbehave!"); 563 cs->v_encoding = false;
542 564
543 pthread_mutex_destroy(cs->queue_mutex); 565 free(cs->split_video_frame);
544 566 cs->split_video_frame = NULL;
545 if ( cs->audio_encoder ) opus_encoder_destroy(cs->audio_encoder); 567
546 568 vpx_codec_destroy(cs->v_encoder);
547 if ( cs->audio_decoder ) opus_decoder_destroy(cs->audio_decoder); 569 }
548 570}
549
550 if (has_video) {
551 if ( cs->capabilities & cs_VideoDecoding ) vpx_codec_destroy(&cs->v_decoder);
552
553 if ( cs->capabilities & cs_VideoEncoding ) vpx_codec_destroy(&cs->v_encoder);
554 571
572void cs_disable_video_receiving(CSSession* cs)
573{
574 if (cs->v_decoding) {
575 cs->v_decoding = false;
576
555 buffer_free(cs->vbuf_raw); 577 buffer_free(cs->vbuf_raw);
556 578 cs->vbuf_raw = NULL;
557 free(cs->frame_buf); 579 free(cs->frame_buf);
558 free(cs->split_video_frame); 580 cs->frame_buf = NULL;
581
582 vpx_codec_destroy(cs->v_decoder);
559 } 583 }
584}
560 585
561 jbuf_free(cs->j_buf);
562 free(cs);
563 586
564 return NULL;
565}
566 587
567void cs_kill(CSSession *cs) 588int cs_set_sending_audio_bitrate(CSSession *cs, int32_t rate)
568{ 589{
569 if (!cs) return; 590 if (cs->audio_encoder == NULL)
591 return -1;
592
593 int rc = opus_encoder_ctl(cs->audio_encoder, OPUS_SET_BITRATE(rate));
594
595 if ( rc != OPUS_OK ) {
596 LOGGER_ERROR("Error while setting encoder ctl: %s", opus_strerror(rc));
597 return -1;
598 }
599
600 return 0;
601}
570 602
571 /* queue_message will not be called since it's unregistered before cs_kill is called */ 603int cs_set_sending_audio_sampling_rate(CSSession* cs, int32_t rate)
572 pthread_mutex_destroy(cs->queue_mutex); 604{
605 /* TODO Find a better way? */
606 if (cs->audio_encoder == NULL)
607 return -1;
608
609 int rc = OPUS_OK;
610 int bitrate = 0;
611 int channels = cs->encoder_channels;
612
613 rc = opus_encoder_ctl(cs->audio_encoder, OPUS_GET_BITRATE(&bitrate));
614
615 if ( rc != OPUS_OK ) {
616 LOGGER_ERROR("Error while getting encoder ctl: %s", opus_strerror(rc));
617 return -1;
618 }
619
620 cs_disable_audio_sending(cs);
621 return cs_enable_audio_sending(cs, bitrate, channels);
622}
573 623
624int cs_set_sending_audio_channels(CSSession* cs, int32_t count)
625{
626 /* TODO Find a better way? */
627 if (cs->audio_encoder == NULL)
628 return -1;
629
630 if (cs->encoder_channels == count)
631 return 0;
632
633 int rc = OPUS_OK;
634 int bitrate = 0;
635
636 rc = opus_encoder_ctl(cs->audio_encoder, OPUS_GET_BITRATE(&bitrate));
637
638 if ( rc != OPUS_OK ) {
639 LOGGER_ERROR("Error while getting encoder ctl: %s", opus_strerror(rc));
640 return -1;
641 }
642
643 cs_disable_audio_sending(cs);
644 return cs_enable_audio_sending(cs, bitrate, count);
645}
574 646
575 if ( cs->audio_encoder ) 647void cs_disable_audio_sending(CSSession* cs)
648{
649 if ( cs->audio_encoder ) {
576 opus_encoder_destroy(cs->audio_encoder); 650 opus_encoder_destroy(cs->audio_encoder);
651 cs->audio_encoder = NULL;
652 cs->encoder_channels = 0;
653 }
654}
577 655
578 if ( cs->audio_decoder ) 656void cs_disable_audio_receiving(CSSession* cs)
657{
658 if ( cs->audio_decoder ) {
579 opus_decoder_destroy(cs->audio_decoder); 659 opus_decoder_destroy(cs->audio_decoder);
660 cs->audio_decoder = NULL;
661 jbuf_free(cs->j_buf);
662 cs->j_buf = NULL;
663
664 /* It's used for measuring iteration interval so this has to be some value.
665 * To avoid unecessary checking we set this to 500
666 */
667 cs->last_packet_frame_duration = 500;
668 }
669}
580 670
581 if ( cs->capabilities & cs_VideoDecoding ) 671int cs_enable_audio_sending(CSSession* cs, uint32_t bitrate, int channels)
582 vpx_codec_destroy(&cs->v_decoder); 672{
583 673 if (cs->audio_encoder)
584 if ( cs->capabilities & cs_VideoEncoding ) 674 return 0;
585 vpx_codec_destroy(&cs->v_encoder); 675
586 676 int rc = OPUS_OK;
587 jbuf_free(cs->j_buf); 677 cs->audio_encoder = opus_encoder_create(48000, channels, OPUS_APPLICATION_AUDIO, &rc);
588 buffer_free(cs->vbuf_raw); 678
589 free(cs->frame_buf); 679 if ( rc != OPUS_OK ) {
590 free(cs->split_video_frame); 680 LOGGER_ERROR("Error while starting audio encoder: %s", opus_strerror(rc));
591 681 return -1;
592 LOGGER_DEBUG("Terminated codec state: %p", cs); 682 }
593 free(cs); 683
684 rc = opus_encoder_ctl(cs->audio_encoder, OPUS_SET_BITRATE(bitrate));
685
686 if ( rc != OPUS_OK ) {
687 LOGGER_ERROR("Error while setting encoder ctl: %s", opus_strerror(rc));
688 goto FAILURE;
689 }
690
691 rc = opus_encoder_ctl(cs->audio_encoder, OPUS_SET_COMPLEXITY(10));
692
693 if ( rc != OPUS_OK ) {
694 LOGGER_ERROR("Error while setting encoder ctl: %s", opus_strerror(rc));
695 goto FAILURE;
696 }
697
698 cs->encoder_channels = channels;
699 return 0;
700
701FAILURE:
702 cs_disable_audio_sending(cs);
703 return -1;
594} 704}
595 705
706int cs_enable_audio_receiving(CSSession* cs)
707{
708 if (cs->audio_decoder)
709 return 0;
710
711 int rc;
712 cs->audio_decoder = opus_decoder_create(48000, 2, &rc );
713
714 if ( rc != OPUS_OK ) {
715 LOGGER_ERROR("Error while starting audio decoder: %s", opus_strerror(rc));
716 return -1;
717 }
718
719
720 if ( !(cs->j_buf = jbuf_new(DEFAULT_JBUF)) ) {
721 LOGGER_WARNING("Jitter buffer creaton failed!");
722 opus_decoder_destroy(cs->audio_decoder);
723 cs->audio_decoder = NULL;
724 return -1;
725 }
726
727 /* It's used for measuring iteration interval so this has to be some value.
728 * To avoid unecessary checking we set this to 500
729 */
730 cs->last_packet_frame_duration = 500;
731 return 0;
732}
596 733
597 734
598 735
@@ -607,7 +744,7 @@ void queue_message(RTPSession *session, RTPMessage *msg)
607 if (!cs) return; 744 if (!cs) return;
608 745
609 /* Audio */ 746 /* Audio */
610 if (session->payload_type == msi_TypeAudio % 128) { 747 if (session->payload_type == rtp_TypeAudio % 128) {
611 pthread_mutex_lock(cs->queue_mutex); 748 pthread_mutex_lock(cs->queue_mutex);
612 int ret = jbuf_write(cs->j_buf, msg); 749 int ret = jbuf_write(cs->j_buf, msg);
613 pthread_mutex_unlock(cs->queue_mutex); 750 pthread_mutex_unlock(cs->queue_mutex);
@@ -664,10 +801,10 @@ void queue_message(RTPSession *session, RTPMessage *msg)
664 801
665 uint8_t piece_number = packet[1]; 802 uint8_t piece_number = packet[1];
666 803
667 uint32_t length_before_piece = ((piece_number - 1) * cs->video_frame_piece_size); 804 uint32_t length_before_piece = ((piece_number - 1) * cs->peer_video_frame_piece_size);
668 uint32_t framebuf_new_length = length_before_piece + (packet_size - VIDEOFRAME_HEADER_SIZE); 805 uint32_t framebuf_new_length = length_before_piece + (packet_size - VIDEOFRAME_HEADER_SIZE);
669 806
670 if (framebuf_new_length > cs->max_video_frame_size) { 807 if (framebuf_new_length > MAX_VIDEOFRAME_SIZE) {
671 goto end; 808 goto end;
672 } 809 }
673 810
@@ -678,9 +815,8 @@ void queue_message(RTPSession *session, RTPMessage *msg)
678 packet + VIDEOFRAME_HEADER_SIZE, 815 packet + VIDEOFRAME_HEADER_SIZE,
679 packet_size - VIDEOFRAME_HEADER_SIZE); 816 packet_size - VIDEOFRAME_HEADER_SIZE);
680 817
681 if (framebuf_new_length > cs->frame_size) { 818 if (framebuf_new_length > cs->frame_size)
682 cs->frame_size = framebuf_new_length; 819 cs->frame_size = framebuf_new_length;
683 }
684 820
685end: 821end:
686 rtp_free_msg(NULL, msg); 822 rtp_free_msg(NULL, msg);