[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