Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package live555 for openSUSE:Factory checked 
in at 2021-08-16 10:09:04
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/live555 (Old)
 and      /work/SRC/openSUSE:Factory/.live555.new.1899 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "live555"

Mon Aug 16 10:09:04 2021 rev:26 rq:911953 version:2021.08.09

Changes:
--------
--- /work/SRC/openSUSE:Factory/live555/live555.changes  2021-06-24 
18:22:00.260878288 +0200
+++ /work/SRC/openSUSE:Factory/.live555.new.1899/live555.changes        
2021-08-16 10:14:00.874923494 +0200
@@ -1,0 +2,51 @@
+Thu Aug 12 00:38:24 UTC 2021 - Fusion Future <qydwhotm...@gmail.com>
+
+- Update to 2021.08.09:
+  - Fixed a bug in the MPEG-1 or 2 file server demultiplexors that 
+    could cause a RTSP server to crash if it received successive 
+    RTSP "SETUP" commands for the same track. (Thanks to Ba 
+    Jinsheng for reporting this.)(boo#1189352, CVE-2021-38381)
+- Update to 2021.08.06:
+  - Fixed a bug in the Matroska and Ogg file server demultiplexors 
+    that could cause a RTSP server to crash if it received 
+    successive RTSP "SETUP" commands for the same track.  (Thanks 
+    to Ba Jinsheng for reporting this.)(boo#1189353, CVE-2021-38382)
+- Update to 2021.08.04:
+  - In the "MP3FileSource" implementation, we no longer do a 
+    recursive call to "doEventLoop()" when attempting to 
+    synchronously read from a MP3 file.  This avoids a possible 
+    stack overflow in the RTSP server if multiple concurrent 
+    requests are made. (Thanks to Ba Jinsheng for reporting this.)  
+    The server still does some synchronous reads, when 
+    initializing, and when parsing MP3 frame headers. This should 
+    be fixed sometime in the future. (boo#1189351, CVE-2021-38380)
+- Update to 2021.07.20:
+  - If a "RTSPClient" receives a response to a RTSP "PLAY" that 
+    changes the 'scale()' or 'speed()' of the whole session, then 
+    those parameters also need to be changed in each subsession (as 
+    that inheritance doesn't happen automatically). (Thanks to a 
+    developer in China for reporting this.)
+- Update to 2021.07.10:
+  - Updated "H264or5VideoStreamFramer.cpp" once again to set the 
+    default value of "DeltaTfiDivisor" to 2.0 for H.265, and 1.0 
+    for everything else.  (This fixes the frame rate for another 
+    stream supplied by Paul Westlund.)
+- Update to 2021.06.29:
+  - In the proxy server implementation, if a client closes one 
+    substream, but there are still other clients receiving other 
+    substream(s), then we no send a single-track RTSP "PAUSE" 
+    command downstream, because some back-end servers might handle 
+    that by pausing all tracks of the stream.  So now, in this 
+    case, we don't send a RTSP "PAUSE" command at all. (Thanks to 
+    Jose Maria Infanzon for noting this issue.)
+- Update to 2021.06.25:
+  - Updated "H264or5VideoStreamFramer.cpp" to set the default value 
+    of "DeltaTfiDivisor" to 1.0 (rather than 2.0), and to assume a 
+    frame rate of 30 fps (rather than 25 fps) if there is no VPS or 
+    SPS NAL unit that specifies a different frame rate.  This seems 
+    to work the best for most raw H.264 and H.265 video streams.  
+    (Thanks to Paul Westlund for supplying an example file to 
+    motivate this.)
+- Change the so version of libliveMedia to 97
+
+-------------------------------------------------------------------

Old:
----
  live.2021.05.22.tar.gz

New:
----
  live.2021.08.09.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ live555.spec ++++++
--- /var/tmp/diff_new_pack.fiDPmQ/_old  2021-08-16 10:14:01.310922937 +0200
+++ /var/tmp/diff_new_pack.fiDPmQ/_new  2021-08-16 10:14:01.314922931 +0200
@@ -17,10 +17,10 @@
 #
 
 
-%define lmdmaj 94
+%define lmdmaj 97
 
 Name:           live555
-Version:        2021.05.22
+Version:        2021.08.09
 Release:        0
 Summary:        LIVE555 Streaming Media
 License:        LGPL-2.1-only

++++++ live.2021.05.22.tar.gz -> live.2021.08.09.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/live/BasicUsageEnvironment/include/BasicUsageEnvironment_version.hh 
new/live/BasicUsageEnvironment/include/BasicUsageEnvironment_version.hh
--- old/live/BasicUsageEnvironment/include/BasicUsageEnvironment_version.hh     
2021-05-22 07:12:13.000000000 +0200
+++ new/live/BasicUsageEnvironment/include/BasicUsageEnvironment_version.hh     
2021-08-09 08:33:36.000000000 +0200
@@ -19,7 +19,7 @@
 #ifndef _BASICUSAGEENVIRONMENT_VERSION_HH
 #define _BASICUSAGEENVIRONMENT_VERSION_HH
 
-#define BASICUSAGEENVIRONMENT_LIBRARY_VERSION_STRING   "2021.05.22"
-#define BASICUSAGEENVIRONMENT_LIBRARY_VERSION_INT              1621641600
+#define BASICUSAGEENVIRONMENT_LIBRARY_VERSION_STRING   "2021.08.09"
+#define BASICUSAGEENVIRONMENT_LIBRARY_VERSION_INT              1628467200
 
 #endif
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/live/UsageEnvironment/include/UsageEnvironment_version.hh 
new/live/UsageEnvironment/include/UsageEnvironment_version.hh
--- old/live/UsageEnvironment/include/UsageEnvironment_version.hh       
2021-05-22 07:12:13.000000000 +0200
+++ new/live/UsageEnvironment/include/UsageEnvironment_version.hh       
2021-08-09 08:33:36.000000000 +0200
@@ -19,7 +19,7 @@
 #ifndef _USAGEENVIRONMENT_VERSION_HH
 #define _USAGEENVIRONMENT_VERSION_HH
 
-#define USAGEENVIRONMENT_LIBRARY_VERSION_STRING        "2021.05.22"
-#define USAGEENVIRONMENT_LIBRARY_VERSION_INT           1621641600
+#define USAGEENVIRONMENT_LIBRARY_VERSION_STRING        "2021.08.09"
+#define USAGEENVIRONMENT_LIBRARY_VERSION_INT           1628467200
 
 #endif
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/live/config.linux-with-shared-libraries 
new/live/config.linux-with-shared-libraries
--- old/live/config.linux-with-shared-libraries 2021-05-22 07:12:22.000000000 
+0200
+++ new/live/config.linux-with-shared-libraries 2021-08-09 08:33:57.000000000 
+0200
@@ -3,8 +3,8 @@
 # At least one interface changes, or is removed => CURRENT += 1; REVISION = 0; 
AGE = 0
 # One or more interfaces were added, but no existing interfaces were changed 
or removed => CURRENT += 1; REVISION = 0; AGE += 1
 
-libliveMedia_VERSION_CURRENT=94
-libliveMedia_VERSION_REVISION=3
+libliveMedia_VERSION_CURRENT=97
+libliveMedia_VERSION_REVISION=0
 libliveMedia_VERSION_AGE=0
 libliveMedia_LIB_SUFFIX=so.$(shell expr $(libliveMedia_VERSION_CURRENT) - 
$(libliveMedia_VERSION_AGE)).$(libliveMedia_VERSION_AGE).$(libliveMedia_VERSION_REVISION)
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/live/groupsock/include/groupsock_version.hh 
new/live/groupsock/include/groupsock_version.hh
--- old/live/groupsock/include/groupsock_version.hh     2021-05-22 
07:12:13.000000000 +0200
+++ new/live/groupsock/include/groupsock_version.hh     2021-08-09 
08:33:36.000000000 +0200
@@ -19,7 +19,7 @@
 #ifndef _GROUPSOCK_VERSION_HH
 #define _GROUPSOCK_VERSION_HH
 
-#define GROUPSOCK_LIBRARY_VERSION_STRING       "2021.05.22"
-#define GROUPSOCK_LIBRARY_VERSION_INT          1621641600
+#define GROUPSOCK_LIBRARY_VERSION_STRING       "2021.08.09"
+#define GROUPSOCK_LIBRARY_VERSION_INT          1628467200
 
 #endif
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/live/liveMedia/H264or5VideoStreamFramer.cpp 
new/live/liveMedia/H264or5VideoStreamFramer.cpp
--- old/live/liveMedia/H264or5VideoStreamFramer.cpp     2021-05-22 
07:12:13.000000000 +0200
+++ new/live/liveMedia/H264or5VideoStreamFramer.cpp     2021-08-09 
08:33:36.000000000 +0200
@@ -86,7 +86,7 @@
   fParser = createParser
     ? new H264or5VideoStreamParser(hNumber, this, inputSource, 
includeStartCodeInOutput)
     : NULL;
-  fFrameRate = 25.0; // We assume a frame rate of 25 fps, unless we learn 
otherwise (from parsing a VPS or SPS NAL unit)
+  fFrameRate = 30.0; // We assume a frame rate of 30 fps, unless we learn 
otherwise (from parsing a VPS or SPS NAL unit)
 }
 
 H264or5VideoStreamFramer::~H264or5VideoStreamFramer() {
@@ -198,7 +198,7 @@
     fHNumber(hNumber), fOutputStartCodeSize(includeStartCodeInOutput ? 4 : 0), 
fHaveSeenFirstStartCode(False), fHaveSeenFirstByteOfNALUnit(False), 
fParsedFrameRate(0.0),
     cpb_removal_delay_length_minus1(23), dpb_output_delay_length_minus1(23),
     CpbDpbDelaysPresentFlag(0), pic_struct_present_flag(0),
-    DeltaTfiDivisor(2.0) {
+    DeltaTfiDivisor(hNumber == 264 ? 2.0 : 1.0) {
 }
 
 H264or5VideoStreamParser::~H264or5VideoStreamParser() {
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/live/liveMedia/MP3AudioFileServerMediaSubsession.cpp 
new/live/liveMedia/MP3AudioFileServerMediaSubsession.cpp
--- old/live/liveMedia/MP3AudioFileServerMediaSubsession.cpp    2021-05-22 
07:12:13.000000000 +0200
+++ new/live/liveMedia/MP3AudioFileServerMediaSubsession.cpp    2021-08-09 
08:33:36.000000000 +0200
@@ -57,6 +57,7 @@
     // Use the MP3 file size, plus the duration, to estimate the stream's 
bitrate:
     if (mp3NumBytes > 0 && fFileDuration > 0.0) {
       estBitrate = (unsigned)(mp3NumBytes/(125*fFileDuration) + 0.5); // kbps, 
rounded
+      if (estBitrate == 0) estBitrate = 128; // kbps, estimate
     } else {
       estBitrate = 128; // kbps, estimate
     }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/live/liveMedia/MP3FileSource.cpp 
new/live/liveMedia/MP3FileSource.cpp
--- old/live/liveMedia/MP3FileSource.cpp        2021-05-22 07:12:13.000000000 
+0200
+++ new/live/liveMedia/MP3FileSource.cpp        2021-08-09 08:33:36.000000000 
+0200
@@ -24,19 +24,6 @@
 
 ////////// MP3FileSource //////////
 
-MP3FileSource::MP3FileSource(UsageEnvironment& env, FILE* fid)
-  : FramedFileSource(env, fid),
-    fStreamState(new MP3StreamState(env)) {
-}
-
-MP3FileSource::~MP3FileSource() {
-  delete fStreamState;
-}
-
-char const* MP3FileSource::MIMEtype() const {
-  return "audio/MPEG";
-}
-
 MP3FileSource* MP3FileSource::createNew(UsageEnvironment& env, char const* 
fileName) {
   MP3FileSource* newSource = NULL;
 
@@ -51,7 +38,6 @@
 
     unsigned fileSize = (unsigned)GetFileSize(fileName, fid);
     newSource->assignStream(fid, fileSize);
-    if (!newSource->initializeStream()) break;
 
     return newSource;
   } while (0);
@@ -60,6 +46,29 @@
   return NULL;
 }
 
+MP3FileSource::MP3FileSource(UsageEnvironment& env, FILE* fid)
+  : FramedFileSource(env, fid),
+    fStreamState(new MP3StreamState),
+    fHaveStartedReading(False), fHaveBeenInitialized(False),
+    fLimitNumBytesToStream(False), fNumBytesToStream(0) {
+  //###### We can't make the socket non-blocking yet, because we still do 
synchronous reads
+  //###### on it (to find MP3 headers).  Later, fix this.
+  //makeSocketNonBlocking(fileno(fFid));
+
+  // Test whether the file is seekable
+  fFidIsSeekable = FileIsSeekable(fFid);
+}
+
+MP3FileSource::~MP3FileSource() {
+  if (fFid != NULL) 
envir().taskScheduler().turnOffBackgroundReadHandling(fileno(fFid));
+
+  delete fStreamState; // closes the input file
+}
+
+char const* MP3FileSource::MIMEtype() const {
+  return "audio/MPEG";
+}
+
 float MP3FileSource::filePlayTime() const {
   return fStreamState->filePlayTime();
 }
@@ -109,54 +118,66 @@
 }
 
 void MP3FileSource::doGetNextFrame() {
-  if (!doGetNextFrame1()) {
+  if (feof(fFid) || ferror(fFid) || (fLimitNumBytesToStream && 
fNumBytesToStream == 0)) {
     handleClosure();
     return;
   }
 
-  // Switch to another task:
-#if defined(__WIN32__) || defined(_WIN32)
-  // HACK: liveCaster/lc uses an implementation of scheduleDelayedTask()
-  // that performs very badly (chewing up lots of CPU time, apparently polling)
-  // on Windows.  Until this is fixed, we just call our "afterGetting()"
-  // function directly.  This avoids infinite recursion, as long as our sink
-  // is discontinuous, which is the case for the RTP sink that liveCaster/lc
-  // uses. #####
-  afterGetting(this);
-#else
-  nextTask() = envir().taskScheduler().scheduleDelayedTask(0,
-                               (TaskFunc*)afterGetting, this);
-#endif
-}
+  if (!fHaveStartedReading) {
+    // Await readable data from the file:
+    envir().taskScheduler().turnOnBackgroundReadHandling(fileno(fFid),
+                (TaskScheduler::BackgroundHandlerProc*)&fileReadableHandler, 
this);
+    fHaveStartedReading = True;
+    return;
+  }
 
-Boolean MP3FileSource::doGetNextFrame1() {
-  if (fLimitNumBytesToStream && fNumBytesToStream == 0) return False; // we've 
already streamed as much as we were asked for
+  if (!fHaveBeenInitialized) {
+    if (!initializeStream()) return;
 
-  if (!fHaveJustInitialized) {
-    if (fStreamState->findNextHeader(fPresentationTime) == 0) return False;
-  } else {
     fPresentationTime = fFirstFramePresentationTime;
-    fHaveJustInitialized = False;
+    fHaveBeenInitialized = True;
+  } else {
+    if (fStreamState->findNextHeader(fPresentationTime) == 0) return;
   }
 
+  if (fLimitNumBytesToStream && fNumBytesToStream < (u_int64_t)fMaxSize) {
+    fMaxSize = (unsigned)fNumBytesToStream;
+  }
   if (!fStreamState->readFrame(fTo, fMaxSize, fFrameSize, 
fDurationInMicroseconds)) {
     char tmp[200];
     sprintf(tmp,
            "Insufficient buffer size %d for reading MPEG audio frame (needed 
%d)\n",
            fMaxSize, fFrameSize);
     envir().setResultMsg(tmp);
-    fFrameSize = fMaxSize;
-    return False;
+    handleClosure();
+    return;
   }
-  if (fNumBytesToStream > fFrameSize) fNumBytesToStream -= fFrameSize; else 
fNumBytesToStream = 0;
+  fNumBytesToStream -= fFrameSize;
 
-  return True;
+  // Inform the reader that he has data:
+  // Because the file read was done from the event loop, we can call the
+  // 'after getting' function directly, without risk of infinite recursion:
+  FramedSource::afterGetting(this);
+}
+
+void MP3FileSource::fileReadableHandler(MP3FileSource* source, int /*mask*/) {
+  if (!source->isCurrentlyAwaitingData()) {
+    source->doStopGettingFrames(); // we're not ready for the data yet
+    return;
+  }
+  source->doGetNextFrame();
 }
 
 void MP3FileSource::assignStream(FILE* fid, unsigned fileSize) {
   fStreamState->assignStream(fid, fileSize);
-}
 
+  if (!fHaveBeenInitialized) {
+    if (!initializeStream()) return;
+
+    fPresentationTime = fFirstFramePresentationTime;
+    fHaveBeenInitialized = True;
+  }
+}
 
 Boolean MP3FileSource::initializeStream() {
   // Make sure the file has an appropriate header near the start:
@@ -167,10 +188,6 @@
 
   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());
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/live/liveMedia/MP3Internals.cpp 
new/live/liveMedia/MP3Internals.cpp
--- old/live/liveMedia/MP3Internals.cpp 2021-05-22 07:12:13.000000000 +0200
+++ new/live/liveMedia/MP3Internals.cpp 2021-08-09 08:33:36.000000000 +0200
@@ -97,7 +97,8 @@
 ////////// MP3FrameParams //////////
 
 MP3FrameParams::MP3FrameParams()
-  : bv(frameBytes, 0, sizeof frameBytes) /* by default */ {
+  : isMPEG2(0), samplingFreq(44100), frameSize(413), // init params, in case 
we're used early
+    bv(frameBytes, 0, sizeof frameBytes) /* by default */ {
   oldHdr = firstHdr = 0;
 
   static Boolean doneInit = False;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/live/liveMedia/MP3StreamState.cpp 
new/live/liveMedia/MP3StreamState.cpp
--- old/live/liveMedia/MP3StreamState.cpp       2021-05-22 07:12:13.000000000 
+0200
+++ new/live/liveMedia/MP3StreamState.cpp       2021-08-09 08:33:36.000000000 
+0200
@@ -31,8 +31,8 @@
 
 #define MILLION 1000000
 
-MP3StreamState::MP3StreamState(UsageEnvironment& env)
-  : fEnv(env), fFid(NULL), fPresentationTimeScale(1) {
+MP3StreamState::MP3StreamState()
+  : fFid(NULL), fPresentationTimeScale(1) {
 }
 
 MP3StreamState::~MP3StreamState() {
@@ -142,7 +142,7 @@
 Boolean MP3StreamState::readFrame(unsigned char* outBuf, unsigned outBufSize,
                                  unsigned& resultFrameSize,
                                  unsigned& resultDurationInMicroseconds) {
-  /* We assume that "mp3FindNextHeader()" has already been called */
+  /* We assume that "findNextHeader()" has already been called */
 
   resultFrameSize = 4 + fr().frameSize;
 
@@ -336,59 +336,9 @@
   return True;
 }
 
-static Boolean socketIsReadable(int socket) {
-  const unsigned numFds = socket+1;
-  fd_set rd_set;
-  FD_ZERO(&rd_set);
-  FD_SET((unsigned)socket, &rd_set);
-  struct timeval timeout;
-  timeout.tv_sec = timeout.tv_usec = 0;
-
-  int result = select(numFds, &rd_set, NULL, NULL, &timeout);
-  return result != 0; // not > 0, because windows can return -1 for file 
sockets
-}
-
-static char watchVariable;
-
-static void checkFunc(void* /*clientData*/) {
-  watchVariable = ~0;
-}
-
-static void waitUntilSocketIsReadable(UsageEnvironment& env, int socket) {
-  while (!socketIsReadable(socket)) {
-    // Delay a short period of time before checking again.
-    unsigned usecsToDelay = 1000; // 1 ms
-    env.taskScheduler().scheduleDelayedTask(usecsToDelay,
-                                           (TaskFunc*)checkFunc, (void*)NULL);
-    watchVariable = 0;
-    env.taskScheduler().doEventLoop(&watchVariable);
-        // This allows other tasks to run while we're waiting:
-  }
-}
-
 unsigned MP3StreamState::readFromStream(unsigned char* buf,
                                        unsigned numChars) {
-  // Hack for doing socket I/O instead of file I/O (e.g., on Windows)
-  if (fFidIsReallyASocket) {
-    intptr_t fid_long = (intptr_t)fFid;
-    int sock = (int)fid_long;
-    unsigned totBytesRead = 0;
-    do {
-      waitUntilSocketIsReadable(fEnv, sock);
-      int bytesRead
-       = recv(sock, &((char*)buf)[totBytesRead], numChars-totBytesRead, 0);
-      if (bytesRead < 0) return 0;
-
-      totBytesRead += (unsigned)bytesRead;
-    } while (totBytesRead < numChars);
-
-    return totBytesRead;
-  } else {
-#ifndef _WIN32_WCE
-    waitUntilSocketIsReadable(fEnv, (int)fileno(fFid));
-#endif
-    return fread(buf, 1, numChars, fFid);
-  }
+  return fread(buf, 1, numChars, fFid);
 }
 
 #define XING_FRAMES_FLAG       0x0001
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/live/liveMedia/MP3StreamState.hh 
new/live/liveMedia/MP3StreamState.hh
--- old/live/liveMedia/MP3StreamState.hh        2021-05-22 07:12:13.000000000 
+0200
+++ new/live/liveMedia/MP3StreamState.hh        2021-08-09 08:33:36.000000000 
+0200
@@ -40,7 +40,7 @@
 
 class MP3StreamState {
 public:
-  MP3StreamState(UsageEnvironment& env);
+  MP3StreamState();
   virtual ~MP3StreamState();
 
   void assignStream(FILE* fid, unsigned fileSize);
@@ -73,7 +73,6 @@
   Boolean findNextFrame();
 
 private:
-  UsageEnvironment& fEnv;
   FILE* fFid;
   Boolean fFidIsReallyASocket;
   unsigned fFileSize;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/live/liveMedia/MPEG1or2Demux.cpp 
new/live/liveMedia/MPEG1or2Demux.cpp
--- old/live/liveMedia/MPEG1or2Demux.cpp        2021-05-22 07:12:13.000000000 
+0200
+++ new/live/liveMedia/MPEG1or2Demux.cpp        2021-08-09 08:33:36.000000000 
+0200
@@ -80,12 +80,14 @@
 
 MPEG1or2Demux
 ::MPEG1or2Demux(UsageEnvironment& env,
-               FramedSource* inputSource, Boolean reclaimWhenLastESDies)
+               FramedSource* inputSource, Boolean reclaimWhenLastESDies,
+               MPEG1or2DemuxOnDeletionFunc* onDeletionFunc, void* 
objectToNotify)
   : Medium(env),
     fInputSource(inputSource), fMPEGversion(0),
     fNextAudioStreamNumber(0), fNextVideoStreamNumber(0),
     fReclaimWhenLastESDies(reclaimWhenLastESDies), fNumOutstandingESs(0),
-    fNumPendingReads(0), fHaveUndeliveredData(False) {
+    fNumPendingReads(0), fHaveUndeliveredData(False),
+    fOnDeletionFunc(onDeletionFunc), fOnDeletionObjectToNotify(objectToNotify) 
{
   fParser = new MPEGProgramStreamParser(this, inputSource);
   for (unsigned i = 0; i < 256; ++i) {
     fOutput[i].savedDataHead = fOutput[i].savedDataTail = NULL;
@@ -96,6 +98,10 @@
 }
 
 MPEG1or2Demux::~MPEG1or2Demux() {
+  if (fOnDeletionFunc != NULL) {
+    (*fOnDeletionFunc)(fOnDeletionObjectToNotify, this);
+  }
+
   delete fParser;
   for (unsigned i = 0; i < 256; ++i) delete fOutput[i].savedDataHead;
   Medium::close(fInputSource);
@@ -103,10 +109,13 @@
 
 MPEG1or2Demux* MPEG1or2Demux
 ::createNew(UsageEnvironment& env,
-           FramedSource* inputSource, Boolean reclaimWhenLastESDies) {
+           FramedSource* inputSource, Boolean reclaimWhenLastESDies,
+           MPEG1or2DemuxOnDeletionFunc* onDeletionFunc,
+           void* objectToNotify) {
   // Need to add source type checking here???  #####
 
-  return new MPEG1or2Demux(env, inputSource, reclaimWhenLastESDies);
+  return new MPEG1or2Demux(env, inputSource, reclaimWhenLastESDies,
+                          onDeletionFunc, objectToNotify);
 }
 
 MPEG1or2Demux::SCR::SCR()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/live/liveMedia/MPEG1or2FileServerDemux.cpp 
new/live/liveMedia/MPEG1or2FileServerDemux.cpp
--- old/live/liveMedia/MPEG1or2FileServerDemux.cpp      2021-05-22 
07:12:13.000000000 +0200
+++ new/live/liveMedia/MPEG1or2FileServerDemux.cpp      2021-08-09 
08:33:36.000000000 +0200
@@ -67,7 +67,8 @@
 MPEG1or2DemuxedElementaryStream*
 MPEG1or2FileServerDemux::newElementaryStream(unsigned clientSessionId,
                                             u_int8_t streamIdTag) {
-  MPEG1or2Demux* demuxToUse;
+  MPEG1or2Demux* demuxToUse = NULL;
+
   if (clientSessionId == 0) {
     // 'Session 0' is treated especially, because its audio & video streams
     // are created and destroyed one-at-a-time, rather than both streams being
@@ -86,28 +87,36 @@
   } else {
     // First, check whether this is a new client session.  If so, create a new
     // demux for it:
-    if (clientSessionId != fLastClientSessionId) {
+    if (clientSessionId == fLastClientSessionId) {
+      demuxToUse = fLastCreatedDemux; // use the same demultiplexor as before
+    }
+
+    if (demuxToUse == NULL) {
       // Open our input file as a 'byte-stream file source':
       ByteStreamFileSource* fileSource
        = ByteStreamFileSource::createNew(envir(), fFileName);
       if (fileSource == NULL) return NULL;
 
-      fLastCreatedDemux = MPEG1or2Demux::createNew(envir(), fileSource, True);
-      // Note: We tell the demux to delete itself when its last
-      // elementary stream is deleted.
-      fLastClientSessionId = clientSessionId;
-      // Note: This code relies upon the fact that the creation of streams for
-      // different client sessions do not overlap - so one "MPEG1or2Demux" is 
used
-      // at a time.
+      demuxToUse = MPEG1or2Demux::createNew(envir(), fileSource, True, 
onDemuxDeletion, this);
+        // Note: We tell the demux to delete itself when its last
+        // elementary stream is deleted.
     }
-    demuxToUse = fLastCreatedDemux;
-  }
 
-  if (demuxToUse == NULL) return NULL; // shouldn't happen
+    fLastClientSessionId = clientSessionId;
+    fLastCreatedDemux = demuxToUse;
+  }
 
   return demuxToUse->newElementaryStream(streamIdTag);
 }
 
+void MPEG1or2FileServerDemux::onDemuxDeletion(void* clientData, MPEG1or2Demux* 
demuxBeingDeleted) {
+  ((MPEG1or2FileServerDemux*)clientData)->onDemuxDeletion(demuxBeingDeleted);
+}
+
+void MPEG1or2FileServerDemux::onDemuxDeletion(MPEG1or2Demux* 
demuxBeingDeleted) {
+  if (fLastCreatedDemux == demuxBeingDeleted) fLastCreatedDemux = NULL;
+}
+
 
 static Boolean getMPEG1or2TimeCode(FramedSource* dataSource,
                                   MPEG1or2Demux& parentDemux,
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/live/liveMedia/MatroskaFile.cpp 
new/live/liveMedia/MatroskaFile.cpp
--- old/live/liveMedia/MatroskaFile.cpp 2021-05-22 07:12:13.000000000 +0200
+++ new/live/liveMedia/MatroskaFile.cpp 2021-08-09 08:33:36.000000000 +0200
@@ -132,14 +132,21 @@
   }
 }
 
+struct DemuxRecord {
+  MatroskaDemux* demux;
+  MatroskaDemuxOnDeletionFunc* onDeletionFunc;
+  void* objectToNotify;
+};
+
 MatroskaFile::~MatroskaFile() {
   delete fParserForInitialization;
   delete fCuePoints;
 
   // Delete any outstanding "MatroskaDemux"s, and the table for them:
-  MatroskaDemux* demux;
-  while ((demux = (MatroskaDemux*)fDemuxesTable->RemoveNext()) != NULL) {
-    delete demux;
+  DemuxRecord* demuxRecord;
+  while ((demuxRecord = (DemuxRecord*)fDemuxesTable->RemoveNext()) != NULL) {
+    delete demuxRecord->demux;
+    delete demuxRecord;
   }
   delete fDemuxesTable;
   delete fTrackTable;
@@ -233,15 +240,30 @@
   return fTrackTable->lookup(trackNumber);
 }
 
-MatroskaDemux* MatroskaFile::newDemux() {
+MatroskaDemux* MatroskaFile
+::newDemux(MatroskaDemuxOnDeletionFunc* onDeletionFunc, void* objectToNotify) {
   MatroskaDemux* demux = new MatroskaDemux(*this);
-  fDemuxesTable->Add((char const*)demux, demux);
+
+  DemuxRecord* demuxRecord = new DemuxRecord();
+  demuxRecord->demux = demux;
+  demuxRecord->onDeletionFunc = onDeletionFunc;
+  demuxRecord->objectToNotify = objectToNotify;
+
+  fDemuxesTable->Add((char const*)demux, demuxRecord);
 
   return demux;
 }
 
 void MatroskaFile::removeDemux(MatroskaDemux* demux) {
-  fDemuxesTable->Remove((char const*)demux);
+  DemuxRecord* demuxRecord = (DemuxRecord*)(fDemuxesTable->Lookup((char 
const*)demux));
+  if (demuxRecord != NULL) {
+    fDemuxesTable->Remove((char const*)demux);
+
+    if (demuxRecord->onDeletionFunc != NULL) {
+      (*demuxRecord->onDeletionFunc)(demuxRecord->objectToNotify, demux);
+    }
+    delete demuxRecord;
+  }
 }
 
 #define getPrivByte(b) if (n == 0) break; else do {b = *p++; --n;} while (0) 
/* Vorbis/Theora configuration header parsing */
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/live/liveMedia/MatroskaFileServerDemux.cpp 
new/live/liveMedia/MatroskaFileServerDemux.cpp
--- old/live/liveMedia/MatroskaFileServerDemux.cpp      2021-05-22 
07:12:13.000000000 +0200
+++ new/live/liveMedia/MatroskaFileServerDemux.cpp      2021-08-09 
08:33:36.000000000 +0200
@@ -87,7 +87,7 @@
       // for other ('real') session ids).  Because of this, a separate 
demultiplexor is used for each 'session 0' track.
   }
 
-  if (demuxToUse == NULL) demuxToUse = fOurMatroskaFile->newDemux();
+  if (demuxToUse == NULL) demuxToUse = 
fOurMatroskaFile->newDemux(onDemuxDeletion, this);
 
   fLastClientSessionId = clientSessionId;
   fLastCreatedDemux = demuxToUse;
@@ -119,3 +119,12 @@
   // Now, call our own creation notification function:
   if (fOnCreation != NULL) (*fOnCreation)(this, fOnCreationClientData);
 }
+
+void MatroskaFileServerDemux
+::onDemuxDeletion(void* clientData, MatroskaDemux* demuxBeingDeleted) {
+  ((MatroskaFileServerDemux*)clientData)->onDemuxDeletion(demuxBeingDeleted);
+}
+
+void MatroskaFileServerDemux::onDemuxDeletion(MatroskaDemux* 
demuxBeingDeleted) {
+  if (fLastCreatedDemux == demuxBeingDeleted) fLastCreatedDemux = NULL;
+}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/live/liveMedia/OggFile.cpp 
new/live/liveMedia/OggFile.cpp
--- old/live/liveMedia/OggFile.cpp      2021-05-22 07:12:13.000000000 +0200
+++ new/live/liveMedia/OggFile.cpp      2021-08-09 08:33:36.000000000 +0200
@@ -56,13 +56,38 @@
   return fTrackTable->lookup(trackNumber);
 }
 
-OggDemux* OggFile::newDemux() {
+struct DemuxRecord {
+  OggDemux* demux;
+  OggDemuxOnDeletionFunc* onDeletionFunc;
+  void* objectToNotify;
+};
+
+OggDemux* OggFile
+::newDemux(OggDemuxOnDeletionFunc* onDeletionFunc, void* objectToNotify) {
   OggDemux* demux = new OggDemux(*this);
-  fDemuxesTable->Add((char const*)demux, demux);
+
+  DemuxRecord* demuxRecord = new DemuxRecord();
+  demuxRecord->demux = demux;
+  demuxRecord->onDeletionFunc = onDeletionFunc;
+  demuxRecord->objectToNotify = objectToNotify;
+
+  fDemuxesTable->Add((char const*)demux, demuxRecord);
 
   return demux;
 }
 
+void OggFile::removeDemux(OggDemux* demux) {
+  DemuxRecord* demuxRecord = (DemuxRecord*)(fDemuxesTable->Lookup((char 
const*)demux));
+  if (demuxRecord != NULL) {
+    fDemuxesTable->Remove((char const*)demux);
+
+    if (demuxRecord->onDeletionFunc != NULL) {
+      (*demuxRecord->onDeletionFunc)(demuxRecord->objectToNotify, demux);
+    }
+    delete demuxRecord;
+  }
+}
+
 unsigned OggFile::numTracks() const {
   return fTrackTable->numTracks();
 }
@@ -143,9 +168,10 @@
   delete fParserForInitialization;
 
   // Delete any outstanding "OggDemux"s, and the table for them:
-  OggDemux* demux;
-  while ((demux = (OggDemux*)fDemuxesTable->RemoveNext()) != NULL) {
-    delete demux;
+  DemuxRecord* demuxRecord;
+  while ((demuxRecord = (DemuxRecord*)fDemuxesTable->RemoveNext()) != NULL) {
+    delete demuxRecord->demux;
+    delete demuxRecord;
   }
   delete fDemuxesTable;
   delete fTrackTable;
@@ -169,10 +195,6 @@
   fTrackTable->add(newTrack);
 }
 
-void OggFile::removeDemux(OggDemux* demux) {
-  fDemuxesTable->Remove((char const*)demux);
-}
-
 
 ////////// OggTrackTable implementation /////////
 
@@ -290,7 +312,7 @@
   fDemuxedTracksTable->Remove((char const*)trackNumber);
   if (fDemuxedTracksTable->numEntries() == 0) {
     // We no longer have any demuxed tracks, so delete ourselves now:
-    delete this;
+    Medium::close(this);
   }
 }
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/live/liveMedia/OggFileServerDemux.cpp 
new/live/liveMedia/OggFileServerDemux.cpp
--- old/live/liveMedia/OggFileServerDemux.cpp   2021-05-22 07:12:13.000000000 
+0200
+++ new/live/liveMedia/OggFileServerDemux.cpp   2021-08-09 08:33:36.000000000 
+0200
@@ -71,7 +71,7 @@
       // for other ('real') session ids).  Because of this, a separate 
demultiplexor is used for each 'session 0' track.
   }
 
-  if (demuxToUse == NULL) demuxToUse = fOurOggFile->newDemux();
+  if (demuxToUse == NULL) demuxToUse = fOurOggFile->newDemux(onDemuxDeletion, 
this);
 
   fLastClientSessionId = clientSessionId;
   fLastCreatedDemux = demuxToUse;
@@ -107,3 +107,11 @@
   // Now, call our own creation notification function:
   if (fOnCreation != NULL) (*fOnCreation)(this, fOnCreationClientData);
 }
+
+void OggFileServerDemux::onDemuxDeletion(void* clientData, OggDemux* 
demuxBeingDeleted) {
+  ((OggFileServerDemux*)clientData)->onDemuxDeletion(demuxBeingDeleted);
+}
+
+void OggFileServerDemux::onDemuxDeletion(OggDemux* demuxBeingDeleted) {
+  if (fLastCreatedDemux == demuxBeingDeleted) fLastCreatedDemux = NULL;
+}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/live/liveMedia/ProxyServerMediaSession.cpp 
new/live/liveMedia/ProxyServerMediaSession.cpp
--- old/live/liveMedia/ProxyServerMediaSession.cpp      2021-05-22 
07:12:13.000000000 +0200
+++ new/live/liveMedia/ProxyServerMediaSession.cpp      2021-08-09 
08:33:36.000000000 +0200
@@ -653,10 +653,13 @@
     if (proxyRTSPClient->fLastCommandWasPLAY) { // so that we send only one 
"PAUSE"; not one for each subsession
       if (fParentSession->referenceCount() > 1) {
        // There are other client(s) still streaming other subsessions of this 
stream.
-       // Therefore, we don't send a "PAUSE" for the whole stream, but only 
for the sub-stream:
-       proxyRTSPClient->sendPauseCommand(fClientMediaSubsession, NULL, 
proxyRTSPClient->auth());
+       // Therefore, we don't send a "PAUSE" for the whole stream.
+       // In principle, we would send a "PAUSE" only for the sub-stream here, 
but some
+       // back-end servers might mis-handle that by pausing the entire stream.
+       // So instead, we do nothing here.
+       //proxyRTSPClient->sendPauseCommand(fClientMediaSubsession, NULL, 
proxyRTSPClient->auth());
       } else {
-       // Normal case: There are no other client still streaming (parts of) 
this stream.
+       // Normal case: There are no other clients still streaming (parts of) 
this stream.
        // Send a "PAUSE" for the whole stream.
        
proxyRTSPClient->sendPauseCommand(fClientMediaSubsession.parentSession(), NULL, 
proxyRTSPClient->auth());
        proxyRTSPClient->fLastCommandWasPLAY = False;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/live/liveMedia/RTSPClient.cpp 
new/live/liveMedia/RTSPClient.cpp
--- old/live/liveMedia/RTSPClient.cpp   2021-05-22 07:12:13.000000000 +0200
+++ new/live/liveMedia/RTSPClient.cpp   2021-08-09 08:33:36.000000000 +0200
@@ -1301,6 +1301,9 @@
       MediaSubsessionIterator iter(*session);
       MediaSubsession* subsession;
       while ((subsession = iter.next()) != NULL) {
+       subsession->scale() = session->scale();
+       subsession->speed() = session->speed();
+
        u_int16_t seqNum; u_int32_t timestamp;
        subsession->rtpInfo.infoIsNew = False;
        if (parseRTPInfoParams(rtpInfoParamsStr, seqNum, timestamp)) {
@@ -1328,9 +1331,9 @@
       u_int16_t seqNum; u_int32_t timestamp;
       subsession->rtpInfo.infoIsNew = False;
       if (parseRTPInfoParams(rtpInfoParamsStr, seqNum, timestamp)) {
-    subsession->rtpInfo.seqNum = seqNum;
-    subsession->rtpInfo.timestamp = timestamp;
-    subsession->rtpInfo.infoIsNew = True;
+       subsession->rtpInfo.seqNum = seqNum;
+       subsession->rtpInfo.timestamp = timestamp;
+       subsession->rtpInfo.infoIsNew = True;
       }
 
       if (subsession->rtpSource() != NULL) 
subsession->rtpSource()->enableRTCPReports() = True; // start sending RTCP 
"RR"s now
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/live/liveMedia/include/MP3FileSource.hh 
new/live/liveMedia/include/MP3FileSource.hh
--- old/live/liveMedia/include/MP3FileSource.hh 2021-05-22 07:12:13.000000000 
+0200
+++ new/live/liveMedia/include/MP3FileSource.hh 2021-08-09 08:33:36.000000000 
+0200
@@ -56,11 +56,13 @@
   virtual void getAttributes() const;
 
 private:
-  virtual Boolean doGetNextFrame1();
+  static void fileReadableHandler(MP3FileSource* source, int mask);
 
 private:
   MP3StreamState* fStreamState;
-  Boolean fHaveJustInitialized;
+  Boolean fFidIsSeekable;
+  Boolean fHaveStartedReading;
+  unsigned fHaveBeenInitialized;
   struct timeval fFirstFramePresentationTime; // set on stream init
   Boolean fLimitNumBytesToStream;
   unsigned fNumBytesToStream; // used iff "fLimitNumBytesToStream" is True
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/live/liveMedia/include/MPEG1or2Demux.hh 
new/live/liveMedia/include/MPEG1or2Demux.hh
--- old/live/liveMedia/include/MPEG1or2Demux.hh 2021-05-22 07:12:13.000000000 
+0200
+++ new/live/liveMedia/include/MPEG1or2Demux.hh 2021-08-09 08:33:36.000000000 
+0200
@@ -27,11 +27,15 @@
 
 class MPEG1or2DemuxedElementaryStream; // forward
 
+typedef void MPEG1or2DemuxOnDeletionFunc(void* objectToNotify, class 
MPEG1or2Demux* demuxBeingDeleted);
+
 class MPEG1or2Demux: public Medium {
 public:
   static MPEG1or2Demux* createNew(UsageEnvironment& env,
                                  FramedSource* inputSource,
-                                 Boolean reclaimWhenLastESDies = False);
+                                 Boolean reclaimWhenLastESDies = False,
+                                 MPEG1or2DemuxOnDeletionFunc* onDeletionFunc = 
NULL,
+                                 void* objectToNotify = NULL);
   // If "reclaimWhenLastESDies" is True, the the demux is deleted when
   // all "MPEG1or2DemuxedElementaryStream"s that we created get deleted.
 
@@ -81,7 +85,8 @@
 
 private:
   MPEG1or2Demux(UsageEnvironment& env,
-               FramedSource* inputSource, Boolean reclaimWhenLastESDies);
+               FramedSource* inputSource, Boolean reclaimWhenLastESDies,
+               MPEG1or2DemuxOnDeletionFunc* onDeletionFunc, void* 
objectToNotify);
       // called only by createNew()
   virtual ~MPEG1or2Demux();
 
@@ -142,6 +147,9 @@
   unsigned fNumPendingReads;
   Boolean fHaveUndeliveredData;
 
+  MPEG1or2DemuxOnDeletionFunc* fOnDeletionFunc;
+  void* fOnDeletionObjectToNotify;
+
 private: // parsing state
   class MPEGProgramStreamParser* fParser;
   friend class MPEGProgramStreamParser; // hack
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/live/liveMedia/include/MPEG1or2FileServerDemux.hh 
new/live/liveMedia/include/MPEG1or2FileServerDemux.hh
--- old/live/liveMedia/include/MPEG1or2FileServerDemux.hh       2021-05-22 
07:12:13.000000000 +0200
+++ new/live/liveMedia/include/MPEG1or2FileServerDemux.hh       2021-08-09 
08:33:36.000000000 +0200
@@ -54,6 +54,9 @@
   MPEG1or2DemuxedElementaryStream* newElementaryStream(unsigned 
clientSessionId,
                                                       u_int8_t streamIdTag);
 
+  static void onDemuxDeletion(void* clientData, MPEG1or2Demux* 
demuxBeingDeleted);
+  void onDemuxDeletion(MPEG1or2Demux* demuxBeingDeleted);
+
 private:
   char const* fFileName;
   unsigned fFileSize;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/live/liveMedia/include/MatroskaFile.hh 
new/live/liveMedia/include/MatroskaFile.hh
--- old/live/liveMedia/include/MatroskaFile.hh  2021-05-22 07:12:13.000000000 
+0200
+++ new/live/liveMedia/include/MatroskaFile.hh  2021-08-09 08:33:36.000000000 
+0200
@@ -34,6 +34,8 @@
 class MatroskaTrack; // forward
 class MatroskaDemux; // forward
 
+typedef void MatroskaDemuxOnDeletionFunc(void* objectToNotify, MatroskaDemux* 
demuxBeingDeleted);
+
 class MatroskaFile: public Medium {
 public:
   typedef void (onCreationFunc)(MatroskaFile* newFile, void* clientData);
@@ -45,8 +47,9 @@
 
   MatroskaTrack* lookup(unsigned trackNumber) const;
 
-  // Create a demultiplexor for extracting tracks from this file.  (Separate 
clients will typically have separate demultiplexors.)
-  MatroskaDemux* newDemux();
+  MatroskaDemux* newDemux(MatroskaDemuxOnDeletionFunc* onDeletionFunc = NULL, 
void* objectToNotify = NULL);
+      // Creates a demultiplexor for extracting tracks from this file.
+      // (Separate clients will typically have separate demultiplexors.)
 
   // Parameters of the file ('Segment'); set when the file is parsed:
   unsigned timecodeScale() { return fTimecodeScale; } // in nanoseconds
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/live/liveMedia/include/MatroskaFileServerDemux.hh 
new/live/liveMedia/include/MatroskaFileServerDemux.hh
--- old/live/liveMedia/include/MatroskaFileServerDemux.hh       2021-05-22 
07:12:13.000000000 +0200
+++ new/live/liveMedia/include/MatroskaFileServerDemux.hh       2021-08-09 
08:33:36.000000000 +0200
@@ -67,6 +67,10 @@
 
   static void onMatroskaFileCreation(MatroskaFile* newFile, void* clientData);
   void onMatroskaFileCreation(MatroskaFile* newFile);
+
+  static void onDemuxDeletion(void* clientData, MatroskaDemux* 
demuxBeingDeleted);
+  void onDemuxDeletion(MatroskaDemux* demuxBeingDeleted);
+
 private:
   char const* fFileName; 
   onCreationFunc* fOnCreation;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/live/liveMedia/include/OggFile.hh 
new/live/liveMedia/include/OggFile.hh
--- old/live/liveMedia/include/OggFile.hh       2021-05-22 07:12:13.000000000 
+0200
+++ new/live/liveMedia/include/OggFile.hh       2021-08-09 08:33:36.000000000 
+0200
@@ -31,6 +31,8 @@
 class OggTrack; // forward
 class OggDemux; // forward
 
+typedef void OggDemuxOnDeletionFunc(void* objectToNotify, OggDemux* 
demuxBeingDeleted);
+
 class OggFile: public Medium {
 public:
   typedef void (onCreationFunc)(OggFile* newFile, void* clientData);
@@ -44,7 +46,7 @@
 
   OggTrack* lookup(u_int32_t trackNumber);
 
-  OggDemux* newDemux();
+  OggDemux* newDemux(OggDemuxOnDeletionFunc* onDeletionFunc = NULL, void* 
objectToNotify = NULL);
       // Creates a demultiplexor for extracting tracks from this file.
       // (Separate clients will typically have separate demultiplexors.)
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/live/liveMedia/include/OggFileServerDemux.hh 
new/live/liveMedia/include/OggFileServerDemux.hh
--- old/live/liveMedia/include/OggFileServerDemux.hh    2021-05-22 
07:12:13.000000000 +0200
+++ new/live/liveMedia/include/OggFileServerDemux.hh    2021-08-09 
08:33:36.000000000 +0200
@@ -64,6 +64,10 @@
 
   static void onOggFileCreation(OggFile* newFile, void* clientData);
   void onOggFileCreation(OggFile* newFile);
+
+  static void onDemuxDeletion(void* clientData, OggDemux* demuxBeingDeleted);
+  void onDemuxDeletion(OggDemux* demuxBeingDeleted);
+  
 private:
   char const* fFileName; 
   onCreationFunc* fOnCreation;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/live/liveMedia/include/liveMedia_version.hh 
new/live/liveMedia/include/liveMedia_version.hh
--- old/live/liveMedia/include/liveMedia_version.hh     2021-05-22 
07:12:13.000000000 +0200
+++ new/live/liveMedia/include/liveMedia_version.hh     2021-08-09 
08:33:36.000000000 +0200
@@ -19,7 +19,7 @@
 #ifndef _LIVEMEDIA_VERSION_HH
 #define _LIVEMEDIA_VERSION_HH
 
-#define LIVEMEDIA_LIBRARY_VERSION_STRING       "2021.05.22"
-#define LIVEMEDIA_LIBRARY_VERSION_INT          1621641600
+#define LIVEMEDIA_LIBRARY_VERSION_STRING       "2021.08.09"
+#define LIVEMEDIA_LIBRARY_VERSION_INT          1628467200
 
 #endif

Reply via email to