2 Copyright (c) 2006, Fluendo / Xiph.Org
4 Redistribution and use in source and binary forms, with or without
5 modification, are permitted provided that the following conditions are met:
7 * Redistributions of source code must retain the above copyright notice,
8 this list of conditions and the following disclaimer.
10 * Redistributions in binary form must reproduce the above copyright notice,
11 this list of conditions and the following disclaimer in the documentation
12 and/or other materials provided with the distribution.
14 * Neither the name of the Xiph.Org nor the names of its contributors may
15 be used to endorse or promote products derived from this software without
16 specific prior written permission.
18 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
20 TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
21 PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
22 BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
28 THE POSSIBILITY OF SUCH DAMAGE.
30 Author: Luca Barbato <lu_zero@gentoo.org>
40 #include <vorbis/codec.h>
41 #include <theora/theora.h>
43 #include <arpa/inet.h>
44 #include <netinet/in.h>
46 #include <sys/types.h>
47 #include <sys/socket.h>
52 void progressmarker (int type
)
54 static int outmarkpos
=0;
59 fprintf (out
, "."); /* normal */
62 fprintf (out
, "<"); /* start fragment */
66 fprintf (out
, "+"); /* middle fragment */
70 fprintf (out
, ">"); /* end fragment */
74 fprintf (stdout
, "b"); /* setup header */
78 fprintf (stdout
, "p"); /* packed */
82 fprintf (stdout
, "c"); /* info header */
92 if (outmarkpos
== 70) {
101 int createsocket (xiph_rtp_t
*xr
, char *addr
, unsigned int port
,
106 struct sockaddr_in sin
;
107 rtp_headers_t
*headers
= &xr
->headers
;
109 /* Init RTP headers */
111 /* Sets v=2, p=0, x=0, cc=0 */
112 headers
-> flags1
= 0x80;
114 /* Sets m=0, pt=96 */
115 headers
-> flags2
= 0x60;
117 headers
-> sequence
= htonl (rand () & 65535);
118 headers
-> timestamp
= htonl (rand ());
119 headers
-> ssrc
= htonl (rand ());
123 xr
->socket
= socket(AF_INET
, SOCK_DGRAM
, 0);
125 if (xr
->socket
< 0) {
126 fprintf (stderr
, "Socket creation failed.\n");
130 xr
->rtpsock
.sin_family
= sin
.sin_family
= AF_INET
;
131 xr
->rtpsock
.sin_port
= sin
.sin_port
= htons (port
);
132 xr
->rtpsock
.sin_addr
.s_addr
= inet_addr (addr
);
134 ret
= setsockopt (xr
->socket
, SOL_SOCKET
, SO_REUSEADDR
, &optval
, sizeof (int));
137 fprintf (stderr
, "setsockopt SO_REUSEADDR error\n");
141 /* Set multicast parameters */
143 if (IN_MULTICAST (ntohl (xr
->rtpsock
.sin_addr
.s_addr
))) {
145 ret
= setsockopt (xr
->socket
, IPPROTO_IP
, IP_MULTICAST_TTL
, &TTL
, sizeof (char));
148 fprintf (stderr
, "Multicast setsockopt TTL failed.\n");
154 ret
= setsockopt (xr
->socket
, IPPROTO_IP
, IP_MULTICAST_LOOP
, &optval
, sizeof (char));
157 fprintf (stderr
, "Multicast setsockopt LOOP failed.\n");
165 int sendrtp (xiph_rtp_t
*xr
, const void *data
, int len
)
171 fprintf(stderr
,"sent %d bytes\n",len
);
173 outbuffer
= malloc (sizeof (rtp_headers_t
) + len
);
175 memcpy (outbuffer
, &xr
->headers
, sizeof (rtp_headers_t
));
176 memcpy (outbuffer
+ sizeof (rtp_headers_t
), data
, len
);
178 ret
= sendto (xr
->socket
, outbuffer
, sizeof (rtp_headers_t
) + len
,
179 0, (struct sockaddr
*) &xr
->rtpsock
,
180 sizeof (struct sockaddr_in
));
187 static void flush_stack (xiph_rtp_t
*xr
, long timestamp
, long sleeptime
)
189 framestack_t
*fs
= &xr
->fs
;
190 unsigned char *packet
;
192 if ( fs
->stackcount
)
194 /* Set Vorbis header flags */
195 xr
->bitfield
.frag_type
= 0;
196 xr
->bitfield
.data_type
= 0;
197 xr
->bitfield
.pkts
= fs
->stackcount
;
199 packet
= malloc (fs
->stacksize
+ 4);
201 makeheader (xr
, packet
, fs
->stacksize
+ 4);
202 memcpy (packet
+ 4, fs
->framestack
, fs
->stacksize
);
204 /* Swap RTP headers from host to network order */
205 xr
->headers
.sequence
= htons (xr
->headers
.sequence
);
206 xr
->headers
.timestamp
= htonl (xr
->headers
.timestamp
);
208 sendrtp (xr
, packet
, fs
->stacksize
+ 4);
210 /* Swap headers back to host order */
211 xr
->headers
.sequence
= ntohs (xr
->headers
.sequence
);
212 xr
->headers
.timestamp
= ntohl (xr
->headers
.timestamp
);
214 if (fs
->stackcount
== 1)
221 xr
->headers
.sequence
++;
222 xr
->headers
.timestamp
+= timestamp
;
231 static void stack_packet(xiph_rtp_t
*xr
, unsigned char* vorbdata
, int length
,
234 framestack_t
*fs
= &xr
->fs
;
237 realloc (fs
->framestack
, (fs
->stacksize
+ (length
+ 2)));
238 fs
->framestack
[fs
->stacksize
++]= (length
&0xff00)>>8;
239 fs
->framestack
[fs
->stacksize
++]= length
&0xff;
241 memcpy (fs
->framestack
+ (fs
->stacksize
), vorbdata
, length
);
244 fs
->stacksize
+= length
;
245 xr
->headers
.timestamp
+= timestamp
;
249 //FIXME max_payload should stay somewhere else
250 void creatertp (xiph_rtp_t
*xr
, unsigned char* vorbdata
, int length
,
251 long timestamp
, long sleeptime
, int type
, int last
)
253 int frag
, position
= 0;
254 unsigned short framesize
;
255 unsigned char *packet
;
256 framestack_t
*fs
= &xr
->fs
;
257 const unsigned int max_payload
= 1000;
261 // flush any other packet in queue (chained ogg!)
262 flush_stack(xr
, timestamp
, sleeptime
);
263 sleeptime
= 300; // ((1 / (float) bitrate) * 1000000);
266 /* Frame packing. Used only for type 0 packets (raw Vorbis data) */
268 if ((length
<= max_payload
&& type
== 0 ) || fs
->stacksize
) {
270 if (length
+ fs
->stacksize
<= max_payload
271 && fs
->stackcount
< 15)
273 stack_packet(xr
, vorbdata
, length
, timestamp
);
276 else if (length
+ fs
->stacksize
> max_payload
277 || fs
->stackcount
>= 15)
279 flush_stack(xr
, timestamp
, sleeptime
);
281 if (length
<= max_payload
)
282 stack_packet(xr
, vorbdata
, length
, timestamp
);
285 flush_stack(xr
, timestamp
, sleeptime
);
289 /* Send header packets (under max_payload octets) - No Packing */
291 else if (length
< max_payload
) {
293 /* Set Vorbis header flags */
294 xr
->bitfield
.frag_type
= 0;
295 xr
->bitfield
.data_type
= type
;
296 xr
->bitfield
.pkts
= 1;
298 framesize
= (unsigned char) length
;
300 packet
= malloc (length
+ 4 + 2);
302 makeheader (xr
, packet
, length
+ 4 + 2);
304 packet
[4]=(length
&0xff00)>>8;
305 packet
[5]=length
&0xff;
307 memcpy (packet
+ 4 + 2, vorbdata
, length
);
309 /* Swap RTP headers from host to network order */
310 xr
->headers
.sequence
= htons (xr
->headers
.sequence
);
311 xr
->headers
.timestamp
= htonl (xr
->headers
.timestamp
);
313 sendrtp (xr
, packet
, length
+ 4 + 2);
315 /* Swap headers back to host order */
316 xr
->headers
.sequence
= htons (xr
->headers
.sequence
);
317 xr
->headers
.timestamp
= ntohl (xr
->headers
.timestamp
);
319 /* We need to sleep enough time to not overflow
320 * the playout buffer nor starve it */
323 xr
->headers
.sequence
++;
324 xr
->headers
.timestamp
+= timestamp
;
329 /* Frame fragmentation */
331 if (length
> max_payload
) {
333 while (length
> max_payload
) {
334 /* Set Vorbis header flags */
335 xr
->bitfield
.frag_type
= frag
;
336 xr
->bitfield
.data_type
= type
;
337 xr
->bitfield
.pkts
= 0;
339 framesize
= max_payload
;
341 packet
= malloc (framesize
+ 4 + 2);
343 makeheader (xr
, packet
, framesize
+ 2 + 4);
344 /* write 16-bit network order fragment length */
345 packet
[4]=(framesize
&0xff00)>>8;
346 packet
[5]=framesize
&0xff;
347 memcpy (packet
+ 4 + 2, vorbdata
+ position
, framesize
);
349 /* Swap RTP headers from host to network order */
350 xr
->headers
.sequence
= htons (xr
->headers
.sequence
);
352 sendrtp (xr
, packet
, framesize
+ 4 + 2);
354 /* Swap headers back to host order */
355 xr
->headers
.sequence
= ntohs (xr
->headers
.sequence
);
357 length
-= max_payload
;
358 position
+= max_payload
;
361 xr
->headers
.sequence
= xr
->headers
.sequence
+ 1;
368 /* Set Vorbis header flags */
369 xr
->bitfield
.frag_type
= 3;
370 xr
->bitfield
.data_type
= type
;
371 xr
->bitfield
.pkts
= 0;
375 packet
= malloc (length
+ 4 + 2);
377 makeheader (xr
, packet
, length
+ 4 + 2);
378 packet
[4]=(framesize
&0xff00)>>8;
379 packet
[5]=framesize
&0xff;
380 memcpy (packet
+ 4 + 2, vorbdata
+ position
, length
);
382 /* Swap RTP headers from host to network order */
383 xr
->headers
.sequence
= htons (xr
->headers
.sequence
);
384 xr
->headers
.timestamp
= htonl (xr
->headers
.timestamp
);
386 sendrtp (xr
, packet
, length
+ 4 + 2);
388 /* Swap headers back to host order */
389 xr
->headers
.sequence
= htons (xr
->headers
.sequence
);
390 xr
->headers
.timestamp
= ntohl (xr
->headers
.timestamp
);
392 /* Increment RTP headers */
393 xr
->headers
.sequence
++;
394 xr
->headers
.timestamp
+= timestamp
;
403 int makeheader (xiph_rtp_t
*xr
, unsigned char *packet
, int length
)
405 if (xr
->codec
== 3) return 0; //Speex has no header
407 /* Vorbis and Theora header */
408 if (length
< sizeof(header_bitfield_t
)) return -1;
410 printf( "ident %06x, frag type %d,"
411 " data type %d, pkts %02d, size %d\n", xr
->bitfield
.cbident
,
412 xr
->bitfield
.frag_type
, xr
->bitfield
.data_type
,
413 xr
->bitfield
.pkts
, length
);
415 packet
[0] = (xr
->bitfield
.cbident
&0xff0000)>>16;
416 packet
[1] = (xr
->bitfield
.cbident
&0xff00)>>8;
417 packet
[2] = xr
->bitfield
.cbident
&0xff;
419 packet
[3] = (xr
->bitfield
.frag_type
) << 6;
420 packet
[3] |= (xr
->bitfield
.data_type
) << 4;
421 packet
[3] |= (xr
->bitfield
.pkts
) & 0xf;
427 int ogg_copy_packet(ogg_packet
*dst
, ogg_packet
*src
)
430 dst
->packet
= malloc(src
->bytes
);
431 memcpy(dst
->packet
, src
->packet
, src
->bytes
);
432 dst
->bytes
= src
->bytes
;
433 dst
->b_o_s
= src
->b_o_s
;
434 dst
->e_o_s
= src
->e_o_s
;
436 dst
->granulepos
= src
->granulepos
;
437 dst
->packetno
= src
->packetno
;
440 printf("- bytes %ld bos %ld eos %ld gp %lld pno %lld\n",
441 dst
->bytes
, dst
->b_o_s
, dst
->e_o_s
, dst
->granulepos
, dst
->packetno
);