[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