]> git.sesse.net Git - vlc/blob - modules/access/rtsp/real_rmff.c
FSF address change.
[vlc] / modules / access / rtsp / real_rmff.c
1 /*
2  * Copyright (C) 2002-2003 the xine project
3  *
4  * This file is part of xine, a free video player.
5  *
6  * xine is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * xine is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA
19  *
20  * $Id$
21  *
22  * functions for real media file format
23  * adopted from joschkas real tools
24  */
25
26 #include "real.h"
27
28 #define BE_16(x)  ((((uint8_t*)(x))[0] << 8) | ((uint8_t*)(x))[1])
29 #define BE_32(x)  ((((uint8_t*)(x))[0] << 24) | \
30                    (((uint8_t*)(x))[1] << 16) | \
31                    (((uint8_t*)(x))[2] << 8) | \
32                     ((uint8_t*)(x))[3])
33
34 /*
35  * writes header data to a buffer
36  */
37
38 static void rmff_dump_fileheader(rmff_fileheader_t *fileheader, char *buffer) {
39
40   if (!fileheader) return;
41   fileheader->object_id=BE_32(&fileheader->object_id);
42   fileheader->size=BE_32(&fileheader->size);
43   fileheader->object_version=BE_16(&fileheader->object_version);
44   fileheader->file_version=BE_32(&fileheader->file_version);
45   fileheader->num_headers=BE_32(&fileheader->num_headers);
46
47   memcpy(buffer, fileheader, 8);
48   memcpy(&buffer[8], &fileheader->object_version, 2);
49   memcpy(&buffer[10], &fileheader->file_version, 8);
50
51   fileheader->size=BE_32(&fileheader->size);
52   fileheader->object_version=BE_16(&fileheader->object_version);
53   fileheader->file_version=BE_32(&fileheader->file_version);
54   fileheader->num_headers=BE_32(&fileheader->num_headers);
55   fileheader->object_id=BE_32(&fileheader->object_id);
56 }
57
58 static void rmff_dump_prop(rmff_prop_t *prop, char *buffer) {
59
60   if (!prop) return;
61   prop->object_id=BE_32(&prop->object_id);
62   prop->size=BE_32(&prop->size);
63   prop->object_version=BE_16(&prop->object_version);
64   prop->max_bit_rate=BE_32(&prop->max_bit_rate);
65   prop->avg_bit_rate=BE_32(&prop->avg_bit_rate);
66   prop->max_packet_size=BE_32(&prop->max_packet_size);
67   prop->avg_packet_size=BE_32(&prop->avg_packet_size);
68   prop->num_packets=BE_32(&prop->num_packets);
69   prop->duration=BE_32(&prop->duration);
70   prop->preroll=BE_32(&prop->preroll);
71   prop->index_offset=BE_32(&prop->index_offset);
72   prop->data_offset=BE_32(&prop->data_offset);
73   prop->num_streams=BE_16(&prop->num_streams);
74   prop->flags=BE_16(&prop->flags);
75
76   memcpy(buffer, prop, 8);
77   memcpy(&buffer[8], &prop->object_version, 2);
78   memcpy(&buffer[10], &prop->max_bit_rate, 36);
79   memcpy(&buffer[46], &prop->num_streams, 2);
80   memcpy(&buffer[48], &prop->flags, 2);
81
82   prop->size=BE_32(&prop->size);
83   prop->object_version=BE_16(&prop->object_version);
84   prop->max_bit_rate=BE_32(&prop->max_bit_rate);
85   prop->avg_bit_rate=BE_32(&prop->avg_bit_rate);
86   prop->max_packet_size=BE_32(&prop->max_packet_size);
87   prop->avg_packet_size=BE_32(&prop->avg_packet_size);
88   prop->num_packets=BE_32(&prop->num_packets);
89   prop->duration=BE_32(&prop->duration);
90   prop->preroll=BE_32(&prop->preroll);
91   prop->index_offset=BE_32(&prop->index_offset);
92   prop->data_offset=BE_32(&prop->data_offset);
93   prop->num_streams=BE_16(&prop->num_streams);
94   prop->flags=BE_16(&prop->flags);
95   prop->object_id=BE_32(&prop->object_id);
96 }
97
98 static void rmff_dump_mdpr(rmff_mdpr_t *mdpr, char *buffer) {
99
100   int s1, s2, s3;
101
102   if (!mdpr) return;
103   mdpr->object_id=BE_32(&mdpr->object_id);
104   mdpr->size=BE_32(&mdpr->size);
105   mdpr->object_version=BE_16(&mdpr->object_version);
106   mdpr->stream_number=BE_16(&mdpr->stream_number);
107   mdpr->max_bit_rate=BE_32(&mdpr->max_bit_rate);
108   mdpr->avg_bit_rate=BE_32(&mdpr->avg_bit_rate);
109   mdpr->max_packet_size=BE_32(&mdpr->max_packet_size);
110   mdpr->avg_packet_size=BE_32(&mdpr->avg_packet_size);
111   mdpr->start_time=BE_32(&mdpr->start_time);
112   mdpr->preroll=BE_32(&mdpr->preroll);
113   mdpr->duration=BE_32(&mdpr->duration);
114
115   memcpy(buffer, mdpr, 8);
116   memcpy(&buffer[8], &mdpr->object_version, 2);
117   memcpy(&buffer[10], &mdpr->stream_number, 2);
118   memcpy(&buffer[12], &mdpr->max_bit_rate, 28);
119   memcpy(&buffer[40], &mdpr->stream_name_size, 1);
120   s1=mdpr->stream_name_size;
121   memcpy(&buffer[41], mdpr->stream_name, s1);
122
123   memcpy(&buffer[41+s1], &mdpr->mime_type_size, 1);
124   s2=mdpr->mime_type_size;
125   memcpy(&buffer[42+s1], mdpr->mime_type, s2);
126
127   mdpr->type_specific_len=BE_32(&mdpr->type_specific_len);
128   memcpy(&buffer[42+s1+s2], &mdpr->type_specific_len, 4);
129   mdpr->type_specific_len=BE_32(&mdpr->type_specific_len);
130   s3=mdpr->type_specific_len;
131   memcpy(&buffer[46+s1+s2], mdpr->type_specific_data, s3);
132
133   mdpr->size=BE_32(&mdpr->size);
134   mdpr->stream_number=BE_16(&mdpr->stream_number);
135   mdpr->max_bit_rate=BE_32(&mdpr->max_bit_rate);
136   mdpr->avg_bit_rate=BE_32(&mdpr->avg_bit_rate);
137   mdpr->max_packet_size=BE_32(&mdpr->max_packet_size);
138   mdpr->avg_packet_size=BE_32(&mdpr->avg_packet_size);
139   mdpr->start_time=BE_32(&mdpr->start_time);
140   mdpr->preroll=BE_32(&mdpr->preroll);
141   mdpr->duration=BE_32(&mdpr->duration);
142   mdpr->object_id=BE_32(&mdpr->object_id);
143
144 }
145
146 static void rmff_dump_cont(rmff_cont_t *cont, char *buffer) {
147
148   int p;
149
150   if (!cont) return;
151   cont->object_id=BE_32(&cont->object_id);
152   cont->size=BE_32(&cont->size);
153   cont->object_version=BE_16(&cont->object_version);
154
155   memcpy(buffer, cont, 8);
156   memcpy(&buffer[8], &cont->object_version, 2);
157
158   cont->title_len=BE_16(&cont->title_len);
159   memcpy(&buffer[10], &cont->title_len, 2);
160   cont->title_len=BE_16(&cont->title_len);
161   memcpy(&buffer[12], cont->title, cont->title_len);
162   p=12+cont->title_len;
163
164   cont->author_len=BE_16(&cont->author_len);
165   memcpy(&buffer[p], &cont->author_len, 2);
166   cont->author_len=BE_16(&cont->author_len);
167   memcpy(&buffer[p+2], cont->author, cont->author_len);
168   p+=2+cont->author_len;
169
170   cont->copyright_len=BE_16(&cont->copyright_len);
171   memcpy(&buffer[p], &cont->copyright_len, 2);
172   cont->copyright_len=BE_16(&cont->copyright_len);
173   memcpy(&buffer[p+2], cont->copyright, cont->copyright_len);
174   p+=2+cont->copyright_len;
175
176   cont->comment_len=BE_16(&cont->comment_len);
177   memcpy(&buffer[p], &cont->comment_len, 2);
178   cont->comment_len=BE_16(&cont->comment_len);
179   memcpy(&buffer[p+2], cont->comment, cont->comment_len);
180
181   cont->size=BE_32(&cont->size);
182   cont->object_version=BE_16(&cont->object_version);
183   cont->object_id=BE_32(&cont->object_id);
184 }
185
186 static void rmff_dump_dataheader(rmff_data_t *data, char *buffer) {
187
188   if (!data) return;
189
190   data->object_id=BE_32(&data->object_id);
191   data->size=BE_32(&data->size);
192   data->object_version=BE_16(&data->object_version);
193   data->num_packets=BE_32(&data->num_packets);
194   data->next_data_header=BE_32(&data->next_data_header);
195
196   memcpy(buffer, data, 8);
197   memcpy(&buffer[8], &data->object_version, 2);
198   memcpy(&buffer[10], &data->num_packets, 8);
199
200   data->num_packets=BE_32(&data->num_packets);
201   data->next_data_header=BE_32(&data->next_data_header);
202   data->size=BE_32(&data->size);
203   data->object_version=BE_16(&data->object_version);
204   data->object_id=BE_32(&data->object_id);
205 }
206
207 int rmff_dump_header(rmff_header_t *h, char *buffer, int max) {
208
209   int written=0;
210   rmff_mdpr_t **stream=h->streams;
211
212   rmff_dump_fileheader(h->fileheader, &buffer[written]);
213   written+=h->fileheader->size;
214   rmff_dump_prop(h->prop, &buffer[written]);
215   written+=h->prop->size;
216   rmff_dump_cont(h->cont, &buffer[written]);
217   written+=h->cont->size;
218   if (stream)
219   {
220     while(*stream)
221     {
222       rmff_dump_mdpr(*stream, &buffer[written]);
223       written+=(*stream)->size;
224       stream++;
225     }
226   }
227
228   rmff_dump_dataheader(h->data, &buffer[written]);
229   written+=18;
230
231   return written;
232 }
233
234 void rmff_dump_pheader(rmff_pheader_t *h, char *data) {
235
236   data[0]=(h->object_version>>8) & 0xff;
237   data[1]=h->object_version & 0xff;
238   data[2]=(h->length>>8) & 0xff;
239   data[3]=h->length & 0xff;
240   data[4]=(h->stream_number>>8) & 0xff;
241   data[5]=h->stream_number & 0xff;
242   data[6]=(h->timestamp>>24) & 0xff;
243   data[7]=(h->timestamp>>16) & 0xff;
244   data[8]=(h->timestamp>>8) & 0xff;
245   data[9]=h->timestamp & 0xff;
246   data[10]=h->reserved;
247   data[11]=h->flags;
248 }
249
250 rmff_fileheader_t *rmff_new_fileheader(uint32_t num_headers) {
251
252   rmff_fileheader_t *fileheader = malloc(sizeof(rmff_fileheader_t));
253   if( !fileheader ) return NULL;
254
255   memset(fileheader, 0, sizeof(rmff_fileheader_t));
256   fileheader->object_id=RMF_TAG;
257   fileheader->size=18;
258   fileheader->object_version=0;
259   fileheader->file_version=0;
260   fileheader->num_headers=num_headers;
261
262   return fileheader;
263 }
264
265 rmff_prop_t *rmff_new_prop (
266   uint32_t max_bit_rate,
267   uint32_t avg_bit_rate,
268   uint32_t max_packet_size,
269   uint32_t avg_packet_size,
270   uint32_t num_packets,
271   uint32_t duration,
272   uint32_t preroll,
273   uint32_t index_offset,
274   uint32_t data_offset,
275   uint16_t num_streams,
276   uint16_t flags ) {
277
278   rmff_prop_t *prop = malloc(sizeof(rmff_prop_t));
279   if( !prop ) return NULL;
280
281   memset(prop, 0, sizeof(rmff_prop_t));
282   prop->object_id=PROP_TAG;
283   prop->size=50;
284   prop->object_version=0;
285   prop->max_bit_rate=max_bit_rate;
286   prop->avg_bit_rate=avg_bit_rate;
287   prop->max_packet_size=max_packet_size;
288   prop->avg_packet_size=avg_packet_size;
289   prop->num_packets=num_packets;
290   prop->duration=duration;
291   prop->preroll=preroll;
292   prop->index_offset=index_offset;
293   prop->data_offset=data_offset;
294   prop->num_streams=num_streams;
295   prop->flags=flags;
296
297   return prop;
298 }
299
300 rmff_mdpr_t *rmff_new_mdpr(
301   uint16_t   stream_number,
302   uint32_t   max_bit_rate,
303   uint32_t   avg_bit_rate,
304   uint32_t   max_packet_size,
305   uint32_t   avg_packet_size,
306   uint32_t   start_time,
307   uint32_t   preroll,
308   uint32_t   duration,
309   const char *stream_name,
310   const char *mime_type,
311   uint32_t   type_specific_len,
312   const char *type_specific_data ) {
313
314   rmff_mdpr_t *mdpr = malloc(sizeof(rmff_mdpr_t));
315   if( !mdpr ) return NULL;
316
317   memset(mdpr, 0, sizeof(rmff_mdpr_t));
318   mdpr->object_id=MDPR_TAG;
319   mdpr->object_version=0;
320   mdpr->stream_number=stream_number;
321   mdpr->max_bit_rate=max_bit_rate;
322   mdpr->avg_bit_rate=avg_bit_rate;
323   mdpr->max_packet_size=max_packet_size;
324   mdpr->avg_packet_size=avg_packet_size;
325   mdpr->start_time=start_time;
326   mdpr->preroll=preroll;
327   mdpr->duration=duration;
328   mdpr->stream_name_size=0;
329   if (stream_name) {
330     mdpr->stream_name=strdup(stream_name);
331     mdpr->stream_name_size=strlen(stream_name);
332   }
333   mdpr->mime_type_size=0;
334   if (mime_type) {
335     mdpr->mime_type=strdup(mime_type);
336     mdpr->mime_type_size=strlen(mime_type);
337   }
338   mdpr->type_specific_len=type_specific_len;
339
340   mdpr->type_specific_data = malloc(sizeof(char)*type_specific_len);
341   if( !mdpr->type_specific_data ) {
342     if( mdpr->stream_name ) free( mdpr->stream_name );
343     free( mdpr );
344     return NULL;
345   }
346   memcpy(mdpr->type_specific_data,type_specific_data,type_specific_len);
347   mdpr->mlti_data=NULL;
348   mdpr->size=mdpr->stream_name_size+mdpr->mime_type_size+mdpr->type_specific_len+46;
349   return mdpr;
350 }
351
352 rmff_cont_t *rmff_new_cont(const char *title, const char *author, const char *copyright, const char *comment) {
353
354   rmff_cont_t *cont = malloc(sizeof(rmff_cont_t));
355   if( !cont ) return NULL;
356
357   memset(cont, 0, sizeof(rmff_cont_t));
358   cont->object_id=CONT_TAG;
359   cont->object_version=0;
360   cont->title=NULL;
361   cont->author=NULL;
362   cont->copyright=NULL;
363   cont->comment=NULL;
364   cont->title_len=0;
365   cont->author_len=0;
366   cont->copyright_len=0;
367   cont->comment_len=0;
368
369   if (title) {
370     cont->title_len=strlen(title);
371     cont->title=strdup(title);
372   }
373   if (author)
374   {
375     cont->author_len=strlen(author);
376     cont->author=strdup(author);
377   }
378   if (copyright) {
379     cont->copyright_len=strlen(copyright);
380     cont->copyright=strdup(copyright);
381   }
382   if (comment) {
383     cont->comment_len=strlen(comment);
384     cont->comment=strdup(comment);
385   }
386   cont->size=cont->title_len+cont->author_len+cont->copyright_len+cont->comment_len+18;
387   return cont;
388 }
389
390 rmff_data_t *rmff_new_dataheader(uint32_t num_packets, uint32_t next_data_header) {
391   rmff_data_t *data = malloc(sizeof(rmff_data_t));
392   if( !data ) return NULL;
393
394   memset(data, 0, sizeof(rmff_data_t));
395   data->object_id=DATA_TAG;
396   data->size=18;
397   data->object_version=0;
398   data->num_packets=num_packets;
399   data->next_data_header=next_data_header;
400
401   return data;
402 }
403
404 void rmff_print_header(rmff_header_t *h) {
405   rmff_mdpr_t **stream;
406
407   if(!h) {
408     printf("rmff_print_header: NULL given\n");
409     return;
410   }
411   if(h->fileheader) {
412     printf("\nFILE:\n");
413     printf("file version      : %d\n", h->fileheader->file_version);
414     printf("number of headers : %d\n", h->fileheader->num_headers);
415   }
416   if(h->cont) {
417     printf("\nCONTENT:\n");
418     printf("title     : %s\n", h->cont->title);
419     printf("author    : %s\n", h->cont->author);
420     printf("copyright : %s\n", h->cont->copyright);
421     printf("comment   : %s\n", h->cont->comment);
422   }
423   if(h->prop) {
424     printf("\nSTREAM PROPERTIES:\n");
425     printf("bit rate (max/avg)    : %i/%i\n", h->prop->max_bit_rate, h->prop->avg_bit_rate);
426     printf("packet size (max/avg) : %i/%i bytes\n", h->prop->max_packet_size, h->prop->avg_packet_size);
427     printf("packets       : %i\n", h->prop->num_packets);
428     printf("duration      : %i ms\n", h->prop->duration);
429     printf("pre-buffer    : %i ms\n", h->prop->preroll);
430     printf("index offset  : %i bytes\n", h->prop->index_offset);
431     printf("data offset   : %i bytes\n", h->prop->data_offset);
432     printf("media streams : %i\n", h->prop->num_streams);
433     printf("flags         : ");
434     if (h->prop->flags & PN_SAVE_ENABLED) printf("save_enabled ");
435     if (h->prop->flags & PN_PERFECT_PLAY_ENABLED) printf("perfect_play_enabled ");
436     if (h->prop->flags & PN_LIVE_BROADCAST) printf("live_broadcast ");
437     printf("\n");
438   }
439   stream=h->streams;
440   if(stream) {
441     while (*stream) {
442       printf("\nSTREAM %i:\n", (*stream)->stream_number);
443       printf("stream name [mime type] : %s [%s]\n", (*stream)->stream_name, (*stream)->mime_type);
444       printf("bit rate (max/avg)      : %i/%i\n", (*stream)->max_bit_rate, (*stream)->avg_bit_rate);
445       printf("packet size (max/avg)   : %i/%i bytes\n", (*stream)->max_packet_size, (*stream)->avg_packet_size);
446       printf("start time : %i\n", (*stream)->start_time);
447       printf("pre-buffer : %i ms\n", (*stream)->preroll);
448       printf("duration   : %i ms\n", (*stream)->duration);
449       printf("type specific data:\n");
450       stream++;
451     }
452   }
453   if(h->data) {
454     printf("\nDATA:\n");
455     printf("size      : %i\n", h->data->size);
456     printf("packets   : %i\n", h->data->num_packets);
457     printf("next DATA : 0x%08x\n", h->data->next_data_header);
458   }
459 }
460
461 void rmff_fix_header(rmff_header_t *h) {
462
463   unsigned int num_headers=0;
464   unsigned int header_size=0;
465   rmff_mdpr_t **streams;
466   int num_streams=0;
467
468   if (!h) {
469     lprintf("rmff_fix_header: fatal: no header given.\n");
470     return;
471   }
472   if (!h->streams) {
473     lprintf("rmff_fix_header: warning: no MDPR chunks\n");
474   } else {
475     streams=h->streams;
476     while (*streams) {
477         num_streams++;
478         num_headers++;
479         header_size+=(*streams)->size;
480         streams++;
481     }
482   }
483   if (h->prop) {
484     if (h->prop->size != 50) {
485       lprintf("rmff_fix_header: correcting prop.size from %i to %i\n", h->prop->size, 50);
486       h->prop->size=50;
487     }
488     if (h->prop->num_streams != num_streams) {
489       lprintf("rmff_fix_header: correcting prop.num_streams from %i to %i\n", h->prop->num_streams, num_streams);
490       h->prop->num_streams=num_streams;
491     }
492     num_headers++;
493     header_size+=50;
494   } else lprintf("rmff_fix_header: warning: no PROP chunk.\n");
495
496   if (h->cont) {
497     num_headers++;
498     header_size+=h->cont->size;
499   } else lprintf("rmff_fix_header: warning: no CONT chunk.\n");
500
501   if (!h->data) {
502     lprintf("rmff_fix_header: no DATA chunk, creating one\n");
503     h->data = malloc(sizeof(rmff_data_t));
504     if( h->data ) {
505       memset(h->data, 0, sizeof(rmff_data_t));
506       h->data->object_id=DATA_TAG;
507       h->data->object_version=0;
508       h->data->size=18;
509       h->data->num_packets=0;
510       h->data->next_data_header=0;
511     }
512   }
513   num_headers++;
514
515   if (!h->fileheader) {
516     lprintf("rmff_fix_header: no fileheader, creating one");
517     h->fileheader = malloc(sizeof(rmff_fileheader_t));
518     if( h->fileheader ) {
519       memset(h->fileheader, 0, sizeof(rmff_fileheader_t));
520       h->fileheader->object_id=RMF_TAG;
521       h->fileheader->size=18;
522       h->fileheader->object_version=0;
523       h->fileheader->file_version=0;
524       h->fileheader->num_headers=num_headers+1;
525     }
526   }
527   header_size+=h->fileheader->size;
528   num_headers++;
529
530   if(h->fileheader->num_headers != num_headers) {
531     lprintf("rmff_fix_header: setting num_headers from %i to %i\n", h->fileheader->num_headers, num_headers);
532     h->fileheader->num_headers=num_headers;
533   }
534   if(h->prop) {
535     if (h->prop->data_offset != header_size) {
536       lprintf("rmff_fix_header: setting prop.data_offset from %i to %i\n", h->prop->data_offset, header_size);
537       h->prop->data_offset=header_size;
538     }
539
540     /* FIXME: I doubt this is right to do this here.
541      * It should belong to the demux. */
542     if (h->prop->num_packets == 0) {
543       int p=(int)(h->prop->avg_bit_rate/8.0*(h->prop->duration/1000.0)/h->prop->avg_packet_size);
544       lprintf("rmff_fix_header: assuming prop.num_packets=%i\n", p);
545       h->prop->num_packets=p;
546     }
547     if (h->data->num_packets == 0) {
548       lprintf("rmff_fix_header: assuming data.num_packets=%i\n", h->prop->num_packets);
549       h->data->num_packets=h->prop->num_packets;
550     }
551     if (h->data->size == 18 || !h->data->size ) {
552       lprintf("rmff_fix_header: assuming data.size=%i\n", h->prop->num_packets*h->prop->avg_packet_size);
553       h->data->size+=h->prop->num_packets*h->prop->avg_packet_size;
554     }
555   }
556 }
557
558 int rmff_get_header_size(rmff_header_t *h) {
559   if (!h) return 0;
560   if (!h->prop) return -1;
561   return h->prop->data_offset+18;
562 }
563
564 void rmff_free_header(rmff_header_t *h)
565 {
566   if (!h) return;
567
568   if (h->fileheader) free(h->fileheader);
569   if (h->prop) free(h->prop);
570   if (h->data) free(h->data);
571   if (h->cont) {
572     free(h->cont->title);
573     free(h->cont->author);
574     free(h->cont->copyright);
575     free(h->cont->comment);
576     free(h->cont);
577   }
578   if (h->streams) {
579     rmff_mdpr_t **s=h->streams;
580
581     while(*s) {
582       free((*s)->stream_name);
583       free((*s)->mime_type);
584       free((*s)->type_specific_data);
585       free(*s);
586       s++;
587     }
588     free(h->streams);
589   }
590   free(h);
591 }