demux_mkv.c

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

C
2,147
字号
static intdemux_mkv_read_trackvideo (demuxer_t *demuxer, mkv_track_t *track){  stream_t *s = demuxer->stream;  uint64_t len, length, l;  int il;  len = length = ebml_read_length (s, &il);  len += il;  while (length > 0)    {      switch (ebml_read_id (s, &il))        {        case MATROSKA_ID_VIDEOFRAMERATE:          {            long double num = ebml_read_float (s, &l);            if (num == EBML_FLOAT_INVALID)              return 0;            track->v_frate = num;            mp_msg (MSGT_DEMUX, MSGL_V, "[mkv] |   + Frame rate: %f\n",                    track->v_frate);            if (track->v_frate > 0)              track->default_duration = 1 / track->v_frate;            break;          }        case MATROSKA_ID_VIDEODISPLAYWIDTH:          {            uint64_t num = ebml_read_uint (s, &l);            if (num == EBML_UINT_INVALID)              return 0;            track->v_dwidth = num;            mp_msg (MSGT_DEMUX, MSGL_V, "[mkv] |   + Display width: %u\n",                    track->v_dwidth);            break;          }        case MATROSKA_ID_VIDEODISPLAYHEIGHT:          {            uint64_t num = ebml_read_uint (s, &l);            if (num == EBML_UINT_INVALID)              return 0;            track->v_dheight = num;            mp_msg (MSGT_DEMUX, MSGL_V, "[mkv] |   + Display height: %u\n",                    track->v_dheight);            break;          }        case MATROSKA_ID_VIDEOPIXELWIDTH:          {            uint64_t num = ebml_read_uint (s, &l);            if (num == EBML_UINT_INVALID)              return 0;            track->v_width = num;            mp_msg (MSGT_DEMUX, MSGL_V, "[mkv] |   + Pixel width: %u\n",                    track->v_width);            break;          }        case MATROSKA_ID_VIDEOPIXELHEIGHT:          {            uint64_t num = ebml_read_uint (s, &l);            if (num == EBML_UINT_INVALID)              return 0;            track->v_height = num;            mp_msg (MSGT_DEMUX, MSGL_V, "[mkv] |   + Pixel height: %u\n",                    track->v_height);            break;          }        default:            ebml_read_skip (s, &l);            break;        }      length -= l + il;    }  return len;}/** * \brief free any data associated with given track * \param track track of which to free data */static voiddemux_mkv_free_trackentry(mkv_track_t *track) {  if (track->name)    free (track->name);  if (track->codec_id)    free (track->codec_id);  if (track->language)    free (track->language);  if (track->private_data)    free (track->private_data);  if (track->audio_buf)    free (track->audio_buf);  if (track->audio_timestamp)    free (track->audio_timestamp);#ifdef USE_ASS  if (track->sh_sub && track->sh_sub->ass_track)    ass_free_track (track->sh_sub->ass_track);#endif  demux_mkv_free_encodings(track->encodings, track->num_encodings);  free(track);}static intdemux_mkv_read_trackentry (demuxer_t *demuxer){  mkv_demuxer_t *mkv_d = (mkv_demuxer_t *) demuxer->priv;  stream_t *s = demuxer->stream;  mkv_track_t *track;  uint64_t len, length, l;  int il;  track = calloc (1, sizeof (*track));  /* set default values */  track->default_track = 1;  track->name = 0;  track->language = strdup("eng");  len = length = ebml_read_length (s, &il);  len += il;  while (length > 0)    {      switch (ebml_read_id (s, &il))        {        case MATROSKA_ID_TRACKNUMBER:          {            uint64_t num = ebml_read_uint (s, &l);            if (num == EBML_UINT_INVALID)              goto err_out;            track->tnum = num;            mp_msg (MSGT_DEMUX, MSGL_V, "[mkv] |  + Track number: %u\n",                    track->tnum);            break;          }        case MATROSKA_ID_TRACKNAME:          {            track->name = ebml_read_utf8 (s, &l);            if (track->name == NULL)              goto err_out;            mp_msg (MSGT_DEMUX, MSGL_V, "[mkv] |  + Name: %s\n",                    track->name);            break;          }                  case MATROSKA_ID_TRACKTYPE:          {            uint64_t num = ebml_read_uint (s, &l);            if (num == EBML_UINT_INVALID)              return 0;            track->type = num;            mp_msg (MSGT_DEMUX, MSGL_V, "[mkv] |  + Track type: ");            switch (track->type)              {              case MATROSKA_TRACK_AUDIO:                mp_msg (MSGT_DEMUX, MSGL_V, "Audio\n");                break;              case MATROSKA_TRACK_VIDEO:                mp_msg (MSGT_DEMUX, MSGL_V, "Video\n");                break;              case MATROSKA_TRACK_SUBTITLE:                mp_msg (MSGT_DEMUX, MSGL_V, "Subtitle\n");                break;              default:                mp_msg (MSGT_DEMUX, MSGL_V, "unknown\n");                break;            }            break;          }        case MATROSKA_ID_TRACKAUDIO:          mp_msg (MSGT_DEMUX, MSGL_V, "[mkv] |  + Audio track\n");          l = demux_mkv_read_trackaudio (demuxer, track);          if (l == 0)            goto err_out;          break;        case MATROSKA_ID_TRACKVIDEO:          mp_msg (MSGT_DEMUX, MSGL_V, "[mkv] |  + Video track\n");          l = demux_mkv_read_trackvideo (demuxer, track);          if (l == 0)            goto err_out;          break;        case MATROSKA_ID_CODECID:          track->codec_id = ebml_read_ascii (s, &l);          if (track->codec_id == NULL)            goto err_out;          if (!strcmp (track->codec_id, MKV_V_MSCOMP) ||              !strcmp (track->codec_id, MKV_A_ACM))            track->ms_compat = 1;          else if (!strcmp (track->codec_id, MKV_S_VOBSUB))            track->subtitle_type = MATROSKA_SUBTYPE_VOBSUB;          else if (!strcmp (track->codec_id, MKV_S_TEXTSSA)                   || !strcmp (track->codec_id, MKV_S_TEXTASS)                   || !strcmp (track->codec_id, MKV_S_SSA)                   || !strcmp (track->codec_id, MKV_S_ASS))            {              track->subtitle_type = MATROSKA_SUBTYPE_SSA;            }          else if (!strcmp (track->codec_id, MKV_S_TEXTASCII))            track->subtitle_type = MATROSKA_SUBTYPE_TEXT;          if (!strcmp (track->codec_id, MKV_S_TEXTUTF8))            {              track->subtitle_type = MATROSKA_SUBTYPE_TEXT;            }          mp_msg (MSGT_DEMUX, MSGL_V, "[mkv] |  + Codec ID: %s\n",                  track->codec_id);          break;        case MATROSKA_ID_CODECPRIVATE:          {            int x;            uint64_t num = ebml_read_length (s, &x);	    // audit: cheap guard against overflows later..	    if (num > SIZE_MAX - 1000) return 0;            l = x + num;            track->private_data = malloc (num + LZO_INPUT_PADDING);            if (stream_read(s, track->private_data, num) != (int) num)              goto err_out;            track->private_size = num;            mp_msg (MSGT_DEMUX, MSGL_V, "[mkv] |  + CodecPrivate, length "                    "%u\n", track->private_size);            break;          }        case MATROSKA_ID_TRACKLANGUAGE:          free(track->language);          track->language = ebml_read_utf8 (s, &l);          if (track->language == NULL)            goto err_out;          mp_msg (MSGT_DEMUX, MSGL_V, "[mkv] |  + Language: %s\n",                  track->language);          break;        case MATROSKA_ID_TRACKFLAGDEFAULT:          {            uint64_t num = ebml_read_uint (s, &l);            if (num == EBML_UINT_INVALID)              goto err_out;            track->default_track = num;            mp_msg (MSGT_DEMUX, MSGL_V, "[mkv] |  + Default flag: %u\n",                    track->default_track);            break;          }        case MATROSKA_ID_TRACKDEFAULTDURATION:          {            uint64_t num = ebml_read_uint (s, &l);            if (num == EBML_UINT_INVALID)              goto err_out;            if (num == 0)              mp_msg (MSGT_DEMUX, MSGL_V, "[mkv] |  + Default duration: 0");            else              {                track->v_frate = 1000000000.0 / num;                track->default_duration = num / 1000000000.0;                mp_msg (MSGT_DEMUX, MSGL_V, "[mkv] |  + Default duration: "                        "%.3fms ( = %.3f fps)\n",num/1000000.0,track->v_frate);              }            break;          }        case MATROSKA_ID_TRACKENCODINGS:          l = demux_mkv_read_trackencodings (demuxer, track);          if (l == 0)            goto err_out;          break;        default:          ebml_read_skip (s, &l);          break;        }      length -= l + il;    }  mkv_d->tracks[mkv_d->num_tracks++] = track;  return len;err_out:  demux_mkv_free_trackentry(track);  return 0;}static intdemux_mkv_read_tracks (demuxer_t *demuxer){  mkv_demuxer_t *mkv_d = (mkv_demuxer_t *) demuxer->priv;  stream_t *s = demuxer->stream;  uint64_t length, l;  int il;  mkv_d->tracks = malloc (sizeof (*mkv_d->tracks));  mkv_d->num_tracks = 0;  length = ebml_read_length (s, NULL);  while (length > 0)    {      switch (ebml_read_id (s, &il))        {        case MATROSKA_ID_TRACKENTRY:          mp_msg (MSGT_DEMUX, MSGL_V, "[mkv] | + a track...\n");          mkv_d->tracks = realloc (mkv_d->tracks,                                   (mkv_d->num_tracks+1)                                   *sizeof (*mkv_d->tracks));          l = demux_mkv_read_trackentry (demuxer);          if (l == 0)            return 1;          break;        default:            ebml_read_skip (s, &l);            break;        }      length -= l + il;    }  return 0;}static intdemux_mkv_read_cues (demuxer_t *demuxer){  mkv_demuxer_t *mkv_d = (mkv_demuxer_t *) demuxer->priv;  stream_t *s = demuxer->stream;  uint64_t length, l, time, track, pos;  off_t off;  int i, il;  if (index_mode == 0) {    ebml_read_skip (s, NULL);    return 0;  }  off = stream_tell (s);  for (i=0; i<mkv_d->parsed_cues_num; i++)    if (mkv_d->parsed_cues[i] == off)      {        ebml_read_skip (s, NULL);        return 0;      }  mkv_d->parsed_cues = realloc (mkv_d->parsed_cues,                                 (mkv_d->parsed_cues_num+1)                                * sizeof (off_t));  mkv_d->parsed_cues[mkv_d->parsed_cues_num++] = off;  mp_msg (MSGT_DEMUX, MSGL_V, "[mkv] /---- [ parsing cues ] -----------\n");  length = ebml_read_length (s, NULL);  while (length > 0)    {      time = track = pos = EBML_UINT_INVALID;      switch (ebml_read_id (s, &il))        {        case MATROSKA_ID_POINTENTRY:          {            uint64_t len;            len = ebml_read_length (s, &i);            l = len + i;            while (len > 0)              {                uint64_t l;                int il;                switch (ebml_read_id (s, &il))                  {                  case MATROSKA_ID_CUETIME:                    time = ebml_read_uint (s, &l);                    break;                  case MATROSKA_ID_CUETRACKPOSITION:                    {                      uint64_t le;                      le = ebml_read_length (s, &i);                      l = le + i;                      while (le > 0)                        {                          uint64_t l;                          int il;                          switch (ebml_read_id (s, &il))                            {                            case MATROSKA_ID_CUETRACK:                              track = ebml_read_uint (s, &l);                              break;                            case MATROSKA_ID_CUECLUSTERPOSITION:                              pos = ebml_read_uint (s, &l);                              break;                            default:                              ebml_read_skip (s, &l);                              break;                            }                          le -= l + il;                        }                      break;                    }                  default:                    ebml_read_skip (s, &l);                    break;                  }                len -= l + il;              }            break;          }        default:          ebml_read_skip (s, &l);          break;        }      length -= l + il;      if (time != EBML_UINT_INVALID && track != EBML_UINT_INVALID          && pos != EBML_UINT_INVALID)        {          grow_array(&mkv_d->indexes, mkv_d->num_indexes, sizeof(mkv_index_t));          mkv_d->indexes[mkv_d->num_indexes].tnum = track;          mkv_d->indexes[mkv_d->num_indexes].timecode = time;          mkv_d->indexes[mkv_d->num_indexes].filepos =mkv_d->segment_start+pos;          mp_msg (MSGT_DEMUX, MSGL_DBG2, "[mkv] |+ found cue point "                  "for track %"PRIu64": timecode %"PRIu64", filepos: %"PRIu64"\n",                   track, time, mkv_d->segment_start + pos);

⌨️ 快捷键说明

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