matroska.c
上传用户:lctgjx
上传日期:2022-06-04
资源大小:8887k
文件大小:14k
源码类别:

流媒体/Mpeg4/MP4

开发平台:

Visual C++

  1. /*****************************************************************************
  2.  * matroska.c:
  3.  *****************************************************************************
  4.  * Copyright (C) 2005 Mike Matsnev
  5.  *
  6.  * This program 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.  * This program 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., 51 Franklin Street, Fifth Floor, Boston, MA  02111, USA.
  19.  *****************************************************************************/
  20. #include <stdlib.h>
  21. #include <string.h>
  22. #include "common/osdep.h"
  23. #include "matroska.h"
  24. #define CLSIZE 1048576
  25. #define CHECK(x)
  26. do
  27. {
  28.     if( (x) < 0 ) return -1;
  29. }
  30. while( 0 )
  31. struct mk_context
  32. {
  33.     struct mk_context *next, **prev, *parent;
  34.     struct mk_writer *owner;
  35.     unsigned id;
  36.     void *data;
  37.     unsigned d_cur, d_max;
  38. };
  39. typedef struct mk_context mk_context;
  40. struct mk_writer
  41. {
  42.     FILE *fp;
  43.     unsigned duration_ptr;
  44.     mk_context *root, *cluster, *frame;
  45.     mk_context *freelist;
  46.     mk_context *actlist;
  47.     int64_t def_duration;
  48.     int64_t timescale;
  49.     int64_t cluster_tc_scaled;
  50.     int64_t frame_tc, prev_frame_tc_scaled, max_frame_tc;
  51.     char wrote_header, in_frame, keyframe;
  52. };
  53. static mk_context *mk_create_context( mk_writer *w, mk_context *parent, unsigned id )
  54. {
  55.     mk_context  *c;
  56.     if( w->freelist )
  57.     {
  58.         c = w->freelist;
  59.         w->freelist = w->freelist->next;
  60.     }
  61.     else
  62.     {
  63.         c = malloc( sizeof(*c) );
  64.         if( !c )
  65.             return NULL;
  66.         memset( c, 0, sizeof(*c) );
  67.     }
  68.     c->parent = parent;
  69.     c->owner = w;
  70.     c->id = id;
  71.     if( c->owner->actlist )
  72.         c->owner->actlist->prev = &c->next;
  73.     c->next = c->owner->actlist;
  74.     c->prev = &c->owner->actlist;
  75.     c->owner->actlist = c;
  76.     return c;
  77. }
  78. static int mk_append_context_data( mk_context *c, const void *data, unsigned size )
  79. {
  80.     unsigned ns = c->d_cur + size;
  81.     if( ns > c->d_max )
  82.     {
  83.         void *dp;
  84.         unsigned dn = c->d_max ? c->d_max << 1 : 16;
  85.         while( ns > dn )
  86.             dn <<= 1;
  87.         dp = realloc( c->data, dn );
  88.         if( !dp )
  89.             return -1;
  90.         c->data = dp;
  91.         c->d_max = dn;
  92.     }
  93.     memcpy( (char*)c->data + c->d_cur, data, size );
  94.     c->d_cur = ns;
  95.     return 0;
  96. }
  97. static int mk_write_id( mk_context *c, unsigned id )
  98. {
  99.     unsigned char c_id[4] = { id >> 24, id >> 16, id >> 8, id };
  100.     if( c_id[0] )
  101.         return mk_append_context_data( c, c_id, 4 );
  102.     if( c_id[1] )
  103.         return mk_append_context_data( c, c_id+1, 3 );
  104.     if( c_id[2] )
  105.         return mk_append_context_data( c, c_id+2, 2 );
  106.     return mk_append_context_data( c, c_id+3, 1 );
  107. }
  108. static int mk_write_size( mk_context *c, unsigned size )
  109. {
  110.     unsigned char c_size[5] = { 0x08, size >> 24, size >> 16, size >> 8, size };
  111.     if( size < 0x7f )
  112.     {
  113.         c_size[4] |= 0x80;
  114.         return mk_append_context_data( c, c_size+4, 1 );
  115.     }
  116.     if( size < 0x3fff )
  117.     {
  118.         c_size[3] |= 0x40;
  119.         return mk_append_context_data( c, c_size+3, 2 );
  120.     }
  121.     if( size < 0x1fffff )
  122.     {
  123.         c_size[2] |= 0x20;
  124.         return mk_append_context_data( c, c_size+2, 3 );
  125.     }
  126.     if( size < 0x0fffffff )
  127.     {
  128.         c_size[1] |= 0x10;
  129.         return mk_append_context_data( c, c_size+1, 4 );
  130.     }
  131.     return mk_append_context_data( c, c_size, 5 );
  132. }
  133. static int mk_flush_context_id( mk_context *c )
  134. {
  135.     unsigned char ff = 0xff;
  136.     if( !c->id )
  137.         return 0;
  138.     CHECK( mk_write_id( c->parent, c->id ) );
  139.     CHECK( mk_append_context_data( c->parent, &ff, 1 ) );
  140.     c->id = 0;
  141.     return 0;
  142. }
  143. static int mk_flush_context_data(mk_context *c)
  144. {
  145.     if( !c->d_cur )
  146.         return 0;
  147.     if( c->parent )
  148.         CHECK( mk_append_context_data( c->parent, c->data, c->d_cur ) );
  149.     else if( fwrite( c->data, c->d_cur, 1, c->owner->fp ) != 1 )
  150.         return -1;
  151.     c->d_cur = 0;
  152.     return 0;
  153. }
  154. static int mk_close_context(mk_context *c, unsigned *off)
  155. {
  156.     if( c->id )
  157.     {
  158.         CHECK( mk_write_id( c->parent, c->id ) );
  159.         CHECK( mk_write_size( c->parent, c->d_cur ) );
  160.     }
  161.     if( c->parent && off )
  162.         *off += c->parent->d_cur;
  163.     CHECK( mk_flush_context_data( c ) );
  164.     if( c->next )
  165.         c->next->prev = c->prev;
  166.     *(c->prev) = c->next;
  167.     c->next = c->owner->freelist;
  168.     c->owner->freelist = c;
  169.     return 0;
  170. }
  171. static void mk_destroy_contexts( mk_writer *w )
  172. {
  173.     mk_context *cur, *next;
  174.     for( cur = w->freelist; cur; cur = next )
  175.     {
  176.         next = cur->next;
  177.         free( cur->data );
  178.         free( cur );
  179.     }
  180.     for( cur = w->actlist; cur; cur = next )
  181.     {
  182.         next = cur->next;
  183.         free( cur->data );
  184.         free( cur );
  185.     }
  186.     w->freelist = w->actlist = w->root = NULL;
  187. }
  188. static int mk_write_string( mk_context *c, unsigned id, const char *str )
  189. {
  190.     size_t len = strlen( str );
  191.     CHECK( mk_write_id( c, id ) );
  192.     CHECK( mk_write_size( c, len ) );
  193.     CHECK( mk_append_context_data( c, str, len ) );
  194.     return 0;
  195. }
  196. static int mk_write_bin( mk_context *c, unsigned id, const void *data, unsigned size )
  197. {
  198.     CHECK( mk_write_id( c, id ) );
  199.     CHECK( mk_write_size( c, size ) );
  200.     CHECK( mk_append_context_data( c, data, size ) ) ;
  201.     return 0;
  202. }
  203. static int mk_write_uint( mk_context *c, unsigned id, int64_t ui )
  204. {
  205.     unsigned char c_ui[8] = { ui >> 56, ui >> 48, ui >> 40, ui >> 32, ui >> 24, ui >> 16, ui >> 8, ui };
  206.     unsigned i = 0;
  207.     CHECK( mk_write_id( c, id ) );
  208.     while( i < 7 && !c_ui[i] )
  209.         ++i;
  210.     CHECK( mk_write_size( c, 8 - i ) );
  211.     CHECK( mk_append_context_data( c, c_ui+i, 8 - i ) );
  212.     return 0;
  213. }
  214. static int mk_write_sint( mk_context *c, unsigned id, int64_t si )
  215. {
  216.     unsigned char c_si[8] = { si >> 56, si >> 48, si >> 40, si >> 32, si >> 24, si >> 16, si >> 8, si };
  217.     unsigned i = 0;
  218.     CHECK( mk_write_id( c, id ) );
  219.     if( si < 0 )
  220.         while( i < 7 && c_si[i] == 0xff && c_si[i+1] & 0x80 )
  221.             ++i;
  222.     else
  223.         while( i < 7 && c_si[i] == 0 && !(c_si[i+1] & 0x80 ) )
  224.             ++i;
  225.     CHECK( mk_write_size( c, 8 - i ) );
  226.     CHECK( mk_append_context_data( c, c_si+i, 8 - i ) );
  227.     return 0;
  228. }
  229. static int mk_write_float_raw( mk_context *c, float f )
  230. {
  231.     union
  232.     {
  233.         float f;
  234.         unsigned u;
  235.     } u;
  236.     unsigned char c_f[4];
  237.     u.f = f;
  238.     c_f[0] = u.u >> 24;
  239.     c_f[1] = u.u >> 16;
  240.     c_f[2] = u.u >> 8;
  241.     c_f[3] = u.u;
  242.     return mk_append_context_data( c, c_f, 4 );
  243. }
  244. static int mk_write_float( mk_context *c, unsigned id, float f )
  245. {
  246.     CHECK( mk_write_id( c, id ) );
  247.     CHECK( mk_write_size( c, 4 ) );
  248.     CHECK( mk_write_float_raw( c, f ) );
  249.     return 0;
  250. }
  251. static unsigned mk_ebml_size_size( unsigned s )
  252. {
  253.     if( s < 0x7f )
  254.         return 1;
  255.     if( s < 0x3fff )
  256.         return 2;
  257.     if( s < 0x1fffff )
  258.         return 3;
  259.     if( s < 0x0fffffff )
  260.         return 4;
  261.     return 5;
  262. }
  263. static unsigned mk_ebml_sint_size( int64_t si )
  264. {
  265.     unsigned char c_si[8] = { si >> 56, si >> 48, si >> 40, si >> 32, si >> 24, si >> 16, si >> 8, si };
  266.     unsigned i = 0;
  267.     if( si < 0 )
  268.         while( i < 7 && c_si[i] == 0xff && c_si[i+1] & 0x80 )
  269.             ++i;
  270.     else
  271.         while( i < 7 && c_si[i] == 0 && !(c_si[i+1] & 0x80) )
  272.             ++i;
  273.     return 8 - i;
  274. }
  275. mk_writer *mk_create_writer( const char *filename )
  276. {
  277.     mk_writer *w = malloc( sizeof(*w) );
  278.     if( !w )
  279.         return NULL;
  280.     memset( w, 0, sizeof(*w) );
  281.     w->root = mk_create_context( w, NULL, 0 );
  282.     if( !w->root )
  283.     {
  284.         free( w );
  285.         return NULL;
  286.     }
  287.     w->fp = fopen( filename, "wb" );
  288.     if( !w->fp )
  289.     {
  290.         mk_destroy_contexts( w );
  291.         free( w );
  292.         return NULL;
  293.     }
  294.     w->timescale = 1000000;
  295.     return w;
  296. }
  297. int mk_writeHeader( mk_writer *w, const char *writing_app,
  298.                     const char *codec_id,
  299.                     const void *codec_private, unsigned codec_private_size,
  300.                     int64_t default_frame_duration,
  301.                     int64_t timescale,
  302.                     unsigned width, unsigned height,
  303.                     unsigned d_width, unsigned d_height )
  304. {
  305.     mk_context  *c, *ti, *v;
  306.     if( w->wrote_header )
  307.         return -1;
  308.     w->timescale = timescale;
  309.     w->def_duration = default_frame_duration;
  310.     if( !(c = mk_create_context(w, w->root, 0x1a45dfa3)) ) // EBML
  311.         return -1;
  312.     CHECK( mk_write_uint( c, 0x4286, 1 ) ); // EBMLVersion
  313.     CHECK( mk_write_uint( c, 0x42f7, 1 ) ); // EBMLReadVersion
  314.     CHECK( mk_write_uint( c, 0x42f2, 4 ) ); // EBMLMaxIDLength
  315.     CHECK( mk_write_uint( c, 0x42f3, 8 ) ); // EBMLMaxSizeLength
  316.     CHECK( mk_write_string( c, 0x4282, "matroska") ); // DocType
  317.     CHECK( mk_write_uint( c, 0x4287, 1 ) ); // DocTypeVersion
  318.     CHECK( mk_write_uint( c, 0x4285, 1 ) ); // DocTypeReadversion
  319.     CHECK( mk_close_context( c, 0 ) );
  320.     if( !(c = mk_create_context( w, w->root, 0x18538067 )) ) // Segment
  321.         return -1;
  322.     CHECK( mk_flush_context_id( c ) );
  323.     CHECK( mk_close_context( c, 0 ) );
  324.     if( !(c = mk_create_context(w, w->root, 0x1549a966)) ) // SegmentInfo
  325.         return -1;
  326.     CHECK( mk_write_string( c, 0x4d80, "Haali Matroska Writer b0" ) );
  327.     CHECK( mk_write_string( c, 0x5741, writing_app ) );
  328.     CHECK( mk_write_uint( c, 0x2ad7b1, w->timescale ) );
  329.     CHECK( mk_write_float( c, 0x4489, 0) );
  330.     w->duration_ptr = c->d_cur - 4;
  331.     CHECK( mk_close_context( c, &w->duration_ptr ) );
  332.     if( !(c = mk_create_context( w, w->root, 0x1654ae6b )) ) // tracks
  333.         return -1;
  334.     if( !(ti = mk_create_context( w, c, 0xae )) ) // TrackEntry
  335.         return -1;
  336.     CHECK( mk_write_uint( ti, 0xd7, 1 ) ); // TrackNumber
  337.     CHECK( mk_write_uint( ti, 0x73c5, 1 ) ); // TrackUID
  338.     CHECK( mk_write_uint( ti, 0x83, 1 ) ); // TrackType
  339.     CHECK( mk_write_uint( ti, 0x9c, 0 ) ); // FlagLacing
  340.     CHECK( mk_write_string( ti, 0x86, codec_id ) ); // codec_id
  341.     if( codec_private_size )
  342.         CHECK( mk_write_bin( ti, 0x63a2, codec_private, codec_private_size ) ); // codec_private
  343.     if( default_frame_duration )
  344.         CHECK( mk_write_uint( ti, 0x23e383, default_frame_duration ) ); // DefaultDuration
  345.     if( !(v = mk_create_context( w, ti, 0xe0 ) ) ) // Video
  346.         return -1;
  347.     CHECK( mk_write_uint( v, 0xb0, width ) );
  348.     CHECK( mk_write_uint( v, 0xba, height ) );
  349.     CHECK( mk_write_uint( v, 0x54b0, d_width ) );
  350.     CHECK( mk_write_uint( v, 0x54ba, d_height ) );
  351.     CHECK( mk_close_context( v, 0 ) );
  352.     CHECK( mk_close_context( ti, 0 ) );
  353.     CHECK( mk_close_context( c, 0 ) );
  354.     CHECK( mk_flush_context_data( w->root ) );
  355.     w->wrote_header = 1;
  356.     return 0;
  357. }
  358. static int mk_close_cluster( mk_writer *w )
  359. {
  360.     if( w->cluster == NULL )
  361.         return 0;
  362.     CHECK( mk_close_context( w->cluster, 0 ) );
  363.     w->cluster = NULL;
  364.     CHECK( mk_flush_context_data( w->root ) );
  365.     return 0;
  366. }
  367. static int mk_flush_frame( mk_writer *w )
  368. {
  369.     int64_t delta, ref = 0;
  370.     unsigned fsize, bgsize;
  371.     unsigned char c_delta_flags[3];
  372.     if( !w->in_frame )
  373.         return 0;
  374.     delta = w->frame_tc/w->timescale - w->cluster_tc_scaled;
  375.     if( delta > 32767ll || delta < -32768ll )
  376.         CHECK( mk_close_cluster( w ) );
  377.     if( !w->cluster )
  378.     {
  379.         w->cluster_tc_scaled = w->frame_tc / w->timescale;
  380.         w->cluster = mk_create_context( w, w->root, 0x1f43b675 ); // Cluster
  381.         if( !w->cluster )
  382.             return -1;
  383.         CHECK( mk_write_uint( w->cluster, 0xe7, w->cluster_tc_scaled ) ); // Timecode
  384.         delta = 0;
  385.     }
  386.     fsize = w->frame ? w->frame->d_cur : 0;
  387.     bgsize = fsize + 4 + mk_ebml_size_size( fsize + 4 ) + 1;
  388.     if( !w->keyframe )
  389.     {
  390.         ref = w->prev_frame_tc_scaled - w->cluster_tc_scaled - delta;
  391.         bgsize += 1 + 1 + mk_ebml_sint_size( ref );
  392.     }
  393.     CHECK( mk_write_id( w->cluster, 0xa0 ) ); // BlockGroup
  394.     CHECK( mk_write_size( w->cluster, bgsize ) );
  395.     CHECK( mk_write_id( w->cluster, 0xa1 ) ); // Block
  396.     CHECK( mk_write_size( w->cluster, fsize + 4 ) );
  397.     CHECK( mk_write_size( w->cluster, 1 ) ); // track number
  398.     c_delta_flags[0] = delta >> 8;
  399.     c_delta_flags[1] = delta;
  400.     c_delta_flags[2] = 0;
  401.     CHECK( mk_append_context_data( w->cluster, c_delta_flags, 3 ) );
  402.     if( w->frame )
  403.     {
  404.         CHECK( mk_append_context_data(w->cluster, w->frame->data, w->frame->d_cur));
  405.         w->frame->d_cur = 0;
  406.     }
  407.     if( !w->keyframe )
  408.         CHECK( mk_write_sint(w->cluster, 0xfb, ref ) ); // ReferenceBlock
  409.     w->in_frame = 0;
  410.     w->prev_frame_tc_scaled = w->cluster_tc_scaled + delta;
  411.     if( w->cluster->d_cur > CLSIZE )
  412.         CHECK( mk_close_cluster( w ) );
  413.     return 0;
  414. }
  415. int mk_start_frame( mk_writer *w )
  416. {
  417.     if( mk_flush_frame( w ) < 0 )
  418.         return -1;
  419.     w->in_frame = 1;
  420.     w->keyframe = 0;
  421.     return 0;
  422. }
  423. int mk_set_frame_flags( mk_writer *w,int64_t timestamp, int keyframe )
  424. {
  425.     if( !w->in_frame )
  426.         return -1;
  427.     w->frame_tc = timestamp;
  428.     w->keyframe = keyframe != 0;
  429.     if( w->max_frame_tc < timestamp )
  430.         w->max_frame_tc = timestamp;
  431.     return 0;
  432. }
  433. int mk_add_frame_data( mk_writer *w, const void *data, unsigned size )
  434. {
  435.     if( !w->in_frame )
  436.         return -1;
  437.     if( !w->frame )
  438.         if( !(w->frame = mk_create_context( w, NULL, 0 )) )
  439.         return -1;
  440.   return mk_append_context_data( w->frame, data, size );
  441. }
  442. int mk_close( mk_writer *w )
  443. {
  444.     int ret = 0;
  445.     if( mk_flush_frame( w ) < 0 || mk_close_cluster( w ) < 0 )
  446.         ret = -1;
  447.     if( w->wrote_header )
  448.     {
  449.         fseek( w->fp, w->duration_ptr, SEEK_SET );
  450.         if( mk_write_float_raw( w->root, (float)((double)(w->max_frame_tc+w->def_duration) / w->timescale) ) < 0 ||
  451.             mk_flush_context_data(w->root) < 0 )
  452.             ret = -1;
  453.     }
  454.     mk_destroy_contexts( w );
  455.     fclose( w->fp );
  456.     free( w );
  457.     return ret;
  458. }