summaryrefslogtreecommitdiff
path: root/toxav/codec.c
diff options
context:
space:
mode:
authormannol <eniz_vukovic@hotmail.com>2015-04-13 01:45:53 +0200
committermannol <eniz_vukovic@hotmail.com>2015-04-13 01:45:53 +0200
commit2465f486acd90ed8395c8a83a13af09ecd024c98 (patch)
tree4abe53d39eb07a45e5ed4d8894b7ae038e2bb705 /toxav/codec.c
parentb2d88a4544a81a217db18b60d91a44d85821db3d (diff)
Started custom RTCP
Diffstat (limited to 'toxav/codec.c')
-rw-r--r--toxav/codec.c98
1 files changed, 11 insertions, 87 deletions
diff --git a/toxav/codec.c b/toxav/codec.c
index d55cc345..671be1ac 100644
--- a/toxav/codec.c
+++ b/toxav/codec.c
@@ -46,78 +46,13 @@
46#define MAX_VIDEOFRAME_SIZE 0x40000 /* 256KiB */ 46#define MAX_VIDEOFRAME_SIZE 0x40000 /* 256KiB */
47#define VIDEOFRAME_HEADER_SIZE 0x2 47#define VIDEOFRAME_HEADER_SIZE 0x2
48 48
49/* FIXME: Might not be enough */ 49/* FIXME: Might not be enough? NOTE: I think it is enough */
50#define VIDEO_DECODE_BUFFER_SIZE 20 50#define VIDEO_DECODE_BUFFER_SIZE 20
51 51
52#define ARRAY(TYPE__) struct { uint16_t size; TYPE__ data[]; } 52#define ARRAY(TYPE__) struct { uint16_t size; TYPE__ data[]; }
53 53
54typedef ARRAY(uint8_t) Payload; 54typedef ARRAY(uint8_t) Payload;
55 55
56typedef struct {
57 uint16_t size; /* Max size */
58 uint16_t start;
59 uint16_t end;
60 Payload **packets;
61} PayloadBuffer;
62
63static bool buffer_full(const PayloadBuffer *b)
64{
65 return (b->end + 1) % b->size == b->start;
66}
67
68static bool buffer_empty(const PayloadBuffer *b)
69{
70 return b->end == b->start;
71}
72
73static void buffer_write(PayloadBuffer *b, Payload *p)
74{
75 b->packets[b->end] = p;
76 b->end = (b->end + 1) % b->size;
77
78 if (b->end == b->start) b->start = (b->start + 1) % b->size; /* full, overwrite */
79}
80
81static void buffer_read(PayloadBuffer *b, Payload **p)
82{
83 *p = b->packets[b->start];
84 b->start = (b->start + 1) % b->size;
85}
86
87static void buffer_clear(PayloadBuffer *b)
88{
89 while (!buffer_empty(b)) {
90 Payload *p;
91 buffer_read(b, &p);
92 free(p);
93 }
94}
95
96static PayloadBuffer *buffer_new(int size)
97{
98 PayloadBuffer *buf = calloc(sizeof(PayloadBuffer), 1);
99
100 if (!buf) return NULL;
101
102 buf->size = size + 1; /* include empty elem */
103
104 if (!(buf->packets = calloc(buf->size, sizeof(Payload *)))) {
105 free(buf);
106 return NULL;
107 }
108
109 return buf;
110}
111
112static void buffer_free(PayloadBuffer *b)
113{
114 if (b) {
115 buffer_clear(b);
116 free(b->packets);
117 free(b);
118 }
119}
120
121/* JITTER BUFFER WORK */ 56/* JITTER BUFFER WORK */
122typedef struct JitterBuffer_s { 57typedef struct JitterBuffer_s {
123 RTPMessage **queue; 58 RTPMessage **queue;
@@ -318,7 +253,7 @@ bool reconfigure_audio_decoder(CSession* cs, int32_t sampling_rate, int8_t chann
318 int status; 253 int status;
319 OpusDecoder* new_dec = opus_decoder_create(sampling_rate, channels, &status ); 254 OpusDecoder* new_dec = opus_decoder_create(sampling_rate, channels, &status );
320 if ( status != OPUS_OK ) { 255 if ( status != OPUS_OK ) {
321 LOGGER_ERROR("Error while starting audio decoder: %s", opus_strerror(status)); 256 LOGGER_ERROR("Error while starting audio decoder(%d %d): %s", sampling_rate, channels, opus_strerror(status));
322 return false; 257 return false;
323 } 258 }
324 259
@@ -336,7 +271,6 @@ bool reconfigure_audio_decoder(CSession* cs, int32_t sampling_rate, int8_t chann
336} 271}
337 272
338/* PUBLIC */ 273/* PUBLIC */
339
340void cs_do(CSession *cs) 274void cs_do(CSession *cs)
341{ 275{
342 /* Codec session should always be protected by call mutex so no need to check for cs validity 276 /* Codec session should always be protected by call mutex so no need to check for cs validity
@@ -416,9 +350,9 @@ void cs_do(CSession *cs)
416 } 350 }
417 351
418 /********************* VIDEO *********************/ 352 /********************* VIDEO *********************/
419 if (cs->vbuf_raw && !buffer_empty(cs->vbuf_raw)) { 353 if (cs->vbuf_raw && !rb_empty(cs->vbuf_raw)) {
420 /* Decode video */ 354 /* Decode video */
421 buffer_read(cs->vbuf_raw, &p); 355 rb_read(cs->vbuf_raw, (void**)&p);
422 356
423 /* Leave space for (possibly) other thread to queue more data after we read it here */ 357 /* Leave space for (possibly) other thread to queue more data after we read it here */
424 LOGGED_UNLOCK(cs->queue_mutex); 358 LOGGED_UNLOCK(cs->queue_mutex);
@@ -447,7 +381,6 @@ void cs_do(CSession *cs)
447 381
448 LOGGED_UNLOCK(cs->queue_mutex); 382 LOGGED_UNLOCK(cs->queue_mutex);
449} 383}
450
451CSession *cs_new(uint32_t peer_video_frame_piece_size) 384CSession *cs_new(uint32_t peer_video_frame_piece_size)
452{ 385{
453 CSession *cs = calloc(sizeof(CSession), 1); 386 CSession *cs = calloc(sizeof(CSession), 1);
@@ -510,7 +443,7 @@ CSession *cs_new(uint32_t peer_video_frame_piece_size)
510 goto AUDIO_DECODER_CLEANUP; 443 goto AUDIO_DECODER_CLEANUP;
511 } 444 }
512 445
513 if ( !(cs->vbuf_raw = buffer_new(VIDEO_DECODE_BUFFER_SIZE)) ) { 446 if ( !(cs->vbuf_raw = rb_new(VIDEO_DECODE_BUFFER_SIZE)) ) {
514 free(cs->frame_buf); 447 free(cs->frame_buf);
515 vpx_codec_destroy(cs->v_decoder); 448 vpx_codec_destroy(cs->v_decoder);
516 goto AUDIO_DECODER_CLEANUP; 449 goto AUDIO_DECODER_CLEANUP;
@@ -542,7 +475,7 @@ CSession *cs_new(uint32_t peer_video_frame_piece_size)
542 return cs; 475 return cs;
543 476
544VIDEO_DECODER_CLEANUP: 477VIDEO_DECODER_CLEANUP:
545 buffer_free(cs->vbuf_raw); 478 rb_free(cs->vbuf_raw);
546 free(cs->frame_buf); 479 free(cs->frame_buf);
547 vpx_codec_destroy(cs->v_decoder); 480 vpx_codec_destroy(cs->v_decoder);
548AUDIO_DECODER_CLEANUP: 481AUDIO_DECODER_CLEANUP:
@@ -553,7 +486,6 @@ FAILURE:
553 free(cs); 486 free(cs);
554 return NULL; 487 return NULL;
555} 488}
556
557void cs_kill(CSession *cs) 489void cs_kill(CSession *cs)
558{ 490{
559 if (!cs) 491 if (!cs)
@@ -567,22 +499,21 @@ void cs_kill(CSession *cs)
567 vpx_codec_destroy(cs->v_decoder); 499 vpx_codec_destroy(cs->v_decoder);
568 opus_encoder_destroy(cs->audio_encoder); 500 opus_encoder_destroy(cs->audio_encoder);
569 opus_decoder_destroy(cs->audio_decoder); 501 opus_decoder_destroy(cs->audio_decoder);
570 buffer_free(cs->vbuf_raw); 502 rb_free(cs->vbuf_raw);
571 jbuf_free(cs->j_buf); 503 jbuf_free(cs->j_buf);
572 free(cs->frame_buf); 504 free(cs->frame_buf);
505 free(cs->split_video_frame);
573 506
574 pthread_mutex_destroy(cs->queue_mutex); 507 pthread_mutex_destroy(cs->queue_mutex);
575 508
576 LOGGER_DEBUG("Terminated codec state: %p", cs); 509 LOGGER_DEBUG("Terminated codec state: %p", cs);
577 free(cs); 510 free(cs);
578} 511}
579
580void cs_init_video_splitter_cycle(CSession* cs) 512void cs_init_video_splitter_cycle(CSession* cs)
581{ 513{
582 cs->split_video_frame[0] = cs->frameid_out++; 514 cs->split_video_frame[0] = cs->frameid_out++;
583 cs->split_video_frame[1] = 0; 515 cs->split_video_frame[1] = 0;
584} 516}
585
586int cs_update_video_splitter_cycle(CSession *cs, const uint8_t *payload, uint16_t length) 517int cs_update_video_splitter_cycle(CSession *cs, const uint8_t *payload, uint16_t length)
587{ 518{
588 cs->processing_video_frame = payload; 519 cs->processing_video_frame = payload;
@@ -590,7 +521,6 @@ int cs_update_video_splitter_cycle(CSession *cs, const uint8_t *payload, uint16_
590 521
591 return ((length - 1) / VIDEOFRAME_PIECE_SIZE) + 1; 522 return ((length - 1) / VIDEOFRAME_PIECE_SIZE) + 1;
592} 523}
593
594const uint8_t *cs_iterate_split_video_frame(CSession *cs, uint16_t *size) 524const uint8_t *cs_iterate_split_video_frame(CSession *cs, uint16_t *size)
595{ 525{
596 if (!cs || !size) return NULL; 526 if (!cs || !size) return NULL;
@@ -616,9 +546,6 @@ const uint8_t *cs_iterate_split_video_frame(CSession *cs, uint16_t *size)
616 546
617 return cs->split_video_frame; 547 return cs->split_video_frame;
618} 548}
619
620
621
622int cs_reconfigure_video_encoder(CSession* cs, int32_t bitrate, uint16_t width, uint16_t height) 549int cs_reconfigure_video_encoder(CSession* cs, int32_t bitrate, uint16_t width, uint16_t height)
623{ 550{
624 vpx_codec_enc_cfg_t cfg = *cs->v_encoder[0].config.enc; 551 vpx_codec_enc_cfg_t cfg = *cs->v_encoder[0].config.enc;
@@ -637,7 +564,6 @@ int cs_reconfigure_video_encoder(CSession* cs, int32_t bitrate, uint16_t width,
637 564
638 return 0; 565 return 0;
639} 566}
640
641int cs_reconfigure_audio_encoder(CSession* cs, int32_t bitrate, int32_t sampling_rate, uint8_t channels) 567int cs_reconfigure_audio_encoder(CSession* cs, int32_t bitrate, int32_t sampling_rate, uint8_t channels)
642{ 568{
643 /* Values are checked in toxav.c */ 569 /* Values are checked in toxav.c */
@@ -667,8 +593,6 @@ int cs_reconfigure_audio_encoder(CSession* cs, int32_t bitrate, int32_t sampling
667 LOGGER_DEBUG ("Reconfigured audio encoder br: %d sr: %d cc:%d", bitrate, sampling_rate, channels); 593 LOGGER_DEBUG ("Reconfigured audio encoder br: %d sr: %d cc:%d", bitrate, sampling_rate, channels);
668 return 0; 594 return 0;
669} 595}
670
671
672/* Called from RTP */ 596/* Called from RTP */
673void queue_message(RTPSession *session, RTPMessage *msg) 597void queue_message(RTPSession *session, RTPMessage *msg)
674{ 598{
@@ -705,10 +629,10 @@ void queue_message(RTPSession *session, RTPMessage *msg)
705 if (p) { 629 if (p) {
706 LOGGED_LOCK(cs->queue_mutex); 630 LOGGED_LOCK(cs->queue_mutex);
707 631
708 if (buffer_full(cs->vbuf_raw)) { 632 if (rb_full(cs->vbuf_raw)) {
709 LOGGER_DEBUG("Dropped video frame"); 633 LOGGER_DEBUG("Dropped video frame");
710 Payload *tp; 634 Payload *tp;
711 buffer_read(cs->vbuf_raw, &tp); 635 rb_read(cs->vbuf_raw, (void**)&tp);
712 free(tp); 636 free(tp);
713 } else { 637 } else {
714 p->size = cs->frame_size; 638 p->size = cs->frame_size;
@@ -720,7 +644,7 @@ void queue_message(RTPSession *session, RTPMessage *msg)
720 cs->lcfd = t_lcfd > 100 ? cs->lcfd : t_lcfd; 644 cs->lcfd = t_lcfd > 100 ? cs->lcfd : t_lcfd;
721 cs->linfts = current_time_monotonic(); 645 cs->linfts = current_time_monotonic();
722 646
723 buffer_write(cs->vbuf_raw, p); 647 rb_write(cs->vbuf_raw, p);
724 LOGGED_UNLOCK(cs->queue_mutex); 648 LOGGED_UNLOCK(cs->queue_mutex);
725 } else { 649 } else {
726 LOGGER_WARNING("Allocation failed! Program might misbehave!"); 650 LOGGER_WARNING("Allocation failed! Program might misbehave!");