Changes of Revision 2
[-] | Added | live.changes |
1
2 +------------------------------------------------------------------- 3 +Sun Jul 17 09:02:42 UTC 2011 - cs@linux-administrator.com 4 + 5 +- re-import 6 |
||
[-] | Changed | live.spec ^ |
114 1
2 License: GPL v2 or later 3 Group: Development/Libraries/C and C++ 4 URL: http://www.live555.com/liveMedia/ 5 -Version: 2010.09.25 6 -Release: 1.pm.1.1 7 +Version: 2011.06.16 8 +Release: 2 9 Source0: live.%{version}.tar.bz2 10 Source1: live-CHANGELOG 11 Patch0: live-config.patch 12
13 Live.com Bibliothek (wird benötigt um MPlayer und vlc zu compilieren) Entwicklerpaket 14 15 16 -%debug_package 17 + 18 19 20 %prep 21
22 %{_libdir}/live 23 24 %changelog 25 -* Sun Oct 03 2010 Manfred Tremmel <Manfred.Tremmel@iiv.de> - 2010.09.25-0.pm.1 26 -- update to current version 2010.09.25 27 -* Wed Jun 16 2010 Manfred Tremmel <Manfred.Tremmel@iiv.de> - 2010.06.16a-0.pm.1 28 -- update to current version 2010.06.16a 29 -* Fri May 28 2010 Manfred Tremmel <Manfred.Tremmel@iiv.de> - 2010.05.28-0.pm.1 30 -- update to current version 2010.05.28 31 -* Sat Apr 03 2010 Manfred Tremmel <Manfred.Tremmel@iiv.de> - 2010.04.01-0.pm.1 32 -- update to current version 2010.04.01 33 -* Sat Feb 06 2010 Manfred Tremmel <Manfred.Tremmel@iiv.de> - 2010.02.06-0.pm.1 34 -- update to current version 2010.01.22 35 -* Thu Jan 07 2010 Manfred Tremmel <Manfred.Tremmel@iiv.de> - 2010.01.07-0.pm.1 36 -- update to current version 2010.01.07 37 -* Fri Dec 11 2009 Manfred Tremmel <Manfred.Tremmel@iiv.de> - 2009.11.27-0.pm.1 38 -- update to current version 2009.11.27 39 -* Sat Oct 03 2009 Manfred.Tremmel <Manfred.Tremmel@iiv.de> - 2009.07.28-2.pm.0 40 -- downgrade to 2009.07.28 because of problems with vlc 41 -* Mon Sep 28 2009 Manfred Tremmel <Manfred.Tremmel@iiv.de> - 2009.09.28-0.pm.1 42 -- update to current version 2009.09.28 43 -* Tue Sep 22 2009 Manfred Tremmel <Manfred.Tremmel@iiv.de> - 2009.09.21-0.pm.1 44 -- update to current version 2009.09.21 45 -* Sat Sep 05 2009 Manfred Tremmel <Manfred.Tremmel@iiv.de> - 2009.09.04-0.pm.1 46 -- update to current version 2009.09.04 47 -* Thu Aug 27 2009 Manfred.Tremmel <Manfred.Tremmel@iiv.de> - 2009.07.28-1.pm.1 48 -- cleanups where rpmlint wasn't so happy 49 -* Tue Jul 28 2009 Manfred Tremmel <Manfred.Tremmel@iiv.de> 50 -- update to current version 2009.07.28 51 -* Sat Jul 11 2009 Manfred Tremmel <Manfred.Tremmel@iiv.de> 52 -- update to current version 2009.07.09 53 -* Tue Jun 02 2009 Manfred Tremmel <Manfred.Tremmel@iiv.de> 54 -- update to current version 2009.06.02 55 -* Wed Apr 08 2009 Manfred Tremmel <Manfred.Tremmel@iiv.de> 56 -- update to current version 2009.04.07 57 -* Mon Feb 23 2009 Manfred Tremmel <Manfred.Tremmel@iiv.de> 58 -- update to current version 2009.02.23 59 -* Tue Jan 27 2009 Manfred Tremmel <Manfred.Tremmel@iiv.de> 60 -- update to current version 2009.01.26 61 -* Sat Dec 20 2008 Manfred Tremmel <Manfred.Tremmel@iiv.de> 62 -- update to current version 2008.12.20 63 -* Wed Nov 05 2008 Manfred Tremmel <Manfred.Tremmel@iiv.de> 64 -- update to current version 2008.11.04 65 -* Thu Sep 04 2008 Manfred Tremmel <Manfred.Tremmel@iiv.de> 66 -- update to current version 2008.09.02 67 -* Thu Aug 28 2008 Manfred Tremmel <Manfred.Tremmel@iiv.de> 68 -- update to current version 2008.07.25 69 -* Thu Jun 26 2008 Manfred Tremmel <Manfred.Tremmel@iiv.de> 70 -- update to current version 2008.06.26 71 -* Thu Apr 03 2008 Manfred Tremmel <Manfred.Tremmel@iiv.de> 72 -- update to current version 2008.04.03 73 -* Fri Jan 18 2008 Manfred Tremmel <Manfred.Tremmel@iiv.de> 74 -- update to current version 2008.01.18 75 -* Tue Jan 01 2008 Manfred Tremmel <Manfred.Tremmel@iiv.de> 76 -- update to current version 2007.12.27 77 -* Fri Nov 02 2007 Manfred Tremmel <Manfred.Tremmel@iiv.de> 78 -- update to current version 2007.11.01 79 -* Wed Jul 11 2007 Manfred Tremmel <Manfred.Tremmel@iiv.de> 80 -- update to current version 2007.07.11 81 -* Wed May 23 2007 Manfred Tremmel <Manfred.Tremmel@iiv.de> 82 -- update to current version 2007.05.23 83 -* Sat Dec 09 2006 Manfred Tremmel <Manfred.Tremmel@iiv.de> 84 -- update to current version 2006.12.08 85 -* Sun Oct 08 2006 Manfred Tremmel <Manfred.Tremmel@iiv.de> 86 -- update to current version 2006.10.07 87 -* Sat Aug 26 2006 Manfred Tremmel <Manfred.Tremmel@iiv.de> 88 -- update to current version 2006.08.26 89 -* Sat Jun 24 2006 Manfred Tremmel <Manfred.Tremmel@iiv.de> 90 -- update to current version 2006.06.23 91 -* Fri May 12 2006 Manfred Tremmel <Manfred.Tremmel@iiv.de> 92 -- update to current version 2006.05.11 93 -* Wed Jan 25 2006 Manfred Tremmel <Manfred.Tremmel@iiv.de> 94 -- update to current version 2006.01.24 95 -* Wed Dec 14 2005 Manfred Tremmel <Manfred.Tremmel@iiv.de> 96 -- update to current version 2005.12.09 97 -* Wed Sep 21 2005 Manfred Tremmel <Manfred.Tremmel@iiv.de> 98 -- update to current version 2005.09.20 99 -* Fri Jul 22 2005 Manfred Tremmel <Manfred.Tremmel@iiv.de> 100 -- update to current version 2005.07.21 101 -* Sat May 07 2005 Manfred Tremmel <Manfred.Tremmel@iiv.de> 102 -- update to current version 2005.05.05 103 -* Sun Apr 17 2005 Manfred Tremmel <Manfred.Tremmel@iiv.de> 104 -- update to current version 2005.04.13 105 -* Sat Apr 02 2005 Manfred Tremmel <Manfred.Tremmel@iiv.de> 106 -- update to current version 2005.04.01 107 -* Sat Oct 30 2004 Manfred Tremmel <Manfred.Tremmel@iiv.de> 108 -- update to current version 2004.10.28a 109 -* Fri Jun 04 2004 Manfred Tremmel <Manfred.Tremmel@iiv.de> 110 -- added packman headers 111 -- update to current version 2004.06.03 112 -* Sun May 02 2004 Henne Vogelsang <henne@links2linux.de> 113 -- first build and release, Version 2004.05.02 114 |
||
[+] | 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. |