想用VC做一个流媒体播放器,功能就想网络电台一样,由服务端和客户端组成
服务端就像一个常规播放器一样,他放什么,客户端就听见什么。
数据传输我打算用RTP,从网上当了一个库jrtplib,据说很多人用,
但是我不知道怎么把他用进去,jrtplib的英文文档也看了,说得太简单,不详细。哪位用过jrtplib或着熟悉RTP的给我点指导,不胜感激!
如果有做好的流媒体播放器的代码更好,可以另贴结分!
谢谢!!

解决方案 »

  1.   

    jrtplib文挡写得很清楚的,你怎么会看不明白呢?
      

  2.   

    我把里面的例子稍稍改了一下,以便在Windows下运行,代码如下:
    int main(void)
    {
    RTPSession sess;
    int portbase;
    unsigned long destip;
    int destport;
    char ipstr[255];
    int status,i;
    char dummybuffer[1024];
    WSADATA wsaData;
    WORD wVersionRequested;
    int err; wVersionRequested = MAKEWORD(2, 2);
            /*
               First, we'll ask for the necessary information
            */
    err=WSAStartup(wVersionRequested,&wsaData) ;
    if(err!=0)
    // if(WSAStartup(0x101, &wsaData))
    printf("Socket Initialize Error!\n");

    printf("Enter the local portbase\n");
    scanf("%d",&portbase);
    printf("\n");

    printf("Enter the destination IP address\n");
    scanf("%s",ipstr);
    destip = inet_addr(ipstr);
    if (destip == INADDR_NONE)
    {
    printf("Bad IP address specified\n");
    return -1;
    }

    // The inet_addr function returns a value in network byte order, but
    // we need the IP address in host byte order, so we use a call to
    // ntohl
    destip = ntohl(destip);

    printf("Enter the destination port\n");
    scanf("%d",&destport);

    /*
       Now, we'll create a RTP session, set the destination, send some
       packets and poll for incoming data.
    */
    status = sess.Create(portbase);
    checkerror(status);

    status = sess.AddDestination(destip,destport);
    checkerror(status);

    for (i = 1 ; i <= 10 ; i++)
    {
    printf("\nSending packet %d/10\n",i);

    // send the packet
                      status = sess.SendPacket("1234567890",(int)10,(unsigned char)0,(bool)false,(unsigned long)10);
    checkerror(status);

    // poll for incoming data
    status = sess.PollData();

    // check incoming packets
    /*!!!*/ if (sess.GotoFirstSourceWithData())  /*!!!失败处!!!*/
    {
    do
    {
    RTPPacket *pack;
    while ((pack = sess.GetNextPacket()) != NULL)
    {
    // You can examine the data here
    printf("Got packet !\n");

    // we don't longer need the packet, 
    // we'll delete it
    delete pack;
    }
    } while (sess.GotoNextSourceWithData());
    }

    printf("Press enter to send the next packet\n");
    gets(dummybuffer);
    }

    return 0;
    }
    在XP下用VC6编译正常,单步执行,一路正常,
    但是,到if (sess.GotoFirstSourceWithData()) 时出错, 
    sess.GotoFirstSourceWithData()返回false,接收数据都不成功
    望各位指点!
      

  3.   

    RTP能解决UDP乱序的问题吗 是不是还要自己实现
      

  4.   

    Columbia RTP Library Example User CodeAugust 21, 1997 
    Go back to library 
    Sample Code to Use RTP
    The following code is a test program that initiates a single member of an RTP session that is able to send and receive RTP packets, displays all packets received, and periodically displays membership information. The member initiates its CSRC list with 3 imaginary contributing members (whose SSRCs are chosen randomly). The code is fully functional except that the encryption / decryption algorithms have been removed since the code used cannot be made publicly available. 
    Contents:
    Scheduler 
    RTPSchedule() function 
    Callback functions 
    The main() function 
    Use of the RTPLib functionality 
    /* rtp_test.c: test ability to send / receive data Copyright 1997 Lucent Technologies; all rights reserved */
    #include <stdlib.h>
    #include <stdio.h>
    #include <sys/time.h>
    #include <string.h>
    #include <math.h>
    #include <errno.h>
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <arpa/inet.h> 
    #include <sys/uio.h>
    #include "rtp_api.h"
    #include "rtp_crypt.h"#define DEFAULT_MULTI "224.119.10.10"
    #define DEFAULT_PORT 5076#define RTPSTAMPRATE 1.0
    #define MAX_SCHEDULE 100#ifndef FALSE
    #define FALSE 0
    #define TRUE 1
    #endif
    /* Below are functions that implement the scheduler */
    /* Scheduler */
    typedef struct {
      int Active;
      struct timeval activate_time;
      int32 opaque;
    } sched_item;
    /* Allow scheduling of up to MAX_SCHEDULE items */
    sched_item sched[MAX_SCHEDULE];
      
    /* Scheduler initialization routine */
    void InitSched(){
      int i;
      for (i=0; i<MAX_SCHEDULE; i++){
        sched[i].Active = FALSE;
      }
      return;
    }
    /* FindInactive locates an empty slot on the scheduler array so that a new item can be scheduled there */
    int FindInactive(){
      int i;
      for (i=0; i < MAX_SCHEDULE;i++){
        if (!sched[i].Active){
          return i;
        }
      }
      return -1;
    }/* Returns an item that is ready to be activated. Note that this does not return the items in any particular chronological order. */
    int FindReady(){
      int i;
      struct timeval curtime;
      gettimeofday(&curtime, NULL);
      for (i=0; i<MAX_SCHEDULE; i++){
        if (sched[i].Active && (sched[i].activate_time.tv_sec < curtime.tv_sec ||
    (sched[i].activate_time.tv_sec == curtime.tv_sec &&
     sched[i].activate_time.tv_usec < curtime.tv_usec))){
          sched[i].Active = FALSE;
          return i;
        }
      }
      return -1;
    }/* RTPSchedule() function */
    /* The scheduling routine */
    void RTPSchedule(context cid, int32 opaque, struct timeval *tp){
      struct timeval curtime;
      int i = FindInactive();
      if (i < 0){
        printf("error: no more room in scheduler\n");
        exit(1);
      }
      sched[i].Active = TRUE;
      sched[i].activate_time = *tp;
      sched[i].opaque = opaque;  gettimeofday(&curtime, NULL);
      printf("Scheduled for %f seconds\n", (float) (tp->tv_sec - curtime.tv_sec) +
     (float) (tp->tv_usec - curtime.tv_usec) / 1000000);
      return;
    }
    /* Callback functions */
    /* The callback function to be used when a new member joins the session */
    void ReportNewMember(context cid, person id_no, unsigned int flags){
      int32 new_ssrc;
      int err;
      err = RTPMemberInfoGetSSRC(cid, id_no, &new_ssrc);
      if (err != RTP_OK){
        printf("%s\n", RTPStrError());
      }
      printf("New Member number %ld: SSRC %x\n", id_no, (int)new_ssrc);
      return;
    }
    /* The callback function to be used when a member expires from the session */
    void ReportExpMember(context cid, person id_no, unsigned int flags){
      int32 new_ssrc;
      int err;
      err = RTPMemberInfoGetSSRC(cid, id_no, &new_ssrc);
      if (err != RTP_OK){
        printf("%s\n", RTPStrError());
      }
      printf("Exp Member number %ld: SSRC %x\n", id_no, (int)new_ssrc);
      return;
    }
    /* The callback function to be used when a member becomes or returns to being a sender */
    void ReportNewSender(context cid, person id_no, unsigned int flags){
      int32 new_ssrc;
      int err;
      err = RTPMemberInfoGetSSRC(cid, id_no, &new_ssrc);
      if (err != RTP_OK){
        printf("%s\n", RTPStrError());
      }
      printf("New SENDER number %ld: SSRC %x\n", id_no, (int)new_ssrc);
      return;
    }/* The callback function to be used when a sender expires or returns to being a sender */
    void ReportExpSender(context cid, person id_no, unsigned int flags){
      int32 new_ssrc;
      int err;
      err = RTPMemberInfoGetSSRC(cid, id_no, &new_ssrc);
      if (err != RTP_OK){
        printf("%s\n", RTPStrError());
      }
      printf("Exp SENDER number %ld: SSRC %x\n", id_no, (int)new_ssrc);
      return;
    }
    /* The callback function to be used when a member's SDES info changes */
    void ReportChangedMemberInfo(context cid, person id_no, memberinfo field,
         char *new, char *old, unsigned int flags){
      printf("Person %ld: SDES field %d changed from %s to %s\n",
     id_no, field, old ? old : "(NULL)", new);
      return;
    }
    /* The callback function to be used when 2 SSRCs are found to collide */
    void ReportCollision(context cid, person id_1, person id_2,
         unsigned int flags){
      printf("Persons %ld and %ld colliding\n", id_1, id_2);
      return;
    }
    /* The callback function to be used when a member's liveness status changes */
    void ReportMemberAlive(context cid, person id_no, int alive, unsigned int flags){ printf("Person %ld: %s\n", id_no, alive ? "alive" : "timed out"); return; } /* Describe Usage is called when the user incorrectly entered something on command line */
    void DescribeUsage(int help){
      fprintf(stderr, "Usage: rtp_test [-help] [-tMin] [-S [tsec]] [-e[1]] [-r[0]] [[addr]/[port]]\n");
      if (help){
        fprintf(stderr, "-help : this help message\n");
        fprintf(stderr, "-tMin: run rtp_test for min minutes\n");
        fprintf(stderr, "-S[dsec] : send RTP packets at rate of 10 per dsec seconds.  default is 10\n");
        fprintf(stderr, "-e : Turn on encryption (-e1 encrypts only SDES info) default is off\n");
        fprintf(stderr, "-r : Reconsideration, -r0 turns reconsideration off.  Default is on\n");
        fprintf(stderr, "[addr]/[port] : address (multicast or unicast) and / or port to use.\n");
        fprintf(stderr, "Default address is multicast %s, default port is %d\n",
        DEFAULT_MULTI, DEFAULT_PORT);
      }
      exit(2);
    }
    /* The main() function */
    void main(int argc, char **argv){
      char addr[20];
      int i, j, parts, ssrc_count, fromlen, count, rtpcount, runtime, encryption,
        reconsideration, is_sender, sendrate, port;
      struct timeval curtime, endtime, next_RTP_send, last_RTP_send, tinytime;
      person cur_mem;
      member_iterator the_iter;
      rtcp_bye_block byeblock;
      double rtptimechange;
      char usekey[9] = "DESKEY01\0";
      char payload[1000], theload[10000], *pktparts[100];
      rtp_packet rtppkt;
      rtcp_packet rtcppkt;
      rtcp_report_block the_block;
      rtcp_sdes_item cur_item;
      struct sockaddr fromaddr;
      context my_context;
      int32 csrc_list[10], csrcguy, cur_ssrc;
      int loaduse;
      rtperror the_err;
      socktype rtpsock, rtcpsock;
      int maxfd = 0;
      fd_set selection;  
    /* Establish default encryption / time, etc. */
    /* Default is encryption not used */
      encryption = 2; /* run for 10 min */
      runtime = 10; /* Set reconsideration to on by default */
      reconsideration = 3; 
      

  5.   

    /* By default, not a sender */
      is_sender = FALSE; 
      sendrate = 10;
      port = DEFAULT_PORT;
      sprintf(addr, "%s", DEFAULT_MULTI);
          for (i=1; i< argc; i++){
        if (argv[i][0] == '-'){
          if (strlen(argv[i]) == 1){
    fprintf(stderr, "rtp_test: option must follow a '-'\n");
    DescribeUsage(FALSE);
          }
          switch(argv[i][1]){
          case 'S':
    is_sender = TRUE;
    if (strlen(argv[i])==2){
      break;
    }
    sendrate = atoi(argv[i]+2);
    break;
          case 't':
    if (strlen(argv[i]) == 2){
      fprintf(stderr, "rtp_test: option t requires integer\n");
      DescribeUsage(FALSE);
    }
    runtime = atoi(argv[i]+2);
    break;
          case 'h':
    DescribeUsage(TRUE);
          case 'e':
    encryption = 0;
    if (strlen(argv[i]) > 2){
      if (argv[i][2] == '1'){
        encryption = 1;
      }
    }
    break;
          case 'r':
    reconsideration = 1;
    if (strlen(argv[i]) > 2){
      if (argv[i][2] == '0'){
        reconsideration = 0;
      }
    }
    break;
          default:
    fprintf(stderr, "rtp_test: illegal option -- %c\n", argv[i][1]);
    DescribeUsage(FALSE);
          }
        }
        else {
          j = 1;
          if (argv[i][0] != '/'){
    strncpy(addr, argv[i], 20);
    for (j=0; j<20 && addr[j]!='\0'; j++){
      if (addr[j] == '/'){
        addr[j] = '\0';
        j++;
        break;
      }
    }
          }
          if (argv[i][j] != '\0'){
    port = atoi(argv[i]+j);
          }
        }
      }
      printf("Using address %s/%d\n", addr, port);     
    /* The following is used if RTP is going to track memory allocation (useful for debugging memory leaks */
    #ifdef _RTP_WATCH_ALLOCATION  
      InitMallocs();
    #endif  tinytime.tv_sec = 0;
      tinytime.tv_usec = 100000;  
    /* Initialize the scheduler */
      InitSched();
      gettimeofday(&curtime, NULL);
      endtime = curtime;
      next_RTP_send = curtime;  endtime.tv_sec += 60 * runtime;
      
    /* Receiver has 3 CSRCs */
      for (i=0; i<3; i++){
        csrc_list[i] = (int32) curtime.tv_usec + i;
      }  
    /* Use of the RTPLib functionality */
    /* Start a new context */
      the_err = RTPCreate(&my_context);
      if (the_err != RTP_OK){
        printf("%s\n", RTPStrError());
      }  
    /* Install the callback functions */
      the_err = RTPSetNewMemberCallBack(my_context, &ReportNewMember);
      if (the_err != RTP_OK){
        printf("%s\n", RTPStrError());
      }
      the_err = RTPSetExpiredMemberCallBack(my_context, &ReportExpMember);
      if (the_err != RTP_OK){
        printf("%s\n", RTPStrError());
      }
      the_err = RTPSetNewSenderCallBack(my_context, &ReportNewSender);
      if (the_err != RTP_OK){
        printf("%s\n", RTPStrError());
      } 
      the_err = RTPSetChangedMemberInfoCallBack(my_context,
        &ReportChangedMemberInfo);
      if (the_err != RTP_OK){
        printf("%s\n", RTPStrError());
      }
      the_err = RTPSetExpiredSenderCallBack(my_context, &ReportExpSender);
      if (the_err != RTP_OK){
        printf("%s\n", RTPStrError());
      }
      the_err = RTPSetCollidedMemberCallBack(my_context, &ReportCollision);
      if (the_err != RTP_OK){
        printf("%s\n", RTPStrError());
      }  
    /* Set the address that we are sending RTP / RTCP packets to. If it's a multicast address, we are going to join the group on that address. */
      the_err = RTPSessionSetAddr(my_context, htonl(inet_addr(addr)));
      if (the_err != RTP_OK){
        printf("%s\n", RTPStrError());
      }  
    /* Our FreeBSD machine is hidden behind a firewall. We need to set the local address for it to work correctly. NOTE: The local address has been altered within this code. */
    #ifdef _RTP_ARCH_FreeBSD
      the_err = RTPSessionSetLocalAddr(my_context, ntohl(inet_addr("0.0.0.0")));
      if (the_err != RTP_OK){
        printf("%s\n", RTPStrError());
      }
    #endif  
    /* Here, we pick a random CNAME for the receiver */
      gethostname(payload, 1000);
      sprintf(theload, "I am %s:%ld",payload, curtime.tv_usec);
      the_err = RTPMemberInfoSetSDES(my_context, 0, 1, theload);
      if (the_err != RTP_OK){
        printf("%s\n", RTPStrError());
      }
      
    /* Set the CSRC list for the local member */
      the_err = RTPSessionSetCSRCList(my_context, csrc_list, 3);
      if (the_err != RTP_OK){ 
        printf("%s\n", RTPStrError());
      } 
      for (i=0; i<3; i++){
        
    /* Set CNAMEs for each of the CSRC members. */
    /* First, we need to retrieve the CSRC member's unique ID */
        the_err = RTPSessionGetUniqueIDForCSRC(my_context, csrc_list[i], &csrcguy);
        if (the_err != RTP_OK){
          printf("%s\n", RTPStrError());
        }
        
    /* Now set the CNAME */
        sprintf(theload, "I am CSRC %d from %s:%ld", i, payload, 
        curtime.tv_usec);
        the_err = RTPMemberInfoSetSDES(my_context, csrcguy, 1, theload);
        if (the_err != RTP_OK){
          printf("%s\n", RTPStrError());
        }
      }
      
    /* Set the port (for sending and receiving) */
      the_err = RTPSessionSetPort(my_context, port);
      if (the_err != RTP_OK){
        printf("%s\n", RTPStrError());
      }
      
            
    /* Install encryption functions */
      the_err = RTPSessionSetEncryptionFuncs(my_context,
     &RTPInit,
          &RTPEncrypt,
     &RTPDecrypt); 
      if (the_err != RTP_OK){
        printf("%s\n", RTPStrError());
      }  
    /* Set encryption to what user specified */
      the_err = RTPSessionSetEncryption(my_context, encryption);
      if (the_err != RTP_OK){
        printf("%s\n", RTPStrError());
      }  
    /* Set reconsideration to what user specified */
      the_err = RTPSessionSetReconsideration(my_context, reconsideration);
      
    /* Set the encryption key */
      the_err = RTPSessionSetKey(my_context, (void*) usekey);  
    /* RTPStamprates are initialized by default, but we can change the rate if we want to */
      the_err = RTPSessionSetRTPStampRate(my_context, 3, RTPSTAMPRATE);
      if (the_err != RTP_OK){
        printf("%s\n", RTPStrError());
      }  
    /* Open the connection (and become a member of the RTP / RTCP session */
      the_err = RTPOpenConnection(my_context);
      if (the_err != RTP_OK){
        printf("%s\n", RTPStrError());
      }  
    /* Get the sockets being used for RTP send and RTCP send / receive */
      the_err = RTPSessionGetRTPSocket(my_context, &rtpsock);
      if (the_err != RTP_OK){
        printf("%s\n", RTPStrError());
      }
      if (maxfd < rtpsock.sock)
        maxfd = rtpsock.sock;
      the_err = RTPSessionGetRTCPSocket(my_context, &rtcpsock);
      if (the_err != RTP_OK){
        printf("%s\n", RTPStrError());
      }
      if (maxfd < rtcpsock.sock)
        maxfd = rtcpsock.sock;  count = 0;
      rtpcount = 0;
      
    /* Now go into receiver / sender mode for the specified amount of time */
      while (curtime.tv_sec < endtime.tv_sec){  
    /* Get my SSRC and print it to the screen */
        RTPMemberInfoGetSSRC(my_context, 0, &cur_ssrc);
        if (the_err != RTP_OK){
          printf("%s\n", RTPStrError());
        }
        printf("My SSRC is %x\n", (int)cur_ssrc);    
      

  6.   

    /* By default, not a sender */
      is_sender = FALSE; 
      sendrate = 10;
      port = DEFAULT_PORT;
      sprintf(addr, "%s", DEFAULT_MULTI);
          for (i=1; i< argc; i++){
        if (argv[i][0] == '-'){
          if (strlen(argv[i]) == 1){
    fprintf(stderr, "rtp_test: option must follow a '-'\n");
    DescribeUsage(FALSE);
          }
          switch(argv[i][1]){
          case 'S':
    is_sender = TRUE;
    if (strlen(argv[i])==2){
      break;
    }
    sendrate = atoi(argv[i]+2);
    break;
          case 't':
    if (strlen(argv[i]) == 2){
      fprintf(stderr, "rtp_test: option t requires integer\n");
      DescribeUsage(FALSE);
    }
    runtime = atoi(argv[i]+2);
    break;
          case 'h':
    DescribeUsage(TRUE);
          case 'e':
    encryption = 0;
    if (strlen(argv[i]) > 2){
      if (argv[i][2] == '1'){
        encryption = 1;
      }
    }
    break;
          case 'r':
    reconsideration = 1;
    if (strlen(argv[i]) > 2){
      if (argv[i][2] == '0'){
        reconsideration = 0;
      }
    }
    break;
          default:
    fprintf(stderr, "rtp_test: illegal option -- %c\n", argv[i][1]);
    DescribeUsage(FALSE);
          }
        }
        else {
          j = 1;
          if (argv[i][0] != '/'){
    strncpy(addr, argv[i], 20);
    for (j=0; j<20 && addr[j]!='\0'; j++){
      if (addr[j] == '/'){
        addr[j] = '\0';
        j++;
        break;
      }
    }
          }
          if (argv[i][j] != '\0'){
    port = atoi(argv[i]+j);
          }
        }
      }
      printf("Using address %s/%d\n", addr, port);     
    /* The following is used if RTP is going to track memory allocation (useful for debugging memory leaks */
    #ifdef _RTP_WATCH_ALLOCATION  
      InitMallocs();
    #endif  tinytime.tv_sec = 0;
      tinytime.tv_usec = 100000;  
    /* Initialize the scheduler */
      InitSched();
      gettimeofday(&curtime, NULL);
      endtime = curtime;
      next_RTP_send = curtime;  endtime.tv_sec += 60 * runtime;
      
    /* Receiver has 3 CSRCs */
      for (i=0; i<3; i++){
        csrc_list[i] = (int32) curtime.tv_usec + i;
      }  
    /* Use of the RTPLib functionality */
    /* Start a new context */
      the_err = RTPCreate(&my_context);
      if (the_err != RTP_OK){
        printf("%s\n", RTPStrError());
      }  
    /* Install the callback functions */
      the_err = RTPSetNewMemberCallBack(my_context, &ReportNewMember);
      if (the_err != RTP_OK){
        printf("%s\n", RTPStrError());
      }
      the_err = RTPSetExpiredMemberCallBack(my_context, &ReportExpMember);
      if (the_err != RTP_OK){
        printf("%s\n", RTPStrError());
      }
      the_err = RTPSetNewSenderCallBack(my_context, &ReportNewSender);
      if (the_err != RTP_OK){
        printf("%s\n", RTPStrError());
      } 
      the_err = RTPSetChangedMemberInfoCallBack(my_context,
        &ReportChangedMemberInfo);
      if (the_err != RTP_OK){
        printf("%s\n", RTPStrError());
      }
      the_err = RTPSetExpiredSenderCallBack(my_context, &ReportExpSender);
      if (the_err != RTP_OK){
        printf("%s\n", RTPStrError());
      }
      the_err = RTPSetCollidedMemberCallBack(my_context, &ReportCollision);
      if (the_err != RTP_OK){
        printf("%s\n", RTPStrError());
      }  
    /* Set the address that we are sending RTP / RTCP packets to. If it's a multicast address, we are going to join the group on that address. */
      the_err = RTPSessionSetAddr(my_context, htonl(inet_addr(addr)));
      if (the_err != RTP_OK){
        printf("%s\n", RTPStrError());
      }  
    /* Our FreeBSD machine is hidden behind a firewall. We need to set the local address for it to work correctly. NOTE: The local address has been altered within this code. */
    #ifdef _RTP_ARCH_FreeBSD
      the_err = RTPSessionSetLocalAddr(my_context, ntohl(inet_addr("0.0.0.0")));
      if (the_err != RTP_OK){
        printf("%s\n", RTPStrError());
      }
    #endif  
    /* Here, we pick a random CNAME for the receiver */
      gethostname(payload, 1000);
      sprintf(theload, "I am %s:%ld",payload, curtime.tv_usec);
      the_err = RTPMemberInfoSetSDES(my_context, 0, 1, theload);
      if (the_err != RTP_OK){
        printf("%s\n", RTPStrError());
      }
      
    /* Set the CSRC list for the local member */
      the_err = RTPSessionSetCSRCList(my_context, csrc_list, 3);
      if (the_err != RTP_OK){ 
        printf("%s\n", RTPStrError());
      } 
      for (i=0; i<3; i++){
        
    /* Set CNAMEs for each of the CSRC members. */
    /* First, we need to retrieve the CSRC member's unique ID */
        the_err = RTPSessionGetUniqueIDForCSRC(my_context, csrc_list[i], &csrcguy);
        if (the_err != RTP_OK){
          printf("%s\n", RTPStrError());
        }
        
    /* Now set the CNAME */
        sprintf(theload, "I am CSRC %d from %s:%ld", i, payload, 
        curtime.tv_usec);
        the_err = RTPMemberInfoSetSDES(my_context, csrcguy, 1, theload);
        if (the_err != RTP_OK){
          printf("%s\n", RTPStrError());
        }
      }
      
    /* Set the port (for sending and receiving) */
      the_err = RTPSessionSetPort(my_context, port);
      if (the_err != RTP_OK){
        printf("%s\n", RTPStrError());
      }
      
            
    /* Install encryption functions */
      the_err = RTPSessionSetEncryptionFuncs(my_context,
     &RTPInit,
          &RTPEncrypt,
     &RTPDecrypt); 
      if (the_err != RTP_OK){
        printf("%s\n", RTPStrError());
      }  
    /* Set encryption to what user specified */
      the_err = RTPSessionSetEncryption(my_context, encryption);
      if (the_err != RTP_OK){
        printf("%s\n", RTPStrError());
      }  
    /* Set reconsideration to what user specified */
      the_err = RTPSessionSetReconsideration(my_context, reconsideration);
      
    /* Set the encryption key */
      the_err = RTPSessionSetKey(my_context, (void*) usekey);  
    /* RTPStamprates are initialized by default, but we can change the rate if we want to */
      the_err = RTPSessionSetRTPStampRate(my_context, 3, RTPSTAMPRATE);
      if (the_err != RTP_OK){
        printf("%s\n", RTPStrError());
      }  
    /* Open the connection (and become a member of the RTP / RTCP session */
      the_err = RTPOpenConnection(my_context);
      if (the_err != RTP_OK){
        printf("%s\n", RTPStrError());
      }  
    /* Get the sockets being used for RTP send and RTCP send / receive */
      the_err = RTPSessionGetRTPSocket(my_context, &rtpsock);
      if (the_err != RTP_OK){
        printf("%s\n", RTPStrError());
      }
      if (maxfd < rtpsock.sock)
        maxfd = rtpsock.sock;
      the_err = RTPSessionGetRTCPSocket(my_context, &rtcpsock);
      if (the_err != RTP_OK){
        printf("%s\n", RTPStrError());
      }
      if (maxfd < rtcpsock.sock)
        maxfd = rtcpsock.sock;  count = 0;
      rtpcount = 0;
      
    /* Now go into receiver / sender mode for the specified amount of time */
      while (curtime.tv_sec < endtime.tv_sec){  
    /* Get my SSRC and print it to the screen */
        RTPMemberInfoGetSSRC(my_context, 0, &cur_ssrc);
        if (the_err != RTP_OK){
          printf("%s\n", RTPStrError());
        }
        printf("My SSRC is %x\n", (int)cur_ssrc);    
      

  7.   

    to  nkwesley(江南丝竹) 请问你用的是那个库文件