real_rmff.c
上传用户:kjfoods
上传日期:2020-07-06
资源大小:29949k
文件大小:19k
源码类别:

midi

开发平台:

Unix_Linux

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