summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorirungentoo <irungentoo@gmail.com>2014-11-07 21:30:26 -0500
committerirungentoo <irungentoo@gmail.com>2014-11-07 21:30:26 -0500
commitd7f1f223eeaea9abcdd7e0395741dfa4a46bee7c (patch)
tree4239226a9c4c08eb45561125777993ed0d264109
parent6d90808c15c853a0f6e63554133ce89108b0b227 (diff)
First commit of actual A/V code for group chats.
-rw-r--r--toxav/Makefile.inc2
-rw-r--r--toxav/group.c241
-rw-r--r--toxav/group.h32
3 files changed, 275 insertions, 0 deletions
diff --git a/toxav/Makefile.inc b/toxav/Makefile.inc
index de8ef8ff..0b4b869d 100644
--- a/toxav/Makefile.inc
+++ b/toxav/Makefile.inc
@@ -8,6 +8,8 @@ libtoxav_la_SOURCES = ../toxav/rtp.h \
8 ../toxav/rtp.c \ 8 ../toxav/rtp.c \
9 ../toxav/msi.h \ 9 ../toxav/msi.h \
10 ../toxav/msi.c \ 10 ../toxav/msi.c \
11 ../toxav/group.h \
12 ../toxav/group.c \
11 ../toxav/codec.h \ 13 ../toxav/codec.h \
12 ../toxav/codec.c \ 14 ../toxav/codec.c \
13 ../toxav/toxav.h \ 15 ../toxav/toxav.h \
diff --git a/toxav/group.c b/toxav/group.c
new file mode 100644
index 00000000..503adc57
--- /dev/null
+++ b/toxav/group.c
@@ -0,0 +1,241 @@
1/** groupav.h
2 *
3 * Copyright (C) 2014 Tox project All Rights Reserved.
4 *
5 * This file is part of Tox.
6 *
7 * Tox is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * Tox is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with Tox. If not, see <http://www.gnu.org/licenses/>.
19 */
20
21#ifdef HAVE_CONFIG_H
22#include "config.h"
23#endif
24
25#include "group.h"
26#include "../toxcore/logger.h"
27
28typedef struct {
29 uint16_t sequnum;
30 uint16_t length;
31 uint8_t data[];
32} Group_Audio_Packet;
33
34typedef struct {
35 Group_Audio_Packet **queue;
36 uint32_t size;
37 uint32_t capacity;
38 uint16_t bottom;
39 uint16_t top;
40} Group_JitterBuffer;
41
42static Group_JitterBuffer *create_queue(unsigned int capacity)
43{
44 unsigned int size = 1;
45
46 while (size <= capacity) {
47 size *= 2;
48 }
49
50 Group_JitterBuffer *q;
51
52 if ( !(q = calloc(sizeof(Group_JitterBuffer), 1)) ) return NULL;
53
54 if (!(q->queue = calloc(sizeof(Group_Audio_Packet *), size))) {
55 free(q);
56 return NULL;
57 }
58
59 q->size = size;
60 q->capacity = capacity;
61 return q;
62}
63
64static void clear_queue(Group_JitterBuffer *q)
65{
66 for (; q->bottom != q->top; ++q->bottom) {
67 if (q->queue[q->bottom % q->size]) {
68 free(q->queue[q->bottom % q->size]);
69 q->queue[q->bottom % q->size] = NULL;
70 }
71 }
72}
73
74static void terminate_queue(Group_JitterBuffer *q)
75{
76 if (!q) return;
77
78 clear_queue(q);
79 free(q->queue);
80 free(q);
81}
82
83static void queue(Group_JitterBuffer *q, Group_Audio_Packet *pk)
84{
85 uint16_t sequnum = pk->sequnum;
86
87 unsigned int num = sequnum % q->size;
88
89 if ((uint32_t)(sequnum - q->bottom) > q->size) {
90 clear_queue(q);
91 q->bottom = sequnum;
92 q->queue[num] = pk;
93 q->top = sequnum + 1;
94 return;
95 }
96
97 if (q->queue[num])
98 return;
99
100 q->queue[num] = pk;
101
102 if ((sequnum - q->bottom) >= (q->top - q->bottom))
103 q->top = sequnum + 1;
104}
105
106/* success is 0 when there is nothing to dequeue, 1 when there's a good packet, 2 when there's a lost packet */
107static Group_Audio_Packet *dequeue(Group_JitterBuffer *q, int *success)
108{
109 if (q->top == q->bottom) {
110 *success = 0;
111 return NULL;
112 }
113
114 unsigned int num = q->bottom % q->size;
115
116 if (q->queue[num]) {
117 Group_Audio_Packet *ret = q->queue[num];
118 q->queue[num] = NULL;
119 ++q->bottom;
120 *success = 1;
121 return ret;
122 }
123
124 if ((uint32_t)(q->top - q->bottom) > q->capacity) {
125 ++q->bottom;
126 *success = 2;
127 return NULL;
128 }
129
130 *success = 0;
131 return NULL;
132}
133
134
135typedef struct {
136 OpusEncoder *audio_encoder;
137
138 unsigned int audio_channels, audio_sample_rate, audio_bitrate;
139} Group_AV;
140
141typedef struct {
142 Group_JitterBuffer *buffer;
143
144 OpusDecoder *audio_decoder;
145} Group_Peer_AV;
146
147static void kill_group_av(Group_AV *group_av)
148{
149 opus_encoder_destroy(group_av->audio_encoder);
150 free(group_av);
151}
152
153static Group_AV *new_group_av(unsigned int audio_channels, unsigned int audio_sample_rate, unsigned int audio_bitrate)
154{
155 Group_AV *group_av = calloc(1, sizeof(Group_AV));
156
157 int rc = OPUS_OK;
158 group_av->audio_encoder = opus_encoder_create(audio_sample_rate, audio_channels, OPUS_APPLICATION_AUDIO, &rc);
159
160 if ( rc != OPUS_OK ) {
161 LOGGER_ERROR("Error while starting audio encoder: %s", opus_strerror(rc));
162 free(group_av);
163 return NULL;
164 }
165
166 rc = opus_encoder_ctl(group_av->audio_encoder, OPUS_SET_BITRATE(audio_bitrate));
167
168 if ( rc != OPUS_OK ) {
169 LOGGER_ERROR("Error while setting encoder ctl: %s", opus_strerror(rc));
170 opus_encoder_destroy(group_av->audio_encoder);
171 free(group_av);
172 return NULL;
173 }
174
175 rc = opus_encoder_ctl(group_av->audio_encoder, OPUS_SET_COMPLEXITY(10));
176
177 if ( rc != OPUS_OK ) {
178 LOGGER_ERROR("Error while setting encoder ctl: %s", opus_strerror(rc));
179 opus_encoder_destroy(group_av->audio_encoder);
180 free(group_av);
181 return NULL;
182 }
183
184 group_av->audio_channels = audio_channels;
185 group_av->audio_sample_rate = audio_sample_rate;
186 group_av->audio_bitrate = audio_bitrate;
187 return 0;
188}
189
190static void group_av_peer_new(void *object, int groupnumber, int friendgroupnumber)
191{
192
193
194}
195
196static void group_av_peer_delete(void *object, int groupnumber, int friendgroupnumber, void *peer_object)
197{
198
199
200}
201
202static int groupchat_enable_av(Group_Chats *g_c, int groupnumber)
203{
204 Group_AV *group_av = new_group_av(1, 48000, 64000); //TODO: Use variables instead.
205
206 if (group_av == NULL) {
207 return -1;
208 }
209
210 if (group_set_object(g_c, groupnumber, group_av) == -1
211 || callback_groupchat_peer_new(g_c, groupnumber, group_av_peer_new) == -1
212 || callback_groupchat_peer_delete(g_c, groupnumber, group_av_peer_delete) == -1) {
213 kill_group_av(group_av);
214 return -1;
215 }
216
217 return 0;
218}
219
220/* Create a new toxav group.
221 *
222 * return group number on success.
223 * return -1 on failure.
224 */
225int add_av_groupchat(Group_Chats *g_c)
226{
227 int groupnumber = add_groupchat(g_c);
228
229 if (groupnumber == -1) {
230 return -1;
231 }
232
233 if (groupchat_enable_av(g_c, groupnumber) == -1) {
234 del_groupchat(g_c, groupnumber);
235 return -1;
236 }
237
238 return groupnumber;
239}
240
241
diff --git a/toxav/group.h b/toxav/group.h
new file mode 100644
index 00000000..19bb0483
--- /dev/null
+++ b/toxav/group.h
@@ -0,0 +1,32 @@
1/** groupav.c
2 *
3 * Copyright (C) 2014 Tox project All Rights Reserved.
4 *
5 * This file is part of Tox.
6 *
7 * Tox is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * Tox is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with Tox. If not, see <http://www.gnu.org/licenses/>.
19 */
20
21/* Audio encoding/decoding */
22#include <opus.h>
23
24#include "../toxcore/group.h"
25
26/* Create a new toxav group.
27 *
28 * return group number on success.
29 * return -1 on failure.
30 */
31int add_av_groupchat(Group_Chats *g_c);
32