Esempio n. 1
0
/*
 * Init media stack.
 */
static pj_status_t init_media()
{
    unsigned	i;
    pj_uint16_t	rtp_port;
    pj_status_t	status;


    /* Initialize media endpoint so that at least error subsystem is properly
     * initialized.
     */
    status = pjmedia_endpt_create(&app.cp.factory, 
				  pjsip_endpt_get_ioqueue(app.sip_endpt), 0, 
				  &app.med_endpt);
    PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);


    /* Must register all codecs to be supported */
    pjmedia_codec_register_audio_codecs(app.med_endpt, NULL);

    /* Init dummy socket addresses */
    app.skinfo_cnt = 0;
    for (i=0, rtp_port=4000; i<PJ_ARRAY_SIZE(app.skinfo); ++i, rtp_port+=2) {
	pjmedia_sock_info *skinfo;

	skinfo = &app.skinfo[i];
	
	pj_sockaddr_in_init(&skinfo->rtp_addr_name.ipv4, &app.local_addr,
			    (pj_uint16_t)rtp_port);
	pj_sockaddr_in_init(&skinfo->rtp_addr_name.ipv4, &app.local_addr,
			    (pj_uint16_t)(rtp_port+1));
	app.skinfo_cnt++;
    }

    /* Generate dummy SDP */
    dummy_sdp_str.slen = pj_ansi_strlen(dummy_sdp_str.ptr);
    status = pjmedia_sdp_parse(app.pool, dummy_sdp_str.ptr, dummy_sdp_str.slen, 
			       &app.dummy_sdp);
    if (status != PJ_SUCCESS) {
	app_perror(THIS_FILE, "Error parsing dummy SDP", status);
	return status;
    }


    /* Done */
    return PJ_SUCCESS;
}
Esempio n. 2
0
static void pcap2wav(const pj_str_t *codec,
		     const pj_str_t *wav_filename,
		     pjmedia_aud_dev_index dev_id,
		     const pj_str_t *srtp_crypto,
		     const pj_str_t *srtp_key)
{
    const pj_str_t WAV = {".wav", 4};
    struct pkt
    {
	pj_uint8_t	 buffer[320];
	pjmedia_rtp_hdr	*rtp;
	pj_uint8_t	*payload;
	unsigned	 payload_len;
    } pkt0;
    pjmedia_codec_mgr *cmgr;
    const pjmedia_codec_info *ci;
    pjmedia_codec_param param;
    unsigned samples_per_frame;
    pj_status_t status;

    /* Initialize all codecs */
    T( pjmedia_codec_register_audio_codecs(app.mept, NULL) );

    /* Create SRTP transport is needed */
#if PJMEDIA_HAS_SRTP
    if (srtp_crypto->slen) {
	pjmedia_srtp_crypto crypto;

	pj_bzero(&crypto, sizeof(crypto));
	crypto.key = *srtp_key;
	crypto.name = *srtp_crypto;
	T( pjmedia_transport_srtp_create(app.mept, NULL, NULL, &app.srtp) );
	T( pjmedia_transport_srtp_start(app.srtp, &crypto, &crypto) );
    }
#else
    PJ_UNUSED_ARG(srtp_crypto);
    PJ_UNUSED_ARG(srtp_key);
#endif

    /* Read first packet */
    read_rtp(pkt0.buffer, sizeof(pkt0.buffer), &pkt0.rtp, 
	     &pkt0.payload, &pkt0.payload_len, PJ_FALSE);

    cmgr = pjmedia_endpt_get_codec_mgr(app.mept);

    /* Get codec info and param for the specified payload type */
    app.pt = pkt0.rtp->pt;
    if (app.pt >=0 && app.pt < 96) {
	T( pjmedia_codec_mgr_get_codec_info(cmgr, pkt0.rtp->pt, &ci) );
    } else {
	unsigned cnt = 2;
	const pjmedia_codec_info *info[2];
	T( pjmedia_codec_mgr_find_codecs_by_id(cmgr, codec, &cnt, 
					       info, NULL) );
	if (cnt != 1)
	    err_exit("Codec ID must be specified and unique!", 0);

	ci = info[0];
    }
    T( pjmedia_codec_mgr_get_default_param(cmgr, ci, &param) );

    /* Alloc and init codec */
    T( pjmedia_codec_mgr_alloc_codec(cmgr, ci, &app.codec) );
    T( pjmedia_codec_init(app.codec, app.pool) );
    T( pjmedia_codec_open(app.codec, &param) );

    /* Init audio device or WAV file */
    samples_per_frame = ci->clock_rate * param.info.frm_ptime / 1000;
    if (pj_strcmp2(wav_filename, "-") == 0) {
	pjmedia_aud_param aud_param;

	/* Open audio device */
	T( pjmedia_aud_dev_default_param(dev_id, &aud_param) );
	aud_param.dir = PJMEDIA_DIR_PLAYBACK;
	aud_param.channel_count = ci->channel_cnt;
	aud_param.clock_rate = ci->clock_rate;
	aud_param.samples_per_frame = samples_per_frame;
	T( pjmedia_aud_stream_create(&aud_param, NULL, &play_cb, 
				     NULL, &app.aud_strm) );
	T( pjmedia_aud_stream_start(app.aud_strm) );
    } else if (pj_stristr(wav_filename, &WAV)) {
	/* Open WAV file */
	T( pjmedia_wav_writer_port_create(app.pool, wav_filename->ptr,
					  ci->clock_rate, ci->channel_cnt,
					  samples_per_frame,
					  param.info.pcm_bits_per_sample, 0, 0,
					  &app.wav) );
    } else {
	err_exit("invalid output file", PJ_EINVAL);
    }

    /* Loop reading PCAP and writing WAV file */
    for (;;) {
	struct pkt pkt1;
	pj_timestamp ts;
	pjmedia_frame frames[16], pcm_frame;
	short pcm[320];
	unsigned i, frame_cnt;
	long samples_cnt, ts_gap;

	pj_assert(sizeof(pcm) >= samples_per_frame);

	/* Parse first packet */
	ts.u64 = 0;
	frame_cnt = PJ_ARRAY_SIZE(frames);
	T( pjmedia_codec_parse(app.codec, pkt0.payload, pkt0.payload_len, 
				&ts, &frame_cnt, frames) );

	/* Decode and write to WAV file */
	samples_cnt = 0;
	for (i=0; i<frame_cnt; ++i) {
	    pjmedia_frame pcm_frame;

	    pcm_frame.buf = pcm;
	    pcm_frame.size = samples_per_frame * 2;

	    T( pjmedia_codec_decode(app.codec, &frames[i], 
				    (unsigned)pcm_frame.size, &pcm_frame) );
	    if (app.wav) {
		T( pjmedia_port_put_frame(app.wav, &pcm_frame) );
	    }
	    if (app.aud_strm) {
		T( wait_play(&pcm_frame) );
	    }
	    samples_cnt += samples_per_frame;
	}

	/* Read next packet */
	read_rtp(pkt1.buffer, sizeof(pkt1.buffer), &pkt1.rtp,
		 &pkt1.payload, &pkt1.payload_len, PJ_TRUE);

	/* Fill in the gap (if any) between pkt0 and pkt1 */
	ts_gap = pj_ntohl(pkt1.rtp->ts) - pj_ntohl(pkt0.rtp->ts) -
		 samples_cnt;
	while (ts_gap >= (long)samples_per_frame) {

	    pcm_frame.buf = pcm;
	    pcm_frame.size = samples_per_frame * 2;

	    if (app.codec->op->recover) {
		T( pjmedia_codec_recover(app.codec, (unsigned)pcm_frame.size, 
					 &pcm_frame) );
	    } else {
		pj_bzero(pcm_frame.buf, pcm_frame.size);
	    }

	    if (app.wav) {
		T( pjmedia_port_put_frame(app.wav, &pcm_frame) );
	    }
	    if (app.aud_strm) {
		T( wait_play(&pcm_frame) );
	    }
	    ts_gap -= samples_per_frame;
	}
	
	/* Next */
	pkt0 = pkt1;
	pkt0.rtp = (pjmedia_rtp_hdr*)pkt0.buffer;
	pkt0.payload = pkt0.buffer + (pkt1.payload - pkt1.buffer);
    }
}
Esempio n. 3
0
/* 
 * Register all codecs. 
 */
static pj_status_t init_codecs(pjmedia_endpt *med_endpt)
{
    return pjmedia_codec_register_audio_codecs(med_endpt, NULL);
}
Esempio n. 4
0
static pj_status_t test_init(void)
{
    struct stream_cfg strm_cfg;
    pj_status_t status;

    /* Must init PJLIB first: */
    status = pj_init();
    PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);

    /* Must create a pool factory before we can allocate any memory. */
    pj_caching_pool_init(&g_app.cp, &pj_pool_factory_default_policy, 0);

    /* Pool */
    g_app.pool = pj_pool_create(&g_app.cp.factory, "g_app", 512, 512, NULL);

    /* Log file */
    if (g_app.cfg.log_file) {
	status = pj_file_open(g_app.pool, g_app.cfg.log_file, 
			      PJ_O_WRONLY,
			      &g_app.log_fd);
	if (status != PJ_SUCCESS) {
	    jbsim_perror("Error writing output file", status);
	    goto on_error;
	}

	pj_log_set_decor(PJ_LOG_HAS_SENDER | PJ_LOG_HAS_COLOR | PJ_LOG_HAS_LEVEL_TEXT);
	pj_log_set_log_func(&log_cb);
    }

    /* 
     * Initialize media endpoint.
     * This will implicitly initialize PJMEDIA too.
     */
    status = pjmedia_endpt_create(&g_app.cp.factory, NULL, 0, &g_app.endpt);
    if (status != PJ_SUCCESS) {
	jbsim_perror("Error creating media endpoint", status);
	goto on_error;
    }

    /* Register codecs */
    pjmedia_codec_register_audio_codecs(g_app.endpt, NULL);

    /* Create the loop transport */
    status = pjmedia_transport_loop_create(g_app.endpt, &g_app.loop);
    if (status != PJ_SUCCESS) {
	jbsim_perror("Error creating loop transport", status);
	goto on_error;
    }

    /* Create transmitter stream */
    pj_bzero(&strm_cfg, sizeof(strm_cfg));
    strm_cfg.name = "tx";
    strm_cfg.dir = PJMEDIA_DIR_ENCODING;
    strm_cfg.codec = g_app.cfg.codec;
    strm_cfg.ptime = g_app.cfg.tx_ptime;
    strm_cfg.dtx = g_app.cfg.tx_dtx;
    strm_cfg.plc = PJ_TRUE;
    status = stream_init(&strm_cfg, &g_app.tx);
    if (status != PJ_SUCCESS) 
	goto on_error;

    /* Create transmitter WAV */
    status = pjmedia_wav_player_port_create(g_app.pool, 
					    g_app.cfg.tx_wav_in,
					    g_app.cfg.tx_ptime,
					    0,
					    0,
					    &g_app.tx_wav);
    if (status != PJ_SUCCESS) {
	jbsim_perror("Error reading input WAV file", status);
	goto on_error;
    }

    /* Make sure stream and WAV parameters match */
    if (PJMEDIA_PIA_SRATE(&g_app.tx_wav->info) != PJMEDIA_PIA_SRATE(&g_app.tx->port->info) ||
	PJMEDIA_PIA_CCNT(&g_app.tx_wav->info) != PJMEDIA_PIA_CCNT(&g_app.tx->port->info))
    {
	jbsim_perror("Error: Input WAV file has different clock rate "
		     "or number of channels than the codec", PJ_SUCCESS);
	goto on_error;
    }


    /* Create receiver */
    pj_bzero(&strm_cfg, sizeof(strm_cfg));
    strm_cfg.name = "rx";
    strm_cfg.dir = PJMEDIA_DIR_DECODING;
    strm_cfg.codec = g_app.cfg.codec;
    strm_cfg.ptime = g_app.cfg.rx_ptime;
    strm_cfg.dtx = PJ_TRUE;
    strm_cfg.plc = g_app.cfg.rx_plc;
    status = stream_init(&strm_cfg, &g_app.rx);
    if (status != PJ_SUCCESS) 
	goto on_error;

    /* Create receiver WAV */
    status = pjmedia_wav_writer_port_create(g_app.pool, 
					    g_app.cfg.rx_wav_out,
					    PJMEDIA_PIA_SRATE(&g_app.rx->port->info),
					    PJMEDIA_PIA_CCNT(&g_app.rx->port->info),
					    PJMEDIA_PIA_SPF(&g_app.rx->port->info),
					    PJMEDIA_PIA_BITS(&g_app.rx->port->info),
					    0,
					    0,
					    &g_app.rx_wav);
    if (status != PJ_SUCCESS) {
	jbsim_perror("Error creating output WAV file", status);
	goto on_error;
    }


    /* Frame buffer */
    g_app.framebuf = (pj_int16_t*)
		     pj_pool_alloc(g_app.pool,
				   MAX(PJMEDIA_PIA_SPF(&g_app.rx->port->info),
				       PJMEDIA_PIA_SPF(&g_app.tx->port->info)) * sizeof(pj_int16_t));


    /* Set the receiver in the loop transport */
    pjmedia_transport_loop_disable_rx(g_app.loop, g_app.tx->strm, PJ_TRUE);

    /* Done */
    return PJ_SUCCESS;

on_error:
    test_destroy();
    return status;
}