[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