static int
demux_mkv_read_cluster(FILE *s, mkv_demuxer_t *mkv_d)
{
	uint64_t length, l;
	int il;

	length = ebml_read_length (s, NULL);
	while (length > 0)
	{
		switch (ebml_read_id (s, &il))
		{
			case MATROSKA_ID_BLOCKGROUP:
				demux_mkv_read_block(s, mkv_d);
				return 1;
				break;
			case EBML_ID_INVALID:
				return 0;
			default:
				ebml_read_skip (s, &l);
				break;
		}
		length -= l + il;
	}

	return 1;
}
static int
demux_mkv_read_tracks (FILE *s, mkv_demuxer_t *mkv_d)
{
  uint64_t length, l;
  int il;

  mkv_d->tracks = (mkv_track_t**)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 = (mkv_track_t**)realloc (mkv_d->tracks,
                                   (mkv_d->num_tracks+1)
                                   *sizeof (*mkv_d->tracks));
          l = demux_mkv_read_trackentry (s, mkv_d);
          if (l == 0)
            return 1;
          break;

        default:
            ebml_read_skip (s, &l);
            break;
        }
      length -= l + il;
    }
  return 0;
}
static int
demux_mkv_read_trackaudio (FILE *s, mkv_track_t *track)
{
  uint64_t len, length, l;
  int il;

  track->a_sfreq = 8000.0;
  track->a_channels = 1;

  len = length = ebml_read_length (s, &il);
  len += il;
  while (length > 0)
    {
      switch (ebml_read_id (s, &il))
        {
        case MATROSKA_ID_AUDIOSAMPLINGFREQ:
          {
            long double num = ebml_read_float (s, &l);
            if (num == EBML_FLOAT_INVALID)
              return 0;
            track->a_sfreq = num;
            mp_msg (MSGT_DEMUX, MSGL_V, "[mkv] |   + Sampling frequency: %f\n",
                    track->a_sfreq);
            break;
          }

        case MATROSKA_ID_AUDIOBITDEPTH:
          {
            uint64_t num = ebml_read_uint (s, &l);
            if (num == EBML_UINT_INVALID)
              return 0;
            track->a_bps = num;
            mp_msg (MSGT_DEMUX, MSGL_V, "[mkv] |   + Bit depth: %u\n",
                    track->a_bps);
            break;
          }

        case MATROSKA_ID_AUDIOCHANNELS:
          {
            uint64_t num = ebml_read_uint (s, &l);
            if (num == EBML_UINT_INVALID)
              return 0;
            track->a_channels = num;
            mp_msg (MSGT_DEMUX, MSGL_V, "[mkv] |   + Channels: %u\n",
                    track->a_channels);
            break;
          }

        default:
            ebml_read_skip (s, &l);
            break;
        }
      length -= l + il;
    }
  return len;
}
static int
demux_mkv_read_info (FILE *s, mkv_demuxer_t *mkv_d)
{
  uint64_t length, l;
  int il;
  uint64_t tc_scale = 1000000;
  long double duration = 0.;

  length = ebml_read_length (s, NULL);
  while (length > 0)
    {
      switch (ebml_read_id (s, &il))
        {
        case MATROSKA_ID_TIMECODESCALE:
          {
            uint64_t num = ebml_read_uint (s, &l);
            if (num == EBML_UINT_INVALID)
              return 1;
            tc_scale = num;
            mp_msg (MSGT_DEMUX, MSGL_V, "[mkv] | + timecode scale: %"PRIu64"\n",
                    tc_scale);
            break;
          }

        case MATROSKA_ID_DURATION:
          {
            long double num = ebml_read_float (s, &l);
            if (num == EBML_FLOAT_INVALID)
              return 1;
            duration = num;
            mp_msg (MSGT_DEMUX, MSGL_V, "[mkv] | + duration: %.3Lfs\n",
                    duration * tc_scale / 1000000000.0);
            break;
          }

        default:
          ebml_read_skip (s, &l);
          break;
        }
      length -= l + il;
    }
  mkv_d->tc_scale = tc_scale;
  mkv_d->duration = duration * tc_scale / 1000000000.0;
  return 0;
}
Beispiel #5
0
/*
 * Read an EBML header.
 */
char *ebml_read_header(stream_t *s, int *version)
{
    uint64_t length, l, num;
    uint32_t id;
    char *str = NULL;

    if (ebml_read_master(s, &length) != EBML_ID_HEADER)
        return 0;

    if (version)
        *version = 1;

    while (length > 0) {
        id = ebml_read_id(s, NULL);
        if (id == EBML_ID_INVALID)
            return NULL;
        length -= 2;

        switch (id) {
            /* is our read version uptodate? */
        case EBML_ID_EBMLREADVERSION:
            num = ebml_read_uint(s, &l);
            if (num != EBML_VERSION)
                return NULL;
            break;

            /* we only handle 8 byte lengths at max */
        case EBML_ID_EBMLMAXSIZELENGTH:
            num = ebml_read_uint(s, &l);
            if (num != sizeof(uint64_t))
                return NULL;
            break;

            /* we handle 4 byte IDs at max */
        case EBML_ID_EBMLMAXIDLENGTH:
            num = ebml_read_uint(s, &l);
            if (num != sizeof(uint32_t))
                return NULL;
            break;

        case EBML_ID_DOCTYPE:
            str = ebml_read_ascii(s, &l);
            if (str == NULL)
                return NULL;
            break;

        case EBML_ID_DOCTYPEREADVERSION:
            num = ebml_read_uint(s, &l);
            if (num == EBML_UINT_INVALID)
                return NULL;
            if (version)
                *version = num;
            break;

            /* we ignore these two, they don't tell us anything we care about */
        case EBML_ID_VOID:
        case EBML_ID_EBMLVERSION:
        case EBML_ID_DOCTYPEVERSION:
        default:
            if (ebml_read_skip(s, &l))
                return NULL;
            break;
        }
        length -= l;
    }

    return str;
}
static int
demux_mkv_read_trackentry (FILE *s, mkv_demuxer_t *mkv_d)
{
  mkv_track_t *track;
  uint64_t len, length, l;
  int il;

  track = (mkv_track_t *)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)
              goto err_out;
            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 (s, 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 (s, 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)
              goto err_out;
            l = x + num;
            track->private_data = malloc (num + AV_LZO_INPUT_PADDING);
            if (read_data(s, track->private_data, num) != (size_t) num)
              goto err_out;
            track->private_size = num;
            mp_msg (MSGT_DEMUX, MSGL_V, "[mkv] |  + CodecPrivate, length "
                    "%u\n", track->private_size);
			if( track->type == MATROSKA_TRACK_VIDEO &&
					!strcmp(track->codec_id,MKV_V_MPEG4_AVC)
			  )
			{
				unsigned char*  ptr, *hdr;
				int write_len=0;
				int avc1_header_size = 0;

				ptr = (unsigned char *)track->private_data + 7; //skip 01 64 00 29 FF E1 00 and seek to first header len pos.

				unsigned char *avc1_header = (unsigned char *)malloc (track->private_size + AV_LZO_INPUT_PADDING);
				hdr = avc1_header;

				write_len = *ptr++; //get first header len

				hdr[0] = hdr[1] = hdr[2] = 0;
				hdr[3] = (unsigned char)write_len;
				hdr += 4;

				memcpy(hdr, ptr, write_len);
				hdr += write_len;
				ptr += write_len;

				avc1_header_size += 4 + write_len;

				mp_msg(MSGT_DEMUX, MSGL_V, "1write_len[%d]\n",write_len);//SkyMedi_Vincent

				ptr += 2;   //skip 01 00 and seek to second header len pos.
				write_len = *ptr++; //get second header len

				hdr[0] = hdr[1] = hdr[2] = 0;
				hdr[3] = (unsigned char)write_len;
				hdr += 4;

				memcpy(hdr, ptr, write_len);

				avc1_header_size += 4 + write_len;

				mp_msg(MSGT_DEMUX, MSGL_V, "2write_len[%d]\n",write_len);//SkyMedi_Vincent
				mp_msg(MSGT_DEMUX, MSGL_V, "avc1_header_size = %d\n", avc1_header_size);
				{
					int i = 0;
					for( i = 0 ; i< avc1_header_size; i++)
						mp_msg(MSGT_DEMUX, MSGL_V, "%02X ", avc1_header[i]);
					mp_msg(MSGT_DEMUX, MSGL_V, "\n");
				}

				if (!check_avc1_sps_bank0(avc1_header+5, avc1_header_size-5))
					goto err_out;

				free(avc1_header);
			}
            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 (s, 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 int
demux_mkv_read_trackencodings (FILE *s, mkv_track_t *track)
{
  mkv_content_encoding_t *ce, e;
  uint64_t len, length, l;
  int il, n;

  ce = (mkv_content_encoding_t *)malloc (sizeof (*ce));
  n = 0;

  len = length = ebml_read_length (s, &il);
  if (len == EBML_UINT_INVALID)
	  goto err_out;
  len += il;
  while (length > 0)
    {
      switch (ebml_read_id (s, &il))
        {
        case MATROSKA_ID_CONTENTENCODING:
          {
            uint64_t len;
            int i;

            memset (&e, 0, sizeof (e));
            e.scope = 1;

            len = ebml_read_length (s, &i);
	    if (len == EBML_UINT_INVALID)
		    goto err_out;
            l = len + i;

            while (len > 0)
              {
                uint64_t num, ll;
                int iil;

                switch (ebml_read_id (s, &iil))
                  {
                  case MATROSKA_ID_CONTENTENCODINGORDER:
                    num = ebml_read_uint (s, &ll);
                    if (num == EBML_UINT_INVALID)
                      goto err_out;
                    e.order = num;
                    break;

                  case MATROSKA_ID_CONTENTENCODINGSCOPE:
                    num = ebml_read_uint (s, &ll);
                    if (num == EBML_UINT_INVALID)
                      goto err_out;
                    e.scope = num;
                    break;

                  case MATROSKA_ID_CONTENTENCODINGTYPE:
                    num = ebml_read_uint (s, &ll);
                    if (num == EBML_UINT_INVALID)
                      goto err_out;
                    e.type = num;
                    break;

                  case MATROSKA_ID_CONTENTCOMPRESSION:
                    {
                      uint64_t le;

                      le = ebml_read_length (s, &i);
		      if (le == EBML_UINT_INVALID)
			      goto err_out;
                      ll = le + i;

                      while (le > 0)
                        {
                          uint64_t lll;
                          int iiil;

                          switch (ebml_read_id (s, &iiil))
                            {
                            case MATROSKA_ID_CONTENTCOMPALGO:
                              num = ebml_read_uint (s, &lll);
                              if (num == EBML_UINT_INVALID)
                                goto err_out;
                              e.comp_algo = num;
                              break;

                            case MATROSKA_ID_CONTENTCOMPSETTINGS:
                              lll = ebml_read_length (s, &i);
			      if (lll == EBML_UINT_INVALID)
                                goto err_out;
                              e.comp_settings = (uint8_t*)malloc (lll);
                              read_data(s, e.comp_settings, lll);
                              e.comp_settings_len = lll;
                              lll += i;
                              break;

                            default:
                              ebml_read_skip (s, &lll);
                              break;
                            }
                          le -= lll + iiil;
                        }

                      if (e.type == 1)
                        {
                          mp_msg(MSGT_DEMUX, MSGL_WARN,
                                 MSGTR_MPDEMUX_MKV_TrackEncrypted, track->tnum);
                        }
                      else if (e.type != 0)
                        {
                          mp_msg(MSGT_DEMUX, MSGL_WARN,
                                 MSGTR_MPDEMUX_MKV_UnknownContentEncoding, track->tnum);
                        }

                      if (e.comp_algo != 0 && e.comp_algo != 2)
                        {
                          mp_msg (MSGT_DEMUX, MSGL_WARN,
                                  MSGTR_MPDEMUX_MKV_UnknownCompression,
                                  track->tnum, e.comp_algo);
                        }
#if !CONFIG_ZLIB
                      else if (e.comp_algo == 0)
                        {
                          mp_msg (MSGT_DEMUX, MSGL_WARN,
                                  MSGTR_MPDEMUX_MKV_ZlibCompressionUnsupported,
                                  track->tnum);
                        }
#endif

                      break;
                    }

                  default:
                    ebml_read_skip (s, &ll);
                    break;
                  }
                len -= ll + iil;
              }
            for (i=0; i<n; i++)
              if (e.order <= ce[i].order)
                break;
            ce = (mkv_content_encoding_t*)realloc (ce, (n+1) *sizeof (*ce));
            memmove (ce+i+1, ce+i, (n-i) * sizeof (*ce));
            memcpy (ce+i, &e, sizeof (e));
            n++;
            break;
          }

        default:
          ebml_read_skip (s, &l);
          break;
        }

      length -= l + il;
    }

  track->encodings = ce;
  track->num_encodings = n;
  return len;

err_out:
  demux_mkv_free_encodings(ce, n);
  return 0;
}
static int
demux_mkv_read_block(FILE *s, mkv_demuxer_t *mkv_d)
{
	uint64_t length, l;
	int il, tmp;
	uint64_t block_duration = 0,  block_length = 0;
	int64_t block_bref = 0, block_fref = 0;
	uint8_t *block = NULL;

	length = ebml_read_length (s, NULL);
	while (length > 0)
	{
		switch (ebml_read_id (s, &il))
		{
			case MATROSKA_ID_BLOCKDURATION:
				//puts("MATROSKA_ID_BLOCKDURATION");
				block_duration = ebml_read_uint (s, &l);
				if (block_duration == EBML_UINT_INVALID) {
					if(block)
						free(block);
					return 0;
				}
				block_duration *= mkv_d->tc_scale / 1000000.0;
				break;
			case MATROSKA_ID_BLOCK:
				//puts("MATROSKA_ID_BLOCK");
				block_length = ebml_read_length (s, &tmp);
				if(block)
					free(block);
				if (block_length > SIZE_MAX - AV_LZO_INPUT_PADDING) return 0;
				block = (uint8_t *)malloc (block_length + AV_LZO_INPUT_PADDING);
				if (!block)
				{
					return 0;
				}
				if (fread(block, 1, (size_t)block_length, s) != (size_t) block_length)
				{
					if(block)
						free(block);
					return 0;
				}
				l = tmp + block_length;
				break;
			case MATROSKA_ID_REFERENCEBLOCK:
				//puts("MATROSKA_ID_REFERENCEBLOCK");
				{
					int64_t num = ebml_read_int (s, &l);
					if (num == EBML_INT_INVALID) {
						if(block)
							free(block);
						return 0;
					}
					if (num <= 0)
						block_bref = num;
					else
						block_fref = num;
					break;
				}
			case EBML_ID_INVALID:
				//puts("EBML_ID_INVALID");
				if(block)
					free(block);
				return 0;
			default:
				ebml_read_skip (s, &l);
				break;
		}
		length -= l + il;

		if (block)
		{
			handle_block (mkv_d, block, block_length,
					block_duration, block_bref, block_fref, 0);
			free (block);
			block = NULL;
		}
	}
	return 0;
}
static int
demux_mkv_read_trackvideo (FILE *s, mkv_track_t *track)
{
  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;
}
int MKV_Parser(FILE *fp, FileInfo *finfo)
{
	int nRet = 0, cont = 0, ii, jj;
	int is_hw_notsupport = 0;
	nRet = mkv_check_file(fp, finfo);
	mkv_track_t *track;

	if (nRet == 0)
		return nRet;

	mp_msg (MSGT_DEMUX, MSGL_V, "[mkv] Found the head...\n");

	if (ebml_read_id (fp, NULL) != MATROSKA_ID_SEGMENT)
	{
		mp_msg (MSGT_DEMUX, MSGL_V, "[mkv] but no segment :(\n");
		return 0;
	}
	ebml_read_length (fp, NULL);  /* return bytes number until EOF */

	mp_msg (MSGT_DEMUX, MSGL_V, "[mkv] + a segment...\n");

	mkv_demuxer_t *mkv_d = (mkv_demuxer_t *)calloc (1, sizeof (mkv_demuxer_t));
	finfo->priv = mkv_d;
	mkv_d->tc_scale = 1000000;
	mkv_d->segment_start = read_tell (fp);
	mkv_d->parsed_cues = (off_t *)malloc (sizeof (off_t));
	mkv_d->parsed_seekhead = (off_t *)malloc (sizeof (off_t));

	while (!cont)
	{
		switch (ebml_read_id (fp, NULL))
		{
			case MATROSKA_ID_INFO:
				mp_msg (MSGT_DEMUX, MSGL_V, "[mkv] |+ segment information...\n");
				cont = demux_mkv_read_info (fp, mkv_d);
				break;

			case MATROSKA_ID_TRACKS:
				mp_msg (MSGT_DEMUX, MSGL_V, "[mkv] |+ segment tracks...\n");
				cont = demux_mkv_read_tracks (fp, mkv_d);
				break;

			case MATROSKA_ID_CUES:
			case MATROSKA_ID_TAGS:
			case MATROSKA_ID_SEEKHEAD:
			case MATROSKA_ID_CHAPTERS:
			case MATROSKA_ID_ATTACHMENTS:
				ebml_read_skip (fp, NULL);
				break;
			case MATROSKA_ID_CLUSTER:
				mp_msg (MSGT_DEMUX, MSGL_V, "[mkv] |+ found cluster, headers are "
						"parsed completely :)\n");
				demux_mkv_read_cluster(fp, mkv_d);
				cont = 1;
				break;

			default:
				cont = 1;
			case EBML_ID_VOID:
				ebml_read_skip (fp, NULL);
				break;
		}
	}

	/* select video track */
	track = NULL;
	/* search for a video track that has the 'default' flag set */
	/*
	for (ii=0; ii<mkv_d->num_tracks; ii++)
		if (mkv_d->tracks[ii]->type == MATROSKA_TRACK_VIDEO
				&& mkv_d->tracks[ii]->default_track)
		{
			if (mkv_d->tracks[ii]->hw_notsupport == 1)
			{
				is_hw_notsupport = 1;
				break;
			} else {
				track = mkv_d->tracks[ii];
				break;
			}
		}
		*/

	if (track == NULL)
	{
		int comp_algo_support = 1;
		/* no track has the 'default' flag set */
		/* let's take the first video track */
		for (ii=0; ii<mkv_d->num_tracks; ii++)
		{
			if (mkv_d->tracks[ii]->type == MATROSKA_TRACK_VIDEO)
			{
				if(mkv_d->tracks[ii]->hw_notsupport == 1)
				{
					is_hw_notsupport = 1;
				} else {
					track = mkv_d->tracks[ii];

					for (jj=0; jj < track->num_encodings; jj++)
					{
						mp_msg(MSGT_DEMUX, MSGL_V, "num_encodings: %d, comp algo: %d\n",
								track->num_encodings,
								track->encodings->comp_algo);
                      if (track->encodings->comp_algo != 0 && track->encodings->comp_algo != 2 &&track->encodings->comp_algo != 3)
					  {
						  printf("MKV: Video track %d has been compressed\n", track->tnum);
						  comp_algo_support = 0;
					  }
					}
					if (comp_algo_support == 0)
						continue;
					else
					{
						comp_algo_support = 1;
						break;
					}
				}
			}
		}
		if (comp_algo_support == 0)
		{
			goto mkv_parse_err;
		}
	}
	if (track != NULL)
	{
		if (demux_mkv_open_video(finfo, track) == 0)
		{
			finfo->bVideo = 1;
			finfo->FileDuration = mkv_d->duration;
			nRet = 1;
		}
	}

	if ((track == NULL) && (is_hw_notsupport == 1))
	{
		// the only video is not support.
	}
	else 
	{

		/* select audio track */
		track = NULL;
		/* search for an audio track that has the 'default' flag set */
		/*
		for (ii=0; ii < mkv_d->num_tracks; ii++)
		{
			if (mkv_d->tracks[ii]->type == MATROSKA_TRACK_AUDIO
					&& mkv_d->tracks[ii]->default_track)
			{
				track = mkv_d->tracks[ii];
				break;
			}
		}
		*/

		if (track == NULL)
		{
			/* no track has the 'default' flag set */
			/* let's take the first audio track */
			for (ii=0; ii < mkv_d->num_tracks; ii++)
			{
				if (mkv_d->tracks[ii]->type == MATROSKA_TRACK_AUDIO)
				{
					track = mkv_d->tracks[ii];
					int comp_algo_support = 1;

					for (jj=0; jj < track->num_encodings; jj++)
					{
						mp_msg(MSGT_DEMUX, MSGL_V, "num_encodings: %d, comp algo: %d\n",
								track->num_encodings,
								track->encodings->comp_algo);
                      if (track->encodings->comp_algo != 0 && track->encodings->comp_algo != 2 &&track->encodings->comp_algo != 3)
					  {
						  printf("MKV: Audio track %d has been compressed\n", track->tnum);
						  comp_algo_support = 0;
					  }
					}
					if (demux_mkv_open_audio(finfo, track) == 0)
					{
						finfo->bAudio = 1;
						finfo->AudioDuration = mkv_d->duration;
						finfo->AudioType = track->a_formattag;
						if (comp_algo_support == 1)
						{
							nRet = 1;
							if (check_audio_type(track->a_formattag, track->a_channels, finfo->hw_a_flag) == 1)
							{
								break;
							}
						} else {
							nRet = 0;
						}
					} else {
						nRet = 0;
					}
				}
			}
		}
	}

mkv_parse_err:
	if (mkv_d != NULL)
	{
		demux_close_mkv(mkv_d);
		finfo->priv = NULL;
	}

	return nRet;
}