3 votes

<p>capture and play données pcm pjsip</p>

Je possède des appareils intégrés qui n'ont pas de périphérique audio par défaut. Ils communiquent entre eux via un FPGA. Donc ma question est, comment puis-je capturer/lire de l'audio à partir de pjsip en pcm afin de l'envoyer/de le recevoir avec le FPGA?

Je sais qu'il existe pjmedia_mem_player_create() et pjmedia_mem_capture_create() mais je n'arrive pas à trouver des bonnes informations sur l'utilisation de ces fonctions.

J'ai essayé le morceau de code suivant, mais une assertion a échoué car l'un des paramètres de la fonction est "vide".

Erreur:

pjmedia_mem_capture_create: Assertion `pool && buffer && size && clock_rate && channel_count && samples_per_frame && bits_per_sample && p_port' failed.

Remarque : J'utilise principalement pjsua2 pour tout le reste comme les enregistrements, les transports, etc. De plus, l'audio par défaut est défini sur null avec ep.audDevManager().setNullDev(); car sans cela, passer/recevoir un appel échouerait simplement ?!

void MyCall::onCallMediaState(OnCallMediaStateParam &prm){
CallInfo ci = getInfo();

pj_caching_pool_init(&cp, &pj_pool_factory_default_policy, 0);
pj_pool_t *pool = pj_pool_create(&cp.factory, "POOLNAME", 2000, 2000, NULL);

void *buffer;
pjmedia_port *prt;

#define CLOCK_RATE 8000
#define CHANELS 1
#define SAMPLES_PER_FRAME 480
#define BITS_PER_SAMPLE 16

pjmedia_mem_capture_create( pool, //Pool
                            buffer, //Buffer
                            2000, //Buffer Size
                            CLOCK_RATE, 
                            CHANELS, 
                            SAMPLES_PER_FRAME, 
                            BITS_PER_SAMPLE, 
                            0, //Options
                            &prt); //The return port}

MISE À JOUR

L'assertion a échoué car la variable de buffer n'a pas de mémoire qui lui est attribuée. Allouez deux fois la quantité de samples par frame pour avoir suffisamment de mémoire.

 buffer = pj_pool_zalloc(pool, 960);

Un rappel doit également être enregistré avec pjmedia_mem_capture_set_eof_cb2() (Le deux à la fin est nécessaire pour PJSIP 2.10 ou ultérieur) Apparemment, à partir de là, le buffer peut être utilisé. Mais pour le moment, mon implémentation n'exécute pas le rappel.

0 votes

Avez-vous fait des progrès à ce sujet? Je suis bloqué avec le même problème

0 votes

Aucun pour le moment. J'avais essayé de contacter les développeurs mais malheureusement aucune réponse.

1voto

Islam Sabyrgaliyev Points 170

On dirait que j'ai trouvé la solution, j'ai modifié votre code et écrit un code simple en C avec l'API pjsua pour enregistrer chaque trame dans un fichier. Désolé pour le désordre, je ne suis pas compétent en C :

pjsua_call_info ci;
pjsua_call_get_info(call_id, &ci);
pjsua_conf_port_info cpi;
pjsua_conf_get_port_info(ci.conf_slot, &cpi);

pj_pool_t *pool = pjsua_pool_create("NAMEPOOL", 2000, 2000);
pjmedia_port *prt;
uint buf_size = cpi.bits_per_sample*cpi.samples_per_frame/8;
void *buffer = pj_pool_zalloc(pool, buf_size);
pjsua_conf_port_id port_id;

pjmedia_mem_capture_create(pool,
                            buffer,
                            buf_size,
                            cpi.clock_rate,
                            cpi.channel_count,
                            cpi.samples_per_frame,
                            cpi.bits_per_sample,
                            0,
                            &prt);
pjmedia_mem_capture_set_eof_cb(prt, buffer, dump_incoming_frames);
pjsua_conf_add_port(pool, prt, &port_id);
pjsua_conf_connect(ci.conf_slot, port_id); //connect port with conference

///////dumping frames///
static pj_status_t dump_incoming_frames(pjmedia_port * port, void * usr_data){
   pj_size_t buf_size = pjmedia_mem_capture_get_size(port);
   char * data = usr_data;
   ...
   fwrite(data,sizeof(data[0]),buf_size,fptr);
   ...
}

La documentation indique que pjmedia_mem_capture_set_eof_cb est obsolète mais je n'ai pas réussi à faire fonctionner pjmedia_mem_capture_set_eof_cb2, buf_size est toujours à 0 pour chaque appel de dump_incoming_frames donc j'ai laissé la fonction obsolète. J'ai également réussi à obtenir le même résultat en créant un port personnalisé.

J'espère que vous pourrez le modifier facilement pour votre code C++/pjsua2

MISE À JOUR : J'ai modifié le PJSIP et ai regroupé le streaming audio d'entrée-sortie dans des classes PJSUA2/Media appropriées afin qu'il puisse être appelé depuis Python. Le code complet est ici.

0 votes

Dude tu es un génie! J'ai réussi à le faire fonctionner après avoir eu une LONGUE lutte pour définir la bonne valeur de l'adresse publique.

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