我正在研究RTP API,它包括在我的PC和目标之间通过RTP发送音频WAV文件。
我有一个问题,发送给我sock_common.c;我使用gdb来找到如何修复这个bug,但我无法解决这个问题。
4:48:46.482 strm0x1386e58 VAD temporarily disabled 14:48:46.483 rtp.c pjmedia_rtp_session_init: ses=0x1390824, default_pt=0, ssrc=0x7f2776b6 14:48:46.483 rtp.c pjmedia_rtp_session_init: ses=0x1390e44, default_pt=0, ssrc=0x7f2776b6 streamutil: ../src/pj/sock_common.c:393: pj_sockaddr_get_len: Assertion `a->addr.sa_family == PJ_AF_INET || a->addr.sa_family == PJ_AF_INET6' failed. Aborted (core dumped)
如果您可以帮我修复此错误,请查找附上我的代码。
答案 0 :(得分:0)
#include <pjmedia/rtp.h>
#include <pjlib.h>
#include <pjlib-util.h>
#include <pjmedia.h>
#include <pjmedia-codec.h>
#include <pjmedia/codec.h>
#include <pjmedia/stream.h>
#include <pjmedia/port.h>
#include <pjsip.h>
#include <pjsip_simple.h>
#include <pjsip_ua.h>
#include <pjsua-lib/pjsua.h>
#include <pjsua-lib/pjsua_internal.h>
#include <stdlib.h>
#include <string.h>
#define THIS_FILE "audiotxrtp.c"
#define true 1
#define false 0
#define PJ_INET_ADDRSTRLEN 16
#define ALL_ADDRESSES "0.0.0.0"
#define LOCAL_ADDRESS "127.0.0.1"
#define REMOTE_ADDRESS "192.168.2.2"
#define STREAMMEDIA_SAMPLE_PER_FRAME 160
#define MAX_RTP_PAYLOAD_LENGHT 160
#define MAX_RTP_PACKET_SIZE 200
#define DEFAULT_RTP_PORT 4000
#define PTIME 20
typedef struct RtpSessionCtx_t
{
pjmedia_rtp_session pjInRtpSess;
pjmedia_rtp_session pjOutRtpSess;
pjmedia_port *play_file_port;
pjmedia_port *stream_port;
pjmedia_master_port *master_port;
pjmedia_snd_port *snd_port;
pjmedia_transport* pjTransportPtr;
pjmedia_aud_dev_index dev_idx;
pjmedia_frame play_frame;
pjmedia_stream *stream;
pjmedia_stream_info info;
pjmedia_sock_info sock_info;
pjmedia_codec_info *codec_info;
pjmedia_codec_param codec_param;
pjmedia_dir dir;
pj_caching_pool pjCp;
pj_pool_t *pool;
pjmedia_endpt* pjMedEndptPtr;
}RtpSessionCtx_t;
static RtpSessionCtx_t RtpSession;
static pj_status_t init_codecs(pjmedia_endpt *med_endpt)
{
return pjmedia_codec_register_audio_codecs(med_endpt, NULL);
}
static int rtptest(char *argv[])
{
pj_status_t status;
pj_log_push_indent();
pj_sockaddr_in remoteAddr;
pj_uint16_t remotePort;
pj_uint16_t localPort=DEFAULT_RTP_PORT;
RtpSession.play_file_port = NULL;
RtpSession.master_port = NULL;
RtpSession.stream = NULL;
pj_str_t remoteAddressStr;
pj_timestamp t0,t1;
char rem_addr_str[PJ_INET_ADDRSTRLEN];
enum pjmedia_transport_udp_options
{
/**
* Normally the UDP transport will continuously check the source address
* of incoming packets to see if it is different than the configured
* remote address, and switch the remote address to the source address
* of the packet if they are different after several packets are
* received.
* Specifying this option will disable this feature.
*/
PJMEDIA_UDP_NO_SRC_ADDR_CHECKING = 1
};
pj_bzero(&RtpSession.info.rem_addr.ipv4
,sizeof(&RtpSession.info.rem_addr.ipv4));
status =pj_sockaddr_in_init(&RtpSession.info.rem_addr.ipv4
,(const pj_str_t*)&remoteAddressStr,remotePort);
if (status != PJ_SUCCESS)
{
pjsua_perror(THIS_FILE,"Unable to resolve IP interface--Invalid remote
address",status);
goto on_error;
}
/* Encoding (outgoing to network) stream as known as capture */
RtpSession.dir=PJMEDIA_DIR_ENCODING;
/* Verify arguments. */
if (RtpSession.dir & PJMEDIA_DIR_ENCODING)
{
if (RtpSession.info.rem_addr.ipv4.sin_addr.s_addr == 0)
{
printf("Error: remote address must be set\n");
return 1;
}
}
if (argv[1] != NULL && RtpSession.dir != PJMEDIA_DIR_ENCODING)
{
printf("Direction is set to --send-only because of --play-file\n");
RtpSession.dir = PJMEDIA_DIR_ENCODING;
}
/* initializing the cache pool the pools will exploit the entire cache 3=0
*/
pj_caching_pool_init(&RtpSession.pjCp, &pj_pool_factory_default_policy, 0);
/* create the media endpoint/socket instance and initialize audio subsystem
--card sounds PC
via Alsa
*/
status = pjmedia_endpt_create(&RtpSession.pjCp.factory, NULL, 1,
&RtpSession.pjMedEndptPtr);
if (status == PJ_SUCCESS)
{
puts("\nRTP creation endpoint Successfully \n");
}
else
{
pjsua_perror(THIS_FILE,"RTP endpoint creation failure\n", status);
goto on_error;
}
/* Register all known audio codecs implemented in PJMEDA-CODEC
library to the specified media endpoint. */
status = init_codecs(RtpSession.pjMedEndptPtr);
PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
pjmedia_codec_mgr_get_codec_info(pjmedia_endpt_get_codec_mgr
(RtpSession.pjMedEndptPtr),0
,(const pjmedia_codec_info**)
&RtpSession.codec_info);
/* creating a memory pool for playing file */
RtpSession.pool = pj_pool_create( &RtpSession.pjCp.factory, // pool factory
"wav", /* pool name. */
4000, /* init size 4096 bytes */
4000, /* increment size */
NULL); /* callback on error */
if(RtpSession.pool==NULL)
{
puts("Unable to create memory pool for playing file");
}
else
{
puts("create memory pool for playing file Successful\n");
}
/* Create stream based on program arguments */
RtpSession.pjTransportPtr=NULL;
/* Initialize stream info Format RTP header formats */
RtpSession.info.type = PJMEDIA_TYPE_AUDIO;
/* RTP using Audio/Video profile -- PJMEDIA_TP_PROTO_RTP_SAVP Secure RTP */
RtpSession.info.proto = PJMEDIA_TP_PROTO_RTP_AVP;
RtpSession.info.dir = RtpSession.dir;
/*fmt.clock_rate=8000;fmt.channel=1;fmt.type = PJMEDIA_TYPE_AUDIO;
fmt.encoding_name = "PCMU"*/
pj_memcpy(&RtpSession.info.fmt, RtpSession.codec_info,
sizeof(pjmedia_codec_info));
/* Get codec default param for info */
status = pjmedia_codec_mgr_get_default_param(
pjmedia_endpt_get_codec_mgr(RtpSession.pjMedEndptPtr),
RtpSession.codec_info,&RtpSession.codec_param);
/* Should be ok, as create_stream() above succeeded */
PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
/* Outgoing codec paylaod type -- PCMU */
RtpSession.info.tx_pt = RtpSession.codec_info->pt;
/* Incoming codec paylaod type -- PCMU */
RtpSession.info.rx_pt = RtpSession.codec_info->pt;
/*Outgoing pt for telephone-events=0 Outgoing codec max ptime=0
Incoming pt for telephone-events=0
*/
/* RTP SSRC could be arbitrary
*/
RtpSession.info.ssrc = 1234;
/* Initial RTP timestamp=0 Initial RTP sequence number=0
rtp_seq_ts_set->Bitmask flags if initial RTP sequence and/or timestamp for
sender are set.
bit 0/LSB : sequence flag bit 1 : timestamp flag
Jitter buffer init delay 0 msec
Jitter buffer minimum prefetch delay=0msec
Jitter buffer maximum prefetch delay 0 msec
Jitter buffer max delay 0 msec
Disable automatic sending of RTCP SDES and BYE=0
use_ka?
*/
/* If remote address is not set -- unspecified family adress, set to an
arbitrary address
* (otherwise stream will assert). remote port=0 PJ_AF_UNSPEC loopback
*/
if (RtpSession.info.rem_addr.addr.sa_family == PJ_AF_UNSPEC)
{
const pj_str_t remoteAddrStr = pj_str("127.0.0.1");
pj_sockaddr_in_init(&RtpSession.info.rem_addr.ipv4, &remoteAddrStr, 0);
printf("Remote adress and Port are set to %s:%d\n",
pj_inet_ntop2(PJ_AF_INET,
&RtpSession.info.rem_addr.ipv4.sin_addr, rem_addr_str
,sizeof(rem_addr_str))
,pj_ntohs(RtpSession.info.rem_addr.ipv4.sin_port));
}
status = pjmedia_transport_udp_create(RtpSession.pjMedEndptPtr, NULL,
localPort,0, &RtpSession.pjTransportPtr);
if (status == PJ_SUCCESS)
{
puts("UDP Socket Bind Successfully\n");
/* Log Media Transport */
puts("======== Media transport info ========\n");
pjmedia_transport_info tpinfo;
char addr_buf[80];
/* Initialize transport info */
pjmedia_transport_info_init(&tpinfo);
/* Get media transport info from the specified transport and all underlying
transports if any
The transport also contains information about socket info which describes
the local address
of the transport, and would be needed for example to fill in the "c=" and
"m=" line of local
SDP
*/
pjmedia_transport_get_info(RtpSession.pjTransportPtr, &tpinfo);
/* The RTP socket handle =3
Address to be advertised as the local address for the RTP socket, which
does not need to be equal
as the bound address (for example, this address can be the address
resolved with STUN).
*/
PJ_LOG(3,(THIS_FILE,"\n\n%s: %s\n",
(pjsua_var.media_cfg.enable_ice ? "ICE" : "UDP"),
pj_sockaddr_print(&tpinfo.sock_info.rtp_addr_name
,addr_buf,sizeof(addr_buf),3)));
}
else
{
pjsua_perror(THIS_FILE, " media transport failed ",status);
pjmedia_transport_close(RtpSession.pjTransportPtr );
return status;
}
/* Now that the stream info is initialized, we can create the
stream.
session establishment
*/
status = pjmedia_stream_create(RtpSession.pjMedEndptPtr, RtpSession.pool,
&RtpSession.info,
RtpSession.pjTransportPtr,
NULL, &RtpSession.stream);
if (status != PJ_SUCCESS)
{
pjsua_perror(THIS_FILE,"Error creating stream",status);
pjmedia_transport_close(RtpSession.pjTransportPtr );
return status;
}
/* Get the port interface of the stream */
status = pjmedia_stream_get_port(RtpSession.stream,
&RtpSession.stream_port);
PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
/* Create file media port from the WAV file */
status = pjmedia_wav_player_port_create(RtpSession.pool, // memory pool
argv[1], // file to play
20, // wav_ptime ptime.
0, // flags play whole
-1, // 0 default buffer
&RtpSession.play_file_port);
if (status == PJ_SUCCESS)
{
puts("opening WAV file port");
}
else
{
pjsua_perror(THIS_FILE, "Impossible to create wav file port --Unable to
use file", status);
goto on_error;
}
/* Create bridge */
status = pjmedia_master_port_create(RtpSession.pool,
RtpSession.play_file_port,
RtpSession.stream_port, 0,
&RtpSession.master_port);
if (status != PJ_SUCCESS)
{
pjsua_perror(THIS_FILE, "Unable to create master port", status);
goto on_error;
}
status = pjmedia_master_port_start(RtpSession.master_port);
if (status != PJ_SUCCESS)
{
pjsua_perror(THIS_FILE, "Error starting master port",status);
goto on_error;
}
printf("Playing from WAV file %s..\n", argv[1]);
/* Acquire high resolution timer value. The time value are stored in
cycles*/
pj_get_timestamp(&t0);
/* Start streaming */
pjmedia_stream_start(RtpSession.stream);
printf("Stream is active, dir is send-only, sending to %s:%d\n",
pj_inet_ntop2(PJ_AF_INET, &remoteAddr.sin_addr,
rem_addr_str,sizeof(rem_addr_str)),
pj_ntohs(remoteAddr.sin_port));
pj_get_timestamp(&t1);
PJ_LOG(3,(THIS_FILE, "Completed in %u msec\n", pj_elapsed_msec(&t0, &t1)));
return 0;
on_error:
pj_log_pop_indent(); //log en pop / avec identation à gauche PJ_LOG_INDENT
return status;
}
int main(int argc, char *argv[])
{
pj_status_t status;
char tmp[10];
if (argc != 3)
{
puts("Error: filename and remote adress required");
puts(DescriptionPtr);
return 1;
}
/* Initializing the PJLIB library before using it */
status =pj_init();
PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
puts("\n======== Start Audio implementation Test (audiotxrtp)
========\n");
rtptest(argv);
// pj_thread_sleep(10000); // sleep 10 s /* Sleep to allow log messages
to flush */
/* Without this sleep, Windows/DirectSound will repeteadly
* play the last frame during destroy.
*/
pj_thread_sleep(100);
printf("Playing %s \n", argv[1]);
puts("");
puts("Press <ENTER> to stop playing and quit");
if (fgets(tmp, sizeof(tmp), stdin) == NULL)
{
puts("EOF while reading stdin, will quit now..");
}
/* Start deinitialization: */
/* Destroy master port */
pjmedia_master_port_destroy(RtpSession.master_port, PJ_TRUE);
RtpSession.play_file_port = NULL;
RtpSession.stream = NULL;
/* Destroy stream */
if (RtpSession.stream)
{
pjmedia_transport *tp;
tp = pjmedia_stream_get_transport(RtpSession.stream);
pjmedia_stream_destroy(RtpSession.stream);
pjmedia_transport_close(tp); //app no longer needs media transport
}
status = pjmedia_port_destroy( RtpSession.play_file_port);
PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
pj_pool_release( RtpSession.pool );
pjmedia_endpt_destroy( RtpSession.pjMedEndptPtr );
pj_caching_pool_destroy( &RtpSession.pjCp );
/* Arrêt PJLIB */
pj_shutdown();
return true;
}