1/**********
2This library is free software; you can redistribute it and/or modify it under
3the terms of the GNU Lesser General Public License as published by the
4Free Software Foundation; either version 3 of the License, or (at your
5option) any later version. (See <http://www.gnu.org/copyleft/lesser.html>.)
6
7This library is distributed in the hope that it will be useful, but WITHOUT
8ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
9FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
10more details.
11
12You should have received a copy of the GNU Lesser General Public License
13along with this library; if not, write to the Free Software Foundation, Inc.,
1451 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
15**********/
16// "liveMedia"
17// Copyright (c) 1996-2020 Live Networks, Inc. All rights reserved.
18// RTP sink for Vorbis audio
19// Implementation
20
21#include "VorbisAudioRTPSink.hh"
22#include "Base64.hh"
23#include "VorbisAudioRTPSource.hh" // for parseVorbisOrTheoraConfigStr()
24
25VorbisAudioRTPSink* VorbisAudioRTPSink
26::createNew(UsageEnvironment& env, Groupsock* RTPgs,
27 u_int8_t rtpPayloadFormat, u_int32_t rtpTimestampFrequency, unsigned numChannels,
28 u_int8_t* identificationHeader, unsigned identificationHeaderSize,
29 u_int8_t* commentHeader, unsigned commentHeaderSize,
30 u_int8_t* setupHeader, unsigned setupHeaderSize,
31 u_int32_t identField) {
32 return new VorbisAudioRTPSink(env, RTPgs,
33 rtpPayloadFormat, rtpTimestampFrequency, numChannels,
34 identificationHeader, identificationHeaderSize,
35 commentHeader, commentHeaderSize,
36 setupHeader, setupHeaderSize,
37 identField);
38}
39
40VorbisAudioRTPSink* VorbisAudioRTPSink
41::createNew(UsageEnvironment& env, Groupsock* RTPgs,u_int8_t rtpPayloadFormat,
42 u_int32_t rtpTimestampFrequency, unsigned numChannels,
43 char const* configStr) {
44 // Begin by decoding and unpacking the configuration string:
45 u_int8_t* identificationHeader; unsigned identificationHeaderSize;
46 u_int8_t* commentHeader; unsigned commentHeaderSize;
47 u_int8_t* setupHeader; unsigned setupHeaderSize;
48 u_int32_t identField;
49
50 parseVorbisOrTheoraConfigStr(configStr,
51 identificationHeader, identificationHeaderSize,
52 commentHeader, commentHeaderSize,
53 setupHeader, setupHeaderSize,
54 identField);
55
56 VorbisAudioRTPSink* resultSink
57 = new VorbisAudioRTPSink(env, RTPgs, rtpPayloadFormat, rtpTimestampFrequency, numChannels,
58 identificationHeader, identificationHeaderSize,
59 commentHeader, commentHeaderSize,
60 setupHeader, setupHeaderSize,
61 identField);
62 delete[] identificationHeader; delete[] commentHeader; delete[] setupHeader;
63
64 return resultSink;
65}
66
67VorbisAudioRTPSink
68::VorbisAudioRTPSink(UsageEnvironment& env, Groupsock* RTPgs, u_int8_t rtpPayloadFormat,
69 u_int32_t rtpTimestampFrequency, unsigned numChannels,
70 u_int8_t* identificationHeader, unsigned identificationHeaderSize,
71 u_int8_t* commentHeader, unsigned commentHeaderSize,
72 u_int8_t* setupHeader, unsigned setupHeaderSize,
73 u_int32_t identField)
74 : AudioRTPSink(env, RTPgs, rtpPayloadFormat, rtpTimestampFrequency, "VORBIS", numChannels),
75 fIdent(identField), fFmtpSDPLine(NULL) {
76 if (identificationHeaderSize >= 28) {
77 // Get the 'bitrate' values from this header, and use them to set our estimated bitrate:
78 u_int32_t val;
79 u_int8_t* p;
80
81 p = &identificationHeader[16];
82 val = ((p[3]*256 + p[2])*256 + p[1])*256 + p[0]; // i.e., little-endian
83 int bitrate_maximum = (int)val;
84 if (bitrate_maximum < 0) bitrate_maximum = 0;
85
86 p = &identificationHeader[20];
87 val = ((p[3]*256 + p[2])*256 + p[1])*256 + p[0]; // i.e., little-endian
88 int bitrate_nominal = (int)val;
89 if (bitrate_nominal < 0) bitrate_nominal = 0;
90
91 p = &identificationHeader[24];
92 val = ((p[3]*256 + p[2])*256 + p[1])*256 + p[0]; // i.e., little-endian
93 int bitrate_minimum = (int)val;
94 if (bitrate_minimum < 0) bitrate_minimum = 0;
95
96 int bitrate
97 = bitrate_nominal > 0 ? bitrate_nominal
98 : bitrate_maximum > 0 ? bitrate_maximum
99 : bitrate_minimum > 0 ? bitrate_minimum : 0;
100 if (bitrate > 0) estimatedBitrate() = ((unsigned)bitrate)/1000;
101 }
102
103 // Generate a 'config' string from the supplied configuration headers:
104 char* base64PackedHeaders
105 = generateVorbisOrTheoraConfigStr(identificationHeader, identificationHeaderSize,
106 commentHeader, commentHeaderSize,
107 setupHeader, setupHeaderSize,
108 identField);
109 if (base64PackedHeaders == NULL) return;
110
111 // Then use this 'config' string to construct our "a=fmtp:" SDP line:
112 unsigned fmtpSDPLineMaxSize = 50 + strlen(base64PackedHeaders); // 50 => more than enough space
113 fFmtpSDPLine = new char[fmtpSDPLineMaxSize];
114 sprintf(fFmtpSDPLine, "a=fmtp:%d configuration=%s\r\n", rtpPayloadType(), base64PackedHeaders);
115 delete[] base64PackedHeaders;
116}
117
118VorbisAudioRTPSink::~VorbisAudioRTPSink() {
119 delete[] fFmtpSDPLine;
120}
121
122char const* VorbisAudioRTPSink::auxSDPLine() {
123 return fFmtpSDPLine;
124}
125
126void VorbisAudioRTPSink
127::doSpecialFrameHandling(unsigned fragmentationOffset,
128 unsigned char* frameStart,
129 unsigned numBytesInFrame,
130 struct timeval framePresentationTime,
131 unsigned numRemainingBytes) {
132 // Set the 4-byte "payload header", as defined in RFC 5215, section 2.2:
133 u_int8_t header[4];
134
135 // The first three bytes of the header are our "Ident":
136 header[0] = fIdent>>16; header[1] = fIdent>>8; header[2] = fIdent;
137
138 // The final byte contains the "F", "VDT", and "numPkts" fields:
139 u_int8_t F; // Fragment type
140 if (numRemainingBytes > 0) {
141 if (fragmentationOffset > 0) {
142 F = 2<<6; // continuation fragment
143 } else {
144 F = 1<<6; // start fragment
145 }
146 } else {
147 if (fragmentationOffset > 0) {
148 F = 3<<6; // end fragment
149 } else {
150 F = 0<<6; // not fragmented
151 }
152 }
153 u_int8_t const VDT = 0<<4; // Vorbis Data Type (always a "Raw Vorbis payload")
154 u_int8_t numPkts = F == 0 ? (numFramesUsedSoFar() + 1): 0; // set to 0 when we're a fragment
155 header[3] = F|VDT|numPkts;
156
157 setSpecialHeaderBytes(header, sizeof header);
158
159 // There's also a 2-byte 'frame-specific' header: The length of the Vorbis data:
160 u_int8_t frameSpecificHeader[2];
161 frameSpecificHeader[0] = numBytesInFrame>>8;
162 frameSpecificHeader[1] = numBytesInFrame;
163 setFrameSpecificHeaderBytes(frameSpecificHeader, 2);
164
165 // Important: Also call our base class's doSpecialFrameHandling(),
166 // to set the packet's timestamp:
167 MultiFramedRTPSink::doSpecialFrameHandling(fragmentationOffset,
168 frameStart, numBytesInFrame,
169 framePresentationTime,
170 numRemainingBytes);
171}
172
173Boolean VorbisAudioRTPSink::frameCanAppearAfterPacketStart(unsigned char const* /*frameStart*/,
174 unsigned /*numBytesInFrame*/) const {
175 // We allow more than one frame to be packed into an outgoing RTP packet, but no more than 15:
176 return numFramesUsedSoFar() <= 15;
177}
178
179unsigned VorbisAudioRTPSink::specialHeaderSize() const {
180 return 4;
181}
182
183unsigned VorbisAudioRTPSink::frameSpecificHeaderSize() const {
184 return 2;
185}
186
187
188////////// generateVorbisOrTheoraConfigStr() implementation //////////
189
190char* generateVorbisOrTheoraConfigStr(u_int8_t* identificationHeader, unsigned identificationHeaderSize,
191 u_int8_t* commentHeader, unsigned commentHeaderSize,
192 u_int8_t* setupHeader, unsigned setupHeaderSize,
193 u_int32_t identField) {
194 // First, count how many headers (<=3) are included, and how many bytes will be used
195 // to encode these headers' sizes:
196 unsigned numHeaders = 0;
197 unsigned sizeSize[2]; // The number of bytes used to encode the lengths of the first two headers (but not the length of the 3rd)
198 sizeSize[0] = sizeSize[1] = 0;
199 if (identificationHeaderSize > 0) {
200 sizeSize[numHeaders++] = identificationHeaderSize < 128 ? 1 : identificationHeaderSize < 16384 ? 2 : 3;
201 }
202 if (commentHeaderSize > 0) {
203 sizeSize[numHeaders++] = commentHeaderSize < 128 ? 1 : commentHeaderSize < 16384 ? 2 : 3;
204 }
205 if (setupHeaderSize > 0) {
206 ++numHeaders;
207 } else {
208 sizeSize[1] = 0; // We have at most two headers, so the second one's length isn't encoded
209 }
210 if (numHeaders == 0) return NULL; // With no headers, we can't set up a configuration
211 if (numHeaders == 1) sizeSize[0] = 0; // With only one header, its length isn't encoded
212
213 // Then figure out the size of the packed configuration headers, and allocate space for this:
214 unsigned length = identificationHeaderSize + commentHeaderSize + setupHeaderSize;
215 // The "length" field in the packed headers
216 if (length > (unsigned)0xFFFF) return NULL; // too big for a 16-bit field; we can't handle this
217 unsigned packedHeadersSize
218 = 4 // "Number of packed headers" field
219 + 3 // "ident" field
220 + 2 // "length" field
221 + 1 // "n. of headers" field
222 + sizeSize[0] + sizeSize[1] // "length1" and "length2" (if present) fields
223 + length;
224 u_int8_t* packedHeaders = new u_int8_t[packedHeadersSize];
225 if (packedHeaders == NULL) return NULL;
226
227 // Fill in the 'packed headers':
228 u_int8_t* p = packedHeaders;
229 *p++ = 0; *p++ = 0; *p++ = 0; *p++ = 1; // "Number of packed headers": 1
230 *p++ = identField>>16; *p++ = identField>>8; *p++ = identField; // "Ident" (24 bits)
231 *p++ = length>>8; *p++ = length; // "length" (16 bits)
232 *p++ = numHeaders-1; // "n. of headers"
233 if (numHeaders > 1) {
234 // Fill in the "length1" header:
235 unsigned length1 = identificationHeaderSize > 0 ? identificationHeaderSize : commentHeaderSize;
236 if (length1 >= 16384) {
237 *p++ = 0x80; // flag, but no more, because we know length1 <= 32767
238 }
239 if (length1 >= 128) {
240 *p++ = 0x80|((length1&0x3F80)>>7); // flag + the second 7 bits
241 }
242 *p++ = length1&0x7F; // the low 7 bits
243
244 if (numHeaders > 2) { // numHeaders == 3
245 // Fill in the "length2" header (for the 'Comment' header):
246 unsigned length2 = commentHeaderSize;
247 if (length2 >= 16384) {
248 *p++ = 0x80; // flag, but no more, because we know length2 <= 32767
249 }
250 if (length2 >= 128) {
251 *p++ = 0x80|((length2&0x3F80)>>7); // flag + the second 7 bits
252 }
253 *p++ = length2&0x7F; // the low 7 bits
254 }
255 }
256 // Copy each header:
257 if (identificationHeader != NULL) memmove(p, identificationHeader, identificationHeaderSize); p += identificationHeaderSize;
258 if (commentHeader != NULL) memmove(p, commentHeader, commentHeaderSize); p += commentHeaderSize;
259 if (setupHeader != NULL) memmove(p, setupHeader, setupHeaderSize);
260
261 // Having set up the 'packed configuration headers', Base-64-encode this, for our result:
262 char* base64PackedHeaders = base64Encode((char const*)packedHeaders, packedHeadersSize);
263 delete[] packedHeaders;
264
265 return base64PackedHeaders;
266}
267