matroska.c
上传用户:hjq518
上传日期:2021-12-09
资源大小:5084k
文件大小:13k
源码类别:

Audio

开发平台:

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