demux_mkv.c

来自「君正早期ucos系统(只有早期的才不没有打包成库),MPLAYER,文件系统,图」· C语言 代码 · 共 2,147 行 · 第 1/5 页

C
2,147
字号
/* * native Matroska demuxer * Written by Aurelien Jacobs <aurel@gnuage.org> * Based on the one written by Ronald Bultje for gstreamer *   and on demux_mkv.cpp from Moritz Bunkus. * Licence: GPL */#include "config.h"#include <mplaylib.h>#include <mplaylib.h>#ifndef USE_16M_SDRAM#include <ctype.h>#endif#include <inttypes.h>#include "stream/stream.h"#include "demuxer.h"#include "stheader.h"#include "ebml.h"#include "matroska.h"#include "mp_msg.h"#include "help_mp.h"#include "subreader.h"#include "libvo/sub.h"#include "libass/ass.h"#include "libass/ass_mp.h"#include "libavutil/common.h"#ifdef USE_QTX_CODECS#include "loader/qtx/qtxsdk/components.h"#endif#ifdef HAVE_ZLIB#include <zlib.h>#endif#ifdef USE_LIBAVUTIL_SO#include <ffmpeg/lzo.h>#include <ffmpeg/intreadwrite.h>#else#include "libavutil/lzo.h"#include "libavutil/intreadwrite.h"#endif#include "libavutil/avstring.h"#undef memcpy#define memcpy uc_memcpystatic unsigned char sipr_swaps[38][2]={    {0,63},{1,22},{2,44},{3,90},{5,81},{7,31},{8,86},{9,58},{10,36},{12,68},    {13,39},{14,73},{15,53},{16,69},{17,57},{19,88},{20,34},{21,71},{24,46},    {25,94},{26,54},{28,75},{29,50},{32,70},{33,92},{35,74},{38,85},{40,56},    {42,87},{43,65},{45,59},{48,79},{49,93},{51,89},{55,95},{61,76},{67,83},    {77,80} };// Map flavour to bytes per second#define SIPR_FLAVORS 4#define ATRC_FLAVORS 8#define COOK_FLAVORS 34static int sipr_fl2bps[SIPR_FLAVORS] = {813, 1062, 625, 2000};static int atrc_fl2bps[ATRC_FLAVORS] = {8269, 11714, 13092, 16538, 18260, 22050, 33075, 44100};static int cook_fl2bps[COOK_FLAVORS] = {1000, 1378, 2024, 2584, 4005, 5513, 8010, 4005, 750, 2498,                                        4048, 5513, 8010, 11973, 8010, 2584, 4005, 2067, 2584, 2584,                                        4005, 4005, 5513, 5513, 8010, 12059, 1550, 8010, 12059, 5513,                                        12016, 16408, 22911, 33506};typedef struct{  uint32_t order, type, scope;  uint32_t comp_algo;  uint8_t *comp_settings;  int comp_settings_len;} mkv_content_encoding_t;typedef struct mkv_track{  int tnum;  char *name;    char *codec_id;  int ms_compat;  char *language;  int type;    uint32_t v_width, v_height, v_dwidth, v_dheight;  float v_frate;  uint32_t a_formattag;  uint32_t a_channels, a_bps;  float a_sfreq;  float default_duration;  int default_track;  void *private_data;  unsigned int private_size;  /* stuff for realmedia */  int realmedia;  int rv_kf_base, rv_kf_pts;  float rv_pts;  /* previous video timestamp */  float ra_pts;  /* previous audio timestamp */  /** realaudio descrambling */  int sub_packet_size; ///< sub packet size, per stream  int sub_packet_h; ///< number of coded frames per block  int coded_framesize; ///< coded frame size, per stream  int audiopk_size; ///< audio packet size  unsigned char *audio_buf; ///< place to store reordered audio data  float *audio_timestamp; ///< timestamp for each audio packet  int sub_packet_cnt; ///< number of subpacket already received  int audio_filepos; ///< file position of first audio packet in block  /* stuff for quicktime */  int fix_i_bps;  float qt_last_a_pts;  int subtitle_type;  /* The timecodes of video frames might have to be reordered if they're     in display order (the timecodes, not the frames themselves!). In this     case demux packets have to be cached with the help of these variables. */  int reorder_timecodes;  demux_packet_t **cached_dps;  int num_cached_dps, num_allocated_dps;  float max_pts;  /* generic content encoding support */  mkv_content_encoding_t *encodings;  int num_encodings;  /* For VobSubs and SSA/ASS */  sh_sub_t *sh_sub;} mkv_track_t;typedef struct mkv_index{  int tnum;  uint64_t timecode, filepos;} mkv_index_t;typedef struct mkv_attachment{  char* name;  char* mime;  uint64_t uid;  void* data;  unsigned int data_size;} mkv_attachment_t;typedef struct mkv_demuxer{  off_t segment_start;  float duration, last_pts;  uint64_t last_filepos;  mkv_track_t **tracks;  int num_tracks;  uint64_t tc_scale, cluster_tc, first_tc;  int has_first_tc;  uint64_t cluster_size;  uint64_t blockgroup_size;  mkv_index_t *indexes;  int num_indexes;  off_t *parsed_cues;  int parsed_cues_num;  off_t *parsed_seekhead;  int parsed_seekhead_num;  uint64_t *cluster_positions;  int num_cluster_pos;  int64_t skip_to_timecode;  int v_skip_to_keyframe, a_skip_to_keyframe;  int64_t stop_timecode;    int last_aid;  int audio_tracks[MAX_A_STREAMS];    mkv_attachment_t *attachments;  int num_attachments;} mkv_demuxer_t;#define REALHEADER_SIZE    16#define RVPROPERTIES_SIZE  34#define RAPROPERTIES4_SIZE 56#define RAPROPERTIES5_SIZE 70/* for e.g. "-slang ger" */extern char *dvdsub_lang;extern char *audio_lang;extern int dvdsub_id;/** * \brief ensures there is space for at least one additional element * \param array array to grow * \param nelem current number of elements in array * \param elsize size of one array element */static void grow_array(void **array, int nelem, size_t elsize) {  if (!(nelem & 31))    *array = realloc(*array, (nelem + 32) * elsize);}static mkv_track_t *demux_mkv_find_track_by_num (mkv_demuxer_t *d, int n, int type){  int i, id;  for (i=0, id=0; i < d->num_tracks; i++)    if (d->tracks[i] != NULL && d->tracks[i]->type == type)      if (id++ == n)        return d->tracks[i];    return NULL;}static mkv_track_t *demux_mkv_find_track_by_language (mkv_demuxer_t *d, char *language, int type){  int i, len;    language += strspn(language,",");  while((len = strcspn(language,",")) > 0)    {      for (i=0; i < d->num_tracks; i++)        if (d->tracks[i] != NULL && d->tracks[i]->language != NULL &&            d->tracks[i]->type == type &&            !strncmp(d->tracks[i]->language, language, len))          return d->tracks[i];      language += len;      language += strspn(language,",");    }    return NULL;}static voidadd_cluster_position (mkv_demuxer_t *mkv_d, uint64_t position){  int i = mkv_d->num_cluster_pos;  while (i--)    if (mkv_d->cluster_positions[i] == position)      return;  grow_array(&mkv_d->cluster_positions, mkv_d->num_cluster_pos,             sizeof(uint64_t));  mkv_d->cluster_positions[mkv_d->num_cluster_pos++] = position;}#define AAC_SYNC_EXTENSION_TYPE 0x02b7static intaac_get_sample_rate_index (uint32_t sample_rate){  if (92017 <= sample_rate)    return 0;  else if (75132 <= sample_rate)    return 1;  else if (55426 <= sample_rate)    return 2;  else if (46009 <= sample_rate)    return 3;  else if (37566 <= sample_rate)    return 4;  else if (27713 <= sample_rate)    return 5;  else if (23004 <= sample_rate)    return 6;  else if (18783 <= sample_rate)    return 7;  else if (13856 <= sample_rate)    return 8;  else if (11502 <= sample_rate)    return 9;  else if (9391 <= sample_rate)    return 10;  else    return 11;}static intvobsub_parse_size (sh_sub_t *sh, const char *start){  if (sscanf(&start[6], "%dx%d", &sh->width, &sh->height) == 2)    {      mp_msg(MSGT_DEMUX, MSGL_V, "[mkv] VobSub size: %ux%u\n",             sh->width, sh->height);      return 1;    }  return 0;}static intvobsub_parse_palette (sh_sub_t *sh, const char *start){  int i, r, g, b, y, u, v, tmp;  start += 8;  while (isspace(*start))    start++;  for (i = 0; i < 16; i++)    {      if (sscanf(start, "%06x", &tmp) != 1)        break;      r = tmp >> 16 & 0xff;      g = tmp >> 8 & 0xff;      b = tmp & 0xff;      y = av_clip_uint8( 0.1494  * r + 0.6061 * g + 0.2445 * b);      u = av_clip_uint8( 0.6066  * r - 0.4322 * g - 0.1744 * b + 128);      v = av_clip_uint8(-0.08435 * r - 0.3422 * g + 0.4266 * b + 128);      sh->palette[i] = y << 16 | u << 8 | v;      start += 6;      while ((*start == ',') || isspace(*start))        start++;    }  if (i == 16)    {      mp_msg(MSGT_DEMUX, MSGL_V, "[mkv] VobSub palette: %06x,%06x,"             "%06x,%06x,%06x,%06x,%06x,%06x,%06x,%06x,%06x,%06x,%06x,"             "%06x,%06x,%06x\n", sh->palette[0],             sh->palette[1], sh->palette[2],             sh->palette[3], sh->palette[4],             sh->palette[5], sh->palette[6],             sh->palette[7], sh->palette[8],             sh->palette[9], sh->palette[10],             sh->palette[11], sh->palette[12],             sh->palette[13], sh->palette[14],             sh->palette[15]);      sh->has_palette = 1;      return 2;    }  return 0;}static intvobsub_parse_custom_colors (sh_sub_t *sh, const char *start){  int use_custom_colors, i;  use_custom_colors = 0;  start += 14;  while (isspace(*start))    start++;   if (!strncasecmp(start, "ON", 2) || (*start == '1'))     use_custom_colors = 1;   else if (!strncasecmp(start, "OFF", 3) || (*start == '0'))     use_custom_colors = 0;   mp_msg(MSGT_DEMUX, MSGL_V, "[mkv] VobSub custom colors: %s\n",          use_custom_colors ? "ON" : "OFF");   if ((start = strstr(start, "colors:")) != NULL)     {       start += 7;       while (isspace(*start))         start++;       for (i = 0; i < 4; i++)         {           if (sscanf(start, "%06x", &sh->colors[i]) != 1)             break;           start += 6;           while ((*start == ',') || isspace(*start))             start++;         }       if (i == 4)         {           sh->custom_colors = 4;           mp_msg(MSGT_DEMUX, MSGL_V, "[mkv] VobSub colors: %06x,"                  "%06x,%06x,%06x\n", sh->colors[0],                  sh->colors[1], sh->colors[2],                  sh->colors[3]);         }     }   if (!use_custom_colors)     sh->custom_colors = 0;   return 4;}static intvobsub_parse_forced_subs (sh_sub_t *sh, const char *start){  start += 12;  while (isspace(*start))    start++;  if (!strncasecmp(start, "on", 2) || (*start == '1'))    sh->forced_subs_only = 1;  else if (!strncasecmp(start, "off", 3) || (*start == '0'))    sh->forced_subs_only = 0;  else    return 0;  mp_msg(MSGT_DEMUX, MSGL_V, "[mkv] VobSub forced subs: %d\n",         sh->forced_subs_only);  return 8;}/** \brief Free cached demux packets * * Reordering the timecodes requires caching of demux packets. This function * frees all these cached packets and the memory for the cached pointers * itself. * * \param demuxer The demuxer for which the cache is to be freed. */static voidfree_cached_dps (demuxer_t *demuxer){  mkv_demuxer_t *mkv_d = (mkv_demuxer_t *) demuxer->priv;  mkv_track_t *track;  int i, k;  for (k = 0; k < mkv_d->num_tracks; k++)    {      track = mkv_d->tracks[k];      for (i = 0; i < track->num_cached_dps; i++)        free_demux_packet (track->cached_dps[i]);      free(track->cached_dps);      track->cached_dps = NULL;

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?