Main Page | Modules | Class Hierarchy | Class List | Directories | File List | Class Members | File Members | Related Pages

real_rmff.c

00001 /*
00002  * Copyright (C) 2002-2003 the xine project
00003  *
00004  * This file is part of xine, a free video player.
00005  *
00006  * xine is free software; you can redistribute it and/or modify
00007  * it under the terms of the GNU General Public License as published by
00008  * the Free Software Foundation; either version 2 of the License, or
00009  * (at your option) any later version.
00010  *
00011  * xine is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  * GNU General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU General Public License
00017  * along with this program; if not, write to the Free Software
00018  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA
00019  *
00020  * $Id: rmff.c,v 1.7 2003/12/05 15:54:58 f1rmb Exp $
00021  *
00022  * functions for real media file format
00023  * adopted from joschkas real tools
00024  */
00025 
00026 #include "real.h"
00027 
00028 #define BE_16(x)  ((((uint8_t*)(x))[0] << 8) | ((uint8_t*)(x))[1])
00029 #define BE_32(x)  ((((uint8_t*)(x))[0] << 24) | \
00030                    (((uint8_t*)(x))[1] << 16) | \
00031                    (((uint8_t*)(x))[2] << 8) | \
00032                     ((uint8_t*)(x))[3])
00033 
00034 /*
00035  * writes header data to a buffer
00036  */
00037 
00038 static void rmff_dump_fileheader(rmff_fileheader_t *fileheader, char *buffer) {
00039 
00040   if (!fileheader) return;
00041   fileheader->object_id=BE_32(&fileheader->object_id);
00042   fileheader->size=BE_32(&fileheader->size);
00043   fileheader->object_version=BE_16(&fileheader->object_version);
00044   fileheader->file_version=BE_32(&fileheader->file_version);
00045   fileheader->num_headers=BE_32(&fileheader->num_headers);
00046 
00047   memcpy(buffer, fileheader, 8);
00048   memcpy(&buffer[8], &fileheader->object_version, 2);
00049   memcpy(&buffer[10], &fileheader->file_version, 8);
00050 
00051   fileheader->size=BE_32(&fileheader->size);
00052   fileheader->object_version=BE_16(&fileheader->object_version);
00053   fileheader->file_version=BE_32(&fileheader->file_version);
00054   fileheader->num_headers=BE_32(&fileheader->num_headers);
00055   fileheader->object_id=BE_32(&fileheader->object_id);
00056 }
00057 
00058 static void rmff_dump_prop(rmff_prop_t *prop, char *buffer) {
00059 
00060   if (!prop) return;
00061   prop->object_id=BE_32(&prop->object_id);
00062   prop->size=BE_32(&prop->size);
00063   prop->object_version=BE_16(&prop->object_version);
00064   prop->max_bit_rate=BE_32(&prop->max_bit_rate);
00065   prop->avg_bit_rate=BE_32(&prop->avg_bit_rate);
00066   prop->max_packet_size=BE_32(&prop->max_packet_size);
00067   prop->avg_packet_size=BE_32(&prop->avg_packet_size);
00068   prop->num_packets=BE_32(&prop->num_packets);
00069   prop->duration=BE_32(&prop->duration);
00070   prop->preroll=BE_32(&prop->preroll);
00071   prop->index_offset=BE_32(&prop->index_offset);
00072   prop->data_offset=BE_32(&prop->data_offset);
00073   prop->num_streams=BE_16(&prop->num_streams);
00074   prop->flags=BE_16(&prop->flags);
00075 
00076   memcpy(buffer, prop, 8);
00077   memcpy(&buffer[8], &prop->object_version, 2);
00078   memcpy(&buffer[10], &prop->max_bit_rate, 36);
00079   memcpy(&buffer[46], &prop->num_streams, 2);
00080   memcpy(&buffer[48], &prop->flags, 2);
00081 
00082   prop->size=BE_32(&prop->size);
00083   prop->object_version=BE_16(&prop->object_version);
00084   prop->max_bit_rate=BE_32(&prop->max_bit_rate);
00085   prop->avg_bit_rate=BE_32(&prop->avg_bit_rate);
00086   prop->max_packet_size=BE_32(&prop->max_packet_size);
00087   prop->avg_packet_size=BE_32(&prop->avg_packet_size);
00088   prop->num_packets=BE_32(&prop->num_packets);
00089   prop->duration=BE_32(&prop->duration);
00090   prop->preroll=BE_32(&prop->preroll);
00091   prop->index_offset=BE_32(&prop->index_offset);
00092   prop->data_offset=BE_32(&prop->data_offset);
00093   prop->num_streams=BE_16(&prop->num_streams);
00094   prop->flags=BE_16(&prop->flags);
00095   prop->object_id=BE_32(&prop->object_id);
00096 }
00097 
00098 static void rmff_dump_mdpr(rmff_mdpr_t *mdpr, char *buffer) {
00099 
00100   int s1, s2, s3;
00101 
00102   if (!mdpr) return;
00103   mdpr->object_id=BE_32(&mdpr->object_id);
00104   mdpr->size=BE_32(&mdpr->size);
00105   mdpr->object_version=BE_16(&mdpr->object_version);
00106   mdpr->stream_number=BE_16(&mdpr->stream_number);
00107   mdpr->max_bit_rate=BE_32(&mdpr->max_bit_rate);
00108   mdpr->avg_bit_rate=BE_32(&mdpr->avg_bit_rate);
00109   mdpr->max_packet_size=BE_32(&mdpr->max_packet_size);
00110   mdpr->avg_packet_size=BE_32(&mdpr->avg_packet_size);
00111   mdpr->start_time=BE_32(&mdpr->start_time);
00112   mdpr->preroll=BE_32(&mdpr->preroll);
00113   mdpr->duration=BE_32(&mdpr->duration);
00114 
00115   memcpy(buffer, mdpr, 8);
00116   memcpy(&buffer[8], &mdpr->object_version, 2);
00117   memcpy(&buffer[10], &mdpr->stream_number, 2);
00118   memcpy(&buffer[12], &mdpr->max_bit_rate, 28);
00119   memcpy(&buffer[40], &mdpr->stream_name_size, 1);
00120   s1=mdpr->stream_name_size;
00121   memcpy(&buffer[41], mdpr->stream_name, s1);
00122 
00123   memcpy(&buffer[41+s1], &mdpr->mime_type_size, 1);
00124   s2=mdpr->mime_type_size;
00125   memcpy(&buffer[42+s1], mdpr->mime_type, s2);
00126 
00127   mdpr->type_specific_len=BE_32(&mdpr->type_specific_len);
00128   memcpy(&buffer[42+s1+s2], &mdpr->type_specific_len, 4);
00129   mdpr->type_specific_len=BE_32(&mdpr->type_specific_len);
00130   s3=mdpr->type_specific_len;
00131   memcpy(&buffer[46+s1+s2], mdpr->type_specific_data, s3);
00132 
00133   mdpr->size=BE_32(&mdpr->size);
00134   mdpr->stream_number=BE_16(&mdpr->stream_number);
00135   mdpr->max_bit_rate=BE_32(&mdpr->max_bit_rate);
00136   mdpr->avg_bit_rate=BE_32(&mdpr->avg_bit_rate);
00137   mdpr->max_packet_size=BE_32(&mdpr->max_packet_size);
00138   mdpr->avg_packet_size=BE_32(&mdpr->avg_packet_size);
00139   mdpr->start_time=BE_32(&mdpr->start_time);
00140   mdpr->preroll=BE_32(&mdpr->preroll);
00141   mdpr->duration=BE_32(&mdpr->duration);
00142   mdpr->object_id=BE_32(&mdpr->object_id);
00143 
00144 }
00145 
00146 static void rmff_dump_cont(rmff_cont_t *cont, char *buffer) {
00147 
00148   int p;
00149 
00150   if (!cont) return;
00151   cont->object_id=BE_32(&cont->object_id);
00152   cont->size=BE_32(&cont->size);
00153   cont->object_version=BE_16(&cont->object_version);
00154 
00155   memcpy(buffer, cont, 8);
00156   memcpy(&buffer[8], &cont->object_version, 2);
00157 
00158   cont->title_len=BE_16(&cont->title_len);
00159   memcpy(&buffer[10], &cont->title_len, 2);
00160   cont->title_len=BE_16(&cont->title_len);
00161   memcpy(&buffer[12], cont->title, cont->title_len);
00162   p=12+cont->title_len;
00163 
00164   cont->author_len=BE_16(&cont->author_len);
00165   memcpy(&buffer[p], &cont->author_len, 2);
00166   cont->author_len=BE_16(&cont->author_len);
00167   memcpy(&buffer[p+2], cont->author, cont->author_len);
00168   p+=2+cont->author_len;
00169 
00170   cont->copyright_len=BE_16(&cont->copyright_len);
00171   memcpy(&buffer[p], &cont->copyright_len, 2);
00172   cont->copyright_len=BE_16(&cont->copyright_len);
00173   memcpy(&buffer[p+2], cont->copyright, cont->copyright_len);
00174   p+=2+cont->copyright_len;
00175 
00176   cont->comment_len=BE_16(&cont->comment_len);
00177   memcpy(&buffer[p], &cont->comment_len, 2);
00178   cont->comment_len=BE_16(&cont->comment_len);
00179   memcpy(&buffer[p+2], cont->comment, cont->comment_len);
00180 
00181   cont->size=BE_32(&cont->size);
00182   cont->object_version=BE_16(&cont->object_version);
00183   cont->object_id=BE_32(&cont->object_id);
00184 }
00185 
00186 static void rmff_dump_dataheader(rmff_data_t *data, char *buffer) {
00187 
00188   if (!data) return;
00189 
00190   data->object_id=BE_32(&data->object_id);
00191   data->size=BE_32(&data->size);
00192   data->object_version=BE_16(&data->object_version);
00193   data->num_packets=BE_32(&data->num_packets);
00194   data->next_data_header=BE_32(&data->next_data_header);
00195 
00196   memcpy(buffer, data, 8);
00197   memcpy(&buffer[8], &data->object_version, 2);
00198   memcpy(&buffer[10], &data->num_packets, 8);
00199 
00200   data->num_packets=BE_32(&data->num_packets);
00201   data->next_data_header=BE_32(&data->next_data_header);
00202   data->size=BE_32(&data->size);
00203   data->object_version=BE_16(&data->object_version);
00204   data->object_id=BE_32(&data->object_id);
00205 }
00206 
00207 int rmff_dump_header(rmff_header_t *h, char *buffer, int max) {
00208 
00209   int written=0;
00210   rmff_mdpr_t **stream=h->streams;
00211 
00212   rmff_dump_fileheader(h->fileheader, &buffer[written]);
00213   written+=h->fileheader->size;
00214   rmff_dump_prop(h->prop, &buffer[written]);
00215   written+=h->prop->size;
00216   rmff_dump_cont(h->cont, &buffer[written]);
00217   written+=h->cont->size;
00218   if (stream)
00219   {
00220     while(*stream)
00221     {
00222       rmff_dump_mdpr(*stream, &buffer[written]);
00223       written+=(*stream)->size;
00224       stream++;
00225     }
00226   }
00227 
00228   rmff_dump_dataheader(h->data, &buffer[written]);
00229   written+=18;
00230 
00231   return written;
00232 }
00233 
00234 void rmff_dump_pheader(rmff_pheader_t *h, char *data) {
00235 
00236   data[0]=(h->object_version>>8) & 0xff;
00237   data[1]=h->object_version & 0xff;
00238   data[2]=(h->length>>8) & 0xff;
00239   data[3]=h->length & 0xff;
00240   data[4]=(h->stream_number>>8) & 0xff;
00241   data[5]=h->stream_number & 0xff;
00242   data[6]=(h->timestamp>>24) & 0xff;
00243   data[7]=(h->timestamp>>16) & 0xff;
00244   data[8]=(h->timestamp>>8) & 0xff;
00245   data[9]=h->timestamp & 0xff;
00246   data[10]=h->reserved;
00247   data[11]=h->flags;
00248 }
00249 
00250 rmff_fileheader_t *rmff_new_fileheader(uint32_t num_headers) {
00251 
00252   rmff_fileheader_t *fileheader = malloc(sizeof(rmff_fileheader_t));
00253   if( !fileheader ) return NULL;
00254 
00255   memset(fileheader, 0, sizeof(rmff_fileheader_t));
00256   fileheader->object_id=RMF_TAG;
00257   fileheader->size=18;
00258   fileheader->object_version=0;
00259   fileheader->file_version=0;
00260   fileheader->num_headers=num_headers;
00261 
00262   return fileheader;
00263 }
00264 
00265 rmff_prop_t *rmff_new_prop (
00266   uint32_t max_bit_rate,
00267   uint32_t avg_bit_rate,
00268   uint32_t max_packet_size,
00269   uint32_t avg_packet_size,
00270   uint32_t num_packets,
00271   uint32_t duration,
00272   uint32_t preroll,
00273   uint32_t index_offset,
00274   uint32_t data_offset,
00275   uint16_t num_streams,
00276   uint16_t flags ) {
00277 
00278   rmff_prop_t *prop = malloc(sizeof(rmff_prop_t));
00279   if( !prop ) return NULL;
00280 
00281   memset(prop, 0, sizeof(rmff_prop_t));
00282   prop->object_id=PROP_TAG;
00283   prop->size=50;
00284   prop->object_version=0;
00285   prop->max_bit_rate=max_bit_rate;
00286   prop->avg_bit_rate=avg_bit_rate;
00287   prop->max_packet_size=max_packet_size;
00288   prop->avg_packet_size=avg_packet_size;
00289   prop->num_packets=num_packets;
00290   prop->duration=duration;
00291   prop->preroll=preroll;
00292   prop->index_offset=index_offset;
00293   prop->data_offset=data_offset;
00294   prop->num_streams=num_streams;
00295   prop->flags=flags;
00296 
00297   return prop;
00298 }
00299 
00300 rmff_mdpr_t *rmff_new_mdpr(
00301   uint16_t   stream_number,
00302   uint32_t   max_bit_rate,
00303   uint32_t   avg_bit_rate,
00304   uint32_t   max_packet_size,
00305   uint32_t   avg_packet_size,
00306   uint32_t   start_time,
00307   uint32_t   preroll,
00308   uint32_t   duration,
00309   const char *stream_name,
00310   const char *mime_type,
00311   uint32_t   type_specific_len,
00312   const char *type_specific_data ) {
00313 
00314   rmff_mdpr_t *mdpr = malloc(sizeof(rmff_mdpr_t));
00315   if( !mdpr ) return NULL;
00316 
00317   memset(mdpr, 0, sizeof(rmff_mdpr_t));
00318   mdpr->object_id=MDPR_TAG;
00319   mdpr->object_version=0;
00320   mdpr->stream_number=stream_number;
00321   mdpr->max_bit_rate=max_bit_rate;
00322   mdpr->avg_bit_rate=avg_bit_rate;
00323   mdpr->max_packet_size=max_packet_size;
00324   mdpr->avg_packet_size=avg_packet_size;
00325   mdpr->start_time=start_time;
00326   mdpr->preroll=preroll;
00327   mdpr->duration=duration;
00328   mdpr->stream_name_size=0;
00329   if (stream_name) {
00330     mdpr->stream_name=strdup(stream_name);
00331     mdpr->stream_name_size=strlen(stream_name);
00332   }
00333   mdpr->mime_type_size=0;
00334   if (mime_type) {
00335     mdpr->mime_type=strdup(mime_type);
00336     mdpr->mime_type_size=strlen(mime_type);
00337   }
00338   mdpr->type_specific_len=type_specific_len;
00339 
00340   mdpr->type_specific_data = malloc(sizeof(char)*type_specific_len);
00341   if( !mdpr->type_specific_data ) {
00342     if( mdpr->stream_name ) free( mdpr->stream_name );
00343     free( mdpr );
00344     return NULL;
00345   }
00346   memcpy(mdpr->type_specific_data,type_specific_data,type_specific_len);
00347   mdpr->mlti_data=NULL;
00348   mdpr->size=mdpr->stream_name_size+mdpr->mime_type_size+mdpr->type_specific_len+46;
00349   return mdpr;
00350 }
00351 
00352 rmff_cont_t *rmff_new_cont(const char *title, const char *author, const char *copyright, const char *comment) {
00353 
00354   rmff_cont_t *cont = malloc(sizeof(rmff_cont_t));
00355   if( !cont ) return NULL;
00356 
00357   memset(cont, 0, sizeof(rmff_cont_t));
00358   cont->object_id=CONT_TAG;
00359   cont->object_version=0;
00360   cont->title=NULL;
00361   cont->author=NULL;
00362   cont->copyright=NULL;
00363   cont->comment=NULL;
00364   cont->title_len=0;
00365   cont->author_len=0;
00366   cont->copyright_len=0;
00367   cont->comment_len=0;
00368 
00369   if (title) {
00370     cont->title_len=strlen(title);
00371     cont->title=strdup(title);
00372   }
00373   if (author)
00374   {
00375     cont->author_len=strlen(author);
00376     cont->author=strdup(author);
00377   }
00378   if (copyright) {
00379     cont->copyright_len=strlen(copyright);
00380     cont->copyright=strdup(copyright);
00381   }
00382   if (comment) {
00383     cont->comment_len=strlen(comment);
00384     cont->comment=strdup(comment);
00385   }
00386   cont->size=cont->title_len+cont->author_len+cont->copyright_len+cont->comment_len+18;
00387   return cont;
00388 }
00389 
00390 rmff_data_t *rmff_new_dataheader(uint32_t num_packets, uint32_t next_data_header) {
00391   rmff_data_t *data = malloc(sizeof(rmff_data_t));
00392   if( !data ) return NULL;
00393 
00394   memset(data, 0, sizeof(rmff_data_t));
00395   data->object_id=DATA_TAG;
00396   data->size=18;
00397   data->object_version=0;
00398   data->num_packets=num_packets;
00399   data->next_data_header=next_data_header;
00400 
00401   return data;
00402 }
00403 
00404 void rmff_print_header(rmff_header_t *h) {
00405   rmff_mdpr_t **stream;
00406 
00407   if(!h) {
00408     printf("rmff_print_header: NULL given\n");
00409     return;
00410   }
00411   if(h->fileheader) {
00412     printf("\nFILE:\n");
00413     printf("file version      : %d\n", h->fileheader->file_version);
00414     printf("number of headers : %d\n", h->fileheader->num_headers);
00415   }
00416   if(h->cont) {
00417     printf("\nCONTENT:\n");
00418     printf("title     : %s\n", h->cont->title);
00419     printf("author    : %s\n", h->cont->author);
00420     printf("copyright : %s\n", h->cont->copyright);
00421     printf("comment   : %s\n", h->cont->comment);
00422   }
00423   if(h->prop) {
00424     printf("\nSTREAM PROPERTIES:\n");
00425     printf("bit rate (max/avg)    : %i/%i\n", h->prop->max_bit_rate, h->prop->avg_bit_rate);
00426     printf("packet size (max/avg) : %i/%i bytes\n", h->prop->max_packet_size, h->prop->avg_packet_size);
00427     printf("packets       : %i\n", h->prop->num_packets);
00428     printf("duration      : %i ms\n", h->prop->duration);
00429     printf("pre-buffer    : %i ms\n", h->prop->preroll);
00430     printf("index offset  : %i bytes\n", h->prop->index_offset);
00431     printf("data offset   : %i bytes\n", h->prop->data_offset);
00432     printf("media streams : %i\n", h->prop->num_streams);
00433     printf("flags         : ");
00434     if (h->prop->flags & PN_SAVE_ENABLED) printf("save_enabled ");
00435     if (h->prop->flags & PN_PERFECT_PLAY_ENABLED) printf("perfect_play_enabled ");
00436     if (h->prop->flags & PN_LIVE_BROADCAST) printf("live_broadcast ");
00437     printf("\n");
00438   }
00439   stream=h->streams;
00440   if(stream) {
00441     while (*stream) {
00442       printf("\nSTREAM %i:\n", (*stream)->stream_number);
00443       printf("stream name [mime type] : %s [%s]\n", (*stream)->stream_name, (*stream)->mime_type);
00444       printf("bit rate (max/avg)      : %i/%i\n", (*stream)->max_bit_rate, (*stream)->avg_bit_rate);
00445       printf("packet size (max/avg)   : %i/%i bytes\n", (*stream)->max_packet_size, (*stream)->avg_packet_size);
00446       printf("start time : %i\n", (*stream)->start_time);
00447       printf("pre-buffer : %i ms\n", (*stream)->preroll);
00448       printf("duration   : %i ms\n", (*stream)->duration);
00449       printf("type specific data:\n");
00450       stream++;
00451     }
00452   }
00453   if(h->data) {
00454     printf("\nDATA:\n");
00455     printf("size      : %i\n", h->data->size);
00456     printf("packets   : %i\n", h->data->num_packets);
00457     printf("next DATA : 0x%08x\n", h->data->next_data_header);
00458   }
00459 }
00460 
00461 void rmff_fix_header(rmff_header_t *h) {
00462 
00463   unsigned int num_headers=0;
00464   unsigned int header_size=0;
00465   rmff_mdpr_t **streams;
00466   int num_streams=0;
00467 
00468   if (!h) {
00469     lprintf("rmff_fix_header: fatal: no header given.\n");
00470     return;
00471   }
00472   if (!h->streams) {
00473     lprintf("rmff_fix_header: warning: no MDPR chunks\n");
00474   } else {
00475     streams=h->streams;
00476     while (*streams) {
00477         num_streams++;
00478         num_headers++;
00479         header_size+=(*streams)->size;
00480         streams++;
00481     }
00482   }
00483   if (h->prop) {
00484     if (h->prop->size != 50) {
00485       lprintf("rmff_fix_header: correcting prop.size from %i to %i\n", h->prop->size, 50);
00486       h->prop->size=50;
00487     }
00488     if (h->prop->num_streams != num_streams) {
00489       lprintf("rmff_fix_header: correcting prop.num_streams from %i to %i\n", h->prop->num_streams, num_streams);
00490       h->prop->num_streams=num_streams;
00491     }
00492     num_headers++;
00493     header_size+=50;
00494   } else lprintf("rmff_fix_header: warning: no PROP chunk.\n");
00495 
00496   if (h->cont) {
00497     num_headers++;
00498     header_size+=h->cont->size;
00499   } else lprintf("rmff_fix_header: warning: no CONT chunk.\n");
00500 
00501   if (!h->data) {
00502     lprintf("rmff_fix_header: no DATA chunk, creating one\n");
00503     h->data = malloc(sizeof(rmff_data_t));
00504     if( h->data ) {
00505       memset(h->data, 0, sizeof(rmff_data_t));
00506       h->data->object_id=DATA_TAG;
00507       h->data->object_version=0;
00508       h->data->size=18;
00509       h->data->num_packets=0;
00510       h->data->next_data_header=0;
00511     }
00512   }
00513   num_headers++;
00514 
00515   if (!h->fileheader) {
00516     lprintf("rmff_fix_header: no fileheader, creating one");
00517     h->fileheader = malloc(sizeof(rmff_fileheader_t));
00518     if( h->fileheader ) {
00519       memset(h->fileheader, 0, sizeof(rmff_fileheader_t));
00520       h->fileheader->object_id=RMF_TAG;
00521       h->fileheader->size=18;
00522       h->fileheader->object_version=0;
00523       h->fileheader->file_version=0;
00524       h->fileheader->num_headers=num_headers+1;
00525     }
00526   }
00527   header_size+=h->fileheader->size;
00528   num_headers++;
00529 
00530   if(h->fileheader->num_headers != num_headers) {
00531     lprintf("rmff_fix_header: setting num_headers from %i to %i\n", h->fileheader->num_headers, num_headers);
00532     h->fileheader->num_headers=num_headers;
00533   }
00534   if(h->prop) {
00535     if (h->prop->data_offset != header_size) {
00536       lprintf("rmff_fix_header: setting prop.data_offset from %i to %i\n", h->prop->data_offset, header_size);
00537       h->prop->data_offset=header_size;
00538     }
00539 
00540     /* FIXME: I doubt this is right to do this here.
00541      * It should belong to the demux. */
00542     if (h->prop->num_packets == 0) {
00543       int p=(int)(h->prop->avg_bit_rate/8.0*(h->prop->duration/1000.0)/h->prop->avg_packet_size);
00544       lprintf("rmff_fix_header: assuming prop.num_packets=%i\n", p);
00545       h->prop->num_packets=p;
00546     }
00547     if (h->data->num_packets == 0) {
00548       lprintf("rmff_fix_header: assuming data.num_packets=%i\n", h->prop->num_packets);
00549       h->data->num_packets=h->prop->num_packets;
00550     }
00551     if (h->data->size == 18 || !h->data->size ) {
00552       lprintf("rmff_fix_header: assuming data.size=%i\n", h->prop->num_packets*h->prop->avg_packet_size);
00553       h->data->size+=h->prop->num_packets*h->prop->avg_packet_size;
00554     }
00555   }
00556 }
00557 
00558 int rmff_get_header_size(rmff_header_t *h) {
00559   if (!h) return 0;
00560   if (!h->prop) return -1;
00561   return h->prop->data_offset+18;
00562 }
00563 
00564 void rmff_free_header(rmff_header_t *h)
00565 {
00566   if (!h) return;
00567 
00568   if (h->fileheader) free(h->fileheader);
00569   if (h->prop) free(h->prop);
00570   if (h->data) free(h->data);
00571   if (h->cont) {
00572     free(h->cont->title);
00573     free(h->cont->author);
00574     free(h->cont->copyright);
00575     free(h->cont->comment);
00576     free(h->cont);
00577   }
00578   if (h->streams) {
00579     rmff_mdpr_t **s=h->streams;
00580 
00581     while(*s) {
00582       free((*s)->stream_name);
00583       free((*s)->mime_type);
00584       free((*s)->type_specific_data);
00585       free(*s);
00586       s++;
00587     }
00588     free(h->streams);
00589   }
00590   free(h);
00591 }

Generated on Tue Dec 20 10:14:26 2005 for vlc-0.8.4a by  doxygen 1.4.2