mirror of https://github.com/irungentoo/toxcore
Group audio might work now but I have not tested anything yet.
parent
97742ed1e9
commit
94ac524374
|
@ -1001,11 +1001,17 @@ void print_help(char *prog_name)
|
|||
puts(" -f keyfile [Optional] Specify a keyfile to read from and write to.");
|
||||
}
|
||||
|
||||
void print_invite(Tox *m, int friendnumber, const uint8_t *data, uint16_t length, void *userdata)
|
||||
void print_invite(Tox *m, int friendnumber, uint8_t type, const uint8_t *data, uint16_t length, void *userdata)
|
||||
{
|
||||
char msg[256];
|
||||
sprintf(msg, "[i] received group chat invite from: %u, auto accepting and joining. group number: %u", friendnumber,
|
||||
tox_join_groupchat(m, friendnumber, data, length));
|
||||
|
||||
if (type == TOX_GROUPCHAT_TYPE_TEXT) {
|
||||
sprintf(msg, "[i] received group chat invite from: %u, auto accepting and joining. group number: %u", friendnumber,
|
||||
tox_join_groupchat(m, friendnumber, data, length));
|
||||
} else {
|
||||
sprintf(msg, "[i] Group chat invite received of type %u that could not be accepted by ntox.", type);
|
||||
}
|
||||
|
||||
new_lines(msg);
|
||||
}
|
||||
|
||||
|
|
184
toxav/group.c
184
toxav/group.c
|
@ -135,19 +135,25 @@ static Group_Audio_Packet *dequeue(Group_JitterBuffer *q, int *success)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
typedef struct {
|
||||
Group_Chats *g_c;
|
||||
OpusEncoder *audio_encoder;
|
||||
|
||||
unsigned int audio_channels, audio_sample_rate, audio_bitrate;
|
||||
|
||||
uint16_t audio_sequnum;
|
||||
|
||||
void (*audio_data)(Messenger *m, int groupnumber, int peernumber, const int16_t *pcm, unsigned int samples,
|
||||
uint8_t channels, unsigned int sample_rate, void *userdata);
|
||||
void *userdata;
|
||||
} Group_AV;
|
||||
|
||||
typedef struct {
|
||||
Group_JitterBuffer *buffer;
|
||||
|
||||
OpusDecoder *audio_decoder;
|
||||
int decoder_channels;
|
||||
unsigned int last_packet_samples;
|
||||
} Group_Peer_AV;
|
||||
|
||||
static void kill_group_av(Group_AV *group_av)
|
||||
|
@ -156,8 +162,13 @@ static void kill_group_av(Group_AV *group_av)
|
|||
free(group_av);
|
||||
}
|
||||
|
||||
static Group_AV *new_group_av(unsigned int audio_channels, unsigned int audio_sample_rate, unsigned int audio_bitrate)
|
||||
static Group_AV *new_group_av(Group_Chats *g_c, unsigned int audio_channels, unsigned int audio_sample_rate,
|
||||
unsigned int audio_bitrate, void (*audio_callback)(Messenger *, int, int, const int16_t *, unsigned int, uint8_t,
|
||||
unsigned int, void *), void *userdata)
|
||||
{
|
||||
if (!g_c)
|
||||
return NULL;
|
||||
|
||||
Group_AV *group_av = calloc(1, sizeof(Group_AV));
|
||||
|
||||
int rc = OPUS_OK;
|
||||
|
@ -190,6 +201,10 @@ static Group_AV *new_group_av(unsigned int audio_channels, unsigned int audio_sa
|
|||
group_av->audio_channels = audio_channels;
|
||||
group_av->audio_sample_rate = audio_sample_rate;
|
||||
group_av->audio_bitrate = audio_bitrate;
|
||||
group_av->g_c = g_c;
|
||||
|
||||
group_av->audio_data = audio_callback;
|
||||
group_av->userdata = userdata;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -217,6 +232,100 @@ static void group_av_peer_delete(void *object, int groupnumber, int friendgroupn
|
|||
free(peer_object);
|
||||
}
|
||||
|
||||
static int decode_audio_packet(Group_AV *group_av, Group_Peer_AV *peer_av, int groupnumber, int friendgroupnumber)
|
||||
{
|
||||
if (!group_av || !peer_av)
|
||||
return -1;
|
||||
|
||||
int success;
|
||||
Group_Audio_Packet *pk = dequeue(peer_av->buffer, &success);
|
||||
|
||||
if (success == 0)
|
||||
return -1;
|
||||
|
||||
int16_t *out_audio = NULL;
|
||||
unsigned int out_audio_samples = 0;
|
||||
|
||||
if (success == 1) {
|
||||
int channels = opus_packet_get_nb_channels(pk->data);
|
||||
|
||||
if (channels == OPUS_INVALID_PACKET) {
|
||||
free(pk);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (channels != 1 && channels != 2) {
|
||||
free(pk);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (channels != peer_av->decoder_channels) {
|
||||
if (peer_av->audio_decoder) {
|
||||
opus_decoder_destroy(peer_av->audio_decoder);
|
||||
peer_av->audio_decoder = NULL;
|
||||
}
|
||||
|
||||
int rc;
|
||||
peer_av->audio_decoder = opus_decoder_create(group_av->audio_sample_rate, channels, &rc);
|
||||
|
||||
if ( rc != OPUS_OK ) {
|
||||
LOGGER_ERROR("Error while starting audio decoder: %s", opus_strerror(rc));
|
||||
free(pk);
|
||||
return -1;
|
||||
}
|
||||
|
||||
peer_av->decoder_channels = channels;
|
||||
}
|
||||
|
||||
int num_samples = opus_decoder_get_nb_samples(peer_av->audio_decoder, pk->data, pk->length);
|
||||
|
||||
out_audio = malloc(num_samples * peer_av->decoder_channels * sizeof(int16_t));
|
||||
|
||||
if (!out_audio) {
|
||||
free(pk);
|
||||
return -1;
|
||||
}
|
||||
|
||||
out_audio_samples = opus_decode(peer_av->audio_decoder, pk->data, pk->length, out_audio, num_samples, 0);
|
||||
free(pk);
|
||||
|
||||
if (out_audio_samples <= 0)
|
||||
return -1;
|
||||
|
||||
peer_av->last_packet_samples = out_audio_samples;
|
||||
} else {
|
||||
if (!peer_av->audio_decoder)
|
||||
return -1;
|
||||
|
||||
if (!peer_av->last_packet_samples)
|
||||
return -1;
|
||||
|
||||
out_audio = malloc(peer_av->last_packet_samples * peer_av->decoder_channels * sizeof(int16_t));
|
||||
|
||||
if (!out_audio) {
|
||||
free(pk);
|
||||
return -1;
|
||||
}
|
||||
|
||||
out_audio_samples = opus_decode(peer_av->audio_decoder, NULL, 0, out_audio, peer_av->last_packet_samples, 1);
|
||||
|
||||
if (out_audio_samples <= 0)
|
||||
return -1;
|
||||
|
||||
}
|
||||
|
||||
if (out_audio) {
|
||||
//TODO callback
|
||||
/*
|
||||
if (group_av->audio_data)
|
||||
audio_data(
|
||||
*/
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int handle_group_audio_packet(void *object, int groupnumber, int friendgroupnumber, void *peer_object,
|
||||
const uint8_t *packet, uint16_t length)
|
||||
{
|
||||
|
@ -244,13 +353,21 @@ static int handle_group_audio_packet(void *object, int groupnumber, int friendgr
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int groupchat_enable_av(Group_Chats *g_c, int groupnumber)
|
||||
/* Convert groupchat to an A/V groupchat.
|
||||
*
|
||||
* return 0 on success.
|
||||
* return -1 on failure.
|
||||
*/
|
||||
static int groupchat_enable_av(Group_Chats *g_c, int groupnumber, void (*audio_callback)(Messenger *, int, int,
|
||||
const int16_t *, unsigned int, uint8_t, unsigned int, void *), void *userdata)
|
||||
{
|
||||
Group_AV *group_av = new_group_av(1, 48000, 64000); //TODO: Use variables instead.
|
||||
|
||||
if (group_av == NULL) {
|
||||
if (groupnumber == -1)
|
||||
return -1;
|
||||
|
||||
Group_AV *group_av = new_group_av(g_c, 1, 48000, 64000, audio_callback, userdata); //TODO: Use variables instead.
|
||||
|
||||
if (group_av == NULL)
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (group_set_object(g_c, groupnumber, group_av) == -1
|
||||
|| callback_groupchat_peer_new(g_c, groupnumber, group_av_peer_new) == -1
|
||||
|
@ -268,15 +385,39 @@ static int groupchat_enable_av(Group_Chats *g_c, int groupnumber)
|
|||
* return group number on success.
|
||||
* return -1 on failure.
|
||||
*/
|
||||
int add_av_groupchat(Group_Chats *g_c)
|
||||
int add_av_groupchat(Group_Chats *g_c, void (*audio_callback)(Messenger *, int, int, const int16_t *, unsigned int,
|
||||
uint8_t, unsigned int, void *), void *userdata)
|
||||
{
|
||||
int groupnumber = add_groupchat(g_c);
|
||||
int groupnumber = add_groupchat(g_c, GROUPCHAT_TYPE_AV);
|
||||
|
||||
if (groupnumber == -1) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (groupchat_enable_av(g_c, groupnumber) == -1) {
|
||||
if (groupchat_enable_av(g_c, groupnumber, audio_callback, userdata) == -1) {
|
||||
del_groupchat(g_c, groupnumber);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return groupnumber;
|
||||
}
|
||||
|
||||
/* Join a AV group (you need to have been invited first.)
|
||||
*
|
||||
* returns group number on success
|
||||
* returns -1 on failure.
|
||||
*/
|
||||
int join_av_groupchat(Group_Chats *g_c, int32_t friendnumber, const uint8_t *data, uint16_t length,
|
||||
void (*audio_callback)(Messenger *, int, int, const int16_t *, unsigned int, uint8_t, unsigned int, void *),
|
||||
void *userdata)
|
||||
{
|
||||
int groupnumber = join_groupchat(g_c, friendnumber, GROUPCHAT_TYPE_AV, data, length);
|
||||
|
||||
if (groupnumber == -1) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (groupchat_enable_av(g_c, groupnumber, audio_callback, userdata) == -1) {
|
||||
del_groupchat(g_c, groupnumber);
|
||||
return -1;
|
||||
}
|
||||
|
@ -308,3 +449,26 @@ static int send_audio_packet(Group_Chats *g_c, int groupnumber, uint8_t *packet,
|
|||
++group_av->audio_sequnum;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Send audio to the group chat.
|
||||
*
|
||||
* return 0 on success.
|
||||
* return -1 on failure.
|
||||
*/
|
||||
int group_send_audio(Group_Chats *g_c, int groupnumber, const int16_t *pcm, unsigned int samples, uint8_t channels,
|
||||
unsigned int sample_rate)
|
||||
{
|
||||
//TODO use channels and sample_rate arguments.
|
||||
Group_AV *group_av = group_get_object(g_c, groupnumber);
|
||||
|
||||
if (!group_av)
|
||||
return -1;
|
||||
|
||||
uint8_t encoded[1024];
|
||||
int32_t size = opus_encode(group_av->audio_encoder, pcm, samples, encoded, sizeof(encoded));
|
||||
|
||||
if (size <= 0)
|
||||
return -1;
|
||||
|
||||
return send_audio_packet(g_c, groupnumber, encoded, size);
|
||||
}
|
||||
|
|
|
@ -30,5 +30,24 @@
|
|||
* return group number on success.
|
||||
* return -1 on failure.
|
||||
*/
|
||||
int add_av_groupchat(Group_Chats *g_c);
|
||||
int add_av_groupchat(Group_Chats *g_c, void (*audio_callback)(Messenger *, int, int, const int16_t *, unsigned int,
|
||||
uint8_t, unsigned int, void *), void *userdata);
|
||||
|
||||
/* Join a AV group (you need to have been invited first.)
|
||||
*
|
||||
* returns group number on success
|
||||
* returns -1 on failure.
|
||||
*/
|
||||
int join_av_groupchat(Group_Chats *g_c, int32_t friendnumber, const uint8_t *data, uint16_t length,
|
||||
void (*audio_callback)(Messenger *, int, int, const int16_t *, unsigned int, uint8_t, unsigned int, void *),
|
||||
void *userdata);
|
||||
|
||||
|
||||
/* Send audio to the group chat.
|
||||
*
|
||||
* return 0 on success.
|
||||
* return -1 on failure.
|
||||
*/
|
||||
int group_send_audio(Group_Chats *g_c, int groupnumber, const int16_t *pcm, unsigned int samples, uint8_t channels,
|
||||
unsigned int sample_rate);
|
||||
|
||||
|
|
|
@ -23,6 +23,8 @@
|
|||
#include "config.h"
|
||||
#endif /* HAVE_CONFIG_H */
|
||||
|
||||
#define __TOX_DEFINED__
|
||||
typedef struct Messenger Tox;
|
||||
|
||||
#define _GNU_SOURCE /* implicit declaration warning */
|
||||
|
||||
|
@ -30,6 +32,7 @@
|
|||
#include "codec.h"
|
||||
#include "msi.h"
|
||||
#include "toxav.h"
|
||||
#include "group.h"
|
||||
|
||||
#include "../toxcore/logger.h"
|
||||
|
||||
|
@ -1148,3 +1151,42 @@ end:
|
|||
rtp_free_msg(NULL, _msg);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Create a new toxav group.
|
||||
*
|
||||
* return group number on success.
|
||||
* return -1 on failure.
|
||||
*/
|
||||
int toxav_add_av_groupchat(Tox *tox, void (*audio_callback)(Messenger *, int, int, const int16_t *, unsigned int,
|
||||
uint8_t, unsigned int, void *), void *userdata)
|
||||
{
|
||||
Messenger *m = tox;
|
||||
return add_av_groupchat(m->group_chat_object, audio_callback, userdata);
|
||||
}
|
||||
|
||||
/* Join a AV group (you need to have been invited first.)
|
||||
*
|
||||
* returns group number on success
|
||||
* returns -1 on failure.
|
||||
*/
|
||||
int toxav_join_av_groupchat(Tox *tox, int32_t friendnumber, const uint8_t *data, uint16_t length,
|
||||
void (*audio_callback)(Messenger *, int, int, const int16_t *, unsigned int, uint8_t, unsigned int, void *),
|
||||
void *userdata)
|
||||
{
|
||||
Messenger *m = tox;
|
||||
return join_av_groupchat(m->group_chat_object, friendnumber, data, length, audio_callback, userdata);
|
||||
}
|
||||
|
||||
/* Send audio to the group chat.
|
||||
*
|
||||
* return 0 on success.
|
||||
* return -1 on failure.
|
||||
*/
|
||||
int toxav_group_send_audio(Tox *tox, int groupnumber, const int16_t *pcm, unsigned int samples, uint8_t channels,
|
||||
unsigned int sample_rate)
|
||||
{
|
||||
Messenger *m = tox;
|
||||
return group_send_audio(m->group_chat_object, groupnumber, pcm, samples, channels, sample_rate);
|
||||
}
|
||||
|
||||
|
|
|
@ -382,6 +382,31 @@ Tox *toxav_get_tox(ToxAv *av);
|
|||
|
||||
int toxav_has_activity ( ToxAv *av, int32_t call_index, int16_t *PCM, uint16_t frame_size, float ref_energy );
|
||||
|
||||
|
||||
/* Create a new toxav group.
|
||||
*
|
||||
* return group number on success.
|
||||
* return -1 on failure.
|
||||
*/
|
||||
int toxav_add_av_groupchat(Tox *tox, void (*audio_callback)(Tox *, int, int, const int16_t *, unsigned int, uint8_t,
|
||||
unsigned int, void *), void *userdata);
|
||||
|
||||
/* Join a AV group (you need to have been invited first.)
|
||||
*
|
||||
* returns group number on success
|
||||
* returns -1 on failure.
|
||||
*/
|
||||
int toxav_join_av_groupchat(Tox *tox, int32_t friendnumber, const uint8_t *data, uint16_t length,
|
||||
void (*audio_callback)(Tox *, int, int, const int16_t *, unsigned int, uint8_t, unsigned int, void *), void *userdata);
|
||||
|
||||
/* Send audio to the group chat.
|
||||
*
|
||||
* return 0 on success.
|
||||
* return -1 on failure.
|
||||
*/
|
||||
int toxav_group_send_audio(Tox *tox, int groupnumber, const int16_t *pcm, unsigned int samples, uint8_t channels,
|
||||
unsigned int sample_rate);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
Loading…
Reference in New Issue