fixing a stackoverflow.com post about pjsip

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi,

There's an interesting posting at stackoverflow.com about how to stream
audio from a sip-session without audio-hardware.
https://stackoverflow.com/questions/46243029/how-to-get-the-audio-stream-from-pjsip-when-there-is-no-audio-hardware-device
Now no-one responded to it so I took it on me to fix it - answer the
post (I also want to be able to stream audio without audio-device).

Some fixes were easy: the callbacks were missing and a loop waiting for
the call to be set-up was missing as well.
If I start the program, my phone starts ringing and I can pick it up.
Only then I get:

09:24:29.022          pjsua_media.c  ......pjsua_aud_channel_update() failed for call_id 0 media 0: Invalid operation (PJ_EINVALIDOP)
09:24:29.022          pjsua_media.c  ......Error updating media call00:0: Invalid operation (PJ_EINVALIDOP)
09:24:29.022           pjsua_call.c  .....Unable to create media session: No active media stream after negotiation (PJMEDIA_SDPNEG_ENOMEDIA) [status=220048]

which is a bit strange as all codecs are allowed in the asterisk setup
it is talking against.

Any ideas?

#include <pjlib.h>
#include <pjlib-util.h>
#include <pjnath.h>
#include <pjsip.h>
#include <pjsip_ua.h>
#include <pjsip_simple.h>
#include <pjsua-lib/pjsua.h>
#include <pjmedia.h>
#include <pjmedia-codec.h>
#include <pj/log.h>
#include <pj/os.h>
#include <unistd.h>

pj_status_t test_rec_cb(void *user_data, pjmedia_frame *frame)
{
	return PJ_SUCCESS;
}

pj_status_t test_play_cb(void *user_data, pjmedia_frame *frame)
{
	return PJ_SUCCESS;
}

int main(int, char **)
{
	// Create pjsua first! 
	pj_status_t status = pjsua_create();
	if (status != PJ_SUCCESS)
	{
		fprintf(stderr,"pjsua_create error\n");
		return -1;
	}

	// Init pjsua 
	pjsua_config cfg;
	pjsua_logging_config log_cfg;

	pjsua_config_default(&cfg);

	pjsua_logging_config_default(&log_cfg);
	log_cfg.console_level = 1;

	status = pjsua_init(&cfg, &log_cfg, NULL);
	if (status != PJ_SUCCESS)
	{
		fprintf(stderr,"pjsua_init error\n");
		return -1;
	}


	// Proactively list known audio devices so we are sure there are NONE
	pjmedia_aud_dev_info info[64];
	unsigned info_count = 64;
	pjsua_enum_aud_devs(info, &info_count);

	fprintf(stderr,"Listing known sound devices, total of [%u]\n", info_count);
	for (unsigned i = 0; i<info_count; ++i)
		fprintf(stderr,"Name [%s]\n", info[i].name);

	// Add transport
	pjsua_transport_config tcfg;
	pjsua_transport_id trans_id;
	pjsua_transport_config_default(&tcfg);
	tcfg.port = 5060;
	status = pjsua_transport_create(PJSIP_TRANSPORT_UDP, &tcfg, &trans_id);
	if (status != PJ_SUCCESS)
	{
		fprintf(stderr, "pjsua_transport_create error\n");
		return -1;
	}

	// Initialization is done, now start pjsua 
	status = pjsua_start();
	if (status != PJ_SUCCESS)
	{
		fprintf(stderr, "pjsua_start error\n");
		return -1;
	}

	// Set NULL sound
#if 1
	pjmedia_port *port = pjsua_set_no_snd_dev();
#else
	status = pjsua_set_null_snd_dev();
	if (status != PJ_SUCCESS)
	{
		fprintf(stderr, "pjsua_set_null_snd_dev error");
		return -1;
	}
#endif

	// Register to a SIP server by creating SIP account, I happen use use Asterisk 
	pjsua_acc_id acc_id;
	fprintf(stderr, "Setting up SIP server registration\n");
	if (1)
	{
		pjsua_acc_config cfg;
		pjsua_acc_config_default(&cfg);
		cfg.id = pj_str("sip:1000@192.168.64.1");
		cfg.reg_uri = cfg.id; // same as ID
		cfg.cred_count = 1;

		cfg.cred_info[0].realm = pj_str("*");
		cfg.cred_info[0].scheme = pj_str("digest"); 
		cfg.cred_info[0].username = pj_str("1000");
		cfg.cred_info[0].data_type = PJSIP_CRED_DATA_PLAIN_PASSWD;
		cfg.cred_info[0].data = pj_str("1234");

		status = pjsua_acc_add(&cfg, PJ_TRUE, &acc_id);
		if (status != PJ_SUCCESS)
		{
			fprintf(stderr, "pjsua_acc_add error\n");
			return -1;
		}
	}

	fprintf(stderr, "Waiting for SIP server registration to complete....\n");

	sleep(2); // sleep 2 seconds

	// Call extension 9 on my Asterisk server at 10.0.0.21:5060
	pj_str_t sip_target(pj_str("sip:6001@192.168.64.1"));
	fprintf(stderr, "Making call to [%s]\n", sip_target.ptr);

	pjsua_call_id call_id;
	status = pjsua_call_make_call(acc_id, &sip_target, 0, NULL, NULL, &call_id);
	if (status != PJ_SUCCESS)
	{
		fprintf(stderr, "pjsua_call_make_call error\n");
		return -1;
	}

	while(pjsua_call_is_active(call_id) == false) {
		printf("Not active\n");
		sleep(1);
	}

	pj_pool_t * pool = nullptr;
	pjmedia_port * wav = nullptr;
	pjmedia_aud_stream *strm = nullptr;
	pool = pj_pool_create(pjmedia_aud_subsys_get_pool_factory(), "wav-audio", 1000, 1000, NULL);

	if (nullptr == pool)
	{
		fprintf(stderr,"Pool creation failed\n");
		return -1;
	}

	// 8kHz, single channel 16bit MS WAV format file
	status = pjmedia_wav_writer_port_create(pool, "test.wav", 8000, 1, 320, 16, PJMEDIA_FILE_WRITE_PCM, 0, &wav);
	if (status != PJ_SUCCESS)
	{
		fprintf(stderr, "Error creating WAV file\n");
		return -1;
	}

	pjmedia_aud_param param; 
	//////////////////////////////////////////////////////
	// FAILURE HERE : This is the function call which returns PJMEDIA_AUD_INVALID_DEV
	//////////////////////////////////////////////////////
	status = pjmedia_aud_dev_default_param(PJMEDIA_AUD_DEFAULT_CAPTURE_DEV, &param); 
	if (status != PJ_SUCCESS) 
	{
		fprintf(stderr, "pjmedia_aud_dev_default_param()");
		return -1;
	}

	param.dir = PJMEDIA_DIR_CAPTURE;
	param.clock_rate = PJMEDIA_PIA_SRATE(&wav->info);
	param.samples_per_frame = PJMEDIA_PIA_SPF(&wav->info);
	param.channel_count = PJMEDIA_PIA_CCNT(&wav->info);
	param.bits_per_sample = PJMEDIA_PIA_BITS(&wav->info);

	status = pjmedia_aud_stream_create(&param, test_rec_cb, test_play_cb, wav, &strm);
	if (status != PJ_SUCCESS)
	{
		fprintf(stderr, "Error opening the sound stream");
		return -1;
	}

	status = pjmedia_aud_stream_start(strm);
	if (status != PJ_SUCCESS)
	{
		fprintf(stderr, "Error starting the sound device");
		return -1;
	}

	// Spend some time allowing the called party to pick up and recording to proceed
	sleep(10); // sleep 10 seconds

	// Clean up code omitted
	return 0;
}



Folkert van Heusden

-- 

_______________________________________________
Visit our blog: http://blog.pjsip.org

pjsip mailing list
pjsip@xxxxxxxxxxxxxxx
http://lists.pjsip.org/mailman/listinfo/pjsip_lists.pjsip.org



[Index of Archives]     [Asterisk Users]     [Asterisk App Development]     [Linux ARM Kernel]     [Linux ARM]     [Linux Omap]     [Fedora ARM]     [IETF Annouce]     [Security]     [Bugtraq]     [Linux]     [Linux OMAP]     [Linux MIPS]     [Linux API]
  Powered by Linux