mirror of
https://github.com/irungentoo/toxcore.git
synced 2024-03-22 13:30:51 +08:00
Group audio might work now but I have not tested anything yet.
This commit is contained in:
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.");
|
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];
|
char msg[256];
|
||||||
|
|
||||||
|
if (type == TOX_GROUPCHAT_TYPE_TEXT) {
|
||||||
sprintf(msg, "[i] received group chat invite from: %u, auto accepting and joining. group number: %u", friendnumber,
|
sprintf(msg, "[i] received group chat invite from: %u, auto accepting and joining. group number: %u", friendnumber,
|
||||||
tox_join_groupchat(m, friendnumber, data, length));
|
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);
|
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;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
Group_Chats *g_c;
|
||||||
OpusEncoder *audio_encoder;
|
OpusEncoder *audio_encoder;
|
||||||
|
|
||||||
unsigned int audio_channels, audio_sample_rate, audio_bitrate;
|
unsigned int audio_channels, audio_sample_rate, audio_bitrate;
|
||||||
|
|
||||||
uint16_t audio_sequnum;
|
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;
|
} Group_AV;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
Group_JitterBuffer *buffer;
|
Group_JitterBuffer *buffer;
|
||||||
|
|
||||||
OpusDecoder *audio_decoder;
|
OpusDecoder *audio_decoder;
|
||||||
|
int decoder_channels;
|
||||||
|
unsigned int last_packet_samples;
|
||||||
} Group_Peer_AV;
|
} Group_Peer_AV;
|
||||||
|
|
||||||
static void kill_group_av(Group_AV *group_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);
|
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));
|
Group_AV *group_av = calloc(1, sizeof(Group_AV));
|
||||||
|
|
||||||
int rc = OPUS_OK;
|
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_channels = audio_channels;
|
||||||
group_av->audio_sample_rate = audio_sample_rate;
|
group_av->audio_sample_rate = audio_sample_rate;
|
||||||
group_av->audio_bitrate = audio_bitrate;
|
group_av->audio_bitrate = audio_bitrate;
|
||||||
|
group_av->g_c = g_c;
|
||||||
|
|
||||||
|
group_av->audio_data = audio_callback;
|
||||||
|
group_av->userdata = userdata;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -217,6 +232,100 @@ static void group_av_peer_delete(void *object, int groupnumber, int friendgroupn
|
|||||||
free(peer_object);
|
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,
|
static int handle_group_audio_packet(void *object, int groupnumber, int friendgroupnumber, void *peer_object,
|
||||||
const uint8_t *packet, uint16_t length)
|
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;
|
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 (groupnumber == -1)
|
||||||
|
return -1;
|
||||||
if (group_av == NULL) {
|
|
||||||
|
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;
|
return -1;
|
||||||
}
|
|
||||||
|
|
||||||
if (group_set_object(g_c, groupnumber, group_av) == -1
|
if (group_set_object(g_c, groupnumber, group_av) == -1
|
||||||
|| callback_groupchat_peer_new(g_c, groupnumber, group_av_peer_new) == -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 group number on success.
|
||||||
* return -1 on failure.
|
* 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) {
|
if (groupnumber == -1) {
|
||||||
return -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);
|
del_groupchat(g_c, groupnumber);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@ -308,3 +449,26 @@ static int send_audio_packet(Group_Chats *g_c, int groupnumber, uint8_t *packet,
|
|||||||
++group_av->audio_sequnum;
|
++group_av->audio_sequnum;
|
||||||
return 0;
|
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 group number on success.
|
||||||
* return -1 on failure.
|
* 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"
|
#include "config.h"
|
||||||
#endif /* HAVE_CONFIG_H */
|
#endif /* HAVE_CONFIG_H */
|
||||||
|
|
||||||
|
#define __TOX_DEFINED__
|
||||||
|
typedef struct Messenger Tox;
|
||||||
|
|
||||||
#define _GNU_SOURCE /* implicit declaration warning */
|
#define _GNU_SOURCE /* implicit declaration warning */
|
||||||
|
|
||||||
@ -30,6 +32,7 @@
|
|||||||
#include "codec.h"
|
#include "codec.h"
|
||||||
#include "msi.h"
|
#include "msi.h"
|
||||||
#include "toxav.h"
|
#include "toxav.h"
|
||||||
|
#include "group.h"
|
||||||
|
|
||||||
#include "../toxcore/logger.h"
|
#include "../toxcore/logger.h"
|
||||||
|
|
||||||
@ -1148,3 +1151,42 @@ end:
|
|||||||
rtp_free_msg(NULL, _msg);
|
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 );
|
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
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
x
Reference in New Issue
Block a user