2 File: Vorbis RTP Server
3 Authors: Phil Kerr, Luca Barbato
7 Copyright (c) 2006, Fluendo / Xiph.Org
9 Redistribution and use in source and binary forms, with or without
10 modification, are permitted provided that the following conditions are met:
12 * Redistributions of source code must retain the above copyright notice,
13 this list of conditions and the following disclaimer.
15 * Redistributions in binary form must reproduce the above copyright notice,
16 this list of conditions and the following disclaimer in the documentation
17 and/or other materials provided with the distribution.
19 * Neither the name of the Xiph.Org nor the names of its contributors may
20 be used to endorse or promote products derived from this software without
21 specific prior written permission.
23 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
25 TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
26 PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
27 BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
28 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
29 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
30 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
31 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
32 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
33 THE POSSIBILITY OF SUCH DAMAGE.
47 #include <theora/theora.h>
49 /* Network includes */
51 #include <arpa/inet.h>
52 #include <netinet/in.h>
54 #include <sys/types.h>
55 #include <sys/socket.h>
63 #define BUFFER_SIZE 4096
64 unsigned int cfg_parse( xiph_rtp_t
*xr
)
68 oggpackB_readinit(&opb
,xr
->header
[0].packet
, xr
->header
[0].bytes
);
70 oggpackB_read(&opb
,8*7); // 0x80"theora"
71 oggpackB_read(&opb
,8*3); // version
72 oggpackB_read(&opb
,16); //w
73 oggpackB_read(&opb
,16); //h
75 oggpackB_read(&opb
,64);
77 oggpackB_read(&opb
,32);
78 oggpackB_read(&opb
,32);
80 oggpackB_read(&opb
,24);
81 oggpackB_read(&opb
,24);
83 oggpackB_read(&opb
,38);
85 xr
->gp_shift
= oggpackB_read(&opb
,5);
87 printf("gp_shift %d \n", xr
->gp_shift
);
92 int main (int argc
, char **argv
)
102 ogg_sync_init (&xr
.oy
);
107 char *ip
= "227.0.0.1";
108 unsigned int port
= 4044;
109 unsigned int ttl
= 1;
112 fprintf (stderr
, "Theora RTP Server (draft-barbato-avt-rtp-theora-00)\n");
113 memset (&xr
,0,sizeof(xiph_rtp_t
));
115 /* Command-line args processing */
118 fprintf (stderr
, "\n\tNo Theora file specified.\n");
119 fprintf (stderr
, "\tUsage: %s [-i ip address] [-p port] [-t ttl] filename\n\n",argv
[0]);
123 while ((opt
= getopt (argc
, argv
, "i:p:t:")) != -1) {
134 port
= atoi (optarg
);
144 fprintf (stderr
, "\n Unknown option `-%c'.\n", optopt
);
145 fprintf (stderr
, "\tUsage: %s [-i ip address] [-p port] [-t ttl] filename\n\n",argv
[0]);
150 /* Init RTP socket */
152 if ( createsocket (&xr
, ip
, port
, ttl
)<0) return 1;
154 /* Print network details */
156 fprintf (stdout
, "\n Network setup\n");
157 fprintf (stdout
, " IP Address= %s\n", ip
);
158 fprintf (stdout
, " Port = %d\n", port
);
159 fprintf (stdout
, " TTL = %d\n", ttl
);
160 fprintf (stdout
, "\n");
162 /* Open Theora file */
164 filename
= argv
[argc
- 1];
165 file
= fopen (filename
, "rb");
168 fprintf (stderr
, " Could not open file %s\n", filename
);
172 fprintf (stdout
, " Theora setup\n");
173 fprintf (stdout
, " Filename: %s\n", filename
);
177 buffer
= ogg_sync_buffer (&xr
.oy
, BUFFER_SIZE
);
179 bytes
= fread (buffer
, 1, BUFFER_SIZE
, file
);
181 ogg_sync_wrote (&xr
.oy
, bytes
);
183 if (ogg_sync_pageout (&xr
.oy
, &xr
.og
) != 1) {
184 if (bytes
< BUFFER_SIZE
) {
185 fprintf (stdout
, " Done\n");
189 fprintf (stderr
, "\n Input does not appear to be an Ogg bitstream.\n");
193 ogg_stream_init (&xr
.os
, ogg_page_serialno (&xr
.og
));
195 theora_info_init (&xr
.ti
);
196 theora_comment_init (&xr
.tc
);
198 if (ogg_stream_pagein (&xr
.os
, &xr
.og
) < 0) {
199 fprintf (stderr
, " Error reading first page of Ogg bitstream data.\n");
203 if (ogg_stream_packetout (&xr
.os
, &xr
.op
) != 1) {
204 fprintf (stderr
, " Error reading initial header packet.\n");
208 if (theora_decode_header (&xr
.ti
, &xr
.tc
, &xr
.op
) < 0) {
209 fprintf (stderr
, " This Ogg bitstream does not contain Theora video data.\n");
213 ogg_copy_packet(&(xr
.header
[i
]), &xr
.op
); //FIXME change it?
215 /*===========================================================================*/
216 /* Process comment and codebook headers */
217 /*===========================================================================*/
221 int result
= ogg_sync_pageout (&xr
.oy
, &xr
.og
);
223 if (result
== 0) break; /* Need more data */
226 ogg_stream_pagein (&xr
.os
, &xr
.og
);
229 result
= ogg_stream_packetout (&xr
.os
, &xr
.op
);
231 if (result
== 0) break;
234 fprintf (stderr
, " Corrupt secondary header. Exiting.\n");
238 theora_decode_header (&xr
.ti
, &xr
.tc
, &xr
.op
);
241 ogg_copy_packet(&(xr
.header
[i
]), &xr
.op
);
246 buffer
= ogg_sync_buffer (&xr
.oy
, BUFFER_SIZE
);
247 bytes
= fread (buffer
, 1, BUFFER_SIZE
, file
);
249 if (bytes
== 0 && i
< 2) {
250 fprintf (stderr
, "|| End of file before finding all Vorbis headers!\n");
254 ogg_sync_wrote (&xr
.oy
, bytes
);
257 xr
.bitfield
.cbident
= rand ();
259 theora_decode_init (&xr
.td
, &xr
.ti
);
261 /*===========================================================================*/
263 /*===========================================================================*/
264 fprintf(stdout
,"Theora %dx%d %.02f fps video\n"
265 "Encoded frame content is %dx%d with %dx%d offset\n",
266 xr
.ti
.width
,xr
.ti
.height
,
267 (double)xr
.ti
.fps_numerator
/xr
.ti
.fps_denominator
,
268 xr
.ti
.frame_width
, xr
.ti
.frame_height
,
269 xr
.ti
.offset_x
, xr
.ti
.offset_y
);
271 fprintf (stdout
, "Decode setup ident is 0x%06x\n", xr
.bitfield
.cbident
);
272 fprintf (stdout
, "\n");
273 fprintf (stdout
, "Processing\n");
275 /*===========================================================================*/
276 /* Send the three headers inline */
277 /*===========================================================================*/
279 int conf_bytes
= xr
.header
[0].bytes
+ xr
.header
[2].bytes
;
280 unsigned char *conf_packet
= malloc(conf_bytes
);
282 memcpy (conf_packet
, xr
.header
[0].packet
, xr
.header
[0].bytes
);
283 memcpy (conf_packet
+ xr
.header
[0].bytes
,
286 creatertp(&xr
, conf_packet
, conf_bytes
, 0, 0, 1, 0);
293 /* Read raw data and send RTP packet */
297 int result
= ogg_sync_pageout (&xr
.oy
, &xr
.og
);
299 if (result
== 0) break; /* need more data */
302 fprintf (stderr
, "\n Corrupt or missing data in bitstream; continuing....\n ");
304 ogg_stream_pagein (&xr
.os
, &xr
.og
);
307 result
= ogg_stream_packetout (&xr
.os
, &xr
.op
);
309 if (result
== 0) break; /* need more data */
312 /* no reason to complain; already complained above */
314 theora_decode_packetin(&xr
.td
,&xr
.op
);
315 if (xr
.op
.granulepos
!= -1)
316 timestamp
= (xr
.op
.granulepos
>>xr
.gp_shift
)+
317 (xr
.op
.granulepos
& ((1<<xr
.gp_shift
)-1));
324 oggpackB_readinit(&opb
,xr
.op
.packet
,xr
.op
.bytes
);
325 oggpack_read(&opb
,1); //video marker
327 type
= oggpackB_read(&opb
,1);
328 printf(" type %d stamp %ld", type
, timestamp
);
330 printf(" bytes %ld bos %ld eos %ld gp %lld pno %lld\n", xr
.op
.bytes
, xr
.op
.b_o_s
, xr
.op
.e_o_s
, xr
.op
.granulepos
, xr
.op
.packetno
);
332 //FIXME ugly as hell and probably wrong!!!!
333 creatertp ( &xr
, xr
.op
.packet
, xr
.op
.bytes
,
334 timestamp
*90000/((double)xr
.ti
.fps_numerator
/xr
.ti
.fps_denominator
), timestamp
, 0, xr
.op
.e_o_s
);
338 if (ogg_page_eos (&xr
.og
)) eos
= 1;
343 buffer
= ogg_sync_buffer (&xr
.oy
, BUFFER_SIZE
);
344 bytes
= fread (buffer
, 1, BUFFER_SIZE
, file
);
346 ogg_sync_wrote (&xr
.oy
, bytes
);
348 if (bytes
== 0) eos
= 1;
351 //FIXME make it a cleanup function!
352 ogg_packet_clear (&(xr
.header
[0]));
353 ogg_packet_clear (&(xr
.header
[1]));
354 ogg_packet_clear (&(xr
.header
[2]));
356 ogg_stream_clear (&xr
.os
);
358 theora_clear(&xr
.td
);
359 theora_comment_clear(&xr
.tc
);
360 theora_info_clear(&xr
.ti
);
362 ogg_sync_clear (&xr
.oy
);
365 fprintf (stdout
, "Done.\n");