demux: ts: only seek on pcr for current program
[vlc.git] / modules / access / rtsp / real_rmff.c
blob1ec861d1dd820007085ada47c79b4aa2faa9d20a
1 /*
2 * Copyright (C) 2002-2003 the xine project
4 * This file is part of xine, a free video player.
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.
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.
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
20 * $Id$
22 * functions for real media file format
23 * adopted from joschkas real tools
26 #include "real.h"
27 #include "real_rmff.h"
29 #include <vlc_messages.h>
31 #define BE_16(x) ((((uint8_t*)(x))[0] << 8) | ((uint8_t*)(x))[1])
32 #define BE_32(x) ((((uint8_t*)(x))[0] << 24) | \
33 (((uint8_t*)(x))[1] << 16) | \
34 (((uint8_t*)(x))[2] << 8) | \
35 ((uint8_t*)(x))[3])
38 * writes header data to a buffer
41 static int rmff_dump_fileheader(rmff_fileheader_t *fileheader, uint8_t *buffer, int bufsize) {
42 if (!fileheader) return 0;
43 if (bufsize < RMFF_FILEHEADER_SIZE)
44 return -1;
46 fileheader->object_id=BE_32(&fileheader->object_id);
47 fileheader->size=BE_32(&fileheader->size);
48 fileheader->object_version=BE_16(&fileheader->object_version);
49 fileheader->file_version=BE_32(&fileheader->file_version);
50 fileheader->num_headers=BE_32(&fileheader->num_headers);
52 memcpy(buffer, fileheader, 8);
53 memcpy(&buffer[8], &fileheader->object_version, 2);
54 memcpy(&buffer[10], &fileheader->file_version, 8);
56 fileheader->size=BE_32(&fileheader->size);
57 fileheader->object_version=BE_16(&fileheader->object_version);
58 fileheader->file_version=BE_32(&fileheader->file_version);
59 fileheader->num_headers=BE_32(&fileheader->num_headers);
60 fileheader->object_id=BE_32(&fileheader->object_id);
62 return RMFF_FILEHEADER_SIZE;
65 static int rmff_dump_prop(rmff_prop_t *prop, uint8_t *buffer, int bufsize) {
67 if (!prop) return 0;
69 if (bufsize < RMFF_PROPHEADER_SIZE)
70 return -1;
72 prop->object_id=BE_32(&prop->object_id);
73 prop->size=BE_32(&prop->size);
74 prop->object_version=BE_16(&prop->object_version);
75 prop->max_bit_rate=BE_32(&prop->max_bit_rate);
76 prop->avg_bit_rate=BE_32(&prop->avg_bit_rate);
77 prop->max_packet_size=BE_32(&prop->max_packet_size);
78 prop->avg_packet_size=BE_32(&prop->avg_packet_size);
79 prop->num_packets=BE_32(&prop->num_packets);
80 prop->duration=BE_32(&prop->duration);
81 prop->preroll=BE_32(&prop->preroll);
82 prop->index_offset=BE_32(&prop->index_offset);
83 prop->data_offset=BE_32(&prop->data_offset);
84 prop->num_streams=BE_16(&prop->num_streams);
85 prop->flags=BE_16(&prop->flags);
87 memcpy(buffer, prop, 8);
88 memcpy(&buffer[8], &prop->object_version, 2);
89 memcpy(&buffer[10], &prop->max_bit_rate, 36);
90 memcpy(&buffer[46], &prop->num_streams, 2);
91 memcpy(&buffer[48], &prop->flags, 2);
93 prop->size=BE_32(&prop->size);
94 prop->object_version=BE_16(&prop->object_version);
95 prop->max_bit_rate=BE_32(&prop->max_bit_rate);
96 prop->avg_bit_rate=BE_32(&prop->avg_bit_rate);
97 prop->max_packet_size=BE_32(&prop->max_packet_size);
98 prop->avg_packet_size=BE_32(&prop->avg_packet_size);
99 prop->num_packets=BE_32(&prop->num_packets);
100 prop->duration=BE_32(&prop->duration);
101 prop->preroll=BE_32(&prop->preroll);
102 prop->index_offset=BE_32(&prop->index_offset);
103 prop->data_offset=BE_32(&prop->data_offset);
104 prop->num_streams=BE_16(&prop->num_streams);
105 prop->flags=BE_16(&prop->flags);
106 prop->object_id=BE_32(&prop->object_id);
108 return RMFF_PROPHEADER_SIZE;
111 static int rmff_dump_mdpr(rmff_mdpr_t *mdpr, uint8_t *buffer, unsigned int bufsize) {
113 int s1, s2, s3;
115 if (!mdpr) return 0;
116 if (bufsize < RMFF_MDPRHEADER_SIZE + mdpr->type_specific_len +
117 mdpr->stream_name_size + mdpr->mime_type_size)
118 return -1;
120 mdpr->object_id=BE_32(&mdpr->object_id);
121 mdpr->size=BE_32(&mdpr->size);
122 mdpr->object_version=BE_16(&mdpr->object_version);
123 mdpr->stream_number=BE_16(&mdpr->stream_number);
124 mdpr->max_bit_rate=BE_32(&mdpr->max_bit_rate);
125 mdpr->avg_bit_rate=BE_32(&mdpr->avg_bit_rate);
126 mdpr->max_packet_size=BE_32(&mdpr->max_packet_size);
127 mdpr->avg_packet_size=BE_32(&mdpr->avg_packet_size);
128 mdpr->start_time=BE_32(&mdpr->start_time);
129 mdpr->preroll=BE_32(&mdpr->preroll);
130 mdpr->duration=BE_32(&mdpr->duration);
132 memcpy(buffer, mdpr, 8);
133 memcpy(&buffer[8], &mdpr->object_version, 2);
134 memcpy(&buffer[10], &mdpr->stream_number, 2);
135 memcpy(&buffer[12], &mdpr->max_bit_rate, 28);
136 memcpy(&buffer[40], &mdpr->stream_name_size, 1);
137 s1=mdpr->stream_name_size;
138 memcpy(&buffer[41], mdpr->stream_name, s1);
140 memcpy(&buffer[41+s1], &mdpr->mime_type_size, 1);
141 s2=mdpr->mime_type_size;
142 memcpy(&buffer[42+s1], mdpr->mime_type, s2);
144 mdpr->type_specific_len=BE_32(&mdpr->type_specific_len);
145 memcpy(&buffer[42+s1+s2], &mdpr->type_specific_len, 4);
146 mdpr->type_specific_len=BE_32(&mdpr->type_specific_len);
147 s3=mdpr->type_specific_len;
148 memcpy(&buffer[46+s1+s2], mdpr->type_specific_data, s3);
150 mdpr->size=BE_32(&mdpr->size);
151 mdpr->stream_number=BE_16(&mdpr->stream_number);
152 mdpr->max_bit_rate=BE_32(&mdpr->max_bit_rate);
153 mdpr->avg_bit_rate=BE_32(&mdpr->avg_bit_rate);
154 mdpr->max_packet_size=BE_32(&mdpr->max_packet_size);
155 mdpr->avg_packet_size=BE_32(&mdpr->avg_packet_size);
156 mdpr->start_time=BE_32(&mdpr->start_time);
157 mdpr->preroll=BE_32(&mdpr->preroll);
158 mdpr->duration=BE_32(&mdpr->duration);
159 mdpr->object_id=BE_32(&mdpr->object_id);
161 return RMFF_MDPRHEADER_SIZE + s1 + s2 + s3;
164 static int rmff_dump_cont(rmff_cont_t *cont, uint8_t *buffer, int bufsize) {
166 int p;
168 if (!cont) return 0;
170 if (bufsize < RMFF_CONTHEADER_SIZE + cont->title_len + cont->author_len + \
171 cont->copyright_len + cont->comment_len)
172 return -1;
174 cont->object_id=BE_32(&cont->object_id);
175 cont->size=BE_32(&cont->size);
176 cont->object_version=BE_16(&cont->object_version);
178 memcpy(buffer, cont, 8);
179 memcpy(&buffer[8], &cont->object_version, 2);
181 cont->title_len=BE_16(&cont->title_len);
182 memcpy(&buffer[10], &cont->title_len, 2);
183 cont->title_len=BE_16(&cont->title_len);
184 memcpy(&buffer[12], cont->title, cont->title_len);
185 p=12+cont->title_len;
187 cont->author_len=BE_16(&cont->author_len);
188 memcpy(&buffer[p], &cont->author_len, 2);
189 cont->author_len=BE_16(&cont->author_len);
190 memcpy(&buffer[p+2], cont->author, cont->author_len);
191 p+=2+cont->author_len;
193 cont->copyright_len=BE_16(&cont->copyright_len);
194 memcpy(&buffer[p], &cont->copyright_len, 2);
195 cont->copyright_len=BE_16(&cont->copyright_len);
196 memcpy(&buffer[p+2], cont->copyright, cont->copyright_len);
197 p+=2+cont->copyright_len;
199 cont->comment_len=BE_16(&cont->comment_len);
200 memcpy(&buffer[p], &cont->comment_len, 2);
201 cont->comment_len=BE_16(&cont->comment_len);
202 memcpy(&buffer[p+2], cont->comment, cont->comment_len);
204 cont->size=BE_32(&cont->size);
205 cont->object_version=BE_16(&cont->object_version);
206 cont->object_id=BE_32(&cont->object_id);
208 return RMFF_CONTHEADER_SIZE + cont->title_len + cont->author_len + \
209 cont->copyright_len + cont->comment_len;
212 static int rmff_dump_dataheader(rmff_data_t *data, uint8_t *buffer, int bufsize) {
214 if (!data) return 0;
216 if (bufsize < RMFF_DATAHEADER_SIZE)
217 return -1;
220 data->object_id=BE_32(&data->object_id);
221 data->size=BE_32(&data->size);
222 data->object_version=BE_16(&data->object_version);
223 data->num_packets=BE_32(&data->num_packets);
224 data->next_data_header=BE_32(&data->next_data_header);
226 memcpy(buffer, data, 8);
227 memcpy(&buffer[8], &data->object_version, 2);
228 memcpy(&buffer[10], &data->num_packets, 8);
230 data->num_packets=BE_32(&data->num_packets);
231 data->next_data_header=BE_32(&data->next_data_header);
232 data->size=BE_32(&data->size);
233 data->object_version=BE_16(&data->object_version);
234 data->object_id=BE_32(&data->object_id);
236 return RMFF_DATAHEADER_SIZE;
239 int rmff_dump_header(rmff_header_t *h, void *buf_gen, int max) {
240 uint8_t *buffer = buf_gen;
242 int written=0, size;
243 rmff_mdpr_t **stream=h->streams;
245 if ((size=rmff_dump_fileheader(h->fileheader, &buffer[written], max)) < 0)
246 return -1;
248 written += size;
249 max -= size;
251 if ((size=rmff_dump_prop(h->prop, &buffer[written], max)) < 0)
252 return -1;
254 written += size;
255 max -= size;
257 if ((size=rmff_dump_cont(h->cont, &buffer[written], max)) < 0)
258 return -1;
260 written += size;
261 max -= size;
263 if (stream) {
264 while(*stream) {
265 if ((size=rmff_dump_mdpr(*stream, &buffer[written], max)) < 0)
266 return -1;
267 written += size;
268 max -= size;
269 stream++;
273 if ((size=rmff_dump_dataheader(h->data, &buffer[written], max)) < 0)
274 return -1;
276 written+=size;
278 return written;
281 void rmff_dump_pheader(rmff_pheader_t *h, char *data) {
283 data[0]=(h->object_version>>8) & 0xff;
284 data[1]=h->object_version & 0xff;
285 data[2]=(h->length>>8) & 0xff;
286 data[3]=h->length & 0xff;
287 data[4]=(h->stream_number>>8) & 0xff;
288 data[5]=h->stream_number & 0xff;
289 data[6]=(h->timestamp>>24) & 0xff;
290 data[7]=(h->timestamp>>16) & 0xff;
291 data[8]=(h->timestamp>>8) & 0xff;
292 data[9]=h->timestamp & 0xff;
293 data[10]=h->reserved;
294 data[11]=h->flags;
297 rmff_fileheader_t *rmff_new_fileheader(uint32_t num_headers) {
299 rmff_fileheader_t *fileheader = calloc( 1, sizeof(rmff_fileheader_t) );
300 if( !fileheader )
301 return NULL;
303 fileheader->object_id=RMF_TAG;
304 fileheader->size=18;
305 fileheader->object_version=0;
306 fileheader->file_version=0;
307 fileheader->num_headers=num_headers;
309 return fileheader;
312 rmff_prop_t *rmff_new_prop (
313 uint32_t max_bit_rate,
314 uint32_t avg_bit_rate,
315 uint32_t max_packet_size,
316 uint32_t avg_packet_size,
317 uint32_t num_packets,
318 uint32_t duration,
319 uint32_t preroll,
320 uint32_t index_offset,
321 uint32_t data_offset,
322 uint16_t num_streams,
323 uint16_t flags ) {
325 rmff_prop_t *prop = calloc( 1, sizeof(rmff_prop_t) );
326 if( !prop )
327 return NULL;
329 prop->object_id=PROP_TAG;
330 prop->size=50;
331 prop->object_version=0;
332 prop->max_bit_rate=max_bit_rate;
333 prop->avg_bit_rate=avg_bit_rate;
334 prop->max_packet_size=max_packet_size;
335 prop->avg_packet_size=avg_packet_size;
336 prop->num_packets=num_packets;
337 prop->duration=duration;
338 prop->preroll=preroll;
339 prop->index_offset=index_offset;
340 prop->data_offset=data_offset;
341 prop->num_streams=num_streams;
342 prop->flags=flags;
344 return prop;
347 rmff_mdpr_t *rmff_new_mdpr(
348 uint16_t stream_number,
349 uint32_t max_bit_rate,
350 uint32_t avg_bit_rate,
351 uint32_t max_packet_size,
352 uint32_t avg_packet_size,
353 uint32_t start_time,
354 uint32_t preroll,
355 uint32_t duration,
356 const char *stream_name,
357 const char *mime_type,
358 uint32_t type_specific_len,
359 const char *type_specific_data ) {
361 rmff_mdpr_t *mdpr = calloc( 1, sizeof(rmff_mdpr_t) );
362 if( !mdpr )
363 return NULL;
365 mdpr->object_id=MDPR_TAG;
366 mdpr->object_version=0;
367 mdpr->stream_number=stream_number;
368 mdpr->max_bit_rate=max_bit_rate;
369 mdpr->avg_bit_rate=avg_bit_rate;
370 mdpr->max_packet_size=max_packet_size;
371 mdpr->avg_packet_size=avg_packet_size;
372 mdpr->start_time=start_time;
373 mdpr->preroll=preroll;
374 mdpr->duration=duration;
375 mdpr->stream_name_size=0;
376 if (stream_name) {
377 mdpr->stream_name=strdup(stream_name);
378 mdpr->stream_name_size=strlen(stream_name);
380 mdpr->mime_type_size=0;
381 if (mime_type) {
382 mdpr->mime_type=strdup(mime_type);
383 mdpr->mime_type_size=strlen(mime_type);
385 mdpr->type_specific_len=type_specific_len;
387 mdpr->type_specific_data = malloc(type_specific_len);
388 if( !mdpr->type_specific_data ) {
389 free( mdpr->stream_name );
390 free( mdpr );
391 return NULL;
393 memcpy(mdpr->type_specific_data,type_specific_data,type_specific_len);
394 mdpr->mlti_data=NULL;
395 mdpr->size=mdpr->stream_name_size+mdpr->mime_type_size+mdpr->type_specific_len+46;
396 return mdpr;
399 rmff_cont_t *rmff_new_cont(const char *title, const char *author, const char *copyright, const char *comment) {
401 rmff_cont_t *cont = calloc( 1, sizeof(rmff_cont_t) );
402 if( !cont )
403 return NULL;
405 cont->object_id=CONT_TAG;
406 cont->object_version=0;
407 cont->title=NULL;
408 cont->author=NULL;
409 cont->copyright=NULL;
410 cont->comment=NULL;
411 cont->title_len=0;
412 cont->author_len=0;
413 cont->copyright_len=0;
414 cont->comment_len=0;
416 if (title) {
417 cont->title_len=strlen(title);
418 cont->title=strdup(title);
420 if (author)
422 cont->author_len=strlen(author);
423 cont->author=strdup(author);
425 if (copyright) {
426 cont->copyright_len=strlen(copyright);
427 cont->copyright=strdup(copyright);
429 if (comment) {
430 cont->comment_len=strlen(comment);
431 cont->comment=strdup(comment);
433 cont->size=cont->title_len+cont->author_len+cont->copyright_len+cont->comment_len+18;
434 return cont;
437 rmff_data_t *rmff_new_dataheader(uint32_t num_packets, uint32_t next_data_header) {
438 rmff_data_t *data = calloc( 1, sizeof(rmff_data_t) );
439 if( !data )
440 return NULL;
442 data->object_id=DATA_TAG;
443 data->size=18;
444 data->object_version=0;
445 data->num_packets=num_packets;
446 data->next_data_header=next_data_header;
448 return data;
451 void rmff_print_header(rmff_header_t *h) {
452 rmff_mdpr_t **stream;
454 if(!h) {
455 printf("rmff_print_header: NULL given\n");
456 return;
458 if(h->fileheader)
460 printf("\nFILE:\n");
461 printf("file version : %d\n", h->fileheader->file_version);
462 printf("number of headers : %d\n", h->fileheader->num_headers);
464 if(h->cont)
466 printf("\nCONTENT:\n");
467 printf("title : %s\n", h->cont->title);
468 printf("author : %s\n", h->cont->author);
469 printf("copyright : %s\n", h->cont->copyright);
470 printf("comment : %s\n", h->cont->comment);
472 if(h->prop)
474 printf("\nSTREAM PROPERTIES:\n");
475 printf("bit rate (max/avg) : %i/%i\n", h->prop->max_bit_rate, h->prop->avg_bit_rate);
476 printf("packet size (max/avg) : %i/%i bytes\n", h->prop->max_packet_size, h->prop->avg_packet_size);
477 printf("packets : %i\n", h->prop->num_packets);
478 printf("duration : %i ms\n", h->prop->duration);
479 printf("pre-buffer : %i ms\n", h->prop->preroll);
480 printf("index offset : %i bytes\n", h->prop->index_offset);
481 printf("data offset : %i bytes\n", h->prop->data_offset);
482 printf("media streams : %i\n", h->prop->num_streams);
483 printf("flags : ");
484 if (h->prop->flags & PN_SAVE_ENABLED) printf("save_enabled ");
485 if (h->prop->flags & PN_PERFECT_PLAY_ENABLED) printf("perfect_play_enabled ");
486 if (h->prop->flags & PN_LIVE_BROADCAST) printf("live_broadcast ");
487 printf("\n");
489 stream=h->streams;
490 if(stream)
492 while (*stream)
494 printf("\nSTREAM %i:\n", (*stream)->stream_number);
495 printf("stream name [mime type] : %s [%s]\n", (*stream)->stream_name, (*stream)->mime_type);
496 printf("bit rate (max/avg) : %i/%i\n", (*stream)->max_bit_rate, (*stream)->avg_bit_rate);
497 printf("packet size (max/avg) : %i/%i bytes\n", (*stream)->max_packet_size, (*stream)->avg_packet_size);
498 printf("start time : %i\n", (*stream)->start_time);
499 printf("pre-buffer : %i ms\n", (*stream)->preroll);
500 printf("duration : %i ms\n", (*stream)->duration);
501 printf("type specific data:\n");
502 stream++;
505 if(h->data)
507 printf("\nDATA:\n");
508 printf("size : %i\n", h->data->size);
509 printf("packets : %i\n", h->data->num_packets);
510 printf("next DATA : 0x%08x\n", h->data->next_data_header);
514 void rmff_fix_header(stream_t *p_access, rmff_header_t *h) {
516 unsigned int num_headers=0;
517 unsigned int header_size=0;
518 rmff_mdpr_t **streams;
519 int num_streams=0;
521 if (!h) {
522 msg_Warn(p_access, "rmff_fix_header: fatal: no header given.");
523 return;
525 if (!h->streams) {
526 msg_Warn(p_access, "rmff_fix_header: warning: no MDPR chunks");
527 } else
529 streams=h->streams;
530 while (*streams)
532 num_streams++;
533 num_headers++;
534 header_size+=(*streams)->size;
535 streams++;
538 if (h->prop) {
539 if (h->prop->size != 50)
541 msg_Dbg(p_access, "rmff_fix_header: correcting prop.size from %i to %i", h->prop->size, 50);
542 h->prop->size=50;
544 if (h->prop->num_streams != num_streams)
546 msg_Dbg(p_access, "rmff_fix_header: correcting prop.num_streams from %i to %i", h->prop->num_streams, num_streams);
547 h->prop->num_streams=num_streams;
549 num_headers++;
550 header_size+=50;
551 } else
552 msg_Warn(p_access, "rmff_fix_header: warning: no PROP chunk.");
554 if (h->cont) {
555 num_headers++;
556 header_size+=h->cont->size;
557 } else
558 msg_Warn(p_access, "rmff_fix_header: warning: no CONT chunk.");
560 if (!h->data) {
561 msg_Warn(p_access, "rmff_fix_header: no DATA chunk, creating one");
562 h->data = calloc( 1, sizeof(rmff_data_t) );
563 if( h->data )
565 h->data->object_id=DATA_TAG;
566 h->data->object_version=0;
567 h->data->size=18;
568 h->data->num_packets=0;
569 h->data->next_data_header=0;
572 num_headers++;
574 if (!h->fileheader) {
575 msg_Warn(p_access, "rmff_fix_header: no fileheader, creating one");
576 h->fileheader = calloc( 1, sizeof(rmff_fileheader_t) );
577 if( h->fileheader )
579 h->fileheader->object_id=RMF_TAG;
580 h->fileheader->size=18;
581 h->fileheader->object_version=0;
582 h->fileheader->file_version=0;
583 h->fileheader->num_headers=num_headers+1;
586 header_size+=h->fileheader->size;
587 num_headers++;
589 if(h->fileheader->num_headers != num_headers) {
590 msg_Dbg(p_access, "rmff_fix_header: setting num_headers from %i to %i", h->fileheader->num_headers, num_headers);
591 h->fileheader->num_headers=num_headers;
593 if(h->prop) {
594 if (h->prop->data_offset != header_size) {
595 msg_Dbg(p_access, "rmff_fix_header: setting prop.data_offset from %i to %i", h->prop->data_offset, header_size);
596 h->prop->data_offset=header_size;
599 /* FIXME: I doubt this is right to do this here.
600 * It should belong to the demux. */
601 if (h->prop->num_packets == 0) {
602 int p=(int)(h->prop->avg_bit_rate/8.0*(h->prop->duration/1000.0)/h->prop->avg_packet_size);
603 msg_Dbg(p_access, "rmff_fix_header: assuming prop.num_packets=%i", p);
604 h->prop->num_packets=p;
606 if (h->data->num_packets == 0) {
607 msg_Dbg(p_access, "rmff_fix_header: assuming data.num_packets=%i", h->prop->num_packets);
608 h->data->num_packets=h->prop->num_packets;
610 if (h->data->size == 18 || !h->data->size ) {
611 msg_Dbg(p_access, "rmff_fix_header: assuming data.size=%i", h->prop->num_packets*h->prop->avg_packet_size);
612 h->data->size+=h->prop->num_packets*h->prop->avg_packet_size;
617 int rmff_get_header_size(rmff_header_t *h) {
618 if (!h) return 0;
619 if (!h->prop) return -1;
620 return h->prop->data_offset+18;
623 void rmff_free_header(rmff_header_t *h)
625 if (!h) return;
627 free( h->fileheader );
628 free( h->prop );
629 free( h->data );
630 if( h->cont ) {
631 free( h->cont->title );
632 free( h->cont->author );
633 free( h->cont->copyright );
634 free( h->cont->comment );
635 free( h->cont );
637 if (h->streams)
639 rmff_mdpr_t **s=h->streams;
641 while(*s) {
642 free((*s)->stream_name);
643 free((*s)->mime_type);
644 free((*s)->type_specific_data);
645 free(*s);
646 s++;
648 free(h->streams);
650 free(h);