[Live-devel] OPUS encoded stream via SimpleRTPSink

Clemens Arth clemens at arth.co.at
Sat Feb 4 06:14:09 PST 2017


> You’re correct that “SimpleRTPSink” is the correct ‘sink’ class to
> use.  (You can do this because the RTP payload format for OPUS audio
> - defined in RFC 7587 - is relatively straightforward.)

> Note that - from RFC 7587, section 4.2 - a RTP packet contains
> exactly one ‘OPUS packet’, which must represent no more than 120ms of
> audio.  An ‘OPUS packet’ is defined in RFC 6716, section 3.
> Therefore, your input source (to the “SimpleRTPSink”) must deliver
> exactly one ‘OPUS packet’ at a time - i.e., as a ‘frame’ in our
> software.

> Your call to “SimpleRTPSink::createNew()” (e.g., from your
> “createNewRTPSink()” function, if you’re doing this from a RTSP
> server) would be:
> 	SimpleRTPSink::createNew(env, rtpGS, rtpPayloadTypeIfDynamic,
> 48000, "audio", "OPUS", 2, False);

thanks a lot. For testing I used the following:

m_audioSink = SimpleRTPSink::createNew(*m_env, m_rtpGroupsockAud, 96,
48000,"audio", "OPUS", 1, false);

I always push exactly one packet each time. VLC recognizes the stream as
"audio" and retrieves packets, but it says the codec is "undef" and does
not play.

I did not fully get the part about the RTP packet assembly. The RTP
packet (12-byte header) is created by the RTPSink, right? So after
digging through the RFCs and the code, is there any more information
that I actively have to provide in addition to the frame itself? Right
now I also set fFrameSize, fNumTruncatedBytes, fPresentationTime,
fDurationInMicroseconds, although I don't know if this is mandatory?

I know you don't look at codes :-) , however, here it is:

void deliverFrame()
{
    if((!isCurrentlyAwaitingData()))
        return;

    if(!m_queue.empty())
    {
        gettimeofday(&fPresentationTime, NULL);
        fDurationInMicroseconds = 20000; // 20 ms buffers!

        m_queueMutex.lock();
        OPUSFrame newFrame = m_queue.front(); m_queue.pop();
        m_queueMutex.unlock();

        unsigned newFrameSize = newFrame.m_size;

        // Deliver the data here:
        if (newFrameSize > fMaxSize) {
            fFrameSize = fMaxSize;
            fNumTruncatedBytes = newFrameSize - fMaxSize;
        }
        else {
            fFrameSize = newFrameSize;
        }

        memcpy(fTo, newFrame.m_buf, newFrame.m_size);

        // free memory in frame struct
        delete[] newFrame.m_buf;

        FramedSource::afterGetting(this);
    }
}













More information about the live-devel mailing list