Pjsip function is very strong, do SIP RTP voice call Library preferred. After 2.0, video is also supported. However, its video function is collected from the video device by default, then compiled and sent out. Suppose we already have a video source, such as an IP camera, and do not need to collect and encode this process, how to deal with it? Let's say we use the Pjsua included with Pjsip as an example.
The usual method:
1 The video source of course files to deal with, sample has. However, this method is not used much.
2 Modify VID_STREAM.C, in Put_frame and get_frame, change our own video source. This method uses the most, many people in the 1.x version of the support video, this method.
3 This article uses: Re-construct the SDP and create the RTP channel yourself.
The first two ways of thinking directly, the code is not small, especially the second one, need to modify the PJ bottom code.
If based onPjsua do a simple video communication, you can use the method in this article. In fact, the amount of code is not small, but sample provides a reference, the implementation is easier. Here is a brief description:
1 key points on the SDP, Pjsua_call_make_call this function is very convenient to call each other directly. But it does too much work at the bottom, like starting the sound card. Instead of this function, directly with the comparison of the underlying pjsip_inv_send_msg, the work of their own relatively more (but not difficult, but this does not need to pjsua this off-the-shelf program, so we continue to use Pjsua_call_make_call).
But fortunately, the PJ Library provides a number of callbacks, one of which: on_call_sdp_created, which is called back up after the SDP is created and modified by ourselves. For example, we define RTP port g_local_port ourselves.
void on_call_sdp_created (pjsua_call_id call_id,
Pjmedia_sdp_session *SDP,
pj_pool_t *pool,
Const Pjmedia_sdp_session *REM_SDP)
{
int nport;
if (SDP! = NULL)
{
Pjmedia_sdp_media *m = sdp->media[sdp->media_count-1];
M->desc.port = G_local_port;
Pjmedia_sdp_conn *c = sdp->conn;
char* addr;
if (c)
Addr= c->addr.ptr;
Else
{
Const pj_str_t *hostname;
Pj_sockaddr_in tmp_addr;
Char *addr;
hostname = Pj_gethostname ();
Pj_sockaddr_in_init (&TMP_ADDR, hostname, 0);
Addr = Pj_inet_ntoa (TMP_ADDR.SIN_ADDR);
Sdp->conn = (Pjmedia_sdp_conn *) pj_pool_zalloc (pool, sizeof (pjmedia_sdp_conn));
Sdp->conn->net_type = Pj_str ("in");
Sdp->conn->addr_type = Pj_str ("IP4");
Sdp->conn->addr = pj_str (addr);
}
SDP->ORIGIN.ADDR = *pj_gethostname ();
}
}
Similarly, you can modify payload type and so on.
This is when the call is initiated, after the receiver receives the response, it will also trigger this callback, set the RTP port itself, payload type can be.
2
After the call succeeds, the two sides establish a connection relationship, then the RTP data needs to be transmitted. Pjsua put all the work on the ground floor, do not make any changes, only need to send and receive, do some of their own processing on the line.
First say the receiver (refer to SIPRTP.C source):
pj_status_t INIT_LOCAL_RTP ()
{
if (M_binitmedia)
{
Destroy_media ();
}
G_local_port = Local_port;
Pj_caching_pool_init (&CP, &pj_pool_factory_default_policy, 0);
Pool = Pj_pool_create (& (Cp.factory), "test", +, +, NULL);
int status;
Status = Pjmedia_endpt_create (&cp.factory, Pjsip_endpt_get_ioqueue (PJSUA_GET_PJSIP_ENDPT ()), 0, &med_ ENDPT);
Status = Pjmedia_endpt_create (&cp.factory, NULL, 1, &MED_ENDPT);
Status = Pjmedia_rtp_session_init (&video.out_sess, Pj_rand ());
Status = Pjmedia_rtp_session_init (&video.in_sess, 97, 0);
Status = Pjmedia_transport_udp_create (MED_ENDPT, NULL, G_local_port, 0, &video.transport);
M_binitmedia = true;
Video.active = true;
return 0;
}
This code is a local boot RTP port used to receive video data.
Then, from the SDP to get the IP and port sent by the other side, call Pjmedia_transport_attach, to establish the association on it.
The sender also invokes the above function to initialize the local port, but does not require pjmedia_transport_attach. (assuming that the video transmission is single-direction)
Send the action is relatively simple, first to send the data sub-packet, size not more than 1400, then PJMEDIA_RTP_ENCODE_RTP, and then PJMEDIA_TRANSPORT_SEND_RTP.
There is no way to tell what the receiver is going to do with the data, and here is the callback mechanism provided by PJ:
Status = Pjmedia_transport_attach (Video.transport, &video,
&INFO.REM_ADDR,
&REMOTE_ADDR,
Null
sizeof (PJ_SOCKADDR_IN),
&ON_RX_RTP,
NULL);
The ON_RX_RTP in this is the callback that receives the RTP.
Video.transport and other definitions:
struct Media_stream
{
/* Static: */
Unsignedcall_index; /* Call owner.*/
Unsignedmedia_index; /* Media index in call.*/
Pjmedia_transport *transport; /* to SEND/RECV rtp/rtcp*/
/* Active? */
pj_bool_tactive; /* Non-zero if is in call.*/
/* Current Stream Info: */
Pjmedia_stream_infosi; /* Current Stream info.*/
/* More info: */
Unsignedclock_rate; /* Clock rate*/
Unsignedsamples_per_frame; /* Samples per frame*/
Unsignedbytes_per_frame; /* Frame size.*/
/* RTP session: */
pjmedia_rtp_sessionout_sess; /* Outgoing RTP session*/
pjmedia_rtp_sessionin_sess; /* Incoming RTP session*/
/* RTCP Stats: */
Pjmedia_rtcp_session RTCP; /* Incoming RTCP session.*/
/* Thread: */
Pj_bool_tthread_quit_flag; /* Stop Media thread.*/
Pj_thread_t*thread; /* Media thread.*/
};
struct Media_stream video;
SOURCE in: Https://github.com/sxcong/pjsipvideo_demo
Video source RTSP, you can directly use Ipcam, such as Hoi Hong Camera.
SIP Server is an open source Resiprocate, which is compiled for direct use.
The demo program is written by vc2008, including SIP login, send request, send and receive video and decode playback. Two instance tests can be run on the same machine.
But after all, it is demo, just show how to use, details and a lot of problems need to be modified.
From:http://blog.chinaunix.net/uid-15063109-id-4445165.html
Use PJSIP to transfer already encoded video, source code on GitHub