After doing some in-depth debugging on Live555 itself, I have found that it contains a bug. The $-delimited data is basically RTCP "RR" packets that wrongly get sent before the PLAY command has been issued (it should only happen after PLAY has been issued). The 2012/10/04 build of live555 seems to have included a "EnableRTCPReports" flag to indicate whether sending of "RR" can proceed or not and this value is set to allow sending of these reports only after the PLAY has been issued.
However, in the code that actually does the sending, there is a condition under which this flag is not checked before sending out the "RR" report. This is the bug that I found. This bug report has been submitted to the Live555 project along with the fix, but I am placing the fix here as well for anyone encountering it in the meantime:
In livemedia/include/RTSPSource.hh we have the enableRTCPReports function to return fEnableRTCPReports. However, this cannot be called by a const object (which is what we'll need to do), so simply declare a very similar function, but make it const and safe:
...
Boolean& enableRTCPReports() { return fEnableRTCPReports; }
//****The following function is part of the fix. The same as enableRTCPReports except that it is "const" and "safe" for const object references to call, which means we can call this from RTCPInstance using the fSource object there.
Boolean constAccessibleEnableRTCPReports() const { return fEnableRTCPReports; }
...
In livemedia/RTCP.cpp:
...
Boolean RTCPInstance::addReport(Boolean alwaysAdd) {
// Include a SR or a RR, depending on whether we have an associated sink or source:
if (fSink != NULL) {
if (!alwaysAdd) {
if (!fSink->enableRTCPReports()) return False;
// Hack: Don't send a SR during those (brief) times when the timestamp of the
// next outgoing RTP packet has been preset, to ensure that that timestamp gets
// used for that outgoing packet. (David Bertrand, 2006.07.18)
if (fSink->nextTimestampHasBeenPreset()) return False;
}
addSR();
} else if (fSource != NULL) {
//****The following IF-statement is the fix. As in the case of the Sink Node above (but using our "const-accessible" function), we first check the value of EnableRTCPReports before we do addRR().
if (!fSource->constAccessibleEnableRTCPReports()) return false;
addRR();
}
return True;
}
...