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

📄 playcommon.cpp

📁 流媒体传输协议的实现代码,非常有用.可以支持rtsp mms等流媒体传输协议
💻 CPP
📖 第 1 页 / 共 4 页
字号:
/**********This library is free software; you can redistribute it and/or modify it underthe terms of the GNU Lesser General Public License as published by theFree Software Foundation; either version 2.1 of the License, or (at youroption) any later version. (See <http://www.gnu.org/copyleft/lesser.html>.)This library is distributed in the hope that it will be useful, but WITHOUTANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESSFOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License formore details.You should have received a copy of the GNU Lesser General Public Licensealong with this library; if not, write to the Free Software Foundation, Inc.,59 Temple Place, Suite 330, Boston, MA  02111-1307  USA**********/// Copyright (c) 1996-2004, Live Networks, Inc.  All rights reserved// A common framework, used for the "openRTSP" and "playSIP" applications// Implementation#include "playCommon.hh"#include "BasicUsageEnvironment.hh"#include "GroupsockHelper.hh"#ifdef SUPPORT_REAL_RTSP#include "../RealRTSP/include/RealRTSP.hh"#endif#if defined(__WIN32__) || defined(_WIN32)#define snprintf _snprintf#else#include <signal.h>#define USE_SIGNALS 1#endif// Forward function definitions:void setupStreams();void startPlayingStreams();void tearDownStreams();void closeMediaSinks();void subsessionAfterPlaying(void* clientData);void subsessionByeHandler(void* clientData);void sessionAfterPlaying(void* clientData = NULL);void sessionTimerHandler(void* clientData);void shutdown(int exitCode = 1);void signalHandlerShutdown(int sig);void checkForPacketArrival(void* clientData);void checkInterPacketGaps(void* clientData);void beginQOSMeasurement();Boolean setupDestinationRTSPServer();char const* progName;UsageEnvironment* env;Medium* ourClient = NULL;MediaSession* session = NULL;TaskToken sessionTimerTask = NULL;TaskToken arrivalCheckTimerTask = NULL;TaskToken interPacketGapCheckTimerTask = NULL;TaskToken qosMeasurementTimerTask = NULL;Boolean createReceivers = True;Boolean outputQuickTimeFile = False;Boolean generateMP4Format = False;QuickTimeFileSink* qtOut = NULL;Boolean outputAVIFile = False;AVIFileSink* aviOut = NULL;Boolean audioOnly = False;Boolean videoOnly = False;char const* singleMedium = NULL;int verbosityLevel = 0;double endTime = 0;double endTimeSlop = -1.0; // extra seconds to play at the endunsigned interPacketGapMaxTime = 0;unsigned totNumPacketsReceived = ~0; // used if checking inter-packet gapsBoolean playContinuously = False;int simpleRTPoffsetArg = -1;Boolean sendOptionsRequest = True;Boolean sendOptionsRequestOnly = False;Boolean oneFilePerFrame = False;Boolean notifyOnPacketArrival = False;Boolean streamUsingTCP = False;portNumBits tunnelOverHTTPPortNum = 0;char* username = NULL;char* password = NULL;char* proxyServerName = NULL;unsigned short proxyServerPortNum = 0;unsigned char desiredAudioRTPPayloadFormat = 0;char* mimeSubtype = NULL;unsigned short movieWidth = 240; // defaultBoolean movieWidthOptionSet = False;unsigned short movieHeight = 180; // defaultBoolean movieHeightOptionSet = False;unsigned movieFPS = 15; // defaultBoolean movieFPSOptionSet = False;char* fileNamePrefix = "";unsigned fileSinkBufferSize = 20000;unsigned socketInputBufferSize = 0;Boolean packetLossCompensate = False;Boolean syncStreams = False;Boolean generateHintTracks = False;char* destRTSPURL = NULL;unsigned qosMeasurementIntervalMS = 0; // 0 means: Don't output QOS dataunsigned statusCode = 0;struct timeval startTime;void usage() {  *env << "Usage: " << progName       << " [-p <startPortNum>] [-r|-q|-4|-i] [-a|-v] [-V] [-e <endTime>] [-E <max-inter-packet-gap-time> [-c] [-s <offset>] [-n] [-O]"	   << (controlConnectionUsesTCP ? " [-t|-T <http-port>]" : "")       << " [-u <username> <password>"	   << (allowProxyServers ? " [<proxy-server> [<proxy-server-port>]]" : "")       << "]" << (supportCodecSelection ? " [-A <audio-codec-rtp-payload-format-code>|-D <mime-subtype-name>]" : "")       << " [-w <width> -h <height>] [-f <frames-per-second>] [-y] [-H] [-Q [<measurement-interval>]] [-F <filename-prefix>] [-b <file-sink-buffer-size>] [-B <input-socket-buffer-size>] [-I <input-interface-ip-address>] [-m] <url> (or " << progName << " -o [-V] <url>)\n";  //##### Add "-R <dest-rtsp-url>" #####  shutdown();}int main(int argc, char** argv) {  // Begin by setting up our usage environment:  TaskScheduler* scheduler = BasicTaskScheduler::createNew();  env = BasicUsageEnvironment::createNew(*scheduler);  progName = argv[0];  gettimeofday(&startTime, NULL);#ifdef USE_SIGNALS  // Allow ourselves to be shut down gracefully by a SIGHUP or a SIGUSR1:  signal(SIGHUP, signalHandlerShutdown);  signal(SIGUSR1, signalHandlerShutdown);#endif  unsigned short desiredPortNum = 0;  // unfortunately we can't use getopt() here, as Windoze doesn't have it  while (argc > 2) {    char* const opt = argv[1];    if (opt[0] != '-') usage();    switch (opt[1]) {    case 'p': { // specify start port number      int portArg;      if (sscanf(argv[2], "%d", &portArg) != 1) {	usage();      }      if (portArg <= 0 || portArg >= 65536 || portArg&1) {	*env << "bad port number: " << portArg		<< " (must be even, and in the range (0,65536))\n";	usage();      }      desiredPortNum = (unsigned short)portArg;      ++argv; --argc;      break;    }    case 'r': { // do not receive data (instead, just 'play' the stream(s))      createReceivers = False;      break;    }    case 'q': { // output a QuickTime file (to stdout)      outputQuickTimeFile = True;      break;    }    case '4': { // output a 'mp4'-format file (to stdout)      outputQuickTimeFile = True;      generateMP4Format = True;      break;    }    case 'i': { // output an AVI file (to stdout)      outputAVIFile = True;      break;    }    case 'I': { // specify input interface...       NetAddressList addresses(argv[2]);      if (addresses.numAddresses() == 0) {	*env << "Failed to find network address for \"" << argv[2] << "\"";	break;      }      ReceivingInterfaceAddr = *(unsigned*)(addresses.firstAddress()->data());      ++argv; --argc;      break;    }    case 'a': { // receive/record an audio stream only      audioOnly = True;      singleMedium = "audio";      break;    }    case 'v': { // receive/record a video stream only      videoOnly = True;      singleMedium = "video";      break;    }    case 'V': { // verbose output      verbosityLevel = 1;      break;    }    case 'e': { // specify end time, or how much to delay after end time      float arg;      if (sscanf(argv[2], "%g", &arg) != 1) {	usage();      }      if (argv[2][0] == '-') { // not "arg<0", in case argv[2] was "-0"	// a 'negative' argument was specified; use this for "endTimeSlop":	endTime = 0; // use whatever's in the SDP	endTimeSlop = -arg;      } else {	endTime = arg;	endTimeSlop = 0;      }      ++argv; --argc;      break;    }    case 'E': { // specify maximum number of seconds to wait for packets:      if (sscanf(argv[2], "%u", &interPacketGapMaxTime) != 1) {	usage();      }      ++argv; --argc;      break;    }    case 'c': { // play continuously      playContinuously = True;      break;    }    case 's': { // specify an offset to use with "SimpleRTPSource"s      if (sscanf(argv[2], "%d", &simpleRTPoffsetArg) != 1) {	usage();      }      if (simpleRTPoffsetArg < 0) {	*env << "offset argument to \"-s\" must be >= 0\n";	usage();      }      ++argv; --argc;      break;    }    case 'O': { // Don't send an "OPTIONS" request before "DESCRIBE"      sendOptionsRequest = False;      break;    }    case 'o': { // Send only the "OPTIONS" request to the server      sendOptionsRequestOnly = True;      break;    }    case 'm': { // output multiple files - one for each frame      oneFilePerFrame = True;      break;    }    case 'n': { // notify the user when the first data packet arrives      notifyOnPacketArrival = True;      break;    }    case 't': {      // stream RTP and RTCP over the TCP 'control' connection      if (controlConnectionUsesTCP) {	streamUsingTCP = True;      } else {	usage();      }      break;    }    case 'T': {      // stream RTP and RTCP over a HTTP connection      if (controlConnectionUsesTCP) {	if (argc > 3 && argv[2][0] != '-') {	  // The next argument is the HTTP server port number:	  if (sscanf(argv[2], "%hu", &tunnelOverHTTPPortNum) == 1	      && tunnelOverHTTPPortNum > 0) {	    ++argv; --argc;	    break;	  }	}      }      // If we get here, the option was specified incorrectly:      usage();      break;    }    case 'u': { // specify a username and password      username = argv[2];      password = argv[3];      argv+=2; argc-=2;      if (allowProxyServers && argc > 3 && argv[2][0] != '-') {	// The next argument is the name of a proxy server:	proxyServerName = argv[2];	++argv; --argc;	if (argc > 3 && argv[2][0] != '-') {	  // The next argument is the proxy server port number:	  if (sscanf(argv[2], "%hu", &proxyServerPortNum) != 1) {	    usage();	  }	  ++argv; --argc;	}      }      break;    }    case 'A': { // specify a desired audio RTP payload format      unsigned formatArg;      if (sscanf(argv[2], "%u", &formatArg) != 1	  || formatArg >= 96) {	usage();      }      desiredAudioRTPPayloadFormat = (unsigned char)formatArg;      ++argv; --argc;      break;    }    case 'D': { // specify a MIME subtype for a dynamic RTP payload type      mimeSubtype = argv[2];      if (desiredAudioRTPPayloadFormat==0) desiredAudioRTPPayloadFormat =96;      ++argv; --argc;      break;    }    case 'w': { // specify a width (pixels) for an output QuickTime or AVI movie      if (sscanf(argv[2], "%hu", &movieWidth) != 1) {	usage();      }      movieWidthOptionSet = True;      ++argv; --argc;      break;    }    case 'h': { // specify a height (pixels) for an output QuickTime or AVI movie      if (sscanf(argv[2], "%hu", &movieHeight) != 1) {	usage();      }      movieHeightOptionSet = True;      ++argv; --argc;      break;    }    case 'f': { // specify a frame rate (per second) for an output QT or AVI movie      if (sscanf(argv[2], "%u", &movieFPS) != 1) {	usage();      }      movieFPSOptionSet = True;      ++argv; --argc;      break;    }    case 'F': { // specify a prefix for the audio and video output files      fileNamePrefix = argv[2];      ++argv; --argc;      break;    }    case 'b': { // specify the size of buffers for "FileSink"s      if (sscanf(argv[2], "%u", &fileSinkBufferSize) != 1) {	usage();      }      ++argv; --argc;      break;    }    case 'B': { // specify the size of input socket buffers

⌨️ 快捷键说明

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