16 votes

faire en sorte que iaxclient envoie l'audio vers/depuis un tampon au lieu d'un périphérique audio

J'essaie d'écrire un programme en C++ (bien que python aurait également fait l'affaire au cas où quelqu'un connaîtrait une meilleure alternative (IAX/SIP)) qui se connecte à un serveur Asterisk.

Après la connexion, il doit écouter l'audio et le traiter. Il doit également renvoyer l'audio. J'utilise https://sourceforge.net/projects/iaxclient/ pour cela (notez qu'il existe plusieurs versions (bêtas, versions régulières, version svn) qui se comportent toutes différemment).

Si j'ai bien compris le code de la bibliothèque, elle peut appeler une fonction de rappel avec un événement. L'un de ces événements est IAXC_EVENT_AUDIO. Dans la structure de cet IAXC_EVENT_AUDIO, il y a une direction ; entrant sortant. Et c'est là que je suis perdu : avec certaines versions d'iaxclient, je ne reçois que les messages IAXC_SOURCE_REMOTE, avec d'autres les deux. Et si je passe en mode test (qui ne devrait désactiver que le périphérique audio), je ne reçois souvent rien du tout. Lorsque je reçois à la fois IAXC_SOURCE_LOCAL et IAXC_SOURCE_REMOTE, j'ai essayé de définir les tampons de ces événements sur des données aléatoires mais cela n'atteint pas du tout l'autre extrémité (je l'ai défini en mode RAW).

Quelqu'un a-t-il des suggestions pour résoudre ce problème ?

Mon code de test est :

#include <iaxclient.h>
#include <unistd.h>

int iaxc_event_callback(iaxc_event e)
{
    if (e.type == IAXC_EVENT_TEXT) {
        printf("text\n");
    }
    else if (e.type == IAXC_EVENT_LEVELS) {
        printf("level\n");
    }
    else if (e.type == IAXC_EVENT_STATE) {
        struct iaxc_ev_call_state *st = iaxc_get_event_state(&e);
        printf("\tcallno %d state %d format %d remote %s(%s)\n", st->callNo, st->state, st->format,st->remote, st->remote_name);
        iaxc_key_radio(st->callNo);
    }
    else if (e.type == IAXC_EVENT_NETSTAT) {
        printf("\tcallno %d rtt %d\n", e.ev.netstats.callNo, e.ev.netstats.rtt);
    }
    else if (e.type == IAXC_EVENT_AUDIO) {
        printf("\t AUDIO!!!! %d %u %d\n", e.ev.audio.source, e.ev.audio.ts, e.ev.audio.size);

        for(int i=0; i<e.ev.audio.size; i++)
            printf("%02x ", e.ev.audio.data[i]);
        printf("\n");
    }
    else {
        printf("type: %d\n", e.type);
    }

    return 1;
}

int main(int argc, char *argv[])
{
    iaxc_set_test_mode(1);
    printf("init %d\n", iaxc_initialize(1));

    iaxc_set_formats(IAXC_FORMAT_SPEEX, IAXC_FORMAT_SPEEX);

    iaxc_set_event_callback(iaxc_event_callback);
    printf("get audio pref %d\n", iaxc_get_audio_prefs());
    //printf("set audio pref %d\n", iaxc_set_audio_prefs(IAXC_AUDIO_PREF_RECV_REMOTE_ENCODED));
    printf("set audio pref %d\n", iaxc_set_audio_prefs(IAXC_AUDIO_PREF_RECV_REMOTE_RAW | IAXC_AUDIO_PREF_RECV_LOCAL_RAW));
    printf("get audio pref %d\n", iaxc_get_audio_prefs());

    printf("start thread %d\n", iaxc_start_processing_thread());

    int id = -1;
    printf("register %d\n", id = iaxc_register("6003", "1923", "192.168.64.1"));

    int callNo = -1;
    printf("call %d\n", callNo = iaxc_call("6003:1923@192.168.64.1/6001"));

    printf("unquelch: %d\n", iaxc_unquelch(callNo));

    pause();

    printf("finish\n");
    printf("%d\n", iaxc_unregister(id));
    printf("%d\n", iaxc_stop_processing_thread());
    iaxc_shutdown();

    return 0;
}

2voto

Gillsoft AB Points 823

Veuillez consulter le site iaxclient_lib.c pour voir comment la logique fonctionne. Pour accrocher ou remplacer l'entrée/sortie vous pouvez changer la fonction iaxci_do_audio_callback à l'adresse memcpy(e.ev.audio.data, data, size) ; où le tampon est placé. Jetez également un coup d'œil à service_audio pour comprendre comment vous pouvez remplacer le tampon/flux envoyé à l'emplacement distant (par exemple, want_send_audio et want_local_audio). Vous pouvez également créer des périphériques d'entrée/sortie virtuels dans portaudio qu'iaxclient utilise pour traiter l'audio en utilisant des tampons à la place.

Pour un exemple plus concret, regardez la méthode principale de l'application source simple d'appel pour prendre un bon départ. Cependant, le code source est trop long pour être copié-collé, désolé pour cela.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X