[Live-devel] [PATCH]MPEG1-Audio for Kasenna

Glen Gray glen at lincor.com
Wed Jul 5 03:39:45 PDT 2006


Further to my mail last night, Greg found the reason for the continued 
issues.

<Quote>
StreamParser.cpp is using the wrong index in
StreamParser::ensureValidBytes1() to check for enough remaining space
in a bank buffer.

-  if (fCurParserIndex + bufSpaceNeeded > BANK_SIZE ) {
+  if (fTotNumValidBytes + bufSpaceNeeded > BANK_SIZE ) {

This needs to be combined with my previous UDP data-loss fix
patch to prevent data loss.

This change on it's own will decrease the amount of UDP data
lost but won't stop it.

    Greg



--- StreamParser.cpp	2006-07-05 11:29:04.000000000 +0100
+++ StreamParser.cpp.new	2006-07-05 11:29:49.000000000 +0100
@@ -71,7 +71,7 @@
    // bank.  If so, start using a new bank now.
  //  if (fCurParserIndex + numBytesNeeded > (BANK_SIZE-MAX_PACKET_SIZE)) {

-  if (fCurParserIndex + bufSpaceNeeded > BANK_SIZE ) {
+  if (fTotNumValidBytes + bufSpaceNeeded > BANK_SIZE ) {
      // Swap banks, but save any still-needed bytes from the old bank:
      unsigned numBytesToSave = fTotNumValidBytes - fSavedParserIndex;
      unsigned char const* from = &curBank()[fSavedParserIndex];

</Quote>

Glen Gray wrote:
> Hey Ross/Guys,
> 
> Here is a set of 3 patches we've been working on, to enable MPEG-Audio 
> playback from Kasenna.
> 
> live_mpa_sdp_fix.diff:: modified RTSPClient.cpp to allow it to generate 
> a valid SDP string from Kasenna's Description data. Previously it was 
> hardcoded to just generate a Video SDP. This was done by me back in March.
> 
> The next 2 patches where made by Greg Farrell <greg at lincor.com>. If 
> these are accepted, please ensure he gets the credit for them.
> 
> live_mpeg_audio.diff:: this is effectively the final part of the above 
> patch and was implemented by Greg after I moved off the project onto 
> something else. This basically wraps the in coming UDP data with 
> MPEG1or2AudioStreamFramer, based on the fCodeName string, in much the 
> same way that MPEG2TransportStreamFramer was called to enable Mpeg2-ts 
> video playback from the Kasenna.
> 
> With the first patch above, we got our version of VLC establishing and 
> playing back an MPEG1-Audio stream from our Kasenna, however we didn't 
> get to hear the Audio (no pts's on the raw data). With the second patch 
> we could hear the audio, but noticed a problem. After a while we lost 
> sync and eventually the stream collapsed.
> 
> live555_udp.diff::
> 
> Quote from Greg
>> The StreamParser class uses two receive buffers or 'banks'. It 
>> receives data into
>> one bank until it is full then swaps to the other bank and so on.
>>
>> How the StreamParser class decides if there is enough room in the 
>> current buffer
>> to perform a receive is by checking if the space left is greater than 
>> the number
>> of bytes of data requested from the StreamParser.
>>
>> However if the underlying data source is UDP (BasicUdpSource) then a 
>> receive with
>> a max length of less than the size of incoming UDP packets will result 
>> in the rest of
>> the packet being silently dropped in GroupsockHelper/readSocket().
>>
>> This will happen whenever there is enough room for a frame (the length 
>> of data
>> StreamParser will be asked for) in a bank buffer but not enough room 
>> for a full
>> UDP packet. Kasenna's will put multiple mpeg audio frames in one UDP 
>> packet
>> for efficiency I assume and this will result in lost data on most bank 
>> buffer swaps.
>>
>> To fix it I've changed the StreamParser to swap banks whenever it 
>> believes there is
>> not enough room left for a packet as well as a frame. As you can't 
>> tell in advance what
>> size incoming UDP packets will be the StreamParser defaults to a guess 
>> of 512 bytes
>> and increases that whenever it sees larger packets.
> 
> We are still experiencing some problems however. Namely, pts drifts out 
> of sync and eventually the streams break down. We'd put a hack in place 
> to force the pts values to stay synced and that was when we noticed that 
> we where loosing UDP data. Fixing that with the final patch listed 
> above, we've put all these patches into our VLC build and noticed that 
> we are still experiencing pts drift (which we'd assumed was happening 
> because of the lost UDP data).
> 
> We're continuing to investigate.
> Kind regards,
> 
> 
> ------------------------------------------------------------------------
> 
> diff -uNr vlc-trunk.orig/live/liveMedia/StreamParser.cpp vlc-trunk.work/live/liveMedia/StreamParser.cpp
> --- vlc-trunk.orig/live/liveMedia/StreamParser.cpp	2006-07-04 14:40:17.000000000 +0100
> +++ vlc-trunk.work/live/liveMedia/StreamParser.cpp	2006-07-04 15:33:30.000000000 +0100
> @@ -41,6 +41,7 @@
>    fBank[1] = new unsigned char[BANK_SIZE];
>    fCurBankNum = 0;
>    fCurBank = fBank[fCurBankNum];
> +  MAX_PACKET_SIZE = 512;
>  }
>  
>  StreamParser::~StreamParser() {
> @@ -53,15 +54,23 @@
>    // We need to read some more bytes from the input source.
>    // First, clarify how much data to ask for:
>    unsigned maxInputFrameSize = fInputSource->maxFrameSize();
> +  unsigned bufSpaceNeeded;
>    if (maxInputFrameSize > numBytesNeeded) numBytesNeeded = maxInputFrameSize;
>  
> +  // Check if our frame size or expected max packet sizes are the limiting factor
> +  // on whether we've enough room in our current bank.
> +  if (MAX_PACKET_SIZE > numBytesNeeded)
> +    bufSpaceNeeded = MAX_PACKET_SIZE;
> +  else
> +    bufSpaceNeeded = numBytesNeeded;
> +
>    // First, check whether these new bytes would overflow the current
>    // bank.  If so, start using a new bank now.
> -  if (fCurParserIndex + numBytesNeeded > BANK_SIZE) {
> +  if (fCurParserIndex + bufSpaceNeeded > BANK_SIZE ) {
>      // Swap banks, but save any still-needed bytes from the old bank:
>      unsigned numBytesToSave = fTotNumValidBytes - fSavedParserIndex;
>      unsigned char const* from = &curBank()[fSavedParserIndex];
> -    
> +
>      fCurBankNum = (fCurBankNum + 1)%2;
>      fCurBank = fBank[fCurBankNum];
>      memmove(curBank(), from, numBytesToSave);
> @@ -106,6 +115,9 @@
>        << numBytesRead << " bytes; expected no more than "
>        << BANK_SIZE - buffer->fTotNumValidBytes << "\n";
>    }
> +  // Check if we're receiving larger packets than expected
> +  if ( numBytesRead > buffer->MAX_PACKET_SIZE)
> +      buffer->MAX_PACKET_SIZE = numBytesRead;
>  
>    unsigned char* ptr = &buffer->curBank()[buffer->fTotNumValidBytes];
>    buffer->fTotNumValidBytes += numBytesRead;
> Binary files vlc-trunk.orig/live/liveMedia/.StreamParser.cpp.swp and vlc-trunk.work/live/liveMedia/.StreamParser.cpp.swp differ
> diff -uNr vlc-trunk.orig/live/liveMedia/StreamParser.hh vlc-trunk.work/live/liveMedia/StreamParser.hh
> --- vlc-trunk.orig/live/liveMedia/StreamParser.hh	2006-07-04 14:40:17.000000000 +0100
> +++ vlc-trunk.work/live/liveMedia/StreamParser.hh	2006-07-04 15:19:52.000000000 +0100
> @@ -132,6 +132,7 @@
>    // The current position of the parser within the current bank:
>    unsigned fCurParserIndex; // <= fTotNumValidBytes
>    unsigned char fRemainingUnparsedBits; // in previous byte: [0,7]
> +  unsigned MAX_PACKET_SIZE;
>  
>    // The total number of valid bytes stored in the current bank:
>    unsigned fTotNumValidBytes; // <= BANK_SIZE
> 
> 
> ------------------------------------------------------------------------
> 
> diff -uNr live/liveMedia/RTSPClient.cpp live.lincor/liveMedia/RTSPClient.cpp
> --- live/liveMedia/RTSPClient.cpp	2006-01-27 09:14:44.000000000 +0000
> +++ live.lincor/liveMedia/RTSPClient.cpp	2006-04-05 15:14:41.000000000 +0100
> @@ -452,17 +452,33 @@
>        unsigned char byte2 = (fServerAddress & 0x0000ff00) >>  8;
>        unsigned char byte3 = (fServerAddress & 0x00ff0000) >> 16;
>        unsigned char byte4 = (fServerAddress & 0xff000000) >> 24;
> -      
> -      char const* sdpFmt =
> -	"v=0\r\n"
> -	"o=NoSpacesAllowed 1 1 IN IP4 %u.%u.%u.%u\r\n"
> -	"s=%s\r\n"
> -	"c=IN IP4 %u.%u.%u.%u\r\n"
> -	"t=0 0\r\n"
> -	"a=control:*\r\n"
> -	"a=range:npt=0-%llu\r\n"
> -	"m=video 1554 RAW/RAW/UDP 33\r\n"
> -	"a=control:trackID=%d\r\n";
> +
> +      char const* sdpFmt = NULL;
> +     
> +      if (fKasennaContentType != NULL
> +	  && strcmp(fKasennaContentType, "MPEG1-Audio") == 0) {
> +          sdpFmt =
> +            "v=0\r\n"
> +            "o=NoSpacesAllowed 1 1 IN IP4 %u.%u.%u.%u\r\n"
> +            "s=%s\r\n"
> +            "c=IN IP4 %u.%u.%u.%u\r\n"
> +            "t=0 0\r\n"
> +            "a=control:*\r\n"
> +            "a=range:npt=0-%llu\r\n"
> +            "m=audio 1554 RAW/RAW/UDP 14\r\n"
> +            "a=control:trackID=%d\r\n";
> +      } else {
> +          sdpFmt =
> +            "v=0\r\n"
> +            "o=NoSpacesAllowed 1 1 IN IP4 %u.%u.%u.%u\r\n"
> +            "s=%s\r\n"
> +            "c=IN IP4 %u.%u.%u.%u\r\n"
> +            "t=0 0\r\n"
> +            "a=control:*\r\n"
> +            "a=range:npt=0-%llu\r\n"
> +            "m=video 1554 RAW/RAW/UDP 33\r\n"
> +            "a=control:trackID=%d\r\n";
> +      }
>        unsigned sdpBufSize = strlen(sdpFmt)
>  	+ 4*3 // IP address
>  	+ strlen(url)
> 
> 
> ------------------------------------------------------------------------
> 
> diff -uNr vlc-trunk.orig/live/liveMedia/MediaSession.cpp vlc-trunk.work/live/liveMedia/MediaSession.cpp
> --- vlc-trunk.orig/live/liveMedia/MediaSession.cpp	2006-06-21 10:34:35.000000000 +0100
> +++ vlc-trunk.work/live/liveMedia/MediaSession.cpp	2006-06-21 16:30:33.000000000 +0100
> @@ -648,7 +648,6 @@
>        env().setResultMsg(tmpBuf);
>        break;
>      }
> -
>      // Check "fProtocolName"
>      if (strcmp(fProtocolName, "UDP") == 0) {
>        // A UDP-packetized stream (*not* a RTP stream)
> @@ -659,6 +658,9 @@
>  	fReadSource = MPEG2TransportStreamFramer::createNew(env(), fReadSource);
>  	    // this sets "durationInMicroseconds" correctly, based on the PCR values
>        }
> +      else if (strcmp(fCodecName, "MPA") == 0) { // MPEG Audio Stream
> +	fReadSource =MPEG1or2AudioStreamFramer::createNew(env(), fReadSource);
> +      }
>      } else {
>        // Check "fCodecName" against the set of codecs that we support,
>        // and create our RTP source accordingly


-- 
Glen Gray <glen at lincor.com>              Digital Depot, Thomas Street
Senior Software Engineer                            Dublin 8, Ireland
Lincor Solutions Ltd.                          Ph: +353 (0) 1 4893682


More information about the live-devel mailing list