[Live-devel] doGetNextFrame interval

James Heliker james.heliker at gmail.com
Sat Oct 11 19:10:51 PDT 2014


Hi Ross -

Thanks again for your help here. I understand what you're saying with using
an event trigger for when additional data is available, but I'm having no
luck implementing as my C++ is fairly bad. Coming from C# and other
higher-level languages is proving to be a bit of a learning curve for me!

I have a very simple circular buffer in my code as RtAudio code (for ASIO
input device) calls back my code, and the Live555 code also calls back my
code, both at their own regular intervals. Below, I've posted my
AudioBufferSource::doGetNextFrame(), in hopes you might be able to provide
a more verbose suggestion... I understand if you don't have the time.

Thanks again!

- James

void AudioBufferSource::doGetNextFrame() {

    signed availableFrames = fBufferManager->_writeCnt -
fBufferManager->_readCnt;
    while (availableFrames < 64)
    {
        availableFrames = fBufferManager->_writeCnt -
fBufferManager->_readCnt;
    }

    fFrameSize = 0;

    if (fLimitNumBytesToStream && fNumBytesToStream < fMaxSize) {
    fMaxSize = fNumBytesToStream;
    }
    if (fPreferredFrameSize < fMaxSize) {
    fMaxSize = fPreferredFrameSize;
    }

    unsigned bytesPerSample = (fNumChannels*fBitsPerSample) / 8;
    if (bytesPerSample == 0) bytesPerSample = 1; // because we can't read
less than a byte at a time

    unsigned numberOfPCMFramesToGet = fMaxSize / bytesPerSample;
    unsigned pcmFramesGotten = fBufferManager->getFrames((int16_t*)fTo,
numberOfPCMFramesToGet);

    unsigned numBytesRead = pcmFramesGotten * bytesPerSample;
    fFrameSize += numBytesRead;
    fTo += numBytesRead;
    fMaxSize -= numBytesRead;
    fNumBytesToStream -= numBytesRead;

    // Set the 'presentation time' and 'duration' of this RTP frame
    if (fPresentationTime.tv_sec == 0 && fPresentationTime.tv_usec == 0) {
        // This is the first frame, so use the current time:
        gettimeofday(&fPresentationTime, NULL);
    }
    else {
        // Increment by the play time of the previous RTP frame
        unsigned uSeconds = fPresentationTime.tv_usec + fLastPlayTime;
        fPresentationTime.tv_sec += uSeconds / 1000000;
        fPresentationTime.tv_usec = uSeconds % 1000000;
    }

    // Remember the play time of this RTP frame
    fDurationInMicroseconds = fLastPlayTime =
(unsigned)((fPlayTimePerSample*fFrameSize) / bytesPerSample);

    // Inform the reader that he has data:
    // To avoid possible infinite recursion, we need to return to the event
loop to do this:
    nextTask() = envir().taskScheduler().scheduleDelayedTask(0,
(TaskFunc*)FramedSource::afterGetting, this);
}




On Sat, Oct 11, 2014 at 8:14 AM, Ross Finlayson <finlayson at live555.com>
wrote:

> I see what you mean, and fDurationInMicroseconds is being calculated
> correctly. For my fragmentation issue, If I don't call afterGetting() then
> doGetNextFrame() is not ever re-invoked, so the server essentially stops on
> the first partial read.
>
> Is there a method or variable I should set to indicate to Live555 that I
> want to continue accumulating data?
>
>
> Your "doGetNextFrame()" implementation should call
> "FramedSource::afterGetting()" *only* when you have a complete frame that
> you want to deliver to the downstream object.  If you don't yet have a
> complete frame, then simply return, without
> calling "FramedSource::afterGetting()".  If you do that, then
> "doGetNextFrame()" won't get called again in the meantime.
>
> But, you're probably thinking, if "doGetNextFrame()" simply returns
> without completing delivery of a frame, and doesn't get called again, then
> how can I figure out when I later get enough data to deliver?  Basically,
> that has to be an 'event' that gets handled within the event loop.  One way
> to do this is by 'polling' - i.e., by scheduling a periodic delayed task
> (using "TaskScheduler::scheduleDelayedTask()") that checks whether you have
> enough data (and then calls "FramedSource::afterGetting()" when you do have
> enough data).  Another way is to have a separate thread that's gathering
> data, and then have this thread use an 'event trigger' (by calling
> "TaskScheduler::triggerEvent()") to signal when data is ready to be
> delivered.  For an example of this, see the 'DeviceSource' code in
> "liveMedia/DeviceSource.cpp".  (Note that if you do this, then
> "TaskScheduler::triggerEvent()" is the *only* LIVE555 function that the
> separate 'data gathering' thread is allowed to call; see <
> http://www.live555.com/liveMedia/faq.html#threads>).
>
>
> Ross Finlayson
> Live Networks, Inc.
> http://www.live555.com/
>
>
> _______________________________________________
> live-devel mailing list
> live-devel at lists.live555.com
> http://lists.live555.com/mailman/listinfo/live-devel
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.live555.com/pipermail/live-devel/attachments/20141011/be8de7c7/attachment-0001.html>


More information about the live-devel mailing list