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

Audio

开发平台:

Visual C++

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