summaryrefslogtreecommitdiff
path: root/toxav/codec.c
diff options
context:
space:
mode:
authormannol <eniz_vukovic@hotmail.com>2015-01-24 23:29:54 +0100
committermannol <eniz_vukovic@hotmail.com>2015-01-24 23:29:54 +0100
commit1450c22d01cbb5185ee8eac14657ddf3301d7e48 (patch)
tree366f795f56689b0fb53dfe52941fb9c813429e8b /toxav/codec.c
parente57fb8c12ea7de1a5070ea0fc6f14c8e242c409f (diff)
Current progress
Diffstat (limited to 'toxav/codec.c')
-rw-r--r--toxav/codec.c529
1 files changed, 343 insertions, 186 deletions
diff --git a/toxav/codec.c b/toxav/codec.c
index dae35d54..fd2f9f93 100644
--- a/toxav/codec.c
+++ b/toxav/codec.c
@@ -31,6 +31,7 @@
31 31
32#include <stdio.h> 32#include <stdio.h>
33#include <stdlib.h> 33#include <stdlib.h>
34#include <stdbool.h>
34#include <math.h> 35#include <math.h>
35#include <assert.h> 36#include <assert.h>
36#include <time.h> 37#include <time.h>
@@ -39,6 +40,9 @@
39#include "rtp.h" 40#include "rtp.h"
40#include "codec.h" 41#include "codec.h"
41 42
43
44#define DEFAULT_JBUF 6
45
42/* Good quality encode. */ 46/* Good quality encode. */
43#define MAX_ENCODE_TIME_US VPX_DL_GOOD_QUALITY 47#define MAX_ENCODE_TIME_US VPX_DL_GOOD_QUALITY
44#define MAX_DECODE_TIME_US 0 48#define MAX_DECODE_TIME_US 0
@@ -62,12 +66,12 @@ typedef struct {
62 Payload **packets; 66 Payload **packets;
63} PayloadBuffer; 67} PayloadBuffer;
64 68
65static _Bool buffer_full(const PayloadBuffer *b) 69static bool buffer_full(const PayloadBuffer *b)
66{ 70{
67 return (b->end + 1) % b->size == b->start; 71 return (b->end + 1) % b->size == b->start;
68} 72}
69 73
70static _Bool buffer_empty(const PayloadBuffer *b) 74static bool buffer_empty(const PayloadBuffer *b)
71{ 75{
72 return b->end == b->start; 76 return b->end == b->start;
73} 77}
@@ -121,7 +125,7 @@ static void buffer_free(PayloadBuffer *b)
121} 125}
122 126
123/* JITTER BUFFER WORK */ 127/* JITTER BUFFER WORK */
124typedef struct _JitterBuffer { 128typedef struct {
125 RTPMessage **queue; 129 RTPMessage **queue;
126 uint32_t size; 130 uint32_t size;
127 uint32_t capacity; 131 uint32_t capacity;
@@ -225,99 +229,9 @@ static RTPMessage *jbuf_read(JitterBuffer *q, int32_t *success)
225 return NULL; 229 return NULL;
226} 230}
227 231
228static int init_video_decoder(CSSession *cs)
229{
230 int rc = vpx_codec_dec_init_ver(&cs->v_decoder, VIDEO_CODEC_DECODER_INTERFACE, NULL, 0, VPX_DECODER_ABI_VERSION);
231
232 if ( rc != VPX_CODEC_OK) {
233 LOGGER_ERROR("Init video_decoder failed: %s", vpx_codec_err_to_string(rc));
234 return -1;
235 }
236
237 return 0;
238}
239
240static int init_audio_decoder(CSSession *cs)
241{
242 int rc;
243 cs->audio_decoder = opus_decoder_create(cs->audio_decoder_sample_rate, cs->audio_decoder_channels, &rc );
244
245 if ( rc != OPUS_OK ) {
246 LOGGER_ERROR("Error while starting audio decoder: %s", opus_strerror(rc));
247 return -1;
248 }
249
250 return 0;
251}
252
253static int init_video_encoder(CSSession *cs, uint16_t max_width, uint16_t max_height, uint32_t video_bitrate)
254{
255 vpx_codec_enc_cfg_t cfg;
256 int rc = vpx_codec_enc_config_default(VIDEO_CODEC_ENCODER_INTERFACE, &cfg, 0);
257
258 if (rc != VPX_CODEC_OK) {
259 LOGGER_ERROR("Failed to get config: %s", vpx_codec_err_to_string(rc));
260 return -1;
261 }
262
263 cfg.rc_target_bitrate = video_bitrate;
264 cfg.g_w = max_width;
265 cfg.g_h = max_height;
266 cfg.g_pass = VPX_RC_ONE_PASS;
267 cfg.g_error_resilient = VPX_ERROR_RESILIENT_DEFAULT | VPX_ERROR_RESILIENT_PARTITIONS;
268 cfg.g_lag_in_frames = 0;
269 cfg.kf_min_dist = 0;
270 cfg.kf_max_dist = 48;
271 cfg.kf_mode = VPX_KF_AUTO;
272
273 rc = vpx_codec_enc_init_ver(&cs->v_encoder, VIDEO_CODEC_ENCODER_INTERFACE, &cfg, 0, VPX_ENCODER_ABI_VERSION);
274
275 if ( rc != VPX_CODEC_OK) {
276 LOGGER_ERROR("Failed to initialize encoder: %s", vpx_codec_err_to_string(rc));
277 return -1;
278 }
279
280 rc = vpx_codec_control(&cs->v_encoder, VP8E_SET_CPUUSED, 8);
281
282 if ( rc != VPX_CODEC_OK) {
283 LOGGER_ERROR("Failed to set encoder control setting: %s", vpx_codec_err_to_string(rc));
284 return -1;
285 }
286
287 cs->max_width = max_width;
288 cs->max_height = max_height;
289 cs->video_bitrate = video_bitrate;
290
291 return 0;
292}
293
294static int init_audio_encoder(CSSession *cs)
295{
296 int rc = OPUS_OK;
297 cs->audio_encoder = opus_encoder_create(cs->audio_encoder_sample_rate,
298 cs->audio_encoder_channels, OPUS_APPLICATION_AUDIO, &rc);
299
300 if ( rc != OPUS_OK ) {
301 LOGGER_ERROR("Error while starting audio encoder: %s", opus_strerror(rc));
302 return -1;
303 }
304
305 rc = opus_encoder_ctl(cs->audio_encoder, OPUS_SET_BITRATE(cs->audio_encoder_bitrate));
306 232
307 if ( rc != OPUS_OK ) {
308 LOGGER_ERROR("Error while setting encoder ctl: %s", opus_strerror(rc));
309 return -1;
310 }
311 233
312 rc = opus_encoder_ctl(cs->audio_encoder, OPUS_SET_COMPLEXITY(10));
313 234
314 if ( rc != OPUS_OK ) {
315 LOGGER_ERROR("Error while setting encoder ctl: %s", opus_strerror(rc));
316 return -1;
317 }
318
319 return 0;
320}
321 235
322/* PUBLIC */ 236/* PUBLIC */
323int cs_split_video_payload(CSSession *cs, const uint8_t *payload, uint16_t length) 237int cs_split_video_payload(CSSession *cs, const uint8_t *payload, uint16_t length)
@@ -406,17 +320,17 @@ void cs_do(CSSession *cs)
406 /* Leave space for (possibly) other thread to queue more data after we read it here */ 320 /* Leave space for (possibly) other thread to queue more data after we read it here */
407 pthread_mutex_unlock(cs->queue_mutex); 321 pthread_mutex_unlock(cs->queue_mutex);
408 322
409 rc = vpx_codec_decode(&cs->v_decoder, p->data, p->size, NULL, MAX_DECODE_TIME_US); 323 rc = vpx_codec_decode(cs->v_decoder, p->data, p->size, NULL, MAX_DECODE_TIME_US);
410 free(p); 324 free(p);
411 325
412 if (rc != VPX_CODEC_OK) { 326 if (rc != VPX_CODEC_OK) {
413 LOGGER_ERROR("Error decoding video: %s", vpx_codec_err_to_string(rc)); 327 LOGGER_ERROR("Error decoding video: %s", vpx_codec_err_to_string(rc));
414 } else { 328 } else {
415 vpx_codec_iter_t iter = NULL; 329 vpx_codec_iter_t iter = NULL;
416 vpx_image_t *dest = vpx_codec_get_frame(&cs->v_decoder, &iter); 330 vpx_image_t *dest = vpx_codec_get_frame(cs->v_decoder, &iter);
417 331
418 /* Play decoded images */ 332 /* Play decoded images */
419 for (; dest; dest = vpx_codec_get_frame(&cs->v_decoder, &iter)) { 333 for (; dest; dest = vpx_codec_get_frame(cs->v_decoder, &iter)) {
420 if (cs->vcb.first) 334 if (cs->vcb.first)
421 cs->vcb.first(cs->agent, cs->call_idx, dest, cs->vcb.second); 335 cs->vcb.first(cs->agent, cs->call_idx, dest, cs->vcb.second);
422 336
@@ -430,13 +344,17 @@ void cs_do(CSSession *cs)
430 pthread_mutex_unlock(cs->queue_mutex); 344 pthread_mutex_unlock(cs->queue_mutex);
431} 345}
432 346
433int cs_set_video_encoder_resolution(CSSession *cs, uint16_t width, uint16_t height) 347int cs_set_sending_video_resolution(CSSession *cs, uint16_t width, uint16_t height)
434{ 348{
435 vpx_codec_enc_cfg_t cfg = *cs->v_encoder.config.enc; 349 if (!cs->v_encoding)
436 350 return -1;
351
352 /* TODO FIXME reference is safe? */
353 vpx_codec_enc_cfg_t cfg = *cs->v_encoder[0].config.enc;
354
437 if (cfg.g_w == width && cfg.g_h == height) 355 if (cfg.g_w == width && cfg.g_h == height)
438 return 0; 356 return 0;
439 357/*
440 if (width * height > cs->max_width * cs->max_height) { 358 if (width * height > cs->max_width * cs->max_height) {
441 vpx_codec_ctx_t v_encoder = cs->v_encoder; 359 vpx_codec_ctx_t v_encoder = cs->v_encoder;
442 360
@@ -447,12 +365,12 @@ int cs_set_video_encoder_resolution(CSSession *cs, uint16_t width, uint16_t heig
447 365
448 vpx_codec_destroy(&v_encoder); 366 vpx_codec_destroy(&v_encoder);
449 return 0; 367 return 0;
450 } 368 }*/
451 369
452 LOGGER_DEBUG("New video resolution: %u %u", width, height); 370 LOGGER_DEBUG("New video resolution: %u %u", width, height);
453 cfg.g_w = width; 371 cfg.g_w = width;
454 cfg.g_h = height; 372 cfg.g_h = height;
455 int rc = vpx_codec_enc_config_set(&cs->v_encoder, &cfg); 373 int rc = vpx_codec_enc_config_set(cs->v_encoder, &cfg);
456 374
457 if ( rc != VPX_CODEC_OK) { 375 if ( rc != VPX_CODEC_OK) {
458 LOGGER_ERROR("Failed to set encoder control setting: %s", vpx_codec_err_to_string(rc)); 376 LOGGER_ERROR("Failed to set encoder control setting: %s", vpx_codec_err_to_string(rc));
@@ -462,27 +380,107 @@ int cs_set_video_encoder_resolution(CSSession *cs, uint16_t width, uint16_t heig
462 return 0; 380 return 0;
463} 381}
464 382
465int cs_set_video_encoder_bitrate(CSSession *cs, uint32_t video_bitrate) 383int cs_set_sending_video_bitrate(CSSession *cs, uint32_t bitrate)
466{ 384{
467 vpx_codec_enc_cfg_t cfg = *cs->v_encoder.config.enc; 385 if (!cs->v_encoding)
468 386 return -1;
469 if (cfg.rc_target_bitrate == video_bitrate) 387
388 /* TODO FIXME reference is safe? */
389 vpx_codec_enc_cfg_t cfg = *cs->v_encoder[0].config.enc;
390 if (cfg.rc_target_bitrate == bitrate)
470 return 0; 391 return 0;
471 392
472 LOGGER_DEBUG("New video bitrate: %u", video_bitrate); 393 LOGGER_DEBUG("New video bitrate: %u", video_bitrate);
473 cfg.rc_target_bitrate = video_bitrate; 394 cfg.rc_target_bitrate = bitrate;
474 int rc = vpx_codec_enc_config_set(&cs->v_encoder, &cfg); 395
475 396 int rc = vpx_codec_enc_config_set(cs->v_encoder, &cfg);
476 if ( rc != VPX_CODEC_OK) { 397 if ( rc != VPX_CODEC_OK) {
477 LOGGER_ERROR("Failed to set encoder control setting: %s", vpx_codec_err_to_string(rc)); 398 LOGGER_ERROR("Failed to set encoder control setting: %s", vpx_codec_err_to_string(rc));
478 return cs_ErrorSettingVideoBitrate; 399 return cs_ErrorSettingVideoBitrate;
479 } 400 }
480 401
481 cs->video_bitrate = video_bitrate;
482 return 0; 402 return 0;
483} 403}
484 404
485CSSession *cs_new(const ToxAvCSettings *cs_self, const ToxAvCSettings *cs_peer, uint32_t jbuf_size, int has_video) 405int cs_set_sending_audio_bitrate(CSSession *cs, int32_t rate)
406{
407 if (cs->audio_encoder == NULL)
408 return -1;
409
410 int rc = opus_encoder_ctl(cs->audio_encoder, OPUS_SET_BITRATE(rate));
411
412 if ( rc != OPUS_OK ) {
413 LOGGER_ERROR("Error while setting encoder ctl: %s", opus_strerror(rc));
414 return -1;
415 }
416
417 return 0;
418}
419
420int cs_set_sending_audio_sampling_rate(CSSession* cs, int32_t rate)
421{
422 /* TODO Find a better way? */
423 if (cs->audio_encoder == NULL)
424 return -1;
425
426 int rc = OPUS_OK;
427 int last_rate = 0;
428
429 rc = opus_encoder_ctl(cs->audio_encoder, OPUS_SET_BITRATE(&last_rate));
430
431 if ( rc != OPUS_OK ) {
432 LOGGER_ERROR("Error while getting encoder ctl: %s", opus_strerror(rc));
433 return -1;
434 }
435
436 if (rate == last_rate)
437 return 0;
438
439 OpusEncoder* new_enc = opus_encoder_create(rate, cs->channels, OPUS_APPLICATION_AUDIO, &rc);
440
441 if ( rc != OPUS_OK ) {
442 LOGGER_ERROR("Error while starting audio encoder: %s", opus_strerror(rc));
443 return -1;
444 }
445
446 opus_encoder_destroy(cs->audio_encoder);
447 cs->audio_encoder = new_enc;
448 return 0;
449}
450
451int cs_set_sending_audio_channels(CSSession* cs, int32_t count)
452{
453 /* TODO Find a better way? */
454 if (cs->audio_encoder == NULL)
455 return -1;
456
457 if (cs->channels == count)
458 return 0;
459
460 int rc = OPUS_OK;
461 int bitrate = 0;
462
463 rc = opus_encoder_ctl(cs->audio_encoder, OPUS_SET_BITRATE(&bitrate));
464
465 if ( rc != OPUS_OK ) {
466 LOGGER_ERROR("Error while getting encoder ctl: %s", opus_strerror(rc));
467 return -1;
468 }
469
470 cs->channels = count;
471 OpusEncoder* new_enc = opus_encoder_create(bitrate, cs->channels, OPUS_APPLICATION_AUDIO, &rc);
472
473 if ( rc != OPUS_OK ) {
474 LOGGER_ERROR("Error while starting audio encoder: %s", opus_strerror(rc));
475 return -1;
476 }
477
478 opus_encoder_destroy(cs->audio_encoder);
479 cs->audio_encoder = new_enc;
480 return 0;
481}
482
483CSSession *cs_new(uint32_t s_audio_b, uint32_t p_audio_b, uint32_t s_video_b, uint32_t p_video_b)
486{ 484{
487 CSSession *cs = calloc(sizeof(CSSession), 1); 485 CSSession *cs = calloc(sizeof(CSSession), 1);
488 486
@@ -491,106 +489,265 @@ CSSession *cs_new(const ToxAvCSettings *cs_self, const ToxAvCSettings *cs_peer,
491 return NULL; 489 return NULL;
492 } 490 }
493 491
494 if (create_recursive_mutex(cs->queue_mutex) != 0) { 492 /* TODO this has to be exchanged in msi */
495 LOGGER_WARNING("Failed to create recursive mutex!"); 493 cs->max_video_frame_size = MAX_VIDEOFRAME_SIZE;
496 free(cs); 494 cs->video_frame_piece_size = VIDEOFRAME_PIECE_SIZE;
497 return NULL; 495
496 if (s_audio_b > 0 && 0 != cs_enable_audio_sending(cs, s_audio_b)) { /* Sending audio enabled */
497 LOGGER_WARNING("Failed to enable audio sending!");
498 goto FAILURE;
498 } 499 }
499 500
500 if ( !(cs->j_buf = jbuf_new(jbuf_size)) ) { 501 if (p_audio_b > 0 && 0 != cs_enable_audio_receiving(cs)) { /* Receiving audio enabled */
501 LOGGER_WARNING("Jitter buffer creaton failed!"); 502 LOGGER_WARNING("Failed to enable audio receiving!");
502 goto error; 503 goto FAILURE;
503 } 504 }
504 505
505 cs->audio_encoder_bitrate = cs_self->audio_bitrate; 506 if (s_video_b > 0 && 0 != cs_enable_video_sending(cs, s_video_b)) { /* Sending video enabled */
506 cs->audio_encoder_sample_rate = cs_self->audio_sample_rate; 507 LOGGER_WARNING("Failed to enable video sending!");
507 cs->audio_encoder_channels = cs_self->audio_channels; 508 goto FAILURE;
508 cs->audio_encoder_frame_duration = cs_self->audio_frame_duration; 509 }
509 510
510 cs->audio_decoder_bitrate = cs_peer->audio_bitrate; 511 if (p_video_b > 0 && 0 != cs_enable_video_receiving(cs)) { /* Receiving video enabled */
511 cs->audio_decoder_sample_rate = cs_peer->audio_sample_rate; 512 LOGGER_WARNING("Failed to enable video receiving!");
512 cs->audio_decoder_channels = cs_peer->audio_channels; 513 goto FAILURE;
513 cs->audio_decoder_frame_duration = cs_peer->audio_frame_duration;
514
515
516 cs->capabilities |= ( 0 == init_audio_encoder(cs) ) ? cs_AudioEncoding : 0;
517 cs->capabilities |= ( 0 == init_audio_decoder(cs) ) ? cs_AudioDecoding : 0;
518
519 if ( !(cs->capabilities & cs_AudioEncoding) || !(cs->capabilities & cs_AudioDecoding) ) goto error;
520
521 if ((cs->support_video = has_video)) {
522 cs->max_video_frame_size = MAX_VIDEOFRAME_SIZE;
523 cs->video_frame_piece_size = VIDEOFRAME_PIECE_SIZE;
524
525 cs->capabilities |= ( 0 == init_video_encoder(cs, cs_self->max_video_width,
526 cs_self->max_video_height, cs_self->video_bitrate) ) ? cs_VideoEncoding : 0;
527 cs->capabilities |= ( 0 == init_video_decoder(cs) ) ? cs_VideoDecoding : 0;
528
529 if ( !(cs->capabilities & cs_VideoEncoding) || !(cs->capabilities & cs_VideoDecoding) ) goto error;
530
531 if ( !(cs->frame_buf = calloc(cs->max_video_frame_size, 1)) ) goto error;
532
533 if ( !(cs->split_video_frame = calloc(cs->video_frame_piece_size + VIDEOFRAME_HEADER_SIZE, 1)) )
534 goto error;
535
536 if ( !(cs->vbuf_raw = buffer_new(VIDEO_DECODE_BUFFER_SIZE)) ) goto error;
537 } 514 }
538 515
539 return cs; 516 return cs;
540 517
541error: 518FAILURE:
542 LOGGER_WARNING("Error initializing codec session! Application might misbehave!"); 519 LOGGER_WARNING("Error initializing codec session! Application might misbehave!");
543 520
544 pthread_mutex_destroy(cs->queue_mutex); 521 cs_disable_audio_sending(cs);
545 522 cs_disable_audio_receiving(cs);
546 if ( cs->audio_encoder ) opus_encoder_destroy(cs->audio_encoder); 523 cs_disable_video_sending(cs);
547 524 cs_disable_video_receiving(cs);
548 if ( cs->audio_decoder ) opus_decoder_destroy(cs->audio_decoder); 525
549 526 free(cs);
550
551 if (has_video) {
552 if ( cs->capabilities & cs_VideoDecoding ) vpx_codec_destroy(&cs->v_decoder);
553 527
554 if ( cs->capabilities & cs_VideoEncoding ) vpx_codec_destroy(&cs->v_encoder); 528 return NULL;
529}
555 530
556 buffer_free(cs->vbuf_raw); 531void cs_kill(CSSession *cs)
532{
533 if (!cs)
534 return;
557 535
558 free(cs->frame_buf); 536 /* NOTE: queue_message() will not be called since
559 free(cs->split_video_frame); 537 * the callback is unregistered before cs_kill is called.
560 } 538 */
539
540 cs_disable_audio_sending(cs);
541 cs_disable_audio_receiving(cs);
542 cs_disable_video_sending(cs);
543 cs_disable_video_receiving(cs);
561 544
562 jbuf_free(cs->j_buf); 545 LOGGER_DEBUG("Terminated codec state: %p", cs);
563 free(cs); 546 free(cs);
547}
564 548
565 return NULL; 549int cs_enable_audio_sending(CSSession* cs, uint32_t bitrate)
550{
551 if (cs->audio_encoder)
552 return 0;
553
554 /**
555 * Encoder is initialized with default values. These values (Sampling rate, channel count)
556 * change on the fly from toxav.
557 */
558
559 int rc = OPUS_OK;
560 cs->audio_encoder = opus_encoder_create(48000, 2, OPUS_APPLICATION_AUDIO, &rc);
561
562 if ( rc != OPUS_OK ) {
563 LOGGER_ERROR("Error while starting audio encoder: %s", opus_strerror(rc));
564 return -1;
565 }
566
567 rc = opus_encoder_ctl(cs->audio_encoder, OPUS_SET_BITRATE(bitrate));
568
569 if ( rc != OPUS_OK ) {
570 LOGGER_ERROR("Error while setting encoder ctl: %s", opus_strerror(rc));
571 goto FAILURE;
572 }
573
574 rc = opus_encoder_ctl(cs->audio_encoder, OPUS_SET_COMPLEXITY(10));
575
576 if ( rc != OPUS_OK ) {
577 LOGGER_ERROR("Error while setting encoder ctl: %s", opus_strerror(rc));
578 goto FAILURE;
579 }
580
581 cs->channels = 2;
582 return 0;
583
584FAILURE:
585 cs_disable_audio_sending(cs);
586 return -1;
566} 587}
567 588
568void cs_kill(CSSession *cs) 589int cs_enable_audio_receiving(CSSession* cs)
569{ 590{
570 if (!cs) return; 591 if (cs->audio_decoder)
592 return 0;
593
594 /**
595 * Decoder is initialized with default values. These values (Sampling rate, channel count)
596 * change on the fly from toxav.
597 */
598
599 int rc;
600 cs->audio_decoder = opus_decoder_create(48000, 2, &rc );
601
602 if ( rc != OPUS_OK ) {
603 LOGGER_ERROR("Error while starting audio decoder: %s", opus_strerror(rc));
604 return -1;
605 }
606
607
608 if ( !(cs->j_buf = jbuf_new(DEFAULT_JBUF)) ) {
609 LOGGER_WARNING("Jitter buffer creaton failed!");
610 opus_decoder_destroy(cs->audio_decoder);
611 cs->audio_decoder = NULL;
612 return -1;
613 }
614
615
616 return 0;
617}
571 618
572 /* queue_message will not be called since it's unregistered before cs_kill is called */ 619int cs_enable_video_sending(CSSession* cs, uint32_t bitrate)
573 pthread_mutex_destroy(cs->queue_mutex); 620{
621 if (cs->v_encoding)
622 return 0;
623
624 vpx_codec_enc_cfg_t cfg;
625 int rc = vpx_codec_enc_config_default(VIDEO_CODEC_ENCODER_INTERFACE, &cfg, 0);
626
627 if (rc != VPX_CODEC_OK) {
628 LOGGER_ERROR("Failed to get config: %s", vpx_codec_err_to_string(rc));
629 return -1;
630 }
631
632 rc = vpx_codec_enc_init_ver(cs->v_encoder, VIDEO_CODEC_ENCODER_INTERFACE, &cfg, 0,
633 VPX_ENCODER_ABI_VERSION);
634
635 if ( rc != VPX_CODEC_OK) {
636 LOGGER_ERROR("Failed to initialize encoder: %s", vpx_codec_err_to_string(rc));
637 return -1;
638 }
639
640 /* So that we can use cs_disable_video_sending to clean up */
641 cs->v_encoding = true;
642
643 if ( !(cs->split_video_frame = calloc(cs->video_frame_piece_size + VIDEOFRAME_HEADER_SIZE, 1)) )
644 goto FAILURE;
645
646 cfg.rc_target_bitrate = bitrate;
647 cfg.g_w = 800;
648 cfg.g_h = 600;
649 cfg.g_pass = VPX_RC_ONE_PASS;
650 cfg.g_error_resilient = VPX_ERROR_RESILIENT_DEFAULT | VPX_ERROR_RESILIENT_PARTITIONS;
651 cfg.g_lag_in_frames = 0;
652 cfg.kf_min_dist = 0;
653 cfg.kf_max_dist = 48;
654 cfg.kf_mode = VPX_KF_AUTO;
655
656
657 rc = vpx_codec_control(cs->v_encoder, VP8E_SET_CPUUSED, 8);
658
659 if ( rc != VPX_CODEC_OK) {
660 LOGGER_ERROR("Failed to set encoder control setting: %s", vpx_codec_err_to_string(rc));
661 goto FAILURE;
662 }
663
664 return 0;
665
666FAILURE:
667 cs_disable_video_sending(cs);
668 return -1;
669}
574 670
671int cs_enable_video_receiving(CSSession* cs)
672{
673 if (cs->v_decoding)
674 return 0;
675
676 if (create_recursive_mutex(cs->queue_mutex) != 0) {
677 LOGGER_WARNING("Failed to create recursive mutex!");
678 return -1;
679 }
680
681 int rc = vpx_codec_dec_init_ver(cs->v_decoder, VIDEO_CODEC_DECODER_INTERFACE,
682 NULL, 0, VPX_DECODER_ABI_VERSION);
683
684 if ( rc != VPX_CODEC_OK) {
685 LOGGER_ERROR("Init video_decoder failed: %s", vpx_codec_err_to_string(rc));
686
687 pthread_mutex_destroy(cs->queue_mutex);
688 return -1;
689 }
690
691 /* So that we can use cs_disable_video_sending to clean up */
692 cs->v_decoding = true;
693
694 if ( !(cs->frame_buf = calloc(cs->max_video_frame_size, 1)) )
695 goto FAILURE;
696
697 if ( !(cs->vbuf_raw = buffer_new(VIDEO_DECODE_BUFFER_SIZE)) )
698 goto FAILURE;
699
700 return 0;
701
702FAILURE:
703 cs_disable_video_receiving(cs);
704 return -1;
705}
575 706
576 if ( cs->audio_encoder ) 707void cs_disable_audio_sending(CSSession* cs)
708{
709 if ( cs->audio_encoder ) {
577 opus_encoder_destroy(cs->audio_encoder); 710 opus_encoder_destroy(cs->audio_encoder);
711 cs->audio_encoder = NULL;
712 cs->channels = 0;
713 }
714}
578 715
579 if ( cs->audio_decoder ) 716void cs_disable_audio_receiving(CSSession* cs)
717{
718 if ( cs->audio_decoder ) {
580 opus_decoder_destroy(cs->audio_decoder); 719 opus_decoder_destroy(cs->audio_decoder);
720 cs->audio_decoder = NULL;
721 jbuf_free(cs->j_buf);
722 cs->j_buf = NULL;
723 }
724}
581 725
582 if ( cs->capabilities & cs_VideoDecoding ) 726void cs_disable_video_sending(CSSession* cs)
583 vpx_codec_destroy(&cs->v_decoder); 727{
584 728 if (cs->v_encoding) {
585 if ( cs->capabilities & cs_VideoEncoding ) 729 cs->v_encoding = false;
586 vpx_codec_destroy(&cs->v_encoder); 730
587 731 free(cs->split_video_frame);
588 jbuf_free(cs->j_buf); 732 cs->split_video_frame = NULL;
589 buffer_free(cs->vbuf_raw); 733
590 free(cs->frame_buf); 734 vpx_codec_destroy(cs->v_encoder);
735 }
736}
591 737
592 LOGGER_DEBUG("Terminated codec state: %p", cs); 738void cs_disable_video_receiving(CSSession* cs)
593 free(cs); 739{
740 if (cs->v_decoding) {
741 cs->v_decoding = false;
742
743 buffer_free(cs->vbuf_raw);
744 cs->vbuf_raw = NULL;
745 free(cs->frame_buf);
746 cs->frame_buf = NULL;
747
748 vpx_codec_destroy(cs->v_decoder);
749 pthread_mutex_destroy(cs->queue_mutex);
750 }
594} 751}
595 752
596 753