RTP实时音视频数据传输(二)

2013-01-09 14:05:21 · 作者: · 浏览: 608

 

  (2) receive.cpp

  [cpp] view plaincopy

  #include "rtpsession.h"

  #include "rtppacket.h"

  #include "rtpudpv4transmitter.h"

  #include "rtpipv4address.h"

  #include "rtpsessionparams.h"

  #include "rtperrors.h"

  #ifndef WIN32

  #include <netinet/in.h>

  #include <arpa/inet.h>

  #else

  #include <winsock2.h>

  #endif // WIN32

  #include "rtpsourcedata.h"

  #include <stdlib.h>

  #include <stdio.h>

  #include <iostream>

  #include <string>

  //

  // This function checks if there was a RTP error. If so, it displays an error

  // message and exists.

  //

  void checkerror(int rtperr)

  {

  if (rtperr < 0)

  {

  std::cout 《 "ERROR: " 《 RTPGetErrorString(rtperr) 《 std::endl;

  exit(-1);

  }

  }

  //

  // The new class routine

  //

  class MyRTPSession : public RTPSession

  {

  protected:

  void OnNewSource(RTPSourceData *dat)

  {

  if (dat->IsOwnSSRC())

  return;

  uint32_t ip;

  uint16_t port;

  if (dat->GetRTPDataAddress() != 0)

  {

  const RTPIPv4Address *addr = (const RTPIPv4Address *)(dat->GetRTPDataAddress());

  ip = addr->GetIP();

  port = addr->GetPort();

  }

  else if (dat->GetRTCPDataAddress() != 0)

  {

  const RTPIPv4Address *addr = (const RTPIPv4Address *)(dat->GetRTCPDataAddress());

  ip = addr->GetIP();

  port = addr->GetPort()-1;

  }

  else

  return;

  RTPIPv4Address dest(ip,port);

  AddDestination(dest);

  struct in_addr inaddr;

  inaddr.s_addr = htonl(ip);

  std::cout 《 "Adding destination " 《 std::string(inet_ntoa(inaddr)) 《 ":" 《 port 《 std::endl;

  }

  void OnBYEPacket(RTPSourceData *dat)

  {

  if (dat->IsOwnSSRC())

  return;

  uint32_t ip;

  uint16_t port;

  if (dat->GetRTPDataAddress() != 0)

  {

  const RTPIPv4Address *addr = (const RTPIPv4Address *)(dat->GetRTPDataAddress());

  ip = addr->GetIP();

  port = addr->GetPort();

  }

  else if (dat->GetRTCPDataAddress() != 0)

  {

  const RTPIPv4Address *addr = (const RTPIPv4Address *)(dat->GetRTCPDataAddress());

  ip = addr->GetIP();

  port = addr->GetPort()-1;

  }

  else

  return;

  RTPIPv4Address dest(ip,port);

  DeleteDestination(dest);

  struct in_addr inaddr;

  inaddr.s_addr = htonl(ip);

  std::cout 《 "Deleting destination " 《 std::string(inet_ntoa(inaddr)) 《 ":" 《 port 《 std::endl;

  }

  void OnRemoveSource(RTPSourceData *dat)

  {

  if (dat->IsOwnSSRC())

  return;

  if (dat->ReceivedBYE())

  return;

  uint32_t ip;

  uint16_t port;

  if (dat->GetRTPDataAddress() != 0)

  {

  const RTPIPv4Address *addr = (const RTPIPv4Address *)(dat->GetRTPDataAddress());

  ip = addr->GetIP();

  port = addr->GetPort();

  }

  else if (dat->GetRTCPDataAddress() != 0)

  {

  const RTPIPv4Address *addr = (const RTPIPv4Address *)(dat->GetRTCPDataAddress());

  ip = addr->GetIP();

  port = addr->GetPort()-1;

  }

  else

  return;

  RTPIPv4Address dest(ip,port);

  DeleteDestination(dest);

  struct in_addr inaddr;

  inaddr.s_addr = htonl(ip);

  std::cout 《 "Deleting destination " 《 std::string(inet_ntoa(inaddr)) 《 ":" 《 port 《 std::endl;

  }

  };

  //

  // The main routine

  //

  int main(void)

  {

  #ifdef WIN32

  WSADATA dat;

  WSAStartup(MAKEWORD(2,2),&dat);

  #endif // WIN32

  MyRTPSession sess;

  uint16_t portbase;

  std::string ipstr;

  int status,i,num;

  // First, we'll ask for the necessary information

  std::cout 《 "Enter local portbase:" 《 std::endl;

  std::cin 》 portbase;

  std::cout 《 std::endl;

  std::cout 《 std::endl;

  std::cout 《 "Number of seconds you wish to wait:" 《 std::endl;

  std::cin 》 num;

  // Now, we'll create a RTP session, set the destination

  // and poll for incoming data.

  RTPUDPv4TransmissionParams transparams;

  RTPSessionParams sessparams;

  // IMPORTANT: The local timestamp unit MUST be set, otherwise

  //            RTCP Sender Report info will be calculated wrong

  // In this case, we'll be just use 8000 samples per second.

  sessparams.SetOwnTimestampUnit(1.0/8000.0);

  sessparams.SetAcceptOwnPackets(true);

  transparams.SetPortbase(portbase);

  status = sess.Create(sessparams,&transparams);

  checkerror(status);

  for (i = 1 ; i <= num ; i++)

  {

  sess.BeginDataAccess();

  // 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, so

  // we'll delete it

  sess.DeletePacket(pack);

  }

  } while (sess.GotoNextSourceWithData());

  }

  sess.EndDataAccess();

  #ifndef RTP_SUPPORT_THREAD

  status = sess.Poll();

  checkerror(status);

  #endif // RTP_SUPPORT_THREAD

  RTPTime::Wait(RTPTime(1,0));

  }

  sess.BYEDestroy(RTPTime(10,0),0,0);

  #ifdef WIN32

  WSACleanup();

  #endif // WIN32

  return 0;

  }