[-]
[+]
|
Added |
live.changes
|
|
[-]
[+]
|
Changed |
live.spec
^
|
|
[-]
[+]
|
Changed |
live-CHANGELOG
^
|
@@ -1,6 +1,228 @@
-Next version, in progress:
-- Updated the "timestampString()" function in "groupsock/GroupsockHelper.cpp" to allow for the possibility of "cimt()" returning
- NULL.
+2011.06.16:
+- Updated "AC3AudioRTPSink" and "AC3AudioRTPSource" to conform to RFC 4184, which defines the RTP payload format for AC-3 audio.
+ Previously, we were using a different, incompatible payload format (that had been defined by an initial draft document, but
+ which differed from that defined in the final RFC. Unfortunately, this means that older clients that use our code
+ - including existing binary versions of VLC and MPlayer - will no longer be able to play AC-3/RTP streams from our server
+ (until they are rebuilt using this newest version of our library).
+- Updated "AC3AudioStreamFramer" - and added a new class "AC3AudioFileServerMediaSubsession" - to support streaming from an AC-3
+ audio file. We also added this support to the "testOnDemandRTSPServer" demo application, and to the "LIVE555 Media Server"
+ (currently just the source code; not the prebuilt binary versions).
+ (Thanks to Ashwani Kathuria for suggesting this.)
+- Moved the definition of "class StreamState" from "OnDemandServerMediaSubsession.cpp" to "OnDemandServerMediaSubsession.hh".
+ Even though "class StreamState" is used only internally, in the implementation of "OnDemandServerMediaSubsession", moving its
+ definition to the header file makes it possible for subclasses of "OnDemandServerMediaSubsession" to access it.
+
+2011.06.14a:
+- Removed some junk (debugging) files that had accidentally been left in the "testProgs/" directory.
+
+2011.06.14:
+- Fixed a race condition in "H264VideoFileServerMediaSubsession" and "MPEG4VideoFileServerMediaSubsession" that could have been
+ triggered when two separate clients tried to stream the same file concurrently. (Thanks to Bruno Abreu for reporting this.)
+- Fixed a minor bug in "Authenticator::operator=()": we were not freeing the LHS object's memory before doing the
+ assignment. (Thanks to Sawan Das for noting this.)
+- Updated "config.iphoneos" to change LIBRARY_LINK from "ar cr " to "libtool -s -o ", just as we did for "config.macosx" in the
+ previous release.
+
+2011.06.12:
+- Updated the RTCP implementation to (if we're a SSM source) reflect incoming RTCP packets back to the multicast group
+ *only* if the packet originated from another host. This means that we won't reflect packets that come from other
+ processes on our own host. The reason for this is that we can't reliably distinguish such packets from packets that were
+ actually looped back from us. (We must not 'reflect' such packets, otherwise we risk a packet storm.)
+- Updated the "ByteStreamFileSource" code to make the underlying socket non-blocking. We also read data using "read()"
+ rather than "fread()", to eliminate blocking (if READ_FROM_FILES_SYNCHRONOUSLY is not defined). (This change should
+ affect only reading from pipes, not regular files.) (Thanks to Tyson Wiser for noting this issue.)
+- Updated the "DelayQueue" destructor to make sure that any remaining delay queue entries are destroyed.
+ (Thanks to "Mr. Xiao" and Luke Kucalaba for (independently) reporting this issue.)
+- Updated "config.macosx" to change LIBRARY_LINK from "ar cr " to "libtool -s -o ", because someone reported that "ar"
+ didn't work for them.
+- Added support for receiving the "audio/EAC3" RTP payload format (which is handled the same way as "audio/AC3").
+ (Thanks to Gregory McGarry for the patch.)
+
+2011.05.25:
+- Fixed a bug in "RTSPClient" which was causing clients to crash if servers returned a 401 error code, but without a
+ "WWW-Authenticate:" header. (Thanks to Sebastien Escudier for reporting this.)
+
+2011.03.14:
+- Updated the "MPEG2TransportFileServerMediaSubsession" to use the "streamDuration" parameter (if >0.0) to limit
+ the number of Transport Packets that are streamed from the source file. (This happens only if the file is indexed.)
+ This allows the server to implement finite RTSP ranges for such streams.
+- Fixed a minor bug in "OnDemandServerMediaSubsession" if "reuseFirstSource" is set. (Thanks to Andreas Gaer for noting this.)
+
+2011.03.06:
+- Changed the implementation of "RTSPClient::teardownMediaSession()" and "RTSPClient::teardownMediaSubsession()"
+ (i.e., in the old, now-deprecated synchronous "RTSPClient" interface) to not wait for, or handle, a response to the
+ RTSP "TEARDOWN" command. This avoids the client blocking indefinitely if the server (or its connection) happens to die before
+ the RTSP response gets sent.
+ (Note, however: All RTSP client applications should be updated to use the new, asynchronous interface. The old synchronous
+ interface will not be supported indefinitely.)
+
+2011.03.05:
+- Changed the signature of the "OnDemandServerMediaSubsession::seekStreamSource()"
+ virtual function to add a "streamDuration" field. This field (if >0.0) tells
+ the implementation how much data to stream before ending with EOF.
+ Our RTSPServer implementation now uses this to implement finite RTSP ranges
+ (as specified in the "Range:" header). As with seeking, only some codecs currently
+ implement this: MP3 audio, WAV audio, and DV video.
+- We now support streaming from IMA ADPCM ("DVI4") WAV files.
+- When streaming MP3 audio files or indexed MPEG Transport Stream Files, we now compute a more accurate bitrate estimate
+ (for use in computing RTCP packet frequencies).
+
+2011.01.24:
+- Fixed a bug that was accidentally introduced in version 2011.01.10, and which crashes VLC (when VLC is used to play a
+ "rtsp://" URL). To avoid the bug, VLC should therefore use this version or later.
+
+2011.01.21:
+- Fixed a bug in "H264VideoStreamFramer" that was introduced in the last release.
+ (This affected the "testH264VideoToTransportStream" demo application.) (Thanks to Dunling Li for reporting this.)
+- Fixed a minor syntax bug in "H264VideoStreamFramer.cpp" which (fortunately) had not been an actual problem.
+ (Thanks to Guillaume Le Neindre for the report.)
+
+2011.01.20:
+- Added a new demo application "testH264VideoToTransportStream", which takes a H.264 Video input file (named "in.264"),
+ and converts it to a Transport Stream file (named "out.ts").
+ (Note that for this conversion to work properly, the input H.264 file must contain sufficient timing information for us to be
+ able to deduce the frame rate.)
+ (Thanks to Dunling Li for this suggestion.)
+- Changed our RTSP server implementation so that the "SET_PARAMETER" command succeeds (but does nothing) by default.
+ (Subclasses can redefine its behavior, if necessary.) We also now support the special "*" URL, which designates an
+ operation on the entire server. (The only commands for which this is allowed are "OPTIONS", "GET_PARAMETER" and "SET_PARAMETER".)
+ (Thanks to Jeremy Noring for noting that some clients need this.)
+
+2011.01.19:
+- Fixed a bug in "OnDemandServerMediaSubsession" that was causing unicast RTSP/RTP
+ servers to sometimes omit sending the very first packet of a stream. (This seemed
+ to occur only for servers running on Windows.)
+
+2011.01.10:
+- Updated "RTSPClient" so that the new asynchronous interface can handle RTSP URLs that contain a "<username>:<password>@"
+ before the server host name/address. This had been supported in the old synchronous interface, but when we implemented the
+ new asynchronous interface, we had forgotten to implement it there as well.
+- Made a change to the implementation (but not the default behavior) of "RTSPServer" to allow for the possibility of a subclass
+ implementing HTTP streaming (using the same HTTP port that we use to support RTSP-over-HTTP tunneling).
+
+2011.01.06:
+- We added support for receiving the RTP payload formats "audio/L20", "audio/L24" and "audio/DAT12", as defined in RFC 3190.
+ We also recognize the new "fmtp:"-line parameters "emphasis" and "channel-order" that this RFC also defines.
+ (Thanks to Maciej Szlapka for noting that these payload formats had not previously been supported.)
+
+2011.01.05:
+- Made a small change to the sanity check introduced to "MultiFramedRTPSink" and "BasicUDPSink" in version 2010.12.05 to
+ eliminate the possibility of small extra delays accumulating over time. (Thanks to Warren Young for raising this issue.)
+- Made a small change to the 'magic values' that are used to implement the "esds" atom for MPEG-4 video in "QuickTimeFileSink".
+ (I have no idea what these values are supposed to do, but Stu Tomlinson reports that the new values work better for him.)
+
+2010.12.31:
+- We now support 'trick play' operations (seeking, fast-forward, reverse play) on MPEG Transport Stream files that contain
+ H.264 video (rather than just MPEG-2 video, as previously). To support this, the index file format has been extended in a
+ backwards-compatible way, so that existing index files (for MPEG-2 video Transport Streams) will continue to work as before.
+ New versions of the "MPEG2TransportStreamIndexer" and "testMPEG2TransportStreamTrickPlay" utilities - and the
+ "live555MediaServer" - have also been released.
+- Fixed a bug in the definition of the "profile_level_id" field in "H264VideoRTPSink". (Thanks to Geoff Cleary for noting this.)
+- Change the parsing of RTSP "Range:" headers to allow parameters of the form "clock=" or"smtpe=". (However, we currently don't
+ interpret parameters of this form; instead, we just ignore them.)
+ (Thanks to Sebastien Escudier for this suggestion.)
+- Fixed "openRTSP" to properly reset internal state before repeating the playing of a stream (if the '-c' (play continuously))
+ option is used. (Thanks to Anon Sricharoenchai for noting this.)
+
+2010.12.14:
+- Oops - there was a serious bug in the 'event trigger' implementation in the previous release.
+ IMPORTANT: You should upgrade to this new version if you plan to use the 'event trigger' mechanism!
+ (Thanks to "P.J." for noticing the bug in the previous version.)
+
+2010.12.11:
+- Added a new 'event trigger' mechanism to "TaskScheduler". This makes it possible
+ to define new events that can be handled within the event loop. Unlike other
+ library functions, events can be 'triggered' (i.e., fired) from a separate thread.
+ This makes it easier to implement input devices than the old 'watchVariable'
+ mechanism (which remains).
+ Also, the "DeviceSource" class - which is a model for how to implement an input
+ device class - has been significantly improved. It now uses the new 'event trigger'
+ mechanism. Also, more of it has been implemented, making it clearer where new code
+ needs to be written.
+
+2010.12.05:
+- Significantly improved our support for streaming H.264 video. In particular, "H264VideoStreamFramer"
+ and "H264VideoStreamDiscreteFramer" (a new class) act like their corresponding MPEG4 versions: "H264VideoStreamFramer" reads
+ a H.264 Video Elementary Stream byte stream (e.g., from a file), and "H264VideoStreamDiscreteFramer" reads discrete H.264 video
+ NAL units (i.e., one-at-a-time), e.g., from a H.264 video encoder. (Note that developers no longer need to subclass
+ "H264VideoStreamFramer".) We also added a new demo application - "testH264VideoStreamer" - for streaming from
+ a H.264 Elementary Stream Video file via multicast. "testOnDemandRTSPServer" and "live555MediaServer" were also updated to
+ stream H.264 Video Elementary Stream files.
+- Added a sanity check to "MultiFramedRTPSink" and "BasicUDPSink" to allow for the possibility of the system clock jumping ahead
+ in time, and thereby messing up the calculation of how long to wait before sending the next packet.
+ (Thanks to Anders Chen for noting this issue.)
+- Fixed bugs in "AMRAudioRTPSource" and "QCELPAudioRTPSource" that might sometimes cause an event handler to try to reference
+ objects that had already been deleted. (Thanks to David Cailliere for detecting the problem with "AMRAudioRTPSource";
+ it turns out that "QCELPAudioRTPSource" had the same problem.)
+
+2010.11.17:
+- Added new a member function "setAuthenticationDatabase()" to "RTSPServer". This allows a server's manager to change
+ (or disable) authentication at runtime. (Thanks to Jeremy Norling for suggesting this functionality.)
+
+2010.11.10:
+- Fixed "openRTSP" to eliminate a recursive call to "shutdown()" if we receive a RTCP "BYE" while in the middle of doing
+ a RTSP "TEARDOWN" command. (Thanks to David Cailliere for noting this issue.)
+
+2010.11.09:
+- The previous release had accidentally included some experimental changes to "H264VideoStreamFramer" that were not (yet)
+ intended to see the light of day.
+
+2010.11.08:
+- Fixed a minor problem with RTSP-over-HTTP support in "RTSPClient" that was causing some servers to complain due to the
+ "CSeq:" header value not being incremented properly. (Thanks to Kamil Dobkowski for the report.)
+
+2010.11.04:
+- Backed out and corrected the change to "RTSPClient" that we made in version 2010.10.22. It turns out that existing RTSP-over-HTTP
+ servers that return "401 Unauthorized" in response to the HTTP "GET" *do*, in fact, want clients to resend the "GET" command
+ (with a filled-in "Authorization:" header). However, at least one such server out there closes the TCP connection after
+ sending back the "401 Unauthorized" response, so we need to send the second "GET" command using a new TCP connection.
+ (Thanks to Kamil Dobkowski for providing access to a server that illustrated this problem.)
+
+2010.10.28:
+- Updated "JPEGVideoRTPSource" amd "JPEGVideoRTPSink" to support optional "Restart Marker Headers" in the outgoing RTP packet.
+ (We already supported such headers in *incoming* JPEG/RTP packets ("JPEGVideoRTPSource").)
+ If "type()" (defined by the "JPEGVideoSource" subclass) returns a value in [64,127], then the "JPEGVideoSource" subclass must
+ also redefine "restartInterval()" to return a non-zero value.
+ (Thanks to Cristiano Belloni for suggesting this addition.)
+
+2010.10.23a:
+- Fixed a bug in the way that "RTSPClient" generates ephemeral RTP/RTCP port number pairs for use when receiving unicast
+ RTSP/RTP streams. The RTP (even) port was guaranteed not to be in use elsewhere on the same host, but that guarantee was not
+ necessarily true for the RTCP (next, i.e. odd) port. This version fixes this.
+
+2010.10.23:
+- Our server implementation of "RTSP-over-HTTP tunneling" now allows for the possibility of receiving data from the
+ (Base-64-encoded) initial RTSP command at the same time that we receive the HTTP "POST" command. (This is a possibility because
+ the client does not wait for a response to the "POST" - because there isn't one.)
|
[-]
[+]
|
Deleted |
live.2010.09.25.tar.bz2/liveMedia/RTSPOverHTTPServer.cpp
^
|
@@ -1,379 +0,0 @@
-/**********
-This library is free software; you can redistribute it and/or modify it under
-the terms of the GNU Lesser General Public License as published by the
-Free Software Foundation; either version 2.1 of the License, or (at your
-option) any later version. (See <http://www.gnu.org/copyleft/lesser.html>.)
-
-This library 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 Lesser General Public License for
-more details.
-
-You should have received a copy of the GNU Lesser General Public License
-along with this library; if not, write to the Free Software Foundation, Inc.,
-51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
-**********/
-// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
-// A simple HTTP server that acts solely to implement RTSP-over-HTTP tunneling
-// (to a separate RTSP server), as described in
-// http://developer.apple.com/documentation/QuickTime/QTSS/Concepts/chapter_2_section_14.html
-// Implementation
-
-#include "RTSPOverHTTPServer.hh"
-#include "RTSPCommon.hh"
-#include <GroupsockHelper.hh>
-
-#include <string.h>
-#if defined(__WIN32__) || defined(_WIN32) || defined(_QNX4)
-#define snprintf _snprintf
-#else
-#include <signal.h>
-#define USE_SIGNALS 1
-#endif
-
-
-#define DEBUG 1 //#####@@@@@
-///////// RTSPOverHTTPServer implementation //////////
-
-#define HTTP_PARAM_STRING_MAX 100
-
-RTSPOverHTTPServer*
-RTSPOverHTTPServer::createNew(UsageEnvironment& env, Port ourHTTPPort,
- Port rtspServerPort, char const* rtspServerHostName) {
- int ourSocket = -1;
-
- do {
- ourSocket = setUpOurSocket(env, ourHTTPPort);
- if (ourSocket == -1) break;
-
- return new RTSPOverHTTPServer(env, ourSocket, rtspServerPort, rtspServerHostName);
- } while (0);
-
- if (ourSocket != -1) ::closeSocket(ourSocket);
- return NULL;
-}
-
-#define LISTEN_BACKLOG_SIZE 20
-
-int RTSPOverHTTPServer::setUpOurSocket(UsageEnvironment& env, Port& ourPort) {
- int ourSocket = -1;
-
- do {
- NoReuse dummy; // Don't use this socket if there's already a local server using it
-
- ourSocket = setupStreamSocket(env, ourPort);
- if (ourSocket < 0) break;
-
- // Make sure we have a big send buffer:
- if (!increaseSendBufferTo(env, ourSocket, 50*1024)) break;
-
- // Allow multiple simultaneous connections:
- if (listen(ourSocket, LISTEN_BACKLOG_SIZE) < 0) {
- env.setResultErrMsg("listen() failed: ");
- break;
- }
-
- if (ourPort.num() == 0) {
- // bind() will have chosen a port for us; return it also:
- if (!getSourcePort(env, ourSocket, ourPort)) break;
- }
-
- return ourSocket;
- } while (0);
-
- if (ourSocket != -1) ::closeSocket(ourSocket);
- return -1;
-}
-
-RTSPOverHTTPServer
-::RTSPOverHTTPServer(UsageEnvironment& env, int ourSocket,
- Port rtspServerPort, char const* rtspServerHostName)
- : Medium(env),
- fServerSocket(ourSocket),
- fRTSPServerPort(rtspServerPort), fRTSPServerHostName(strDup(rtspServerHostName)) {
-#ifdef USE_SIGNALS
- // Ignore the SIGPIPE signal, so that clients on the same host that are killed
- // don't also kill us:
- signal(SIGPIPE, SIG_IGN);
-#endif
-
- // Arrange to handle connections from others:
- env.taskScheduler().turnOnBackgroundReadHandling(fServerSocket,
- (TaskScheduler::BackgroundHandlerProc*)&incomingConnectionHandler,
- this);
-}
-
-RTSPOverHTTPServer::~RTSPOverHTTPServer() {
- delete[] fRTSPServerHostName;
-}
-
-void RTSPOverHTTPServer::incomingConnectionHandler(void* instance, int /*mask*/) {
- RTSPOverHTTPServer* server = (RTSPOverHTTPServer*)instance;
- server->incomingConnectionHandler1();
-}
-
-void RTSPOverHTTPServer::incomingConnectionHandler1() {
- struct sockaddr_in clientAddr;
- SOCKLEN_T clientAddrLen = sizeof clientAddr;
- int clientSocket = accept(fServerSocket, (struct sockaddr*)&clientAddr,
- &clientAddrLen);
- if (clientSocket < 0) {
- int err = envir().getErrno();
- if (err != EWOULDBLOCK) {
- envir().setResultErrMsg("accept() failed: ");
- }
- return;
- }
- makeSocketNonBlocking(clientSocket);
- increaseSendBufferTo(envir(), clientSocket, 50*1024);
-#if defined(DEBUG) || defined(DEBUG_CONNECTIONS)
- fprintf(stderr, "accept()ed connection from %s\n", our_inet_ntoa(clientAddr.sin_addr));
-#endif
-
- // Create a new object for handling this HTTP connection:
- new HTTPClientConnection(*this, clientSocket);
-}
-
-
-////////// HTTPClientConnection implementation /////////
-
-RTSPOverHTTPServer::HTTPClientConnection
-::HTTPClientConnection(RTSPOverHTTPServer& ourServer, int clientSocket)
- : fOurServer(ourServer), fClientSocket(clientSocket), fSessionIsActive(True) {
- // Arrange to handle incoming requests:
- resetRequestBuffer();
- envir().taskScheduler().turnOnBackgroundReadHandling(fClientSocket,
- (TaskScheduler::BackgroundHandlerProc*)&incomingRequestHandler, this);
-}
-
-RTSPOverHTTPServer::HTTPClientConnection
-::~HTTPClientConnection() {
- // Turn off background read handling:
- envir().taskScheduler().turnOffBackgroundReadHandling(fClientSocket);
-
- ::closeSocket(fClientSocket);
-}
-
-void RTSPOverHTTPServer::HTTPClientConnection
-::incomingRequestHandler(void* instance, int /*mask*/) {
- HTTPClientConnection* connection = (HTTPClientConnection*)instance;
- connection->incomingRequestHandler1();
-}
-
-void RTSPOverHTTPServer::HTTPClientConnection::incomingRequestHandler1() {
- struct sockaddr_in dummy; // 'from' address, meaningless in this case
- Boolean endOfMsg = False;
- unsigned char* ptr = &fRequestBuffer[fRequestBytesAlreadySeen];
-
- int bytesRead = readSocket(envir(), fClientSocket,
- ptr, fRequestBufferBytesLeft, dummy);
- if (bytesRead <= 0 || (unsigned)bytesRead >= fRequestBufferBytesLeft) {
- // Either the client socket has died, or the request was too big for us.
- // Terminate this connection:
-#ifdef DEBUG
- fprintf(stderr, "HTTPClientConnection[%p]::incomingRequestHandler1() read %d bytes (of %d); terminating connection!\n", this, bytesRead, fRequestBufferBytesLeft);
-#endif
- delete this;
- return;
- }
-#ifdef DEBUG
- ptr[bytesRead] = '\0';
- fprintf(stderr, "HTTPClientConnection[%p]::incomingRequestHandler1() read %d bytes:%s\n",
- this, bytesRead, ptr);
-#endif
-
- // Look for the end of the message: <CR><LF><CR><LF>
- unsigned char *tmpPtr = ptr;
- if (fRequestBytesAlreadySeen > 0) --tmpPtr;
- // in case the last read ended with a <CR>
- while (tmpPtr < &ptr[bytesRead-1]) {
- if (*tmpPtr == '\r' && *(tmpPtr+1) == '\n') {
- if (tmpPtr - fLastCRLF == 2) { // This is it:
- endOfMsg = 1;
- break;
- }
- fLastCRLF = tmpPtr;
- }
- ++tmpPtr;
- }
-
- fRequestBufferBytesLeft -= bytesRead;
- fRequestBytesAlreadySeen += bytesRead;
-
- if (!endOfMsg) return; // subsequent reads will be needed to complete the request
-
- // Parse the request string to get the (few) parameters that we care about,
- // then handle the command:
- fRequestBuffer[fRequestBytesAlreadySeen] = '\0';
- char cmdName[HTTP_PARAM_STRING_MAX];
- char sessionCookie[HTTP_PARAM_STRING_MAX];
- char acceptStr[HTTP_PARAM_STRING_MAX];
- char contentTypeStr[HTTP_PARAM_STRING_MAX];
- if (!parseHTTPRequestString(cmdName, sizeof cmdName,
- sessionCookie, sizeof sessionCookie,
- acceptStr, sizeof acceptStr,
- contentTypeStr, sizeof contentTypeStr)) {
-#ifdef DEBUG
- fprintf(stderr, "parseHTTPRTSPRequestString() failed!\n");
-#endif
- handleCmd_bad();
- } else {
-#ifdef DEBUG
- fprintf(stderr, "parseHTTPRTSPRequestString() returned cmdName \"%s\", sessionCookie \"%s\", acceptStr \"%s\", contentTypeStr \"%s\"\n", cmdName, sessionCookie, acceptStr, contentTypeStr);
-#endif
-#if 0
- if (strcmp(cmdName, "OPTIONS") == 0) {
- handleCmd_OPTIONS(cseq);
- } else if (strcmp(cmdName, "DESCRIBE") == 0) {
- handleCmd_DESCRIBE(cseq, urlSuffix, (char const*)fRequestBuffer);
- } else if (strcmp(cmdName, "SETUP") == 0) {
- handleCmd_SETUP(cseq, urlPreSuffix, urlSuffix, (char const*)fRequestBuffer);
- } else if (strcmp(cmdName, "TEARDOWN") == 0
- || strcmp(cmdName, "PLAY") == 0
- || strcmp(cmdName, "PAUSE") == 0
- || strcmp(cmdName, "GET_PARAMETER") == 0
- || strcmp(cmdName, "SET_PARAMETER") == 0) {
- handleCmd_withinSession(cmdName, urlPreSuffix, urlSuffix, cseq,
- (char const*)fRequestBuffer);
- } else {
- handleCmd_notSupported(cseq);
- }
-#endif
- }
-
-#ifdef DEBUG
- fprintf(stderr, "sending response: %s", fResponseBuffer);
-#endif
- send(fClientSocket, (char const*)fResponseBuffer, strlen((char*)fResponseBuffer), 0);
-
- resetRequestBuffer(); // to prepare for any subsequent request
- if (!fSessionIsActive) delete this;
-}
-
-void RTSPOverHTTPServer::HTTPClientConnection::resetRequestBuffer() {
- fRequestBytesAlreadySeen = 0;
- fRequestBufferBytesLeft = sizeof fRequestBuffer;
- fLastCRLF = &fRequestBuffer[-3]; // hack
-}
-
-Boolean RTSPOverHTTPServer::HTTPClientConnection::
-parseHTTPRequestString(char* resultCmdName,
- unsigned resultCmdNameMaxSize,
- char* sessionCookie,
- unsigned sessionCookieMaxSize,
- char* acceptStr,
- unsigned acceptStrMaxSize,
- char* contentTypeStr,
- unsigned contentTypeStrMaxSize) {
- return False; //#####@@@@@
-#if 0
- // This parser is currently rather dumb; it should be made smarter #####
-
- // Read everything up to the first space as the command name:
- Boolean parseSucceeded = False;
- unsigned i;
- for (i = 0; i < resultCmdNameMaxSize-1 && i < reqStrSize; ++i) {
- char c = reqStr[i];
- if (c == ' ' || c == '\t') {
- parseSucceeded = True;
- break;
- }
-
- resultCmdName[i] = c;
- }
- resultCmdName[i] = '\0';
- if (!parseSucceeded) return False;
-
- // Skip over the prefix of any "rtsp://" or "rtsp:/" URL that follows:
- unsigned j = i+1;
- while (j < reqStrSize && (reqStr[j] == ' ' || reqStr[j] == '\t')) ++j; // skip over any additional white space
- for (j = i+1; j < reqStrSize-8; ++j) {
- if ((reqStr[j] == 'r' || reqStr[j] == 'R')
- && (reqStr[j+1] == 't' || reqStr[j+1] == 'T')
- && (reqStr[j+2] == 's' || reqStr[j+2] == 'S')
- && (reqStr[j+3] == 'p' || reqStr[j+3] == 'P')
- && reqStr[j+4] == ':' && reqStr[j+5] == '/') {
- j += 6;
- if (reqStr[j] == '/') {
- // This is a "rtsp://" URL; skip over the host:port part that follows:
- ++j;
- while (j < reqStrSize && reqStr[j] != '/' && reqStr[j] != ' ') ++j;
- } else {
- // This is a "rtsp:/" URL; back up to the "/":
- --j;
- }
- i = j;
- break;
- }
- }
-
- // Look for the URL suffix (before the following "RTSP/"):
- parseSucceeded = False;
- for (unsigned k = i+1; k < reqStrSize-5; ++k) {
- if (reqStr[k] == 'R' && reqStr[k+1] == 'T' &&
- reqStr[k+2] == 'S' && reqStr[k+3] == 'P' && reqStr[k+4] == '/') {
- while (--k >= i && reqStr[k] == ' ') {} // go back over all spaces before "RTSP/"
- unsigned k1 = k;
- while (k1 > i && reqStr[k1] != '/' && reqStr[k1] != ' ') --k1;
- // the URL suffix comes from [k1+1,k]
-
- // Copy "resultURLSuffix":
- if (k - k1 + 1 > resultURLSuffixMaxSize) return False; // there's no room
- unsigned n = 0, k2 = k1+1;
- while (k2 <= k) resultURLSuffix[n++] = reqStr[k2++];
- resultURLSuffix[n] = '\0';
-
- // Also look for the URL 'pre-suffix' before this:
- unsigned k3 = --k1;
- while (k3 > i && reqStr[k3] != '/' && reqStr[k3] != ' ') --k3;
- // the URL pre-suffix comes from [k3+1,k1]
-
- // Copy "resultURLPreSuffix":
- if (k1 - k3 + 1 > resultURLPreSuffixMaxSize) return False; // there's no room
- n = 0; k2 = k3+1;
- while (k2 <= k1) resultURLPreSuffix[n++] = reqStr[k2++];
- resultURLPreSuffix[n] = '\0';
-
- i = k + 7; // to go past " RTSP/"
- parseSucceeded = True;
- break;
- }
- }
- if (!parseSucceeded) return False;
-
- // Look for "CSeq:", skip whitespace,
- // then read everything up to the next \r or \n as 'CSeq':
- parseSucceeded = False;
- for (j = i; j < reqStrSize-5; ++j) {
- if (reqStr[j] == 'C' && reqStr[j+1] == 'S' && reqStr[j+2] == 'e' &&
- reqStr[j+3] == 'q' && reqStr[j+4] == ':') {
- j += 5;
- unsigned n;
- while (j < reqStrSize && (reqStr[j] == ' ' || reqStr[j] == '\t')) ++j;
- for (n = 0; n < resultCSeqMaxSize-1 && j < reqStrSize; ++n,++j) {
- char c = reqStr[j];
- if (c == '\r' || c == '\n') {
- parseSucceeded = True;
- break;
- }
-
- resultCSeq[n] = c;
- }
- resultCSeq[n] = '\0';
- break;
- }
- }
- if (!parseSucceeded) return False;
-
- return True;
-#endif
-}
-
-static char const* allowedCommandNames = "GET, PUT";
-
-void RTSPOverHTTPServer::HTTPClientConnection::handleCmd_bad() {
- snprintf((char*)fResponseBuffer, sizeof fResponseBuffer,
- "HTTP/1.1 400 Bad Request\r\nAllow: %s\r\n\r\n",
- allowedCommandNames);
-}
|
[-]
[+]
|
Deleted |
live.2010.09.25.tar.bz2/liveMedia/include/RTSPOverHTTPServer.hh
^
|
@@ -1,131 +0,0 @@
-/**********
-This library is free software; you can redistribute it and/or modify it under
-the terms of the GNU Lesser General Public License as published by the
-Free Software Foundation; either version 2.1 of the License, or (at your
-option) any later version. (See <http://www.gnu.org/copyleft/lesser.html>.)
-
-This library 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 Lesser General Public License for
-more details.
-
-You should have received a copy of the GNU Lesser General Public License
-along with this library; if not, write to the Free Software Foundation, Inc.,
-51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
-**********/
-// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
-// A simple HTTP server that acts solely to implement RTSP-over-HTTP tunneling
-// (to a separate RTSP server), as described in
-// http://developer.apple.com/documentation/QuickTime/QTSS/Concepts/chapter_2_section_14.html
-// C++ header
-
-#ifndef _RTSP_OVER_HTTP_SERVER_HH
-#define _RTSP_OVER_HTTP_SERVER_HH
-
-#include "Media.hh"
-#include "NetInterface.hh"
-
-#define HTTP_BUFFER_SIZE 10000 // for incoming requests, and outgoing responses
-
-class RTSPOverHTTPServer: public Medium {
-public:
- static RTSPOverHTTPServer* createNew(UsageEnvironment& env, Port ourHTTPPort = 80,
- Port rtspServerPort = 554,
- char const* rtspServerHostName = "localhost");
-
-protected:
- RTSPOverHTTPServer(UsageEnvironment& env, int ourSocket,
- Port rtspServerPort, char const* rtspServerHostName);
- // called only by createNew();
- virtual ~RTSPOverHTTPServer();
-
- static int setUpOurSocket(UsageEnvironment& env, Port& ourPort);
-
-private:
- static void incomingConnectionHandler(void*, int /*mask*/);
- void incomingConnectionHandler1();
-
- // The state of each individual connection handled by a HTTP server:
- class HTTPClientConnection {
- public:
- HTTPClientConnection(RTSPOverHTTPServer& ourServer, int clientSocket);
- virtual ~HTTPClientConnection();
- private:
- static void incomingRequestHandler(void*, int /*mask*/);
- void incomingRequestHandler1();
- UsageEnvironment& envir() { return fOurServer.envir(); }
- void resetRequestBuffer();
- Boolean parseHTTPRequestString(char* resultCmdName,
- unsigned resultCmdNameMaxSize,
- char* sessionCookie,
- unsigned sessionCookieMaxSize,
- char* acceptStr,
- unsigned acceptStrMaxSize,
- char* contentTypeStr,
- unsigned contentTypeStrMaxSize);
- void handleCmd_bad();
-#if 0 //#####@@@@@
- void handleCmd_notSupported(char const* cseq);
- void handleCmd_notFound(char const* cseq);
- void handleCmd_unsupportedTransport(char const* cseq);
- void handleCmd_OPTIONS(char const* cseq);
- void handleCmd_DESCRIBE(char const* cseq, char const* urlSuffix,
- char const* fullRequestStr);
- void handleCmd_SETUP(char const* cseq,
- char const* urlPreSuffix, char const* urlSuffix,
- char const* fullRequestStr);
- void handleCmd_withinSession(char const* cmdName,
- char const* urlPreSuffix, char const* urlSuffix,
- char const* cseq, char const* fullRequestStr);
- void handleCmd_TEARDOWN(ServerMediaSubsession* subsession,
- char const* cseq);
- void handleCmd_PLAY(ServerMediaSubsession* subsession,
- char const* cseq, char const* fullRequestStr);
- void handleCmd_PAUSE(ServerMediaSubsession* subsession,
- char const* cseq);
- void handleCmd_GET_PARAMETER(ServerMediaSubsession* subsession,
- char const* cseq, char const* fullRequestStr);
- Boolean authenticationOK(char const* cmdName, char const* cseq,
- char const* fullRequestStr);
- void noteLiveness();
- Boolean isMulticast() const { return fIsMulticast; }
- static void noteClientLiveness(HTTPClientConnection* clientConnection);
- static void livenessTimeoutTask(HTTPClientConnection* clientConnection);
-#endif
-
- private:
- RTSPOverHTTPServer& fOurServer;
-#if 0 //#####@@@@@
- unsigned fOurSessionId;
- ServerMediaSession* fOurServerMediaSession;
-#endif
- int fClientSocket;
-#if 0 //#####@@@@@
- struct sockaddr_in fClientAddr;
- TaskToken fLivenessCheckTask;
-#endif
- unsigned char fRequestBuffer[HTTP_BUFFER_SIZE];
- unsigned fRequestBytesAlreadySeen, fRequestBufferBytesLeft;
- unsigned char* fLastCRLF;
- unsigned char fResponseBuffer[HTTP_BUFFER_SIZE];
- Boolean fSessionIsActive;
-#if 0 //#####@@@@@
- Authenticator fCurrentAuthenticator; // used if access control is needed
- unsigned char fTCPStreamIdCount; // used for (optional) RTP/TCP
- unsigned fNumStreamStates;
- struct streamState {
- ServerMediaSubsession* subsession;
- void* streamToken;
- } * fStreamStates;
-#endif
- };
-
-private:
- friend class RTSPOverHTTPTunnel;
- int fServerSocket;
- Port fRTSPServerPort;
- char* fRTSPServerHostName;
-};
-
-#endif
|
[-]
[+]
|
Deleted |
live.2010.09.25.tar.bz2/testProgs/_rtp_over_tcp.txt
^
|
@@ -1,8 +0,0 @@
-Opening connection to 192.168.3.75, port 554...
-...Connection to server failed: No route to host
-Sending request: DESCRIBE rtsp://192.168.3.75/VideoInput/1/jpeg/1 RTSP/1.0
-CSeq: 3
-User-Agent: ./openRTSP (LIVE555 Streaming Media v2010.07.10)
-Accept: application/sdp
-
-
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/BasicUsageEnvironment/BasicHashTable.cpp
^
|
@@ -13,7 +13,7 @@
along with this library; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// Basic Hash Table implementation
// Implementation
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/BasicUsageEnvironment/BasicTaskScheduler.cpp
^
|
@@ -13,7 +13,7 @@
along with this library; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// Basic Usage Environment: for a simple, non-scripted, console application
// Implementation
@@ -32,11 +32,18 @@
return new BasicTaskScheduler();
}
+#define MAX_SCHEDULER_GRANULARITY 10000 // 10 microseconds: We will return to the event loop at least this often
+static void schedulerTickTask(void* clientData) {
+ ((BasicTaskScheduler*)clientData)->scheduleDelayedTask(MAX_SCHEDULER_GRANULARITY, schedulerTickTask, clientData);
+}
+
BasicTaskScheduler::BasicTaskScheduler()
: fMaxNumSockets(0) {
FD_ZERO(&fReadSet);
FD_ZERO(&fWriteSet);
FD_ZERO(&fExceptionSet);
+
+ schedulerTickTask(this); // ensures that we handle events frequently
}
BasicTaskScheduler::~BasicTaskScheduler() {
@@ -145,8 +152,40 @@
if (handler == NULL) fLastHandledSocketNum = -1;//because we didn't call a handler
}
- // Also handle any delayed event that may have come due. (Note that we do this *after* calling a socket
- // handler, in case the delayed event handler modifies the set of readable sockets.)
+ // Also handle any newly-triggered event (Note that we do this *after* calling a socket handler,
+ // in case the triggered event handler modifies The set of readable sockets.)
+ if (fTriggersAwaitingHandling != 0) {
+ if (fTriggersAwaitingHandling == fLastUsedTriggerMask) {
+ // Common-case optimization for a single event trigger:
+ fTriggersAwaitingHandling = 0;
+ if (fTriggeredEventHandlers[fLastUsedTriggerNum] != NULL) {
+ (*fTriggeredEventHandlers[fLastUsedTriggerNum])(fTriggeredEventClientDatas[fLastUsedTriggerNum]);
+ }
+ } else {
+ // Look for an event trigger that needs handling (making sure that we make forward progress through all possible triggers):
+ unsigned i = fLastUsedTriggerNum;
+ EventTriggerId mask = fLastUsedTriggerMask;
+
+ do {
+ i = (i+1)%MAX_NUM_EVENT_TRIGGERS;
+ mask >>= 1;
+ if (mask == 0) mask = 0x80000000;
+
+ if ((fTriggersAwaitingHandling&mask) != 0) {
+ fTriggersAwaitingHandling &=~ mask;
+ if (fTriggeredEventHandlers[i] != NULL) {
+ (*fTriggeredEventHandlers[i])(fTriggeredEventClientDatas[i]);
+ }
+
+ fLastUsedTriggerMask = mask;
+ fLastUsedTriggerNum = i;
+ break;
+ }
+ } while (i != fLastUsedTriggerNum);
+ }
+ }
+
+ // Also handle any delayed event that may have come due.
fDelayQueue.handleAlarm();
}
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/BasicUsageEnvironment/BasicTaskScheduler0.cpp
^
|
@@ -13,7 +13,7 @@
along with this library; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// Basic Usage Environment: for a simple, non-scripted, console application
// Implementation
@@ -44,8 +44,12 @@
////////// BasicTaskScheduler0 //////////
BasicTaskScheduler0::BasicTaskScheduler0()
- : fLastHandledSocketNum(-1) {
+ : fLastHandledSocketNum(-1), fTriggersAwaitingHandling(0), fLastUsedTriggerMask(1), fLastUsedTriggerNum(MAX_NUM_EVENT_TRIGGERS-1) {
fHandlers = new HandlerSet;
+ for (unsigned i = 0; i < MAX_NUM_EVENT_TRIGGERS; ++i) {
+ fTriggeredEventHandlers[i] = NULL;
+ fTriggeredEventClientDatas[i] = NULL;
+ }
}
BasicTaskScheduler0::~BasicTaskScheduler0() {
@@ -77,6 +81,74 @@
}
}
+EventTriggerId BasicTaskScheduler0::createEventTrigger(TaskFunc* eventHandlerProc) {
+ unsigned i = fLastUsedTriggerNum;
+ EventTriggerId mask = fLastUsedTriggerMask;
+
+ do {
+ i = (i+1)%MAX_NUM_EVENT_TRIGGERS;
+ mask >>= 1;
+ if (mask == 0) mask = 0x80000000;
+
+ if (fTriggeredEventHandlers[i] == NULL) {
+ // This trigger number is free; use it:
+ fTriggeredEventHandlers[i] = eventHandlerProc;
+ fTriggeredEventClientDatas[i] = NULL; // sanity
+
+ fLastUsedTriggerMask = mask;
+ fLastUsedTriggerNum = i;
+
+ return mask;
+ }
+ } while (i != fLastUsedTriggerNum);
+
+ // All available event triggers are allocated; return 0 instead:
+ return 0;
+}
+
+void BasicTaskScheduler0::deleteEventTrigger(EventTriggerId eventTriggerId) {
+ fTriggersAwaitingHandling &=~ eventTriggerId;
+
+ if (eventTriggerId == fLastUsedTriggerMask) { // common-case optimization:
+ fTriggeredEventHandlers[fLastUsedTriggerNum] = NULL;
+ fTriggeredEventClientDatas[fLastUsedTriggerNum] = NULL;
+ } else {
+ // "eventTriggerId" should have just one bit set.
+ // However, we do the reasonable thing if the user happened to 'or' together two or more "EventTriggerId"s:
+ EventTriggerId mask = 0x80000000;
+ for (unsigned i = 0; i < MAX_NUM_EVENT_TRIGGERS; ++i) {
+ if ((eventTriggerId&mask) != 0) {
+ fTriggeredEventHandlers[i] = NULL;
+ fTriggeredEventClientDatas[i] = NULL;
+ }
+ mask >>= 1;
+ }
+ }
+}
+
+void BasicTaskScheduler0::triggerEvent(EventTriggerId eventTriggerId, void* clientData) {
+ // First, record the "clientData":
+ if (eventTriggerId == fLastUsedTriggerMask) { // common-case optimization:
+ fTriggeredEventClientDatas[fLastUsedTriggerNum] = clientData;
+ } else {
+ EventTriggerId mask = 0x80000000;
+ for (unsigned i = 0; i < MAX_NUM_EVENT_TRIGGERS; ++i) {
+ if ((eventTriggerId&mask) != 0) {
+ fTriggeredEventClientDatas[i] = clientData;
+
+ fLastUsedTriggerMask = mask;
+ fLastUsedTriggerNum = i;
+ }
+ mask >>= 1;
+ }
+ }
+
+ // Then, note this event as being ready to be handled.
+ // (Note that because this function (unlike others in the library) can be called from an external thread, we do this last, to
+ // reduce the risk of a race condition.)
+ fTriggersAwaitingHandling |= eventTriggerId;
+}
+
////////// HandlerSet (etc.) implementation //////////
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/BasicUsageEnvironment/BasicUsageEnvironment.cpp
^
|
@@ -13,7 +13,7 @@
along with this library; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// Basic Usage Environment: for a simple, non-scripted, console application
// Implementation
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/BasicUsageEnvironment/BasicUsageEnvironment0.cpp
^
|
@@ -13,7 +13,7 @@
along with this library; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// Basic Usage Environment: for a simple, non-scripted, console application
// Implementation
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/BasicUsageEnvironment/DelayQueue.cpp
^
|
@@ -13,7 +13,7 @@
along with this library; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
-// Copyright (c) 1996-2010, Live Networks, Inc. All rights reserved
+// Copyright (c) 1996-2011, Live Networks, Inc. All rights reserved
// Help by Carlo Bonamico to get working for Windows
// Delay queue
// Implementation
@@ -113,7 +113,11 @@
}
DelayQueue::~DelayQueue() {
- while (fNext != this) removeEntry(fNext);
+ while (fNext != this) {
+ DelayQueueEntry* entryToRemove = fNext;
+ removeEntry(entryToRemove);
+ delete entryToRemove;
+ }
}
void DelayQueue::addEntry(DelayQueueEntry* newEntry) {
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/BasicUsageEnvironment/include/BasicHashTable.hh
^
|
@@ -13,7 +13,7 @@
along with this library; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// Basic Hash Table implementation
// C++ header
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/BasicUsageEnvironment/include/BasicUsageEnvironment.hh
^
|
@@ -13,7 +13,7 @@
along with this library; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// Basic Usage Environment: for a simple, non-scripted, console application
// C++ header
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/BasicUsageEnvironment/include/BasicUsageEnvironment0.hh
^
|
@@ -13,7 +13,7 @@
along with this library; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// Basic Usage Environment: for a simple, non-scripted, console application
// C++ header
@@ -67,6 +67,8 @@
class HandlerSet; // forward
+#define MAX_NUM_EVENT_TRIGGERS 32
+
// An abstract base class, useful for subclassing
// (e.g., to redefine the implementation of socket event handling)
class BasicTaskScheduler0: public TaskScheduler {
@@ -86,6 +88,10 @@
virtual void doEventLoop(char* watchVariable);
+ virtual EventTriggerId createEventTrigger(TaskFunc* eventHandlerProc);
+ virtual void deleteEventTrigger(EventTriggerId eventTriggerId);
+ virtual void triggerEvent(EventTriggerId eventTriggerId, void* clientData = NULL);
+
protected:
BasicTaskScheduler0();
@@ -96,6 +102,12 @@
// To implement background reads:
HandlerSet* fHandlers;
int fLastHandledSocketNum;
+
+ // To implement event triggers:
+ EventTriggerId fTriggersAwaitingHandling, fLastUsedTriggerMask; // implemented as 32-bit bitmaps
+ TaskFunc* fTriggeredEventHandlers[MAX_NUM_EVENT_TRIGGERS];
+ void* fTriggeredEventClientDatas[MAX_NUM_EVENT_TRIGGERS];
+ unsigned fLastUsedTriggerNum; // in the range [0,MAX_NUM_EVENT_TRIGGERS)
};
#endif
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/BasicUsageEnvironment/include/BasicUsageEnvironment_version.hh
^
|
@@ -1,10 +1,10 @@
// Version information for the "BasicUsageEnvironment" library
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
#ifndef _BASICUSAGEENVIRONMENT_VERSION_HH
#define _BASICUSAGEENVIRONMENT_VERSION_HH
-#define BASICUSAGEENVIRONMENT_LIBRARY_VERSION_STRING "2010.09.25"
-#define BASICUSAGEENVIRONMENT_LIBRARY_VERSION_INT 1285372800
+#define BASICUSAGEENVIRONMENT_LIBRARY_VERSION_STRING "2011.06.16"
+#define BASICUSAGEENVIRONMENT_LIBRARY_VERSION_INT 1308182400
#endif
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/BasicUsageEnvironment/include/DelayQueue.hh
^
|
@@ -13,7 +13,7 @@
along with this library; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
- // Copyright (c) 1996-2010, Live Networks, Inc. All rights reserved
+ // Copyright (c) 1996-2011, Live Networks, Inc. All rights reserved
// Delay queue
// C++ header
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/BasicUsageEnvironment/include/HandlerSet.hh
^
|
@@ -13,7 +13,7 @@
along with this library; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// Basic Usage Environment: for a simple, non-scripted, console application
// C++ header
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/UsageEnvironment/HashTable.cpp
^
|
@@ -13,7 +13,7 @@
along with this library; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// Generic Hash Table
// Implementation
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/UsageEnvironment/Makefile.tail
^
|
@@ -16,7 +16,7 @@
$(CPLUSPLUS_COMPILER) -c $(CPLUSPLUS_FLAGS) $<
UsageEnvironment.$(CPP): include/UsageEnvironment.hh
-include/UsageEnvironment.hh: include/UsageEnvironment_version.hh include/strDup.hh
+include/UsageEnvironment.hh: include/UsageEnvironment_version.hh include/Boolean.hh include/strDup.hh
HashTable.$(CPP): include/HashTable.hh
include/HashTable.hh: include/Boolean.hh
strDup.$(CPP): include/strDup.hh
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/UsageEnvironment/UsageEnvironment.cpp
^
|
@@ -13,7 +13,7 @@
along with this library; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// Usage Environment
// Implementation
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/UsageEnvironment/include/HashTable.hh
^
|
@@ -13,7 +13,7 @@
along with this library; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// Generic Hash Table
// C++ header
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/UsageEnvironment/include/UsageEnvironment.hh
^
|
@@ -13,7 +13,7 @@
along with this library; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// Usage Environment
// C++ header
@@ -28,6 +28,10 @@
#include "NetCommon.h"
#endif
+#ifndef _BOOLEAN_HH
+#include "Boolean.hh"
+#endif
+
#ifndef _STRDUP_HH
// "strDup()" is used often, so include this here, so everyone gets it:
#include "strDup.hh"
@@ -96,6 +100,7 @@
typedef void TaskFunc(void* clientData);
typedef void* TaskToken;
+typedef u_int32_t EventTriggerId;
class TaskScheduler {
public:
@@ -132,11 +137,19 @@
// Changes any socket handling for "oldSocketNum" so that occurs with "newSocketNum" instead.
virtual void doEventLoop(char* watchVariable = NULL) = 0;
- // Stops the current thread of control from proceeding,
- // but allows delayed tasks (and/or background I/O handling)
- // to proceed.
- // (If "watchVariable" is not NULL, then we return from this
- // routine when *watchVariable != 0)
+ // Causes further execution to take place within the event loop.
+ // Delayed tasks, background I/O handling, and other events are handled, sequentially (as a single thread of control).
+ // (If "watchVariable" is not NULL, then we return from this routine when *watchVariable != 0)
+
+ virtual EventTriggerId createEventTrigger(TaskFunc* eventHandlerProc) = 0;
+ // Creates a 'trigger' for an event, which - if it occurs - will be handled (from the event loop) using "eventHandlerProc".
+ // (Returns 0 iff no such trigger can be created (e.g., because of implementation limits on the number of triggers).)
+ virtual void deleteEventTrigger(EventTriggerId eventTriggerId) = 0;
+
+ virtual void triggerEvent(EventTriggerId eventTriggerId, void* clientData = NULL) = 0;
+ // Causes the (previously-registered) handler function for the specified event to be handled (from the event loop).
+ // The handler function is called with "clientData" as parameter.
+ // Note: This function (unlike other library functions) may be called from an external thread - to signal an external event.
// The following two functions are deprecated, and are provided for backwards-compatibility only:
void turnOnBackgroundReadHandling(int socketNum, BackgroundHandlerProc* handlerProc, void* clientData) {
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/UsageEnvironment/include/UsageEnvironment_version.hh
^
|
@@ -1,10 +1,10 @@
// Version information for the "UsageEnvironment" library
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
#ifndef _USAGEENVIRONMENT_VERSION_HH
#define _USAGEENVIRONMENT_VERSION_HH
-#define USAGEENVIRONMENT_LIBRARY_VERSION_STRING "2010.09.25"
-#define USAGEENVIRONMENT_LIBRARY_VERSION_INT 1285372800
+#define USAGEENVIRONMENT_LIBRARY_VERSION_STRING "2011.06.16"
+#define USAGEENVIRONMENT_LIBRARY_VERSION_INT 1308182400
#endif
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/UsageEnvironment/include/strDup.hh
^
|
@@ -17,7 +17,7 @@
#ifndef _STRDUP_HH
#define _STRDUP_HH
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// A C++ equivalent to the standard C routine "strdup()".
// This generates a char* that can be deleted using "delete[]"
// Header
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/UsageEnvironment/strDup.cpp
^
|
@@ -13,7 +13,7 @@
along with this library; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// A C++ equivalent to the standard C routine "strdup()".
// This generates a char* that can be deleted using "delete[]"
// Implementation
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/WindowsAudioInputDevice/WindowsAudioInputDevice_common.hh
^
|
@@ -13,7 +13,7 @@
along with this library; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// Windows implementation of a generic audio input device
// Base class for both library versions:
// One that uses Windows' built-in software mixer; another that doesn't.
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/WindowsAudioInputDevice/WindowsAudioInputDevice_mixer.hh
^
|
@@ -13,7 +13,7 @@
along with this library; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// Windows implementation of a generic audio input device
// This version uses Windows' built-in software mixer.
// C++ header
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/WindowsAudioInputDevice/WindowsAudioInputDevice_noMixer.hh
^
|
@@ -13,7 +13,7 @@
along with this library; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// Windows implementation of a generic audio input device
// This version does not use Windows' built-in software mixer.
// C++ header
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/WindowsAudioInputDevice/showAudioInputPorts.cpp
^
|
@@ -13,7 +13,7 @@
along with this library; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
-// Copyright (c) 1996-2010, Live Networks, Inc. All rights reserved
+// Copyright (c) 1996-2011, Live Networks, Inc. All rights reserved
// A program that prints out this computer's audio input ports
#include "AudioInputDevice.hh"
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/config.iphoneos
^
|
@@ -9,7 +9,7 @@
LINK = /Developer/Platforms/iPhoneOS.platform/Developer/usr/bin/g++ -o
LINK_OPTS = -L. -arch armv7 --sysroot=/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS3.0.sdk
CONSOLE_LINK_OPTS = $(LINK_OPTS)
-LIBRARY_LINK = ar cr
+LIBRARY_LINK = libtool -s -o
LIBRARY_LINK_OPTS =
LIB_SUFFIX = a
LIBS_FOR_CONSOLE_APPLICATION =
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/config.macosx
^
|
@@ -9,7 +9,7 @@
LINK = c++ -o
LINK_OPTS = -L.
CONSOLE_LINK_OPTS = $(LINK_OPTS)
-LIBRARY_LINK = ar cr
+LIBRARY_LINK = libtool -s -o
LIBRARY_LINK_OPTS =
LIB_SUFFIX = a
LIBS_FOR_CONSOLE_APPLICATION =
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/groupsock/GroupEId.cpp
^
|
@@ -13,7 +13,7 @@
along with this library; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
-// Copyright (c) 1996-2010, Live Networks, Inc. All rights reserved
+// Copyright (c) 1996-2011, Live Networks, Inc. All rights reserved
// "Group Endpoint Id"
// Implementation
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/groupsock/Groupsock.cpp
^
|
@@ -13,7 +13,7 @@
along with this library; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// 'Group sockets'
// Implementation
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/groupsock/GroupsockHelper.cpp
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "mTunnel" multicast access service
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// Helper routines to implement 'group sockets'
// Implementation
@@ -633,12 +633,16 @@
#if !defined(_WIN32_WCE)
static char timeString[9]; // holds hh:mm:ss plus trailing '\0'
char const* ctimeResult = ctime((time_t*)&tvNow.tv_sec);
- char const* from = &ctimeResult[11];
- int i;
- for (i = 0; i < 8; ++i) {
- timeString[i] = from[i];
+ if (ctimeResult == NULL) {
+ sprintf(timeString, "??:??:??");
+ } else {
+ char const* from = &ctimeResult[11];
+ int i;
+ for (i = 0; i < 8; ++i) {
+ timeString[i] = from[i];
+ }
+ timeString[i] = '\0';
}
- timeString[i] = '\0';
#else
// WinCE apparently doesn't have "ctime()", so instead, construct
// a timestamp string just using the integer and fractional parts
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/groupsock/IOHandlers.cpp
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "mTunnel" multicast access service
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// IO event handlers
// Implementation
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/groupsock/NetAddress.cpp
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "mTunnel" multicast access service
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// Network Addresses
// Implementation
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/groupsock/NetInterface.cpp
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "mTunnel" multicast access service
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// Network Interfaces
// Implementation
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/groupsock/include/GroupEId.hh
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "multikit" Multicast Application Shell
-// Copyright (c) 1996-2010, Live Networks, Inc. All rights reserved
+// Copyright (c) 1996-2011, Live Networks, Inc. All rights reserved
// "Group Endpoint Id"
// C++ header
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/groupsock/include/Groupsock.hh
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "mTunnel" multicast access service
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// 'Group sockets'
// C++ header
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/groupsock/include/GroupsockHelper.hh
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "mTunnel" multicast access service
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// Helper routines to implement 'group sockets'
// C++ header
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/groupsock/include/IOHandlers.hh
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "mTunnel" multicast access service
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// IO event handlers
// C++ header
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/groupsock/include/NetAddress.hh
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "mTunnel" multicast access service
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// Network Addresses
// C++ header
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/groupsock/include/NetCommon.h
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
/* "groupsock" interface
- * Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+ * Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
* Common include files, typically used for networking
*/
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/groupsock/include/NetInterface.hh
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "mTunnel" multicast access service
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// Network Interfaces
// C++ header
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/groupsock/include/TunnelEncaps.hh
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "mTunnel" multicast access service
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// Encapsulation trailer for tunnels
// C++ header
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/groupsock/include/groupsock_version.hh
^
|
@@ -1,10 +1,10 @@
// Version information for the "groupsock" library
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
#ifndef _GROUPSOCK_VERSION_HH
#define _GROUPSOCK_VERSION_HH
-#define GROUPSOCK_LIBRARY_VERSION_STRING "2010.09.25"
-#define GROUPSOCK_LIBRARY_VERSION_INT 1285372800
+#define GROUPSOCK_LIBRARY_VERSION_STRING "2011.06.16"
+#define GROUPSOCK_LIBRARY_VERSION_INT 1308182400
#endif
|
[-]
[+]
|
Added |
live.2011.06.16.tar.bz2/liveMedia/AC3AudioFileServerMediaSubsession.cpp
^
|
@@ -0,0 +1,61 @@
+/**********
+This library is free software; you can redistribute it and/or modify it under
+the terms of the GNU Lesser General Public License as published by the
+Free Software Foundation; either version 2.1 of the License, or (at your
+option) any later version. (See <http://www.gnu.org/copyleft/lesser.html>.)
+
+This library 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 Lesser General Public License for
+more details.
+
+You should have received a copy of the GNU Lesser General Public License
+along with this library; if not, write to the Free Software Foundation, Inc.,
+51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+**********/
+// "liveMedia"
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
+// A 'ServerMediaSubsession' object that creates new, unicast, "RTPSink"s
+// on demand, from an AC3 audio file.
+// Implementation
+
+#include "AC3AudioFileServerMediaSubsession.hh"
+#include "ByteStreamFileSource.hh"
+#include "AC3AudioStreamFramer.hh"
+#include "AC3AudioRTPSink.hh"
+
+AC3AudioFileServerMediaSubsession*
+AC3AudioFileServerMediaSubsession::createNew(UsageEnvironment& env,
+ char const* fileName,
+ Boolean reuseFirstSource) {
+ return new AC3AudioFileServerMediaSubsession(env, fileName, reuseFirstSource);
+}
+
+AC3AudioFileServerMediaSubsession
+::AC3AudioFileServerMediaSubsession(UsageEnvironment& env,
+ char const* fileName, Boolean reuseFirstSource)
+ : FileServerMediaSubsession(env, fileName, reuseFirstSource) {
+}
+
+AC3AudioFileServerMediaSubsession::~AC3AudioFileServerMediaSubsession() {
+}
+
+FramedSource* AC3AudioFileServerMediaSubsession
+::createNewStreamSource(unsigned /*clientSessionId*/, unsigned& estBitrate) {
+ estBitrate = 48; // kbps, estimate
+
+ ByteStreamFileSource* fileSource = ByteStreamFileSource::createNew(envir(), fFileName);
+ if (fileSource == NULL) return NULL;
+
+ return AC3AudioStreamFramer::createNew(envir(), fileSource);
+}
+
+RTPSink* AC3AudioFileServerMediaSubsession
+::createNewRTPSink(Groupsock* rtpGroupsock,
+ unsigned char rtpPayloadTypeIfDynamic,
+ FramedSource* inputSource) {
+ AC3AudioStreamFramer* audioSource = (AC3AudioStreamFramer*)inputSource;
+ return AC3AudioRTPSink::createNew(envir(), rtpGroupsock,
+ rtpPayloadTypeIfDynamic,
+ audioSource->samplingRate());
+}
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/AC3AudioRTPSink.cpp
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// RTP sink for AC3 audio
// Implementation
@@ -24,7 +24,8 @@
u_int8_t rtpPayloadFormat,
u_int32_t rtpTimestampFrequency)
: AudioRTPSink(env, RTPgs, rtpPayloadFormat,
- rtpTimestampFrequency, "AC3") {
+ rtpTimestampFrequency, "AC3"),
+ fTotNumFragmentsUsed(0) {
}
AC3AudioRTPSink::~AC3AudioRTPSink() {
@@ -51,21 +52,29 @@
unsigned numBytesInFrame,
struct timeval frameTimestamp,
unsigned numRemainingBytes) {
- // Update the "NDU" header.
- // Also set the "Data Unit Header" for the frame, because we
- // have already allotted space for this, by virtue of the fact that
- // (for now) we pack only one frame in each RTP packet:
+ // Set the 2-byte "payload header", as defined in RFC 4184.
unsigned char headers[2];
- headers[0] = numFramesUsedSoFar() + 1;
Boolean isFragment = numRemainingBytes > 0 || fragmentationOffset > 0;
- unsigned const totalFrameSize
- = fragmentationOffset + numBytesInFrame + numRemainingBytes;
- unsigned const fiveEighthsPoint = totalFrameSize/2 + totalFrameSize/8;
- Boolean haveFiveEighths
- = fragmentationOffset == 0 && numBytesInFrame >= fiveEighthsPoint;
- headers[1] = (isFragment<<5)|(haveFiveEighths<<4); // F|B
- // Note: TYP==0, RDT==0 ???, T==0 ???
+ if (!isFragment) {
+ headers[0] = 0; // One or more complete frames
+ headers[1] = 1; // because we (for now) allow at most 1 frame per packet
+ } else {
+ if (fragmentationOffset > 0) {
+ headers[0] = 3; // Fragment of frame other than initial fragment
+ } else {
+ // An initial fragment of the frame
+ unsigned const totalFrameSize = fragmentationOffset + numBytesInFrame + numRemainingBytes;
+ unsigned const fiveEighthsPoint = totalFrameSize/2 + totalFrameSize/8;
+ headers[0] = numBytesInFrame >= fiveEighthsPoint ? 1 : 2;
+
+ // Because this outgoing packet will be full (because it's an initial fragment), we can compute how many total
+ // fragments (and thus packets) will make up the complete AC-3 frame:
+ fTotNumFragmentsUsed = (totalFrameSize + (numBytesInFrame-1))/numBytesInFrame;
+ }
+
+ headers[1] = fTotNumFragmentsUsed;
+ }
setSpecialHeaderBytes(headers, sizeof headers);
@@ -84,9 +93,5 @@
}
unsigned AC3AudioRTPSink::specialHeaderSize() const {
- // There's a 1 byte "NDU" header.
- // There's also a 1-byte "Data Unit Header" preceding each frame in
- // the RTP packet, but since we (for now) pack only one frame in
- // each RTP packet, we also count this here:
- return 1 + 1;
+ return 2;
}
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/AC3AudioRTPSource.cpp
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// AC3 Audio RTP Sources
// Implementation
@@ -46,30 +46,17 @@
unsigned char* headerStart = packet->data();
unsigned packetSize = packet->dataSize();
- // There's a 1-byte "NDU" header, containing the number of frames
- // present in this RTP packet.
+ // There's a 2-byte payload header at the beginning:
if (packetSize < 2) return False;
- unsigned char numFrames = headerStart[0];
- if (numFrames == 0) return False;
-
- // TEMP: We can't currently handle packets containing > 1 frame #####
- if (numFrames > 1) {
- envir() << "AC3AudioRTPSource::processSpecialHeader(): packet contains "
- << numFrames << " frames (we can't handle this!)\n";
- return False;
- }
-
- // We current can't handle packets that consist only of redundant data:
- unsigned char typ_field = headerStart[1] >> 6;
- if (typ_field >= 2) return False;
+ resultSpecialHeaderSize = 2;
- fCurrentPacketBeginsFrame = fCurrentPacketCompletesFrame;
- // whether the *previous* packet ended a frame
+ unsigned char FT = headerStart[0]&0x03;
+ fCurrentPacketBeginsFrame = FT != 3;
- // The RTP "M" (marker) bit indicates the last fragment of a frame:
- fCurrentPacketCompletesFrame = packet->rtpMarkerBit();
+ // The RTP "M" (marker) bit indicates the last fragment of a frame.
+ // In case the sender did not set the "M" bit correctly, we also test for FT == 0:
+ fCurrentPacketCompletesFrame = packet->rtpMarkerBit() || FT == 0;
- resultSpecialHeaderSize = 2;
return True;
}
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/AC3AudioStreamFramer.cpp
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// A filter that breaks up an AC3 audio elementary stream into frames
// Implementation
@@ -44,9 +44,8 @@
virtual ~AC3AudioStreamParser();
public:
- Boolean testStreamCode(unsigned char ourStreamCode,
- unsigned char* ptr, unsigned size);
- // returns True iff the initial stream code is ours
+ void testStreamCode(unsigned char ourStreamCode,
+ unsigned char* ptr, unsigned size);
unsigned parseFrame(unsigned& numTruncatedBytes);
// returns the size of the frame that was acquired, or 0 if none was
@@ -151,13 +150,8 @@
void AC3AudioStreamFramer
::handleNewData(unsigned char* ptr, unsigned size) {
- if (!fParser->testStreamCode(fOurStreamCode, ptr, size)) {
- // This block of data is not for us; try again:
- parseNextFrame();
- return;
- }
+ fParser->testStreamCode(fOurStreamCode, ptr, size);
- // Now that we know that this data is for us, get the next frame:
parseNextFrame();
}
@@ -238,23 +232,21 @@
fMaxSize = maxSize;
}
-Boolean AC3AudioStreamParser
+void AC3AudioStreamParser
::testStreamCode(unsigned char ourStreamCode,
unsigned char* ptr, unsigned size) {
- if (size < 4) return False; // shouldn't happen
+ if (ourStreamCode == 0) return; // we assume that there's no stream code at the beginning of the data
+
+ if (size < 4) return; // shouldn't happen
unsigned char streamCode = *ptr;
if (streamCode == ourStreamCode) {
// Remove the first 4 bytes from the stream:
memmove(ptr, ptr + 4, size - 4);
totNumValidBytes() = totNumValidBytes() - 4;
-
- return True;
} else {
// Discard all of the data that was just read:
totNumValidBytes() = totNumValidBytes() - size;
-
- return False;
}
}
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/ADTSAudioFileServerMediaSubsession.cpp
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// A 'ServerMediaSubsession' object that creates new, unicast, "RTPSink"s
// on demand, from an AAC audio file in ADTS format
// Implementation
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/ADTSAudioFileSource.cpp
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// A source object for AAC audio files in ADTS format
// Implementation
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/AMRAudioFileServerMediaSubsession.cpp
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// A 'ServerMediaSubsession' object that creates new, unicast, "RTPSink"s
// on demand, from an AMR audio file.
// Implementation
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/AMRAudioFileSink.cpp
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// AMR Audio File sinks
// Implementation
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/AMRAudioFileSource.cpp
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// A source object for AMR audio files (as defined in RFC 3267, section 5)
// Implementation
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/AMRAudioRTPSink.cpp
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// RTP sink for AMR audio (RFC 3267)
// Implementation
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/AMRAudioRTPSource.cpp
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// AMR Audio RTP Sources (RFC 3267)
// Implementation
@@ -101,7 +101,6 @@
RawAMRRTPSource* fInputSource;
class AMRDeinterleavingBuffer* fDeinterleavingBuffer;
Boolean fNeedAFrame;
-
};
@@ -480,6 +479,7 @@
}
void AMRDeinterleaver::doStopGettingFrames() {
+ fNeedAFrame = False;
fInputSource->stopGettingFrames();
}
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/AMRAudioSource.cpp
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// A source object for AMR audio sources
// Implementation
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/AVIFileSink.cpp
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// A sink that generates an AVI file from a composite media session
// Implementation
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/AudioRTPSink.cpp
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// A generic RTP sink for audio codecs (abstract base class)
// Implementation
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/Base64.cpp
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// Base64 encoding and decoding
// implementation
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/BasicUDPSink.cpp
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// A simple UDP sink (i.e., without RTP or other headers added); one frame per packet
// Implementation
@@ -82,8 +82,11 @@
struct timeval timeNow;
gettimeofday(&timeNow, NULL);
- int64_t uSecondsToGo;
- uSecondsToGo = (fNextSendTime.tv_sec - timeNow.tv_sec)*1000000 + (fNextSendTime.tv_usec - timeNow.tv_usec);
+ int secsDiff = fNextSendTime.tv_sec - timeNow.tv_sec;
+ int64_t uSecondsToGo = secsDiff*1000000 + (fNextSendTime.tv_usec - timeNow.tv_usec);
+ if (uSecondsToGo < 0 || secsDiff < 0) { // sanity check: Make sure that the time-to-delay is non-negative:
+ uSecondsToGo = 0;
+ }
// Delay this amount of time:
nextTask() = envir().taskScheduler().scheduleDelayedTask(uSecondsToGo,
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/BasicUDPSource.cpp
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// A simple UDP source, where every UDP payload is a complete frame
// Implementation
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/BitVector.cpp
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// Bit Vector data structure
// Implementation
@@ -41,6 +41,8 @@
#define MAX_LENGTH 32
void BitVector::putBits(unsigned from, unsigned numBits) {
+ if (numBits == 0) return;
+
unsigned char tmpBuf[4];
unsigned overflowingBits = 0;
@@ -63,7 +65,6 @@
fCurBitIndex += numBits - overflowingBits;
}
-
void BitVector::put1Bit(unsigned bit) {
// The following is equivalent to "putBits(..., 1)", except faster:
if (fCurBitIndex >= fTotNumBits) { /* overflow */
@@ -79,8 +80,9 @@
}
}
-
unsigned BitVector::getBits(unsigned numBits) {
+ if (numBits == 0) return 0;
+
unsigned char tmpBuf[4];
unsigned overflowingBits = 0;
@@ -125,10 +127,24 @@
}
}
+unsigned BitVector::get_expGolomb() {
+ unsigned numLeadingZeroBits = 0;
+ unsigned codeStart = 1;
+
+ while (get1Bit() == 0 && fCurBitIndex < fTotNumBits) {
+ ++numLeadingZeroBits;
+ codeStart *= 2;
+ }
+
+ return codeStart -1 + getBits(numLeadingZeroBits);
+}
+
void shiftBits(unsigned char* toBasePtr, unsigned toBitOffset,
unsigned char const* fromBasePtr, unsigned fromBitOffset,
unsigned numBits) {
+ if (numBits == 0) return;
+
/* Note that from and to may overlap, if from>to */
unsigned char const* fromBytePtr = fromBasePtr + fromBitOffset/8;
unsigned fromBitRem = fromBitOffset%8;
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/BitVector.hh
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// Bit Vector data structure
// C++ header
@@ -43,6 +43,9 @@
unsigned totNumBits() const { return fTotNumBits; }
unsigned numBitsRemaining() const { return fTotNumBits - fCurBitIndex; }
+ unsigned get_expGolomb();
+ // Returns the value of the next bits, assuming that they were encoded using an exponential-Golomb code of order 0
+
private:
unsigned char* fBaseBytePtr;
unsigned fBaseBitOffset;
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/ByteStreamFileSource.cpp
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// A file source that is a plain byte stream (rather than frames)
// Implementation
@@ -69,8 +69,11 @@
return newSource;
}
-void ByteStreamFileSource::seekToByteAbsolute(u_int64_t byteNumber) {
+void ByteStreamFileSource::seekToByteAbsolute(u_int64_t byteNumber, u_int64_t numBytesToStream) {
SeekFile64(fFid, (int64_t)byteNumber, SEEK_SET);
+
+ fNumBytesToStream = numBytesToStream;
+ fLimitNumBytesToStream = fNumBytesToStream > 0;
}
void ByteStreamFileSource::seekToByteRelative(int64_t offset) {
@@ -83,7 +86,11 @@
unsigned playTimePerFrame)
: FramedFileSource(env, fid), fPreferredFrameSize(preferredFrameSize),
fPlayTimePerFrame(playTimePerFrame), fLastPlayTime(0), fFileSize(0),
- fDeleteFidOnClose(deleteFidOnClose), fHaveStartedReading(False) {
+ fDeleteFidOnClose(deleteFidOnClose), fHaveStartedReading(False),
+ fLimitNumBytesToStream(False), fNumBytesToStream(0) {
+#ifndef READ_FROM_FILES_SYNCHRONOUSLY
+ makeSocketNonBlocking(fileno(fFid));
+#endif
}
ByteStreamFileSource::~ByteStreamFileSource() {
@@ -97,7 +104,7 @@
}
void ByteStreamFileSource::doGetNextFrame() {
- if (feof(fFid) || ferror(fFid)) {
+ if (feof(fFid) || ferror(fFid) || (fLimitNumBytesToStream && fNumBytesToStream == 0)) {
handleClosure(this);
return;
}
@@ -130,16 +137,23 @@
}
void ByteStreamFileSource::doReadFromFile() {
- // Try to read as many bytes as will fit in the buffer provided
- // (or "fPreferredFrameSize" if less)
+ // Try to read as many bytes as will fit in the buffer provided (or "fPreferredFrameSize" if less)
+ if (fLimitNumBytesToStream && fNumBytesToStream < (u_int64_t)fMaxSize) {
+ fMaxSize = (unsigned)fNumBytesToStream;
+ }
if (fPreferredFrameSize > 0 && fPreferredFrameSize < fMaxSize) {
fMaxSize = fPreferredFrameSize;
}
+#ifdef READ_FROM_FILES_SYNCHRONOUSLY
fFrameSize = fread(fTo, 1, fMaxSize, fFid);
+#else
+ fFrameSize = read(fileno(fFid), fTo, fMaxSize);
+#endif
if (fFrameSize == 0) {
handleClosure(this);
return;
}
+ fNumBytesToStream -= fFrameSize;
// Set the 'presentation time':
if (fPlayTimePerFrame > 0 && fPreferredFrameSize > 0) {
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/ByteStreamMultiFileSource.cpp
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// A source that consists of multiple byte-stream files, read sequentially
// Implementation
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/DVVideoFileServerMediaSubsession.cpp
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// A 'ServerMediaSubsession' object that creates new, unicast, "RTPSink"s
// on demand, from a DV video file.
// Implementation
@@ -75,7 +75,7 @@
return fFileDuration;
}
-void DVVideoFileServerMediaSubsession::seekStreamSource(FramedSource* inputSource, double seekNPT) {
+void DVVideoFileServerMediaSubsession::seekStreamSource(FramedSource* inputSource, double seekNPT, double streamDuration) {
// First, get the file source from "inputSource" (a framer):
DVVideoStreamFramer* framer = (DVVideoStreamFramer*)inputSource;
ByteStreamFileSource* fileSource = (ByteStreamFileSource*)(framer->inputSource());
@@ -83,6 +83,7 @@
// Then figure out where to seek to within the file:
if (fFileDuration > 0.0) {
u_int64_t seekByteNumber = (u_int64_t)(((int64_t)fFileSize*seekNPT)/fFileDuration);
- fileSource->seekToByteAbsolute(seekByteNumber);
+ u_int64_t numBytesToStream = (u_int64_t)(((int64_t)fFileSize*streamDuration)/fFileDuration);
+ fileSource->seekToByteAbsolute(seekByteNumber, numBytesToStream);
}
}
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/DVVideoRTPSink.cpp
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// RTP sink for DV video (RFC 3189)
// (Thanks to Ben Hutchings for prototyping this.)
// Implementation
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/DVVideoRTPSource.cpp
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// DV Video RTP Sources
// Implementation
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/DVVideoStreamFramer.cpp
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// A filter that parses a DV input stream into DV frames to deliver to the downstream object
// Implementation
// (Thanks to Ben Hutchings for his help, including a prototype implementation.)
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/DarwinInjector.cpp
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// An object that redirects one or more RTP/RTCP streams - forming a single
// multimedia session - into a 'Darwin Streaming Server' (for subsequent
// reflection to potentially arbitrarily many remote RTSP clients).
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/DeviceSource.cpp
^
|
@@ -14,11 +14,15 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// A template for a MediaSource encapsulating an audio/video input device
+//
+// NOTE: Sections of this code labeled "%%% TO BE WRITTEN %%%" are incomplete, and need to be written by the programmer
+// (depending on the features of the particular device).
// Implementation
#include "DeviceSource.hh"
+#include <GroupsockHelper.hh> // for "gettimeofday()"
DeviceSource*
DeviceSource::createNew(UsageEnvironment& env,
@@ -26,39 +30,76 @@
return new DeviceSource(env, params);
}
+EventTriggerId DeviceSource::eventTriggerId = 0;
+
+unsigned DeviceSource::referenceCount = 0;
+
DeviceSource::DeviceSource(UsageEnvironment& env,
DeviceParameters params)
: FramedSource(env), fParams(params) {
- // Any initialization of the device would be done here
+ if (referenceCount == 0) {
+ // Any global initialization of the device would be done here:
+ //%%% TO BE WRITTEN %%%
+ }
+ ++referenceCount;
+
+ // Any instance-specific initialization of the device would be done here:
+ //%%% TO BE WRITTEN %%%
+
+ // We arrange here for our "deliverFrame" member function to be called
+ // whenever the next frame of data becomes available from the device.
+ //
+ // If the device can be accessed as a readable socket, then one easy way to do this is using a call to
+ // envir().taskScheduler().turnOnBackgroundReadHandling( ... )
+ // (See examples of this call in the "liveMedia" directory.)
+ //
+ // If, however, the device *cannot* be accessed as a readable socket, then instead we can implement it using 'event triggers':
+ // Create an 'event trigger' for this device (if it hasn't already been done):
+ if (eventTriggerId == 0) {
+ eventTriggerId = envir().taskScheduler().createEventTrigger(deliverFrame0);
+ }
}
DeviceSource::~DeviceSource() {
+ // Any instance-specific 'destruction' (i.e., resetting) of the device would be done here:
+ //%%% TO BE WRITTEN %%%
+
+ --referenceCount;
+ if (referenceCount == 0) {
+ // Any global 'destruction' (i.e., resetting) of the device would be done here:
+ //%%% TO BE WRITTEN %%%
+
+ // Reclaim our 'event trigger'
+ envir().taskScheduler().deleteEventTrigger(eventTriggerId);
+ eventTriggerId = 0;
+ }
}
void DeviceSource::doGetNextFrame() {
- // Arrange here for our "deliverFrame" member function to be called
- // when the next frame of data becomes available from the device.
- // This must be done in a non-blocking fashion - i.e., so that we
- // return immediately from this function even if no data is
- // currently available.
- //
- // If the device can be implemented as a readable socket, then one easy
- // way to do this is using a call to
- // envir().taskScheduler().turnOnBackgroundReadHandling( ... )
- // (See examples of this call in the "liveMedia" directory.)
+ // This function is called (by our 'downstream' object) when it asks for new data.
- // If, for some reason, the source device stops being readable
- // (e.g., it gets closed), then you do the following:
- if (0 /* the source stops being readable */) {
+ // Note: If, for some reason, the source device stops being readable (e.g., it gets closed), then you do the following:
+ if (0 /* the source stops being readable */ /*%%% TO BE WRITTEN %%%*/) {
handleClosure(this);
return;
}
+
+ // If a new frame of data is immediately available to be delivered, then do this now:
+ if (0 /* a new frame of data is immediately available to be delivered*/ /*%%% TO BE WRITTEN %%%*/) {
+ deliverFrame();
+ }
+
+ // No new data is immediately available to be delivered. We don't do anything more here.
+ // Instead, our event trigger must be called (e.g., from a separate thread) when new data becomes available.
+}
+
+void DeviceSource::deliverFrame0(void* clientData) {
+ ((DeviceSource*)clientData)->deliverFrame();
}
void DeviceSource::deliverFrame() {
- // This would be called when new frame data is available from the device.
- // This function should deliver the next frame of data from the device,
- // using the following parameters (class members):
+ // This function is called when new frame data is available from the device.
+ // We deliver this data by copying it to the 'downstream' object, using the following parameters (class members):
// 'in' parameters (these should *not* be modified by this function):
// fTo: The frame data is copied to this address.
// (Note that the variable "fTo" is *not* modified. Instead,
@@ -72,12 +113,41 @@
// bigger than "fMaxSize", in which case it's set to the number of bytes
// that have been omitted.
// fPresentationTime: Should be set to the frame's presentation time
- // (seconds, microseconds).
+ // (seconds, microseconds). This time must be aligned with 'wall-clock time' - i.e., the time that you would get
+ // by calling "gettimeofday()".
// fDurationInMicroseconds: Should be set to the frame's duration, if known.
+ // If, however, the device is a 'live source' (e.g., encoded from a camera or microphone), then we probably don't need
+ // to set this variable, because - in this case - data will never arrive 'early'.
+ // Note the code below.
+
if (!isCurrentlyAwaitingData()) return; // we're not ready for the data yet
+ u_int8_t* newFrameDataStart = (u_int8_t*)0xDEADBEEF; //%%% TO BE WRITTEN %%%
+ unsigned newFrameSize = 0; //%%% TO BE WRITTEN %%%
+
// Deliver the data here:
+ if (newFrameSize > fMaxSize) {
+ fFrameSize = fMaxSize;
+ fNumTruncatedBytes = newFrameSize - fMaxSize;
+ } else {
+ fFrameSize = newFrameSize;
+ }
+ gettimeofday(&fPresentationTime, NULL); // If you have a more accurate time - e.g., from an encoder - then use that instead.
+ // If the device is *not* a 'live source' (e.g., it comes instead from a file or buffer), then set "fDurationInMicroseconds" here.
+ memmove(fTo, newFrameDataStart, fFrameSize);
// After delivering the data, inform the reader that it is now available:
FramedSource::afterGetting(this);
}
+
+
+// The following code would be called to signal that a new frame of data has become available.
+// This (unlike other "LIVE555 Streaming Media" library code) may be called from a separate thread.
+void signalNewFrameData() {
+ TaskScheduler* ourScheduler = NULL; //%%% TO BE WRITTEN %%%
+ DeviceSource* ourDevice = NULL; //%%% TO BE WRITTEN %%%
+
+ if (ourScheduler != NULL) { // sanity check
+ ourScheduler->triggerEvent(DeviceSource::eventTriggerId, ourDevice);
+ }
+}
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/DigestAuthentication.cpp
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// A class used for digest authentication.
// Implementation
@@ -30,13 +30,12 @@
assign(NULL, NULL, NULL, NULL, False);
}
-Authenticator::Authenticator(char const* username, char const* password) {
- setUsernameAndPassword(username, password);
+Authenticator::Authenticator(char const* username, char const* password, Boolean passwordIsMD5) {
+ assign(NULL, NULL, username, password, passwordIsMD5);
}
Authenticator::Authenticator(const Authenticator& orig) {
- assign(orig.realm(), orig.nonce(), orig.username(), orig.password(),
- orig.fPasswordIsMD5);
+ assign(orig.realm(), orig.nonce(), orig.username(), orig.password(), orig.fPasswordIsMD5);
}
Authenticator& Authenticator::operator=(const Authenticator& rightSide) {
@@ -145,17 +144,14 @@
fNonce = strDup(nonce);
}
-void Authenticator
-::assignUsernameAndPassword(char const* username, char const* password,
- Boolean passwordIsMD5) {
+void Authenticator::assignUsernameAndPassword(char const* username, char const* password, Boolean passwordIsMD5) {
fUsername = strDup(username);
fPassword = strDup(password);
fPasswordIsMD5 = passwordIsMD5;
}
void Authenticator::assign(char const* realm, char const* nonce,
- char const* username, char const* password,
- Boolean passwordIsMD5) {
+ char const* username, char const* password, Boolean passwordIsMD5) {
assignRealmAndNonce(realm, nonce);
assignUsernameAndPassword(username, password, passwordIsMD5);
}
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/FileServerMediaSubsession.cpp
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// A 'ServerMediaSubsession' object that creates new, unicast, "RTPSink"s
// on demand, from a file.
// Implementation
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/FileSink.cpp
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// File sinks
// Implementation
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/FramedFileSource.cpp
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// Framed File Sources
// Implementation
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/FramedFilter.cpp
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// Framed Filters
// Implementation
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/FramedSource.cpp
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// Framed Sources
// Implementation
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/GSMAudioRTPSink.cpp
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// RTP sink for GSM audio
// Implementation
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/H261VideoRTPSource.cpp
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// H.261 Video RTP Sources
// Implementation
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/H263plusVideoFileServerMediaSubsession.cpp
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// A 'ServerMediaSubsession' object that creates new, unicast, "RTPSink"s
// on demand, from a H263 video file.
// Implementation
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/H263plusVideoRTPSink.cpp
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// RTP sink for H.263+ video (RFC 4629)
// Implementation
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/H263plusVideoRTPSource.cpp
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// H.263+ Video RTP Sources
// Implementation
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/H263plusVideoStreamFramer.cpp
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// Author Bernhard Feiten
// A filter that breaks up an H.263plus video stream into frames.
//
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/H263plusVideoStreamParser.cpp
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// Author Bernhard Feiten
// A filter that breaks up an H.263plus video stream into frames.
// Based on MPEG4IP/mp4creator/h263.c
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/H263plusVideoStreamParser.hh
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// A filter that breaks up an H263 video stream into frames.
// derived from MPEG4IP h263.c
// Author Benhard Feiten
|
[-]
[+]
|
Added |
live.2011.06.16.tar.bz2/liveMedia/H264VideoFileServerMediaSubsession.cpp
^
|
@@ -0,0 +1,117 @@
+/**********
+This library is free software; you can redistribute it and/or modify it under
+the terms of the GNU Lesser General Public License as published by the
+Free Software Foundation; either version 2.1 of the License, or (at your
+option) any later version. (See <http://www.gnu.org/copyleft/lesser.html>.)
+
+This library 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 Lesser General Public License for
+more details.
+
+You should have received a copy of the GNU Lesser General Public License
+along with this library; if not, write to the Free Software Foundation, Inc.,
+51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+**********/
+// "liveMedia"
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
+// A 'ServerMediaSubsession' object that creates new, unicast, "RTPSink"s
+// on demand, from a H264 video file.
+// Implementation
+
+#include "H264VideoFileServerMediaSubsession.hh"
+#include "H264VideoRTPSink.hh"
+#include "ByteStreamFileSource.hh"
+#include "H264VideoStreamFramer.hh"
+
+H264VideoFileServerMediaSubsession*
+H264VideoFileServerMediaSubsession::createNew(UsageEnvironment& env,
+ char const* fileName,
+ Boolean reuseFirstSource) {
+ return new H264VideoFileServerMediaSubsession(env, fileName, reuseFirstSource);
+}
+
+H264VideoFileServerMediaSubsession::H264VideoFileServerMediaSubsession(UsageEnvironment& env,
+ char const* fileName, Boolean reuseFirstSource)
+ : FileServerMediaSubsession(env, fileName, reuseFirstSource),
+ fAuxSDPLine(NULL), fDoneFlag(0), fDummyRTPSink(NULL) {
+}
+
+H264VideoFileServerMediaSubsession::~H264VideoFileServerMediaSubsession() {
+ delete[] fAuxSDPLine;
+}
+
+static void afterPlayingDummy(void* clientData) {
+ H264VideoFileServerMediaSubsession* subsess = (H264VideoFileServerMediaSubsession*)clientData;
+ subsess->afterPlayingDummy1();
+}
+
+void H264VideoFileServerMediaSubsession::afterPlayingDummy1() {
+ // Unschedule any pending 'checking' task:
+ envir().taskScheduler().unscheduleDelayedTask(nextTask());
+ // Signal the event loop that we're done:
+ setDoneFlag();
+}
+
+static void checkForAuxSDPLine(void* clientData) {
+ H264VideoFileServerMediaSubsession* subsess = (H264VideoFileServerMediaSubsession*)clientData;
+ subsess->checkForAuxSDPLine1();
+}
+
+void H264VideoFileServerMediaSubsession::checkForAuxSDPLine1() {
+ if (fAuxSDPLine != NULL) {
+ // Signal the event loop that we're done:
+ setDoneFlag();
+ } else if (fDummyRTPSink != NULL && fDummyRTPSink->auxSDPLine() != NULL) {
+ fAuxSDPLine = strDup(fDummyRTPSink->auxSDPLine());
+ fDummyRTPSink = NULL;
+
+ // Signal the event loop that we're done:
+ setDoneFlag();
+ } else {
+ // try again after a brief delay:
+ int uSecsToDelay = 100000; // 100 ms
+ nextTask() = envir().taskScheduler().scheduleDelayedTask(uSecsToDelay,
+ (TaskFunc*)checkForAuxSDPLine, this);
+ }
+}
+
+char const* H264VideoFileServerMediaSubsession::getAuxSDPLine(RTPSink* rtpSink, FramedSource* inputSource) {
+ if (fAuxSDPLine != NULL) return fAuxSDPLine; // it's already been set up (for a previous client)
+
+ if (fDummyRTPSink == NULL) { // we're not already setting it up for another, concurrent stream
+ // Note: For H264 video files, the 'config' information ("profile-level-id" and "sprop-parameter-sets") isn't known
+ // until we start reading the file. This means that "rtpSink"s "auxSDPLine()" will be NULL initially,
+ // and we need to start reading data from our file until this changes.
+ fDummyRTPSink = rtpSink;
+
+ // Start reading the file:
+ fDummyRTPSink->startPlaying(*inputSource, afterPlayingDummy, this);
+
+ // Check whether the sink's 'auxSDPLine()' is ready:
+ checkForAuxSDPLine(this);
+ }
+
+ envir().taskScheduler().doEventLoop(&fDoneFlag);
+
+ return fAuxSDPLine;
+}
+
+FramedSource* H264VideoFileServerMediaSubsession::createNewStreamSource(unsigned /*clientSessionId*/, unsigned& estBitrate) {
+ estBitrate = 500; // kbps, estimate
+
+ // Create the video source:
+ ByteStreamFileSource* fileSource = ByteStreamFileSource::createNew(envir(), fFileName);
+ if (fileSource == NULL) return NULL;
+ fFileSize = fileSource->fileSize();
+
+ // Create a framer for the Video Elementary Stream:
+ return H264VideoStreamFramer::createNew(envir(), fileSource);
+}
+
+RTPSink* H264VideoFileServerMediaSubsession
+::createNewRTPSink(Groupsock* rtpGroupsock,
+ unsigned char rtpPayloadTypeIfDynamic,
+ FramedSource* /*inputSource*/) {
+ return H264VideoRTPSink::createNew(envir(), rtpGroupsock, rtpPayloadTypeIfDynamic);
+}
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/H264VideoFileSink.cpp
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// H.264 Video File sinks
// Implementation
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/H264VideoRTPSink.cpp
^
|
@@ -14,38 +14,21 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// RTP sink for H.264 video (RFC 3984)
// Implementation
#include "H264VideoRTPSink.hh"
#include "H264VideoStreamFramer.hh"
+#include "Base64.hh"
////////// H264VideoRTPSink implementation //////////
H264VideoRTPSink
::H264VideoRTPSink(UsageEnvironment& env, Groupsock* RTPgs,
- unsigned char rtpPayloadFormat,
- unsigned profile_level_id,
- char const* sprop_parameter_sets_str)
+ unsigned char rtpPayloadFormat)
: VideoRTPSink(env, RTPgs, rtpPayloadFormat, 90000, "H264"),
- fOurFragmenter(NULL) {
- // Set up the "a=fmtp:" SDP line for this stream:
- char const* fmtpFmt =
- "a=fmtp:%d packetization-mode=1"
- ";profile-level-id=%06X"
- ";sprop-parameter-sets=%s\r\n";
- unsigned fmtpFmtSize = strlen(fmtpFmt)
- + 3 /* max char len */
- + 8 /* max unsigned len in hex */
- + strlen(sprop_parameter_sets_str);
- char* fmtp = new char[fmtpFmtSize];
- sprintf(fmtp, fmtpFmt,
- rtpPayloadFormat,
- profile_level_id,
- sprop_parameter_sets_str);
- fFmtpSDPLine = strDup(fmtp);
- delete[] fmtp;
+ fOurFragmenter(NULL), fFmtpSDPLine(NULL) {
}
H264VideoRTPSink::~H264VideoRTPSink() {
@@ -56,11 +39,8 @@
H264VideoRTPSink*
H264VideoRTPSink::createNew(UsageEnvironment& env, Groupsock* RTPgs,
- unsigned char rtpPayloadFormat,
- unsigned profile_level_id,
- char const* sprop_parameter_sets_str) {
- return new H264VideoRTPSink(env, RTPgs, rtpPayloadFormat,
- profile_level_id, sprop_parameter_sets_str);
+ unsigned char rtpPayloadFormat) {
+ return new H264VideoRTPSink(env, RTPgs, rtpPayloadFormat);
}
Boolean H264VideoRTPSink::sourceIsCompatibleWithUs(MediaSource& source) {
@@ -97,16 +77,16 @@
struct timeval frameTimestamp,
unsigned /*numRemainingBytes*/) {
// Set the RTP 'M' (marker) bit iff
- // 1/ The most recently delivered fragment was the end of
- // (or the only fragment of) an NAL unit, and
+ // 1/ The most recently delivered fragment was the end of (or the only fragment of) an NAL unit, and
// 2/ This NAL unit was the last NAL unit of an 'access unit' (i.e. video frame).
if (fOurFragmenter != NULL) {
H264VideoStreamFramer* framerSource
= (H264VideoStreamFramer*)(fOurFragmenter->inputSource());
- // This relies on our fragmenter's source being a "MPEG4VideoStreamFramer".
+ // This relies on our fragmenter's source being a "H264VideoStreamFramer".
if (fOurFragmenter->lastFragmentCompletedNALUnit()
- && framerSource != NULL && framerSource->currentNALUnitEndsAccessUnit()) {
+ && framerSource != NULL && framerSource->pictureEndMarker()) {
setMarkerBit();
+ framerSource->pictureEndMarker() = False;
}
}
@@ -120,6 +100,45 @@
}
char const* H264VideoRTPSink::auxSDPLine() {
+ // Generate a new "a=fmtp:" line each time, using parameters from
+ // our framer source (in case they've changed since the last time that
+ // we were called):
+ if (fOurFragmenter == NULL) return NULL; // we don't yet have a fragmenter (and therefore not a source)
+ H264VideoStreamFramer* framerSource = (H264VideoStreamFramer*)(fOurFragmenter->inputSource());
+ if (framerSource == NULL) return NULL; // we don't yet have a source
+
+ u_int8_t* sps; unsigned spsSize;
+ u_int8_t* pps; unsigned ppsSize;
+ framerSource->getSPSandPPS(sps, spsSize, pps, ppsSize);
+ if (sps == NULL || pps == NULL) return NULL; // our source isn't ready
+
+ u_int32_t profile_level_id;
+ if (spsSize < 4) { // sanity check
+ profile_level_id = 0;
+ } else {
+ profile_level_id = (sps[1]<<16)|(sps[2]<<8)|sps[3]; // profile_idc|constraint_setN_flag|level_idc
+ }
+
+ // Set up the "a=fmtp:" SDP line for this stream:
+ char* sps_base64 = base64Encode((char*)sps, spsSize);
+ char* pps_base64 = base64Encode((char*)pps, ppsSize);
+ char const* fmtpFmt =
+ "a=fmtp:%d packetization-mode=1"
+ ";profile-level-id=%06X"
+ ";sprop-parameter-sets=%s,%s\r\n";
+ unsigned fmtpFmtSize = strlen(fmtpFmt)
+ + 3 /* max char len */
+ + 6 /* 3 bytes in hex */
+ + strlen(sps_base64) + strlen(pps_base64);
+ char* fmtp = new char[fmtpFmtSize];
+ sprintf(fmtp, fmtpFmt,
+ rtpPayloadType(),
+ profile_level_id,
+ sps_base64, pps_base64);
+ delete[] sps_base64;
+ delete[] pps_base64;
+
+ delete[] fFmtpSDPLine; fFmtpSDPLine = fmtp;
return fFmtpSDPLine;
}
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/H264VideoRTPSource.cpp
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// H.264 Video RTP Sources
// Implementation
|
[-]
[+]
|
Added |
live.2011.06.16.tar.bz2/liveMedia/H264VideoStreamDiscreteFramer.cpp
^
|
@@ -0,0 +1,87 @@
+/**********
+This library is free software; you can redistribute it and/or modify it under
+the terms of the GNU Lesser General Public License as published by the
+Free Software Foundation; either version 2.1 of the License, or (at your
+option) any later version. (See <http://www.gnu.org/copyleft/lesser.html>.)
+
+This library 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 Lesser General Public License for
+more details.
+
+You should have received a copy of the GNU Lesser General Public License
+along with this library; if not, write to the Free Software Foundation, Inc.,
+51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+**********/
+// "liveMedia"
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
+// A simplified version of "H264VideoStreamFramer" that takes only complete,
+// discrete frames (rather than an arbitrary byte stream) as input.
+// This avoids the parsing and data copying overhead of the full
+// "H264VideoStreamFramer".
+// Implementation
+
+#include "H264VideoStreamDiscreteFramer.hh"
+
+H264VideoStreamDiscreteFramer*
+H264VideoStreamDiscreteFramer::createNew(UsageEnvironment& env, FramedSource* inputSource) {
+ // Need to add source type checking here??? #####
+ return new H264VideoStreamDiscreteFramer(env, inputSource);
+}
+
+H264VideoStreamDiscreteFramer
+::H264VideoStreamDiscreteFramer(UsageEnvironment& env, FramedSource* inputSource)
+ : H264VideoStreamFramer(env, inputSource, False/*don't create a parser*/, False) {
+}
+
+H264VideoStreamDiscreteFramer::~H264VideoStreamDiscreteFramer() {
+}
+
+void H264VideoStreamDiscreteFramer::doGetNextFrame() {
+ // Arrange to read data (which should be a complete H.264 NAL unit)
+ // from our data source, directly into the client's input buffer.
+ // After reading this, we'll do some parsing on the frame.
+ fInputSource->getNextFrame(fTo, fMaxSize,
+ afterGettingFrame, this,
+ FramedSource::handleClosure, this);
+}
+
+void H264VideoStreamDiscreteFramer
+::afterGettingFrame(void* clientData, unsigned frameSize,
+ unsigned numTruncatedBytes,
+ struct timeval presentationTime,
+ unsigned durationInMicroseconds) {
+ H264VideoStreamDiscreteFramer* source = (H264VideoStreamDiscreteFramer*)clientData;
+ source->afterGettingFrame1(frameSize, numTruncatedBytes, presentationTime, durationInMicroseconds);
+}
+
+void H264VideoStreamDiscreteFramer
+::afterGettingFrame1(unsigned frameSize, unsigned numTruncatedBytes,
+ struct timeval presentationTime,
+ unsigned durationInMicroseconds) {
+ // Get the "nal_unit_type", to see if this NAL unit is one that we want to save a copy of:
+ u_int8_t nal_unit_type = frameSize == 0 ? 0xFF : fTo[0]&0x1F;
+
+ // Check for a (likely) common error: NAL units that (erroneously) begin with a 0x00000001 or 0x000001 'start code'
+ // (Those start codes should only be in byte-stream data; not data that consists of discrete NAL units.)
+ if (nal_unit_type == 0) {
+ envir() << "Warning: Invalid 'nal_unit_type': 0. Does the NAL unit begin with a MPEG 'start code' by mistake?\n";
+ } else if (nal_unit_type == 7) { // Sequence parameter set (SPS)
+ saveCopyOfSPS(fTo, frameSize);
+ } else if (nal_unit_type == 8) { // Picture parameter set (PPS)
+ saveCopyOfPPS(fTo, frameSize);
+ }
+
+ // Next, check whether this NAL unit ends the current 'access unit' (basically, a video frame). Unfortunately, we can't do this
+ // reliably, because we don't yet know anything about the *next* NAL unit that we'll see. So, we guess this as best as we can,
+ // by assuming that if this NAL unit is a VCL NAL unit, then it ends the current 'access unit'.
+ Boolean const isVCL = nal_unit_type <= 5 && nal_unit_type > 0; // Would need to include type 20 for SVC and MVC #####
+ if (isVCL) fPictureEndMarker = True;
+
+ // Finally, complete delivery to the client:
+ fFrameSize = frameSize;
+ fNumTruncatedBytes = numTruncatedBytes;
+ fPresentationTime = presentationTime;
+ fDurationInMicroseconds = durationInMicroseconds;
+ afterGetting(this);
+}
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/H264VideoStreamFramer.cpp
^
|
@@ -14,21 +14,742 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
-// Any source that feeds into a "H264VideoRTPSink" must be of this class.
-// This is a virtual base class; subclasses must implement the
-// "currentNALUnitEndsAccessUnit()" virtual function.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
+// A filter that breaks up a H.264 Video Elementary Stream into NAL units.
// Implementation
#include "H264VideoStreamFramer.hh"
+#include "MPEGVideoStreamParser.hh"
+#include "BitVector.hh"
-H264VideoStreamFramer::H264VideoStreamFramer(UsageEnvironment& env, FramedSource* inputSource)
- : FramedFilter(env, inputSource) {
+////////// H264VideoStreamParser definition //////////
+
+class H264VideoStreamParser: public MPEGVideoStreamParser {
+public:
+ H264VideoStreamParser(H264VideoStreamFramer* usingSource, FramedSource* inputSource, Boolean includeStartCodeInOutput);
+ virtual ~H264VideoStreamParser();
+
+private: // redefined virtual functions:
+ virtual void flushInput();
+ virtual unsigned parse();
+
+private:
+ H264VideoStreamFramer* usingSource() {
+ return (H264VideoStreamFramer*)fUsingSource;
+ }
+
+ void removeEmulationBytes(u_int8_t* nalUnitCopy, unsigned maxSize, unsigned& nalUnitCopySize);
+
+ void analyze_seq_parameter_set_data(unsigned& num_units_in_tick, unsigned& time_scale, unsigned& fixed_frame_rate_flag);
+ void analyze_vui_parameters(BitVector& bv,
+ unsigned& num_units_in_tick, unsigned& time_scale, unsigned& fixed_frame_rate_flag);
+#ifdef DO_FULL_SPS_PARSING
+ void analyze_hrd_parameters(BitVector& bv);
+#endif
+ void analyze_sei_data();
+ void analyze_slice_header(u_int8_t* start, u_int8_t* end, u_int8_t nal_unit_type,
+ unsigned &frame_num, unsigned &pic_parameter_set_id, unsigned& idr_pic_id,
+ Boolean& field_pic_flag, Boolean& bottom_field_flag);
+
+private:
+ unsigned fOutputStartCodeSize;
+ Boolean fHaveSeenFirstStartCode;
+
+ // Fields in H.264 headers, used in parsing:
+ unsigned log2_max_frame_num; // log2_max_frame_num_minus4 + 4
+ Boolean separate_colour_plane_flag;
+ Boolean frame_mbs_only_flag;
+};
+
+
+////////// H264VideoStreamFramer implementation //////////
+
+H264VideoStreamFramer* H264VideoStreamFramer
+::createNew(UsageEnvironment& env, FramedSource* inputSource, Boolean includeStartCodeInOutput) {
+ return new H264VideoStreamFramer(env, inputSource, True, includeStartCodeInOutput);
+}
+
+H264VideoStreamFramer
+::H264VideoStreamFramer(UsageEnvironment& env, FramedSource* inputSource, Boolean createParser, Boolean includeStartCodeInOutput)
+ : MPEGVideoStreamFramer(env, inputSource),
+ fIncludeStartCodeInOutput(includeStartCodeInOutput),
+ fLastSeenSPS(NULL), fLastSeenSPSSize(0), fLastSeenPPS(NULL), fLastSeenPPSSize(0) {
+ fParser = createParser
+ ? new H264VideoStreamParser(this, inputSource, includeStartCodeInOutput)
+ : NULL;
+ fNextPresentationTime = fPresentationTimeBase;
+ fFrameRate = 25.0; // We assume a frame rate of 25 fps, unless we learn otherwise (from parsing a Sequence Parameter Set NAL unit)
}
H264VideoStreamFramer::~H264VideoStreamFramer() {
+ delete[] fLastSeenSPS;
+ delete[] fLastSeenPPS;
+}
+
+void H264VideoStreamFramer::saveCopyOfSPS(u_int8_t* from, unsigned size) {
+ delete[] fLastSeenSPS;
+ fLastSeenSPS = new u_int8_t[size];
+ memmove(fLastSeenSPS, from, size);
+
+ fLastSeenSPSSize = size;
+}
+
+void H264VideoStreamFramer::saveCopyOfPPS(u_int8_t* from, unsigned size) {
+ delete[] fLastSeenPPS;
+ fLastSeenPPS = new u_int8_t[size];
+ memmove(fLastSeenPPS, from, size);
+
+ fLastSeenPPSSize = size;
}
Boolean H264VideoStreamFramer::isH264VideoStreamFramer() const {
return True;
}
+
+
+////////// H264VideoStreamParser implementation //////////
+
+H264VideoStreamParser
+::H264VideoStreamParser(H264VideoStreamFramer* usingSource, FramedSource* inputSource, Boolean includeStartCodeInOutput)
+ : MPEGVideoStreamParser(usingSource, inputSource),
+ fOutputStartCodeSize(includeStartCodeInOutput ? 4 : 0), fHaveSeenFirstStartCode(False),
+ // Default values for our parser variables (in case they're not set explicitly in headers that we parse:
+ log2_max_frame_num(5), separate_colour_plane_flag(False), frame_mbs_only_flag(True) {
+}
+
+H264VideoStreamParser::~H264VideoStreamParser() {
+}
+
+void H264VideoStreamParser::removeEmulationBytes(u_int8_t* nalUnitCopy, unsigned maxSize, unsigned& nalUnitCopySize) {
+ u_int8_t* nalUnitOrig = fStartOfFrame + fOutputStartCodeSize;
+ unsigned const NumBytesInNALunit = fTo - nalUnitOrig;
+ if (NumBytesInNALunit > maxSize) return;
+ nalUnitCopySize = 0;
+ for (unsigned i = 0; i < NumBytesInNALunit; ++i) {
+ if (i+2 < NumBytesInNALunit && nalUnitOrig[i] == 0 && nalUnitOrig[i+1] == 0 && nalUnitOrig[i+2] == 3) {
+ nalUnitCopy[nalUnitCopySize++] = nalUnitOrig[i++];
+ nalUnitCopy[nalUnitCopySize++] = nalUnitOrig[i++];
+ } else {
+ nalUnitCopy[nalUnitCopySize++] = nalUnitOrig[i];
+ }
+ }
+}
+
+#ifdef DEBUG
+char const* nal_unit_type_description[32] = {
+ "Unspecified", //0
+ "Coded slice of a non-IDR picture", //1
+ "Coded slice data partition A", //2
+ "Coded slice data partition B", //3
+ "Coded slice data partition C", //4
+ "Coded slice of an IDR picture", //5
+ "Supplemental enhancement information (SEI)", //6
+ "Sequence parameter set", //7
+ "Picture parameter set", //8
+ "Access unit delimiter", //9
+ "End of sequence", //10
+ "End of stream", //11
+ "Filler data", //12
+ "Sequence parameter set extension", //13
+ "Prefix NAL unit", //14
+ "Subset sequence parameter set", //15
+ "Reserved", //16
+ "Reserved", //17
+ "Reserved", //18
+ "Coded slice of an auxiliary coded picture without partitioning", //19
+ "Coded slice extension", //20
+ "Reserved", //21
+ "Reserved", //22
+ "Reserved", //23
+ "Unspecified", //24
+ "Unspecified", //25
+ "Unspecified", //26
+ "Unspecified", //27
+ "Unspecified", //28
+ "Unspecified", //29
+ "Unspecified", //30
+ "Unspecified" //31
+};
+#endif
+
+#ifdef DEBUG
+static unsigned numDebugTabs = 1;
+#define DEBUG_PRINT_TABS for (unsigned _i = 0; _i < numDebugTabs; ++_i) fprintf(stderr, "\t")
+#define DEBUG_PRINT(x) do { DEBUG_PRINT_TABS; fprintf(stderr, "%s: %d\n", #x, x); } while (0)
+#define DEBUG_STR(x) do { DEBUG_PRINT_TABS; fprintf(stderr, "%s\n", x); } while (0)
+class DebugTab {
+public:
+ DebugTab() {++numDebugTabs;}
+ ~DebugTab() {--numDebugTabs;}
+};
+#define DEBUG_TAB DebugTab dummy
+#else
+#define DEBUG_PRINT(x) do {x = x;} while (0)
+ // Note: the "x=x;" statement is intended to eliminate "unused variable" compiler warning messages
+#define DEBUG_STR(x) do {} while (0)
+#define DEBUG_TAB do {} while (0)
+#endif
+
+#ifdef DO_FULL_SPS_PARSING
+void H264VideoStreamParser::analyze_hrd_parameters(BitVector& bv) {
+ DEBUG_STR("BEGIN hrd_parameters");
+ unsigned cpb_cnt_minus1 = bv.get_expGolomb();
+ DEBUG_PRINT(cpb_cnt_minus1);
+ unsigned bit_rate_scale = bv.getBits(4);
+ DEBUG_PRINT(bit_rate_scale);
+ unsigned cpb_size_scale = bv.getBits(4);
+ DEBUG_PRINT(cpb_size_scale);
+ for (unsigned SchedSelIdx = 0; SchedSelIdx <= cpb_cnt_minus1; ++SchedSelIdx) {
+ DEBUG_TAB;
+ unsigned bit_rate_value_minus1 = bv.get_expGolomb();
+ DEBUG_PRINT(bit_rate_value_minus1);
+ unsigned cpb_size_value_minus1 = bv.get_expGolomb();
+ DEBUG_PRINT(cpb_size_value_minus1);
+ unsigned cbr_flag = bv.get1Bit();
+ DEBUG_PRINT(cbr_flag);
+ }
+ unsigned initial_cpb_removal_delay_length_minus1 = bv.getBits(5);
+ DEBUG_PRINT(initial_cpb_removal_delay_length_minus1);
+ unsigned cpb_removal_delay_length_minus1 = bv.getBits(5);
+ DEBUG_PRINT(cpb_removal_delay_length_minus1);
+ unsigned dpb_output_delay_length_minus1 = bv.getBits(5);
+ DEBUG_PRINT(dpb_output_delay_length_minus1);
+ unsigned time_offset_length = bv.getBits(5);
+ DEBUG_PRINT(time_offset_length);
+ DEBUG_STR("END hrd_parameters");
+}
+#endif
+
+void H264VideoStreamParser
+::analyze_vui_parameters(BitVector& bv,
+ unsigned& num_units_in_tick, unsigned& time_scale, unsigned& fixed_frame_rate_flag) {
+ DEBUG_STR("BEGIN vui_parameters");
+ unsigned aspect_ratio_info_present_flag = bv.get1Bit();
+ DEBUG_PRINT(aspect_ratio_info_present_flag);
+ if (aspect_ratio_info_present_flag) {
+ DEBUG_TAB;
+ unsigned aspect_ratio_idc = bv.getBits(8);
+ DEBUG_PRINT(aspect_ratio_idc);
+ if (aspect_ratio_idc == 255/*Extended_SAR*/) {
+ bv.skipBits(32); // sar_width; sar_height
+ }
+ }
+ unsigned overscan_info_present_flag = bv.get1Bit();
+ DEBUG_PRINT(overscan_info_present_flag);
+ if (overscan_info_present_flag) {
+ bv.skipBits(1); // overscan_appropriate_flag
+ }
+ unsigned video_signal_type_present_flag = bv.get1Bit();
+ DEBUG_PRINT(video_signal_type_present_flag);
+ if (video_signal_type_present_flag) {
+ DEBUG_TAB;
+ bv.skipBits(4); // video_format; video_full_range_flag
+ unsigned colour_description_present_flag = bv.get1Bit();
+ DEBUG_PRINT(colour_description_present_flag);
+ if (colour_description_present_flag) {
+ bv.skipBits(24); // colour_primaries; transfer_characteristics; matrix_coefficients
+ }
+ }
+ unsigned chroma_loc_info_present_flag = bv.get1Bit();
+ DEBUG_PRINT(chroma_loc_info_present_flag);
+ if (chroma_loc_info_present_flag) {
+ (void)bv.get_expGolomb(); // chroma_sample_loc_type_top_field
+ (void)bv.get_expGolomb(); // chroma_sample_loc_type_bottom_field
+ }
+ unsigned timing_info_present_flag = bv.get1Bit();
+ DEBUG_PRINT(timing_info_present_flag);
+ if (timing_info_present_flag) {
+ DEBUG_TAB;
+ num_units_in_tick = bv.getBits(32);
+ DEBUG_PRINT(num_units_in_tick);
+ time_scale = bv.getBits(32);
+ DEBUG_PRINT(time_scale);
+ fixed_frame_rate_flag = bv.get1Bit();
+ DEBUG_PRINT(fixed_frame_rate_flag);
+ }
+#ifdef DO_FULL_SPS_PARSING
+ unsigned nal_hrd_parameters_present_flag = bv.get1Bit();
+ DEBUG_PRINT(nal_hrd_parameters_present_flag);
+ if (nal_hrd_parameters_present_flag) {
+ DEBUG_TAB;
+ analyze_hrd_parameters(bv);
+ }
+ unsigned vcl_hrd_parameters_present_flag = bv.get1Bit();
+ DEBUG_PRINT(vcl_hrd_parameters_present_flag);
+ if (vcl_hrd_parameters_present_flag) {
+ DEBUG_TAB;
+ analyze_hrd_parameters(bv);
+ }
+ if (nal_hrd_parameters_present_flag || vcl_hrd_parameters_present_flag) {
+ bv.skipBits(1); // low_delay_hrd_flag
+ }
+ bv.skipBits(1); // pic_struct_present_flag
+ unsigned bitstream_restriction_flag = bv.get1Bit();
+ DEBUG_PRINT(bitstream_restriction_flag);
+ if (bitstream_restriction_flag) {
+ bv.skipBits(1); // motion_vectors_over_pic_boundaries_flag
+ (void)bv.get_expGolomb(); // max_bytes_per_pic_denom
+ (void)bv.get_expGolomb(); // max_bits_per_mb_denom
+ (void)bv.get_expGolomb(); // log2_max_mv_length_horizontal
+ (void)bv.get_expGolomb(); // log2_max_mv_length_vertical
+ (void)bv.get_expGolomb(); // num_reorder_frames
+ (void)bv.get_expGolomb(); // max_dec_frame_buffering
+ }
+ DEBUG_STR("END vui_parameters");
+#endif
+}
+
+#define SPS_MAX_SIZE 1000 // larger than the largest possible SPS (Sequence Parameter Set) NAL unit
+
+void H264VideoStreamParser
+::analyze_seq_parameter_set_data(unsigned& num_units_in_tick, unsigned& time_scale, unsigned& fixed_frame_rate_flag) {
+ num_units_in_tick = time_scale = fixed_frame_rate_flag = 0; // default values
+
+ // Begin by making a copy of the NAL unit data, removing any 'emulation prevention' bytes:
+ u_int8_t sps[SPS_MAX_SIZE];
+ unsigned spsSize;
+ removeEmulationBytes(sps, sizeof sps, spsSize);
+
+ BitVector bv(sps, 0, 8*spsSize);
+
+ bv.skipBits(8); // forbidden_zero_bit; nal_ref_idc; nal_unit_type
+ unsigned profile_idc = bv.getBits(8);
+ DEBUG_PRINT(profile_idc);
+ unsigned constraint_setN_flag = bv.getBits(8); // also "reserved_zero_2bits" at end
+ DEBUG_PRINT(constraint_setN_flag);
+ unsigned level_idc = bv.getBits(8);
+ DEBUG_PRINT(level_idc);
+ unsigned seq_parameter_set_id = bv.get_expGolomb();
+ DEBUG_PRINT(seq_parameter_set_id);
+ if (profile_idc == 100 || profile_idc == 110 || profile_idc == 122 || profile_idc == 244 || profile_idc == 44 || profile_idc == 83 || profile_idc == 86 || profile_idc == 118 || profile_idc == 128 ) {
+ DEBUG_TAB;
+ unsigned chroma_format_idc = bv.get_expGolomb();
+ DEBUG_PRINT(chroma_format_idc);
+ if (chroma_format_idc == 3) {
+ DEBUG_TAB;
+ separate_colour_plane_flag = bv.get1Bit();
+ DEBUG_PRINT(separate_colour_plane_flag);
+ }
+ (void)bv.get_expGolomb(); // bit_depth_luma_minus8
+ (void)bv.get_expGolomb(); // bit_depth_chroma_minus8
+ bv.skipBits(1); // qpprime_y_zero_transform_bypass_flag
+ unsigned seq_scaling_matrix_present_flag = bv.get1Bit();
+ DEBUG_PRINT(seq_scaling_matrix_present_flag);
+ if (seq_scaling_matrix_present_flag) {
+ for (int i = 0; i < ((chroma_format_idc != 3) ? 8 : 12); ++i) {
+ DEBUG_TAB;
+ DEBUG_PRINT(i);
+ unsigned seq_scaling_list_present_flag = bv.get1Bit();
+ DEBUG_PRINT(seq_scaling_list_present_flag);
+ if (seq_scaling_list_present_flag) {
+ DEBUG_TAB;
+ unsigned sizeOfScalingList = i < 6 ? 16 : 64;
+ unsigned lastScale = 8;
+ unsigned nextScale = 8;
+ for (unsigned j = 0; j < sizeOfScalingList; ++j) {
+ DEBUG_TAB;
+ DEBUG_PRINT(j);
+ DEBUG_PRINT(nextScale);
+ if (nextScale != 0) {
+ DEBUG_TAB;
+ unsigned delta_scale = bv.get_expGolomb();
+ DEBUG_PRINT(delta_scale);
+ nextScale = (lastScale + delta_scale + 256) % 256;
+ }
+ lastScale = (nextScale == 0) ? lastScale : nextScale;
+ DEBUG_PRINT(lastScale);
+ }
+ }
+ }
+ }
+ }
+ unsigned log2_max_frame_num_minus4 = bv.get_expGolomb();
+ DEBUG_PRINT(log2_max_frame_num_minus4);
+ log2_max_frame_num = log2_max_frame_num_minus4 + 4;
+ unsigned pic_order_cnt_type = bv.get_expGolomb();
+ DEBUG_PRINT(pic_order_cnt_type);
+ if (pic_order_cnt_type == 0) {
+ DEBUG_TAB;
+ unsigned log2_max_pic_order_cnt_lsb_minus4 = bv.get_expGolomb();
+ DEBUG_PRINT(log2_max_pic_order_cnt_lsb_minus4);
+ } else if (pic_order_cnt_type == 1) {
+ DEBUG_TAB;
+ bv.skipBits(1); // delta_pic_order_always_zero_flag
+ (void)bv.get_expGolomb(); // offset_for_non_ref_pic
+ (void)bv.get_expGolomb(); // offset_for_top_to_bottom_field
+ unsigned num_ref_frames_in_pic_order_cnt_cycle = bv.get_expGolomb();
+ DEBUG_PRINT(num_ref_frames_in_pic_order_cnt_cycle);
+ for (unsigned i = 0; i < num_ref_frames_in_pic_order_cnt_cycle; ++i) {
+ (void)bv.get_expGolomb(); // offset_for_ref_frame[i]
+ }
+ }
+ unsigned max_num_ref_frames = bv.get_expGolomb();
+ DEBUG_PRINT(max_num_ref_frames);
+ unsigned gaps_in_frame_num_value_allowed_flag = bv.get1Bit();
+ DEBUG_PRINT(gaps_in_frame_num_value_allowed_flag);
+ unsigned pic_width_in_mbs_minus1 = bv.get_expGolomb();
+ DEBUG_PRINT(pic_width_in_mbs_minus1);
+ unsigned pic_height_in_map_units_minus1 = bv.get_expGolomb();
+ DEBUG_PRINT(pic_height_in_map_units_minus1);
+ frame_mbs_only_flag = bv.get1Bit();
+ DEBUG_PRINT(frame_mbs_only_flag);
+ if (!frame_mbs_only_flag) {
+ bv.skipBits(1); // mb_adaptive_frame_field_flag
+ }
+ bv.skipBits(1); // direct_8x8_inference_flag
+ unsigned frame_cropping_flag = bv.get1Bit();
+ DEBUG_PRINT(frame_cropping_flag);
+ if (frame_cropping_flag) {
+ (void)bv.get_expGolomb(); // frame_crop_left_offset
+ (void)bv.get_expGolomb(); // frame_crop_right_offset
+ (void)bv.get_expGolomb(); // frame_crop_top_offset
+ (void)bv.get_expGolomb(); // frame_crop_bottom_offset
+ }
+ unsigned vui_parameters_present_flag = bv.get1Bit();
+ DEBUG_PRINT(vui_parameters_present_flag);
+ if (vui_parameters_present_flag) {
+ DEBUG_TAB;
+ analyze_vui_parameters(bv,num_units_in_tick, time_scale, fixed_frame_rate_flag);
+ }
+}
+
+#define SEI_MAX_SIZE 5000 // larger than the largest possible SEI NAL unit
+
+#ifdef DEBUG
+#define MAX_SEI_PAYLOAD_TYPE_DESCRIPTION 46
+char const* sei_payloadType_description[MAX_SEI_PAYLOAD_TYPE_DESCRIPTION+1] = {
+ "buffering_period", //0
+ "pic_timing", //1
+ "pan_scan_rect", //2
+ "filler_payload", //3
+ "user_data_registered_itu_t_t35", //4
+ "user_data_unregistered", //5
+ "recovery_point", //6
+ "dec_ref_pic_marking_repetition", //7
+ "spare_pic", //8
+ "scene_info", //9
+ "sub_seq_info", //10
+ "sub_seq_layer_characteristics", //11
+ "sub_seq_characteristics", //12
+ "full_frame_freeze", //13
+ "full_frame_freeze_release", //14
+ "full_frame_snapshot", //15
+ "progressive_refinement_segment_start", //16
+ "progressive_refinement_segment_end", //17
+ "motion_constrained_slice_group_set", //18
+ "film_grain_characteristics", //19
+ "deblocking_filter_display_preference", //20
+ "stereo_video_info", //21
+ "post_filter_hint", //22
+ "tone_mapping_info", //23
+ "scalability_info", //24
+ "sub_pic_scalable_layer", //25
+ "non_required_layer_rep", //26
+ "priority_layer_info", //27
+ "layers_not_present", //28
+ "layer_dependency_change", //29
+ "scalable_nesting", //30
+ "base_layer_temporal_hrd", //31
+ "quality_layer_integrity_check", //32
+ "redundant_pic_property", //33
+ "tl0_dep_rep_index", //34
+ "tl_switching_point", //35
+ "parallel_decoding_info", //36
+ "mvc_scalable_nesting", //37
+ "view_scalability_info", //38
+ "multiview_scene_info", //39
+ "multiview_acquisition_info", //40
+ "non_required_view_component", //41
+ "view_dependency_change", //42
+ "operation_points_not_present", //43
+ "base_view_temporal_hrd", //44
+ "frame_packing_arrangement", //45
+ "reserved_sei_message" // 46 or higher
+};
+#endif
+
+void H264VideoStreamParser::analyze_sei_data() {
+ // Begin by making a copy of the NAL unit data, removing any 'emulation prevention' bytes:
+ u_int8_t sei[SEI_MAX_SIZE];
+ unsigned seiSize;
+ removeEmulationBytes(sei, sizeof sei, seiSize);
+
+ unsigned j = 1; // skip the initial byte (forbidden_zero_bit; nal_ref_idc; nal_unit_type); we've already seen it
+ while (j < seiSize) {
+ unsigned payloadType = 0;
+ do {
+ payloadType += sei[j];
+ } while (sei[j++] == 255 && j < seiSize);
+ if (j >= seiSize) break;
+
+ unsigned payloadSize = 0;
+ do {
+ payloadSize += sei[j];
+ } while (sei[j++] == 255 && j < seiSize);
+ if (j >= seiSize) break;
+
+#ifdef DEBUG
+ unsigned descriptionNum = payloadType <= MAX_SEI_PAYLOAD_TYPE_DESCRIPTION ? payloadType : MAX_SEI_PAYLOAD_TYPE_DESCRIPTION;
+ fprintf(stderr, "\tpayloadType %d (\"%s\"); payloadSize %d\n", payloadType, sei_payloadType_description[descriptionNum], payloadSize);
+#endif
+ j += payloadSize;
+ }
+}
+
+void H264VideoStreamParser
+::analyze_slice_header(u_int8_t* start, u_int8_t* end, u_int8_t nal_unit_type,
+ unsigned &frame_num, unsigned &pic_parameter_set_id, unsigned& idr_pic_id,
+ Boolean& field_pic_flag, Boolean& bottom_field_flag) {
+ BitVector bv(start, 0, 8*(end-start));
+
+ // Some of the result parameters might not be present in the header; set them to default values:
+ field_pic_flag = bottom_field_flag = 0;
+
+ // Note: We assume that there aren't any 'emulation prevention' bytes here to worry about...
+ bv.skipBits(8); // forbidden_zero_bit; nal_ref_idc; nal_unit_type
+ unsigned first_mb_in_slice = bv.get_expGolomb();
+ DEBUG_PRINT(first_mb_in_slice);
+ unsigned slice_type = bv.get_expGolomb();
+ DEBUG_PRINT(slice_type);
+ pic_parameter_set_id = bv.get_expGolomb();
+ DEBUG_PRINT(pic_parameter_set_id);
+ if (separate_colour_plane_flag) {
+ bv.skipBits(2); // colour_plane_id
+ }
+ frame_num = bv.getBits(log2_max_frame_num);
+ DEBUG_PRINT(frame_num);
+ if (!frame_mbs_only_flag) {
+ DEBUG_TAB;
+ field_pic_flag = bv.get1Bit();
+ DEBUG_PRINT(field_pic_flag);
+ if (field_pic_flag) {
+ DEBUG_TAB;
+ bottom_field_flag = bv.get1Bit();
+ DEBUG_PRINT(bottom_field_flag);
+ }
+ }
+ Boolean IdrPicFlag = nal_unit_type == 5;
+ if (IdrPicFlag) {
+ DEBUG_TAB;
+ idr_pic_id = bv.get_expGolomb();
+ DEBUG_PRINT(idr_pic_id);
+ }
+ // We don't parse any more of the "slice_header", because we don't need the remaining fields (for our purpose)
+}
+
+void H264VideoStreamParser::flushInput() {
+ fHaveSeenFirstStartCode = False;
+
+ StreamParser::flushInput();
+}
+
+#define NUM_NEXT_SLICE_HEADER_BYTES_TO_ANALYZE 12
+
+unsigned H264VideoStreamParser::parse() {
+ try {
+ // The stream must start with a 0x00000001:
+ if (!fHaveSeenFirstStartCode) {
+ // Skip over any input bytes that precede the first 0x00000001:
+ u_int32_t first4Bytes;
+ while ((first4Bytes = test4Bytes()) != 0x00000001) {
+ get1Byte(); setParseState(); // ensures that we progress over bad data
+ }
+ skipBytes(4); // skip this initial code
+
+ setParseState();
+ fHaveSeenFirstStartCode = True; // from now on
+ }
+
+ if (fOutputStartCodeSize > 0) {
+ // Include a start code in the output:
+ save4Bytes(0x00000001);
+ }
+
+ // Then save everything up until the next 0x00000001 (4 bytes) or 0x000001 (4 bytes).
+ // Also make note of the first byte, because it contains the "nal_unit_type":
+ u_int32_t next4Bytes = test4Bytes();
+ u_int8_t firstByte = next4Bytes>>24;
+ u_int8_t nal_ref_idc = (firstByte&0x60)>>5;
+ u_int8_t nal_unit_type = firstByte&0x1F;
+ while (next4Bytes != 0x00000001 && (next4Bytes&0xFFFFFF00) != 0x00000100) {
+ // We save at least some of "next4Bytes".
+ if ((unsigned)(next4Bytes&0xFF) > 1) {
+ // Common case: 0x00000001 or 0x000001 definitely doesn't begin anywhere in "next4Bytes", so we save all of it:
+ save4Bytes(next4Bytes);
+ skipBytes(4);
+ } else {
+ // Save the first byte, and continue testing the rest:
+ saveByte(next4Bytes>>24);
+ skipBytes(1);
+ }
+ next4Bytes = test4Bytes();
+ }
+ // Assert: next4Bytes starts with 0x00000001 or 0x000001, and we've saved all previous bytes (forming a complete NAL unit).
+ // Skip over these remaining bytes, up until the start of the next NAL unit:
+ if (next4Bytes == 0x00000001) {
+ skipBytes(4);
+ } else {
+ skipBytes(3);
+ }
+#ifdef DEBUG
+ fprintf(stderr, "Parsed %d-byte NAL-unit (nal_ref_idc: %d, nal_unit_type: %d (\"%s\"))\n",
+ curFrameSize()-fOutputStartCodeSize, nal_ref_idc, nal_unit_type, nal_unit_type_description[nal_unit_type]);
+#endif
+
+ switch (nal_unit_type) {
+ case 6: { // Supplemental enhancement information (SEI)
+ analyze_sei_data();
+ // Later, perhaps adjust "fPresentationTime" if we saw a "pic_timing" SEI payload??? #####
+ break;
+ }
+ case 7: { // Sequence parameter set
+ // First, save a copy of this NAL unit, in case the downstream object wants to see it:
+ usingSource()->saveCopyOfSPS(fStartOfFrame + fOutputStartCodeSize, fTo - fStartOfFrame - fOutputStartCodeSize);
+
+ // Parse this NAL unit to check whether frame rate information is present:
+ unsigned num_units_in_tick, time_scale, fixed_frame_rate_flag;
+ analyze_seq_parameter_set_data(num_units_in_tick, time_scale, fixed_frame_rate_flag);
+ if (time_scale > 0 && num_units_in_tick > 0) {
+ usingSource()->fFrameRate = time_scale/(2.0*num_units_in_tick);
+#ifdef DEBUG
+ fprintf(stderr, "Set frame rate to %f fps\n", usingSource()->fFrameRate);
+ if (fixed_frame_rate_flag == 0) {
+ fprintf(stderr, "\tWARNING: \"fixed_frame_rate_flag\" was not set\n");
+ }
+#endif
+ } else {
+#ifdef DEBUG
+ fprintf(stderr, "\tThis \"Sequence Parameter Set\" NAL unit contained no frame rate information, so we use a default frame rate of %f fps\n", usingSource()->fFrameRate);
+#endif
+ }
+ break;
+ }
+ case 8: { // Picture parameter set
+ // Save a copy of this NAL unit, in case the downstream object wants to see it:
+ usingSource()->saveCopyOfPPS(fStartOfFrame + fOutputStartCodeSize, fTo - fStartOfFrame - fOutputStartCodeSize);
+ }
+ }
+
+ usingSource()->setPresentationTime();
+#ifdef DEBUG
+ unsigned long secs = (unsigned long)usingSource()->fPresentationTime.tv_sec;
+ unsigned uSecs = (unsigned)usingSource()->fPresentationTime.tv_usec;
+ fprintf(stderr, "\tPresentation time: %lu.%06u\n", secs, uSecs);
+#endif
+
+ // If this NAL unit is a VCL NAL unit, we also scan the start of the next NAL unit, to determine whether this NAL unit
+ // ends the current 'access unit'. We need this information to figure out when to increment "fPresentationTime".
+ // (RTP streamers also need to know this in order to figure out whether or not to set the "M" bit.)
+ Boolean thisNALUnitEndsAccessUnit = False; // until we learn otherwise
+ Boolean const isVCL = nal_unit_type <= 5 && nal_unit_type > 0; // Would need to include type 20 for SVC and MVC #####
+ if (isVCL) {
+ u_int32_t first4BytesOfNextNALUnit = test4Bytes();
+ u_int8_t firstByteOfNextNALUnit = first4BytesOfNextNALUnit>>24;
+ u_int8_t next_nal_ref_idc = (firstByteOfNextNALUnit&0x60)>>5;
+ u_int8_t next_nal_unit_type = firstByteOfNextNALUnit&0x1F;
+ if (next_nal_unit_type >= 6) {
+ // The next NAL unit is not a VCL; therefore, we assume that this NAL unit ends the current 'access unit':
+#ifdef DEBUG
+ fprintf(stderr, "\t(The next NAL unit is not a VCL)\n");
+#endif
+ thisNALUnitEndsAccessUnit = True;
+ } else {
+ // The next NAL unit is also a VLC. We need to examine it a little to figure out if it's a different 'access unit'.
+ // (We use many of the criteria described in section 7.4.1.2.4 of the H.264 specification.)
+ Boolean IdrPicFlag = nal_unit_type == 5;
+ Boolean next_IdrPicFlag = next_nal_unit_type == 5;
+ if (next_IdrPicFlag != IdrPicFlag) {
+ // IdrPicFlag differs in value
+#ifdef DEBUG
+ fprintf(stderr, "\t(IdrPicFlag differs in value)\n");
+#endif
+ thisNALUnitEndsAccessUnit = True;
+ } else if (next_nal_ref_idc != nal_ref_idc && next_nal_ref_idc*nal_ref_idc == 0) {
+ // nal_ref_idc differs in value with one of the nal_ref_idc values being equal to 0
+#ifdef DEBUG
+ fprintf(stderr, "\t(nal_ref_idc differs in value with one of the nal_ref_idc values being equal to 0)\n");
+#endif
+ thisNALUnitEndsAccessUnit = True;
+ } else if ((nal_unit_type == 1 || nal_unit_type == 2 || nal_unit_type == 5)
+ && (next_nal_unit_type == 1 || next_nal_unit_type == 2 || next_nal_unit_type == 5)) {
+ // Both this and the next NAL units begin with a "slice_header".
+ // Parse this (for each), to get parameters that we can compare:
+
+ // Current NAL unit's "slice_header":
+ unsigned frame_num, pic_parameter_set_id, idr_pic_id;
+ Boolean field_pic_flag, bottom_field_flag;
+ analyze_slice_header(fStartOfFrame + fOutputStartCodeSize, fTo, nal_unit_type,
+ frame_num, pic_parameter_set_id, idr_pic_id, field_pic_flag, bottom_field_flag);
+
+ // Next NAL unit's "slice_header":
+#ifdef DEBUG
+ fprintf(stderr, " Next NAL unit's slice_header:\n");
+#endif
+ u_int8_t next_slice_header[NUM_NEXT_SLICE_HEADER_BYTES_TO_ANALYZE];
+ testBytes(next_slice_header, sizeof next_slice_header);
+ unsigned next_frame_num, next_pic_parameter_set_id, next_idr_pic_id;
+ Boolean next_field_pic_flag, next_bottom_field_flag;
+ analyze_slice_header(next_slice_header, &next_slice_header[sizeof next_slice_header], next_nal_unit_type,
+ next_frame_num, next_pic_parameter_set_id, next_idr_pic_id, next_field_pic_flag, next_bottom_field_flag);
+
+ if (next_frame_num != frame_num) {
+ // frame_num differs in value
+#ifdef DEBUG
+ fprintf(stderr, "\t(frame_num differs in value)\n");
+#endif
+ thisNALUnitEndsAccessUnit = True;
+ } else if (next_pic_parameter_set_id != pic_parameter_set_id) {
+ // pic_parameter_set_id differs in value
+#ifdef DEBUG
+ fprintf(stderr, "\t(pic_parameter_set_id differs in value)\n");
+#endif
+ thisNALUnitEndsAccessUnit = True;
+ } else if (next_field_pic_flag != field_pic_flag) {
+ // field_pic_flag differs in value
+#ifdef DEBUG
+ fprintf(stderr, "\t(field_pic_flag differs in value)\n");
+#endif
+ thisNALUnitEndsAccessUnit = True;
+ } else if (next_bottom_field_flag != bottom_field_flag) {
+ // bottom_field_flag differs in value
+#ifdef DEBUG
+ fprintf(stderr, "\t(bottom_field_flag differs in value)\n");
+#endif
+ thisNALUnitEndsAccessUnit = True;
+ } else if (next_IdrPicFlag == 1 && next_idr_pic_id != idr_pic_id) {
+ // IdrPicFlag is equal to 1 for both and idr_pic_id differs in value
+ // Note: We already know that IdrPicFlag is the same for both.
+#ifdef DEBUG
+ fprintf(stderr, "\t(IdrPicFlag is equal to 1 for both and idr_pic_id differs in value)\n");
+#endif
+ thisNALUnitEndsAccessUnit = True;
+ }
+ }
+ }
+
+ if (thisNALUnitEndsAccessUnit) {
+#ifdef DEBUG
+ fprintf(stderr, "\t*****This NAL unit ends the current access unit*****\n");
+#endif
+ usingSource()->fPictureEndMarker = True;
+ ++usingSource()->fPictureCount;
+
+ // Note that the presentation time for the next NAL unit will be different:
+ struct timeval& nextPT = usingSource()->fNextPresentationTime; // alias
+ nextPT = usingSource()->fPresentationTime;
+ double nextFraction = nextPT.tv_usec/1000000.0 + 1/usingSource()->fFrameRate;
+ unsigned nextSecsIncrement = (long)nextFraction;
+ nextPT.tv_sec += (long)nextSecsIncrement;
+ nextPT.tv_usec = (long)((nextFraction - nextSecsIncrement)*1000000);
+ }
+ }
+ setParseState();
+
+ return curFrameSize();
+ } catch (int /*e*/) {
+#ifdef DEBUG
+ fprintf(stderr, "H264VideoStreamParser::parse() EXCEPTION (This is normal behavior - *not* an error)\n");
+#endif
+ return 0; // the parsing got interrupted
+ }
+}
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/HTTPSink.cpp
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// HTTP sinks
// Implementation
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/InputFile.cpp
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// Common routines for opening/closing named input files
// Implementation
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/JPEGVideoRTPSink.cpp
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// RTP sink for JPEG video (RFC 2435)
// Implementation
@@ -56,17 +56,33 @@
if (source == NULL) return; // sanity check
u_int8_t mainJPEGHeader[8]; // the special header
+ u_int8_t const type = source->type();
mainJPEGHeader[0] = 0; // Type-specific
mainJPEGHeader[1] = fragmentationOffset >> 16;
mainJPEGHeader[2] = fragmentationOffset >> 8;
mainJPEGHeader[3] = fragmentationOffset;
- mainJPEGHeader[4] = source->type();
+ mainJPEGHeader[4] = type;
mainJPEGHeader[5] = source->qFactor();
mainJPEGHeader[6] = source->width();
mainJPEGHeader[7] = source->height();
setSpecialHeaderBytes(mainJPEGHeader, sizeof mainJPEGHeader);
+ unsigned restartMarkerHeaderSize = 0; // by default
+ if (type >= 64 && type <= 127) {
+ // There is also a Restart Marker Header:
+ restartMarkerHeaderSize = 4;
+ u_int16_t const restartInterval = source->restartInterval(); // should be non-zero
+
+ u_int8_t restartMarkerHeader[4];
+ restartMarkerHeader[0] = restartInterval>>8;
+ restartMarkerHeader[1] = restartInterval&0xFF;
+ restartMarkerHeader[2] = restartMarkerHeader[3] = 0xFF; // F=L=1; Restart Count = 0x3FFF
+
+ setSpecialHeaderBytes(restartMarkerHeader, restartMarkerHeaderSize,
+ sizeof mainJPEGHeader/* start position */);
+ }
+
if (fragmentationOffset == 0 && source->qFactor() >= 128) {
// There is also a Quantization Header:
u_int8_t precision;
@@ -88,7 +104,7 @@
}
setSpecialHeaderBytes(quantizationHeader, quantizationHeaderSize,
- sizeof mainJPEGHeader /* start position */);
+ sizeof mainJPEGHeader + restartMarkerHeaderSize/* start position */);
delete[] quantizationHeader;
}
@@ -110,6 +126,12 @@
unsigned headerSize = 8; // by default
+ u_int8_t const type = source->type();
+ if (type >= 64 && type <= 127) {
+ // There is also a Restart Marker Header:
+ headerSize += 4;
+ }
+
if (curFragmentationOffset() == 0 && source->qFactor() >= 128) {
// There is also a Quantization Header:
u_int8_t dummy;
@@ -119,7 +141,5 @@
headerSize += 4 + quantizationTablesSize;
}
- // Note: We assume that there are no 'restart markers'
-
return headerSize;
}
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/JPEGVideoRTPSource.cpp
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// JPEG Video (RFC 2435) RTP Sources
// Implementation
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/JPEGVideoSource.cpp
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// JPEG video sources
// Implementation
@@ -35,6 +35,11 @@
return NULL;
}
+u_int16_t JPEGVideoSource::restartInterval() {
+ // Default implementation
+ return 0;
+}
+
Boolean JPEGVideoSource::isJPEGVideoSource() const {
return True;
}
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/Locale.cpp
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// Support for temporarily setting the locale (e.g., to POSIX) for (e.g.) parsing or printing
// floating-point numbers in protocol headers, or calling toupper()/tolower() on human-input strings.
// Implementation
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/MP3ADU.cpp
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// 'ADU' MP3 streams (for improved loss-tolerance)
// Implementation
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/MP3ADURTPSink.cpp
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// RTP sink for 'ADUized' MP3 frames ("mpa-robust")
// Implementation
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/MP3ADURTPSource.cpp
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// RTP source for 'ADUized' MP3 frames ("mpa-robust")
// Implementation
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/MP3ADUTranscoder.cpp
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// Transcoder for ADUized MP3 frames
// Implementation
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/MP3ADUdescriptor.cpp
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// Descriptor preceding frames of 'ADU' MP3 streams (for improved loss-tolerance)
// Implementation
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/MP3ADUdescriptor.hh
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// Descriptor preceding frames of 'ADU' MP3 streams (for improved loss-tolerance)
// C++ header
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/MP3ADUinterleaving.cpp
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// Interleaving of MP3 ADUs
// Implementation
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/MP3AudioFileServerMediaSubsession.cpp
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// A 'ServerMediaSubsession' object that creates new, unicast, "RTPSink"s
// on demand, from a MP3 audio file.
// (Actually, any MPEG-1 or MPEG-2 audio file should work.)
@@ -48,7 +48,7 @@
}
void MP3AudioFileServerMediaSubsession
-::seekStreamSource(FramedSource* inputSource, double seekNPT) {
+::seekStreamSource(FramedSource* inputSource, double seekNPT, double streamDuration) {
MP3FileSource* mp3Source;
if (fGenerateADUs) {
// "inputSource" is a filter; use its input source instead.
@@ -73,7 +73,7 @@
mp3Source = (MP3FileSource*)inputSource;
}
- mp3Source->seekWithinFile(seekNPT);
+ mp3Source->seekWithinFile(seekNPT, streamDuration);
}
void MP3AudioFileServerMediaSubsession
@@ -104,7 +104,6 @@
FramedSource* MP3AudioFileServerMediaSubsession
::createNewStreamSource(unsigned /*clientSessionId*/, unsigned& estBitrate) {
- estBitrate = 128; // kbps, estimate
FramedSource* streamSource;
do {
@@ -113,6 +112,14 @@
if (streamSource == NULL) break;
fFileDuration = mp3Source->filePlayTime();
+ unsigned fileSize = mp3Source->fileSize();
+ // Use this, plus the duration, to estimate the stream's bitrate:
+ if (fileSize > 0 && fFileDuration > 0.0) {
+ estBitrate = (unsigned)(fileSize/(125*fFileDuration) + 0.5); // kbps, rounded
+ } else {
+ estBitrate = 128; // kbps, estimate
+ }
+
if (fGenerateADUs) {
// Add a filter that converts the source MP3s to ADUs:
streamSource = ADUFromMP3Source::createNew(envir(), streamSource);
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/MP3FileSource.cpp
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// MP3 File Sources
// Implementation
@@ -64,12 +64,43 @@
return fStreamState->filePlayTime();
}
+unsigned MP3FileSource::fileSize() const {
+ return fStreamState->fileSize();
+}
+
void MP3FileSource::setPresentationTimeScale(unsigned scale) {
fStreamState->setPresentationTimeScale(scale);
}
-void MP3FileSource::seekWithinFile(double seekNPT) {
- fStreamState->seekWithinFile(seekNPT);
+void MP3FileSource::seekWithinFile(double seekNPT, double streamDuration) {
+ float fileDuration = filePlayTime();
+
+ // First, make sure that 0.0 <= seekNPT <= seekNPT + streamDuration <= fileDuration
+ if (seekNPT < 0.0) {
+ seekNPT = 0.0;
+ } else if (seekNPT > fileDuration) {
+ seekNPT = fileDuration;
+ }
+ if (streamDuration < 0.0) {
+ streamDuration = 0.0;
+ } else if (seekNPT + streamDuration > fileDuration) {
+ streamDuration = fileDuration - seekNPT;
+ }
+
+ float seekFraction = (float)seekNPT/fileDuration;
+ unsigned seekByteNumber = fStreamState->getByteNumberFromPositionFraction(seekFraction);
+ fStreamState->seekWithinFile(seekByteNumber);
+
+ fLimitNumBytesToStream = False; // by default
+ if (streamDuration > 0.0) {
+ float endFraction = (float)(seekNPT + streamDuration)/fileDuration;
+ unsigned endByteNumber = fStreamState->getByteNumberFromPositionFraction(endFraction);
+ if (endByteNumber > seekByteNumber) { // sanity check
+ fNumBytesToStream = endByteNumber - seekByteNumber;
+ fLimitNumBytesToStream = True;
+ }
+ } else {
+ }
}
void MP3FileSource::getAttributes() const {
@@ -100,6 +131,8 @@
}
Boolean MP3FileSource::doGetNextFrame1() {
+ if (fLimitNumBytesToStream && fNumBytesToStream == 0) return False; // we've already streamed as much as we were asked for
+
if (!fHaveJustInitialized) {
if (fStreamState->findNextHeader(fPresentationTime) == 0) return False;
} else {
@@ -116,6 +149,7 @@
fFrameSize = fMaxSize;
return False;
}
+ if (fNumBytesToStream > fFrameSize) fNumBytesToStream -= fFrameSize; else fNumBytesToStream = 0;
return True;
}
@@ -135,6 +169,9 @@
fStreamState->checkForXingHeader(); // in case this is a VBR file
fHaveJustInitialized = True;
+ fLimitNumBytesToStream = False;
+ fNumBytesToStream = 0;
+
// Hack: It's possible that our environment's 'result message' has been
// reset within this function, so set it again to our name now:
envir().setResultMsg(name());
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/MP3HTTPSource.cpp
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// MP3 HTTP Sources
// Implementation
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/MP3Internals.cpp
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// MP3 internal implementation details
// Implementation
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/MP3Internals.hh
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// MP3 internal implementation details
// C++ header
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/MP3InternalsHuffman.cpp
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// MP3 internal implementation details (Huffman encoding)
// Implementation
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/MP3InternalsHuffman.hh
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// MP3 internal implementation details (Huffman encoding)
// C++ header
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/MP3InternalsHuffmanTable.cpp
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// MP3 internal implementation details (Huffman encoding)
// Table
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/MP3StreamState.cpp
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// A class encapsulating the state of a MP3 stream
// Implementation
@@ -86,21 +86,10 @@
return numFramesInFile*(pt.tv_sec + pt.tv_usec/(float)MILLION);
}
-void MP3StreamState::seekWithinFile(double seekNPT) {
- if (fFidIsReallyASocket) return; // it's not seekable
-
- float fileDuration = filePlayTime();
- if (seekNPT < 0.0) {
- seekNPT = 0.0;
- } else if (seekNPT > fileDuration) {
- seekNPT = fileDuration;
- }
- float seekFraction = (float)seekNPT/fileDuration;
-
- unsigned seekByteNumber;
+unsigned MP3StreamState::getByteNumberFromPositionFraction(float fraction) {
if (fHasXingTOC) {
// The file is VBR, with a Xing TOC; use it to determine which byte to seek to:
- float percent = seekFraction*100.0f;
+ float percent = fraction*100.0f;
unsigned a = (unsigned)percent;
if (a > 99) a = 99;
@@ -111,14 +100,15 @@
} else {
fb = 256;
}
- float seekByteFraction = (fa + (fb-fa)*(percent-a))/256.0f;
-
- seekByteNumber = (unsigned)(seekByteFraction*fFileSize);
- } else {
- // Normal case: Treat the file as if it's CBR:
- seekByteNumber = (unsigned)(seekFraction*fFileSize);
+ fraction = (fa + (fb-fa)*(percent-a))/256.0f;
}
+ return (unsigned)(fraction*fFileSize);
+}
+
+void MP3StreamState::seekWithinFile(unsigned seekByteNumber) {
+ if (fFidIsReallyASocket) return; // it's not seekable
+
fseek(fFid, seekByteNumber, SEEK_SET);
}
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/MP3StreamState.hh
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// A class encapsulating the state of a MP3 stream
// C++ header
@@ -57,8 +57,10 @@
char const* fileName);
float filePlayTime() const; // in seconds
+ unsigned fileSize() const { return fFileSize; }
void setPresentationTimeScale(unsigned scale) { fPresentationTimeScale = scale; }
- void seekWithinFile(double seekNPT);
+ unsigned getByteNumberFromPositionFraction(float fraction); // 0.0 <= fraction <= 1.0
+ void seekWithinFile(unsigned seekByteNumber);
void checkForXingHeader(); // hack for Xing VBR files
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/MP3Transcoder.cpp
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// MP3 Transcoder
// Implementation
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/MPEG1or2AudioRTPSink.cpp
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// RTP sink for MPEG audio (RFC 2250)
// Implementation
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/MPEG1or2AudioRTPSource.cpp
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// MPEG-1 or MPEG-2 Audio RTP Sources
// Implementation
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/MPEG1or2AudioStreamFramer.cpp
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// A filter that breaks up an MPEG (1,2) audio elementary stream into frames
// Implementation
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/MPEG1or2Demux.cpp
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// Demultiplexer for a MPEG 1 or 2 Program Stream
// Implementation
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/MPEG1or2DemuxedElementaryStream.cpp
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// A MPEG 1 or 2 Elementary Stream, demultiplexed from a Program Stream
// Implementation
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/MPEG1or2DemuxedServerMediaSubsession.cpp
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// A 'ServerMediaSubsession' object that creates new, unicast, "RTPSink"s
// on demand, from a MPEG-1 or 2 demuxer.
// Implementation
@@ -94,7 +94,7 @@
}
void MPEG1or2DemuxedServerMediaSubsession
-::seekStreamSource(FramedSource* inputSource, double seekNPT) {
+::seekStreamSource(FramedSource* inputSource, double seekNPT, double /*streamDuration*/) {
float const dur = duration();
unsigned const size = fOurDemux.fileSize();
unsigned absBytePosition = dur == 0.0 ? 0 : (unsigned)((seekNPT/dur)*size);
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/MPEG1or2FileServerDemux.cpp
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// A server demultiplexer for a MPEG 1 or 2 Program Stream
// Implementation
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/MPEG1or2VideoFileServerMediaSubsession.cpp
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// A 'ServerMediaSubsession' object that creates new, unicast, "RTPSink"s
// on demand, from a MPEG-1 or 2 Elementary Stream video file.
// Implementation
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/MPEG1or2VideoHTTPSink.cpp
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// A HTTP Sink specifically for MPEG Video
// Implementation
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/MPEG1or2VideoRTPSink.cpp
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// RTP sink for MPEG video (RFC 2250)
// Implementation
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/MPEG1or2VideoRTPSource.cpp
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// MPEG-1 or MPEG-2 Video RTP Sources
// Implementation
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/MPEG1or2VideoStreamDiscreteFramer.cpp
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// A simplified version of "MPEG1or2VideoStreamFramer" that takes only
// complete, discrete frames (rather than an arbitrary byte stream) as input.
// This avoids the parsing and data copying overhead of the full
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/MPEG1or2VideoStreamFramer.cpp
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// A filter that breaks up an MPEG 1 or 2 video elementary stream into
// frames for: Video_Sequence_Header, GOP_Header, Picture_Header
// Implementation
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/MPEG2IndexFromTransportStream.cpp
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// A filter that produces a sequence of I-frame indices from a MPEG-2 Transport Stream
// Implementation
@@ -24,10 +24,16 @@
enum RecordType {
RECORD_UNPARSED = 0,
- RECORD_VSH = 1,
+ RECORD_VSH = 1, // a MPEG Video Sequence Header
RECORD_GOP = 2,
RECORD_PIC_NON_IFRAME = 3, // includes slices
RECORD_PIC_IFRAME = 4, // includes slices
+ RECORD_NAL_SPS = 5, // H.264
+ RECORD_NAL_PPS = 6, // H.264
+ RECORD_NAL_SEI = 7, // H.264
+ RECORD_NAL_NON_IFRAME = 8, // H.264
+ RECORD_NAL_IFRAME = 9, // H.264
+ RECORD_NAL_OTHER = 10, // H.264
RECORD_JUNK
};
@@ -68,6 +74,12 @@
"GOP",
"PIC(non-I-frame)",
"PIC(I-frame)",
+ "SPS (H.264)",
+ "PPS (H.264)",
+ "SEI (H.264)",
+ "H.264 non-I-frame",
+ "H.264 I-frame",
+ "other NAL unit (H.264)",
"JUNK"
};
UsageEnvironment& operator<<(UsageEnvironment& env, IndexRecord& r) {
@@ -101,7 +113,7 @@
::MPEG2IFrameIndexFromTransportStream(UsageEnvironment& env,
FramedSource* inputSource)
: FramedFilter(env, inputSource),
- fInputTransportPacketCounter((unsigned)-1), fClosureNumber(0),
+ fIsH264(False), fInputTransportPacketCounter((unsigned)-1), fClosureNumber(0),
fLastContinuityCounter(~0),
fFirstPCR(0.0), fLastPCR(0.0), fHaveSeenFirstPCR(False),
fPMT_PID(0x10), fVideo_PID(0xE0), // default values
@@ -156,13 +168,15 @@
presentationTime, durationInMicroseconds);
}
+#define TRANSPORT_SYNC_BYTE 0x47
+
void MPEG2IFrameIndexFromTransportStream
::afterGettingFrame1(unsigned frameSize,
unsigned numTruncatedBytes,
struct timeval presentationTime,
unsigned durationInMicroseconds) {
- if (frameSize < TRANSPORT_PACKET_SIZE || fInputBuffer[0] != 0x47/*sync byte*/) {
- if (fInputBuffer[0] != 0x47) {
+ if (frameSize < TRANSPORT_PACKET_SIZE || fInputBuffer[0] != TRANSPORT_SYNC_BYTE) {
+ if (fInputBuffer[0] != TRANSPORT_SYNC_BYTE) {
envir() << "Bad TS sync byte: 0x" << fInputBuffer[0] << "\n";
}
// Handle this as if the source ended:
@@ -309,8 +323,9 @@
while (size >= 9) {
u_int8_t stream_type = pkt[0];
u_int16_t elementary_PID = ((pkt[1]&0x1F)<<8) | pkt[2];
- if (stream_type == 1 || stream_type == 2) {
- fVideo_PID = elementary_PID;
+ if (stream_type == 1 || stream_type == 2 || stream_type == 0x1B/*H.264 video*/) {
+ if (stream_type == 0x1B) fIsH264 = True;
+ fVideo_PID = elementary_PID;
return;
}
@@ -382,8 +397,9 @@
// At this point, we have a queue of >=0 (unparsed) index records, representing
// the data in the parse buffer from "fParseBufferFrameStart"
// to "fParseBufferDataEnd". We now parse through this data, looking for
- // a complete 'frame' (where a 'frame', in this case, means
- // a Video Sequence Header, GOP Header, Picture Header, or Slice).
+ // a complete 'frame', where a 'frame', in this case, means:
+ // for MPEG video: a Video Sequence Header, GOP Header, Picture Header, or Slice
+ // for H.264 video: a NAL unit
// Inspect the frame's initial 4-byte code, to make sure it starts with a system code:
if (fParseBufferDataEnd-fParseBufferFrameStart < 4) return False; // not enough data
@@ -406,6 +422,7 @@
}
unsigned char curCode = p[3];
+ if (fIsH264) curCode &= 0x1F; // nal_unit_type
RecordType curRecordType;
unsigned char nextCode;
switch (curCode) {
@@ -430,14 +447,39 @@
}
break;
}
- default: { // picture (including slices)
- curRecordType = RECORD_PIC_NON_IFRAME; // may get changed to IFRAME later
- while (1) {
+ case 1: // Coded slice of a non-IDR picture (H.264)
+ curRecordType = RECORD_NAL_NON_IFRAME;
+ if (!parseToNextCode(nextCode)) return False;
+ break;
+ case 5: // Coded slice of an IDR picture (H.264)
+ curRecordType = RECORD_NAL_IFRAME;
+ if (!parseToNextCode(nextCode)) return False;
+ break;
+ case 6: // Supplemental enhancement information (SEI) (H.264)
+ curRecordType = RECORD_NAL_SEI;
+ if (!parseToNextCode(nextCode)) return False;
+ break;
+ case 7: // Sequence parameter set (SPS) (H.264)
+ curRecordType = RECORD_NAL_SPS;
+ if (!parseToNextCode(nextCode)) return False;
+ break;
+ case 8: // Picture parameter set (PPS) (H.264)
+ curRecordType = RECORD_NAL_PPS;
+ if (!parseToNextCode(nextCode)) return False;
+ break;
+ default: { // picture (including slices), or some other H.264 NAL unit
+ if (fIsH264) {
+ curRecordType = RECORD_NAL_OTHER;
if (!parseToNextCode(nextCode)) return False;
- if (nextCode == VIDEO_SEQUENCE_START_CODE || nextCode == VISUAL_OBJECT_SEQUENCE_START_CODE ||
- nextCode == GROUP_START_CODE || nextCode == GROUP_VOP_START_CODE ||
- nextCode == PICTURE_START_CODE || nextCode == VOP_START_CODE) break;
- fParseBufferParseEnd += 4; // skip over the code that we just saw
+ } else {
+ curRecordType = RECORD_PIC_NON_IFRAME; // may get changed to IFRAME later
+ while (1) {
+ if (!parseToNextCode(nextCode)) return False;
+ if (nextCode == VIDEO_SEQUENCE_START_CODE || nextCode == VISUAL_OBJECT_SEQUENCE_START_CODE ||
+ nextCode == GROUP_START_CODE || nextCode == GROUP_VOP_START_CODE ||
+ nextCode == PICTURE_START_CODE || nextCode == VOP_START_CODE) break;
+ fParseBufferParseEnd += 4; // skip over the code that we just saw
+ }
}
break;
}
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/MPEG2TransportFileServerMediaSubsession.cpp
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// A 'ServerMediaSubsession' object that creates new, unicast, "RTPSink"s
// on demand, from a MPEG-2 Transport Stream file.
// Implementation
@@ -26,10 +26,6 @@
#include "MPEG2TransportStreamFromESSource.hh"
#include "MPEG2TransportStreamFramer.hh"
-// We assume that the video - in the original Transport Stream file - is MPEG-2.
-// If, instead, it is MPEG-1, then change the following definition to 1:
-#define VIDEO_MPEG_VERSION 2
-
////////// ClientTrickPlayState definition //////////
// This class encapsulates the 'trick play' state for each current client (for
@@ -40,7 +36,7 @@
ClientTrickPlayState(MPEG2TransportStreamIndexFile* indexFile);
// Functions to bring "fNPT", "fTSRecordNum" and "fIxRecordNum" in sync:
- void updateStateFromNPT(double npt);
+ void updateStateFromNPT(double npt, double seekDuration);
void updateStateOnScaleChange();
void updateStateOnPlayChange(Boolean reverseToPreviousVSH);
@@ -72,12 +68,14 @@
char const* fileName,
char const* indexFileName,
Boolean reuseFirstSource) {
+ MPEG2TransportStreamIndexFile* indexFile;
if (indexFileName != NULL && reuseFirstSource) {
// It makes no sense to support trick play if all clients use the same source. Fix this:
env << "MPEG2TransportFileServerMediaSubsession::createNew(): ignoring the index file name, because \"reuseFirstSource\" is set\n";
- indexFileName = NULL;
+ indexFile = NULL;
+ } else {
+ indexFile = MPEG2TransportStreamIndexFile::createNew(env, indexFileName);
}
- MPEG2TransportStreamIndexFile* indexFile = MPEG2TransportStreamIndexFile::createNew(env, indexFileName);
return new MPEG2TransportFileServerMediaSubsession(env, fileName, indexFile,
reuseFirstSource);
}
@@ -154,16 +152,16 @@
}
void MPEG2TransportFileServerMediaSubsession
-::seekStream(unsigned clientSessionId, void* streamToken, double seekNPT) {
+::seekStream(unsigned clientSessionId, void* streamToken, double seekNPT, double streamDuration) {
if (fIndexFile != NULL) { // we support 'trick play'
ClientTrickPlayState* client = lookupClient(clientSessionId);
if (client != NULL) {
- client->updateStateFromNPT(seekNPT);
+ client->updateStateFromNPT(seekNPT, streamDuration);
}
}
// Call the original, default version of this routine:
- OnDemandServerMediaSubsession::seekStream(clientSessionId, streamToken, seekNPT);
+ OnDemandServerMediaSubsession::seekStream(clientSessionId, streamToken, seekNPT, streamDuration);
}
void MPEG2TransportFileServerMediaSubsession
@@ -194,8 +192,6 @@
FramedSource* MPEG2TransportFileServerMediaSubsession
::createNewStreamSource(unsigned clientSessionId, unsigned& estBitrate) {
- estBitrate = 5000; // kbps, estimate
-
// Create the video source:
unsigned const inputDataChunkSize
= TRANSPORT_PACKETS_PER_NETWORK_PACKET*TRANSPORT_PACKET_SIZE;
@@ -204,6 +200,14 @@
if (fileSource == NULL) return NULL;
fFileSize = fileSource->fileSize();
+ // Use the file size and the duration to estimate the stream's bitrate:
+ if (fFileSize > 0 && fDuration > 0.0) {
+ estBitrate = (unsigned)((int64_t)fFileSize/(125*fDuration) + 0.5); // kbps, rounded
+ } else {
+ estBitrate = 5000; // kbps, estimate
+ }
+
+
// Create a framer for the Transport Stream:
MPEG2TransportStreamFramer* framer
= MPEG2TransportStreamFramer::createNew(envir(), fileSource);
@@ -262,7 +266,7 @@
fTSRecordNum(0), fIxRecordNum(0) {
}
-void ClientTrickPlayState::updateStateFromNPT(double npt) {
+void ClientTrickPlayState::updateStateFromNPT(double npt, double streamDuration) {
fNPT = (float)npt;
// Map "fNPT" to the corresponding Transport Stream and Index record numbers:
unsigned long tsRecordNum, ixRecordNum;
@@ -281,6 +285,18 @@
fFramer->clearPIDStatusTable();
}
+
+ unsigned long numTSRecordsToStream = 0;
+ if (streamDuration > 0.0) {
+ // Use the index file to figure out how many Transport Packets we get to stream:
+ unsigned long toTSRecordNum, toIxRecordNum;
+ float toNPT = (float)(fNPT + streamDuration);
+ fIndexFile->lookupTSPacketNumFromNPT(toNPT, toTSRecordNum, toIxRecordNum);
+ if (toTSRecordNum > tsRecordNum) { // sanity check
+ numTSRecordsToStream = toTSRecordNum - tsRecordNum;
+ }
+ }
+ fFramer->setNumTSPacketsToStream(numTSRecordsToStream);
}
void ClientTrickPlayState::updateStateOnScaleChange() {
@@ -304,7 +320,7 @@
// And generate a Transport Stream from this:
fTrickPlaySource = MPEG2TransportStreamFromESSource::createNew(env);
- fTrickPlaySource->addNewVideoSource(fTrickModeFilter, VIDEO_MPEG_VERSION);
+ fTrickPlaySource->addNewVideoSource(fTrickModeFilter, fIndexFile->mpegVersion());
fFramer->changeInputSource(fTrickPlaySource);
} else {
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/MPEG2TransportStreamFramer.cpp
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// A filter that passes through (unchanged) chunks that contain an integral number
// of MPEG-2 Transport Stream packets, but returning (in "fDurationInMicroseconds")
// an updated estimate of the time gap between chunks.
@@ -73,7 +73,8 @@
MPEG2TransportStreamFramer
::MPEG2TransportStreamFramer(UsageEnvironment& env, FramedSource* inputSource)
: FramedFilter(env, inputSource),
- fTSPacketCount(0), fTSPacketDurationEstimate(0.0), fTSPCRCount(0) {
+ fTSPacketCount(0), fTSPacketDurationEstimate(0.0), fTSPCRCount(0),
+ fLimitNumTSPacketsToStream(False), fNumTSPacketsToStream(0) {
fPIDStatusTable = HashTable::create(ONE_WORD_HASH_KEYS);
}
@@ -89,7 +90,22 @@
}
}
+void MPEG2TransportStreamFramer::setNumTSPacketsToStream(unsigned long numTSRecordsToStream) {
+ fNumTSPacketsToStream = numTSRecordsToStream;
+ fLimitNumTSPacketsToStream = numTSRecordsToStream > 0;
+}
+
void MPEG2TransportStreamFramer::doGetNextFrame() {
+ if (fLimitNumTSPacketsToStream) {
+ if (fNumTSPacketsToStream == 0) {
+ handleClosure(this);
+ return;
+ }
+ if (fNumTSPacketsToStream*TRANSPORT_PACKET_SIZE < fMaxSize) {
+ fMaxSize = fNumTSPacketsToStream*TRANSPORT_PACKET_SIZE;
+ }
+ }
+
// Read directly from our input source into our client's buffer:
fFrameSize = 0;
fInputSource->getNextFrame(fTo, fMaxSize,
@@ -120,6 +136,7 @@
struct timeval presentationTime) {
fFrameSize += frameSize;
unsigned const numTSPackets = fFrameSize/TRANSPORT_PACKET_SIZE;
+ fNumTSPacketsToStream -= numTSPackets;
fFrameSize = numTSPackets*TRANSPORT_PACKET_SIZE; // an integral # of TS packets
if (fFrameSize == 0) {
// We didn't read a complete TS packet; assume that the input source has closed.
@@ -216,7 +233,7 @@
// (This can produce more accurate estimates for wildly VBR streams.)
double meanPCRPeriod = 0.0;
if (fTSPCRCount > 0) {
- meanPCRPeriod=(double)fTSPacketCount/fTSPCRCount;
+ meanPCRPeriod = (double)fTSPacketCount/fTSPCRCount;
if (fTSPacketCount - pidStatus->lastPacketNum < meanPCRPeriod*PCR_PERIOD_VARIATION_RATIO) return;
}
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/MPEG2TransportStreamFromESSource.cpp
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// A filter for converting one or more MPEG Elementary Streams
// to a MPEG-2 Transport Stream
// Implementation
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/MPEG2TransportStreamFromPESSource.cpp
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// A filter for converting a stream of MPEG PES packets to a MPEG-2 Transport Stream
// Implementation
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/MPEG2TransportStreamIndexFile.cpp
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// A class that encapsulates MPEG-2 Transport Stream 'index files'/
// These index files are used to implement 'trick play' operations
// (seek-by-time, fast forward, reverse play) on Transport Stream files.
@@ -27,7 +27,7 @@
MPEG2TransportStreamIndexFile
::MPEG2TransportStreamIndexFile(UsageEnvironment& env, char const* indexFileName)
: Medium(env),
- fFileName(strDup(indexFileName)), fFid(NULL), fCurrentIndexRecordNum(0),
+ fFileName(strDup(indexFileName)), fFid(NULL), fMPEGVersion(0), fCurrentIndexRecordNum(0),
fCachedPCR(0.0f), fCachedTSPacketNumber(0), fNumIndexRecords(0) {
// Get the file size, to determine how many index records it contains:
u_int64_t indexFileSize = GetFileSize(indexFileName, NULL);
@@ -109,7 +109,7 @@
ixFound = ixRight;
// "Rewind' until we reach the start of a Video Sequence or GOP header:
- success = rewindToVSH(ixFound);
+ success = rewindToCleanPoint(ixFound);
} while (0);
if (success && readIndexRecord(ixFound)) {
@@ -126,7 +126,7 @@
}
void MPEG2TransportStreamIndexFile
-::lookupPCRFromTSPacketNum(unsigned long& tsPacketNumber, Boolean reverseToPreviousVSH,
+::lookupPCRFromTSPacketNum(unsigned long& tsPacketNumber, Boolean reverseToPreviousCleanPoint,
float& pcr, unsigned long& indexRecordNumber) {
if (tsPacketNumber == 0 || fNumIndexRecords == 0) { // Fast-track a common case:
pcr = 0.0f;
@@ -173,9 +173,9 @@
if (ixRight-ixLeft > 1 || tsPacketNumber <= tsLeft || tsPacketNumber > tsRight) break; // bad PCR values in index file?
ixFound = ixRight;
- if (reverseToPreviousVSH) {
+ if (reverseToPreviousCleanPoint) {
// "Rewind' until we reach the start of a Video Sequence or GOP header:
- success = rewindToVSH(ixFound);
+ success = rewindToCleanPoint(ixFound);
} else {
success = True;
}
@@ -185,7 +185,7 @@
// Return (and cache) information from record "ixFound":
pcr = fCachedPCR = pcrFromBuf();
fCachedTSPacketNumber = tsPacketNumFromBuf();
- if (reverseToPreviousVSH) tsPacketNumber = fCachedTSPacketNumber;
+ if (reverseToPreviousCleanPoint) tsPacketNumber = fCachedTSPacketNumber;
indexRecordNumber = fCachedIndexRecordNumber = ixFound;
} else {
// An error occurred: Return the default values, for tsPacketNumber == 0:
@@ -215,6 +215,16 @@
return pcrFromBuf();
}
+int MPEG2TransportStreamIndexFile::mpegVersion() {
+ if (fMPEGVersion != 0) return fMPEGVersion; // we already know it
+
+ // Read the first index record, and figure out the MPEG version from its type:
+ if (!readOneIndexRecord(0)) return 0; // unknown; perhaps the indecx file is empty?
+
+ setMPEGVersionFromRecordType(recordTypeFromBuf());
+ return fMPEGVersion;
+}
+
Boolean MPEG2TransportStreamIndexFile::openFid() {
if (fFid == NULL && fFileName != NULL) {
if ((fFid = OpenInputFile(envir(), fFileName)) != NULL) {
@@ -271,33 +281,57 @@
return (fBuf[10]<<24) | (fBuf[9]<<16) | (fBuf[8]<<8) | fBuf[7];
}
-Boolean MPEG2TransportStreamIndexFile::rewindToVSH(unsigned long&ixFound) {
- Boolean success = False;
+void MPEG2TransportStreamIndexFile::setMPEGVersionFromRecordType(u_int8_t recordType) {
+ if (fMPEGVersion != 0) return; // we already know it
+
+ u_int8_t const recordTypeWithoutStartBit = recordType&~0x80;
+ if (recordTypeWithoutStartBit >= 1 && recordTypeWithoutStartBit <= 4) fMPEGVersion = 2;
+ else if (recordTypeWithoutStartBit >= 5 && recordTypeWithoutStartBit <= 10) fMPEGVersion = 5; // represents H.264
+}
+
+Boolean MPEG2TransportStreamIndexFile::rewindToCleanPoint(unsigned long&ixFound) {
+ Boolean success = False; // until we learn otherwise
while (ixFound > 0) {
if (!readIndexRecord(ixFound)) break;
u_int8_t recordType = recordTypeFromBuf();
- if ((recordType&0x80) != 0 && (recordType&0x7F) <= 2/*GOP*/) {
- if ((recordType&0x7F) == 2) {
- // This is a GOP. Hack: If the preceding record is for a Video Sequence Header,
- // then use it instead:
- unsigned long newIxFound = ixFound;
-
- while (--newIxFound > 0) {
- if (!readIndexRecord(newIxFound)) break;
- recordType = recordTypeFromBuf();
- if ((recordType&0x7F) != 1) break; // not a Video Sequence Header
- if ((recordType&0x80) != 0) { // this is the start of the VSH; use it
- ixFound = newIxFound;
- break;
- }
+ setMPEGVersionFromRecordType(recordType);
+
+ // A 'clean point' is the start of a 'frame' from which a decoder can cleanly resume handling the stream:
+ // For H.264, this is a SPS. For MPEG-2, this is a Video Sequence Header, or a GOP.
+
+ if ((recordType&0x80) != 0) { // This is the start of a 'frame'
+ recordType &=~ 0x80; // remove the 'start of frame' bit
+ if (fMPEGVersion == 5/*H.264*/) {
+ if (recordType == 5/*SPS*/) {
+ success = True;
+ break;
}
+ } else {
+ if (recordType == 1/*VSH*/) {
+ success = True;
+ break;
+ } else if (recordType == 2/*GOP*/) {
+ // Hack: If the preceding record is for a Video Sequence Header, then use it instead:
+ unsigned long newIxFound = ixFound;
+
+ while (--newIxFound > 0) {
+ if (!readIndexRecord(newIxFound)) break;
+ recordType = recordTypeFromBuf();
+ if ((recordType&0x7F) != 1) break; // not a Video Sequence Header
+ if ((recordType&0x80) != 0) { // this is the start of the VSH; use it
+ ixFound = newIxFound;
+ break;
+ }
+ }
+ }
+ success = True;
+ break;
}
- // Record 'ixFound' as appropriate to return:
- success = True;
- break;
}
+
+ // Keep checking, from the previous record:
--ixFound;
}
if (ixFound == 0) success = True; // use record 0 anyway
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/MPEG2TransportStreamMultiplexor.cpp
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// A class for generating MPEG-2 Transport Stream from one or more input
// Elementary Stream data sources
// Implementation
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/MPEG2TransportStreamTrickModeFilter.cpp
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// A filter that converts a MPEG Transport Stream file - with corresponding index file
// - to a corresponding Video Elementary Stream. It also uses a "scale" parameter
// to implement 'trick mode' (fast forward or reverse play, using I-frames) on
@@ -62,9 +62,9 @@
return True;
}
-#define isIFrameStart(type) ((type) == 0x81) // actually, a Video Sequence Header
-// This relies upon the fact that I-frames are always preceded by VSH and GOP
-#define isNonIFrameStart(type) ((type) == 0x83)
+#define isIFrameStart(type) ((type) == 0x81/*actually, a VSH*/ || (type) == 0x85/*actually, a SPS*//*for H.264*/)
+ // This relies upon I-frames always being preceded by a VSH+GOP (for MPEG-2 data) and by a SPS (for H.264 data)
+#define isNonIFrameStart(type) ((type) == 0x83 || (type) == 0x88/*for H.264*/)
void MPEG2TransportStreamTrickModeFilter::doGetNextFrame() {
// fprintf(stderr, "#####DGNF1\n");
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/MPEG4ESVideoRTPSink.cpp
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// RTP sink for MPEG-4 Elementary Stream video (RFC 3016)
// Implementation
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/MPEG4ESVideoRTPSource.cpp
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// MP4V-ES video RTP stream sources
// Implementation
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/MPEG4GenericRTPSink.cpp
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// MPEG4-GENERIC ("audio", "video", or "application") RTP stream sinks
// Implementation
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/MPEG4GenericRTPSource.cpp
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// MPEG4-GENERIC ("audio", "video", or "application") RTP stream sources
// Implementation
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/MPEG4LATMAudioRTPSink.cpp
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// RTP sink for MPEG-4 audio, using LATM multiplexing (RFC 3016)
// Implementation
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/MPEG4LATMAudioRTPSource.cpp
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// MPEG-4 audio, using LATM multiplexing
// Implementation
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/MPEG4VideoFileServerMediaSubsession.cpp
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// A 'ServerMediaSubsession' object that creates new, unicast, "RTPSink"s
// on demand, from a MPEG-4 video file.
// Implementation
@@ -35,11 +35,11 @@
::MPEG4VideoFileServerMediaSubsession(UsageEnvironment& env,
char const* fileName, Boolean reuseFirstSource)
: FileServerMediaSubsession(env, fileName, reuseFirstSource),
- fDoneFlag(0) {
+ fAuxSDPLine(NULL), fDoneFlag(0), fDummyRTPSink(NULL) {
}
-MPEG4VideoFileServerMediaSubsession
-::~MPEG4VideoFileServerMediaSubsession() {
+MPEG4VideoFileServerMediaSubsession::~MPEG4VideoFileServerMediaSubsession() {
+ delete[] fAuxSDPLine;
}
static void afterPlayingDummy(void* clientData) {
@@ -62,7 +62,13 @@
}
void MPEG4VideoFileServerMediaSubsession::checkForAuxSDPLine1() {
- if (fDummyRTPSink->auxSDPLine() != NULL) {
+ if (fAuxSDPLine != NULL) {
+ // Signal the event loop that we're done:
+ setDoneFlag();
+ } else if (fDummyRTPSink != NULL && fDummyRTPSink->auxSDPLine() != NULL) {
+ fAuxSDPLine= strDup(fDummyRTPSink->auxSDPLine());
+ fDummyRTPSink = NULL;
+
// Signal the event loop that we're done:
setDoneFlag();
} else {
@@ -73,24 +79,25 @@
}
}
-char const* MPEG4VideoFileServerMediaSubsession
-::getAuxSDPLine(RTPSink* rtpSink, FramedSource* inputSource) {
- // Note: For MPEG-4 video files, the 'config' information isn't known
- // until we start reading the file. This means that "rtpSink"s
- // "auxSDPLine()" will be NULL initially, and we need to start reading
- // data from our file until this changes.
- fDummyRTPSink = rtpSink;
+char const* MPEG4VideoFileServerMediaSubsession::getAuxSDPLine(RTPSink* rtpSink, FramedSource* inputSource) {
+ if (fAuxSDPLine != NULL) return fAuxSDPLine; // it's already been set up (for a previous client)
+
+ if (fDummyRTPSink == NULL) { // we're not already setting it up for another, concurrent stream
+ // Note: For MPEG-4 video files, the 'config' information isn't known
+ // until we start reading the file. This means that "rtpSink"s
+ // "auxSDPLine()" will be NULL initially, and we need to start reading data from our file until this changes.
+ fDummyRTPSink = rtpSink;
- // Start reading the file:
- fDummyRTPSink->startPlaying(*inputSource, afterPlayingDummy, this);
+ // Start reading the file:
+ fDummyRTPSink->startPlaying(*inputSource, afterPlayingDummy, this);
- // Check whether the sink's 'auxSDPLine()' is ready:
- checkForAuxSDPLine(this);
+ // Check whether the sink's 'auxSDPLine()' is ready:
+ checkForAuxSDPLine(this);
+ }
envir().taskScheduler().doEventLoop(&fDoneFlag);
- char const* auxSDPLine = fDummyRTPSink->auxSDPLine();
- return auxSDPLine;
+ return fAuxSDPLine;
}
FramedSource* MPEG4VideoFileServerMediaSubsession
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/MPEG4VideoStreamDiscreteFramer.cpp
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// A simplified version of "MPEG4VideoStreamFramer" that takes only complete,
// discrete frames (rather than an arbitrary byte stream) as input.
// This avoids the parsing and data copying overhead of the full
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/MPEG4VideoStreamFramer.cpp
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// A filter that breaks up an MPEG-4 video elementary stream into
// frames for:
// - Visual Object Sequence (VS) Header + Visual Object (VO) Header
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/MPEGVideoStreamFramer.cpp
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// A filter that breaks up an MPEG video elementary stream into
// headers and frames
// Implementation
@@ -165,7 +165,7 @@
= (fFrameRate == 0.0 || ((int)fPictureCount) < 0) ? 0
: (unsigned)((fPictureCount*1000000)/fFrameRate);
#ifdef DEBUG
- fprintf(stderr, "fDurationInMicroseconds: %d ((%d*1000000)/%f)\n", fDurationInMicroseconds, fPictureCount, fFrameRate);
+ fprintf(stderr, "%d bytes @%u.%06d, fDurationInMicroseconds: %d ((%d*1000000)/%f)\n", acquiredFrameSize, fPresentationTime.tv_sec, fPresentationTime.tv_usec, fDurationInMicroseconds, fPictureCount, fFrameRate);
#endif
fPictureCount = 0;
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/MPEGVideoStreamParser.cpp
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// An abstract parser for MPEG video streams
// Implementation
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/MPEGVideoStreamParser.hh
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// An abstract parser for MPEG video streams
// C++ header
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/Makefile.tail
^
|
@@ -11,7 +11,7 @@
$(CPLUSPLUS_COMPILER) -c $(CPLUSPLUS_FLAGS) $<
MP3_SOURCE_OBJS = MP3FileSource.$(OBJ) MP3HTTPSource.$(OBJ) MP3Transcoder.$(OBJ) MP3ADU.$(OBJ) MP3ADUdescriptor.$(OBJ) MP3ADUinterleaving.$(OBJ) MP3ADUTranscoder.$(OBJ) MP3StreamState.$(OBJ) MP3Internals.$(OBJ) MP3InternalsHuffman.$(OBJ) MP3InternalsHuffmanTable.$(OBJ) MP3ADURTPSource.$(OBJ)
-MPEG_SOURCE_OBJS = MPEG1or2Demux.$(OBJ) MPEG1or2DemuxedElementaryStream.$(OBJ) MPEGVideoStreamFramer.$(OBJ) MPEG1or2VideoStreamFramer.$(OBJ) MPEG1or2VideoStreamDiscreteFramer.$(OBJ) MPEG4VideoStreamFramer.$(OBJ) MPEG4VideoStreamDiscreteFramer.$(OBJ) H264VideoStreamFramer.$(OBJ) MPEGVideoStreamParser.$(OBJ) MPEG1or2AudioStreamFramer.$(OBJ) MPEG1or2AudioRTPSource.$(OBJ) MPEG4LATMAudioRTPSource.$(OBJ) MPEG4ESVideoRTPSource.$(OBJ) MPEG4GenericRTPSource.$(OBJ) $(MP3_SOURCE_OBJS) MPEG1or2VideoRTPSource.$(OBJ) MPEG2TransportStreamMultiplexor.$(OBJ) MPEG2TransportStreamFromPESSource.$(OBJ) MPEG2TransportStreamFromESSource.$(OBJ) MPEG2TransportStreamFramer.$(OBJ) ADTSAudioFileSource.$(OBJ)
+MPEG_SOURCE_OBJS = MPEG1or2Demux.$(OBJ) MPEG1or2DemuxedElementaryStream.$(OBJ) MPEGVideoStreamFramer.$(OBJ) MPEG1or2VideoStreamFramer.$(OBJ) MPEG1or2VideoStreamDiscreteFramer.$(OBJ) MPEG4VideoStreamFramer.$(OBJ) MPEG4VideoStreamDiscreteFramer.$(OBJ) H264VideoStreamFramer.$(OBJ) H264VideoStreamDiscreteFramer.$(OBJ) MPEGVideoStreamParser.$(OBJ) MPEG1or2AudioStreamFramer.$(OBJ) MPEG1or2AudioRTPSource.$(OBJ) MPEG4LATMAudioRTPSource.$(OBJ) MPEG4ESVideoRTPSource.$(OBJ) MPEG4GenericRTPSource.$(OBJ) $(MP3_SOURCE_OBJS) MPEG1or2VideoRTPSource.$(OBJ) MPEG2TransportStreamMultiplexor.$(OBJ) MPEG2TransportStreamFromPESSource.$(OBJ) MPEG2TransportStreamFromESSource.$(OBJ) MPEG2TransportStreamFramer.$(OBJ) ADTSAudioFileSource.$(OBJ)
H263_SOURCE_OBJS = H263plusVideoRTPSource.$(OBJ) H263plusVideoStreamFramer.$(OBJ) H263plusVideoStreamParser.$(OBJ)
AC3_SOURCE_OBJS = AC3AudioStreamFramer.$(OBJ) AC3AudioRTPSource.$(OBJ)
DV_SOURCE_OBJS = DVVideoStreamFramer.$(OBJ) DVVideoRTPSource.$(OBJ)
@@ -33,10 +33,10 @@
RTP_OBJS = $(RTP_SOURCE_OBJS) $(RTP_SINK_OBJS) $(RTP_INTERFACE_OBJS)
RTCP_OBJS = RTCP.$(OBJ) rtcp_from_spec.$(OBJ)
-RTSP_OBJS = RTSPServer.$(OBJ) RTSPOverHTTPServer.$(OBJ) RTSPClient.$(OBJ) RTSPCommon.$(OBJ)
+RTSP_OBJS = RTSPServer.$(OBJ) RTSPClient.$(OBJ) RTSPCommon.$(OBJ)
SIP_OBJS = SIPClient.$(OBJ)
-SESSION_OBJS = MediaSession.$(OBJ) ServerMediaSession.$(OBJ) PassiveServerMediaSubsession.$(OBJ) OnDemandServerMediaSubsession.$(OBJ) FileServerMediaSubsession.$(OBJ) MPEG4VideoFileServerMediaSubsession.$(OBJ) H263plusVideoFileServerMediaSubsession.$(OBJ) WAVAudioFileServerMediaSubsession.$(OBJ) AMRAudioFileServerMediaSubsession.$(OBJ) MP3AudioFileServerMediaSubsession.$(OBJ) MPEG1or2VideoFileServerMediaSubsession.$(OBJ) MPEG1or2FileServerDemux.$(OBJ) MPEG1or2DemuxedServerMediaSubsession.$(OBJ) MPEG2TransportFileServerMediaSubsession.$(OBJ) ADTSAudioFileServerMediaSubsession.$(OBJ) DVVideoFileServerMediaSubsession.$(OBJ)
+SESSION_OBJS = MediaSession.$(OBJ) ServerMediaSession.$(OBJ) PassiveServerMediaSubsession.$(OBJ) OnDemandServerMediaSubsession.$(OBJ) FileServerMediaSubsession.$(OBJ) MPEG4VideoFileServerMediaSubsession.$(OBJ) H264VideoFileServerMediaSubsession.$(OBJ) H263plusVideoFileServerMediaSubsession.$(OBJ) WAVAudioFileServerMediaSubsession.$(OBJ) AMRAudioFileServerMediaSubsession.$(OBJ) MP3AudioFileServerMediaSubsession.$(OBJ) MPEG1or2VideoFileServerMediaSubsession.$(OBJ) MPEG1or2FileServerDemux.$(OBJ) MPEG1or2DemuxedServerMediaSubsession.$(OBJ) MPEG2TransportFileServerMediaSubsession.$(OBJ) ADTSAudioFileServerMediaSubsession.$(OBJ) DVVideoFileServerMediaSubsession.$(OBJ) AC3AudioFileServerMediaSubsession.$(OBJ)
QUICKTIME_OBJS = QuickTimeFileSink.$(OBJ) QuickTimeGenericRTPSource.$(OBJ)
AVI_OBJS = AVIFileSink.$(OBJ)
@@ -105,8 +105,10 @@
include/MPEG4VideoStreamFramer.hh: include/MPEGVideoStreamFramer.hh
MPEG4VideoStreamDiscreteFramer.$(CPP): include/MPEG4VideoStreamDiscreteFramer.hh
include/MPEG4VideoStreamDiscreteFramer.hh: include/MPEG4VideoStreamFramer.hh
-H264VideoStreamFramer.$(CPP): include/H264VideoStreamFramer.hh
-include/H264VideoStreamFramer.hh: include/FramedFilter.hh
+H264VideoStreamFramer.$(CPP): include/H264VideoStreamFramer.hh MPEGVideoStreamParser.hh BitVector.hh
+include/H264VideoStreamFramer.hh: include/MPEGVideoStreamFramer.hh
+H264VideoStreamDiscreteFramer.$(CPP): include/H264VideoStreamDiscreteFramer.hh
+include/H264VideoStreamDiscreteFramer.hh: include/H264VideoStreamFramer.hh
MPEGVideoStreamParser.$(CPP): MPEGVideoStreamParser.hh
MPEG1or2AudioStreamFramer.$(CPP): include/MPEG1or2AudioStreamFramer.hh StreamParser.hh MP3Internals.hh
include/MPEG1or2AudioStreamFramer.hh: include/FramedFilter.hh
@@ -149,7 +151,7 @@
MPEG2TransportStreamFromESSource.$(CPP): include/MPEG2TransportStreamFromESSource.hh
include/MPEG2TransportStreamFromESSource.hh: include/MPEG2TransportStreamMultiplexor.hh
MPEG2TransportStreamFramer.$(CPP): include/MPEG2TransportStreamFramer.hh
-include/MPEG2TransportStreamFramer.hh: include/FramedFilter.hh
+include/MPEG2TransportStreamFramer.hh: include/FramedFilter.hh include/MPEG2TransportStreamIndexFile.hh
ADTSAudioFileSource.$(CPP): include/ADTSAudioFileSource.hh include/InputFile.hh
include/ADTSAudioFileSource.hh: include/FramedFileSource.hh
H263plusVideoRTPSource.$(CPP): include/H263plusVideoRTPSource.hh
@@ -208,7 +210,7 @@
include/MPEG4ESVideoRTPSink.hh: include/VideoRTPSink.hh
H263plusVideoRTPSink.$(CPP): include/H263plusVideoRTPSink.hh
include/H263plusVideoRTPSink.hh: include/VideoRTPSink.hh
-H264VideoRTPSink.$(CPP): include/H264VideoRTPSink.hh include/H264VideoStreamFramer.hh
+H264VideoRTPSink.$(CPP): include/H264VideoRTPSink.hh include/H264VideoStreamFramer.hh include/Base64.hh
include/H264VideoRTPSink.hh: include/VideoRTPSink.hh include/FramedFilter.hh
DVVideoRTPSink.$(CPP): include/DVVideoRTPSink.hh
include/DVVideoRTPSink.hh: include/VideoRTPSink.hh include/DVVideoStreamFramer.hh
@@ -235,11 +237,9 @@
RTCP.$(CPP): include/RTCP.hh rtcp_from_spec.h
include/RTCP.hh: include/RTPSink.hh include/RTPSource.hh
rtcp_from_spec.$(C): rtcp_from_spec.h
-RTSPServer.$(CPP): include/RTSPServer.hh include/RTSPCommon.hh
+RTSPServer.$(CPP): include/RTSPServer.hh include/RTSPCommon.hh include/Base64.hh
include/RTSPServer.hh: include/ServerMediaSession.hh include/DigestAuthentication.hh include/RTSPCommon.hh
include/ServerMediaSession.hh: include/Media.hh include/RTPInterface.hh
-RTSPOverHTTPServer.$(CPP): include/RTSPOverHTTPServer.hh include/RTSPCommon.hh
-include/RTSPOverHTTPServer.hh: include/Media.hh
RTSPClient.$(CPP): include/RTSPClient.hh include/RTSPCommon.hh include/Base64.hh include/Locale.hh our_md5.h
include/RTSPClient.hh: include/MediaSession.hh include/DigestAuthentication.hh
RTSPCommon.$(CPP): include/RTSPCommon.hh include/Locale.hh
@@ -250,12 +250,14 @@
ServerMediaSession.$(CPP): include/ServerMediaSession.hh
PassiveServerMediaSubsession.$(CPP): include/PassiveServerMediaSubsession.hh
include/PassiveServerMediaSubsession.hh: include/ServerMediaSession.hh include/RTPSink.hh include/RTCP.hh
-OnDemandServerMediaSubsession.$(CPP): include/OnDemandServerMediaSubsession.hh include/RTCP.hh
-include/OnDemandServerMediaSubsession.hh: include/ServerMediaSession.hh include/RTPSink.hh
+OnDemandServerMediaSubsession.$(CPP): include/OnDemandServerMediaSubsession.hh
+include/OnDemandServerMediaSubsession.hh: include/ServerMediaSession.hh include/RTPSink.hh include/BasicUDPSink.hh include/RTCP.hh
FileServerMediaSubsession.$(CPP): include/FileServerMediaSubsession.hh
include/FileServerMediaSubsession.hh: include/OnDemandServerMediaSubsession.hh
MPEG4VideoFileServerMediaSubsession.$(CPP): include/MPEG4VideoFileServerMediaSubsession.hh include/MPEG4ESVideoRTPSink.hh include/ByteStreamFileSource.hh include/MPEG4VideoStreamFramer.hh
include/MPEG4VideoFileServerMediaSubsession.hh: include/FileServerMediaSubsession.hh
+H264VideoFileServerMediaSubsession.$(CPP): include/H264VideoFileServerMediaSubsession.hh include/H264VideoRTPSink.hh include/ByteStreamFileSource.hh include/H264VideoStreamFramer.hh
+include/H264VideoFileServerMediaSubsession.hh: include/FileServerMediaSubsession.hh
H263plusVideoFileServerMediaSubsession.$(CPP): include/H263plusVideoFileServerMediaSubsession.hh include/H263plusVideoRTPSink.hh include/ByteStreamFileSource.hh include/H263plusVideoStreamFramer.hh
include/H263plusVideoFileServerMediaSubsession.hh: include/FileServerMediaSubsession.hh
WAVAudioFileServerMediaSubsession.$(CPP): include/WAVAudioFileServerMediaSubsession.hh include/WAVAudioFileSource.hh include/uLawAudioFilter.hh include/SimpleRTPSink.hh
@@ -276,6 +278,8 @@
include/ADTSAudioFileServerMediaSubsession.hh: include/FileServerMediaSubsession.hh
DVVideoFileServerMediaSubsession.$(CPP): include/DVVideoFileServerMediaSubsession.hh include/DVVideoRTPSink.hh include/ByteStreamFileSource.hh include/DVVideoStreamFramer.hh
include/DVVideoFileServerMediaSubsession.hh: include/FileServerMediaSubsession.hh
+AC3AudioFileServerMediaSubsession.$(CPP): include/AC3AudioFileServerMediaSubsession.hh include/AC3AudioRTPSink.hh include/ByteStreamFileSource.hh include/AC3AudioStreamFramer.hh
+include/AC3AudioFileServerMediaSubsession.hh: include/FileServerMediaSubsession.hh
QuickTimeFileSink.$(CPP): include/QuickTimeFileSink.hh include/InputFile.hh include/OutputFile.hh include/QuickTimeGenericRTPSource.hh include/H263plusVideoRTPSource.hh include/MPEG4GenericRTPSource.hh include/MPEG4LATMAudioRTPSource.hh
include/QuickTimeFileSink.hh: include/MediaSession.hh
QuickTimeGenericRTPSource.$(CPP): include/QuickTimeGenericRTPSource.hh
@@ -292,11 +296,11 @@
Base64.$(CPP): include/Base64.hh
Locale.$(CPP): include/Locale.hh
-include/liveMedia.hh:: include/MPEG1or2AudioRTPSink.hh include/MP3ADURTPSink.hh include/MPEG1or2VideoRTPSink.hh include/MPEG4ESVideoRTPSink.hh include/BasicUDPSink.hh include/AMRAudioFileSink.hh include/H264VideoFileSink.hh include/MPEG1or2VideoHTTPSink.hh include/GSMAudioRTPSink.hh include/H263plusVideoRTPSink.hh include/H264VideoRTPSink.hh include/DVVideoRTPSource.hh include/DVVideoRTPSink.hh include/DVVideoStreamFramer.hh include/H264VideoStreamFramer.hh include/JPEGVideoRTPSink.hh include/SimpleRTPSink.hh include/uLawAudioFilter.hh include/MPEG2IndexFromTransportStream.hh include/MPEG2TransportStreamTrickModeFilter.hh include/ByteStreamFileSource.hh include/BasicUDPSource.hh include/SimpleRTPSource.hh include/MPEG1or2AudioRTPSource.hh include/MPEG4LATMAudioRTPSource.hh include/MPEG4LATMAudioRTPSink.hh include/MPEG4ESVideoRTPSource.hh include/MPEG4GenericRTPSource.hh include/MP3ADURTPSource.hh include/QCELPAudioRTPSource.hh include/AMRAudioRTPSource.hh include/JPEGVideoRTPSource.hh include/MPEG1or2VideoRTPSource.hh
+include/liveMedia.hh:: include/MPEG1or2AudioRTPSink.hh include/MP3ADURTPSink.hh include/MPEG1or2VideoRTPSink.hh include/MPEG4ESVideoRTPSink.hh include/BasicUDPSink.hh include/AMRAudioFileSink.hh include/H264VideoFileSink.hh include/MPEG1or2VideoHTTPSink.hh include/GSMAudioRTPSink.hh include/H263plusVideoRTPSink.hh include/H264VideoRTPSink.hh include/DVVideoRTPSource.hh include/DVVideoRTPSink.hh include/DVVideoStreamFramer.hh include/H264VideoStreamDiscreteFramer.hh include/JPEGVideoRTPSink.hh include/SimpleRTPSink.hh include/uLawAudioFilter.hh include/MPEG2IndexFromTransportStream.hh include/MPEG2TransportStreamTrickModeFilter.hh include/ByteStreamFileSource.hh include/BasicUDPSource.hh include/SimpleRTPSource.hh include/MPEG1or2AudioRTPSource.hh include/MPEG4LATMAudioRTPSource.hh include/MPEG4LATMAudioRTPSink.hh include/MPEG4ESVideoRTPSource.hh include/MPEG4GenericRTPSource.hh include/MP3ADURTPSource.hh include/QCELPAudioRTPSource.hh include/AMRAudioRTPSource.hh include/JPEGVideoRTPSource.hh include/MPEG1or2VideoRTPSource.hh
include/liveMedia.hh:: include/MPEG2TransportStreamFromPESSource.hh include/MPEG2TransportStreamFromESSource.hh include/MPEG2TransportStreamFramer.hh include/ADTSAudioFileSource.hh include/H261VideoRTPSource.hh include/H263plusVideoRTPSource.hh include/H264VideoRTPSource.hh include/MP3HTTPSource.hh include/MP3ADU.hh include/MP3ADUinterleaving.hh include/MP3Transcoder.hh include/MPEG1or2DemuxedElementaryStream.hh include/MPEG1or2AudioStreamFramer.hh include/MPEG1or2VideoStreamDiscreteFramer.hh include/MPEG4VideoStreamDiscreteFramer.hh include/H263plusVideoStreamFramer.hh include/AC3AudioStreamFramer.hh include/AC3AudioRTPSource.hh include/AC3AudioRTPSink.hh include/MPEG4GenericRTPSink.hh include/DeviceSource.hh include/AudioInputDevice.hh include/WAVAudioFileSource.hh
-include/liveMedia.hh:: include/RTSPServer.hh include/RTSPOverHTTPServer.hh include/RTSPClient.hh include/SIPClient.hh include/QuickTimeFileSink.hh include/QuickTimeGenericRTPSource.hh include/AVIFileSink.hh include/PassiveServerMediaSubsession.hh include/MPEG4VideoFileServerMediaSubsession.hh include/WAVAudioFileServerMediaSubsession.hh include/AMRAudioFileServerMediaSubsession.hh include/AMRAudioFileSource.hh include/AMRAudioRTPSink.hh include/MP3AudioFileServerMediaSubsession.hh include/MPEG1or2VideoFileServerMediaSubsession.hh include/MPEG1or2FileServerDemux.hh include/MPEG2TransportFileServerMediaSubsession.hh include/H263plusVideoFileServerMediaSubsession.hh include/ADTSAudioFileServerMediaSubsession.hh include/DVVideoFileServerMediaSubsession.hh include/DarwinInjector.hh
+include/liveMedia.hh:: include/RTSPServer.hh include/RTSPClient.hh include/SIPClient.hh include/QuickTimeFileSink.hh include/QuickTimeGenericRTPSource.hh include/AVIFileSink.hh include/PassiveServerMediaSubsession.hh include/MPEG4VideoFileServerMediaSubsession.hh include/H264VideoFileServerMediaSubsession.hh include/WAVAudioFileServerMediaSubsession.hh include/AMRAudioFileServerMediaSubsession.hh include/AMRAudioFileSource.hh include/AMRAudioRTPSink.hh include/MP3AudioFileServerMediaSubsession.hh include/MPEG1or2VideoFileServerMediaSubsession.hh include/MPEG1or2FileServerDemux.hh include/MPEG2TransportFileServerMediaSubsession.hh include/H263plusVideoFileServerMediaSubsession.hh include/ADTSAudioFileServerMediaSubsession.hh include/DVVideoFileServerMediaSubsession.hh include/AC3AudioFileServerMediaSubsession.hh include/DarwinInjector.hh
clean:
-rm -rf *.$(OBJ) $(ALL) core *.core *~ include/*~
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/Media.cpp
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// Media
// Implementation
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/MediaSession.cpp
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// A data structure that represents a session that consists of
// potentially multiple (audio and/or video) sub-sessions
// Implementation
@@ -535,7 +535,7 @@
fObjecttype(0), fOctetalign(0), fProfile_level_id(0), fRobustsorting(0),
fSizelength(0), fStreamstateindication(0), fStreamtype(0),
fCpresent(False), fRandomaccessindication(False),
- fConfig(NULL), fMode(NULL), fSpropParameterSets(NULL),
+ fConfig(NULL), fMode(NULL), fSpropParameterSets(NULL), fEmphasis(NULL), fChannelOrder(NULL),
fPlayStartTime(0.0), fPlayEndTime(0.0),
fVideoWidth(0), fVideoHeight(0), fVideoFPS(0), fNumChannels(1), fScale(1.0f), fNPT_PTS_Offset(0.0f),
fRTPSocket(NULL), fRTCPSocket(NULL),
@@ -548,7 +548,8 @@
delete[] fConnectionEndpointName; delete[] fSavedSDPLines;
delete[] fMediumName; delete[] fCodecName; delete[] fProtocolName;
- delete[] fControlPath; delete[] fConfig; delete[] fMode; delete[] fSpropParameterSets;
+ delete[] fControlPath;
+ delete[] fConfig; delete[] fMode; delete[] fSpropParameterSets; delete[] fEmphasis; delete[] fChannelOrder;
delete fNext;
}
@@ -649,12 +650,14 @@
} else {
fRTCPSocket = new Groupsock(env(), tempAddr, rtcpPortNum, 255);
}
- if (fRTCPSocket != NULL) {
+ if (fRTCPSocket != NULL && fRTCPSocket->socketNum() >= 0) {
// Success! Use these two sockets.
success = True;
break;
} else {
// We couldn't create the RTCP socket (perhaps that port number's already in use elsewhere?).
+ delete fRTCPSocket;
+
// Record the first socket in our table, and keep trying:
unsigned key = (unsigned)fClientPortNum;
Groupsock* existing = (Groupsock*)socketHashTable->Add((char const*)key, fRTPSocket);
@@ -758,7 +761,7 @@
= MPEG4LATMAudioRTPSource::createNew(env(), fRTPSocket,
fRTPPayloadFormat,
fRTPTimestampFrequency);
- } else if (strcmp(fCodecName, "AC3") == 0) { // AC3 audio
+ } else if (strcmp(fCodecName, "AC3") == 0 || strcmp(fCodecName, "EAC3") == 0) { // AC3 audio
fReadSource = fRTPSource
= AC3AudioRTPSource::createNew(env(), fRTPSocket,
fRTPPayloadFormat,
@@ -830,17 +833,21 @@
delete[] mimeType;
} else if ( strcmp(fCodecName, "PCMU") == 0 // PCM u-law audio
|| strcmp(fCodecName, "GSM") == 0 // GSM audio
+ || strcmp(fCodecName, "DVI4") == 0 // DVI4 (IMA ADPCM) audio
|| strcmp(fCodecName, "PCMA") == 0 // PCM a-law audio
- || strcmp(fCodecName, "L16") == 0 // 16-bit linear audio
|| strcmp(fCodecName, "MP1S") == 0 // MPEG-1 System Stream
|| strcmp(fCodecName, "MP2P") == 0 // MPEG-2 Program Stream
|| strcmp(fCodecName, "L8") == 0 // 8-bit linear audio
+ || strcmp(fCodecName, "L16") == 0 // 16-bit linear audio
+ || strcmp(fCodecName, "L20") == 0 // 20-bit linear audio (RFC 3190)
+ || strcmp(fCodecName, "L24") == 0 // 24-bit linear audio (RFC 3190)
|| strcmp(fCodecName, "G726-16") == 0 // G.726, 16 kbps
|| strcmp(fCodecName, "G726-24") == 0 // G.726, 24 kbps
|| strcmp(fCodecName, "G726-32") == 0 // G.726, 32 kbps
|| strcmp(fCodecName, "G726-40") == 0 // G.726, 40 kbps
|| strcmp(fCodecName, "SPEEX") == 0 // SPEEX audio
|| strcmp(fCodecName, "T140") == 0 // T.140 text (RFC 4103)
+ || strcmp(fCodecName, "DAT12") == 0 // 12-bit nonlinear audio (RFC 3190)
) {
createSimpleRTPSource = True;
useSpecialRTPoffset = 0;
@@ -1164,6 +1171,11 @@
} else if (sscanf(sdpLine, " sprop-parameter-sets = %[^; \t\r\n]", valueStr) == 1) {
// Note: We used "sdpLine" here, because the value is case-sensitive.
delete[] fSpropParameterSets; fSpropParameterSets = strDup(valueStr);
+ } else if (sscanf(line, " emphasis = %[^; \t\r\n]", valueStr) == 1) {
+ delete[] fEmphasis; fEmphasis = strDup(valueStr);
+ } else if (sscanf(sdpLine, " channel-order = %[^; \t\r\n]", valueStr) == 1) {
+ // Note: We used "sdpLine" here, because the value is case-sensitive.
+ delete[] fChannelOrder; fChannelOrder = strDup(valueStr);
} else {
// Some of the above parameters are Boolean. Check whether the parameter
// names appear alone, without a "= 1" at the end:
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/MediaSink.cpp
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// Media Sinks
// Implementation
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/MediaSource.cpp
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// Media Sources
// Implementation
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/MultiFramedRTPSink.cpp
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// RTP sink for a common kind of payload format: Those which pack multiple,
// complete codec frames (as many as possible) into each RTP packet.
// Implementation
@@ -237,11 +237,10 @@
if (numTruncatedBytes > 0) {
unsigned const bufferSize = fOutBuf->totalBytesAvailable();
- unsigned newMaxSize = frameSize + numTruncatedBytes;
envir() << "MultiFramedRTPSink::afterGettingFrame1(): The input frame data was too large for our buffer size ("
<< bufferSize << "). "
<< numTruncatedBytes << " bytes of trailing data was dropped! Correct this by increasing \"OutPacketBuffer::maxSize\" to at least "
- << newMaxSize << ", *before* creating this 'RTPSink'. (Current value is "
+ << OutPacketBuffer::maxSize + numTruncatedBytes << ", *before* creating this 'RTPSink'. (Current value is "
<< OutPacketBuffer::maxSize << ".)\n";
}
unsigned curFragmentationOffset = fCurFragmentationOffset;
@@ -389,7 +388,11 @@
// sending the next packet.
struct timeval timeNow;
gettimeofday(&timeNow, NULL);
- int64_t uSecondsToGo = (fNextSendTime.tv_sec - timeNow.tv_sec)*1000000 + (fNextSendTime.tv_usec - timeNow.tv_usec);
+ int secsDiff = fNextSendTime.tv_sec - timeNow.tv_sec;
+ int64_t uSecondsToGo = secsDiff*1000000 + (fNextSendTime.tv_usec - timeNow.tv_usec);
+ if (uSecondsToGo < 0 || secsDiff < 0) { // sanity check: Make sure that the time-to-delay is non-negative:
+ uSecondsToGo = 0;
+ }
// Delay this amount of time:
nextTask() = envir().taskScheduler().scheduleDelayedTask(uSecondsToGo, (TaskFunc*)sendNext, this);
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/MultiFramedRTPSource.cpp
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// RTP source for a common kind of payload format: Those that pack multiple,
// complete codec frames (as many as possible) into each RTP packet.
// Implementation
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/OnDemandServerMediaSubsession.cpp
^
|
@@ -14,14 +14,12 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// A 'ServerMediaSubsession' object that creates new, unicast, "RTPSink"s
// on demand.
// Implementation
#include "OnDemandServerMediaSubsession.hh"
-#include "RTCP.hh"
-#include "BasicUDPSink.hh"
#include <GroupsockHelper.hh>
OnDemandServerMediaSubsession
@@ -35,27 +33,6 @@
fCNAME[sizeof fCNAME-1] = '\0'; // just in case
}
-class Destinations {
-public:
- Destinations(struct in_addr const& destAddr,
- Port const& rtpDestPort,
- Port const& rtcpDestPort)
- : isTCP(False), addr(destAddr), rtpPort(rtpDestPort), rtcpPort(rtcpDestPort) {
- }
- Destinations(int tcpSockNum, unsigned char rtpChanId, unsigned char rtcpChanId)
- : isTCP(True), rtpPort(0) /*dummy*/, rtcpPort(0) /*dummy*/,
- tcpSocketNum(tcpSockNum), rtpChannelId(rtpChanId), rtcpChannelId(rtcpChanId) {
- }
-
-public:
- Boolean isTCP;
- struct in_addr addr;
- Port rtpPort;
- Port rtcpPort;
- int tcpSocketNum;
- unsigned char rtpChannelId, rtcpChannelId;
-};
-
OnDemandServerMediaSubsession::~OnDemandServerMediaSubsession() {
delete[] fSDPLines;
@@ -95,53 +72,6 @@
return fSDPLines;
}
-// A class that represents the state of an ongoing stream
-class StreamState {
-public:
- StreamState(OnDemandServerMediaSubsession& master,
- Port const& serverRTPPort, Port const& serverRTCPPort,
- RTPSink* rtpSink, BasicUDPSink* udpSink,
- unsigned totalBW, FramedSource* mediaSource,
- Groupsock* rtpGS, Groupsock* rtcpGS);
- virtual ~StreamState();
-
- void startPlaying(Destinations* destinations,
- TaskFunc* rtcpRRHandler, void* rtcpRRHandlerClientData,
- ServerRequestAlternativeByteHandler* serverRequestAlternativeByteHandler,
- void* serverRequestAlternativeByteHandlerClientData);
- void pause();
- void endPlaying(Destinations* destinations);
- void reclaim();
-
- unsigned& referenceCount() { return fReferenceCount; }
-
- Port const& serverRTPPort() const { return fServerRTPPort; }
- Port const& serverRTCPPort() const { return fServerRTCPPort; }
-
- RTPSink* rtpSink() const { return fRTPSink; }
-
- float streamDuration() const { return fStreamDuration; }
-
- FramedSource* mediaSource() const { return fMediaSource; }
-
-private:
- OnDemandServerMediaSubsession& fMaster;
- Boolean fAreCurrentlyPlaying;
- unsigned fReferenceCount;
-
- Port fServerRTPPort, fServerRTCPPort;
-
- RTPSink* fRTPSink;
- BasicUDPSink* fUDPSink;
-
- float fStreamDuration;
- unsigned fTotalBW; RTCPInstance* fRTCPInstance;
-
- FramedSource* fMediaSource;
-
- Groupsock* fRTPgs; Groupsock* fRTCPgs;
-};
-
void OnDemandServerMediaSubsession
::getStreamParameters(unsigned clientSessionId,
netAddressBits clientAddress,
@@ -287,14 +217,14 @@
}
void OnDemandServerMediaSubsession::seekStream(unsigned /*clientSessionId*/,
- void* streamToken, double seekNPT) {
+ void* streamToken, double seekNPT, double streamDuration) {
// Seeking isn't allowed if multiple clients are receiving data from
// the same source:
if (fReuseFirstSource) return;
StreamState* streamState = (StreamState*)streamToken;
if (streamState != NULL && streamState->mediaSource() != NULL) {
- seekStreamSource(streamState->mediaSource(), seekNPT);
+ seekStreamSource(streamState->mediaSource(), seekNPT, streamDuration);
}
}
@@ -329,7 +259,6 @@
if (streamState->referenceCount() > 0) --streamState->referenceCount();
if (streamState->referenceCount() == 0) {
delete streamState;
- if (fLastStreamToken == streamToken) fLastStreamToken = NULL;
streamToken = NULL;
}
}
@@ -345,7 +274,7 @@
}
void OnDemandServerMediaSubsession::seekStreamSource(FramedSource* /*inputSource*/,
- double /*seekNPT*/) {
+ double /*seekNPT*/, double /*streamDuration*/) {
// Default implementation: Do nothing
}
@@ -443,15 +372,6 @@
ServerRequestAlternativeByteHandler* serverRequestAlternativeByteHandler,
void* serverRequestAlternativeByteHandlerClientData) {
if (dests == NULL) return;
- if (!fAreCurrentlyPlaying && fMediaSource != NULL) {
- if (fRTPSink != NULL) {
- fRTPSink->startPlaying(*fMediaSource, afterPlayingStreamState, this);
- fAreCurrentlyPlaying = True;
- } else if (fUDPSink != NULL) {
- fUDPSink->startPlaying(*fMediaSource, afterPlayingStreamState, this);
- fAreCurrentlyPlaying = True;
- }
- }
if (fRTCPInstance == NULL && fRTPSink != NULL) {
// Create (and start) a 'RTCP instance' for this RTP sink:
@@ -483,6 +403,16 @@
rtcpRRHandler, rtcpRRHandlerClientData);
}
}
+
+ if (!fAreCurrentlyPlaying && fMediaSource != NULL) {
+ if (fRTPSink != NULL) {
+ fRTPSink->startPlaying(*fMediaSource, afterPlayingStreamState, this);
+ fAreCurrentlyPlaying = True;
+ } else if (fUDPSink != NULL) {
+ fUDPSink->startPlaying(*fMediaSource, afterPlayingStreamState, this);
+ fAreCurrentlyPlaying = True;
+ }
+ }
}
void StreamState::pause() {
@@ -519,6 +449,7 @@
Medium::close(fUDPSink); fUDPSink = NULL;
fMaster.closeStreamSource(fMediaSource); fMediaSource = NULL;
+ if (fMaster.fLastStreamToken == this) fMaster.fLastStreamToken = NULL;
delete fRTPgs; fRTPgs = NULL;
delete fRTCPgs; fRTCPgs = NULL;
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/OutputFile.cpp
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// Common routines for opening/closing named output files
// Implementation
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/PassiveServerMediaSubsession.cpp
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// A 'ServerMediaSubsession' object that represents an existing
// 'RTPSink', rather than one that creates new 'RTPSink's on demand.
// Implementation
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/QCELPAudioRTPSource.cpp
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// Qualcomm "PureVoice" (aka. "QCELP") Audio RTP Sources
// Implementation
@@ -82,6 +82,7 @@
private:
// Redefined virtual functions:
void doGetNextFrame();
+ virtual void doStopGettingFrames();
private:
class QCELPDeinterleavingBuffer* fDeinterleavingBuffer;
@@ -349,6 +350,11 @@
}
}
+void QCELPDeinterleaver::doStopGettingFrames() {
+ fNeedAFrame = False;
+ fInputSource->stopGettingFrames();
+}
+
void QCELPDeinterleaver
::afterGettingFrame(void* clientData, unsigned frameSize,
unsigned /*numTruncatedBytes*/,
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/QuickTimeFileSink.cpp
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// A sink that generates a QuickTime file from a composite media session
// Implementation
@@ -1782,8 +1782,8 @@
} else if (strcmp(subsession.mediumName(), "video") == 0) {
// MPEG-4 video
size += addWord(0x00000000); // ???
- size += addWord(0x03370000); // ???
- size += addWord(0x1f042f20); // ???
+ size += addWord(0x03330000); // ???
+ size += addWord(0x1f042b20); // ???
size += addWord(0x1104fd46); // ???
size += addWord(0x000d4e10); // ???
size += addWord(0x000d4e10); // ???
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/QuickTimeGenericRTPSource.cpp
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// RTP Sources containing generic QuickTime stream data, as defined in
// <http://developer.apple.com/quicktime/icefloe/dispatch026.html>
// Implementation
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/RTCP.cpp
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// RTCP
// Implementation
@@ -340,7 +340,9 @@
if (!readResult) break;
// Ignore the packet if it was looped-back from ourself:
+ Boolean packetWasFromOurHost = False;
if (RTCPgs()->wasLoopedBackFromUs(envir(), fromAddress)) {
+ packetWasFromOurHost = True;
// However, we still want to handle incoming RTCP packets from
// *other processes* on the same machine. To distinguish this
// case from a true loop-back, check whether we've just sent a
@@ -354,13 +356,22 @@
}
unsigned char* pkt = fInBuf;
- if (fIsSSMSource) {
- // This packet was received via unicast. 'Reflect' it by resending
- // it to the multicast group.
+ if (fIsSSMSource && !packetWasFromOurHost) {
+ // This packet is assumed to have been received via unicast (because we're a SSM source, and SSM receivers send back RTCP "RR"
+ // packets via unicast). 'Reflect' the packet by resending it to the multicast group, so that any other receivers can also
+ // get to see it.
+
// NOTE: Denial-of-service attacks are possible here.
// Users of this software may wish to add their own,
// application-specific mechanism for 'authenticating' the
// validity of this packet before reflecting it.
+
+ // NOTE: The test for "!packetWasFromOurHost" means that we won't reflect RTCP packets that come from other processes on
+ // the same host as us. The reason for this is that the 'packet size' test above is not 100% reliable; some packets
+ // that were truly looped back from us might not be detected as such, and this might lead to infinite forwarding/receiving
+ // of some packets. To avoid this possibility, we only reflect RTCP packets that we know for sure originated elsewhere.
+ // (Note, though, that if we ever re-enable the code in "Groupsock::multicastSendOnly()", then we could remove the test for
+ // "!packetWasFromOurHost".)
fRTCPInterface.sendPacket(pkt, packetSize);
fHaveJustSentPacket = True;
fLastPacketSentSize = packetSize;
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/RTPInterface.cpp
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// An abstraction of a network interface used for RTP (or RTCP).
// (This allows the RTP-over-TCP hack (RFC 2326, section 10.12) to
// be implemented transparently.)
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/RTPSink.cpp
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// RTP Sinks
// Implementation
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/RTPSource.cpp
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// RTP Sources
// Implementation
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/RTSPClient.cpp
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// A generic RTSP client
// Implementation
@@ -169,13 +169,12 @@
}
Boolean RTSPClient::parseRTSPURL(UsageEnvironment& env, char const* url,
+ char*& username, char*& password,
NetAddress& address,
portNumBits& portNum,
char const** urlSuffix) {
do {
- // Parse the URL as "rtsp://<address>:<port>/<etc>"
- // (with ":<port>" and "/<etc>" optional)
- // Also, skip over any "<username>[:<password>]@" preceding <address>
+ // Parse the URL as "rtsp://[<username>[:<password>]@]<server-address-or-name>[:<port>][/<stream-name>]"
char const* prefix = "rtsp://";
unsigned const prefixLength = 7;
if (_strncasecmp(url, prefix, prefixLength) != 0) {
@@ -187,19 +186,37 @@
char parseBuffer[parseBufferSize];
char const* from = &url[prefixLength];
- // Skip over any "<username>[:<password>]@"
- // (Note that this code fails if <password> contains '@' or '/', but
- // given that these characters can also appear in <etc>, there seems to
- // be no way of unambiguously parsing that situation.)
- char const* from1 = from;
- while (*from1 != '\0' && *from1 != '/') {
- if (*from1 == '@') {
- from = ++from1;
+ // Check whether "<username>[:<password>]@" occurs next.
+ // We do this by checking whether '@' appears before the end of the URL, or before the first '/'.
+ username = password = NULL; // default return values
+ char const* colonPasswordStart = NULL;
+ char const* p;
+ for (p = from; *p != '\0' && *p != '/'; ++p) {
+ if (*p == ':' && colonPasswordStart == NULL) {
+ colonPasswordStart = p;
+ } else if (*p == '@') {
+ // We found <username> (and perhaps <password>). Copy them into newly-allocated result strings:
+ if (colonPasswordStart == NULL) colonPasswordStart = p;
+
+ char const* usernameStart = from;
+ unsigned usernameLen = colonPasswordStart - usernameStart;
+ username = new char[usernameLen + 1] ; // allow for the trailing '\0'
+ for (unsigned i = 0; i < usernameLen; ++i) username[i] = usernameStart[i];
+ username[usernameLen] = '\0';
+
+ char const* passwordStart = colonPasswordStart;
+ if (passwordStart < p) ++passwordStart; // skip over the ':'
+ unsigned passwordLen = p - passwordStart;
+ password = new char[passwordLen + 1]; // allow for the trailing '\0'
+ for (unsigned j = 0; j < passwordLen; ++j) password[j] = passwordStart[j];
+ password[passwordLen] = '\0';
+
+ from = p + 1; // skip over the '@'
break;
}
- ++from1;
}
+ // Next, parse <server-address-or-name>
char* to = &parseBuffer[0];
unsigned i;
for (i = 0; i < parseBufferSize; ++i) {
@@ -248,46 +265,6 @@
return False;
}
-Boolean RTSPClient::parseRTSPURLUsernamePassword(char const* url,
- char*& username,
- char*& password) {
- username = password = NULL; // by default
- do {
- // Parse the URL as "rtsp://<username>[:<password>]@<whatever>"
- char const* prefix = "rtsp://";
- unsigned const prefixLength = 7;
- if (_strncasecmp(url, prefix, prefixLength) != 0) break;
-
- // Look for the ':' and '@':
- unsigned usernameIndex = prefixLength;
- unsigned colonIndex = 0, atIndex = 0;
- for (unsigned i = usernameIndex; url[i] != '\0' && url[i] != '/'; ++i) {
- if (url[i] == ':' && colonIndex == 0) {
- colonIndex = i;
- } else if (url[i] == '@') {
- atIndex = i;
- break; // we're done
- }
- }
- if (atIndex == 0) break; // no '@' found
-
- char* urlCopy = strDup(url);
- urlCopy[atIndex] = '\0';
- if (colonIndex > 0) {
- urlCopy[colonIndex] = '\0';
- password = strDup(&urlCopy[colonIndex+1]);
- } else {
- password = strDup("");
- }
- username = strDup(&urlCopy[usernameIndex]);
- delete[] urlCopy;
-
- return True;
- } while (0);
-
- return False;
-}
-
void RTSPClient::setUserAgentString(char const* userAgentName) {
if (userAgentName == NULL) return;
@@ -381,12 +358,18 @@
do {
// Set up a connection to the server. Begin by parsing the URL:
+ char* username;
+ char* password;
NetAddress destAddress;
portNumBits urlPortNum;
char const* urlSuffix;
- if (!parseRTSPURL(envir(), fBaseURL, destAddress, urlPortNum, &urlSuffix)) break;
- portNumBits destPortNum
- = fTunnelOverHTTPPortNum == 0 ? urlPortNum : fTunnelOverHTTPPortNum;
+ if (!parseRTSPURL(envir(), fBaseURL, username, password, destAddress, urlPortNum, &urlSuffix)) break;
+ portNumBits destPortNum = fTunnelOverHTTPPortNum == 0 ? urlPortNum : fTunnelOverHTTPPortNum;
+ if (username != NULL || password != NULL) {
+ fCurrentAuthenticator.setUsernameAndPassword(username, password);
+ delete[] username;
+ delete[] password;
+ }
// We don't yet have a TCP socket (or we used to have one, but it got closed). Set it up now.
fInputSocketNum = fOutputSocketNum = setupStreamSocket(envir(), 0);
@@ -632,10 +615,16 @@
sprintf(extraHeaders, "%s%s", transportStr, sessionStr);
delete[] transportStr; delete[] sessionStr;
} else if (strcmp(request->commandName(), "GET") == 0 || strcmp(request->commandName(), "POST") == 0) {
+ // We will be sending a HTTP (not a RTSP) request.
+ // Begin by re-parsing our RTSP URL, just to get the stream name, which we'll use as our 'cmdURL' in the subsequent request:
+ char* username;
+ char* password;
NetAddress destAddress;
portNumBits urlPortNum;
- if (!parseRTSPURL(envir(), fBaseURL, destAddress, urlPortNum, (char const**)&cmdURL)) break;
+ if (!parseRTSPURL(envir(), fBaseURL, username, password, destAddress, urlPortNum, (char const**)&cmdURL)) break;
if (cmdURL[0] == '\0') cmdURL = (char*)"/";
+ delete[] username;
+ delete[] password;
protocolStr = "HTTP/1.0";
@@ -661,10 +650,8 @@
extraHeaders = new char[extraHeadersSize];
extraHeadersWereAllocated = True;
sprintf(extraHeaders, extraHeadersFmt,
- fSessionCookie);
+ fSessionCookie);
} else { // "POST"
- protocolStr = "HTTP/1.0";
-
char const* const extraHeadersFmt =
"x-sessioncookie: %s\r\n"
"Content-Type: application/x-rtsp-tunnelled\r\n"
@@ -804,16 +791,13 @@
}
Boolean RTSPClient
-::parseResponseCode(char const* line, unsigned& responseCode, char const*& responseString, Boolean& responseIsHTTP) {
- responseIsHTTP = False; // by default
- if (sscanf(line, "RTSP/%*s%u", &responseCode) != 1) {
- if (sscanf(line, "HTTP/%*s%u", &responseCode) != 1) return False;
- responseIsHTTP = True;
- // Note: We check for HTTP responses as well as RTSP responses, both in order to setup RTSP-over-HTTP tunneling,
- // and so that we get back a meaningful error if the client tried to mistakenly send a RTSP command to a HTTP-only server.
- }
+::parseResponseCode(char const* line, unsigned& responseCode, char const*& responseString) {
+ if (sscanf(line, "RTSP/%*s%u", &responseCode) != 1 &&
+ sscanf(line, "HTTP/%*s%u", &responseCode) != 1) return False;
+ // Note: We check for HTTP responses as well as RTSP responses, both in order to setup RTSP-over-HTTP tunneling,
+ // and so that we get back a meaningful error if the client tried to mistakenly send a RTSP command to a HTTP-only server.
- // Use everything after the RTSP/* as the response string:
+ // Use everything after the RTSP/* (or HTTP/*) as the response string:
responseString = line;
while (responseString[0] != '\0' && responseString[0] != ' ' && responseString[0] != '\t') ++responseString;
while (responseString[0] != '\0' && (responseString[0] == ' ' || responseString[0] == '\t')) ++responseString; // skip whitespace
@@ -1118,6 +1102,8 @@
}
Boolean RTSPClient::handleAuthenticationFailure(char const* paramsStr) {
+ if (paramsStr == NULL) return False; // There was no "WWW-Authenticate:" header; we can't proceed.
+
// Fill in "fCurrentAuthenticator" with the information from the "WWW-Authenticate:" header:
Boolean alreadyHadRealm = fCurrentAuthenticator.realm() != NULL;
char* realm = strDupSize(paramsStr);
@@ -1143,7 +1129,7 @@
Boolean RTSPClient::resendCommand(RequestRecord* request) {
if (fVerbosityLevel >= 1) envir() << "Resending...\n";
- if (request != NULL) request->cseq() = ++fCSeq;
+ if (request != NULL && strcmp(request->commandName(), "GET") != 0) request->cseq() = ++fCSeq;
return sendRequest(request) != 0;
}
@@ -1205,7 +1191,7 @@
Boolean RTSPClient::setupHTTPTunneling1() {
// Set up RTSP-over-HTTP tunneling, as described in
- // http://developer.apple.com/documentation/QuickTime/QTSS/Concepts/chapter_2_section_14.html
+ // http://developer.apple.com/quicktime/icefloe/dispatch028.html and http://images.apple.com/br/quicktime/pdf/QTSS_Modules.pdf
if (fVerbosityLevel >= 1) {
envir() << "Requesting RTSP-over-HTTP tunneling (on port " << fTunnelOverHTTPPortNum << ")\n\n";
}
@@ -1221,6 +1207,8 @@
void RTSPClient::responseHandlerForHTTP_GET1(int responseCode, char* responseString) {
RequestRecord* request;
do {
+ if (responseCode != 0) break; // The HTTP "GET" failed.
+
// Having successfully set up (using the HTTP "GET" command) the server->client link, set up a second TCP connection
// (to the same server & port as before) for the client->server link. All future output will be to this new socket.
fOutputSocketNum = setupStreamSocket(envir(), 0);
@@ -1394,7 +1382,6 @@
char* headerDataCopy;
unsigned responseCode = 200;
char const* responseStr = NULL;
- Boolean responseIsHTTP = False;
RequestRecord* foundRequest = NULL;
char const* sessionParamsStr = NULL;
char const* transportParamsStr = NULL;
@@ -1413,7 +1400,7 @@
char* lineStart = headerDataCopy;
char* nextLineStart = getLine(lineStart);
- if (!parseResponseCode(lineStart, responseCode, responseStr, responseIsHTTP)) {
+ if (!parseResponseCode(lineStart, responseCode, responseStr)) {
// This does not appear to be a RTSP response; perhaps it's a RTSP request instead?
handleIncomingRequest();
break; // we're done with this data
@@ -1482,8 +1469,8 @@
}
if (!reachedEndOfHeaders) break; // an error occurred
- if (foundRequest == NULL && responseIsHTTP) {
- // Hack: HTTP responses don't have a "CSeq:" header, so if we got a HTTP response, assume it's for our most recent request:
+ if (foundRequest == NULL) {
+ // Hack: The response didn't have a "CSeq:" header; assume it's for our most recent request:
foundRequest = fRequestsAwaitingResponse.dequeue();
}
@@ -1534,7 +1521,15 @@
if (!handleGET_PARAMETERResponse(foundRequest->contentStr(), bodyStart)) break;
}
} else if (responseCode == 401 && handleAuthenticationFailure(wwwAuthenticateParamsStr)) {
+ // We need to resend the command, with an "Authorization:" header:
needToResendCommand = True;
+
+ if (strcmp(foundRequest->commandName(), "GET") == 0) {
+ // Note: If a HTTP "GET" command (for RTSP-over-HTTP tunneling) returns "401 Unauthorized", then we resend it
+ // (with an "Authorization:" header), just as we would for a RTSP command. However, we do so using a new TCP connection,
+ // because some servers close the original connection after returning the "401 Unauthorized".
+ resetTCPSockets(); // forces the opening of a new connection for the resent command
+ }
} else if (responseCode == 301 || responseCode == 302) { // redirection
resetTCPSockets(); // because we need to connect somewhere else next
needToResendCommand = True;
@@ -1688,8 +1683,7 @@
char* RTSPClient::describeWithPassword(char const* url,
char const* username, char const* password,
Boolean allowKasennaProtocol, int timeout) {
- Authenticator authenticator;
- authenticator.setUsernameAndPassword(username, password);
+ Authenticator authenticator(username, password);
return describeURL(url, &authenticator, allowKasennaProtocol, timeout);
}
@@ -1704,16 +1698,14 @@
// (and no username,password pair was supplied separately):
if (username == NULL && password == NULL
&& parseRTSPURLUsernamePassword(url, username, password)) {
- Authenticator newAuthenticator;
- newAuthenticator.setUsernameAndPassword(username, password);
+ Authenticator newAuthenticator(username,password);
result = sendOptionsCmd(url, username, password, &newAuthenticator, timeout);
delete[] username; delete[] password; // they were dynamically allocated
return result;
} else if (username != NULL && password != NULL) {
// Use the separately supplied username and password:
- authenticator = new Authenticator;
+ authenticator = new Authenticator(username,password);
haveAllocatedAuthenticator = True;
- authenticator->setUsernameAndPassword(username, password);
result = sendOptionsCmd(url, username, password, authenticator, timeout);
if (result != NULL) return result; // We are already authorized
@@ -1768,8 +1760,7 @@
Boolean RTSPClient
::announceWithPassword(char const* url, char const* sdpDescription,
char const* username, char const* password, int timeout) {
- Authenticator authenticator;
- authenticator.setUsernameAndPassword(username, password);
+ Authenticator authenticator(username,password);
return announceSDPDescription(url, sdpDescription, &authenticator, timeout);
}
@@ -1876,23 +1867,55 @@
Boolean RTSPClient::teardownMediaSession(MediaSession& session) {
fWatchVariableForSyncInterface = 0;
fTimeoutTask = NULL;
- (void)sendTeardownCommand(session, responseHandlerForSyncInterface);
-
- // Now block (but handling events) until we get a response (or a timeout):
- envir().taskScheduler().doEventLoop(&fWatchVariableForSyncInterface);
- delete[] fResultString;
- return fResultCode == 0;
+ (void)sendTeardownCommand(session, NULL);
+ return True; // we don't wait for a response to the "TEARDOWN"
}
Boolean RTSPClient::teardownMediaSubsession(MediaSubsession& subsession) {
fWatchVariableForSyncInterface = 0;
fTimeoutTask = NULL;
- (void)sendTeardownCommand(subsession, responseHandlerForSyncInterface);
+ (void)sendTeardownCommand(subsession, NULL);
+ return True; // we don't wait for a response to the "TEARDOWN"
+}
- // Now block (but handling events) until we get a response (or a timeout):
- envir().taskScheduler().doEventLoop(&fWatchVariableForSyncInterface);
- delete[] fResultString;
- return fResultCode == 0;
+Boolean RTSPClient::parseRTSPURLUsernamePassword(char const* url,
+ char*& username,
+ char*& password) {
+ username = password = NULL; // by default
+ do {
+ // Parse the URL as "rtsp://<username>[:<password>]@<whatever>"
+ char const* prefix = "rtsp://";
+ unsigned const prefixLength = 7;
+ if (_strncasecmp(url, prefix, prefixLength) != 0) break;
+
+ // Look for the ':' and '@':
+ unsigned usernameIndex = prefixLength;
+ unsigned colonIndex = 0, atIndex = 0;
+ for (unsigned i = usernameIndex; url[i] != '\0' && url[i] != '/'; ++i) {
+ if (url[i] == ':' && colonIndex == 0) {
+ colonIndex = i;
+ } else if (url[i] == '@') {
+ atIndex = i;
+ break; // we're done
+ }
+ }
+ if (atIndex == 0) break; // no '@' found
+
+ char* urlCopy = strDup(url);
+ urlCopy[atIndex] = '\0';
+ if (colonIndex > 0) {
+ urlCopy[colonIndex] = '\0';
+ password = strDup(&urlCopy[colonIndex+1]);
+ } else {
+ password = strDup("");
+ }
+ username = strDup(&urlCopy[usernameIndex]);
+ delete[] urlCopy;
+
+ return True;
+ } while (0);
+
+ return False;
}
void RTSPClient::responseHandlerForSyncInterface(RTSPClient* rtspClient, int responseCode, char* responseString) {
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/RTSPCommon.cpp
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// Common routines used by both RTSP clients and servers
// Implementation
@@ -136,6 +136,7 @@
Boolean parseRangeParam(char const* paramStr, double& rangeStart, double& rangeEnd) {
double start, end;
+ int numCharsMatched = 0;
Locale l("C", LC_NUMERIC);
if (sscanf(paramStr, "npt = %lf - %lf", &start, &end) == 2) {
rangeStart = start;
@@ -146,6 +147,10 @@
} else if (strcmp(paramStr, "npt=now-") == 0) {
rangeStart = 0.0;
rangeEnd = 0.0;
+ } else if (sscanf(paramStr, "clock = %*s%n", &numCharsMatched) == 0 && numCharsMatched > 0) {
+ // We accept "clock=" parameters, but currently do no interpret them.
+ } else if (sscanf(paramStr, "smtpe = %*s%n", &numCharsMatched) == 0 && numCharsMatched > 0) {
+ // We accept "smtpe=" parameters, but currently do no interpret them.
} else {
return False; // The header is malformed
}
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/RTSPServer.cpp
^
|
@@ -14,12 +14,13 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// A RTSP server
// Implementation
#include "RTSPServer.hh"
#include "RTSPCommon.hh"
+#include "Base64.hh"
#include <GroupsockHelper.hh>
#if defined(__WIN32__) || defined(_WIN32) || defined(_QNX4)
@@ -72,9 +73,7 @@
char const* sessionName = serverMediaSession->streamName();
if (sessionName == NULL) sessionName = "";
ServerMediaSession* existingSession
- = (ServerMediaSession*)
- (fServerMediaSessions->Add(sessionName,
- (void*)serverMediaSession));
+ = (ServerMediaSession*)(fServerMediaSessions->Add(sessionName, (void*)serverMediaSession));
removeServerMediaSession(existingSession); // if any
}
@@ -97,6 +96,18 @@
removeServerMediaSession(lookupServerMediaSession(streamName));
}
+char* RTSPServer
+::rtspURL(ServerMediaSession const* serverMediaSession, int clientSocket) const {
+ char* urlPrefix = rtspURLPrefix(clientSocket);
+ char const* sessionName = serverMediaSession->streamName();
+
+ char* resultURL = new char[strlen(urlPrefix) + strlen(sessionName) + 1];
+ sprintf(resultURL, "%s%s", urlPrefix, sessionName);
+
+ delete[] urlPrefix;
+ return resultURL;
+}
+
char* RTSPServer::rtspURLPrefix(int clientSocket) const {
struct sockaddr_in ourAddress;
if (clientSocket < 0) {
@@ -111,7 +122,7 @@
char urlBuffer[100]; // more than big enough for "rtsp://<ip-address>:<port>/"
- portNumBits portNumHostOrder = ntohs(fServerPort.num());
+ portNumBits portNumHostOrder = ntohs(fRTSPServerPort.num());
if (portNumHostOrder == 554 /* the default port number */) {
sprintf(urlBuffer, "rtsp://%s/", our_inet_ntoa(ourAddress.sin_addr));
} else {
@@ -122,16 +133,27 @@
return strDup(urlBuffer);
}
-char* RTSPServer
-::rtspURL(ServerMediaSession const* serverMediaSession, int clientSocket) const {
- char* urlPrefix = rtspURLPrefix(clientSocket);
- char const* sessionName = serverMediaSession->streamName();
+UserAuthenticationDatabase* RTSPServer::setAuthenticationDatabase(UserAuthenticationDatabase* newDB) {
+ UserAuthenticationDatabase* oldDB = fAuthDB;
+ fAuthDB = newDB;
+
+ return oldDB;
+}
- char* resultURL = new char[strlen(urlPrefix) + strlen(sessionName) + 1];
- sprintf(resultURL, "%s%s", urlPrefix, sessionName);
+Boolean RTSPServer::setUpTunnelingOverHTTP(Port httpPort) {
+ fHTTPServerSocket = setUpOurSocket(envir(), httpPort);
+ if (fHTTPServerSocket >= 0) {
+ fHTTPServerPort = httpPort;
+ envir().taskScheduler().turnOnBackgroundReadHandling(fHTTPServerSocket,
+ (TaskScheduler::BackgroundHandlerProc*)&incomingConnectionHandlerHTTP, this);
+ return True;
+ }
- delete[] urlPrefix;
- return resultURL;
+ return False;
+}
+
+portNumBits RTSPServer::httpServerPortNum() const {
+ return ntohs(fHTTPServerPort.num());
}
#define LISTEN_BACKLOG_SIZE 20
@@ -140,6 +162,8 @@
int ourSocket = -1;
do {
+ NoReuse dummy; // Don't use this socket if there's already a local server using it
+
ourSocket = setupStreamSocket(env, ourPort);
if (ourSocket < 0) break;
@@ -175,7 +199,8 @@
UserAuthenticationDatabase* authDatabase,
unsigned reclamationTestSeconds)
: Medium(env),
- fServerSocket(ourSocket), fServerPort(ourPort),
+ fRTSPServerSocket(ourSocket), fRTSPServerPort(ourPort),
+ fHTTPServerSocket(-1), fHTTPServerPort(0), fClientSessionsForHTTPTunneling(NULL),
fAuthDB(authDatabase), fReclamationTestSeconds(reclamationTestSeconds),
fServerMediaSessions(HashTable::create(STRING_HASH_KEYS)) {
#ifdef USE_SIGNALS
@@ -185,16 +210,19 @@
#endif
// Arrange to handle connections from others:
- env.taskScheduler().turnOnBackgroundReadHandling(fServerSocket,
- (TaskScheduler::BackgroundHandlerProc*)&incomingConnectionHandler,
- this);
+ env.taskScheduler().turnOnBackgroundReadHandling(fRTSPServerSocket,
+ (TaskScheduler::BackgroundHandlerProc*)&incomingConnectionHandlerRTSP, this);
}
RTSPServer::~RTSPServer() {
// Turn off background read handling:
- envir().taskScheduler().turnOffBackgroundReadHandling(fServerSocket);
+ envir().taskScheduler().turnOffBackgroundReadHandling(fRTSPServerSocket);
+ ::closeSocket(fRTSPServerSocket);
+
+ envir().taskScheduler().turnOffBackgroundReadHandling(fHTTPServerSocket);
+ ::closeSocket(fHTTPServerSocket);
- ::closeSocket(fServerSocket);
+ delete fClientSessionsForHTTPTunneling;
// Remove all server media sessions (they'll get deleted when they're finished):
while (1) {
@@ -212,16 +240,26 @@
return True;
}
-void RTSPServer::incomingConnectionHandler(void* instance, int /*mask*/) {
+void RTSPServer::incomingConnectionHandlerRTSP(void* instance, int /*mask*/) {
RTSPServer* server = (RTSPServer*)instance;
- server->incomingConnectionHandler1();
+ server->incomingConnectionHandlerRTSP1();
+}
+void RTSPServer::incomingConnectionHandlerRTSP1() {
+ incomingConnectionHandler(fRTSPServerSocket);
}
-void RTSPServer::incomingConnectionHandler1() {
+void RTSPServer::incomingConnectionHandlerHTTP(void* instance, int /*mask*/) {
+ RTSPServer* server = (RTSPServer*)instance;
+ server->incomingConnectionHandlerHTTP1();
+}
+void RTSPServer::incomingConnectionHandlerHTTP1() {
+ incomingConnectionHandler(fHTTPServerSocket);
+}
+
+void RTSPServer::incomingConnectionHandler(int serverSocket) {
struct sockaddr_in clientAddr;
SOCKLEN_T clientAddrLen = sizeof clientAddr;
- int clientSocket = accept(fServerSocket, (struct sockaddr*)&clientAddr,
- &clientAddrLen);
+ int clientSocket = accept(serverSocket, (struct sockaddr*)&clientAddr, &clientAddrLen);
if (clientSocket < 0) {
int err = envir().getErrno();
if (err != EWOULDBLOCK) {
@@ -232,8 +270,8 @@
makeSocketNonBlocking(clientSocket);
increaseSendBufferTo(envir(), clientSocket, 50*1024);
-#if defined(DEBUG) || defined(DEBUG_CONNECTIONS)
- envir() << "accept()ed connection from " << our_inet_ntoa(clientAddr.sin_addr) << '\n';
+#ifdef DEBUG
+ envir() << "accept()ed connection from " << our_inet_ntoa(clientAddr.sin_addr) << "\n";
#endif
// Create a new object for this RTSP session.
@@ -247,17 +285,16 @@
////////// RTSPServer::RTSPClientSession implementation //////////
RTSPServer::RTSPClientSession
-::RTSPClientSession(RTSPServer& ourServer, unsigned sessionId,
- int clientSocket, struct sockaddr_in clientAddr)
+::RTSPClientSession(RTSPServer& ourServer, unsigned sessionId, int clientSocket, struct sockaddr_in clientAddr)
: fOurServer(ourServer), fOurSessionId(sessionId),
fOurServerMediaSession(NULL),
- fClientSocket(clientSocket), fClientAddr(clientAddr),
- fLivenessCheckTask(NULL),
+ fClientInputSocket(clientSocket), fClientOutputSocket(clientSocket), fClientAddr(clientAddr),
+ fSessionCookie(NULL), fLivenessCheckTask(NULL),
fIsMulticast(False), fSessionIsActive(True), fStreamAfterSETUP(False),
fTCPStreamIdCount(0), fNumStreamStates(0), fStreamStates(NULL) {
// Arrange to handle incoming requests:
resetRequestBuffer();
- envir().taskScheduler().turnOnBackgroundReadHandling(fClientSocket,
+ envir().taskScheduler().turnOnBackgroundReadHandling(fClientInputSocket,
(TaskScheduler::BackgroundHandlerProc*)&incomingRequestHandler, this);
noteLiveness();
}
@@ -267,9 +304,16 @@
envir().taskScheduler().unscheduleDelayedTask(fLivenessCheckTask);
// Turn off background read handling:
- envir().taskScheduler().turnOffBackgroundReadHandling(fClientSocket);
+ envir().taskScheduler().turnOffBackgroundReadHandling(fClientInputSocket);
+
+ if (fClientOutputSocket != fClientInputSocket) ::closeSocket(fClientOutputSocket);
+ ::closeSocket(fClientInputSocket);
- ::closeSocket(fClientSocket);
+ if (fSessionCookie != NULL) {
+ // We were being used for RTSP-over-HTTP tunneling. Remove ourselves from the 'session cookie' hash table before we go:
+ fOurServer.fClientSessionsForHTTPTunneling->Remove(fSessionCookie);
+ delete[] fSessionCookie;
+ }
reclaimStreamStates();
@@ -297,6 +341,7 @@
fRequestBytesAlreadySeen = 0;
fRequestBufferBytesLeft = sizeof fRequestBuffer;
fLastCRLF = &fRequestBuffer[-3]; // hack
+ fBase64RemainderCount = 0;
}
void RTSPServer::RTSPClientSession::incomingRequestHandler(void* instance, int /*mask*/) {
@@ -307,7 +352,7 @@
void RTSPServer::RTSPClientSession::incomingRequestHandler1() {
struct sockaddr_in dummy; // 'from' address, meaningless in this case
- int bytesRead = readSocket(envir(), fClientSocket, &fRequestBuffer[fRequestBytesAlreadySeen], fRequestBufferBytesLeft, dummy);
+ int bytesRead = readSocket(envir(), fClientInputSocket, &fRequestBuffer[fRequestBytesAlreadySeen], fRequestBufferBytesLeft, dummy);
handleRequestBytes(bytesRead);
}
@@ -343,6 +388,36 @@
fprintf(stderr, "RTSPClientSession[%p]::handleRequestBytes() read %d new bytes:%s\n", this, newBytesRead, ptr);
#endif
+ if (fClientOutputSocket != fClientInputSocket) {
+ // We're doing RTSP-over-HTTP tunneling, and input commands are assumed to have been Base64-encoded.
+ // We therefore Base64-decode as much of this new data as we can (i.e., up to a multiple of 4 bytes):
+ unsigned numBytesToDecode = fBase64RemainderCount + newBytesRead;
+ unsigned newBase64RemainderCount = numBytesToDecode%4;
+ numBytesToDecode -= newBase64RemainderCount;
+ if (numBytesToDecode > 0) {
+ ptr[newBytesRead] = '\0';
+ unsigned decodedSize;
+ unsigned char* decodedBytes = base64Decode((char*)(ptr-fBase64RemainderCount), decodedSize);
+#ifdef DEBUG
+ fprintf(stderr, "Base64-decided %d input bytes into %d new bytes:", numBytesToDecode, decodedSize);
+ for (unsigned k = 0; k < decodedSize; ++k) fprintf(stderr, "%c", decodedBytes[k]);
+ fprintf(stderr, "\n");
+#endif
+
+ // Copy the new decoded bytes in place of the old ones (we can do this because there are fewer decoded bytes than original):
+ unsigned char* to = ptr-fBase64RemainderCount;
+ for (unsigned i = 0; i < decodedSize; ++i) *to++ = decodedBytes[i];
+
+ // Then copy any remaining (undecoded) bytes to the end:
+ for (unsigned j = 0; j < newBase64RemainderCount; ++j) *to++ = (ptr-fBase64RemainderCount+numBytesToDecode)[j];
+
+ newBytesRead = decodedSize + newBase64RemainderCount; // adjust to allow for the size of the new decoded data (+ remainder)
+ delete[] decodedBytes;
+ }
+ fBase64RemainderCount = newBase64RemainderCount;
+ if (fBase64RemainderCount > 0) return; // because we know that we have more input bytes still to receive
+ }
+
// Look for the end of the message: <CR><LF><CR><LF>
unsigned char *tmpPtr = ptr;
if (fRequestBytesAlreadySeen > 0) --tmpPtr;
@@ -363,25 +438,19 @@
if (!endOfMsg) return; // subsequent reads will be needed to complete the request
- // Parse the request string into command name and 'CSeq',
- // then handle the command:
+ // Parse the request string into command name and 'CSeq', then handle the command:
fRequestBuffer[fRequestBytesAlreadySeen] = '\0';
char cmdName[RTSP_PARAM_STRING_MAX];
char urlPreSuffix[RTSP_PARAM_STRING_MAX];
char urlSuffix[RTSP_PARAM_STRING_MAX];
char cseq[RTSP_PARAM_STRING_MAX];
- if (!parseRTSPRequestString((char*)fRequestBuffer, fRequestBytesAlreadySeen,
- cmdName, sizeof cmdName,
- urlPreSuffix, sizeof urlPreSuffix,
- urlSuffix, sizeof urlSuffix,
- cseq, sizeof cseq)) {
-#ifdef DEBUG
- fprintf(stderr, "parseRTSPRequestString() failed!\n");
-#endif
- handleCmd_bad(cseq);
- } else {
+ if (parseRTSPRequestString((char*)fRequestBuffer, fRequestBytesAlreadySeen,
+ cmdName, sizeof cmdName,
+ urlPreSuffix, sizeof urlPreSuffix,
+ urlSuffix, sizeof urlSuffix,
+ cseq, sizeof cseq)) {
#ifdef DEBUG
- fprintf(stderr, "parseRTSPRequestString() returned cmdName \"%s\", urlPreSuffix \"%s\", urlSuffix \"%s\"\n", cmdName, urlPreSuffix, urlSuffix);
+ fprintf(stderr, "parseRTSPRequestString() succeeded, returning cmdName \"%s\", urlPreSuffix \"%s\", urlSuffix \"%s\"\n", cmdName, urlPreSuffix, urlSuffix);
#endif
if (strcmp(cmdName, "OPTIONS") == 0) {
handleCmd_OPTIONS(cseq);
@@ -399,12 +468,60 @@
} else {
handleCmd_notSupported(cseq);
}
+ } else {
+#ifdef DEBUG
+ fprintf(stderr, "parseRTSPRequestString() failed\n");
+#endif
+ // The request was not (valid) RTSP, but check for a special case: HTTP commands (for setting up RTSP-over-HTTP tunneling):
+ char sessionCookie[RTSP_PARAM_STRING_MAX];
+ char acceptStr[RTSP_PARAM_STRING_MAX];
+ if (parseHTTPRequestString(cmdName, sizeof cmdName,
+ urlSuffix, sizeof urlPreSuffix,
+ sessionCookie, sizeof sessionCookie,
+ acceptStr, sizeof acceptStr)) {
+#ifdef DEBUG
+ fprintf(stderr, "parseHTTPRequestString() succeeded, returning cmdName \"%s\", urlSuffix \"%s\", sessionCookie \"%s\", acceptStr \"%s\"\n", cmdName, urlSuffix, sessionCookie, acceptStr);
+#endif
+ // Check that the HTTP command is valid for RTSP-over-HTTP tunneling: There must be a 'session cookie'.
+ Boolean isValidHTTPCmd = True;
+ if (sessionCookie[0] == '\0') {
+ // There was no "x-sessionCookie:" header. If there was an "Accept: application/x-rtsp-tunnelled" header,
+ // then this is a bad tunneling request. Otherwise, assume that it's an attempt to access the stream via HTTP.
+ if (strcmp(acceptStr, "application/x-rtsp-tunnelled") == 0) {
+ isValidHTTPCmd = False;
+ } else {
+ handleHTTPCmd_StreamingGET(urlSuffix, (char const*)fRequestBuffer);
+ }
+ } else if (strcmp(cmdName, "GET") == 0) {
+ handleHTTPCmd_TunnelingGET(sessionCookie);
+ } else if (strcmp(cmdName, "POST") == 0) {
+ // We might have received additional data following the HTTP "POST" command - i.e., the first Base64-encoded RTSP command.
+ // Check for this, and handle it if it exists:
+ unsigned char const* extraData = fLastCRLF+4;
+ unsigned extraDataSize = &fRequestBuffer[fRequestBytesAlreadySeen] - extraData;
+ if (handleHTTPCmd_TunnelingPOST(sessionCookie, extraData, extraDataSize)) {
+ // We don't respond to the "POST" command, and we go away:
+ delete this;
+ return;
+ }
+ } else {
+ isValidHTTPCmd = False;
+ }
+ if (!isValidHTTPCmd) {
+ handleHTTPCmd_notSupported();
+ }
+ } else {
+#ifdef DEBUG
+ fprintf(stderr, "parseHTTPRequestString() failed!\n");
+#endif
+ handleCmd_bad(cseq);
+ }
}
#ifdef DEBUG
fprintf(stderr, "sending response: %s", fResponseBuffer);
#endif
- send(fClientSocket, (char const*)fResponseBuffer, strlen((char*)fResponseBuffer), 0);
+ send(fClientOutputSocket, (char const*)fResponseBuffer, strlen((char*)fResponseBuffer), 0);
if (strcmp(cmdName, "SETUP") == 0 && fStreamAfterSETUP) {
// The client has asked for streaming to commence now, rather than after a
@@ -521,7 +638,7 @@
// Also, generate our RTSP URL, for the "Content-Base:" header
// (which is necessary to ensure that the correct URL gets used in
// subsequent "SETUP" requests).
- rtspURL = fOurServer.rtspURL(session, fClientSocket);
+ rtspURL = fOurServer.rtspURL(session, fClientInputSocket);
snprintf((char*)fResponseBuffer, sizeof fResponseBuffer,
"RTSP/1.0 200 OK\r\nCSeq: %s\r\n"
@@ -705,10 +822,13 @@
clientsDestinationAddressStr, clientsDestinationTTL,
clientRTPPortNum, clientRTCPPortNum,
rtpChannelId, rtcpChannelId);
- if (streamingMode == RTP_TCP && rtpChannelId == 0xFF) {
- // TCP streaming was requested, but with no "interleaving=" fields.
- // (QuickTime Player sometimes does this.) Set the RTP and RTCP channel ids to
- // proper values:
+ if (streamingMode == RTP_TCP && rtpChannelId == 0xFF ||
+ streamingMode != RTP_TCP && fClientOutputSocket != fClientInputSocket) {
+ // An anomolous situation, caused by a buggy client. Either:
+ // 1/ TCP streaming was requested, but with no "interleaving=" fields. (QuickTime Player sometimes does this.), or
+ // 2/ TCP streaming was not requested, but we're doing RTSP-over-HTTP tunneling (which implies TCP streaming).
+ // In either case, we assume TCP streaming, and set the RTP and RTCP channel ids to proper values:
+ streamingMode = RTP_TCP;
rtpChannelId = fTCPStreamIdCount; rtcpChannelId = fTCPStreamIdCount+1;
}
fTCPStreamIdCount += 2;
@@ -723,7 +843,7 @@
parsePlayNowHeader(fullRequestStr);
// Then, get server parameters from the 'subsession':
- int tcpSocketNum = streamingMode == RTP_TCP ? fClientSocket : -1;
+ int tcpSocketNum = streamingMode == RTP_TCP ? fClientOutputSocket : -1;
netAddressBits destinationAddress = 0;
u_int8_t destinationTTL = 255;
#ifdef RTSP_ALLOW_CLIENT_DESTINATION_SETTING
@@ -743,7 +863,7 @@
// Make sure that we transmit on the same interface that's used by the client (in case we're a multi-homed server):
struct sockaddr_in sourceAddr; SOCKLEN_T namelen = sizeof sourceAddr;
- getsockname(fClientSocket, (struct sockaddr*)&sourceAddr, &namelen);
+ getsockname(fClientInputSocket, (struct sockaddr*)&sourceAddr, &namelen);
netAddressBits origSendingInterfaceAddr = SendingInterfaceAddr;
netAddressBits origReceivingInterfaceAddr = ReceivingInterfaceAddr;
// NOTE: The following might not work properly, so we ifdef it out for now:
@@ -845,19 +965,27 @@
char const* urlPreSuffix, char const* urlSuffix,
char const* cseq, char const* fullRequestStr) {
// This will either be:
+ // - an operation on the entire server, if "urlPreSuffix" is "", and "urlSuffix" is "*" (i.e., the special "*" URL), or
// - a non-aggregated operation, if "urlPreSuffix" is the session (stream)
// name and "urlSuffix" is the subsession (track) name, or
- // - a aggregated operation, if "urlSuffix" is the session (stream) name,
- // or "urlPreSuffix" is the session (stream) name, and "urlSuffix"
- // is empty.
- // First, figure out which of these it is:
- if (fOurServerMediaSession == NULL) { // There wasn't a previous SETUP!
+ // - an aggregated operation, if "urlSuffix" is the session (stream) name,
+ // or "urlPreSuffix" is the session (stream) name, and "urlSuffix" is empty.
+ // Begin by figuring out which of these it is:
+ ServerMediaSubsession* subsession;
+ if (urlPreSuffix[0] == '\0' && urlSuffix[0] == '*' && urlSuffix[1] == '\0') {
+ // An operation on the entire server. This works only for GET_PARAMETER and SET_PARAMETER:
+ if (strcmp(cmdName, "GET_PARAMETER") == 0) {
+ handleCmd_GET_PARAMETER(NULL, cseq, fullRequestStr);
+ } else if (strcmp(cmdName, "SET_PARAMETER") == 0) {
+ handleCmd_SET_PARAMETER(NULL, cseq, fullRequestStr);
+ } else {
+ handleCmd_notSupported(cseq);
+ }
+ return;
+ } else if (fOurServerMediaSession == NULL) { // There wasn't a previous SETUP!
handleCmd_notSupported(cseq);
return;
- }
- ServerMediaSubsession* subsession;
- if (urlSuffix[0] != '\0' &&
- strcmp(fOurServerMediaSession->streamName(), urlPreSuffix) == 0) {
+ } else if (urlSuffix[0] != '\0' && strcmp(fOurServerMediaSession->streamName(), urlPreSuffix) == 0) {
// Non-aggregated operation.
// Look up the media subsession whose track id is "urlSuffix":
ServerMediaSubsessionIterator iter(*fOurServerMediaSession);
@@ -925,7 +1053,7 @@
void RTSPServer::RTSPClientSession
::handleCmd_PLAY(ServerMediaSubsession* subsession, char const* cseq,
char const* fullRequestStr) {
- char* rtspURL = fOurServer.rtspURL(fOurServerMediaSession, fClientSocket);
+ char* rtspURL = fOurServer.rtspURL(fOurServerMediaSession, fClientInputSocket);
unsigned rtspURLSize = strlen(rtspURL);
// Parse the client's "Scale:" header, if any:
@@ -962,11 +1090,18 @@
duration = -duration;
}
- if (rangeEnd <= 0.0 || rangeEnd > duration) rangeEnd = duration;
- if (rangeStart < 0.0) {
- rangeStart = 0.0;
- } else if (rangeEnd > 0.0 && scale > 0.0 && rangeStart > rangeEnd) {
+ // Make sure that "rangeStart" and "rangeEnd" (from the client's "Range:" header) have sane values
+ // before we send back our own "Range:" header in our response:
+ if (rangeStart < 0.0) rangeStart = 0.0;
+ else if (rangeStart > duration) rangeStart = duration;
+ if (rangeEnd < 0.0) rangeEnd = 0.0;
+ else if (rangeEnd > duration) rangeEnd = duration;
+ if ((scale > 0.0 && rangeStart > rangeEnd && rangeEnd > 0.0) ||
+ (scale < 0.0 && rangeStart < rangeEnd)) {
+ // "rangeStart" and "rangeEnd" were the wrong way around; swap them:
+ double tmp = rangeStart;
rangeStart = rangeEnd;
+ rangeEnd = tmp;
}
char* rangeHeader;
@@ -1001,9 +1136,15 @@
scale);
}
if (sawRangeHeader) {
+ double streamDuration = 0.0; // by default; means: stream until the end of the media
+ if (rangeEnd > 0.0 && (rangeEnd+0.001) < duration) { // the 0.001 is because we limited the values to 3 decimal places
+ // We want the stream to end early. Set the duration we want:
+ streamDuration = rangeEnd - rangeStart;
+ if (streamDuration < 0.0) streamDuration = -streamDuration; // should happen only if scale < 0.0
+ }
fStreamStates[i].subsession->seekStream(fOurSessionId,
fStreamStates[i].streamToken,
- rangeStart);
+ rangeStart, streamDuration);
}
}
}
@@ -1082,10 +1223,11 @@
}
void RTSPServer::RTSPClientSession
-::handleCmd_GET_PARAMETER(ServerMediaSubsession* subsession, char const* cseq,
+::handleCmd_GET_PARAMETER(ServerMediaSubsession* /*subsession*/, char const* cseq,
char const* /*fullRequestStr*/) {
- // We implement "GET_PARAMETER" just as a 'keep alive',
- // and send back an empty response:
+ // By default, we implement "GET_PARAMETER" just as a 'keep alive', and send back an empty response.
+ // (If you want to handle "GET_PARAMETER" properly, you can do so by defining a subclass of "RTSPServer"
+ // and "RTSPServer::RTSPClientSession", and then reimplement this virtual function in your subclass.)
snprintf((char*)fResponseBuffer, sizeof fResponseBuffer,
"RTSP/1.0 200 OK\r\nCSeq: %s\r\n%sSession: %08X\r\n\r\n",
cseq, dateHeader(), fOurSessionId);
@@ -1094,8 +1236,147 @@
void RTSPServer::RTSPClientSession
::handleCmd_SET_PARAMETER(ServerMediaSubsession* /*subsession*/, char const* cseq,
char const* /*fullRequestStr*/) {
- // By default, we don't implement "SET_PARAMETER":
- handleCmd_notSupported(cseq);
+ // By default, we implement "SET_PARAMETER" just as a 'keep alive', and send back an empty response.
+ // (If you want to handle "SET_PARAMETER" properly, you can do so by defining a subclass of "RTSPServer"
+ // and "RTSPServer::RTSPClientSession", and then reimplement this virtual function in your subclass.)
+ snprintf((char*)fResponseBuffer, sizeof fResponseBuffer,
+ "RTSP/1.0 200 OK\r\nCSeq: %s\r\n%sSession: %08X\r\n\r\n",
+ cseq, dateHeader(), fOurSessionId);
+}
+
+static void lookForHeader(char const* headerName, char const* source, unsigned sourceLen, char* resultStr, unsigned resultMaxSize) {
+ resultStr[0] = '\0'; // by default, return an empty string
+ unsigned headerNameLen = strlen(headerName);
+ for (int i = 0; i < (int)(sourceLen-headerNameLen); ++i) {
+ if (strncmp(&source[i], headerName, headerNameLen) == 0 && source[i+headerNameLen] == ':') {
+ // We found the header. Skip over any whitespace, then copy the rest of the line to "resultStr":
+ for (i += headerNameLen+1; i < (int)sourceLen && (source[i] == ' ' || source[i] == '\t'); ++i) {}
+ for (unsigned j = i; j < sourceLen; ++j) {
+ if (source[j] == '\r' || source[j] == '\n') {
+ // We've found the end of the line. Copy it to the result (if it will fit):
+ if (j-i+1 > resultMaxSize) break;
+ char const* resultSource = &source[i];
+ char const* resultSourceEnd = &source[j];
+ while (resultSource < resultSourceEnd) *resultStr++ = *resultSource++;
+ *resultStr = '\0';
+ break;
+ }
+ }
+ }
+ }
+}
+
+Boolean RTSPServer::RTSPClientSession::parseHTTPRequestString(char* resultCmdName, unsigned resultCmdNameMaxSize,
+ char* urlSuffix, unsigned urlSuffixMaxSize,
+ char* sessionCookie, unsigned sessionCookieMaxSize,
+ char* acceptStr, unsigned acceptStrMaxSize) {
+ // Check for the limited HTTP requests that we expect for specifying RTSP-over-HTTP tunneling.
+ // This parser is currently rather dumb; it should be made smarter #####
+ char const* reqStr = (char const*)fRequestBuffer;
+ unsigned const reqStrSize = fRequestBytesAlreadySeen;
+
+ // Read everything up to the first space as the command name:
+ Boolean parseSucceeded = False;
+ unsigned i;
+ for (i = 0; i < resultCmdNameMaxSize-1 && i < reqStrSize; ++i) {
+ char c = reqStr[i];
+ if (c == ' ' || c == '\t') {
+ parseSucceeded = True;
+ break;
+ }
+
+ resultCmdName[i] = c;
+ }
+ resultCmdName[i] = '\0';
+ if (!parseSucceeded) return False;
+
+ // Look for the string "HTTP/", before the first \r or \n:
+ parseSucceeded = False;
+ for (; i < reqStrSize-5 && reqStr[i] != '\r' && reqStr[i] != '\n'; ++i) {
+ if (reqStr[i] == 'H' && reqStr[i+1] == 'T' && reqStr[i+2]== 'T' && reqStr[i+3]== 'P' && reqStr[i+4]== '/') {
+ i += 5; // to advance past the "HTTP/"
+ parseSucceeded = True;
+ break;
+ }
+ }
+ if (!parseSucceeded) return False;
+
+ // Get the 'URL suffix' that occurred before this:
+ unsigned k = i-6;
+ while (k > 0 && reqStr[k] == ' ') --k; // back up over white space
+ unsigned j = k;
+ while (j > 0 && reqStr[j] != ' ' && reqStr[j] != '/') --j;
+ // The URL suffix is in position (j,k]:
+ if (k - j + 1 > urlSuffixMaxSize) return False; // there's no room>
+ unsigned n = 0;
+ while (++j <= k) urlSuffix[n++] = reqStr[j];
+ urlSuffix[n] = '\0';
+
+ // Look for various headers that we're interested in:
+ lookForHeader("x-sessioncookie", &reqStr[i], reqStrSize-i, sessionCookie, sessionCookieMaxSize);
+ lookForHeader("Accept", &reqStr[i], reqStrSize-i, acceptStr, acceptStrMaxSize);
+
+ return True;
+}
+
+void RTSPServer::RTSPClientSession::handleHTTPCmd_notSupported() {
+ snprintf((char*)fResponseBuffer, sizeof fResponseBuffer,
+ "HTTP/1.0 405 Method Not Allowed\r\n%s\r\n\r\n",
+ dateHeader());
+}
+
+void RTSPServer::RTSPClientSession::handleHTTPCmd_notFound() {
+ snprintf((char*)fResponseBuffer, sizeof fResponseBuffer,
+ "HTTP/1.0 404 Not Found\r\n%s\r\n\r\n",
+ dateHeader());
+}
+
+void RTSPServer::RTSPClientSession::handleHTTPCmd_TunnelingGET(char const* sessionCookie) {
+ // Record ourself as having this 'session cookie', so that a subsequent HTTP "POST" command (with the same 'session cookie')
+ // can find us:
+ if (fOurServer.fClientSessionsForHTTPTunneling == NULL) {
+ fOurServer.fClientSessionsForHTTPTunneling = HashTable::create(STRING_HASH_KEYS);
+ }
+ fOurServer.fClientSessionsForHTTPTunneling->Add(sessionCookie, (void*)this);
+#ifdef DEBUG
+ fprintf(stderr, "Handled HTTP \"GET\" request (client output socket: %d)\n", fClientOutputSocket);
+#endif
+
+ // Construct our response:
+ snprintf((char*)fResponseBuffer, sizeof fResponseBuffer,
+ "HTTP/1.0 200 OK\r\n"
+ "Date: Thu, 19 Aug 1982 18:30:00 GMT\r\n"
+ "Cache-Control: no-cache\r\n"
+ "Pragma: no-cache\r\n"
+ "Content-Type: application/x-rtsp-tunnelled\r\n"
+ "\r\n");
+}
+
+Boolean RTSPServer::RTSPClientSession
+::handleHTTPCmd_TunnelingPOST(char const* sessionCookie, unsigned char const* extraData, unsigned extraDataSize) {
+ // Use the "sessionCookie" string to look up the separate "RTSPClientSession" object that should have been used to handle
+ // an earlier HTTP "GET" request:
+ RTSPServer::RTSPClientSession* prevClientSession
+ = (RTSPServer::RTSPClientSession*)(fOurServer.fClientSessionsForHTTPTunneling->Lookup(sessionCookie));
+ if (prevClientSession == NULL) {
+ // There was no previous HTTP "GET" request; treat this "POST" request as bad:
+ handleHTTPCmd_notSupported();
+ fSessionIsActive = False; // triggers deletion of ourself
+ return False;
+ }
+#ifdef DEBUG
+ fprintf(stderr, "Handled HTTP \"POST\" request (client input socket: %d)\n", fClientInputSocket);
+#endif
+
+ // Change the previous "RTSPClientSession" object's input socket to ours. It will be used for subsequent requests:
+ prevClientSession->changeClientInputSocket(fClientInputSocket, extraData, extraDataSize);
+ fClientInputSocket = fClientOutputSocket = -1; // so the socket doesn't get closed when we get deleted
+ return True;
+}
+
+void RTSPServer::RTSPClientSession::handleHTTPCmd_StreamingGET(char const* /*urlSuffix*/, char const* /*fullRequestStr*/) {
+ // By default, we don't support requests to access streams via HTTP:
+ handleHTTPCmd_notSupported();
}
static Boolean parseAuthorizationHeader(char const* buf,
@@ -1149,7 +1430,7 @@
::authenticationOK(char const* cmdName, char const* cseq,
char const* urlSuffix, char const* fullRequestStr) {
- if (!fOurServer.specialClientAccessCheck(fClientSocket, fClientAddr, urlSuffix)) {
+ if (!fOurServer.specialClientAccessCheck(fClientInputSocket, fClientAddr, urlSuffix)) {
snprintf((char*)fResponseBuffer, sizeof fResponseBuffer,
"RTSP/1.0 401 Unauthorized\r\n"
"CSeq: %s\r\n"
@@ -1220,6 +1501,9 @@
}
void RTSPServer::RTSPClientSession::noteLiveness() {
+#ifdef DEBUG
+ fprintf(stderr, "Liveness indication from client at %s\n", our_inet_ntoa(fClientAddr.sin_addr));
+#endif
if (fOurServer.fReclamationTestSeconds > 0) {
envir().taskScheduler()
.rescheduleDelayedTask(fLivenessCheckTask,
@@ -1248,6 +1532,23 @@
return new RTSPClientSession(*this, sessionId, clientSocket, clientAddr);
}
+void RTSPServer::RTSPClientSession
+::changeClientInputSocket(int newSocketNum, unsigned char const* extraData, unsigned extraDataSize) {
+ envir().taskScheduler().turnOffBackgroundReadHandling(fClientInputSocket);
+ fClientInputSocket = newSocketNum;
+ envir().taskScheduler().turnOnBackgroundReadHandling(fClientInputSocket,
+ (TaskScheduler::BackgroundHandlerProc*)&incomingRequestHandler, this);
+
+ // Also write any extra data to our buffer, and handle it:
+ if (extraDataSize > 0 && extraDataSize <= fRequestBufferBytesLeft/*sanity check; should always be true*/) {
+ unsigned char* ptr = &fRequestBuffer[fRequestBytesAlreadySeen];
+ for (unsigned i = 0; i < extraDataSize; ++i) {
+ ptr[i] = extraData[i];
+ }
+ handleRequestBytes(extraDataSize);
+ }
+}
+
////////// ServerMediaSessionIterator implementation //////////
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/SIPClient.cpp
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// A generic SIP client
// Implementation
@@ -606,8 +606,7 @@
delete[] (char*)fUserName; fUserName = strDup(username);
fUserNameSize = strlen(fUserName);
- Authenticator authenticator;
- authenticator.setUsernameAndPassword(username, password);
+ Authenticator authenticator(username, password);
char* inviteResult = invite(url, &authenticator);
if (inviteResult != NULL) {
// We are already authorized
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/ServerMediaSession.cpp
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// A data structure that represents a session that consists of
// potentially multiple (audio and/or video) sub-sessions
// (This data structure is used for media *streamers* - i.e., servers.
@@ -339,7 +339,7 @@
// default implementation: do nothing
}
void ServerMediaSubsession::seekStream(unsigned /*clientSessionId*/,
- void* /*streamToken*/, double /*seekNPT*/) {
+ void* /*streamToken*/, double /*seekNPT*/, double /*streamDuration*/) {
// default implementation: do nothing
}
void ServerMediaSubsession::setStreamScale(unsigned /*clientSessionId*/,
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/SimpleRTPSink.cpp
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// A simple RTP sink that packs frames into each outgoing
// packet, without any fragmentation or special headers.
// Implementation
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/SimpleRTPSource.cpp
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// A RTP source for a simple RTP payload format that
// - doesn't have any special headers following the RTP header
// - doesn't have any special framing apart from the packet data itself
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/StreamParser.cpp
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// Abstract class for parsing a byte stream
// Implementation
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/StreamParser.hh
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// Abstract class for parsing a byte stream
// C++ header
@@ -76,11 +76,14 @@
}
void getBytes(u_int8_t* to, unsigned numBytes) {
- ensureValidBytes(numBytes);
- memmove(to, nextToParse(), numBytes);
+ testBytes(to, numBytes);
fCurParserIndex += numBytes;
fRemainingUnparsedBits = 0;
}
+ void testBytes(u_int8_t* to, unsigned numBytes) { // as above, but doesn't advance ptr
+ ensureValidBytes(numBytes);
+ memmove(to, nextToParse(), numBytes);
+ }
void skipBytes(unsigned numBytes) {
ensureValidBytes(numBytes);
fCurParserIndex += numBytes;
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/VideoRTPSink.cpp
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// A generic RTP sink for video codecs (abstract base class)
// Implementation
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/WAVAudioFileServerMediaSubsession.cpp
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// A 'ServerMediaSubsession' object that creates new, unicast, "RTPSink"s
// on demand, from an WAV audio file.
// Implementation
@@ -43,7 +43,7 @@
}
void WAVAudioFileServerMediaSubsession
-::seekStreamSource(FramedSource* inputSource, double seekNPT) {
+::seekStreamSource(FramedSource* inputSource, double seekNPT, double streamDuration) {
WAVAudioFileSource* wavSource;
if (fBitsPerSample == 16) {
// "inputSource" is a filter; its input source is the original WAV file source:
@@ -56,7 +56,10 @@
unsigned seekSampleNumber = (unsigned)(seekNPT*fSamplingFrequency);
unsigned seekByteNumber = (seekSampleNumber*fNumChannels*fBitsPerSample)/8;
- wavSource->seekToPCMByte(seekByteNumber);
+ unsigned numDurationSamples = (unsigned)(streamDuration*fSamplingFrequency);
+ unsigned numDurationBytes = (numDurationSamples*fNumChannels*fBitsPerSample)/8;
+
+ wavSource->seekToPCMByte(seekByteNumber, numDurationBytes);
}
void WAVAudioFileServerMediaSubsession
@@ -86,9 +89,8 @@
fAudioFormat = wavSource->getAudioFormat();
fBitsPerSample = wavSource->bitsPerSample();
- if (fBitsPerSample != 8 && fBitsPerSample != 16) {
- envir() << "The input file contains " << fBitsPerSample
- << " bit-per-sample audio, which we don't handle\n";
+ if (!(fBitsPerSample == 4 || fBitsPerSample == 8 || fBitsPerSample == 16)) {
+ envir() << "The input file contains " << fBitsPerSample << " bit-per-sample audio, which we don't handle\n";
break;
}
fSamplingFrequency = wavSource->samplingFrequency();
@@ -170,6 +172,21 @@
} else {
payloadFormatCode = rtpPayloadTypeIfDynamic;
}
+ } else if (fAudioFormat == WA_IMA_ADPCM) {
+ mimeType = "DVI4";
+ payloadFormatCode = rtpPayloadTypeIfDynamic; // by default; could be changed below:
+ // Use a static payload type, if one is defined:
+ if (fNumChannels == 1) {
+ if (fSamplingFrequency == 8000) {
+ payloadFormatCode = 5; // a static RTP payload type
+ } else if (fSamplingFrequency == 16000) {
+ payloadFormatCode = 6; // a static RTP payload type
+ } else if (fSamplingFrequency == 11025) {
+ payloadFormatCode = 16; // a static RTP payload type
+ } else if (fSamplingFrequency == 22050) {
+ payloadFormatCode = 17; // a static RTP payload type
+ }
+ }
} else { //unknown format
break;
}
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/WAVAudioFileSource.cpp
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// A WAV audio file source
// Implementation
@@ -57,16 +57,20 @@
// Because we're reading backwards, seek back one sample, to ensure that
// (i) we start reading the last sample before the start point, and
// (ii) we don't hit end-of-file on the first read.
- int const bytesPerSample = (fNumChannels*fBitsPerSample)/8;
+ int bytesPerSample = (fNumChannels*fBitsPerSample)/8;
+ if (bytesPerSample == 0) bytesPerSample = 1;
fseek(fFid, -bytesPerSample, SEEK_CUR);
}
}
-void WAVAudioFileSource::seekToPCMByte(unsigned byteNumber) {
+void WAVAudioFileSource::seekToPCMByte(unsigned byteNumber, unsigned numBytesToStream) {
byteNumber += fWAVHeaderSize;
if (byteNumber > fFileSize) byteNumber = fFileSize;
fseek(fFid, byteNumber, SEEK_SET);
+
+ fNumBytesToStream = numBytesToStream;
+ fLimitNumBytesToStream = fNumBytesToStream > 0;
}
unsigned char WAVAudioFileSource::getAudioFormat() {
@@ -101,15 +105,12 @@
WAVAudioFileSource::WAVAudioFileSource(UsageEnvironment& env, FILE* fid)
: AudioInputDevice(env, 0, 0, 0, 0)/* set the real parameters later */,
fFid(fid), fLastPlayTime(0), fWAVHeaderSize(0), fFileSize(0), fScaleFactor(1),
- fAudioFormat(WA_UNKNOWN) {
+ fLimitNumBytesToStream(False), fNumBytesToStream(0), fAudioFormat(WA_UNKNOWN) {
// Check the WAV file header for validity.
// Note: The following web pages contain info about the WAV format:
- // http://www.technology.niagarac.on.ca/courses/comp630/WavFileFormat.html
- // http://ccrma-www.stanford.edu/CCRMA/Courses/422/projects/WaveFormat/
// http://www.ringthis.com/dev/wave_format.htm
// http://www.lightlink.com/tjweber/StripWav/Canon.html
- // http://www.borg.com/~jglatt/tech/wave.htm
- // http://www.wotsit.org/download.asp?f=wavecomp
+ // http://www.wotsit.org/list.asp?al=W
Boolean success = False; // until we learn otherwise
do {
@@ -126,9 +127,9 @@
if (!get2Bytes(fid, audioFormat)) break;
fAudioFormat = (unsigned char)audioFormat;
- if (fAudioFormat != WA_PCM && fAudioFormat != WA_PCMA && fAudioFormat != WA_PCMU) {
- // not PCM/PCMU/PCMA - we can't handle this
- env.setResultMsg("Audio format is not PCM/PCMU/PCMA");
+ if (fAudioFormat != WA_PCM && fAudioFormat != WA_PCMA && fAudioFormat != WA_PCMU && fAudioFormat != WA_IMA_ADPCM) {
+ // It's a format that we don't (yet) understand
+ env.setResultMsg("Audio format is not one that we handle (PCM/PCMU/PCMA or IMA ADPCM)");
break;
}
unsigned short numChannels;
@@ -145,7 +146,7 @@
env.setResultMsg("Bad sampling frequency: 0");
break;
}
- if (!skipBytes(fid, 6)) break;
+ if (!skipBytes(fid, 6)) break; // "nAvgBytesPerSec" (4 bytes) + "nBlockAlign" (2 bytes)
unsigned short bitsPerSample;
if (!get2Bytes(fid, bitsPerSample)) break;
fBitsPerSample = (unsigned char)bitsPerSample;
@@ -189,8 +190,7 @@
// than 1400 bytes (to ensure that it will fit in a single RTP packet)
unsigned maxSamplesPerFrame = (1400*8)/(fNumChannels*fBitsPerSample);
unsigned desiredSamplesPerFrame = (unsigned)(0.02*fSamplingFrequency);
- unsigned samplesPerFrame = desiredSamplesPerFrame < maxSamplesPerFrame
- ? desiredSamplesPerFrame : maxSamplesPerFrame;
+ unsigned samplesPerFrame = desiredSamplesPerFrame < maxSamplesPerFrame ? desiredSamplesPerFrame : maxSamplesPerFrame;
fPreferredFrameSize = (samplesPerFrame*fNumChannels*fBitsPerSample)/8;
}
@@ -201,21 +201,25 @@
// Note: We should change the following to use asynchronous file reading, #####
// as we now do with ByteStreamFileSource. #####
void WAVAudioFileSource::doGetNextFrame() {
- if (feof(fFid) || ferror(fFid)) {
+ if (feof(fFid) || ferror(fFid) || (fLimitNumBytesToStream && fNumBytesToStream == 0)) {
handleClosure(this);
return;
}
- // Try to read as many bytes as will fit in the buffer provided
- // (or "fPreferredFrameSize" if less)
+ // Try to read as many bytes as will fit in the buffer provided (or "fPreferredFrameSize" if less)
+ if (fLimitNumBytesToStream && fNumBytesToStream < fMaxSize) {
+ fMaxSize = fNumBytesToStream;
+ }
if (fPreferredFrameSize < fMaxSize) {
fMaxSize = fPreferredFrameSize;
}
- unsigned const bytesPerSample = (fNumChannels*fBitsPerSample)/8;
+ unsigned bytesPerSample = (fNumChannels*fBitsPerSample)/8;
+ if (bytesPerSample == 0) bytesPerSample = 1; // because we can't read less than a byte at a time
unsigned bytesToRead = fMaxSize - fMaxSize%bytesPerSample;
if (fScaleFactor == 1) {
// Common case - read samples in bulk:
fFrameSize = fread(fTo, 1, bytesToRead, fFid);
+ fNumBytesToStream -= fFrameSize;
} else {
// We read every 'fScaleFactor'th sample:
fFrameSize = 0;
@@ -224,6 +228,7 @@
if (bytesRead <= 0) break;
fTo += bytesRead;
fFrameSize += bytesRead;
+ fNumBytesToStream -= bytesRead;
bytesToRead -= bytesRead;
// Seek to the appropriate place for the next sample:
|
[-]
[+]
|
Added |
live.2011.06.16.tar.bz2/liveMedia/include/AC3AudioFileServerMediaSubsession.hh
^
|
@@ -0,0 +1,48 @@
+/**********
+This library is free software; you can redistribute it and/or modify it under
+the terms of the GNU Lesser General Public License as published by the
+Free Software Foundation; either version 2.1 of the License, or (at your
+option) any later version. (See <http://www.gnu.org/copyleft/lesser.html>.)
+
+This library 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 Lesser General Public License for
+more details.
+
+You should have received a copy of the GNU Lesser General Public License
+along with this library; if not, write to the Free Software Foundation, Inc.,
+51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+**********/
+// "liveMedia"
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
+// A 'ServerMediaSubsession' object that creates new, unicast, "RTPSink"s
+// on demand, from an AC3 audio file.
+// C++ header
+
+#ifndef _AC3_AUDIO_FILE_SERVER_MEDIA_SUBSESSION_HH
+#define _AC3_AUDIO_FILE_SERVER_MEDIA_SUBSESSION_HH
+
+#ifndef _FILE_SERVER_MEDIA_SUBSESSION_HH
+#include "FileServerMediaSubsession.hh"
+#endif
+
+class AC3AudioFileServerMediaSubsession: public FileServerMediaSubsession{
+public:
+ static AC3AudioFileServerMediaSubsession*
+ createNew(UsageEnvironment& env, char const* fileName, Boolean reuseFirstSource);
+
+private:
+ AC3AudioFileServerMediaSubsession(UsageEnvironment& env,
+ char const* fileName, Boolean reuseFirstSource);
+ // called only by createNew();
+ virtual ~AC3AudioFileServerMediaSubsession();
+
+private: // redefined virtual functions
+ virtual FramedSource* createNewStreamSource(unsigned clientSessionId,
+ unsigned& estBitrate);
+ virtual RTPSink* createNewRTPSink(Groupsock* rtpGroupsock,
+ unsigned char rtpPayloadTypeIfDynamic,
+ FramedSource* inputSource);
+};
+
+#endif
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/include/AC3AudioRTPSink.hh
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// RTP sink for AC3 audio
// C++ header
@@ -41,15 +41,17 @@
virtual ~AC3AudioRTPSink();
private: // redefined virtual functions:
- virtual
- Boolean frameCanAppearAfterPacketStart(unsigned char const* frameStart,
- unsigned numBytesInFrame) const;
+ virtual Boolean frameCanAppearAfterPacketStart(unsigned char const* frameStart,
+ unsigned numBytesInFrame) const;
virtual void doSpecialFrameHandling(unsigned fragmentationOffset,
unsigned char* frameStart,
unsigned numBytesInFrame,
struct timeval frameTimestamp,
unsigned numRemainingBytes);
virtual unsigned specialHeaderSize() const;
+
+private:
+ unsigned char fTotNumFragmentsUsed; // used only if a frame gets fragmented across multiple packets
};
#endif
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/include/AC3AudioRTPSource.hh
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// AC3 Audio RTP Sources
// C++ header
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/include/AC3AudioStreamFramer.hh
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// A filter that breaks up an AC3 audio elementary stream into frames
// C++ header
@@ -29,7 +29,10 @@
public:
static AC3AudioStreamFramer*
createNew(UsageEnvironment& env, FramedSource* inputSource,
- unsigned char streamCode = 0x80);
+ unsigned char streamCode = 0);
+ // If "streamCode" != 0, then we assume that there's a 1-byte code at the beginning of each chunk of data that we read from
+ // our source. If that code is not the value we want, we discard the chunk of data.
+ // However, if "streamCode" == 0 (the default), then we don't expect this 1-byte code.
unsigned samplingRate();
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/include/ADTSAudioFileServerMediaSubsession.hh
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// A 'ServerMediaSubsession' object that creates new, unicast, "RTPSink"s
// on demand, from an AAC audio file in ADTS format
// C++ header
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/include/ADTSAudioFileSource.hh
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// A source object for AAC audio files in ADTS format
// C++ header
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/include/AMRAudioFileServerMediaSubsession.hh
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// A 'ServerMediaSubsession' object that creates new, unicast, "RTPSink"s
// on demand, from an AMR audio file.
// C++ header
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/include/AMRAudioFileSink.hh
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// AMR Audio File Sinks
// C++ header
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/include/AMRAudioFileSource.hh
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// A source object for AMR audio files (as defined in RFC 3267, section 5)
// C++ header
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/include/AMRAudioRTPSink.hh
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// RTP sink for AMR audio (RFC 3267)
// C++ header
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/include/AMRAudioRTPSource.hh
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// AMR Audio RTP Sources (RFC 3267)
// C++ header
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/include/AMRAudioSource.hh
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// A source object for AMR audio sources
// C++ header
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/include/AVIFileSink.hh
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// A sink that generates an AVI file from a composite media session
// C++ header
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/include/AudioInputDevice.hh
^
|
@@ -13,7 +13,7 @@
along with this library; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// Generic audio input device (such as a microphone, or an input sound card)
// C++ header
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/include/AudioRTPSink.hh
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// A generic RTP sink for audio codecs (abstract base class)
// C++ header
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/include/Base64.hh
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// Base64 encoding and decoding
// C++ header
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/include/BasicUDPSink.hh
^
|
@@ -14,12 +14,12 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// A simple UDP sink (i.e., without RTP or other headers added); one frame per packet
// C++ header
-#ifndef _SIMPLE_UDP_SINK_HH
-#define _SIMPLE_UDP_SINK_HH
+#ifndef _BASIC_UDP_SINK_HH
+#define _BASIC_UDP_SINK_HH
#ifndef _MEDIA_SINK_HH
#include "MediaSink.hh"
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/include/BasicUDPSource.hh
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// A simple UDP source, where every UDP payload is a complete frame
// C++ header
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/include/ByteStreamFileSource.hh
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// A file source that is a plain byte stream (rather than frames)
// C++ header
@@ -45,7 +45,8 @@
u_int64_t fileSize() const { return fFileSize; }
// 0 means zero-length, unbounded, or unknown
- void seekToByteAbsolute(u_int64_t byteNumber);
+ void seekToByteAbsolute(u_int64_t byteNumber, u_int64_t numBytesToStream = 0);
+ // if "numBytesToStream" is >0, then we limit the stream to that number of bytes, before treating it as EOF
void seekToByteRelative(int64_t offset);
protected:
@@ -72,6 +73,8 @@
u_int64_t fFileSize;
Boolean fDeleteFidOnClose;
Boolean fHaveStartedReading;
+ Boolean fLimitNumBytesToStream;
+ u_int64_t fNumBytesToStream; // used iff "fLimitNumBytesToStream" is True
};
#endif
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/include/ByteStreamMultiFileSource.hh
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// A source that consists of multiple byte-stream files, read sequentially
// C++ header
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/include/DVVideoFileServerMediaSubsession.hh
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// A 'ServerMediaSubsession' object that creates new, unicast, "RTPSink"s
// on demand, from a DV video file.
// C++ header
@@ -38,7 +38,7 @@
private: // redefined virtual functions
virtual char const* getAuxSDPLine(RTPSink* rtpSink, FramedSource* inputSource);
- virtual void seekStreamSource(FramedSource* inputSource, double seekNPT);
+ virtual void seekStreamSource(FramedSource* inputSource, double seekNPT, double streamDuration);
virtual FramedSource* createNewStreamSource(unsigned clientSessionId, unsigned& estBitrate);
virtual RTPSink* createNewRTPSink(Groupsock* rtpGroupsock, unsigned char rtpPayloadTypeIfDynamic, FramedSource* inputSource);
virtual float duration() const;
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/include/DVVideoRTPSink.hh
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// RTP sink for DV video (RFC 3189)
// (Thanks to Ben Hutchings for prototyping this.)
// C++ header
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/include/DVVideoRTPSource.hh
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// DV Video RTP Sources
// C++ header
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/include/DVVideoStreamFramer.hh
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// A filter that parses a DV input stream into DV frames to deliver to the downstream object
// C++ header
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/include/DarwinInjector.hh
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// An object that redirects one or more RTP/RTCP streams - forming a single
// multimedia session - into a 'Darwin Streaming Server' (for subsequent
// reflection to potentially arbitrarily many remote RTSP clients).
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/include/DeviceSource.hh
^
|
@@ -14,8 +14,11 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// A template for a MediaSource encapsulating an audio/video input device
+//
+// NOTE: Sections of this code labeled "%%% TO BE WRITTEN %%%" are incomplete, and needto be written by the programmer
+// (depending on the features of the particulardevice).
// C++ header
#ifndef _DEVICE_SOURCE_HH
@@ -27,6 +30,7 @@
// The following class can be used to define specific encoder parameters
class DeviceParameters {
+ //%%% TO BE WRITTEN %%%
};
class DeviceSource: public FramedSource {
@@ -34,6 +38,9 @@
static DeviceSource* createNew(UsageEnvironment& env,
DeviceParameters params);
+public:
+ static EventTriggerId eventTriggerId;
+
protected:
DeviceSource(UsageEnvironment& env, DeviceParameters params);
// called only by createNew(), or by subclass constructors
@@ -44,9 +51,11 @@
virtual void doGetNextFrame();
private:
+ static void deliverFrame0(void* clientData);
void deliverFrame();
private:
+ static unsigned referenceCount; // used to count how many instances of this class currently exist
DeviceParameters fParams;
};
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/include/DigestAuthentication.hh
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// A class used for digest authentication.
// C++ header
@@ -32,7 +32,9 @@
class Authenticator {
public:
Authenticator();
- Authenticator(char const* username, char const* password);
+ Authenticator(char const* username, char const* password, Boolean passwordIsMD5 = False);
+ // If "passwordIsMD5" is True, then "password" is actually the value computed
+ // by md5(<username>:<realm>:<actual-password>)
Authenticator(const Authenticator& orig);
Authenticator& operator=(const Authenticator& rightSide);
virtual ~Authenticator();
@@ -42,8 +44,7 @@
void setRealmAndRandomNonce(char const* realm);
// as above, except that the nonce is created randomly.
// (This is used by servers.)
- void setUsernameAndPassword(char const* username, char const* password,
- Boolean passwordIsMD5 = False);
+ void setUsernameAndPassword(char const* username, char const* password, Boolean passwordIsMD5 = False);
// If "passwordIsMD5" is True, then "password" is actually the value computed
// by md5(<username>:<realm>:<actual-password>)
@@ -59,8 +60,7 @@
void resetRealmAndNonce();
void resetUsernameAndPassword();
void assignRealmAndNonce(char const* realm, char const* nonce);
- void assignUsernameAndPassword(char const* username, char const* password,
- Boolean passwordIsMD5);
+ void assignUsernameAndPassword(char const* username, char const* password, Boolean passwordIsMD5);
void assign(char const* realm, char const* nonce,
char const* username, char const* password, Boolean passwordIsMD5);
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/include/FileServerMediaSubsession.hh
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// A 'ServerMediaSubsession' object that creates new, unicast, "RTPSink"s
// on demand, from a file.
// C++ header
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/include/FileSink.hh
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// File Sinks
// C++ header
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/include/FramedFileSource.hh
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// Framed File Sources
// C++ header
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/include/FramedFilter.hh
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// Framed Filters
// C++ header
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/include/FramedSource.hh
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// Framed Sources
// C++ header
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/include/GSMAudioRTPSink.hh
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// RTP sink for GSM audio
// C++ header
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/include/H261VideoRTPSource.hh
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// H.261 Video RTP Sources
// C++ header
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/include/H263plusVideoFileServerMediaSubsession.hh
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// A 'ServerMediaSubsession' object that creates new, unicast, "RTPSink"s
// on demand, from a H.263 video file.
// C++ header
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/include/H263plusVideoRTPSink.hh
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// RTP sink for H.263+ video (RFC 4629)
// C++ header
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/include/H263plusVideoRTPSource.hh
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// H.263+ Video RTP Sources
// C++ header
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/include/H263plusVideoStreamFramer.hh
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// A filter that breaks up an H263 video elementary stream into frames.
// Author Benhard Feiten
@@ -52,7 +52,7 @@
virtual Boolean isH263plusVideoStreamFramer() const;
protected:
- double fFrameRate; // Note: For MPEG-4, this is really a 'tick rate' ??
+ double fFrameRate;
unsigned fPictureCount; // hack used to implement doGetNextFrame() ??
Boolean fPictureEndMarker;
|
[-]
[+]
|
Added |
live.2011.06.16.tar.bz2/liveMedia/include/H264VideoFileServerMediaSubsession.hh
^
|
@@ -0,0 +1,61 @@
+/**********
+This library is free software; you can redistribute it and/or modify it under
+the terms of the GNU Lesser General Public License as published by the
+Free Software Foundation; either version 2.1 of the License, or (at your
+option) any later version. (See <http://www.gnu.org/copyleft/lesser.html>.)
+
+This library 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 Lesser General Public License for
+more details.
+
+You should have received a copy of the GNU Lesser General Public License
+along with this library; if not, write to the Free Software Foundation, Inc.,
+51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+**********/
+// "liveMedia"
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
+// A 'ServerMediaSubsession' object that creates new, unicast, "RTPSink"s
+// on demand, from a H264 Elementary Stream video file.
+// C++ header
+
+#ifndef _H264_VIDEO_FILE_SERVER_MEDIA_SUBSESSION_HH
+#define _H264_VIDEO_FILE_SERVER_MEDIA_SUBSESSION_HH
+
+#ifndef _FILE_SERVER_MEDIA_SUBSESSION_HH
+#include "FileServerMediaSubsession.hh"
+#endif
+
+class H264VideoFileServerMediaSubsession: public FileServerMediaSubsession{
+public:
+ static H264VideoFileServerMediaSubsession*
+ createNew(UsageEnvironment& env, char const* fileName, Boolean reuseFirstSource);
+
+ // Used to implement "getAuxSDPLine()":
+ void checkForAuxSDPLine1();
+ void afterPlayingDummy1();
+
+private:
+ H264VideoFileServerMediaSubsession(UsageEnvironment& env,
+ char const* fileName, Boolean reuseFirstSource);
+ // called only by createNew();
+ virtual ~H264VideoFileServerMediaSubsession();
+
+ void setDoneFlag() { fDoneFlag = ~0; }
+
+private: // redefined virtual functions
+ virtual char const* getAuxSDPLine(RTPSink* rtpSink,
+ FramedSource* inputSource);
+ virtual FramedSource* createNewStreamSource(unsigned clientSessionId,
+ unsigned& estBitrate);
+ virtual RTPSink* createNewRTPSink(Groupsock* rtpGroupsock,
+ unsigned char rtpPayloadTypeIfDynamic,
+ FramedSource* inputSource);
+
+private:
+ char* fAuxSDPLine;
+ char fDoneFlag; // used when setting up "fAuxSDPLine"
+ RTPSink* fDummyRTPSink; // ditto
+};
+
+#endif
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/include/H264VideoFileSink.hh
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// H.264 Video File Sinks
// C++ header
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/include/H264VideoRTPSink.hh
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// RTP sink for H.264 video (RFC 3984)
// C++ header
@@ -34,15 +34,11 @@
public:
static H264VideoRTPSink* createNew(UsageEnvironment& env,
Groupsock* RTPgs,
- unsigned char rtpPayloadFormat,
- unsigned profile_level_id,
- char const* sprop_parameter_sets_str);
+ unsigned char rtpPayloadFormat);
protected:
H264VideoRTPSink(UsageEnvironment& env, Groupsock* RTPgs,
- unsigned char rtpPayloadFormat,
- unsigned profile_level_id,
- char const* sprop_parameter_sets_str);
+ unsigned char rtpPayloadFormat);
// called only by createNew()
virtual ~H264VideoRTPSink();
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/include/H264VideoRTPSource.hh
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// H.264 Video RTP Sources
// C++ header
|
[-]
[+]
|
Added |
live.2011.06.16.tar.bz2/liveMedia/include/H264VideoStreamDiscreteFramer.hh
^
|
@@ -0,0 +1,57 @@
+/**********
+This library is free software; you can redistribute it and/or modify it under
+the terms of the GNU Lesser General Public License as published by the
+Free Software Foundation; either version 2.1 of the License, or (at your
+option) any later version. (See <http://www.gnu.org/copyleft/lesser.html>.)
+
+This library 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 Lesser General Public License for
+more details.
+
+You should have received a copy of the GNU Lesser General Public License
+along with this library; if not, write to the Free Software Foundation, Inc.,
+51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+**********/
+// "liveMedia"
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
+// A simplified version of "H264VideoStreamFramer" that takes only complete,
+// discrete frames (rather than an arbitrary byte stream) as input.
+// This avoids the parsing and data copying overhead of the full
+// "H264VideoStreamFramer".
+// C++ header
+
+#ifndef _H264_VIDEO_STREAM_DISCRETE_FRAMER_HH
+#define _H264_VIDEO_STREAM_DISCRETE_FRAMER_HH
+
+#ifndef _H264_VIDEO_STREAM_FRAMER_HH
+#include "H264VideoStreamFramer.hh"
+#endif
+
+class H264VideoStreamDiscreteFramer: public H264VideoStreamFramer {
+public:
+ static H264VideoStreamDiscreteFramer*
+ createNew(UsageEnvironment& env, FramedSource* inputSource);
+
+protected:
+ H264VideoStreamDiscreteFramer(UsageEnvironment& env,
+ FramedSource* inputSource);
+ // called only by createNew()
+ virtual ~H264VideoStreamDiscreteFramer();
+
+protected:
+ // redefined virtual functions:
+ virtual void doGetNextFrame();
+
+protected:
+ static void afterGettingFrame(void* clientData, unsigned frameSize,
+ unsigned numTruncatedBytes,
+ struct timeval presentationTime,
+ unsigned durationInMicroseconds);
+ void afterGettingFrame1(unsigned frameSize,
+ unsigned numTruncatedBytes,
+ struct timeval presentationTime,
+ unsigned durationInMicroseconds);
+};
+
+#endif
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/include/H264VideoStreamFramer.hh
^
|
@@ -14,32 +14,50 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
-// Any source that feeds into a "H264VideoRTPSink" must be of this class.
-// This is a virtual base class; subclasses must implement the
-// "currentNALUnitEndsAccessUnit()" virtual function.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
+// A filter that breaks up a H.264 Video Elementary Stream into NAL units.
// C++ header
#ifndef _H264_VIDEO_STREAM_FRAMER_HH
#define _H264_VIDEO_STREAM_FRAMER_HH
-#ifndef _FRAMED_FILTER_HH
-#include "FramedFilter.hh"
+#ifndef _MPEG_VIDEO_STREAM_FRAMER_HH
+#include "MPEGVideoStreamFramer.hh"
#endif
-class H264VideoStreamFramer: public FramedFilter {
+class H264VideoStreamFramer: public MPEGVideoStreamFramer {
public:
- virtual Boolean currentNALUnitEndsAccessUnit() = 0;
- // subclasses must define this function. It returns True iff the
- // most recently received NAL unit ends a video 'access unit' (i.e., 'frame')
+ static H264VideoStreamFramer* createNew(UsageEnvironment& env, FramedSource* inputSource,
+ Boolean includeStartCodeInOutput = False);
+
+ void getSPSandPPS(u_int8_t*& sps, unsigned& spsSize, u_int8_t*& pps, unsigned& ppsSize) const{
+ // Returns pointers to copies of the most recently seen SPS (sequence parameter set) and PPS (picture parameter set) NAL unit.
+ // (NULL pointers are returned if the NAL units have not yet been seen.)
+ sps = fLastSeenSPS; spsSize = fLastSeenSPSSize;
+ pps = fLastSeenPPS; ppsSize = fLastSeenPPSSize;
+ }
protected:
- H264VideoStreamFramer(UsageEnvironment& env, FramedSource* inputSource);
+ H264VideoStreamFramer(UsageEnvironment& env, FramedSource* inputSource, Boolean createParser, Boolean includeStartCodeInOutput);
virtual ~H264VideoStreamFramer();
-private:
+ void saveCopyOfSPS(u_int8_t* from, unsigned size);
+ void saveCopyOfPPS(u_int8_t* from, unsigned size);
+
// redefined virtual functions:
virtual Boolean isH264VideoStreamFramer() const;
+
+private:
+ void setPresentationTime() { fPresentationTime = fNextPresentationTime; }
+
+private:
+ Boolean fIncludeStartCodeInOutput;
+ u_int8_t* fLastSeenSPS;
+ unsigned fLastSeenSPSSize;
+ u_int8_t* fLastSeenPPS;
+ unsigned fLastSeenPPSSize;
+ struct timeval fNextPresentationTime; // the presentation time to be used for the next NAL unit to be parsed/delivered after this
+ friend class H264VideoStreamParser; // hack
};
#endif
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/include/HTTPSink.hh
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// HTTP Sinks
// C++ header
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/include/InputFile.hh
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// Common routines for opening/closing named input files
// C++ header
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/include/JPEGVideoRTPSink.hh
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// RTP sink for JPEG video (RFC 2435)
// C++ header
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/include/JPEGVideoRTPSource.hh
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// JPEG Video (RFC 2435) RTP Sources
// C++ header
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/include/JPEGVideoSource.hh
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// JPEG video sources
// C++ header
@@ -39,6 +39,10 @@
// (The default implementation of this function just returns NULL.)
// "precision" and "length" are as defined in RFC 2435, section 3.1.8.
+ virtual u_int16_t restartInterval();
+ // If restart intervals are being used (i.e., 64 <= type() <= 127), then this function must be
+ // redefined - by a subclass - to return a non-zero value.
+
protected:
JPEGVideoSource(UsageEnvironment& env); // abstract base class
virtual ~JPEGVideoSource();
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/include/Locale.hh
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// Support for temporarily setting the locale (e.g., to POSIX) for (e.g.) parsing or printing
// floating-point numbers in protocol headers, or calling toupper()/tolower() on human-input strings.
// C++ header
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/include/MP3ADU.hh
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// 'ADU' MP3 streams (for improved loss-tolerance)
// C++ header
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/include/MP3ADURTPSink.hh
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// RTP sink for 'ADUized' MP3 frames ("mpa-robust")
// C++ header
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/include/MP3ADURTPSource.hh
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// RTP source for 'ADUized' MP3 frames ("mpa-robust")
// C++ header
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/include/MP3ADUTranscoder.hh
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// Transcoder for ADUized MP3 frames
// C++ header
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/include/MP3ADUinterleaving.hh
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// Interleaving of MP3 ADUs
// C++ header
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/include/MP3AudioFileServerMediaSubsession.hh
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// A 'ServerMediaSubsession' object that creates new, unicast, "RTPSink"s
// on demand, from an MP3 audio file.
// (Actually, any MPEG-1 or MPEG-2 audio file should work.)
@@ -47,7 +47,7 @@
virtual ~MP3AudioFileServerMediaSubsession();
private: // redefined virtual functions
- virtual void seekStreamSource(FramedSource* inputSource, double seekNPT);
+ virtual void seekStreamSource(FramedSource* inputSource, double seekNPT, double streamDuration);
virtual void setStreamSourceScale(FramedSource* inputSource, float scale);
virtual FramedSource* createNewStreamSource(unsigned clientSessionId,
unsigned& estBitrate);
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/include/MP3FileSource.hh
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// MP3 File Sources
// C++ header
@@ -32,8 +32,10 @@
static MP3FileSource* createNew(UsageEnvironment& env, char const* fileName);
float filePlayTime() const;
+ unsigned fileSize() const;
void setPresentationTimeScale(unsigned scale);
- void seekWithinFile(double seekNPT);
+ void seekWithinFile(double seekNPT, double streamDuration);
+ // if "streamDuration" is >0.0, then we limit the stream to that duration, before treating it as EOF
protected:
MP3FileSource(UsageEnvironment& env, FILE* fid);
@@ -60,6 +62,8 @@
MP3StreamState* fStreamState;
Boolean fHaveJustInitialized;
struct timeval fFirstFramePresentationTime; // set on stream init
+ Boolean fLimitNumBytesToStream;
+ unsigned fNumBytesToStream; // used iff "fLimitNumBytesToStream" is True
};
#endif
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/include/MP3HTTPSource.hh
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// MP3 HTTP Sources
// C++ header
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/include/MP3Transcoder.hh
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// MP3 Transcoder
// C++ header
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/include/MPEG1or2AudioRTPSink.hh
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// RTP sink for MPEG audio (RFC 2250)
// C++ header
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/include/MPEG1or2AudioRTPSource.hh
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// MPEG-1 or MPEG-2 Audio RTP Sources
// C++ header
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/include/MPEG1or2AudioStreamFramer.hh
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// A filter that breaks up an MPEG (1,2) audio elementary stream into frames
// C++ header
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/include/MPEG1or2Demux.hh
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// Demultiplexer for a MPEG 1 or 2 Program Stream
// C++ header
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/include/MPEG1or2DemuxedElementaryStream.hh
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// A MPEG 1 or 2 Elementary Stream, demultiplexed from a Program Stream
// C++ header
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/include/MPEG1or2DemuxedServerMediaSubsession.hh
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// A 'ServerMediaSubsession' object that creates new, unicast, "RTPSink"s
// on demand, from a MPEG-1 or 2 demuxer.
// C++ header
@@ -45,7 +45,7 @@
virtual ~MPEG1or2DemuxedServerMediaSubsession();
private: // redefined virtual functions
- virtual void seekStreamSource(FramedSource* inputSource, double seekNPT);
+ virtual void seekStreamSource(FramedSource* inputSource, double seekNPT, double streamDuration);
virtual FramedSource* createNewStreamSource(unsigned clientSessionId,
unsigned& estBitrate);
virtual RTPSink* createNewRTPSink(Groupsock* rtpGroupsock,
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/include/MPEG1or2FileServerDemux.hh
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// A server demultiplexer for a MPEG 1 or 2 Program Stream
// C++ header
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/include/MPEG1or2VideoFileServerMediaSubsession.hh
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// A 'ServerMediaSubsession' object that creates new, unicast, "RTPSink"s
// on demand, from a MPEG-1 or 2 Elementary Stream video file.
// C++ header
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/include/MPEG1or2VideoHTTPSink.hh
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// A HTTP Sink specifically for MPEG Video
// C++ header
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/include/MPEG1or2VideoRTPSink.hh
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// RTP sink for MPEG video (RFC 2250)
// C++ header
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/include/MPEG1or2VideoRTPSource.hh
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// MPEG-1 or MPEG-2 Video RTP Sources
// C++ header
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/include/MPEG1or2VideoStreamDiscreteFramer.hh
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// A simplified version of "MPEG1or2VideoStreamFramer" that takes only
// complete, discrete frames (rather than an arbitrary byte stream) as input.
// This avoids the parsing and data copying overhead of the full
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/include/MPEG1or2VideoStreamFramer.hh
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// A filter that breaks up an MPEG 1 or 2 video elementary stream into
// frames for: Video_Sequence_Header, GOP_Header, Picture_Header
// C++ header
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/include/MPEG2IndexFromTransportStream.hh
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// A filter that produces a sequence of I-frame indices from a MPEG-2 Transport Stream
// C++ header
@@ -73,6 +73,7 @@
void addToTail(IndexRecord* newIndexRecord);
private:
+ Boolean fIsH264; // True iff the video is H.264 (encapsulated in a Transport Stream)
unsigned long fInputTransportPacketCounter;
unsigned fClosureNumber;
u_int8_t fLastContinuityCounter;
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/include/MPEG2TransportFileServerMediaSubsession.hh
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// A 'ServerMediaSubsession' object that creates new, unicast, "RTPSink"s
// on demand, from a MPEG-2 Transport Stream file.
// C++ header
@@ -59,7 +59,7 @@
ServerRequestAlternativeByteHandler* serverRequestAlternativeByteHandler,
void* serverRequestAlternativeByteHandlerClientData);
virtual void pauseStream(unsigned clientSessionId, void* streamToken);
- virtual void seekStream(unsigned clientSessionId, void* streamToken, double seekNPT);
+ virtual void seekStream(unsigned clientSessionId, void* streamToken, double seekNPT, double streamDuration);
virtual void setStreamScale(unsigned clientSessionId, void* streamToken, float scale);
virtual void deleteStream(unsigned clientSessionId, void*& streamToken);
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/include/MPEG2TransportStreamFramer.hh
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// A filter that passes through (unchanged) chunks that contain an integral number
// of MPEG-2 Transport Stream packets, but returning (in "fDurationInMicroseconds")
// an updated estimate of the time gap between chunks.
@@ -41,6 +41,7 @@
void changeInputSource(FramedSource* newInputSource) { fInputSource = newInputSource; }
void clearPIDStatusTable();
+ void setNumTSPacketsToStream(unsigned long numTSRecordsToStream);
protected:
MPEG2TransportStreamFramer(UsageEnvironment& env, FramedSource* inputSource);
@@ -67,6 +68,8 @@
double fTSPacketDurationEstimate;
HashTable* fPIDStatusTable;
unsigned long fTSPCRCount;
+ Boolean fLimitNumTSPacketsToStream;
+ unsigned long fNumTSPacketsToStream; // used iff "fLimitNumTSPacketsToStream" is True
};
#endif
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/include/MPEG2TransportStreamFromESSource.hh
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// A filter for converting one or more MPEG Elementary Streams
// to a MPEG-2 Transport Stream
// C++ header
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/include/MPEG2TransportStreamFromPESSource.hh
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// A filter for converting a stream of MPEG PES packets to a MPEG-2 Transport Stream
// C++ header
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/include/MPEG2TransportStreamIndexFile.hh
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// A class that encapsulates MPEG-2 Transport Stream 'index files'/
// These index files are used to implement 'trick play' operations
// (seek-by-time, fast forward, reverse play) on Transport Stream files.
@@ -46,10 +46,10 @@
// (This may modify "npt" to a more exact value.)
// (We also return the index record number that we looked up.)
- void lookupPCRFromTSPacketNum(unsigned long& tsPacketNumber, Boolean reverseToPreviousVSH,
+ void lookupPCRFromTSPacketNum(unsigned long& tsPacketNumber, Boolean reverseToPreviousCleanPoint,
float& pcr, unsigned long& indexRecordNumber);
// Looks up the PCR timestamp for the transport packet "tsPacketNumber".
- // (Adjust "tsPacketNumber" only if "reverseToPreviousVSH" is True.)
+ // (Adjust "tsPacketNumber" only if "reverseToPreviousCleanPoint" is True.)
// (We also return the index record number that we looked up.)
// Miscellaneous functions used to implement 'trick play':
@@ -59,6 +59,10 @@
float getPlayingDuration();
void stopReading() { closeFid(); }
+ int mpegVersion();
+ // returns the best guess for the version of MPEG being used for data within the underlying Transport Stream file.
+ // (1,2,4, or 5 (representing H.264). 0 means 'don't know' (usually because the index file is empty))
+
private:
MPEG2TransportStreamIndexFile(UsageEnvironment& env, char const* indexFileName);
@@ -73,13 +77,15 @@
u_int8_t sizeFromBuf() { return fBuf[2]; }
float pcrFromBuf(); // after "fBuf" has been read
unsigned long tsPacketNumFromBuf();
+ void setMPEGVersionFromRecordType(u_int8_t recordType);
- Boolean rewindToVSH(unsigned long&ixFound);
+ Boolean rewindToCleanPoint(unsigned long&ixFound);
// used to implement "lookupTSPacketNumber()"
private:
char* fFileName;
FILE* fFid; // used internally when reading from the file
+ int fMPEGVersion;
unsigned long fCurrentIndexRecordNum; // within "fFid"
float fCachedPCR;
unsigned long fCachedTSPacketNumber, fCachedIndexRecordNumber;
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/include/MPEG2TransportStreamMultiplexor.hh
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// A class for generating MPEG-2 Transport Stream from one or more input
// Elementary Stream data sources
// C++ header
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/include/MPEG2TransportStreamTrickModeFilter.hh
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.// A filter that converts a MPEG Transport Stream file - with corresponding index file
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.// A filter that converts a MPEG Transport Stream file - with corresponding index file
// - to a corresponding Video Elementary Stream. It also uses a "scale" parameter
// to implement 'trick mode' (fast forward or reverse play, using I-frames) on
// the video stream.
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/include/MPEG4ESVideoRTPSink.hh
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// RTP sink for MPEG-4 Elementary Stream video (RFC 3016)
// C++ header
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/include/MPEG4ESVideoRTPSource.hh
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// MP4V-ES video RTP stream sources
// C++ header
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/include/MPEG4GenericRTPSink.hh
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// MPEG4-GENERIC ("audio", "video", or "application") RTP stream sinks
// C++ header
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/include/MPEG4GenericRTPSource.hh
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// MPEG4-GENERIC ("audio", "video", or "application") RTP stream sources
// C++ header
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/include/MPEG4LATMAudioRTPSink.hh
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// RTP sink for MPEG-4 audio, using LATM multiplexing (RFC 3016)
// (Note that the initial 'size' field is assumed to be present at the start of
// each frame.)
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/include/MPEG4LATMAudioRTPSource.hh
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// MPEG-4 audio, using LATM multiplexing
// C++ header
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/include/MPEG4VideoFileServerMediaSubsession.hh
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// A 'ServerMediaSubsession' object that creates new, unicast, "RTPSink"s
// on demand, from a MPEG-4 video file.
// C++ header
@@ -53,7 +53,8 @@
FramedSource* inputSource);
private:
- char fDoneFlag; // used when setting up "fSDPLines"
+ char* fAuxSDPLine;
+ char fDoneFlag; // used when setting up "fAuxSDPLine"
RTPSink* fDummyRTPSink; // ditto
};
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/include/MPEG4VideoStreamDiscreteFramer.hh
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// A simplified version of "MPEG4VideoStreamFramer" that takes only complete,
// discrete frames (rather than an arbitrary byte stream) as input.
// This avoids the parsing and data copying overhead of the full
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/include/MPEG4VideoStreamFramer.hh
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// A filter that breaks up an MPEG-4 video elementary stream into
// frames for:
// - Visual Object Sequence (VS) Header + Visual Object (VO) Header
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/include/MPEGVideoStreamFramer.hh
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// A filter that breaks up an MPEG video elementary stream into
// headers and frames
// C++ header
@@ -67,13 +67,13 @@
double fFrameRate; // Note: For MPEG-4, this is really a 'tick rate'
unsigned fPictureCount; // hack used to implement doGetNextFrame()
Boolean fPictureEndMarker;
+ struct timeval fPresentationTimeBase;
// parsing state
class MPEGVideoStreamParser* fParser;
friend class MPEGVideoStreamParser; // hack
private:
- struct timeval fPresentationTimeBase;
TimeCode fCurGOPTimeCode, fPrevGOPTimeCode;
unsigned fPicturesAdjustment;
double fPictureTimeBase;
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/include/Media.hh
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// Medium
// C++ header
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/include/MediaSession.hh
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// A data structure that represents a session that consists of
// potentially multiple (audio and/or video) sub-sessions
// (This data structure is used for media *receivers* - i.e., clients.
@@ -188,6 +188,8 @@
char const* fmtp_config() const { return fConfig; }
char const* fmtp_mode() const { return fMode; }
char const* fmtp_spropparametersets() const { return fSpropParameterSets; }
+ char const* fmtp_emphasis() const { return fEmphasis; }
+ char const* fmtp_channelorder() const { return fChannelOrder; }
netAddressBits connectionEndpointAddress() const;
// Converts "fConnectionEndpointName" to an address (or 0 if unknown)
@@ -266,7 +268,7 @@
unsigned fOctetalign, fProfile_level_id, fRobustsorting;
unsigned fSizelength, fStreamstateindication, fStreamtype;
Boolean fCpresent, fRandomaccessindication;
- char *fConfig, *fMode, *fSpropParameterSets;
+ char *fConfig, *fMode, *fSpropParameterSets, *fEmphasis, *fChannelOrder;
double fPlayStartTime;
double fPlayEndTime;
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/include/MediaSink.hh
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// Media Sinks
// C++ header
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/include/MediaSource.hh
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// Media Sources
// C++ header
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/include/MultiFramedRTPSink.hh
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// RTP sink for a common kind of payload format: Those which pack multiple,
// complete codec frames (as many as possible) into each RTP packet.
// C++ header
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/include/MultiFramedRTPSource.hh
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// RTP source for a common kind of payload format: Those which pack multiple,
// complete codec frames (as many as possible) into each RTP packet.
// C++ header
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/include/OnDemandServerMediaSubsession.hh
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// A 'ServerMediaSubsession' object that creates new, unicast, "RTPSink"s
// on demand.
// C++ header
@@ -28,6 +28,12 @@
#ifndef _RTP_SINK_HH
#include "RTPSink.hh"
#endif
+#ifndef _BASIC_UDP_SINK_HH
+#include "BasicUDPSink.hh"
+#endif
+#ifndef _RTCP_HH
+#include "RTCP.hh"
+#endif
class OnDemandServerMediaSubsession: public ServerMediaSubsession {
protected: // we're a virtual base class
@@ -37,6 +43,7 @@
protected: // redefined virtual functions
virtual char const* sdpLines();
+public://#####@@@@@
virtual void getStreamParameters(unsigned clientSessionId,
netAddressBits clientAddress,
Port const& clientRTPPort,
@@ -58,14 +65,15 @@
ServerRequestAlternativeByteHandler* serverRequestAlternativeByteHandler,
void* serverRequestAlternativeByteHandlerClientData);
virtual void pauseStream(unsigned clientSessionId, void* streamToken);
- virtual void seekStream(unsigned clientSessionId, void* streamToken, double seekNPT);
+ virtual void seekStream(unsigned clientSessionId, void* streamToken, double seekNPT, double streamDuration);
virtual void setStreamScale(unsigned clientSessionId, void* streamToken, float scale);
virtual void deleteStream(unsigned clientSessionId, void*& streamToken);
protected: // new virtual functions, possibly redefined by subclasses
virtual char const* getAuxSDPLine(RTPSink* rtpSink,
FramedSource* inputSource);
- virtual void seekStreamSource(FramedSource* inputSource, double seekNPT);
+ virtual void seekStreamSource(FramedSource* inputSource, double seekNPT, double streamDuration);
+ // "streamDuration", if >0.0, specifies how much data to stream, past "seekNPT". (If <=0.0, all remaining data is streamed.)
virtual void setStreamSourceScale(FramedSource* inputSource, float scale);
virtual void closeStreamSource(FramedSource *inputSource);
@@ -94,4 +102,77 @@
friend class StreamState;
};
+
+// A class that represents the state of an ongoing stream. This is used only internally, in the implementation of
+// "OnDemandServerMediaSubsession", but we expose the definition here, in case subclasses of "OnDemandServerMediaSubsession"
+// want to access it.
+class Destinations {
+public:
+ Destinations(struct in_addr const& destAddr,
+ Port const& rtpDestPort,
+ Port const& rtcpDestPort)
+ : isTCP(False), addr(destAddr), rtpPort(rtpDestPort), rtcpPort(rtcpDestPort) {
+ }
+ Destinations(int tcpSockNum, unsigned char rtpChanId, unsigned char rtcpChanId)
+ : isTCP(True), rtpPort(0) /*dummy*/, rtcpPort(0) /*dummy*/,
+ tcpSocketNum(tcpSockNum), rtpChannelId(rtpChanId), rtcpChannelId(rtcpChanId) {
+ }
+
+public:
+ Boolean isTCP;
+ struct in_addr addr;
+ Port rtpPort;
+ Port rtcpPort;
+ int tcpSocketNum;
+ unsigned char rtpChannelId, rtcpChannelId;
+};
+
+class StreamState {
+public:
+ StreamState(OnDemandServerMediaSubsession& master,
+ Port const& serverRTPPort, Port const& serverRTCPPort,
+ RTPSink* rtpSink, BasicUDPSink* udpSink,
+ unsigned totalBW, FramedSource* mediaSource,
+ Groupsock* rtpGS, Groupsock* rtcpGS);
+ virtual ~StreamState();
+
+ void startPlaying(Destinations* destinations,
+ TaskFunc* rtcpRRHandler, void* rtcpRRHandlerClientData,
+ ServerRequestAlternativeByteHandler* serverRequestAlternativeByteHandler,
+ void* serverRequestAlternativeByteHandlerClientData);
+ void pause();
+ void endPlaying(Destinations* destinations);
+ void reclaim();
+
+ unsigned& referenceCount() { return fReferenceCount; }
+
+ Port const& serverRTPPort() const { return fServerRTPPort; }
+ Port const& serverRTCPPort() const { return fServerRTCPPort; }
+
+ RTPSink* rtpSink() const { return fRTPSink; }
+
+ float streamDuration() const { return fStreamDuration; }
+
+ FramedSource* mediaSource() const { return fMediaSource; }
+
+private:
+ OnDemandServerMediaSubsession& fMaster;
+ Boolean fAreCurrentlyPlaying;
+ unsigned fReferenceCount;
+
+ Port fServerRTPPort, fServerRTCPPort;
+
+ RTPSink* fRTPSink;
+ BasicUDPSink* fUDPSink;
+
+ float fStreamDuration;
+ unsigned fTotalBW;
+ RTCPInstance* fRTCPInstance;
+
+ FramedSource* fMediaSource;
+
+ Groupsock* fRTPgs;
+ Groupsock* fRTCPgs;
+};
+
#endif
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/include/OutputFile.hh
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// Common routines for opening/closing named output files
// C++ header
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/include/PassiveServerMediaSubsession.hh
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// A 'ServerMediaSubsession' object that represents an existing
// 'RTPSink', rather than one that creates new 'RTPSink's on demand.
// C++ header
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/include/QCELPAudioRTPSource.hh
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// Qualcomm "PureVoice" (aka. "QCELP") Audio RTP Sources
// C++ header
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/include/QuickTimeFileSink.hh
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// A sink that generates a QuickTime file from a composite media session
// C++ header
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/include/QuickTimeGenericRTPSource.hh
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// RTP Sources containing generic QuickTime stream data, as defined in
// <http://developer.apple.com/quicktime/icefloe/dispatch026.html>
// C++ header
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/include/RTCP.hh
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// RTCP
// C++ header
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/include/RTPInterface.hh
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// An abstraction of a network interface used for RTP (or RTCP).
// (This allows the RTP-over-TCP hack (RFC 2326, section 10.12) to
// be implemented transparently.)
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/include/RTPSink.hh
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// RTP Sinks
// C++ header
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/include/RTPSource.hh
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// RTP Sources
// C++ header
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/include/RTSPClient.hh
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// A generic RTSP client - for a single "rtsp://" URL
// C++ header
@@ -56,6 +56,8 @@
// "resultString" for a successful "DESCRIBE" command will be the media session's SDP description.
// "resultString" for a successful "OPTIONS" command will be a list of allowed commands.
// Note that this string can be present (i.e., not NULL) even if "resultCode" is non-zero - i.e., an error message.
+ // Also, "resultString" can be NULL, even if "resultCode" is zero (e.g., if the RTSP command succeeded, but without
+ // including an appropriate result header).
// Note also that this string is dynamically allocated, and must be freed by the handler (or the caller)
// - using "delete[]".
@@ -142,13 +144,12 @@
RTSPClient*& resultClient);
static Boolean parseRTSPURL(UsageEnvironment& env, char const* url,
- NetAddress& address, portNumBits& portNum, char const** urlSuffix = NULL);
- // (ignores any "<username>[:<password>]@" in "url"); to get those, use:
- static Boolean parseRTSPURLUsernamePassword(char const* url,
- char*& username, char*& password);
+ char*& username, char*& password, NetAddress& address, portNumBits& portNum, char const** urlSuffix = NULL);
+ // Parses "url" as "rtsp://[<username>[:<password>]@]<server-address-or-name>[:<port>][/<stream-name>]"
+ // (Note that the returned "username" and "password" are either NULL, or heap-allocated strings that the caller must later delete[].)
void setUserAgentString(char const* userAgentName);
- // sets an alternative string to be used in RTSP "User-Agent:" headers
+ // sets an alternative string to be used in RTSP "User-Agent:" headers
unsigned sessionTimeoutParameter() const { return fSessionTimeoutParameter; }
@@ -222,7 +223,7 @@
char* createAuthenticatorString(char const* cmd, char const* url);
unsigned sendRequest(RequestRecord* request);
void handleRequestError(RequestRecord* request);
- Boolean parseResponseCode(char const* line, unsigned& responseCode, char const*& responseString, Boolean& responseIsHTTP);
+ Boolean parseResponseCode(char const* line, unsigned& responseCode, char const*& responseString);
void handleIncomingRequest();
static Boolean checkForHeader(char const* line, char const* headerName, unsigned headerNameLength, char const*& headerParams);
Boolean parseTransportParams(char const* paramsStr,
@@ -329,6 +330,9 @@
char*& parameterValue);
Boolean teardownMediaSession(MediaSession& session);
Boolean teardownMediaSubsession(MediaSubsession& subsession);
+
+ static Boolean parseRTSPURLUsernamePassword(char const* url,
+ char*& username, char*& password);
private: // used to implement the old interface:
static void responseHandlerForSyncInterface(RTSPClient* rtspClient,
int responseCode, char* responseString);
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/include/RTSPCommon.hh
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// Common routines used by both RTSP clients and servers
// C++ header
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/include/RTSPServer.hh
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// A RTSP server
// C++ header
@@ -91,6 +91,16 @@
// each session's "rtsp://" URL.
// This string is dynamically allocated; caller should delete[]
+ UserAuthenticationDatabase* setAuthenticationDatabase(UserAuthenticationDatabase* newDB);
+ // Changes the server's authentication database to "newDB", returning a pointer to the old database (if there was one).
+ // "newDB" may be NULL (you can use this to disable authentication at runtime, if desired).
+
+ Boolean setUpTunnelingOverHTTP(Port httpPort);
+ // (Attempts to) enable RTSP-over-HTTP tunneling on the specified port.
+ // Returns True iff the specified port can be used in this way (i.e., it's not already being used for a separate HTTP server).
+ // Note: RTSP-over-HTTP tunneling is described in http://developer.apple.com/quicktime/icefloe/dispatch028.html
+ portNumBits httpServerPortNum() const; // in host byte order. (Returns 0 if not present.)
+
protected:
RTSPServer(UsageEnvironment& env,
int ourSocket, Port ourPort,
@@ -141,6 +151,16 @@
char const* cseq, char const* fullRequestStr);
virtual void handleCmd_SET_PARAMETER(ServerMediaSubsession* subsession,
char const* cseq, char const* fullRequestStr);
+ // Support for optional RTSP-over-HTTP tunneling:
+ virtual Boolean parseHTTPRequestString(char* resultCmdName, unsigned resultCmdNameMaxSize,
+ char* urlSuffix, unsigned urlSuffixMaxSize,
+ char* sessionCookie, unsigned sessionCookieMaxSize,
+ char* acceptStr, unsigned acceptStrMaxSize);
+ virtual void handleHTTPCmd_notSupported();
+ virtual void handleHTTPCmd_notFound();
+ virtual void handleHTTPCmd_TunnelingGET(char const* sessionCookie);
+ virtual Boolean handleHTTPCmd_TunnelingPOST(char const* sessionCookie, unsigned char const* extraData, unsigned extraDataSize);
+ virtual void handleHTTPCmd_StreamingGET(char const* urlSuffix, char const* fullRequestStr);
protected:
UsageEnvironment& envir() { return fOurServer.envir(); }
void reclaimStreamStates();
@@ -157,16 +177,19 @@
void noteLiveness();
static void noteClientLiveness(RTSPClientSession* clientSession);
static void livenessTimeoutTask(RTSPClientSession* clientSession);
+ void changeClientInputSocket(int newSocketNum, unsigned char const* extraData, unsigned extraDataSize);
protected:
RTSPServer& fOurServer;
unsigned fOurSessionId;
ServerMediaSession* fOurServerMediaSession;
- int fClientSocket;
+ int fClientInputSocket, fClientOutputSocket;
struct sockaddr_in fClientAddr;
+ char* fSessionCookie; // used for optional RTSP-over-HTTP tunneling
TaskToken fLivenessCheckTask;
unsigned char fRequestBuffer[RTSP_BUFFER_SIZE];
unsigned fRequestBytesAlreadySeen, fRequestBufferBytesLeft;
unsigned char* fLastCRLF;
+ unsigned fBase64RemainderCount; // used for optional RTSP-over-HTTP tunneling (possible values: 0,1,2,3)
unsigned char fResponseBuffer[RTSP_BUFFER_SIZE];
Boolean fIsMulticast, fSessionIsActive, fStreamAfterSETUP;
Authenticator fCurrentAuthenticator; // used if access control is needed
@@ -195,14 +218,22 @@
};
private:
- static void incomingConnectionHandler(void*, int /*mask*/);
- void incomingConnectionHandler1();
+ static void incomingConnectionHandlerRTSP(void*, int /*mask*/);
+ void incomingConnectionHandlerRTSP1();
+
+ static void incomingConnectionHandlerHTTP(void*, int /*mask*/);
+ void incomingConnectionHandlerHTTP1();
+
+ void incomingConnectionHandler(int serverSocket);
private:
friend class RTSPClientSession;
friend class ServerMediaSessionIterator;
- int fServerSocket;
- Port fServerPort;
+ int fRTSPServerSocket;
+ Port fRTSPServerPort;
+ int fHTTPServerSocket; // for optional RTSP-over-HTTP tunneling
+ Port fHTTPServerPort; // ditto
+ HashTable* fClientSessionsForHTTPTunneling; // ditto (maps 'session cookie' strings to "RTSPClientSession"s)
UserAuthenticationDatabase* fAuthDB;
unsigned fReclamationTestSeconds;
HashTable* fServerMediaSessions;
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/include/SIPClient.hh
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// A generic SIP client
// C++ header
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/include/ServerMediaSession.hh
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// A data structure that represents a session that consists of
// potentially multiple (audio and/or video) sub-sessions
// (This data structure is used for media *streamers* - i.e., servers.
@@ -140,7 +140,8 @@
ServerRequestAlternativeByteHandler* serverRequestAlternativeByteHandler,
void* serverRequestAlternativeByteHandlerClientData) = 0;
virtual void pauseStream(unsigned clientSessionId, void* streamToken);
- virtual void seekStream(unsigned clientSessionId, void* streamToken, double seekNPT);
+ virtual void seekStream(unsigned clientSessionId, void* streamToken, double seekNPT, double streamDuration);
+ // "streamDuration", if >0.0, specifies how much data to stream, past "seekNPT". (If <=0.0, all remaining data is streamed.)
virtual void setStreamScale(unsigned clientSessionId, void* streamToken, float scale);
virtual void deleteStream(unsigned clientSessionId, void*& streamToken);
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/include/SimpleRTPSink.hh
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// A simple RTP sink that packs frames into each outgoing
// packet, without any fragmentation or special headers.
// C++ header
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/include/SimpleRTPSource.hh
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// A RTP source for a simple RTP payload format that
// - doesn't have any special headers following the RTP header
// (if necessary, the "offset" parameter can be used to specify a
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/include/VideoRTPSink.hh
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// A generic RTP sink for video codecs (abstract base class)
// C++ header
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/include/WAVAudioFileServerMediaSubsession.hh
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// A 'ServerMediaSubsession' object that creates new, unicast, "RTPSink"s
// on demand, from an WAV audio file.
// C++ header
@@ -41,7 +41,7 @@
virtual ~WAVAudioFileServerMediaSubsession();
protected: // redefined virtual functions
- virtual void seekStreamSource(FramedSource* inputSource, double seekNPT);
+ virtual void seekStreamSource(FramedSource* inputSource, double seekNPT, double streamDuration);
virtual void setStreamSourceScale(FramedSource* inputSource, float scale);
virtual FramedSource* createNewStreamSource(unsigned clientSessionId,
unsigned& estBitrate);
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/include/WAVAudioFileSource.hh
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// A WAV audio file source
// NOTE: Samples are returned in little-endian order (the same order in which
// they were stored in the file).
@@ -28,11 +28,12 @@
#endif
typedef enum {
- WA_PCM = 1,
- WA_PCMA = 6,
- WA_PCMU = 7,
+ WA_PCM = 0x01,
+ WA_PCMA = 0x06,
+ WA_PCMU = 0x07,
+ WA_IMA_ADPCM = 0x11,
WA_UNKNOWN
-}WAV_AUDIO_FORMAT;
+} WAV_AUDIO_FORMAT;
class WAVAudioFileSource: public AudioInputDevice {
@@ -43,7 +44,8 @@
unsigned numPCMBytes() const;
void setScaleFactor(int scale);
- void seekToPCMByte(unsigned byteNumber);
+ void seekToPCMByte(unsigned byteNumber, unsigned numBytesToStream);
+ // if "numBytesToStream" is >0, then we limit the stream to that number of bytes, before treating it as EOF
unsigned char getAudioFormat();
@@ -67,7 +69,8 @@
unsigned fWAVHeaderSize;
unsigned fFileSize;
int fScaleFactor;
-
+ Boolean fLimitNumBytesToStream;
+ unsigned fNumBytesToStream; // used iff "fLimitNumBytesToStream" is True
unsigned char fAudioFormat;
};
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/include/liveMedia.hh
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// Inclusion of header files representing the interface
// for the entire library
//
@@ -38,7 +38,7 @@
#include "DVVideoRTPSource.hh"
#include "DVVideoRTPSink.hh"
#include "DVVideoStreamFramer.hh"
-#include "H264VideoStreamFramer.hh"
+#include "H264VideoStreamDiscreteFramer.hh"
#include "JPEGVideoRTPSink.hh"
#include "SimpleRTPSink.hh"
#include "uLawAudioFilter.hh"
@@ -82,7 +82,6 @@
#include "AudioInputDevice.hh"
#include "WAVAudioFileSource.hh"
#include "RTSPServer.hh"
-#include "RTSPOverHTTPServer.hh"
#include "RTSPClient.hh"
#include "SIPClient.hh"
#include "QuickTimeFileSink.hh"
@@ -90,6 +89,7 @@
#include "AVIFileSink.hh"
#include "PassiveServerMediaSubsession.hh"
#include "MPEG4VideoFileServerMediaSubsession.hh"
+#include "H264VideoFileServerMediaSubsession.hh"
#include "WAVAudioFileServerMediaSubsession.hh"
#include "AMRAudioFileServerMediaSubsession.hh"
#include "AMRAudioFileSource.hh"
@@ -101,6 +101,7 @@
#include "H263plusVideoFileServerMediaSubsession.hh"
#include "ADTSAudioFileServerMediaSubsession.hh"
#include "DVVideoFileServerMediaSubsession.hh"
+#include "AC3AudioFileServerMediaSubsession.hh"
#include "DarwinInjector.hh"
#endif
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/include/liveMedia_version.hh
^
|
@@ -1,10 +1,10 @@
// Version information for the "liveMedia" library
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
#ifndef _LIVEMEDIA_VERSION_HH
#define _LIVEMEDIA_VERSION_HH
-#define LIVEMEDIA_LIBRARY_VERSION_STRING "2010.09.25"
-#define LIVEMEDIA_LIBRARY_VERSION_INT 1285372800
+#define LIVEMEDIA_LIBRARY_VERSION_STRING "2011.06.16"
+#define LIVEMEDIA_LIBRARY_VERSION_INT 1308182400
#endif
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/include/uLawAudioFilter.hh
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// Filters for converting between raw PCM audio and uLaw
// C++ header
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/liveMedia/uLawAudioFilter.cpp
^
|
@@ -14,7 +14,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
// "liveMedia"
-// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.
+// Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
// Filters for converting between raw PCM audio and uLaw
// Implementation
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/mediaServer/DynamicRTSPServer.cpp
^
|
@@ -13,7 +13,7 @@
along with this library; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
-// Copyright (c) 1996-2010, Live Networks, Inc. All rights reserved
+// Copyright (c) 1996-2011, Live Networks, Inc. All rights reserved
// A subclass of "RTSPServer" that creates "ServerMediaSession"s on demand,
// based on whether or not the specified stream name exists as a file
// Implementation
@@ -101,10 +101,19 @@
// Assumed to be an AMR Audio file:
NEW_SMS("AMR Audio");
sms->addSubsession(AMRAudioFileServerMediaSubsession::createNew(env, fileName, reuseSource));
+ } else if (strcmp(extension, ".ac3") == 0) {
+ // Assumed to be an AC-3 Audio file:
+ NEW_SMS("AC-3 Audio");
+ sms->addSubsession(AC3AudioFileServerMediaSubsession::createNew(env, fileName, reuseSource));
} else if (strcmp(extension, ".m4e") == 0) {
// Assumed to be a MPEG-4 Video Elementary Stream file:
NEW_SMS("MPEG-4 Video");
sms->addSubsession(MPEG4VideoFileServerMediaSubsession::createNew(env, fileName, reuseSource));
+ } else if (strcmp(extension, ".264") == 0) {
+ // Assumed to be a H.264 Video Elementary Stream file:
+ NEW_SMS("H.264 Video");
+ OutPacketBuffer::maxSize = 100000; // allow for some possibly large H.264 frames
+ sms->addSubsession(H264VideoFileServerMediaSubsession::createNew(env, fileName, reuseSource));
} else if (strcmp(extension, ".mp3") == 0) {
// Assumed to be a MPEG-1 or 2 Audio file:
NEW_SMS("MPEG-1 or 2 Audio");
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/mediaServer/DynamicRTSPServer.hh
^
|
@@ -13,7 +13,7 @@
along with this library; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
-// Copyright (c) 1996-2010, Live Networks, Inc. All rights reserved
+// Copyright (c) 1996-2011, Live Networks, Inc. All rights reserved
// A subclass of "RTSPServer" that creates "ServerMediaSession"s on demand,
// based on whether or not the specified stream name exists as a file
// Header file
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/mediaServer/live555MediaServer.cpp
^
|
@@ -13,13 +13,12 @@
along with this library; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
-// Copyright (c) 1996-2010, Live Networks, Inc. All rights reserved
+// Copyright (c) 1996-2011, Live Networks, Inc. All rights reserved
// LIVE555 Media Server
// main program
#include <BasicUsageEnvironment.hh>
#include "DynamicRTSPServer.hh"
-#include "RTSPOverHTTPServer.hh"
#include "version.hh"
int main(int argc, char** argv) {
@@ -59,10 +58,12 @@
*env << "Play streams from this server using the URL\n\t"
<< urlPrefix << "<filename>\nwhere <filename> is a file present in the current directory.\n";
*env << "Each file's type is inferred from its name suffix:\n";
+ *env << "\t\".264\" => a H.264 Video Elementary Stream file\n";
*env << "\t\".aac\" => an AAC Audio (ADTS format) file\n";
+ *env << "\t\".ac3\" => an AC-3 Audio file\n";
*env << "\t\".amr\" => an AMR Audio file\n";
- *env << "\t\".m4e\" => a MPEG-4 Video Elementary Stream file\n";
*env << "\t\".dv\" => a DV Video file\n";
+ *env << "\t\".m4e\" => a MPEG-4 Video Elementary Stream file\n";
*env << "\t\".mp3\" => a MPEG-1 or 2 Audio file\n";
*env << "\t\".mpg\" => a MPEG-1 or 2 Program Stream (audio+video) file\n";
*env << "\t\".ts\" => a MPEG Transport Stream file\n";
@@ -70,23 +71,15 @@
*env << "\t\".wav\" => a WAV Audio file\n";
*env << "See http://www.live555.com/mediaServer/ for additional documentation.\n";
-#if 0 // RTSP-over-HTTP tunneling is not yet working
// Also, attempt to create a HTTP server for RTSP-over-HTTP tunneling.
// Try first with the default HTTP port (80), and then with the alternative HTTP
- // port number (8000).
- RTSPOverHTTPServer* rtspOverHTTPServer;
- portNumBits httpServerPortNum = 80;
- rtspOverHTTPServer = RTSPOverHTTPServer::createNew(*env, httpServerPortNum, rtspServerPortNum);
- if (rtspOverHTTPServer == NULL) {
- httpServerPortNum = 8000;
- rtspOverHTTPServer = RTSPOverHTTPServer::createNew(*env, httpServerPortNum, rtspServerPortNum);
- }
- if (rtspOverHTTPServer == NULL) {
- *env << "(No server for RTSP-over-HTTP tunneling was created.)\n";
+ // port numbers (8000 and 8080).
+
+ if (rtspServer->setUpTunnelingOverHTTP(80) || rtspServer->setUpTunnelingOverHTTP(8000) || rtspServer->setUpTunnelingOverHTTP(8080)) {
+ *env << "(We use port " << rtspServer->httpServerPortNum() << " for optional RTSP-over-HTTP tunneling.)\n";
} else {
- *env << "(We use port " << httpServerPortNum << " for RTSP-over-HTTP tunneling.)\n";
+ *env << "(RTSP-over-HTTP tunneling is not available.)\n";
}
-#endif
env->taskScheduler().doEventLoop(); // does not return
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/mediaServer/version.hh
^
|
@@ -1,10 +1,10 @@
-// Copyright (c) 1996-2010, Live Networks, Inc. All rights reserved
+// Copyright (c) 1996-2011, Live Networks, Inc. All rights reserved
// Version information for the LIVE555 Media Server application
// Header file
#ifndef _MEDIA_SERVER_VERSION_HH
#define _MEDIA_SERVER_VERSION_HH
-#define MEDIA_SERVER_VERSION_STRING "0.5"
+#define MEDIA_SERVER_VERSION_STRING "0.67"
#endif
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/testProgs/MPEG2TransportStreamIndexer.cpp
^
|
@@ -13,7 +13,7 @@
along with this library; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
-// Copyright (c) 1996-2010, Live Networks, Inc. All rights reserved
+// Copyright (c) 1996-2011, Live Networks, Inc. All rights reserved
// A program that reads an existing MPEG-2 Transport Stream file,
// and generates a separate index file that can be used - by our RTSP server
// implementation - to support 'trick play' operations when streaming the
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/testProgs/Makefile.tail
^
|
@@ -1,6 +1,6 @@
##### End of variables to change
-MULTICAST_STREAMER_APPS = testMP3Streamer$(EXE) testMPEG1or2VideoStreamer$(EXE) testMPEG1or2AudioVideoStreamer$(EXE) testMPEG2TransportStreamer$(EXE) testMPEG4VideoStreamer$(EXE) testDVVideoStreamer$(EXE) testWAVAudioStreamer$(EXE) testAMRAudioStreamer$(EXE) vobStreamer$(EXE)
+MULTICAST_STREAMER_APPS = testMP3Streamer$(EXE) testMPEG1or2VideoStreamer$(EXE) testMPEG1or2AudioVideoStreamer$(EXE) testMPEG2TransportStreamer$(EXE) testMPEG4VideoStreamer$(EXE) testH264VideoStreamer$(EXE) testDVVideoStreamer$(EXE) testWAVAudioStreamer$(EXE) testAMRAudioStreamer$(EXE) vobStreamer$(EXE)
MULTICAST_RECEIVER_APPS = testMP3Receiver$(EXE) testMPEG1or2VideoReceiver$(EXE) sapWatch$(EXE)
MULTICAST_MISC_APPS = testRelay$(EXE)
MULTICAST_APPS = $(MULTICAST_STREAMER_APPS) $(MULTICAST_RECEIVER_APPS) $(MULTICAST_MISC_APPS)
@@ -9,7 +9,7 @@
UNICAST_RECEIVER_APPS = openRTSP$(EXE) playSIP$(EXE)
UNICAST_APPS = $(UNICAST_STREAMER_APPS) $(UNICAST_RECEIVER_APPS)
-MISC_APPS = testMPEG1or2Splitter$(EXE) testMPEG1or2ProgramToTransportStream$(EXE) MPEG2TransportStreamIndexer$(EXE) testMPEG2TransportStreamTrickPlay$(EXE)
+MISC_APPS = testMPEG1or2Splitter$(EXE) testMPEG1or2ProgramToTransportStream$(EXE) testH264VideoToTransportStream$(EXE) MPEG2TransportStreamIndexer$(EXE) testMPEG2TransportStreamTrickPlay$(EXE)
ALL = $(MULTICAST_APPS) $(UNICAST_APPS) $(MISC_APPS)
all: $(ALL)
@@ -31,6 +31,7 @@
MPEG_1OR2_AUDIO_VIDEO_STREAMER_OBJS = testMPEG1or2AudioVideoStreamer.$(OBJ)
MPEG2_TRANSPORT_STREAMER_OBJS = testMPEG2TransportStreamer.$(OBJ)
MPEG4_VIDEO_STREAMER_OBJS = testMPEG4VideoStreamer.$(OBJ)
+H264_VIDEO_STREAMER_OBJS = testH264VideoStreamer.$(OBJ)
DV_VIDEO_STREAMER_OBJS = testDVVideoStreamer.$(OBJ)
WAV_AUDIO_STREAMER_OBJS = testWAVAudioStreamer.$(OBJ)
AMR_AUDIO_STREAMER_OBJS = testAMRAudioStreamer.$(OBJ)
@@ -42,6 +43,7 @@
MPEG_1OR2_AUDIO_VIDEO_TO_DARWIN_OBJS = testMPEG1or2AudioVideoToDarwin.$(OBJ)
MPEG_4_VIDEO_TO_DARWIN_OBJS = testMPEG4VideoToDarwin.$(OBJ)
MPEG_1OR2_PROGRAM_TO_TRANSPORT_STREAM_OBJS = testMPEG1or2ProgramToTransportStream.$(OBJ)
+H264_VIDEO_TO_TRANSPORT_STREAM_OBJS = testH264VideoToTransportStream.$(OBJ)
MPEG2_TRANSPORT_STREAM_INDEXER_OBJS = MPEG2TransportStreamIndexer.$(OBJ)
MPEG2_TRANSPORT_STREAM_TRICK_PLAY_OBJS = testMPEG2TransportStreamTrickPlay.$(OBJ)
@@ -81,6 +83,8 @@
$(LINK)$@ $(CONSOLE_LINK_OPTS) $(MPEG2_TRANSPORT_STREAMER_OBJS) $(LIBS)
testMPEG4VideoStreamer$(EXE): $(MPEG4_VIDEO_STREAMER_OBJS) $(LOCAL_LIBS)
$(LINK)$@ $(CONSOLE_LINK_OPTS) $(MPEG4_VIDEO_STREAMER_OBJS) $(LIBS)
+testH264VideoStreamer$(EXE): $(H264_VIDEO_STREAMER_OBJS) $(LOCAL_LIBS)
+ $(LINK)$@ $(CONSOLE_LINK_OPTS) $(H264_VIDEO_STREAMER_OBJS) $(LIBS)
testDVVideoStreamer$(EXE): $(DV_VIDEO_STREAMER_OBJS) $(LOCAL_LIBS)
$(LINK)$@ $(CONSOLE_LINK_OPTS) $(DV_VIDEO_STREAMER_OBJS) $(LIBS)
testWAVAudioStreamer$(EXE): $(WAV_AUDIO_STREAMER_OBJS) $(LOCAL_LIBS)
@@ -103,6 +107,8 @@
$(LINK)$@ $(CONSOLE_LINK_OPTS) $(MPEG_4_VIDEO_TO_DARWIN_OBJS) $(LIBS)
testMPEG1or2ProgramToTransportStream$(EXE): $(MPEG_1OR2_PROGRAM_TO_TRANSPORT_STREAM_OBJS) $(LOCAL_LIBS)
$(LINK)$@ $(CONSOLE_LINK_OPTS) $(MPEG_1OR2_PROGRAM_TO_TRANSPORT_STREAM_OBJS) $(LIBS)
+testH264VideoToTransportStream$(EXE): $(H264_VIDEO_TO_TRANSPORT_STREAM_OBJS) $(LOCAL_LIBS)
+ $(LINK)$@ $(CONSOLE_LINK_OPTS) $(H264_VIDEO_TO_TRANSPORT_STREAM_OBJS) $(LIBS)
MPEG2TransportStreamIndexer$(EXE): $(MPEG2_TRANSPORT_STREAM_INDEXER_OBJS) $(LOCAL_LIBS)
$(LINK)$@ $(CONSOLE_LINK_OPTS) $(MPEG2_TRANSPORT_STREAM_INDEXER_OBJS) $(LIBS)
testMPEG2TransportStreamTrickPlay$(EXE): $(MPEG2_TRANSPORT_STREAM_TRICK_PLAY_OBJS) $(LOCAL_LIBS)
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/testProgs/openRTSP.cpp
^
|
@@ -13,7 +13,7 @@
along with this library; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
-// Copyright (c) 1996-2010, Live Networks, Inc. All rights reserved
+// Copyright (c) 1996-2011, Live Networks, Inc. All rights reserved
// A RTSP client test program that opens a RTSP URL argument,
// and extracts the data from each incoming RTP stream.
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/testProgs/playCommon.cpp
^
|
@@ -13,7 +13,7 @@
along with this library; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
-// Copyright (c) 1996-2010, Live Networks, Inc. All rights reserved
+// Copyright (c) 1996-2011, Live Networks, Inc. All rights reserved
// A common framework, used for the "openRTSP" and "playSIP" applications
// Implementation
@@ -310,8 +310,7 @@
}
}
- ourAuthenticator = new Authenticator;
- ourAuthenticator->setUsernameAndPassword(username, password);
+ ourAuthenticator = new Authenticator(username,password);
break;
}
@@ -766,8 +765,7 @@
// Also set a handler to be called if a RTCP "BYE" arrives
// for this subsession:
if (subsession->rtcpInstance() != NULL) {
- subsession->rtcpInstance()->setByeHandler(subsessionByeHandler,
- subsession);
+ subsession->rtcpInstance()->setByeHandler(subsessionByeHandler, subsession);
}
madeProgress = True;
@@ -894,7 +892,16 @@
if (!playContinuously) {
shutdown(0);
} else {
- // We've been asked to play the stream(s) over again:
+ // We've been asked to play the stream(s) over again.
+ // First, reset state from the current session:
+ if (env != NULL) {
+ env->taskScheduler().unscheduleDelayedTask(sessionTimerTask);
+ env->taskScheduler().unscheduleDelayedTask(arrivalCheckTimerTask);
+ env->taskScheduler().unscheduleDelayedTask(interPacketGapCheckTimerTask);
+ env->taskScheduler().unscheduleDelayedTask(qosMeasurementTimerTask);
+ }
+ totNumPacketsReceived = ~0;
+
startPlayingSession(session, initialSeekTime, endTime, scale, continueAfterPLAY);
}
}
@@ -1112,8 +1119,12 @@
delete qosRecordHead;
}
+Boolean areAlreadyShuttingDown = False;
int shutdownExitCode;
void shutdown(int exitCode) {
+ if (areAlreadyShuttingDown) return; // in case we're called after receiving a RTCP "BYE" while in the middle of a "TEARDOWN".
+ areAlreadyShuttingDown = True;
+
shutdownExitCode = exitCode;
if (env != NULL) {
env->taskScheduler().unscheduleDelayedTask(sessionTimerTask);
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/testProgs/playCommon.hh
^
|
@@ -13,7 +13,7 @@
along with this library; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
-// Copyright (c) 1996-2010, Live Networks, Inc. All rights reserved
+// Copyright (c) 1996-2011, Live Networks, Inc. All rights reserved
// A common framework, used for the "openRTSP" and "playSIP" applications
// Interfaces
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/testProgs/playSIP.cpp
^
|
@@ -13,7 +13,7 @@
along with this library; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
-// Copyright (c) 1996-2010, Live Networks, Inc. All rights reserved
+// Copyright (c) 1996-2011, Live Networks, Inc. All rights reserved
// A SIP client test program that opens a SIP URL argument,
// and extracts the data from each incoming RTP stream.
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/testProgs/sapWatch.cpp
^
|
@@ -13,7 +13,7 @@
along with this library; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
-// Copyright (c) 1996-2010, Live Networks, Inc. All rights reserved
+// Copyright (c) 1996-2011, Live Networks, Inc. All rights reserved
// A program that receives and prints SDP/SAP announcements
// (on the default SDP/SAP directory: 224.2.127.254/9875)
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/testProgs/testAMRAudioStreamer.cpp
^
|
@@ -13,7 +13,7 @@
along with this library; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
-// Copyright (c) 1996-2010, Live Networks, Inc. All rights reserved
+// Copyright (c) 1996-2011, Live Networks, Inc. All rights reserved
// A test program that reads an AMR audio file (as defined in RFC 3267)
// and streams it using RTP
// main program
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/testProgs/testDVVideoStreamer.cpp
^
|
@@ -13,7 +13,7 @@
along with this library; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
-// Copyright (c) 1996-2010, Live Networks, Inc. All rights reserved
+// Copyright (c) 1996-2011, Live Networks, Inc. All rights reserved
// A test program that reads a DV Video Elementary Stream file,
// and streams it using RTP
// main program
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/testProgs/testGSMStreamer.cpp
^
|
@@ -13,7 +13,7 @@
along with this library; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
-// Copyright (c) 1996-2010, Live Networks, Inc. All rights reserved
+// Copyright (c) 1996-2011, Live Networks, Inc. All rights reserved
// A test program that streams GSM audio via RTP/RTCP
// main program
|
[-]
[+]
|
Added |
live.2011.06.16.tar.bz2/testProgs/testH264VideoStreamer.cpp
^
|
@@ -0,0 +1,126 @@
+/**********
+This library is free software; you can redistribute it and/or modify it under
+the terms of the GNU Lesser General Public License as published by the
+Free Software Foundation; either version 2.1 of the License, or (at your
+option) any later version. (See <http://www.gnu.org/copyleft/lesser.html>.)
+
+This library 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 Lesser General Public License for
+more details.
+
+You should have received a copy of the GNU Lesser General Public License
+along 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-2011, Live Networks, Inc. All rights reserved
+// A test program that reads a H264 video file (with NAL unit lengths embedded)
+// and streams it using RTP
+// main program
+
+#include <liveMedia.hh>
+#include <BasicUsageEnvironment.hh>
+#include <GroupsockHelper.hh>
+
+UsageEnvironment* env;
+char const* inputFileName = "test.264";
+H264VideoStreamFramer* videoSource;
+RTPSink* videoSink;
+
+void play(); // forward
+
+int main(int argc, char** argv) {
+ // Begin by setting up our usage environment:
+ TaskScheduler* scheduler = BasicTaskScheduler::createNew();
+ env = BasicUsageEnvironment::createNew(*scheduler);
+
+ // Create 'groupsocks' for RTP and RTCP:
+ struct in_addr destinationAddress;
+ destinationAddress.s_addr = chooseRandomIPv4SSMAddress(*env);
+ // Note: This is a multicast address. If you wish instead to stream
+ // using unicast, then you should use the "testOnDemandRTSPServer"
+ // test program - not this test program - as a model.
+
+ const unsigned short rtpPortNum = 18888;
+ const unsigned short rtcpPortNum = rtpPortNum+1;
+ const unsigned char ttl = 255;
+
+ const Port rtpPort(rtpPortNum);
+ const Port rtcpPort(rtcpPortNum);
+
+ Groupsock rtpGroupsock(*env, destinationAddress, rtpPort, ttl);
+ rtpGroupsock.multicastSendOnly(); // we're a SSM source
+ Groupsock rtcpGroupsock(*env, destinationAddress, rtcpPort, ttl);
+ rtcpGroupsock.multicastSendOnly(); // we're a SSM source
+
+ // Create a 'H264 Video RTP' sink from the RTP 'groupsock':
+ OutPacketBuffer::maxSize = 100000;
+ videoSink = H264VideoRTPSink::createNew(*env, &rtpGroupsock, 96);
+
+ // Create (and start) a 'RTCP instance' for this RTP sink:
+ const unsigned estimatedSessionBandwidth = 500; // in kbps; for RTCP b/w share
+ const unsigned maxCNAMElen = 100;
+ unsigned char CNAME[maxCNAMElen+1];
+ gethostname((char*)CNAME, maxCNAMElen);
+ CNAME[maxCNAMElen] = '\0'; // just in case
+ RTCPInstance* rtcp
+ = RTCPInstance::createNew(*env, &rtcpGroupsock,
+ estimatedSessionBandwidth, CNAME,
+ videoSink, NULL /* we're a server */,
+ True /* we're a SSM source */);
+ // Note: This starts RTCP running automatically
+
+ RTSPServer* rtspServer = RTSPServer::createNew(*env, 8554);
+ if (rtspServer == NULL) {
+ *env << "Failed to create RTSP server: " << env->getResultMsg() << "\n";
+ exit(1);
+ }
+ ServerMediaSession* sms
+ = ServerMediaSession::createNew(*env, "testStream", inputFileName,
+ "Session streamed by \"testH264VideoStreamer\"",
+ True /*SSM*/);
+ sms->addSubsession(PassiveServerMediaSubsession::createNew(*videoSink, rtcp));
+ rtspServer->addServerMediaSession(sms);
+
+ char* url = rtspServer->rtspURL(sms);
+ *env << "Play this stream using the URL \"" << url << "\"\n";
+ delete[] url;
+
+ // Start the streaming:
+ *env << "Beginning streaming...\n";
+ play();
+
+ env->taskScheduler().doEventLoop(); // does not return
+
+ return 0; // only to prevent compiler warning
+}
+
+void afterPlaying(void* /*clientData*/) {
+ *env << "...done reading from file\n";
+
+ Medium::close(videoSource);
+ // Note that this also closes the input file that this source read from.
+
+ // Start playing once again:
+ play();
+}
+
+void play() {
+ // Open the input file as a 'byte-stream file source':
+ ByteStreamFileSource* fileSource
+ = ByteStreamFileSource::createNew(*env, inputFileName);
+ if (fileSource == NULL) {
+ *env << "Unable to open file \"" << inputFileName
+ << "\" as a byte-stream file source\n";
+ exit(1);
+ }
+
+ FramedSource* videoES = fileSource;
+
+ // Create a framer for the Video Elementary Stream:
+ videoSource = H264VideoStreamFramer::createNew(*env, videoES);
+
+ // Finally, start playing:
+ *env << "Beginning to read from file...\n";
+ videoSink->startPlaying(*videoSource, afterPlaying, videoSink);
+}
|
[-]
[+]
|
Added |
live.2011.06.16.tar.bz2/testProgs/testH264VideoToTransportStream.cpp
^
|
@@ -0,0 +1,70 @@
+/**********
+This library is free software; you can redistribute it and/or modify it under
+the terms of the GNU Lesser General Public License as published by the
+Free Software Foundation; either version 2.1 of the License, or (at your
+option) any later version. (See <http://www.gnu.org/copyleft/lesser.html>.)
+
+This library 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 Lesser General Public License for
+more details.
+
+You should have received a copy of the GNU Lesser General Public License
+along with this library; if not, write to the Free Software Foundation, Inc.,
+51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+**********/
+// Copyright (c) 1996-2011, Live Networks, Inc. All rights reserved
+// A program that converts a H.264 (Elementary Stream) video file into a Transport Stream file.
+// main program
+
+#include "liveMedia.hh"
+#include "BasicUsageEnvironment.hh"
+
+char const* inputFileName = "in.264";
+char const* outputFileName = "out.ts";
+
+void afterPlaying(void* clientData); // forward
+
+UsageEnvironment* env;
+
+int main(int argc, char** argv) {
+ // Begin by setting up our usage environment:
+ TaskScheduler* scheduler = BasicTaskScheduler::createNew();
+ env = BasicUsageEnvironment::createNew(*scheduler);
+
+ // Open the input file as a 'byte-stream file source':
+ FramedSource* inputSource = ByteStreamFileSource::createNew(*env, inputFileName);
+ if (inputSource == NULL) {
+ *env << "Unable to open file \"" << inputFileName
+ << "\" as a byte-stream file source\n";
+ exit(1);
+ }
+
+ // Create a 'framer' filter for this file source, to generate presentation times for each NAL unit:
+ H264VideoStreamFramer* framer = H264VideoStreamFramer::createNew(*env, inputSource, True/*includeStartCodeInOutput*/);
+
+ // Then create a filter that packs the H.264 video data into a Transport Stream:
+ MPEG2TransportStreamFromESSource* tsFrames = MPEG2TransportStreamFromESSource::createNew(*env);
+ tsFrames->addNewVideoSource(framer, 5/*mpegVersion: H.264*/);
+
+ // Open the output file as a 'file sink':
+ MediaSink* outputSink = FileSink::createNew(*env, outputFileName);
+ if (outputSink == NULL) {
+ *env << "Unable to open file \"" << outputFileName << "\" as a file sink\n";
+ exit(1);
+ }
+
+ // Finally, start playing:
+ *env << "Beginning to read...\n";
+ outputSink->startPlaying(*tsFrames, afterPlaying, NULL);
+
+ env->taskScheduler().doEventLoop(); // does not return
+
+ return 0; // only to prevent compiler warning
+}
+
+void afterPlaying(void* /*clientData*/) {
+ *env << "Done reading.\n";
+ *env << "Wrote output file: \"" << outputFileName << "\"\n";
+ exit(0);
+}
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/testProgs/testMP3Receiver.cpp
^
|
@@ -13,7 +13,7 @@
along with this library; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
-// Copyright (c) 1996-2010, Live Networks, Inc. All rights reserved
+// Copyright (c) 1996-2011, Live Networks, Inc. All rights reserved
// A test program that receives a RTP/RTCP multicast MP3 stream,
// and outputs the resulting MP3 file stream to 'stdout'
// main program
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/testProgs/testMP3Streamer.cpp
^
|
@@ -13,7 +13,7 @@
along with this library; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
-// Copyright (c) 1996-2010, Live Networks, Inc. All rights reserved
+// Copyright (c) 1996-2011, Live Networks, Inc. All rights reserved
// A test program that streams a MP3 file via RTP/RTCP
// main program
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/testProgs/testMPEG1or2AudioVideoStreamer.cpp
^
|
@@ -13,7 +13,7 @@
along with this library; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
-// Copyright (c) 1996-2010, Live Networks, Inc. All rights reserved
+// Copyright (c) 1996-2011, Live Networks, Inc. All rights reserved
// A test program that reads a MPEG-1 or 2 Program Stream file,
// splits it into Audio and Video Elementary Streams,
// and streams both using RTP
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/testProgs/testMPEG1or2AudioVideoToDarwin.cpp
^
|
@@ -13,7 +13,7 @@
along with this library; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
-// Copyright (c) 1996-2010, Live Networks, Inc. All rights reserved
+// Copyright (c) 1996-2011, Live Networks, Inc. All rights reserved
// A test program that reads a MPEG-1 or 2 Program Stream file,
// splits it into Audio and Video Elementary Streams,
// and streams both using RTP, through a remote Darwin Streaming Server.
@@ -23,8 +23,8 @@
// This demo software is provided only as a courtesy to those developers who - for whatever reason - wish
// to send outgoing streams through a separate Darwin Streaming Server. However, it is not necessary to use
// a Darwin Streaming Server in order to serve streams using RTP/RTSP. Instead, the "LIVE555 Streaming Media"
-// includes its own RTSP/RTP server implementation, which you should use instead. For tips on using our
-// RTSP/RTP server implementation, see the "testOnDemandRTSPServer" demo application, and/or the
+// software includes its own RTSP/RTP server implementation, which you should use instead. For tips on using
+// our RTSP/RTP server implementation, see the "testOnDemandRTSPServer" demo application, and/or the
// "live555MediaServer" application (in the "mediaServer") directory.
//////////////////////////
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/testProgs/testMPEG1or2ProgramToTransportStream.cpp
^
|
@@ -13,7 +13,7 @@
along with this library; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
-// Copyright (c) 1996-2010, Live Networks, Inc. All rights reserved
+// Copyright (c) 1996-2011, Live Networks, Inc. All rights reserved
// A program that converts a MPEG-1 or 2 Program Stream file into
// a Transport Stream file.
// main program
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/testProgs/testMPEG1or2Splitter.cpp
^
|
@@ -13,7 +13,7 @@
along with this library; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
-// Copyright (c) 1996-2010, Live Networks, Inc. All rights reserved
+// Copyright (c) 1996-2011, Live Networks, Inc. All rights reserved
// A test program that splits a MPEG-1 or 2 Program Stream file into
// video and audio output files.
// main program
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/testProgs/testMPEG1or2VideoReceiver.cpp
^
|
@@ -13,7 +13,7 @@
along with this library; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
-// Copyright (c) 1996-2010, Live Networks, Inc. All rights reserved
+// Copyright (c) 1996-2011, Live Networks, Inc. All rights reserved
// A test program that receives a RTP/RTCP multicast MPEG video stream,
// and outputs the resulting MPEG file stream to 'stdout'
// main program
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/testProgs/testMPEG1or2VideoStreamer.cpp
^
|
@@ -13,7 +13,7 @@
along with this library; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
-// Copyright (c) 1996-2010, Live Networks, Inc. All rights reserved
+// Copyright (c) 1996-2011, Live Networks, Inc. All rights reserved
// A test program that reads a MPEG-1 or 2 Video Elementary Stream file,
// and streams it using RTP
// main program
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/testProgs/testMPEG2TransportStreamTrickPlay.cpp
^
|
@@ -13,7 +13,7 @@
along with this library; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
-// Copyright (c) 1996-2010, Live Networks, Inc. All rights reserved
+// Copyright (c) 1996-2011, Live Networks, Inc. All rights reserved
// A program that tests 'trick mode' operations on a MPEG-2 Transport Stream file,
// by generating a new Transport Stream file that represents the result of the
// 'trick mode' operation (seeking and/or fast forward/reverse play).
@@ -25,10 +25,6 @@
#include <liveMedia.hh>
#include <BasicUsageEnvironment.hh>
-// We assume that the video - in the original Transport Stream file - is MPEG-2. If, instead, it is MPEG-1,
-// then change the following definition to 1:
-#define VIDEO_MPEG_VERSION 2
-
void afterPlaying(void* clientData); // forward
UsageEnvironment* env;
@@ -105,7 +101,7 @@
// Generate a new Transport Stream from the Trick Mode filter:
MPEG2TransportStreamFromESSource* newTransportStream
= MPEG2TransportStreamFromESSource::createNew(*env);
- newTransportStream->addNewVideoSource(trickModeFilter, VIDEO_MPEG_VERSION);
+ newTransportStream->addNewVideoSource(trickModeFilter, indexFile->mpegVersion());
// Open the output file (for writing), as a 'file sink':
char const* outputFileName = argv[4];
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/testProgs/testMPEG2TransportStreamer.cpp
^
|
@@ -13,7 +13,7 @@
along with this library; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
-// Copyright (c) 1996-2010, Live Networks, Inc. All rights reserved
+// Copyright (c) 1996-2011, Live Networks, Inc. All rights reserved
// A test program that reads a MPEG-2 Transport Stream file,
// and streams it using RTP
// main program
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/testProgs/testMPEG4VideoStreamer.cpp
^
|
@@ -13,7 +13,7 @@
along with this library; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
-// Copyright (c) 1996-2010, Live Networks, Inc. All rights reserved
+// Copyright (c) 1996-2011, Live Networks, Inc. All rights reserved
// A test program that reads a MPEG-4 Video Elementary Stream file,
// and streams it using RTP
// main program
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/testProgs/testMPEG4VideoToDarwin.cpp
^
|
@@ -13,7 +13,7 @@
along with this library; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
-// Copyright (c) 1996-2010, Live Networks, Inc. All rights reserved
+// Copyright (c) 1996-2011, Live Networks, Inc. All rights reserved
// A test program that reads a MPEG-4 Video Elementary Stream file,
// and streams both using RTP, through a remote Darwin Streaming Server.
// main program
@@ -22,8 +22,8 @@
// This demo software is provided only as a courtesy to those developers who - for whatever reason - wish
// to send outgoing streams through a separate Darwin Streaming Server. However, it is not necessary to use
// a Darwin Streaming Server in order to serve streams using RTP/RTSP. Instead, the "LIVE555 Streaming Media"
-// includes its own RTSP/RTP server implementation, which you should use instead. For tips on using our
-// RTSP/RTP server implementation, see the "testOnDemandRTSPServer" demo application, and/or the
+// software includes its own RTSP/RTP server implementation, which you should use instead. For tips on using
+// our RTSP/RTP server implementation, see the "testOnDemandRTSPServer" demo application, and/or the
// "live555MediaServer" application (in the "mediaServer") directory.
//////////////////////////
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/testProgs/testOnDemandRTSPServer.cpp
^
|
@@ -13,7 +13,7 @@
along with this library; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
-// Copyright (c) 1996-2010, Live Networks, Inc. All rights reserved
+// Copyright (c) 1996-2011, Live Networks, Inc. All rights reserved
// A test program that demonstrates how to stream - via unicast RTP
// - various kinds of file on demand, using a built-in RTSP server.
// main program
@@ -79,6 +79,20 @@
announceStream(rtspServer, sms, streamName, inputFileName);
}
+ // A H.264 video elementary stream:
+ {
+ char const* streamName = "h264ESVideoTest";
+ char const* inputFileName = "test.264";
+ ServerMediaSession* sms
+ = ServerMediaSession::createNew(*env, streamName, streamName,
+ descriptionString);
+ sms->addSubsession(H264VideoFileServerMediaSubsession
+ ::createNew(*env, inputFileName, reuseFirstSource));
+ rtspServer->addServerMediaSession(sms);
+
+ announceStream(rtspServer, sms, streamName, inputFileName);
+ }
+
// A MPEG-1 or 2 audio+video program stream:
{
char const* streamName = "mpeg1or2AudioVideoTest";
@@ -237,6 +251,32 @@
announceStream(rtspServer, sms, streamName, inputFileName);
}
+ // A AC3 video elementary stream:
+ {
+ char const* streamName = "ac3AudioTest";
+ char const* inputFileName = "test.ac3";
+ ServerMediaSession* sms
+ = ServerMediaSession::createNew(*env, streamName, streamName,
+ descriptionString);
+
+ sms->addSubsession(AC3AudioFileServerMediaSubsession
+ ::createNew(*env, inputFileName, reuseFirstSource));
+
+ rtspServer->addServerMediaSession(sms);
+
+ announceStream(rtspServer, sms, streamName, inputFileName);
+ }
+
+ // Also, attempt to create a HTTP server for RTSP-over-HTTP tunneling.
+ // Try first with the default HTTP port (80), and then with the alternative HTTP
+ // port numbers (8000 and 8080).
+
+ if (rtspServer->setUpTunnelingOverHTTP(80) || rtspServer->setUpTunnelingOverHTTP(8000) || rtspServer->setUpTunnelingOverHTTP(8080)) {
+ *env << "\n(We use port " << rtspServer->httpServerPortNum() << " for optional RTSP-over-HTTP tunneling.)\n";
+ } else {
+ *env << "\n(RTSP-over-HTTP tunneling is not available.)\n";
+ }
+
env->taskScheduler().doEventLoop(); // does not return
return 0; // only to prevent compiler warning
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/testProgs/testRelay.cpp
^
|
@@ -13,7 +13,7 @@
along with this library; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
-// Copyright (c) 1996-2010, Live Networks, Inc. All rights reserved
+// Copyright (c) 1996-2011, Live Networks, Inc. All rights reserved
// A test program that receives a UDP multicast stream
// and retransmits it to another (multicast or unicast) address & port
// main program
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/testProgs/testWAVAudioStreamer.cpp
^
|
@@ -13,7 +13,7 @@
along with this library; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
-// Copyright (c) 1996-2010, Live Networks, Inc. All rights reserved
+// Copyright (c) 1996-2011, Live Networks, Inc. All rights reserved
// A test program that streams a WAV audio file via RTP/RTCP
// main program
|
[-]
[+]
|
Changed |
live.2011.06.16.tar.bz2/testProgs/vobStreamer.cpp
^
|
@@ -13,7 +13,7 @@
along with this library; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**********/
-// Copyright (c) 1996-2010, Live Networks, Inc. All rights reserved
+// Copyright (c) 1996-2011, Live Networks, Inc. All rights reserved
// A test program that reads a VOB file
// splits it into Audio (AC3) and Video (MPEG) Elementary Streams,
// and streams both using RTP.
|