⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 netoutput.cpp

📁 很好的流媒体服务器程序,linux或window下做流媒体的可以参考很不错哦
💻 CPP
字号:
/******************************************************************************** netoutput.cpp: network output*-------------------------------------------------------------------------------* (c)1999-2001 VideoLAN* $Id: netoutput.cpp,v 1.11.4.5 2003/05/16 19:43:59 nitrox Exp $** Authors: Benoit Steiner <benny@via.ecp.fr>*          Arnaud de Bossoreille de Ribou <bozo@via.ecp.fr>** This program is free software; you can redistribute it and/or* modify it under the terms of the GNU General Public License* as published by the Free Software Foundation; either version 2* of the License, or (at your option) any later version.** This program is distributed in the hope that it will be useful,* but WITHOUT ANY WARRANTY; without even the implied warranty of* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the* GNU General Public License for more details.** You should have received a copy of the GNU General Public License* along with this program; if not, write to the Free Software* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.**-------------------------------------------------------------------------------********************************************************************************///------------------------------------------------------------------------------// Preamble//------------------------------------------------------------------------------#ifdef WIN32#include <winsock2.h>#include <ws2tcpip.h>#endif#include "../../core/defs.h"#include "../../core/core.h"#include "../../mpeg/mpeg.h"#include "../../mpeg/ts.h"#include "../../mpeg/rtp.h"#include "../../server/buffer.h"#include "../../server/output.h"#ifdef HAVE_NET_IF_H#include <net/if.h>#endif#include "netoutput.h"//******************************************************************************// C_NetOutput class//******************************************************************************////******************************************************************************//------------------------------------------------------------------------------// //------------------------------------------------------------------------------C_NetOutput::C_NetOutput(const C_String& strChannelName)                : C_Output(TS_IN_ETHER), m_cSocketBuff(TS_IN_ETHER+1){  C_Application* pApp = C_Application::GetApp();  ASSERT(pApp);  m_strSrcHost = pApp->GetSetting(strChannelName+".SrcHost", "");  m_strSrcPort = pApp->GetSetting(strChannelName+".SrcPort", "");  m_strDstHost = pApp->GetSetting(strChannelName+".DstHost", "");  m_strDstPort = pApp->GetSetting(strChannelName+".DstPort", "1234");  m_strType = pApp->GetSetting(strChannelName+".Type", "unicast").ToLower();  m_strInterface = pApp->GetSetting(strChannelName+".Interface", "");  C_String strTTL = pApp->GetSetting(strChannelName+".TTL", "0");  m_iTTL = strTTL.ToInt();  // Init the buffer  // The first slot is reserved for the Rtp Header  m_cSocketBuff.SetSlotSize(0, RTP_HEADER_LEN);  for(int iIndex = 1; iIndex < TS_IN_ETHER + 1; iIndex++)    m_cSocketBuff.SetSlotSize(iIndex, TS_PACKET_LEN);}//------------------------------------------------------------------------------// //------------------------------------------------------------------------------C_NetOutput::~C_NetOutput(){}//------------------------------------------------------------------------------// //------------------------------------------------------------------------------void C_NetOutput::OnInit(){  ASSERT(    (m_strType == "unicast")          || (m_strType == "multicast")          || (m_strType == "broadcast"));  int iOptVal=1;  if(m_strType == "broadcast")  {    // Allow the socket to send broadcast packets    iOptVal = 1;    m_cSocket.SetOption(SOL_SOCKET, SO_BROADCAST, (char *)&iOptVal, sizeof(iOptVal));  }  // Allow to use the ip/port couple more than once at a time to be  // able to send several streams to a same client using the same port  iOptVal = 1;  m_cSocket.SetOption(SOL_SOCKET, SO_REUSEADDR, (char *)&iOptVal, sizeof(iOptVal));  // Try to increase the size of the socket output buffer to 1/2MB (8Mb/s  // during 1/2s) to avoid packet loss  iOptVal = 524288;  for(;;)  {    try    {      m_cSocket.SetOption(SOL_SOCKET, SO_SNDBUF, (char *)&iOptVal, sizeof(iOptVal));      break;    }    catch(E_Exception e)    {      iOptVal = iOptVal / 2;      if(iOptVal <= 524288/16)        throw E_Output("Unable to allocate output buffer", e);    }  }#ifdef HAVE_IPV6  if ((m_cSocket.GetDomain() == AF_INET6)&&	  (m_strType == "multicast")&&	  (m_strInterface != ""))  {	/* now get the ifindex for this interface */	/* and set the appropriate option */    int mcif = if_nametoindex(m_strInterface.GetString());	if (mcif == 0) perror("if_nametoindex()\n");	else m_cSocket.SetOption(IPPROTO_IPV6, IPV6_MULTICAST_IF,                                 (char *)&mcif, sizeof(mcif));  }#endif#ifdef HAVE_SO_BINDTODEVICE  // If an interface is specified then bind to it  // (Very useful when several interfaces are connected to the same subnet)  if(m_strInterface != "")  {    struct ifreq sInterface;    strncpy(sInterface.ifr_ifrn.ifrn_name,            m_strInterface.GetString(), IFNAMSIZ);    m_cSocket.SetOption(SOL_SOCKET, SO_BINDTODEVICE, (char *)&sInterface,                        sizeof(sInterface));  }#endif  // Set the Time To Live value if != 0  if(m_iTTL)  {	if (m_cSocket.GetDomain() == AF_INET)	{      if((m_strType == "unicast") || (m_strType == "broadcast"))        m_cSocket.SetOption(IPPROTO_IP, IP_TTL, (char *)&m_iTTL, sizeof(m_iTTL));      else if(m_strType == "multicast")        m_cSocket.SetOption(IPPROTO_IP, IP_MULTICAST_TTL,                            (char *)&m_iTTL, sizeof(m_iTTL));    }#ifdef HAVE_IPV6	else if (m_cSocket.GetDomain() == AF_INET6)	{	    /* of course broadcast does not exist in IPv6 */    	if((m_strType == "unicast") || (m_strType == "broadcast"))      		m_cSocket.SetOption(IPPROTO_IPV6, IPV6_UNICAST_HOPS,                                    (char *)&m_iTTL, sizeof(m_iTTL));	    else if(m_strType == "multicast")      		m_cSocket.SetOption(IPPROTO_IPV6, IPV6_MULTICAST_HOPS,                                    (char *)&m_iTTL, sizeof(m_iTTL));	}#endif  }  // Bind it to the local address if specified  if(m_strSrcHost.Length() != 0)    m_cSocket.Bind(m_strSrcHost, m_strSrcPort);#ifndef BUGGY_VLC  // Connect it  m_cSocket.Connect(m_strDstHost, m_strDstPort);#endif}//------------------------------------------------------------------------------// //------------------------------------------------------------------------------void C_NetOutput::OnClose(){  try  {    m_cSocket.Close();  }  catch(E_Exception e)  {    throw E_Output("Output termination failed", e);  }}//------------------------------------------------------------------------------////------------------------------------------------------------------------------////------------------------------------------------------------------------------void C_NetOutput::WriteToPort(bool RtpEncapsulation, u32 RtpSendTime){  ASSERT(m_pTsProvider);  unsigned int iPacketNumber = m_cTsBuff.Size();  int HeaderOffset;  bool HasDiscontinuity = 0;    if(iPacketNumber > 0)  {    // To avoid problems with the socket buff    ASSERT(iPacketNumber <= TS_IN_ETHER);    if (RtpEncapsulation)    {      HeaderOffset = RTP_HEADER_LEN;      m_pRtpHeader->BuildHeader(m_iRtpCounter++);      // Check for discontinuity in one of the TS packets      for(unsigned int iIndex = 0; iIndex < iPacketNumber; iIndex++)        HasDiscontinuity |= m_cTsBuff[iIndex].IsDiscontinuity();      m_pRtpHeader->SetRtpDiscontinuity(HasDiscontinuity);      // Convert to the 90kHzClock : RtpSendTime()*90 000/1 000 000      // Doing a /10 *9 /10 fo conversion / integer issues.      m_pRtpHeader->SetRtpTimeStamp( ((RtpSendTime/10)*9)/10 );#ifdef BUGGY_VLC      memcpy(m_ByteBuff, *m_pRtpHeader, RTP_HEADER_LEN);#endif    }    else HeaderOffset = 0;#ifdef BUGGY_VLC    // TS concatenation    for(unsigned int iIndex = 0; iIndex < iPacketNumber; iIndex++)      memcpy(m_ByteBuff + HeaderOffset + TS_PACKET_LEN * iIndex, m_cTsBuff[iIndex],             TS_PACKET_LEN);    // Send the data that were stored in the buffer    int iRc = PrivateWriteTo(HeaderOffset + TS_PACKET_LEN * iPacketNumber);    if(iRc != HeaderOffset + TS_IN_ETHER * TS_PACKET_LEN)      m_iByteLost += HeaderOffset + TS_IN_ETHER * TS_PACKET_LEN - iRc;#else    // Fill in the socketbuff    if (RtpEncapsulation)    { // Rtp Header First      m_cSocketBuff.SetSlotBuff(0,(char*)(byte*)*m_pRtpHeader);    }    for(unsigned int iIndex = 1; iIndex < iPacketNumber+1; iIndex++)    {      m_cSocketBuff.SetSlotBuff(iIndex,(char*)(byte*)m_cTsBuff[iIndex-1]);    }    // Send the data that were stored in the buffer    try    {      int iRc;      if (RtpEncapsulation)      {        iRc = m_cSocket.Send(m_cSocketBuff, iPacketNumber + 1 , 0);      }      else      {        // No Rtp : skip first SockBuff -> iOffset=1        iRc = m_cSocket.Send(m_cSocketBuff, iPacketNumber, 1);      }      if(iRc != HeaderOffset + TS_IN_ETHER * TS_PACKET_LEN)        m_iByteLost += HeaderOffset + TS_IN_ETHER * TS_PACKET_LEN - iRc;    }    catch(E_Exception e)    {      throw E_Output("Connection lost", e);    }#endif    // Free the now unused packets    C_TsPacket* pPacket;    for(unsigned int i = 0; i < iPacketNumber; i++)    {      // Pop the packet from the buffer      pPacket = m_cTsBuff.Pop();      ASSERT(pPacket);      // And release it      m_pTsProvider->ReleasePacket(pPacket);    }  }}//******************************************************************************// C_Net4Output class//******************************************************************************////******************************************************************************//------------------------------------------------------------------------------// //------------------------------------------------------------------------------C_Net4Output::C_Net4Output(const C_String& strChannelName) :                                                C_NetOutput(strChannelName){}//------------------------------------------------------------------------------// //------------------------------------------------------------------------------C_Net4Output::~C_Net4Output(){}//------------------------------------------------------------------------------// //------------------------------------------------------------------------------void C_Net4Output::OnInit(){  try  {#ifdef BUGGY_VLC    /* Build the destination address */    m_cOutputInetAddr.Build(m_strDstHost, m_strDstPort);#endif    // Open the socket    m_cSocket.Open(AF_INET, SOCK_DGRAM);    C_NetOutput::OnInit();#ifndef _WIN32    if(m_strType == "multicast")    {      struct ip_mreq imr;      C_Inet4Addr cAddr;      imr.imr_interface.s_addr = INADDR_ANY;      cAddr.Build(m_strDstHost, m_strDstPort);      imr.imr_multiaddr.s_addr = cAddr.GetInetAddr()->sin_addr.s_addr;      m_cSocket.SetOption(IPPROTO_IP, IP_ADD_MEMBERSHIP, (char *)&imr, sizeof(imr));    }#endif  }  catch(E_Exception e)  {    throw E_Output("Net4Output initialisation failed", e);  }}//------------------------------------------------------------------------------// //------------------------------------------------------------------------------void C_Net4Output::OnClose(){  try  {#ifndef _WIN32    if(m_strType == "multicast")    {      struct ip_mreq imr;      C_Inet4Addr cAddr;      imr.imr_interface.s_addr = INADDR_ANY;      cAddr.Build(m_strDstHost, m_strDstPort);      imr.imr_multiaddr.s_addr = cAddr.GetInetAddr()->sin_addr.s_addr;      m_cSocket.SetOption(IPPROTO_IP, IP_DROP_MEMBERSHIP, (char *)&imr, sizeof(imr));    }#endif    C_NetOutput::OnClose();  }  catch(E_Exception e)  {    throw E_Output("Net4Output termination failed", e);  }}#ifdef BUGGY_VLC//------------------------------------------------------------------------------////------------------------------------------------------------------------------int C_Net4Output::PrivateWriteTo(int iBuffLen){  return m_cSocket.WriteTo(m_cOutputInetAddr, (char *)m_ByteBuff, iBuffLen);}#endif//******************************************************************************// C_Net6Output class//******************************************************************************////******************************************************************************#ifdef HAVE_IPV6//------------------------------------------------------------------------------// //------------------------------------------------------------------------------C_Net6Output::C_Net6Output(const C_String& strChannelName) :                                                C_NetOutput(strChannelName){}//------------------------------------------------------------------------------// //------------------------------------------------------------------------------C_Net6Output::~C_Net6Output(){}//------------------------------------------------------------------------------// //------------------------------------------------------------------------------void C_Net6Output::OnInit(){  try  {#ifdef BUGGY_VLC    /* Build the destination address */    m_cOutputInetAddr.Build(m_strDstHost, m_strDstPort, SOCK_DGRAM);#endif    // Open the socket    m_cSocket.Open(AF_INET6, SOCK_DGRAM);    C_NetOutput::OnInit();    if(m_strType == "multicast")    {      struct ipv6_mreq imr;      C_Inet6Addr cAddr;      imr.ipv6mr_interface = 0;      cAddr.Build(m_strDstHost, m_strDstPort, SOCK_DGRAM);      imr.ipv6mr_multiaddr = cAddr.GetInetAddr()->sin6_addr;      m_cSocket.SetOption(IPPROTO_IPV6, IPV6_JOIN_GROUP, (char *)&imr, sizeof(imr));    }  }  catch(E_Exception e)  {    throw E_Output("Net6Output initialisation failed", e);  }}//------------------------------------------------------------------------------// //------------------------------------------------------------------------------void C_Net6Output::OnClose(){  try  {    if(m_strType == "multicast")    {      struct ipv6_mreq imr;      C_Inet6Addr cAddr;      imr.ipv6mr_interface = 0;      cAddr.Build(m_strDstHost, m_strDstPort, SOCK_DGRAM);      imr.ipv6mr_multiaddr = cAddr.GetInetAddr()->sin6_addr;      m_cSocket.SetOption(IPPROTO_IPV6, IPV6_LEAVE_GROUP,                          (char *)&imr, sizeof(imr));    }    C_NetOutput::OnClose();  }  catch(E_Exception e)  {    throw E_Output("Net6Output termination failed", e);  }}#ifdef BUGGY_VLC//------------------------------------------------------------------------------////------------------------------------------------------------------------------int C_Net6Output::PrivateWriteTo(int iBuffLen){  return m_cSocket.WriteTo(m_cOutputInetAddr, (const char *) m_ByteBuff, iBuffLen);}#endif#endif

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -