ื—ืงืจ ืžื ื•ืข ื”-VoIP Mediastreamer2. ื—ืœืง 9

ื”ื—ื•ืžืจ ืฉืœ ื”ืžืืžืจ ืœืงื•ื— ืžืžื ื™ ืขืจื•ืฅ ื–ืŸ.

ืื™ื ื˜ืจืงื•ื ื“ื•ืคืœืงืก

ื—ืงืจ ืžื ื•ืข ื”-VoIP Mediastreamer2. ื—ืœืง 9

ื‘ืขื‘ืจ ัั‚ะฐั‚ัŒะต ื”ื•ื›ืจื– ืขืœ ืื™ื ื˜ืจืงื•ื ื“ื•ืคืœืงืก, ื•ื‘ื–ื” ืื ื—ื ื• ื ืขืฉื” ืืช ื–ื”.

ื”ืชืจืฉื™ื ืžื•ืฆื’ ื‘ืื™ื•ืจ ื”ื›ื•ืชืจืช. ืฉืจืฉืจืช ื”ืžืกื ื ื™ื ื”ืชื—ืชื•ื ื” ื™ื•ืฆืจืช ืืช ื ืชื™ื‘ ื”ืฉื™ื“ื•ืจ, ืฉืžืชื—ื™ืœ ืžื›ืจื˜ื™ืก ื”ืงื•ืœ. ื”ื•ื ืžืกืคืง ื“ื’ื™ืžื•ืช ืื•ืช ืžื”ืžื™ืงืจื•ืคื•ืŸ. ื›ื‘ืจื™ืจืช ืžื—ื“ืœ, ื–ื” ืžืชืจื—ืฉ ื‘ืงืฆื‘ ืฉืœ 8000 ื“ื’ื™ืžื•ืช ื‘ืฉื ื™ื™ื”. ืขื•ืžืง ืกื™ื‘ื™ื•ืช ื”ื ืชื•ื ื™ื ืฉื‘ื• ืžืฉืชืžืฉื™ื ืžืกื ื ื™ ืื•ื“ื™ื• ืฉืœ ืกื˜ืจื™ืžืจ ืžื“ื™ื” ื”ื•ื 16 ืกื™ื‘ื™ื•ืช (ื–ื” ืœื ื—ืฉื•ื‘; ืื ืชืจืฆื”, ืชื•ื›ืœ ืœื›ืชื•ื‘ ืžืกื ื ื™ื ืฉื™ืขื‘ื“ื• ืขื ืขื•ืžืง ืกื™ื‘ื™ื•ืช ื’ื‘ื•ื” ื™ื•ืชืจ). ื”ื ืชื•ื ื™ื ืžืงื•ื‘ืฆื™ื ืœื‘ืœื•ืงื™ื ืฉืœ 160 ื“ื’ื™ืžื•ืช. ืœืคื™ื›ืš, ื›ืœ ื‘ืœื•ืง ื”ื•ื ื‘ื’ื•ื“ืœ 320 ื‘ืชื™ื. ืœืื—ืจ ืžื›ืŸ, ื ื–ื™ืŸ ืืช ื”ื ืชื•ื ื™ื ืœืงืœื˜ ืฉืœ ื”ื’ื ืจื˜ื•ืจ, ืฉื›ืืฉืจ ื”ื•ื ื›ื‘ื•ื™, ื”ื•ื "ืฉืงื•ืฃ" ืœื ืชื•ื ื™ื. ื”ื•ืกืคืชื™ ืืช ื–ื” ืœืžืงืจื” ืฉื ืžืืก ืœืš ืœื“ื‘ืจ ืœืžื™ืงืจื•ืคื•ืŸ ื‘ืžื”ืœืš ืื™ืชื•ืจ ื‘ืื’ื™ื - ืืชื” ื™ื›ื•ืœ ืœื”ืฉืชืžืฉ ื‘ืžื—ื•ืœืœ ื›ื“ื™ "ืœื™ืจื•ืช" ืืช ื”ื ืชื™ื‘ ืขื ืื•ืช ืฆืœื™ืœ.

ืœืื—ืจ ื”ืžื—ื•ืœืœ, ื”ืื•ืช ืขื•ื‘ืจ ืœืžืงื•ื“ื“, ืืฉืจ ืžืžื™ืจ ืืช ื”ื“ื’ื™ืžื•ืช ืฉืœื ื• ื‘-16 ืกื™ื‘ื™ื•ืช ืœืคื™ ื—ื•ืง ื”-ยต (ืชืงืŸ G.711) ืœื“ื’ื™ืžื•ืช ืฉืœ ืฉืžื•ื ื” ืกื™ื‘ื™ื•ืช. ื‘ื™ืฆื™ืื” ืฉืœ ื”ืžืงื•ื“ื“, ื™ืฉ ืœื ื• ื›ื‘ืจ ื‘ืœื•ืง ื ืชื•ื ื™ื ื‘ื’ื•ื“ืœ ื—ืฆื™ ืžื”ื’ื•ื“ืœ. ื‘ืื•ืคืŸ ื›ืœืœื™, ืื ื• ื™ื›ื•ืœื™ื ืœื”ืขื‘ื™ืจ ื ืชื•ื ื™ื ืœืœื ื“ื—ื™ืกื” ืื ืื™ื ื ื• ืฆืจื™ื›ื™ื ืœื—ืกื•ืš ื‘ืชื ื•ืขื”. ืื‘ืœ ื›ืืŸ ื–ื” ืฉื™ืžื•ืฉื™ ืœื”ืฉืชืžืฉ ื‘ืžืงื•ื“ื“, ืžื›ื™ื•ื•ืŸ ืฉ-Wireshark ื™ื›ื•ืœ ืœืฉื—ื–ืจ ืื•ื“ื™ื• ืžื–ืจื RTP ืจืง ื›ืืฉืจ ื”ื•ื ื“ื—ื•ืก ืœืคื™ ื—ื•ืง ยต ืื• ื-ื—ื•ืง.

ืœืื—ืจ ื”ืžืงื•ื“ื“, ื’ื•ืฉื™ ื”ื ืชื•ื ื™ื ื”ืงืœื™ื ื™ื•ืชืจ ื ืฉืœื—ื™ื ืœืžืกื ืŸ rtpsend, ืฉื™ื›ื ื™ืก ืื•ืชื ืœื—ื‘ื™ืœืช RTP, ื™ืงื‘ืข ืืช ื”ื“ื’ืœื™ื ื”ื“ืจื•ืฉื™ื ื•ื™ืขื‘ื™ืจ ืื•ืชื ืœืกื˜ืจื™ืžืจ ื”ืžื“ื™ื” ืœืฉื™ื“ื•ืจ ื‘ืจืฉืช ื‘ืฆื•ืจื” ืฉืœ ื—ื‘ื™ืœืช UDP.

ืฉืจืฉืจืช ื”ืžืกื ื ื™ื ื”ืขืœื™ื•ื ื” ืžื”ื•ื•ื” ืืช ื ืชื™ื‘ ื”ืงื‘ืœื”; ืžื ื•ืช RTP ื”ืžืชืงื‘ืœื•ืช ืขืœ ื™ื“ื™ ืกื˜ืจื™ืžืจ ื”ืžื“ื™ื” ืžื”ืจืฉืช ื ื›ื ืกื•ืช ืœืžืกื ืŸ rtprecv, ืฉื‘ืคืœื˜ ืฉืœื• ื”ืŸ ืžื•ืคื™ืขื•ืช ื‘ืฆื•ืจื” ืฉืœ ื‘ืœื•ืงื™ ื ืชื•ื ื™ื, ืฉื›ืœ ืื—ื“ ืžื”ื ืžืชืื™ื ืœื—ื‘ื™ืœื” ืื—ืช ืฉื”ืชืงื‘ืœื”. ื”ื‘ืœื•ืง ืžื›ื™ืœ ืจืง ื ืชื•ื ื™ ืžื˜ืขืŸ; ื‘ืžืืžืจ ื”ืงื•ื“ื ื”ื ื”ื•ืฆื’ื• ื‘ื™ืจื•ืง ื‘ืื™ื•ืจ.

ืœืื—ืจ ืžื›ืŸ, ื”ื‘ืœื•ืงื™ื ื ืฉืœื—ื™ื ืœืžืกื ืŸ ื”ืžืคืขื ื—, ืืฉืจ ืžืžื™ืจ ืืช ื”ื“ื’ื™ืžื•ืช ืฉืœ ื‘ืชื™ื ื‘ื•ื“ื“ื™ื ื”ื›ืœื•ืœื™ื ื‘ื”ื ืœื“ื•ื’ืžืื•ืช ืœื™ื ื™ืืจื™ื•ืช ืฉืœ 16 ืกื™ื‘ื™ื•ืช. ืžื” ืฉื›ื‘ืจ ื ื™ืชืŸ ืœืขื™ื‘ื•ื“ ืขืœ ื™ื“ื™ ืžืกื ื ื™ ืกื˜ืจื™ืžืจ ืžื“ื™ื”. ื‘ืžืงืจื” ืฉืœื ื•, ืื ื—ื ื• ืคืฉื•ื˜ ืฉื•ืœื—ื™ื ืื•ืชื ืœื›ืจื˜ื™ืก ื”ืงื•ืœ ืœื”ืฉืžืขื” ื‘ืจืžืงื•ืœื™ื ืฉืœ ื”ืื•ื–ื ื™ื•ืช ืฉืœืš.

ื›ืขืช ื ืขื‘ื•ืจ ืœื™ื™ืฉื•ื ืชื•ื›ื ื”. ืœืฉื ื›ืš ื ืฉืœื‘ ืืช ืงื‘ืฆื™ ื”ืžืงืœื˜ ื•ื”ืžืฉื“ืจ ืฉื”ืคืจื“ื ื• ืงื•ื“ื ืœื›ืŸ. ืœืคื ื™ ื›ืŸ, ื”ืฉืชืžืฉื ื• ื‘ื”ื’ื“ืจื•ืช ืงื‘ื•ืขื•ืช ืขื‘ื•ืจ ื™ืฆื™ืื•ืช ื•ื›ืชื•ื‘ื•ืช, ืืš ื›ืขืช ืื ื• ืฆืจื™ื›ื™ื ืฉื”ืชื•ื›ื ื™ืช ืชื•ื›ืœ ืœื”ืฉืชืžืฉ ื‘ื”ื’ื“ืจื•ืช ืฉืื ื• ืžืฆื™ื™ื ื™ื ื‘ืขืช ื”ื”ืคืขืœื”. ืœืฉื ื›ืš, ื ื•ืกื™ืฃ ืคื•ื ืงืฆื™ื•ื ืœื™ื•ืช ืœืขื™ื‘ื•ื“ ืืจื’ื•ืžื ื˜ื™ื ืฉืœ ืฉื•ืจืช ื”ืคืงื•ื“ื”. ืœืื—ืจ ืžื›ืŸ ื ื•ื›ืœ ืœื”ื’ื“ื™ืจ ืืช ื›ืชื•ื‘ืช ื”-IP ื•ื”ื™ืฆื™ืื” ืฉืœ ื”ืื™ื ื˜ืจืงื•ื ืื™ืชื• ื ืจืฆื” ืœื™ืฆื•ืจ ื—ื™ื‘ื•ืจ.

ืจืืฉื™ืช, ื‘ื•ืื• ื ื•ืกื™ืฃ ืžื‘ื ื” ืœืชื•ื›ื ื™ืช ืฉื™ืื—ืกืŸ ืืช ื”ื”ื’ื“ืจื•ืช ืฉืœื”:

struct _app_vars
{
  int  local_port;              /* ะ›ะพะบะฐะปัŒะฝั‹ะน ะฟะพั€ั‚. */
  int  remote_port;             /* ะŸะพั€ั‚ ะฟะตั€ะตะณะพะฒะพั€ะฝะพะณะพ ัƒัั‚ั€ะพะนัั‚ะฒะฐ ะฝะฐ ัƒะดะฐะปะตะฝะฝะพะผ ะบะพะผะฟัŒัŽั‚ะตั€ะต. */
  char remote_addr[128];        /* IP-ะฐะดั€ะตั ัƒะดะฐะปะตะฝะฝะพะณะพ ะบะพะผะฟัŒัŽั‚ะตั€ะฐ. */
  MSDtmfGenCustomTone dtmf_cfg; /* ะะฐัั‚ั€ะพะนะบะธ ั‚ะตัั‚ะพะฒะพะณะพ ัะธะณะฝะฐะปะฐ ะณะตะฝะตั€ะฐั‚ะพั€ะฐ. */
};

typedef struct _app_vars app_vars;

ื”ืชื•ื›ื ื™ืช ืชื›ืจื™ื– ืขืœ ืžื‘ื ื” ืžืกื•ื’ ื–ื” ื”ื ืงืจื vars.
ืœืื—ืจ ืžื›ืŸ, ื‘ื•ืื• ื ื•ืกื™ืฃ ืคื•ื ืงืฆื™ื” ืœื ืชื— ืืจื’ื•ืžื ื˜ื™ื ืฉืœ ืฉื•ืจืช ื”ืคืงื•ื“ื”:

/* ะคัƒะฝะบั†ะธั ะฟั€ะตะพะฑั€ะฐะทะพะฒะฐะฝะธั ะฐั€ะณัƒะผะตะฝั‚ะพะฒ ะบะพะผะฐะฝะดะฝะพะน ัั‚ั€ะพะบะธ ะฒ
* ะฝะฐัั‚ั€ะพะนะบะธ ะฟั€ะพะณั€ะฐะผะผั‹. */
void  scan_args(int argc, char *argv[], app_vars *v)
{
    char i;
    for (i=0; i<argc; i++)
    {
        if (!strcmp(argv[i], "--help"))
        {
            char *p=argv[0]; p=p + 2;
            printf("  %s walkie talkienn", p);
            printf("--help      List of options.n");
            printf("--version   Version of application.n");
            printf("--addr      Remote abonent IP address string.n");
            printf("--port      Remote abonent port number.n");
            printf("--lport     Local port number.n");
            printf("--gen       Generator frequency.n");
            exit(0);
        }

        if (!strcmp(argv[i], "--version"))
        {
            printf("0.1n");
            exit(0);
        }

        if (!strcmp(argv[i], "--addr"))
        {
            strncpy(v->remote_addr, argv[i+1], 16);
            v->remote_addr[16]=0;
            printf("remote addr: %sn", v->remote_addr);
        }

        if (!strcmp(argv[i], "--port"))
        {
            v->remote_port=atoi(argv[i+1]);
            printf("remote port: %in", v->remote_port);
        }

        if (!strcmp(argv[i], "--lport"))
        {
            v->local_port=atoi(argv[i+1]);
            printf("local port : %in", v->local_port);
        }

        if (!strcmp(argv[i], "--gen"))
        {
            v -> dtmf_cfg.frequencies[0] = atoi(argv[i+1]);
                printf("gen freq : %in", v -> dtmf_cfg.frequencies[0]);
        }
    }
}

ื›ืชื•ืฆืื” ืžื ื™ืชื•ื—, ื”ืืจื’ื•ืžื ื˜ื™ื ืฉืœ ืฉื•ืจืช ื”ืคืงื•ื“ื” ื™ืžื•ืงืžื• ื‘ืฉื“ื•ืช ืฉืœ ืžื‘ื ื” vars. ืชืคืงื™ื“ื” ื”ืขื™ืงืจื™ ืฉืœ ื”ืืคืœื™ืงืฆื™ื” ื™ื”ื™ื” ืœืืกื•ืฃ ื ืชื™ื‘ื™ ืฉื™ื“ื•ืจ ื•ืงื‘ืœื” ืžืคื™ืœื˜ืจื™ื; ืœืื—ืจ ื—ื™ื‘ื•ืจ ื”ื˜ื™ืงืจ, ื”ืฉืœื™ื˜ื” ืชื•ืขื‘ืจ ืœืœื•ืœืื” ืื™ื ืกื•ืคื™ืช ืืฉืจ ืื ืชื“ืจ ื”ืžื—ื•ืœืœ ื”ื•ื’ื“ืจ ืœืœื ืืคืก, ืชืคืขื™ืœ ืžื—ื“ืฉ ืืช ืžื—ื•ืœืœ ื”ื‘ื“ื™ืงื” ื›ืš ืฉ ื–ื” ืขื•ื‘ื“ ื‘ืœื™ ืœื”ืคืกื™ืง.

ื”ื’ื ืจื˜ื•ืจ ื™ื–ื“ืงืง ืœืืชื—ื•ืœื™ื ืืœื” ื‘ืฉืœ ื”ืขื™ืฆื•ื‘ ืฉืœื•; ืžืฉื•ื ืžื” ื”ื•ื ืœื ื™ื›ื•ืœ ืœื”ืคื™ืง ืื•ืช ืฉื ืžืฉืš ื™ื•ืชืจ ืž-16 ืฉื ื™ื•ืช. ื™ืฉ ืœืฆื™ื™ืŸ ื›ื™ ืžืฉืš ื”ื–ืžืŸ ืฉืœื• ืžืฆื•ื™ืŸ ื‘ืžืกืคืจ 32 ืกื™ื‘ื™ื•ืช.

ื›ืœ ื”ืชื•ื›ื ื™ืช ืชื™ืจืื” ื›ืš:

/* ะคะฐะนะป mstest8.c ะ˜ะผะธั‚ะฐั‚ะพั€ ะฟะตั€ะตะณะพะฒะพั€ะฝะพะณะพ ัƒัั‚ั€ะพะนัั‚ะฒะฐ. */

#include <mediastreamer2/mssndcard.h>
#include <mediastreamer2/dtmfgen.h>
#include <mediastreamer2/msrtp.h>

/* ะŸะพะดะบะปัŽั‡ะฐะตะผ ั„ะฐะนะป ะพะฑั‰ะธั… ั„ัƒะฝะบั†ะธะน. */
#include "mstest_common.c"

/*----------------------------------------------------------*/
struct _app_vars
{
    int  local_port;              /* ะ›ะพะบะฐะปัŒะฝั‹ะน ะฟะพั€ั‚. */
    int  remote_port;             /* ะŸะพั€ั‚ ะฟะตั€ะตะณะพะฒะพั€ะฝะพะณะพ ัƒัั‚ั€ะพะนัั‚ะฒะฐ ะฝะฐ ัƒะดะฐะปะตะฝะฝะพะผ ะบะพะผะฟัŒัŽั‚ะตั€ะต. */
    char remote_addr[128];        /* IP-ะฐะดั€ะตั ัƒะดะฐะปะตะฝะฝะพะณะพ ะบะพะผะฟัŒัŽั‚ะตั€ะฐ. */
    MSDtmfGenCustomTone dtmf_cfg; /* ะะฐัั‚ั€ะพะนะบะธ ั‚ะตัั‚ะพะฒะพะณะพ ัะธะณะฝะฐะปะฐ ะณะตะฝะตั€ะฐั‚ะพั€ะฐ. */
};

typedef struct _app_vars app_vars;

/*----------------------------------------------------------*/
/* ะกะพะทะดะฐะตะผ ะดัƒะฟะปะตะบัะฝัƒัŽ RTP-ัะตััะธัŽ. */
RtpSession* create_duplex_rtp_session(app_vars v)
{
    RtpSession *session = create_rtpsession (v.local_port, v.local_port + 1, FALSE, RTP_SESSION_SENDRECV);
    rtp_session_set_remote_addr_and_port(session, v.remote_addr, v.remote_port, v.remote_port + 1);
    rtp_session_set_send_payload_type(session, PCMU);
    return session;
}

/*----------------------------------------------------------*/
/* ะคัƒะฝะบั†ะธั ะฟั€ะตะพะฑั€ะฐะทะพะฒะฐะฝะธั ะฐั€ะณัƒะผะตะฝั‚ะพะฒ ะบะพะผะฐะฝะดะฝะพะน ัั‚ั€ะพะบะธ ะฒ
* ะฝะฐัั‚ั€ะพะนะบะธ ะฟั€ะพะณั€ะฐะผะผั‹. */
void  scan_args(int argc, char *argv[], app_vars *v)
{
    char i;
    for (i=0; i<argc; i++)
    {
        if (!strcmp(argv[i], "--help"))
        {
            char *p=argv[0]; p=p + 2;
            printf("  %s walkie talkienn", p);
            printf("--help      List of options.n");
            printf("--version   Version of application.n");
            printf("--addr      Remote abonent IP address string.n");
            printf("--port      Remote abonent port number.n");
            printf("--lport     Local port number.n");
            printf("--gen       Generator frequency.n");
            exit(0);
        }

        if (!strcmp(argv[i], "--version"))
        {
            printf("0.1n");
            exit(0);
        }

        if (!strcmp(argv[i], "--addr"))
        {
            strncpy(v->remote_addr, argv[i+1], 16);
            v->remote_addr[16]=0;
            printf("remote addr: %sn", v->remote_addr);
        }

        if (!strcmp(argv[i], "--port"))
        {
            v->remote_port=atoi(argv[i+1]);
            printf("remote port: %in", v->remote_port);
        }

        if (!strcmp(argv[i], "--lport"))
        {
            v->local_port=atoi(argv[i+1]);
            printf("local port : %in", v->local_port);
        }

        if (!strcmp(argv[i], "--gen"))
        {
            v -> dtmf_cfg.frequencies[0] = atoi(argv[i+1]);
                printf("gen freq : %in", v -> dtmf_cfg.frequencies[0]);
        }
    }
}

/*----------------------------------------------------------*/
int main(int argc, char *argv[])
{
    /* ะฃัั‚ะฐะฝะฐะฒะปะธะฒะฐะตะผ ะฝะฐัั‚ั€ะพะนะบะธ ะฟะพ ัƒะผะพะปั‡ะฐะฝะธัŽ. */
    app_vars vars={5004, 7010, "127.0.0.1", {0}};

    /* ะฃัั‚ะฐะฝะฐะฒะปะธะฒะฐะตะผ ะฝะฐัั‚ั€ะพะนะบะธ ะฝะฐัั‚ั€ะพะนะบะธ ะฟั€ะพะณั€ะฐะผะผั‹ ะฒ
     * ัะพะพั‚ะฒะตั‚ัั‚ะฒะธะธ ั ะฐั€ะณัƒะผะตะฝั‚ะฐะผะธ ะบะพะผะฐะฝะดะฝะพะน ัั‚ั€ะพะบะธ. */
    scan_args(argc, argv, &vars);

    ms_init();

    /* ะกะพะทะดะฐะตะผ ัะบะทะตะผะฟะปัั€ั‹ ั„ะธะปัŒั‚ั€ะพะฒ ะฟะตั€ะตะดะฐัŽั‰ะตะณะพ ั‚ั€ะฐะบั‚ะฐ. */
    MSSndCard *snd_card =
        ms_snd_card_manager_get_default_card(ms_snd_card_manager_get());
    MSFilter *snd_card_read = ms_snd_card_create_reader(snd_card);
    MSFilter *dtmfgen = ms_filter_new(MS_DTMF_GEN_ID);
    MSFilter *rtpsend = ms_filter_new(MS_RTP_SEND_ID);

    /* ะกะพะทะดะฐะตะผ ั„ะธะปัŒั‚ั€ ะบะพะดะตั€ะฐ. */
    MSFilter *encoder = ms_filter_create_encoder("PCMU");

    /* ะ ะตะณะธัั‚ั€ะธั€ัƒะตะผ ั‚ะธะฟั‹ ะฝะฐะณั€ัƒะทะบะธ. */
    register_payloads();

    /* ะกะพะทะดะฐะตะผ ะดัƒะฟะปะตะบัะฝัƒัŽ RTP-ัะตััะธัŽ. */
    RtpSession* rtp_session= create_duplex_rtp_session(vars);
    ms_filter_call_method(rtpsend, MS_RTP_SEND_SET_SESSION, rtp_session);

    /* ะกะพะตะดะธะฝัะตะผ ั„ะธะปัŒั‚ั€ั‹ ะฟะตั€ะตะดะฐั‚ั‡ะธะบะฐ. */
    ms_filter_link(snd_card_read, 0, dtmfgen, 0);
    ms_filter_link(dtmfgen, 0, encoder, 0);
    ms_filter_link(encoder, 0, rtpsend, 0);

    /* ะกะพะทะดะฐะตะผ ั„ะธะปัŒั‚ั€ั‹ ะฟั€ะธะตะผะฝะพะณะพ ั‚ั€ะฐะบั‚ะฐ. */
    MSFilter *rtprecv = ms_filter_new(MS_RTP_RECV_ID);
    ms_filter_call_method(rtprecv, MS_RTP_RECV_SET_SESSION, rtp_session);

    /* ะกะพะทะดะฐะตะผ ั„ะธะปัŒั‚ั€ ะดะตะบะพะดะตั€ะฐ, */
    MSFilter *decoder=ms_filter_create_decoder("PCMU");

    /* ะกะพะทะดะฐะตะผ ั„ะธะปัŒั‚ั€ ะทะฒัƒะบะพะฒะพะน ะบะฐั€ั‚ั‹. */
    MSFilter *snd_card_write = ms_snd_card_create_writer(snd_card);

    /* ะกะพะตะดะธะฝัะตะผ ั„ะธะปัŒั‚ั€ั‹ ะฟั€ะธั‘ะผะฝะพะณะพ ั‚ั€ะฐะบั‚ะฐ. */
    ms_filter_link(rtprecv, 0, decoder, 0);
    ms_filter_link(decoder, 0,  snd_card_write, 0);

    /* ะกะพะทะดะฐะตะผ ะธัั‚ะพั‡ะฝะธะบ ั‚ะฐะบั‚ะพะฒ - ั‚ะธะบะตั€. */
    MSTicker *ticker = ms_ticker_new();

    /* ะŸะพะดะบะปัŽั‡ะฐะตะผ ะธัั‚ะพั‡ะฝะธะบ ั‚ะฐะบั‚ะพะฒ. */
    ms_ticker_attach(ticker, snd_card_read);
    ms_ticker_attach(ticker, rtprecv);

    /* ะ•ัะปะธ ะฝะฐัั‚ั€ะพะนะบะฐ ั‡ะฐัั‚ะพั‚ั‹ ะณะตะฝะตั€ะฐั‚ะพั€ะฐ ะพั‚ะปะธั‡ะฝะฐ ะพั‚ ะฝัƒะปั, ั‚ะพ ะทะฐะฟัƒัะบะฐะตะผ ะณะตะฝะตั€ะฐั‚ะพั€. */   
    if (vars.dtmf_cfg.frequencies[0])
    {
        /* ะะฐัั‚ั€ะฐะธะฒะฐะตะผ ัั‚ั€ัƒะบั‚ัƒั€ัƒ, ัƒะฟั€ะฐะฒะปััŽั‰ัƒัŽ ะฒั‹ั…ะพะดะฝั‹ะผ ัะธะณะฝะฐะปะพะผ ะณะตะฝะตั€ะฐั‚ะพั€ะฐ. */
        vars.dtmf_cfg.duration = 10000;
        vars.dtmf_cfg.amplitude = 1.0;
    }

    /* ะžั€ะณะฐะฝะธะทัƒะตะผ ั†ะธะบะป ะฟะตั€ะตะทะฐะฟัƒัะบะฐ ะณะตะฝะตั€ะฐั‚ะพั€ะฐ. */
    while(TRUE)
    {
        if(vars.dtmf_cfg.frequencies[0])
        {
            /* ะ’ะบะปัŽั‡ะฐะตะผ ะทะฒัƒะบะพะฒะพะน ะณะตะฝะตั€ะฐั‚ะพั€. */
            ms_filter_call_method(dtmfgen, MS_DTMF_GEN_PLAY_CUSTOM,
                    (void*)&vars.dtmf_cfg);
        }
        /* ะฃะบะปะฐะดั‹ะฒะฐะตะผ ั‚ั€ะตะด ะฒ ัะฟัั‡ะบัƒ ะฝะฐ 20ะผั, ั‡ั‚ะพะฑั‹ ะดั€ัƒะณะธะต ั‚ั€ะตะดั‹
         * ะฟั€ะธะปะพะถะตะฝะธั ะฟะพะปัƒั‡ะธะปะธ ะฒั€ะตะผั ะฝะฐ ั€ะฐะฑะพั‚ัƒ. */
        ms_usleep(20000);
    }
}

ื‘ื•ืื• ื ืขืฉื” ืงื•ืžืคื™ืœืฆื™ื”. ืœืื—ืจ ืžื›ืŸ ื ื™ืชืŸ ืœื”ืคืขื™ืœ ืืช ื”ืชื•ื›ื ื™ืช ื‘ืฉื ื™ ืžื—ืฉื‘ื™ื. ืื• ืขืœ ืื—ื“, ื›ืคื™ ืฉืืขืฉื” ืขื›ืฉื™ื•. ืื ื• ืžืฉื™ืงื™ื ืืช TShark ืขื ื”ื˜ื™ืขื•ื ื™ื ื”ื‘ืื™ื:

$ sudo tshark -i lo -f "udp dst port 7010" -P -V -O RTP -o rtp.heuristic_rtp:TRUE -x

ืื ืฉื“ื” ื”ื”ืฉืงื” ื‘ืžืกื•ืฃ ืžืฆื™ื’ ืจืง ื”ื•ื“ืขื” ืขืœ ืชื—ื™ืœืช ื”ืœื›ื™ื“ื”, ืื– ื–ื” ืกื™ืžืŸ ื˜ื•ื‘ - ื–ื” ืื•ืžืจ ืฉื”ื™ืฆื™ืื” ืฉืœื ื• ื›ื ืจืื” ืœื ืชืคื•ืกื” ืขืœ ื™ื“ื™ ืชื•ื›ื ื™ื•ืช ืื—ืจื•ืช. ื‘ื˜ืจืžื™ื ืœ ืื—ืจ, ืื ื• ืžืฉื™ืงื™ื ืžื•ืคืข ืชื•ื›ื ื™ืช ืฉื™ื“ืžื” ืื™ื ื˜ืจืงื•ื "ืžืจื•ื—ืง" ืขืœ ื™ื“ื™ ืฆื™ื•ืŸ ืžืกืคืจ ื”ื™ืฆื™ืื” ื”ื–ื”:

$ ./mstest8 --port 9010 --lport 7010

ื›ืคื™ ืฉื ื™ืชืŸ ืœืจืื•ืช ืžื˜ืงืกื˜ ื”ืชื•ื›ื ื™ืช, ื›ืชื•ื‘ืช ื”-IP ื”ืžื•ื’ื“ืจืช ื›ื‘ืจื™ืจืช ืžื—ื“ืœ ื”ื™ื 127.0.0.1 (ืœื•ืœืื” ื—ื•ื–ืจืช ืžืงื•ืžื™ืช).

ื‘ื˜ืจืžื™ื ืœ ืื—ืจ, ืื ื• ืžืฉื™ืงื™ื ืžื•ืคืข ืฉื ื™ ืฉืœ ื”ืชื•ื›ื ื™ืช, ื”ืžื“ืžื” ืžื›ืฉื™ืจ ืžืงื•ืžื™. ืื ื• ืžืฉืชืžืฉื™ื ื‘ืืจื’ื•ืžื ื˜ ื ื•ืกืฃ ื”ืžืืคืฉืจ ืœืžื—ื•ืœืœ ื”ื‘ื“ื™ืงื•ืช ื”ืžื•ื‘ื ื” ืœืขื‘ื•ื“:

$ ./mstest8  --port 7010 --lport 9010 --gen 440

ื‘ืจื’ืข ื–ื”, ืžื ื•ืช ื”ืžื•ืขื‘ืจื•ืช ืœื›ื™ื•ื•ืŸ ื”ืžื›ืฉื™ืจ ื”"ืžืจื•ื—ืง" ืืžื•ืจื•ืช ืœื”ืชื—ื™ืœ ืœื”ื‘ื”ื‘ ื‘ืงื•ื ืกื•ืœื” ืขื TShark, ื•ืงื•ืœ ืจืฆื™ืฃ ื™ื™ืฉืžืข ืžืจืžืงื•ืœ ื”ืžื—ืฉื‘.

ืื ื”ื›ืœ ืงืจื” ื›ืคื™ ืฉื ื›ืชื‘, ืื ื• ืžืคืขื™ืœื™ื ืžื—ื“ืฉ ืืช ื”ืขื•ืชืง ื”ืฉื ื™ ืฉืœ ื”ืชื•ื›ื ื™ืช, ืืš ืœืœื ื”ืžืคืชื— ื•ื”ื˜ื™ืขื•ืŸ "-gen 440". ื›ืขืช ืชืฉื—ืง ืืช ื”ืชืคืงื™ื“ ืฉืœ ืžื—ื•ืœืœ. ืœืื—ืจ ืžื›ืŸ, ืืชื” ื™ื›ื•ืœ ืœืขืฉื•ืช ืจืขืฉ ืœืชื•ืš ื”ืžื™ืงืจื•ืคื•ืŸ; ืืชื” ืืžื•ืจ ืœืฉืžื•ืข ืืช ื”ืฆืœื™ืœ ื”ืžืชืื™ื ื‘ืจืžืงื•ืœ ืื• ื‘ืื•ื–ื ื™ื•ืช. ืขื™ืจื•ืจ ืขืฆืžื™ ืืงื•ืกื˜ื™ ืขืฉื•ื™ ืืคื™ืœื• ืœื”ืชืจื—ืฉ; ื”ื ืžื™ืš ืืช ืขื•ืฆืžืช ื”ืงื•ืœ ืฉืœ ื”ืจืžืงื•ืœ ื•ื”ืืคืงื˜ ื™ื™ืขืœื.

ืื ื”ืจืฆืชื ืื•ืชื• ืขืœ ืฉื ื™ ืžื—ืฉื‘ื™ื ื•ืœื ื”ืชื‘ืœื‘ืœืชื ืœื’ื‘ื™ ื›ืชื•ื‘ื•ืช ื”-IP, ืื– ืื•ืชื” ืชื•ืฆืื” ืžื—ื›ื” ืœื›ื - ืชืงืฉื•ืจืช ืงื•ืœื™ืช ื‘ืื™ื›ื•ืช ื“ื•-ื›ื™ื•ื•ื ื™ืช.

ื‘ืžืืžืจ ื”ื‘ื ื ืœืžื“ ื›ื™ืฆื“ ืœื›ืชื•ื‘ ืคื™ืœื˜ืจื™ื ืžืฉืœื ื• - ืชื•ืกืคื™ื, ื”ื•ื“ื•ืช ืœืžื™ื•ืžื ื•ืช ื–ื• ืชื•ื›ืœื• ืœื”ืฉืชืžืฉ ื‘ืกื˜ืจื™ืžืจ ื”ืžื“ื™ื” ืœื ืจืง ืขื‘ื•ืจ ืื•ื“ื™ื• ื•ื•ื™ื“ืื•, ืืœื ื’ื ื‘ืื–ื•ืจ ืžืกื•ื™ื ืื—ืจ.

ืžืงื•ืจ: www.habr.com

ื”ื•ืกืคืช ืชื’ื•ื‘ื”