Estudiamos el motor VoIP Mediastreamer2. Parte 6

Material del artículo tomado de mi canal zen .



Transmisión de audio a través de transmisión RTP



En el último artículo, armamos un circuito de control remoto desde un generador y un detector de señales tonales que funcionan dentro de un programa. En este artículo, aprenderemos cómo usar el protocolo RTP (RFC 3550 - RTP: un protocolo de transporte para aplicaciones en tiempo real ) para recibir / transmitir audio a través de una red Ethernet.


RTP (Real Time Protocol) , , , , , . . , .


UDP-, . RTP- . , , , , . , , .


. , , , ..


. RFC3551 (RTP Profile for Audio and Video Conferenceswith Minimal Control) . - - .


, ( MTU). 1500 . , , . . 50 , .. 50 . RTP- RTP-.


, , IP- , . .. , . , RTP- .


, , , , , .


, , , , .. RTCP-. RFC 3605. 200..300 , , . , RTCP- , RTP-. , , , .


, , : . , .


RTP-. , — .


RTP- : MS_RTP_SEND MS_RTP_RECV. RTP-. , RTP-, RTP- . RTP-, MS_RTP_SEND (encoder), 16- , u- (-). decoder.


, ( # include , ):


/*  mstest6.c     . */

#include <mediastreamer2/msfilter.h>
#include <mediastreamer2/msticker.h>
#include <mediastreamer2/dtmfgen.h>
#include <mediastreamer2/mssndcard.h>
#include <mediastreamer2/msvolume.h>
#include <mediastreamer2/mstonedetector.h>
#include <mediastreamer2/msrtp.h>
#include <ortp/rtpsession.h>
#include <ortp/payloadtype.h>

/*       
* .*/
include <mediastreamer2/mseventqueue.h>

#define PCMU 0

/*   ,    ,   
      . */
static void tone_detected_cb(void *data, MSFilter *f, unsigned int event_id,
MSToneDetectorEvent *ev)
{
printf(" : %s\n", ev->tone_name);
}

/*----------------------------------------------------------------------------*/
/*     . */
void register_payloads(void)
{
/*     . ,  
   RTP-     
 ,     . */
rtp_profile_set_payload (&av_profile, PCMU, &payload_type_pcm8000);
}

/*----------------------------------------------------------------------------*/
/*      create_duplex_rtpsession()  audiostream.c
2. */
static RtpSession *
create_rtpsession (int loc_rtp_port, int loc_rtcp_port,
bool_t ipv6, RtpSessionMode mode)
{
RtpSession *rtpr;
rtpr = rtp_session_new ((int) mode);
rtp_session_set_scheduling_mode (rtpr, 0);
rtp_session_set_blocking_mode (rtpr, 0);
rtp_session_enable_adaptive_jitter_compensation (rtpr, TRUE);
rtp_session_set_symmetric_rtp (rtpr, TRUE);
rtp_session_set_local_addr (rtpr, ipv6 ? "::" : "0.0.0.0", loc_rtp_port,
loc_rtcp_port);
rtp_session_signal_connect (rtpr, "timestamp_jump",
(RtpCallback) rtp_session_resync, 0);
rtp_session_signal_connect (rtpr, "ssrc_changed",
(RtpCallback) rtp_session_resync, 0);
rtp_session_set_ssrc_changed_threshold (rtpr, 0);
rtp_session_set_send_payload_type(rtpr, PCMU);

/*    RTCP-,        . */
rtp_session_enable_rtcp (rtpr, FALSE);
return rtpr;
}

/*----------------------------------------------------------------------------*/
int main()
{
ms_init();

/*   . */
MSFilter *voidsource = ms_filter_new(MS_VOID_SOURCE_ID);
MSFilter *dtmfgen = ms_filter_new(MS_DTMF_GEN_ID);
MSFilter *volume = ms_filter_new(MS_VOLUME_ID);
MSSndCard *card_playback =
ms_snd_card_manager_get_default_card(ms_snd_card_manager_get());
MSFilter *snd_card_write = ms_snd_card_create_writer(card_playback);
MSFilter *detector = ms_filter_new(MS_TONE_DETECTOR_ID);

/*      ,  
*    .*/
ms_filter_call_method(detector, MS_TONE_DETECTOR_CLEAR_SCANS, 0);

/*      . */
ms_filter_set_notify_callback(detector,
(MSFilterNotifyFunc)tone_detected_cb, NULL);

/*  ,     
*   ,   :  
*  ,   ,   ,
*    0,775. */
MSToneDetectorDef scan[6]=
{
{"V+",440, 100, 0.1}, /*  " ". */
{"V-",540, 100, 0.1}, /*  " ". */
{"C+",640, 100, 0.1}, /*  "  ". */
{"C-",740, 100, 0.1}, /*  "  ". */
{"ON",840, 100, 0.1}, /*  " ". */
{"OFF", 940, 100, 0.1}/*  " ". */
};

/*  ""   . */
int i;
for (i = 0; i < 6; i++)
{
ms_filter_call_method(detector, MS_TONE_DETECTOR_ADD_SCAN,
&scan[i]);
}

/*      */
MSFilter *encoder = ms_filter_create_encoder("PCMU");
MSFilter *decoder=ms_filter_create_decoder("PCMU");
/*   . */
register_payloads();

/*  RTP- . */
RtpSession *tx_rtp_session = create_rtpsession (8010, 8011, FALSE, RTP_SESSION_SENDONLY);
rtp_session_set_remote_addr_and_port(tx_rtp_session,"127.0.0.1", 7010, 7011);
rtp_session_set_send_payload_type(tx_rtp_session, PCMU);
MSFilter *rtpsend = ms_filter_new(MS_RTP_SEND_ID);
ms_filter_call_method(rtpsend, MS_RTP_SEND_SET_SESSION, tx_rtp_session);

/*  RTP- . */
MSFilter *rtprecv = ms_filter_new(MS_RTP_RECV_ID);
RtpSession *rx_rtp_session = create_rtpsession (7010, 7011, FALSE, RTP_SESSION_RECVONLY);
ms_filter_call_method(rtprecv, MS_RTP_RECV_SET_SESSION, rx_rtp_session);

/*    - . */
MSTicker *ticker_tx = ms_ticker_new();
MSTicker *ticker_rx = ms_ticker_new();

/*   . */
ms_filter_link(voidsource, 0, dtmfgen, 0);
ms_filter_link(dtmfgen, 0, volume, 0);
ms_filter_link(volume, 0, encoder, 0);
ms_filter_link(encoder, 0, rtpsend, 0);

/*   . */
ms_filter_link(rtprecv, 0, decoder, 0);
ms_filter_link(decoder, 0, detector, 0);
ms_filter_link(detector, 0, snd_card_write, 0);

/*   . */
ms_ticker_attach(ticker_tx, voidsource);
ms_ticker_attach(ticker_rx, rtprecv);

/*  ,    . */
MSDtmfGenCustomTone dtmf_cfg;
dtmf_cfg.tone_name[0] = 0;
dtmf_cfg.duration = 1000;
dtmf_cfg.frequencies[0] = 440;
/*    ,      0. */
dtmf_cfg.frequencies[1] = 0;
dtmf_cfg.amplitude = 1.0;
dtmf_cfg.interval = 0.;
dtmf_cfg.repeat_count = 0.;

/*     .   
*    . */
char key='9';
printf("  ,  .\n"
"    0.\n");
while(key != '0')
{
key = getchar();
if ((key >= 49) && (key <= 54))
{
printf(" : %c\n", key);

/*      
 *   . */
dtmf_cfg.frequencies[0] = 440 + 100*(key-49);

/*    c  . */
ms_filter_call_method(dtmfgen, MS_DTMF_GEN_PLAY_CUSTOM,
(void*)&dtmf_cfg);
}

/*      20,   
 *     . */
ms_usleep(20000);
}
}

Compila, corre. El programa funcionará como en el ejemplo anterior, pero los datos se transmitirán a través del flujo RTP.


En el próximo artículo, dividiremos este programa en dos aplicaciones independientes: un receptor y un transmisor y los ejecutaremos en diferentes terminales. En paralelo, aprenderemos cómo analizar paquetes RTP usando TShark.


All Articles